diff --git a/[refs] b/[refs] index 4aa03f16f4d9..25bf03765c65 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 3498d13b8090c0b0ef911409fbc503a7c4cca6ef +refs/heads/master: 1139b4516f3927ae835ed3b0a9c69a0dfaf4cdd4 diff --git a/trunk/Documentation/ABI/testing/sysfs-bus-pci b/trunk/Documentation/ABI/testing/sysfs-bus-pci index dff1f48d252d..34f51100f029 100644 --- a/trunk/Documentation/ABI/testing/sysfs-bus-pci +++ b/trunk/Documentation/ABI/testing/sysfs-bus-pci @@ -210,15 +210,3 @@ Users: firmware assigned instance number of the PCI device that can help in understanding the firmware intended order of the PCI device. - -What: /sys/bus/pci/devices/.../d3cold_allowed -Date: July 2012 -Contact: Huang Ying -Description: - d3cold_allowed is bit to control whether the corresponding PCI - device can be put into D3Cold state. If it is cleared, the - device will never be put into D3Cold state. If it is set, the - device may be put into D3Cold state if other requirements are - satisfied too. Reading this attribute will show the current - value of d3cold_allowed bit. Writing this attribute will set - the value of d3cold_allowed bit. diff --git a/trunk/Documentation/ABI/testing/sysfs-class-extcon b/trunk/Documentation/ABI/testing/sysfs-class-extcon index 57a726232912..20ab361bd8c6 100644 --- a/trunk/Documentation/ABI/testing/sysfs-class-extcon +++ b/trunk/Documentation/ABI/testing/sysfs-class-extcon @@ -13,7 +13,7 @@ Description: accessory cables have such capability. For example, the 30-pin port of Nuri board (/arch/arm/mach-exynos) may have both HDMI and Charger attached, or analog audio, - video, and USB cables attached simultaneously. + video, and USB cables attached simulteneously. If there are cables mutually exclusive with each other, such binary relations may be expressed with extcon_dev's @@ -35,7 +35,7 @@ Description: The /sys/class/extcon/.../state shows and stores the cable attach/detach information of the corresponding extcon object. If the extcon object has an optional callback "show_state" - defined, the showing function is overridden with the optional + defined, the showing function is overriden with the optional callback. If the default callback for showing function is used, the @@ -46,19 +46,19 @@ Description: TA=1 EAR_JACK=0 # - In this example, the extcon device has USB_OTG and TA + In this example, the extcon device have USB_OTG and TA cables attached and HDMI and EAR_JACK cables detached. In order to update the state of an extcon device, enter a hex - state number starting with 0x: - # echo 0xHEX > state + state number starting with 0x. + echo 0xHEX > state - This updates the whole state of the extcon device. + This updates the whole state of the extcon dev. Inputs of all the methods are required to meet the - mutually_exclusive conditions if they exist. + mutually_exclusive contidions if they exist. It is recommended to use this "global" state interface if - you need to set the value atomically. The later state + you need to enter the value atomically. The later state interface associated with each cable cannot update multiple cable states of an extcon device simultaneously. @@ -73,7 +73,7 @@ What: /sys/class/extcon/.../cable.x/state Date: February 2012 Contact: MyungJoo Ham Description: - The /sys/class/extcon/.../cable.x/state shows and stores the + The /sys/class/extcon/.../cable.x/name shows and stores the state of cable "x" (integer between 0 and 31) of an extcon device. The state value is either 0 (detached) or 1 (attached). @@ -83,8 +83,8 @@ Date: December 2011 Contact: MyungJoo Ham Description: Shows the relations of mutually exclusiveness. For example, - if the mutually_exclusive array of extcon device is - {0x3, 0x5, 0xC, 0x0}, then the output is: + if the mutually_exclusive array of extcon_dev is + {0x3, 0x5, 0xC, 0x0}, the, the output is: # ls mutually_exclusive/ 0x3 0x5 diff --git a/trunk/Documentation/ABI/testing/sysfs-class-regulator b/trunk/Documentation/ABI/testing/sysfs-class-regulator index bc578bc60628..e091fa873792 100644 --- a/trunk/Documentation/ABI/testing/sysfs-class-regulator +++ b/trunk/Documentation/ABI/testing/sysfs-class-regulator @@ -349,24 +349,3 @@ Description: This will be one of the same strings reported by the "state" attribute. - -What: /sys/class/regulator/.../bypass -Date: September 2012 -KernelVersion: 3.7 -Contact: Mark Brown -Description: - Some regulator directories will contain a field called - bypass. This indicates if the device is in bypass mode. - - This will be one of the following strings: - - 'enabled' - 'disabled' - 'unknown' - - 'enabled' means the regulator is in bypass mode. - - 'disabled' means that the regulator is regulating. - - 'unknown' means software cannot determine the state, or - the reported state is invalid. diff --git a/trunk/Documentation/ABI/testing/sysfs-driver-wacom b/trunk/Documentation/ABI/testing/sysfs-driver-wacom index 7fc781048b79..8d55a83d6921 100644 --- a/trunk/Documentation/ABI/testing/sysfs-driver-wacom +++ b/trunk/Documentation/ABI/testing/sysfs-driver-wacom @@ -1,16 +1,3 @@ -WWhat: /sys/class/hidraw/hidraw*/device/oled*_img -Date: June 2012 -Contact: linux-bluetooth@vger.kernel.org -Description: - The /sys/class/hidraw/hidraw*/device/oled*_img files control - OLED mocro displays on Intuos4 Wireless tablet. Accepted image - has to contain 256 bytes (64x32 px 1 bit colour). The format - is the same as PBM image 62x32px without header (64 bits per - horizontal line, 32 lines). An example of setting OLED No. 0: - dd bs=256 count=1 if=img_file of=[path to oled0_img]/oled0_img - The attribute is read only and no local copy of the image is - stored. - What: /sys/class/hidraw/hidraw*/device/speed Date: April 2010 Kernel Version: 2.6.35 diff --git a/trunk/Documentation/ABI/testing/sysfs-platform-ideapad-laptop b/trunk/Documentation/ABI/testing/sysfs-platform-ideapad-laptop index b31e782bd985..814b01354c41 100644 --- a/trunk/Documentation/ABI/testing/sysfs-platform-ideapad-laptop +++ b/trunk/Documentation/ABI/testing/sysfs-platform-ideapad-laptop @@ -5,15 +5,4 @@ Contact: "Ike Panhc " Description: Control the power of camera module. 1 means on, 0 means off. -What: /sys/devices/platform/ideapad/fan_mode -Date: June 2012 -KernelVersion: 3.6 -Contact: "Maxim Mikityanskiy " -Description: - Change fan mode - There are four available modes: - * 0 -> Super Silent Mode - * 1 -> Standard Mode - * 2 -> Dust Cleaning - * 4 -> Efficient Thermal Dissipation Mode diff --git a/trunk/Documentation/ABI/testing/sysfs-tty b/trunk/Documentation/ABI/testing/sysfs-tty index 0c430150d929..b138b663bf54 100644 --- a/trunk/Documentation/ABI/testing/sysfs-tty +++ b/trunk/Documentation/ABI/testing/sysfs-tty @@ -17,12 +17,3 @@ Description: device, like 'tty1'. The file supports poll() to detect virtual console switches. - -What: /sys/class/tty/ttyS0/uartclk -Date: Sep 2012 -Contact: Tomas Hlavacek -Description: - Shows the current uartclk value associated with the - UART port in serial_core, that is bound to TTY like ttyS0. - uartclk = 16 * baud_base - diff --git a/trunk/Documentation/DocBook/filesystems.tmpl b/trunk/Documentation/DocBook/filesystems.tmpl index 25b58efd955d..3fca32c41927 100644 --- a/trunk/Documentation/DocBook/filesystems.tmpl +++ b/trunk/Documentation/DocBook/filesystems.tmpl @@ -224,8 +224,8 @@ all your transactions. -Then at umount time , in your put_super() you can then call journal_destroy() -to clean up your in-core journal object. +Then at umount time , in your put_super() (2.4) or write_super() (2.5) +you can then call journal_destroy() to clean up your in-core journal object. diff --git a/trunk/Documentation/DocBook/media/v4l/vidioc-g-tuner.xml b/trunk/Documentation/DocBook/media/v4l/vidioc-g-tuner.xml index 701138f1209d..720395127904 100644 --- a/trunk/Documentation/DocBook/media/v4l/vidioc-g-tuner.xml +++ b/trunk/Documentation/DocBook/media/v4l/vidioc-g-tuner.xml @@ -125,7 +125,7 @@ the structure refers to a radio tuner the V4L2_TUNER_CAP_NORM flags can't be used. If multiple frequency bands are supported, then capability is the union of all -capability fields of each &v4l2-frequency-band;. +capability> fields of each &v4l2-frequency-band;. diff --git a/trunk/Documentation/RCU/checklist.txt b/trunk/Documentation/RCU/checklist.txt index cdb20d41a44a..fc103d7a0474 100644 --- a/trunk/Documentation/RCU/checklist.txt +++ b/trunk/Documentation/RCU/checklist.txt @@ -310,12 +310,6 @@ over a rather long period of time, but improvements are always welcome! code under the influence of preempt_disable(), you instead need to use synchronize_irq() or synchronize_sched(). - This same limitation also applies to synchronize_rcu_bh() - and synchronize_srcu(), as well as to the asynchronous and - expedited forms of the three primitives, namely call_rcu(), - call_rcu_bh(), call_srcu(), synchronize_rcu_expedited(), - synchronize_rcu_bh_expedited(), and synchronize_srcu_expedited(). - 12. Any lock acquired by an RCU callback must be acquired elsewhere with softirq disabled, e.g., via spin_lock_irqsave(), spin_lock_bh(), etc. Failing to disable irq on a given diff --git a/trunk/Documentation/RCU/stallwarn.txt b/trunk/Documentation/RCU/stallwarn.txt index 1927151b386b..523364e4e1f1 100644 --- a/trunk/Documentation/RCU/stallwarn.txt +++ b/trunk/Documentation/RCU/stallwarn.txt @@ -99,7 +99,7 @@ In kernels with CONFIG_RCU_FAST_NO_HZ, even more information is printed: INFO: rcu_preempt detected stall on CPU - 0: (64628 ticks this GP) idle=dd5/3fffffffffffffff/0 drain=0 . timer not pending + 0: (64628 ticks this GP) idle=dd5/3fffffffffffffff/0 drain=0 . timer=-1 (t=65000 jiffies) The "(64628 ticks this GP)" indicates that this CPU has taken more @@ -116,13 +116,13 @@ number between the two "/"s is the value of the nesting, which will be a small positive number if in the idle loop and a very large positive number (as shown above) otherwise. -For CONFIG_RCU_FAST_NO_HZ kernels, the "drain=0" indicates that the CPU is -not in the process of trying to force itself into dyntick-idle state, the -"." indicates that the CPU has not given up forcing RCU into dyntick-idle -mode (it would be "H" otherwise), and the "timer not pending" indicates -that the CPU has not recently forced RCU into dyntick-idle mode (it -would otherwise indicate the number of microseconds remaining in this -forced state). +For CONFIG_RCU_FAST_NO_HZ kernels, the "drain=0" indicates that the +CPU is not in the process of trying to force itself into dyntick-idle +state, the "." indicates that the CPU has not given up forcing RCU +into dyntick-idle mode (it would be "H" otherwise), and the "timer=-1" +indicates that the CPU has not recented forced RCU into dyntick-idle +mode (it would otherwise indicate the number of microseconds remaining +in this forced state). Multiple Warnings From One Stall diff --git a/trunk/Documentation/RCU/trace.txt b/trunk/Documentation/RCU/trace.txt index 672d19083252..f6f15ce39903 100644 --- a/trunk/Documentation/RCU/trace.txt +++ b/trunk/Documentation/RCU/trace.txt @@ -333,23 +333,23 @@ o Each element of the form "1/1 0:127 ^0" represents one struct The output of "cat rcu/rcu_pending" looks as follows: rcu_sched: - 0 np=255892 qsp=53936 rpq=85 cbr=0 cng=14417 gpc=10033 gps=24320 nn=146741 - 1 np=261224 qsp=54638 rpq=33 cbr=0 cng=25723 gpc=16310 gps=2849 nn=155792 - 2 np=237496 qsp=49664 rpq=23 cbr=0 cng=2762 gpc=45478 gps=1762 nn=136629 - 3 np=236249 qsp=48766 rpq=98 cbr=0 cng=286 gpc=48049 gps=1218 nn=137723 - 4 np=221310 qsp=46850 rpq=7 cbr=0 cng=26 gpc=43161 gps=4634 nn=123110 - 5 np=237332 qsp=48449 rpq=9 cbr=0 cng=54 gpc=47920 gps=3252 nn=137456 - 6 np=219995 qsp=46718 rpq=12 cbr=0 cng=50 gpc=42098 gps=6093 nn=120834 - 7 np=249893 qsp=49390 rpq=42 cbr=0 cng=72 gpc=38400 gps=17102 nn=144888 + 0 np=255892 qsp=53936 rpq=85 cbr=0 cng=14417 gpc=10033 gps=24320 nf=6445 nn=146741 + 1 np=261224 qsp=54638 rpq=33 cbr=0 cng=25723 gpc=16310 gps=2849 nf=5912 nn=155792 + 2 np=237496 qsp=49664 rpq=23 cbr=0 cng=2762 gpc=45478 gps=1762 nf=1201 nn=136629 + 3 np=236249 qsp=48766 rpq=98 cbr=0 cng=286 gpc=48049 gps=1218 nf=207 nn=137723 + 4 np=221310 qsp=46850 rpq=7 cbr=0 cng=26 gpc=43161 gps=4634 nf=3529 nn=123110 + 5 np=237332 qsp=48449 rpq=9 cbr=0 cng=54 gpc=47920 gps=3252 nf=201 nn=137456 + 6 np=219995 qsp=46718 rpq=12 cbr=0 cng=50 gpc=42098 gps=6093 nf=4202 nn=120834 + 7 np=249893 qsp=49390 rpq=42 cbr=0 cng=72 gpc=38400 gps=17102 nf=41 nn=144888 rcu_bh: - 0 np=146741 qsp=1419 rpq=6 cbr=0 cng=6 gpc=0 gps=0 nn=145314 - 1 np=155792 qsp=12597 rpq=3 cbr=0 cng=0 gpc=4 gps=8 nn=143180 - 2 np=136629 qsp=18680 rpq=1 cbr=0 cng=0 gpc=7 gps=6 nn=117936 - 3 np=137723 qsp=2843 rpq=0 cbr=0 cng=0 gpc=10 gps=7 nn=134863 - 4 np=123110 qsp=12433 rpq=0 cbr=0 cng=0 gpc=4 gps=2 nn=110671 - 5 np=137456 qsp=4210 rpq=1 cbr=0 cng=0 gpc=6 gps=5 nn=133235 - 6 np=120834 qsp=9902 rpq=2 cbr=0 cng=0 gpc=6 gps=3 nn=110921 - 7 np=144888 qsp=26336 rpq=0 cbr=0 cng=0 gpc=8 gps=2 nn=118542 + 0 np=146741 qsp=1419 rpq=6 cbr=0 cng=6 gpc=0 gps=0 nf=2 nn=145314 + 1 np=155792 qsp=12597 rpq=3 cbr=0 cng=0 gpc=4 gps=8 nf=3 nn=143180 + 2 np=136629 qsp=18680 rpq=1 cbr=0 cng=0 gpc=7 gps=6 nf=0 nn=117936 + 3 np=137723 qsp=2843 rpq=0 cbr=0 cng=0 gpc=10 gps=7 nf=0 nn=134863 + 4 np=123110 qsp=12433 rpq=0 cbr=0 cng=0 gpc=4 gps=2 nf=0 nn=110671 + 5 np=137456 qsp=4210 rpq=1 cbr=0 cng=0 gpc=6 gps=5 nf=0 nn=133235 + 6 np=120834 qsp=9902 rpq=2 cbr=0 cng=0 gpc=6 gps=3 nf=2 nn=110921 + 7 np=144888 qsp=26336 rpq=0 cbr=0 cng=0 gpc=8 gps=2 nf=0 nn=118542 As always, this is once again split into "rcu_sched" and "rcu_bh" portions, with CONFIG_TREE_PREEMPT_RCU kernels having an additional @@ -377,6 +377,17 @@ o "gpc" is the number of times that an old grace period had o "gps" is the number of times that a new grace period had started, but this CPU was not yet aware of it. +o "nf" is the number of times that this CPU suspected that the + current grace period had run for too long, and thus needed to + be forced. + + Please note that "forcing" consists of sending resched IPIs + to holdout CPUs. If that CPU really still is in an old RCU + read-side critical section, then we really do have to wait for it. + The assumption behing "forcing" is that the CPU is not still in + an old RCU read-side critical section, but has not yet responded + for some other reason. + o "nn" is the number of times that this CPU needed nothing. Alert readers will note that the rcu "nn" number for a given CPU very closely matches the rcu_bh "np" number for that same CPU. This diff --git a/trunk/Documentation/RCU/whatisRCU.txt b/trunk/Documentation/RCU/whatisRCU.txt index bf0f6de2aa00..69ee188515e7 100644 --- a/trunk/Documentation/RCU/whatisRCU.txt +++ b/trunk/Documentation/RCU/whatisRCU.txt @@ -873,7 +873,7 @@ d. Do you need to treat NMI handlers, hardirq handlers, and code segments with preemption disabled (whether via preempt_disable(), local_irq_save(), local_bh_disable(), or some other mechanism) as if they were explicit RCU readers? - If so, RCU-sched is the only choice that will work for you. + If so, you need RCU-sched. e. Do you need RCU grace periods to complete even in the face of softirq monopolization of one or more of the CPUs? For @@ -884,12 +884,7 @@ f. Is your workload too update-intensive for normal use of RCU, but inappropriate for other synchronization mechanisms? If so, consider SLAB_DESTROY_BY_RCU. But please be careful! -g. Do you need read-side critical sections that are respected - even though they are in the middle of the idle loop, during - user-mode execution, or on an offlined CPU? If so, SRCU is the - only choice that will work for you. - -h. Otherwise, use RCU. +g. Otherwise, use RCU. Of course, this all assumes that you have determined that RCU is in fact the right tool for your job. diff --git a/trunk/Documentation/accounting/getdelays.c b/trunk/Documentation/accounting/getdelays.c index 6f706aca2049..f6318f6d7baf 100644 --- a/trunk/Documentation/accounting/getdelays.c +++ b/trunk/Documentation/accounting/getdelays.c @@ -98,9 +98,10 @@ static int create_nl_socket(int protocol) if (rcvbufsz) if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &rcvbufsz, sizeof(rcvbufsz)) < 0) { - fprintf(stderr, "Unable to set socket rcv buf size to %d\n", + fprintf(stderr, "Unable to set socket rcv buf size " + "to %d\n", rcvbufsz); - goto error; + return -1; } memset(&local, 0, sizeof(local)); diff --git a/trunk/Documentation/arm64/booting.txt b/trunk/Documentation/arm64/booting.txt deleted file mode 100644 index 9c4d388daddc..000000000000 --- a/trunk/Documentation/arm64/booting.txt +++ /dev/null @@ -1,152 +0,0 @@ - Booting AArch64 Linux - ===================== - -Author: Will Deacon -Date : 07 September 2012 - -This document is based on the ARM booting document by Russell King and -is relevant to all public releases of the AArch64 Linux kernel. - -The AArch64 exception model is made up of a number of exception levels -(EL0 - EL3), with EL0 and EL1 having a secure and a non-secure -counterpart. EL2 is the hypervisor level and exists only in non-secure -mode. EL3 is the highest priority level and exists only in secure mode. - -For the purposes of this document, we will use the term `boot loader' -simply to define all software that executes on the CPU(s) before control -is passed to the Linux kernel. This may include secure monitor and -hypervisor code, or it may just be a handful of instructions for -preparing a minimal boot environment. - -Essentially, the boot loader should provide (as a minimum) the -following: - -1. Setup and initialise the RAM -2. Setup the device tree -3. Decompress the kernel image -4. Call the kernel image - - -1. Setup and initialise RAM ---------------------------- - -Requirement: MANDATORY - -The boot loader is expected to find and initialise all RAM that the -kernel will use for volatile data storage in the system. It performs -this in a machine dependent manner. (It may use internal algorithms -to automatically locate and size all RAM, or it may use knowledge of -the RAM in the machine, or any other method the boot loader designer -sees fit.) - - -2. Setup the device tree -------------------------- - -Requirement: MANDATORY - -The device tree blob (dtb) must be no bigger than 2 megabytes in size -and placed at a 2-megabyte boundary within the first 512 megabytes from -the start of the kernel image. This is to allow the kernel to map the -blob using a single section mapping in the initial page tables. - - -3. Decompress the kernel image ------------------------------- - -Requirement: OPTIONAL - -The AArch64 kernel does not currently provide a decompressor and -therefore requires decompression (gzip etc.) to be performed by the boot -loader if a compressed Image target (e.g. Image.gz) is used. For -bootloaders that do not implement this requirement, the uncompressed -Image target is available instead. - - -4. Call the kernel image ------------------------- - -Requirement: MANDATORY - -The decompressed kernel image contains a 32-byte header as follows: - - u32 magic = 0x14000008; /* branch to stext, little-endian */ - u32 res0 = 0; /* reserved */ - u64 text_offset; /* Image load offset */ - u64 res1 = 0; /* reserved */ - u64 res2 = 0; /* reserved */ - -The image must be placed at the specified offset (currently 0x80000) -from the start of the system RAM and called there. The start of the -system RAM must be aligned to 2MB. - -Before jumping into the kernel, the following conditions must be met: - -- Quiesce all DMA capable devices so that memory does not get - corrupted by bogus network packets or disk data. This will save - you many hours of debug. - -- Primary CPU general-purpose register settings - x0 = physical address of device tree blob (dtb) in system RAM. - x1 = 0 (reserved for future use) - x2 = 0 (reserved for future use) - x3 = 0 (reserved for future use) - -- CPU mode - All forms of interrupts must be masked in PSTATE.DAIF (Debug, SError, - IRQ and FIQ). - The CPU must be in either EL2 (RECOMMENDED in order to have access to - the virtualisation extensions) or non-secure EL1. - -- Caches, MMUs - The MMU must be off. - Instruction cache may be on or off. - Data cache must be off and invalidated. - External caches (if present) must be configured and disabled. - -- Architected timers - CNTFRQ must be programmed with the timer frequency. - If entering the kernel at EL1, CNTHCTL_EL2 must have EL1PCTEN (bit 0) - set where available. - -- Coherency - All CPUs to be booted by the kernel must be part of the same coherency - domain on entry to the kernel. This may require IMPLEMENTATION DEFINED - initialisation to enable the receiving of maintenance operations on - each CPU. - -- System registers - All writable architected system registers at the exception level where - the kernel image will be entered must be initialised by software at a - higher exception level to prevent execution in an UNKNOWN state. - -The boot loader is expected to enter the kernel on each CPU in the -following manner: - -- The primary CPU must jump directly to the first instruction of the - kernel image. The device tree blob passed by this CPU must contain - for each CPU node: - - 1. An 'enable-method' property. Currently, the only supported value - for this field is the string "spin-table". - - 2. A 'cpu-release-addr' property identifying a 64-bit, - zero-initialised memory location. - - It is expected that the bootloader will generate these device tree - properties and insert them into the blob prior to kernel entry. - -- Any secondary CPUs must spin outside of the kernel in a reserved area - of memory (communicated to the kernel by a /memreserve/ region in the - device tree) polling their cpu-release-addr location, which must be - contained in the reserved region. A wfe instruction may be inserted - to reduce the overhead of the busy-loop and a sev will be issued by - the primary CPU. When a read of the location pointed to by the - cpu-release-addr returns a non-zero value, the CPU must jump directly - to this value. - -- Secondary CPU general-purpose register settings - x0 = 0 (reserved for future use) - x1 = 0 (reserved for future use) - x2 = 0 (reserved for future use) - x3 = 0 (reserved for future use) diff --git a/trunk/Documentation/arm64/memory.txt b/trunk/Documentation/arm64/memory.txt deleted file mode 100644 index dbbdcbba75a3..000000000000 --- a/trunk/Documentation/arm64/memory.txt +++ /dev/null @@ -1,73 +0,0 @@ - Memory Layout on AArch64 Linux - ============================== - -Author: Catalin Marinas -Date : 20 February 2012 - -This document describes the virtual memory layout used by the AArch64 -Linux kernel. The architecture allows up to 4 levels of translation -tables with a 4KB page size and up to 3 levels with a 64KB page size. - -AArch64 Linux uses 3 levels of translation tables with the 4KB page -configuration, allowing 39-bit (512GB) virtual addresses for both user -and kernel. With 64KB pages, only 2 levels of translation tables are -used but the memory layout is the same. - -User addresses have bits 63:39 set to 0 while the kernel addresses have -the same bits set to 1. TTBRx selection is given by bit 63 of the -virtual address. The swapper_pg_dir contains only kernel (global) -mappings while the user pgd contains only user (non-global) mappings. -The swapper_pgd_dir address is written to TTBR1 and never written to -TTBR0. - - -AArch64 Linux memory layout: - -Start End Size Use ------------------------------------------------------------------------ -0000000000000000 0000007fffffffff 512GB user - -ffffff8000000000 ffffffbbfffcffff ~240GB vmalloc - -ffffffbbfffd0000 ffffffbcfffdffff 64KB [guard page] - -ffffffbbfffe0000 ffffffbcfffeffff 64KB PCI I/O space - -ffffffbbffff0000 ffffffbcffffffff 64KB [guard page] - -ffffffbc00000000 ffffffbdffffffff 8GB vmemmap - -ffffffbe00000000 ffffffbffbffffff ~8GB [guard, future vmmemap] - -ffffffbffc000000 ffffffbfffffffff 64MB modules - -ffffffc000000000 ffffffffffffffff 256GB memory - - -Translation table lookup with 4KB pages: - -+--------+--------+--------+--------+--------+--------+--------+--------+ -|63 56|55 48|47 40|39 32|31 24|23 16|15 8|7 0| -+--------+--------+--------+--------+--------+--------+--------+--------+ - | | | | | | - | | | | | v - | | | | | [11:0] in-page offset - | | | | +-> [20:12] L3 index - | | | +-----------> [29:21] L2 index - | | +---------------------> [38:30] L1 index - | +-------------------------------> [47:39] L0 index (not used) - +-------------------------------------------------> [63] TTBR0/1 - - -Translation table lookup with 64KB pages: - -+--------+--------+--------+--------+--------+--------+--------+--------+ -|63 56|55 48|47 40|39 32|31 24|23 16|15 8|7 0| -+--------+--------+--------+--------+--------+--------+--------+--------+ - | | | | | - | | | | v - | | | | [15:0] in-page offset - | | | +----------> [28:16] L3 index - | | +--------------------------> [41:29] L2 index (only 38:29 used) - | +-------------------------------> [47:42] L1 index (not used) - +-------------------------------------------------> [63] TTBR0/1 diff --git a/trunk/Documentation/block/00-INDEX b/trunk/Documentation/block/00-INDEX index d18ecd827c40..d111e3b23db0 100644 --- a/trunk/Documentation/block/00-INDEX +++ b/trunk/Documentation/block/00-INDEX @@ -3,21 +3,15 @@ biodoc.txt - Notes on the Generic Block Layer Rewrite in Linux 2.5 capability.txt - - Generic Block Device Capability (/sys/block//capability) -cfq-iosched.txt - - CFQ IO scheduler tunables -data-integrity.txt - - Block data integrity + - Generic Block Device Capability (/sys/block//capability) deadline-iosched.txt - Deadline IO scheduler tunables ioprio.txt - Block io priorities (in CFQ scheduler) -queue-sysfs.txt - - Queue's sysfs entries request.txt - The members of struct request (in include/linux/blkdev.h) stat.txt - - Block layer statistics in /sys/block//stat + - Block layer statistics in /sys/block//stat switching-sched.txt - Switching I/O schedulers at runtime writeback_cache_control.txt diff --git a/trunk/Documentation/block/cfq-iosched.txt b/trunk/Documentation/block/cfq-iosched.txt index d89b4fe724d7..6d670f570451 100644 --- a/trunk/Documentation/block/cfq-iosched.txt +++ b/trunk/Documentation/block/cfq-iosched.txt @@ -1,14 +1,3 @@ -CFQ (Complete Fairness Queueing) -=============================== - -The main aim of CFQ scheduler is to provide a fair allocation of the disk -I/O bandwidth for all the processes which requests an I/O operation. - -CFQ maintains the per process queue for the processes which request I/O -operation(syncronous requests). In case of asynchronous requests, all the -requests from all the processes are batched together according to their -process's I/O priority. - CFQ ioscheduler tunables ======================== @@ -36,72 +25,6 @@ there are multiple spindles behind single LUN (Host based hardware RAID controller or for storage arrays), setting slice_idle=0 might end up in better throughput and acceptable latencies. -back_seek_max -------------- -This specifies, given in Kbytes, the maximum "distance" for backward seeking. -The distance is the amount of space from the current head location to the -sectors that are backward in terms of distance. - -This parameter allows the scheduler to anticipate requests in the "backward" -direction and consider them as being the "next" if they are within this -distance from the current head location. - -back_seek_penalty ------------------ -This parameter is used to compute the cost of backward seeking. If the -backward distance of request is just 1/back_seek_penalty from a "front" -request, then the seeking cost of two requests is considered equivalent. - -So scheduler will not bias toward one or the other request (otherwise scheduler -will bias toward front request). Default value of back_seek_penalty is 2. - -fifo_expire_async ------------------ -This parameter is used to set the timeout of asynchronous requests. Default -value of this is 248ms. - -fifo_expire_sync ----------------- -This parameter is used to set the timeout of synchronous requests. Default -value of this is 124ms. In case to favor synchronous requests over asynchronous -one, this value should be decreased relative to fifo_expire_async. - -slice_async ------------ -This parameter is same as of slice_sync but for asynchronous queue. The -default value is 40ms. - -slice_async_rq --------------- -This parameter is used to limit the dispatching of asynchronous request to -device request queue in queue's slice time. The maximum number of request that -are allowed to be dispatched also depends upon the io priority. Default value -for this is 2. - -slice_sync ----------- -When a queue is selected for execution, the queues IO requests are only -executed for a certain amount of time(time_slice) before switching to another -queue. This parameter is used to calculate the time slice of synchronous -queue. - -time_slice is computed using the below equation:- -time_slice = slice_sync + (slice_sync/5 * (4 - prio)). To increase the -time_slice of synchronous queue, increase the value of slice_sync. Default -value is 100ms. - -quantum -------- -This specifies the number of request dispatched to the device queue. In a -queue's time slice, a request will not be dispatched if the number of request -in the device exceeds this parameter. This parameter is used for synchronous -request. - -In case of storage with several disk, this setting can limit the parallel -processing of request. Therefore, increasing the value can imporve the -performace although this can cause the latency of some I/O to increase due -to more number of requests. - CFQ IOPS Mode for group scheduling =================================== Basic CFQ design is to provide priority based time slices. Higher priority diff --git a/trunk/Documentation/block/queue-sysfs.txt b/trunk/Documentation/block/queue-sysfs.txt index e54ac1d53403..6518a55273e7 100644 --- a/trunk/Documentation/block/queue-sysfs.txt +++ b/trunk/Documentation/block/queue-sysfs.txt @@ -9,71 +9,20 @@ These files are the ones found in the /sys/block/xxx/queue/ directory. Files denoted with a RO postfix are readonly and the RW postfix means read-write. -add_random (RW) ----------------- -This file allows to trun off the disk entropy contribution. Default -value of this file is '1'(on). - -discard_granularity (RO) ------------------------ -This shows the size of internal allocation of the device in bytes, if -reported by the device. A value of '0' means device does not support -the discard functionality. - -discard_max_bytes (RO) ----------------------- -Devices that support discard functionality may have internal limits on -the number of bytes that can be trimmed or unmapped in a single operation. -The discard_max_bytes parameter is set by the device driver to the maximum -number of bytes that can be discarded in a single operation. Discard -requests issued to the device must not exceed this limit. A discard_max_bytes -value of 0 means that the device does not support discard functionality. - -discard_zeroes_data (RO) ------------------------- -When read, this file will show if the discarded block are zeroed by the -device or not. If its value is '1' the blocks are zeroed otherwise not. - hw_sector_size (RO) ------------------- This is the hardware sector size of the device, in bytes. -iostats (RW) -------------- -This file is used to control (on/off) the iostats accounting of the -disk. - -logical_block_size (RO) ------------------------ -This is the logcal block size of the device, in bytes. - max_hw_sectors_kb (RO) ---------------------- This is the maximum number of kilobytes supported in a single data transfer. -max_integrity_segments (RO) ---------------------------- -When read, this file shows the max limit of integrity segments as -set by block layer which a hardware controller can handle. - max_sectors_kb (RW) ------------------- This is the maximum number of kilobytes that the block layer will allow for a filesystem request. Must be smaller than or equal to the maximum size allowed by the hardware. -max_segments (RO) ------------------ -Maximum number of segments of the device. - -max_segment_size (RO) ---------------------- -Maximum segment size of the device. - -minimum_io_size (RO) --------------------- -This is the smallest preferred io size reported by the device. - nomerges (RW) ------------- This enables the user to disable the lookup logic involved with IO @@ -96,24 +45,11 @@ per-block-cgroup request pool. IOW, if there are N block cgroups, each request queue may have upto N request pools, each independently regulated by nr_requests. -optimal_io_size (RO) --------------------- -This is the optimal io size reported by the device. - -physical_block_size (RO) ------------------------- -This is the physical block size of device, in bytes. - read_ahead_kb (RW) ------------------ Maximum number of kilobytes to read-ahead for filesystems on this block device. -rotational (RW) ---------------- -This file is used to stat if the device is of rotational type or -non-rotational type. - rq_affinity (RW) ---------------- If this option is '1', the block layer will migrate request completions to the diff --git a/trunk/Documentation/devicetree/bindings/misc/at25.txt b/trunk/Documentation/devicetree/bindings/misc/at25.txt index 1d3447165c37..ab3c327929dd 100644 --- a/trunk/Documentation/devicetree/bindings/misc/at25.txt +++ b/trunk/Documentation/devicetree/bindings/misc/at25.txt @@ -1,35 +1,21 @@ -EEPROMs (SPI) compatible with Atmel at25. +Atmel AT25 eeprom Required properties: - compatible : "atmel,at25". - reg : chip select number - spi-max-frequency : max spi frequency to use -- pagesize : size of the eeprom page -- size : total eeprom size in bytes -- address-width : number of address bits (one of 8, 16, or 24) -Optional properties: -- spi-cpha : SPI shifted clock phase, as per spi-bus bindings. -- spi-cpol : SPI inverse clock polarity, as per spi-bus bindings. -- read-only : this parameter-less property disables writes to the eeprom - -Obsolete legacy properties are can be used in place of "size", "pagesize", -"address-width", and "read-only": - at25,byte-len : total eeprom size in bytes - at25,addr-mode : addr-mode flags, as defined in include/linux/spi/eeprom.h - at25,page-size : size of the eeprom page -Additional compatible properties are also allowed. - -Example: - at25@0 { - compatible = "atmel,at25", "st,m95256"; - reg = <0> - spi-max-frequency = <5000000>; - spi-cpha; - spi-cpol; +Examples: +at25@0 { + compatible = "atmel,at25"; + reg = <0> + spi-max-frequency = <5000000>; - pagesize = <64>; - size = <32768>; - address-width = <16>; - }; + at25,byte-len = <0x8000>; + at25,addr-mode = <2>; + at25,page-size = <64>; +}; diff --git a/trunk/Documentation/devicetree/bindings/misc/lis302.txt b/trunk/Documentation/devicetree/bindings/misc/lis302.txt deleted file mode 100644 index 6def86f6b053..000000000000 --- a/trunk/Documentation/devicetree/bindings/misc/lis302.txt +++ /dev/null @@ -1,112 +0,0 @@ -LIS302 accelerometer devicetree bindings - -This device is matched via its bus drivers, and has a number of properties -that apply in on the generic device (independent from the bus). - - -Required properties for the SPI bindings: - - compatible: should be set to "st,lis3lv02d_spi" - - reg: the chipselect index - - spi-max-frequency: maximal bus speed, should be set to 1000000 unless - constrained by external circuitry - - interrupts: the interrupt generated by the device - -Required properties for the I2C bindings: - - compatible: should be set to "st,lis3lv02d" - - reg: i2c slave address - - Vdd-supply: The input supply for Vdd - - Vdd_IO-supply: The input supply for Vdd_IO - - -Optional properties for all bus drivers: - - - st,click-single-{x,y,z}: if present, tells the device to issue an - interrupt on single click events on the - x/y/z axis. - - st,click-double-{x,y,z}: if present, tells the device to issue an - interrupt on double click events on the - x/y/z axis. - - st,click-thresh-{x,y,z}: set the x/y/z axis threshold - - st,click-click-time-limit: click time limit, from 0 to 127.5msec - with step of 0.5 msec - - st,click-latency: click latency, from 0 to 255 msec with - step of 1 msec. - - st,click-window: click window, from 0 to 255 msec with - step of 1 msec. - - st,irq{1,2}-disable: disable IRQ 1/2 - - st,irq{1,2}-ff-wu-1: raise IRQ 1/2 on FF_WU_1 condition - - st,irq{1,2}-ff-wu-2: raise IRQ 1/2 on FF_WU_2 condition - - st,irq{1,2}-data-ready: raise IRQ 1/2 on data ready contition - - st,irq{1,2}-click: raise IRQ 1/2 on click condition - - st,irq-open-drain: consider IRQ lines open-drain - - st,irq-active-low: make IRQ lines active low - - st,wu-duration-1: duration register for Free-Fall/Wake-Up - interrupt 1 - - st,wu-duration-2: duration register for Free-Fall/Wake-Up - interrupt 2 - - st,wakeup-{x,y,z}-{lo,hi}: set wakeup condition on x/y/z axis for - upper/lower limit - - st,highpass-cutoff-hz=: 1, 2, 4 or 8 for 1Hz, 2Hz, 4Hz or 8Hz of - highpass cut-off frequency - - st,hipass{1,2}-disable: disable highpass 1/2. - - st,default-rate=: set the default rate - - st,axis-{x,y,z}=: set the axis to map to the three coordinates - - st,{min,max}-limit-{x,y,z} set the min/max limits for x/y/z axis - (used by self-test) - - -Example for a SPI device node: - - lis302@0 { - compatible = "st,lis302dl-spi"; - reg = <0>; - spi-max-frequency = <1000000>; - interrupt-parent = <&gpio>; - interrupts = <104 0>; - - st,click-single-x; - st,click-single-y; - st,click-single-z; - st,click-thresh-x = <10>; - st,click-thresh-y = <10>; - st,click-thresh-z = <10>; - st,irq1-click; - st,irq2-click; - st,wakeup-x-lo; - st,wakeup-x-hi; - st,wakeup-y-lo; - st,wakeup-y-hi; - st,wakeup-z-lo; - st,wakeup-z-hi; - }; - -Example for a I2C device node: - - lis331dlh: lis331dlh@18 { - compatible = "st,lis331dlh", "st,lis3lv02d"; - reg = <0x18>; - Vdd-supply = <&lis3_reg>; - Vdd_IO-supply = <&lis3_reg>; - - st,click-single-x; - st,click-single-y; - st,click-single-z; - st,click-thresh-x = <10>; - st,click-thresh-y = <10>; - st,click-thresh-z = <10>; - st,irq1-click; - st,irq2-click; - st,wakeup-x-lo; - st,wakeup-x-hi; - st,wakeup-y-lo; - st,wakeup-y-hi; - st,wakeup-z-lo; - st,wakeup-z-hi; - st,min-limit-x = <120>; - st,min-limit-y = <120>; - st,min-limit-z = <140>; - st,max-limit-x = <550>; - st,max-limit-y = <550>; - st,max-limit-z = <750>; - }; - diff --git a/trunk/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.txt b/trunk/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.txt index 1dd622546d06..70cd49b1caa8 100644 --- a/trunk/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.txt +++ b/trunk/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.txt @@ -10,8 +10,8 @@ Required properties: - compatible : Should be "fsl,-esdhc" Optional properties: -- fsl,cd-controller : Indicate to use controller internal card detection -- fsl,wp-controller : Indicate to use controller internal write protection +- fsl,cd-internal : Indicate to use controller internal card detection +- fsl,wp-internal : Indicate to use controller internal write protection Examples: @@ -19,8 +19,8 @@ esdhc@70004000 { compatible = "fsl,imx51-esdhc"; reg = <0x70004000 0x4000>; interrupts = <1>; - fsl,cd-controller; - fsl,wp-controller; + fsl,cd-internal; + fsl,wp-internal; }; esdhc@70008000 { diff --git a/trunk/Documentation/devicetree/bindings/regulator/regulator.txt b/trunk/Documentation/devicetree/bindings/regulator/regulator.txt index ecfc6ccd67ef..66ece3f87bbc 100644 --- a/trunk/Documentation/devicetree/bindings/regulator/regulator.txt +++ b/trunk/Documentation/devicetree/bindings/regulator/regulator.txt @@ -11,13 +11,10 @@ Optional properties: - regulator-boot-on: bootloader/firmware enabled regulator - -supply: phandle to the parent supply/regulator node - regulator-ramp-delay: ramp delay for regulator(in uV/uS) - -Deprecated properties: - regulator-compatible: If a regulator chip contains multiple regulators, and if the chip's binding contains a child node that describes each regulator, then this property indicates which regulator - this child node is intended to configure. If this property is missing, - the node's name will be used instead. + this child node is intended to configure. Example: diff --git a/trunk/Documentation/devicetree/bindings/regulator/tps65217.txt b/trunk/Documentation/devicetree/bindings/regulator/tps65217.txt index d316fb895daf..0487e9675ba0 100644 --- a/trunk/Documentation/devicetree/bindings/regulator/tps65217.txt +++ b/trunk/Documentation/devicetree/bindings/regulator/tps65217.txt @@ -22,49 +22,66 @@ Example: compatible = "ti,tps65217"; regulators { - dcdc1_reg: dcdc1 { + #address-cells = <1>; + #size-cells = <0>; + + dcdc1_reg: regulator@0 { + reg = <0>; + regulator-compatible = "dcdc1"; regulator-min-microvolt = <900000>; regulator-max-microvolt = <1800000>; regulator-boot-on; regulator-always-on; }; - dcdc2_reg: dcdc2 { + dcdc2_reg: regulator@1 { + reg = <1>; + regulator-compatible = "dcdc2"; regulator-min-microvolt = <900000>; regulator-max-microvolt = <3300000>; regulator-boot-on; regulator-always-on; }; - dcdc3_reg: dcc3 { + dcdc3_reg: regulator@2 { + reg = <2>; + regulator-compatible = "dcdc3"; regulator-min-microvolt = <900000>; regulator-max-microvolt = <1500000>; regulator-boot-on; regulator-always-on; }; - ldo1_reg: ldo1 { + ldo1_reg: regulator@3 { + reg = <3>; + regulator-compatible = "ldo1"; regulator-min-microvolt = <1000000>; regulator-max-microvolt = <3300000>; regulator-boot-on; regulator-always-on; }; - ldo2_reg: ldo2 { + ldo2_reg: regulator@4 { + reg = <4>; + regulator-compatible = "ldo2"; regulator-min-microvolt = <900000>; regulator-max-microvolt = <3300000>; regulator-boot-on; regulator-always-on; }; - ldo3_reg: ldo3 { + ldo3_reg: regulator@5 { + reg = <5>; + regulator-compatible = "ldo3"; regulator-min-microvolt = <1800000>; regulator-max-microvolt = <3300000>; regulator-boot-on; regulator-always-on; }; - ldo4_reg: ldo4 { + ldo4_reg: regulator@6 { + reg = <6>; + regulator-compatible = "ldo4"; regulator-min-microvolt = <1800000>; regulator-max-microvolt = <3300000>; regulator-boot-on; diff --git a/trunk/Documentation/devicetree/bindings/regulator/tps6586x.txt b/trunk/Documentation/devicetree/bindings/regulator/tps6586x.txt index 07b9ef6e49d5..d156e1b5db12 100644 --- a/trunk/Documentation/devicetree/bindings/regulator/tps6586x.txt +++ b/trunk/Documentation/devicetree/bindings/regulator/tps6586x.txt @@ -6,16 +6,12 @@ Required properties: - interrupts: the interrupt outputs of the controller - #gpio-cells: number of cells to describe a GPIO - gpio-controller: mark the device as a GPIO controller -- regulators: A node that houses a sub-node for each regulator within the - device. Each sub-node is identified using the node's name (or the deprecated - regulator-compatible property if present), with valid values listed below. - The content of each sub-node is defined by the standard binding for - regulators; see regulator.txt. - sys, sm[0-2], ldo[0-9] and ldo_rtc -- sys-supply: The input supply for SYS. -- vin-sm0-supply: The input supply for the SM0. -- vin-sm1-supply: The input supply for the SM1. -- vin-sm2-supply: The input supply for the SM2. +- regulators: list of regulators provided by this controller, must have + property "regulator-compatible" to match their hardware counterparts: + sm[0-2], ldo[0-9] and ldo_rtc +- sm0-supply: The input supply for the SM0. +- sm1-supply: The input supply for the SM1. +- sm2-supply: The input supply for the SM2. - vinldo01-supply: The input supply for the LDO1 and LDO2 - vinldo23-supply: The input supply for the LDO2 and LDO3 - vinldo4-supply: The input supply for the LDO4 @@ -24,9 +20,6 @@ Required properties: Each regulator is defined using the standard binding for regulators. -Note: LDO5 and LDO_RTC is supplied by SYS regulator internally and driver - take care of making proper parent child relationship. - Example: pmu: tps6586x@34 { @@ -37,10 +30,9 @@ Example: #gpio-cells = <2>; gpio-controller; - sys-supply = <&some_reg>; - vin-sm0-supply = <&some_reg>; - vin-sm1-supply = <&some_reg>; - vin-sm2-supply = <&some_reg>; + sm0-supply = <&some_reg>; + sm1-supply = <&some_reg>; + sm2-supply = <&some_reg>; vinldo01-supply = <...>; vinldo23-supply = <...>; vinldo4-supply = <...>; @@ -48,80 +40,103 @@ Example: vinldo9-supply = <...>; regulators { - sys_reg: sys { - regulator-name = "vdd_sys"; - regulator-boot-on; - regulator-always-on; - }; + #address-cells = <1>; + #size-cells = <0>; - sm0_reg: sm0 { + sm0_reg: regulator@0 { + reg = <0>; + regulator-compatible = "sm0"; regulator-min-microvolt = < 725000>; regulator-max-microvolt = <1500000>; regulator-boot-on; regulator-always-on; }; - sm1_reg: sm1 { + sm1_reg: regulator@1 { + reg = <1>; + regulator-compatible = "sm1"; regulator-min-microvolt = < 725000>; regulator-max-microvolt = <1500000>; regulator-boot-on; regulator-always-on; }; - sm2_reg: sm2 { + sm2_reg: regulator@2 { + reg = <2>; + regulator-compatible = "sm2"; regulator-min-microvolt = <3000000>; regulator-max-microvolt = <4550000>; regulator-boot-on; regulator-always-on; }; - ldo0_reg: ldo0 { + ldo0_reg: regulator@3 { + reg = <3>; + regulator-compatible = "ldo0"; regulator-name = "PCIE CLK"; regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; }; - ldo1_reg: ldo1 { + ldo1_reg: regulator@4 { + reg = <4>; + regulator-compatible = "ldo1"; regulator-min-microvolt = < 725000>; regulator-max-microvolt = <1500000>; }; - ldo2_reg: ldo2 { + ldo2_reg: regulator@5 { + reg = <5>; + regulator-compatible = "ldo2"; regulator-min-microvolt = < 725000>; regulator-max-microvolt = <1500000>; }; - ldo3_reg: ldo3 { + ldo3_reg: regulator@6 { + reg = <6>; + regulator-compatible = "ldo3"; regulator-min-microvolt = <1250000>; regulator-max-microvolt = <3300000>; }; - ldo4_reg: ldo4 { + ldo4_reg: regulator@7 { + reg = <7>; + regulator-compatible = "ldo4"; regulator-min-microvolt = <1700000>; regulator-max-microvolt = <2475000>; }; - ldo5_reg: ldo5 { + ldo5_reg: regulator@8 { + reg = <8>; + regulator-compatible = "ldo5"; regulator-min-microvolt = <1250000>; regulator-max-microvolt = <3300000>; }; - ldo6_reg: ldo6 { + ldo6_reg: regulator@9 { + reg = <9>; + regulator-compatible = "ldo6"; regulator-min-microvolt = <1250000>; regulator-max-microvolt = <3300000>; }; - ldo7_reg: ldo7 { + ldo7_reg: regulator@10 { + reg = <10>; + regulator-compatible = "ldo7"; regulator-min-microvolt = <1250000>; regulator-max-microvolt = <3300000>; }; - ldo8_reg: ldo8 { + ldo8_reg: regulator@11 { + reg = <11>; + regulator-compatible = "ldo8"; regulator-min-microvolt = <1250000>; regulator-max-microvolt = <3300000>; }; - ldo9_reg: ldo9 { + ldo9_reg: regulator@12 { + reg = <12>; + regulator-compatible = "ldo9"; regulator-min-microvolt = <1250000>; regulator-max-microvolt = <3300000>; }; diff --git a/trunk/Documentation/devicetree/bindings/staging/iio/adc/mxs-lradc.txt b/trunk/Documentation/devicetree/bindings/staging/iio/adc/mxs-lradc.txt deleted file mode 100644 index 801d58cb6d4d..000000000000 --- a/trunk/Documentation/devicetree/bindings/staging/iio/adc/mxs-lradc.txt +++ /dev/null @@ -1,15 +0,0 @@ -* Freescale i.MX28 LRADC device driver - -Required properties: -- compatible: Should be "fsl,imx28-lradc" -- reg: Address and length of the register set for the device -- interrupts: Should contain the LRADC interrupts - -Examples: - - lradc@80050000 { - compatible = "fsl,imx28-lradc"; - reg = <0x80050000 0x2000>; - interrupts = <10 14 15 16 17 18 19 - 20 21 22 23 24 25>; - }; diff --git a/trunk/Documentation/devicetree/bindings/staging/imx-drm/fsl-imx-drm.txt b/trunk/Documentation/devicetree/bindings/staging/imx-drm/fsl-imx-drm.txt deleted file mode 100644 index 07654f0338b6..000000000000 --- a/trunk/Documentation/devicetree/bindings/staging/imx-drm/fsl-imx-drm.txt +++ /dev/null @@ -1,41 +0,0 @@ -Freescale i.MX IPUv3 -==================== - -Required properties: -- compatible: Should be "fsl,-ipu" -- reg: should be register base and length as documented in the - datasheet -- interrupts: Should contain sync interrupt and error interrupt, - in this order. -- #crtc-cells: 1, See below - -example: - -ipu: ipu@18000000 { - #crtc-cells = <1>; - compatible = "fsl,imx53-ipu"; - reg = <0x18000000 0x080000000>; - interrupts = <11 10>; -}; - -Parallel display support -======================== - -Required properties: -- compatible: Should be "fsl,imx-parallel-display" -- crtc: the crtc this display is connected to, see below -Optional properties: -- interface_pix_fmt: How this display is connected to the - crtc. Currently supported types: "rgb24", "rgb565" -- edid: verbatim EDID data block describing attached display. -- ddc: phandle describing the i2c bus handling the display data - channel - -example: - -display@di0 { - compatible = "fsl,imx-parallel-display"; - edid = [edid-data]; - crtc = <&ipu 0>; - interface-pix-fmt = "rgb24"; -}; diff --git a/trunk/Documentation/devicetree/bindings/tty/serial/nxp-lpc32xx-hsuart.txt b/trunk/Documentation/devicetree/bindings/tty/serial/nxp-lpc32xx-hsuart.txt deleted file mode 100644 index 0d439dfc1aa5..000000000000 --- a/trunk/Documentation/devicetree/bindings/tty/serial/nxp-lpc32xx-hsuart.txt +++ /dev/null @@ -1,14 +0,0 @@ -* NXP LPC32xx SoC High Speed UART - -Required properties: -- compatible: Should be "nxp,lpc3220-hsuart" -- reg: Should contain registers location and length -- interrupts: Should contain interrupt - -Example: - - uart1: serial@40014000 { - compatible = "nxp,lpc3220-hsuart"; - reg = <0x40014000 0x1000>; - interrupts = <26 0>; - }; diff --git a/trunk/Documentation/devicetree/bindings/tty/serial/of-serial.txt b/trunk/Documentation/devicetree/bindings/tty/serial/of-serial.txt index ba385f2e0ddc..0847fdeee11a 100644 --- a/trunk/Documentation/devicetree/bindings/tty/serial/of-serial.txt +++ b/trunk/Documentation/devicetree/bindings/tty/serial/of-serial.txt @@ -25,8 +25,6 @@ Optional properties: accesses to the UART (e.g. TI davinci). - used-by-rtas : set to indicate that the port is in use by the OpenFirmware RTAS and should not be registered. -- no-loopback-test: set to indicate that the port does not implements loopback - test mode Example: diff --git a/trunk/Documentation/devicetree/bindings/usb/pxa-usb.txt b/trunk/Documentation/devicetree/bindings/usb/pxa-usb.txt new file mode 100644 index 000000000000..79729a948d5a --- /dev/null +++ b/trunk/Documentation/devicetree/bindings/usb/pxa-usb.txt @@ -0,0 +1,31 @@ +PXA USB controllers + +OHCI + +Required properties: + - compatible: Should be "marvell,pxa-ohci" for USB controllers + used in host mode. + +Optional properties: + - "marvell,enable-port1", "marvell,enable-port2", "marvell,enable-port3" + If present, enables the appropriate USB port of the controller. + - "marvell,port-mode" selects the mode of the ports: + 1 = PMM_NPS_MODE + 2 = PMM_GLOBAL_MODE + 3 = PMM_PERPORT_MODE + - "marvell,power-sense-low" - power sense pin is low-active. + - "marvell,power-control-low" - power control pin is low-active. + - "marvell,no-oc-protection" - disable over-current protection. + - "marvell,oc-mode-perport" - enable per-port over-current protection. + - "marvell,power_on_delay" Power On to Power Good time - in ms. + +Example: + + usb0: ohci@4c000000 { + compatible = "marvell,pxa-ohci", "usb-ohci"; + reg = <0x4c000000 0x100000>; + interrupts = <18>; + marvell,enable-port1; + marvell,port-mode = <2>; /* PMM_GLOBAL_MODE */ + }; + diff --git a/trunk/Documentation/devicetree/bindings/w1/w1-gpio.txt b/trunk/Documentation/devicetree/bindings/w1/w1-gpio.txt deleted file mode 100644 index 6e09c35d9f1a..000000000000 --- a/trunk/Documentation/devicetree/bindings/w1/w1-gpio.txt +++ /dev/null @@ -1,22 +0,0 @@ -w1-gpio devicetree bindings - -Required properties: - - - compatible: "w1-gpio" - - gpios: one or two GPIO specs: - - the first one is used as data I/O pin - - the second one is optional. If specified, it is used as - enable pin for an external pin pullup. - -Optional properties: - - - linux,open-drain: if specified, the data pin is considered in - open-drain mode. - -Examples: - - onewire@0 { - compatible = "w1-gpio"; - gpios = <&gpio 126 0>, <&gpio 105 0>; - }; - diff --git a/trunk/Documentation/dontdiff b/trunk/Documentation/dontdiff index 74c25c8d8884..39462cf35cd4 100644 --- a/trunk/Documentation/dontdiff +++ b/trunk/Documentation/dontdiff @@ -162,6 +162,7 @@ mach-types.h machtypes.h map map_hugetlb +maui_boot.h media mconf miboot* diff --git a/trunk/Documentation/feature-removal-schedule.txt b/trunk/Documentation/feature-removal-schedule.txt index bc55d38081dc..afaff312bf41 100644 --- a/trunk/Documentation/feature-removal-schedule.txt +++ b/trunk/Documentation/feature-removal-schedule.txt @@ -253,6 +253,38 @@ Who: Dave Jones , Matthew Garrett ----------------------------- +What: fakephp and associated sysfs files in /sys/bus/pci/slots/ +When: 2011 +Why: In 2.6.27, the semantics of /sys/bus/pci/slots was redefined to + represent a machine's physical PCI slots. The change in semantics + had userspace implications, as the hotplug core no longer allowed + drivers to create multiple sysfs files per physical slot (required + for multi-function devices, e.g.). fakephp was seen as a developer's + tool only, and its interface changed. Too late, we learned that + there were some users of the fakephp interface. + + In 2.6.30, the original fakephp interface was restored. At the same + time, the PCI core gained the ability that fakephp provided, namely + function-level hot-remove and hot-add. + + Since the PCI core now provides the same functionality, exposed in: + + /sys/bus/pci/rescan + /sys/bus/pci/devices/.../remove + /sys/bus/pci/devices/.../rescan + + there is no functional reason to maintain fakephp as well. + + We will keep the existing module so that 'modprobe fakephp' will + present the old /sys/bus/pci/slots/... interface for compatibility, + but users are urged to migrate their applications to the API above. + + After a reasonable transition period, we will remove the legacy + fakephp interface. +Who: Alex Chiang + +--------------------------- + What: CONFIG_RFKILL_INPUT When: 2.6.33 Why: Should be implemented in userspace, policy daemon. @@ -547,7 +579,7 @@ Why: KVM tracepoints provide mostly equivalent information in a much more ---------------------------- What: at91-mci driver ("CONFIG_MMC_AT91") -When: 3.8 +When: 3.7 Why: There are two mci drivers: at91-mci and atmel-mci. The PDC support was added to atmel-mci as a first step to support more chips. Then at91-mci was kept only for old IP versions (on at91rm9200 and diff --git a/trunk/Documentation/filesystems/Locking b/trunk/Documentation/filesystems/Locking index e540a24e5d06..0f103e39b4f6 100644 --- a/trunk/Documentation/filesystems/Locking +++ b/trunk/Documentation/filesystems/Locking @@ -114,6 +114,7 @@ prototypes: int (*drop_inode) (struct inode *); void (*evict_inode) (struct inode *); void (*put_super) (struct super_block *); + void (*write_super) (struct super_block *); int (*sync_fs)(struct super_block *sb, int wait); int (*freeze_fs) (struct super_block *); int (*unfreeze_fs) (struct super_block *); @@ -135,6 +136,7 @@ write_inode: drop_inode: !!!inode->i_lock!!! evict_inode: put_super: write +write_super: read sync_fs: read freeze_fs: write unfreeze_fs: write diff --git a/trunk/Documentation/filesystems/debugfs.txt b/trunk/Documentation/filesystems/debugfs.txt index 3a863f692728..7a34f827989c 100644 --- a/trunk/Documentation/filesystems/debugfs.txt +++ b/trunk/Documentation/filesystems/debugfs.txt @@ -15,8 +15,8 @@ Debugfs is typically mounted with a command like: mount -t debugfs none /sys/kernel/debug (Or an equivalent /etc/fstab line). -The debugfs root directory is accessible only to the root user by -default. To change access to the tree the "uid", "gid" and "mode" mount +The debugfs root directory is accessible by anyone by default. To +restrict access to the tree the "uid", "gid" and "mode" mount options can be used. Note that the debugfs API is exported GPL-only to modules. diff --git a/trunk/Documentation/filesystems/porting b/trunk/Documentation/filesystems/porting index 0742feebc6e2..2bef2b3843d1 100644 --- a/trunk/Documentation/filesystems/porting +++ b/trunk/Documentation/filesystems/porting @@ -94,8 +94,9 @@ protected. --- [mandatory] -BKL is also moved from around sb operations. BKL should have been shifted into -individual fs sb_op functions. If you don't need it, remove it. +BKL is also moved from around sb operations. ->write_super() Is now called +without BKL held. BKL should have been shifted into individual fs sb_op +functions. If you don't need it, remove it. --- [informational] diff --git a/trunk/Documentation/filesystems/vfat.txt b/trunk/Documentation/filesystems/vfat.txt index de1e6c4dccff..ead764b2728f 100644 --- a/trunk/Documentation/filesystems/vfat.txt +++ b/trunk/Documentation/filesystems/vfat.txt @@ -137,17 +137,6 @@ errors=panic|continue|remount-ro without doing anything or remount the partition in read-only mode (default behavior). -discard -- If set, issues discard/TRIM commands to the block - device when blocks are freed. This is useful for SSD devices - and sparse/thinly-provisoned LUNs. - -nfs -- This option maintains an index (cache) of directory - inodes by i_logstart which is used by the nfs-related code to - improve look-ups. - - Enable this only if you want to export the FAT filesystem - over NFS - : 0,1,yes,no,true,false TODO diff --git a/trunk/Documentation/filesystems/vfs.txt b/trunk/Documentation/filesystems/vfs.txt index 2ee133e030c3..065aa2dc0835 100644 --- a/trunk/Documentation/filesystems/vfs.txt +++ b/trunk/Documentation/filesystems/vfs.txt @@ -216,6 +216,7 @@ struct super_operations { void (*drop_inode) (struct inode *); void (*delete_inode) (struct inode *); void (*put_super) (struct super_block *); + void (*write_super) (struct super_block *); int (*sync_fs)(struct super_block *sb, int wait); int (*freeze_fs) (struct super_block *); int (*unfreeze_fs) (struct super_block *); @@ -272,6 +273,9 @@ or bottom half). put_super: called when the VFS wishes to free the superblock (i.e. unmount). This is called with the superblock lock held + write_super: called when the VFS superblock needs to be written to + disc. This method is optional + sync_fs: called when VFS is writing out all dirty data associated with a superblock. The second parameter indicates whether the method should wait until the write out has been completed. Optional. diff --git a/trunk/Documentation/hid/hid-sensor.txt b/trunk/Documentation/hid/hid-sensor.txt deleted file mode 100755 index 948b0989c433..000000000000 --- a/trunk/Documentation/hid/hid-sensor.txt +++ /dev/null @@ -1,140 +0,0 @@ - -HID Sensors Framework -====================== -HID sensor framework provides necessary interfaces to implement sensor drivers, -which are connected to a sensor hub. The sensor hub is a HID device and it provides -a report descriptor conforming to HID 1.12 sensor usage tables. - -Description from the HID 1.12 "HID Sensor Usages" specification: -"Standardization of HID usages for sensors would allow (but not require) sensor -hardware vendors to provide a consistent Plug And Play interface at the USB boundary, -thereby enabling some operating systems to incorporate common device drivers that -could be reused between vendors, alleviating any need for the vendors to provide -the drivers themselves." - -This specification describes many usage IDs, which describe the type of sensor -and also the individual data fields. Each sensor can have variable number of -data fields. The length and order is specified in the report descriptor. For -example a part of report descriptor can look like: - - INPUT(1)[INPUT] - .. - Field(2) - Physical(0020.0073) - Usage(1) - 0020.045f - Logical Minimum(-32767) - Logical Maximum(32767) - Report Size(8) - Report Count(1) - Report Offset(16) - Flags(Variable Absolute) -.. -.. - -The report is indicating "sensor page (0x20)" contains an accelerometer-3D (0x73). -This accelerometer-3D has some fields. Here for example field 2 is motion intensity -(0x045f) with a logical minimum value of -32767 and logical maximum of 32767. The -order of fields and length of each field is important as the input event raw -data will use this format. - - -Implementation -================= - -This specification defines many different types of sensors with different sets of -data fields. It is difficult to have a common input event to user space applications, -for different sensors. For example an accelerometer can send X,Y and Z data, whereas -an ambient light sensor can send illumination data. -So the implementation has two parts: -- Core hid driver -- Individual sensor processing part (sensor drivers) - -Core driver ------------ -The core driver registers (hid-sensor-hub) registers as a HID driver. It parses -report descriptors and identifies all the sensors present. It adds an MFD device -with name HID-SENSOR-xxxx (where xxxx is usage id from the specification). -For example -HID-SENSOR-200073 is registered for an Accelerometer 3D driver. -So if any driver with this name is inserted, then the probe routine for that -function will be called. So an accelerometer processing driver can register -with this name and will be probed if there is an accelerometer-3D detected. - -The core driver provides a set of APIs which can be used by the processing -drivers to register and get events for that usage id. Also it provides parsing -functions, which get and set each input/feature/output report. - -Individual sensor processing part (sensor drivers) ------------ -The processing driver will use an interface provided by the core driver to parse -the report and get the indexes of the fields and also can get events. This driver -can use IIO interface to use the standard ABI defined for a type of sensor. - - -Core driver Interface -===================== - -Callback structure: -Each processing driver can use this structure to set some callbacks. - int (*suspend)(..): Callback when HID suspend is received - int (*resume)(..): Callback when HID resume is received - int (*capture_sample)(..): Capture a sample for one of its data fields - int (*send_event)(..): One complete event is received which can have - multiple data fields. - -Registration functions: -int sensor_hub_register_callback(struct hid_sensor_hub_device *hsdev, - u32 usage_id, - struct hid_sensor_hub_callbacks *usage_callback): - -Registers callbacks for an usage id. The callback functions are not allowed -to sleep. - - -int sensor_hub_remove_callback(struct hid_sensor_hub_device *hsdev, - u32 usage_id): - -Removes callbacks for an usage id. - - -Parsing function: -int sensor_hub_input_get_attribute_info(struct hid_sensor_hub_device *hsdev, - u8 type, - u32 usage_id, u32 attr_usage_id, - struct hid_sensor_hub_attribute_info *info); - -A processing driver can look for some field of interest and check if it exists -in a report descriptor. If it exists it will store necessary information -so that fields can be set or get individually. -These indexes avoid searching every time and getting field index to get or set. - - -Set Feature report -int sensor_hub_set_feature(struct hid_sensor_hub_device *hsdev, u32 report_id, - u32 field_index, s32 value); - -This interface is used to set a value for a field in feature report. For example -if there is a field report_interval, which is parsed by a call to -sensor_hub_input_get_attribute_info before, then it can directly set that individual -field. - - -int sensor_hub_get_feature(struct hid_sensor_hub_device *hsdev, u32 report_id, - u32 field_index, s32 *value); - -This interface is used to get a value for a field in input report. For example -if there is a field report_interval, which is parsed by a call to -sensor_hub_input_get_attribute_info before, then it can directly get that individual -field value. - - -int sensor_hub_input_attr_get_raw_value(struct hid_sensor_hub_device *hsdev, - u32 usage_id, - u32 attr_usage_id, u32 report_id); - -This is used to get a particular field value through input reports. For example -accelerometer wants to poll X axis value, then it can call this function with -the usage id of X axis. HID sensors can provide events, so this is not necessary -to poll for any field. If there is some new sample, the core driver will call -registered callback function to process the sample. diff --git a/trunk/Documentation/i2c/busses/i2c-i801 b/trunk/Documentation/i2c/busses/i2c-i801 index 157416e78cc4..615142da4ef6 100644 --- a/trunk/Documentation/i2c/busses/i2c-i801 +++ b/trunk/Documentation/i2c/busses/i2c-i801 @@ -21,7 +21,6 @@ Supported adapters: * Intel DH89xxCC (PCH) * Intel Panther Point (PCH) * Intel Lynx Point (PCH) - * Intel Lynx Point-LP (PCH) Datasheets: Publicly available at the Intel website On Intel Patsburg and later chipsets, both the normal host SMBus controller diff --git a/trunk/Documentation/ia64/aliasing-test.c b/trunk/Documentation/ia64/aliasing-test.c index 62a190d45f38..5caa2af33207 100644 --- a/trunk/Documentation/ia64/aliasing-test.c +++ b/trunk/Documentation/ia64/aliasing-test.c @@ -132,7 +132,6 @@ static int read_rom(char *path) rc = write(fd, "1", 2); if (rc <= 0) { - close(fd); perror("write"); return -1; } diff --git a/trunk/Documentation/kernel-parameters.txt b/trunk/Documentation/kernel-parameters.txt index df551dfa8e52..ad7e2e5088c1 100644 --- a/trunk/Documentation/kernel-parameters.txt +++ b/trunk/Documentation/kernel-parameters.txt @@ -1833,12 +1833,6 @@ bytes respectively. Such letter suffixes can also be entirely omitted. and restore using xsave. The kernel will fallback to enabling legacy floating-point and sse state. - eagerfpu= [X86] - on enable eager fpu restore - off disable eager fpu restore - auto selects the default scheme, which automatically - enables eagerfpu restore for xsaveopt. - nohlt [BUGS=ARM,SH] Tells the kernel that the sleep(SH) or wfi(ARM) instruction doesn't work correctly and not to use it. This is also useful when using JTAG debugger. @@ -2391,17 +2385,6 @@ bytes respectively. Such letter suffixes can also be entirely omitted. rcutree.rcu_cpu_stall_timeout= [KNL,BOOT] Set timeout for RCU CPU stall warning messages. - rcutree.jiffies_till_first_fqs= [KNL,BOOT] - Set delay from grace-period initialization to - first attempt to force quiescent states. - Units are jiffies, minimum value is zero, - and maximum value is HZ. - - rcutree.jiffies_till_next_fqs= [KNL,BOOT] - Set delay between subsequent attempts to force - quiescent states. Units are jiffies, minimum - value is one, and maximum value is HZ. - rcutorture.fqs_duration= [KNL,BOOT] Set duration of force_quiescent_state bursts. @@ -2655,6 +2638,9 @@ bytes respectively. Such letter suffixes can also be entirely omitted. smart2= [HW] Format: [,[,...,]] + smp-alt-once [X86-32,SMP] On a hotplug CPU system, only + attempt to substitute SMP alternatives once at boot. + smsc-ircc2.nopnp [HW] Don't use PNP to discover SMC devices smsc-ircc2.ircc_cfg= [HW] Device configuration I/O port smsc-ircc2.ircc_sir= [HW] SIR base I/O port diff --git a/trunk/Documentation/kobject.txt b/trunk/Documentation/kobject.txt index c5182bb2c16c..49578cf1aea5 100644 --- a/trunk/Documentation/kobject.txt +++ b/trunk/Documentation/kobject.txt @@ -284,11 +284,9 @@ instead, it is associated with the ktype. So let us introduce struct kobj_type: struct kobj_type { - void (*release)(struct kobject *kobj); + void (*release)(struct kobject *); const struct sysfs_ops *sysfs_ops; - struct attribute **default_attrs; - const struct kobj_ns_type_operations *(*child_ns_type)(struct kobject *kobj); - const void *(*namespace)(struct kobject *kobj); + struct attribute **default_attrs; }; This structure is used to describe a particular type of kobject (or, more diff --git a/trunk/Documentation/laptops/laptop-mode.txt b/trunk/Documentation/laptops/laptop-mode.txt index 4ebbfc3f1c6e..0bf25eebce94 100644 --- a/trunk/Documentation/laptops/laptop-mode.txt +++ b/trunk/Documentation/laptops/laptop-mode.txt @@ -262,9 +262,9 @@ MINIMUM_BATTERY_MINUTES=10 # # Allowed dirty background ratio, in percent. Once DIRTY_RATIO has been -# exceeded, the kernel will wake flusher threads which will then reduce the -# amount of dirty memory to dirty_background_ratio. Set this nice and low, -# so once some writeout has commenced, we do a lot of it. +# exceeded, the kernel will wake pdflush which will then reduce the amount +# of dirty memory to dirty_background_ratio. Set this nice and low, so once +# some writeout has commenced, we do a lot of it. # #DIRTY_BACKGROUND_RATIO=5 @@ -384,9 +384,9 @@ CPU_MAXFREQ=${CPU_MAXFREQ:-'slowest'} # # Allowed dirty background ratio, in percent. Once DIRTY_RATIO has been -# exceeded, the kernel will wake flusher threads which will then reduce the -# amount of dirty memory to dirty_background_ratio. Set this nice and low, -# so once some writeout has commenced, we do a lot of it. +# exceeded, the kernel will wake pdflush which will then reduce the amount +# of dirty memory to dirty_background_ratio. Set this nice and low, so once +# some writeout has commenced, we do a lot of it. # DIRTY_BACKGROUND_RATIO=${DIRTY_BACKGROUND_RATIO:-'5'} diff --git a/trunk/Documentation/misc-devices/lis3lv02d b/trunk/Documentation/misc-devices/lis3lv02d index af815b9ba413..f1a4ec840f86 100644 --- a/trunk/Documentation/misc-devices/lis3lv02d +++ b/trunk/Documentation/misc-devices/lis3lv02d @@ -4,8 +4,7 @@ Kernel driver lis3lv02d Supported chips: * STMicroelectronics LIS3LV02DL, LIS3LV02DQ (12 bits precision) - * STMicroelectronics LIS302DL, LIS3L02DQ, LIS331DL (8 bits) and - LIS331DLH (16 bits) + * STMicroelectronics LIS302DL, LIS3L02DQ, LIS331DL (8 bits) Authors: Yan Burman diff --git a/trunk/Documentation/networking/netconsole.txt b/trunk/Documentation/networking/netconsole.txt index 2e9e0ae2cd45..8d022073e3ef 100644 --- a/trunk/Documentation/networking/netconsole.txt +++ b/trunk/Documentation/networking/netconsole.txt @@ -51,23 +51,8 @@ Built-in netconsole starts immediately after the TCP stack is initialized and attempts to bring up the supplied dev at the supplied address. -The remote host has several options to receive the kernel messages, -for example: - -1) syslogd - -2) netcat - - On distributions using a BSD-based netcat version (e.g. Fedora, - openSUSE and Ubuntu) the listening port must be specified without - the -p switch: - - 'nc -u -l -p ' / 'nc -u -l ' or - 'netcat -u -l -p ' / 'netcat -u -l ' - -3) socat - - 'socat udp-recv: -' +The remote host can run either 'netcat -u -l -p ', +'nc -l -u ' or syslogd. Dynamic reconfiguration: ======================== diff --git a/trunk/Documentation/pinctrl.txt b/trunk/Documentation/pinctrl.txt index 1479aca23744..e40f4b4e1977 100644 --- a/trunk/Documentation/pinctrl.txt +++ b/trunk/Documentation/pinctrl.txt @@ -840,9 +840,9 @@ static unsigned long i2c_pin_configs[] = { static struct pinctrl_map __initdata mapping[] = { PIN_MAP_MUX_GROUP("foo-i2c.0", PINCTRL_STATE_DEFAULT, "pinctrl-foo", "i2c0", "i2c0"), - PIN_MAP_CONFIGS_GROUP("foo-i2c.0", PINCTRL_STATE_DEFAULT, "pinctrl-foo", "i2c0", i2c_grp_configs), - PIN_MAP_CONFIGS_PIN("foo-i2c.0", PINCTRL_STATE_DEFAULT, "pinctrl-foo", "i2c0scl", i2c_pin_configs), - PIN_MAP_CONFIGS_PIN("foo-i2c.0", PINCTRL_STATE_DEFAULT, "pinctrl-foo", "i2c0sda", i2c_pin_configs), + PIN_MAP_MUX_CONFIGS_GROUP("foo-i2c.0", PINCTRL_STATE_DEFAULT, "pinctrl-foo", "i2c0", i2c_grp_configs), + PIN_MAP_MUX_CONFIGS_PIN("foo-i2c.0", PINCTRL_STATE_DEFAULT, "pinctrl-foo", "i2c0scl", i2c_pin_configs), + PIN_MAP_MUX_CONFIGS_PIN("foo-i2c.0", PINCTRL_STATE_DEFAULT, "pinctrl-foo", "i2c0sda", i2c_pin_configs), }; Finally, some devices expect the mapping table to contain certain specific diff --git a/trunk/Documentation/power/swsusp.txt b/trunk/Documentation/power/swsusp.txt index 0b4b63e7e9b6..92341b84250d 100644 --- a/trunk/Documentation/power/swsusp.txt +++ b/trunk/Documentation/power/swsusp.txt @@ -53,7 +53,7 @@ before suspend (it is limited to 500 MB by default). Article about goals and implementation of Software Suspend for Linux ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Author: Gábor Kuti +Author: G‚ábor Kuti Last revised: 2003-10-20 by Pavel Machek Idea and goals to achieve diff --git a/trunk/Documentation/scheduler/sched-arch.txt b/trunk/Documentation/scheduler/sched-arch.txt index b1b8587b86f0..28aa1075e291 100644 --- a/trunk/Documentation/scheduler/sched-arch.txt +++ b/trunk/Documentation/scheduler/sched-arch.txt @@ -17,6 +17,16 @@ you must `#define __ARCH_WANT_UNLOCKED_CTXSW` in a header file Unlocked context switches introduce only a very minor performance penalty to the core scheduler implementation in the CONFIG_SMP case. +2. Interrupt status +By default, the switch_to arch function is called with interrupts +disabled. Interrupts may be enabled over the call if it is likely to +introduce a significant interrupt latency by adding the line +`#define __ARCH_WANT_INTERRUPTS_ON_CTXSW` in the same place as for +unlocked context switches. This define also implies +`__ARCH_WANT_UNLOCKED_CTXSW`. See arch/arm/include/asm/system.h for an +example. + + CPU idle ======== Your cpu_idle routines need to obey the following rules: diff --git a/trunk/Documentation/security/Yama.txt b/trunk/Documentation/security/Yama.txt index dd908cf64ecf..e369de2d48cd 100644 --- a/trunk/Documentation/security/Yama.txt +++ b/trunk/Documentation/security/Yama.txt @@ -46,13 +46,14 @@ restrictions, it can call prctl(PR_SET_PTRACER, PR_SET_PTRACER_ANY, ...) so that any otherwise allowed process (even those in external pid namespaces) may attach. -The sysctl settings (writable only with CAP_SYS_PTRACE) are: +These restrictions do not change how ptrace via PTRACE_TRACEME operates. + +The sysctl settings are: 0 - classic ptrace permissions: a process can PTRACE_ATTACH to any other process running under the same uid, as long as it is dumpable (i.e. did not transition uids, start privileged, or have called - prctl(PR_SET_DUMPABLE...) already). Similarly, PTRACE_TRACEME is - unchanged. + prctl(PR_SET_DUMPABLE...) already). 1 - restricted ptrace: a process must have a predefined relationship with the inferior it wants to call PTRACE_ATTACH on. By default, @@ -60,13 +61,12 @@ The sysctl settings (writable only with CAP_SYS_PTRACE) are: classic criteria is also met. To change the relationship, an inferior can call prctl(PR_SET_PTRACER, debugger, ...) to declare an allowed debugger PID to call PTRACE_ATTACH on the inferior. - Using PTRACE_TRACEME is unchanged. 2 - admin-only attach: only processes with CAP_SYS_PTRACE may use ptrace - with PTRACE_ATTACH, or through children calling PTRACE_TRACEME. + with PTRACE_ATTACH. -3 - no attach: no processes may use ptrace with PTRACE_ATTACH nor via - PTRACE_TRACEME. Once set, this sysctl value cannot be changed. +3 - no attach: no processes may use ptrace with PTRACE_ATTACH. Once set, + this sysctl cannot be changed to a lower value. The original children-only logic was based on the restrictions in grsecurity. diff --git a/trunk/Documentation/serial/00-INDEX b/trunk/Documentation/serial/00-INDEX index f7b0c7dc25ef..e09468ad3cb1 100644 --- a/trunk/Documentation/serial/00-INDEX +++ b/trunk/Documentation/serial/00-INDEX @@ -2,6 +2,8 @@ - this file. README.cycladesZ - info on Cyclades-Z firmware loading. +computone.txt + - info on Computone Intelliport II/Plus Multiport Serial Driver. digiepca.txt - info on Digi Intl. {PC,PCI,EISA}Xx and Xem series cards. hayes-esp.txt diff --git a/trunk/Documentation/serial/computone.txt b/trunk/Documentation/serial/computone.txt new file mode 100644 index 000000000000..a6a1158ea2ba --- /dev/null +++ b/trunk/Documentation/serial/computone.txt @@ -0,0 +1,520 @@ +NOTE: This is an unmaintained driver. It is not guaranteed to work due to +changes made in the tty layer in 2.6. If you wish to take over maintenance of +this driver, contact Michael Warfield . + +Changelog: +---------- +11-01-2001: Original Document + +10-29-2004: Minor misspelling & format fix, update status of driver. + James Nelson + +Computone Intelliport II/Plus Multiport Serial Driver +----------------------------------------------------- + +Release Notes For Linux Kernel 2.2 and higher. +These notes are for the drivers which have already been integrated into the +kernel and have been tested on Linux kernels 2.0, 2.2, 2.3, and 2.4. + +Version: 1.2.14 +Date: 11/01/2001 +Historical Author: Andrew Manison +Primary Author: Doug McNash + +This file assumes that you are using the Computone drivers which are +integrated into the kernel sources. For updating the drivers or installing +drivers into kernels which do not already have Computone drivers, please +refer to the instructions in the README.computone file in the driver patch. + + +1. INTRODUCTION + +This driver supports the entire family of Intelliport II/Plus controllers +with the exception of the MicroChannel controllers. It does not support +products previous to the Intelliport II. + +This driver was developed on the v2.0.x Linux tree and has been tested up +to v2.4.14; it will probably not work with earlier v1.X kernels,. + + +2. QUICK INSTALLATION + +Hardware - If you have an ISA card, find a free interrupt and io port. + List those in use with `cat /proc/interrupts` and + `cat /proc/ioports`. Set the card dip switches to a free + address. You may need to configure your BIOS to reserve an + irq for an ISA card. PCI and EISA parameters are set + automagically. Insert card into computer with the power off + before or after drivers installation. + + Note the hardware address from the Computone ISA cards installed into + the system. These are required for editing ip2.c or editing + /etc/modprobe.d/*.conf, or for specification on the modprobe + command line. + + Note that the /etc/modules.conf should be used for older (pre-2.6) + kernels. + +Software - + +Module installation: + +a) Determine free irq/address to use if any (configure BIOS if need be) +b) Run "make config" or "make menuconfig" or "make xconfig" + Select (m) module for CONFIG_COMPUTONE under character + devices. CONFIG_PCI and CONFIG_MODULES also may need to be set. +c) Set address on ISA cards then: + edit /usr/src/linux/drivers/char/ip2.c if needed + or + edit config file in /etc/modprobe.d/ if needed (module). + or both to match this setting. +d) Run "make modules" +e) Run "make modules_install" +f) Run "/sbin/depmod -a" +g) install driver using `modprobe ip2 ` (options listed below) +h) run ip2mkdev (either the script below or the binary version) + + +Kernel installation: + +a) Determine free irq/address to use if any (configure BIOS if need be) +b) Run "make config" or "make menuconfig" or "make xconfig" + Select (y) kernel for CONFIG_COMPUTONE under character + devices. CONFIG_PCI may need to be set if you have PCI bus. +c) Set address on ISA cards then: + edit /usr/src/linux/drivers/char/ip2.c + (Optional - may be specified on kernel command line now) +d) Run "make zImage" or whatever target you prefer. +e) mv /usr/src/linux/arch/x86/boot/zImage to /boot. +f) Add new config for this kernel into /etc/lilo.conf, run "lilo" + or copy to a floppy disk and boot from that floppy disk. +g) Reboot using this kernel +h) run ip2mkdev (either the script below or the binary version) + +Kernel command line options: + +When compiling the driver into the kernel, io and irq may be +compiled into the driver by editing ip2.c and setting the values for +io and irq in the appropriate array. An alternative is to specify +a command line parameter to the kernel at boot up. + + ip2=io0,irq0,io1,irq1,io2,irq2,io3,irq3 + +Note that this order is very different from the specifications for the +modload parameters which have separate IRQ and IO specifiers. + +The io port also selects PCI (1) and EISA (2) boards. + + io=0 No board + io=1 PCI board + io=2 EISA board + else ISA board io address + +You only need to specify the boards which are present. + + Examples: + + 2 PCI boards: + + ip2=1,0,1,0 + + 1 ISA board at 0x310 irq 5: + + ip2=0x310,5 + +This can be added to and "append" option in lilo.conf similar to this: + + append="ip2=1,0,1,0" + + +3. INSTALLATION + +Previously, the driver sources were packaged with a set of patch files +to update the character drivers' makefile and configuration file, and other +kernel source files. A build script (ip2build) was included which applies +the patches if needed, and build any utilities needed. +What you receive may be a single patch file in conventional kernel +patch format build script. That form can also be applied by +running patch -p1 < ThePatchFile. Otherwise run ip2build. + +The driver can be installed as a module (recommended) or built into the +kernel. This is selected as for other drivers through the `make config` +command from the root of the Linux source tree. If the driver is built +into the kernel you will need to edit the file ip2.c to match the boards +you are installing. See that file for instructions. If the driver is +installed as a module the configuration can also be specified on the +modprobe command line as follows: + + modprobe ip2 irq=irq1,irq2,irq3,irq4 io=addr1,addr2,addr3,addr4 + +where irqnum is one of the valid Intelliport II interrupts (3,4,5,7,10,11, +12,15) and addr1-4 are the base addresses for up to four controllers. If +the irqs are not specified the driver uses the default in ip2.c (which +selects polled mode). If no base addresses are specified the defaults in +ip2.c are used. If you are autoloading the driver module with kerneld or +kmod the base addresses and interrupt number must also be set in ip2.c +and recompile or just insert and options line in /etc/modprobe.d/*.conf or both. +The options line is equivalent to the command line and takes precedence over +what is in ip2.c. + +config sample to put /etc/modprobe.d/*.conf: + options ip2 io=1,0x328 irq=1,10 + alias char-major-71 ip2 + alias char-major-72 ip2 + alias char-major-73 ip2 + +The equivalent in ip2.c: + +static int io[IP2_MAX_BOARDS]= { 1, 0x328, 0, 0 }; +static int irq[IP2_MAX_BOARDS] = { 1, 10, -1, -1 }; + +The equivalent for the kernel command line (in lilo.conf): + + append="ip2=1,1,0x328,10" + + +Note: Both io and irq should be updated to reflect YOUR system. An "io" + address of 1 or 2 indicates a PCI or EISA card in the board table. + The PCI or EISA irq will be assigned automatically. + +Specifying an invalid or in-use irq will default the driver into +running in polled mode for that card. If all irq entries are 0 then +all cards will operate in polled mode. + +If you select the driver as part of the kernel run : + + make zlilo (or whatever you do to create a bootable kernel) + +If you selected a module run : + + make modules && make modules_install + +The utility ip2mkdev (see 5 and 7 below) creates all the device nodes +required by the driver. For a device to be created it must be configured +in the driver and the board must be installed. Only devices corresponding +to real IntelliPort II ports are created. With multiple boards and expansion +boxes this will leave gaps in the sequence of device names. ip2mkdev uses +Linux tty naming conventions: ttyF0 - ttyF255 for normal devices, and +cuf0 - cuf255 for callout devices. + + +4. USING THE DRIVERS + +As noted above, the driver implements the ports in accordance with Linux +conventions, and the devices should be interchangeable with the standard +serial devices. (This is a key point for problem reporting: please make +sure that what you are trying do works on the ttySx/cuax ports first; then +tell us what went wrong with the ip2 ports!) + +Higher speeds can be obtained using the setserial utility which remaps +38,400 bps (extb) to 57,600 bps, 115,200 bps, or a custom speed. +Intelliport II installations using the PowerPort expansion module can +use the custom speed setting to select the highest speeds: 153,600 bps, +230,400 bps, 307,200 bps, 460,800bps and 921,600 bps. The base for +custom baud rate configuration is fixed at 921,600 for cards/expansion +modules with ST654's and 115200 for those with Cirrus CD1400's. This +corresponds to the maximum bit rates those chips are capable. +For example if the baud base is 921600 and the baud divisor is 18 then +the custom rate is 921600/18 = 51200 bps. See the setserial man page for +complete details. Of course if stty accepts the higher rates now you can +use that as well as the standard ioctls(). + + +5. ip2mkdev and assorted utilities... + +Several utilities, including the source for a binary ip2mkdev utility are +available under .../drivers/char/ip2. These can be build by changing to +that directory and typing "make" after the kernel has be built. If you do +not wish to compile the binary utilities, the shell script below can be +cut out and run as "ip2mkdev" to create the necessary device files. To +use the ip2mkdev script, you must have procfs enabled and the proc file +system mounted on /proc. + + +6. NOTES + +This is a release version of the driver, but it is impossible to test it +in all configurations of Linux. If there is any anomalous behaviour that +does not match the standard serial port's behaviour please let us know. + + +7. ip2mkdev shell script + +Previously, this script was simply attached here. It is now attached as a +shar archive to make it easier to extract the script from the documentation. +To create the ip2mkdev shell script change to a convenient directory (/tmp +works just fine) and run the following command: + + unshar Documentation/serial/computone.txt + (This file) + +You should now have a file ip2mkdev in your current working directory with +permissions set to execute. Running that script with then create the +necessary devices for the Computone boards, interfaces, and ports which +are present on you system at the time it is run. + + +#!/bin/sh +# This is a shell archive (produced by GNU sharutils 4.2.1). +# To extract the files from this archive, save it to some FILE, remove +# everything before the `!/bin/sh' line above, then type `sh FILE'. +# +# Made on 2001-10-29 10:32 EST by . +# Source directory was `/home2/src/tmp'. +# +# Existing files will *not* be overwritten unless `-c' is specified. +# +# This shar contains: +# length mode name +# ------ ---------- ------------------------------------------ +# 4251 -rwxr-xr-x ip2mkdev +# +save_IFS="${IFS}" +IFS="${IFS}:" +gettext_dir=FAILED +locale_dir=FAILED +first_param="$1" +for dir in $PATH +do + if test "$gettext_dir" = FAILED && test -f $dir/gettext \ + && ($dir/gettext --version >/dev/null 2>&1) + then + set `$dir/gettext --version 2>&1` + if test "$3" = GNU + then + gettext_dir=$dir + fi + fi + if test "$locale_dir" = FAILED && test -f $dir/shar \ + && ($dir/shar --print-text-domain-dir >/dev/null 2>&1) + then + locale_dir=`$dir/shar --print-text-domain-dir` + fi +done +IFS="$save_IFS" +if test "$locale_dir" = FAILED || test "$gettext_dir" = FAILED +then + echo=echo +else + TEXTDOMAINDIR=$locale_dir + export TEXTDOMAINDIR + TEXTDOMAIN=sharutils + export TEXTDOMAIN + echo="$gettext_dir/gettext -s" +fi +if touch -am -t 200112312359.59 $$.touch >/dev/null 2>&1 && test ! -f 200112312359.59 -a -f $$.touch; then + shar_touch='touch -am -t $1$2$3$4$5$6.$7 "$8"' +elif touch -am 123123592001.59 $$.touch >/dev/null 2>&1 && test ! -f 123123592001.59 -a ! -f 123123592001.5 -a -f $$.touch; then + shar_touch='touch -am $3$4$5$6$1$2.$7 "$8"' +elif touch -am 1231235901 $$.touch >/dev/null 2>&1 && test ! -f 1231235901 -a -f $$.touch; then + shar_touch='touch -am $3$4$5$6$2 "$8"' +else + shar_touch=: + echo + $echo 'WARNING: not restoring timestamps. Consider getting and' + $echo "installing GNU \`touch', distributed in GNU File Utilities..." + echo +fi +rm -f 200112312359.59 123123592001.59 123123592001.5 1231235901 $$.touch +# +if mkdir _sh17581; then + $echo 'x -' 'creating lock directory' +else + $echo 'failed to create lock directory' + exit 1 +fi +# ============= ip2mkdev ============== +if test -f 'ip2mkdev' && test "$first_param" != -c; then + $echo 'x -' SKIPPING 'ip2mkdev' '(file already exists)' +else + $echo 'x -' extracting 'ip2mkdev' '(text)' + sed 's/^X//' << 'SHAR_EOF' > 'ip2mkdev' && +#!/bin/sh - +# +# ip2mkdev +# +# Make or remove devices as needed for Computone Intelliport drivers +# +# First rule! If the dev file exists and you need it, don't mess +# with it. That prevents us from screwing up open ttys, ownership +# and permissions on a running system! +# +# This script will NOT remove devices that no longer exist if their +# board or interface box has been removed. If you want to get rid +# of them, you can manually do an "rm -f /dev/ttyF* /dev/cuaf*" +# before running this script. Running this script will then recreate +# all the valid devices. +# +# Michael H. Warfield +# /\/\|=mhw=|\/\/ +# mhw@wittsend.com +# +# Updated 10/29/2000 for version 1.2.13 naming convention +# under devfs. /\/\|=mhw=|\/\/ +# +# Updated 03/09/2000 for devfs support in ip2 drivers. /\/\|=mhw=|\/\/ +# +X +if test -d /dev/ip2 ; then +# This is devfs mode... We don't do anything except create symlinks +# from the real devices to the old names! +X cd /dev +X echo "Creating symbolic links to devfs devices" +X for i in `ls ip2` ; do +X if test ! -L ip2$i ; then +X # Remove it incase it wasn't a symlink (old device) +X rm -f ip2$i +X ln -s ip2/$i ip2$i +X fi +X done +X for i in `( cd tts ; ls F* )` ; do +X if test ! -L tty$i ; then +X # Remove it incase it wasn't a symlink (old device) +X rm -f tty$i +X ln -s tts/$i tty$i +X fi +X done +X for i in `( cd cua ; ls F* )` ; do +X DEVNUMBER=`expr $i : 'F\(.*\)'` +X if test ! -L cuf$DEVNUMBER ; then +X # Remove it incase it wasn't a symlink (old device) +X rm -f cuf$DEVNUMBER +X ln -s cua/$i cuf$DEVNUMBER +X fi +X done +X exit 0 +fi +X +if test ! -f /proc/tty/drivers +then +X echo "\ +Unable to check driver status. +Make sure proc file system is mounted." +X +X exit 255 +fi +X +if test ! -f /proc/tty/driver/ip2 +then +X echo "\ +Unable to locate ip2 proc file. +Attempting to load driver" +X +X if /sbin/insmod ip2 +X then +X if test ! -f /proc/tty/driver/ip2 +X then +X echo "\ +Unable to locate ip2 proc file after loading driver. +Driver initialization failure or driver version error. +" +X exit 255 +X fi +X else +X echo "Unable to load ip2 driver." +X exit 255 +X fi +fi +X +# Ok... So we got the driver loaded and we can locate the procfs files. +# Next we need our major numbers. +X +TTYMAJOR=`sed -e '/^ip2/!d' -e '/\/dev\/tt/!d' -e 's/.*tt[^ ]*[ ]*\([0-9]*\)[ ]*.*/\1/' < /proc/tty/drivers` +CUAMAJOR=`sed -e '/^ip2/!d' -e '/\/dev\/cu/!d' -e 's/.*cu[^ ]*[ ]*\([0-9]*\)[ ]*.*/\1/' < /proc/tty/drivers` +BRDMAJOR=`sed -e '/^Driver: /!d' -e 's/.*IMajor=\([0-9]*\)[ ]*.*/\1/' < /proc/tty/driver/ip2` +X +echo "\ +TTYMAJOR = $TTYMAJOR +CUAMAJOR = $CUAMAJOR +BRDMAJOR = $BRDMAJOR +" +X +# Ok... Now we should know our major numbers, if appropriate... +# Now we need our boards and start the device loops. +X +grep '^Board [0-9]:' /proc/tty/driver/ip2 | while read token number type alltherest +do +X # The test for blank "type" will catch the stats lead-in lines +X # if they exist in the file +X if test "$type" = "vacant" -o "$type" = "Vacant" -o "$type" = "" +X then +X continue +X fi +X +X BOARDNO=`expr "$number" : '\([0-9]\):'` +X PORTS=`expr "$alltherest" : '.*ports=\([0-9]*\)' | tr ',' ' '` +X MINORS=`expr "$alltherest" : '.*minors=\([0-9,]*\)' | tr ',' ' '` +X +X if test "$BOARDNO" = "" -o "$PORTS" = "" +X then +# This may be a bug. We should at least get this much information +X echo "Unable to process board line" +X continue +X fi +X +X if test "$MINORS" = "" +X then +# Silently skip this one. This board seems to have no boxes +X continue +X fi +X +X echo "board $BOARDNO: $type ports = $PORTS; port numbers = $MINORS" +X +X if test "$BRDMAJOR" != "" +X then +X BRDMINOR=`expr $BOARDNO \* 4` +X STSMINOR=`expr $BRDMINOR + 1` +X if test ! -c /dev/ip2ipl$BOARDNO ; then +X mknod /dev/ip2ipl$BOARDNO c $BRDMAJOR $BRDMINOR +X fi +X if test ! -c /dev/ip2stat$BOARDNO ; then +X mknod /dev/ip2stat$BOARDNO c $BRDMAJOR $STSMINOR +X fi +X fi +X +X if test "$TTYMAJOR" != "" +X then +X PORTNO=$BOARDBASE +X +X for PORTNO in $MINORS +X do +X if test ! -c /dev/ttyF$PORTNO ; then +X # We got the hardware but no device - make it +X mknod /dev/ttyF$PORTNO c $TTYMAJOR $PORTNO +X fi +X done +X fi +X +X if test "$CUAMAJOR" != "" +X then +X PORTNO=$BOARDBASE +X +X for PORTNO in $MINORS +X do +X if test ! -c /dev/cuf$PORTNO ; then +X # We got the hardware but no device - make it +X mknod /dev/cuf$PORTNO c $CUAMAJOR $PORTNO +X fi +X done +X fi +done +X +Xexit 0 +SHAR_EOF + (set 20 01 10 29 10 32 01 'ip2mkdev'; eval "$shar_touch") && + chmod 0755 'ip2mkdev' || + $echo 'restore of' 'ip2mkdev' 'failed' + if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \ + && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then + md5sum -c << SHAR_EOF >/dev/null 2>&1 \ + || $echo 'ip2mkdev:' 'MD5 check failed' +cb5717134509f38bad9fde6b1f79b4a4 ip2mkdev +SHAR_EOF + else + shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'ip2mkdev'`" + test 4251 -eq "$shar_count" || + $echo 'ip2mkdev:' 'original size' '4251,' 'current size' "$shar_count!" + fi +fi +rm -fr _sh17581 +exit 0 diff --git a/trunk/Documentation/sysctl/vm.txt b/trunk/Documentation/sysctl/vm.txt index 078701fdbd4d..dcc2a94ae34e 100644 --- a/trunk/Documentation/sysctl/vm.txt +++ b/trunk/Documentation/sysctl/vm.txt @@ -76,8 +76,8 @@ huge pages although processes will also directly compact memory as required. dirty_background_bytes -Contains the amount of dirty memory at which the background kernel -flusher threads will start writeback. +Contains the amount of dirty memory at which the pdflush background writeback +daemon will start writeback. Note: dirty_background_bytes is the counterpart of dirty_background_ratio. Only one of them may be specified at a time. When one sysctl is written it is @@ -89,7 +89,7 @@ other appears as 0 when read. dirty_background_ratio Contains, as a percentage of total system memory, the number of pages at which -the background kernel flusher threads will start writing out dirty data. +the pdflush background writeback daemon will start writing out dirty data. ============================================================== @@ -112,9 +112,9 @@ retained. dirty_expire_centisecs This tunable is used to define when dirty data is old enough to be eligible -for writeout by the kernel flusher threads. It is expressed in 100'ths -of a second. Data which has been dirty in-memory for longer than this -interval will be written out next time a flusher thread wakes up. +for writeout by the pdflush daemons. It is expressed in 100'ths of a second. +Data which has been dirty in-memory for longer than this interval will be +written out next time a pdflush daemon wakes up. ============================================================== @@ -128,7 +128,7 @@ data. dirty_writeback_centisecs -The kernel flusher threads will periodically wake up and write `old' data +The pdflush writeback daemons will periodically wake up and write `old' data out to disk. This tunable expresses the interval between those wakeups, in 100'ths of a second. diff --git a/trunk/Documentation/trace/kprobetrace.txt b/trunk/Documentation/trace/kprobetrace.txt index d68ea5fc812b..d0d0bb9e3e25 100644 --- a/trunk/Documentation/trace/kprobetrace.txt +++ b/trunk/Documentation/trace/kprobetrace.txt @@ -12,7 +12,7 @@ kprobes can probe (this means, all functions body except for __kprobes functions). Unlike the Tracepoint based event, this can be added and removed dynamically, on the fly. -To enable this feature, build your kernel with CONFIG_KPROBE_EVENT=y. +To enable this feature, build your kernel with CONFIG_KPROBE_TRACING=y. Similar to the events tracer, this doesn't need to be activated via current_tracer. Instead of that, add probe points via diff --git a/trunk/Documentation/vfio.txt b/trunk/Documentation/vfio.txt index 8eda3635a17d..0cb6685c8029 100644 --- a/trunk/Documentation/vfio.txt +++ b/trunk/Documentation/vfio.txt @@ -133,7 +133,7 @@ character devices for this group: $ lspci -n -s 0000:06:0d.0 06:0d.0 0401: 1102:0002 (rev 08) # echo 0000:06:0d.0 > /sys/bus/pci/devices/0000:06:0d.0/driver/unbind -# echo 1102 0002 > /sys/bus/pci/drivers/vfio-pci/new_id +# echo 1102 0002 > /sys/bus/pci/drivers/vfio/new_id Now we need to look at what other devices are in the group to free it for use by VFIO: diff --git a/trunk/Documentation/vm/hugetlbpage.txt b/trunk/Documentation/vm/hugetlbpage.txt index 4ac359b7aa17..f8551b3879f8 100644 --- a/trunk/Documentation/vm/hugetlbpage.txt +++ b/trunk/Documentation/vm/hugetlbpage.txt @@ -299,17 +299,11 @@ map_hugetlb.c. ******************************************************************* /* - * map_hugetlb: see tools/testing/selftests/vm/map_hugetlb.c + * hugepage-shm: see Documentation/vm/hugepage-shm.c */ ******************************************************************* /* - * hugepage-shm: see tools/testing/selftests/vm/hugepage-shm.c - */ - -******************************************************************* - -/* - * hugepage-mmap: see tools/testing/selftests/vm/hugepage-mmap.c + * hugepage-mmap: see Documentation/vm/hugepage-mmap.c */ diff --git a/trunk/Documentation/w1/slaves/w1_therm b/trunk/Documentation/w1/slaves/w1_therm index 874a8ca93feb..0403aaaba878 100644 --- a/trunk/Documentation/w1/slaves/w1_therm +++ b/trunk/Documentation/w1/slaves/w1_therm @@ -3,7 +3,6 @@ Kernel driver w1_therm Supported chips: * Maxim ds18*20 based temperature sensors. - * Maxim ds1825 based temperature sensors. Author: Evgeniy Polyakov @@ -16,7 +15,6 @@ supported family codes: W1_THERM_DS18S20 0x10 W1_THERM_DS1822 0x22 W1_THERM_DS18B20 0x28 -W1_THERM_DS1825 0x3B Support is provided through the sysfs w1_slave file. Each open and read sequence will initiate a temperature conversion then provide two diff --git a/trunk/Documentation/watchdog/src/watchdog-test.c b/trunk/Documentation/watchdog/src/watchdog-test.c index 3da822967ee0..73ff5cc93e05 100644 --- a/trunk/Documentation/watchdog/src/watchdog-test.c +++ b/trunk/Documentation/watchdog/src/watchdog-test.c @@ -31,7 +31,7 @@ static void keep_alive(void) * or "-e" to enable the card. */ -static void term(int sig) +void term(int sig) { close(fd); fprintf(stderr, "Stopping watchdog ticks...\n"); diff --git a/trunk/Documentation/x86/x86_64/boot-options.txt b/trunk/Documentation/x86/x86_64/boot-options.txt index de38429beb71..c54b4f503e2a 100644 --- a/trunk/Documentation/x86/x86_64/boot-options.txt +++ b/trunk/Documentation/x86/x86_64/boot-options.txt @@ -50,13 +50,6 @@ Machine check monarchtimeout: Sets the time in us to wait for other CPUs on machine checks. 0 to disable. - mce=bios_cmci_threshold - Don't overwrite the bios-set CMCI threshold. This boot option - prevents Linux from overwriting the CMCI threshold set by the - bios. Without this option, Linux always sets the CMCI - threshold to 1. Enabling this may make memory predictive failure - analysis less effective if the bios sets thresholds for memory - errors since we will not see details for all errors. nomce (for compatibility with i386): same as mce=off diff --git a/trunk/Documentation/zh_CN/arm/Booting b/trunk/Documentation/zh_CN/arm/Booting deleted file mode 100644 index 6158a64df80c..000000000000 --- a/trunk/Documentation/zh_CN/arm/Booting +++ /dev/null @@ -1,175 +0,0 @@ -Chinese translated version of Documentation/arm/Booting - -If you have any comment or update to the content, please contact the -original document maintainer directly. However, if you have a problem -communicating in English you can also ask the Chinese maintainer for -help. Contact the Chinese maintainer if this translation is outdated -or if there is a problem with the translation. - -Maintainer: Russell King -Chinese maintainer: Fu Wei ---------------------------------------------------------------------- -Documentation/arm/Booting 的中文翻译 - -如果想评论或更新本文的内容,请直接联系原文档的维护者。如果你使用英文 -交流有困难的话,也可以向中文版维护者求助。如果本翻译更新不及时或者翻 -译存在问题,请联系中文版维护者。 - -英文版维护者: Russell King -中文版维护者: 傅炜 Fu Wei -中文版翻译者: 傅炜 Fu Wei -中文版校译者: 傅炜 Fu Wei - -以下为正文 ---------------------------------------------------------------------- - - 启动 ARM Linux - ============== - -作者:Russell King -日期:2002年5月18日 - -以下文档适用于 2.4.18-rmk6 及以上版本。 - -为了启动 ARM Linux,你需要一个引导装载程序(boot loader), -它是一个在主内核启动前运行的一个小程序。引导装载程序需要初始化各种 -设备,并最终调用 Linux 内核,将信息传递给内核。 - -从本质上讲,引导装载程序应提供(至少)以下功能: - -1、设置和初始化 RAM。 -2、初始化一个串口。 -3、检测机器的类型(machine type)。 -4、设置内核标签列表(tagged list)。 -5、调用内核映像。 - - -1、设置和初始化 RAM -------------------- - -现有的引导加载程序: 强制 -新开发的引导加载程序: 强制 - -引导装载程序应该找到并初始化系统中所有内核用于保持系统变量数据的 RAM。 -这个操作的执行是设备依赖的。(它可能使用内部算法来自动定位和计算所有 -RAM,或可能使用对这个设备已知的 RAM 信息,还可能使用任何引导装载程序 -设计者想到的匹配方法。) - - -2、初始化一个串口 ------------------------------ - -现有的引导加载程序: 可选、建议 -新开发的引导加载程序: 可选、建议 - -引导加载程序应该初始化并使能一个目标板上的串口。这允许内核串口驱动 -自动检测哪个串口用于内核控制台。(一般用于调试或与目标板通信。) - -作为替代方案,引导加载程序也可以通过标签列表传递相关的'console=' -选项给内核以指定某个串口,而串口数据格式的选项在以下文档中描述: - - Documentation/kernel-parameters.txt。 - - -3、检测机器类型 --------------------------- - -现有的引导加载程序: 可选 -新开发的引导加载程序: 强制 - -引导加载程序应该通过某些方式检测自身所处的机器类型。这是一个硬件 -代码或通过查看所连接的硬件用某些算法得到,这些超出了本文档的范围。 -引导加载程序最终必须能提供一个 MACH_TYPE_xxx 值给内核。 -(详见 linux/arch/arm/tools/mach-types )。 - -4、设置启动数据 ------------------- - -现有的引导加载程序: 可选、强烈建议 -新开发的引导加载程序: 强制 - -引导加载程序必须提供标签列表或者 dtb 映像以传递配置数据给内核。启动 -数据的物理地址通过寄存器 r2 传递给内核。 - -4a、设置内核标签列表 --------------------------------- - -bootloader 必须创建和初始化内核标签列表。一个有效的标签列表以 -ATAG_CORE 标签开始,并以 ATAG_NONE 标签结束。ATAG_CORE 标签可以是 -空的,也可以是非空。一个空 ATAG_CORE 标签其 size 域设置为 -‘2’(0x00000002)。ATAG_NONE 标签的 size 域必须设置为零。 - -在列表中可以保存任意数量的标签。对于一个重复的标签是追加到之前标签 -所携带的信息之后,还是会覆盖原来的信息,是未定义的。某些标签的行为 -是前者,其他是后者。 - -bootloader 必须传递一个系统内存的位置和最小值,以及根文件系统位置。 -因此,最小的标签列表如下所示: - - +-----------+ -基地址 -> | ATAG_CORE | | - +-----------+ | - | ATAG_MEM | | 地址增长方向 - +-----------+ | - | ATAG_NONE | | - +-----------+ v - -标签列表应该保存在系统的 RAM 中。 - -标签列表必须置于内核自解压和 initrd'bootp' 程序都不会覆盖的内存区。 -建议放在 RAM 的头 16KiB 中。 - -4b、设置设备树 -------------------------- - -bootloader 必须以 64bit 地址对齐的形式加载一个设备树映像(dtb)到系统 -RAM 中,并用启动数据初始化它。dtb 格式在文档 -Documentation/devicetree/booting-without-of.txt 中。内核将会在 -dtb 物理地址处查找 dtb 魔数值(0xd00dfeed),以确定 dtb 是否已经代替 -标签列表被传递进来。 - -bootloader 必须传递一个系统内存的位置和最小值,以及根文件系统位置。 -dtb 必须置于内核自解压不会覆盖的内存区。建议将其放置于 RAM 的头 16KiB -中。但是不可将其放置于“0”物理地址处,因为内核认为:r2 中为 0,意味着 -没有标签列表和 dtb 传递过来。 - -5、调用内核映像 ---------------------------- - -现有的引导加载程序: 强制 -新开发的引导加载程序: 强制 - -调用内核映像 zImage 有两个选择。如果 zImge 保存在 flash 中,且是为了 -在 flash 中直接运行而被正确链接的。这样引导加载程序就可以在 flash 中 -直接调用 zImage。 - -zImage 也可以被放在系统 RAM(任意位置)中被调用。注意:内核使用映像 -基地址的前 16KB RAM 空间来保存页表。建议将映像置于 RAM 的 32KB 处。 - -对于以上任意一种情况,都必须符合以下启动状态: - -- 停止所有 DMA 设备,这样内存数据就不会因为虚假网络包或磁盘数据而被破坏。 - 这可能可以节省你许多的调试时间。 - -- CPU 寄存器配置 - r0 = 0, - r1 = (在上面 3 中获取的)机器类型码。 - r2 = 标签列表在系统 RAM 中的物理地址,或 - 设备树块(dtb)在系统 RAM 中的物理地址 - -- CPU 模式 - 所有形式的中断必须被禁止 (IRQs 和 FIQs) - CPU 必须处于 SVC 模式。(对于 Angel 调试有特例存在) - -- 缓存,MMUs - MMU 必须关闭。 - 指令缓存开启或关闭都可以。 - 数据缓存必须关闭。 - -- 引导加载程序应该通过直接跳转到内核映像的第一条指令来调用内核映像。 - - 对于支持 ARM 指令集的 CPU,跳入内核入口时必须处在 ARM 状态,即使 - 对于 Thumb-2 内核也是如此。 - - 对于仅支持 Thumb 指令集的 CPU,比如 Cortex-M 系列的 CPU,跳入 - 内核入口时必须处于 Thumb 状态。 diff --git a/trunk/Documentation/zh_CN/basic_profiling.txt b/trunk/Documentation/zh_CN/basic_profiling.txt deleted file mode 100644 index 1e6bf0bdf8f5..000000000000 --- a/trunk/Documentation/zh_CN/basic_profiling.txt +++ /dev/null @@ -1,71 +0,0 @@ -Chinese translated version of Documentation/basic_profiling - -If you have any comment or update to the content, please post to LKML directly. -However, if you have problem communicating in English you can also ask the -Chinese maintainer for help. Contact the Chinese maintainer, if this -translation is outdated or there is problem with translation. - -Chinese maintainer: Liang Xie ---------------------------------------------------------------------- -Documentation/basic_profiling的中文翻译 - -如果想评论或更新本文的内容,请直接发信到LKML。如果你使用英文交流有困难的话,也可 -以向中文版维护者求助。如果本翻译更新不及时或者翻译存在问题,请联系中文版维护者。 - -中文版维护者: 谢良 Liang Xie -中文版翻译者: 谢良 Liang Xie -中文版校译者: -以下为正文 ---------------------------------------------------------------------- - -下面这些说明指令都是非常基础的,如果你想进一步了解请阅读相关专业文档:) -请不要再在本文档增加新的内容,但可以修复文档中的错误:)(mbligh@aracnet.com) -感谢John Levon,Dave Hansen等在撰写时的帮助 - - 用于表示要测量的目标 -请先确保您已经有正确的System.map / vmlinux配置! - -对于linux系统来说,配置vmlinuz最容易的方法可能就是使用“make install”,然后修改 -/sbin/installkernel将vmlinux拷贝到/boot目录,而System.map通常是默认安装好的 - -Readprofile ------------ -2.6系列内核需要版本相对较新的readprofile,比如util-linux 2.12a中包含的,可以从: - -http://www.kernel.org/pub/linux/utils/util-linux/ 下载 - -大部分linux发行版已经包含了. - -启用readprofile需要在kernel启动命令行增加”profile=2“ - -clear readprofile -r - -dump output readprofile -m /boot/System.map > captured_profile - -Oprofile --------- - -从http://oprofile.sourceforge.net/获取源代码(请参考Changes以获取匹配的版本) -在kernel启动命令行增加“idle=poll” - -配置CONFIG_PROFILING=y和CONFIG_OPROFILE=y然后重启进入新kernel - -./configure --with-kernel-support -make install - -想得到好的测量结果,请确保启用了本地APIC特性。如果opreport显示有0Hz CPU, -说明APIC特性没有开启。另外注意idle=poll选项可能有损性能。 - -One time setup: - opcontrol --setup --vmlinux=/boot/vmlinux - -clear opcontrol --reset -start opcontrol --start - -stop opcontrol --stop -dump output opreport > output_file - -如果只看kernel相关的报告结果,请运行命令 opreport -l /boot/vmlinux > output_file - -通过reset选项可以清理过期统计数据,相当于重启的效果。 - diff --git a/trunk/Documentation/zh_CN/filesystems/sysfs.txt b/trunk/Documentation/zh_CN/filesystems/sysfs.txt deleted file mode 100644 index e230eaa33122..000000000000 --- a/trunk/Documentation/zh_CN/filesystems/sysfs.txt +++ /dev/null @@ -1,372 +0,0 @@ -Chinese translated version of Documentation/filesystems/sysfs.txt - -If you have any comment or update to the content, please contact the -original document maintainer directly. However, if you have a problem -communicating in English you can also ask the Chinese maintainer for -help. Contact the Chinese maintainer if this translation is outdated -or if there is a problem with the translation. - -Maintainer: Patrick Mochel - Mike Murphy -Chinese maintainer: Fu Wei ---------------------------------------------------------------------- -Documentation/filesystems/sysfs.txt 的中文翻译 - -如果想评论或更新本文的内容,请直接联系原文档的维护者。如果你使用英文 -交流有困难的话,也可以向中文版维护者求助。如果本翻译更新不及时或者翻 -译存在问题,请联系中文版维护者。 -英文版维护者: Patrick Mochel - Mike Murphy -中文版维护者: 傅炜 Fu Wei -中文版翻译者: 傅炜 Fu Wei -中文版校译者: 傅炜 Fu Wei - - -以下为正文 ---------------------------------------------------------------------- -sysfs - 用于导出内核对象(kobject)的文件系统 - -Patrick Mochel -Mike Murphy - -修订: 16 August 2011 -原始版本: 10 January 2003 - - -sysfs 简介: -~~~~~~~~~~ - -sysfs 是一个最初基于 ramfs 且位于内存的文件系统。它提供导出内核 -数据结构及其属性,以及它们之间的关联到用户空间的方法。 - -sysfs 始终与 kobject 的底层结构紧密相关。请阅读 -Documentation/kobject.txt 文档以获得更多关于 kobject 接口的 -信息。 - - -使用 sysfs -~~~~~~~~~~~ - -只要内核配置中定义了 CONFIG_SYSFS ,sysfs 总是被编译进内核。你可 -通过以下命令挂载它: - - mount -t sysfs sysfs /sys - - -创建目录 -~~~~~~~~ - -任何 kobject 在系统中注册,就会有一个目录在 sysfs 中被创建。这个 -目录是作为该 kobject 的父对象所在目录的子目录创建的,以准确地传递 -内核的对象层次到用户空间。sysfs 中的顶层目录代表着内核对象层次的 -共同祖先;例如:某些对象属于某个子系统。 - -Sysfs 在与其目录关联的 sysfs_dirent 对象中内部保存一个指向实现 -目录的 kobject 的指针。以前,这个 kobject 指针被 sysfs 直接用于 -kobject 文件打开和关闭的引用计数。而现在的 sysfs 实现中,kobject -引用计数只能通过 sysfs_schedule_callback() 函数直接修改。 - - -属性 -~~~~ - -kobject 的属性可在文件系统中以普通文件的形式导出。Sysfs 为属性定义 -了面向文件 I/O 操作的方法,以提供对内核属性的读写。 - - -属性应为 ASCII 码文本文件。以一个文件只存储一个属性值为宜。但一个 -文件只包含一个属性值可能影响效率,所以一个包含相同数据类型的属性值 -数组也被广泛地接受。 - -混合类型、表达多行数据以及一些怪异的数据格式会遭到强烈反对。这样做是 -很丢脸的,而且其代码会在未通知作者的情况下被重写。 - - -一个简单的属性结构定义如下: - -struct attribute { - char * name; - struct module *owner; - umode_t mode; -}; - - -int sysfs_create_file(struct kobject * kobj, const struct attribute * attr); -void sysfs_remove_file(struct kobject * kobj, const struct attribute * attr); - - -一个单独的属性结构并不包含读写其属性值的方法。子系统最好为增删特定 -对象类型的属性定义自己的属性结构体和封装函数。 - -例如:驱动程序模型定义的 device_attribute 结构体如下: - -struct device_attribute { - struct attribute attr; - ssize_t (*show)(struct device *dev, struct device_attribute *attr, - char *buf); - ssize_t (*store)(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count); -}; - -int device_create_file(struct device *, const struct device_attribute *); -void device_remove_file(struct device *, const struct device_attribute *); - -为了定义设备属性,同时定义了一下辅助宏: - -#define DEVICE_ATTR(_name, _mode, _show, _store) \ -struct device_attribute dev_attr_##_name = __ATTR(_name, _mode, _show, _store) - -例如:声明 - -static DEVICE_ATTR(foo, S_IWUSR | S_IRUGO, show_foo, store_foo); - -等同于如下代码: - -static struct device_attribute dev_attr_foo = { - .attr = { - .name = "foo", - .mode = S_IWUSR | S_IRUGO, - .show = show_foo, - .store = store_foo, - }, -}; - - -子系统特有的回调函数 -~~~~~~~~~~~~~~~~~~~ - -当一个子系统定义一个新的属性类型时,必须实现一系列的 sysfs 操作, -以帮助读写调用实现属性所有者的显示和储存方法。 - -struct sysfs_ops { - ssize_t (*show)(struct kobject *, struct attribute *, char *); - ssize_t (*store)(struct kobject *, struct attribute *, const char *, size_t); -}; - -[子系统应已经定义了一个 struct kobj_type 结构体作为这个类型的 -描述符,并在此保存 sysfs_ops 的指针。更多的信息参见 kobject 的 -文档] - -sysfs 会为这个类型调用适当的方法。当一个文件被读写时,这个方法会 -将一般的kobject 和 attribute 结构体指针转换为适当的指针类型后 -调用相关联的函数。 - - -示例: - -#define to_dev(obj) container_of(obj, struct device, kobj) -#define to_dev_attr(_attr) container_of(_attr, struct device_attribute, attr) - -static ssize_t dev_attr_show(struct kobject *kobj, struct attribute *attr, - char *buf) -{ - struct device_attribute *dev_attr = to_dev_attr(attr); - struct device *dev = to_dev(kobj); - ssize_t ret = -EIO; - - if (dev_attr->show) - ret = dev_attr->show(dev, dev_attr, buf); - if (ret >= (ssize_t)PAGE_SIZE) { - print_symbol("dev_attr_show: %s returned bad count\n", - (unsigned long)dev_attr->show); - } - return ret; -} - - - -读写属性数据 -~~~~~~~~~~~~ - -在声明属性时,必须指定 show() 或 store() 方法,以实现属性的 -读或写。这些方法的类型应该和以下的设备属性定义一样简单。 - -ssize_t (*show)(struct device *dev, struct device_attribute *attr, char *buf); -ssize_t (*store)(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count); - -也就是说,他们应只以一个处理对象、一个属性和一个缓冲指针作为参数。 - -sysfs 会分配一个大小为 (PAGE_SIZE) 的缓冲区并传递给这个方法。 -Sysfs 将会为每次读写操作调用一次这个方法。这使得这些方法在执行时 -会出现以下的行为: - -- 在读方面(read(2)),show() 方法应该填充整个缓冲区。回想属性 - 应只导出了一个属性值或是一个同类型属性值的数组,所以这个代价将 - 不会不太高。 - - 这使得用户空间可以局部地读和任意的向前搜索整个文件。如果用户空间 - 向后搜索到零或使用‘0’偏移执行一个pread(2)操作,show()方法将 - 再次被调用,以重新填充缓存。 - -- 在写方面(write(2)),sysfs 希望在第一次写操作时得到整个缓冲区。 - 之后 Sysfs 传递整个缓冲区给 store() 方法。 - - 当要写 sysfs 文件时,用户空间进程应首先读取整个文件,修该想要 - 改变的值,然后回写整个缓冲区。 - - 在读写属性值时,属性方法的执行应操作相同的缓冲区。 - -注记: - -- 写操作导致的 show() 方法重载,会忽略当前文件位置。 - -- 缓冲区应总是 PAGE_SIZE 大小。对于i386,这个值为4096。 - -- show() 方法应该返回写入缓冲区的字节数,也就是 snprintf()的 - 返回值。 - -- show() 应始终使用 snprintf()。 - -- store() 应返回缓冲区的已用字节数。如果整个缓存都已填满,只需返回 - count 参数。 - -- show() 或 store() 可以返回错误值。当得到一个非法值,必须返回一个 - 错误值。 - -- 一个传递给方法的对象将会通过 sysfs 调用对象内嵌的引用计数固定在 - 内存中。尽管如此,对象代表的物理实体(如设备)可能已不存在。如有必要, - 应该实现一个检测机制。 - -一个简单的(未经实验证实的)设备属性实现如下: - -static ssize_t show_name(struct device *dev, struct device_attribute *attr, - char *buf) -{ - return scnprintf(buf, PAGE_SIZE, "%s\n", dev->name); -} - -static ssize_t store_name(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - snprintf(dev->name, sizeof(dev->name), "%.*s", - (int)min(count, sizeof(dev->name) - 1), buf); - return count; -} - -static DEVICE_ATTR(name, S_IRUGO, show_name, store_name); - - -(注意:真正的实现不允许用户空间设置设备名。) - -顶层目录布局 -~~~~~~~~~~~~ - -sysfs 目录的安排显示了内核数据结构之间的关系。 - -顶层 sysfs 目录如下: - -block/ -bus/ -class/ -dev/ -devices/ -firmware/ -net/ -fs/ - -devices/ 包含了一个设备树的文件系统表示。他直接映射了内部的内核 -设备树,反映了设备的层次结构。 - -bus/ 包含了内核中各种总线类型的平面目录布局。每个总线目录包含两个 -子目录: - - devices/ - drivers/ - -devices/ 包含了系统中出现的每个设备的符号链接,他们指向 root/ 下的 -设备目录。 - -drivers/ 包含了每个已为特定总线上的设备而挂载的驱动程序的目录(这里 -假定驱动没有跨越多个总线类型)。 - -fs/ 包含了一个为文件系统设立的目录。现在每个想要导出属性的文件系统必须 -在 fs/ 下创建自己的层次结构(参见Documentation/filesystems/fuse.txt)。 - -dev/ 包含两个子目录: char/ 和 block/。在这两个子目录中,有以 -: 格式命名的符号链接。这些符号链接指向 sysfs 目录 -中相应的设备。/sys/dev 提供一个通过一个 stat(2) 操作结果,查找 -设备 sysfs 接口快捷的方法。 - -更多有关 driver-model 的特性信息可以在 Documentation/driver-model/ -中找到。 - - -TODO: 完成这一节。 - - -当前接口 -~~~~~~~~ - -以下的接口层普遍存在于当前的sysfs中: - -- 设备 (include/linux/device.h) ----------------------------------- -结构体: - -struct device_attribute { - struct attribute attr; - ssize_t (*show)(struct device *dev, struct device_attribute *attr, - char *buf); - ssize_t (*store)(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count); -}; - -声明: - -DEVICE_ATTR(_name, _mode, _show, _store); - -增/删属性: - -int device_create_file(struct device *dev, const struct device_attribute * attr); -void device_remove_file(struct device *dev, const struct device_attribute * attr); - - -- 总线驱动程序 (include/linux/device.h) --------------------------------------- -结构体: - -struct bus_attribute { - struct attribute attr; - ssize_t (*show)(struct bus_type *, char * buf); - ssize_t (*store)(struct bus_type *, const char * buf, size_t count); -}; - -声明: - -BUS_ATTR(_name, _mode, _show, _store) - -增/删属性: - -int bus_create_file(struct bus_type *, struct bus_attribute *); -void bus_remove_file(struct bus_type *, struct bus_attribute *); - - -- 设备驱动程序 (include/linux/device.h) ------------------------------------------ - -结构体: - -struct driver_attribute { - struct attribute attr; - ssize_t (*show)(struct device_driver *, char * buf); - ssize_t (*store)(struct device_driver *, const char * buf, - size_t count); -}; - -声明: - -DRIVER_ATTR(_name, _mode, _show, _store) - -增/删属性: - -int driver_create_file(struct device_driver *, const struct driver_attribute *); -void driver_remove_file(struct device_driver *, const struct driver_attribute *); - - -文档 -~~~~ - -sysfs 目录结构以及其中包含的属性定义了一个内核与用户空间之间的 ABI。 -对于任何 ABI,其自身的稳定和适当的文档是非常重要的。所有新的 sysfs -属性必须在 Documentation/ABI 中有文档。详见 Documentation/ABI/README。 diff --git a/trunk/Documentation/zh_CN/gpio.txt b/trunk/Documentation/zh_CN/gpio.txt deleted file mode 100644 index 4fa7b4e6f856..000000000000 --- a/trunk/Documentation/zh_CN/gpio.txt +++ /dev/null @@ -1,658 +0,0 @@ -Chinese translated version of Documentation/gpio.txt - -If you have any comment or update to the content, please contact the -original document maintainer directly. However, if you have a problem -communicating in English you can also ask the Chinese maintainer for -help. Contact the Chinese maintainer if this translation is outdated -or if there is a problem with the translation. - -Maintainer: Grant Likely - Linus Walleij -Chinese maintainer: Fu Wei ---------------------------------------------------------------------- -Documentation/gpio.txt 的中文翻译 - -如果想评论或更新本文的内容,请直接联系原文档的维护者。如果你使用英文 -交流有困难的话,也可以向中文版维护者求助。如果本翻译更新不及时或者翻 -译存在问题,请联系中文版维护者。 -英文版维护者: Grant Likely - Linus Walleij -中文版维护者: 傅炜 Fu Wei -中文版翻译者: 傅炜 Fu Wei -中文版校译者: 傅炜 Fu Wei - - -以下为正文 ---------------------------------------------------------------------- -GPIO 接口 - -本文档提供了一个在Linux下访问GPIO的公约概述。 - -这些函数以 gpio_* 作为前缀。其他的函数不允许使用这样的前缀或相关的 -__gpio_* 前缀。 - - -什么是GPIO? -========== -"通用输入/输出口"(GPIO)是一个灵活的由软件控制的数字信号。他们可 -由多种芯片提供,且对于从事嵌入式和定制硬件的 Linux 开发者来说是 -比较熟悉。每个GPIO 都代表一个连接到特定引脚或球栅阵列(BGA)封装中 -“球珠”的一个位。电路板原理图显示了 GPIO 与外部硬件的连接关系。 -驱动可以编写成通用代码,以使板级启动代码可传递引脚配置数据给驱动。 - -片上系统 (SOC) 处理器对 GPIO 有很大的依赖。在某些情况下,每个 -非专用引脚都可配置为 GPIO,且大多数芯片都最少有一些 GPIO。 -可编程逻辑器件(类似 FPGA) 可以方便地提供 GPIO。像电源管理和 -音频编解码器这样的多功能芯片经常留有一些这样的引脚来帮助那些引脚 -匮乏的 SOC。同时还有通过 I2C 或 SPI 串行总线连接的“GPIO扩展器” -芯片。大多数 PC 的南桥有一些拥有 GPIO 能力的引脚 (只有BIOS -固件才知道如何使用他们)。 - -GPIO 的实际功能因系统而异。通常用法有: - - - 输出值可写 (高电平=1,低电平=0)。一些芯片也有如何驱动这些值的选项, - 例如只允许输出一个值、支持“线与”及其他取值类似的模式(值得注意的是 - “开漏”信号) - - - 输入值可读(1、0)。一些芯片支持引脚在配置为“输出”时回读,这对于类似 - “线与”的情况(以支持双向信号)是非常有用的。GPIO 控制器可能有输入 - 去毛刺/消抖逻辑,这有时需要软件控制。 - - - 输入通常可作为 IRQ 信号,一般是沿触发,但有时是电平触发。这样的 IRQ - 可能配置为系统唤醒事件,以将系统从低功耗状态下唤醒。 - - - 通常一个 GPIO 根据不同产品电路板的需求,可以配置为输入或输出,也有仅 - 支持单向的。 - - - 大部分 GPIO 可以在持有自旋锁时访问,但是通常由串行总线扩展的 GPIO - 不允许持有自旋锁。但某些系统也支持这种类型。 - -对于给定的电路板,每个 GPIO 都用于某个特定的目的,如监控 MMC/SD 卡的 -插入/移除、检测卡的写保护状态、驱动 LED、配置收发器、模拟串行总线、 -复位硬件看门狗、感知开关状态等等。 - - -GPIO 公约 -========= -注意,这个叫做“公约”,因为这不是强制性的,不遵循这个公约是无伤大雅的, -因为此时可移植性并不重要。GPIO 常用于板级特定的电路逻辑,甚至可能 -随着电路板的版本而改变,且不可能在不同走线的电路板上使用。仅有在少数 -功能上才具有可移植性,其他功能是平台特定。这也是由于“胶合”的逻辑造成的。 - -此外,这不需要任何的执行框架,只是一个接口。某个平台可能通过一个简单地 -访问芯片寄存器的内联函数来实现它,其他平台可能通过委托一系列不同的GPIO -控制器的抽象函数来实现它。(有一些可选的代码能支持这种策略的实现,本文档 -后面会介绍,但作为 GPIO 接口的客户端驱动程序必须与它的实现无关。) - -也就是说,如果在他们的平台上支持这个公约,驱动应尽可能的使用它。平台 -必须在 Kconfig 中声明对 GENERIC_GPIO的支持 (布尔型 true),并提供 -一个 文件。那些调用标准 GPIO 函数的驱动应该在 Kconfig -入口中声明依赖GENERIC_GPIO。当驱动包含文件: - - #include - -则 GPIO 函数是可用,无论是“真实代码”还是经优化过的语句。如果你遵守 -这个公约,当你的代码完成后,对其他的开发者来说会更容易看懂和维护。 - -注意,这些操作包含所用平台的 I/O 屏障代码,驱动无须显式地调用他们。 - - -标识 GPIO ---------- -GPIO 是通过无符号整型来标识的,范围是 0 到 MAX_INT。保留“负”数 -用于其他目的,例如标识信号“在这个板子上不可用”或指示错误。未接触底层 -硬件的代码会忽略这些整数。 - -平台会定义这些整数的用法,且通常使用 #define 来定义 GPIO,这样 -板级特定的启动代码可以直接关联相应的原理图。相对来说,驱动应该仅使用 -启动代码传递过来的 GPIO 编号,使用 platform_data 保存板级特定 -引脚配置数据 (同时还有其他须要的板级特定数据),避免可能出现的问题。 - -例如一个平台使用编号 32-159 来标识 GPIO,而在另一个平台使用编号0-63 -标识一组 GPIO 控制器,64-79标识另一类 GPIO 控制器,且在一个含有 -FPGA 的特定板子上使用 80-95。编号不一定要连续,那些平台中,也可以 -使用编号2000-2063来标识一个 I2C 接口的 GPIO 扩展器中的 GPIO。 - -如果你要初始化一个带有无效 GPIO 编号的结构体,可以使用一些负编码 -(如"-EINVAL"),那将使其永远不会是有效。来测试这样一个结构体中的编号 -是否关联一个 GPIO,你可使用以下断言: - - int gpio_is_valid(int number); - -如果编号不存在,则请求和释放 GPIO 的函数将拒绝执行相关操作(见下文)。 -其他编号也可能被拒绝,比如一个编号可能存在,但暂时在给定的电路上不可用。 - -一个平台是否支持多个 GPIO 控制器为平台特定的实现问题,就像是否可以 -在 GPIO 编号空间中有“空洞”和是否可以在运行时添加新的控制器一样。 -这些问题会影响其他事情,包括相邻的 GPIO 编号是否存在等。 - -使用 GPIO ---------- -对于一个 GPIO,系统应该做的第一件事情就是通过 gpio_request() -函数分配它,见下文。 - -接下来是设置I/O方向,这通常是在板级启动代码中为所使用的 GPIO 设置 -platform_device 时完成。 - - /* 设置为输入或输出, 返回 0 或负的错误代码 */ - int gpio_direction_input(unsigned gpio); - int gpio_direction_output(unsigned gpio, int value); - -返回值为零代表成功,否则返回一个负的错误代码。这个返回值需要检查,因为 -get/set(获取/设置)函数调用没法返回错误,且有可能是配置错误。通常, -你应该在进程上下文中调用这些函数。然而,对于自旋锁安全的 GPIO,在板子 -启动的早期、进程启动前使用他们也是可以的。 - -对于作为输出的 GPIO,为其提供初始输出值,对于避免在系统启动期间出现 -信号毛刺是很有帮助的。 - -为了与传统的 GPIO 接口兼容, 在设置一个 GPIO 方向时,如果它还未被申请, -则隐含了申请那个 GPIO 的操作(见下文)。这种兼容性正在从可选的 gpiolib -框架中移除。 - -如果这个 GPIO 编码不存在,或者特定的 GPIO 不能用于那种模式,则方向 -设置可能失败。依赖启动固件来正确地设置方向通常是一个坏主意,因为它可能 -除了启动Linux,并没有做更多的验证工作。(同理, 板子的启动代码可能需要 -将这个复用的引脚设置为 GPIO,并正确地配置上拉/下拉电阻。) - - -访问自旋锁安全的 GPIO -------------------- -大多数 GPIO 控制器可以通过内存读/写指令来访问。这些指令不会休眠,可以 -安全地在硬(非线程)中断例程和类似的上下文中完成。 - -对于那些用 gpio_cansleep()测试总是返回失败的 GPIO(见下文),使用 -以下的函数访问: - - /* GPIO 输入:返回零或非零 */ - int gpio_get_value(unsigned gpio); - - /* GPIO 输出 */ - void gpio_set_value(unsigned gpio, int value); - -GPIO值是布尔值,零表示低电平,非零表示高电平。当读取一个输出引脚的值时, -返回值应该是引脚上的值。这个值不总是和输出值相符,因为存在开漏输出信号和 -输出延迟问题。 - -以上的 get/set 函数无错误返回值,因为之前 gpio_direction_*()应已检查过 -其是否为“无效GPIO”。此外,还需要注意的是并不是所有平台都可以从输出引脚 -中读取数据,对于不能读取的引脚应总返回零。另外,对那些在原子上下文中无法 -安全访问的 GPIO (译者注:因为访问可能导致休眠)使用这些函数是不合适的 -(见下文)。 - -在 GPIO 编号(还有输出、值)为常数的情况下,鼓励通过平台特定的实现来优化 -这两个函数来访问 GPIO 值。这种情况(读写一个硬件寄存器)下只需要几条指令 -是很正常的,且无须自旋锁。这种优化函数比起那些在子程序上花费许多指令的 -函数可以使得模拟接口(译者注:例如 GPIO 模拟 I2C、1-wire 或 SPI)的 -应用(在空间和时间上都)更具效率。 - - -访问可能休眠的 GPIO ------------------ -某些 GPIO 控制器必须通过基于总线(如 I2C 或 SPI)的消息访问。读或写这些 -GPIO 值的命令需要等待其信息排到队首才发送命令,再获得其反馈。期间需要 -休眠,这不能在 IRQ 例程(中断上下文)中执行。 - -支持此类 GPIO 的平台通过以下函数返回非零值来区分出这种 GPIO。(此函数需要 -一个之前通过 gpio_request 分配到的有效 GPIO 编号): - - int gpio_cansleep(unsigned gpio); - -为了访问这种 GPIO,内核定义了一套不同的函数: - - /* GPIO 输入:返回零或非零 ,可能会休眠 */ - int gpio_get_value_cansleep(unsigned gpio); - - /* GPIO 输出,可能会休眠 */ - void gpio_set_value_cansleep(unsigned gpio, int value); - - -访问这样的 GPIO 需要一个允许休眠的上下文,例如线程 IRQ 处理例程,并用以上的 -访问函数替换那些没有 cansleep()后缀的自旋锁安全访问函数。 - -除了这些访问函数可能休眠,且它们操作的 GPIO 不能在硬件 IRQ 处理例程中访问的 -事实,这些处理例程实际上和自旋锁安全的函数是一样的。 - -** 除此之外 ** 调用设置和配置此类 GPIO 的函数也必须在允许休眠的上下文中, -因为它们可能也需要访问 GPIO 控制器芯片: (这些设置函数通常在板级启动代码或者 -驱动探测/断开代码中,所以这是一个容易满足的约束条件。) - - gpio_direction_input() - gpio_direction_output() - gpio_request() - -## gpio_request_one() -## gpio_request_array() -## gpio_free_array() - - gpio_free() - gpio_set_debounce() - - - -声明和释放 GPIO ----------------------------- -为了有助于捕获系统配置错误,定义了两个函数。 - - /* 申请 GPIO, 返回 0 或负的错误代码. - * 非空标签可能有助于诊断. - */ - int gpio_request(unsigned gpio, const char *label); - - /* 释放之前声明的 GPIO */ - void gpio_free(unsigned gpio); - -将无效的 GPIO 编码传递给 gpio_request()会导致失败,申请一个已使用这个 -函数声明过的 GPIO 也会失败。gpio_request()的返回值必须检查。你应该在 -进程上下文中调用这些函数。然而,对于自旋锁安全的 GPIO,在板子启动的早期、 -进入进程之前是可以申请的。 - -这个函数完成两个基本的目标。一是标识那些实际上已作为 GPIO 使用的信号线, -这样便于更好地诊断;系统可能需要服务几百个可用的 GPIO,但是对于任何一个 -给定的电路板通常只有一些被使用。另一个目的是捕获冲突,查明错误:如两个或 -更多驱动错误地认为他们已经独占了某个信号线,或是错误地认为移除一个管理着 -某个已激活信号的驱动是安全的。也就是说,申请 GPIO 的作用类似一种锁机制。 - -某些平台可能也使用 GPIO 作为电源管理激活信号(例如通过关闭未使用芯片区和 -简单地关闭未使用时钟)。 - -对于 GPIO 使用 pinctrl 子系统已知的引脚,子系统应该被告知其使用情况; -一个 gpiolib 驱动的 .request()操作应调用 pinctrl_request_gpio(), -而 gpiolib 驱动的 .free()操作应调用 pinctrl_free_gpio()。pinctrl -子系统允许 pinctrl_request_gpio()在某个引脚或引脚组以复用形式“属于” -一个设备时都成功返回。 - -任何须将 GPIO 信号导向适当引脚的引脚复用硬件的编程应该发生在 GPIO -驱动的 .direction_input()或 .direction_output()函数中,以及 -任何输出 GPIO 值的设置之后。这样可使从引脚特殊功能到 GPIO 的转换 -不会在引脚产生毛刺波形。有时当用一个 GPIO 实现其信号驱动一个非 GPIO -硬件模块的解决方案时,就需要这种机制。 - -某些平台允许部分或所有 GPIO 信号使用不同的引脚。类似的,GPIO 或引脚的 -其他方面也需要配置,如上拉/下拉。平台软件应该在对这些 GPIO 调用 -gpio_request()前将这类细节配置好,例如使用 pinctrl 子系统的映射表, -使得 GPIO 的用户无须关注这些细节。 - -还有一个值得注意的是在释放 GPIO 前,你必须停止使用它。 - - -注意:申请一个 GPIO 并没有以任何方式配置它,只不过标识那个 GPIO 处于使用 -状态。必须有另外的代码来处理引脚配置(如控制 GPIO 使用的引脚、上拉/下拉)。 -考虑到大多数情况下声明 GPIO 之后就会立即配置它们,所以定义了以下三个辅助函数: - - /* 申请一个 GPIO 信号, 同时通过特定的'flags'初始化配置, - * 其他和 gpio_request()的参数和返回值相同 - * - */ - int gpio_request_one(unsigned gpio, unsigned long flags, const char *label); - - /* 在单个函数中申请多个 GPIO - */ - int gpio_request_array(struct gpio *array, size_t num); - - /* 在单个函数中释放多个 GPIO - */ - void gpio_free_array(struct gpio *array, size_t num); - -这里 'flags' 当前定义可指定以下属性: - - * GPIOF_DIR_IN - 配置方向为输入 - * GPIOF_DIR_OUT - 配置方向为输出 - - * GPIOF_INIT_LOW - 在作为输出时,初始值为低电平 - * GPIOF_INIT_HIGH - 在作为输出时,初始值为高电平 - * GPIOF_OPEN_DRAIN - gpio引脚为开漏信号 - * GPIOF_OPEN_SOURCE - gpio引脚为源极开路信号 - - * GPIOF_EXPORT_DIR_FIXED - 将 gpio 导出到 sysfs,并保持方向 - * GPIOF_EXPORT_DIR_CHANGEABLE - 同样是导出, 但允许改变方向 - -因为 GPIOF_INIT_* 仅有在配置为输出的时候才存在,所以有效的组合为: - - * GPIOF_IN - 配置为输入 - * GPIOF_OUT_INIT_LOW - 配置为输出,并初始化为低电平 - * GPIOF_OUT_INIT_HIGH - 配置为输出,并初始化为高电平 - -当设置 flag 为 GPIOF_OPEN_DRAIN 时,则假设引脚是开漏信号。这样的引脚 -将不会在输出模式下置1。这样的引脚需要连接上拉电阻。通过使能这个标志,gpio库 -将会在被要求输出模式下置1时将引脚变为输入状态来使引脚置高。引脚在输出模式下 -通过置0使其输出低电平。 - -当设置 flag 为 GPIOF_OPEN_SOURCE 时,则假设引脚为源极开路信号。这样的引脚 -将不会在输出模式下置0。这样的引脚需要连接下拉电阻。通过使能这个标志,gpio库 -将会在被要求输出模式下置0时将引脚变为输入状态来使引脚置低。引脚在输出模式下 -通过置1使其输出高电平。 - -将来这些标志可能扩展到支持更多的属性。 - -更进一步,为了更简单地声明/释放多个 GPIO,'struct gpio'被引进来封装所有 -这三个领域: - - struct gpio { - unsigned gpio; - unsigned long flags; - const char *label; - }; - -一个典型的用例: - - static struct gpio leds_gpios[] = { - { 32, GPIOF_OUT_INIT_HIGH, "Power LED" }, /* 默认开启 */ - { 33, GPIOF_OUT_INIT_LOW, "Green LED" }, /* 默认关闭 */ - { 34, GPIOF_OUT_INIT_LOW, "Red LED" }, /* 默认关闭 */ - { 35, GPIOF_OUT_INIT_LOW, "Blue LED" }, /* 默认关闭 */ - { ... }, - }; - - err = gpio_request_one(31, GPIOF_IN, "Reset Button"); - if (err) - ... - - err = gpio_request_array(leds_gpios, ARRAY_SIZE(leds_gpios)); - if (err) - ... - - gpio_free_array(leds_gpios, ARRAY_SIZE(leds_gpios)); - - -GPIO 映射到 IRQ --------------------- -GPIO 编号是无符号整数;IRQ 编号也是。这些构成了两个逻辑上不同的命名空间 -(GPIO 0 不一定使用 IRQ 0)。你可以通过以下函数在它们之间实现映射: - - /* 映射 GPIO 编号到 IRQ 编号 */ - int gpio_to_irq(unsigned gpio); - - /* 映射 IRQ 编号到 GPIO 编号 (尽量避免使用) */ - int irq_to_gpio(unsigned irq); - -它们的返回值为对应命名空间的相关编号,或是负的错误代码(如果无法映射)。 -(例如,某些 GPIO 无法做为 IRQ 使用。)以下的编号错误是未经检测的:使用一个 -未通过 gpio_direction_input()配置为输入的 GPIO 编号,或者使用一个 -并非来源于gpio_to_irq()的 IRQ 编号。 - -这两个映射函数可能会在信号编号的加减计算过程上花些时间。它们不可休眠。 - -gpio_to_irq()返回的非错误值可以传递给 request_irq()或者 free_irq()。 -它们通常通过板级特定的初始化代码存放到平台设备的 IRQ 资源中。注意:IRQ -触发选项是 IRQ 接口的一部分,如 IRQF_TRIGGER_FALLING,系统唤醒能力 -也是如此。 - -irq_to_gpio()返回的非错误值大多数通常可以被 gpio_get_value()所使用, -比如在 IRQ 是沿触发时初始化或更新驱动状态。注意某些平台不支持反映射,所以 -你应该尽量避免使用它。 - - -模拟开漏信号 ----------------------------- -有时在只有低电平信号作为实际驱动结果(译者注:多个输出连接于一点,逻辑电平 -结果为所有输出的逻辑与)的时候,共享的信号线需要使用“开漏”信号。(该术语 -适用于 CMOS 管;而 TTL 用“集电极开路”。)一个上拉电阻使信号为高电平。这 -有时被称为“线与”。实际上,从负逻辑(低电平为真)的角度来看,这是一个“线或”。 - -一个开漏信号的常见例子是共享的低电平使能 IRQ 信号线。此外,有时双向数据总线 -信号也使用漏极开路信号。 - -某些 GPIO 控制器直接支持开漏输出,还有许多不支持。当你需要开漏信号,但 -硬件又不直接支持的时候,一个常用的方法是用任何即可作输入也可作输出的 GPIO -引脚来模拟: - - LOW: gpio_direction_output(gpio, 0) ... 这代码驱动信号并覆盖 - 上拉配置。 - - HIGH: gpio_direction_input(gpio) ... 这代码关闭输出,所以上拉电阻 - (或其他的一些器件)控制了信号。 - -如果你将信号线“驱动”为高电平,但是 gpio_get_value(gpio)报告了一个 -低电平(在适当的上升时间后),你就可以知道是其他的一些组件将共享信号线拉低了。 -这不一定是错误的。一个常见的例子就是 I2C 时钟的延长:一个需要较慢时钟的 -从设备延迟 SCK 的上升沿,而 I2C 主设备相应地调整其信号传输速率。 - - -这些公约忽略了什么? -================ -这些公约忽略的最大一件事就是引脚复用,因为这属于高度芯片特定的属性且 -没有可移植性。某个平台可能不需要明确的复用信息;有的对于任意给定的引脚 -可能只有两个功能选项;有的可能每个引脚有八个功能选项;有的可能可以将 -几个引脚中的任何一个作为给定的 GPIO。(是的,这些例子都来自于当前运行 -Linux 的系统。) - -在某些系统中,与引脚复用相关的是配置和使能集成的上、下拉模式。并不是所有 -平台都支持这种模式,或者不会以相同的方式来支持这种模式;且任何给定的电路板 -可能使用外置的上拉(或下拉)电阻,这时芯片上的就不应该使用。(当一个电路需要 -5kOhm 的拉动电阻,芯片上的 100 kOhm 电阻就不能做到。)同样的,驱动能力 -(2 mA vs 20 mA)和电压(1.8V vs 3.3V)是平台特定问题,就像模型一样在 -可配置引脚和 GPIO 之间(没)有一一对应的关系。 - -还有其他一些系统特定的机制没有在这里指出,例如上述的输入去毛刺和线与输出 -选项。硬件可能支持批量读或写 GPIO,但是那一般是配置相关的:对于处于同一 -块区(bank)的GPIO。(GPIO 通常以 16 或 32 个组成一个区块,一个给定的 -片上系统一般有几个这样的区块。)某些系统可以通过输出 GPIO 触发 IRQ, -或者从并非以 GPIO 管理的引脚取值。这些机制的相关代码没有必要具有可移植性。 - -当前,动态定义 GPIO 并不是标准的,例如作为配置一个带有某些 GPIO 扩展器的 -附加电路板的副作用。 - -GPIO 实现者的框架 (可选) -===================== -前面提到了,有一个可选的实现框架,让平台使用相同的编程接口,更加简单地支持 -不同种类的 GPIO 控制器。这个框架称为"gpiolib"。 - -作为一个辅助调试功能,如果 debugfs 可用,就会有一个 /sys/kernel/debug/gpio -文件。通过这个框架,它可以列出所有注册的控制器,以及当前正在使用中的 GPIO -的状态。 - - -控制器驱动: gpio_chip -------------------- -在框架中每个 GPIO 控制器都包装为一个 "struct gpio_chip",他包含了 -该类型的每个控制器的常用信息: - - - 设置 GPIO 方向的方法 - - 用于访问 GPIO 值的方法 - - 告知调用其方法是否可能休眠的标志 - - 可选的 debugfs 信息导出方法 (显示类似上拉配置一样的额外状态) - - 诊断标签 - -也包含了来自 device.platform_data 的每个实例的数据:它第一个 GPIO 的 -编号和它可用的 GPIO 的数量。 - -实现 gpio_chip 的代码应支持多控制器实例,这可能使用驱动模型。那些代码要 -配置每个 gpio_chip,并发起gpiochip_add()。卸载一个 GPIO 控制器很少见, -但在必要的时候可以使用 gpiochip_remove()。 - -大部分 gpio_chip 是一个实例特定结构体的一部分,而并不将 GPIO 接口单独 -暴露出来,比如编址、电源管理等。类似编解码器这样的芯片会有复杂的非 GPIO -状态。 - -任何一个 debugfs 信息导出方法通常应该忽略还未申请作为 GPIO 的信号线。 -他们可以使用 gpiochip_is_requested()测试,当这个 GPIO 已经申请过了 -就返回相关的标签,否则返回 NULL。 - - -平台支持 -------- -为了支持这个框架,一个平台的 Kconfig 文件将会 "select"(选择) -ARCH_REQUIRE_GPIOLIB 或 ARCH_WANT_OPTIONAL_GPIOLIB,并让它的 - 包含 ,同时定义三个方法: -gpio_get_value()、gpio_set_value()和 gpio_cansleep()。 - -它也应提供一个 ARCH_NR_GPIOS 的定义值,这样可以更好地反映该平台 GPIO -的实际数量,节省静态表的空间。(这个定义值应该包含片上系统内建 GPIO 和 -GPIO 扩展器中的数据。) - -ARCH_REQUIRE_GPIOLIB 意味着 gpiolib 核心在这个构架中将总是编译进内核。 - -ARCH_WANT_OPTIONAL_GPIOLIB 意味着 gpiolib 核心默认关闭,且用户可以 -使能它,并将其编译进内核(可选)。 - -如果这些选项都没被选择,该平台就不通过 GPIO-lib 支持 GPIO,且代码不可以 -被用户使能。 - -以下这些方法的实现可以直接使用框架代码,并总是通过 gpio_chip 调度: - - #define gpio_get_value __gpio_get_value - #define gpio_set_value __gpio_set_value - #define gpio_cansleep __gpio_cansleep - -这些定义可以用更理想的实现方法替代,那就是使用经过逻辑优化的内联函数来访问 -基于特定片上系统的 GPIO。例如,若引用的 GPIO (寄存器位偏移)是常量“12”, -读取或设置它可能只需少则两或三个指令,且不会休眠。当这样的优化无法实现时, -那些函数必须使用框架提供的代码,那就至少要几十条指令才可以实现。对于用 GPIO -模拟的 I/O 接口, 如此精简指令是很有意义的。 - -对于片上系统,平台特定代码为片上 GPIO 每个区(bank)定义并注册 gpio_chip -实例。那些 GPIO 应该根据芯片厂商的文档进行编码/标签,并直接和电路板原理图 -对应。他们应该开始于零并终止于平台特定的限制。这些 GPIO(代码)通常从 -arch_initcall()或者更早的地方集成进平台初始化代码,使这些 GPIO 总是可用, -且他们通常可以作为 IRQ 使用。 - -板级支持 -------- -对于外部 GPIO 控制器(例如 I2C 或 SPI 扩展器、专用芯片、多功能器件、FPGA -或 CPLD),大多数常用板级特定代码都可以注册控制器设备,并保证他们的驱动知道 -gpiochip_add()所使用的 GPIO 编号。他们的起始编号通常跟在平台特定的 GPIO -编号之后。 - -例如板级启动代码应该创建结构体指明芯片公开的 GPIO 范围,并使用 platform_data -将其传递给每个 GPIO 扩展器芯片。然后芯片驱动中的 probe()例程可以将这个 -数据传递给 gpiochip_add()。 - -初始化顺序很重要。例如,如果一个设备依赖基于 I2C 的(扩展)GPIO,那么它的 -probe()例程就应该在那个 GPIO 有效以后才可以被调用。这意味着设备应该在 -GPIO 可以工作之后才可被注册。解决这类依赖的的一种方法是让这种 gpio_chip -控制器向板级特定代码提供 setup()和 teardown()回调函数。一旦所有必须的 -资源可用之后,这些板级特定的回调函数将会注册设备,并可以在这些 GPIO 控制器 -设备变成无效时移除它们。 - - -用户空间的 Sysfs 接口(可选) -======================== -使用“gpiolib”实现框架的平台可以选择配置一个 GPIO 的 sysfs 用户接口。 -这不同于 debugfs 接口,因为它提供的是对 GPIO方向和值的控制,而不只显示 -一个GPIO 的状态摘要。此外,它可以出现在没有调试支持的产品级系统中。 - -例如,通过适当的系统硬件文档,用户空间可以知道 GIOP #23 控制 Flash -存储器的写保护(用于保护其中 Bootloader 分区)。产品的系统升级可能需要 -临时解除这个保护:首先导入一个 GPIO,改变其输出状态,然后在重新使能写保护 -前升级代码。通常情况下,GPIO #23 是不会被触及的,并且内核也不需要知道他。 - -根据适当的硬件文档,某些系统的用户空间 GPIO 可以用于确定系统配置数据, -这些数据是标准内核不知道的。在某些任务中,简单的用户空间 GPIO 驱动可能是 -系统真正需要的。 - -注意:标准内核驱动中已经存在通用的“LED 和按键”GPIO 任务,分别是: -"leds-gpio" 和 "gpio_keys"。请使用这些来替代直接访问 GPIO,因为集成在 -内核框架中的这类驱动比你在用户空间的代码更好。 - - -Sysfs 中的路径 --------------- -在/sys/class/gpio 中有 3 类入口: - - - 用于在用户空间控制 GPIO 的控制接口; - - - GPIOs 本身;以及 - - - GPIO 控制器 ("gpio_chip" 实例)。 - -除了这些标准的文件,还包含“device”符号链接。 - -控制接口是只写的: - - /sys/class/gpio/ - - "export" ... 用户空间可以通过写其编号到这个文件,要求内核导出 - 一个 GPIO 的控制到用户空间。 - - 例如: 如果内核代码没有申请 GPIO #19,"echo 19 > export" - 将会为 GPIO #19 创建一个 "gpio19" 节点。 - - "unexport" ... 导出到用户空间的逆操作。 - - 例如: "echo 19 > unexport" 将会移除使用"export"文件导出的 - "gpio19" 节点。 - -GPIO 信号的路径类似 /sys/class/gpio/gpio42/ (对于 GPIO #42 来说), -并有如下的读/写属性: - - /sys/class/gpio/gpioN/ - - "direction" ... 读取得到 "in" 或 "out"。这个值通常运行写入。 - 写入"out" 时,其引脚的默认输出为低电平。为了确保无故障运行, - "low" 或 "high" 的电平值应该写入 GPIO 的配置,作为初始输出值。 - - 注意:如果内核不支持改变 GPIO 的方向,或者在导出时内核代码没有 - 明确允许用户空间可以重新配置 GPIO 方向,那么这个属性将不存在。 - - "value" ... 读取得到 0 (低电平) 或 1 (高电平)。如果 GPIO 配置为 - 输出,这个值允许写操作。任何非零值都以高电平看待。 - - 如果引脚可以配置为中断信号,且如果已经配置了产生中断的模式 - (见"edge"的描述),你可以对这个文件使用轮询操作(poll(2)), - 且轮询操作会在任何中断触发时返回。如果你使用轮询操作(poll(2)), - 请在 events 中设置 POLLPRI 和 POLLERR。如果你使用轮询操作 - (select(2)),请在 exceptfds 设置你期望的文件描述符。在 - 轮询操作(poll(2))返回之后,既可以通过 lseek(2)操作读取 - sysfs 文件的开始部分,也可以关闭这个文件并重新打开它来读取数据。 - - "edge" ... 读取得到“none”、“rising”、“falling”或者“both”。 - 将这些字符串写入这个文件可以选择沿触发模式,会使得轮询操作 - (select(2))在"value"文件中返回。 - - 这个文件仅有在这个引脚可以配置为可产生中断输入引脚时,才存在。 - - "active_low" ... 读取得到 0 (假) 或 1 (真)。写入任何非零值可以 - 翻转这个属性的(读写)值。已存在或之后通过"edge"属性设置了"rising" - 和 "falling" 沿触发模式的轮询操作(poll(2))将会遵循这个设置。 - -GPIO 控制器的路径类似 /sys/class/gpio/gpiochip42/ (对于从#42 GPIO -开始实现控制的控制器),并有着以下只读属性: - - /sys/class/gpio/gpiochipN/ - - "base" ... 与以上的 N 相同,代表此芯片管理的第一个 GPIO 的编号 - - "label" ... 用于诊断 (并不总是只有唯一值) - - "ngpio" ... 此控制器所管理的 GPIO 数量(而 GPIO 编号从 N 到 - N + ngpio - 1) - -大多数情况下,电路板的文档应当标明每个 GPIO 的使用目的。但是那些编号并不总是 -固定的,例如在扩展卡上的 GPIO会根据所使用的主板或所在堆叠架构中其他的板子而 -有所不同。在这种情况下,你可能需要使用 gpiochip 节点(尽可能地结合电路图)来 -确定给定信号所用的 GPIO 编号。 - - -从内核代码中导出 -------------- -内核代码可以明确地管理那些已通过 gpio_request()申请的 GPIO 的导出: - - /* 导出 GPIO 到用户空间 */ - int gpio_export(unsigned gpio, bool direction_may_change); - - /* gpio_export()的逆操作 */ - void gpio_unexport(); - - /* 创建一个 sysfs 连接到已导出的 GPIO 节点 */ - int gpio_export_link(struct device *dev, const char *name, - unsigned gpio) - - /* 改变 sysfs 中的一个 GPIO 节点的极性 */ - int gpio_sysfs_set_active_low(unsigned gpio, int value); - -在一个内核驱动申请一个 GPIO 之后,它可以通过 gpio_export()使其在 sysfs -接口中可见。该驱动可以控制信号方向是否可修改。这有助于防止用户空间代码无意间 -破坏重要的系统状态。 - -这个明确的导出有助于(通过使某些实验更容易来)调试,也可以提供一个始终存在的接口, -与文档配合作为板级支持包的一部分。 - -在 GPIO 被导出之后,gpio_export_link()允许在 sysfs 文件系统的任何地方 -创建一个到这个 GPIO sysfs 节点的符号链接。这样驱动就可以通过一个描述性的 -名字,在 sysfs 中他们所拥有的设备下提供一个(到这个 GPIO sysfs 节点的)接口。 - -驱动可以使用 gpio_sysfs_set_active_low() 来在用户空间隐藏电路板之间 -GPIO 线的极性差异。这个仅对 sysfs 接口起作用。极性的改变可以在 gpio_export() -前后进行,且之前使能的轮询操作(poll(2))支持(上升或下降沿)将会被重新配置来遵循 -这个设置。 diff --git a/trunk/Documentation/zh_CN/video4linux/omap3isp.txt b/trunk/Documentation/zh_CN/video4linux/omap3isp.txt deleted file mode 100644 index 67ffbf352ae0..000000000000 --- a/trunk/Documentation/zh_CN/video4linux/omap3isp.txt +++ /dev/null @@ -1,277 +0,0 @@ -Chinese translated version of Documentation/video4linux/omap3isp.txt - -If you have any comment or update to the content, please contact the -original document maintainer directly. However, if you have a problem -communicating in English you can also ask the Chinese maintainer for -help. Contact the Chinese maintainer if this translation is outdated -or if there is a problem with the translation. - -Maintainer: Laurent Pinchart - Sakari Ailus - David Cohen -Chinese maintainer: Fu Wei ---------------------------------------------------------------------- -Documentation/video4linux/omap3isp.txt 的中文翻译 - -如果想评论或更新本文的内容,请直接联系原文档的维护者。如果你使用英文 -交流有困难的话,也可以向中文版维护者求助。如果本翻译更新不及时或者翻 -译存在问题,请联系中文版维护者。 -英文版维护者: Laurent Pinchart - Sakari Ailus - David Cohen -中文版维护者: 傅炜 Fu Wei -中文版翻译者: 傅炜 Fu Wei -中文版校译者: 傅炜 Fu Wei - - -以下为正文 ---------------------------------------------------------------------- -OMAP 3 图像信号处理器 (ISP) 驱动 - -Copyright (C) 2010 Nokia Corporation -Copyright (C) 2009 Texas Instruments, Inc. - -联系人: Laurent Pinchart - Sakari Ailus - David Cohen - - -介绍 -=== - -本文档介绍了由 drivers/media/video/omap3isp 加载的德州仪器 -(TI)OMAP 3 图像信号处理器 (ISP) 驱动。原始驱动由德州仪器(TI) -编写,但此后由诺基亚重写了两次。 - -驱动已在以下 OMAP 3 系列的芯片中成功使用: - - 3430 - 3530 - 3630 - -驱动实现了 V4L2、媒体控制器和 v4l2_subdev 接口。支持内核中使用 -v4l2_subdev 接口的传感器、镜头和闪光灯驱动。 - - -拆分为子设备 -========== - -OMAP 3 ISP 被拆分为 V4L2 子设备,ISP中的每个模块都由一个子设备 -来表示。每个子设备向用户空间提供一个 V4L2 子设备接口。 - - OMAP3 ISP CCP2 - OMAP3 ISP CSI2a - OMAP3 ISP CCDC - OMAP3 ISP preview - OMAP3 ISP resizer - OMAP3 ISP AEWB - OMAP3 ISP AF - OMAP3 ISP histogram - -ISP 中每个可能的连接都通过一个链接嵌入到媒体控制器接口中。详见例程 [2]。 - - -控制 OMAP 3 ISP -============== - -通常,对 OMAP 3 ISP 的配置会在下一帧起始时生效。在传感器垂直消隐期间, -模块变为空闲时完成配置。在内存到内存的操作中,视频管道一次处理一帧。 -应用配置应在帧间完成。 - -ISP 中的所有模块,除 CSI-2 和 (可能存在的)CCP2 接收器外,都必须 -接收完整的帧数据。因此,传感器必须保证从不发送部分帧数据给ISP。 - -Autoidle(自动空闲)功能至少在 3430 的 ISP 模块中确实存在一些问题。 -当 omap3isp 模块参数 autoidle 非零时,autoidle(自动空闲)功能 -仅在 3630 中启用了。 - - -事件机制 -====== - -OMAP 3 ISP 驱动在 CCDC 和统计(AEWB、AF 和 直方图)子设备中支持 -V4L2 事件机制接口。 - -CCDC 子设备通过 HS_VS 中断,处理 V4L2_EVENT_FRAME_SYNC 类型 -事件,用于告知帧起始。早期版本的驱动则使用 V4L2_EVENT_OMAP3ISP_HS_VS。 -当在 CCDC 模块中接收到起始帧的第一行时,会准确地触发事件。这个事件 -可以在 CCDC 子设备中“订阅”。 - -(当使用并行接口时,必须注意正确地配置 VS 信号极性。而当使用串行接收时 -这个会自动校正。) - -每个统计子设备都可以产生事件。每当一个统计缓冲区可由用户空间应用程序 -通过 VIDIOC_OMAP3ISP_STAT_REQ IOCTL 操作获取时,就会产生一个 -事件。当前存在以下事件: - - V4L2_EVENT_OMAP3ISP_AEWB - V4L2_EVENT_OMAP3ISP_AF - V4L2_EVENT_OMAP3ISP_HIST - -这些 ioctl 的事件数据类型为 struct omap3isp_stat_event_status -结构体。如果出现计算错误的统计,也同样会产生一个事件,但没有相关的统计 -数据缓冲区。这种情况下 omap3isp_stat_event_status.buf_err 会被 -设置为非零值。 - - -私有 IOCTL -========== - -OMAP 3 ISP 驱动支持标准的 V4L2 IOCTL 以及可能存在且实用的控制。但 -ISP 提供的许多功能都不在标准 IOCTL 之列,例如 gamma(伽马)表和统计 -数据采集配置等。 - -通常,会有一个私有 ioctl 用于配置每个包含硬件依赖功能的模块。 - -支持以下私有 IOCTL: - - VIDIOC_OMAP3ISP_CCDC_CFG - VIDIOC_OMAP3ISP_PRV_CFG - VIDIOC_OMAP3ISP_AEWB_CFG - VIDIOC_OMAP3ISP_HIST_CFG - VIDIOC_OMAP3ISP_AF_CFG - VIDIOC_OMAP3ISP_STAT_REQ - VIDIOC_OMAP3ISP_STAT_EN - -在 include/linux/omap3isp.h 中描述了这些 ioctl 使用的参数结构体。 -与特定 ISP 模块相关的 ISP 自身的详细功能在技术参考手册 (TRMs)中有 -描述,详见文档结尾。 - -虽然在不使用任何私有 IOCTL 的情况下使用 ISP 驱动是可能的,但这样无法 -获得最佳的图像质量。AEWB、AF 和 直方图(译者注:一般用于自动曝光和增益 -控制,以及图像均衡等)模块无法在未使用适当的私有 IOCTL 配置的情况下使用。 - - -CCDC 和 preview(预览)模块 IOCTL -=============================== - -VIDIOC_OMAP3ISP_CCDC_CFG 和 VIDIOC_OMAP3ISP_PRV_CFG IOCTL -被分别用于配置、启用和禁用 CCDC 和 preview(预览)模块的功能。在它们 -所控制的模块中,两个 IOCTL 控制多种功能。VIDIOC_OMAP3ISP_CCDC_CFG IOCTL -接受一个指向 omap3isp_ccdc_update_config 结构体的指针作为它的参数。 -同样的,VIDIOC_OMAP3ISP_PRV_CFG 接受一个指向 omap3isp_prev_update_config -结构体的指针。以上两个结构体定义位于 [1]。 - -这些结构体中的 update 域标识是否针对指定的功能更新配置,而 flag 域 -则标识是启用还是禁用此功能。 - -update 和 flag 位接受以下掩码值。CCDC 和 preview(预览)模块的 -每个单独功能都与一个 flag 关联(禁用或启用;在结构体中 flag 域的 -一部分)和一个指向功能配置数据的指针。 - -对于 VIDIOC_OMAP3ISP_CCDC_CFG,下面列出了 update 和 flag 域 -中的有效值。 这些值可能会在同一个 IOCTL 调用中配置多个功能。 - - OMAP3ISP_CCDC_ALAW - OMAP3ISP_CCDC_LPF - OMAP3ISP_CCDC_BLCLAMP - OMAP3ISP_CCDC_BCOMP - OMAP3ISP_CCDC_FPC - OMAP3ISP_CCDC_CULL - OMAP3ISP_CCDC_CONFIG_LSC - OMAP3ISP_CCDC_TBL_LSC - -针对 VIDIOC_OMAP3ISP_PRV_CFG 的相应值如下: - - OMAP3ISP_PREV_LUMAENH - OMAP3ISP_PREV_INVALAW - OMAP3ISP_PREV_HRZ_MED - OMAP3ISP_PREV_CFA - OMAP3ISP_PREV_CHROMA_SUPP - OMAP3ISP_PREV_WB - OMAP3ISP_PREV_BLKADJ - OMAP3ISP_PREV_RGB2RGB - OMAP3ISP_PREV_COLOR_CONV - OMAP3ISP_PREV_YC_LIMIT - OMAP3ISP_PREV_DEFECT_COR - OMAP3ISP_PREV_GAMMABYPASS - OMAP3ISP_PREV_DRK_FRM_CAPTURE - OMAP3ISP_PREV_DRK_FRM_SUBTRACT - OMAP3ISP_PREV_LENS_SHADING - OMAP3ISP_PREV_NF - OMAP3ISP_PREV_GAMMA - -在启用某个功能的时候,相关的配置数据指针不可为 NULL。在禁用某个功能时, -配置数据指针会被忽略。 - - -统计模块 IOCTL -============= - -统计子设备相较于其他子设备提供了更多动态配置选项。在图像处理流水线处于 -工作状态时,它们可以被启用、禁用和重配。 - -统计模块总是从 CCDC 中获取输入的图像数据(由于直方图内存读取未实现)。 -统计数据可由用户通过统计子设备节点使用私有 IOCTL 获取。 - -AEWB、AF 和 直方图子设备提供的私有 IOCTL 极大程度上反应了 ISP 硬件 -提供的寄存器级接口。有些方面纯粹和驱动程序的实现相关,这些将在下面讨论。 - -VIDIOC_OMAP3ISP_STAT_EN ------------------------ - -这个私有 IOCTL 启用/禁用 一个统计模块。如果这个申请在视频流启动前完成, -它将在视频流水线开始工作时生效。如果视频流水线已经处于工作状态了,它将在 -CCDC 变为空闲时生效。 - -VIDIOC_OMAP3ISP_AEWB_CFG, VIDIOC_OMAP3ISP_HIST_CFG and VIDIOC_OMAP3ISP_AF_CFG ------------------------------------------------------------------------------ - -这些 IOCTL 用于配置模块。它们要求用户应用程序对硬件有深入的认识。对 -大多数域的解释可以在 OMAP 的 TRM 中找到。以下两个域对于以上所有的 -私有 IOCTL 配置都很常见,由于他们没有在 TRM 中提及,故需要对其有 -更好的认识。 - -omap3isp_[h3a_af/h3a_aewb/hist]_config.buf_size: - -模块在内部处理自身缓冲。对模块数据输出所必需的缓存大小依赖于已申请的配置。 -虽然驱动支持在视频流工作时重新配置,但对于所需缓存量大于模块启用时内部 -所分配数量的情况,则不支持重新配置。在这种情况下将返回 -EBUSY。为了避免 -此类状况,无论是禁用/重配/启用模块,还是第一次配置时申请必须的缓存大小, -都应在模块禁用的情况下进行。 - -内部缓冲分配的大小需综合考虑所申请配置的最小缓存量以及 buf_size 域中 -所设的值。如果 buf_size 域在[minimum(最小值), maximum(最大值)] -缓冲大小范围之外,则应该将其调整到其范围中。驱动则会选择最大值。正确的 -buf_size 值将回写到用户应用程序中。 - -omap3isp_[h3a_af/h3a_aewb/hist]_config.config_counter: - -由于配置并未在申请之后同步生效,驱动必须提供一个跟踪这类信息的方法, -以提供更准确的数据。在一个配置被申请之后,返回到用户空间应用程序的 -config_counter 是一个与其配置相关的唯一值。当用户应用程序接收到 -一个缓冲可用或一个新的缓冲申请事件时,这个 config_counter 用于 -一个缓冲数据和一个配置的匹配。 - -VIDIOC_OMAP3ISP_STAT_REQ ------------------------- - -将内部缓冲队列中最早的数据发送到用户空间,然后丢弃此缓冲区。 -omap3isp_stat_data.frame_number 域与视频缓冲的 field_count -域相匹配。 - - -技术参考手册 (TRMs) 和其他文档 -========================== - -OMAP 3430 TRM: - -参考于 2011-03-05. - -OMAP 35xx TRM: - 参考于 2011-03-05. - -OMAP 3630 TRM: - -参考于 2011-03-05. - -DM 3730 TRM: - 参考于 2011-03-06. - - -参考资料 -======= - -[1] include/linux/omap3isp.h - -[2] http://git.ideasonboard.org/?p=media-ctl.git;a=summary diff --git a/trunk/Documentation/zh_CN/video4linux/v4l2-framework.txt b/trunk/Documentation/zh_CN/video4linux/v4l2-framework.txt deleted file mode 100644 index 3e74f13af426..000000000000 --- a/trunk/Documentation/zh_CN/video4linux/v4l2-framework.txt +++ /dev/null @@ -1,983 +0,0 @@ -Chinese translated version of Documentation/video4linux/v4l2-framework.txt - -If you have any comment or update to the content, please contact the -original document maintainer directly. However, if you have a problem -communicating in English you can also ask the Chinese maintainer for -help. Contact the Chinese maintainer if this translation is outdated -or if there is a problem with the translation. - -Maintainer: Mauro Carvalho Chehab -Chinese maintainer: Fu Wei ---------------------------------------------------------------------- -Documentation/video4linux/v4l2-framework.txt 的中文翻译 - -如果想评论或更新本文的内容,请直接联系原文档的维护者。如果你使用英文 -交流有困难的话,也可以向中文版维护者求助。如果本翻译更新不及时或者翻 -译存在问题,请联系中文版维护者。 -英文版维护者: Mauro Carvalho Chehab -中文版维护者: 傅炜 Fu Wei -中文版翻译者: 傅炜 Fu Wei -中文版校译者: 傅炜 Fu Wei - - -以下为正文 ---------------------------------------------------------------------- -V4L2 驱动框架概览 -============== - -本文档描述 V4L2 框架所提供的各种结构和它们之间的关系。 - - -介绍 ----- - -大部分现代 V4L2 设备由多个 IC 组成,在 /dev 下导出多个设备节点, -并同时创建非 V4L2 设备(如 DVB、ALSA、FB、I2C 和红外输入设备)。 -由于这种硬件的复杂性,V4L2 驱动也变得非常复杂。 - -尤其是 V4L2 必须支持 IC 实现音视频的多路复用和编解码,这就更增加了其 -复杂性。通常这些 IC 通过一个或多个 I2C 总线连接到主桥驱动器,但也可 -使用其他总线。这些设备称为“子设备”。 - -长期以来,这个框架仅限于通过 video_device 结构体创建 V4L 设备节点, -并使用 video_buf 处理视频缓冲(注:本文不讨论 video_buf 框架)。 - -这意味着所有驱动必须自己设置设备实例并连接到子设备。其中一部分要正确地 -完成是比较复杂的,使得许多驱动都没有正确地实现。 - -由于框架的缺失,有很多通用代码都不可重复利用。 - -因此,这个框架构建所有驱动都需要的基本结构块,而统一的框架将使通用代码 -创建成实用函数并在所有驱动中共享变得更加容易。 - - -驱动结构 -------- - -所有 V4L2 驱动都有如下结构: - -1) 每个设备实例的结构体--包含其设备状态。 - -2) 初始化和控制子设备的方法(如果有)。 - -3) 创建 V4L2 设备节点 (/dev/videoX、/dev/vbiX 和 /dev/radioX) - 并跟踪设备节点的特定数据。 - -4) 特定文件句柄结构体--包含每个文件句柄的数据。 - -5) 视频缓冲处理。 - -以下是它们的初略关系图: - - device instances(设备实例) - | - +-sub-device instances(子设备实例) - | - \-V4L2 device nodes(V4L2 设备节点) - | - \-filehandle instances(文件句柄实例) - - -框架结构 -------- - -该框架非常类似驱动结构:它有一个 v4l2_device 结构用于保存设备 -实例的数据;一个 v4l2_subdev 结构体代表子设备实例;video_device -结构体保存 V4L2 设备节点的数据;将来 v4l2_fh 结构体将跟踪文件句柄 -实例(暂未尚未实现)。 - -V4L2 框架也可与媒体框架整合(可选的)。如果驱动设置了 v4l2_device -结构体的 mdev 域,子设备和视频节点的入口将自动出现在媒体框架中。 - - -v4l2_device 结构体 ----------------- - -每个设备实例都通过 v4l2_device (v4l2-device.h)结构体来表示。 -简单设备可以仅分配这个结构体,但在大多数情况下,都会将这个结构体 -嵌入到一个更大的结构体中。 - -你必须注册这个设备实例: - - v4l2_device_register(struct device *dev, struct v4l2_device *v4l2_dev); - -注册操作将会初始化 v4l2_device 结构体。如果 dev->driver_data 域 -为 NULL,就将其指向 v4l2_dev。 - -需要与媒体框架整合的驱动必须手动设置 dev->driver_data,指向包含 -v4l2_device 结构体实例的驱动特定设备结构体。这可以在注册 V4L2 设备 -实例前通过 dev_set_drvdata() 函数完成。同时必须设置 v4l2_device -结构体的 mdev 域,指向适当的初始化并注册过的 media_device 实例。 - -如果 v4l2_dev->name 为空,则它将被设置为从 dev 中衍生出的值(为了 -更加精确,形式为驱动名后跟 bus_id)。如果你在调用 v4l2_device_register -前已经设置好了,则不会被修改。如果 dev 为 NULL,则你*必须*在调用 -v4l2_device_register 前设置 v4l2_dev->name。 - -你可以基于驱动名和驱动的全局 atomic_t 类型的实例编号,通过 -v4l2_device_set_name() 设置 name。这样会生成类似 ivtv0、ivtv1 等 -名字。若驱动名以数字结尾,则会在编号和驱动名间插入一个破折号,如: -cx18-0、cx18-1 等。此函数返回实例编号。 - -第一个 “dev” 参数通常是一个指向 pci_dev、usb_interface 或 -platform_device 的指针。很少使其为 NULL,除非是一个ISA设备或者 -当一个设备创建了多个 PCI 设备,使得 v4l2_dev 无法与一个特定的父设备 -关联。 - -你也可以提供一个 notify() 回调,使子设备可以调用它实现事件通知。 -但这个设置与子设备相关。子设备支持的任何通知必须在 -include/media/.h 中定义一个消息头。 - -注销 v4l2_device 使用如下函数: - - v4l2_device_unregister(struct v4l2_device *v4l2_dev); - -如果 dev->driver_data 域指向 v4l2_dev,将会被重置为 NULL。注销同时 -会自动从设备中注销所有子设备。 - -如果你有一个热插拔设备(如USB设备),则当断开发生时,父设备将无效。 -由于 v4l2_device 有一个指向父设备的指针必须被清除,同时标志父设备 -已消失,所以必须调用以下函数: - - v4l2_device_disconnect(struct v4l2_device *v4l2_dev); - -这个函数并*不*注销子设备,因此你依然要调用 v4l2_device_unregister() -函数。如果你的驱动器并非热插拔的,就没有必要调用 v4l2_device_disconnect()。 - -有时你需要遍历所有被特定驱动注册的设备。这通常发生在多个设备驱动使用 -同一个硬件的情况下。如:ivtvfb 驱动是一个使用 ivtv 硬件的帧缓冲驱动, -同时 alsa 驱动也使用此硬件。 - -你可以使用如下例程遍历所有注册的设备: - -static int callback(struct device *dev, void *p) -{ - struct v4l2_device *v4l2_dev = dev_get_drvdata(dev); - - /* 测试这个设备是否已经初始化 */ - if (v4l2_dev == NULL) - return 0; - ... - return 0; -} - -int iterate(void *p) -{ - struct device_driver *drv; - int err; - - /* 在PCI 总线上查找ivtv驱动。 - pci_bus_type是全局的. 对于USB总线使用usb_bus_type。 */ - drv = driver_find("ivtv", &pci_bus_type); - /* 遍历所有的ivtv设备实例 */ - err = driver_for_each_device(drv, NULL, p, callback); - put_driver(drv); - return err; -} - -有时你需要一个设备实例的运行计数。这个通常用于映射一个设备实例到一个 -模块选择数组的索引。 - -推荐方法如下: - -static atomic_t drv_instance = ATOMIC_INIT(0); - -static int __devinit drv_probe(struct pci_dev *pdev, - const struct pci_device_id *pci_id) -{ - ... - state->instance = atomic_inc_return(&drv_instance) - 1; -} - -如果你有多个设备节点,对于热插拔设备,知道何时注销 v4l2_device 结构体 -就比较困难。为此 v4l2_device 有引用计数支持。当调用 video_register_device -时增加引用计数,而设备节点释放时减小引用计数。当引用计数为零,则 -v4l2_device 的release() 回调将被执行。你就可以在此时做最后的清理工作。 - -如果创建了其他设备节点(比如 ALSA),则你可以通过以下函数手动增减 -引用计数: - -void v4l2_device_get(struct v4l2_device *v4l2_dev); - -或: - -int v4l2_device_put(struct v4l2_device *v4l2_dev); - -由于引用技术初始化为 1 ,你也需要在 disconnect() 回调(对于 USB 设备)中 -调用 v4l2_device_put,或者 remove() 回调(例如对于 PCI 设备),否则 -引用计数将永远不会为 0 。 - -v4l2_subdev结构体 ------------------- - -许多驱动需要与子设备通信。这些设备可以完成各种任务,但通常他们负责 -音视频复用和编解码。如网络摄像头的子设备通常是传感器和摄像头控制器。 - -这些一般为 I2C 接口设备,但并不一定都是。为了给驱动提供调用子设备的 -统一接口,v4l2_subdev 结构体(v4l2-subdev.h)产生了。 - -每个子设备驱动都必须有一个 v4l2_subdev 结构体。这个结构体可以单独 -代表一个简单的子设备,也可以嵌入到一个更大的结构体中,与更多设备状态 -信息保存在一起。通常有一个下级设备结构体(比如:i2c_client)包含了 -内核创建的设备数据。建议使用 v4l2_set_subdevdata() 将这个结构体的 -指针保存在 v4l2_subdev 的私有数据域(dev_priv)中。这使得通过 v4l2_subdev -找到实际的低层总线特定设备数据变得容易。 - -你同时需要一个从低层结构体获取 v4l2_subdev 指针的方法。对于常用的 -i2c_client 结构体,i2c_set_clientdata() 函数可用于保存一个 v4l2_subdev -指针;对于其他总线你可能需要使用其他相关函数。 - -桥驱动中也应保存每个子设备的私有数据,比如一个指向特定桥的各设备私有 -数据的指针。为此 v4l2_subdev 结构体提供主机私有数据域(host_priv), -并可通过 v4l2_get_subdev_hostdata() 和 v4l2_set_subdev_hostdata() -访问。 - -从总线桥驱动的视角,驱动加载子设备模块并以某种方式获得 v4l2_subdev -结构体指针。对于 i2c 总线设备相对简单:调用 i2c_get_clientdata()。 -对于其他总线也需要做类似的操作。针对 I2C 总线上的子设备辅助函数帮你 -完成了大部分复杂的工作。 - -每个 v4l2_subdev 都包含子设备驱动需要实现的函数指针(如果对此设备 -不适用,可为NULL)。由于子设备可完成许多不同的工作,而在一个庞大的 -函数指针结构体中通常仅有少数有用的函数实现其功能肯定不合适。所以, -函数指针根据其实现的功能被分类,每一类都有自己的函数指针结构体。 - -顶层函数指针结构体包含了指向各类函数指针结构体的指针,如果子设备驱动 -不支持该类函数中的任何一个功能,则指向该类结构体的指针为NULL。 - -这些结构体定义如下: - -struct v4l2_subdev_core_ops { - int (*g_chip_ident)(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip); - int (*log_status)(struct v4l2_subdev *sd); - int (*init)(struct v4l2_subdev *sd, u32 val); - ... -}; - -struct v4l2_subdev_tuner_ops { - ... -}; - -struct v4l2_subdev_audio_ops { - ... -}; - -struct v4l2_subdev_video_ops { - ... -}; - -struct v4l2_subdev_pad_ops { - ... -}; - -struct v4l2_subdev_ops { - const struct v4l2_subdev_core_ops *core; - const struct v4l2_subdev_tuner_ops *tuner; - const struct v4l2_subdev_audio_ops *audio; - const struct v4l2_subdev_video_ops *video; - const struct v4l2_subdev_pad_ops *video; -}; - -其中 core(核心)函数集通常可用于所有子设备,其他类别的实现依赖于 -子设备。如视频设备可能不支持音频操作函数,反之亦然。 - -这样的设置在限制了函数指针数量的同时,还使增加新的操作函数和分类 -变得较为容易。 - -子设备驱动可使用如下函数初始化 v4l2_subdev 结构体: - - v4l2_subdev_init(sd, &ops); - -然后,你必须用一个唯一的名字初始化 subdev->name,并初始化模块的 -owner 域。若使用 i2c 辅助函数,这些都会帮你处理好。 - -若需同媒体框架整合,你必须调用 media_entity_init() 初始化 v4l2_subdev -结构体中的 media_entity 结构体(entity 域): - - struct media_pad *pads = &my_sd->pads; - int err; - - err = media_entity_init(&sd->entity, npads, pads, 0); - -pads 数组必须预先初始化。无须手动设置 media_entity 的 type 和 -name 域,但如有必要,revision 域必须初始化。 - -当(任何)子设备节点被打开/关闭,对 entity 的引用将被自动获取/释放。 - -在子设备被注销之后,不要忘记清理 media_entity 结构体: - - media_entity_cleanup(&sd->entity); - -如果子设备驱动趋向于处理视频并整合进了媒体框架,必须使用 v4l2_subdev_pad_ops -替代 v4l2_subdev_video_ops 实现格式相关的功能。 - -这种情况下,子设备驱动应该设置 link_validate 域,以提供它自身的链接 -验证函数。链接验证函数应对管道(两端链接的都是 V4L2 子设备)中的每个 -链接调用。驱动还要负责验证子设备和视频节点间格式配置的正确性。 - -如果 link_validate 操作没有设置,默认的 v4l2_subdev_link_validate_default() -函数将会被调用。这个函数保证宽、高和媒体总线像素格式在链接的收发两端 -都一致。子设备驱动除了它们自己的检测外,也可以自由使用这个函数以执行 -上面提到的检查。 - -设备(桥)驱动程序必须向 v4l2_device 注册 v4l2_subdev: - - int err = v4l2_device_register_subdev(v4l2_dev, sd); - -如果子设备模块在它注册前消失,这个操作可能失败。在这个函数成功返回后, -subdev->dev 域就指向了 v4l2_device。 - -如果 v4l2_device 父设备的 mdev 域为非 NULL 值,则子设备实体将被自动 -注册为媒体设备。 - -注销子设备则可用如下函数: - - v4l2_device_unregister_subdev(sd); - -此后,子设备模块就可卸载,且 sd->dev == NULL。 - -注册之设备后,可通过以下方式直接调用其操作函数: - - err = sd->ops->core->g_chip_ident(sd, &chip); - -但使用如下宏会比较容易且合适: - - err = v4l2_subdev_call(sd, core, g_chip_ident, &chip); - -这个宏将会做 NULL 指针检查,如果 subdev 为 NULL,则返回-ENODEV;如果 -subdev->core 或 subdev->core->g_chip_ident 为 NULL,则返回 -ENOIOCTLCMD; -否则将返回 subdev->ops->core->g_chip_ident ops 调用的实际结果。 - -有时也可能同时调用所有或一系列子设备的某个操作函数: - - v4l2_device_call_all(v4l2_dev, 0, core, g_chip_ident, &chip); - -任何不支持此操作的子设备都会被跳过,并忽略错误返回值。但如果你需要 -检查出错码,则可使用如下函数: - - err = v4l2_device_call_until_err(v4l2_dev, 0, core, g_chip_ident, &chip); - -除 -ENOIOCTLCMD 外的任何错误都会跳出循环并返回错误值。如果(除 -ENOIOCTLCMD -外)没有错误发生,则返回 0。 - -对于以上两个函数的第二个参数为组 ID。如果为 0,则所有子设备都会执行 -这个操作。如果为非 0 值,则只有那些组 ID 匹配的子设备才会执行此操作。 -在桥驱动注册一个子设备前,可以设置 sd->grp_id 为任何期望值(默认值为 -0)。这个值属于桥驱动,且子设备驱动将不会修改和使用它。 - -组 ID 赋予了桥驱动更多对于如何调用回调的控制。例如,电路板上有多个 -音频芯片,每个都有改变音量的能力。但当用户想要改变音量的时候,通常 -只有一个会被实际使用。你可以对这样的子设备设置组 ID 为(例如 AUDIO_CONTROLLER) -并在调用 v4l2_device_call_all() 时指定它为组 ID 值。这就保证了只有 -需要的子设备才会执行这个回调。 - -如果子设备需要通知它的 v4l2_device 父设备一个事件,可以调用 -v4l2_subdev_notify(sd, notification, arg)。这个宏检查是否有一个 -notify() 回调被注册,如果没有,返回 -ENODEV。否则返回 notify() 调用 -结果。 - -使用 v4l2_subdev 的好处在于它是一个通用结构体,且不包含任何底层硬件 -信息。所有驱动可以包含多个 I2C 总线的子设备,但也有子设备是通过 GPIO -控制。这个区别仅在配置设备时有关系,一旦子设备注册完成,对于 v4l2 -子系统来说就完全透明了。 - - -V4L2 子设备用户空间API --------------------- - -除了通过 v4l2_subdev_ops 结构导出的内核 API,V4L2 子设备也可以直接 -通过用户空间应用程序来控制。 - -可以在 /dev 中创建名为 v4l-subdevX 设备节点,以通过其直接访问子设备。 -如果子设备支持用户空间直接配置,必须在注册前设置 V4L2_SUBDEV_FL_HAS_DEVNODE -标志。 - -注册子设备之后, v4l2_device 驱动会通过调用 v4l2_device_register_subdev_nodes() -函数为所有已注册并设置了 V4L2_SUBDEV_FL_HAS_DEVNODE 的子设备创建 -设备节点。这些设备节点会在子设备注销时自动删除。 - -这些设备节点处理 V4L2 API 的一个子集。 - -VIDIOC_QUERYCTRL -VIDIOC_QUERYMENU -VIDIOC_G_CTRL -VIDIOC_S_CTRL -VIDIOC_G_EXT_CTRLS -VIDIOC_S_EXT_CTRLS -VIDIOC_TRY_EXT_CTRLS - - 这些 ioctls 控制与 V4L2 中定义的一致。他们行为相同,唯一的 - 不同是他们只处理子设备的控制实现。根据驱动程序,这些控制也 - 可以通过一个(或多个) V4L2 设备节点访问。 - -VIDIOC_DQEVENT -VIDIOC_SUBSCRIBE_EVENT -VIDIOC_UNSUBSCRIBE_EVENT - - 这些 ioctls 事件与 V4L2 中定义的一致。他们行为相同,唯一的 - 不同是他们只处理子设备产生的事件。根据驱动程序,这些事件也 - 可以通过一个(或多个) V4L2 设备节点上报。 - - 要使用事件通知的子设备驱动,在注册子设备前必须在 v4l2_subdev::flags - 中设置 V4L2_SUBDEV_USES_EVENTS 并在 v4l2_subdev::nevents - 中初始化事件队列深度。注册完成后,事件会在 v4l2_subdev::devnode - 设备节点中像通常一样被排队。 - - 为正确支持事件机制,poll() 文件操作也应被实现。 - -私有 ioctls - - 不在以上列表中的所有 ioctls 会通过 core::ioctl 操作直接传递 - 给子设备驱动。 - - -I2C 子设备驱动 -------------- - -由于这些驱动很常见,所以内特提供了特定的辅助函数(v4l2-common.h)让这些 -设备的使用更加容易。 - -添加 v4l2_subdev 支持的推荐方法是让 I2C 驱动将 v4l2_subdev 结构体 -嵌入到为每个 I2C 设备实例创建的状态结构体中。而最简单的设备没有状态 -结构体,此时可以直接创建一个 v4l2_subdev 结构体。 - -一个典型的状态结构体如下所示(‘chipname’用芯片名代替): - -struct chipname_state { - struct v4l2_subdev sd; - ... /* 附加的状态域*/ -}; - -初始化 v4l2_subdev 结构体的方法如下: - - v4l2_i2c_subdev_init(&state->sd, client, subdev_ops); - -这个函数将填充 v4l2_subdev 结构体中的所有域,并保证 v4l2_subdev 和 -i2c_client 都指向彼此。 - -同时,你也应该为从 v4l2_subdev 指针找到 chipname_state 结构体指针 -添加一个辅助内联函数。 - -static inline struct chipname_state *to_state(struct v4l2_subdev *sd) -{ - return container_of(sd, struct chipname_state, sd); -} - -使用以下函数可以通过 v4l2_subdev 结构体指针获得 i2c_client 结构体 -指针: - - struct i2c_client *client = v4l2_get_subdevdata(sd); - -而以下函数则相反,通过 i2c_client 结构体指针获得 v4l2_subdev 结构体 -指针: - - struct v4l2_subdev *sd = i2c_get_clientdata(client); - -当 remove()函数被调用前,必须保证先调用 v4l2_device_unregister_subdev(sd)。 -此操作将会从桥驱动中注销子设备。即使子设备没有注册,调用此函数也是 -安全的。 - -必须这样做的原因是:当桥驱动注销 i2c 适配器时,remove()回调函数 -会被那个适配器上的 i2c 设备调用。此后,相应的 v4l2_subdev 结构体 -就不存在了,所有它们必须先被注销。在 remove()回调函数中调用 -v4l2_device_unregister_subdev(sd),可以保证执行总是正确的。 - - -桥驱动也有一些辅组函数可用: - -struct v4l2_subdev *sd = v4l2_i2c_new_subdev(v4l2_dev, adapter, - "module_foo", "chipid", 0x36, NULL); - -这个函数会加载给定的模块(如果没有模块需要加载,可以为 NULL), -并用给定的 i2c 适配器结构体指针(i2c_adapter)和 器件地址(chip/address) -作为参数调用 i2c_new_device()。如果一切顺利,则就在 v4l2_device -中注册了子设备。 - -你也可以利用 v4l2_i2c_new_subdev()的最后一个参数,传递一个可能的 -I2C 地址数组,让函数自动探测。这些探测地址只有在前一个参数为 0 的 -情况下使用。非零参数意味着你知道准确的 i2c 地址,所以此时无须进行 -探测。 - -如果出错,两个函数都返回 NULL。 - -注意:传递给 v4l2_i2c_new_subdev()的 chipid 通常与模块名一致。 -它允许你指定一个芯片的变体,比如“saa7114”或“saa7115”。一般通过 -i2c 驱动自动探测。chipid 的使用是在今后需要深入了解的事情。这个与 -i2c 驱动不同,较容易混淆。要知道支持哪些芯片变体,你可以查阅 i2c -驱动代码的 i2c_device_id 表,上面列出了所有可能支持的芯片。 - -还有两个辅助函数: - -v4l2_i2c_new_subdev_cfg:这个函数添加新的 irq 和 platform_data -参数,并有‘addr’和‘probed_addrs’参数:如果 addr 非零,则被使用 -(不探测变体),否则 probed_addrs 中的地址将用于自动探测。 - -例如:以下代码将会探测地址(0x10): - -struct v4l2_subdev *sd = v4l2_i2c_new_subdev_cfg(v4l2_dev, adapter, - "module_foo", "chipid", 0, NULL, 0, I2C_ADDRS(0x10)); - -v4l2_i2c_new_subdev_board 使用一个 i2c_board_info 结构体,将其 -替代 irq、platform_data 和 add r参数传递给 i2c 驱动。 - -如果子设备支持 s_config 核心操作,这个操作会在子设备配置好之后以 irq 和 -platform_data 为参数调用。早期的 v4l2_i2c_new_(probed_)subdev 函数 -同样也会调用 s_config,但仅在 irq 为 0 且 platform_data 为 NULL 时。 - -video_device结构体 ------------------ - -在 /dev 目录下的实际设备节点根据 video_device 结构体(v4l2-dev.h) -创建。此结构体既可以动态分配也可以嵌入到一个更大的结构体中。 - -动态分配方法如下: - - struct video_device *vdev = video_device_alloc(); - - if (vdev == NULL) - return -ENOMEM; - - vdev->release = video_device_release; - -如果将其嵌入到一个大结构体中,则必须自己实现 release()回调。 - - struct video_device *vdev = &my_vdev->vdev; - - vdev->release = my_vdev_release; - -release()回调必须被设置,且在最后一个 video_device 用户退出之后 -被调用。 - -默认的 video_device_release()回调只是调用 kfree 来释放之前分配的 -内存。 - -你应该设置这些域: - -- v4l2_dev: 设置为 v4l2_device 父设备。 - -- name: 设置为唯一的描述性设备名。 - -- fops: 设置为已有的 v4l2_file_operations 结构体。 - -- ioctl_ops: 如果你使用v4l2_ioctl_ops 来简化 ioctl 的维护 - (强烈建议使用,且将来可能变为强制性的!),然后设置你自己的 - v4l2_ioctl_ops 结构体. - -- lock: 如果你要在驱动中实现所有的锁操作,则设为 NULL 。否则 - 就要设置一个指向 struct mutex_lock 结构体的指针,这个锁将 - 在 unlocked_ioctl 文件操作被调用前由内核获得,并在调用返回后 - 释放。详见下一节。 - -- prio: 保持对优先级的跟踪。用于实现 VIDIOC_G/S_PRIORITY。如果 - 设置为 NULL,则会使用 v4l2_device 中的 v4l2_prio_state 结构体。 - 如果要对每个设备节点(组)实现独立的优先级,可以将其指向自己 - 实现的 v4l2_prio_state 结构体。 - -- parent: 仅在使用 NULL 作为父设备结构体参数注册 v4l2_device 时 - 设置此参数。只有在一个硬件设备包含多一个 PCI 设备,共享同一个 - v4l2_device 核心时才会发生。 - - cx88 驱动就是一个例子:一个 v4l2_device 结构体核心,被一个裸的 - 视频 PCI 设备(cx8800)和一个 MPEG PCI 设备(cx8802)共用。由于 - v4l2_device 无法与特定的 PCI 设备关联,所有没有设置父设备。但当 - video_device 配置后,就知道使用哪个父 PCI 设备了。 - -- flags:可选。如果你要让框架处理设置 VIDIOC_G/S_PRIORITY ioctls, - 请设置 V4L2_FL_USE_FH_PRIO。这要求你使用 v4l2_fh 结构体。 - 一旦所有驱动使用了核心的优先级处理,最终这个标志将消失。但现在它 - 必须被显式设置。 - -如果你使用 v4l2_ioctl_ops,则应该在 v4l2_file_operations 结构体中 -设置 .unlocked_ioctl 指向 video_ioctl2。 - -请勿使用 .ioctl!它已被废弃,今后将消失。 - -某些情况下你要告诉核心:你在 v4l2_ioctl_ops 指定的某个函数应被忽略。 -你可以在 video_device_register 被调用前通过以下函数标记这个 ioctls。 - -void v4l2_disable_ioctl(struct video_device *vdev, unsigned int cmd); - -基于外部因素(例如某个板卡已被使用),在不创建新结构体的情况下,你想 -要关闭 v4l2_ioctl_ops 中某个特性往往需要这个机制。 - -v4l2_file_operations 结构体是 file_operations 的一个子集。其主要 -区别在于:因 inode 参数从未被使用,它将被忽略。 - -如果需要与媒体框架整合,你必须通过调用 media_entity_init() 初始化 -嵌入在 video_device 结构体中的 media_entity(entity 域)结构体: - - struct media_pad *pad = &my_vdev->pad; - int err; - - err = media_entity_init(&vdev->entity, 1, pad, 0); - -pads 数组必须预先初始化。没有必要手动设置 media_entity 的 type 和 -name 域。 - -当(任何)子设备节点被打开/关闭,对 entity 的引用将被自动获取/释放。 - -v4l2_file_operations 与锁 --------------------------- - -你可以在 video_device 结构体中设置一个指向 mutex_lock 的指针。通常 -这既可是一个顶层互斥锁也可为设备节点自身的互斥锁。默认情况下,此锁 -用于 unlocked_ioctl,但为了使用 ioctls 你通过以下函数可禁用锁定: - - void v4l2_disable_ioctl_locking(struct video_device *vdev, unsigned int cmd); - -例如: v4l2_disable_ioctl_locking(vdev, VIDIOC_DQBUF); - -你必须在注册 video_device 前调用这个函数。 - -特别是对于 USB 驱动程序,某些命令(如设置控制)需要很长的时间,可能 -需要自行为缓冲区队列的 ioctls 实现锁定。 - -如果你需要更细粒度的锁,你必须设置 mutex_lock 为 NULL,并完全自己实现 -锁机制。 - -这完全由驱动开发者决定使用何种方法。然而,如果你的驱动存在长延时操作 -(例如,改变 USB 摄像头的曝光时间可能需要较长时间),而你又想让用户 -在等待长延时操作完成期间做其他的事,则你最好自己实现锁机制。 - -如果指定一个锁,则所有 ioctl 操作将在这个锁的作用下串行执行。如果你 -使用 videobuf,则必须将同一个锁传递给 videobuf 队列初始化函数;如 -videobuf 必须等待一帧的到达,则可临时解锁并在这之后重新上锁。如果驱动 -也在代码执行期间等待,则可做同样的工作(临时解锁,再上锁)让其他进程 -可以在第一个进程阻塞时访问设备节点。 - -在使用 videobuf2 的情况下,必须实现 wait_prepare 和 wait_finish 回调 -在适当的时候解锁/加锁。进一步来说,如果你在 video_device 结构体中使用 -锁,则必须在 wait_prepare 和 wait_finish 中对这个互斥锁进行解锁/加锁。 - -热插拔的断开实现也必须在调用 v4l2_device_disconnect 前获得锁。 - -video_device注册 ---------------- - -接下来你需要注册视频设备:这会为你创建一个字符设备。 - - err = video_register_device(vdev, VFL_TYPE_GRABBER, -1); - if (err) { - video_device_release(vdev); /* or kfree(my_vdev); */ - return err; - } - -如果 v4l2_device 父设备的 mdev 域为非 NULL 值,视频设备实体将自动 -注册为媒体设备。 - -注册哪种设备是根据类型(type)参数。存在以下类型: - -VFL_TYPE_GRABBER: 用于视频输入/输出设备的 videoX -VFL_TYPE_VBI: 用于垂直消隐数据的 vbiX (例如,隐藏式字幕,图文电视) -VFL_TYPE_RADIO: 用于广播调谐器的 radioX - -最后一个参数让你确定一个所控制设备的设备节点号数量(例如 videoX 中的 X)。 -通常你可以传入-1,让 v4l2 框架自己选择第一个空闲的编号。但是有时用户 -需要选择一个特定的节点号。驱动允许用户通过驱动模块参数选择一个特定的 -设备节点号是很普遍的。这个编号将会传递给这个函数,且 video_register_device -将会试图选择这个设备节点号。如果这个编号被占用,下一个空闲的设备节点 -编号将被选中,并向内核日志中发送一个警告信息。 - -另一个使用场景是当驱动创建多个设备时。这种情况下,对不同的视频设备在 -编号上使用不同的范围是很有用的。例如,视频捕获设备从 0 开始,视频 -输出设备从 16 开始。所以你可以使用最后一个参数来指定设备节点号最小值, -而 v4l2 框架会试图选择第一个的空闲编号(等于或大于你提供的编号)。 -如果失败,则它会就选择第一个空闲的编号。 - -由于这种情况下,你会忽略无法选择特定设备节点号的警告,则可调用 -video_register_device_no_warn() 函数避免警告信息的产生。 - -只要设备节点被创建,一些属性也会同时创建。在 /sys/class/video4linux -目录中你会找到这些设备。例如进入其中的 video0 目录,你会看到‘name’和 -‘index’属性。‘name’属性值就是 video_device 结构体中的‘name’域。 - -‘index’属性值就是设备节点的索引值:每次调用 video_register_device(), -索引值都递增 1 。第一个视频设备节点总是从索引值 0 开始。 - -用户可以设置 udev 规则,利用索引属性生成花哨的设备名(例如:用‘mpegX’ -代表 MPEG 视频捕获设备节点)。 - -在设备成功注册后,就可以使用这些域: - -- vfl_type: 传递给 video_register_device 的设备类型。 -- minor: 已指派的次设备号。 -- num: 设备节点编号 (例如 videoX 中的 X)。 -- index: 设备索引号。 - -如果注册失败,你必须调用 video_device_release() 来释放已分配的 -video_device 结构体;如果 video_device 是嵌入在自己创建的结构体中, -你也必须释放它。vdev->release() 回调不会在注册失败之后被调用, -你也不应试图在注册失败后注销设备。 - - -video_device 注销 ----------------- - -当视频设备节点已被移除,不论是卸载驱动还是USB设备断开,你都应注销 -它们: - - video_unregister_device(vdev); - -这个操作将从 sysfs 中移除设备节点(导致 udev 将其从 /dev 中移除)。 - -video_unregister_device() 返回之后,就无法完成打开操作。尽管如此, -USB 设备的情况则不同,某些应用程序可能依然打开着其中一个已注销设备 -节点。所以在注销之后,所有文件操作(当然除了 release )也应返回错误值。 - -当最后一个视频设备节点的用户退出,则 vdev->release() 回调会被调用, -并且你可以做最后的清理操作。 - -不要忘记清理与视频设备相关的媒体入口(如果被初始化过): - - media_entity_cleanup(&vdev->entity); - -这可以在 release 回调中完成。 - - -video_device 辅助函数 ---------------------- - -一些有用的辅助函数如下: - -- file/video_device 私有数据 - -你可以用以下函数在 video_device 结构体中设置/获取驱动私有数据: - -void *video_get_drvdata(struct video_device *vdev); -void video_set_drvdata(struct video_device *vdev, void *data); - -注意:在调用 video_register_device() 前执行 video_set_drvdata() -是安全的。 - -而以下函数: - -struct video_device *video_devdata(struct file *file); - -返回 file 结构体中拥有的的 video_device 指针。 - -video_drvdata 辅助函数结合了 video_get_drvdata 和 video_devdata -的功能: - -void *video_drvdata(struct file *file); - -你可以使用如下代码从 video_device 结构体中获取 v4l2_device 结构体 -指针: - -struct v4l2_device *v4l2_dev = vdev->v4l2_dev; - -- 设备节点名 - -video_device 设备节点在内核中的名称可以通过以下函数获得 - -const char *video_device_node_name(struct video_device *vdev); - -这个名字被用户空间工具(例如 udev)作为提示信息使用。应尽可能使用 -此功能,而非访问 video_device::num 和 video_device::minor 域。 - - -视频缓冲辅助函数 ---------------- - -v4l2 核心 API 提供了一个处理视频缓冲的标准方法(称为“videobuf”)。 -这些方法使驱动可以通过统一的方式实现 read()、mmap() 和 overlay()。 -目前在设备上支持视频缓冲的方法有分散/聚集 DMA(videobuf-dma-sg)、 -线性 DMA(videobuf-dma-contig)以及大多用于 USB 设备的用 vmalloc -分配的缓冲(videobuf-vmalloc)。 - -请参阅 Documentation/video4linux/videobuf,以获得更多关于 videobuf -层的使用信息。 - -v4l2_fh 结构体 -------------- - -v4l2_fh 结构体提供一个保存用于 V4L2 框架的文件句柄特定数据的简单方法。 -如果 video_device 的 flag 设置了 V4L2_FL_USE_FH_PRIO 标志,新驱动 -必须使用 v4l2_fh 结构体,因为它也用于实现优先级处理(VIDIOC_G/S_PRIORITY)。 - -v4l2_fh 的用户(位于 V4l2 框架中,并非驱动)可通过测试 -video_device->flags 中的 V4L2_FL_USES_V4L2_FH 位得知驱动是否使用 -v4l2_fh 作为他的 file->private_data 指针。这个位会在调用 v4l2_fh_init() -时被设置。 - -v4l2_fh 结构体作为驱动自身文件句柄结构体的一部分被分配,且驱动在 -其打开函数中将 file->private_data 指向它。 - -在许多情况下,v4l2_fh 结构体会嵌入到一个更大的结构体中。这钟情况下, -应该在 open() 中调用 v4l2_fh_init+v4l2_fh_add,并在 release() 中 -调用 v4l2_fh_del+v4l2_fh_exit。 - -驱动可以通过使用 container_of 宏提取他们自己的文件句柄结构体。例如: - -struct my_fh { - int blah; - struct v4l2_fh fh; -}; - -... - -int my_open(struct file *file) -{ - struct my_fh *my_fh; - struct video_device *vfd; - int ret; - - ... - - my_fh = kzalloc(sizeof(*my_fh), GFP_KERNEL); - - ... - - v4l2_fh_init(&my_fh->fh, vfd); - - ... - - file->private_data = &my_fh->fh; - v4l2_fh_add(&my_fh->fh); - return 0; -} - -int my_release(struct file *file) -{ - struct v4l2_fh *fh = file->private_data; - struct my_fh *my_fh = container_of(fh, struct my_fh, fh); - - ... - v4l2_fh_del(&my_fh->fh); - v4l2_fh_exit(&my_fh->fh); - kfree(my_fh); - return 0; -} - -以下是 v4l2_fh 函数使用的简介: - -void v4l2_fh_init(struct v4l2_fh *fh, struct video_device *vdev) - - 初始化文件句柄。这*必须*在驱动的 v4l2_file_operations->open() - 函数中执行。 - -void v4l2_fh_add(struct v4l2_fh *fh) - - 添加一个 v4l2_fh 到 video_device 文件句柄列表。一旦文件句柄 - 初始化完成就必须调用。 - -void v4l2_fh_del(struct v4l2_fh *fh) - - 从 video_device() 中解除文件句柄的关联。文件句柄的退出函数也 - 将被调用。 - -void v4l2_fh_exit(struct v4l2_fh *fh) - - 清理文件句柄。在清理完 v4l2_fh 后,相关内存会被释放。 - - -如果 v4l2_fh 不是嵌入在其他结构体中的,则可以用这些辅助函数: - -int v4l2_fh_open(struct file *filp) - - 分配一个 v4l2_fh 结构体空间,初始化并将其添加到 file 结构体相关的 - video_device 结构体中。 - -int v4l2_fh_release(struct file *filp) - - 从 file 结构体相关的 video_device 结构体中删除 v4l2_fh ,清理 - v4l2_fh 并释放空间。 - -这两个函数可以插入到 v4l2_file_operation 的 open() 和 release() -操作中。 - - -某些驱动需要在第一个文件句柄打开和最后一个文件句柄关闭的时候做些 -工作。所以加入了两个辅助函数以检查 v4l2_fh 结构体是否是相关设备 -节点打开的唯一文件句柄。 - -int v4l2_fh_is_singular(struct v4l2_fh *fh) - - 如果此文件句柄是唯一打开的文件句柄,则返回 1 ,否则返回 0 。 - -int v4l2_fh_is_singular_file(struct file *filp) - - 功能相同,但通过 filp->private_data 调用 v4l2_fh_is_singular。 - - -V4L2 事件机制 ------------ - -V4L2 事件机制提供了一个通用的方法将事件传递到用户空间。驱动必须使用 -v4l2_fh 才能支持 V4L2 事件机制。 - - -事件通过一个类型和选择 ID 来定义。ID 对应一个 V4L2 对象,例如 -一个控制 ID。如果未使用,则 ID 为 0。 - -当用户订阅一个事件,驱动会为此分配一些 kevent 结构体。所以每个 -事件组(类型、ID)都会有自己的一套 kevent 结构体。这保证了如果 -一个驱动短时间内产生了许多同类事件,不会覆盖其他类型的事件。 - -但如果你收到的事件数量大于同类事件 kevent 的保存数量,则最早的 -事件将被丢弃,并加入新事件。 - -此外,v4l2_subscribed_event 结构体内部有可供驱动设置的 merge() 和 -replace() 回调,这些回调会在新事件产生且没有多余空间的时候被调用。 -replace() 回调让你可以将早期事件的净荷替换为新事件的净荷,将早期 -净荷的相关数据合并到替换进来的新净荷中。当该类型的事件仅分配了一个 -kevent 结构体时,它将被调用。merge() 回调让你可以合并最早的事件净荷 -到在它之后的那个事件净荷中。当该类型的事件分配了两个或更多 kevent -结构体时,它将被调用。 - -这种方法不会有状态信息丢失,只会导致中间步骤信息丢失。 - - -关于 replace/merge 回调的一个不错的例子在 v4l2-event.c 中:用于 -控制事件的 ctrls_replace() 和 ctrls_merge() 回调。 - -注意:这些回调可以在中断上下文中调用,所以它们必须尽快完成并退出。 - -有用的函数: - -void v4l2_event_queue(struct video_device *vdev, const struct v4l2_event *ev) - - 将事件加入视频设备的队列。驱动仅负责填充 type 和 data 域。 - 其他域由 V4L2 填充。 - -int v4l2_event_subscribe(struct v4l2_fh *fh, - struct v4l2_event_subscription *sub, unsigned elems, - const struct v4l2_subscribed_event_ops *ops) - - video_device->ioctl_ops->vidioc_subscribe_event 必须检测驱动能 - 产生特定 id 的事件。然后调用 v4l2_event_subscribe() 来订阅该事件。 - - elems 参数是该事件的队列大小。若为 0,V4L2 框架将会(根据事件类型) - 填充默认值。 - - ops 参数允许驱动指定一系列回调: - * add: 当添加一个新监听者时调用(重复订阅同一个事件,此回调 - 仅被执行一次)。 - * del: 当一个监听者停止监听时调用。 - * replace: 用‘新’事件替换‘早期‘事件。 - * merge: 将‘早期‘事件合并到‘新’事件中。 - 这四个调用都是可选的,如果不想指定任何回调,则 ops 可为 NULL。 - -int v4l2_event_unsubscribe(struct v4l2_fh *fh, - struct v4l2_event_subscription *sub) - - v4l2_ioctl_ops 结构体中的 vidioc_unsubscribe_event 回调函数。 - 驱动程序可以直接使用 v4l2_event_unsubscribe() 实现退订事件过程。 - - 特殊的 V4L2_EVENT_ALL 类型,可用于退订所有事件。驱动可能在特殊 - 情况下需要做此操作。 - -int v4l2_event_pending(struct v4l2_fh *fh) - - 返回未决事件的数量。有助于实现轮询(poll)操作。 - -事件通过 poll 系统调用传递到用户空间。驱动可用 -v4l2_fh->wait (wait_queue_head_t 类型)作为参数调用 poll_wait()。 - -事件分为标准事件和私有事件。新的标准事件必须使用可用的最小事件类型 -编号。驱动必须从他们本类型的编号起始处分配事件。类型的编号起始为 -V4L2_EVENT_PRIVATE_START + n * 1000 ,其中 n 为可用最小编号。每个 -类型中的第一个事件类型编号是为以后的使用保留的,所以第一个可用事件 -类型编号是‘class base + 1’。 - -V4L2 事件机制的使用实例可以在 OMAP3 ISP 的驱动 -(drivers/media/video/omap3isp)中找到。 diff --git a/trunk/MAINTAINERS b/trunk/MAINTAINERS index 0318e6264346..94b823f71e94 100644 --- a/trunk/MAINTAINERS +++ b/trunk/MAINTAINERS @@ -827,24 +827,24 @@ F: arch/arm/mach-pxa/colibri-pxa270-income.c ARM/INTEL IOP32X ARM ARCHITECTURE M: Lennert Buytenhek -M: Dan Williams +M: Dan Williams L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained ARM/INTEL IOP33X ARM ARCHITECTURE -M: Dan Williams +M: Dan Williams L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained ARM/INTEL IOP13XX ARM ARCHITECTURE M: Lennert Buytenhek -M: Dan Williams +M: Dan Williams L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained ARM/INTEL IQ81342EX MACHINE SUPPORT M: Lennert Buytenhek -M: Dan Williams +M: Dan Williams L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained @@ -869,7 +869,7 @@ F: drivers/pcmcia/pxa2xx_stargate2.c ARM/INTEL XSC3 (MANZANO) ARM CORE M: Lennert Buytenhek -M: Dan Williams +M: Dan Williams L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained @@ -925,14 +925,14 @@ S: Maintained ARM/NOMADIK ARCHITECTURE M: Alessandro Rubini -M: Linus Walleij +M: Linus Walleij M: STEricsson L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained F: arch/arm/mach-nomadik/ F: arch/arm/plat-nomadik/ F: drivers/i2c/busses/i2c-nomadik.c -T: git git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-nomadik.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-stericsson.git ARM/OPENMOKO NEO FREERUNNER (GTA02) MACHINE SUPPORT M: Nelson Castillo @@ -1146,7 +1146,7 @@ F: drivers/usb/host/ehci-w90x900.c F: drivers/video/nuc900fb.c ARM/U300 MACHINE SUPPORT -M: Linus Walleij +M: Linus Walleij L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Supported F: arch/arm/mach-u300/ @@ -1161,20 +1161,15 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-stericsson.git ARM/Ux500 ARM ARCHITECTURE M: Srinidhi Kasagar -M: Linus Walleij +M: Linus Walleij L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained F: arch/arm/mach-ux500/ -F: drivers/clocksource/clksrc-dbx500-prcmu.c F: drivers/dma/ste_dma40* -F: drivers/hwspinlock/u8500_hsem.c F: drivers/mfd/abx500* F: drivers/mfd/ab8500* -F: drivers/mfd/dbx500* -F: drivers/mfd/db8500* -F: drivers/pinctrl/pinctrl-nomadik* +F: drivers/mfd/stmpe* F: drivers/rtc/rtc-ab8500.c -F: drivers/rtc/rtc-pl031.c T: git git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-stericsson.git ARM/VFP SUPPORT @@ -1209,12 +1204,6 @@ S: Maintained F: arch/arm/mach-pxa/z2.c F: arch/arm/mach-pxa/include/mach/z2.h -ARM64 PORT (AARCH64 ARCHITECTURE) -M: Catalin Marinas -L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) -S: Maintained -F: arch/arm64/ - ASC7621 HARDWARE MONITOR DRIVER M: George Joseph L: lm-sensors@lm-sensors.org @@ -1238,9 +1227,9 @@ S: Maintained F: drivers/hwmon/asb100.c ASYNCHRONOUS TRANSFERS/TRANSFORMS (IOAT) API -M: Dan Williams +M: Dan Williams W: http://sourceforge.net/projects/xscaleiop -S: Maintained +S: Supported F: Documentation/crypto/async-tx-api.txt F: crypto/async_tx/ F: drivers/dma/ @@ -2223,7 +2212,7 @@ S: Maintained F: drivers/scsi/tmscsim.* DC395x SCSI driver -M: Oliver Neukum +M: Oliver Neukum M: Ali Akcaagac M: Jamie Lenehan W: http://twibble.org/dist/dc395x/ @@ -2370,7 +2359,7 @@ T: git git://git.linaro.org/people/sumitsemwal/linux-dma-buf.git DMA GENERIC OFFLOAD ENGINE SUBSYSTEM M: Vinod Koul -M: Dan Williams +M: Dan Williams S: Supported F: drivers/dma/ F: include/linux/dma* @@ -2865,9 +2854,7 @@ F: include/linux/firewire*.h F: tools/firewire/ FIRMWARE LOADER (request_firmware) -M: Ming Lei -L: linux-kernel@vger.kernel.org -S: Maintained +S: Orphan F: Documentation/firmware_class/ F: drivers/base/firmware*.c F: include/linux/firmware.h @@ -3107,7 +3094,7 @@ F: include/linux/gigaset_dev.h GPIO SUBSYSTEM M: Grant Likely -M: Linus Walleij +M: Linus Walleij S: Maintained T: git git://git.secretlab.ca/git/linux-2.6.git F: Documentation/gpio.txt @@ -3396,7 +3383,7 @@ M: "Wolfram Sang (embedded platforms)" L: linux-i2c@vger.kernel.org W: http://i2c.wiki.kernel.org/ T: quilt kernel.org/pub/linux/kernel/people/jdelvare/linux-2.6/jdelvare-i2c/ -T: git git://git.pengutronix.de/git/wsa/linux.git +T: git git://git.fluff.org/bjdooks/linux.git S: Maintained F: Documentation/i2c/ F: drivers/i2c/ @@ -3560,12 +3547,12 @@ K: \b(ABS|SYN)_MT_ INTEL C600 SERIES SAS CONTROLLER DRIVER M: Intel SCU Linux support -M: Lukasz Dorau -M: Maciej Patelczyk +M: Dan Williams M: Dave Jiang +M: Ed Nadolski L: linux-scsi@vger.kernel.org -T: git git://git.code.sf.net/p/intel-sas/isci -S: Supported +T: git git://git.kernel.org/pub/scm/linux/kernel/git/djbw/isci.git +S: Maintained F: drivers/scsi/isci/ F: firmware/isci/ @@ -3603,8 +3590,8 @@ F: arch/x86/kernel/microcode_core.c F: arch/x86/kernel/microcode_intel.c INTEL I/OAT DMA DRIVER -M: Dan Williams -S: Maintained +M: Dan Williams +S: Supported F: drivers/dma/ioat* INTEL IOMMU (VT-d) @@ -3616,8 +3603,8 @@ F: drivers/iommu/intel-iommu.c F: include/linux/intel-iommu.h INTEL IOP-ADMA DMA DRIVER -M: Dan Williams -S: Odd fixes +M: Dan Williams +S: Maintained F: drivers/dma/iop-adma.c INTEL IXP4XX QMGR, NPE, ETHERNET and HSS SUPPORT @@ -3675,12 +3662,11 @@ F: Documentation/networking/README.ipw2200 F: drivers/net/wireless/ipw2x00/ INTEL(R) TRUSTED EXECUTION TECHNOLOGY (TXT) -M: Richard L Maliszewski -M: Gang Wei +M: Joseph Cihula M: Shane Wang L: tboot-devel@lists.sourceforge.net W: http://tboot.sourceforge.net -T: hg http://tboot.hg.sourceforge.net:8000/hgroot/tboot/tboot +T: Mercurial http://www.bughost.org/repos.hg/tboot.hg S: Supported F: Documentation/intel_txt.txt F: include/linux/tboot.h @@ -4547,7 +4533,7 @@ S: Supported F: arch/microblaze/ MICROTEK X6 SCANNER -M: Oliver Neukum +M: Oliver Neukum S: Maintained F: drivers/usb/image/microtek.* @@ -5330,12 +5316,6 @@ L: linux-mtd@lists.infradead.org S: Maintained F: drivers/mtd/devices/phram.c -PICOLCD HID DRIVER -M: Bruno Prémont -L: linux-input@vger.kernel.org -S: Maintained -F: drivers/hid/hid-picolcd* - PICOXCELL SUPPORT M: Jamie Iles L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) @@ -5349,15 +5329,14 @@ PIN CONTROL SUBSYSTEM M: Linus Walleij S: Maintained F: drivers/pinctrl/ -F: include/linux/pinctrl/ PIN CONTROLLER - ST SPEAR -M: Viresh Kumar +M: Viresh Kumar L: spear-devel@list.st.com L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) W: http://www.st.com/spear S: Maintained -F: drivers/pinctrl/spear/ +F: driver/pinctrl/spear/ PKTCDVD DRIVER M: Peter Osterlund @@ -5559,8 +5538,6 @@ F: Documentation/devicetree/bindings/pwm/ F: include/linux/pwm.h F: include/linux/of_pwm.h F: drivers/pwm/ -F: drivers/video/backlight/pwm_bl.c -F: include/linux/pwm_backlight.h PXA2xx/PXA3xx SUPPORT M: Eric Miao @@ -7094,7 +7071,7 @@ F: include/linux/mtd/ubi.h F: include/mtd/ubi-user.h USB ACM DRIVER -M: Oliver Neukum +M: Oliver Neukum L: linux-usb@vger.kernel.org S: Maintained F: Documentation/usb/acm.txt @@ -7115,7 +7092,7 @@ S: Supported F: drivers/block/ub.c USB CDC ETHERNET DRIVER -M: Oliver Neukum +M: Oliver Neukum L: linux-usb@vger.kernel.org S: Maintained F: drivers/net/usb/cdc_*.c @@ -7188,7 +7165,7 @@ F: drivers/usb/host/isp116x* F: include/linux/usb/isp116x.h USB KAWASAKI LSI DRIVER -M: Oliver Neukum +M: Oliver Neukum L: linux-usb@vger.kernel.org S: Maintained F: drivers/usb/serial/kl5kusb105.* @@ -7306,12 +7283,6 @@ W: http://www.connecttech.com S: Supported F: drivers/usb/serial/whiteheat* -USB SMSC75XX ETHERNET DRIVER -M: Steve Glendinning -L: netdev@vger.kernel.org -S: Maintained -F: drivers/net/usb/smsc75xx.* - USB SMSC95XX ETHERNET DRIVER M: Steve Glendinning L: netdev@vger.kernel.org @@ -7694,28 +7665,23 @@ S: Supported F: Documentation/hwmon/wm83?? F: arch/arm/mach-s3c64xx/mach-crag6410* F: drivers/clk/clk-wm83*.c -F: drivers/extcon/extcon-arizona.c F: drivers/leds/leds-wm83*.c F: drivers/gpio/gpio-*wm*.c -F: drivers/gpio/gpio-arizona.c F: drivers/hwmon/wm83??-hwmon.c F: drivers/input/misc/wm831x-on.c F: drivers/input/touchscreen/wm831x-ts.c F: drivers/input/touchscreen/wm97*.c -F: drivers/mfd/arizona* -F: drivers/mfd/wm*.c +F: drivers/mfd/wm8*.c F: drivers/power/wm83*.c F: drivers/rtc/rtc-wm83*.c F: drivers/regulator/wm8*.c F: drivers/video/backlight/wm83*_bl.c F: drivers/watchdog/wm83*_wdt.c -F: include/linux/mfd/arizona/ F: include/linux/mfd/wm831x/ F: include/linux/mfd/wm8350/ F: include/linux/mfd/wm8400* F: include/linux/wm97xx.h F: include/sound/wm????.h -F: sound/soc/codecs/arizona.? F: sound/soc/codecs/wm* WORKQUEUE diff --git a/trunk/Makefile b/trunk/Makefile index 846dd7607854..ddf5be952e45 100644 --- a/trunk/Makefile +++ b/trunk/Makefile @@ -1,8 +1,8 @@ VERSION = 3 PATCHLEVEL = 6 SUBLEVEL = 0 -EXTRAVERSION = -NAME = Terrified Chipmunk +EXTRAVERSION = -rc1 +NAME = Saber-toothed Squirrel # *DOCUMENTATION* # To see a list of typical targets execute "make help" @@ -609,11 +609,7 @@ KBUILD_CFLAGS += $(call cc-option, -femit-struct-debug-baseonly) endif ifdef CONFIG_FUNCTION_TRACER -ifdef CONFIG_HAVE_FENTRY -CC_USING_FENTRY := $(call cc-option, -mfentry -DCC_USING_FENTRY) -endif -KBUILD_CFLAGS += -pg $(CC_USING_FENTRY) -KBUILD_AFLAGS += $(CC_USING_FENTRY) +KBUILD_CFLAGS += -pg ifdef CONFIG_DYNAMIC_FTRACE ifdef CONFIG_HAVE_C_RECORDMCOUNT BUILD_C_RECORDMCOUNT := y diff --git a/trunk/arch/Kconfig b/trunk/arch/Kconfig index a62965d057f6..72f2fa189cc5 100644 --- a/trunk/arch/Kconfig +++ b/trunk/arch/Kconfig @@ -222,19 +222,6 @@ config HAVE_PERF_EVENTS_NMI subsystem. Also has support for calculating CPU cycle events to determine how many clock cycles in a given period. -config HAVE_PERF_REGS - bool - help - Support selective register dumps for perf events. This includes - bit-mapping of each registers and a unique architecture id. - -config HAVE_PERF_USER_STACK_DUMP - bool - help - Support user stack dumps for perf event samples. This needs - access to the user stack pointer which is not unified across - architectures. - config HAVE_ARCH_JUMP_LABEL bool @@ -294,23 +281,4 @@ config SECCOMP_FILTER See Documentation/prctl/seccomp_filter.txt for details. -config HAVE_RCU_USER_QS - bool - help - Provide kernel entry/exit hooks necessary for userspace - RCU extended quiescent state. Syscalls need to be wrapped inside - rcu_user_exit()-rcu_user_enter() through the slow path using - TIF_NOHZ flag. Exceptions handlers must be wrapped as well. Irqs - are already protected inside rcu_irq_enter/rcu_irq_exit() but - preemption or signal handling on irq exit still need to be protected. - -config HAVE_VIRT_CPU_ACCOUNTING - bool - -config HAVE_IRQ_TIME_ACCOUNTING - bool - help - Archs need to ensure they use a high enough resolution clock to - support irq time accounting and then call enable_sched_clock_irqtime(). - source "kernel/gcov/Kconfig" diff --git a/trunk/arch/alpha/Kconfig b/trunk/arch/alpha/Kconfig index 9944dedee5b1..d5b9b5e645cc 100644 --- a/trunk/arch/alpha/Kconfig +++ b/trunk/arch/alpha/Kconfig @@ -18,8 +18,6 @@ config ALPHA select ARCH_HAVE_NMI_SAFE_CMPXCHG select GENERIC_SMP_IDLE_THREAD select GENERIC_CMOS_UPDATE - select GENERIC_STRNCPY_FROM_USER - select GENERIC_STRNLEN_USER help The Alpha is a 64-bit general-purpose processor designed and marketed by the Digital Equipment Corporation of blessed memory, diff --git a/trunk/arch/alpha/include/asm/atomic.h b/trunk/arch/alpha/include/asm/atomic.h index c2cbe4fc391c..3bb7ffeae3bc 100644 --- a/trunk/arch/alpha/include/asm/atomic.h +++ b/trunk/arch/alpha/include/asm/atomic.h @@ -14,8 +14,8 @@ */ -#define ATOMIC_INIT(i) { (i) } -#define ATOMIC64_INIT(i) { (i) } +#define ATOMIC_INIT(i) ( (atomic_t) { (i) } ) +#define ATOMIC64_INIT(i) ( (atomic64_t) { (i) } ) #define atomic_read(v) (*(volatile int *)&(v)->counter) #define atomic64_read(v) (*(volatile long *)&(v)->counter) diff --git a/trunk/arch/alpha/include/asm/fpu.h b/trunk/arch/alpha/include/asm/fpu.h index e477bcd5b94a..db00f7885faa 100644 --- a/trunk/arch/alpha/include/asm/fpu.h +++ b/trunk/arch/alpha/include/asm/fpu.h @@ -1,9 +1,7 @@ #ifndef __ASM_ALPHA_FPU_H #define __ASM_ALPHA_FPU_H -#ifdef __KERNEL__ #include -#endif /* * Alpha floating-point control register defines: diff --git a/trunk/arch/alpha/include/asm/ptrace.h b/trunk/arch/alpha/include/asm/ptrace.h index b87755a19554..fd698a174f26 100644 --- a/trunk/arch/alpha/include/asm/ptrace.h +++ b/trunk/arch/alpha/include/asm/ptrace.h @@ -76,10 +76,7 @@ struct switch_stack { #define task_pt_regs(task) \ ((struct pt_regs *) (task_stack_page(task) + 2*PAGE_SIZE) - 1) -#define current_pt_regs() \ - ((struct pt_regs *) ((char *)current_thread_info() + 2*PAGE_SIZE) - 1) - -#define force_successful_syscall_return() (current_pt_regs()->r0 = 0) +#define force_successful_syscall_return() (task_pt_regs(current)->r0 = 0) #endif diff --git a/trunk/arch/alpha/include/asm/socket.h b/trunk/arch/alpha/include/asm/socket.h index 7d2f75be932e..dcb221a4b5be 100644 --- a/trunk/arch/alpha/include/asm/socket.h +++ b/trunk/arch/alpha/include/asm/socket.h @@ -76,11 +76,9 @@ /* Instruct lower device to use last 4-bytes of skb data as FCS */ #define SO_NOFCS 43 -#ifdef __KERNEL__ /* O_NONBLOCK clashes with the bits used for socket types. Therefore we * have to define SOCK_NONBLOCK to a different value here. */ #define SOCK_NONBLOCK 0x40000000 -#endif /* __KERNEL__ */ #endif /* _ASM_SOCKET_H */ diff --git a/trunk/arch/alpha/include/asm/uaccess.h b/trunk/arch/alpha/include/asm/uaccess.h index 766fdfde2b7a..b49ec2f8d6e3 100644 --- a/trunk/arch/alpha/include/asm/uaccess.h +++ b/trunk/arch/alpha/include/asm/uaccess.h @@ -433,12 +433,36 @@ clear_user(void __user *to, long len) #undef __module_address #undef __module_call -#define user_addr_max() \ - (segment_eq(get_fs(), USER_DS) ? TASK_SIZE : ~0UL) +/* Returns: -EFAULT if exception before terminator, N if the entire + buffer filled, else strlen. */ -extern long strncpy_from_user(char *dest, const char __user *src, long count); -extern __must_check long strlen_user(const char __user *str); -extern __must_check long strnlen_user(const char __user *str, long n); +extern long __strncpy_from_user(char *__to, const char __user *__from, long __to_len); + +extern inline long +strncpy_from_user(char *to, const char __user *from, long n) +{ + long ret = -EFAULT; + if (__access_ok((unsigned long)from, 0, get_fs())) + ret = __strncpy_from_user(to, from, n); + return ret; +} + +/* Returns: 0 if bad, string length+1 (memory size) of string if ok */ +extern long __strlen_user(const char __user *); + +extern inline long strlen_user(const char __user *str) +{ + return access_ok(VERIFY_READ,str,0) ? __strlen_user(str) : 0; +} + +/* Returns: 0 if exception before NUL or reaching the supplied limit (N), + * a value greater than N if the limit would be exceeded, else strlen. */ +extern long __strnlen_user(const char __user *, long); + +extern inline long strnlen_user(const char __user *str, long n) +{ + return access_ok(VERIFY_READ,str,0) ? __strnlen_user(str, n) : 0; +} /* * About the exception table: diff --git a/trunk/arch/alpha/include/asm/unistd.h b/trunk/arch/alpha/include/asm/unistd.h index a31a78eac9b9..633b23b0664a 100644 --- a/trunk/arch/alpha/include/asm/unistd.h +++ b/trunk/arch/alpha/include/asm/unistd.h @@ -465,12 +465,10 @@ #define __NR_setns 501 #define __NR_accept4 502 #define __NR_sendmmsg 503 -#define __NR_process_vm_readv 504 -#define __NR_process_vm_writev 505 #ifdef __KERNEL__ -#define NR_SYSCALLS 506 +#define NR_SYSCALLS 504 #define __ARCH_WANT_OLD_READDIR #define __ARCH_WANT_STAT64 diff --git a/trunk/arch/alpha/include/asm/word-at-a-time.h b/trunk/arch/alpha/include/asm/word-at-a-time.h deleted file mode 100644 index 6b340d0f1521..000000000000 --- a/trunk/arch/alpha/include/asm/word-at-a-time.h +++ /dev/null @@ -1,55 +0,0 @@ -#ifndef _ASM_WORD_AT_A_TIME_H -#define _ASM_WORD_AT_A_TIME_H - -#include - -/* - * word-at-a-time interface for Alpha. - */ - -/* - * We do not use the word_at_a_time struct on Alpha, but it needs to be - * implemented to humour the generic code. - */ -struct word_at_a_time { - const unsigned long unused; -}; - -#define WORD_AT_A_TIME_CONSTANTS { 0 } - -/* Return nonzero if val has a zero */ -static inline unsigned long has_zero(unsigned long val, unsigned long *bits, const struct word_at_a_time *c) -{ - unsigned long zero_locations = __kernel_cmpbge(0, val); - *bits = zero_locations; - return zero_locations; -} - -static inline unsigned long prep_zero_mask(unsigned long val, unsigned long bits, const struct word_at_a_time *c) -{ - return bits; -} - -#define create_zero_mask(bits) (bits) - -static inline unsigned long find_zero(unsigned long bits) -{ -#if defined(CONFIG_ALPHA_EV6) && defined(CONFIG_ALPHA_EV67) - /* Simple if have CIX instructions */ - return __kernel_cttz(bits); -#else - unsigned long t1, t2, t3; - /* Retain lowest set bit only */ - bits &= -bits; - /* Binary search for lowest set bit */ - t1 = bits & 0xf0; - t2 = bits & 0xcc; - t3 = bits & 0xaa; - if (t1) t1 = 4; - if (t2) t2 = 2; - if (t3) t3 = 1; - return t1 + t2 + t3; -#endif -} - -#endif /* _ASM_WORD_AT_A_TIME_H */ diff --git a/trunk/arch/alpha/kernel/alpha_ksyms.c b/trunk/arch/alpha/kernel/alpha_ksyms.c index 15fa821d09cd..d96e742d4dc2 100644 --- a/trunk/arch/alpha/kernel/alpha_ksyms.c +++ b/trunk/arch/alpha/kernel/alpha_ksyms.c @@ -52,6 +52,7 @@ EXPORT_SYMBOL(alpha_write_fp_reg_s); /* entry.S */ EXPORT_SYMBOL(kernel_thread); +EXPORT_SYMBOL(kernel_execve); /* Networking helper routines. */ EXPORT_SYMBOL(csum_tcpudp_magic); @@ -73,6 +74,8 @@ EXPORT_SYMBOL(alpha_fp_emul); */ EXPORT_SYMBOL(__copy_user); EXPORT_SYMBOL(__do_clear_user); +EXPORT_SYMBOL(__strncpy_from_user); +EXPORT_SYMBOL(__strnlen_user); /* * SMP-specific symbols. diff --git a/trunk/arch/alpha/kernel/entry.S b/trunk/arch/alpha/kernel/entry.S index ec0da0567ab5..6d159cee5f2f 100644 --- a/trunk/arch/alpha/kernel/entry.S +++ b/trunk/arch/alpha/kernel/entry.S @@ -663,6 +663,58 @@ kernel_thread: br ret_to_kernel .end kernel_thread +/* + * kernel_execve(path, argv, envp) + */ + .align 4 + .globl kernel_execve + .ent kernel_execve +kernel_execve: + /* We can be called from a module. */ + ldgp $gp, 0($27) + lda $sp, -(32+SIZEOF_PT_REGS+8)($sp) + .frame $sp, 32+SIZEOF_PT_REGS+8, $26, 0 + stq $26, 0($sp) + stq $16, 8($sp) + stq $17, 16($sp) + stq $18, 24($sp) + .prologue 1 + + lda $16, 32($sp) + lda $17, 0 + lda $18, SIZEOF_PT_REGS + bsr $26, memset !samegp + + /* Avoid the HAE being gratuitously wrong, which would cause us + to do the whole turn off interrupts thing and restore it. */ + ldq $2, alpha_mv+HAE_CACHE + stq $2, 152+32($sp) + + ldq $16, 8($sp) + ldq $17, 16($sp) + ldq $18, 24($sp) + lda $19, 32($sp) + bsr $26, do_execve !samegp + + ldq $26, 0($sp) + bne $0, 1f /* error! */ + + /* Move the temporary pt_regs struct from its current location + to the top of the kernel stack frame. See copy_thread for + details for a normal process. */ + lda $16, 0x4000 - SIZEOF_PT_REGS($8) + lda $17, 32($sp) + lda $18, SIZEOF_PT_REGS + bsr $26, memmove !samegp + + /* Take that over as our new stack frame and visit userland! */ + lda $sp, 0x4000 - SIZEOF_PT_REGS($8) + br $31, ret_from_sys_call + +1: lda $sp, 32+SIZEOF_PT_REGS+8($sp) + ret +.end kernel_execve + /* * Special system calls. Most of these are special in that they either @@ -744,6 +796,115 @@ sys_rt_sigreturn: br ret_from_sys_call .end sys_rt_sigreturn + .align 4 + .globl sys_sethae + .ent sys_sethae +sys_sethae: + .prologue 0 + stq $16, 152($sp) + ret +.end sys_sethae + + .align 4 + .globl osf_getpriority + .ent osf_getpriority +osf_getpriority: + lda $sp, -16($sp) + stq $26, 0($sp) + .prologue 0 + + jsr $26, sys_getpriority + + ldq $26, 0($sp) + blt $0, 1f + + /* Return value is the unbiased priority, i.e. 20 - prio. + This does result in negative return values, so signal + no error by writing into the R0 slot. */ + lda $1, 20 + stq $31, 16($sp) + subl $1, $0, $0 + unop + +1: lda $sp, 16($sp) + ret +.end osf_getpriority + + .align 4 + .globl sys_getxuid + .ent sys_getxuid +sys_getxuid: + .prologue 0 + ldq $2, TI_TASK($8) + ldq $3, TASK_CRED($2) + ldl $0, CRED_UID($3) + ldl $1, CRED_EUID($3) + stq $1, 80($sp) + ret +.end sys_getxuid + + .align 4 + .globl sys_getxgid + .ent sys_getxgid +sys_getxgid: + .prologue 0 + ldq $2, TI_TASK($8) + ldq $3, TASK_CRED($2) + ldl $0, CRED_GID($3) + ldl $1, CRED_EGID($3) + stq $1, 80($sp) + ret +.end sys_getxgid + + .align 4 + .globl sys_getxpid + .ent sys_getxpid +sys_getxpid: + .prologue 0 + ldq $2, TI_TASK($8) + + /* See linux/kernel/timer.c sys_getppid for discussion + about this loop. */ + ldq $3, TASK_GROUP_LEADER($2) + ldq $4, TASK_REAL_PARENT($3) + ldl $0, TASK_TGID($2) +1: ldl $1, TASK_TGID($4) +#ifdef CONFIG_SMP + mov $4, $5 + mb + ldq $3, TASK_GROUP_LEADER($2) + ldq $4, TASK_REAL_PARENT($3) + cmpeq $4, $5, $5 + beq $5, 1b +#endif + stq $1, 80($sp) + ret +.end sys_getxpid + + .align 4 + .globl sys_alpha_pipe + .ent sys_alpha_pipe +sys_alpha_pipe: + lda $sp, -16($sp) + stq $26, 0($sp) + .prologue 0 + + mov $31, $17 + lda $16, 8($sp) + jsr $26, do_pipe_flags + + ldq $26, 0($sp) + bne $0, 1f + + /* The return values are in $0 and $20. */ + ldl $1, 12($sp) + ldl $0, 8($sp) + + stq $1, 80+16($sp) +1: lda $sp, 16($sp) + ret +.end sys_alpha_pipe + .align 4 .globl sys_execve .ent sys_execve diff --git a/trunk/arch/alpha/kernel/osf_sys.c b/trunk/arch/alpha/kernel/osf_sys.c index bc1acdda7a5e..98a103621af6 100644 --- a/trunk/arch/alpha/kernel/osf_sys.c +++ b/trunk/arch/alpha/kernel/osf_sys.c @@ -1404,52 +1404,3 @@ SYSCALL_DEFINE3(osf_writev, unsigned long, fd, } #endif - -SYSCALL_DEFINE2(osf_getpriority, int, which, int, who) -{ - int prio = sys_getpriority(which, who); - if (prio >= 0) { - /* Return value is the unbiased priority, i.e. 20 - prio. - This does result in negative return values, so signal - no error */ - force_successful_syscall_return(); - prio = 20 - prio; - } - return prio; -} - -SYSCALL_DEFINE0(getxuid) -{ - current_pt_regs()->r20 = sys_geteuid(); - return sys_getuid(); -} - -SYSCALL_DEFINE0(getxgid) -{ - current_pt_regs()->r20 = sys_getegid(); - return sys_getgid(); -} - -SYSCALL_DEFINE0(getxpid) -{ - current_pt_regs()->r20 = sys_getppid(); - return sys_getpid(); -} - -SYSCALL_DEFINE0(alpha_pipe) -{ - int fd[2]; - int res = do_pipe_flags(fd, 0); - if (!res) { - /* The return values are in $0 and $20. */ - current_pt_regs()->r20 = fd[1]; - res = fd[0]; - } - return res; -} - -SYSCALL_DEFINE1(sethae, unsigned long, val) -{ - current_pt_regs()->hae = val; - return 0; -} diff --git a/trunk/arch/alpha/kernel/pci.c b/trunk/arch/alpha/kernel/pci.c index ef757147cbf9..9816d5a4d176 100644 --- a/trunk/arch/alpha/kernel/pci.c +++ b/trunk/arch/alpha/kernel/pci.c @@ -256,6 +256,12 @@ pcibios_fixup_bus(struct pci_bus *bus) } } +void __init +pcibios_update_irq(struct pci_dev *dev, int irq) +{ + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq); +} + int pcibios_enable_device(struct pci_dev *dev, int mask) { diff --git a/trunk/arch/alpha/kernel/process.c b/trunk/arch/alpha/kernel/process.c index 83638aa096d5..153d3fce3e8e 100644 --- a/trunk/arch/alpha/kernel/process.c +++ b/trunk/arch/alpha/kernel/process.c @@ -28,7 +28,6 @@ #include #include #include -#include #include #include @@ -55,12 +54,9 @@ cpu_idle(void) /* FIXME -- EV6 and LCA45 know how to power down the CPU. */ - rcu_idle_enter(); while (!need_resched()) cpu_relax(); - - rcu_idle_exit(); - schedule_preempt_disabled(); + schedule(); } } @@ -459,22 +455,3 @@ get_wchan(struct task_struct *p) } return pc; } - -int kernel_execve(const char *path, const char *const argv[], const char *const envp[]) -{ - /* Avoid the HAE being gratuitously wrong, which would cause us - to do the whole turn off interrupts thing and restore it. */ - struct pt_regs regs = {.hae = alpha_mv.hae_cache}; - int err = do_execve(path, argv, envp, ®s); - if (!err) { - struct pt_regs *p = current_pt_regs(); - /* copy regs to normal position and off to userland we go... */ - *p = regs; - __asm__ __volatile__ ( - "mov %0, $sp;" - "br $31, ret_from_sys_call" - : : "r"(p)); - } - return err; -} -EXPORT_SYMBOL(kernel_execve); diff --git a/trunk/arch/alpha/kernel/smp.c b/trunk/arch/alpha/kernel/smp.c index a41ad90a97a6..35ddc02bfa4a 100644 --- a/trunk/arch/alpha/kernel/smp.c +++ b/trunk/arch/alpha/kernel/smp.c @@ -166,7 +166,6 @@ smp_callin(void) DBGS(("smp_callin: commencing CPU %d current %p active_mm %p\n", cpuid, current, current->active_mm)); - preempt_disable(); /* Do nothing. */ cpu_idle(); } diff --git a/trunk/arch/alpha/kernel/srmcons.c b/trunk/arch/alpha/kernel/srmcons.c index 5d5865204a1d..3ea809430eda 100644 --- a/trunk/arch/alpha/kernel/srmcons.c +++ b/trunk/arch/alpha/kernel/srmcons.c @@ -223,7 +223,6 @@ srmcons_init(void) driver->subtype = SYSTEM_TYPE_SYSCONS; driver->init_termios = tty_std_termios; tty_set_operations(driver, &srmcons_ops); - tty_port_link_device(&srmcons_singleton.port, driver, 0); err = tty_register_driver(driver); if (err) { put_tty_driver(driver); diff --git a/trunk/arch/alpha/kernel/systbls.S b/trunk/arch/alpha/kernel/systbls.S index 2ac6b45c3e00..87835235f114 100644 --- a/trunk/arch/alpha/kernel/systbls.S +++ b/trunk/arch/alpha/kernel/systbls.S @@ -111,7 +111,7 @@ sys_call_table: .quad sys_socket .quad sys_connect .quad sys_accept - .quad sys_osf_getpriority /* 100 */ + .quad osf_getpriority /* 100 */ .quad sys_send .quad sys_recv .quad sys_sigreturn @@ -522,8 +522,6 @@ sys_call_table: .quad sys_setns .quad sys_accept4 .quad sys_sendmmsg - .quad sys_process_vm_readv - .quad sys_process_vm_writev /* 505 */ .size sys_call_table, . - sys_call_table .type sys_call_table, @object diff --git a/trunk/arch/alpha/lib/Makefile b/trunk/arch/alpha/lib/Makefile index 59660743237c..c0a83ab62b78 100644 --- a/trunk/arch/alpha/lib/Makefile +++ b/trunk/arch/alpha/lib/Makefile @@ -31,6 +31,8 @@ lib-y = __divqu.o __remqu.o __divlu.o __remlu.o \ $(ev6-y)memchr.o \ $(ev6-y)copy_user.o \ $(ev6-y)clear_user.o \ + $(ev6-y)strncpy_from_user.o \ + $(ev67-y)strlen_user.o \ $(ev6-y)csum_ipv6_magic.o \ $(ev6-y)clear_page.o \ $(ev6-y)copy_page.o \ diff --git a/trunk/arch/alpha/lib/ev6-strncpy_from_user.S b/trunk/arch/alpha/lib/ev6-strncpy_from_user.S new file mode 100644 index 000000000000..d2e28178cacc --- /dev/null +++ b/trunk/arch/alpha/lib/ev6-strncpy_from_user.S @@ -0,0 +1,424 @@ +/* + * arch/alpha/lib/ev6-strncpy_from_user.S + * 21264 version contributed by Rick Gorton + * + * Just like strncpy except in the return value: + * + * -EFAULT if an exception occurs before the terminator is copied. + * N if the buffer filled. + * + * Otherwise the length of the string is returned. + * + * Much of the information about 21264 scheduling/coding comes from: + * Compiler Writer's Guide for the Alpha 21264 + * abbreviated as 'CWG' in other comments here + * ftp.digital.com/pub/Digital/info/semiconductor/literature/dsc-library.html + * Scheduling notation: + * E - either cluster + * U - upper subcluster; U0 - subcluster U0; U1 - subcluster U1 + * L - lower subcluster; L0 - subcluster L0; L1 - subcluster L1 + * A bunch of instructions got moved and temp registers were changed + * to aid in scheduling. Control flow was also re-arranged to eliminate + * branches, and to provide longer code sequences to enable better scheduling. + * A total rewrite (using byte load/stores for start & tail sequences) + * is desirable, but very difficult to do without a from-scratch rewrite. + * Save that for the future. + */ + + +#include +#include + + +/* Allow an exception for an insn; exit if we get one. */ +#define EX(x,y...) \ + 99: x,##y; \ + .section __ex_table,"a"; \ + .long 99b - .; \ + lda $31, $exception-99b($0); \ + .previous + + + .set noat + .set noreorder + .text + + .globl __strncpy_from_user + .ent __strncpy_from_user + .frame $30, 0, $26 + .prologue 0 + + .align 4 +__strncpy_from_user: + and a0, 7, t3 # E : find dest misalignment + beq a2, $zerolength # U : + + /* Are source and destination co-aligned? */ + mov a0, v0 # E : save the string start + xor a0, a1, t4 # E : + EX( ldq_u t1, 0(a1) ) # L : Latency=3 load first quadword + ldq_u t0, 0(a0) # L : load first (partial) aligned dest quadword + + addq a2, t3, a2 # E : bias count by dest misalignment + subq a2, 1, a3 # E : + addq zero, 1, t10 # E : + and t4, 7, t4 # E : misalignment between the two + + and a3, 7, t6 # E : number of tail bytes + sll t10, t6, t10 # E : t10 = bitmask of last count byte + bne t4, $unaligned # U : + lda t2, -1 # E : build a mask against false zero + + /* + * We are co-aligned; take care of a partial first word. + * On entry to this basic block: + * t0 == the first destination word for masking back in + * t1 == the first source word. + */ + + srl a3, 3, a2 # E : a2 = loop counter = (count - 1)/8 + addq a1, 8, a1 # E : + mskqh t2, a1, t2 # U : detection in the src word + nop + + /* Create the 1st output word and detect 0's in the 1st input word. */ + mskqh t1, a1, t3 # U : + mskql t0, a1, t0 # U : assemble the first output word + ornot t1, t2, t2 # E : + nop + + cmpbge zero, t2, t8 # E : bits set iff null found + or t0, t3, t0 # E : + beq a2, $a_eoc # U : + bne t8, $a_eos # U : 2nd branch in a quad. Bad. + + /* On entry to this basic block: + * t0 == a source quad not containing a null. + * a0 - current aligned destination address + * a1 - current aligned source address + * a2 - count of quadwords to move. + * NOTE: Loop improvement - unrolling this is going to be + * a huge win, since we're going to stall otherwise. + * Fix this later. For _really_ large copies, look + * at using wh64 on a look-ahead basis. See the code + * in clear_user.S and copy_user.S. + * Presumably, since (a0) and (a1) do not overlap (by C definition) + * Lots of nops here: + * - Separate loads from stores + * - Keep it to 1 branch/quadpack so the branch predictor + * can train. + */ +$a_loop: + stq_u t0, 0(a0) # L : + addq a0, 8, a0 # E : + nop + subq a2, 1, a2 # E : + + EX( ldq_u t0, 0(a1) ) # L : + addq a1, 8, a1 # E : + cmpbge zero, t0, t8 # E : Stall 2 cycles on t0 + beq a2, $a_eoc # U : + + beq t8, $a_loop # U : + nop + nop + nop + + /* Take care of the final (partial) word store. At this point + * the end-of-count bit is set in t8 iff it applies. + * + * On entry to this basic block we have: + * t0 == the source word containing the null + * t8 == the cmpbge mask that found it. + */ +$a_eos: + negq t8, t12 # E : find low bit set + and t8, t12, t12 # E : + + /* We're doing a partial word store and so need to combine + our source and original destination words. */ + ldq_u t1, 0(a0) # L : + subq t12, 1, t6 # E : + + or t12, t6, t8 # E : + zapnot t0, t8, t0 # U : clear src bytes > null + zap t1, t8, t1 # U : clear dst bytes <= null + or t0, t1, t0 # E : + + stq_u t0, 0(a0) # L : + br $finish_up # L0 : + nop + nop + + /* Add the end-of-count bit to the eos detection bitmask. */ + .align 4 +$a_eoc: + or t10, t8, t8 + br $a_eos + nop + nop + + +/* The source and destination are not co-aligned. Align the destination + and cope. We have to be very careful about not reading too much and + causing a SEGV. */ + + .align 4 +$u_head: + /* We know just enough now to be able to assemble the first + full source word. We can still find a zero at the end of it + that prevents us from outputting the whole thing. + + On entry to this basic block: + t0 == the first dest word, unmasked + t1 == the shifted low bits of the first source word + t6 == bytemask that is -1 in dest word bytes */ + + EX( ldq_u t2, 8(a1) ) # L : load second src word + addq a1, 8, a1 # E : + mskql t0, a0, t0 # U : mask trailing garbage in dst + extqh t2, a1, t4 # U : + + or t1, t4, t1 # E : first aligned src word complete + mskqh t1, a0, t1 # U : mask leading garbage in src + or t0, t1, t0 # E : first output word complete + or t0, t6, t6 # E : mask original data for zero test + + cmpbge zero, t6, t8 # E : + beq a2, $u_eocfin # U : + bne t8, $u_final # U : bad news - 2nd branch in a quad + lda t6, -1 # E : mask out the bits we have + + mskql t6, a1, t6 # U : already seen + stq_u t0, 0(a0) # L : store first output word + or t6, t2, t2 # E : + cmpbge zero, t2, t8 # E : find nulls in second partial + + addq a0, 8, a0 # E : + subq a2, 1, a2 # E : + bne t8, $u_late_head_exit # U : + nop + + /* Finally, we've got all the stupid leading edge cases taken care + of and we can set up to enter the main loop. */ + + extql t2, a1, t1 # U : position hi-bits of lo word + EX( ldq_u t2, 8(a1) ) # L : read next high-order source word + addq a1, 8, a1 # E : + cmpbge zero, t2, t8 # E : + + beq a2, $u_eoc # U : + bne t8, $u_eos # U : + nop + nop + + /* Unaligned copy main loop. In order to avoid reading too much, + the loop is structured to detect zeros in aligned source words. + This has, unfortunately, effectively pulled half of a loop + iteration out into the head and half into the tail, but it does + prevent nastiness from accumulating in the very thing we want + to run as fast as possible. + + On entry to this basic block: + t1 == the shifted high-order bits from the previous source word + t2 == the unshifted current source word + + We further know that t2 does not contain a null terminator. */ + + /* + * Extra nops here: + * separate load quads from store quads + * only one branch/quad to permit predictor training + */ + + .align 4 +$u_loop: + extqh t2, a1, t0 # U : extract high bits for current word + addq a1, 8, a1 # E : + extql t2, a1, t3 # U : extract low bits for next time + addq a0, 8, a0 # E : + + or t0, t1, t0 # E : current dst word now complete + EX( ldq_u t2, 0(a1) ) # L : load high word for next time + subq a2, 1, a2 # E : + nop + + stq_u t0, -8(a0) # L : save the current word + mov t3, t1 # E : + cmpbge zero, t2, t8 # E : test new word for eos + beq a2, $u_eoc # U : + + beq t8, $u_loop # U : + nop + nop + nop + + /* We've found a zero somewhere in the source word we just read. + If it resides in the lower half, we have one (probably partial) + word to write out, and if it resides in the upper half, we + have one full and one partial word left to write out. + + On entry to this basic block: + t1 == the shifted high-order bits from the previous source word + t2 == the unshifted current source word. */ + .align 4 +$u_eos: + extqh t2, a1, t0 # U : + or t0, t1, t0 # E : first (partial) source word complete + cmpbge zero, t0, t8 # E : is the null in this first bit? + nop + + bne t8, $u_final # U : + stq_u t0, 0(a0) # L : the null was in the high-order bits + addq a0, 8, a0 # E : + subq a2, 1, a2 # E : + + .align 4 +$u_late_head_exit: + extql t2, a1, t0 # U : + cmpbge zero, t0, t8 # E : + or t8, t10, t6 # E : + cmoveq a2, t6, t8 # E : + + /* Take care of a final (probably partial) result word. + On entry to this basic block: + t0 == assembled source word + t8 == cmpbge mask that found the null. */ + .align 4 +$u_final: + negq t8, t6 # E : isolate low bit set + and t6, t8, t12 # E : + ldq_u t1, 0(a0) # L : + subq t12, 1, t6 # E : + + or t6, t12, t8 # E : + zapnot t0, t8, t0 # U : kill source bytes > null + zap t1, t8, t1 # U : kill dest bytes <= null + or t0, t1, t0 # E : + + stq_u t0, 0(a0) # E : + br $finish_up # U : + nop + nop + + .align 4 +$u_eoc: # end-of-count + extqh t2, a1, t0 # U : + or t0, t1, t0 # E : + cmpbge zero, t0, t8 # E : + nop + + .align 4 +$u_eocfin: # end-of-count, final word + or t10, t8, t8 # E : + br $u_final # U : + nop + nop + + /* Unaligned copy entry point. */ + .align 4 +$unaligned: + + srl a3, 3, a2 # U : a2 = loop counter = (count - 1)/8 + and a0, 7, t4 # E : find dest misalignment + and a1, 7, t5 # E : find src misalignment + mov zero, t0 # E : + + /* Conditionally load the first destination word and a bytemask + with 0xff indicating that the destination byte is sacrosanct. */ + + mov zero, t6 # E : + beq t4, 1f # U : + ldq_u t0, 0(a0) # L : + lda t6, -1 # E : + + mskql t6, a0, t6 # E : + nop + nop + nop + + .align 4 +1: + subq a1, t4, a1 # E : sub dest misalignment from src addr + /* If source misalignment is larger than dest misalignment, we need + extra startup checks to avoid SEGV. */ + cmplt t4, t5, t12 # E : + extql t1, a1, t1 # U : shift src into place + lda t2, -1 # E : for creating masks later + + beq t12, $u_head # U : + mskqh t2, t5, t2 # U : begin src byte validity mask + cmpbge zero, t1, t8 # E : is there a zero? + nop + + extql t2, a1, t2 # U : + or t8, t10, t5 # E : test for end-of-count too + cmpbge zero, t2, t3 # E : + cmoveq a2, t5, t8 # E : Latency=2, extra map slot + + nop # E : goes with cmov + andnot t8, t3, t8 # E : + beq t8, $u_head # U : + nop + + /* At this point we've found a zero in the first partial word of + the source. We need to isolate the valid source data and mask + it into the original destination data. (Incidentally, we know + that we'll need at least one byte of that original dest word.) */ + + ldq_u t0, 0(a0) # L : + negq t8, t6 # E : build bitmask of bytes <= zero + mskqh t1, t4, t1 # U : + and t6, t8, t12 # E : + + subq t12, 1, t6 # E : + or t6, t12, t8 # E : + zapnot t2, t8, t2 # U : prepare source word; mirror changes + zapnot t1, t8, t1 # U : to source validity mask + + andnot t0, t2, t0 # E : zero place for source to reside + or t0, t1, t0 # E : and put it there + stq_u t0, 0(a0) # L : + nop + + .align 4 +$finish_up: + zapnot t0, t12, t4 # U : was last byte written null? + and t12, 0xf0, t3 # E : binary search for the address of the + cmovne t4, 1, t4 # E : Latency=2, extra map slot + nop # E : with cmovne + + and t12, 0xcc, t2 # E : last byte written + and t12, 0xaa, t1 # E : + cmovne t3, 4, t3 # E : Latency=2, extra map slot + nop # E : with cmovne + + bic a0, 7, t0 + cmovne t2, 2, t2 # E : Latency=2, extra map slot + nop # E : with cmovne + nop + + cmovne t1, 1, t1 # E : Latency=2, extra map slot + nop # E : with cmovne + addq t0, t3, t0 # E : + addq t1, t2, t1 # E : + + addq t0, t1, t0 # E : + addq t0, t4, t0 # add one if we filled the buffer + subq t0, v0, v0 # find string length + ret # L0 : + + .align 4 +$zerolength: + nop + nop + nop + clr v0 + +$exception: + nop + nop + nop + ret + + .end __strncpy_from_user diff --git a/trunk/arch/alpha/lib/ev67-strlen_user.S b/trunk/arch/alpha/lib/ev67-strlen_user.S new file mode 100644 index 000000000000..57e0d77b81a6 --- /dev/null +++ b/trunk/arch/alpha/lib/ev67-strlen_user.S @@ -0,0 +1,107 @@ +/* + * arch/alpha/lib/ev67-strlen_user.S + * 21264 version contributed by Rick Gorton + * + * Return the length of the string including the NULL terminator + * (strlen+1) or zero if an error occurred. + * + * In places where it is critical to limit the processing time, + * and the data is not trusted, strnlen_user() should be used. + * It will return a value greater than its second argument if + * that limit would be exceeded. This implementation is allowed + * to access memory beyond the limit, but will not cross a page + * boundary when doing so. + * + * Much of the information about 21264 scheduling/coding comes from: + * Compiler Writer's Guide for the Alpha 21264 + * abbreviated as 'CWG' in other comments here + * ftp.digital.com/pub/Digital/info/semiconductor/literature/dsc-library.html + * Scheduling notation: + * E - either cluster + * U - upper subcluster; U0 - subcluster U0; U1 - subcluster U1 + * L - lower subcluster; L0 - subcluster L0; L1 - subcluster L1 + * Try not to change the actual algorithm if possible for consistency. + */ + +#include + + +/* Allow an exception for an insn; exit if we get one. */ +#define EX(x,y...) \ + 99: x,##y; \ + .section __ex_table,"a"; \ + .long 99b - .; \ + lda v0, $exception-99b(zero); \ + .previous + + + .set noreorder + .set noat + .text + + .globl __strlen_user + .ent __strlen_user + .frame sp, 0, ra + + .align 4 +__strlen_user: + ldah a1, 32767(zero) # do not use plain strlen_user() for strings + # that might be almost 2 GB long; you should + # be using strnlen_user() instead + nop + nop + nop + + .globl __strnlen_user + + .align 4 +__strnlen_user: + .prologue 0 + EX( ldq_u t0, 0(a0) ) # L : load first quadword (a0 may be misaligned) + lda t1, -1(zero) # E : + + insqh t1, a0, t1 # U : + andnot a0, 7, v0 # E : + or t1, t0, t0 # E : + subq a0, 1, a0 # E : get our +1 for the return + + cmpbge zero, t0, t1 # E : t1 <- bitmask: bit i == 1 <==> i-th byte == 0 + subq a1, 7, t2 # E : + subq a0, v0, t0 # E : + bne t1, $found # U : + + addq t2, t0, t2 # E : + addq a1, 1, a1 # E : + nop # E : + nop # E : + + .align 4 +$loop: ble t2, $limit # U : + EX( ldq t0, 8(v0) ) # L : + nop # E : + nop # E : + + cmpbge zero, t0, t1 # E : + subq t2, 8, t2 # E : + addq v0, 8, v0 # E : addr += 8 + beq t1, $loop # U : + +$found: cttz t1, t2 # U0 : + addq v0, t2, v0 # E : + subq v0, a0, v0 # E : + ret # L0 : + +$exception: + nop + nop + nop + ret + + .align 4 # currently redundant +$limit: + nop + nop + subq a1, t2, v0 + ret + + .end __strlen_user diff --git a/trunk/arch/alpha/lib/strlen_user.S b/trunk/arch/alpha/lib/strlen_user.S new file mode 100644 index 000000000000..508a18e96479 --- /dev/null +++ b/trunk/arch/alpha/lib/strlen_user.S @@ -0,0 +1,91 @@ +/* + * arch/alpha/lib/strlen_user.S + * + * Return the length of the string including the NUL terminator + * (strlen+1) or zero if an error occurred. + * + * In places where it is critical to limit the processing time, + * and the data is not trusted, strnlen_user() should be used. + * It will return a value greater than its second argument if + * that limit would be exceeded. This implementation is allowed + * to access memory beyond the limit, but will not cross a page + * boundary when doing so. + */ + +#include + + +/* Allow an exception for an insn; exit if we get one. */ +#define EX(x,y...) \ + 99: x,##y; \ + .section __ex_table,"a"; \ + .long 99b - .; \ + lda v0, $exception-99b(zero); \ + .previous + + + .set noreorder + .set noat + .text + + .globl __strlen_user + .ent __strlen_user + .frame sp, 0, ra + + .align 3 +__strlen_user: + ldah a1, 32767(zero) # do not use plain strlen_user() for strings + # that might be almost 2 GB long; you should + # be using strnlen_user() instead + + .globl __strnlen_user + + .align 3 +__strnlen_user: + .prologue 0 + + EX( ldq_u t0, 0(a0) ) # load first quadword (a0 may be misaligned) + lda t1, -1(zero) + insqh t1, a0, t1 + andnot a0, 7, v0 + or t1, t0, t0 + subq a0, 1, a0 # get our +1 for the return + cmpbge zero, t0, t1 # t1 <- bitmask: bit i == 1 <==> i-th byte == 0 + subq a1, 7, t2 + subq a0, v0, t0 + bne t1, $found + + addq t2, t0, t2 + addq a1, 1, a1 + + .align 3 +$loop: ble t2, $limit + EX( ldq t0, 8(v0) ) + subq t2, 8, t2 + addq v0, 8, v0 # addr += 8 + cmpbge zero, t0, t1 + beq t1, $loop + +$found: negq t1, t2 # clear all but least set bit + and t1, t2, t1 + + and t1, 0xf0, t2 # binary search for that set bit + and t1, 0xcc, t3 + and t1, 0xaa, t4 + cmovne t2, 4, t2 + cmovne t3, 2, t3 + cmovne t4, 1, t4 + addq t2, t3, t2 + addq v0, t4, v0 + addq v0, t2, v0 + nop # dual issue next two on ev4 and ev5 + subq v0, a0, v0 +$exception: + ret + + .align 3 # currently redundant +$limit: + subq a1, t2, v0 + ret + + .end __strlen_user diff --git a/trunk/arch/alpha/lib/strncpy_from_user.S b/trunk/arch/alpha/lib/strncpy_from_user.S new file mode 100644 index 000000000000..73ee21160ff7 --- /dev/null +++ b/trunk/arch/alpha/lib/strncpy_from_user.S @@ -0,0 +1,339 @@ +/* + * arch/alpha/lib/strncpy_from_user.S + * Contributed by Richard Henderson (rth@tamu.edu) + * + * Just like strncpy except in the return value: + * + * -EFAULT if an exception occurs before the terminator is copied. + * N if the buffer filled. + * + * Otherwise the length of the string is returned. + */ + + +#include +#include + + +/* Allow an exception for an insn; exit if we get one. */ +#define EX(x,y...) \ + 99: x,##y; \ + .section __ex_table,"a"; \ + .long 99b - .; \ + lda $31, $exception-99b($0); \ + .previous + + + .set noat + .set noreorder + .text + + .globl __strncpy_from_user + .ent __strncpy_from_user + .frame $30, 0, $26 + .prologue 0 + + .align 3 +$aligned: + /* On entry to this basic block: + t0 == the first destination word for masking back in + t1 == the first source word. */ + + /* Create the 1st output word and detect 0's in the 1st input word. */ + lda t2, -1 # e1 : build a mask against false zero + mskqh t2, a1, t2 # e0 : detection in the src word + mskqh t1, a1, t3 # e0 : + ornot t1, t2, t2 # .. e1 : + mskql t0, a1, t0 # e0 : assemble the first output word + cmpbge zero, t2, t8 # .. e1 : bits set iff null found + or t0, t3, t0 # e0 : + beq a2, $a_eoc # .. e1 : + bne t8, $a_eos # .. e1 : + + /* On entry to this basic block: + t0 == a source word not containing a null. */ + +$a_loop: + stq_u t0, 0(a0) # e0 : + addq a0, 8, a0 # .. e1 : + EX( ldq_u t0, 0(a1) ) # e0 : + addq a1, 8, a1 # .. e1 : + subq a2, 1, a2 # e0 : + cmpbge zero, t0, t8 # .. e1 (stall) + beq a2, $a_eoc # e1 : + beq t8, $a_loop # e1 : + + /* Take care of the final (partial) word store. At this point + the end-of-count bit is set in t8 iff it applies. + + On entry to this basic block we have: + t0 == the source word containing the null + t8 == the cmpbge mask that found it. */ + +$a_eos: + negq t8, t12 # e0 : find low bit set + and t8, t12, t12 # e1 (stall) + + /* For the sake of the cache, don't read a destination word + if we're not going to need it. */ + and t12, 0x80, t6 # e0 : + bne t6, 1f # .. e1 (zdb) + + /* We're doing a partial word store and so need to combine + our source and original destination words. */ + ldq_u t1, 0(a0) # e0 : + subq t12, 1, t6 # .. e1 : + or t12, t6, t8 # e0 : + unop # + zapnot t0, t8, t0 # e0 : clear src bytes > null + zap t1, t8, t1 # .. e1 : clear dst bytes <= null + or t0, t1, t0 # e1 : + +1: stq_u t0, 0(a0) + br $finish_up + + /* Add the end-of-count bit to the eos detection bitmask. */ +$a_eoc: + or t10, t8, t8 + br $a_eos + + /*** The Function Entry Point ***/ + .align 3 +__strncpy_from_user: + mov a0, v0 # save the string start + beq a2, $zerolength + + /* Are source and destination co-aligned? */ + xor a0, a1, t1 # e0 : + and a0, 7, t0 # .. e1 : find dest misalignment + and t1, 7, t1 # e0 : + addq a2, t0, a2 # .. e1 : bias count by dest misalignment + subq a2, 1, a2 # e0 : + and a2, 7, t2 # e1 : + srl a2, 3, a2 # e0 : a2 = loop counter = (count - 1)/8 + addq zero, 1, t10 # .. e1 : + sll t10, t2, t10 # e0 : t10 = bitmask of last count byte + bne t1, $unaligned # .. e1 : + + /* We are co-aligned; take care of a partial first word. */ + + EX( ldq_u t1, 0(a1) ) # e0 : load first src word + addq a1, 8, a1 # .. e1 : + + beq t0, $aligned # avoid loading dest word if not needed + ldq_u t0, 0(a0) # e0 : + br $aligned # .. e1 : + + +/* The source and destination are not co-aligned. Align the destination + and cope. We have to be very careful about not reading too much and + causing a SEGV. */ + + .align 3 +$u_head: + /* We know just enough now to be able to assemble the first + full source word. We can still find a zero at the end of it + that prevents us from outputting the whole thing. + + On entry to this basic block: + t0 == the first dest word, unmasked + t1 == the shifted low bits of the first source word + t6 == bytemask that is -1 in dest word bytes */ + + EX( ldq_u t2, 8(a1) ) # e0 : load second src word + addq a1, 8, a1 # .. e1 : + mskql t0, a0, t0 # e0 : mask trailing garbage in dst + extqh t2, a1, t4 # e0 : + or t1, t4, t1 # e1 : first aligned src word complete + mskqh t1, a0, t1 # e0 : mask leading garbage in src + or t0, t1, t0 # e0 : first output word complete + or t0, t6, t6 # e1 : mask original data for zero test + cmpbge zero, t6, t8 # e0 : + beq a2, $u_eocfin # .. e1 : + bne t8, $u_final # e1 : + + lda t6, -1 # e1 : mask out the bits we have + mskql t6, a1, t6 # e0 : already seen + stq_u t0, 0(a0) # e0 : store first output word + or t6, t2, t2 # .. e1 : + cmpbge zero, t2, t8 # e0 : find nulls in second partial + addq a0, 8, a0 # .. e1 : + subq a2, 1, a2 # e0 : + bne t8, $u_late_head_exit # .. e1 : + + /* Finally, we've got all the stupid leading edge cases taken care + of and we can set up to enter the main loop. */ + + extql t2, a1, t1 # e0 : position hi-bits of lo word + EX( ldq_u t2, 8(a1) ) # .. e1 : read next high-order source word + addq a1, 8, a1 # e0 : + cmpbge zero, t2, t8 # e1 (stall) + beq a2, $u_eoc # e1 : + bne t8, $u_eos # e1 : + + /* Unaligned copy main loop. In order to avoid reading too much, + the loop is structured to detect zeros in aligned source words. + This has, unfortunately, effectively pulled half of a loop + iteration out into the head and half into the tail, but it does + prevent nastiness from accumulating in the very thing we want + to run as fast as possible. + + On entry to this basic block: + t1 == the shifted high-order bits from the previous source word + t2 == the unshifted current source word + + We further know that t2 does not contain a null terminator. */ + + .align 3 +$u_loop: + extqh t2, a1, t0 # e0 : extract high bits for current word + addq a1, 8, a1 # .. e1 : + extql t2, a1, t3 # e0 : extract low bits for next time + addq a0, 8, a0 # .. e1 : + or t0, t1, t0 # e0 : current dst word now complete + EX( ldq_u t2, 0(a1) ) # .. e1 : load high word for next time + stq_u t0, -8(a0) # e0 : save the current word + mov t3, t1 # .. e1 : + subq a2, 1, a2 # e0 : + cmpbge zero, t2, t8 # .. e1 : test new word for eos + beq a2, $u_eoc # e1 : + beq t8, $u_loop # e1 : + + /* We've found a zero somewhere in the source word we just read. + If it resides in the lower half, we have one (probably partial) + word to write out, and if it resides in the upper half, we + have one full and one partial word left to write out. + + On entry to this basic block: + t1 == the shifted high-order bits from the previous source word + t2 == the unshifted current source word. */ +$u_eos: + extqh t2, a1, t0 # e0 : + or t0, t1, t0 # e1 : first (partial) source word complete + + cmpbge zero, t0, t8 # e0 : is the null in this first bit? + bne t8, $u_final # .. e1 (zdb) + + stq_u t0, 0(a0) # e0 : the null was in the high-order bits + addq a0, 8, a0 # .. e1 : + subq a2, 1, a2 # e1 : + +$u_late_head_exit: + extql t2, a1, t0 # .. e0 : + cmpbge zero, t0, t8 # e0 : + or t8, t10, t6 # e1 : + cmoveq a2, t6, t8 # e0 : + nop # .. e1 : + + /* Take care of a final (probably partial) result word. + On entry to this basic block: + t0 == assembled source word + t8 == cmpbge mask that found the null. */ +$u_final: + negq t8, t6 # e0 : isolate low bit set + and t6, t8, t12 # e1 : + + and t12, 0x80, t6 # e0 : avoid dest word load if we can + bne t6, 1f # .. e1 (zdb) + + ldq_u t1, 0(a0) # e0 : + subq t12, 1, t6 # .. e1 : + or t6, t12, t8 # e0 : + zapnot t0, t8, t0 # .. e1 : kill source bytes > null + zap t1, t8, t1 # e0 : kill dest bytes <= null + or t0, t1, t0 # e1 : + +1: stq_u t0, 0(a0) # e0 : + br $finish_up + +$u_eoc: # end-of-count + extqh t2, a1, t0 + or t0, t1, t0 + cmpbge zero, t0, t8 + +$u_eocfin: # end-of-count, final word + or t10, t8, t8 + br $u_final + + /* Unaligned copy entry point. */ + .align 3 +$unaligned: + + EX( ldq_u t1, 0(a1) ) # e0 : load first source word + + and a0, 7, t4 # .. e1 : find dest misalignment + and a1, 7, t5 # e0 : find src misalignment + + /* Conditionally load the first destination word and a bytemask + with 0xff indicating that the destination byte is sacrosanct. */ + + mov zero, t0 # .. e1 : + mov zero, t6 # e0 : + beq t4, 1f # .. e1 : + ldq_u t0, 0(a0) # e0 : + lda t6, -1 # .. e1 : + mskql t6, a0, t6 # e0 : +1: + subq a1, t4, a1 # .. e1 : sub dest misalignment from src addr + + /* If source misalignment is larger than dest misalignment, we need + extra startup checks to avoid SEGV. */ + + cmplt t4, t5, t12 # e1 : + extql t1, a1, t1 # .. e0 : shift src into place + lda t2, -1 # e0 : for creating masks later + beq t12, $u_head # e1 : + + mskqh t2, t5, t2 # e0 : begin src byte validity mask + cmpbge zero, t1, t8 # .. e1 : is there a zero? + extql t2, a1, t2 # e0 : + or t8, t10, t5 # .. e1 : test for end-of-count too + cmpbge zero, t2, t3 # e0 : + cmoveq a2, t5, t8 # .. e1 : + andnot t8, t3, t8 # e0 : + beq t8, $u_head # .. e1 (zdb) + + /* At this point we've found a zero in the first partial word of + the source. We need to isolate the valid source data and mask + it into the original destination data. (Incidentally, we know + that we'll need at least one byte of that original dest word.) */ + + ldq_u t0, 0(a0) # e0 : + negq t8, t6 # .. e1 : build bitmask of bytes <= zero + mskqh t1, t4, t1 # e0 : + and t6, t8, t12 # .. e1 : + subq t12, 1, t6 # e0 : + or t6, t12, t8 # e1 : + + zapnot t2, t8, t2 # e0 : prepare source word; mirror changes + zapnot t1, t8, t1 # .. e1 : to source validity mask + + andnot t0, t2, t0 # e0 : zero place for source to reside + or t0, t1, t0 # e1 : and put it there + stq_u t0, 0(a0) # e0 : + +$finish_up: + zapnot t0, t12, t4 # was last byte written null? + cmovne t4, 1, t4 + + and t12, 0xf0, t3 # binary search for the address of the + and t12, 0xcc, t2 # last byte written + and t12, 0xaa, t1 + bic a0, 7, t0 + cmovne t3, 4, t3 + cmovne t2, 2, t2 + cmovne t1, 1, t1 + addq t0, t3, t0 + addq t1, t2, t1 + addq t0, t1, t0 + addq t0, t4, t0 # add one if we filled the buffer + + subq t0, v0, v0 # find string length + ret + +$zerolength: + clr v0 +$exception: + ret + + .end __strncpy_from_user diff --git a/trunk/arch/alpha/mm/fault.c b/trunk/arch/alpha/mm/fault.c index 0c4132dd3507..5eecab1a84ef 100644 --- a/trunk/arch/alpha/mm/fault.c +++ b/trunk/arch/alpha/mm/fault.c @@ -89,8 +89,6 @@ do_page_fault(unsigned long address, unsigned long mmcsr, const struct exception_table_entry *fixup; int fault, si_code = SEGV_MAPERR; siginfo_t info; - unsigned int flags = (FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE | - (cause > 0 ? FAULT_FLAG_WRITE : 0)); /* As of EV6, a load into $31/$f31 is a prefetch, and never faults (or is suppressed by the PALcode). Support that for older CPUs @@ -116,7 +114,6 @@ do_page_fault(unsigned long address, unsigned long mmcsr, goto vmalloc_fault; #endif -retry: down_read(&mm->mmap_sem); vma = find_vma(mm, address); if (!vma) @@ -147,11 +144,8 @@ do_page_fault(unsigned long address, unsigned long mmcsr, /* If for any reason at all we couldn't handle the fault, make sure we exit gracefully rather than endlessly redo the fault. */ - fault = handle_mm_fault(mm, vma, address, flags); - - if ((fault & VM_FAULT_RETRY) && fatal_signal_pending(current)) - return; - + fault = handle_mm_fault(mm, vma, address, cause > 0 ? FAULT_FLAG_WRITE : 0); + up_read(&mm->mmap_sem); if (unlikely(fault & VM_FAULT_ERROR)) { if (fault & VM_FAULT_OOM) goto out_of_memory; @@ -159,26 +153,10 @@ do_page_fault(unsigned long address, unsigned long mmcsr, goto do_sigbus; BUG(); } - - if (flags & FAULT_FLAG_ALLOW_RETRY) { - if (fault & VM_FAULT_MAJOR) - current->maj_flt++; - else - current->min_flt++; - if (fault & VM_FAULT_RETRY) { - flags &= ~FAULT_FLAG_ALLOW_RETRY; - - /* No need to up_read(&mm->mmap_sem) as we would - * have already released it in __lock_page_or_retry - * in mm/filemap.c. - */ - - goto retry; - } - } - - up_read(&mm->mmap_sem); - + if (fault & VM_FAULT_MAJOR) + current->maj_flt++; + else + current->min_flt++; return; /* Something tried to access memory that isn't in our memory map. @@ -208,14 +186,12 @@ do_page_fault(unsigned long address, unsigned long mmcsr, /* We ran out of memory, or some other thing happened to us that made us unable to handle the page fault gracefully. */ out_of_memory: - up_read(&mm->mmap_sem); if (!user_mode(regs)) goto no_context; pagefault_out_of_memory(); return; do_sigbus: - up_read(&mm->mmap_sem); /* Send a sigbus, regardless of whether we were in kernel or user mode. */ info.si_signo = SIGBUS; diff --git a/trunk/arch/alpha/oprofile/common.c b/trunk/arch/alpha/oprofile/common.c index b8ce18f485d3..a0a5d27aa215 100644 --- a/trunk/arch/alpha/oprofile/common.c +++ b/trunk/arch/alpha/oprofile/common.c @@ -12,7 +12,6 @@ #include #include #include -#include #include "op_impl.h" diff --git a/trunk/arch/arm/Kconfig b/trunk/arch/arm/Kconfig index de325f4615bd..e91c7cdc6fe5 100644 --- a/trunk/arch/arm/Kconfig +++ b/trunk/arch/arm/Kconfig @@ -6,7 +6,7 @@ config ARM select HAVE_DMA_API_DEBUG select HAVE_IDE if PCI || ISA || PCMCIA select HAVE_DMA_ATTRS - select HAVE_DMA_CONTIGUOUS if MMU + select HAVE_DMA_CONTIGUOUS if (CPU_V6 || CPU_V6K || CPU_V7) select HAVE_MEMBLOCK select RTC_LIB select SYS_SUPPORTS_APM_EMULATION @@ -38,6 +38,7 @@ config ARM select HARDIRQS_SW_RESEND select GENERIC_IRQ_PROBE select GENERIC_IRQ_SHOW + select GENERIC_IRQ_PROBE select ARCH_WANT_IPC_PARSE_VERSION select HARDIRQS_SW_RESEND select CPU_PM if (SUSPEND || CPU_IDLE) @@ -125,6 +126,11 @@ config TRACE_IRQFLAGS_SUPPORT bool default y +config GENERIC_LOCKBREAK + bool + default y + depends on SMP && PREEMPT + config RWSEM_GENERIC_SPINLOCK bool default y @@ -273,7 +279,7 @@ config ARCH_INTEGRATOR select ARM_AMBA select ARCH_HAS_CPUFREQ select COMMON_CLK - select COMMON_CLK_VERSATILE + select CLK_VERSATILE select HAVE_TCM select ICST select GENERIC_CLOCKEVENTS @@ -289,12 +295,13 @@ config ARCH_INTEGRATOR config ARCH_REALVIEW bool "ARM Ltd. RealView family" select ARM_AMBA - select COMMON_CLK - select COMMON_CLK_VERSATILE + select CLKDEV_LOOKUP + select HAVE_MACH_CLKDEV select ICST select GENERIC_CLOCKEVENTS select ARCH_WANT_OPTIONAL_GPIOLIB select PLAT_VERSATILE + select PLAT_VERSATILE_CLOCK select PLAT_VERSATILE_CLCD select ARM_TIMER_SP804 select GPIO_PL061 if GPIOLIB @@ -412,7 +419,7 @@ config ARCH_PRIMA2 select NO_IOPORT select ARCH_REQUIRE_GPIOLIB select GENERIC_CLOCKEVENTS - select COMMON_CLK + select CLKDEV_LOOKUP select GENERIC_IRQ_CHIP select MIGHT_HAVE_CACHE_L2X0 select PINCTRL @@ -2143,7 +2150,6 @@ source "drivers/cpufreq/Kconfig" config CPU_FREQ_IMX tristate "CPUfreq driver for i.MX CPUs" depends on ARCH_MXC && CPU_FREQ - select CPU_FREQ_TABLE help This enables the CPUfreq driver for i.MX CPUs. diff --git a/trunk/arch/arm/Kconfig.debug b/trunk/arch/arm/Kconfig.debug index e968a52e4881..f15f82bf3a50 100644 --- a/trunk/arch/arm/Kconfig.debug +++ b/trunk/arch/arm/Kconfig.debug @@ -356,15 +356,15 @@ choice is nothing connected to read from the DCC. config DEBUG_SEMIHOSTING - bool "Kernel low-level debug output via semihosting I/O" + bool "Kernel low-level debug output via semihosting I" help Semihosting enables code running on an ARM target to use the I/O facilities on a host debugger/emulator through a - simple SVC call. The host debugger or emulator must have + simple SVC calls. The host debugger or emulator must have semihosting enabled for the special svc call to be trapped otherwise the kernel will crash. - This is known to work with OpenOCD, as well as + This is known to work with OpenOCD, as wellas ARM's Fast Models, or any other controlling environment that implements semihosting. diff --git a/trunk/arch/arm/Makefile b/trunk/arch/arm/Makefile index a051dfbdd7db..30eae87ead6d 100644 --- a/trunk/arch/arm/Makefile +++ b/trunk/arch/arm/Makefile @@ -284,10 +284,10 @@ zImage Image xipImage bootpImage uImage: vmlinux zinstall uinstall install: vmlinux $(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $@ -%.dtb: scripts +%.dtb: $(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $(boot)/$@ -dtbs: scripts +dtbs: $(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $(boot)/$@ # We use MRPROPER_FILES and CLEAN_FILES now diff --git a/trunk/arch/arm/boot/compressed/head.S b/trunk/arch/arm/boot/compressed/head.S index bc67cbff3944..b8c64b80bafc 100644 --- a/trunk/arch/arm/boot/compressed/head.S +++ b/trunk/arch/arm/boot/compressed/head.S @@ -653,21 +653,16 @@ __armv7_mmu_cache_on: mcrne p15, 0, r0, c8, c7, 0 @ flush I,D TLBs #endif mrc p15, 0, r0, c1, c0, 0 @ read control reg - bic r0, r0, #1 << 28 @ clear SCTLR.TRE orr r0, r0, #0x5000 @ I-cache enable, RR cache replacement orr r0, r0, #0x003c @ write buffer #ifdef CONFIG_MMU #ifdef CONFIG_CPU_ENDIAN_BE8 orr r0, r0, #1 << 25 @ big-endian page tables #endif - mrcne p15, 0, r6, c2, c0, 2 @ read ttb control reg orrne r0, r0, #1 @ MMU enabled movne r1, #0xfffffffd @ domain 0 = client - bic r6, r6, #1 << 31 @ 32-bit translation system - bic r6, r6, #3 << 0 @ use only ttbr0 mcrne p15, 0, r3, c2, c0, 0 @ load page table pointer mcrne p15, 0, r1, c3, c0, 0 @ load domain access control - mcrne p15, 0, r6, c2, c0, 2 @ load ttb control #endif mcr p15, 0, r0, c7, c5, 4 @ ISB mcr p15, 0, r0, c1, c0, 0 @ load control register diff --git a/trunk/arch/arm/boot/dts/am33xx.dtsi b/trunk/arch/arm/boot/dts/am33xx.dtsi index bd0cff3f808c..59509c48d7e5 100644 --- a/trunk/arch/arm/boot/dts/am33xx.dtsi +++ b/trunk/arch/arm/boot/dts/am33xx.dtsi @@ -154,10 +154,5 @@ #size-cells = <0>; ti,hwmods = "i2c3"; }; - - wdt2: wdt@44e35000 { - compatible = "ti,omap3-wdt"; - ti,hwmods = "wd_timer2"; - }; }; }; diff --git a/trunk/arch/arm/boot/dts/at91sam9260.dtsi b/trunk/arch/arm/boot/dts/at91sam9260.dtsi index 7c95f76398de..66389c1c6f62 100644 --- a/trunk/arch/arm/boot/dts/at91sam9260.dtsi +++ b/trunk/arch/arm/boot/dts/at91sam9260.dtsi @@ -104,7 +104,6 @@ #gpio-cells = <2>; gpio-controller; interrupt-controller; - #interrupt-cells = <2>; }; pioB: gpio@fffff600 { @@ -114,7 +113,6 @@ #gpio-cells = <2>; gpio-controller; interrupt-controller; - #interrupt-cells = <2>; }; pioC: gpio@fffff800 { @@ -124,7 +122,6 @@ #gpio-cells = <2>; gpio-controller; interrupt-controller; - #interrupt-cells = <2>; }; dbgu: serial@fffff200 { diff --git a/trunk/arch/arm/boot/dts/at91sam9263.dtsi b/trunk/arch/arm/boot/dts/at91sam9263.dtsi index 195019b7ca0e..b460d6ce9eb5 100644 --- a/trunk/arch/arm/boot/dts/at91sam9263.dtsi +++ b/trunk/arch/arm/boot/dts/at91sam9263.dtsi @@ -95,7 +95,6 @@ #gpio-cells = <2>; gpio-controller; interrupt-controller; - #interrupt-cells = <2>; }; pioB: gpio@fffff400 { @@ -105,7 +104,6 @@ #gpio-cells = <2>; gpio-controller; interrupt-controller; - #interrupt-cells = <2>; }; pioC: gpio@fffff600 { @@ -115,7 +113,6 @@ #gpio-cells = <2>; gpio-controller; interrupt-controller; - #interrupt-cells = <2>; }; pioD: gpio@fffff800 { @@ -125,7 +122,6 @@ #gpio-cells = <2>; gpio-controller; interrupt-controller; - #interrupt-cells = <2>; }; pioE: gpio@fffffa00 { @@ -135,7 +131,6 @@ #gpio-cells = <2>; gpio-controller; interrupt-controller; - #interrupt-cells = <2>; }; dbgu: serial@ffffee00 { diff --git a/trunk/arch/arm/boot/dts/at91sam9g25ek.dts b/trunk/arch/arm/boot/dts/at91sam9g25ek.dts index 96514c134e54..7829a4d0cb22 100644 --- a/trunk/arch/arm/boot/dts/at91sam9g25ek.dts +++ b/trunk/arch/arm/boot/dts/at91sam9g25ek.dts @@ -15,7 +15,7 @@ compatible = "atmel,at91sam9g25ek", "atmel,at91sam9x5ek", "atmel,at91sam9x5", "atmel,at91sam9"; chosen { - bootargs = "console=ttyS0,115200 root=/dev/mtdblock1 rw rootfstype=ubifs ubi.mtd=1 root=ubi0:rootfs"; + bootargs = "128M console=ttyS0,115200 root=/dev/mtdblock1 rw rootfstype=ubifs ubi.mtd=1 root=ubi0:rootfs"; }; ahb { diff --git a/trunk/arch/arm/boot/dts/at91sam9g45.dtsi b/trunk/arch/arm/boot/dts/at91sam9g45.dtsi index 63751b1e744b..bafa8806fc17 100644 --- a/trunk/arch/arm/boot/dts/at91sam9g45.dtsi +++ b/trunk/arch/arm/boot/dts/at91sam9g45.dtsi @@ -113,7 +113,6 @@ #gpio-cells = <2>; gpio-controller; interrupt-controller; - #interrupt-cells = <2>; }; pioB: gpio@fffff400 { @@ -123,7 +122,6 @@ #gpio-cells = <2>; gpio-controller; interrupt-controller; - #interrupt-cells = <2>; }; pioC: gpio@fffff600 { @@ -133,7 +131,6 @@ #gpio-cells = <2>; gpio-controller; interrupt-controller; - #interrupt-cells = <2>; }; pioD: gpio@fffff800 { @@ -143,7 +140,6 @@ #gpio-cells = <2>; gpio-controller; interrupt-controller; - #interrupt-cells = <2>; }; pioE: gpio@fffffa00 { @@ -153,7 +149,6 @@ #gpio-cells = <2>; gpio-controller; interrupt-controller; - #interrupt-cells = <2>; }; dbgu: serial@ffffee00 { diff --git a/trunk/arch/arm/boot/dts/at91sam9n12.dtsi b/trunk/arch/arm/boot/dts/at91sam9n12.dtsi index ef9336ae9614..bfac0dfc332c 100644 --- a/trunk/arch/arm/boot/dts/at91sam9n12.dtsi +++ b/trunk/arch/arm/boot/dts/at91sam9n12.dtsi @@ -107,7 +107,6 @@ #gpio-cells = <2>; gpio-controller; interrupt-controller; - #interrupt-cells = <2>; }; pioB: gpio@fffff600 { @@ -117,7 +116,6 @@ #gpio-cells = <2>; gpio-controller; interrupt-controller; - #interrupt-cells = <2>; }; pioC: gpio@fffff800 { @@ -127,7 +125,6 @@ #gpio-cells = <2>; gpio-controller; interrupt-controller; - #interrupt-cells = <2>; }; pioD: gpio@fffffa00 { @@ -137,7 +134,6 @@ #gpio-cells = <2>; gpio-controller; interrupt-controller; - #interrupt-cells = <2>; }; dbgu: serial@fffff200 { diff --git a/trunk/arch/arm/boot/dts/at91sam9x5.dtsi b/trunk/arch/arm/boot/dts/at91sam9x5.dtsi index 8a387a8d61b7..4a18c393b136 100644 --- a/trunk/arch/arm/boot/dts/at91sam9x5.dtsi +++ b/trunk/arch/arm/boot/dts/at91sam9x5.dtsi @@ -115,7 +115,6 @@ #gpio-cells = <2>; gpio-controller; interrupt-controller; - #interrupt-cells = <2>; }; pioB: gpio@fffff600 { @@ -125,7 +124,6 @@ #gpio-cells = <2>; gpio-controller; interrupt-controller; - #interrupt-cells = <2>; }; pioC: gpio@fffff800 { @@ -135,7 +133,6 @@ #gpio-cells = <2>; gpio-controller; interrupt-controller; - #interrupt-cells = <2>; }; pioD: gpio@fffffa00 { @@ -145,7 +142,6 @@ #gpio-cells = <2>; gpio-controller; interrupt-controller; - #interrupt-cells = <2>; }; dbgu: serial@fffff200 { diff --git a/trunk/arch/arm/boot/dts/imx23.dtsi b/trunk/arch/arm/boot/dts/imx23.dtsi index e6138310e5ce..a874dbfb5ae6 100644 --- a/trunk/arch/arm/boot/dts/imx23.dtsi +++ b/trunk/arch/arm/boot/dts/imx23.dtsi @@ -51,11 +51,11 @@ dma-apbh@80004000 { compatible = "fsl,imx23-dma-apbh"; - reg = <0x80004000 0x2000>; + reg = <0x80004000 2000>; }; ecc@80008000 { - reg = <0x80008000 0x2000>; + reg = <0x80008000 2000>; status = "disabled"; }; @@ -63,7 +63,7 @@ compatible = "fsl,imx23-gpmi-nand"; #address-cells = <1>; #size-cells = <1>; - reg = <0x8000c000 0x2000>, <0x8000a000 0x2000>; + reg = <0x8000c000 2000>, <0x8000a000 2000>; reg-names = "gpmi-nand", "bch"; interrupts = <13>, <56>; interrupt-names = "gpmi-dma", "bch"; @@ -72,14 +72,14 @@ }; ssp0: ssp@80010000 { - reg = <0x80010000 0x2000>; + reg = <0x80010000 2000>; interrupts = <15 14>; fsl,ssp-dma-channel = <1>; status = "disabled"; }; etm@80014000 { - reg = <0x80014000 0x2000>; + reg = <0x80014000 2000>; status = "disabled"; }; @@ -87,7 +87,7 @@ #address-cells = <1>; #size-cells = <0>; compatible = "fsl,imx23-pinctrl", "simple-bus"; - reg = <0x80018000 0x2000>; + reg = <0x80018000 2000>; gpio0: gpio@0 { compatible = "fsl,imx23-gpio", "fsl,mxs-gpio"; @@ -273,32 +273,32 @@ }; emi@80020000 { - reg = <0x80020000 0x2000>; + reg = <0x80020000 2000>; status = "disabled"; }; dma-apbx@80024000 { compatible = "fsl,imx23-dma-apbx"; - reg = <0x80024000 0x2000>; + reg = <0x80024000 2000>; }; dcp@80028000 { - reg = <0x80028000 0x2000>; + reg = <0x80028000 2000>; status = "disabled"; }; pxp@8002a000 { - reg = <0x8002a000 0x2000>; + reg = <0x8002a000 2000>; status = "disabled"; }; ocotp@8002c000 { - reg = <0x8002c000 0x2000>; + reg = <0x8002c000 2000>; status = "disabled"; }; axi-ahb@8002e000 { - reg = <0x8002e000 0x2000>; + reg = <0x8002e000 2000>; status = "disabled"; }; @@ -310,14 +310,14 @@ }; ssp1: ssp@80034000 { - reg = <0x80034000 0x2000>; + reg = <0x80034000 2000>; interrupts = <2 20>; fsl,ssp-dma-channel = <2>; status = "disabled"; }; tvenc@80038000 { - reg = <0x80038000 0x2000>; + reg = <0x80038000 2000>; status = "disabled"; }; }; @@ -330,37 +330,37 @@ ranges; clkctl@80040000 { - reg = <0x80040000 0x2000>; + reg = <0x80040000 2000>; status = "disabled"; }; saif0: saif@80042000 { - reg = <0x80042000 0x2000>; + reg = <0x80042000 2000>; status = "disabled"; }; power@80044000 { - reg = <0x80044000 0x2000>; + reg = <0x80044000 2000>; status = "disabled"; }; saif1: saif@80046000 { - reg = <0x80046000 0x2000>; + reg = <0x80046000 2000>; status = "disabled"; }; audio-out@80048000 { - reg = <0x80048000 0x2000>; + reg = <0x80048000 2000>; status = "disabled"; }; audio-in@8004c000 { - reg = <0x8004c000 0x2000>; + reg = <0x8004c000 2000>; status = "disabled"; }; lradc@80050000 { - reg = <0x80050000 0x2000>; + reg = <0x80050000 2000>; status = "disabled"; }; @@ -370,26 +370,26 @@ }; i2c@80058000 { - reg = <0x80058000 0x2000>; + reg = <0x80058000 2000>; status = "disabled"; }; rtc@8005c000 { compatible = "fsl,imx23-rtc", "fsl,stmp3xxx-rtc"; - reg = <0x8005c000 0x2000>; + reg = <0x8005c000 2000>; interrupts = <22>; }; pwm: pwm@80064000 { compatible = "fsl,imx23-pwm"; - reg = <0x80064000 0x2000>; + reg = <0x80064000 2000>; #pwm-cells = <2>; fsl,pwm-number = <5>; status = "disabled"; }; timrot@80068000 { - reg = <0x80068000 0x2000>; + reg = <0x80068000 2000>; status = "disabled"; }; @@ -429,7 +429,7 @@ ranges; usbctrl@80080000 { - reg = <0x80080000 0x40000>; + reg = <0x80080000 0x10000>; status = "disabled"; }; }; diff --git a/trunk/arch/arm/boot/dts/imx27-3ds.dts b/trunk/arch/arm/boot/dts/imx27-3ds.dts index 0a8978a40ece..d3f8296e19e0 100644 --- a/trunk/arch/arm/boot/dts/imx27-3ds.dts +++ b/trunk/arch/arm/boot/dts/imx27-3ds.dts @@ -27,7 +27,7 @@ status = "okay"; }; - uart1: serial@1000a000 { + uart@1000a000 { fsl,uart-has-rtscts; status = "okay"; }; diff --git a/trunk/arch/arm/boot/dts/imx27.dtsi b/trunk/arch/arm/boot/dts/imx27.dtsi index 5303ab680a34..00bae3aad5ab 100644 --- a/trunk/arch/arm/boot/dts/imx27.dtsi +++ b/trunk/arch/arm/boot/dts/imx27.dtsi @@ -19,12 +19,6 @@ serial3 = &uart4; serial4 = &uart5; serial5 = &uart6; - gpio0 = &gpio1; - gpio1 = &gpio2; - gpio2 = &gpio3; - gpio3 = &gpio4; - gpio4 = &gpio5; - gpio5 = &gpio6; }; avic: avic-interrupt-controller@e0000000 { diff --git a/trunk/arch/arm/boot/dts/imx28.dtsi b/trunk/arch/arm/boot/dts/imx28.dtsi index 3fa6d190fab4..787efac68da8 100644 --- a/trunk/arch/arm/boot/dts/imx28.dtsi +++ b/trunk/arch/arm/boot/dts/imx28.dtsi @@ -57,18 +57,18 @@ }; hsadc@80002000 { - reg = <0x80002000 0x2000>; + reg = <0x80002000 2000>; interrupts = <13 87>; status = "disabled"; }; dma-apbh@80004000 { compatible = "fsl,imx28-dma-apbh"; - reg = <0x80004000 0x2000>; + reg = <0x80004000 2000>; }; perfmon@80006000 { - reg = <0x80006000 0x800>; + reg = <0x80006000 800>; interrupts = <27>; status = "disabled"; }; @@ -77,7 +77,7 @@ compatible = "fsl,imx28-gpmi-nand"; #address-cells = <1>; #size-cells = <1>; - reg = <0x8000c000 0x2000>, <0x8000a000 0x2000>; + reg = <0x8000c000 2000>, <0x8000a000 2000>; reg-names = "gpmi-nand", "bch"; interrupts = <88>, <41>; interrupt-names = "gpmi-dma", "bch"; @@ -86,28 +86,28 @@ }; ssp0: ssp@80010000 { - reg = <0x80010000 0x2000>; + reg = <0x80010000 2000>; interrupts = <96 82>; fsl,ssp-dma-channel = <0>; status = "disabled"; }; ssp1: ssp@80012000 { - reg = <0x80012000 0x2000>; + reg = <0x80012000 2000>; interrupts = <97 83>; fsl,ssp-dma-channel = <1>; status = "disabled"; }; ssp2: ssp@80014000 { - reg = <0x80014000 0x2000>; + reg = <0x80014000 2000>; interrupts = <98 84>; fsl,ssp-dma-channel = <2>; status = "disabled"; }; ssp3: ssp@80016000 { - reg = <0x80016000 0x2000>; + reg = <0x80016000 2000>; interrupts = <99 85>; fsl,ssp-dma-channel = <3>; status = "disabled"; @@ -117,7 +117,7 @@ #address-cells = <1>; #size-cells = <0>; compatible = "fsl,imx28-pinctrl", "simple-bus"; - reg = <0x80018000 0x2000>; + reg = <0x80018000 2000>; gpio0: gpio@0 { compatible = "fsl,imx28-gpio", "fsl,mxs-gpio"; @@ -510,96 +510,96 @@ }; digctl@8001c000 { - reg = <0x8001c000 0x2000>; + reg = <0x8001c000 2000>; interrupts = <89>; status = "disabled"; }; etm@80022000 { - reg = <0x80022000 0x2000>; + reg = <0x80022000 2000>; status = "disabled"; }; dma-apbx@80024000 { compatible = "fsl,imx28-dma-apbx"; - reg = <0x80024000 0x2000>; + reg = <0x80024000 2000>; }; dcp@80028000 { - reg = <0x80028000 0x2000>; + reg = <0x80028000 2000>; interrupts = <52 53 54>; status = "disabled"; }; pxp@8002a000 { - reg = <0x8002a000 0x2000>; + reg = <0x8002a000 2000>; interrupts = <39>; status = "disabled"; }; ocotp@8002c000 { - reg = <0x8002c000 0x2000>; + reg = <0x8002c000 2000>; status = "disabled"; }; axi-ahb@8002e000 { - reg = <0x8002e000 0x2000>; + reg = <0x8002e000 2000>; status = "disabled"; }; lcdif@80030000 { compatible = "fsl,imx28-lcdif"; - reg = <0x80030000 0x2000>; + reg = <0x80030000 2000>; interrupts = <38 86>; status = "disabled"; }; can0: can@80032000 { compatible = "fsl,imx28-flexcan", "fsl,p1010-flexcan"; - reg = <0x80032000 0x2000>; + reg = <0x80032000 2000>; interrupts = <8>; status = "disabled"; }; can1: can@80034000 { compatible = "fsl,imx28-flexcan", "fsl,p1010-flexcan"; - reg = <0x80034000 0x2000>; + reg = <0x80034000 2000>; interrupts = <9>; status = "disabled"; }; simdbg@8003c000 { - reg = <0x8003c000 0x200>; + reg = <0x8003c000 200>; status = "disabled"; }; simgpmisel@8003c200 { - reg = <0x8003c200 0x100>; + reg = <0x8003c200 100>; status = "disabled"; }; simsspsel@8003c300 { - reg = <0x8003c300 0x100>; + reg = <0x8003c300 100>; status = "disabled"; }; simmemsel@8003c400 { - reg = <0x8003c400 0x100>; + reg = <0x8003c400 100>; status = "disabled"; }; gpiomon@8003c500 { - reg = <0x8003c500 0x100>; + reg = <0x8003c500 100>; status = "disabled"; }; simenet@8003c700 { - reg = <0x8003c700 0x100>; + reg = <0x8003c700 100>; status = "disabled"; }; armjtag@8003c800 { - reg = <0x8003c800 0x100>; + reg = <0x8003c800 100>; status = "disabled"; }; }; @@ -612,45 +612,45 @@ ranges; clkctl@80040000 { - reg = <0x80040000 0x2000>; + reg = <0x80040000 2000>; status = "disabled"; }; saif0: saif@80042000 { compatible = "fsl,imx28-saif"; - reg = <0x80042000 0x2000>; + reg = <0x80042000 2000>; interrupts = <59 80>; fsl,saif-dma-channel = <4>; status = "disabled"; }; power@80044000 { - reg = <0x80044000 0x2000>; + reg = <0x80044000 2000>; status = "disabled"; }; saif1: saif@80046000 { compatible = "fsl,imx28-saif"; - reg = <0x80046000 0x2000>; + reg = <0x80046000 2000>; interrupts = <58 81>; fsl,saif-dma-channel = <5>; status = "disabled"; }; lradc@80050000 { - reg = <0x80050000 0x2000>; + reg = <0x80050000 2000>; status = "disabled"; }; spdif@80054000 { - reg = <0x80054000 0x2000>; + reg = <0x80054000 2000>; interrupts = <45 66>; status = "disabled"; }; rtc@80056000 { compatible = "fsl,imx28-rtc", "fsl,stmp3xxx-rtc"; - reg = <0x80056000 0x2000>; + reg = <0x80056000 2000>; interrupts = <29>; }; @@ -658,7 +658,7 @@ #address-cells = <1>; #size-cells = <0>; compatible = "fsl,imx28-i2c"; - reg = <0x80058000 0x2000>; + reg = <0x80058000 2000>; interrupts = <111 68>; clock-frequency = <100000>; status = "disabled"; @@ -668,7 +668,7 @@ #address-cells = <1>; #size-cells = <0>; compatible = "fsl,imx28-i2c"; - reg = <0x8005a000 0x2000>; + reg = <0x8005a000 2000>; interrupts = <110 69>; clock-frequency = <100000>; status = "disabled"; @@ -676,14 +676,14 @@ pwm: pwm@80064000 { compatible = "fsl,imx28-pwm", "fsl,imx23-pwm"; - reg = <0x80064000 0x2000>; + reg = <0x80064000 2000>; #pwm-cells = <2>; fsl,pwm-number = <8>; status = "disabled"; }; timrot@80068000 { - reg = <0x80068000 0x2000>; + reg = <0x80068000 2000>; status = "disabled"; }; diff --git a/trunk/arch/arm/boot/dts/imx51-babbage.dts b/trunk/arch/arm/boot/dts/imx51-babbage.dts index 59d9789e5508..de065b5976e6 100644 --- a/trunk/arch/arm/boot/dts/imx51-babbage.dts +++ b/trunk/arch/arm/boot/dts/imx51-babbage.dts @@ -25,8 +25,8 @@ aips@70000000 { /* aips-1 */ spba@70000000 { esdhc@70004000 { /* ESDHC1 */ - fsl,cd-controller; - fsl,wp-controller; + fsl,cd-internal; + fsl,wp-internal; status = "okay"; }; @@ -53,7 +53,7 @@ spi-max-frequency = <6000000>; reg = <0>; interrupt-parent = <&gpio1>; - interrupts = <8 0x4>; + interrupts = <8>; regulators { sw1_reg: sw1 { diff --git a/trunk/arch/arm/boot/dts/imx51.dtsi b/trunk/arch/arm/boot/dts/imx51.dtsi index aba28dc87fc8..53cbaa3d4f90 100644 --- a/trunk/arch/arm/boot/dts/imx51.dtsi +++ b/trunk/arch/arm/boot/dts/imx51.dtsi @@ -17,10 +17,6 @@ serial0 = &uart1; serial1 = &uart2; serial2 = &uart3; - gpio0 = &gpio1; - gpio1 = &gpio2; - gpio2 = &gpio3; - gpio3 = &gpio4; }; tzic: tz-interrupt-controller@e0000000 { diff --git a/trunk/arch/arm/boot/dts/imx53-ard.dts b/trunk/arch/arm/boot/dts/imx53-ard.dts index da895e93a999..5b8eafcdbeec 100644 --- a/trunk/arch/arm/boot/dts/imx53-ard.dts +++ b/trunk/arch/arm/boot/dts/imx53-ard.dts @@ -64,32 +64,12 @@ reg = <0xf4000000 0x2000000>; phy-mode = "mii"; interrupt-parent = <&gpio2>; - interrupts = <31 0x8>; + interrupts = <31>; reg-io-width = <4>; - /* - * VDD33A and VDDVARIO of LAN9220 are supplied by - * SW4_3V3 of LTC3589. Before the regulator driver - * for this PMIC is available, we use a fixed dummy - * 3V3 regulator to get LAN9220 driver probing work. - */ - vdd33a-supply = <®_3p3v>; - vddvario-supply = <®_3p3v>; smsc,irq-push-pull; }; }; - regulators { - compatible = "simple-bus"; - - reg_3p3v: 3p3v { - compatible = "regulator-fixed"; - regulator-name = "3P3V"; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - regulator-always-on; - }; - }; - gpio-keys { compatible = "gpio-keys"; diff --git a/trunk/arch/arm/boot/dts/imx53.dtsi b/trunk/arch/arm/boot/dts/imx53.dtsi index cd37165edce5..fc79cdc4b4e6 100644 --- a/trunk/arch/arm/boot/dts/imx53.dtsi +++ b/trunk/arch/arm/boot/dts/imx53.dtsi @@ -19,13 +19,6 @@ serial2 = &uart3; serial3 = &uart4; serial4 = &uart5; - gpio0 = &gpio1; - gpio1 = &gpio2; - gpio2 = &gpio3; - gpio3 = &gpio4; - gpio4 = &gpio5; - gpio5 = &gpio6; - gpio6 = &gpio7; }; tzic: tz-interrupt-controller@0fffc000 { diff --git a/trunk/arch/arm/boot/dts/imx6q-sabrelite.dts b/trunk/arch/arm/boot/dts/imx6q-sabrelite.dts index 72f30f3e6171..d42e851ceb97 100644 --- a/trunk/arch/arm/boot/dts/imx6q-sabrelite.dts +++ b/trunk/arch/arm/boot/dts/imx6q-sabrelite.dts @@ -53,7 +53,6 @@ fsl,pins = < 144 0x80000000 /* MX6Q_PAD_EIM_D22__GPIO_3_22 */ 121 0x80000000 /* MX6Q_PAD_EIM_D19__GPIO_3_19 */ - 953 0x80000000 /* MX6Q_PAD_GPIO_0__CCM_CLKO */ >; }; }; diff --git a/trunk/arch/arm/boot/dts/imx6q.dtsi b/trunk/arch/arm/boot/dts/imx6q.dtsi index fd57079f71a9..3d3c64b014e6 100644 --- a/trunk/arch/arm/boot/dts/imx6q.dtsi +++ b/trunk/arch/arm/boot/dts/imx6q.dtsi @@ -19,13 +19,6 @@ serial2 = &uart3; serial3 = &uart4; serial4 = &uart5; - gpio0 = &gpio1; - gpio1 = &gpio2; - gpio2 = &gpio3; - gpio3 = &gpio4; - gpio4 = &gpio5; - gpio5 = &gpio6; - gpio6 = &gpio7; }; cpus { diff --git a/trunk/arch/arm/boot/dts/kirkwood-iconnect.dts b/trunk/arch/arm/boot/dts/kirkwood-iconnect.dts index f8ca6fa88192..52d947045106 100644 --- a/trunk/arch/arm/boot/dts/kirkwood-iconnect.dts +++ b/trunk/arch/arm/boot/dts/kirkwood-iconnect.dts @@ -41,12 +41,8 @@ }; power-blue { label = "power:blue"; - gpios = <&gpio1 10 0>; - linux,default-trigger = "timer"; - }; - power-red { - label = "power:red"; gpios = <&gpio1 11 0>; + linux,default-trigger = "timer"; }; usb1 { label = "usb1:blue"; diff --git a/trunk/arch/arm/boot/dts/twl6030.dtsi b/trunk/arch/arm/boot/dts/twl6030.dtsi index d351b27d7213..3b2f3510d7eb 100644 --- a/trunk/arch/arm/boot/dts/twl6030.dtsi +++ b/trunk/arch/arm/boot/dts/twl6030.dtsi @@ -66,7 +66,6 @@ vcxio: regulator@8 { compatible = "ti,twl6030-vcxio"; - regulator-always-on; }; vusb: regulator@9 { @@ -75,12 +74,10 @@ v1v8: regulator@10 { compatible = "ti,twl6030-v1v8"; - regulator-always-on; }; v2v1: regulator@11 { compatible = "ti,twl6030-v2v1"; - regulator-always-on; }; clk32kg: regulator@12 { diff --git a/trunk/arch/arm/configs/armadillo800eva_defconfig b/trunk/arch/arm/configs/armadillo800eva_defconfig index 90610c7030f7..7d8718468e0d 100644 --- a/trunk/arch/arm/configs/armadillo800eva_defconfig +++ b/trunk/arch/arm/configs/armadillo800eva_defconfig @@ -33,7 +33,7 @@ CONFIG_AEABI=y CONFIG_FORCE_MAX_ZONEORDER=13 CONFIG_ZBOOT_ROM_TEXT=0x0 CONFIG_ZBOOT_ROM_BSS=0x0 -CONFIG_CMDLINE="console=tty0 console=ttySC1,115200 earlyprintk=sh-sci.1,115200 ignore_loglevel root=/dev/nfs ip=dhcp nfsroot=,rsize=4096,wsize=4096 rw" +CONFIG_CMDLINE="console=tty0 console=ttySC1,115200 earlyprintk=sh-sci.1,115200 ignore_loglevel root=/dev/nfs ip=dhcp nfsroot=,rsize=4096,wsize=4096" CONFIG_CMDLINE_FORCE=y CONFIG_KEXEC=y CONFIG_VFP=y diff --git a/trunk/arch/arm/configs/imx_v6_v7_defconfig b/trunk/arch/arm/configs/imx_v6_v7_defconfig index 3c9f32f9b6b4..f725b9637b33 100644 --- a/trunk/arch/arm/configs/imx_v6_v7_defconfig +++ b/trunk/arch/arm/configs/imx_v6_v7_defconfig @@ -192,7 +192,6 @@ CONFIG_RTC_DRV_MC13XXX=y CONFIG_RTC_DRV_MXC=y CONFIG_DMADEVICES=y CONFIG_IMX_SDMA=y -CONFIG_MXS_DMA=y CONFIG_COMMON_CLK_DEBUG=y # CONFIG_IOMMU_SUPPORT is not set CONFIG_EXT2_FS=y diff --git a/trunk/arch/arm/configs/mxs_defconfig b/trunk/arch/arm/configs/mxs_defconfig index 4edcfb4e4dee..ccdb6357fb74 100644 --- a/trunk/arch/arm/configs/mxs_defconfig +++ b/trunk/arch/arm/configs/mxs_defconfig @@ -34,6 +34,7 @@ CONFIG_NO_HZ=y CONFIG_HIGH_RES_TIMERS=y CONFIG_PREEMPT_VOLUNTARY=y CONFIG_AEABI=y +CONFIG_DEFAULT_MMAP_MIN_ADDR=65536 CONFIG_AUTO_ZRELADDR=y CONFIG_FPE_NWFPE=y CONFIG_NET=y diff --git a/trunk/arch/arm/configs/tct_hammer_defconfig b/trunk/arch/arm/configs/tct_hammer_defconfig index 71277a1591ba..1d24f8458bef 100644 --- a/trunk/arch/arm/configs/tct_hammer_defconfig +++ b/trunk/arch/arm/configs/tct_hammer_defconfig @@ -7,7 +7,7 @@ CONFIG_SYSFS_DEPRECATED_V2=y CONFIG_BLK_DEV_INITRD=y CONFIG_EXPERT=y # CONFIG_KALLSYMS is not set -# CONFIG_BUGVERBOSE is not set +# CONFIG_BUG is not set # CONFIG_ELF_CORE is not set # CONFIG_SHMEM is not set CONFIG_SLOB=y diff --git a/trunk/arch/arm/configs/u8500_defconfig b/trunk/arch/arm/configs/u8500_defconfig index da6845493caa..2d4f661d1cf6 100644 --- a/trunk/arch/arm/configs/u8500_defconfig +++ b/trunk/arch/arm/configs/u8500_defconfig @@ -86,7 +86,6 @@ CONFIG_NEW_LEDS=y CONFIG_LEDS_CLASS=y CONFIG_LEDS_LM3530=y CONFIG_LEDS_LP5521=y -CONFIG_LEDS_GPIO=y CONFIG_RTC_CLASS=y CONFIG_RTC_DRV_AB8500=y CONFIG_RTC_DRV_PL031=y diff --git a/trunk/arch/arm/include/asm/assembler.h b/trunk/arch/arm/include/asm/assembler.h index 5c8b3bf4d825..03fb93621d0d 100644 --- a/trunk/arch/arm/include/asm/assembler.h +++ b/trunk/arch/arm/include/asm/assembler.h @@ -320,12 +320,4 @@ .size \name , . - \name .endm - .macro check_uaccess, addr:req, size:req, limit:req, tmp:req, bad:req -#ifndef CONFIG_CPU_USE_DOMAINS - adds \tmp, \addr, #\size - 1 - sbcccs \tmp, \tmp, \limit - bcs \bad -#endif - .endm - #endif /* __ASM_ASSEMBLER_H__ */ diff --git a/trunk/arch/arm/include/asm/dma-mapping.h b/trunk/arch/arm/include/asm/dma-mapping.h index 5c44dcb0987b..2ae842df4551 100644 --- a/trunk/arch/arm/include/asm/dma-mapping.h +++ b/trunk/arch/arm/include/asm/dma-mapping.h @@ -202,13 +202,6 @@ static inline void dma_free_writecombine(struct device *dev, size_t size, return dma_free_attrs(dev, size, cpu_addr, dma_handle, &attrs); } -/* - * This can be called during early boot to increase the size of the atomic - * coherent DMA pool above the default value of 256KiB. It must be called - * before postcore_initcall. - */ -extern void __init init_dma_coherent_pool_size(unsigned long size); - /* * This can be called during boot to increase the size of the consistent * DMA region above it's default value of 2MB. It must be called before the diff --git a/trunk/arch/arm/include/asm/memory.h b/trunk/arch/arm/include/asm/memory.h index 5f6ddcc56452..e965f1b560f1 100644 --- a/trunk/arch/arm/include/asm/memory.h +++ b/trunk/arch/arm/include/asm/memory.h @@ -187,7 +187,6 @@ static inline unsigned long __phys_to_virt(unsigned long x) #define __phys_to_virt(x) ((x) - PHYS_OFFSET + PAGE_OFFSET) #endif #endif -#endif /* __ASSEMBLY__ */ #ifndef PHYS_OFFSET #ifdef PLAT_PHYS_OFFSET @@ -197,8 +196,6 @@ static inline unsigned long __phys_to_virt(unsigned long x) #endif #endif -#ifndef __ASSEMBLY__ - /* * PFNs are used to describe any physical page; this means * PFN 0 == physical address 0. diff --git a/trunk/arch/arm/include/asm/pgtable.h b/trunk/arch/arm/include/asm/pgtable.h index 41dc31f834c3..f66626d71e7d 100644 --- a/trunk/arch/arm/include/asm/pgtable.h +++ b/trunk/arch/arm/include/asm/pgtable.h @@ -195,18 +195,6 @@ static inline pte_t *pmd_page_vaddr(pmd_t pmd) #define pte_clear(mm,addr,ptep) set_pte_ext(ptep, __pte(0), 0) -#define pte_none(pte) (!pte_val(pte)) -#define pte_present(pte) (pte_val(pte) & L_PTE_PRESENT) -#define pte_write(pte) (!(pte_val(pte) & L_PTE_RDONLY)) -#define pte_dirty(pte) (pte_val(pte) & L_PTE_DIRTY) -#define pte_young(pte) (pte_val(pte) & L_PTE_YOUNG) -#define pte_exec(pte) (!(pte_val(pte) & L_PTE_XN)) -#define pte_special(pte) (0) - -#define pte_present_user(pte) \ - ((pte_val(pte) & (L_PTE_PRESENT | L_PTE_USER)) == \ - (L_PTE_PRESENT | L_PTE_USER)) - #if __LINUX_ARM_ARCH__ < 6 static inline void __sync_icache_dcache(pte_t pteval) { @@ -218,16 +206,26 @@ extern void __sync_icache_dcache(pte_t pteval); static inline void set_pte_at(struct mm_struct *mm, unsigned long addr, pte_t *ptep, pte_t pteval) { - unsigned long ext = 0; - - if (addr < TASK_SIZE && pte_present_user(pteval)) { + if (addr >= TASK_SIZE) + set_pte_ext(ptep, pteval, 0); + else { __sync_icache_dcache(pteval); - ext |= PTE_EXT_NG; + set_pte_ext(ptep, pteval, PTE_EXT_NG); } - - set_pte_ext(ptep, pteval, ext); } +#define pte_none(pte) (!pte_val(pte)) +#define pte_present(pte) (pte_val(pte) & L_PTE_PRESENT) +#define pte_write(pte) (!(pte_val(pte) & L_PTE_RDONLY)) +#define pte_dirty(pte) (pte_val(pte) & L_PTE_DIRTY) +#define pte_young(pte) (pte_val(pte) & L_PTE_YOUNG) +#define pte_exec(pte) (!(pte_val(pte) & L_PTE_XN)) +#define pte_special(pte) (0) + +#define pte_present_user(pte) \ + ((pte_val(pte) & (L_PTE_PRESENT | L_PTE_USER)) == \ + (L_PTE_PRESENT | L_PTE_USER)) + #define PTE_BIT_FUNC(fn,op) \ static inline pte_t pte_##fn(pte_t pte) { pte_val(pte) op; return pte; } @@ -253,13 +251,13 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) * * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 - * <--------------- offset ----------------------> < type -> 0 0 0 + * <--------------- offset --------------------> <- type --> 0 0 0 * - * This gives us up to 31 swap files and 64GB per swap file. Note that + * This gives us up to 63 swap files and 32GB per swap file. Note that * the offset field is always non-zero. */ #define __SWP_TYPE_SHIFT 3 -#define __SWP_TYPE_BITS 5 +#define __SWP_TYPE_BITS 6 #define __SWP_TYPE_MASK ((1 << __SWP_TYPE_BITS) - 1) #define __SWP_OFFSET_SHIFT (__SWP_TYPE_BITS + __SWP_TYPE_SHIFT) diff --git a/trunk/arch/arm/include/asm/sched_clock.h b/trunk/arch/arm/include/asm/sched_clock.h index 05b8e82ec9f5..e3f757263438 100644 --- a/trunk/arch/arm/include/asm/sched_clock.h +++ b/trunk/arch/arm/include/asm/sched_clock.h @@ -10,7 +10,5 @@ extern void sched_clock_postinit(void); extern void setup_sched_clock(u32 (*read)(void), int bits, unsigned long rate); -extern void setup_sched_clock_needs_suspend(u32 (*read)(void), int bits, - unsigned long rate); #endif diff --git a/trunk/arch/arm/include/asm/tlb.h b/trunk/arch/arm/include/asm/tlb.h index 99a19512ee26..314d4664eae7 100644 --- a/trunk/arch/arm/include/asm/tlb.h +++ b/trunk/arch/arm/include/asm/tlb.h @@ -199,9 +199,6 @@ static inline void __pte_free_tlb(struct mmu_gather *tlb, pgtable_t pte, { pgtable_page_dtor(pte); -#ifdef CONFIG_ARM_LPAE - tlb_add_flush(tlb, addr); -#else /* * With the classic ARM MMU, a pte page has two corresponding pmd * entries, each covering 1MB. @@ -209,7 +206,6 @@ static inline void __pte_free_tlb(struct mmu_gather *tlb, pgtable_t pte, addr &= PMD_MASK; tlb_add_flush(tlb, addr + SZ_1M - PAGE_SIZE); tlb_add_flush(tlb, addr + SZ_1M); -#endif tlb_remove_page(tlb, pte); } diff --git a/trunk/arch/arm/include/asm/uaccess.h b/trunk/arch/arm/include/asm/uaccess.h index 77bd79f2ffdb..479a6352e0b5 100644 --- a/trunk/arch/arm/include/asm/uaccess.h +++ b/trunk/arch/arm/include/asm/uaccess.h @@ -101,39 +101,28 @@ extern int __get_user_1(void *); extern int __get_user_2(void *); extern int __get_user_4(void *); -#define __GUP_CLOBBER_1 "lr", "cc" -#ifdef CONFIG_CPU_USE_DOMAINS -#define __GUP_CLOBBER_2 "ip", "lr", "cc" -#else -#define __GUP_CLOBBER_2 "lr", "cc" -#endif -#define __GUP_CLOBBER_4 "lr", "cc" - -#define __get_user_x(__r2,__p,__e,__l,__s) \ +#define __get_user_x(__r2,__p,__e,__s,__i...) \ __asm__ __volatile__ ( \ __asmeq("%0", "r0") __asmeq("%1", "r2") \ - __asmeq("%3", "r1") \ "bl __get_user_" #__s \ : "=&r" (__e), "=r" (__r2) \ - : "0" (__p), "r" (__l) \ - : __GUP_CLOBBER_##__s) + : "0" (__p) \ + : __i, "cc") -#define __get_user_check(x,p) \ +#define get_user(x,p) \ ({ \ - unsigned long __limit = current_thread_info()->addr_limit - 1; \ register const typeof(*(p)) __user *__p asm("r0") = (p);\ register unsigned long __r2 asm("r2"); \ - register unsigned long __l asm("r1") = __limit; \ register int __e asm("r0"); \ switch (sizeof(*(__p))) { \ case 1: \ - __get_user_x(__r2, __p, __e, __l, 1); \ - break; \ + __get_user_x(__r2, __p, __e, 1, "lr"); \ + break; \ case 2: \ - __get_user_x(__r2, __p, __e, __l, 2); \ + __get_user_x(__r2, __p, __e, 2, "r3", "lr"); \ break; \ case 4: \ - __get_user_x(__r2, __p, __e, __l, 4); \ + __get_user_x(__r2, __p, __e, 4, "lr"); \ break; \ default: __e = __get_user_bad(); break; \ } \ @@ -141,57 +130,42 @@ extern int __get_user_4(void *); __e; \ }) -#define get_user(x,p) \ - ({ \ - might_fault(); \ - __get_user_check(x,p); \ - }) - extern int __put_user_1(void *, unsigned int); extern int __put_user_2(void *, unsigned int); extern int __put_user_4(void *, unsigned int); extern int __put_user_8(void *, unsigned long long); -#define __put_user_x(__r2,__p,__e,__l,__s) \ +#define __put_user_x(__r2,__p,__e,__s) \ __asm__ __volatile__ ( \ __asmeq("%0", "r0") __asmeq("%2", "r2") \ - __asmeq("%3", "r1") \ "bl __put_user_" #__s \ : "=&r" (__e) \ - : "0" (__p), "r" (__r2), "r" (__l) \ + : "0" (__p), "r" (__r2) \ : "ip", "lr", "cc") -#define __put_user_check(x,p) \ +#define put_user(x,p) \ ({ \ - unsigned long __limit = current_thread_info()->addr_limit - 1; \ register const typeof(*(p)) __r2 asm("r2") = (x); \ register const typeof(*(p)) __user *__p asm("r0") = (p);\ - register unsigned long __l asm("r1") = __limit; \ register int __e asm("r0"); \ switch (sizeof(*(__p))) { \ case 1: \ - __put_user_x(__r2, __p, __e, __l, 1); \ + __put_user_x(__r2, __p, __e, 1); \ break; \ case 2: \ - __put_user_x(__r2, __p, __e, __l, 2); \ + __put_user_x(__r2, __p, __e, 2); \ break; \ case 4: \ - __put_user_x(__r2, __p, __e, __l, 4); \ + __put_user_x(__r2, __p, __e, 4); \ break; \ case 8: \ - __put_user_x(__r2, __p, __e, __l, 8); \ + __put_user_x(__r2, __p, __e, 8); \ break; \ default: __e = __put_user_bad(); break; \ } \ __e; \ }) -#define put_user(x,p) \ - ({ \ - might_fault(); \ - __put_user_check(x,p); \ - }) - #else /* CONFIG_MMU */ /* @@ -245,7 +219,6 @@ do { \ unsigned long __gu_addr = (unsigned long)(ptr); \ unsigned long __gu_val; \ __chk_user_ptr(ptr); \ - might_fault(); \ switch (sizeof(*(ptr))) { \ case 1: __get_user_asm_byte(__gu_val,__gu_addr,err); break; \ case 2: __get_user_asm_half(__gu_val,__gu_addr,err); break; \ @@ -327,7 +300,6 @@ do { \ unsigned long __pu_addr = (unsigned long)(ptr); \ __typeof__(*(ptr)) __pu_val = (x); \ __chk_user_ptr(ptr); \ - might_fault(); \ switch (sizeof(*(ptr))) { \ case 1: __put_user_asm_byte(__pu_val,__pu_addr,err); break; \ case 2: __put_user_asm_half(__pu_val,__pu_addr,err); break; \ diff --git a/trunk/arch/arm/include/asm/unistd.h b/trunk/arch/arm/include/asm/unistd.h index 2fde5fd1acce..0cab47d4a83f 100644 --- a/trunk/arch/arm/include/asm/unistd.h +++ b/trunk/arch/arm/include/asm/unistd.h @@ -404,7 +404,6 @@ #define __NR_setns (__NR_SYSCALL_BASE+375) #define __NR_process_vm_readv (__NR_SYSCALL_BASE+376) #define __NR_process_vm_writev (__NR_SYSCALL_BASE+377) - /* 378 for kcmp */ /* * The following SWIs are ARM private. @@ -484,7 +483,6 @@ */ #define __IGNORE_fadvise64_64 #define __IGNORE_migrate_pages -#define __IGNORE_kcmp #endif /* __KERNEL__ */ #endif /* __ASM_ARM_UNISTD_H */ diff --git a/trunk/arch/arm/kernel/bios32.c b/trunk/arch/arm/kernel/bios32.c index 9cf16b83bbb5..2b2f25e7fef5 100644 --- a/trunk/arch/arm/kernel/bios32.c +++ b/trunk/arch/arm/kernel/bios32.c @@ -270,6 +270,15 @@ static void __devinit pci_fixup_it8152(struct pci_dev *dev) } DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ITE, PCI_DEVICE_ID_ITE_8152, pci_fixup_it8152); + + +void __devinit pcibios_update_irq(struct pci_dev *dev, int irq) +{ + if (debug_pci) + printk("PCI: Assigning IRQ %02d to %s\n", irq, pci_name(dev)); + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq); +} + /* * If the bus contains any of these devices, then we must not turn on * parity checking of any kind. Currently this is CyberPro 20x0 only. diff --git a/trunk/arch/arm/kernel/calls.S b/trunk/arch/arm/kernel/calls.S index e337879595e5..463ff4a0ec8a 100644 --- a/trunk/arch/arm/kernel/calls.S +++ b/trunk/arch/arm/kernel/calls.S @@ -387,7 +387,6 @@ /* 375 */ CALL(sys_setns) CALL(sys_process_vm_readv) CALL(sys_process_vm_writev) - CALL(sys_ni_syscall) /* reserved for sys_kcmp */ #ifndef syscalls_counted .equ syscalls_padding, ((NR_syscalls + 3) & ~3) - NR_syscalls #define syscalls_counted diff --git a/trunk/arch/arm/kernel/hw_breakpoint.c b/trunk/arch/arm/kernel/hw_breakpoint.c index 281bf3301241..ba386bd94107 100644 --- a/trunk/arch/arm/kernel/hw_breakpoint.c +++ b/trunk/arch/arm/kernel/hw_breakpoint.c @@ -159,12 +159,6 @@ static int debug_arch_supported(void) arch >= ARM_DEBUG_ARCH_V7_1; } -/* Can we determine the watchpoint access type from the fsr? */ -static int debug_exception_updates_fsr(void) -{ - return 0; -} - /* Determine number of WRP registers available. */ static int get_num_wrp_resources(void) { @@ -610,14 +604,13 @@ int arch_validate_hwbkpt_settings(struct perf_event *bp) /* Aligned */ break; case 1: + /* Allow single byte watchpoint. */ + if (info->ctrl.len == ARM_BREAKPOINT_LEN_1) + break; case 2: /* Allow halfword watchpoints and breakpoints. */ if (info->ctrl.len == ARM_BREAKPOINT_LEN_2) break; - case 3: - /* Allow single byte watchpoint. */ - if (info->ctrl.len == ARM_BREAKPOINT_LEN_1) - break; default: ret = -EINVAL; goto out; @@ -626,35 +619,18 @@ int arch_validate_hwbkpt_settings(struct perf_event *bp) info->address &= ~alignment_mask; info->ctrl.len <<= offset; - if (!bp->overflow_handler) { - /* - * Mismatch breakpoints are required for single-stepping - * breakpoints. - */ - if (!core_has_mismatch_brps()) - return -EINVAL; - - /* We don't allow mismatch breakpoints in kernel space. */ - if (arch_check_bp_in_kernelspace(bp)) - return -EPERM; - - /* - * Per-cpu breakpoints are not supported by our stepping - * mechanism. - */ - if (!bp->hw.bp_target) - return -EINVAL; - - /* - * We only support specific access types if the fsr - * reports them. - */ - if (!debug_exception_updates_fsr() && - (info->ctrl.type == ARM_BREAKPOINT_LOAD || - info->ctrl.type == ARM_BREAKPOINT_STORE)) - return -EINVAL; + /* + * Currently we rely on an overflow handler to take + * care of single-stepping the breakpoint when it fires. + * In the case of userspace breakpoints on a core with V7 debug, + * we can use the mismatch feature as a poor-man's hardware + * single-step, but this only works for per-task breakpoints. + */ + if (!bp->overflow_handler && (arch_check_bp_in_kernelspace(bp) || + !core_has_mismatch_brps() || !bp->hw.bp_target)) { + pr_warning("overflow handler required but none found\n"); + ret = -EINVAL; } - out: return ret; } @@ -730,12 +706,10 @@ static void watchpoint_handler(unsigned long addr, unsigned int fsr, goto unlock; /* Check that the access type matches. */ - if (debug_exception_updates_fsr()) { - access = (fsr & ARM_FSR_ACCESS_MASK) ? - HW_BREAKPOINT_W : HW_BREAKPOINT_R; - if (!(access & hw_breakpoint_type(wp))) - goto unlock; - } + access = (fsr & ARM_FSR_ACCESS_MASK) ? HW_BREAKPOINT_W : + HW_BREAKPOINT_R; + if (!(access & hw_breakpoint_type(wp))) + goto unlock; /* We have a winner. */ info->trigger = addr; diff --git a/trunk/arch/arm/kernel/sched_clock.c b/trunk/arch/arm/kernel/sched_clock.c index f4515393248d..27d186abbc06 100644 --- a/trunk/arch/arm/kernel/sched_clock.c +++ b/trunk/arch/arm/kernel/sched_clock.c @@ -21,8 +21,6 @@ struct clock_data { u32 epoch_cyc_copy; u32 mult; u32 shift; - bool suspended; - bool needs_suspend; }; static void sched_clock_poll(unsigned long wrap_ticks); @@ -51,9 +49,6 @@ static unsigned long long cyc_to_sched_clock(u32 cyc, u32 mask) u64 epoch_ns; u32 epoch_cyc; - if (cd.suspended) - return cd.epoch_ns; - /* * Load the epoch_cyc and epoch_ns atomically. We do this by * ensuring that we always write epoch_cyc, epoch_ns and @@ -103,13 +98,6 @@ static void sched_clock_poll(unsigned long wrap_ticks) update_sched_clock(); } -void __init setup_sched_clock_needs_suspend(u32 (*read)(void), int bits, - unsigned long rate) -{ - setup_sched_clock(read, bits, rate); - cd.needs_suspend = true; -} - void __init setup_sched_clock(u32 (*read)(void), int bits, unsigned long rate) { unsigned long r, w; @@ -181,23 +169,11 @@ void __init sched_clock_postinit(void) static int sched_clock_suspend(void) { sched_clock_poll(sched_clock_timer.data); - if (cd.needs_suspend) - cd.suspended = true; return 0; } -static void sched_clock_resume(void) -{ - if (cd.needs_suspend) { - cd.epoch_cyc = read_sched_clock(); - cd.epoch_cyc_copy = cd.epoch_cyc; - cd.suspended = false; - } -} - static struct syscore_ops sched_clock_ops = { .suspend = sched_clock_suspend, - .resume = sched_clock_resume, }; static int __init sched_clock_syscore_init(void) diff --git a/trunk/arch/arm/kernel/smp_twd.c b/trunk/arch/arm/kernel/smp_twd.c index e1f906989bb8..fef42b21cecb 100644 --- a/trunk/arch/arm/kernel/smp_twd.c +++ b/trunk/arch/arm/kernel/smp_twd.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -95,52 +96,7 @@ static void twd_timer_stop(struct clock_event_device *clk) disable_percpu_irq(clk->irq); } -#ifdef CONFIG_COMMON_CLK - -/* - * Updates clockevent frequency when the cpu frequency changes. - * Called on the cpu that is changing frequency with interrupts disabled. - */ -static void twd_update_frequency(void *new_rate) -{ - twd_timer_rate = *((unsigned long *) new_rate); - - clockevents_update_freq(*__this_cpu_ptr(twd_evt), twd_timer_rate); -} - -static int twd_rate_change(struct notifier_block *nb, - unsigned long flags, void *data) -{ - struct clk_notifier_data *cnd = data; - - /* - * The twd clock events must be reprogrammed to account for the new - * frequency. The timer is local to a cpu, so cross-call to the - * changing cpu. - */ - if (flags == POST_RATE_CHANGE) - smp_call_function(twd_update_frequency, - (void *)&cnd->new_rate, 1); - - return NOTIFY_OK; -} - -static struct notifier_block twd_clk_nb = { - .notifier_call = twd_rate_change, -}; - -static int twd_clk_init(void) -{ - if (twd_evt && *__this_cpu_ptr(twd_evt) && !IS_ERR(twd_clk)) - return clk_notifier_register(twd_clk, &twd_clk_nb); - - return 0; -} -core_initcall(twd_clk_init); - -#elif defined (CONFIG_CPU_FREQ) - -#include +#ifdef CONFIG_CPU_FREQ /* * Updates clockevent frequency when the cpu frequency changes. diff --git a/trunk/arch/arm/kernel/topology.c b/trunk/arch/arm/kernel/topology.c index 26c12c6440fc..198b08456e90 100644 --- a/trunk/arch/arm/kernel/topology.c +++ b/trunk/arch/arm/kernel/topology.c @@ -321,7 +321,7 @@ void store_cpu_topology(unsigned int cpuid) * init_cpu_topology is called at boot when only one cpu is running * which prevent simultaneous write access to cpu_topology array */ -void __init init_cpu_topology(void) +void init_cpu_topology(void) { unsigned int cpu; diff --git a/trunk/arch/arm/kernel/traps.c b/trunk/arch/arm/kernel/traps.c index b0179b89a04c..f7945218b8c6 100644 --- a/trunk/arch/arm/kernel/traps.c +++ b/trunk/arch/arm/kernel/traps.c @@ -420,23 +420,20 @@ asmlinkage void __exception do_undefinstr(struct pt_regs *regs) #endif instr = *(u32 *) pc; } else if (thumb_mode(regs)) { - if (get_user(instr, (u16 __user *)pc)) - goto die_sig; + get_user(instr, (u16 __user *)pc); if (is_wide_instruction(instr)) { unsigned int instr2; - if (get_user(instr2, (u16 __user *)pc+1)) - goto die_sig; + get_user(instr2, (u16 __user *)pc+1); instr <<= 16; instr |= instr2; } - } else if (get_user(instr, (u32 __user *)pc)) { - goto die_sig; + } else { + get_user(instr, (u32 __user *)pc); } if (call_undef_hook(regs, instr) == 0) return; -die_sig: #ifdef CONFIG_DEBUG_USER if (user_debug & UDBG_UNDEFINED) { printk(KERN_INFO "%s (%d): undefined instruction: pc=%p\n", diff --git a/trunk/arch/arm/lib/Makefile b/trunk/arch/arm/lib/Makefile index af72969820b4..2473fd1fd51c 100644 --- a/trunk/arch/arm/lib/Makefile +++ b/trunk/arch/arm/lib/Makefile @@ -16,30 +16,13 @@ lib-y := backtrace.o changebit.o csumipv6.o csumpartial.o \ call_with_stack.o mmu-y := clear_user.o copy_page.o getuser.o putuser.o - -# the code in uaccess.S is not preemption safe and -# probably faster on ARMv3 only -ifeq ($(CONFIG_PREEMPT),y) - mmu-y += copy_from_user.o copy_to_user.o -else -ifneq ($(CONFIG_CPU_32v3),y) - mmu-y += copy_from_user.o copy_to_user.o -else - mmu-y += uaccess.o -endif -endif +mmu-y += copy_from_user.o copy_to_user.o # using lib_ here won't override already available weak symbols obj-$(CONFIG_UACCESS_WITH_MEMCPY) += uaccess_with_memcpy.o -lib-$(CONFIG_MMU) += $(mmu-y) - -ifeq ($(CONFIG_CPU_32v3),y) - lib-y += io-readsw-armv3.o io-writesw-armv3.o -else - lib-y += io-readsw-armv4.o io-writesw-armv4.o -endif - +lib-$(CONFIG_MMU) += $(mmu-y) +lib-y += io-readsw-armv4.o io-writesw-armv4.o lib-$(CONFIG_ARCH_RPC) += ecard.o io-acorn.o floppydma.o lib-$(CONFIG_ARCH_SHARK) += io-shark.o diff --git a/trunk/arch/arm/lib/delay.c b/trunk/arch/arm/lib/delay.c index 395d5fbb8fa2..d6dacc69254e 100644 --- a/trunk/arch/arm/lib/delay.c +++ b/trunk/arch/arm/lib/delay.c @@ -59,7 +59,6 @@ void __init init_current_timer_delay(unsigned long freq) { pr_info("Switching to timer-based delay loop\n"); lpj_fine = freq / HZ; - loops_per_jiffy = lpj_fine; arm_delay_ops.delay = __timer_delay; arm_delay_ops.const_udelay = __timer_const_udelay; arm_delay_ops.udelay = __timer_udelay; diff --git a/trunk/arch/arm/lib/getuser.S b/trunk/arch/arm/lib/getuser.S index 9b06bb41fca6..11093a7c3e32 100644 --- a/trunk/arch/arm/lib/getuser.S +++ b/trunk/arch/arm/lib/getuser.S @@ -16,9 +16,8 @@ * __get_user_X * * Inputs: r0 contains the address - * r1 contains the address limit, which must be preserved * Outputs: r0 is the error code - * r2 contains the zero-extended value + * r2, r3 contains the zero-extended value * lr corrupted * * No other registers must be altered. (see @@ -28,39 +27,33 @@ * Note also that it is intended that __get_user_bad is not global. */ #include -#include #include #include ENTRY(__get_user_1) - check_uaccess r0, 1, r1, r2, __get_user_bad 1: TUSER(ldrb) r2, [r0] mov r0, #0 mov pc, lr ENDPROC(__get_user_1) ENTRY(__get_user_2) - check_uaccess r0, 2, r1, r2, __get_user_bad -#ifdef CONFIG_CPU_USE_DOMAINS -rb .req ip -2: ldrbt r2, [r0], #1 -3: ldrbt rb, [r0], #0 +#ifdef CONFIG_THUMB2_KERNEL +2: TUSER(ldrb) r2, [r0] +3: TUSER(ldrb) r3, [r0, #1] #else -rb .req r0 -2: ldrb r2, [r0] -3: ldrb rb, [r0, #1] +2: TUSER(ldrb) r2, [r0], #1 +3: TUSER(ldrb) r3, [r0] #endif #ifndef __ARMEB__ - orr r2, r2, rb, lsl #8 + orr r2, r2, r3, lsl #8 #else - orr r2, rb, r2, lsl #8 + orr r2, r3, r2, lsl #8 #endif mov r0, #0 mov pc, lr ENDPROC(__get_user_2) ENTRY(__get_user_4) - check_uaccess r0, 4, r1, r2, __get_user_bad 4: TUSER(ldr) r2, [r0] mov r0, #0 mov pc, lr diff --git a/trunk/arch/arm/lib/io-readsw-armv3.S b/trunk/arch/arm/lib/io-readsw-armv3.S deleted file mode 100644 index 88487c8c4f23..000000000000 --- a/trunk/arch/arm/lib/io-readsw-armv3.S +++ /dev/null @@ -1,106 +0,0 @@ -/* - * linux/arch/arm/lib/io-readsw-armv3.S - * - * Copyright (C) 1995-2000 Russell King - * - * 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 -#include - -.Linsw_bad_alignment: - adr r0, .Linsw_bad_align_msg - mov r2, lr - b panic -.Linsw_bad_align_msg: - .asciz "insw: bad buffer alignment (0x%p, lr=0x%08lX)\n" - .align - -.Linsw_align: tst r1, #1 - bne .Linsw_bad_alignment - - ldr r3, [r0] - strb r3, [r1], #1 - mov r3, r3, lsr #8 - strb r3, [r1], #1 - - subs r2, r2, #1 - moveq pc, lr - -ENTRY(__raw_readsw) - teq r2, #0 @ do we have to check for the zero len? - moveq pc, lr - tst r1, #3 - bne .Linsw_align - -.Linsw_aligned: mov ip, #0xff - orr ip, ip, ip, lsl #8 - stmfd sp!, {r4, r5, r6, lr} - - subs r2, r2, #8 - bmi .Lno_insw_8 - -.Linsw_8_lp: ldr r3, [r0] - and r3, r3, ip - ldr r4, [r0] - orr r3, r3, r4, lsl #16 - - ldr r4, [r0] - and r4, r4, ip - ldr r5, [r0] - orr r4, r4, r5, lsl #16 - - ldr r5, [r0] - and r5, r5, ip - ldr r6, [r0] - orr r5, r5, r6, lsl #16 - - ldr r6, [r0] - and r6, r6, ip - ldr lr, [r0] - orr r6, r6, lr, lsl #16 - - stmia r1!, {r3 - r6} - - subs r2, r2, #8 - bpl .Linsw_8_lp - - tst r2, #7 - ldmeqfd sp!, {r4, r5, r6, pc} - -.Lno_insw_8: tst r2, #4 - beq .Lno_insw_4 - - ldr r3, [r0] - and r3, r3, ip - ldr r4, [r0] - orr r3, r3, r4, lsl #16 - - ldr r4, [r0] - and r4, r4, ip - ldr r5, [r0] - orr r4, r4, r5, lsl #16 - - stmia r1!, {r3, r4} - -.Lno_insw_4: tst r2, #2 - beq .Lno_insw_2 - - ldr r3, [r0] - and r3, r3, ip - ldr r4, [r0] - orr r3, r3, r4, lsl #16 - - str r3, [r1], #4 - -.Lno_insw_2: tst r2, #1 - ldrne r3, [r0] - strneb r3, [r1], #1 - movne r3, r3, lsr #8 - strneb r3, [r1] - - ldmfd sp!, {r4, r5, r6, pc} - - diff --git a/trunk/arch/arm/lib/io-writesw-armv3.S b/trunk/arch/arm/lib/io-writesw-armv3.S deleted file mode 100644 index 49b800419e32..000000000000 --- a/trunk/arch/arm/lib/io-writesw-armv3.S +++ /dev/null @@ -1,126 +0,0 @@ -/* - * linux/arch/arm/lib/io-writesw-armv3.S - * - * Copyright (C) 1995-2000 Russell King - * - * 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 -#include - -.Loutsw_bad_alignment: - adr r0, .Loutsw_bad_align_msg - mov r2, lr - b panic -.Loutsw_bad_align_msg: - .asciz "outsw: bad buffer alignment (0x%p, lr=0x%08lX)\n" - .align - -.Loutsw_align: tst r1, #1 - bne .Loutsw_bad_alignment - - add r1, r1, #2 - - ldr r3, [r1, #-4] - mov r3, r3, lsr #16 - orr r3, r3, r3, lsl #16 - str r3, [r0] - subs r2, r2, #1 - moveq pc, lr - -ENTRY(__raw_writesw) - teq r2, #0 @ do we have to check for the zero len? - moveq pc, lr - tst r1, #3 - bne .Loutsw_align - - stmfd sp!, {r4, r5, r6, lr} - - subs r2, r2, #8 - bmi .Lno_outsw_8 - -.Loutsw_8_lp: ldmia r1!, {r3, r4, r5, r6} - - mov ip, r3, lsl #16 - orr ip, ip, ip, lsr #16 - str ip, [r0] - - mov ip, r3, lsr #16 - orr ip, ip, ip, lsl #16 - str ip, [r0] - - mov ip, r4, lsl #16 - orr ip, ip, ip, lsr #16 - str ip, [r0] - - mov ip, r4, lsr #16 - orr ip, ip, ip, lsl #16 - str ip, [r0] - - mov ip, r5, lsl #16 - orr ip, ip, ip, lsr #16 - str ip, [r0] - - mov ip, r5, lsr #16 - orr ip, ip, ip, lsl #16 - str ip, [r0] - - mov ip, r6, lsl #16 - orr ip, ip, ip, lsr #16 - str ip, [r0] - - mov ip, r6, lsr #16 - orr ip, ip, ip, lsl #16 - str ip, [r0] - - subs r2, r2, #8 - bpl .Loutsw_8_lp - - tst r2, #7 - ldmeqfd sp!, {r4, r5, r6, pc} - -.Lno_outsw_8: tst r2, #4 - beq .Lno_outsw_4 - - ldmia r1!, {r3, r4} - - mov ip, r3, lsl #16 - orr ip, ip, ip, lsr #16 - str ip, [r0] - - mov ip, r3, lsr #16 - orr ip, ip, ip, lsl #16 - str ip, [r0] - - mov ip, r4, lsl #16 - orr ip, ip, ip, lsr #16 - str ip, [r0] - - mov ip, r4, lsr #16 - orr ip, ip, ip, lsl #16 - str ip, [r0] - -.Lno_outsw_4: tst r2, #2 - beq .Lno_outsw_2 - - ldr r3, [r1], #4 - - mov ip, r3, lsl #16 - orr ip, ip, ip, lsr #16 - str ip, [r0] - - mov ip, r3, lsr #16 - orr ip, ip, ip, lsl #16 - str ip, [r0] - -.Lno_outsw_2: tst r2, #1 - - ldrne r3, [r1] - - movne ip, r3, lsl #16 - orrne ip, ip, ip, lsr #16 - strne ip, [r0] - - ldmfd sp!, {r4, r5, r6, pc} diff --git a/trunk/arch/arm/lib/putuser.S b/trunk/arch/arm/lib/putuser.S index 3d73dcb959b0..7db25990c589 100644 --- a/trunk/arch/arm/lib/putuser.S +++ b/trunk/arch/arm/lib/putuser.S @@ -16,7 +16,6 @@ * __put_user_X * * Inputs: r0 contains the address - * r1 contains the address limit, which must be preserved * r2, r3 contains the value * Outputs: r0 is the error code * lr corrupted @@ -28,19 +27,16 @@ * Note also that it is intended that __put_user_bad is not global. */ #include -#include #include #include ENTRY(__put_user_1) - check_uaccess r0, 1, r1, ip, __put_user_bad 1: TUSER(strb) r2, [r0] mov r0, #0 mov pc, lr ENDPROC(__put_user_1) ENTRY(__put_user_2) - check_uaccess r0, 2, r1, ip, __put_user_bad mov ip, r2, lsr #8 #ifdef CONFIG_THUMB2_KERNEL #ifndef __ARMEB__ @@ -64,14 +60,12 @@ ENTRY(__put_user_2) ENDPROC(__put_user_2) ENTRY(__put_user_4) - check_uaccess r0, 4, r1, ip, __put_user_bad 4: TUSER(str) r2, [r0] mov r0, #0 mov pc, lr ENDPROC(__put_user_4) ENTRY(__put_user_8) - check_uaccess r0, 8, r1, ip, __put_user_bad #ifdef CONFIG_THUMB2_KERNEL 5: TUSER(str) r2, [r0] 6: TUSER(str) r3, [r0, #4] diff --git a/trunk/arch/arm/lib/uaccess.S b/trunk/arch/arm/lib/uaccess.S deleted file mode 100644 index 5c908b1cb8ed..000000000000 --- a/trunk/arch/arm/lib/uaccess.S +++ /dev/null @@ -1,564 +0,0 @@ -/* - * linux/arch/arm/lib/uaccess.S - * - * Copyright (C) 1995, 1996,1997,1998 Russell King - * - * 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. - * - * Routines to block copy data to/from user memory - * These are highly optimised both for the 4k page size - * and for various alignments. - */ -#include -#include -#include -#include - - .text - -#define PAGE_SHIFT 12 - -/* Prototype: int __copy_to_user(void *to, const char *from, size_t n) - * Purpose : copy a block to user memory from kernel memory - * Params : to - user memory - * : from - kernel memory - * : n - number of bytes to copy - * Returns : Number of bytes NOT copied. - */ - -.Lc2u_dest_not_aligned: - rsb ip, ip, #4 - cmp ip, #2 - ldrb r3, [r1], #1 -USER( TUSER( strb) r3, [r0], #1) @ May fault - ldrgeb r3, [r1], #1 -USER( TUSER( strgeb) r3, [r0], #1) @ May fault - ldrgtb r3, [r1], #1 -USER( TUSER( strgtb) r3, [r0], #1) @ May fault - sub r2, r2, ip - b .Lc2u_dest_aligned - -ENTRY(__copy_to_user) - stmfd sp!, {r2, r4 - r7, lr} - cmp r2, #4 - blt .Lc2u_not_enough - ands ip, r0, #3 - bne .Lc2u_dest_not_aligned -.Lc2u_dest_aligned: - - ands ip, r1, #3 - bne .Lc2u_src_not_aligned -/* - * Seeing as there has to be at least 8 bytes to copy, we can - * copy one word, and force a user-mode page fault... - */ - -.Lc2u_0fupi: subs r2, r2, #4 - addmi ip, r2, #4 - bmi .Lc2u_0nowords - ldr r3, [r1], #4 -USER( TUSER( str) r3, [r0], #4) @ May fault - mov ip, r0, lsl #32 - PAGE_SHIFT @ On each page, use a ld/st??t instruction - rsb ip, ip, #0 - movs ip, ip, lsr #32 - PAGE_SHIFT - beq .Lc2u_0fupi -/* - * ip = max no. of bytes to copy before needing another "strt" insn - */ - cmp r2, ip - movlt ip, r2 - sub r2, r2, ip - subs ip, ip, #32 - blt .Lc2u_0rem8lp - -.Lc2u_0cpy8lp: ldmia r1!, {r3 - r6} - stmia r0!, {r3 - r6} @ Shouldnt fault - ldmia r1!, {r3 - r6} - subs ip, ip, #32 - stmia r0!, {r3 - r6} @ Shouldnt fault - bpl .Lc2u_0cpy8lp - -.Lc2u_0rem8lp: cmn ip, #16 - ldmgeia r1!, {r3 - r6} - stmgeia r0!, {r3 - r6} @ Shouldnt fault - tst ip, #8 - ldmneia r1!, {r3 - r4} - stmneia r0!, {r3 - r4} @ Shouldnt fault - tst ip, #4 - ldrne r3, [r1], #4 - TUSER( strne) r3, [r0], #4 @ Shouldnt fault - ands ip, ip, #3 - beq .Lc2u_0fupi -.Lc2u_0nowords: teq ip, #0 - beq .Lc2u_finished -.Lc2u_nowords: cmp ip, #2 - ldrb r3, [r1], #1 -USER( TUSER( strb) r3, [r0], #1) @ May fault - ldrgeb r3, [r1], #1 -USER( TUSER( strgeb) r3, [r0], #1) @ May fault - ldrgtb r3, [r1], #1 -USER( TUSER( strgtb) r3, [r0], #1) @ May fault - b .Lc2u_finished - -.Lc2u_not_enough: - movs ip, r2 - bne .Lc2u_nowords -.Lc2u_finished: mov r0, #0 - ldmfd sp!, {r2, r4 - r7, pc} - -.Lc2u_src_not_aligned: - bic r1, r1, #3 - ldr r7, [r1], #4 - cmp ip, #2 - bgt .Lc2u_3fupi - beq .Lc2u_2fupi -.Lc2u_1fupi: subs r2, r2, #4 - addmi ip, r2, #4 - bmi .Lc2u_1nowords - mov r3, r7, pull #8 - ldr r7, [r1], #4 - orr r3, r3, r7, push #24 -USER( TUSER( str) r3, [r0], #4) @ May fault - mov ip, r0, lsl #32 - PAGE_SHIFT - rsb ip, ip, #0 - movs ip, ip, lsr #32 - PAGE_SHIFT - beq .Lc2u_1fupi - cmp r2, ip - movlt ip, r2 - sub r2, r2, ip - subs ip, ip, #16 - blt .Lc2u_1rem8lp - -.Lc2u_1cpy8lp: mov r3, r7, pull #8 - ldmia r1!, {r4 - r7} - subs ip, ip, #16 - orr r3, r3, r4, push #24 - mov r4, r4, pull #8 - orr r4, r4, r5, push #24 - mov r5, r5, pull #8 - orr r5, r5, r6, push #24 - mov r6, r6, pull #8 - orr r6, r6, r7, push #24 - stmia r0!, {r3 - r6} @ Shouldnt fault - bpl .Lc2u_1cpy8lp - -.Lc2u_1rem8lp: tst ip, #8 - movne r3, r7, pull #8 - ldmneia r1!, {r4, r7} - orrne r3, r3, r4, push #24 - movne r4, r4, pull #8 - orrne r4, r4, r7, push #24 - stmneia r0!, {r3 - r4} @ Shouldnt fault - tst ip, #4 - movne r3, r7, pull #8 - ldrne r7, [r1], #4 - orrne r3, r3, r7, push #24 - TUSER( strne) r3, [r0], #4 @ Shouldnt fault - ands ip, ip, #3 - beq .Lc2u_1fupi -.Lc2u_1nowords: mov r3, r7, get_byte_1 - teq ip, #0 - beq .Lc2u_finished - cmp ip, #2 -USER( TUSER( strb) r3, [r0], #1) @ May fault - movge r3, r7, get_byte_2 -USER( TUSER( strgeb) r3, [r0], #1) @ May fault - movgt r3, r7, get_byte_3 -USER( TUSER( strgtb) r3, [r0], #1) @ May fault - b .Lc2u_finished - -.Lc2u_2fupi: subs r2, r2, #4 - addmi ip, r2, #4 - bmi .Lc2u_2nowords - mov r3, r7, pull #16 - ldr r7, [r1], #4 - orr r3, r3, r7, push #16 -USER( TUSER( str) r3, [r0], #4) @ May fault - mov ip, r0, lsl #32 - PAGE_SHIFT - rsb ip, ip, #0 - movs ip, ip, lsr #32 - PAGE_SHIFT - beq .Lc2u_2fupi - cmp r2, ip - movlt ip, r2 - sub r2, r2, ip - subs ip, ip, #16 - blt .Lc2u_2rem8lp - -.Lc2u_2cpy8lp: mov r3, r7, pull #16 - ldmia r1!, {r4 - r7} - subs ip, ip, #16 - orr r3, r3, r4, push #16 - mov r4, r4, pull #16 - orr r4, r4, r5, push #16 - mov r5, r5, pull #16 - orr r5, r5, r6, push #16 - mov r6, r6, pull #16 - orr r6, r6, r7, push #16 - stmia r0!, {r3 - r6} @ Shouldnt fault - bpl .Lc2u_2cpy8lp - -.Lc2u_2rem8lp: tst ip, #8 - movne r3, r7, pull #16 - ldmneia r1!, {r4, r7} - orrne r3, r3, r4, push #16 - movne r4, r4, pull #16 - orrne r4, r4, r7, push #16 - stmneia r0!, {r3 - r4} @ Shouldnt fault - tst ip, #4 - movne r3, r7, pull #16 - ldrne r7, [r1], #4 - orrne r3, r3, r7, push #16 - TUSER( strne) r3, [r0], #4 @ Shouldnt fault - ands ip, ip, #3 - beq .Lc2u_2fupi -.Lc2u_2nowords: mov r3, r7, get_byte_2 - teq ip, #0 - beq .Lc2u_finished - cmp ip, #2 -USER( TUSER( strb) r3, [r0], #1) @ May fault - movge r3, r7, get_byte_3 -USER( TUSER( strgeb) r3, [r0], #1) @ May fault - ldrgtb r3, [r1], #0 -USER( TUSER( strgtb) r3, [r0], #1) @ May fault - b .Lc2u_finished - -.Lc2u_3fupi: subs r2, r2, #4 - addmi ip, r2, #4 - bmi .Lc2u_3nowords - mov r3, r7, pull #24 - ldr r7, [r1], #4 - orr r3, r3, r7, push #8 -USER( TUSER( str) r3, [r0], #4) @ May fault - mov ip, r0, lsl #32 - PAGE_SHIFT - rsb ip, ip, #0 - movs ip, ip, lsr #32 - PAGE_SHIFT - beq .Lc2u_3fupi - cmp r2, ip - movlt ip, r2 - sub r2, r2, ip - subs ip, ip, #16 - blt .Lc2u_3rem8lp - -.Lc2u_3cpy8lp: mov r3, r7, pull #24 - ldmia r1!, {r4 - r7} - subs ip, ip, #16 - orr r3, r3, r4, push #8 - mov r4, r4, pull #24 - orr r4, r4, r5, push #8 - mov r5, r5, pull #24 - orr r5, r5, r6, push #8 - mov r6, r6, pull #24 - orr r6, r6, r7, push #8 - stmia r0!, {r3 - r6} @ Shouldnt fault - bpl .Lc2u_3cpy8lp - -.Lc2u_3rem8lp: tst ip, #8 - movne r3, r7, pull #24 - ldmneia r1!, {r4, r7} - orrne r3, r3, r4, push #8 - movne r4, r4, pull #24 - orrne r4, r4, r7, push #8 - stmneia r0!, {r3 - r4} @ Shouldnt fault - tst ip, #4 - movne r3, r7, pull #24 - ldrne r7, [r1], #4 - orrne r3, r3, r7, push #8 - TUSER( strne) r3, [r0], #4 @ Shouldnt fault - ands ip, ip, #3 - beq .Lc2u_3fupi -.Lc2u_3nowords: mov r3, r7, get_byte_3 - teq ip, #0 - beq .Lc2u_finished - cmp ip, #2 -USER( TUSER( strb) r3, [r0], #1) @ May fault - ldrgeb r3, [r1], #1 -USER( TUSER( strgeb) r3, [r0], #1) @ May fault - ldrgtb r3, [r1], #0 -USER( TUSER( strgtb) r3, [r0], #1) @ May fault - b .Lc2u_finished -ENDPROC(__copy_to_user) - - .pushsection .fixup,"ax" - .align 0 -9001: ldmfd sp!, {r0, r4 - r7, pc} - .popsection - -/* Prototype: unsigned long __copy_from_user(void *to,const void *from,unsigned long n); - * Purpose : copy a block from user memory to kernel memory - * Params : to - kernel memory - * : from - user memory - * : n - number of bytes to copy - * Returns : Number of bytes NOT copied. - */ -.Lcfu_dest_not_aligned: - rsb ip, ip, #4 - cmp ip, #2 -USER( TUSER( ldrb) r3, [r1], #1) @ May fault - strb r3, [r0], #1 -USER( TUSER( ldrgeb) r3, [r1], #1) @ May fault - strgeb r3, [r0], #1 -USER( TUSER( ldrgtb) r3, [r1], #1) @ May fault - strgtb r3, [r0], #1 - sub r2, r2, ip - b .Lcfu_dest_aligned - -ENTRY(__copy_from_user) - stmfd sp!, {r0, r2, r4 - r7, lr} - cmp r2, #4 - blt .Lcfu_not_enough - ands ip, r0, #3 - bne .Lcfu_dest_not_aligned -.Lcfu_dest_aligned: - ands ip, r1, #3 - bne .Lcfu_src_not_aligned - -/* - * Seeing as there has to be at least 8 bytes to copy, we can - * copy one word, and force a user-mode page fault... - */ - -.Lcfu_0fupi: subs r2, r2, #4 - addmi ip, r2, #4 - bmi .Lcfu_0nowords -USER( TUSER( ldr) r3, [r1], #4) - str r3, [r0], #4 - mov ip, r1, lsl #32 - PAGE_SHIFT @ On each page, use a ld/st??t instruction - rsb ip, ip, #0 - movs ip, ip, lsr #32 - PAGE_SHIFT - beq .Lcfu_0fupi -/* - * ip = max no. of bytes to copy before needing another "strt" insn - */ - cmp r2, ip - movlt ip, r2 - sub r2, r2, ip - subs ip, ip, #32 - blt .Lcfu_0rem8lp - -.Lcfu_0cpy8lp: ldmia r1!, {r3 - r6} @ Shouldnt fault - stmia r0!, {r3 - r6} - ldmia r1!, {r3 - r6} @ Shouldnt fault - subs ip, ip, #32 - stmia r0!, {r3 - r6} - bpl .Lcfu_0cpy8lp - -.Lcfu_0rem8lp: cmn ip, #16 - ldmgeia r1!, {r3 - r6} @ Shouldnt fault - stmgeia r0!, {r3 - r6} - tst ip, #8 - ldmneia r1!, {r3 - r4} @ Shouldnt fault - stmneia r0!, {r3 - r4} - tst ip, #4 - TUSER( ldrne) r3, [r1], #4 @ Shouldnt fault - strne r3, [r0], #4 - ands ip, ip, #3 - beq .Lcfu_0fupi -.Lcfu_0nowords: teq ip, #0 - beq .Lcfu_finished -.Lcfu_nowords: cmp ip, #2 -USER( TUSER( ldrb) r3, [r1], #1) @ May fault - strb r3, [r0], #1 -USER( TUSER( ldrgeb) r3, [r1], #1) @ May fault - strgeb r3, [r0], #1 -USER( TUSER( ldrgtb) r3, [r1], #1) @ May fault - strgtb r3, [r0], #1 - b .Lcfu_finished - -.Lcfu_not_enough: - movs ip, r2 - bne .Lcfu_nowords -.Lcfu_finished: mov r0, #0 - add sp, sp, #8 - ldmfd sp!, {r4 - r7, pc} - -.Lcfu_src_not_aligned: - bic r1, r1, #3 -USER( TUSER( ldr) r7, [r1], #4) @ May fault - cmp ip, #2 - bgt .Lcfu_3fupi - beq .Lcfu_2fupi -.Lcfu_1fupi: subs r2, r2, #4 - addmi ip, r2, #4 - bmi .Lcfu_1nowords - mov r3, r7, pull #8 -USER( TUSER( ldr) r7, [r1], #4) @ May fault - orr r3, r3, r7, push #24 - str r3, [r0], #4 - mov ip, r1, lsl #32 - PAGE_SHIFT - rsb ip, ip, #0 - movs ip, ip, lsr #32 - PAGE_SHIFT - beq .Lcfu_1fupi - cmp r2, ip - movlt ip, r2 - sub r2, r2, ip - subs ip, ip, #16 - blt .Lcfu_1rem8lp - -.Lcfu_1cpy8lp: mov r3, r7, pull #8 - ldmia r1!, {r4 - r7} @ Shouldnt fault - subs ip, ip, #16 - orr r3, r3, r4, push #24 - mov r4, r4, pull #8 - orr r4, r4, r5, push #24 - mov r5, r5, pull #8 - orr r5, r5, r6, push #24 - mov r6, r6, pull #8 - orr r6, r6, r7, push #24 - stmia r0!, {r3 - r6} - bpl .Lcfu_1cpy8lp - -.Lcfu_1rem8lp: tst ip, #8 - movne r3, r7, pull #8 - ldmneia r1!, {r4, r7} @ Shouldnt fault - orrne r3, r3, r4, push #24 - movne r4, r4, pull #8 - orrne r4, r4, r7, push #24 - stmneia r0!, {r3 - r4} - tst ip, #4 - movne r3, r7, pull #8 -USER( TUSER( ldrne) r7, [r1], #4) @ May fault - orrne r3, r3, r7, push #24 - strne r3, [r0], #4 - ands ip, ip, #3 - beq .Lcfu_1fupi -.Lcfu_1nowords: mov r3, r7, get_byte_1 - teq ip, #0 - beq .Lcfu_finished - cmp ip, #2 - strb r3, [r0], #1 - movge r3, r7, get_byte_2 - strgeb r3, [r0], #1 - movgt r3, r7, get_byte_3 - strgtb r3, [r0], #1 - b .Lcfu_finished - -.Lcfu_2fupi: subs r2, r2, #4 - addmi ip, r2, #4 - bmi .Lcfu_2nowords - mov r3, r7, pull #16 -USER( TUSER( ldr) r7, [r1], #4) @ May fault - orr r3, r3, r7, push #16 - str r3, [r0], #4 - mov ip, r1, lsl #32 - PAGE_SHIFT - rsb ip, ip, #0 - movs ip, ip, lsr #32 - PAGE_SHIFT - beq .Lcfu_2fupi - cmp r2, ip - movlt ip, r2 - sub r2, r2, ip - subs ip, ip, #16 - blt .Lcfu_2rem8lp - - -.Lcfu_2cpy8lp: mov r3, r7, pull #16 - ldmia r1!, {r4 - r7} @ Shouldnt fault - subs ip, ip, #16 - orr r3, r3, r4, push #16 - mov r4, r4, pull #16 - orr r4, r4, r5, push #16 - mov r5, r5, pull #16 - orr r5, r5, r6, push #16 - mov r6, r6, pull #16 - orr r6, r6, r7, push #16 - stmia r0!, {r3 - r6} - bpl .Lcfu_2cpy8lp - -.Lcfu_2rem8lp: tst ip, #8 - movne r3, r7, pull #16 - ldmneia r1!, {r4, r7} @ Shouldnt fault - orrne r3, r3, r4, push #16 - movne r4, r4, pull #16 - orrne r4, r4, r7, push #16 - stmneia r0!, {r3 - r4} - tst ip, #4 - movne r3, r7, pull #16 -USER( TUSER( ldrne) r7, [r1], #4) @ May fault - orrne r3, r3, r7, push #16 - strne r3, [r0], #4 - ands ip, ip, #3 - beq .Lcfu_2fupi -.Lcfu_2nowords: mov r3, r7, get_byte_2 - teq ip, #0 - beq .Lcfu_finished - cmp ip, #2 - strb r3, [r0], #1 - movge r3, r7, get_byte_3 - strgeb r3, [r0], #1 -USER( TUSER( ldrgtb) r3, [r1], #0) @ May fault - strgtb r3, [r0], #1 - b .Lcfu_finished - -.Lcfu_3fupi: subs r2, r2, #4 - addmi ip, r2, #4 - bmi .Lcfu_3nowords - mov r3, r7, pull #24 -USER( TUSER( ldr) r7, [r1], #4) @ May fault - orr r3, r3, r7, push #8 - str r3, [r0], #4 - mov ip, r1, lsl #32 - PAGE_SHIFT - rsb ip, ip, #0 - movs ip, ip, lsr #32 - PAGE_SHIFT - beq .Lcfu_3fupi - cmp r2, ip - movlt ip, r2 - sub r2, r2, ip - subs ip, ip, #16 - blt .Lcfu_3rem8lp - -.Lcfu_3cpy8lp: mov r3, r7, pull #24 - ldmia r1!, {r4 - r7} @ Shouldnt fault - orr r3, r3, r4, push #8 - mov r4, r4, pull #24 - orr r4, r4, r5, push #8 - mov r5, r5, pull #24 - orr r5, r5, r6, push #8 - mov r6, r6, pull #24 - orr r6, r6, r7, push #8 - stmia r0!, {r3 - r6} - subs ip, ip, #16 - bpl .Lcfu_3cpy8lp - -.Lcfu_3rem8lp: tst ip, #8 - movne r3, r7, pull #24 - ldmneia r1!, {r4, r7} @ Shouldnt fault - orrne r3, r3, r4, push #8 - movne r4, r4, pull #24 - orrne r4, r4, r7, push #8 - stmneia r0!, {r3 - r4} - tst ip, #4 - movne r3, r7, pull #24 -USER( TUSER( ldrne) r7, [r1], #4) @ May fault - orrne r3, r3, r7, push #8 - strne r3, [r0], #4 - ands ip, ip, #3 - beq .Lcfu_3fupi -.Lcfu_3nowords: mov r3, r7, get_byte_3 - teq ip, #0 - beq .Lcfu_finished - cmp ip, #2 - strb r3, [r0], #1 -USER( TUSER( ldrgeb) r3, [r1], #1) @ May fault - strgeb r3, [r0], #1 -USER( TUSER( ldrgtb) r3, [r1], #1) @ May fault - strgtb r3, [r0], #1 - b .Lcfu_finished -ENDPROC(__copy_from_user) - - .pushsection .fixup,"ax" - .align 0 - /* - * We took an exception. r0 contains a pointer to - * the byte not copied. - */ -9001: ldr r2, [sp], #4 @ void *to - sub r2, r0, r2 @ bytes copied - ldr r1, [sp], #4 @ unsigned long count - subs r4, r1, r2 @ bytes left to copy - movne r1, r4 - blne __memzero - mov r0, r4 - ldmfd sp!, {r4 - r7, pc} - .popsection - diff --git a/trunk/arch/arm/mach-at91/at91rm9200_time.c b/trunk/arch/arm/mach-at91/at91rm9200_time.c index aaa443b48c91..104ca40d8d18 100644 --- a/trunk/arch/arm/mach-at91/at91rm9200_time.c +++ b/trunk/arch/arm/mach-at91/at91rm9200_time.c @@ -197,7 +197,7 @@ void __init at91rm9200_timer_init(void) at91_st_read(AT91_ST_SR); /* Make IRQs happen for the system timer */ - setup_irq(NR_IRQS_LEGACY + AT91_ID_SYS, &at91rm9200_timer_irq); + setup_irq(AT91_ID_SYS, &at91rm9200_timer_irq); /* The 32KiHz "Slow Clock" (tick every 30517.58 nanoseconds) is used * directly for the clocksource and all clockevents, after adjusting diff --git a/trunk/arch/arm/mach-at91/at91sam9260_devices.c b/trunk/arch/arm/mach-at91/at91sam9260_devices.c index bce572a530ef..7b9c2ba396ed 100644 --- a/trunk/arch/arm/mach-at91/at91sam9260_devices.c +++ b/trunk/arch/arm/mach-at91/at91sam9260_devices.c @@ -726,8 +726,6 @@ static struct resource rtt_resources[] = { .flags = IORESOURCE_MEM, }, { .flags = IORESOURCE_MEM, - }, { - .flags = IORESOURCE_IRQ, }, }; @@ -746,12 +744,10 @@ static void __init at91_add_device_rtt_rtc(void) * The second resource is needed: * GPBR will serve as the storage for RTC time offset */ - at91sam9260_rtt_device.num_resources = 3; + at91sam9260_rtt_device.num_resources = 2; rtt_resources[1].start = AT91SAM9260_BASE_GPBR + 4 * CONFIG_RTC_DRV_AT91SAM9_GPBR; rtt_resources[1].end = rtt_resources[1].start + 3; - rtt_resources[2].start = NR_IRQS_LEGACY + AT91_ID_SYS; - rtt_resources[2].end = NR_IRQS_LEGACY + AT91_ID_SYS; } #else static void __init at91_add_device_rtt_rtc(void) diff --git a/trunk/arch/arm/mach-at91/at91sam9261_devices.c b/trunk/arch/arm/mach-at91/at91sam9261_devices.c index bc2590d712d0..8df5c1bdff92 100644 --- a/trunk/arch/arm/mach-at91/at91sam9261_devices.c +++ b/trunk/arch/arm/mach-at91/at91sam9261_devices.c @@ -609,8 +609,6 @@ static struct resource rtt_resources[] = { .flags = IORESOURCE_MEM, }, { .flags = IORESOURCE_MEM, - }, { - .flags = IORESOURCE_IRQ, } }; @@ -628,12 +626,10 @@ static void __init at91_add_device_rtt_rtc(void) * The second resource is needed: * GPBR will serve as the storage for RTC time offset */ - at91sam9261_rtt_device.num_resources = 3; + at91sam9261_rtt_device.num_resources = 2; rtt_resources[1].start = AT91SAM9261_BASE_GPBR + 4 * CONFIG_RTC_DRV_AT91SAM9_GPBR; rtt_resources[1].end = rtt_resources[1].start + 3; - rtt_resources[2].start = NR_IRQS_LEGACY + AT91_ID_SYS; - rtt_resources[2].end = NR_IRQS_LEGACY + AT91_ID_SYS; } #else static void __init at91_add_device_rtt_rtc(void) diff --git a/trunk/arch/arm/mach-at91/at91sam9263_devices.c b/trunk/arch/arm/mach-at91/at91sam9263_devices.c index 9b6ca734f1a9..eb6bbf86fb9f 100644 --- a/trunk/arch/arm/mach-at91/at91sam9263_devices.c +++ b/trunk/arch/arm/mach-at91/at91sam9263_devices.c @@ -990,8 +990,6 @@ static struct resource rtt0_resources[] = { .flags = IORESOURCE_MEM, }, { .flags = IORESOURCE_MEM, - }, { - .flags = IORESOURCE_IRQ, } }; @@ -1008,8 +1006,6 @@ static struct resource rtt1_resources[] = { .flags = IORESOURCE_MEM, }, { .flags = IORESOURCE_MEM, - }, { - .flags = IORESOURCE_IRQ, } }; @@ -1031,14 +1027,14 @@ static void __init at91_add_device_rtt_rtc(void) * The second resource is needed only for the chosen RTT: * GPBR will serve as the storage for RTC time offset */ - at91sam9263_rtt0_device.num_resources = 3; + at91sam9263_rtt0_device.num_resources = 2; at91sam9263_rtt1_device.num_resources = 1; pdev = &at91sam9263_rtt0_device; r = rtt0_resources; break; case 1: at91sam9263_rtt0_device.num_resources = 1; - at91sam9263_rtt1_device.num_resources = 3; + at91sam9263_rtt1_device.num_resources = 2; pdev = &at91sam9263_rtt1_device; r = rtt1_resources; break; @@ -1051,8 +1047,6 @@ static void __init at91_add_device_rtt_rtc(void) pdev->name = "rtc-at91sam9"; r[1].start = AT91SAM9263_BASE_GPBR + 4 * CONFIG_RTC_DRV_AT91SAM9_GPBR; r[1].end = r[1].start + 3; - r[2].start = NR_IRQS_LEGACY + AT91_ID_SYS; - r[2].end = NR_IRQS_LEGACY + AT91_ID_SYS; } #else static void __init at91_add_device_rtt_rtc(void) diff --git a/trunk/arch/arm/mach-at91/at91sam9g45_devices.c b/trunk/arch/arm/mach-at91/at91sam9g45_devices.c index 1b47319ca00b..06073996a382 100644 --- a/trunk/arch/arm/mach-at91/at91sam9g45_devices.c +++ b/trunk/arch/arm/mach-at91/at91sam9g45_devices.c @@ -1293,8 +1293,6 @@ static struct resource rtt_resources[] = { .flags = IORESOURCE_MEM, }, { .flags = IORESOURCE_MEM, - }, { - .flags = IORESOURCE_IRQ, } }; @@ -1312,12 +1310,10 @@ static void __init at91_add_device_rtt_rtc(void) * The second resource is needed: * GPBR will serve as the storage for RTC time offset */ - at91sam9g45_rtt_device.num_resources = 3; + at91sam9g45_rtt_device.num_resources = 2; rtt_resources[1].start = AT91SAM9G45_BASE_GPBR + 4 * CONFIG_RTC_DRV_AT91SAM9_GPBR; rtt_resources[1].end = rtt_resources[1].start + 3; - rtt_resources[2].start = NR_IRQS_LEGACY + AT91_ID_SYS; - rtt_resources[2].end = NR_IRQS_LEGACY + AT91_ID_SYS; } #else static void __init at91_add_device_rtt_rtc(void) diff --git a/trunk/arch/arm/mach-at91/at91sam9rl_devices.c b/trunk/arch/arm/mach-at91/at91sam9rl_devices.c index b3d365dadef5..f09fff932172 100644 --- a/trunk/arch/arm/mach-at91/at91sam9rl_devices.c +++ b/trunk/arch/arm/mach-at91/at91sam9rl_devices.c @@ -688,8 +688,6 @@ static struct resource rtt_resources[] = { .flags = IORESOURCE_MEM, }, { .flags = IORESOURCE_MEM, - }, { - .flags = IORESOURCE_IRQ, } }; @@ -707,12 +705,10 @@ static void __init at91_add_device_rtt_rtc(void) * The second resource is needed: * GPBR will serve as the storage for RTC time offset */ - at91sam9rl_rtt_device.num_resources = 3; + at91sam9rl_rtt_device.num_resources = 2; rtt_resources[1].start = AT91SAM9RL_BASE_GPBR + 4 * CONFIG_RTC_DRV_AT91SAM9_GPBR; rtt_resources[1].end = rtt_resources[1].start + 3; - rtt_resources[2].start = NR_IRQS_LEGACY + AT91_ID_SYS; - rtt_resources[2].end = NR_IRQS_LEGACY + AT91_ID_SYS; } #else static void __init at91_add_device_rtt_rtc(void) diff --git a/trunk/arch/arm/mach-at91/clock.c b/trunk/arch/arm/mach-at91/clock.c index 188c82971ebd..de2ec6b8fea7 100644 --- a/trunk/arch/arm/mach-at91/clock.c +++ b/trunk/arch/arm/mach-at91/clock.c @@ -63,12 +63,6 @@ EXPORT_SYMBOL_GPL(at91_pmc_base); #define cpu_has_300M_plla() (cpu_is_at91sam9g10()) -#define cpu_has_240M_plla() (cpu_is_at91sam9261() \ - || cpu_is_at91sam9263() \ - || cpu_is_at91sam9rl()) - -#define cpu_has_210M_plla() (cpu_is_at91sam9260()) - #define cpu_has_pllb() (!(cpu_is_at91sam9rl() \ || cpu_is_at91sam9g45() \ || cpu_is_at91sam9x5() \ @@ -712,12 +706,6 @@ static int __init at91_pmc_init(unsigned long main_clock) } else if (cpu_has_800M_plla()) { if (plla.rate_hz > 800000000) pll_overclock = true; - } else if (cpu_has_240M_plla()) { - if (plla.rate_hz > 240000000) - pll_overclock = true; - } else if (cpu_has_210M_plla()) { - if (plla.rate_hz > 210000000) - pll_overclock = true; } else { if (plla.rate_hz > 209000000) pll_overclock = true; diff --git a/trunk/arch/arm/mach-davinci/board-neuros-osd2.c b/trunk/arch/arm/mach-davinci/board-neuros-osd2.c index f6b9fc70161b..5de69f2fcca9 100644 --- a/trunk/arch/arm/mach-davinci/board-neuros-osd2.c +++ b/trunk/arch/arm/mach-davinci/board-neuros-osd2.c @@ -162,6 +162,38 @@ static void __init davinci_ntosd2_map_io(void) dm644x_init(); } +/* + I2C initialization +*/ +static struct davinci_i2c_platform_data ntosd2_i2c_pdata = { + .bus_freq = 20 /* kHz */, + .bus_delay = 100 /* usec */, +}; + +static struct i2c_board_info __initdata ntosd2_i2c_info[] = { +}; + +static int ntosd2_init_i2c(void) +{ + int status; + + davinci_init_i2c(&ntosd2_i2c_pdata); + status = gpio_request(NTOSD2_MSP430_IRQ, ntosd2_i2c_info[0].type); + if (status == 0) { + status = gpio_direction_input(NTOSD2_MSP430_IRQ); + if (status == 0) { + status = gpio_to_irq(NTOSD2_MSP430_IRQ); + if (status > 0) { + ntosd2_i2c_info[0].irq = status; + i2c_register_board_info(1, + ntosd2_i2c_info, + ARRAY_SIZE(ntosd2_i2c_info)); + } + } + } + return status; +} + static struct davinci_mmc_config davinci_ntosd2_mmc_config = { .wires = 4, .version = MMC_CTLR_VERSION_1 @@ -186,6 +218,7 @@ static __init void davinci_ntosd2_init(void) { struct clk *aemif_clk; struct davinci_soc_info *soc_info = &davinci_soc_info; + int status; aemif_clk = clk_get(NULL, "aemif"); clk_enable(aemif_clk); @@ -209,6 +242,12 @@ static __init void davinci_ntosd2_init(void) platform_add_devices(davinci_ntosd2_devices, ARRAY_SIZE(davinci_ntosd2_devices)); + /* Initialize I2C interface specific for this board */ + status = ntosd2_init_i2c(); + if (status < 0) + pr_warning("davinci_ntosd2_init: msp430 irq setup failed:" + " %d\n", status); + davinci_serial_init(&uart_config); dm644x_init_asp(&dm644x_ntosd2_snd_data); diff --git a/trunk/arch/arm/mach-dove/common.c b/trunk/arch/arm/mach-dove/common.c index 6321567d8eaa..4db5de54b6a7 100644 --- a/trunk/arch/arm/mach-dove/common.c +++ b/trunk/arch/arm/mach-dove/common.c @@ -102,8 +102,7 @@ void __init dove_ehci1_init(void) void __init dove_ge00_init(struct mv643xx_eth_platform_data *eth_data) { orion_ge00_init(eth_data, DOVE_GE00_PHYS_BASE, - IRQ_DOVE_GE00_SUM, IRQ_DOVE_GE00_ERR, - 1600); + IRQ_DOVE_GE00_SUM, IRQ_DOVE_GE00_ERR); } /***************************************************************************** diff --git a/trunk/arch/arm/mach-exynos/mach-origen.c b/trunk/arch/arm/mach-exynos/mach-origen.c index 4e574c24581c..5ca80307d6d7 100644 --- a/trunk/arch/arm/mach-exynos/mach-origen.c +++ b/trunk/arch/arm/mach-exynos/mach-origen.c @@ -42,7 +42,6 @@ #include #include #include -#include #include #include @@ -735,11 +734,6 @@ static void __init origen_bt_setup(void) s3c_gpio_setpull(EXYNOS4_GPX2(2), S3C_GPIO_PULL_NONE); } -/* I2C module and id for HDMIPHY */ -static struct i2c_board_info hdmiphy_info = { - I2C_BOARD_INFO("hdmiphy-exynos4210", 0x38), -}; - static void s5p_tv_setup(void) { /* Direct HPD to HDMI chip */ @@ -787,7 +781,6 @@ static void __init origen_machine_init(void) s5p_tv_setup(); s5p_i2c_hdmiphy_set_platdata(NULL); - s5p_hdmi_set_platdata(&hdmiphy_info, NULL, 0); #ifdef CONFIG_DRM_EXYNOS s5p_device_fimd0.dev.platform_data = &drm_fimd_pdata; diff --git a/trunk/arch/arm/mach-exynos/mach-smdkv310.c b/trunk/arch/arm/mach-exynos/mach-smdkv310.c index 73f2bce097e1..3cfa688d274a 100644 --- a/trunk/arch/arm/mach-exynos/mach-smdkv310.c +++ b/trunk/arch/arm/mach-exynos/mach-smdkv310.c @@ -40,7 +40,6 @@ #include #include #include -#include #include #include @@ -355,11 +354,6 @@ static struct platform_pwm_backlight_data smdkv310_bl_data = { .pwm_period_ns = 1000, }; -/* I2C module and id for HDMIPHY */ -static struct i2c_board_info hdmiphy_info = { - I2C_BOARD_INFO("hdmiphy-exynos4210", 0x38), -}; - static void s5p_tv_setup(void) { /* direct HPD to HDMI chip */ @@ -394,7 +388,6 @@ static void __init smdkv310_machine_init(void) s5p_tv_setup(); s5p_i2c_hdmiphy_set_platdata(NULL); - s5p_hdmi_set_platdata(&hdmiphy_info, NULL, 0); samsung_keypad_set_platdata(&smdkv310_keypad_data); diff --git a/trunk/arch/arm/mach-exynos/pm_domains.c b/trunk/arch/arm/mach-exynos/pm_domains.c index c0bc83a7663e..373c3c00d24c 100644 --- a/trunk/arch/arm/mach-exynos/pm_domains.c +++ b/trunk/arch/arm/mach-exynos/pm_domains.c @@ -115,7 +115,7 @@ static __init int exynos_pm_dt_parse_domains(void) } #endif /* CONFIG_OF */ -static __init __maybe_unused void exynos_pm_add_dev_to_genpd(struct platform_device *pdev, +static __init void exynos_pm_add_dev_to_genpd(struct platform_device *pdev, struct exynos_pm_domain *pd) { if (pdev->dev.bus) { diff --git a/trunk/arch/arm/mach-gemini/irq.c b/trunk/arch/arm/mach-gemini/irq.c index 020852d3bdd8..ca70e5fcc7ac 100644 --- a/trunk/arch/arm/mach-gemini/irq.c +++ b/trunk/arch/arm/mach-gemini/irq.c @@ -17,7 +17,6 @@ #include #include #include -#include #include #define IRQ_SOURCE(base_addr) (base_addr + 0x00) diff --git a/trunk/arch/arm/mach-imx/Makefile b/trunk/arch/arm/mach-imx/Makefile index d004d37ad9d8..07f7c226e4cf 100644 --- a/trunk/arch/arm/mach-imx/Makefile +++ b/trunk/arch/arm/mach-imx/Makefile @@ -9,8 +9,7 @@ obj-$(CONFIG_SOC_IMX27) += clk-imx27.o mm-imx27.o ehci-imx27.o obj-$(CONFIG_SOC_IMX31) += mm-imx3.o cpu-imx31.o clk-imx31.o iomux-imx31.o ehci-imx31.o pm-imx3.o obj-$(CONFIG_SOC_IMX35) += mm-imx3.o cpu-imx35.o clk-imx35.o ehci-imx35.o pm-imx3.o -imx5-pm-$(CONFIG_PM) += pm-imx5.o -obj-$(CONFIG_SOC_IMX5) += cpu-imx5.o mm-imx5.o clk-imx51-imx53.o ehci-imx5.o $(imx5-pm-y) cpu_op-mx51.o +obj-$(CONFIG_SOC_IMX5) += cpu-imx5.o mm-imx5.o clk-imx51-imx53.o ehci-imx5.o pm-imx5.o cpu_op-mx51.o obj-$(CONFIG_COMMON_CLK) += clk-pllv1.o clk-pllv2.o clk-pllv3.o clk-gate2.o \ clk-pfd.o clk-busy.o @@ -71,13 +70,14 @@ obj-$(CONFIG_DEBUG_LL) += lluart.o obj-$(CONFIG_HAVE_IMX_GPC) += gpc.o obj-$(CONFIG_HAVE_IMX_MMDC) += mmdc.o obj-$(CONFIG_HAVE_IMX_SRC) += src.o -AFLAGS_headsmp.o :=-Wa,-march=armv7-a -obj-$(CONFIG_SMP) += headsmp.o platsmp.o +obj-$(CONFIG_CPU_V7) += head-v7.o +AFLAGS_head-v7.o :=-Wa,-march=armv7-a +obj-$(CONFIG_SMP) += platsmp.o obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o obj-$(CONFIG_SOC_IMX6Q) += clk-imx6q.o mach-imx6q.o ifeq ($(CONFIG_PM),y) -obj-$(CONFIG_SOC_IMX6Q) += pm-imx6q.o headsmp.o +obj-$(CONFIG_SOC_IMX6Q) += pm-imx6q.o endif # i.MX5 based machines diff --git a/trunk/arch/arm/mach-imx/clk-imx25.c b/trunk/arch/arm/mach-imx/clk-imx25.c index d20d4795f4ea..fdd8cc87c9fe 100644 --- a/trunk/arch/arm/mach-imx/clk-imx25.c +++ b/trunk/arch/arm/mach-imx/clk-imx25.c @@ -222,8 +222,10 @@ int __init mx25_clocks_init(void) clk_register_clkdev(clk[lcdc_ipg], "ipg", "imx-fb.0"); clk_register_clkdev(clk[lcdc_ahb], "ahb", "imx-fb.0"); clk_register_clkdev(clk[wdt_ipg], NULL, "imx2-wdt.0"); - clk_register_clkdev(clk[ssi1_ipg], NULL, "imx-ssi.0"); - clk_register_clkdev(clk[ssi2_ipg], NULL, "imx-ssi.1"); + clk_register_clkdev(clk[ssi1_ipg_per], "per", "imx-ssi.0"); + clk_register_clkdev(clk[ssi1_ipg], "ipg", "imx-ssi.0"); + clk_register_clkdev(clk[ssi2_ipg_per], "per", "imx-ssi.1"); + clk_register_clkdev(clk[ssi2_ipg], "ipg", "imx-ssi.1"); clk_register_clkdev(clk[esdhc1_ipg_per], "per", "sdhci-esdhc-imx25.0"); clk_register_clkdev(clk[esdhc1_ipg], "ipg", "sdhci-esdhc-imx25.0"); clk_register_clkdev(clk[esdhc1_ahb], "ahb", "sdhci-esdhc-imx25.0"); @@ -241,6 +243,6 @@ int __init mx25_clocks_init(void) clk_register_clkdev(clk[sdma_ahb], "ahb", "imx35-sdma"); clk_register_clkdev(clk[iim_ipg], "iim", NULL); - mxc_timer_init(MX25_IO_ADDRESS(MX25_GPT1_BASE_ADDR), MX25_INT_GPT1); + mxc_timer_init(MX25_IO_ADDRESS(MX25_GPT1_BASE_ADDR), 54); return 0; } diff --git a/trunk/arch/arm/mach-imx/clk-imx27.c b/trunk/arch/arm/mach-imx/clk-imx27.c index f69ca4680049..7aa6313fb167 100644 --- a/trunk/arch/arm/mach-imx/clk-imx27.c +++ b/trunk/arch/arm/mach-imx/clk-imx27.c @@ -223,7 +223,7 @@ int __init mx27_clocks_init(unsigned long fref) clk_register_clkdev(clk[per3_gate], "per", "imx-fb.0"); clk_register_clkdev(clk[lcdc_ipg_gate], "ipg", "imx-fb.0"); clk_register_clkdev(clk[lcdc_ahb_gate], "ahb", "imx-fb.0"); - clk_register_clkdev(clk[csi_ahb_gate], "ahb", "mx2-camera.0"); + clk_register_clkdev(clk[csi_ahb_gate], NULL, "mx2-camera.0"); clk_register_clkdev(clk[usb_div], "per", "fsl-usb2-udc"); clk_register_clkdev(clk[usb_ipg_gate], "ipg", "fsl-usb2-udc"); clk_register_clkdev(clk[usb_ahb_gate], "ahb", "fsl-usb2-udc"); @@ -250,10 +250,8 @@ int __init mx27_clocks_init(unsigned long fref) clk_register_clkdev(clk[i2c2_ipg_gate], NULL, "imx-i2c.1"); clk_register_clkdev(clk[owire_ipg_gate], NULL, "mxc_w1.0"); clk_register_clkdev(clk[kpp_ipg_gate], NULL, "imx-keypad"); - clk_register_clkdev(clk[emma_ahb_gate], "emma-ahb", "mx2-camera.0"); - clk_register_clkdev(clk[emma_ipg_gate], "emma-ipg", "mx2-camera.0"); - clk_register_clkdev(clk[emma_ahb_gate], "ahb", "m2m-emmaprp.0"); - clk_register_clkdev(clk[emma_ipg_gate], "ipg", "m2m-emmaprp.0"); + clk_register_clkdev(clk[emma_ahb_gate], "ahb", "imx-emma"); + clk_register_clkdev(clk[emma_ipg_gate], "ipg", "imx-emma"); clk_register_clkdev(clk[iim_ipg_gate], "iim", NULL); clk_register_clkdev(clk[gpio_ipg_gate], "gpio", NULL); clk_register_clkdev(clk[brom_ahb_gate], "brom", NULL); diff --git a/trunk/arch/arm/mach-imx/clk-imx31.c b/trunk/arch/arm/mach-imx/clk-imx31.c index 1253af2d9971..8e19e70f90f9 100644 --- a/trunk/arch/arm/mach-imx/clk-imx31.c +++ b/trunk/arch/arm/mach-imx/clk-imx31.c @@ -130,7 +130,7 @@ int __init mx31_clocks_init(unsigned long fref) clk_register_clkdev(clk[nfc], NULL, "mxc_nand.0"); clk_register_clkdev(clk[ipu_gate], NULL, "ipu-core"); clk_register_clkdev(clk[ipu_gate], NULL, "mx3_sdc_fb"); - clk_register_clkdev(clk[kpp_gate], NULL, "imx-keypad"); + clk_register_clkdev(clk[kpp_gate], "kpp", NULL); clk_register_clkdev(clk[usb_div_post], "per", "mxc-ehci.0"); clk_register_clkdev(clk[usb_gate], "ahb", "mxc-ehci.0"); clk_register_clkdev(clk[ipg], "ipg", "mxc-ehci.0"); diff --git a/trunk/arch/arm/mach-imx/clk-imx35.c b/trunk/arch/arm/mach-imx/clk-imx35.c index 65fb8bcd86cb..c6422fb10bae 100644 --- a/trunk/arch/arm/mach-imx/clk-imx35.c +++ b/trunk/arch/arm/mach-imx/clk-imx35.c @@ -230,8 +230,10 @@ int __init mx35_clocks_init() clk_register_clkdev(clk[ipu_gate], NULL, "mx3_sdc_fb"); clk_register_clkdev(clk[owire_gate], NULL, "mxc_w1"); clk_register_clkdev(clk[sdma_gate], NULL, "imx35-sdma"); - clk_register_clkdev(clk[ssi1_gate], NULL, "imx-ssi.0"); - clk_register_clkdev(clk[ssi2_gate], NULL, "imx-ssi.1"); + clk_register_clkdev(clk[ipg], "ipg", "imx-ssi.0"); + clk_register_clkdev(clk[ssi1_div_post], "per", "imx-ssi.0"); + clk_register_clkdev(clk[ipg], "ipg", "imx-ssi.1"); + clk_register_clkdev(clk[ssi2_div_post], "per", "imx-ssi.1"); /* i.mx35 has the i.mx21 type uart */ clk_register_clkdev(clk[uart1_gate], "per", "imx21-uart.0"); clk_register_clkdev(clk[ipg], "ipg", "imx21-uart.0"); diff --git a/trunk/arch/arm/mach-imx/clk-imx51-imx53.c b/trunk/arch/arm/mach-imx/clk-imx51-imx53.c index 4bdcaa97bd98..f6086693ebd2 100644 --- a/trunk/arch/arm/mach-imx/clk-imx51-imx53.c +++ b/trunk/arch/arm/mach-imx/clk-imx51-imx53.c @@ -303,7 +303,6 @@ static void __init mx5_clocks_common_init(unsigned long rate_ckil, clk_prepare_enable(clk[aips_tz2]); /* fec */ clk_prepare_enable(clk[spba]); clk_prepare_enable(clk[emi_fast_gate]); /* fec */ - clk_prepare_enable(clk[emi_slow_gate]); /* eim */ clk_prepare_enable(clk[tmax1]); clk_prepare_enable(clk[tmax2]); /* esdhc2, fec */ clk_prepare_enable(clk[tmax3]); /* esdhc1, esdhc4 */ diff --git a/trunk/arch/arm/mach-imx/clk-imx6q.c b/trunk/arch/arm/mach-imx/clk-imx6q.c index 4233d9e3531d..ea89520b6e22 100644 --- a/trunk/arch/arm/mach-imx/clk-imx6q.c +++ b/trunk/arch/arm/mach-imx/clk-imx6q.c @@ -152,7 +152,7 @@ enum mx6q_clks { ssi2, ssi3, uart_ipg, uart_serial, usboh3, usdhc1, usdhc2, usdhc3, usdhc4, vdo_axi, vpu_axi, cko1, pll1_sys, pll2_bus, pll3_usb_otg, pll4_audio, pll5_video, pll6_mlb, pll7_usb_host, pll8_enet, ssi1_ipg, - ssi2_ipg, ssi3_ipg, rom, usbphy1, usbphy2, ldb_di0_div_3_5, ldb_di1_div_3_5, + ssi2_ipg, ssi3_ipg, rom, usbphy1, usbphy2, clk_max }; @@ -288,10 +288,8 @@ int __init mx6q_clocks_init(void) clk[gpu3d_shader] = imx_clk_divider("gpu3d_shader", "gpu3d_shader_sel", base + 0x18, 29, 3); clk[ipu1_podf] = imx_clk_divider("ipu1_podf", "ipu1_sel", base + 0x3c, 11, 3); clk[ipu2_podf] = imx_clk_divider("ipu2_podf", "ipu2_sel", base + 0x3c, 16, 3); - clk[ldb_di0_div_3_5] = imx_clk_fixed_factor("ldb_di0_div_3_5", "ldb_di0_sel", 2, 7); - clk[ldb_di0_podf] = imx_clk_divider("ldb_di0_podf", "ldb_di0_div_3_5", base + 0x20, 10, 1); - clk[ldb_di1_div_3_5] = imx_clk_fixed_factor("ldb_di1_div_3_5", "ldb_di1_sel", 2, 7); - clk[ldb_di1_podf] = imx_clk_divider("ldb_di1_podf", "ldb_di1_div_3_5", base + 0x20, 11, 1); + clk[ldb_di0_podf] = imx_clk_divider("ldb_di0_podf", "ldb_di0_sel", base + 0x20, 10, 1); + clk[ldb_di1_podf] = imx_clk_divider("ldb_di1_podf", "ldb_di1_sel", base + 0x20, 11, 1); clk[ipu1_di0_pre] = imx_clk_divider("ipu1_di0_pre", "ipu1_di0_pre_sel", base + 0x34, 3, 3); clk[ipu1_di1_pre] = imx_clk_divider("ipu1_di1_pre", "ipu1_di1_pre_sel", base + 0x34, 12, 3); clk[ipu2_di0_pre] = imx_clk_divider("ipu2_di0_pre", "ipu2_di0_pre_sel", base + 0x38, 3, 3); diff --git a/trunk/arch/arm/mach-imx/headsmp.S b/trunk/arch/arm/mach-imx/head-v7.S similarity index 100% rename from trunk/arch/arm/mach-imx/headsmp.S rename to trunk/arch/arm/mach-imx/head-v7.S diff --git a/trunk/arch/arm/mach-imx/hotplug.c b/trunk/arch/arm/mach-imx/hotplug.c index f8f7437c83b8..20ed2d56c1af 100644 --- a/trunk/arch/arm/mach-imx/hotplug.c +++ b/trunk/arch/arm/mach-imx/hotplug.c @@ -42,6 +42,22 @@ static inline void cpu_enter_lowpower(void) : "cc"); } +static inline void cpu_leave_lowpower(void) +{ + unsigned int v; + + asm volatile( + "mrc p15, 0, %0, c1, c0, 0\n" + " orr %0, %0, %1\n" + " mcr p15, 0, %0, c1, c0, 0\n" + " mrc p15, 0, %0, c1, c0, 1\n" + " orr %0, %0, %2\n" + " mcr p15, 0, %0, c1, c0, 1\n" + : "=&r" (v) + : "Ir" (CR_C), "Ir" (0x40) + : "cc"); +} + /* * platform-specific code to shutdown a CPU * @@ -51,10 +67,11 @@ void platform_cpu_die(unsigned int cpu) { cpu_enter_lowpower(); imx_enable_cpu(cpu, false); + cpu_do_idle(); + cpu_leave_lowpower(); - /* spin here until hardware takes it down */ - while (1) - ; + /* We should never return from idle */ + panic("cpu %d unexpectedly exit from shutdown\n", cpu); } int platform_cpu_disable(unsigned int cpu) diff --git a/trunk/arch/arm/mach-imx/mach-armadillo5x0.c b/trunk/arch/arm/mach-imx/mach-armadillo5x0.c index 5985ed1b8c98..2c6ab3273f9e 100644 --- a/trunk/arch/arm/mach-imx/mach-armadillo5x0.c +++ b/trunk/arch/arm/mach-imx/mach-armadillo5x0.c @@ -526,8 +526,7 @@ static void __init armadillo5x0_init(void) imx31_add_mxc_nand(&armadillo5x0_nand_board_info); /* set NAND page size to 2k if not configured via boot mode pins */ - __raw_writel(__raw_readl(mx3_ccm_base + MXC_CCM_RCSR) | - (1 << 30), mx3_ccm_base + MXC_CCM_RCSR); + __raw_writel(__raw_readl(MXC_CCM_RCSR) | (1 << 30), MXC_CCM_RCSR); /* RTC */ /* Get RTC IRQ and register the chip */ diff --git a/trunk/arch/arm/mach-imx/mach-imx6q.c b/trunk/arch/arm/mach-imx/mach-imx6q.c index 045b3f6a387d..5ec0608f2a76 100644 --- a/trunk/arch/arm/mach-imx/mach-imx6q.c +++ b/trunk/arch/arm/mach-imx/mach-imx6q.c @@ -71,7 +71,7 @@ void imx6q_restart(char mode, const char *cmd) /* For imx6q sabrelite board: set KSZ9021RN RGMII pad skew */ static int ksz9021rn_phy_fixup(struct phy_device *phydev) { - if (IS_BUILTIN(CONFIG_PHYLIB)) { + if (IS_ENABLED(CONFIG_PHYLIB)) { /* min rx data delay */ phy_write(phydev, 0x0b, 0x8105); phy_write(phydev, 0x0c, 0x0000); @@ -112,7 +112,7 @@ static void __init imx6q_sabrelite_cko1_setup(void) static void __init imx6q_sabrelite_init(void) { - if (IS_BUILTIN(CONFIG_PHYLIB)) + if (IS_ENABLED(CONFIG_PHYLIB)) phy_register_fixup_for_uid(PHY_ID_KSZ9021, MICREL_PHY_ID_MASK, ksz9021rn_phy_fixup); imx6q_sabrelite_cko1_setup(); diff --git a/trunk/arch/arm/mach-integrator/core.c b/trunk/arch/arm/mach-integrator/core.c index 3fa6c51390da..ebf680bebdf2 100644 --- a/trunk/arch/arm/mach-integrator/core.c +++ b/trunk/arch/arm/mach-integrator/core.c @@ -11,7 +11,6 @@ #include #include #include -#include #include #include #include diff --git a/trunk/arch/arm/mach-integrator/integrator_ap.c b/trunk/arch/arm/mach-integrator/integrator_ap.c index 3b2267529f5e..7b1055c8e0b9 100644 --- a/trunk/arch/arm/mach-integrator/integrator_ap.c +++ b/trunk/arch/arm/mach-integrator/integrator_ap.c @@ -456,7 +456,7 @@ static void __init ap_init_timer(void) clk = clk_get_sys("ap_timer", NULL); BUG_ON(IS_ERR(clk)); - clk_prepare_enable(clk); + clk_enable(clk); rate = clk_get_rate(clk); writel(0, TIMER0_VA_BASE + TIMER_CTRL); diff --git a/trunk/arch/arm/mach-kirkwood/Makefile.boot b/trunk/arch/arm/mach-kirkwood/Makefile.boot index a13299d758e1..2a576abf409b 100644 --- a/trunk/arch/arm/mach-kirkwood/Makefile.boot +++ b/trunk/arch/arm/mach-kirkwood/Makefile.boot @@ -7,8 +7,7 @@ dtb-$(CONFIG_MACH_DLINK_KIRKWOOD_DT) += kirkwood-dns320.dtb dtb-$(CONFIG_MACH_DLINK_KIRKWOOD_DT) += kirkwood-dns325.dtb dtb-$(CONFIG_MACH_ICONNECT_DT) += kirkwood-iconnect.dtb dtb-$(CONFIG_MACH_IB62X0_DT) += kirkwood-ib62x0.dtb -dtb-$(CONFIG_MACH_TS219_DT) += kirkwood-ts219-6281.dtb -dtb-$(CONFIG_MACH_TS219_DT) += kirkwood-ts219-6282.dtb +dtb-$(CONFIG_MACH_TS219_DT) += kirkwood-qnap-ts219.dtb dtb-$(CONFIG_MACH_GOFLEXNET_DT) += kirkwood-goflexnet.dtb -dtb-$(CONFIG_MACH_LSXL_DT) += kirkwood-lschlv2.dtb -dtb-$(CONFIG_MACH_LSXL_DT) += kirkwood-lsxhl.dtb +dbt-$(CONFIG_MACH_LSXL_DT) += kirkwood-lschlv2.dtb +dbt-$(CONFIG_MACH_LSXL_DT) += kirkwood-lsxhl.dtb diff --git a/trunk/arch/arm/mach-kirkwood/common.c b/trunk/arch/arm/mach-kirkwood/common.c index 1201191d7f1b..c4b64adcbfce 100644 --- a/trunk/arch/arm/mach-kirkwood/common.c +++ b/trunk/arch/arm/mach-kirkwood/common.c @@ -301,7 +301,7 @@ void __init kirkwood_ge00_init(struct mv643xx_eth_platform_data *eth_data) { orion_ge00_init(eth_data, GE00_PHYS_BASE, IRQ_KIRKWOOD_GE00_SUM, - IRQ_KIRKWOOD_GE00_ERR, 1600); + IRQ_KIRKWOOD_GE00_ERR); /* The interface forgets the MAC address assigned by u-boot if the clock is turned off, so claim the clk now. */ clk_prepare_enable(ge0); @@ -315,7 +315,7 @@ void __init kirkwood_ge01_init(struct mv643xx_eth_platform_data *eth_data) { orion_ge01_init(eth_data, GE01_PHYS_BASE, IRQ_KIRKWOOD_GE01_SUM, - IRQ_KIRKWOOD_GE01_ERR, 1600); + IRQ_KIRKWOOD_GE01_ERR); clk_prepare_enable(ge1); } @@ -517,13 +517,6 @@ void __init kirkwood_wdt_init(void) void __init kirkwood_init_early(void) { orion_time_set_base(TIMER_VIRT_BASE); - - /* - * Some Kirkwood devices allocate their coherent buffers from atomic - * context. Increase size of atomic coherent pool to make sure such - * the allocations won't fail. - */ - init_dma_coherent_pool_size(SZ_1M); } int kirkwood_tclk; diff --git a/trunk/arch/arm/mach-kirkwood/db88f6281-bp-setup.c b/trunk/arch/arm/mach-kirkwood/db88f6281-bp-setup.c index be90b7d0e10b..d93359379598 100644 --- a/trunk/arch/arm/mach-kirkwood/db88f6281-bp-setup.c +++ b/trunk/arch/arm/mach-kirkwood/db88f6281-bp-setup.c @@ -10,7 +10,6 @@ #include #include -#include #include #include #include diff --git a/trunk/arch/arm/mach-mmp/Kconfig b/trunk/arch/arm/mach-mmp/Kconfig index d697d07a1bf0..7fddd01b85b9 100644 --- a/trunk/arch/arm/mach-mmp/Kconfig +++ b/trunk/arch/arm/mach-mmp/Kconfig @@ -108,21 +108,18 @@ endmenu config CPU_PXA168 bool select CPU_MOHAWK - select COMMON_CLK help Select code specific to PXA168 config CPU_PXA910 bool select CPU_MOHAWK - select COMMON_CLK help Select code specific to PXA910 config CPU_MMP2 bool select CPU_PJ4 - select COMMON_CLK help Select code specific to MMP2. MMP2 is ARMv7 compatible. diff --git a/trunk/arch/arm/mach-mmp/sram.c b/trunk/arch/arm/mach-mmp/sram.c index 7e8a5a2e1ec7..4304f9519372 100644 --- a/trunk/arch/arm/mach-mmp/sram.c +++ b/trunk/arch/arm/mach-mmp/sram.c @@ -68,7 +68,7 @@ static int __devinit sram_probe(struct platform_device *pdev) struct resource *res; int ret = 0; - if (!pdata || !pdata->pool_name) + if (!pdata && !pdata->pool_name) return -ENODEV; info = kzalloc(sizeof(*info), GFP_KERNEL); diff --git a/trunk/arch/arm/mach-mv78xx0/addr-map.c b/trunk/arch/arm/mach-mv78xx0/addr-map.c index a9bc84180d21..62b53d710efd 100644 --- a/trunk/arch/arm/mach-mv78xx0/addr-map.c +++ b/trunk/arch/arm/mach-mv78xx0/addr-map.c @@ -37,7 +37,7 @@ #define WIN0_OFF(n) (BRIDGE_VIRT_BASE + 0x0000 + ((n) << 4)) #define WIN8_OFF(n) (BRIDGE_VIRT_BASE + 0x0900 + (((n) - 8) << 4)) -static void __init __iomem *win_cfg_base(const struct orion_addr_map_cfg *cfg, int win) +static void __init __iomem *win_cfg_base(int win) { /* * Find the control register base address for this window. diff --git a/trunk/arch/arm/mach-mv78xx0/common.c b/trunk/arch/arm/mach-mv78xx0/common.c index 3057f7d4329a..b4c53b846c9c 100644 --- a/trunk/arch/arm/mach-mv78xx0/common.c +++ b/trunk/arch/arm/mach-mv78xx0/common.c @@ -213,8 +213,7 @@ void __init mv78xx0_ge00_init(struct mv643xx_eth_platform_data *eth_data) { orion_ge00_init(eth_data, GE00_PHYS_BASE, IRQ_MV78XX0_GE00_SUM, - IRQ_MV78XX0_GE_ERR, - MV643XX_TX_CSUM_DEFAULT_LIMIT); + IRQ_MV78XX0_GE_ERR); } @@ -225,8 +224,7 @@ void __init mv78xx0_ge01_init(struct mv643xx_eth_platform_data *eth_data) { orion_ge01_init(eth_data, GE01_PHYS_BASE, IRQ_MV78XX0_GE01_SUM, - NO_IRQ, - MV643XX_TX_CSUM_DEFAULT_LIMIT); + NO_IRQ); } diff --git a/trunk/arch/arm/mach-mxs/Kconfig b/trunk/arch/arm/mach-mxs/Kconfig index 9a8bbda195b2..ccdf83b17cf1 100644 --- a/trunk/arch/arm/mach-mxs/Kconfig +++ b/trunk/arch/arm/mach-mxs/Kconfig @@ -2,6 +2,9 @@ if ARCH_MXS source "arch/arm/mach-mxs/devices/Kconfig" +config MXS_OCOTP + bool + config SOC_IMX23 bool select ARM_AMBA @@ -63,6 +66,7 @@ config MACH_MX28EVK select MXS_HAVE_PLATFORM_MXS_SAIF select MXS_HAVE_PLATFORM_MXS_I2C select MXS_HAVE_PLATFORM_RTC_STMP3XXX + select MXS_OCOTP help Include support for MX28EVK platform. This includes specific configurations for the board and its peripherals. @@ -90,6 +94,7 @@ config MODULE_M28 select MXS_HAVE_PLATFORM_MXS_I2C select MXS_HAVE_PLATFORM_MXS_MMC select MXS_HAVE_PLATFORM_MXSFB + select MXS_OCOTP config MODULE_APX4 bool @@ -101,6 +106,7 @@ config MODULE_APX4 select MXS_HAVE_PLATFORM_MXS_I2C select MXS_HAVE_PLATFORM_MXS_MMC select MXS_HAVE_PLATFORM_MXS_SAIF + select MXS_OCOTP config MACH_TX28 bool "Ka-Ro TX28 module" diff --git a/trunk/arch/arm/mach-mxs/Makefile b/trunk/arch/arm/mach-mxs/Makefile index fed3695a1339..e41590ccb437 100644 --- a/trunk/arch/arm/mach-mxs/Makefile +++ b/trunk/arch/arm/mach-mxs/Makefile @@ -1,6 +1,7 @@ # Common support -obj-y := devices.o icoll.o iomux.o ocotp.o system.o timer.o mm.o +obj-y := devices.o icoll.o iomux.o system.o timer.o mm.o +obj-$(CONFIG_MXS_OCOTP) += ocotp.o obj-$(CONFIG_PM) += pm.o obj-$(CONFIG_MACH_MXS_DT) += mach-mxs.o diff --git a/trunk/arch/arm/mach-mxs/mach-mxs.c b/trunk/arch/arm/mach-mxs/mach-mxs.c index ff886e01a0b0..8dabfe81d07c 100644 --- a/trunk/arch/arm/mach-mxs/mach-mxs.c +++ b/trunk/arch/arm/mach-mxs/mach-mxs.c @@ -261,7 +261,7 @@ static void __init apx4devkit_init(void) enable_clk_enet_out(); if (IS_BUILTIN(CONFIG_PHYLIB)) - phy_register_fixup_for_uid(PHY_ID_KSZ8051, MICREL_PHY_ID_MASK, + phy_register_fixup_for_uid(PHY_ID_KS8051, MICREL_PHY_ID_MASK, apx4devkit_phy_fixup); mxsfb_pdata.mode_list = apx4devkit_video_modes; diff --git a/trunk/arch/arm/mach-omap2/Kconfig b/trunk/arch/arm/mach-omap2/Kconfig index 346fd26f3aa6..dd2db025f778 100644 --- a/trunk/arch/arm/mach-omap2/Kconfig +++ b/trunk/arch/arm/mach-omap2/Kconfig @@ -62,14 +62,13 @@ config ARCH_OMAP4 select PM_OPP if PM select USB_ARCH_HAS_EHCI if USB_SUPPORT select ARM_CPU_SUSPEND if PM - select ARCH_NEEDS_CPU_IDLE_COUPLED if SMP + select ARCH_NEEDS_CPU_IDLE_COUPLED config SOC_OMAP5 bool "TI OMAP5" select CPU_V7 select ARM_GIC select HAVE_SMP - select ARM_CPU_SUSPEND if PM comment "OMAP Core Type" depends on ARCH_OMAP2 @@ -232,11 +231,10 @@ config MACH_OMAP3_PANDORA select OMAP_PACKAGE_CBB select REGULATOR_FIXED_VOLTAGE if REGULATOR -config MACH_TOUCHBOOK +config MACH_OMAP3_TOUCHBOOK bool "OMAP3 Touch Book" depends on ARCH_OMAP3 default y - select OMAP_PACKAGE_CBB config MACH_OMAP_3430SDP bool "OMAP 3430 SDP board" diff --git a/trunk/arch/arm/mach-omap2/Makefile b/trunk/arch/arm/mach-omap2/Makefile index 34c2c7f59f0a..f6a24b3f9c4f 100644 --- a/trunk/arch/arm/mach-omap2/Makefile +++ b/trunk/arch/arm/mach-omap2/Makefile @@ -255,7 +255,7 @@ obj-$(CONFIG_MACH_OMAP_3630SDP) += board-zoom-display.o obj-$(CONFIG_MACH_CM_T35) += board-cm-t35.o obj-$(CONFIG_MACH_CM_T3517) += board-cm-t3517.o obj-$(CONFIG_MACH_IGEP0020) += board-igep0020.o -obj-$(CONFIG_MACH_TOUCHBOOK) += board-omap3touchbook.o +obj-$(CONFIG_MACH_OMAP3_TOUCHBOOK) += board-omap3touchbook.o obj-$(CONFIG_MACH_OMAP_4430SDP) += board-4430sdp.o obj-$(CONFIG_MACH_OMAP4_PANDA) += board-omap4panda.o diff --git a/trunk/arch/arm/mach-omap2/board-igep0020.c b/trunk/arch/arm/mach-omap2/board-igep0020.c index 28214483aaba..74915295482e 100644 --- a/trunk/arch/arm/mach-omap2/board-igep0020.c +++ b/trunk/arch/arm/mach-omap2/board-igep0020.c @@ -554,8 +554,6 @@ static const struct usbhs_omap_board_data igep3_usbhs_bdata __initconst = { #ifdef CONFIG_OMAP_MUX static struct omap_board_mux board_mux[] __initdata = { - /* SMSC9221 LAN Controller ETH IRQ (GPIO_176) */ - OMAP3_MUX(MCSPI1_CS2, OMAP_MUX_MODE4 | OMAP_PIN_INPUT), { .reg_offset = OMAP_MUX_TERMINATOR }, }; #endif diff --git a/trunk/arch/arm/mach-omap2/board-omap3evm.c b/trunk/arch/arm/mach-omap2/board-omap3evm.c index 0d362e9f9cb9..ef230a0eb5eb 100644 --- a/trunk/arch/arm/mach-omap2/board-omap3evm.c +++ b/trunk/arch/arm/mach-omap2/board-omap3evm.c @@ -58,7 +58,6 @@ #include "hsmmc.h" #include "common-board-devices.h" -#define OMAP3_EVM_TS_GPIO 175 #define OMAP3_EVM_EHCI_VBUS 22 #define OMAP3_EVM_EHCI_SELECT 61 diff --git a/trunk/arch/arm/mach-omap2/clock33xx_data.c b/trunk/arch/arm/mach-omap2/clock33xx_data.c index ae27de8899a6..25bbcc7ca4dc 100644 --- a/trunk/arch/arm/mach-omap2/clock33xx_data.c +++ b/trunk/arch/arm/mach-omap2/clock33xx_data.c @@ -1036,13 +1036,13 @@ static struct omap_clk am33xx_clks[] = { CLK(NULL, "mmu_fck", &mmu_fck, CK_AM33XX), CLK(NULL, "smartreflex0_fck", &smartreflex0_fck, CK_AM33XX), CLK(NULL, "smartreflex1_fck", &smartreflex1_fck, CK_AM33XX), - CLK(NULL, "timer1_fck", &timer1_fck, CK_AM33XX), - CLK(NULL, "timer2_fck", &timer2_fck, CK_AM33XX), - CLK(NULL, "timer3_fck", &timer3_fck, CK_AM33XX), - CLK(NULL, "timer4_fck", &timer4_fck, CK_AM33XX), - CLK(NULL, "timer5_fck", &timer5_fck, CK_AM33XX), - CLK(NULL, "timer6_fck", &timer6_fck, CK_AM33XX), - CLK(NULL, "timer7_fck", &timer7_fck, CK_AM33XX), + CLK(NULL, "gpt1_fck", &timer1_fck, CK_AM33XX), + CLK(NULL, "gpt2_fck", &timer2_fck, CK_AM33XX), + CLK(NULL, "gpt3_fck", &timer3_fck, CK_AM33XX), + CLK(NULL, "gpt4_fck", &timer4_fck, CK_AM33XX), + CLK(NULL, "gpt5_fck", &timer5_fck, CK_AM33XX), + CLK(NULL, "gpt6_fck", &timer6_fck, CK_AM33XX), + CLK(NULL, "gpt7_fck", &timer7_fck, CK_AM33XX), CLK(NULL, "usbotg_fck", &usbotg_fck, CK_AM33XX), CLK(NULL, "ieee5000_fck", &ieee5000_fck, CK_AM33XX), CLK(NULL, "wdt1_fck", &wdt1_fck, CK_AM33XX), diff --git a/trunk/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c b/trunk/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c index f99e65cfb862..a0d68dbecfa3 100644 --- a/trunk/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c +++ b/trunk/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c @@ -241,52 +241,6 @@ static void omap3_clkdm_deny_idle(struct clockdomain *clkdm) _clkdm_del_autodeps(clkdm); } -static int omap3xxx_clkdm_clk_enable(struct clockdomain *clkdm) -{ - bool hwsup = false; - - if (!clkdm->clktrctrl_mask) - return 0; - - hwsup = omap2_cm_is_clkdm_in_hwsup(clkdm->pwrdm.ptr->prcm_offs, - clkdm->clktrctrl_mask); - - if (hwsup) { - /* Disable HW transitions when we are changing deps */ - _disable_hwsup(clkdm); - _clkdm_add_autodeps(clkdm); - _enable_hwsup(clkdm); - } else { - if (clkdm->flags & CLKDM_CAN_FORCE_WAKEUP) - omap3_clkdm_wakeup(clkdm); - } - - return 0; -} - -static int omap3xxx_clkdm_clk_disable(struct clockdomain *clkdm) -{ - bool hwsup = false; - - if (!clkdm->clktrctrl_mask) - return 0; - - hwsup = omap2_cm_is_clkdm_in_hwsup(clkdm->pwrdm.ptr->prcm_offs, - clkdm->clktrctrl_mask); - - if (hwsup) { - /* Disable HW transitions when we are changing deps */ - _disable_hwsup(clkdm); - _clkdm_del_autodeps(clkdm); - _enable_hwsup(clkdm); - } else { - if (clkdm->flags & CLKDM_CAN_FORCE_SLEEP) - omap3_clkdm_sleep(clkdm); - } - - return 0; -} - struct clkdm_ops omap2_clkdm_operations = { .clkdm_add_wkdep = omap2_clkdm_add_wkdep, .clkdm_del_wkdep = omap2_clkdm_del_wkdep, @@ -313,6 +267,6 @@ struct clkdm_ops omap3_clkdm_operations = { .clkdm_wakeup = omap3_clkdm_wakeup, .clkdm_allow_idle = omap3_clkdm_allow_idle, .clkdm_deny_idle = omap3_clkdm_deny_idle, - .clkdm_clk_enable = omap3xxx_clkdm_clk_enable, - .clkdm_clk_disable = omap3xxx_clkdm_clk_disable, + .clkdm_clk_enable = omap2_clkdm_clk_enable, + .clkdm_clk_disable = omap2_clkdm_clk_disable, }; diff --git a/trunk/arch/arm/mach-omap2/cm-regbits-34xx.h b/trunk/arch/arm/mach-omap2/cm-regbits-34xx.h index 975f6bda0e0b..766338fe4d34 100644 --- a/trunk/arch/arm/mach-omap2/cm-regbits-34xx.h +++ b/trunk/arch/arm/mach-omap2/cm-regbits-34xx.h @@ -67,7 +67,6 @@ #define OMAP3430_EN_IVA2_DPLL_MASK (0x7 << 0) /* CM_IDLEST_IVA2 */ -#define OMAP3430_ST_IVA2_SHIFT 0 #define OMAP3430_ST_IVA2_MASK (1 << 0) /* CM_IDLEST_PLL_IVA2 */ diff --git a/trunk/arch/arm/mach-omap2/common-board-devices.c b/trunk/arch/arm/mach-omap2/common-board-devices.c index c1875862679f..14734746457c 100644 --- a/trunk/arch/arm/mach-omap2/common-board-devices.c +++ b/trunk/arch/arm/mach-omap2/common-board-devices.c @@ -35,6 +35,16 @@ static struct omap2_mcspi_device_config ads7846_mcspi_config = { .turbo_mode = 0, }; +/* + * ADS7846 driver maybe request a gpio according to the value + * of pdata->get_pendown_state, but we have done this. So set + * get_pendown_state to avoid twice gpio requesting. + */ +static int omap3_get_pendown_state(void) +{ + return !gpio_get_value(OMAP3_EVM_TS_GPIO); +} + static struct ads7846_platform_data ads7846_config = { .x_max = 0x0fff, .y_max = 0x0fff, @@ -45,6 +55,7 @@ static struct ads7846_platform_data ads7846_config = { .debounce_rep = 1, .gpio_pendown = -EINVAL, .keep_vref_on = 1, + .get_pendown_state = &omap3_get_pendown_state, }; static struct spi_board_info ads7846_spi_board_info __initdata = { diff --git a/trunk/arch/arm/mach-omap2/common-board-devices.h b/trunk/arch/arm/mach-omap2/common-board-devices.h index a0b4a42836ab..4c4ef6a6166b 100644 --- a/trunk/arch/arm/mach-omap2/common-board-devices.h +++ b/trunk/arch/arm/mach-omap2/common-board-devices.h @@ -4,6 +4,7 @@ #include "twl-common.h" #define NAND_BLOCK_SIZE SZ_128K +#define OMAP3_EVM_TS_GPIO 175 struct mtd_partition; struct ads7846_platform_data; diff --git a/trunk/arch/arm/mach-omap2/cpuidle44xx.c b/trunk/arch/arm/mach-omap2/cpuidle44xx.c index 288bee6cbb76..ee05e193fc61 100644 --- a/trunk/arch/arm/mach-omap2/cpuidle44xx.c +++ b/trunk/arch/arm/mach-omap2/cpuidle44xx.c @@ -238,9 +238,8 @@ int __init omap4_idle_init(void) for_each_cpu(cpu_id, cpu_online_mask) { dev = &per_cpu(omap4_idle_dev, cpu_id); dev->cpu = cpu_id; -#ifdef CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED dev->coupled_cpus = *cpu_online_mask; -#endif + cpuidle_register_driver(&omap4_idle_driver); if (cpuidle_register_device(dev)) { diff --git a/trunk/arch/arm/mach-omap2/mux.h b/trunk/arch/arm/mach-omap2/mux.h index 76f9b3c2f586..471e62a74a16 100644 --- a/trunk/arch/arm/mach-omap2/mux.h +++ b/trunk/arch/arm/mach-omap2/mux.h @@ -127,6 +127,7 @@ struct omap_mux_partition { * @gpio: GPIO number * @muxnames: available signal modes for a ball * @balls: available balls on the package + * @partition: mux partition */ struct omap_mux { u16 reg_offset; diff --git a/trunk/arch/arm/mach-omap2/omap-wakeupgen.c b/trunk/arch/arm/mach-omap2/omap-wakeupgen.c index 330d4c6e746b..05fdebfaa195 100644 --- a/trunk/arch/arm/mach-omap2/omap-wakeupgen.c +++ b/trunk/arch/arm/mach-omap2/omap-wakeupgen.c @@ -46,7 +46,7 @@ static void __iomem *wakeupgen_base; static void __iomem *sar_base; static DEFINE_SPINLOCK(wakeupgen_lock); -static unsigned int irq_target_cpu[MAX_IRQS]; +static unsigned int irq_target_cpu[NR_IRQS]; static unsigned int irq_banks = MAX_NR_REG_BANKS; static unsigned int max_irqs = MAX_IRQS; static unsigned int omap_secure_apis; diff --git a/trunk/arch/arm/mach-omap2/omap_hwmod.c b/trunk/arch/arm/mach-omap2/omap_hwmod.c index 37afbd173c2c..6ca8e519968d 100644 --- a/trunk/arch/arm/mach-omap2/omap_hwmod.c +++ b/trunk/arch/arm/mach-omap2/omap_hwmod.c @@ -1889,7 +1889,6 @@ static int _enable(struct omap_hwmod *oh) _enable_sysc(oh); } } else { - _omap4_disable_module(oh); _disable_clocks(oh); pr_debug("omap_hwmod: %s: _wait_target_ready: %d\n", oh->name, r); diff --git a/trunk/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/trunk/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c index ce7e6068768f..c9e38200216b 100644 --- a/trunk/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c +++ b/trunk/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c @@ -100,9 +100,9 @@ static struct omap_hwmod omap3xxx_mpu_hwmod = { /* IVA2 (IVA2) */ static struct omap_hwmod_rst_info omap3xxx_iva_resets[] = { - { .name = "logic", .rst_shift = 0, .st_shift = 8 }, - { .name = "seq0", .rst_shift = 1, .st_shift = 9 }, - { .name = "seq1", .rst_shift = 2, .st_shift = 10 }, + { .name = "logic", .rst_shift = 0 }, + { .name = "seq0", .rst_shift = 1 }, + { .name = "seq1", .rst_shift = 2 }, }; static struct omap_hwmod omap3xxx_iva_hwmod = { @@ -112,15 +112,6 @@ static struct omap_hwmod omap3xxx_iva_hwmod = { .rst_lines = omap3xxx_iva_resets, .rst_lines_cnt = ARRAY_SIZE(omap3xxx_iva_resets), .main_clk = "iva2_ck", - .prcm = { - .omap2 = { - .module_offs = OMAP3430_IVA2_MOD, - .prcm_reg_id = 1, - .module_bit = OMAP3430_CM_FCLKEN_IVA2_EN_IVA2_SHIFT, - .idlest_reg_id = 1, - .idlest_idle_bit = OMAP3430_ST_IVA2_SHIFT, - } - }, }; /* timer class */ diff --git a/trunk/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/trunk/arch/arm/mach-omap2/omap_hwmod_44xx_data.c index afb60917a948..242aee498ceb 100644 --- a/trunk/arch/arm/mach-omap2/omap_hwmod_44xx_data.c +++ b/trunk/arch/arm/mach-omap2/omap_hwmod_44xx_data.c @@ -4210,7 +4210,7 @@ static struct omap_hwmod_ocp_if omap44xx_dsp__iva = { }; /* dsp -> sl2if */ -static struct omap_hwmod_ocp_if __maybe_unused omap44xx_dsp__sl2if = { +static struct omap_hwmod_ocp_if omap44xx_dsp__sl2if = { .master = &omap44xx_dsp_hwmod, .slave = &omap44xx_sl2if_hwmod, .clk = "dpll_iva_m5x2_ck", @@ -4828,7 +4828,7 @@ static struct omap_hwmod_ocp_if omap44xx_l3_main_2__iss = { }; /* iva -> sl2if */ -static struct omap_hwmod_ocp_if __maybe_unused omap44xx_iva__sl2if = { +static struct omap_hwmod_ocp_if omap44xx_iva__sl2if = { .master = &omap44xx_iva_hwmod, .slave = &omap44xx_sl2if_hwmod, .clk = "dpll_iva_m5x2_ck", @@ -5362,7 +5362,7 @@ static struct omap_hwmod_ocp_if omap44xx_l4_wkup__scrm = { }; /* l3_main_2 -> sl2if */ -static struct omap_hwmod_ocp_if __maybe_unused omap44xx_l3_main_2__sl2if = { +static struct omap_hwmod_ocp_if omap44xx_l3_main_2__sl2if = { .master = &omap44xx_l3_main_2_hwmod, .slave = &omap44xx_sl2if_hwmod, .clk = "l3_div_ck", @@ -6032,7 +6032,7 @@ static struct omap_hwmod_ocp_if *omap44xx_hwmod_ocp_ifs[] __initdata = { &omap44xx_l4_abe__dmic, &omap44xx_l4_abe__dmic_dma, &omap44xx_dsp__iva, - /* &omap44xx_dsp__sl2if, */ + &omap44xx_dsp__sl2if, &omap44xx_l4_cfg__dsp, &omap44xx_l3_main_2__dss, &omap44xx_l4_per__dss, @@ -6068,7 +6068,7 @@ static struct omap_hwmod_ocp_if *omap44xx_hwmod_ocp_ifs[] __initdata = { &omap44xx_l4_per__i2c4, &omap44xx_l3_main_2__ipu, &omap44xx_l3_main_2__iss, - /* &omap44xx_iva__sl2if, */ + &omap44xx_iva__sl2if, &omap44xx_l3_main_2__iva, &omap44xx_l4_wkup__kbd, &omap44xx_l4_cfg__mailbox, @@ -6099,7 +6099,7 @@ static struct omap_hwmod_ocp_if *omap44xx_hwmod_ocp_ifs[] __initdata = { &omap44xx_l4_cfg__cm_core, &omap44xx_l4_wkup__prm, &omap44xx_l4_wkup__scrm, - /* &omap44xx_l3_main_2__sl2if, */ + &omap44xx_l3_main_2__sl2if, &omap44xx_l4_abe__slimbus1, &omap44xx_l4_abe__slimbus1_dma, &omap44xx_l4_per__slimbus2, diff --git a/trunk/arch/arm/mach-omap2/opp4xxx_data.c b/trunk/arch/arm/mach-omap2/opp4xxx_data.c index c95415da23c2..2293ba27101b 100644 --- a/trunk/arch/arm/mach-omap2/opp4xxx_data.c +++ b/trunk/arch/arm/mach-omap2/opp4xxx_data.c @@ -94,7 +94,7 @@ int __init omap4_opp_init(void) { int r = -ENODEV; - if (!cpu_is_omap443x()) + if (!cpu_is_omap44xx()) return r; r = omap_init_opp_table(omap44xx_opp_def_list, diff --git a/trunk/arch/arm/mach-omap2/pm34xx.c b/trunk/arch/arm/mach-omap2/pm34xx.c index 05bd8f02723f..e4fc88c65dbd 100644 --- a/trunk/arch/arm/mach-omap2/pm34xx.c +++ b/trunk/arch/arm/mach-omap2/pm34xx.c @@ -272,16 +272,21 @@ void omap_sram_idle(void) per_next_state = pwrdm_read_next_pwrst(per_pwrdm); core_next_state = pwrdm_read_next_pwrst(core_pwrdm); - pwrdm_pre_transition(NULL); + if (mpu_next_state < PWRDM_POWER_ON) { + pwrdm_pre_transition(mpu_pwrdm); + pwrdm_pre_transition(neon_pwrdm); + } /* PER */ if (per_next_state < PWRDM_POWER_ON) { + pwrdm_pre_transition(per_pwrdm); per_going_off = (per_next_state == PWRDM_POWER_OFF) ? 1 : 0; omap2_gpio_prepare_for_idle(per_going_off); } /* CORE */ if (core_next_state < PWRDM_POWER_ON) { + pwrdm_pre_transition(core_pwrdm); if (core_next_state == PWRDM_POWER_OFF) { omap3_core_save_context(); omap3_cm_save_context(); @@ -334,14 +339,20 @@ void omap_sram_idle(void) omap2_prm_clear_mod_reg_bits(OMAP3430_AUTO_OFF_MASK, OMAP3430_GR_MOD, OMAP3_PRM_VOLTCTRL_OFFSET); + pwrdm_post_transition(core_pwrdm); } omap3_intc_resume_idle(); - pwrdm_post_transition(NULL); - /* PER */ - if (per_next_state < PWRDM_POWER_ON) + if (per_next_state < PWRDM_POWER_ON) { omap2_gpio_resume_after_idle(); + pwrdm_post_transition(per_pwrdm); + } + + if (mpu_next_state < PWRDM_POWER_ON) { + pwrdm_post_transition(mpu_pwrdm); + pwrdm_post_transition(neon_pwrdm); + } } static void omap3_pm_idle(void) diff --git a/trunk/arch/arm/mach-omap2/serial.c b/trunk/arch/arm/mach-omap2/serial.c index 9e80d209d138..c1b93c752d70 100644 --- a/trunk/arch/arm/mach-omap2/serial.c +++ b/trunk/arch/arm/mach-omap2/serial.c @@ -81,9 +81,8 @@ static struct omap_uart_port_info omap_serial_default_info[] __initdata = { }; #ifdef CONFIG_PM -static void omap_uart_enable_wakeup(struct device *dev, bool enable) +static void omap_uart_enable_wakeup(struct platform_device *pdev, bool enable) { - struct platform_device *pdev = to_platform_device(dev); struct omap_device *od = to_omap_device(pdev); if (!od) @@ -100,17 +99,15 @@ static void omap_uart_enable_wakeup(struct device *dev, bool enable) * in Smartidle Mode When Configured for DMA Operations. * WA: configure uart in force idle mode. */ -static void omap_uart_set_noidle(struct device *dev) +static void omap_uart_set_noidle(struct platform_device *pdev) { - struct platform_device *pdev = to_platform_device(dev); struct omap_device *od = to_omap_device(pdev); omap_hwmod_set_slave_idlemode(od->hwmods[0], HWMOD_IDLEMODE_NO); } -static void omap_uart_set_smartidle(struct device *dev) +static void omap_uart_set_smartidle(struct platform_device *pdev) { - struct platform_device *pdev = to_platform_device(dev); struct omap_device *od = to_omap_device(pdev); u8 idlemode; @@ -123,10 +120,10 @@ static void omap_uart_set_smartidle(struct device *dev) } #else -static void omap_uart_enable_wakeup(struct device *dev, bool enable) +static void omap_uart_enable_wakeup(struct platform_device *pdev, bool enable) {} -static void omap_uart_set_noidle(struct device *dev) {} -static void omap_uart_set_smartidle(struct device *dev) {} +static void omap_uart_set_noidle(struct platform_device *pdev) {} +static void omap_uart_set_smartidle(struct platform_device *pdev) {} #endif /* CONFIG_PM */ #ifdef CONFIG_OMAP_MUX @@ -307,9 +304,6 @@ void __init omap_serial_init_port(struct omap_board_data *bdata, omap_up.dma_rx_timeout = info->dma_rx_timeout; omap_up.dma_rx_poll_rate = info->dma_rx_poll_rate; omap_up.autosuspend_timeout = info->autosuspend_timeout; - omap_up.DTR_gpio = info->DTR_gpio; - omap_up.DTR_inverted = info->DTR_inverted; - omap_up.DTR_present = info->DTR_present; pdata = &omap_up; pdata_size = sizeof(struct omap_uart_port_info); diff --git a/trunk/arch/arm/mach-omap2/sleep44xx.S b/trunk/arch/arm/mach-omap2/sleep44xx.S index 91e71d8f46f0..9f6b83d1b193 100644 --- a/trunk/arch/arm/mach-omap2/sleep44xx.S +++ b/trunk/arch/arm/mach-omap2/sleep44xx.S @@ -56,13 +56,9 @@ ppa_por_params: * The restore function pointer is stored at CPUx_WAKEUP_NS_PA_ADDR_OFFSET. * It returns to the caller for CPU INACTIVE and ON power states or in case * CPU failed to transition to targeted OFF/DORMANT state. - * - * omap4_finish_suspend() calls v7_flush_dcache_all() which doesn't save - * stack frame and it expects the caller to take care of it. Hence the entire - * stack frame is saved to avoid possible stack corruption. */ ENTRY(omap4_finish_suspend) - stmfd sp!, {r4-r12, lr} + stmfd sp!, {lr} cmp r0, #0x0 beq do_WFI @ No lowpower state, jump to WFI @@ -230,7 +226,7 @@ scu_gp_clear: skip_scu_gp_clear: isb dsb - ldmfd sp!, {r4-r12, pc} + ldmfd sp!, {pc} ENDPROC(omap4_finish_suspend) /* diff --git a/trunk/arch/arm/mach-omap2/timer.c b/trunk/arch/arm/mach-omap2/timer.c index 2ba4f57dda86..2ff6d41ec6c6 100644 --- a/trunk/arch/arm/mach-omap2/timer.c +++ b/trunk/arch/arm/mach-omap2/timer.c @@ -260,7 +260,6 @@ static u32 notrace dmtimer_read_sched_clock(void) return 0; } -#ifdef CONFIG_OMAP_32K_TIMER /* Setup free-running counter for clocksource */ static int __init omap2_sync32k_clocksource_init(void) { @@ -300,12 +299,6 @@ static int __init omap2_sync32k_clocksource_init(void) return ret; } -#else -static inline int omap2_sync32k_clocksource_init(void) -{ - return -ENODEV; -} -#endif static void __init omap2_gptimer_clocksource_init(int gptimer_id, const char *fck_source) diff --git a/trunk/arch/arm/mach-omap2/twl-common.c b/trunk/arch/arm/mach-omap2/twl-common.c index db5ff6642375..de47f170ba50 100644 --- a/trunk/arch/arm/mach-omap2/twl-common.c +++ b/trunk/arch/arm/mach-omap2/twl-common.c @@ -67,7 +67,6 @@ void __init omap_pmic_init(int bus, u32 clkrate, const char *pmic_type, int pmic_irq, struct twl4030_platform_data *pmic_data) { - omap_mux_init_signal("sys_nirq", OMAP_PIN_INPUT_PULLUP | OMAP_PIN_OFF_WAKEUPENABLE); strncpy(pmic_i2c_board_info.type, pmic_type, sizeof(pmic_i2c_board_info.type)); pmic_i2c_board_info.irq = pmic_irq; diff --git a/trunk/arch/arm/mach-orion5x/common.c b/trunk/arch/arm/mach-orion5x/common.c index a6cd14ab1e4e..9148b229d0de 100644 --- a/trunk/arch/arm/mach-orion5x/common.c +++ b/trunk/arch/arm/mach-orion5x/common.c @@ -109,8 +109,7 @@ void __init orion5x_eth_init(struct mv643xx_eth_platform_data *eth_data) { orion_ge00_init(eth_data, ORION5X_ETH_PHYS_BASE, IRQ_ORION5X_ETH_SUM, - IRQ_ORION5X_ETH_ERR, - MV643XX_TX_CSUM_DEFAULT_LIMIT); + IRQ_ORION5X_ETH_ERR); } @@ -204,13 +203,6 @@ void __init orion5x_wdt_init(void) void __init orion5x_init_early(void) { orion_time_set_base(TIMER_VIRT_BASE); - - /* - * Some Orion5x devices allocate their coherent buffers from atomic - * context. Increase size of atomic coherent pool to make sure such - * the allocations won't fail. - */ - init_dma_coherent_pool_size(SZ_1M); } int orion5x_tclk; diff --git a/trunk/arch/arm/mach-prima2/Makefile b/trunk/arch/arm/mach-prima2/Makefile index 841847d56032..13dd1604d951 100644 --- a/trunk/arch/arm/mach-prima2/Makefile +++ b/trunk/arch/arm/mach-prima2/Makefile @@ -1,5 +1,6 @@ obj-y := timer.o obj-y += irq.o +obj-y += clock.o obj-y += rstc.o obj-y += prima2.o obj-y += rtciobrg.o diff --git a/trunk/arch/arm/mach-prima2/clock.c b/trunk/arch/arm/mach-prima2/clock.c new file mode 100644 index 000000000000..aebad7e565cf --- /dev/null +++ b/trunk/arch/arm/mach-prima2/clock.c @@ -0,0 +1,510 @@ +/* + * Clock tree for CSR SiRFprimaII + * + * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company. + * + * Licensed under GPLv2 or later. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define SIRFSOC_CLKC_CLK_EN0 0x0000 +#define SIRFSOC_CLKC_CLK_EN1 0x0004 +#define SIRFSOC_CLKC_REF_CFG 0x0014 +#define SIRFSOC_CLKC_CPU_CFG 0x0018 +#define SIRFSOC_CLKC_MEM_CFG 0x001c +#define SIRFSOC_CLKC_SYS_CFG 0x0020 +#define SIRFSOC_CLKC_IO_CFG 0x0024 +#define SIRFSOC_CLKC_DSP_CFG 0x0028 +#define SIRFSOC_CLKC_GFX_CFG 0x002c +#define SIRFSOC_CLKC_MM_CFG 0x0030 +#define SIRFSOC_LKC_LCD_CFG 0x0034 +#define SIRFSOC_CLKC_MMC_CFG 0x0038 +#define SIRFSOC_CLKC_PLL1_CFG0 0x0040 +#define SIRFSOC_CLKC_PLL2_CFG0 0x0044 +#define SIRFSOC_CLKC_PLL3_CFG0 0x0048 +#define SIRFSOC_CLKC_PLL1_CFG1 0x004c +#define SIRFSOC_CLKC_PLL2_CFG1 0x0050 +#define SIRFSOC_CLKC_PLL3_CFG1 0x0054 +#define SIRFSOC_CLKC_PLL1_CFG2 0x0058 +#define SIRFSOC_CLKC_PLL2_CFG2 0x005c +#define SIRFSOC_CLKC_PLL3_CFG2 0x0060 + +#define SIRFSOC_CLOCK_VA_BASE SIRFSOC_VA(0x005000) + +#define KHZ 1000 +#define MHZ (KHZ * KHZ) + +struct clk_ops { + unsigned long (*get_rate)(struct clk *clk); + long (*round_rate)(struct clk *clk, unsigned long rate); + int (*set_rate)(struct clk *clk, unsigned long rate); + int (*enable)(struct clk *clk); + int (*disable)(struct clk *clk); + struct clk *(*get_parent)(struct clk *clk); + int (*set_parent)(struct clk *clk, struct clk *parent); +}; + +struct clk { + struct clk *parent; /* parent clk */ + unsigned long rate; /* clock rate in Hz */ + signed char usage; /* clock enable count */ + signed char enable_bit; /* enable bit: 0 ~ 63 */ + unsigned short regofs; /* register offset */ + struct clk_ops *ops; /* clock operation */ +}; + +static DEFINE_SPINLOCK(clocks_lock); + +static inline unsigned long clkc_readl(unsigned reg) +{ + return readl(SIRFSOC_CLOCK_VA_BASE + reg); +} + +static inline void clkc_writel(u32 val, unsigned reg) +{ + writel(val, SIRFSOC_CLOCK_VA_BASE + reg); +} + +/* + * osc_rtc - real time oscillator - 32.768KHz + * osc_sys - high speed oscillator - 26MHz + */ + +static struct clk clk_rtc = { + .rate = 32768, +}; + +static struct clk clk_osc = { + .rate = 26 * MHZ, +}; + +/* + * std pll + */ +static unsigned long std_pll_get_rate(struct clk *clk) +{ + unsigned long fin = clk_get_rate(clk->parent); + u32 regcfg2 = clk->regofs + SIRFSOC_CLKC_PLL1_CFG2 - + SIRFSOC_CLKC_PLL1_CFG0; + + if (clkc_readl(regcfg2) & BIT(2)) { + /* pll bypass mode */ + clk->rate = fin; + } else { + /* fout = fin * nf / nr / od */ + u32 cfg0 = clkc_readl(clk->regofs); + u32 nf = (cfg0 & (BIT(13) - 1)) + 1; + u32 nr = ((cfg0 >> 13) & (BIT(6) - 1)) + 1; + u32 od = ((cfg0 >> 19) & (BIT(4) - 1)) + 1; + WARN_ON(fin % MHZ); + clk->rate = fin / MHZ * nf / nr / od * MHZ; + } + + return clk->rate; +} + +static int std_pll_set_rate(struct clk *clk, unsigned long rate) +{ + unsigned long fin, nf, nr, od, reg; + + /* + * fout = fin * nf / (nr * od); + * set od = 1, nr = fin/MHz, so fout = nf * MHz + */ + + nf = rate / MHZ; + if (unlikely((rate % MHZ) || nf > BIT(13) || nf < 1)) + return -EINVAL; + + fin = clk_get_rate(clk->parent); + BUG_ON(fin < MHZ); + + nr = fin / MHZ; + BUG_ON((fin % MHZ) || nr > BIT(6)); + + od = 1; + + reg = (nf - 1) | ((nr - 1) << 13) | ((od - 1) << 19); + clkc_writel(reg, clk->regofs); + + reg = clk->regofs + SIRFSOC_CLKC_PLL1_CFG1 - SIRFSOC_CLKC_PLL1_CFG0; + clkc_writel((nf >> 1) - 1, reg); + + reg = clk->regofs + SIRFSOC_CLKC_PLL1_CFG2 - SIRFSOC_CLKC_PLL1_CFG0; + while (!(clkc_readl(reg) & BIT(6))) + cpu_relax(); + + clk->rate = 0; /* set to zero will force recalculation */ + return 0; +} + +static struct clk_ops std_pll_ops = { + .get_rate = std_pll_get_rate, + .set_rate = std_pll_set_rate, +}; + +static struct clk clk_pll1 = { + .parent = &clk_osc, + .regofs = SIRFSOC_CLKC_PLL1_CFG0, + .ops = &std_pll_ops, +}; + +static struct clk clk_pll2 = { + .parent = &clk_osc, + .regofs = SIRFSOC_CLKC_PLL2_CFG0, + .ops = &std_pll_ops, +}; + +static struct clk clk_pll3 = { + .parent = &clk_osc, + .regofs = SIRFSOC_CLKC_PLL3_CFG0, + .ops = &std_pll_ops, +}; + +/* + * clock domains - cpu, mem, sys/io + */ + +static struct clk clk_mem; + +static struct clk *dmn_get_parent(struct clk *clk) +{ + struct clk *clks[] = { + &clk_osc, &clk_rtc, &clk_pll1, &clk_pll2, &clk_pll3 + }; + u32 cfg = clkc_readl(clk->regofs); + WARN_ON((cfg & (BIT(3) - 1)) > 4); + return clks[cfg & (BIT(3) - 1)]; +} + +static int dmn_set_parent(struct clk *clk, struct clk *parent) +{ + const struct clk *clks[] = { + &clk_osc, &clk_rtc, &clk_pll1, &clk_pll2, &clk_pll3 + }; + u32 cfg = clkc_readl(clk->regofs); + int i; + for (i = 0; i < ARRAY_SIZE(clks); i++) { + if (clks[i] == parent) { + cfg &= ~(BIT(3) - 1); + clkc_writel(cfg | i, clk->regofs); + /* BIT(3) - switching status: 1 - busy, 0 - done */ + while (clkc_readl(clk->regofs) & BIT(3)) + cpu_relax(); + return 0; + } + } + return -EINVAL; +} + +static unsigned long dmn_get_rate(struct clk *clk) +{ + unsigned long fin = clk_get_rate(clk->parent); + u32 cfg = clkc_readl(clk->regofs); + if (cfg & BIT(24)) { + /* fcd bypass mode */ + clk->rate = fin; + } else { + /* + * wait count: bit[19:16], hold count: bit[23:20] + */ + u32 wait = (cfg >> 16) & (BIT(4) - 1); + u32 hold = (cfg >> 20) & (BIT(4) - 1); + + clk->rate = fin / (wait + hold + 2); + } + + return clk->rate; +} + +static int dmn_set_rate(struct clk *clk, unsigned long rate) +{ + unsigned long fin; + unsigned ratio, wait, hold, reg; + unsigned bits = (clk == &clk_mem) ? 3 : 4; + + fin = clk_get_rate(clk->parent); + ratio = fin / rate; + + if (unlikely(ratio < 2 || ratio > BIT(bits + 1))) + return -EINVAL; + + WARN_ON(fin % rate); + + wait = (ratio >> 1) - 1; + hold = ratio - wait - 2; + + reg = clkc_readl(clk->regofs); + reg &= ~(((BIT(bits) - 1) << 16) | ((BIT(bits) - 1) << 20)); + reg |= (wait << 16) | (hold << 20) | BIT(25); + clkc_writel(reg, clk->regofs); + + /* waiting FCD been effective */ + while (clkc_readl(clk->regofs) & BIT(25)) + cpu_relax(); + + clk->rate = 0; /* set to zero will force recalculation */ + + return 0; +} + +/* + * cpu clock has no FCD register in Prima2, can only change pll + */ +static int cpu_set_rate(struct clk *clk, unsigned long rate) +{ + int ret1, ret2; + struct clk *cur_parent, *tmp_parent; + + cur_parent = dmn_get_parent(clk); + BUG_ON(cur_parent == NULL || cur_parent->usage > 1); + + /* switch to tmp pll before setting parent clock's rate */ + tmp_parent = cur_parent == &clk_pll1 ? &clk_pll2 : &clk_pll1; + ret1 = dmn_set_parent(clk, tmp_parent); + BUG_ON(ret1); + + ret2 = clk_set_rate(cur_parent, rate); + + ret1 = dmn_set_parent(clk, cur_parent); + + clk->rate = 0; /* set to zero will force recalculation */ + + return ret2 ? ret2 : ret1; +} + +static struct clk_ops cpu_ops = { + .get_parent = dmn_get_parent, + .set_parent = dmn_set_parent, + .set_rate = cpu_set_rate, +}; + +static struct clk clk_cpu = { + .parent = &clk_pll1, + .regofs = SIRFSOC_CLKC_CPU_CFG, + .ops = &cpu_ops, +}; + + +static struct clk_ops msi_ops = { + .set_rate = dmn_set_rate, + .get_rate = dmn_get_rate, + .set_parent = dmn_set_parent, + .get_parent = dmn_get_parent, +}; + +static struct clk clk_mem = { + .parent = &clk_pll2, + .regofs = SIRFSOC_CLKC_MEM_CFG, + .ops = &msi_ops, +}; + +static struct clk clk_sys = { + .parent = &clk_pll3, + .regofs = SIRFSOC_CLKC_SYS_CFG, + .ops = &msi_ops, +}; + +static struct clk clk_io = { + .parent = &clk_pll3, + .regofs = SIRFSOC_CLKC_IO_CFG, + .ops = &msi_ops, +}; + +/* + * on-chip clock sets + */ +static struct clk_lookup onchip_clks[] = { + { + .dev_id = "rtc", + .clk = &clk_rtc, + }, { + .dev_id = "osc", + .clk = &clk_osc, + }, { + .dev_id = "pll1", + .clk = &clk_pll1, + }, { + .dev_id = "pll2", + .clk = &clk_pll2, + }, { + .dev_id = "pll3", + .clk = &clk_pll3, + }, { + .dev_id = "cpu", + .clk = &clk_cpu, + }, { + .dev_id = "mem", + .clk = &clk_mem, + }, { + .dev_id = "sys", + .clk = &clk_sys, + }, { + .dev_id = "io", + .clk = &clk_io, + }, +}; + +int clk_enable(struct clk *clk) +{ + unsigned long flags; + + if (unlikely(IS_ERR_OR_NULL(clk))) + return -EINVAL; + + if (clk->parent) + clk_enable(clk->parent); + + spin_lock_irqsave(&clocks_lock, flags); + if (!clk->usage++ && clk->ops && clk->ops->enable) + clk->ops->enable(clk); + spin_unlock_irqrestore(&clocks_lock, flags); + return 0; +} +EXPORT_SYMBOL(clk_enable); + +void clk_disable(struct clk *clk) +{ + unsigned long flags; + + if (unlikely(IS_ERR_OR_NULL(clk))) + return; + + WARN_ON(!clk->usage); + + spin_lock_irqsave(&clocks_lock, flags); + if (--clk->usage == 0 && clk->ops && clk->ops->disable) + clk->ops->disable(clk); + spin_unlock_irqrestore(&clocks_lock, flags); + + if (clk->parent) + clk_disable(clk->parent); +} +EXPORT_SYMBOL(clk_disable); + +unsigned long clk_get_rate(struct clk *clk) +{ + if (unlikely(IS_ERR_OR_NULL(clk))) + return 0; + + if (clk->rate) + return clk->rate; + + if (clk->ops && clk->ops->get_rate) + return clk->ops->get_rate(clk); + + return clk_get_rate(clk->parent); +} +EXPORT_SYMBOL(clk_get_rate); + +long clk_round_rate(struct clk *clk, unsigned long rate) +{ + if (unlikely(IS_ERR_OR_NULL(clk))) + return 0; + + if (clk->ops && clk->ops->round_rate) + return clk->ops->round_rate(clk, rate); + + return 0; +} +EXPORT_SYMBOL(clk_round_rate); + +int clk_set_rate(struct clk *clk, unsigned long rate) +{ + if (unlikely(IS_ERR_OR_NULL(clk))) + return -EINVAL; + + if (!clk->ops || !clk->ops->set_rate) + return -EINVAL; + + return clk->ops->set_rate(clk, rate); +} +EXPORT_SYMBOL(clk_set_rate); + +int clk_set_parent(struct clk *clk, struct clk *parent) +{ + int ret; + unsigned long flags; + + if (unlikely(IS_ERR_OR_NULL(clk))) + return -EINVAL; + + if (!clk->ops || !clk->ops->set_parent) + return -EINVAL; + + spin_lock_irqsave(&clocks_lock, flags); + ret = clk->ops->set_parent(clk, parent); + if (!ret) { + parent->usage += clk->usage; + clk->parent->usage -= clk->usage; + BUG_ON(clk->parent->usage < 0); + clk->parent = parent; + } + spin_unlock_irqrestore(&clocks_lock, flags); + return ret; +} +EXPORT_SYMBOL(clk_set_parent); + +struct clk *clk_get_parent(struct clk *clk) +{ + unsigned long flags; + + if (unlikely(IS_ERR_OR_NULL(clk))) + return NULL; + + if (!clk->ops || !clk->ops->get_parent) + return clk->parent; + + spin_lock_irqsave(&clocks_lock, flags); + clk->parent = clk->ops->get_parent(clk); + spin_unlock_irqrestore(&clocks_lock, flags); + return clk->parent; +} +EXPORT_SYMBOL(clk_get_parent); + +static void __init sirfsoc_clk_init(void) +{ + clkdev_add_table(onchip_clks, ARRAY_SIZE(onchip_clks)); +} + +static struct of_device_id clkc_ids[] = { + { .compatible = "sirf,prima2-clkc" }, + {}, +}; + +void __init sirfsoc_of_clk_init(void) +{ + struct device_node *np; + struct resource res; + struct map_desc sirfsoc_clkc_iodesc = { + .virtual = SIRFSOC_CLOCK_VA_BASE, + .type = MT_DEVICE, + }; + + np = of_find_matching_node(NULL, clkc_ids); + if (!np) + panic("unable to find compatible clkc node in dtb\n"); + + if (of_address_to_resource(np, 0, &res)) + panic("unable to find clkc range in dtb"); + of_node_put(np); + + sirfsoc_clkc_iodesc.pfn = __phys_to_pfn(res.start); + sirfsoc_clkc_iodesc.length = 1 + res.end - res.start; + + iotable_init(&sirfsoc_clkc_iodesc, 1); + + sirfsoc_clk_init(); +} diff --git a/trunk/arch/arm/mach-prima2/prima2.c b/trunk/arch/arm/mach-prima2/prima2.c index e9a17aebe0d6..8f0429d4b79f 100644 --- a/trunk/arch/arm/mach-prima2/prima2.c +++ b/trunk/arch/arm/mach-prima2/prima2.c @@ -38,6 +38,7 @@ static const char *prima2cb_dt_match[] __initdata = { MACHINE_START(PRIMA2_EVB, "prima2cb") /* Maintainer: Barry Song */ .atag_offset = 0x100, + .init_early = sirfsoc_of_clk_init, .map_io = sirfsoc_map_lluart, .init_irq = sirfsoc_of_irq_init, .timer = &sirfsoc_timer, diff --git a/trunk/arch/arm/mach-prima2/timer.c b/trunk/arch/arm/mach-prima2/timer.c index d95bf252f694..f224107de7bc 100644 --- a/trunk/arch/arm/mach-prima2/timer.c +++ b/trunk/arch/arm/mach-prima2/timer.c @@ -21,8 +21,6 @@ #include #include -#include "common.h" - #define SIRFSOC_TIMER_COUNTER_LO 0x0000 #define SIRFSOC_TIMER_COUNTER_HI 0x0004 #define SIRFSOC_TIMER_MATCH_0 0x0008 @@ -190,13 +188,9 @@ static void __init sirfsoc_clockevent_init(void) static void __init sirfsoc_timer_init(void) { unsigned long rate; - struct clk *clk; - - /* initialize clocking early, we want to set the OS timer */ - sirfsoc_of_clk_init(); /* timer's input clock is io clock */ - clk = clk_get_sys("io", NULL); + struct clk *clk = clk_get_sys("io", NULL); BUG_ON(IS_ERR(clk)); diff --git a/trunk/arch/arm/mach-pxa/raumfeld.c b/trunk/arch/arm/mach-pxa/raumfeld.c index d89d87ae144c..5905ed130e94 100644 --- a/trunk/arch/arm/mach-pxa/raumfeld.c +++ b/trunk/arch/arm/mach-pxa/raumfeld.c @@ -953,12 +953,12 @@ static struct i2c_board_info raumfeld_connector_i2c_board_info __initdata = { static struct eeti_ts_platform_data eeti_ts_pdata = { .irq_active_high = 1, - .irq_gpio = GPIO_TOUCH_IRQ, }; static struct i2c_board_info raumfeld_controller_i2c_board_info __initdata = { .type = "eeti_ts", .addr = 0x0a, + .irq = PXA_GPIO_TO_IRQ(GPIO_TOUCH_IRQ), .platform_data = &eeti_ts_pdata, }; diff --git a/trunk/arch/arm/mach-realview/core.c b/trunk/arch/arm/mach-realview/core.c index ff007d15e0ec..45868bb43cbd 100644 --- a/trunk/arch/arm/mach-realview/core.c +++ b/trunk/arch/arm/mach-realview/core.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -225,10 +226,115 @@ struct mmci_platform_data realview_mmc1_plat_data = { .cd_invert = true, }; +/* + * Clock handling + */ +static const struct icst_params realview_oscvco_params = { + .ref = 24000000, + .vco_max = ICST307_VCO_MAX, + .vco_min = ICST307_VCO_MIN, + .vd_min = 4 + 8, + .vd_max = 511 + 8, + .rd_min = 1 + 2, + .rd_max = 127 + 2, + .s2div = icst307_s2div, + .idx2s = icst307_idx2s, +}; + +static void realview_oscvco_set(struct clk *clk, struct icst_vco vco) +{ + void __iomem *sys_lock = __io_address(REALVIEW_SYS_BASE) + REALVIEW_SYS_LOCK_OFFSET; + u32 val; + + val = readl(clk->vcoreg) & ~0x7ffff; + val |= vco.v | (vco.r << 9) | (vco.s << 16); + + writel(0xa05f, sys_lock); + writel(val, clk->vcoreg); + writel(0, sys_lock); +} + +static const struct clk_ops oscvco_clk_ops = { + .round = icst_clk_round, + .set = icst_clk_set, + .setvco = realview_oscvco_set, +}; + +static struct clk oscvco_clk = { + .ops = &oscvco_clk_ops, + .params = &realview_oscvco_params, +}; + +/* + * These are fixed clocks. + */ +static struct clk ref24_clk = { + .rate = 24000000, +}; + +static struct clk sp804_clk = { + .rate = 1000000, +}; + +static struct clk dummy_apb_pclk; + +static struct clk_lookup lookups[] = { + { /* Bus clock */ + .con_id = "apb_pclk", + .clk = &dummy_apb_pclk, + }, { /* UART0 */ + .dev_id = "dev:uart0", + .clk = &ref24_clk, + }, { /* UART1 */ + .dev_id = "dev:uart1", + .clk = &ref24_clk, + }, { /* UART2 */ + .dev_id = "dev:uart2", + .clk = &ref24_clk, + }, { /* UART3 */ + .dev_id = "fpga:uart3", + .clk = &ref24_clk, + }, { /* UART3 is on the dev chip in PB1176 */ + .dev_id = "dev:uart3", + .clk = &ref24_clk, + }, { /* UART4 only exists in PB1176 */ + .dev_id = "fpga:uart4", + .clk = &ref24_clk, + }, { /* KMI0 */ + .dev_id = "fpga:kmi0", + .clk = &ref24_clk, + }, { /* KMI1 */ + .dev_id = "fpga:kmi1", + .clk = &ref24_clk, + }, { /* MMC0 */ + .dev_id = "fpga:mmc0", + .clk = &ref24_clk, + }, { /* CLCD is in the PB1176 and EB DevChip */ + .dev_id = "dev:clcd", + .clk = &oscvco_clk, + }, { /* PB:CLCD */ + .dev_id = "issp:clcd", + .clk = &oscvco_clk, + }, { /* SSP */ + .dev_id = "dev:ssp0", + .clk = &ref24_clk, + }, { /* SP804 timers */ + .dev_id = "sp804", + .clk = &sp804_clk, + }, +}; + void __init realview_init_early(void) { void __iomem *sys = __io_address(REALVIEW_SYS_BASE); + if (machine_is_realview_pb1176()) + oscvco_clk.vcoreg = sys + REALVIEW_SYS_OSC0_OFFSET; + else + oscvco_clk.vcoreg = sys + REALVIEW_SYS_OSC4_OFFSET; + + clkdev_add_table(lookups, ARRAY_SIZE(lookups)); + versatile_sched_clock_init(sys + REALVIEW_SYS_24MHz_OFFSET, 24000000); } diff --git a/trunk/arch/arm/mach-realview/include/mach/clkdev.h b/trunk/arch/arm/mach-realview/include/mach/clkdev.h new file mode 100644 index 000000000000..e58d0771b64e --- /dev/null +++ b/trunk/arch/arm/mach-realview/include/mach/clkdev.h @@ -0,0 +1,16 @@ +#ifndef __ASM_MACH_CLKDEV_H +#define __ASM_MACH_CLKDEV_H + +#include + +struct clk { + unsigned long rate; + const struct clk_ops *ops; + const struct icst_params *params; + void __iomem *vcoreg; +}; + +#define __clk_get(clk) ({ 1; }) +#define __clk_put(clk) do { } while (0) + +#endif diff --git a/trunk/arch/arm/mach-realview/realview_eb.c b/trunk/arch/arm/mach-realview/realview_eb.c index a33e33b76733..baf382c5e776 100644 --- a/trunk/arch/arm/mach-realview/realview_eb.c +++ b/trunk/arch/arm/mach-realview/realview_eb.c @@ -27,7 +27,6 @@ #include #include #include -#include #include #include @@ -415,7 +414,6 @@ static void __init realview_eb_timer_init(void) else timer_irq = IRQ_EB_TIMER0_1; - realview_clk_init(__io_address(REALVIEW_SYS_BASE), false); realview_timer_init(timer_irq); realview_eb_twd_init(); } diff --git a/trunk/arch/arm/mach-realview/realview_pb1176.c b/trunk/arch/arm/mach-realview/realview_pb1176.c index f0298cbc203e..b1d7cafa1a6d 100644 --- a/trunk/arch/arm/mach-realview/realview_pb1176.c +++ b/trunk/arch/arm/mach-realview/realview_pb1176.c @@ -29,7 +29,6 @@ #include #include #include -#include #include #include @@ -327,7 +326,6 @@ static void __init realview_pb1176_timer_init(void) timer2_va_base = __io_address(REALVIEW_PB1176_TIMER2_3_BASE); timer3_va_base = __io_address(REALVIEW_PB1176_TIMER2_3_BASE) + 0x20; - realview_clk_init(__io_address(REALVIEW_SYS_BASE), true); realview_timer_init(IRQ_DC1176_TIMER0); } diff --git a/trunk/arch/arm/mach-realview/realview_pb11mp.c b/trunk/arch/arm/mach-realview/realview_pb11mp.c index 1f019f76f7b5..a98c536e3327 100644 --- a/trunk/arch/arm/mach-realview/realview_pb11mp.c +++ b/trunk/arch/arm/mach-realview/realview_pb11mp.c @@ -27,7 +27,6 @@ #include #include #include -#include #include #include @@ -313,7 +312,6 @@ static void __init realview_pb11mp_timer_init(void) timer2_va_base = __io_address(REALVIEW_PB11MP_TIMER2_3_BASE); timer3_va_base = __io_address(REALVIEW_PB11MP_TIMER2_3_BASE) + 0x20; - realview_clk_init(__io_address(REALVIEW_SYS_BASE), false); realview_timer_init(IRQ_TC11MP_TIMER0_1); realview_pb11mp_twd_init(); } diff --git a/trunk/arch/arm/mach-realview/realview_pba8.c b/trunk/arch/arm/mach-realview/realview_pba8.c index 5032775dbfee..59650174e6ed 100644 --- a/trunk/arch/arm/mach-realview/realview_pba8.c +++ b/trunk/arch/arm/mach-realview/realview_pba8.c @@ -27,7 +27,6 @@ #include #include #include -#include #include #include @@ -262,7 +261,6 @@ static void __init realview_pba8_timer_init(void) timer2_va_base = __io_address(REALVIEW_PBA8_TIMER2_3_BASE); timer3_va_base = __io_address(REALVIEW_PBA8_TIMER2_3_BASE) + 0x20; - realview_clk_init(__io_address(REALVIEW_SYS_BASE), false); realview_timer_init(IRQ_PBA8_TIMER0_1); } diff --git a/trunk/arch/arm/mach-realview/realview_pbx.c b/trunk/arch/arm/mach-realview/realview_pbx.c index de64ba0ddb95..3f2f605624e9 100644 --- a/trunk/arch/arm/mach-realview/realview_pbx.c +++ b/trunk/arch/arm/mach-realview/realview_pbx.c @@ -26,7 +26,6 @@ #include #include #include -#include #include #include @@ -321,7 +320,6 @@ static void __init realview_pbx_timer_init(void) timer2_va_base = __io_address(REALVIEW_PBX_TIMER2_3_BASE); timer3_va_base = __io_address(REALVIEW_PBX_TIMER2_3_BASE) + 0x20; - realview_clk_init(__io_address(REALVIEW_SYS_BASE), false); realview_timer_init(IRQ_PBX_TIMER0_1); realview_pbx_twd_init(); } diff --git a/trunk/arch/arm/mach-s3c24xx/Kconfig b/trunk/arch/arm/mach-s3c24xx/Kconfig index d56b0f7f2b20..e24961109b70 100644 --- a/trunk/arch/arm/mach-s3c24xx/Kconfig +++ b/trunk/arch/arm/mach-s3c24xx/Kconfig @@ -483,7 +483,7 @@ config MACH_NEO1973_GTA02 select I2C select POWER_SUPPLY select MACH_NEO1973 - select S3C24XX_PWM + select S3C2410_PWM select S3C_DEV_USB_HOST help Say Y here if you are using the Openmoko GTA02 / Freerunner GSM Phone @@ -493,7 +493,7 @@ config MACH_RX1950 select S3C24XX_DCLK select PM_H1940 if PM select I2C - select S3C24XX_PWM + select S3C2410_PWM select S3C_DEV_NAND select S3C2410_IOTIMING if S3C2440_CPUFREQ select S3C2440_XTAL_16934400 diff --git a/trunk/arch/arm/mach-s3c24xx/include/mach/dma.h b/trunk/arch/arm/mach-s3c24xx/include/mach/dma.h index ee99fd56c043..454831b66037 100644 --- a/trunk/arch/arm/mach-s3c24xx/include/mach/dma.h +++ b/trunk/arch/arm/mach-s3c24xx/include/mach/dma.h @@ -24,8 +24,7 @@ */ enum dma_ch { - DMACH_DT_PROP = -1, /* not yet supported, do not use */ - DMACH_XD0 = 0, + DMACH_XD0, DMACH_XD1, DMACH_SDI, DMACH_SPI0, diff --git a/trunk/arch/arm/mach-sa1100/leds-hackkit.c b/trunk/arch/arm/mach-sa1100/leds-hackkit.c index f8e47235babe..6a2352436e62 100644 --- a/trunk/arch/arm/mach-sa1100/leds-hackkit.c +++ b/trunk/arch/arm/mach-sa1100/leds-hackkit.c @@ -10,7 +10,6 @@ * as cpu led, the green one is used as timer led. */ #include -#include #include #include diff --git a/trunk/arch/arm/mach-shmobile/board-armadillo800eva.c b/trunk/arch/arm/mach-shmobile/board-armadillo800eva.c index 453a6e50db8b..cf10f92856dc 100644 --- a/trunk/arch/arm/mach-shmobile/board-armadillo800eva.c +++ b/trunk/arch/arm/mach-shmobile/board-armadillo800eva.c @@ -520,14 +520,13 @@ static struct platform_device hdmi_lcdc_device = { }; /* GPIO KEY */ -#define GPIO_KEY(c, g, d, ...) \ - { .code = c, .gpio = g, .desc = d, .active_low = 1, __VA_ARGS__ } +#define GPIO_KEY(c, g, d) { .code = c, .gpio = g, .desc = d, .active_low = 1 } static struct gpio_keys_button gpio_buttons[] = { - GPIO_KEY(KEY_POWER, GPIO_PORT99, "SW3", .wakeup = 1), - GPIO_KEY(KEY_BACK, GPIO_PORT100, "SW4"), - GPIO_KEY(KEY_MENU, GPIO_PORT97, "SW5"), - GPIO_KEY(KEY_HOME, GPIO_PORT98, "SW6"), + GPIO_KEY(KEY_POWER, GPIO_PORT99, "SW1"), + GPIO_KEY(KEY_BACK, GPIO_PORT100, "SW2"), + GPIO_KEY(KEY_MENU, GPIO_PORT97, "SW3"), + GPIO_KEY(KEY_HOME, GPIO_PORT98, "SW4"), }; static struct gpio_keys_platform_data gpio_key_info = { @@ -902,8 +901,8 @@ static struct platform_device *eva_devices[] __initdata = { &camera_device, &ceu0_device, &fsi_device, - &fsi_wm8978_device, &fsi_hdmi_device, + &fsi_wm8978_device, }; static void __init eva_clock_init(void) diff --git a/trunk/arch/arm/mach-shmobile/board-kzm9g.c b/trunk/arch/arm/mach-shmobile/board-kzm9g.c index 3b8a0171c3cb..53b7ea92c32c 100644 --- a/trunk/arch/arm/mach-shmobile/board-kzm9g.c +++ b/trunk/arch/arm/mach-shmobile/board-kzm9g.c @@ -346,11 +346,11 @@ static struct resource sh_mmcif_resources[] = { .flags = IORESOURCE_MEM, }, [1] = { - .start = gic_spi(140), + .start = gic_spi(141), .flags = IORESOURCE_IRQ, }, [2] = { - .start = gic_spi(141), + .start = gic_spi(140), .flags = IORESOURCE_IRQ, }, }; diff --git a/trunk/arch/arm/mach-shmobile/board-mackerel.c b/trunk/arch/arm/mach-shmobile/board-mackerel.c index c129542f6aed..7ea2b31e3199 100644 --- a/trunk/arch/arm/mach-shmobile/board-mackerel.c +++ b/trunk/arch/arm/mach-shmobile/board-mackerel.c @@ -695,7 +695,6 @@ static struct platform_device usbhs0_device = { * - J30 "open" * - modify usbhs1_get_id() USBHS_HOST -> USBHS_GADGET * - add .get_vbus = usbhs_get_vbus in usbhs1_private - * - check usbhs0_device(pio)/usbhs1_device(irq) order in mackerel_devices. */ #define IRQ8 evt2irq(0x0300) #define USB_PHY_MODE (1 << 4) @@ -1326,8 +1325,8 @@ static struct platform_device *mackerel_devices[] __initdata = { &nor_flash_device, &smc911x_device, &lcdc_device, - &usbhs0_device, &usbhs1_device, + &usbhs0_device, &leds_device, &fsi_device, &fsi_ak4643_device, diff --git a/trunk/arch/arm/mach-shmobile/board-marzen.c b/trunk/arch/arm/mach-shmobile/board-marzen.c index fcf5a47f4772..3a528cf4366c 100644 --- a/trunk/arch/arm/mach-shmobile/board-marzen.c +++ b/trunk/arch/arm/mach-shmobile/board-marzen.c @@ -67,7 +67,7 @@ static struct smsc911x_platform_config smsc911x_platdata = { static struct platform_device eth_device = { .name = "smsc911x", - .id = -1, + .id = 0, .dev = { .platform_data = &smsc911x_platdata, }, diff --git a/trunk/arch/arm/mach-shmobile/intc-sh73a0.c b/trunk/arch/arm/mach-shmobile/intc-sh73a0.c index 588555a67d9c..ee447404c857 100644 --- a/trunk/arch/arm/mach-shmobile/intc-sh73a0.c +++ b/trunk/arch/arm/mach-shmobile/intc-sh73a0.c @@ -259,9 +259,9 @@ static int sh73a0_set_wake(struct irq_data *data, unsigned int on) return 0; /* always allow wakeup */ } -#define RELOC_BASE 0x1200 +#define RELOC_BASE 0x1000 -/* INTCA IRQ pins at INTCS + RELOC_BASE to make space for GIC+INTC handling */ +/* INTCA IRQ pins at INTCS + 0x1000 to make space for GIC+INTC handling */ #define INTCS_VECT_RELOC(n, vect) INTCS_VECT((n), (vect) + RELOC_BASE) INTC_IRQ_PINS_32(intca_irq_pins, 0xe6900000, diff --git a/trunk/arch/arm/mach-tegra/board-harmony-power.c b/trunk/arch/arm/mach-tegra/board-harmony-power.c index 94486e7e9dfd..8fd387bf31f0 100644 --- a/trunk/arch/arm/mach-tegra/board-harmony-power.c +++ b/trunk/arch/arm/mach-tegra/board-harmony-power.c @@ -51,7 +51,7 @@ static struct regulator_init_data ldo0_data = { .consumer_supplies = tps658621_ldo0_supply, }; -#define HARMONY_REGULATOR_INIT(_id, _name, _supply, _minmv, _maxmv, _on)\ +#define HARMONY_REGULATOR_INIT(_id, _name, _supply, _minmv, _maxmv) \ static struct regulator_init_data _id##_data = { \ .supply_regulator = _supply, \ .constraints = { \ @@ -63,29 +63,21 @@ static struct regulator_init_data ldo0_data = { .valid_ops_mask = (REGULATOR_CHANGE_MODE | \ REGULATOR_CHANGE_STATUS | \ REGULATOR_CHANGE_VOLTAGE), \ - .always_on = _on, \ }, \ } -static struct regulator_init_data sys_data = { - .supply_regulator = "vdd_5v0", - .constraints = { - .name = "vdd_sys", - }, -}; - -HARMONY_REGULATOR_INIT(sm0, "vdd_sm0", "vdd_sys", 725, 1500, 1); -HARMONY_REGULATOR_INIT(sm1, "vdd_sm1", "vdd_sys", 725, 1500, 1); -HARMONY_REGULATOR_INIT(sm2, "vdd_sm2", "vdd_sys", 3000, 4550, 1); -HARMONY_REGULATOR_INIT(ldo1, "vdd_ldo1", "vdd_sm2", 725, 1500, 1); -HARMONY_REGULATOR_INIT(ldo2, "vdd_ldo2", "vdd_sm2", 725, 1500, 0); -HARMONY_REGULATOR_INIT(ldo3, "vdd_ldo3", "vdd_sm2", 1250, 3300, 1); -HARMONY_REGULATOR_INIT(ldo4, "vdd_ldo4", "vdd_sm2", 1700, 2475, 1); -HARMONY_REGULATOR_INIT(ldo5, "vdd_ldo5", "vdd_sys", 1250, 3300, 1); -HARMONY_REGULATOR_INIT(ldo6, "vdd_ldo6", "vdd_sm2", 1250, 3300, 0); -HARMONY_REGULATOR_INIT(ldo7, "vdd_ldo7", "vdd_sm2", 1250, 3300, 0); -HARMONY_REGULATOR_INIT(ldo8, "vdd_ldo8", "vdd_sm2", 1250, 3300, 0); -HARMONY_REGULATOR_INIT(ldo9, "vdd_ldo9", "vdd_sm2", 1250, 3300, 1); +HARMONY_REGULATOR_INIT(sm0, "vdd_sm0", "vdd_sys", 725, 1500); +HARMONY_REGULATOR_INIT(sm1, "vdd_sm1", "vdd_sys", 725, 1500); +HARMONY_REGULATOR_INIT(sm2, "vdd_sm2", "vdd_sys", 3000, 4550); +HARMONY_REGULATOR_INIT(ldo1, "vdd_ldo1", "vdd_sm2", 725, 1500); +HARMONY_REGULATOR_INIT(ldo2, "vdd_ldo2", "vdd_sm2", 725, 1500); +HARMONY_REGULATOR_INIT(ldo3, "vdd_ldo3", "vdd_sm2", 1250, 3300); +HARMONY_REGULATOR_INIT(ldo4, "vdd_ldo4", "vdd_sm2", 1700, 2475); +HARMONY_REGULATOR_INIT(ldo5, "vdd_ldo5", NULL, 1250, 3300); +HARMONY_REGULATOR_INIT(ldo6, "vdd_ldo6", "vdd_sm2", 1250, 3300); +HARMONY_REGULATOR_INIT(ldo7, "vdd_ldo7", "vdd_sm2", 1250, 3300); +HARMONY_REGULATOR_INIT(ldo8, "vdd_ldo8", "vdd_sm2", 1250, 3300); +HARMONY_REGULATOR_INIT(ldo9, "vdd_ldo9", "vdd_sm2", 1250, 3300); #define TPS_REG(_id, _data) \ { \ @@ -95,7 +87,6 @@ HARMONY_REGULATOR_INIT(ldo9, "vdd_ldo9", "vdd_sm2", 1250, 3300, 1); } static struct tps6586x_subdev_info tps_devs[] = { - TPS_REG(SYS, &sys_data), TPS_REG(SM_0, &sm0_data), TPS_REG(SM_1, &sm1_data), TPS_REG(SM_2, &sm2_data), @@ -128,10 +119,9 @@ static struct i2c_board_info __initdata harmony_regulators[] = { int __init harmony_regulator_init(void) { - regulator_register_always_on(0, "vdd_5v0", - NULL, 0, 5000000); - if (machine_is_harmony()) { + regulator_register_always_on(0, "vdd_sys", + NULL, 0, 5000000); i2c_register_board_info(3, harmony_regulators, 1); } else { /* Harmony, booted using device tree */ struct device_node *np; diff --git a/trunk/arch/arm/mach-tegra/pcie.c b/trunk/arch/arm/mach-tegra/pcie.c index c25a2a4f2e3d..d3ad5150d660 100644 --- a/trunk/arch/arm/mach-tegra/pcie.c +++ b/trunk/arch/arm/mach-tegra/pcie.c @@ -367,7 +367,17 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_NVIDIA, 0x0bf1, tegra_pcie_fixup_class); /* Tegra PCIE requires relaxed ordering */ static void __devinit tegra_pcie_relax_enable(struct pci_dev *dev) { - pcie_capability_set_word(dev, PCI_EXP_DEVCTL, PCI_EXP_DEVCTL_RELAX_EN); + u16 val16; + int pos = pci_find_capability(dev, PCI_CAP_ID_EXP); + + if (pos <= 0) { + dev_err(&dev->dev, "skipping relaxed ordering fixup\n"); + return; + } + + pci_read_config_word(dev, pos + PCI_EXP_DEVCTL, &val16); + val16 |= PCI_EXP_DEVCTL_RELAX_EN; + pci_write_config_word(dev, pos + PCI_EXP_DEVCTL, val16); } DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, tegra_pcie_relax_enable); diff --git a/trunk/arch/arm/mach-ux500/Kconfig b/trunk/arch/arm/mach-ux500/Kconfig index a258996d954b..c013bbf79cac 100644 --- a/trunk/arch/arm/mach-ux500/Kconfig +++ b/trunk/arch/arm/mach-ux500/Kconfig @@ -11,7 +11,6 @@ config UX500_SOC_COMMON select CACHE_L2X0 select PINCTRL select PINCTRL_NOMADIK - select COMMON_CLK config UX500_SOC_DB8500 bool @@ -42,6 +41,7 @@ config MACH_HREFV60 config MACH_SNOWBALL bool "U8500 Snowball platform" select MACH_MOP500 + select LEDS_GPIO help Include support for the snowball development platform. diff --git a/trunk/arch/arm/mach-ux500/Makefile b/trunk/arch/arm/mach-ux500/Makefile index 5691ef679d01..026086ff9e6c 100644 --- a/trunk/arch/arm/mach-ux500/Makefile +++ b/trunk/arch/arm/mach-ux500/Makefile @@ -2,7 +2,7 @@ # Makefile for the linux kernel, U8500 machine. # -obj-y := cpu.o devices.o devices-common.o \ +obj-y := clock.o cpu.o devices.o devices-common.o \ id.o usb.o timer.o obj-$(CONFIG_CPU_IDLE) += cpuidle.o obj-$(CONFIG_CACHE_L2X0) += cache-l2x0.o diff --git a/trunk/arch/arm/mach-ux500/board-mop500-msp.c b/trunk/arch/arm/mach-ux500/board-mop500-msp.c index df15646036aa..996048038743 100644 --- a/trunk/arch/arm/mach-ux500/board-mop500-msp.c +++ b/trunk/arch/arm/mach-ux500/board-mop500-msp.c @@ -191,9 +191,9 @@ static struct platform_device *db8500_add_msp_i2s(struct device *parent, return pdev; } -/* Platform device for ASoC MOP500 machine */ -static struct platform_device snd_soc_mop500 = { - .name = "snd-soc-mop500", +/* Platform device for ASoC U8500 machine */ +static struct platform_device snd_soc_u8500 = { + .name = "snd-soc-u8500", .id = 0, .dev = { .platform_data = NULL, @@ -227,8 +227,8 @@ int mop500_msp_init(struct device *parent) { struct platform_device *msp1; - pr_info("%s: Register platform-device 'snd-soc-mop500'.\n", __func__); - platform_device_register(&snd_soc_mop500); + pr_info("%s: Register platform-device 'snd-soc-u8500'.\n", __func__); + platform_device_register(&snd_soc_u8500); pr_info("Initialize MSP I2S-devices.\n"); db8500_add_msp_i2s(parent, 0, U8500_MSP0_BASE, IRQ_DB8500_MSP0, diff --git a/trunk/arch/arm/mach-ux500/board-mop500.c b/trunk/arch/arm/mach-ux500/board-mop500.c index 1d2e3c6f8b59..8674a890fd1c 100644 --- a/trunk/arch/arm/mach-ux500/board-mop500.c +++ b/trunk/arch/arm/mach-ux500/board-mop500.c @@ -524,12 +524,33 @@ static struct stedma40_chan_cfg uart2_dma_cfg_tx = { }; #endif +#define PRCC_K_SOFTRST_SET 0x18 +#define PRCC_K_SOFTRST_CLEAR 0x1C +static void ux500_uart0_reset(void) +{ + void __iomem *prcc_rst_set, *prcc_rst_clr; + + prcc_rst_set = (void __iomem *)IO_ADDRESS(U8500_CLKRST1_BASE + + PRCC_K_SOFTRST_SET); + prcc_rst_clr = (void __iomem *)IO_ADDRESS(U8500_CLKRST1_BASE + + PRCC_K_SOFTRST_CLEAR); + + /* Activate soft reset PRCC_K_SOFTRST_CLEAR */ + writel((readl(prcc_rst_clr) | 0x1), prcc_rst_clr); + udelay(1); + + /* Release soft reset PRCC_K_SOFTRST_SET */ + writel((readl(prcc_rst_set) | 0x1), prcc_rst_set); + udelay(1); +} + static struct amba_pl011_data uart0_plat = { #ifdef CONFIG_STE_DMA40 .dma_filter = stedma40_filter, .dma_rx_param = &uart0_dma_cfg_rx, .dma_tx_param = &uart0_dma_cfg_tx, #endif + .reset = ux500_uart0_reset, }; static struct amba_pl011_data uart1_plat = { @@ -776,7 +797,6 @@ static void __init u8500_init_machine(void) ARRAY_SIZE(mop500_platform_devs)); mop500_sdi_init(parent); - mop500_msp_init(parent); i2c0_devs = ARRAY_SIZE(mop500_i2c0_devices); i2c_register_board_info(0, mop500_i2c0_devices, i2c0_devs); i2c_register_board_info(2, mop500_i2c2_devices, @@ -784,8 +804,6 @@ static void __init u8500_init_machine(void) mop500_uib_init(); - } else if (of_machine_is_compatible("calaosystems,snowball-a9500")) { - mop500_msp_init(parent); } else if (of_machine_is_compatible("st-ericsson,hrefv60+")) { /* * The HREFv60 board removed a GPIO expander and routed @@ -797,7 +815,6 @@ static void __init u8500_init_machine(void) ARRAY_SIZE(mop500_platform_devs)); hrefv60_sdi_init(parent); - mop500_msp_init(parent); i2c0_devs = ARRAY_SIZE(mop500_i2c0_devices); i2c0_devs -= NUM_PRE_V60_I2C0_DEVICES; diff --git a/trunk/arch/arm/mach-ux500/clock.c b/trunk/arch/arm/mach-ux500/clock.c new file mode 100644 index 000000000000..8d73b066a18d --- /dev/null +++ b/trunk/arch/arm/mach-ux500/clock.c @@ -0,0 +1,715 @@ +/* + * Copyright (C) 2009 ST-Ericsson + * Copyright (C) 2009 STMicroelectronics + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include "clock.h" + +#ifdef CONFIG_DEBUG_FS +#include +#include /* for copy_from_user */ +static LIST_HEAD(clk_list); +#endif + +#define PRCC_PCKEN 0x00 +#define PRCC_PCKDIS 0x04 +#define PRCC_KCKEN 0x08 +#define PRCC_KCKDIS 0x0C + +#define PRCM_YYCLKEN0_MGT_SET 0x510 +#define PRCM_YYCLKEN1_MGT_SET 0x514 +#define PRCM_YYCLKEN0_MGT_CLR 0x518 +#define PRCM_YYCLKEN1_MGT_CLR 0x51C +#define PRCM_YYCLKEN0_MGT_VAL 0x520 +#define PRCM_YYCLKEN1_MGT_VAL 0x524 + +#define PRCM_SVAMMDSPCLK_MGT 0x008 +#define PRCM_SIAMMDSPCLK_MGT 0x00C +#define PRCM_SGACLK_MGT 0x014 +#define PRCM_UARTCLK_MGT 0x018 +#define PRCM_MSP02CLK_MGT 0x01C +#define PRCM_MSP1CLK_MGT 0x288 +#define PRCM_I2CCLK_MGT 0x020 +#define PRCM_SDMMCCLK_MGT 0x024 +#define PRCM_SLIMCLK_MGT 0x028 +#define PRCM_PER1CLK_MGT 0x02C +#define PRCM_PER2CLK_MGT 0x030 +#define PRCM_PER3CLK_MGT 0x034 +#define PRCM_PER5CLK_MGT 0x038 +#define PRCM_PER6CLK_MGT 0x03C +#define PRCM_PER7CLK_MGT 0x040 +#define PRCM_LCDCLK_MGT 0x044 +#define PRCM_BMLCLK_MGT 0x04C +#define PRCM_HSITXCLK_MGT 0x050 +#define PRCM_HSIRXCLK_MGT 0x054 +#define PRCM_HDMICLK_MGT 0x058 +#define PRCM_APEATCLK_MGT 0x05C +#define PRCM_APETRACECLK_MGT 0x060 +#define PRCM_MCDECLK_MGT 0x064 +#define PRCM_IPI2CCLK_MGT 0x068 +#define PRCM_DSIALTCLK_MGT 0x06C +#define PRCM_DMACLK_MGT 0x074 +#define PRCM_B2R2CLK_MGT 0x078 +#define PRCM_TVCLK_MGT 0x07C +#define PRCM_TCR 0x1C8 +#define PRCM_TCR_STOPPED (1 << 16) +#define PRCM_TCR_DOZE_MODE (1 << 17) +#define PRCM_UNIPROCLK_MGT 0x278 +#define PRCM_SSPCLK_MGT 0x280 +#define PRCM_RNGCLK_MGT 0x284 +#define PRCM_UICCCLK_MGT 0x27C + +#define PRCM_MGT_ENABLE (1 << 8) + +static DEFINE_SPINLOCK(clocks_lock); + +static void __clk_enable(struct clk *clk) +{ + if (clk->enabled++ == 0) { + if (clk->parent_cluster) + __clk_enable(clk->parent_cluster); + + if (clk->parent_periph) + __clk_enable(clk->parent_periph); + + if (clk->ops && clk->ops->enable) + clk->ops->enable(clk); + } +} + +int clk_enable(struct clk *clk) +{ + unsigned long flags; + + spin_lock_irqsave(&clocks_lock, flags); + __clk_enable(clk); + spin_unlock_irqrestore(&clocks_lock, flags); + + return 0; +} +EXPORT_SYMBOL(clk_enable); + +static void __clk_disable(struct clk *clk) +{ + if (--clk->enabled == 0) { + if (clk->ops && clk->ops->disable) + clk->ops->disable(clk); + + if (clk->parent_periph) + __clk_disable(clk->parent_periph); + + if (clk->parent_cluster) + __clk_disable(clk->parent_cluster); + } +} + +void clk_disable(struct clk *clk) +{ + unsigned long flags; + + WARN_ON(!clk->enabled); + + spin_lock_irqsave(&clocks_lock, flags); + __clk_disable(clk); + spin_unlock_irqrestore(&clocks_lock, flags); +} +EXPORT_SYMBOL(clk_disable); + +/* + * The MTU has a separate, rather complex muxing setup + * with alternative parents (peripheral cluster or + * ULP or fixed 32768 Hz) depending on settings + */ +static unsigned long clk_mtu_get_rate(struct clk *clk) +{ + void __iomem *addr; + u32 tcr; + int mtu = (int) clk->data; + /* + * One of these is selected eventually + * TODO: Replace the constant with a reference + * to the ULP source once this is modeled. + */ + unsigned long clk32k = 32768; + unsigned long mturate; + unsigned long retclk; + + if (cpu_is_u8500_family()) + addr = __io_address(U8500_PRCMU_BASE); + else + ux500_unknown_soc(); + + /* + * On a startup, always conifgure the TCR to the doze mode; + * bootloaders do it for us. Do this in the kernel too. + */ + writel(PRCM_TCR_DOZE_MODE, addr + PRCM_TCR); + + tcr = readl(addr + PRCM_TCR); + + /* Get the rate from the parent as a default */ + if (clk->parent_periph) + mturate = clk_get_rate(clk->parent_periph); + else if (clk->parent_cluster) + mturate = clk_get_rate(clk->parent_cluster); + else + /* We need to be connected SOMEWHERE */ + BUG(); + + /* Return the clock selected for this MTU */ + if (tcr & (1 << mtu)) + retclk = clk32k; + else + retclk = mturate; + + pr_info("MTU%d clock rate: %lu Hz\n", mtu, retclk); + return retclk; +} + +unsigned long clk_get_rate(struct clk *clk) +{ + unsigned long rate; + + /* + * If there is a custom getrate callback for this clock, + * it will take precedence. + */ + if (clk->get_rate) + return clk->get_rate(clk); + + if (clk->ops && clk->ops->get_rate) + return clk->ops->get_rate(clk); + + rate = clk->rate; + if (!rate) { + if (clk->parent_periph) + rate = clk_get_rate(clk->parent_periph); + else if (clk->parent_cluster) + rate = clk_get_rate(clk->parent_cluster); + } + + return rate; +} +EXPORT_SYMBOL(clk_get_rate); + +long clk_round_rate(struct clk *clk, unsigned long rate) +{ + /*TODO*/ + return rate; +} +EXPORT_SYMBOL(clk_round_rate); + +int clk_set_rate(struct clk *clk, unsigned long rate) +{ + clk->rate = rate; + return 0; +} +EXPORT_SYMBOL(clk_set_rate); + +int clk_set_parent(struct clk *clk, struct clk *parent) +{ + /*TODO*/ + return -ENOSYS; +} +EXPORT_SYMBOL(clk_set_parent); + +static void clk_prcmu_enable(struct clk *clk) +{ + void __iomem *cg_set_reg = __io_address(U8500_PRCMU_BASE) + + PRCM_YYCLKEN0_MGT_SET + clk->prcmu_cg_off; + + writel(1 << clk->prcmu_cg_bit, cg_set_reg); +} + +static void clk_prcmu_disable(struct clk *clk) +{ + void __iomem *cg_clr_reg = __io_address(U8500_PRCMU_BASE) + + PRCM_YYCLKEN0_MGT_CLR + clk->prcmu_cg_off; + + writel(1 << clk->prcmu_cg_bit, cg_clr_reg); +} + +static struct clkops clk_prcmu_ops = { + .enable = clk_prcmu_enable, + .disable = clk_prcmu_disable, +}; + +static unsigned int clkrst_base[] = { + [1] = U8500_CLKRST1_BASE, + [2] = U8500_CLKRST2_BASE, + [3] = U8500_CLKRST3_BASE, + [5] = U8500_CLKRST5_BASE, + [6] = U8500_CLKRST6_BASE, +}; + +static void clk_prcc_enable(struct clk *clk) +{ + void __iomem *addr = __io_address(clkrst_base[clk->cluster]); + + if (clk->prcc_kernel != -1) + writel(1 << clk->prcc_kernel, addr + PRCC_KCKEN); + + if (clk->prcc_bus != -1) + writel(1 << clk->prcc_bus, addr + PRCC_PCKEN); +} + +static void clk_prcc_disable(struct clk *clk) +{ + void __iomem *addr = __io_address(clkrst_base[clk->cluster]); + + if (clk->prcc_bus != -1) + writel(1 << clk->prcc_bus, addr + PRCC_PCKDIS); + + if (clk->prcc_kernel != -1) + writel(1 << clk->prcc_kernel, addr + PRCC_KCKDIS); +} + +static struct clkops clk_prcc_ops = { + .enable = clk_prcc_enable, + .disable = clk_prcc_disable, +}; + +static struct clk clk_32khz = { + .name = "clk_32khz", + .rate = 32000, +}; + +/* + * PRCMU level clock gating + */ + +/* Bank 0 */ +static DEFINE_PRCMU_CLK(svaclk, 0x0, 2, SVAMMDSPCLK); +static DEFINE_PRCMU_CLK(siaclk, 0x0, 3, SIAMMDSPCLK); +static DEFINE_PRCMU_CLK(sgaclk, 0x0, 4, SGACLK); +static DEFINE_PRCMU_CLK_RATE(uartclk, 0x0, 5, UARTCLK, 38400000); +static DEFINE_PRCMU_CLK(msp02clk, 0x0, 6, MSP02CLK); +static DEFINE_PRCMU_CLK(msp1clk, 0x0, 7, MSP1CLK); /* v1 */ +static DEFINE_PRCMU_CLK_RATE(i2cclk, 0x0, 8, I2CCLK, 48000000); +static DEFINE_PRCMU_CLK_RATE(sdmmcclk, 0x0, 9, SDMMCCLK, 100000000); +static DEFINE_PRCMU_CLK(slimclk, 0x0, 10, SLIMCLK); +static DEFINE_PRCMU_CLK(per1clk, 0x0, 11, PER1CLK); +static DEFINE_PRCMU_CLK(per2clk, 0x0, 12, PER2CLK); +static DEFINE_PRCMU_CLK(per3clk, 0x0, 13, PER3CLK); +static DEFINE_PRCMU_CLK(per5clk, 0x0, 14, PER5CLK); +static DEFINE_PRCMU_CLK_RATE(per6clk, 0x0, 15, PER6CLK, 133330000); +static DEFINE_PRCMU_CLK(lcdclk, 0x0, 17, LCDCLK); +static DEFINE_PRCMU_CLK(bmlclk, 0x0, 18, BMLCLK); +static DEFINE_PRCMU_CLK(hsitxclk, 0x0, 19, HSITXCLK); +static DEFINE_PRCMU_CLK(hsirxclk, 0x0, 20, HSIRXCLK); +static DEFINE_PRCMU_CLK(hdmiclk, 0x0, 21, HDMICLK); +static DEFINE_PRCMU_CLK(apeatclk, 0x0, 22, APEATCLK); +static DEFINE_PRCMU_CLK(apetraceclk, 0x0, 23, APETRACECLK); +static DEFINE_PRCMU_CLK(mcdeclk, 0x0, 24, MCDECLK); +static DEFINE_PRCMU_CLK(ipi2clk, 0x0, 25, IPI2CCLK); +static DEFINE_PRCMU_CLK(dsialtclk, 0x0, 26, DSIALTCLK); /* v1 */ +static DEFINE_PRCMU_CLK(dmaclk, 0x0, 27, DMACLK); +static DEFINE_PRCMU_CLK(b2r2clk, 0x0, 28, B2R2CLK); +static DEFINE_PRCMU_CLK(tvclk, 0x0, 29, TVCLK); +static DEFINE_PRCMU_CLK(uniproclk, 0x0, 30, UNIPROCLK); /* v1 */ +static DEFINE_PRCMU_CLK_RATE(sspclk, 0x0, 31, SSPCLK, 48000000); /* v1 */ + +/* Bank 1 */ +static DEFINE_PRCMU_CLK(rngclk, 0x4, 0, RNGCLK); /* v1 */ +static DEFINE_PRCMU_CLK(uiccclk, 0x4, 1, UICCCLK); /* v1 */ + +/* + * PRCC level clock gating + * Format: per#, clk, PCKEN bit, KCKEN bit, parent + */ + +/* Peripheral Cluster #1 */ +static DEFINE_PRCC_CLK(1, msp3, 11, 10, &clk_msp1clk); +static DEFINE_PRCC_CLK(1, i2c4, 10, 9, &clk_i2cclk); +static DEFINE_PRCC_CLK(1, gpio0, 9, -1, NULL); +static DEFINE_PRCC_CLK(1, slimbus0, 8, 8, &clk_slimclk); +static DEFINE_PRCC_CLK(1, spi3, 7, -1, NULL); +static DEFINE_PRCC_CLK(1, i2c2, 6, 6, &clk_i2cclk); +static DEFINE_PRCC_CLK(1, sdi0, 5, 5, &clk_sdmmcclk); +static DEFINE_PRCC_CLK(1, msp1, 4, 4, &clk_msp1clk); +static DEFINE_PRCC_CLK(1, msp0, 3, 3, &clk_msp02clk); +static DEFINE_PRCC_CLK(1, i2c1, 2, 2, &clk_i2cclk); +static DEFINE_PRCC_CLK(1, uart1, 1, 1, &clk_uartclk); +static DEFINE_PRCC_CLK(1, uart0, 0, 0, &clk_uartclk); + +/* Peripheral Cluster #2 */ +static DEFINE_PRCC_CLK(2, gpio1, 11, -1, NULL); +static DEFINE_PRCC_CLK(2, ssitx, 10, 7, NULL); +static DEFINE_PRCC_CLK(2, ssirx, 9, 6, NULL); +static DEFINE_PRCC_CLK(2, spi0, 8, -1, NULL); +static DEFINE_PRCC_CLK(2, sdi3, 7, 5, &clk_sdmmcclk); +static DEFINE_PRCC_CLK(2, sdi1, 6, 4, &clk_sdmmcclk); +static DEFINE_PRCC_CLK(2, msp2, 5, 3, &clk_msp02clk); +static DEFINE_PRCC_CLK(2, sdi4, 4, 2, &clk_sdmmcclk); +static DEFINE_PRCC_CLK(2, pwl, 3, 1, NULL); +static DEFINE_PRCC_CLK(2, spi1, 2, -1, NULL); +static DEFINE_PRCC_CLK(2, spi2, 1, -1, NULL); +static DEFINE_PRCC_CLK(2, i2c3, 0, 0, &clk_i2cclk); + +/* Peripheral Cluster #3 */ +static DEFINE_PRCC_CLK(3, gpio2, 8, -1, NULL); +static DEFINE_PRCC_CLK(3, sdi5, 7, 7, &clk_sdmmcclk); +static DEFINE_PRCC_CLK(3, uart2, 6, 6, &clk_uartclk); +static DEFINE_PRCC_CLK(3, ske, 5, 5, &clk_32khz); +static DEFINE_PRCC_CLK(3, sdi2, 4, 4, &clk_sdmmcclk); +static DEFINE_PRCC_CLK(3, i2c0, 3, 3, &clk_i2cclk); +static DEFINE_PRCC_CLK(3, ssp1, 2, 2, &clk_sspclk); +static DEFINE_PRCC_CLK(3, ssp0, 1, 1, &clk_sspclk); +static DEFINE_PRCC_CLK(3, fsmc, 0, -1, NULL); + +/* Peripheral Cluster #4 is in the always on domain */ + +/* Peripheral Cluster #5 */ +static DEFINE_PRCC_CLK(5, gpio3, 1, -1, NULL); +static DEFINE_PRCC_CLK(5, usb, 0, 0, NULL); + +/* Peripheral Cluster #6 */ + +/* MTU ID in data */ +static DEFINE_PRCC_CLK_CUSTOM(6, mtu1, 9, -1, NULL, clk_mtu_get_rate, 1); +static DEFINE_PRCC_CLK_CUSTOM(6, mtu0, 8, -1, NULL, clk_mtu_get_rate, 0); +static DEFINE_PRCC_CLK(6, cfgreg, 7, 7, NULL); +static DEFINE_PRCC_CLK(6, hash1, 6, -1, NULL); +static DEFINE_PRCC_CLK(6, unipro, 5, 1, &clk_uniproclk); +static DEFINE_PRCC_CLK(6, pka, 4, -1, NULL); +static DEFINE_PRCC_CLK(6, hash0, 3, -1, NULL); +static DEFINE_PRCC_CLK(6, cryp0, 2, -1, NULL); +static DEFINE_PRCC_CLK(6, cryp1, 1, -1, NULL); +static DEFINE_PRCC_CLK(6, rng, 0, 0, &clk_rngclk); + +static struct clk clk_dummy_apb_pclk = { + .name = "apb_pclk", +}; + +static struct clk_lookup u8500_clks[] = { + CLK(dummy_apb_pclk, NULL, "apb_pclk"), + + /* Peripheral Cluster #1 */ + CLK(gpio0, "gpio.0", NULL), + CLK(gpio0, "gpio.1", NULL), + CLK(slimbus0, "slimbus0", NULL), + CLK(i2c2, "nmk-i2c.2", NULL), + CLK(sdi0, "sdi0", NULL), + CLK(msp0, "ux500-msp-i2s.0", NULL), + CLK(i2c1, "nmk-i2c.1", NULL), + CLK(uart1, "uart1", NULL), + CLK(uart0, "uart0", NULL), + + /* Peripheral Cluster #3 */ + CLK(gpio2, "gpio.2", NULL), + CLK(gpio2, "gpio.3", NULL), + CLK(gpio2, "gpio.4", NULL), + CLK(gpio2, "gpio.5", NULL), + CLK(sdi5, "sdi5", NULL), + CLK(uart2, "uart2", NULL), + CLK(ske, "ske", NULL), + CLK(ske, "nmk-ske-keypad", NULL), + CLK(sdi2, "sdi2", NULL), + CLK(i2c0, "nmk-i2c.0", NULL), + CLK(fsmc, "fsmc", NULL), + + /* Peripheral Cluster #5 */ + CLK(gpio3, "gpio.8", NULL), + + /* Peripheral Cluster #6 */ + CLK(hash1, "hash1", NULL), + CLK(pka, "pka", NULL), + CLK(hash0, "hash0", NULL), + CLK(cryp0, "cryp0", NULL), + CLK(cryp1, "cryp1", NULL), + + /* PRCMU level clock gating */ + + /* Bank 0 */ + CLK(svaclk, "sva", NULL), + CLK(siaclk, "sia", NULL), + CLK(sgaclk, "sga", NULL), + CLK(slimclk, "slim", NULL), + CLK(lcdclk, "lcd", NULL), + CLK(bmlclk, "bml", NULL), + CLK(hsitxclk, "stm-hsi.0", NULL), + CLK(hsirxclk, "stm-hsi.1", NULL), + CLK(hdmiclk, "hdmi", NULL), + CLK(apeatclk, "apeat", NULL), + CLK(apetraceclk, "apetrace", NULL), + CLK(mcdeclk, "mcde", NULL), + CLK(ipi2clk, "ipi2", NULL), + CLK(dmaclk, "dma40.0", NULL), + CLK(b2r2clk, "b2r2", NULL), + CLK(tvclk, "tv", NULL), + + /* Peripheral Cluster #1 */ + CLK(i2c4, "nmk-i2c.4", NULL), + CLK(spi3, "spi3", NULL), + CLK(msp1, "ux500-msp-i2s.1", NULL), + CLK(msp3, "ux500-msp-i2s.3", NULL), + + /* Peripheral Cluster #2 */ + CLK(gpio1, "gpio.6", NULL), + CLK(gpio1, "gpio.7", NULL), + CLK(ssitx, "ssitx", NULL), + CLK(ssirx, "ssirx", NULL), + CLK(spi0, "spi0", NULL), + CLK(sdi3, "sdi3", NULL), + CLK(sdi1, "sdi1", NULL), + CLK(msp2, "ux500-msp-i2s.2", NULL), + CLK(sdi4, "sdi4", NULL), + CLK(pwl, "pwl", NULL), + CLK(spi1, "spi1", NULL), + CLK(spi2, "spi2", NULL), + CLK(i2c3, "nmk-i2c.3", NULL), + + /* Peripheral Cluster #3 */ + CLK(ssp1, "ssp1", NULL), + CLK(ssp0, "ssp0", NULL), + + /* Peripheral Cluster #5 */ + CLK(usb, "musb-ux500.0", "usb"), + + /* Peripheral Cluster #6 */ + CLK(mtu1, "mtu1", NULL), + CLK(mtu0, "mtu0", NULL), + CLK(cfgreg, "cfgreg", NULL), + CLK(hash1, "hash1", NULL), + CLK(unipro, "unipro", NULL), + CLK(rng, "rng", NULL), + + /* PRCMU level clock gating */ + + /* Bank 0 */ + CLK(uniproclk, "uniproclk", NULL), + CLK(dsialtclk, "dsialt", NULL), + + /* Bank 1 */ + CLK(rngclk, "rng", NULL), + CLK(uiccclk, "uicc", NULL), +}; + +#ifdef CONFIG_DEBUG_FS +/* + * debugfs support to trace clock tree hierarchy and attributes with + * powerdebug + */ +static struct dentry *clk_debugfs_root; + +void __init clk_debugfs_add_table(struct clk_lookup *cl, size_t num) +{ + while (num--) { + /* Check that the clock has not been already registered */ + if (!(cl->clk->list.prev != cl->clk->list.next)) + list_add_tail(&cl->clk->list, &clk_list); + + cl++; + } +} + +static ssize_t usecount_dbg_read(struct file *file, char __user *buf, + size_t size, loff_t *off) +{ + struct clk *clk = file->f_dentry->d_inode->i_private; + char cusecount[128]; + unsigned int len; + + len = sprintf(cusecount, "%u\n", clk->enabled); + return simple_read_from_buffer(buf, size, off, cusecount, len); +} + +static ssize_t rate_dbg_read(struct file *file, char __user *buf, + size_t size, loff_t *off) +{ + struct clk *clk = file->f_dentry->d_inode->i_private; + char crate[128]; + unsigned int rate; + unsigned int len; + + rate = clk_get_rate(clk); + len = sprintf(crate, "%u\n", rate); + return simple_read_from_buffer(buf, size, off, crate, len); +} + +static const struct file_operations usecount_fops = { + .read = usecount_dbg_read, +}; + +static const struct file_operations set_rate_fops = { + .read = rate_dbg_read, +}; + +static struct dentry *clk_debugfs_register_dir(struct clk *c, + struct dentry *p_dentry) +{ + struct dentry *d, *clk_d; + const char *p = c->name; + + if (!p) + p = "BUG"; + + clk_d = debugfs_create_dir(p, p_dentry); + if (!clk_d) + return NULL; + + d = debugfs_create_file("usecount", S_IRUGO, + clk_d, c, &usecount_fops); + if (!d) + goto err_out; + d = debugfs_create_file("rate", S_IRUGO, + clk_d, c, &set_rate_fops); + if (!d) + goto err_out; + /* + * TODO : not currently available in ux500 + * d = debugfs_create_x32("flags", S_IRUGO, clk_d, (u32 *)&c->flags); + * if (!d) + * goto err_out; + */ + + return clk_d; + +err_out: + debugfs_remove_recursive(clk_d); + return NULL; +} + +static int clk_debugfs_register_one(struct clk *c) +{ + struct clk *pa = c->parent_periph; + struct clk *bpa = c->parent_cluster; + + if (!(bpa && !pa)) { + c->dent = clk_debugfs_register_dir(c, + pa ? pa->dent : clk_debugfs_root); + if (!c->dent) + return -ENOMEM; + } + + if (bpa) { + c->dent_bus = clk_debugfs_register_dir(c, + bpa->dent_bus ? bpa->dent_bus : bpa->dent); + if ((!c->dent_bus) && (c->dent)) { + debugfs_remove_recursive(c->dent); + c->dent = NULL; + return -ENOMEM; + } + } + return 0; +} + +static int clk_debugfs_register(struct clk *c) +{ + int err; + struct clk *pa = c->parent_periph; + struct clk *bpa = c->parent_cluster; + + if (pa && (!pa->dent && !pa->dent_bus)) { + err = clk_debugfs_register(pa); + if (err) + return err; + } + + if (bpa && (!bpa->dent && !bpa->dent_bus)) { + err = clk_debugfs_register(bpa); + if (err) + return err; + } + + if ((!c->dent) && (!c->dent_bus)) { + err = clk_debugfs_register_one(c); + if (err) + return err; + } + return 0; +} + +int __init clk_debugfs_init(void) +{ + struct clk *c; + struct dentry *d; + int err; + + d = debugfs_create_dir("clock", NULL); + if (!d) + return -ENOMEM; + clk_debugfs_root = d; + + list_for_each_entry(c, &clk_list, list) { + err = clk_debugfs_register(c); + if (err) + goto err_out; + } + return 0; +err_out: + debugfs_remove_recursive(clk_debugfs_root); + return err; +} + +#endif /* defined(CONFIG_DEBUG_FS) */ + +unsigned long clk_smp_twd_rate = 500000000; + +unsigned long clk_smp_twd_get_rate(struct clk *clk) +{ + return clk_smp_twd_rate; +} + +static struct clk clk_smp_twd = { + .get_rate = clk_smp_twd_get_rate, + .name = "smp_twd", +}; + +static struct clk_lookup clk_smp_twd_lookup = { + .dev_id = "smp_twd", + .clk = &clk_smp_twd, +}; + +#ifdef CONFIG_CPU_FREQ + +static int clk_twd_cpufreq_transition(struct notifier_block *nb, + unsigned long state, void *data) +{ + struct cpufreq_freqs *f = data; + + if (state == CPUFREQ_PRECHANGE) { + /* Save frequency in simple Hz */ + clk_smp_twd_rate = (f->new * 1000) / 2; + } + + return NOTIFY_OK; +} + +static struct notifier_block clk_twd_cpufreq_nb = { + .notifier_call = clk_twd_cpufreq_transition, +}; + +int clk_init_smp_twd_cpufreq(void) +{ + return cpufreq_register_notifier(&clk_twd_cpufreq_nb, + CPUFREQ_TRANSITION_NOTIFIER); +} + +#endif + +int __init clk_init(void) +{ + clkdev_add_table(u8500_clks, ARRAY_SIZE(u8500_clks)); + clkdev_add(&clk_smp_twd_lookup); + +#ifdef CONFIG_DEBUG_FS + clk_debugfs_add_table(u8500_clks, ARRAY_SIZE(u8500_clks)); +#endif + return 0; +} diff --git a/trunk/arch/arm/mach-ux500/clock.h b/trunk/arch/arm/mach-ux500/clock.h new file mode 100644 index 000000000000..65d27a13f46d --- /dev/null +++ b/trunk/arch/arm/mach-ux500/clock.h @@ -0,0 +1,164 @@ +/* + * Copyright (C) 2010 ST-Ericsson + * Copyright (C) 2009 STMicroelectronics + * + * 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. + */ + +/** + * struct clkops - ux500 clock operations + * @enable: function to enable the clock + * @disable: function to disable the clock + * @get_rate: function to get the current clock rate + * + * This structure contains function pointers to functions that will be used to + * control the clock. All of these functions are optional. If get_rate is + * NULL, the rate in the struct clk will be used. + */ +struct clkops { + void (*enable) (struct clk *); + void (*disable) (struct clk *); + unsigned long (*get_rate) (struct clk *); + int (*set_parent)(struct clk *, struct clk *); +}; + +/** + * struct clk - ux500 clock structure + * @ops: pointer to clkops struct used to control this clock + * @name: name, for debugging + * @enabled: refcount. positive if enabled, zero if disabled + * @get_rate: custom callback for getting the clock rate + * @data: custom per-clock data for example for the get_rate + * callback + * @rate: fixed rate for clocks which don't implement + * ops->getrate + * @prcmu_cg_off: address offset of the combined enable/disable register + * (used on u8500v1) + * @prcmu_cg_bit: bit in the combined enable/disable register (used on + * u8500v1) + * @prcmu_cg_mgt: address of the enable/disable register (used on + * u8500ed) + * @cluster: peripheral cluster number + * @prcc_bus: bit for the bus clock in the peripheral's CLKRST + * @prcc_kernel: bit for the kernel clock in the peripheral's CLKRST. + * -1 if no kernel clock exists. + * @parent_cluster: pointer to parent's cluster clk struct + * @parent_periph: pointer to parent's peripheral clk struct + * + * Peripherals are organised into clusters, and each cluster has an associated + * bus clock. Some peripherals also have a parent peripheral clock. + * + * In order to enable a clock for a peripheral, we need to enable: + * (1) the parent cluster (bus) clock at the PRCMU level + * (2) the parent peripheral clock (if any) at the PRCMU level + * (3) the peripheral's bus & kernel clock at the PRCC level + * + * (1) and (2) are handled by defining clk structs (DEFINE_PRCMU_CLK) for each + * of the cluster and peripheral clocks, and hooking these as the parents of + * the individual peripheral clocks. + * + * (3) is handled by specifying the bits in the PRCC control registers required + * to enable these clocks and modifying them in the ->enable and + * ->disable callbacks of the peripheral clocks (DEFINE_PRCC_CLK). + * + * This structure describes both the PRCMU-level clocks and PRCC-level clocks. + * The prcmu_* fields are only used for the PRCMU clocks, and the cluster, + * prcc, and parent pointers are only used for the PRCC-level clocks. + */ +struct clk { + const struct clkops *ops; + const char *name; + unsigned int enabled; + unsigned long (*get_rate)(struct clk *); + void *data; + + unsigned long rate; + struct list_head list; + + /* These three are only for PRCMU clks */ + + unsigned int prcmu_cg_off; + unsigned int prcmu_cg_bit; + unsigned int prcmu_cg_mgt; + + /* The rest are only for PRCC clks */ + + int cluster; + unsigned int prcc_bus; + unsigned int prcc_kernel; + + struct clk *parent_cluster; + struct clk *parent_periph; +#if defined(CONFIG_DEBUG_FS) + struct dentry *dent; /* For visible tree hierarchy */ + struct dentry *dent_bus; /* For visible tree hierarchy */ +#endif +}; + +#define DEFINE_PRCMU_CLK(_name, _cg_off, _cg_bit, _reg) \ +struct clk clk_##_name = { \ + .name = #_name, \ + .ops = &clk_prcmu_ops, \ + .prcmu_cg_off = _cg_off, \ + .prcmu_cg_bit = _cg_bit, \ + .prcmu_cg_mgt = PRCM_##_reg##_MGT \ + } + +#define DEFINE_PRCMU_CLK_RATE(_name, _cg_off, _cg_bit, _reg, _rate) \ +struct clk clk_##_name = { \ + .name = #_name, \ + .ops = &clk_prcmu_ops, \ + .prcmu_cg_off = _cg_off, \ + .prcmu_cg_bit = _cg_bit, \ + .rate = _rate, \ + .prcmu_cg_mgt = PRCM_##_reg##_MGT \ + } + +#define DEFINE_PRCC_CLK(_pclust, _name, _bus_en, _kernel_en, _kernclk) \ +struct clk clk_##_name = { \ + .name = #_name, \ + .ops = &clk_prcc_ops, \ + .cluster = _pclust, \ + .prcc_bus = _bus_en, \ + .prcc_kernel = _kernel_en, \ + .parent_cluster = &clk_per##_pclust##clk, \ + .parent_periph = _kernclk \ + } + +#define DEFINE_PRCC_CLK_CUSTOM(_pclust, _name, _bus_en, _kernel_en, _kernclk, _callback, _data) \ +struct clk clk_##_name = { \ + .name = #_name, \ + .ops = &clk_prcc_ops, \ + .cluster = _pclust, \ + .prcc_bus = _bus_en, \ + .prcc_kernel = _kernel_en, \ + .parent_cluster = &clk_per##_pclust##clk, \ + .parent_periph = _kernclk, \ + .get_rate = _callback, \ + .data = (void *) _data \ + } + + +#define CLK(_clk, _devname, _conname) \ + { \ + .clk = &clk_##_clk, \ + .dev_id = _devname, \ + .con_id = _conname, \ + } + +int __init clk_db8500_ed_fixup(void); +int __init clk_init(void); + +#ifdef CONFIG_DEBUG_FS +int clk_debugfs_init(void); +#else +static inline int clk_debugfs_init(void) { return 0; } +#endif + +#ifdef CONFIG_CPU_FREQ +int clk_init_smp_twd_cpufreq(void); +#else +static inline int clk_init_smp_twd_cpufreq(void) { return 0; } +#endif diff --git a/trunk/arch/arm/mach-ux500/cpu.c b/trunk/arch/arm/mach-ux500/cpu.c index 17a78ec516ff..e2360e7c770d 100644 --- a/trunk/arch/arm/mach-ux500/cpu.c +++ b/trunk/arch/arm/mach-ux500/cpu.c @@ -8,6 +8,7 @@ #include #include +#include #include #include #include @@ -16,7 +17,6 @@ #include #include #include -#include #include #include @@ -25,6 +25,8 @@ #include #include +#include "clock.h" + void __iomem *_PRCMU_BASE; /* @@ -68,17 +70,13 @@ void __init ux500_init_irq(void) */ if (cpu_is_u8500_family()) db8500_prcmu_early_init(); - - if (cpu_is_u8500_family()) - u8500_clk_init(); - else if (cpu_is_u9540()) - u9540_clk_init(); - else if (cpu_is_u8540()) - u8540_clk_init(); + clk_init(); } void __init ux500_init_late(void) { + clk_debugfs_init(); + clk_init_smp_twd_cpufreq(); } static const char * __init ux500_get_machine(void) diff --git a/trunk/arch/arm/mm/context.c b/trunk/arch/arm/mm/context.c index 4e07eec1270d..119bc52ab93e 100644 --- a/trunk/arch/arm/mm/context.c +++ b/trunk/arch/arm/mm/context.c @@ -63,11 +63,10 @@ static int contextidr_notifier(struct notifier_block *unused, unsigned long cmd, pid = task_pid_nr(thread->task) << ASID_BITS; asm volatile( " mrc p15, 0, %0, c13, c0, 1\n" - " and %0, %0, %2\n" - " orr %0, %0, %1\n" - " mcr p15, 0, %0, c13, c0, 1\n" + " bfi %1, %0, #0, %2\n" + " mcr p15, 0, %1, c13, c0, 1\n" : "=r" (contextidr), "+r" (pid) - : "I" (~ASID_MASK)); + : "I" (ASID_BITS)); isb(); return NOTIFY_OK; diff --git a/trunk/arch/arm/mm/dma-mapping.c b/trunk/arch/arm/mm/dma-mapping.c index 13f555d62491..c2cdf6500f75 100644 --- a/trunk/arch/arm/mm/dma-mapping.c +++ b/trunk/arch/arm/mm/dma-mapping.c @@ -267,19 +267,17 @@ static void __dma_free_remap(void *cpu_addr, size_t size) vunmap(cpu_addr); } -#define DEFAULT_DMA_COHERENT_POOL_SIZE SZ_256K - struct dma_pool { size_t size; spinlock_t lock; unsigned long *bitmap; unsigned long nr_pages; void *vaddr; - struct page **pages; + struct page *page; }; static struct dma_pool atomic_pool = { - .size = DEFAULT_DMA_COHERENT_POOL_SIZE, + .size = SZ_256K, }; static int __init early_coherent_pool(char *p) @@ -289,21 +287,6 @@ static int __init early_coherent_pool(char *p) } early_param("coherent_pool", early_coherent_pool); -void __init init_dma_coherent_pool_size(unsigned long size) -{ - /* - * Catch any attempt to set the pool size too late. - */ - BUG_ON(atomic_pool.vaddr); - - /* - * Set architecture specific coherent pool size only if - * it has not been changed by kernel command line parameter. - */ - if (atomic_pool.size == DEFAULT_DMA_COHERENT_POOL_SIZE) - atomic_pool.size = size; -} - /* * Initialise the coherent pool for atomic allocations. */ @@ -314,7 +297,6 @@ static int __init atomic_pool_init(void) unsigned long nr_pages = pool->size >> PAGE_SHIFT; unsigned long *bitmap; struct page *page; - struct page **pages; void *ptr; int bitmap_size = BITS_TO_LONGS(nr_pages) * sizeof(long); @@ -322,33 +304,21 @@ static int __init atomic_pool_init(void) if (!bitmap) goto no_bitmap; - pages = kzalloc(nr_pages * sizeof(struct page *), GFP_KERNEL); - if (!pages) - goto no_pages; - if (IS_ENABLED(CONFIG_CMA)) ptr = __alloc_from_contiguous(NULL, pool->size, prot, &page); else ptr = __alloc_remap_buffer(NULL, pool->size, GFP_KERNEL, prot, &page, NULL); if (ptr) { - int i; - - for (i = 0; i < nr_pages; i++) - pages[i] = page + i; - spin_lock_init(&pool->lock); pool->vaddr = ptr; - pool->pages = pages; + pool->page = page; pool->bitmap = bitmap; pool->nr_pages = nr_pages; pr_info("DMA: preallocated %u KiB pool for atomic coherent allocations\n", (unsigned)pool->size / 1024); return 0; } - - kfree(pages); -no_pages: kfree(bitmap); no_bitmap: pr_err("DMA: failed to allocate %u KiB pool for atomic coherent allocation\n", @@ -388,7 +358,7 @@ void __init dma_contiguous_remap(void) if (end > arm_lowmem_limit) end = arm_lowmem_limit; if (start >= end) - continue; + return; map.pfn = __phys_to_pfn(start); map.virtual = __phys_to_virt(start); @@ -453,7 +423,7 @@ static void *__alloc_from_pool(size_t size, struct page **ret_page) unsigned int pageno; unsigned long flags; void *ptr = NULL; - unsigned long align_mask; + size_t align; if (!pool->vaddr) { WARN(1, "coherent pool not initialised!\n"); @@ -465,53 +435,35 @@ static void *__alloc_from_pool(size_t size, struct page **ret_page) * small, so align them to their order in pages, minimum is a page * size. This helps reduce fragmentation of the DMA space. */ - align_mask = (1 << get_order(size)) - 1; + align = PAGE_SIZE << get_order(size); spin_lock_irqsave(&pool->lock, flags); pageno = bitmap_find_next_zero_area(pool->bitmap, pool->nr_pages, - 0, count, align_mask); + 0, count, (1 << align) - 1); if (pageno < pool->nr_pages) { bitmap_set(pool->bitmap, pageno, count); ptr = pool->vaddr + PAGE_SIZE * pageno; - *ret_page = pool->pages[pageno]; - } else { - pr_err_once("ERROR: %u KiB atomic DMA coherent pool is too small!\n" - "Please increase it with coherent_pool= kernel parameter!\n", - (unsigned)pool->size / 1024); + *ret_page = pool->page + pageno; } spin_unlock_irqrestore(&pool->lock, flags); return ptr; } -static bool __in_atomic_pool(void *start, size_t size) -{ - struct dma_pool *pool = &atomic_pool; - void *end = start + size; - void *pool_start = pool->vaddr; - void *pool_end = pool->vaddr + pool->size; - - if (start < pool_start || start >= pool_end) - return false; - - if (end <= pool_end) - return true; - - WARN(1, "Wrong coherent size(%p-%p) from atomic pool(%p-%p)\n", - start, end - 1, pool_start, pool_end - 1); - - return false; -} - static int __free_from_pool(void *start, size_t size) { struct dma_pool *pool = &atomic_pool; unsigned long pageno, count; unsigned long flags; - if (!__in_atomic_pool(start, size)) + if (start < pool->vaddr || start > pool->vaddr + pool->size) return 0; + if (start + size > pool->vaddr + pool->size) { + WARN(1, "freeing wrong coherent size from pool\n"); + return 0; + } + pageno = (start - pool->vaddr) >> PAGE_SHIFT; count = size >> PAGE_SHIFT; @@ -696,12 +648,12 @@ void arm_dma_free(struct device *dev, size_t size, void *cpu_addr, if (arch_is_coherent() || nommu()) { __dma_free_buffer(page, size); - } else if (__free_from_pool(cpu_addr, size)) { - return; } else if (!IS_ENABLED(CONFIG_CMA)) { __dma_free_remap(cpu_addr, size); __dma_free_buffer(page, size); } else { + if (__free_from_pool(cpu_addr, size)) + return; /* * Non-atomic allocations cannot be freed with IRQs disabled */ @@ -1138,22 +1090,10 @@ static int __iommu_remove_mapping(struct device *dev, dma_addr_t iova, size_t si return 0; } -static struct page **__atomic_get_pages(void *addr) -{ - struct dma_pool *pool = &atomic_pool; - struct page **pages = pool->pages; - int offs = (addr - pool->vaddr) >> PAGE_SHIFT; - - return pages + offs; -} - static struct page **__iommu_get_pages(void *cpu_addr, struct dma_attrs *attrs) { struct vm_struct *area; - if (__in_atomic_pool(cpu_addr, PAGE_SIZE)) - return __atomic_get_pages(cpu_addr); - if (dma_get_attr(DMA_ATTR_NO_KERNEL_MAPPING, attrs)) return cpu_addr; @@ -1163,34 +1103,6 @@ static struct page **__iommu_get_pages(void *cpu_addr, struct dma_attrs *attrs) return NULL; } -static void *__iommu_alloc_atomic(struct device *dev, size_t size, - dma_addr_t *handle) -{ - struct page *page; - void *addr; - - addr = __alloc_from_pool(size, &page); - if (!addr) - return NULL; - - *handle = __iommu_create_mapping(dev, &page, size); - if (*handle == DMA_ERROR_CODE) - goto err_mapping; - - return addr; - -err_mapping: - __free_from_pool(addr, size); - return NULL; -} - -static void __iommu_free_atomic(struct device *dev, struct page **pages, - dma_addr_t handle, size_t size) -{ - __iommu_remove_mapping(dev, handle, size); - __free_from_pool(page_address(pages[0]), size); -} - static void *arm_iommu_alloc_attrs(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp, struct dma_attrs *attrs) { @@ -1201,9 +1113,6 @@ static void *arm_iommu_alloc_attrs(struct device *dev, size_t size, *handle = DMA_ERROR_CODE; size = PAGE_ALIGN(size); - if (gfp & GFP_ATOMIC) - return __iommu_alloc_atomic(dev, size, handle); - pages = __iommu_alloc_buffer(dev, size, gfp); if (!pages) return NULL; @@ -1270,11 +1179,6 @@ void arm_iommu_free_attrs(struct device *dev, size_t size, void *cpu_addr, return; } - if (__in_atomic_pool(cpu_addr, size)) { - __iommu_free_atomic(dev, pages, handle, size); - return; - } - if (!dma_get_attr(DMA_ATTR_NO_KERNEL_MAPPING, attrs)) { unmap_kernel_range((unsigned long)cpu_addr, size); vunmap(cpu_addr); diff --git a/trunk/arch/arm/mm/flush.c b/trunk/arch/arm/mm/flush.c index 40ca11ed6e5f..77458548e031 100644 --- a/trunk/arch/arm/mm/flush.c +++ b/trunk/arch/arm/mm/flush.c @@ -231,6 +231,8 @@ void __sync_icache_dcache(pte_t pteval) struct page *page; struct address_space *mapping; + if (!pte_present_user(pteval)) + return; if (cache_is_vipt_nonaliasing() && !pte_exec(pteval)) /* only flush non-aliasing VIPT caches for exec mappings */ return; diff --git a/trunk/arch/arm/mm/mm.h b/trunk/arch/arm/mm/mm.h index a8ee92da3544..6776160618ef 100644 --- a/trunk/arch/arm/mm/mm.h +++ b/trunk/arch/arm/mm/mm.h @@ -55,9 +55,6 @@ extern void __flush_dcache_page(struct address_space *mapping, struct page *page /* permanent static mappings from iotable_init() */ #define VM_ARM_STATIC_MAPPING 0x40000000 -/* empty mapping */ -#define VM_ARM_EMPTY_MAPPING 0x20000000 - /* mapping type (attributes) for permanent static mappings */ #define VM_ARM_MTYPE(mt) ((mt) << 20) #define VM_ARM_MTYPE_MASK (0x1f << 20) diff --git a/trunk/arch/arm/mm/mmu.c b/trunk/arch/arm/mm/mmu.c index c2fa21d0103e..4c2d0451e84a 100644 --- a/trunk/arch/arm/mm/mmu.c +++ b/trunk/arch/arm/mm/mmu.c @@ -807,7 +807,7 @@ static void __init pmd_empty_section_gap(unsigned long addr) vm = early_alloc_aligned(sizeof(*vm), __alignof__(*vm)); vm->addr = (void *)addr; vm->size = SECTION_SIZE; - vm->flags = VM_IOREMAP | VM_ARM_EMPTY_MAPPING; + vm->flags = VM_IOREMAP | VM_ARM_STATIC_MAPPING; vm->caller = pmd_empty_section_gap; vm_area_add_early(vm); } @@ -820,7 +820,7 @@ static void __init fill_pmd_gaps(void) /* we're still single threaded hence no lock needed here */ for (vm = vmlist; vm; vm = vm->next) { - if (!(vm->flags & (VM_ARM_STATIC_MAPPING | VM_ARM_EMPTY_MAPPING))) + if (!(vm->flags & VM_ARM_STATIC_MAPPING)) continue; addr = (unsigned long)vm->addr; if (addr < next) @@ -961,8 +961,8 @@ void __init sanity_check_meminfo(void) * Check whether this memory bank would partially overlap * the vmalloc area. */ - if (__va(bank->start + bank->size - 1) >= vmalloc_min || - __va(bank->start + bank->size - 1) <= __va(bank->start)) { + if (__va(bank->start + bank->size) > vmalloc_min || + __va(bank->start + bank->size) < __va(bank->start)) { unsigned long newsize = vmalloc_min - __va(bank->start); printk(KERN_NOTICE "Truncating RAM at %.8llx-%.8llx " "to -%.8llx (vmalloc region overlap).\n", diff --git a/trunk/arch/arm/mm/tlb-v7.S b/trunk/arch/arm/mm/tlb-v7.S index ea94765acf9a..c2021139cb56 100644 --- a/trunk/arch/arm/mm/tlb-v7.S +++ b/trunk/arch/arm/mm/tlb-v7.S @@ -38,10 +38,10 @@ ENTRY(v7wbi_flush_user_tlb_range) dsb mov r0, r0, lsr #PAGE_SHIFT @ align address mov r1, r1, lsr #PAGE_SHIFT - asid r3, r3 @ mask ASID #ifdef CONFIG_ARM_ERRATA_720789 - ALT_SMP(W(mov) r3, #0 ) - ALT_UP(W(nop) ) + mov r3, #0 +#else + asid r3, r3 @ mask ASID #endif orr r0, r3, r0, lsl #PAGE_SHIFT @ Create initial MVA mov r1, r1, lsl #PAGE_SHIFT diff --git a/trunk/arch/arm/plat-mxc/include/mach/mx25.h b/trunk/arch/arm/plat-mxc/include/mach/mx25.h index ec466400a200..627d94f1b010 100644 --- a/trunk/arch/arm/plat-mxc/include/mach/mx25.h +++ b/trunk/arch/arm/plat-mxc/include/mach/mx25.h @@ -98,7 +98,6 @@ #define MX25_INT_UART1 (NR_IRQS_LEGACY + 45) #define MX25_INT_GPIO2 (NR_IRQS_LEGACY + 51) #define MX25_INT_GPIO1 (NR_IRQS_LEGACY + 52) -#define MX25_INT_GPT1 (NR_IRQS_LEGACY + 54) #define MX25_INT_FEC (NR_IRQS_LEGACY + 57) #define MX25_DMA_REQ_SSI2_RX1 22 diff --git a/trunk/arch/arm/plat-omap/dmtimer.c b/trunk/arch/arm/plat-omap/dmtimer.c index 938b50a33439..626ad8cad7a9 100644 --- a/trunk/arch/arm/plat-omap/dmtimer.c +++ b/trunk/arch/arm/plat-omap/dmtimer.c @@ -189,7 +189,6 @@ struct omap_dm_timer *omap_dm_timer_request(void) timer->reserved = 1; break; } - spin_unlock_irqrestore(&dm_timer_lock, flags); if (timer) { ret = omap_dm_timer_prepare(timer); @@ -198,6 +197,7 @@ struct omap_dm_timer *omap_dm_timer_request(void) timer = NULL; } } + spin_unlock_irqrestore(&dm_timer_lock, flags); if (!timer) pr_debug("%s: timer request failed!\n", __func__); @@ -220,7 +220,6 @@ struct omap_dm_timer *omap_dm_timer_request_specific(int id) break; } } - spin_unlock_irqrestore(&dm_timer_lock, flags); if (timer) { ret = omap_dm_timer_prepare(timer); @@ -229,6 +228,7 @@ struct omap_dm_timer *omap_dm_timer_request_specific(int id) timer = NULL; } } + spin_unlock_irqrestore(&dm_timer_lock, flags); if (!timer) pr_debug("%s: timer%d request failed!\n", __func__, id); @@ -258,7 +258,7 @@ EXPORT_SYMBOL_GPL(omap_dm_timer_enable); void omap_dm_timer_disable(struct omap_dm_timer *timer) { - pm_runtime_put_sync(&timer->pdev->dev); + pm_runtime_put(&timer->pdev->dev); } EXPORT_SYMBOL_GPL(omap_dm_timer_disable); diff --git a/trunk/arch/arm/plat-omap/include/plat/cpu.h b/trunk/arch/arm/plat-omap/include/plat/cpu.h index bb5d08a70dbc..68b180edcfff 100644 --- a/trunk/arch/arm/plat-omap/include/plat/cpu.h +++ b/trunk/arch/arm/plat-omap/include/plat/cpu.h @@ -372,8 +372,7 @@ IS_OMAP_TYPE(3430, 0x3430) #define cpu_class_is_omap1() (cpu_is_omap7xx() || cpu_is_omap15xx() || \ cpu_is_omap16xx()) #define cpu_class_is_omap2() (cpu_is_omap24xx() || cpu_is_omap34xx() || \ - cpu_is_omap44xx() || soc_is_omap54xx() || \ - soc_is_am33xx()) + cpu_is_omap44xx() || soc_is_omap54xx()) /* Various silicon revisions for omap2 */ #define OMAP242X_CLASS 0x24200024 diff --git a/trunk/arch/arm/plat-omap/include/plat/multi.h b/trunk/arch/arm/plat-omap/include/plat/multi.h index 324d31b14852..045e320f1067 100644 --- a/trunk/arch/arm/plat-omap/include/plat/multi.h +++ b/trunk/arch/arm/plat-omap/include/plat/multi.h @@ -108,13 +108,4 @@ # endif #endif -#ifdef CONFIG_SOC_AM33XX -# ifdef OMAP_NAME -# undef MULTI_OMAP2 -# define MULTI_OMAP2 -# else -# define OMAP_NAME am33xx -# endif -#endif - #endif /* __PLAT_OMAP_MULTI_H */ diff --git a/trunk/arch/arm/plat-omap/include/plat/omap-serial.h b/trunk/arch/arm/plat-omap/include/plat/omap-serial.h index a531149823bb..1a52725ffcf2 100644 --- a/trunk/arch/arm/plat-omap/include/plat/omap-serial.h +++ b/trunk/arch/arm/plat-omap/include/plat/omap-serial.h @@ -18,7 +18,7 @@ #define __OMAP_SERIAL_H__ #include -#include +#include #include #include @@ -42,10 +42,10 @@ #define OMAP_UART_WER_MOD_WKUP 0X7F /* Enable XON/XOFF flow control on output */ -#define OMAP_UART_SW_TX 0x8 +#define OMAP_UART_SW_TX 0x04 /* Enable XON/XOFF flow control on input */ -#define OMAP_UART_SW_RX 0x2 +#define OMAP_UART_SW_RX 0x04 #define OMAP_UART_SYSC_RESET 0X07 #define OMAP_UART_TCR_TRIG 0X0F @@ -69,14 +69,11 @@ struct omap_uart_port_info { unsigned int dma_rx_timeout; unsigned int autosuspend_timeout; unsigned int dma_rx_poll_rate; - int DTR_gpio; - int DTR_inverted; - int DTR_present; int (*get_context_loss_count)(struct device *); - void (*set_forceidle)(struct device *); - void (*set_noidle)(struct device *); - void (*enable_wakeup)(struct device *, bool); + void (*set_forceidle)(struct platform_device *); + void (*set_noidle)(struct platform_device *); + void (*enable_wakeup)(struct platform_device *, bool); }; struct uart_omap_dma { @@ -105,4 +102,39 @@ struct uart_omap_dma { unsigned int rx_timeout; }; +struct uart_omap_port { + struct uart_port port; + struct uart_omap_dma uart_dma; + struct platform_device *pdev; + + unsigned char ier; + unsigned char lcr; + unsigned char mcr; + unsigned char fcr; + unsigned char efr; + unsigned char dll; + unsigned char dlh; + unsigned char mdr1; + unsigned char scr; + + int use_dma; + /* + * Some bits in registers are cleared on a read, so they must + * be saved whenever the register is read but the bits will not + * be immediately processed. + */ + unsigned int lsr_break_flag; + unsigned char msr_saved_flags; + char name[20]; + unsigned long port_activity; + u32 context_loss_cnt; + u32 errata; + u8 wakeups_enabled; + + struct pm_qos_request pm_qos_request; + u32 latency; + u32 calc_latency; + struct work_struct qos_work; +}; + #endif /* __OMAP_SERIAL_H__ */ diff --git a/trunk/arch/arm/plat-omap/include/plat/uncompress.h b/trunk/arch/arm/plat-omap/include/plat/uncompress.h index 7f7b112acccb..b8d19a136781 100644 --- a/trunk/arch/arm/plat-omap/include/plat/uncompress.h +++ b/trunk/arch/arm/plat-omap/include/plat/uncompress.h @@ -110,7 +110,7 @@ static inline void flush(void) _DEBUG_LL_ENTRY(mach, AM33XX_UART##p##_BASE, OMAP_PORT_SHIFT, \ AM33XXUART##p) -static inline void arch_decomp_setup(void) +static inline void __arch_decomp_setup(unsigned long arch_id) { int port = 0; @@ -198,6 +198,8 @@ static inline void arch_decomp_setup(void) } while (0); } +#define arch_decomp_setup() __arch_decomp_setup(arch_id) + /* * nothing to do */ diff --git a/trunk/arch/arm/plat-omap/sram.c b/trunk/arch/arm/plat-omap/sram.c index 024f3b08db29..766181cb5c95 100644 --- a/trunk/arch/arm/plat-omap/sram.c +++ b/trunk/arch/arm/plat-omap/sram.c @@ -68,7 +68,6 @@ static unsigned long omap_sram_start; static void __iomem *omap_sram_base; -static unsigned long omap_sram_skip; static unsigned long omap_sram_size; static void __iomem *omap_sram_ceil; @@ -107,7 +106,6 @@ static int is_sram_locked(void) */ static void __init omap_detect_sram(void) { - omap_sram_skip = SRAM_BOOTLOADER_SZ; if (cpu_class_is_omap2()) { if (is_sram_locked()) { if (cpu_is_omap34xx()) { @@ -115,7 +113,6 @@ static void __init omap_detect_sram(void) if ((omap_type() == OMAP2_DEVICE_TYPE_EMU) || (omap_type() == OMAP2_DEVICE_TYPE_SEC)) { omap_sram_size = 0x7000; /* 28K */ - omap_sram_skip += SZ_16K; } else { omap_sram_size = 0x8000; /* 32K */ } @@ -178,10 +175,8 @@ static void __init omap_map_sram(void) return; #ifdef CONFIG_OMAP4_ERRATA_I688 - if (cpu_is_omap44xx()) { omap_sram_start += PAGE_SIZE; omap_sram_size -= SZ_16K; - } #endif if (cpu_is_omap34xx()) { /* @@ -208,8 +203,8 @@ static void __init omap_map_sram(void) * Looks like we need to preserve some bootloader code at the * beginning of SRAM for jumping to flash for reboot to work... */ - memset_io(omap_sram_base + omap_sram_skip, 0, - omap_sram_size - omap_sram_skip); + memset_io(omap_sram_base + SRAM_BOOTLOADER_SZ, 0, + omap_sram_size - SRAM_BOOTLOADER_SZ); } /* @@ -223,7 +218,7 @@ void *omap_sram_push_address(unsigned long size) { unsigned long available, new_ceil = (unsigned long)omap_sram_ceil; - available = omap_sram_ceil - (omap_sram_base + omap_sram_skip); + available = omap_sram_ceil - (omap_sram_base + SRAM_BOOTLOADER_SZ); if (size > available) { pr_err("Not enough space in SRAM\n"); diff --git a/trunk/arch/arm/plat-orion/common.c b/trunk/arch/arm/plat-orion/common.c index b8b747a9d360..d245a87dc014 100644 --- a/trunk/arch/arm/plat-orion/common.c +++ b/trunk/arch/arm/plat-orion/common.c @@ -291,12 +291,10 @@ static struct platform_device orion_ge00 = { void __init orion_ge00_init(struct mv643xx_eth_platform_data *eth_data, unsigned long mapbase, unsigned long irq, - unsigned long irq_err, - unsigned int tx_csum_limit) + unsigned long irq_err) { fill_resources(&orion_ge00_shared, orion_ge00_shared_resources, mapbase + 0x2000, SZ_16K - 1, irq_err); - orion_ge00_shared_data.tx_csum_limit = tx_csum_limit; ge_complete(&orion_ge00_shared_data, orion_ge00_resources, irq, &orion_ge00_shared, eth_data, &orion_ge00); @@ -345,12 +343,10 @@ static struct platform_device orion_ge01 = { void __init orion_ge01_init(struct mv643xx_eth_platform_data *eth_data, unsigned long mapbase, unsigned long irq, - unsigned long irq_err, - unsigned int tx_csum_limit) + unsigned long irq_err) { fill_resources(&orion_ge01_shared, orion_ge01_shared_resources, mapbase + 0x2000, SZ_16K - 1, irq_err); - orion_ge01_shared_data.tx_csum_limit = tx_csum_limit; ge_complete(&orion_ge01_shared_data, orion_ge01_resources, irq, &orion_ge01_shared, eth_data, &orion_ge01); diff --git a/trunk/arch/arm/plat-orion/include/plat/common.h b/trunk/arch/arm/plat-orion/include/plat/common.h index ae2377ef63e5..e00fdb213609 100644 --- a/trunk/arch/arm/plat-orion/include/plat/common.h +++ b/trunk/arch/arm/plat-orion/include/plat/common.h @@ -39,14 +39,12 @@ void __init orion_rtc_init(unsigned long mapbase, void __init orion_ge00_init(struct mv643xx_eth_platform_data *eth_data, unsigned long mapbase, unsigned long irq, - unsigned long irq_err, - unsigned int tx_csum_limit); + unsigned long irq_err); void __init orion_ge01_init(struct mv643xx_eth_platform_data *eth_data, unsigned long mapbase, unsigned long irq, - unsigned long irq_err, - unsigned int tx_csum_limit); + unsigned long irq_err); void __init orion_ge10_init(struct mv643xx_eth_platform_data *eth_data, unsigned long mapbase, diff --git a/trunk/arch/arm/plat-s3c24xx/dma.c b/trunk/arch/arm/plat-s3c24xx/dma.c index db98e7021f0d..28f898f75380 100644 --- a/trunk/arch/arm/plat-s3c24xx/dma.c +++ b/trunk/arch/arm/plat-s3c24xx/dma.c @@ -430,7 +430,7 @@ s3c2410_dma_canload(struct s3c2410_dma_chan *chan) * when necessary. */ -int s3c2410_dma_enqueue(enum dma_ch channel, void *id, +int s3c2410_dma_enqueue(unsigned int channel, void *id, dma_addr_t data, int size) { struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel); diff --git a/trunk/arch/arm/plat-samsung/Kconfig b/trunk/arch/arm/plat-samsung/Kconfig index 9c3b90c3538e..7aca31c1df1f 100644 --- a/trunk/arch/arm/plat-samsung/Kconfig +++ b/trunk/arch/arm/plat-samsung/Kconfig @@ -403,8 +403,7 @@ config S5P_DEV_USB_EHCI config S3C24XX_PWM bool "PWM device support" - select PWM - select PWM_SAMSUNG + select HAVE_PWM help Support for exporting the PWM timer blocks via the pwm device system diff --git a/trunk/arch/arm/plat-samsung/clock.c b/trunk/arch/arm/plat-samsung/clock.c index d1116e2dfbea..65c5eca475e7 100644 --- a/trunk/arch/arm/plat-samsung/clock.c +++ b/trunk/arch/arm/plat-samsung/clock.c @@ -144,7 +144,6 @@ long clk_round_rate(struct clk *clk, unsigned long rate) int clk_set_rate(struct clk *clk, unsigned long rate) { - unsigned long flags; int ret; if (IS_ERR(clk)) @@ -160,9 +159,9 @@ int clk_set_rate(struct clk *clk, unsigned long rate) if (clk->ops == NULL || clk->ops->set_rate == NULL) return -EINVAL; - spin_lock_irqsave(&clocks_lock, flags); + spin_lock(&clocks_lock); ret = (clk->ops->set_rate)(clk, rate); - spin_unlock_irqrestore(&clocks_lock, flags); + spin_unlock(&clocks_lock); return ret; } @@ -174,18 +173,17 @@ struct clk *clk_get_parent(struct clk *clk) int clk_set_parent(struct clk *clk, struct clk *parent) { - unsigned long flags; int ret = 0; if (IS_ERR(clk)) return -EINVAL; - spin_lock_irqsave(&clocks_lock, flags); + spin_lock(&clocks_lock); if (clk->ops && clk->ops->set_parent) ret = (clk->ops->set_parent)(clk, parent); - spin_unlock_irqrestore(&clocks_lock, flags); + spin_unlock(&clocks_lock); return ret; } diff --git a/trunk/arch/arm/plat-samsung/devs.c b/trunk/arch/arm/plat-samsung/devs.c index fc49f3dabd76..74e31ce35538 100644 --- a/trunk/arch/arm/plat-samsung/devs.c +++ b/trunk/arch/arm/plat-samsung/devs.c @@ -32,8 +32,6 @@ #include #include -#include - #include #include #include @@ -750,8 +748,7 @@ void __init s5p_i2c_hdmiphy_set_platdata(struct s3c2410_platform_i2c *pd) if (!pd) { pd = &default_i2c_data; - if (soc_is_exynos4210() || - soc_is_exynos4212() || soc_is_exynos4412()) + if (soc_is_exynos4210()) pd->bus_num = 8; else if (soc_is_s5pv210()) pd->bus_num = 3; @@ -762,30 +759,6 @@ void __init s5p_i2c_hdmiphy_set_platdata(struct s3c2410_platform_i2c *pd) npd = s3c_set_platdata(pd, sizeof(struct s3c2410_platform_i2c), &s5p_device_i2c_hdmiphy); } - -struct s5p_hdmi_platform_data s5p_hdmi_def_platdata; - -void __init s5p_hdmi_set_platdata(struct i2c_board_info *hdmiphy_info, - struct i2c_board_info *mhl_info, int mhl_bus) -{ - struct s5p_hdmi_platform_data *pd = &s5p_hdmi_def_platdata; - - if (soc_is_exynos4210() || - soc_is_exynos4212() || soc_is_exynos4412()) - pd->hdmiphy_bus = 8; - else if (soc_is_s5pv210()) - pd->hdmiphy_bus = 3; - else - pd->hdmiphy_bus = 0; - - pd->hdmiphy_info = hdmiphy_info; - pd->mhl_info = mhl_info; - pd->mhl_bus = mhl_bus; - - s3c_set_platdata(pd, sizeof(struct s5p_hdmi_platform_data), - &s5p_device_hdmi); -} - #endif /* CONFIG_S5P_DEV_I2C_HDMIPHY */ /* I2S */ diff --git a/trunk/arch/arm/plat-samsung/include/plat/hdmi.h b/trunk/arch/arm/plat-samsung/include/plat/hdmi.h deleted file mode 100644 index 331d046ac2c5..000000000000 --- a/trunk/arch/arm/plat-samsung/include/plat/hdmi.h +++ /dev/null @@ -1,16 +0,0 @@ -/* - * Copyright (C) 2012 Samsung Electronics Co.Ltd - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - */ - -#ifndef __PLAT_SAMSUNG_HDMI_H -#define __PLAT_SAMSUNG_HDMI_H __FILE__ - -extern void s5p_hdmi_set_platdata(struct i2c_board_info *hdmiphy_info, - struct i2c_board_info *mhl_info, int mhl_bus); - -#endif /* __PLAT_SAMSUNG_HDMI_H */ diff --git a/trunk/arch/arm/plat-samsung/pm.c b/trunk/arch/arm/plat-samsung/pm.c index 15070284343e..64ab65f0fdbc 100644 --- a/trunk/arch/arm/plat-samsung/pm.c +++ b/trunk/arch/arm/plat-samsung/pm.c @@ -74,7 +74,7 @@ unsigned char pm_uart_udivslot; #ifdef CONFIG_SAMSUNG_PM_DEBUG -static struct pm_uart_save uart_save[CONFIG_SERIAL_SAMSUNG_UARTS]; +struct pm_uart_save uart_save[CONFIG_SERIAL_SAMSUNG_UARTS]; static void s3c_pm_save_uart(unsigned int uart, struct pm_uart_save *save) { diff --git a/trunk/arch/arm/vfp/vfpmodule.c b/trunk/arch/arm/vfp/vfpmodule.c index c834b32af275..fb849d044bde 100644 --- a/trunk/arch/arm/vfp/vfpmodule.c +++ b/trunk/arch/arm/vfp/vfpmodule.c @@ -719,10 +719,8 @@ static int __init vfp_init(void) if ((fmrx(MVFR1) & 0x000fff00) == 0x00011100) elf_hwcap |= HWCAP_NEON; #endif -#ifdef CONFIG_VFPv3 if ((fmrx(MVFR1) & 0xf0000000) == 0x10000000) elf_hwcap |= HWCAP_VFPv4; -#endif } } return 0; diff --git a/trunk/arch/arm64/Kconfig b/trunk/arch/arm64/Kconfig deleted file mode 100644 index 767ba5685454..000000000000 --- a/trunk/arch/arm64/Kconfig +++ /dev/null @@ -1,222 +0,0 @@ -config ARM64 - def_bool y - select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE - select GENERIC_CLOCKEVENTS - select GENERIC_HARDIRQS_NO_DEPRECATED - select GENERIC_IOMAP - select GENERIC_IRQ_PROBE - select GENERIC_IRQ_SHOW - select GENERIC_SMP_IDLE_THREAD - select GENERIC_TIME_VSYSCALL - select HARDIRQS_SW_RESEND - select HAVE_ARCH_TRACEHOOK - select HAVE_DMA_API_DEBUG - select HAVE_DMA_ATTRS - select HAVE_GENERIC_DMA_COHERENT - select HAVE_GENERIC_HARDIRQS - select HAVE_HW_BREAKPOINT if PERF_EVENTS - select HAVE_IRQ_WORK - select HAVE_MEMBLOCK - select HAVE_PERF_EVENTS - select HAVE_SPARSE_IRQ - select IRQ_DOMAIN - select NO_BOOTMEM - select OF - select OF_EARLY_FLATTREE - select PERF_USE_VMALLOC - select RTC_LIB - select SPARSE_IRQ - help - ARM 64-bit (AArch64) Linux support. - -config 64BIT - def_bool y - -config ARCH_PHYS_ADDR_T_64BIT - def_bool y - -config MMU - def_bool y - -config NO_IOPORT - def_bool y - -config STACKTRACE_SUPPORT - def_bool y - -config LOCKDEP_SUPPORT - def_bool y - -config TRACE_IRQFLAGS_SUPPORT - def_bool y - -config GENERIC_LOCKBREAK - def_bool y - depends on SMP && PREEMPT - -config RWSEM_GENERIC_SPINLOCK - def_bool y - -config GENERIC_HWEIGHT - def_bool y - -config GENERIC_CSUM - def_bool y - -config GENERIC_CALIBRATE_DELAY - def_bool y - -config ZONE_DMA32 - def_bool y - -config ARCH_DMA_ADDR_T_64BIT - def_bool y - -config NEED_DMA_MAP_STATE - def_bool y - -config NEED_SG_DMA_LENGTH - def_bool y - -config SWIOTLB - def_bool y - -config IOMMU_HELPER - def_bool SWIOTLB - -source "init/Kconfig" - -source "kernel/Kconfig.freezer" - -menu "System Type" - -endmenu - -menu "Bus support" - -config ARM_AMBA - bool - -endmenu - -menu "Kernel Features" - -source "kernel/time/Kconfig" - -config ARM64_64K_PAGES - bool "Enable 64KB pages support" - help - This feature enables 64KB pages support (4KB by default) - allowing only two levels of page tables and faster TLB - look-up. AArch32 emulation is not available when this feature - is enabled. - -config SMP - bool "Symmetric Multi-Processing" - select USE_GENERIC_SMP_HELPERS - help - This enables support for systems with more than one CPU. If - you say N here, the kernel will run on single and - multiprocessor machines, but will use only one CPU of a - multiprocessor machine. If you say Y here, the kernel will run - on many, but not all, single processor machines. On a single - processor machine, the kernel will run faster if you say N - here. - - If you don't know what to do here, say N. - -config NR_CPUS - int "Maximum number of CPUs (2-32)" - range 2 32 - depends on SMP - default "4" - -source kernel/Kconfig.preempt - -config HZ - int - default 100 - -config ARCH_HAS_HOLES_MEMORYMODEL - def_bool y if SPARSEMEM - -config ARCH_SPARSEMEM_ENABLE - def_bool y - select SPARSEMEM_VMEMMAP_ENABLE - -config ARCH_SPARSEMEM_DEFAULT - def_bool ARCH_SPARSEMEM_ENABLE - -config ARCH_SELECT_MEMORY_MODEL - def_bool ARCH_SPARSEMEM_ENABLE - -config HAVE_ARCH_PFN_VALID - def_bool ARCH_HAS_HOLES_MEMORYMODEL || !SPARSEMEM - -config HW_PERF_EVENTS - bool "Enable hardware performance counter support for perf events" - depends on PERF_EVENTS - default y - help - Enable hardware performance counter support for perf events. If - disabled, perf events will use software events only. - -source "mm/Kconfig" - -endmenu - -menu "Boot options" - -config CMDLINE - string "Default kernel command string" - default "" - help - Provide a set of default command-line options at build time by - entering them here. As a minimum, you should specify the the - root device (e.g. root=/dev/nfs). - -config CMDLINE_FORCE - bool "Always use the default kernel command string" - help - Always use the default kernel command string, even if the boot - loader passes other arguments to the kernel. - This is useful if you cannot or don't want to change the - command-line options your boot loader passes to the kernel. - -endmenu - -menu "Userspace binary formats" - -source "fs/Kconfig.binfmt" - -config COMPAT - bool "Kernel support for 32-bit EL0" - depends on !ARM64_64K_PAGES - select COMPAT_BINFMT_ELF - help - This option enables support for a 32-bit EL0 running under a 64-bit - kernel at EL1. AArch32-specific components such as system calls, - the user helper functions, VFP support and the ptrace interface are - handled appropriately by the kernel. - - If you want to execute 32-bit userspace applications, say Y. - -config SYSVIPC_COMPAT - def_bool y - depends on COMPAT && SYSVIPC - -endmenu - -source "net/Kconfig" - -source "drivers/Kconfig" - -source "fs/Kconfig" - -source "arch/arm64/Kconfig.debug" - -source "security/Kconfig" - -source "crypto/Kconfig" - -source "lib/Kconfig" diff --git a/trunk/arch/arm64/Kconfig.debug b/trunk/arch/arm64/Kconfig.debug deleted file mode 100644 index d7553f2bda66..000000000000 --- a/trunk/arch/arm64/Kconfig.debug +++ /dev/null @@ -1,27 +0,0 @@ -menu "Kernel hacking" - -source "lib/Kconfig.debug" - -config FRAME_POINTER - bool - default y - -config DEBUG_ERRORS - bool "Verbose kernel error messages" - depends on DEBUG_KERNEL - help - This option controls verbose debugging information which can be - printed when the kernel detects an internal error. This debugging - information is useful to kernel hackers when tracking down problems, - but mostly meaningless to other people. It's safe to say Y unless - you are concerned with the code size or don't want to see these - messages. - -config DEBUG_STACK_USAGE - bool "Enable stack utilization instrumentation" - depends on DEBUG_KERNEL - help - Enables the display of the minimum amount of free stack which each - task has ever had available in the sysrq-T output. - -endmenu diff --git a/trunk/arch/arm64/Makefile b/trunk/arch/arm64/Makefile deleted file mode 100644 index 364191f3be43..000000000000 --- a/trunk/arch/arm64/Makefile +++ /dev/null @@ -1,71 +0,0 @@ -# -# arch/arm64/Makefile -# -# This file is included by the global makefile so that you can add your own -# architecture-specific flags and dependencies. -# -# 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) 1995-2001 by Russell King - -LDFLAGS_vmlinux :=-p --no-undefined -X -CPPFLAGS_vmlinux.lds = -DTEXT_OFFSET=$(TEXT_OFFSET) -OBJCOPYFLAGS :=-O binary -R .note -R .note.gnu.build-id -R .comment -S -GZFLAGS :=-9 - -LIBGCC := $(shell $(CC) $(KBUILD_CFLAGS) -print-libgcc-file-name) - -KBUILD_DEFCONFIG := defconfig - -KBUILD_CFLAGS += -mgeneral-regs-only -KBUILD_CPPFLAGS += -mlittle-endian -AS += -EL -LD += -EL - -comma = , - -CHECKFLAGS += -D__aarch64__ - -# Default value -head-y := arch/arm64/kernel/head.o - -# The byte offset of the kernel image in RAM from the start of RAM. -TEXT_OFFSET := 0x00080000 - -export TEXT_OFFSET GZFLAGS - -core-y += arch/arm64/kernel/ arch/arm64/mm/ -libs-y := arch/arm64/lib/ $(libs-y) -libs-y += $(LIBGCC) - -# Default target when executing plain make -KBUILD_IMAGE := Image.gz - -all: $(KBUILD_IMAGE) - -boot := arch/arm64/boot - -Image Image.gz: vmlinux - $(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $(boot)/$@ - -zinstall install: vmlinux - $(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $@ - -%.dtb: - $(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $(boot)/$@ - -# We use MRPROPER_FILES and CLEAN_FILES now -archclean: - $(Q)$(MAKE) $(clean)=$(boot) - -define archhelp - echo '* Image.gz - Compressed kernel image (arch/$(ARCH)/boot/Image.gz)' - echo ' Image - Uncompressed kernel image (arch/$(ARCH)/boot/Image)' - echo ' install - Install uncompressed kernel' - echo ' zinstall - Install compressed kernel' - echo ' Install using (your) ~/bin/installkernel or' - echo ' (distribution) /sbin/installkernel or' - echo ' install to $$(INSTALL_PATH) and run lilo' -endef diff --git a/trunk/arch/arm64/boot/.gitignore b/trunk/arch/arm64/boot/.gitignore deleted file mode 100644 index 8dab0bb6ae66..000000000000 --- a/trunk/arch/arm64/boot/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -Image -Image.gz diff --git a/trunk/arch/arm64/boot/Makefile b/trunk/arch/arm64/boot/Makefile deleted file mode 100644 index eca209b2b0bf..000000000000 --- a/trunk/arch/arm64/boot/Makefile +++ /dev/null @@ -1,36 +0,0 @@ -# -# arch/arm64/boot/Makefile -# -# This file is included by the global makefile so that you can add your own -# architecture-specific flags and dependencies. -# -# 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) 2012, ARM Ltd. -# Author: Will Deacon -# -# Based on the ia64 boot/Makefile. -# - -targets := Image Image.gz - -$(obj)/Image: vmlinux FORCE - $(call if_changed,objcopy) - -$(obj)/Image.gz: $(obj)/Image FORCE - $(call if_changed,gzip) - -$(obj)/%.dtb: $(src)/dts/%.dts - $(call cmd,dtc) - -install: $(obj)/Image - $(CONFIG_SHELL) $(srctree)/$(src)/install.sh $(KERNELRELEASE) \ - $(obj)/Image System.map "$(INSTALL_PATH)" - -zinstall: $(obj)/Image.gz - $(CONFIG_SHELL) $(srctree)/$(src)/install.sh $(KERNELRELEASE) \ - $(obj)/Image.gz System.map "$(INSTALL_PATH)" - -clean-files += *.dtb diff --git a/trunk/arch/arm64/boot/install.sh b/trunk/arch/arm64/boot/install.sh deleted file mode 100644 index 12ed78aa6f0c..000000000000 --- a/trunk/arch/arm64/boot/install.sh +++ /dev/null @@ -1,46 +0,0 @@ -#!/bin/sh -# -# arch/arm64/boot/install.sh -# -# 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) 1995 by Linus Torvalds -# -# Adapted from code in arch/i386/boot/Makefile by H. Peter Anvin -# Adapted from code in arch/i386/boot/install.sh by Russell King -# -# "make install" script for the AArch64 Linux port -# -# Arguments: -# $1 - kernel version -# $2 - kernel image file -# $3 - kernel map file -# $4 - default install path (blank if root directory) -# - -# User may have a custom install script -if [ -x ~/bin/${INSTALLKERNEL} ]; then exec ~/bin/${INSTALLKERNEL} "$@"; fi -if [ -x /sbin/${INSTALLKERNEL} ]; then exec /sbin/${INSTALLKERNEL} "$@"; fi - -if [ "$(basename $2)" = "Image.gz" ]; then -# Compressed install - echo "Installing compressed kernel" - base=vmlinuz -else -# Normal install - echo "Installing normal kernel" - base=vmlinux -fi - -if [ -f $4/$base-$1 ]; then - mv $4/$base-$1 $4/$base-$1.old -fi -cat $2 > $4/$base-$1 - -# Install system map file -if [ -f $4/System.map-$1 ]; then - mv $4/System.map-$1 $4/System.map-$1.old -fi -cp $3 $4/System.map-$1 diff --git a/trunk/arch/arm64/configs/defconfig b/trunk/arch/arm64/configs/defconfig deleted file mode 100644 index 9212c7880da7..000000000000 --- a/trunk/arch/arm64/configs/defconfig +++ /dev/null @@ -1,85 +0,0 @@ -CONFIG_EXPERIMENTAL=y -# CONFIG_LOCALVERSION_AUTO is not set -# CONFIG_SWAP is not set -CONFIG_SYSVIPC=y -CONFIG_POSIX_MQUEUE=y -CONFIG_BSD_PROCESS_ACCT=y -CONFIG_BSD_PROCESS_ACCT_V3=y -CONFIG_NO_HZ=y -CONFIG_HIGH_RES_TIMERS=y -CONFIG_IKCONFIG=y -CONFIG_IKCONFIG_PROC=y -CONFIG_LOG_BUF_SHIFT=14 -# CONFIG_UTS_NS is not set -# CONFIG_IPC_NS is not set -# CONFIG_PID_NS is not set -# CONFIG_NET_NS is not set -CONFIG_SCHED_AUTOGROUP=y -CONFIG_BLK_DEV_INITRD=y -CONFIG_KALLSYMS_ALL=y -# CONFIG_COMPAT_BRK is not set -CONFIG_PROFILING=y -CONFIG_MODULES=y -CONFIG_MODULE_UNLOAD=y -# CONFIG_BLK_DEV_BSG is not set -# CONFIG_IOSCHED_DEADLINE is not set -CONFIG_SMP=y -CONFIG_PREEMPT_VOLUNTARY=y -CONFIG_CMDLINE="console=ttyAMA0" -# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set -CONFIG_COMPAT=y -CONFIG_NET=y -CONFIG_PACKET=y -CONFIG_UNIX=y -CONFIG_INET=y -CONFIG_IP_PNP=y -CONFIG_IP_PNP_DHCP=y -CONFIG_IP_PNP_BOOTP=y -# CONFIG_INET_LRO is not set -# CONFIG_IPV6 is not set -# CONFIG_WIRELESS is not set -CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" -CONFIG_DEVTMPFS=y -# CONFIG_BLK_DEV is not set -CONFIG_SCSI=y -# CONFIG_SCSI_PROC_FS is not set -CONFIG_BLK_DEV_SD=y -# CONFIG_SCSI_LOWLEVEL is not set -CONFIG_NETDEVICES=y -CONFIG_MII=y -# CONFIG_WLAN is not set -CONFIG_INPUT_EVDEV=y -# CONFIG_SERIO_I8042 is not set -# CONFIG_SERIO_SERPORT is not set -CONFIG_LEGACY_PTY_COUNT=16 -# CONFIG_HW_RANDOM is not set -# CONFIG_HWMON is not set -CONFIG_FB=y -# CONFIG_VGA_CONSOLE is not set -CONFIG_FRAMEBUFFER_CONSOLE=y -CONFIG_LOGO=y -# CONFIG_LOGO_LINUX_MONO is not set -# CONFIG_LOGO_LINUX_VGA16 is not set -# CONFIG_USB_SUPPORT is not set -# CONFIG_IOMMU_SUPPORT is not set -CONFIG_EXT2_FS=y -CONFIG_EXT3_FS=y -# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set -# CONFIG_EXT3_FS_XATTR is not set -CONFIG_FUSE_FS=y -CONFIG_CUSE=y -CONFIG_VFAT_FS=y -CONFIG_TMPFS=y -# CONFIG_MISC_FILESYSTEMS is not set -CONFIG_NFS_FS=y -CONFIG_ROOT_NFS=y -CONFIG_NLS_CODEPAGE_437=y -CONFIG_NLS_ISO8859_1=y -CONFIG_MAGIC_SYSRQ=y -CONFIG_DEBUG_FS=y -CONFIG_DEBUG_KERNEL=y -# CONFIG_SCHED_DEBUG is not set -CONFIG_DEBUG_INFO=y -# CONFIG_FTRACE is not set -CONFIG_ATOMIC64_SELFTEST=y -CONFIG_DEBUG_ERRORS=y diff --git a/trunk/arch/arm64/include/asm/Kbuild b/trunk/arch/arm64/include/asm/Kbuild deleted file mode 100644 index 35924a542d43..000000000000 --- a/trunk/arch/arm64/include/asm/Kbuild +++ /dev/null @@ -1,51 +0,0 @@ -include include/asm-generic/Kbuild.asm - -header-y += hwcap.h - -generic-y += bug.h -generic-y += bugs.h -generic-y += checksum.h -generic-y += cputime.h -generic-y += current.h -generic-y += delay.h -generic-y += div64.h -generic-y += dma.h -generic-y += emergency-restart.h -generic-y += errno.h -generic-y += ftrace.h -generic-y += hw_irq.h -generic-y += ioctl.h -generic-y += ioctls.h -generic-y += ipcbuf.h -generic-y += irq_regs.h -generic-y += kdebug.h -generic-y += kmap_types.h -generic-y += linkage.h -generic-y += local.h -generic-y += local64.h -generic-y += mman.h -generic-y += msgbuf.h -generic-y += mutex.h -generic-y += pci.h -generic-y += percpu.h -generic-y += poll.h -generic-y += posix_types.h -generic-y += resource.h -generic-y += scatterlist.h -generic-y += sections.h -generic-y += segment.h -generic-y += sembuf.h -generic-y += serial.h -generic-y += shmbuf.h -generic-y += sizes.h -generic-y += socket.h -generic-y += sockios.h -generic-y += string.h -generic-y += switch_to.h -generic-y += swab.h -generic-y += termbits.h -generic-y += termios.h -generic-y += topology.h -generic-y += types.h -generic-y += unaligned.h -generic-y += user.h diff --git a/trunk/arch/arm64/include/asm/arm_generic.h b/trunk/arch/arm64/include/asm/arm_generic.h deleted file mode 100644 index e4cec9d30f27..000000000000 --- a/trunk/arch/arm64/include/asm/arm_generic.h +++ /dev/null @@ -1,100 +0,0 @@ -/* - * arch/arm64/include/asm/arm_generic.h - * - * Copyright (C) 2012 ARM Ltd. - * Author: Marc Zyngier - * - * 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 __ASM_ARM_GENERIC_H -#define __ASM_ARM_GENERIC_H - -#include - -#define ARCH_TIMER_CTRL_ENABLE (1 << 0) -#define ARCH_TIMER_CTRL_IMASK (1 << 1) -#define ARCH_TIMER_CTRL_ISTATUS (1 << 2) - -#define ARCH_TIMER_REG_CTRL 0 -#define ARCH_TIMER_REG_FREQ 1 -#define ARCH_TIMER_REG_TVAL 2 - -static inline void arch_timer_reg_write(int reg, u32 val) -{ - switch (reg) { - case ARCH_TIMER_REG_CTRL: - asm volatile("msr cntp_ctl_el0, %0" : : "r" (val)); - break; - case ARCH_TIMER_REG_TVAL: - asm volatile("msr cntp_tval_el0, %0" : : "r" (val)); - break; - default: - BUILD_BUG(); - } - - isb(); -} - -static inline u32 arch_timer_reg_read(int reg) -{ - u32 val; - - switch (reg) { - case ARCH_TIMER_REG_CTRL: - asm volatile("mrs %0, cntp_ctl_el0" : "=r" (val)); - break; - case ARCH_TIMER_REG_FREQ: - asm volatile("mrs %0, cntfrq_el0" : "=r" (val)); - break; - case ARCH_TIMER_REG_TVAL: - asm volatile("mrs %0, cntp_tval_el0" : "=r" (val)); - break; - default: - BUILD_BUG(); - } - - return val; -} - -static inline void __cpuinit arch_counter_enable_user_access(void) -{ - u32 cntkctl; - - /* Disable user access to the timers and the virtual counter. */ - asm volatile("mrs %0, cntkctl_el1" : "=r" (cntkctl)); - cntkctl &= ~((3 << 8) | (1 << 1)); - - /* Enable user access to the physical counter and frequency. */ - cntkctl |= 1; - asm volatile("msr cntkctl_el1, %0" : : "r" (cntkctl)); -} - -static inline cycle_t arch_counter_get_cntpct(void) -{ - cycle_t cval; - - asm volatile("mrs %0, cntpct_el0" : "=r" (cval)); - - return cval; -} - -static inline cycle_t arch_counter_get_cntvct(void) -{ - cycle_t cval; - - asm volatile("mrs %0, cntvct_el0" : "=r" (cval)); - - return cval; -} - -#endif diff --git a/trunk/arch/arm64/include/asm/asm-offsets.h b/trunk/arch/arm64/include/asm/asm-offsets.h deleted file mode 100644 index d370ee36a182..000000000000 --- a/trunk/arch/arm64/include/asm/asm-offsets.h +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/trunk/arch/arm64/include/asm/assembler.h b/trunk/arch/arm64/include/asm/assembler.h deleted file mode 100644 index da2a13e8f1e6..000000000000 --- a/trunk/arch/arm64/include/asm/assembler.h +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Based on arch/arm/include/asm/assembler.h - * - * Copyright (C) 1996-2000 Russell King - * Copyright (C) 2012 ARM 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 __ASSEMBLY__ -#error "Only include this from assembly code" -#endif - -#include - -/* - * Stack pushing/popping (register pairs only). Equivalent to store decrement - * before, load increment after. - */ - .macro push, xreg1, xreg2 - stp \xreg1, \xreg2, [sp, #-16]! - .endm - - .macro pop, xreg1, xreg2 - ldp \xreg1, \xreg2, [sp], #16 - .endm - -/* - * Enable and disable interrupts. - */ - .macro disable_irq - msr daifset, #2 - .endm - - .macro enable_irq - msr daifclr, #2 - .endm - -/* - * Save/disable and restore interrupts. - */ - .macro save_and_disable_irqs, olddaif - mrs \olddaif, daif - disable_irq - .endm - - .macro restore_irqs, olddaif - msr daif, \olddaif - .endm - -/* - * Enable and disable debug exceptions. - */ - .macro disable_dbg - msr daifset, #8 - .endm - - .macro enable_dbg - msr daifclr, #8 - .endm - - .macro disable_step, tmp - mrs \tmp, mdscr_el1 - bic \tmp, \tmp, #1 - msr mdscr_el1, \tmp - .endm - - .macro enable_step, tmp - mrs \tmp, mdscr_el1 - orr \tmp, \tmp, #1 - msr mdscr_el1, \tmp - .endm - - .macro enable_dbg_if_not_stepping, tmp - mrs \tmp, mdscr_el1 - tbnz \tmp, #1, 9990f - enable_dbg -9990: - .endm - -/* - * SMP data memory barrier - */ - .macro smp_dmb, opt -#ifdef CONFIG_SMP - dmb \opt -#endif - .endm - -#define USER(l, x...) \ -9999: x; \ - .section __ex_table,"a"; \ - .align 3; \ - .quad 9999b,l; \ - .previous - -/* - * Register aliases. - */ -lr .req x30 // link register diff --git a/trunk/arch/arm64/include/asm/atomic.h b/trunk/arch/arm64/include/asm/atomic.h deleted file mode 100644 index 407717ba060e..000000000000 --- a/trunk/arch/arm64/include/asm/atomic.h +++ /dev/null @@ -1,305 +0,0 @@ -/* - * Based on arch/arm/include/asm/atomic.h - * - * Copyright (C) 1996 Russell King. - * Copyright (C) 2002 Deep Blue Solutions Ltd. - * Copyright (C) 2012 ARM 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 __ASM_ATOMIC_H -#define __ASM_ATOMIC_H - -#include -#include - -#include -#include - -#define ATOMIC_INIT(i) { (i) } - -#ifdef __KERNEL__ - -/* - * On ARM, ordinary assignment (str instruction) doesn't clear the local - * strex/ldrex monitor on some implementations. The reason we can use it for - * atomic_set() is the clrex or dummy strex done on every exception return. - */ -#define atomic_read(v) (*(volatile int *)&(v)->counter) -#define atomic_set(v,i) (((v)->counter) = (i)) - -/* - * AArch64 UP and SMP safe atomic ops. We use load exclusive and - * store exclusive to ensure that these are atomic. We may loop - * to ensure that the update happens. - */ -static inline void atomic_add(int i, atomic_t *v) -{ - unsigned long tmp; - int result; - - asm volatile("// atomic_add\n" -"1: ldxr %w0, [%3]\n" -" add %w0, %w0, %w4\n" -" stxr %w1, %w0, [%3]\n" -" cbnz %w1, 1b" - : "=&r" (result), "=&r" (tmp), "+o" (v->counter) - : "r" (&v->counter), "Ir" (i) - : "cc"); -} - -static inline int atomic_add_return(int i, atomic_t *v) -{ - unsigned long tmp; - int result; - - asm volatile("// atomic_add_return\n" -"1: ldaxr %w0, [%3]\n" -" add %w0, %w0, %w4\n" -" stlxr %w1, %w0, [%3]\n" -" cbnz %w1, 1b" - : "=&r" (result), "=&r" (tmp), "+o" (v->counter) - : "r" (&v->counter), "Ir" (i) - : "cc"); - - return result; -} - -static inline void atomic_sub(int i, atomic_t *v) -{ - unsigned long tmp; - int result; - - asm volatile("// atomic_sub\n" -"1: ldxr %w0, [%3]\n" -" sub %w0, %w0, %w4\n" -" stxr %w1, %w0, [%3]\n" -" cbnz %w1, 1b" - : "=&r" (result), "=&r" (tmp), "+o" (v->counter) - : "r" (&v->counter), "Ir" (i) - : "cc"); -} - -static inline int atomic_sub_return(int i, atomic_t *v) -{ - unsigned long tmp; - int result; - - asm volatile("// atomic_sub_return\n" -"1: ldaxr %w0, [%3]\n" -" sub %w0, %w0, %w4\n" -" stlxr %w1, %w0, [%3]\n" -" cbnz %w1, 1b" - : "=&r" (result), "=&r" (tmp), "+o" (v->counter) - : "r" (&v->counter), "Ir" (i) - : "cc"); - - return result; -} - -static inline int atomic_cmpxchg(atomic_t *ptr, int old, int new) -{ - unsigned long tmp; - int oldval; - - asm volatile("// atomic_cmpxchg\n" -"1: ldaxr %w1, [%3]\n" -" cmp %w1, %w4\n" -" b.ne 2f\n" -" stlxr %w0, %w5, [%3]\n" -" cbnz %w0, 1b\n" -"2:" - : "=&r" (tmp), "=&r" (oldval), "+o" (ptr->counter) - : "r" (&ptr->counter), "Ir" (old), "r" (new) - : "cc"); - - return oldval; -} - -static inline void atomic_clear_mask(unsigned long mask, unsigned long *addr) -{ - unsigned long tmp, tmp2; - - asm volatile("// atomic_clear_mask\n" -"1: ldxr %0, [%3]\n" -" bic %0, %0, %4\n" -" stxr %w1, %0, [%3]\n" -" cbnz %w1, 1b" - : "=&r" (tmp), "=&r" (tmp2), "+o" (*addr) - : "r" (addr), "Ir" (mask) - : "cc"); -} - -#define atomic_xchg(v, new) (xchg(&((v)->counter), new)) - -static inline int __atomic_add_unless(atomic_t *v, int a, int u) -{ - int c, old; - - c = atomic_read(v); - while (c != u && (old = atomic_cmpxchg((v), c, c + a)) != c) - c = old; - return c; -} - -#define atomic_inc(v) atomic_add(1, v) -#define atomic_dec(v) atomic_sub(1, v) - -#define atomic_inc_and_test(v) (atomic_add_return(1, v) == 0) -#define atomic_dec_and_test(v) (atomic_sub_return(1, v) == 0) -#define atomic_inc_return(v) (atomic_add_return(1, v)) -#define atomic_dec_return(v) (atomic_sub_return(1, v)) -#define atomic_sub_and_test(i, v) (atomic_sub_return(i, v) == 0) - -#define atomic_add_negative(i,v) (atomic_add_return(i, v) < 0) - -#define smp_mb__before_atomic_dec() smp_mb() -#define smp_mb__after_atomic_dec() smp_mb() -#define smp_mb__before_atomic_inc() smp_mb() -#define smp_mb__after_atomic_inc() smp_mb() - -/* - * 64-bit atomic operations. - */ -#define ATOMIC64_INIT(i) { (i) } - -#define atomic64_read(v) (*(volatile long long *)&(v)->counter) -#define atomic64_set(v,i) (((v)->counter) = (i)) - -static inline void atomic64_add(u64 i, atomic64_t *v) -{ - long result; - unsigned long tmp; - - asm volatile("// atomic64_add\n" -"1: ldxr %0, [%3]\n" -" add %0, %0, %4\n" -" stxr %w1, %0, [%3]\n" -" cbnz %w1, 1b" - : "=&r" (result), "=&r" (tmp), "+o" (v->counter) - : "r" (&v->counter), "Ir" (i) - : "cc"); -} - -static inline long atomic64_add_return(long i, atomic64_t *v) -{ - long result; - unsigned long tmp; - - asm volatile("// atomic64_add_return\n" -"1: ldaxr %0, [%3]\n" -" add %0, %0, %4\n" -" stlxr %w1, %0, [%3]\n" -" cbnz %w1, 1b" - : "=&r" (result), "=&r" (tmp), "+o" (v->counter) - : "r" (&v->counter), "Ir" (i) - : "cc"); - - return result; -} - -static inline void atomic64_sub(u64 i, atomic64_t *v) -{ - long result; - unsigned long tmp; - - asm volatile("// atomic64_sub\n" -"1: ldxr %0, [%3]\n" -" sub %0, %0, %4\n" -" stxr %w1, %0, [%3]\n" -" cbnz %w1, 1b" - : "=&r" (result), "=&r" (tmp), "+o" (v->counter) - : "r" (&v->counter), "Ir" (i) - : "cc"); -} - -static inline long atomic64_sub_return(long i, atomic64_t *v) -{ - long result; - unsigned long tmp; - - asm volatile("// atomic64_sub_return\n" -"1: ldaxr %0, [%3]\n" -" sub %0, %0, %4\n" -" stlxr %w1, %0, [%3]\n" -" cbnz %w1, 1b" - : "=&r" (result), "=&r" (tmp), "+o" (v->counter) - : "r" (&v->counter), "Ir" (i) - : "cc"); - - return result; -} - -static inline long atomic64_cmpxchg(atomic64_t *ptr, long old, long new) -{ - long oldval; - unsigned long res; - - asm volatile("// atomic64_cmpxchg\n" -"1: ldaxr %1, [%3]\n" -" cmp %1, %4\n" -" b.ne 2f\n" -" stlxr %w0, %5, [%3]\n" -" cbnz %w0, 1b\n" -"2:" - : "=&r" (res), "=&r" (oldval), "+o" (ptr->counter) - : "r" (&ptr->counter), "Ir" (old), "r" (new) - : "cc"); - - return oldval; -} - -#define atomic64_xchg(v, new) (xchg(&((v)->counter), new)) - -static inline long atomic64_dec_if_positive(atomic64_t *v) -{ - long result; - unsigned long tmp; - - asm volatile("// atomic64_dec_if_positive\n" -"1: ldaxr %0, [%3]\n" -" subs %0, %0, #1\n" -" b.mi 2f\n" -" stlxr %w1, %0, [%3]\n" -" cbnz %w1, 1b\n" -"2:" - : "=&r" (result), "=&r" (tmp), "+o" (v->counter) - : "r" (&v->counter) - : "cc"); - - return result; -} - -static inline int atomic64_add_unless(atomic64_t *v, long a, long u) -{ - long c, old; - - c = atomic64_read(v); - while (c != u && (old = atomic64_cmpxchg((v), c, c + a)) != c) - c = old; - - return c != u; -} - -#define atomic64_add_negative(a, v) (atomic64_add_return((a), (v)) < 0) -#define atomic64_inc(v) atomic64_add(1LL, (v)) -#define atomic64_inc_return(v) atomic64_add_return(1LL, (v)) -#define atomic64_inc_and_test(v) (atomic64_inc_return(v) == 0) -#define atomic64_sub_and_test(a, v) (atomic64_sub_return((a), (v)) == 0) -#define atomic64_dec(v) atomic64_sub(1LL, (v)) -#define atomic64_dec_return(v) atomic64_sub_return(1LL, (v)) -#define atomic64_dec_and_test(v) (atomic64_dec_return((v)) == 0) -#define atomic64_inc_not_zero(v) atomic64_add_unless((v), 1LL, 0LL) - -#endif -#endif diff --git a/trunk/arch/arm64/include/asm/auxvec.h b/trunk/arch/arm64/include/asm/auxvec.h deleted file mode 100644 index 22d6d8885854..000000000000 --- a/trunk/arch/arm64/include/asm/auxvec.h +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (C) 2012 ARM 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 __ASM_AUXVEC_H -#define __ASM_AUXVEC_H - -/* vDSO location */ -#define AT_SYSINFO_EHDR 33 - -#endif diff --git a/trunk/arch/arm64/include/asm/barrier.h b/trunk/arch/arm64/include/asm/barrier.h deleted file mode 100644 index d4a63338a53c..000000000000 --- a/trunk/arch/arm64/include/asm/barrier.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Based on arch/arm/include/asm/barrier.h - * - * Copyright (C) 2012 ARM 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 __ASM_BARRIER_H -#define __ASM_BARRIER_H - -#ifndef __ASSEMBLY__ - -#define sev() asm volatile("sev" : : : "memory") -#define wfe() asm volatile("wfe" : : : "memory") -#define wfi() asm volatile("wfi" : : : "memory") - -#define isb() asm volatile("isb" : : : "memory") -#define dsb() asm volatile("dsb sy" : : : "memory") - -#define mb() dsb() -#define rmb() asm volatile("dsb ld" : : : "memory") -#define wmb() asm volatile("dsb st" : : : "memory") - -#ifndef CONFIG_SMP -#define smp_mb() barrier() -#define smp_rmb() barrier() -#define smp_wmb() barrier() -#else -#define smp_mb() asm volatile("dmb ish" : : : "memory") -#define smp_rmb() asm volatile("dmb ishld" : : : "memory") -#define smp_wmb() asm volatile("dmb ishst" : : : "memory") -#endif - -#define read_barrier_depends() do { } while(0) -#define smp_read_barrier_depends() do { } while(0) - -#define set_mb(var, value) do { var = value; smp_mb(); } while (0) -#define nop() asm volatile("nop"); - -#endif /* __ASSEMBLY__ */ - -#endif /* __ASM_BARRIER_H */ diff --git a/trunk/arch/arm64/include/asm/bitops.h b/trunk/arch/arm64/include/asm/bitops.h deleted file mode 100644 index 5e693073b030..000000000000 --- a/trunk/arch/arm64/include/asm/bitops.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2012 ARM 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 __ASM_BITOPS_H -#define __ASM_BITOPS_H - -#include - -#include - -/* - * clear_bit may not imply a memory barrier - */ -#ifndef smp_mb__before_clear_bit -#define smp_mb__before_clear_bit() smp_mb() -#define smp_mb__after_clear_bit() smp_mb() -#endif - -#ifndef _LINUX_BITOPS_H -#error only can be included directly -#endif - -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include - -#endif /* __ASM_BITOPS_H */ diff --git a/trunk/arch/arm64/include/asm/bitsperlong.h b/trunk/arch/arm64/include/asm/bitsperlong.h deleted file mode 100644 index fce9c2924fa3..000000000000 --- a/trunk/arch/arm64/include/asm/bitsperlong.h +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (C) 2012 ARM 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 __ASM_BITSPERLONG_H -#define __ASM_BITSPERLONG_H - -#define __BITS_PER_LONG 64 - -#include - -#endif /* __ASM_BITSPERLONG_H */ diff --git a/trunk/arch/arm64/include/asm/byteorder.h b/trunk/arch/arm64/include/asm/byteorder.h deleted file mode 100644 index 2b92046aafc5..000000000000 --- a/trunk/arch/arm64/include/asm/byteorder.h +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (C) 2012 ARM 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 __ASM_BYTEORDER_H -#define __ASM_BYTEORDER_H - -#include - -#endif /* __ASM_BYTEORDER_H */ diff --git a/trunk/arch/arm64/include/asm/cache.h b/trunk/arch/arm64/include/asm/cache.h deleted file mode 100644 index 390308a67f0d..000000000000 --- a/trunk/arch/arm64/include/asm/cache.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (C) 2012 ARM 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 __ASM_CACHE_H -#define __ASM_CACHE_H - -#define L1_CACHE_SHIFT 6 -#define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT) - -/* - * Memory returned by kmalloc() may be used for DMA, so we must make - * sure that all such allocations are cache aligned. Otherwise, - * unrelated code may cause parts of the buffer to be read into the - * cache before the transfer is done, causing old data to be seen by - * the CPU. - */ -#define ARCH_DMA_MINALIGN L1_CACHE_BYTES -#define ARCH_SLAB_MINALIGN 8 - -#endif diff --git a/trunk/arch/arm64/include/asm/cacheflush.h b/trunk/arch/arm64/include/asm/cacheflush.h deleted file mode 100644 index aa3132ab7f29..000000000000 --- a/trunk/arch/arm64/include/asm/cacheflush.h +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Based on arch/arm/include/asm/cacheflush.h - * - * Copyright (C) 1999-2002 Russell King. - * Copyright (C) 2012 ARM 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 __ASM_CACHEFLUSH_H -#define __ASM_CACHEFLUSH_H - -#include - -/* - * This flag is used to indicate that the page pointed to by a pte is clean - * and does not require cleaning before returning it to the user. - */ -#define PG_dcache_clean PG_arch_1 - -/* - * MM Cache Management - * =================== - * - * The arch/arm64/mm/cache.S implements these methods. - * - * Start addresses are inclusive and end addresses are exclusive; start - * addresses should be rounded down, end addresses up. - * - * See Documentation/cachetlb.txt for more information. Please note that - * the implementation assumes non-aliasing VIPT D-cache and (aliasing) - * VIPT or ASID-tagged VIVT I-cache. - * - * flush_cache_all() - * - * Unconditionally clean and invalidate the entire cache. - * - * flush_cache_mm(mm) - * - * Clean and invalidate all user space cache entries - * before a change of page tables. - * - * flush_icache_range(start, end) - * - * Ensure coherency between the I-cache and the D-cache in the - * region described by start, end. - * - start - virtual start address - * - end - virtual end address - * - * __flush_cache_user_range(start, end) - * - * Ensure coherency between the I-cache and the D-cache in the - * region described by start, end. - * - start - virtual start address - * - end - virtual end address - * - * __flush_dcache_area(kaddr, size) - * - * Ensure that the data held in page is written back. - * - kaddr - page address - * - size - region size - */ -extern void flush_cache_all(void); -extern void flush_cache_mm(struct mm_struct *mm); -extern void flush_cache_range(struct vm_area_struct *vma, unsigned long start, unsigned long end); -extern void flush_cache_page(struct vm_area_struct *vma, unsigned long user_addr, unsigned long pfn); -extern void flush_icache_range(unsigned long start, unsigned long end); -extern void __flush_dcache_area(void *addr, size_t len); -extern void __flush_cache_user_range(unsigned long start, unsigned long end); - -/* - * Copy user data from/to a page which is mapped into a different - * processes address space. Really, we want to allow our "user - * space" model to handle this. - */ -extern void copy_to_user_page(struct vm_area_struct *, struct page *, - unsigned long, void *, const void *, unsigned long); -#define copy_from_user_page(vma, page, vaddr, dst, src, len) \ - do { \ - memcpy(dst, src, len); \ - } while (0) - -#define flush_cache_dup_mm(mm) flush_cache_mm(mm) - -/* - * flush_dcache_page is used when the kernel has written to the page - * cache page at virtual address page->virtual. - * - * If this page isn't mapped (ie, page_mapping == NULL), or it might - * have userspace mappings, then we _must_ always clean + invalidate - * the dcache entries associated with the kernel mapping. - * - * Otherwise we can defer the operation, and clean the cache when we are - * about to change to user space. This is the same method as used on SPARC64. - * See update_mmu_cache for the user space part. - */ -#define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 1 -extern void flush_dcache_page(struct page *); - -static inline void __flush_icache_all(void) -{ - asm("ic ialluis"); -} - -#define flush_dcache_mmap_lock(mapping) \ - spin_lock_irq(&(mapping)->tree_lock) -#define flush_dcache_mmap_unlock(mapping) \ - spin_unlock_irq(&(mapping)->tree_lock) - -#define flush_icache_user_range(vma,page,addr,len) \ - flush_dcache_page(page) - -/* - * We don't appear to need to do anything here. In fact, if we did, we'd - * duplicate cache flushing elsewhere performed by flush_dcache_page(). - */ -#define flush_icache_page(vma,page) do { } while (0) - -/* - * flush_cache_vmap() is used when creating mappings (eg, via vmap, - * vmalloc, ioremap etc) in kernel space for pages. On non-VIPT - * caches, since the direct-mappings of these pages may contain cached - * data, we need to do a full cache flush to ensure that writebacks - * don't corrupt data placed into these pages via the new mappings. - */ -static inline void flush_cache_vmap(unsigned long start, unsigned long end) -{ - /* - * set_pte_at() called from vmap_pte_range() does not - * have a DSB after cleaning the cache line. - */ - dsb(); -} - -static inline void flush_cache_vunmap(unsigned long start, unsigned long end) -{ -} - -#endif diff --git a/trunk/arch/arm64/include/asm/cachetype.h b/trunk/arch/arm64/include/asm/cachetype.h deleted file mode 100644 index 85f5f511352a..000000000000 --- a/trunk/arch/arm64/include/asm/cachetype.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (C) 2012 ARM 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 __ASM_CACHETYPE_H -#define __ASM_CACHETYPE_H - -#include - -#define CTR_L1IP_SHIFT 14 -#define CTR_L1IP_MASK 3 - -#define ICACHE_POLICY_RESERVED 0 -#define ICACHE_POLICY_AIVIVT 1 -#define ICACHE_POLICY_VIPT 2 -#define ICACHE_POLICY_PIPT 3 - -static inline u32 icache_policy(void) -{ - return (read_cpuid_cachetype() >> CTR_L1IP_SHIFT) & CTR_L1IP_MASK; -} - -/* - * Whilst the D-side always behaves as PIPT on AArch64, aliasing is - * permitted in the I-cache. - */ -static inline int icache_is_aliasing(void) -{ - return icache_policy() != ICACHE_POLICY_PIPT; -} - -static inline int icache_is_aivivt(void) -{ - return icache_policy() == ICACHE_POLICY_AIVIVT; -} - -#endif /* __ASM_CACHETYPE_H */ diff --git a/trunk/arch/arm64/include/asm/cmpxchg.h b/trunk/arch/arm64/include/asm/cmpxchg.h deleted file mode 100644 index e0e65b069d9e..000000000000 --- a/trunk/arch/arm64/include/asm/cmpxchg.h +++ /dev/null @@ -1,173 +0,0 @@ -/* - * Based on arch/arm/include/asm/cmpxchg.h - * - * Copyright (C) 2012 ARM 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 __ASM_CMPXCHG_H -#define __ASM_CMPXCHG_H - -#include - -#include - -static inline unsigned long __xchg(unsigned long x, volatile void *ptr, int size) -{ - unsigned long ret, tmp; - - switch (size) { - case 1: - asm volatile("// __xchg1\n" - "1: ldaxrb %w0, [%3]\n" - " stlxrb %w1, %w2, [%3]\n" - " cbnz %w1, 1b\n" - : "=&r" (ret), "=&r" (tmp) - : "r" (x), "r" (ptr) - : "memory", "cc"); - break; - case 2: - asm volatile("// __xchg2\n" - "1: ldaxrh %w0, [%3]\n" - " stlxrh %w1, %w2, [%3]\n" - " cbnz %w1, 1b\n" - : "=&r" (ret), "=&r" (tmp) - : "r" (x), "r" (ptr) - : "memory", "cc"); - break; - case 4: - asm volatile("// __xchg4\n" - "1: ldaxr %w0, [%3]\n" - " stlxr %w1, %w2, [%3]\n" - " cbnz %w1, 1b\n" - : "=&r" (ret), "=&r" (tmp) - : "r" (x), "r" (ptr) - : "memory", "cc"); - break; - case 8: - asm volatile("// __xchg8\n" - "1: ldaxr %0, [%3]\n" - " stlxr %w1, %2, [%3]\n" - " cbnz %w1, 1b\n" - : "=&r" (ret), "=&r" (tmp) - : "r" (x), "r" (ptr) - : "memory", "cc"); - break; - default: - BUILD_BUG(); - } - - return ret; -} - -#define xchg(ptr,x) \ - ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr)))) - -static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old, - unsigned long new, int size) -{ - unsigned long oldval = 0, res; - - switch (size) { - case 1: - do { - asm volatile("// __cmpxchg1\n" - " ldxrb %w1, [%2]\n" - " mov %w0, #0\n" - " cmp %w1, %w3\n" - " b.ne 1f\n" - " stxrb %w0, %w4, [%2]\n" - "1:\n" - : "=&r" (res), "=&r" (oldval) - : "r" (ptr), "Ir" (old), "r" (new) - : "cc"); - } while (res); - break; - - case 2: - do { - asm volatile("// __cmpxchg2\n" - " ldxrh %w1, [%2]\n" - " mov %w0, #0\n" - " cmp %w1, %w3\n" - " b.ne 1f\n" - " stxrh %w0, %w4, [%2]\n" - "1:\n" - : "=&r" (res), "=&r" (oldval) - : "r" (ptr), "Ir" (old), "r" (new) - : "memory", "cc"); - } while (res); - break; - - case 4: - do { - asm volatile("// __cmpxchg4\n" - " ldxr %w1, [%2]\n" - " mov %w0, #0\n" - " cmp %w1, %w3\n" - " b.ne 1f\n" - " stxr %w0, %w4, [%2]\n" - "1:\n" - : "=&r" (res), "=&r" (oldval) - : "r" (ptr), "Ir" (old), "r" (new) - : "cc"); - } while (res); - break; - - case 8: - do { - asm volatile("// __cmpxchg8\n" - " ldxr %1, [%2]\n" - " mov %w0, #0\n" - " cmp %1, %3\n" - " b.ne 1f\n" - " stxr %w0, %4, [%2]\n" - "1:\n" - : "=&r" (res), "=&r" (oldval) - : "r" (ptr), "Ir" (old), "r" (new) - : "cc"); - } while (res); - break; - - default: - BUILD_BUG(); - } - - return oldval; -} - -static inline unsigned long __cmpxchg_mb(volatile void *ptr, unsigned long old, - unsigned long new, int size) -{ - unsigned long ret; - - smp_mb(); - ret = __cmpxchg(ptr, old, new, size); - smp_mb(); - - return ret; -} - -#define cmpxchg(ptr,o,n) \ - ((__typeof__(*(ptr)))__cmpxchg_mb((ptr), \ - (unsigned long)(o), \ - (unsigned long)(n), \ - sizeof(*(ptr)))) - -#define cmpxchg_local(ptr,o,n) \ - ((__typeof__(*(ptr)))__cmpxchg((ptr), \ - (unsigned long)(o), \ - (unsigned long)(n), \ - sizeof(*(ptr)))) - -#endif /* __ASM_CMPXCHG_H */ diff --git a/trunk/arch/arm64/include/asm/compat.h b/trunk/arch/arm64/include/asm/compat.h deleted file mode 100644 index a670a33ad736..000000000000 --- a/trunk/arch/arm64/include/asm/compat.h +++ /dev/null @@ -1,242 +0,0 @@ -/* - * Copyright (C) 2012 ARM 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 __ASM_COMPAT_H -#define __ASM_COMPAT_H -#ifdef __KERNEL__ -#ifdef CONFIG_COMPAT - -/* - * Architecture specific compatibility types - */ -#include -#include - -#define COMPAT_USER_HZ 100 -#define COMPAT_UTS_MACHINE "armv8l\0\0" - -typedef u32 compat_size_t; -typedef s32 compat_ssize_t; -typedef s32 compat_time_t; -typedef s32 compat_clock_t; -typedef s32 compat_pid_t; -typedef u32 __compat_uid_t; -typedef u32 __compat_gid_t; -typedef u32 __compat_uid32_t; -typedef u32 __compat_gid32_t; -typedef u32 compat_mode_t; -typedef u32 compat_ino_t; -typedef u32 compat_dev_t; -typedef s32 compat_off_t; -typedef s64 compat_loff_t; -typedef s16 compat_nlink_t; -typedef u16 compat_ipc_pid_t; -typedef s32 compat_daddr_t; -typedef u32 compat_caddr_t; -typedef __kernel_fsid_t compat_fsid_t; -typedef s32 compat_key_t; -typedef s32 compat_timer_t; - -typedef s32 compat_int_t; -typedef s32 compat_long_t; -typedef s64 compat_s64; -typedef u32 compat_uint_t; -typedef u32 compat_ulong_t; -typedef u64 compat_u64; - -struct compat_timespec { - compat_time_t tv_sec; - s32 tv_nsec; -}; - -struct compat_timeval { - compat_time_t tv_sec; - s32 tv_usec; -}; - -struct compat_stat { - compat_dev_t st_dev; - compat_ino_t st_ino; - compat_mode_t st_mode; - compat_nlink_t st_nlink; - __compat_uid32_t st_uid; - __compat_gid32_t st_gid; - compat_dev_t st_rdev; - compat_off_t st_size; - compat_off_t st_blksize; - compat_off_t st_blocks; - compat_time_t st_atime; - u32 st_atime_nsec; - compat_time_t st_mtime; - u32 st_mtime_nsec; - compat_time_t st_ctime; - u32 st_ctime_nsec; - u32 __unused4[2]; -}; - -struct compat_flock { - short l_type; - short l_whence; - compat_off_t l_start; - compat_off_t l_len; - compat_pid_t l_pid; -}; - -#define F_GETLK64 12 /* using 'struct flock64' */ -#define F_SETLK64 13 -#define F_SETLKW64 14 - -struct compat_flock64 { - short l_type; - short l_whence; - compat_loff_t l_start; - compat_loff_t l_len; - compat_pid_t l_pid; -}; - -struct compat_statfs { - int f_type; - int f_bsize; - int f_blocks; - int f_bfree; - int f_bavail; - int f_files; - int f_ffree; - compat_fsid_t f_fsid; - int f_namelen; /* SunOS ignores this field. */ - int f_frsize; - int f_flags; - int f_spare[4]; -}; - -#define COMPAT_RLIM_INFINITY 0xffffffff - -typedef u32 compat_old_sigset_t; - -#define _COMPAT_NSIG 64 -#define _COMPAT_NSIG_BPW 32 - -typedef u32 compat_sigset_word; - -#define COMPAT_OFF_T_MAX 0x7fffffff -#define COMPAT_LOFF_T_MAX 0x7fffffffffffffffL - -/* - * A pointer passed in from user mode. This should not - * be used for syscall parameters, just declare them - * as pointers because the syscall entry code will have - * appropriately converted them already. - */ -typedef u32 compat_uptr_t; - -static inline void __user *compat_ptr(compat_uptr_t uptr) -{ - return (void __user *)(unsigned long)uptr; -} - -static inline compat_uptr_t ptr_to_compat(void __user *uptr) -{ - return (u32)(unsigned long)uptr; -} - -static inline void __user *arch_compat_alloc_user_space(long len) -{ - struct pt_regs *regs = task_pt_regs(current); - return (void __user *)regs->compat_sp - len; -} - -struct compat_ipc64_perm { - compat_key_t key; - __compat_uid32_t uid; - __compat_gid32_t gid; - __compat_uid32_t cuid; - __compat_gid32_t cgid; - unsigned short mode; - unsigned short __pad1; - unsigned short seq; - unsigned short __pad2; - compat_ulong_t unused1; - compat_ulong_t unused2; -}; - -struct compat_semid64_ds { - struct compat_ipc64_perm sem_perm; - compat_time_t sem_otime; - compat_ulong_t __unused1; - compat_time_t sem_ctime; - compat_ulong_t __unused2; - compat_ulong_t sem_nsems; - compat_ulong_t __unused3; - compat_ulong_t __unused4; -}; - -struct compat_msqid64_ds { - struct compat_ipc64_perm msg_perm; - compat_time_t msg_stime; - compat_ulong_t __unused1; - compat_time_t msg_rtime; - compat_ulong_t __unused2; - compat_time_t msg_ctime; - compat_ulong_t __unused3; - compat_ulong_t msg_cbytes; - compat_ulong_t msg_qnum; - compat_ulong_t msg_qbytes; - compat_pid_t msg_lspid; - compat_pid_t msg_lrpid; - compat_ulong_t __unused4; - compat_ulong_t __unused5; -}; - -struct compat_shmid64_ds { - struct compat_ipc64_perm shm_perm; - compat_size_t shm_segsz; - compat_time_t shm_atime; - compat_ulong_t __unused1; - compat_time_t shm_dtime; - compat_ulong_t __unused2; - compat_time_t shm_ctime; - compat_ulong_t __unused3; - compat_pid_t shm_cpid; - compat_pid_t shm_lpid; - compat_ulong_t shm_nattch; - compat_ulong_t __unused4; - compat_ulong_t __unused5; -}; - -static inline int is_compat_task(void) -{ - return test_thread_flag(TIF_32BIT); -} - -static inline int is_compat_thread(struct thread_info *thread) -{ - return test_ti_thread_flag(thread, TIF_32BIT); -} - -#else /* !CONFIG_COMPAT */ - -static inline int is_compat_task(void) -{ - return 0; -} - -static inline int is_compat_thread(struct thread_info *thread) -{ - return 0; -} - -#endif /* CONFIG_COMPAT */ -#endif /* __KERNEL__ */ -#endif /* __ASM_COMPAT_H */ diff --git a/trunk/arch/arm64/include/asm/compiler.h b/trunk/arch/arm64/include/asm/compiler.h deleted file mode 100644 index ee35fd0f2236..000000000000 --- a/trunk/arch/arm64/include/asm/compiler.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Based on arch/arm/include/asm/compiler.h - * - * Copyright (C) 2012 ARM 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 __ASM_COMPILER_H -#define __ASM_COMPILER_H - -/* - * This is used to ensure the compiler did actually allocate the register we - * asked it for some inline assembly sequences. Apparently we can't trust the - * compiler from one version to another so a bit of paranoia won't hurt. This - * string is meant to be concatenated with the inline asm string and will - * cause compilation to stop on mismatch. (for details, see gcc PR 15089) - */ -#define __asmeq(x, y) ".ifnc " x "," y " ; .err ; .endif\n\t" - -#endif /* __ASM_COMPILER_H */ diff --git a/trunk/arch/arm64/include/asm/cputable.h b/trunk/arch/arm64/include/asm/cputable.h deleted file mode 100644 index e3bd983d3661..000000000000 --- a/trunk/arch/arm64/include/asm/cputable.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * arch/arm64/include/asm/cputable.h - * - * Copyright (C) 2012 ARM 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 __ASM_CPUTABLE_H -#define __ASM_CPUTABLE_H - -struct cpu_info { - unsigned int cpu_id_val; - unsigned int cpu_id_mask; - const char *cpu_name; - unsigned long (*cpu_setup)(void); -}; - -extern struct cpu_info *lookup_processor_type(unsigned int); - -#endif diff --git a/trunk/arch/arm64/include/asm/cputype.h b/trunk/arch/arm64/include/asm/cputype.h deleted file mode 100644 index ef54125e6c1e..000000000000 --- a/trunk/arch/arm64/include/asm/cputype.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (C) 2012 ARM 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 __ASM_CPUTYPE_H -#define __ASM_CPUTYPE_H - -#define ID_MIDR_EL1 "midr_el1" -#define ID_CTR_EL0 "ctr_el0" - -#define ID_AA64PFR0_EL1 "id_aa64pfr0_el1" -#define ID_AA64DFR0_EL1 "id_aa64dfr0_el1" -#define ID_AA64AFR0_EL1 "id_aa64afr0_el1" -#define ID_AA64ISAR0_EL1 "id_aa64isar0_el1" -#define ID_AA64MMFR0_EL1 "id_aa64mmfr0_el1" - -#define read_cpuid(reg) ({ \ - u64 __val; \ - asm("mrs %0, " reg : "=r" (__val)); \ - __val; \ -}) - -/* - * The CPU ID never changes at run time, so we might as well tell the - * compiler that it's constant. Use this function to read the CPU ID - * rather than directly reading processor_id or read_cpuid() directly. - */ -static inline u32 __attribute_const__ read_cpuid_id(void) -{ - return read_cpuid(ID_MIDR_EL1); -} - -static inline u32 __attribute_const__ read_cpuid_cachetype(void) -{ - return read_cpuid(ID_CTR_EL0); -} - -#endif diff --git a/trunk/arch/arm64/include/asm/debug-monitors.h b/trunk/arch/arm64/include/asm/debug-monitors.h deleted file mode 100644 index 7eaa0b302493..000000000000 --- a/trunk/arch/arm64/include/asm/debug-monitors.h +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (C) 2012 ARM 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 __ASM_DEBUG_MONITORS_H -#define __ASM_DEBUG_MONITORS_H - -#ifdef __KERNEL__ - -#define DBG_ESR_EVT(x) (((x) >> 27) & 0x7) - -/* AArch64 */ -#define DBG_ESR_EVT_HWBP 0x0 -#define DBG_ESR_EVT_HWSS 0x1 -#define DBG_ESR_EVT_HWWP 0x2 -#define DBG_ESR_EVT_BRK 0x6 - -enum debug_el { - DBG_ACTIVE_EL0 = 0, - DBG_ACTIVE_EL1, -}; - -/* AArch32 */ -#define DBG_ESR_EVT_BKPT 0x4 -#define DBG_ESR_EVT_VECC 0x5 - -#define AARCH32_BREAK_ARM 0x07f001f0 -#define AARCH32_BREAK_THUMB 0xde01 -#define AARCH32_BREAK_THUMB2_LO 0xf7f0 -#define AARCH32_BREAK_THUMB2_HI 0xa000 - -#ifndef __ASSEMBLY__ -struct task_struct; - -#define local_dbg_save(flags) \ - do { \ - typecheck(unsigned long, flags); \ - asm volatile( \ - "mrs %0, daif // local_dbg_save\n" \ - "msr daifset, #8" \ - : "=r" (flags) : : "memory"); \ - } while (0) - -#define local_dbg_restore(flags) \ - do { \ - typecheck(unsigned long, flags); \ - asm volatile( \ - "msr daif, %0 // local_dbg_restore\n" \ - : : "r" (flags) : "memory"); \ - } while (0) - -#define DBG_ARCH_ID_RESERVED 0 /* In case of ptrace ABI updates. */ - -u8 debug_monitors_arch(void); - -void enable_debug_monitors(enum debug_el el); -void disable_debug_monitors(enum debug_el el); - -void user_rewind_single_step(struct task_struct *task); -void user_fastforward_single_step(struct task_struct *task); - -void kernel_enable_single_step(struct pt_regs *regs); -void kernel_disable_single_step(void); -int kernel_active_single_step(void); - -#ifdef CONFIG_HAVE_HW_BREAKPOINT -int reinstall_suspended_bps(struct pt_regs *regs); -#else -static inline int reinstall_suspended_bps(struct pt_regs *regs) -{ - return -ENODEV; -} -#endif - -#endif /* __ASSEMBLY */ -#endif /* __KERNEL__ */ -#endif /* __ASM_DEBUG_MONITORS_H */ diff --git a/trunk/arch/arm64/include/asm/device.h b/trunk/arch/arm64/include/asm/device.h deleted file mode 100644 index 0d8453c755a8..000000000000 --- a/trunk/arch/arm64/include/asm/device.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (C) 2012 ARM 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 __ASM_DEVICE_H -#define __ASM_DEVICE_H - -struct dev_archdata { - struct dma_map_ops *dma_ops; -}; - -struct pdev_archdata { -}; - -#endif diff --git a/trunk/arch/arm64/include/asm/dma-mapping.h b/trunk/arch/arm64/include/asm/dma-mapping.h deleted file mode 100644 index 538f4b44db5d..000000000000 --- a/trunk/arch/arm64/include/asm/dma-mapping.h +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright (C) 2012 ARM 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 __ASM_DMA_MAPPING_H -#define __ASM_DMA_MAPPING_H - -#ifdef __KERNEL__ - -#include -#include - -#include - -#define ARCH_HAS_DMA_GET_REQUIRED_MASK - -extern struct dma_map_ops *dma_ops; - -static inline struct dma_map_ops *get_dma_ops(struct device *dev) -{ - if (unlikely(!dev) || !dev->archdata.dma_ops) - return dma_ops; - else - return dev->archdata.dma_ops; -} - -#include - -static inline dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr) -{ - return (dma_addr_t)paddr; -} - -static inline phys_addr_t dma_to_phys(struct device *dev, dma_addr_t dev_addr) -{ - return (phys_addr_t)dev_addr; -} - -static inline int dma_mapping_error(struct device *dev, dma_addr_t dev_addr) -{ - struct dma_map_ops *ops = get_dma_ops(dev); - return ops->mapping_error(dev, dev_addr); -} - -static inline int dma_supported(struct device *dev, u64 mask) -{ - struct dma_map_ops *ops = get_dma_ops(dev); - return ops->dma_supported(dev, mask); -} - -static inline int dma_set_mask(struct device *dev, u64 mask) -{ - if (!dev->dma_mask || !dma_supported(dev, mask)) - return -EIO; - *dev->dma_mask = mask; - - return 0; -} - -static inline bool dma_capable(struct device *dev, dma_addr_t addr, size_t size) -{ - if (!dev->dma_mask) - return 0; - - return addr + size - 1 <= *dev->dma_mask; -} - -static inline void dma_mark_clean(void *addr, size_t size) -{ -} - -static inline void *dma_alloc_coherent(struct device *dev, size_t size, - dma_addr_t *dma_handle, gfp_t flags) -{ - struct dma_map_ops *ops = get_dma_ops(dev); - void *vaddr; - - if (dma_alloc_from_coherent(dev, size, dma_handle, &vaddr)) - return vaddr; - - vaddr = ops->alloc(dev, size, dma_handle, flags, NULL); - debug_dma_alloc_coherent(dev, size, *dma_handle, vaddr); - return vaddr; -} - -static inline void dma_free_coherent(struct device *dev, size_t size, - void *vaddr, dma_addr_t dev_addr) -{ - struct dma_map_ops *ops = get_dma_ops(dev); - - if (dma_release_from_coherent(dev, get_order(size), vaddr)) - return; - - debug_dma_free_coherent(dev, size, vaddr, dev_addr); - ops->free(dev, size, vaddr, dev_addr, NULL); -} - -/* - * There is no dma_cache_sync() implementation, so just return NULL here. - */ -static inline void *dma_alloc_noncoherent(struct device *dev, size_t size, - dma_addr_t *handle, gfp_t flags) -{ - return NULL; -} - -static inline void dma_free_noncoherent(struct device *dev, size_t size, - void *cpu_addr, dma_addr_t handle) -{ -} - -#endif /* __KERNEL__ */ -#endif /* __ASM_DMA_MAPPING_H */ diff --git a/trunk/arch/arm64/include/asm/elf.h b/trunk/arch/arm64/include/asm/elf.h deleted file mode 100644 index cf284649dfcb..000000000000 --- a/trunk/arch/arm64/include/asm/elf.h +++ /dev/null @@ -1,179 +0,0 @@ -/* - * Copyright (C) 2012 ARM 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 __ASM_ELF_H -#define __ASM_ELF_H - -#include - -/* - * ELF register definitions.. - */ -#include -#include - -typedef unsigned long elf_greg_t; -typedef unsigned long elf_freg_t[3]; - -#define ELF_NGREG (sizeof (struct pt_regs) / sizeof(elf_greg_t)) -typedef elf_greg_t elf_gregset_t[ELF_NGREG]; - -typedef struct user_fp elf_fpregset_t; - -#define EM_AARCH64 183 - -/* - * AArch64 static relocation types. - */ - -/* Miscellaneous. */ -#define R_ARM_NONE 0 -#define R_AARCH64_NONE 256 - -/* Data. */ -#define R_AARCH64_ABS64 257 -#define R_AARCH64_ABS32 258 -#define R_AARCH64_ABS16 259 -#define R_AARCH64_PREL64 260 -#define R_AARCH64_PREL32 261 -#define R_AARCH64_PREL16 262 - -/* Instructions. */ -#define R_AARCH64_MOVW_UABS_G0 263 -#define R_AARCH64_MOVW_UABS_G0_NC 264 -#define R_AARCH64_MOVW_UABS_G1 265 -#define R_AARCH64_MOVW_UABS_G1_NC 266 -#define R_AARCH64_MOVW_UABS_G2 267 -#define R_AARCH64_MOVW_UABS_G2_NC 268 -#define R_AARCH64_MOVW_UABS_G3 269 - -#define R_AARCH64_MOVW_SABS_G0 270 -#define R_AARCH64_MOVW_SABS_G1 271 -#define R_AARCH64_MOVW_SABS_G2 272 - -#define R_AARCH64_LD_PREL_LO19 273 -#define R_AARCH64_ADR_PREL_LO21 274 -#define R_AARCH64_ADR_PREL_PG_HI21 275 -#define R_AARCH64_ADR_PREL_PG_HI21_NC 276 -#define R_AARCH64_ADD_ABS_LO12_NC 277 -#define R_AARCH64_LDST8_ABS_LO12_NC 278 - -#define R_AARCH64_TSTBR14 279 -#define R_AARCH64_CONDBR19 280 -#define R_AARCH64_JUMP26 282 -#define R_AARCH64_CALL26 283 -#define R_AARCH64_LDST16_ABS_LO12_NC 284 -#define R_AARCH64_LDST32_ABS_LO12_NC 285 -#define R_AARCH64_LDST64_ABS_LO12_NC 286 -#define R_AARCH64_LDST128_ABS_LO12_NC 299 - -#define R_AARCH64_MOVW_PREL_G0 287 -#define R_AARCH64_MOVW_PREL_G0_NC 288 -#define R_AARCH64_MOVW_PREL_G1 289 -#define R_AARCH64_MOVW_PREL_G1_NC 290 -#define R_AARCH64_MOVW_PREL_G2 291 -#define R_AARCH64_MOVW_PREL_G2_NC 292 -#define R_AARCH64_MOVW_PREL_G3 293 - - -/* - * These are used to set parameters in the core dumps. - */ -#define ELF_CLASS ELFCLASS64 -#define ELF_DATA ELFDATA2LSB -#define ELF_ARCH EM_AARCH64 - -#define ELF_PLATFORM_SIZE 16 -#define ELF_PLATFORM ("aarch64") - -/* - * This is used to ensure we don't load something for the wrong architecture. - */ -#define elf_check_arch(x) ((x)->e_machine == EM_AARCH64) - -#define elf_read_implies_exec(ex,stk) (stk != EXSTACK_DISABLE_X) - -#define CORE_DUMP_USE_REGSET -#define ELF_EXEC_PAGESIZE PAGE_SIZE - -/* - * This is the location that an ET_DYN program is loaded if exec'ed. Typical - * use of this is to invoke "./ld.so someprog" to test out a new version of - * the loader. We need to make sure that it is out of the way of the program - * that it will "exec", and that there is sufficient room for the brk. - */ -extern unsigned long randomize_et_dyn(unsigned long base); -#define ELF_ET_DYN_BASE (randomize_et_dyn(2 * TASK_SIZE_64 / 3)) - -/* - * When the program starts, a1 contains a pointer to a function to be - * registered with atexit, as per the SVR4 ABI. A value of 0 means we have no - * such handler. - */ -#define ELF_PLAT_INIT(_r, load_addr) (_r)->regs[0] = 0 - -#define SET_PERSONALITY(ex) clear_thread_flag(TIF_32BIT); - -#define ARCH_DLINFO \ -do { \ - NEW_AUX_ENT(AT_SYSINFO_EHDR, \ - (elf_addr_t)current->mm->context.vdso); \ -} while (0) - -#define ARCH_HAS_SETUP_ADDITIONAL_PAGES -struct linux_binprm; -extern int arch_setup_additional_pages(struct linux_binprm *bprm, - int uses_interp); - -/* 1GB of VA */ -#ifdef CONFIG_COMPAT -#define STACK_RND_MASK (test_thread_flag(TIF_32BIT) ? \ - 0x7ff >> (PAGE_SHIFT - 12) : \ - 0x3ffff >> (PAGE_SHIFT - 12)) -#else -#define STACK_RND_MASK (0x3ffff >> (PAGE_SHIFT - 12)) -#endif - -struct mm_struct; -extern unsigned long arch_randomize_brk(struct mm_struct *mm); -#define arch_randomize_brk arch_randomize_brk - -#ifdef CONFIG_COMPAT -#define EM_ARM 40 -#define COMPAT_ELF_PLATFORM ("v8l") - -#define COMPAT_ELF_ET_DYN_BASE (randomize_et_dyn(2 * TASK_SIZE_32 / 3)) - -/* AArch32 registers. */ -#define COMPAT_ELF_NGREG 18 -typedef unsigned int compat_elf_greg_t; -typedef compat_elf_greg_t compat_elf_gregset_t[COMPAT_ELF_NGREG]; - -/* AArch32 EABI. */ -#define EF_ARM_EABI_MASK 0xff000000 -#define compat_elf_check_arch(x) (((x)->e_machine == EM_ARM) && \ - ((x)->e_flags & EF_ARM_EABI_MASK)) - -#define compat_start_thread compat_start_thread -#define COMPAT_SET_PERSONALITY(ex) set_thread_flag(TIF_32BIT); -#define COMPAT_ARCH_DLINFO -extern int aarch32_setup_vectors_page(struct linux_binprm *bprm, - int uses_interp); -#define compat_arch_setup_additional_pages \ - aarch32_setup_vectors_page - -#endif /* CONFIG_COMPAT */ - -#endif diff --git a/trunk/arch/arm64/include/asm/exception.h b/trunk/arch/arm64/include/asm/exception.h deleted file mode 100644 index ac63519b7b90..000000000000 --- a/trunk/arch/arm64/include/asm/exception.h +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Based on arch/arm/include/asm/exception.h - * - * Copyright (C) 2012 ARM 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 __ASM_EXCEPTION_H -#define __ASM_EXCEPTION_H - -#define __exception __attribute__((section(".exception.text"))) - -#endif /* __ASM_EXCEPTION_H */ diff --git a/trunk/arch/arm64/include/asm/exec.h b/trunk/arch/arm64/include/asm/exec.h deleted file mode 100644 index db0563c23482..000000000000 --- a/trunk/arch/arm64/include/asm/exec.h +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Based on arch/arm/include/asm/exec.h - * - * Copyright (C) 2012 ARM 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 __ASM_EXEC_H -#define __ASM_EXEC_H - -extern unsigned long arch_align_stack(unsigned long sp); - -#endif /* __ASM_EXEC_H */ diff --git a/trunk/arch/arm64/include/asm/fb.h b/trunk/arch/arm64/include/asm/fb.h deleted file mode 100644 index adb88a64b2fe..000000000000 --- a/trunk/arch/arm64/include/asm/fb.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (C) 2012 ARM 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 __ASM_FB_H_ -#define __ASM_FB_H_ - -#include -#include -#include - -static inline void fb_pgprotect(struct file *file, struct vm_area_struct *vma, - unsigned long off) -{ - vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); -} - -static inline int fb_is_primary_device(struct fb_info *info) -{ - return 0; -} - -#endif /* __ASM_FB_H_ */ diff --git a/trunk/arch/arm64/include/asm/fcntl.h b/trunk/arch/arm64/include/asm/fcntl.h deleted file mode 100644 index cd2e630c235e..000000000000 --- a/trunk/arch/arm64/include/asm/fcntl.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (C) 2012 ARM 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 __ASM_FCNTL_H -#define __ASM_FCNTL_H - -/* - * Using our own definitions for AArch32 (compat) support. - */ -#define O_DIRECTORY 040000 /* must be a directory */ -#define O_NOFOLLOW 0100000 /* don't follow links */ -#define O_DIRECT 0200000 /* direct disk access hint - currently ignored */ -#define O_LARGEFILE 0400000 - -#include - -#endif diff --git a/trunk/arch/arm64/include/asm/fpsimd.h b/trunk/arch/arm64/include/asm/fpsimd.h deleted file mode 100644 index b42fab9f62a9..000000000000 --- a/trunk/arch/arm64/include/asm/fpsimd.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (C) 2012 ARM 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 __ASM_FP_H -#define __ASM_FP_H - -#include - -#ifndef __ASSEMBLY__ - -/* - * FP/SIMD storage area has: - * - FPSR and FPCR - * - 32 128-bit data registers - * - * Note that user_fp forms a prefix of this structure, which is relied - * upon in the ptrace FP/SIMD accessors. struct user_fpsimd_state must - * form a prefix of struct fpsimd_state. - */ -struct fpsimd_state { - union { - struct user_fpsimd_state user_fpsimd; - struct { - __uint128_t vregs[32]; - u32 fpsr; - u32 fpcr; - }; - }; -}; - -#if defined(__KERNEL__) && defined(CONFIG_COMPAT) -/* Masks for extracting the FPSR and FPCR from the FPSCR */ -#define VFP_FPSCR_STAT_MASK 0xf800009f -#define VFP_FPSCR_CTRL_MASK 0x07f79f00 -/* - * The VFP state has 32x64-bit registers and a single 32-bit - * control/status register. - */ -#define VFP_STATE_SIZE ((32 * 8) + 4) -#endif - -struct task_struct; - -extern void fpsimd_save_state(struct fpsimd_state *state); -extern void fpsimd_load_state(struct fpsimd_state *state); - -extern void fpsimd_thread_switch(struct task_struct *next); -extern void fpsimd_flush_thread(void); - -#endif - -#endif diff --git a/trunk/arch/arm64/include/asm/futex.h b/trunk/arch/arm64/include/asm/futex.h deleted file mode 100644 index 3468ae8439fa..000000000000 --- a/trunk/arch/arm64/include/asm/futex.h +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Copyright (C) 2012 ARM 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 __ASM_FUTEX_H -#define __ASM_FUTEX_H - -#ifdef __KERNEL__ - -#include -#include -#include - -#define __futex_atomic_op(insn, ret, oldval, uaddr, tmp, oparg) \ - asm volatile( \ -"1: ldaxr %w1, %2\n" \ - insn "\n" \ -"2: stlxr %w3, %w0, %2\n" \ -" cbnz %w3, 1b\n" \ -"3:\n" \ -" .pushsection .fixup,\"ax\"\n" \ -"4: mov %w0, %w5\n" \ -" b 3b\n" \ -" .popsection\n" \ -" .pushsection __ex_table,\"a\"\n" \ -" .align 3\n" \ -" .quad 1b, 4b, 2b, 4b\n" \ -" .popsection\n" \ - : "=&r" (ret), "=&r" (oldval), "+Q" (*uaddr), "=&r" (tmp) \ - : "r" (oparg), "Ir" (-EFAULT) \ - : "cc") - -static inline int -futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr) -{ - int op = (encoded_op >> 28) & 7; - int cmp = (encoded_op >> 24) & 15; - int oparg = (encoded_op << 8) >> 20; - int cmparg = (encoded_op << 20) >> 20; - int oldval = 0, ret, tmp; - - if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) - oparg = 1 << oparg; - - if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))) - return -EFAULT; - - pagefault_disable(); /* implies preempt_disable() */ - - switch (op) { - case FUTEX_OP_SET: - __futex_atomic_op("mov %w0, %w4", - ret, oldval, uaddr, tmp, oparg); - break; - case FUTEX_OP_ADD: - __futex_atomic_op("add %w0, %w1, %w4", - ret, oldval, uaddr, tmp, oparg); - break; - case FUTEX_OP_OR: - __futex_atomic_op("orr %w0, %w1, %w4", - ret, oldval, uaddr, tmp, oparg); - break; - case FUTEX_OP_ANDN: - __futex_atomic_op("and %w0, %w1, %w4", - ret, oldval, uaddr, tmp, ~oparg); - break; - case FUTEX_OP_XOR: - __futex_atomic_op("eor %w0, %w1, %w4", - ret, oldval, uaddr, tmp, oparg); - break; - default: - ret = -ENOSYS; - } - - pagefault_enable(); /* subsumes preempt_enable() */ - - if (!ret) { - switch (cmp) { - case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break; - case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break; - case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break; - case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break; - case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break; - case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break; - default: ret = -ENOSYS; - } - } - return ret; -} - -static inline int -futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, - u32 oldval, u32 newval) -{ - int ret = 0; - u32 val, tmp; - - if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))) - return -EFAULT; - - asm volatile("// futex_atomic_cmpxchg_inatomic\n" -"1: ldaxr %w1, %2\n" -" sub %w3, %w1, %w4\n" -" cbnz %w3, 3f\n" -"2: stlxr %w3, %w5, %2\n" -" cbnz %w3, 1b\n" -"3:\n" -" .pushsection .fixup,\"ax\"\n" -"4: mov %w0, %w6\n" -" b 3b\n" -" .popsection\n" -" .pushsection __ex_table,\"a\"\n" -" .align 3\n" -" .quad 1b, 4b, 2b, 4b\n" -" .popsection\n" - : "+r" (ret), "=&r" (val), "+Q" (*uaddr), "=&r" (tmp) - : "r" (oldval), "r" (newval), "Ir" (-EFAULT) - : "cc", "memory"); - - *uval = val; - return ret; -} - -#endif /* __KERNEL__ */ -#endif /* __ASM_FUTEX_H */ diff --git a/trunk/arch/arm64/include/asm/hardirq.h b/trunk/arch/arm64/include/asm/hardirq.h deleted file mode 100644 index 507546353d62..000000000000 --- a/trunk/arch/arm64/include/asm/hardirq.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (C) 2012 ARM 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 __ASM_HARDIRQ_H -#define __ASM_HARDIRQ_H - -#include -#include -#include - -#define NR_IPI 4 - -typedef struct { - unsigned int __softirq_pending; -#ifdef CONFIG_SMP - unsigned int ipi_irqs[NR_IPI]; -#endif -} ____cacheline_aligned irq_cpustat_t; - -#include /* Standard mappings for irq_cpustat_t above */ - -#define __inc_irq_stat(cpu, member) __IRQ_STAT(cpu, member)++ -#define __get_irq_stat(cpu, member) __IRQ_STAT(cpu, member) - -#ifdef CONFIG_SMP -u64 smp_irq_stat_cpu(unsigned int cpu); -#define arch_irq_stat_cpu smp_irq_stat_cpu -#endif - -#define __ARCH_IRQ_EXIT_IRQS_DISABLED 1 - -static inline void ack_bad_irq(unsigned int irq) -{ - extern unsigned long irq_err_count; - irq_err_count++; -} - -extern void handle_IRQ(unsigned int, struct pt_regs *); - -#endif /* __ASM_HARDIRQ_H */ diff --git a/trunk/arch/arm64/include/asm/hw_breakpoint.h b/trunk/arch/arm64/include/asm/hw_breakpoint.h deleted file mode 100644 index d064047612b1..000000000000 --- a/trunk/arch/arm64/include/asm/hw_breakpoint.h +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Copyright (C) 2012 ARM 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 __ASM_HW_BREAKPOINT_H -#define __ASM_HW_BREAKPOINT_H - -#ifdef __KERNEL__ - -struct arch_hw_breakpoint_ctrl { - u32 __reserved : 19, - len : 8, - type : 2, - privilege : 2, - enabled : 1; -}; - -struct arch_hw_breakpoint { - u64 address; - u64 trigger; - struct arch_hw_breakpoint_ctrl ctrl; -}; - -static inline u32 encode_ctrl_reg(struct arch_hw_breakpoint_ctrl ctrl) -{ - return (ctrl.len << 5) | (ctrl.type << 3) | (ctrl.privilege << 1) | - ctrl.enabled; -} - -static inline void decode_ctrl_reg(u32 reg, - struct arch_hw_breakpoint_ctrl *ctrl) -{ - ctrl->enabled = reg & 0x1; - reg >>= 1; - ctrl->privilege = reg & 0x3; - reg >>= 2; - ctrl->type = reg & 0x3; - reg >>= 2; - ctrl->len = reg & 0xff; -} - -/* Breakpoint */ -#define ARM_BREAKPOINT_EXECUTE 0 - -/* Watchpoints */ -#define ARM_BREAKPOINT_LOAD 1 -#define ARM_BREAKPOINT_STORE 2 -#define AARCH64_ESR_ACCESS_MASK (1 << 6) - -/* Privilege Levels */ -#define AARCH64_BREAKPOINT_EL1 1 -#define AARCH64_BREAKPOINT_EL0 2 - -/* Lengths */ -#define ARM_BREAKPOINT_LEN_1 0x1 -#define ARM_BREAKPOINT_LEN_2 0x3 -#define ARM_BREAKPOINT_LEN_4 0xf -#define ARM_BREAKPOINT_LEN_8 0xff - -/* Kernel stepping */ -#define ARM_KERNEL_STEP_NONE 0 -#define ARM_KERNEL_STEP_ACTIVE 1 -#define ARM_KERNEL_STEP_SUSPEND 2 - -/* - * Limits. - * Changing these will require modifications to the register accessors. - */ -#define ARM_MAX_BRP 16 -#define ARM_MAX_WRP 16 -#define ARM_MAX_HBP_SLOTS (ARM_MAX_BRP + ARM_MAX_WRP) - -/* Virtual debug register bases. */ -#define AARCH64_DBG_REG_BVR 0 -#define AARCH64_DBG_REG_BCR (AARCH64_DBG_REG_BVR + ARM_MAX_BRP) -#define AARCH64_DBG_REG_WVR (AARCH64_DBG_REG_BCR + ARM_MAX_BRP) -#define AARCH64_DBG_REG_WCR (AARCH64_DBG_REG_WVR + ARM_MAX_WRP) - -/* Debug register names. */ -#define AARCH64_DBG_REG_NAME_BVR "bvr" -#define AARCH64_DBG_REG_NAME_BCR "bcr" -#define AARCH64_DBG_REG_NAME_WVR "wvr" -#define AARCH64_DBG_REG_NAME_WCR "wcr" - -/* Accessor macros for the debug registers. */ -#define AARCH64_DBG_READ(N, REG, VAL) do {\ - asm volatile("mrs %0, dbg" REG #N "_el1" : "=r" (VAL));\ -} while (0) - -#define AARCH64_DBG_WRITE(N, REG, VAL) do {\ - asm volatile("msr dbg" REG #N "_el1, %0" :: "r" (VAL));\ -} while (0) - -struct task_struct; -struct notifier_block; -struct perf_event; -struct pmu; - -extern int arch_bp_generic_fields(struct arch_hw_breakpoint_ctrl ctrl, - int *gen_len, int *gen_type); -extern int arch_check_bp_in_kernelspace(struct perf_event *bp); -extern int arch_validate_hwbkpt_settings(struct perf_event *bp); -extern int hw_breakpoint_exceptions_notify(struct notifier_block *unused, - unsigned long val, void *data); - -extern int arch_install_hw_breakpoint(struct perf_event *bp); -extern void arch_uninstall_hw_breakpoint(struct perf_event *bp); -extern void hw_breakpoint_pmu_read(struct perf_event *bp); -extern int hw_breakpoint_slots(int type); - -#ifdef CONFIG_HAVE_HW_BREAKPOINT -extern void hw_breakpoint_thread_switch(struct task_struct *next); -extern void ptrace_hw_copy_thread(struct task_struct *task); -#else -static inline void hw_breakpoint_thread_switch(struct task_struct *next) -{ -} -static inline void ptrace_hw_copy_thread(struct task_struct *task) -{ -} -#endif - -extern struct pmu perf_ops_bp; - -#endif /* __KERNEL__ */ -#endif /* __ASM_BREAKPOINT_H */ diff --git a/trunk/arch/arm64/include/asm/hwcap.h b/trunk/arch/arm64/include/asm/hwcap.h deleted file mode 100644 index f8190ba45a3e..000000000000 --- a/trunk/arch/arm64/include/asm/hwcap.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2012 ARM 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 __ASM_HWCAP_H -#define __ASM_HWCAP_H - -/* - * HWCAP flags - for elf_hwcap (in kernel) and AT_HWCAP - */ -#define HWCAP_FP (1 << 0) -#define HWCAP_ASIMD (1 << 1) - -#define COMPAT_HWCAP_HALF (1 << 1) -#define COMPAT_HWCAP_THUMB (1 << 2) -#define COMPAT_HWCAP_FAST_MULT (1 << 4) -#define COMPAT_HWCAP_VFP (1 << 6) -#define COMPAT_HWCAP_EDSP (1 << 7) -#define COMPAT_HWCAP_NEON (1 << 12) -#define COMPAT_HWCAP_VFPv3 (1 << 13) -#define COMPAT_HWCAP_TLS (1 << 15) -#define COMPAT_HWCAP_VFPv4 (1 << 16) -#define COMPAT_HWCAP_IDIVA (1 << 17) -#define COMPAT_HWCAP_IDIVT (1 << 18) -#define COMPAT_HWCAP_IDIV (COMPAT_HWCAP_IDIVA|COMPAT_HWCAP_IDIVT) - -#if defined(__KERNEL__) && !defined(__ASSEMBLY__) -/* - * This yields a mask that user programs can use to figure out what - * instruction set this cpu supports. - */ -#define ELF_HWCAP (elf_hwcap) -#define COMPAT_ELF_HWCAP (COMPAT_HWCAP_HALF|COMPAT_HWCAP_THUMB|\ - COMPAT_HWCAP_FAST_MULT|COMPAT_HWCAP_EDSP|\ - COMPAT_HWCAP_TLS|COMPAT_HWCAP_VFP|\ - COMPAT_HWCAP_VFPv3|COMPAT_HWCAP_VFPv4|\ - COMPAT_HWCAP_NEON|COMPAT_HWCAP_IDIV) - -extern unsigned int elf_hwcap; -#endif - -#endif diff --git a/trunk/arch/arm64/include/asm/io.h b/trunk/arch/arm64/include/asm/io.h deleted file mode 100644 index 74a2a7d304a9..000000000000 --- a/trunk/arch/arm64/include/asm/io.h +++ /dev/null @@ -1,258 +0,0 @@ -/* - * Based on arch/arm/include/asm/io.h - * - * Copyright (C) 1996-2000 Russell King - * Copyright (C) 2012 ARM 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 __ASM_IO_H -#define __ASM_IO_H - -#ifdef __KERNEL__ - -#include - -#include -#include -#include - -/* - * Generic IO read/write. These perform native-endian accesses. - */ -static inline void __raw_writeb(u8 val, volatile void __iomem *addr) -{ - asm volatile("strb %w0, [%1]" : : "r" (val), "r" (addr)); -} - -static inline void __raw_writew(u16 val, volatile void __iomem *addr) -{ - asm volatile("strh %w0, [%1]" : : "r" (val), "r" (addr)); -} - -static inline void __raw_writel(u32 val, volatile void __iomem *addr) -{ - asm volatile("str %w0, [%1]" : : "r" (val), "r" (addr)); -} - -static inline void __raw_writeq(u64 val, volatile void __iomem *addr) -{ - asm volatile("str %0, [%1]" : : "r" (val), "r" (addr)); -} - -static inline u8 __raw_readb(const volatile void __iomem *addr) -{ - u8 val; - asm volatile("ldrb %w0, [%1]" : "=r" (val) : "r" (addr)); - return val; -} - -static inline u16 __raw_readw(const volatile void __iomem *addr) -{ - u16 val; - asm volatile("ldrh %w0, [%1]" : "=r" (val) : "r" (addr)); - return val; -} - -static inline u32 __raw_readl(const volatile void __iomem *addr) -{ - u32 val; - asm volatile("ldr %w0, [%1]" : "=r" (val) : "r" (addr)); - return val; -} - -static inline u64 __raw_readq(const volatile void __iomem *addr) -{ - u64 val; - asm volatile("ldr %0, [%1]" : "=r" (val) : "r" (addr)); - return val; -} - -/* IO barriers */ -#define __iormb() rmb() -#define __iowmb() wmb() - -#define mmiowb() do { } while (0) - -/* - * Relaxed I/O memory access primitives. These follow the Device memory - * ordering rules but do not guarantee any ordering relative to Normal memory - * accesses. - */ -#define readb_relaxed(c) ({ u8 __v = __raw_readb(c); __v; }) -#define readw_relaxed(c) ({ u16 __v = le16_to_cpu((__force __le16)__raw_readw(c)); __v; }) -#define readl_relaxed(c) ({ u32 __v = le32_to_cpu((__force __le32)__raw_readl(c)); __v; }) - -#define writeb_relaxed(v,c) ((void)__raw_writeb((v),(c))) -#define writew_relaxed(v,c) ((void)__raw_writew((__force u16)cpu_to_le16(v),(c))) -#define writel_relaxed(v,c) ((void)__raw_writel((__force u32)cpu_to_le32(v),(c))) - -/* - * I/O memory access primitives. Reads are ordered relative to any - * following Normal memory access. Writes are ordered relative to any prior - * Normal memory access. - */ -#define readb(c) ({ u8 __v = readb_relaxed(c); __iormb(); __v; }) -#define readw(c) ({ u16 __v = readw_relaxed(c); __iormb(); __v; }) -#define readl(c) ({ u32 __v = readl_relaxed(c); __iormb(); __v; }) - -#define writeb(v,c) ({ __iowmb(); writeb_relaxed((v),(c)); }) -#define writew(v,c) ({ __iowmb(); writew_relaxed((v),(c)); }) -#define writel(v,c) ({ __iowmb(); writel_relaxed((v),(c)); }) - -/* - * I/O port access primitives. - */ -#define IO_SPACE_LIMIT 0xffff -#define PCI_IOBASE ((void __iomem *)0xffffffbbfffe0000UL) - -static inline u8 inb(unsigned long addr) -{ - return readb(addr + PCI_IOBASE); -} - -static inline u16 inw(unsigned long addr) -{ - return readw(addr + PCI_IOBASE); -} - -static inline u32 inl(unsigned long addr) -{ - return readl(addr + PCI_IOBASE); -} - -static inline void outb(u8 b, unsigned long addr) -{ - writeb(b, addr + PCI_IOBASE); -} - -static inline void outw(u16 b, unsigned long addr) -{ - writew(b, addr + PCI_IOBASE); -} - -static inline void outl(u32 b, unsigned long addr) -{ - writel(b, addr + PCI_IOBASE); -} - -#define inb_p(addr) inb(addr) -#define inw_p(addr) inw(addr) -#define inl_p(addr) inl(addr) - -#define outb_p(x, addr) outb((x), (addr)) -#define outw_p(x, addr) outw((x), (addr)) -#define outl_p(x, addr) outl((x), (addr)) - -static inline void insb(unsigned long addr, void *buffer, int count) -{ - u8 *buf = buffer; - while (count--) - *buf++ = __raw_readb(addr + PCI_IOBASE); -} - -static inline void insw(unsigned long addr, void *buffer, int count) -{ - u16 *buf = buffer; - while (count--) - *buf++ = __raw_readw(addr + PCI_IOBASE); -} - -static inline void insl(unsigned long addr, void *buffer, int count) -{ - u32 *buf = buffer; - while (count--) - *buf++ = __raw_readl(addr + PCI_IOBASE); -} - -static inline void outsb(unsigned long addr, const void *buffer, int count) -{ - const u8 *buf = buffer; - while (count--) - __raw_writeb(*buf++, addr + PCI_IOBASE); -} - -static inline void outsw(unsigned long addr, const void *buffer, int count) -{ - const u16 *buf = buffer; - while (count--) - __raw_writew(*buf++, addr + PCI_IOBASE); -} - -static inline void outsl(unsigned long addr, const void *buffer, int count) -{ - const u32 *buf = buffer; - while (count--) - __raw_writel(*buf++, addr + PCI_IOBASE); -} - -#define insb_p(port,to,len) insb(port,to,len) -#define insw_p(port,to,len) insw(port,to,len) -#define insl_p(port,to,len) insl(port,to,len) - -#define outsb_p(port,from,len) outsb(port,from,len) -#define outsw_p(port,from,len) outsw(port,from,len) -#define outsl_p(port,from,len) outsl(port,from,len) - -/* - * String version of I/O memory access operations. - */ -extern void __memcpy_fromio(void *, const volatile void __iomem *, size_t); -extern void __memcpy_toio(volatile void __iomem *, const void *, size_t); -extern void __memset_io(volatile void __iomem *, int, size_t); - -#define memset_io(c,v,l) __memset_io((c),(v),(l)) -#define memcpy_fromio(a,c,l) __memcpy_fromio((a),(c),(l)) -#define memcpy_toio(c,a,l) __memcpy_toio((c),(a),(l)) - -/* - * I/O memory mapping functions. - */ -extern void __iomem *__ioremap(phys_addr_t phys_addr, size_t size, pgprot_t prot); -extern void __iounmap(volatile void __iomem *addr); - -#define PROT_DEFAULT (PTE_TYPE_PAGE | PTE_AF | PTE_DIRTY) -#define PROT_DEVICE_nGnRE (PROT_DEFAULT | PTE_XN | PTE_ATTRINDX(MT_DEVICE_nGnRE)) -#define PROT_NORMAL_NC (PROT_DEFAULT | PTE_ATTRINDX(MT_NORMAL_NC)) - -#define ioremap(addr, size) __ioremap((addr), (size), PROT_DEVICE_nGnRE) -#define ioremap_nocache(addr, size) __ioremap((addr), (size), PROT_DEVICE_nGnRE) -#define ioremap_wc(addr, size) __ioremap((addr), (size), PROT_NORMAL_NC) -#define iounmap __iounmap - -#define ARCH_HAS_IOREMAP_WC -#include - -/* - * More restrictive address range checking than the default implementation - * (PHYS_OFFSET and PHYS_MASK taken into account). - */ -#define ARCH_HAS_VALID_PHYS_ADDR_RANGE -extern int valid_phys_addr_range(unsigned long addr, size_t size); -extern int valid_mmap_phys_addr_range(unsigned long pfn, size_t size); - -extern int devmem_is_allowed(unsigned long pfn); - -/* - * Convert a physical pointer to a virtual kernel pointer for /dev/mem - * access - */ -#define xlate_dev_mem_ptr(p) __va(p) - -/* - * Convert a virtual cached pointer to an uncached pointer - */ -#define xlate_dev_kmem_ptr(p) p - -#endif /* __KERNEL__ */ -#endif /* __ASM_IO_H */ diff --git a/trunk/arch/arm64/include/asm/irq.h b/trunk/arch/arm64/include/asm/irq.h deleted file mode 100644 index a4e1cad3202a..000000000000 --- a/trunk/arch/arm64/include/asm/irq.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef __ASM_IRQ_H -#define __ASM_IRQ_H - -#include - -extern void (*handle_arch_irq)(struct pt_regs *); - -#endif diff --git a/trunk/arch/arm64/include/asm/irqflags.h b/trunk/arch/arm64/include/asm/irqflags.h deleted file mode 100644 index aa11943b8502..000000000000 --- a/trunk/arch/arm64/include/asm/irqflags.h +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright (C) 2012 ARM 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 __ASM_IRQFLAGS_H -#define __ASM_IRQFLAGS_H - -#ifdef __KERNEL__ - -#include - -/* - * CPU interrupt mask handling. - */ -static inline unsigned long arch_local_irq_save(void) -{ - unsigned long flags; - asm volatile( - "mrs %0, daif // arch_local_irq_save\n" - "msr daifset, #2" - : "=r" (flags) - : - : "memory"); - return flags; -} - -static inline void arch_local_irq_enable(void) -{ - asm volatile( - "msr daifclr, #2 // arch_local_irq_enable" - : - : - : "memory"); -} - -static inline void arch_local_irq_disable(void) -{ - asm volatile( - "msr daifset, #2 // arch_local_irq_disable" - : - : - : "memory"); -} - -#define local_fiq_enable() asm("msr daifclr, #1" : : : "memory") -#define local_fiq_disable() asm("msr daifset, #1" : : : "memory") - -/* - * Save the current interrupt enable state. - */ -static inline unsigned long arch_local_save_flags(void) -{ - unsigned long flags; - asm volatile( - "mrs %0, daif // arch_local_save_flags" - : "=r" (flags) - : - : "memory"); - return flags; -} - -/* - * restore saved IRQ state - */ -static inline void arch_local_irq_restore(unsigned long flags) -{ - asm volatile( - "msr daif, %0 // arch_local_irq_restore" - : - : "r" (flags) - : "memory"); -} - -static inline int arch_irqs_disabled_flags(unsigned long flags) -{ - return flags & PSR_I_BIT; -} - -#endif -#endif diff --git a/trunk/arch/arm64/include/asm/memblock.h b/trunk/arch/arm64/include/asm/memblock.h deleted file mode 100644 index 6afeed2467f1..000000000000 --- a/trunk/arch/arm64/include/asm/memblock.h +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (C) 2012 ARM 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 __ASM_MEMBLOCK_H -#define __ASM_MEMBLOCK_H - -extern void arm64_memblock_init(void); - -#endif diff --git a/trunk/arch/arm64/include/asm/memory.h b/trunk/arch/arm64/include/asm/memory.h deleted file mode 100644 index 1cac16a001cb..000000000000 --- a/trunk/arch/arm64/include/asm/memory.h +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Based on arch/arm/include/asm/memory.h - * - * Copyright (C) 2000-2002 Russell King - * Copyright (C) 2012 ARM 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 . - * - * Note: this file should not be included by non-asm/.h files - */ -#ifndef __ASM_MEMORY_H -#define __ASM_MEMORY_H - -#include -#include -#include -#include - -/* - * Allow for constants defined here to be used from assembly code - * by prepending the UL suffix only with actual C code compilation. - */ -#define UL(x) _AC(x, UL) - -/* - * PAGE_OFFSET - the virtual address of the start of the kernel image. - * VA_BITS - the maximum number of bits for virtual addresses. - * TASK_SIZE - the maximum size of a user space task. - * TASK_UNMAPPED_BASE - the lower boundary of the mmap VM area. - * The module space lives between the addresses given by TASK_SIZE - * and PAGE_OFFSET - it must be within 128MB of the kernel text. - */ -#define PAGE_OFFSET UL(0xffffffc000000000) -#define MODULES_END (PAGE_OFFSET) -#define MODULES_VADDR (MODULES_END - SZ_64M) -#define VA_BITS (39) -#define TASK_SIZE_64 (UL(1) << VA_BITS) - -#ifdef CONFIG_COMPAT -#define TASK_SIZE_32 UL(0x100000000) -#define TASK_SIZE (test_thread_flag(TIF_32BIT) ? \ - TASK_SIZE_32 : TASK_SIZE_64) -#else -#define TASK_SIZE TASK_SIZE_64 -#endif /* CONFIG_COMPAT */ - -#define TASK_UNMAPPED_BASE (PAGE_ALIGN(TASK_SIZE / 4)) - -#if TASK_SIZE_64 > MODULES_VADDR -#error Top of 64-bit user space clashes with start of module space -#endif - -/* - * Physical vs virtual RAM address space conversion. These are - * private definitions which should NOT be used outside memory.h - * files. Use virt_to_phys/phys_to_virt/__pa/__va instead. - */ -#define __virt_to_phys(x) (((phys_addr_t)(x) - PAGE_OFFSET + PHYS_OFFSET)) -#define __phys_to_virt(x) ((unsigned long)((x) - PHYS_OFFSET + PAGE_OFFSET)) - -/* - * Convert a physical address to a Page Frame Number and back - */ -#define __phys_to_pfn(paddr) ((unsigned long)((paddr) >> PAGE_SHIFT)) -#define __pfn_to_phys(pfn) ((phys_addr_t)(pfn) << PAGE_SHIFT) - -/* - * Convert a page to/from a physical address - */ -#define page_to_phys(page) (__pfn_to_phys(page_to_pfn(page))) -#define phys_to_page(phys) (pfn_to_page(__phys_to_pfn(phys))) - -/* - * Memory types available. - */ -#define MT_DEVICE_nGnRnE 0 -#define MT_DEVICE_nGnRE 1 -#define MT_DEVICE_GRE 2 -#define MT_NORMAL_NC 3 -#define MT_NORMAL 4 - -#ifndef __ASSEMBLY__ - -extern phys_addr_t memstart_addr; -/* PHYS_OFFSET - the physical address of the start of memory. */ -#define PHYS_OFFSET ({ memstart_addr; }) - -/* - * PFNs are used to describe any physical page; this means - * PFN 0 == physical address 0. - * - * This is the PFN of the first RAM page in the kernel - * direct-mapped view. We assume this is the first page - * of RAM in the mem_map as well. - */ -#define PHYS_PFN_OFFSET (PHYS_OFFSET >> PAGE_SHIFT) - -/* - * Note: Drivers should NOT use these. They are the wrong - * translation for translating DMA addresses. Use the driver - * DMA support - see dma-mapping.h. - */ -static inline phys_addr_t virt_to_phys(const volatile void *x) -{ - return __virt_to_phys((unsigned long)(x)); -} - -static inline void *phys_to_virt(phys_addr_t x) -{ - return (void *)(__phys_to_virt(x)); -} - -/* - * Drivers should NOT use these either. - */ -#define __pa(x) __virt_to_phys((unsigned long)(x)) -#define __va(x) ((void *)__phys_to_virt((phys_addr_t)(x))) -#define pfn_to_kaddr(pfn) __va((pfn) << PAGE_SHIFT) - -/* - * virt_to_page(k) convert a _valid_ virtual address to struct page * - * virt_addr_valid(k) indicates whether a virtual address is valid - */ -#define ARCH_PFN_OFFSET PHYS_PFN_OFFSET - -#define virt_to_page(kaddr) pfn_to_page(__pa(kaddr) >> PAGE_SHIFT) -#define virt_addr_valid(kaddr) (((void *)(kaddr) >= (void *)PAGE_OFFSET) && \ - ((void *)(kaddr) < (void *)high_memory)) - -#endif - -#include - -#endif diff --git a/trunk/arch/arm64/include/asm/mmu.h b/trunk/arch/arm64/include/asm/mmu.h deleted file mode 100644 index d4f7fd5b9e33..000000000000 --- a/trunk/arch/arm64/include/asm/mmu.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (C) 2012 ARM 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 __ASM_MMU_H -#define __ASM_MMU_H - -typedef struct { - unsigned int id; - raw_spinlock_t id_lock; - void *vdso; -} mm_context_t; - -#define ASID(mm) ((mm)->context.id & 0xffff) - -extern void paging_init(void); -extern void setup_mm_for_reboot(void); - -#endif diff --git a/trunk/arch/arm64/include/asm/mmu_context.h b/trunk/arch/arm64/include/asm/mmu_context.h deleted file mode 100644 index f68465dee026..000000000000 --- a/trunk/arch/arm64/include/asm/mmu_context.h +++ /dev/null @@ -1,152 +0,0 @@ -/* - * Based on arch/arm/include/asm/mmu_context.h - * - * Copyright (C) 1996 Russell King. - * Copyright (C) 2012 ARM 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 __ASM_MMU_CONTEXT_H -#define __ASM_MMU_CONTEXT_H - -#include -#include - -#include -#include -#include -#include -#include - -#define MAX_ASID_BITS 16 - -extern unsigned int cpu_last_asid; - -void __init_new_context(struct task_struct *tsk, struct mm_struct *mm); -void __new_context(struct mm_struct *mm); - -/* - * Set TTBR0 to empty_zero_page. No translations will be possible via TTBR0. - */ -static inline void cpu_set_reserved_ttbr0(void) -{ - unsigned long ttbr = page_to_phys(empty_zero_page); - - asm( - " msr ttbr0_el1, %0 // set TTBR0\n" - " isb" - : - : "r" (ttbr)); -} - -static inline void switch_new_context(struct mm_struct *mm) -{ - unsigned long flags; - - __new_context(mm); - - local_irq_save(flags); - cpu_switch_mm(mm->pgd, mm); - local_irq_restore(flags); -} - -static inline void check_and_switch_context(struct mm_struct *mm, - struct task_struct *tsk) -{ - /* - * Required during context switch to avoid speculative page table - * walking with the wrong TTBR. - */ - cpu_set_reserved_ttbr0(); - - if (!((mm->context.id ^ cpu_last_asid) >> MAX_ASID_BITS)) - /* - * The ASID is from the current generation, just switch to the - * new pgd. This condition is only true for calls from - * context_switch() and interrupts are already disabled. - */ - cpu_switch_mm(mm->pgd, mm); - else if (irqs_disabled()) - /* - * Defer the new ASID allocation until after the context - * switch critical region since __new_context() cannot be - * called with interrupts disabled. - */ - set_ti_thread_flag(task_thread_info(tsk), TIF_SWITCH_MM); - else - /* - * That is a direct call to switch_mm() or activate_mm() with - * interrupts enabled and a new context. - */ - switch_new_context(mm); -} - -#define init_new_context(tsk,mm) (__init_new_context(tsk,mm),0) -#define destroy_context(mm) do { } while(0) - -#define finish_arch_post_lock_switch \ - finish_arch_post_lock_switch -static inline void finish_arch_post_lock_switch(void) -{ - if (test_and_clear_thread_flag(TIF_SWITCH_MM)) { - struct mm_struct *mm = current->mm; - unsigned long flags; - - __new_context(mm); - - local_irq_save(flags); - cpu_switch_mm(mm->pgd, mm); - local_irq_restore(flags); - } -} - -/* - * This is called when "tsk" is about to enter lazy TLB mode. - * - * mm: describes the currently active mm context - * tsk: task which is entering lazy tlb - * cpu: cpu number which is entering lazy tlb - * - * tsk->mm will be NULL - */ -static inline void -enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk) -{ -} - -/* - * This is the actual mm switch as far as the scheduler - * is concerned. No registers are touched. We avoid - * calling the CPU specific function when the mm hasn't - * actually changed. - */ -static inline void -switch_mm(struct mm_struct *prev, struct mm_struct *next, - struct task_struct *tsk) -{ - unsigned int cpu = smp_processor_id(); - -#ifdef CONFIG_SMP - /* check for possible thread migration */ - if (!cpumask_empty(mm_cpumask(next)) && - !cpumask_test_cpu(cpu, mm_cpumask(next))) - __flush_icache_all(); -#endif - if (!cpumask_test_and_set_cpu(cpu, mm_cpumask(next)) || prev != next) - check_and_switch_context(next, tsk); -} - -#define deactivate_mm(tsk,mm) do { } while (0) -#define activate_mm(prev,next) switch_mm(prev, next, NULL) - -#endif diff --git a/trunk/arch/arm64/include/asm/module.h b/trunk/arch/arm64/include/asm/module.h deleted file mode 100644 index e80e232b730e..000000000000 --- a/trunk/arch/arm64/include/asm/module.h +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (C) 2012 ARM 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 __ASM_MODULE_H -#define __ASM_MODULE_H - -#include - -#define MODULE_ARCH_VERMAGIC "aarch64" - -#endif /* __ASM_MODULE_H */ diff --git a/trunk/arch/arm64/include/asm/page.h b/trunk/arch/arm64/include/asm/page.h deleted file mode 100644 index 46bf66628b6a..000000000000 --- a/trunk/arch/arm64/include/asm/page.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Based on arch/arm/include/asm/page.h - * - * Copyright (C) 1995-2003 Russell King - * Copyright (C) 2012 ARM 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 __ASM_PAGE_H -#define __ASM_PAGE_H - -/* PAGE_SHIFT determines the page size */ -#ifdef CONFIG_ARM64_64K_PAGES -#define PAGE_SHIFT 16 -#else -#define PAGE_SHIFT 12 -#endif -#define PAGE_SIZE (_AC(1,UL) << PAGE_SHIFT) -#define PAGE_MASK (~(PAGE_SIZE-1)) - -/* We do define AT_SYSINFO_EHDR but don't use the gate mechanism */ -#define __HAVE_ARCH_GATE_AREA 1 - -#ifndef __ASSEMBLY__ - -#ifdef CONFIG_ARM64_64K_PAGES -#include -#else -#include -#endif - -extern void __cpu_clear_user_page(void *p, unsigned long user); -extern void __cpu_copy_user_page(void *to, const void *from, - unsigned long user); -extern void copy_page(void *to, const void *from); -extern void clear_page(void *to); - -#define clear_user_page(addr,vaddr,pg) __cpu_clear_user_page(addr, vaddr) -#define copy_user_page(to,from,vaddr,pg) __cpu_copy_user_page(to, from, vaddr) - -typedef struct page *pgtable_t; - -#ifdef CONFIG_HAVE_ARCH_PFN_VALID -extern int pfn_valid(unsigned long); -#endif - -#include - -#endif /* !__ASSEMBLY__ */ - -#define VM_DATA_DEFAULT_FLAGS \ - (((current->personality & READ_IMPLIES_EXEC) ? VM_EXEC : 0) | \ - VM_READ | VM_WRITE | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC) - -#include - -#endif diff --git a/trunk/arch/arm64/include/asm/param.h b/trunk/arch/arm64/include/asm/param.h deleted file mode 100644 index 8e3a281d448a..000000000000 --- a/trunk/arch/arm64/include/asm/param.h +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (C) 2012 ARM 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 __ASM_PARAM_H -#define __ASM_PARAM_H - -#define EXEC_PAGESIZE 65536 - -#include - -#endif diff --git a/trunk/arch/arm64/include/asm/perf_event.h b/trunk/arch/arm64/include/asm/perf_event.h deleted file mode 100644 index a6fffd511c5e..000000000000 --- a/trunk/arch/arm64/include/asm/perf_event.h +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (C) 2012 ARM 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 __ASM_PERF_EVENT_H -#define __ASM_PERF_EVENT_H - -/* It's quiet around here... */ - -#endif diff --git a/trunk/arch/arm64/include/asm/pgalloc.h b/trunk/arch/arm64/include/asm/pgalloc.h deleted file mode 100644 index f214069ec5d5..000000000000 --- a/trunk/arch/arm64/include/asm/pgalloc.h +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Based on arch/arm/include/asm/pgalloc.h - * - * Copyright (C) 2000-2001 Russell King - * Copyright (C) 2012 ARM 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 __ASM_PGALLOC_H -#define __ASM_PGALLOC_H - -#include -#include -#include -#include - -#define check_pgt_cache() do { } while (0) - -#ifndef CONFIG_ARM64_64K_PAGES - -static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long addr) -{ - return (pmd_t *)get_zeroed_page(GFP_KERNEL | __GFP_REPEAT); -} - -static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd) -{ - BUG_ON((unsigned long)pmd & (PAGE_SIZE-1)); - free_page((unsigned long)pmd); -} - -static inline void pud_populate(struct mm_struct *mm, pud_t *pud, pmd_t *pmd) -{ - set_pud(pud, __pud(__pa(pmd) | PMD_TYPE_TABLE)); -} - -#endif /* CONFIG_ARM64_64K_PAGES */ - -extern pgd_t *pgd_alloc(struct mm_struct *mm); -extern void pgd_free(struct mm_struct *mm, pgd_t *pgd); - -#define PGALLOC_GFP (GFP_KERNEL | __GFP_NOTRACK | __GFP_REPEAT | __GFP_ZERO) - -static inline pte_t * -pte_alloc_one_kernel(struct mm_struct *mm, unsigned long addr) -{ - return (pte_t *)__get_free_page(PGALLOC_GFP); -} - -static inline pgtable_t -pte_alloc_one(struct mm_struct *mm, unsigned long addr) -{ - struct page *pte; - - pte = alloc_pages(PGALLOC_GFP, 0); - if (pte) - pgtable_page_ctor(pte); - - return pte; -} - -/* - * Free a PTE table. - */ -static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte) -{ - if (pte) - free_page((unsigned long)pte); -} - -static inline void pte_free(struct mm_struct *mm, pgtable_t pte) -{ - pgtable_page_dtor(pte); - __free_page(pte); -} - -static inline void __pmd_populate(pmd_t *pmdp, phys_addr_t pte, - pmdval_t prot) -{ - set_pmd(pmdp, __pmd(pte | prot)); -} - -/* - * Populate the pmdp entry with a pointer to the pte. This pmd is part - * of the mm address space. - */ -static inline void -pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmdp, pte_t *ptep) -{ - /* - * The pmd must be loaded with the physical address of the PTE table - */ - __pmd_populate(pmdp, __pa(ptep), PMD_TYPE_TABLE); -} - -static inline void -pmd_populate(struct mm_struct *mm, pmd_t *pmdp, pgtable_t ptep) -{ - __pmd_populate(pmdp, page_to_phys(ptep), PMD_TYPE_TABLE); -} -#define pmd_pgtable(pmd) pmd_page(pmd) - -#endif diff --git a/trunk/arch/arm64/include/asm/pgtable-2level-hwdef.h b/trunk/arch/arm64/include/asm/pgtable-2level-hwdef.h deleted file mode 100644 index 0a8ed3f94e93..000000000000 --- a/trunk/arch/arm64/include/asm/pgtable-2level-hwdef.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (C) 2012 ARM 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 __ASM_PGTABLE_2LEVEL_HWDEF_H -#define __ASM_PGTABLE_2LEVEL_HWDEF_H - -/* - * With LPAE and 64KB pages, there are 2 levels of page tables. Each level has - * 8192 entries of 8 bytes each, occupying a 64KB page. Levels 0 and 1 are not - * used. The 2nd level table (PGD for Linux) can cover a range of 4TB, each - * entry representing 512MB. The user and kernel address spaces are limited to - * 512GB and therefore we only use 1024 entries in the PGD. - */ -#define PTRS_PER_PTE 8192 -#define PTRS_PER_PGD 1024 - -/* - * PGDIR_SHIFT determines the size a top-level page table entry can map. - */ -#define PGDIR_SHIFT 29 -#define PGDIR_SIZE (_AC(1, UL) << PGDIR_SHIFT) -#define PGDIR_MASK (~(PGDIR_SIZE-1)) - -/* - * section address mask and size definitions. - */ -#define SECTION_SHIFT 29 -#define SECTION_SIZE (_AC(1, UL) << SECTION_SHIFT) -#define SECTION_MASK (~(SECTION_SIZE-1)) - -#endif diff --git a/trunk/arch/arm64/include/asm/pgtable-2level-types.h b/trunk/arch/arm64/include/asm/pgtable-2level-types.h deleted file mode 100644 index 3c3ca7d361e4..000000000000 --- a/trunk/arch/arm64/include/asm/pgtable-2level-types.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (C) 2012 ARM 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 __ASM_PGTABLE_2LEVEL_TYPES_H -#define __ASM_PGTABLE_2LEVEL_TYPES_H - -typedef u64 pteval_t; -typedef u64 pgdval_t; -typedef pgdval_t pmdval_t; - -#undef STRICT_MM_TYPECHECKS - -#ifdef STRICT_MM_TYPECHECKS - -/* - * These are used to make use of C type-checking.. - */ -typedef struct { pteval_t pte; } pte_t; -typedef struct { pgdval_t pgd; } pgd_t; -typedef struct { pteval_t pgprot; } pgprot_t; - -#define pte_val(x) ((x).pte) -#define pgd_val(x) ((x).pgd) -#define pgprot_val(x) ((x).pgprot) - -#define __pte(x) ((pte_t) { (x) } ) -#define __pgd(x) ((pgd_t) { (x) } ) -#define __pgprot(x) ((pgprot_t) { (x) } ) - -#else /* !STRICT_MM_TYPECHECKS */ - -typedef pteval_t pte_t; -typedef pgdval_t pgd_t; -typedef pteval_t pgprot_t; - -#define pte_val(x) (x) -#define pgd_val(x) (x) -#define pgprot_val(x) (x) - -#define __pte(x) (x) -#define __pgd(x) (x) -#define __pgprot(x) (x) - -#endif /* STRICT_MM_TYPECHECKS */ - -#include - -#endif /* __ASM_PGTABLE_2LEVEL_TYPES_H */ diff --git a/trunk/arch/arm64/include/asm/pgtable-3level-hwdef.h b/trunk/arch/arm64/include/asm/pgtable-3level-hwdef.h deleted file mode 100644 index 3dbf941d7767..000000000000 --- a/trunk/arch/arm64/include/asm/pgtable-3level-hwdef.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (C) 2012 ARM 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 __ASM_PGTABLE_3LEVEL_HWDEF_H -#define __ASM_PGTABLE_3LEVEL_HWDEF_H - -/* - * With LPAE and 4KB pages, there are 3 levels of page tables. Each level has - * 512 entries of 8 bytes each, occupying a 4K page. The first level table - * covers a range of 512GB, each entry representing 1GB. The user and kernel - * address spaces are limited to 512GB each. - */ -#define PTRS_PER_PTE 512 -#define PTRS_PER_PMD 512 -#define PTRS_PER_PGD 512 - -/* - * PGDIR_SHIFT determines the size a top-level page table entry can map. - */ -#define PGDIR_SHIFT 30 -#define PGDIR_SIZE (_AC(1, UL) << PGDIR_SHIFT) -#define PGDIR_MASK (~(PGDIR_SIZE-1)) - -/* - * PMD_SHIFT determines the size a middle-level page table entry can map. - */ -#define PMD_SHIFT 21 -#define PMD_SIZE (_AC(1, UL) << PMD_SHIFT) -#define PMD_MASK (~(PMD_SIZE-1)) - -/* - * section address mask and size definitions. - */ -#define SECTION_SHIFT 21 -#define SECTION_SIZE (_AC(1, UL) << SECTION_SHIFT) -#define SECTION_MASK (~(SECTION_SIZE-1)) - -#endif diff --git a/trunk/arch/arm64/include/asm/pgtable-3level-types.h b/trunk/arch/arm64/include/asm/pgtable-3level-types.h deleted file mode 100644 index 4489615f14a9..000000000000 --- a/trunk/arch/arm64/include/asm/pgtable-3level-types.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (C) 2012 ARM 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 __ASM_PGTABLE_3LEVEL_TYPES_H -#define __ASM_PGTABLE_3LEVEL_TYPES_H - -typedef u64 pteval_t; -typedef u64 pmdval_t; -typedef u64 pgdval_t; - -#undef STRICT_MM_TYPECHECKS - -#ifdef STRICT_MM_TYPECHECKS - -/* - * These are used to make use of C type-checking.. - */ -typedef struct { pteval_t pte; } pte_t; -typedef struct { pmdval_t pmd; } pmd_t; -typedef struct { pgdval_t pgd; } pgd_t; -typedef struct { pteval_t pgprot; } pgprot_t; - -#define pte_val(x) ((x).pte) -#define pmd_val(x) ((x).pmd) -#define pgd_val(x) ((x).pgd) -#define pgprot_val(x) ((x).pgprot) - -#define __pte(x) ((pte_t) { (x) } ) -#define __pmd(x) ((pmd_t) { (x) } ) -#define __pgd(x) ((pgd_t) { (x) } ) -#define __pgprot(x) ((pgprot_t) { (x) } ) - -#else /* !STRICT_MM_TYPECHECKS */ - -typedef pteval_t pte_t; -typedef pmdval_t pmd_t; -typedef pgdval_t pgd_t; -typedef pteval_t pgprot_t; - -#define pte_val(x) (x) -#define pmd_val(x) (x) -#define pgd_val(x) (x) -#define pgprot_val(x) (x) - -#define __pte(x) (x) -#define __pmd(x) (x) -#define __pgd(x) (x) -#define __pgprot(x) (x) - -#endif /* STRICT_MM_TYPECHECKS */ - -#include - -#endif /* __ASM_PGTABLE_3LEVEL_TYPES_H */ diff --git a/trunk/arch/arm64/include/asm/pgtable-hwdef.h b/trunk/arch/arm64/include/asm/pgtable-hwdef.h deleted file mode 100644 index 0f3b4581d925..000000000000 --- a/trunk/arch/arm64/include/asm/pgtable-hwdef.h +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (C) 2012 ARM 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 __ASM_PGTABLE_HWDEF_H -#define __ASM_PGTABLE_HWDEF_H - -#ifdef CONFIG_ARM64_64K_PAGES -#include -#else -#include -#endif - -/* - * Hardware page table definitions. - * - * Level 2 descriptor (PMD). - */ -#define PMD_TYPE_MASK (_AT(pmdval_t, 3) << 0) -#define PMD_TYPE_FAULT (_AT(pmdval_t, 0) << 0) -#define PMD_TYPE_TABLE (_AT(pmdval_t, 3) << 0) -#define PMD_TYPE_SECT (_AT(pmdval_t, 1) << 0) - -/* - * Section - */ -#define PMD_SECT_S (_AT(pmdval_t, 3) << 8) -#define PMD_SECT_AF (_AT(pmdval_t, 1) << 10) -#define PMD_SECT_NG (_AT(pmdval_t, 1) << 11) -#define PMD_SECT_XN (_AT(pmdval_t, 1) << 54) - -/* - * AttrIndx[2:0] encoding (mapping attributes defined in the MAIR* registers). - */ -#define PMD_ATTRINDX(t) (_AT(pmdval_t, (t)) << 2) -#define PMD_ATTRINDX_MASK (_AT(pmdval_t, 7) << 2) - -/* - * Level 3 descriptor (PTE). - */ -#define PTE_TYPE_MASK (_AT(pteval_t, 3) << 0) -#define PTE_TYPE_FAULT (_AT(pteval_t, 0) << 0) -#define PTE_TYPE_PAGE (_AT(pteval_t, 3) << 0) -#define PTE_USER (_AT(pteval_t, 1) << 6) /* AP[1] */ -#define PTE_RDONLY (_AT(pteval_t, 1) << 7) /* AP[2] */ -#define PTE_SHARED (_AT(pteval_t, 3) << 8) /* SH[1:0], inner shareable */ -#define PTE_AF (_AT(pteval_t, 1) << 10) /* Access Flag */ -#define PTE_NG (_AT(pteval_t, 1) << 11) /* nG */ -#define PTE_XN (_AT(pteval_t, 1) << 54) /* XN */ - -/* - * AttrIndx[2:0] encoding (mapping attributes defined in the MAIR* registers). - */ -#define PTE_ATTRINDX(t) (_AT(pteval_t, (t)) << 2) -#define PTE_ATTRINDX_MASK (_AT(pteval_t, 7) << 2) - -/* - * 40-bit physical address supported. - */ -#define PHYS_MASK_SHIFT (40) -#define PHYS_MASK ((UL(1) << PHYS_MASK_SHIFT) - 1) - -/* - * TCR flags. - */ -#define TCR_TxSZ(x) (((UL(64) - (x)) << 16) | ((UL(64) - (x)) << 0)) -#define TCR_IRGN_NC ((UL(0) << 8) | (UL(0) << 24)) -#define TCR_IRGN_WBWA ((UL(1) << 8) | (UL(1) << 24)) -#define TCR_IRGN_WT ((UL(2) << 8) | (UL(2) << 24)) -#define TCR_IRGN_WBnWA ((UL(3) << 8) | (UL(3) << 24)) -#define TCR_IRGN_MASK ((UL(3) << 8) | (UL(3) << 24)) -#define TCR_ORGN_NC ((UL(0) << 10) | (UL(0) << 26)) -#define TCR_ORGN_WBWA ((UL(1) << 10) | (UL(1) << 26)) -#define TCR_ORGN_WT ((UL(2) << 10) | (UL(2) << 26)) -#define TCR_ORGN_WBnWA ((UL(3) << 10) | (UL(3) << 26)) -#define TCR_ORGN_MASK ((UL(3) << 10) | (UL(3) << 26)) -#define TCR_SHARED ((UL(3) << 12) | (UL(3) << 28)) -#define TCR_TG0_64K (UL(1) << 14) -#define TCR_TG1_64K (UL(1) << 30) -#define TCR_IPS_40BIT (UL(2) << 32) -#define TCR_ASID16 (UL(1) << 36) - -#endif diff --git a/trunk/arch/arm64/include/asm/pgtable.h b/trunk/arch/arm64/include/asm/pgtable.h deleted file mode 100644 index 8960239be722..000000000000 --- a/trunk/arch/arm64/include/asm/pgtable.h +++ /dev/null @@ -1,328 +0,0 @@ -/* - * Copyright (C) 2012 ARM 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 __ASM_PGTABLE_H -#define __ASM_PGTABLE_H - -#include - -#include -#include - -/* - * Software defined PTE bits definition. - */ -#define PTE_VALID (_AT(pteval_t, 1) << 0) /* pte_present() check */ -#define PTE_FILE (_AT(pteval_t, 1) << 2) /* only when !pte_present() */ -#define PTE_DIRTY (_AT(pteval_t, 1) << 55) -#define PTE_SPECIAL (_AT(pteval_t, 1) << 56) - -/* - * VMALLOC and SPARSEMEM_VMEMMAP ranges. - */ -#define VMALLOC_START UL(0xffffff8000000000) -#define VMALLOC_END (PAGE_OFFSET - UL(0x400000000) - SZ_64K) - -#define vmemmap ((struct page *)(VMALLOC_END + SZ_64K)) - -#define FIRST_USER_ADDRESS 0 - -#ifndef __ASSEMBLY__ -extern void __pte_error(const char *file, int line, unsigned long val); -extern void __pmd_error(const char *file, int line, unsigned long val); -extern void __pgd_error(const char *file, int line, unsigned long val); - -#define pte_ERROR(pte) __pte_error(__FILE__, __LINE__, pte_val(pte)) -#ifndef CONFIG_ARM64_64K_PAGES -#define pmd_ERROR(pmd) __pmd_error(__FILE__, __LINE__, pmd_val(pmd)) -#endif -#define pgd_ERROR(pgd) __pgd_error(__FILE__, __LINE__, pgd_val(pgd)) - -/* - * The pgprot_* and protection_map entries will be fixed up at runtime to - * include the cachable and bufferable bits based on memory policy, as well as - * any architecture dependent bits like global/ASID and SMP shared mapping - * bits. - */ -#define _PAGE_DEFAULT PTE_TYPE_PAGE | PTE_AF - -extern pgprot_t pgprot_default; - -#define _MOD_PROT(p, b) __pgprot(pgprot_val(p) | (b)) - -#define PAGE_NONE _MOD_PROT(pgprot_default, PTE_NG | PTE_XN | PTE_RDONLY) -#define PAGE_SHARED _MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_XN) -#define PAGE_SHARED_EXEC _MOD_PROT(pgprot_default, PTE_USER | PTE_NG) -#define PAGE_COPY _MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_XN | PTE_RDONLY) -#define PAGE_COPY_EXEC _MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_RDONLY) -#define PAGE_READONLY _MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_XN | PTE_RDONLY) -#define PAGE_READONLY_EXEC _MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_RDONLY) -#define PAGE_KERNEL _MOD_PROT(pgprot_default, PTE_XN | PTE_DIRTY) -#define PAGE_KERNEL_EXEC _MOD_PROT(pgprot_default, PTE_DIRTY) - -#define __PAGE_NONE __pgprot(_PAGE_DEFAULT | PTE_NG | PTE_XN | PTE_RDONLY) -#define __PAGE_SHARED __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_XN) -#define __PAGE_SHARED_EXEC __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG) -#define __PAGE_COPY __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_XN | PTE_RDONLY) -#define __PAGE_COPY_EXEC __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_RDONLY) -#define __PAGE_READONLY __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_XN | PTE_RDONLY) -#define __PAGE_READONLY_EXEC __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_RDONLY) - -#endif /* __ASSEMBLY__ */ - -#define __P000 __PAGE_NONE -#define __P001 __PAGE_READONLY -#define __P010 __PAGE_COPY -#define __P011 __PAGE_COPY -#define __P100 __PAGE_READONLY_EXEC -#define __P101 __PAGE_READONLY_EXEC -#define __P110 __PAGE_COPY_EXEC -#define __P111 __PAGE_COPY_EXEC - -#define __S000 __PAGE_NONE -#define __S001 __PAGE_READONLY -#define __S010 __PAGE_SHARED -#define __S011 __PAGE_SHARED -#define __S100 __PAGE_READONLY_EXEC -#define __S101 __PAGE_READONLY_EXEC -#define __S110 __PAGE_SHARED_EXEC -#define __S111 __PAGE_SHARED_EXEC - -#ifndef __ASSEMBLY__ -/* - * ZERO_PAGE is a global shared page that is always zero: used - * for zero-mapped memory areas etc.. - */ -extern struct page *empty_zero_page; -#define ZERO_PAGE(vaddr) (empty_zero_page) - -#define pte_pfn(pte) ((pte_val(pte) & PHYS_MASK) >> PAGE_SHIFT) - -#define pfn_pte(pfn,prot) (__pte(((phys_addr_t)(pfn) << PAGE_SHIFT) | pgprot_val(prot))) - -#define pte_none(pte) (!pte_val(pte)) -#define pte_clear(mm,addr,ptep) set_pte(ptep, __pte(0)) -#define pte_page(pte) (pfn_to_page(pte_pfn(pte))) -#define pte_offset_kernel(dir,addr) (pmd_page_vaddr(*(dir)) + __pte_index(addr)) - -#define pte_offset_map(dir,addr) pte_offset_kernel((dir), (addr)) -#define pte_offset_map_nested(dir,addr) pte_offset_kernel((dir), (addr)) -#define pte_unmap(pte) do { } while (0) -#define pte_unmap_nested(pte) do { } while (0) - -/* - * The following only work if pte_present(). Undefined behaviour otherwise. - */ -#define pte_present(pte) (pte_val(pte) & PTE_VALID) -#define pte_dirty(pte) (pte_val(pte) & PTE_DIRTY) -#define pte_young(pte) (pte_val(pte) & PTE_AF) -#define pte_special(pte) (pte_val(pte) & PTE_SPECIAL) -#define pte_write(pte) (!(pte_val(pte) & PTE_RDONLY)) -#define pte_exec(pte) (!(pte_val(pte) & PTE_XN)) - -#define pte_present_exec_user(pte) \ - ((pte_val(pte) & (PTE_VALID | PTE_USER | PTE_XN)) == \ - (PTE_VALID | PTE_USER)) - -#define PTE_BIT_FUNC(fn,op) \ -static inline pte_t pte_##fn(pte_t pte) { pte_val(pte) op; return pte; } - -PTE_BIT_FUNC(wrprotect, |= PTE_RDONLY); -PTE_BIT_FUNC(mkwrite, &= ~PTE_RDONLY); -PTE_BIT_FUNC(mkclean, &= ~PTE_DIRTY); -PTE_BIT_FUNC(mkdirty, |= PTE_DIRTY); -PTE_BIT_FUNC(mkold, &= ~PTE_AF); -PTE_BIT_FUNC(mkyoung, |= PTE_AF); -PTE_BIT_FUNC(mkspecial, |= PTE_SPECIAL); - -static inline void set_pte(pte_t *ptep, pte_t pte) -{ - *ptep = pte; -} - -extern void __sync_icache_dcache(pte_t pteval, unsigned long addr); - -static inline void set_pte_at(struct mm_struct *mm, unsigned long addr, - pte_t *ptep, pte_t pte) -{ - if (pte_present_exec_user(pte)) - __sync_icache_dcache(pte, addr); - set_pte(ptep, pte); -} - -/* - * Huge pte definitions. - */ -#define pte_huge(pte) ((pte_val(pte) & PTE_TYPE_MASK) == PTE_TYPE_HUGEPAGE) -#define pte_mkhuge(pte) (__pte((pte_val(pte) & ~PTE_TYPE_MASK) | PTE_TYPE_HUGEPAGE)) - -#define __pgprot_modify(prot,mask,bits) \ - __pgprot((pgprot_val(prot) & ~(mask)) | (bits)) - -#define __HAVE_ARCH_PTE_SPECIAL - -/* - * Mark the prot value as uncacheable and unbufferable. - */ -#define pgprot_noncached(prot) \ - __pgprot_modify(prot, PTE_ATTRINDX_MASK, PTE_ATTRINDX(MT_DEVICE_nGnRnE)) -#define pgprot_writecombine(prot) \ - __pgprot_modify(prot, PTE_ATTRINDX_MASK, PTE_ATTRINDX(MT_DEVICE_GRE)) -#define pgprot_dmacoherent(prot) \ - __pgprot_modify(prot, PTE_ATTRINDX_MASK, PTE_ATTRINDX(MT_NORMAL_NC)) -#define __HAVE_PHYS_MEM_ACCESS_PROT -struct file; -extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn, - unsigned long size, pgprot_t vma_prot); - -#define pmd_none(pmd) (!pmd_val(pmd)) -#define pmd_present(pmd) (pmd_val(pmd)) - -#define pmd_bad(pmd) (!(pmd_val(pmd) & 2)) - -static inline void set_pmd(pmd_t *pmdp, pmd_t pmd) -{ - *pmdp = pmd; - dsb(); -} - -static inline void pmd_clear(pmd_t *pmdp) -{ - set_pmd(pmdp, __pmd(0)); -} - -static inline pte_t *pmd_page_vaddr(pmd_t pmd) -{ - return __va(pmd_val(pmd) & PHYS_MASK & (s32)PAGE_MASK); -} - -#define pmd_page(pmd) pfn_to_page(__phys_to_pfn(pmd_val(pmd) & PHYS_MASK)) - -/* - * Conversion functions: convert a page and protection to a page entry, - * and a page entry and page directory to the page they refer to. - */ -#define mk_pte(page,prot) pfn_pte(page_to_pfn(page),prot) - -#ifndef CONFIG_ARM64_64K_PAGES - -#define pud_none(pud) (!pud_val(pud)) -#define pud_bad(pud) (!(pud_val(pud) & 2)) -#define pud_present(pud) (pud_val(pud)) - -static inline void set_pud(pud_t *pudp, pud_t pud) -{ - *pudp = pud; - dsb(); -} - -static inline void pud_clear(pud_t *pudp) -{ - set_pud(pudp, __pud(0)); -} - -static inline pmd_t *pud_page_vaddr(pud_t pud) -{ - return __va(pud_val(pud) & PHYS_MASK & (s32)PAGE_MASK); -} - -#endif /* CONFIG_ARM64_64K_PAGES */ - -/* to find an entry in a page-table-directory */ -#define pgd_index(addr) (((addr) >> PGDIR_SHIFT) & (PTRS_PER_PGD - 1)) - -#define pgd_offset(mm, addr) ((mm)->pgd+pgd_index(addr)) - -/* to find an entry in a kernel page-table-directory */ -#define pgd_offset_k(addr) pgd_offset(&init_mm, addr) - -/* Find an entry in the second-level page table.. */ -#ifndef CONFIG_ARM64_64K_PAGES -#define pmd_index(addr) (((addr) >> PMD_SHIFT) & (PTRS_PER_PMD - 1)) -static inline pmd_t *pmd_offset(pud_t *pud, unsigned long addr) -{ - return (pmd_t *)pud_page_vaddr(*pud) + pmd_index(addr); -} -#endif - -/* Find an entry in the third-level page table.. */ -#define __pte_index(addr) (((addr) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1)) - -static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) -{ - const pteval_t mask = PTE_USER | PTE_XN | PTE_RDONLY; - pte_val(pte) = (pte_val(pte) & ~mask) | (pgprot_val(newprot) & mask); - return pte; -} - -extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; -extern pgd_t idmap_pg_dir[PTRS_PER_PGD]; - -#define SWAPPER_DIR_SIZE (3 * PAGE_SIZE) -#define IDMAP_DIR_SIZE (2 * PAGE_SIZE) - -/* - * Encode and decode a swap entry: - * bits 0-1: present (must be zero) - * bit 2: PTE_FILE - * bits 3-8: swap type - * bits 9-63: swap offset - */ -#define __SWP_TYPE_SHIFT 3 -#define __SWP_TYPE_BITS 6 -#define __SWP_TYPE_MASK ((1 << __SWP_TYPE_BITS) - 1) -#define __SWP_OFFSET_SHIFT (__SWP_TYPE_BITS + __SWP_TYPE_SHIFT) - -#define __swp_type(x) (((x).val >> __SWP_TYPE_SHIFT) & __SWP_TYPE_MASK) -#define __swp_offset(x) ((x).val >> __SWP_OFFSET_SHIFT) -#define __swp_entry(type,offset) ((swp_entry_t) { ((type) << __SWP_TYPE_SHIFT) | ((offset) << __SWP_OFFSET_SHIFT) }) - -#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) -#define __swp_entry_to_pte(swp) ((pte_t) { (swp).val }) - -/* - * Ensure that there are not more swap files than can be encoded in the kernel - * the PTEs. - */ -#define MAX_SWAPFILES_CHECK() BUILD_BUG_ON(MAX_SWAPFILES_SHIFT > __SWP_TYPE_BITS) - -/* - * Encode and decode a file entry: - * bits 0-1: present (must be zero) - * bit 2: PTE_FILE - * bits 3-63: file offset / PAGE_SIZE - */ -#define pte_file(pte) (pte_val(pte) & PTE_FILE) -#define pte_to_pgoff(x) (pte_val(x) >> 3) -#define pgoff_to_pte(x) __pte(((x) << 3) | PTE_FILE) - -#define PTE_FILE_MAX_BITS 61 - -extern int kern_addr_valid(unsigned long addr); - -#include - -/* - * remap a physical page `pfn' of size `size' with page protection `prot' - * into virtual address `from' - */ -#define io_remap_pfn_range(vma,from,pfn,size,prot) \ - remap_pfn_range(vma, from, pfn, size, prot) - -#define pgtable_cache_init() do { } while (0) - -#endif /* !__ASSEMBLY__ */ - -#endif /* __ASM_PGTABLE_H */ diff --git a/trunk/arch/arm64/include/asm/pmu.h b/trunk/arch/arm64/include/asm/pmu.h deleted file mode 100644 index e6f087806aaf..000000000000 --- a/trunk/arch/arm64/include/asm/pmu.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Based on arch/arm/include/asm/pmu.h - * - * Copyright (C) 2009 picoChip Designs Ltd, Jamie Iles - * Copyright (C) 2012 ARM 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 __ASM_PMU_H -#define __ASM_PMU_H - -#ifdef CONFIG_HW_PERF_EVENTS - -/* The events for a given PMU register set. */ -struct pmu_hw_events { - /* - * The events that are active on the PMU for the given index. - */ - struct perf_event **events; - - /* - * A 1 bit for an index indicates that the counter is being used for - * an event. A 0 means that the counter can be used. - */ - unsigned long *used_mask; - - /* - * Hardware lock to serialize accesses to PMU registers. Needed for the - * read/modify/write sequences. - */ - raw_spinlock_t pmu_lock; -}; - -struct arm_pmu { - struct pmu pmu; - cpumask_t active_irqs; - const char *name; - irqreturn_t (*handle_irq)(int irq_num, void *dev); - void (*enable)(struct hw_perf_event *evt, int idx); - void (*disable)(struct hw_perf_event *evt, int idx); - int (*get_event_idx)(struct pmu_hw_events *hw_events, - struct hw_perf_event *hwc); - int (*set_event_filter)(struct hw_perf_event *evt, - struct perf_event_attr *attr); - u32 (*read_counter)(int idx); - void (*write_counter)(int idx, u32 val); - void (*start)(void); - void (*stop)(void); - void (*reset)(void *); - int (*map_event)(struct perf_event *event); - int num_events; - atomic_t active_events; - struct mutex reserve_mutex; - u64 max_period; - struct platform_device *plat_device; - struct pmu_hw_events *(*get_hw_events)(void); -}; - -#define to_arm_pmu(p) (container_of(p, struct arm_pmu, pmu)) - -int __init armpmu_register(struct arm_pmu *armpmu, char *name, int type); - -u64 armpmu_event_update(struct perf_event *event, - struct hw_perf_event *hwc, - int idx); - -int armpmu_event_set_period(struct perf_event *event, - struct hw_perf_event *hwc, - int idx); - -#endif /* CONFIG_HW_PERF_EVENTS */ -#endif /* __ASM_PMU_H */ diff --git a/trunk/arch/arm64/include/asm/proc-fns.h b/trunk/arch/arm64/include/asm/proc-fns.h deleted file mode 100644 index 7cdf466fd0c5..000000000000 --- a/trunk/arch/arm64/include/asm/proc-fns.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Based on arch/arm/include/asm/proc-fns.h - * - * Copyright (C) 1997-1999 Russell King - * Copyright (C) 2000 Deep Blue Solutions Ltd - * Copyright (C) 2012 ARM 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 __ASM_PROCFNS_H -#define __ASM_PROCFNS_H - -#ifdef __KERNEL__ -#ifndef __ASSEMBLY__ - -#include - -struct mm_struct; - -extern void cpu_cache_off(void); -extern void cpu_do_idle(void); -extern void cpu_do_switch_mm(unsigned long pgd_phys, struct mm_struct *mm); -extern void cpu_reset(unsigned long addr) __attribute__((noreturn)); - -#include - -#define cpu_switch_mm(pgd,mm) cpu_do_switch_mm(virt_to_phys(pgd),mm) - -#define cpu_get_pgd() \ -({ \ - unsigned long pg; \ - asm("mrs %0, ttbr0_el1\n" \ - : "=r" (pg)); \ - pg &= ~0xffff000000003ffful; \ - (pgd_t *)phys_to_virt(pg); \ -}) - -#endif /* __ASSEMBLY__ */ -#endif /* __KERNEL__ */ -#endif /* __ASM_PROCFNS_H */ diff --git a/trunk/arch/arm64/include/asm/processor.h b/trunk/arch/arm64/include/asm/processor.h deleted file mode 100644 index 39a208a392f7..000000000000 --- a/trunk/arch/arm64/include/asm/processor.h +++ /dev/null @@ -1,175 +0,0 @@ -/* - * Based on arch/arm/include/asm/processor.h - * - * Copyright (C) 1995-1999 Russell King - * Copyright (C) 2012 ARM 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 __ASM_PROCESSOR_H -#define __ASM_PROCESSOR_H - -/* - * Default implementation of macro that returns current - * instruction pointer ("program counter"). - */ -#define current_text_addr() ({ __label__ _l; _l: &&_l;}) - -#ifdef __KERNEL__ - -#include - -#include -#include -#include -#include - -#ifdef __KERNEL__ -#define STACK_TOP_MAX TASK_SIZE_64 -#ifdef CONFIG_COMPAT -#define AARCH32_VECTORS_BASE 0xffff0000 -#define STACK_TOP (test_thread_flag(TIF_32BIT) ? \ - AARCH32_VECTORS_BASE : STACK_TOP_MAX) -#else -#define STACK_TOP STACK_TOP_MAX -#endif /* CONFIG_COMPAT */ -#endif /* __KERNEL__ */ - -struct debug_info { - /* Have we suspended stepping by a debugger? */ - int suspended_step; - /* Allow breakpoints and watchpoints to be disabled for this thread. */ - int bps_disabled; - int wps_disabled; - /* Hardware breakpoints pinned to this task. */ - struct perf_event *hbp_break[ARM_MAX_BRP]; - struct perf_event *hbp_watch[ARM_MAX_WRP]; -}; - -struct cpu_context { - unsigned long x19; - unsigned long x20; - unsigned long x21; - unsigned long x22; - unsigned long x23; - unsigned long x24; - unsigned long x25; - unsigned long x26; - unsigned long x27; - unsigned long x28; - unsigned long fp; - unsigned long sp; - unsigned long pc; -}; - -struct thread_struct { - struct cpu_context cpu_context; /* cpu context */ - unsigned long tp_value; - struct fpsimd_state fpsimd_state; - unsigned long fault_address; /* fault info */ - struct debug_info debug; /* debugging */ -}; - -#define INIT_THREAD { } - -static inline void start_thread_common(struct pt_regs *regs, unsigned long pc) -{ - memset(regs, 0, sizeof(*regs)); - regs->syscallno = ~0UL; - regs->pc = pc; -} - -static inline void start_thread(struct pt_regs *regs, unsigned long pc, - unsigned long sp) -{ - unsigned long *stack = (unsigned long *)sp; - - start_thread_common(regs, pc); - regs->pstate = PSR_MODE_EL0t; - regs->sp = sp; - regs->regs[2] = stack[2]; /* x2 (envp) */ - regs->regs[1] = stack[1]; /* x1 (argv) */ - regs->regs[0] = stack[0]; /* x0 (argc) */ -} - -#ifdef CONFIG_COMPAT -static inline void compat_start_thread(struct pt_regs *regs, unsigned long pc, - unsigned long sp) -{ - unsigned int *stack = (unsigned int *)sp; - - start_thread_common(regs, pc); - regs->pstate = COMPAT_PSR_MODE_USR; - if (pc & 1) - regs->pstate |= COMPAT_PSR_T_BIT; - regs->compat_sp = sp; - regs->regs[2] = stack[2]; /* x2 (envp) */ - regs->regs[1] = stack[1]; /* x1 (argv) */ - regs->regs[0] = stack[0]; /* x0 (argc) */ -} -#endif - -/* Forward declaration, a strange C thing */ -struct task_struct; - -/* Free all resources held by a thread. */ -extern void release_thread(struct task_struct *); - -/* Prepare to copy thread state - unlazy all lazy status */ -#define prepare_to_copy(tsk) do { } while (0) - -unsigned long get_wchan(struct task_struct *p); - -#define cpu_relax() barrier() - -/* Thread switching */ -extern struct task_struct *cpu_switch_to(struct task_struct *prev, - struct task_struct *next); - -/* - * Create a new kernel thread - */ -extern int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags); - -#define task_pt_regs(p) \ - ((struct pt_regs *)(THREAD_START_SP + task_stack_page(p)) - 1) - -#define KSTK_EIP(tsk) task_pt_regs(tsk)->pc -#define KSTK_ESP(tsk) task_pt_regs(tsk)->sp - -/* - * Prefetching support - */ -#define ARCH_HAS_PREFETCH -static inline void prefetch(const void *ptr) -{ - asm volatile("prfm pldl1keep, %a0\n" : : "p" (ptr)); -} - -#define ARCH_HAS_PREFETCHW -static inline void prefetchw(const void *ptr) -{ - asm volatile("prfm pstl1keep, %a0\n" : : "p" (ptr)); -} - -#define ARCH_HAS_SPINLOCK_PREFETCH -static inline void spin_lock_prefetch(const void *x) -{ - prefetchw(x); -} - -#define HAVE_ARCH_PICK_MMAP_LAYOUT - -#endif - -#endif /* __ASM_PROCESSOR_H */ diff --git a/trunk/arch/arm64/include/asm/prom.h b/trunk/arch/arm64/include/asm/prom.h deleted file mode 100644 index 68b90e682957..000000000000 --- a/trunk/arch/arm64/include/asm/prom.h +++ /dev/null @@ -1 +0,0 @@ -/* Empty for now */ diff --git a/trunk/arch/arm64/include/asm/ptrace.h b/trunk/arch/arm64/include/asm/ptrace.h deleted file mode 100644 index 0fa5d6c9ef76..000000000000 --- a/trunk/arch/arm64/include/asm/ptrace.h +++ /dev/null @@ -1,207 +0,0 @@ -/* - * Based on arch/arm/include/asm/ptrace.h - * - * Copyright (C) 1996-2003 Russell King - * Copyright (C) 2012 ARM 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 __ASM_PTRACE_H -#define __ASM_PTRACE_H - -#include - -#include - -/* AArch32-specific ptrace requests */ -#define COMPAT_PTRACE_GETREGS 12 -#define COMPAT_PTRACE_SETREGS 13 -#define COMPAT_PTRACE_GET_THREAD_AREA 22 -#define COMPAT_PTRACE_SET_SYSCALL 23 -#define COMPAT_PTRACE_GETVFPREGS 27 -#define COMPAT_PTRACE_SETVFPREGS 28 -#define COMPAT_PTRACE_GETHBPREGS 29 -#define COMPAT_PTRACE_SETHBPREGS 30 - -/* - * PSR bits - */ -#define PSR_MODE_EL0t 0x00000000 -#define PSR_MODE_EL1t 0x00000004 -#define PSR_MODE_EL1h 0x00000005 -#define PSR_MODE_EL2t 0x00000008 -#define PSR_MODE_EL2h 0x00000009 -#define PSR_MODE_EL3t 0x0000000c -#define PSR_MODE_EL3h 0x0000000d -#define PSR_MODE_MASK 0x0000000f - -/* AArch32 CPSR bits */ -#define PSR_MODE32_BIT 0x00000010 -#define COMPAT_PSR_MODE_USR 0x00000010 -#define COMPAT_PSR_T_BIT 0x00000020 -#define COMPAT_PSR_IT_MASK 0x0600fc00 /* If-Then execution state mask */ - -/* AArch64 SPSR bits */ -#define PSR_F_BIT 0x00000040 -#define PSR_I_BIT 0x00000080 -#define PSR_A_BIT 0x00000100 -#define PSR_D_BIT 0x00000200 -#define PSR_Q_BIT 0x08000000 -#define PSR_V_BIT 0x10000000 -#define PSR_C_BIT 0x20000000 -#define PSR_Z_BIT 0x40000000 -#define PSR_N_BIT 0x80000000 - -/* - * Groups of PSR bits - */ -#define PSR_f 0xff000000 /* Flags */ -#define PSR_s 0x00ff0000 /* Status */ -#define PSR_x 0x0000ff00 /* Extension */ -#define PSR_c 0x000000ff /* Control */ - -/* - * These are 'magic' values for PTRACE_PEEKUSR that return info about where a - * process is located in memory. - */ -#define PT_TEXT_ADDR 0x10000 -#define PT_DATA_ADDR 0x10004 -#define PT_TEXT_END_ADDR 0x10008 - -#ifndef __ASSEMBLY__ - -/* - * User structures for general purpose, floating point and debug registers. - */ -struct user_pt_regs { - __u64 regs[31]; - __u64 sp; - __u64 pc; - __u64 pstate; -}; - -struct user_fpsimd_state { - __uint128_t vregs[32]; - __u32 fpsr; - __u32 fpcr; -}; - -struct user_hwdebug_state { - __u32 dbg_info; - struct { - __u64 addr; - __u32 ctrl; - } dbg_regs[16]; -}; - -#ifdef __KERNEL__ - -/* sizeof(struct user) for AArch32 */ -#define COMPAT_USER_SZ 296 -/* AArch32 uses x13 as the stack pointer... */ -#define compat_sp regs[13] -/* ... and x14 as the link register. */ -#define compat_lr regs[14] - -/* - * This struct defines the way the registers are stored on the stack during an - * exception. Note that sizeof(struct pt_regs) has to be a multiple of 16 (for - * stack alignment). struct user_pt_regs must form a prefix of struct pt_regs. - */ -struct pt_regs { - union { - struct user_pt_regs user_regs; - struct { - u64 regs[31]; - u64 sp; - u64 pc; - u64 pstate; - }; - }; - u64 orig_x0; - u64 syscallno; -}; - -#define arch_has_single_step() (1) - -#ifdef CONFIG_COMPAT -#define compat_thumb_mode(regs) \ - (((regs)->pstate & COMPAT_PSR_T_BIT)) -#else -#define compat_thumb_mode(regs) (0) -#endif - -#define user_mode(regs) \ - (((regs)->pstate & PSR_MODE_MASK) == PSR_MODE_EL0t) - -#define compat_user_mode(regs) \ - (((regs)->pstate & (PSR_MODE32_BIT | PSR_MODE_MASK)) == \ - (PSR_MODE32_BIT | PSR_MODE_EL0t)) - -#define processor_mode(regs) \ - ((regs)->pstate & PSR_MODE_MASK) - -#define interrupts_enabled(regs) \ - (!((regs)->pstate & PSR_I_BIT)) - -#define fast_interrupts_enabled(regs) \ - (!((regs)->pstate & PSR_F_BIT)) - -#define user_stack_pointer(regs) \ - ((regs)->sp) - -/* - * Are the current registers suitable for user mode? (used to maintain - * security in signal handlers) - */ -static inline int valid_user_regs(struct user_pt_regs *regs) -{ - if (user_mode(regs) && (regs->pstate & PSR_I_BIT) == 0) { - regs->pstate &= ~(PSR_F_BIT | PSR_A_BIT); - - /* The T bit is reserved for AArch64 */ - if (!(regs->pstate & PSR_MODE32_BIT)) - regs->pstate &= ~COMPAT_PSR_T_BIT; - - return 1; - } - - /* - * Force PSR to something logical... - */ - regs->pstate &= PSR_f | PSR_s | (PSR_x & ~PSR_A_BIT) | \ - COMPAT_PSR_T_BIT | PSR_MODE32_BIT; - - if (!(regs->pstate & PSR_MODE32_BIT)) { - regs->pstate &= ~COMPAT_PSR_T_BIT; - regs->pstate |= PSR_MODE_EL0t; - } - - return 0; -} - -#define instruction_pointer(regs) (regs)->pc - -#ifdef CONFIG_SMP -extern unsigned long profile_pc(struct pt_regs *regs); -#else -#define profile_pc(regs) instruction_pointer(regs) -#endif - -extern int aarch32_break_trap(struct pt_regs *regs); - -#endif /* __KERNEL__ */ - -#endif /* __ASSEMBLY__ */ - -#endif diff --git a/trunk/arch/arm64/include/asm/setup.h b/trunk/arch/arm64/include/asm/setup.h deleted file mode 100644 index 9cf2e46fbbdf..000000000000 --- a/trunk/arch/arm64/include/asm/setup.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Based on arch/arm/include/asm/setup.h - * - * Copyright (C) 1997-1999 Russell King - * Copyright (C) 2012 ARM 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 __ASM_SETUP_H -#define __ASM_SETUP_H - -#include - -#define COMMAND_LINE_SIZE 2048 - -#endif diff --git a/trunk/arch/arm64/include/asm/shmparam.h b/trunk/arch/arm64/include/asm/shmparam.h deleted file mode 100644 index 4df608a8459e..000000000000 --- a/trunk/arch/arm64/include/asm/shmparam.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (C) 2012 ARM 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 __ASM_SHMPARAM_H -#define __ASM_SHMPARAM_H - -/* - * For IPC syscalls from compat tasks, we need to use the legacy 16k - * alignment value. Since we don't have aliasing D-caches, the rest of - * the time we can safely use PAGE_SIZE. - */ -#define COMPAT_SHMLBA 0x4000 - -#include - -#endif /* __ASM_SHMPARAM_H */ diff --git a/trunk/arch/arm64/include/asm/sigcontext.h b/trunk/arch/arm64/include/asm/sigcontext.h deleted file mode 100644 index 573cec778819..000000000000 --- a/trunk/arch/arm64/include/asm/sigcontext.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (C) 2012 ARM 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 __ASM_SIGCONTEXT_H -#define __ASM_SIGCONTEXT_H - -#include - -/* - * Signal context structure - contains all info to do with the state - * before the signal handler was invoked. - */ -struct sigcontext { - __u64 fault_address; - /* AArch64 registers */ - __u64 regs[31]; - __u64 sp; - __u64 pc; - __u64 pstate; - /* 4K reserved for FP/SIMD state and future expansion */ - __u8 __reserved[4096] __attribute__((__aligned__(16))); -}; - -/* - * Header to be used at the beginning of structures extending the user - * context. Such structures must be placed after the rt_sigframe on the stack - * and be 16-byte aligned. The last structure must be a dummy one with the - * magic and size set to 0. - */ -struct _aarch64_ctx { - __u32 magic; - __u32 size; -}; - -#define FPSIMD_MAGIC 0x46508001 - -struct fpsimd_context { - struct _aarch64_ctx head; - __u32 fpsr; - __u32 fpcr; - __uint128_t vregs[32]; -}; - -#ifdef __KERNEL__ -/* - * Auxiliary context saved in the sigcontext.__reserved array. Not exported to - * user space as it will change with the addition of new context. User space - * should check the magic/size information. - */ -struct aux_context { - struct fpsimd_context fpsimd; - /* additional context to be added before "end" */ - struct _aarch64_ctx end; -}; -#endif - -#endif diff --git a/trunk/arch/arm64/include/asm/siginfo.h b/trunk/arch/arm64/include/asm/siginfo.h deleted file mode 100644 index 5a74a0853db0..000000000000 --- a/trunk/arch/arm64/include/asm/siginfo.h +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (C) 2012 ARM 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 __ASM_SIGINFO_H -#define __ASM_SIGINFO_H - -#define __ARCH_SI_PREAMBLE_SIZE (4 * sizeof(int)) - -#include - -#endif diff --git a/trunk/arch/arm64/include/asm/signal.h b/trunk/arch/arm64/include/asm/signal.h deleted file mode 100644 index 8d1e7236431b..000000000000 --- a/trunk/arch/arm64/include/asm/signal.h +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (C) 2012 ARM 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 __ASM_SIGNAL_H -#define __ASM_SIGNAL_H - -/* Required for AArch32 compatibility. */ -#define SA_RESTORER 0x04000000 - -#include - -#endif diff --git a/trunk/arch/arm64/include/asm/signal32.h b/trunk/arch/arm64/include/asm/signal32.h deleted file mode 100644 index 7c275e3b640f..000000000000 --- a/trunk/arch/arm64/include/asm/signal32.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2012 ARM 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 __ASM_SIGNAL32_H -#define __ASM_SIGNAL32_H - -#ifdef __KERNEL__ -#ifdef CONFIG_COMPAT -#include - -#define AARCH32_KERN_SIGRET_CODE_OFFSET 0x500 - -extern const compat_ulong_t aarch32_sigret_code[6]; - -int compat_setup_frame(int usig, struct k_sigaction *ka, sigset_t *set, - struct pt_regs *regs); -int compat_setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info, - sigset_t *set, struct pt_regs *regs); - -void compat_setup_restart_syscall(struct pt_regs *regs); -#else - -static inline int compat_setup_frame(int usid, struct k_sigaction *ka, - sigset_t *set, struct pt_regs *regs) -{ - return -ENOSYS; -} - -static inline int compat_setup_rt_frame(int usig, struct k_sigaction *ka, - siginfo_t *info, sigset_t *set, - struct pt_regs *regs) -{ - return -ENOSYS; -} - -static inline void compat_setup_restart_syscall(struct pt_regs *regs) -{ -} -#endif /* CONFIG_COMPAT */ -#endif /* __KERNEL__ */ -#endif /* __ASM_SIGNAL32_H */ diff --git a/trunk/arch/arm64/include/asm/smp.h b/trunk/arch/arm64/include/asm/smp.h deleted file mode 100644 index 7e34295f78e3..000000000000 --- a/trunk/arch/arm64/include/asm/smp.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (C) 2012 ARM 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 __ASM_SMP_H -#define __ASM_SMP_H - -#include -#include -#include - -#ifndef CONFIG_SMP -# error " included in non-SMP build" -#endif - -#define raw_smp_processor_id() (current_thread_info()->cpu) - -struct seq_file; - -/* - * generate IPI list text - */ -extern void show_ipi_list(struct seq_file *p, int prec); - -/* - * Called from C code, this handles an IPI. - */ -extern void handle_IPI(int ipinr, struct pt_regs *regs); - -/* - * Setup the set of possible CPUs (via set_cpu_possible) - */ -extern void smp_init_cpus(void); - -/* - * Provide a function to raise an IPI cross call on CPUs in callmap. - */ -extern void set_smp_cross_call(void (*)(const struct cpumask *, unsigned int)); - -/* - * Called from the secondary holding pen, this is the secondary CPU entry point. - */ -asmlinkage void secondary_start_kernel(void); - -/* - * Initial data for bringing up a secondary CPU. - */ -struct secondary_data { - void *stack; -}; -extern struct secondary_data secondary_data; -extern void secondary_holding_pen(void); -extern volatile unsigned long secondary_holding_pen_release; - -extern void arch_send_call_function_single_ipi(int cpu); -extern void arch_send_call_function_ipi_mask(const struct cpumask *mask); - -#endif /* ifndef __ASM_SMP_H */ diff --git a/trunk/arch/arm64/include/asm/sparsemem.h b/trunk/arch/arm64/include/asm/sparsemem.h deleted file mode 100644 index 1be62bcb9d47..000000000000 --- a/trunk/arch/arm64/include/asm/sparsemem.h +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (C) 2012 ARM 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 __ASM_SPARSEMEM_H -#define __ASM_SPARSEMEM_H - -#ifdef CONFIG_SPARSEMEM -#define MAX_PHYSMEM_BITS 40 -#define SECTION_SIZE_BITS 30 -#endif - -#endif diff --git a/trunk/arch/arm64/include/asm/spinlock.h b/trunk/arch/arm64/include/asm/spinlock.h deleted file mode 100644 index 41112fe2f8b1..000000000000 --- a/trunk/arch/arm64/include/asm/spinlock.h +++ /dev/null @@ -1,202 +0,0 @@ -/* - * Copyright (C) 2012 ARM 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 __ASM_SPINLOCK_H -#define __ASM_SPINLOCK_H - -#include -#include - -/* - * Spinlock implementation. - * - * The old value is read exclusively and the new one, if unlocked, is written - * exclusively. In case of failure, the loop is restarted. - * - * The memory barriers are implicit with the load-acquire and store-release - * instructions. - * - * Unlocked value: 0 - * Locked value: 1 - */ - -#define arch_spin_is_locked(x) ((x)->lock != 0) -#define arch_spin_unlock_wait(lock) \ - do { while (arch_spin_is_locked(lock)) cpu_relax(); } while (0) - -#define arch_spin_lock_flags(lock, flags) arch_spin_lock(lock) - -static inline void arch_spin_lock(arch_spinlock_t *lock) -{ - unsigned int tmp; - - asm volatile( - " sevl\n" - "1: wfe\n" - "2: ldaxr %w0, [%1]\n" - " cbnz %w0, 1b\n" - " stxr %w0, %w2, [%1]\n" - " cbnz %w0, 2b\n" - : "=&r" (tmp) - : "r" (&lock->lock), "r" (1) - : "memory"); -} - -static inline int arch_spin_trylock(arch_spinlock_t *lock) -{ - unsigned int tmp; - - asm volatile( - " ldaxr %w0, [%1]\n" - " cbnz %w0, 1f\n" - " stxr %w0, %w2, [%1]\n" - "1:\n" - : "=&r" (tmp) - : "r" (&lock->lock), "r" (1) - : "memory"); - - return !tmp; -} - -static inline void arch_spin_unlock(arch_spinlock_t *lock) -{ - asm volatile( - " stlr %w1, [%0]\n" - : : "r" (&lock->lock), "r" (0) : "memory"); -} - -/* - * Write lock implementation. - * - * Write locks set bit 31. Unlocking, is done by writing 0 since the lock is - * exclusively held. - * - * The memory barriers are implicit with the load-acquire and store-release - * instructions. - */ - -static inline void arch_write_lock(arch_rwlock_t *rw) -{ - unsigned int tmp; - - asm volatile( - " sevl\n" - "1: wfe\n" - "2: ldaxr %w0, [%1]\n" - " cbnz %w0, 1b\n" - " stxr %w0, %w2, [%1]\n" - " cbnz %w0, 2b\n" - : "=&r" (tmp) - : "r" (&rw->lock), "r" (0x80000000) - : "memory"); -} - -static inline int arch_write_trylock(arch_rwlock_t *rw) -{ - unsigned int tmp; - - asm volatile( - " ldaxr %w0, [%1]\n" - " cbnz %w0, 1f\n" - " stxr %w0, %w2, [%1]\n" - "1:\n" - : "=&r" (tmp) - : "r" (&rw->lock), "r" (0x80000000) - : "memory"); - - return !tmp; -} - -static inline void arch_write_unlock(arch_rwlock_t *rw) -{ - asm volatile( - " stlr %w1, [%0]\n" - : : "r" (&rw->lock), "r" (0) : "memory"); -} - -/* write_can_lock - would write_trylock() succeed? */ -#define arch_write_can_lock(x) ((x)->lock == 0) - -/* - * Read lock implementation. - * - * It exclusively loads the lock value, increments it and stores the new value - * back if positive and the CPU still exclusively owns the location. If the - * value is negative, the lock is already held. - * - * During unlocking there may be multiple active read locks but no write lock. - * - * The memory barriers are implicit with the load-acquire and store-release - * instructions. - */ -static inline void arch_read_lock(arch_rwlock_t *rw) -{ - unsigned int tmp, tmp2; - - asm volatile( - " sevl\n" - "1: wfe\n" - "2: ldaxr %w0, [%2]\n" - " add %w0, %w0, #1\n" - " tbnz %w0, #31, 1b\n" - " stxr %w1, %w0, [%2]\n" - " cbnz %w1, 2b\n" - : "=&r" (tmp), "=&r" (tmp2) - : "r" (&rw->lock) - : "memory"); -} - -static inline void arch_read_unlock(arch_rwlock_t *rw) -{ - unsigned int tmp, tmp2; - - asm volatile( - "1: ldxr %w0, [%2]\n" - " sub %w0, %w0, #1\n" - " stlxr %w1, %w0, [%2]\n" - " cbnz %w1, 1b\n" - : "=&r" (tmp), "=&r" (tmp2) - : "r" (&rw->lock) - : "memory"); -} - -static inline int arch_read_trylock(arch_rwlock_t *rw) -{ - unsigned int tmp, tmp2 = 1; - - asm volatile( - " ldaxr %w0, [%2]\n" - " add %w0, %w0, #1\n" - " tbnz %w0, #31, 1f\n" - " stxr %w1, %w0, [%2]\n" - "1:\n" - : "=&r" (tmp), "+r" (tmp2) - : "r" (&rw->lock) - : "memory"); - - return !tmp2; -} - -/* read_can_lock - would read_trylock() succeed? */ -#define arch_read_can_lock(x) ((x)->lock < 0x80000000) - -#define arch_read_lock_flags(lock, flags) arch_read_lock(lock) -#define arch_write_lock_flags(lock, flags) arch_write_lock(lock) - -#define arch_spin_relax(lock) cpu_relax() -#define arch_read_relax(lock) cpu_relax() -#define arch_write_relax(lock) cpu_relax() - -#endif /* __ASM_SPINLOCK_H */ diff --git a/trunk/arch/arm64/include/asm/spinlock_types.h b/trunk/arch/arm64/include/asm/spinlock_types.h deleted file mode 100644 index 9a494346efed..000000000000 --- a/trunk/arch/arm64/include/asm/spinlock_types.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (C) 2012 ARM 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 __ASM_SPINLOCK_TYPES_H -#define __ASM_SPINLOCK_TYPES_H - -#if !defined(__LINUX_SPINLOCK_TYPES_H) && !defined(__ASM_SPINLOCK_H) -# error "please don't include this file directly" -#endif - -/* We only require natural alignment for exclusive accesses. */ -#define __lock_aligned - -typedef struct { - volatile unsigned int lock; -} arch_spinlock_t; - -#define __ARCH_SPIN_LOCK_UNLOCKED { 0 } - -typedef struct { - volatile unsigned int lock; -} arch_rwlock_t; - -#define __ARCH_RW_LOCK_UNLOCKED { 0 } - -#endif diff --git a/trunk/arch/arm64/include/asm/stacktrace.h b/trunk/arch/arm64/include/asm/stacktrace.h deleted file mode 100644 index 7318f6d54aa9..000000000000 --- a/trunk/arch/arm64/include/asm/stacktrace.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (C) 2012 ARM 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 __ASM_STACKTRACE_H -#define __ASM_STACKTRACE_H - -struct stackframe { - unsigned long fp; - unsigned long sp; - unsigned long pc; -}; - -extern int unwind_frame(struct stackframe *frame); -extern void walk_stackframe(struct stackframe *frame, - int (*fn)(struct stackframe *, void *), void *data); - -#endif /* __ASM_STACKTRACE_H */ diff --git a/trunk/arch/arm64/include/asm/stat.h b/trunk/arch/arm64/include/asm/stat.h deleted file mode 100644 index d87225cbead8..000000000000 --- a/trunk/arch/arm64/include/asm/stat.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (C) 2012 ARM 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 __ASM_STAT_H -#define __ASM_STAT_H - -#include - -#if defined(__KERNEL__) && defined(CONFIG_COMPAT) - -#include - -/* - * struct stat64 is needed for compat tasks only. Its definition is different - * from the generic struct stat64. - */ -struct stat64 { - compat_u64 st_dev; - unsigned char __pad0[4]; - -#define STAT64_HAS_BROKEN_ST_INO 1 - compat_ulong_t __st_ino; - compat_uint_t st_mode; - compat_uint_t st_nlink; - - compat_ulong_t st_uid; - compat_ulong_t st_gid; - - compat_u64 st_rdev; - unsigned char __pad3[4]; - - compat_s64 st_size; - compat_ulong_t st_blksize; - compat_u64 st_blocks; /* Number of 512-byte blocks allocated. */ - - compat_ulong_t st_atime; - compat_ulong_t st_atime_nsec; - - compat_ulong_t st_mtime; - compat_ulong_t st_mtime_nsec; - - compat_ulong_t st_ctime; - compat_ulong_t st_ctime_nsec; - - compat_u64 st_ino; -}; - -#endif - -#endif diff --git a/trunk/arch/arm64/include/asm/statfs.h b/trunk/arch/arm64/include/asm/statfs.h deleted file mode 100644 index 6f6219050978..000000000000 --- a/trunk/arch/arm64/include/asm/statfs.h +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (C) 2012 ARM 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 __ASM_STATFS_H -#define __ASM_STATFS_H - -#define ARCH_PACK_COMPAT_STATFS64 __attribute__((packed,aligned(4))) - -#include - -#endif diff --git a/trunk/arch/arm64/include/asm/syscall.h b/trunk/arch/arm64/include/asm/syscall.h deleted file mode 100644 index 89c047f9a971..000000000000 --- a/trunk/arch/arm64/include/asm/syscall.h +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright (C) 2012 ARM 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 __ASM_SYSCALL_H -#define __ASM_SYSCALL_H - -#include - - -static inline int syscall_get_nr(struct task_struct *task, - struct pt_regs *regs) -{ - return regs->syscallno; -} - -static inline void syscall_rollback(struct task_struct *task, - struct pt_regs *regs) -{ - regs->regs[0] = regs->orig_x0; -} - - -static inline long syscall_get_error(struct task_struct *task, - struct pt_regs *regs) -{ - unsigned long error = regs->regs[0]; - return IS_ERR_VALUE(error) ? error : 0; -} - -static inline long syscall_get_return_value(struct task_struct *task, - struct pt_regs *regs) -{ - return regs->regs[0]; -} - -static inline void syscall_set_return_value(struct task_struct *task, - struct pt_regs *regs, - int error, long val) -{ - regs->regs[0] = (long) error ? error : val; -} - -#define SYSCALL_MAX_ARGS 6 - -static inline void syscall_get_arguments(struct task_struct *task, - struct pt_regs *regs, - unsigned int i, unsigned int n, - unsigned long *args) -{ - if (i + n > SYSCALL_MAX_ARGS) { - unsigned long *args_bad = args + SYSCALL_MAX_ARGS - i; - unsigned int n_bad = n + i - SYSCALL_MAX_ARGS; - pr_warning("%s called with max args %d, handling only %d\n", - __func__, i + n, SYSCALL_MAX_ARGS); - memset(args_bad, 0, n_bad * sizeof(args[0])); - } - - if (i == 0) { - args[0] = regs->orig_x0; - args++; - i++; - n--; - } - - memcpy(args, ®s->regs[i], n * sizeof(args[0])); -} - -static inline void syscall_set_arguments(struct task_struct *task, - struct pt_regs *regs, - unsigned int i, unsigned int n, - const unsigned long *args) -{ - if (i + n > SYSCALL_MAX_ARGS) { - pr_warning("%s called with max args %d, handling only %d\n", - __func__, i + n, SYSCALL_MAX_ARGS); - n = SYSCALL_MAX_ARGS - i; - } - - if (i == 0) { - regs->orig_x0 = args[0]; - args++; - i++; - n--; - } - - memcpy(®s->regs[i], args, n * sizeof(args[0])); -} - -#endif /* __ASM_SYSCALL_H */ diff --git a/trunk/arch/arm64/include/asm/syscalls.h b/trunk/arch/arm64/include/asm/syscalls.h deleted file mode 100644 index 09ff33572aab..000000000000 --- a/trunk/arch/arm64/include/asm/syscalls.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (C) 2012 ARM 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 __ASM_SYSCALLS_H -#define __ASM_SYSCALLS_H - -#include -#include -#include - -/* - * System call wrappers implemented in kernel/entry.S. - */ -asmlinkage long sys_execve_wrapper(const char __user *filename, - const char __user *const __user *argv, - const char __user *const __user *envp); -asmlinkage long sys_clone_wrapper(unsigned long clone_flags, - unsigned long newsp, - void __user *parent_tid, - unsigned long tls_val, - void __user *child_tid); -asmlinkage long sys_rt_sigreturn_wrapper(void); -asmlinkage long sys_sigaltstack_wrapper(const stack_t __user *uss, - stack_t __user *uoss); - -#include - -#endif /* __ASM_SYSCALLS_H */ diff --git a/trunk/arch/arm64/include/asm/system_misc.h b/trunk/arch/arm64/include/asm/system_misc.h deleted file mode 100644 index 95e407255347..000000000000 --- a/trunk/arch/arm64/include/asm/system_misc.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Based on arch/arm/include/asm/system_misc.h - * - * Copyright (C) 2012 ARM 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 __ASM_SYSTEM_MISC_H -#define __ASM_SYSTEM_MISC_H - -#ifndef __ASSEMBLY__ - -#include -#include -#include - -struct pt_regs; - -void die(const char *msg, struct pt_regs *regs, int err); - -struct siginfo; -void arm64_notify_die(const char *str, struct pt_regs *regs, - struct siginfo *info, int err); - -void hook_debug_fault_code(int nr, int (*fn)(unsigned long, unsigned int, - struct pt_regs *), - int sig, int code, const char *name); - -struct mm_struct; -extern void show_pte(struct mm_struct *mm, unsigned long addr); -extern void __show_regs(struct pt_regs *); - -void soft_restart(unsigned long); -extern void (*pm_restart)(const char *cmd); - -#define UDBG_UNDEFINED (1 << 0) -#define UDBG_SYSCALL (1 << 1) -#define UDBG_BADABORT (1 << 2) -#define UDBG_SEGV (1 << 3) -#define UDBG_BUS (1 << 4) - -#endif /* __ASSEMBLY__ */ - -#endif /* __ASM_SYSTEM_MISC_H */ diff --git a/trunk/arch/arm64/include/asm/thread_info.h b/trunk/arch/arm64/include/asm/thread_info.h deleted file mode 100644 index 3659e460071d..000000000000 --- a/trunk/arch/arm64/include/asm/thread_info.h +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Based on arch/arm/include/asm/thread_info.h - * - * Copyright (C) 2002 Russell King. - * Copyright (C) 2012 ARM 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 __ASM_THREAD_INFO_H -#define __ASM_THREAD_INFO_H - -#ifdef __KERNEL__ - -#include - -#ifndef CONFIG_ARM64_64K_PAGES -#define THREAD_SIZE_ORDER 1 -#endif - -#define THREAD_SIZE 8192 -#define THREAD_START_SP (THREAD_SIZE - 16) - -#ifndef __ASSEMBLY__ - -struct task_struct; -struct exec_domain; - -#include - -typedef unsigned long mm_segment_t; - -/* - * low level task data that entry.S needs immediate access to. - * __switch_to() assumes cpu_context follows immediately after cpu_domain. - */ -struct thread_info { - unsigned long flags; /* low level flags */ - mm_segment_t addr_limit; /* address limit */ - struct task_struct *task; /* main task structure */ - struct exec_domain *exec_domain; /* execution domain */ - struct restart_block restart_block; - int preempt_count; /* 0 => preemptable, <0 => bug */ - int cpu; /* cpu */ -}; - -#define INIT_THREAD_INFO(tsk) \ -{ \ - .task = &tsk, \ - .exec_domain = &default_exec_domain, \ - .flags = 0, \ - .preempt_count = INIT_PREEMPT_COUNT, \ - .addr_limit = KERNEL_DS, \ - .restart_block = { \ - .fn = do_no_restart_syscall, \ - }, \ -} - -#define init_thread_info (init_thread_union.thread_info) -#define init_stack (init_thread_union.stack) - -/* - * how to get the thread information struct from C - */ -static inline struct thread_info *current_thread_info(void) __attribute_const__; - -static inline struct thread_info *current_thread_info(void) -{ - register unsigned long sp asm ("sp"); - return (struct thread_info *)(sp & ~(THREAD_SIZE - 1)); -} - -#define thread_saved_pc(tsk) \ - ((unsigned long)(tsk->thread.cpu_context.pc)) -#define thread_saved_sp(tsk) \ - ((unsigned long)(tsk->thread.cpu_context.sp)) -#define thread_saved_fp(tsk) \ - ((unsigned long)(tsk->thread.cpu_context.fp)) - -#endif - -/* - * We use bit 30 of the preempt_count to indicate that kernel - * preemption is occurring. See . - */ -#define PREEMPT_ACTIVE 0x40000000 - -/* - * thread information flags: - * TIF_SYSCALL_TRACE - syscall trace active - * TIF_SIGPENDING - signal pending - * TIF_NEED_RESCHED - rescheduling necessary - * TIF_NOTIFY_RESUME - callback before returning to user - * TIF_USEDFPU - FPU was used by this task this quantum (SMP) - * TIF_POLLING_NRFLAG - true if poll_idle() is polling TIF_NEED_RESCHED - */ -#define TIF_SIGPENDING 0 -#define TIF_NEED_RESCHED 1 -#define TIF_NOTIFY_RESUME 2 /* callback before returning to user */ -#define TIF_SYSCALL_TRACE 8 -#define TIF_POLLING_NRFLAG 16 -#define TIF_MEMDIE 18 /* is terminating due to OOM killer */ -#define TIF_FREEZE 19 -#define TIF_RESTORE_SIGMASK 20 -#define TIF_SINGLESTEP 21 -#define TIF_32BIT 22 /* 32bit process */ -#define TIF_SWITCH_MM 23 /* deferred switch_mm */ - -#define _TIF_SIGPENDING (1 << TIF_SIGPENDING) -#define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED) -#define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME) -#define _TIF_32BIT (1 << TIF_32BIT) - -#define _TIF_WORK_MASK (_TIF_NEED_RESCHED | _TIF_SIGPENDING | \ - _TIF_NOTIFY_RESUME) - -#endif /* __KERNEL__ */ -#endif /* __ASM_THREAD_INFO_H */ diff --git a/trunk/arch/arm64/include/asm/timex.h b/trunk/arch/arm64/include/asm/timex.h deleted file mode 100644 index b24a31a7e2c9..000000000000 --- a/trunk/arch/arm64/include/asm/timex.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (C) 2012 ARM 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 __ASM_TIMEX_H -#define __ASM_TIMEX_H - -/* - * Use the current timer as a cycle counter since this is what we use for - * the delay loop. - */ -#define get_cycles() ({ cycles_t c; read_current_timer(&c); c; }) - -#include - -#define ARCH_HAS_READ_CURRENT_TIMER - -#endif diff --git a/trunk/arch/arm64/include/asm/tlb.h b/trunk/arch/arm64/include/asm/tlb.h deleted file mode 100644 index 654f0968030b..000000000000 --- a/trunk/arch/arm64/include/asm/tlb.h +++ /dev/null @@ -1,190 +0,0 @@ -/* - * Based on arch/arm/include/asm/tlb.h - * - * Copyright (C) 2002 Russell King - * Copyright (C) 2012 ARM 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 __ASM_TLB_H -#define __ASM_TLB_H - -#include -#include - -#include -#include - -#define MMU_GATHER_BUNDLE 8 - -/* - * TLB handling. This allows us to remove pages from the page - * tables, and efficiently handle the TLB issues. - */ -struct mmu_gather { - struct mm_struct *mm; - unsigned int fullmm; - struct vm_area_struct *vma; - unsigned long range_start; - unsigned long range_end; - unsigned int nr; - unsigned int max; - struct page **pages; - struct page *local[MMU_GATHER_BUNDLE]; -}; - -/* - * This is unnecessarily complex. There's three ways the TLB shootdown - * code is used: - * 1. Unmapping a range of vmas. See zap_page_range(), unmap_region(). - * tlb->fullmm = 0, and tlb_start_vma/tlb_end_vma will be called. - * tlb->vma will be non-NULL. - * 2. Unmapping all vmas. See exit_mmap(). - * tlb->fullmm = 1, and tlb_start_vma/tlb_end_vma will be called. - * tlb->vma will be non-NULL. Additionally, page tables will be freed. - * 3. Unmapping argument pages. See shift_arg_pages(). - * tlb->fullmm = 0, but tlb_start_vma/tlb_end_vma will not be called. - * tlb->vma will be NULL. - */ -static inline void tlb_flush(struct mmu_gather *tlb) -{ - if (tlb->fullmm || !tlb->vma) - flush_tlb_mm(tlb->mm); - else if (tlb->range_end > 0) { - flush_tlb_range(tlb->vma, tlb->range_start, tlb->range_end); - tlb->range_start = TASK_SIZE; - tlb->range_end = 0; - } -} - -static inline void tlb_add_flush(struct mmu_gather *tlb, unsigned long addr) -{ - if (!tlb->fullmm) { - if (addr < tlb->range_start) - tlb->range_start = addr; - if (addr + PAGE_SIZE > tlb->range_end) - tlb->range_end = addr + PAGE_SIZE; - } -} - -static inline void __tlb_alloc_page(struct mmu_gather *tlb) -{ - unsigned long addr = __get_free_pages(GFP_NOWAIT | __GFP_NOWARN, 0); - - if (addr) { - tlb->pages = (void *)addr; - tlb->max = PAGE_SIZE / sizeof(struct page *); - } -} - -static inline void tlb_flush_mmu(struct mmu_gather *tlb) -{ - tlb_flush(tlb); - free_pages_and_swap_cache(tlb->pages, tlb->nr); - tlb->nr = 0; - if (tlb->pages == tlb->local) - __tlb_alloc_page(tlb); -} - -static inline void -tlb_gather_mmu(struct mmu_gather *tlb, struct mm_struct *mm, unsigned int fullmm) -{ - tlb->mm = mm; - tlb->fullmm = fullmm; - tlb->vma = NULL; - tlb->max = ARRAY_SIZE(tlb->local); - tlb->pages = tlb->local; - tlb->nr = 0; - __tlb_alloc_page(tlb); -} - -static inline void -tlb_finish_mmu(struct mmu_gather *tlb, unsigned long start, unsigned long end) -{ - tlb_flush_mmu(tlb); - - /* keep the page table cache within bounds */ - check_pgt_cache(); - - if (tlb->pages != tlb->local) - free_pages((unsigned long)tlb->pages, 0); -} - -/* - * Memorize the range for the TLB flush. - */ -static inline void -tlb_remove_tlb_entry(struct mmu_gather *tlb, pte_t *ptep, unsigned long addr) -{ - tlb_add_flush(tlb, addr); -} - -/* - * In the case of tlb vma handling, we can optimise these away in the - * case where we're doing a full MM flush. When we're doing a munmap, - * the vmas are adjusted to only cover the region to be torn down. - */ -static inline void -tlb_start_vma(struct mmu_gather *tlb, struct vm_area_struct *vma) -{ - if (!tlb->fullmm) { - tlb->vma = vma; - tlb->range_start = TASK_SIZE; - tlb->range_end = 0; - } -} - -static inline void -tlb_end_vma(struct mmu_gather *tlb, struct vm_area_struct *vma) -{ - if (!tlb->fullmm) - tlb_flush(tlb); -} - -static inline int __tlb_remove_page(struct mmu_gather *tlb, struct page *page) -{ - tlb->pages[tlb->nr++] = page; - VM_BUG_ON(tlb->nr > tlb->max); - return tlb->max - tlb->nr; -} - -static inline void tlb_remove_page(struct mmu_gather *tlb, struct page *page) -{ - if (!__tlb_remove_page(tlb, page)) - tlb_flush_mmu(tlb); -} - -static inline void __pte_free_tlb(struct mmu_gather *tlb, pgtable_t pte, - unsigned long addr) -{ - pgtable_page_dtor(pte); - tlb_add_flush(tlb, addr); - tlb_remove_page(tlb, pte); -} - -#ifndef CONFIG_ARM64_64K_PAGES -static inline void __pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmdp, - unsigned long addr) -{ - tlb_add_flush(tlb, addr); - tlb_remove_page(tlb, virt_to_page(pmdp)); -} -#endif - -#define pte_free_tlb(tlb, ptep, addr) __pte_free_tlb(tlb, ptep, addr) -#define pmd_free_tlb(tlb, pmdp, addr) __pmd_free_tlb(tlb, pmdp, addr) -#define pud_free_tlb(tlb, pudp, addr) pud_free((tlb)->mm, pudp) - -#define tlb_migrate_finish(mm) do { } while (0) - -#endif diff --git a/trunk/arch/arm64/include/asm/tlbflush.h b/trunk/arch/arm64/include/asm/tlbflush.h deleted file mode 100644 index 122d6320f745..000000000000 --- a/trunk/arch/arm64/include/asm/tlbflush.h +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Based on arch/arm/include/asm/tlbflush.h - * - * Copyright (C) 1999-2003 Russell King - * Copyright (C) 2012 ARM 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 __ASM_TLBFLUSH_H -#define __ASM_TLBFLUSH_H - -#ifndef __ASSEMBLY__ - -#include -#include - -extern void __cpu_flush_user_tlb_range(unsigned long, unsigned long, struct vm_area_struct *); -extern void __cpu_flush_kern_tlb_range(unsigned long, unsigned long); - -extern struct cpu_tlb_fns cpu_tlb; - -/* - * TLB Management - * ============== - * - * The arch/arm64/mm/tlb.S files implement these methods. - * - * The TLB specific code is expected to perform whatever tests it needs - * to determine if it should invalidate the TLB for each call. Start - * addresses are inclusive and end addresses are exclusive; it is safe to - * round these addresses down. - * - * flush_tlb_all() - * - * Invalidate the entire TLB. - * - * flush_tlb_mm(mm) - * - * Invalidate all TLB entries in a particular address space. - * - mm - mm_struct describing address space - * - * flush_tlb_range(mm,start,end) - * - * Invalidate a range of TLB entries in the specified address - * space. - * - mm - mm_struct describing address space - * - start - start address (may not be aligned) - * - end - end address (exclusive, may not be aligned) - * - * flush_tlb_page(vaddr,vma) - * - * Invalidate the specified page in the specified address range. - * - vaddr - virtual address (may not be aligned) - * - vma - vma_struct describing address range - * - * flush_kern_tlb_page(kaddr) - * - * Invalidate the TLB entry for the specified page. The address - * will be in the kernels virtual memory space. Current uses - * only require the D-TLB to be invalidated. - * - kaddr - Kernel virtual memory address - */ -static inline void flush_tlb_all(void) -{ - dsb(); - asm("tlbi vmalle1is"); - dsb(); - isb(); -} - -static inline void flush_tlb_mm(struct mm_struct *mm) -{ - unsigned long asid = (unsigned long)ASID(mm) << 48; - - dsb(); - asm("tlbi aside1is, %0" : : "r" (asid)); - dsb(); -} - -static inline void flush_tlb_page(struct vm_area_struct *vma, - unsigned long uaddr) -{ - unsigned long addr = uaddr >> 12 | - ((unsigned long)ASID(vma->vm_mm) << 48); - - dsb(); - asm("tlbi vae1is, %0" : : "r" (addr)); - dsb(); -} - -/* - * Convert calls to our calling convention. - */ -#define flush_tlb_range(vma,start,end) __cpu_flush_user_tlb_range(start,end,vma) -#define flush_tlb_kernel_range(s,e) __cpu_flush_kern_tlb_range(s,e) - -/* - * On AArch64, the cache coherency is handled via the set_pte_at() function. - */ -static inline void update_mmu_cache(struct vm_area_struct *vma, - unsigned long addr, pte_t *ptep) -{ - /* - * set_pte() does not have a DSB, so make sure that the page table - * write is visible. - */ - dsb(); -} - -#endif - -#endif diff --git a/trunk/arch/arm64/include/asm/traps.h b/trunk/arch/arm64/include/asm/traps.h deleted file mode 100644 index 10ca8ff93cc2..000000000000 --- a/trunk/arch/arm64/include/asm/traps.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Based on arch/arm/include/asm/traps.h - * - * Copyright (C) 2012 ARM 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 __ASM_TRAP_H -#define __ASM_TRAP_H - -static inline int in_exception_text(unsigned long ptr) -{ - extern char __exception_text_start[]; - extern char __exception_text_end[]; - - return ptr >= (unsigned long)&__exception_text_start && - ptr < (unsigned long)&__exception_text_end; -} - -#endif diff --git a/trunk/arch/arm64/include/asm/uaccess.h b/trunk/arch/arm64/include/asm/uaccess.h deleted file mode 100644 index 008f8481da65..000000000000 --- a/trunk/arch/arm64/include/asm/uaccess.h +++ /dev/null @@ -1,297 +0,0 @@ -/* - * Based on arch/arm/include/asm/uaccess.h - * - * Copyright (C) 2012 ARM 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 __ASM_UACCESS_H -#define __ASM_UACCESS_H - -/* - * User space memory access functions - */ -#include -#include - -#include -#include -#include -#include - -#define VERIFY_READ 0 -#define VERIFY_WRITE 1 - -/* - * The exception table consists of pairs of addresses: the first is the - * address of an instruction that is allowed to fault, and the second is - * the address at which the program should continue. No registers are - * modified, so it is entirely up to the continuation code to figure out - * what to do. - * - * All the routines below use bits of fixup code that are out of line - * with the main instruction path. This means when everything is well, - * we don't even have to jump over them. Further, they do not intrude - * on our cache or tlb entries. - */ - -struct exception_table_entry -{ - unsigned long insn, fixup; -}; - -extern int fixup_exception(struct pt_regs *regs); - -#define KERNEL_DS (-1UL) -#define get_ds() (KERNEL_DS) - -#define USER_DS TASK_SIZE_64 -#define get_fs() (current_thread_info()->addr_limit) - -static inline void set_fs(mm_segment_t fs) -{ - current_thread_info()->addr_limit = fs; -} - -#define segment_eq(a,b) ((a) == (b)) - -/* - * Return 1 if addr < current->addr_limit, 0 otherwise. - */ -#define __addr_ok(addr) \ -({ \ - unsigned long flag; \ - asm("cmp %1, %0; cset %0, lo" \ - : "=&r" (flag) \ - : "r" (addr), "0" (current_thread_info()->addr_limit) \ - : "cc"); \ - flag; \ -}) - -/* - * Test whether a block of memory is a valid user space address. - * Returns 1 if the range is valid, 0 otherwise. - * - * This is equivalent to the following test: - * (u65)addr + (u65)size < (u65)current->addr_limit - * - * This needs 65-bit arithmetic. - */ -#define __range_ok(addr, size) \ -({ \ - unsigned long flag, roksum; \ - __chk_user_ptr(addr); \ - asm("adds %1, %1, %3; ccmp %1, %4, #2, cc; cset %0, cc" \ - : "=&r" (flag), "=&r" (roksum) \ - : "1" (addr), "Ir" (size), \ - "r" (current_thread_info()->addr_limit) \ - : "cc"); \ - flag; \ -}) - -#define access_ok(type, addr, size) __range_ok(addr, size) - -/* - * The "__xxx" versions of the user access functions do not verify the address - * space - it must have been done previously with a separate "access_ok()" - * call. - * - * The "__xxx_error" versions set the third argument to -EFAULT if an error - * occurs, and leave it unchanged on success. - */ -#define __get_user_asm(instr, reg, x, addr, err) \ - asm volatile( \ - "1: " instr " " reg "1, [%2]\n" \ - "2:\n" \ - " .section .fixup, \"ax\"\n" \ - " .align 2\n" \ - "3: mov %w0, %3\n" \ - " mov %1, #0\n" \ - " b 2b\n" \ - " .previous\n" \ - " .section __ex_table,\"a\"\n" \ - " .align 3\n" \ - " .quad 1b, 3b\n" \ - " .previous" \ - : "+r" (err), "=&r" (x) \ - : "r" (addr), "i" (-EFAULT)) - -#define __get_user_err(x, ptr, err) \ -do { \ - unsigned long __gu_val; \ - __chk_user_ptr(ptr); \ - switch (sizeof(*(ptr))) { \ - case 1: \ - __get_user_asm("ldrb", "%w", __gu_val, (ptr), (err)); \ - break; \ - case 2: \ - __get_user_asm("ldrh", "%w", __gu_val, (ptr), (err)); \ - break; \ - case 4: \ - __get_user_asm("ldr", "%w", __gu_val, (ptr), (err)); \ - break; \ - case 8: \ - __get_user_asm("ldr", "%", __gu_val, (ptr), (err)); \ - break; \ - default: \ - BUILD_BUG(); \ - } \ - (x) = (__typeof__(*(ptr)))__gu_val; \ -} while (0) - -#define __get_user(x, ptr) \ -({ \ - int __gu_err = 0; \ - __get_user_err((x), (ptr), __gu_err); \ - __gu_err; \ -}) - -#define __get_user_error(x, ptr, err) \ -({ \ - __get_user_err((x), (ptr), (err)); \ - (void)0; \ -}) - -#define __get_user_unaligned __get_user - -#define get_user(x, ptr) \ -({ \ - might_sleep(); \ - access_ok(VERIFY_READ, (ptr), sizeof(*(ptr))) ? \ - __get_user((x), (ptr)) : \ - ((x) = 0, -EFAULT); \ -}) - -#define __put_user_asm(instr, reg, x, addr, err) \ - asm volatile( \ - "1: " instr " " reg "1, [%2]\n" \ - "2:\n" \ - " .section .fixup,\"ax\"\n" \ - " .align 2\n" \ - "3: mov %w0, %3\n" \ - " b 2b\n" \ - " .previous\n" \ - " .section __ex_table,\"a\"\n" \ - " .align 3\n" \ - " .quad 1b, 3b\n" \ - " .previous" \ - : "+r" (err) \ - : "r" (x), "r" (addr), "i" (-EFAULT)) - -#define __put_user_err(x, ptr, err) \ -do { \ - __typeof__(*(ptr)) __pu_val = (x); \ - __chk_user_ptr(ptr); \ - switch (sizeof(*(ptr))) { \ - case 1: \ - __put_user_asm("strb", "%w", __pu_val, (ptr), (err)); \ - break; \ - case 2: \ - __put_user_asm("strh", "%w", __pu_val, (ptr), (err)); \ - break; \ - case 4: \ - __put_user_asm("str", "%w", __pu_val, (ptr), (err)); \ - break; \ - case 8: \ - __put_user_asm("str", "%", __pu_val, (ptr), (err)); \ - break; \ - default: \ - BUILD_BUG(); \ - } \ -} while (0) - -#define __put_user(x, ptr) \ -({ \ - int __pu_err = 0; \ - __put_user_err((x), (ptr), __pu_err); \ - __pu_err; \ -}) - -#define __put_user_error(x, ptr, err) \ -({ \ - __put_user_err((x), (ptr), (err)); \ - (void)0; \ -}) - -#define __put_user_unaligned __put_user - -#define put_user(x, ptr) \ -({ \ - might_sleep(); \ - access_ok(VERIFY_WRITE, (ptr), sizeof(*(ptr))) ? \ - __put_user((x), (ptr)) : \ - -EFAULT; \ -}) - -extern unsigned long __must_check __copy_from_user(void *to, const void __user *from, unsigned long n); -extern unsigned long __must_check __copy_to_user(void __user *to, const void *from, unsigned long n); -extern unsigned long __must_check __copy_in_user(void __user *to, const void __user *from, unsigned long n); -extern unsigned long __must_check __clear_user(void __user *addr, unsigned long n); - -extern unsigned long __must_check __strncpy_from_user(char *to, const char __user *from, unsigned long count); -extern unsigned long __must_check __strnlen_user(const char __user *s, long n); - -static inline unsigned long __must_check copy_from_user(void *to, const void __user *from, unsigned long n) -{ - if (access_ok(VERIFY_READ, from, n)) - n = __copy_from_user(to, from, n); - else /* security hole - plug it */ - memset(to, 0, n); - return n; -} - -static inline unsigned long __must_check copy_to_user(void __user *to, const void *from, unsigned long n) -{ - if (access_ok(VERIFY_WRITE, to, n)) - n = __copy_to_user(to, from, n); - return n; -} - -static inline unsigned long __must_check copy_in_user(void __user *to, const void __user *from, unsigned long n) -{ - if (access_ok(VERIFY_READ, from, n) && access_ok(VERIFY_WRITE, to, n)) - n = __copy_in_user(to, from, n); - return n; -} - -#define __copy_to_user_inatomic __copy_to_user -#define __copy_from_user_inatomic __copy_from_user - -static inline unsigned long __must_check clear_user(void __user *to, unsigned long n) -{ - if (access_ok(VERIFY_WRITE, to, n)) - n = __clear_user(to, n); - return n; -} - -static inline long __must_check strncpy_from_user(char *dst, const char __user *src, long count) -{ - long res = -EFAULT; - if (access_ok(VERIFY_READ, src, 1)) - res = __strncpy_from_user(dst, src, count); - return res; -} - -#define strlen_user(s) strnlen_user(s, ~0UL >> 1) - -static inline long __must_check strnlen_user(const char __user *s, long n) -{ - unsigned long res = 0; - - if (__addr_ok(s)) - res = __strnlen_user(s, n); - - return res; -} - -#endif /* __ASM_UACCESS_H */ diff --git a/trunk/arch/arm64/include/asm/ucontext.h b/trunk/arch/arm64/include/asm/ucontext.h deleted file mode 100644 index bde960720892..000000000000 --- a/trunk/arch/arm64/include/asm/ucontext.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (C) 2012 ARM 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 __ASM_UCONTEXT_H -#define __ASM_UCONTEXT_H - -struct ucontext { - unsigned long uc_flags; - struct ucontext *uc_link; - stack_t uc_stack; - sigset_t uc_sigmask; - /* glibc uses a 1024-bit sigset_t */ - __u8 __unused[(1024 - sizeof(sigset_t)) / 8]; - /* last for future expansion */ - struct sigcontext uc_mcontext; -}; - -#endif /* __ASM_UCONTEXT_H */ diff --git a/trunk/arch/arm64/include/asm/unistd.h b/trunk/arch/arm64/include/asm/unistd.h deleted file mode 100644 index fe18a683274f..000000000000 --- a/trunk/arch/arm64/include/asm/unistd.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (C) 2012 ARM 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 . - */ -#if !defined(__ASM_UNISTD_H) || defined(__SYSCALL) -#define __ASM_UNISTD_H - -#ifndef __SYSCALL_COMPAT -#include -#endif - -#if defined(__KERNEL__) && defined(CONFIG_COMPAT) -#include -#endif - -#endif /* __ASM_UNISTD_H */ diff --git a/trunk/arch/arm64/include/asm/unistd32.h b/trunk/arch/arm64/include/asm/unistd32.h deleted file mode 100644 index a50405f5ee42..000000000000 --- a/trunk/arch/arm64/include/asm/unistd32.h +++ /dev/null @@ -1,758 +0,0 @@ -/* - * Based on arch/arm/include/asm/unistd.h - * - * Copyright (C) 2001-2005 Russell King - * Copyright (C) 2012 ARM 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 . - */ -#if !defined(__ASM_UNISTD32_H) || defined(__SYSCALL) -#define __ASM_UNISTD32_H - -#ifndef __SYSCALL -#define __SYSCALL(x, y) -#endif - -/* - * This file contains the system call numbers. - */ - -#ifdef __SYSCALL_COMPAT - -#define __NR_restart_syscall 0 -__SYSCALL(__NR_restart_syscall, sys_restart_syscall) -#define __NR_exit 1 -__SYSCALL(__NR_exit, sys_exit) -#define __NR_fork 2 -__SYSCALL(__NR_fork, sys_fork) -#define __NR_read 3 -__SYSCALL(__NR_read, sys_read) -#define __NR_write 4 -__SYSCALL(__NR_write, sys_write) -#define __NR_open 5 -__SYSCALL(__NR_open, sys_open) -#define __NR_close 6 -__SYSCALL(__NR_close, sys_close) -__SYSCALL(7, sys_ni_syscall) /* 7 was sys_waitpid */ -#define __NR_creat 8 -__SYSCALL(__NR_creat, sys_creat) -#define __NR_link 9 -__SYSCALL(__NR_link, sys_link) -#define __NR_unlink 10 -__SYSCALL(__NR_unlink, sys_unlink) -#define __NR_execve 11 -__SYSCALL(__NR_execve, sys_execve) -#define __NR_chdir 12 -__SYSCALL(__NR_chdir, sys_chdir) -__SYSCALL(13, sys_ni_syscall) /* 13 was sys_time */ -#define __NR_mknod 14 -__SYSCALL(__NR_mknod, sys_mknod) -#define __NR_chmod 15 -__SYSCALL(__NR_chmod, sys_chmod) -#define __NR_lchown 16 -__SYSCALL(__NR_lchown, sys_lchown16) -__SYSCALL(17, sys_ni_syscall) /* 17 was sys_break */ -__SYSCALL(18, sys_ni_syscall) /* 18 was sys_stat */ -#define __NR_lseek 19 -__SYSCALL(__NR_lseek, sys_lseek) -#define __NR_getpid 20 -__SYSCALL(__NR_getpid, sys_getpid) -#define __NR_mount 21 -__SYSCALL(__NR_mount, sys_mount) -__SYSCALL(22, sys_ni_syscall) /* 22 was sys_umount */ -#define __NR_setuid 23 -__SYSCALL(__NR_setuid, sys_setuid16) -#define __NR_getuid 24 -__SYSCALL(__NR_getuid, sys_getuid16) -__SYSCALL(25, sys_ni_syscall) /* 25 was sys_stime */ -#define __NR_ptrace 26 -__SYSCALL(__NR_ptrace, sys_ptrace) -__SYSCALL(27, sys_ni_syscall) /* 27 was sys_alarm */ -__SYSCALL(28, sys_ni_syscall) /* 28 was sys_fstat */ -#define __NR_pause 29 -__SYSCALL(__NR_pause, sys_pause) -__SYSCALL(30, sys_ni_syscall) /* 30 was sys_utime */ -__SYSCALL(31, sys_ni_syscall) /* 31 was sys_stty */ -__SYSCALL(32, sys_ni_syscall) /* 32 was sys_gtty */ -#define __NR_access 33 -__SYSCALL(__NR_access, sys_access) -#define __NR_nice 34 -__SYSCALL(__NR_nice, sys_nice) -__SYSCALL(35, sys_ni_syscall) /* 35 was sys_ftime */ -#define __NR_sync 36 -__SYSCALL(__NR_sync, sys_sync) -#define __NR_kill 37 -__SYSCALL(__NR_kill, sys_kill) -#define __NR_rename 38 -__SYSCALL(__NR_rename, sys_rename) -#define __NR_mkdir 39 -__SYSCALL(__NR_mkdir, sys_mkdir) -#define __NR_rmdir 40 -__SYSCALL(__NR_rmdir, sys_rmdir) -#define __NR_dup 41 -__SYSCALL(__NR_dup, sys_dup) -#define __NR_pipe 42 -__SYSCALL(__NR_pipe, sys_pipe) -#define __NR_times 43 -__SYSCALL(__NR_times, sys_times) -__SYSCALL(44, sys_ni_syscall) /* 44 was sys_prof */ -#define __NR_brk 45 -__SYSCALL(__NR_brk, sys_brk) -#define __NR_setgid 46 -__SYSCALL(__NR_setgid, sys_setgid16) -#define __NR_getgid 47 -__SYSCALL(__NR_getgid, sys_getgid16) -__SYSCALL(48, sys_ni_syscall) /* 48 was sys_signal */ -#define __NR_geteuid 49 -__SYSCALL(__NR_geteuid, sys_geteuid16) -#define __NR_getegid 50 -__SYSCALL(__NR_getegid, sys_getegid16) -#define __NR_acct 51 -__SYSCALL(__NR_acct, sys_acct) -#define __NR_umount2 52 -__SYSCALL(__NR_umount2, sys_umount) -__SYSCALL(53, sys_ni_syscall) /* 53 was sys_lock */ -#define __NR_ioctl 54 -__SYSCALL(__NR_ioctl, sys_ioctl) -#define __NR_fcntl 55 -__SYSCALL(__NR_fcntl, sys_fcntl) -__SYSCALL(56, sys_ni_syscall) /* 56 was sys_mpx */ -#define __NR_setpgid 57 -__SYSCALL(__NR_setpgid, sys_setpgid) -__SYSCALL(58, sys_ni_syscall) /* 58 was sys_ulimit */ -__SYSCALL(59, sys_ni_syscall) /* 59 was sys_olduname */ -#define __NR_umask 60 -__SYSCALL(__NR_umask, sys_umask) -#define __NR_chroot 61 -__SYSCALL(__NR_chroot, sys_chroot) -#define __NR_ustat 62 -__SYSCALL(__NR_ustat, sys_ustat) -#define __NR_dup2 63 -__SYSCALL(__NR_dup2, sys_dup2) -#define __NR_getppid 64 -__SYSCALL(__NR_getppid, sys_getppid) -#define __NR_getpgrp 65 -__SYSCALL(__NR_getpgrp, sys_getpgrp) -#define __NR_setsid 66 -__SYSCALL(__NR_setsid, sys_setsid) -#define __NR_sigaction 67 -__SYSCALL(__NR_sigaction, sys_sigaction) -__SYSCALL(68, sys_ni_syscall) /* 68 was sys_sgetmask */ -__SYSCALL(69, sys_ni_syscall) /* 69 was sys_ssetmask */ -#define __NR_setreuid 70 -__SYSCALL(__NR_setreuid, sys_setreuid16) -#define __NR_setregid 71 -__SYSCALL(__NR_setregid, sys_setregid16) -#define __NR_sigsuspend 72 -__SYSCALL(__NR_sigsuspend, sys_sigsuspend) -#define __NR_sigpending 73 -__SYSCALL(__NR_sigpending, sys_sigpending) -#define __NR_sethostname 74 -__SYSCALL(__NR_sethostname, sys_sethostname) -#define __NR_setrlimit 75 -__SYSCALL(__NR_setrlimit, sys_setrlimit) -__SYSCALL(76, sys_ni_syscall) /* 76 was sys_getrlimit */ -#define __NR_getrusage 77 -__SYSCALL(__NR_getrusage, sys_getrusage) -#define __NR_gettimeofday 78 -__SYSCALL(__NR_gettimeofday, sys_gettimeofday) -#define __NR_settimeofday 79 -__SYSCALL(__NR_settimeofday, sys_settimeofday) -#define __NR_getgroups 80 -__SYSCALL(__NR_getgroups, sys_getgroups16) -#define __NR_setgroups 81 -__SYSCALL(__NR_setgroups, sys_setgroups16) -__SYSCALL(82, sys_ni_syscall) /* 82 was sys_select */ -#define __NR_symlink 83 -__SYSCALL(__NR_symlink, sys_symlink) -__SYSCALL(84, sys_ni_syscall) /* 84 was sys_lstat */ -#define __NR_readlink 85 -__SYSCALL(__NR_readlink, sys_readlink) -#define __NR_uselib 86 -__SYSCALL(__NR_uselib, sys_uselib) -#define __NR_swapon 87 -__SYSCALL(__NR_swapon, sys_swapon) -#define __NR_reboot 88 -__SYSCALL(__NR_reboot, sys_reboot) -__SYSCALL(89, sys_ni_syscall) /* 89 was sys_readdir */ -__SYSCALL(90, sys_ni_syscall) /* 90 was sys_mmap */ -#define __NR_munmap 91 -__SYSCALL(__NR_munmap, sys_munmap) -#define __NR_truncate 92 -__SYSCALL(__NR_truncate, sys_truncate) -#define __NR_ftruncate 93 -__SYSCALL(__NR_ftruncate, sys_ftruncate) -#define __NR_fchmod 94 -__SYSCALL(__NR_fchmod, sys_fchmod) -#define __NR_fchown 95 -__SYSCALL(__NR_fchown, sys_fchown16) -#define __NR_getpriority 96 -__SYSCALL(__NR_getpriority, sys_getpriority) -#define __NR_setpriority 97 -__SYSCALL(__NR_setpriority, sys_setpriority) -__SYSCALL(98, sys_ni_syscall) /* 98 was sys_profil */ -#define __NR_statfs 99 -__SYSCALL(__NR_statfs, sys_statfs) -#define __NR_fstatfs 100 -__SYSCALL(__NR_fstatfs, sys_fstatfs) -__SYSCALL(101, sys_ni_syscall) /* 101 was sys_ioperm */ -__SYSCALL(102, sys_ni_syscall) /* 102 was sys_socketcall */ -#define __NR_syslog 103 -__SYSCALL(__NR_syslog, sys_syslog) -#define __NR_setitimer 104 -__SYSCALL(__NR_setitimer, sys_setitimer) -#define __NR_getitimer 105 -__SYSCALL(__NR_getitimer, sys_getitimer) -#define __NR_stat 106 -__SYSCALL(__NR_stat, sys_newstat) -#define __NR_lstat 107 -__SYSCALL(__NR_lstat, sys_newlstat) -#define __NR_fstat 108 -__SYSCALL(__NR_fstat, sys_newfstat) -__SYSCALL(109, sys_ni_syscall) /* 109 was sys_uname */ -__SYSCALL(110, sys_ni_syscall) /* 110 was sys_iopl */ -#define __NR_vhangup 111 -__SYSCALL(__NR_vhangup, sys_vhangup) -__SYSCALL(112, sys_ni_syscall) /* 112 was sys_idle */ -__SYSCALL(113, sys_ni_syscall) /* 113 was sys_syscall */ -#define __NR_wait4 114 -__SYSCALL(__NR_wait4, sys_wait4) -#define __NR_swapoff 115 -__SYSCALL(__NR_swapoff, sys_swapoff) -#define __NR_sysinfo 116 -__SYSCALL(__NR_sysinfo, sys_sysinfo) -__SYSCALL(117, sys_ni_syscall) /* 117 was sys_ipc */ -#define __NR_fsync 118 -__SYSCALL(__NR_fsync, sys_fsync) -#define __NR_sigreturn 119 -__SYSCALL(__NR_sigreturn, sys_sigreturn) -#define __NR_clone 120 -__SYSCALL(__NR_clone, sys_clone) -#define __NR_setdomainname 121 -__SYSCALL(__NR_setdomainname, sys_setdomainname) -#define __NR_uname 122 -__SYSCALL(__NR_uname, sys_newuname) -__SYSCALL(123, sys_ni_syscall) /* 123 was sys_modify_ldt */ -#define __NR_adjtimex 124 -__SYSCALL(__NR_adjtimex, sys_adjtimex) -#define __NR_mprotect 125 -__SYSCALL(__NR_mprotect, sys_mprotect) -#define __NR_sigprocmask 126 -__SYSCALL(__NR_sigprocmask, sys_sigprocmask) -__SYSCALL(127, sys_ni_syscall) /* 127 was sys_create_module */ -#define __NR_init_module 128 -__SYSCALL(__NR_init_module, sys_init_module) -#define __NR_delete_module 129 -__SYSCALL(__NR_delete_module, sys_delete_module) -__SYSCALL(130, sys_ni_syscall) /* 130 was sys_get_kernel_syms */ -#define __NR_quotactl 131 -__SYSCALL(__NR_quotactl, sys_quotactl) -#define __NR_getpgid 132 -__SYSCALL(__NR_getpgid, sys_getpgid) -#define __NR_fchdir 133 -__SYSCALL(__NR_fchdir, sys_fchdir) -#define __NR_bdflush 134 -__SYSCALL(__NR_bdflush, sys_bdflush) -#define __NR_sysfs 135 -__SYSCALL(__NR_sysfs, sys_sysfs) -#define __NR_personality 136 -__SYSCALL(__NR_personality, sys_personality) -__SYSCALL(137, sys_ni_syscall) /* 137 was sys_afs_syscall */ -#define __NR_setfsuid 138 -__SYSCALL(__NR_setfsuid, sys_setfsuid16) -#define __NR_setfsgid 139 -__SYSCALL(__NR_setfsgid, sys_setfsgid16) -#define __NR__llseek 140 -__SYSCALL(__NR__llseek, sys_llseek) -#define __NR_getdents 141 -__SYSCALL(__NR_getdents, sys_getdents) -#define __NR__newselect 142 -__SYSCALL(__NR__newselect, sys_select) -#define __NR_flock 143 -__SYSCALL(__NR_flock, sys_flock) -#define __NR_msync 144 -__SYSCALL(__NR_msync, sys_msync) -#define __NR_readv 145 -__SYSCALL(__NR_readv, sys_readv) -#define __NR_writev 146 -__SYSCALL(__NR_writev, sys_writev) -#define __NR_getsid 147 -__SYSCALL(__NR_getsid, sys_getsid) -#define __NR_fdatasync 148 -__SYSCALL(__NR_fdatasync, sys_fdatasync) -#define __NR__sysctl 149 -__SYSCALL(__NR__sysctl, sys_sysctl) -#define __NR_mlock 150 -__SYSCALL(__NR_mlock, sys_mlock) -#define __NR_munlock 151 -__SYSCALL(__NR_munlock, sys_munlock) -#define __NR_mlockall 152 -__SYSCALL(__NR_mlockall, sys_mlockall) -#define __NR_munlockall 153 -__SYSCALL(__NR_munlockall, sys_munlockall) -#define __NR_sched_setparam 154 -__SYSCALL(__NR_sched_setparam, sys_sched_setparam) -#define __NR_sched_getparam 155 -__SYSCALL(__NR_sched_getparam, sys_sched_getparam) -#define __NR_sched_setscheduler 156 -__SYSCALL(__NR_sched_setscheduler, sys_sched_setscheduler) -#define __NR_sched_getscheduler 157 -__SYSCALL(__NR_sched_getscheduler, sys_sched_getscheduler) -#define __NR_sched_yield 158 -__SYSCALL(__NR_sched_yield, sys_sched_yield) -#define __NR_sched_get_priority_max 159 -__SYSCALL(__NR_sched_get_priority_max, sys_sched_get_priority_max) -#define __NR_sched_get_priority_min 160 -__SYSCALL(__NR_sched_get_priority_min, sys_sched_get_priority_min) -#define __NR_sched_rr_get_interval 161 -__SYSCALL(__NR_sched_rr_get_interval, sys_sched_rr_get_interval) -#define __NR_nanosleep 162 -__SYSCALL(__NR_nanosleep, sys_nanosleep) -#define __NR_mremap 163 -__SYSCALL(__NR_mremap, sys_mremap) -#define __NR_setresuid 164 -__SYSCALL(__NR_setresuid, sys_setresuid16) -#define __NR_getresuid 165 -__SYSCALL(__NR_getresuid, sys_getresuid16) -__SYSCALL(166, sys_ni_syscall) /* 166 was sys_vm86 */ -__SYSCALL(167, sys_ni_syscall) /* 167 was sys_query_module */ -#define __NR_poll 168 -__SYSCALL(__NR_poll, sys_poll) -#define __NR_nfsservctl 169 -__SYSCALL(__NR_nfsservctl, sys_ni_syscall) -#define __NR_setresgid 170 -__SYSCALL(__NR_setresgid, sys_setresgid16) -#define __NR_getresgid 171 -__SYSCALL(__NR_getresgid, sys_getresgid16) -#define __NR_prctl 172 -__SYSCALL(__NR_prctl, sys_prctl) -#define __NR_rt_sigreturn 173 -__SYSCALL(__NR_rt_sigreturn, sys_rt_sigreturn) -#define __NR_rt_sigaction 174 -__SYSCALL(__NR_rt_sigaction, sys_rt_sigaction) -#define __NR_rt_sigprocmask 175 -__SYSCALL(__NR_rt_sigprocmask, sys_rt_sigprocmask) -#define __NR_rt_sigpending 176 -__SYSCALL(__NR_rt_sigpending, sys_rt_sigpending) -#define __NR_rt_sigtimedwait 177 -__SYSCALL(__NR_rt_sigtimedwait, sys_rt_sigtimedwait) -#define __NR_rt_sigqueueinfo 178 -__SYSCALL(__NR_rt_sigqueueinfo, sys_rt_sigqueueinfo) -#define __NR_rt_sigsuspend 179 -__SYSCALL(__NR_rt_sigsuspend, sys_rt_sigsuspend) -#define __NR_pread64 180 -__SYSCALL(__NR_pread64, sys_pread64) -#define __NR_pwrite64 181 -__SYSCALL(__NR_pwrite64, sys_pwrite64) -#define __NR_chown 182 -__SYSCALL(__NR_chown, sys_chown16) -#define __NR_getcwd 183 -__SYSCALL(__NR_getcwd, sys_getcwd) -#define __NR_capget 184 -__SYSCALL(__NR_capget, sys_capget) -#define __NR_capset 185 -__SYSCALL(__NR_capset, sys_capset) -#define __NR_sigaltstack 186 -__SYSCALL(__NR_sigaltstack, sys_sigaltstack) -#define __NR_sendfile 187 -__SYSCALL(__NR_sendfile, sys_sendfile) -__SYSCALL(188, sys_ni_syscall) /* 188 reserved */ -__SYSCALL(189, sys_ni_syscall) /* 189 reserved */ -#define __NR_vfork 190 -__SYSCALL(__NR_vfork, sys_vfork) -#define __NR_ugetrlimit 191 /* SuS compliant getrlimit */ -__SYSCALL(__NR_ugetrlimit, sys_getrlimit) -#define __NR_mmap2 192 -__SYSCALL(__NR_mmap2, sys_mmap2) -#define __NR_truncate64 193 -__SYSCALL(__NR_truncate64, sys_truncate64) -#define __NR_ftruncate64 194 -__SYSCALL(__NR_ftruncate64, sys_ftruncate64) -#define __NR_stat64 195 -__SYSCALL(__NR_stat64, sys_stat64) -#define __NR_lstat64 196 -__SYSCALL(__NR_lstat64, sys_lstat64) -#define __NR_fstat64 197 -__SYSCALL(__NR_fstat64, sys_fstat64) -#define __NR_lchown32 198 -__SYSCALL(__NR_lchown32, sys_lchown) -#define __NR_getuid32 199 -__SYSCALL(__NR_getuid32, sys_getuid) -#define __NR_getgid32 200 -__SYSCALL(__NR_getgid32, sys_getgid) -#define __NR_geteuid32 201 -__SYSCALL(__NR_geteuid32, sys_geteuid) -#define __NR_getegid32 202 -__SYSCALL(__NR_getegid32, sys_getegid) -#define __NR_setreuid32 203 -__SYSCALL(__NR_setreuid32, sys_setreuid) -#define __NR_setregid32 204 -__SYSCALL(__NR_setregid32, sys_setregid) -#define __NR_getgroups32 205 -__SYSCALL(__NR_getgroups32, sys_getgroups) -#define __NR_setgroups32 206 -__SYSCALL(__NR_setgroups32, sys_setgroups) -#define __NR_fchown32 207 -__SYSCALL(__NR_fchown32, sys_fchown) -#define __NR_setresuid32 208 -__SYSCALL(__NR_setresuid32, sys_setresuid) -#define __NR_getresuid32 209 -__SYSCALL(__NR_getresuid32, sys_getresuid) -#define __NR_setresgid32 210 -__SYSCALL(__NR_setresgid32, sys_setresgid) -#define __NR_getresgid32 211 -__SYSCALL(__NR_getresgid32, sys_getresgid) -#define __NR_chown32 212 -__SYSCALL(__NR_chown32, sys_chown) -#define __NR_setuid32 213 -__SYSCALL(__NR_setuid32, sys_setuid) -#define __NR_setgid32 214 -__SYSCALL(__NR_setgid32, sys_setgid) -#define __NR_setfsuid32 215 -__SYSCALL(__NR_setfsuid32, sys_setfsuid) -#define __NR_setfsgid32 216 -__SYSCALL(__NR_setfsgid32, sys_setfsgid) -#define __NR_getdents64 217 -__SYSCALL(__NR_getdents64, sys_getdents64) -#define __NR_pivot_root 218 -__SYSCALL(__NR_pivot_root, sys_pivot_root) -#define __NR_mincore 219 -__SYSCALL(__NR_mincore, sys_mincore) -#define __NR_madvise 220 -__SYSCALL(__NR_madvise, sys_madvise) -#define __NR_fcntl64 221 -__SYSCALL(__NR_fcntl64, sys_fcntl64) -__SYSCALL(222, sys_ni_syscall) /* 222 for tux */ -__SYSCALL(223, sys_ni_syscall) /* 223 is unused */ -#define __NR_gettid 224 -__SYSCALL(__NR_gettid, sys_gettid) -#define __NR_readahead 225 -__SYSCALL(__NR_readahead, sys_readahead) -#define __NR_setxattr 226 -__SYSCALL(__NR_setxattr, sys_setxattr) -#define __NR_lsetxattr 227 -__SYSCALL(__NR_lsetxattr, sys_lsetxattr) -#define __NR_fsetxattr 228 -__SYSCALL(__NR_fsetxattr, sys_fsetxattr) -#define __NR_getxattr 229 -__SYSCALL(__NR_getxattr, sys_getxattr) -#define __NR_lgetxattr 230 -__SYSCALL(__NR_lgetxattr, sys_lgetxattr) -#define __NR_fgetxattr 231 -__SYSCALL(__NR_fgetxattr, sys_fgetxattr) -#define __NR_listxattr 232 -__SYSCALL(__NR_listxattr, sys_listxattr) -#define __NR_llistxattr 233 -__SYSCALL(__NR_llistxattr, sys_llistxattr) -#define __NR_flistxattr 234 -__SYSCALL(__NR_flistxattr, sys_flistxattr) -#define __NR_removexattr 235 -__SYSCALL(__NR_removexattr, sys_removexattr) -#define __NR_lremovexattr 236 -__SYSCALL(__NR_lremovexattr, sys_lremovexattr) -#define __NR_fremovexattr 237 -__SYSCALL(__NR_fremovexattr, sys_fremovexattr) -#define __NR_tkill 238 -__SYSCALL(__NR_tkill, sys_tkill) -#define __NR_sendfile64 239 -__SYSCALL(__NR_sendfile64, sys_sendfile64) -#define __NR_futex 240 -__SYSCALL(__NR_futex, sys_futex) -#define __NR_sched_setaffinity 241 -__SYSCALL(__NR_sched_setaffinity, sys_sched_setaffinity) -#define __NR_sched_getaffinity 242 -__SYSCALL(__NR_sched_getaffinity, sys_sched_getaffinity) -#define __NR_io_setup 243 -__SYSCALL(__NR_io_setup, sys_io_setup) -#define __NR_io_destroy 244 -__SYSCALL(__NR_io_destroy, sys_io_destroy) -#define __NR_io_getevents 245 -__SYSCALL(__NR_io_getevents, sys_io_getevents) -#define __NR_io_submit 246 -__SYSCALL(__NR_io_submit, sys_io_submit) -#define __NR_io_cancel 247 -__SYSCALL(__NR_io_cancel, sys_io_cancel) -#define __NR_exit_group 248 -__SYSCALL(__NR_exit_group, sys_exit_group) -#define __NR_lookup_dcookie 249 -__SYSCALL(__NR_lookup_dcookie, sys_lookup_dcookie) -#define __NR_epoll_create 250 -__SYSCALL(__NR_epoll_create, sys_epoll_create) -#define __NR_epoll_ctl 251 -__SYSCALL(__NR_epoll_ctl, sys_epoll_ctl) -#define __NR_epoll_wait 252 -__SYSCALL(__NR_epoll_wait, sys_epoll_wait) -#define __NR_remap_file_pages 253 -__SYSCALL(__NR_remap_file_pages, sys_remap_file_pages) -__SYSCALL(254, sys_ni_syscall) /* 254 for set_thread_area */ -__SYSCALL(255, sys_ni_syscall) /* 255 for get_thread_area */ -#define __NR_set_tid_address 256 -__SYSCALL(__NR_set_tid_address, sys_set_tid_address) -#define __NR_timer_create 257 -__SYSCALL(__NR_timer_create, sys_timer_create) -#define __NR_timer_settime 258 -__SYSCALL(__NR_timer_settime, sys_timer_settime) -#define __NR_timer_gettime 259 -__SYSCALL(__NR_timer_gettime, sys_timer_gettime) -#define __NR_timer_getoverrun 260 -__SYSCALL(__NR_timer_getoverrun, sys_timer_getoverrun) -#define __NR_timer_delete 261 -__SYSCALL(__NR_timer_delete, sys_timer_delete) -#define __NR_clock_settime 262 -__SYSCALL(__NR_clock_settime, sys_clock_settime) -#define __NR_clock_gettime 263 -__SYSCALL(__NR_clock_gettime, sys_clock_gettime) -#define __NR_clock_getres 264 -__SYSCALL(__NR_clock_getres, sys_clock_getres) -#define __NR_clock_nanosleep 265 -__SYSCALL(__NR_clock_nanosleep, sys_clock_nanosleep) -#define __NR_statfs64 266 -__SYSCALL(__NR_statfs64, sys_statfs64) -#define __NR_fstatfs64 267 -__SYSCALL(__NR_fstatfs64, sys_fstatfs64) -#define __NR_tgkill 268 -__SYSCALL(__NR_tgkill, sys_tgkill) -#define __NR_utimes 269 -__SYSCALL(__NR_utimes, sys_utimes) -#define __NR_fadvise64 270 -__SYSCALL(__NR_fadvise64, sys_fadvise64_64) -#define __NR_pciconfig_iobase 271 -__SYSCALL(__NR_pciconfig_iobase, sys_pciconfig_iobase) -#define __NR_pciconfig_read 272 -__SYSCALL(__NR_pciconfig_read, sys_pciconfig_read) -#define __NR_pciconfig_write 273 -__SYSCALL(__NR_pciconfig_write, sys_pciconfig_write) -#define __NR_mq_open 274 -__SYSCALL(__NR_mq_open, sys_mq_open) -#define __NR_mq_unlink 275 -__SYSCALL(__NR_mq_unlink, sys_mq_unlink) -#define __NR_mq_timedsend 276 -__SYSCALL(__NR_mq_timedsend, sys_mq_timedsend) -#define __NR_mq_timedreceive 277 -__SYSCALL(__NR_mq_timedreceive, sys_mq_timedreceive) -#define __NR_mq_notify 278 -__SYSCALL(__NR_mq_notify, sys_mq_notify) -#define __NR_mq_getsetattr 279 -__SYSCALL(__NR_mq_getsetattr, sys_mq_getsetattr) -#define __NR_waitid 280 -__SYSCALL(__NR_waitid, sys_waitid) -#define __NR_socket 281 -__SYSCALL(__NR_socket, sys_socket) -#define __NR_bind 282 -__SYSCALL(__NR_bind, sys_bind) -#define __NR_connect 283 -__SYSCALL(__NR_connect, sys_connect) -#define __NR_listen 284 -__SYSCALL(__NR_listen, sys_listen) -#define __NR_accept 285 -__SYSCALL(__NR_accept, sys_accept) -#define __NR_getsockname 286 -__SYSCALL(__NR_getsockname, sys_getsockname) -#define __NR_getpeername 287 -__SYSCALL(__NR_getpeername, sys_getpeername) -#define __NR_socketpair 288 -__SYSCALL(__NR_socketpair, sys_socketpair) -#define __NR_send 289 -__SYSCALL(__NR_send, sys_send) -#define __NR_sendto 290 -__SYSCALL(__NR_sendto, sys_sendto) -#define __NR_recv 291 -__SYSCALL(__NR_recv, sys_recv) -#define __NR_recvfrom 292 -__SYSCALL(__NR_recvfrom, sys_recvfrom) -#define __NR_shutdown 293 -__SYSCALL(__NR_shutdown, sys_shutdown) -#define __NR_setsockopt 294 -__SYSCALL(__NR_setsockopt, sys_setsockopt) -#define __NR_getsockopt 295 -__SYSCALL(__NR_getsockopt, sys_getsockopt) -#define __NR_sendmsg 296 -__SYSCALL(__NR_sendmsg, sys_sendmsg) -#define __NR_recvmsg 297 -__SYSCALL(__NR_recvmsg, sys_recvmsg) -#define __NR_semop 298 -__SYSCALL(__NR_semop, sys_semop) -#define __NR_semget 299 -__SYSCALL(__NR_semget, sys_semget) -#define __NR_semctl 300 -__SYSCALL(__NR_semctl, sys_semctl) -#define __NR_msgsnd 301 -__SYSCALL(__NR_msgsnd, sys_msgsnd) -#define __NR_msgrcv 302 -__SYSCALL(__NR_msgrcv, sys_msgrcv) -#define __NR_msgget 303 -__SYSCALL(__NR_msgget, sys_msgget) -#define __NR_msgctl 304 -__SYSCALL(__NR_msgctl, sys_msgctl) -#define __NR_shmat 305 -__SYSCALL(__NR_shmat, sys_shmat) -#define __NR_shmdt 306 -__SYSCALL(__NR_shmdt, sys_shmdt) -#define __NR_shmget 307 -__SYSCALL(__NR_shmget, sys_shmget) -#define __NR_shmctl 308 -__SYSCALL(__NR_shmctl, sys_shmctl) -#define __NR_add_key 309 -__SYSCALL(__NR_add_key, sys_add_key) -#define __NR_request_key 310 -__SYSCALL(__NR_request_key, sys_request_key) -#define __NR_keyctl 311 -__SYSCALL(__NR_keyctl, sys_keyctl) -#define __NR_semtimedop 312 -__SYSCALL(__NR_semtimedop, sys_semtimedop) -#define __NR_vserver 313 -__SYSCALL(__NR_vserver, sys_ni_syscall) -#define __NR_ioprio_set 314 -__SYSCALL(__NR_ioprio_set, sys_ioprio_set) -#define __NR_ioprio_get 315 -__SYSCALL(__NR_ioprio_get, sys_ioprio_get) -#define __NR_inotify_init 316 -__SYSCALL(__NR_inotify_init, sys_inotify_init) -#define __NR_inotify_add_watch 317 -__SYSCALL(__NR_inotify_add_watch, sys_inotify_add_watch) -#define __NR_inotify_rm_watch 318 -__SYSCALL(__NR_inotify_rm_watch, sys_inotify_rm_watch) -#define __NR_mbind 319 -__SYSCALL(__NR_mbind, sys_mbind) -#define __NR_get_mempolicy 320 -__SYSCALL(__NR_get_mempolicy, sys_get_mempolicy) -#define __NR_set_mempolicy 321 -__SYSCALL(__NR_set_mempolicy, sys_set_mempolicy) -#define __NR_openat 322 -__SYSCALL(__NR_openat, sys_openat) -#define __NR_mkdirat 323 -__SYSCALL(__NR_mkdirat, sys_mkdirat) -#define __NR_mknodat 324 -__SYSCALL(__NR_mknodat, sys_mknodat) -#define __NR_fchownat 325 -__SYSCALL(__NR_fchownat, sys_fchownat) -#define __NR_futimesat 326 -__SYSCALL(__NR_futimesat, sys_futimesat) -#define __NR_fstatat64 327 -__SYSCALL(__NR_fstatat64, sys_fstatat64) -#define __NR_unlinkat 328 -__SYSCALL(__NR_unlinkat, sys_unlinkat) -#define __NR_renameat 329 -__SYSCALL(__NR_renameat, sys_renameat) -#define __NR_linkat 330 -__SYSCALL(__NR_linkat, sys_linkat) -#define __NR_symlinkat 331 -__SYSCALL(__NR_symlinkat, sys_symlinkat) -#define __NR_readlinkat 332 -__SYSCALL(__NR_readlinkat, sys_readlinkat) -#define __NR_fchmodat 333 -__SYSCALL(__NR_fchmodat, sys_fchmodat) -#define __NR_faccessat 334 -__SYSCALL(__NR_faccessat, sys_faccessat) -#define __NR_pselect6 335 -__SYSCALL(__NR_pselect6, sys_pselect6) -#define __NR_ppoll 336 -__SYSCALL(__NR_ppoll, sys_ppoll) -#define __NR_unshare 337 -__SYSCALL(__NR_unshare, sys_unshare) -#define __NR_set_robust_list 338 -__SYSCALL(__NR_set_robust_list, sys_set_robust_list) -#define __NR_get_robust_list 339 -__SYSCALL(__NR_get_robust_list, sys_get_robust_list) -#define __NR_splice 340 -__SYSCALL(__NR_splice, sys_splice) -#define __NR_sync_file_range2 341 -__SYSCALL(__NR_sync_file_range2, sys_sync_file_range2) -#define __NR_tee 342 -__SYSCALL(__NR_tee, sys_tee) -#define __NR_vmsplice 343 -__SYSCALL(__NR_vmsplice, sys_vmsplice) -#define __NR_move_pages 344 -__SYSCALL(__NR_move_pages, sys_move_pages) -#define __NR_getcpu 345 -__SYSCALL(__NR_getcpu, sys_getcpu) -#define __NR_epoll_pwait 346 -__SYSCALL(__NR_epoll_pwait, sys_epoll_pwait) -#define __NR_kexec_load 347 -__SYSCALL(__NR_kexec_load, sys_kexec_load) -#define __NR_utimensat 348 -__SYSCALL(__NR_utimensat, sys_utimensat) -#define __NR_signalfd 349 -__SYSCALL(__NR_signalfd, sys_signalfd) -#define __NR_timerfd_create 350 -__SYSCALL(__NR_timerfd_create, sys_timerfd_create) -#define __NR_eventfd 351 -__SYSCALL(__NR_eventfd, sys_eventfd) -#define __NR_fallocate 352 -__SYSCALL(__NR_fallocate, sys_fallocate) -#define __NR_timerfd_settime 353 -__SYSCALL(__NR_timerfd_settime, sys_timerfd_settime) -#define __NR_timerfd_gettime 354 -__SYSCALL(__NR_timerfd_gettime, sys_timerfd_gettime) -#define __NR_signalfd4 355 -__SYSCALL(__NR_signalfd4, sys_signalfd4) -#define __NR_eventfd2 356 -__SYSCALL(__NR_eventfd2, sys_eventfd2) -#define __NR_epoll_create1 357 -__SYSCALL(__NR_epoll_create1, sys_epoll_create1) -#define __NR_dup3 358 -__SYSCALL(__NR_dup3, sys_dup3) -#define __NR_pipe2 359 -__SYSCALL(__NR_pipe2, sys_pipe2) -#define __NR_inotify_init1 360 -__SYSCALL(__NR_inotify_init1, sys_inotify_init1) -#define __NR_preadv 361 -__SYSCALL(__NR_preadv, sys_preadv) -#define __NR_pwritev 362 -__SYSCALL(__NR_pwritev, sys_pwritev) -#define __NR_rt_tgsigqueueinfo 363 -__SYSCALL(__NR_rt_tgsigqueueinfo, sys_rt_tgsigqueueinfo) -#define __NR_perf_event_open 364 -__SYSCALL(__NR_perf_event_open, sys_perf_event_open) -#define __NR_recvmmsg 365 -__SYSCALL(__NR_recvmmsg, sys_recvmmsg) -#define __NR_accept4 366 -__SYSCALL(__NR_accept4, sys_accept4) -#define __NR_fanotify_init 367 -__SYSCALL(__NR_fanotify_init, sys_fanotify_init) -#define __NR_fanotify_mark 368 -__SYSCALL(__NR_fanotify_mark, sys_fanotify_mark) -#define __NR_prlimit64 369 -__SYSCALL(__NR_prlimit64, sys_prlimit64) -#define __NR_name_to_handle_at 370 -__SYSCALL(__NR_name_to_handle_at, sys_name_to_handle_at) -#define __NR_open_by_handle_at 371 -__SYSCALL(__NR_open_by_handle_at, sys_open_by_handle_at) -#define __NR_clock_adjtime 372 -__SYSCALL(__NR_clock_adjtime, sys_clock_adjtime) -#define __NR_syncfs 373 -__SYSCALL(__NR_syncfs, sys_syncfs) - -/* - * The following SVCs are ARM private. - */ -#define __ARM_NR_COMPAT_BASE 0x0f0000 -#define __ARM_NR_compat_cacheflush (__ARM_NR_COMPAT_BASE+2) -#define __ARM_NR_compat_set_tls (__ARM_NR_COMPAT_BASE+5) - -#endif /* __SYSCALL_COMPAT */ - -#define __NR_compat_syscalls 374 - -#define __ARCH_WANT_COMPAT_IPC_PARSE_VERSION -#define __ARCH_WANT_COMPAT_STAT64 -#define __ARCH_WANT_SYS_GETHOSTNAME -#define __ARCH_WANT_SYS_PAUSE -#define __ARCH_WANT_SYS_GETPGRP -#define __ARCH_WANT_SYS_LLSEEK -#define __ARCH_WANT_SYS_NICE -#define __ARCH_WANT_SYS_SIGPENDING -#define __ARCH_WANT_SYS_SIGPROCMASK -#define __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND - -#endif /* __ASM_UNISTD32_H */ diff --git a/trunk/arch/arm64/include/asm/vdso.h b/trunk/arch/arm64/include/asm/vdso.h deleted file mode 100644 index 839ce0031bd5..000000000000 --- a/trunk/arch/arm64/include/asm/vdso.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (C) 2012 ARM Limited - * - * 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 __ASM_VDSO_H -#define __ASM_VDSO_H - -#ifdef __KERNEL__ - -/* - * Default link address for the vDSO. - * Since we randomise the VDSO mapping, there's little point in trying - * to prelink this. - */ -#define VDSO_LBASE 0x0 - -#ifndef __ASSEMBLY__ - -#include - -#define VDSO_SYMBOL(base, name) \ -({ \ - (void *)(vdso_offset_##name - VDSO_LBASE + (unsigned long)(base)); \ -}) - -#endif /* !__ASSEMBLY__ */ - -#endif /* __KERNEL__ */ - -#endif /* __ASM_VDSO_H */ diff --git a/trunk/arch/arm64/include/asm/vdso_datapage.h b/trunk/arch/arm64/include/asm/vdso_datapage.h deleted file mode 100644 index de66199673d7..000000000000 --- a/trunk/arch/arm64/include/asm/vdso_datapage.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (C) 2012 ARM Limited - * - * 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 __ASM_VDSO_DATAPAGE_H -#define __ASM_VDSO_DATAPAGE_H - -#ifdef __KERNEL__ - -#ifndef __ASSEMBLY__ - -struct vdso_data { - __u64 cs_cycle_last; /* Timebase at clocksource init */ - __u64 xtime_clock_sec; /* Kernel time */ - __u64 xtime_clock_nsec; - __u64 xtime_coarse_sec; /* Coarse time */ - __u64 xtime_coarse_nsec; - __u64 wtm_clock_sec; /* Wall to monotonic time */ - __u64 wtm_clock_nsec; - __u32 tb_seq_count; /* Timebase sequence counter */ - __u32 cs_mult; /* Clocksource multiplier */ - __u32 cs_shift; /* Clocksource shift */ - __u32 tz_minuteswest; /* Whacky timezone stuff */ - __u32 tz_dsttime; - __u32 use_syscall; -}; - -#endif /* !__ASSEMBLY__ */ - -#endif /* __KERNEL__ */ - -#endif /* __ASM_VDSO_DATAPAGE_H */ diff --git a/trunk/arch/arm64/kernel/.gitignore b/trunk/arch/arm64/kernel/.gitignore deleted file mode 100644 index c5f676c3c224..000000000000 --- a/trunk/arch/arm64/kernel/.gitignore +++ /dev/null @@ -1 +0,0 @@ -vmlinux.lds diff --git a/trunk/arch/arm64/kernel/Makefile b/trunk/arch/arm64/kernel/Makefile deleted file mode 100644 index e2caff1b812a..000000000000 --- a/trunk/arch/arm64/kernel/Makefile +++ /dev/null @@ -1,27 +0,0 @@ -# -# Makefile for the linux kernel. -# - -CPPFLAGS_vmlinux.lds := -DTEXT_OFFSET=$(TEXT_OFFSET) -AFLAGS_head.o := -DTEXT_OFFSET=$(TEXT_OFFSET) - -# Object file lists. -arm64-obj-y := cputable.o debug-monitors.o entry.o irq.o fpsimd.o \ - entry-fpsimd.o process.o ptrace.o setup.o signal.o \ - sys.o stacktrace.o time.o traps.o io.o vdso.o - -arm64-obj-$(CONFIG_COMPAT) += sys32.o kuser32.o signal32.o \ - sys_compat.o -arm64-obj-$(CONFIG_MODULES) += arm64ksyms.o module.o -arm64-obj-$(CONFIG_SMP) += smp.o -arm64-obj-$(CONFIG_HW_PERF_EVENTS) += perf_event.o -arm64-obj-$(CONFIG_HAVE_HW_BREAKPOINT)+= hw_breakpoint.o - -obj-y += $(arm64-obj-y) vdso/ -obj-m += $(arm64-obj-m) -head-y := head.o -extra-y := $(head-y) vmlinux.lds - -# vDSO - this must be built first to generate the symbol offsets -$(call objectify,$(arm64-obj-y)): $(obj)/vdso/vdso-offsets.h -$(obj)/vdso/vdso-offsets.h: $(obj)/vdso diff --git a/trunk/arch/arm64/kernel/arm64ksyms.c b/trunk/arch/arm64/kernel/arm64ksyms.c deleted file mode 100644 index cef3925eaf60..000000000000 --- a/trunk/arch/arm64/kernel/arm64ksyms.c +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Based on arch/arm/kernel/armksyms.c - * - * Copyright (C) 2000 Russell King - * Copyright (C) 2012 ARM 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 -#include -#include -#include -#include - -#include - - /* user mem (segment) */ -EXPORT_SYMBOL(__strnlen_user); -EXPORT_SYMBOL(__strncpy_from_user); - -EXPORT_SYMBOL(copy_page); - -EXPORT_SYMBOL(__copy_from_user); -EXPORT_SYMBOL(__copy_to_user); -EXPORT_SYMBOL(__clear_user); - - /* bitops */ -EXPORT_SYMBOL(__atomic_hash); - - /* physical memory */ -EXPORT_SYMBOL(memstart_addr); diff --git a/trunk/arch/arm64/kernel/asm-offsets.c b/trunk/arch/arm64/kernel/asm-offsets.c deleted file mode 100644 index a2a4d810bea3..000000000000 --- a/trunk/arch/arm64/kernel/asm-offsets.c +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Based on arch/arm/kernel/asm-offsets.c - * - * Copyright (C) 1995-2003 Russell King - * 2001-2002 Keith Owens - * Copyright (C) 2012 ARM 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 -#include -#include -#include - -int main(void) -{ - DEFINE(TSK_ACTIVE_MM, offsetof(struct task_struct, active_mm)); - BLANK(); - DEFINE(TI_FLAGS, offsetof(struct thread_info, flags)); - DEFINE(TI_PREEMPT, offsetof(struct thread_info, preempt_count)); - DEFINE(TI_ADDR_LIMIT, offsetof(struct thread_info, addr_limit)); - DEFINE(TI_TASK, offsetof(struct thread_info, task)); - DEFINE(TI_EXEC_DOMAIN, offsetof(struct thread_info, exec_domain)); - DEFINE(TI_CPU, offsetof(struct thread_info, cpu)); - BLANK(); - DEFINE(THREAD_CPU_CONTEXT, offsetof(struct task_struct, thread.cpu_context)); - BLANK(); - DEFINE(S_X0, offsetof(struct pt_regs, regs[0])); - DEFINE(S_X1, offsetof(struct pt_regs, regs[1])); - DEFINE(S_X2, offsetof(struct pt_regs, regs[2])); - DEFINE(S_X3, offsetof(struct pt_regs, regs[3])); - DEFINE(S_X4, offsetof(struct pt_regs, regs[4])); - DEFINE(S_X5, offsetof(struct pt_regs, regs[5])); - DEFINE(S_X6, offsetof(struct pt_regs, regs[6])); - DEFINE(S_X7, offsetof(struct pt_regs, regs[7])); - DEFINE(S_LR, offsetof(struct pt_regs, regs[30])); - DEFINE(S_SP, offsetof(struct pt_regs, sp)); -#ifdef CONFIG_COMPAT - DEFINE(S_COMPAT_SP, offsetof(struct pt_regs, compat_sp)); -#endif - DEFINE(S_PSTATE, offsetof(struct pt_regs, pstate)); - DEFINE(S_PC, offsetof(struct pt_regs, pc)); - DEFINE(S_ORIG_X0, offsetof(struct pt_regs, orig_x0)); - DEFINE(S_SYSCALLNO, offsetof(struct pt_regs, syscallno)); - DEFINE(S_FRAME_SIZE, sizeof(struct pt_regs)); - BLANK(); - DEFINE(MM_CONTEXT_ID, offsetof(struct mm_struct, context.id)); - BLANK(); - DEFINE(VMA_VM_MM, offsetof(struct vm_area_struct, vm_mm)); - DEFINE(VMA_VM_FLAGS, offsetof(struct vm_area_struct, vm_flags)); - BLANK(); - DEFINE(VM_EXEC, VM_EXEC); - BLANK(); - DEFINE(PAGE_SZ, PAGE_SIZE); - BLANK(); - DEFINE(CPU_INFO_SZ, sizeof(struct cpu_info)); - DEFINE(CPU_INFO_SETUP, offsetof(struct cpu_info, cpu_setup)); - BLANK(); - DEFINE(DMA_BIDIRECTIONAL, DMA_BIDIRECTIONAL); - DEFINE(DMA_TO_DEVICE, DMA_TO_DEVICE); - DEFINE(DMA_FROM_DEVICE, DMA_FROM_DEVICE); - BLANK(); - DEFINE(CLOCK_REALTIME, CLOCK_REALTIME); - DEFINE(CLOCK_MONOTONIC, CLOCK_MONOTONIC); - DEFINE(CLOCK_REALTIME_RES, MONOTONIC_RES_NSEC); - DEFINE(CLOCK_REALTIME_COARSE, CLOCK_REALTIME_COARSE); - DEFINE(CLOCK_MONOTONIC_COARSE,CLOCK_MONOTONIC_COARSE); - DEFINE(CLOCK_COARSE_RES, LOW_RES_NSEC); - DEFINE(NSEC_PER_SEC, NSEC_PER_SEC); - BLANK(); - DEFINE(VDSO_CS_CYCLE_LAST, offsetof(struct vdso_data, cs_cycle_last)); - DEFINE(VDSO_XTIME_CLK_SEC, offsetof(struct vdso_data, xtime_clock_sec)); - DEFINE(VDSO_XTIME_CLK_NSEC, offsetof(struct vdso_data, xtime_clock_nsec)); - DEFINE(VDSO_XTIME_CRS_SEC, offsetof(struct vdso_data, xtime_coarse_sec)); - DEFINE(VDSO_XTIME_CRS_NSEC, offsetof(struct vdso_data, xtime_coarse_nsec)); - DEFINE(VDSO_WTM_CLK_SEC, offsetof(struct vdso_data, wtm_clock_sec)); - DEFINE(VDSO_WTM_CLK_NSEC, offsetof(struct vdso_data, wtm_clock_nsec)); - DEFINE(VDSO_TB_SEQ_COUNT, offsetof(struct vdso_data, tb_seq_count)); - DEFINE(VDSO_CS_MULT, offsetof(struct vdso_data, cs_mult)); - DEFINE(VDSO_CS_SHIFT, offsetof(struct vdso_data, cs_shift)); - DEFINE(VDSO_TZ_MINWEST, offsetof(struct vdso_data, tz_minuteswest)); - DEFINE(VDSO_TZ_DSTTIME, offsetof(struct vdso_data, tz_dsttime)); - DEFINE(VDSO_USE_SYSCALL, offsetof(struct vdso_data, use_syscall)); - BLANK(); - DEFINE(TVAL_TV_SEC, offsetof(struct timeval, tv_sec)); - DEFINE(TVAL_TV_USEC, offsetof(struct timeval, tv_usec)); - DEFINE(TSPEC_TV_SEC, offsetof(struct timespec, tv_sec)); - DEFINE(TSPEC_TV_NSEC, offsetof(struct timespec, tv_nsec)); - BLANK(); - DEFINE(TZ_MINWEST, offsetof(struct timezone, tz_minuteswest)); - DEFINE(TZ_DSTTIME, offsetof(struct timezone, tz_dsttime)); - return 0; -} diff --git a/trunk/arch/arm64/kernel/cputable.c b/trunk/arch/arm64/kernel/cputable.c deleted file mode 100644 index 63cfc4a43f4e..000000000000 --- a/trunk/arch/arm64/kernel/cputable.c +++ /dev/null @@ -1,33 +0,0 @@ -/* - * arch/arm64/kernel/cputable.c - * - * Copyright (C) 2012 ARM 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 - -extern unsigned long __cpu_setup(void); - -struct cpu_info __initdata cpu_table[] = { - { - .cpu_id_val = 0x000f0000, - .cpu_id_mask = 0x000f0000, - .cpu_name = "AArch64 Processor", - .cpu_setup = __cpu_setup, - }, - { /* Empty */ }, -}; diff --git a/trunk/arch/arm64/kernel/debug-monitors.c b/trunk/arch/arm64/kernel/debug-monitors.c deleted file mode 100644 index 0c3ba9f51376..000000000000 --- a/trunk/arch/arm64/kernel/debug-monitors.c +++ /dev/null @@ -1,288 +0,0 @@ -/* - * ARMv8 single-step debug support and mdscr context switching. - * - * Copyright (C) 2012 ARM Limited - * - * 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 . - * - * Author: Will Deacon - */ - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -/* Low-level stepping controls. */ -#define DBG_MDSCR_SS (1 << 0) -#define DBG_SPSR_SS (1 << 21) - -/* MDSCR_EL1 enabling bits */ -#define DBG_MDSCR_KDE (1 << 13) -#define DBG_MDSCR_MDE (1 << 15) -#define DBG_MDSCR_MASK ~(DBG_MDSCR_KDE | DBG_MDSCR_MDE) - -/* Determine debug architecture. */ -u8 debug_monitors_arch(void) -{ - return read_cpuid(ID_AA64DFR0_EL1) & 0xf; -} - -/* - * MDSCR access routines. - */ -static void mdscr_write(u32 mdscr) -{ - unsigned long flags; - local_dbg_save(flags); - asm volatile("msr mdscr_el1, %0" :: "r" (mdscr)); - local_dbg_restore(flags); -} - -static u32 mdscr_read(void) -{ - u32 mdscr; - asm volatile("mrs %0, mdscr_el1" : "=r" (mdscr)); - return mdscr; -} - -/* - * Allow root to disable self-hosted debug from userspace. - * This is useful if you want to connect an external JTAG debugger. - */ -static u32 debug_enabled = 1; - -static int create_debug_debugfs_entry(void) -{ - debugfs_create_bool("debug_enabled", 0644, NULL, &debug_enabled); - return 0; -} -fs_initcall(create_debug_debugfs_entry); - -static int __init early_debug_disable(char *buf) -{ - debug_enabled = 0; - return 0; -} - -early_param("nodebugmon", early_debug_disable); - -/* - * Keep track of debug users on each core. - * The ref counts are per-cpu so we use a local_t type. - */ -static DEFINE_PER_CPU(local_t, mde_ref_count); -static DEFINE_PER_CPU(local_t, kde_ref_count); - -void enable_debug_monitors(enum debug_el el) -{ - u32 mdscr, enable = 0; - - WARN_ON(preemptible()); - - if (local_inc_return(&__get_cpu_var(mde_ref_count)) == 1) - enable = DBG_MDSCR_MDE; - - if (el == DBG_ACTIVE_EL1 && - local_inc_return(&__get_cpu_var(kde_ref_count)) == 1) - enable |= DBG_MDSCR_KDE; - - if (enable && debug_enabled) { - mdscr = mdscr_read(); - mdscr |= enable; - mdscr_write(mdscr); - } -} - -void disable_debug_monitors(enum debug_el el) -{ - u32 mdscr, disable = 0; - - WARN_ON(preemptible()); - - if (local_dec_and_test(&__get_cpu_var(mde_ref_count))) - disable = ~DBG_MDSCR_MDE; - - if (el == DBG_ACTIVE_EL1 && - local_dec_and_test(&__get_cpu_var(kde_ref_count))) - disable &= ~DBG_MDSCR_KDE; - - if (disable) { - mdscr = mdscr_read(); - mdscr &= disable; - mdscr_write(mdscr); - } -} - -/* - * OS lock clearing. - */ -static void clear_os_lock(void *unused) -{ - asm volatile("msr mdscr_el1, %0" : : "r" (0)); - isb(); - asm volatile("msr oslar_el1, %0" : : "r" (0)); - isb(); -} - -static int __cpuinit os_lock_notify(struct notifier_block *self, - unsigned long action, void *data) -{ - int cpu = (unsigned long)data; - if (action == CPU_ONLINE) - smp_call_function_single(cpu, clear_os_lock, NULL, 1); - return NOTIFY_OK; -} - -static struct notifier_block __cpuinitdata os_lock_nb = { - .notifier_call = os_lock_notify, -}; - -static int __cpuinit debug_monitors_init(void) -{ - /* Clear the OS lock. */ - smp_call_function(clear_os_lock, NULL, 1); - clear_os_lock(NULL); - - /* Register hotplug handler. */ - register_cpu_notifier(&os_lock_nb); - return 0; -} -postcore_initcall(debug_monitors_init); - -/* - * Single step API and exception handling. - */ -static void set_regs_spsr_ss(struct pt_regs *regs) -{ - unsigned long spsr; - - spsr = regs->pstate; - spsr &= ~DBG_SPSR_SS; - spsr |= DBG_SPSR_SS; - regs->pstate = spsr; -} - -static void clear_regs_spsr_ss(struct pt_regs *regs) -{ - unsigned long spsr; - - spsr = regs->pstate; - spsr &= ~DBG_SPSR_SS; - regs->pstate = spsr; -} - -static int single_step_handler(unsigned long addr, unsigned int esr, - struct pt_regs *regs) -{ - siginfo_t info; - - /* - * If we are stepping a pending breakpoint, call the hw_breakpoint - * handler first. - */ - if (!reinstall_suspended_bps(regs)) - return 0; - - if (user_mode(regs)) { - info.si_signo = SIGTRAP; - info.si_errno = 0; - info.si_code = TRAP_HWBKPT; - info.si_addr = (void __user *)instruction_pointer(regs); - force_sig_info(SIGTRAP, &info, current); - - /* - * ptrace will disable single step unless explicitly - * asked to re-enable it. For other clients, it makes - * sense to leave it enabled (i.e. rewind the controls - * to the active-not-pending state). - */ - user_rewind_single_step(current); - } else { - /* TODO: route to KGDB */ - pr_warning("Unexpected kernel single-step exception at EL1\n"); - /* - * Re-enable stepping since we know that we will be - * returning to regs. - */ - set_regs_spsr_ss(regs); - } - - return 0; -} - -static int __init single_step_init(void) -{ - hook_debug_fault_code(DBG_ESR_EVT_HWSS, single_step_handler, SIGTRAP, - TRAP_HWBKPT, "single-step handler"); - return 0; -} -arch_initcall(single_step_init); - -/* Re-enable single step for syscall restarting. */ -void user_rewind_single_step(struct task_struct *task) -{ - /* - * If single step is active for this thread, then set SPSR.SS - * to 1 to avoid returning to the active-pending state. - */ - if (test_ti_thread_flag(task_thread_info(task), TIF_SINGLESTEP)) - set_regs_spsr_ss(task_pt_regs(task)); -} - -void user_fastforward_single_step(struct task_struct *task) -{ - if (test_ti_thread_flag(task_thread_info(task), TIF_SINGLESTEP)) - clear_regs_spsr_ss(task_pt_regs(task)); -} - -/* Kernel API */ -void kernel_enable_single_step(struct pt_regs *regs) -{ - WARN_ON(!irqs_disabled()); - set_regs_spsr_ss(regs); - mdscr_write(mdscr_read() | DBG_MDSCR_SS); - enable_debug_monitors(DBG_ACTIVE_EL1); -} - -void kernel_disable_single_step(void) -{ - WARN_ON(!irqs_disabled()); - mdscr_write(mdscr_read() & ~DBG_MDSCR_SS); - disable_debug_monitors(DBG_ACTIVE_EL1); -} - -int kernel_active_single_step(void) -{ - WARN_ON(!irqs_disabled()); - return mdscr_read() & DBG_MDSCR_SS; -} - -/* ptrace API */ -void user_enable_single_step(struct task_struct *task) -{ - set_ti_thread_flag(task_thread_info(task), TIF_SINGLESTEP); - set_regs_spsr_ss(task_pt_regs(task)); -} - -void user_disable_single_step(struct task_struct *task) -{ - clear_ti_thread_flag(task_thread_info(task), TIF_SINGLESTEP); -} diff --git a/trunk/arch/arm64/kernel/entry-fpsimd.S b/trunk/arch/arm64/kernel/entry-fpsimd.S deleted file mode 100644 index 17988a6e7ea2..000000000000 --- a/trunk/arch/arm64/kernel/entry-fpsimd.S +++ /dev/null @@ -1,80 +0,0 @@ -/* - * FP/SIMD state saving and restoring - * - * Copyright (C) 2012 ARM Ltd. - * Author: Catalin Marinas - * - * 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 - -/* - * Save the FP registers. - * - * x0 - pointer to struct fpsimd_state - */ -ENTRY(fpsimd_save_state) - stp q0, q1, [x0, #16 * 0] - stp q2, q3, [x0, #16 * 2] - stp q4, q5, [x0, #16 * 4] - stp q6, q7, [x0, #16 * 6] - stp q8, q9, [x0, #16 * 8] - stp q10, q11, [x0, #16 * 10] - stp q12, q13, [x0, #16 * 12] - stp q14, q15, [x0, #16 * 14] - stp q16, q17, [x0, #16 * 16] - stp q18, q19, [x0, #16 * 18] - stp q20, q21, [x0, #16 * 20] - stp q22, q23, [x0, #16 * 22] - stp q24, q25, [x0, #16 * 24] - stp q26, q27, [x0, #16 * 26] - stp q28, q29, [x0, #16 * 28] - stp q30, q31, [x0, #16 * 30]! - mrs x8, fpsr - str w8, [x0, #16 * 2] - mrs x8, fpcr - str w8, [x0, #16 * 2 + 4] - ret -ENDPROC(fpsimd_save_state) - -/* - * Load the FP registers. - * - * x0 - pointer to struct fpsimd_state - */ -ENTRY(fpsimd_load_state) - ldp q0, q1, [x0, #16 * 0] - ldp q2, q3, [x0, #16 * 2] - ldp q4, q5, [x0, #16 * 4] - ldp q6, q7, [x0, #16 * 6] - ldp q8, q9, [x0, #16 * 8] - ldp q10, q11, [x0, #16 * 10] - ldp q12, q13, [x0, #16 * 12] - ldp q14, q15, [x0, #16 * 14] - ldp q16, q17, [x0, #16 * 16] - ldp q18, q19, [x0, #16 * 18] - ldp q20, q21, [x0, #16 * 20] - ldp q22, q23, [x0, #16 * 22] - ldp q24, q25, [x0, #16 * 24] - ldp q26, q27, [x0, #16 * 26] - ldp q28, q29, [x0, #16 * 28] - ldp q30, q31, [x0, #16 * 30]! - ldr w8, [x0, #16 * 2] - ldr w9, [x0, #16 * 2 + 4] - msr fpsr, x8 - msr fpcr, x9 - ret -ENDPROC(fpsimd_load_state) diff --git a/trunk/arch/arm64/kernel/entry.S b/trunk/arch/arm64/kernel/entry.S deleted file mode 100644 index 38cf853a3667..000000000000 --- a/trunk/arch/arm64/kernel/entry.S +++ /dev/null @@ -1,695 +0,0 @@ -/* - * Low-level exception handling code - * - * Copyright (C) 2012 ARM Ltd. - * Authors: Catalin Marinas - * Will Deacon - * - * 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 -#include -#include - -/* - * Bad Abort numbers - *----------------- - */ -#define BAD_SYNC 0 -#define BAD_IRQ 1 -#define BAD_FIQ 2 -#define BAD_ERROR 3 - - .macro kernel_entry, el, regsize = 64 - sub sp, sp, #S_FRAME_SIZE - S_LR // room for LR, SP, SPSR, ELR - .if \regsize == 32 - mov w0, w0 // zero upper 32 bits of x0 - .endif - push x28, x29 - push x26, x27 - push x24, x25 - push x22, x23 - push x20, x21 - push x18, x19 - push x16, x17 - push x14, x15 - push x12, x13 - push x10, x11 - push x8, x9 - push x6, x7 - push x4, x5 - push x2, x3 - push x0, x1 - .if \el == 0 - mrs x21, sp_el0 - .else - add x21, sp, #S_FRAME_SIZE - .endif - mrs x22, elr_el1 - mrs x23, spsr_el1 - stp lr, x21, [sp, #S_LR] - stp x22, x23, [sp, #S_PC] - - /* - * Set syscallno to -1 by default (overridden later if real syscall). - */ - .if \el == 0 - mvn x21, xzr - str x21, [sp, #S_SYSCALLNO] - .endif - - /* - * Registers that may be useful after this macro is invoked: - * - * x21 - aborted SP - * x22 - aborted PC - * x23 - aborted PSTATE - */ - .endm - - .macro kernel_exit, el, ret = 0 - ldp x21, x22, [sp, #S_PC] // load ELR, SPSR - .if \el == 0 - ldr x23, [sp, #S_SP] // load return stack pointer - .endif - .if \ret - ldr x1, [sp, #S_X1] // preserve x0 (syscall return) - add sp, sp, S_X2 - .else - pop x0, x1 - .endif - pop x2, x3 // load the rest of the registers - pop x4, x5 - pop x6, x7 - pop x8, x9 - msr elr_el1, x21 // set up the return data - msr spsr_el1, x22 - .if \el == 0 - msr sp_el0, x23 - .endif - pop x10, x11 - pop x12, x13 - pop x14, x15 - pop x16, x17 - pop x18, x19 - pop x20, x21 - pop x22, x23 - pop x24, x25 - pop x26, x27 - pop x28, x29 - ldr lr, [sp], #S_FRAME_SIZE - S_LR // load LR and restore SP - eret // return to kernel - .endm - - .macro get_thread_info, rd - mov \rd, sp - and \rd, \rd, #~((1 << 13) - 1) // top of 8K stack - .endm - -/* - * These are the registers used in the syscall handler, and allow us to - * have in theory up to 7 arguments to a function - x0 to x6. - * - * x7 is reserved for the system call number in 32-bit mode. - */ -sc_nr .req x25 // number of system calls -scno .req x26 // syscall number -stbl .req x27 // syscall table pointer -tsk .req x28 // current thread_info - -/* - * Interrupt handling. - */ - .macro irq_handler - ldr x1, handle_arch_irq - mov x0, sp - blr x1 - .endm - - .text - -/* - * Exception vectors. - */ - .macro ventry label - .align 7 - b \label - .endm - - .align 11 -ENTRY(vectors) - ventry el1_sync_invalid // Synchronous EL1t - ventry el1_irq_invalid // IRQ EL1t - ventry el1_fiq_invalid // FIQ EL1t - ventry el1_error_invalid // Error EL1t - - ventry el1_sync // Synchronous EL1h - ventry el1_irq // IRQ EL1h - ventry el1_fiq_invalid // FIQ EL1h - ventry el1_error_invalid // Error EL1h - - ventry el0_sync // Synchronous 64-bit EL0 - ventry el0_irq // IRQ 64-bit EL0 - ventry el0_fiq_invalid // FIQ 64-bit EL0 - ventry el0_error_invalid // Error 64-bit EL0 - -#ifdef CONFIG_COMPAT - ventry el0_sync_compat // Synchronous 32-bit EL0 - ventry el0_irq_compat // IRQ 32-bit EL0 - ventry el0_fiq_invalid_compat // FIQ 32-bit EL0 - ventry el0_error_invalid_compat // Error 32-bit EL0 -#else - ventry el0_sync_invalid // Synchronous 32-bit EL0 - ventry el0_irq_invalid // IRQ 32-bit EL0 - ventry el0_fiq_invalid // FIQ 32-bit EL0 - ventry el0_error_invalid // Error 32-bit EL0 -#endif -END(vectors) - -/* - * Invalid mode handlers - */ - .macro inv_entry, el, reason, regsize = 64 - kernel_entry el, \regsize - mov x0, sp - mov x1, #\reason - mrs x2, esr_el1 - b bad_mode - .endm - -el0_sync_invalid: - inv_entry 0, BAD_SYNC -ENDPROC(el0_sync_invalid) - -el0_irq_invalid: - inv_entry 0, BAD_IRQ -ENDPROC(el0_irq_invalid) - -el0_fiq_invalid: - inv_entry 0, BAD_FIQ -ENDPROC(el0_fiq_invalid) - -el0_error_invalid: - inv_entry 0, BAD_ERROR -ENDPROC(el0_error_invalid) - -#ifdef CONFIG_COMPAT -el0_fiq_invalid_compat: - inv_entry 0, BAD_FIQ, 32 -ENDPROC(el0_fiq_invalid_compat) - -el0_error_invalid_compat: - inv_entry 0, BAD_ERROR, 32 -ENDPROC(el0_error_invalid_compat) -#endif - -el1_sync_invalid: - inv_entry 1, BAD_SYNC -ENDPROC(el1_sync_invalid) - -el1_irq_invalid: - inv_entry 1, BAD_IRQ -ENDPROC(el1_irq_invalid) - -el1_fiq_invalid: - inv_entry 1, BAD_FIQ -ENDPROC(el1_fiq_invalid) - -el1_error_invalid: - inv_entry 1, BAD_ERROR -ENDPROC(el1_error_invalid) - -/* - * EL1 mode handlers. - */ - .align 6 -el1_sync: - kernel_entry 1 - mrs x1, esr_el1 // read the syndrome register - lsr x24, x1, #26 // exception class - cmp x24, #0x25 // data abort in EL1 - b.eq el1_da - cmp x24, #0x18 // configurable trap - b.eq el1_undef - cmp x24, #0x26 // stack alignment exception - b.eq el1_sp_pc - cmp x24, #0x22 // pc alignment exception - b.eq el1_sp_pc - cmp x24, #0x00 // unknown exception in EL1 - b.eq el1_undef - cmp x24, #0x30 // debug exception in EL1 - b.ge el1_dbg - b el1_inv -el1_da: - /* - * Data abort handling - */ - mrs x0, far_el1 - enable_dbg_if_not_stepping x2 - // re-enable interrupts if they were enabled in the aborted context - tbnz x23, #7, 1f // PSR_I_BIT - enable_irq -1: - mov x2, sp // struct pt_regs - bl do_mem_abort - - // disable interrupts before pulling preserved data off the stack - disable_irq - kernel_exit 1 -el1_sp_pc: - /* - * Stack or PC alignment exception handling - */ - mrs x0, far_el1 - mov x1, x25 - mov x2, sp - b do_sp_pc_abort -el1_undef: - /* - * Undefined instruction - */ - mov x0, sp - b do_undefinstr -el1_dbg: - /* - * Debug exception handling - */ - tbz x24, #0, el1_inv // EL1 only - mrs x0, far_el1 - mov x2, sp // struct pt_regs - bl do_debug_exception - - kernel_exit 1 -el1_inv: - // TODO: add support for undefined instructions in kernel mode - mov x0, sp - mov x1, #BAD_SYNC - mrs x2, esr_el1 - b bad_mode -ENDPROC(el1_sync) - - .align 6 -el1_irq: - kernel_entry 1 - enable_dbg_if_not_stepping x0 -#ifdef CONFIG_TRACE_IRQFLAGS - bl trace_hardirqs_off -#endif -#ifdef CONFIG_PREEMPT - get_thread_info tsk - ldr x24, [tsk, #TI_PREEMPT] // get preempt count - add x0, x24, #1 // increment it - str x0, [tsk, #TI_PREEMPT] -#endif - irq_handler -#ifdef CONFIG_PREEMPT - str x24, [tsk, #TI_PREEMPT] // restore preempt count - cbnz x24, 1f // preempt count != 0 - ldr x0, [tsk, #TI_FLAGS] // get flags - tbz x0, #TIF_NEED_RESCHED, 1f // needs rescheduling? - bl el1_preempt -1: -#endif -#ifdef CONFIG_TRACE_IRQFLAGS - bl trace_hardirqs_on -#endif - kernel_exit 1 -ENDPROC(el1_irq) - -#ifdef CONFIG_PREEMPT -el1_preempt: - mov x24, lr -1: enable_dbg - bl preempt_schedule_irq // irq en/disable is done inside - ldr x0, [tsk, #TI_FLAGS] // get new tasks TI_FLAGS - tbnz x0, #TIF_NEED_RESCHED, 1b // needs rescheduling? - ret x24 -#endif - -/* - * EL0 mode handlers. - */ - .align 6 -el0_sync: - kernel_entry 0 - mrs x25, esr_el1 // read the syndrome register - lsr x24, x25, #26 // exception class - cmp x24, #0x15 // SVC in 64-bit state - b.eq el0_svc - adr lr, ret_from_exception - cmp x24, #0x24 // data abort in EL0 - b.eq el0_da - cmp x24, #0x20 // instruction abort in EL0 - b.eq el0_ia - cmp x24, #0x07 // FP/ASIMD access - b.eq el0_fpsimd_acc - cmp x24, #0x2c // FP/ASIMD exception - b.eq el0_fpsimd_exc - cmp x24, #0x18 // configurable trap - b.eq el0_undef - cmp x24, #0x26 // stack alignment exception - b.eq el0_sp_pc - cmp x24, #0x22 // pc alignment exception - b.eq el0_sp_pc - cmp x24, #0x00 // unknown exception in EL0 - b.eq el0_undef - cmp x24, #0x30 // debug exception in EL0 - b.ge el0_dbg - b el0_inv - -#ifdef CONFIG_COMPAT - .align 6 -el0_sync_compat: - kernel_entry 0, 32 - mrs x25, esr_el1 // read the syndrome register - lsr x24, x25, #26 // exception class - cmp x24, #0x11 // SVC in 32-bit state - b.eq el0_svc_compat - adr lr, ret_from_exception - cmp x24, #0x24 // data abort in EL0 - b.eq el0_da - cmp x24, #0x20 // instruction abort in EL0 - b.eq el0_ia - cmp x24, #0x07 // FP/ASIMD access - b.eq el0_fpsimd_acc - cmp x24, #0x28 // FP/ASIMD exception - b.eq el0_fpsimd_exc - cmp x24, #0x00 // unknown exception in EL0 - b.eq el0_undef - cmp x24, #0x30 // debug exception in EL0 - b.ge el0_dbg - b el0_inv -el0_svc_compat: - /* - * AArch32 syscall handling - */ - adr stbl, compat_sys_call_table // load compat syscall table pointer - uxtw scno, w7 // syscall number in w7 (r7) - mov sc_nr, #__NR_compat_syscalls - b el0_svc_naked - - .align 6 -el0_irq_compat: - kernel_entry 0, 32 - b el0_irq_naked -#endif - -el0_da: - /* - * Data abort handling - */ - mrs x0, far_el1 - disable_step x1 - isb - enable_dbg - // enable interrupts before calling the main handler - enable_irq - mov x1, x25 - mov x2, sp - b do_mem_abort -el0_ia: - /* - * Instruction abort handling - */ - mrs x0, far_el1 - disable_step x1 - isb - enable_dbg - // enable interrupts before calling the main handler - enable_irq - orr x1, x25, #1 << 24 // use reserved ISS bit for instruction aborts - mov x2, sp - b do_mem_abort -el0_fpsimd_acc: - /* - * Floating Point or Advanced SIMD access - */ - mov x0, x25 - mov x1, sp - b do_fpsimd_acc -el0_fpsimd_exc: - /* - * Floating Point or Advanced SIMD exception - */ - mov x0, x25 - mov x1, sp - b do_fpsimd_exc -el0_sp_pc: - /* - * Stack or PC alignment exception handling - */ - mrs x0, far_el1 - disable_step x1 - isb - enable_dbg - // enable interrupts before calling the main handler - enable_irq - mov x1, x25 - mov x2, sp - b do_sp_pc_abort -el0_undef: - /* - * Undefined instruction - */ - mov x0, sp - b do_undefinstr -el0_dbg: - /* - * Debug exception handling - */ - tbnz x24, #0, el0_inv // EL0 only - mrs x0, far_el1 - disable_step x1 - mov x1, x25 - mov x2, sp - b do_debug_exception -el0_inv: - mov x0, sp - mov x1, #BAD_SYNC - mrs x2, esr_el1 - b bad_mode -ENDPROC(el0_sync) - - .align 6 -el0_irq: - kernel_entry 0 -el0_irq_naked: - disable_step x1 - isb - enable_dbg -#ifdef CONFIG_TRACE_IRQFLAGS - bl trace_hardirqs_off -#endif - get_thread_info tsk -#ifdef CONFIG_PREEMPT - ldr x24, [tsk, #TI_PREEMPT] // get preempt count - add x23, x24, #1 // increment it - str x23, [tsk, #TI_PREEMPT] -#endif - irq_handler -#ifdef CONFIG_PREEMPT - ldr x0, [tsk, #TI_PREEMPT] - str x24, [tsk, #TI_PREEMPT] - cmp x0, x23 - b.eq 1f - mov x1, #0 - str x1, [x1] // BUG -1: -#endif -#ifdef CONFIG_TRACE_IRQFLAGS - bl trace_hardirqs_on -#endif - b ret_to_user -ENDPROC(el0_irq) - -/* - * This is the return code to user mode for abort handlers - */ -ret_from_exception: - get_thread_info tsk - b ret_to_user -ENDPROC(ret_from_exception) - -/* - * Register switch for AArch64. The callee-saved registers need to be saved - * and restored. On entry: - * x0 = previous task_struct (must be preserved across the switch) - * x1 = next task_struct - * Previous and next are guaranteed not to be the same. - * - */ -ENTRY(cpu_switch_to) - add x8, x0, #THREAD_CPU_CONTEXT - mov x9, sp - stp x19, x20, [x8], #16 // store callee-saved registers - stp x21, x22, [x8], #16 - stp x23, x24, [x8], #16 - stp x25, x26, [x8], #16 - stp x27, x28, [x8], #16 - stp x29, x9, [x8], #16 - str lr, [x8] - add x8, x1, #THREAD_CPU_CONTEXT - ldp x19, x20, [x8], #16 // restore callee-saved registers - ldp x21, x22, [x8], #16 - ldp x23, x24, [x8], #16 - ldp x25, x26, [x8], #16 - ldp x27, x28, [x8], #16 - ldp x29, x9, [x8], #16 - ldr lr, [x8] - mov sp, x9 - ret -ENDPROC(cpu_switch_to) - -/* - * This is the fast syscall return path. We do as little as possible here, - * and this includes saving x0 back into the kernel stack. - */ -ret_fast_syscall: - disable_irq // disable interrupts - ldr x1, [tsk, #TI_FLAGS] - and x2, x1, #_TIF_WORK_MASK - cbnz x2, fast_work_pending - tbz x1, #TIF_SINGLESTEP, fast_exit - disable_dbg - enable_step x2 -fast_exit: - kernel_exit 0, ret = 1 - -/* - * Ok, we need to do extra processing, enter the slow path. - */ -fast_work_pending: - str x0, [sp, #S_X0] // returned x0 -work_pending: - tbnz x1, #TIF_NEED_RESCHED, work_resched - /* TIF_SIGPENDING or TIF_NOTIFY_RESUME case */ - ldr x2, [sp, #S_PSTATE] - mov x0, sp // 'regs' - tst x2, #PSR_MODE_MASK // user mode regs? - b.ne no_work_pending // returning to kernel - bl do_notify_resume - b ret_to_user -work_resched: - enable_dbg - bl schedule - -/* - * "slow" syscall return path. - */ -ENTRY(ret_to_user) - disable_irq // disable interrupts - ldr x1, [tsk, #TI_FLAGS] - and x2, x1, #_TIF_WORK_MASK - cbnz x2, work_pending - tbz x1, #TIF_SINGLESTEP, no_work_pending - disable_dbg - enable_step x2 -no_work_pending: - kernel_exit 0, ret = 0 -ENDPROC(ret_to_user) - -/* - * This is how we return from a fork. - */ -ENTRY(ret_from_fork) - bl schedule_tail - get_thread_info tsk - b ret_to_user -ENDPROC(ret_from_fork) - -/* - * SVC handler. - */ - .align 6 -el0_svc: - adrp stbl, sys_call_table // load syscall table pointer - uxtw scno, w8 // syscall number in w8 - mov sc_nr, #__NR_syscalls -el0_svc_naked: // compat entry point - stp x0, scno, [sp, #S_ORIG_X0] // save the original x0 and syscall number - disable_step x16 - isb - enable_dbg - enable_irq - - get_thread_info tsk - ldr x16, [tsk, #TI_FLAGS] // check for syscall tracing - tbnz x16, #TIF_SYSCALL_TRACE, __sys_trace // are we tracing syscalls? - adr lr, ret_fast_syscall // return address - cmp scno, sc_nr // check upper syscall limit - b.hs ni_sys - ldr x16, [stbl, scno, lsl #3] // address in the syscall table - br x16 // call sys_* routine -ni_sys: - mov x0, sp - b do_ni_syscall -ENDPROC(el0_svc) - - /* - * This is the really slow path. We're going to be doing context - * switches, and waiting for our parent to respond. - */ -__sys_trace: - mov x1, sp - mov w0, #0 // trace entry - bl syscall_trace - adr lr, __sys_trace_return // return address - uxtw scno, w0 // syscall number (possibly new) - mov x1, sp // pointer to regs - cmp scno, sc_nr // check upper syscall limit - b.hs ni_sys - ldp x0, x1, [sp] // restore the syscall args - ldp x2, x3, [sp, #S_X2] - ldp x4, x5, [sp, #S_X4] - ldp x6, x7, [sp, #S_X6] - ldr x16, [stbl, scno, lsl #3] // address in the syscall table - br x16 // call sys_* routine - -__sys_trace_return: - str x0, [sp] // save returned x0 - mov x1, sp - mov w0, #1 // trace exit - bl syscall_trace - b ret_to_user - -/* - * Special system call wrappers. - */ -ENTRY(sys_execve_wrapper) - mov x3, sp - b sys_execve -ENDPROC(sys_execve_wrapper) - -ENTRY(sys_clone_wrapper) - mov x5, sp - b sys_clone -ENDPROC(sys_clone_wrapper) - -ENTRY(sys_rt_sigreturn_wrapper) - mov x0, sp - b sys_rt_sigreturn -ENDPROC(sys_rt_sigreturn_wrapper) - -ENTRY(sys_sigaltstack_wrapper) - ldr x2, [sp, #S_SP] - b sys_sigaltstack -ENDPROC(sys_sigaltstack_wrapper) - -ENTRY(handle_arch_irq) - .quad 0 diff --git a/trunk/arch/arm64/kernel/fpsimd.c b/trunk/arch/arm64/kernel/fpsimd.c deleted file mode 100644 index e8b8357aedb4..000000000000 --- a/trunk/arch/arm64/kernel/fpsimd.c +++ /dev/null @@ -1,106 +0,0 @@ -/* - * FP/SIMD context switching and fault handling - * - * Copyright (C) 2012 ARM Ltd. - * Author: Catalin Marinas - * - * 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 -#include - -#define FPEXC_IOF (1 << 0) -#define FPEXC_DZF (1 << 1) -#define FPEXC_OFF (1 << 2) -#define FPEXC_UFF (1 << 3) -#define FPEXC_IXF (1 << 4) -#define FPEXC_IDF (1 << 7) - -/* - * Trapped FP/ASIMD access. - */ -void do_fpsimd_acc(unsigned int esr, struct pt_regs *regs) -{ - /* TODO: implement lazy context saving/restoring */ - WARN_ON(1); -} - -/* - * Raise a SIGFPE for the current process. - */ -void do_fpsimd_exc(unsigned int esr, struct pt_regs *regs) -{ - siginfo_t info; - unsigned int si_code = 0; - - if (esr & FPEXC_IOF) - si_code = FPE_FLTINV; - else if (esr & FPEXC_DZF) - si_code = FPE_FLTDIV; - else if (esr & FPEXC_OFF) - si_code = FPE_FLTOVF; - else if (esr & FPEXC_UFF) - si_code = FPE_FLTUND; - else if (esr & FPEXC_IXF) - si_code = FPE_FLTRES; - - memset(&info, 0, sizeof(info)); - info.si_signo = SIGFPE; - info.si_code = si_code; - info.si_addr = (void __user *)instruction_pointer(regs); - - send_sig_info(SIGFPE, &info, current); -} - -void fpsimd_thread_switch(struct task_struct *next) -{ - /* check if not kernel threads */ - if (current->mm) - fpsimd_save_state(¤t->thread.fpsimd_state); - if (next->mm) - fpsimd_load_state(&next->thread.fpsimd_state); -} - -void fpsimd_flush_thread(void) -{ - memset(¤t->thread.fpsimd_state, 0, sizeof(struct fpsimd_state)); - fpsimd_load_state(¤t->thread.fpsimd_state); -} - -/* - * FP/SIMD support code initialisation. - */ -static int __init fpsimd_init(void) -{ - u64 pfr = read_cpuid(ID_AA64PFR0_EL1); - - if (pfr & (0xf << 16)) { - pr_notice("Floating-point is not implemented\n"); - return 0; - } - elf_hwcap |= HWCAP_FP; - - if (pfr & (0xf << 20)) - pr_notice("Advanced SIMD is not implemented\n"); - else - elf_hwcap |= HWCAP_ASIMD; - - return 0; -} -late_initcall(fpsimd_init); diff --git a/trunk/arch/arm64/kernel/head.S b/trunk/arch/arm64/kernel/head.S deleted file mode 100644 index a2f02b63eae9..000000000000 --- a/trunk/arch/arm64/kernel/head.S +++ /dev/null @@ -1,510 +0,0 @@ -/* - * Low-level CPU initialisation - * Based on arch/arm/kernel/head.S - * - * Copyright (C) 1994-2002 Russell King - * Copyright (C) 2003-2012 ARM Ltd. - * Authors: Catalin Marinas - * Will Deacon - * - * 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 -#include -#include -#include -#include -#include - -/* - * swapper_pg_dir is the virtual address of the initial page table. We place - * the page tables 3 * PAGE_SIZE below KERNEL_RAM_VADDR. The idmap_pg_dir has - * 2 pages and is placed below swapper_pg_dir. - */ -#define KERNEL_RAM_VADDR (PAGE_OFFSET + TEXT_OFFSET) - -#if (KERNEL_RAM_VADDR & 0xfffff) != 0x80000 -#error KERNEL_RAM_VADDR must start at 0xXXX80000 -#endif - -#define SWAPPER_DIR_SIZE (3 * PAGE_SIZE) -#define IDMAP_DIR_SIZE (2 * PAGE_SIZE) - - .globl swapper_pg_dir - .equ swapper_pg_dir, KERNEL_RAM_VADDR - SWAPPER_DIR_SIZE - - .globl idmap_pg_dir - .equ idmap_pg_dir, swapper_pg_dir - IDMAP_DIR_SIZE - - .macro pgtbl, ttb0, ttb1, phys - add \ttb1, \phys, #TEXT_OFFSET - SWAPPER_DIR_SIZE - sub \ttb0, \ttb1, #IDMAP_DIR_SIZE - .endm - -#ifdef CONFIG_ARM64_64K_PAGES -#define BLOCK_SHIFT PAGE_SHIFT -#define BLOCK_SIZE PAGE_SIZE -#else -#define BLOCK_SHIFT SECTION_SHIFT -#define BLOCK_SIZE SECTION_SIZE -#endif - -#define KERNEL_START KERNEL_RAM_VADDR -#define KERNEL_END _end - -/* - * Initial memory map attributes. - */ -#ifndef CONFIG_SMP -#define PTE_FLAGS PTE_TYPE_PAGE | PTE_AF -#define PMD_FLAGS PMD_TYPE_SECT | PMD_SECT_AF -#else -#define PTE_FLAGS PTE_TYPE_PAGE | PTE_AF | PTE_SHARED -#define PMD_FLAGS PMD_TYPE_SECT | PMD_SECT_AF | PMD_SECT_S -#endif - -#ifdef CONFIG_ARM64_64K_PAGES -#define MM_MMUFLAGS PTE_ATTRINDX(MT_NORMAL) | PTE_FLAGS -#define IO_MMUFLAGS PTE_ATTRINDX(MT_DEVICE_nGnRE) | PTE_XN | PTE_FLAGS -#else -#define MM_MMUFLAGS PMD_ATTRINDX(MT_NORMAL) | PMD_FLAGS -#define IO_MMUFLAGS PMD_ATTRINDX(MT_DEVICE_nGnRE) | PMD_SECT_XN | PMD_FLAGS -#endif - -/* - * Kernel startup entry point. - * --------------------------- - * - * The requirements are: - * MMU = off, D-cache = off, I-cache = on or off, - * x0 = physical address to the FDT blob. - * - * This code is mostly position independent so you call this at - * __pa(PAGE_OFFSET + TEXT_OFFSET). - * - * Note that the callee-saved registers are used for storing variables - * that are useful before the MMU is enabled. The allocations are described - * in the entry routines. - */ - __HEAD - - /* - * DO NOT MODIFY. Image header expected by Linux boot-loaders. - */ - b stext // branch to kernel start, magic - .long 0 // reserved - .quad TEXT_OFFSET // Image load offset from start of RAM - .quad 0 // reserved - .quad 0 // reserved - -ENTRY(stext) - mov x21, x0 // x21=FDT - bl el2_setup // Drop to EL1 - mrs x22, midr_el1 // x22=cpuid - mov x0, x22 - bl lookup_processor_type - mov x23, x0 // x23=current cpu_table - cbz x23, __error_p // invalid processor (x23=0)? - bl __calc_phys_offset // x24=PHYS_OFFSET, x28=PHYS_OFFSET-PAGE_OFFSET - bl __vet_fdt - bl __create_page_tables // x25=TTBR0, x26=TTBR1 - /* - * The following calls CPU specific code in a position independent - * manner. See arch/arm64/mm/proc.S for details. x23 = base of - * cpu_info structure selected by lookup_processor_type above. - * On return, the CPU will be ready for the MMU to be turned on and - * the TCR will have been set. - */ - ldr x27, __switch_data // address to jump to after - // MMU has been enabled - adr lr, __enable_mmu // return (PIC) address - ldr x12, [x23, #CPU_INFO_SETUP] - add x12, x12, x28 // __virt_to_phys - br x12 // initialise processor -ENDPROC(stext) - -/* - * If we're fortunate enough to boot at EL2, ensure that the world is - * sane before dropping to EL1. - */ -ENTRY(el2_setup) - mrs x0, CurrentEL - cmp x0, #PSR_MODE_EL2t - ccmp x0, #PSR_MODE_EL2h, #0x4, ne - b.eq 1f - ret - - /* Hyp configuration. */ -1: mov x0, #(1 << 31) // 64-bit EL1 - msr hcr_el2, x0 - - /* Generic timers. */ - mrs x0, cnthctl_el2 - orr x0, x0, #3 // Enable EL1 physical timers - msr cnthctl_el2, x0 - - /* Populate ID registers. */ - mrs x0, midr_el1 - mrs x1, mpidr_el1 - msr vpidr_el2, x0 - msr vmpidr_el2, x1 - - /* sctlr_el1 */ - mov x0, #0x0800 // Set/clear RES{1,0} bits - movk x0, #0x30d0, lsl #16 - msr sctlr_el1, x0 - - /* Coprocessor traps. */ - mov x0, #0x33ff - msr cptr_el2, x0 // Disable copro. traps to EL2 - -#ifdef CONFIG_COMPAT - msr hstr_el2, xzr // Disable CP15 traps to EL2 -#endif - - /* spsr */ - mov x0, #(PSR_F_BIT | PSR_I_BIT | PSR_A_BIT | PSR_D_BIT |\ - PSR_MODE_EL1h) - msr spsr_el2, x0 - msr elr_el2, lr - eret -ENDPROC(el2_setup) - - .align 3 -2: .quad . - .quad PAGE_OFFSET - -#ifdef CONFIG_SMP - .pushsection .smp.pen.text, "ax" - .align 3 -1: .quad . - .quad secondary_holding_pen_release - - /* - * This provides a "holding pen" for platforms to hold all secondary - * cores are held until we're ready for them to initialise. - */ -ENTRY(secondary_holding_pen) - bl el2_setup // Drop to EL1 - mrs x0, mpidr_el1 - and x0, x0, #15 // CPU number - adr x1, 1b - ldp x2, x3, [x1] - sub x1, x1, x2 - add x3, x3, x1 -pen: ldr x4, [x3] - cmp x4, x0 - b.eq secondary_startup - wfe - b pen -ENDPROC(secondary_holding_pen) - .popsection - -ENTRY(secondary_startup) - /* - * Common entry point for secondary CPUs. - */ - mrs x22, midr_el1 // x22=cpuid - mov x0, x22 - bl lookup_processor_type - mov x23, x0 // x23=current cpu_table - cbz x23, __error_p // invalid processor (x23=0)? - - bl __calc_phys_offset // x24=phys offset - pgtbl x25, x26, x24 // x25=TTBR0, x26=TTBR1 - ldr x12, [x23, #CPU_INFO_SETUP] - add x12, x12, x28 // __virt_to_phys - blr x12 // initialise processor - - ldr x21, =secondary_data - ldr x27, =__secondary_switched // address to jump to after enabling the MMU - b __enable_mmu -ENDPROC(secondary_startup) - -ENTRY(__secondary_switched) - ldr x0, [x21] // get secondary_data.stack - mov sp, x0 - mov x29, #0 - b secondary_start_kernel -ENDPROC(__secondary_switched) -#endif /* CONFIG_SMP */ - -/* - * Setup common bits before finally enabling the MMU. Essentially this is just - * loading the page table pointer and vector base registers. - * - * On entry to this code, x0 must contain the SCTLR_EL1 value for turning on - * the MMU. - */ -__enable_mmu: - ldr x5, =vectors - msr vbar_el1, x5 - msr ttbr0_el1, x25 // load TTBR0 - msr ttbr1_el1, x26 // load TTBR1 - isb - b __turn_mmu_on -ENDPROC(__enable_mmu) - -/* - * Enable the MMU. This completely changes the structure of the visible memory - * space. You will not be able to trace execution through this. - * - * x0 = system control register - * x27 = *virtual* address to jump to upon completion - * - * other registers depend on the function called upon completion - */ - .align 6 -__turn_mmu_on: - msr sctlr_el1, x0 - isb - br x27 -ENDPROC(__turn_mmu_on) - -/* - * Calculate the start of physical memory. - */ -__calc_phys_offset: - adr x0, 1f - ldp x1, x2, [x0] - sub x28, x0, x1 // x28 = PHYS_OFFSET - PAGE_OFFSET - add x24, x2, x28 // x24 = PHYS_OFFSET - ret -ENDPROC(__calc_phys_offset) - - .align 3 -1: .quad . - .quad PAGE_OFFSET - -/* - * Macro to populate the PGD for the corresponding block entry in the next - * level (tbl) for the given virtual address. - * - * Preserves: pgd, tbl, virt - * Corrupts: tmp1, tmp2 - */ - .macro create_pgd_entry, pgd, tbl, virt, tmp1, tmp2 - lsr \tmp1, \virt, #PGDIR_SHIFT - and \tmp1, \tmp1, #PTRS_PER_PGD - 1 // PGD index - orr \tmp2, \tbl, #3 // PGD entry table type - str \tmp2, [\pgd, \tmp1, lsl #3] - .endm - -/* - * Macro to populate block entries in the page table for the start..end - * virtual range (inclusive). - * - * Preserves: tbl, flags - * Corrupts: phys, start, end, pstate - */ - .macro create_block_map, tbl, flags, phys, start, end, idmap=0 - lsr \phys, \phys, #BLOCK_SHIFT - .if \idmap - and \start, \phys, #PTRS_PER_PTE - 1 // table index - .else - lsr \start, \start, #BLOCK_SHIFT - and \start, \start, #PTRS_PER_PTE - 1 // table index - .endif - orr \phys, \flags, \phys, lsl #BLOCK_SHIFT // table entry - .ifnc \start,\end - lsr \end, \end, #BLOCK_SHIFT - and \end, \end, #PTRS_PER_PTE - 1 // table end index - .endif -9999: str \phys, [\tbl, \start, lsl #3] // store the entry - .ifnc \start,\end - add \start, \start, #1 // next entry - add \phys, \phys, #BLOCK_SIZE // next block - cmp \start, \end - b.ls 9999b - .endif - .endm - -/* - * Setup the initial page tables. We only setup the barest amount which is - * required to get the kernel running. The following sections are required: - * - identity mapping to enable the MMU (low address, TTBR0) - * - first few MB of the kernel linear mapping to jump to once the MMU has - * been enabled, including the FDT blob (TTBR1) - */ -__create_page_tables: - pgtbl x25, x26, x24 // idmap_pg_dir and swapper_pg_dir addresses - - /* - * Clear the idmap and swapper page tables. - */ - mov x0, x25 - add x6, x26, #SWAPPER_DIR_SIZE -1: stp xzr, xzr, [x0], #16 - stp xzr, xzr, [x0], #16 - stp xzr, xzr, [x0], #16 - stp xzr, xzr, [x0], #16 - cmp x0, x6 - b.lo 1b - - ldr x7, =MM_MMUFLAGS - - /* - * Create the identity mapping. - */ - add x0, x25, #PAGE_SIZE // section table address - adr x3, __turn_mmu_on // virtual/physical address - create_pgd_entry x25, x0, x3, x5, x6 - create_block_map x0, x7, x3, x5, x5, idmap=1 - - /* - * Map the kernel image (starting with PHYS_OFFSET). - */ - add x0, x26, #PAGE_SIZE // section table address - mov x5, #PAGE_OFFSET - create_pgd_entry x26, x0, x5, x3, x6 - ldr x6, =KERNEL_END - 1 - mov x3, x24 // phys offset - create_block_map x0, x7, x3, x5, x6 - - /* - * Map the FDT blob (maximum 2MB; must be within 512MB of - * PHYS_OFFSET). - */ - mov x3, x21 // FDT phys address - and x3, x3, #~((1 << 21) - 1) // 2MB aligned - mov x6, #PAGE_OFFSET - sub x5, x3, x24 // subtract PHYS_OFFSET - tst x5, #~((1 << 29) - 1) // within 512MB? - csel x21, xzr, x21, ne // zero the FDT pointer - b.ne 1f - add x5, x5, x6 // __va(FDT blob) - add x6, x5, #1 << 21 // 2MB for the FDT blob - sub x6, x6, #1 // inclusive range - create_block_map x0, x7, x3, x5, x6 -1: - ret -ENDPROC(__create_page_tables) - .ltorg - - .align 3 - .type __switch_data, %object -__switch_data: - .quad __mmap_switched - .quad __data_loc // x4 - .quad _data // x5 - .quad __bss_start // x6 - .quad _end // x7 - .quad processor_id // x4 - .quad __fdt_pointer // x5 - .quad memstart_addr // x6 - .quad init_thread_union + THREAD_START_SP // sp - -/* - * The following fragment of code is executed with the MMU on in MMU mode, and - * uses absolute addresses; this is not position independent. - */ -__mmap_switched: - adr x3, __switch_data + 8 - - ldp x4, x5, [x3], #16 - ldp x6, x7, [x3], #16 - cmp x4, x5 // Copy data segment if needed -1: ccmp x5, x6, #4, ne - b.eq 2f - ldr x16, [x4], #8 - str x16, [x5], #8 - b 1b -2: -1: cmp x6, x7 - b.hs 2f - str xzr, [x6], #8 // Clear BSS - b 1b -2: - ldp x4, x5, [x3], #16 - ldr x6, [x3], #8 - ldr x16, [x3] - mov sp, x16 - str x22, [x4] // Save processor ID - str x21, [x5] // Save FDT pointer - str x24, [x6] // Save PHYS_OFFSET - mov x29, #0 - b start_kernel -ENDPROC(__mmap_switched) - -/* - * Exception handling. Something went wrong and we can't proceed. We ought to - * tell the user, but since we don't have any guarantee that we're even - * running on the right architecture, we do virtually nothing. - */ -__error_p: -ENDPROC(__error_p) - -__error: -1: nop - b 1b -ENDPROC(__error) - -/* - * This function gets the processor ID in w0 and searches the cpu_table[] for - * a match. It returns a pointer to the struct cpu_info it found. The - * cpu_table[] must end with an empty (all zeros) structure. - * - * This routine can be called via C code and it needs to work with the MMU - * both disabled and enabled (the offset is calculated automatically). - */ -ENTRY(lookup_processor_type) - adr x1, __lookup_processor_type_data - ldp x2, x3, [x1] - sub x1, x1, x2 // get offset between VA and PA - add x3, x3, x1 // convert VA to PA -1: - ldp w5, w6, [x3] // load cpu_id_val and cpu_id_mask - cbz w5, 2f // end of list? - and w6, w6, w0 - cmp w5, w6 - b.eq 3f - add x3, x3, #CPU_INFO_SZ - b 1b -2: - mov x3, #0 // unknown processor -3: - mov x0, x3 - ret -ENDPROC(lookup_processor_type) - - .align 3 - .type __lookup_processor_type_data, %object -__lookup_processor_type_data: - .quad . - .quad cpu_table - .size __lookup_processor_type_data, . - __lookup_processor_type_data - -/* - * Determine validity of the x21 FDT pointer. - * The dtb must be 8-byte aligned and live in the first 512M of memory. - */ -__vet_fdt: - tst x21, #0x7 - b.ne 1f - cmp x21, x24 - b.lt 1f - mov x0, #(1 << 29) - add x0, x0, x24 - cmp x21, x0 - b.ge 1f - ret -1: - mov x21, #0 - ret -ENDPROC(__vet_fdt) diff --git a/trunk/arch/arm64/kernel/hw_breakpoint.c b/trunk/arch/arm64/kernel/hw_breakpoint.c deleted file mode 100644 index 5ab825c59db9..000000000000 --- a/trunk/arch/arm64/kernel/hw_breakpoint.c +++ /dev/null @@ -1,880 +0,0 @@ -/* - * HW_breakpoint: a unified kernel/user-space hardware breakpoint facility, - * using the CPU's debug registers. - * - * Copyright (C) 2012 ARM Limited - * Author: Will Deacon - * - * 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 . - */ - -#define pr_fmt(fmt) "hw-breakpoint: " fmt - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -/* Breakpoint currently in use for each BRP. */ -static DEFINE_PER_CPU(struct perf_event *, bp_on_reg[ARM_MAX_BRP]); - -/* Watchpoint currently in use for each WRP. */ -static DEFINE_PER_CPU(struct perf_event *, wp_on_reg[ARM_MAX_WRP]); - -/* Currently stepping a per-CPU kernel breakpoint. */ -static DEFINE_PER_CPU(int, stepping_kernel_bp); - -/* Number of BRP/WRP registers on this CPU. */ -static int core_num_brps; -static int core_num_wrps; - -/* Determine number of BRP registers available. */ -static int get_num_brps(void) -{ - return ((read_cpuid(ID_AA64DFR0_EL1) >> 12) & 0xf) + 1; -} - -/* Determine number of WRP registers available. */ -static int get_num_wrps(void) -{ - return ((read_cpuid(ID_AA64DFR0_EL1) >> 20) & 0xf) + 1; -} - -int hw_breakpoint_slots(int type) -{ - /* - * We can be called early, so don't rely on - * our static variables being initialised. - */ - switch (type) { - case TYPE_INST: - return get_num_brps(); - case TYPE_DATA: - return get_num_wrps(); - default: - pr_warning("unknown slot type: %d\n", type); - return 0; - } -} - -#define READ_WB_REG_CASE(OFF, N, REG, VAL) \ - case (OFF + N): \ - AARCH64_DBG_READ(N, REG, VAL); \ - break - -#define WRITE_WB_REG_CASE(OFF, N, REG, VAL) \ - case (OFF + N): \ - AARCH64_DBG_WRITE(N, REG, VAL); \ - break - -#define GEN_READ_WB_REG_CASES(OFF, REG, VAL) \ - READ_WB_REG_CASE(OFF, 0, REG, VAL); \ - READ_WB_REG_CASE(OFF, 1, REG, VAL); \ - READ_WB_REG_CASE(OFF, 2, REG, VAL); \ - READ_WB_REG_CASE(OFF, 3, REG, VAL); \ - READ_WB_REG_CASE(OFF, 4, REG, VAL); \ - READ_WB_REG_CASE(OFF, 5, REG, VAL); \ - READ_WB_REG_CASE(OFF, 6, REG, VAL); \ - READ_WB_REG_CASE(OFF, 7, REG, VAL); \ - READ_WB_REG_CASE(OFF, 8, REG, VAL); \ - READ_WB_REG_CASE(OFF, 9, REG, VAL); \ - READ_WB_REG_CASE(OFF, 10, REG, VAL); \ - READ_WB_REG_CASE(OFF, 11, REG, VAL); \ - READ_WB_REG_CASE(OFF, 12, REG, VAL); \ - READ_WB_REG_CASE(OFF, 13, REG, VAL); \ - READ_WB_REG_CASE(OFF, 14, REG, VAL); \ - READ_WB_REG_CASE(OFF, 15, REG, VAL) - -#define GEN_WRITE_WB_REG_CASES(OFF, REG, VAL) \ - WRITE_WB_REG_CASE(OFF, 0, REG, VAL); \ - WRITE_WB_REG_CASE(OFF, 1, REG, VAL); \ - WRITE_WB_REG_CASE(OFF, 2, REG, VAL); \ - WRITE_WB_REG_CASE(OFF, 3, REG, VAL); \ - WRITE_WB_REG_CASE(OFF, 4, REG, VAL); \ - WRITE_WB_REG_CASE(OFF, 5, REG, VAL); \ - WRITE_WB_REG_CASE(OFF, 6, REG, VAL); \ - WRITE_WB_REG_CASE(OFF, 7, REG, VAL); \ - WRITE_WB_REG_CASE(OFF, 8, REG, VAL); \ - WRITE_WB_REG_CASE(OFF, 9, REG, VAL); \ - WRITE_WB_REG_CASE(OFF, 10, REG, VAL); \ - WRITE_WB_REG_CASE(OFF, 11, REG, VAL); \ - WRITE_WB_REG_CASE(OFF, 12, REG, VAL); \ - WRITE_WB_REG_CASE(OFF, 13, REG, VAL); \ - WRITE_WB_REG_CASE(OFF, 14, REG, VAL); \ - WRITE_WB_REG_CASE(OFF, 15, REG, VAL) - -static u64 read_wb_reg(int reg, int n) -{ - u64 val = 0; - - switch (reg + n) { - GEN_READ_WB_REG_CASES(AARCH64_DBG_REG_BVR, AARCH64_DBG_REG_NAME_BVR, val); - GEN_READ_WB_REG_CASES(AARCH64_DBG_REG_BCR, AARCH64_DBG_REG_NAME_BCR, val); - GEN_READ_WB_REG_CASES(AARCH64_DBG_REG_WVR, AARCH64_DBG_REG_NAME_WVR, val); - GEN_READ_WB_REG_CASES(AARCH64_DBG_REG_WCR, AARCH64_DBG_REG_NAME_WCR, val); - default: - pr_warning("attempt to read from unknown breakpoint register %d\n", n); - } - - return val; -} - -static void write_wb_reg(int reg, int n, u64 val) -{ - switch (reg + n) { - GEN_WRITE_WB_REG_CASES(AARCH64_DBG_REG_BVR, AARCH64_DBG_REG_NAME_BVR, val); - GEN_WRITE_WB_REG_CASES(AARCH64_DBG_REG_BCR, AARCH64_DBG_REG_NAME_BCR, val); - GEN_WRITE_WB_REG_CASES(AARCH64_DBG_REG_WVR, AARCH64_DBG_REG_NAME_WVR, val); - GEN_WRITE_WB_REG_CASES(AARCH64_DBG_REG_WCR, AARCH64_DBG_REG_NAME_WCR, val); - default: - pr_warning("attempt to write to unknown breakpoint register %d\n", n); - } - isb(); -} - -/* - * Convert a breakpoint privilege level to the corresponding exception - * level. - */ -static enum debug_el debug_exception_level(int privilege) -{ - switch (privilege) { - case AARCH64_BREAKPOINT_EL0: - return DBG_ACTIVE_EL0; - case AARCH64_BREAKPOINT_EL1: - return DBG_ACTIVE_EL1; - default: - pr_warning("invalid breakpoint privilege level %d\n", privilege); - return -EINVAL; - } -} - -/* - * Install a perf counter breakpoint. - */ -int arch_install_hw_breakpoint(struct perf_event *bp) -{ - struct arch_hw_breakpoint *info = counter_arch_bp(bp); - struct perf_event **slot, **slots; - struct debug_info *debug_info = ¤t->thread.debug; - int i, max_slots, ctrl_reg, val_reg, reg_enable; - u32 ctrl; - - if (info->ctrl.type == ARM_BREAKPOINT_EXECUTE) { - /* Breakpoint */ - ctrl_reg = AARCH64_DBG_REG_BCR; - val_reg = AARCH64_DBG_REG_BVR; - slots = __get_cpu_var(bp_on_reg); - max_slots = core_num_brps; - reg_enable = !debug_info->bps_disabled; - } else { - /* Watchpoint */ - ctrl_reg = AARCH64_DBG_REG_WCR; - val_reg = AARCH64_DBG_REG_WVR; - slots = __get_cpu_var(wp_on_reg); - max_slots = core_num_wrps; - reg_enable = !debug_info->wps_disabled; - } - - for (i = 0; i < max_slots; ++i) { - slot = &slots[i]; - - if (!*slot) { - *slot = bp; - break; - } - } - - if (WARN_ONCE(i == max_slots, "Can't find any breakpoint slot")) - return -ENOSPC; - - /* Ensure debug monitors are enabled at the correct exception level. */ - enable_debug_monitors(debug_exception_level(info->ctrl.privilege)); - - /* Setup the address register. */ - write_wb_reg(val_reg, i, info->address); - - /* Setup the control register. */ - ctrl = encode_ctrl_reg(info->ctrl); - write_wb_reg(ctrl_reg, i, reg_enable ? ctrl | 0x1 : ctrl & ~0x1); - - return 0; -} - -void arch_uninstall_hw_breakpoint(struct perf_event *bp) -{ - struct arch_hw_breakpoint *info = counter_arch_bp(bp); - struct perf_event **slot, **slots; - int i, max_slots, base; - - if (info->ctrl.type == ARM_BREAKPOINT_EXECUTE) { - /* Breakpoint */ - base = AARCH64_DBG_REG_BCR; - slots = __get_cpu_var(bp_on_reg); - max_slots = core_num_brps; - } else { - /* Watchpoint */ - base = AARCH64_DBG_REG_WCR; - slots = __get_cpu_var(wp_on_reg); - max_slots = core_num_wrps; - } - - /* Remove the breakpoint. */ - for (i = 0; i < max_slots; ++i) { - slot = &slots[i]; - - if (*slot == bp) { - *slot = NULL; - break; - } - } - - if (WARN_ONCE(i == max_slots, "Can't find any breakpoint slot")) - return; - - /* Reset the control register. */ - write_wb_reg(base, i, 0); - - /* Release the debug monitors for the correct exception level. */ - disable_debug_monitors(debug_exception_level(info->ctrl.privilege)); -} - -static int get_hbp_len(u8 hbp_len) -{ - unsigned int len_in_bytes = 0; - - switch (hbp_len) { - case ARM_BREAKPOINT_LEN_1: - len_in_bytes = 1; - break; - case ARM_BREAKPOINT_LEN_2: - len_in_bytes = 2; - break; - case ARM_BREAKPOINT_LEN_4: - len_in_bytes = 4; - break; - case ARM_BREAKPOINT_LEN_8: - len_in_bytes = 8; - break; - } - - return len_in_bytes; -} - -/* - * Check whether bp virtual address is in kernel space. - */ -int arch_check_bp_in_kernelspace(struct perf_event *bp) -{ - unsigned int len; - unsigned long va; - struct arch_hw_breakpoint *info = counter_arch_bp(bp); - - va = info->address; - len = get_hbp_len(info->ctrl.len); - - return (va >= TASK_SIZE) && ((va + len - 1) >= TASK_SIZE); -} - -/* - * Extract generic type and length encodings from an arch_hw_breakpoint_ctrl. - * Hopefully this will disappear when ptrace can bypass the conversion - * to generic breakpoint descriptions. - */ -int arch_bp_generic_fields(struct arch_hw_breakpoint_ctrl ctrl, - int *gen_len, int *gen_type) -{ - /* Type */ - switch (ctrl.type) { - case ARM_BREAKPOINT_EXECUTE: - *gen_type = HW_BREAKPOINT_X; - break; - case ARM_BREAKPOINT_LOAD: - *gen_type = HW_BREAKPOINT_R; - break; - case ARM_BREAKPOINT_STORE: - *gen_type = HW_BREAKPOINT_W; - break; - case ARM_BREAKPOINT_LOAD | ARM_BREAKPOINT_STORE: - *gen_type = HW_BREAKPOINT_RW; - break; - default: - return -EINVAL; - } - - /* Len */ - switch (ctrl.len) { - case ARM_BREAKPOINT_LEN_1: - *gen_len = HW_BREAKPOINT_LEN_1; - break; - case ARM_BREAKPOINT_LEN_2: - *gen_len = HW_BREAKPOINT_LEN_2; - break; - case ARM_BREAKPOINT_LEN_4: - *gen_len = HW_BREAKPOINT_LEN_4; - break; - case ARM_BREAKPOINT_LEN_8: - *gen_len = HW_BREAKPOINT_LEN_8; - break; - default: - return -EINVAL; - } - - return 0; -} - -/* - * Construct an arch_hw_breakpoint from a perf_event. - */ -static int arch_build_bp_info(struct perf_event *bp) -{ - struct arch_hw_breakpoint *info = counter_arch_bp(bp); - - /* Type */ - switch (bp->attr.bp_type) { - case HW_BREAKPOINT_X: - info->ctrl.type = ARM_BREAKPOINT_EXECUTE; - break; - case HW_BREAKPOINT_R: - info->ctrl.type = ARM_BREAKPOINT_LOAD; - break; - case HW_BREAKPOINT_W: - info->ctrl.type = ARM_BREAKPOINT_STORE; - break; - case HW_BREAKPOINT_RW: - info->ctrl.type = ARM_BREAKPOINT_LOAD | ARM_BREAKPOINT_STORE; - break; - default: - return -EINVAL; - } - - /* Len */ - switch (bp->attr.bp_len) { - case HW_BREAKPOINT_LEN_1: - info->ctrl.len = ARM_BREAKPOINT_LEN_1; - break; - case HW_BREAKPOINT_LEN_2: - info->ctrl.len = ARM_BREAKPOINT_LEN_2; - break; - case HW_BREAKPOINT_LEN_4: - info->ctrl.len = ARM_BREAKPOINT_LEN_4; - break; - case HW_BREAKPOINT_LEN_8: - info->ctrl.len = ARM_BREAKPOINT_LEN_8; - break; - default: - return -EINVAL; - } - - /* - * On AArch64, we only permit breakpoints of length 4, whereas - * AArch32 also requires breakpoints of length 2 for Thumb. - * Watchpoints can be of length 1, 2, 4 or 8 bytes. - */ - if (info->ctrl.type == ARM_BREAKPOINT_EXECUTE) { - if (is_compat_task()) { - if (info->ctrl.len != ARM_BREAKPOINT_LEN_2 && - info->ctrl.len != ARM_BREAKPOINT_LEN_4) - return -EINVAL; - } else if (info->ctrl.len != ARM_BREAKPOINT_LEN_4) { - /* - * FIXME: Some tools (I'm looking at you perf) assume - * that breakpoints should be sizeof(long). This - * is nonsense. For now, we fix up the parameter - * but we should probably return -EINVAL instead. - */ - info->ctrl.len = ARM_BREAKPOINT_LEN_4; - } - } - - /* Address */ - info->address = bp->attr.bp_addr; - - /* - * Privilege - * Note that we disallow combined EL0/EL1 breakpoints because - * that would complicate the stepping code. - */ - if (arch_check_bp_in_kernelspace(bp)) - info->ctrl.privilege = AARCH64_BREAKPOINT_EL1; - else - info->ctrl.privilege = AARCH64_BREAKPOINT_EL0; - - /* Enabled? */ - info->ctrl.enabled = !bp->attr.disabled; - - return 0; -} - -/* - * Validate the arch-specific HW Breakpoint register settings. - */ -int arch_validate_hwbkpt_settings(struct perf_event *bp) -{ - struct arch_hw_breakpoint *info = counter_arch_bp(bp); - int ret; - u64 alignment_mask, offset; - - /* Build the arch_hw_breakpoint. */ - ret = arch_build_bp_info(bp); - if (ret) - return ret; - - /* - * Check address alignment. - * We don't do any clever alignment correction for watchpoints - * because using 64-bit unaligned addresses is deprecated for - * AArch64. - * - * AArch32 tasks expect some simple alignment fixups, so emulate - * that here. - */ - if (is_compat_task()) { - if (info->ctrl.len == ARM_BREAKPOINT_LEN_8) - alignment_mask = 0x7; - else - alignment_mask = 0x3; - offset = info->address & alignment_mask; - switch (offset) { - case 0: - /* Aligned */ - break; - case 1: - /* Allow single byte watchpoint. */ - if (info->ctrl.len == ARM_BREAKPOINT_LEN_1) - break; - case 2: - /* Allow halfword watchpoints and breakpoints. */ - if (info->ctrl.len == ARM_BREAKPOINT_LEN_2) - break; - default: - return -EINVAL; - } - - info->address &= ~alignment_mask; - info->ctrl.len <<= offset; - } else { - if (info->ctrl.type == ARM_BREAKPOINT_EXECUTE) - alignment_mask = 0x3; - else - alignment_mask = 0x7; - if (info->address & alignment_mask) - return -EINVAL; - } - - /* - * Disallow per-task kernel breakpoints since these would - * complicate the stepping code. - */ - if (info->ctrl.privilege == AARCH64_BREAKPOINT_EL1 && bp->hw.bp_target) - return -EINVAL; - - return 0; -} - -/* - * Enable/disable all of the breakpoints active at the specified - * exception level at the register level. - * This is used when single-stepping after a breakpoint exception. - */ -static void toggle_bp_registers(int reg, enum debug_el el, int enable) -{ - int i, max_slots, privilege; - u32 ctrl; - struct perf_event **slots; - - switch (reg) { - case AARCH64_DBG_REG_BCR: - slots = __get_cpu_var(bp_on_reg); - max_slots = core_num_brps; - break; - case AARCH64_DBG_REG_WCR: - slots = __get_cpu_var(wp_on_reg); - max_slots = core_num_wrps; - break; - default: - return; - } - - for (i = 0; i < max_slots; ++i) { - if (!slots[i]) - continue; - - privilege = counter_arch_bp(slots[i])->ctrl.privilege; - if (debug_exception_level(privilege) != el) - continue; - - ctrl = read_wb_reg(reg, i); - if (enable) - ctrl |= 0x1; - else - ctrl &= ~0x1; - write_wb_reg(reg, i, ctrl); - } -} - -/* - * Debug exception handlers. - */ -static int breakpoint_handler(unsigned long unused, unsigned int esr, - struct pt_regs *regs) -{ - int i, step = 0, *kernel_step; - u32 ctrl_reg; - u64 addr, val; - struct perf_event *bp, **slots; - struct debug_info *debug_info; - struct arch_hw_breakpoint_ctrl ctrl; - - slots = (struct perf_event **)__get_cpu_var(bp_on_reg); - addr = instruction_pointer(regs); - debug_info = ¤t->thread.debug; - - for (i = 0; i < core_num_brps; ++i) { - rcu_read_lock(); - - bp = slots[i]; - - if (bp == NULL) - goto unlock; - - /* Check if the breakpoint value matches. */ - val = read_wb_reg(AARCH64_DBG_REG_BVR, i); - if (val != (addr & ~0x3)) - goto unlock; - - /* Possible match, check the byte address select to confirm. */ - ctrl_reg = read_wb_reg(AARCH64_DBG_REG_BCR, i); - decode_ctrl_reg(ctrl_reg, &ctrl); - if (!((1 << (addr & 0x3)) & ctrl.len)) - goto unlock; - - counter_arch_bp(bp)->trigger = addr; - perf_bp_event(bp, regs); - - /* Do we need to handle the stepping? */ - if (!bp->overflow_handler) - step = 1; -unlock: - rcu_read_unlock(); - } - - if (!step) - return 0; - - if (user_mode(regs)) { - debug_info->bps_disabled = 1; - toggle_bp_registers(AARCH64_DBG_REG_BCR, DBG_ACTIVE_EL0, 0); - - /* If we're already stepping a watchpoint, just return. */ - if (debug_info->wps_disabled) - return 0; - - if (test_thread_flag(TIF_SINGLESTEP)) - debug_info->suspended_step = 1; - else - user_enable_single_step(current); - } else { - toggle_bp_registers(AARCH64_DBG_REG_BCR, DBG_ACTIVE_EL1, 0); - kernel_step = &__get_cpu_var(stepping_kernel_bp); - - if (*kernel_step != ARM_KERNEL_STEP_NONE) - return 0; - - if (kernel_active_single_step()) { - *kernel_step = ARM_KERNEL_STEP_SUSPEND; - } else { - *kernel_step = ARM_KERNEL_STEP_ACTIVE; - kernel_enable_single_step(regs); - } - } - - return 0; -} - -static int watchpoint_handler(unsigned long addr, unsigned int esr, - struct pt_regs *regs) -{ - int i, step = 0, *kernel_step, access; - u32 ctrl_reg; - u64 val, alignment_mask; - struct perf_event *wp, **slots; - struct debug_info *debug_info; - struct arch_hw_breakpoint *info; - struct arch_hw_breakpoint_ctrl ctrl; - - slots = (struct perf_event **)__get_cpu_var(wp_on_reg); - debug_info = ¤t->thread.debug; - - for (i = 0; i < core_num_wrps; ++i) { - rcu_read_lock(); - - wp = slots[i]; - - if (wp == NULL) - goto unlock; - - info = counter_arch_bp(wp); - /* AArch32 watchpoints are either 4 or 8 bytes aligned. */ - if (is_compat_task()) { - if (info->ctrl.len == ARM_BREAKPOINT_LEN_8) - alignment_mask = 0x7; - else - alignment_mask = 0x3; - } else { - alignment_mask = 0x7; - } - - /* Check if the watchpoint value matches. */ - val = read_wb_reg(AARCH64_DBG_REG_WVR, i); - if (val != (addr & ~alignment_mask)) - goto unlock; - - /* Possible match, check the byte address select to confirm. */ - ctrl_reg = read_wb_reg(AARCH64_DBG_REG_WCR, i); - decode_ctrl_reg(ctrl_reg, &ctrl); - if (!((1 << (addr & alignment_mask)) & ctrl.len)) - goto unlock; - - /* - * Check that the access type matches. - * 0 => load, otherwise => store - */ - access = (esr & AARCH64_ESR_ACCESS_MASK) ? HW_BREAKPOINT_W : - HW_BREAKPOINT_R; - if (!(access & hw_breakpoint_type(wp))) - goto unlock; - - info->trigger = addr; - perf_bp_event(wp, regs); - - /* Do we need to handle the stepping? */ - if (!wp->overflow_handler) - step = 1; - -unlock: - rcu_read_unlock(); - } - - if (!step) - return 0; - - /* - * We always disable EL0 watchpoints because the kernel can - * cause these to fire via an unprivileged access. - */ - toggle_bp_registers(AARCH64_DBG_REG_WCR, DBG_ACTIVE_EL0, 0); - - if (user_mode(regs)) { - debug_info->wps_disabled = 1; - - /* If we're already stepping a breakpoint, just return. */ - if (debug_info->bps_disabled) - return 0; - - if (test_thread_flag(TIF_SINGLESTEP)) - debug_info->suspended_step = 1; - else - user_enable_single_step(current); - } else { - toggle_bp_registers(AARCH64_DBG_REG_WCR, DBG_ACTIVE_EL1, 0); - kernel_step = &__get_cpu_var(stepping_kernel_bp); - - if (*kernel_step != ARM_KERNEL_STEP_NONE) - return 0; - - if (kernel_active_single_step()) { - *kernel_step = ARM_KERNEL_STEP_SUSPEND; - } else { - *kernel_step = ARM_KERNEL_STEP_ACTIVE; - kernel_enable_single_step(regs); - } - } - - return 0; -} - -/* - * Handle single-step exception. - */ -int reinstall_suspended_bps(struct pt_regs *regs) -{ - struct debug_info *debug_info = ¤t->thread.debug; - int handled_exception = 0, *kernel_step; - - kernel_step = &__get_cpu_var(stepping_kernel_bp); - - /* - * Called from single-step exception handler. - * Return 0 if execution can resume, 1 if a SIGTRAP should be - * reported. - */ - if (user_mode(regs)) { - if (debug_info->bps_disabled) { - debug_info->bps_disabled = 0; - toggle_bp_registers(AARCH64_DBG_REG_BCR, DBG_ACTIVE_EL0, 1); - handled_exception = 1; - } - - if (debug_info->wps_disabled) { - debug_info->wps_disabled = 0; - toggle_bp_registers(AARCH64_DBG_REG_WCR, DBG_ACTIVE_EL0, 1); - handled_exception = 1; - } - - if (handled_exception) { - if (debug_info->suspended_step) { - debug_info->suspended_step = 0; - /* Allow exception handling to fall-through. */ - handled_exception = 0; - } else { - user_disable_single_step(current); - } - } - } else if (*kernel_step != ARM_KERNEL_STEP_NONE) { - toggle_bp_registers(AARCH64_DBG_REG_BCR, DBG_ACTIVE_EL1, 1); - toggle_bp_registers(AARCH64_DBG_REG_WCR, DBG_ACTIVE_EL1, 1); - - if (!debug_info->wps_disabled) - toggle_bp_registers(AARCH64_DBG_REG_WCR, DBG_ACTIVE_EL0, 1); - - if (*kernel_step != ARM_KERNEL_STEP_SUSPEND) { - kernel_disable_single_step(); - handled_exception = 1; - } else { - handled_exception = 0; - } - - *kernel_step = ARM_KERNEL_STEP_NONE; - } - - return !handled_exception; -} - -/* - * Context-switcher for restoring suspended breakpoints. - */ -void hw_breakpoint_thread_switch(struct task_struct *next) -{ - /* - * current next - * disabled: 0 0 => The usual case, NOTIFY_DONE - * 0 1 => Disable the registers - * 1 0 => Enable the registers - * 1 1 => NOTIFY_DONE. per-task bps will - * get taken care of by perf. - */ - - struct debug_info *current_debug_info, *next_debug_info; - - current_debug_info = ¤t->thread.debug; - next_debug_info = &next->thread.debug; - - /* Update breakpoints. */ - if (current_debug_info->bps_disabled != next_debug_info->bps_disabled) - toggle_bp_registers(AARCH64_DBG_REG_BCR, - DBG_ACTIVE_EL0, - !next_debug_info->bps_disabled); - - /* Update watchpoints. */ - if (current_debug_info->wps_disabled != next_debug_info->wps_disabled) - toggle_bp_registers(AARCH64_DBG_REG_WCR, - DBG_ACTIVE_EL0, - !next_debug_info->wps_disabled); -} - -/* - * CPU initialisation. - */ -static void reset_ctrl_regs(void *unused) -{ - int i; - - for (i = 0; i < core_num_brps; ++i) { - write_wb_reg(AARCH64_DBG_REG_BCR, i, 0UL); - write_wb_reg(AARCH64_DBG_REG_BVR, i, 0UL); - } - - for (i = 0; i < core_num_wrps; ++i) { - write_wb_reg(AARCH64_DBG_REG_WCR, i, 0UL); - write_wb_reg(AARCH64_DBG_REG_WVR, i, 0UL); - } -} - -static int __cpuinit hw_breakpoint_reset_notify(struct notifier_block *self, - unsigned long action, - void *hcpu) -{ - int cpu = (long)hcpu; - if (action == CPU_ONLINE) - smp_call_function_single(cpu, reset_ctrl_regs, NULL, 1); - return NOTIFY_OK; -} - -static struct notifier_block __cpuinitdata hw_breakpoint_reset_nb = { - .notifier_call = hw_breakpoint_reset_notify, -}; - -/* - * One-time initialisation. - */ -static int __init arch_hw_breakpoint_init(void) -{ - core_num_brps = get_num_brps(); - core_num_wrps = get_num_wrps(); - - pr_info("found %d breakpoint and %d watchpoint registers.\n", - core_num_brps, core_num_wrps); - - /* - * Reset the breakpoint resources. We assume that a halting - * debugger will leave the world in a nice state for us. - */ - smp_call_function(reset_ctrl_regs, NULL, 1); - reset_ctrl_regs(NULL); - - /* Register debug fault handlers. */ - hook_debug_fault_code(DBG_ESR_EVT_HWBP, breakpoint_handler, SIGTRAP, - TRAP_HWBKPT, "hw-breakpoint handler"); - hook_debug_fault_code(DBG_ESR_EVT_HWWP, watchpoint_handler, SIGTRAP, - TRAP_HWBKPT, "hw-watchpoint handler"); - - /* Register hotplug notifier. */ - register_cpu_notifier(&hw_breakpoint_reset_nb); - - return 0; -} -arch_initcall(arch_hw_breakpoint_init); - -void hw_breakpoint_pmu_read(struct perf_event *bp) -{ -} - -/* - * Dummy function to register with die_notifier. - */ -int hw_breakpoint_exceptions_notify(struct notifier_block *unused, - unsigned long val, void *data) -{ - return NOTIFY_DONE; -} diff --git a/trunk/arch/arm64/kernel/io.c b/trunk/arch/arm64/kernel/io.c deleted file mode 100644 index 7d37ead4d199..000000000000 --- a/trunk/arch/arm64/kernel/io.c +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Based on arch/arm/kernel/io.c - * - * Copyright (C) 2012 ARM 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 - -/* - * Copy data from IO memory space to "real" memory space. - */ -void __memcpy_fromio(void *to, const volatile void __iomem *from, size_t count) -{ - unsigned char *t = to; - while (count) { - count--; - *t = readb(from); - t++; - from++; - } -} -EXPORT_SYMBOL(__memcpy_fromio); - -/* - * Copy data from "real" memory space to IO memory space. - */ -void __memcpy_toio(volatile void __iomem *to, const void *from, size_t count) -{ - const unsigned char *f = from; - while (count) { - count--; - writeb(*f, to); - f++; - to++; - } -} -EXPORT_SYMBOL(__memcpy_toio); - -/* - * "memset" on IO memory space. - */ -void __memset_io(volatile void __iomem *dst, int c, size_t count) -{ - while (count) { - count--; - writeb(c, dst); - dst++; - } -} -EXPORT_SYMBOL(__memset_io); diff --git a/trunk/arch/arm64/kernel/irq.c b/trunk/arch/arm64/kernel/irq.c deleted file mode 100644 index 0373c6609eaf..000000000000 --- a/trunk/arch/arm64/kernel/irq.c +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Based on arch/arm/kernel/irq.c - * - * Copyright (C) 1992 Linus Torvalds - * Modifications for ARM processor Copyright (C) 1995-2000 Russell King. - * Support for Dynamic Tick Timer Copyright (C) 2004-2005 Nokia Corporation. - * Dynamic Tick Timer written by Tony Lindgren and - * Tuukka Tikkanen . - * Copyright (C) 2012 ARM 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 -#include -#include - -unsigned long irq_err_count; - -int arch_show_interrupts(struct seq_file *p, int prec) -{ -#ifdef CONFIG_SMP - show_ipi_list(p, prec); -#endif - seq_printf(p, "%*s: %10lu\n", prec, "Err", irq_err_count); - return 0; -} - -/* - * handle_IRQ handles all hardware IRQ's. Decoded IRQs should - * not come via this function. Instead, they should provide their - * own 'handler'. Used by platform code implementing C-based 1st - * level decoding. - */ -void handle_IRQ(unsigned int irq, struct pt_regs *regs) -{ - struct pt_regs *old_regs = set_irq_regs(regs); - - irq_enter(); - - /* - * Some hardware gives randomly wrong interrupts. Rather - * than crashing, do something sensible. - */ - if (unlikely(irq >= nr_irqs)) { - pr_warn_ratelimited("Bad IRQ%u\n", irq); - ack_bad_irq(irq); - } else { - generic_handle_irq(irq); - } - - irq_exit(); - set_irq_regs(old_regs); -} - -/* - * Interrupt controllers supported by the kernel. - */ -static const struct of_device_id intctrl_of_match[] __initconst = { - /* IRQ controllers { .compatible, .data } info to go here */ - {} -}; - -void __init init_IRQ(void) -{ - of_irq_init(intctrl_of_match); - - if (!handle_arch_irq) - panic("No interrupt controller found."); -} diff --git a/trunk/arch/arm64/kernel/kuser32.S b/trunk/arch/arm64/kernel/kuser32.S deleted file mode 100644 index 8b69ecb1d8bc..000000000000 --- a/trunk/arch/arm64/kernel/kuser32.S +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Low-level user helpers placed in the vectors page for AArch32. - * Based on the kuser helpers in arch/arm/kernel/entry-armv.S. - * - * Copyright (C) 2005-2011 Nicolas Pitre - * Copyright (C) 2012 ARM 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 . - * - * - * AArch32 user helpers. - * - * Each segment is 32-byte aligned and will be moved to the top of the high - * vector page. New segments (if ever needed) must be added in front of - * existing ones. This mechanism should be used only for things that are - * really small and justified, and not be abused freely. - * - * See Documentation/arm/kernel_user_helpers.txt for formal definitions. - */ - .align 5 - .globl __kuser_helper_start -__kuser_helper_start: - -__kuser_cmpxchg64: // 0xffff0f60 - .inst 0xe92d00f0 // push {r4, r5, r6, r7} - .inst 0xe1c040d0 // ldrd r4, r5, [r0] - .inst 0xe1c160d0 // ldrd r6, r7, [r1] - .inst 0xf57ff05f // dmb sy - .inst 0xe1b20f9f // 1: ldrexd r0, r1, [r2] - .inst 0xe0303004 // eors r3, r0, r4 - .inst 0x00313005 // eoreqs r3, r1, r5 - .inst 0x01a23f96 // strexdeq r3, r6, [r2] - .inst 0x03330001 // teqeq r3, #1 - .inst 0x0afffff9 // beq 1b - .inst 0xf57ff05f // dmb sy - .inst 0xe2730000 // rsbs r0, r3, #0 - .inst 0xe8bd00f0 // pop {r4, r5, r6, r7} - .inst 0xe12fff1e // bx lr - - .align 5 -__kuser_memory_barrier: // 0xffff0fa0 - .inst 0xf57ff05f // dmb sy - .inst 0xe12fff1e // bx lr - - .align 5 -__kuser_cmpxchg: // 0xffff0fc0 - .inst 0xf57ff05f // dmb sy - .inst 0xe1923f9f // 1: ldrex r3, [r2] - .inst 0xe0533000 // subs r3, r3, r0 - .inst 0x01823f91 // strexeq r3, r1, [r2] - .inst 0x03330001 // teqeq r3, #1 - .inst 0x0afffffa // beq 1b - .inst 0xe2730000 // rsbs r0, r3, #0 - .inst 0xeaffffef // b <__kuser_memory_barrier> - - .align 5 -__kuser_get_tls: // 0xffff0fe0 - .inst 0xee1d0f70 // mrc p15, 0, r0, c13, c0, 3 - .inst 0xe12fff1e // bx lr - .rep 5 - .word 0 - .endr - -__kuser_helper_version: // 0xffff0ffc - .word ((__kuser_helper_end - __kuser_helper_start) >> 5) - .globl __kuser_helper_end -__kuser_helper_end: diff --git a/trunk/arch/arm64/kernel/module.c b/trunk/arch/arm64/kernel/module.c deleted file mode 100644 index ca0e3d55da99..000000000000 --- a/trunk/arch/arm64/kernel/module.c +++ /dev/null @@ -1,456 +0,0 @@ -/* - * AArch64 loadable module support. - * - * Copyright (C) 2012 ARM Limited - * - * 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 . - * - * Author: Will Deacon - */ - -#include -#include -#include -#include -#include -#include -#include - -void *module_alloc(unsigned long size) -{ - return __vmalloc_node_range(size, 1, MODULES_VADDR, MODULES_END, - GFP_KERNEL, PAGE_KERNEL_EXEC, -1, - __builtin_return_address(0)); -} - -enum aarch64_reloc_op { - RELOC_OP_NONE, - RELOC_OP_ABS, - RELOC_OP_PREL, - RELOC_OP_PAGE, -}; - -static u64 do_reloc(enum aarch64_reloc_op reloc_op, void *place, u64 val) -{ - switch (reloc_op) { - case RELOC_OP_ABS: - return val; - case RELOC_OP_PREL: - return val - (u64)place; - case RELOC_OP_PAGE: - return (val & ~0xfff) - ((u64)place & ~0xfff); - case RELOC_OP_NONE: - return 0; - } - - pr_err("do_reloc: unknown relocation operation %d\n", reloc_op); - return 0; -} - -static int reloc_data(enum aarch64_reloc_op op, void *place, u64 val, int len) -{ - u64 imm_mask = (1 << len) - 1; - s64 sval = do_reloc(op, place, val); - - switch (len) { - case 16: - *(s16 *)place = sval; - break; - case 32: - *(s32 *)place = sval; - break; - case 64: - *(s64 *)place = sval; - break; - default: - pr_err("Invalid length (%d) for data relocation\n", len); - return 0; - } - - /* - * Extract the upper value bits (including the sign bit) and - * shift them to bit 0. - */ - sval = (s64)(sval & ~(imm_mask >> 1)) >> (len - 1); - - /* - * Overflow has occurred if the value is not representable in - * len bits (i.e the bottom len bits are not sign-extended and - * the top bits are not all zero). - */ - if ((u64)(sval + 1) > 2) - return -ERANGE; - - return 0; -} - -enum aarch64_imm_type { - INSN_IMM_MOVNZ, - INSN_IMM_MOVK, - INSN_IMM_ADR, - INSN_IMM_26, - INSN_IMM_19, - INSN_IMM_16, - INSN_IMM_14, - INSN_IMM_12, - INSN_IMM_9, -}; - -static u32 encode_insn_immediate(enum aarch64_imm_type type, u32 insn, u64 imm) -{ - u32 immlo, immhi, lomask, himask, mask; - int shift; - - switch (type) { - case INSN_IMM_MOVNZ: - /* - * For signed MOVW relocations, we have to manipulate the - * instruction encoding depending on whether or not the - * immediate is less than zero. - */ - insn &= ~(3 << 29); - if ((s64)imm >= 0) { - /* >=0: Set the instruction to MOVZ (opcode 10b). */ - insn |= 2 << 29; - } else { - /* - * <0: Set the instruction to MOVN (opcode 00b). - * Since we've masked the opcode already, we - * don't need to do anything other than - * inverting the new immediate field. - */ - imm = ~imm; - } - case INSN_IMM_MOVK: - mask = BIT(16) - 1; - shift = 5; - break; - case INSN_IMM_ADR: - lomask = 0x3; - himask = 0x7ffff; - immlo = imm & lomask; - imm >>= 2; - immhi = imm & himask; - imm = (immlo << 24) | (immhi); - mask = (lomask << 24) | (himask); - shift = 5; - break; - case INSN_IMM_26: - mask = BIT(26) - 1; - shift = 0; - break; - case INSN_IMM_19: - mask = BIT(19) - 1; - shift = 5; - break; - case INSN_IMM_16: - mask = BIT(16) - 1; - shift = 5; - break; - case INSN_IMM_14: - mask = BIT(14) - 1; - shift = 5; - break; - case INSN_IMM_12: - mask = BIT(12) - 1; - shift = 10; - break; - case INSN_IMM_9: - mask = BIT(9) - 1; - shift = 12; - break; - default: - pr_err("encode_insn_immediate: unknown immediate encoding %d\n", - type); - return 0; - } - - /* Update the immediate field. */ - insn &= ~(mask << shift); - insn |= (imm & mask) << shift; - - return insn; -} - -static int reloc_insn_movw(enum aarch64_reloc_op op, void *place, u64 val, - int lsb, enum aarch64_imm_type imm_type) -{ - u64 imm, limit = 0; - s64 sval; - u32 insn = *(u32 *)place; - - sval = do_reloc(op, place, val); - sval >>= lsb; - imm = sval & 0xffff; - - /* Update the instruction with the new encoding. */ - *(u32 *)place = encode_insn_immediate(imm_type, insn, imm); - - /* Shift out the immediate field. */ - sval >>= 16; - - /* - * For unsigned immediates, the overflow check is straightforward. - * For signed immediates, the sign bit is actually the bit past the - * most significant bit of the field. - * The INSN_IMM_16 immediate type is unsigned. - */ - if (imm_type != INSN_IMM_16) { - sval++; - limit++; - } - - /* Check the upper bits depending on the sign of the immediate. */ - if ((u64)sval > limit) - return -ERANGE; - - return 0; -} - -static int reloc_insn_imm(enum aarch64_reloc_op op, void *place, u64 val, - int lsb, int len, enum aarch64_imm_type imm_type) -{ - u64 imm, imm_mask; - s64 sval; - u32 insn = *(u32 *)place; - - /* Calculate the relocation value. */ - sval = do_reloc(op, place, val); - sval >>= lsb; - - /* Extract the value bits and shift them to bit 0. */ - imm_mask = (BIT(lsb + len) - 1) >> lsb; - imm = sval & imm_mask; - - /* Update the instruction's immediate field. */ - *(u32 *)place = encode_insn_immediate(imm_type, insn, imm); - - /* - * Extract the upper value bits (including the sign bit) and - * shift them to bit 0. - */ - sval = (s64)(sval & ~(imm_mask >> 1)) >> (len - 1); - - /* - * Overflow has occurred if the upper bits are not all equal to - * the sign bit of the value. - */ - if ((u64)(sval + 1) >= 2) - return -ERANGE; - - return 0; -} - -int apply_relocate_add(Elf64_Shdr *sechdrs, - const char *strtab, - unsigned int symindex, - unsigned int relsec, - struct module *me) -{ - unsigned int i; - int ovf; - bool overflow_check; - Elf64_Sym *sym; - void *loc; - u64 val; - Elf64_Rela *rel = (void *)sechdrs[relsec].sh_addr; - - for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) { - /* loc corresponds to P in the AArch64 ELF document. */ - loc = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr - + rel[i].r_offset; - - /* sym is the ELF symbol we're referring to. */ - sym = (Elf64_Sym *)sechdrs[symindex].sh_addr - + ELF64_R_SYM(rel[i].r_info); - - /* val corresponds to (S + A) in the AArch64 ELF document. */ - val = sym->st_value + rel[i].r_addend; - - /* Check for overflow by default. */ - overflow_check = true; - - /* Perform the static relocation. */ - switch (ELF64_R_TYPE(rel[i].r_info)) { - /* Null relocations. */ - case R_ARM_NONE: - case R_AARCH64_NONE: - ovf = 0; - break; - - /* Data relocations. */ - case R_AARCH64_ABS64: - overflow_check = false; - ovf = reloc_data(RELOC_OP_ABS, loc, val, 64); - break; - case R_AARCH64_ABS32: - ovf = reloc_data(RELOC_OP_ABS, loc, val, 32); - break; - case R_AARCH64_ABS16: - ovf = reloc_data(RELOC_OP_ABS, loc, val, 16); - break; - case R_AARCH64_PREL64: - overflow_check = false; - ovf = reloc_data(RELOC_OP_PREL, loc, val, 64); - break; - case R_AARCH64_PREL32: - ovf = reloc_data(RELOC_OP_PREL, loc, val, 32); - break; - case R_AARCH64_PREL16: - ovf = reloc_data(RELOC_OP_PREL, loc, val, 16); - break; - - /* MOVW instruction relocations. */ - case R_AARCH64_MOVW_UABS_G0_NC: - overflow_check = false; - case R_AARCH64_MOVW_UABS_G0: - ovf = reloc_insn_movw(RELOC_OP_ABS, loc, val, 0, - INSN_IMM_16); - break; - case R_AARCH64_MOVW_UABS_G1_NC: - overflow_check = false; - case R_AARCH64_MOVW_UABS_G1: - ovf = reloc_insn_movw(RELOC_OP_ABS, loc, val, 16, - INSN_IMM_16); - break; - case R_AARCH64_MOVW_UABS_G2_NC: - overflow_check = false; - case R_AARCH64_MOVW_UABS_G2: - ovf = reloc_insn_movw(RELOC_OP_ABS, loc, val, 32, - INSN_IMM_16); - break; - case R_AARCH64_MOVW_UABS_G3: - /* We're using the top bits so we can't overflow. */ - overflow_check = false; - ovf = reloc_insn_movw(RELOC_OP_ABS, loc, val, 48, - INSN_IMM_16); - break; - case R_AARCH64_MOVW_SABS_G0: - ovf = reloc_insn_movw(RELOC_OP_ABS, loc, val, 0, - INSN_IMM_MOVNZ); - break; - case R_AARCH64_MOVW_SABS_G1: - ovf = reloc_insn_movw(RELOC_OP_ABS, loc, val, 16, - INSN_IMM_MOVNZ); - break; - case R_AARCH64_MOVW_SABS_G2: - ovf = reloc_insn_movw(RELOC_OP_ABS, loc, val, 32, - INSN_IMM_MOVNZ); - break; - case R_AARCH64_MOVW_PREL_G0_NC: - overflow_check = false; - ovf = reloc_insn_movw(RELOC_OP_PREL, loc, val, 0, - INSN_IMM_MOVK); - break; - case R_AARCH64_MOVW_PREL_G0: - ovf = reloc_insn_movw(RELOC_OP_PREL, loc, val, 0, - INSN_IMM_MOVNZ); - break; - case R_AARCH64_MOVW_PREL_G1_NC: - overflow_check = false; - ovf = reloc_insn_movw(RELOC_OP_PREL, loc, val, 16, - INSN_IMM_MOVK); - break; - case R_AARCH64_MOVW_PREL_G1: - ovf = reloc_insn_movw(RELOC_OP_PREL, loc, val, 16, - INSN_IMM_MOVNZ); - break; - case R_AARCH64_MOVW_PREL_G2_NC: - overflow_check = false; - ovf = reloc_insn_movw(RELOC_OP_PREL, loc, val, 32, - INSN_IMM_MOVK); - break; - case R_AARCH64_MOVW_PREL_G2: - ovf = reloc_insn_movw(RELOC_OP_PREL, loc, val, 32, - INSN_IMM_MOVNZ); - break; - case R_AARCH64_MOVW_PREL_G3: - /* We're using the top bits so we can't overflow. */ - overflow_check = false; - ovf = reloc_insn_movw(RELOC_OP_PREL, loc, val, 48, - INSN_IMM_MOVNZ); - break; - - /* Immediate instruction relocations. */ - case R_AARCH64_LD_PREL_LO19: - ovf = reloc_insn_imm(RELOC_OP_PREL, loc, val, 2, 19, - INSN_IMM_19); - break; - case R_AARCH64_ADR_PREL_LO21: - ovf = reloc_insn_imm(RELOC_OP_PREL, loc, val, 0, 21, - INSN_IMM_ADR); - break; - case R_AARCH64_ADR_PREL_PG_HI21_NC: - overflow_check = false; - case R_AARCH64_ADR_PREL_PG_HI21: - ovf = reloc_insn_imm(RELOC_OP_PAGE, loc, val, 12, 21, - INSN_IMM_ADR); - break; - case R_AARCH64_ADD_ABS_LO12_NC: - case R_AARCH64_LDST8_ABS_LO12_NC: - overflow_check = false; - ovf = reloc_insn_imm(RELOC_OP_ABS, loc, val, 0, 12, - INSN_IMM_12); - break; - case R_AARCH64_LDST16_ABS_LO12_NC: - overflow_check = false; - ovf = reloc_insn_imm(RELOC_OP_ABS, loc, val, 1, 11, - INSN_IMM_12); - break; - case R_AARCH64_LDST32_ABS_LO12_NC: - overflow_check = false; - ovf = reloc_insn_imm(RELOC_OP_ABS, loc, val, 2, 10, - INSN_IMM_12); - break; - case R_AARCH64_LDST64_ABS_LO12_NC: - overflow_check = false; - ovf = reloc_insn_imm(RELOC_OP_ABS, loc, val, 3, 9, - INSN_IMM_12); - break; - case R_AARCH64_LDST128_ABS_LO12_NC: - overflow_check = false; - ovf = reloc_insn_imm(RELOC_OP_ABS, loc, val, 4, 8, - INSN_IMM_12); - break; - case R_AARCH64_TSTBR14: - ovf = reloc_insn_imm(RELOC_OP_PREL, loc, val, 2, 14, - INSN_IMM_14); - break; - case R_AARCH64_CONDBR19: - ovf = reloc_insn_imm(RELOC_OP_PREL, loc, val, 2, 19, - INSN_IMM_19); - break; - case R_AARCH64_JUMP26: - case R_AARCH64_CALL26: - ovf = reloc_insn_imm(RELOC_OP_PREL, loc, val, 2, 26, - INSN_IMM_26); - break; - - default: - pr_err("module %s: unsupported RELA relocation: %llu\n", - me->name, ELF64_R_TYPE(rel[i].r_info)); - return -ENOEXEC; - } - - if (overflow_check && ovf == -ERANGE) - goto overflow; - - } - - return 0; - -overflow: - pr_err("module %s: overflow in relocation type %d val %Lx\n", - me->name, (int)ELF64_R_TYPE(rel[i].r_info), val); - return -ENOEXEC; -} diff --git a/trunk/arch/arm64/kernel/perf_event.c b/trunk/arch/arm64/kernel/perf_event.c deleted file mode 100644 index ecbf2d81ec5c..000000000000 --- a/trunk/arch/arm64/kernel/perf_event.c +++ /dev/null @@ -1,1368 +0,0 @@ -/* - * PMU support - * - * Copyright (C) 2012 ARM Limited - * Author: Will Deacon - * - * This code is based heavily on the ARMv7 perf event code. - * - * 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 . - */ -#define pr_fmt(fmt) "hw perfevents: " fmt - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -/* - * ARMv8 supports a maximum of 32 events. - * The cycle counter is included in this total. - */ -#define ARMPMU_MAX_HWEVENTS 32 - -static DEFINE_PER_CPU(struct perf_event * [ARMPMU_MAX_HWEVENTS], hw_events); -static DEFINE_PER_CPU(unsigned long [BITS_TO_LONGS(ARMPMU_MAX_HWEVENTS)], used_mask); -static DEFINE_PER_CPU(struct pmu_hw_events, cpu_hw_events); - -#define to_arm_pmu(p) (container_of(p, struct arm_pmu, pmu)) - -/* Set at runtime when we know what CPU type we are. */ -static struct arm_pmu *cpu_pmu; - -int -armpmu_get_max_events(void) -{ - int max_events = 0; - - if (cpu_pmu != NULL) - max_events = cpu_pmu->num_events; - - return max_events; -} -EXPORT_SYMBOL_GPL(armpmu_get_max_events); - -int perf_num_counters(void) -{ - return armpmu_get_max_events(); -} -EXPORT_SYMBOL_GPL(perf_num_counters); - -#define HW_OP_UNSUPPORTED 0xFFFF - -#define C(_x) \ - PERF_COUNT_HW_CACHE_##_x - -#define CACHE_OP_UNSUPPORTED 0xFFFF - -static int -armpmu_map_cache_event(const unsigned (*cache_map) - [PERF_COUNT_HW_CACHE_MAX] - [PERF_COUNT_HW_CACHE_OP_MAX] - [PERF_COUNT_HW_CACHE_RESULT_MAX], - u64 config) -{ - unsigned int cache_type, cache_op, cache_result, ret; - - cache_type = (config >> 0) & 0xff; - if (cache_type >= PERF_COUNT_HW_CACHE_MAX) - return -EINVAL; - - cache_op = (config >> 8) & 0xff; - if (cache_op >= PERF_COUNT_HW_CACHE_OP_MAX) - return -EINVAL; - - cache_result = (config >> 16) & 0xff; - if (cache_result >= PERF_COUNT_HW_CACHE_RESULT_MAX) - return -EINVAL; - - ret = (int)(*cache_map)[cache_type][cache_op][cache_result]; - - if (ret == CACHE_OP_UNSUPPORTED) - return -ENOENT; - - return ret; -} - -static int -armpmu_map_event(const unsigned (*event_map)[PERF_COUNT_HW_MAX], u64 config) -{ - int mapping = (*event_map)[config]; - return mapping == HW_OP_UNSUPPORTED ? -ENOENT : mapping; -} - -static int -armpmu_map_raw_event(u32 raw_event_mask, u64 config) -{ - return (int)(config & raw_event_mask); -} - -static int map_cpu_event(struct perf_event *event, - const unsigned (*event_map)[PERF_COUNT_HW_MAX], - const unsigned (*cache_map) - [PERF_COUNT_HW_CACHE_MAX] - [PERF_COUNT_HW_CACHE_OP_MAX] - [PERF_COUNT_HW_CACHE_RESULT_MAX], - u32 raw_event_mask) -{ - u64 config = event->attr.config; - - switch (event->attr.type) { - case PERF_TYPE_HARDWARE: - return armpmu_map_event(event_map, config); - case PERF_TYPE_HW_CACHE: - return armpmu_map_cache_event(cache_map, config); - case PERF_TYPE_RAW: - return armpmu_map_raw_event(raw_event_mask, config); - } - - return -ENOENT; -} - -int -armpmu_event_set_period(struct perf_event *event, - struct hw_perf_event *hwc, - int idx) -{ - struct arm_pmu *armpmu = to_arm_pmu(event->pmu); - s64 left = local64_read(&hwc->period_left); - s64 period = hwc->sample_period; - int ret = 0; - - if (unlikely(left <= -period)) { - left = period; - local64_set(&hwc->period_left, left); - hwc->last_period = period; - ret = 1; - } - - if (unlikely(left <= 0)) { - left += period; - local64_set(&hwc->period_left, left); - hwc->last_period = period; - ret = 1; - } - - if (left > (s64)armpmu->max_period) - left = armpmu->max_period; - - local64_set(&hwc->prev_count, (u64)-left); - - armpmu->write_counter(idx, (u64)(-left) & 0xffffffff); - - perf_event_update_userpage(event); - - return ret; -} - -u64 -armpmu_event_update(struct perf_event *event, - struct hw_perf_event *hwc, - int idx) -{ - struct arm_pmu *armpmu = to_arm_pmu(event->pmu); - u64 delta, prev_raw_count, new_raw_count; - -again: - prev_raw_count = local64_read(&hwc->prev_count); - new_raw_count = armpmu->read_counter(idx); - - if (local64_cmpxchg(&hwc->prev_count, prev_raw_count, - new_raw_count) != prev_raw_count) - goto again; - - delta = (new_raw_count - prev_raw_count) & armpmu->max_period; - - local64_add(delta, &event->count); - local64_sub(delta, &hwc->period_left); - - return new_raw_count; -} - -static void -armpmu_read(struct perf_event *event) -{ - struct hw_perf_event *hwc = &event->hw; - - /* Don't read disabled counters! */ - if (hwc->idx < 0) - return; - - armpmu_event_update(event, hwc, hwc->idx); -} - -static void -armpmu_stop(struct perf_event *event, int flags) -{ - struct arm_pmu *armpmu = to_arm_pmu(event->pmu); - struct hw_perf_event *hwc = &event->hw; - - /* - * ARM pmu always has to update the counter, so ignore - * PERF_EF_UPDATE, see comments in armpmu_start(). - */ - if (!(hwc->state & PERF_HES_STOPPED)) { - armpmu->disable(hwc, hwc->idx); - barrier(); /* why? */ - armpmu_event_update(event, hwc, hwc->idx); - hwc->state |= PERF_HES_STOPPED | PERF_HES_UPTODATE; - } -} - -static void -armpmu_start(struct perf_event *event, int flags) -{ - struct arm_pmu *armpmu = to_arm_pmu(event->pmu); - struct hw_perf_event *hwc = &event->hw; - - /* - * ARM pmu always has to reprogram the period, so ignore - * PERF_EF_RELOAD, see the comment below. - */ - if (flags & PERF_EF_RELOAD) - WARN_ON_ONCE(!(hwc->state & PERF_HES_UPTODATE)); - - hwc->state = 0; - /* - * Set the period again. Some counters can't be stopped, so when we - * were stopped we simply disabled the IRQ source and the counter - * may have been left counting. If we don't do this step then we may - * get an interrupt too soon or *way* too late if the overflow has - * happened since disabling. - */ - armpmu_event_set_period(event, hwc, hwc->idx); - armpmu->enable(hwc, hwc->idx); -} - -static void -armpmu_del(struct perf_event *event, int flags) -{ - struct arm_pmu *armpmu = to_arm_pmu(event->pmu); - struct pmu_hw_events *hw_events = armpmu->get_hw_events(); - struct hw_perf_event *hwc = &event->hw; - int idx = hwc->idx; - - WARN_ON(idx < 0); - - armpmu_stop(event, PERF_EF_UPDATE); - hw_events->events[idx] = NULL; - clear_bit(idx, hw_events->used_mask); - - perf_event_update_userpage(event); -} - -static int -armpmu_add(struct perf_event *event, int flags) -{ - struct arm_pmu *armpmu = to_arm_pmu(event->pmu); - struct pmu_hw_events *hw_events = armpmu->get_hw_events(); - struct hw_perf_event *hwc = &event->hw; - int idx; - int err = 0; - - perf_pmu_disable(event->pmu); - - /* If we don't have a space for the counter then finish early. */ - idx = armpmu->get_event_idx(hw_events, hwc); - if (idx < 0) { - err = idx; - goto out; - } - - /* - * If there is an event in the counter we are going to use then make - * sure it is disabled. - */ - event->hw.idx = idx; - armpmu->disable(hwc, idx); - hw_events->events[idx] = event; - - hwc->state = PERF_HES_STOPPED | PERF_HES_UPTODATE; - if (flags & PERF_EF_START) - armpmu_start(event, PERF_EF_RELOAD); - - /* Propagate our changes to the userspace mapping. */ - perf_event_update_userpage(event); - -out: - perf_pmu_enable(event->pmu); - return err; -} - -static int -validate_event(struct pmu_hw_events *hw_events, - struct perf_event *event) -{ - struct arm_pmu *armpmu = to_arm_pmu(event->pmu); - struct hw_perf_event fake_event = event->hw; - struct pmu *leader_pmu = event->group_leader->pmu; - - if (event->pmu != leader_pmu || event->state <= PERF_EVENT_STATE_OFF) - return 1; - - return armpmu->get_event_idx(hw_events, &fake_event) >= 0; -} - -static int -validate_group(struct perf_event *event) -{ - struct perf_event *sibling, *leader = event->group_leader; - struct pmu_hw_events fake_pmu; - DECLARE_BITMAP(fake_used_mask, ARMPMU_MAX_HWEVENTS); - - /* - * Initialise the fake PMU. We only need to populate the - * used_mask for the purposes of validation. - */ - memset(fake_used_mask, 0, sizeof(fake_used_mask)); - fake_pmu.used_mask = fake_used_mask; - - if (!validate_event(&fake_pmu, leader)) - return -EINVAL; - - list_for_each_entry(sibling, &leader->sibling_list, group_entry) { - if (!validate_event(&fake_pmu, sibling)) - return -EINVAL; - } - - if (!validate_event(&fake_pmu, event)) - return -EINVAL; - - return 0; -} - -static void -armpmu_release_hardware(struct arm_pmu *armpmu) -{ - int i, irq, irqs; - struct platform_device *pmu_device = armpmu->plat_device; - - irqs = min(pmu_device->num_resources, num_possible_cpus()); - - for (i = 0; i < irqs; ++i) { - if (!cpumask_test_and_clear_cpu(i, &armpmu->active_irqs)) - continue; - irq = platform_get_irq(pmu_device, i); - if (irq >= 0) - free_irq(irq, armpmu); - } -} - -static int -armpmu_reserve_hardware(struct arm_pmu *armpmu) -{ - int i, err, irq, irqs; - struct platform_device *pmu_device = armpmu->plat_device; - - if (!pmu_device) { - pr_err("no PMU device registered\n"); - return -ENODEV; - } - - irqs = min(pmu_device->num_resources, num_possible_cpus()); - if (irqs < 1) { - pr_err("no irqs for PMUs defined\n"); - return -ENODEV; - } - - for (i = 0; i < irqs; ++i) { - err = 0; - irq = platform_get_irq(pmu_device, i); - if (irq < 0) - continue; - - /* - * If we have a single PMU interrupt that we can't shift, - * assume that we're running on a uniprocessor machine and - * continue. Otherwise, continue without this interrupt. - */ - if (irq_set_affinity(irq, cpumask_of(i)) && irqs > 1) { - pr_warning("unable to set irq affinity (irq=%d, cpu=%u)\n", - irq, i); - continue; - } - - err = request_irq(irq, armpmu->handle_irq, - IRQF_NOBALANCING, - "arm-pmu", armpmu); - if (err) { - pr_err("unable to request IRQ%d for ARM PMU counters\n", - irq); - armpmu_release_hardware(armpmu); - return err; - } - - cpumask_set_cpu(i, &armpmu->active_irqs); - } - - return 0; -} - -static void -hw_perf_event_destroy(struct perf_event *event) -{ - struct arm_pmu *armpmu = to_arm_pmu(event->pmu); - atomic_t *active_events = &armpmu->active_events; - struct mutex *pmu_reserve_mutex = &armpmu->reserve_mutex; - - if (atomic_dec_and_mutex_lock(active_events, pmu_reserve_mutex)) { - armpmu_release_hardware(armpmu); - mutex_unlock(pmu_reserve_mutex); - } -} - -static int -event_requires_mode_exclusion(struct perf_event_attr *attr) -{ - return attr->exclude_idle || attr->exclude_user || - attr->exclude_kernel || attr->exclude_hv; -} - -static int -__hw_perf_event_init(struct perf_event *event) -{ - struct arm_pmu *armpmu = to_arm_pmu(event->pmu); - struct hw_perf_event *hwc = &event->hw; - int mapping, err; - - mapping = armpmu->map_event(event); - - if (mapping < 0) { - pr_debug("event %x:%llx not supported\n", event->attr.type, - event->attr.config); - return mapping; - } - - /* - * We don't assign an index until we actually place the event onto - * hardware. Use -1 to signify that we haven't decided where to put it - * yet. For SMP systems, each core has it's own PMU so we can't do any - * clever allocation or constraints checking at this point. - */ - hwc->idx = -1; - hwc->config_base = 0; - hwc->config = 0; - hwc->event_base = 0; - - /* - * Check whether we need to exclude the counter from certain modes. - */ - if ((!armpmu->set_event_filter || - armpmu->set_event_filter(hwc, &event->attr)) && - event_requires_mode_exclusion(&event->attr)) { - pr_debug("ARM performance counters do not support mode exclusion\n"); - return -EPERM; - } - - /* - * Store the event encoding into the config_base field. - */ - hwc->config_base |= (unsigned long)mapping; - - if (!hwc->sample_period) { - /* - * For non-sampling runs, limit the sample_period to half - * of the counter width. That way, the new counter value - * is far less likely to overtake the previous one unless - * you have some serious IRQ latency issues. - */ - hwc->sample_period = armpmu->max_period >> 1; - hwc->last_period = hwc->sample_period; - local64_set(&hwc->period_left, hwc->sample_period); - } - - err = 0; - if (event->group_leader != event) { - err = validate_group(event); - if (err) - return -EINVAL; - } - - return err; -} - -static int armpmu_event_init(struct perf_event *event) -{ - struct arm_pmu *armpmu = to_arm_pmu(event->pmu); - int err = 0; - atomic_t *active_events = &armpmu->active_events; - - if (armpmu->map_event(event) == -ENOENT) - return -ENOENT; - - event->destroy = hw_perf_event_destroy; - - if (!atomic_inc_not_zero(active_events)) { - mutex_lock(&armpmu->reserve_mutex); - if (atomic_read(active_events) == 0) - err = armpmu_reserve_hardware(armpmu); - - if (!err) - atomic_inc(active_events); - mutex_unlock(&armpmu->reserve_mutex); - } - - if (err) - return err; - - err = __hw_perf_event_init(event); - if (err) - hw_perf_event_destroy(event); - - return err; -} - -static void armpmu_enable(struct pmu *pmu) -{ - struct arm_pmu *armpmu = to_arm_pmu(pmu); - struct pmu_hw_events *hw_events = armpmu->get_hw_events(); - int enabled = bitmap_weight(hw_events->used_mask, armpmu->num_events); - - if (enabled) - armpmu->start(); -} - -static void armpmu_disable(struct pmu *pmu) -{ - struct arm_pmu *armpmu = to_arm_pmu(pmu); - armpmu->stop(); -} - -static void __init armpmu_init(struct arm_pmu *armpmu) -{ - atomic_set(&armpmu->active_events, 0); - mutex_init(&armpmu->reserve_mutex); - - armpmu->pmu = (struct pmu) { - .pmu_enable = armpmu_enable, - .pmu_disable = armpmu_disable, - .event_init = armpmu_event_init, - .add = armpmu_add, - .del = armpmu_del, - .start = armpmu_start, - .stop = armpmu_stop, - .read = armpmu_read, - }; -} - -int __init armpmu_register(struct arm_pmu *armpmu, char *name, int type) -{ - armpmu_init(armpmu); - return perf_pmu_register(&armpmu->pmu, name, type); -} - -/* - * ARMv8 PMUv3 Performance Events handling code. - * Common event types. - */ -enum armv8_pmuv3_perf_types { - /* Required events. */ - ARMV8_PMUV3_PERFCTR_PMNC_SW_INCR = 0x00, - ARMV8_PMUV3_PERFCTR_L1_DCACHE_REFILL = 0x03, - ARMV8_PMUV3_PERFCTR_L1_DCACHE_ACCESS = 0x04, - ARMV8_PMUV3_PERFCTR_PC_BRANCH_MIS_PRED = 0x10, - ARMV8_PMUV3_PERFCTR_CLOCK_CYCLES = 0x11, - ARMV8_PMUV3_PERFCTR_PC_BRANCH_PRED = 0x12, - - /* At least one of the following is required. */ - ARMV8_PMUV3_PERFCTR_INSTR_EXECUTED = 0x08, - ARMV8_PMUV3_PERFCTR_OP_SPEC = 0x1B, - - /* Common architectural events. */ - ARMV8_PMUV3_PERFCTR_MEM_READ = 0x06, - ARMV8_PMUV3_PERFCTR_MEM_WRITE = 0x07, - ARMV8_PMUV3_PERFCTR_EXC_TAKEN = 0x09, - ARMV8_PMUV3_PERFCTR_EXC_EXECUTED = 0x0A, - ARMV8_PMUV3_PERFCTR_CID_WRITE = 0x0B, - ARMV8_PMUV3_PERFCTR_PC_WRITE = 0x0C, - ARMV8_PMUV3_PERFCTR_PC_IMM_BRANCH = 0x0D, - ARMV8_PMUV3_PERFCTR_PC_PROC_RETURN = 0x0E, - ARMV8_PMUV3_PERFCTR_MEM_UNALIGNED_ACCESS = 0x0F, - ARMV8_PMUV3_PERFCTR_TTBR_WRITE = 0x1C, - - /* Common microarchitectural events. */ - ARMV8_PMUV3_PERFCTR_L1_ICACHE_REFILL = 0x01, - ARMV8_PMUV3_PERFCTR_ITLB_REFILL = 0x02, - ARMV8_PMUV3_PERFCTR_DTLB_REFILL = 0x05, - ARMV8_PMUV3_PERFCTR_MEM_ACCESS = 0x13, - ARMV8_PMUV3_PERFCTR_L1_ICACHE_ACCESS = 0x14, - ARMV8_PMUV3_PERFCTR_L1_DCACHE_WB = 0x15, - ARMV8_PMUV3_PERFCTR_L2_CACHE_ACCESS = 0x16, - ARMV8_PMUV3_PERFCTR_L2_CACHE_REFILL = 0x17, - ARMV8_PMUV3_PERFCTR_L2_CACHE_WB = 0x18, - ARMV8_PMUV3_PERFCTR_BUS_ACCESS = 0x19, - ARMV8_PMUV3_PERFCTR_MEM_ERROR = 0x1A, - ARMV8_PMUV3_PERFCTR_BUS_CYCLES = 0x1D, - - /* - * This isn't an architected event. - * We detect this event number and use the cycle counter instead. - */ - ARMV8_PMUV3_PERFCTR_CPU_CYCLES = 0xFF, -}; - -/* PMUv3 HW events mapping. */ -static const unsigned armv8_pmuv3_perf_map[PERF_COUNT_HW_MAX] = { - [PERF_COUNT_HW_CPU_CYCLES] = ARMV8_PMUV3_PERFCTR_CPU_CYCLES, - [PERF_COUNT_HW_INSTRUCTIONS] = ARMV8_PMUV3_PERFCTR_INSTR_EXECUTED, - [PERF_COUNT_HW_CACHE_REFERENCES] = ARMV8_PMUV3_PERFCTR_L1_DCACHE_ACCESS, - [PERF_COUNT_HW_CACHE_MISSES] = ARMV8_PMUV3_PERFCTR_L1_DCACHE_REFILL, - [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = HW_OP_UNSUPPORTED, - [PERF_COUNT_HW_BRANCH_MISSES] = ARMV8_PMUV3_PERFCTR_PC_BRANCH_MIS_PRED, - [PERF_COUNT_HW_BUS_CYCLES] = HW_OP_UNSUPPORTED, - [PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = HW_OP_UNSUPPORTED, - [PERF_COUNT_HW_STALLED_CYCLES_BACKEND] = HW_OP_UNSUPPORTED, -}; - -static const unsigned armv8_pmuv3_perf_cache_map[PERF_COUNT_HW_CACHE_MAX] - [PERF_COUNT_HW_CACHE_OP_MAX] - [PERF_COUNT_HW_CACHE_RESULT_MAX] = { - [C(L1D)] = { - [C(OP_READ)] = { - [C(RESULT_ACCESS)] = ARMV8_PMUV3_PERFCTR_L1_DCACHE_ACCESS, - [C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_L1_DCACHE_REFILL, - }, - [C(OP_WRITE)] = { - [C(RESULT_ACCESS)] = ARMV8_PMUV3_PERFCTR_L1_DCACHE_ACCESS, - [C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_L1_DCACHE_REFILL, - }, - [C(OP_PREFETCH)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, - }, - }, - [C(L1I)] = { - [C(OP_READ)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, - }, - [C(OP_WRITE)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, - }, - [C(OP_PREFETCH)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, - }, - }, - [C(LL)] = { - [C(OP_READ)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, - }, - [C(OP_WRITE)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, - }, - [C(OP_PREFETCH)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, - }, - }, - [C(DTLB)] = { - [C(OP_READ)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, - }, - [C(OP_WRITE)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, - }, - [C(OP_PREFETCH)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, - }, - }, - [C(ITLB)] = { - [C(OP_READ)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, - }, - [C(OP_WRITE)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, - }, - [C(OP_PREFETCH)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, - }, - }, - [C(BPU)] = { - [C(OP_READ)] = { - [C(RESULT_ACCESS)] = ARMV8_PMUV3_PERFCTR_PC_BRANCH_PRED, - [C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_PC_BRANCH_MIS_PRED, - }, - [C(OP_WRITE)] = { - [C(RESULT_ACCESS)] = ARMV8_PMUV3_PERFCTR_PC_BRANCH_PRED, - [C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_PC_BRANCH_MIS_PRED, - }, - [C(OP_PREFETCH)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, - }, - }, - [C(NODE)] = { - [C(OP_READ)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, - }, - [C(OP_WRITE)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, - }, - [C(OP_PREFETCH)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, - }, - }, -}; - -/* - * Perf Events' indices - */ -#define ARMV8_IDX_CYCLE_COUNTER 0 -#define ARMV8_IDX_COUNTER0 1 -#define ARMV8_IDX_COUNTER_LAST (ARMV8_IDX_CYCLE_COUNTER + cpu_pmu->num_events - 1) - -#define ARMV8_MAX_COUNTERS 32 -#define ARMV8_COUNTER_MASK (ARMV8_MAX_COUNTERS - 1) - -/* - * ARMv8 low level PMU access - */ - -/* - * Perf Event to low level counters mapping - */ -#define ARMV8_IDX_TO_COUNTER(x) \ - (((x) - ARMV8_IDX_COUNTER0) & ARMV8_COUNTER_MASK) - -/* - * Per-CPU PMCR: config reg - */ -#define ARMV8_PMCR_E (1 << 0) /* Enable all counters */ -#define ARMV8_PMCR_P (1 << 1) /* Reset all counters */ -#define ARMV8_PMCR_C (1 << 2) /* Cycle counter reset */ -#define ARMV8_PMCR_D (1 << 3) /* CCNT counts every 64th cpu cycle */ -#define ARMV8_PMCR_X (1 << 4) /* Export to ETM */ -#define ARMV8_PMCR_DP (1 << 5) /* Disable CCNT if non-invasive debug*/ -#define ARMV8_PMCR_N_SHIFT 11 /* Number of counters supported */ -#define ARMV8_PMCR_N_MASK 0x1f -#define ARMV8_PMCR_MASK 0x3f /* Mask for writable bits */ - -/* - * PMOVSR: counters overflow flag status reg - */ -#define ARMV8_OVSR_MASK 0xffffffff /* Mask for writable bits */ -#define ARMV8_OVERFLOWED_MASK ARMV8_OVSR_MASK - -/* - * PMXEVTYPER: Event selection reg - */ -#define ARMV8_EVTYPE_MASK 0xc00000ff /* Mask for writable bits */ -#define ARMV8_EVTYPE_EVENT 0xff /* Mask for EVENT bits */ - -/* - * Event filters for PMUv3 - */ -#define ARMV8_EXCLUDE_EL1 (1 << 31) -#define ARMV8_EXCLUDE_EL0 (1 << 30) -#define ARMV8_INCLUDE_EL2 (1 << 27) - -static inline u32 armv8pmu_pmcr_read(void) -{ - u32 val; - asm volatile("mrs %0, pmcr_el0" : "=r" (val)); - return val; -} - -static inline void armv8pmu_pmcr_write(u32 val) -{ - val &= ARMV8_PMCR_MASK; - isb(); - asm volatile("msr pmcr_el0, %0" :: "r" (val)); -} - -static inline int armv8pmu_has_overflowed(u32 pmovsr) -{ - return pmovsr & ARMV8_OVERFLOWED_MASK; -} - -static inline int armv8pmu_counter_valid(int idx) -{ - return idx >= ARMV8_IDX_CYCLE_COUNTER && idx <= ARMV8_IDX_COUNTER_LAST; -} - -static inline int armv8pmu_counter_has_overflowed(u32 pmnc, int idx) -{ - int ret = 0; - u32 counter; - - if (!armv8pmu_counter_valid(idx)) { - pr_err("CPU%u checking wrong counter %d overflow status\n", - smp_processor_id(), idx); - } else { - counter = ARMV8_IDX_TO_COUNTER(idx); - ret = pmnc & BIT(counter); - } - - return ret; -} - -static inline int armv8pmu_select_counter(int idx) -{ - u32 counter; - - if (!armv8pmu_counter_valid(idx)) { - pr_err("CPU%u selecting wrong PMNC counter %d\n", - smp_processor_id(), idx); - return -EINVAL; - } - - counter = ARMV8_IDX_TO_COUNTER(idx); - asm volatile("msr pmselr_el0, %0" :: "r" (counter)); - isb(); - - return idx; -} - -static inline u32 armv8pmu_read_counter(int idx) -{ - u32 value = 0; - - if (!armv8pmu_counter_valid(idx)) - pr_err("CPU%u reading wrong counter %d\n", - smp_processor_id(), idx); - else if (idx == ARMV8_IDX_CYCLE_COUNTER) - asm volatile("mrs %0, pmccntr_el0" : "=r" (value)); - else if (armv8pmu_select_counter(idx) == idx) - asm volatile("mrs %0, pmxevcntr_el0" : "=r" (value)); - - return value; -} - -static inline void armv8pmu_write_counter(int idx, u32 value) -{ - if (!armv8pmu_counter_valid(idx)) - pr_err("CPU%u writing wrong counter %d\n", - smp_processor_id(), idx); - else if (idx == ARMV8_IDX_CYCLE_COUNTER) - asm volatile("msr pmccntr_el0, %0" :: "r" (value)); - else if (armv8pmu_select_counter(idx) == idx) - asm volatile("msr pmxevcntr_el0, %0" :: "r" (value)); -} - -static inline void armv8pmu_write_evtype(int idx, u32 val) -{ - if (armv8pmu_select_counter(idx) == idx) { - val &= ARMV8_EVTYPE_MASK; - asm volatile("msr pmxevtyper_el0, %0" :: "r" (val)); - } -} - -static inline int armv8pmu_enable_counter(int idx) -{ - u32 counter; - - if (!armv8pmu_counter_valid(idx)) { - pr_err("CPU%u enabling wrong PMNC counter %d\n", - smp_processor_id(), idx); - return -EINVAL; - } - - counter = ARMV8_IDX_TO_COUNTER(idx); - asm volatile("msr pmcntenset_el0, %0" :: "r" (BIT(counter))); - return idx; -} - -static inline int armv8pmu_disable_counter(int idx) -{ - u32 counter; - - if (!armv8pmu_counter_valid(idx)) { - pr_err("CPU%u disabling wrong PMNC counter %d\n", - smp_processor_id(), idx); - return -EINVAL; - } - - counter = ARMV8_IDX_TO_COUNTER(idx); - asm volatile("msr pmcntenclr_el0, %0" :: "r" (BIT(counter))); - return idx; -} - -static inline int armv8pmu_enable_intens(int idx) -{ - u32 counter; - - if (!armv8pmu_counter_valid(idx)) { - pr_err("CPU%u enabling wrong PMNC counter IRQ enable %d\n", - smp_processor_id(), idx); - return -EINVAL; - } - - counter = ARMV8_IDX_TO_COUNTER(idx); - asm volatile("msr pmintenset_el1, %0" :: "r" (BIT(counter))); - return idx; -} - -static inline int armv8pmu_disable_intens(int idx) -{ - u32 counter; - - if (!armv8pmu_counter_valid(idx)) { - pr_err("CPU%u disabling wrong PMNC counter IRQ enable %d\n", - smp_processor_id(), idx); - return -EINVAL; - } - - counter = ARMV8_IDX_TO_COUNTER(idx); - asm volatile("msr pmintenclr_el1, %0" :: "r" (BIT(counter))); - isb(); - /* Clear the overflow flag in case an interrupt is pending. */ - asm volatile("msr pmovsclr_el0, %0" :: "r" (BIT(counter))); - isb(); - return idx; -} - -static inline u32 armv8pmu_getreset_flags(void) -{ - u32 value; - - /* Read */ - asm volatile("mrs %0, pmovsclr_el0" : "=r" (value)); - - /* Write to clear flags */ - value &= ARMV8_OVSR_MASK; - asm volatile("msr pmovsclr_el0, %0" :: "r" (value)); - - return value; -} - -static void armv8pmu_enable_event(struct hw_perf_event *hwc, int idx) -{ - unsigned long flags; - struct pmu_hw_events *events = cpu_pmu->get_hw_events(); - - /* - * Enable counter and interrupt, and set the counter to count - * the event that we're interested in. - */ - raw_spin_lock_irqsave(&events->pmu_lock, flags); - - /* - * Disable counter - */ - armv8pmu_disable_counter(idx); - - /* - * Set event (if destined for PMNx counters). - */ - armv8pmu_write_evtype(idx, hwc->config_base); - - /* - * Enable interrupt for this counter - */ - armv8pmu_enable_intens(idx); - - /* - * Enable counter - */ - armv8pmu_enable_counter(idx); - - raw_spin_unlock_irqrestore(&events->pmu_lock, flags); -} - -static void armv8pmu_disable_event(struct hw_perf_event *hwc, int idx) -{ - unsigned long flags; - struct pmu_hw_events *events = cpu_pmu->get_hw_events(); - - /* - * Disable counter and interrupt - */ - raw_spin_lock_irqsave(&events->pmu_lock, flags); - - /* - * Disable counter - */ - armv8pmu_disable_counter(idx); - - /* - * Disable interrupt for this counter - */ - armv8pmu_disable_intens(idx); - - raw_spin_unlock_irqrestore(&events->pmu_lock, flags); -} - -static irqreturn_t armv8pmu_handle_irq(int irq_num, void *dev) -{ - u32 pmovsr; - struct perf_sample_data data; - struct pmu_hw_events *cpuc; - struct pt_regs *regs; - int idx; - - /* - * Get and reset the IRQ flags - */ - pmovsr = armv8pmu_getreset_flags(); - - /* - * Did an overflow occur? - */ - if (!armv8pmu_has_overflowed(pmovsr)) - return IRQ_NONE; - - /* - * Handle the counter(s) overflow(s) - */ - regs = get_irq_regs(); - - cpuc = &__get_cpu_var(cpu_hw_events); - for (idx = 0; idx < cpu_pmu->num_events; ++idx) { - struct perf_event *event = cpuc->events[idx]; - struct hw_perf_event *hwc; - - /* Ignore if we don't have an event. */ - if (!event) - continue; - - /* - * We have a single interrupt for all counters. Check that - * each counter has overflowed before we process it. - */ - if (!armv8pmu_counter_has_overflowed(pmovsr, idx)) - continue; - - hwc = &event->hw; - armpmu_event_update(event, hwc, idx); - perf_sample_data_init(&data, 0, hwc->last_period); - if (!armpmu_event_set_period(event, hwc, idx)) - continue; - - if (perf_event_overflow(event, &data, regs)) - cpu_pmu->disable(hwc, idx); - } - - /* - * Handle the pending perf events. - * - * Note: this call *must* be run with interrupts disabled. For - * platforms that can have the PMU interrupts raised as an NMI, this - * will not work. - */ - irq_work_run(); - - return IRQ_HANDLED; -} - -static void armv8pmu_start(void) -{ - unsigned long flags; - struct pmu_hw_events *events = cpu_pmu->get_hw_events(); - - raw_spin_lock_irqsave(&events->pmu_lock, flags); - /* Enable all counters */ - armv8pmu_pmcr_write(armv8pmu_pmcr_read() | ARMV8_PMCR_E); - raw_spin_unlock_irqrestore(&events->pmu_lock, flags); -} - -static void armv8pmu_stop(void) -{ - unsigned long flags; - struct pmu_hw_events *events = cpu_pmu->get_hw_events(); - - raw_spin_lock_irqsave(&events->pmu_lock, flags); - /* Disable all counters */ - armv8pmu_pmcr_write(armv8pmu_pmcr_read() & ~ARMV8_PMCR_E); - raw_spin_unlock_irqrestore(&events->pmu_lock, flags); -} - -static int armv8pmu_get_event_idx(struct pmu_hw_events *cpuc, - struct hw_perf_event *event) -{ - int idx; - unsigned long evtype = event->config_base & ARMV8_EVTYPE_EVENT; - - /* Always place a cycle counter into the cycle counter. */ - if (evtype == ARMV8_PMUV3_PERFCTR_CPU_CYCLES) { - if (test_and_set_bit(ARMV8_IDX_CYCLE_COUNTER, cpuc->used_mask)) - return -EAGAIN; - - return ARMV8_IDX_CYCLE_COUNTER; - } - - /* - * For anything other than a cycle counter, try and use - * the events counters - */ - for (idx = ARMV8_IDX_COUNTER0; idx < cpu_pmu->num_events; ++idx) { - if (!test_and_set_bit(idx, cpuc->used_mask)) - return idx; - } - - /* The counters are all in use. */ - return -EAGAIN; -} - -/* - * Add an event filter to a given event. This will only work for PMUv2 PMUs. - */ -static int armv8pmu_set_event_filter(struct hw_perf_event *event, - struct perf_event_attr *attr) -{ - unsigned long config_base = 0; - - if (attr->exclude_idle) - return -EPERM; - if (attr->exclude_user) - config_base |= ARMV8_EXCLUDE_EL0; - if (attr->exclude_kernel) - config_base |= ARMV8_EXCLUDE_EL1; - if (!attr->exclude_hv) - config_base |= ARMV8_INCLUDE_EL2; - - /* - * Install the filter into config_base as this is used to - * construct the event type. - */ - event->config_base = config_base; - - return 0; -} - -static void armv8pmu_reset(void *info) -{ - u32 idx, nb_cnt = cpu_pmu->num_events; - - /* The counter and interrupt enable registers are unknown at reset. */ - for (idx = ARMV8_IDX_CYCLE_COUNTER; idx < nb_cnt; ++idx) - armv8pmu_disable_event(NULL, idx); - - /* Initialize & Reset PMNC: C and P bits. */ - armv8pmu_pmcr_write(ARMV8_PMCR_P | ARMV8_PMCR_C); - - /* Disable access from userspace. */ - asm volatile("msr pmuserenr_el0, %0" :: "r" (0)); -} - -static int armv8_pmuv3_map_event(struct perf_event *event) -{ - return map_cpu_event(event, &armv8_pmuv3_perf_map, - &armv8_pmuv3_perf_cache_map, 0xFF); -} - -static struct arm_pmu armv8pmu = { - .handle_irq = armv8pmu_handle_irq, - .enable = armv8pmu_enable_event, - .disable = armv8pmu_disable_event, - .read_counter = armv8pmu_read_counter, - .write_counter = armv8pmu_write_counter, - .get_event_idx = armv8pmu_get_event_idx, - .start = armv8pmu_start, - .stop = armv8pmu_stop, - .reset = armv8pmu_reset, - .max_period = (1LLU << 32) - 1, -}; - -static u32 __init armv8pmu_read_num_pmnc_events(void) -{ - u32 nb_cnt; - - /* Read the nb of CNTx counters supported from PMNC */ - nb_cnt = (armv8pmu_pmcr_read() >> ARMV8_PMCR_N_SHIFT) & ARMV8_PMCR_N_MASK; - - /* Add the CPU cycles counter and return */ - return nb_cnt + 1; -} - -static struct arm_pmu *__init armv8_pmuv3_pmu_init(void) -{ - armv8pmu.name = "arm/armv8-pmuv3"; - armv8pmu.map_event = armv8_pmuv3_map_event; - armv8pmu.num_events = armv8pmu_read_num_pmnc_events(); - armv8pmu.set_event_filter = armv8pmu_set_event_filter; - return &armv8pmu; -} - -/* - * Ensure the PMU has sane values out of reset. - * This requires SMP to be available, so exists as a separate initcall. - */ -static int __init -cpu_pmu_reset(void) -{ - if (cpu_pmu && cpu_pmu->reset) - return on_each_cpu(cpu_pmu->reset, NULL, 1); - return 0; -} -arch_initcall(cpu_pmu_reset); - -/* - * PMU platform driver and devicetree bindings. - */ -static struct of_device_id armpmu_of_device_ids[] = { - {.compatible = "arm,armv8-pmuv3"}, - {}, -}; - -static int __devinit armpmu_device_probe(struct platform_device *pdev) -{ - if (!cpu_pmu) - return -ENODEV; - - cpu_pmu->plat_device = pdev; - return 0; -} - -static struct platform_driver armpmu_driver = { - .driver = { - .name = "arm-pmu", - .of_match_table = armpmu_of_device_ids, - }, - .probe = armpmu_device_probe, -}; - -static int __init register_pmu_driver(void) -{ - return platform_driver_register(&armpmu_driver); -} -device_initcall(register_pmu_driver); - -static struct pmu_hw_events *armpmu_get_cpu_events(void) -{ - return &__get_cpu_var(cpu_hw_events); -} - -static void __init cpu_pmu_init(struct arm_pmu *armpmu) -{ - int cpu; - for_each_possible_cpu(cpu) { - struct pmu_hw_events *events = &per_cpu(cpu_hw_events, cpu); - events->events = per_cpu(hw_events, cpu); - events->used_mask = per_cpu(used_mask, cpu); - raw_spin_lock_init(&events->pmu_lock); - } - armpmu->get_hw_events = armpmu_get_cpu_events; -} - -static int __init init_hw_perf_events(void) -{ - u64 dfr = read_cpuid(ID_AA64DFR0_EL1); - - switch ((dfr >> 8) & 0xf) { - case 0x1: /* PMUv3 */ - cpu_pmu = armv8_pmuv3_pmu_init(); - break; - } - - if (cpu_pmu) { - pr_info("enabled with %s PMU driver, %d counters available\n", - cpu_pmu->name, cpu_pmu->num_events); - cpu_pmu_init(cpu_pmu); - armpmu_register(cpu_pmu, "cpu", PERF_TYPE_RAW); - } else { - pr_info("no hardware support available\n"); - } - - return 0; -} -early_initcall(init_hw_perf_events); - -/* - * Callchain handling code. - */ -struct frame_tail { - struct frame_tail __user *fp; - unsigned long lr; -} __attribute__((packed)); - -/* - * Get the return address for a single stackframe and return a pointer to the - * next frame tail. - */ -static struct frame_tail __user * -user_backtrace(struct frame_tail __user *tail, - struct perf_callchain_entry *entry) -{ - struct frame_tail buftail; - unsigned long err; - - /* Also check accessibility of one struct frame_tail beyond */ - if (!access_ok(VERIFY_READ, tail, sizeof(buftail))) - return NULL; - - pagefault_disable(); - err = __copy_from_user_inatomic(&buftail, tail, sizeof(buftail)); - pagefault_enable(); - - if (err) - return NULL; - - perf_callchain_store(entry, buftail.lr); - - /* - * Frame pointers should strictly progress back up the stack - * (towards higher addresses). - */ - if (tail >= buftail.fp) - return NULL; - - return buftail.fp; -} - -void perf_callchain_user(struct perf_callchain_entry *entry, - struct pt_regs *regs) -{ - struct frame_tail __user *tail; - - tail = (struct frame_tail __user *)regs->regs[29]; - - while (entry->nr < PERF_MAX_STACK_DEPTH && - tail && !((unsigned long)tail & 0xf)) - tail = user_backtrace(tail, entry); -} - -/* - * Gets called by walk_stackframe() for every stackframe. This will be called - * whist unwinding the stackframe and is like a subroutine return so we use - * the PC. - */ -static int callchain_trace(struct stackframe *frame, void *data) -{ - struct perf_callchain_entry *entry = data; - perf_callchain_store(entry, frame->pc); - return 0; -} - -void perf_callchain_kernel(struct perf_callchain_entry *entry, - struct pt_regs *regs) -{ - struct stackframe frame; - - frame.fp = regs->regs[29]; - frame.sp = regs->sp; - frame.pc = regs->pc; - walk_stackframe(&frame, callchain_trace, entry); -} diff --git a/trunk/arch/arm64/kernel/process.c b/trunk/arch/arm64/kernel/process.c deleted file mode 100644 index f22965ea1cfc..000000000000 --- a/trunk/arch/arm64/kernel/process.c +++ /dev/null @@ -1,408 +0,0 @@ -/* - * Based on arch/arm/kernel/process.c - * - * Original Copyright (C) 1995 Linus Torvalds - * Copyright (C) 1996-2000 Russell King - Converted to ARM. - * Copyright (C) 2012 ARM 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -static void setup_restart(void) -{ - /* - * Tell the mm system that we are going to reboot - - * we may need it to insert some 1:1 mappings so that - * soft boot works. - */ - setup_mm_for_reboot(); - - /* Clean and invalidate caches */ - flush_cache_all(); - - /* Turn D-cache off */ - cpu_cache_off(); - - /* Push out any further dirty data, and ensure cache is empty */ - flush_cache_all(); -} - -void soft_restart(unsigned long addr) -{ - setup_restart(); - cpu_reset(addr); -} - -/* - * Function pointers to optional machine specific functions - */ -void (*pm_power_off)(void); -EXPORT_SYMBOL_GPL(pm_power_off); - -void (*pm_restart)(const char *cmd); -EXPORT_SYMBOL_GPL(pm_restart); - - -/* - * This is our default idle handler. - */ -static void default_idle(void) -{ - /* - * This should do all the clock switching and wait for interrupt - * tricks - */ - cpu_do_idle(); - local_irq_enable(); -} - -void (*pm_idle)(void) = default_idle; -EXPORT_SYMBOL_GPL(pm_idle); - -/* - * The idle thread, has rather strange semantics for calling pm_idle, - * but this is what x86 does and we need to do the same, so that - * things like cpuidle get called in the same way. The only difference - * is that we always respect 'hlt_counter' to prevent low power idle. - */ -void cpu_idle(void) -{ - local_fiq_enable(); - - /* endless idle loop with no priority at all */ - while (1) { - tick_nohz_idle_enter(); - rcu_idle_enter(); - while (!need_resched()) { - /* - * We need to disable interrupts here to ensure - * we don't miss a wakeup call. - */ - local_irq_disable(); - if (!need_resched()) { - stop_critical_timings(); - pm_idle(); - start_critical_timings(); - /* - * pm_idle functions should always return - * with IRQs enabled. - */ - WARN_ON(irqs_disabled()); - } else { - local_irq_enable(); - } - } - rcu_idle_exit(); - tick_nohz_idle_exit(); - schedule_preempt_disabled(); - } -} - -void machine_shutdown(void) -{ -#ifdef CONFIG_SMP - smp_send_stop(); -#endif -} - -void machine_halt(void) -{ - machine_shutdown(); - while (1); -} - -void machine_power_off(void) -{ - machine_shutdown(); - if (pm_power_off) - pm_power_off(); -} - -void machine_restart(char *cmd) -{ - machine_shutdown(); - - /* Disable interrupts first */ - local_irq_disable(); - local_fiq_disable(); - - /* Now call the architecture specific reboot code. */ - if (pm_restart) - pm_restart(cmd); - - /* - * Whoops - the architecture was unable to reboot. - */ - printk("Reboot failed -- System halted\n"); - while (1); -} - -void __show_regs(struct pt_regs *regs) -{ - int i; - - printk("CPU: %d %s (%s %.*s)\n", - raw_smp_processor_id(), print_tainted(), - init_utsname()->release, - (int)strcspn(init_utsname()->version, " "), - init_utsname()->version); - print_symbol("PC is at %s\n", instruction_pointer(regs)); - print_symbol("LR is at %s\n", regs->regs[30]); - printk("pc : [<%016llx>] lr : [<%016llx>] pstate: %08llx\n", - regs->pc, regs->regs[30], regs->pstate); - printk("sp : %016llx\n", regs->sp); - for (i = 29; i >= 0; i--) { - printk("x%-2d: %016llx ", i, regs->regs[i]); - if (i % 2 == 0) - printk("\n"); - } - printk("\n"); -} - -void show_regs(struct pt_regs * regs) -{ - printk("\n"); - printk("Pid: %d, comm: %20s\n", task_pid_nr(current), current->comm); - __show_regs(regs); -} - -/* - * Free current thread data structures etc.. - */ -void exit_thread(void) -{ -} - -void flush_thread(void) -{ - fpsimd_flush_thread(); - flush_ptrace_hw_breakpoint(current); -} - -void release_thread(struct task_struct *dead_task) -{ -} - -int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src) -{ - fpsimd_save_state(¤t->thread.fpsimd_state); - *dst = *src; - return 0; -} - -asmlinkage void ret_from_fork(void) asm("ret_from_fork"); - -int copy_thread(unsigned long clone_flags, unsigned long stack_start, - unsigned long stk_sz, struct task_struct *p, - struct pt_regs *regs) -{ - struct pt_regs *childregs = task_pt_regs(p); - unsigned long tls = p->thread.tp_value; - - *childregs = *regs; - childregs->regs[0] = 0; - - if (is_compat_thread(task_thread_info(p))) - childregs->compat_sp = stack_start; - else { - /* - * Read the current TLS pointer from tpidr_el0 as it may be - * out-of-sync with the saved value. - */ - asm("mrs %0, tpidr_el0" : "=r" (tls)); - childregs->sp = stack_start; - } - - memset(&p->thread.cpu_context, 0, sizeof(struct cpu_context)); - p->thread.cpu_context.sp = (unsigned long)childregs; - p->thread.cpu_context.pc = (unsigned long)ret_from_fork; - - /* If a TLS pointer was passed to clone, use that for the new thread. */ - if (clone_flags & CLONE_SETTLS) - tls = regs->regs[3]; - p->thread.tp_value = tls; - - ptrace_hw_copy_thread(p); - - return 0; -} - -static void tls_thread_switch(struct task_struct *next) -{ - unsigned long tpidr, tpidrro; - - if (!is_compat_task()) { - asm("mrs %0, tpidr_el0" : "=r" (tpidr)); - current->thread.tp_value = tpidr; - } - - if (is_compat_thread(task_thread_info(next))) { - tpidr = 0; - tpidrro = next->thread.tp_value; - } else { - tpidr = next->thread.tp_value; - tpidrro = 0; - } - - asm( - " msr tpidr_el0, %0\n" - " msr tpidrro_el0, %1" - : : "r" (tpidr), "r" (tpidrro)); -} - -/* - * Thread switching. - */ -struct task_struct *__switch_to(struct task_struct *prev, - struct task_struct *next) -{ - struct task_struct *last; - - fpsimd_thread_switch(next); - tls_thread_switch(next); - hw_breakpoint_thread_switch(next); - - /* the actual thread switch */ - last = cpu_switch_to(prev, next); - - return last; -} - -/* - * Fill in the task's elfregs structure for a core dump. - */ -int dump_task_regs(struct task_struct *t, elf_gregset_t *elfregs) -{ - elf_core_copy_regs(elfregs, task_pt_regs(t)); - return 1; -} - -/* - * fill in the fpe structure for a core dump... - */ -int dump_fpu (struct pt_regs *regs, struct user_fp *fp) -{ - return 0; -} -EXPORT_SYMBOL(dump_fpu); - -/* - * Shuffle the argument into the correct register before calling the - * thread function. x1 is the thread argument, x2 is the pointer to - * the thread function, and x3 points to the exit function. - */ -extern void kernel_thread_helper(void); -asm( ".section .text\n" -" .align\n" -" .type kernel_thread_helper, #function\n" -"kernel_thread_helper:\n" -" mov x0, x1\n" -" mov x30, x3\n" -" br x2\n" -" .size kernel_thread_helper, . - kernel_thread_helper\n" -" .previous"); - -#define kernel_thread_exit do_exit - -/* - * Create a kernel thread. - */ -pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags) -{ - struct pt_regs regs; - - memset(®s, 0, sizeof(regs)); - - regs.regs[1] = (unsigned long)arg; - regs.regs[2] = (unsigned long)fn; - regs.regs[3] = (unsigned long)kernel_thread_exit; - regs.pc = (unsigned long)kernel_thread_helper; - regs.pstate = PSR_MODE_EL1h; - - return do_fork(flags|CLONE_VM|CLONE_UNTRACED, 0, ®s, 0, NULL, NULL); -} -EXPORT_SYMBOL(kernel_thread); - -unsigned long get_wchan(struct task_struct *p) -{ - struct stackframe frame; - int count = 0; - if (!p || p == current || p->state == TASK_RUNNING) - return 0; - - frame.fp = thread_saved_fp(p); - frame.sp = thread_saved_sp(p); - frame.pc = thread_saved_pc(p); - do { - int ret = unwind_frame(&frame); - if (ret < 0) - return 0; - if (!in_sched_functions(frame.pc)) - return frame.pc; - } while (count ++ < 16); - return 0; -} - -unsigned long arch_align_stack(unsigned long sp) -{ - if (!(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space) - sp -= get_random_int() & ~PAGE_MASK; - return sp & ~0xf; -} - -static unsigned long randomize_base(unsigned long base) -{ - unsigned long range_end = base + (STACK_RND_MASK << PAGE_SHIFT) + 1; - return randomize_range(base, range_end, 0) ? : base; -} - -unsigned long arch_randomize_brk(struct mm_struct *mm) -{ - return randomize_base(mm->brk); -} - -unsigned long randomize_et_dyn(unsigned long base) -{ - return randomize_base(base); -} diff --git a/trunk/arch/arm64/kernel/ptrace.c b/trunk/arch/arm64/kernel/ptrace.c deleted file mode 100644 index ac3550ecc7b5..000000000000 --- a/trunk/arch/arm64/kernel/ptrace.c +++ /dev/null @@ -1,1126 +0,0 @@ -/* - * Based on arch/arm/kernel/ptrace.c - * - * By Ross Biro 1/23/92 - * edited by Linus Torvalds - * ARM modifications Copyright (C) 2000 Russell King - * Copyright (C) 2012 ARM 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -/* - * TODO: does not yet catch signals sent when the child dies. - * in exit.c or in signal.c. - */ - -/* - * Called by kernel/ptrace.c when detaching.. - */ -void ptrace_disable(struct task_struct *child) -{ -} - -/* - * Handle hitting a breakpoint. - */ -static int ptrace_break(struct pt_regs *regs) -{ - siginfo_t info = { - .si_signo = SIGTRAP, - .si_errno = 0, - .si_code = TRAP_BRKPT, - .si_addr = (void __user *)instruction_pointer(regs), - }; - - force_sig_info(SIGTRAP, &info, current); - return 0; -} - -static int arm64_break_trap(unsigned long addr, unsigned int esr, - struct pt_regs *regs) -{ - return ptrace_break(regs); -} - -#ifdef CONFIG_HAVE_HW_BREAKPOINT -/* - * Handle hitting a HW-breakpoint. - */ -static void ptrace_hbptriggered(struct perf_event *bp, - struct perf_sample_data *data, - struct pt_regs *regs) -{ - struct arch_hw_breakpoint *bkpt = counter_arch_bp(bp); - siginfo_t info = { - .si_signo = SIGTRAP, - .si_errno = 0, - .si_code = TRAP_HWBKPT, - .si_addr = (void __user *)(bkpt->trigger), - }; - -#ifdef CONFIG_COMPAT - int i; - - if (!is_compat_task()) - goto send_sig; - - for (i = 0; i < ARM_MAX_BRP; ++i) { - if (current->thread.debug.hbp_break[i] == bp) { - info.si_errno = (i << 1) + 1; - break; - } - } - for (i = ARM_MAX_BRP; i < ARM_MAX_HBP_SLOTS && !bp; ++i) { - if (current->thread.debug.hbp_watch[i] == bp) { - info.si_errno = -((i << 1) + 1); - break; - } - } - -send_sig: -#endif - force_sig_info(SIGTRAP, &info, current); -} - -/* - * Unregister breakpoints from this task and reset the pointers in - * the thread_struct. - */ -void flush_ptrace_hw_breakpoint(struct task_struct *tsk) -{ - int i; - struct thread_struct *t = &tsk->thread; - - for (i = 0; i < ARM_MAX_BRP; i++) { - if (t->debug.hbp_break[i]) { - unregister_hw_breakpoint(t->debug.hbp_break[i]); - t->debug.hbp_break[i] = NULL; - } - } - - for (i = 0; i < ARM_MAX_WRP; i++) { - if (t->debug.hbp_watch[i]) { - unregister_hw_breakpoint(t->debug.hbp_watch[i]); - t->debug.hbp_watch[i] = NULL; - } - } -} - -void ptrace_hw_copy_thread(struct task_struct *tsk) -{ - memset(&tsk->thread.debug, 0, sizeof(struct debug_info)); -} - -static struct perf_event *ptrace_hbp_get_event(unsigned int note_type, - struct task_struct *tsk, - unsigned long idx) -{ - struct perf_event *bp = ERR_PTR(-EINVAL); - - switch (note_type) { - case NT_ARM_HW_BREAK: - if (idx < ARM_MAX_BRP) - bp = tsk->thread.debug.hbp_break[idx]; - break; - case NT_ARM_HW_WATCH: - if (idx < ARM_MAX_WRP) - bp = tsk->thread.debug.hbp_watch[idx]; - break; - } - - return bp; -} - -static int ptrace_hbp_set_event(unsigned int note_type, - struct task_struct *tsk, - unsigned long idx, - struct perf_event *bp) -{ - int err = -EINVAL; - - switch (note_type) { - case NT_ARM_HW_BREAK: - if (idx < ARM_MAX_BRP) { - tsk->thread.debug.hbp_break[idx] = bp; - err = 0; - } - break; - case NT_ARM_HW_WATCH: - if (idx < ARM_MAX_WRP) { - tsk->thread.debug.hbp_watch[idx] = bp; - err = 0; - } - break; - } - - return err; -} - -static struct perf_event *ptrace_hbp_create(unsigned int note_type, - struct task_struct *tsk, - unsigned long idx) -{ - struct perf_event *bp; - struct perf_event_attr attr; - int err, type; - - switch (note_type) { - case NT_ARM_HW_BREAK: - type = HW_BREAKPOINT_X; - break; - case NT_ARM_HW_WATCH: - type = HW_BREAKPOINT_RW; - break; - default: - return ERR_PTR(-EINVAL); - } - - ptrace_breakpoint_init(&attr); - - /* - * Initialise fields to sane defaults - * (i.e. values that will pass validation). - */ - attr.bp_addr = 0; - attr.bp_len = HW_BREAKPOINT_LEN_4; - attr.bp_type = type; - attr.disabled = 1; - - bp = register_user_hw_breakpoint(&attr, ptrace_hbptriggered, NULL, tsk); - if (IS_ERR(bp)) - return bp; - - err = ptrace_hbp_set_event(note_type, tsk, idx, bp); - if (err) - return ERR_PTR(err); - - return bp; -} - -static int ptrace_hbp_fill_attr_ctrl(unsigned int note_type, - struct arch_hw_breakpoint_ctrl ctrl, - struct perf_event_attr *attr) -{ - int err, len, type; - - err = arch_bp_generic_fields(ctrl, &len, &type); - if (err) - return err; - - switch (note_type) { - case NT_ARM_HW_BREAK: - if ((type & HW_BREAKPOINT_X) != type) - return -EINVAL; - break; - case NT_ARM_HW_WATCH: - if ((type & HW_BREAKPOINT_RW) != type) - return -EINVAL; - break; - default: - return -EINVAL; - } - - attr->bp_len = len; - attr->bp_type = type; - attr->disabled = !ctrl.enabled; - - return 0; -} - -static int ptrace_hbp_get_resource_info(unsigned int note_type, u32 *info) -{ - u8 num; - u32 reg = 0; - - switch (note_type) { - case NT_ARM_HW_BREAK: - num = hw_breakpoint_slots(TYPE_INST); - break; - case NT_ARM_HW_WATCH: - num = hw_breakpoint_slots(TYPE_DATA); - break; - default: - return -EINVAL; - } - - reg |= debug_monitors_arch(); - reg <<= 8; - reg |= num; - - *info = reg; - return 0; -} - -static int ptrace_hbp_get_ctrl(unsigned int note_type, - struct task_struct *tsk, - unsigned long idx, - u32 *ctrl) -{ - struct perf_event *bp = ptrace_hbp_get_event(note_type, tsk, idx); - - if (IS_ERR(bp)) - return PTR_ERR(bp); - - *ctrl = bp ? encode_ctrl_reg(counter_arch_bp(bp)->ctrl) : 0; - return 0; -} - -static int ptrace_hbp_get_addr(unsigned int note_type, - struct task_struct *tsk, - unsigned long idx, - u64 *addr) -{ - struct perf_event *bp = ptrace_hbp_get_event(note_type, tsk, idx); - - if (IS_ERR(bp)) - return PTR_ERR(bp); - - *addr = bp ? bp->attr.bp_addr : 0; - return 0; -} - -static struct perf_event *ptrace_hbp_get_initialised_bp(unsigned int note_type, - struct task_struct *tsk, - unsigned long idx) -{ - struct perf_event *bp = ptrace_hbp_get_event(note_type, tsk, idx); - - if (!bp) - bp = ptrace_hbp_create(note_type, tsk, idx); - - return bp; -} - -static int ptrace_hbp_set_ctrl(unsigned int note_type, - struct task_struct *tsk, - unsigned long idx, - u32 uctrl) -{ - int err; - struct perf_event *bp; - struct perf_event_attr attr; - struct arch_hw_breakpoint_ctrl ctrl; - - bp = ptrace_hbp_get_initialised_bp(note_type, tsk, idx); - if (IS_ERR(bp)) { - err = PTR_ERR(bp); - return err; - } - - attr = bp->attr; - decode_ctrl_reg(uctrl, &ctrl); - err = ptrace_hbp_fill_attr_ctrl(note_type, ctrl, &attr); - if (err) - return err; - - return modify_user_hw_breakpoint(bp, &attr); -} - -static int ptrace_hbp_set_addr(unsigned int note_type, - struct task_struct *tsk, - unsigned long idx, - u64 addr) -{ - int err; - struct perf_event *bp; - struct perf_event_attr attr; - - bp = ptrace_hbp_get_initialised_bp(note_type, tsk, idx); - if (IS_ERR(bp)) { - err = PTR_ERR(bp); - return err; - } - - attr = bp->attr; - attr.bp_addr = addr; - err = modify_user_hw_breakpoint(bp, &attr); - return err; -} - -#define PTRACE_HBP_ADDR_SZ sizeof(u64) -#define PTRACE_HBP_CTRL_SZ sizeof(u32) -#define PTRACE_HBP_REG_OFF sizeof(u32) - -static int hw_break_get(struct task_struct *target, - const struct user_regset *regset, - unsigned int pos, unsigned int count, - void *kbuf, void __user *ubuf) -{ - unsigned int note_type = regset->core_note_type; - int ret, idx = 0, offset = PTRACE_HBP_REG_OFF, limit; - u32 info, ctrl; - u64 addr; - - /* Resource info */ - ret = ptrace_hbp_get_resource_info(note_type, &info); - if (ret) - return ret; - - ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, &info, 0, 4); - if (ret) - return ret; - - /* (address, ctrl) registers */ - limit = regset->n * regset->size; - while (count && offset < limit) { - ret = ptrace_hbp_get_addr(note_type, target, idx, &addr); - if (ret) - return ret; - ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, &addr, - offset, offset + PTRACE_HBP_ADDR_SZ); - if (ret) - return ret; - offset += PTRACE_HBP_ADDR_SZ; - - ret = ptrace_hbp_get_ctrl(note_type, target, idx, &ctrl); - if (ret) - return ret; - ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, &ctrl, - offset, offset + PTRACE_HBP_CTRL_SZ); - if (ret) - return ret; - offset += PTRACE_HBP_CTRL_SZ; - idx++; - } - - return 0; -} - -static int hw_break_set(struct task_struct *target, - const struct user_regset *regset, - unsigned int pos, unsigned int count, - const void *kbuf, const void __user *ubuf) -{ - unsigned int note_type = regset->core_note_type; - int ret, idx = 0, offset = PTRACE_HBP_REG_OFF, limit; - u32 ctrl; - u64 addr; - - /* Resource info */ - ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf, 0, 4); - if (ret) - return ret; - - /* (address, ctrl) registers */ - limit = regset->n * regset->size; - while (count && offset < limit) { - ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &addr, - offset, offset + PTRACE_HBP_ADDR_SZ); - if (ret) - return ret; - ret = ptrace_hbp_set_addr(note_type, target, idx, addr); - if (ret) - return ret; - offset += PTRACE_HBP_ADDR_SZ; - - ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &ctrl, - offset, offset + PTRACE_HBP_CTRL_SZ); - if (ret) - return ret; - ret = ptrace_hbp_set_ctrl(note_type, target, idx, ctrl); - if (ret) - return ret; - offset += PTRACE_HBP_CTRL_SZ; - idx++; - } - - return 0; -} -#endif /* CONFIG_HAVE_HW_BREAKPOINT */ - -static int gpr_get(struct task_struct *target, - const struct user_regset *regset, - unsigned int pos, unsigned int count, - void *kbuf, void __user *ubuf) -{ - struct user_pt_regs *uregs = &task_pt_regs(target)->user_regs; - return user_regset_copyout(&pos, &count, &kbuf, &ubuf, uregs, 0, -1); -} - -static int gpr_set(struct task_struct *target, const struct user_regset *regset, - unsigned int pos, unsigned int count, - const void *kbuf, const void __user *ubuf) -{ - int ret; - struct user_pt_regs newregs; - - ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &newregs, 0, -1); - if (ret) - return ret; - - if (!valid_user_regs(&newregs)) - return -EINVAL; - - task_pt_regs(target)->user_regs = newregs; - return 0; -} - -/* - * TODO: update fp accessors for lazy context switching (sync/flush hwstate) - */ -static int fpr_get(struct task_struct *target, const struct user_regset *regset, - unsigned int pos, unsigned int count, - void *kbuf, void __user *ubuf) -{ - struct user_fpsimd_state *uregs; - uregs = &target->thread.fpsimd_state.user_fpsimd; - return user_regset_copyout(&pos, &count, &kbuf, &ubuf, uregs, 0, -1); -} - -static int fpr_set(struct task_struct *target, const struct user_regset *regset, - unsigned int pos, unsigned int count, - const void *kbuf, const void __user *ubuf) -{ - int ret; - struct user_fpsimd_state newstate; - - ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &newstate, 0, -1); - if (ret) - return ret; - - target->thread.fpsimd_state.user_fpsimd = newstate; - return ret; -} - -static int tls_get(struct task_struct *target, const struct user_regset *regset, - unsigned int pos, unsigned int count, - void *kbuf, void __user *ubuf) -{ - unsigned long *tls = &target->thread.tp_value; - return user_regset_copyout(&pos, &count, &kbuf, &ubuf, tls, 0, -1); -} - -static int tls_set(struct task_struct *target, const struct user_regset *regset, - unsigned int pos, unsigned int count, - const void *kbuf, const void __user *ubuf) -{ - int ret; - unsigned long tls; - - ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &tls, 0, -1); - if (ret) - return ret; - - target->thread.tp_value = tls; - return ret; -} - -enum aarch64_regset { - REGSET_GPR, - REGSET_FPR, - REGSET_TLS, -#ifdef CONFIG_HAVE_HW_BREAKPOINT - REGSET_HW_BREAK, - REGSET_HW_WATCH, -#endif -}; - -static const struct user_regset aarch64_regsets[] = { - [REGSET_GPR] = { - .core_note_type = NT_PRSTATUS, - .n = sizeof(struct user_pt_regs) / sizeof(u64), - .size = sizeof(u64), - .align = sizeof(u64), - .get = gpr_get, - .set = gpr_set - }, - [REGSET_FPR] = { - .core_note_type = NT_PRFPREG, - .n = sizeof(struct user_fpsimd_state) / sizeof(u32), - /* - * We pretend we have 32-bit registers because the fpsr and - * fpcr are 32-bits wide. - */ - .size = sizeof(u32), - .align = sizeof(u32), - .get = fpr_get, - .set = fpr_set - }, - [REGSET_TLS] = { - .core_note_type = NT_ARM_TLS, - .n = 1, - .size = sizeof(void *), - .align = sizeof(void *), - .get = tls_get, - .set = tls_set, - }, -#ifdef CONFIG_HAVE_HW_BREAKPOINT - [REGSET_HW_BREAK] = { - .core_note_type = NT_ARM_HW_BREAK, - .n = sizeof(struct user_hwdebug_state) / sizeof(u32), - .size = sizeof(u32), - .align = sizeof(u32), - .get = hw_break_get, - .set = hw_break_set, - }, - [REGSET_HW_WATCH] = { - .core_note_type = NT_ARM_HW_WATCH, - .n = sizeof(struct user_hwdebug_state) / sizeof(u32), - .size = sizeof(u32), - .align = sizeof(u32), - .get = hw_break_get, - .set = hw_break_set, - }, -#endif -}; - -static const struct user_regset_view user_aarch64_view = { - .name = "aarch64", .e_machine = EM_AARCH64, - .regsets = aarch64_regsets, .n = ARRAY_SIZE(aarch64_regsets) -}; - -#ifdef CONFIG_COMPAT -#include - -enum compat_regset { - REGSET_COMPAT_GPR, - REGSET_COMPAT_VFP, -}; - -static int compat_gpr_get(struct task_struct *target, - const struct user_regset *regset, - unsigned int pos, unsigned int count, - void *kbuf, void __user *ubuf) -{ - int ret = 0; - unsigned int i, start, num_regs; - - /* Calculate the number of AArch32 registers contained in count */ - num_regs = count / regset->size; - - /* Convert pos into an register number */ - start = pos / regset->size; - - if (start + num_regs > regset->n) - return -EIO; - - for (i = 0; i < num_regs; ++i) { - unsigned int idx = start + i; - void *reg; - - switch (idx) { - case 15: - reg = (void *)&task_pt_regs(target)->pc; - break; - case 16: - reg = (void *)&task_pt_regs(target)->pstate; - break; - case 17: - reg = (void *)&task_pt_regs(target)->orig_x0; - break; - default: - reg = (void *)&task_pt_regs(target)->regs[idx]; - } - - ret = copy_to_user(ubuf, reg, sizeof(compat_ulong_t)); - - if (ret) - break; - else - ubuf += sizeof(compat_ulong_t); - } - - return ret; -} - -static int compat_gpr_set(struct task_struct *target, - const struct user_regset *regset, - unsigned int pos, unsigned int count, - const void *kbuf, const void __user *ubuf) -{ - struct pt_regs newregs; - int ret = 0; - unsigned int i, start, num_regs; - - /* Calculate the number of AArch32 registers contained in count */ - num_regs = count / regset->size; - - /* Convert pos into an register number */ - start = pos / regset->size; - - if (start + num_regs > regset->n) - return -EIO; - - newregs = *task_pt_regs(target); - - for (i = 0; i < num_regs; ++i) { - unsigned int idx = start + i; - void *reg; - - switch (idx) { - case 15: - reg = (void *)&newregs.pc; - break; - case 16: - reg = (void *)&newregs.pstate; - break; - case 17: - reg = (void *)&newregs.orig_x0; - break; - default: - reg = (void *)&newregs.regs[idx]; - } - - ret = copy_from_user(reg, ubuf, sizeof(compat_ulong_t)); - - if (ret) - goto out; - else - ubuf += sizeof(compat_ulong_t); - } - - if (valid_user_regs(&newregs.user_regs)) - *task_pt_regs(target) = newregs; - else - ret = -EINVAL; - -out: - return ret; -} - -static int compat_vfp_get(struct task_struct *target, - const struct user_regset *regset, - unsigned int pos, unsigned int count, - void *kbuf, void __user *ubuf) -{ - struct user_fpsimd_state *uregs; - compat_ulong_t fpscr; - int ret; - - uregs = &target->thread.fpsimd_state.user_fpsimd; - - /* - * The VFP registers are packed into the fpsimd_state, so they all sit - * nicely together for us. We just need to create the fpscr separately. - */ - ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, uregs, 0, - VFP_STATE_SIZE - sizeof(compat_ulong_t)); - - if (count && !ret) { - fpscr = (uregs->fpsr & VFP_FPSCR_STAT_MASK) | - (uregs->fpcr & VFP_FPSCR_CTRL_MASK); - ret = put_user(fpscr, (compat_ulong_t *)ubuf); - } - - return ret; -} - -static int compat_vfp_set(struct task_struct *target, - const struct user_regset *regset, - unsigned int pos, unsigned int count, - const void *kbuf, const void __user *ubuf) -{ - struct user_fpsimd_state *uregs; - compat_ulong_t fpscr; - int ret; - - if (pos + count > VFP_STATE_SIZE) - return -EIO; - - uregs = &target->thread.fpsimd_state.user_fpsimd; - - ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, uregs, 0, - VFP_STATE_SIZE - sizeof(compat_ulong_t)); - - if (count && !ret) { - ret = get_user(fpscr, (compat_ulong_t *)ubuf); - uregs->fpsr = fpscr & VFP_FPSCR_STAT_MASK; - uregs->fpcr = fpscr & VFP_FPSCR_CTRL_MASK; - } - - return ret; -} - -static const struct user_regset aarch32_regsets[] = { - [REGSET_COMPAT_GPR] = { - .core_note_type = NT_PRSTATUS, - .n = COMPAT_ELF_NGREG, - .size = sizeof(compat_elf_greg_t), - .align = sizeof(compat_elf_greg_t), - .get = compat_gpr_get, - .set = compat_gpr_set - }, - [REGSET_COMPAT_VFP] = { - .core_note_type = NT_ARM_VFP, - .n = VFP_STATE_SIZE / sizeof(compat_ulong_t), - .size = sizeof(compat_ulong_t), - .align = sizeof(compat_ulong_t), - .get = compat_vfp_get, - .set = compat_vfp_set - }, -}; - -static const struct user_regset_view user_aarch32_view = { - .name = "aarch32", .e_machine = EM_ARM, - .regsets = aarch32_regsets, .n = ARRAY_SIZE(aarch32_regsets) -}; - -int aarch32_break_trap(struct pt_regs *regs) -{ - unsigned int instr; - bool bp = false; - void __user *pc = (void __user *)instruction_pointer(regs); - - if (compat_thumb_mode(regs)) { - /* get 16-bit Thumb instruction */ - get_user(instr, (u16 __user *)pc); - if (instr == AARCH32_BREAK_THUMB2_LO) { - /* get second half of 32-bit Thumb-2 instruction */ - get_user(instr, (u16 __user *)(pc + 2)); - bp = instr == AARCH32_BREAK_THUMB2_HI; - } else { - bp = instr == AARCH32_BREAK_THUMB; - } - } else { - /* 32-bit ARM instruction */ - get_user(instr, (u32 __user *)pc); - bp = (instr & ~0xf0000000) == AARCH32_BREAK_ARM; - } - - if (bp) - return ptrace_break(regs); - return 1; -} - -static int compat_ptrace_read_user(struct task_struct *tsk, compat_ulong_t off, - compat_ulong_t __user *ret) -{ - compat_ulong_t tmp; - - if (off & 3) - return -EIO; - - if (off == PT_TEXT_ADDR) - tmp = tsk->mm->start_code; - else if (off == PT_DATA_ADDR) - tmp = tsk->mm->start_data; - else if (off == PT_TEXT_END_ADDR) - tmp = tsk->mm->end_code; - else if (off < sizeof(compat_elf_gregset_t)) - return copy_regset_to_user(tsk, &user_aarch32_view, - REGSET_COMPAT_GPR, off, - sizeof(compat_ulong_t), ret); - else if (off >= COMPAT_USER_SZ) - return -EIO; - else - tmp = 0; - - return put_user(tmp, ret); -} - -static int compat_ptrace_write_user(struct task_struct *tsk, compat_ulong_t off, - compat_ulong_t val) -{ - int ret; - - if (off & 3 || off >= COMPAT_USER_SZ) - return -EIO; - - if (off >= sizeof(compat_elf_gregset_t)) - return 0; - - ret = copy_regset_from_user(tsk, &user_aarch32_view, - REGSET_COMPAT_GPR, off, - sizeof(compat_ulong_t), - &val); - return ret; -} - -#ifdef CONFIG_HAVE_HW_BREAKPOINT - -/* - * Convert a virtual register number into an index for a thread_info - * breakpoint array. Breakpoints are identified using positive numbers - * whilst watchpoints are negative. The registers are laid out as pairs - * of (address, control), each pair mapping to a unique hw_breakpoint struct. - * Register 0 is reserved for describing resource information. - */ -static int compat_ptrace_hbp_num_to_idx(compat_long_t num) -{ - return (abs(num) - 1) >> 1; -} - -static int compat_ptrace_hbp_get_resource_info(u32 *kdata) -{ - u8 num_brps, num_wrps, debug_arch, wp_len; - u32 reg = 0; - - num_brps = hw_breakpoint_slots(TYPE_INST); - num_wrps = hw_breakpoint_slots(TYPE_DATA); - - debug_arch = debug_monitors_arch(); - wp_len = 8; - reg |= debug_arch; - reg <<= 8; - reg |= wp_len; - reg <<= 8; - reg |= num_wrps; - reg <<= 8; - reg |= num_brps; - - *kdata = reg; - return 0; -} - -static int compat_ptrace_hbp_get(unsigned int note_type, - struct task_struct *tsk, - compat_long_t num, - u32 *kdata) -{ - u64 addr = 0; - u32 ctrl = 0; - - int err, idx = compat_ptrace_hbp_num_to_idx(num);; - - if (num & 1) { - err = ptrace_hbp_get_addr(note_type, tsk, idx, &addr); - *kdata = (u32)addr; - } else { - err = ptrace_hbp_get_ctrl(note_type, tsk, idx, &ctrl); - *kdata = ctrl; - } - - return err; -} - -static int compat_ptrace_hbp_set(unsigned int note_type, - struct task_struct *tsk, - compat_long_t num, - u32 *kdata) -{ - u64 addr; - u32 ctrl; - - int err, idx = compat_ptrace_hbp_num_to_idx(num); - - if (num & 1) { - addr = *kdata; - err = ptrace_hbp_set_addr(note_type, tsk, idx, addr); - } else { - ctrl = *kdata; - err = ptrace_hbp_set_ctrl(note_type, tsk, idx, ctrl); - } - - return err; -} - -static int compat_ptrace_gethbpregs(struct task_struct *tsk, compat_long_t num, - compat_ulong_t __user *data) -{ - int ret; - u32 kdata; - mm_segment_t old_fs = get_fs(); - - set_fs(KERNEL_DS); - /* Watchpoint */ - if (num < 0) { - ret = compat_ptrace_hbp_get(NT_ARM_HW_WATCH, tsk, num, &kdata); - /* Resource info */ - } else if (num == 0) { - ret = compat_ptrace_hbp_get_resource_info(&kdata); - /* Breakpoint */ - } else { - ret = compat_ptrace_hbp_get(NT_ARM_HW_BREAK, tsk, num, &kdata); - } - set_fs(old_fs); - - if (!ret) - ret = put_user(kdata, data); - - return ret; -} - -static int compat_ptrace_sethbpregs(struct task_struct *tsk, compat_long_t num, - compat_ulong_t __user *data) -{ - int ret; - u32 kdata = 0; - mm_segment_t old_fs = get_fs(); - - if (num == 0) - return 0; - - ret = get_user(kdata, data); - if (ret) - return ret; - - set_fs(KERNEL_DS); - if (num < 0) - ret = compat_ptrace_hbp_set(NT_ARM_HW_WATCH, tsk, num, &kdata); - else - ret = compat_ptrace_hbp_set(NT_ARM_HW_BREAK, tsk, num, &kdata); - set_fs(old_fs); - - return ret; -} -#endif /* CONFIG_HAVE_HW_BREAKPOINT */ - -long compat_arch_ptrace(struct task_struct *child, compat_long_t request, - compat_ulong_t caddr, compat_ulong_t cdata) -{ - unsigned long addr = caddr; - unsigned long data = cdata; - void __user *datap = compat_ptr(data); - int ret; - - switch (request) { - case PTRACE_PEEKUSR: - ret = compat_ptrace_read_user(child, addr, datap); - break; - - case PTRACE_POKEUSR: - ret = compat_ptrace_write_user(child, addr, data); - break; - - case COMPAT_PTRACE_GETREGS: - ret = copy_regset_to_user(child, - &user_aarch32_view, - REGSET_COMPAT_GPR, - 0, sizeof(compat_elf_gregset_t), - datap); - break; - - case COMPAT_PTRACE_SETREGS: - ret = copy_regset_from_user(child, - &user_aarch32_view, - REGSET_COMPAT_GPR, - 0, sizeof(compat_elf_gregset_t), - datap); - break; - - case COMPAT_PTRACE_GET_THREAD_AREA: - ret = put_user((compat_ulong_t)child->thread.tp_value, - (compat_ulong_t __user *)datap); - break; - - case COMPAT_PTRACE_SET_SYSCALL: - task_pt_regs(child)->syscallno = data; - ret = 0; - break; - - case COMPAT_PTRACE_GETVFPREGS: - ret = copy_regset_to_user(child, - &user_aarch32_view, - REGSET_COMPAT_VFP, - 0, VFP_STATE_SIZE, - datap); - break; - - case COMPAT_PTRACE_SETVFPREGS: - ret = copy_regset_from_user(child, - &user_aarch32_view, - REGSET_COMPAT_VFP, - 0, VFP_STATE_SIZE, - datap); - break; - -#ifdef CONFIG_HAVE_HW_BREAKPOINT - case COMPAT_PTRACE_GETHBPREGS: - ret = compat_ptrace_gethbpregs(child, addr, datap); - break; - - case COMPAT_PTRACE_SETHBPREGS: - ret = compat_ptrace_sethbpregs(child, addr, datap); - break; -#endif - - default: - ret = compat_ptrace_request(child, request, addr, - data); - break; - } - - return ret; -} -#endif /* CONFIG_COMPAT */ - -const struct user_regset_view *task_user_regset_view(struct task_struct *task) -{ -#ifdef CONFIG_COMPAT - if (is_compat_thread(task_thread_info(task))) - return &user_aarch32_view; -#endif - return &user_aarch64_view; -} - -long arch_ptrace(struct task_struct *child, long request, - unsigned long addr, unsigned long data) -{ - return ptrace_request(child, request, addr, data); -} - - -static int __init ptrace_break_init(void) -{ - hook_debug_fault_code(DBG_ESR_EVT_BRK, arm64_break_trap, SIGTRAP, - TRAP_BRKPT, "ptrace BRK handler"); - return 0; -} -core_initcall(ptrace_break_init); - - -asmlinkage int syscall_trace(int dir, struct pt_regs *regs) -{ - unsigned long saved_reg; - - if (!test_thread_flag(TIF_SYSCALL_TRACE)) - return regs->syscallno; - - if (is_compat_task()) { - /* AArch32 uses ip (r12) for scratch */ - saved_reg = regs->regs[12]; - regs->regs[12] = dir; - } else { - /* - * Save X7. X7 is used to denote syscall entry/exit: - * X7 = 0 -> entry, = 1 -> exit - */ - saved_reg = regs->regs[7]; - regs->regs[7] = dir; - } - - if (dir) - tracehook_report_syscall_exit(regs, 0); - else if (tracehook_report_syscall_entry(regs)) - regs->syscallno = ~0UL; - - if (is_compat_task()) - regs->regs[12] = saved_reg; - else - regs->regs[7] = saved_reg; - - return regs->syscallno; -} diff --git a/trunk/arch/arm64/kernel/setup.c b/trunk/arch/arm64/kernel/setup.c deleted file mode 100644 index 48ffb9fb3fe3..000000000000 --- a/trunk/arch/arm64/kernel/setup.c +++ /dev/null @@ -1,347 +0,0 @@ -/* - * Based on arch/arm/kernel/setup.c - * - * Copyright (C) 1995-2001 Russell King - * Copyright (C) 2012 ARM 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -unsigned int processor_id; -EXPORT_SYMBOL(processor_id); - -unsigned int elf_hwcap __read_mostly; -EXPORT_SYMBOL_GPL(elf_hwcap); - -static const char *cpu_name; -static const char *machine_name; -phys_addr_t __fdt_pointer __initdata; - -/* - * Standard memory resources - */ -static struct resource mem_res[] = { - { - .name = "Kernel code", - .start = 0, - .end = 0, - .flags = IORESOURCE_MEM - }, - { - .name = "Kernel data", - .start = 0, - .end = 0, - .flags = IORESOURCE_MEM - } -}; - -#define kernel_code mem_res[0] -#define kernel_data mem_res[1] - -void __init early_print(const char *str, ...) -{ - char buf[256]; - va_list ap; - - va_start(ap, str); - vsnprintf(buf, sizeof(buf), str, ap); - va_end(ap); - - printk("%s", buf); -} - -static void __init setup_processor(void) -{ - struct cpu_info *cpu_info; - - /* - * locate processor in the list of supported processor - * types. The linker builds this table for us from the - * entries in arch/arm/mm/proc.S - */ - cpu_info = lookup_processor_type(read_cpuid_id()); - if (!cpu_info) { - printk("CPU configuration botched (ID %08x), unable to continue.\n", - read_cpuid_id()); - while (1); - } - - cpu_name = cpu_info->cpu_name; - - printk("CPU: %s [%08x] revision %d\n", - cpu_name, read_cpuid_id(), read_cpuid_id() & 15); - - sprintf(init_utsname()->machine, "aarch64"); - elf_hwcap = 0; -} - -static void __init setup_machine_fdt(phys_addr_t dt_phys) -{ - struct boot_param_header *devtree; - unsigned long dt_root; - - /* Check we have a non-NULL DT pointer */ - if (!dt_phys) { - early_print("\n" - "Error: NULL or invalid device tree blob\n" - "The dtb must be 8-byte aligned and passed in the first 512MB of memory\n" - "\nPlease check your bootloader.\n"); - - while (true) - cpu_relax(); - - } - - devtree = phys_to_virt(dt_phys); - - /* Check device tree validity */ - if (be32_to_cpu(devtree->magic) != OF_DT_HEADER) { - early_print("\n" - "Error: invalid device tree blob at physical address 0x%p (virtual address 0x%p)\n" - "Expected 0x%x, found 0x%x\n" - "\nPlease check your bootloader.\n", - dt_phys, devtree, OF_DT_HEADER, - be32_to_cpu(devtree->magic)); - - while (true) - cpu_relax(); - } - - initial_boot_params = devtree; - dt_root = of_get_flat_dt_root(); - - machine_name = of_get_flat_dt_prop(dt_root, "model", NULL); - if (!machine_name) - machine_name = of_get_flat_dt_prop(dt_root, "compatible", NULL); - if (!machine_name) - machine_name = ""; - pr_info("Machine: %s\n", machine_name); - - /* Retrieve various information from the /chosen node */ - of_scan_flat_dt(early_init_dt_scan_chosen, boot_command_line); - /* Initialize {size,address}-cells info */ - of_scan_flat_dt(early_init_dt_scan_root, NULL); - /* Setup memory, calling early_init_dt_add_memory_arch */ - of_scan_flat_dt(early_init_dt_scan_memory, NULL); -} - -void __init early_init_dt_add_memory_arch(u64 base, u64 size) -{ - size &= PAGE_MASK; - memblock_add(base, size); -} - -void * __init early_init_dt_alloc_memory_arch(u64 size, u64 align) -{ - return __va(memblock_alloc(size, align)); -} - -/* - * Limit the memory size that was specified via FDT. - */ -static int __init early_mem(char *p) -{ - phys_addr_t limit; - - if (!p) - return 1; - - limit = memparse(p, &p) & PAGE_MASK; - pr_notice("Memory limited to %lldMB\n", limit >> 20); - - memblock_enforce_memory_limit(limit); - - return 0; -} -early_param("mem", early_mem); - -static void __init request_standard_resources(void) -{ - struct memblock_region *region; - struct resource *res; - - kernel_code.start = virt_to_phys(_text); - kernel_code.end = virt_to_phys(_etext - 1); - kernel_data.start = virt_to_phys(_sdata); - kernel_data.end = virt_to_phys(_end - 1); - - for_each_memblock(memory, region) { - res = alloc_bootmem_low(sizeof(*res)); - res->name = "System RAM"; - res->start = __pfn_to_phys(memblock_region_memory_base_pfn(region)); - res->end = __pfn_to_phys(memblock_region_memory_end_pfn(region)) - 1; - res->flags = IORESOURCE_MEM | IORESOURCE_BUSY; - - request_resource(&iomem_resource, res); - - if (kernel_code.start >= res->start && - kernel_code.end <= res->end) - request_resource(res, &kernel_code); - if (kernel_data.start >= res->start && - kernel_data.end <= res->end) - request_resource(res, &kernel_data); - } -} - -void __init setup_arch(char **cmdline_p) -{ - setup_processor(); - - setup_machine_fdt(__fdt_pointer); - - init_mm.start_code = (unsigned long) _text; - init_mm.end_code = (unsigned long) _etext; - init_mm.end_data = (unsigned long) _edata; - init_mm.brk = (unsigned long) _end; - - *cmdline_p = boot_command_line; - - parse_early_param(); - - arm64_memblock_init(); - - paging_init(); - request_standard_resources(); - - unflatten_device_tree(); - -#ifdef CONFIG_SMP - smp_init_cpus(); -#endif - -#ifdef CONFIG_VT -#if defined(CONFIG_VGA_CONSOLE) - conswitchp = &vga_con; -#elif defined(CONFIG_DUMMY_CONSOLE) - conswitchp = &dummy_con; -#endif -#endif -} - -static DEFINE_PER_CPU(struct cpu, cpu_data); - -static int __init topology_init(void) -{ - int i; - - for_each_possible_cpu(i) { - struct cpu *cpu = &per_cpu(cpu_data, i); - cpu->hotpluggable = 1; - register_cpu(cpu, i); - } - - return 0; -} -subsys_initcall(topology_init); - -static const char *hwcap_str[] = { - "fp", - "asimd", - NULL -}; - -static int c_show(struct seq_file *m, void *v) -{ - int i; - - seq_printf(m, "Processor\t: %s rev %d (%s)\n", - cpu_name, read_cpuid_id() & 15, ELF_PLATFORM); - - for_each_online_cpu(i) { - /* - * glibc reads /proc/cpuinfo to determine the number of - * online processors, looking for lines beginning with - * "processor". Give glibc what it expects. - */ -#ifdef CONFIG_SMP - seq_printf(m, "processor\t: %d\n", i); -#endif - seq_printf(m, "BogoMIPS\t: %lu.%02lu\n\n", - loops_per_jiffy / (500000UL/HZ), - loops_per_jiffy / (5000UL/HZ) % 100); - } - - /* dump out the processor features */ - seq_puts(m, "Features\t: "); - - for (i = 0; hwcap_str[i]; i++) - if (elf_hwcap & (1 << i)) - seq_printf(m, "%s ", hwcap_str[i]); - - seq_printf(m, "\nCPU implementer\t: 0x%02x\n", read_cpuid_id() >> 24); - seq_printf(m, "CPU architecture: AArch64\n"); - seq_printf(m, "CPU variant\t: 0x%x\n", (read_cpuid_id() >> 20) & 15); - seq_printf(m, "CPU part\t: 0x%03x\n", (read_cpuid_id() >> 4) & 0xfff); - seq_printf(m, "CPU revision\t: %d\n", read_cpuid_id() & 15); - - seq_puts(m, "\n"); - - seq_printf(m, "Hardware\t: %s\n", machine_name); - - return 0; -} - -static void *c_start(struct seq_file *m, loff_t *pos) -{ - return *pos < 1 ? (void *)1 : NULL; -} - -static void *c_next(struct seq_file *m, void *v, loff_t *pos) -{ - ++*pos; - return NULL; -} - -static void c_stop(struct seq_file *m, void *v) -{ -} - -const struct seq_operations cpuinfo_op = { - .start = c_start, - .next = c_next, - .stop = c_stop, - .show = c_show -}; diff --git a/trunk/arch/arm64/kernel/signal.c b/trunk/arch/arm64/kernel/signal.c deleted file mode 100644 index 8807ba2cf262..000000000000 --- a/trunk/arch/arm64/kernel/signal.c +++ /dev/null @@ -1,437 +0,0 @@ -/* - * Based on arch/arm/kernel/signal.c - * - * Copyright (C) 1995-2009 Russell King - * Copyright (C) 2012 ARM 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 -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* - * Do a signal return; undo the signal stack. These are aligned to 128-bit. - */ -struct rt_sigframe { - struct siginfo info; - struct ucontext uc; -}; - -static int preserve_fpsimd_context(struct fpsimd_context __user *ctx) -{ - struct fpsimd_state *fpsimd = ¤t->thread.fpsimd_state; - int err; - - /* dump the hardware registers to the fpsimd_state structure */ - fpsimd_save_state(fpsimd); - - /* copy the FP and status/control registers */ - err = __copy_to_user(ctx->vregs, fpsimd->vregs, sizeof(fpsimd->vregs)); - __put_user_error(fpsimd->fpsr, &ctx->fpsr, err); - __put_user_error(fpsimd->fpcr, &ctx->fpcr, err); - - /* copy the magic/size information */ - __put_user_error(FPSIMD_MAGIC, &ctx->head.magic, err); - __put_user_error(sizeof(struct fpsimd_context), &ctx->head.size, err); - - return err ? -EFAULT : 0; -} - -static int restore_fpsimd_context(struct fpsimd_context __user *ctx) -{ - struct fpsimd_state fpsimd; - __u32 magic, size; - int err = 0; - - /* check the magic/size information */ - __get_user_error(magic, &ctx->head.magic, err); - __get_user_error(size, &ctx->head.size, err); - if (err) - return -EFAULT; - if (magic != FPSIMD_MAGIC || size != sizeof(struct fpsimd_context)) - return -EINVAL; - - /* copy the FP and status/control registers */ - err = __copy_from_user(fpsimd.vregs, ctx->vregs, - sizeof(fpsimd.vregs)); - __get_user_error(fpsimd.fpsr, &ctx->fpsr, err); - __get_user_error(fpsimd.fpcr, &ctx->fpcr, err); - - /* load the hardware registers from the fpsimd_state structure */ - if (!err) { - preempt_disable(); - fpsimd_load_state(&fpsimd); - preempt_enable(); - } - - return err ? -EFAULT : 0; -} - -static int restore_sigframe(struct pt_regs *regs, - struct rt_sigframe __user *sf) -{ - sigset_t set; - int i, err; - struct aux_context __user *aux = - (struct aux_context __user *)sf->uc.uc_mcontext.__reserved; - - err = __copy_from_user(&set, &sf->uc.uc_sigmask, sizeof(set)); - if (err == 0) - set_current_blocked(&set); - - for (i = 0; i < 31; i++) - __get_user_error(regs->regs[i], &sf->uc.uc_mcontext.regs[i], - err); - __get_user_error(regs->sp, &sf->uc.uc_mcontext.sp, err); - __get_user_error(regs->pc, &sf->uc.uc_mcontext.pc, err); - __get_user_error(regs->pstate, &sf->uc.uc_mcontext.pstate, err); - - /* - * Avoid sys_rt_sigreturn() restarting. - */ - regs->syscallno = ~0UL; - - err |= !valid_user_regs(®s->user_regs); - - if (err == 0) - err |= restore_fpsimd_context(&aux->fpsimd); - - return err; -} - -asmlinkage long sys_rt_sigreturn(struct pt_regs *regs) -{ - struct rt_sigframe __user *frame; - - /* Always make any pending restarted system calls return -EINTR */ - current_thread_info()->restart_block.fn = do_no_restart_syscall; - - /* - * Since we stacked the signal on a 128-bit boundary, then 'sp' should - * be word aligned here. - */ - if (regs->sp & 15) - goto badframe; - - frame = (struct rt_sigframe __user *)regs->sp; - - if (!access_ok(VERIFY_READ, frame, sizeof (*frame))) - goto badframe; - - if (restore_sigframe(regs, frame)) - goto badframe; - - if (do_sigaltstack(&frame->uc.uc_stack, - NULL, regs->sp) == -EFAULT) - goto badframe; - - return regs->regs[0]; - -badframe: - if (show_unhandled_signals) - pr_info_ratelimited("%s[%d]: bad frame in %s: pc=%08llx sp=%08llx\n", - current->comm, task_pid_nr(current), __func__, - regs->pc, regs->sp); - force_sig(SIGSEGV, current); - return 0; -} - -asmlinkage long sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, - unsigned long sp) -{ - return do_sigaltstack(uss, uoss, sp); -} - -static int setup_sigframe(struct rt_sigframe __user *sf, - struct pt_regs *regs, sigset_t *set) -{ - int i, err = 0; - struct aux_context __user *aux = - (struct aux_context __user *)sf->uc.uc_mcontext.__reserved; - - for (i = 0; i < 31; i++) - __put_user_error(regs->regs[i], &sf->uc.uc_mcontext.regs[i], - err); - __put_user_error(regs->sp, &sf->uc.uc_mcontext.sp, err); - __put_user_error(regs->pc, &sf->uc.uc_mcontext.pc, err); - __put_user_error(regs->pstate, &sf->uc.uc_mcontext.pstate, err); - - __put_user_error(current->thread.fault_address, &sf->uc.uc_mcontext.fault_address, err); - - err |= __copy_to_user(&sf->uc.uc_sigmask, set, sizeof(*set)); - - if (err == 0) - err |= preserve_fpsimd_context(&aux->fpsimd); - - /* set the "end" magic */ - __put_user_error(0, &aux->end.magic, err); - __put_user_error(0, &aux->end.size, err); - - return err; -} - -static void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, - int framesize) -{ - unsigned long sp, sp_top; - void __user *frame; - - sp = sp_top = regs->sp; - - /* - * This is the X/Open sanctioned signal stack switching. - */ - if ((ka->sa.sa_flags & SA_ONSTACK) && !sas_ss_flags(sp)) - sp = sp_top = current->sas_ss_sp + current->sas_ss_size; - - /* room for stack frame (FP, LR) */ - sp -= 16; - - sp = (sp - framesize) & ~15; - frame = (void __user *)sp; - - /* - * Check that we can actually write to the signal frame. - */ - if (!access_ok(VERIFY_WRITE, frame, sp_top - sp)) - frame = NULL; - - return frame; -} - -static int setup_return(struct pt_regs *regs, struct k_sigaction *ka, - void __user *frame, int usig) -{ - int err = 0; - __sigrestore_t sigtramp; - unsigned long __user *sp = (unsigned long __user *)regs->sp; - - /* set up the stack frame */ - __put_user_error(regs->regs[29], sp - 2, err); - __put_user_error(regs->regs[30], sp - 1, err); - - regs->regs[0] = usig; - regs->regs[29] = regs->sp - 16; - regs->sp = (unsigned long)frame; - regs->pc = (unsigned long)ka->sa.sa_handler; - - if (ka->sa.sa_flags & SA_RESTORER) - sigtramp = ka->sa.sa_restorer; - else - sigtramp = VDSO_SYMBOL(current->mm->context.vdso, sigtramp); - - regs->regs[30] = (unsigned long)sigtramp; - - return err; -} - -static int setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info, - sigset_t *set, struct pt_regs *regs) -{ - struct rt_sigframe __user *frame; - stack_t stack; - int err = 0; - - frame = get_sigframe(ka, regs, sizeof(*frame)); - if (!frame) - return 1; - - __put_user_error(0, &frame->uc.uc_flags, err); - __put_user_error(NULL, &frame->uc.uc_link, err); - - memset(&stack, 0, sizeof(stack)); - stack.ss_sp = (void __user *)current->sas_ss_sp; - stack.ss_flags = sas_ss_flags(regs->sp); - stack.ss_size = current->sas_ss_size; - err |= __copy_to_user(&frame->uc.uc_stack, &stack, sizeof(stack)); - - err |= setup_sigframe(frame, regs, set); - if (err == 0) - err = setup_return(regs, ka, frame, usig); - - if (err == 0 && ka->sa.sa_flags & SA_SIGINFO) { - err |= copy_siginfo_to_user(&frame->info, info); - regs->regs[1] = (unsigned long)&frame->info; - regs->regs[2] = (unsigned long)&frame->uc; - } - - return err; -} - -static void setup_restart_syscall(struct pt_regs *regs) -{ - if (is_compat_task()) - compat_setup_restart_syscall(regs); - else - regs->regs[8] = __NR_restart_syscall; -} - -/* - * OK, we're invoking a handler - */ -static void handle_signal(unsigned long sig, struct k_sigaction *ka, - siginfo_t *info, struct pt_regs *regs) -{ - struct thread_info *thread = current_thread_info(); - struct task_struct *tsk = current; - sigset_t *oldset = sigmask_to_save(); - int usig = sig; - int ret; - - /* - * translate the signal - */ - if (usig < 32 && thread->exec_domain && thread->exec_domain->signal_invmap) - usig = thread->exec_domain->signal_invmap[usig]; - - /* - * Set up the stack frame - */ - if (is_compat_task()) { - if (ka->sa.sa_flags & SA_SIGINFO) - ret = compat_setup_rt_frame(usig, ka, info, oldset, - regs); - else - ret = compat_setup_frame(usig, ka, oldset, regs); - } else { - ret = setup_rt_frame(usig, ka, info, oldset, regs); - } - - /* - * Check that the resulting registers are actually sane. - */ - ret |= !valid_user_regs(®s->user_regs); - - if (ret != 0) { - force_sigsegv(sig, tsk); - return; - } - - /* - * Fast forward the stepping logic so we step into the signal - * handler. - */ - user_fastforward_single_step(tsk); - - signal_delivered(sig, info, ka, regs, 0); -} - -/* - * Note that 'init' is a special process: it doesn't get signals it doesn't - * want to handle. Thus you cannot kill init even with a SIGKILL even by - * mistake. - * - * Note that we go through the signals twice: once to check the signals that - * the kernel can handle, and then we build all the user-level signal handling - * stack-frames in one go after that. - */ -static void do_signal(struct pt_regs *regs) -{ - unsigned long continue_addr = 0, restart_addr = 0; - struct k_sigaction ka; - siginfo_t info; - int signr, retval = 0; - int syscall = (int)regs->syscallno; - - /* - * If we were from a system call, check for system call restarting... - */ - if (syscall >= 0) { - continue_addr = regs->pc; - restart_addr = continue_addr - (compat_thumb_mode(regs) ? 2 : 4); - retval = regs->regs[0]; - - /* - * Avoid additional syscall restarting via ret_to_user. - */ - regs->syscallno = ~0UL; - - /* - * Prepare for system call restart. We do this here so that a - * debugger will see the already changed PC. - */ - switch (retval) { - case -ERESTARTNOHAND: - case -ERESTARTSYS: - case -ERESTARTNOINTR: - case -ERESTART_RESTARTBLOCK: - regs->regs[0] = regs->orig_x0; - regs->pc = restart_addr; - break; - } - } - - /* - * Get the signal to deliver. When running under ptrace, at this point - * the debugger may change all of our registers. - */ - signr = get_signal_to_deliver(&info, &ka, regs, NULL); - if (signr > 0) { - /* - * Depending on the signal settings, we may need to revert the - * decision to restart the system call, but skip this if a - * debugger has chosen to restart at a different PC. - */ - if (regs->pc == restart_addr && - (retval == -ERESTARTNOHAND || - retval == -ERESTART_RESTARTBLOCK || - (retval == -ERESTARTSYS && - !(ka.sa.sa_flags & SA_RESTART)))) { - regs->regs[0] = -EINTR; - regs->pc = continue_addr; - } - - handle_signal(signr, &ka, &info, regs); - return; - } - - /* - * Handle restarting a different system call. As above, if a debugger - * has chosen to restart at a different PC, ignore the restart. - */ - if (syscall >= 0 && regs->pc == restart_addr) { - if (retval == -ERESTART_RESTARTBLOCK) - setup_restart_syscall(regs); - user_rewind_single_step(current); - } - - restore_saved_sigmask(); -} - -asmlinkage void do_notify_resume(struct pt_regs *regs, - unsigned int thread_flags) -{ - if (thread_flags & _TIF_SIGPENDING) - do_signal(regs); - - if (thread_flags & _TIF_NOTIFY_RESUME) { - clear_thread_flag(TIF_NOTIFY_RESUME); - tracehook_notify_resume(regs); - } -} diff --git a/trunk/arch/arm64/kernel/signal32.c b/trunk/arch/arm64/kernel/signal32.c deleted file mode 100644 index ac74c2f261e3..000000000000 --- a/trunk/arch/arm64/kernel/signal32.c +++ /dev/null @@ -1,876 +0,0 @@ -/* - * Based on arch/arm/kernel/signal.c - * - * Copyright (C) 1995-2009 Russell King - * Copyright (C) 2012 ARM Ltd. - * Modified by Will Deacon - * - * 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 . - */ - -#define __SYSCALL_COMPAT - -#include -#include -#include -#include - -#include -#include -#include -#include - -typedef struct compat_siginfo { - int si_signo; - int si_errno; - int si_code; - - union { - /* The padding is the same size as AArch64. */ - int _pad[SI_PAD_SIZE]; - - /* kill() */ - struct { - compat_pid_t _pid; /* sender's pid */ - __compat_uid32_t _uid; /* sender's uid */ - } _kill; - - /* POSIX.1b timers */ - struct { - compat_timer_t _tid; /* timer id */ - int _overrun; /* overrun count */ - compat_sigval_t _sigval; /* same as below */ - int _sys_private; /* not to be passed to user */ - } _timer; - - /* POSIX.1b signals */ - struct { - compat_pid_t _pid; /* sender's pid */ - __compat_uid32_t _uid; /* sender's uid */ - compat_sigval_t _sigval; - } _rt; - - /* SIGCHLD */ - struct { - compat_pid_t _pid; /* which child */ - __compat_uid32_t _uid; /* sender's uid */ - int _status; /* exit code */ - compat_clock_t _utime; - compat_clock_t _stime; - } _sigchld; - - /* SIGILL, SIGFPE, SIGSEGV, SIGBUS */ - struct { - compat_uptr_t _addr; /* faulting insn/memory ref. */ - short _addr_lsb; /* LSB of the reported address */ - } _sigfault; - - /* SIGPOLL */ - struct { - compat_long_t _band; /* POLL_IN, POLL_OUT, POLL_MSG */ - int _fd; - } _sigpoll; - } _sifields; -} compat_siginfo_t; - -struct compat_sigaction { - compat_uptr_t sa_handler; - compat_ulong_t sa_flags; - compat_uptr_t sa_restorer; - compat_sigset_t sa_mask; -}; - -struct compat_old_sigaction { - compat_uptr_t sa_handler; - compat_old_sigset_t sa_mask; - compat_ulong_t sa_flags; - compat_uptr_t sa_restorer; -}; - -typedef struct compat_sigaltstack { - compat_uptr_t ss_sp; - int ss_flags; - compat_size_t ss_size; -} compat_stack_t; - -struct compat_sigcontext { - /* We always set these two fields to 0 */ - compat_ulong_t trap_no; - compat_ulong_t error_code; - - compat_ulong_t oldmask; - compat_ulong_t arm_r0; - compat_ulong_t arm_r1; - compat_ulong_t arm_r2; - compat_ulong_t arm_r3; - compat_ulong_t arm_r4; - compat_ulong_t arm_r5; - compat_ulong_t arm_r6; - compat_ulong_t arm_r7; - compat_ulong_t arm_r8; - compat_ulong_t arm_r9; - compat_ulong_t arm_r10; - compat_ulong_t arm_fp; - compat_ulong_t arm_ip; - compat_ulong_t arm_sp; - compat_ulong_t arm_lr; - compat_ulong_t arm_pc; - compat_ulong_t arm_cpsr; - compat_ulong_t fault_address; -}; - -struct compat_ucontext { - compat_ulong_t uc_flags; - struct compat_ucontext *uc_link; - compat_stack_t uc_stack; - struct compat_sigcontext uc_mcontext; - compat_sigset_t uc_sigmask; - int __unused[32 - (sizeof (compat_sigset_t) / sizeof (int))]; - compat_ulong_t uc_regspace[128] __attribute__((__aligned__(8))); -}; - -struct compat_vfp_sigframe { - compat_ulong_t magic; - compat_ulong_t size; - struct compat_user_vfp { - compat_u64 fpregs[32]; - compat_ulong_t fpscr; - } ufp; - struct compat_user_vfp_exc { - compat_ulong_t fpexc; - compat_ulong_t fpinst; - compat_ulong_t fpinst2; - } ufp_exc; -} __attribute__((__aligned__(8))); - -#define VFP_MAGIC 0x56465001 -#define VFP_STORAGE_SIZE sizeof(struct compat_vfp_sigframe) - -struct compat_aux_sigframe { - struct compat_vfp_sigframe vfp; - - /* Something that isn't a valid magic number for any coprocessor. */ - unsigned long end_magic; -} __attribute__((__aligned__(8))); - -struct compat_sigframe { - struct compat_ucontext uc; - compat_ulong_t retcode[2]; -}; - -struct compat_rt_sigframe { - struct compat_siginfo info; - struct compat_sigframe sig; -}; - -#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) - -/* - * For ARM syscalls, the syscall number has to be loaded into r7. - * We do not support an OABI userspace. - */ -#define MOV_R7_NR_SIGRETURN (0xe3a07000 | __NR_sigreturn) -#define SVC_SYS_SIGRETURN (0xef000000 | __NR_sigreturn) -#define MOV_R7_NR_RT_SIGRETURN (0xe3a07000 | __NR_rt_sigreturn) -#define SVC_SYS_RT_SIGRETURN (0xef000000 | __NR_rt_sigreturn) - -/* - * For Thumb syscalls, we also pass the syscall number via r7. We therefore - * need two 16-bit instructions. - */ -#define SVC_THUMB_SIGRETURN (((0xdf00 | __NR_sigreturn) << 16) | \ - 0x2700 | __NR_sigreturn) -#define SVC_THUMB_RT_SIGRETURN (((0xdf00 | __NR_rt_sigreturn) << 16) | \ - 0x2700 | __NR_rt_sigreturn) - -const compat_ulong_t aarch32_sigret_code[6] = { - /* - * AArch32 sigreturn code. - * We don't construct an OABI SWI - instead we just set the imm24 field - * to the EABI syscall number so that we create a sane disassembly. - */ - MOV_R7_NR_SIGRETURN, SVC_SYS_SIGRETURN, SVC_THUMB_SIGRETURN, - MOV_R7_NR_RT_SIGRETURN, SVC_SYS_RT_SIGRETURN, SVC_THUMB_RT_SIGRETURN, -}; - -static inline int put_sigset_t(compat_sigset_t __user *uset, sigset_t *set) -{ - compat_sigset_t cset; - - cset.sig[0] = set->sig[0] & 0xffffffffull; - cset.sig[1] = set->sig[0] >> 32; - - return copy_to_user(uset, &cset, sizeof(*uset)); -} - -static inline int get_sigset_t(sigset_t *set, - const compat_sigset_t __user *uset) -{ - compat_sigset_t s32; - - if (copy_from_user(&s32, uset, sizeof(*uset))) - return -EFAULT; - - set->sig[0] = s32.sig[0] | (((long)s32.sig[1]) << 32); - return 0; -} - -int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from) -{ - int err; - - if (!access_ok(VERIFY_WRITE, to, sizeof(*to))) - return -EFAULT; - - /* If you change siginfo_t structure, please be sure - * this code is fixed accordingly. - * It should never copy any pad contained in the structure - * to avoid security leaks, but must copy the generic - * 3 ints plus the relevant union member. - * This routine must convert siginfo from 64bit to 32bit as well - * at the same time. - */ - err = __put_user(from->si_signo, &to->si_signo); - err |= __put_user(from->si_errno, &to->si_errno); - err |= __put_user((short)from->si_code, &to->si_code); - if (from->si_code < 0) - err |= __copy_to_user(&to->_sifields._pad, &from->_sifields._pad, - SI_PAD_SIZE); - else switch (from->si_code & __SI_MASK) { - case __SI_KILL: - err |= __put_user(from->si_pid, &to->si_pid); - err |= __put_user(from->si_uid, &to->si_uid); - break; - case __SI_TIMER: - err |= __put_user(from->si_tid, &to->si_tid); - err |= __put_user(from->si_overrun, &to->si_overrun); - err |= __put_user((compat_uptr_t)(unsigned long)from->si_ptr, - &to->si_ptr); - break; - case __SI_POLL: - err |= __put_user(from->si_band, &to->si_band); - err |= __put_user(from->si_fd, &to->si_fd); - break; - case __SI_FAULT: - err |= __put_user((compat_uptr_t)(unsigned long)from->si_addr, - &to->si_addr); -#ifdef BUS_MCEERR_AO - /* - * Other callers might not initialize the si_lsb field, - * so check explicitely for the right codes here. - */ - if (from->si_code == BUS_MCEERR_AR || from->si_code == BUS_MCEERR_AO) - err |= __put_user(from->si_addr_lsb, &to->si_addr_lsb); -#endif - break; - case __SI_CHLD: - err |= __put_user(from->si_pid, &to->si_pid); - err |= __put_user(from->si_uid, &to->si_uid); - err |= __put_user(from->si_status, &to->si_status); - err |= __put_user(from->si_utime, &to->si_utime); - err |= __put_user(from->si_stime, &to->si_stime); - break; - case __SI_RT: /* This is not generated by the kernel as of now. */ - case __SI_MESGQ: /* But this is */ - err |= __put_user(from->si_pid, &to->si_pid); - err |= __put_user(from->si_uid, &to->si_uid); - err |= __put_user((compat_uptr_t)(unsigned long)from->si_ptr, &to->si_ptr); - break; - default: /* this is just in case for now ... */ - err |= __put_user(from->si_pid, &to->si_pid); - err |= __put_user(from->si_uid, &to->si_uid); - break; - } - return err; -} - -int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from) -{ - memset(to, 0, sizeof *to); - - if (copy_from_user(to, from, __ARCH_SI_PREAMBLE_SIZE) || - copy_from_user(to->_sifields._pad, - from->_sifields._pad, SI_PAD_SIZE)) - return -EFAULT; - - return 0; -} - -/* - * VFP save/restore code. - */ -static int compat_preserve_vfp_context(struct compat_vfp_sigframe __user *frame) -{ - struct fpsimd_state *fpsimd = ¤t->thread.fpsimd_state; - compat_ulong_t magic = VFP_MAGIC; - compat_ulong_t size = VFP_STORAGE_SIZE; - compat_ulong_t fpscr, fpexc; - int err = 0; - - /* - * Save the hardware registers to the fpsimd_state structure. - * Note that this also saves V16-31, which aren't visible - * in AArch32. - */ - fpsimd_save_state(fpsimd); - - /* Place structure header on the stack */ - __put_user_error(magic, &frame->magic, err); - __put_user_error(size, &frame->size, err); - - /* - * Now copy the FP registers. Since the registers are packed, - * we can copy the prefix we want (V0-V15) as it is. - * FIXME: Won't work if big endian. - */ - err |= __copy_to_user(&frame->ufp.fpregs, fpsimd->vregs, - sizeof(frame->ufp.fpregs)); - - /* Create an AArch32 fpscr from the fpsr and the fpcr. */ - fpscr = (fpsimd->fpsr & VFP_FPSCR_STAT_MASK) | - (fpsimd->fpcr & VFP_FPSCR_CTRL_MASK); - __put_user_error(fpscr, &frame->ufp.fpscr, err); - - /* - * The exception register aren't available so we fake up a - * basic FPEXC and zero everything else. - */ - fpexc = (1 << 30); - __put_user_error(fpexc, &frame->ufp_exc.fpexc, err); - __put_user_error(0, &frame->ufp_exc.fpinst, err); - __put_user_error(0, &frame->ufp_exc.fpinst2, err); - - return err ? -EFAULT : 0; -} - -static int compat_restore_vfp_context(struct compat_vfp_sigframe __user *frame) -{ - struct fpsimd_state fpsimd; - compat_ulong_t magic = VFP_MAGIC; - compat_ulong_t size = VFP_STORAGE_SIZE; - compat_ulong_t fpscr; - int err = 0; - - __get_user_error(magic, &frame->magic, err); - __get_user_error(size, &frame->size, err); - - if (err) - return -EFAULT; - if (magic != VFP_MAGIC || size != VFP_STORAGE_SIZE) - return -EINVAL; - - /* - * Copy the FP registers into the start of the fpsimd_state. - * FIXME: Won't work if big endian. - */ - err |= __copy_from_user(fpsimd.vregs, frame->ufp.fpregs, - sizeof(frame->ufp.fpregs)); - - /* Extract the fpsr and the fpcr from the fpscr */ - __get_user_error(fpscr, &frame->ufp.fpscr, err); - fpsimd.fpsr = fpscr & VFP_FPSCR_STAT_MASK; - fpsimd.fpcr = fpscr & VFP_FPSCR_CTRL_MASK; - - /* - * We don't need to touch the exception register, so - * reload the hardware state. - */ - if (!err) { - preempt_disable(); - fpsimd_load_state(&fpsimd); - preempt_enable(); - } - - return err ? -EFAULT : 0; -} - -/* - * atomically swap in the new signal mask, and wait for a signal. - */ -asmlinkage int compat_sys_sigsuspend(int restart, compat_ulong_t oldmask, - compat_old_sigset_t mask) -{ - sigset_t blocked; - - siginitset(¤t->blocked, mask); - return sigsuspend(&blocked); -} - -asmlinkage int compat_sys_sigaction(int sig, - const struct compat_old_sigaction __user *act, - struct compat_old_sigaction __user *oact) -{ - struct k_sigaction new_ka, old_ka; - int ret; - compat_old_sigset_t mask; - compat_uptr_t handler, restorer; - - if (act) { - if (!access_ok(VERIFY_READ, act, sizeof(*act)) || - __get_user(handler, &act->sa_handler) || - __get_user(restorer, &act->sa_restorer) || - __get_user(new_ka.sa.sa_flags, &act->sa_flags) || - __get_user(mask, &act->sa_mask)) - return -EFAULT; - - new_ka.sa.sa_handler = compat_ptr(handler); - new_ka.sa.sa_restorer = compat_ptr(restorer); - siginitset(&new_ka.sa.sa_mask, mask); - } - - ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); - - if (!ret && oact) { - if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) || - __put_user(ptr_to_compat(old_ka.sa.sa_handler), - &oact->sa_handler) || - __put_user(ptr_to_compat(old_ka.sa.sa_restorer), - &oact->sa_restorer) || - __put_user(old_ka.sa.sa_flags, &oact->sa_flags) || - __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask)) - return -EFAULT; - } - - return ret; -} - -asmlinkage int compat_sys_rt_sigaction(int sig, - const struct compat_sigaction __user *act, - struct compat_sigaction __user *oact, - compat_size_t sigsetsize) -{ - struct k_sigaction new_ka, old_ka; - int ret; - - /* XXX: Don't preclude handling different sized sigset_t's. */ - if (sigsetsize != sizeof(compat_sigset_t)) - return -EINVAL; - - if (act) { - compat_uptr_t handler, restorer; - - ret = get_user(handler, &act->sa_handler); - new_ka.sa.sa_handler = compat_ptr(handler); - ret |= get_user(restorer, &act->sa_restorer); - new_ka.sa.sa_restorer = compat_ptr(restorer); - ret |= get_sigset_t(&new_ka.sa.sa_mask, &act->sa_mask); - ret |= __get_user(new_ka.sa.sa_flags, &act->sa_flags); - if (ret) - return -EFAULT; - } - - ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); - if (!ret && oact) { - ret = put_user(ptr_to_compat(old_ka.sa.sa_handler), &oact->sa_handler); - ret |= put_sigset_t(&oact->sa_mask, &old_ka.sa.sa_mask); - ret |= __put_user(old_ka.sa.sa_flags, &oact->sa_flags); - } - return ret; -} - -int compat_do_sigaltstack(compat_uptr_t compat_uss, compat_uptr_t compat_uoss, - compat_ulong_t sp) -{ - compat_stack_t __user *newstack = compat_ptr(compat_uss); - compat_stack_t __user *oldstack = compat_ptr(compat_uoss); - compat_uptr_t ss_sp; - int ret; - mm_segment_t old_fs; - stack_t uss, uoss; - - /* Marshall the compat new stack into a stack_t */ - if (newstack) { - if (get_user(ss_sp, &newstack->ss_sp) || - __get_user(uss.ss_flags, &newstack->ss_flags) || - __get_user(uss.ss_size, &newstack->ss_size)) - return -EFAULT; - uss.ss_sp = compat_ptr(ss_sp); - } - - old_fs = get_fs(); - set_fs(KERNEL_DS); - /* The __user pointer casts are valid because of the set_fs() */ - ret = do_sigaltstack( - newstack ? (stack_t __user *) &uss : NULL, - oldstack ? (stack_t __user *) &uoss : NULL, - (unsigned long)sp); - set_fs(old_fs); - - /* Convert the old stack_t into a compat stack. */ - if (!ret && oldstack && - (put_user(ptr_to_compat(uoss.ss_sp), &oldstack->ss_sp) || - __put_user(uoss.ss_flags, &oldstack->ss_flags) || - __put_user(uoss.ss_size, &oldstack->ss_size))) - return -EFAULT; - return ret; -} - -static int compat_restore_sigframe(struct pt_regs *regs, - struct compat_sigframe __user *sf) -{ - int err; - sigset_t set; - struct compat_aux_sigframe __user *aux; - - err = get_sigset_t(&set, &sf->uc.uc_sigmask); - if (err == 0) { - sigdelsetmask(&set, ~_BLOCKABLE); - set_current_blocked(&set); - } - - __get_user_error(regs->regs[0], &sf->uc.uc_mcontext.arm_r0, err); - __get_user_error(regs->regs[1], &sf->uc.uc_mcontext.arm_r1, err); - __get_user_error(regs->regs[2], &sf->uc.uc_mcontext.arm_r2, err); - __get_user_error(regs->regs[3], &sf->uc.uc_mcontext.arm_r3, err); - __get_user_error(regs->regs[4], &sf->uc.uc_mcontext.arm_r4, err); - __get_user_error(regs->regs[5], &sf->uc.uc_mcontext.arm_r5, err); - __get_user_error(regs->regs[6], &sf->uc.uc_mcontext.arm_r6, err); - __get_user_error(regs->regs[7], &sf->uc.uc_mcontext.arm_r7, err); - __get_user_error(regs->regs[8], &sf->uc.uc_mcontext.arm_r8, err); - __get_user_error(regs->regs[9], &sf->uc.uc_mcontext.arm_r9, err); - __get_user_error(regs->regs[10], &sf->uc.uc_mcontext.arm_r10, err); - __get_user_error(regs->regs[11], &sf->uc.uc_mcontext.arm_fp, err); - __get_user_error(regs->regs[12], &sf->uc.uc_mcontext.arm_ip, err); - __get_user_error(regs->compat_sp, &sf->uc.uc_mcontext.arm_sp, err); - __get_user_error(regs->compat_lr, &sf->uc.uc_mcontext.arm_lr, err); - __get_user_error(regs->pc, &sf->uc.uc_mcontext.arm_pc, err); - __get_user_error(regs->pstate, &sf->uc.uc_mcontext.arm_cpsr, err); - - /* - * Avoid compat_sys_sigreturn() restarting. - */ - regs->syscallno = ~0UL; - - err |= !valid_user_regs(®s->user_regs); - - aux = (struct compat_aux_sigframe __user *) sf->uc.uc_regspace; - if (err == 0) - err |= compat_restore_vfp_context(&aux->vfp); - - return err; -} - -asmlinkage int compat_sys_sigreturn(struct pt_regs *regs) -{ - struct compat_sigframe __user *frame; - - /* Always make any pending restarted system calls return -EINTR */ - current_thread_info()->restart_block.fn = do_no_restart_syscall; - - /* - * Since we stacked the signal on a 64-bit boundary, - * then 'sp' should be word aligned here. If it's - * not, then the user is trying to mess with us. - */ - if (regs->compat_sp & 7) - goto badframe; - - frame = (struct compat_sigframe __user *)regs->compat_sp; - - if (!access_ok(VERIFY_READ, frame, sizeof (*frame))) - goto badframe; - - if (compat_restore_sigframe(regs, frame)) - goto badframe; - - return regs->regs[0]; - -badframe: - if (show_unhandled_signals) - pr_info_ratelimited("%s[%d]: bad frame in %s: pc=%08llx sp=%08llx\n", - current->comm, task_pid_nr(current), __func__, - regs->pc, regs->sp); - force_sig(SIGSEGV, current); - return 0; -} - -asmlinkage int compat_sys_rt_sigreturn(struct pt_regs *regs) -{ - struct compat_rt_sigframe __user *frame; - - /* Always make any pending restarted system calls return -EINTR */ - current_thread_info()->restart_block.fn = do_no_restart_syscall; - - /* - * Since we stacked the signal on a 64-bit boundary, - * then 'sp' should be word aligned here. If it's - * not, then the user is trying to mess with us. - */ - if (regs->compat_sp & 7) - goto badframe; - - frame = (struct compat_rt_sigframe __user *)regs->compat_sp; - - if (!access_ok(VERIFY_READ, frame, sizeof (*frame))) - goto badframe; - - if (compat_restore_sigframe(regs, &frame->sig)) - goto badframe; - - if (compat_do_sigaltstack(ptr_to_compat(&frame->sig.uc.uc_stack), - ptr_to_compat((void __user *)NULL), - regs->compat_sp) == -EFAULT) - goto badframe; - - return regs->regs[0]; - -badframe: - if (show_unhandled_signals) - pr_info_ratelimited("%s[%d]: bad frame in %s: pc=%08llx sp=%08llx\n", - current->comm, task_pid_nr(current), __func__, - regs->pc, regs->sp); - force_sig(SIGSEGV, current); - return 0; -} - -static inline void __user *compat_get_sigframe(struct k_sigaction *ka, - struct pt_regs *regs, - int framesize) -{ - compat_ulong_t sp = regs->compat_sp; - void __user *frame; - - /* - * This is the X/Open sanctioned signal stack switching. - */ - if ((ka->sa.sa_flags & SA_ONSTACK) && !sas_ss_flags(sp)) - sp = current->sas_ss_sp + current->sas_ss_size; - - /* - * ATPCS B01 mandates 8-byte alignment - */ - frame = compat_ptr((compat_uptr_t)((sp - framesize) & ~7)); - - /* - * Check that we can actually write to the signal frame. - */ - if (!access_ok(VERIFY_WRITE, frame, framesize)) - frame = NULL; - - return frame; -} - -static int compat_setup_return(struct pt_regs *regs, struct k_sigaction *ka, - compat_ulong_t __user *rc, void __user *frame, - int usig) -{ - compat_ulong_t handler = ptr_to_compat(ka->sa.sa_handler); - compat_ulong_t retcode; - compat_ulong_t spsr = regs->pstate & ~PSR_f; - int thumb; - - /* Check if the handler is written for ARM or Thumb */ - thumb = handler & 1; - - if (thumb) { - spsr |= COMPAT_PSR_T_BIT; - spsr &= ~COMPAT_PSR_IT_MASK; - } else { - spsr &= ~COMPAT_PSR_T_BIT; - } - - if (ka->sa.sa_flags & SA_RESTORER) { - retcode = ptr_to_compat(ka->sa.sa_restorer); - } else { - /* Set up sigreturn pointer */ - unsigned int idx = thumb << 1; - - if (ka->sa.sa_flags & SA_SIGINFO) - idx += 3; - - retcode = AARCH32_VECTORS_BASE + - AARCH32_KERN_SIGRET_CODE_OFFSET + - (idx << 2) + thumb; - } - - regs->regs[0] = usig; - regs->compat_sp = ptr_to_compat(frame); - regs->compat_lr = retcode; - regs->pc = handler; - regs->pstate = spsr; - - return 0; -} - -static int compat_setup_sigframe(struct compat_sigframe __user *sf, - struct pt_regs *regs, sigset_t *set) -{ - struct compat_aux_sigframe __user *aux; - int err = 0; - - __put_user_error(regs->regs[0], &sf->uc.uc_mcontext.arm_r0, err); - __put_user_error(regs->regs[1], &sf->uc.uc_mcontext.arm_r1, err); - __put_user_error(regs->regs[2], &sf->uc.uc_mcontext.arm_r2, err); - __put_user_error(regs->regs[3], &sf->uc.uc_mcontext.arm_r3, err); - __put_user_error(regs->regs[4], &sf->uc.uc_mcontext.arm_r4, err); - __put_user_error(regs->regs[5], &sf->uc.uc_mcontext.arm_r5, err); - __put_user_error(regs->regs[6], &sf->uc.uc_mcontext.arm_r6, err); - __put_user_error(regs->regs[7], &sf->uc.uc_mcontext.arm_r7, err); - __put_user_error(regs->regs[8], &sf->uc.uc_mcontext.arm_r8, err); - __put_user_error(regs->regs[9], &sf->uc.uc_mcontext.arm_r9, err); - __put_user_error(regs->regs[10], &sf->uc.uc_mcontext.arm_r10, err); - __put_user_error(regs->regs[11], &sf->uc.uc_mcontext.arm_fp, err); - __put_user_error(regs->regs[12], &sf->uc.uc_mcontext.arm_ip, err); - __put_user_error(regs->compat_sp, &sf->uc.uc_mcontext.arm_sp, err); - __put_user_error(regs->compat_lr, &sf->uc.uc_mcontext.arm_lr, err); - __put_user_error(regs->pc, &sf->uc.uc_mcontext.arm_pc, err); - __put_user_error(regs->pstate, &sf->uc.uc_mcontext.arm_cpsr, err); - - __put_user_error((compat_ulong_t)0, &sf->uc.uc_mcontext.trap_no, err); - __put_user_error((compat_ulong_t)0, &sf->uc.uc_mcontext.error_code, err); - __put_user_error(current->thread.fault_address, &sf->uc.uc_mcontext.fault_address, err); - __put_user_error(set->sig[0], &sf->uc.uc_mcontext.oldmask, err); - - err |= put_sigset_t(&sf->uc.uc_sigmask, set); - - aux = (struct compat_aux_sigframe __user *) sf->uc.uc_regspace; - - if (err == 0) - err |= compat_preserve_vfp_context(&aux->vfp); - __put_user_error(0, &aux->end_magic, err); - - return err; -} - -/* - * 32-bit signal handling routines called from signal.c - */ -int compat_setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info, - sigset_t *set, struct pt_regs *regs) -{ - struct compat_rt_sigframe __user *frame; - compat_stack_t stack; - int err = 0; - - frame = compat_get_sigframe(ka, regs, sizeof(*frame)); - - if (!frame) - return 1; - - err |= copy_siginfo_to_user32(&frame->info, info); - - __put_user_error(0, &frame->sig.uc.uc_flags, err); - __put_user_error(NULL, &frame->sig.uc.uc_link, err); - - memset(&stack, 0, sizeof(stack)); - stack.ss_sp = (compat_uptr_t)current->sas_ss_sp; - stack.ss_flags = sas_ss_flags(regs->compat_sp); - stack.ss_size = current->sas_ss_size; - err |= __copy_to_user(&frame->sig.uc.uc_stack, &stack, sizeof(stack)); - - err |= compat_setup_sigframe(&frame->sig, regs, set); - if (err == 0) - err = compat_setup_return(regs, ka, frame->sig.retcode, frame, - usig); - - if (err == 0) { - regs->regs[1] = (compat_ulong_t)(unsigned long)&frame->info; - regs->regs[2] = (compat_ulong_t)(unsigned long)&frame->sig.uc; - } - - return err; -} - -int compat_setup_frame(int usig, struct k_sigaction *ka, sigset_t *set, - struct pt_regs *regs) -{ - struct compat_sigframe __user *frame; - int err = 0; - - frame = compat_get_sigframe(ka, regs, sizeof(*frame)); - - if (!frame) - return 1; - - __put_user_error(0x5ac3c35a, &frame->uc.uc_flags, err); - - err |= compat_setup_sigframe(frame, regs, set); - if (err == 0) - err = compat_setup_return(regs, ka, frame->retcode, frame, usig); - - return err; -} - -/* - * RT signals don't have generic compat wrappers. - * See arch/powerpc/kernel/signal_32.c - */ -asmlinkage int compat_sys_rt_sigprocmask(int how, compat_sigset_t __user *set, - compat_sigset_t __user *oset, - compat_size_t sigsetsize) -{ - sigset_t s; - sigset_t __user *up; - int ret; - mm_segment_t old_fs = get_fs(); - - if (set) { - if (get_sigset_t(&s, set)) - return -EFAULT; - } - - set_fs(KERNEL_DS); - /* This is valid because of the set_fs() */ - up = (sigset_t __user *) &s; - ret = sys_rt_sigprocmask(how, set ? up : NULL, oset ? up : NULL, - sigsetsize); - set_fs(old_fs); - if (ret) - return ret; - if (oset) { - if (put_sigset_t(oset, &s)) - return -EFAULT; - } - return 0; -} - -asmlinkage int compat_sys_rt_sigpending(compat_sigset_t __user *set, - compat_size_t sigsetsize) -{ - sigset_t s; - int ret; - mm_segment_t old_fs = get_fs(); - - set_fs(KERNEL_DS); - /* The __user pointer cast is valid because of the set_fs() */ - ret = sys_rt_sigpending((sigset_t __user *) &s, sigsetsize); - set_fs(old_fs); - if (!ret) { - if (put_sigset_t(set, &s)) - return -EFAULT; - } - return ret; -} - -asmlinkage int compat_sys_rt_sigqueueinfo(int pid, int sig, - compat_siginfo_t __user *uinfo) -{ - siginfo_t info; - int ret; - mm_segment_t old_fs = get_fs(); - - ret = copy_siginfo_from_user32(&info, uinfo); - if (unlikely(ret)) - return ret; - - set_fs (KERNEL_DS); - /* The __user pointer cast is valid because of the set_fs() */ - ret = sys_rt_sigqueueinfo(pid, sig, (siginfo_t __user *) &info); - set_fs (old_fs); - return ret; -} - -void compat_setup_restart_syscall(struct pt_regs *regs) -{ - regs->regs[7] = __NR_restart_syscall; -} diff --git a/trunk/arch/arm64/kernel/smp.c b/trunk/arch/arm64/kernel/smp.c deleted file mode 100644 index b711525be21f..000000000000 --- a/trunk/arch/arm64/kernel/smp.c +++ /dev/null @@ -1,469 +0,0 @@ -/* - * SMP initialisation and IPI support - * Based on arch/arm/kernel/smp.c - * - * Copyright (C) 2012 ARM 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* - * as from 2.5, kernels no longer have an init_tasks structure - * so we need some other way of telling a new secondary core - * where to place its SVC stack - */ -struct secondary_data secondary_data; -volatile unsigned long secondary_holding_pen_release = -1; - -enum ipi_msg_type { - IPI_RESCHEDULE, - IPI_CALL_FUNC, - IPI_CALL_FUNC_SINGLE, - IPI_CPU_STOP, -}; - -static DEFINE_RAW_SPINLOCK(boot_lock); - -/* - * Write secondary_holding_pen_release in a way that is guaranteed to be - * visible to all observers, irrespective of whether they're taking part - * in coherency or not. This is necessary for the hotplug code to work - * reliably. - */ -static void __cpuinit write_pen_release(int val) -{ - void *start = (void *)&secondary_holding_pen_release; - unsigned long size = sizeof(secondary_holding_pen_release); - - secondary_holding_pen_release = val; - __flush_dcache_area(start, size); -} - -/* - * Boot a secondary CPU, and assign it the specified idle task. - * This also gives us the initial stack to use for this CPU. - */ -static int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) -{ - unsigned long timeout; - - /* - * Set synchronisation state between this boot processor - * and the secondary one - */ - raw_spin_lock(&boot_lock); - - /* - * Update the pen release flag. - */ - write_pen_release(cpu); - - /* - * Send an event, causing the secondaries to read pen_release. - */ - sev(); - - timeout = jiffies + (1 * HZ); - while (time_before(jiffies, timeout)) { - if (secondary_holding_pen_release == -1UL) - break; - udelay(10); - } - - /* - * Now the secondary core is starting up let it run its - * calibrations, then wait for it to finish - */ - raw_spin_unlock(&boot_lock); - - return secondary_holding_pen_release != -1 ? -ENOSYS : 0; -} - -static DECLARE_COMPLETION(cpu_running); - -int __cpuinit __cpu_up(unsigned int cpu, struct task_struct *idle) -{ - int ret; - - /* - * We need to tell the secondary core where to find its stack and the - * page tables. - */ - secondary_data.stack = task_stack_page(idle) + THREAD_START_SP; - __flush_dcache_area(&secondary_data, sizeof(secondary_data)); - - /* - * Now bring the CPU into our world. - */ - ret = boot_secondary(cpu, idle); - if (ret == 0) { - /* - * CPU was successfully started, wait for it to come online or - * time out. - */ - wait_for_completion_timeout(&cpu_running, - msecs_to_jiffies(1000)); - - if (!cpu_online(cpu)) { - pr_crit("CPU%u: failed to come online\n", cpu); - ret = -EIO; - } - } else { - pr_err("CPU%u: failed to boot: %d\n", cpu, ret); - } - - secondary_data.stack = NULL; - - return ret; -} - -/* - * This is the secondary CPU boot entry. We're using this CPUs - * idle thread stack, but a set of temporary page tables. - */ -asmlinkage void __cpuinit secondary_start_kernel(void) -{ - struct mm_struct *mm = &init_mm; - unsigned int cpu = smp_processor_id(); - - printk("CPU%u: Booted secondary processor\n", cpu); - - /* - * All kernel threads share the same mm context; grab a - * reference and switch to it. - */ - atomic_inc(&mm->mm_count); - current->active_mm = mm; - cpumask_set_cpu(cpu, mm_cpumask(mm)); - - /* - * TTBR0 is only used for the identity mapping at this stage. Make it - * point to zero page to avoid speculatively fetching new entries. - */ - cpu_set_reserved_ttbr0(); - flush_tlb_all(); - - preempt_disable(); - trace_hardirqs_off(); - - /* - * Let the primary processor know we're out of the - * pen, then head off into the C entry point - */ - write_pen_release(-1); - - /* - * Synchronise with the boot thread. - */ - raw_spin_lock(&boot_lock); - raw_spin_unlock(&boot_lock); - - /* - * Enable local interrupts. - */ - notify_cpu_starting(cpu); - local_irq_enable(); - local_fiq_enable(); - - /* - * OK, now it's safe to let the boot CPU continue. Wait for - * the CPU migration code to notice that the CPU is online - * before we continue. - */ - set_cpu_online(cpu, true); - while (!cpu_active(cpu)) - cpu_relax(); - - /* - * OK, it's off to the idle thread for us - */ - cpu_idle(); -} - -void __init smp_cpus_done(unsigned int max_cpus) -{ - unsigned long bogosum = loops_per_jiffy * num_online_cpus(); - - pr_info("SMP: Total of %d processors activated (%lu.%02lu BogoMIPS).\n", - num_online_cpus(), bogosum / (500000/HZ), - (bogosum / (5000/HZ)) % 100); -} - -void __init smp_prepare_boot_cpu(void) -{ -} - -static void (*smp_cross_call)(const struct cpumask *, unsigned int); -static phys_addr_t cpu_release_addr[NR_CPUS]; - -/* - * Enumerate the possible CPU set from the device tree. - */ -void __init smp_init_cpus(void) -{ - const char *enable_method; - struct device_node *dn = NULL; - int cpu = 0; - - while ((dn = of_find_node_by_type(dn, "cpu"))) { - if (cpu >= NR_CPUS) - goto next; - - /* - * We currently support only the "spin-table" enable-method. - */ - enable_method = of_get_property(dn, "enable-method", NULL); - if (!enable_method || strcmp(enable_method, "spin-table")) { - pr_err("CPU %d: missing or invalid enable-method property: %s\n", - cpu, enable_method); - goto next; - } - - /* - * Determine the address from which the CPU is polling. - */ - if (of_property_read_u64(dn, "cpu-release-addr", - &cpu_release_addr[cpu])) { - pr_err("CPU %d: missing or invalid cpu-release-addr property\n", - cpu); - goto next; - } - - set_cpu_possible(cpu, true); -next: - cpu++; - } - - /* sanity check */ - if (cpu > NR_CPUS) - pr_warning("no. of cores (%d) greater than configured maximum of %d - clipping\n", - cpu, NR_CPUS); -} - -void __init smp_prepare_cpus(unsigned int max_cpus) -{ - int cpu; - void **release_addr; - unsigned int ncores = num_possible_cpus(); - - /* - * are we trying to boot more cores than exist? - */ - if (max_cpus > ncores) - max_cpus = ncores; - - /* - * Initialise the present map (which describes the set of CPUs - * actually populated at the present time) and release the - * secondaries from the bootloader. - */ - for_each_possible_cpu(cpu) { - if (max_cpus == 0) - break; - - if (!cpu_release_addr[cpu]) - continue; - - release_addr = __va(cpu_release_addr[cpu]); - release_addr[0] = (void *)__pa(secondary_holding_pen); - __flush_dcache_area(release_addr, sizeof(release_addr[0])); - - set_cpu_present(cpu, true); - max_cpus--; - } - - /* - * Send an event to wake up the secondaries. - */ - sev(); -} - - -void __init set_smp_cross_call(void (*fn)(const struct cpumask *, unsigned int)) -{ - smp_cross_call = fn; -} - -void arch_send_call_function_ipi_mask(const struct cpumask *mask) -{ - smp_cross_call(mask, IPI_CALL_FUNC); -} - -void arch_send_call_function_single_ipi(int cpu) -{ - smp_cross_call(cpumask_of(cpu), IPI_CALL_FUNC_SINGLE); -} - -static const char *ipi_types[NR_IPI] = { -#define S(x,s) [x - IPI_RESCHEDULE] = s - S(IPI_RESCHEDULE, "Rescheduling interrupts"), - S(IPI_CALL_FUNC, "Function call interrupts"), - S(IPI_CALL_FUNC_SINGLE, "Single function call interrupts"), - S(IPI_CPU_STOP, "CPU stop interrupts"), -}; - -void show_ipi_list(struct seq_file *p, int prec) -{ - unsigned int cpu, i; - - for (i = 0; i < NR_IPI; i++) { - seq_printf(p, "%*s%u:%s", prec - 1, "IPI", i + IPI_RESCHEDULE, - prec >= 4 ? " " : ""); - for_each_present_cpu(cpu) - seq_printf(p, "%10u ", - __get_irq_stat(cpu, ipi_irqs[i])); - seq_printf(p, " %s\n", ipi_types[i]); - } -} - -u64 smp_irq_stat_cpu(unsigned int cpu) -{ - u64 sum = 0; - int i; - - for (i = 0; i < NR_IPI; i++) - sum += __get_irq_stat(cpu, ipi_irqs[i]); - - return sum; -} - -static DEFINE_RAW_SPINLOCK(stop_lock); - -/* - * ipi_cpu_stop - handle IPI from smp_send_stop() - */ -static void ipi_cpu_stop(unsigned int cpu) -{ - if (system_state == SYSTEM_BOOTING || - system_state == SYSTEM_RUNNING) { - raw_spin_lock(&stop_lock); - pr_crit("CPU%u: stopping\n", cpu); - dump_stack(); - raw_spin_unlock(&stop_lock); - } - - set_cpu_online(cpu, false); - - local_fiq_disable(); - local_irq_disable(); - - while (1) - cpu_relax(); -} - -/* - * Main handler for inter-processor interrupts - */ -void handle_IPI(int ipinr, struct pt_regs *regs) -{ - unsigned int cpu = smp_processor_id(); - struct pt_regs *old_regs = set_irq_regs(regs); - - if (ipinr >= IPI_RESCHEDULE && ipinr < IPI_RESCHEDULE + NR_IPI) - __inc_irq_stat(cpu, ipi_irqs[ipinr - IPI_RESCHEDULE]); - - switch (ipinr) { - case IPI_RESCHEDULE: - scheduler_ipi(); - break; - - case IPI_CALL_FUNC: - irq_enter(); - generic_smp_call_function_interrupt(); - irq_exit(); - break; - - case IPI_CALL_FUNC_SINGLE: - irq_enter(); - generic_smp_call_function_single_interrupt(); - irq_exit(); - break; - - case IPI_CPU_STOP: - irq_enter(); - ipi_cpu_stop(cpu); - irq_exit(); - break; - - default: - pr_crit("CPU%u: Unknown IPI message 0x%x\n", cpu, ipinr); - break; - } - set_irq_regs(old_regs); -} - -void smp_send_reschedule(int cpu) -{ - smp_cross_call(cpumask_of(cpu), IPI_RESCHEDULE); -} - -void smp_send_stop(void) -{ - unsigned long timeout; - - if (num_online_cpus() > 1) { - cpumask_t mask; - - cpumask_copy(&mask, cpu_online_mask); - cpu_clear(smp_processor_id(), mask); - - smp_cross_call(&mask, IPI_CPU_STOP); - } - - /* Wait up to one second for other CPUs to stop */ - timeout = USEC_PER_SEC; - while (num_online_cpus() > 1 && timeout--) - udelay(1); - - if (num_online_cpus() > 1) - pr_warning("SMP: failed to stop secondary CPUs\n"); -} - -/* - * not supported here - */ -int setup_profiling_timer(unsigned int multiplier) -{ - return -EINVAL; -} diff --git a/trunk/arch/arm64/kernel/stacktrace.c b/trunk/arch/arm64/kernel/stacktrace.c deleted file mode 100644 index d25459ff57fc..000000000000 --- a/trunk/arch/arm64/kernel/stacktrace.c +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Stack tracing support - * - * Copyright (C) 2012 ARM 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 - -/* - * AArch64 PCS assigns the frame pointer to x29. - * - * A simple function prologue looks like this: - * sub sp, sp, #0x10 - * stp x29, x30, [sp] - * mov x29, sp - * - * A simple function epilogue looks like this: - * mov sp, x29 - * ldp x29, x30, [sp] - * add sp, sp, #0x10 - */ -int unwind_frame(struct stackframe *frame) -{ - unsigned long high, low; - unsigned long fp = frame->fp; - - low = frame->sp; - high = ALIGN(low, THREAD_SIZE); - - if (fp < low || fp > high || fp & 0xf) - return -EINVAL; - - frame->sp = fp + 0x10; - frame->fp = *(unsigned long *)(fp); - frame->pc = *(unsigned long *)(fp + 8); - - return 0; -} - -void notrace walk_stackframe(struct stackframe *frame, - int (*fn)(struct stackframe *, void *), void *data) -{ - while (1) { - int ret; - - if (fn(frame, data)) - break; - ret = unwind_frame(frame); - if (ret < 0) - break; - } -} -EXPORT_SYMBOL(walk_stackframe); - -#ifdef CONFIG_STACKTRACE -struct stack_trace_data { - struct stack_trace *trace; - unsigned int no_sched_functions; - unsigned int skip; -}; - -static int save_trace(struct stackframe *frame, void *d) -{ - struct stack_trace_data *data = d; - struct stack_trace *trace = data->trace; - unsigned long addr = frame->pc; - - if (data->no_sched_functions && in_sched_functions(addr)) - return 0; - if (data->skip) { - data->skip--; - return 0; - } - - trace->entries[trace->nr_entries++] = addr; - - return trace->nr_entries >= trace->max_entries; -} - -void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace) -{ - struct stack_trace_data data; - struct stackframe frame; - - data.trace = trace; - data.skip = trace->skip; - - if (tsk != current) { - data.no_sched_functions = 1; - frame.fp = thread_saved_fp(tsk); - frame.sp = thread_saved_sp(tsk); - frame.pc = thread_saved_pc(tsk); - } else { - register unsigned long current_sp asm("sp"); - data.no_sched_functions = 0; - frame.fp = (unsigned long)__builtin_frame_address(0); - frame.sp = current_sp; - frame.pc = (unsigned long)save_stack_trace_tsk; - } - - walk_stackframe(&frame, save_trace, &data); - if (trace->nr_entries < trace->max_entries) - trace->entries[trace->nr_entries++] = ULONG_MAX; -} - -void save_stack_trace(struct stack_trace *trace) -{ - save_stack_trace_tsk(current, trace); -} -EXPORT_SYMBOL_GPL(save_stack_trace); -#endif diff --git a/trunk/arch/arm64/kernel/sys.c b/trunk/arch/arm64/kernel/sys.c deleted file mode 100644 index 905fcfb0ddd0..000000000000 --- a/trunk/arch/arm64/kernel/sys.c +++ /dev/null @@ -1,138 +0,0 @@ -/* - * AArch64-specific system calls implementation - * - * Copyright (C) 2012 ARM Ltd. - * Author: Catalin Marinas - * - * 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 -#include -#include -#include - -/* - * Clone a task - this clones the calling program thread. - */ -asmlinkage long sys_clone(unsigned long clone_flags, unsigned long newsp, - int __user *parent_tidptr, unsigned long tls_val, - int __user *child_tidptr, struct pt_regs *regs) -{ - if (!newsp) - newsp = regs->sp; - /* 16-byte aligned stack mandatory on AArch64 */ - if (newsp & 15) - return -EINVAL; - return do_fork(clone_flags, newsp, regs, 0, parent_tidptr, child_tidptr); -} - -/* - * sys_execve() executes a new program. - */ -asmlinkage long sys_execve(const char __user *filenamei, - const char __user *const __user *argv, - const char __user *const __user *envp, - struct pt_regs *regs) -{ - long error; - char * filename; - - filename = getname(filenamei); - error = PTR_ERR(filename); - if (IS_ERR(filename)) - goto out; - error = do_execve(filename, argv, envp, regs); - putname(filename); -out: - return error; -} - -int kernel_execve(const char *filename, - const char *const argv[], - const char *const envp[]) -{ - struct pt_regs regs; - int ret; - - memset(®s, 0, sizeof(struct pt_regs)); - ret = do_execve(filename, - (const char __user *const __user *)argv, - (const char __user *const __user *)envp, ®s); - if (ret < 0) - goto out; - - /* - * Save argc to the register structure for userspace. - */ - regs.regs[0] = ret; - - /* - * We were successful. We won't be returning to our caller, but - * instead to user space by manipulating the kernel stack. - */ - asm( "add x0, %0, %1\n\t" - "mov x1, %2\n\t" - "mov x2, %3\n\t" - "bl memmove\n\t" /* copy regs to top of stack */ - "mov x27, #0\n\t" /* not a syscall */ - "mov x28, %0\n\t" /* thread structure */ - "mov sp, x0\n\t" /* reposition stack pointer */ - "b ret_to_user" - : - : "r" (current_thread_info()), - "Ir" (THREAD_START_SP - sizeof(regs)), - "r" (®s), - "Ir" (sizeof(regs)) - : "x0", "x1", "x2", "x27", "x28", "x30", "memory"); - - out: - return ret; -} -EXPORT_SYMBOL(kernel_execve); - -asmlinkage long sys_mmap(unsigned long addr, unsigned long len, - unsigned long prot, unsigned long flags, - unsigned long fd, off_t off) -{ - if (offset_in_page(off) != 0) - return -EINVAL; - - return sys_mmap_pgoff(addr, len, prot, flags, fd, off >> PAGE_SHIFT); -} - -/* - * Wrappers to pass the pt_regs argument. - */ -#define sys_execve sys_execve_wrapper -#define sys_clone sys_clone_wrapper -#define sys_rt_sigreturn sys_rt_sigreturn_wrapper -#define sys_sigaltstack sys_sigaltstack_wrapper - -#include - -#undef __SYSCALL -#define __SYSCALL(nr, sym) [nr] = sym, - -/* - * The sys_call_table array must be 4K aligned to be accessible from - * kernel/entry.S. - */ -void *sys_call_table[__NR_syscalls] __aligned(4096) = { - [0 ... __NR_syscalls - 1] = sys_ni_syscall, -#include -}; diff --git a/trunk/arch/arm64/kernel/sys32.S b/trunk/arch/arm64/kernel/sys32.S deleted file mode 100644 index 5e4dc93cc31f..000000000000 --- a/trunk/arch/arm64/kernel/sys32.S +++ /dev/null @@ -1,282 +0,0 @@ -/* - * Compat system call wrappers - * - * Copyright (C) 2012 ARM Ltd. - * Authors: Will Deacon - * Catalin Marinas - * - * 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 - -/* - * System call wrappers for the AArch32 compatibility layer. - */ -compat_sys_fork_wrapper: - mov x0, sp - b compat_sys_fork -ENDPROC(compat_sys_fork_wrapper) - -compat_sys_vfork_wrapper: - mov x0, sp - b compat_sys_vfork -ENDPROC(compat_sys_vfork_wrapper) - -compat_sys_execve_wrapper: - mov x3, sp - b compat_sys_execve -ENDPROC(compat_sys_execve_wrapper) - -compat_sys_clone_wrapper: - mov x5, sp - b compat_sys_clone -ENDPROC(compat_sys_clone_wrapper) - -compat_sys_sigreturn_wrapper: - mov x0, sp - mov x27, #0 // prevent syscall restart handling (why) - b compat_sys_sigreturn -ENDPROC(compat_sys_sigreturn_wrapper) - -compat_sys_rt_sigreturn_wrapper: - mov x0, sp - mov x27, #0 // prevent syscall restart handling (why) - b compat_sys_rt_sigreturn -ENDPROC(compat_sys_rt_sigreturn_wrapper) - -compat_sys_sigaltstack_wrapper: - ldr x2, [sp, #S_COMPAT_SP] - b compat_do_sigaltstack -ENDPROC(compat_sys_sigaltstack_wrapper) - -compat_sys_statfs64_wrapper: - mov w3, #84 - cmp w1, #88 - csel w1, w3, w1, eq - b compat_sys_statfs64 -ENDPROC(compat_sys_statfs64_wrapper) - -compat_sys_fstatfs64_wrapper: - mov w3, #84 - cmp w1, #88 - csel w1, w3, w1, eq - b compat_sys_fstatfs64 -ENDPROC(compat_sys_fstatfs64_wrapper) - -/* - * Wrappers for AArch32 syscalls that either take 64-bit parameters - * in registers or that take 32-bit parameters which require sign - * extension. - */ -compat_sys_lseek_wrapper: - sxtw x1, w1 - b sys_lseek -ENDPROC(compat_sys_lseek_wrapper) - -compat_sys_pread64_wrapper: - orr x3, x4, x5, lsl #32 - b sys_pread64 -ENDPROC(compat_sys_pread64_wrapper) - -compat_sys_pwrite64_wrapper: - orr x3, x4, x5, lsl #32 - b sys_pwrite64 -ENDPROC(compat_sys_pwrite64_wrapper) - -compat_sys_truncate64_wrapper: - orr x1, x2, x3, lsl #32 - b sys_truncate -ENDPROC(compat_sys_truncate64_wrapper) - -compat_sys_ftruncate64_wrapper: - orr x1, x2, x3, lsl #32 - b sys_ftruncate -ENDPROC(compat_sys_ftruncate64_wrapper) - -compat_sys_readahead_wrapper: - orr x1, x2, x3, lsl #32 - mov w2, w4 - b sys_readahead -ENDPROC(compat_sys_readahead_wrapper) - -compat_sys_lookup_dcookie: - orr x0, x0, x1, lsl #32 - mov w1, w2 - mov w2, w3 - b sys_lookup_dcookie -ENDPROC(compat_sys_lookup_dcookie) - -compat_sys_fadvise64_64_wrapper: - mov w6, w1 - orr x1, x2, x3, lsl #32 - orr x2, x4, x5, lsl #32 - mov w3, w6 - b sys_fadvise64_64 -ENDPROC(compat_sys_fadvise64_64_wrapper) - -compat_sys_sync_file_range2_wrapper: - orr x2, x2, x3, lsl #32 - orr x3, x4, x5, lsl #32 - b sys_sync_file_range2 -ENDPROC(compat_sys_sync_file_range2_wrapper) - -compat_sys_fallocate_wrapper: - orr x2, x2, x3, lsl #32 - orr x3, x4, x5, lsl #32 - b sys_fallocate -ENDPROC(compat_sys_fallocate_wrapper) - -compat_sys_fanotify_mark_wrapper: - orr x2, x2, x3, lsl #32 - mov w3, w4 - mov w4, w5 - b sys_fanotify_mark -ENDPROC(compat_sys_fanotify_mark_wrapper) - -/* - * Use the compat system call wrappers. - */ -#define sys_fork compat_sys_fork_wrapper -#define sys_open compat_sys_open -#define sys_execve compat_sys_execve_wrapper -#define sys_lseek compat_sys_lseek_wrapper -#define sys_mount compat_sys_mount -#define sys_ptrace compat_sys_ptrace -#define sys_times compat_sys_times -#define sys_ioctl compat_sys_ioctl -#define sys_fcntl compat_sys_fcntl -#define sys_ustat compat_sys_ustat -#define sys_sigaction compat_sys_sigaction -#define sys_sigsuspend compat_sys_sigsuspend -#define sys_sigpending compat_sys_sigpending -#define sys_setrlimit compat_sys_setrlimit -#define sys_getrusage compat_sys_getrusage -#define sys_gettimeofday compat_sys_gettimeofday -#define sys_settimeofday compat_sys_settimeofday -#define sys_statfs compat_sys_statfs -#define sys_fstatfs compat_sys_fstatfs -#define sys_setitimer compat_sys_setitimer -#define sys_getitimer compat_sys_getitimer -#define sys_newstat compat_sys_newstat -#define sys_newlstat compat_sys_newlstat -#define sys_newfstat compat_sys_newfstat -#define sys_wait4 compat_sys_wait4 -#define sys_sysinfo compat_sys_sysinfo -#define sys_sigreturn compat_sys_sigreturn_wrapper -#define sys_clone compat_sys_clone_wrapper -#define sys_adjtimex compat_sys_adjtimex -#define sys_sigprocmask compat_sys_sigprocmask -#define sys_getdents compat_sys_getdents -#define sys_select compat_sys_select -#define sys_readv compat_sys_readv -#define sys_writev compat_sys_writev -#define sys_sysctl compat_sys_sysctl -#define sys_sched_rr_get_interval compat_sys_sched_rr_get_interval -#define sys_nanosleep compat_sys_nanosleep -#define sys_rt_sigreturn compat_sys_rt_sigreturn_wrapper -#define sys_rt_sigaction compat_sys_rt_sigaction -#define sys_rt_sigprocmask compat_sys_rt_sigprocmask -#define sys_rt_sigpending compat_sys_rt_sigpending -#define sys_rt_sigtimedwait compat_sys_rt_sigtimedwait -#define sys_rt_sigqueueinfo compat_sys_rt_sigqueueinfo -#define sys_rt_sigsuspend compat_sys_rt_sigsuspend -#define sys_pread64 compat_sys_pread64_wrapper -#define sys_pwrite64 compat_sys_pwrite64_wrapper -#define sys_sigaltstack compat_sys_sigaltstack_wrapper -#define sys_sendfile compat_sys_sendfile -#define sys_vfork compat_sys_vfork_wrapper -#define sys_getrlimit compat_sys_getrlimit -#define sys_mmap2 sys_mmap_pgoff -#define sys_truncate64 compat_sys_truncate64_wrapper -#define sys_ftruncate64 compat_sys_ftruncate64_wrapper -#define sys_getdents64 compat_sys_getdents64 -#define sys_fcntl64 compat_sys_fcntl64 -#define sys_readahead compat_sys_readahead_wrapper -#define sys_futex compat_sys_futex -#define sys_sched_setaffinity compat_sys_sched_setaffinity -#define sys_sched_getaffinity compat_sys_sched_getaffinity -#define sys_io_setup compat_sys_io_setup -#define sys_io_getevents compat_sys_io_getevents -#define sys_io_submit compat_sys_io_submit -#define sys_lookup_dcookie compat_sys_lookup_dcookie -#define sys_timer_create compat_sys_timer_create -#define sys_timer_settime compat_sys_timer_settime -#define sys_timer_gettime compat_sys_timer_gettime -#define sys_clock_settime compat_sys_clock_settime -#define sys_clock_gettime compat_sys_clock_gettime -#define sys_clock_getres compat_sys_clock_getres -#define sys_clock_nanosleep compat_sys_clock_nanosleep -#define sys_statfs64 compat_sys_statfs64_wrapper -#define sys_fstatfs64 compat_sys_fstatfs64_wrapper -#define sys_utimes compat_sys_utimes -#define sys_fadvise64_64 compat_sys_fadvise64_64_wrapper -#define sys_mq_open compat_sys_mq_open -#define sys_mq_timedsend compat_sys_mq_timedsend -#define sys_mq_timedreceive compat_sys_mq_timedreceive -#define sys_mq_notify compat_sys_mq_notify -#define sys_mq_getsetattr compat_sys_mq_getsetattr -#define sys_waitid compat_sys_waitid -#define sys_recv compat_sys_recv -#define sys_recvfrom compat_sys_recvfrom -#define sys_setsockopt compat_sys_setsockopt -#define sys_getsockopt compat_sys_getsockopt -#define sys_sendmsg compat_sys_sendmsg -#define sys_recvmsg compat_sys_recvmsg -#define sys_semctl compat_sys_semctl -#define sys_msgsnd compat_sys_msgsnd -#define sys_msgrcv compat_sys_msgrcv -#define sys_msgctl compat_sys_msgctl -#define sys_shmat compat_sys_shmat -#define sys_shmctl compat_sys_shmctl -#define sys_keyctl compat_sys_keyctl -#define sys_semtimedop compat_sys_semtimedop -#define sys_mbind compat_sys_mbind -#define sys_get_mempolicy compat_sys_get_mempolicy -#define sys_set_mempolicy compat_sys_set_mempolicy -#define sys_openat compat_sys_openat -#define sys_futimesat compat_sys_futimesat -#define sys_pselect6 compat_sys_pselect6 -#define sys_ppoll compat_sys_ppoll -#define sys_set_robust_list compat_sys_set_robust_list -#define sys_get_robust_list compat_sys_get_robust_list -#define sys_sync_file_range2 compat_sys_sync_file_range2_wrapper -#define sys_vmsplice compat_sys_vmsplice -#define sys_move_pages compat_sys_move_pages -#define sys_epoll_pwait compat_sys_epoll_pwait -#define sys_kexec_load compat_sys_kexec_load -#define sys_utimensat compat_sys_utimensat -#define sys_signalfd compat_sys_signalfd -#define sys_fallocate compat_sys_fallocate_wrapper -#define sys_timerfd_settime compat_sys_timerfd_settime -#define sys_timerfd_gettime compat_sys_timerfd_gettime -#define sys_signalfd4 compat_sys_signalfd4 -#define sys_preadv compat_sys_preadv -#define sys_pwritev compat_sys_pwritev -#define sys_rt_tgsigqueueinfo compat_sys_rt_tgsigqueueinfo -#define sys_recvmmsg compat_sys_recvmmsg -#define sys_fanotify_mark compat_sys_fanotify_mark_wrapper - -#undef __SYSCALL -#define __SYSCALL(x, y) .quad y // x -#define __SYSCALL_COMPAT - -/* - * The system calls table must be 4KB aligned. - */ - .align 12 -ENTRY(compat_sys_call_table) -#include diff --git a/trunk/arch/arm64/kernel/sys_compat.c b/trunk/arch/arm64/kernel/sys_compat.c deleted file mode 100644 index 967e92fdff01..000000000000 --- a/trunk/arch/arm64/kernel/sys_compat.c +++ /dev/null @@ -1,164 +0,0 @@ -/* - * Based on arch/arm/kernel/sys_arm.c - * - * Copyright (C) People who wrote linux/arch/i386/kernel/sys_i386.c - * Copyright (C) 1995, 1996 Russell King. - * Copyright (C) 2012 ARM 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 . - */ - -#define __SYSCALL_COMPAT - -#include -#include -#include -#include -#include -#include - -#include -#include - -asmlinkage int compat_sys_fork(struct pt_regs *regs) -{ - return do_fork(SIGCHLD, regs->compat_sp, regs, 0, NULL, NULL); -} - -asmlinkage int compat_sys_clone(unsigned long clone_flags, unsigned long newsp, - int __user *parent_tidptr, int tls_val, - int __user *child_tidptr, struct pt_regs *regs) -{ - if (!newsp) - newsp = regs->compat_sp; - - return do_fork(clone_flags, newsp, regs, 0, parent_tidptr, child_tidptr); -} - -asmlinkage int compat_sys_vfork(struct pt_regs *regs) -{ - return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->compat_sp, - regs, 0, NULL, NULL); -} - -asmlinkage int compat_sys_execve(const char __user *filenamei, - compat_uptr_t argv, compat_uptr_t envp, - struct pt_regs *regs) -{ - int error; - char * filename; - - filename = getname(filenamei); - error = PTR_ERR(filename); - if (IS_ERR(filename)) - goto out; - error = compat_do_execve(filename, compat_ptr(argv), compat_ptr(envp), - regs); - putname(filename); -out: - return error; -} - -asmlinkage int compat_sys_sched_rr_get_interval(compat_pid_t pid, - struct compat_timespec __user *interval) -{ - struct timespec t; - int ret; - mm_segment_t old_fs = get_fs(); - - set_fs(KERNEL_DS); - ret = sys_sched_rr_get_interval(pid, (struct timespec __user *)&t); - set_fs(old_fs); - if (put_compat_timespec(&t, interval)) - return -EFAULT; - return ret; -} - -asmlinkage int compat_sys_sendfile(int out_fd, int in_fd, - compat_off_t __user *offset, s32 count) -{ - mm_segment_t old_fs = get_fs(); - int ret; - off_t of; - - if (offset && get_user(of, offset)) - return -EFAULT; - - set_fs(KERNEL_DS); - ret = sys_sendfile(out_fd, in_fd, offset ? (off_t __user *)&of : NULL, - count); - set_fs(old_fs); - - if (offset && put_user(of, offset)) - return -EFAULT; - return ret; -} - -static inline void -do_compat_cache_op(unsigned long start, unsigned long end, int flags) -{ - struct mm_struct *mm = current->active_mm; - struct vm_area_struct *vma; - - if (end < start || flags) - return; - - down_read(&mm->mmap_sem); - vma = find_vma(mm, start); - if (vma && vma->vm_start < end) { - if (start < vma->vm_start) - start = vma->vm_start; - if (end > vma->vm_end) - end = vma->vm_end; - up_read(&mm->mmap_sem); - __flush_cache_user_range(start & PAGE_MASK, PAGE_ALIGN(end)); - return; - } - up_read(&mm->mmap_sem); -} - -/* - * Handle all unrecognised system calls. - */ -long compat_arm_syscall(struct pt_regs *regs) -{ - unsigned int no = regs->regs[7]; - - switch (no) { - /* - * Flush a region from virtual address 'r0' to virtual address 'r1' - * _exclusive_. There is no alignment requirement on either address; - * user space does not need to know the hardware cache layout. - * - * r2 contains flags. It should ALWAYS be passed as ZERO until it - * is defined to be something else. For now we ignore it, but may - * the fires of hell burn in your belly if you break this rule. ;) - * - * (at a later date, we may want to allow this call to not flush - * various aspects of the cache. Passing '0' will guarantee that - * everything necessary gets flushed to maintain consistency in - * the specified region). - */ - case __ARM_NR_compat_cacheflush: - do_compat_cache_op(regs->regs[0], regs->regs[1], regs->regs[2]); - return 0; - - case __ARM_NR_compat_set_tls: - current->thread.tp_value = regs->regs[0]; - asm ("msr tpidrro_el0, %0" : : "r" (regs->regs[0])); - return 0; - - default: - return -ENOSYS; - } -} diff --git a/trunk/arch/arm64/kernel/time.c b/trunk/arch/arm64/kernel/time.c deleted file mode 100644 index 3b4b7258f492..000000000000 --- a/trunk/arch/arm64/kernel/time.c +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Based on arch/arm/kernel/time.c - * - * Copyright (C) 1991, 1992, 1995 Linus Torvalds - * Modifications for ARM (C) 1994-2001 Russell King - * Copyright (C) 2012 ARM 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 -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include - -#ifdef CONFIG_SMP -unsigned long profile_pc(struct pt_regs *regs) -{ - struct stackframe frame; - - if (!in_lock_functions(regs->pc)) - return regs->pc; - - frame.fp = regs->regs[29]; - frame.sp = regs->sp; - frame.pc = regs->pc; - do { - int ret = unwind_frame(&frame); - if (ret < 0) - return 0; - } while (in_lock_functions(frame.pc)); - - return frame.pc; -} -EXPORT_SYMBOL(profile_pc); -#endif - -void __init time_init(void) -{ - arm_generic_timer_init(); -} diff --git a/trunk/arch/arm64/kernel/traps.c b/trunk/arch/arm64/kernel/traps.c deleted file mode 100644 index 3883f842434f..000000000000 --- a/trunk/arch/arm64/kernel/traps.c +++ /dev/null @@ -1,348 +0,0 @@ -/* - * Based on arch/arm/kernel/traps.c - * - * Copyright (C) 1995-2009 Russell King - * Copyright (C) 2012 ARM 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 -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -static const char *handler[]= { - "Synchronous Abort", - "IRQ", - "FIQ", - "Error" -}; - -int show_unhandled_signals = 1; - -/* - * Dump out the contents of some memory nicely... - */ -static void dump_mem(const char *lvl, const char *str, unsigned long bottom, - unsigned long top) -{ - unsigned long first; - mm_segment_t fs; - int i; - - /* - * We need to switch to kernel mode so that we can use __get_user - * to safely read from kernel space. Note that we now dump the - * code first, just in case the backtrace kills us. - */ - fs = get_fs(); - set_fs(KERNEL_DS); - - printk("%s%s(0x%016lx to 0x%016lx)\n", lvl, str, bottom, top); - - for (first = bottom & ~31; first < top; first += 32) { - unsigned long p; - char str[sizeof(" 12345678") * 8 + 1]; - - memset(str, ' ', sizeof(str)); - str[sizeof(str) - 1] = '\0'; - - for (p = first, i = 0; i < 8 && p < top; i++, p += 4) { - if (p >= bottom && p < top) { - unsigned int val; - if (__get_user(val, (unsigned int *)p) == 0) - sprintf(str + i * 9, " %08x", val); - else - sprintf(str + i * 9, " ????????"); - } - } - printk("%s%04lx:%s\n", lvl, first & 0xffff, str); - } - - set_fs(fs); -} - -static void dump_backtrace_entry(unsigned long where, unsigned long stack) -{ - print_ip_sym(where); - if (in_exception_text(where)) - dump_mem("", "Exception stack", stack, - stack + sizeof(struct pt_regs)); -} - -static void dump_instr(const char *lvl, struct pt_regs *regs) -{ - unsigned long addr = instruction_pointer(regs); - mm_segment_t fs; - char str[sizeof("00000000 ") * 5 + 2 + 1], *p = str; - int i; - - /* - * We need to switch to kernel mode so that we can use __get_user - * to safely read from kernel space. Note that we now dump the - * code first, just in case the backtrace kills us. - */ - fs = get_fs(); - set_fs(KERNEL_DS); - - for (i = -4; i < 1; i++) { - unsigned int val, bad; - - bad = __get_user(val, &((u32 *)addr)[i]); - - if (!bad) - p += sprintf(p, i == 0 ? "(%08x) " : "%08x ", val); - else { - p += sprintf(p, "bad PC value"); - break; - } - } - printk("%sCode: %s\n", lvl, str); - - set_fs(fs); -} - -static void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk) -{ - struct stackframe frame; - const register unsigned long current_sp asm ("sp"); - - pr_debug("%s(regs = %p tsk = %p)\n", __func__, regs, tsk); - - if (!tsk) - tsk = current; - - if (regs) { - frame.fp = regs->regs[29]; - frame.sp = regs->sp; - frame.pc = regs->pc; - } else if (tsk == current) { - frame.fp = (unsigned long)__builtin_frame_address(0); - frame.sp = current_sp; - frame.pc = (unsigned long)dump_backtrace; - } else { - /* - * task blocked in __switch_to - */ - frame.fp = thread_saved_fp(tsk); - frame.sp = thread_saved_sp(tsk); - frame.pc = thread_saved_pc(tsk); - } - - printk("Call trace:\n"); - while (1) { - unsigned long where = frame.pc; - int ret; - - ret = unwind_frame(&frame); - if (ret < 0) - break; - dump_backtrace_entry(where, frame.sp); - } -} - -void dump_stack(void) -{ - dump_backtrace(NULL, NULL); -} - -EXPORT_SYMBOL(dump_stack); - -void show_stack(struct task_struct *tsk, unsigned long *sp) -{ - dump_backtrace(NULL, tsk); - barrier(); -} - -#ifdef CONFIG_PREEMPT -#define S_PREEMPT " PREEMPT" -#else -#define S_PREEMPT "" -#endif -#ifdef CONFIG_SMP -#define S_SMP " SMP" -#else -#define S_SMP "" -#endif - -static int __die(const char *str, int err, struct thread_info *thread, - struct pt_regs *regs) -{ - struct task_struct *tsk = thread->task; - static int die_counter; - int ret; - - pr_emerg("Internal error: %s: %x [#%d]" S_PREEMPT S_SMP "\n", - str, err, ++die_counter); - - /* trap and error numbers are mostly meaningless on ARM */ - ret = notify_die(DIE_OOPS, str, regs, err, 0, SIGSEGV); - if (ret == NOTIFY_STOP) - return ret; - - print_modules(); - __show_regs(regs); - pr_emerg("Process %.*s (pid: %d, stack limit = 0x%p)\n", - TASK_COMM_LEN, tsk->comm, task_pid_nr(tsk), thread + 1); - - if (!user_mode(regs) || in_interrupt()) { - dump_mem(KERN_EMERG, "Stack: ", regs->sp, - THREAD_SIZE + (unsigned long)task_stack_page(tsk)); - dump_backtrace(regs, tsk); - dump_instr(KERN_EMERG, regs); - } - - return ret; -} - -static DEFINE_RAW_SPINLOCK(die_lock); - -/* - * This function is protected against re-entrancy. - */ -void die(const char *str, struct pt_regs *regs, int err) -{ - struct thread_info *thread = current_thread_info(); - int ret; - - oops_enter(); - - raw_spin_lock_irq(&die_lock); - console_verbose(); - bust_spinlocks(1); - ret = __die(str, err, thread, regs); - - if (regs && kexec_should_crash(thread->task)) - crash_kexec(regs); - - bust_spinlocks(0); - add_taint(TAINT_DIE); - raw_spin_unlock_irq(&die_lock); - oops_exit(); - - if (in_interrupt()) - panic("Fatal exception in interrupt"); - if (panic_on_oops) - panic("Fatal exception"); - if (ret != NOTIFY_STOP) - do_exit(SIGSEGV); -} - -void arm64_notify_die(const char *str, struct pt_regs *regs, - struct siginfo *info, int err) -{ - if (user_mode(regs)) - force_sig_info(info->si_signo, info, current); - else - die(str, regs, err); -} - -asmlinkage void __exception do_undefinstr(struct pt_regs *regs) -{ - siginfo_t info; - void __user *pc = (void __user *)instruction_pointer(regs); - -#ifdef CONFIG_COMPAT - /* check for AArch32 breakpoint instructions */ - if (compat_user_mode(regs) && aarch32_break_trap(regs) == 0) - return; -#endif - - if (show_unhandled_signals) { - pr_info("%s[%d]: undefined instruction: pc=%p\n", - current->comm, task_pid_nr(current), pc); - dump_instr(KERN_INFO, regs); - } - - info.si_signo = SIGILL; - info.si_errno = 0; - info.si_code = ILL_ILLOPC; - info.si_addr = pc; - - arm64_notify_die("Oops - undefined instruction", regs, &info, 0); -} - -long compat_arm_syscall(struct pt_regs *regs); - -asmlinkage long do_ni_syscall(struct pt_regs *regs) -{ -#ifdef CONFIG_COMPAT - long ret; - if (is_compat_task()) { - ret = compat_arm_syscall(regs); - if (ret != -ENOSYS) - return ret; - } -#endif - - if (show_unhandled_signals) { - pr_info("%s[%d]: syscall %d\n", current->comm, - task_pid_nr(current), (int)regs->syscallno); - dump_instr("", regs); - if (user_mode(regs)) - __show_regs(regs); - } - - return sys_ni_syscall(); -} - -/* - * bad_mode handles the impossible case in the exception vector. - */ -asmlinkage void bad_mode(struct pt_regs *regs, int reason, unsigned int esr) -{ - console_verbose(); - - pr_crit("Bad mode in %s handler detected, code 0x%08x\n", - handler[reason], esr); - - die("Oops - bad mode", regs, 0); - local_irq_disable(); - panic("bad mode"); -} - -void __pte_error(const char *file, int line, unsigned long val) -{ - printk("%s:%d: bad pte %016lx.\n", file, line, val); -} - -void __pmd_error(const char *file, int line, unsigned long val) -{ - printk("%s:%d: bad pmd %016lx.\n", file, line, val); -} - -void __pgd_error(const char *file, int line, unsigned long val) -{ - printk("%s:%d: bad pgd %016lx.\n", file, line, val); -} - -void __init trap_init(void) -{ - return; -} diff --git a/trunk/arch/arm64/kernel/vdso.c b/trunk/arch/arm64/kernel/vdso.c deleted file mode 100644 index 17948fc7d663..000000000000 --- a/trunk/arch/arm64/kernel/vdso.c +++ /dev/null @@ -1,261 +0,0 @@ -/* - * VDSO implementation for AArch64 and vector page setup for AArch32. - * - * Copyright (C) 2012 ARM Limited - * - * 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 . - * - * Author: Will Deacon - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -extern char vdso_start, vdso_end; -static unsigned long vdso_pages; -static struct page **vdso_pagelist; - -/* - * The vDSO data page. - */ -static union { - struct vdso_data data; - u8 page[PAGE_SIZE]; -} vdso_data_store __page_aligned_data; -struct vdso_data *vdso_data = &vdso_data_store.data; - -#ifdef CONFIG_COMPAT -/* - * Create and map the vectors page for AArch32 tasks. - */ -static struct page *vectors_page[1]; - -static int alloc_vectors_page(void) -{ - extern char __kuser_helper_start[], __kuser_helper_end[]; - int kuser_sz = __kuser_helper_end - __kuser_helper_start; - unsigned long vpage; - - vpage = get_zeroed_page(GFP_ATOMIC); - - if (!vpage) - return -ENOMEM; - - /* kuser helpers */ - memcpy((void *)vpage + 0x1000 - kuser_sz, __kuser_helper_start, - kuser_sz); - - /* sigreturn code */ - memcpy((void *)vpage + AARCH32_KERN_SIGRET_CODE_OFFSET, - aarch32_sigret_code, sizeof(aarch32_sigret_code)); - - flush_icache_range(vpage, vpage + PAGE_SIZE); - vectors_page[0] = virt_to_page(vpage); - - return 0; -} -arch_initcall(alloc_vectors_page); - -int aarch32_setup_vectors_page(struct linux_binprm *bprm, int uses_interp) -{ - struct mm_struct *mm = current->mm; - unsigned long addr = AARCH32_VECTORS_BASE; - int ret; - - down_write(&mm->mmap_sem); - current->mm->context.vdso = (void *)addr; - - /* Map vectors page at the high address. */ - ret = install_special_mapping(mm, addr, PAGE_SIZE, - VM_READ|VM_EXEC|VM_MAYREAD|VM_MAYEXEC, - vectors_page); - - up_write(&mm->mmap_sem); - - return ret; -} -#endif /* CONFIG_COMPAT */ - -static int __init vdso_init(void) -{ - struct page *pg; - char *vbase; - int i, ret = 0; - - vdso_pages = (&vdso_end - &vdso_start) >> PAGE_SHIFT; - pr_info("vdso: %ld pages (%ld code, %ld data) at base %p\n", - vdso_pages + 1, vdso_pages, 1L, &vdso_start); - - /* Allocate the vDSO pagelist, plus a page for the data. */ - vdso_pagelist = kzalloc(sizeof(struct page *) * (vdso_pages + 1), - GFP_KERNEL); - if (vdso_pagelist == NULL) { - pr_err("Failed to allocate vDSO pagelist!\n"); - return -ENOMEM; - } - - /* Grab the vDSO code pages. */ - for (i = 0; i < vdso_pages; i++) { - pg = virt_to_page(&vdso_start + i*PAGE_SIZE); - ClearPageReserved(pg); - get_page(pg); - vdso_pagelist[i] = pg; - } - - /* Sanity check the shared object header. */ - vbase = vmap(vdso_pagelist, 1, 0, PAGE_KERNEL); - if (vbase == NULL) { - pr_err("Failed to map vDSO pagelist!\n"); - return -ENOMEM; - } else if (memcmp(vbase, "\177ELF", 4)) { - pr_err("vDSO is not a valid ELF object!\n"); - ret = -EINVAL; - goto unmap; - } - - /* Grab the vDSO data page. */ - pg = virt_to_page(vdso_data); - get_page(pg); - vdso_pagelist[i] = pg; - -unmap: - vunmap(vbase); - return ret; -} -arch_initcall(vdso_init); - -int arch_setup_additional_pages(struct linux_binprm *bprm, - int uses_interp) -{ - struct mm_struct *mm = current->mm; - unsigned long vdso_base, vdso_mapping_len; - int ret; - - /* Be sure to map the data page */ - vdso_mapping_len = (vdso_pages + 1) << PAGE_SHIFT; - - down_write(&mm->mmap_sem); - vdso_base = get_unmapped_area(NULL, 0, vdso_mapping_len, 0, 0); - if (IS_ERR_VALUE(vdso_base)) { - ret = vdso_base; - goto up_fail; - } - mm->context.vdso = (void *)vdso_base; - - ret = install_special_mapping(mm, vdso_base, vdso_mapping_len, - VM_READ|VM_EXEC| - VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC, - vdso_pagelist); - if (ret) { - mm->context.vdso = NULL; - goto up_fail; - } - -up_fail: - up_write(&mm->mmap_sem); - - return ret; -} - -const char *arch_vma_name(struct vm_area_struct *vma) -{ - /* - * We can re-use the vdso pointer in mm_context_t for identifying - * the vectors page for compat applications. The vDSO will always - * sit above TASK_UNMAPPED_BASE and so we don't need to worry about - * it conflicting with the vectors base. - */ - if (vma->vm_mm && vma->vm_start == (long)vma->vm_mm->context.vdso) { -#ifdef CONFIG_COMPAT - if (vma->vm_start == AARCH32_VECTORS_BASE) - return "[vectors]"; -#endif - return "[vdso]"; - } - - return NULL; -} - -/* - * We define AT_SYSINFO_EHDR, so we need these function stubs to keep - * Linux happy. - */ -int in_gate_area_no_mm(unsigned long addr) -{ - return 0; -} - -int in_gate_area(struct mm_struct *mm, unsigned long addr) -{ - return 0; -} - -struct vm_area_struct *get_gate_vma(struct mm_struct *mm) -{ - return NULL; -} - -/* - * Update the vDSO data page to keep in sync with kernel timekeeping. - */ -void update_vsyscall(struct timespec *ts, struct timespec *wtm, - struct clocksource *clock, u32 mult) -{ - struct timespec xtime_coarse; - u32 use_syscall = strcmp(clock->name, "arch_sys_counter"); - - ++vdso_data->tb_seq_count; - smp_wmb(); - - xtime_coarse = __current_kernel_time(); - vdso_data->use_syscall = use_syscall; - vdso_data->xtime_coarse_sec = xtime_coarse.tv_sec; - vdso_data->xtime_coarse_nsec = xtime_coarse.tv_nsec; - - if (!use_syscall) { - vdso_data->cs_cycle_last = clock->cycle_last; - vdso_data->xtime_clock_sec = ts->tv_sec; - vdso_data->xtime_clock_nsec = ts->tv_nsec; - vdso_data->cs_mult = mult; - vdso_data->cs_shift = clock->shift; - vdso_data->wtm_clock_sec = wtm->tv_sec; - vdso_data->wtm_clock_nsec = wtm->tv_nsec; - } - - smp_wmb(); - ++vdso_data->tb_seq_count; -} - -void update_vsyscall_tz(void) -{ - ++vdso_data->tb_seq_count; - smp_wmb(); - vdso_data->tz_minuteswest = sys_tz.tz_minuteswest; - vdso_data->tz_dsttime = sys_tz.tz_dsttime; - smp_wmb(); - ++vdso_data->tb_seq_count; -} diff --git a/trunk/arch/arm64/kernel/vdso/.gitignore b/trunk/arch/arm64/kernel/vdso/.gitignore deleted file mode 100644 index b8cc94e9698b..000000000000 --- a/trunk/arch/arm64/kernel/vdso/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -vdso.lds -vdso-offsets.h diff --git a/trunk/arch/arm64/kernel/vdso/Makefile b/trunk/arch/arm64/kernel/vdso/Makefile deleted file mode 100644 index d8064af42e62..000000000000 --- a/trunk/arch/arm64/kernel/vdso/Makefile +++ /dev/null @@ -1,63 +0,0 @@ -# -# Building a vDSO image for AArch64. -# -# Author: Will Deacon -# Heavily based on the vDSO Makefiles for other archs. -# - -obj-vdso := gettimeofday.o note.o sigreturn.o - -# Build rules -targets := $(obj-vdso) vdso.so vdso.so.dbg -obj-vdso := $(addprefix $(obj)/, $(obj-vdso)) - -ccflags-y := -shared -fno-common -fno-builtin -ccflags-y += -nostdlib -Wl,-soname=linux-vdso.so.1 \ - $(call cc-ldoption, -Wl$(comma)--hash-style=sysv) - -obj-y += vdso.o -extra-y += vdso.lds vdso-offsets.h -CPPFLAGS_vdso.lds += -P -C -U$(ARCH) - -# Force dependency (incbin is bad) -$(obj)/vdso.o : $(obj)/vdso.so - -# Link rule for the .so file, .lds has to be first -$(obj)/vdso.so.dbg: $(src)/vdso.lds $(obj-vdso) - $(call if_changed,vdsold) - -# Strip rule for the .so file -$(obj)/%.so: OBJCOPYFLAGS := -S -$(obj)/%.so: $(obj)/%.so.dbg FORCE - $(call if_changed,objcopy) - -# Generate VDSO offsets using helper script -gen-vdsosym := $(srctree)/$(src)/gen_vdso_offsets.sh -quiet_cmd_vdsosym = VDSOSYM $@ -define cmd_vdsosym - $(NM) $< | $(gen-vdsosym) | LC_ALL=C sort > $@ && \ - cp $@ include/generated/ -endef - -$(obj)/vdso-offsets.h: $(obj)/vdso.so.dbg FORCE - $(call if_changed,vdsosym) - -# Assembly rules for the .S files -$(obj-vdso): %.o: %.S - $(call if_changed_dep,vdsoas) - -# Actual build commands -quiet_cmd_vdsold = VDSOL $@ - cmd_vdsold = $(CC) $(c_flags) -Wl,-T $^ -o $@ -quiet_cmd_vdsoas = VDSOA $@ - cmd_vdsoas = $(CC) $(a_flags) -c -o $@ $< - -# Install commands for the unstripped file -quiet_cmd_vdso_install = INSTALL $@ - cmd_vdso_install = cp $(obj)/$@.dbg $(MODLIB)/vdso/$@ - -vdso.so: $(obj)/vdso.so.dbg - @mkdir -p $(MODLIB)/vdso - $(call cmd,vdso_install) - -vdso_install: vdso.so diff --git a/trunk/arch/arm64/kernel/vdso/gen_vdso_offsets.sh b/trunk/arch/arm64/kernel/vdso/gen_vdso_offsets.sh deleted file mode 100755 index 01924ff071ad..000000000000 --- a/trunk/arch/arm64/kernel/vdso/gen_vdso_offsets.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/sh - -# -# Match symbols in the DSO that look like VDSO_*; produce a header file -# of constant offsets into the shared object. -# -# Doing this inside the Makefile will break the $(filter-out) function, -# causing Kbuild to rebuild the vdso-offsets header file every time. -# -# Author: Will Deacon . - * - * Author: Will Deacon - */ - -#include -#include -#include - -#define NSEC_PER_SEC_LO16 0xca00 -#define NSEC_PER_SEC_HI16 0x3b9a - -vdso_data .req x6 -use_syscall .req w7 -seqcnt .req w8 - - .macro seqcnt_acquire -9999: ldr seqcnt, [vdso_data, #VDSO_TB_SEQ_COUNT] - tbnz seqcnt, #0, 9999b - dmb ishld - ldr use_syscall, [vdso_data, #VDSO_USE_SYSCALL] - .endm - - .macro seqcnt_read, cnt - dmb ishld - ldr \cnt, [vdso_data, #VDSO_TB_SEQ_COUNT] - .endm - - .macro seqcnt_check, cnt, fail - cmp \cnt, seqcnt - b.ne \fail - .endm - - .text - -/* int __kernel_gettimeofday(struct timeval *tv, struct timezone *tz); */ -ENTRY(__kernel_gettimeofday) - .cfi_startproc - mov x2, x30 - .cfi_register x30, x2 - - /* Acquire the sequence counter and get the timespec. */ - adr vdso_data, _vdso_data -1: seqcnt_acquire - cbnz use_syscall, 4f - - /* If tv is NULL, skip to the timezone code. */ - cbz x0, 2f - bl __do_get_tspec - seqcnt_check w13, 1b - - /* Convert ns to us. */ - mov x11, #1000 - udiv x10, x10, x11 - stp x9, x10, [x0, #TVAL_TV_SEC] -2: - /* If tz is NULL, return 0. */ - cbz x1, 3f - ldp w4, w5, [vdso_data, #VDSO_TZ_MINWEST] - seqcnt_read w13 - seqcnt_check w13, 1b - stp w4, w5, [x1, #TZ_MINWEST] -3: - mov x0, xzr - ret x2 -4: - /* Syscall fallback. */ - mov x8, #__NR_gettimeofday - svc #0 - ret x2 - .cfi_endproc -ENDPROC(__kernel_gettimeofday) - -/* int __kernel_clock_gettime(clockid_t clock_id, struct timespec *tp); */ -ENTRY(__kernel_clock_gettime) - .cfi_startproc - cmp w0, #CLOCK_REALTIME - ccmp w0, #CLOCK_MONOTONIC, #0x4, ne - b.ne 2f - - mov x2, x30 - .cfi_register x30, x2 - - /* Get kernel timespec. */ - adr vdso_data, _vdso_data -1: seqcnt_acquire - cbnz use_syscall, 7f - - bl __do_get_tspec - seqcnt_check w13, 1b - - cmp w0, #CLOCK_MONOTONIC - b.ne 6f - - /* Get wtm timespec. */ - ldp x14, x15, [vdso_data, #VDSO_WTM_CLK_SEC] - - /* Check the sequence counter. */ - seqcnt_read w13 - seqcnt_check w13, 1b - b 4f -2: - cmp w0, #CLOCK_REALTIME_COARSE - ccmp w0, #CLOCK_MONOTONIC_COARSE, #0x4, ne - b.ne 8f - - /* Get coarse timespec. */ - adr vdso_data, _vdso_data -3: seqcnt_acquire - ldp x9, x10, [vdso_data, #VDSO_XTIME_CRS_SEC] - - cmp w0, #CLOCK_MONOTONIC_COARSE - b.ne 6f - - /* Get wtm timespec. */ - ldp x14, x15, [vdso_data, #VDSO_WTM_CLK_SEC] - - /* Check the sequence counter. */ - seqcnt_read w13 - seqcnt_check w13, 3b -4: - /* Add on wtm timespec. */ - add x9, x9, x14 - add x10, x10, x15 - - /* Normalise the new timespec. */ - mov x14, #NSEC_PER_SEC_LO16 - movk x14, #NSEC_PER_SEC_HI16, lsl #16 - cmp x10, x14 - b.lt 5f - sub x10, x10, x14 - add x9, x9, #1 -5: - cmp x10, #0 - b.ge 6f - add x10, x10, x14 - sub x9, x9, #1 - -6: /* Store to the user timespec. */ - stp x9, x10, [x1, #TSPEC_TV_SEC] - mov x0, xzr - ret x2 -7: - mov x30, x2 -8: /* Syscall fallback. */ - mov x8, #__NR_clock_gettime - svc #0 - ret - .cfi_endproc -ENDPROC(__kernel_clock_gettime) - -/* int __kernel_clock_getres(clockid_t clock_id, struct timespec *res); */ -ENTRY(__kernel_clock_getres) - .cfi_startproc - cbz w1, 3f - - cmp w0, #CLOCK_REALTIME - ccmp w0, #CLOCK_MONOTONIC, #0x4, ne - b.ne 1f - - ldr x2, 5f - b 2f -1: - cmp w0, #CLOCK_REALTIME_COARSE - ccmp w0, #CLOCK_MONOTONIC_COARSE, #0x4, ne - b.ne 4f - ldr x2, 6f -2: - stp xzr, x2, [x1] - -3: /* res == NULL. */ - mov w0, wzr - ret - -4: /* Syscall fallback. */ - mov x8, #__NR_clock_getres - svc #0 - ret -5: - .quad CLOCK_REALTIME_RES -6: - .quad CLOCK_COARSE_RES - .cfi_endproc -ENDPROC(__kernel_clock_getres) - -/* - * Read the current time from the architected counter. - * Expects vdso_data to be initialised. - * Clobbers the temporary registers (x9 - x15). - * Returns: - * - (x9, x10) = (ts->tv_sec, ts->tv_nsec) - * - (x11, x12) = (xtime->tv_sec, xtime->tv_nsec) - * - w13 = vDSO sequence counter - */ -ENTRY(__do_get_tspec) - .cfi_startproc - - /* Read from the vDSO data page. */ - ldr x10, [vdso_data, #VDSO_CS_CYCLE_LAST] - ldp x11, x12, [vdso_data, #VDSO_XTIME_CLK_SEC] - ldp w14, w15, [vdso_data, #VDSO_CS_MULT] - seqcnt_read w13 - - /* Read the physical counter. */ - isb - mrs x9, cntpct_el0 - - /* Calculate cycle delta and convert to ns. */ - sub x10, x9, x10 - /* We can only guarantee 56 bits of precision. */ - movn x9, #0xff0, lsl #48 - and x10, x9, x10 - mul x10, x10, x14 - lsr x10, x10, x15 - - /* Use the kernel time to calculate the new timespec. */ - add x10, x12, x10 - mov x14, #NSEC_PER_SEC_LO16 - movk x14, #NSEC_PER_SEC_HI16, lsl #16 - udiv x15, x10, x14 - add x9, x15, x11 - mul x14, x14, x15 - sub x10, x10, x14 - - ret - .cfi_endproc -ENDPROC(__do_get_tspec) diff --git a/trunk/arch/arm64/kernel/vdso/note.S b/trunk/arch/arm64/kernel/vdso/note.S deleted file mode 100644 index b82c85e5d972..000000000000 --- a/trunk/arch/arm64/kernel/vdso/note.S +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (C) 2012 ARM Limited - * - * 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 . - * - * Author: Will Deacon - * - * This supplies .note.* sections to go into the PT_NOTE inside the vDSO text. - * Here we can supply some information useful to userland. - */ - -#include -#include -#include - -ELFNOTE_START(Linux, 0, "a") - .long LINUX_VERSION_CODE -ELFNOTE_END diff --git a/trunk/arch/arm64/kernel/vdso/sigreturn.S b/trunk/arch/arm64/kernel/vdso/sigreturn.S deleted file mode 100644 index 20d98effa7dd..000000000000 --- a/trunk/arch/arm64/kernel/vdso/sigreturn.S +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Sigreturn trampoline for returning from a signal when the SA_RESTORER - * flag is not set. - * - * Copyright (C) 2012 ARM Limited - * - * 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 . - * - * Author: Will Deacon - */ - -#include -#include - - .text - - nop -ENTRY(__kernel_rt_sigreturn) - .cfi_startproc - .cfi_signal_frame - .cfi_def_cfa x29, 0 - .cfi_offset x29, 0 * 8 - .cfi_offset x30, 1 * 8 - mov x8, #__NR_rt_sigreturn - svc #0 - .cfi_endproc -ENDPROC(__kernel_rt_sigreturn) diff --git a/trunk/arch/arm64/kernel/vdso/vdso.S b/trunk/arch/arm64/kernel/vdso/vdso.S deleted file mode 100644 index 60c1db54b41a..000000000000 --- a/trunk/arch/arm64/kernel/vdso/vdso.S +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (C) 2012 ARM Limited - * - * 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 . - * - * Author: Will Deacon - */ - -#include -#include -#include -#include - - __PAGE_ALIGNED_DATA - - .globl vdso_start, vdso_end - .balign PAGE_SIZE -vdso_start: - .incbin "arch/arm64/kernel/vdso/vdso.so" - .balign PAGE_SIZE -vdso_end: - - .previous diff --git a/trunk/arch/arm64/kernel/vdso/vdso.lds.S b/trunk/arch/arm64/kernel/vdso/vdso.lds.S deleted file mode 100644 index 8154b8d1c826..000000000000 --- a/trunk/arch/arm64/kernel/vdso/vdso.lds.S +++ /dev/null @@ -1,100 +0,0 @@ -/* - * GNU linker script for the VDSO library. -* - * Copyright (C) 2012 ARM Limited - * - * 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 . - * - * Author: Will Deacon - * Heavily based on the vDSO linker scripts for other archs. - */ - -#include -#include -#include - -OUTPUT_FORMAT("elf64-littleaarch64", "elf64-bigaarch64", "elf64-littleaarch64") -OUTPUT_ARCH(aarch64) - -SECTIONS -{ - . = VDSO_LBASE + SIZEOF_HEADERS; - - .hash : { *(.hash) } :text - .gnu.hash : { *(.gnu.hash) } - .dynsym : { *(.dynsym) } - .dynstr : { *(.dynstr) } - .gnu.version : { *(.gnu.version) } - .gnu.version_d : { *(.gnu.version_d) } - .gnu.version_r : { *(.gnu.version_r) } - - .note : { *(.note.*) } :text :note - - . = ALIGN(16); - - .text : { *(.text*) } :text =0xd503201f - PROVIDE (__etext = .); - PROVIDE (_etext = .); - PROVIDE (etext = .); - - .eh_frame_hdr : { *(.eh_frame_hdr) } :text :eh_frame_hdr - .eh_frame : { KEEP (*(.eh_frame)) } :text - - .dynamic : { *(.dynamic) } :text :dynamic - - .rodata : { *(.rodata*) } :text - - _end = .; - PROVIDE(end = .); - - . = ALIGN(PAGE_SIZE); - PROVIDE(_vdso_data = .); - - /DISCARD/ : { - *(.note.GNU-stack) - *(.data .data.* .gnu.linkonce.d.* .sdata*) - *(.bss .sbss .dynbss .dynsbss) - } -} - -/* - * We must supply the ELF program headers explicitly to get just one - * PT_LOAD segment, and set the flags explicitly to make segments read-only. - */ -PHDRS -{ - text PT_LOAD FLAGS(5) FILEHDR PHDRS; /* PF_R|PF_X */ - dynamic PT_DYNAMIC FLAGS(4); /* PF_R */ - note PT_NOTE FLAGS(4); /* PF_R */ - eh_frame_hdr PT_GNU_EH_FRAME; -} - -/* - * This controls what symbols we export from the DSO. - */ -VERSION -{ - LINUX_2.6.39 { - global: - __kernel_rt_sigreturn; - __kernel_gettimeofday; - __kernel_clock_gettime; - __kernel_clock_getres; - local: *; - }; -} - -/* - * Make the sigreturn code visible to the kernel. - */ -VDSO_sigtramp = __kernel_rt_sigreturn; diff --git a/trunk/arch/arm64/kernel/vmlinux.lds.S b/trunk/arch/arm64/kernel/vmlinux.lds.S deleted file mode 100644 index 3fae2be8b016..000000000000 --- a/trunk/arch/arm64/kernel/vmlinux.lds.S +++ /dev/null @@ -1,126 +0,0 @@ -/* - * ld script to make ARM Linux kernel - * taken from the i386 version by Russell King - * Written by Martin Mares - */ - -#include -#include -#include -#include - -#define ARM_EXIT_KEEP(x) -#define ARM_EXIT_DISCARD(x) x - -OUTPUT_ARCH(aarch64) -ENTRY(stext) - -jiffies = jiffies_64; - -SECTIONS -{ - /* - * XXX: The linker does not define how output sections are - * assigned to input sections when there are multiple statements - * matching the same input section name. There is no documented - * order of matching. - */ - /DISCARD/ : { - ARM_EXIT_DISCARD(EXIT_TEXT) - ARM_EXIT_DISCARD(EXIT_DATA) - EXIT_CALL - *(.discard) - *(.discard.*) - } - - . = PAGE_OFFSET + TEXT_OFFSET; - - .head.text : { - _text = .; - HEAD_TEXT - } - .text : { /* Real text segment */ - _stext = .; /* Text and read-only data */ - *(.smp.pen.text) - __exception_text_start = .; - *(.exception.text) - __exception_text_end = .; - IRQENTRY_TEXT - TEXT_TEXT - SCHED_TEXT - LOCK_TEXT - *(.fixup) - *(.gnu.warning) - . = ALIGN(16); - *(.got) /* Global offset table */ - } - - RO_DATA(PAGE_SIZE) - - _etext = .; /* End of text and rodata section */ - - . = ALIGN(PAGE_SIZE); - __init_begin = .; - - INIT_TEXT_SECTION(8) - .exit.text : { - ARM_EXIT_KEEP(EXIT_TEXT) - } - . = ALIGN(16); - .init.data : { - INIT_DATA - INIT_SETUP(16) - INIT_CALLS - CON_INITCALL - SECURITY_INITCALL - INIT_RAM_FS - } - .exit.data : { - ARM_EXIT_KEEP(EXIT_DATA) - } - - PERCPU_SECTION(64) - - __init_end = .; - . = ALIGN(THREAD_SIZE); - __data_loc = .; - - .data : AT(__data_loc) { - _data = .; /* address in memory */ - _sdata = .; - - /* - * first, the init task union, aligned - * to an 8192 byte boundary. - */ - INIT_TASK_DATA(THREAD_SIZE) - NOSAVE_DATA - CACHELINE_ALIGNED_DATA(64) - READ_MOSTLY_DATA(64) - - /* - * The exception fixup table (might need resorting at runtime) - */ - . = ALIGN(32); - __start___ex_table = .; - *(__ex_table) - __stop___ex_table = .; - - /* - * and the usual data section - */ - DATA_DATA - CONSTRUCTORS - - _edata = .; - } - _edata_loc = __data_loc + SIZEOF(.data); - - NOTES - - BSS_SECTION(0, 0, 0) - _end = .; - - STABS_DEBUG - .comment 0 : { *(.comment) } -} diff --git a/trunk/arch/arm64/lib/Makefile b/trunk/arch/arm64/lib/Makefile deleted file mode 100644 index 2fb7f6092aae..000000000000 --- a/trunk/arch/arm64/lib/Makefile +++ /dev/null @@ -1,4 +0,0 @@ -lib-y := bitops.o delay.o \ - strncpy_from_user.o strnlen_user.o clear_user.o \ - copy_from_user.o copy_to_user.o copy_in_user.o \ - copy_page.o clear_page.o diff --git a/trunk/arch/arm64/lib/bitops.c b/trunk/arch/arm64/lib/bitops.c deleted file mode 100644 index aa4965e60acc..000000000000 --- a/trunk/arch/arm64/lib/bitops.c +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (C) 2012 ARM Limited - * - * 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 - -#ifdef CONFIG_SMP -arch_spinlock_t __atomic_hash[ATOMIC_HASH_SIZE] __lock_aligned = { - [0 ... (ATOMIC_HASH_SIZE-1)] = __ARCH_SPIN_LOCK_UNLOCKED -}; -#endif diff --git a/trunk/arch/arm64/lib/clear_page.S b/trunk/arch/arm64/lib/clear_page.S deleted file mode 100644 index ef08e905e35b..000000000000 --- a/trunk/arch/arm64/lib/clear_page.S +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (C) 2012 ARM 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 - -/* - * Clear page @dest - * - * Parameters: - * x0 - dest - */ -ENTRY(clear_page) - mrs x1, dczid_el0 - and w1, w1, #0xf - mov x2, #4 - lsl x1, x2, x1 - -1: dc zva, x0 - add x0, x0, x1 - tst x0, #(PAGE_SIZE - 1) - b.ne 1b - ret -ENDPROC(clear_page) diff --git a/trunk/arch/arm64/lib/clear_user.S b/trunk/arch/arm64/lib/clear_user.S deleted file mode 100644 index 6e0ed93d51fe..000000000000 --- a/trunk/arch/arm64/lib/clear_user.S +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Based on arch/arm/lib/clear_user.S - * - * Copyright (C) 2012 ARM 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 - - .text - -/* Prototype: int __clear_user(void *addr, size_t sz) - * Purpose : clear some user memory - * Params : addr - user memory address to clear - * : sz - number of bytes to clear - * Returns : number of bytes NOT cleared - * - * Alignment fixed up by hardware. - */ -ENTRY(__clear_user) - mov x2, x1 // save the size for fixup return - subs x1, x1, #8 - b.mi 2f -1: -USER(9f, str xzr, [x0], #8 ) - subs x1, x1, #8 - b.pl 1b -2: adds x1, x1, #4 - b.mi 3f -USER(9f, str wzr, [x0], #4 ) - sub x1, x1, #4 -3: adds x1, x1, #2 - b.mi 4f -USER(9f, strh wzr, [x0], #2 ) - sub x1, x1, #2 -4: adds x1, x1, #1 - b.mi 5f - strb wzr, [x0] -5: mov x0, #0 - ret -ENDPROC(__clear_user) - - .section .fixup,"ax" - .align 2 -9: mov x0, x2 // return the original size - ret - .previous diff --git a/trunk/arch/arm64/lib/copy_from_user.S b/trunk/arch/arm64/lib/copy_from_user.S deleted file mode 100644 index 5e27add9d362..000000000000 --- a/trunk/arch/arm64/lib/copy_from_user.S +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (C) 2012 ARM 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 - -/* - * Copy from user space to a kernel buffer (alignment handled by the hardware) - * - * Parameters: - * x0 - to - * x1 - from - * x2 - n - * Returns: - * x0 - bytes not copied - */ -ENTRY(__copy_from_user) - add x4, x1, x2 // upper user buffer boundary - subs x2, x2, #8 - b.mi 2f -1: -USER(9f, ldr x3, [x1], #8 ) - subs x2, x2, #8 - str x3, [x0], #8 - b.pl 1b -2: adds x2, x2, #4 - b.mi 3f -USER(9f, ldr w3, [x1], #4 ) - sub x2, x2, #4 - str w3, [x0], #4 -3: adds x2, x2, #2 - b.mi 4f -USER(9f, ldrh w3, [x1], #2 ) - sub x2, x2, #2 - strh w3, [x0], #2 -4: adds x2, x2, #1 - b.mi 5f -USER(9f, ldrb w3, [x1] ) - strb w3, [x0] -5: mov x0, #0 - ret -ENDPROC(__copy_from_user) - - .section .fixup,"ax" - .align 2 -9: sub x2, x4, x1 - mov x3, x2 -10: strb wzr, [x0], #1 // zero remaining buffer space - subs x3, x3, #1 - b.ne 10b - mov x0, x2 // bytes not copied - ret - .previous diff --git a/trunk/arch/arm64/lib/copy_in_user.S b/trunk/arch/arm64/lib/copy_in_user.S deleted file mode 100644 index 84b6c9bb9b93..000000000000 --- a/trunk/arch/arm64/lib/copy_in_user.S +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copy from user space to user space - * - * Copyright (C) 2012 ARM 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 - -/* - * Copy from user space to user space (alignment handled by the hardware) - * - * Parameters: - * x0 - to - * x1 - from - * x2 - n - * Returns: - * x0 - bytes not copied - */ -ENTRY(__copy_in_user) - add x4, x0, x2 // upper user buffer boundary - subs x2, x2, #8 - b.mi 2f -1: -USER(9f, ldr x3, [x1], #8 ) - subs x2, x2, #8 -USER(9f, str x3, [x0], #8 ) - b.pl 1b -2: adds x2, x2, #4 - b.mi 3f -USER(9f, ldr w3, [x1], #4 ) - sub x2, x2, #4 -USER(9f, str w3, [x0], #4 ) -3: adds x2, x2, #2 - b.mi 4f -USER(9f, ldrh w3, [x1], #2 ) - sub x2, x2, #2 -USER(9f, strh w3, [x0], #2 ) -4: adds x2, x2, #1 - b.mi 5f -USER(9f, ldrb w3, [x1] ) -USER(9f, strb w3, [x0] ) -5: mov x0, #0 - ret -ENDPROC(__copy_in_user) - - .section .fixup,"ax" - .align 2 -9: sub x0, x4, x0 // bytes not copied - ret - .previous diff --git a/trunk/arch/arm64/lib/copy_page.S b/trunk/arch/arm64/lib/copy_page.S deleted file mode 100644 index 512b9a7b980e..000000000000 --- a/trunk/arch/arm64/lib/copy_page.S +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (C) 2012 ARM 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 - -/* - * Copy a page from src to dest (both are page aligned) - * - * Parameters: - * x0 - dest - * x1 - src - */ -ENTRY(copy_page) - /* Assume cache line size is 64 bytes. */ - prfm pldl1strm, [x1, #64] -1: ldp x2, x3, [x1] - ldp x4, x5, [x1, #16] - ldp x6, x7, [x1, #32] - ldp x8, x9, [x1, #48] - add x1, x1, #64 - prfm pldl1strm, [x1, #64] - stnp x2, x3, [x0] - stnp x4, x5, [x0, #16] - stnp x6, x7, [x0, #32] - stnp x8, x9, [x0, #48] - add x0, x0, #64 - tst x1, #(PAGE_SIZE - 1) - b.ne 1b - ret -ENDPROC(copy_page) diff --git a/trunk/arch/arm64/lib/copy_to_user.S b/trunk/arch/arm64/lib/copy_to_user.S deleted file mode 100644 index a0aeeb9b7a28..000000000000 --- a/trunk/arch/arm64/lib/copy_to_user.S +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (C) 2012 ARM 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 - -/* - * Copy to user space from a kernel buffer (alignment handled by the hardware) - * - * Parameters: - * x0 - to - * x1 - from - * x2 - n - * Returns: - * x0 - bytes not copied - */ -ENTRY(__copy_to_user) - add x4, x0, x2 // upper user buffer boundary - subs x2, x2, #8 - b.mi 2f -1: - ldr x3, [x1], #8 - subs x2, x2, #8 -USER(9f, str x3, [x0], #8 ) - b.pl 1b -2: adds x2, x2, #4 - b.mi 3f - ldr w3, [x1], #4 - sub x2, x2, #4 -USER(9f, str w3, [x0], #4 ) -3: adds x2, x2, #2 - b.mi 4f - ldrh w3, [x1], #2 - sub x2, x2, #2 -USER(9f, strh w3, [x0], #2 ) -4: adds x2, x2, #1 - b.mi 5f - ldrb w3, [x1] -USER(9f, strb w3, [x0] ) -5: mov x0, #0 - ret -ENDPROC(__copy_to_user) - - .section .fixup,"ax" - .align 2 -9: sub x0, x4, x0 // bytes not copied - ret - .previous diff --git a/trunk/arch/arm64/lib/delay.c b/trunk/arch/arm64/lib/delay.c deleted file mode 100644 index dad4ec9bbfd1..000000000000 --- a/trunk/arch/arm64/lib/delay.c +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Delay loops based on the OpenRISC implementation. - * - * Copyright (C) 2012 ARM Limited - * - * 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 . - * - * Author: Will Deacon - */ - -#include -#include -#include -#include -#include - -void __delay(unsigned long cycles) -{ - cycles_t start = get_cycles(); - - while ((get_cycles() - start) < cycles) - cpu_relax(); -} -EXPORT_SYMBOL(__delay); - -inline void __const_udelay(unsigned long xloops) -{ - unsigned long loops; - - loops = xloops * loops_per_jiffy * HZ; - __delay(loops >> 32); -} -EXPORT_SYMBOL(__const_udelay); - -void __udelay(unsigned long usecs) -{ - __const_udelay(usecs * 0x10C7UL); /* 2**32 / 1000000 (rounded up) */ -} -EXPORT_SYMBOL(__udelay); - -void __ndelay(unsigned long nsecs) -{ - __const_udelay(nsecs * 0x5UL); /* 2**32 / 1000000000 (rounded up) */ -} -EXPORT_SYMBOL(__ndelay); diff --git a/trunk/arch/arm64/lib/strncpy_from_user.S b/trunk/arch/arm64/lib/strncpy_from_user.S deleted file mode 100644 index 56e448a831a0..000000000000 --- a/trunk/arch/arm64/lib/strncpy_from_user.S +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Based on arch/arm/lib/strncpy_from_user.S - * - * Copyright (C) 1995-2000 Russell King - * Copyright (C) 2012 ARM 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 - - .text - .align 5 - -/* - * Copy a string from user space to kernel space. - * x0 = dst, x1 = src, x2 = byte length - * returns the number of characters copied (strlen of copied string), - * -EFAULT on exception, or "len" if we fill the whole buffer - */ -ENTRY(__strncpy_from_user) - mov x4, x1 -1: subs x2, x2, #1 - bmi 2f -USER(9f, ldrb w3, [x1], #1 ) - strb w3, [x0], #1 - cbnz w3, 1b - sub x1, x1, #1 // take NUL character out of count -2: sub x0, x1, x4 - ret -ENDPROC(__strncpy_from_user) - - .section .fixup,"ax" - .align 0 -9: strb wzr, [x0] // null terminate - mov x0, #-EFAULT - ret - .previous diff --git a/trunk/arch/arm64/lib/strnlen_user.S b/trunk/arch/arm64/lib/strnlen_user.S deleted file mode 100644 index 7f7b176a5646..000000000000 --- a/trunk/arch/arm64/lib/strnlen_user.S +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Based on arch/arm/lib/strnlen_user.S - * - * Copyright (C) 1995-2000 Russell King - * Copyright (C) 2012 ARM 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 - - .text - .align 5 - -/* Prototype: unsigned long __strnlen_user(const char *str, long n) - * Purpose : get length of a string in user memory - * Params : str - address of string in user memory - * Returns : length of string *including terminator* - * or zero on exception, or n if too long - */ -ENTRY(__strnlen_user) - mov x2, x0 -1: subs x1, x1, #1 - b.mi 2f -USER(9f, ldrb w3, [x0], #1 ) - cbnz w3, 1b -2: sub x0, x0, x2 - ret -ENDPROC(__strnlen_user) - - .section .fixup,"ax" - .align 0 -9: mov x0, #0 - ret - .previous diff --git a/trunk/arch/arm64/mm/Makefile b/trunk/arch/arm64/mm/Makefile deleted file mode 100644 index 3140a2abcdc2..000000000000 --- a/trunk/arch/arm64/mm/Makefile +++ /dev/null @@ -1,4 +0,0 @@ -obj-y := dma-mapping.o extable.o fault.o init.o \ - cache.o copypage.o flush.o \ - ioremap.o mmap.o pgd.o mmu.o \ - context.o tlb.o proc.o diff --git a/trunk/arch/arm64/mm/cache.S b/trunk/arch/arm64/mm/cache.S deleted file mode 100644 index abe69b80cf7f..000000000000 --- a/trunk/arch/arm64/mm/cache.S +++ /dev/null @@ -1,168 +0,0 @@ -/* - * Cache maintenance - * - * Copyright (C) 2001 Deep Blue Solutions Ltd. - * Copyright (C) 2012 ARM 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 "proc-macros.S" - -/* - * __flush_dcache_all() - * - * Flush the whole D-cache. - * - * Corrupted registers: x0-x7, x9-x11 - */ -ENTRY(__flush_dcache_all) - dsb sy // ensure ordering with previous memory accesses - mrs x0, clidr_el1 // read clidr - and x3, x0, #0x7000000 // extract loc from clidr - lsr x3, x3, #23 // left align loc bit field - cbz x3, finished // if loc is 0, then no need to clean - mov x10, #0 // start clean at cache level 0 -loop1: - add x2, x10, x10, lsr #1 // work out 3x current cache level - lsr x1, x0, x2 // extract cache type bits from clidr - and x1, x1, #7 // mask of the bits for current cache only - cmp x1, #2 // see what cache we have at this level - b.lt skip // skip if no cache, or just i-cache - save_and_disable_irqs x9 // make CSSELR and CCSIDR access atomic - msr csselr_el1, x10 // select current cache level in csselr - isb // isb to sych the new cssr&csidr - mrs x1, ccsidr_el1 // read the new ccsidr - restore_irqs x9 - and x2, x1, #7 // extract the length of the cache lines - add x2, x2, #4 // add 4 (line length offset) - mov x4, #0x3ff - and x4, x4, x1, lsr #3 // find maximum number on the way size - clz x5, x4 // find bit position of way size increment - mov x7, #0x7fff - and x7, x7, x1, lsr #13 // extract max number of the index size -loop2: - mov x9, x4 // create working copy of max way size -loop3: - lsl x6, x9, x5 - orr x11, x10, x6 // factor way and cache number into x11 - lsl x6, x7, x2 - orr x11, x11, x6 // factor index number into x11 - dc cisw, x11 // clean & invalidate by set/way - subs x9, x9, #1 // decrement the way - b.ge loop3 - subs x7, x7, #1 // decrement the index - b.ge loop2 -skip: - add x10, x10, #2 // increment cache number - cmp x3, x10 - b.gt loop1 -finished: - mov x10, #0 // swith back to cache level 0 - msr csselr_el1, x10 // select current cache level in csselr - dsb sy - isb - ret -ENDPROC(__flush_dcache_all) - -/* - * flush_cache_all() - * - * Flush the entire cache system. The data cache flush is now achieved - * using atomic clean / invalidates working outwards from L1 cache. This - * is done using Set/Way based cache maintainance instructions. The - * instruction cache can still be invalidated back to the point of - * unification in a single instruction. - */ -ENTRY(flush_cache_all) - mov x12, lr - bl __flush_dcache_all - mov x0, #0 - ic ialluis // I+BTB cache invalidate - ret x12 -ENDPROC(flush_cache_all) - -/* - * flush_icache_range(start,end) - * - * Ensure that the I and D caches are coherent within specified region. - * This is typically used when code has been written to a memory region, - * and will be executed. - * - * - start - virtual start address of region - * - end - virtual end address of region - */ -ENTRY(flush_icache_range) - /* FALLTHROUGH */ - -/* - * __flush_cache_user_range(start,end) - * - * Ensure that the I and D caches are coherent within specified region. - * This is typically used when code has been written to a memory region, - * and will be executed. - * - * - start - virtual start address of region - * - end - virtual end address of region - */ -ENTRY(__flush_cache_user_range) - dcache_line_size x2, x3 - sub x3, x2, #1 - bic x4, x0, x3 -1: -USER(9f, dc cvau, x4 ) // clean D line to PoU - add x4, x4, x2 - cmp x4, x1 - b.lo 1b - dsb sy - - icache_line_size x2, x3 - sub x3, x2, #1 - bic x4, x0, x3 -1: -USER(9f, ic ivau, x4 ) // invalidate I line PoU - add x4, x4, x2 - cmp x4, x1 - b.lo 1b -9: // ignore any faulting cache operation - dsb sy - isb - ret -ENDPROC(flush_icache_range) -ENDPROC(__flush_cache_user_range) - -/* - * __flush_kern_dcache_page(kaddr) - * - * Ensure that the data held in the page kaddr is written back to the - * page in question. - * - * - kaddr - kernel address - * - size - size in question - */ -ENTRY(__flush_dcache_area) - dcache_line_size x2, x3 - add x1, x0, x1 - sub x3, x2, #1 - bic x0, x0, x3 -1: dc civac, x0 // clean & invalidate D line / unified line - add x0, x0, x2 - cmp x0, x1 - b.lo 1b - dsb sy - ret -ENDPROC(__flush_dcache_area) diff --git a/trunk/arch/arm64/mm/context.c b/trunk/arch/arm64/mm/context.c deleted file mode 100644 index baa758d37021..000000000000 --- a/trunk/arch/arm64/mm/context.c +++ /dev/null @@ -1,159 +0,0 @@ -/* - * Based on arch/arm/mm/context.c - * - * Copyright (C) 2002-2003 Deep Blue Solutions Ltd, all rights reserved. - * Copyright (C) 2012 ARM 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 - -#include -#include -#include - -#define asid_bits(reg) \ - (((read_cpuid(ID_AA64MMFR0_EL1) & 0xf0) >> 2) + 8) - -#define ASID_FIRST_VERSION (1 << MAX_ASID_BITS) - -static DEFINE_RAW_SPINLOCK(cpu_asid_lock); -unsigned int cpu_last_asid = ASID_FIRST_VERSION; - -/* - * We fork()ed a process, and we need a new context for the child to run in. - */ -void __init_new_context(struct task_struct *tsk, struct mm_struct *mm) -{ - mm->context.id = 0; - raw_spin_lock_init(&mm->context.id_lock); -} - -static void flush_context(void) -{ - /* set the reserved TTBR0 before flushing the TLB */ - cpu_set_reserved_ttbr0(); - flush_tlb_all(); - if (icache_is_aivivt()) - __flush_icache_all(); -} - -#ifdef CONFIG_SMP - -static void set_mm_context(struct mm_struct *mm, unsigned int asid) -{ - unsigned long flags; - - /* - * Locking needed for multi-threaded applications where the same - * mm->context.id could be set from different CPUs during the - * broadcast. This function is also called via IPI so the - * mm->context.id_lock has to be IRQ-safe. - */ - raw_spin_lock_irqsave(&mm->context.id_lock, flags); - if (likely((mm->context.id ^ cpu_last_asid) >> MAX_ASID_BITS)) { - /* - * Old version of ASID found. Set the new one and reset - * mm_cpumask(mm). - */ - mm->context.id = asid; - cpumask_clear(mm_cpumask(mm)); - } - raw_spin_unlock_irqrestore(&mm->context.id_lock, flags); - - /* - * Set the mm_cpumask(mm) bit for the current CPU. - */ - cpumask_set_cpu(smp_processor_id(), mm_cpumask(mm)); -} - -/* - * Reset the ASID on the current CPU. This function call is broadcast from the - * CPU handling the ASID rollover and holding cpu_asid_lock. - */ -static void reset_context(void *info) -{ - unsigned int asid; - unsigned int cpu = smp_processor_id(); - struct mm_struct *mm = current->active_mm; - - smp_rmb(); - asid = cpu_last_asid + cpu; - - flush_context(); - set_mm_context(mm, asid); - - /* set the new ASID */ - cpu_switch_mm(mm->pgd, mm); -} - -#else - -static inline void set_mm_context(struct mm_struct *mm, unsigned int asid) -{ - mm->context.id = asid; - cpumask_copy(mm_cpumask(mm), cpumask_of(smp_processor_id())); -} - -#endif - -void __new_context(struct mm_struct *mm) -{ - unsigned int asid; - unsigned int bits = asid_bits(); - - raw_spin_lock(&cpu_asid_lock); -#ifdef CONFIG_SMP - /* - * Check the ASID again, in case the change was broadcast from another - * CPU before we acquired the lock. - */ - if (!unlikely((mm->context.id ^ cpu_last_asid) >> MAX_ASID_BITS)) { - cpumask_set_cpu(smp_processor_id(), mm_cpumask(mm)); - raw_spin_unlock(&cpu_asid_lock); - return; - } -#endif - /* - * At this point, it is guaranteed that the current mm (with an old - * ASID) isn't active on any other CPU since the ASIDs are changed - * simultaneously via IPI. - */ - asid = ++cpu_last_asid; - - /* - * If we've used up all our ASIDs, we need to start a new version and - * flush the TLB. - */ - if (unlikely((asid & ((1 << bits) - 1)) == 0)) { - /* increment the ASID version */ - cpu_last_asid += (1 << MAX_ASID_BITS) - (1 << bits); - if (cpu_last_asid == 0) - cpu_last_asid = ASID_FIRST_VERSION; - asid = cpu_last_asid + smp_processor_id(); - flush_context(); -#ifdef CONFIG_SMP - smp_wmb(); - smp_call_function(reset_context, NULL, 1); -#endif - cpu_last_asid += NR_CPUS - 1; - } - - set_mm_context(mm, asid); - raw_spin_unlock(&cpu_asid_lock); -} diff --git a/trunk/arch/arm64/mm/copypage.c b/trunk/arch/arm64/mm/copypage.c deleted file mode 100644 index 9aecbace4128..000000000000 --- a/trunk/arch/arm64/mm/copypage.c +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Based on arch/arm/mm/copypage.c - * - * Copyright (C) 2002 Deep Blue Solutions Ltd, All Rights Reserved. - * Copyright (C) 2012 ARM 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 - -void __cpu_copy_user_page(void *kto, const void *kfrom, unsigned long vaddr) -{ - copy_page(kto, kfrom); - __flush_dcache_area(kto, PAGE_SIZE); -} - -void __cpu_clear_user_page(void *kaddr, unsigned long vaddr) -{ - clear_page(kaddr); -} diff --git a/trunk/arch/arm64/mm/dma-mapping.c b/trunk/arch/arm64/mm/dma-mapping.c deleted file mode 100644 index 5eb244453a5b..000000000000 --- a/trunk/arch/arm64/mm/dma-mapping.c +++ /dev/null @@ -1,79 +0,0 @@ -/* - * SWIOTLB-based DMA API implementation - * - * Copyright (C) 2012 ARM Ltd. - * Author: Catalin Marinas - * - * 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 -#include - -#include - -struct dma_map_ops *dma_ops; -EXPORT_SYMBOL(dma_ops); - -static void *arm64_swiotlb_alloc_coherent(struct device *dev, size_t size, - dma_addr_t *dma_handle, gfp_t flags, - struct dma_attrs *attrs) -{ - if (IS_ENABLED(CONFIG_ZONE_DMA32) && - dev->coherent_dma_mask <= DMA_BIT_MASK(32)) - flags |= GFP_DMA32; - return swiotlb_alloc_coherent(dev, size, dma_handle, flags); -} - -static void arm64_swiotlb_free_coherent(struct device *dev, size_t size, - void *vaddr, dma_addr_t dma_handle, - struct dma_attrs *attrs) -{ - swiotlb_free_coherent(dev, size, vaddr, dma_handle); -} - -static struct dma_map_ops arm64_swiotlb_dma_ops = { - .alloc = arm64_swiotlb_alloc_coherent, - .free = arm64_swiotlb_free_coherent, - .map_page = swiotlb_map_page, - .unmap_page = swiotlb_unmap_page, - .map_sg = swiotlb_map_sg_attrs, - .unmap_sg = swiotlb_unmap_sg_attrs, - .sync_single_for_cpu = swiotlb_sync_single_for_cpu, - .sync_single_for_device = swiotlb_sync_single_for_device, - .sync_sg_for_cpu = swiotlb_sync_sg_for_cpu, - .sync_sg_for_device = swiotlb_sync_sg_for_device, - .dma_supported = swiotlb_dma_supported, - .mapping_error = swiotlb_dma_mapping_error, -}; - -void __init swiotlb_init_with_default_size(size_t default_size, int verbose); - -void __init arm64_swiotlb_init(size_t max_size) -{ - dma_ops = &arm64_swiotlb_dma_ops; - swiotlb_init_with_default_size(min((size_t)SZ_64M, max_size), 1); -} - -#define PREALLOC_DMA_DEBUG_ENTRIES 4096 - -static int __init dma_debug_do_init(void) -{ - dma_debug_init(PREALLOC_DMA_DEBUG_ENTRIES); - return 0; -} -fs_initcall(dma_debug_do_init); diff --git a/trunk/arch/arm64/mm/extable.c b/trunk/arch/arm64/mm/extable.c deleted file mode 100644 index 79444279ba8c..000000000000 --- a/trunk/arch/arm64/mm/extable.c +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Based on arch/arm/mm/extable.c - */ - -#include -#include - -int fixup_exception(struct pt_regs *regs) -{ - const struct exception_table_entry *fixup; - - fixup = search_exception_tables(instruction_pointer(regs)); - if (fixup) - regs->pc = fixup->fixup; - - return fixup != NULL; -} diff --git a/trunk/arch/arm64/mm/fault.c b/trunk/arch/arm64/mm/fault.c deleted file mode 100644 index 1909a69983ca..000000000000 --- a/trunk/arch/arm64/mm/fault.c +++ /dev/null @@ -1,534 +0,0 @@ -/* - * Based on arch/arm/mm/fault.c - * - * Copyright (C) 1995 Linus Torvalds - * Copyright (C) 1995-2004 Russell King - * Copyright (C) 2012 ARM 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 -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -/* - * Dump out the page tables associated with 'addr' in mm 'mm'. - */ -void show_pte(struct mm_struct *mm, unsigned long addr) -{ - pgd_t *pgd; - - if (!mm) - mm = &init_mm; - - pr_alert("pgd = %p\n", mm->pgd); - pgd = pgd_offset(mm, addr); - pr_alert("[%08lx] *pgd=%016llx", addr, pgd_val(*pgd)); - - do { - pud_t *pud; - pmd_t *pmd; - pte_t *pte; - - if (pgd_none_or_clear_bad(pgd)) - break; - - pud = pud_offset(pgd, addr); - if (pud_none_or_clear_bad(pud)) - break; - - pmd = pmd_offset(pud, addr); - printk(", *pmd=%016llx", pmd_val(*pmd)); - if (pmd_none_or_clear_bad(pmd)) - break; - - pte = pte_offset_map(pmd, addr); - printk(", *pte=%016llx", pte_val(*pte)); - pte_unmap(pte); - } while(0); - - printk("\n"); -} - -/* - * The kernel tried to access some page that wasn't present. - */ -static void __do_kernel_fault(struct mm_struct *mm, unsigned long addr, - unsigned int esr, struct pt_regs *regs) -{ - /* - * Are we prepared to handle this kernel fault? - */ - if (fixup_exception(regs)) - return; - - /* - * No handler, we'll have to terminate things with extreme prejudice. - */ - bust_spinlocks(1); - pr_alert("Unable to handle kernel %s at virtual address %08lx\n", - (addr < PAGE_SIZE) ? "NULL pointer dereference" : - "paging request", addr); - - show_pte(mm, addr); - die("Oops", regs, esr); - bust_spinlocks(0); - do_exit(SIGKILL); -} - -/* - * Something tried to access memory that isn't in our memory map. User mode - * accesses just cause a SIGSEGV - */ -static void __do_user_fault(struct task_struct *tsk, unsigned long addr, - unsigned int esr, unsigned int sig, int code, - struct pt_regs *regs) -{ - struct siginfo si; - - if (show_unhandled_signals) { - pr_info("%s[%d]: unhandled page fault (%d) at 0x%08lx, code 0x%03x\n", - tsk->comm, task_pid_nr(tsk), sig, addr, esr); - show_pte(tsk->mm, addr); - show_regs(regs); - } - - tsk->thread.fault_address = addr; - si.si_signo = sig; - si.si_errno = 0; - si.si_code = code; - si.si_addr = (void __user *)addr; - force_sig_info(sig, &si, tsk); -} - -void do_bad_area(unsigned long addr, unsigned int esr, struct pt_regs *regs) -{ - struct task_struct *tsk = current; - struct mm_struct *mm = tsk->active_mm; - - /* - * If we are in kernel mode at this point, we have no context to - * handle this fault with. - */ - if (user_mode(regs)) - __do_user_fault(tsk, addr, esr, SIGSEGV, SEGV_MAPERR, regs); - else - __do_kernel_fault(mm, addr, esr, regs); -} - -#define VM_FAULT_BADMAP 0x010000 -#define VM_FAULT_BADACCESS 0x020000 - -#define ESR_WRITE (1 << 6) -#define ESR_LNX_EXEC (1 << 24) - -/* - * Check that the permissions on the VMA allow for the fault which occurred. - * If we encountered a write fault, we must have write permission, otherwise - * we allow any permission. - */ -static inline bool access_error(unsigned int esr, struct vm_area_struct *vma) -{ - unsigned int mask = VM_READ | VM_WRITE | VM_EXEC; - - if (esr & ESR_WRITE) - mask = VM_WRITE; - if (esr & ESR_LNX_EXEC) - mask = VM_EXEC; - - return vma->vm_flags & mask ? false : true; -} - -static int __do_page_fault(struct mm_struct *mm, unsigned long addr, - unsigned int esr, unsigned int flags, - struct task_struct *tsk) -{ - struct vm_area_struct *vma; - int fault; - - vma = find_vma(mm, addr); - fault = VM_FAULT_BADMAP; - if (unlikely(!vma)) - goto out; - if (unlikely(vma->vm_start > addr)) - goto check_stack; - - /* - * Ok, we have a good vm_area for this memory access, so we can handle - * it. - */ -good_area: - if (access_error(esr, vma)) { - fault = VM_FAULT_BADACCESS; - goto out; - } - - return handle_mm_fault(mm, vma, addr & PAGE_MASK, flags); - -check_stack: - if (vma->vm_flags & VM_GROWSDOWN && !expand_stack(vma, addr)) - goto good_area; -out: - return fault; -} - -static int __kprobes do_page_fault(unsigned long addr, unsigned int esr, - struct pt_regs *regs) -{ - struct task_struct *tsk; - struct mm_struct *mm; - int fault, sig, code; - int write = esr & ESR_WRITE; - unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE | - (write ? FAULT_FLAG_WRITE : 0); - - tsk = current; - mm = tsk->mm; - - /* Enable interrupts if they were enabled in the parent context. */ - if (interrupts_enabled(regs)) - local_irq_enable(); - - /* - * If we're in an interrupt or have no user context, we must not take - * the fault. - */ - if (in_atomic() || !mm) - goto no_context; - - /* - * As per x86, we may deadlock here. However, since the kernel only - * validly references user space from well defined areas of the code, - * we can bug out early if this is from code which shouldn't. - */ - if (!down_read_trylock(&mm->mmap_sem)) { - if (!user_mode(regs) && !search_exception_tables(regs->pc)) - goto no_context; -retry: - down_read(&mm->mmap_sem); - } else { - /* - * The above down_read_trylock() might have succeeded in which - * case, we'll have missed the might_sleep() from down_read(). - */ - might_sleep(); -#ifdef CONFIG_DEBUG_VM - if (!user_mode(regs) && !search_exception_tables(regs->pc)) - goto no_context; -#endif - } - - fault = __do_page_fault(mm, addr, esr, flags, tsk); - - /* - * If we need to retry but a fatal signal is pending, handle the - * signal first. We do not need to release the mmap_sem because it - * would already be released in __lock_page_or_retry in mm/filemap.c. - */ - if ((fault & VM_FAULT_RETRY) && fatal_signal_pending(current)) - return 0; - - /* - * Major/minor page fault accounting is only done on the initial - * attempt. If we go through a retry, it is extremely likely that the - * page will be found in page cache at that point. - */ - - perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, addr); - if (flags & FAULT_FLAG_ALLOW_RETRY) { - if (fault & VM_FAULT_MAJOR) { - tsk->maj_flt++; - perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ, 1, regs, - addr); - } else { - tsk->min_flt++; - perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MIN, 1, regs, - addr); - } - if (fault & VM_FAULT_RETRY) { - /* - * Clear FAULT_FLAG_ALLOW_RETRY to avoid any risk of - * starvation. - */ - flags &= ~FAULT_FLAG_ALLOW_RETRY; - goto retry; - } - } - - up_read(&mm->mmap_sem); - - /* - * Handle the "normal" case first - VM_FAULT_MAJOR / VM_FAULT_MINOR - */ - if (likely(!(fault & (VM_FAULT_ERROR | VM_FAULT_BADMAP | - VM_FAULT_BADACCESS)))) - return 0; - - if (fault & VM_FAULT_OOM) { - /* - * We ran out of memory, call the OOM killer, and return to - * userspace (which will retry the fault, or kill us if we got - * oom-killed). - */ - pagefault_out_of_memory(); - return 0; - } - - /* - * If we are in kernel mode at this point, we have no context to - * handle this fault with. - */ - if (!user_mode(regs)) - goto no_context; - - if (fault & VM_FAULT_SIGBUS) { - /* - * We had some memory, but were unable to successfully fix up - * this page fault. - */ - sig = SIGBUS; - code = BUS_ADRERR; - } else { - /* - * Something tried to access memory that isn't in our memory - * map. - */ - sig = SIGSEGV; - code = fault == VM_FAULT_BADACCESS ? - SEGV_ACCERR : SEGV_MAPERR; - } - - __do_user_fault(tsk, addr, esr, sig, code, regs); - return 0; - -no_context: - __do_kernel_fault(mm, addr, esr, regs); - return 0; -} - -/* - * First Level Translation Fault Handler - * - * We enter here because the first level page table doesn't contain a valid - * entry for the address. - * - * If the address is in kernel space (>= TASK_SIZE), then we are probably - * faulting in the vmalloc() area. - * - * If the init_task's first level page tables contains the relevant entry, we - * copy the it to this task. If not, we send the process a signal, fixup the - * exception, or oops the kernel. - * - * NOTE! We MUST NOT take any locks for this case. We may be in an interrupt - * or a critical region, and should only copy the information from the master - * page table, nothing more. - */ -static int __kprobes do_translation_fault(unsigned long addr, - unsigned int esr, - struct pt_regs *regs) -{ - if (addr < TASK_SIZE) - return do_page_fault(addr, esr, regs); - - do_bad_area(addr, esr, regs); - return 0; -} - -/* - * Some section permission faults need to be handled gracefully. They can - * happen due to a __{get,put}_user during an oops. - */ -static int do_sect_fault(unsigned long addr, unsigned int esr, - struct pt_regs *regs) -{ - do_bad_area(addr, esr, regs); - return 0; -} - -/* - * This abort handler always returns "fault". - */ -static int do_bad(unsigned long addr, unsigned int esr, struct pt_regs *regs) -{ - return 1; -} - -static struct fault_info { - int (*fn)(unsigned long addr, unsigned int esr, struct pt_regs *regs); - int sig; - int code; - const char *name; -} fault_info[] = { - { do_bad, SIGBUS, 0, "ttbr address size fault" }, - { do_bad, SIGBUS, 0, "level 1 address size fault" }, - { do_bad, SIGBUS, 0, "level 2 address size fault" }, - { do_bad, SIGBUS, 0, "level 3 address size fault" }, - { do_translation_fault, SIGSEGV, SEGV_MAPERR, "input address range fault" }, - { do_translation_fault, SIGSEGV, SEGV_MAPERR, "level 1 translation fault" }, - { do_translation_fault, SIGSEGV, SEGV_MAPERR, "level 2 translation fault" }, - { do_page_fault, SIGSEGV, SEGV_MAPERR, "level 3 translation fault" }, - { do_bad, SIGBUS, 0, "reserved access flag fault" }, - { do_bad, SIGSEGV, SEGV_ACCERR, "level 1 access flag fault" }, - { do_bad, SIGSEGV, SEGV_ACCERR, "level 2 access flag fault" }, - { do_page_fault, SIGSEGV, SEGV_ACCERR, "level 3 access flag fault" }, - { do_bad, SIGBUS, 0, "reserved permission fault" }, - { do_bad, SIGSEGV, SEGV_ACCERR, "level 1 permission fault" }, - { do_sect_fault, SIGSEGV, SEGV_ACCERR, "level 2 permission fault" }, - { do_page_fault, SIGSEGV, SEGV_ACCERR, "level 3 permission fault" }, - { do_bad, SIGBUS, 0, "synchronous external abort" }, - { do_bad, SIGBUS, 0, "asynchronous external abort" }, - { do_bad, SIGBUS, 0, "unknown 18" }, - { do_bad, SIGBUS, 0, "unknown 19" }, - { do_bad, SIGBUS, 0, "synchronous abort (translation table walk)" }, - { do_bad, SIGBUS, 0, "synchronous abort (translation table walk)" }, - { do_bad, SIGBUS, 0, "synchronous abort (translation table walk)" }, - { do_bad, SIGBUS, 0, "synchronous abort (translation table walk)" }, - { do_bad, SIGBUS, 0, "synchronous parity error" }, - { do_bad, SIGBUS, 0, "asynchronous parity error" }, - { do_bad, SIGBUS, 0, "unknown 26" }, - { do_bad, SIGBUS, 0, "unknown 27" }, - { do_bad, SIGBUS, 0, "synchronous parity error (translation table walk" }, - { do_bad, SIGBUS, 0, "synchronous parity error (translation table walk" }, - { do_bad, SIGBUS, 0, "synchronous parity error (translation table walk" }, - { do_bad, SIGBUS, 0, "synchronous parity error (translation table walk" }, - { do_bad, SIGBUS, 0, "unknown 32" }, - { do_bad, SIGBUS, BUS_ADRALN, "alignment fault" }, - { do_bad, SIGBUS, 0, "debug event" }, - { do_bad, SIGBUS, 0, "unknown 35" }, - { do_bad, SIGBUS, 0, "unknown 36" }, - { do_bad, SIGBUS, 0, "unknown 37" }, - { do_bad, SIGBUS, 0, "unknown 38" }, - { do_bad, SIGBUS, 0, "unknown 39" }, - { do_bad, SIGBUS, 0, "unknown 40" }, - { do_bad, SIGBUS, 0, "unknown 41" }, - { do_bad, SIGBUS, 0, "unknown 42" }, - { do_bad, SIGBUS, 0, "unknown 43" }, - { do_bad, SIGBUS, 0, "unknown 44" }, - { do_bad, SIGBUS, 0, "unknown 45" }, - { do_bad, SIGBUS, 0, "unknown 46" }, - { do_bad, SIGBUS, 0, "unknown 47" }, - { do_bad, SIGBUS, 0, "unknown 48" }, - { do_bad, SIGBUS, 0, "unknown 49" }, - { do_bad, SIGBUS, 0, "unknown 50" }, - { do_bad, SIGBUS, 0, "unknown 51" }, - { do_bad, SIGBUS, 0, "implementation fault (lockdown abort)" }, - { do_bad, SIGBUS, 0, "unknown 53" }, - { do_bad, SIGBUS, 0, "unknown 54" }, - { do_bad, SIGBUS, 0, "unknown 55" }, - { do_bad, SIGBUS, 0, "unknown 56" }, - { do_bad, SIGBUS, 0, "unknown 57" }, - { do_bad, SIGBUS, 0, "implementation fault (coprocessor abort)" }, - { do_bad, SIGBUS, 0, "unknown 59" }, - { do_bad, SIGBUS, 0, "unknown 60" }, - { do_bad, SIGBUS, 0, "unknown 61" }, - { do_bad, SIGBUS, 0, "unknown 62" }, - { do_bad, SIGBUS, 0, "unknown 63" }, -}; - -/* - * Dispatch a data abort to the relevant handler. - */ -asmlinkage void __exception do_mem_abort(unsigned long addr, unsigned int esr, - struct pt_regs *regs) -{ - const struct fault_info *inf = fault_info + (esr & 63); - struct siginfo info; - - if (!inf->fn(addr, esr, regs)) - return; - - pr_alert("Unhandled fault: %s (0x%08x) at 0x%016lx\n", - inf->name, esr, addr); - - info.si_signo = inf->sig; - info.si_errno = 0; - info.si_code = inf->code; - info.si_addr = (void __user *)addr; - arm64_notify_die("", regs, &info, esr); -} - -/* - * Handle stack alignment exceptions. - */ -asmlinkage void __exception do_sp_pc_abort(unsigned long addr, - unsigned int esr, - struct pt_regs *regs) -{ - struct siginfo info; - - info.si_signo = SIGBUS; - info.si_errno = 0; - info.si_code = BUS_ADRALN; - info.si_addr = (void __user *)addr; - arm64_notify_die("", regs, &info, esr); -} - -static struct fault_info debug_fault_info[] = { - { do_bad, SIGTRAP, TRAP_HWBKPT, "hardware breakpoint" }, - { do_bad, SIGTRAP, TRAP_HWBKPT, "hardware single-step" }, - { do_bad, SIGTRAP, TRAP_HWBKPT, "hardware watchpoint" }, - { do_bad, SIGBUS, 0, "unknown 3" }, - { do_bad, SIGTRAP, TRAP_BRKPT, "aarch32 BKPT" }, - { do_bad, SIGTRAP, 0, "aarch32 vector catch" }, - { do_bad, SIGTRAP, TRAP_BRKPT, "aarch64 BRK" }, - { do_bad, SIGBUS, 0, "unknown 7" }, -}; - -void __init hook_debug_fault_code(int nr, - int (*fn)(unsigned long, unsigned int, struct pt_regs *), - int sig, int code, const char *name) -{ - BUG_ON(nr < 0 || nr >= ARRAY_SIZE(debug_fault_info)); - - debug_fault_info[nr].fn = fn; - debug_fault_info[nr].sig = sig; - debug_fault_info[nr].code = code; - debug_fault_info[nr].name = name; -} - -asmlinkage int __exception do_debug_exception(unsigned long addr, - unsigned int esr, - struct pt_regs *regs) -{ - const struct fault_info *inf = debug_fault_info + DBG_ESR_EVT(esr); - struct siginfo info; - - if (!inf->fn(addr, esr, regs)) - return 1; - - pr_alert("Unhandled debug exception: %s (0x%08x) at 0x%016lx\n", - inf->name, esr, addr); - - info.si_signo = inf->sig; - info.si_errno = 0; - info.si_code = inf->code; - info.si_addr = (void __user *)addr; - arm64_notify_die("", regs, &info, esr); - - return 0; -} diff --git a/trunk/arch/arm64/mm/flush.c b/trunk/arch/arm64/mm/flush.c deleted file mode 100644 index c144adb1682f..000000000000 --- a/trunk/arch/arm64/mm/flush.c +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Based on arch/arm/mm/flush.c - * - * Copyright (C) 1995-2002 Russell King - * Copyright (C) 2012 ARM 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 -#include - -#include "mm.h" - -void flush_cache_mm(struct mm_struct *mm) -{ -} - -void flush_cache_range(struct vm_area_struct *vma, unsigned long start, - unsigned long end) -{ - if (vma->vm_flags & VM_EXEC) - __flush_icache_all(); -} - -void flush_cache_page(struct vm_area_struct *vma, unsigned long user_addr, - unsigned long pfn) -{ -} - -static void flush_ptrace_access(struct vm_area_struct *vma, struct page *page, - unsigned long uaddr, void *kaddr, - unsigned long len) -{ - if (vma->vm_flags & VM_EXEC) { - unsigned long addr = (unsigned long)kaddr; - if (icache_is_aliasing()) { - __flush_dcache_area(kaddr, len); - __flush_icache_all(); - } else { - flush_icache_range(addr, addr + len); - } - } -} - -/* - * Copy user data from/to a page which is mapped into a different processes - * address space. Really, we want to allow our "user space" model to handle - * this. - * - * Note that this code needs to run on the current CPU. - */ -void copy_to_user_page(struct vm_area_struct *vma, struct page *page, - unsigned long uaddr, void *dst, const void *src, - unsigned long len) -{ -#ifdef CONFIG_SMP - preempt_disable(); -#endif - memcpy(dst, src, len); - flush_ptrace_access(vma, page, uaddr, dst, len); -#ifdef CONFIG_SMP - preempt_enable(); -#endif -} - -void __flush_dcache_page(struct page *page) -{ - __flush_dcache_area(page_address(page), PAGE_SIZE); -} - -void __sync_icache_dcache(pte_t pte, unsigned long addr) -{ - unsigned long pfn; - struct page *page; - - pfn = pte_pfn(pte); - if (!pfn_valid(pfn)) - return; - - page = pfn_to_page(pfn); - if (!test_and_set_bit(PG_dcache_clean, &page->flags)) { - __flush_dcache_page(page); - __flush_icache_all(); - } else if (icache_is_aivivt()) { - __flush_icache_all(); - } -} - -/* - * Ensure cache coherency between kernel mapping and userspace mapping of this - * page. - */ -void flush_dcache_page(struct page *page) -{ - struct address_space *mapping; - - /* - * The zero page is never written to, so never has any dirty cache - * lines, and therefore never needs to be flushed. - */ - if (page == ZERO_PAGE(0)) - return; - - mapping = page_mapping(page); - if (mapping && mapping_mapped(mapping)) { - __flush_dcache_page(page); - __flush_icache_all(); - set_bit(PG_dcache_clean, &page->flags); - } else { - clear_bit(PG_dcache_clean, &page->flags); - } -} -EXPORT_SYMBOL(flush_dcache_page); - -/* - * Additional functions defined in assembly. - */ -EXPORT_SYMBOL(flush_cache_all); -EXPORT_SYMBOL(flush_icache_range); diff --git a/trunk/arch/arm64/mm/init.c b/trunk/arch/arm64/mm/init.c deleted file mode 100644 index 5f719ba949bc..000000000000 --- a/trunk/arch/arm64/mm/init.c +++ /dev/null @@ -1,437 +0,0 @@ -/* - * Based on arch/arm/mm/init.c - * - * Copyright (C) 1995-2005 Russell King - * Copyright (C) 2012 ARM 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 -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "mm.h" - -static unsigned long phys_initrd_start __initdata = 0; -static unsigned long phys_initrd_size __initdata = 0; - -phys_addr_t memstart_addr __read_mostly = 0; - -void __init early_init_dt_setup_initrd_arch(unsigned long start, - unsigned long end) -{ - phys_initrd_start = start; - phys_initrd_size = end - start; -} - -static int __init early_initrd(char *p) -{ - unsigned long start, size; - char *endp; - - start = memparse(p, &endp); - if (*endp == ',') { - size = memparse(endp + 1, NULL); - - phys_initrd_start = start; - phys_initrd_size = size; - } - return 0; -} -early_param("initrd", early_initrd); - -#define MAX_DMA32_PFN ((4UL * 1024 * 1024 * 1024) >> PAGE_SHIFT) - -static void __init zone_sizes_init(unsigned long min, unsigned long max) -{ - struct memblock_region *reg; - unsigned long zone_size[MAX_NR_ZONES], zhole_size[MAX_NR_ZONES]; - unsigned long max_dma32 = min; - - memset(zone_size, 0, sizeof(zone_size)); - -#ifdef CONFIG_ZONE_DMA32 - /* 4GB maximum for 32-bit only capable devices */ - max_dma32 = min(max, MAX_DMA32_PFN); - zone_size[ZONE_DMA32] = max_dma32 - min; -#endif - zone_size[ZONE_NORMAL] = max - max_dma32; - - memcpy(zhole_size, zone_size, sizeof(zhole_size)); - - for_each_memblock(memory, reg) { - unsigned long start = memblock_region_memory_base_pfn(reg); - unsigned long end = memblock_region_memory_end_pfn(reg); - - if (start >= max) - continue; -#ifdef CONFIG_ZONE_DMA32 - if (start < max_dma32) { - unsigned long dma_end = min(end, max_dma32); - zhole_size[ZONE_DMA32] -= dma_end - start; - } -#endif - if (end > max_dma32) { - unsigned long normal_end = min(end, max); - unsigned long normal_start = max(start, max_dma32); - zhole_size[ZONE_NORMAL] -= normal_end - normal_start; - } - } - - free_area_init_node(0, zone_size, min, zhole_size); -} - -#ifdef CONFIG_HAVE_ARCH_PFN_VALID -int pfn_valid(unsigned long pfn) -{ - return memblock_is_memory(pfn << PAGE_SHIFT); -} -EXPORT_SYMBOL(pfn_valid); -#endif - -#ifndef CONFIG_SPARSEMEM -static void arm64_memory_present(void) -{ -} -#else -static void arm64_memory_present(void) -{ - struct memblock_region *reg; - - for_each_memblock(memory, reg) - memory_present(0, memblock_region_memory_base_pfn(reg), - memblock_region_memory_end_pfn(reg)); -} -#endif - -void __init arm64_memblock_init(void) -{ - u64 *reserve_map, base, size; - - /* Register the kernel text, kernel data and initrd with memblock */ - memblock_reserve(__pa(_text), _end - _text); -#ifdef CONFIG_BLK_DEV_INITRD - if (phys_initrd_size) { - memblock_reserve(phys_initrd_start, phys_initrd_size); - - /* Now convert initrd to virtual addresses */ - initrd_start = __phys_to_virt(phys_initrd_start); - initrd_end = initrd_start + phys_initrd_size; - } -#endif - - /* - * Reserve the page tables. These are already in use, - * and can only be in node 0. - */ - memblock_reserve(__pa(swapper_pg_dir), SWAPPER_DIR_SIZE); - memblock_reserve(__pa(idmap_pg_dir), IDMAP_DIR_SIZE); - - /* Reserve the dtb region */ - memblock_reserve(virt_to_phys(initial_boot_params), - be32_to_cpu(initial_boot_params->totalsize)); - - /* - * Process the reserve map. This will probably overlap the initrd - * and dtb locations which are already reserved, but overlapping - * doesn't hurt anything - */ - reserve_map = ((void*)initial_boot_params) + - be32_to_cpu(initial_boot_params->off_mem_rsvmap); - while (1) { - base = be64_to_cpup(reserve_map++); - size = be64_to_cpup(reserve_map++); - if (!size) - break; - memblock_reserve(base, size); - } - - memblock_allow_resize(); - memblock_dump_all(); -} - -void __init bootmem_init(void) -{ - unsigned long min, max; - - min = PFN_UP(memblock_start_of_DRAM()); - max = PFN_DOWN(memblock_end_of_DRAM()); - - /* - * Sparsemem tries to allocate bootmem in memory_present(), so must be - * done after the fixed reservations. - */ - arm64_memory_present(); - - sparse_init(); - zone_sizes_init(min, max); - - high_memory = __va((max << PAGE_SHIFT) - 1) + 1; - max_pfn = max_low_pfn = max; -} - -static inline int free_area(unsigned long pfn, unsigned long end, char *s) -{ - unsigned int pages = 0, size = (end - pfn) << (PAGE_SHIFT - 10); - - for (; pfn < end; pfn++) { - struct page *page = pfn_to_page(pfn); - ClearPageReserved(page); - init_page_count(page); - __free_page(page); - pages++; - } - - if (size && s) - pr_info("Freeing %s memory: %dK\n", s, size); - - return pages; -} - -/* - * Poison init memory with an undefined instruction (0x0). - */ -static inline void poison_init_mem(void *s, size_t count) -{ - memset(s, 0, count); -} - -#ifndef CONFIG_SPARSEMEM_VMEMMAP -static inline void free_memmap(unsigned long start_pfn, unsigned long end_pfn) -{ - struct page *start_pg, *end_pg; - unsigned long pg, pgend; - - /* - * Convert start_pfn/end_pfn to a struct page pointer. - */ - start_pg = pfn_to_page(start_pfn - 1) + 1; - end_pg = pfn_to_page(end_pfn - 1) + 1; - - /* - * Convert to physical addresses, and round start upwards and end - * downwards. - */ - pg = (unsigned long)PAGE_ALIGN(__pa(start_pg)); - pgend = (unsigned long)__pa(end_pg) & PAGE_MASK; - - /* - * If there are free pages between these, free the section of the - * memmap array. - */ - if (pg < pgend) - free_bootmem(pg, pgend - pg); -} - -/* - * The mem_map array can get very big. Free the unused area of the memory map. - */ -static void __init free_unused_memmap(void) -{ - unsigned long start, prev_end = 0; - struct memblock_region *reg; - - for_each_memblock(memory, reg) { - start = __phys_to_pfn(reg->base); - -#ifdef CONFIG_SPARSEMEM - /* - * Take care not to free memmap entries that don't exist due - * to SPARSEMEM sections which aren't present. - */ - start = min(start, ALIGN(prev_end, PAGES_PER_SECTION)); -#endif - /* - * If we had a previous bank, and there is a space between the - * current bank and the previous, free it. - */ - if (prev_end && prev_end < start) - free_memmap(prev_end, start); - - /* - * Align up here since the VM subsystem insists that the - * memmap entries are valid from the bank end aligned to - * MAX_ORDER_NR_PAGES. - */ - prev_end = ALIGN(start + __phys_to_pfn(reg->size), - MAX_ORDER_NR_PAGES); - } - -#ifdef CONFIG_SPARSEMEM - if (!IS_ALIGNED(prev_end, PAGES_PER_SECTION)) - free_memmap(prev_end, ALIGN(prev_end, PAGES_PER_SECTION)); -#endif -} -#endif /* !CONFIG_SPARSEMEM_VMEMMAP */ - -/* - * mem_init() marks the free areas in the mem_map and tells us how much memory - * is free. This is done after various parts of the system have claimed their - * memory after the kernel image. - */ -void __init mem_init(void) -{ - unsigned long reserved_pages, free_pages; - struct memblock_region *reg; - -#if CONFIG_SWIOTLB - extern void __init arm64_swiotlb_init(size_t max_size); - arm64_swiotlb_init(max_pfn << (PAGE_SHIFT - 1)); -#endif - - max_mapnr = pfn_to_page(max_pfn + PHYS_PFN_OFFSET) - mem_map; - -#ifndef CONFIG_SPARSEMEM_VMEMMAP - /* this will put all unused low memory onto the freelists */ - free_unused_memmap(); -#endif - - totalram_pages += free_all_bootmem(); - - reserved_pages = free_pages = 0; - - for_each_memblock(memory, reg) { - unsigned int pfn1, pfn2; - struct page *page, *end; - - pfn1 = __phys_to_pfn(reg->base); - pfn2 = pfn1 + __phys_to_pfn(reg->size); - - page = pfn_to_page(pfn1); - end = pfn_to_page(pfn2 - 1) + 1; - - do { - if (PageReserved(page)) - reserved_pages++; - else if (!page_count(page)) - free_pages++; - page++; - } while (page < end); - } - - /* - * Since our memory may not be contiguous, calculate the real number - * of pages we have in this system. - */ - pr_info("Memory:"); - num_physpages = 0; - for_each_memblock(memory, reg) { - unsigned long pages = memblock_region_memory_end_pfn(reg) - - memblock_region_memory_base_pfn(reg); - num_physpages += pages; - printk(" %ldMB", pages >> (20 - PAGE_SHIFT)); - } - printk(" = %luMB total\n", num_physpages >> (20 - PAGE_SHIFT)); - - pr_notice("Memory: %luk/%luk available, %luk reserved\n", - nr_free_pages() << (PAGE_SHIFT-10), - free_pages << (PAGE_SHIFT-10), - reserved_pages << (PAGE_SHIFT-10)); - -#define MLK(b, t) b, t, ((t) - (b)) >> 10 -#define MLM(b, t) b, t, ((t) - (b)) >> 20 -#define MLK_ROUNDUP(b, t) b, t, DIV_ROUND_UP(((t) - (b)), SZ_1K) - - pr_notice("Virtual kernel memory layout:\n" - " vmalloc : 0x%16lx - 0x%16lx (%6ld MB)\n" -#ifdef CONFIG_SPARSEMEM_VMEMMAP - " vmemmap : 0x%16lx - 0x%16lx (%6ld MB)\n" -#endif - " modules : 0x%16lx - 0x%16lx (%6ld MB)\n" - " memory : 0x%16lx - 0x%16lx (%6ld MB)\n" - " .init : 0x%p" " - 0x%p" " (%6ld kB)\n" - " .text : 0x%p" " - 0x%p" " (%6ld kB)\n" - " .data : 0x%p" " - 0x%p" " (%6ld kB)\n", - MLM(VMALLOC_START, VMALLOC_END), -#ifdef CONFIG_SPARSEMEM_VMEMMAP - MLM((unsigned long)virt_to_page(PAGE_OFFSET), - (unsigned long)virt_to_page(high_memory)), -#endif - MLM(MODULES_VADDR, MODULES_END), - MLM(PAGE_OFFSET, (unsigned long)high_memory), - - MLK_ROUNDUP(__init_begin, __init_end), - MLK_ROUNDUP(_text, _etext), - MLK_ROUNDUP(_sdata, _edata)); - -#undef MLK -#undef MLM -#undef MLK_ROUNDUP - - /* - * Check boundaries twice: Some fundamental inconsistencies can be - * detected at build time already. - */ -#ifdef CONFIG_COMPAT - BUILD_BUG_ON(TASK_SIZE_32 > TASK_SIZE_64); -#endif - BUILD_BUG_ON(TASK_SIZE_64 > MODULES_VADDR); - BUG_ON(TASK_SIZE_64 > MODULES_VADDR); - - if (PAGE_SIZE >= 16384 && num_physpages <= 128) { - extern int sysctl_overcommit_memory; - /* - * On a machine this small we won't get anywhere without - * overcommit, so turn it on by default. - */ - sysctl_overcommit_memory = OVERCOMMIT_ALWAYS; - } -} - -void free_initmem(void) -{ - poison_init_mem(__init_begin, __init_end - __init_begin); - totalram_pages += free_area(__phys_to_pfn(__pa(__init_begin)), - __phys_to_pfn(__pa(__init_end)), - "init"); -} - -#ifdef CONFIG_BLK_DEV_INITRD - -static int keep_initrd; - -void free_initrd_mem(unsigned long start, unsigned long end) -{ - if (!keep_initrd) { - poison_init_mem((void *)start, PAGE_ALIGN(end) - start); - totalram_pages += free_area(__phys_to_pfn(__pa(start)), - __phys_to_pfn(__pa(end)), - "initrd"); - } -} - -static int __init keepinitrd_setup(char *__unused) -{ - keep_initrd = 1; - return 1; -} - -__setup("keepinitrd", keepinitrd_setup); -#endif diff --git a/trunk/arch/arm64/mm/ioremap.c b/trunk/arch/arm64/mm/ioremap.c deleted file mode 100644 index 1725cd6db37a..000000000000 --- a/trunk/arch/arm64/mm/ioremap.c +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Based on arch/arm/mm/ioremap.c - * - * (C) Copyright 1995 1996 Linus Torvalds - * Hacked for ARM by Phil Blundell - * Hacked to allow all architectures to build, and various cleanups - * by Russell King - * Copyright (C) 2012 ARM 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 - -static void __iomem *__ioremap_caller(phys_addr_t phys_addr, size_t size, - pgprot_t prot, void *caller) -{ - unsigned long last_addr; - unsigned long offset = phys_addr & ~PAGE_MASK; - int err; - unsigned long addr; - struct vm_struct *area; - - /* - * Page align the mapping address and size, taking account of any - * offset. - */ - phys_addr &= PAGE_MASK; - size = PAGE_ALIGN(size + offset); - - /* - * Don't allow wraparound, zero size or outside PHYS_MASK. - */ - last_addr = phys_addr + size - 1; - if (!size || last_addr < phys_addr || (last_addr & ~PHYS_MASK)) - return NULL; - - /* - * Don't allow RAM to be mapped. - */ - if (WARN_ON(pfn_valid(__phys_to_pfn(phys_addr)))) - return NULL; - - area = get_vm_area_caller(size, VM_IOREMAP, caller); - if (!area) - return NULL; - addr = (unsigned long)area->addr; - - err = ioremap_page_range(addr, addr + size, phys_addr, prot); - if (err) { - vunmap((void *)addr); - return NULL; - } - - return (void __iomem *)(offset + addr); -} - -void __iomem *__ioremap(phys_addr_t phys_addr, size_t size, pgprot_t prot) -{ - return __ioremap_caller(phys_addr, size, prot, - __builtin_return_address(0)); -} -EXPORT_SYMBOL(__ioremap); - -void __iounmap(volatile void __iomem *io_addr) -{ - void *addr = (void *)(PAGE_MASK & (unsigned long)io_addr); - - vunmap(addr); -} -EXPORT_SYMBOL(__iounmap); diff --git a/trunk/arch/arm64/mm/mm.h b/trunk/arch/arm64/mm/mm.h deleted file mode 100644 index d8d6e7851c14..000000000000 --- a/trunk/arch/arm64/mm/mm.h +++ /dev/null @@ -1,2 +0,0 @@ -extern void __flush_dcache_page(struct page *page); -extern void __init bootmem_init(void); diff --git a/trunk/arch/arm64/mm/mmap.c b/trunk/arch/arm64/mm/mmap.c deleted file mode 100644 index 7c7be7855638..000000000000 --- a/trunk/arch/arm64/mm/mmap.c +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Based on arch/arm/mm/mmap.c - * - * Copyright (C) 2012 ARM 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 -#include -#include -#include -#include -#include - -#include - -/* - * Leave enough space between the mmap area and the stack to honour ulimit in - * the face of randomisation. - */ -#define MIN_GAP (SZ_128M + ((STACK_RND_MASK << PAGE_SHIFT) + 1)) -#define MAX_GAP (STACK_TOP/6*5) - -static int mmap_is_legacy(void) -{ - if (current->personality & ADDR_COMPAT_LAYOUT) - return 1; - - if (rlimit(RLIMIT_STACK) == RLIM_INFINITY) - return 1; - - return sysctl_legacy_va_layout; -} - -/* - * Since get_random_int() returns the same value within a 1 jiffy window, we - * will almost always get the same randomisation for the stack and mmap - * region. This will mean the relative distance between stack and mmap will be - * the same. - * - * To avoid this we can shift the randomness by 1 bit. - */ -static unsigned long mmap_rnd(void) -{ - unsigned long rnd = 0; - - if (current->flags & PF_RANDOMIZE) - rnd = (long)get_random_int() & (STACK_RND_MASK >> 1); - - return rnd << (PAGE_SHIFT + 1); -} - -static unsigned long mmap_base(void) -{ - unsigned long gap = rlimit(RLIMIT_STACK); - - if (gap < MIN_GAP) - gap = MIN_GAP; - else if (gap > MAX_GAP) - gap = MAX_GAP; - - return PAGE_ALIGN(STACK_TOP - gap - mmap_rnd()); -} - -/* - * This function, called very early during the creation of a new process VM - * image, sets up which VM layout function to use: - */ -void arch_pick_mmap_layout(struct mm_struct *mm) -{ - /* - * Fall back to the standard layout if the personality bit is set, or - * if the expected stack growth is unlimited: - */ - if (mmap_is_legacy()) { - mm->mmap_base = TASK_UNMAPPED_BASE; - mm->get_unmapped_area = arch_get_unmapped_area; - mm->unmap_area = arch_unmap_area; - } else { - mm->mmap_base = mmap_base(); - mm->get_unmapped_area = arch_get_unmapped_area_topdown; - mm->unmap_area = arch_unmap_area_topdown; - } -} -EXPORT_SYMBOL_GPL(arch_pick_mmap_layout); - - -/* - * You really shouldn't be using read() or write() on /dev/mem. This might go - * away in the future. - */ -int valid_phys_addr_range(unsigned long addr, size_t size) -{ - if (addr < PHYS_OFFSET) - return 0; - if (addr + size > __pa(high_memory - 1) + 1) - return 0; - - return 1; -} - -/* - * Do not allow /dev/mem mappings beyond the supported physical range. - */ -int valid_mmap_phys_addr_range(unsigned long pfn, size_t size) -{ - return !(((pfn << PAGE_SHIFT) + size) & ~PHYS_MASK); -} - -#ifdef CONFIG_STRICT_DEVMEM - -#include - -/* - * devmem_is_allowed() checks to see if /dev/mem access to a certain address - * is valid. The argument is a physical page number. We mimic x86 here by - * disallowing access to system RAM as well as device-exclusive MMIO regions. - * This effectively disable read()/write() on /dev/mem. - */ -int devmem_is_allowed(unsigned long pfn) -{ - if (iomem_is_exclusive(pfn << PAGE_SHIFT)) - return 0; - if (!page_is_ram(pfn)) - return 1; - return 0; -} - -#endif diff --git a/trunk/arch/arm64/mm/mmu.c b/trunk/arch/arm64/mm/mmu.c deleted file mode 100644 index a6885d896ab6..000000000000 --- a/trunk/arch/arm64/mm/mmu.c +++ /dev/null @@ -1,395 +0,0 @@ -/* - * Based on arch/arm/mm/mmu.c - * - * Copyright (C) 1995-2005 Russell King - * Copyright (C) 2012 ARM 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 -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include "mm.h" - -/* - * Empty_zero_page is a special page that is used for zero-initialized data - * and COW. - */ -struct page *empty_zero_page; -EXPORT_SYMBOL(empty_zero_page); - -pgprot_t pgprot_default; -EXPORT_SYMBOL(pgprot_default); - -static pmdval_t prot_sect_kernel; - -struct cachepolicy { - const char policy[16]; - u64 mair; - u64 tcr; -}; - -static struct cachepolicy cache_policies[] __initdata = { - { - .policy = "uncached", - .mair = 0x44, /* inner, outer non-cacheable */ - .tcr = TCR_IRGN_NC | TCR_ORGN_NC, - }, { - .policy = "writethrough", - .mair = 0xaa, /* inner, outer write-through, read-allocate */ - .tcr = TCR_IRGN_WT | TCR_ORGN_WT, - }, { - .policy = "writeback", - .mair = 0xee, /* inner, outer write-back, read-allocate */ - .tcr = TCR_IRGN_WBnWA | TCR_ORGN_WBnWA, - } -}; - -/* - * These are useful for identifying cache coherency problems by allowing the - * cache or the cache and writebuffer to be turned off. It changes the Normal - * memory caching attributes in the MAIR_EL1 register. - */ -static int __init early_cachepolicy(char *p) -{ - int i; - u64 tmp; - - for (i = 0; i < ARRAY_SIZE(cache_policies); i++) { - int len = strlen(cache_policies[i].policy); - - if (memcmp(p, cache_policies[i].policy, len) == 0) - break; - } - if (i == ARRAY_SIZE(cache_policies)) { - pr_err("ERROR: unknown or unsupported cache policy: %s\n", p); - return 0; - } - - flush_cache_all(); - - /* - * Modify MT_NORMAL attributes in MAIR_EL1. - */ - asm volatile( - " mrs %0, mair_el1\n" - " bfi %0, %1, #%2, #8\n" - " msr mair_el1, %0\n" - " isb\n" - : "=&r" (tmp) - : "r" (cache_policies[i].mair), "i" (MT_NORMAL * 8)); - - /* - * Modify TCR PTW cacheability attributes. - */ - asm volatile( - " mrs %0, tcr_el1\n" - " bic %0, %0, %2\n" - " orr %0, %0, %1\n" - " msr tcr_el1, %0\n" - " isb\n" - : "=&r" (tmp) - : "r" (cache_policies[i].tcr), "r" (TCR_IRGN_MASK | TCR_ORGN_MASK)); - - flush_cache_all(); - - return 0; -} -early_param("cachepolicy", early_cachepolicy); - -/* - * Adjust the PMD section entries according to the CPU in use. - */ -static void __init init_mem_pgprot(void) -{ - pteval_t default_pgprot; - int i; - - default_pgprot = PTE_ATTRINDX(MT_NORMAL); - prot_sect_kernel = PMD_TYPE_SECT | PMD_SECT_AF | PMD_ATTRINDX(MT_NORMAL); - -#ifdef CONFIG_SMP - /* - * Mark memory with the "shared" attribute for SMP systems - */ - default_pgprot |= PTE_SHARED; - prot_sect_kernel |= PMD_SECT_S; -#endif - - for (i = 0; i < 16; i++) { - unsigned long v = pgprot_val(protection_map[i]); - protection_map[i] = __pgprot(v | default_pgprot); - } - - pgprot_default = __pgprot(PTE_TYPE_PAGE | PTE_AF | default_pgprot); -} - -pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn, - unsigned long size, pgprot_t vma_prot) -{ - if (!pfn_valid(pfn)) - return pgprot_noncached(vma_prot); - else if (file->f_flags & O_SYNC) - return pgprot_writecombine(vma_prot); - return vma_prot; -} -EXPORT_SYMBOL(phys_mem_access_prot); - -static void __init *early_alloc(unsigned long sz) -{ - void *ptr = __va(memblock_alloc(sz, sz)); - memset(ptr, 0, sz); - return ptr; -} - -static void __init alloc_init_pte(pmd_t *pmd, unsigned long addr, - unsigned long end, unsigned long pfn) -{ - pte_t *pte; - - if (pmd_none(*pmd)) { - pte = early_alloc(PTRS_PER_PTE * sizeof(pte_t)); - __pmd_populate(pmd, __pa(pte), PMD_TYPE_TABLE); - } - BUG_ON(pmd_bad(*pmd)); - - pte = pte_offset_kernel(pmd, addr); - do { - set_pte(pte, pfn_pte(pfn, PAGE_KERNEL_EXEC)); - pfn++; - } while (pte++, addr += PAGE_SIZE, addr != end); -} - -static void __init alloc_init_pmd(pud_t *pud, unsigned long addr, - unsigned long end, phys_addr_t phys) -{ - pmd_t *pmd; - unsigned long next; - - /* - * Check for initial section mappings in the pgd/pud and remove them. - */ - if (pud_none(*pud) || pud_bad(*pud)) { - pmd = early_alloc(PTRS_PER_PMD * sizeof(pmd_t)); - pud_populate(&init_mm, pud, pmd); - } - - pmd = pmd_offset(pud, addr); - do { - next = pmd_addr_end(addr, end); - /* try section mapping first */ - if (((addr | next | phys) & ~SECTION_MASK) == 0) - set_pmd(pmd, __pmd(phys | prot_sect_kernel)); - else - alloc_init_pte(pmd, addr, next, __phys_to_pfn(phys)); - phys += next - addr; - } while (pmd++, addr = next, addr != end); -} - -static void __init alloc_init_pud(pgd_t *pgd, unsigned long addr, - unsigned long end, unsigned long phys) -{ - pud_t *pud = pud_offset(pgd, addr); - unsigned long next; - - do { - next = pud_addr_end(addr, end); - alloc_init_pmd(pud, addr, next, phys); - phys += next - addr; - } while (pud++, addr = next, addr != end); -} - -/* - * Create the page directory entries and any necessary page tables for the - * mapping specified by 'md'. - */ -static void __init create_mapping(phys_addr_t phys, unsigned long virt, - phys_addr_t size) -{ - unsigned long addr, length, end, next; - pgd_t *pgd; - - if (virt < VMALLOC_START) { - pr_warning("BUG: not creating mapping for 0x%016llx at 0x%016lx - outside kernel range\n", - phys, virt); - return; - } - - addr = virt & PAGE_MASK; - length = PAGE_ALIGN(size + (virt & ~PAGE_MASK)); - - pgd = pgd_offset_k(addr); - end = addr + length; - do { - next = pgd_addr_end(addr, end); - alloc_init_pud(pgd, addr, next, phys); - phys += next - addr; - } while (pgd++, addr = next, addr != end); -} - -static void __init map_mem(void) -{ - struct memblock_region *reg; - - /* map all the memory banks */ - for_each_memblock(memory, reg) { - phys_addr_t start = reg->base; - phys_addr_t end = start + reg->size; - - if (start >= end) - break; - - create_mapping(start, __phys_to_virt(start), end - start); - } -} - -/* - * paging_init() sets up the page tables, initialises the zone memory - * maps and sets up the zero page. - */ -void __init paging_init(void) -{ - void *zero_page; - - /* - * Maximum PGDIR_SIZE addressable via the initial direct kernel - * mapping in swapper_pg_dir. - */ - memblock_set_current_limit((PHYS_OFFSET & PGDIR_MASK) + PGDIR_SIZE); - - init_mem_pgprot(); - map_mem(); - - /* - * Finally flush the caches and tlb to ensure that we're in a - * consistent state. - */ - flush_cache_all(); - flush_tlb_all(); - - /* allocate the zero page. */ - zero_page = early_alloc(PAGE_SIZE); - - bootmem_init(); - - empty_zero_page = virt_to_page(zero_page); - __flush_dcache_page(empty_zero_page); - - /* - * TTBR0 is only used for the identity mapping at this stage. Make it - * point to zero page to avoid speculatively fetching new entries. - */ - cpu_set_reserved_ttbr0(); - flush_tlb_all(); -} - -/* - * Enable the identity mapping to allow the MMU disabling. - */ -void setup_mm_for_reboot(void) -{ - cpu_switch_mm(idmap_pg_dir, &init_mm); - flush_tlb_all(); -} - -/* - * Check whether a kernel address is valid (derived from arch/x86/). - */ -int kern_addr_valid(unsigned long addr) -{ - pgd_t *pgd; - pud_t *pud; - pmd_t *pmd; - pte_t *pte; - - if ((((long)addr) >> VA_BITS) != -1UL) - return 0; - - pgd = pgd_offset_k(addr); - if (pgd_none(*pgd)) - return 0; - - pud = pud_offset(pgd, addr); - if (pud_none(*pud)) - return 0; - - pmd = pmd_offset(pud, addr); - if (pmd_none(*pmd)) - return 0; - - pte = pte_offset_kernel(pmd, addr); - if (pte_none(*pte)) - return 0; - - return pfn_valid(pte_pfn(*pte)); -} -#ifdef CONFIG_SPARSEMEM_VMEMMAP -#ifdef CONFIG_ARM64_64K_PAGES -int __meminit vmemmap_populate(struct page *start_page, - unsigned long size, int node) -{ - return vmemmap_populate_basepages(start_page, size, node); -} -#else /* !CONFIG_ARM64_64K_PAGES */ -int __meminit vmemmap_populate(struct page *start_page, - unsigned long size, int node) -{ - unsigned long addr = (unsigned long)start_page; - unsigned long end = (unsigned long)(start_page + size); - unsigned long next; - pgd_t *pgd; - pud_t *pud; - pmd_t *pmd; - - do { - next = pmd_addr_end(addr, end); - - pgd = vmemmap_pgd_populate(addr, node); - if (!pgd) - return -ENOMEM; - - pud = vmemmap_pud_populate(pgd, addr, node); - if (!pud) - return -ENOMEM; - - pmd = pmd_offset(pud, addr); - if (pmd_none(*pmd)) { - void *p = NULL; - - p = vmemmap_alloc_block_buf(PMD_SIZE, node); - if (!p) - return -ENOMEM; - - set_pmd(pmd, __pmd(__pa(p) | prot_sect_kernel)); - } else - vmemmap_verify((pte_t *)pmd, node, addr, next); - } while (addr = next, addr != end); - - return 0; -} -#endif /* CONFIG_ARM64_64K_PAGES */ -#endif /* CONFIG_SPARSEMEM_VMEMMAP */ diff --git a/trunk/arch/arm64/mm/pgd.c b/trunk/arch/arm64/mm/pgd.c deleted file mode 100644 index 7083cdada657..000000000000 --- a/trunk/arch/arm64/mm/pgd.c +++ /dev/null @@ -1,54 +0,0 @@ -/* - * PGD allocation/freeing - * - * Copyright (C) 2012 ARM Ltd. - * Author: Catalin Marinas - * - * 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 -#include -#include - -#include "mm.h" - -#define PGD_SIZE (PTRS_PER_PGD * sizeof(pgd_t)) - -pgd_t *pgd_alloc(struct mm_struct *mm) -{ - pgd_t *new_pgd; - - if (PGD_SIZE == PAGE_SIZE) - new_pgd = (pgd_t *)get_zeroed_page(GFP_KERNEL); - else - new_pgd = kzalloc(PGD_SIZE, GFP_KERNEL); - - if (!new_pgd) - return NULL; - - return new_pgd; -} - -void pgd_free(struct mm_struct *mm, pgd_t *pgd) -{ - if (PGD_SIZE == PAGE_SIZE) - free_page((unsigned long)pgd); - else - kfree(pgd); -} diff --git a/trunk/arch/arm64/mm/proc-macros.S b/trunk/arch/arm64/mm/proc-macros.S deleted file mode 100644 index 8957b822010b..000000000000 --- a/trunk/arch/arm64/mm/proc-macros.S +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Based on arch/arm/mm/proc-macros.S - * - * Copyright (C) 2012 ARM 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 - -/* - * vma_vm_mm - get mm pointer from vma pointer (vma->vm_mm) - */ - .macro vma_vm_mm, rd, rn - ldr \rd, [\rn, #VMA_VM_MM] - .endm - -/* - * mmid - get context id from mm pointer (mm->context.id) - */ - .macro mmid, rd, rn - ldr \rd, [\rn, #MM_CONTEXT_ID] - .endm - -/* - * dcache_line_size - get the minimum D-cache line size from the CTR register. - */ - .macro dcache_line_size, reg, tmp - mrs \tmp, ctr_el0 // read CTR - lsr \tmp, \tmp, #16 - and \tmp, \tmp, #0xf // cache line size encoding - mov \reg, #4 // bytes per word - lsl \reg, \reg, \tmp // actual cache line size - .endm - -/* - * icache_line_size - get the minimum I-cache line size from the CTR register. - */ - .macro icache_line_size, reg, tmp - mrs \tmp, ctr_el0 // read CTR - and \tmp, \tmp, #0xf // cache line size encoding - mov \reg, #4 // bytes per word - lsl \reg, \reg, \tmp // actual cache line size - .endm diff --git a/trunk/arch/arm64/mm/proc.S b/trunk/arch/arm64/mm/proc.S deleted file mode 100644 index f1d8b9bbfdad..000000000000 --- a/trunk/arch/arm64/mm/proc.S +++ /dev/null @@ -1,175 +0,0 @@ -/* - * Based on arch/arm/mm/proc.S - * - * Copyright (C) 2001 Deep Blue Solutions Ltd. - * Copyright (C) 2012 ARM Ltd. - * Author: Catalin Marinas - * - * 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 -#include -#include - -#include "proc-macros.S" - -#ifndef CONFIG_SMP -/* PTWs cacheable, inner/outer WBWA not shareable */ -#define TCR_FLAGS TCR_IRGN_WBWA | TCR_ORGN_WBWA -#else -/* PTWs cacheable, inner/outer WBWA shareable */ -#define TCR_FLAGS TCR_IRGN_WBWA | TCR_ORGN_WBWA | TCR_SHARED -#endif - -#define MAIR(attr, mt) ((attr) << ((mt) * 8)) - -/* - * cpu_cache_off() - * - * Turn the CPU D-cache off. - */ -ENTRY(cpu_cache_off) - mrs x0, sctlr_el1 - bic x0, x0, #1 << 2 // clear SCTLR.C - msr sctlr_el1, x0 - isb - ret -ENDPROC(cpu_cache_off) - -/* - * cpu_reset(loc) - * - * Perform a soft reset of the system. Put the CPU into the same state - * as it would be if it had been reset, and branch to what would be the - * reset vector. It must be executed with the flat identity mapping. - * - * - loc - location to jump to for soft reset - */ - .align 5 -ENTRY(cpu_reset) - mrs x1, sctlr_el1 - bic x1, x1, #1 - msr sctlr_el1, x1 // disable the MMU - isb - ret x0 -ENDPROC(cpu_reset) - -/* - * cpu_do_idle() - * - * Idle the processor (wait for interrupt). - */ -ENTRY(cpu_do_idle) - dsb sy // WFI may enter a low-power mode - wfi - ret -ENDPROC(cpu_do_idle) - -/* - * cpu_switch_mm(pgd_phys, tsk) - * - * Set the translation table base pointer to be pgd_phys. - * - * - pgd_phys - physical address of new TTB - */ -ENTRY(cpu_do_switch_mm) - mmid w1, x1 // get mm->context.id - bfi x0, x1, #48, #16 // set the ASID - msr ttbr0_el1, x0 // set TTBR0 - isb - ret -ENDPROC(cpu_do_switch_mm) - -cpu_name: - .ascii "AArch64 Processor" - .align - - .section ".text.init", #alloc, #execinstr - -/* - * __cpu_setup - * - * Initialise the processor for turning the MMU on. Return in x0 the - * value of the SCTLR_EL1 register. - */ -ENTRY(__cpu_setup) - /* - * Preserve the link register across the function call. - */ - mov x28, lr - bl __flush_dcache_all - mov lr, x28 - ic iallu // I+BTB cache invalidate - dsb sy - - mov x0, #3 << 20 - msr cpacr_el1, x0 // Enable FP/ASIMD - mov x0, #1 - msr oslar_el1, x0 // Set the debug OS lock - tlbi vmalle1is // invalidate I + D TLBs - /* - * Memory region attributes for LPAE: - * - * n = AttrIndx[2:0] - * n MAIR - * DEVICE_nGnRnE 000 00000000 - * DEVICE_nGnRE 001 00000100 - * DEVICE_GRE 010 00001100 - * NORMAL_NC 011 01000100 - * NORMAL 100 11111111 - */ - ldr x5, =MAIR(0x00, MT_DEVICE_nGnRnE) | \ - MAIR(0x04, MT_DEVICE_nGnRE) | \ - MAIR(0x0c, MT_DEVICE_GRE) | \ - MAIR(0x44, MT_NORMAL_NC) | \ - MAIR(0xff, MT_NORMAL) - msr mair_el1, x5 - /* - * Prepare SCTLR - */ - adr x5, crval - ldp w5, w6, [x5] - mrs x0, sctlr_el1 - bic x0, x0, x5 // clear bits - orr x0, x0, x6 // set bits - /* - * Set/prepare TCR and TTBR. We use 512GB (39-bit) address range for - * both user and kernel. - */ - ldr x10, =TCR_TxSZ(VA_BITS) | TCR_FLAGS | TCR_IPS_40BIT | \ - TCR_ASID16 | (1 << 31) -#ifdef CONFIG_ARM64_64K_PAGES - orr x10, x10, TCR_TG0_64K - orr x10, x10, TCR_TG1_64K -#endif - msr tcr_el1, x10 - ret // return to head.S -ENDPROC(__cpu_setup) - - /* - * n n T - * U E WT T UD US IHBS - * CE0 XWHW CZ ME TEEA S - * .... .IEE .... NEAI TE.I ..AD DEN0 ACAM - * 0011 0... 1101 ..0. ..0. 10.. .... .... < hardware reserved - * .... .100 .... 01.1 11.1 ..01 0001 1101 < software settings - */ - .type crval, #object -crval: - .word 0x030802e2 // clear - .word 0x0405d11d // set diff --git a/trunk/arch/arm64/mm/tlb.S b/trunk/arch/arm64/mm/tlb.S deleted file mode 100644 index 8ae80a18e8ec..000000000000 --- a/trunk/arch/arm64/mm/tlb.S +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Based on arch/arm/mm/tlb.S - * - * Copyright (C) 1997-2002 Russell King - * Copyright (C) 2012 ARM Ltd. - * Written by Catalin Marinas - * - * 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 -#include "proc-macros.S" - -/* - * __cpu_flush_user_tlb_range(start, end, vma) - * - * Invalidate a range of TLB entries in the specified address space. - * - * - start - start address (may not be aligned) - * - end - end address (exclusive, may not be aligned) - * - vma - vma_struct describing address range - */ -ENTRY(__cpu_flush_user_tlb_range) - vma_vm_mm x3, x2 // get vma->vm_mm - mmid x3, x3 // get vm_mm->context.id - dsb sy - lsr x0, x0, #12 // align address - lsr x1, x1, #12 - bfi x0, x3, #48, #16 // start VA and ASID - bfi x1, x3, #48, #16 // end VA and ASID -1: tlbi vae1is, x0 // TLB invalidate by address and ASID - add x0, x0, #1 - cmp x0, x1 - b.lo 1b - dsb sy - ret -ENDPROC(__cpu_flush_user_tlb_range) - -/* - * __cpu_flush_kern_tlb_range(start,end) - * - * Invalidate a range of kernel TLB entries. - * - * - start - start address (may not be aligned) - * - end - end address (exclusive, may not be aligned) - */ -ENTRY(__cpu_flush_kern_tlb_range) - dsb sy - lsr x0, x0, #12 // align address - lsr x1, x1, #12 -1: tlbi vaae1is, x0 // TLB invalidate by address - add x0, x0, #1 - cmp x0, x1 - b.lo 1b - dsb sy - isb - ret -ENDPROC(__cpu_flush_kern_tlb_range) diff --git a/trunk/arch/blackfin/Kconfig b/trunk/arch/blackfin/Kconfig index c7092e6057c5..f34861920634 100644 --- a/trunk/arch/blackfin/Kconfig +++ b/trunk/arch/blackfin/Kconfig @@ -38,7 +38,6 @@ config BLACKFIN select GENERIC_ATOMIC64 select GENERIC_IRQ_PROBE select IRQ_PER_CPU if SMP - select USE_GENERIC_SMP_HELPERS if SMP select HAVE_NMI_WATCHDOG if NMI_WATCHDOG select GENERIC_SMP_IDLE_THREAD select ARCH_USES_GETTIMEOFFSET if !GENERIC_CLOCKEVENTS diff --git a/trunk/arch/blackfin/Makefile b/trunk/arch/blackfin/Makefile index 66cf00095b84..d3d7e64ca96d 100644 --- a/trunk/arch/blackfin/Makefile +++ b/trunk/arch/blackfin/Makefile @@ -20,6 +20,7 @@ endif KBUILD_AFLAGS += $(call cc-option,-mno-fdpic) KBUILD_CFLAGS_MODULE += -mlong-calls LDFLAGS += -m elf32bfin +KALLSYMS += --symbol-prefix=_ KBUILD_DEFCONFIG := BF537-STAMP_defconfig diff --git a/trunk/arch/blackfin/include/asm/smp.h b/trunk/arch/blackfin/include/asm/smp.h index 9631598dcc5d..dc3d144b4bb5 100644 --- a/trunk/arch/blackfin/include/asm/smp.h +++ b/trunk/arch/blackfin/include/asm/smp.h @@ -18,8 +18,6 @@ #define raw_smp_processor_id() blackfin_core_id() extern void bfin_relocate_coreb_l1_mem(void); -extern void arch_send_call_function_single_ipi(int cpu); -extern void arch_send_call_function_ipi_mask(const struct cpumask *mask); #if defined(CONFIG_SMP) && defined(CONFIG_ICACHE_FLUSH_L1) asmlinkage void blackfin_icache_flush_range_l1(unsigned long *ptr); diff --git a/trunk/arch/blackfin/kernel/setup.c b/trunk/arch/blackfin/kernel/setup.c index fb96e607adcf..ada8f0fc71e4 100644 --- a/trunk/arch/blackfin/kernel/setup.c +++ b/trunk/arch/blackfin/kernel/setup.c @@ -52,6 +52,7 @@ EXPORT_SYMBOL(reserved_mem_dcache_on); #ifdef CONFIG_MTD_UCLINUX extern struct map_info uclinux_ram_map; unsigned long memory_mtd_end, memory_mtd_start, mtd_size; +unsigned long _ebss; EXPORT_SYMBOL(memory_mtd_end); EXPORT_SYMBOL(memory_mtd_start); EXPORT_SYMBOL(mtd_size); diff --git a/trunk/arch/blackfin/mach-common/smp.c b/trunk/arch/blackfin/mach-common/smp.c index a40151306b77..00bbe672b3b3 100644 --- a/trunk/arch/blackfin/mach-common/smp.c +++ b/trunk/arch/blackfin/mach-common/smp.c @@ -48,13 +48,10 @@ unsigned long blackfin_iflush_l1_entry[NR_CPUS]; struct blackfin_initial_pda __cpuinitdata initial_pda_coreb; -enum ipi_message_type { - BFIN_IPI_TIMER, - BFIN_IPI_RESCHEDULE, - BFIN_IPI_CALL_FUNC, - BFIN_IPI_CALL_FUNC_SINGLE, - BFIN_IPI_CPU_STOP, -}; +#define BFIN_IPI_TIMER 0 +#define BFIN_IPI_RESCHEDULE 1 +#define BFIN_IPI_CALL_FUNC 2 +#define BFIN_IPI_CPU_STOP 3 struct blackfin_flush_data { unsigned long start; @@ -63,20 +60,35 @@ struct blackfin_flush_data { void *secondary_stack; + +struct smp_call_struct { + void (*func)(void *info); + void *info; + int wait; + cpumask_t *waitmask; +}; + static struct blackfin_flush_data smp_flush_data; static DEFINE_SPINLOCK(stop_lock); +struct ipi_message { + unsigned long type; + struct smp_call_struct call_struct; +}; + /* A magic number - stress test shows this is safe for common cases */ #define BFIN_IPI_MSGQ_LEN 5 /* Simple FIFO buffer, overflow leads to panic */ -struct ipi_data { +struct ipi_message_queue { + spinlock_t lock; unsigned long count; - unsigned long bits; + unsigned long head; /* head of the queue */ + struct ipi_message ipi_message[BFIN_IPI_MSGQ_LEN]; }; -static DEFINE_PER_CPU(struct ipi_data, bfin_ipi); +static DEFINE_PER_CPU(struct ipi_message_queue, ipi_msg_queue); static void ipi_cpu_stop(unsigned int cpu) { @@ -117,6 +129,28 @@ static void ipi_flush_icache(void *info) blackfin_icache_flush_range(fdata->start, fdata->end); } +static void ipi_call_function(unsigned int cpu, struct ipi_message *msg) +{ + int wait; + void (*func)(void *info); + void *info; + func = msg->call_struct.func; + info = msg->call_struct.info; + wait = msg->call_struct.wait; + func(info); + if (wait) { +#ifdef __ARCH_SYNC_CORE_DCACHE + /* + * 'wait' usually means synchronization between CPUs. + * Invalidate D cache in case shared data was changed + * by func() to ensure cache coherence. + */ + resync_core_dcache(); +#endif + cpumask_clear_cpu(cpu, msg->call_struct.waitmask); + } +} + /* Use IRQ_SUPPLE_0 to request reschedule. * When returning from interrupt to user space, * there is chance to reschedule */ @@ -138,95 +172,152 @@ void ipi_timer(void) static irqreturn_t ipi_handler_int1(int irq, void *dev_instance) { - struct ipi_data *bfin_ipi_data; + struct ipi_message *msg; + struct ipi_message_queue *msg_queue; unsigned int cpu = smp_processor_id(); - unsigned long pending; - unsigned long msg; + unsigned long flags; platform_clear_ipi(cpu, IRQ_SUPPLE_1); - bfin_ipi_data = &__get_cpu_var(bfin_ipi); - - while ((pending = xchg(&bfin_ipi_data->bits, 0)) != 0) { - msg = 0; - do { - msg = find_next_bit(&pending, BITS_PER_LONG, msg + 1); - switch (msg) { - case BFIN_IPI_TIMER: - ipi_timer(); - break; - case BFIN_IPI_RESCHEDULE: - scheduler_ipi(); - break; - case BFIN_IPI_CALL_FUNC: - generic_smp_call_function_interrupt(); - break; - - case BFIN_IPI_CALL_FUNC_SINGLE: - generic_smp_call_function_single_interrupt(); - break; - - case BFIN_IPI_CPU_STOP: - ipi_cpu_stop(cpu); - break; - } - } while (msg < BITS_PER_LONG); - - smp_mb(); + msg_queue = &__get_cpu_var(ipi_msg_queue); + + spin_lock_irqsave(&msg_queue->lock, flags); + + while (msg_queue->count) { + msg = &msg_queue->ipi_message[msg_queue->head]; + switch (msg->type) { + case BFIN_IPI_TIMER: + ipi_timer(); + break; + case BFIN_IPI_RESCHEDULE: + scheduler_ipi(); + break; + case BFIN_IPI_CALL_FUNC: + ipi_call_function(cpu, msg); + break; + case BFIN_IPI_CPU_STOP: + ipi_cpu_stop(cpu); + break; + default: + printk(KERN_CRIT "CPU%u: Unknown IPI message 0x%lx\n", + cpu, msg->type); + break; + } + msg_queue->head++; + msg_queue->head %= BFIN_IPI_MSGQ_LEN; + msg_queue->count--; } + spin_unlock_irqrestore(&msg_queue->lock, flags); return IRQ_HANDLED; } -static void bfin_ipi_init(void) +static void ipi_queue_init(void) { unsigned int cpu; - struct ipi_data *bfin_ipi_data; + struct ipi_message_queue *msg_queue; for_each_possible_cpu(cpu) { - bfin_ipi_data = &per_cpu(bfin_ipi, cpu); - bfin_ipi_data->bits = 0; - bfin_ipi_data->count = 0; + msg_queue = &per_cpu(ipi_msg_queue, cpu); + spin_lock_init(&msg_queue->lock); + msg_queue->count = 0; + msg_queue->head = 0; } } -void send_ipi(const struct cpumask *cpumask, enum ipi_message_type msg) +static inline void smp_send_message(cpumask_t callmap, unsigned long type, + void (*func) (void *info), void *info, int wait) { unsigned int cpu; - struct ipi_data *bfin_ipi_data; - unsigned long flags; - - local_irq_save(flags); - - for_each_cpu(cpu, cpumask) { - bfin_ipi_data = &per_cpu(bfin_ipi, cpu); - smp_mb(); - set_bit(msg, &bfin_ipi_data->bits); - bfin_ipi_data->count++; + struct ipi_message_queue *msg_queue; + struct ipi_message *msg; + unsigned long flags, next_msg; + cpumask_t waitmask; /* waitmask is shared by all cpus */ + + cpumask_copy(&waitmask, &callmap); + for_each_cpu(cpu, &callmap) { + msg_queue = &per_cpu(ipi_msg_queue, cpu); + spin_lock_irqsave(&msg_queue->lock, flags); + if (msg_queue->count < BFIN_IPI_MSGQ_LEN) { + next_msg = (msg_queue->head + msg_queue->count) + % BFIN_IPI_MSGQ_LEN; + msg = &msg_queue->ipi_message[next_msg]; + msg->type = type; + if (type == BFIN_IPI_CALL_FUNC) { + msg->call_struct.func = func; + msg->call_struct.info = info; + msg->call_struct.wait = wait; + msg->call_struct.waitmask = &waitmask; + } + msg_queue->count++; + } else + panic("IPI message queue overflow\n"); + spin_unlock_irqrestore(&msg_queue->lock, flags); platform_send_ipi_cpu(cpu, IRQ_SUPPLE_1); } - local_irq_restore(flags); + if (wait) { + while (!cpumask_empty(&waitmask)) + blackfin_dcache_invalidate_range( + (unsigned long)(&waitmask), + (unsigned long)(&waitmask)); +#ifdef __ARCH_SYNC_CORE_DCACHE + /* + * Invalidate D cache in case shared data was changed by + * other processors to ensure cache coherence. + */ + resync_core_dcache(); +#endif + } } -void arch_send_call_function_single_ipi(int cpu) +int smp_call_function(void (*func)(void *info), void *info, int wait) { - send_ipi(cpumask_of(cpu), BFIN_IPI_CALL_FUNC_SINGLE); + cpumask_t callmap; + + preempt_disable(); + cpumask_copy(&callmap, cpu_online_mask); + cpumask_clear_cpu(smp_processor_id(), &callmap); + if (!cpumask_empty(&callmap)) + smp_send_message(callmap, BFIN_IPI_CALL_FUNC, func, info, wait); + + preempt_enable(); + + return 0; } +EXPORT_SYMBOL_GPL(smp_call_function); -void arch_send_call_function_ipi_mask(const struct cpumask *mask) +int smp_call_function_single(int cpuid, void (*func) (void *info), void *info, + int wait) { - send_ipi(mask, BFIN_IPI_CALL_FUNC); + unsigned int cpu = cpuid; + cpumask_t callmap; + + if (cpu_is_offline(cpu)) + return 0; + cpumask_clear(&callmap); + cpumask_set_cpu(cpu, &callmap); + + smp_send_message(callmap, BFIN_IPI_CALL_FUNC, func, info, wait); + + return 0; } +EXPORT_SYMBOL_GPL(smp_call_function_single); void smp_send_reschedule(int cpu) { - send_ipi(cpumask_of(cpu), BFIN_IPI_RESCHEDULE); + cpumask_t callmap; + /* simply trigger an ipi */ + + cpumask_clear(&callmap); + cpumask_set_cpu(cpu, &callmap); + + smp_send_message(callmap, BFIN_IPI_RESCHEDULE, NULL, NULL, 0); return; } void smp_send_msg(const struct cpumask *mask, unsigned long type) { - send_ipi(mask, type); + smp_send_message(*mask, type, NULL, NULL, 0); } void smp_timer_broadcast(const struct cpumask *mask) @@ -242,7 +333,7 @@ void smp_send_stop(void) cpumask_copy(&callmap, cpu_online_mask); cpumask_clear_cpu(smp_processor_id(), &callmap); if (!cpumask_empty(&callmap)) - send_ipi(&callmap, BFIN_IPI_CPU_STOP); + smp_send_message(callmap, BFIN_IPI_CPU_STOP, NULL, NULL, 0); preempt_enable(); @@ -345,7 +436,7 @@ void __init smp_prepare_boot_cpu(void) void __init smp_prepare_cpus(unsigned int max_cpus) { platform_prepare_cpus(max_cpus); - bfin_ipi_init(); + ipi_queue_init(); platform_request_ipi(IRQ_SUPPLE_0, ipi_handler_int0); platform_request_ipi(IRQ_SUPPLE_1, ipi_handler_int1); } diff --git a/trunk/arch/c6x/Kconfig b/trunk/arch/c6x/Kconfig index 983c859e40b7..052f81a76239 100644 --- a/trunk/arch/c6x/Kconfig +++ b/trunk/arch/c6x/Kconfig @@ -6,7 +6,6 @@ config C6X def_bool y select CLKDEV_LOOKUP - select GENERIC_ATOMIC64 select GENERIC_IRQ_SHOW select HAVE_ARCH_TRACEHOOK select HAVE_DMA_API_DEBUG diff --git a/trunk/arch/c6x/include/asm/Kbuild b/trunk/arch/c6x/include/asm/Kbuild index f08e89183cda..3af601e31e66 100644 --- a/trunk/arch/c6x/include/asm/Kbuild +++ b/trunk/arch/c6x/include/asm/Kbuild @@ -2,7 +2,6 @@ include include/asm-generic/Kbuild.asm generic-y += atomic.h generic-y += auxvec.h -generic-y += barrier.h generic-y += bitsperlong.h generic-y += bugs.h generic-y += cputime.h diff --git a/trunk/arch/c6x/include/asm/barrier.h b/trunk/arch/c6x/include/asm/barrier.h new file mode 100644 index 000000000000..538240e85909 --- /dev/null +++ b/trunk/arch/c6x/include/asm/barrier.h @@ -0,0 +1,27 @@ +/* + * Port on Texas Instruments TMS320C6x architecture + * + * Copyright (C) 2004, 2009, 2010, 2011 Texas Instruments Incorporated + * Author: Aurelien Jacquiot (aurelien.jacquiot@jaluna.com) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#ifndef _ASM_C6X_BARRIER_H +#define _ASM_C6X_BARRIER_H + +#define nop() asm("NOP\n"); + +#define mb() barrier() +#define rmb() barrier() +#define wmb() barrier() +#define set_mb(var, value) do { var = value; mb(); } while (0) +#define set_wmb(var, value) do { var = value; wmb(); } while (0) + +#define smp_mb() barrier() +#define smp_rmb() barrier() +#define smp_wmb() barrier() +#define smp_read_barrier_depends() do { } while (0) + +#endif /* _ASM_C6X_BARRIER_H */ diff --git a/trunk/arch/c6x/include/asm/cache.h b/trunk/arch/c6x/include/asm/cache.h index 09c5a0f5f4d1..6d521d96d941 100644 --- a/trunk/arch/c6x/include/asm/cache.h +++ b/trunk/arch/c6x/include/asm/cache.h @@ -1,7 +1,7 @@ /* * Port on Texas Instruments TMS320C6x architecture * - * Copyright (C) 2005, 2006, 2009, 2010, 2012 Texas Instruments Incorporated + * Copyright (C) 2005, 2006, 2009, 2010 Texas Instruments Incorporated * Author: Aurelien Jacquiot (aurelien.jacquiot@jaluna.com) * * This program is free software; you can redistribute it and/or modify @@ -16,14 +16,9 @@ /* * Cache line size */ -#define L1D_CACHE_SHIFT 6 -#define L1D_CACHE_BYTES (1 << L1D_CACHE_SHIFT) - -#define L1P_CACHE_SHIFT 5 -#define L1P_CACHE_BYTES (1 << L1P_CACHE_SHIFT) - -#define L2_CACHE_SHIFT 7 -#define L2_CACHE_BYTES (1 << L2_CACHE_SHIFT) +#define L1D_CACHE_BYTES 64 +#define L1P_CACHE_BYTES 32 +#define L2_CACHE_BYTES 128 /* * L2 used as cache @@ -34,8 +29,7 @@ * For practical reasons the L1_CACHE_BYTES defines should not be smaller than * the L2 line size */ -#define L1_CACHE_SHIFT L2_CACHE_SHIFT -#define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT) +#define L1_CACHE_BYTES L2_CACHE_BYTES #define L2_CACHE_ALIGN_LOW(x) \ (((x) & ~(L2_CACHE_BYTES - 1))) diff --git a/trunk/arch/cris/kernel/process.c b/trunk/arch/cris/kernel/process.c index 7f65be6f7f17..66fd01728790 100644 --- a/trunk/arch/cris/kernel/process.c +++ b/trunk/arch/cris/kernel/process.c @@ -25,7 +25,6 @@ #include #include #include -#include //#define DEBUG @@ -75,7 +74,6 @@ void cpu_idle (void) { /* endless idle loop with no priority at all */ while (1) { - rcu_idle_enter(); while (!need_resched()) { void (*idle)(void); /* @@ -88,7 +86,6 @@ void cpu_idle (void) idle = default_idle; idle(); } - rcu_idle_exit(); schedule_preempt_disabled(); } } diff --git a/trunk/arch/frv/kernel/process.c b/trunk/arch/frv/kernel/process.c index 2eb7fa5bf9d8..ff95f50efea5 100644 --- a/trunk/arch/frv/kernel/process.c +++ b/trunk/arch/frv/kernel/process.c @@ -25,7 +25,6 @@ #include #include #include -#include #include #include @@ -70,14 +69,12 @@ void cpu_idle(void) { /* endless idle loop with no priority at all */ while (1) { - rcu_idle_enter(); while (!need_resched()) { check_pgt_cache(); if (!frv_dma_inprogress && idle) idle(); } - rcu_idle_exit(); schedule_preempt_disabled(); } diff --git a/trunk/arch/frv/mb93090-mb00/pci-vdk.c b/trunk/arch/frv/mb93090-mb00/pci-vdk.c index 71e9bcf58105..d04ed14bbf0c 100644 --- a/trunk/arch/frv/mb93090-mb00/pci-vdk.c +++ b/trunk/arch/frv/mb93090-mb00/pci-vdk.c @@ -330,8 +330,10 @@ void __init pcibios_fixup_bus(struct pci_bus *bus) pci_read_bridge_bases(bus); if (bus->number == 0) { + struct list_head *ln; struct pci_dev *dev; - list_for_each_entry(dev, &bus->devices, bus_list) { + for (ln=bus->devices.next; ln != &bus->devices; ln=ln->next) { + dev = pci_dev_b(ln); if (dev->devfn == 0) { dev->resource[0].start = 0; dev->resource[0].end = 0; diff --git a/trunk/arch/h8300/kernel/process.c b/trunk/arch/h8300/kernel/process.c index f153ed1a4c08..0e9c315be104 100644 --- a/trunk/arch/h8300/kernel/process.c +++ b/trunk/arch/h8300/kernel/process.c @@ -36,7 +36,6 @@ #include #include #include -#include #include #include @@ -79,10 +78,8 @@ void (*idle)(void) = default_idle; void cpu_idle(void) { while (1) { - rcu_idle_enter(); while (!need_resched()) idle(); - rcu_idle_exit(); schedule_preempt_disabled(); } } diff --git a/trunk/arch/ia64/Kconfig b/trunk/arch/ia64/Kconfig index 3c720ef6c32d..310cf5781fad 100644 --- a/trunk/arch/ia64/Kconfig +++ b/trunk/arch/ia64/Kconfig @@ -25,7 +25,6 @@ config IA64 select HAVE_GENERIC_HARDIRQS select HAVE_MEMBLOCK select HAVE_MEMBLOCK_NODE_MAP - select HAVE_VIRT_CPU_ACCOUNTING select ARCH_DISCARD_MEMBLOCK select GENERIC_IRQ_PROBE select GENERIC_PENDING_IRQ if SMP @@ -341,6 +340,17 @@ config FORCE_MAX_ZONEORDER default "17" if HUGETLB_PAGE default "11" +config VIRT_CPU_ACCOUNTING + bool "Deterministic task and CPU time accounting" + default n + help + Select this option to enable more accurate task and CPU time + accounting. This is done by reading a CPU counter on each + kernel entry and exit and on transitions within the kernel + between system, softirq and hardirq state, so there is a + small performance impact. + If in doubt, say N here. + config SMP bool "Symmetric multi-processing support" select USE_GENERIC_SMP_HELPERS diff --git a/trunk/arch/ia64/configs/generic_defconfig b/trunk/arch/ia64/configs/generic_defconfig index 7913695b2fcb..954d81e2e837 100644 --- a/trunk/arch/ia64/configs/generic_defconfig +++ b/trunk/arch/ia64/configs/generic_defconfig @@ -234,4 +234,5 @@ CONFIG_CRYPTO_PCBC=m CONFIG_CRYPTO_MD5=y # CONFIG_CRYPTO_ANSI_CPRNG is not set CONFIG_CRC_T10DIF=y +CONFIG_MISC_DEVICES=y CONFIG_INTEL_IOMMU=y diff --git a/trunk/arch/ia64/configs/gensparse_defconfig b/trunk/arch/ia64/configs/gensparse_defconfig index f8e913365423..91c41ecfa6d9 100644 --- a/trunk/arch/ia64/configs/gensparse_defconfig +++ b/trunk/arch/ia64/configs/gensparse_defconfig @@ -209,3 +209,4 @@ CONFIG_MAGIC_SYSRQ=y CONFIG_DEBUG_KERNEL=y CONFIG_DEBUG_MUTEXES=y CONFIG_CRYPTO_MD5=y +CONFIG_MISC_DEVICES=y diff --git a/trunk/arch/ia64/hp/sim/simserial.c b/trunk/arch/ia64/hp/sim/simserial.c index ec536e4e36c9..c34785dca92b 100644 --- a/trunk/arch/ia64/hp/sim/simserial.c +++ b/trunk/arch/ia64/hp/sim/simserial.c @@ -338,7 +338,7 @@ static void rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios) { /* Handle turning off CRTSCTS */ if ((old_termios->c_cflag & CRTSCTS) && - !(tty->termios.c_cflag & CRTSCTS)) { + !(tty->termios->c_cflag & CRTSCTS)) { tty->hw_stopped = 0; } } @@ -545,7 +545,6 @@ static int __init simrs_init(void) /* the port is imaginary */ printk(KERN_INFO "ttyS0 at 0x03f8 (irq = %d) is a 16550\n", state->irq); - tty_port_link_device(&state->port, hp_simserial_driver, 0); retval = tty_register_driver(hp_simserial_driver); if (retval) { printk(KERN_ERR "Couldn't register simserial driver\n"); diff --git a/trunk/arch/ia64/include/asm/switch_to.h b/trunk/arch/ia64/include/asm/switch_to.h index d38c7ea5eea5..cb2412fcd17f 100644 --- a/trunk/arch/ia64/include/asm/switch_to.h +++ b/trunk/arch/ia64/include/asm/switch_to.h @@ -30,6 +30,13 @@ extern struct task_struct *ia64_switch_to (void *next_task); extern void ia64_save_extra (struct task_struct *task); extern void ia64_load_extra (struct task_struct *task); +#ifdef CONFIG_VIRT_CPU_ACCOUNTING +extern void ia64_account_on_switch (struct task_struct *prev, struct task_struct *next); +# define IA64_ACCOUNT_ON_SWITCH(p,n) ia64_account_on_switch(p,n) +#else +# define IA64_ACCOUNT_ON_SWITCH(p,n) +#endif + #ifdef CONFIG_PERFMON DECLARE_PER_CPU(unsigned long, pfm_syst_info); # define PERFMON_IS_SYSWIDE() (__get_cpu_var(pfm_syst_info) & 0x1) @@ -42,6 +49,7 @@ extern void ia64_load_extra (struct task_struct *task); || PERFMON_IS_SYSWIDE()) #define __switch_to(prev,next,last) do { \ + IA64_ACCOUNT_ON_SWITCH(prev, next); \ if (IA64_HAS_EXTRA_STATE(prev)) \ ia64_save_extra(prev); \ if (IA64_HAS_EXTRA_STATE(next)) \ diff --git a/trunk/arch/ia64/kernel/acpi.c b/trunk/arch/ia64/kernel/acpi.c index 440578850ae5..6f38b6120d96 100644 --- a/trunk/arch/ia64/kernel/acpi.c +++ b/trunk/arch/ia64/kernel/acpi.c @@ -497,7 +497,7 @@ acpi_numa_processor_affinity_init(struct acpi_srat_cpu_affinity *pa) srat_num_cpus++; } -int __init +void __init acpi_numa_memory_affinity_init(struct acpi_srat_mem_affinity *ma) { unsigned long paddr, size; @@ -512,7 +512,7 @@ acpi_numa_memory_affinity_init(struct acpi_srat_mem_affinity *ma) /* Ignore disabled entries */ if (!(ma->flags & ACPI_SRAT_MEM_ENABLED)) - return -1; + return; /* record this node in proximity bitmap */ pxm_bit_set(pxm); @@ -531,7 +531,6 @@ acpi_numa_memory_affinity_init(struct acpi_srat_mem_affinity *ma) p->size = size; p->nid = pxm; num_node_memblks++; - return 0; } void __init acpi_numa_arch_fixup(void) diff --git a/trunk/arch/ia64/kernel/process.c b/trunk/arch/ia64/kernel/process.c index 3e316ec0b835..dd6fc1449741 100644 --- a/trunk/arch/ia64/kernel/process.c +++ b/trunk/arch/ia64/kernel/process.c @@ -29,7 +29,6 @@ #include #include #include -#include #include #include @@ -280,7 +279,6 @@ cpu_idle (void) /* endless idle loop with no priority at all */ while (1) { - rcu_idle_enter(); if (can_do_pal_halt) { current_thread_info()->status &= ~TS_POLLING; /* @@ -311,7 +309,6 @@ cpu_idle (void) normal_xtp(); #endif } - rcu_idle_exit(); schedule_preempt_disabled(); check_pgt_cache(); if (cpu_is_offline(cpu)) diff --git a/trunk/arch/ia64/kernel/time.c b/trunk/arch/ia64/kernel/time.c index 80ff9acc5edf..ecc904b33c5f 100644 --- a/trunk/arch/ia64/kernel/time.c +++ b/trunk/arch/ia64/kernel/time.c @@ -83,36 +83,32 @@ static struct clocksource *itc_clocksource; extern cputime_t cycle_to_cputime(u64 cyc); -static void vtime_account_user(struct task_struct *tsk) -{ - cputime_t delta_utime; - struct thread_info *ti = task_thread_info(tsk); - - if (ti->ac_utime) { - delta_utime = cycle_to_cputime(ti->ac_utime); - account_user_time(tsk, delta_utime, delta_utime); - ti->ac_utime = 0; - } -} - /* * Called from the context switch with interrupts disabled, to charge all * accumulated times to the current process, and to prepare accounting on * the next process. */ -void vtime_task_switch(struct task_struct *prev) +void ia64_account_on_switch(struct task_struct *prev, struct task_struct *next) { struct thread_info *pi = task_thread_info(prev); - struct thread_info *ni = task_thread_info(current); + struct thread_info *ni = task_thread_info(next); + cputime_t delta_stime, delta_utime; + __u64 now; + now = ia64_get_itc(); + + delta_stime = cycle_to_cputime(pi->ac_stime + (now - pi->ac_stamp)); if (idle_task(smp_processor_id()) != prev) - vtime_account_system(prev); + account_system_time(prev, 0, delta_stime, delta_stime); else - vtime_account_idle(prev); + account_idle_time(delta_stime); - vtime_account_user(prev); + if (pi->ac_utime) { + delta_utime = cycle_to_cputime(pi->ac_utime); + account_user_time(prev, delta_utime, delta_utime); + } - pi->ac_stamp = ni->ac_stamp; + pi->ac_stamp = ni->ac_stamp = now; ni->ac_stime = ni->ac_utime = 0; } @@ -120,32 +116,29 @@ void vtime_task_switch(struct task_struct *prev) * Account time for a transition between system, hard irq or soft irq state. * Note that this function is called with interrupts enabled. */ -static cputime_t vtime_delta(struct task_struct *tsk) +void account_system_vtime(struct task_struct *tsk) { struct thread_info *ti = task_thread_info(tsk); + unsigned long flags; cputime_t delta_stime; __u64 now; + local_irq_save(flags); + now = ia64_get_itc(); delta_stime = cycle_to_cputime(ti->ac_stime + (now - ti->ac_stamp)); + if (irq_count() || idle_task(smp_processor_id()) != tsk) + account_system_time(tsk, 0, delta_stime, delta_stime); + else + account_idle_time(delta_stime); ti->ac_stime = 0; - ti->ac_stamp = now; - - return delta_stime; -} -void vtime_account_system(struct task_struct *tsk) -{ - cputime_t delta = vtime_delta(tsk); + ti->ac_stamp = now; - account_system_time(tsk, 0, delta, delta); -} - -void vtime_account_idle(struct task_struct *tsk) -{ - account_idle_time(vtime_delta(tsk)); + local_irq_restore(flags); } +EXPORT_SYMBOL_GPL(account_system_vtime); /* * Called from the timer interrupt handler to charge accumulated user time @@ -153,7 +146,14 @@ void vtime_account_idle(struct task_struct *tsk) */ void account_process_tick(struct task_struct *p, int user_tick) { - vtime_account_user(p); + struct thread_info *ti = task_thread_info(p); + cputime_t delta_utime; + + if (ti->ac_utime) { + delta_utime = cycle_to_cputime(ti->ac_utime); + account_user_time(p, delta_utime, delta_utime); + ti->ac_utime = 0; + } } #endif /* CONFIG_VIRT_CPU_ACCOUNTING */ diff --git a/trunk/arch/ia64/pci/pci.c b/trunk/arch/ia64/pci/pci.c index 5faa66c5c2a8..81acc7a57f3e 100644 --- a/trunk/arch/ia64/pci/pci.c +++ b/trunk/arch/ia64/pci/pci.c @@ -295,6 +295,7 @@ static __devinit acpi_status add_window(struct acpi_resource *res, void *data) window->resource.flags = flags; window->resource.start = addr.minimum + offset; window->resource.end = window->resource.start + addr.address_length - 1; + window->resource.child = NULL; window->offset = offset; if (insert_resource(root, &window->resource)) { @@ -356,7 +357,7 @@ pci_acpi_scan_root(struct acpi_pci_root *root) &windows); if (windows) { controller->window = - kzalloc_node(sizeof(*controller->window) * windows, + kmalloc_node(sizeof(*controller->window) * windows, GFP_KERNEL, controller->node); if (!controller->window) goto out2; @@ -460,6 +461,14 @@ void pcibios_set_master (struct pci_dev *dev) /* No special bus mastering setup handling */ } +void __devinit +pcibios_update_irq (struct pci_dev *dev, int irq) +{ + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq); + + /* ??? FIXME -- record old value for shutdown. */ +} + int pcibios_enable_device (struct pci_dev *dev, int mask) { diff --git a/trunk/arch/ia64/sn/kernel/io_common.c b/trunk/arch/ia64/sn/kernel/io_common.c index 8630875e74b5..fbb5f2f87eed 100644 --- a/trunk/arch/ia64/sn/kernel/io_common.c +++ b/trunk/arch/ia64/sn/kernel/io_common.c @@ -229,6 +229,7 @@ void sn_pci_fixup_slot(struct pci_dev *dev, struct pcidev_info *pcidev_info, { int segment = pci_domain_nr(dev->bus); struct pcibus_bussoft *bs; + struct pci_bus *host_pci_bus; struct pci_dev *host_pci_dev; unsigned int bus_no, devfn; @@ -244,7 +245,8 @@ void sn_pci_fixup_slot(struct pci_dev *dev, struct pcidev_info *pcidev_info, bus_no = (pcidev_info->pdi_slot_host_handle >> 32) & 0xff; devfn = pcidev_info->pdi_slot_host_handle & 0xffffffff; - host_pci_dev = pci_get_domain_bus_and_slot(segment, bus_no, devfn); + host_pci_bus = pci_find_bus(segment, bus_no); + host_pci_dev = pci_get_slot(host_pci_bus, devfn); pcidev_info->host_pci_dev = host_pci_dev; pcidev_info->pdi_linux_pcidev = dev; diff --git a/trunk/arch/m32r/kernel/process.c b/trunk/arch/m32r/kernel/process.c index 384e63f3a4c4..3a4a32b27208 100644 --- a/trunk/arch/m32r/kernel/process.c +++ b/trunk/arch/m32r/kernel/process.c @@ -26,7 +26,6 @@ #include #include #include -#include #include #include @@ -83,7 +82,6 @@ void cpu_idle (void) { /* endless idle loop with no priority at all */ while (1) { - rcu_idle_enter(); while (!need_resched()) { void (*idle)(void) = pm_idle; @@ -92,7 +90,6 @@ void cpu_idle (void) idle(); } - rcu_idle_exit(); schedule_preempt_disabled(); } } diff --git a/trunk/arch/m68k/Kconfig b/trunk/arch/m68k/Kconfig index b22df9410dce..0b0f8b8c4a26 100644 --- a/trunk/arch/m68k/Kconfig +++ b/trunk/arch/m68k/Kconfig @@ -5,7 +5,6 @@ config M68K select HAVE_AOUT if MMU select HAVE_GENERIC_HARDIRQS select GENERIC_IRQ_SHOW - select GENERIC_ATOMIC64 select ARCH_HAVE_NMI_SAFE_CMPXCHG if RMW_INSNS select GENERIC_CPU_DEVICES select GENERIC_STRNCPY_FROM_USER if MMU @@ -55,6 +54,18 @@ config ZONE_DMA bool default y +config CPU_HAS_NO_BITFIELDS + bool + +config CPU_HAS_NO_MULDIV64 + bool + +config CPU_HAS_ADDRESS_SPACES + bool + +config FPU + bool + config HZ int default 1000 if CLEOPATRA diff --git a/trunk/arch/m68k/Kconfig.cpu b/trunk/arch/m68k/Kconfig.cpu index c4eb79edecec..43a9f8f1b8eb 100644 --- a/trunk/arch/m68k/Kconfig.cpu +++ b/trunk/arch/m68k/Kconfig.cpu @@ -28,7 +28,6 @@ config COLDFIRE select CPU_HAS_NO_BITFIELDS select CPU_HAS_NO_MULDIV64 select GENERIC_CSUM - select HAVE_CLK endchoice @@ -38,7 +37,6 @@ config M68000 bool select CPU_HAS_NO_BITFIELDS select CPU_HAS_NO_MULDIV64 - select CPU_HAS_NO_UNALIGNED select GENERIC_CSUM help The Freescale (was Motorola) 68000 CPU is the first generation of @@ -50,7 +48,6 @@ config M68000 config MCPU32 bool select CPU_HAS_NO_BITFIELDS - select CPU_HAS_NO_UNALIGNED help The Freescale (was then Motorola) CPU32 is a CPU core that is based on the 68020 processor. For the most part it is used in @@ -59,6 +56,7 @@ config MCPU32 config M68020 bool "68020 support" depends on MMU + select GENERIC_ATOMIC64 select CPU_HAS_ADDRESS_SPACES help If you anticipate running this kernel on a computer with a MC68020 @@ -69,6 +67,7 @@ config M68020 config M68030 bool "68030 support" depends on MMU && !MMU_SUN3 + select GENERIC_ATOMIC64 select CPU_HAS_ADDRESS_SPACES help If you anticipate running this kernel on a computer with a MC68030 @@ -78,6 +77,7 @@ config M68030 config M68040 bool "68040 support" depends on MMU && !MMU_SUN3 + select GENERIC_ATOMIC64 select CPU_HAS_ADDRESS_SPACES help If you anticipate running this kernel on a computer with a MC68LC040 @@ -88,6 +88,7 @@ config M68040 config M68060 bool "68060 support" depends on MMU && !MMU_SUN3 + select GENERIC_ATOMIC64 select CPU_HAS_ADDRESS_SPACES help If you anticipate running this kernel on a computer with a MC68060 @@ -375,18 +376,6 @@ config NODES_SHIFT default "3" depends on !SINGLE_MEMORY_CHUNK -config CPU_HAS_NO_BITFIELDS - bool - -config CPU_HAS_NO_MULDIV64 - bool - -config CPU_HAS_NO_UNALIGNED - bool - -config CPU_HAS_ADDRESS_SPACES - bool - config FPU bool diff --git a/trunk/arch/m68k/apollo/config.c b/trunk/arch/m68k/apollo/config.c index f5565d6eeb8e..0a30406b9442 100644 --- a/trunk/arch/m68k/apollo/config.c +++ b/trunk/arch/m68k/apollo/config.c @@ -177,8 +177,8 @@ irqreturn_t dn_timer_int(int irq, void *dev_id) timer_handler(irq, dev_id); - x = *(volatile unsigned char *)(apollo_timer + 3); - x = *(volatile unsigned char *)(apollo_timer + 5); + x=*(volatile unsigned char *)(timer+3); + x=*(volatile unsigned char *)(timer+5); return IRQ_HANDLED; } @@ -186,17 +186,17 @@ irqreturn_t dn_timer_int(int irq, void *dev_id) void dn_sched_init(irq_handler_t timer_routine) { /* program timer 1 */ - *(volatile unsigned char *)(apollo_timer + 3) = 0x01; - *(volatile unsigned char *)(apollo_timer + 1) = 0x40; - *(volatile unsigned char *)(apollo_timer + 5) = 0x09; - *(volatile unsigned char *)(apollo_timer + 7) = 0xc4; + *(volatile unsigned char *)(timer+3)=0x01; + *(volatile unsigned char *)(timer+1)=0x40; + *(volatile unsigned char *)(timer+5)=0x09; + *(volatile unsigned char *)(timer+7)=0xc4; /* enable IRQ of PIC B */ *(volatile unsigned char *)(pica+1)&=(~8); #if 0 - printk("*(0x10803) %02x\n",*(volatile unsigned char *)(apollo_timer + 0x3)); - printk("*(0x10803) %02x\n",*(volatile unsigned char *)(apollo_timer + 0x3)); + printk("*(0x10803) %02x\n",*(volatile unsigned char *)(timer+0x3)); + printk("*(0x10803) %02x\n",*(volatile unsigned char *)(timer+0x3)); #endif if (request_irq(IRQ_APOLLO, dn_timer_int, 0, "time", timer_routine)) diff --git a/trunk/arch/m68k/emu/nfcon.c b/trunk/arch/m68k/emu/nfcon.c index 16d170f53bfd..8db25e806947 100644 --- a/trunk/arch/m68k/emu/nfcon.c +++ b/trunk/arch/m68k/emu/nfcon.c @@ -19,7 +19,6 @@ #include static int stderr_id; -static struct tty_port nfcon_tty_port; static struct tty_driver *nfcon_tty_driver; static void nfputs(const char *str, unsigned int count) @@ -120,8 +119,6 @@ static int __init nfcon_init(void) { int res; - tty_port_init(&nfcon_tty_port); - stderr_id = nf_get_id("NF_STDERR"); if (!stderr_id) return -ENODEV; @@ -138,7 +135,6 @@ static int __init nfcon_init(void) nfcon_tty_driver->flags = TTY_DRIVER_REAL_RAW; tty_set_operations(nfcon_tty_driver, &nfcon_tty_ops); - tty_port_link_device(&nfcon_tty_port, nfcon_tty_driver, 0); res = tty_register_driver(nfcon_tty_driver); if (res) { pr_err("failed to register nfcon tty driver\n"); diff --git a/trunk/arch/m68k/include/asm/Kbuild b/trunk/arch/m68k/include/asm/Kbuild index a74e5d95c384..eafa2539a8ee 100644 --- a/trunk/arch/m68k/include/asm/Kbuild +++ b/trunk/arch/m68k/include/asm/Kbuild @@ -1,29 +1,4 @@ include include/asm-generic/Kbuild.asm header-y += cachectl.h -generic-y += bitsperlong.h -generic-y += cputime.h -generic-y += device.h -generic-y += emergency-restart.h -generic-y += errno.h -generic-y += futex.h -generic-y += ioctl.h -generic-y += ipcbuf.h -generic-y += irq_regs.h -generic-y += kdebug.h -generic-y += kmap_types.h -generic-y += kvm_para.h -generic-y += local64.h -generic-y += local.h -generic-y += mman.h -generic-y += mutex.h -generic-y += percpu.h -generic-y += resource.h -generic-y += scatterlist.h -generic-y += sections.h -generic-y += siginfo.h -generic-y += statfs.h -generic-y += topology.h -generic-y += types.h generic-y += word-at-a-time.h -generic-y += xor.h diff --git a/trunk/arch/m68k/include/asm/MC68332.h b/trunk/arch/m68k/include/asm/MC68332.h new file mode 100644 index 000000000000..6bb8f02685a2 --- /dev/null +++ b/trunk/arch/m68k/include/asm/MC68332.h @@ -0,0 +1,152 @@ + +/* include/asm-m68knommu/MC68332.h: '332 control registers + * + * Copyright (C) 1998 Kenneth Albanowski , + * + */ + +#ifndef _MC68332_H_ +#define _MC68332_H_ + +#define BYTE_REF(addr) (*((volatile unsigned char*)addr)) +#define WORD_REF(addr) (*((volatile unsigned short*)addr)) + +#define PORTE_ADDR 0xfffa11 +#define PORTE BYTE_REF(PORTE_ADDR) +#define DDRE_ADDR 0xfffa15 +#define DDRE BYTE_REF(DDRE_ADDR) +#define PEPAR_ADDR 0xfffa17 +#define PEPAR BYTE_REF(PEPAR_ADDR) + +#define PORTF_ADDR 0xfffa19 +#define PORTF BYTE_REF(PORTF_ADDR) +#define DDRF_ADDR 0xfffa1d +#define DDRF BYTE_REF(DDRF_ADDR) +#define PFPAR_ADDR 0xfffa1f +#define PFPAR BYTE_REF(PFPAR_ADDR) + +#define PORTQS_ADDR 0xfffc15 +#define PORTQS BYTE_REF(PORTQS_ADDR) +#define DDRQS_ADDR 0xfffc17 +#define DDRQS BYTE_REF(DDRQS_ADDR) +#define PQSPAR_ADDR 0xfffc16 +#define PQSPAR BYTE_REF(PQSPAR_ADDR) + +#define CSPAR0_ADDR 0xFFFA44 +#define CSPAR0 WORD_REF(CSPAR0_ADDR) +#define CSPAR1_ADDR 0xFFFA46 +#define CSPAR1 WORD_REF(CSPAR1_ADDR) +#define CSARBT_ADDR 0xFFFA48 +#define CSARBT WORD_REF(CSARBT_ADDR) +#define CSOPBT_ADDR 0xFFFA4A +#define CSOPBT WORD_REF(CSOPBT_ADDR) +#define CSBAR0_ADDR 0xFFFA4C +#define CSBAR0 WORD_REF(CSBAR0_ADDR) +#define CSOR0_ADDR 0xFFFA4E +#define CSOR0 WORD_REF(CSOR0_ADDR) +#define CSBAR1_ADDR 0xFFFA50 +#define CSBAR1 WORD_REF(CSBAR1_ADDR) +#define CSOR1_ADDR 0xFFFA52 +#define CSOR1 WORD_REF(CSOR1_ADDR) +#define CSBAR2_ADDR 0xFFFA54 +#define CSBAR2 WORD_REF(CSBAR2_ADDR) +#define CSOR2_ADDR 0xFFFA56 +#define CSOR2 WORD_REF(CSOR2_ADDR) +#define CSBAR3_ADDR 0xFFFA58 +#define CSBAR3 WORD_REF(CSBAR3_ADDR) +#define CSOR3_ADDR 0xFFFA5A +#define CSOR3 WORD_REF(CSOR3_ADDR) +#define CSBAR4_ADDR 0xFFFA5C +#define CSBAR4 WORD_REF(CSBAR4_ADDR) +#define CSOR4_ADDR 0xFFFA5E +#define CSOR4 WORD_REF(CSOR4_ADDR) +#define CSBAR5_ADDR 0xFFFA60 +#define CSBAR5 WORD_REF(CSBAR5_ADDR) +#define CSOR5_ADDR 0xFFFA62 +#define CSOR5 WORD_REF(CSOR5_ADDR) +#define CSBAR6_ADDR 0xFFFA64 +#define CSBAR6 WORD_REF(CSBAR6_ADDR) +#define CSOR6_ADDR 0xFFFA66 +#define CSOR6 WORD_REF(CSOR6_ADDR) +#define CSBAR7_ADDR 0xFFFA68 +#define CSBAR7 WORD_REF(CSBAR7_ADDR) +#define CSOR7_ADDR 0xFFFA6A +#define CSOR7 WORD_REF(CSOR7_ADDR) +#define CSBAR8_ADDR 0xFFFA6C +#define CSBAR8 WORD_REF(CSBAR8_ADDR) +#define CSOR8_ADDR 0xFFFA6E +#define CSOR8 WORD_REF(CSOR8_ADDR) +#define CSBAR9_ADDR 0xFFFA70 +#define CSBAR9 WORD_REF(CSBAR9_ADDR) +#define CSOR9_ADDR 0xFFFA72 +#define CSOR9 WORD_REF(CSOR9_ADDR) +#define CSBAR10_ADDR 0xFFFA74 +#define CSBAR10 WORD_REF(CSBAR10_ADDR) +#define CSOR10_ADDR 0xFFFA76 +#define CSOR10 WORD_REF(CSOR10_ADDR) + +#define CSOR_MODE_ASYNC 0x0000 +#define CSOR_MODE_SYNC 0x8000 +#define CSOR_MODE_MASK 0x8000 +#define CSOR_BYTE_DISABLE 0x0000 +#define CSOR_BYTE_UPPER 0x4000 +#define CSOR_BYTE_LOWER 0x2000 +#define CSOR_BYTE_BOTH 0x6000 +#define CSOR_BYTE_MASK 0x6000 +#define CSOR_RW_RSVD 0x0000 +#define CSOR_RW_READ 0x0800 +#define CSOR_RW_WRITE 0x1000 +#define CSOR_RW_BOTH 0x1800 +#define CSOR_RW_MASK 0x1800 +#define CSOR_STROBE_DS 0x0400 +#define CSOR_STROBE_AS 0x0000 +#define CSOR_STROBE_MASK 0x0400 +#define CSOR_DSACK_WAIT(x) (wait << 6) +#define CSOR_DSACK_FTERM (14 << 6) +#define CSOR_DSACK_EXTERNAL (15 << 6) +#define CSOR_DSACK_MASK 0x03c0 +#define CSOR_SPACE_CPU 0x0000 +#define CSOR_SPACE_USER 0x0010 +#define CSOR_SPACE_SU 0x0020 +#define CSOR_SPACE_BOTH 0x0030 +#define CSOR_SPACE_MASK 0x0030 +#define CSOR_IPL_ALL 0x0000 +#define CSOR_IPL_PRIORITY(x) (x << 1) +#define CSOR_IPL_MASK 0x000e +#define CSOR_AVEC_ON 0x0001 +#define CSOR_AVEC_OFF 0x0000 +#define CSOR_AVEC_MASK 0x0001 + +#define CSBAR_ADDR(x) ((addr >> 11) << 3) +#define CSBAR_ADDR_MASK 0xfff8 +#define CSBAR_BLKSIZE_2K 0x0000 +#define CSBAR_BLKSIZE_8K 0x0001 +#define CSBAR_BLKSIZE_16K 0x0002 +#define CSBAR_BLKSIZE_64K 0x0003 +#define CSBAR_BLKSIZE_128K 0x0004 +#define CSBAR_BLKSIZE_256K 0x0005 +#define CSBAR_BLKSIZE_512K 0x0006 +#define CSBAR_BLKSIZE_1M 0x0007 +#define CSBAR_BLKSIZE_MASK 0x0007 + +#define CSPAR_DISC 0 +#define CSPAR_ALT 1 +#define CSPAR_CS8 2 +#define CSPAR_CS16 3 +#define CSPAR_MASK 3 + +#define CSPAR0_CSBOOT(x) (x << 0) +#define CSPAR0_CS0(x) (x << 2) +#define CSPAR0_CS1(x) (x << 4) +#define CSPAR0_CS2(x) (x << 6) +#define CSPAR0_CS3(x) (x << 8) +#define CSPAR0_CS4(x) (x << 10) +#define CSPAR0_CS5(x) (x << 12) + +#define CSPAR1_CS6(x) (x << 0) +#define CSPAR1_CS7(x) (x << 2) +#define CSPAR1_CS8(x) (x << 4) +#define CSPAR1_CS9(x) (x << 6) +#define CSPAR1_CS10(x) (x << 8) + +#endif diff --git a/trunk/arch/m68k/include/asm/apollodma.h b/trunk/arch/m68k/include/asm/apollodma.h new file mode 100644 index 000000000000..954adc851adb --- /dev/null +++ b/trunk/arch/m68k/include/asm/apollodma.h @@ -0,0 +1,248 @@ +/* + * linux/include/asm/dma.h: Defines for using and allocating dma channels. + * Written by Hennus Bergman, 1992. + * High DMA channel support & info by Hannu Savolainen + * and John Boyd, Nov. 1992. + */ + +#ifndef _ASM_APOLLO_DMA_H +#define _ASM_APOLLO_DMA_H + +#include /* need byte IO */ +#include /* And spinlocks */ +#include + + +#define dma_outb(val,addr) (*((volatile unsigned char *)(addr+IO_BASE)) = (val)) +#define dma_inb(addr) (*((volatile unsigned char *)(addr+IO_BASE))) + +/* + * NOTES about DMA transfers: + * + * controller 1: channels 0-3, byte operations, ports 00-1F + * controller 2: channels 4-7, word operations, ports C0-DF + * + * - ALL registers are 8 bits only, regardless of transfer size + * - channel 4 is not used - cascades 1 into 2. + * - channels 0-3 are byte - addresses/counts are for physical bytes + * - channels 5-7 are word - addresses/counts are for physical words + * - transfers must not cross physical 64K (0-3) or 128K (5-7) boundaries + * - transfer count loaded to registers is 1 less than actual count + * - controller 2 offsets are all even (2x offsets for controller 1) + * - page registers for 5-7 don't use data bit 0, represent 128K pages + * - page registers for 0-3 use bit 0, represent 64K pages + * + * DMA transfers are limited to the lower 16MB of _physical_ memory. + * Note that addresses loaded into registers must be _physical_ addresses, + * not logical addresses (which may differ if paging is active). + * + * Address mapping for channels 0-3: + * + * A23 ... A16 A15 ... A8 A7 ... A0 (Physical addresses) + * | ... | | ... | | ... | + * | ... | | ... | | ... | + * | ... | | ... | | ... | + * P7 ... P0 A7 ... A0 A7 ... A0 + * | Page | Addr MSB | Addr LSB | (DMA registers) + * + * Address mapping for channels 5-7: + * + * A23 ... A17 A16 A15 ... A9 A8 A7 ... A1 A0 (Physical addresses) + * | ... | \ \ ... \ \ \ ... \ \ + * | ... | \ \ ... \ \ \ ... \ (not used) + * | ... | \ \ ... \ \ \ ... \ + * P7 ... P1 (0) A7 A6 ... A0 A7 A6 ... A0 + * | Page | Addr MSB | Addr LSB | (DMA registers) + * + * Again, channels 5-7 transfer _physical_ words (16 bits), so addresses + * and counts _must_ be word-aligned (the lowest address bit is _ignored_ at + * the hardware level, so odd-byte transfers aren't possible). + * + * Transfer count (_not # bytes_) is limited to 64K, represented as actual + * count - 1 : 64K => 0xFFFF, 1 => 0x0000. Thus, count is always 1 or more, + * and up to 128K bytes may be transferred on channels 5-7 in one operation. + * + */ + +#define MAX_DMA_CHANNELS 8 + +/* The maximum address that we can perform a DMA transfer to on this platform */#define MAX_DMA_ADDRESS (PAGE_OFFSET+0x1000000) + +/* 8237 DMA controllers */ +#define IO_DMA1_BASE 0x10C00 /* 8 bit slave DMA, channels 0..3 */ +#define IO_DMA2_BASE 0x10D00 /* 16 bit master DMA, ch 4(=slave input)..7 */ + +/* DMA controller registers */ +#define DMA1_CMD_REG (IO_DMA1_BASE+0x08) /* command register (w) */ +#define DMA1_STAT_REG (IO_DMA1_BASE+0x08) /* status register (r) */ +#define DMA1_REQ_REG (IO_DMA1_BASE+0x09) /* request register (w) */ +#define DMA1_MASK_REG (IO_DMA1_BASE+0x0A) /* single-channel mask (w) */ +#define DMA1_MODE_REG (IO_DMA1_BASE+0x0B) /* mode register (w) */ +#define DMA1_CLEAR_FF_REG (IO_DMA1_BASE+0x0C) /* clear pointer flip-flop (w) */ +#define DMA1_TEMP_REG (IO_DMA1_BASE+0x0D) /* Temporary Register (r) */ +#define DMA1_RESET_REG (IO_DMA1_BASE+0x0D) /* Master Clear (w) */ +#define DMA1_CLR_MASK_REG (IO_DMA1_BASE+0x0E) /* Clear Mask */ +#define DMA1_MASK_ALL_REG (IO_DMA1_BASE+0x0F) /* all-channels mask (w) */ + +#define DMA2_CMD_REG (IO_DMA2_BASE+0x10) /* command register (w) */ +#define DMA2_STAT_REG (IO_DMA2_BASE+0x10) /* status register (r) */ +#define DMA2_REQ_REG (IO_DMA2_BASE+0x12) /* request register (w) */ +#define DMA2_MASK_REG (IO_DMA2_BASE+0x14) /* single-channel mask (w) */ +#define DMA2_MODE_REG (IO_DMA2_BASE+0x16) /* mode register (w) */ +#define DMA2_CLEAR_FF_REG (IO_DMA2_BASE+0x18) /* clear pointer flip-flop (w) */ +#define DMA2_TEMP_REG (IO_DMA2_BASE+0x1A) /* Temporary Register (r) */ +#define DMA2_RESET_REG (IO_DMA2_BASE+0x1A) /* Master Clear (w) */ +#define DMA2_CLR_MASK_REG (IO_DMA2_BASE+0x1C) /* Clear Mask */ +#define DMA2_MASK_ALL_REG (IO_DMA2_BASE+0x1E) /* all-channels mask (w) */ + +#define DMA_ADDR_0 (IO_DMA1_BASE+0x00) /* DMA address registers */ +#define DMA_ADDR_1 (IO_DMA1_BASE+0x02) +#define DMA_ADDR_2 (IO_DMA1_BASE+0x04) +#define DMA_ADDR_3 (IO_DMA1_BASE+0x06) +#define DMA_ADDR_4 (IO_DMA2_BASE+0x00) +#define DMA_ADDR_5 (IO_DMA2_BASE+0x04) +#define DMA_ADDR_6 (IO_DMA2_BASE+0x08) +#define DMA_ADDR_7 (IO_DMA2_BASE+0x0C) + +#define DMA_CNT_0 (IO_DMA1_BASE+0x01) /* DMA count registers */ +#define DMA_CNT_1 (IO_DMA1_BASE+0x03) +#define DMA_CNT_2 (IO_DMA1_BASE+0x05) +#define DMA_CNT_3 (IO_DMA1_BASE+0x07) +#define DMA_CNT_4 (IO_DMA2_BASE+0x02) +#define DMA_CNT_5 (IO_DMA2_BASE+0x06) +#define DMA_CNT_6 (IO_DMA2_BASE+0x0A) +#define DMA_CNT_7 (IO_DMA2_BASE+0x0E) + +#define DMA_MODE_READ 0x44 /* I/O to memory, no autoinit, increment, single mode */ +#define DMA_MODE_WRITE 0x48 /* memory to I/O, no autoinit, increment, single mode */ +#define DMA_MODE_CASCADE 0xC0 /* pass thru DREQ->HRQ, DACK<-HLDA only */ + +#define DMA_AUTOINIT 0x10 + +#define DMA_8BIT 0 +#define DMA_16BIT 1 +#define DMA_BUSMASTER 2 + +extern spinlock_t dma_spin_lock; + +static __inline__ unsigned long claim_dma_lock(void) +{ + unsigned long flags; + spin_lock_irqsave(&dma_spin_lock, flags); + return flags; +} + +static __inline__ void release_dma_lock(unsigned long flags) +{ + spin_unlock_irqrestore(&dma_spin_lock, flags); +} + +/* enable/disable a specific DMA channel */ +static __inline__ void enable_dma(unsigned int dmanr) +{ + if (dmanr<=3) + dma_outb(dmanr, DMA1_MASK_REG); + else + dma_outb(dmanr & 3, DMA2_MASK_REG); +} + +static __inline__ void disable_dma(unsigned int dmanr) +{ + if (dmanr<=3) + dma_outb(dmanr | 4, DMA1_MASK_REG); + else + dma_outb((dmanr & 3) | 4, DMA2_MASK_REG); +} + +/* Clear the 'DMA Pointer Flip Flop'. + * Write 0 for LSB/MSB, 1 for MSB/LSB access. + * Use this once to initialize the FF to a known state. + * After that, keep track of it. :-) + * --- In order to do that, the DMA routines below should --- + * --- only be used while holding the DMA lock ! --- + */ +static __inline__ void clear_dma_ff(unsigned int dmanr) +{ + if (dmanr<=3) + dma_outb(0, DMA1_CLEAR_FF_REG); + else + dma_outb(0, DMA2_CLEAR_FF_REG); +} + +/* set mode (above) for a specific DMA channel */ +static __inline__ void set_dma_mode(unsigned int dmanr, char mode) +{ + if (dmanr<=3) + dma_outb(mode | dmanr, DMA1_MODE_REG); + else + dma_outb(mode | (dmanr&3), DMA2_MODE_REG); +} + +/* Set transfer address & page bits for specific DMA channel. + * Assumes dma flipflop is clear. + */ +static __inline__ void set_dma_addr(unsigned int dmanr, unsigned int a) +{ + if (dmanr <= 3) { + dma_outb( a & 0xff, ((dmanr&3)<<1) + IO_DMA1_BASE ); + dma_outb( (a>>8) & 0xff, ((dmanr&3)<<1) + IO_DMA1_BASE ); + } else { + dma_outb( (a>>1) & 0xff, ((dmanr&3)<<2) + IO_DMA2_BASE ); + dma_outb( (a>>9) & 0xff, ((dmanr&3)<<2) + IO_DMA2_BASE ); + } +} + + +/* Set transfer size (max 64k for DMA1..3, 128k for DMA5..7) for + * a specific DMA channel. + * You must ensure the parameters are valid. + * NOTE: from a manual: "the number of transfers is one more + * than the initial word count"! This is taken into account. + * Assumes dma flip-flop is clear. + * NOTE 2: "count" represents _bytes_ and must be even for channels 5-7. + */ +static __inline__ void set_dma_count(unsigned int dmanr, unsigned int count) +{ + count--; + if (dmanr <= 3) { + dma_outb( count & 0xff, ((dmanr&3)<<1) + 1 + IO_DMA1_BASE ); + dma_outb( (count>>8) & 0xff, ((dmanr&3)<<1) + 1 + IO_DMA1_BASE ); + } else { + dma_outb( (count>>1) & 0xff, ((dmanr&3)<<2) + 2 + IO_DMA2_BASE ); + dma_outb( (count>>9) & 0xff, ((dmanr&3)<<2) + 2 + IO_DMA2_BASE ); + } +} + + +/* Get DMA residue count. After a DMA transfer, this + * should return zero. Reading this while a DMA transfer is + * still in progress will return unpredictable results. + * If called before the channel has been used, it may return 1. + * Otherwise, it returns the number of _bytes_ left to transfer. + * + * Assumes DMA flip-flop is clear. + */ +static __inline__ int get_dma_residue(unsigned int dmanr) +{ + unsigned int io_port = (dmanr<=3)? ((dmanr&3)<<1) + 1 + IO_DMA1_BASE + : ((dmanr&3)<<2) + 2 + IO_DMA2_BASE; + + /* using short to get 16-bit wrap around */ + unsigned short count; + + count = 1 + dma_inb(io_port); + count += dma_inb(io_port) << 8; + + return (dmanr<=3)? count : (count<<1); +} + + +/* These are in kernel/dma.c: */ +extern int request_dma(unsigned int dmanr, const char * device_id); /* reserve a DMA channel */ +extern void free_dma(unsigned int dmanr); /* release it again */ + +/* These are in arch/m68k/apollo/dma.c: */ +extern unsigned short dma_map_page(unsigned long phys_addr,int count,int type); +extern void dma_unmap_page(unsigned short dma_addr); + +#endif /* _ASM_APOLLO_DMA_H */ diff --git a/trunk/arch/m68k/include/asm/apollohw.h b/trunk/arch/m68k/include/asm/apollohw.h index 635ef4f89010..a1373b9aa281 100644 --- a/trunk/arch/m68k/include/asm/apollohw.h +++ b/trunk/arch/m68k/include/asm/apollohw.h @@ -98,7 +98,7 @@ extern u_long timer_physaddr; #define cpuctrl (*(volatile unsigned int *)(IO_BASE + cpuctrl_physaddr)) #define pica (IO_BASE + pica_physaddr) #define picb (IO_BASE + picb_physaddr) -#define apollo_timer (IO_BASE + timer_physaddr) +#define timer (IO_BASE + timer_physaddr) #define addr_xlat_map ((unsigned short *)(IO_BASE + 0x17000)) #define isaIO2mem(x) (((((x) & 0x3f8) << 7) | (((x) & 0xfc00) >> 6) | ((x) & 0x7)) + 0x40000 + IO_BASE) diff --git a/trunk/arch/m68k/include/asm/bitsperlong.h b/trunk/arch/m68k/include/asm/bitsperlong.h new file mode 100644 index 000000000000..6dc0bb0c13b2 --- /dev/null +++ b/trunk/arch/m68k/include/asm/bitsperlong.h @@ -0,0 +1 @@ +#include diff --git a/trunk/arch/m68k/include/asm/cputime.h b/trunk/arch/m68k/include/asm/cputime.h new file mode 100644 index 000000000000..c79c5e892305 --- /dev/null +++ b/trunk/arch/m68k/include/asm/cputime.h @@ -0,0 +1,6 @@ +#ifndef __M68K_CPUTIME_H +#define __M68K_CPUTIME_H + +#include + +#endif /* __M68K_CPUTIME_H */ diff --git a/trunk/arch/m68k/include/asm/delay.h b/trunk/arch/m68k/include/asm/delay.h index 12d8fe4f1d30..9c09becfd4c9 100644 --- a/trunk/arch/m68k/include/asm/delay.h +++ b/trunk/arch/m68k/include/asm/delay.h @@ -43,7 +43,7 @@ static inline void __delay(unsigned long loops) extern void __bad_udelay(void); -#ifdef CONFIG_CPU_HAS_NO_MULDIV64 +#if defined(CONFIG_M68000) || defined(CONFIG_COLDFIRE) /* * The simpler m68k and ColdFire processors do not have a 32*32->64 * multiply instruction. So we need to handle them a little differently. diff --git a/trunk/arch/m68k/include/asm/device.h b/trunk/arch/m68k/include/asm/device.h new file mode 100644 index 000000000000..d8f9872b0e2d --- /dev/null +++ b/trunk/arch/m68k/include/asm/device.h @@ -0,0 +1,7 @@ +/* + * Arch specific extensions to struct device + * + * This file is released under the GPLv2 + */ +#include + diff --git a/trunk/arch/m68k/include/asm/emergency-restart.h b/trunk/arch/m68k/include/asm/emergency-restart.h new file mode 100644 index 000000000000..108d8c48e42e --- /dev/null +++ b/trunk/arch/m68k/include/asm/emergency-restart.h @@ -0,0 +1,6 @@ +#ifndef _ASM_EMERGENCY_RESTART_H +#define _ASM_EMERGENCY_RESTART_H + +#include + +#endif /* _ASM_EMERGENCY_RESTART_H */ diff --git a/trunk/arch/m68k/include/asm/errno.h b/trunk/arch/m68k/include/asm/errno.h new file mode 100644 index 000000000000..0d4e188d6ef6 --- /dev/null +++ b/trunk/arch/m68k/include/asm/errno.h @@ -0,0 +1,6 @@ +#ifndef _M68K_ERRNO_H +#define _M68K_ERRNO_H + +#include + +#endif /* _M68K_ERRNO_H */ diff --git a/trunk/arch/m68k/include/asm/futex.h b/trunk/arch/m68k/include/asm/futex.h new file mode 100644 index 000000000000..6a332a9f099c --- /dev/null +++ b/trunk/arch/m68k/include/asm/futex.h @@ -0,0 +1,6 @@ +#ifndef _ASM_FUTEX_H +#define _ASM_FUTEX_H + +#include + +#endif diff --git a/trunk/arch/m68k/include/asm/ioctl.h b/trunk/arch/m68k/include/asm/ioctl.h new file mode 100644 index 000000000000..b279fe06dfe5 --- /dev/null +++ b/trunk/arch/m68k/include/asm/ioctl.h @@ -0,0 +1 @@ +#include diff --git a/trunk/arch/m68k/include/asm/ipcbuf.h b/trunk/arch/m68k/include/asm/ipcbuf.h new file mode 100644 index 000000000000..84c7e51cb6d0 --- /dev/null +++ b/trunk/arch/m68k/include/asm/ipcbuf.h @@ -0,0 +1 @@ +#include diff --git a/trunk/arch/m68k/include/asm/irq_regs.h b/trunk/arch/m68k/include/asm/irq_regs.h new file mode 100644 index 000000000000..3dd9c0b70270 --- /dev/null +++ b/trunk/arch/m68k/include/asm/irq_regs.h @@ -0,0 +1 @@ +#include diff --git a/trunk/arch/m68k/include/asm/kdebug.h b/trunk/arch/m68k/include/asm/kdebug.h new file mode 100644 index 000000000000..6ece1b037665 --- /dev/null +++ b/trunk/arch/m68k/include/asm/kdebug.h @@ -0,0 +1 @@ +#include diff --git a/trunk/arch/m68k/include/asm/kmap_types.h b/trunk/arch/m68k/include/asm/kmap_types.h new file mode 100644 index 000000000000..3413cc1390ec --- /dev/null +++ b/trunk/arch/m68k/include/asm/kmap_types.h @@ -0,0 +1,6 @@ +#ifndef __ASM_M68K_KMAP_TYPES_H +#define __ASM_M68K_KMAP_TYPES_H + +#include + +#endif /* __ASM_M68K_KMAP_TYPES_H */ diff --git a/trunk/arch/m68k/include/asm/kvm_para.h b/trunk/arch/m68k/include/asm/kvm_para.h new file mode 100644 index 000000000000..14fab8f0b957 --- /dev/null +++ b/trunk/arch/m68k/include/asm/kvm_para.h @@ -0,0 +1 @@ +#include diff --git a/trunk/arch/m68k/include/asm/local.h b/trunk/arch/m68k/include/asm/local.h new file mode 100644 index 000000000000..6c259263e1f0 --- /dev/null +++ b/trunk/arch/m68k/include/asm/local.h @@ -0,0 +1,6 @@ +#ifndef _ASM_M68K_LOCAL_H +#define _ASM_M68K_LOCAL_H + +#include + +#endif /* _ASM_M68K_LOCAL_H */ diff --git a/trunk/arch/m68k/include/asm/local64.h b/trunk/arch/m68k/include/asm/local64.h new file mode 100644 index 000000000000..36c93b5cc239 --- /dev/null +++ b/trunk/arch/m68k/include/asm/local64.h @@ -0,0 +1 @@ +#include diff --git a/trunk/arch/m68k/include/asm/mac_mouse.h b/trunk/arch/m68k/include/asm/mac_mouse.h new file mode 100644 index 000000000000..39a5c292eaee --- /dev/null +++ b/trunk/arch/m68k/include/asm/mac_mouse.h @@ -0,0 +1,23 @@ +#ifndef _ASM_MAC_MOUSE_H +#define _ASM_MAC_MOUSE_H + +/* + * linux/include/asm-m68k/mac_mouse.h + * header file for Macintosh ADB mouse driver + * 27-10-97 Michael Schmitz + * copied from: + * header file for Atari Mouse driver + * by Robert de Vries (robert@and.nl) on 19Jul93 + */ + +struct mouse_status { + char buttons; + short dx; + short dy; + int ready; + int active; + wait_queue_head_t wait; + struct fasync_struct *fasyncptr; +}; + +#endif diff --git a/trunk/arch/m68k/include/asm/mcfmbus.h b/trunk/arch/m68k/include/asm/mcfmbus.h new file mode 100644 index 000000000000..319899c47a2c --- /dev/null +++ b/trunk/arch/m68k/include/asm/mcfmbus.h @@ -0,0 +1,77 @@ +/****************************************************************************/ + +/* + * mcfmbus.h -- Coldfire MBUS support defines. + * + * (C) Copyright 1999, Martin Floeer (mfloeer@axcent.de) + */ + +/****************************************************************************/ + + +#ifndef mcfmbus_h +#define mcfmbus_h + + +#define MCFMBUS_BASE 0x280 +#define MCFMBUS_IRQ_VECTOR 0x19 +#define MCFMBUS_IRQ 0x1 +#define MCFMBUS_CLK 0x3f +#define MCFMBUS_IRQ_LEVEL 0x07 /*IRQ Level 1*/ +#define MCFMBUS_ADDRESS 0x01 + + +/* +* Define the 5307 MBUS register set addresses +*/ + +#define MCFMBUS_MADR 0x00 +#define MCFMBUS_MFDR 0x04 +#define MCFMBUS_MBCR 0x08 +#define MCFMBUS_MBSR 0x0C +#define MCFMBUS_MBDR 0x10 + + +#define MCFMBUS_MADR_ADDR(a) (((a)&0x7F)<<0x01) /*Slave Address*/ + +#define MCFMBUS_MFDR_MBC(a) ((a)&0x3F) /*M-Bus Clock*/ + +/* +* Define bit flags in Control Register +*/ + +#define MCFMBUS_MBCR_MEN (0x80) /* M-Bus Enable */ +#define MCFMBUS_MBCR_MIEN (0x40) /* M-Bus Interrupt Enable */ +#define MCFMBUS_MBCR_MSTA (0x20) /* Master/Slave Mode Select Bit */ +#define MCFMBUS_MBCR_MTX (0x10) /* Transmit/Rcv Mode Select Bit */ +#define MCFMBUS_MBCR_TXAK (0x08) /* Transmit Acknowledge Enable */ +#define MCFMBUS_MBCR_RSTA (0x04) /* Repeat Start */ + +/* +* Define bit flags in Status Register +*/ + +#define MCFMBUS_MBSR_MCF (0x80) /* Data Transfer Complete */ +#define MCFMBUS_MBSR_MAAS (0x40) /* Addressed as a Slave */ +#define MCFMBUS_MBSR_MBB (0x20) /* Bus Busy */ +#define MCFMBUS_MBSR_MAL (0x10) /* Arbitration Lost */ +#define MCFMBUS_MBSR_SRW (0x04) /* Slave Transmit */ +#define MCFMBUS_MBSR_MIF (0x02) /* M-Bus Interrupt */ +#define MCFMBUS_MBSR_RXAK (0x01) /* No Acknowledge Received */ + +/* +* Define bit flags in DATA I/O Register +*/ + +#define MCFMBUS_MBDR_READ (0x01) /* 1=read 0=write MBUS */ + +#define MBUSIOCSCLOCK 1 +#define MBUSIOCGCLOCK 2 +#define MBUSIOCSADDR 3 +#define MBUSIOCGADDR 4 +#define MBUSIOCSSLADDR 5 +#define MBUSIOCGSLADDR 6 +#define MBUSIOCSSUBADDR 7 +#define MBUSIOCGSUBADDR 8 + +#endif diff --git a/trunk/arch/m68k/include/asm/mman.h b/trunk/arch/m68k/include/asm/mman.h new file mode 100644 index 000000000000..8eebf89f5ab1 --- /dev/null +++ b/trunk/arch/m68k/include/asm/mman.h @@ -0,0 +1 @@ +#include diff --git a/trunk/arch/m68k/include/asm/mutex.h b/trunk/arch/m68k/include/asm/mutex.h new file mode 100644 index 000000000000..458c1f7fbc18 --- /dev/null +++ b/trunk/arch/m68k/include/asm/mutex.h @@ -0,0 +1,9 @@ +/* + * Pull in the generic implementation for the mutex fastpath. + * + * TODO: implement optimized primitives instead, or leave the generic + * implementation in place, or pick the atomic_xchg() based generic + * implementation. (see asm-generic/mutex-xchg.h for details) + */ + +#include diff --git a/trunk/arch/m68k/include/asm/percpu.h b/trunk/arch/m68k/include/asm/percpu.h new file mode 100644 index 000000000000..0859d048faf5 --- /dev/null +++ b/trunk/arch/m68k/include/asm/percpu.h @@ -0,0 +1,6 @@ +#ifndef __ASM_M68K_PERCPU_H +#define __ASM_M68K_PERCPU_H + +#include + +#endif /* __ASM_M68K_PERCPU_H */ diff --git a/trunk/arch/m68k/include/asm/resource.h b/trunk/arch/m68k/include/asm/resource.h new file mode 100644 index 000000000000..e7d35019f337 --- /dev/null +++ b/trunk/arch/m68k/include/asm/resource.h @@ -0,0 +1,6 @@ +#ifndef _M68K_RESOURCE_H +#define _M68K_RESOURCE_H + +#include + +#endif /* _M68K_RESOURCE_H */ diff --git a/trunk/arch/m68k/include/asm/sbus.h b/trunk/arch/m68k/include/asm/sbus.h new file mode 100644 index 000000000000..bfe3ba147f2e --- /dev/null +++ b/trunk/arch/m68k/include/asm/sbus.h @@ -0,0 +1,45 @@ +/* + * some sbus structures and macros to make usage of sbus drivers possible + */ + +#ifndef __M68K_SBUS_H +#define __M68K_SBUS_H + +struct sbus_dev { + struct { + unsigned int which_io; + unsigned int phys_addr; + } reg_addrs[1]; +}; + +/* sbus IO functions stolen from include/asm-sparc/io.h for the serial driver */ +/* No SBUS on the Sun3, kludge -- sam */ + +static inline void _sbus_writeb(unsigned char val, unsigned long addr) +{ + *(volatile unsigned char *)addr = val; +} + +static inline unsigned char _sbus_readb(unsigned long addr) +{ + return *(volatile unsigned char *)addr; +} + +static inline void _sbus_writel(unsigned long val, unsigned long addr) +{ + *(volatile unsigned long *)addr = val; + +} + +extern inline unsigned long _sbus_readl(unsigned long addr) +{ + return *(volatile unsigned long *)addr; +} + + +#define sbus_readb(a) _sbus_readb((unsigned long)a) +#define sbus_writeb(v, a) _sbus_writeb(v, (unsigned long)a) +#define sbus_readl(a) _sbus_readl((unsigned long)a) +#define sbus_writel(v, a) _sbus_writel(v, (unsigned long)a) + +#endif diff --git a/trunk/arch/m68k/include/asm/scatterlist.h b/trunk/arch/m68k/include/asm/scatterlist.h new file mode 100644 index 000000000000..312505452a1e --- /dev/null +++ b/trunk/arch/m68k/include/asm/scatterlist.h @@ -0,0 +1,6 @@ +#ifndef _M68K_SCATTERLIST_H +#define _M68K_SCATTERLIST_H + +#include + +#endif /* !(_M68K_SCATTERLIST_H) */ diff --git a/trunk/arch/m68k/include/asm/sections.h b/trunk/arch/m68k/include/asm/sections.h new file mode 100644 index 000000000000..5277e52715ec --- /dev/null +++ b/trunk/arch/m68k/include/asm/sections.h @@ -0,0 +1,8 @@ +#ifndef _ASM_M68K_SECTIONS_H +#define _ASM_M68K_SECTIONS_H + +#include + +extern char _sbss[], _ebss[]; + +#endif /* _ASM_M68K_SECTIONS_H */ diff --git a/trunk/arch/m68k/include/asm/shm.h b/trunk/arch/m68k/include/asm/shm.h new file mode 100644 index 000000000000..fa56ec84a126 --- /dev/null +++ b/trunk/arch/m68k/include/asm/shm.h @@ -0,0 +1,31 @@ +#ifndef _M68K_SHM_H +#define _M68K_SHM_H + + +/* format of page table entries that correspond to shared memory pages + currently out in swap space (see also mm/swap.c): + bits 0-1 (PAGE_PRESENT) is = 0 + bits 8..2 (SWP_TYPE) are = SHM_SWP_TYPE + bits 31..9 are used like this: + bits 15..9 (SHM_ID) the id of the shared memory segment + bits 30..16 (SHM_IDX) the index of the page within the shared memory segment + (actually only bits 25..16 get used since SHMMAX is so low) + bit 31 (SHM_READ_ONLY) flag whether the page belongs to a read-only attach +*/ +/* on the m68k both bits 0 and 1 must be zero */ +/* format on the sun3 is similar, but bits 30, 31 are set to zero and all + others are reduced by 2. --m */ + +#ifndef CONFIG_SUN3 +#define SHM_ID_SHIFT 9 +#else +#define SHM_ID_SHIFT 7 +#endif +#define _SHM_ID_BITS 7 +#define SHM_ID_MASK ((1<<_SHM_ID_BITS)-1) + +#define SHM_IDX_SHIFT (SHM_ID_SHIFT+_SHM_ID_BITS) +#define _SHM_IDX_BITS 15 +#define SHM_IDX_MASK ((1<<_SHM_IDX_BITS)-1) + +#endif /* _M68K_SHM_H */ diff --git a/trunk/arch/m68k/include/asm/siginfo.h b/trunk/arch/m68k/include/asm/siginfo.h new file mode 100644 index 000000000000..851d3d784b53 --- /dev/null +++ b/trunk/arch/m68k/include/asm/siginfo.h @@ -0,0 +1,6 @@ +#ifndef _M68K_SIGINFO_H +#define _M68K_SIGINFO_H + +#include + +#endif diff --git a/trunk/arch/m68k/include/asm/statfs.h b/trunk/arch/m68k/include/asm/statfs.h new file mode 100644 index 000000000000..08d93f14e061 --- /dev/null +++ b/trunk/arch/m68k/include/asm/statfs.h @@ -0,0 +1,6 @@ +#ifndef _M68K_STATFS_H +#define _M68K_STATFS_H + +#include + +#endif /* _M68K_STATFS_H */ diff --git a/trunk/arch/m68k/include/asm/topology.h b/trunk/arch/m68k/include/asm/topology.h new file mode 100644 index 000000000000..ca173e9f26ff --- /dev/null +++ b/trunk/arch/m68k/include/asm/topology.h @@ -0,0 +1,6 @@ +#ifndef _ASM_M68K_TOPOLOGY_H +#define _ASM_M68K_TOPOLOGY_H + +#include + +#endif /* _ASM_M68K_TOPOLOGY_H */ diff --git a/trunk/arch/m68k/include/asm/types.h b/trunk/arch/m68k/include/asm/types.h new file mode 100644 index 000000000000..89705adcbd52 --- /dev/null +++ b/trunk/arch/m68k/include/asm/types.h @@ -0,0 +1,22 @@ +#ifndef _M68K_TYPES_H +#define _M68K_TYPES_H + +/* + * This file is never included by application software unless + * explicitly requested (e.g., via linux/types.h) in which case the + * application is Linux specific so (user-) name space pollution is + * not a major issue. However, for interoperability, libraries still + * need to be careful to avoid a name clashes. + */ +#include + +/* + * These aren't exported outside the kernel to avoid name space clashes + */ +#ifdef __KERNEL__ + +#define BITS_PER_LONG 32 + +#endif /* __KERNEL__ */ + +#endif /* _M68K_TYPES_H */ diff --git a/trunk/arch/m68k/include/asm/unaligned.h b/trunk/arch/m68k/include/asm/unaligned.h index 2b3ca0bf7a0d..f4043ae63db1 100644 --- a/trunk/arch/m68k/include/asm/unaligned.h +++ b/trunk/arch/m68k/include/asm/unaligned.h @@ -2,7 +2,7 @@ #define _ASM_M68K_UNALIGNED_H -#ifdef CONFIG_CPU_HAS_NO_UNALIGNED +#if defined(CONFIG_COLDFIRE) || defined(CONFIG_M68000) #include #include #include @@ -12,7 +12,7 @@ #else /* - * The m68k can do unaligned accesses itself. + * The m68k can do unaligned accesses itself. */ #include #include diff --git a/trunk/arch/m68k/include/asm/xor.h b/trunk/arch/m68k/include/asm/xor.h new file mode 100644 index 000000000000..c82eb12a5b18 --- /dev/null +++ b/trunk/arch/m68k/include/asm/xor.h @@ -0,0 +1 @@ +#include diff --git a/trunk/arch/m68k/kernel/pcibios.c b/trunk/arch/m68k/kernel/pcibios.c index 73fa0b56a06c..b2988aa1840b 100644 --- a/trunk/arch/m68k/kernel/pcibios.c +++ b/trunk/arch/m68k/kernel/pcibios.c @@ -87,6 +87,11 @@ int pcibios_enable_device(struct pci_dev *dev, int mask) return 0; } +void pcibios_update_irq(struct pci_dev *dev, int irq) +{ + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq); +} + void __devinit pcibios_fixup_bus(struct pci_bus *bus) { struct pci_dev *dev; diff --git a/trunk/arch/m68k/kernel/process.c b/trunk/arch/m68k/kernel/process.c index ac2892e49c7c..c488e3cfab53 100644 --- a/trunk/arch/m68k/kernel/process.c +++ b/trunk/arch/m68k/kernel/process.c @@ -25,7 +25,6 @@ #include #include #include -#include #include #include @@ -76,10 +75,8 @@ void cpu_idle(void) { /* endless idle loop with no priority at all */ while (1) { - rcu_idle_enter(); while (!need_resched()) idle(); - rcu_idle_exit(); schedule_preempt_disabled(); } } diff --git a/trunk/arch/m68k/kernel/setup_no.c b/trunk/arch/m68k/kernel/setup_no.c index 71fb29938dba..7dc186b7a85f 100644 --- a/trunk/arch/m68k/kernel/setup_no.c +++ b/trunk/arch/m68k/kernel/setup_no.c @@ -218,10 +218,13 @@ void __init setup_arch(char **cmdline_p) printk(KERN_INFO "Motorola M5235EVB support (C)2005 Syn-tech Systems, Inc. (Jate Sujjavanich)\n"); #endif - pr_debug("KERNEL -> TEXT=0x%p-0x%p DATA=0x%p-0x%p BSS=0x%p-0x%p\n", - _stext, _etext, _sdata, _edata, __bss_start, __bss_stop); - pr_debug("MEMORY -> ROMFS=0x%p-0x%06lx MEM=0x%06lx-0x%06lx\n ", - __bss_stop, memory_start, memory_start, memory_end); + pr_debug("KERNEL -> TEXT=0x%06x-0x%06x DATA=0x%06x-0x%06x " + "BSS=0x%06x-0x%06x\n", (int) &_stext, (int) &_etext, + (int) &_sdata, (int) &_edata, + (int) &_sbss, (int) &_ebss); + pr_debug("MEMORY -> ROMFS=0x%06x-0x%06x MEM=0x%06x-0x%06x\n ", + (int) &_ebss, (int) memory_start, + (int) memory_start, (int) memory_end); /* Keep a copy of command line */ *cmdline_p = &command_line[0]; diff --git a/trunk/arch/m68k/kernel/sys_m68k.c b/trunk/arch/m68k/kernel/sys_m68k.c index 9a5932ec3689..8623f8dc16f8 100644 --- a/trunk/arch/m68k/kernel/sys_m68k.c +++ b/trunk/arch/m68k/kernel/sys_m68k.c @@ -479,13 +479,9 @@ sys_atomic_cmpxchg_32(unsigned long newval, int oldval, int d3, int d4, int d5, goto bad_access; } - /* - * No need to check for EFAULT; we know that the page is - * present and writable. - */ - __get_user(mem_value, mem); + mem_value = *mem; if (mem_value == oldval) - __put_user(newval, mem); + *mem = newval; pte_unmap_unlock(pte, ptl); up_read(&mm->mmap_sem); diff --git a/trunk/arch/m68k/kernel/vmlinux-nommu.lds b/trunk/arch/m68k/kernel/vmlinux-nommu.lds index 06a763f49fd3..40e02d9c38b4 100644 --- a/trunk/arch/m68k/kernel/vmlinux-nommu.lds +++ b/trunk/arch/m68k/kernel/vmlinux-nommu.lds @@ -78,7 +78,9 @@ SECTIONS { __init_end = .; } + _sbss = .; BSS_SECTION(0, 0, 0) + _ebss = .; _end = .; diff --git a/trunk/arch/m68k/kernel/vmlinux-std.lds b/trunk/arch/m68k/kernel/vmlinux-std.lds index d0993594f558..63407c836826 100644 --- a/trunk/arch/m68k/kernel/vmlinux-std.lds +++ b/trunk/arch/m68k/kernel/vmlinux-std.lds @@ -31,7 +31,9 @@ SECTIONS RW_DATA_SECTION(16, PAGE_SIZE, THREAD_SIZE) + _sbss = .; BSS_SECTION(0, 0, 0) + _ebss = .; _edata = .; /* End of data section */ diff --git a/trunk/arch/m68k/kernel/vmlinux-sun3.lds b/trunk/arch/m68k/kernel/vmlinux-sun3.lds index 8080469ee6c1..ad0f46d64c0b 100644 --- a/trunk/arch/m68k/kernel/vmlinux-sun3.lds +++ b/trunk/arch/m68k/kernel/vmlinux-sun3.lds @@ -44,7 +44,9 @@ __init_begin = .; . = ALIGN(PAGE_SIZE); __init_end = .; + _sbss = .; BSS_SECTION(0, 0, 0) + _ebss = .; _end = . ; diff --git a/trunk/arch/m68k/lib/muldi3.c b/trunk/arch/m68k/lib/muldi3.c index ee5f0b1b5c5d..79e928a525d0 100644 --- a/trunk/arch/m68k/lib/muldi3.c +++ b/trunk/arch/m68k/lib/muldi3.c @@ -19,7 +19,7 @@ along with GNU CC; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#ifdef CONFIG_CPU_HAS_NO_MULDIV64 +#if defined(CONFIG_M68000) || defined(CONFIG_COLDFIRE) #define SI_TYPE_SIZE 32 #define __BITS4 (SI_TYPE_SIZE / 4) diff --git a/trunk/arch/m68k/mm/init_mm.c b/trunk/arch/m68k/mm/init_mm.c index 282f9de68966..f77f258dce3a 100644 --- a/trunk/arch/m68k/mm/init_mm.c +++ b/trunk/arch/m68k/mm/init_mm.c @@ -104,7 +104,7 @@ void __init print_memmap(void) MLK_ROUNDUP(__init_begin, __init_end), MLK_ROUNDUP(_stext, _etext), MLK_ROUNDUP(_sdata, _edata), - MLK_ROUNDUP(__bss_start, __bss_stop)); + MLK_ROUNDUP(_sbss, _ebss)); } void __init mem_init(void) diff --git a/trunk/arch/m68k/mm/init_no.c b/trunk/arch/m68k/mm/init_no.c index 688e3664aea0..345ec0d83e3d 100644 --- a/trunk/arch/m68k/mm/init_no.c +++ b/trunk/arch/m68k/mm/init_no.c @@ -91,7 +91,7 @@ void __init mem_init(void) totalram_pages = free_all_bootmem(); codek = (_etext - _stext) >> 10; - datak = (__bss_stop - _sdata) >> 10; + datak = (_ebss - _sdata) >> 10; initk = (__init_begin - __init_end) >> 10; tmp = nr_free_pages() << PAGE_SHIFT; diff --git a/trunk/arch/m68k/platform/68328/head-de2.S b/trunk/arch/m68k/platform/68328/head-de2.S index 537d3245b539..f632fdcb93e9 100644 --- a/trunk/arch/m68k/platform/68328/head-de2.S +++ b/trunk/arch/m68k/platform/68328/head-de2.S @@ -60,8 +60,8 @@ _start: * Move ROM filesystem above bss :-) */ - moveal #__bss_start, %a0 /* romfs at the start of bss */ - moveal #__bss_stop, %a1 /* Set up destination */ + moveal #_sbss, %a0 /* romfs at the start of bss */ + moveal #_ebss, %a1 /* Set up destination */ movel %a0, %a2 /* Copy of bss start */ movel 8(%a0), %d1 /* Get size of ROMFS */ @@ -84,8 +84,8 @@ _start: * Initialize BSS segment to 0 */ - lea __bss_start, %a0 - lea __bss_stop, %a1 + lea _sbss, %a0 + lea _ebss, %a1 /* Copy 0 to %a0 until %a0 == %a1 */ 2: cmpal %a0, %a1 diff --git a/trunk/arch/m68k/platform/68328/head-pilot.S b/trunk/arch/m68k/platform/68328/head-pilot.S index 45a9dad29e3d..2ebfd6420818 100644 --- a/trunk/arch/m68k/platform/68328/head-pilot.S +++ b/trunk/arch/m68k/platform/68328/head-pilot.S @@ -110,7 +110,7 @@ L0: movel #CONFIG_VECTORBASE, %d7 addl #16, %d7 moveal %d7, %a0 - moveal #__bss_stop, %a1 + moveal #_ebss, %a1 lea %a1@(512), %a2 DBG_PUTC('C') @@ -138,8 +138,8 @@ LD1: DBG_PUTC('E') - moveal #__bss_start, %a0 - moveal #__bss_stop, %a1 + moveal #_sbss, %a0 + moveal #_ebss, %a1 /* Copy 0 to %a0 until %a0 == %a1 */ L1: @@ -150,7 +150,7 @@ L1: DBG_PUTC('F') /* Copy command line from end of bss to command line */ - moveal #__bss_stop, %a0 + moveal #_ebss, %a0 moveal #command_line, %a1 lea %a1@(512), %a2 @@ -165,7 +165,7 @@ L3: movel #_sdata, %d0 movel %d0, _rambase - movel #__bss_stop, %d0 + movel #_ebss, %d0 movel %d0, _ramstart movel %a4, %d0 diff --git a/trunk/arch/m68k/platform/68328/head-ram.S b/trunk/arch/m68k/platform/68328/head-ram.S index 5189ef926098..7f1aeeacb219 100644 --- a/trunk/arch/m68k/platform/68328/head-ram.S +++ b/trunk/arch/m68k/platform/68328/head-ram.S @@ -76,8 +76,8 @@ pclp3: beq pclp3 #endif /* DEBUG */ moveal #0x007ffff0, %ssp - moveal #__bss_start, %a0 - moveal #__bss_stop, %a1 + moveal #_sbss, %a0 + moveal #_ebss, %a1 /* Copy 0 to %a0 until %a0 >= %a1 */ L1: diff --git a/trunk/arch/m68k/platform/68328/head-rom.S b/trunk/arch/m68k/platform/68328/head-rom.S index 3dff98ba2e97..a5ff96d0295f 100644 --- a/trunk/arch/m68k/platform/68328/head-rom.S +++ b/trunk/arch/m68k/platform/68328/head-rom.S @@ -59,8 +59,8 @@ _stext: movew #0x2700,%sr cmpal %a1, %a2 bhi 1b - moveal #__bss_start, %a0 - moveal #__bss_stop, %a1 + moveal #_sbss, %a0 + moveal #_ebss, %a1 /* Copy 0 to %a0 until %a0 == %a1 */ 1: @@ -70,7 +70,7 @@ _stext: movew #0x2700,%sr movel #_sdata, %d0 movel %d0, _rambase - movel #__bss_stop, %d0 + movel #_ebss, %d0 movel %d0, _ramstart movel #RAMEND-CONFIG_MEMORY_RESERVE*0x100000, %d0 movel %d0, _ramend diff --git a/trunk/arch/m68k/platform/68360/head-ram.S b/trunk/arch/m68k/platform/68360/head-ram.S index acd213170d80..8eb94fb6b971 100644 --- a/trunk/arch/m68k/platform/68360/head-ram.S +++ b/trunk/arch/m68k/platform/68360/head-ram.S @@ -219,8 +219,8 @@ LD1: cmp.l #_edata, %a1 blt LD1 - moveal #__bss_start, %a0 - moveal #__bss_stop, %a1 + moveal #_sbss, %a0 + moveal #_ebss, %a1 /* Copy 0 to %a0 until %a0 == %a1 */ L1: @@ -234,7 +234,7 @@ load_quicc: store_ram_size: /* Set ram size information */ move.l #_sdata, _rambase - move.l #__bss_stop, _ramstart + move.l #_ebss, _ramstart move.l #RAMEND, %d0 sub.l #0x1000, %d0 /* Reserve 4K for stack space.*/ move.l %d0, _ramend /* Different from RAMEND.*/ diff --git a/trunk/arch/m68k/platform/68360/head-rom.S b/trunk/arch/m68k/platform/68360/head-rom.S index dfc756d99886..97510e55b802 100644 --- a/trunk/arch/m68k/platform/68360/head-rom.S +++ b/trunk/arch/m68k/platform/68360/head-rom.S @@ -13,7 +13,7 @@ */ .global _stext -.global __bss_start +.global _sbss .global _start .global _rambase @@ -229,8 +229,8 @@ LD1: cmp.l #_edata, %a1 blt LD1 - moveal #__bss_start, %a0 - moveal #__bss_stop, %a1 + moveal #_sbss, %a0 + moveal #_ebss, %a1 /* Copy 0 to %a0 until %a0 == %a1 */ L1: @@ -244,7 +244,7 @@ load_quicc: store_ram_size: /* Set ram size information */ move.l #_sdata, _rambase - move.l #__bss_stop, _ramstart + move.l #_ebss, _ramstart move.l #RAMEND, %d0 sub.l #0x1000, %d0 /* Reserve 4K for stack space.*/ move.l %d0, _ramend /* Different from RAMEND.*/ diff --git a/trunk/arch/m68k/platform/coldfire/clk.c b/trunk/arch/m68k/platform/coldfire/clk.c index 9cd13b4ce42b..75f9ee967ea7 100644 --- a/trunk/arch/m68k/platform/coldfire/clk.c +++ b/trunk/arch/m68k/platform/coldfire/clk.c @@ -146,3 +146,9 @@ struct clk_ops clk_ops1 = { }; #endif /* MCFPM_PPMCR1 */ #endif /* MCFPM_PPMCR0 */ + +struct clk *devm_clk_get(struct device *dev, const char *id) +{ + return NULL; +} +EXPORT_SYMBOL(devm_clk_get); diff --git a/trunk/arch/m68k/platform/coldfire/head.S b/trunk/arch/m68k/platform/coldfire/head.S index b88f5716f357..4e0c9eb3bd1f 100644 --- a/trunk/arch/m68k/platform/coldfire/head.S +++ b/trunk/arch/m68k/platform/coldfire/head.S @@ -230,8 +230,8 @@ _vstart: /* * Move ROM filesystem above bss :-) */ - lea __bss_start,%a0 /* get start of bss */ - lea __bss_stop,%a1 /* set up destination */ + lea _sbss,%a0 /* get start of bss */ + lea _ebss,%a1 /* set up destination */ movel %a0,%a2 /* copy of bss start */ movel 8(%a0),%d0 /* get size of ROMFS */ @@ -249,7 +249,7 @@ _copy_romfs: bne _copy_romfs #else /* CONFIG_ROMFS_FS */ - lea __bss_stop,%a1 + lea _ebss,%a1 movel %a1,_ramstart #endif /* CONFIG_ROMFS_FS */ @@ -257,8 +257,8 @@ _copy_romfs: /* * Zero out the bss region. */ - lea __bss_start,%a0 /* get start of bss */ - lea __bss_stop,%a1 /* get end of bss */ + lea _sbss,%a0 /* get start of bss */ + lea _ebss,%a1 /* get end of bss */ clrl %d0 /* set value */ _clear_bss: movel %d0,(%a0)+ /* clear each word */ diff --git a/trunk/arch/m68k/sun3/prom/init.c b/trunk/arch/m68k/sun3/prom/init.c index eeba067d565f..d8e6349336b4 100644 --- a/trunk/arch/m68k/sun3/prom/init.c +++ b/trunk/arch/m68k/sun3/prom/init.c @@ -22,13 +22,57 @@ int prom_root_node; struct linux_nodeops *prom_nodeops; /* You must call prom_init() before you attempt to use any of the - * routines in the prom library. - * It gets passed the pointer to the PROM vector. + * routines in the prom library. It returns 0 on success, 1 on + * failure. It gets passed the pointer to the PROM vector. */ +extern void prom_meminit(void); +extern void prom_ranges_init(void); + void __init prom_init(struct linux_romvec *rp) { romvec = rp; +#ifndef CONFIG_SUN3 + switch(romvec->pv_romvers) { + case 0: + prom_vers = PROM_V0; + break; + case 2: + prom_vers = PROM_V2; + break; + case 3: + prom_vers = PROM_V3; + break; + case 4: + prom_vers = PROM_P1275; + prom_printf("PROMLIB: Sun IEEE Prom not supported yet\n"); + prom_halt(); + break; + default: + prom_printf("PROMLIB: Bad PROM version %d\n", + romvec->pv_romvers); + prom_halt(); + break; + }; + + prom_rev = romvec->pv_plugin_revision; + prom_prev = romvec->pv_printrev; + prom_nodeops = romvec->pv_nodeops; + + prom_root_node = prom_getsibling(0); + if((prom_root_node == 0) || (prom_root_node == -1)) + prom_halt(); + + if((((unsigned long) prom_nodeops) == 0) || + (((unsigned long) prom_nodeops) == -1)) + prom_halt(); + + prom_meminit(); + + prom_ranges_init(); +#endif +// printk("PROMLIB: Sun Boot Prom Version %d Revision %d\n", +// romvec->pv_romvers, prom_rev); /* Initialization successful. */ return; diff --git a/trunk/arch/microblaze/include/asm/sections.h b/trunk/arch/microblaze/include/asm/sections.h index c07ed5d2a820..4487e150b455 100644 --- a/trunk/arch/microblaze/include/asm/sections.h +++ b/trunk/arch/microblaze/include/asm/sections.h @@ -18,6 +18,10 @@ extern char _ssbss[], _esbss[]; extern unsigned long __ivt_start[], __ivt_end[]; extern char _etext[], _stext[]; +# ifdef CONFIG_MTD_UCLINUX +extern char *_ebss; +# endif + extern u32 _fdt_start[], _fdt_end[]; # endif /* !__ASSEMBLY__ */ diff --git a/trunk/arch/microblaze/kernel/microblaze_ksyms.c b/trunk/arch/microblaze/kernel/microblaze_ksyms.c index 2b25bcf05c00..bb4907c828dc 100644 --- a/trunk/arch/microblaze/kernel/microblaze_ksyms.c +++ b/trunk/arch/microblaze/kernel/microblaze_ksyms.c @@ -21,6 +21,9 @@ #include #include +extern char *_ebss; +EXPORT_SYMBOL_GPL(_ebss); + #ifdef CONFIG_FUNCTION_TRACER extern void _mcount(void); EXPORT_SYMBOL(_mcount); diff --git a/trunk/arch/microblaze/kernel/setup.c b/trunk/arch/microblaze/kernel/setup.c index 4da971d4392f..16d8dfd9094b 100644 --- a/trunk/arch/microblaze/kernel/setup.c +++ b/trunk/arch/microblaze/kernel/setup.c @@ -121,7 +121,7 @@ void __init machine_early_init(const char *cmdline, unsigned int ram, /* Move ROMFS out of BSS before clearing it */ if (romfs_size > 0) { - memmove(&__bss_stop, (int *)romfs_base, romfs_size); + memmove(&_ebss, (int *)romfs_base, romfs_size); klimit += romfs_size; } #endif @@ -165,7 +165,7 @@ void __init machine_early_init(const char *cmdline, unsigned int ram, BUG_ON(romfs_size < 0); /* What else can we do? */ printk("Moved 0x%08x bytes from 0x%08x to 0x%08x\n", - romfs_size, romfs_base, (unsigned)&__bss_stop); + romfs_size, romfs_base, (unsigned)&_ebss); printk("New klimit: 0x%08x\n", (unsigned)klimit); #endif diff --git a/trunk/arch/microblaze/kernel/vmlinux.lds.S b/trunk/arch/microblaze/kernel/vmlinux.lds.S index 936d01a689d7..109e9d86ade4 100644 --- a/trunk/arch/microblaze/kernel/vmlinux.lds.S +++ b/trunk/arch/microblaze/kernel/vmlinux.lds.S @@ -131,6 +131,7 @@ SECTIONS { *(COMMON) . = ALIGN (4) ; __bss_stop = . ; + _ebss = . ; } . = ALIGN(PAGE_SIZE); _end = .; diff --git a/trunk/arch/mips/Kconfig b/trunk/arch/mips/Kconfig index faf65286574e..331d574df99c 100644 --- a/trunk/arch/mips/Kconfig +++ b/trunk/arch/mips/Kconfig @@ -89,7 +89,6 @@ config ATH79 select CEVT_R4K select CSRC_R4K select DMA_NONCOHERENT - select HAVE_CLK select IRQ_CPU select MIPS_MACHINE select SYS_HAS_CPU_MIPS32_R2 diff --git a/trunk/arch/mips/alchemy/board-mtx1.c b/trunk/arch/mips/alchemy/board-mtx1.c index a124c251c0c9..99969484c475 100644 --- a/trunk/arch/mips/alchemy/board-mtx1.c +++ b/trunk/arch/mips/alchemy/board-mtx1.c @@ -228,8 +228,6 @@ static int mtx1_pci_idsel(unsigned int devsel, int assert) * adapter on the mtx-1 "singleboard" variant. It triggers a custom * logic chip connected to EXT_IO3 (GPIO1) to suppress IDSEL signals. */ - udelay(1); - if (assert && devsel != 0) /* Suppress signal to Cardbus */ alchemy_gpio_set_value(1, 0); /* set EXT_IO3 OFF */ diff --git a/trunk/arch/mips/ath79/dev-usb.c b/trunk/arch/mips/ath79/dev-usb.c index b2a2311ec85b..36e9570e7bc4 100644 --- a/trunk/arch/mips/ath79/dev-usb.c +++ b/trunk/arch/mips/ath79/dev-usb.c @@ -145,8 +145,6 @@ static void __init ar7240_usb_setup(void) ath79_ohci_resources[0].start = AR7240_OHCI_BASE; ath79_ohci_resources[0].end = AR7240_OHCI_BASE + AR7240_OHCI_SIZE - 1; - ath79_ohci_resources[1].start = ATH79_CPU_IRQ_USB; - ath79_ohci_resources[1].end = ATH79_CPU_IRQ_USB; platform_device_register(&ath79_ohci_device); } diff --git a/trunk/arch/mips/ath79/gpio.c b/trunk/arch/mips/ath79/gpio.c index 48fe762d2526..29054f211832 100644 --- a/trunk/arch/mips/ath79/gpio.c +++ b/trunk/arch/mips/ath79/gpio.c @@ -188,10 +188,8 @@ void __init ath79_gpio_init(void) if (soc_is_ar71xx()) ath79_gpio_count = AR71XX_GPIO_COUNT; - else if (soc_is_ar7240()) - ath79_gpio_count = AR7240_GPIO_COUNT; - else if (soc_is_ar7241() || soc_is_ar7242()) - ath79_gpio_count = AR7241_GPIO_COUNT; + else if (soc_is_ar724x()) + ath79_gpio_count = AR724X_GPIO_COUNT; else if (soc_is_ar913x()) ath79_gpio_count = AR913X_GPIO_COUNT; else if (soc_is_ar933x()) diff --git a/trunk/arch/mips/bcm63xx/dev-spi.c b/trunk/arch/mips/bcm63xx/dev-spi.c index f1c9c3e2f678..e39f73048d4f 100644 --- a/trunk/arch/mips/bcm63xx/dev-spi.c +++ b/trunk/arch/mips/bcm63xx/dev-spi.c @@ -106,15 +106,11 @@ int __init bcm63xx_spi_register(void) if (BCMCPU_IS_6338() || BCMCPU_IS_6348()) { spi_resources[0].end += BCM_6338_RSET_SPI_SIZE - 1; spi_pdata.fifo_size = SPI_6338_MSG_DATA_SIZE; - spi_pdata.msg_type_shift = SPI_6338_MSG_TYPE_SHIFT; - spi_pdata.msg_ctl_width = SPI_6338_MSG_CTL_WIDTH; } if (BCMCPU_IS_6358() || BCMCPU_IS_6368()) { spi_resources[0].end += BCM_6358_RSET_SPI_SIZE - 1; spi_pdata.fifo_size = SPI_6358_MSG_DATA_SIZE; - spi_pdata.msg_type_shift = SPI_6358_MSG_TYPE_SHIFT; - spi_pdata.msg_ctl_width = SPI_6358_MSG_CTL_WIDTH; } bcm63xx_spi_regs_init(); diff --git a/trunk/arch/mips/cavium-octeon/octeon-irq.c b/trunk/arch/mips/cavium-octeon/octeon-irq.c index 274cd4fad30c..7fb1f222b8a5 100644 --- a/trunk/arch/mips/cavium-octeon/octeon-irq.c +++ b/trunk/arch/mips/cavium-octeon/octeon-irq.c @@ -61,12 +61,6 @@ static void octeon_irq_set_ciu_mapping(int irq, int line, int bit, octeon_irq_ciu_to_irq[line][bit] = irq; } -static void octeon_irq_force_ciu_mapping(struct irq_domain *domain, - int irq, int line, int bit) -{ - irq_domain_associate(domain, irq, line << 6 | bit); -} - static int octeon_coreid_for_cpu(int cpu) { #ifdef CONFIG_SMP @@ -189,9 +183,19 @@ static void __init octeon_irq_init_core(void) mutex_init(&cd->core_irq_mutex); irq = OCTEON_IRQ_SW0 + i; - irq_set_chip_data(irq, cd); - irq_set_chip_and_handler(irq, &octeon_irq_chip_core, - handle_percpu_irq); + switch (irq) { + case OCTEON_IRQ_TIMER: + case OCTEON_IRQ_SW0: + case OCTEON_IRQ_SW1: + case OCTEON_IRQ_5: + case OCTEON_IRQ_PERF: + irq_set_chip_data(irq, cd); + irq_set_chip_and_handler(irq, &octeon_irq_chip_core, + handle_percpu_irq); + break; + default: + break; + } } } @@ -886,6 +890,7 @@ static int octeon_irq_gpio_xlat(struct irq_domain *d, unsigned int type; unsigned int pin; unsigned int trigger; + struct octeon_irq_gpio_domain_data *gpiod; if (d->of_node != node) return -EINVAL; @@ -920,7 +925,8 @@ static int octeon_irq_gpio_xlat(struct irq_domain *d, break; } *out_type = type; - *out_hwirq = pin; + gpiod = d->host_data; + *out_hwirq = gpiod->base_hwirq + pin; return 0; } @@ -990,21 +996,19 @@ static int octeon_irq_ciu_map(struct irq_domain *d, static int octeon_irq_gpio_map(struct irq_domain *d, unsigned int virq, irq_hw_number_t hw) { - struct octeon_irq_gpio_domain_data *gpiod = d->host_data; - unsigned int line, bit; + unsigned int line = hw >> 6; + unsigned int bit = hw & 63; if (!octeon_irq_virq_in_range(virq)) return -EINVAL; - hw += gpiod->base_hwirq; - line = hw >> 6; - bit = hw & 63; if (line > 1 || octeon_irq_ciu_to_irq[line][bit] != 0) return -EINVAL; octeon_irq_set_ciu_mapping(virq, line, bit, octeon_irq_gpio_chip, octeon_irq_handle_gpio); + return 0; } @@ -1145,7 +1149,6 @@ static void __init octeon_irq_init_ciu(void) struct irq_chip *chip_wd; struct device_node *gpio_node; struct device_node *ciu_node; - struct irq_domain *ciu_domain = NULL; octeon_irq_init_ciu_percpu(); octeon_irq_setup_secondary = octeon_irq_setup_secondary_ciu; @@ -1174,6 +1177,31 @@ static void __init octeon_irq_init_ciu(void) /* Mips internal */ octeon_irq_init_core(); + /* CIU_0 */ + for (i = 0; i < 16; i++) + octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_WORKQ0, 0, i + 0, chip, handle_level_irq); + + octeon_irq_set_ciu_mapping(OCTEON_IRQ_MBOX0, 0, 32, chip_mbox, handle_percpu_irq); + octeon_irq_set_ciu_mapping(OCTEON_IRQ_MBOX1, 0, 33, chip_mbox, handle_percpu_irq); + + for (i = 0; i < 4; i++) + octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_PCI_INT0, 0, i + 36, chip, handle_level_irq); + for (i = 0; i < 4; i++) + octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_PCI_MSI0, 0, i + 40, chip, handle_level_irq); + + octeon_irq_set_ciu_mapping(OCTEON_IRQ_RML, 0, 46, chip, handle_level_irq); + for (i = 0; i < 4; i++) + octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_TIMER0, 0, i + 52, chip, handle_edge_irq); + + octeon_irq_set_ciu_mapping(OCTEON_IRQ_USB0, 0, 56, chip, handle_level_irq); + octeon_irq_set_ciu_mapping(OCTEON_IRQ_BOOTDMA, 0, 63, chip, handle_level_irq); + + /* CIU_1 */ + for (i = 0; i < 16; i++) + octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_WDOG0, 1, i + 0, chip_wd, handle_level_irq); + + octeon_irq_set_ciu_mapping(OCTEON_IRQ_USB1, 1, 17, chip, handle_level_irq); + gpio_node = of_find_compatible_node(NULL, NULL, "cavium,octeon-3860-gpio"); if (gpio_node) { struct octeon_irq_gpio_domain_data *gpiod; @@ -1191,35 +1219,10 @@ static void __init octeon_irq_init_ciu(void) ciu_node = of_find_compatible_node(NULL, NULL, "cavium,octeon-3860-ciu"); if (ciu_node) { - ciu_domain = irq_domain_add_tree(ciu_node, &octeon_irq_domain_ciu_ops, NULL); + irq_domain_add_tree(ciu_node, &octeon_irq_domain_ciu_ops, NULL); of_node_put(ciu_node); } else - panic("Cannot find device node for cavium,octeon-3860-ciu."); - - /* CIU_0 */ - for (i = 0; i < 16; i++) - octeon_irq_force_ciu_mapping(ciu_domain, i + OCTEON_IRQ_WORKQ0, 0, i + 0); - - octeon_irq_set_ciu_mapping(OCTEON_IRQ_MBOX0, 0, 32, chip_mbox, handle_percpu_irq); - octeon_irq_set_ciu_mapping(OCTEON_IRQ_MBOX1, 0, 33, chip_mbox, handle_percpu_irq); - - for (i = 0; i < 4; i++) - octeon_irq_force_ciu_mapping(ciu_domain, i + OCTEON_IRQ_PCI_INT0, 0, i + 36); - for (i = 0; i < 4; i++) - octeon_irq_force_ciu_mapping(ciu_domain, i + OCTEON_IRQ_PCI_MSI0, 0, i + 40); - - octeon_irq_force_ciu_mapping(ciu_domain, OCTEON_IRQ_RML, 0, 46); - for (i = 0; i < 4; i++) - octeon_irq_force_ciu_mapping(ciu_domain, i + OCTEON_IRQ_TIMER0, 0, i + 52); - - octeon_irq_force_ciu_mapping(ciu_domain, OCTEON_IRQ_USB0, 0, 56); - octeon_irq_force_ciu_mapping(ciu_domain, OCTEON_IRQ_BOOTDMA, 0, 63); - - /* CIU_1 */ - for (i = 0; i < 16; i++) - octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_WDOG0, 1, i + 0, chip_wd, handle_level_irq); - - octeon_irq_force_ciu_mapping(ciu_domain, OCTEON_IRQ_USB1, 1, 17); + pr_warn("Cannot find device node for cavium,octeon-3860-ciu.\n"); /* Enable the CIU lines */ set_c0_status(STATUSF_IP3 | STATUSF_IP2); diff --git a/trunk/arch/mips/cavium-octeon/serial.c b/trunk/arch/mips/cavium-octeon/serial.c index 569f41bdcc46..138b2216b4f8 100644 --- a/trunk/arch/mips/cavium-octeon/serial.c +++ b/trunk/arch/mips/cavium-octeon/serial.c @@ -47,40 +47,40 @@ static int __devinit octeon_serial_probe(struct platform_device *pdev) { int irq, res; struct resource *res_mem; - struct uart_8250_port up; + struct uart_port port; /* All adaptors have an irq. */ irq = platform_get_irq(pdev, 0); if (irq < 0) return irq; - memset(&up, 0, sizeof(up)); + memset(&port, 0, sizeof(port)); - up.port.flags = ASYNC_SKIP_TEST | UPF_SHARE_IRQ | UPF_FIXED_TYPE; - up.port.type = PORT_OCTEON; - up.port.iotype = UPIO_MEM; - up.port.regshift = 3; - up.port.dev = &pdev->dev; + port.flags = ASYNC_SKIP_TEST | UPF_SHARE_IRQ | UPF_FIXED_TYPE; + port.type = PORT_OCTEON; + port.iotype = UPIO_MEM; + port.regshift = 3; + port.dev = &pdev->dev; if (octeon_is_simulation()) /* Make simulator output fast*/ - up.port.uartclk = 115200 * 16; + port.uartclk = 115200 * 16; else - up.port.uartclk = octeon_get_io_clock_rate(); + port.uartclk = octeon_get_io_clock_rate(); - up.port.serial_in = octeon_serial_in; - up.port.serial_out = octeon_serial_out; - up.port.irq = irq; + port.serial_in = octeon_serial_in; + port.serial_out = octeon_serial_out; + port.irq = irq; res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (res_mem == NULL) { dev_err(&pdev->dev, "found no memory resource\n"); return -ENXIO; } - up.port.mapbase = res_mem->start; - up.port.membase = ioremap(res_mem->start, resource_size(res_mem)); + port.mapbase = res_mem->start; + port.membase = ioremap(res_mem->start, resource_size(res_mem)); - res = serial8250_register_8250_port(&up); + res = serial8250_register_port(&port); return res >= 0 ? 0 : res; } diff --git a/trunk/arch/mips/include/asm/mach-ath79/ar71xx_regs.h b/trunk/arch/mips/include/asm/mach-ath79/ar71xx_regs.h index dde504477fac..1caa78ad06d5 100644 --- a/trunk/arch/mips/include/asm/mach-ath79/ar71xx_regs.h +++ b/trunk/arch/mips/include/asm/mach-ath79/ar71xx_regs.h @@ -393,8 +393,7 @@ #define AR71XX_GPIO_REG_FUNC 0x28 #define AR71XX_GPIO_COUNT 16 -#define AR7240_GPIO_COUNT 18 -#define AR7241_GPIO_COUNT 20 +#define AR724X_GPIO_COUNT 18 #define AR913X_GPIO_COUNT 22 #define AR933X_GPIO_COUNT 30 #define AR934X_GPIO_COUNT 23 diff --git a/trunk/arch/mips/include/asm/mach-ath79/cpu-feature-overrides.h b/trunk/arch/mips/include/asm/mach-ath79/cpu-feature-overrides.h index 6ddae926bf79..4476fa03bf36 100644 --- a/trunk/arch/mips/include/asm/mach-ath79/cpu-feature-overrides.h +++ b/trunk/arch/mips/include/asm/mach-ath79/cpu-feature-overrides.h @@ -42,6 +42,7 @@ #define cpu_has_mips64r1 0 #define cpu_has_mips64r2 0 +#define cpu_has_dsp 0 #define cpu_has_mipsmt 0 #define cpu_has_64bits 0 diff --git a/trunk/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_spi.h b/trunk/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_spi.h index c9bae1362606..7d98dbe5d4b5 100644 --- a/trunk/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_spi.h +++ b/trunk/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_spi.h @@ -9,8 +9,6 @@ int __init bcm63xx_spi_register(void); struct bcm63xx_spi_pdata { unsigned int fifo_size; - unsigned int msg_type_shift; - unsigned int msg_ctl_width; int bus_num; int num_chipselect; u32 speed_hz; diff --git a/trunk/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h b/trunk/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h index 61f2a2a5099d..4ccc2a748aff 100644 --- a/trunk/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h +++ b/trunk/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h @@ -1054,8 +1054,7 @@ #define SPI_6338_FILL_BYTE 0x07 #define SPI_6338_MSG_TAIL 0x09 #define SPI_6338_RX_TAIL 0x0b -#define SPI_6338_MSG_CTL 0x40 /* 8-bits register */ -#define SPI_6338_MSG_CTL_WIDTH 8 +#define SPI_6338_MSG_CTL 0x40 #define SPI_6338_MSG_DATA 0x41 #define SPI_6338_MSG_DATA_SIZE 0x3f #define SPI_6338_RX_DATA 0x80 @@ -1071,8 +1070,7 @@ #define SPI_6348_FILL_BYTE 0x07 #define SPI_6348_MSG_TAIL 0x09 #define SPI_6348_RX_TAIL 0x0b -#define SPI_6348_MSG_CTL 0x40 /* 8-bits register */ -#define SPI_6348_MSG_CTL_WIDTH 8 +#define SPI_6348_MSG_CTL 0x40 #define SPI_6348_MSG_DATA 0x41 #define SPI_6348_MSG_DATA_SIZE 0x3f #define SPI_6348_RX_DATA 0x80 @@ -1080,7 +1078,6 @@ /* BCM 6358 SPI core */ #define SPI_6358_MSG_CTL 0x00 /* 16-bits register */ -#define SPI_6358_MSG_CTL_WIDTH 16 #define SPI_6358_MSG_DATA 0x02 #define SPI_6358_MSG_DATA_SIZE 0x21e #define SPI_6358_RX_DATA 0x400 @@ -1097,7 +1094,6 @@ /* BCM 6358 SPI core */ #define SPI_6368_MSG_CTL 0x00 /* 16-bits register */ -#define SPI_6368_MSG_CTL_WIDTH 16 #define SPI_6368_MSG_DATA 0x02 #define SPI_6368_MSG_DATA_SIZE 0x21e #define SPI_6368_RX_DATA 0x400 @@ -1119,10 +1115,7 @@ #define SPI_HD_W 0x01 #define SPI_HD_R 0x02 #define SPI_BYTE_CNT_SHIFT 0 -#define SPI_6338_MSG_TYPE_SHIFT 6 -#define SPI_6348_MSG_TYPE_SHIFT 6 -#define SPI_6358_MSG_TYPE_SHIFT 14 -#define SPI_6368_MSG_TYPE_SHIFT 14 +#define SPI_MSG_TYPE_SHIFT 14 /* Command */ #define SPI_CMD_NOOP 0x00 diff --git a/trunk/arch/mips/include/asm/mach-cavium-octeon/irq.h b/trunk/arch/mips/include/asm/mach-cavium-octeon/irq.h index c22a3078bf11..418992042f6f 100644 --- a/trunk/arch/mips/include/asm/mach-cavium-octeon/irq.h +++ b/trunk/arch/mips/include/asm/mach-cavium-octeon/irq.h @@ -21,10 +21,14 @@ enum octeon_irq { OCTEON_IRQ_TIMER, /* sources in CIU_INTX_EN0 */ OCTEON_IRQ_WORKQ0, - OCTEON_IRQ_WDOG0 = OCTEON_IRQ_WORKQ0 + 16, + OCTEON_IRQ_GPIO0 = OCTEON_IRQ_WORKQ0 + 16, + OCTEON_IRQ_WDOG0 = OCTEON_IRQ_GPIO0 + 16, OCTEON_IRQ_WDOG15 = OCTEON_IRQ_WDOG0 + 15, OCTEON_IRQ_MBOX0 = OCTEON_IRQ_WDOG0 + 16, OCTEON_IRQ_MBOX1, + OCTEON_IRQ_UART0, + OCTEON_IRQ_UART1, + OCTEON_IRQ_UART2, OCTEON_IRQ_PCI_INT0, OCTEON_IRQ_PCI_INT1, OCTEON_IRQ_PCI_INT2, @@ -34,6 +38,8 @@ enum octeon_irq { OCTEON_IRQ_PCI_MSI2, OCTEON_IRQ_PCI_MSI3, + OCTEON_IRQ_TWSI, + OCTEON_IRQ_TWSI2, OCTEON_IRQ_RML, OCTEON_IRQ_TIMER0, OCTEON_IRQ_TIMER1, @@ -41,6 +47,8 @@ enum octeon_irq { OCTEON_IRQ_TIMER3, OCTEON_IRQ_USB0, OCTEON_IRQ_USB1, + OCTEON_IRQ_MII0, + OCTEON_IRQ_MII1, OCTEON_IRQ_BOOTDMA, #ifndef CONFIG_PCI_MSI OCTEON_IRQ_LAST = 127 diff --git a/trunk/arch/mips/include/asm/module.h b/trunk/arch/mips/include/asm/module.h index dca8bce8c7ab..7531ecd654d6 100644 --- a/trunk/arch/mips/include/asm/module.h +++ b/trunk/arch/mips/include/asm/module.h @@ -10,7 +10,6 @@ struct mod_arch_specific { struct list_head dbe_list; const struct exception_table_entry *dbe_start; const struct exception_table_entry *dbe_end; - struct mips_hi16 *r_mips_hi16_list; }; typedef uint8_t Elf64_Byte; /* Type for a 8-bit quantity. */ diff --git a/trunk/arch/mips/include/asm/r4k-timer.h b/trunk/arch/mips/include/asm/r4k-timer.h index afe9e0e03fe9..a37d12b3b61c 100644 --- a/trunk/arch/mips/include/asm/r4k-timer.h +++ b/trunk/arch/mips/include/asm/r4k-timer.h @@ -12,16 +12,16 @@ #ifdef CONFIG_SYNC_R4K -extern void synchronise_count_master(int cpu); -extern void synchronise_count_slave(int cpu); +extern void synchronise_count_master(void); +extern void synchronise_count_slave(void); #else -static inline void synchronise_count_master(int cpu) +static inline void synchronise_count_master(void) { } -static inline void synchronise_count_slave(int cpu) +static inline void synchronise_count_slave(void) { } diff --git a/trunk/arch/mips/kernel/module.c b/trunk/arch/mips/kernel/module.c index 4f8c3cba8c0c..a5066b1c3de3 100644 --- a/trunk/arch/mips/kernel/module.c +++ b/trunk/arch/mips/kernel/module.c @@ -39,6 +39,8 @@ struct mips_hi16 { Elf_Addr value; }; +static struct mips_hi16 *mips_hi16_list; + static LIST_HEAD(dbe_list); static DEFINE_SPINLOCK(dbe_lock); @@ -126,8 +128,8 @@ static int apply_r_mips_hi16_rel(struct module *me, u32 *location, Elf_Addr v) n->addr = (Elf_Addr *)location; n->value = v; - n->next = me->arch.r_mips_hi16_list; - me->arch.r_mips_hi16_list = n; + n->next = mips_hi16_list; + mips_hi16_list = n; return 0; } @@ -140,28 +142,18 @@ static int apply_r_mips_hi16_rela(struct module *me, u32 *location, Elf_Addr v) return 0; } -static void free_relocation_chain(struct mips_hi16 *l) -{ - struct mips_hi16 *next; - - while (l) { - next = l->next; - kfree(l); - l = next; - } -} - static int apply_r_mips_lo16_rel(struct module *me, u32 *location, Elf_Addr v) { unsigned long insnlo = *location; - struct mips_hi16 *l; Elf_Addr val, vallo; /* Sign extend the addend we extract from the lo insn. */ vallo = ((insnlo & 0xffff) ^ 0x8000) - 0x8000; - if (me->arch.r_mips_hi16_list != NULL) { - l = me->arch.r_mips_hi16_list; + if (mips_hi16_list != NULL) { + struct mips_hi16 *l; + + l = mips_hi16_list; while (l != NULL) { struct mips_hi16 *next; unsigned long insn; @@ -196,7 +188,7 @@ static int apply_r_mips_lo16_rel(struct module *me, u32 *location, Elf_Addr v) l = next; } - me->arch.r_mips_hi16_list = NULL; + mips_hi16_list = NULL; } /* @@ -209,9 +201,6 @@ static int apply_r_mips_lo16_rel(struct module *me, u32 *location, Elf_Addr v) return 0; out_danger: - free_relocation_chain(l); - me->arch.r_mips_hi16_list = NULL; - pr_err("module %s: dangerous R_MIPS_LO16 REL relocation\n", me->name); return -ENOEXEC; @@ -284,7 +273,6 @@ int apply_relocate(Elf_Shdr *sechdrs, const char *strtab, pr_debug("Applying relocate section %u to %u\n", relsec, sechdrs[relsec].sh_info); - me->arch.r_mips_hi16_list = NULL; for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) { /* This is where to make the change */ location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr @@ -308,19 +296,6 @@ int apply_relocate(Elf_Shdr *sechdrs, const char *strtab, return res; } - /* - * Normally the hi16 list should be deallocated at this point. A - * malformed binary however could contain a series of R_MIPS_HI16 - * relocations not followed by a R_MIPS_LO16 relocation. In that - * case, free up the list and return an error. - */ - if (me->arch.r_mips_hi16_list) { - free_relocation_chain(me->arch.r_mips_hi16_list); - me->arch.r_mips_hi16_list = NULL; - - return -ENOEXEC; - } - return 0; } diff --git a/trunk/arch/mips/kernel/smp-cmp.c b/trunk/arch/mips/kernel/smp-cmp.c index afc379ca3753..e7e03ecf5495 100644 --- a/trunk/arch/mips/kernel/smp-cmp.c +++ b/trunk/arch/mips/kernel/smp-cmp.c @@ -102,7 +102,7 @@ static void cmp_init_secondary(void) c->vpe_id = (read_c0_tcbind() >> TCBIND_CURVPE_SHIFT) & TCBIND_CURVPE; #endif #ifdef CONFIG_MIPS_MT_SMTC - c->tc_id = (read_c0_tcbind() & TCBIND_CURTC) >> TCBIND_CURTC_SHIFT; + c->tc_id = (read_c0_tcbind() >> TCBIND_CURTC_SHIFT) & TCBIND_CURTC; #endif } diff --git a/trunk/arch/mips/kernel/smp.c b/trunk/arch/mips/kernel/smp.c index 9005bf9fb859..31637d8c8738 100644 --- a/trunk/arch/mips/kernel/smp.c +++ b/trunk/arch/mips/kernel/smp.c @@ -130,7 +130,7 @@ asmlinkage __cpuinit void start_secondary(void) cpu_set(cpu, cpu_callin_map); - synchronise_count_slave(cpu); + synchronise_count_slave(); /* * irq will be enabled in ->smp_finish(), enabling it too early @@ -173,6 +173,7 @@ void smp_send_stop(void) void __init smp_cpus_done(unsigned int max_cpus) { mp_ops->cpus_done(); + synchronise_count_master(); } /* called from main before smp_init() */ @@ -205,7 +206,6 @@ int __cpuinit __cpu_up(unsigned int cpu, struct task_struct *tidle) while (!cpu_isset(cpu, cpu_callin_map)) udelay(100); - synchronise_count_master(cpu); return 0; } diff --git a/trunk/arch/mips/kernel/sync-r4k.c b/trunk/arch/mips/kernel/sync-r4k.c index 7f1eca3858de..842d55e411fd 100644 --- a/trunk/arch/mips/kernel/sync-r4k.c +++ b/trunk/arch/mips/kernel/sync-r4k.c @@ -28,11 +28,12 @@ static atomic_t __cpuinitdata count_reference = ATOMIC_INIT(0); #define COUNTON 100 #define NR_LOOPS 5 -void __cpuinit synchronise_count_master(int cpu) +void __cpuinit synchronise_count_master(void) { int i; unsigned long flags; unsigned int initcount; + int nslaves; #ifdef CONFIG_MIPS_MT_SMTC /* @@ -42,7 +43,8 @@ void __cpuinit synchronise_count_master(int cpu) return; #endif - printk(KERN_INFO "Synchronize counters for CPU %u: ", cpu); + printk(KERN_INFO "Synchronize counters across %u CPUs: ", + num_online_cpus()); local_irq_save(flags); @@ -50,7 +52,7 @@ void __cpuinit synchronise_count_master(int cpu) * Notify the slaves that it's time to start */ atomic_set(&count_reference, read_c0_count()); - atomic_set(&count_start_flag, cpu); + atomic_set(&count_start_flag, 1); smp_wmb(); /* Count will be initialised to current timer for all CPU's */ @@ -67,9 +69,10 @@ void __cpuinit synchronise_count_master(int cpu) * two CPUs. */ + nslaves = num_online_cpus()-1; for (i = 0; i < NR_LOOPS; i++) { - /* slaves loop on '!= 2' */ - while (atomic_read(&count_count_start) != 1) + /* slaves loop on '!= ncpus' */ + while (atomic_read(&count_count_start) != nslaves) mb(); atomic_set(&count_count_stop, 0); smp_wmb(); @@ -86,7 +89,7 @@ void __cpuinit synchronise_count_master(int cpu) /* * Wait for all slaves to leave the synchronization point: */ - while (atomic_read(&count_count_stop) != 1) + while (atomic_read(&count_count_stop) != nslaves) mb(); atomic_set(&count_count_start, 0); smp_wmb(); @@ -94,7 +97,6 @@ void __cpuinit synchronise_count_master(int cpu) } /* Arrange for an interrupt in a short while */ write_c0_compare(read_c0_count() + COUNTON); - atomic_set(&count_start_flag, 0); local_irq_restore(flags); @@ -106,10 +108,11 @@ void __cpuinit synchronise_count_master(int cpu) printk("done.\n"); } -void __cpuinit synchronise_count_slave(int cpu) +void __cpuinit synchronise_count_slave(void) { int i; unsigned int initcount; + int ncpus; #ifdef CONFIG_MIPS_MT_SMTC /* @@ -124,15 +127,16 @@ void __cpuinit synchronise_count_slave(int cpu) * so we first wait for the master to say everyone is ready */ - while (atomic_read(&count_start_flag) != cpu) + while (!atomic_read(&count_start_flag)) mb(); /* Count will be initialised to next expire for all CPU's */ initcount = atomic_read(&count_reference); + ncpus = num_online_cpus(); for (i = 0; i < NR_LOOPS; i++) { atomic_inc(&count_count_start); - while (atomic_read(&count_count_start) != 2) + while (atomic_read(&count_count_start) != ncpus) mb(); /* @@ -142,7 +146,7 @@ void __cpuinit synchronise_count_slave(int cpu) write_c0_count(initcount); atomic_inc(&count_count_stop); - while (atomic_read(&count_count_stop) != 2) + while (atomic_read(&count_count_stop) != ncpus) mb(); } /* Arrange for an interrupt in a short while */ diff --git a/trunk/arch/mips/mm/gup.c b/trunk/arch/mips/mm/gup.c index dcfd573871c1..33aadbcf170b 100644 --- a/trunk/arch/mips/mm/gup.c +++ b/trunk/arch/mips/mm/gup.c @@ -152,8 +152,6 @@ static int gup_huge_pud(pud_t pud, unsigned long addr, unsigned long end, do { VM_BUG_ON(compound_head(page) != head); pages[*nr] = page; - if (PageTail(page)) - get_huge_page_tail(page); (*nr)++; page++; refs++; diff --git a/trunk/arch/mips/mti-malta/malta-int.c b/trunk/arch/mips/mti-malta/malta-int.c index fea823f18479..7b13a4caeea4 100644 --- a/trunk/arch/mips/mti-malta/malta-int.c +++ b/trunk/arch/mips/mti-malta/malta-int.c @@ -273,19 +273,16 @@ asmlinkage void plat_irq_dispatch(void) unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM; int irq; - if (unlikely(!pending)) { - spurious_interrupt(); - return; - } - irq = irq_ffs(pending); if (irq == MIPSCPU_INT_I8259A) malta_hw0_irqdispatch(); else if (gic_present && ((1 << irq) & ipi_map[smp_processor_id()])) malta_ipi_irqdispatch(); - else + else if (irq >= 0) do_IRQ(MIPS_CPU_IRQ_BASE + irq); + else + spurious_interrupt(); } #ifdef CONFIG_MIPS_MT_SMP diff --git a/trunk/arch/mips/mti-malta/malta-pci.c b/trunk/arch/mips/mti-malta/malta-pci.c index 2147cb34e705..284dea54faf5 100644 --- a/trunk/arch/mips/mti-malta/malta-pci.c +++ b/trunk/arch/mips/mti-malta/malta-pci.c @@ -252,3 +252,16 @@ void __init mips_pcibios_init(void) register_pci_controller(controller); } + +/* Enable PCI 2.1 compatibility in PIIX4 */ +static void __devinit quirk_dlcsetup(struct pci_dev *dev) +{ + u8 odlc, ndlc; + (void) pci_read_config_byte(dev, 0x82, &odlc); + /* Enable passive releases and delayed transaction */ + ndlc = odlc | 7; + (void) pci_write_config_byte(dev, 0x82, ndlc); +} + +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_0, + quirk_dlcsetup); diff --git a/trunk/arch/mips/mti-malta/malta-platform.c b/trunk/arch/mips/mti-malta/malta-platform.c index 80562b81f0f2..4c35301720e7 100644 --- a/trunk/arch/mips/mti-malta/malta-platform.c +++ b/trunk/arch/mips/mti-malta/malta-platform.c @@ -138,6 +138,11 @@ static int __init malta_add_devices(void) if (err) return err; + /* + * Set RTC to BCD mode to support current alarm code. + */ + CMOS_WRITE(CMOS_READ(RTC_CONTROL) & ~RTC_DM_BINARY, RTC_CONTROL); + return 0; } diff --git a/trunk/arch/mips/pci/pci-ar724x.c b/trunk/arch/mips/pci/pci-ar724x.c index 86d77a666458..414a7459858d 100644 --- a/trunk/arch/mips/pci/pci-ar724x.c +++ b/trunk/arch/mips/pci/pci-ar724x.c @@ -23,12 +23,9 @@ #define AR724X_PCI_MEM_BASE 0x10000000 #define AR724X_PCI_MEM_SIZE 0x08000000 -#define AR724X_PCI_REG_RESET 0x18 #define AR724X_PCI_REG_INT_STATUS 0x4c #define AR724X_PCI_REG_INT_MASK 0x50 -#define AR724X_PCI_RESET_LINK_UP BIT(0) - #define AR724X_PCI_INT_DEV0 BIT(14) #define AR724X_PCI_IRQ_COUNT 1 @@ -41,15 +38,6 @@ static void __iomem *ar724x_pci_ctrl_base; static u32 ar724x_pci_bar0_value; static bool ar724x_pci_bar0_is_cached; -static bool ar724x_pci_link_up; - -static inline bool ar724x_pci_check_link(void) -{ - u32 reset; - - reset = __raw_readl(ar724x_pci_ctrl_base + AR724X_PCI_REG_RESET); - return reset & AR724X_PCI_RESET_LINK_UP; -} static int ar724x_pci_read(struct pci_bus *bus, unsigned int devfn, int where, int size, uint32_t *value) @@ -58,9 +46,6 @@ static int ar724x_pci_read(struct pci_bus *bus, unsigned int devfn, int where, void __iomem *base; u32 data; - if (!ar724x_pci_link_up) - return PCIBIOS_DEVICE_NOT_FOUND; - if (devfn) return PCIBIOS_DEVICE_NOT_FOUND; @@ -111,9 +96,6 @@ static int ar724x_pci_write(struct pci_bus *bus, unsigned int devfn, int where, u32 data; int s; - if (!ar724x_pci_link_up) - return PCIBIOS_DEVICE_NOT_FOUND; - if (devfn) return PCIBIOS_DEVICE_NOT_FOUND; @@ -298,10 +280,6 @@ int __init ar724x_pcibios_init(int irq) if (ar724x_pci_ctrl_base == NULL) goto err_unmap_devcfg; - ar724x_pci_link_up = ar724x_pci_check_link(); - if (!ar724x_pci_link_up) - pr_warn("ar724x: PCIe link is down\n"); - ar724x_pci_irq_init(irq); register_pci_controller(&ar724x_pci_controller); diff --git a/trunk/arch/mips/pci/pci-octeon.c b/trunk/arch/mips/pci/pci-octeon.c index c5dfb2c87d44..52a1ba70b3b6 100644 --- a/trunk/arch/mips/pci/pci-octeon.c +++ b/trunk/arch/mips/pci/pci-octeon.c @@ -117,11 +117,16 @@ int pcibios_plat_dev_init(struct pci_dev *dev) } /* Enable the PCIe normal error reporting */ - config = PCI_EXP_DEVCTL_CERE; /* Correctable Error Reporting */ - config |= PCI_EXP_DEVCTL_NFERE; /* Non-Fatal Error Reporting */ - config |= PCI_EXP_DEVCTL_FERE; /* Fatal Error Reporting */ - config |= PCI_EXP_DEVCTL_URRE; /* Unsupported Request */ - pcie_capability_set_word(dev, PCI_EXP_DEVCTL, config); + pos = pci_find_capability(dev, PCI_CAP_ID_EXP); + if (pos) { + /* Update Device Control */ + pci_read_config_word(dev, pos + PCI_EXP_DEVCTL, &config); + config |= PCI_EXP_DEVCTL_CERE; /* Correctable Error Reporting */ + config |= PCI_EXP_DEVCTL_NFERE; /* Non-Fatal Error Reporting */ + config |= PCI_EXP_DEVCTL_FERE; /* Fatal Error Reporting */ + config |= PCI_EXP_DEVCTL_URRE; /* Unsupported Request */ + pci_write_config_word(dev, pos + PCI_EXP_DEVCTL, config); + } /* Find the Advanced Error Reporting capability */ pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR); diff --git a/trunk/arch/mips/pci/pci.c b/trunk/arch/mips/pci/pci.c index 04e35bcde07c..690356808f8a 100644 --- a/trunk/arch/mips/pci/pci.c +++ b/trunk/arch/mips/pci/pci.c @@ -313,6 +313,12 @@ void __devinit pcibios_fixup_bus(struct pci_bus *bus) } } +void __init +pcibios_update_irq(struct pci_dev *dev, int irq) +{ + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq); +} + #ifdef CONFIG_HOTPLUG EXPORT_SYMBOL(PCIBIOS_MIN_IO); EXPORT_SYMBOL(PCIBIOS_MIN_MEM); diff --git a/trunk/arch/mips/sni/a20r.c b/trunk/arch/mips/sni/a20r.c index b2d4f492d782..c48194c3073b 100644 --- a/trunk/arch/mips/sni/a20r.c +++ b/trunk/arch/mips/sni/a20r.c @@ -133,38 +133,6 @@ static struct platform_device sc26xx_pdev = { } }; -#warning "Please try migrate to use new driver SCCNXP and report the status" \ - "in the linux-serial mailing list." - -/* The code bellow is a replacement of SC26XX to SCCNXP */ -#if 0 -#include - -static struct sccnxp_pdata sccnxp_data = { - .reg_shift = 2, - .frequency = 3686400, - .mctrl_cfg[0] = MCTRL_SIG(DTR_OP, LINE_OP7) | - MCTRL_SIG(RTS_OP, LINE_OP3) | - MCTRL_SIG(DSR_IP, LINE_IP5) | - MCTRL_SIG(DCD_IP, LINE_IP6), - .mctrl_cfg[1] = MCTRL_SIG(DTR_OP, LINE_OP2) | - MCTRL_SIG(RTS_OP, LINE_OP1) | - MCTRL_SIG(DSR_IP, LINE_IP0) | - MCTRL_SIG(CTS_IP, LINE_IP1) | - MCTRL_SIG(DCD_IP, LINE_IP2) | - MCTRL_SIG(RNG_IP, LINE_IP3), -}; - -static struct platform_device sc2681_pdev = { - .name = "sc2681", - .resource = sc2xxx_rsrc, - .num_resources = ARRAY_SIZE(sc2xxx_rsrc), - .dev = { - .platform_data = &sccnxp_data, - }, -}; -#endif - static u32 a20r_ack_hwint(void) { u32 status = read_c0_status(); diff --git a/trunk/arch/mn10300/kernel/process.c b/trunk/arch/mn10300/kernel/process.c index e9cceba193b6..7dab0cd36466 100644 --- a/trunk/arch/mn10300/kernel/process.c +++ b/trunk/arch/mn10300/kernel/process.c @@ -25,7 +25,6 @@ #include #include #include -#include #include #include #include @@ -108,7 +107,6 @@ void cpu_idle(void) { /* endless idle loop with no priority at all */ for (;;) { - rcu_idle_enter(); while (!need_resched()) { void (*idle)(void); @@ -123,7 +121,6 @@ void cpu_idle(void) } idle(); } - rcu_idle_exit(); schedule_preempt_disabled(); } diff --git a/trunk/arch/parisc/include/asm/atomic.h b/trunk/arch/parisc/include/asm/atomic.h index af9cf30ed474..6c6defc24619 100644 --- a/trunk/arch/parisc/include/asm/atomic.h +++ b/trunk/arch/parisc/include/asm/atomic.h @@ -141,7 +141,7 @@ static __inline__ int __atomic_add_unless(atomic_t *v, int a, int u) #define atomic_sub_and_test(i,v) (atomic_sub_return((i),(v)) == 0) -#define ATOMIC_INIT(i) { (i) } +#define ATOMIC_INIT(i) ((atomic_t) { (i) }) #define smp_mb__before_atomic_dec() smp_mb() #define smp_mb__after_atomic_dec() smp_mb() @@ -150,7 +150,7 @@ static __inline__ int __atomic_add_unless(atomic_t *v, int a, int u) #ifdef CONFIG_64BIT -#define ATOMIC64_INIT(i) { (i) } +#define ATOMIC64_INIT(i) ((atomic64_t) { (i) }) static __inline__ s64 __atomic64_add_return(s64 i, atomic64_t *v) diff --git a/trunk/arch/parisc/kernel/pdc_cons.c b/trunk/arch/parisc/kernel/pdc_cons.c index 88238638aee6..47341aa208f2 100644 --- a/trunk/arch/parisc/kernel/pdc_cons.c +++ b/trunk/arch/parisc/kernel/pdc_cons.c @@ -202,7 +202,6 @@ static int __init pdc_console_tty_driver_init(void) pdc_console_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_RESET_TERMIOS; tty_set_operations(pdc_console_tty_driver, &pdc_console_tty_ops); - tty_port_link_device(&tty_port, pdc_console_tty_driver, 0); err = tty_register_driver(pdc_console_tty_driver); if (err) { diff --git a/trunk/arch/parisc/kernel/process.c b/trunk/arch/parisc/kernel/process.c index 8c6b6b6561f0..d4b94b395c16 100644 --- a/trunk/arch/parisc/kernel/process.c +++ b/trunk/arch/parisc/kernel/process.c @@ -48,7 +48,6 @@ #include #include #include -#include #include #include @@ -70,10 +69,8 @@ void cpu_idle(void) /* endless idle loop with no priority at all */ while (1) { - rcu_idle_enter(); while (!need_resched()) barrier(); - rcu_idle_exit(); schedule_preempt_disabled(); check_pgt_cache(); } @@ -312,7 +309,7 @@ copy_thread(unsigned long clone_flags, unsigned long usp, cregs->ksp = (unsigned long)stack + (pregs->gr[21] & (THREAD_SIZE - 1)); cregs->gr[30] = usp; - if (personality(p->personality) == PER_HPUX) { + if (p->personality == PER_HPUX) { #ifdef CONFIG_HPUX cregs->kpc = (unsigned long) &hpux_child_return; #else diff --git a/trunk/arch/parisc/kernel/sys_parisc.c b/trunk/arch/parisc/kernel/sys_parisc.c index 7426e40699bd..c9b932260f47 100644 --- a/trunk/arch/parisc/kernel/sys_parisc.c +++ b/trunk/arch/parisc/kernel/sys_parisc.c @@ -225,12 +225,12 @@ long parisc_personality(unsigned long personality) long err; if (personality(current->personality) == PER_LINUX32 - && personality(personality) == PER_LINUX) - personality = (personality & ~PER_MASK) | PER_LINUX32; + && personality == PER_LINUX) + personality = PER_LINUX32; err = sys_personality(personality); - if (personality(err) == PER_LINUX32) - err = (err & ~PER_MASK) | PER_LINUX; + if (err == PER_LINUX32) + err = PER_LINUX; return err; } diff --git a/trunk/arch/powerpc/boot/.gitignore b/trunk/arch/powerpc/boot/.gitignore index c32ae5ce9fff..1c1aadc8c48f 100644 --- a/trunk/arch/powerpc/boot/.gitignore +++ b/trunk/arch/powerpc/boot/.gitignore @@ -1,6 +1,10 @@ addnote empty.c hack-coff +infblock.c +infblock.h +infcodes.c +infcodes.h inffast.c inffast.h inffixed.h diff --git a/trunk/arch/powerpc/boot/dts/fsl/p4080si-post.dtsi b/trunk/arch/powerpc/boot/dts/fsl/p4080si-post.dtsi index 4f9c9f682ecf..8d35d2c1f694 100644 --- a/trunk/arch/powerpc/boot/dts/fsl/p4080si-post.dtsi +++ b/trunk/arch/powerpc/boot/dts/fsl/p4080si-post.dtsi @@ -345,13 +345,6 @@ /include/ "qoriq-duart-1.dtsi" /include/ "qoriq-gpio-0.dtsi" /include/ "qoriq-usb2-mph-0.dtsi" - usb@210000 { - compatible = "fsl-usb2-mph-v1.6", "fsl,mpc85xx-usb2-mph", "fsl-usb2-mph"; - port0; - }; /include/ "qoriq-usb2-dr-0.dtsi" - usb@211000 { - compatible = "fsl-usb2-dr-v1.6", "fsl,mpc85xx-usb2-dr", "fsl-usb2-dr"; - }; /include/ "qoriq-sec4.0-0.dtsi" }; diff --git a/trunk/arch/powerpc/configs/85xx/p1023rds_defconfig b/trunk/arch/powerpc/configs/85xx/p1023rds_defconfig index 26e541c4662b..f4337bacd0e7 100644 --- a/trunk/arch/powerpc/configs/85xx/p1023rds_defconfig +++ b/trunk/arch/powerpc/configs/85xx/p1023rds_defconfig @@ -6,27 +6,28 @@ CONFIG_SYSVIPC=y CONFIG_POSIX_MQUEUE=y CONFIG_BSD_PROCESS_ACCT=y CONFIG_AUDIT=y -CONFIG_IRQ_DOMAIN_DEBUG=y -CONFIG_NO_HZ=y -CONFIG_HIGH_RES_TIMERS=y +CONFIG_SPARSE_IRQ=y CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=14 CONFIG_BLK_DEV_INITRD=y +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set CONFIG_KALLSYMS_ALL=y +CONFIG_KALLSYMS_EXTRA_PASS=y CONFIG_EMBEDDED=y CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y CONFIG_MODULE_FORCE_UNLOAD=y CONFIG_MODVERSIONS=y # CONFIG_BLK_DEV_BSG is not set -CONFIG_PARTITION_ADVANCED=y -CONFIG_MAC_PARTITION=y CONFIG_P1023_RDS=y CONFIG_QUICC_ENGINE=y CONFIG_QE_GPIO=y CONFIG_CPM2=y +CONFIG_GPIO_MPC8XXX=y CONFIG_HIGHMEM=y +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set CONFIG_BINFMT_MISC=m CONFIG_MATH_EMULATION=y @@ -62,11 +63,11 @@ CONFIG_INET_ESP=y CONFIG_IPV6=y CONFIG_IP_SCTP=m CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" -CONFIG_DEVTMPFS=y CONFIG_PROC_DEVICETREE=y CONFIG_BLK_DEV_LOOP=y CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_SIZE=131072 +CONFIG_MISC_DEVICES=y CONFIG_EEPROM_LEGACY=y CONFIG_BLK_DEV_SD=y CONFIG_CHR_DEV_ST=y @@ -79,14 +80,15 @@ CONFIG_SATA_FSL=y CONFIG_SATA_SIL24=y CONFIG_NETDEVICES=y CONFIG_DUMMY=y -CONFIG_FS_ENET=y -CONFIG_FSL_PQ_MDIO=y -CONFIG_E1000E=y CONFIG_MARVELL_PHY=y CONFIG_DAVICOM_PHY=y CONFIG_CICADA_PHY=y CONFIG_VITESSE_PHY=y CONFIG_FIXED_PHY=y +CONFIG_NET_ETHERNET=y +CONFIG_FS_ENET=y +CONFIG_E1000E=y +CONFIG_FSL_PQ_MDIO=y CONFIG_INPUT_FF_MEMLESS=m # CONFIG_INPUT_MOUSEDEV is not set # CONFIG_INPUT_KEYBOARD is not set @@ -96,15 +98,16 @@ CONFIG_SERIAL_8250=y CONFIG_SERIAL_8250_CONSOLE=y CONFIG_SERIAL_8250_NR_UARTS=2 CONFIG_SERIAL_8250_RUNTIME_UARTS=2 +CONFIG_SERIAL_8250_EXTENDED=y CONFIG_SERIAL_8250_MANY_PORTS=y CONFIG_SERIAL_8250_DETECT_IRQ=y CONFIG_SERIAL_8250_RSA=y CONFIG_SERIAL_QE=m +CONFIG_HW_RANDOM=y CONFIG_NVRAM=y CONFIG_I2C=y CONFIG_I2C_CPM=m CONFIG_I2C_MPC=y -CONFIG_GPIO_MPC8XXX=y # CONFIG_HWMON is not set CONFIG_VIDEO_OUTPUT_CONTROL=y CONFIG_SOUND=y @@ -120,6 +123,7 @@ CONFIG_DMADEVICES=y CONFIG_FSL_DMA=y # CONFIG_NET_DMA is not set CONFIG_STAGING=y +# CONFIG_STAGING_EXCLUDE_BUILD is not set CONFIG_EXT2_FS=y CONFIG_EXT3_FS=y # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set @@ -146,15 +150,22 @@ CONFIG_QNX4FS_FS=m CONFIG_SYSV_FS=m CONFIG_UFS_FS=m CONFIG_NFS_FS=y +CONFIG_NFS_V3=y CONFIG_NFS_V4=y CONFIG_ROOT_NFS=y CONFIG_NFSD=y +CONFIG_PARTITION_ADVANCED=y +CONFIG_MAC_PARTITION=y CONFIG_CRC_T10DIF=y CONFIG_FRAME_WARN=8092 CONFIG_DEBUG_FS=y +CONFIG_DEBUG_KERNEL=y CONFIG_DETECT_HUNG_TASK=y # CONFIG_DEBUG_BUGVERBOSE is not set CONFIG_DEBUG_INFO=y +# CONFIG_RCU_CPU_STALL_DETECTOR is not set +CONFIG_SYSCTL_SYSCALL_CHECK=y +CONFIG_IRQ_DOMAIN_DEBUG=y CONFIG_CRYPTO_PCBC=m CONFIG_CRYPTO_SHA256=y CONFIG_CRYPTO_SHA512=y diff --git a/trunk/arch/powerpc/configs/corenet32_smp_defconfig b/trunk/arch/powerpc/configs/corenet32_smp_defconfig index 8b3d57c1ebe8..cbb98c1234fd 100644 --- a/trunk/arch/powerpc/configs/corenet32_smp_defconfig +++ b/trunk/arch/powerpc/configs/corenet32_smp_defconfig @@ -6,8 +6,8 @@ CONFIG_SYSVIPC=y CONFIG_POSIX_MQUEUE=y CONFIG_BSD_PROCESS_ACCT=y CONFIG_AUDIT=y -CONFIG_NO_HZ=y -CONFIG_HIGH_RES_TIMERS=y +CONFIG_SPARSE_IRQ=y +CONFIG_RCU_TRACE=y CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=14 @@ -21,22 +21,23 @@ CONFIG_MODULE_UNLOAD=y CONFIG_MODULE_FORCE_UNLOAD=y CONFIG_MODVERSIONS=y # CONFIG_BLK_DEV_BSG is not set -CONFIG_PARTITION_ADVANCED=y -CONFIG_MAC_PARTITION=y CONFIG_P2041_RDB=y CONFIG_P3041_DS=y CONFIG_P4080_DS=y CONFIG_P5020_DS=y CONFIG_HIGHMEM=y +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set CONFIG_BINFMT_MISC=m CONFIG_KEXEC=y CONFIG_IRQ_ALL_CPUS=y CONFIG_FORCE_MAX_ZONEORDER=13 +CONFIG_FSL_LBC=y CONFIG_PCI=y CONFIG_PCIEPORTBUS=y -# CONFIG_PCIEASPM is not set CONFIG_PCI_MSI=y +# CONFIG_PCIEASPM is not set CONFIG_RAPIDIO=y CONFIG_FSL_RIO=y CONFIG_NET=y @@ -69,7 +70,6 @@ CONFIG_INET_IPCOMP=y CONFIG_IPV6=y CONFIG_IP_SCTP=m CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" -CONFIG_DEVTMPFS=y CONFIG_MTD=y CONFIG_MTD_CMDLINE_PARTS=y CONFIG_MTD_CHAR=y @@ -77,14 +77,17 @@ CONFIG_MTD_BLOCK=y CONFIG_MTD_CFI=y CONFIG_MTD_CFI_AMDSTD=y CONFIG_MTD_PHYSMAP_OF=y -CONFIG_MTD_M25P80=y CONFIG_MTD_NAND=y -CONFIG_MTD_NAND_FSL_ELBC=y +CONFIG_MTD_NAND_ECC=y +CONFIG_MTD_NAND_IDS=y CONFIG_MTD_NAND_FSL_IFC=y +CONFIG_MTD_NAND_FSL_ELBC=y +CONFIG_MTD_M25P80=y CONFIG_PROC_DEVICETREE=y CONFIG_BLK_DEV_LOOP=y CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_SIZE=131072 +CONFIG_MISC_DEVICES=y CONFIG_BLK_DEV_SD=y CONFIG_CHR_DEV_ST=y CONFIG_BLK_DEV_SR=y @@ -112,9 +115,11 @@ CONFIG_SERIO_LIBPS2=y CONFIG_PPC_EPAPR_HV_BYTECHAN=y CONFIG_SERIAL_8250=y CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_EXTENDED=y CONFIG_SERIAL_8250_MANY_PORTS=y CONFIG_SERIAL_8250_DETECT_IRQ=y CONFIG_SERIAL_8250_RSA=y +CONFIG_HW_RANDOM=y CONFIG_NVRAM=y CONFIG_I2C=y CONFIG_I2C_CHARDEV=y @@ -127,6 +132,7 @@ CONFIG_SPI_FSL_ESPI=y CONFIG_VIDEO_OUTPUT_CONTROL=y CONFIG_USB_HID=m CONFIG_USB=y +CONFIG_USB_DEVICEFS=y CONFIG_USB_MON=y CONFIG_USB_EHCI_HCD=y CONFIG_USB_EHCI_FSL=y @@ -136,6 +142,8 @@ CONFIG_USB_OHCI_HCD_PPC_OF_LE=y CONFIG_USB_STORAGE=y CONFIG_MMC=y CONFIG_MMC_SDHCI=y +CONFIG_MMC_SDHCI_OF=y +CONFIG_MMC_SDHCI_OF_ESDHC=y CONFIG_EDAC=y CONFIG_EDAC_MM_EDAC=y CONFIG_EDAC_MPC85XX=y @@ -162,16 +170,19 @@ CONFIG_HUGETLBFS=y CONFIG_JFFS2_FS=y CONFIG_CRAMFS=y CONFIG_NFS_FS=y +CONFIG_NFS_V3=y CONFIG_NFS_V4=y CONFIG_ROOT_NFS=y CONFIG_NFSD=m +CONFIG_PARTITION_ADVANCED=y +CONFIG_MAC_PARTITION=y CONFIG_NLS_ISO8859_1=y CONFIG_NLS_UTF8=m CONFIG_MAGIC_SYSRQ=y CONFIG_DEBUG_SHIRQ=y CONFIG_DETECT_HUNG_TASK=y CONFIG_DEBUG_INFO=y -CONFIG_RCU_TRACE=y +CONFIG_SYSCTL_SYSCALL_CHECK=y CONFIG_CRYPTO_NULL=y CONFIG_CRYPTO_PCBC=m CONFIG_CRYPTO_MD4=y diff --git a/trunk/arch/powerpc/configs/corenet64_smp_defconfig b/trunk/arch/powerpc/configs/corenet64_smp_defconfig index 0516e22ca3de..dd89de8b0b7f 100644 --- a/trunk/arch/powerpc/configs/corenet64_smp_defconfig +++ b/trunk/arch/powerpc/configs/corenet64_smp_defconfig @@ -56,7 +56,6 @@ CONFIG_INET_ESP=y CONFIG_IPV6=y CONFIG_IP_SCTP=m CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" -CONFIG_DEVTMPFS=y CONFIG_MTD=y CONFIG_MTD_CMDLINE_PARTS=y CONFIG_MTD_CHAR=y diff --git a/trunk/arch/powerpc/configs/g5_defconfig b/trunk/arch/powerpc/configs/g5_defconfig index 07b7f2af2dca..15130066e5e2 100644 --- a/trunk/arch/powerpc/configs/g5_defconfig +++ b/trunk/arch/powerpc/configs/g5_defconfig @@ -1,10 +1,8 @@ -CONFIG_PPC64=y -CONFIG_ALTIVEC=y -CONFIG_SMP=y -CONFIG_NR_CPUS=4 CONFIG_EXPERIMENTAL=y CONFIG_SYSVIPC=y CONFIG_POSIX_MQUEUE=y +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_BLK_DEV_INITRD=y @@ -15,16 +13,15 @@ CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y CONFIG_MODVERSIONS=y CONFIG_MODULE_SRCVERSION_ALL=y -# CONFIG_PPC_PSERIES is not set +CONFIG_PARTITION_ADVANCED=y +CONFIG_MAC_PARTITION=y +CONFIG_SMP=y +CONFIG_NR_CPUS=4 +CONFIG_KEXEC=y +# CONFIG_RELOCATABLE is not set CONFIG_CPU_FREQ=y CONFIG_CPU_FREQ_GOV_POWERSAVE=y CONFIG_CPU_FREQ_GOV_USERSPACE=y -CONFIG_CPU_FREQ_PMAC64=y -CONFIG_NO_HZ=y -CONFIG_HIGH_RES_TIMERS=y -CONFIG_KEXEC=y -CONFIG_IRQ_ALL_CPUS=y -# CONFIG_MIGRATION is not set CONFIG_PCI_MSI=y CONFIG_NET=y CONFIG_PACKET=y @@ -52,7 +49,6 @@ CONFIG_NF_CT_NETLINK=m CONFIG_NF_CONNTRACK_IPV4=m CONFIG_IP_NF_QUEUE=m CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" -CONFIG_PROC_DEVICETREE=y CONFIG_BLK_DEV_LOOP=y CONFIG_BLK_DEV_NBD=m CONFIG_BLK_DEV_RAM=y @@ -60,8 +56,6 @@ CONFIG_BLK_DEV_RAM_SIZE=65536 CONFIG_CDROM_PKTCDVD=m CONFIG_IDE=y CONFIG_BLK_DEV_IDECD=y -CONFIG_BLK_DEV_IDE_PMAC=y -CONFIG_BLK_DEV_IDE_PMAC_ATA100FIRST=y CONFIG_BLK_DEV_SD=y CONFIG_CHR_DEV_ST=y CONFIG_BLK_DEV_SR=y @@ -85,33 +79,24 @@ CONFIG_DM_CRYPT=m CONFIG_DM_SNAPSHOT=m CONFIG_DM_MIRROR=m CONFIG_DM_ZERO=m -CONFIG_IEEE1394=y -CONFIG_IEEE1394_OHCI1394=y -CONFIG_IEEE1394_SBP2=m -CONFIG_IEEE1394_ETH1394=m -CONFIG_IEEE1394_RAWIO=y -CONFIG_IEEE1394_VIDEO1394=m -CONFIG_IEEE1394_DV1394=m -CONFIG_ADB_PMU=y -CONFIG_PMAC_SMU=y +CONFIG_MACINTOSH_DRIVERS=y CONFIG_MAC_EMUMOUSEBTN=y -CONFIG_THERM_PM72=y -CONFIG_WINDFARM=y -CONFIG_WINDFARM_PM81=y -CONFIG_WINDFARM_PM91=y -CONFIG_WINDFARM_PM112=y -CONFIG_WINDFARM_PM121=y CONFIG_NETDEVICES=y -CONFIG_DUMMY=m CONFIG_BONDING=m -CONFIG_TUN=m -CONFIG_NET_ETHERNET=y +CONFIG_DUMMY=m CONFIG_MII=y -CONFIG_SUNGEM=y +CONFIG_TUN=m CONFIG_ACENIC=m CONFIG_ACENIC_OMIT_TIGON_I=y -CONFIG_E1000=y CONFIG_TIGON3=y +CONFIG_E1000=y +CONFIG_SUNGEM=y +CONFIG_PPP=m +CONFIG_PPP_BSDCOMP=m +CONFIG_PPP_DEFLATE=m +CONFIG_PPPOE=m +CONFIG_PPP_ASYNC=m +CONFIG_PPP_SYNC_TTY=m CONFIG_USB_CATC=m CONFIG_USB_KAWETH=m CONFIG_USB_PEGASUS=m @@ -121,36 +106,24 @@ CONFIG_USB_USBNET=m # CONFIG_USB_NET_NET1080 is not set # CONFIG_USB_NET_CDC_SUBSET is not set # CONFIG_USB_NET_ZAURUS is not set -CONFIG_PPP=m -CONFIG_PPP_ASYNC=m -CONFIG_PPP_SYNC_TTY=m -CONFIG_PPP_DEFLATE=m -CONFIG_PPP_BSDCOMP=m -CONFIG_PPPOE=m # CONFIG_INPUT_MOUSEDEV_PSAUX is not set CONFIG_INPUT_JOYDEV=m CONFIG_INPUT_EVDEV=y -# CONFIG_KEYBOARD_ATKBD is not set # CONFIG_MOUSE_PS2 is not set -# CONFIG_SERIO_I8042 is not set # CONFIG_SERIO_SERPORT is not set +CONFIG_VT_HW_CONSOLE_BINDING=y # CONFIG_HW_RANDOM is not set CONFIG_GEN_RTC=y CONFIG_RAW_DRIVER=y CONFIG_I2C_CHARDEV=y # CONFIG_HWMON is not set -CONFIG_AGP=m -CONFIG_AGP_UNINORTH=m +CONFIG_AGP=y +CONFIG_DRM=y +CONFIG_DRM_NOUVEAU=y CONFIG_VIDEO_OUTPUT_CONTROL=m -CONFIG_FB=y CONFIG_FIRMWARE_EDID=y CONFIG_FB_TILEBLITTING=y -CONFIG_FB_OF=y -CONFIG_FB_NVIDIA=y -CONFIG_FB_NVIDIA_I2C=y CONFIG_FB_RADEON=y -# CONFIG_VGA_CONSOLE is not set -CONFIG_FRAMEBUFFER_CONSOLE=y CONFIG_LOGO=y CONFIG_SOUND=m CONFIG_SND=m @@ -158,15 +131,7 @@ CONFIG_SND_SEQUENCER=m CONFIG_SND_MIXER_OSS=m CONFIG_SND_PCM_OSS=m CONFIG_SND_SEQUENCER_OSS=y -CONFIG_SND_POWERMAC=m -CONFIG_SND_AOA=m -CONFIG_SND_AOA_FABRIC_LAYOUT=m -CONFIG_SND_AOA_ONYX=m -CONFIG_SND_AOA_TAS=m -CONFIG_SND_AOA_TOONIE=m CONFIG_SND_USB_AUDIO=m -CONFIG_HID_PID=y -CONFIG_USB_HIDDEV=y CONFIG_HID_GYRATION=y CONFIG_LOGITECH_FF=y CONFIG_HID_PANTHERLORD=y @@ -174,13 +139,12 @@ CONFIG_HID_PETALYNX=y CONFIG_HID_SAMSUNG=y CONFIG_HID_SONY=y CONFIG_HID_SUNPLUS=y +CONFIG_HID_PID=y +CONFIG_USB_HIDDEV=y CONFIG_USB=y -CONFIG_USB_DEVICEFS=y CONFIG_USB_MON=y CONFIG_USB_EHCI_HCD=y -# CONFIG_USB_EHCI_HCD_PPC_OF is not set CONFIG_USB_OHCI_HCD=y -CONFIG_USB_OHCI_HCD_PPC_OF_BE=y CONFIG_USB_ACM=m CONFIG_USB_PRINTER=y CONFIG_USB_STORAGE=y @@ -244,8 +208,6 @@ CONFIG_REISERFS_FS_POSIX_ACL=y CONFIG_REISERFS_FS_SECURITY=y CONFIG_XFS_FS=m CONFIG_XFS_POSIX_ACL=y -CONFIG_INOTIFY=y -CONFIG_AUTOFS_FS=m CONFIG_ISO9660_FS=y CONFIG_JOLIET=y CONFIG_ZISOFS=y @@ -259,14 +221,12 @@ CONFIG_HFS_FS=m CONFIG_HFSPLUS_FS=m CONFIG_CRAMFS=y CONFIG_NFS_FS=y -CONFIG_NFS_V3=y CONFIG_NFS_V3_ACL=y CONFIG_NFS_V4=y CONFIG_NFSD=y CONFIG_NFSD_V3_ACL=y CONFIG_NFSD_V4=y CONFIG_CIFS=m -CONFIG_PARTITION_ADVANCED=y CONFIG_NLS_CODEPAGE_437=y CONFIG_NLS_CODEPAGE_1250=y CONFIG_NLS_CODEPAGE_1251=y @@ -274,29 +234,23 @@ CONFIG_NLS_ASCII=y CONFIG_NLS_ISO8859_1=y CONFIG_NLS_ISO8859_15=y CONFIG_NLS_UTF8=y -CONFIG_CRC_T10DIF=y -CONFIG_LIBCRC32C=m CONFIG_MAGIC_SYSRQ=y +# CONFIG_UNUSED_SYMBOLS is not set CONFIG_DEBUG_FS=y CONFIG_DEBUG_KERNEL=y CONFIG_DEBUG_MUTEXES=y -# CONFIG_RCU_CPU_STALL_DETECTOR is not set CONFIG_LATENCYTOP=y -CONFIG_SYSCTL_SYSCALL_CHECK=y -CONFIG_BOOTX_TEXT=y +CONFIG_STRICT_DEVMEM=y CONFIG_CRYPTO_NULL=m CONFIG_CRYPTO_TEST=m -CONFIG_CRYPTO_ECB=m CONFIG_CRYPTO_PCBC=m CONFIG_CRYPTO_HMAC=y -CONFIG_CRYPTO_MD4=m CONFIG_CRYPTO_MICHAEL_MIC=m CONFIG_CRYPTO_SHA256=m CONFIG_CRYPTO_SHA512=m CONFIG_CRYPTO_WP512=m CONFIG_CRYPTO_AES=m CONFIG_CRYPTO_ANUBIS=m -CONFIG_CRYPTO_ARC4=m CONFIG_CRYPTO_BLOWFISH=m CONFIG_CRYPTO_CAST5=m CONFIG_CRYPTO_CAST6=m @@ -306,3 +260,6 @@ CONFIG_CRYPTO_TEA=m CONFIG_CRYPTO_TWOFISH=m # CONFIG_CRYPTO_ANSI_CPRNG is not set # CONFIG_CRYPTO_HW is not set +# CONFIG_VIRTUALIZATION is not set +CONFIG_CRC_T10DIF=y +CONFIG_LIBCRC32C=m diff --git a/trunk/arch/powerpc/configs/mpc83xx_defconfig b/trunk/arch/powerpc/configs/mpc83xx_defconfig index 9352e4430c3b..5aac9a8bc53b 100644 --- a/trunk/arch/powerpc/configs/mpc83xx_defconfig +++ b/trunk/arch/powerpc/configs/mpc83xx_defconfig @@ -2,12 +2,12 @@ CONFIG_EXPERIMENTAL=y CONFIG_SYSVIPC=y CONFIG_LOG_BUF_SHIFT=14 CONFIG_BLK_DEV_INITRD=y +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set CONFIG_EXPERT=y CONFIG_SLAB=y CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y # CONFIG_BLK_DEV_BSG is not set -CONFIG_PARTITION_ADVANCED=y # CONFIG_PPC_CHRP is not set # CONFIG_PPC_PMAC is not set CONFIG_PPC_83xx=y @@ -25,6 +25,7 @@ CONFIG_ASP834x=y CONFIG_QUICC_ENGINE=y CONFIG_QE_GPIO=y CONFIG_MATH_EMULATION=y +CONFIG_SPARSE_IRQ=y CONFIG_PCI=y CONFIG_NET=y CONFIG_PACKET=y @@ -41,9 +42,10 @@ CONFIG_INET_ESP=y # CONFIG_INET_LRO is not set # CONFIG_IPV6 is not set CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" -CONFIG_DEVTMPFS=y # CONFIG_FW_LOADER is not set CONFIG_MTD=y +CONFIG_MTD_PARTITIONS=y +CONFIG_MTD_OF_PARTS=y CONFIG_MTD_CHAR=y CONFIG_MTD_BLOCK=y CONFIG_MTD_CFI=y @@ -62,14 +64,15 @@ CONFIG_ATA=y CONFIG_SATA_FSL=y CONFIG_SATA_SIL=y CONFIG_NETDEVICES=y -CONFIG_MII=y -CONFIG_UCC_GETH=y -CONFIG_GIANFAR=y CONFIG_MARVELL_PHY=y CONFIG_DAVICOM_PHY=y CONFIG_VITESSE_PHY=y CONFIG_ICPLUS_PHY=y CONFIG_FIXED_PHY=y +CONFIG_NET_ETHERNET=y +CONFIG_MII=y +CONFIG_GIANFAR=y +CONFIG_UCC_GETH=y CONFIG_INPUT_FF_MEMLESS=m # CONFIG_INPUT_MOUSEDEV is not set # CONFIG_INPUT_KEYBOARD is not set @@ -109,12 +112,17 @@ CONFIG_RTC_DRV_DS1374=y CONFIG_EXT2_FS=y CONFIG_EXT3_FS=y # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set +CONFIG_INOTIFY=y CONFIG_PROC_KCORE=y CONFIG_TMPFS=y CONFIG_NFS_FS=y +CONFIG_NFS_V3=y CONFIG_NFS_V4=y CONFIG_ROOT_NFS=y +CONFIG_PARTITION_ADVANCED=y CONFIG_CRC_T10DIF=y +# CONFIG_RCU_CPU_STALL_DETECTOR is not set +CONFIG_SYSCTL_SYSCALL_CHECK=y CONFIG_CRYPTO_ECB=m CONFIG_CRYPTO_PCBC=m CONFIG_CRYPTO_SHA256=y diff --git a/trunk/arch/powerpc/configs/mpc85xx_defconfig b/trunk/arch/powerpc/configs/mpc85xx_defconfig index 8b5bda27d248..03ee911c4577 100644 --- a/trunk/arch/powerpc/configs/mpc85xx_defconfig +++ b/trunk/arch/powerpc/configs/mpc85xx_defconfig @@ -5,9 +5,7 @@ CONFIG_SYSVIPC=y CONFIG_POSIX_MQUEUE=y CONFIG_BSD_PROCESS_ACCT=y CONFIG_AUDIT=y -CONFIG_IRQ_DOMAIN_DEBUG=y -CONFIG_NO_HZ=y -CONFIG_HIGH_RES_TIMERS=y +CONFIG_SPARSE_IRQ=y CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=14 @@ -19,8 +17,6 @@ CONFIG_MODULE_UNLOAD=y CONFIG_MODULE_FORCE_UNLOAD=y CONFIG_MODVERSIONS=y # CONFIG_BLK_DEV_BSG is not set -CONFIG_PARTITION_ADVANCED=y -CONFIG_MAC_PARTITION=y CONFIG_MPC8540_ADS=y CONFIG_MPC8560_ADS=y CONFIG_MPC85xx_CDS=y @@ -44,6 +40,8 @@ CONFIG_SBC8548=y CONFIG_QUICC_ENGINE=y CONFIG_QE_GPIO=y CONFIG_HIGHMEM=y +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y CONFIG_BINFMT_MISC=m CONFIG_MATH_EMULATION=y CONFIG_FORCE_MAX_ZONEORDER=12 @@ -76,25 +74,36 @@ CONFIG_INET_ESP=y CONFIG_IPV6=y CONFIG_IP_SCTP=m CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" -CONFIG_DEVTMPFS=y CONFIG_MTD=y CONFIG_MTD_CMDLINE_PARTS=y CONFIG_MTD_CHAR=y CONFIG_MTD_BLOCK=y -CONFIG_FTL=y CONFIG_MTD_CFI=y +CONFIG_FTL=y +CONFIG_MTD_GEN_PROBE=y +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y CONFIG_MTD_CFI_INTELEXT=y CONFIG_MTD_CFI_AMDSTD=y +CONFIG_MTD_CFI_UTIL=y CONFIG_MTD_PHYSMAP_OF=y -CONFIG_MTD_M25P80=y +CONFIG_MTD_PARTITIONS=y +CONFIG_MTD_OF_PARTS=y CONFIG_MTD_NAND=y CONFIG_MTD_NAND_FSL_ELBC=y CONFIG_MTD_NAND_FSL_IFC=y +CONFIG_MTD_NAND_IDS=y +CONFIG_MTD_NAND_ECC=y +CONFIG_MTD_M25P80=y CONFIG_PROC_DEVICETREE=y CONFIG_BLK_DEV_LOOP=y CONFIG_BLK_DEV_NBD=y CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_SIZE=131072 +CONFIG_MISC_DEVICES=y CONFIG_EEPROM_LEGACY=y CONFIG_BLK_DEV_SD=y CONFIG_CHR_DEV_ST=y @@ -106,7 +115,6 @@ CONFIG_ATA=y CONFIG_SATA_AHCI=y CONFIG_SATA_FSL=y CONFIG_PATA_ALI=y -CONFIG_PATA_VIA=y CONFIG_NETDEVICES=y CONFIG_DUMMY=y CONFIG_FS_ENET=y @@ -126,6 +134,7 @@ CONFIG_SERIAL_8250=y CONFIG_SERIAL_8250_CONSOLE=y CONFIG_SERIAL_8250_NR_UARTS=2 CONFIG_SERIAL_8250_RUNTIME_UARTS=2 +CONFIG_SERIAL_8250_EXTENDED=y CONFIG_SERIAL_8250_MANY_PORTS=y CONFIG_SERIAL_8250_DETECT_IRQ=y CONFIG_SERIAL_8250_RSA=y @@ -174,6 +183,7 @@ CONFIG_HID_SAMSUNG=y CONFIG_HID_SONY=y CONFIG_HID_SUNPLUS=y CONFIG_USB=y +CONFIG_USB_DEVICEFS=y CONFIG_USB_MON=y CONFIG_USB_EHCI_HCD=y CONFIG_USB_EHCI_FSL=y @@ -219,13 +229,18 @@ CONFIG_QNX4FS_FS=m CONFIG_SYSV_FS=m CONFIG_UFS_FS=m CONFIG_NFS_FS=y +CONFIG_NFS_V3=y CONFIG_NFS_V4=y CONFIG_ROOT_NFS=y CONFIG_NFSD=y +CONFIG_PARTITION_ADVANCED=y +CONFIG_MAC_PARTITION=y CONFIG_CRC_T10DIF=y CONFIG_DEBUG_FS=y CONFIG_DETECT_HUNG_TASK=y CONFIG_DEBUG_INFO=y +CONFIG_SYSCTL_SYSCALL_CHECK=y +CONFIG_IRQ_DOMAIN_DEBUG=y CONFIG_CRYPTO_PCBC=m CONFIG_CRYPTO_SHA256=y CONFIG_CRYPTO_SHA512=y diff --git a/trunk/arch/powerpc/configs/mpc85xx_smp_defconfig b/trunk/arch/powerpc/configs/mpc85xx_smp_defconfig index b0974e7e98ae..fdfa84dc908f 100644 --- a/trunk/arch/powerpc/configs/mpc85xx_smp_defconfig +++ b/trunk/arch/powerpc/configs/mpc85xx_smp_defconfig @@ -7,9 +7,7 @@ CONFIG_SYSVIPC=y CONFIG_POSIX_MQUEUE=y CONFIG_BSD_PROCESS_ACCT=y CONFIG_AUDIT=y -CONFIG_IRQ_DOMAIN_DEBUG=y -CONFIG_NO_HZ=y -CONFIG_HIGH_RES_TIMERS=y +CONFIG_SPARSE_IRQ=y CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=14 @@ -21,8 +19,6 @@ CONFIG_MODULE_UNLOAD=y CONFIG_MODULE_FORCE_UNLOAD=y CONFIG_MODVERSIONS=y # CONFIG_BLK_DEV_BSG is not set -CONFIG_PARTITION_ADVANCED=y -CONFIG_MAC_PARTITION=y CONFIG_MPC8540_ADS=y CONFIG_MPC8560_ADS=y CONFIG_MPC85xx_CDS=y @@ -46,6 +42,8 @@ CONFIG_SBC8548=y CONFIG_QUICC_ENGINE=y CONFIG_QE_GPIO=y CONFIG_HIGHMEM=y +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y CONFIG_BINFMT_MISC=m CONFIG_MATH_EMULATION=y CONFIG_IRQ_ALL_CPUS=y @@ -79,25 +77,36 @@ CONFIG_INET_ESP=y CONFIG_IPV6=y CONFIG_IP_SCTP=m CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" -CONFIG_DEVTMPFS=y CONFIG_MTD=y CONFIG_MTD_CMDLINE_PARTS=y CONFIG_MTD_CHAR=y CONFIG_MTD_BLOCK=y -CONFIG_FTL=y CONFIG_MTD_CFI=y +CONFIG_FTL=y +CONFIG_MTD_GEN_PROBE=y +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y CONFIG_MTD_CFI_INTELEXT=y CONFIG_MTD_CFI_AMDSTD=y +CONFIG_MTD_CFI_UTIL=y CONFIG_MTD_PHYSMAP_OF=y -CONFIG_MTD_M25P80=y +CONFIG_MTD_PARTITIONS=y +CONFIG_MTD_OF_PARTS=y CONFIG_MTD_NAND=y CONFIG_MTD_NAND_FSL_ELBC=y CONFIG_MTD_NAND_FSL_IFC=y +CONFIG_MTD_NAND_IDS=y +CONFIG_MTD_NAND_ECC=y +CONFIG_MTD_M25P80=y CONFIG_PROC_DEVICETREE=y CONFIG_BLK_DEV_LOOP=y CONFIG_BLK_DEV_NBD=y CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_SIZE=131072 +CONFIG_MISC_DEVICES=y CONFIG_EEPROM_LEGACY=y CONFIG_BLK_DEV_SD=y CONFIG_CHR_DEV_ST=y @@ -128,6 +137,7 @@ CONFIG_SERIAL_8250=y CONFIG_SERIAL_8250_CONSOLE=y CONFIG_SERIAL_8250_NR_UARTS=2 CONFIG_SERIAL_8250_RUNTIME_UARTS=2 +CONFIG_SERIAL_8250_EXTENDED=y CONFIG_SERIAL_8250_MANY_PORTS=y CONFIG_SERIAL_8250_DETECT_IRQ=y CONFIG_SERIAL_8250_RSA=y @@ -176,6 +186,7 @@ CONFIG_HID_SAMSUNG=y CONFIG_HID_SONY=y CONFIG_HID_SUNPLUS=y CONFIG_USB=y +CONFIG_USB_DEVICEFS=y CONFIG_USB_MON=y CONFIG_USB_EHCI_HCD=y CONFIG_USB_EHCI_FSL=y @@ -221,13 +232,18 @@ CONFIG_QNX4FS_FS=m CONFIG_SYSV_FS=m CONFIG_UFS_FS=m CONFIG_NFS_FS=y +CONFIG_NFS_V3=y CONFIG_NFS_V4=y CONFIG_ROOT_NFS=y CONFIG_NFSD=y +CONFIG_PARTITION_ADVANCED=y +CONFIG_MAC_PARTITION=y CONFIG_CRC_T10DIF=y CONFIG_DEBUG_FS=y CONFIG_DETECT_HUNG_TASK=y CONFIG_DEBUG_INFO=y +CONFIG_SYSCTL_SYSCALL_CHECK=y +CONFIG_IRQ_DOMAIN_DEBUG=y CONFIG_CRYPTO_PCBC=m CONFIG_CRYPTO_SHA256=y CONFIG_CRYPTO_SHA512=y diff --git a/trunk/arch/powerpc/include/asm/cputable.h b/trunk/arch/powerpc/include/asm/cputable.h index b3c083de17ad..50d82c8a037f 100644 --- a/trunk/arch/powerpc/include/asm/cputable.h +++ b/trunk/arch/powerpc/include/asm/cputable.h @@ -553,7 +553,9 @@ static inline int cpu_has_feature(unsigned long feature) & feature); } +#ifdef CONFIG_HAVE_HW_BREAKPOINT #define HBP_NUM 1 +#endif /* CONFIG_HAVE_HW_BREAKPOINT */ #endif /* !__ASSEMBLY__ */ diff --git a/trunk/arch/powerpc/include/asm/kvm_host.h b/trunk/arch/powerpc/include/asm/kvm_host.h index a8bf5c673a3c..50ea12fd7bf5 100644 --- a/trunk/arch/powerpc/include/asm/kvm_host.h +++ b/trunk/arch/powerpc/include/asm/kvm_host.h @@ -33,7 +33,6 @@ #include #include #include -#include #define KVM_MAX_VCPUS NR_CPUS #define KVM_MAX_VCORES NR_CPUS diff --git a/trunk/arch/powerpc/include/asm/kvm_ppc.h b/trunk/arch/powerpc/include/asm/kvm_ppc.h index e006f0bdea95..0124937a23b9 100644 --- a/trunk/arch/powerpc/include/asm/kvm_ppc.h +++ b/trunk/arch/powerpc/include/asm/kvm_ppc.h @@ -219,16 +219,4 @@ void kvmppc_claim_lpid(long lpid); void kvmppc_free_lpid(long lpid); void kvmppc_init_lpid(unsigned long nr_lpids); -static inline void kvmppc_mmu_flush_icache(pfn_t pfn) -{ - /* Clear i-cache for new pages */ - struct page *page; - page = pfn_to_page(pfn); - if (!test_bit(PG_arch_1, &page->flags)) { - flush_dcache_icache_page(page); - set_bit(PG_arch_1, &page->flags); - } -} - - #endif /* __POWERPC_KVM_PPC_H__ */ diff --git a/trunk/arch/powerpc/include/asm/machdep.h b/trunk/arch/powerpc/include/asm/machdep.h index f7706d722b39..42ce570812c1 100644 --- a/trunk/arch/powerpc/include/asm/machdep.h +++ b/trunk/arch/powerpc/include/asm/machdep.h @@ -214,9 +214,6 @@ struct machdep_calls { /* Called after scan and before resource survey */ void (*pcibios_fixup_phb)(struct pci_controller *hose); - /* Called during PCI resource reassignment */ - resource_size_t (*pcibios_window_alignment)(struct pci_bus *, unsigned long type); - /* Called to shutdown machine specific hardware not already controlled * by other drivers. */ diff --git a/trunk/arch/powerpc/include/asm/mpic_msgr.h b/trunk/arch/powerpc/include/asm/mpic_msgr.h index d4f471fb1031..326d33ca55cd 100644 --- a/trunk/arch/powerpc/include/asm/mpic_msgr.h +++ b/trunk/arch/powerpc/include/asm/mpic_msgr.h @@ -14,7 +14,6 @@ #include #include #include -#include struct mpic_msgr { u32 __iomem *base; diff --git a/trunk/arch/powerpc/include/asm/processor.h b/trunk/arch/powerpc/include/asm/processor.h index 54b73a28c205..53b6dfa83344 100644 --- a/trunk/arch/powerpc/include/asm/processor.h +++ b/trunk/arch/powerpc/include/asm/processor.h @@ -386,7 +386,6 @@ extern unsigned long cpuidle_disable; enum idle_boot_override {IDLE_NO_OVERRIDE = 0, IDLE_POWERSAVE_OFF}; extern int powersave_nap; /* set if nap mode can be used in idle loop */ -extern void power7_nap(void); #ifdef CONFIG_PSERIES_IDLE extern void update_smt_snooze_delay(int snooze); diff --git a/trunk/arch/powerpc/include/asm/time.h b/trunk/arch/powerpc/include/asm/time.h index c1f267694acb..3b4b4a8da922 100644 --- a/trunk/arch/powerpc/include/asm/time.h +++ b/trunk/arch/powerpc/include/asm/time.h @@ -197,6 +197,12 @@ struct cpu_usage { DECLARE_PER_CPU(struct cpu_usage, cpu_usage_array); +#if defined(CONFIG_VIRT_CPU_ACCOUNTING) +#define account_process_vtime(tsk) account_process_tick(tsk, 0) +#else +#define account_process_vtime(tsk) do { } while (0) +#endif + extern void secondary_cpu_time_init(void); DECLARE_PER_CPU(u64, decrementers_next_tb); diff --git a/trunk/arch/powerpc/kernel/asm-offsets.c b/trunk/arch/powerpc/kernel/asm-offsets.c index e8995727b1c1..85b05c463fae 100644 --- a/trunk/arch/powerpc/kernel/asm-offsets.c +++ b/trunk/arch/powerpc/kernel/asm-offsets.c @@ -76,7 +76,6 @@ int main(void) DEFINE(SIGSEGV, SIGSEGV); DEFINE(NMI_MASK, NMI_MASK); DEFINE(THREAD_DSCR, offsetof(struct thread_struct, dscr)); - DEFINE(THREAD_DSCR_INHERIT, offsetof(struct thread_struct, dscr_inherit)); #else DEFINE(THREAD_INFO, offsetof(struct task_struct, stack)); #endif /* CONFIG_PPC64 */ diff --git a/trunk/arch/powerpc/kernel/dbell.c b/trunk/arch/powerpc/kernel/dbell.c index a892680668d8..5b25c8060fd6 100644 --- a/trunk/arch/powerpc/kernel/dbell.c +++ b/trunk/arch/powerpc/kernel/dbell.c @@ -28,8 +28,6 @@ void doorbell_setup_this_cpu(void) void doorbell_cause_ipi(int cpu, unsigned long data) { - /* Order previous accesses vs. msgsnd, which is treated as a store */ - mb(); ppc_msgsnd(PPC_DBELL, 0, data); } diff --git a/trunk/arch/powerpc/kernel/dma-iommu.c b/trunk/arch/powerpc/kernel/dma-iommu.c index e4897523de41..2d7bb8ced136 100644 --- a/trunk/arch/powerpc/kernel/dma-iommu.c +++ b/trunk/arch/powerpc/kernel/dma-iommu.c @@ -83,10 +83,11 @@ static int dma_iommu_dma_supported(struct device *dev, u64 mask) return 0; } - if (tbl->it_offset > (mask >> IOMMU_PAGE_SHIFT)) { - dev_info(dev, "Warning: IOMMU offset too big for device mask\n"); - dev_info(dev, "mask: 0x%08llx, table offset: 0x%08lx\n", - mask, tbl->it_offset << IOMMU_PAGE_SHIFT); + if ((tbl->it_offset + tbl->it_size) > (mask >> IOMMU_PAGE_SHIFT)) { + dev_info(dev, "Warning: IOMMU window too big for device mask\n"); + dev_info(dev, "mask: 0x%08llx, table end: 0x%08lx\n", + mask, (tbl->it_offset + tbl->it_size) << + IOMMU_PAGE_SHIFT); return 0; } else return 1; diff --git a/trunk/arch/powerpc/kernel/entry_64.S b/trunk/arch/powerpc/kernel/entry_64.S index b40e0b4815b3..4b01a25e29ef 100644 --- a/trunk/arch/powerpc/kernel/entry_64.S +++ b/trunk/arch/powerpc/kernel/entry_64.S @@ -370,12 +370,6 @@ _GLOBAL(ret_from_fork) li r3,0 b syscall_exit - .section ".toc","aw" -DSCR_DEFAULT: - .tc dscr_default[TC],dscr_default - - .section ".text" - /* * This routine switches between two different tasks. The process * state of one is saved on its kernel stack. Then the state @@ -515,6 +509,9 @@ END_MMU_FTR_SECTION_IFSET(MMU_FTR_1T_SEGMENT) mr r1,r8 /* start using new stack pointer */ std r7,PACAKSAVE(r13) + ld r6,_CCR(r1) + mtcrf 0xFF,r6 + #ifdef CONFIG_ALTIVEC BEGIN_FTR_SECTION ld r0,THREAD_VRSAVE(r4) @@ -523,22 +520,14 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) #endif /* CONFIG_ALTIVEC */ #ifdef CONFIG_PPC64 BEGIN_FTR_SECTION - lwz r6,THREAD_DSCR_INHERIT(r4) - ld r7,DSCR_DEFAULT@toc(2) ld r0,THREAD_DSCR(r4) - cmpwi r6,0 - bne 1f - ld r0,0(r7) -1: cmpd r0,r25 - beq 2f + cmpd r0,r25 + beq 1f mtspr SPRN_DSCR,r0 -2: +1: END_FTR_SECTION_IFSET(CPU_FTR_DSCR) #endif - ld r6,_CCR(r1) - mtcrf 0xFF,r6 - /* r3-r13 are destroyed -- Cort */ REST_8GPRS(14, r1) REST_10GPRS(22, r1) diff --git a/trunk/arch/powerpc/kernel/exceptions-64s.S b/trunk/arch/powerpc/kernel/exceptions-64s.S index 39aa97d3ff88..e894515e77bb 100644 --- a/trunk/arch/powerpc/kernel/exceptions-64s.S +++ b/trunk/arch/powerpc/kernel/exceptions-64s.S @@ -186,7 +186,7 @@ hardware_interrupt_hv: KVM_HANDLER_PR(PACA_EXGEN, EXC_STD, 0x800) MASKABLE_EXCEPTION_PSERIES(0x900, 0x900, decrementer) - STD_EXCEPTION_HV(0x980, 0x982, hdecrementer) + MASKABLE_EXCEPTION_HV(0x980, 0x982, decrementer) STD_EXCEPTION_PSERIES(0xa00, 0xa00, trap_0a) KVM_HANDLER_PR(PACA_EXGEN, EXC_STD, 0xa00) @@ -486,7 +486,6 @@ machine_check_common: STD_EXCEPTION_COMMON_ASYNC(0x500, hardware_interrupt, do_IRQ) STD_EXCEPTION_COMMON_ASYNC(0x900, decrementer, .timer_interrupt) - STD_EXCEPTION_COMMON(0x980, hdecrementer, .hdec_interrupt) STD_EXCEPTION_COMMON(0xa00, trap_0a, .unknown_exception) STD_EXCEPTION_COMMON(0xb00, trap_0b, .unknown_exception) STD_EXCEPTION_COMMON(0xd00, single_step, .single_step_exception) diff --git a/trunk/arch/powerpc/kernel/hw_breakpoint.c b/trunk/arch/powerpc/kernel/hw_breakpoint.c index 956a4c496de9..f3a82dde61db 100644 --- a/trunk/arch/powerpc/kernel/hw_breakpoint.c +++ b/trunk/arch/powerpc/kernel/hw_breakpoint.c @@ -253,7 +253,7 @@ int __kprobes hw_breakpoint_handler(struct die_args *args) /* Do not emulate user-space instructions, instead single-step them */ if (user_mode(regs)) { - current->thread.last_hit_ubp = bp; + bp->ctx->task->thread.last_hit_ubp = bp; regs->msr |= MSR_SE; goto out; } diff --git a/trunk/arch/powerpc/kernel/idle_power7.S b/trunk/arch/powerpc/kernel/idle_power7.S index e11863f4e595..7140d838339e 100644 --- a/trunk/arch/powerpc/kernel/idle_power7.S +++ b/trunk/arch/powerpc/kernel/idle_power7.S @@ -28,9 +28,7 @@ _GLOBAL(power7_idle) lwz r4,ADDROFF(powersave_nap)(r3) cmpwi 0,r4,0 beqlr - /* fall through */ -_GLOBAL(power7_nap) /* NAP is a state loss, we create a regs frame on the * stack, fill it up with the state we care about and * stick a pointer to it in PACAR1. We really only diff --git a/trunk/arch/powerpc/kernel/kgdb.c b/trunk/arch/powerpc/kernel/kgdb.c index c470a40b29f5..782bd0a3c2f0 100644 --- a/trunk/arch/powerpc/kernel/kgdb.c +++ b/trunk/arch/powerpc/kernel/kgdb.c @@ -25,7 +25,6 @@ #include #include #include -#include /* * This table contains the mapping between PowerPC hardware trap types, and @@ -102,21 +101,6 @@ static int computeSignal(unsigned int tt) return SIGHUP; /* default for things we don't know about */ } -/** - * - * kgdb_skipexception - Bail out of KGDB when we've been triggered. - * @exception: Exception vector number - * @regs: Current &struct pt_regs. - * - * On some architectures we need to skip a breakpoint exception when - * it occurs after a breakpoint has been removed. - * - */ -int kgdb_skipexception(int exception, struct pt_regs *regs) -{ - return kgdb_isremovedbreak(regs->nip); -} - static int kgdb_call_nmi_hook(struct pt_regs *regs) { kgdb_nmicallback(raw_smp_processor_id(), regs); @@ -154,8 +138,6 @@ static int kgdb_handle_breakpoint(struct pt_regs *regs) static int kgdb_singlestep(struct pt_regs *regs) { struct thread_info *thread_info, *exception_thread_info; - struct thread_info *backup_current_thread_info = \ - (struct thread_info *)kmalloc(sizeof(struct thread_info), GFP_KERNEL); if (user_mode(regs)) return 0; @@ -173,17 +155,13 @@ static int kgdb_singlestep(struct pt_regs *regs) thread_info = (struct thread_info *)(regs->gpr[1] & ~(THREAD_SIZE-1)); exception_thread_info = current_thread_info(); - if (thread_info != exception_thread_info) { - /* Save the original current_thread_info. */ - memcpy(backup_current_thread_info, exception_thread_info, sizeof *thread_info); + if (thread_info != exception_thread_info) memcpy(exception_thread_info, thread_info, sizeof *thread_info); - } kgdb_handle_exception(0, SIGTRAP, 0, regs); if (thread_info != exception_thread_info) - /* Restore current_thread_info lastly. */ - memcpy(exception_thread_info, backup_current_thread_info, sizeof *thread_info); + memcpy(thread_info, exception_thread_info, sizeof *thread_info); return 1; } @@ -432,6 +410,7 @@ int kgdb_arch_handle_exception(int vector, int signo, int err_code, #else linux_regs->msr |= MSR_SE; #endif + kgdb_single_step = 1; atomic_set(&kgdb_cpu_doing_single_step, raw_smp_processor_id()); } diff --git a/trunk/arch/powerpc/kernel/pci-common.c b/trunk/arch/powerpc/kernel/pci-common.c index 43fea543d686..2aa04f29e1de 100644 --- a/trunk/arch/powerpc/kernel/pci-common.c +++ b/trunk/arch/powerpc/kernel/pci-common.c @@ -99,26 +99,6 @@ void pcibios_free_controller(struct pci_controller *phb) kfree(phb); } -/* - * The function is used to return the minimal alignment - * for memory or I/O windows of the associated P2P bridge. - * By default, 4KiB alignment for I/O windows and 1MiB for - * memory windows. - */ -resource_size_t pcibios_window_alignment(struct pci_bus *bus, - unsigned long type) -{ - if (ppc_md.pcibios_window_alignment) - return ppc_md.pcibios_window_alignment(bus, type); - - /* - * PCI core will figure out the default - * alignment: 4KiB for I/O and 1MiB for - * memory window. - */ - return 1; -} - static resource_size_t pcibios_io_size(const struct pci_controller *hose) { #ifdef CONFIG_PPC64 diff --git a/trunk/arch/powerpc/kernel/process.c b/trunk/arch/powerpc/kernel/process.c index e9cb51f5f801..710f400476de 100644 --- a/trunk/arch/powerpc/kernel/process.c +++ b/trunk/arch/powerpc/kernel/process.c @@ -514,6 +514,9 @@ struct task_struct *__switch_to(struct task_struct *prev, local_irq_save(flags); + account_system_vtime(current); + account_process_vtime(current); + /* * We can't take a PMU exception inside _switch() since there is a * window where the kernel stack SLB and the kernel stack are out @@ -799,8 +802,16 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, #endif /* CONFIG_PPC_STD_MMU_64 */ #ifdef CONFIG_PPC64 if (cpu_has_feature(CPU_FTR_DSCR)) { - p->thread.dscr_inherit = current->thread.dscr_inherit; - p->thread.dscr = current->thread.dscr; + if (current->thread.dscr_inherit) { + p->thread.dscr_inherit = 1; + p->thread.dscr = current->thread.dscr; + } else if (0 != dscr_default) { + p->thread.dscr_inherit = 1; + p->thread.dscr = dscr_default; + } else { + p->thread.dscr_inherit = 0; + p->thread.dscr = 0; + } } #endif diff --git a/trunk/arch/powerpc/kernel/smp.c b/trunk/arch/powerpc/kernel/smp.c index 8d4214afc21d..0321007086f7 100644 --- a/trunk/arch/powerpc/kernel/smp.c +++ b/trunk/arch/powerpc/kernel/smp.c @@ -198,15 +198,8 @@ void smp_muxed_ipi_message_pass(int cpu, int msg) struct cpu_messages *info = &per_cpu(ipi_message, cpu); char *message = (char *)&info->messages; - /* - * Order previous accesses before accesses in the IPI handler. - */ - smp_mb(); message[msg] = 1; - /* - * cause_ipi functions are required to include a full barrier - * before doing whatever causes the IPI. - */ + mb(); smp_ops->cause_ipi(cpu, info->data); } @@ -218,7 +211,7 @@ irqreturn_t smp_ipi_demux(void) mb(); /* order any irq clear */ do { - all = xchg(&info->messages, 0); + all = xchg_local(&info->messages, 0); #ifdef __BIG_ENDIAN if (all & (1 << (24 - 8 * PPC_MSG_CALL_FUNCTION))) diff --git a/trunk/arch/powerpc/kernel/syscalls.c b/trunk/arch/powerpc/kernel/syscalls.c index 4e3cc47f26b9..f2496f2faecc 100644 --- a/trunk/arch/powerpc/kernel/syscalls.c +++ b/trunk/arch/powerpc/kernel/syscalls.c @@ -107,11 +107,11 @@ long ppc64_personality(unsigned long personality) long ret; if (personality(current->personality) == PER_LINUX32 - && personality(personality) == PER_LINUX) - personality = (personality & ~PER_MASK) | PER_LINUX32; + && personality == PER_LINUX) + personality = PER_LINUX32; ret = sys_personality(personality); - if (personality(ret) == PER_LINUX32) - ret = (ret & ~PER_MASK) | PER_LINUX; + if (ret == PER_LINUX32) + ret = PER_LINUX; return ret; } #endif diff --git a/trunk/arch/powerpc/kernel/sysfs.c b/trunk/arch/powerpc/kernel/sysfs.c index 8302af649219..3529446c2abd 100644 --- a/trunk/arch/powerpc/kernel/sysfs.c +++ b/trunk/arch/powerpc/kernel/sysfs.c @@ -194,14 +194,6 @@ static ssize_t show_dscr_default(struct device *dev, return sprintf(buf, "%lx\n", dscr_default); } -static void update_dscr(void *dummy) -{ - if (!current->thread.dscr_inherit) { - current->thread.dscr = dscr_default; - mtspr(SPRN_DSCR, dscr_default); - } -} - static ssize_t __used store_dscr_default(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) @@ -214,8 +206,6 @@ static ssize_t __used store_dscr_default(struct device *dev, return -EINVAL; dscr_default = val; - on_each_cpu(update_dscr, NULL, 1); - return count; } diff --git a/trunk/arch/powerpc/kernel/time.c b/trunk/arch/powerpc/kernel/time.c index eaa9d0e6abca..be171ee73bf8 100644 --- a/trunk/arch/powerpc/kernel/time.c +++ b/trunk/arch/powerpc/kernel/time.c @@ -291,12 +291,13 @@ static inline u64 calculate_stolen_time(u64 stop_tb) * Account time for a transition between system, hard irq * or soft irq state. */ -static u64 vtime_delta(struct task_struct *tsk, - u64 *sys_scaled, u64 *stolen) +void account_system_vtime(struct task_struct *tsk) { - u64 now, nowscaled, deltascaled; - u64 udelta, delta, user_scaled; + u64 now, nowscaled, delta, deltascaled; + unsigned long flags; + u64 stolen, udelta, sys_scaled, user_scaled; + local_irq_save(flags); now = mftb(); nowscaled = read_spurr(now); get_paca()->system_time += now - get_paca()->starttime; @@ -304,7 +305,7 @@ static u64 vtime_delta(struct task_struct *tsk, deltascaled = nowscaled - get_paca()->startspurr; get_paca()->startspurr = nowscaled; - *stolen = calculate_stolen_time(now); + stolen = calculate_stolen_time(now); delta = get_paca()->system_time; get_paca()->system_time = 0; @@ -321,45 +322,35 @@ static u64 vtime_delta(struct task_struct *tsk, * the user ticks get saved up in paca->user_time_scaled to be * used by account_process_tick. */ - *sys_scaled = delta; + sys_scaled = delta; user_scaled = udelta; if (deltascaled != delta + udelta) { if (udelta) { - *sys_scaled = deltascaled * delta / (delta + udelta); - user_scaled = deltascaled - *sys_scaled; + sys_scaled = deltascaled * delta / (delta + udelta); + user_scaled = deltascaled - sys_scaled; } else { - *sys_scaled = deltascaled; + sys_scaled = deltascaled; } } get_paca()->user_time_scaled += user_scaled; - return delta; -} - -void vtime_account_system(struct task_struct *tsk) -{ - u64 delta, sys_scaled, stolen; - - delta = vtime_delta(tsk, &sys_scaled, &stolen); - account_system_time(tsk, 0, delta, sys_scaled); - if (stolen) - account_steal_time(stolen); -} - -void vtime_account_idle(struct task_struct *tsk) -{ - u64 delta, sys_scaled, stolen; - - delta = vtime_delta(tsk, &sys_scaled, &stolen); - account_idle_time(delta + stolen); + if (in_interrupt() || idle_task(smp_processor_id()) != tsk) { + account_system_time(tsk, 0, delta, sys_scaled); + if (stolen) + account_steal_time(stolen); + } else { + account_idle_time(delta + stolen); + } + local_irq_restore(flags); } +EXPORT_SYMBOL_GPL(account_system_vtime); /* * Transfer the user and system times accumulated in the paca * by the exception entry and exit code to the generic process * user and system time records. * Must be called with interrupts disabled. - * Assumes that vtime_account() has been called recently + * Assumes that account_system_vtime() has been called recently * (i.e. since the last entry from usermode) so that * get_paca()->user_time_scaled is up to date. */ @@ -375,12 +366,6 @@ void account_process_tick(struct task_struct *tsk, int user_tick) account_user_time(tsk, utime, utimescaled); } -void vtime_task_switch(struct task_struct *prev) -{ - vtime_account(prev); - account_process_tick(prev, 0); -} - #else /* ! CONFIG_VIRT_CPU_ACCOUNTING */ #define calc_cputime_factors() #endif @@ -550,15 +535,6 @@ void timer_interrupt(struct pt_regs * regs) trace_timer_interrupt_exit(regs); } -/* - * Hypervisor decrementer interrupts shouldn't occur but are sometimes - * left pending on exit from a KVM guest. We don't need to do anything - * to clear them, as they are edge-triggered. - */ -void hdec_interrupt(struct pt_regs *regs) -{ -} - #ifdef CONFIG_SUSPEND static void generic_suspend_disable_irqs(void) { diff --git a/trunk/arch/powerpc/kernel/traps.c b/trunk/arch/powerpc/kernel/traps.c index ae0843fa7a61..158972341a2d 100644 --- a/trunk/arch/powerpc/kernel/traps.c +++ b/trunk/arch/powerpc/kernel/traps.c @@ -972,9 +972,8 @@ static int emulate_instruction(struct pt_regs *regs) cpu_has_feature(CPU_FTR_DSCR)) { PPC_WARN_EMULATED(mtdscr, regs); rd = (instword >> 21) & 0x1f; - current->thread.dscr = regs->gpr[rd]; + mtspr(SPRN_DSCR, regs->gpr[rd]); current->thread.dscr_inherit = 1; - mtspr(SPRN_DSCR, current->thread.dscr); return 0; } #endif diff --git a/trunk/arch/powerpc/kvm/book3s_32_mmu_host.c b/trunk/arch/powerpc/kvm/book3s_32_mmu_host.c index 837f13e7b6bf..f922c29bb234 100644 --- a/trunk/arch/powerpc/kvm/book3s_32_mmu_host.c +++ b/trunk/arch/powerpc/kvm/book3s_32_mmu_host.c @@ -211,9 +211,6 @@ int kvmppc_mmu_map_page(struct kvm_vcpu *vcpu, struct kvmppc_pte *orig_pte) pteg1 |= PP_RWRX; } - if (orig_pte->may_execute) - kvmppc_mmu_flush_icache(hpaddr >> PAGE_SHIFT); - local_irq_disable(); if (pteg[rr]) { diff --git a/trunk/arch/powerpc/kvm/book3s_64_mmu_host.c b/trunk/arch/powerpc/kvm/book3s_64_mmu_host.c index 0688b6b39585..10fc8ec9d2a8 100644 --- a/trunk/arch/powerpc/kvm/book3s_64_mmu_host.c +++ b/trunk/arch/powerpc/kvm/book3s_64_mmu_host.c @@ -126,8 +126,6 @@ int kvmppc_mmu_map_page(struct kvm_vcpu *vcpu, struct kvmppc_pte *orig_pte) if (!orig_pte->may_execute) rflags |= HPTE_R_N; - else - kvmppc_mmu_flush_icache(hpaddr >> PAGE_SHIFT); hash = hpt_hash(va, PTE_SIZE, MMU_SEGSIZE_256M); diff --git a/trunk/arch/powerpc/kvm/book3s_hv_rmhandlers.S b/trunk/arch/powerpc/kvm/book3s_hv_rmhandlers.S index 44b72feaff7d..5a84c8d3d040 100644 --- a/trunk/arch/powerpc/kvm/book3s_hv_rmhandlers.S +++ b/trunk/arch/powerpc/kvm/book3s_hv_rmhandlers.S @@ -1421,13 +1421,13 @@ _GLOBAL(kvmppc_h_cede) sync /* order setting ceded vs. testing prodded */ lbz r5,VCPU_PRODDED(r3) cmpwi r5,0 - bne kvm_cede_prodded + bne 1f li r0,0 /* set trap to 0 to say hcall is handled */ stw r0,VCPU_TRAP(r3) li r0,H_SUCCESS std r0,VCPU_GPR(R3)(r3) BEGIN_FTR_SECTION - b kvm_cede_exit /* just send it up to host on 970 */ + b 2f /* just send it up to host on 970 */ END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_206) /* @@ -1446,7 +1446,7 @@ END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_206) or r4,r4,r0 PPC_POPCNTW(R7,R4) cmpw r7,r8 - bge kvm_cede_exit + bge 2f stwcx. r4,0,r6 bne 31b li r0,1 @@ -1555,8 +1555,7 @@ kvm_end_cede: b hcall_real_fallback /* cede when already previously prodded case */ -kvm_cede_prodded: - li r0,0 +1: li r0,0 stb r0,VCPU_PRODDED(r3) sync /* order testing prodded vs. clearing ceded */ stb r0,VCPU_CEDED(r3) @@ -1564,8 +1563,7 @@ kvm_cede_prodded: blr /* we've ceded but we want to give control to the host */ -kvm_cede_exit: - li r3,H_TOO_HARD +2: li r3,H_TOO_HARD blr secondary_too_late: diff --git a/trunk/arch/powerpc/kvm/e500_tlb.c b/trunk/arch/powerpc/kvm/e500_tlb.c index a2b66717813d..c510fc961302 100644 --- a/trunk/arch/powerpc/kvm/e500_tlb.c +++ b/trunk/arch/powerpc/kvm/e500_tlb.c @@ -322,11 +322,11 @@ static inline void kvmppc_e500_ref_release(struct tlbe_ref *ref) static void clear_tlb1_bitmap(struct kvmppc_vcpu_e500 *vcpu_e500) { if (vcpu_e500->g2h_tlb1_map) - memset(vcpu_e500->g2h_tlb1_map, 0, - sizeof(u64) * vcpu_e500->gtlb_params[1].entries); + memset(vcpu_e500->g2h_tlb1_map, + sizeof(u64) * vcpu_e500->gtlb_params[1].entries, 0); if (vcpu_e500->h2g_tlb1_rmap) - memset(vcpu_e500->h2g_tlb1_rmap, 0, - sizeof(unsigned int) * host_tlb_params[1].entries); + memset(vcpu_e500->h2g_tlb1_rmap, + sizeof(unsigned int) * host_tlb_params[1].entries, 0); } static void clear_tlb_privs(struct kvmppc_vcpu_e500 *vcpu_e500) @@ -539,9 +539,6 @@ static inline void kvmppc_e500_shadow_map(struct kvmppc_vcpu_e500 *vcpu_e500, kvmppc_e500_setup_stlbe(&vcpu_e500->vcpu, gtlbe, tsize, ref, gvaddr, stlbe); - - /* Clear i-cache for new pages */ - kvmppc_mmu_flush_icache(pfn); } /* XXX only map the one-one case, for now use TLB0 */ diff --git a/trunk/arch/powerpc/lib/code-patching.c b/trunk/arch/powerpc/lib/code-patching.c index 17e5b2364312..dd223b3eb333 100644 --- a/trunk/arch/powerpc/lib/code-patching.c +++ b/trunk/arch/powerpc/lib/code-patching.c @@ -20,7 +20,7 @@ int patch_instruction(unsigned int *addr, unsigned int instr) { int err; - __put_user_size(instr, addr, 4, err); + err = __put_user(instr, addr); if (err) return err; asm ("dcbst 0, %0; sync; icbi 0,%0; sync; isync" : : "r" (addr)); diff --git a/trunk/arch/powerpc/lib/copyuser_power7.S b/trunk/arch/powerpc/lib/copyuser_power7.S index 0d24ff15f5f6..f9ede7c6606e 100644 --- a/trunk/arch/powerpc/lib/copyuser_power7.S +++ b/trunk/arch/powerpc/lib/copyuser_power7.S @@ -288,7 +288,7 @@ err1; stb r0,0(r3) std r0,16(r1) stdu r1,-STACKFRAMESIZE(r1) bl .enter_vmx_usercopy - cmpwi cr1,r3,0 + cmpwi r3,0 ld r0,STACKFRAMESIZE+16(r1) ld r3,STACKFRAMESIZE+48(r1) ld r4,STACKFRAMESIZE+56(r1) @@ -326,7 +326,38 @@ err1; stb r0,0(r3) dcbt r0,r8,0b01010 /* GO */ .machine pop - beq cr1,.Lunwind_stack_nonvmx_copy + /* + * We prefetch both the source and destination using enhanced touch + * instructions. We use a stream ID of 0 for the load side and + * 1 for the store side. + */ + clrrdi r6,r4,7 + clrrdi r9,r3,7 + ori r9,r9,1 /* stream=1 */ + + srdi r7,r5,7 /* length in cachelines, capped at 0x3FF */ + cmpldi cr1,r7,0x3FF + ble cr1,1f + li r7,0x3FF +1: lis r0,0x0E00 /* depth=7 */ + sldi r7,r7,7 + or r7,r7,r0 + ori r10,r7,1 /* stream=1 */ + + lis r8,0x8000 /* GO=1 */ + clrldi r8,r8,32 + +.machine push +.machine "power4" + dcbt r0,r6,0b01000 + dcbt r0,r7,0b01010 + dcbtst r0,r9,0b01000 + dcbtst r0,r10,0b01010 + eieio + dcbt r0,r8,0b01010 /* GO */ +.machine pop + + beq .Lunwind_stack_nonvmx_copy /* * If source and destination are not relatively aligned we use a diff --git a/trunk/arch/powerpc/lib/memcpy_power7.S b/trunk/arch/powerpc/lib/memcpy_power7.S index 7ba6c96de778..0efdc51bc716 100644 --- a/trunk/arch/powerpc/lib/memcpy_power7.S +++ b/trunk/arch/powerpc/lib/memcpy_power7.S @@ -222,7 +222,7 @@ _GLOBAL(memcpy_power7) std r0,16(r1) stdu r1,-STACKFRAMESIZE(r1) bl .enter_vmx_copy - cmpwi cr1,r3,0 + cmpwi r3,0 ld r0,STACKFRAMESIZE+16(r1) ld r3,STACKFRAMESIZE+48(r1) ld r4,STACKFRAMESIZE+56(r1) @@ -260,7 +260,7 @@ _GLOBAL(memcpy_power7) dcbt r0,r8,0b01010 /* GO */ .machine pop - beq cr1,.Lunwind_stack_nonvmx_copy + beq .Lunwind_stack_nonvmx_copy /* * If source and destination are not relatively aligned we use a diff --git a/trunk/arch/powerpc/mm/mem.c b/trunk/arch/powerpc/mm/mem.c index fbdad0e3929a..baaafde7d135 100644 --- a/trunk/arch/powerpc/mm/mem.c +++ b/trunk/arch/powerpc/mm/mem.c @@ -469,7 +469,6 @@ void flush_dcache_icache_page(struct page *page) __flush_dcache_icache_phys(page_to_pfn(page) << PAGE_SHIFT); #endif } -EXPORT_SYMBOL(flush_dcache_icache_page); void clear_user_page(void *page, unsigned long vaddr, struct page *pg) { diff --git a/trunk/arch/powerpc/mm/numa.c b/trunk/arch/powerpc/mm/numa.c index 59213cfaeca9..39b159751c35 100644 --- a/trunk/arch/powerpc/mm/numa.c +++ b/trunk/arch/powerpc/mm/numa.c @@ -1436,11 +1436,11 @@ static long vphn_get_associativity(unsigned long cpu, /* * Update the node maps and sysfs entries for each cpu whose home node - * has changed. Returns 1 when the topology has changed, and 0 otherwise. + * has changed. */ int arch_update_cpu_topology(void) { - int cpu, nid, old_nid, changed = 0; + int cpu, nid, old_nid; unsigned int associativity[VPHN_ASSOC_BUFSIZE] = {0}; struct device *dev; @@ -1466,10 +1466,9 @@ int arch_update_cpu_topology(void) dev = get_cpu_device(cpu); if (dev) kobject_uevent(&dev->kobj, KOBJ_CHANGE); - changed = 1; } - return changed; + return 1; } static void topology_work_fn(struct work_struct *work) diff --git a/trunk/arch/powerpc/perf/core-book3s.c b/trunk/arch/powerpc/perf/core-book3s.c index 7cd2dbd6e4c4..77b49ddda9d3 100644 --- a/trunk/arch/powerpc/perf/core-book3s.c +++ b/trunk/arch/powerpc/perf/core-book3s.c @@ -1431,7 +1431,7 @@ static void perf_event_interrupt(struct pt_regs *regs) if (!event->hw.idx || is_limited_pmc(event->hw.idx)) continue; val = read_pmc(event->hw.idx); - if (pmc_overflow(val)) { + if ((int)val < 0) { /* event has overflowed */ found = 1; record_and_restart(event, val, regs); diff --git a/trunk/arch/powerpc/platforms/Kconfig.cputype b/trunk/arch/powerpc/platforms/Kconfig.cputype index 72afd2888cad..30fd01de6bed 100644 --- a/trunk/arch/powerpc/platforms/Kconfig.cputype +++ b/trunk/arch/powerpc/platforms/Kconfig.cputype @@ -1,7 +1,6 @@ config PPC64 bool "64-bit kernel" default n - select HAVE_VIRT_CPU_ACCOUNTING help This option selects whether a 32-bit or a 64-bit kernel will be built. @@ -338,6 +337,21 @@ config PPC_MM_SLICES default y if (!PPC_FSL_BOOK3E && PPC64 && HUGETLB_PAGE) || (PPC_STD_MMU_64 && PPC_64K_PAGES) default n +config VIRT_CPU_ACCOUNTING + bool "Deterministic task and CPU time accounting" + depends on PPC64 + default y + help + Select this option to enable more accurate task and CPU time + accounting. This is done by reading a CPU counter on each + kernel entry and exit and on transitions within the kernel + between system, softirq and hardirq state, so there is a + small performance impact. This also enables accounting of + stolen time on logically-partitioned systems running on + IBM POWER5-based machines. + + If in doubt, say Y here. + config PPC_HAVE_PMU_SUPPORT bool diff --git a/trunk/arch/powerpc/platforms/powernv/pci-ioda.c b/trunk/arch/powerpc/platforms/powernv/pci-ioda.c index 0e7eccc0f88d..9cda6a1ad0cf 100644 --- a/trunk/arch/powerpc/platforms/powernv/pci-ioda.c +++ b/trunk/arch/powerpc/platforms/powernv/pci-ioda.c @@ -855,7 +855,7 @@ static void __devinit pnv_ioda_setup_PEs(struct pci_bus *bus) if (pe == NULL) continue; /* Leaving the PCIe domain ... single PE# */ - if (pci_pcie_type(dev) == PCI_EXP_TYPE_PCI_BRIDGE) + if (dev->pcie_type == PCI_EXP_TYPE_PCI_BRIDGE) pnv_ioda_setup_bus_PE(dev, pe); else if (dev->subordinate) pnv_ioda_setup_PEs(dev->subordinate); @@ -1139,44 +1139,6 @@ static void __devinit pnv_pci_ioda_fixup_phb(struct pci_controller *hose) } } -/* - * Returns the alignment for I/O or memory windows for P2P - * bridges. That actually depends on how PEs are segmented. - * For now, we return I/O or M32 segment size for PE sensitive - * P2P bridges. Otherwise, the default values (4KiB for I/O, - * 1MiB for memory) will be returned. - * - * The current PCI bus might be put into one PE, which was - * create against the parent PCI bridge. For that case, we - * needn't enlarge the alignment so that we can save some - * resources. - */ -static resource_size_t pnv_pci_window_alignment(struct pci_bus *bus, - unsigned long type) -{ - struct pci_dev *bridge; - struct pci_controller *hose = pci_bus_to_host(bus); - struct pnv_phb *phb = hose->private_data; - int num_pci_bridges = 0; - - bridge = bus->self; - while (bridge) { - if (pci_pcie_type(bridge) == PCI_EXP_TYPE_PCI_BRIDGE) { - num_pci_bridges++; - if (num_pci_bridges >= 2) - return 1; - } - - bridge = bridge->bus->self; - } - - /* We need support prefetchable memory window later */ - if (type & IORESOURCE_MEM) - return phb->ioda.m32_segsize; - - return phb->ioda.io_segsize; -} - /* Prevent enabling devices for which we couldn't properly * assign a PE */ @@ -1344,7 +1306,6 @@ void __init pnv_pci_init_ioda1_phb(struct device_node *np) */ ppc_md.pcibios_fixup_phb = pnv_pci_ioda_fixup_phb; ppc_md.pcibios_enable_device_hook = pnv_pci_enable_device_hook; - ppc_md.pcibios_window_alignment = pnv_pci_window_alignment; pci_add_flags(PCI_PROBE_ONLY | PCI_REASSIGN_ALL_RSRC); /* Reset IODA tables to a clean state */ diff --git a/trunk/arch/powerpc/platforms/powernv/smp.c b/trunk/arch/powerpc/platforms/powernv/smp.c index 7698b6e13c57..3ef46254c35b 100644 --- a/trunk/arch/powerpc/platforms/powernv/smp.c +++ b/trunk/arch/powerpc/platforms/powernv/smp.c @@ -106,6 +106,14 @@ static void pnv_smp_cpu_kill_self(void) { unsigned int cpu; + /* If powersave_nap is enabled, use NAP mode, else just + * spin aimlessly + */ + if (!powersave_nap) { + generic_mach_cpu_die(); + return; + } + /* Standard hot unplug procedure */ local_irq_disable(); idle_task_exit(); @@ -120,7 +128,7 @@ static void pnv_smp_cpu_kill_self(void) */ mtspr(SPRN_LPCR, mfspr(SPRN_LPCR) & ~(u64)LPCR_PECE1); while (!generic_check_cpu_restart(cpu)) { - power7_nap(); + power7_idle(); if (!generic_check_cpu_restart(cpu)) { DBG("CPU%d Unexpected exit while offline !\n", cpu); /* We may be getting an IPI, so we re-enable diff --git a/trunk/arch/powerpc/sysdev/fsl_pci.c b/trunk/arch/powerpc/sysdev/fsl_pci.c index c37f46136321..a7b2a600d0a4 100644 --- a/trunk/arch/powerpc/sysdev/fsl_pci.c +++ b/trunk/arch/powerpc/sysdev/fsl_pci.c @@ -465,7 +465,7 @@ int __init fsl_add_bridge(struct device_node *dev, int is_primary) iounmap(hose->cfg_data); iounmap(hose->cfg_addr); pcibios_free_controller(hose); - return -ENODEV; + return 0; } setup_pci_cmd(hose); @@ -827,7 +827,6 @@ struct device_node *fsl_pci_primary; void __devinit fsl_pci_init(void) { - int ret; struct device_node *node; struct pci_controller *hose; dma_addr_t max = 0xffffffff; @@ -856,12 +855,10 @@ void __devinit fsl_pci_init(void) if (!fsl_pci_primary) fsl_pci_primary = node; - ret = fsl_add_bridge(node, fsl_pci_primary == node); - if (ret == 0) { - hose = pci_find_hose_for_OF_device(node); - max = min(max, hose->dma_window_base_cur + - hose->dma_window_size); - } + fsl_add_bridge(node, fsl_pci_primary == node); + hose = pci_find_hose_for_OF_device(node); + max = min(max, hose->dma_window_base_cur + + hose->dma_window_size); } } diff --git a/trunk/arch/powerpc/sysdev/mpic_msgr.c b/trunk/arch/powerpc/sysdev/mpic_msgr.c index e961f8c4a8f0..483d8fa72e8b 100644 --- a/trunk/arch/powerpc/sysdev/mpic_msgr.c +++ b/trunk/arch/powerpc/sysdev/mpic_msgr.c @@ -14,9 +14,6 @@ #include #include #include -#include -#include -#include #include #include #include diff --git a/trunk/arch/powerpc/sysdev/xics/icp-hv.c b/trunk/arch/powerpc/sysdev/xics/icp-hv.c index df0fc5821469..14469cf9df68 100644 --- a/trunk/arch/powerpc/sysdev/xics/icp-hv.c +++ b/trunk/arch/powerpc/sysdev/xics/icp-hv.c @@ -65,11 +65,7 @@ static inline void icp_hv_set_xirr(unsigned int value) static inline void icp_hv_set_qirr(int n_cpu , u8 value) { int hw_cpu = get_hard_smp_processor_id(n_cpu); - long rc; - - /* Make sure all previous accesses are ordered before IPI sending */ - mb(); - rc = plpar_hcall_norets(H_IPI, hw_cpu, value); + long rc = plpar_hcall_norets(H_IPI, hw_cpu, value); if (rc != H_SUCCESS) { pr_err("%s: bad return code qirr cpu=%d hw_cpu=%d mfrr=0x%x " "returned %ld\n", __func__, n_cpu, hw_cpu, value, rc); diff --git a/trunk/arch/powerpc/xmon/xmon.c b/trunk/arch/powerpc/xmon/xmon.c index 9b49c65ee7a4..eab3492a45c5 100644 --- a/trunk/arch/powerpc/xmon/xmon.c +++ b/trunk/arch/powerpc/xmon/xmon.c @@ -17,7 +17,6 @@ #include #include #include -#include #include #include #include @@ -895,13 +894,13 @@ cmds(struct pt_regs *excp) #endif default: printf("Unrecognized command: "); - do { + do { if (' ' < cmd && cmd <= '~') putchar(cmd); else printf("\\x%x", cmd); cmd = inchar(); - } while (cmd != '\n'); + } while (cmd != '\n'); printf(" (type ? for help)\n"); break; } @@ -1098,7 +1097,7 @@ static long check_bp_loc(unsigned long addr) return 1; } -static char *breakpoint_help_string = +static char *breakpoint_help_string = "Breakpoint command usage:\n" "b show breakpoints\n" "b [cnt] set breakpoint at given instr addr\n" @@ -1194,7 +1193,7 @@ bpt_cmds(void) default: termch = cmd; - cmd = skipbl(); + cmd = skipbl(); if (cmd == '?') { printf(breakpoint_help_string); break; @@ -1360,7 +1359,7 @@ static void xmon_show_stack(unsigned long sp, unsigned long lr, sp + REGS_OFFSET); break; } - printf("--- Exception: %lx %s at ", regs.trap, + printf("--- Exception: %lx %s at ", regs.trap, getvecname(TRAP(®s))); pc = regs.nip; lr = regs.link; @@ -1624,14 +1623,14 @@ static void super_regs(void) cmd = skipbl(); if (cmd == '\n') { - unsigned long sp, toc; + unsigned long sp, toc; asm("mr %0,1" : "=r" (sp) :); asm("mr %0,2" : "=r" (toc) :); printf("msr = "REG" sprg0= "REG"\n", mfmsr(), mfspr(SPRN_SPRG0)); printf("pvr = "REG" sprg1= "REG"\n", - mfspr(SPRN_PVR), mfspr(SPRN_SPRG1)); + mfspr(SPRN_PVR), mfspr(SPRN_SPRG1)); printf("dec = "REG" sprg2= "REG"\n", mfspr(SPRN_DEC), mfspr(SPRN_SPRG2)); printf("sp = "REG" sprg3= "REG"\n", sp, mfspr(SPRN_SPRG3)); @@ -1784,7 +1783,7 @@ byterev(unsigned char *val, int size) static int brev; static int mnoread; -static char *memex_help_string = +static char *memex_help_string = "Memory examine command usage:\n" "m [addr] [flags] examine/change memory\n" " addr is optional. will start where left off.\n" @@ -1799,7 +1798,7 @@ static char *memex_help_string = "NOTE: flags are saved as defaults\n" ""; -static char *memex_subcmd_help_string = +static char *memex_subcmd_help_string = "Memory examine subcommands:\n" " hexval write this val to current location\n" " 'string' write chars from string to this location\n" @@ -2065,7 +2064,7 @@ prdump(unsigned long adrs, long ndump) nr = mread(adrs, temp, r); adrs += nr; for (m = 0; m < r; ++m) { - if ((m & (sizeof(long) - 1)) == 0 && m > 0) + if ((m & (sizeof(long) - 1)) == 0 && m > 0) putchar(' '); if (m < nr) printf("%.2x", temp[m]); @@ -2073,7 +2072,7 @@ prdump(unsigned long adrs, long ndump) printf("%s", fault_chars[fault_type]); } for (; m < 16; ++m) { - if ((m & (sizeof(long) - 1)) == 0) + if ((m & (sizeof(long) - 1)) == 0) putchar(' '); printf(" "); } @@ -2149,28 +2148,45 @@ print_address(unsigned long addr) void dump_log_buf(void) { - struct kmsg_dumper dumper = { .active = 1 }; - unsigned char buf[128]; - size_t len; - - if (setjmp(bus_error_jmp) != 0) { - printf("Error dumping printk buffer!\n"); - return; - } - - catch_memory_errors = 1; - sync(); - - kmsg_dump_rewind_nolock(&dumper); - while (kmsg_dump_get_line_nolock(&dumper, false, buf, sizeof(buf), &len)) { - buf[len] = '\0'; - printf("%s", buf); - } - - sync(); - /* wait a little while to see if we get a machine check */ - __delay(200); - catch_memory_errors = 0; + const unsigned long size = 128; + unsigned long end, addr; + unsigned char buf[size + 1]; + + addr = 0; + buf[size] = '\0'; + + if (setjmp(bus_error_jmp) != 0) { + printf("Unable to lookup symbol __log_buf!\n"); + return; + } + + catch_memory_errors = 1; + sync(); + addr = kallsyms_lookup_name("__log_buf"); + + if (! addr) + printf("Symbol __log_buf not found!\n"); + else { + end = addr + (1 << CONFIG_LOG_BUF_SHIFT); + while (addr < end) { + if (! mread(addr, buf, size)) { + printf("Can't read memory at address 0x%lx\n", addr); + break; + } + + printf("%s", buf); + + if (strlen(buf) < size) + break; + + addr += size; + } + } + + sync(); + /* wait a little while to see if we get a machine check */ + __delay(200); + catch_memory_errors = 0; } /* diff --git a/trunk/arch/s390/Kbuild b/trunk/arch/s390/Kbuild index cc45d25487b0..9858476fa0fe 100644 --- a/trunk/arch/s390/Kbuild +++ b/trunk/arch/s390/Kbuild @@ -5,4 +5,3 @@ obj-$(CONFIG_CRYPTO_HW) += crypto/ obj-$(CONFIG_S390_HYPFS_FS) += hypfs/ obj-$(CONFIG_APPLDATA_BASE) += appldata/ obj-$(CONFIG_MATHEMU) += math-emu/ -obj-y += net/ diff --git a/trunk/arch/s390/Kconfig b/trunk/arch/s390/Kconfig index f9acddd9ace3..76de6b68487c 100644 --- a/trunk/arch/s390/Kconfig +++ b/trunk/arch/s390/Kconfig @@ -49,13 +49,10 @@ config GENERIC_LOCKBREAK config PGSTE def_bool y if KVM -config ARCH_SUPPORTS_DEBUG_PAGEALLOC - def_bool y - -config KEXEC +config VIRT_CPU_ACCOUNTING def_bool y -config AUDIT_ARCH +config ARCH_SUPPORTS_DEBUG_PAGEALLOC def_bool y config S390 @@ -87,15 +84,11 @@ config S390 select HAVE_KERNEL_XZ select HAVE_ARCH_MUTEX_CPU_RELAX select HAVE_ARCH_JUMP_LABEL if !MARCH_G5 - select HAVE_BPF_JIT if 64BIT && PACK_STACK select ARCH_SAVE_PAGE_KEYS if HIBERNATION select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE select HAVE_MEMBLOCK select HAVE_MEMBLOCK_NODE_MAP select HAVE_CMPXCHG_LOCAL - select HAVE_CMPXCHG_DOUBLE - select HAVE_VIRT_CPU_ACCOUNTING - select VIRT_CPU_ACCOUNTING select ARCH_DISCARD_MEMBLOCK select BUILDTIME_EXTABLE_SORT select ARCH_INLINE_SPIN_TRYLOCK @@ -131,7 +124,6 @@ config S390 select GENERIC_TIME_VSYSCALL select GENERIC_CLOCKEVENTS select KTIME_SCALAR if 32BIT - select HAVE_ARCH_SECCOMP_FILTER config SCHED_OMIT_FRAME_POINTER def_bool y @@ -140,79 +132,9 @@ source "init/Kconfig" source "kernel/Kconfig.freezer" -menu "Processor type and features" - -config HAVE_MARCH_Z900_FEATURES - def_bool n - -config HAVE_MARCH_Z990_FEATURES - def_bool n - select HAVE_MARCH_Z900_FEATURES - -config HAVE_MARCH_Z9_109_FEATURES - def_bool n - select HAVE_MARCH_Z990_FEATURES - -config HAVE_MARCH_Z10_FEATURES - def_bool n - select HAVE_MARCH_Z9_109_FEATURES - -config HAVE_MARCH_Z196_FEATURES - def_bool n - select HAVE_MARCH_Z10_FEATURES - -choice - prompt "Processor type" - default MARCH_G5 - -config MARCH_G5 - bool "System/390 model G5 and G6" - depends on !64BIT - help - Select this to build a 31 bit kernel that works - on all ESA/390 and z/Architecture machines. +menu "Base setup" -config MARCH_Z900 - bool "IBM zSeries model z800 and z900" - select HAVE_MARCH_Z900_FEATURES if 64BIT - help - Select this to enable optimizations for model z800/z900 (2064 and - 2066 series). This will enable some optimizations that are not - available on older ESA/390 (31 Bit) only CPUs. - -config MARCH_Z990 - bool "IBM zSeries model z890 and z990" - select HAVE_MARCH_Z990_FEATURES if 64BIT - help - Select this to enable optimizations for model z890/z990 (2084 and - 2086 series). The kernel will be slightly faster but will not work - on older machines. - -config MARCH_Z9_109 - bool "IBM System z9" - select HAVE_MARCH_Z9_109_FEATURES if 64BIT - help - Select this to enable optimizations for IBM System z9 (2094 and - 2096 series). The kernel will be slightly faster but will not work - on older machines. - -config MARCH_Z10 - bool "IBM System z10" - select HAVE_MARCH_Z10_FEATURES if 64BIT - help - Select this to enable optimizations for IBM System z10 (2097 and - 2098 series). The kernel will be slightly faster but will not work - on older machines. - -config MARCH_Z196 - bool "IBM zEnterprise 114 and 196" - select HAVE_MARCH_Z196_FEATURES if 64BIT - help - Select this to enable optimizations for IBM zEnterprise 114 and 196 - (2818 and 2817 series). The kernel will be slightly faster but will - not work on older machines. - -endchoice +comment "Processor type and features" config 64BIT def_bool y @@ -224,24 +146,6 @@ config 64BIT config 32BIT def_bool y if !64BIT -config COMPAT - def_bool y - prompt "Kernel support for 31 bit emulation" - depends on 64BIT - select COMPAT_BINFMT_ELF if BINFMT_ELF - select ARCH_WANT_OLD_COMPAT_IPC - help - Select this option if you want to enable your system kernel to - handle system-calls from ELF binaries for 31 bit ESA. This option - (and some other stuff like libraries and such) is needed for - executing 31 bit applications. It is safe to say "Y". - -config SYSVIPC_COMPAT - def_bool y if COMPAT && SYSVIPC - -config KEYS_COMPAT - def_bool y if COMPAT && KEYS - config SMP def_bool y prompt "Symmetric multi-processing support" @@ -297,8 +201,6 @@ config SCHED_BOOK Book scheduler support improves the CPU scheduler's decision making when dealing with machines that have several books. -source kernel/Kconfig.preempt - config MATHEMU def_bool y prompt "IEEE FPU emulation" @@ -308,35 +210,100 @@ config MATHEMU on older ESA/390 machines. Say Y unless you know your machine doesn't need this. -source kernel/Kconfig.hz +config COMPAT + def_bool y + prompt "Kernel support for 31 bit emulation" + depends on 64BIT + select COMPAT_BINFMT_ELF if BINFMT_ELF + select ARCH_WANT_OLD_COMPAT_IPC + help + Select this option if you want to enable your system kernel to + handle system-calls from ELF binaries for 31 bit ESA. This option + (and some other stuff like libraries and such) is needed for + executing 31 bit applications. It is safe to say "Y". -endmenu +config SYSVIPC_COMPAT + def_bool y if COMPAT && SYSVIPC -menu "Memory setup" +config KEYS_COMPAT + def_bool y if COMPAT && KEYS -config ARCH_SPARSEMEM_ENABLE +config AUDIT_ARCH def_bool y - select SPARSEMEM_VMEMMAP_ENABLE - select SPARSEMEM_VMEMMAP - select SPARSEMEM_STATIC if !64BIT -config ARCH_SPARSEMEM_DEFAULT - def_bool y +config HAVE_MARCH_Z900_FEATURES + def_bool n -config ARCH_SELECT_MEMORY_MODEL - def_bool y +config HAVE_MARCH_Z990_FEATURES + def_bool n + select HAVE_MARCH_Z900_FEATURES -config ARCH_ENABLE_MEMORY_HOTPLUG - def_bool y if SPARSEMEM +config HAVE_MARCH_Z9_109_FEATURES + def_bool n + select HAVE_MARCH_Z990_FEATURES -config ARCH_ENABLE_MEMORY_HOTREMOVE - def_bool y +config HAVE_MARCH_Z10_FEATURES + def_bool n + select HAVE_MARCH_Z9_109_FEATURES -config FORCE_MAX_ZONEORDER - int - default "9" +config HAVE_MARCH_Z196_FEATURES + def_bool n + select HAVE_MARCH_Z10_FEATURES -source "mm/Kconfig" +comment "Code generation options" + +choice + prompt "Processor type" + default MARCH_G5 + +config MARCH_G5 + bool "System/390 model G5 and G6" + depends on !64BIT + help + Select this to build a 31 bit kernel that works + on all ESA/390 and z/Architecture machines. + +config MARCH_Z900 + bool "IBM zSeries model z800 and z900" + select HAVE_MARCH_Z900_FEATURES if 64BIT + help + Select this to enable optimizations for model z800/z900 (2064 and + 2066 series). This will enable some optimizations that are not + available on older ESA/390 (31 Bit) only CPUs. + +config MARCH_Z990 + bool "IBM zSeries model z890 and z990" + select HAVE_MARCH_Z990_FEATURES if 64BIT + help + Select this to enable optimizations for model z890/z990 (2084 and + 2086 series). The kernel will be slightly faster but will not work + on older machines. + +config MARCH_Z9_109 + bool "IBM System z9" + select HAVE_MARCH_Z9_109_FEATURES if 64BIT + help + Select this to enable optimizations for IBM System z9 (2094 and + 2096 series). The kernel will be slightly faster but will not work + on older machines. + +config MARCH_Z10 + bool "IBM System z10" + select HAVE_MARCH_Z10_FEATURES if 64BIT + help + Select this to enable optimizations for IBM System z10 (2097 and + 2098 series). The kernel will be slightly faster but will not work + on older machines. + +config MARCH_Z196 + bool "IBM zEnterprise 114 and 196" + select HAVE_MARCH_Z196_FEATURES if 64BIT + help + Select this to enable optimizations for IBM zEnterprise 114 and 196 + (2818 and 2817 series). The kernel will be slightly faster but will + not work on older machines. + +endchoice config PACK_STACK def_bool y @@ -400,9 +367,34 @@ config WARN_DYNAMIC_STACK Say N if you are unsure. -endmenu +comment "Kernel preemption" + +source "kernel/Kconfig.preempt" + +config ARCH_SPARSEMEM_ENABLE + def_bool y + select SPARSEMEM_VMEMMAP_ENABLE + select SPARSEMEM_VMEMMAP + select SPARSEMEM_STATIC if !64BIT + +config ARCH_SPARSEMEM_DEFAULT + def_bool y + +config ARCH_SELECT_MEMORY_MODEL + def_bool y + +config ARCH_ENABLE_MEMORY_HOTPLUG + def_bool y if SPARSEMEM + +config ARCH_ENABLE_MEMORY_HOTREMOVE + def_bool y + +config ARCH_HIBERNATION_POSSIBLE + def_bool y if 64BIT + +source "mm/Kconfig" -menu "I/O subsystem" +comment "I/O subsystem configuration" config QDIO def_tristate y @@ -433,102 +425,13 @@ config CHSC_SCH If unsure, say N. -config SCM_BUS - def_bool y - depends on 64BIT - prompt "SCM bus driver" - help - Bus driver for Storage Class Memory. - -config EADM_SCH - def_tristate m - prompt "Support for EADM subchannels" - depends on SCM_BUS - help - This driver allows usage of EADM subchannels. EADM subchannels act - as a communication vehicle for SCM increments. - - To compile this driver as a module, choose M here: the - module will be called eadm_sch. - -endmenu - -menu "Dump support" - -config CRASH_DUMP - bool "kernel crash dumps" - depends on 64BIT && SMP - select KEXEC - help - Generate crash dump after being started by kexec. - Crash dump kernels are loaded in the main kernel with kexec-tools - into a specially reserved region and then later executed after - a crash by kdump/kexec. - For more details see Documentation/kdump/kdump.txt - -config ZFCPDUMP - def_bool n - prompt "zfcpdump support" - select SMP - help - Select this option if you want to build an zfcpdump enabled kernel. - Refer to for more details on this. - -endmenu - -menu "Executable file formats / Emulations" +comment "Misc" source "fs/Kconfig.binfmt" -config SECCOMP - def_bool y - prompt "Enable seccomp to safely compute untrusted bytecode" - depends on PROC_FS - help - This kernel feature is useful for number crunching applications - that may need to compute untrusted bytecode during their - execution. By using pipes or other transports made available to - the process as file descriptors supporting the read/write - syscalls, it's possible to isolate those applications in - their own address space using seccomp. Once seccomp is - enabled via /proc//seccomp, it cannot be disabled - and the task is only allowed to execute a few safe syscalls - defined by each seccomp mode. - - If unsure, say Y. - -endmenu - -menu "Power Management" - -config ARCH_HIBERNATION_POSSIBLE - def_bool y if 64BIT - -source "kernel/power/Kconfig" - -endmenu - -source "net/Kconfig" - -config PCMCIA - def_bool n - -config CCW - def_bool y - -source "drivers/Kconfig" - -source "fs/Kconfig" - -source "arch/s390/Kconfig.debug" - -source "security/Kconfig" - -source "crypto/Kconfig" - -source "lib/Kconfig" - -menu "Virtualization" +config FORCE_MAX_ZONEORDER + int + default "9" config PFAULT def_bool y @@ -544,8 +447,8 @@ config PFAULT this option. config SHARED_KERNEL - bool "VM shared kernel support" - depends on !JUMP_LABEL + def_bool y + prompt "VM shared kernel support" help Select this option, if you want to share the text segment of the Linux kernel between different VM guests. This reduces memory @@ -640,6 +543,8 @@ config APPLDATA_NET_SUM This can also be compiled as a module, which will be called appldata_net_sum.o. +source kernel/Kconfig.hz + config S390_HYPFS_FS def_bool y prompt "s390 hypervisor file system support" @@ -648,21 +553,90 @@ config S390_HYPFS_FS This is a virtual file system intended to provide accounting information in an s390 hypervisor environment. -source "arch/s390/kvm/Kconfig" +config KEXEC + def_bool n + prompt "kexec system call" + help + kexec is a system call that implements the ability to shutdown your + current kernel, and to start another kernel. It is like a reboot + but is independent of hardware/microcode support. + +config CRASH_DUMP + bool "kernel crash dumps" + depends on 64BIT && SMP + select KEXEC + help + Generate crash dump after being started by kexec. + Crash dump kernels are loaded in the main kernel with kexec-tools + into a specially reserved region and then later executed after + a crash by kdump/kexec. + For more details see Documentation/kdump/kdump.txt + +config ZFCPDUMP + def_bool n + prompt "zfcpdump support" + select SMP + help + Select this option if you want to build an zfcpdump enabled kernel. + Refer to for more details on this. config S390_GUEST def_bool y - prompt "s390 support for virtio devices (EXPERIMENTAL)" + prompt "s390 guest support for KVM (EXPERIMENTAL)" depends on 64BIT && EXPERIMENTAL select VIRTUALIZATION select VIRTIO select VIRTIO_RING select VIRTIO_CONSOLE help - Enabling this option adds support for virtio based paravirtual device - drivers on s390. - Select this option if you want to run the kernel as a guest under - the KVM hypervisor. + the KVM hypervisor. This will add detection for KVM as well as a + virtio transport. If KVM is detected, the virtio console will be + the default console. + +config SECCOMP + def_bool y + prompt "Enable seccomp to safely compute untrusted bytecode" + depends on PROC_FS + help + This kernel feature is useful for number crunching applications + that may need to compute untrusted bytecode during their + execution. By using pipes or other transports made available to + the process as file descriptors supporting the read/write + syscalls, it's possible to isolate those applications in + their own address space using seccomp. Once seccomp is + enabled via /proc//seccomp, it cannot be disabled + and the task is only allowed to execute a few safe syscalls + defined by each seccomp mode. + + If unsure, say Y. endmenu + +menu "Power Management" + +source "kernel/power/Kconfig" + +endmenu + +source "net/Kconfig" + +config PCMCIA + def_bool n + +config CCW + def_bool y + +source "drivers/Kconfig" + +source "fs/Kconfig" + +source "arch/s390/Kconfig.debug" + +source "security/Kconfig" + +source "crypto/Kconfig" + +source "lib/Kconfig" + +source "arch/s390/kvm/Kconfig" diff --git a/trunk/arch/s390/boot/compressed/Makefile b/trunk/arch/s390/boot/compressed/Makefile index 3ad8f61c9985..10e22c4ec4a7 100644 --- a/trunk/arch/s390/boot/compressed/Makefile +++ b/trunk/arch/s390/boot/compressed/Makefile @@ -11,7 +11,6 @@ targets := vmlinux.lds vmlinux vmlinux.bin vmlinux.bin.gz vmlinux.bin.bz2 \ sizes.h head$(BITS).o KBUILD_CFLAGS := -m$(BITS) -D__KERNEL__ $(LINUX_INCLUDE) -O2 -KBUILD_CFLAGS += -DDISABLE_BRANCH_PROFILING KBUILD_CFLAGS += $(cflags-y) KBUILD_CFLAGS += $(call cc-option,-mpacked-stack) KBUILD_CFLAGS += $(call cc-option,-ffreestanding) diff --git a/trunk/arch/s390/boot/compressed/misc.c b/trunk/arch/s390/boot/compressed/misc.c index c4c6a1cf221b..465eca756feb 100644 --- a/trunk/arch/s390/boot/compressed/misc.c +++ b/trunk/arch/s390/boot/compressed/misc.c @@ -71,37 +71,34 @@ void *memset(void *s, int c, size_t n) { char *xs; - xs = s; - while (n--) - *xs++ = c; + if (c == 0) + return __builtin_memset(s, 0, n); + + xs = (char *) s; + if (n > 0) + do { + *xs++ = c; + } while (--n > 0); return s; } -void *memcpy(void *dest, const void *src, size_t n) +void *memcpy(void *__dest, __const void *__src, size_t __n) { - const char *s = src; - char *d = dest; - - while (n--) - *d++ = *s++; - return dest; + return __builtin_memcpy(__dest, __src, __n); } -void *memmove(void *dest, const void *src, size_t n) +void *memmove(void *__dest, __const void *__src, size_t __n) { - const char *s = src; - char *d = dest; - - if (d <= s) { - while (n--) - *d++ = *s++; - } else { - d += n; - s += n; - while (n--) - *--d = *--s; - } - return dest; + char *d; + const char *s; + + if (__dest <= __src) + return __builtin_memcpy(__dest, __src, __n); + d = __dest + __n; + s = __src + __n; + while (__n--) + *--d = *--s; + return __dest; } static void error(char *x) diff --git a/trunk/arch/s390/defconfig b/trunk/arch/s390/defconfig index b74400e3e035..f39cd710980b 100644 --- a/trunk/arch/s390/defconfig +++ b/trunk/arch/s390/defconfig @@ -16,8 +16,8 @@ CONFIG_CGROUPS=y CONFIG_CPUSETS=y CONFIG_CGROUP_CPUACCT=y CONFIG_RESOURCE_COUNTERS=y -CONFIG_MEMCG=y -CONFIG_MEMCG_SWAP=y +CONFIG_CGROUP_MEMCG=y +CONFIG_CGROUP_MEM_RES_CTLR_SWAP=y CONFIG_CGROUP_SCHED=y CONFIG_RT_GROUP_SCHED=y CONFIG_BLK_CGROUP=y @@ -32,19 +32,20 @@ CONFIG_EXPERT=y CONFIG_PROFILING=y CONFIG_OPROFILE=y CONFIG_KPROBES=y -CONFIG_JUMP_LABEL=y CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y CONFIG_MODVERSIONS=y CONFIG_PARTITION_ADVANCED=y CONFIG_IBM_PARTITION=y CONFIG_DEFAULT_DEADLINE=y -CONFIG_HZ_100=y +CONFIG_PREEMPT=y CONFIG_MEMORY_HOTPLUG=y CONFIG_MEMORY_HOTREMOVE=y CONFIG_KSM=y -CONFIG_CRASH_DUMP=y CONFIG_BINFMT_MISC=m +CONFIG_CMM=m +CONFIG_HZ_100=y +CONFIG_CRASH_DUMP=y CONFIG_HIBERNATION=y CONFIG_PACKET=y CONFIG_UNIX=y @@ -74,7 +75,6 @@ CONFIG_NET_CLS_RSVP=m CONFIG_NET_CLS_RSVP6=m CONFIG_NET_CLS_ACT=y CONFIG_NET_ACT_POLICE=y -CONFIG_BPF_JIT=y CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" CONFIG_DEVTMPFS=y CONFIG_BLK_DEV_LOOP=m @@ -121,6 +121,7 @@ CONFIG_DEBUG_NOTIFIERS=y CONFIG_RCU_TRACE=y CONFIG_KPROBES_SANITY_TEST=y CONFIG_DEBUG_FORCE_WEAK_PER_CPU=y +CONFIG_CPU_NOTIFIER_ERROR_INJECT=m CONFIG_LATENCYTOP=y CONFIG_DEBUG_PAGEALLOC=y CONFIG_BLK_DEV_IO_TRACE=y @@ -172,4 +173,3 @@ CONFIG_CRYPTO_SHA512_S390=m CONFIG_CRYPTO_DES_S390=m CONFIG_CRYPTO_AES_S390=m CONFIG_CRC7=m -CONFIG_CMM=m diff --git a/trunk/arch/s390/include/asm/appldata.h b/trunk/arch/s390/include/asm/appldata.h index 32a705987156..f328294faeae 100644 --- a/trunk/arch/s390/include/asm/appldata.h +++ b/trunk/arch/s390/include/asm/appldata.h @@ -70,7 +70,7 @@ static inline int appldata_asm(struct appldata_product_id *id, int ry; if (!MACHINE_IS_VM) - return -EOPNOTSUPP; + return -ENOSYS; parm_list.diag = 0xdc; parm_list.function = fn; parm_list.parlist_length = sizeof(parm_list); diff --git a/trunk/arch/s390/include/asm/chsc.h b/trunk/arch/s390/include/asm/chsc.h index aea451fd182e..bf115b49f444 100644 --- a/trunk/arch/s390/include/asm/chsc.h +++ b/trunk/arch/s390/include/asm/chsc.h @@ -125,4 +125,32 @@ struct chsc_cpd_info { #define CHSC_INFO_CPD _IOWR(CHSC_IOCTL_MAGIC, 0x87, struct chsc_cpd_info) #define CHSC_INFO_DCAL _IOWR(CHSC_IOCTL_MAGIC, 0x88, struct chsc_dcal) +#ifdef __KERNEL__ + +struct css_general_char { + u64 : 12; + u32 dynio : 1; /* bit 12 */ + u32 : 28; + u32 aif : 1; /* bit 41 */ + u32 : 3; + u32 mcss : 1; /* bit 45 */ + u32 fcs : 1; /* bit 46 */ + u32 : 1; + u32 ext_mb : 1; /* bit 48 */ + u32 : 7; + u32 aif_tdd : 1; /* bit 56 */ + u32 : 1; + u32 qebsm : 1; /* bit 58 */ + u32 : 8; + u32 aif_osa : 1; /* bit 67 */ + u32 : 14; + u32 cib : 1; /* bit 82 */ + u32 : 5; + u32 fcx : 1; /* bit 88 */ + u32 : 7; +}__attribute__((packed)); + +extern struct css_general_char css_general_characteristics; + +#endif /* __KERNEL__ */ #endif diff --git a/trunk/arch/s390/include/asm/cio.h b/trunk/arch/s390/include/asm/cio.h index 55bde6035216..77043aa44d67 100644 --- a/trunk/arch/s390/include/asm/cio.h +++ b/trunk/arch/s390/include/asm/cio.h @@ -79,18 +79,6 @@ struct erw { __u32 res16 : 16; } __attribute__ ((packed)); -/** - * struct erw_eadm - EADM Subchannel extended report word - * @b: aob error - * @r: arsb error - */ -struct erw_eadm { - __u32 : 16; - __u32 b : 1; - __u32 r : 1; - __u32 : 14; -} __packed; - /** * struct sublog - subchannel logout area * @res0: reserved @@ -181,23 +169,10 @@ struct esw3 { __u32 zeros[3]; } __attribute__ ((packed)); -/** - * struct esw_eadm - EADM Subchannel Extended Status Word (ESW) - * @sublog: subchannel logout - * @erw: extended report word - */ -struct esw_eadm { - __u32 sublog; - struct erw_eadm erw; - __u32 : 32; - __u32 : 32; - __u32 : 32; -} __packed; - /** * struct irb - interruption response block * @scsw: subchannel status word - * @esw: extened status word + * @esw: extened status word, 4 formats * @ecw: extended control word * * The irb that is handed to the device driver when an interrupt occurs. For @@ -216,7 +191,6 @@ struct irb { struct esw1 esw1; struct esw2 esw2; struct esw3 esw3; - struct esw_eadm eadm; } esw; __u8 ecw[32]; } __attribute__ ((packed,aligned(4))); diff --git a/trunk/arch/s390/include/asm/cmpxchg.h b/trunk/arch/s390/include/asm/cmpxchg.h index 0f636cbdf342..8d798e962b63 100644 --- a/trunk/arch/s390/include/asm/cmpxchg.h +++ b/trunk/arch/s390/include/asm/cmpxchg.h @@ -7,9 +7,7 @@ #ifndef __ASM_CMPXCHG_H #define __ASM_CMPXCHG_H -#include #include -#include extern void __xchg_called_with_bad_pointer(void); @@ -205,65 +203,6 @@ static inline unsigned long long __cmpxchg64(void *ptr, }) #endif /* CONFIG_64BIT */ -#define __cmpxchg_double_op(p1, p2, o1, o2, n1, n2, insn) \ -({ \ - register __typeof__(*(p1)) __old1 asm("2") = (o1); \ - register __typeof__(*(p2)) __old2 asm("3") = (o2); \ - register __typeof__(*(p1)) __new1 asm("4") = (n1); \ - register __typeof__(*(p2)) __new2 asm("5") = (n2); \ - int cc; \ - asm volatile( \ - insn " %[old],%[new],%[ptr]\n" \ - " ipm %[cc]\n" \ - " srl %[cc],28" \ - : [cc] "=d" (cc), [old] "+d" (__old1), "+d" (__old2) \ - : [new] "d" (__new1), "d" (__new2), \ - [ptr] "Q" (*(p1)), "Q" (*(p2)) \ - : "memory", "cc"); \ - !cc; \ -}) - -#define __cmpxchg_double_4(p1, p2, o1, o2, n1, n2) \ - __cmpxchg_double_op(p1, p2, o1, o2, n1, n2, "cds") - -#define __cmpxchg_double_8(p1, p2, o1, o2, n1, n2) \ - __cmpxchg_double_op(p1, p2, o1, o2, n1, n2, "cdsg") - -extern void __cmpxchg_double_called_with_bad_pointer(void); - -#define __cmpxchg_double(p1, p2, o1, o2, n1, n2) \ -({ \ - int __ret; \ - switch (sizeof(*(p1))) { \ - case 4: \ - __ret = __cmpxchg_double_4(p1, p2, o1, o2, n1, n2); \ - break; \ - case 8: \ - __ret = __cmpxchg_double_8(p1, p2, o1, o2, n1, n2); \ - break; \ - default: \ - __cmpxchg_double_called_with_bad_pointer(); \ - } \ - __ret; \ -}) - -#define cmpxchg_double(p1, p2, o1, o2, n1, n2) \ -({ \ - __typeof__(p1) __p1 = (p1); \ - __typeof__(p2) __p2 = (p2); \ - int __ret; \ - BUILD_BUG_ON(sizeof(*(p1)) != sizeof(long)); \ - BUILD_BUG_ON(sizeof(*(p2)) != sizeof(long)); \ - VM_BUG_ON((unsigned long)((__p1) + 1) != (unsigned long)(__p2));\ - if (sizeof(long) == 4) \ - __ret = __cmpxchg_double_4(__p1, __p2, o1, o2, n1, n2); \ - else \ - __ret = __cmpxchg_double_8(__p1, __p2, o1, o2, n1, n2); \ - __ret; \ -}) - -#define system_has_cmpxchg_double() 1 - #include static inline unsigned long __cmpxchg_local(void *ptr, diff --git a/trunk/arch/s390/include/asm/cpu_mf.h b/trunk/arch/s390/include/asm/cpu_mf.h index 35f0020b7ba7..a3afecdae145 100644 --- a/trunk/arch/s390/include/asm/cpu_mf.h +++ b/trunk/arch/s390/include/asm/cpu_mf.h @@ -21,15 +21,11 @@ #define CPU_MF_INT_SF_LSDA (1 << 22) /* loss of sample data alert */ #define CPU_MF_INT_CF_CACA (1 << 7) /* counter auth. change alert */ #define CPU_MF_INT_CF_LCDA (1 << 6) /* loss of counter data alert */ -#define CPU_MF_INT_RI_HALTED (1 << 5) /* run-time instr. halted */ -#define CPU_MF_INT_RI_BUF_FULL (1 << 4) /* run-time instr. program - buffer full */ #define CPU_MF_INT_CF_MASK (CPU_MF_INT_CF_CACA|CPU_MF_INT_CF_LCDA) #define CPU_MF_INT_SF_MASK (CPU_MF_INT_SF_IAE|CPU_MF_INT_SF_ISE| \ CPU_MF_INT_SF_PRA|CPU_MF_INT_SF_SACA| \ CPU_MF_INT_SF_LSDA) -#define CPU_MF_INT_RI_MASK (CPU_MF_INT_RI_HALTED|CPU_MF_INT_RI_BUF_FULL) /* CPU measurement facility support */ static inline int cpum_cf_avail(void) diff --git a/trunk/arch/s390/include/asm/cputime.h b/trunk/arch/s390/include/asm/cputime.h index 023d5ae24482..8709bdef233c 100644 --- a/trunk/arch/s390/include/asm/cputime.h +++ b/trunk/arch/s390/include/asm/cputime.h @@ -12,9 +12,6 @@ #include #include - -#define __ARCH_HAS_VTIME_ACCOUNT - /* We want to use full resolution of the CPU timer: 2**-12 micro-seconds. */ typedef unsigned long long __nocast cputime_t; diff --git a/trunk/arch/s390/include/asm/css_chars.h b/trunk/arch/s390/include/asm/css_chars.h deleted file mode 100644 index a06ebc2623fb..000000000000 --- a/trunk/arch/s390/include/asm/css_chars.h +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef _ASM_CSS_CHARS_H -#define _ASM_CSS_CHARS_H - -#include - -#ifdef __KERNEL__ - -struct css_general_char { - u64 : 12; - u32 dynio : 1; /* bit 12 */ - u32 : 4; - u32 eadm : 1; /* bit 17 */ - u32 : 23; - u32 aif : 1; /* bit 41 */ - u32 : 3; - u32 mcss : 1; /* bit 45 */ - u32 fcs : 1; /* bit 46 */ - u32 : 1; - u32 ext_mb : 1; /* bit 48 */ - u32 : 7; - u32 aif_tdd : 1; /* bit 56 */ - u32 : 1; - u32 qebsm : 1; /* bit 58 */ - u32 : 8; - u32 aif_osa : 1; /* bit 67 */ - u32 : 12; - u32 eadm_rf : 1; /* bit 80 */ - u32 : 1; - u32 cib : 1; /* bit 82 */ - u32 : 5; - u32 fcx : 1; /* bit 88 */ - u32 : 19; - u32 alt_ssi : 1; /* bit 108 */ -} __packed; - -extern struct css_general_char css_general_characteristics; - -#endif /* __KERNEL__ */ -#endif diff --git a/trunk/arch/s390/include/asm/eadm.h b/trunk/arch/s390/include/asm/eadm.h deleted file mode 100644 index 8d4847191ecc..000000000000 --- a/trunk/arch/s390/include/asm/eadm.h +++ /dev/null @@ -1,124 +0,0 @@ -#ifndef _ASM_S390_EADM_H -#define _ASM_S390_EADM_H - -#include -#include - -struct arqb { - u64 data; - u16 fmt:4; - u16:12; - u16 cmd_code; - u16:16; - u16 msb_count; - u32 reserved[12]; -} __packed; - -#define ARQB_CMD_MOVE 1 - -struct arsb { - u16 fmt:4; - u32:28; - u8 ef; - u8:8; - u8 ecbi; - u8:8; - u8 fvf; - u16:16; - u8 eqc; - u32:32; - u64 fail_msb; - u64 fail_aidaw; - u64 fail_ms; - u64 fail_scm; - u32 reserved[4]; -} __packed; - -struct msb { - u8 fmt:4; - u8 oc:4; - u8 flags; - u16:12; - u16 bs:4; - u32 blk_count; - u64 data_addr; - u64 scm_addr; - u64:64; -} __packed; - -struct aidaw { - u8 flags; - u32 :24; - u32 :32; - u64 data_addr; -} __packed; - -#define MSB_OC_CLEAR 0 -#define MSB_OC_READ 1 -#define MSB_OC_WRITE 2 -#define MSB_OC_RELEASE 3 - -#define MSB_FLAG_BNM 0x80 -#define MSB_FLAG_IDA 0x40 - -#define MSB_BS_4K 0 -#define MSB_BS_1M 1 - -#define AOB_NR_MSB 124 - -struct aob { - struct arqb request; - struct arsb response; - struct msb msb[AOB_NR_MSB]; -} __packed __aligned(PAGE_SIZE); - -struct aob_rq_header { - struct scm_device *scmdev; - char data[0]; -}; - -struct scm_device { - u64 address; - u64 size; - unsigned int nr_max_block; - struct device dev; - struct { - unsigned int persistence:4; - unsigned int oper_state:4; - unsigned int data_state:4; - unsigned int rank:4; - unsigned int release:1; - unsigned int res_id:8; - } __packed attrs; -}; - -#define OP_STATE_GOOD 1 -#define OP_STATE_TEMP_ERR 2 -#define OP_STATE_PERM_ERR 3 - -struct scm_driver { - struct device_driver drv; - int (*probe) (struct scm_device *scmdev); - int (*remove) (struct scm_device *scmdev); - void (*notify) (struct scm_device *scmdev); - void (*handler) (struct scm_device *scmdev, void *data, int error); -}; - -int scm_driver_register(struct scm_driver *scmdrv); -void scm_driver_unregister(struct scm_driver *scmdrv); - -int scm_start_aob(struct aob *aob); -void scm_irq_handler(struct aob *aob, int error); - -struct eadm_ops { - int (*eadm_start) (struct aob *aob); - struct module *owner; -}; - -int scm_get_ref(void); -void scm_put_ref(void); - -void register_eadm_ops(struct eadm_ops *ops); -void unregister_eadm_ops(struct eadm_ops *ops); - -#endif /* _ASM_S390_EADM_H */ diff --git a/trunk/arch/s390/include/asm/elf.h b/trunk/arch/s390/include/asm/elf.h index 178ff966a8ba..32e8449640fa 100644 --- a/trunk/arch/s390/include/asm/elf.h +++ b/trunk/arch/s390/include/asm/elf.h @@ -101,7 +101,6 @@ #define HWCAP_S390_HPAGE 128 #define HWCAP_S390_ETF3EH 256 #define HWCAP_S390_HIGH_GPRS 512 -#define HWCAP_S390_TE 1024 /* * These are used to set parameters in the core dumps. @@ -181,8 +180,7 @@ extern char elf_platform[]; #define ELF_PLATFORM (elf_platform) #ifndef CONFIG_64BIT -#define SET_PERSONALITY(ex) \ - set_personality(PER_LINUX | (current->personality & (~PER_MASK))) +#define SET_PERSONALITY(ex) set_personality(PER_LINUX) #else /* CONFIG_64BIT */ #define SET_PERSONALITY(ex) \ do { \ @@ -213,6 +211,4 @@ int arch_setup_additional_pages(struct linux_binprm *, int); extern unsigned long arch_randomize_brk(struct mm_struct *mm); #define arch_randomize_brk arch_randomize_brk -void *fill_cpu_elf_notes(void *ptr, struct save_area *sa); - #endif diff --git a/trunk/arch/s390/include/asm/etr.h b/trunk/arch/s390/include/asm/etr.h index 629b79a93165..a24b03b9fb64 100644 --- a/trunk/arch/s390/include/asm/etr.h +++ b/trunk/arch/s390/include/asm/etr.h @@ -140,7 +140,7 @@ struct etr_ptff_qto { /* Inline assembly helper functions */ static inline int etr_setr(struct etr_eacr *ctrl) { - int rc = -EOPNOTSUPP; + int rc = -ENOSYS; asm volatile( " .insn s,0xb2160000,%1\n" @@ -154,7 +154,7 @@ static inline int etr_setr(struct etr_eacr *ctrl) /* Stores a format 1 aib with 64 bytes */ static inline int etr_stetr(struct etr_aib *aib) { - int rc = -EOPNOTSUPP; + int rc = -ENOSYS; asm volatile( " .insn s,0xb2170000,%1\n" @@ -169,7 +169,7 @@ static inline int etr_stetr(struct etr_aib *aib) static inline int etr_steai(struct etr_aib *aib, unsigned int func) { register unsigned int reg0 asm("0") = func; - int rc = -EOPNOTSUPP; + int rc = -ENOSYS; asm volatile( " .insn s,0xb2b30000,%1\n" @@ -190,7 +190,7 @@ static inline int etr_ptff(void *ptff_block, unsigned int func) { register unsigned int reg0 asm("0") = func; register unsigned long reg1 asm("1") = (unsigned long) ptff_block; - int rc = -EOPNOTSUPP; + int rc = -ENOSYS; asm volatile( " .word 0x0104\n" diff --git a/trunk/arch/s390/include/asm/hugetlb.h b/trunk/arch/s390/include/asm/hugetlb.h index 2d6e6e380564..799ed0f1643d 100644 --- a/trunk/arch/s390/include/asm/hugetlb.h +++ b/trunk/arch/s390/include/asm/hugetlb.h @@ -66,6 +66,16 @@ static inline pte_t huge_ptep_get(pte_t *ptep) return pte; } +static inline pte_t huge_ptep_get_and_clear(struct mm_struct *mm, + unsigned long addr, pte_t *ptep) +{ + pte_t pte = huge_ptep_get(ptep); + + mm->context.flush_mm = 1; + pmd_clear((pmd_t *) ptep); + return pte; +} + static inline void __pmd_csp(pmd_t *pmdp) { register unsigned long reg2 asm("2") = pmd_val(*pmdp); @@ -107,15 +117,6 @@ static inline void huge_ptep_invalidate(struct mm_struct *mm, __pmd_csp(pmdp); } -static inline pte_t huge_ptep_get_and_clear(struct mm_struct *mm, - unsigned long addr, pte_t *ptep) -{ - pte_t pte = huge_ptep_get(ptep); - - huge_ptep_invalidate(mm, addr, ptep); - return pte; -} - #define huge_ptep_set_access_flags(__vma, __addr, __ptep, __entry, __dirty) \ ({ \ int __changed = !pte_same(huge_ptep_get(__ptep), __entry); \ @@ -130,7 +131,10 @@ static inline pte_t huge_ptep_get_and_clear(struct mm_struct *mm, ({ \ pte_t __pte = huge_ptep_get(__ptep); \ if (pte_write(__pte)) { \ - huge_ptep_invalidate(__mm, __addr, __ptep); \ + (__mm)->context.flush_mm = 1; \ + if (atomic_read(&(__mm)->context.attach_count) > 1 || \ + (__mm) != current->active_mm) \ + huge_ptep_invalidate(__mm, __addr, __ptep); \ set_huge_pte_at(__mm, __addr, __ptep, \ huge_pte_wrprotect(__pte)); \ } \ diff --git a/trunk/arch/s390/include/asm/irq.h b/trunk/arch/s390/include/asm/irq.h index 6703dd986fd4..2b9d41899d21 100644 --- a/trunk/arch/s390/include/asm/irq.h +++ b/trunk/arch/s390/include/asm/irq.h @@ -19,7 +19,6 @@ enum interruption_class { EXTINT_IUC, EXTINT_CMS, EXTINT_CMC, - EXTINT_CMR, IOINT_CIO, IOINT_QAI, IOINT_DAS, @@ -31,7 +30,6 @@ enum interruption_class { IOINT_CLW, IOINT_CTC, IOINT_APB, - IOINT_ADM, IOINT_CSC, NMI_NMI, NR_IRQS, diff --git a/trunk/arch/s390/include/asm/isc.h b/trunk/arch/s390/include/asm/isc.h index 5ae606456b0a..1420a1115948 100644 --- a/trunk/arch/s390/include/asm/isc.h +++ b/trunk/arch/s390/include/asm/isc.h @@ -14,7 +14,6 @@ /* Regular I/O interrupts. */ #define IO_SCH_ISC 3 /* regular I/O subchannels */ #define CONSOLE_ISC 1 /* console I/O subchannel */ -#define EADM_SCH_ISC 4 /* EADM subchannels */ #define CHSC_SCH_ISC 7 /* CHSC subchannels */ /* Adapter interrupts. */ #define QDIO_AIRQ_ISC IO_SCH_ISC /* I/O subchannel in qdio mode */ diff --git a/trunk/arch/s390/include/asm/lowcore.h b/trunk/arch/s390/include/asm/lowcore.h index bbf8141408cd..aab5555bbbda 100644 --- a/trunk/arch/s390/include/asm/lowcore.h +++ b/trunk/arch/s390/include/asm/lowcore.h @@ -329,13 +329,9 @@ struct _lowcore { __u8 pad_0x1338[0x1340-0x1338]; /* 0x1338 */ __u32 access_regs_save_area[16]; /* 0x1340 */ __u64 cregs_save_area[16]; /* 0x1380 */ - __u8 pad_0x1400[0x1800-0x1400]; /* 0x1400 */ - - /* Transaction abort diagnostic block */ - __u8 pgm_tdb[256]; /* 0x1800 */ /* align to the top of the prefix area */ - __u8 pad_0x1900[0x2000-0x1900]; /* 0x1900 */ + __u8 pad_0x1400[0x2000-0x1400]; /* 0x1400 */ } __packed; #endif /* CONFIG_32BIT */ diff --git a/trunk/arch/s390/include/asm/mmu_context.h b/trunk/arch/s390/include/asm/mmu_context.h index 084e7755ed9b..b749c5733657 100644 --- a/trunk/arch/s390/include/asm/mmu_context.h +++ b/trunk/arch/s390/include/asm/mmu_context.h @@ -57,7 +57,7 @@ static inline void update_mm(struct mm_struct *mm, struct task_struct *tsk) pgd_t *pgd = mm->pgd; S390_lowcore.user_asce = mm->context.asce_bits | __pa(pgd); - if (s390_user_mode != HOME_SPACE_MODE) { + if (addressing_mode != HOME_SPACE_MODE) { /* Load primary space page table origin. */ asm volatile(LCTL_OPCODE" 1,1,%0\n" : : "m" (S390_lowcore.user_asce) ); diff --git a/trunk/arch/s390/include/asm/percpu.h b/trunk/arch/s390/include/asm/percpu.h index 86fe0ee2cee5..6537e72e0853 100644 --- a/trunk/arch/s390/include/asm/percpu.h +++ b/trunk/arch/s390/include/asm/percpu.h @@ -20,7 +20,7 @@ #endif #define arch_this_cpu_to_op(pcp, val, op) \ -({ \ +do { \ typedef typeof(pcp) pcp_op_T__; \ pcp_op_T__ old__, new__, prev__; \ pcp_op_T__ *ptr__; \ @@ -39,19 +39,13 @@ } \ } while (prev__ != old__); \ preempt_enable(); \ - new__; \ -}) +} while (0) #define this_cpu_add_1(pcp, val) arch_this_cpu_to_op(pcp, val, +) #define this_cpu_add_2(pcp, val) arch_this_cpu_to_op(pcp, val, +) #define this_cpu_add_4(pcp, val) arch_this_cpu_to_op(pcp, val, +) #define this_cpu_add_8(pcp, val) arch_this_cpu_to_op(pcp, val, +) -#define this_cpu_add_return_1(pcp, val) arch_this_cpu_to_op(pcp, val, +) -#define this_cpu_add_return_2(pcp, val) arch_this_cpu_to_op(pcp, val, +) -#define this_cpu_add_return_4(pcp, val) arch_this_cpu_to_op(pcp, val, +) -#define this_cpu_add_return_8(pcp, val) arch_this_cpu_to_op(pcp, val, +) - #define this_cpu_and_1(pcp, val) arch_this_cpu_to_op(pcp, val, &) #define this_cpu_and_2(pcp, val) arch_this_cpu_to_op(pcp, val, &) #define this_cpu_and_4(pcp, val) arch_this_cpu_to_op(pcp, val, &) @@ -67,7 +61,7 @@ #define this_cpu_xor_4(pcp, val) arch_this_cpu_to_op(pcp, val, ^) #define this_cpu_xor_8(pcp, val) arch_this_cpu_to_op(pcp, val, ^) -#define arch_this_cpu_cmpxchg(pcp, oval, nval) \ +#define arch_this_cpu_cmpxchg(pcp, oval, nval) \ ({ \ typedef typeof(pcp) pcp_op_T__; \ pcp_op_T__ ret__; \ @@ -90,44 +84,6 @@ #define this_cpu_cmpxchg_4(pcp, oval, nval) arch_this_cpu_cmpxchg(pcp, oval, nval) #define this_cpu_cmpxchg_8(pcp, oval, nval) arch_this_cpu_cmpxchg(pcp, oval, nval) -#define arch_this_cpu_xchg(pcp, nval) \ -({ \ - typeof(pcp) *ptr__; \ - typeof(pcp) ret__; \ - preempt_disable(); \ - ptr__ = __this_cpu_ptr(&(pcp)); \ - ret__ = xchg(ptr__, nval); \ - preempt_enable(); \ - ret__; \ -}) - -#define this_cpu_xchg_1(pcp, nval) arch_this_cpu_xchg(pcp, nval) -#define this_cpu_xchg_2(pcp, nval) arch_this_cpu_xchg(pcp, nval) -#define this_cpu_xchg_4(pcp, nval) arch_this_cpu_xchg(pcp, nval) -#ifdef CONFIG_64BIT -#define this_cpu_xchg_8(pcp, nval) arch_this_cpu_xchg(pcp, nval) -#endif - -#define arch_this_cpu_cmpxchg_double(pcp1, pcp2, o1, o2, n1, n2) \ -({ \ - typeof(pcp1) o1__ = (o1), n1__ = (n1); \ - typeof(pcp2) o2__ = (o2), n2__ = (n2); \ - typeof(pcp1) *p1__; \ - typeof(pcp2) *p2__; \ - int ret__; \ - preempt_disable(); \ - p1__ = __this_cpu_ptr(&(pcp1)); \ - p2__ = __this_cpu_ptr(&(pcp2)); \ - ret__ = __cmpxchg_double(p1__, p2__, o1__, o2__, n1__, n2__); \ - preempt_enable(); \ - ret__; \ -}) - -#define this_cpu_cmpxchg_double_4 arch_this_cpu_cmpxchg_double -#ifdef CONFIG_64BIT -#define this_cpu_cmpxchg_double_8 arch_this_cpu_cmpxchg_double -#endif - #include #endif /* __ARCH_S390_PERCPU__ */ diff --git a/trunk/arch/s390/include/asm/posix_types.h b/trunk/arch/s390/include/asm/posix_types.h index bf2a2ad2f800..7bcc14e395f0 100644 --- a/trunk/arch/s390/include/asm/posix_types.h +++ b/trunk/arch/s390/include/asm/posix_types.h @@ -13,7 +13,6 @@ */ typedef unsigned long __kernel_size_t; -typedef long __kernel_ssize_t; #define __kernel_size_t __kernel_size_t typedef unsigned short __kernel_old_dev_t; @@ -26,6 +25,7 @@ typedef unsigned short __kernel_mode_t; typedef unsigned short __kernel_ipc_pid_t; typedef unsigned short __kernel_uid_t; typedef unsigned short __kernel_gid_t; +typedef int __kernel_ssize_t; typedef int __kernel_ptrdiff_t; #else /* __s390x__ */ @@ -35,6 +35,7 @@ typedef unsigned int __kernel_mode_t; typedef int __kernel_ipc_pid_t; typedef unsigned int __kernel_uid_t; typedef unsigned int __kernel_gid_t; +typedef long __kernel_ssize_t; typedef long __kernel_ptrdiff_t; typedef unsigned long __kernel_sigset_t; /* at least 32 bits */ diff --git a/trunk/arch/s390/include/asm/processor.h b/trunk/arch/s390/include/asm/processor.h index f3e0aabfc6bc..11e4e3236937 100644 --- a/trunk/arch/s390/include/asm/processor.h +++ b/trunk/arch/s390/include/asm/processor.h @@ -11,15 +11,12 @@ #ifndef __ASM_S390_PROCESSOR_H #define __ASM_S390_PROCESSOR_H -#ifndef __ASSEMBLY__ - #include #include #include #include #include #include -#include /* * Default implementation of macro that returns current @@ -78,20 +75,11 @@ struct thread_struct { unsigned long gmap_addr; /* address of last gmap fault. */ struct per_regs per_user; /* User specified PER registers */ struct per_event per_event; /* Cause of the last PER trap */ - unsigned long per_flags; /* Flags to control debug behavior */ /* pfault_wait is used to block the process on a pfault event */ unsigned long pfault_wait; struct list_head list; - /* cpu runtime instrumentation */ - struct runtime_instr_cb *ri_cb; - int ri_signum; -#ifdef CONFIG_64BIT - unsigned char trap_tdb[256]; /* Transaction abort diagnose block */ -#endif }; -#define PER_FLAG_NO_TE 1UL /* Flag to disable transactions. */ - typedef struct thread_struct thread_struct; /* @@ -142,12 +130,6 @@ struct task_struct; struct mm_struct; struct seq_file; -#ifdef CONFIG_64BIT -extern void show_cacheinfo(struct seq_file *m); -#else -static inline void show_cacheinfo(struct seq_file *m) { } -#endif - /* Free all resources held by a thread. */ extern void release_thread(struct task_struct *); extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); @@ -158,7 +140,6 @@ extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); extern unsigned long thread_saved_pc(struct task_struct *t); extern void show_code(struct pt_regs *regs); -extern void print_fn_code(unsigned char *code, unsigned long len); unsigned long get_wchan(struct task_struct *p); #define task_pt_regs(tsk) ((struct pt_regs *) \ @@ -350,6 +331,23 @@ extern void (*s390_base_ext_handler_fn)(void); #define ARCH_LOW_ADDRESS_LIMIT 0x7fffffffUL +/* + * Helper macro for exception table entries + */ +#ifndef CONFIG_64BIT +#define EX_TABLE(_fault,_target) \ + ".section __ex_table,\"a\"\n" \ + " .align 4\n" \ + " .long " #_fault "," #_target "\n" \ + ".previous\n" +#else +#define EX_TABLE(_fault,_target) \ + ".section __ex_table,\"a\"\n" \ + " .align 8\n" \ + " .quad " #_fault "," #_target "\n" \ + ".previous\n" +#endif + extern int memcpy_real(void *, void *, size_t); extern void memcpy_absolute(void *, void *, size_t); @@ -360,25 +358,4 @@ extern void memcpy_absolute(void *, void *, size_t); memcpy_absolute(&(dest), &__tmp, sizeof(__tmp)); \ } -/* - * Helper macro for exception table entries - */ -#define EX_TABLE(_fault, _target) \ - ".section __ex_table,\"a\"\n" \ - ".align 4\n" \ - ".long (" #_fault ") - .\n" \ - ".long (" #_target ") - .\n" \ - ".previous\n" - -#else /* __ASSEMBLY__ */ - -#define EX_TABLE(_fault, _target) \ - .section __ex_table,"a" ; \ - .align 4 ; \ - .long (_fault) - . ; \ - .long (_target) - . ; \ - .previous - -#endif /* __ASSEMBLY__ */ - -#endif /* __ASM_S390_PROCESSOR_H */ +#endif /* __ASM_S390_PROCESSOR_H */ diff --git a/trunk/arch/s390/include/asm/ptrace.h b/trunk/arch/s390/include/asm/ptrace.h index ce20a53afe91..d5f08ea566ed 100644 --- a/trunk/arch/s390/include/asm/ptrace.h +++ b/trunk/arch/s390/include/asm/ptrace.h @@ -235,7 +235,6 @@ typedef struct #define PSW_MASK_ASC 0x0000C000UL #define PSW_MASK_CC 0x00003000UL #define PSW_MASK_PM 0x00000F00UL -#define PSW_MASK_RI 0x00000000UL #define PSW_MASK_EA 0x00000000UL #define PSW_MASK_BA 0x00000000UL @@ -265,11 +264,10 @@ typedef struct #define PSW_MASK_ASC 0x0000C00000000000UL #define PSW_MASK_CC 0x0000300000000000UL #define PSW_MASK_PM 0x00000F0000000000UL -#define PSW_MASK_RI 0x0000008000000000UL #define PSW_MASK_EA 0x0000000100000000UL #define PSW_MASK_BA 0x0000000080000000UL -#define PSW_MASK_USER 0x00003F8180000000UL +#define PSW_MASK_USER 0x00003F0180000000UL #define PSW_ADDR_AMODE 0x0000000000000000UL #define PSW_ADDR_INSN 0xFFFFFFFFFFFFFFFFUL @@ -361,19 +359,17 @@ struct per_struct_kernel { unsigned char access_id; /* PER trap access identification */ }; -#define PER_EVENT_MASK 0xEB000000UL +#define PER_EVENT_MASK 0xE9000000UL #define PER_EVENT_BRANCH 0x80000000UL #define PER_EVENT_IFETCH 0x40000000UL #define PER_EVENT_STORE 0x20000000UL #define PER_EVENT_STORE_REAL 0x08000000UL -#define PER_EVENT_TRANSACTION_END 0x02000000UL #define PER_EVENT_NULLIFICATION 0x01000000UL -#define PER_CONTROL_MASK 0x00e00000UL +#define PER_CONTROL_MASK 0x00a00000UL #define PER_CONTROL_BRANCH_ADDRESS 0x00800000UL -#define PER_CONTROL_SUSPENSION 0x00400000UL #define PER_CONTROL_ALTERATION 0x00200000UL #endif @@ -487,8 +483,6 @@ typedef struct #define PTRACE_GET_LAST_BREAK 0x5006 #define PTRACE_PEEK_SYSTEM_CALL 0x5007 #define PTRACE_POKE_SYSTEM_CALL 0x5008 -#define PTRACE_ENABLE_TE 0x5009 -#define PTRACE_DISABLE_TE 0x5010 /* * PT_PROT definition is loosely based on hppa bsd definition in diff --git a/trunk/arch/s390/include/asm/runtime_instr.h b/trunk/arch/s390/include/asm/runtime_instr.h deleted file mode 100644 index 830da737ff85..000000000000 --- a/trunk/arch/s390/include/asm/runtime_instr.h +++ /dev/null @@ -1,98 +0,0 @@ -#ifndef _RUNTIME_INSTR_H -#define _RUNTIME_INSTR_H - -#define S390_RUNTIME_INSTR_START 0x1 -#define S390_RUNTIME_INSTR_STOP 0x2 - -struct runtime_instr_cb { - __u64 buf_current; - __u64 buf_origin; - __u64 buf_limit; - - __u32 valid : 1; - __u32 pstate : 1; - __u32 pstate_set_buf : 1; - __u32 home_space : 1; - __u32 altered : 1; - __u32 : 3; - __u32 pstate_sample : 1; - __u32 sstate_sample : 1; - __u32 pstate_collect : 1; - __u32 sstate_collect : 1; - __u32 : 1; - __u32 halted_int : 1; - __u32 int_requested : 1; - __u32 buffer_full_int : 1; - __u32 key : 4; - __u32 : 9; - __u32 rgs : 3; - - __u32 mode : 4; - __u32 next : 1; - __u32 mae : 1; - __u32 : 2; - __u32 call_type_br : 1; - __u32 return_type_br : 1; - __u32 other_type_br : 1; - __u32 bc_other_type : 1; - __u32 emit : 1; - __u32 tx_abort : 1; - __u32 : 2; - __u32 bp_xn : 1; - __u32 bp_xt : 1; - __u32 bp_ti : 1; - __u32 bp_ni : 1; - __u32 suppr_y : 1; - __u32 suppr_z : 1; - - __u32 dc_miss_extra : 1; - __u32 lat_lev_ignore : 1; - __u32 ic_lat_lev : 4; - __u32 dc_lat_lev : 4; - - __u64 reserved1; - __u64 scaling_factor; - __u64 rsic; - __u64 reserved2; -} __packed __aligned(8); - -extern struct runtime_instr_cb runtime_instr_empty_cb; - -static inline void load_runtime_instr_cb(struct runtime_instr_cb *cb) -{ - asm volatile(".insn rsy,0xeb0000000060,0,0,%0" /* LRIC */ - : : "Q" (*cb)); -} - -static inline void store_runtime_instr_cb(struct runtime_instr_cb *cb) -{ - asm volatile(".insn rsy,0xeb0000000061,0,0,%0" /* STRIC */ - : "=Q" (*cb) : : "cc"); -} - -static inline void save_ri_cb(struct runtime_instr_cb *cb_prev) -{ -#ifdef CONFIG_64BIT - if (cb_prev) - store_runtime_instr_cb(cb_prev); -#endif -} - -static inline void restore_ri_cb(struct runtime_instr_cb *cb_next, - struct runtime_instr_cb *cb_prev) -{ -#ifdef CONFIG_64BIT - if (cb_next) - load_runtime_instr_cb(cb_next); - else if (cb_prev) - load_runtime_instr_cb(&runtime_instr_empty_cb); -#endif -} - -#ifdef CONFIG_64BIT -extern void exit_thread_runtime_instr(void); -#else -static inline void exit_thread_runtime_instr(void) { } -#endif - -#endif /* _RUNTIME_INSTR_H */ diff --git a/trunk/arch/s390/include/asm/scsw.h b/trunk/arch/s390/include/asm/scsw.h index 4af99cdaddf5..4071d00978cb 100644 --- a/trunk/arch/s390/include/asm/scsw.h +++ b/trunk/arch/s390/include/asm/scsw.h @@ -1,7 +1,7 @@ /* * Helper functions for scsw access. * - * Copyright IBM Corp. 2008, 2012 + * Copyright IBM Corp. 2008, 2009 * Author(s): Peter Oberparleiter */ @@ -9,7 +9,7 @@ #define _ASM_S390_SCSW_H_ #include -#include +#include #include /** @@ -99,47 +99,15 @@ struct tm_scsw { u32 schxs:8; } __attribute__ ((packed)); -/** - * struct eadm_scsw - subchannel status word for eadm subchannels - * @key: subchannel key - * @eswf: esw format - * @cc: deferred condition code - * @ectl: extended control - * @fctl: function control - * @actl: activity control - * @stctl: status control - * @aob: AOB address - * @dstat: device status - * @cstat: subchannel status - */ -struct eadm_scsw { - u32 key:4; - u32:1; - u32 eswf:1; - u32 cc:2; - u32:6; - u32 ectl:1; - u32:2; - u32 fctl:3; - u32 actl:7; - u32 stctl:5; - u32 aob; - u32 dstat:8; - u32 cstat:8; - u32:16; -} __packed; - /** * union scsw - subchannel status word * @cmd: command-mode SCSW * @tm: transport-mode SCSW - * @eadm: eadm SCSW */ union scsw { struct cmd_scsw cmd; struct tm_scsw tm; - struct eadm_scsw eadm; -} __packed; +} __attribute__ ((packed)); #define SCSW_FCTL_CLEAR_FUNC 0x1 #define SCSW_FCTL_HALT_FUNC 0x2 diff --git a/trunk/arch/s390/include/asm/setup.h b/trunk/arch/s390/include/asm/setup.h index 87b47ca954f1..e6859d16ee2d 100644 --- a/trunk/arch/s390/include/asm/setup.h +++ b/trunk/arch/s390/include/asm/setup.h @@ -60,7 +60,7 @@ void create_mem_hole(struct mem_chunk memory_chunk[], unsigned long addr, #define SECONDARY_SPACE_MODE 2 #define HOME_SPACE_MODE 3 -extern unsigned int s390_user_mode; +extern unsigned int addressing_mode; /* * Machine features detected in head.S @@ -80,7 +80,6 @@ extern unsigned int s390_user_mode; #define MACHINE_FLAG_LPAR (1UL << 12) #define MACHINE_FLAG_SPP (1UL << 13) #define MACHINE_FLAG_TOPOLOGY (1UL << 14) -#define MACHINE_FLAG_TE (1UL << 15) #define MACHINE_IS_VM (S390_lowcore.machine_flags & MACHINE_FLAG_VM) #define MACHINE_IS_KVM (S390_lowcore.machine_flags & MACHINE_FLAG_KVM) @@ -99,7 +98,6 @@ extern unsigned int s390_user_mode; #define MACHINE_HAS_PFMF (0) #define MACHINE_HAS_SPP (0) #define MACHINE_HAS_TOPOLOGY (0) -#define MACHINE_HAS_TE (0) #else /* CONFIG_64BIT */ #define MACHINE_HAS_IEEE (1) #define MACHINE_HAS_CSP (1) @@ -111,7 +109,6 @@ extern unsigned int s390_user_mode; #define MACHINE_HAS_PFMF (S390_lowcore.machine_flags & MACHINE_FLAG_PFMF) #define MACHINE_HAS_SPP (S390_lowcore.machine_flags & MACHINE_FLAG_SPP) #define MACHINE_HAS_TOPOLOGY (S390_lowcore.machine_flags & MACHINE_FLAG_TOPOLOGY) -#define MACHINE_HAS_TE (S390_lowcore.machine_flags & MACHINE_FLAG_TE) #endif /* CONFIG_64BIT */ #define ZFCPDUMP_HSA_SIZE (32UL<<20) diff --git a/trunk/arch/s390/include/asm/smp.h b/trunk/arch/s390/include/asm/smp.h index b64f15c3b4cc..a0a8340daafa 100644 --- a/trunk/arch/s390/include/asm/smp.h +++ b/trunk/arch/s390/include/asm/smp.h @@ -30,8 +30,6 @@ extern int smp_vcpu_scheduled(int cpu); extern void smp_yield_cpu(int cpu); extern void smp_yield(void); extern void smp_stop_cpu(void); -extern void smp_cpu_set_polarization(int cpu, int val); -extern int smp_cpu_get_polarization(int cpu); #else /* CONFIG_SMP */ @@ -45,8 +43,7 @@ static inline void smp_call_online_cpu(void (*func)(void *), void *data) func(data); } -static inline int smp_find_processor_id(u16 address) { return 0; } -static inline int smp_store_status(int cpu) { return 0; } +static inline int smp_find_processor_id(int address) { return 0; } static inline int smp_vcpu_scheduled(int cpu) { return 1; } static inline void smp_yield_cpu(int cpu) { } static inline void smp_yield(void) { } diff --git a/trunk/arch/s390/include/asm/sparsemem.h b/trunk/arch/s390/include/asm/sparsemem.h index a60d085ddb4d..0fb34027d3f6 100644 --- a/trunk/arch/s390/include/asm/sparsemem.h +++ b/trunk/arch/s390/include/asm/sparsemem.h @@ -4,11 +4,13 @@ #ifdef CONFIG_64BIT #define SECTION_SIZE_BITS 28 +#define MAX_PHYSADDR_BITS 46 #define MAX_PHYSMEM_BITS 46 #else #define SECTION_SIZE_BITS 25 +#define MAX_PHYSADDR_BITS 31 #define MAX_PHYSMEM_BITS 31 #endif /* CONFIG_64BIT */ diff --git a/trunk/arch/s390/include/asm/string.h b/trunk/arch/s390/include/asm/string.h index 7e2dcd7c57ef..1bd1352fa3b5 100644 --- a/trunk/arch/s390/include/asm/string.h +++ b/trunk/arch/s390/include/asm/string.h @@ -96,6 +96,7 @@ static inline char *strcat(char *dst, const char *src) static inline char *strcpy(char *dst, const char *src) { +#if __GNUC__ < 4 register int r0 asm("0") = 0; char *ret = dst; @@ -105,10 +106,14 @@ static inline char *strcpy(char *dst, const char *src) : "+&a" (dst), "+&a" (src) : "d" (r0) : "cc", "memory"); return ret; +#else + return __builtin_strcpy(dst, src); +#endif } static inline size_t strlen(const char *s) { +#if __GNUC__ < 4 register unsigned long r0 asm("0") = 0; const char *tmp = s; @@ -117,6 +122,9 @@ static inline size_t strlen(const char *s) " jo 0b" : "+d" (r0), "+a" (tmp) : : "cc"); return r0 - (unsigned long) s; +#else + return __builtin_strlen(s); +#endif } static inline size_t strnlen(const char * s, size_t n) diff --git a/trunk/arch/s390/include/asm/switch_to.h b/trunk/arch/s390/include/asm/switch_to.h index f3a9e0f92704..f223068b7822 100644 --- a/trunk/arch/s390/include/asm/switch_to.h +++ b/trunk/arch/s390/include/asm/switch_to.h @@ -80,19 +80,21 @@ static inline void restore_access_regs(unsigned int *acrs) if (prev->mm) { \ save_fp_regs(&prev->thread.fp_regs); \ save_access_regs(&prev->thread.acrs[0]); \ - save_ri_cb(prev->thread.ri_cb); \ } \ if (next->mm) { \ restore_fp_regs(&next->thread.fp_regs); \ restore_access_regs(&next->thread.acrs[0]); \ - restore_ri_cb(next->thread.ri_cb, prev->thread.ri_cb); \ update_per_regs(next); \ } \ prev = __switch_to(prev,next); \ } while (0) +extern void account_vtime(struct task_struct *, struct task_struct *); +extern void account_tick_vtime(struct task_struct *); + #define finish_arch_switch(prev) do { \ set_fs(current->thread.mm_segment); \ + account_vtime(prev, current); \ } while (0) #endif /* __ASM_SWITCH_TO_H */ diff --git a/trunk/arch/s390/include/asm/syscall.h b/trunk/arch/s390/include/asm/syscall.h index fe7b99759e12..fb214dd9b7e0 100644 --- a/trunk/arch/s390/include/asm/syscall.h +++ b/trunk/arch/s390/include/asm/syscall.h @@ -12,7 +12,6 @@ #ifndef _ASM_SYSCALL_H #define _ASM_SYSCALL_H 1 -#include #include #include #include @@ -88,13 +87,4 @@ static inline void syscall_set_arguments(struct task_struct *task, regs->orig_gpr2 = args[0]; } -static inline int syscall_get_arch(struct task_struct *task, - struct pt_regs *regs) -{ -#ifdef CONFIG_COMPAT - if (test_tsk_thread_flag(task, TIF_31BIT)) - return AUDIT_ARCH_S390; -#endif - return sizeof(long) == 8 ? AUDIT_ARCH_S390X : AUDIT_ARCH_S390; -} #endif /* _ASM_SYSCALL_H */ diff --git a/trunk/arch/s390/include/asm/sysinfo.h b/trunk/arch/s390/include/asm/sysinfo.h index f92428e459f8..282ee36f6162 100644 --- a/trunk/arch/s390/include/asm/sysinfo.h +++ b/trunk/arch/s390/include/asm/sysinfo.h @@ -17,10 +17,7 @@ #include struct sysinfo_1_1_1 { - unsigned char p:1; - unsigned char :6; - unsigned char t:1; - unsigned char :8; + unsigned short :16; unsigned char ccr; unsigned char cai; char reserved_0[28]; @@ -33,14 +30,9 @@ struct sysinfo_1_1_1 { char model[16]; char model_perm_cap[16]; char model_temp_cap[16]; - unsigned int model_cap_rating; - unsigned int model_perm_cap_rating; - unsigned int model_temp_cap_rating; - unsigned char typepct[5]; - unsigned char reserved_2[3]; - unsigned int ncr; - unsigned int npr; - unsigned int ntr; + char model_cap_rating[4]; + char model_perm_cap_rating[4]; + char model_temp_cap_rating[4]; }; struct sysinfo_1_2_1 { @@ -55,9 +47,8 @@ struct sysinfo_1_2_2 { char format; char reserved_0[1]; unsigned short acc_offset; - char reserved_1[20]; - unsigned int nominal_cap; - unsigned int secondary_cap; + char reserved_1[24]; + unsigned int secondary_capability; unsigned int capability; unsigned short cpus_total; unsigned short cpus_configured; @@ -118,8 +109,6 @@ struct sysinfo_3_2_2 { char reserved_544[3552]; }; -extern int topology_max_mnest; - #define TOPOLOGY_CPU_BITS 64 #define TOPOLOGY_NR_MAG 6 @@ -153,7 +142,21 @@ struct sysinfo_15_1_x { union topology_entry tle[0]; }; -int stsi(void *sysinfo, int fc, int sel1, int sel2); +static inline int stsi(void *sysinfo, int fc, int sel1, int sel2) +{ + register int r0 asm("0") = (fc << 28) | sel1; + register int r1 asm("1") = sel2; + + asm volatile( + " stsi 0(%2)\n" + "0: jz 2f\n" + "1: lhi %0,%3\n" + "2:\n" + EX_TABLE(0b, 1b) + : "+d" (r0) : "d" (r1), "a" (sysinfo), "K" (-ENOSYS) + : "cc", "memory"); + return r0; +} /* * Service level reporting interface. diff --git a/trunk/arch/s390/include/asm/tlbflush.h b/trunk/arch/s390/include/asm/tlbflush.h index 1d8fe2b17ef6..9fde315f3a7c 100644 --- a/trunk/arch/s390/include/asm/tlbflush.h +++ b/trunk/arch/s390/include/asm/tlbflush.h @@ -90,10 +90,12 @@ static inline void __tlb_flush_mm(struct mm_struct * mm) static inline void __tlb_flush_mm_cond(struct mm_struct * mm) { + spin_lock(&mm->page_table_lock); if (mm->context.flush_mm) { __tlb_flush_mm(mm); mm->context.flush_mm = 0; } + spin_unlock(&mm->page_table_lock); } /* diff --git a/trunk/arch/s390/include/asm/topology.h b/trunk/arch/s390/include/asm/topology.h index 9ca305383760..0837de80c351 100644 --- a/trunk/arch/s390/include/asm/topology.h +++ b/trunk/arch/s390/include/asm/topology.h @@ -2,8 +2,8 @@ #define _ASM_S390_TOPOLOGY_H #include +#include -struct sysinfo_15_1_x; struct cpu; #ifdef CONFIG_SCHED_BOOK @@ -51,6 +51,24 @@ static inline void topology_expect_change(void) { } #define POLARIZATION_VM (2) #define POLARIZATION_VH (3) +extern int cpu_polarization[]; + +static inline void cpu_set_polarization(int cpu, int val) +{ +#ifdef CONFIG_SCHED_BOOK + cpu_polarization[cpu] = val; +#endif +} + +static inline int cpu_read_polarization(int cpu) +{ +#ifdef CONFIG_SCHED_BOOK + return cpu_polarization[cpu]; +#else + return POLARIZATION_HRZ; +#endif +} + #ifdef CONFIG_SCHED_BOOK void s390_init_cpu_topology(void); #else diff --git a/trunk/arch/s390/include/asm/uaccess.h b/trunk/arch/s390/include/asm/uaccess.h index 34268df959a3..a8ab18b18b54 100644 --- a/trunk/arch/s390/include/asm/uaccess.h +++ b/trunk/arch/s390/include/asm/uaccess.h @@ -76,22 +76,9 @@ static inline int __range_ok(unsigned long addr, unsigned long size) struct exception_table_entry { - int insn, fixup; + unsigned long insn, fixup; }; -static inline unsigned long extable_insn(const struct exception_table_entry *x) -{ - return (unsigned long)&x->insn + x->insn; -} - -static inline unsigned long extable_fixup(const struct exception_table_entry *x) -{ - return (unsigned long)&x->fixup + x->fixup; -} - -#define ARCH_HAS_SORT_EXTABLE -#define ARCH_HAS_SEARCH_EXTABLE - struct uaccess_ops { size_t (*copy_from_user)(size_t, const void __user *, void *); size_t (*copy_from_user_small)(size_t, const void __user *, void *); diff --git a/trunk/arch/s390/include/asm/unistd.h b/trunk/arch/s390/include/asm/unistd.h index 4e64b5cd1558..6756e78f4808 100644 --- a/trunk/arch/s390/include/asm/unistd.h +++ b/trunk/arch/s390/include/asm/unistd.h @@ -277,9 +277,7 @@ #define __NR_setns 339 #define __NR_process_vm_readv 340 #define __NR_process_vm_writev 341 -#define __NR_s390_runtime_instr 342 -#define __NR_kcmp 343 -#define NR_syscalls 344 +#define NR_syscalls 342 /* * There are some system calls that are not present on 64 bit, some diff --git a/trunk/arch/s390/kernel/Makefile b/trunk/arch/s390/kernel/Makefile index 4da52fe31743..9733b3f0eb6d 100644 --- a/trunk/arch/s390/kernel/Makefile +++ b/trunk/arch/s390/kernel/Makefile @@ -23,11 +23,10 @@ CFLAGS_sysinfo.o += -Iinclude/math-emu -Iarch/s390/math-emu -w obj-y := bitmap.o traps.o time.o process.o base.o early.o setup.o vtime.o \ processor.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o nmi.o \ debug.o irq.o ipl.o dis.o diag.o mem_detect.o sclp.o vdso.o \ - sysinfo.o jump_label.o lgr.o os_info.o machine_kexec.o + sysinfo.o jump_label.o lgr.o os_info.o obj-y += $(if $(CONFIG_64BIT),entry64.o,entry.o) obj-y += $(if $(CONFIG_64BIT),reipl64.o,reipl.o) -obj-y += $(if $(CONFIG_64BIT),relocate_kernel64.o,relocate_kernel.o) extra-y += head.o vmlinux.lds extra-y += $(if $(CONFIG_64BIT),head64.o,head31.o) @@ -49,11 +48,12 @@ obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o obj-$(CONFIG_FTRACE_SYSCALLS) += ftrace.o obj-$(CONFIG_CRASH_DUMP) += crash_dump.o - -ifdef CONFIG_64BIT obj-$(CONFIG_PERF_EVENTS) += perf_event.o perf_cpum_cf.o -obj-y += runtime_instr.o cache.o -endif + +# Kexec part +S390_KEXEC_OBJS := machine_kexec.o crash.o +S390_KEXEC_OBJS += $(if $(CONFIG_64BIT),relocate_kernel64.o,relocate_kernel.o) +obj-$(CONFIG_KEXEC) += $(S390_KEXEC_OBJS) # vdso obj-$(CONFIG_64BIT) += vdso64/ diff --git a/trunk/arch/s390/kernel/asm-offsets.c b/trunk/arch/s390/kernel/asm-offsets.c index fface87056eb..45ef1a7b08f9 100644 --- a/trunk/arch/s390/kernel/asm-offsets.c +++ b/trunk/arch/s390/kernel/asm-offsets.c @@ -157,8 +157,6 @@ int main(void) DEFINE(__LC_LAST_BREAK, offsetof(struct _lowcore, breaking_event_addr)); DEFINE(__LC_VDSO_PER_CPU, offsetof(struct _lowcore, vdso_per_cpu_data)); DEFINE(__LC_GMAP, offsetof(struct _lowcore, gmap)); - DEFINE(__LC_PGM_TDB, offsetof(struct _lowcore, pgm_tdb)); - DEFINE(__THREAD_trap_tdb, offsetof(struct task_struct, thread.trap_tdb)); DEFINE(__GMAP_ASCE, offsetof(struct gmap, asce)); #endif /* CONFIG_32BIT */ return 0; diff --git a/trunk/arch/s390/kernel/cache.c b/trunk/arch/s390/kernel/cache.c deleted file mode 100644 index 8df8d8a19c98..000000000000 --- a/trunk/arch/s390/kernel/cache.c +++ /dev/null @@ -1,385 +0,0 @@ -/* - * Extract CPU cache information and expose them via sysfs. - * - * Copyright IBM Corp. 2012 - * Author(s): Heiko Carstens - */ - -#include -#include -#include -#include -#include -#include -#include - -struct cache { - unsigned long size; - unsigned int line_size; - unsigned int associativity; - unsigned int nr_sets; - unsigned int level : 3; - unsigned int type : 2; - unsigned int private : 1; - struct list_head list; -}; - -struct cache_dir { - struct kobject *kobj; - struct cache_index_dir *index; -}; - -struct cache_index_dir { - struct kobject kobj; - int cpu; - struct cache *cache; - struct cache_index_dir *next; -}; - -enum { - CACHE_SCOPE_NOTEXISTS, - CACHE_SCOPE_PRIVATE, - CACHE_SCOPE_SHARED, - CACHE_SCOPE_RESERVED, -}; - -enum { - CACHE_TYPE_SEPARATE, - CACHE_TYPE_DATA, - CACHE_TYPE_INSTRUCTION, - CACHE_TYPE_UNIFIED, -}; - -enum { - EXTRACT_TOPOLOGY, - EXTRACT_LINE_SIZE, - EXTRACT_SIZE, - EXTRACT_ASSOCIATIVITY, -}; - -enum { - CACHE_TI_UNIFIED = 0, - CACHE_TI_INSTRUCTION = 0, - CACHE_TI_DATA, -}; - -struct cache_info { - unsigned char : 4; - unsigned char scope : 2; - unsigned char type : 2; -}; - -#define CACHE_MAX_LEVEL 8 - -union cache_topology { - struct cache_info ci[CACHE_MAX_LEVEL]; - unsigned long long raw; -}; - -static const char * const cache_type_string[] = { - "Data", - "Instruction", - "Unified", -}; - -static struct cache_dir *cache_dir_cpu[NR_CPUS]; -static LIST_HEAD(cache_list); - -void show_cacheinfo(struct seq_file *m) -{ - struct cache *cache; - int index = 0; - - list_for_each_entry(cache, &cache_list, list) { - seq_printf(m, "cache%-11d: ", index); - seq_printf(m, "level=%d ", cache->level); - seq_printf(m, "type=%s ", cache_type_string[cache->type]); - seq_printf(m, "scope=%s ", cache->private ? "Private" : "Shared"); - seq_printf(m, "size=%luK ", cache->size >> 10); - seq_printf(m, "line_size=%u ", cache->line_size); - seq_printf(m, "associativity=%d", cache->associativity); - seq_puts(m, "\n"); - index++; - } -} - -static inline unsigned long ecag(int ai, int li, int ti) -{ - unsigned long cmd, val; - - cmd = ai << 4 | li << 1 | ti; - asm volatile(".insn rsy,0xeb000000004c,%0,0,0(%1)" /* ecag */ - : "=d" (val) : "a" (cmd)); - return val; -} - -static int __init cache_add(int level, int private, int type) -{ - struct cache *cache; - int ti; - - cache = kzalloc(sizeof(*cache), GFP_KERNEL); - if (!cache) - return -ENOMEM; - ti = type == CACHE_TYPE_DATA ? CACHE_TI_DATA : CACHE_TI_UNIFIED; - cache->size = ecag(EXTRACT_SIZE, level, ti); - cache->line_size = ecag(EXTRACT_LINE_SIZE, level, ti); - cache->associativity = ecag(EXTRACT_ASSOCIATIVITY, level, ti); - cache->nr_sets = cache->size / cache->associativity; - cache->nr_sets /= cache->line_size; - cache->private = private; - cache->level = level + 1; - cache->type = type - 1; - list_add_tail(&cache->list, &cache_list); - return 0; -} - -static void __init cache_build_info(void) -{ - struct cache *cache, *next; - union cache_topology ct; - int level, private, rc; - - ct.raw = ecag(EXTRACT_TOPOLOGY, 0, 0); - for (level = 0; level < CACHE_MAX_LEVEL; level++) { - switch (ct.ci[level].scope) { - case CACHE_SCOPE_NOTEXISTS: - case CACHE_SCOPE_RESERVED: - return; - case CACHE_SCOPE_SHARED: - private = 0; - break; - case CACHE_SCOPE_PRIVATE: - private = 1; - break; - } - if (ct.ci[level].type == CACHE_TYPE_SEPARATE) { - rc = cache_add(level, private, CACHE_TYPE_DATA); - rc |= cache_add(level, private, CACHE_TYPE_INSTRUCTION); - } else { - rc = cache_add(level, private, ct.ci[level].type); - } - if (rc) - goto error; - } - return; -error: - list_for_each_entry_safe(cache, next, &cache_list, list) { - list_del(&cache->list); - kfree(cache); - } -} - -static struct cache_dir *__cpuinit cache_create_cache_dir(int cpu) -{ - struct cache_dir *cache_dir; - struct kobject *kobj = NULL; - struct device *dev; - - dev = get_cpu_device(cpu); - if (!dev) - goto out; - kobj = kobject_create_and_add("cache", &dev->kobj); - if (!kobj) - goto out; - cache_dir = kzalloc(sizeof(*cache_dir), GFP_KERNEL); - if (!cache_dir) - goto out; - cache_dir->kobj = kobj; - cache_dir_cpu[cpu] = cache_dir; - return cache_dir; -out: - kobject_put(kobj); - return NULL; -} - -static struct cache_index_dir *kobj_to_cache_index_dir(struct kobject *kobj) -{ - return container_of(kobj, struct cache_index_dir, kobj); -} - -static void cache_index_release(struct kobject *kobj) -{ - struct cache_index_dir *index; - - index = kobj_to_cache_index_dir(kobj); - kfree(index); -} - -static ssize_t cache_index_show(struct kobject *kobj, - struct attribute *attr, char *buf) -{ - struct kobj_attribute *kobj_attr; - - kobj_attr = container_of(attr, struct kobj_attribute, attr); - return kobj_attr->show(kobj, kobj_attr, buf); -} - -#define DEFINE_CACHE_ATTR(_name, _format, _value) \ -static ssize_t cache_##_name##_show(struct kobject *kobj, \ - struct kobj_attribute *attr, \ - char *buf) \ -{ \ - struct cache_index_dir *index; \ - \ - index = kobj_to_cache_index_dir(kobj); \ - return sprintf(buf, _format, _value); \ -} \ -static struct kobj_attribute cache_##_name##_attr = \ - __ATTR(_name, 0444, cache_##_name##_show, NULL); - -DEFINE_CACHE_ATTR(size, "%luK\n", index->cache->size >> 10); -DEFINE_CACHE_ATTR(coherency_line_size, "%u\n", index->cache->line_size); -DEFINE_CACHE_ATTR(number_of_sets, "%u\n", index->cache->nr_sets); -DEFINE_CACHE_ATTR(ways_of_associativity, "%u\n", index->cache->associativity); -DEFINE_CACHE_ATTR(type, "%s\n", cache_type_string[index->cache->type]); -DEFINE_CACHE_ATTR(level, "%d\n", index->cache->level); - -static ssize_t shared_cpu_map_func(struct kobject *kobj, int type, char *buf) -{ - struct cache_index_dir *index; - int len; - - index = kobj_to_cache_index_dir(kobj); - len = type ? - cpulist_scnprintf(buf, PAGE_SIZE - 2, cpumask_of(index->cpu)) : - cpumask_scnprintf(buf, PAGE_SIZE - 2, cpumask_of(index->cpu)); - len += sprintf(&buf[len], "\n"); - return len; -} - -static ssize_t shared_cpu_map_show(struct kobject *kobj, - struct kobj_attribute *attr, char *buf) -{ - return shared_cpu_map_func(kobj, 0, buf); -} -static struct kobj_attribute cache_shared_cpu_map_attr = - __ATTR(shared_cpu_map, 0444, shared_cpu_map_show, NULL); - -static ssize_t shared_cpu_list_show(struct kobject *kobj, - struct kobj_attribute *attr, char *buf) -{ - return shared_cpu_map_func(kobj, 1, buf); -} -static struct kobj_attribute cache_shared_cpu_list_attr = - __ATTR(shared_cpu_list, 0444, shared_cpu_list_show, NULL); - -static struct attribute *cache_index_default_attrs[] = { - &cache_type_attr.attr, - &cache_size_attr.attr, - &cache_number_of_sets_attr.attr, - &cache_ways_of_associativity_attr.attr, - &cache_level_attr.attr, - &cache_coherency_line_size_attr.attr, - &cache_shared_cpu_map_attr.attr, - &cache_shared_cpu_list_attr.attr, - NULL, -}; - -static const struct sysfs_ops cache_index_ops = { - .show = cache_index_show, -}; - -static struct kobj_type cache_index_type = { - .sysfs_ops = &cache_index_ops, - .release = cache_index_release, - .default_attrs = cache_index_default_attrs, -}; - -static int __cpuinit cache_create_index_dir(struct cache_dir *cache_dir, - struct cache *cache, int index, - int cpu) -{ - struct cache_index_dir *index_dir; - int rc; - - index_dir = kzalloc(sizeof(*index_dir), GFP_KERNEL); - if (!index_dir) - return -ENOMEM; - index_dir->cache = cache; - index_dir->cpu = cpu; - rc = kobject_init_and_add(&index_dir->kobj, &cache_index_type, - cache_dir->kobj, "index%d", index); - if (rc) - goto out; - index_dir->next = cache_dir->index; - cache_dir->index = index_dir; - return 0; -out: - kfree(index_dir); - return rc; -} - -static int __cpuinit cache_add_cpu(int cpu) -{ - struct cache_dir *cache_dir; - struct cache *cache; - int rc, index = 0; - - if (list_empty(&cache_list)) - return 0; - cache_dir = cache_create_cache_dir(cpu); - if (!cache_dir) - return -ENOMEM; - list_for_each_entry(cache, &cache_list, list) { - if (!cache->private) - break; - rc = cache_create_index_dir(cache_dir, cache, index, cpu); - if (rc) - return rc; - index++; - } - return 0; -} - -static void __cpuinit cache_remove_cpu(int cpu) -{ - struct cache_index_dir *index, *next; - struct cache_dir *cache_dir; - - cache_dir = cache_dir_cpu[cpu]; - if (!cache_dir) - return; - index = cache_dir->index; - while (index) { - next = index->next; - kobject_put(&index->kobj); - index = next; - } - kobject_put(cache_dir->kobj); - kfree(cache_dir); - cache_dir_cpu[cpu] = NULL; -} - -static int __cpuinit cache_hotplug(struct notifier_block *nfb, - unsigned long action, void *hcpu) -{ - int cpu = (long)hcpu; - int rc = 0; - - switch (action & ~CPU_TASKS_FROZEN) { - case CPU_ONLINE: - rc = cache_add_cpu(cpu); - if (rc) - cache_remove_cpu(cpu); - break; - case CPU_DEAD: - cache_remove_cpu(cpu); - break; - } - return rc ? NOTIFY_BAD : NOTIFY_OK; -} - -static int __init cache_init(void) -{ - int cpu; - - if (!test_facility(34)) - return 0; - cache_build_info(); - for_each_online_cpu(cpu) - cache_add_cpu(cpu); - hotcpu_notifier(cache_hotplug, 0); - return 0; -} -device_initcall(cache_init); diff --git a/trunk/arch/s390/kernel/compat_linux.c b/trunk/arch/s390/kernel/compat_linux.c index f606d935f495..d1225089a4bb 100644 --- a/trunk/arch/s390/kernel/compat_linux.c +++ b/trunk/arch/s390/kernel/compat_linux.c @@ -620,6 +620,7 @@ asmlinkage unsigned long old32_mmap(struct mmap_arg_struct_emu31 __user *arg) return -EFAULT; if (a.offset & ~PAGE_MASK) return -EINVAL; + a.addr = (unsigned long) compat_ptr(a.addr); return sys_mmap_pgoff(a.addr, a.len, a.prot, a.flags, a.fd, a.offset >> PAGE_SHIFT); } @@ -630,6 +631,7 @@ asmlinkage long sys32_mmap2(struct mmap_arg_struct_emu31 __user *arg) if (copy_from_user(&a, arg, sizeof(a))) return -EFAULT; + a.addr = (unsigned long) compat_ptr(a.addr); return sys_mmap_pgoff(a.addr, a.len, a.prot, a.flags, a.fd, a.offset); } diff --git a/trunk/arch/s390/kernel/compat_wrapper.S b/trunk/arch/s390/kernel/compat_wrapper.S index 3afba804fe97..e835d6d5b7fd 100644 --- a/trunk/arch/s390/kernel/compat_wrapper.S +++ b/trunk/arch/s390/kernel/compat_wrapper.S @@ -1635,7 +1635,7 @@ ENTRY(compat_sys_process_vm_readv_wrapper) llgfr %r6,%r6 # unsigned long llgf %r0,164(%r15) # unsigned long stg %r0,160(%r15) - jg compat_sys_process_vm_readv + jg sys_process_vm_readv ENTRY(compat_sys_process_vm_writev_wrapper) lgfr %r2,%r2 # compat_pid_t @@ -1645,17 +1645,4 @@ ENTRY(compat_sys_process_vm_writev_wrapper) llgfr %r6,%r6 # unsigned long llgf %r0,164(%r15) # unsigned long stg %r0,160(%r15) - jg compat_sys_process_vm_writev - -ENTRY(sys_s390_runtime_instr_wrapper) - lgfr %r2,%r2 # int - lgfr %r3,%r3 # int - jg sys_s390_runtime_instr - -ENTRY(sys_kcmp_wrapper) - lgfr %r2,%r2 # pid_t - lgfr %r3,%r3 # pid_t - lgfr %r4,%r4 # int - llgfr %r5,%r5 # unsigned long - llgfr %r6,%r6 # unsigned long - jg sys_kcmp + jg sys_process_vm_writev diff --git a/trunk/arch/s390/kernel/crash.c b/trunk/arch/s390/kernel/crash.c new file mode 100644 index 000000000000..3819153de8bd --- /dev/null +++ b/trunk/arch/s390/kernel/crash.c @@ -0,0 +1,14 @@ +/* + * Copyright IBM Corp. 2005 + * + * Author(s): Heiko Carstens + * + */ + +#include +#include +#include + +void machine_crash_shutdown(struct pt_regs *regs) +{ +} diff --git a/trunk/arch/s390/kernel/crash_dump.c b/trunk/arch/s390/kernel/crash_dump.c index fb8d8781a011..cc1172b26873 100644 --- a/trunk/arch/s390/kernel/crash_dump.c +++ b/trunk/arch/s390/kernel/crash_dump.c @@ -13,9 +13,8 @@ #include #include #include -#include -#include #include +#include #define PTR_ADD(x, y) (((char *) (x)) + ((unsigned long) (y))) #define PTR_SUB(x, y) (((char *) (x)) - ((unsigned long) (y))) diff --git a/trunk/arch/s390/kernel/dis.c b/trunk/arch/s390/kernel/dis.c index cc84a24c023f..619c5d350726 100644 --- a/trunk/arch/s390/kernel/dis.c +++ b/trunk/arch/s390/kernel/dis.c @@ -315,11 +315,6 @@ enum { LONG_INSN_POPCNT, LONG_INSN_RISBHG, LONG_INSN_RISBLG, - LONG_INSN_RINEXT, - LONG_INSN_RIEMIT, - LONG_INSN_TABORT, - LONG_INSN_TBEGIN, - LONG_INSN_TBEGINC, }; static char *long_insn_name[] = { @@ -334,12 +329,7 @@ static char *long_insn_name[] = { [LONG_INSN_LLGHRL] = "llghrl", [LONG_INSN_POPCNT] = "popcnt", [LONG_INSN_RISBHG] = "risbhg", - [LONG_INSN_RISBLG] = "risblg", - [LONG_INSN_RINEXT] = "rinext", - [LONG_INSN_RIEMIT] = "riemit", - [LONG_INSN_TABORT] = "tabort", - [LONG_INSN_TBEGIN] = "tbegin", - [LONG_INSN_TBEGINC] = "tbeginc", + [LONG_INSN_RISBLG] = "risblk", }; static struct insn opcode[] = { @@ -592,17 +582,6 @@ static struct insn opcode_a7[] = { { "", 0, INSTR_INVALID } }; -static struct insn opcode_aa[] = { -#ifdef CONFIG_64BIT - { { 0, LONG_INSN_RINEXT }, 0x00, INSTR_RI_RI }, - { "rion", 0x01, INSTR_RI_RI }, - { "tric", 0x02, INSTR_RI_RI }, - { "rioff", 0x03, INSTR_RI_RI }, - { { 0, LONG_INSN_RIEMIT }, 0x04, INSTR_RI_RI }, -#endif - { "", 0, INSTR_INVALID } -}; - static struct insn opcode_b2[] = { #ifdef CONFIG_64BIT { "sske", 0x2b, INSTR_RRF_M0RR }, @@ -615,9 +594,6 @@ static struct insn opcode_b2[] = { { "lpswe", 0xb2, INSTR_S_RD }, { "srnmt", 0xb9, INSTR_S_RD }, { "lfas", 0xbd, INSTR_S_RD }, - { "etndg", 0xec, INSTR_RRE_R0 }, - { { 0, LONG_INSN_TABORT }, 0xfc, INSTR_S_RD }, - { "tend", 0xf8, INSTR_S_RD }, #endif { "stidp", 0x02, INSTR_S_RD }, { "sck", 0x04, INSTR_S_RD }, @@ -1174,7 +1150,6 @@ static struct insn opcode_e3[] = { { "stfh", 0xcb, INSTR_RXY_RRRD }, { "chf", 0xcd, INSTR_RXY_RRRD }, { "clhf", 0xcf, INSTR_RXY_RRRD }, - { "ntstg", 0x25, INSTR_RXY_RRRD }, #endif { "lrv", 0x1e, INSTR_RXY_RRRD }, { "lrvh", 0x1f, INSTR_RXY_RRRD }, @@ -1198,8 +1173,6 @@ static struct insn opcode_e5[] = { { "mvhhi", 0x44, INSTR_SIL_RDI }, { "mvhi", 0x4c, INSTR_SIL_RDI }, { "mvghi", 0x48, INSTR_SIL_RDI }, - { { 0, LONG_INSN_TBEGIN }, 0x60, INSTR_SIL_RDU }, - { { 0, LONG_INSN_TBEGINC }, 0x61, INSTR_SIL_RDU }, #endif { "lasp", 0x00, INSTR_SSE_RDRD }, { "tprot", 0x01, INSTR_SSE_RDRD }, @@ -1237,9 +1210,6 @@ static struct insn opcode_eb[] = { { "cliy", 0x55, INSTR_SIY_URD }, { "oiy", 0x56, INSTR_SIY_URD }, { "xiy", 0x57, INSTR_SIY_URD }, - { "lric", 0x60, INSTR_RSY_RDRM }, - { "stric", 0x61, INSTR_RSY_RDRM }, - { "mric", 0x62, INSTR_RSY_RDRM }, { "icmh", 0x80, INSTR_RSE_RURD }, { "icmh", 0x80, INSTR_RSY_RURD }, { "icmy", 0x81, INSTR_RSY_RURD }, @@ -1438,9 +1408,6 @@ static struct insn *find_insn(unsigned char *code) case 0xa7: table = opcode_a7; break; - case 0xaa: - table = opcode_aa; - break; case 0xb2: table = opcode_b2; break; @@ -1634,26 +1601,3 @@ void show_code(struct pt_regs *regs) } printk("\n"); } - -void print_fn_code(unsigned char *code, unsigned long len) -{ - char buffer[64], *ptr; - int opsize, i; - - while (len) { - ptr = buffer; - opsize = insn_length(*code); - ptr += sprintf(ptr, "%p: ", code); - for (i = 0; i < opsize; i++) - ptr += sprintf(ptr, "%02x", code[i]); - *ptr++ = '\t'; - if (i < 4) - *ptr++ = '\t'; - ptr += print_insn(ptr, code, (unsigned long) code); - *ptr++ = '\n'; - *ptr++ = 0; - printk(buffer); - code += opsize; - len -= opsize; - } -} diff --git a/trunk/arch/s390/kernel/early.c b/trunk/arch/s390/kernel/early.c index 7f4717675c19..83c3271c442b 100644 --- a/trunk/arch/s390/kernel/early.c +++ b/trunk/arch/s390/kernel/early.c @@ -215,54 +215,36 @@ static noinline __init void init_kernel_storage_key(void) PAGE_DEFAULT_KEY, 0); } -static __initdata char sysinfo_page[PAGE_SIZE] __aligned(PAGE_SIZE); +static __initdata struct sysinfo_3_2_2 vmms __aligned(PAGE_SIZE); static noinline __init void detect_machine_type(void) { - struct sysinfo_3_2_2 *vmms = (struct sysinfo_3_2_2 *)&sysinfo_page; - /* Check current-configuration-level */ - if (stsi(NULL, 0, 0, 0) <= 2) { + if ((stsi(NULL, 0, 0, 0) >> 28) <= 2) { S390_lowcore.machine_flags |= MACHINE_FLAG_LPAR; return; } /* Get virtual-machine cpu information. */ - if (stsi(vmms, 3, 2, 2) || !vmms->count) + if (stsi(&vmms, 3, 2, 2) == -ENOSYS || !vmms.count) return; /* Running under KVM? If not we assume z/VM */ - if (!memcmp(vmms->vm[0].cpi, "\xd2\xe5\xd4", 3)) + if (!memcmp(vmms.vm[0].cpi, "\xd2\xe5\xd4", 3)) S390_lowcore.machine_flags |= MACHINE_FLAG_KVM; else S390_lowcore.machine_flags |= MACHINE_FLAG_VM; } -static __init void setup_topology(void) -{ -#ifdef CONFIG_64BIT - int max_mnest; - - if (!test_facility(11)) - return; - S390_lowcore.machine_flags |= MACHINE_FLAG_TOPOLOGY; - for (max_mnest = 6; max_mnest > 1; max_mnest--) { - if (stsi(&sysinfo_page, 15, 1, max_mnest) == 0) - break; - } - topology_max_mnest = max_mnest; -#endif -} - static void early_pgm_check_handler(void) { - const struct exception_table_entry *fixup; unsigned long addr; + const struct exception_table_entry *fixup; addr = S390_lowcore.program_old_psw.addr; fixup = search_exception_tables(addr & PSW_ADDR_INSN); if (!fixup) disabled_wait(0); - S390_lowcore.program_old_psw.addr = extable_fixup(fixup)|PSW_ADDR_AMODE; + S390_lowcore.program_old_psw.addr = fixup->fixup | PSW_ADDR_AMODE; } static noinline __init void setup_lowcore_early(void) @@ -285,10 +267,12 @@ static noinline __init void setup_facility_list(void) static noinline __init void setup_hpage(void) { +#ifndef CONFIG_DEBUG_PAGEALLOC if (!test_facility(2) || !test_facility(8)) return; S390_lowcore.machine_flags |= MACHINE_FLAG_HPAGE; __ctl_set_bit(0, 23); +#endif } static __init void detect_mvpg(void) @@ -382,12 +366,12 @@ static __init void detect_machine_facilities(void) S390_lowcore.machine_flags |= MACHINE_FLAG_IDTE; if (test_facility(8)) S390_lowcore.machine_flags |= MACHINE_FLAG_PFMF; + if (test_facility(11)) + S390_lowcore.machine_flags |= MACHINE_FLAG_TOPOLOGY; if (test_facility(27)) S390_lowcore.machine_flags |= MACHINE_FLAG_MVCOS; if (test_facility(40)) S390_lowcore.machine_flags |= MACHINE_FLAG_SPP; - if (test_facility(50) && test_facility(73)) - S390_lowcore.machine_flags |= MACHINE_FLAG_TE; #endif } @@ -457,6 +441,7 @@ static void __init setup_boot_command_line(void) append_to_cmdline(append_ipl_scpdata); } + /* * Save ipl parameters, clear bss memory, initialize storage keys * and create a kernel NSS at startup if the SAVESYS= parm is defined @@ -483,7 +468,6 @@ void __init startup_init(void) detect_diag44(); detect_machine_facilities(); setup_hpage(); - setup_topology(); sclp_facilities_detect(); detect_memory_layout(memory_chunk); #ifdef CONFIG_DYNAMIC_FTRACE diff --git a/trunk/arch/s390/kernel/entry64.S b/trunk/arch/s390/kernel/entry64.S index 7549985402f7..349b7eeb348a 100644 --- a/trunk/arch/s390/kernel/entry64.S +++ b/trunk/arch/s390/kernel/entry64.S @@ -10,7 +10,6 @@ #include #include -#include #include #include #include @@ -413,11 +412,6 @@ ENTRY(pgm_check_handler) 1: UPDATE_VTIME %r14,__LC_SYNC_ENTER_TIMER LAST_BREAK %r14 lg %r15,__LC_KERNEL_STACK - lg %r14,__TI_task(%r12) - lghi %r13,__LC_PGM_TDB - tm __LC_PGM_ILC+2,0x02 # check for transaction abort - jz 2f - mvc __THREAD_trap_tdb(256,%r14),0(%r13) 2: aghi %r15,-(STACK_FRAME_OVERHEAD + __PT_SIZE) la %r11,STACK_FRAME_OVERHEAD(%r15) stmg %r0,%r7,__PT_R0(%r11) @@ -428,12 +422,13 @@ ENTRY(pgm_check_handler) stg %r10,__PT_ARGS(%r11) tm __LC_PGM_ILC+3,0x80 # check for per exception jz 0f + lg %r1,__TI_task(%r12) tmhh %r8,0x0001 # kernel per event ? jz pgm_kprobe oi __TI_flags+7(%r12),_TIF_PER_TRAP - mvc __THREAD_per_address(8,%r14),__LC_PER_ADDRESS - mvc __THREAD_per_cause(2,%r14),__LC_PER_CAUSE - mvc __THREAD_per_paid(1,%r14),__LC_PER_PAID + mvc __THREAD_per_address(8,%r1),__LC_PER_ADDRESS + mvc __THREAD_per_cause(2,%r1),__LC_PER_CAUSE + mvc __THREAD_per_paid(1,%r1),__LC_PER_PAID 0: REENABLE_IRQS xc __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15) larl %r1,pgm_check_table @@ -1009,7 +1004,9 @@ sie_fault: .Lhost_id: .quad 0 - EX_TABLE(sie_loop,sie_fault) + .section __ex_table,"a" + .quad sie_loop,sie_fault + .previous #endif .section .rodata, "a" diff --git a/trunk/arch/s390/kernel/irq.c b/trunk/arch/s390/kernel/irq.c index 6cdc55b26d68..dd7630d8aab7 100644 --- a/trunk/arch/s390/kernel/irq.c +++ b/trunk/arch/s390/kernel/irq.c @@ -30,35 +30,33 @@ struct irq_class { }; static const struct irq_class intrclass_names[] = { - [EXTERNAL_INTERRUPT] = {.name = "EXT"}, - [IO_INTERRUPT] = {.name = "I/O"}, - [EXTINT_CLK] = {.name = "CLK", .desc = "[EXT] Clock Comparator"}, - [EXTINT_EXC] = {.name = "EXC", .desc = "[EXT] External Call"}, - [EXTINT_EMS] = {.name = "EMS", .desc = "[EXT] Emergency Signal"}, - [EXTINT_TMR] = {.name = "TMR", .desc = "[EXT] CPU Timer"}, - [EXTINT_TLA] = {.name = "TAL", .desc = "[EXT] Timing Alert"}, - [EXTINT_PFL] = {.name = "PFL", .desc = "[EXT] Pseudo Page Fault"}, - [EXTINT_DSD] = {.name = "DSD", .desc = "[EXT] DASD Diag"}, - [EXTINT_VRT] = {.name = "VRT", .desc = "[EXT] Virtio"}, - [EXTINT_SCP] = {.name = "SCP", .desc = "[EXT] Service Call"}, - [EXTINT_IUC] = {.name = "IUC", .desc = "[EXT] IUCV"}, - [EXTINT_CMS] = {.name = "CMS", .desc = "[EXT] CPU-Measurement: Sampling"}, - [EXTINT_CMC] = {.name = "CMC", .desc = "[EXT] CPU-Measurement: Counter"}, - [EXTINT_CMR] = {.name = "CMR", .desc = "[EXT] CPU-Measurement: RI"}, - [IOINT_CIO] = {.name = "CIO", .desc = "[I/O] Common I/O Layer Interrupt"}, - [IOINT_QAI] = {.name = "QAI", .desc = "[I/O] QDIO Adapter Interrupt"}, - [IOINT_DAS] = {.name = "DAS", .desc = "[I/O] DASD"}, - [IOINT_C15] = {.name = "C15", .desc = "[I/O] 3215"}, - [IOINT_C70] = {.name = "C70", .desc = "[I/O] 3270"}, - [IOINT_TAP] = {.name = "TAP", .desc = "[I/O] Tape"}, - [IOINT_VMR] = {.name = "VMR", .desc = "[I/O] Unit Record Devices"}, - [IOINT_LCS] = {.name = "LCS", .desc = "[I/O] LCS"}, - [IOINT_CLW] = {.name = "CLW", .desc = "[I/O] CLAW"}, - [IOINT_CTC] = {.name = "CTC", .desc = "[I/O] CTC"}, - [IOINT_APB] = {.name = "APB", .desc = "[I/O] AP Bus"}, - [IOINT_ADM] = {.name = "ADM", .desc = "[I/O] EADM Subchannel"}, - [IOINT_CSC] = {.name = "CSC", .desc = "[I/O] CHSC Subchannel"}, - [NMI_NMI] = {.name = "NMI", .desc = "[NMI] Machine Check"}, + {.name = "EXT" }, + {.name = "I/O" }, + {.name = "CLK", .desc = "[EXT] Clock Comparator" }, + {.name = "EXC", .desc = "[EXT] External Call" }, + {.name = "EMS", .desc = "[EXT] Emergency Signal" }, + {.name = "TMR", .desc = "[EXT] CPU Timer" }, + {.name = "TAL", .desc = "[EXT] Timing Alert" }, + {.name = "PFL", .desc = "[EXT] Pseudo Page Fault" }, + {.name = "DSD", .desc = "[EXT] DASD Diag" }, + {.name = "VRT", .desc = "[EXT] Virtio" }, + {.name = "SCP", .desc = "[EXT] Service Call" }, + {.name = "IUC", .desc = "[EXT] IUCV" }, + {.name = "CMS", .desc = "[EXT] CPU-Measurement: Sampling" }, + {.name = "CMC", .desc = "[EXT] CPU-Measurement: Counter" }, + {.name = "CIO", .desc = "[I/O] Common I/O Layer Interrupt" }, + {.name = "QAI", .desc = "[I/O] QDIO Adapter Interrupt" }, + {.name = "DAS", .desc = "[I/O] DASD" }, + {.name = "C15", .desc = "[I/O] 3215" }, + {.name = "C70", .desc = "[I/O] 3270" }, + {.name = "TAP", .desc = "[I/O] Tape" }, + {.name = "VMR", .desc = "[I/O] Unit Record Devices" }, + {.name = "LCS", .desc = "[I/O] LCS" }, + {.name = "CLW", .desc = "[I/O] CLAW" }, + {.name = "CTC", .desc = "[I/O] CTC" }, + {.name = "APB", .desc = "[I/O] AP Bus" }, + {.name = "CSC", .desc = "[I/O] CHSC Subchannel" }, + {.name = "NMI", .desc = "[NMI] Machine Check" }, }; /* diff --git a/trunk/arch/s390/kernel/kprobes.c b/trunk/arch/s390/kernel/kprobes.c index d1c7214e157c..8aa634f5944b 100644 --- a/trunk/arch/s390/kernel/kprobes.c +++ b/trunk/arch/s390/kernel/kprobes.c @@ -547,7 +547,7 @@ static int __kprobes kprobe_trap_handler(struct pt_regs *regs, int trapnr) */ entry = search_exception_tables(regs->psw.addr & PSW_ADDR_INSN); if (entry) { - regs->psw.addr = extable_fixup(entry) | PSW_ADDR_AMODE; + regs->psw.addr = entry->fixup | PSW_ADDR_AMODE; return 1; } diff --git a/trunk/arch/s390/kernel/lgr.c b/trunk/arch/s390/kernel/lgr.c index 6ea6d69339b5..eca94e74d19a 100644 --- a/trunk/arch/s390/kernel/lgr.c +++ b/trunk/arch/s390/kernel/lgr.c @@ -50,6 +50,16 @@ static struct lgr_info lgr_info_last; static struct lgr_info lgr_info_cur; static struct debug_info *lgr_dbf; +/* + * Return number of valid stsi levels + */ +static inline int stsi_0(void) +{ + int rc = stsi(NULL, 0, 0, 0); + + return rc == -ENOSYS ? rc : (((unsigned int) rc) >> 28); +} + /* * Copy buffer and then convert it to ASCII */ @@ -66,7 +76,7 @@ static void lgr_stsi_1_1_1(struct lgr_info *lgr_info) { struct sysinfo_1_1_1 *si = (void *) lgr_page; - if (stsi(si, 1, 1, 1)) + if (stsi(si, 1, 1, 1) == -ENOSYS) return; cpascii(lgr_info->manufacturer, si->manufacturer, sizeof(si->manufacturer)); @@ -83,7 +93,7 @@ static void lgr_stsi_2_2_2(struct lgr_info *lgr_info) { struct sysinfo_2_2_2 *si = (void *) lgr_page; - if (stsi(si, 2, 2, 2)) + if (stsi(si, 2, 2, 2) == -ENOSYS) return; cpascii(lgr_info->name, si->name, sizeof(si->name)); memcpy(&lgr_info->lpar_number, &si->lpar_number, @@ -98,7 +108,7 @@ static void lgr_stsi_3_2_2(struct lgr_info *lgr_info) struct sysinfo_3_2_2 *si = (void *) lgr_page; int i; - if (stsi(si, 3, 2, 2)) + if (stsi(si, 3, 2, 2) == -ENOSYS) return; for (i = 0; i < min_t(u8, si->count, VM_LEVEL_MAX); i++) { cpascii(lgr_info->vm[i].name, si->vm[i].name, @@ -114,17 +124,16 @@ static void lgr_stsi_3_2_2(struct lgr_info *lgr_info) */ static void lgr_info_get(struct lgr_info *lgr_info) { - int level; - memset(lgr_info, 0, sizeof(*lgr_info)); stfle(lgr_info->stfle_fac_list, ARRAY_SIZE(lgr_info->stfle_fac_list)); - level = stsi(NULL, 0, 0, 0); - lgr_info->level = level; - if (level >= 1) + lgr_info->level = stsi_0(); + if (lgr_info->level == -ENOSYS) + return; + if (lgr_info->level >= 1) lgr_stsi_1_1_1(lgr_info); - if (level >= 2) + if (lgr_info->level >= 2) lgr_stsi_2_2_2(lgr_info); - if (level >= 3) + if (lgr_info->level >= 3) lgr_stsi_3_2_2(lgr_info); } diff --git a/trunk/arch/s390/kernel/machine_kexec.c b/trunk/arch/s390/kernel/machine_kexec.c index b3de27700016..493304bdf1c7 100644 --- a/trunk/arch/s390/kernel/machine_kexec.c +++ b/trunk/arch/s390/kernel/machine_kexec.c @@ -21,7 +21,6 @@ #include #include #include -#include #include #include @@ -32,6 +31,8 @@ extern const unsigned long long relocate_kernel_len; #ifdef CONFIG_CRASH_DUMP +void *fill_cpu_elf_notes(void *ptr, struct save_area *sa); + /* * Create ELF notes for one CPU */ @@ -158,7 +159,7 @@ int machine_kexec_prepare(struct kimage *image) /* Can't replace kernel image since it is read-only. */ if (ipl_flags & IPL_NSS_VALID) - return -EOPNOTSUPP; + return -ENOSYS; if (image->type == KEXEC_TYPE_CRASH) return machine_kexec_prepare_kdump(); @@ -190,10 +191,6 @@ void machine_shutdown(void) { } -void machine_crash_shutdown(struct pt_regs *regs) -{ -} - /* * Do normal kexec */ diff --git a/trunk/arch/s390/kernel/process.c b/trunk/arch/s390/kernel/process.c index 5024be27df44..733175373a4c 100644 --- a/trunk/arch/s390/kernel/process.c +++ b/trunk/arch/s390/kernel/process.c @@ -26,12 +26,10 @@ #include #include #include -#include #include #include #include #include -#include #include "entry.h" asmlinkage void ret_from_fork(void) asm ("ret_from_fork"); @@ -134,7 +132,6 @@ EXPORT_SYMBOL(kernel_thread); */ void exit_thread(void) { - exit_thread_runtime_instr(); } void flush_thread(void) @@ -173,11 +170,6 @@ int copy_thread(unsigned long clone_flags, unsigned long new_stackp, /* Save access registers to new thread structure. */ save_access_regs(&p->thread.acrs[0]); - /* Don't copy runtime instrumentation info */ - p->thread.ri_cb = NULL; - p->thread.ri_signum = 0; - frame->childregs.psw.mask &= ~PSW_MASK_RI; - #ifndef CONFIG_64BIT /* * save fprs to current->thread.fp_regs to merge them with diff --git a/trunk/arch/s390/kernel/processor.c b/trunk/arch/s390/kernel/processor.c index 753c41d0ffd3..572d4c9cb33b 100644 --- a/trunk/arch/s390/kernel/processor.c +++ b/trunk/arch/s390/kernel/processor.c @@ -39,9 +39,9 @@ void __cpuinit cpu_init(void) */ static int show_cpuinfo(struct seq_file *m, void *v) { - static const char *hwcap_str[] = { + static const char *hwcap_str[10] = { "esan3", "zarch", "stfle", "msa", "ldisp", "eimm", "dfp", - "edat", "etf3eh", "highgprs", "te" + "edat", "etf3eh", "highgprs" }; unsigned long n = (unsigned long) v - 1; int i; @@ -54,11 +54,10 @@ static int show_cpuinfo(struct seq_file *m, void *v) num_online_cpus(), loops_per_jiffy/(500000/HZ), (loops_per_jiffy/(5000/HZ))%100); seq_puts(m, "features\t: "); - for (i = 0; i < ARRAY_SIZE(hwcap_str); i++) + for (i = 0; i < 10; i++) if (hwcap_str[i] && (elf_hwcap & (1UL << i))) seq_printf(m, "%s ", hwcap_str[i]); seq_puts(m, "\n"); - show_cacheinfo(m); } get_online_cpus(); if (cpu_online(n)) { diff --git a/trunk/arch/s390/kernel/ptrace.c b/trunk/arch/s390/kernel/ptrace.c index a314c57f4e94..f4eb37680b91 100644 --- a/trunk/arch/s390/kernel/ptrace.c +++ b/trunk/arch/s390/kernel/ptrace.c @@ -42,7 +42,6 @@ enum s390_regset { REGSET_GENERAL, REGSET_FP, REGSET_LAST_BREAK, - REGSET_TDB, REGSET_SYSTEM_CALL, REGSET_GENERAL_EXTENDED, }; @@ -53,22 +52,6 @@ void update_per_regs(struct task_struct *task) struct thread_struct *thread = &task->thread; struct per_regs old, new; -#ifdef CONFIG_64BIT - /* Take care of the enable/disable of transactional execution. */ - if (MACHINE_HAS_TE) { - unsigned long cr0, cr0_new; - - __ctl_store(cr0, 0, 0); - /* set or clear transaction execution bits 8 and 9. */ - if (task->thread.per_flags & PER_FLAG_NO_TE) - cr0_new = cr0 & ~(3UL << 54); - else - cr0_new = cr0 | (3UL << 54); - /* Only load control register 0 if necessary. */ - if (cr0 != cr0_new) - __ctl_load(cr0_new, 0, 0); - } -#endif /* Copy user specified PER registers */ new.control = thread->per_user.control; new.start = thread->per_user.start; @@ -77,10 +60,6 @@ void update_per_regs(struct task_struct *task) /* merge TIF_SINGLE_STEP into user specified PER registers. */ if (test_tsk_thread_flag(task, TIF_SINGLE_STEP)) { new.control |= PER_EVENT_IFETCH; -#ifdef CONFIG_64BIT - new.control |= PER_CONTROL_SUSPENSION; - new.control |= PER_EVENT_TRANSACTION_END; -#endif new.start = 0; new.end = PSW_ADDR_INSN; } @@ -121,7 +100,6 @@ void ptrace_disable(struct task_struct *task) memset(&task->thread.per_event, 0, sizeof(task->thread.per_event)); clear_tsk_thread_flag(task, TIF_SINGLE_STEP); clear_tsk_thread_flag(task, TIF_PER_TRAP); - task->thread.per_flags = 0; } #ifndef CONFIG_64BIT @@ -438,16 +416,6 @@ long arch_ptrace(struct task_struct *child, long request, put_user(task_thread_info(child)->last_break, (unsigned long __user *) data); return 0; - case PTRACE_ENABLE_TE: - if (!MACHINE_HAS_TE) - return -EIO; - child->thread.per_flags &= ~PER_FLAG_NO_TE; - return 0; - case PTRACE_DISABLE_TE: - if (!MACHINE_HAS_TE) - return -EIO; - child->thread.per_flags |= PER_FLAG_NO_TE; - return 0; default: /* Removing high order bit from addr (only for 31 bit). */ addr &= PSW_ADDR_INSN; @@ -751,11 +719,7 @@ asmlinkage long do_syscall_trace_enter(struct pt_regs *regs) long ret = 0; /* Do the secure computing check first. */ - if (secure_computing(regs->gprs[2])) { - /* seccomp failures shouldn't expose any additional code. */ - ret = -1; - goto out; - } + secure_computing_strict(regs->gprs[2]); /* * The sysc_tracesys code in entry.S stored the system @@ -781,7 +745,6 @@ asmlinkage long do_syscall_trace_enter(struct pt_regs *regs) regs->gprs[2], regs->orig_gpr2, regs->gprs[3], regs->gprs[4], regs->gprs[5]); -out: return ret ?: regs->gprs[2]; } @@ -935,28 +898,6 @@ static int s390_last_break_set(struct task_struct *target, return 0; } -static int s390_tdb_get(struct task_struct *target, - const struct user_regset *regset, - unsigned int pos, unsigned int count, - void *kbuf, void __user *ubuf) -{ - struct pt_regs *regs = task_pt_regs(target); - unsigned char *data; - - if (!(regs->int_code & 0x200)) - return -ENODATA; - data = target->thread.trap_tdb; - return user_regset_copyout(&pos, &count, &kbuf, &ubuf, data, 0, 256); -} - -static int s390_tdb_set(struct task_struct *target, - const struct user_regset *regset, - unsigned int pos, unsigned int count, - const void *kbuf, const void __user *ubuf) -{ - return 0; -} - #endif static int s390_system_call_get(struct task_struct *target, @@ -1005,14 +946,6 @@ static const struct user_regset s390_regsets[] = { .get = s390_last_break_get, .set = s390_last_break_set, }, - [REGSET_TDB] = { - .core_note_type = NT_S390_TDB, - .n = 1, - .size = 256, - .align = 1, - .get = s390_tdb_get, - .set = s390_tdb_set, - }, #endif [REGSET_SYSTEM_CALL] = { .core_note_type = NT_S390_SYSTEM_CALL, @@ -1210,14 +1143,6 @@ static const struct user_regset s390_compat_regsets[] = { .get = s390_compat_last_break_get, .set = s390_compat_last_break_set, }, - [REGSET_TDB] = { - .core_note_type = NT_S390_TDB, - .n = 1, - .size = 256, - .align = 1, - .get = s390_tdb_get, - .set = s390_tdb_set, - }, [REGSET_SYSTEM_CALL] = { .core_note_type = NT_S390_SYSTEM_CALL, .n = 1, diff --git a/trunk/arch/s390/kernel/runtime_instr.c b/trunk/arch/s390/kernel/runtime_instr.c deleted file mode 100644 index 61066f6f71a5..000000000000 --- a/trunk/arch/s390/kernel/runtime_instr.c +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Copyright IBM Corp. 2012 - * Author(s): Jan Glauber - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* empty control block to disable RI by loading it */ -struct runtime_instr_cb runtime_instr_empty_cb; - -static int runtime_instr_avail(void) -{ - return test_facility(64); -} - -static void disable_runtime_instr(void) -{ - struct pt_regs *regs = task_pt_regs(current); - - load_runtime_instr_cb(&runtime_instr_empty_cb); - - /* - * Make sure the RI bit is deleted from the PSW. If the user did not - * switch off RI before the system call the process will get a - * specification exception otherwise. - */ - regs->psw.mask &= ~PSW_MASK_RI; -} - -static void init_runtime_instr_cb(struct runtime_instr_cb *cb) -{ - cb->buf_limit = 0xfff; - if (s390_user_mode == HOME_SPACE_MODE) - cb->home_space = 1; - cb->int_requested = 1; - cb->pstate = 1; - cb->pstate_set_buf = 1; - cb->pstate_sample = 1; - cb->pstate_collect = 1; - cb->key = PAGE_DEFAULT_KEY; - cb->valid = 1; -} - -void exit_thread_runtime_instr(void) -{ - struct task_struct *task = current; - - if (!task->thread.ri_cb) - return; - disable_runtime_instr(); - kfree(task->thread.ri_cb); - task->thread.ri_signum = 0; - task->thread.ri_cb = NULL; -} - -static void runtime_instr_int_handler(struct ext_code ext_code, - unsigned int param32, unsigned long param64) -{ - struct siginfo info; - - if (!(param32 & CPU_MF_INT_RI_MASK)) - return; - - kstat_cpu(smp_processor_id()).irqs[EXTINT_CMR]++; - - if (!current->thread.ri_cb) - return; - if (current->thread.ri_signum < SIGRTMIN || - current->thread.ri_signum > SIGRTMAX) { - WARN_ON_ONCE(1); - return; - } - - memset(&info, 0, sizeof(info)); - info.si_signo = current->thread.ri_signum; - info.si_code = SI_QUEUE; - if (param32 & CPU_MF_INT_RI_BUF_FULL) - info.si_int = ENOBUFS; - else if (param32 & CPU_MF_INT_RI_HALTED) - info.si_int = ECANCELED; - else - return; /* unknown reason */ - - send_sig_info(current->thread.ri_signum, &info, current); -} - -SYSCALL_DEFINE2(s390_runtime_instr, int, command, int, signum) -{ - struct runtime_instr_cb *cb; - - if (!runtime_instr_avail()) - return -EOPNOTSUPP; - - if (command == S390_RUNTIME_INSTR_STOP) { - preempt_disable(); - exit_thread_runtime_instr(); - preempt_enable(); - return 0; - } - - if (command != S390_RUNTIME_INSTR_START || - (signum < SIGRTMIN || signum > SIGRTMAX)) - return -EINVAL; - - if (!current->thread.ri_cb) { - cb = kzalloc(sizeof(*cb), GFP_KERNEL); - if (!cb) - return -ENOMEM; - } else { - cb = current->thread.ri_cb; - memset(cb, 0, sizeof(*cb)); - } - - init_runtime_instr_cb(cb); - current->thread.ri_signum = signum; - - /* now load the control block to make it available */ - preempt_disable(); - current->thread.ri_cb = cb; - load_runtime_instr_cb(cb); - preempt_enable(); - return 0; -} - -static int __init runtime_instr_init(void) -{ - int rc; - - if (!runtime_instr_avail()) - return 0; - - measurement_alert_subclass_register(); - rc = register_external_interrupt(0x1407, runtime_instr_int_handler); - if (rc) - measurement_alert_subclass_unregister(); - else - pr_info("Runtime instrumentation facility initialized\n"); - return rc; -} -device_initcall(runtime_instr_init); diff --git a/trunk/arch/s390/kernel/s390_ksyms.c b/trunk/arch/s390/kernel/s390_ksyms.c index 9bdbcef1da9e..57b536649b00 100644 --- a/trunk/arch/s390/kernel/s390_ksyms.c +++ b/trunk/arch/s390/kernel/s390_ksyms.c @@ -8,5 +8,3 @@ EXPORT_SYMBOL(_mcount); #if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE) EXPORT_SYMBOL(sie64a); #endif -EXPORT_SYMBOL(memcpy); -EXPORT_SYMBOL(memset); diff --git a/trunk/arch/s390/kernel/setup.c b/trunk/arch/s390/kernel/setup.c index afa9fdba200e..f86c81e13c37 100644 --- a/trunk/arch/s390/kernel/setup.c +++ b/trunk/arch/s390/kernel/setup.c @@ -302,10 +302,10 @@ static int __init parse_vmalloc(char *arg) } early_param("vmalloc", parse_vmalloc); -unsigned int s390_user_mode = PRIMARY_SPACE_MODE; -EXPORT_SYMBOL_GPL(s390_user_mode); +unsigned int addressing_mode = HOME_SPACE_MODE; +EXPORT_SYMBOL_GPL(addressing_mode); -static void __init set_user_mode_primary(void) +static int set_amode_primary(void) { psw_kernel_bits = (psw_kernel_bits & ~PSW_MASK_ASC) | PSW_ASC_HOME; psw_user_bits = (psw_user_bits & ~PSW_MASK_ASC) | PSW_ASC_PRIMARY; @@ -313,30 +313,48 @@ static void __init set_user_mode_primary(void) psw32_user_bits = (psw32_user_bits & ~PSW32_MASK_ASC) | PSW32_ASC_PRIMARY; #endif - uaccess = MACHINE_HAS_MVCOS ? uaccess_mvcos_switch : uaccess_pt; + + if (MACHINE_HAS_MVCOS) { + memcpy(&uaccess, &uaccess_mvcos_switch, sizeof(uaccess)); + return 1; + } else { + memcpy(&uaccess, &uaccess_pt, sizeof(uaccess)); + return 0; + } +} + +/* + * Switch kernel/user addressing modes? + */ +static int __init early_parse_switch_amode(char *p) +{ + addressing_mode = PRIMARY_SPACE_MODE; + return 0; } +early_param("switch_amode", early_parse_switch_amode); static int __init early_parse_user_mode(char *p) { if (p && strcmp(p, "primary") == 0) - s390_user_mode = PRIMARY_SPACE_MODE; + addressing_mode = PRIMARY_SPACE_MODE; else if (!p || strcmp(p, "home") == 0) - s390_user_mode = HOME_SPACE_MODE; + addressing_mode = HOME_SPACE_MODE; else return 1; return 0; } early_param("user_mode", early_parse_user_mode); -static void __init setup_addressing_mode(void) +static void setup_addressing_mode(void) { - if (s390_user_mode != PRIMARY_SPACE_MODE) - return; - set_user_mode_primary(); - if (MACHINE_HAS_MVCOS) - pr_info("Address spaces switched, mvcos available\n"); - else - pr_info("Address spaces switched, mvcos not available\n"); + if (addressing_mode == PRIMARY_SPACE_MODE) { + if (set_amode_primary()) + pr_info("Address spaces switched, " + "mvcos available\n"); + else + pr_info("Address spaces switched, " + "mvcos not available\n"); + } } void *restart_stack __attribute__((__section__(".data"))); @@ -584,7 +602,9 @@ static void __init setup_memory_end(void) static void __init setup_vmcoreinfo(void) { +#ifdef CONFIG_KEXEC mem_assign_absolute(S390_lowcore.vmcore_info, paddr_vmcoreinfo_note()); +#endif } #ifdef CONFIG_CRASH_DUMP @@ -954,20 +974,12 @@ static void __init setup_hwcaps(void) if (MACHINE_HAS_HPAGE) elf_hwcap |= HWCAP_S390_HPAGE; -#if defined(CONFIG_64BIT) /* * 64-bit register support for 31-bit processes * HWCAP_S390_HIGH_GPRS is bit 9. */ elf_hwcap |= HWCAP_S390_HIGH_GPRS; - /* - * Transactional execution support HWCAP_S390_TE is bit 10. - */ - if (test_facility(50) && test_facility(73)) - elf_hwcap |= HWCAP_S390_TE; -#endif - get_cpu_id(&cpu_id); switch (cpu_id.machine) { case 0x9672: diff --git a/trunk/arch/s390/kernel/smp.c b/trunk/arch/s390/kernel/smp.c index ea431e551c6b..720fda1620f2 100644 --- a/trunk/arch/s390/kernel/smp.c +++ b/trunk/arch/s390/kernel/smp.c @@ -66,7 +66,7 @@ struct pcpu { unsigned long panic_stack; /* panic stack for the cpu */ unsigned long ec_mask; /* bit mask for ec_xxx functions */ int state; /* physical cpu state */ - int polarization; /* physical polarization */ + u32 status; /* last status received via sigp */ u16 address; /* physical cpu address */ }; @@ -74,10 +74,6 @@ static u8 boot_cpu_type; static u16 boot_cpu_address; static struct pcpu pcpu_devices[NR_CPUS]; -/* - * The smp_cpu_state_mutex must be held when changing the state or polarization - * member of a pcpu data structure within the pcpu_devices arreay. - */ DEFINE_MUTEX(smp_cpu_state_mutex); /* @@ -103,7 +99,7 @@ static inline int __pcpu_sigp_relax(u16 addr, u8 order, u32 parm, u32 *status) int cc; while (1) { - cc = __pcpu_sigp(addr, order, parm, NULL); + cc = __pcpu_sigp(addr, order, parm, status); if (cc != SIGP_CC_BUSY) return cc; cpu_relax(); @@ -115,7 +111,7 @@ static int pcpu_sigp_retry(struct pcpu *pcpu, u8 order, u32 parm) int cc, retry; for (retry = 0; ; retry++) { - cc = __pcpu_sigp(pcpu->address, order, parm, NULL); + cc = __pcpu_sigp(pcpu->address, order, parm, &pcpu->status); if (cc != SIGP_CC_BUSY) break; if (retry >= 3) @@ -126,18 +122,16 @@ static int pcpu_sigp_retry(struct pcpu *pcpu, u8 order, u32 parm) static inline int pcpu_stopped(struct pcpu *pcpu) { - u32 uninitialized_var(status); - if (__pcpu_sigp(pcpu->address, SIGP_SENSE, - 0, &status) != SIGP_CC_STATUS_STORED) + 0, &pcpu->status) != SIGP_CC_STATUS_STORED) return 0; - return !!(status & (SIGP_STATUS_CHECK_STOP|SIGP_STATUS_STOPPED)); + return !!(pcpu->status & (SIGP_STATUS_CHECK_STOP|SIGP_STATUS_STOPPED)); } static inline int pcpu_running(struct pcpu *pcpu) { if (__pcpu_sigp(pcpu->address, SIGP_SENSE_RUNNING, - 0, NULL) != SIGP_CC_STATUS_STORED) + 0, &pcpu->status) != SIGP_CC_STATUS_STORED) return 1; /* Status stored condition code is equivalent to cpu not running. */ return 0; @@ -592,16 +586,6 @@ static inline void smp_get_save_area(int cpu, u16 address) { } #endif /* CONFIG_ZFCPDUMP || CONFIG_CRASH_DUMP */ -void smp_cpu_set_polarization(int cpu, int val) -{ - pcpu_devices[cpu].polarization = val; -} - -int smp_cpu_get_polarization(int cpu) -{ - return pcpu_devices[cpu].polarization; -} - static struct sclp_cpu_info *smp_get_cpu_info(void) { static int use_sigp_detection; @@ -644,7 +628,7 @@ static int __devinit __smp_rescan_cpus(struct sclp_cpu_info *info, pcpu->address = info->cpu[i].address; pcpu->state = (cpu >= info->configured) ? CPU_STATE_STANDBY : CPU_STATE_CONFIGURED; - smp_cpu_set_polarization(cpu, POLARIZATION_UNKNOWN); + cpu_set_polarization(cpu, POLARIZATION_UNKNOWN); set_cpu_present(cpu, true); if (sysfs_add && smp_add_present_cpu(cpu) != 0) set_cpu_present(cpu, false); @@ -812,7 +796,7 @@ void __init smp_prepare_boot_cpu(void) pcpu->async_stack = S390_lowcore.async_stack - ASYNC_SIZE; pcpu->panic_stack = S390_lowcore.panic_stack - PAGE_SIZE; S390_lowcore.percpu_offset = __per_cpu_offset[0]; - smp_cpu_set_polarization(0, POLARIZATION_UNKNOWN); + cpu_set_polarization(0, POLARIZATION_UNKNOWN); set_cpu_present(0, true); set_cpu_online(0, true); } @@ -878,7 +862,7 @@ static ssize_t cpu_configure_store(struct device *dev, if (rc) break; pcpu->state = CPU_STATE_STANDBY; - smp_cpu_set_polarization(cpu, POLARIZATION_UNKNOWN); + cpu_set_polarization(cpu, POLARIZATION_UNKNOWN); topology_expect_change(); break; case 1: @@ -888,7 +872,7 @@ static ssize_t cpu_configure_store(struct device *dev, if (rc) break; pcpu->state = CPU_STATE_CONFIGURED; - smp_cpu_set_polarization(cpu, POLARIZATION_UNKNOWN); + cpu_set_polarization(cpu, POLARIZATION_UNKNOWN); topology_expect_change(); break; default: @@ -975,17 +959,23 @@ static int __cpuinit smp_cpu_notify(struct notifier_block *self, struct device *s = &c->dev; int err = 0; - switch (action & ~CPU_TASKS_FROZEN) { + switch (action) { case CPU_ONLINE: + case CPU_ONLINE_FROZEN: err = sysfs_create_group(&s->kobj, &cpu_online_attr_group); break; case CPU_DEAD: + case CPU_DEAD_FROZEN: sysfs_remove_group(&s->kobj, &cpu_online_attr_group); break; } return notifier_from_errno(err); } +static struct notifier_block __cpuinitdata smp_cpu_nb = { + .notifier_call = smp_cpu_notify, +}; + static int __devinit smp_add_present_cpu(int cpu) { struct cpu *c = &pcpu_devices[cpu].cpu; @@ -1060,7 +1050,7 @@ static int __init s390_smp_init(void) { int cpu, rc; - hotcpu_notifier(smp_cpu_notify, 0); + register_cpu_notifier(&smp_cpu_nb); #ifdef CONFIG_HOTPLUG_CPU rc = device_create_file(cpu_subsys.dev_root, &dev_attr_rescan); if (rc) diff --git a/trunk/arch/s390/kernel/sys_s390.c b/trunk/arch/s390/kernel/sys_s390.c index d0964d22adb5..b4a29eee41b8 100644 --- a/trunk/arch/s390/kernel/sys_s390.c +++ b/trunk/arch/s390/kernel/sys_s390.c @@ -81,12 +81,11 @@ SYSCALL_DEFINE1(s390_personality, unsigned int, personality) { unsigned int ret; - if (personality(current->personality) == PER_LINUX32 && - personality(personality) == PER_LINUX) - personality |= PER_LINUX32; + if (current->personality == PER_LINUX32 && personality == PER_LINUX) + personality = PER_LINUX32; ret = sys_personality(personality); - if (personality(ret) == PER_LINUX32) - ret &= ~PER_LINUX32; + if (ret == PER_LINUX32) + ret = PER_LINUX; return ret; } diff --git a/trunk/arch/s390/kernel/syscalls.S b/trunk/arch/s390/kernel/syscalls.S index 48174850f3b0..bcab2f04ba58 100644 --- a/trunk/arch/s390/kernel/syscalls.S +++ b/trunk/arch/s390/kernel/syscalls.S @@ -350,5 +350,3 @@ SYSCALL(sys_syncfs,sys_syncfs,sys_syncfs_wrapper) SYSCALL(sys_setns,sys_setns,sys_setns_wrapper) SYSCALL(sys_process_vm_readv,sys_process_vm_readv,compat_sys_process_vm_readv_wrapper) /* 340 */ SYSCALL(sys_process_vm_writev,sys_process_vm_writev,compat_sys_process_vm_writev_wrapper) -SYSCALL(sys_ni_syscall,sys_s390_runtime_instr,sys_s390_runtime_instr_wrapper) -SYSCALL(sys_kcmp,sys_kcmp,sys_kcmp_wrapper) diff --git a/trunk/arch/s390/kernel/sysinfo.c b/trunk/arch/s390/kernel/sysinfo.c index 62f89d98e880..fa0eb238dac7 100644 --- a/trunk/arch/s390/kernel/sysinfo.c +++ b/trunk/arch/s390/kernel/sysinfo.c @@ -22,41 +22,17 @@ #include #include -int topology_max_mnest; - -/* - * stsi - store system information - * - * Returns the current configuration level if function code 0 was specified. - * Otherwise returns 0 on success or a negative value on error. - */ -int stsi(void *sysinfo, int fc, int sel1, int sel2) +static inline int stsi_0(void) { - register int r0 asm("0") = (fc << 28) | sel1; - register int r1 asm("1") = sel2; - int rc = 0; - - asm volatile( - " stsi 0(%3)\n" - "0: jz 2f\n" - "1: lhi %1,%4\n" - "2:\n" - EX_TABLE(0b, 1b) - : "+d" (r0), "+d" (rc) - : "d" (r1), "a" (sysinfo), "K" (-EOPNOTSUPP) - : "cc", "memory"); - if (rc) - return rc; - return fc ? 0 : ((unsigned int) r0) >> 28; + int rc = stsi(NULL, 0, 0, 0); + return rc == -ENOSYS ? rc : (((unsigned int) rc) >> 28); } -EXPORT_SYMBOL(stsi); -static void stsi_1_1_1(struct seq_file *m, struct sysinfo_1_1_1 *info) +static int stsi_1_1_1(struct sysinfo_1_1_1 *info, char *page, int len) { - int i; + if (stsi(info, 1, 1, 1) == -ENOSYS) + return len; - if (stsi(info, 1, 1, 1)) - return; EBCASC(info->manufacturer, sizeof(info->manufacturer)); EBCASC(info->type, sizeof(info->type)); EBCASC(info->model, sizeof(info->model)); @@ -65,197 +41,242 @@ static void stsi_1_1_1(struct seq_file *m, struct sysinfo_1_1_1 *info) EBCASC(info->model_capacity, sizeof(info->model_capacity)); EBCASC(info->model_perm_cap, sizeof(info->model_perm_cap)); EBCASC(info->model_temp_cap, sizeof(info->model_temp_cap)); - seq_printf(m, "Manufacturer: %-16.16s\n", info->manufacturer); - seq_printf(m, "Type: %-4.4s\n", info->type); - /* - * Sigh: the model field has been renamed with System z9 - * to model_capacity and a new model field has been added - * after the plant field. To avoid confusing older programs - * the "Model:" prints "model_capacity model" or just - * "model_capacity" if the model string is empty . - */ - seq_printf(m, "Model: %-16.16s", info->model_capacity); + len += sprintf(page + len, "Manufacturer: %-16.16s\n", + info->manufacturer); + len += sprintf(page + len, "Type: %-4.4s\n", + info->type); if (info->model[0] != '\0') - seq_printf(m, " %-16.16s", info->model); - seq_putc(m, '\n'); - seq_printf(m, "Sequence Code: %-16.16s\n", info->sequence); - seq_printf(m, "Plant: %-4.4s\n", info->plant); - seq_printf(m, "Model Capacity: %-16.16s %08u\n", - info->model_capacity, info->model_cap_rating); - if (info->model_perm_cap_rating) - seq_printf(m, "Model Perm. Capacity: %-16.16s %08u\n", - info->model_perm_cap, - info->model_perm_cap_rating); - if (info->model_temp_cap_rating) - seq_printf(m, "Model Temp. Capacity: %-16.16s %08u\n", - info->model_temp_cap, - info->model_temp_cap_rating); - if (info->ncr) - seq_printf(m, "Nominal Cap. Rating: %08u\n", info->ncr); - if (info->npr) - seq_printf(m, "Nominal Perm. Rating: %08u\n", info->npr); - if (info->ntr) - seq_printf(m, "Nominal Temp. Rating: %08u\n", info->ntr); + /* + * Sigh: the model field has been renamed with System z9 + * to model_capacity and a new model field has been added + * after the plant field. To avoid confusing older programs + * the "Model:" prints "model_capacity model" or just + * "model_capacity" if the model string is empty . + */ + len += sprintf(page + len, + "Model: %-16.16s %-16.16s\n", + info->model_capacity, info->model); + else + len += sprintf(page + len, "Model: %-16.16s\n", + info->model_capacity); + len += sprintf(page + len, "Sequence Code: %-16.16s\n", + info->sequence); + len += sprintf(page + len, "Plant: %-4.4s\n", + info->plant); + len += sprintf(page + len, "Model Capacity: %-16.16s %08u\n", + info->model_capacity, *(u32 *) info->model_cap_rating); + if (info->model_perm_cap[0] != '\0') + len += sprintf(page + len, + "Model Perm. Capacity: %-16.16s %08u\n", + info->model_perm_cap, + *(u32 *) info->model_perm_cap_rating); + if (info->model_temp_cap[0] != '\0') + len += sprintf(page + len, + "Model Temp. Capacity: %-16.16s %08u\n", + info->model_temp_cap, + *(u32 *) info->model_temp_cap_rating); if (info->cai) { - seq_printf(m, "Capacity Adj. Ind.: %d\n", info->cai); - seq_printf(m, "Capacity Ch. Reason: %d\n", info->ccr); - seq_printf(m, "Capacity Transient: %d\n", info->t); - } - if (info->p) { - for (i = 1; i <= ARRAY_SIZE(info->typepct); i++) { - seq_printf(m, "Type %d Percentage: %d\n", - i, info->typepct[i - 1]); - } + len += sprintf(page + len, + "Capacity Adj. Ind.: %d\n", + info->cai); + len += sprintf(page + len, "Capacity Ch. Reason: %d\n", + info->ccr); } + return len; } -static void stsi_15_1_x(struct seq_file *m, struct sysinfo_15_1_x *info) +static int stsi_15_1_x(struct sysinfo_15_1_x *info, char *page, int len) { static int max_mnest; int i, rc; - seq_putc(m, '\n'); + len += sprintf(page + len, "\n"); if (!MACHINE_HAS_TOPOLOGY) - return; - if (stsi(info, 15, 1, topology_max_mnest)) - return; - seq_printf(m, "CPU Topology HW: "); + return len; + if (max_mnest) { + stsi(info, 15, 1, max_mnest); + } else { + for (max_mnest = 6; max_mnest > 1; max_mnest--) { + rc = stsi(info, 15, 1, max_mnest); + if (rc != -ENOSYS) + break; + } + } + len += sprintf(page + len, "CPU Topology HW: "); for (i = 0; i < TOPOLOGY_NR_MAG; i++) - seq_printf(m, " %d", info->mag[i]); - seq_putc(m, '\n'); + len += sprintf(page + len, " %d", info->mag[i]); + len += sprintf(page + len, "\n"); #ifdef CONFIG_SCHED_MC store_topology(info); - seq_printf(m, "CPU Topology SW: "); + len += sprintf(page + len, "CPU Topology SW: "); for (i = 0; i < TOPOLOGY_NR_MAG; i++) - seq_printf(m, " %d", info->mag[i]); - seq_putc(m, '\n'); + len += sprintf(page + len, " %d", info->mag[i]); + len += sprintf(page + len, "\n"); #endif + return len; } -static void stsi_1_2_2(struct seq_file *m, struct sysinfo_1_2_2 *info) +static int stsi_1_2_2(struct sysinfo_1_2_2 *info, char *page, int len) { struct sysinfo_1_2_2_extension *ext; int i; - if (stsi(info, 1, 2, 2)) - return; + if (stsi(info, 1, 2, 2) == -ENOSYS) + return len; ext = (struct sysinfo_1_2_2_extension *) ((unsigned long) info + info->acc_offset); - seq_printf(m, "CPUs Total: %d\n", info->cpus_total); - seq_printf(m, "CPUs Configured: %d\n", info->cpus_configured); - seq_printf(m, "CPUs Standby: %d\n", info->cpus_standby); - seq_printf(m, "CPUs Reserved: %d\n", info->cpus_reserved); - /* - * Sigh 2. According to the specification the alternate - * capability field is a 32 bit floating point number - * if the higher order 8 bits are not zero. Printing - * a floating point number in the kernel is a no-no, - * always print the number as 32 bit unsigned integer. - * The user-space needs to know about the strange - * encoding of the alternate cpu capability. - */ - seq_printf(m, "Capability: %u", info->capability); - if (info->format == 1) - seq_printf(m, " %u", ext->alt_capability); - seq_putc(m, '\n'); - if (info->nominal_cap) - seq_printf(m, "Nominal Capability: %d\n", info->nominal_cap); - if (info->secondary_cap) - seq_printf(m, "Secondary Capability: %d\n", info->secondary_cap); - for (i = 2; i <= info->cpus_total; i++) { - seq_printf(m, "Adjustment %02d-way: %u", - i, info->adjustment[i-2]); - if (info->format == 1) - seq_printf(m, " %u", ext->alt_adjustment[i-2]); - seq_putc(m, '\n'); + + len += sprintf(page + len, "CPUs Total: %d\n", + info->cpus_total); + len += sprintf(page + len, "CPUs Configured: %d\n", + info->cpus_configured); + len += sprintf(page + len, "CPUs Standby: %d\n", + info->cpus_standby); + len += sprintf(page + len, "CPUs Reserved: %d\n", + info->cpus_reserved); + + if (info->format == 1) { + /* + * Sigh 2. According to the specification the alternate + * capability field is a 32 bit floating point number + * if the higher order 8 bits are not zero. Printing + * a floating point number in the kernel is a no-no, + * always print the number as 32 bit unsigned integer. + * The user-space needs to know about the strange + * encoding of the alternate cpu capability. + */ + len += sprintf(page + len, "Capability: %u %u\n", + info->capability, ext->alt_capability); + for (i = 2; i <= info->cpus_total; i++) + len += sprintf(page + len, + "Adjustment %02d-way: %u %u\n", + i, info->adjustment[i-2], + ext->alt_adjustment[i-2]); + + } else { + len += sprintf(page + len, "Capability: %u\n", + info->capability); + for (i = 2; i <= info->cpus_total; i++) + len += sprintf(page + len, + "Adjustment %02d-way: %u\n", + i, info->adjustment[i-2]); } + + if (info->secondary_capability != 0) + len += sprintf(page + len, "Secondary Capability: %d\n", + info->secondary_capability); + return len; } -static void stsi_2_2_2(struct seq_file *m, struct sysinfo_2_2_2 *info) +static int stsi_2_2_2(struct sysinfo_2_2_2 *info, char *page, int len) { - if (stsi(info, 2, 2, 2)) - return; + if (stsi(info, 2, 2, 2) == -ENOSYS) + return len; + EBCASC(info->name, sizeof(info->name)); - seq_putc(m, '\n'); - seq_printf(m, "LPAR Number: %d\n", info->lpar_number); - seq_printf(m, "LPAR Characteristics: "); + + len += sprintf(page + len, "\n"); + len += sprintf(page + len, "LPAR Number: %d\n", + info->lpar_number); + + len += sprintf(page + len, "LPAR Characteristics: "); if (info->characteristics & LPAR_CHAR_DEDICATED) - seq_printf(m, "Dedicated "); + len += sprintf(page + len, "Dedicated "); if (info->characteristics & LPAR_CHAR_SHARED) - seq_printf(m, "Shared "); + len += sprintf(page + len, "Shared "); if (info->characteristics & LPAR_CHAR_LIMITED) - seq_printf(m, "Limited "); - seq_putc(m, '\n'); - seq_printf(m, "LPAR Name: %-8.8s\n", info->name); - seq_printf(m, "LPAR Adjustment: %d\n", info->caf); - seq_printf(m, "LPAR CPUs Total: %d\n", info->cpus_total); - seq_printf(m, "LPAR CPUs Configured: %d\n", info->cpus_configured); - seq_printf(m, "LPAR CPUs Standby: %d\n", info->cpus_standby); - seq_printf(m, "LPAR CPUs Reserved: %d\n", info->cpus_reserved); - seq_printf(m, "LPAR CPUs Dedicated: %d\n", info->cpus_dedicated); - seq_printf(m, "LPAR CPUs Shared: %d\n", info->cpus_shared); + len += sprintf(page + len, "Limited "); + len += sprintf(page + len, "\n"); + + len += sprintf(page + len, "LPAR Name: %-8.8s\n", + info->name); + + len += sprintf(page + len, "LPAR Adjustment: %d\n", + info->caf); + + len += sprintf(page + len, "LPAR CPUs Total: %d\n", + info->cpus_total); + len += sprintf(page + len, "LPAR CPUs Configured: %d\n", + info->cpus_configured); + len += sprintf(page + len, "LPAR CPUs Standby: %d\n", + info->cpus_standby); + len += sprintf(page + len, "LPAR CPUs Reserved: %d\n", + info->cpus_reserved); + len += sprintf(page + len, "LPAR CPUs Dedicated: %d\n", + info->cpus_dedicated); + len += sprintf(page + len, "LPAR CPUs Shared: %d\n", + info->cpus_shared); + return len; } -static void stsi_3_2_2(struct seq_file *m, struct sysinfo_3_2_2 *info) +static int stsi_3_2_2(struct sysinfo_3_2_2 *info, char *page, int len) { int i; - if (stsi(info, 3, 2, 2)) - return; + if (stsi(info, 3, 2, 2) == -ENOSYS) + return len; for (i = 0; i < info->count; i++) { EBCASC(info->vm[i].name, sizeof(info->vm[i].name)); EBCASC(info->vm[i].cpi, sizeof(info->vm[i].cpi)); - seq_putc(m, '\n'); - seq_printf(m, "VM%02d Name: %-8.8s\n", i, info->vm[i].name); - seq_printf(m, "VM%02d Control Program: %-16.16s\n", i, info->vm[i].cpi); - seq_printf(m, "VM%02d Adjustment: %d\n", i, info->vm[i].caf); - seq_printf(m, "VM%02d CPUs Total: %d\n", i, info->vm[i].cpus_total); - seq_printf(m, "VM%02d CPUs Configured: %d\n", i, info->vm[i].cpus_configured); - seq_printf(m, "VM%02d CPUs Standby: %d\n", i, info->vm[i].cpus_standby); - seq_printf(m, "VM%02d CPUs Reserved: %d\n", i, info->vm[i].cpus_reserved); + len += sprintf(page + len, "\n"); + len += sprintf(page + len, "VM%02d Name: %-8.8s\n", + i, info->vm[i].name); + len += sprintf(page + len, "VM%02d Control Program: %-16.16s\n", + i, info->vm[i].cpi); + + len += sprintf(page + len, "VM%02d Adjustment: %d\n", + i, info->vm[i].caf); + + len += sprintf(page + len, "VM%02d CPUs Total: %d\n", + i, info->vm[i].cpus_total); + len += sprintf(page + len, "VM%02d CPUs Configured: %d\n", + i, info->vm[i].cpus_configured); + len += sprintf(page + len, "VM%02d CPUs Standby: %d\n", + i, info->vm[i].cpus_standby); + len += sprintf(page + len, "VM%02d CPUs Reserved: %d\n", + i, info->vm[i].cpus_reserved); } + return len; } -static int sysinfo_show(struct seq_file *m, void *v) +static int proc_read_sysinfo(char *page, char **start, + off_t off, int count, + int *eof, void *data) { - void *info = (void *)get_zeroed_page(GFP_KERNEL); - int level; + unsigned long info = get_zeroed_page(GFP_KERNEL); + int level, len; if (!info) return 0; - level = stsi(NULL, 0, 0, 0); + + len = 0; + level = stsi_0(); if (level >= 1) - stsi_1_1_1(m, info); + len = stsi_1_1_1((struct sysinfo_1_1_1 *) info, page, len); + if (level >= 1) - stsi_15_1_x(m, info); + len = stsi_15_1_x((struct sysinfo_15_1_x *) info, page, len); + if (level >= 1) - stsi_1_2_2(m, info); + len = stsi_1_2_2((struct sysinfo_1_2_2 *) info, page, len); + if (level >= 2) - stsi_2_2_2(m, info); + len = stsi_2_2_2((struct sysinfo_2_2_2 *) info, page, len); + if (level >= 3) - stsi_3_2_2(m, info); - free_page((unsigned long)info); - return 0; -} + len = stsi_3_2_2((struct sysinfo_3_2_2 *) info, page, len); -static int sysinfo_open(struct inode *inode, struct file *file) -{ - return single_open(file, sysinfo_show, NULL); + free_page(info); + return len; } -static const struct file_operations sysinfo_fops = { - .open = sysinfo_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -static int __init sysinfo_create_proc(void) +static __init int create_proc_sysinfo(void) { - proc_create("sysinfo", 0444, NULL, &sysinfo_fops); + create_proc_read_entry("sysinfo", 0444, NULL, + proc_read_sysinfo, NULL); return 0; } -device_initcall(sysinfo_create_proc); +device_initcall(create_proc_sysinfo); /* * Service levels interface. @@ -386,7 +407,7 @@ void s390_adjust_jiffies(void) if (!info) return; - if (stsi(info, 1, 2, 2) == 0) { + if (stsi(info, 1, 2, 2) != -ENOSYS) { /* * Major sigh. The cpu capability encoding is "special". * If the first 9 bits of info->capability are 0 then it diff --git a/trunk/arch/s390/kernel/time.c b/trunk/arch/s390/kernel/time.c index 2db1011b8b19..dcec960fc724 100644 --- a/trunk/arch/s390/kernel/time.c +++ b/trunk/arch/s390/kernel/time.c @@ -329,7 +329,7 @@ static unsigned long clock_sync_flags; * The synchronous get_clock function. It will write the current clock * value to the clock pointer and return 0 if the clock is in sync with * the external time source. If the clock mode is local it will return - * -EOPNOTSUPP and -EAGAIN if the clock is not in sync with the external + * -ENOSYS and -EAGAIN if the clock is not in sync with the external * reference. */ int get_sync_clock(unsigned long long *clock) @@ -347,7 +347,7 @@ int get_sync_clock(unsigned long long *clock) return 0; if (!test_bit(CLOCK_SYNC_HAS_ETR, &clock_sync_flags) && !test_bit(CLOCK_SYNC_HAS_STP, &clock_sync_flags)) - return -EOPNOTSUPP; + return -ENOSYS; if (!test_bit(CLOCK_SYNC_ETR, &clock_sync_flags) && !test_bit(CLOCK_SYNC_STP, &clock_sync_flags)) return -EACCES; diff --git a/trunk/arch/s390/kernel/topology.c b/trunk/arch/s390/kernel/topology.c index 54d93f4b6818..05151e06c388 100644 --- a/trunk/arch/s390/kernel/topology.c +++ b/trunk/arch/s390/kernel/topology.c @@ -17,7 +17,6 @@ #include #include #include -#include #define PTF_HORIZONTAL (0UL) #define PTF_VERTICAL (1UL) @@ -45,6 +44,9 @@ static struct mask_info book_info; cpumask_t cpu_book_map[NR_CPUS]; unsigned char cpu_book_id[NR_CPUS]; +/* smp_cpu_state_mutex must be held when accessing this array */ +int cpu_polarization[NR_CPUS]; + static cpumask_t cpu_group_map(struct mask_info *info, unsigned int cpu) { cpumask_t mask; @@ -73,7 +75,10 @@ static struct mask_info *add_cpus_to_mask(struct topology_cpu *tl_cpu, { unsigned int cpu; - for_each_set_bit(cpu, &tl_cpu->mask[0], TOPOLOGY_CPU_BITS) { + for (cpu = find_first_bit(&tl_cpu->mask[0], TOPOLOGY_CPU_BITS); + cpu < TOPOLOGY_CPU_BITS; + cpu = find_next_bit(&tl_cpu->mask[0], TOPOLOGY_CPU_BITS, cpu + 1)) + { unsigned int rcpu; int lcpu; @@ -89,7 +94,7 @@ static struct mask_info *add_cpus_to_mask(struct topology_cpu *tl_cpu, } else { cpu_core_id[lcpu] = core->id; } - smp_cpu_set_polarization(lcpu, tl_cpu->pp); + cpu_set_polarization(lcpu, tl_cpu->pp); } } return core; @@ -196,7 +201,7 @@ static void topology_update_polarization_simple(void) mutex_lock(&smp_cpu_state_mutex); for_each_possible_cpu(cpu) - smp_cpu_set_polarization(cpu, POLARIZATION_HRZ); + cpu_set_polarization(cpu, POLARIZATION_HRZ); mutex_unlock(&smp_cpu_state_mutex); } @@ -226,7 +231,7 @@ int topology_set_cpu_management(int fc) if (rc) return -EBUSY; for_each_possible_cpu(cpu) - smp_cpu_set_polarization(cpu, POLARIZATION_UNKNOWN); + cpu_set_polarization(cpu, POLARIZATION_UNKNOWN); return rc; } @@ -245,10 +250,12 @@ static void update_cpu_core_map(void) void store_topology(struct sysinfo_15_1_x *info) { - if (topology_max_mnest >= 3) - stsi(info, 15, 1, 3); - else - stsi(info, 15, 1, 2); + int rc; + + rc = stsi(info, 15, 1, 3); + if (rc != -ENOSYS) + return; + stsi(info, 15, 1, 2); } int arch_update_cpu_topology(void) @@ -408,7 +415,7 @@ static ssize_t cpu_polarization_show(struct device *dev, ssize_t count; mutex_lock(&smp_cpu_state_mutex); - switch (smp_cpu_get_polarization(cpu)) { + switch (cpu_read_polarization(cpu)) { case POLARIZATION_HRZ: count = sprintf(buf, "horizontal\n"); break; diff --git a/trunk/arch/s390/kernel/traps.c b/trunk/arch/s390/kernel/traps.c index 3d2b0fa37db0..01775c04a90e 100644 --- a/trunk/arch/s390/kernel/traps.c +++ b/trunk/arch/s390/kernel/traps.c @@ -57,23 +57,6 @@ static int kstack_depth_to_print = 12; static int kstack_depth_to_print = 20; #endif /* CONFIG_64BIT */ -static inline void __user *get_trap_ip(struct pt_regs *regs) -{ -#ifdef CONFIG_64BIT - unsigned long address; - - if (regs->int_code & 0x200) - address = *(unsigned long *)(current->thread.trap_tdb + 24); - else - address = regs->psw.addr; - return (void __user *) - ((address - (regs->int_code >> 16)) & PSW_ADDR_INSN); -#else - return (void __user *) - ((regs->psw.addr - (regs->int_code >> 16)) & PSW_ADDR_INSN); -#endif -} - /* * For show_trace we have tree different stack to consider: * - the panic stack which is used if the kernel stack has overflown @@ -231,6 +214,7 @@ void show_registers(struct pt_regs *regs) void show_regs(struct pt_regs *regs) { + print_modules(); printk("CPU: %d %s %s %.*s\n", task_thread_info(current)->cpu, print_tainted(), init_utsname()->release, @@ -270,7 +254,6 @@ void die(struct pt_regs *regs, const char *str) #endif printk("\n"); notify_die(DIE_OOPS, str, regs, 0, regs->int_code & 0xffff, SIGSEGV); - print_modules(); show_regs(regs); bust_spinlocks(0); add_taint(TAINT_DIE); @@ -302,6 +285,12 @@ int is_valid_bugaddr(unsigned long addr) return 1; } +static inline void __user *get_psw_address(struct pt_regs *regs) +{ + return (void __user *) + ((regs->psw.addr - (regs->int_code >> 16)) & PSW_ADDR_INSN); +} + static void __kprobes do_trap(struct pt_regs *regs, int si_signo, int si_code, char *str) { @@ -315,14 +304,14 @@ static void __kprobes do_trap(struct pt_regs *regs, info.si_signo = si_signo; info.si_errno = 0; info.si_code = si_code; - info.si_addr = get_trap_ip(regs); + info.si_addr = get_psw_address(regs); force_sig_info(si_signo, &info, current); report_user_fault(regs, si_signo); } else { const struct exception_table_entry *fixup; fixup = search_exception_tables(regs->psw.addr & PSW_ADDR_INSN); if (fixup) - regs->psw.addr = extable_fixup(fixup) | PSW_ADDR_AMODE; + regs->psw.addr = fixup->fixup | PSW_ADDR_AMODE; else { enum bug_trap_type btt; @@ -392,11 +381,6 @@ DO_ERROR_INFO(special_op_exception, SIGILL, ILL_ILLOPN, DO_ERROR_INFO(translation_exception, SIGILL, ILL_ILLOPN, "translation exception") -#ifdef CONFIG_64BIT -DO_ERROR_INFO(transaction_exception, SIGILL, ILL_ILLOPN, - "transaction constraint exception") -#endif - static inline void do_fp_trap(struct pt_regs *regs, int fpc) { int si_code = 0; @@ -424,7 +408,7 @@ static void __kprobes illegal_op(struct pt_regs *regs) __u16 __user *location; int signal = 0; - location = get_trap_ip(regs); + location = get_psw_address(regs); if (user_mode(regs)) { if (get_user(*((__u16 *) opcode), (__u16 __user *) location)) @@ -492,7 +476,7 @@ void specification_exception(struct pt_regs *regs) __u16 __user *location = NULL; int signal = 0; - location = (__u16 __user *) get_trap_ip(regs); + location = (__u16 __user *) get_psw_address(regs); if (user_mode(regs)) { get_user(*((__u16 *) opcode), location); @@ -541,7 +525,7 @@ static void data_exception(struct pt_regs *regs) __u16 __user *location; int signal = 0; - location = get_trap_ip(regs); + location = get_psw_address(regs); if (MACHINE_HAS_IEEE) asm volatile("stfpc %0" : "=m" (current->thread.fp_regs.fpc)); @@ -657,7 +641,6 @@ void __init trap_init(void) pgm_check_table[0x12] = &translation_exception; pgm_check_table[0x13] = &special_op_exception; #ifdef CONFIG_64BIT - pgm_check_table[0x18] = &transaction_exception; pgm_check_table[0x38] = &do_asce_exception; pgm_check_table[0x39] = &do_dat_exception; pgm_check_table[0x3A] = &do_dat_exception; diff --git a/trunk/arch/s390/kernel/vdso.c b/trunk/arch/s390/kernel/vdso.c index d7776281cb60..9a19ca367c17 100644 --- a/trunk/arch/s390/kernel/vdso.c +++ b/trunk/arch/s390/kernel/vdso.c @@ -85,7 +85,7 @@ struct vdso_data *vdso_data = &vdso_data_store.data; static void vdso_init_data(struct vdso_data *vd) { vd->ectg_available = - s390_user_mode != HOME_SPACE_MODE && test_facility(31); + addressing_mode != HOME_SPACE_MODE && test_facility(31); } #ifdef CONFIG_64BIT @@ -102,7 +102,7 @@ int vdso_alloc_per_cpu(struct _lowcore *lowcore) lowcore->vdso_per_cpu_data = __LC_PASTE; - if (s390_user_mode == HOME_SPACE_MODE || !vdso_enabled) + if (addressing_mode == HOME_SPACE_MODE || !vdso_enabled) return 0; segment_table = __get_free_pages(GFP_KERNEL, SEGMENT_ORDER); @@ -147,7 +147,7 @@ void vdso_free_per_cpu(struct _lowcore *lowcore) unsigned long segment_table, page_table, page_frame; u32 *psal, *aste; - if (s390_user_mode == HOME_SPACE_MODE || !vdso_enabled) + if (addressing_mode == HOME_SPACE_MODE || !vdso_enabled) return; psal = (u32 *)(addr_t) lowcore->paste[4]; @@ -165,7 +165,7 @@ static void vdso_init_cr5(void) { unsigned long cr5; - if (s390_user_mode == HOME_SPACE_MODE || !vdso_enabled) + if (addressing_mode == HOME_SPACE_MODE || !vdso_enabled) return; cr5 = offsetof(struct _lowcore, paste); __ctl_load(cr5, 5, 5); diff --git a/trunk/arch/s390/kernel/vtime.c b/trunk/arch/s390/kernel/vtime.c index 790334427895..4fc97b40a6e1 100644 --- a/trunk/arch/s390/kernel/vtime.c +++ b/trunk/arch/s390/kernel/vtime.c @@ -99,7 +99,7 @@ static int do_account_vtime(struct task_struct *tsk, int hardirq_offset) return virt_timer_forward(user + system); } -void vtime_task_switch(struct task_struct *prev) +void account_vtime(struct task_struct *prev, struct task_struct *next) { struct thread_info *ti; @@ -107,7 +107,7 @@ void vtime_task_switch(struct task_struct *prev) ti = task_thread_info(prev); ti->user_timer = S390_lowcore.user_timer; ti->system_timer = S390_lowcore.system_timer; - ti = task_thread_info(current); + ti = task_thread_info(next); S390_lowcore.user_timer = ti->user_timer; S390_lowcore.system_timer = ti->system_timer; } @@ -122,7 +122,7 @@ void account_process_tick(struct task_struct *tsk, int user_tick) * Update process times based on virtual cpu times stored by entry.S * to the lowcore fields user_timer, system_timer & steal_clock. */ -void vtime_account(struct task_struct *tsk) +void account_system_vtime(struct task_struct *tsk) { struct thread_info *ti = task_thread_info(tsk); u64 timer, system; @@ -138,7 +138,7 @@ void vtime_account(struct task_struct *tsk) virt_timer_forward(system); } -EXPORT_SYMBOL_GPL(vtime_account); +EXPORT_SYMBOL_GPL(account_system_vtime); void __kprobes vtime_stop_cpu(void) { @@ -378,8 +378,9 @@ static int __cpuinit s390_nohz_notify(struct notifier_block *self, long cpu = (long) hcpu; idle = &per_cpu(s390_idle, cpu); - switch (action & ~CPU_TASKS_FROZEN) { + switch (action) { case CPU_DYING: + case CPU_DYING_FROZEN: idle->nohz_delay = 0; default: break; diff --git a/trunk/arch/s390/kvm/Kconfig b/trunk/arch/s390/kvm/Kconfig index 9b04a32e5695..78eb9847008f 100644 --- a/trunk/arch/s390/kvm/Kconfig +++ b/trunk/arch/s390/kvm/Kconfig @@ -5,7 +5,7 @@ source "virt/kvm/Kconfig" menuconfig VIRTUALIZATION def_bool y - prompt "KVM" + prompt "Virtualization" ---help--- Say Y here to get to see options for using your Linux host to run other operating systems inside virtual machines (guests). diff --git a/trunk/arch/s390/kvm/priv.c b/trunk/arch/s390/kvm/priv.c index 310be61bead7..60da903d6f3e 100644 --- a/trunk/arch/s390/kvm/priv.c +++ b/trunk/arch/s390/kvm/priv.c @@ -211,7 +211,7 @@ static void handle_stsi_3_2_2(struct kvm_vcpu *vcpu, struct sysinfo_3_2_2 *mem) spin_unlock(&fi->lock); /* deal with other level 3 hypervisors */ - if (stsi(mem, 3, 2, 2)) + if (stsi(mem, 3, 2, 2) == -ENOSYS) mem->count = 0; if (mem->count < 8) mem->count++; @@ -259,7 +259,7 @@ static int handle_stsi(struct kvm_vcpu *vcpu) mem = get_zeroed_page(GFP_KERNEL); if (!mem) goto out_fail; - if (stsi((void *) mem, fc, sel1, sel2)) + if (stsi((void *) mem, fc, sel1, sel2) == -ENOSYS) goto out_mem; break; case 3: diff --git a/trunk/arch/s390/lib/Makefile b/trunk/arch/s390/lib/Makefile index 6ab0d0b5cec8..761ab8b56afc 100644 --- a/trunk/arch/s390/lib/Makefile +++ b/trunk/arch/s390/lib/Makefile @@ -4,7 +4,6 @@ lib-y += delay.o string.o uaccess_std.o uaccess_pt.o obj-y += usercopy.o -obj-$(CONFIG_32BIT) += div64.o qrnnd.o ucmpdi2.o mem32.o -obj-$(CONFIG_64BIT) += mem64.o +obj-$(CONFIG_32BIT) += div64.o qrnnd.o ucmpdi2.o lib-$(CONFIG_64BIT) += uaccess_mvcos.o lib-$(CONFIG_SMP) += spinlock.o diff --git a/trunk/arch/s390/lib/mem32.S b/trunk/arch/s390/lib/mem32.S deleted file mode 100644 index 14ca9244b615..000000000000 --- a/trunk/arch/s390/lib/mem32.S +++ /dev/null @@ -1,92 +0,0 @@ -/* - * String handling functions. - * - * Copyright IBM Corp. 2012 - */ - -#include - -/* - * memset implementation - * - * This code corresponds to the C construct below. We do distinguish - * between clearing (c == 0) and setting a memory array (c != 0) simply - * because nearly all memset invocations in the kernel clear memory and - * the xc instruction is preferred in such cases. - * - * void *memset(void *s, int c, size_t n) - * { - * if (likely(c == 0)) - * return __builtin_memset(s, 0, n); - * return __builtin_memset(s, c, n); - * } - */ -ENTRY(memset) - basr %r5,%r0 -.Lmemset_base: - ltr %r4,%r4 - bzr %r14 - ltr %r3,%r3 - jnz .Lmemset_fill - ahi %r4,-1 - lr %r3,%r4 - srl %r3,8 - ltr %r3,%r3 - lr %r1,%r2 - je .Lmemset_clear_rest -.Lmemset_clear_loop: - xc 0(256,%r1),0(%r1) - la %r1,256(%r1) - brct %r3,.Lmemset_clear_loop -.Lmemset_clear_rest: - ex %r4,.Lmemset_xc-.Lmemset_base(%r5) - br %r14 -.Lmemset_fill: - stc %r3,0(%r2) - chi %r4,1 - lr %r1,%r2 - ber %r14 - ahi %r4,-2 - lr %r3,%r4 - srl %r3,8 - ltr %r3,%r3 - je .Lmemset_fill_rest -.Lmemset_fill_loop: - mvc 1(256,%r1),0(%r1) - la %r1,256(%r1) - brct %r3,.Lmemset_fill_loop -.Lmemset_fill_rest: - ex %r4,.Lmemset_mvc-.Lmemset_base(%r5) - br %r14 -.Lmemset_xc: - xc 0(1,%r1),0(%r1) -.Lmemset_mvc: - mvc 1(1,%r1),0(%r1) - -/* - * memcpy implementation - * - * void *memcpy(void *dest, const void *src, size_t n) - */ -ENTRY(memcpy) - basr %r5,%r0 -.Lmemcpy_base: - ltr %r4,%r4 - bzr %r14 - ahi %r4,-1 - lr %r0,%r4 - srl %r0,8 - ltr %r0,%r0 - lr %r1,%r2 - jnz .Lmemcpy_loop -.Lmemcpy_rest: - ex %r4,.Lmemcpy_mvc-.Lmemcpy_base(%r5) - br %r14 -.Lmemcpy_loop: - mvc 0(256,%r1),0(%r3) - la %r1,256(%r1) - la %r3,256(%r3) - brct %r0,.Lmemcpy_loop - j .Lmemcpy_rest -.Lmemcpy_mvc: - mvc 0(1,%r1),0(%r3) diff --git a/trunk/arch/s390/lib/mem64.S b/trunk/arch/s390/lib/mem64.S deleted file mode 100644 index c6d553e85ab1..000000000000 --- a/trunk/arch/s390/lib/mem64.S +++ /dev/null @@ -1,88 +0,0 @@ -/* - * String handling functions. - * - * Copyright IBM Corp. 2012 - */ - -#include - -/* - * memset implementation - * - * This code corresponds to the C construct below. We do distinguish - * between clearing (c == 0) and setting a memory array (c != 0) simply - * because nearly all memset invocations in the kernel clear memory and - * the xc instruction is preferred in such cases. - * - * void *memset(void *s, int c, size_t n) - * { - * if (likely(c == 0)) - * return __builtin_memset(s, 0, n); - * return __builtin_memset(s, c, n); - * } - */ -ENTRY(memset) - ltgr %r4,%r4 - bzr %r14 - ltgr %r3,%r3 - jnz .Lmemset_fill - aghi %r4,-1 - srlg %r3,%r4,8 - ltgr %r3,%r3 - lgr %r1,%r2 - jz .Lmemset_clear_rest -.Lmemset_clear_loop: - xc 0(256,%r1),0(%r1) - la %r1,256(%r1) - brctg %r3,.Lmemset_clear_loop -.Lmemset_clear_rest: - larl %r3,.Lmemset_xc - ex %r4,0(%r3) - br %r14 -.Lmemset_fill: - stc %r3,0(%r2) - cghi %r4,1 - lgr %r1,%r2 - ber %r14 - aghi %r4,-2 - srlg %r3,%r4,8 - ltgr %r3,%r3 - jz .Lmemset_fill_rest -.Lmemset_fill_loop: - mvc 1(256,%r1),0(%r1) - la %r1,256(%r1) - brctg %r3,.Lmemset_fill_loop -.Lmemset_fill_rest: - larl %r3,.Lmemset_mvc - ex %r4,0(%r3) - br %r14 -.Lmemset_xc: - xc 0(1,%r1),0(%r1) -.Lmemset_mvc: - mvc 1(1,%r1),0(%r1) - -/* - * memcpy implementation - * - * void *memcpy(void *dest, const void *src, size_t n) - */ -ENTRY(memcpy) - ltgr %r4,%r4 - bzr %r14 - aghi %r4,-1 - srlg %r5,%r4,8 - ltgr %r5,%r5 - lgr %r1,%r2 - jnz .Lmemcpy_loop -.Lmemcpy_rest: - larl %r5,.Lmemcpy_mvc - ex %r4,0(%r5) - br %r14 -.Lmemcpy_loop: - mvc 0(256,%r1),0(%r3) - la %r1,256(%r1) - la %r3,256(%r3) - brctg %r5,.Lmemcpy_loop - j .Lmemcpy_rest -.Lmemcpy_mvc: - mvc 0(1,%r1),0(%r3) diff --git a/trunk/arch/s390/lib/string.c b/trunk/arch/s390/lib/string.c index b647d5ff0ad9..846ec64ab2c9 100644 --- a/trunk/arch/s390/lib/string.c +++ b/trunk/arch/s390/lib/string.c @@ -43,7 +43,11 @@ static inline char *__strnend(const char *s, size_t n) */ size_t strlen(const char *s) { +#if __GNUC__ < 4 return __strend(s) - s; +#else + return __builtin_strlen(s); +#endif } EXPORT_SYMBOL(strlen); @@ -69,6 +73,7 @@ EXPORT_SYMBOL(strnlen); */ char *strcpy(char *dest, const char *src) { +#if __GNUC__ < 4 register int r0 asm("0") = 0; char *ret = dest; @@ -77,6 +82,9 @@ char *strcpy(char *dest, const char *src) : "+&a" (dest), "+&a" (src) : "d" (r0) : "cc", "memory" ); return ret; +#else + return __builtin_strcpy(dest, src); +#endif } EXPORT_SYMBOL(strcpy); @@ -98,7 +106,7 @@ size_t strlcpy(char *dest, const char *src, size_t size) if (size) { size_t len = (ret >= size) ? size-1 : ret; dest[len] = '\0'; - memcpy(dest, src, len); + __builtin_memcpy(dest, src, len); } return ret; } @@ -116,8 +124,8 @@ EXPORT_SYMBOL(strlcpy); char *strncpy(char *dest, const char *src, size_t n) { size_t len = __strnend(src, n) - src; - memset(dest + len, 0, n - len); - memcpy(dest, src, len); + __builtin_memset(dest + len, 0, n - len); + __builtin_memcpy(dest, src, len); return dest; } EXPORT_SYMBOL(strncpy); @@ -163,7 +171,7 @@ size_t strlcat(char *dest, const char *src, size_t n) if (len >= n) len = n - 1; dest[len] = '\0'; - memcpy(dest, src, len); + __builtin_memcpy(dest, src, len); } return res; } @@ -186,7 +194,7 @@ char *strncat(char *dest, const char *src, size_t n) char *p = __strend(dest); p[len] = '\0'; - memcpy(p, src, len); + __builtin_memcpy(p, src, len); return dest; } EXPORT_SYMBOL(strncat); @@ -340,3 +348,41 @@ void *memscan(void *s, int c, size_t n) return (void *) ret; } EXPORT_SYMBOL(memscan); + +/** + * memcpy - Copy one area of memory to another + * @dest: Where to copy to + * @src: Where to copy from + * @n: The size of the area. + * + * returns a pointer to @dest + */ +void *memcpy(void *dest, const void *src, size_t n) +{ + return __builtin_memcpy(dest, src, n); +} +EXPORT_SYMBOL(memcpy); + +/** + * memset - Fill a region of memory with the given value + * @s: Pointer to the start of the area. + * @c: The byte to fill the area with + * @n: The size of the area. + * + * returns a pointer to @s + */ +void *memset(void *s, int c, size_t n) +{ + char *xs; + + if (c == 0) + return __builtin_memset(s, 0, n); + + xs = (char *) s; + if (n > 0) + do { + *xs++ = c; + } while (--n > 0); + return s; +} +EXPORT_SYMBOL(memset); diff --git a/trunk/arch/s390/lib/uaccess_pt.c b/trunk/arch/s390/lib/uaccess_pt.c index 2d37bb861faf..60ee2b883797 100644 --- a/trunk/arch/s390/lib/uaccess_pt.c +++ b/trunk/arch/s390/lib/uaccess_pt.c @@ -2,82 +2,69 @@ * User access functions based on page table walks for enhanced * system layout without hardware support. * - * Copyright IBM Corp. 2006, 2012 + * Copyright IBM Corp. 2006 * Author(s): Gerald Schaefer (gerald.schaefer@de.ibm.com) */ #include #include #include -#include #include #include #include "uaccess.h" - -/* - * Returns kernel address for user virtual address. If the returned address is - * >= -4095 (IS_ERR_VALUE(x) returns true), a fault has occured and the address - * contains the (negative) exception code. - */ -static __always_inline unsigned long follow_table(struct mm_struct *mm, - unsigned long addr, int write) +static inline pte_t *follow_table(struct mm_struct *mm, unsigned long addr) { pgd_t *pgd; pud_t *pud; pmd_t *pmd; - pte_t *ptep; pgd = pgd_offset(mm, addr); if (pgd_none(*pgd) || unlikely(pgd_bad(*pgd))) - return -0x3aUL; + return (pte_t *) 0x3a; pud = pud_offset(pgd, addr); if (pud_none(*pud) || unlikely(pud_bad(*pud))) - return -0x3bUL; + return (pte_t *) 0x3b; pmd = pmd_offset(pud, addr); - if (pmd_none(*pmd)) - return -0x10UL; - if (pmd_huge(*pmd)) { - if (write && (pmd_val(*pmd) & _SEGMENT_ENTRY_RO)) - return -0x04UL; - return (pmd_val(*pmd) & HPAGE_MASK) + (addr & ~HPAGE_MASK); - } - if (unlikely(pmd_bad(*pmd))) - return -0x10UL; - - ptep = pte_offset_map(pmd, addr); - if (!pte_present(*ptep)) - return -0x11UL; - if (write && !pte_write(*ptep)) - return -0x04UL; + if (pmd_none(*pmd) || unlikely(pmd_bad(*pmd))) + return (pte_t *) 0x10; - return (pte_val(*ptep) & PAGE_MASK) + (addr & ~PAGE_MASK); + return pte_offset_map(pmd, addr); } static __always_inline size_t __user_copy_pt(unsigned long uaddr, void *kptr, size_t n, int write_user) { struct mm_struct *mm = current->mm; - unsigned long offset, done, size, kaddr; + unsigned long offset, pfn, done, size; + pte_t *pte; void *from, *to; done = 0; retry: spin_lock(&mm->page_table_lock); do { - kaddr = follow_table(mm, uaddr, write_user); - if (IS_ERR_VALUE(kaddr)) + pte = follow_table(mm, uaddr); + if ((unsigned long) pte < 0x1000) goto fault; + if (!pte_present(*pte)) { + pte = (pte_t *) 0x11; + goto fault; + } else if (write_user && !pte_write(*pte)) { + pte = (pte_t *) 0x04; + goto fault; + } - offset = uaddr & ~PAGE_MASK; + pfn = pte_pfn(*pte); + offset = uaddr & (PAGE_SIZE - 1); size = min(n - done, PAGE_SIZE - offset); if (write_user) { - to = (void *) kaddr; + to = (void *)((pfn << PAGE_SHIFT) + offset); from = kptr + done; } else { - from = (void *) kaddr; + from = (void *)((pfn << PAGE_SHIFT) + offset); to = kptr + done; } memcpy(to, from, size); @@ -88,7 +75,7 @@ static __always_inline size_t __user_copy_pt(unsigned long uaddr, void *kptr, return n - done; fault: spin_unlock(&mm->page_table_lock); - if (__handle_fault(uaddr, -kaddr, write_user)) + if (__handle_fault(uaddr, (unsigned long) pte, write_user)) return n - done; goto retry; } @@ -97,22 +84,27 @@ static __always_inline size_t __user_copy_pt(unsigned long uaddr, void *kptr, * Do DAT for user address by page table walk, return kernel address. * This function needs to be called with current->mm->page_table_lock held. */ -static __always_inline unsigned long __dat_user_addr(unsigned long uaddr, - int write) +static __always_inline unsigned long __dat_user_addr(unsigned long uaddr) { struct mm_struct *mm = current->mm; - unsigned long kaddr; + unsigned long pfn; + pte_t *pte; int rc; retry: - kaddr = follow_table(mm, uaddr, write); - if (IS_ERR_VALUE(kaddr)) + pte = follow_table(mm, uaddr); + if ((unsigned long) pte < 0x1000) + goto fault; + if (!pte_present(*pte)) { + pte = (pte_t *) 0x11; goto fault; + } - return kaddr; + pfn = pte_pfn(*pte); + return (pfn << PAGE_SHIFT) + (uaddr & (PAGE_SIZE - 1)); fault: spin_unlock(&mm->page_table_lock); - rc = __handle_fault(uaddr, -kaddr, write); + rc = __handle_fault(uaddr, (unsigned long) pte, 0); spin_lock(&mm->page_table_lock); if (!rc) goto retry; @@ -167,9 +159,11 @@ static size_t clear_user_pt(size_t n, void __user *to) static size_t strnlen_user_pt(size_t count, const char __user *src) { + char *addr; unsigned long uaddr = (unsigned long) src; struct mm_struct *mm = current->mm; - unsigned long offset, done, len, kaddr; + unsigned long offset, pfn, done, len; + pte_t *pte; size_t len_str; if (segment_eq(get_fs(), KERNEL_DS)) @@ -178,13 +172,19 @@ static size_t strnlen_user_pt(size_t count, const char __user *src) retry: spin_lock(&mm->page_table_lock); do { - kaddr = follow_table(mm, uaddr, 0); - if (IS_ERR_VALUE(kaddr)) + pte = follow_table(mm, uaddr); + if ((unsigned long) pte < 0x1000) + goto fault; + if (!pte_present(*pte)) { + pte = (pte_t *) 0x11; goto fault; + } - offset = uaddr & ~PAGE_MASK; + pfn = pte_pfn(*pte); + offset = uaddr & (PAGE_SIZE-1); + addr = (char *)(pfn << PAGE_SHIFT) + offset; len = min(count - done, PAGE_SIZE - offset); - len_str = strnlen((char *) kaddr, len); + len_str = strnlen(addr, len); done += len_str; uaddr += len_str; } while ((len_str == len) && (done < count)); @@ -192,7 +192,7 @@ static size_t strnlen_user_pt(size_t count, const char __user *src) return done + 1; fault: spin_unlock(&mm->page_table_lock); - if (__handle_fault(uaddr, -kaddr, 0)) + if (__handle_fault(uaddr, (unsigned long) pte, 0)) return 0; goto retry; } @@ -225,10 +225,11 @@ static size_t copy_in_user_pt(size_t n, void __user *to, const void __user *from) { struct mm_struct *mm = current->mm; - unsigned long offset_max, uaddr, done, size, error_code; + unsigned long offset_from, offset_to, offset_max, pfn_from, pfn_to, + uaddr, done, size, error_code; unsigned long uaddr_from = (unsigned long) from; unsigned long uaddr_to = (unsigned long) to; - unsigned long kaddr_to, kaddr_from; + pte_t *pte_from, *pte_to; int write_user; if (segment_eq(get_fs(), KERNEL_DS)) { @@ -241,23 +242,38 @@ static size_t copy_in_user_pt(size_t n, void __user *to, do { write_user = 0; uaddr = uaddr_from; - kaddr_from = follow_table(mm, uaddr_from, 0); - error_code = kaddr_from; - if (IS_ERR_VALUE(error_code)) + pte_from = follow_table(mm, uaddr_from); + error_code = (unsigned long) pte_from; + if (error_code < 0x1000) + goto fault; + if (!pte_present(*pte_from)) { + error_code = 0x11; goto fault; + } write_user = 1; uaddr = uaddr_to; - kaddr_to = follow_table(mm, uaddr_to, 1); - error_code = (unsigned long) kaddr_to; - if (IS_ERR_VALUE(error_code)) + pte_to = follow_table(mm, uaddr_to); + error_code = (unsigned long) pte_to; + if (error_code < 0x1000) + goto fault; + if (!pte_present(*pte_to)) { + error_code = 0x11; goto fault; + } else if (!pte_write(*pte_to)) { + error_code = 0x04; + goto fault; + } - offset_max = max(uaddr_from & ~PAGE_MASK, - uaddr_to & ~PAGE_MASK); + pfn_from = pte_pfn(*pte_from); + pfn_to = pte_pfn(*pte_to); + offset_from = uaddr_from & (PAGE_SIZE-1); + offset_to = uaddr_from & (PAGE_SIZE-1); + offset_max = max(offset_from, offset_to); size = min(n - done, PAGE_SIZE - offset_max); - memcpy((void *) kaddr_to, (void *) kaddr_from, size); + memcpy((void *)(pfn_to << PAGE_SHIFT) + offset_to, + (void *)(pfn_from << PAGE_SHIFT) + offset_from, size); done += size; uaddr_from += size; uaddr_to += size; @@ -266,7 +282,7 @@ static size_t copy_in_user_pt(size_t n, void __user *to, return n - done; fault: spin_unlock(&mm->page_table_lock); - if (__handle_fault(uaddr, -error_code, write_user)) + if (__handle_fault(uaddr, error_code, write_user)) return n - done; goto retry; } @@ -325,7 +341,7 @@ int futex_atomic_op_pt(int op, u32 __user *uaddr, int oparg, int *old) return __futex_atomic_op_pt(op, uaddr, oparg, old); spin_lock(¤t->mm->page_table_lock); uaddr = (u32 __force __user *) - __dat_user_addr((__force unsigned long) uaddr, 1); + __dat_user_addr((__force unsigned long) uaddr); if (!uaddr) { spin_unlock(¤t->mm->page_table_lock); return -EFAULT; @@ -362,7 +378,7 @@ int futex_atomic_cmpxchg_pt(u32 *uval, u32 __user *uaddr, return __futex_atomic_cmpxchg_pt(uval, uaddr, oldval, newval); spin_lock(¤t->mm->page_table_lock); uaddr = (u32 __force __user *) - __dat_user_addr((__force unsigned long) uaddr, 1); + __dat_user_addr((__force unsigned long) uaddr); if (!uaddr) { spin_unlock(¤t->mm->page_table_lock); return -EFAULT; diff --git a/trunk/arch/s390/mm/Makefile b/trunk/arch/s390/mm/Makefile index 0f5536b0c1a1..d98fe9004a52 100644 --- a/trunk/arch/s390/mm/Makefile +++ b/trunk/arch/s390/mm/Makefile @@ -3,7 +3,7 @@ # obj-y := init.o fault.o extmem.o mmap.o vmem.o pgtable.o maccess.o \ - page-states.o gup.o extable.o + page-states.o gup.o obj-$(CONFIG_CMM) += cmm.o obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o obj-$(CONFIG_DEBUG_SET_MODULE_RONX) += pageattr.o diff --git a/trunk/arch/s390/mm/extable.c b/trunk/arch/s390/mm/extable.c deleted file mode 100644 index 4d1ee88864e8..000000000000 --- a/trunk/arch/s390/mm/extable.c +++ /dev/null @@ -1,81 +0,0 @@ -#include -#include -#include - -/* - * Search one exception table for an entry corresponding to the - * given instruction address, and return the address of the entry, - * or NULL if none is found. - * We use a binary search, and thus we assume that the table is - * already sorted. - */ -const struct exception_table_entry * -search_extable(const struct exception_table_entry *first, - const struct exception_table_entry *last, - unsigned long value) -{ - const struct exception_table_entry *mid; - unsigned long addr; - - while (first <= last) { - mid = ((last - first) >> 1) + first; - addr = extable_insn(mid); - if (addr < value) - first = mid + 1; - else if (addr > value) - last = mid - 1; - else - return mid; - } - return NULL; -} - -/* - * The exception table needs to be sorted so that the binary - * search that we use to find entries in it works properly. - * This is used both for the kernel exception table and for - * the exception tables of modules that get loaded. - * - */ -static int cmp_ex(const void *a, const void *b) -{ - const struct exception_table_entry *x = a, *y = b; - - /* This compare is only valid after normalization. */ - return x->insn - y->insn; -} - -void sort_extable(struct exception_table_entry *start, - struct exception_table_entry *finish) -{ - struct exception_table_entry *p; - int i; - - /* Normalize entries to being relative to the start of the section */ - for (p = start, i = 0; p < finish; p++, i += 8) - p->insn += i; - sort(start, finish - start, sizeof(*start), cmp_ex, NULL); - /* Denormalize all entries */ - for (p = start, i = 0; p < finish; p++, i += 8) - p->insn -= i; -} - -#ifdef CONFIG_MODULES -/* - * If the exception table is sorted, any referring to the module init - * will be at the beginning or the end. - */ -void trim_init_extable(struct module *m) -{ - /* Trim the beginning */ - while (m->num_exentries && - within_module_init(extable_insn(&m->extable[0]), m)) { - m->extable++; - m->num_exentries--; - } - /* Trim the end */ - while (m->num_exentries && - within_module_init(extable_insn(&m->extable[m->num_exentries-1]), m)) - m->num_exentries--; -} -#endif /* CONFIG_MODULES */ diff --git a/trunk/arch/s390/mm/fault.c b/trunk/arch/s390/mm/fault.c index ac9122ca1152..6c013f544146 100644 --- a/trunk/arch/s390/mm/fault.c +++ b/trunk/arch/s390/mm/fault.c @@ -111,7 +111,7 @@ static inline int user_space_fault(unsigned long trans_exc_code) if (trans_exc_code == 2) /* Access via secondary space, set_fs setting decides */ return current->thread.mm_segment.ar4; - if (s390_user_mode == HOME_SPACE_MODE) + if (addressing_mode == HOME_SPACE_MODE) /* User space if the access has been done via home space. */ return trans_exc_code == 3; /* @@ -163,7 +163,7 @@ static noinline void do_no_context(struct pt_regs *regs) /* Are we prepared to handle this kernel fault? */ fixup = search_exception_tables(regs->psw.addr & PSW_ADDR_INSN); if (fixup) { - regs->psw.addr = extable_fixup(fixup) | PSW_ADDR_AMODE; + regs->psw.addr = fixup->fixup | PSW_ADDR_AMODE; return; } @@ -628,8 +628,9 @@ static int __cpuinit pfault_cpu_notify(struct notifier_block *self, struct thread_struct *thread, *next; struct task_struct *tsk; - switch (action & ~CPU_TASKS_FROZEN) { + switch (action) { case CPU_DEAD: + case CPU_DEAD_FROZEN: spin_lock_irq(&pfault_lock); list_for_each_entry_safe(thread, next, &pfault_list, list) { thread->pfault_wait = 0; diff --git a/trunk/arch/s390/mm/gup.c b/trunk/arch/s390/mm/gup.c index eeaf8023851f..65cb06e2af4e 100644 --- a/trunk/arch/s390/mm/gup.c +++ b/trunk/arch/s390/mm/gup.c @@ -154,43 +154,6 @@ static inline int gup_pud_range(pgd_t *pgdp, pgd_t pgd, unsigned long addr, return 1; } -/* - * Like get_user_pages_fast() except its IRQ-safe in that it won't fall - * back to the regular GUP. - */ -int __get_user_pages_fast(unsigned long start, int nr_pages, int write, - struct page **pages) -{ - struct mm_struct *mm = current->mm; - unsigned long addr, len, end; - unsigned long next, flags; - pgd_t *pgdp, pgd; - int nr = 0; - - start &= PAGE_MASK; - addr = start; - len = (unsigned long) nr_pages << PAGE_SHIFT; - end = start + len; - if (unlikely(!access_ok(write ? VERIFY_WRITE : VERIFY_READ, - (void __user *)start, len))) - return 0; - - local_irq_save(flags); - pgdp = pgd_offset(mm, addr); - do { - pgd = *pgdp; - barrier(); - next = pgd_addr_end(addr, end); - if (pgd_none(pgd)) - break; - if (!gup_pud_range(pgdp, pgd, addr, next, write, pages, &nr)) - break; - } while (pgdp++, addr = next, addr != end); - local_irq_restore(flags); - - return nr; -} - /** * get_user_pages_fast() - pin user pages in memory * @start: starting user address diff --git a/trunk/arch/s390/mm/init.c b/trunk/arch/s390/mm/init.c index 81e596c65dee..6adbc082618a 100644 --- a/trunk/arch/s390/mm/init.c +++ b/trunk/arch/s390/mm/init.c @@ -42,7 +42,7 @@ pgd_t swapper_pg_dir[PTRS_PER_PGD] __attribute__((__aligned__(PAGE_SIZE))); unsigned long empty_zero_page, zero_page_mask; EXPORT_SYMBOL(empty_zero_page); -static unsigned long __init setup_zero_pages(void) +static unsigned long setup_zero_pages(void) { struct cpuid cpu_id; unsigned int order; @@ -212,7 +212,7 @@ void free_initmem(void) } #ifdef CONFIG_BLK_DEV_INITRD -void __init free_initrd_mem(unsigned long start, unsigned long end) +void free_initrd_mem(unsigned long start, unsigned long end) { free_init_pages("initrd memory", start, end); } diff --git a/trunk/arch/s390/mm/pgtable.c b/trunk/arch/s390/mm/pgtable.c index b402991e43d7..18df31d1f2c9 100644 --- a/trunk/arch/s390/mm/pgtable.c +++ b/trunk/arch/s390/mm/pgtable.c @@ -609,8 +609,8 @@ static inline unsigned int atomic_xor_bits(atomic_t *v, unsigned int bits) */ unsigned long *page_table_alloc(struct mm_struct *mm, unsigned long vmaddr) { - unsigned long *uninitialized_var(table); - struct page *uninitialized_var(page); + struct page *page; + unsigned long *table; unsigned int mask, bit; if (mm_has_pgste(mm)) @@ -796,7 +796,7 @@ int s390_enable_sie(void) struct mm_struct *mm, *old_mm; /* Do we have switched amode? If no, we cannot do sie */ - if (s390_user_mode == HOME_SPACE_MODE) + if (addressing_mode == HOME_SPACE_MODE) return -EINVAL; /* Do we have pgstes? if yes, we are done */ diff --git a/trunk/arch/s390/mm/vmem.c b/trunk/arch/s390/mm/vmem.c index c22abf900c9e..6f896e75ab49 100644 --- a/trunk/arch/s390/mm/vmem.c +++ b/trunk/arch/s390/mm/vmem.c @@ -107,7 +107,7 @@ static int vmem_add_mem(unsigned long start, unsigned long size, int ro) pte = mk_pte_phys(address, __pgprot(ro ? _PAGE_RO : 0)); pm_dir = pmd_offset(pu_dir, address); -#if defined(CONFIG_64BIT) && !defined(CONFIG_DEBUG_PAGEALLOC) +#ifdef CONFIG_64BIT if (MACHINE_HAS_HPAGE && !(address & ~HPAGE_MASK) && (address + HPAGE_SIZE <= start + size) && (address >= HPAGE_SIZE)) { diff --git a/trunk/arch/s390/net/Makefile b/trunk/arch/s390/net/Makefile deleted file mode 100644 index 90568c33ddb0..000000000000 --- a/trunk/arch/s390/net/Makefile +++ /dev/null @@ -1,4 +0,0 @@ -# -# Arch-specific network modules -# -obj-$(CONFIG_BPF_JIT) += bpf_jit.o bpf_jit_comp.o diff --git a/trunk/arch/s390/net/bpf_jit.S b/trunk/arch/s390/net/bpf_jit.S deleted file mode 100644 index 7e45d13816c1..000000000000 --- a/trunk/arch/s390/net/bpf_jit.S +++ /dev/null @@ -1,130 +0,0 @@ -/* - * BPF Jit compiler for s390, help functions. - * - * Copyright IBM Corp. 2012 - * - * Author(s): Martin Schwidefsky - */ -#include - -/* - * Calling convention: - * registers %r2, %r6-%r8, %r10-%r11, %r13, %r15 are call saved - * %r2: skb pointer - * %r3: offset parameter - * %r5: BPF A accumulator - * %r8: return address - * %r9: save register for skb pointer - * %r10: skb->data - * %r11: skb->len - skb->data_len (headlen) - * %r12: BPF X accumulator - * - * skb_copy_bits takes 4 parameters: - * %r2 = skb pointer - * %r3 = offset into skb data - * %r4 = length to copy - * %r5 = pointer to temp buffer - */ -#define SKBDATA %r8 - - /* A = *(u32 *) (skb->data+K+X) */ -ENTRY(sk_load_word_ind) - ar %r3,%r12 # offset += X - bmr %r8 # < 0 -> return with cc - - /* A = *(u32 *) (skb->data+K) */ -ENTRY(sk_load_word) - llgfr %r1,%r3 # extend offset - ahi %r3,4 # offset + 4 - clr %r11,%r3 # hlen <= offset + 4 ? - jl sk_load_word_slow - l %r5,0(%r1,%r10) # get word from skb - xr %r1,%r1 # set cc to zero - br %r8 - -sk_load_word_slow: - lgr %r9,%r2 # save %r2 - lhi %r4,4 # 4 bytes - la %r5,160(%r15) # pointer to temp buffer - brasl %r14,skb_copy_bits # get data from skb - l %r5,160(%r15) # load result from temp buffer - ltgr %r2,%r2 # set cc to (%r2 != 0) - lgr %r2,%r9 # restore %r2 - br %r8 - - /* A = *(u16 *) (skb->data+K+X) */ -ENTRY(sk_load_half_ind) - ar %r3,%r12 # offset += X - bmr %r8 # < 0 -> return with cc - - /* A = *(u16 *) (skb->data+K) */ -ENTRY(sk_load_half) - llgfr %r1,%r3 # extend offset - ahi %r3,2 # offset + 2 - clr %r11,%r3 # hlen <= offset + 2 ? - jl sk_load_half_slow - llgh %r5,0(%r1,%r10) # get half from skb - xr %r1,%r1 # set cc to zero - br %r8 - -sk_load_half_slow: - lgr %r9,%r2 # save %r2 - lhi %r4,2 # 2 bytes - la %r5,162(%r15) # pointer to temp buffer - brasl %r14,skb_copy_bits # get data from skb - xc 160(2,%r15),160(%r15) - l %r5,160(%r15) # load result from temp buffer - ltgr %r2,%r2 # set cc to (%r2 != 0) - lgr %r2,%r9 # restore %r2 - br %r8 - - /* A = *(u8 *) (skb->data+K+X) */ -ENTRY(sk_load_byte_ind) - ar %r3,%r12 # offset += X - bmr %r8 # < 0 -> return with cc - - /* A = *(u8 *) (skb->data+K) */ -ENTRY(sk_load_byte) - llgfr %r1,%r3 # extend offset - clr %r11,%r3 # hlen < offset ? - jle sk_load_byte_slow - lhi %r5,0 - ic %r5,0(%r1,%r10) # get byte from skb - xr %r1,%r1 # set cc to zero - br %r8 - -sk_load_byte_slow: - lgr %r9,%r2 # save %r2 - lhi %r4,1 # 1 bytes - la %r5,163(%r15) # pointer to temp buffer - brasl %r14,skb_copy_bits # get data from skb - xc 160(3,%r15),160(%r15) - l %r5,160(%r15) # load result from temp buffer - ltgr %r2,%r2 # set cc to (%r2 != 0) - lgr %r2,%r9 # restore %r2 - br %r8 - - /* A = (*(u8 *)(skb->data+K) & 0xf) << 2 */ -ENTRY(sk_load_byte_msh) - llgfr %r1,%r3 # extend offset - clr %r11,%r3 # hlen < offset ? - jle sk_load_byte_slow - lhi %r12,0 - ic %r12,0(%r1,%r10) # get byte from skb - nill %r12,0x0f - sll %r12,2 - xr %r1,%r1 # set cc to zero - br %r8 - -sk_load_byte_msh_slow: - lgr %r9,%r2 # save %r2 - lhi %r4,2 # 2 bytes - la %r5,162(%r15) # pointer to temp buffer - brasl %r14,skb_copy_bits # get data from skb - xc 160(3,%r15),160(%r15) - l %r12,160(%r15) # load result from temp buffer - nill %r12,0x0f - sll %r12,2 - ltgr %r2,%r2 # set cc to (%r2 != 0) - lgr %r2,%r9 # restore %r2 - br %r8 diff --git a/trunk/arch/s390/net/bpf_jit_comp.c b/trunk/arch/s390/net/bpf_jit_comp.c deleted file mode 100644 index 9b355b406afa..000000000000 --- a/trunk/arch/s390/net/bpf_jit_comp.c +++ /dev/null @@ -1,776 +0,0 @@ -/* - * BPF Jit compiler for s390. - * - * Copyright IBM Corp. 2012 - * - * Author(s): Martin Schwidefsky - */ -#include -#include -#include -#include -#include -#include - -/* - * Conventions: - * %r2 = skb pointer - * %r3 = offset parameter - * %r4 = scratch register / length parameter - * %r5 = BPF A accumulator - * %r8 = return address - * %r9 = save register for skb pointer - * %r10 = skb->data - * %r11 = skb->len - skb->data_len (headlen) - * %r12 = BPF X accumulator - * %r13 = literal pool pointer - * 0(%r15) - 63(%r15) scratch memory array with BPF_MEMWORDS - */ -int bpf_jit_enable __read_mostly; - -/* - * assembly code in arch/x86/net/bpf_jit.S - */ -extern u8 sk_load_word[], sk_load_half[], sk_load_byte[], sk_load_byte_msh[]; -extern u8 sk_load_word_ind[], sk_load_half_ind[], sk_load_byte_ind[]; - -struct bpf_jit { - unsigned int seen; - u8 *start; - u8 *prg; - u8 *mid; - u8 *lit; - u8 *end; - u8 *base_ip; - u8 *ret0_ip; - u8 *exit_ip; - unsigned int off_load_word; - unsigned int off_load_half; - unsigned int off_load_byte; - unsigned int off_load_bmsh; - unsigned int off_load_iword; - unsigned int off_load_ihalf; - unsigned int off_load_ibyte; -}; - -#define BPF_SIZE_MAX 4096 /* Max size for program */ - -#define SEEN_DATAREF 1 /* might call external helpers */ -#define SEEN_XREG 2 /* ebx is used */ -#define SEEN_MEM 4 /* use mem[] for temporary storage */ -#define SEEN_RET0 8 /* pc_ret0 points to a valid return 0 */ -#define SEEN_LITERAL 16 /* code uses literals */ -#define SEEN_LOAD_WORD 32 /* code uses sk_load_word */ -#define SEEN_LOAD_HALF 64 /* code uses sk_load_half */ -#define SEEN_LOAD_BYTE 128 /* code uses sk_load_byte */ -#define SEEN_LOAD_BMSH 256 /* code uses sk_load_byte_msh */ -#define SEEN_LOAD_IWORD 512 /* code uses sk_load_word_ind */ -#define SEEN_LOAD_IHALF 1024 /* code uses sk_load_half_ind */ -#define SEEN_LOAD_IBYTE 2048 /* code uses sk_load_byte_ind */ - -#define EMIT2(op) \ -({ \ - if (jit->prg + 2 <= jit->mid) \ - *(u16 *) jit->prg = op; \ - jit->prg += 2; \ -}) - -#define EMIT4(op) \ -({ \ - if (jit->prg + 4 <= jit->mid) \ - *(u32 *) jit->prg = op; \ - jit->prg += 4; \ -}) - -#define EMIT4_DISP(op, disp) \ -({ \ - unsigned int __disp = (disp) & 0xfff; \ - EMIT4(op | __disp); \ -}) - -#define EMIT4_IMM(op, imm) \ -({ \ - unsigned int __imm = (imm) & 0xffff; \ - EMIT4(op | __imm); \ -}) - -#define EMIT4_PCREL(op, pcrel) \ -({ \ - long __pcrel = ((pcrel) >> 1) & 0xffff; \ - EMIT4(op | __pcrel); \ -}) - -#define EMIT6(op1, op2) \ -({ \ - if (jit->prg + 6 <= jit->mid) { \ - *(u32 *) jit->prg = op1; \ - *(u16 *) (jit->prg + 4) = op2; \ - } \ - jit->prg += 6; \ -}) - -#define EMIT6_DISP(op1, op2, disp) \ -({ \ - unsigned int __disp = (disp) & 0xfff; \ - EMIT6(op1 | __disp, op2); \ -}) - -#define EMIT6_IMM(op, imm) \ -({ \ - unsigned int __imm = (imm); \ - EMIT6(op | (__imm >> 16), __imm & 0xffff); \ -}) - -#define EMIT_CONST(val) \ -({ \ - unsigned int ret; \ - ret = (unsigned int) (jit->lit - jit->base_ip); \ - jit->seen |= SEEN_LITERAL; \ - if (jit->lit + 4 <= jit->end) \ - *(u32 *) jit->lit = val; \ - jit->lit += 4; \ - ret; \ -}) - -#define EMIT_FN_CONST(bit, fn) \ -({ \ - unsigned int ret; \ - ret = (unsigned int) (jit->lit - jit->base_ip); \ - if (jit->seen & bit) { \ - jit->seen |= SEEN_LITERAL; \ - if (jit->lit + 8 <= jit->end) \ - *(void **) jit->lit = fn; \ - jit->lit += 8; \ - } \ - ret; \ -}) - -static void bpf_jit_prologue(struct bpf_jit *jit) -{ - /* Save registers and create stack frame if necessary */ - if (jit->seen & SEEN_DATAREF) { - /* stmg %r8,%r15,88(%r15) */ - EMIT6(0xeb8ff058, 0x0024); - /* lgr %r14,%r15 */ - EMIT4(0xb90400ef); - /* ahi %r15, */ - EMIT4_IMM(0xa7fa0000, (jit->seen & SEEN_MEM) ? -112 : -80); - /* stg %r14,152(%r15) */ - EMIT6(0xe3e0f098, 0x0024); - } else if ((jit->seen & SEEN_XREG) && (jit->seen & SEEN_LITERAL)) - /* stmg %r12,%r13,120(%r15) */ - EMIT6(0xebcdf078, 0x0024); - else if (jit->seen & SEEN_XREG) - /* stg %r12,120(%r15) */ - EMIT6(0xe3c0f078, 0x0024); - else if (jit->seen & SEEN_LITERAL) - /* stg %r13,128(%r15) */ - EMIT6(0xe3d0f080, 0x0024); - - /* Setup literal pool */ - if (jit->seen & SEEN_LITERAL) { - /* basr %r13,0 */ - EMIT2(0x0dd0); - jit->base_ip = jit->prg; - } - jit->off_load_word = EMIT_FN_CONST(SEEN_LOAD_WORD, sk_load_word); - jit->off_load_half = EMIT_FN_CONST(SEEN_LOAD_HALF, sk_load_half); - jit->off_load_byte = EMIT_FN_CONST(SEEN_LOAD_BYTE, sk_load_byte); - jit->off_load_bmsh = EMIT_FN_CONST(SEEN_LOAD_BMSH, sk_load_byte_msh); - jit->off_load_iword = EMIT_FN_CONST(SEEN_LOAD_IWORD, sk_load_word_ind); - jit->off_load_ihalf = EMIT_FN_CONST(SEEN_LOAD_IHALF, sk_load_half_ind); - jit->off_load_ibyte = EMIT_FN_CONST(SEEN_LOAD_IBYTE, sk_load_byte_ind); - - /* Filter needs to access skb data */ - if (jit->seen & SEEN_DATAREF) { - /* l %r11,(%r2) */ - EMIT4_DISP(0x58b02000, offsetof(struct sk_buff, len)); - /* s %r11,(%r2) */ - EMIT4_DISP(0x5bb02000, offsetof(struct sk_buff, data_len)); - /* lg %r10,(%r2) */ - EMIT6_DISP(0xe3a02000, 0x0004, - offsetof(struct sk_buff, data)); - } -} - -static void bpf_jit_epilogue(struct bpf_jit *jit) -{ - /* Return 0 */ - if (jit->seen & SEEN_RET0) { - jit->ret0_ip = jit->prg; - /* lghi %r2,0 */ - EMIT4(0xa7290000); - } - jit->exit_ip = jit->prg; - /* Restore registers */ - if (jit->seen & SEEN_DATAREF) - /* lmg %r8,%r15,(%r15) */ - EMIT6_DISP(0xeb8ff000, 0x0004, - (jit->seen & SEEN_MEM) ? 200 : 168); - else if ((jit->seen & SEEN_XREG) && (jit->seen & SEEN_LITERAL)) - /* lmg %r12,%r13,120(%r15) */ - EMIT6(0xebcdf078, 0x0004); - else if (jit->seen & SEEN_XREG) - /* lg %r12,120(%r15) */ - EMIT6(0xe3c0f078, 0x0004); - else if (jit->seen & SEEN_LITERAL) - /* lg %r13,128(%r15) */ - EMIT6(0xe3d0f080, 0x0004); - /* br %r14 */ - EMIT2(0x07fe); -} - -/* - * make sure we dont leak kernel information to user - */ -static void bpf_jit_noleaks(struct bpf_jit *jit, struct sock_filter *filter) -{ - /* Clear temporary memory if (seen & SEEN_MEM) */ - if (jit->seen & SEEN_MEM) - /* xc 0(64,%r15),0(%r15) */ - EMIT6(0xd73ff000, 0xf000); - /* Clear X if (seen & SEEN_XREG) */ - if (jit->seen & SEEN_XREG) - /* lhi %r12,0 */ - EMIT4(0xa7c80000); - /* Clear A if the first register does not set it. */ - switch (filter[0].code) { - case BPF_S_LD_W_ABS: - case BPF_S_LD_H_ABS: - case BPF_S_LD_B_ABS: - case BPF_S_LD_W_LEN: - case BPF_S_LD_W_IND: - case BPF_S_LD_H_IND: - case BPF_S_LD_B_IND: - case BPF_S_LDX_B_MSH: - case BPF_S_LD_IMM: - case BPF_S_LD_MEM: - case BPF_S_MISC_TXA: - case BPF_S_ANC_PROTOCOL: - case BPF_S_ANC_PKTTYPE: - case BPF_S_ANC_IFINDEX: - case BPF_S_ANC_MARK: - case BPF_S_ANC_QUEUE: - case BPF_S_ANC_HATYPE: - case BPF_S_ANC_RXHASH: - case BPF_S_ANC_CPU: - case BPF_S_RET_K: - /* first instruction sets A register */ - break; - default: /* A = 0 */ - /* lhi %r5,0 */ - EMIT4(0xa7580000); - } -} - -static int bpf_jit_insn(struct bpf_jit *jit, struct sock_filter *filter, - unsigned int *addrs, int i, int last) -{ - unsigned int K; - int offset; - unsigned int mask; - - K = filter->k; - switch (filter->code) { - case BPF_S_ALU_ADD_X: /* A += X */ - jit->seen |= SEEN_XREG; - /* ar %r5,%r12 */ - EMIT2(0x1a5c); - break; - case BPF_S_ALU_ADD_K: /* A += K */ - if (!K) - break; - if (K <= 16383) - /* ahi %r5, */ - EMIT4_IMM(0xa75a0000, K); - else if (test_facility(21)) - /* alfi %r5, */ - EMIT6_IMM(0xc25b0000, K); - else - /* a %r5,(%r13) */ - EMIT4_DISP(0x5a50d000, EMIT_CONST(K)); - break; - case BPF_S_ALU_SUB_X: /* A -= X */ - jit->seen |= SEEN_XREG; - /* sr %r5,%r12 */ - EMIT2(0x1b5c); - break; - case BPF_S_ALU_SUB_K: /* A -= K */ - if (!K) - break; - if (K <= 16384) - /* ahi %r5,-K */ - EMIT4_IMM(0xa75a0000, -K); - else if (test_facility(21)) - /* alfi %r5,-K */ - EMIT6_IMM(0xc25b0000, -K); - else - /* s %r5,(%r13) */ - EMIT4_DISP(0x5b50d000, EMIT_CONST(K)); - break; - case BPF_S_ALU_MUL_X: /* A *= X */ - jit->seen |= SEEN_XREG; - /* msr %r5,%r12 */ - EMIT4(0xb252005c); - break; - case BPF_S_ALU_MUL_K: /* A *= K */ - if (K <= 16383) - /* mhi %r5,K */ - EMIT4_IMM(0xa75c0000, K); - else if (test_facility(34)) - /* msfi %r5, */ - EMIT6_IMM(0xc2510000, K); - else - /* ms %r5,(%r13) */ - EMIT4_DISP(0x7150d000, EMIT_CONST(K)); - break; - case BPF_S_ALU_DIV_X: /* A /= X */ - jit->seen |= SEEN_XREG | SEEN_RET0; - /* ltr %r12,%r12 */ - EMIT2(0x12cc); - /* jz */ - EMIT4_PCREL(0xa7840000, (jit->ret0_ip - jit->prg)); - /* lhi %r4,0 */ - EMIT4(0xa7480000); - /* dr %r4,%r12 */ - EMIT2(0x1d4c); - break; - case BPF_S_ALU_DIV_K: /* A = reciprocal_divide(A, K) */ - /* m %r4,(%r13) */ - EMIT4_DISP(0x5c40d000, EMIT_CONST(K)); - /* lr %r5,%r4 */ - EMIT2(0x1854); - break; - case BPF_S_ALU_AND_X: /* A &= X */ - jit->seen |= SEEN_XREG; - /* nr %r5,%r12 */ - EMIT2(0x145c); - break; - case BPF_S_ALU_AND_K: /* A &= K */ - if (test_facility(21)) - /* nilf %r5, */ - EMIT6_IMM(0xc05b0000, K); - else - /* n %r5,(%r13) */ - EMIT4_DISP(0x5450d000, EMIT_CONST(K)); - break; - case BPF_S_ALU_OR_X: /* A |= X */ - jit->seen |= SEEN_XREG; - /* or %r5,%r12 */ - EMIT2(0x165c); - break; - case BPF_S_ALU_OR_K: /* A |= K */ - if (test_facility(21)) - /* oilf %r5, */ - EMIT6_IMM(0xc05d0000, K); - else - /* o %r5,(%r13) */ - EMIT4_DISP(0x5650d000, EMIT_CONST(K)); - break; - case BPF_S_ANC_ALU_XOR_X: /* A ^= X; */ - jit->seen |= SEEN_XREG; - /* xr %r5,%r12 */ - EMIT2(0x175c); - break; - case BPF_S_ALU_LSH_X: /* A <<= X; */ - jit->seen |= SEEN_XREG; - /* sll %r5,0(%r12) */ - EMIT4(0x8950c000); - break; - case BPF_S_ALU_LSH_K: /* A <<= K */ - if (K == 0) - break; - /* sll %r5,K */ - EMIT4_DISP(0x89500000, K); - break; - case BPF_S_ALU_RSH_X: /* A >>= X; */ - jit->seen |= SEEN_XREG; - /* srl %r5,0(%r12) */ - EMIT4(0x8850c000); - break; - case BPF_S_ALU_RSH_K: /* A >>= K; */ - if (K == 0) - break; - /* srl %r5,K */ - EMIT4_DISP(0x88500000, K); - break; - case BPF_S_ALU_NEG: /* A = -A */ - /* lnr %r5,%r5 */ - EMIT2(0x1155); - break; - case BPF_S_JMP_JA: /* ip += K */ - offset = addrs[i + K] + jit->start - jit->prg; - EMIT4_PCREL(0xa7f40000, offset); - break; - case BPF_S_JMP_JGT_K: /* ip += (A > K) ? jt : jf */ - mask = 0x200000; /* jh */ - goto kbranch; - case BPF_S_JMP_JGE_K: /* ip += (A >= K) ? jt : jf */ - mask = 0xa00000; /* jhe */ - goto kbranch; - case BPF_S_JMP_JEQ_K: /* ip += (A == K) ? jt : jf */ - mask = 0x800000; /* je */ -kbranch: /* Emit compare if the branch targets are different */ - if (filter->jt != filter->jf) { - if (K <= 16383) - /* chi %r5, */ - EMIT4_IMM(0xa75e0000, K); - else if (test_facility(21)) - /* clfi %r5, */ - EMIT6_IMM(0xc25f0000, K); - else - /* c %r5,(%r13) */ - EMIT4_DISP(0x5950d000, EMIT_CONST(K)); - } -branch: if (filter->jt == filter->jf) { - if (filter->jt == 0) - break; - /* j */ - offset = addrs[i + filter->jt] + jit->start - jit->prg; - EMIT4_PCREL(0xa7f40000, offset); - break; - } - if (filter->jt != 0) { - /* brc , */ - offset = addrs[i + filter->jt] + jit->start - jit->prg; - EMIT4_PCREL(0xa7040000 | mask, offset); - } - if (filter->jf != 0) { - /* brc , */ - offset = addrs[i + filter->jf] + jit->start - jit->prg; - EMIT4_PCREL(0xa7040000 | (mask ^ 0xf00000), offset); - } - break; - case BPF_S_JMP_JSET_K: /* ip += (A & K) ? jt : jf */ - mask = 0x700000; /* jnz */ - /* Emit test if the branch targets are different */ - if (filter->jt != filter->jf) { - if (K > 65535) { - /* lr %r4,%r5 */ - EMIT2(0x1845); - /* n %r4,(%r13) */ - EMIT4_DISP(0x5440d000, EMIT_CONST(K)); - } else - /* tmll %r5,K */ - EMIT4_IMM(0xa7510000, K); - } - goto branch; - case BPF_S_JMP_JGT_X: /* ip += (A > X) ? jt : jf */ - mask = 0x200000; /* jh */ - goto xbranch; - case BPF_S_JMP_JGE_X: /* ip += (A >= X) ? jt : jf */ - mask = 0xa00000; /* jhe */ - goto xbranch; - case BPF_S_JMP_JEQ_X: /* ip += (A == X) ? jt : jf */ - mask = 0x800000; /* je */ -xbranch: /* Emit compare if the branch targets are different */ - if (filter->jt != filter->jf) { - jit->seen |= SEEN_XREG; - /* cr %r5,%r12 */ - EMIT2(0x195c); - } - goto branch; - case BPF_S_JMP_JSET_X: /* ip += (A & X) ? jt : jf */ - mask = 0x700000; /* jnz */ - /* Emit test if the branch targets are different */ - if (filter->jt != filter->jf) { - jit->seen |= SEEN_XREG; - /* lr %r4,%r5 */ - EMIT2(0x1845); - /* nr %r4,%r12 */ - EMIT2(0x144c); - } - goto branch; - case BPF_S_LD_W_ABS: /* A = *(u32 *) (skb->data+K) */ - jit->seen |= SEEN_DATAREF | SEEN_RET0 | SEEN_LOAD_WORD; - offset = jit->off_load_word; - goto load_abs; - case BPF_S_LD_H_ABS: /* A = *(u16 *) (skb->data+K) */ - jit->seen |= SEEN_DATAREF | SEEN_RET0 | SEEN_LOAD_HALF; - offset = jit->off_load_half; - goto load_abs; - case BPF_S_LD_B_ABS: /* A = *(u8 *) (skb->data+K) */ - jit->seen |= SEEN_DATAREF | SEEN_RET0 | SEEN_LOAD_BYTE; - offset = jit->off_load_byte; -load_abs: if ((int) K < 0) - goto out; -call_fn: /* lg %r1,(%r13) */ - EMIT6_DISP(0xe310d000, 0x0004, offset); - /* l %r3,(%r13) */ - EMIT4_DISP(0x5830d000, EMIT_CONST(K)); - /* basr %r8,%r1 */ - EMIT2(0x0d81); - /* jnz */ - EMIT4_PCREL(0xa7740000, (jit->ret0_ip - jit->prg)); - break; - case BPF_S_LD_W_IND: /* A = *(u32 *) (skb->data+K+X) */ - jit->seen |= SEEN_DATAREF | SEEN_RET0 | SEEN_LOAD_IWORD; - offset = jit->off_load_iword; - goto call_fn; - case BPF_S_LD_H_IND: /* A = *(u16 *) (skb->data+K+X) */ - jit->seen |= SEEN_DATAREF | SEEN_RET0 | SEEN_LOAD_IHALF; - offset = jit->off_load_ihalf; - goto call_fn; - case BPF_S_LD_B_IND: /* A = *(u8 *) (skb->data+K+X) */ - jit->seen |= SEEN_DATAREF | SEEN_RET0 | SEEN_LOAD_IBYTE; - offset = jit->off_load_ibyte; - goto call_fn; - case BPF_S_LDX_B_MSH: - /* X = (*(u8 *)(skb->data+K) & 0xf) << 2 */ - jit->seen |= SEEN_RET0; - if ((int) K < 0) { - /* j */ - EMIT4_PCREL(0xa7f40000, (jit->ret0_ip - jit->prg)); - break; - } - jit->seen |= SEEN_DATAREF | SEEN_LOAD_BMSH; - offset = jit->off_load_bmsh; - goto call_fn; - case BPF_S_LD_W_LEN: /* A = skb->len; */ - BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, len) != 4); - /* l %r5,(%r2) */ - EMIT4_DISP(0x58502000, offsetof(struct sk_buff, len)); - break; - case BPF_S_LDX_W_LEN: /* X = skb->len; */ - jit->seen |= SEEN_XREG; - /* l %r12,(%r2) */ - EMIT4_DISP(0x58c02000, offsetof(struct sk_buff, len)); - break; - case BPF_S_LD_IMM: /* A = K */ - if (K <= 16383) - /* lhi %r5,K */ - EMIT4_IMM(0xa7580000, K); - else if (test_facility(21)) - /* llilf %r5, */ - EMIT6_IMM(0xc05f0000, K); - else - /* l %r5,(%r13) */ - EMIT4_DISP(0x5850d000, EMIT_CONST(K)); - break; - case BPF_S_LDX_IMM: /* X = K */ - jit->seen |= SEEN_XREG; - if (K <= 16383) - /* lhi %r12, */ - EMIT4_IMM(0xa7c80000, K); - else if (test_facility(21)) - /* llilf %r12, */ - EMIT6_IMM(0xc0cf0000, K); - else - /* l %r12,(%r13) */ - EMIT4_DISP(0x58c0d000, EMIT_CONST(K)); - break; - case BPF_S_LD_MEM: /* A = mem[K] */ - jit->seen |= SEEN_MEM; - /* l %r5,(%r15) */ - EMIT4_DISP(0x5850f000, - (jit->seen & SEEN_DATAREF) ? 160 + K*4 : K*4); - break; - case BPF_S_LDX_MEM: /* X = mem[K] */ - jit->seen |= SEEN_XREG | SEEN_MEM; - /* l %r12,(%r15) */ - EMIT4_DISP(0x58c0f000, - (jit->seen & SEEN_DATAREF) ? 160 + K*4 : K*4); - break; - case BPF_S_MISC_TAX: /* X = A */ - jit->seen |= SEEN_XREG; - /* lr %r12,%r5 */ - EMIT2(0x18c5); - break; - case BPF_S_MISC_TXA: /* A = X */ - jit->seen |= SEEN_XREG; - /* lr %r5,%r12 */ - EMIT2(0x185c); - break; - case BPF_S_RET_K: - if (K == 0) { - jit->seen |= SEEN_RET0; - if (last) - break; - /* j */ - EMIT4_PCREL(0xa7f40000, jit->ret0_ip - jit->prg); - } else { - if (K <= 16383) - /* lghi %r2,K */ - EMIT4_IMM(0xa7290000, K); - else - /* llgf %r2,(%r13) */ - EMIT6_DISP(0xe320d000, 0x0016, EMIT_CONST(K)); - /* j */ - if (last && !(jit->seen & SEEN_RET0)) - break; - EMIT4_PCREL(0xa7f40000, jit->exit_ip - jit->prg); - } - break; - case BPF_S_RET_A: - /* llgfr %r2,%r5 */ - EMIT4(0xb9160025); - /* j */ - EMIT4_PCREL(0xa7f40000, jit->exit_ip - jit->prg); - break; - case BPF_S_ST: /* mem[K] = A */ - jit->seen |= SEEN_MEM; - /* st %r5,(%r15) */ - EMIT4_DISP(0x5050f000, - (jit->seen & SEEN_DATAREF) ? 160 + K*4 : K*4); - break; - case BPF_S_STX: /* mem[K] = X : mov %ebx,off8(%rbp) */ - jit->seen |= SEEN_XREG | SEEN_MEM; - /* st %r12,(%r15) */ - EMIT4_DISP(0x50c0f000, - (jit->seen & SEEN_DATAREF) ? 160 + K*4 : K*4); - break; - case BPF_S_ANC_PROTOCOL: /* A = ntohs(skb->protocol); */ - BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, protocol) != 2); - /* lhi %r5,0 */ - EMIT4(0xa7580000); - /* icm %r5,3,(%r2) */ - EMIT4_DISP(0xbf532000, offsetof(struct sk_buff, protocol)); - break; - case BPF_S_ANC_IFINDEX: /* if (!skb->dev) return 0; - * A = skb->dev->ifindex */ - BUILD_BUG_ON(FIELD_SIZEOF(struct net_device, ifindex) != 4); - jit->seen |= SEEN_RET0; - /* lg %r1,(%r2) */ - EMIT6_DISP(0xe3102000, 0x0004, offsetof(struct sk_buff, dev)); - /* ltgr %r1,%r1 */ - EMIT4(0xb9020011); - /* jz */ - EMIT4_PCREL(0xa7840000, jit->ret0_ip - jit->prg); - /* l %r5,(%r1) */ - EMIT4_DISP(0x58501000, offsetof(struct net_device, ifindex)); - break; - case BPF_S_ANC_MARK: /* A = skb->mark */ - BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, mark) != 4); - /* l %r5,(%r2) */ - EMIT4_DISP(0x58502000, offsetof(struct sk_buff, mark)); - break; - case BPF_S_ANC_QUEUE: /* A = skb->queue_mapping */ - BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, queue_mapping) != 2); - /* lhi %r5,0 */ - EMIT4(0xa7580000); - /* icm %r5,3,(%r2) */ - EMIT4_DISP(0xbf532000, offsetof(struct sk_buff, queue_mapping)); - break; - case BPF_S_ANC_HATYPE: /* if (!skb->dev) return 0; - * A = skb->dev->type */ - BUILD_BUG_ON(FIELD_SIZEOF(struct net_device, type) != 2); - jit->seen |= SEEN_RET0; - /* lg %r1,(%r2) */ - EMIT6_DISP(0xe3102000, 0x0004, offsetof(struct sk_buff, dev)); - /* ltgr %r1,%r1 */ - EMIT4(0xb9020011); - /* jz */ - EMIT4_PCREL(0xa7840000, jit->ret0_ip - jit->prg); - /* lhi %r5,0 */ - EMIT4(0xa7580000); - /* icm %r5,3,(%r1) */ - EMIT4_DISP(0xbf531000, offsetof(struct net_device, type)); - break; - case BPF_S_ANC_RXHASH: /* A = skb->rxhash */ - BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, rxhash) != 4); - /* l %r5,(%r2) */ - EMIT4_DISP(0x58502000, offsetof(struct sk_buff, rxhash)); - break; - case BPF_S_ANC_CPU: /* A = smp_processor_id() */ -#ifdef CONFIG_SMP - /* l %r5, */ - EMIT4_DISP(0x58500000, offsetof(struct _lowcore, cpu_nr)); -#else - /* lhi %r5,0 */ - EMIT4(0xa7580000); -#endif - break; - default: /* too complex, give up */ - goto out; - } - addrs[i] = jit->prg - jit->start; - return 0; -out: - return -1; -} - -void bpf_jit_compile(struct sk_filter *fp) -{ - unsigned long size, prg_len, lit_len; - struct bpf_jit jit, cjit; - unsigned int *addrs; - int pass, i; - - if (!bpf_jit_enable) - return; - addrs = kmalloc(fp->len * sizeof(*addrs), GFP_KERNEL); - if (addrs == NULL) - return; - memset(addrs, 0, fp->len * sizeof(*addrs)); - memset(&jit, 0, sizeof(cjit)); - memset(&cjit, 0, sizeof(cjit)); - - for (pass = 0; pass < 10; pass++) { - jit.prg = jit.start; - jit.lit = jit.mid; - - bpf_jit_prologue(&jit); - bpf_jit_noleaks(&jit, fp->insns); - for (i = 0; i < fp->len; i++) { - if (bpf_jit_insn(&jit, fp->insns + i, addrs, i, - i == fp->len - 1)) - goto out; - } - bpf_jit_epilogue(&jit); - if (jit.start) { - WARN_ON(jit.prg > cjit.prg || jit.lit > cjit.lit); - if (memcmp(&jit, &cjit, sizeof(jit)) == 0) - break; - } else if (jit.prg == cjit.prg && jit.lit == cjit.lit) { - prg_len = jit.prg - jit.start; - lit_len = jit.lit - jit.mid; - size = max_t(unsigned long, prg_len + lit_len, - sizeof(struct work_struct)); - if (size >= BPF_SIZE_MAX) - goto out; - jit.start = module_alloc(size); - if (!jit.start) - goto out; - jit.prg = jit.mid = jit.start + prg_len; - jit.lit = jit.end = jit.start + prg_len + lit_len; - jit.base_ip += (unsigned long) jit.start; - jit.exit_ip += (unsigned long) jit.start; - jit.ret0_ip += (unsigned long) jit.start; - } - cjit = jit; - } - if (bpf_jit_enable > 1) { - pr_err("flen=%d proglen=%lu pass=%d image=%p\n", - fp->len, jit.end - jit.start, pass, jit.start); - if (jit.start) { - printk(KERN_ERR "JIT code:\n"); - print_fn_code(jit.start, jit.mid - jit.start); - print_hex_dump(KERN_ERR, "JIT literals:\n", - DUMP_PREFIX_ADDRESS, 16, 1, - jit.mid, jit.end - jit.mid, false); - } - } - if (jit.start) - fp->bpf_func = (void *) jit.start; -out: - kfree(addrs); -} - -static void jit_free_defer(struct work_struct *arg) -{ - module_free(NULL, arg); -} - -/* run from softirq, we must use a work_struct to call - * module_free() from process context - */ -void bpf_jit_free(struct sk_filter *fp) -{ - struct work_struct *work; - - if (fp->bpf_func == sk_run_filter) - return; - work = (struct work_struct *)fp->bpf_func; - INIT_WORK(work, jit_free_defer); - schedule_work(work); -} diff --git a/trunk/arch/s390/oprofile/init.c b/trunk/arch/s390/oprofile/init.c index 584b93674ea4..a1e9d69a9c90 100644 --- a/trunk/arch/s390/oprofile/init.c +++ b/trunk/arch/s390/oprofile/init.c @@ -169,7 +169,7 @@ static ssize_t hw_interval_write(struct file *file, char const __user *buf, if (*offset) return -EINVAL; retval = oprofilefs_ulong_from_user(&val, buf, count); - if (retval <= 0) + if (retval) return retval; if (val < oprofile_min_interval) oprofile_hw_interval = oprofile_min_interval; @@ -212,7 +212,7 @@ static ssize_t hwsampler_zero_write(struct file *file, char const __user *buf, return -EINVAL; retval = oprofilefs_ulong_from_user(&val, buf, count); - if (retval <= 0) + if (retval) return retval; if (val != 0) return -EINVAL; @@ -243,7 +243,7 @@ static ssize_t hwsampler_kernel_write(struct file *file, char const __user *buf, return -EINVAL; retval = oprofilefs_ulong_from_user(&val, buf, count); - if (retval <= 0) + if (retval) return retval; if (val != 0 && val != 1) @@ -278,7 +278,7 @@ static ssize_t hwsampler_user_write(struct file *file, char const __user *buf, return -EINVAL; retval = oprofilefs_ulong_from_user(&val, buf, count); - if (retval <= 0) + if (retval) return retval; if (val != 0 && val != 1) @@ -317,7 +317,7 @@ static ssize_t timer_enabled_write(struct file *file, char const __user *buf, return -EINVAL; retval = oprofilefs_ulong_from_user(&val, buf, count); - if (retval <= 0) + if (retval) return retval; if (val != 0 && val != 1) diff --git a/trunk/arch/score/kernel/process.c b/trunk/arch/score/kernel/process.c index 637970cfd3f4..2707023c7563 100644 --- a/trunk/arch/score/kernel/process.c +++ b/trunk/arch/score/kernel/process.c @@ -27,7 +27,6 @@ #include #include #include -#include void (*pm_power_off)(void); EXPORT_SYMBOL(pm_power_off); @@ -51,10 +50,9 @@ void __noreturn cpu_idle(void) { /* endless idle loop with no priority at all */ while (1) { - rcu_idle_enter(); while (!need_resched()) barrier(); - rcu_idle_exit(); + schedule_preempt_disabled(); } } diff --git a/trunk/arch/sh/drivers/dma/dma-sh.c b/trunk/arch/sh/drivers/dma/dma-sh.c index b22565623142..4c171f13b0e8 100644 --- a/trunk/arch/sh/drivers/dma/dma-sh.c +++ b/trunk/arch/sh/drivers/dma/dma-sh.c @@ -335,7 +335,7 @@ static int dmae_irq_init(void) for (n = 0; n < NR_DMAE; n++) { int i = request_irq(get_dma_error_irq(n), dma_err, - IRQF_SHARED, dmae_name[n], (void *)dmae_name[n]); + IRQF_SHARED, dmae_name[n], NULL); if (unlikely(i < 0)) { printk(KERN_ERR "%s request_irq fail\n", dmae_name[n]); return i; diff --git a/trunk/arch/sh/drivers/pci/pci.c b/trunk/arch/sh/drivers/pci/pci.c index a7e078f2e2e4..40db2d0aef3f 100644 --- a/trunk/arch/sh/drivers/pci/pci.c +++ b/trunk/arch/sh/drivers/pci/pci.c @@ -192,6 +192,11 @@ int pcibios_enable_device(struct pci_dev *dev, int mask) return pci_enable_resources(dev, mask); } +void __init pcibios_update_irq(struct pci_dev *dev, int irq) +{ + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq); +} + static void __init pcibios_bus_report_status_early(struct pci_channel *hose, int top_bus, int current_bus, diff --git a/trunk/arch/sh/include/asm/sections.h b/trunk/arch/sh/include/asm/sections.h index 1b6199740e98..4a5350037c8f 100644 --- a/trunk/arch/sh/include/asm/sections.h +++ b/trunk/arch/sh/include/asm/sections.h @@ -6,6 +6,7 @@ extern long __nosave_begin, __nosave_end; extern long __machvec_start, __machvec_end; extern char __uncached_start, __uncached_end; +extern char _ebss[]; extern char __start_eh_frame[], __stop_eh_frame[]; #endif /* __ASM_SH_SECTIONS_H */ diff --git a/trunk/arch/sh/include/cpu-sh2a/cpu/sh7269.h b/trunk/arch/sh/include/cpu-sh2a/cpu/sh7269.h index 2a0ca8780f0d..48d14498e774 100644 --- a/trunk/arch/sh/include/cpu-sh2a/cpu/sh7269.h +++ b/trunk/arch/sh/include/cpu-sh2a/cpu/sh7269.h @@ -183,30 +183,18 @@ enum { GPIO_FN_DV_DATA1, GPIO_FN_DV_DATA0, GPIO_FN_LCD_CLK, GPIO_FN_LCD_EXTCLK, GPIO_FN_LCD_VSYNC, GPIO_FN_LCD_HSYNC, GPIO_FN_LCD_DE, - GPIO_FN_LCD_DATA23_PG23, GPIO_FN_LCD_DATA22_PG22, - GPIO_FN_LCD_DATA21_PG21, GPIO_FN_LCD_DATA20_PG20, - GPIO_FN_LCD_DATA19_PG19, GPIO_FN_LCD_DATA18_PG18, - GPIO_FN_LCD_DATA17_PG17, GPIO_FN_LCD_DATA16_PG16, - GPIO_FN_LCD_DATA15_PG15, GPIO_FN_LCD_DATA14_PG14, - GPIO_FN_LCD_DATA13_PG13, GPIO_FN_LCD_DATA12_PG12, - GPIO_FN_LCD_DATA11_PG11, GPIO_FN_LCD_DATA10_PG10, - GPIO_FN_LCD_DATA9_PG9, GPIO_FN_LCD_DATA8_PG8, - GPIO_FN_LCD_DATA7_PG7, GPIO_FN_LCD_DATA6_PG6, - GPIO_FN_LCD_DATA5_PG5, GPIO_FN_LCD_DATA4_PG4, - GPIO_FN_LCD_DATA3_PG3, GPIO_FN_LCD_DATA2_PG2, - GPIO_FN_LCD_DATA1_PG1, GPIO_FN_LCD_DATA0_PG0, - GPIO_FN_LCD_DATA23_PJ23, GPIO_FN_LCD_DATA22_PJ22, - GPIO_FN_LCD_DATA21_PJ21, GPIO_FN_LCD_DATA20_PJ20, - GPIO_FN_LCD_DATA19_PJ19, GPIO_FN_LCD_DATA18_PJ18, - GPIO_FN_LCD_DATA17_PJ17, GPIO_FN_LCD_DATA16_PJ16, - GPIO_FN_LCD_DATA15_PJ15, GPIO_FN_LCD_DATA14_PJ14, - GPIO_FN_LCD_DATA13_PJ13, GPIO_FN_LCD_DATA12_PJ12, - GPIO_FN_LCD_DATA11_PJ11, GPIO_FN_LCD_DATA10_PJ10, - GPIO_FN_LCD_DATA9_PJ9, GPIO_FN_LCD_DATA8_PJ8, - GPIO_FN_LCD_DATA7_PJ7, GPIO_FN_LCD_DATA6_PJ6, - GPIO_FN_LCD_DATA5_PJ5, GPIO_FN_LCD_DATA4_PJ4, - GPIO_FN_LCD_DATA3_PJ3, GPIO_FN_LCD_DATA2_PJ2, - GPIO_FN_LCD_DATA1_PJ1, GPIO_FN_LCD_DATA0_PJ0, + GPIO_FN_LCD_DATA23, GPIO_FN_LCD_DATA22, + GPIO_FN_LCD_DATA21, GPIO_FN_LCD_DATA20, + GPIO_FN_LCD_DATA19, GPIO_FN_LCD_DATA18, + GPIO_FN_LCD_DATA17, GPIO_FN_LCD_DATA16, + GPIO_FN_LCD_DATA15, GPIO_FN_LCD_DATA14, + GPIO_FN_LCD_DATA13, GPIO_FN_LCD_DATA12, + GPIO_FN_LCD_DATA11, GPIO_FN_LCD_DATA10, + GPIO_FN_LCD_DATA9, GPIO_FN_LCD_DATA8, + GPIO_FN_LCD_DATA7, GPIO_FN_LCD_DATA6, + GPIO_FN_LCD_DATA5, GPIO_FN_LCD_DATA4, + GPIO_FN_LCD_DATA3, GPIO_FN_LCD_DATA2, + GPIO_FN_LCD_DATA1, GPIO_FN_LCD_DATA0, GPIO_FN_LCD_M_DISP, }; diff --git a/trunk/arch/sh/kernel/cpu/sh2a/pinmux-sh7269.c b/trunk/arch/sh/kernel/cpu/sh2a/pinmux-sh7269.c index 039e4587dd9b..f25127c46eca 100644 --- a/trunk/arch/sh/kernel/cpu/sh2a/pinmux-sh7269.c +++ b/trunk/arch/sh/kernel/cpu/sh2a/pinmux-sh7269.c @@ -758,22 +758,12 @@ enum { DV_DATA3_MARK, DV_DATA2_MARK, DV_DATA1_MARK, DV_DATA0_MARK, LCD_CLK_MARK, LCD_EXTCLK_MARK, LCD_VSYNC_MARK, LCD_HSYNC_MARK, LCD_DE_MARK, - LCD_DATA23_PG23_MARK, LCD_DATA22_PG22_MARK, LCD_DATA21_PG21_MARK, - LCD_DATA20_PG20_MARK, LCD_DATA19_PG19_MARK, LCD_DATA18_PG18_MARK, - LCD_DATA17_PG17_MARK, LCD_DATA16_PG16_MARK, LCD_DATA15_PG15_MARK, - LCD_DATA14_PG14_MARK, LCD_DATA13_PG13_MARK, LCD_DATA12_PG12_MARK, - LCD_DATA11_PG11_MARK, LCD_DATA10_PG10_MARK, LCD_DATA9_PG9_MARK, - LCD_DATA8_PG8_MARK, LCD_DATA7_PG7_MARK, LCD_DATA6_PG6_MARK, - LCD_DATA5_PG5_MARK, LCD_DATA4_PG4_MARK, LCD_DATA3_PG3_MARK, - LCD_DATA2_PG2_MARK, LCD_DATA1_PG1_MARK, LCD_DATA0_PG0_MARK, - LCD_DATA23_PJ23_MARK, LCD_DATA22_PJ22_MARK, LCD_DATA21_PJ21_MARK, - LCD_DATA20_PJ20_MARK, LCD_DATA19_PJ19_MARK, LCD_DATA18_PJ18_MARK, - LCD_DATA17_PJ17_MARK, LCD_DATA16_PJ16_MARK, LCD_DATA15_PJ15_MARK, - LCD_DATA14_PJ14_MARK, LCD_DATA13_PJ13_MARK, LCD_DATA12_PJ12_MARK, - LCD_DATA11_PJ11_MARK, LCD_DATA10_PJ10_MARK, LCD_DATA9_PJ9_MARK, - LCD_DATA8_PJ8_MARK, LCD_DATA7_PJ7_MARK, LCD_DATA6_PJ6_MARK, - LCD_DATA5_PJ5_MARK, LCD_DATA4_PJ4_MARK, LCD_DATA3_PJ3_MARK, - LCD_DATA2_PJ2_MARK, LCD_DATA1_PJ1_MARK, LCD_DATA0_PJ0_MARK, + LCD_DATA23_MARK, LCD_DATA22_MARK, LCD_DATA21_MARK, LCD_DATA20_MARK, + LCD_DATA19_MARK, LCD_DATA18_MARK, LCD_DATA17_MARK, LCD_DATA16_MARK, + LCD_DATA15_MARK, LCD_DATA14_MARK, LCD_DATA13_MARK, LCD_DATA12_MARK, + LCD_DATA11_MARK, LCD_DATA10_MARK, LCD_DATA9_MARK, LCD_DATA8_MARK, + LCD_DATA7_MARK, LCD_DATA6_MARK, LCD_DATA5_MARK, LCD_DATA4_MARK, + LCD_DATA3_MARK, LCD_DATA2_MARK, LCD_DATA1_MARK, LCD_DATA0_MARK, LCD_TCON6_MARK, LCD_TCON5_MARK, LCD_TCON4_MARK, LCD_TCON3_MARK, LCD_TCON2_MARK, LCD_TCON1_MARK, LCD_TCON0_MARK, LCD_M_DISP_MARK, @@ -1046,7 +1036,6 @@ static pinmux_enum_t pinmux_data[] = { PINMUX_DATA(PF1_DATA, PF1MD_000), PINMUX_DATA(BACK_MARK, PF1MD_001), - PINMUX_DATA(SSL10_MARK, PF1MD_011), PINMUX_DATA(TIOC4B_MARK, PF1MD_100), PINMUX_DATA(DACK0_MARK, PF1MD_101), @@ -1060,50 +1049,47 @@ static pinmux_enum_t pinmux_data[] = { PINMUX_DATA(PG27_DATA, PG27MD_00), PINMUX_DATA(LCD_TCON2_MARK, PG27MD_10), PINMUX_DATA(LCD_EXTCLK_MARK, PG27MD_11), - PINMUX_DATA(LCD_DE_MARK, PG27MD_11), PINMUX_DATA(PG26_DATA, PG26MD_00), PINMUX_DATA(LCD_TCON1_MARK, PG26MD_10), - PINMUX_DATA(LCD_HSYNC_MARK, PG26MD_10), PINMUX_DATA(PG25_DATA, PG25MD_00), PINMUX_DATA(LCD_TCON0_MARK, PG25MD_10), - PINMUX_DATA(LCD_VSYNC_MARK, PG25MD_10), PINMUX_DATA(PG24_DATA, PG24MD_00), PINMUX_DATA(LCD_CLK_MARK, PG24MD_10), PINMUX_DATA(PG23_DATA, PG23MD_000), - PINMUX_DATA(LCD_DATA23_PG23_MARK, PG23MD_010), + PINMUX_DATA(LCD_DATA23_MARK, PG23MD_010), PINMUX_DATA(LCD_TCON6_MARK, PG23MD_011), PINMUX_DATA(TXD5_MARK, PG23MD_100), PINMUX_DATA(PG22_DATA, PG22MD_000), - PINMUX_DATA(LCD_DATA22_PG22_MARK, PG22MD_010), + PINMUX_DATA(LCD_DATA22_MARK, PG22MD_010), PINMUX_DATA(LCD_TCON5_MARK, PG22MD_011), PINMUX_DATA(RXD5_MARK, PG22MD_100), PINMUX_DATA(PG21_DATA, PG21MD_000), PINMUX_DATA(DV_DATA7_MARK, PG21MD_001), - PINMUX_DATA(LCD_DATA21_PG21_MARK, PG21MD_010), + PINMUX_DATA(LCD_DATA21_MARK, PG21MD_010), PINMUX_DATA(LCD_TCON4_MARK, PG21MD_011), PINMUX_DATA(TXD4_MARK, PG21MD_100), PINMUX_DATA(PG20_DATA, PG20MD_000), PINMUX_DATA(DV_DATA6_MARK, PG20MD_001), - PINMUX_DATA(LCD_DATA20_PG20_MARK, PG21MD_010), + PINMUX_DATA(LCD_DATA20_MARK, PG21MD_010), PINMUX_DATA(LCD_TCON3_MARK, PG20MD_011), PINMUX_DATA(RXD4_MARK, PG20MD_100), PINMUX_DATA(PG19_DATA, PG19MD_000), PINMUX_DATA(DV_DATA5_MARK, PG19MD_001), - PINMUX_DATA(LCD_DATA19_PG19_MARK, PG19MD_010), + PINMUX_DATA(LCD_DATA19_MARK, PG19MD_010), PINMUX_DATA(SPDIF_OUT_MARK, PG19MD_011), PINMUX_DATA(SCK5_MARK, PG19MD_100), PINMUX_DATA(PG18_DATA, PG18MD_000), PINMUX_DATA(DV_DATA4_MARK, PG18MD_001), - PINMUX_DATA(LCD_DATA18_PG18_MARK, PG18MD_010), + PINMUX_DATA(LCD_DATA18_MARK, PG18MD_010), PINMUX_DATA(SPDIF_IN_MARK, PG18MD_011), PINMUX_DATA(SCK4_MARK, PG18MD_100), @@ -1111,103 +1097,103 @@ static pinmux_enum_t pinmux_data[] = { // we're going with 2 bits PINMUX_DATA(PG17_DATA, PG17MD_00), PINMUX_DATA(WE3ICIOWRAHDQMUU_MARK, PG17MD_01), - PINMUX_DATA(LCD_DATA17_PG17_MARK, PG17MD_10), + PINMUX_DATA(LCD_DATA17_MARK, PG17MD_10), // TODO hardware manual has PG16 3 bits wide in reg picture and 2 bits in description // we're going with 2 bits PINMUX_DATA(PG16_DATA, PG16MD_00), PINMUX_DATA(WE2ICIORDDQMUL_MARK, PG16MD_01), - PINMUX_DATA(LCD_DATA16_PG16_MARK, PG16MD_10), + PINMUX_DATA(LCD_DATA16_MARK, PG16MD_10), PINMUX_DATA(PG15_DATA, PG15MD_00), PINMUX_DATA(D31_MARK, PG15MD_01), - PINMUX_DATA(LCD_DATA15_PG15_MARK, PG15MD_10), + PINMUX_DATA(LCD_DATA15_MARK, PG15MD_10), PINMUX_DATA(PINT7_PG_MARK, PG15MD_11), PINMUX_DATA(PG14_DATA, PG14MD_00), PINMUX_DATA(D30_MARK, PG14MD_01), - PINMUX_DATA(LCD_DATA14_PG14_MARK, PG14MD_10), + PINMUX_DATA(LCD_DATA14_MARK, PG14MD_10), PINMUX_DATA(PINT6_PG_MARK, PG14MD_11), PINMUX_DATA(PG13_DATA, PG13MD_00), PINMUX_DATA(D29_MARK, PG13MD_01), - PINMUX_DATA(LCD_DATA13_PG13_MARK, PG13MD_10), + PINMUX_DATA(LCD_DATA13_MARK, PG13MD_10), PINMUX_DATA(PINT5_PG_MARK, PG13MD_11), PINMUX_DATA(PG12_DATA, PG12MD_00), PINMUX_DATA(D28_MARK, PG12MD_01), - PINMUX_DATA(LCD_DATA12_PG12_MARK, PG12MD_10), + PINMUX_DATA(LCD_DATA12_MARK, PG12MD_10), PINMUX_DATA(PINT4_PG_MARK, PG12MD_11), PINMUX_DATA(PG11_DATA, PG11MD_000), PINMUX_DATA(D27_MARK, PG11MD_001), - PINMUX_DATA(LCD_DATA11_PG11_MARK, PG11MD_010), + PINMUX_DATA(LCD_DATA11_MARK, PG11MD_010), PINMUX_DATA(PINT3_PG_MARK, PG11MD_011), PINMUX_DATA(TIOC3D_MARK, PG11MD_100), PINMUX_DATA(PG10_DATA, PG10MD_000), PINMUX_DATA(D26_MARK, PG10MD_001), - PINMUX_DATA(LCD_DATA10_PG10_MARK, PG10MD_010), + PINMUX_DATA(LCD_DATA10_MARK, PG10MD_010), PINMUX_DATA(PINT2_PG_MARK, PG10MD_011), PINMUX_DATA(TIOC3C_MARK, PG10MD_100), PINMUX_DATA(PG9_DATA, PG9MD_000), PINMUX_DATA(D25_MARK, PG9MD_001), - PINMUX_DATA(LCD_DATA9_PG9_MARK, PG9MD_010), + PINMUX_DATA(LCD_DATA9_MARK, PG9MD_010), PINMUX_DATA(PINT1_PG_MARK, PG9MD_011), PINMUX_DATA(TIOC3B_MARK, PG9MD_100), PINMUX_DATA(PG8_DATA, PG8MD_000), PINMUX_DATA(D24_MARK, PG8MD_001), - PINMUX_DATA(LCD_DATA8_PG8_MARK, PG8MD_010), + PINMUX_DATA(LCD_DATA8_MARK, PG8MD_010), PINMUX_DATA(PINT0_PG_MARK, PG8MD_011), PINMUX_DATA(TIOC3A_MARK, PG8MD_100), PINMUX_DATA(PG7_DATA, PG7MD_000), PINMUX_DATA(D23_MARK, PG7MD_001), - PINMUX_DATA(LCD_DATA7_PG7_MARK, PG7MD_010), + PINMUX_DATA(LCD_DATA7_MARK, PG7MD_010), PINMUX_DATA(IRQ7_PG_MARK, PG7MD_011), PINMUX_DATA(TIOC2B_MARK, PG7MD_100), PINMUX_DATA(PG6_DATA, PG6MD_000), PINMUX_DATA(D22_MARK, PG6MD_001), - PINMUX_DATA(LCD_DATA6_PG6_MARK, PG6MD_010), + PINMUX_DATA(LCD_DATA6_MARK, PG6MD_010), PINMUX_DATA(IRQ6_PG_MARK, PG6MD_011), PINMUX_DATA(TIOC2A_MARK, PG6MD_100), PINMUX_DATA(PG5_DATA, PG5MD_000), PINMUX_DATA(D21_MARK, PG5MD_001), - PINMUX_DATA(LCD_DATA5_PG5_MARK, PG5MD_010), + PINMUX_DATA(LCD_DATA5_MARK, PG5MD_010), PINMUX_DATA(IRQ5_PG_MARK, PG5MD_011), PINMUX_DATA(TIOC1B_MARK, PG5MD_100), PINMUX_DATA(PG4_DATA, PG4MD_000), PINMUX_DATA(D20_MARK, PG4MD_001), - PINMUX_DATA(LCD_DATA4_PG4_MARK, PG4MD_010), + PINMUX_DATA(LCD_DATA4_MARK, PG4MD_010), PINMUX_DATA(IRQ4_PG_MARK, PG4MD_011), PINMUX_DATA(TIOC1A_MARK, PG4MD_100), PINMUX_DATA(PG3_DATA, PG3MD_000), PINMUX_DATA(D19_MARK, PG3MD_001), - PINMUX_DATA(LCD_DATA3_PG3_MARK, PG3MD_010), + PINMUX_DATA(LCD_DATA3_MARK, PG3MD_010), PINMUX_DATA(IRQ3_PG_MARK, PG3MD_011), PINMUX_DATA(TIOC0D_MARK, PG3MD_100), PINMUX_DATA(PG2_DATA, PG2MD_000), PINMUX_DATA(D18_MARK, PG2MD_001), - PINMUX_DATA(LCD_DATA2_PG2_MARK, PG2MD_010), + PINMUX_DATA(LCD_DATA2_MARK, PG2MD_010), PINMUX_DATA(IRQ2_PG_MARK, PG2MD_011), PINMUX_DATA(TIOC0C_MARK, PG2MD_100), PINMUX_DATA(PG1_DATA, PG1MD_000), PINMUX_DATA(D17_MARK, PG1MD_001), - PINMUX_DATA(LCD_DATA1_PG1_MARK, PG1MD_010), + PINMUX_DATA(LCD_DATA1_MARK, PG1MD_010), PINMUX_DATA(IRQ1_PG_MARK, PG1MD_011), PINMUX_DATA(TIOC0B_MARK, PG1MD_100), PINMUX_DATA(PG0_DATA, PG0MD_000), PINMUX_DATA(D16_MARK, PG0MD_001), - PINMUX_DATA(LCD_DATA0_PG0_MARK, PG0MD_010), + PINMUX_DATA(LCD_DATA0_MARK, PG0MD_010), PINMUX_DATA(IRQ0_PG_MARK, PG0MD_011), PINMUX_DATA(TIOC0A_MARK, PG0MD_100), @@ -1289,14 +1275,14 @@ static pinmux_enum_t pinmux_data[] = { PINMUX_DATA(PJ23_DATA, PJ23MD_000), PINMUX_DATA(DV_DATA23_MARK, PJ23MD_001), - PINMUX_DATA(LCD_DATA23_PJ23_MARK, PJ23MD_010), + PINMUX_DATA(LCD_DATA23_MARK, PJ23MD_010), PINMUX_DATA(LCD_TCON6_MARK, PJ23MD_011), PINMUX_DATA(IRQ3_PJ_MARK, PJ23MD_100), PINMUX_DATA(CTX1_MARK, PJ23MD_101), PINMUX_DATA(PJ22_DATA, PJ22MD_000), PINMUX_DATA(DV_DATA22_MARK, PJ22MD_001), - PINMUX_DATA(LCD_DATA22_PJ22_MARK, PJ22MD_010), + PINMUX_DATA(LCD_DATA22_MARK, PJ22MD_010), PINMUX_DATA(LCD_TCON5_MARK, PJ22MD_011), PINMUX_DATA(IRQ2_PJ_MARK, PJ22MD_100), PINMUX_DATA(CRX1_MARK, PJ22MD_101), @@ -1304,14 +1290,14 @@ static pinmux_enum_t pinmux_data[] = { PINMUX_DATA(PJ21_DATA, PJ21MD_000), PINMUX_DATA(DV_DATA21_MARK, PJ21MD_001), - PINMUX_DATA(LCD_DATA21_PJ21_MARK, PJ21MD_010), + PINMUX_DATA(LCD_DATA21_MARK, PJ21MD_010), PINMUX_DATA(LCD_TCON4_MARK, PJ21MD_011), PINMUX_DATA(IRQ1_PJ_MARK, PJ21MD_100), PINMUX_DATA(CTX2_MARK, PJ21MD_101), PINMUX_DATA(PJ20_DATA, PJ20MD_000), PINMUX_DATA(DV_DATA20_MARK, PJ20MD_001), - PINMUX_DATA(LCD_DATA20_PJ20_MARK, PJ20MD_010), + PINMUX_DATA(LCD_DATA20_MARK, PJ20MD_010), PINMUX_DATA(LCD_TCON3_MARK, PJ20MD_011), PINMUX_DATA(IRQ0_PJ_MARK, PJ20MD_100), PINMUX_DATA(CRX2_MARK, PJ20MD_101), @@ -1319,7 +1305,7 @@ static pinmux_enum_t pinmux_data[] = { PINMUX_DATA(PJ19_DATA, PJ19MD_000), PINMUX_DATA(DV_DATA19_MARK, PJ19MD_001), - PINMUX_DATA(LCD_DATA19_PJ19_MARK, PJ19MD_010), + PINMUX_DATA(LCD_DATA19_MARK, PJ19MD_010), PINMUX_DATA(MISO0_PJ19_MARK, PJ19MD_011), PINMUX_DATA(TIOC0D_MARK, PJ19MD_100), PINMUX_DATA(SIOFRXD_MARK, PJ19MD_101), @@ -1327,126 +1313,126 @@ static pinmux_enum_t pinmux_data[] = { PINMUX_DATA(PJ18_DATA, PJ18MD_000), PINMUX_DATA(DV_DATA18_MARK, PJ18MD_001), - PINMUX_DATA(LCD_DATA18_PJ18_MARK, PJ18MD_010), + PINMUX_DATA(LCD_DATA18_MARK, PJ18MD_010), PINMUX_DATA(MOSI0_PJ18_MARK, PJ18MD_011), PINMUX_DATA(TIOC0C_MARK, PJ18MD_100), PINMUX_DATA(SIOFTXD_MARK, PJ18MD_101), PINMUX_DATA(PJ17_DATA, PJ17MD_000), PINMUX_DATA(DV_DATA17_MARK, PJ17MD_001), - PINMUX_DATA(LCD_DATA17_PJ17_MARK, PJ17MD_010), + PINMUX_DATA(LCD_DATA17_MARK, PJ17MD_010), PINMUX_DATA(SSL00_PJ17_MARK, PJ17MD_011), PINMUX_DATA(TIOC0B_MARK, PJ17MD_100), PINMUX_DATA(SIOFSYNC_MARK, PJ17MD_101), PINMUX_DATA(PJ16_DATA, PJ16MD_000), PINMUX_DATA(DV_DATA16_MARK, PJ16MD_001), - PINMUX_DATA(LCD_DATA16_PJ16_MARK, PJ16MD_010), + PINMUX_DATA(LCD_DATA16_MARK, PJ16MD_010), PINMUX_DATA(RSPCK0_PJ16_MARK, PJ16MD_011), PINMUX_DATA(TIOC0A_MARK, PJ16MD_100), PINMUX_DATA(SIOFSCK_MARK, PJ16MD_101), PINMUX_DATA(PJ15_DATA, PJ15MD_000), PINMUX_DATA(DV_DATA15_MARK, PJ15MD_001), - PINMUX_DATA(LCD_DATA15_PJ15_MARK, PJ15MD_010), + PINMUX_DATA(LCD_DATA15_MARK, PJ15MD_010), PINMUX_DATA(PINT7_PJ_MARK, PJ15MD_011), PINMUX_DATA(PWM2H_MARK, PJ15MD_100), PINMUX_DATA(TXD7_MARK, PJ15MD_101), PINMUX_DATA(PJ14_DATA, PJ14MD_000), PINMUX_DATA(DV_DATA14_MARK, PJ14MD_001), - PINMUX_DATA(LCD_DATA14_PJ14_MARK, PJ14MD_010), + PINMUX_DATA(LCD_DATA14_MARK, PJ14MD_010), PINMUX_DATA(PINT6_PJ_MARK, PJ14MD_011), PINMUX_DATA(PWM2G_MARK, PJ14MD_100), PINMUX_DATA(TXD6_MARK, PJ14MD_101), PINMUX_DATA(PJ13_DATA, PJ13MD_000), PINMUX_DATA(DV_DATA13_MARK, PJ13MD_001), - PINMUX_DATA(LCD_DATA13_PJ13_MARK, PJ13MD_010), + PINMUX_DATA(LCD_DATA13_MARK, PJ13MD_010), PINMUX_DATA(PINT5_PJ_MARK, PJ13MD_011), PINMUX_DATA(PWM2F_MARK, PJ13MD_100), PINMUX_DATA(TXD5_MARK, PJ13MD_101), PINMUX_DATA(PJ12_DATA, PJ12MD_000), PINMUX_DATA(DV_DATA12_MARK, PJ12MD_001), - PINMUX_DATA(LCD_DATA12_PJ12_MARK, PJ12MD_010), + PINMUX_DATA(LCD_DATA12_MARK, PJ12MD_010), PINMUX_DATA(PINT4_PJ_MARK, PJ12MD_011), PINMUX_DATA(PWM2E_MARK, PJ12MD_100), PINMUX_DATA(SCK7_MARK, PJ12MD_101), PINMUX_DATA(PJ11_DATA, PJ11MD_000), PINMUX_DATA(DV_DATA11_MARK, PJ11MD_001), - PINMUX_DATA(LCD_DATA11_PJ11_MARK, PJ11MD_010), + PINMUX_DATA(LCD_DATA11_MARK, PJ11MD_010), PINMUX_DATA(PINT3_PJ_MARK, PJ11MD_011), PINMUX_DATA(PWM2D_MARK, PJ11MD_100), PINMUX_DATA(SCK6_MARK, PJ11MD_101), PINMUX_DATA(PJ10_DATA, PJ10MD_000), PINMUX_DATA(DV_DATA10_MARK, PJ10MD_001), - PINMUX_DATA(LCD_DATA10_PJ10_MARK, PJ10MD_010), + PINMUX_DATA(LCD_DATA10_MARK, PJ10MD_010), PINMUX_DATA(PINT2_PJ_MARK, PJ10MD_011), PINMUX_DATA(PWM2C_MARK, PJ10MD_100), PINMUX_DATA(SCK5_MARK, PJ10MD_101), PINMUX_DATA(PJ9_DATA, PJ9MD_000), PINMUX_DATA(DV_DATA9_MARK, PJ9MD_001), - PINMUX_DATA(LCD_DATA9_PJ9_MARK, PJ9MD_010), + PINMUX_DATA(LCD_DATA9_MARK, PJ9MD_010), PINMUX_DATA(PINT1_PJ_MARK, PJ9MD_011), PINMUX_DATA(PWM2B_MARK, PJ9MD_100), PINMUX_DATA(RTS5_MARK, PJ9MD_101), PINMUX_DATA(PJ8_DATA, PJ8MD_000), PINMUX_DATA(DV_DATA8_MARK, PJ8MD_001), - PINMUX_DATA(LCD_DATA8_PJ8_MARK, PJ8MD_010), + PINMUX_DATA(LCD_DATA8_MARK, PJ8MD_010), PINMUX_DATA(PINT0_PJ_MARK, PJ8MD_011), PINMUX_DATA(PWM2A_MARK, PJ8MD_100), PINMUX_DATA(CTS5_MARK, PJ8MD_101), PINMUX_DATA(PJ7_DATA, PJ7MD_000), PINMUX_DATA(DV_DATA7_MARK, PJ7MD_001), - PINMUX_DATA(LCD_DATA7_PJ7_MARK, PJ7MD_010), + PINMUX_DATA(LCD_DATA7_MARK, PJ7MD_010), PINMUX_DATA(SD_D2_MARK, PJ7MD_011), PINMUX_DATA(PWM1H_MARK, PJ7MD_100), PINMUX_DATA(PJ6_DATA, PJ6MD_000), PINMUX_DATA(DV_DATA6_MARK, PJ6MD_001), - PINMUX_DATA(LCD_DATA6_PJ6_MARK, PJ6MD_010), + PINMUX_DATA(LCD_DATA6_MARK, PJ6MD_010), PINMUX_DATA(SD_D3_MARK, PJ6MD_011), PINMUX_DATA(PWM1G_MARK, PJ6MD_100), PINMUX_DATA(PJ5_DATA, PJ5MD_000), PINMUX_DATA(DV_DATA5_MARK, PJ5MD_001), - PINMUX_DATA(LCD_DATA5_PJ5_MARK, PJ5MD_010), + PINMUX_DATA(LCD_DATA5_MARK, PJ5MD_010), PINMUX_DATA(SD_CMD_MARK, PJ5MD_011), PINMUX_DATA(PWM1F_MARK, PJ5MD_100), PINMUX_DATA(PJ4_DATA, PJ4MD_000), PINMUX_DATA(DV_DATA4_MARK, PJ4MD_001), - PINMUX_DATA(LCD_DATA4_PJ4_MARK, PJ4MD_010), + PINMUX_DATA(LCD_DATA4_MARK, PJ4MD_010), PINMUX_DATA(SD_CLK_MARK, PJ4MD_011), PINMUX_DATA(PWM1E_MARK, PJ4MD_100), PINMUX_DATA(PJ3_DATA, PJ3MD_000), PINMUX_DATA(DV_DATA3_MARK, PJ3MD_001), - PINMUX_DATA(LCD_DATA3_PJ3_MARK, PJ3MD_010), + PINMUX_DATA(LCD_DATA3_MARK, PJ3MD_010), PINMUX_DATA(SD_D0_MARK, PJ3MD_011), PINMUX_DATA(PWM1D_MARK, PJ3MD_100), PINMUX_DATA(PJ2_DATA, PJ2MD_000), PINMUX_DATA(DV_DATA2_MARK, PJ2MD_001), - PINMUX_DATA(LCD_DATA2_PJ2_MARK, PJ2MD_010), + PINMUX_DATA(LCD_DATA2_MARK, PJ2MD_010), PINMUX_DATA(SD_D1_MARK, PJ2MD_011), PINMUX_DATA(PWM1C_MARK, PJ2MD_100), PINMUX_DATA(PJ1_DATA, PJ1MD_000), PINMUX_DATA(DV_DATA1_MARK, PJ1MD_001), - PINMUX_DATA(LCD_DATA1_PJ1_MARK, PJ1MD_010), + PINMUX_DATA(LCD_DATA1_MARK, PJ1MD_010), PINMUX_DATA(SD_WP_MARK, PJ1MD_011), PINMUX_DATA(PWM1B_MARK, PJ1MD_100), PINMUX_DATA(PJ0_DATA, PJ0MD_000), PINMUX_DATA(DV_DATA0_MARK, PJ0MD_001), - PINMUX_DATA(LCD_DATA0_PJ0_MARK, PJ0MD_010), + PINMUX_DATA(LCD_DATA0_MARK, PJ0MD_010), PINMUX_DATA(SD_CD_MARK, PJ0MD_011), PINMUX_DATA(PWM1A_MARK, PJ0MD_100), }; @@ -1891,55 +1877,30 @@ static struct pinmux_gpio pinmux_gpios[] = { PINMUX_GPIO(GPIO_FN_LCD_HSYNC, LCD_HSYNC_MARK), PINMUX_GPIO(GPIO_FN_LCD_DE, LCD_DE_MARK), - PINMUX_GPIO(GPIO_FN_LCD_DATA23_PG23, LCD_DATA23_PG23_MARK), - PINMUX_GPIO(GPIO_FN_LCD_DATA22_PG22, LCD_DATA22_PG22_MARK), - PINMUX_GPIO(GPIO_FN_LCD_DATA21_PG21, LCD_DATA21_PG21_MARK), - PINMUX_GPIO(GPIO_FN_LCD_DATA20_PG20, LCD_DATA20_PG20_MARK), - PINMUX_GPIO(GPIO_FN_LCD_DATA19_PG19, LCD_DATA19_PG19_MARK), - PINMUX_GPIO(GPIO_FN_LCD_DATA18_PG18, LCD_DATA18_PG18_MARK), - PINMUX_GPIO(GPIO_FN_LCD_DATA17_PG17, LCD_DATA17_PG17_MARK), - PINMUX_GPIO(GPIO_FN_LCD_DATA16_PG16, LCD_DATA16_PG16_MARK), - PINMUX_GPIO(GPIO_FN_LCD_DATA15_PG15, LCD_DATA15_PG15_MARK), - PINMUX_GPIO(GPIO_FN_LCD_DATA14_PG14, LCD_DATA14_PG14_MARK), - PINMUX_GPIO(GPIO_FN_LCD_DATA13_PG13, LCD_DATA13_PG13_MARK), - PINMUX_GPIO(GPIO_FN_LCD_DATA12_PG12, LCD_DATA12_PG12_MARK), - PINMUX_GPIO(GPIO_FN_LCD_DATA11_PG11, LCD_DATA11_PG11_MARK), - PINMUX_GPIO(GPIO_FN_LCD_DATA10_PG10, LCD_DATA10_PG10_MARK), - PINMUX_GPIO(GPIO_FN_LCD_DATA9_PG9, LCD_DATA9_PG9_MARK), - PINMUX_GPIO(GPIO_FN_LCD_DATA8_PG8, LCD_DATA8_PG8_MARK), - PINMUX_GPIO(GPIO_FN_LCD_DATA7_PG7, LCD_DATA7_PG7_MARK), - PINMUX_GPIO(GPIO_FN_LCD_DATA6_PG6, LCD_DATA6_PG6_MARK), - PINMUX_GPIO(GPIO_FN_LCD_DATA5_PG5, LCD_DATA5_PG5_MARK), - PINMUX_GPIO(GPIO_FN_LCD_DATA4_PG4, LCD_DATA4_PG4_MARK), - PINMUX_GPIO(GPIO_FN_LCD_DATA3_PG3, LCD_DATA3_PG3_MARK), - PINMUX_GPIO(GPIO_FN_LCD_DATA2_PG2, LCD_DATA2_PG2_MARK), - PINMUX_GPIO(GPIO_FN_LCD_DATA1_PG1, LCD_DATA1_PG1_MARK), - PINMUX_GPIO(GPIO_FN_LCD_DATA0_PG0, LCD_DATA0_PG0_MARK), - - PINMUX_GPIO(GPIO_FN_LCD_DATA23_PJ23, LCD_DATA23_PJ23_MARK), - PINMUX_GPIO(GPIO_FN_LCD_DATA22_PJ22, LCD_DATA22_PJ22_MARK), - PINMUX_GPIO(GPIO_FN_LCD_DATA21_PJ21, LCD_DATA21_PJ21_MARK), - PINMUX_GPIO(GPIO_FN_LCD_DATA20_PJ20, LCD_DATA20_PJ20_MARK), - PINMUX_GPIO(GPIO_FN_LCD_DATA19_PJ19, LCD_DATA19_PJ19_MARK), - PINMUX_GPIO(GPIO_FN_LCD_DATA18_PJ18, LCD_DATA18_PJ18_MARK), - PINMUX_GPIO(GPIO_FN_LCD_DATA17_PJ17, LCD_DATA17_PJ17_MARK), - PINMUX_GPIO(GPIO_FN_LCD_DATA16_PJ16, LCD_DATA16_PJ16_MARK), - PINMUX_GPIO(GPIO_FN_LCD_DATA15_PJ15, LCD_DATA15_PJ15_MARK), - PINMUX_GPIO(GPIO_FN_LCD_DATA14_PJ14, LCD_DATA14_PJ14_MARK), - PINMUX_GPIO(GPIO_FN_LCD_DATA13_PJ13, LCD_DATA13_PJ13_MARK), - PINMUX_GPIO(GPIO_FN_LCD_DATA12_PJ12, LCD_DATA12_PJ12_MARK), - PINMUX_GPIO(GPIO_FN_LCD_DATA11_PJ11, LCD_DATA11_PJ11_MARK), - PINMUX_GPIO(GPIO_FN_LCD_DATA10_PJ10, LCD_DATA10_PJ10_MARK), - PINMUX_GPIO(GPIO_FN_LCD_DATA9_PJ9, LCD_DATA9_PJ9_MARK), - PINMUX_GPIO(GPIO_FN_LCD_DATA8_PJ8, LCD_DATA8_PJ8_MARK), - PINMUX_GPIO(GPIO_FN_LCD_DATA7_PJ7, LCD_DATA7_PJ7_MARK), - PINMUX_GPIO(GPIO_FN_LCD_DATA6_PJ6, LCD_DATA6_PJ6_MARK), - PINMUX_GPIO(GPIO_FN_LCD_DATA5_PJ5, LCD_DATA5_PJ5_MARK), - PINMUX_GPIO(GPIO_FN_LCD_DATA4_PJ4, LCD_DATA4_PJ4_MARK), - PINMUX_GPIO(GPIO_FN_LCD_DATA3_PJ3, LCD_DATA3_PJ3_MARK), - PINMUX_GPIO(GPIO_FN_LCD_DATA2_PJ2, LCD_DATA2_PJ2_MARK), - PINMUX_GPIO(GPIO_FN_LCD_DATA1_PJ1, LCD_DATA1_PJ1_MARK), - PINMUX_GPIO(GPIO_FN_LCD_DATA0_PJ0, LCD_DATA0_PJ0_MARK), + PINMUX_GPIO(GPIO_FN_LCD_DATA23, LCD_DATA23_MARK), + PINMUX_GPIO(GPIO_FN_LCD_DATA22, LCD_DATA22_MARK), + PINMUX_GPIO(GPIO_FN_LCD_DATA21, LCD_DATA21_MARK), + PINMUX_GPIO(GPIO_FN_LCD_DATA20, LCD_DATA20_MARK), + PINMUX_GPIO(GPIO_FN_LCD_DATA19, LCD_DATA19_MARK), + PINMUX_GPIO(GPIO_FN_LCD_DATA18, LCD_DATA18_MARK), + PINMUX_GPIO(GPIO_FN_LCD_DATA17, LCD_DATA17_MARK), + PINMUX_GPIO(GPIO_FN_LCD_DATA16, LCD_DATA16_MARK), + PINMUX_GPIO(GPIO_FN_LCD_DATA15, LCD_DATA15_MARK), + PINMUX_GPIO(GPIO_FN_LCD_DATA14, LCD_DATA14_MARK), + PINMUX_GPIO(GPIO_FN_LCD_DATA13, LCD_DATA13_MARK), + PINMUX_GPIO(GPIO_FN_LCD_DATA12, LCD_DATA12_MARK), + PINMUX_GPIO(GPIO_FN_LCD_DATA11, LCD_DATA11_MARK), + PINMUX_GPIO(GPIO_FN_LCD_DATA10, LCD_DATA10_MARK), + PINMUX_GPIO(GPIO_FN_LCD_DATA9, LCD_DATA9_MARK), + PINMUX_GPIO(GPIO_FN_LCD_DATA8, LCD_DATA8_MARK), + PINMUX_GPIO(GPIO_FN_LCD_DATA7, LCD_DATA7_MARK), + PINMUX_GPIO(GPIO_FN_LCD_DATA6, LCD_DATA6_MARK), + PINMUX_GPIO(GPIO_FN_LCD_DATA5, LCD_DATA5_MARK), + PINMUX_GPIO(GPIO_FN_LCD_DATA4, LCD_DATA4_MARK), + PINMUX_GPIO(GPIO_FN_LCD_DATA3, LCD_DATA3_MARK), + PINMUX_GPIO(GPIO_FN_LCD_DATA2, LCD_DATA2_MARK), + PINMUX_GPIO(GPIO_FN_LCD_DATA1, LCD_DATA1_MARK), + PINMUX_GPIO(GPIO_FN_LCD_DATA0, LCD_DATA0_MARK), PINMUX_GPIO(GPIO_FN_LCD_M_DISP, LCD_M_DISP_MARK), }; diff --git a/trunk/arch/sh/kernel/cpu/sh5/entry.S b/trunk/arch/sh/kernel/cpu/sh5/entry.S index 7e605b95592a..b7cf6a547f11 100644 --- a/trunk/arch/sh/kernel/cpu/sh5/entry.S +++ b/trunk/arch/sh/kernel/cpu/sh5/entry.S @@ -933,7 +933,7 @@ ret_with_reschedule: pta restore_all, tr1 - movi (_TIF_SIGPENDING|_TIF_NOTIFY_RESUME), r8 + movi _TIF_SIGPENDING, r8 and r8, r7, r8 pta work_notifysig, tr0 bne r8, ZERO, tr0 diff --git a/trunk/arch/sh/kernel/entry-common.S b/trunk/arch/sh/kernel/entry-common.S index b96489d8b27d..f67601cb3f1f 100644 --- a/trunk/arch/sh/kernel/entry-common.S +++ b/trunk/arch/sh/kernel/entry-common.S @@ -139,7 +139,7 @@ work_pending: ! r8: current_thread_info ! t: result of "tst #_TIF_NEED_RESCHED, r0" bf/s work_resched - tst #(_TIF_SIGPENDING | _TIF_NOTIFY_RESUME), r0 + tst #_TIF_SIGPENDING, r0 work_notifysig: bt/s __restore_all mov r15, r4 diff --git a/trunk/arch/sh/kernel/setup.c b/trunk/arch/sh/kernel/setup.c index ebe7a7d97215..7b57bf1dc855 100644 --- a/trunk/arch/sh/kernel/setup.c +++ b/trunk/arch/sh/kernel/setup.c @@ -273,7 +273,7 @@ void __init setup_arch(char **cmdline_p) data_resource.start = virt_to_phys(_etext); data_resource.end = virt_to_phys(_edata)-1; bss_resource.start = virt_to_phys(__bss_start); - bss_resource.end = virt_to_phys(__bss_stop)-1; + bss_resource.end = virt_to_phys(_ebss)-1; #ifdef CONFIG_CMDLINE_OVERWRITE strlcpy(command_line, CONFIG_CMDLINE, sizeof(command_line)); diff --git a/trunk/arch/sh/kernel/sh_ksyms_32.c b/trunk/arch/sh/kernel/sh_ksyms_32.c index 2a0a596ebf67..3896f26efa4a 100644 --- a/trunk/arch/sh/kernel/sh_ksyms_32.c +++ b/trunk/arch/sh/kernel/sh_ksyms_32.c @@ -19,6 +19,7 @@ EXPORT_SYMBOL(csum_partial); EXPORT_SYMBOL(csum_partial_copy_generic); EXPORT_SYMBOL(copy_page); EXPORT_SYMBOL(__clear_user); +EXPORT_SYMBOL(_ebss); EXPORT_SYMBOL(empty_zero_page); #define DECLARE_EXPORT(name) \ diff --git a/trunk/arch/sh/kernel/vmlinux.lds.S b/trunk/arch/sh/kernel/vmlinux.lds.S index db88cbf9eafd..c98905f71e28 100644 --- a/trunk/arch/sh/kernel/vmlinux.lds.S +++ b/trunk/arch/sh/kernel/vmlinux.lds.S @@ -78,6 +78,7 @@ SECTIONS . = ALIGN(PAGE_SIZE); __init_end = .; BSS_SECTION(0, PAGE_SIZE, 4) + _ebss = .; /* uClinux MTD sucks */ _end = . ; STABS_DEBUG diff --git a/trunk/arch/sh/lib/mcount.S b/trunk/arch/sh/lib/mcount.S index 60164e65d665..84a57761f17e 100644 --- a/trunk/arch/sh/lib/mcount.S +++ b/trunk/arch/sh/lib/mcount.S @@ -39,7 +39,7 @@ * * Make sure the stack pointer contains a valid address. Valid * addresses for kernel stacks are anywhere after the bss - * (after __bss_stop) and anywhere in init_thread_union (init_stack). + * (after _ebss) and anywhere in init_thread_union (init_stack). */ #define STACK_CHECK() \ mov #(THREAD_SIZE >> 10), r0; \ @@ -60,7 +60,7 @@ cmp/hi r2, r1; \ bf stack_panic; \ \ - /* If sp > __bss_stop then we're OK. */ \ + /* If sp > _ebss then we're OK. */ \ mov.l .L_ebss, r1; \ cmp/hi r1, r15; \ bt 1f; \ @@ -70,7 +70,7 @@ cmp/hs r1, r15; \ bf stack_panic; \ \ - /* If sp > init_stack && sp < __bss_stop, not OK. */ \ + /* If sp > init_stack && sp < _ebss, not OK. */ \ add r0, r1; \ cmp/hs r1, r15; \ bt stack_panic; \ @@ -292,6 +292,8 @@ stack_panic: nop .align 2 +.L_ebss: + .long _ebss .L_init_thread_union: .long init_thread_union .Lpanic: diff --git a/trunk/arch/sparc/kernel/leon_pci.c b/trunk/arch/sparc/kernel/leon_pci.c index fc0521161568..21dcda75a520 100644 --- a/trunk/arch/sparc/kernel/leon_pci.c +++ b/trunk/arch/sparc/kernel/leon_pci.c @@ -102,6 +102,15 @@ int pcibios_enable_device(struct pci_dev *dev, int mask) return pci_enable_resources(dev, mask); } +void __devinit pcibios_update_irq(struct pci_dev *dev, int irq) +{ +#ifdef CONFIG_PCI_DEBUG + printk(KERN_DEBUG "LEONPCI: Assigning IRQ %02d to %s\n", irq, + pci_name(dev)); +#endif + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq); +} + /* in/out routines taken from pcic.c * * This probably belongs here rather than ioport.c because diff --git a/trunk/arch/sparc/kernel/module.c b/trunk/arch/sparc/kernel/module.c index f1ddc0d23679..15e0a1693976 100644 --- a/trunk/arch/sparc/kernel/module.c +++ b/trunk/arch/sparc/kernel/module.c @@ -48,7 +48,9 @@ void *module_alloc(unsigned long size) return NULL; ret = module_map(size); - if (ret) + if (!ret) + ret = ERR_PTR(-ENOMEM); + else memset(ret, 0, size); return ret; @@ -114,10 +116,6 @@ int apply_relocate_add(Elf_Shdr *sechdrs, v = sym->st_value + rel[i].r_addend; switch (ELF_R_TYPE(rel[i].r_info) & 0xff) { - case R_SPARC_DISP32: - v -= (Elf_Addr) location; - *loc32 = v; - break; #ifdef CONFIG_SPARC64 case R_SPARC_64: location[0] = v >> 56; @@ -130,6 +128,11 @@ int apply_relocate_add(Elf_Shdr *sechdrs, location[7] = v >> 0; break; + case R_SPARC_DISP32: + v -= (Elf_Addr) location; + *loc32 = v; + break; + case R_SPARC_WDISP19: v -= (Elf_Addr) location; *loc32 = (*loc32 & ~0x7ffff) | diff --git a/trunk/arch/sparc/kernel/pci.c b/trunk/arch/sparc/kernel/pci.c index acc8c838ff72..065b88c4f868 100644 --- a/trunk/arch/sparc/kernel/pci.c +++ b/trunk/arch/sparc/kernel/pci.c @@ -622,6 +622,10 @@ void __devinit pcibios_fixup_bus(struct pci_bus *pbus) { } +void pcibios_update_irq(struct pci_dev *pdev, int irq) +{ +} + resource_size_t pcibios_align_resource(void *data, const struct resource *res, resource_size_t size, resource_size_t align) { diff --git a/trunk/arch/sparc/kernel/sys_sparc_64.c b/trunk/arch/sparc/kernel/sys_sparc_64.c index 11c6c9603e71..0dc1f5786081 100644 --- a/trunk/arch/sparc/kernel/sys_sparc_64.c +++ b/trunk/arch/sparc/kernel/sys_sparc_64.c @@ -502,12 +502,12 @@ SYSCALL_DEFINE1(sparc64_personality, unsigned long, personality) { int ret; - if (personality(current->personality) == PER_LINUX32 && - personality(personality) == PER_LINUX) - personality |= PER_LINUX32; + if (current->personality == PER_LINUX32 && + personality == PER_LINUX) + personality = PER_LINUX32; ret = sys_personality(personality); - if (personality(ret) == PER_LINUX32) - ret &= ~PER_LINUX32; + if (ret == PER_LINUX32) + ret = PER_LINUX; return ret; } diff --git a/trunk/arch/sparc/mm/init_64.c b/trunk/arch/sparc/mm/init_64.c index d58edf5fefdb..6026fdd1b2ed 100644 --- a/trunk/arch/sparc/mm/init_64.c +++ b/trunk/arch/sparc/mm/init_64.c @@ -2020,9 +2020,6 @@ EXPORT_SYMBOL(_PAGE_CACHE); #ifdef CONFIG_SPARSEMEM_VMEMMAP unsigned long vmemmap_table[VMEMMAP_SIZE]; -static long __meminitdata addr_start, addr_end; -static int __meminitdata node_start; - int __meminit vmemmap_populate(struct page *start, unsigned long nr, int node) { unsigned long vstart = (unsigned long) start; @@ -2053,30 +2050,15 @@ int __meminit vmemmap_populate(struct page *start, unsigned long nr, int node) *vmem_pp = pte_base | __pa(block); - /* check to see if we have contiguous blocks */ - if (addr_end != addr || node_start != node) { - if (addr_start) - printk(KERN_DEBUG " [%lx-%lx] on node %d\n", - addr_start, addr_end-1, node_start); - addr_start = addr; - node_start = node; - } - addr_end = addr + VMEMMAP_CHUNK; + printk(KERN_INFO "[%p-%p] page_structs=%lu " + "node=%d entry=%lu/%lu\n", start, block, nr, + node, + addr >> VMEMMAP_CHUNK_SHIFT, + VMEMMAP_SIZE); } } return 0; } - -void __meminit vmemmap_populate_print_last(void) -{ - if (addr_start) { - printk(KERN_DEBUG " [%lx-%lx] on node %d\n", - addr_start, addr_end-1, node_start); - addr_start = 0; - addr_end = 0; - node_start = 0; - } -} #endif /* CONFIG_SPARSEMEM_VMEMMAP */ static void prot_init_common(unsigned long page_none, diff --git a/trunk/arch/tile/Kconfig b/trunk/arch/tile/Kconfig index c9a3c1fe7297..932e4430f7f3 100644 --- a/trunk/arch/tile/Kconfig +++ b/trunk/arch/tile/Kconfig @@ -412,6 +412,14 @@ config TILE_USB config NEED_BOUNCE_POOL def_bool USB_OHCI_HCD +config HOTPLUG + bool "Support for hot-pluggable devices" + ---help--- + Say Y here if you want to plug devices into your computer while + the system is running, and be able to use them quickly. In many + cases, the devices can likewise be unplugged at any time too. + One well-known example of this is USB. + source "drivers/pci/hotplug/Kconfig" endmenu diff --git a/trunk/arch/tile/include/asm/topology.h b/trunk/arch/tile/include/asm/topology.h index d5e86c9f74fd..7a7ce390534f 100644 --- a/trunk/arch/tile/include/asm/topology.h +++ b/trunk/arch/tile/include/asm/topology.h @@ -69,6 +69,7 @@ static inline const struct cpumask *cpumask_of_node(int node) | 1*SD_BALANCE_FORK \ | 0*SD_BALANCE_WAKE \ | 0*SD_WAKE_AFFINE \ + | 0*SD_PREFER_LOCAL \ | 0*SD_SHARE_CPUPOWER \ | 0*SD_SHARE_PKG_RESOURCES \ | 0*SD_SERIALIZE \ diff --git a/trunk/arch/tile/include/gxio/iorpc_trio.h b/trunk/arch/tile/include/gxio/iorpc_trio.h index 58105c31228b..15fb77992083 100644 --- a/trunk/arch/tile/include/gxio/iorpc_trio.h +++ b/trunk/arch/tile/include/gxio/iorpc_trio.h @@ -25,23 +25,21 @@ #include #include -#define GXIO_TRIO_OP_DEALLOC_ASID IORPC_OPCODE(IORPC_FORMAT_NONE, 0x1400) -#define GXIO_TRIO_OP_ALLOC_ASIDS IORPC_OPCODE(IORPC_FORMAT_NONE, 0x1401) +#define GXIO_TRIO_OP_ALLOC_ASIDS IORPC_OPCODE(IORPC_FORMAT_NONE, 0x1400) -#define GXIO_TRIO_OP_ALLOC_MEMORY_MAPS IORPC_OPCODE(IORPC_FORMAT_NONE, 0x1404) +#define GXIO_TRIO_OP_ALLOC_MEMORY_MAPS IORPC_OPCODE(IORPC_FORMAT_NONE, 0x1402) -#define GXIO_TRIO_OP_ALLOC_PIO_REGIONS IORPC_OPCODE(IORPC_FORMAT_NONE, 0x1412) +#define GXIO_TRIO_OP_ALLOC_PIO_REGIONS IORPC_OPCODE(IORPC_FORMAT_NONE, 0x140e) +#define GXIO_TRIO_OP_INIT_PIO_REGION_AUX IORPC_OPCODE(IORPC_FORMAT_NONE, 0x140f) -#define GXIO_TRIO_OP_INIT_PIO_REGION_AUX IORPC_OPCODE(IORPC_FORMAT_NONE, 0x1414) +#define GXIO_TRIO_OP_INIT_MEMORY_MAP_MMU_AUX IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x1417) +#define GXIO_TRIO_OP_GET_PORT_PROPERTY IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x1418) +#define GXIO_TRIO_OP_CONFIG_LEGACY_INTR IORPC_OPCODE(IORPC_FORMAT_KERNEL_INTERRUPT, 0x1419) +#define GXIO_TRIO_OP_CONFIG_MSI_INTR IORPC_OPCODE(IORPC_FORMAT_KERNEL_INTERRUPT, 0x141a) -#define GXIO_TRIO_OP_INIT_MEMORY_MAP_MMU_AUX IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x141e) -#define GXIO_TRIO_OP_GET_PORT_PROPERTY IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x141f) -#define GXIO_TRIO_OP_CONFIG_LEGACY_INTR IORPC_OPCODE(IORPC_FORMAT_KERNEL_INTERRUPT, 0x1420) -#define GXIO_TRIO_OP_CONFIG_MSI_INTR IORPC_OPCODE(IORPC_FORMAT_KERNEL_INTERRUPT, 0x1421) - -#define GXIO_TRIO_OP_SET_MPS_MRS IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x1423) -#define GXIO_TRIO_OP_FORCE_RC_LINK_UP IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x1424) -#define GXIO_TRIO_OP_FORCE_EP_LINK_UP IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x1425) +#define GXIO_TRIO_OP_SET_MPS_MRS IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x141c) +#define GXIO_TRIO_OP_FORCE_RC_LINK_UP IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x141d) +#define GXIO_TRIO_OP_FORCE_EP_LINK_UP IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x141e) #define GXIO_TRIO_OP_GET_MMIO_BASE IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x8000) #define GXIO_TRIO_OP_CHECK_MMIO_OFFSET IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x8001) diff --git a/trunk/arch/tile/kernel/pci.c b/trunk/arch/tile/kernel/pci.c index 759822687e8f..33c10864d2f7 100644 --- a/trunk/arch/tile/kernel/pci.c +++ b/trunk/arch/tile/kernel/pci.c @@ -246,13 +246,16 @@ static void __devinit fixup_read_and_payload_sizes(void) /* Scan for the smallest maximum payload size. */ while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { + int pcie_caps_offset; u32 devcap; int max_payload; - if (!pci_is_pcie(dev)) + pcie_caps_offset = pci_find_capability(dev, PCI_CAP_ID_EXP); + if (pcie_caps_offset == 0) continue; - pcie_capability_read_dword(dev, PCI_EXP_DEVCAP, &devcap); + pci_read_config_dword(dev, pcie_caps_offset + PCI_EXP_DEVCAP, + &devcap); max_payload = devcap & PCI_EXP_DEVCAP_PAYLOAD; if (max_payload < smallest_max_payload) smallest_max_payload = max_payload; @@ -260,10 +263,21 @@ static void __devinit fixup_read_and_payload_sizes(void) /* Now, set the max_payload_size for all devices to that value. */ new_values = (max_read_size << 12) | (smallest_max_payload << 5); - while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) - pcie_capability_clear_and_set_word(dev, PCI_EXP_DEVCTL, - PCI_EXP_DEVCTL_PAYLOAD | PCI_EXP_DEVCTL_READRQ, - new_values); + while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { + int pcie_caps_offset; + u16 devctl; + + pcie_caps_offset = pci_find_capability(dev, PCI_CAP_ID_EXP); + if (pcie_caps_offset == 0) + continue; + + pci_read_config_word(dev, pcie_caps_offset + PCI_EXP_DEVCTL, + &devctl); + devctl &= ~(PCI_EXP_DEVCTL_PAYLOAD | PCI_EXP_DEVCTL_READRQ); + devctl |= new_values; + pci_write_config_word(dev, pcie_caps_offset + PCI_EXP_DEVCTL, + devctl); + } } @@ -389,6 +403,14 @@ void pcibios_set_master(struct pci_dev *dev) /* No special bus mastering setup handling. */ } +/* + * This is called from the generic Linux layer. + */ +void __devinit pcibios_update_irq(struct pci_dev *dev, int irq) +{ + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq); +} + /* * Enable memory and/or address decoding, as appropriate, for the * device described by the 'dev' struct. diff --git a/trunk/arch/tile/kernel/pci_gx.c b/trunk/arch/tile/kernel/pci_gx.c index 2ba6d052f85d..0e213e35ffc3 100644 --- a/trunk/arch/tile/kernel/pci_gx.c +++ b/trunk/arch/tile/kernel/pci_gx.c @@ -1033,6 +1033,14 @@ char __devinit *pcibios_setup(char *str) return str; } +/* + * This is called from the generic Linux layer. + */ +void __devinit pcibios_update_irq(struct pci_dev *dev, int irq) +{ + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq); +} + /* * Enable memory address decoding, as appropriate, for the * device described by the 'dev' struct. The I/O decoding diff --git a/trunk/arch/um/drivers/line.c b/trunk/arch/um/drivers/line.c index 457475f98414..bbaf2c59830a 100644 --- a/trunk/arch/um/drivers/line.c +++ b/trunk/arch/um/drivers/line.c @@ -409,8 +409,7 @@ int setup_one_line(struct line *lines, int n, char *init, line->valid = 1; err = parse_chan_pair(new, line, n, opts, error_out); if (!err) { - struct device *d = tty_port_register_device(&line->port, - driver, n, NULL); + struct device *d = tty_register_device(driver, n, NULL); if (IS_ERR(d)) { *error_out = "Failed to register device"; err = PTR_ERR(d); diff --git a/trunk/arch/um/drivers/mconsole_kern.c b/trunk/arch/um/drivers/mconsole_kern.c index c17de0db6736..664a60e8dfb4 100644 --- a/trunk/arch/um/drivers/mconsole_kern.c +++ b/trunk/arch/um/drivers/mconsole_kern.c @@ -705,7 +705,6 @@ static void stack_proc(void *arg) struct task_struct *from = current, *to = arg; to->thread.saved_task = from; - rcu_switch(from, to); switch_to(from, to, from); } diff --git a/trunk/arch/um/include/asm/processor-generic.h b/trunk/arch/um/include/asm/processor-generic.h index 33a6a2423bd2..69f1c57a8d0d 100644 --- a/trunk/arch/um/include/asm/processor-generic.h +++ b/trunk/arch/um/include/asm/processor-generic.h @@ -20,6 +20,14 @@ struct mm_struct; struct thread_struct { struct task_struct *saved_task; + /* + * This flag is set to 1 before calling do_fork (and analyzed in + * copy_thread) to mark that we are begin called from userspace (fork / + * vfork / clone), and reset to 0 after. It is left to 0 when called + * from kernelspace (i.e. kernel_thread() or fork_idle(), + * as of 2.6.11). + */ + int forking; struct pt_regs regs; int singlestep_syscall; void *fault_addr; @@ -50,6 +58,7 @@ struct thread_struct { #define INIT_THREAD \ { \ + .forking = 0, \ .regs = EMPTY_REGS, \ .fault_addr = NULL, \ .prev_sched = NULL, \ diff --git a/trunk/arch/um/include/shared/common-offsets.h b/trunk/arch/um/include/shared/common-offsets.h index 2df313b6a586..40db8f71deae 100644 --- a/trunk/arch/um/include/shared/common-offsets.h +++ b/trunk/arch/um/include/shared/common-offsets.h @@ -7,6 +7,16 @@ DEFINE(UM_KERN_PAGE_MASK, PAGE_MASK); DEFINE(UM_KERN_PAGE_SHIFT, PAGE_SHIFT); DEFINE(UM_NSEC_PER_SEC, NSEC_PER_SEC); +DEFINE_STR(UM_KERN_EMERG, KERN_EMERG); +DEFINE_STR(UM_KERN_ALERT, KERN_ALERT); +DEFINE_STR(UM_KERN_CRIT, KERN_CRIT); +DEFINE_STR(UM_KERN_ERR, KERN_ERR); +DEFINE_STR(UM_KERN_WARNING, KERN_WARNING); +DEFINE_STR(UM_KERN_NOTICE, KERN_NOTICE); +DEFINE_STR(UM_KERN_INFO, KERN_INFO); +DEFINE_STR(UM_KERN_DEBUG, KERN_DEBUG); +DEFINE_STR(UM_KERN_CONT, KERN_CONT); + DEFINE(UM_ELF_CLASS, ELF_CLASS); DEFINE(UM_ELFCLASS32, ELFCLASS32); DEFINE(UM_ELFCLASS64, ELFCLASS64); diff --git a/trunk/arch/um/include/shared/user.h b/trunk/arch/um/include/shared/user.h index cef068563336..4fa82c055aab 100644 --- a/trunk/arch/um/include/shared/user.h +++ b/trunk/arch/um/include/shared/user.h @@ -26,17 +26,6 @@ extern void panic(const char *fmt, ...) __attribute__ ((format (printf, 1, 2))); -/* Requires preincluding include/linux/kern_levels.h */ -#define UM_KERN_EMERG KERN_EMERG -#define UM_KERN_ALERT KERN_ALERT -#define UM_KERN_CRIT KERN_CRIT -#define UM_KERN_ERR KERN_ERR -#define UM_KERN_WARNING KERN_WARNING -#define UM_KERN_NOTICE KERN_NOTICE -#define UM_KERN_INFO KERN_INFO -#define UM_KERN_DEBUG KERN_DEBUG -#define UM_KERN_CONT KERN_CONT - #ifdef UML_CONFIG_PRINTK extern int printk(const char *fmt, ...) __attribute__ ((format (printf, 1, 2))); diff --git a/trunk/arch/um/kernel/exec.c b/trunk/arch/um/kernel/exec.c index 8c82786da823..6cade9366364 100644 --- a/trunk/arch/um/kernel/exec.c +++ b/trunk/arch/um/kernel/exec.c @@ -39,21 +39,34 @@ void flush_thread(void) void start_thread(struct pt_regs *regs, unsigned long eip, unsigned long esp) { - get_safe_registers(regs->regs.gp, regs->regs.fp); PT_REGS_IP(regs) = eip; PT_REGS_SP(regs) = esp; - current->ptrace &= ~PT_DTRACE; +} +EXPORT_SYMBOL(start_thread); + +static long execve1(const char *file, + const char __user *const __user *argv, + const char __user *const __user *env) +{ + long error; + + error = do_execve(file, argv, env, ¤t->thread.regs); + if (error == 0) { + task_lock(current); + current->ptrace &= ~PT_DTRACE; #ifdef SUBARCH_EXECVE1 - SUBARCH_EXECVE1(regs->regs); + SUBARCH_EXECVE1(¤t->thread.regs.regs); #endif + task_unlock(current); + } + return error; } -EXPORT_SYMBOL(start_thread); long um_execve(const char *file, const char __user *const __user *argv, const char __user *const __user *env) { long err; - err = do_execve(file, argv, env, ¤t->thread.regs); + err = execve1(file, argv, env); if (!err) UML_LONGJMP(current->thread.exec_buf, 1); return err; @@ -68,7 +81,7 @@ long sys_execve(const char __user *file, const char __user *const __user *argv, filename = getname(file); error = PTR_ERR(filename); if (IS_ERR(filename)) goto out; - error = do_execve(filename, argv, env, ¤t->thread.regs); + error = execve1(filename, argv, env); putname(filename); out: return error; diff --git a/trunk/arch/um/kernel/process.c b/trunk/arch/um/kernel/process.c index c5f5afa50745..57fc7028714a 100644 --- a/trunk/arch/um/kernel/process.c +++ b/trunk/arch/um/kernel/process.c @@ -181,12 +181,11 @@ int copy_thread(unsigned long clone_flags, unsigned long sp, struct pt_regs *regs) { void (*handler)(void); - int kthread = current->flags & PF_KTHREAD; int ret = 0; p->thread = (struct thread_struct) INIT_THREAD; - if (!kthread) { + if (current->thread.forking) { memcpy(&p->thread.regs.regs, ®s->regs, sizeof(p->thread.regs.regs)); PT_REGS_SET_SYSCALL_RETURN(&p->thread.regs, 0); @@ -196,7 +195,8 @@ int copy_thread(unsigned long clone_flags, unsigned long sp, handler = fork_handler; arch_copy_thread(¤t->thread.arch, &p->thread.arch); - } else { + } + else { get_safe_registers(p->thread.regs.regs.gp, p->thread.regs.regs.fp); p->thread.request.u.thread = current->thread.request.u.thread; handler = new_thread_handler; @@ -204,7 +204,7 @@ int copy_thread(unsigned long clone_flags, unsigned long sp, new_thread(task_stack_page(p), &p->thread.switch_buf, handler); - if (!kthread) { + if (current->thread.forking) { clear_flushed_tls(p); /* diff --git a/trunk/arch/um/kernel/signal.c b/trunk/arch/um/kernel/signal.c index cc9c2350e417..7362d58efc29 100644 --- a/trunk/arch/um/kernel/signal.c +++ b/trunk/arch/um/kernel/signal.c @@ -22,13 +22,9 @@ static void handle_signal(struct pt_regs *regs, unsigned long signr, struct k_sigaction *ka, siginfo_t *info) { sigset_t *oldset = sigmask_to_save(); - int singlestep = 0; unsigned long sp; int err; - if ((current->ptrace & PT_DTRACE) && (current->ptrace & PT_PTRACED)) - singlestep = 1; - /* Did we come from a system call? */ if (PT_REGS_SYSCALL_NR(regs) >= 0) { /* If so, check system call restarting.. */ @@ -65,7 +61,7 @@ static void handle_signal(struct pt_regs *regs, unsigned long signr, if (err) force_sigsegv(signr, current); else - signal_delivered(signr, info, ka, regs, singlestep); + signal_delivered(signr, info, ka, regs, 0); } static int kern_do_signal(struct pt_regs *regs) diff --git a/trunk/arch/um/kernel/syscall.c b/trunk/arch/um/kernel/syscall.c index a4c6d8eee74c..f958cb876ee3 100644 --- a/trunk/arch/um/kernel/syscall.c +++ b/trunk/arch/um/kernel/syscall.c @@ -17,25 +17,25 @@ long sys_fork(void) { - return do_fork(SIGCHLD, UPT_SP(¤t->thread.regs.regs), + long ret; + + current->thread.forking = 1; + ret = do_fork(SIGCHLD, UPT_SP(¤t->thread.regs.regs), ¤t->thread.regs, 0, NULL, NULL); + current->thread.forking = 0; + return ret; } long sys_vfork(void) { - return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, + long ret; + + current->thread.forking = 1; + ret = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, UPT_SP(¤t->thread.regs.regs), ¤t->thread.regs, 0, NULL, NULL); -} - -long sys_clone(unsigned long clone_flags, unsigned long newsp, - void __user *parent_tid, void __user *child_tid) -{ - if (!newsp) - newsp = UPT_SP(¤t->thread.regs.regs); - - return do_fork(clone_flags, newsp, ¤t->thread.regs, 0, parent_tid, - child_tid); + current->thread.forking = 0; + return ret; } long old_mmap(unsigned long addr, unsigned long len, diff --git a/trunk/arch/um/os-Linux/time.c b/trunk/arch/um/os-Linux/time.c index 0748fe0c8a73..f60238559af3 100644 --- a/trunk/arch/um/os-Linux/time.c +++ b/trunk/arch/um/os-Linux/time.c @@ -114,7 +114,7 @@ static void deliver_alarm(void) skew += this_tick - last_tick; while (skew >= one_tick) { - alarm_handler(SIGVTALRM, NULL, NULL); + alarm_handler(SIGVTALRM, NULL); skew -= one_tick; } diff --git a/trunk/arch/um/scripts/Makefile.rules b/trunk/arch/um/scripts/Makefile.rules index 15889df9b466..d50270d26b42 100644 --- a/trunk/arch/um/scripts/Makefile.rules +++ b/trunk/arch/um/scripts/Makefile.rules @@ -8,7 +8,7 @@ USER_OBJS += $(filter %_user.o,$(obj-y) $(obj-m) $(USER_SINGLE_OBJS)) USER_OBJS := $(foreach file,$(USER_OBJS),$(obj)/$(file)) $(USER_OBJS:.o=.%): \ - c_flags = -Wp,-MD,$(depfile) $(USER_CFLAGS) -include $(srctree)/include/linux/kern_levels.h -include user.h $(CFLAGS_$(basetarget).o) + c_flags = -Wp,-MD,$(depfile) $(USER_CFLAGS) -include user.h $(CFLAGS_$(basetarget).o) # These are like USER_OBJS but filter USER_CFLAGS through unprofile instead of # using it directly. diff --git a/trunk/arch/unicore32/kernel/pci.c b/trunk/arch/unicore32/kernel/pci.c index b0056f68d321..46cb6c9de6c9 100644 --- a/trunk/arch/unicore32/kernel/pci.c +++ b/trunk/arch/unicore32/kernel/pci.c @@ -154,6 +154,14 @@ void __init puv3_pci_adjust_zones(unsigned long *zone_size, zhole_size[0] = 0; } +void __devinit pcibios_update_irq(struct pci_dev *dev, int irq) +{ + if (debug_pci) + printk(KERN_DEBUG "PCI: Assigning IRQ %02d to %s\n", + irq, pci_name(dev)); + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq); +} + /* * If the bus contains any of these devices, then we must not turn on * parity checking of any kind. diff --git a/trunk/arch/x86/Kconfig b/trunk/arch/x86/Kconfig index 943667050dae..ba2657c49217 100644 --- a/trunk/arch/x86/Kconfig +++ b/trunk/arch/x86/Kconfig @@ -7,13 +7,11 @@ config 64BIT Say no to build a 32-bit kernel - formerly known as i386 config X86_32 - def_bool y - depends on !64BIT + def_bool !64BIT select CLKSRC_I8253 config X86_64 - def_bool y - depends on 64BIT + def_bool 64BIT select X86_DEV_DMA_OPS ### Arch settings @@ -38,7 +36,6 @@ config X86 select HAVE_KRETPROBES select HAVE_OPTPROBES select HAVE_FTRACE_MCOUNT_RECORD - select HAVE_FENTRY if X86_64 select HAVE_C_RECORDMCOUNT select HAVE_DYNAMIC_FTRACE select HAVE_FUNCTION_TRACER @@ -63,8 +60,6 @@ config X86 select HAVE_MIXED_BREAKPOINTS_REGS select PERF_EVENTS select HAVE_PERF_EVENTS_NMI - select HAVE_PERF_REGS - select HAVE_PERF_USER_STACK_DUMP select ANON_INODES select HAVE_ALIGNED_STRUCT_PAGE if SLUB && !M386 select HAVE_CMPXCHG_LOCAL if !M386 @@ -102,12 +97,9 @@ config X86 select KTIME_SCALAR if X86_32 select GENERIC_STRNCPY_FROM_USER select GENERIC_STRNLEN_USER - select HAVE_RCU_USER_QS if X86_64 - select HAVE_IRQ_TIME_ACCOUNTING config INSTRUCTION_DECODER - def_bool y - depends on KPROBES || PERF_EVENTS || UPROBES + def_bool (KPROBES || PERF_EVENTS || UPROBES) config OUTPUT_FORMAT string @@ -135,15 +127,13 @@ config SBUS bool config NEED_DMA_MAP_STATE - def_bool y - depends on X86_64 || INTEL_IOMMU || DMA_API_DEBUG + def_bool (X86_64 || INTEL_IOMMU || DMA_API_DEBUG) config NEED_SG_DMA_LENGTH def_bool y config GENERIC_ISA_DMA - def_bool y - depends on ISA_DMA_API + def_bool ISA_DMA_API config GENERIC_BUG def_bool y @@ -160,16 +150,13 @@ config GENERIC_GPIO bool config ARCH_MAY_HAVE_PC_FDC - def_bool y - depends on ISA_DMA_API + def_bool ISA_DMA_API config RWSEM_GENERIC_SPINLOCK - def_bool y - depends on !X86_XADD + def_bool !X86_XADD config RWSEM_XCHGADD_ALGORITHM - def_bool y - depends on X86_XADD + def_bool X86_XADD config GENERIC_CALIBRATE_DELAY def_bool y @@ -759,14 +746,13 @@ config SWIOTLB def_bool y if X86_64 ---help--- Support for software bounce buffers used on x86-64 systems - which don't have a hardware IOMMU. Using this PCI devices - which can only access 32-bits of memory can be used on systems - with more than 3 GB of memory. - If unsure, say Y. + which don't have a hardware IOMMU (e.g. the current generation + of Intel's x86-64 CPUs). Using this PCI devices which can only + access 32-bits of memory can be used on systems with more than + 3 GB of memory. If unsure, say Y. config IOMMU_HELPER - def_bool y - depends on CALGARY_IOMMU || GART_IOMMU || SWIOTLB || AMD_IOMMU + def_bool (CALGARY_IOMMU || GART_IOMMU || SWIOTLB || AMD_IOMMU) config MAXSMP bool "Enable Maximum number of SMP Processors and NUMA Nodes" @@ -810,6 +796,17 @@ config SCHED_MC making when dealing with multi-core CPU chips at a cost of slightly increased overhead in some places. If unsure say N here. +config IRQ_TIME_ACCOUNTING + bool "Fine granularity task level IRQ time accounting" + default n + ---help--- + Select this option to enable fine granularity task irq time + accounting. This is done by reading a timestamp on each + transitions between softirq and hardirq state, so there can be a + small performance impact. + + If in doubt, say N here. + source "kernel/Kconfig.preempt" config X86_UP_APIC @@ -874,7 +871,6 @@ config X86_REROUTE_FOR_BROKEN_BOOT_IRQS config X86_MCE bool "Machine Check / overheating reporting" - default y ---help--- Machine Check support allows the processor to notify the kernel if it detects a problem (e.g. overheating, data corruption). @@ -986,25 +982,25 @@ config X86_REBOOTFIXUPS Say N otherwise. config MICROCODE - tristate "CPU microcode loading support" + tristate "/dev/cpu/microcode - microcode support" select FW_LOADER ---help--- - If you say Y here, you will be able to update the microcode on certain Intel and AMD processors. The Intel support is for the - IA32 family, e.g. Pentium Pro, Pentium II, Pentium III, Pentium 4, - Xeon etc. The AMD support is for families 0x10 and later. You will - obviously need the actual microcode binary data itself which is not - shipped with the Linux kernel. + IA32 family, e.g. Pentium Pro, Pentium II, Pentium III, + Pentium 4, Xeon etc. The AMD support is for family 0x10 and + 0x11 processors, e.g. Opteron, Phenom and Turion 64 Ultra. + You will obviously need the actual microcode binary data itself + which is not shipped with the Linux kernel. This option selects the general module only, you need to select at least one vendor specific module as well. - To compile this driver as a module, choose M here: the module - will be called microcode. + To compile this driver as a module, choose M here: the + module will be called microcode. config MICROCODE_INTEL - bool "Intel microcode loading support" + bool "Intel microcode patch loading support" depends on MICROCODE default MICROCODE select FW_LOADER @@ -1017,7 +1013,7 @@ config MICROCODE_INTEL . config MICROCODE_AMD - bool "AMD microcode loading support" + bool "AMD microcode patch loading support" depends on MICROCODE select FW_LOADER ---help--- @@ -1163,12 +1159,10 @@ config X86_PAE consumes more pagetable space per process. config ARCH_PHYS_ADDR_T_64BIT - def_bool y - depends on X86_64 || X86_PAE + def_bool X86_64 || X86_PAE config ARCH_DMA_ADDR_T_64BIT - def_bool y - depends on X86_64 || HIGHMEM64G + def_bool X86_64 || HIGHMEM64G config DIRECT_GBPAGES bool "Enable 1GB pages for kernel pagetables" if EXPERT @@ -1291,8 +1285,8 @@ config ARCH_SELECT_MEMORY_MODEL depends on ARCH_SPARSEMEM_ENABLE config ARCH_MEMORY_PROBE - def_bool y - depends on X86_64 && MEMORY_HOTPLUG + def_bool X86_64 + depends on MEMORY_HOTPLUG config ARCH_PROC_KCORE_TEXT def_bool y @@ -1533,7 +1527,7 @@ config SECCOMP If unsure, say Y. Only embedded should say N here. config CC_STACKPROTECTOR - bool "Enable -fstack-protector buffer overflow detection" + bool "Enable -fstack-protector buffer overflow detection (EXPERIMENTAL)" ---help--- This option turns on the -fstack-protector GCC feature. This feature puts, at the beginning of functions, a canary value on @@ -1981,6 +1975,7 @@ config PCI_MMCONFIG config PCI_CNB20LE_QUIRK bool "Read CNB20LE Host Bridge Windows" if EXPERT + default n depends on PCI && EXPERIMENTAL help Read the PCI windows out of the CNB20LE host bridge. This allows @@ -2191,18 +2186,18 @@ config COMPAT depends on IA32_EMULATION || X86_X32 select ARCH_WANT_OLD_COMPAT_IPC -if COMPAT config COMPAT_FOR_U64_ALIGNMENT - def_bool y + def_bool COMPAT + depends on X86_64 config SYSVIPC_COMPAT def_bool y - depends on SYSVIPC + depends on COMPAT && SYSVIPC config KEYS_COMPAT - def_bool y - depends on KEYS -endif + bool + depends on COMPAT && KEYS + default y endmenu diff --git a/trunk/arch/x86/Kconfig.cpu b/trunk/arch/x86/Kconfig.cpu index f3b86d0df44e..706e12e9984b 100644 --- a/trunk/arch/x86/Kconfig.cpu +++ b/trunk/arch/x86/Kconfig.cpu @@ -306,8 +306,7 @@ config X86_INTERNODE_CACHE_SHIFT default X86_L1_CACHE_SHIFT config X86_CMPXCHG - def_bool y - depends on X86_64 || (X86_32 && !M386) + def_bool X86_64 || (X86_32 && !M386) config X86_L1_CACHE_SHIFT int @@ -318,7 +317,7 @@ config X86_L1_CACHE_SHIFT config X86_XADD def_bool y - depends on !M386 + depends on X86_64 || !M386 config X86_PPRO_FENCE bool "PentiumPro memory ordering errata workaround" diff --git a/trunk/arch/x86/Makefile b/trunk/arch/x86/Makefile index 474ca35b1bce..b0c5276861ec 100644 --- a/trunk/arch/x86/Makefile +++ b/trunk/arch/x86/Makefile @@ -27,10 +27,6 @@ ifeq ($(CONFIG_X86_32),y) KBUILD_CFLAGS += -msoft-float -mregparm=3 -freg-struct-return - # Never want PIC in a 32-bit kernel, prevent breakage with GCC built - # with nonstandard options - KBUILD_CFLAGS += -fno-pic - # prevent gcc from keeping the stack 16 byte aligned KBUILD_CFLAGS += $(call cc-option,-mpreferred-stack-boundary=2) @@ -142,7 +138,7 @@ KBUILD_CFLAGS += $(call cc-option,-mno-avx,) KBUILD_CFLAGS += $(mflags-y) KBUILD_AFLAGS += $(mflags-y) -archscripts: scripts_basic +archscripts: $(Q)$(MAKE) $(build)=arch/x86/tools relocs ### diff --git a/trunk/arch/x86/boot/Makefile b/trunk/arch/x86/boot/Makefile index f7535bedc33f..5a747dd884db 100644 --- a/trunk/arch/x86/boot/Makefile +++ b/trunk/arch/x86/boot/Makefile @@ -57,7 +57,7 @@ KBUILD_CFLAGS := $(LINUXINCLUDE) -g -Os -D_SETUP -D__KERNEL__ \ -Wall -Wstrict-prototypes \ -march=i386 -mregparm=3 \ -include $(srctree)/$(src)/code16gcc.h \ - -fno-strict-aliasing -fomit-frame-pointer -fno-pic \ + -fno-strict-aliasing -fomit-frame-pointer \ $(call cc-option, -ffreestanding) \ $(call cc-option, -fno-toplevel-reorder,\ $(call cc-option, -fno-unit-at-a-time)) \ diff --git a/trunk/arch/x86/boot/compressed/Makefile b/trunk/arch/x86/boot/compressed/Makefile index 8a84501acb1b..e398bb5d63bb 100644 --- a/trunk/arch/x86/boot/compressed/Makefile +++ b/trunk/arch/x86/boot/compressed/Makefile @@ -28,9 +28,6 @@ VMLINUX_OBJS = $(obj)/vmlinux.lds $(obj)/head_$(BITS).o $(obj)/misc.o \ $(obj)/string.o $(obj)/cmdline.o $(obj)/early_serial_console.o \ $(obj)/piggy.o -$(obj)/eboot.o: KBUILD_CFLAGS += -fshort-wchar -mno-red-zone -$(obj)/efi_stub_$(BITS).o: KBUILD_CLFAGS += -fshort-wchar -mno-red-zone - ifeq ($(CONFIG_EFI_STUB), y) VMLINUX_OBJS += $(obj)/eboot.o $(obj)/efi_stub_$(BITS).o endif diff --git a/trunk/arch/x86/boot/compressed/eboot.c b/trunk/arch/x86/boot/compressed/eboot.c index c760e073963e..b3e0227df2c9 100644 --- a/trunk/arch/x86/boot/compressed/eboot.c +++ b/trunk/arch/x86/boot/compressed/eboot.c @@ -276,9 +276,8 @@ static efi_status_t setup_gop(struct screen_info *si, efi_guid_t *proto, nr_gops = size / sizeof(void *); for (i = 0; i < nr_gops; i++) { struct efi_graphics_output_mode_info *info; - efi_guid_t conout_proto = EFI_CONSOLE_OUT_DEVICE_GUID; - bool conout_found = false; - void *dummy; + efi_guid_t pciio_proto = EFI_PCI_IO_PROTOCOL_GUID; + void *pciio; void *h = gop_handle[i]; status = efi_call_phys3(sys_table->boottime->handle_protocol, @@ -286,21 +285,19 @@ static efi_status_t setup_gop(struct screen_info *si, efi_guid_t *proto, if (status != EFI_SUCCESS) continue; - status = efi_call_phys3(sys_table->boottime->handle_protocol, - h, &conout_proto, &dummy); - - if (status == EFI_SUCCESS) - conout_found = true; + efi_call_phys3(sys_table->boottime->handle_protocol, + h, &pciio_proto, &pciio); status = efi_call_phys4(gop->query_mode, gop, gop->mode->mode, &size, &info); - if (status == EFI_SUCCESS && (!first_gop || conout_found)) { + if (status == EFI_SUCCESS && (!first_gop || pciio)) { /* - * Systems that use the UEFI Console Splitter may - * provide multiple GOP devices, not all of which are - * backed by real hardware. The workaround is to search - * for a GOP implementing the ConOut protocol, and if - * one isn't found, to just fall back to the first GOP. + * Apple provide GOPs that are not backed by + * real hardware (they're used to handle + * multiple displays). The workaround is to + * search for a GOP implementing the PCIIO + * protocol, and if one isn't found, to just + * fallback to the first GOP. */ width = info->horizontal_resolution; height = info->vertical_resolution; @@ -311,10 +308,10 @@ static efi_status_t setup_gop(struct screen_info *si, efi_guid_t *proto, pixels_per_scan_line = info->pixels_per_scan_line; /* - * Once we've found a GOP supporting ConOut, + * Once we've found a GOP supporting PCIIO, * don't bother looking any further. */ - if (conout_found) + if (pciio) break; first_gop = gop; @@ -331,6 +328,7 @@ static efi_status_t setup_gop(struct screen_info *si, efi_guid_t *proto, si->lfb_width = width; si->lfb_height = height; si->lfb_base = fb_base; + si->lfb_size = fb_size; si->pages = 1; if (pixel_format == PIXEL_RGB_RESERVED_8BIT_PER_COLOR) { @@ -378,10 +376,6 @@ static efi_status_t setup_gop(struct screen_info *si, efi_guid_t *proto, si->rsvd_pos = 0; } - si->lfb_size = si->lfb_linelength * si->lfb_height; - - si->capabilities |= VIDEO_CAPABILITY_SKIP_QUIRKS; - free_handle: efi_call_phys1(sys_table->boottime->free_pool, gop_handle); return status; diff --git a/trunk/arch/x86/boot/compressed/eboot.h b/trunk/arch/x86/boot/compressed/eboot.h index e5b0a8f91c5f..3b6e15627c55 100644 --- a/trunk/arch/x86/boot/compressed/eboot.h +++ b/trunk/arch/x86/boot/compressed/eboot.h @@ -14,10 +14,6 @@ #define EFI_PAGE_SIZE (1UL << EFI_PAGE_SHIFT) #define EFI_READ_CHUNK_SIZE (1024 * 1024) -#define EFI_CONSOLE_OUT_DEVICE_GUID \ - EFI_GUID(0xd3b36f2c, 0xd551, 0x11d4, 0x9a, 0x46, 0x0, 0x90, 0x27, \ - 0x3f, 0xc1, 0x4d) - #define PIXEL_RGB_RESERVED_8BIT_PER_COLOR 0 #define PIXEL_BGR_RESERVED_8BIT_PER_COLOR 1 #define PIXEL_BIT_MASK 2 diff --git a/trunk/arch/x86/boot/header.S b/trunk/arch/x86/boot/header.S index 2a017441b8b2..b4e15dd6786a 100644 --- a/trunk/arch/x86/boot/header.S +++ b/trunk/arch/x86/boot/header.S @@ -32,6 +32,10 @@ SYSSEG = 0x1000 /* historical load address >> 4 */ #define SVGA_MODE ASK_VGA #endif +#ifndef RAMDISK +#define RAMDISK 0 +#endif + #ifndef ROOT_RDONLY #define ROOT_RDONLY 1 #endif diff --git a/trunk/arch/x86/configs/i386_defconfig b/trunk/arch/x86/configs/i386_defconfig index 5598547281a7..119db67dcb03 100644 --- a/trunk/arch/x86/configs/i386_defconfig +++ b/trunk/arch/x86/configs/i386_defconfig @@ -8,8 +8,6 @@ CONFIG_TASK_DELAY_ACCT=y CONFIG_TASK_XACCT=y CONFIG_TASK_IO_ACCOUNTING=y CONFIG_AUDIT=y -CONFIG_NO_HZ=y -CONFIG_HIGH_RES_TIMERS=y CONFIG_LOG_BUF_SHIFT=18 CONFIG_CGROUPS=y CONFIG_CGROUP_FREEZER=y @@ -36,6 +34,8 @@ CONFIG_SGI_PARTITION=y CONFIG_SUN_PARTITION=y CONFIG_KARMA_PARTITION=y CONFIG_EFI_PARTITION=y +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y CONFIG_SMP=y CONFIG_X86_GENERIC=y CONFIG_HPET_TIMER=y @@ -144,6 +144,8 @@ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" CONFIG_DEBUG_DEVRES=y CONFIG_CONNECTOR=y CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_SIZE=16384 CONFIG_BLK_DEV_SD=y CONFIG_BLK_DEV_SR=y CONFIG_BLK_DEV_SR_VENDOR=y @@ -229,6 +231,8 @@ CONFIG_SND_HRTIMER=y CONFIG_SND_HDA_INTEL=y CONFIG_SND_HDA_HWDEP=y CONFIG_HIDRAW=y +CONFIG_HID_PID=y +CONFIG_USB_HIDDEV=y CONFIG_HID_GYRATION=y CONFIG_LOGITECH_FF=y CONFIG_HID_NTRIG=y @@ -239,11 +243,11 @@ CONFIG_HID_SAMSUNG=y CONFIG_HID_SONY=y CONFIG_HID_SUNPLUS=y CONFIG_HID_TOPSEED=y -CONFIG_HID_PID=y -CONFIG_USB_HIDDEV=y CONFIG_USB=y CONFIG_USB_DEBUG=y CONFIG_USB_ANNOUNCE_NEW_DEVICES=y +CONFIG_USB_DEVICEFS=y +# CONFIG_USB_DEVICE_CLASS is not set CONFIG_USB_MON=y CONFIG_USB_EHCI_HCD=y # CONFIG_USB_EHCI_TT_NEWSCHED is not set @@ -258,9 +262,10 @@ CONFIG_RTC_CLASS=y CONFIG_DMADEVICES=y CONFIG_EEEPC_LAPTOP=y CONFIG_EFI_VARS=y -CONFIG_EXT4_FS=y -CONFIG_EXT4_FS_POSIX_ACL=y -CONFIG_EXT4_FS_SECURITY=y +CONFIG_EXT3_FS=y +# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set +CONFIG_EXT3_FS_POSIX_ACL=y +CONFIG_EXT3_FS_SECURITY=y CONFIG_QUOTA=y CONFIG_QUOTA_NETLINK_INTERFACE=y # CONFIG_PRINT_QUOTA_WARNING is not set @@ -275,6 +280,7 @@ CONFIG_PROC_KCORE=y CONFIG_TMPFS_POSIX_ACL=y CONFIG_HUGETLBFS=y CONFIG_NFS_FS=y +CONFIG_NFS_V3=y CONFIG_NFS_V3_ACL=y CONFIG_NFS_V4=y CONFIG_ROOT_NFS=y @@ -293,11 +299,13 @@ CONFIG_DEBUG_KERNEL=y CONFIG_SCHEDSTATS=y CONFIG_TIMER_STATS=y CONFIG_DEBUG_STACK_USAGE=y +CONFIG_SYSCTL_SYSCALL_CHECK=y CONFIG_BLK_DEV_IO_TRACE=y CONFIG_PROVIDE_OHCI1394_DMA_INIT=y CONFIG_EARLY_PRINTK_DBGP=y CONFIG_DEBUG_STACKOVERFLOW=y # CONFIG_DEBUG_RODATA_TEST is not set +CONFIG_DEBUG_NX_TEST=m CONFIG_DEBUG_BOOT_PARAMS=y CONFIG_OPTIMIZE_INLINING=y CONFIG_KEYS_DEBUG_PROC_KEYS=y @@ -308,3 +316,4 @@ CONFIG_SECURITY_SELINUX_BOOTPARAM=y CONFIG_SECURITY_SELINUX_DISABLE=y CONFIG_CRYPTO_AES_586=y # CONFIG_CRYPTO_ANSI_CPRNG is not set +CONFIG_CRC_T10DIF=y diff --git a/trunk/arch/x86/configs/x86_64_defconfig b/trunk/arch/x86/configs/x86_64_defconfig index 671524d0f6c0..76eb2903809f 100644 --- a/trunk/arch/x86/configs/x86_64_defconfig +++ b/trunk/arch/x86/configs/x86_64_defconfig @@ -8,8 +8,6 @@ CONFIG_TASK_DELAY_ACCT=y CONFIG_TASK_XACCT=y CONFIG_TASK_IO_ACCOUNTING=y CONFIG_AUDIT=y -CONFIG_NO_HZ=y -CONFIG_HIGH_RES_TIMERS=y CONFIG_LOG_BUF_SHIFT=18 CONFIG_CGROUPS=y CONFIG_CGROUP_FREEZER=y @@ -36,6 +34,8 @@ CONFIG_SGI_PARTITION=y CONFIG_SUN_PARTITION=y CONFIG_KARMA_PARTITION=y CONFIG_EFI_PARTITION=y +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y CONFIG_SMP=y CONFIG_CALGARY_IOMMU=y CONFIG_NR_CPUS=64 @@ -144,6 +144,8 @@ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" CONFIG_DEBUG_DEVRES=y CONFIG_CONNECTOR=y CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_SIZE=16384 CONFIG_BLK_DEV_SD=y CONFIG_BLK_DEV_SR=y CONFIG_BLK_DEV_SR_VENDOR=y @@ -225,6 +227,8 @@ CONFIG_SND_HRTIMER=y CONFIG_SND_HDA_INTEL=y CONFIG_SND_HDA_HWDEP=y CONFIG_HIDRAW=y +CONFIG_HID_PID=y +CONFIG_USB_HIDDEV=y CONFIG_HID_GYRATION=y CONFIG_LOGITECH_FF=y CONFIG_HID_NTRIG=y @@ -235,11 +239,11 @@ CONFIG_HID_SAMSUNG=y CONFIG_HID_SONY=y CONFIG_HID_SUNPLUS=y CONFIG_HID_TOPSEED=y -CONFIG_HID_PID=y -CONFIG_USB_HIDDEV=y CONFIG_USB=y CONFIG_USB_DEBUG=y CONFIG_USB_ANNOUNCE_NEW_DEVICES=y +CONFIG_USB_DEVICEFS=y +# CONFIG_USB_DEVICE_CLASS is not set CONFIG_USB_MON=y CONFIG_USB_EHCI_HCD=y # CONFIG_USB_EHCI_TT_NEWSCHED is not set @@ -258,9 +262,10 @@ CONFIG_AMD_IOMMU_STATS=y CONFIG_INTEL_IOMMU=y # CONFIG_INTEL_IOMMU_DEFAULT_ON is not set CONFIG_EFI_VARS=y -CONFIG_EXT4_FS=y -CONFIG_EXT4_FS_POSIX_ACL=y -CONFIG_EXT4_FS_SECURITY=y +CONFIG_EXT3_FS=y +# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set +CONFIG_EXT3_FS_POSIX_ACL=y +CONFIG_EXT3_FS_SECURITY=y CONFIG_QUOTA=y CONFIG_QUOTA_NETLINK_INTERFACE=y # CONFIG_PRINT_QUOTA_WARNING is not set @@ -275,6 +280,7 @@ CONFIG_PROC_KCORE=y CONFIG_TMPFS_POSIX_ACL=y CONFIG_HUGETLBFS=y CONFIG_NFS_FS=y +CONFIG_NFS_V3=y CONFIG_NFS_V3_ACL=y CONFIG_NFS_V4=y CONFIG_ROOT_NFS=y @@ -292,11 +298,13 @@ CONFIG_DEBUG_KERNEL=y CONFIG_SCHEDSTATS=y CONFIG_TIMER_STATS=y CONFIG_DEBUG_STACK_USAGE=y +CONFIG_SYSCTL_SYSCALL_CHECK=y CONFIG_BLK_DEV_IO_TRACE=y CONFIG_PROVIDE_OHCI1394_DMA_INIT=y CONFIG_EARLY_PRINTK_DBGP=y CONFIG_DEBUG_STACKOVERFLOW=y # CONFIG_DEBUG_RODATA_TEST is not set +CONFIG_DEBUG_NX_TEST=m CONFIG_DEBUG_BOOT_PARAMS=y CONFIG_OPTIMIZE_INLINING=y CONFIG_KEYS_DEBUG_PROC_KEYS=y @@ -306,3 +314,4 @@ CONFIG_SECURITY_SELINUX=y CONFIG_SECURITY_SELINUX_BOOTPARAM=y CONFIG_SECURITY_SELINUX_DISABLE=y # CONFIG_CRYPTO_ANSI_CPRNG is not set +CONFIG_CRC_T10DIF=y diff --git a/trunk/arch/x86/ia32/ia32_signal.c b/trunk/arch/x86/ia32/ia32_signal.c index 8c77c64fbd27..673ac9b63d6b 100644 --- a/trunk/arch/x86/ia32/ia32_signal.c +++ b/trunk/arch/x86/ia32/ia32_signal.c @@ -162,8 +162,7 @@ asmlinkage long sys32_sigaltstack(const stack_ia32_t __user *uss_ptr, } seg = get_fs(); set_fs(KERNEL_DS); - ret = do_sigaltstack((stack_t __force __user *) (uss_ptr ? &uss : NULL), - (stack_t __force __user *) &uoss, regs->sp); + ret = do_sigaltstack(uss_ptr ? &uss : NULL, &uoss, regs->sp); set_fs(seg); if (ret >= 0 && uoss_ptr) { if (!access_ok(VERIFY_WRITE, uoss_ptr, sizeof(stack_ia32_t))) @@ -251,7 +250,7 @@ static int ia32_restore_sigcontext(struct pt_regs *regs, get_user_ex(tmp, &sc->fpstate); buf = compat_ptr(tmp); - err |= restore_xstate_sig(buf, 1); + err |= restore_i387_xstate_ia32(buf); get_user_ex(*pax, &sc->ax); } get_user_catch(err); @@ -362,7 +361,7 @@ static int ia32_setup_sigcontext(struct sigcontext_ia32 __user *sc, */ static void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size, - void __user **fpstate) + void **fpstate) { unsigned long sp; @@ -382,12 +381,9 @@ static void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, sp = (unsigned long) ka->sa.sa_restorer; if (used_math()) { - unsigned long fx_aligned, math_size; - - sp = alloc_mathframe(sp, 1, &fx_aligned, &math_size); - *fpstate = (struct _fpstate_ia32 __user *) sp; - if (save_xstate_sig(*fpstate, (void __user *)fx_aligned, - math_size) < 0) + sp = sp - sig_xstate_ia32_size; + *fpstate = (struct _fpstate_ia32 *) sp; + if (save_i387_xstate_ia32(*fpstate) < 0) return (void __user *) -1L; } @@ -452,7 +448,7 @@ int ia32_setup_frame(int sig, struct k_sigaction *ka, * These are actually not used anymore, but left because some * gdb versions depend on them as a marker. */ - put_user_ex(*((u64 *)&code), (u64 __user *)frame->retcode); + put_user_ex(*((u64 *)&code), (u64 *)frame->retcode); } put_user_catch(err); if (err) @@ -533,7 +529,7 @@ int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, * Not actually used anymore, but left because some gdb * versions need it. */ - put_user_ex(*((u64 *)&code), (u64 __user *)frame->retcode); + put_user_ex(*((u64 *)&code), (u64 *)frame->retcode); } put_user_catch(err); if (err) diff --git a/trunk/arch/x86/ia32/sys_ia32.c b/trunk/arch/x86/ia32/sys_ia32.c index c5b938d92eab..4540bece0946 100644 --- a/trunk/arch/x86/ia32/sys_ia32.c +++ b/trunk/arch/x86/ia32/sys_ia32.c @@ -287,7 +287,7 @@ asmlinkage long sys32_sigaction(int sig, struct old_sigaction32 __user *act, return ret; } -asmlinkage long sys32_waitpid(compat_pid_t pid, unsigned int __user *stat_addr, +asmlinkage long sys32_waitpid(compat_pid_t pid, unsigned int *stat_addr, int options) { return compat_sys_wait4(pid, stat_addr, options, NULL); diff --git a/trunk/arch/x86/include/asm/alternative.h b/trunk/arch/x86/include/asm/alternative.h index 444704c8e186..70780689599a 100644 --- a/trunk/arch/x86/include/asm/alternative.h +++ b/trunk/arch/x86/include/asm/alternative.h @@ -60,7 +60,7 @@ extern void alternatives_smp_module_add(struct module *mod, char *name, void *locks, void *locks_end, void *text, void *text_end); extern void alternatives_smp_module_del(struct module *mod); -extern void alternatives_enable_smp(void); +extern void alternatives_smp_switch(int smp); extern int alternatives_text_reserved(void *start, void *end); extern bool skip_smp_alternatives; #else @@ -68,7 +68,7 @@ static inline void alternatives_smp_module_add(struct module *mod, char *name, void *locks, void *locks_end, void *text, void *text_end) {} static inline void alternatives_smp_module_del(struct module *mod) {} -static inline void alternatives_enable_smp(void) {} +static inline void alternatives_smp_switch(int smp) {} static inline int alternatives_text_reserved(void *start, void *end) { return 0; diff --git a/trunk/arch/x86/include/asm/bitops.h b/trunk/arch/x86/include/asm/bitops.h index 6dfd0195bb55..72f5009deb5a 100644 --- a/trunk/arch/x86/include/asm/bitops.h +++ b/trunk/arch/x86/include/asm/bitops.h @@ -355,7 +355,7 @@ static int test_bit(int nr, const volatile unsigned long *addr); */ static inline unsigned long __ffs(unsigned long word) { - asm("rep; bsf %1,%0" + asm("bsf %1,%0" : "=r" (word) : "rm" (word)); return word; @@ -369,7 +369,7 @@ static inline unsigned long __ffs(unsigned long word) */ static inline unsigned long ffz(unsigned long word) { - asm("rep; bsf %1,%0" + asm("bsf %1,%0" : "=r" (word) : "r" (~word)); return word; @@ -417,9 +417,10 @@ static inline int ffs(int x) * We cannot do this on 32 bits because at the very least some * 486 CPUs did not behave this way. */ + long tmp = -1; asm("bsfl %1,%0" : "=r" (r) - : "rm" (x), "0" (-1)); + : "rm" (x), "0" (tmp)); #elif defined(CONFIG_X86_CMOV) asm("bsfl %1,%0\n\t" "cmovzl %2,%0" @@ -458,9 +459,10 @@ static inline int fls(int x) * We cannot do this on 32 bits because at the very least some * 486 CPUs did not behave this way. */ + long tmp = -1; asm("bsrl %1,%0" : "=r" (r) - : "rm" (x), "0" (-1)); + : "rm" (x), "0" (tmp)); #elif defined(CONFIG_X86_CMOV) asm("bsrl %1,%0\n\t" "cmovzl %2,%0" @@ -488,13 +490,13 @@ static inline int fls(int x) #ifdef CONFIG_X86_64 static __always_inline int fls64(__u64 x) { - int bitpos = -1; + long bitpos = -1; /* * AMD64 says BSRQ won't clobber the dest reg if x==0; Intel64 says the * dest reg is undefined if x==0, but their CPU architect says its * value is written to set it to the same as before. */ - asm("bsrq %1,%q0" + asm("bsrq %1,%0" : "+r" (bitpos) : "rm" (x)); return bitpos + 1; diff --git a/trunk/arch/x86/include/asm/calling.h b/trunk/arch/x86/include/asm/calling.h index 7f8422a28a46..a9e3a740f697 100644 --- a/trunk/arch/x86/include/asm/calling.h +++ b/trunk/arch/x86/include/asm/calling.h @@ -49,36 +49,38 @@ For 32-bit we have the following conventions - kernel is built with #include "dwarf2.h" /* - * 64-bit system call stack frame layout defines and helpers, - * for assembly code: + * 64-bit system call stack frame layout defines and helpers, for + * assembly code (note that the seemingly unnecessary parentheses + * are to prevent cpp from inserting spaces in expressions that get + * passed to macros): */ -#define R15 0 -#define R14 8 -#define R13 16 -#define R12 24 -#define RBP 32 -#define RBX 40 +#define R15 (0) +#define R14 (8) +#define R13 (16) +#define R12 (24) +#define RBP (32) +#define RBX (40) /* arguments: interrupts/non tracing syscalls only save up to here: */ -#define R11 48 -#define R10 56 -#define R9 64 -#define R8 72 -#define RAX 80 -#define RCX 88 -#define RDX 96 -#define RSI 104 -#define RDI 112 -#define ORIG_RAX 120 /* + error_code */ +#define R11 (48) +#define R10 (56) +#define R9 (64) +#define R8 (72) +#define RAX (80) +#define RCX (88) +#define RDX (96) +#define RSI (104) +#define RDI (112) +#define ORIG_RAX (120) /* + error_code */ /* end of arguments */ /* cpu exception frame or undefined in case of fast syscall: */ -#define RIP 128 -#define CS 136 -#define EFLAGS 144 -#define RSP 152 -#define SS 160 +#define RIP (128) +#define CS (136) +#define EFLAGS (144) +#define RSP (152) +#define SS (160) #define ARGOFFSET R11 #define SWFRAME ORIG_RAX diff --git a/trunk/arch/x86/include/asm/cpufeature.h b/trunk/arch/x86/include/asm/cpufeature.h index 16cae425d1f8..6b7ee5ff6820 100644 --- a/trunk/arch/x86/include/asm/cpufeature.h +++ b/trunk/arch/x86/include/asm/cpufeature.h @@ -97,7 +97,6 @@ #define X86_FEATURE_EXTD_APICID (3*32+26) /* has extended APICID (8 bits) */ #define X86_FEATURE_AMD_DCM (3*32+27) /* multi-node processor */ #define X86_FEATURE_APERFMPERF (3*32+28) /* APERFMPERF */ -#define X86_FEATURE_EAGER_FPU (3*32+29) /* "eagerfpu" Non lazy FPU restore */ /* Intel-defined CPU features, CPUID level 0x00000001 (ecx), word 4 */ #define X86_FEATURE_XMM3 (4*32+ 0) /* "pni" SSE-3 */ @@ -210,7 +209,6 @@ #define X86_FEATURE_RTM (9*32+11) /* Restricted Transactional Memory */ #define X86_FEATURE_RDSEED (9*32+18) /* The RDSEED instruction */ #define X86_FEATURE_ADX (9*32+19) /* The ADCX and ADOX instructions */ -#define X86_FEATURE_SMAP (9*32+20) /* Supervisor Mode Access Prevention */ #if defined(__KERNEL__) && !defined(__ASSEMBLY__) @@ -301,14 +299,12 @@ extern const char * const x86_power_flags[32]; #define cpu_has_xmm4_2 boot_cpu_has(X86_FEATURE_XMM4_2) #define cpu_has_x2apic boot_cpu_has(X86_FEATURE_X2APIC) #define cpu_has_xsave boot_cpu_has(X86_FEATURE_XSAVE) -#define cpu_has_xsaveopt boot_cpu_has(X86_FEATURE_XSAVEOPT) #define cpu_has_osxsave boot_cpu_has(X86_FEATURE_OSXSAVE) #define cpu_has_hypervisor boot_cpu_has(X86_FEATURE_HYPERVISOR) #define cpu_has_pclmulqdq boot_cpu_has(X86_FEATURE_PCLMULQDQ) #define cpu_has_perfctr_core boot_cpu_has(X86_FEATURE_PERFCTR_CORE) #define cpu_has_cx8 boot_cpu_has(X86_FEATURE_CX8) #define cpu_has_cx16 boot_cpu_has(X86_FEATURE_CX16) -#define cpu_has_eager_fpu boot_cpu_has(X86_FEATURE_EAGER_FPU) #if defined(CONFIG_X86_INVLPG) || defined(CONFIG_X86_64) # define cpu_has_invlpg 1 diff --git a/trunk/arch/x86/include/asm/fpu-internal.h b/trunk/arch/x86/include/asm/fpu-internal.h index 92f3c6ed817f..75f4c6d6a331 100644 --- a/trunk/arch/x86/include/asm/fpu-internal.h +++ b/trunk/arch/x86/include/asm/fpu-internal.h @@ -12,7 +12,6 @@ #include #include -#include #include #include #include @@ -22,74 +21,42 @@ #include #include -#ifdef CONFIG_X86_64 -# include -# include -int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, - compat_sigset_t *set, struct pt_regs *regs); -int ia32_setup_frame(int sig, struct k_sigaction *ka, - compat_sigset_t *set, struct pt_regs *regs); -#else -# define user_i387_ia32_struct user_i387_struct -# define user32_fxsr_struct user_fxsr_struct -# define ia32_setup_frame __setup_frame -# define ia32_setup_rt_frame __setup_rt_frame -#endif - -extern unsigned int mxcsr_feature_mask; +extern unsigned int sig_xstate_size; extern void fpu_init(void); -extern void eager_fpu_init(void); DECLARE_PER_CPU(struct task_struct *, fpu_owner_task); -extern void convert_from_fxsr(struct user_i387_ia32_struct *env, - struct task_struct *tsk); -extern void convert_to_fxsr(struct task_struct *tsk, - const struct user_i387_ia32_struct *env); - extern user_regset_active_fn fpregs_active, xfpregs_active; extern user_regset_get_fn fpregs_get, xfpregs_get, fpregs_soft_get, xstateregs_get; extern user_regset_set_fn fpregs_set, xfpregs_set, fpregs_soft_set, xstateregs_set; + /* * xstateregs_active == fpregs_active. Please refer to the comment * at the definition of fpregs_active. */ #define xstateregs_active fpregs_active +extern struct _fpx_sw_bytes fx_sw_reserved; +#ifdef CONFIG_IA32_EMULATION +extern unsigned int sig_xstate_ia32_size; +extern struct _fpx_sw_bytes fx_sw_reserved_ia32; +struct _fpstate_ia32; +struct _xstate_ia32; +extern int save_i387_xstate_ia32(void __user *buf); +extern int restore_i387_xstate_ia32(void __user *buf); +#endif + #ifdef CONFIG_MATH_EMULATION -# define HAVE_HWFP (boot_cpu_data.hard_math) extern void finit_soft_fpu(struct i387_soft_struct *soft); #else -# define HAVE_HWFP 1 static inline void finit_soft_fpu(struct i387_soft_struct *soft) {} #endif -static inline int is_ia32_compat_frame(void) -{ - return config_enabled(CONFIG_IA32_EMULATION) && - test_thread_flag(TIF_IA32); -} - -static inline int is_ia32_frame(void) -{ - return config_enabled(CONFIG_X86_32) || is_ia32_compat_frame(); -} - -static inline int is_x32_frame(void) -{ - return config_enabled(CONFIG_X86_X32_ABI) && test_thread_flag(TIF_X32); -} - #define X87_FSW_ES (1 << 7) /* Exception Summary */ -static __always_inline __pure bool use_eager_fpu(void) -{ - return static_cpu_has(X86_FEATURE_EAGER_FPU); -} - static __always_inline __pure bool use_xsaveopt(void) { return static_cpu_has(X86_FEATURE_XSAVEOPT); @@ -105,13 +72,6 @@ static __always_inline __pure bool use_fxsr(void) return static_cpu_has(X86_FEATURE_FXSR); } -static inline void fx_finit(struct i387_fxsave_struct *fx) -{ - memset(fx, 0, xstate_size); - fx->cwd = 0x37f; - fx->mxcsr = MXCSR_DEFAULT; -} - extern void __sanitize_i387_state(struct task_struct *); static inline void sanitize_i387_state(struct task_struct *tsk) @@ -121,88 +81,131 @@ static inline void sanitize_i387_state(struct task_struct *tsk) __sanitize_i387_state(tsk); } -#define check_insn(insn, output, input...) \ -({ \ - int err; \ - asm volatile("1:" #insn "\n\t" \ - "2:\n" \ - ".section .fixup,\"ax\"\n" \ - "3: movl $-1,%[err]\n" \ - " jmp 2b\n" \ - ".previous\n" \ - _ASM_EXTABLE(1b, 3b) \ - : [err] "=r" (err), output \ - : "0"(0), input); \ - err; \ -}) - -static inline int fsave_user(struct i387_fsave_struct __user *fx) +#ifdef CONFIG_X86_64 +static inline int fxrstor_checking(struct i387_fxsave_struct *fx) { - return check_insn(fnsave %[fx]; fwait, [fx] "=m" (*fx), "m" (*fx)); + int err; + + /* See comment in fxsave() below. */ +#ifdef CONFIG_AS_FXSAVEQ + asm volatile("1: fxrstorq %[fx]\n\t" + "2:\n" + ".section .fixup,\"ax\"\n" + "3: movl $-1,%[err]\n" + " jmp 2b\n" + ".previous\n" + _ASM_EXTABLE(1b, 3b) + : [err] "=r" (err) + : [fx] "m" (*fx), "0" (0)); +#else + asm volatile("1: rex64/fxrstor (%[fx])\n\t" + "2:\n" + ".section .fixup,\"ax\"\n" + "3: movl $-1,%[err]\n" + " jmp 2b\n" + ".previous\n" + _ASM_EXTABLE(1b, 3b) + : [err] "=r" (err) + : [fx] "R" (fx), "m" (*fx), "0" (0)); +#endif + return err; } static inline int fxsave_user(struct i387_fxsave_struct __user *fx) { - if (config_enabled(CONFIG_X86_32)) - return check_insn(fxsave %[fx], [fx] "=m" (*fx), "m" (*fx)); - else if (config_enabled(CONFIG_AS_FXSAVEQ)) - return check_insn(fxsaveq %[fx], [fx] "=m" (*fx), "m" (*fx)); + int err; - /* See comment in fpu_fxsave() below. */ - return check_insn(rex64/fxsave (%[fx]), "=m" (*fx), [fx] "R" (fx)); + /* + * Clear the bytes not touched by the fxsave and reserved + * for the SW usage. + */ + err = __clear_user(&fx->sw_reserved, + sizeof(struct _fpx_sw_bytes)); + if (unlikely(err)) + return -EFAULT; + + /* See comment in fxsave() below. */ +#ifdef CONFIG_AS_FXSAVEQ + asm volatile("1: fxsaveq %[fx]\n\t" + "2:\n" + ".section .fixup,\"ax\"\n" + "3: movl $-1,%[err]\n" + " jmp 2b\n" + ".previous\n" + _ASM_EXTABLE(1b, 3b) + : [err] "=r" (err), [fx] "=m" (*fx) + : "0" (0)); +#else + asm volatile("1: rex64/fxsave (%[fx])\n\t" + "2:\n" + ".section .fixup,\"ax\"\n" + "3: movl $-1,%[err]\n" + " jmp 2b\n" + ".previous\n" + _ASM_EXTABLE(1b, 3b) + : [err] "=r" (err), "=m" (*fx) + : [fx] "R" (fx), "0" (0)); +#endif + if (unlikely(err) && + __clear_user(fx, sizeof(struct i387_fxsave_struct))) + err = -EFAULT; + /* No need to clear here because the caller clears USED_MATH */ + return err; } -static inline int fxrstor_checking(struct i387_fxsave_struct *fx) +static inline void fpu_fxsave(struct fpu *fpu) { - if (config_enabled(CONFIG_X86_32)) - return check_insn(fxrstor %[fx], "=m" (*fx), [fx] "m" (*fx)); - else if (config_enabled(CONFIG_AS_FXSAVEQ)) - return check_insn(fxrstorq %[fx], "=m" (*fx), [fx] "m" (*fx)); + /* Using "rex64; fxsave %0" is broken because, if the memory operand + uses any extended registers for addressing, a second REX prefix + will be generated (to the assembler, rex64 followed by semicolon + is a separate instruction), and hence the 64-bitness is lost. */ - /* See comment in fpu_fxsave() below. */ - return check_insn(rex64/fxrstor (%[fx]), "=m" (*fx), [fx] "R" (fx), - "m" (*fx)); +#ifdef CONFIG_AS_FXSAVEQ + /* Using "fxsaveq %0" would be the ideal choice, but is only supported + starting with gas 2.16. */ + __asm__ __volatile__("fxsaveq %0" + : "=m" (fpu->state->fxsave)); +#else + /* Using, as a workaround, the properly prefixed form below isn't + accepted by any binutils version so far released, complaining that + the same type of prefix is used twice if an extended register is + needed for addressing (fix submitted to mainline 2005-11-21). + asm volatile("rex64/fxsave %0" + : "=m" (fpu->state->fxsave)); + This, however, we can work around by forcing the compiler to select + an addressing mode that doesn't require extended registers. */ + asm volatile("rex64/fxsave (%[fx])" + : "=m" (fpu->state->fxsave) + : [fx] "R" (&fpu->state->fxsave)); +#endif } -static inline int frstor_checking(struct i387_fsave_struct *fx) +#else /* CONFIG_X86_32 */ + +/* perform fxrstor iff the processor has extended states, otherwise frstor */ +static inline int fxrstor_checking(struct i387_fxsave_struct *fx) { - return check_insn(frstor %[fx], "=m" (*fx), [fx] "m" (*fx)); + /* + * The "nop" is needed to make the instructions the same + * length. + */ + alternative_input( + "nop ; frstor %1", + "fxrstor %1", + X86_FEATURE_FXSR, + "m" (*fx)); + + return 0; } static inline void fpu_fxsave(struct fpu *fpu) { - if (config_enabled(CONFIG_X86_32)) - asm volatile( "fxsave %[fx]" : [fx] "=m" (fpu->state->fxsave)); - else if (config_enabled(CONFIG_AS_FXSAVEQ)) - asm volatile("fxsaveq %0" : "=m" (fpu->state->fxsave)); - else { - /* Using "rex64; fxsave %0" is broken because, if the memory - * operand uses any extended registers for addressing, a second - * REX prefix will be generated (to the assembler, rex64 - * followed by semicolon is a separate instruction), and hence - * the 64-bitness is lost. - * - * Using "fxsaveq %0" would be the ideal choice, but is only - * supported starting with gas 2.16. - * - * Using, as a workaround, the properly prefixed form below - * isn't accepted by any binutils version so far released, - * complaining that the same type of prefix is used twice if - * an extended register is needed for addressing (fix submitted - * to mainline 2005-11-21). - * - * asm volatile("rex64/fxsave %0" : "=m" (fpu->state->fxsave)); - * - * This, however, we can work around by forcing the compiler to - * select an addressing mode that doesn't require extended - * registers. - */ - asm volatile( "rex64/fxsave (%[fx])" - : "=m" (fpu->state->fxsave) - : [fx] "R" (&fpu->state->fxsave)); - } + asm volatile("fxsave %[fx]" + : [fx] "=m" (fpu->state->fxsave)); } +#endif /* CONFIG_X86_64 */ + /* * These must be called with preempt disabled. Returns * 'true' if the FPU state is still intact. @@ -245,14 +248,17 @@ static inline int __save_init_fpu(struct task_struct *tsk) return fpu_save_init(&tsk->thread.fpu); } +static inline int fpu_fxrstor_checking(struct fpu *fpu) +{ + return fxrstor_checking(&fpu->state->fxsave); +} + static inline int fpu_restore_checking(struct fpu *fpu) { if (use_xsave()) - return fpu_xrstor_checking(&fpu->state->xsave); - else if (use_fxsr()) - return fxrstor_checking(&fpu->state->fxsave); + return fpu_xrstor_checking(fpu); else - return frstor_checking(&fpu->state->fsave); + return fpu_fxrstor_checking(fpu); } static inline int restore_fpu_checking(struct task_struct *tsk) @@ -304,52 +310,15 @@ static inline void __thread_set_has_fpu(struct task_struct *tsk) static inline void __thread_fpu_end(struct task_struct *tsk) { __thread_clear_has_fpu(tsk); - if (!use_eager_fpu()) - stts(); + stts(); } static inline void __thread_fpu_begin(struct task_struct *tsk) { - if (!use_eager_fpu()) - clts(); + clts(); __thread_set_has_fpu(tsk); } -static inline void __drop_fpu(struct task_struct *tsk) -{ - if (__thread_has_fpu(tsk)) { - /* Ignore delayed exceptions from user space */ - asm volatile("1: fwait\n" - "2:\n" - _ASM_EXTABLE(1b, 2b)); - __thread_fpu_end(tsk); - } -} - -static inline void drop_fpu(struct task_struct *tsk) -{ - /* - * Forget coprocessor state.. - */ - preempt_disable(); - tsk->fpu_counter = 0; - __drop_fpu(tsk); - clear_used_math(); - preempt_enable(); -} - -static inline void drop_init_fpu(struct task_struct *tsk) -{ - if (!use_eager_fpu()) - drop_fpu(tsk); - else { - if (use_xsave()) - xrstor_state(init_xstate_buf, -1); - else - fxrstor_checking(&init_xstate_buf->i387); - } -} - /* * FPU state switching for scheduling. * @@ -383,12 +352,7 @@ static inline fpu_switch_t switch_fpu_prepare(struct task_struct *old, struct ta { fpu_switch_t fpu; - /* - * If the task has used the math, pre-load the FPU on xsave processors - * or if the past 5 consecutive context-switches used math. - */ - fpu.preload = tsk_used_math(new) && (use_eager_fpu() || - new->fpu_counter > 5); + fpu.preload = tsk_used_math(new) && new->fpu_counter > 5; if (__thread_has_fpu(old)) { if (!__save_init_fpu(old)) cpu = ~0; @@ -400,14 +364,14 @@ static inline fpu_switch_t switch_fpu_prepare(struct task_struct *old, struct ta new->fpu_counter++; __thread_set_has_fpu(new); prefetch(new->thread.fpu.state); - } else if (!use_eager_fpu()) + } else stts(); } else { old->fpu_counter = 0; old->thread.fpu.last_cpu = ~0; if (fpu.preload) { new->fpu_counter++; - if (!use_eager_fpu() && fpu_lazy_restore(new, cpu)) + if (fpu_lazy_restore(new, cpu)) fpu.preload = 0; else prefetch(new->thread.fpu.state); @@ -427,54 +391,50 @@ static inline void switch_fpu_finish(struct task_struct *new, fpu_switch_t fpu) { if (fpu.preload) { if (unlikely(restore_fpu_checking(new))) - drop_init_fpu(new); + __thread_fpu_end(new); } } /* * Signal frame handlers... */ -extern int save_xstate_sig(void __user *buf, void __user *fx, int size); -extern int __restore_xstate_sig(void __user *buf, void __user *fx, int size); +extern int save_i387_xstate(void __user *buf); +extern int restore_i387_xstate(void __user *buf); -static inline int xstate_sigframe_size(void) +static inline void __clear_fpu(struct task_struct *tsk) { - return use_xsave() ? xstate_size + FP_XSTATE_MAGIC2_SIZE : xstate_size; -} - -static inline int restore_xstate_sig(void __user *buf, int ia32_frame) -{ - void __user *buf_fx = buf; - int size = xstate_sigframe_size(); - - if (ia32_frame && use_fxsr()) { - buf_fx = buf + sizeof(struct i387_fsave_struct); - size += sizeof(struct i387_fsave_struct); + if (__thread_has_fpu(tsk)) { + /* Ignore delayed exceptions from user space */ + asm volatile("1: fwait\n" + "2:\n" + _ASM_EXTABLE(1b, 2b)); + __thread_fpu_end(tsk); } - - return __restore_xstate_sig(buf, buf_fx, size); } /* - * Need to be preemption-safe. + * The actual user_fpu_begin/end() functions + * need to be preemption-safe. * - * NOTE! user_fpu_begin() must be used only immediately before restoring - * it. This function does not do any save/restore on their own. + * NOTE! user_fpu_end() must be used only after you + * have saved the FP state, and user_fpu_begin() must + * be used only immediately before restoring it. + * These functions do not do any save/restore on + * their own. */ -static inline void user_fpu_begin(void) +static inline void user_fpu_end(void) { preempt_disable(); - if (!user_has_fpu()) - __thread_fpu_begin(current); + __thread_fpu_end(current); preempt_enable(); } -static inline void __save_fpu(struct task_struct *tsk) +static inline void user_fpu_begin(void) { - if (use_xsave()) - xsave_state(&tsk->thread.fpu.state->xsave, -1); - else - fpu_fxsave(&tsk->thread.fpu); + preempt_disable(); + if (!user_has_fpu()) + __thread_fpu_begin(current); + preempt_enable(); } /* @@ -483,18 +443,19 @@ static inline void __save_fpu(struct task_struct *tsk) static inline void save_init_fpu(struct task_struct *tsk) { WARN_ON_ONCE(!__thread_has_fpu(tsk)); - - if (use_eager_fpu()) { - __save_fpu(tsk); - return; - } - preempt_disable(); __save_init_fpu(tsk); __thread_fpu_end(tsk); preempt_enable(); } +static inline void clear_fpu(struct task_struct *tsk) +{ + preempt_disable(); + __clear_fpu(tsk); + preempt_enable(); +} + /* * i387 state interaction */ @@ -549,34 +510,11 @@ static inline void fpu_free(struct fpu *fpu) } } -static inline void fpu_copy(struct task_struct *dst, struct task_struct *src) +static inline void fpu_copy(struct fpu *dst, struct fpu *src) { - if (use_eager_fpu()) { - memset(&dst->thread.fpu.state->xsave, 0, xstate_size); - __save_fpu(dst); - } else { - struct fpu *dfpu = &dst->thread.fpu; - struct fpu *sfpu = &src->thread.fpu; - - unlazy_fpu(src); - memcpy(dfpu->state, sfpu->state, xstate_size); - } + memcpy(dst->state, src->state, xstate_size); } -static inline unsigned long -alloc_mathframe(unsigned long sp, int ia32_frame, unsigned long *buf_fx, - unsigned long *size) -{ - unsigned long frame_size = xstate_sigframe_size(); - - *buf_fx = sp = round_down(sp - frame_size, 64); - if (ia32_frame && use_fxsr()) { - frame_size += sizeof(struct i387_fsave_struct); - sp -= sizeof(struct i387_fsave_struct); - } - - *size = frame_size; - return sp; -} +extern void fpu_finit(struct fpu *fpu); #endif diff --git a/trunk/arch/x86/include/asm/ftrace.h b/trunk/arch/x86/include/asm/ftrace.h index 9a25b522d377..b0767bc08740 100644 --- a/trunk/arch/x86/include/asm/ftrace.h +++ b/trunk/arch/x86/include/asm/ftrace.h @@ -3,54 +3,38 @@ #ifdef __ASSEMBLY__ - /* skip is set if the stack was already partially adjusted */ - .macro MCOUNT_SAVE_FRAME skip=0 - /* - * We add enough stack to save all regs. - */ - subq $(SS+8-\skip), %rsp - movq %rax, RAX(%rsp) - movq %rcx, RCX(%rsp) - movq %rdx, RDX(%rsp) - movq %rsi, RSI(%rsp) - movq %rdi, RDI(%rsp) - movq %r8, R8(%rsp) - movq %r9, R9(%rsp) - /* Move RIP to its proper location */ - movq SS+8(%rsp), %rdx - movq %rdx, RIP(%rsp) + .macro MCOUNT_SAVE_FRAME + /* taken from glibc */ + subq $0x38, %rsp + movq %rax, (%rsp) + movq %rcx, 8(%rsp) + movq %rdx, 16(%rsp) + movq %rsi, 24(%rsp) + movq %rdi, 32(%rsp) + movq %r8, 40(%rsp) + movq %r9, 48(%rsp) .endm - .macro MCOUNT_RESTORE_FRAME skip=0 - movq R9(%rsp), %r9 - movq R8(%rsp), %r8 - movq RDI(%rsp), %rdi - movq RSI(%rsp), %rsi - movq RDX(%rsp), %rdx - movq RCX(%rsp), %rcx - movq RAX(%rsp), %rax - addq $(SS+8-\skip), %rsp + .macro MCOUNT_RESTORE_FRAME + movq 48(%rsp), %r9 + movq 40(%rsp), %r8 + movq 32(%rsp), %rdi + movq 24(%rsp), %rsi + movq 16(%rsp), %rdx + movq 8(%rsp), %rcx + movq (%rsp), %rax + addq $0x38, %rsp .endm #endif #ifdef CONFIG_FUNCTION_TRACER -#ifdef CC_USING_FENTRY -# define MCOUNT_ADDR ((long)(__fentry__)) -#else -# define MCOUNT_ADDR ((long)(mcount)) -#endif +#define MCOUNT_ADDR ((long)(mcount)) #define MCOUNT_INSN_SIZE 5 /* sizeof mcount call */ -#ifdef CONFIG_DYNAMIC_FTRACE -#define ARCH_SUPPORTS_FTRACE_OPS 1 -#define ARCH_SUPPORTS_FTRACE_SAVE_REGS -#endif - #ifndef __ASSEMBLY__ extern void mcount(void); extern atomic_t modifying_ftrace_code; -extern void __fentry__(void); static inline unsigned long ftrace_call_adjust(unsigned long addr) { diff --git a/trunk/arch/x86/include/asm/hardirq.h b/trunk/arch/x86/include/asm/hardirq.h index 81f04cee5f74..d3895dbf4ddb 100644 --- a/trunk/arch/x86/include/asm/hardirq.h +++ b/trunk/arch/x86/include/asm/hardirq.h @@ -18,10 +18,6 @@ typedef struct { #ifdef CONFIG_SMP unsigned int irq_resched_count; unsigned int irq_call_count; - /* - * irq_tlb_count is double-counted in irq_call_count, so it must be - * subtracted from irq_call_count when displaying irq_call_count - */ unsigned int irq_tlb_count; #endif #ifdef CONFIG_X86_THERMAL_VECTOR diff --git a/trunk/arch/x86/include/asm/hpet.h b/trunk/arch/x86/include/asm/hpet.h index 434e2106cc87..2c392d663dce 100644 --- a/trunk/arch/x86/include/asm/hpet.h +++ b/trunk/arch/x86/include/asm/hpet.h @@ -35,6 +35,8 @@ #define HPET_ID_NUMBER_SHIFT 8 #define HPET_ID_VENDOR_SHIFT 16 +#define HPET_ID_VENDOR_8086 0x8086 + #define HPET_CFG_ENABLE 0x001 #define HPET_CFG_LEGACY 0x002 #define HPET_LEGACY_8254 2 diff --git a/trunk/arch/x86/include/asm/i387.h b/trunk/arch/x86/include/asm/i387.h index ed8089d69094..257d9cca214f 100644 --- a/trunk/arch/x86/include/asm/i387.h +++ b/trunk/arch/x86/include/asm/i387.h @@ -19,37 +19,12 @@ struct pt_regs; struct user_i387_struct; extern int init_fpu(struct task_struct *child); -extern void fpu_finit(struct fpu *fpu); extern int dump_fpu(struct pt_regs *, struct user_i387_struct *); extern void math_state_restore(void); extern bool irq_fpu_usable(void); - -/* - * Careful: __kernel_fpu_begin/end() must be called with preempt disabled - * and they don't touch the preempt state on their own. - * If you enable preemption after __kernel_fpu_begin(), preempt notifier - * should call the __kernel_fpu_end() to prevent the kernel/user FPU - * state from getting corrupted. KVM for example uses this model. - * - * All other cases use kernel_fpu_begin/end() which disable preemption - * during kernel FPU usage. - */ -extern void __kernel_fpu_begin(void); -extern void __kernel_fpu_end(void); - -static inline void kernel_fpu_begin(void) -{ - WARN_ON_ONCE(!irq_fpu_usable()); - preempt_disable(); - __kernel_fpu_begin(); -} - -static inline void kernel_fpu_end(void) -{ - __kernel_fpu_end(); - preempt_enable(); -} +extern void kernel_fpu_begin(void); +extern void kernel_fpu_end(void); /* * Some instructions like VIA's padlock instructions generate a spurious diff --git a/trunk/arch/x86/include/asm/iommu_table.h b/trunk/arch/x86/include/asm/iommu_table.h index f42a04735a0a..f229b13a5f30 100644 --- a/trunk/arch/x86/include/asm/iommu_table.h +++ b/trunk/arch/x86/include/asm/iommu_table.h @@ -48,7 +48,7 @@ struct iommu_table_entry { #define __IOMMU_INIT(_detect, _depend, _early_init, _late_init, _finish)\ - static const struct iommu_table_entry \ + static const struct iommu_table_entry const \ __iommu_entry_##_detect __used \ __attribute__ ((unused, __section__(".iommu_table"), \ aligned((sizeof(void *))))) \ @@ -63,10 +63,10 @@ struct iommu_table_entry { * to stop detecting the other IOMMUs after yours has been detected. */ #define IOMMU_INIT_POST(_detect) \ - __IOMMU_INIT(_detect, pci_swiotlb_detect_4gb, NULL, NULL, 0) + __IOMMU_INIT(_detect, pci_swiotlb_detect_4gb, 0, 0, 0) #define IOMMU_INIT_POST_FINISH(detect) \ - __IOMMU_INIT(_detect, pci_swiotlb_detect_4gb, NULL, NULL, 1) + __IOMMU_INIT(_detect, pci_swiotlb_detect_4gb, 0, 0, 1) /* * A more sophisticated version of IOMMU_INIT. This variant requires: diff --git a/trunk/arch/x86/include/asm/kprobes.h b/trunk/arch/x86/include/asm/kprobes.h index d3ddd17405d0..547882539157 100644 --- a/trunk/arch/x86/include/asm/kprobes.h +++ b/trunk/arch/x86/include/asm/kprobes.h @@ -27,7 +27,6 @@ #include #define __ARCH_WANT_KPROBES_INSN_SLOT -#define ARCH_SUPPORTS_KPROBES_ON_FTRACE struct pt_regs; struct kprobe; diff --git a/trunk/arch/x86/include/asm/kvm.h b/trunk/arch/x86/include/asm/kvm.h index 41e08cb6a092..246617efd67f 100644 --- a/trunk/arch/x86/include/asm/kvm.h +++ b/trunk/arch/x86/include/asm/kvm.h @@ -9,22 +9,6 @@ #include #include -#define DE_VECTOR 0 -#define DB_VECTOR 1 -#define BP_VECTOR 3 -#define OF_VECTOR 4 -#define BR_VECTOR 5 -#define UD_VECTOR 6 -#define NM_VECTOR 7 -#define DF_VECTOR 8 -#define TS_VECTOR 10 -#define NP_VECTOR 11 -#define SS_VECTOR 12 -#define GP_VECTOR 13 -#define PF_VECTOR 14 -#define MF_VECTOR 16 -#define MC_VECTOR 18 - /* Select x86 specific features in */ #define __KVM_HAVE_PIT #define __KVM_HAVE_IOAPIC diff --git a/trunk/arch/x86/include/asm/kvm_host.h b/trunk/arch/x86/include/asm/kvm_host.h index 1eaa6b056670..09155d64cf7e 100644 --- a/trunk/arch/x86/include/asm/kvm_host.h +++ b/trunk/arch/x86/include/asm/kvm_host.h @@ -75,6 +75,22 @@ #define KVM_HPAGE_MASK(x) (~(KVM_HPAGE_SIZE(x) - 1)) #define KVM_PAGES_PER_HPAGE(x) (KVM_HPAGE_SIZE(x) / PAGE_SIZE) +#define DE_VECTOR 0 +#define DB_VECTOR 1 +#define BP_VECTOR 3 +#define OF_VECTOR 4 +#define BR_VECTOR 5 +#define UD_VECTOR 6 +#define NM_VECTOR 7 +#define DF_VECTOR 8 +#define TS_VECTOR 10 +#define NP_VECTOR 11 +#define SS_VECTOR 12 +#define GP_VECTOR 13 +#define PF_VECTOR 14 +#define MF_VECTOR 16 +#define MC_VECTOR 18 + #define SELECTOR_TI_MASK (1 << 2) #define SELECTOR_RPL_MASK 0x03 diff --git a/trunk/arch/x86/include/asm/mce.h b/trunk/arch/x86/include/asm/mce.h index 54d73b1f00a0..441520e4174f 100644 --- a/trunk/arch/x86/include/asm/mce.h +++ b/trunk/arch/x86/include/asm/mce.h @@ -33,14 +33,6 @@ #define MCI_STATUS_PCC (1ULL<<57) /* processor context corrupt */ #define MCI_STATUS_S (1ULL<<56) /* Signaled machine check */ #define MCI_STATUS_AR (1ULL<<55) /* Action required */ -#define MCACOD 0xffff /* MCA Error Code */ - -/* Architecturally defined codes from SDM Vol. 3B Chapter 15 */ -#define MCACOD_SCRUB 0x00C0 /* 0xC0-0xCF Memory Scrubbing */ -#define MCACOD_SCRUBMSK 0xfff0 -#define MCACOD_L3WB 0x017A /* L3 Explicit Writeback */ -#define MCACOD_DATA 0x0134 /* Data Load */ -#define MCACOD_INSTR 0x0150 /* Instruction Fetch */ /* MCi_MISC register defines */ #define MCI_MISC_ADDR_LSB(m) ((m) & 0x3f) @@ -116,9 +108,19 @@ struct mce_log { /* Software defined banks */ #define MCE_EXTENDED_BANK 128 #define MCE_THERMAL_BANK MCE_EXTENDED_BANK + 0 -#define K8_MCE_THRESHOLD_BASE (MCE_EXTENDED_BANK + 1) + +#define K8_MCE_THRESHOLD_BASE (MCE_EXTENDED_BANK + 1) /* MCE_AMD */ +#define K8_MCE_THRESHOLD_BANK_0 (MCE_THRESHOLD_BASE + 0 * 9) +#define K8_MCE_THRESHOLD_BANK_1 (MCE_THRESHOLD_BASE + 1 * 9) +#define K8_MCE_THRESHOLD_BANK_2 (MCE_THRESHOLD_BASE + 2 * 9) +#define K8_MCE_THRESHOLD_BANK_3 (MCE_THRESHOLD_BASE + 3 * 9) +#define K8_MCE_THRESHOLD_BANK_4 (MCE_THRESHOLD_BASE + 4 * 9) +#define K8_MCE_THRESHOLD_BANK_5 (MCE_THRESHOLD_BASE + 5 * 9) +#define K8_MCE_THRESHOLD_DRAM_ECC (MCE_THRESHOLD_BANK_4 + 0) + #ifdef __KERNEL__ + extern void mce_register_decode_chain(struct notifier_block *nb); extern void mce_unregister_decode_chain(struct notifier_block *nb); @@ -161,7 +163,6 @@ DECLARE_PER_CPU(struct device *, mce_device); #ifdef CONFIG_X86_MCE_INTEL extern int mce_cmci_disabled; extern int mce_ignore_ce; -extern int mce_bios_cmci_threshold; void mce_intel_feature_init(struct cpuinfo_x86 *c); void cmci_clear(void); void cmci_reenable(void); diff --git a/trunk/arch/x86/include/asm/microcode.h b/trunk/arch/x86/include/asm/microcode.h index 43d921b4752c..4ebe157bf73d 100644 --- a/trunk/arch/x86/include/asm/microcode.h +++ b/trunk/arch/x86/include/asm/microcode.h @@ -15,8 +15,8 @@ struct microcode_ops { enum ucode_state (*request_microcode_user) (int cpu, const void __user *buf, size_t size); - enum ucode_state (*request_microcode_fw) (int cpu, struct device *, - bool refresh_fw); + enum ucode_state (*request_microcode_fw) (int cpu, + struct device *device); void (*microcode_fini_cpu) (int cpu); @@ -49,6 +49,12 @@ static inline struct microcode_ops * __init init_intel_microcode(void) #ifdef CONFIG_MICROCODE_AMD extern struct microcode_ops * __init init_amd_microcode(void); extern void __exit exit_amd_microcode(void); + +static inline void get_ucode_data(void *to, const u8 *from, size_t n) +{ + memcpy(to, from, n); +} + #else static inline struct microcode_ops * __init init_amd_microcode(void) { diff --git a/trunk/arch/x86/include/asm/perf_event.h b/trunk/arch/x86/include/asm/perf_event.h index 4fabcdf1cfa7..dab39350e51e 100644 --- a/trunk/arch/x86/include/asm/perf_event.h +++ b/trunk/arch/x86/include/asm/perf_event.h @@ -196,16 +196,11 @@ static inline u32 get_ibs_caps(void) { return 0; } extern void perf_events_lapic_init(void); /* - * Abuse bits {3,5} of the cpu eflags register. These flags are otherwise - * unused and ABI specified to be 0, so nobody should care what we do with - * them. - * - * EXACT - the IP points to the exact instruction that triggered the - * event (HW bugs exempt). - * VM - original X86_VM_MASK; see set_linear_ip(). + * Abuse bit 3 of the cpu eflags register to indicate proper PEBS IP fixups. + * This flag is otherwise unused and ABI specified to be 0, so nobody should + * care what we do with it. */ #define PERF_EFLAGS_EXACT (1UL << 3) -#define PERF_EFLAGS_VM (1UL << 5) struct pt_regs; extern unsigned long perf_instruction_pointer(struct pt_regs *regs); @@ -262,6 +257,4 @@ static inline void perf_check_microcode(void) { } static inline void amd_pmu_disable_virt(void) { } #endif -#define arch_perf_out_copy_user copy_from_user_nmi - #endif /* _ASM_X86_PERF_EVENT_H */ diff --git a/trunk/arch/x86/include/asm/perf_regs.h b/trunk/arch/x86/include/asm/perf_regs.h deleted file mode 100644 index 3f2207bfd17b..000000000000 --- a/trunk/arch/x86/include/asm/perf_regs.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef _ASM_X86_PERF_REGS_H -#define _ASM_X86_PERF_REGS_H - -enum perf_event_x86_regs { - PERF_REG_X86_AX, - PERF_REG_X86_BX, - PERF_REG_X86_CX, - PERF_REG_X86_DX, - PERF_REG_X86_SI, - PERF_REG_X86_DI, - PERF_REG_X86_BP, - PERF_REG_X86_SP, - PERF_REG_X86_IP, - PERF_REG_X86_FLAGS, - PERF_REG_X86_CS, - PERF_REG_X86_SS, - PERF_REG_X86_DS, - PERF_REG_X86_ES, - PERF_REG_X86_FS, - PERF_REG_X86_GS, - PERF_REG_X86_R8, - PERF_REG_X86_R9, - PERF_REG_X86_R10, - PERF_REG_X86_R11, - PERF_REG_X86_R12, - PERF_REG_X86_R13, - PERF_REG_X86_R14, - PERF_REG_X86_R15, - - PERF_REG_X86_32_MAX = PERF_REG_X86_GS + 1, - PERF_REG_X86_64_MAX = PERF_REG_X86_R15 + 1, -}; -#endif /* _ASM_X86_PERF_REGS_H */ diff --git a/trunk/arch/x86/include/asm/pgtable_types.h b/trunk/arch/x86/include/asm/pgtable_types.h index db8fec6d2953..013286a10c2c 100644 --- a/trunk/arch/x86/include/asm/pgtable_types.h +++ b/trunk/arch/x86/include/asm/pgtable_types.h @@ -303,9 +303,11 @@ void set_pte_vaddr(unsigned long vaddr, pte_t pte); extern void native_pagetable_reserve(u64 start, u64 end); #ifdef CONFIG_X86_32 -extern void native_pagetable_init(void); +extern void native_pagetable_setup_start(pgd_t *base); +extern void native_pagetable_setup_done(pgd_t *base); #else -#define native_pagetable_init paging_init +#define native_pagetable_setup_start x86_init_pgd_noop +#define native_pagetable_setup_done x86_init_pgd_noop #endif struct seq_file; diff --git a/trunk/arch/x86/include/asm/processor.h b/trunk/arch/x86/include/asm/processor.h index b98c0d958ebb..d048cad9bcad 100644 --- a/trunk/arch/x86/include/asm/processor.h +++ b/trunk/arch/x86/include/asm/processor.h @@ -423,6 +423,7 @@ DECLARE_INIT_PER_CPU(irq_stack_union); DECLARE_PER_CPU(char *, irq_stack_ptr); DECLARE_PER_CPU(unsigned int, irq_count); +extern unsigned long kernel_eflags; extern asmlinkage void ignore_sysret(void); #else /* X86_64 */ #ifdef CONFIG_CC_STACKPROTECTOR @@ -758,8 +759,6 @@ static inline void update_debugctlmsr(unsigned long debugctlmsr) wrmsrl(MSR_IA32_DEBUGCTLMSR, debugctlmsr); } -extern void set_task_blockstep(struct task_struct *task, bool on); - /* * from system description table in BIOS. Mostly for MCA use, but * others may find it useful: diff --git a/trunk/arch/x86/include/asm/rcu.h b/trunk/arch/x86/include/asm/rcu.h deleted file mode 100644 index d1ac07a23979..000000000000 --- a/trunk/arch/x86/include/asm/rcu.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef _ASM_X86_RCU_H -#define _ASM_X86_RCU_H - -#ifndef __ASSEMBLY__ - -#include -#include - -static inline void exception_enter(struct pt_regs *regs) -{ - rcu_user_exit(); -} - -static inline void exception_exit(struct pt_regs *regs) -{ -#ifdef CONFIG_RCU_USER_QS - if (user_mode(regs)) - rcu_user_enter(); -#endif -} - -#else /* __ASSEMBLY__ */ - -#ifdef CONFIG_RCU_USER_QS -# define SCHEDULE_USER call schedule_user -#else -# define SCHEDULE_USER call schedule -#endif - -#endif /* !__ASSEMBLY__ */ - -#endif diff --git a/trunk/arch/x86/include/asm/signal.h b/trunk/arch/x86/include/asm/signal.h index 323973f4abf1..598457cbd0f8 100644 --- a/trunk/arch/x86/include/asm/signal.h +++ b/trunk/arch/x86/include/asm/signal.h @@ -31,10 +31,6 @@ typedef struct { unsigned long sig[_NSIG_WORDS]; } sigset_t; -#ifndef CONFIG_COMPAT -typedef sigset_t compat_sigset_t; -#endif - #else /* Here we must cater to libcs that poke about in kernel headers. */ diff --git a/trunk/arch/x86/include/asm/spinlock.h b/trunk/arch/x86/include/asm/spinlock.h index 33692eaabab5..b315a33867f2 100644 --- a/trunk/arch/x86/include/asm/spinlock.h +++ b/trunk/arch/x86/include/asm/spinlock.h @@ -12,7 +12,8 @@ * Simple spin lock operations. There are two variants, one clears IRQ's * on the local processor, one does not. * - * These are fair FIFO ticket locks, which support up to 2^16 CPUs. + * These are fair FIFO ticket locks, which are currently limited to 256 + * CPUs. * * (the type definitions are in asm/spinlock_types.h) */ diff --git a/trunk/arch/x86/include/asm/svm.h b/trunk/arch/x86/include/asm/svm.h index cdf5674dd23a..f2b83bc7d784 100644 --- a/trunk/arch/x86/include/asm/svm.h +++ b/trunk/arch/x86/include/asm/svm.h @@ -1,135 +1,6 @@ #ifndef __SVM_H #define __SVM_H -#define SVM_EXIT_READ_CR0 0x000 -#define SVM_EXIT_READ_CR3 0x003 -#define SVM_EXIT_READ_CR4 0x004 -#define SVM_EXIT_READ_CR8 0x008 -#define SVM_EXIT_WRITE_CR0 0x010 -#define SVM_EXIT_WRITE_CR3 0x013 -#define SVM_EXIT_WRITE_CR4 0x014 -#define SVM_EXIT_WRITE_CR8 0x018 -#define SVM_EXIT_READ_DR0 0x020 -#define SVM_EXIT_READ_DR1 0x021 -#define SVM_EXIT_READ_DR2 0x022 -#define SVM_EXIT_READ_DR3 0x023 -#define SVM_EXIT_READ_DR4 0x024 -#define SVM_EXIT_READ_DR5 0x025 -#define SVM_EXIT_READ_DR6 0x026 -#define SVM_EXIT_READ_DR7 0x027 -#define SVM_EXIT_WRITE_DR0 0x030 -#define SVM_EXIT_WRITE_DR1 0x031 -#define SVM_EXIT_WRITE_DR2 0x032 -#define SVM_EXIT_WRITE_DR3 0x033 -#define SVM_EXIT_WRITE_DR4 0x034 -#define SVM_EXIT_WRITE_DR5 0x035 -#define SVM_EXIT_WRITE_DR6 0x036 -#define SVM_EXIT_WRITE_DR7 0x037 -#define SVM_EXIT_EXCP_BASE 0x040 -#define SVM_EXIT_INTR 0x060 -#define SVM_EXIT_NMI 0x061 -#define SVM_EXIT_SMI 0x062 -#define SVM_EXIT_INIT 0x063 -#define SVM_EXIT_VINTR 0x064 -#define SVM_EXIT_CR0_SEL_WRITE 0x065 -#define SVM_EXIT_IDTR_READ 0x066 -#define SVM_EXIT_GDTR_READ 0x067 -#define SVM_EXIT_LDTR_READ 0x068 -#define SVM_EXIT_TR_READ 0x069 -#define SVM_EXIT_IDTR_WRITE 0x06a -#define SVM_EXIT_GDTR_WRITE 0x06b -#define SVM_EXIT_LDTR_WRITE 0x06c -#define SVM_EXIT_TR_WRITE 0x06d -#define SVM_EXIT_RDTSC 0x06e -#define SVM_EXIT_RDPMC 0x06f -#define SVM_EXIT_PUSHF 0x070 -#define SVM_EXIT_POPF 0x071 -#define SVM_EXIT_CPUID 0x072 -#define SVM_EXIT_RSM 0x073 -#define SVM_EXIT_IRET 0x074 -#define SVM_EXIT_SWINT 0x075 -#define SVM_EXIT_INVD 0x076 -#define SVM_EXIT_PAUSE 0x077 -#define SVM_EXIT_HLT 0x078 -#define SVM_EXIT_INVLPG 0x079 -#define SVM_EXIT_INVLPGA 0x07a -#define SVM_EXIT_IOIO 0x07b -#define SVM_EXIT_MSR 0x07c -#define SVM_EXIT_TASK_SWITCH 0x07d -#define SVM_EXIT_FERR_FREEZE 0x07e -#define SVM_EXIT_SHUTDOWN 0x07f -#define SVM_EXIT_VMRUN 0x080 -#define SVM_EXIT_VMMCALL 0x081 -#define SVM_EXIT_VMLOAD 0x082 -#define SVM_EXIT_VMSAVE 0x083 -#define SVM_EXIT_STGI 0x084 -#define SVM_EXIT_CLGI 0x085 -#define SVM_EXIT_SKINIT 0x086 -#define SVM_EXIT_RDTSCP 0x087 -#define SVM_EXIT_ICEBP 0x088 -#define SVM_EXIT_WBINVD 0x089 -#define SVM_EXIT_MONITOR 0x08a -#define SVM_EXIT_MWAIT 0x08b -#define SVM_EXIT_MWAIT_COND 0x08c -#define SVM_EXIT_XSETBV 0x08d -#define SVM_EXIT_NPF 0x400 - -#define SVM_EXIT_ERR -1 - -#define SVM_EXIT_REASONS \ - { SVM_EXIT_READ_CR0, "read_cr0" }, \ - { SVM_EXIT_READ_CR3, "read_cr3" }, \ - { SVM_EXIT_READ_CR4, "read_cr4" }, \ - { SVM_EXIT_READ_CR8, "read_cr8" }, \ - { SVM_EXIT_WRITE_CR0, "write_cr0" }, \ - { SVM_EXIT_WRITE_CR3, "write_cr3" }, \ - { SVM_EXIT_WRITE_CR4, "write_cr4" }, \ - { SVM_EXIT_WRITE_CR8, "write_cr8" }, \ - { SVM_EXIT_READ_DR0, "read_dr0" }, \ - { SVM_EXIT_READ_DR1, "read_dr1" }, \ - { SVM_EXIT_READ_DR2, "read_dr2" }, \ - { SVM_EXIT_READ_DR3, "read_dr3" }, \ - { SVM_EXIT_WRITE_DR0, "write_dr0" }, \ - { SVM_EXIT_WRITE_DR1, "write_dr1" }, \ - { SVM_EXIT_WRITE_DR2, "write_dr2" }, \ - { SVM_EXIT_WRITE_DR3, "write_dr3" }, \ - { SVM_EXIT_WRITE_DR5, "write_dr5" }, \ - { SVM_EXIT_WRITE_DR7, "write_dr7" }, \ - { SVM_EXIT_EXCP_BASE + DB_VECTOR, "DB excp" }, \ - { SVM_EXIT_EXCP_BASE + BP_VECTOR, "BP excp" }, \ - { SVM_EXIT_EXCP_BASE + UD_VECTOR, "UD excp" }, \ - { SVM_EXIT_EXCP_BASE + PF_VECTOR, "PF excp" }, \ - { SVM_EXIT_EXCP_BASE + NM_VECTOR, "NM excp" }, \ - { SVM_EXIT_EXCP_BASE + MC_VECTOR, "MC excp" }, \ - { SVM_EXIT_INTR, "interrupt" }, \ - { SVM_EXIT_NMI, "nmi" }, \ - { SVM_EXIT_SMI, "smi" }, \ - { SVM_EXIT_INIT, "init" }, \ - { SVM_EXIT_VINTR, "vintr" }, \ - { SVM_EXIT_CPUID, "cpuid" }, \ - { SVM_EXIT_INVD, "invd" }, \ - { SVM_EXIT_HLT, "hlt" }, \ - { SVM_EXIT_INVLPG, "invlpg" }, \ - { SVM_EXIT_INVLPGA, "invlpga" }, \ - { SVM_EXIT_IOIO, "io" }, \ - { SVM_EXIT_MSR, "msr" }, \ - { SVM_EXIT_TASK_SWITCH, "task_switch" }, \ - { SVM_EXIT_SHUTDOWN, "shutdown" }, \ - { SVM_EXIT_VMRUN, "vmrun" }, \ - { SVM_EXIT_VMMCALL, "hypercall" }, \ - { SVM_EXIT_VMLOAD, "vmload" }, \ - { SVM_EXIT_VMSAVE, "vmsave" }, \ - { SVM_EXIT_STGI, "stgi" }, \ - { SVM_EXIT_CLGI, "clgi" }, \ - { SVM_EXIT_SKINIT, "skinit" }, \ - { SVM_EXIT_WBINVD, "wbinvd" }, \ - { SVM_EXIT_MONITOR, "monitor" }, \ - { SVM_EXIT_MWAIT, "mwait" }, \ - { SVM_EXIT_XSETBV, "xsetbv" }, \ - { SVM_EXIT_NPF, "npf" } - -#ifdef __KERNEL__ - enum { INTERCEPT_INTR, INTERCEPT_NMI, @@ -393,6 +264,81 @@ struct __attribute__ ((__packed__)) vmcb { #define SVM_EXITINFO_REG_MASK 0x0F +#define SVM_EXIT_READ_CR0 0x000 +#define SVM_EXIT_READ_CR3 0x003 +#define SVM_EXIT_READ_CR4 0x004 +#define SVM_EXIT_READ_CR8 0x008 +#define SVM_EXIT_WRITE_CR0 0x010 +#define SVM_EXIT_WRITE_CR3 0x013 +#define SVM_EXIT_WRITE_CR4 0x014 +#define SVM_EXIT_WRITE_CR8 0x018 +#define SVM_EXIT_READ_DR0 0x020 +#define SVM_EXIT_READ_DR1 0x021 +#define SVM_EXIT_READ_DR2 0x022 +#define SVM_EXIT_READ_DR3 0x023 +#define SVM_EXIT_READ_DR4 0x024 +#define SVM_EXIT_READ_DR5 0x025 +#define SVM_EXIT_READ_DR6 0x026 +#define SVM_EXIT_READ_DR7 0x027 +#define SVM_EXIT_WRITE_DR0 0x030 +#define SVM_EXIT_WRITE_DR1 0x031 +#define SVM_EXIT_WRITE_DR2 0x032 +#define SVM_EXIT_WRITE_DR3 0x033 +#define SVM_EXIT_WRITE_DR4 0x034 +#define SVM_EXIT_WRITE_DR5 0x035 +#define SVM_EXIT_WRITE_DR6 0x036 +#define SVM_EXIT_WRITE_DR7 0x037 +#define SVM_EXIT_EXCP_BASE 0x040 +#define SVM_EXIT_INTR 0x060 +#define SVM_EXIT_NMI 0x061 +#define SVM_EXIT_SMI 0x062 +#define SVM_EXIT_INIT 0x063 +#define SVM_EXIT_VINTR 0x064 +#define SVM_EXIT_CR0_SEL_WRITE 0x065 +#define SVM_EXIT_IDTR_READ 0x066 +#define SVM_EXIT_GDTR_READ 0x067 +#define SVM_EXIT_LDTR_READ 0x068 +#define SVM_EXIT_TR_READ 0x069 +#define SVM_EXIT_IDTR_WRITE 0x06a +#define SVM_EXIT_GDTR_WRITE 0x06b +#define SVM_EXIT_LDTR_WRITE 0x06c +#define SVM_EXIT_TR_WRITE 0x06d +#define SVM_EXIT_RDTSC 0x06e +#define SVM_EXIT_RDPMC 0x06f +#define SVM_EXIT_PUSHF 0x070 +#define SVM_EXIT_POPF 0x071 +#define SVM_EXIT_CPUID 0x072 +#define SVM_EXIT_RSM 0x073 +#define SVM_EXIT_IRET 0x074 +#define SVM_EXIT_SWINT 0x075 +#define SVM_EXIT_INVD 0x076 +#define SVM_EXIT_PAUSE 0x077 +#define SVM_EXIT_HLT 0x078 +#define SVM_EXIT_INVLPG 0x079 +#define SVM_EXIT_INVLPGA 0x07a +#define SVM_EXIT_IOIO 0x07b +#define SVM_EXIT_MSR 0x07c +#define SVM_EXIT_TASK_SWITCH 0x07d +#define SVM_EXIT_FERR_FREEZE 0x07e +#define SVM_EXIT_SHUTDOWN 0x07f +#define SVM_EXIT_VMRUN 0x080 +#define SVM_EXIT_VMMCALL 0x081 +#define SVM_EXIT_VMLOAD 0x082 +#define SVM_EXIT_VMSAVE 0x083 +#define SVM_EXIT_STGI 0x084 +#define SVM_EXIT_CLGI 0x085 +#define SVM_EXIT_SKINIT 0x086 +#define SVM_EXIT_RDTSCP 0x087 +#define SVM_EXIT_ICEBP 0x088 +#define SVM_EXIT_WBINVD 0x089 +#define SVM_EXIT_MONITOR 0x08a +#define SVM_EXIT_MWAIT 0x08b +#define SVM_EXIT_MWAIT_COND 0x08c +#define SVM_EXIT_XSETBV 0x08d +#define SVM_EXIT_NPF 0x400 + +#define SVM_EXIT_ERR -1 + #define SVM_CR0_SELECTIVE_MASK (X86_CR0_TS | X86_CR0_MP) #define SVM_VMLOAD ".byte 0x0f, 0x01, 0xda" @@ -404,4 +350,3 @@ struct __attribute__ ((__packed__)) vmcb { #endif -#endif diff --git a/trunk/arch/x86/include/asm/sys_ia32.h b/trunk/arch/x86/include/asm/sys_ia32.h index 4ca1c611b552..3fda9db48819 100644 --- a/trunk/arch/x86/include/asm/sys_ia32.h +++ b/trunk/arch/x86/include/asm/sys_ia32.h @@ -40,7 +40,7 @@ asmlinkage long sys32_sigaction(int, struct old_sigaction32 __user *, struct old_sigaction32 __user *); asmlinkage long sys32_alarm(unsigned int); -asmlinkage long sys32_waitpid(compat_pid_t, unsigned int __user *, int); +asmlinkage long sys32_waitpid(compat_pid_t, unsigned int *, int); asmlinkage long sys32_sysfs(int, u32, u32); asmlinkage long sys32_sched_rr_get_interval(compat_pid_t, diff --git a/trunk/arch/x86/include/asm/thread_info.h b/trunk/arch/x86/include/asm/thread_info.h index c535d847e3b5..89f794f007ec 100644 --- a/trunk/arch/x86/include/asm/thread_info.h +++ b/trunk/arch/x86/include/asm/thread_info.h @@ -89,7 +89,6 @@ struct thread_info { #define TIF_NOTSC 16 /* TSC is not accessible in userland */ #define TIF_IA32 17 /* IA32 compatibility process */ #define TIF_FORK 18 /* ret_from_fork */ -#define TIF_NOHZ 19 /* in adaptive nohz mode */ #define TIF_MEMDIE 20 /* is terminating due to OOM killer */ #define TIF_DEBUG 21 /* uses debug registers */ #define TIF_IO_BITMAP 22 /* uses I/O bitmap */ @@ -115,7 +114,6 @@ struct thread_info { #define _TIF_NOTSC (1 << TIF_NOTSC) #define _TIF_IA32 (1 << TIF_IA32) #define _TIF_FORK (1 << TIF_FORK) -#define _TIF_NOHZ (1 << TIF_NOHZ) #define _TIF_DEBUG (1 << TIF_DEBUG) #define _TIF_IO_BITMAP (1 << TIF_IO_BITMAP) #define _TIF_FORCED_TF (1 << TIF_FORCED_TF) @@ -128,13 +126,12 @@ struct thread_info { /* work to do in syscall_trace_enter() */ #define _TIF_WORK_SYSCALL_ENTRY \ (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_EMU | _TIF_SYSCALL_AUDIT | \ - _TIF_SECCOMP | _TIF_SINGLESTEP | _TIF_SYSCALL_TRACEPOINT | \ - _TIF_NOHZ) + _TIF_SECCOMP | _TIF_SINGLESTEP | _TIF_SYSCALL_TRACEPOINT) /* work to do in syscall_trace_leave() */ #define _TIF_WORK_SYSCALL_EXIT \ (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | _TIF_SINGLESTEP | \ - _TIF_SYSCALL_TRACEPOINT | _TIF_NOHZ) + _TIF_SYSCALL_TRACEPOINT) /* work to do on interrupt/exception return */ #define _TIF_WORK_MASK \ @@ -144,8 +141,7 @@ struct thread_info { /* work to do on any return to user space */ #define _TIF_ALLWORK_MASK \ - ((0x0000FFFF & ~_TIF_SECCOMP) | _TIF_SYSCALL_TRACEPOINT | \ - _TIF_NOHZ) + ((0x0000FFFF & ~_TIF_SECCOMP) | _TIF_SYSCALL_TRACEPOINT) /* Only used for 64 bit */ #define _TIF_DO_NOTIFY_MASK \ diff --git a/trunk/arch/x86/include/asm/uprobes.h b/trunk/arch/x86/include/asm/uprobes.h index 8ff8be7835ab..f3971bbcd1de 100644 --- a/trunk/arch/x86/include/asm/uprobes.h +++ b/trunk/arch/x86/include/asm/uprobes.h @@ -42,11 +42,10 @@ struct arch_uprobe { }; struct arch_uprobe_task { + unsigned long saved_trap_nr; #ifdef CONFIG_X86_64 unsigned long saved_scratch_register; #endif - unsigned int saved_trap_nr; - unsigned int saved_tf; }; extern int arch_uprobe_analyze_insn(struct arch_uprobe *aup, struct mm_struct *mm, unsigned long addr); diff --git a/trunk/arch/x86/include/asm/vdso.h b/trunk/arch/x86/include/asm/vdso.h index fddb53d63915..bb0522850b74 100644 --- a/trunk/arch/x86/include/asm/vdso.h +++ b/trunk/arch/x86/include/asm/vdso.h @@ -11,8 +11,7 @@ extern const char VDSO32_PRELINK[]; #define VDSO32_SYMBOL(base, name) \ ({ \ extern const char VDSO32_##name[]; \ - (void __user *)(VDSO32_##name - VDSO32_PRELINK + \ - (unsigned long)(base)); \ + (void *)(VDSO32_##name - VDSO32_PRELINK + (unsigned long)(base)); \ }) #endif diff --git a/trunk/arch/x86/include/asm/vmx.h b/trunk/arch/x86/include/asm/vmx.h index 36ec21c36d68..74fcb963595b 100644 --- a/trunk/arch/x86/include/asm/vmx.h +++ b/trunk/arch/x86/include/asm/vmx.h @@ -25,88 +25,6 @@ * */ -#define VMX_EXIT_REASONS_FAILED_VMENTRY 0x80000000 - -#define EXIT_REASON_EXCEPTION_NMI 0 -#define EXIT_REASON_EXTERNAL_INTERRUPT 1 -#define EXIT_REASON_TRIPLE_FAULT 2 - -#define EXIT_REASON_PENDING_INTERRUPT 7 -#define EXIT_REASON_NMI_WINDOW 8 -#define EXIT_REASON_TASK_SWITCH 9 -#define EXIT_REASON_CPUID 10 -#define EXIT_REASON_HLT 12 -#define EXIT_REASON_INVD 13 -#define EXIT_REASON_INVLPG 14 -#define EXIT_REASON_RDPMC 15 -#define EXIT_REASON_RDTSC 16 -#define EXIT_REASON_VMCALL 18 -#define EXIT_REASON_VMCLEAR 19 -#define EXIT_REASON_VMLAUNCH 20 -#define EXIT_REASON_VMPTRLD 21 -#define EXIT_REASON_VMPTRST 22 -#define EXIT_REASON_VMREAD 23 -#define EXIT_REASON_VMRESUME 24 -#define EXIT_REASON_VMWRITE 25 -#define EXIT_REASON_VMOFF 26 -#define EXIT_REASON_VMON 27 -#define EXIT_REASON_CR_ACCESS 28 -#define EXIT_REASON_DR_ACCESS 29 -#define EXIT_REASON_IO_INSTRUCTION 30 -#define EXIT_REASON_MSR_READ 31 -#define EXIT_REASON_MSR_WRITE 32 -#define EXIT_REASON_INVALID_STATE 33 -#define EXIT_REASON_MWAIT_INSTRUCTION 36 -#define EXIT_REASON_MONITOR_INSTRUCTION 39 -#define EXIT_REASON_PAUSE_INSTRUCTION 40 -#define EXIT_REASON_MCE_DURING_VMENTRY 41 -#define EXIT_REASON_TPR_BELOW_THRESHOLD 43 -#define EXIT_REASON_APIC_ACCESS 44 -#define EXIT_REASON_EPT_VIOLATION 48 -#define EXIT_REASON_EPT_MISCONFIG 49 -#define EXIT_REASON_WBINVD 54 -#define EXIT_REASON_XSETBV 55 -#define EXIT_REASON_INVPCID 58 - -#define VMX_EXIT_REASONS \ - { EXIT_REASON_EXCEPTION_NMI, "EXCEPTION_NMI" }, \ - { EXIT_REASON_EXTERNAL_INTERRUPT, "EXTERNAL_INTERRUPT" }, \ - { EXIT_REASON_TRIPLE_FAULT, "TRIPLE_FAULT" }, \ - { EXIT_REASON_PENDING_INTERRUPT, "PENDING_INTERRUPT" }, \ - { EXIT_REASON_NMI_WINDOW, "NMI_WINDOW" }, \ - { EXIT_REASON_TASK_SWITCH, "TASK_SWITCH" }, \ - { EXIT_REASON_CPUID, "CPUID" }, \ - { EXIT_REASON_HLT, "HLT" }, \ - { EXIT_REASON_INVLPG, "INVLPG" }, \ - { EXIT_REASON_RDPMC, "RDPMC" }, \ - { EXIT_REASON_RDTSC, "RDTSC" }, \ - { EXIT_REASON_VMCALL, "VMCALL" }, \ - { EXIT_REASON_VMCLEAR, "VMCLEAR" }, \ - { EXIT_REASON_VMLAUNCH, "VMLAUNCH" }, \ - { EXIT_REASON_VMPTRLD, "VMPTRLD" }, \ - { EXIT_REASON_VMPTRST, "VMPTRST" }, \ - { EXIT_REASON_VMREAD, "VMREAD" }, \ - { EXIT_REASON_VMRESUME, "VMRESUME" }, \ - { EXIT_REASON_VMWRITE, "VMWRITE" }, \ - { EXIT_REASON_VMOFF, "VMOFF" }, \ - { EXIT_REASON_VMON, "VMON" }, \ - { EXIT_REASON_CR_ACCESS, "CR_ACCESS" }, \ - { EXIT_REASON_DR_ACCESS, "DR_ACCESS" }, \ - { EXIT_REASON_IO_INSTRUCTION, "IO_INSTRUCTION" }, \ - { EXIT_REASON_MSR_READ, "MSR_READ" }, \ - { EXIT_REASON_MSR_WRITE, "MSR_WRITE" }, \ - { EXIT_REASON_MWAIT_INSTRUCTION, "MWAIT_INSTRUCTION" }, \ - { EXIT_REASON_MONITOR_INSTRUCTION, "MONITOR_INSTRUCTION" }, \ - { EXIT_REASON_PAUSE_INSTRUCTION, "PAUSE_INSTRUCTION" }, \ - { EXIT_REASON_MCE_DURING_VMENTRY, "MCE_DURING_VMENTRY" }, \ - { EXIT_REASON_TPR_BELOW_THRESHOLD, "TPR_BELOW_THRESHOLD" }, \ - { EXIT_REASON_APIC_ACCESS, "APIC_ACCESS" }, \ - { EXIT_REASON_EPT_VIOLATION, "EPT_VIOLATION" }, \ - { EXIT_REASON_EPT_MISCONFIG, "EPT_MISCONFIG" }, \ - { EXIT_REASON_WBINVD, "WBINVD" } - -#ifdef __KERNEL__ - #include /* @@ -323,6 +241,49 @@ enum vmcs_field { HOST_RIP = 0x00006c16, }; +#define VMX_EXIT_REASONS_FAILED_VMENTRY 0x80000000 + +#define EXIT_REASON_EXCEPTION_NMI 0 +#define EXIT_REASON_EXTERNAL_INTERRUPT 1 +#define EXIT_REASON_TRIPLE_FAULT 2 + +#define EXIT_REASON_PENDING_INTERRUPT 7 +#define EXIT_REASON_NMI_WINDOW 8 +#define EXIT_REASON_TASK_SWITCH 9 +#define EXIT_REASON_CPUID 10 +#define EXIT_REASON_HLT 12 +#define EXIT_REASON_INVD 13 +#define EXIT_REASON_INVLPG 14 +#define EXIT_REASON_RDPMC 15 +#define EXIT_REASON_RDTSC 16 +#define EXIT_REASON_VMCALL 18 +#define EXIT_REASON_VMCLEAR 19 +#define EXIT_REASON_VMLAUNCH 20 +#define EXIT_REASON_VMPTRLD 21 +#define EXIT_REASON_VMPTRST 22 +#define EXIT_REASON_VMREAD 23 +#define EXIT_REASON_VMRESUME 24 +#define EXIT_REASON_VMWRITE 25 +#define EXIT_REASON_VMOFF 26 +#define EXIT_REASON_VMON 27 +#define EXIT_REASON_CR_ACCESS 28 +#define EXIT_REASON_DR_ACCESS 29 +#define EXIT_REASON_IO_INSTRUCTION 30 +#define EXIT_REASON_MSR_READ 31 +#define EXIT_REASON_MSR_WRITE 32 +#define EXIT_REASON_INVALID_STATE 33 +#define EXIT_REASON_MWAIT_INSTRUCTION 36 +#define EXIT_REASON_MONITOR_INSTRUCTION 39 +#define EXIT_REASON_PAUSE_INSTRUCTION 40 +#define EXIT_REASON_MCE_DURING_VMENTRY 41 +#define EXIT_REASON_TPR_BELOW_THRESHOLD 43 +#define EXIT_REASON_APIC_ACCESS 44 +#define EXIT_REASON_EPT_VIOLATION 48 +#define EXIT_REASON_EPT_MISCONFIG 49 +#define EXIT_REASON_WBINVD 54 +#define EXIT_REASON_XSETBV 55 +#define EXIT_REASON_INVPCID 58 + /* * Interruption-information format */ @@ -527,5 +488,3 @@ enum vm_instruction_error_number { }; #endif - -#endif diff --git a/trunk/arch/x86/include/asm/x86_init.h b/trunk/arch/x86/include/asm/x86_init.h index 57693498519c..38155f667144 100644 --- a/trunk/arch/x86/include/asm/x86_init.h +++ b/trunk/arch/x86/include/asm/x86_init.h @@ -81,13 +81,12 @@ struct x86_init_mapping { /** * struct x86_init_paging - platform specific paging functions - * @pagetable_init: platform specific paging initialization call to setup - * the kernel pagetables and prepare accessors functions. - * Callback must call paging_init(). Called once after the - * direct mapping for phys memory is available. + * @pagetable_setup_start: platform specific pre paging_init() call + * @pagetable_setup_done: platform specific post paging_init() call */ struct x86_init_paging { - void (*pagetable_init)(void); + void (*pagetable_setup_start)(pgd_t *base); + void (*pagetable_setup_done)(pgd_t *base); }; /** diff --git a/trunk/arch/x86/include/asm/xen/page.h b/trunk/arch/x86/include/asm/xen/page.h index 472b9b783019..93971e841dd5 100644 --- a/trunk/arch/x86/include/asm/xen/page.h +++ b/trunk/arch/x86/include/asm/xen/page.h @@ -51,8 +51,7 @@ extern unsigned long set_phys_range_identity(unsigned long pfn_s, extern int m2p_add_override(unsigned long mfn, struct page *page, struct gnttab_map_grant_ref *kmap_op); -extern int m2p_remove_override(struct page *page, - struct gnttab_map_grant_ref *kmap_op); +extern int m2p_remove_override(struct page *page, bool clear_pte); extern struct page *m2p_find_override(unsigned long mfn); extern unsigned long m2p_find_override_pfn(unsigned long mfn, unsigned long pfn); diff --git a/trunk/arch/x86/include/asm/xor_32.h b/trunk/arch/x86/include/asm/xor_32.h index aabd5850bdb9..454570891bdc 100644 --- a/trunk/arch/x86/include/asm/xor_32.h +++ b/trunk/arch/x86/include/asm/xor_32.h @@ -534,6 +534,38 @@ static struct xor_block_template xor_block_p5_mmx = { * Copyright (C) 1999 Zach Brown (with obvious credit due Ingo) */ +#define XMMS_SAVE \ +do { \ + preempt_disable(); \ + cr0 = read_cr0(); \ + clts(); \ + asm volatile( \ + "movups %%xmm0,(%0) ;\n\t" \ + "movups %%xmm1,0x10(%0) ;\n\t" \ + "movups %%xmm2,0x20(%0) ;\n\t" \ + "movups %%xmm3,0x30(%0) ;\n\t" \ + : \ + : "r" (xmm_save) \ + : "memory"); \ +} while (0) + +#define XMMS_RESTORE \ +do { \ + asm volatile( \ + "sfence ;\n\t" \ + "movups (%0),%%xmm0 ;\n\t" \ + "movups 0x10(%0),%%xmm1 ;\n\t" \ + "movups 0x20(%0),%%xmm2 ;\n\t" \ + "movups 0x30(%0),%%xmm3 ;\n\t" \ + : \ + : "r" (xmm_save) \ + : "memory"); \ + write_cr0(cr0); \ + preempt_enable(); \ +} while (0) + +#define ALIGN16 __attribute__((aligned(16))) + #define OFFS(x) "16*("#x")" #define PF_OFFS(x) "256+16*("#x")" #define PF0(x) " prefetchnta "PF_OFFS(x)"(%1) ;\n" @@ -555,8 +587,10 @@ static void xor_sse_2(unsigned long bytes, unsigned long *p1, unsigned long *p2) { unsigned long lines = bytes >> 8; + char xmm_save[16*4] ALIGN16; + int cr0; - kernel_fpu_begin(); + XMMS_SAVE; asm volatile( #undef BLOCK @@ -599,7 +633,7 @@ xor_sse_2(unsigned long bytes, unsigned long *p1, unsigned long *p2) : : "memory"); - kernel_fpu_end(); + XMMS_RESTORE; } static void @@ -607,8 +641,10 @@ xor_sse_3(unsigned long bytes, unsigned long *p1, unsigned long *p2, unsigned long *p3) { unsigned long lines = bytes >> 8; + char xmm_save[16*4] ALIGN16; + int cr0; - kernel_fpu_begin(); + XMMS_SAVE; asm volatile( #undef BLOCK @@ -658,7 +694,7 @@ xor_sse_3(unsigned long bytes, unsigned long *p1, unsigned long *p2, : : "memory" ); - kernel_fpu_end(); + XMMS_RESTORE; } static void @@ -666,8 +702,10 @@ xor_sse_4(unsigned long bytes, unsigned long *p1, unsigned long *p2, unsigned long *p3, unsigned long *p4) { unsigned long lines = bytes >> 8; + char xmm_save[16*4] ALIGN16; + int cr0; - kernel_fpu_begin(); + XMMS_SAVE; asm volatile( #undef BLOCK @@ -724,7 +762,7 @@ xor_sse_4(unsigned long bytes, unsigned long *p1, unsigned long *p2, : : "memory" ); - kernel_fpu_end(); + XMMS_RESTORE; } static void @@ -732,8 +770,10 @@ xor_sse_5(unsigned long bytes, unsigned long *p1, unsigned long *p2, unsigned long *p3, unsigned long *p4, unsigned long *p5) { unsigned long lines = bytes >> 8; + char xmm_save[16*4] ALIGN16; + int cr0; - kernel_fpu_begin(); + XMMS_SAVE; /* Make sure GCC forgets anything it knows about p4 or p5, such that it won't pass to the asm volatile below a @@ -810,7 +850,7 @@ xor_sse_5(unsigned long bytes, unsigned long *p1, unsigned long *p2, like assuming they have some legal value. */ asm("" : "=r" (p4), "=r" (p5)); - kernel_fpu_end(); + XMMS_RESTORE; } static struct xor_block_template xor_block_pIII_sse = { diff --git a/trunk/arch/x86/include/asm/xor_64.h b/trunk/arch/x86/include/asm/xor_64.h index 5fc06d0b7eb5..b9b2323e90fe 100644 --- a/trunk/arch/x86/include/asm/xor_64.h +++ b/trunk/arch/x86/include/asm/xor_64.h @@ -34,7 +34,41 @@ * no advantages to be gotten from x86-64 here anyways. */ -#include +typedef struct { + unsigned long a, b; +} __attribute__((aligned(16))) xmm_store_t; + +/* Doesn't use gcc to save the XMM registers, because there is no easy way to + tell it to do a clts before the register saving. */ +#define XMMS_SAVE \ +do { \ + preempt_disable(); \ + asm volatile( \ + "movq %%cr0,%0 ;\n\t" \ + "clts ;\n\t" \ + "movups %%xmm0,(%1) ;\n\t" \ + "movups %%xmm1,0x10(%1) ;\n\t" \ + "movups %%xmm2,0x20(%1) ;\n\t" \ + "movups %%xmm3,0x30(%1) ;\n\t" \ + : "=&r" (cr0) \ + : "r" (xmm_save) \ + : "memory"); \ +} while (0) + +#define XMMS_RESTORE \ +do { \ + asm volatile( \ + "sfence ;\n\t" \ + "movups (%1),%%xmm0 ;\n\t" \ + "movups 0x10(%1),%%xmm1 ;\n\t" \ + "movups 0x20(%1),%%xmm2 ;\n\t" \ + "movups 0x30(%1),%%xmm3 ;\n\t" \ + "movq %0,%%cr0 ;\n\t" \ + : \ + : "r" (cr0), "r" (xmm_save) \ + : "memory"); \ + preempt_enable(); \ +} while (0) #define OFFS(x) "16*("#x")" #define PF_OFFS(x) "256+16*("#x")" @@ -57,8 +91,10 @@ static void xor_sse_2(unsigned long bytes, unsigned long *p1, unsigned long *p2) { unsigned int lines = bytes >> 8; + unsigned long cr0; + xmm_store_t xmm_save[4]; - kernel_fpu_begin(); + XMMS_SAVE; asm volatile( #undef BLOCK @@ -99,7 +135,7 @@ xor_sse_2(unsigned long bytes, unsigned long *p1, unsigned long *p2) : [inc] "r" (256UL) : "memory"); - kernel_fpu_end(); + XMMS_RESTORE; } static void @@ -107,8 +143,11 @@ xor_sse_3(unsigned long bytes, unsigned long *p1, unsigned long *p2, unsigned long *p3) { unsigned int lines = bytes >> 8; + xmm_store_t xmm_save[4]; + unsigned long cr0; + + XMMS_SAVE; - kernel_fpu_begin(); asm volatile( #undef BLOCK #define BLOCK(i) \ @@ -155,7 +194,7 @@ xor_sse_3(unsigned long bytes, unsigned long *p1, unsigned long *p2, [p1] "+r" (p1), [p2] "+r" (p2), [p3] "+r" (p3) : [inc] "r" (256UL) : "memory"); - kernel_fpu_end(); + XMMS_RESTORE; } static void @@ -163,8 +202,10 @@ xor_sse_4(unsigned long bytes, unsigned long *p1, unsigned long *p2, unsigned long *p3, unsigned long *p4) { unsigned int lines = bytes >> 8; + xmm_store_t xmm_save[4]; + unsigned long cr0; - kernel_fpu_begin(); + XMMS_SAVE; asm volatile( #undef BLOCK @@ -220,7 +261,7 @@ xor_sse_4(unsigned long bytes, unsigned long *p1, unsigned long *p2, : [inc] "r" (256UL) : "memory" ); - kernel_fpu_end(); + XMMS_RESTORE; } static void @@ -228,8 +269,10 @@ xor_sse_5(unsigned long bytes, unsigned long *p1, unsigned long *p2, unsigned long *p3, unsigned long *p4, unsigned long *p5) { unsigned int lines = bytes >> 8; + xmm_store_t xmm_save[4]; + unsigned long cr0; - kernel_fpu_begin(); + XMMS_SAVE; asm volatile( #undef BLOCK @@ -293,7 +336,7 @@ xor_sse_5(unsigned long bytes, unsigned long *p1, unsigned long *p2, : [inc] "r" (256UL) : "memory"); - kernel_fpu_end(); + XMMS_RESTORE; } static struct xor_block_template xor_block_sse = { diff --git a/trunk/arch/x86/include/asm/xor_avx.h b/trunk/arch/x86/include/asm/xor_avx.h index 7ea79c5fa1f2..2510d35f480e 100644 --- a/trunk/arch/x86/include/asm/xor_avx.h +++ b/trunk/arch/x86/include/asm/xor_avx.h @@ -20,6 +20,32 @@ #include #include +#define ALIGN32 __aligned(32) + +#define YMM_SAVED_REGS 4 + +#define YMMS_SAVE \ +do { \ + preempt_disable(); \ + cr0 = read_cr0(); \ + clts(); \ + asm volatile("vmovaps %%ymm0, %0" : "=m" (ymm_save[0]) : : "memory"); \ + asm volatile("vmovaps %%ymm1, %0" : "=m" (ymm_save[32]) : : "memory"); \ + asm volatile("vmovaps %%ymm2, %0" : "=m" (ymm_save[64]) : : "memory"); \ + asm volatile("vmovaps %%ymm3, %0" : "=m" (ymm_save[96]) : : "memory"); \ +} while (0); + +#define YMMS_RESTORE \ +do { \ + asm volatile("sfence" : : : "memory"); \ + asm volatile("vmovaps %0, %%ymm3" : : "m" (ymm_save[96])); \ + asm volatile("vmovaps %0, %%ymm2" : : "m" (ymm_save[64])); \ + asm volatile("vmovaps %0, %%ymm1" : : "m" (ymm_save[32])); \ + asm volatile("vmovaps %0, %%ymm0" : : "m" (ymm_save[0])); \ + write_cr0(cr0); \ + preempt_enable(); \ +} while (0); + #define BLOCK4(i) \ BLOCK(32 * i, 0) \ BLOCK(32 * (i + 1), 1) \ @@ -34,9 +60,10 @@ static void xor_avx_2(unsigned long bytes, unsigned long *p0, unsigned long *p1) { - unsigned long lines = bytes >> 9; + unsigned long cr0, lines = bytes >> 9; + char ymm_save[32 * YMM_SAVED_REGS] ALIGN32; - kernel_fpu_begin(); + YMMS_SAVE while (lines--) { #undef BLOCK @@ -55,15 +82,16 @@ do { \ p1 = (unsigned long *)((uintptr_t)p1 + 512); } - kernel_fpu_end(); + YMMS_RESTORE } static void xor_avx_3(unsigned long bytes, unsigned long *p0, unsigned long *p1, unsigned long *p2) { - unsigned long lines = bytes >> 9; + unsigned long cr0, lines = bytes >> 9; + char ymm_save[32 * YMM_SAVED_REGS] ALIGN32; - kernel_fpu_begin(); + YMMS_SAVE while (lines--) { #undef BLOCK @@ -85,15 +113,16 @@ do { \ p2 = (unsigned long *)((uintptr_t)p2 + 512); } - kernel_fpu_end(); + YMMS_RESTORE } static void xor_avx_4(unsigned long bytes, unsigned long *p0, unsigned long *p1, unsigned long *p2, unsigned long *p3) { - unsigned long lines = bytes >> 9; + unsigned long cr0, lines = bytes >> 9; + char ymm_save[32 * YMM_SAVED_REGS] ALIGN32; - kernel_fpu_begin(); + YMMS_SAVE while (lines--) { #undef BLOCK @@ -118,15 +147,16 @@ do { \ p3 = (unsigned long *)((uintptr_t)p3 + 512); } - kernel_fpu_end(); + YMMS_RESTORE } static void xor_avx_5(unsigned long bytes, unsigned long *p0, unsigned long *p1, unsigned long *p2, unsigned long *p3, unsigned long *p4) { - unsigned long lines = bytes >> 9; + unsigned long cr0, lines = bytes >> 9; + char ymm_save[32 * YMM_SAVED_REGS] ALIGN32; - kernel_fpu_begin(); + YMMS_SAVE while (lines--) { #undef BLOCK @@ -154,7 +184,7 @@ do { \ p4 = (unsigned long *)((uintptr_t)p4 + 512); } - kernel_fpu_end(); + YMMS_RESTORE } static struct xor_block_template xor_block_avx = { diff --git a/trunk/arch/x86/include/asm/xsave.h b/trunk/arch/x86/include/asm/xsave.h index 2ddee1b87793..8a1b6f9b594a 100644 --- a/trunk/arch/x86/include/asm/xsave.h +++ b/trunk/arch/x86/include/asm/xsave.h @@ -34,14 +34,17 @@ extern unsigned int xstate_size; extern u64 pcntxt_mask; extern u64 xstate_fx_sw_bytes[USER_XSTATE_FX_SW_WORDS]; -extern struct xsave_struct *init_xstate_buf; extern void xsave_init(void); extern void update_regset_xstate_info(unsigned int size, u64 xstate_mask); extern int init_fpu(struct task_struct *child); +extern int check_for_xstate(struct i387_fxsave_struct __user *buf, + void __user *fpstate, + struct _fpx_sw_bytes *sw); -static inline int fpu_xrstor_checking(struct xsave_struct *fx) +static inline int fpu_xrstor_checking(struct fpu *fpu) { + struct xsave_struct *fx = &fpu->state->xsave; int err; asm volatile("1: .byte " REX_PREFIX "0x0f,0xae,0x2f\n\t" @@ -66,7 +69,8 @@ static inline int xsave_user(struct xsave_struct __user *buf) * Clear the xsave header first, so that reserved fields are * initialized to zero. */ - err = __clear_user(&buf->xsave_hdr, sizeof(buf->xsave_hdr)); + err = __clear_user(&buf->xsave_hdr, + sizeof(struct xsave_hdr_struct)); if (unlikely(err)) return -EFAULT; @@ -80,6 +84,9 @@ static inline int xsave_user(struct xsave_struct __user *buf) : [err] "=r" (err) : "D" (buf), "a" (-1), "d" (-1), "0" (0) : "memory"); + if (unlikely(err) && __clear_user(buf, xstate_size)) + err = -EFAULT; + /* No need to clear here because the caller clears USED_MATH */ return err; } diff --git a/trunk/arch/x86/kernel/Makefile b/trunk/arch/x86/kernel/Makefile index 8d7a619718b5..8215e5652d97 100644 --- a/trunk/arch/x86/kernel/Makefile +++ b/trunk/arch/x86/kernel/Makefile @@ -100,8 +100,6 @@ obj-$(CONFIG_SWIOTLB) += pci-swiotlb.o obj-$(CONFIG_OF) += devicetree.o obj-$(CONFIG_UPROBES) += uprobes.o -obj-$(CONFIG_PERF_EVENTS) += perf_regs.o - ### # 64 bit specific files ifeq ($(CONFIG_X86_64),y) diff --git a/trunk/arch/x86/kernel/acpi/boot.c b/trunk/arch/x86/kernel/acpi/boot.c index e651f7a589ac..b2297e58c6ed 100644 --- a/trunk/arch/x86/kernel/acpi/boot.c +++ b/trunk/arch/x86/kernel/acpi/boot.c @@ -656,7 +656,7 @@ static int __cpuinit _acpi_map_lsapic(acpi_handle handle, int *pcpu) acpi_register_lapic(physid, ACPI_MADT_ENABLED); /* - * If acpi_register_lapic successfully generates a new logical cpu + * If mp_register_lapic successfully generates a new logical cpu * number, then the following will get us exactly what was mapped */ cpumask_andnot(new_map, cpu_present_mask, tmp_map); diff --git a/trunk/arch/x86/kernel/acpi/sleep.c b/trunk/arch/x86/kernel/acpi/sleep.c index 1b8e5a03d942..95bf99de9058 100644 --- a/trunk/arch/x86/kernel/acpi/sleep.c +++ b/trunk/arch/x86/kernel/acpi/sleep.c @@ -25,6 +25,10 @@ unsigned long acpi_realmode_flags; static char temp_stack[4096]; #endif +asmlinkage void acpi_enter_s3(void) +{ + acpi_enter_sleep_state(3, wake_sleep_flags); +} /** * acpi_suspend_lowlevel - save kernel state * diff --git a/trunk/arch/x86/kernel/acpi/sleep.h b/trunk/arch/x86/kernel/acpi/sleep.h index 67f59f8c6956..5653a5791ec9 100644 --- a/trunk/arch/x86/kernel/acpi/sleep.h +++ b/trunk/arch/x86/kernel/acpi/sleep.h @@ -2,6 +2,7 @@ * Variables and functions used by the code in sleep.c */ +#include #include extern unsigned long saved_video_mode; @@ -10,6 +11,7 @@ extern long saved_magic; extern int wakeup_pmode_return; extern u8 wake_sleep_flags; +extern asmlinkage void acpi_enter_s3(void); extern unsigned long acpi_copy_wakeup_routine(unsigned long); extern void wakeup_long64(void); diff --git a/trunk/arch/x86/kernel/acpi/wakeup_32.S b/trunk/arch/x86/kernel/acpi/wakeup_32.S index 13ab720573e3..72610839f03b 100644 --- a/trunk/arch/x86/kernel/acpi/wakeup_32.S +++ b/trunk/arch/x86/kernel/acpi/wakeup_32.S @@ -74,9 +74,7 @@ restore_registers: ENTRY(do_suspend_lowlevel) call save_processor_state call save_registers - pushl $3 - call acpi_enter_sleep_state - addl $4, %esp + call acpi_enter_s3 # In case of S3 failure, we'll emerge here. Jump # to ret_point to recover diff --git a/trunk/arch/x86/kernel/acpi/wakeup_64.S b/trunk/arch/x86/kernel/acpi/wakeup_64.S index 8ea5164cbd04..014d1d28c397 100644 --- a/trunk/arch/x86/kernel/acpi/wakeup_64.S +++ b/trunk/arch/x86/kernel/acpi/wakeup_64.S @@ -71,9 +71,7 @@ ENTRY(do_suspend_lowlevel) movq %rsi, saved_rsi addq $8, %rsp - movl $3, %edi - xorl %eax, %eax - call acpi_enter_sleep_state + call acpi_enter_s3 /* in case something went wrong, restore the machine status and go on */ jmp resume_point diff --git a/trunk/arch/x86/kernel/alternative.c b/trunk/arch/x86/kernel/alternative.c index ef5ccca79a6c..931280ff8299 100644 --- a/trunk/arch/x86/kernel/alternative.c +++ b/trunk/arch/x86/kernel/alternative.c @@ -23,6 +23,19 @@ #define MAX_PATCH_LEN (255-1) +#ifdef CONFIG_HOTPLUG_CPU +static int smp_alt_once; + +static int __init bootonly(char *str) +{ + smp_alt_once = 1; + return 1; +} +__setup("smp-alt-boot", bootonly); +#else +#define smp_alt_once 1 +#endif + static int __initdata_or_module debug_alternative; static int __init debug_alt(char *str) @@ -152,7 +165,7 @@ static const unsigned char * const k7_nops[ASM_NOP_MAX+2] = #endif #ifdef P6_NOP1 -static const unsigned char p6nops[] = +static const unsigned char __initconst_or_module p6nops[] = { P6_NOP1, P6_NOP2, @@ -211,7 +224,7 @@ void __init arch_init_ideal_nops(void) ideal_nops = intel_nops; #endif } - break; + default: #ifdef CONFIG_X86_64 ideal_nops = k8_nops; @@ -304,7 +317,7 @@ static void alternatives_smp_lock(const s32 *start, const s32 *end, /* turn DS segment override prefix into lock prefix */ if (*ptr == 0x3e) text_poke(ptr, ((unsigned char []){0xf0}), 1); - } + }; mutex_unlock(&text_mutex); } @@ -313,6 +326,9 @@ static void alternatives_smp_unlock(const s32 *start, const s32 *end, { const s32 *poff; + if (noreplace_smp) + return; + mutex_lock(&text_mutex); for (poff = start; poff < end; poff++) { u8 *ptr = (u8 *)poff + *poff; @@ -322,7 +338,7 @@ static void alternatives_smp_unlock(const s32 *start, const s32 *end, /* turn lock prefix into DS segment override prefix */ if (*ptr == 0xf0) text_poke(ptr, ((unsigned char []){0x3E}), 1); - } + }; mutex_unlock(&text_mutex); } @@ -343,7 +359,7 @@ struct smp_alt_module { }; static LIST_HEAD(smp_alt_modules); static DEFINE_MUTEX(smp_alt); -static bool uniproc_patched = false; /* protected by smp_alt */ +static int smp_mode = 1; /* protected by smp_alt */ void __init_or_module alternatives_smp_module_add(struct module *mod, char *name, @@ -352,18 +368,19 @@ void __init_or_module alternatives_smp_module_add(struct module *mod, { struct smp_alt_module *smp; - mutex_lock(&smp_alt); - if (!uniproc_patched) - goto unlock; + if (noreplace_smp) + return; - if (num_possible_cpus() == 1) - /* Don't bother remembering, we'll never have to undo it. */ - goto smp_unlock; + if (smp_alt_once) { + if (boot_cpu_has(X86_FEATURE_UP)) + alternatives_smp_unlock(locks, locks_end, + text, text_end); + return; + } smp = kzalloc(sizeof(*smp), GFP_KERNEL); if (NULL == smp) - /* we'll run the (safe but slow) SMP code then ... */ - goto unlock; + return; /* we'll run the (safe but slow) SMP code then ... */ smp->mod = mod; smp->name = name; @@ -375,10 +392,11 @@ void __init_or_module alternatives_smp_module_add(struct module *mod, __func__, smp->locks, smp->locks_end, smp->text, smp->text_end, smp->name); + mutex_lock(&smp_alt); list_add_tail(&smp->next, &smp_alt_modules); -smp_unlock: - alternatives_smp_unlock(locks, locks_end, text, text_end); -unlock: + if (boot_cpu_has(X86_FEATURE_UP)) + alternatives_smp_unlock(smp->locks, smp->locks_end, + smp->text, smp->text_end); mutex_unlock(&smp_alt); } @@ -386,18 +404,24 @@ void __init_or_module alternatives_smp_module_del(struct module *mod) { struct smp_alt_module *item; + if (smp_alt_once || noreplace_smp) + return; + mutex_lock(&smp_alt); list_for_each_entry(item, &smp_alt_modules, next) { if (mod != item->mod) continue; list_del(&item->next); + mutex_unlock(&smp_alt); + DPRINTK("%s: %s\n", __func__, item->name); kfree(item); - break; + return; } mutex_unlock(&smp_alt); } -void alternatives_enable_smp(void) +bool skip_smp_alternatives; +void alternatives_smp_switch(int smp) { struct smp_alt_module *mod; @@ -412,21 +436,34 @@ void alternatives_enable_smp(void) pr_info("lockdep: fixing up alternatives\n"); #endif - /* Why bother if there are no other CPUs? */ - BUG_ON(num_possible_cpus() == 1); + if (noreplace_smp || smp_alt_once || skip_smp_alternatives) + return; + BUG_ON(!smp && (num_online_cpus() > 1)); mutex_lock(&smp_alt); - if (uniproc_patched) { + /* + * Avoid unnecessary switches because it forces JIT based VMs to + * throw away all cached translations, which can be quite costly. + */ + if (smp == smp_mode) { + /* nothing */ + } else if (smp) { pr_info("switching to SMP code\n"); - BUG_ON(num_online_cpus() != 1); clear_cpu_cap(&boot_cpu_data, X86_FEATURE_UP); clear_cpu_cap(&cpu_data(0), X86_FEATURE_UP); list_for_each_entry(mod, &smp_alt_modules, next) alternatives_smp_lock(mod->locks, mod->locks_end, mod->text, mod->text_end); - uniproc_patched = false; + } else { + pr_info("switching to UP code\n"); + set_cpu_cap(&boot_cpu_data, X86_FEATURE_UP); + set_cpu_cap(&cpu_data(0), X86_FEATURE_UP); + list_for_each_entry(mod, &smp_alt_modules, next) + alternatives_smp_unlock(mod->locks, mod->locks_end, + mod->text, mod->text_end); } + smp_mode = smp; mutex_unlock(&smp_alt); } @@ -503,22 +540,40 @@ void __init alternative_instructions(void) apply_alternatives(__alt_instructions, __alt_instructions_end); + /* switch to patch-once-at-boottime-only mode and free the + * tables in case we know the number of CPUs will never ever + * change */ +#ifdef CONFIG_HOTPLUG_CPU + if (num_possible_cpus() < 2) + smp_alt_once = 1; +#endif + #ifdef CONFIG_SMP - /* Patch to UP if other cpus not imminent. */ - if (!noreplace_smp && (num_present_cpus() == 1 || setup_max_cpus <= 1)) { - uniproc_patched = true; + if (smp_alt_once) { + if (1 == num_possible_cpus()) { + pr_info("switching to UP code\n"); + set_cpu_cap(&boot_cpu_data, X86_FEATURE_UP); + set_cpu_cap(&cpu_data(0), X86_FEATURE_UP); + + alternatives_smp_unlock(__smp_locks, __smp_locks_end, + _text, _etext); + } + } else { alternatives_smp_module_add(NULL, "core kernel", __smp_locks, __smp_locks_end, _text, _etext); + + /* Only switch to UP mode if we don't immediately boot others */ + if (num_present_cpus() == 1 || setup_max_cpus <= 1) + alternatives_smp_switch(0); } +#endif + apply_paravirt(__parainstructions, __parainstructions_end); - if (!uniproc_patched || num_possible_cpus() == 1) + if (smp_alt_once) free_init_pages("SMP alternatives", (unsigned long)__smp_locks, (unsigned long)__smp_locks_end); -#endif - - apply_paravirt(__parainstructions, __parainstructions_end); restart_nmi(); } diff --git a/trunk/arch/x86/kernel/apic/apic.c b/trunk/arch/x86/kernel/apic/apic.c index b17416e72fbd..24deb3082328 100644 --- a/trunk/arch/x86/kernel/apic/apic.c +++ b/trunk/arch/x86/kernel/apic/apic.c @@ -1934,7 +1934,7 @@ void smp_error_interrupt(struct pt_regs *regs) apic_printk(APIC_DEBUG, KERN_CONT " : %s", error_interrupt_reason[i]); i++; v1 >>= 1; - } + }; apic_printk(APIC_DEBUG, KERN_CONT "\n"); diff --git a/trunk/arch/x86/kernel/apic/io_apic.c b/trunk/arch/x86/kernel/apic/io_apic.c index c265593ec2cd..406eee784684 100644 --- a/trunk/arch/x86/kernel/apic/io_apic.c +++ b/trunk/arch/x86/kernel/apic/io_apic.c @@ -1204,7 +1204,7 @@ static void __clear_irq_vector(int irq, struct irq_cfg *cfg) BUG_ON(!cfg->vector); vector = cfg->vector; - for_each_cpu_and(cpu, cfg->domain, cpu_online_mask) + for_each_cpu(cpu, cfg->domain) per_cpu(vector_irq, cpu)[vector] = -1; cfg->vector = 0; @@ -1212,7 +1212,7 @@ static void __clear_irq_vector(int irq, struct irq_cfg *cfg) if (likely(!cfg->move_in_progress)) return; - for_each_cpu_and(cpu, cfg->old_domain, cpu_online_mask) { + for_each_cpu(cpu, cfg->old_domain) { for (vector = FIRST_EXTERNAL_VECTOR; vector < NR_VECTORS; vector++) { if (per_cpu(vector_irq, cpu)[vector] != irq) @@ -1356,16 +1356,6 @@ static void setup_ioapic_irq(unsigned int irq, struct irq_cfg *cfg, if (!IO_APIC_IRQ(irq)) return; - /* - * For legacy irqs, cfg->domain starts with cpu 0. Now that IO-APIC - * can handle this irq and the apic driver is finialized at this point, - * update the cfg->domain. - */ - if (irq < legacy_pic->nr_legacy_irqs && - cpumask_equal(cfg->domain, cpumask_of(0))) - apic->vector_allocation_domain(0, cfg->domain, - apic->target_cpus()); - if (assign_irq_vector(irq, cfg, apic->target_cpus())) return; diff --git a/trunk/arch/x86/kernel/cpu/amd.c b/trunk/arch/x86/kernel/cpu/amd.c index f7e98a2c0d12..9d92e19039f0 100644 --- a/trunk/arch/x86/kernel/cpu/amd.c +++ b/trunk/arch/x86/kernel/cpu/amd.c @@ -737,72 +737,6 @@ static unsigned int __cpuinit amd_size_cache(struct cpuinfo_x86 *c, } #endif -static void __cpuinit cpu_set_tlb_flushall_shift(struct cpuinfo_x86 *c) -{ - if (!cpu_has_invlpg) - return; - - tlb_flushall_shift = 5; - - if (c->x86 <= 0x11) - tlb_flushall_shift = 4; -} - -static void __cpuinit cpu_detect_tlb_amd(struct cpuinfo_x86 *c) -{ - u32 ebx, eax, ecx, edx; - u16 mask = 0xfff; - - if (c->x86 < 0xf) - return; - - if (c->extended_cpuid_level < 0x80000006) - return; - - cpuid(0x80000006, &eax, &ebx, &ecx, &edx); - - tlb_lld_4k[ENTRIES] = (ebx >> 16) & mask; - tlb_lli_4k[ENTRIES] = ebx & mask; - - /* - * K8 doesn't have 2M/4M entries in the L2 TLB so read out the L1 TLB - * characteristics from the CPUID function 0x80000005 instead. - */ - if (c->x86 == 0xf) { - cpuid(0x80000005, &eax, &ebx, &ecx, &edx); - mask = 0xff; - } - - /* Handle DTLB 2M and 4M sizes, fall back to L1 if L2 is disabled */ - if (!((eax >> 16) & mask)) { - u32 a, b, c, d; - - cpuid(0x80000005, &a, &b, &c, &d); - tlb_lld_2m[ENTRIES] = (a >> 16) & 0xff; - } else { - tlb_lld_2m[ENTRIES] = (eax >> 16) & mask; - } - - /* a 4M entry uses two 2M entries */ - tlb_lld_4m[ENTRIES] = tlb_lld_2m[ENTRIES] >> 1; - - /* Handle ITLB 2M and 4M sizes, fall back to L1 if L2 is disabled */ - if (!(eax & mask)) { - /* Erratum 658 */ - if (c->x86 == 0x15 && c->x86_model <= 0x1f) { - tlb_lli_2m[ENTRIES] = 1024; - } else { - cpuid(0x80000005, &eax, &ebx, &ecx, &edx); - tlb_lli_2m[ENTRIES] = eax & 0xff; - } - } else - tlb_lli_2m[ENTRIES] = eax & mask; - - tlb_lli_4m[ENTRIES] = tlb_lli_2m[ENTRIES] >> 1; - - cpu_set_tlb_flushall_shift(c); -} - static const struct cpu_dev __cpuinitconst amd_cpu_dev = { .c_vendor = "AMD", .c_ident = { "AuthenticAMD" }, @@ -822,7 +756,6 @@ static const struct cpu_dev __cpuinitconst amd_cpu_dev = { .c_size_cache = amd_size_cache, #endif .c_early_init = early_init_amd, - .c_detect_tlb = cpu_detect_tlb_amd, .c_bsp_init = bsp_init_amd, .c_init = init_amd, .c_x86_vendor = X86_VENDOR_AMD, diff --git a/trunk/arch/x86/kernel/cpu/bugs.c b/trunk/arch/x86/kernel/cpu/bugs.c index d0e910da16c5..c97bb7b5a9f8 100644 --- a/trunk/arch/x86/kernel/cpu/bugs.c +++ b/trunk/arch/x86/kernel/cpu/bugs.c @@ -165,15 +165,10 @@ void __init check_bugs(void) print_cpu_info(&boot_cpu_data); #endif check_config(); + check_fpu(); check_hlt(); check_popad(); init_utsname()->machine[1] = '0' + (boot_cpu_data.x86 > 6 ? 6 : boot_cpu_data.x86); alternative_instructions(); - - /* - * kernel_fpu_begin/end() in check_fpu() relies on the patched - * alternative instructions. - */ - check_fpu(); } diff --git a/trunk/arch/x86/kernel/cpu/common.c b/trunk/arch/x86/kernel/cpu/common.c index 532691b6c8fe..46d8786d655e 100644 --- a/trunk/arch/x86/kernel/cpu/common.c +++ b/trunk/arch/x86/kernel/cpu/common.c @@ -144,8 +144,6 @@ static int __init x86_xsave_setup(char *s) { setup_clear_cpu_cap(X86_FEATURE_XSAVE); setup_clear_cpu_cap(X86_FEATURE_XSAVEOPT); - setup_clear_cpu_cap(X86_FEATURE_AVX); - setup_clear_cpu_cap(X86_FEATURE_AVX2); return 1; } __setup("noxsave", x86_xsave_setup); @@ -476,7 +474,7 @@ void __cpuinit cpu_detect_tlb(struct cpuinfo_x86 *c) printk(KERN_INFO "Last level iTLB entries: 4KB %d, 2MB %d, 4MB %d\n" \ "Last level dTLB entries: 4KB %d, 2MB %d, 4MB %d\n" \ - "tlb_flushall_shift: %d\n", + "tlb_flushall_shift is 0x%x\n", tlb_lli_4k[ENTRIES], tlb_lli_2m[ENTRIES], tlb_lli_4m[ENTRIES], tlb_lld_4k[ENTRIES], tlb_lld_2m[ENTRIES], tlb_lld_4m[ENTRIES], @@ -942,7 +940,8 @@ void __init identify_boot_cpu(void) #else vgetcpu_set_mode(); #endif - cpu_detect_tlb(&boot_cpu_data); + if (boot_cpu_data.cpuid_level >= 2) + cpu_detect_tlb(&boot_cpu_data); } void __cpuinit identify_secondary_cpu(struct cpuinfo_x86 *c) @@ -1022,16 +1021,14 @@ void __cpuinit print_cpu_info(struct cpuinfo_x86 *c) printk(KERN_CONT "%s ", vendor); if (c->x86_model_id[0]) - printk(KERN_CONT "%s", strim(c->x86_model_id)); + printk(KERN_CONT "%s", c->x86_model_id); else printk(KERN_CONT "%d86", c->x86); - printk(KERN_CONT " (fam: %02x, model: %02x", c->x86, c->x86_model); - if (c->x86_mask || c->cpuid_level >= 0) - printk(KERN_CONT ", stepping: %02x)\n", c->x86_mask); + printk(KERN_CONT " stepping %02x\n", c->x86_mask); else - printk(KERN_CONT ")\n"); + printk(KERN_CONT "\n"); print_cpu_msr(c); } @@ -1117,6 +1114,8 @@ void syscall_init(void) X86_EFLAGS_TF|X86_EFLAGS_DF|X86_EFLAGS_IF|X86_EFLAGS_IOPL); } +unsigned long kernel_eflags; + /* * Copies of the original ist values from the tss are only accessed during * debugging, no special alignment required. @@ -1296,6 +1295,9 @@ void __cpuinit cpu_init(void) dbg_restore_debug_regs(); fpu_init(); + xsave_init(); + + raw_local_save_flags(kernel_eflags); if (is_uv_system()) uv_cpu_init(); @@ -1348,5 +1350,6 @@ void __cpuinit cpu_init(void) dbg_restore_debug_regs(); fpu_init(); + xsave_init(); } #endif diff --git a/trunk/arch/x86/kernel/cpu/intel.c b/trunk/arch/x86/kernel/cpu/intel.c index 198e019a531a..0a4ce2980a5a 100644 --- a/trunk/arch/x86/kernel/cpu/intel.c +++ b/trunk/arch/x86/kernel/cpu/intel.c @@ -648,10 +648,6 @@ static void __cpuinit intel_detect_tlb(struct cpuinfo_x86 *c) int i, j, n; unsigned int regs[4]; unsigned char *desc = (unsigned char *)regs; - - if (c->cpuid_level < 2) - return; - /* Number of times to iterate */ n = cpuid_eax(2) & 0xFF; diff --git a/trunk/arch/x86/kernel/cpu/mcheck/mce-inject.c b/trunk/arch/x86/kernel/cpu/mcheck/mce-inject.c index ddc72f839332..fc4beb393577 100644 --- a/trunk/arch/x86/kernel/cpu/mcheck/mce-inject.c +++ b/trunk/arch/x86/kernel/cpu/mcheck/mce-inject.c @@ -78,7 +78,6 @@ static void raise_exception(struct mce *m, struct pt_regs *pregs) } static cpumask_var_t mce_inject_cpumask; -static DEFINE_MUTEX(mce_inject_mutex); static int mce_raise_notify(unsigned int cmd, struct pt_regs *regs) { @@ -195,11 +194,7 @@ static void raise_mce(struct mce *m) put_online_cpus(); } else #endif - { - preempt_disable(); raise_local(); - preempt_enable(); - } } /* Error injection interface */ @@ -230,10 +225,7 @@ static ssize_t mce_write(struct file *filp, const char __user *ubuf, * so do it a jiffie or two later everywhere. */ schedule_timeout(2); - - mutex_lock(&mce_inject_mutex); raise_mce(&m); - mutex_unlock(&mce_inject_mutex); return usize; } diff --git a/trunk/arch/x86/kernel/cpu/mcheck/mce-internal.h b/trunk/arch/x86/kernel/cpu/mcheck/mce-internal.h index 6a05c1d327a9..ed44c8a65858 100644 --- a/trunk/arch/x86/kernel/cpu/mcheck/mce-internal.h +++ b/trunk/arch/x86/kernel/cpu/mcheck/mce-internal.h @@ -28,18 +28,6 @@ extern int mce_ser; extern struct mce_bank *mce_banks; -#ifdef CONFIG_X86_MCE_INTEL -unsigned long mce_intel_adjust_timer(unsigned long interval); -void mce_intel_cmci_poll(void); -void mce_intel_hcpu_update(unsigned long cpu); -#else -# define mce_intel_adjust_timer mce_adjust_timer_default -static inline void mce_intel_cmci_poll(void) { } -static inline void mce_intel_hcpu_update(unsigned long cpu) { } -#endif - -void mce_timer_kick(unsigned long interval); - #ifdef CONFIG_ACPI_APEI int apei_write_mce(struct mce *m); ssize_t apei_read_mce(struct mce *m, u64 *record_id); diff --git a/trunk/arch/x86/kernel/cpu/mcheck/mce-severity.c b/trunk/arch/x86/kernel/cpu/mcheck/mce-severity.c index 13017626f9a8..413c2ced887c 100644 --- a/trunk/arch/x86/kernel/cpu/mcheck/mce-severity.c +++ b/trunk/arch/x86/kernel/cpu/mcheck/mce-severity.c @@ -55,6 +55,13 @@ static struct severity { #define MCI_UC_S (MCI_STATUS_UC|MCI_STATUS_S) #define MCI_UC_SAR (MCI_STATUS_UC|MCI_STATUS_S|MCI_STATUS_AR) #define MCI_ADDR (MCI_STATUS_ADDRV|MCI_STATUS_MISCV) +#define MCACOD 0xffff +/* Architecturally defined codes from SDM Vol. 3B Chapter 15 */ +#define MCACOD_SCRUB 0x00C0 /* 0xC0-0xCF Memory Scrubbing */ +#define MCACOD_SCRUBMSK 0xfff0 +#define MCACOD_L3WB 0x017A /* L3 Explicit Writeback */ +#define MCACOD_DATA 0x0134 /* Data Load */ +#define MCACOD_INSTR 0x0150 /* Instruction Fetch */ MCESEV( NO, "Invalid", diff --git a/trunk/arch/x86/kernel/cpu/mcheck/mce.c b/trunk/arch/x86/kernel/cpu/mcheck/mce.c index 29e87d3b2843..5e095f873e3e 100644 --- a/trunk/arch/x86/kernel/cpu/mcheck/mce.c +++ b/trunk/arch/x86/kernel/cpu/mcheck/mce.c @@ -83,7 +83,6 @@ static int mce_dont_log_ce __read_mostly; int mce_cmci_disabled __read_mostly; int mce_ignore_ce __read_mostly; int mce_ser __read_mostly; -int mce_bios_cmci_threshold __read_mostly; struct mce_bank *mce_banks __read_mostly; @@ -104,8 +103,6 @@ DEFINE_PER_CPU(mce_banks_t, mce_poll_banks) = { static DEFINE_PER_CPU(struct work_struct, mce_work); -static void (*quirk_no_way_out)(int bank, struct mce *m, struct pt_regs *regs); - /* * CPU/chipset specific EDAC code can register a notifier call here to print * MCE errors in a human-readable form. @@ -653,18 +650,14 @@ EXPORT_SYMBOL_GPL(machine_check_poll); * Do a quick check if any of the events requires a panic. * This decides if we keep the events around or clear them. */ -static int mce_no_way_out(struct mce *m, char **msg, unsigned long *validp, - struct pt_regs *regs) +static int mce_no_way_out(struct mce *m, char **msg, unsigned long *validp) { int i, ret = 0; for (i = 0; i < banks; i++) { m->status = mce_rdmsrl(MSR_IA32_MCx_STATUS(i)); - if (m->status & MCI_STATUS_VAL) { + if (m->status & MCI_STATUS_VAL) __set_bit(i, validp); - if (quirk_no_way_out) - quirk_no_way_out(i, m, regs); - } if (mce_severity(m, tolerant, msg) >= MCE_PANIC_SEVERITY) ret = 1; } @@ -1047,7 +1040,7 @@ void do_machine_check(struct pt_regs *regs, long error_code) *final = m; memset(valid_banks, 0, sizeof(valid_banks)); - no_way_out = mce_no_way_out(&m, &msg, valid_banks, regs); + no_way_out = mce_no_way_out(&m, &msg, valid_banks); barrier(); @@ -1267,14 +1260,6 @@ static unsigned long check_interval = 5 * 60; /* 5 minutes */ static DEFINE_PER_CPU(unsigned long, mce_next_interval); /* in jiffies */ static DEFINE_PER_CPU(struct timer_list, mce_timer); -static unsigned long mce_adjust_timer_default(unsigned long interval) -{ - return interval; -} - -static unsigned long (*mce_adjust_timer)(unsigned long interval) = - mce_adjust_timer_default; - static void mce_timer_fn(unsigned long data) { struct timer_list *t = &__get_cpu_var(mce_timer); @@ -1285,7 +1270,6 @@ static void mce_timer_fn(unsigned long data) if (mce_available(__this_cpu_ptr(&cpu_info))) { machine_check_poll(MCP_TIMESTAMP, &__get_cpu_var(mce_poll_banks)); - mce_intel_cmci_poll(); } /* @@ -1293,38 +1277,14 @@ static void mce_timer_fn(unsigned long data) * polling interval, otherwise increase the polling interval. */ iv = __this_cpu_read(mce_next_interval); - if (mce_notify_irq()) { + if (mce_notify_irq()) iv = max(iv / 2, (unsigned long) HZ/100); - } else { + else iv = min(iv * 2, round_jiffies_relative(check_interval * HZ)); - iv = mce_adjust_timer(iv); - } __this_cpu_write(mce_next_interval, iv); - /* Might have become 0 after CMCI storm subsided */ - if (iv) { - t->expires = jiffies + iv; - add_timer_on(t, smp_processor_id()); - } -} -/* - * Ensure that the timer is firing in @interval from now. - */ -void mce_timer_kick(unsigned long interval) -{ - struct timer_list *t = &__get_cpu_var(mce_timer); - unsigned long when = jiffies + interval; - unsigned long iv = __this_cpu_read(mce_next_interval); - - if (timer_pending(t)) { - if (time_before(when, t->expires)) - mod_timer_pinned(t, when); - } else { - t->expires = round_jiffies(when); - add_timer_on(t, smp_processor_id()); - } - if (interval < iv) - __this_cpu_write(mce_next_interval, interval); + t->expires = jiffies + iv; + add_timer_on(t, smp_processor_id()); } /* Must not be called in IRQ context where del_timer_sync() can deadlock */ @@ -1458,34 +1418,6 @@ static void __mcheck_cpu_init_generic(void) } } -/* - * During IFU recovery Sandy Bridge -EP4S processors set the RIPV and - * EIPV bits in MCG_STATUS to zero on the affected logical processor (SDM - * Vol 3B Table 15-20). But this confuses both the code that determines - * whether the machine check occurred in kernel or user mode, and also - * the severity assessment code. Pretend that EIPV was set, and take the - * ip/cs values from the pt_regs that mce_gather_info() ignored earlier. - */ -static void quirk_sandybridge_ifu(int bank, struct mce *m, struct pt_regs *regs) -{ - if (bank != 0) - return; - if ((m->mcgstatus & (MCG_STATUS_EIPV|MCG_STATUS_RIPV)) != 0) - return; - if ((m->status & (MCI_STATUS_OVER|MCI_STATUS_UC| - MCI_STATUS_EN|MCI_STATUS_MISCV|MCI_STATUS_ADDRV| - MCI_STATUS_PCC|MCI_STATUS_S|MCI_STATUS_AR| - MCACOD)) != - (MCI_STATUS_UC|MCI_STATUS_EN| - MCI_STATUS_MISCV|MCI_STATUS_ADDRV|MCI_STATUS_S| - MCI_STATUS_AR|MCACOD_INSTR)) - return; - - m->mcgstatus |= MCG_STATUS_EIPV; - m->ip = regs->ip; - m->cs = regs->cs; -} - /* Add per CPU specific workarounds here */ static int __cpuinit __mcheck_cpu_apply_quirks(struct cpuinfo_x86 *c) { @@ -1583,9 +1515,6 @@ static int __cpuinit __mcheck_cpu_apply_quirks(struct cpuinfo_x86 *c) */ if (c->x86 == 6 && c->x86_model <= 13 && mce_bootlog < 0) mce_bootlog = 0; - - if (c->x86 == 6 && c->x86_model == 45) - quirk_no_way_out = quirk_sandybridge_ifu; } if (monarch_timeout < 0) monarch_timeout = 0; @@ -1619,7 +1548,6 @@ static void __mcheck_cpu_init_vendor(struct cpuinfo_x86 *c) switch (c->x86_vendor) { case X86_VENDOR_INTEL: mce_intel_feature_init(c); - mce_adjust_timer = mce_intel_adjust_timer; break; case X86_VENDOR_AMD: mce_amd_feature_init(c); @@ -1629,28 +1557,23 @@ static void __mcheck_cpu_init_vendor(struct cpuinfo_x86 *c) } } -static void mce_start_timer(unsigned int cpu, struct timer_list *t) +static void __mcheck_cpu_init_timer(void) { - unsigned long iv = mce_adjust_timer(check_interval * HZ); + struct timer_list *t = &__get_cpu_var(mce_timer); + unsigned long iv = check_interval * HZ; - __this_cpu_write(mce_next_interval, iv); + setup_timer(t, mce_timer_fn, smp_processor_id()); - if (mce_ignore_ce || !iv) + if (mce_ignore_ce) return; + __this_cpu_write(mce_next_interval, iv); + if (!iv) + return; t->expires = round_jiffies(jiffies + iv); add_timer_on(t, smp_processor_id()); } -static void __mcheck_cpu_init_timer(void) -{ - struct timer_list *t = &__get_cpu_var(mce_timer); - unsigned int cpu = smp_processor_id(); - - setup_timer(t, mce_timer_fn, cpu); - mce_start_timer(cpu, t); -} - /* Handle unconfigured int18 (should never happen) */ static void unexpected_machine_check(struct pt_regs *regs, long error_code) { @@ -1947,7 +1870,6 @@ static struct miscdevice mce_chrdev_device = { * check, or 0 to not wait * mce=bootlog Log MCEs from before booting. Disabled by default on AMD. * mce=nobootlog Don't log MCEs from before booting. - * mce=bios_cmci_threshold Don't program the CMCI threshold */ static int __init mcheck_enable(char *str) { @@ -1967,8 +1889,6 @@ static int __init mcheck_enable(char *str) mce_ignore_ce = 1; else if (!strcmp(str, "bootlog") || !strcmp(str, "nobootlog")) mce_bootlog = (str[0] == 'b'); - else if (!strcmp(str, "bios_cmci_threshold")) - mce_bios_cmci_threshold = 1; else if (isdigit(str[0])) { get_option(&str, &tolerant); if (*str == ',') { @@ -2209,11 +2129,6 @@ static struct dev_ext_attribute dev_attr_cmci_disabled = { &mce_cmci_disabled }; -static struct dev_ext_attribute dev_attr_bios_cmci_threshold = { - __ATTR(bios_cmci_threshold, 0444, device_show_int, NULL), - &mce_bios_cmci_threshold -}; - static struct device_attribute *mce_device_attrs[] = { &dev_attr_tolerant.attr, &dev_attr_check_interval.attr, @@ -2222,7 +2137,6 @@ static struct device_attribute *mce_device_attrs[] = { &dev_attr_dont_log_ce.attr, &dev_attr_ignore_ce.attr, &dev_attr_cmci_disabled.attr, - &dev_attr_bios_cmci_threshold.attr, NULL }; @@ -2343,33 +2257,38 @@ mce_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) unsigned int cpu = (unsigned long)hcpu; struct timer_list *t = &per_cpu(mce_timer, cpu); - switch (action & ~CPU_TASKS_FROZEN) { + switch (action) { case CPU_ONLINE: + case CPU_ONLINE_FROZEN: mce_device_create(cpu); if (threshold_cpu_callback) threshold_cpu_callback(action, cpu); break; case CPU_DEAD: + case CPU_DEAD_FROZEN: if (threshold_cpu_callback) threshold_cpu_callback(action, cpu); mce_device_remove(cpu); - mce_intel_hcpu_update(cpu); break; case CPU_DOWN_PREPARE: - smp_call_function_single(cpu, mce_disable_cpu, &action, 1); + case CPU_DOWN_PREPARE_FROZEN: del_timer_sync(t); + smp_call_function_single(cpu, mce_disable_cpu, &action, 1); break; case CPU_DOWN_FAILED: + case CPU_DOWN_FAILED_FROZEN: + if (!mce_ignore_ce && check_interval) { + t->expires = round_jiffies(jiffies + + per_cpu(mce_next_interval, cpu)); + add_timer_on(t, cpu); + } smp_call_function_single(cpu, mce_reenable_cpu, &action, 1); - mce_start_timer(cpu, t); break; - } - - if (action == CPU_POST_DEAD) { + case CPU_POST_DEAD: /* intentionally ignoring frozen here */ cmci_rediscover(cpu); + break; } - return NOTIFY_OK; } diff --git a/trunk/arch/x86/kernel/cpu/mcheck/mce_intel.c b/trunk/arch/x86/kernel/cpu/mcheck/mce_intel.c index 5f88abf07e9c..38e49bc95ffc 100644 --- a/trunk/arch/x86/kernel/cpu/mcheck/mce_intel.c +++ b/trunk/arch/x86/kernel/cpu/mcheck/mce_intel.c @@ -15,8 +15,6 @@ #include #include -#include "mce-internal.h" - /* * Support for Intel Correct Machine Check Interrupts. This allows * the CPU to raise an interrupt when a corrected machine check happened. @@ -32,22 +30,7 @@ static DEFINE_PER_CPU(mce_banks_t, mce_banks_owned); */ static DEFINE_RAW_SPINLOCK(cmci_discover_lock); -#define CMCI_THRESHOLD 1 -#define CMCI_POLL_INTERVAL (30 * HZ) -#define CMCI_STORM_INTERVAL (1 * HZ) -#define CMCI_STORM_THRESHOLD 15 - -static DEFINE_PER_CPU(unsigned long, cmci_time_stamp); -static DEFINE_PER_CPU(unsigned int, cmci_storm_cnt); -static DEFINE_PER_CPU(unsigned int, cmci_storm_state); - -enum { - CMCI_STORM_NONE, - CMCI_STORM_ACTIVE, - CMCI_STORM_SUBSIDED, -}; - -static atomic_t cmci_storm_on_cpus; +#define CMCI_THRESHOLD 1 static int cmci_supported(int *banks) { @@ -70,93 +53,6 @@ static int cmci_supported(int *banks) return !!(cap & MCG_CMCI_P); } -void mce_intel_cmci_poll(void) -{ - if (__this_cpu_read(cmci_storm_state) == CMCI_STORM_NONE) - return; - machine_check_poll(MCP_TIMESTAMP, &__get_cpu_var(mce_banks_owned)); -} - -void mce_intel_hcpu_update(unsigned long cpu) -{ - if (per_cpu(cmci_storm_state, cpu) == CMCI_STORM_ACTIVE) - atomic_dec(&cmci_storm_on_cpus); - - per_cpu(cmci_storm_state, cpu) = CMCI_STORM_NONE; -} - -unsigned long mce_intel_adjust_timer(unsigned long interval) -{ - int r; - - if (interval < CMCI_POLL_INTERVAL) - return interval; - - switch (__this_cpu_read(cmci_storm_state)) { - case CMCI_STORM_ACTIVE: - /* - * We switch back to interrupt mode once the poll timer has - * silenced itself. That means no events recorded and the - * timer interval is back to our poll interval. - */ - __this_cpu_write(cmci_storm_state, CMCI_STORM_SUBSIDED); - r = atomic_sub_return(1, &cmci_storm_on_cpus); - if (r == 0) - pr_notice("CMCI storm subsided: switching to interrupt mode\n"); - /* FALLTHROUGH */ - - case CMCI_STORM_SUBSIDED: - /* - * We wait for all cpus to go back to SUBSIDED - * state. When that happens we switch back to - * interrupt mode. - */ - if (!atomic_read(&cmci_storm_on_cpus)) { - __this_cpu_write(cmci_storm_state, CMCI_STORM_NONE); - cmci_reenable(); - cmci_recheck(); - } - return CMCI_POLL_INTERVAL; - default: - /* - * We have shiny weather. Let the poll do whatever it - * thinks. - */ - return interval; - } -} - -static bool cmci_storm_detect(void) -{ - unsigned int cnt = __this_cpu_read(cmci_storm_cnt); - unsigned long ts = __this_cpu_read(cmci_time_stamp); - unsigned long now = jiffies; - int r; - - if (__this_cpu_read(cmci_storm_state) != CMCI_STORM_NONE) - return true; - - if (time_before_eq(now, ts + CMCI_STORM_INTERVAL)) { - cnt++; - } else { - cnt = 1; - __this_cpu_write(cmci_time_stamp, now); - } - __this_cpu_write(cmci_storm_cnt, cnt); - - if (cnt <= CMCI_STORM_THRESHOLD) - return false; - - cmci_clear(); - __this_cpu_write(cmci_storm_state, CMCI_STORM_ACTIVE); - r = atomic_add_return(1, &cmci_storm_on_cpus); - mce_timer_kick(CMCI_POLL_INTERVAL); - - if (r == 1) - pr_notice("CMCI storm detected: switching to poll mode\n"); - return true; -} - /* * The interrupt handler. This is called on every event. * Just call the poller directly to log any events. @@ -165,28 +61,33 @@ static bool cmci_storm_detect(void) */ static void intel_threshold_interrupt(void) { - if (cmci_storm_detect()) - return; machine_check_poll(MCP_TIMESTAMP, &__get_cpu_var(mce_banks_owned)); mce_notify_irq(); } +static void print_update(char *type, int *hdr, int num) +{ + if (*hdr == 0) + printk(KERN_INFO "CPU %d MCA banks", smp_processor_id()); + *hdr = 1; + printk(KERN_CONT " %s:%d", type, num); +} + /* * Enable CMCI (Corrected Machine Check Interrupt) for available MCE banks * on this CPU. Use the algorithm recommended in the SDM to discover shared * banks. */ -static void cmci_discover(int banks) +static void cmci_discover(int banks, int boot) { unsigned long *owned = (void *)&__get_cpu_var(mce_banks_owned); unsigned long flags; + int hdr = 0; int i; - int bios_wrong_thresh = 0; raw_spin_lock_irqsave(&cmci_discover_lock, flags); for (i = 0; i < banks; i++) { u64 val; - int bios_zero_thresh = 0; if (test_bit(i, owned)) continue; @@ -195,52 +96,29 @@ static void cmci_discover(int banks) /* Already owned by someone else? */ if (val & MCI_CTL2_CMCI_EN) { - clear_bit(i, owned); + if (test_and_clear_bit(i, owned) && !boot) + print_update("SHD", &hdr, i); __clear_bit(i, __get_cpu_var(mce_poll_banks)); continue; } - if (!mce_bios_cmci_threshold) { - val &= ~MCI_CTL2_CMCI_THRESHOLD_MASK; - val |= CMCI_THRESHOLD; - } else if (!(val & MCI_CTL2_CMCI_THRESHOLD_MASK)) { - /* - * If bios_cmci_threshold boot option was specified - * but the threshold is zero, we'll try to initialize - * it to 1. - */ - bios_zero_thresh = 1; - val |= CMCI_THRESHOLD; - } - - val |= MCI_CTL2_CMCI_EN; + val &= ~MCI_CTL2_CMCI_THRESHOLD_MASK; + val |= MCI_CTL2_CMCI_EN | CMCI_THRESHOLD; wrmsrl(MSR_IA32_MCx_CTL2(i), val); rdmsrl(MSR_IA32_MCx_CTL2(i), val); /* Did the enable bit stick? -- the bank supports CMCI */ if (val & MCI_CTL2_CMCI_EN) { - set_bit(i, owned); + if (!test_and_set_bit(i, owned) && !boot) + print_update("CMCI", &hdr, i); __clear_bit(i, __get_cpu_var(mce_poll_banks)); - /* - * We are able to set thresholds for some banks that - * had a threshold of 0. This means the BIOS has not - * set the thresholds properly or does not work with - * this boot option. Note down now and report later. - */ - if (mce_bios_cmci_threshold && bios_zero_thresh && - (val & MCI_CTL2_CMCI_THRESHOLD_MASK)) - bios_wrong_thresh = 1; } else { WARN_ON(!test_bit(i, __get_cpu_var(mce_poll_banks))); } } raw_spin_unlock_irqrestore(&cmci_discover_lock, flags); - if (mce_bios_cmci_threshold && bios_wrong_thresh) { - pr_info_once( - "bios_cmci_threshold: Some banks do not have valid thresholds set\n"); - pr_info_once( - "bios_cmci_threshold: Make sure your BIOS supports this boot option\n"); - } + if (hdr) + printk(KERN_CONT "\n"); } /* @@ -278,7 +156,7 @@ void cmci_clear(void) continue; /* Disable CMCI */ rdmsrl(MSR_IA32_MCx_CTL2(i), val); - val &= ~MCI_CTL2_CMCI_EN; + val &= ~(MCI_CTL2_CMCI_EN|MCI_CTL2_CMCI_THRESHOLD_MASK); wrmsrl(MSR_IA32_MCx_CTL2(i), val); __clear_bit(i, __get_cpu_var(mce_banks_owned)); } @@ -308,7 +186,7 @@ void cmci_rediscover(int dying) continue; /* Recheck banks in case CPUs don't all have the same */ if (cmci_supported(&banks)) - cmci_discover(banks); + cmci_discover(banks, 0); } set_cpus_allowed_ptr(current, old); @@ -322,7 +200,7 @@ void cmci_reenable(void) { int banks; if (cmci_supported(&banks)) - cmci_discover(banks); + cmci_discover(banks, 0); } static void intel_init_cmci(void) @@ -333,7 +211,7 @@ static void intel_init_cmci(void) return; mce_threshold_vector = intel_threshold_interrupt; - cmci_discover(banks); + cmci_discover(banks, 1); /* * For CPU #0 this runs with still disabled APIC, but that's * ok because only the vector is set up. We still do another diff --git a/trunk/arch/x86/kernel/cpu/perf_event.c b/trunk/arch/x86/kernel/cpu/perf_event.c index 915b876edd1e..29557aa06dda 100644 --- a/trunk/arch/x86/kernel/cpu/perf_event.c +++ b/trunk/arch/x86/kernel/cpu/perf_event.c @@ -32,8 +32,6 @@ #include #include #include -#include -#include #include "perf_event.h" @@ -1740,29 +1738,6 @@ valid_user_frame(const void __user *fp, unsigned long size) return (__range_not_ok(fp, size, TASK_SIZE) == 0); } -static unsigned long get_segment_base(unsigned int segment) -{ - struct desc_struct *desc; - int idx = segment >> 3; - - if ((segment & SEGMENT_TI_MASK) == SEGMENT_LDT) { - if (idx > LDT_ENTRIES) - return 0; - - if (idx > current->active_mm->context.size) - return 0; - - desc = current->active_mm->context.ldt; - } else { - if (idx > GDT_ENTRIES) - return 0; - - desc = __this_cpu_ptr(&gdt_page.gdt[0]); - } - - return get_desc_base(desc + idx); -} - #ifdef CONFIG_COMPAT #include @@ -1771,17 +1746,13 @@ static inline int perf_callchain_user32(struct pt_regs *regs, struct perf_callchain_entry *entry) { /* 32-bit process in 64-bit kernel. */ - unsigned long ss_base, cs_base; struct stack_frame_ia32 frame; const void __user *fp; if (!test_thread_flag(TIF_IA32)) return 0; - cs_base = get_segment_base(regs->cs); - ss_base = get_segment_base(regs->ss); - - fp = compat_ptr(ss_base + regs->bp); + fp = compat_ptr(regs->bp); while (entry->nr < PERF_MAX_STACK_DEPTH) { unsigned long bytes; frame.next_frame = 0; @@ -1794,8 +1765,8 @@ perf_callchain_user32(struct pt_regs *regs, struct perf_callchain_entry *entry) if (!valid_user_frame(fp, sizeof(frame))) break; - perf_callchain_store(entry, cs_base + frame.return_address); - fp = compat_ptr(ss_base + frame.next_frame); + perf_callchain_store(entry, frame.return_address); + fp = compat_ptr(frame.next_frame); } return 1; } @@ -1818,12 +1789,6 @@ perf_callchain_user(struct perf_callchain_entry *entry, struct pt_regs *regs) return; } - /* - * We don't know what to do with VM86 stacks.. ignore them for now. - */ - if (regs->flags & (X86_VM_MASK | PERF_EFLAGS_VM)) - return; - fp = (void __user *)regs->bp; perf_callchain_store(entry, regs->ip); @@ -1851,50 +1816,16 @@ perf_callchain_user(struct perf_callchain_entry *entry, struct pt_regs *regs) } } -/* - * Deal with code segment offsets for the various execution modes: - * - * VM86 - the good olde 16 bit days, where the linear address is - * 20 bits and we use regs->ip + 0x10 * regs->cs. - * - * IA32 - Where we need to look at GDT/LDT segment descriptor tables - * to figure out what the 32bit base address is. - * - * X32 - has TIF_X32 set, but is running in x86_64 - * - * X86_64 - CS,DS,SS,ES are all zero based. - */ -static unsigned long code_segment_base(struct pt_regs *regs) -{ - /* - * If we are in VM86 mode, add the segment offset to convert to a - * linear address. - */ - if (regs->flags & X86_VM_MASK) - return 0x10 * regs->cs; - - /* - * For IA32 we look at the GDT/LDT segment base to convert the - * effective IP to a linear address. - */ -#ifdef CONFIG_X86_32 - if (user_mode(regs) && regs->cs != __USER_CS) - return get_segment_base(regs->cs); -#else - if (test_thread_flag(TIF_IA32)) { - if (user_mode(regs) && regs->cs != __USER32_CS) - return get_segment_base(regs->cs); - } -#endif - return 0; -} - unsigned long perf_instruction_pointer(struct pt_regs *regs) { + unsigned long ip; + if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) - return perf_guest_cbs->get_guest_ip(); + ip = perf_guest_cbs->get_guest_ip(); + else + ip = instruction_pointer(regs); - return regs->ip + code_segment_base(regs); + return ip; } unsigned long perf_misc_flags(struct pt_regs *regs) @@ -1907,7 +1838,7 @@ unsigned long perf_misc_flags(struct pt_regs *regs) else misc |= PERF_RECORD_MISC_GUEST_KERNEL; } else { - if (user_mode(regs)) + if (!kernel_ip(regs->ip)) misc |= PERF_RECORD_MISC_USER; else misc |= PERF_RECORD_MISC_KERNEL; diff --git a/trunk/arch/x86/kernel/cpu/perf_event.h b/trunk/arch/x86/kernel/cpu/perf_event.h index 8b6defe7eefc..821d53b696d1 100644 --- a/trunk/arch/x86/kernel/cpu/perf_event.h +++ b/trunk/arch/x86/kernel/cpu/perf_event.h @@ -516,26 +516,6 @@ static inline bool kernel_ip(unsigned long ip) #endif } -/* - * Not all PMUs provide the right context information to place the reported IP - * into full context. Specifically segment registers are typically not - * supplied. - * - * Assuming the address is a linear address (it is for IBS), we fake the CS and - * vm86 mode using the known zero-based code segment and 'fix up' the registers - * to reflect this. - * - * Intel PEBS/LBR appear to typically provide the effective address, nothing - * much we can do about that but pray and treat it like a linear address. - */ -static inline void set_linear_ip(struct pt_regs *regs, unsigned long ip) -{ - regs->cs = kernel_ip(ip) ? __KERNEL_CS : __USER_CS; - if (regs->flags & X86_VM_MASK) - regs->flags ^= (PERF_EFLAGS_VM | X86_VM_MASK); - regs->ip = ip; -} - #ifdef CONFIG_CPU_SUP_AMD int amd_pmu_init(void); @@ -586,8 +566,6 @@ extern struct event_constraint intel_westmere_pebs_event_constraints[]; extern struct event_constraint intel_snb_pebs_event_constraints[]; -extern struct event_constraint intel_ivb_pebs_event_constraints[]; - struct event_constraint *intel_pebs_constraints(struct perf_event *event); void intel_pmu_pebs_enable(struct perf_event *event); diff --git a/trunk/arch/x86/kernel/cpu/perf_event_amd_ibs.c b/trunk/arch/x86/kernel/cpu/perf_event_amd_ibs.c index eebd5ffe1bba..da9bcdcd9856 100644 --- a/trunk/arch/x86/kernel/cpu/perf_event_amd_ibs.c +++ b/trunk/arch/x86/kernel/cpu/perf_event_amd_ibs.c @@ -13,8 +13,6 @@ #include -#include "perf_event.h" - static u32 ibs_caps; #if defined(CONFIG_PERF_EVENTS) && defined(CONFIG_CPU_SUP_AMD) @@ -209,15 +207,6 @@ static int perf_ibs_precise_event(struct perf_event *event, u64 *config) return -EOPNOTSUPP; } -static const struct perf_event_attr ibs_notsupp = { - .exclude_user = 1, - .exclude_kernel = 1, - .exclude_hv = 1, - .exclude_idle = 1, - .exclude_host = 1, - .exclude_guest = 1, -}; - static int perf_ibs_init(struct perf_event *event) { struct hw_perf_event *hwc = &event->hw; @@ -238,9 +227,6 @@ static int perf_ibs_init(struct perf_event *event) if (event->pmu != &perf_ibs->pmu) return -ENOENT; - if (perf_flags(&event->attr) & perf_flags(&ibs_notsupp)) - return -EINVAL; - if (config & ~perf_ibs->config_mask) return -EINVAL; @@ -550,7 +536,7 @@ static int perf_ibs_handle_irq(struct perf_ibs *perf_ibs, struct pt_regs *iregs) if (check_rip && (ibs_data.regs[2] & IBS_RIP_INVALID)) { regs.flags &= ~PERF_EFLAGS_EXACT; } else { - set_linear_ip(®s, ibs_data.regs[1]); + instruction_pointer_set(®s, ibs_data.regs[1]); regs.flags |= PERF_EFLAGS_EXACT; } diff --git a/trunk/arch/x86/kernel/cpu/perf_event_intel.c b/trunk/arch/x86/kernel/cpu/perf_event_intel.c index 6bca492b8547..382366977d4c 100644 --- a/trunk/arch/x86/kernel/cpu/perf_event_intel.c +++ b/trunk/arch/x86/kernel/cpu/perf_event_intel.c @@ -1522,16 +1522,8 @@ static struct perf_guest_switch_msr *intel_guest_get_msrs(int *nr) arr[0].msr = MSR_CORE_PERF_GLOBAL_CTRL; arr[0].host = x86_pmu.intel_ctrl & ~cpuc->intel_ctrl_guest_mask; arr[0].guest = x86_pmu.intel_ctrl & ~cpuc->intel_ctrl_host_mask; - /* - * If PMU counter has PEBS enabled it is not enough to disable counter - * on a guest entry since PEBS memory write can overshoot guest entry - * and corrupt guest memory. Disabling PEBS solves the problem. - */ - arr[1].msr = MSR_IA32_PEBS_ENABLE; - arr[1].host = cpuc->pebs_enabled; - arr[1].guest = 0; - *nr = 2; + *nr = 1; return arr; } @@ -2008,7 +2000,6 @@ __init int intel_pmu_init(void) break; case 28: /* Atom */ - case 54: /* Cedariew */ memcpy(hw_cache_event_ids, atom_hw_cache_event_ids, sizeof(hw_cache_event_ids)); @@ -2048,6 +2039,7 @@ __init int intel_pmu_init(void) case 42: /* SandyBridge */ case 45: /* SandyBridge, "Romely-EP" */ x86_add_quirk(intel_sandybridge_quirk); + case 58: /* IvyBridge */ memcpy(hw_cache_event_ids, snb_hw_cache_event_ids, sizeof(hw_cache_event_ids)); memcpy(hw_cache_extra_regs, snb_hw_cache_extra_regs, @@ -2072,29 +2064,6 @@ __init int intel_pmu_init(void) pr_cont("SandyBridge events, "); break; - case 58: /* IvyBridge */ - memcpy(hw_cache_event_ids, snb_hw_cache_event_ids, - sizeof(hw_cache_event_ids)); - memcpy(hw_cache_extra_regs, snb_hw_cache_extra_regs, - sizeof(hw_cache_extra_regs)); - - intel_pmu_lbr_init_snb(); - - x86_pmu.event_constraints = intel_snb_event_constraints; - x86_pmu.pebs_constraints = intel_ivb_pebs_event_constraints; - x86_pmu.pebs_aliases = intel_pebs_aliases_snb; - x86_pmu.extra_regs = intel_snb_extra_regs; - /* all extra regs are per-cpu when HT is on */ - x86_pmu.er_flags |= ERF_HAS_RSP_1; - x86_pmu.er_flags |= ERF_NO_HT_SHARING; - - /* UOPS_ISSUED.ANY,c=1,i=1 to count stall cycles */ - intel_perfmon_event_map[PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = - X86_CONFIG(.event=0x0e, .umask=0x01, .inv=1, .cmask=1); - - pr_cont("IvyBridge events, "); - break; - default: switch (x86_pmu.version) { diff --git a/trunk/arch/x86/kernel/cpu/perf_event_intel_ds.c b/trunk/arch/x86/kernel/cpu/perf_event_intel_ds.c index 826054a4f2ee..629ae0b7ad90 100644 --- a/trunk/arch/x86/kernel/cpu/perf_event_intel_ds.c +++ b/trunk/arch/x86/kernel/cpu/perf_event_intel_ds.c @@ -407,20 +407,6 @@ struct event_constraint intel_snb_pebs_event_constraints[] = { EVENT_CONSTRAINT_END }; -struct event_constraint intel_ivb_pebs_event_constraints[] = { - INTEL_UEVENT_CONSTRAINT(0x01c0, 0x2), /* INST_RETIRED.PRECDIST */ - INTEL_UEVENT_CONSTRAINT(0x01c2, 0xf), /* UOPS_RETIRED.ALL */ - INTEL_UEVENT_CONSTRAINT(0x02c2, 0xf), /* UOPS_RETIRED.RETIRE_SLOTS */ - INTEL_EVENT_CONSTRAINT(0xc4, 0xf), /* BR_INST_RETIRED.* */ - INTEL_EVENT_CONSTRAINT(0xc5, 0xf), /* BR_MISP_RETIRED.* */ - INTEL_EVENT_CONSTRAINT(0xcd, 0x8), /* MEM_TRANS_RETIRED.* */ - INTEL_EVENT_CONSTRAINT(0xd0, 0xf), /* MEM_UOP_RETIRED.* */ - INTEL_EVENT_CONSTRAINT(0xd1, 0xf), /* MEM_LOAD_UOPS_RETIRED.* */ - INTEL_EVENT_CONSTRAINT(0xd2, 0xf), /* MEM_LOAD_UOPS_LLC_HIT_RETIRED.* */ - INTEL_EVENT_CONSTRAINT(0xd3, 0xf), /* MEM_LOAD_UOPS_LLC_MISS_RETIRED.* */ - EVENT_CONSTRAINT_END -}; - struct event_constraint *intel_pebs_constraints(struct perf_event *event) { struct event_constraint *c; @@ -513,7 +499,7 @@ static int intel_pmu_pebs_fixup_ip(struct pt_regs *regs) * We sampled a branch insn, rewind using the LBR stack */ if (ip == to) { - set_linear_ip(regs, from); + regs->ip = from; return 1; } @@ -543,7 +529,7 @@ static int intel_pmu_pebs_fixup_ip(struct pt_regs *regs) } while (to < ip); if (to == ip) { - set_linear_ip(regs, old_to); + regs->ip = old_to; return 1; } @@ -583,8 +569,7 @@ static void __intel_pmu_pebs_event(struct perf_event *event, * A possible PERF_SAMPLE_REGS will have to transfer all regs. */ regs = *iregs; - regs.flags = pebs->flags; - set_linear_ip(®s, pebs->ip); + regs.ip = pebs->ip; regs.bp = pebs->bp; regs.sp = pebs->sp; diff --git a/trunk/arch/x86/kernel/cpu/perf_event_intel_lbr.c b/trunk/arch/x86/kernel/cpu/perf_event_intel_lbr.c index da02e9cc3754..520b4265fcd2 100644 --- a/trunk/arch/x86/kernel/cpu/perf_event_intel_lbr.c +++ b/trunk/arch/x86/kernel/cpu/perf_event_intel_lbr.c @@ -686,8 +686,7 @@ void intel_pmu_lbr_init_atom(void) * to have an operational LBR which can freeze * on PMU interrupt */ - if (boot_cpu_data.x86_model == 28 - && boot_cpu_data.x86_mask < 10) { + if (boot_cpu_data.x86_mask < 10) { pr_cont("LBR disabled due to erratum"); return; } diff --git a/trunk/arch/x86/kernel/cpu/perf_event_intel_uncore.c b/trunk/arch/x86/kernel/cpu/perf_event_intel_uncore.c index 99d96a4978b5..7563fda9f033 100644 --- a/trunk/arch/x86/kernel/cpu/perf_event_intel_uncore.c +++ b/trunk/arch/x86/kernel/cpu/perf_event_intel_uncore.c @@ -661,11 +661,6 @@ static void snb_uncore_msr_init_box(struct intel_uncore_box *box) } } -static struct uncore_event_desc snb_uncore_events[] = { - INTEL_UNCORE_EVENT_DESC(clockticks, "event=0xff,umask=0x00"), - { /* end: all zeroes */ }, -}; - static struct attribute *snb_uncore_formats_attr[] = { &format_attr_event.attr, &format_attr_umask.attr, @@ -709,7 +704,6 @@ static struct intel_uncore_type snb_uncore_cbox = { .constraints = snb_uncore_cbox_constraints, .ops = &snb_uncore_msr_ops, .format_group = &snb_uncore_format_group, - .event_descs = snb_uncore_events, }; static struct intel_uncore_type *snb_msr_uncores[] = { @@ -802,6 +796,7 @@ static struct intel_uncore_type *nhm_msr_uncores[] = { DEFINE_UNCORE_FORMAT_ATTR(event5, event, "config:1-5"); DEFINE_UNCORE_FORMAT_ATTR(counter, counter, "config:6-7"); +DEFINE_UNCORE_FORMAT_ATTR(mm_cfg, mm_cfg, "config:63"); DEFINE_UNCORE_FORMAT_ATTR(match, match, "config1:0-63"); DEFINE_UNCORE_FORMAT_ATTR(mask, mask, "config2:0-63"); @@ -907,21 +902,16 @@ static struct attribute_group nhmex_uncore_cbox_format_group = { .attrs = nhmex_uncore_cbox_formats_attr, }; -/* msr offset for each instance of cbox */ -static unsigned nhmex_cbox_msr_offsets[] = { - 0x0, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, 0x240, 0x2c0, -}; - static struct intel_uncore_type nhmex_uncore_cbox = { .name = "cbox", .num_counters = 6, - .num_boxes = 10, + .num_boxes = 8, .perf_ctr_bits = 48, .event_ctl = NHMEX_C0_MSR_PMON_EV_SEL0, .perf_ctr = NHMEX_C0_MSR_PMON_CTR0, .event_mask = NHMEX_PMON_RAW_EVENT_MASK, .box_ctl = NHMEX_C0_MSR_PMON_GLOBAL_CTL, - .msr_offsets = nhmex_cbox_msr_offsets, + .msr_offset = NHMEX_C_MSR_OFFSET, .pair_ctr_ctl = 1, .ops = &nhmex_uncore_ops, .format_group = &nhmex_uncore_cbox_format_group @@ -1042,22 +1032,24 @@ static struct intel_uncore_type nhmex_uncore_bbox = { static int nhmex_sbox_hw_config(struct intel_uncore_box *box, struct perf_event *event) { - struct hw_perf_event *hwc = &event->hw; - struct hw_perf_event_extra *reg1 = &hwc->extra_reg; - struct hw_perf_event_extra *reg2 = &hwc->branch_reg; + struct hw_perf_event_extra *reg1 = &event->hw.extra_reg; + struct hw_perf_event_extra *reg2 = &event->hw.branch_reg; - /* only TO_R_PROG_EV event uses the match/mask register */ - if ((hwc->config & NHMEX_PMON_CTL_EV_SEL_MASK) != - NHMEX_S_EVENT_TO_R_PROG_EV) - return 0; + if (event->attr.config & NHMEX_S_PMON_MM_CFG_EN) { + reg1->config = event->attr.config1; + reg2->config = event->attr.config2; + } else { + reg1->config = ~0ULL; + reg2->config = ~0ULL; + } if (box->pmu->pmu_idx == 0) reg1->reg = NHMEX_S0_MSR_MM_CFG; else reg1->reg = NHMEX_S1_MSR_MM_CFG; + reg1->idx = 0; - reg1->config = event->attr.config1; - reg2->config = event->attr.config2; + return 0; } @@ -1067,8 +1059,8 @@ static void nhmex_sbox_msr_enable_event(struct intel_uncore_box *box, struct per struct hw_perf_event_extra *reg1 = &hwc->extra_reg; struct hw_perf_event_extra *reg2 = &hwc->branch_reg; - if (reg1->idx != EXTRA_REG_NONE) { - wrmsrl(reg1->reg, 0); + wrmsrl(reg1->reg, 0); + if (reg1->config != ~0ULL || reg2->config != ~0ULL) { wrmsrl(reg1->reg + 1, reg1->config); wrmsrl(reg1->reg + 2, reg2->config); wrmsrl(reg1->reg, NHMEX_S_PMON_MM_CFG_EN); @@ -1082,6 +1074,7 @@ static struct attribute *nhmex_uncore_sbox_formats_attr[] = { &format_attr_edge.attr, &format_attr_inv.attr, &format_attr_thresh8.attr, + &format_attr_mm_cfg.attr, &format_attr_match.attr, &format_attr_mask.attr, NULL, @@ -1149,9 +1142,6 @@ static struct extra_reg nhmex_uncore_mbox_extra_regs[] = { EVENT_EXTRA_END }; -/* Nehalem-EX or Westmere-EX ? */ -bool uncore_nhmex; - static bool nhmex_mbox_get_shared_reg(struct intel_uncore_box *box, int idx, u64 config) { struct intel_uncore_extra_reg *er; @@ -1181,29 +1171,18 @@ static bool nhmex_mbox_get_shared_reg(struct intel_uncore_box *box, int idx, u64 return false; /* mask of the shared fields */ - if (uncore_nhmex) - mask = NHMEX_M_PMON_ZDP_CTL_FVC_MASK; - else - mask = WSMEX_M_PMON_ZDP_CTL_FVC_MASK; + mask = NHMEX_M_PMON_ZDP_CTL_FVC_MASK; er = &box->shared_regs[EXTRA_REG_NHMEX_M_ZDP_CTL_FVC]; raw_spin_lock_irqsave(&er->lock, flags); /* add mask of the non-shared field if it's in use */ - if (__BITS_VALUE(atomic_read(&er->ref), idx, 8)) { - if (uncore_nhmex) - mask |= NHMEX_M_PMON_ZDP_CTL_FVC_EVENT_MASK(idx); - else - mask |= WSMEX_M_PMON_ZDP_CTL_FVC_EVENT_MASK(idx); - } + if (__BITS_VALUE(atomic_read(&er->ref), idx, 8)) + mask |= NHMEX_M_PMON_ZDP_CTL_FVC_EVENT_MASK(idx); if (!atomic_read(&er->ref) || !((er->config ^ config) & mask)) { atomic_add(1 << (idx * 8), &er->ref); - if (uncore_nhmex) - mask = NHMEX_M_PMON_ZDP_CTL_FVC_MASK | - NHMEX_M_PMON_ZDP_CTL_FVC_EVENT_MASK(idx); - else - mask = WSMEX_M_PMON_ZDP_CTL_FVC_MASK | - WSMEX_M_PMON_ZDP_CTL_FVC_EVENT_MASK(idx); + mask = NHMEX_M_PMON_ZDP_CTL_FVC_MASK | + NHMEX_M_PMON_ZDP_CTL_FVC_EVENT_MASK(idx); er->config &= ~mask; er->config |= (config & mask); ret = true; @@ -1237,10 +1216,7 @@ u64 nhmex_mbox_alter_er(struct perf_event *event, int new_idx, bool modify) /* get the non-shared control bits and shift them */ idx = orig_idx - EXTRA_REG_NHMEX_M_ZDP_CTL_FVC; - if (uncore_nhmex) - config &= NHMEX_M_PMON_ZDP_CTL_FVC_EVENT_MASK(idx); - else - config &= WSMEX_M_PMON_ZDP_CTL_FVC_EVENT_MASK(idx); + config &= NHMEX_M_PMON_ZDP_CTL_FVC_EVENT_MASK(idx); if (new_idx > orig_idx) { idx = new_idx - orig_idx; config <<= 3 * idx; @@ -1250,10 +1226,6 @@ u64 nhmex_mbox_alter_er(struct perf_event *event, int new_idx, bool modify) } /* add the shared control bits back */ - if (uncore_nhmex) - config |= NHMEX_M_PMON_ZDP_CTL_FVC_MASK & reg1->config; - else - config |= WSMEX_M_PMON_ZDP_CTL_FVC_MASK & reg1->config; config |= NHMEX_M_PMON_ZDP_CTL_FVC_MASK & reg1->config; if (modify) { /* adjust the main event selector */ @@ -1292,8 +1264,7 @@ nhmex_mbox_get_constraint(struct intel_uncore_box *box, struct perf_event *event } /* for the match/mask registers */ - if (reg2->idx != EXTRA_REG_NONE && - (uncore_box_is_fake(box) || !reg2->alloc) && + if ((uncore_box_is_fake(box) || !reg2->alloc) && !nhmex_mbox_get_shared_reg(box, reg2->idx, reg2->config)) goto fail; @@ -1307,8 +1278,7 @@ nhmex_mbox_get_constraint(struct intel_uncore_box *box, struct perf_event *event if (idx[0] != 0xff && idx[0] != __BITS_VALUE(reg1->idx, 0, 8)) nhmex_mbox_alter_er(event, idx[0], true); reg1->alloc |= alloc; - if (reg2->idx != EXTRA_REG_NONE) - reg2->alloc = 1; + reg2->alloc = 1; } return NULL; fail: @@ -1372,6 +1342,9 @@ static int nhmex_mbox_hw_config(struct intel_uncore_box *box, struct perf_event struct extra_reg *er; unsigned msr; int reg_idx = 0; + + if (WARN_ON_ONCE(reg1->idx != -1)) + return -EINVAL; /* * The mbox events may require 2 extra MSRs at the most. But only * the lower 32 bits in these MSRs are significant, so we can use @@ -1382,6 +1355,11 @@ static int nhmex_mbox_hw_config(struct intel_uncore_box *box, struct perf_event continue; if (event->attr.config1 & ~er->valid_mask) return -EINVAL; + if (er->idx == __BITS_VALUE(reg1->idx, 0, 8) || + er->idx == __BITS_VALUE(reg1->idx, 1, 8)) + continue; + if (WARN_ON_ONCE(reg_idx >= 2)) + return -EINVAL; msr = er->msr + type->msr_offset * box->pmu->pmu_idx; if (WARN_ON_ONCE(msr >= 0xffff || er->idx >= 0xff)) @@ -1390,8 +1368,6 @@ static int nhmex_mbox_hw_config(struct intel_uncore_box *box, struct perf_event /* always use the 32~63 bits to pass the PLD config */ if (er->idx == EXTRA_REG_NHMEX_M_PLD) reg_idx = 1; - else if (WARN_ON_ONCE(reg_idx > 0)) - return -EINVAL; reg1->idx &= ~(0xff << (reg_idx * 8)); reg1->reg &= ~(0xffff << (reg_idx * 16)); @@ -1400,21 +1376,17 @@ static int nhmex_mbox_hw_config(struct intel_uncore_box *box, struct perf_event reg1->config = event->attr.config1; reg_idx++; } - /* - * The mbox only provides ability to perform address matching - * for the PLD events. - */ - if (reg_idx == 2) { - reg2->idx = EXTRA_REG_NHMEX_M_FILTER; - if (event->attr.config2 & NHMEX_M_PMON_MM_CFG_EN) - reg2->config = event->attr.config2; - else - reg2->config = ~0ULL; - if (box->pmu->pmu_idx == 0) - reg2->reg = NHMEX_M0_MSR_PMU_MM_CFG; - else - reg2->reg = NHMEX_M1_MSR_PMU_MM_CFG; - } + /* use config2 to pass the filter config */ + reg2->idx = EXTRA_REG_NHMEX_M_FILTER; + if (event->attr.config2 & NHMEX_M_PMON_MM_CFG_EN) + reg2->config = event->attr.config2; + else + reg2->config = ~0ULL; + if (box->pmu->pmu_idx == 0) + reg2->reg = NHMEX_M0_MSR_PMU_MM_CFG; + else + reg2->reg = NHMEX_M1_MSR_PMU_MM_CFG; + return 0; } @@ -1450,36 +1422,34 @@ static void nhmex_mbox_msr_enable_event(struct intel_uncore_box *box, struct per wrmsrl(__BITS_VALUE(reg1->reg, 1, 16), nhmex_mbox_shared_reg_config(box, idx)); - if (reg2->idx != EXTRA_REG_NONE) { - wrmsrl(reg2->reg, 0); - if (reg2->config != ~0ULL) { - wrmsrl(reg2->reg + 1, - reg2->config & NHMEX_M_PMON_ADDR_MATCH_MASK); - wrmsrl(reg2->reg + 2, NHMEX_M_PMON_ADDR_MASK_MASK & - (reg2->config >> NHMEX_M_PMON_ADDR_MASK_SHIFT)); - wrmsrl(reg2->reg, NHMEX_M_PMON_MM_CFG_EN); - } + wrmsrl(reg2->reg, 0); + if (reg2->config != ~0ULL) { + wrmsrl(reg2->reg + 1, + reg2->config & NHMEX_M_PMON_ADDR_MATCH_MASK); + wrmsrl(reg2->reg + 2, NHMEX_M_PMON_ADDR_MASK_MASK & + (reg2->config >> NHMEX_M_PMON_ADDR_MASK_SHIFT)); + wrmsrl(reg2->reg, NHMEX_M_PMON_MM_CFG_EN); } wrmsrl(hwc->config_base, hwc->config | NHMEX_PMON_CTL_EN_BIT0); } -DEFINE_UNCORE_FORMAT_ATTR(count_mode, count_mode, "config:2-3"); -DEFINE_UNCORE_FORMAT_ATTR(storage_mode, storage_mode, "config:4-5"); -DEFINE_UNCORE_FORMAT_ATTR(wrap_mode, wrap_mode, "config:6"); -DEFINE_UNCORE_FORMAT_ATTR(flag_mode, flag_mode, "config:7"); -DEFINE_UNCORE_FORMAT_ATTR(inc_sel, inc_sel, "config:9-13"); -DEFINE_UNCORE_FORMAT_ATTR(set_flag_sel, set_flag_sel, "config:19-21"); -DEFINE_UNCORE_FORMAT_ATTR(filter_cfg_en, filter_cfg_en, "config2:63"); -DEFINE_UNCORE_FORMAT_ATTR(filter_match, filter_match, "config2:0-33"); -DEFINE_UNCORE_FORMAT_ATTR(filter_mask, filter_mask, "config2:34-61"); -DEFINE_UNCORE_FORMAT_ATTR(dsp, dsp, "config1:0-31"); -DEFINE_UNCORE_FORMAT_ATTR(thr, thr, "config1:0-31"); -DEFINE_UNCORE_FORMAT_ATTR(fvc, fvc, "config1:0-31"); -DEFINE_UNCORE_FORMAT_ATTR(pgt, pgt, "config1:0-31"); -DEFINE_UNCORE_FORMAT_ATTR(map, map, "config1:0-31"); -DEFINE_UNCORE_FORMAT_ATTR(iss, iss, "config1:0-31"); -DEFINE_UNCORE_FORMAT_ATTR(pld, pld, "config1:32-63"); +DEFINE_UNCORE_FORMAT_ATTR(count_mode, count_mode, "config:2-3"); +DEFINE_UNCORE_FORMAT_ATTR(storage_mode, storage_mode, "config:4-5"); +DEFINE_UNCORE_FORMAT_ATTR(wrap_mode, wrap_mode, "config:6"); +DEFINE_UNCORE_FORMAT_ATTR(flag_mode, flag_mode, "config:7"); +DEFINE_UNCORE_FORMAT_ATTR(inc_sel, inc_sel, "config:9-13"); +DEFINE_UNCORE_FORMAT_ATTR(set_flag_sel, set_flag_sel, "config:19-21"); +DEFINE_UNCORE_FORMAT_ATTR(filter_cfg, filter_cfg, "config2:63"); +DEFINE_UNCORE_FORMAT_ATTR(filter_match, filter_match, "config2:0-33"); +DEFINE_UNCORE_FORMAT_ATTR(filter_mask, filter_mask, "config2:34-61"); +DEFINE_UNCORE_FORMAT_ATTR(dsp, dsp, "config1:0-31"); +DEFINE_UNCORE_FORMAT_ATTR(thr, thr, "config1:0-31"); +DEFINE_UNCORE_FORMAT_ATTR(fvc, fvc, "config1:0-31"); +DEFINE_UNCORE_FORMAT_ATTR(pgt, pgt, "config1:0-31"); +DEFINE_UNCORE_FORMAT_ATTR(map, map, "config1:0-31"); +DEFINE_UNCORE_FORMAT_ATTR(iss, iss, "config1:0-31"); +DEFINE_UNCORE_FORMAT_ATTR(pld, pld, "config1:32-63"); static struct attribute *nhmex_uncore_mbox_formats_attr[] = { &format_attr_count_mode.attr, @@ -1488,7 +1458,7 @@ static struct attribute *nhmex_uncore_mbox_formats_attr[] = { &format_attr_flag_mode.attr, &format_attr_inc_sel.attr, &format_attr_set_flag_sel.attr, - &format_attr_filter_cfg_en.attr, + &format_attr_filter_cfg.attr, &format_attr_filter_match.attr, &format_attr_filter_mask.attr, &format_attr_dsp.attr, @@ -1512,12 +1482,6 @@ static struct uncore_event_desc nhmex_uncore_mbox_events[] = { { /* end: all zeroes */ }, }; -static struct uncore_event_desc wsmex_uncore_mbox_events[] = { - INTEL_UNCORE_EVENT_DESC(bbox_cmds_read, "inc_sel=0xd,fvc=0x5000"), - INTEL_UNCORE_EVENT_DESC(bbox_cmds_write, "inc_sel=0xd,fvc=0x5040"), - { /* end: all zeroes */ }, -}; - static struct intel_uncore_ops nhmex_uncore_mbox_ops = { NHMEX_UNCORE_OPS_COMMON_INIT(), .enable_event = nhmex_mbox_msr_enable_event, @@ -1549,7 +1513,7 @@ void nhmex_rbox_alter_er(struct intel_uncore_box *box, struct perf_event *event) struct hw_perf_event_extra *reg1 = &hwc->extra_reg; int port; - /* adjust the main event selector and extra register index */ + /* adjust the main event selector */ if (reg1->idx % 2) { reg1->idx--; hwc->config -= 1 << NHMEX_R_PMON_CTL_EV_SEL_SHIFT; @@ -1558,17 +1522,29 @@ void nhmex_rbox_alter_er(struct intel_uncore_box *box, struct perf_event *event) hwc->config += 1 << NHMEX_R_PMON_CTL_EV_SEL_SHIFT; } - /* adjust extra register config */ + /* adjust address or config of extra register */ port = reg1->idx / 6 + box->pmu->pmu_idx * 4; switch (reg1->idx % 6) { + case 0: + reg1->reg = NHMEX_R_MSR_PORTN_IPERF_CFG0(port); + break; + case 1: + reg1->reg = NHMEX_R_MSR_PORTN_IPERF_CFG1(port); + break; case 2: - /* shift the 8~15 bits to the 0~7 bits */ + /* the 8~15 bits to the 0~7 bits */ reg1->config >>= 8; break; case 3: - /* shift the 0~7 bits to the 8~15 bits */ + /* the 0~7 bits to the 8~15 bits */ reg1->config <<= 8; break; + case 4: + reg1->reg = NHMEX_R_MSR_PORTN_XBR_SET1_MM_CFG(port); + break; + case 5: + reg1->reg = NHMEX_R_MSR_PORTN_XBR_SET2_MM_CFG(port); + break; }; } @@ -1695,7 +1671,7 @@ static int nhmex_rbox_hw_config(struct intel_uncore_box *box, struct perf_event struct hw_perf_event *hwc = &event->hw; struct hw_perf_event_extra *reg1 = &event->hw.extra_reg; struct hw_perf_event_extra *reg2 = &event->hw.branch_reg; - int idx; + int port, idx; idx = (event->hw.config & NHMEX_R_PMON_CTL_EV_SEL_MASK) >> NHMEX_R_PMON_CTL_EV_SEL_SHIFT; @@ -1705,11 +1681,27 @@ static int nhmex_rbox_hw_config(struct intel_uncore_box *box, struct perf_event reg1->idx = idx; reg1->config = event->attr.config1; - switch (idx % 6) { + port = idx / 6 + box->pmu->pmu_idx * 4; + idx %= 6; + switch (idx) { + case 0: + reg1->reg = NHMEX_R_MSR_PORTN_IPERF_CFG0(port); + break; + case 1: + reg1->reg = NHMEX_R_MSR_PORTN_IPERF_CFG1(port); + break; + case 2: + case 3: + reg1->reg = NHMEX_R_MSR_PORTN_QLX_CFG(port); + break; case 4: case 5: - hwc->config |= event->attr.config & (~0ULL << 32); + if (idx == 4) + reg1->reg = NHMEX_R_MSR_PORTN_XBR_SET1_MM_CFG(port); + else + reg1->reg = NHMEX_R_MSR_PORTN_XBR_SET2_MM_CFG(port); reg2->config = event->attr.config2; + hwc->config |= event->attr.config & (~0ULL << 32); break; }; return 0; @@ -1735,34 +1727,28 @@ static void nhmex_rbox_msr_enable_event(struct intel_uncore_box *box, struct per struct hw_perf_event *hwc = &event->hw; struct hw_perf_event_extra *reg1 = &hwc->extra_reg; struct hw_perf_event_extra *reg2 = &hwc->branch_reg; - int idx, port; + int idx, er_idx; - idx = reg1->idx; - port = idx / 6 + box->pmu->pmu_idx * 4; + idx = reg1->idx % 6; + er_idx = idx; + if (er_idx > 2) + er_idx--; + er_idx += (reg1->idx / 6) * 5; - switch (idx % 6) { + switch (idx) { case 0: - wrmsrl(NHMEX_R_MSR_PORTN_IPERF_CFG0(port), reg1->config); - break; case 1: - wrmsrl(NHMEX_R_MSR_PORTN_IPERF_CFG1(port), reg1->config); + wrmsrl(reg1->reg, reg1->config); break; case 2: case 3: - wrmsrl(NHMEX_R_MSR_PORTN_QLX_CFG(port), - nhmex_rbox_shared_reg_config(box, 2 + (idx / 6) * 5)); + wrmsrl(reg1->reg, nhmex_rbox_shared_reg_config(box, er_idx)); break; case 4: - wrmsrl(NHMEX_R_MSR_PORTN_XBR_SET1_MM_CFG(port), - hwc->config >> 32); - wrmsrl(NHMEX_R_MSR_PORTN_XBR_SET1_MATCH(port), reg1->config); - wrmsrl(NHMEX_R_MSR_PORTN_XBR_SET1_MASK(port), reg2->config); - break; case 5: - wrmsrl(NHMEX_R_MSR_PORTN_XBR_SET2_MM_CFG(port), - hwc->config >> 32); - wrmsrl(NHMEX_R_MSR_PORTN_XBR_SET2_MATCH(port), reg1->config); - wrmsrl(NHMEX_R_MSR_PORTN_XBR_SET2_MASK(port), reg2->config); + wrmsrl(reg1->reg, reg1->config); + wrmsrl(reg1->reg + 1, hwc->config >> 32); + wrmsrl(reg1->reg + 2, reg2->config); break; }; @@ -1770,8 +1756,8 @@ static void nhmex_rbox_msr_enable_event(struct intel_uncore_box *box, struct per (hwc->config & NHMEX_R_PMON_CTL_EV_SEL_MASK)); } -DEFINE_UNCORE_FORMAT_ATTR(xbr_mm_cfg, xbr_mm_cfg, "config:32-63"); -DEFINE_UNCORE_FORMAT_ATTR(xbr_match, xbr_match, "config1:0-63"); +DEFINE_UNCORE_FORMAT_ATTR(xbr_match, xbr_match, "config:32-63"); +DEFINE_UNCORE_FORMAT_ATTR(xbr_mm_cfg, xbr_mm_cfg, "config1:0-63"); DEFINE_UNCORE_FORMAT_ATTR(xbr_mask, xbr_mask, "config2:0-63"); DEFINE_UNCORE_FORMAT_ATTR(qlx_cfg, qlx_cfg, "config1:0-15"); DEFINE_UNCORE_FORMAT_ATTR(iperf_cfg, iperf_cfg, "config1:0-31"); @@ -1950,7 +1936,7 @@ struct intel_uncore_box *uncore_alloc_box(struct intel_uncore_type *type, int cp static struct intel_uncore_box * uncore_pmu_to_box(struct intel_uncore_pmu *pmu, int cpu) { - struct intel_uncore_box *box; + static struct intel_uncore_box *box; box = *per_cpu_ptr(pmu->box, cpu); if (box) @@ -2317,7 +2303,6 @@ int uncore_pmu_event_init(struct perf_event *event) event->hw.idx = -1; event->hw.last_tag = ~0ULL; event->hw.extra_reg.idx = EXTRA_REG_NONE; - event->hw.branch_reg.idx = EXTRA_REG_NONE; if (event->attr.config == UNCORE_FIXED_EVENT) { /* no fixed counter */ @@ -2347,27 +2332,6 @@ int uncore_pmu_event_init(struct perf_event *event) return ret; } -static ssize_t uncore_get_attr_cpumask(struct device *dev, - struct device_attribute *attr, char *buf) -{ - int n = cpulist_scnprintf(buf, PAGE_SIZE - 2, &uncore_cpu_mask); - - buf[n++] = '\n'; - buf[n] = '\0'; - return n; -} - -static DEVICE_ATTR(cpumask, S_IRUGO, uncore_get_attr_cpumask, NULL); - -static struct attribute *uncore_pmu_attrs[] = { - &dev_attr_cpumask.attr, - NULL, -}; - -static struct attribute_group uncore_pmu_attr_group = { - .attrs = uncore_pmu_attrs, -}; - static int __init uncore_pmu_register(struct intel_uncore_pmu *pmu) { int ret; @@ -2405,11 +2369,11 @@ static void __init uncore_type_exit(struct intel_uncore_type *type) free_percpu(type->pmus[i].box); kfree(type->pmus); type->pmus = NULL; - kfree(type->events_group); - type->events_group = NULL; + kfree(type->attr_groups[1]); + type->attr_groups[1] = NULL; } -static void __init uncore_types_exit(struct intel_uncore_type **types) +static void uncore_types_exit(struct intel_uncore_type **types) { int i; for (i = 0; types[i]; i++) @@ -2458,10 +2422,9 @@ static int __init uncore_type_init(struct intel_uncore_type *type) for (j = 0; j < i; j++) attrs[j] = &type->event_descs[j].attr.attr; - type->events_group = events_group; + type->attr_groups[1] = events_group; } - type->pmu_group = &uncore_pmu_attr_group; type->pmus = pmus; return 0; fail: @@ -2851,13 +2814,7 @@ static int __init uncore_cpu_init(void) snbep_uncore_cbox.num_boxes = max_cores; msr_uncores = snbep_msr_uncores; break; - case 46: /* Nehalem-EX */ - uncore_nhmex = true; - case 47: /* Westmere-EX aka. Xeon E7 */ - if (!uncore_nhmex) - nhmex_uncore_mbox.event_descs = wsmex_uncore_mbox_events; - if (nhmex_uncore_cbox.num_boxes > max_cores) - nhmex_uncore_cbox.num_boxes = max_cores; + case 46: msr_uncores = nhmex_msr_uncores; break; default: diff --git a/trunk/arch/x86/kernel/cpu/perf_event_intel_uncore.h b/trunk/arch/x86/kernel/cpu/perf_event_intel_uncore.h index e68a4550e952..f3851892e077 100644 --- a/trunk/arch/x86/kernel/cpu/perf_event_intel_uncore.h +++ b/trunk/arch/x86/kernel/cpu/perf_event_intel_uncore.h @@ -5,7 +5,7 @@ #include "perf_event.h" #define UNCORE_PMU_NAME_LEN 32 -#define UNCORE_PMU_HRTIMER_INTERVAL (60LL * NSEC_PER_SEC) +#define UNCORE_PMU_HRTIMER_INTERVAL (60 * NSEC_PER_SEC) #define UNCORE_FIXED_EVENT 0xff #define UNCORE_PMC_IDX_MAX_GENERIC 8 @@ -230,7 +230,6 @@ #define NHMEX_S1_MSR_MASK 0xe5a #define NHMEX_S_PMON_MM_CFG_EN (0x1ULL << 63) -#define NHMEX_S_EVENT_TO_R_PROG_EV 0 /* NHM-EX Mbox */ #define NHMEX_M0_MSR_GLOBAL_CTL 0xca0 @@ -276,11 +275,17 @@ NHMEX_M_PMON_CTL_INC_SEL_MASK | \ NHMEX_M_PMON_CTL_SET_FLAG_SEL_MASK) -#define NHMEX_M_PMON_ZDP_CTL_FVC_MASK (((1 << 11) - 1) | (1 << 23)) -#define NHMEX_M_PMON_ZDP_CTL_FVC_EVENT_MASK(n) (0x7 << (11 + 3 * (n))) -#define WSMEX_M_PMON_ZDP_CTL_FVC_MASK (((1 << 12) - 1) | (1 << 24)) -#define WSMEX_M_PMON_ZDP_CTL_FVC_EVENT_MASK(n) (0x7 << (12 + 3 * (n))) +#define NHMEX_M_PMON_ZDP_CTL_FVC_FVID_MASK 0x1f +#define NHMEX_M_PMON_ZDP_CTL_FVC_BCMD_MASK (0x7 << 5) +#define NHMEX_M_PMON_ZDP_CTL_FVC_RSP_MASK (0x7 << 8) +#define NHMEX_M_PMON_ZDP_CTL_FVC_PBOX_INIT_ERR (1 << 23) +#define NHMEX_M_PMON_ZDP_CTL_FVC_MASK \ + (NHMEX_M_PMON_ZDP_CTL_FVC_FVID_MASK | \ + NHMEX_M_PMON_ZDP_CTL_FVC_BCMD_MASK | \ + NHMEX_M_PMON_ZDP_CTL_FVC_RSP_MASK | \ + NHMEX_M_PMON_ZDP_CTL_FVC_PBOX_INIT_ERR) +#define NHMEX_M_PMON_ZDP_CTL_FVC_EVENT_MASK(n) (0x7 << (11 + 3 * (n))) /* * use the 9~13 bits to select event If the 7th bit is not set, @@ -363,18 +368,15 @@ struct intel_uncore_type { unsigned num_shared_regs:8; unsigned single_fixed:1; unsigned pair_ctr_ctl:1; - unsigned *msr_offsets; struct event_constraint unconstrainted; struct event_constraint *constraints; struct intel_uncore_pmu *pmus; struct intel_uncore_ops *ops; struct uncore_event_desc *event_descs; - const struct attribute_group *attr_groups[4]; + const struct attribute_group *attr_groups[3]; }; -#define pmu_group attr_groups[0] -#define format_group attr_groups[1] -#define events_group attr_groups[2] +#define format_group attr_groups[0] struct intel_uncore_ops { void (*init_box)(struct intel_uncore_box *); @@ -483,31 +485,29 @@ unsigned uncore_pci_perf_ctr(struct intel_uncore_box *box, int idx) return idx * 8 + box->pmu->type->perf_ctr; } -static inline unsigned uncore_msr_box_offset(struct intel_uncore_box *box) -{ - struct intel_uncore_pmu *pmu = box->pmu; - return pmu->type->msr_offsets ? - pmu->type->msr_offsets[pmu->pmu_idx] : - pmu->type->msr_offset * pmu->pmu_idx; -} - -static inline unsigned uncore_msr_box_ctl(struct intel_uncore_box *box) +static inline +unsigned uncore_msr_box_ctl(struct intel_uncore_box *box) { if (!box->pmu->type->box_ctl) return 0; - return box->pmu->type->box_ctl + uncore_msr_box_offset(box); + return box->pmu->type->box_ctl + + box->pmu->type->msr_offset * box->pmu->pmu_idx; } -static inline unsigned uncore_msr_fixed_ctl(struct intel_uncore_box *box) +static inline +unsigned uncore_msr_fixed_ctl(struct intel_uncore_box *box) { if (!box->pmu->type->fixed_ctl) return 0; - return box->pmu->type->fixed_ctl + uncore_msr_box_offset(box); + return box->pmu->type->fixed_ctl + + box->pmu->type->msr_offset * box->pmu->pmu_idx; } -static inline unsigned uncore_msr_fixed_ctr(struct intel_uncore_box *box) +static inline +unsigned uncore_msr_fixed_ctr(struct intel_uncore_box *box) { - return box->pmu->type->fixed_ctr + uncore_msr_box_offset(box); + return box->pmu->type->fixed_ctr + + box->pmu->type->msr_offset * box->pmu->pmu_idx; } static inline @@ -515,7 +515,7 @@ unsigned uncore_msr_event_ctl(struct intel_uncore_box *box, int idx) { return box->pmu->type->event_ctl + (box->pmu->type->pair_ctr_ctl ? 2 * idx : idx) + - uncore_msr_box_offset(box); + box->pmu->type->msr_offset * box->pmu->pmu_idx; } static inline @@ -523,7 +523,7 @@ unsigned uncore_msr_perf_ctr(struct intel_uncore_box *box, int idx) { return box->pmu->type->perf_ctr + (box->pmu->type->pair_ctr_ctl ? 2 * idx : idx) + - uncore_msr_box_offset(box); + box->pmu->type->msr_offset * box->pmu->pmu_idx; } static inline diff --git a/trunk/arch/x86/kernel/cpu/proc.c b/trunk/arch/x86/kernel/cpu/proc.c index fbd895562292..8022c6681485 100644 --- a/trunk/arch/x86/kernel/cpu/proc.c +++ b/trunk/arch/x86/kernel/cpu/proc.c @@ -140,7 +140,10 @@ static int show_cpuinfo(struct seq_file *m, void *v) static void *c_start(struct seq_file *m, loff_t *pos) { - *pos = cpumask_next(*pos - 1, cpu_online_mask); + if (*pos == 0) /* just in case, cpu 0 is not the first */ + *pos = cpumask_first(cpu_online_mask); + else + *pos = cpumask_next(*pos - 1, cpu_online_mask); if ((*pos) < nr_cpu_ids) return &cpu_data(*pos); return NULL; diff --git a/trunk/arch/x86/kernel/cpuid.c b/trunk/arch/x86/kernel/cpuid.c index 60c78917190c..39472dd2323f 100644 --- a/trunk/arch/x86/kernel/cpuid.c +++ b/trunk/arch/x86/kernel/cpuid.c @@ -199,14 +199,12 @@ static int __init cpuid_init(void) goto out_chrdev; } cpuid_class->devnode = cpuid_devnode; - get_online_cpus(); for_each_online_cpu(i) { err = cpuid_device_create(i); if (err != 0) goto out_class; } register_hotcpu_notifier(&cpuid_class_cpu_notifier); - put_online_cpus(); err = 0; goto out; @@ -216,7 +214,6 @@ static int __init cpuid_init(void) for_each_online_cpu(i) { cpuid_device_destroy(i); } - put_online_cpus(); class_destroy(cpuid_class); out_chrdev: __unregister_chrdev(CPUID_MAJOR, 0, NR_CPUS, "cpu/cpuid"); @@ -228,13 +225,11 @@ static void __exit cpuid_exit(void) { int cpu = 0; - get_online_cpus(); for_each_online_cpu(cpu) cpuid_device_destroy(cpu); class_destroy(cpuid_class); __unregister_chrdev(CPUID_MAJOR, 0, NR_CPUS, "cpu/cpuid"); unregister_hotcpu_notifier(&cpuid_class_cpu_notifier); - put_online_cpus(); } module_init(cpuid_init); diff --git a/trunk/arch/x86/kernel/devicetree.c b/trunk/arch/x86/kernel/devicetree.c index b1581527a236..3ae2ced4a874 100644 --- a/trunk/arch/x86/kernel/devicetree.c +++ b/trunk/arch/x86/kernel/devicetree.c @@ -342,47 +342,6 @@ const struct irq_domain_ops ioapic_irq_domain_ops = { .xlate = ioapic_xlate, }; -static void dt_add_ioapic_domain(unsigned int ioapic_num, - struct device_node *np) -{ - struct irq_domain *id; - struct mp_ioapic_gsi *gsi_cfg; - int ret; - int num; - - gsi_cfg = mp_ioapic_gsi_routing(ioapic_num); - num = gsi_cfg->gsi_end - gsi_cfg->gsi_base + 1; - - id = irq_domain_add_linear(np, num, &ioapic_irq_domain_ops, - (void *)ioapic_num); - BUG_ON(!id); - if (gsi_cfg->gsi_base == 0) { - /* - * The first NR_IRQS_LEGACY irq descs are allocated in - * early_irq_init() and need just a mapping. The - * remaining irqs need both. All of them are preallocated - * and assigned so we can keep the 1:1 mapping which the ioapic - * is having. - */ - ret = irq_domain_associate_many(id, 0, 0, NR_IRQS_LEGACY); - if (ret) - pr_err("Error mapping legacy IRQs: %d\n", ret); - - if (num > NR_IRQS_LEGACY) { - ret = irq_create_strict_mappings(id, NR_IRQS_LEGACY, - NR_IRQS_LEGACY, num - NR_IRQS_LEGACY); - if (ret) - pr_err("Error creating mapping for the " - "remaining IRQs: %d\n", ret); - } - irq_set_default_host(id); - } else { - ret = irq_create_strict_mappings(id, gsi_cfg->gsi_base, 0, num); - if (ret) - pr_err("Error creating IRQ mapping: %d\n", ret); - } -} - static void __init ioapic_add_ofnode(struct device_node *np) { struct resource r; @@ -397,7 +356,15 @@ static void __init ioapic_add_ofnode(struct device_node *np) for (i = 0; i < nr_ioapics; i++) { if (r.start == mpc_ioapic_addr(i)) { - dt_add_ioapic_domain(i, np); + struct irq_domain *id; + struct mp_ioapic_gsi *gsi_cfg; + + gsi_cfg = mp_ioapic_gsi_routing(i); + + id = irq_domain_add_legacy(np, 32, gsi_cfg->gsi_base, 0, + &ioapic_irq_domain_ops, + (void*)i); + BUG_ON(!id); return; } } diff --git a/trunk/arch/x86/kernel/entry_32.S b/trunk/arch/x86/kernel/entry_32.S index f438a44bf8f9..623f28837476 100644 --- a/trunk/arch/x86/kernel/entry_32.S +++ b/trunk/arch/x86/kernel/entry_32.S @@ -1109,21 +1109,17 @@ ENTRY(ftrace_caller) pushl %eax pushl %ecx pushl %edx - pushl $0 /* Pass NULL as regs pointer */ - movl 4*4(%esp), %eax + movl 0xc(%esp), %eax movl 0x4(%ebp), %edx - leal function_trace_op, %ecx subl $MCOUNT_INSN_SIZE, %eax .globl ftrace_call ftrace_call: call ftrace_stub - addl $4,%esp /* skip NULL pointer */ popl %edx popl %ecx popl %eax -ftrace_ret: #ifdef CONFIG_FUNCTION_GRAPH_TRACER .globl ftrace_graph_call ftrace_graph_call: @@ -1135,71 +1131,6 @@ ftrace_stub: ret END(ftrace_caller) -ENTRY(ftrace_regs_caller) - pushf /* push flags before compare (in cs location) */ - cmpl $0, function_trace_stop - jne ftrace_restore_flags - - /* - * i386 does not save SS and ESP when coming from kernel. - * Instead, to get sp, ®s->sp is used (see ptrace.h). - * Unfortunately, that means eflags must be at the same location - * as the current return ip is. We move the return ip into the - * ip location, and move flags into the return ip location. - */ - pushl 4(%esp) /* save return ip into ip slot */ - - pushl $0 /* Load 0 into orig_ax */ - pushl %gs - pushl %fs - pushl %es - pushl %ds - pushl %eax - pushl %ebp - pushl %edi - pushl %esi - pushl %edx - pushl %ecx - pushl %ebx - - movl 13*4(%esp), %eax /* Get the saved flags */ - movl %eax, 14*4(%esp) /* Move saved flags into regs->flags location */ - /* clobbering return ip */ - movl $__KERNEL_CS,13*4(%esp) - - movl 12*4(%esp), %eax /* Load ip (1st parameter) */ - subl $MCOUNT_INSN_SIZE, %eax /* Adjust ip */ - movl 0x4(%ebp), %edx /* Load parent ip (2nd parameter) */ - leal function_trace_op, %ecx /* Save ftrace_pos in 3rd parameter */ - pushl %esp /* Save pt_regs as 4th parameter */ - -GLOBAL(ftrace_regs_call) - call ftrace_stub - - addl $4, %esp /* Skip pt_regs */ - movl 14*4(%esp), %eax /* Move flags back into cs */ - movl %eax, 13*4(%esp) /* Needed to keep addl from modifying flags */ - movl 12*4(%esp), %eax /* Get return ip from regs->ip */ - movl %eax, 14*4(%esp) /* Put return ip back for ret */ - - popl %ebx - popl %ecx - popl %edx - popl %esi - popl %edi - popl %ebp - popl %eax - popl %ds - popl %es - popl %fs - popl %gs - addl $8, %esp /* Skip orig_ax and ip */ - popf /* Pop flags at end (no addl to corrupt flags) */ - jmp ftrace_ret - -ftrace_restore_flags: - popf - jmp ftrace_stub #else /* ! CONFIG_DYNAMIC_FTRACE */ ENTRY(mcount) @@ -1240,6 +1171,9 @@ END(mcount) #ifdef CONFIG_FUNCTION_GRAPH_TRACER ENTRY(ftrace_graph_caller) + cmpl $0, function_trace_stop + jne ftrace_stub + pushl %eax pushl %ecx pushl %edx diff --git a/trunk/arch/x86/kernel/entry_64.S b/trunk/arch/x86/kernel/entry_64.S index 066334be7b74..69babd8c834f 100644 --- a/trunk/arch/x86/kernel/entry_64.S +++ b/trunk/arch/x86/kernel/entry_64.S @@ -56,7 +56,6 @@ #include #include #include -#include #include /* Avoid __ASSEMBLER__'ifying just for this. */ @@ -69,51 +68,25 @@ .section .entry.text, "ax" #ifdef CONFIG_FUNCTION_TRACER - -#ifdef CC_USING_FENTRY -# define function_hook __fentry__ -#else -# define function_hook mcount -#endif - #ifdef CONFIG_DYNAMIC_FTRACE - -ENTRY(function_hook) +ENTRY(mcount) retq -END(function_hook) - -/* skip is set if stack has been adjusted */ -.macro ftrace_caller_setup skip=0 - MCOUNT_SAVE_FRAME \skip - - /* Load the ftrace_ops into the 3rd parameter */ - leaq function_trace_op, %rdx - - /* Load ip into the first parameter */ - movq RIP(%rsp), %rdi - subq $MCOUNT_INSN_SIZE, %rdi - /* Load the parent_ip into the second parameter */ -#ifdef CC_USING_FENTRY - movq SS+16(%rsp), %rsi -#else - movq 8(%rbp), %rsi -#endif -.endm +END(mcount) ENTRY(ftrace_caller) - /* Check if tracing was disabled (quick check) */ cmpl $0, function_trace_stop jne ftrace_stub - ftrace_caller_setup - /* regs go into 4th parameter (but make it NULL) */ - movq $0, %rcx + MCOUNT_SAVE_FRAME + + movq 0x38(%rsp), %rdi + movq 8(%rbp), %rsi + subq $MCOUNT_INSN_SIZE, %rdi GLOBAL(ftrace_call) call ftrace_stub MCOUNT_RESTORE_FRAME -ftrace_return: #ifdef CONFIG_FUNCTION_GRAPH_TRACER GLOBAL(ftrace_graph_call) @@ -124,78 +97,8 @@ GLOBAL(ftrace_stub) retq END(ftrace_caller) -ENTRY(ftrace_regs_caller) - /* Save the current flags before compare (in SS location)*/ - pushfq - - /* Check if tracing was disabled (quick check) */ - cmpl $0, function_trace_stop - jne ftrace_restore_flags - - /* skip=8 to skip flags saved in SS */ - ftrace_caller_setup 8 - - /* Save the rest of pt_regs */ - movq %r15, R15(%rsp) - movq %r14, R14(%rsp) - movq %r13, R13(%rsp) - movq %r12, R12(%rsp) - movq %r11, R11(%rsp) - movq %r10, R10(%rsp) - movq %rbp, RBP(%rsp) - movq %rbx, RBX(%rsp) - /* Copy saved flags */ - movq SS(%rsp), %rcx - movq %rcx, EFLAGS(%rsp) - /* Kernel segments */ - movq $__KERNEL_DS, %rcx - movq %rcx, SS(%rsp) - movq $__KERNEL_CS, %rcx - movq %rcx, CS(%rsp) - /* Stack - skipping return address */ - leaq SS+16(%rsp), %rcx - movq %rcx, RSP(%rsp) - - /* regs go into 4th parameter */ - leaq (%rsp), %rcx - -GLOBAL(ftrace_regs_call) - call ftrace_stub - - /* Copy flags back to SS, to restore them */ - movq EFLAGS(%rsp), %rax - movq %rax, SS(%rsp) - - /* Handlers can change the RIP */ - movq RIP(%rsp), %rax - movq %rax, SS+8(%rsp) - - /* restore the rest of pt_regs */ - movq R15(%rsp), %r15 - movq R14(%rsp), %r14 - movq R13(%rsp), %r13 - movq R12(%rsp), %r12 - movq R10(%rsp), %r10 - movq RBP(%rsp), %rbp - movq RBX(%rsp), %rbx - - /* skip=8 to skip flags saved in SS */ - MCOUNT_RESTORE_FRAME 8 - - /* Restore flags */ - popfq - - jmp ftrace_return -ftrace_restore_flags: - popfq - jmp ftrace_stub - -END(ftrace_regs_caller) - - #else /* ! CONFIG_DYNAMIC_FTRACE */ - -ENTRY(function_hook) +ENTRY(mcount) cmpl $0, function_trace_stop jne ftrace_stub @@ -216,12 +119,8 @@ GLOBAL(ftrace_stub) trace: MCOUNT_SAVE_FRAME - movq RIP(%rsp), %rdi -#ifdef CC_USING_FENTRY - movq SS+16(%rsp), %rsi -#else + movq 0x38(%rsp), %rdi movq 8(%rbp), %rsi -#endif subq $MCOUNT_INSN_SIZE, %rdi call *ftrace_trace_function @@ -229,22 +128,20 @@ trace: MCOUNT_RESTORE_FRAME jmp ftrace_stub -END(function_hook) +END(mcount) #endif /* CONFIG_DYNAMIC_FTRACE */ #endif /* CONFIG_FUNCTION_TRACER */ #ifdef CONFIG_FUNCTION_GRAPH_TRACER ENTRY(ftrace_graph_caller) + cmpl $0, function_trace_stop + jne ftrace_stub + MCOUNT_SAVE_FRAME -#ifdef CC_USING_FENTRY - leaq SS+16(%rsp), %rdi - movq $0, %rdx /* No framepointers needed */ -#else leaq 8(%rbp), %rdi + movq 0x38(%rsp), %rsi movq (%rbp), %rdx -#endif - movq RIP(%rsp), %rsi subq $MCOUNT_INSN_SIZE, %rsi call prepare_ftrace_return @@ -445,15 +342,15 @@ ENDPROC(native_usergs_sysret64) .macro SAVE_ARGS_IRQ cld /* start from rbp in pt_regs and jump over */ - movq_cfi rdi, (RDI-RBP) - movq_cfi rsi, (RSI-RBP) - movq_cfi rdx, (RDX-RBP) - movq_cfi rcx, (RCX-RBP) - movq_cfi rax, (RAX-RBP) - movq_cfi r8, (R8-RBP) - movq_cfi r9, (R9-RBP) - movq_cfi r10, (R10-RBP) - movq_cfi r11, (R11-RBP) + movq_cfi rdi, RDI-RBP + movq_cfi rsi, RSI-RBP + movq_cfi rdx, RDX-RBP + movq_cfi rcx, RCX-RBP + movq_cfi rax, RAX-RBP + movq_cfi r8, R8-RBP + movq_cfi r9, R9-RBP + movq_cfi r10, R10-RBP + movq_cfi r11, R11-RBP /* Save rbp so that we can unwind from get_irq_regs() */ movq_cfi rbp, 0 @@ -487,7 +384,7 @@ ENDPROC(native_usergs_sysret64) .endm ENTRY(save_rest) - PARTIAL_FRAME 1 (REST_SKIP+8) + PARTIAL_FRAME 1 REST_SKIP+8 movq 5*8+16(%rsp), %r11 /* save return address */ movq_cfi rbx, RBX+16 movq_cfi rbp, RBP+16 @@ -543,7 +440,7 @@ ENTRY(ret_from_fork) LOCK ; btr $TIF_FORK,TI_flags(%r8) - pushq_cfi $0x0002 + pushq_cfi kernel_eflags(%rip) popfq_cfi # reset kernel eflags call schedule_tail # rdi: 'prev' task parameter @@ -668,7 +565,7 @@ sysret_careful: TRACE_IRQS_ON ENABLE_INTERRUPTS(CLBR_NONE) pushq_cfi %rdi - SCHEDULE_USER + call schedule popq_cfi %rdi jmp sysret_check @@ -781,7 +678,7 @@ int_careful: TRACE_IRQS_ON ENABLE_INTERRUPTS(CLBR_NONE) pushq_cfi %rdi - SCHEDULE_USER + call schedule popq_cfi %rdi DISABLE_INTERRUPTS(CLBR_NONE) TRACE_IRQS_OFF @@ -1077,7 +974,7 @@ retint_careful: TRACE_IRQS_ON ENABLE_INTERRUPTS(CLBR_NONE) pushq_cfi %rdi - SCHEDULE_USER + call schedule popq_cfi %rdi GET_THREAD_INFO(%rcx) DISABLE_INTERRUPTS(CLBR_NONE) @@ -1552,7 +1449,7 @@ paranoid_userspace: paranoid_schedule: TRACE_IRQS_ON ENABLE_INTERRUPTS(CLBR_ANY) - SCHEDULE_USER + call schedule DISABLE_INTERRUPTS(CLBR_ANY) TRACE_IRQS_OFF jmp paranoid_userspace diff --git a/trunk/arch/x86/kernel/ftrace.c b/trunk/arch/x86/kernel/ftrace.c index 1d414029f1d8..c3a7cb4bf6e6 100644 --- a/trunk/arch/x86/kernel/ftrace.c +++ b/trunk/arch/x86/kernel/ftrace.c @@ -206,21 +206,6 @@ static int ftrace_modify_code(unsigned long ip, unsigned const char *old_code, unsigned const char *new_code); -/* - * Should never be called: - * As it is only called by __ftrace_replace_code() which is called by - * ftrace_replace_code() that x86 overrides, and by ftrace_update_code() - * which is called to turn mcount into nops or nops into function calls - * but not to convert a function from not using regs to one that uses - * regs, which ftrace_modify_call() is for. - */ -int ftrace_modify_call(struct dyn_ftrace *rec, unsigned long old_addr, - unsigned long addr) -{ - WARN_ON(1); - return -EINVAL; -} - int ftrace_update_ftrace_func(ftrace_func_t func) { unsigned long ip = (unsigned long)(&ftrace_call); @@ -235,14 +220,6 @@ int ftrace_update_ftrace_func(ftrace_func_t func) ret = ftrace_modify_code(ip, old, new); - /* Also update the regs callback function */ - if (!ret) { - ip = (unsigned long)(&ftrace_regs_call); - memcpy(old, &ftrace_regs_call, MCOUNT_INSN_SIZE); - new = ftrace_call_replace(ip, (unsigned long)func); - ret = ftrace_modify_code(ip, old, new); - } - atomic_dec(&modifying_ftrace_code); return ret; @@ -322,32 +299,6 @@ static int add_brk_on_nop(struct dyn_ftrace *rec) return add_break(rec->ip, old); } -/* - * If the record has the FTRACE_FL_REGS set, that means that it - * wants to convert to a callback that saves all regs. If FTRACE_FL_REGS - * is not not set, then it wants to convert to the normal callback. - */ -static unsigned long get_ftrace_addr(struct dyn_ftrace *rec) -{ - if (rec->flags & FTRACE_FL_REGS) - return (unsigned long)FTRACE_REGS_ADDR; - else - return (unsigned long)FTRACE_ADDR; -} - -/* - * The FTRACE_FL_REGS_EN is set when the record already points to - * a function that saves all the regs. Basically the '_EN' version - * represents the current state of the function. - */ -static unsigned long get_ftrace_old_addr(struct dyn_ftrace *rec) -{ - if (rec->flags & FTRACE_FL_REGS_EN) - return (unsigned long)FTRACE_REGS_ADDR; - else - return (unsigned long)FTRACE_ADDR; -} - static int add_breakpoints(struct dyn_ftrace *rec, int enable) { unsigned long ftrace_addr; @@ -355,7 +306,7 @@ static int add_breakpoints(struct dyn_ftrace *rec, int enable) ret = ftrace_test_record(rec, enable); - ftrace_addr = get_ftrace_addr(rec); + ftrace_addr = (unsigned long)FTRACE_ADDR; switch (ret) { case FTRACE_UPDATE_IGNORE: @@ -365,10 +316,6 @@ static int add_breakpoints(struct dyn_ftrace *rec, int enable) /* converting nop to call */ return add_brk_on_nop(rec); - case FTRACE_UPDATE_MODIFY_CALL_REGS: - case FTRACE_UPDATE_MODIFY_CALL: - ftrace_addr = get_ftrace_old_addr(rec); - /* fall through */ case FTRACE_UPDATE_MAKE_NOP: /* converting a call to a nop */ return add_brk_on_call(rec, ftrace_addr); @@ -413,21 +360,13 @@ static int remove_breakpoint(struct dyn_ftrace *rec) * If not, don't touch the breakpoint, we make just create * a disaster. */ - ftrace_addr = get_ftrace_addr(rec); - nop = ftrace_call_replace(ip, ftrace_addr); - - if (memcmp(&ins[1], &nop[1], MCOUNT_INSN_SIZE - 1) == 0) - goto update; - - /* Check both ftrace_addr and ftrace_old_addr */ - ftrace_addr = get_ftrace_old_addr(rec); + ftrace_addr = (unsigned long)FTRACE_ADDR; nop = ftrace_call_replace(ip, ftrace_addr); if (memcmp(&ins[1], &nop[1], MCOUNT_INSN_SIZE - 1) != 0) return -EINVAL; } - update: return probe_kernel_write((void *)ip, &nop[0], 1); } @@ -466,14 +405,12 @@ static int add_update(struct dyn_ftrace *rec, int enable) ret = ftrace_test_record(rec, enable); - ftrace_addr = get_ftrace_addr(rec); + ftrace_addr = (unsigned long)FTRACE_ADDR; switch (ret) { case FTRACE_UPDATE_IGNORE: return 0; - case FTRACE_UPDATE_MODIFY_CALL_REGS: - case FTRACE_UPDATE_MODIFY_CALL: case FTRACE_UPDATE_MAKE_CALL: /* converting nop to call */ return add_update_call(rec, ftrace_addr); @@ -518,14 +455,12 @@ static int finish_update(struct dyn_ftrace *rec, int enable) ret = ftrace_update_record(rec, enable); - ftrace_addr = get_ftrace_addr(rec); + ftrace_addr = (unsigned long)FTRACE_ADDR; switch (ret) { case FTRACE_UPDATE_IGNORE: return 0; - case FTRACE_UPDATE_MODIFY_CALL_REGS: - case FTRACE_UPDATE_MODIFY_CALL: case FTRACE_UPDATE_MAKE_CALL: /* converting nop to call */ return finish_update_call(rec, ftrace_addr); diff --git a/trunk/arch/x86/kernel/i387.c b/trunk/arch/x86/kernel/i387.c index 675a05012449..f250431fb505 100644 --- a/trunk/arch/x86/kernel/i387.c +++ b/trunk/arch/x86/kernel/i387.c @@ -19,17 +19,24 @@ #include #include +#ifdef CONFIG_X86_64 +# include +# include +#else +# define save_i387_xstate_ia32 save_i387_xstate +# define restore_i387_xstate_ia32 restore_i387_xstate +# define _fpstate_ia32 _fpstate +# define _xstate_ia32 _xstate +# define sig_xstate_ia32_size sig_xstate_size +# define fx_sw_reserved_ia32 fx_sw_reserved +# define user_i387_ia32_struct user_i387_struct +# define user32_fxsr_struct user_fxsr_struct +#endif + /* * Were we in an interrupt that interrupted kernel mode? * - * For now, with eagerfpu we will return interrupted kernel FPU - * state as not-idle. TBD: Ideally we can change the return value - * to something like __thread_has_fpu(current). But we need to - * be careful of doing __thread_clear_has_fpu() before saving - * the FPU etc for supporting nested uses etc. For now, take - * the simple route! - * - * On others, we can do a kernel_fpu_begin/end() pair *ONLY* if that + * We can do a kernel_fpu_begin/end() pair *ONLY* if that * pair does nothing at all: the thread must not have fpu (so * that we don't try to save the FPU state), and TS must * be set (so that the clts/stts pair does nothing that is @@ -37,9 +44,6 @@ */ static inline bool interrupted_kernel_fpu_idle(void) { - if (use_eager_fpu()) - return 0; - return !__thread_has_fpu(current) && (read_cr0() & X86_CR0_TS); } @@ -73,29 +77,29 @@ bool irq_fpu_usable(void) } EXPORT_SYMBOL(irq_fpu_usable); -void __kernel_fpu_begin(void) +void kernel_fpu_begin(void) { struct task_struct *me = current; + WARN_ON_ONCE(!irq_fpu_usable()); + preempt_disable(); if (__thread_has_fpu(me)) { __save_init_fpu(me); __thread_clear_has_fpu(me); - /* We do 'stts()' in __kernel_fpu_end() */ - } else if (!use_eager_fpu()) { + /* We do 'stts()' in kernel_fpu_end() */ + } else { this_cpu_write(fpu_owner_task, NULL); clts(); } } -EXPORT_SYMBOL(__kernel_fpu_begin); +EXPORT_SYMBOL(kernel_fpu_begin); -void __kernel_fpu_end(void) +void kernel_fpu_end(void) { - if (use_eager_fpu()) - math_state_restore(); - else - stts(); + stts(); + preempt_enable(); } -EXPORT_SYMBOL(__kernel_fpu_end); +EXPORT_SYMBOL(kernel_fpu_end); void unlazy_fpu(struct task_struct *tsk) { @@ -109,15 +113,23 @@ void unlazy_fpu(struct task_struct *tsk) } EXPORT_SYMBOL(unlazy_fpu); -unsigned int mxcsr_feature_mask __read_mostly = 0xffffffffu; +#ifdef CONFIG_MATH_EMULATION +# define HAVE_HWFP (boot_cpu_data.hard_math) +#else +# define HAVE_HWFP 1 +#endif + +static unsigned int mxcsr_feature_mask __read_mostly = 0xffffffffu; unsigned int xstate_size; EXPORT_SYMBOL_GPL(xstate_size); +unsigned int sig_xstate_ia32_size = sizeof(struct _fpstate_ia32); static struct i387_fxsave_struct fx_scratch __cpuinitdata; static void __cpuinit mxcsr_feature_mask_init(void) { unsigned long mask = 0; + clts(); if (cpu_has_fxsr) { memset(&fx_scratch, 0, sizeof(struct i387_fxsave_struct)); asm volatile("fxsave %0" : : "m" (fx_scratch)); @@ -126,6 +138,7 @@ static void __cpuinit mxcsr_feature_mask_init(void) mask = 0x0000ffbf; } mxcsr_feature_mask &= mask; + stts(); } static void __cpuinit init_thread_xstate(void) @@ -179,8 +192,9 @@ void __cpuinit fpu_init(void) init_thread_xstate(); mxcsr_feature_mask_init(); - xsave_init(); - eager_fpu_init(); + /* clean state in init */ + current_thread_info()->status = 0; + clear_used_math(); } void fpu_finit(struct fpu *fpu) @@ -191,7 +205,12 @@ void fpu_finit(struct fpu *fpu) } if (cpu_has_fxsr) { - fx_finit(&fpu->state->fxsave); + struct i387_fxsave_struct *fx = &fpu->state->fxsave; + + memset(fx, 0, xstate_size); + fx->cwd = 0x37f; + if (cpu_has_xmm) + fx->mxcsr = MXCSR_DEFAULT; } else { struct i387_fsave_struct *fp = &fpu->state->fsave; memset(fp, 0, xstate_size); @@ -435,7 +454,7 @@ static inline u32 twd_fxsr_to_i387(struct i387_fxsave_struct *fxsave) * FXSR floating point environment conversions. */ -void +static void convert_from_fxsr(struct user_i387_ia32_struct *env, struct task_struct *tsk) { struct i387_fxsave_struct *fxsave = &tsk->thread.fpu.state->fxsave; @@ -472,8 +491,8 @@ convert_from_fxsr(struct user_i387_ia32_struct *env, struct task_struct *tsk) memcpy(&to[i], &from[i], sizeof(to[0])); } -void convert_to_fxsr(struct task_struct *tsk, - const struct user_i387_ia32_struct *env) +static void convert_to_fxsr(struct task_struct *tsk, + const struct user_i387_ia32_struct *env) { struct i387_fxsave_struct *fxsave = &tsk->thread.fpu.state->fxsave; @@ -569,6 +588,223 @@ int fpregs_set(struct task_struct *target, const struct user_regset *regset, return ret; } +/* + * Signal frame handlers. + */ + +static inline int save_i387_fsave(struct _fpstate_ia32 __user *buf) +{ + struct task_struct *tsk = current; + struct i387_fsave_struct *fp = &tsk->thread.fpu.state->fsave; + + fp->status = fp->swd; + if (__copy_to_user(buf, fp, sizeof(struct i387_fsave_struct))) + return -1; + return 1; +} + +static int save_i387_fxsave(struct _fpstate_ia32 __user *buf) +{ + struct task_struct *tsk = current; + struct i387_fxsave_struct *fx = &tsk->thread.fpu.state->fxsave; + struct user_i387_ia32_struct env; + int err = 0; + + convert_from_fxsr(&env, tsk); + if (__copy_to_user(buf, &env, sizeof(env))) + return -1; + + err |= __put_user(fx->swd, &buf->status); + err |= __put_user(X86_FXSR_MAGIC, &buf->magic); + if (err) + return -1; + + if (__copy_to_user(&buf->_fxsr_env[0], fx, xstate_size)) + return -1; + return 1; +} + +static int save_i387_xsave(void __user *buf) +{ + struct task_struct *tsk = current; + struct _fpstate_ia32 __user *fx = buf; + int err = 0; + + + sanitize_i387_state(tsk); + + /* + * For legacy compatible, we always set FP/SSE bits in the bit + * vector while saving the state to the user context. + * This will enable us capturing any changes(during sigreturn) to + * the FP/SSE bits by the legacy applications which don't touch + * xstate_bv in the xsave header. + * + * xsave aware applications can change the xstate_bv in the xsave + * header as well as change any contents in the memory layout. + * xrestore as part of sigreturn will capture all the changes. + */ + tsk->thread.fpu.state->xsave.xsave_hdr.xstate_bv |= XSTATE_FPSSE; + + if (save_i387_fxsave(fx) < 0) + return -1; + + err = __copy_to_user(&fx->sw_reserved, &fx_sw_reserved_ia32, + sizeof(struct _fpx_sw_bytes)); + err |= __put_user(FP_XSTATE_MAGIC2, + (__u32 __user *) (buf + sig_xstate_ia32_size + - FP_XSTATE_MAGIC2_SIZE)); + if (err) + return -1; + + return 1; +} + +int save_i387_xstate_ia32(void __user *buf) +{ + struct _fpstate_ia32 __user *fp = (struct _fpstate_ia32 __user *) buf; + struct task_struct *tsk = current; + + if (!used_math()) + return 0; + + if (!access_ok(VERIFY_WRITE, buf, sig_xstate_ia32_size)) + return -EACCES; + /* + * This will cause a "finit" to be triggered by the next + * attempted FPU operation by the 'current' process. + */ + clear_used_math(); + + if (!HAVE_HWFP) { + return fpregs_soft_get(current, NULL, + 0, sizeof(struct user_i387_ia32_struct), + NULL, fp) ? -1 : 1; + } + + unlazy_fpu(tsk); + + if (cpu_has_xsave) + return save_i387_xsave(fp); + if (cpu_has_fxsr) + return save_i387_fxsave(fp); + else + return save_i387_fsave(fp); +} + +static inline int restore_i387_fsave(struct _fpstate_ia32 __user *buf) +{ + struct task_struct *tsk = current; + + return __copy_from_user(&tsk->thread.fpu.state->fsave, buf, + sizeof(struct i387_fsave_struct)); +} + +static int restore_i387_fxsave(struct _fpstate_ia32 __user *buf, + unsigned int size) +{ + struct task_struct *tsk = current; + struct user_i387_ia32_struct env; + int err; + + err = __copy_from_user(&tsk->thread.fpu.state->fxsave, &buf->_fxsr_env[0], + size); + /* mxcsr reserved bits must be masked to zero for security reasons */ + tsk->thread.fpu.state->fxsave.mxcsr &= mxcsr_feature_mask; + if (err || __copy_from_user(&env, buf, sizeof(env))) + return 1; + convert_to_fxsr(tsk, &env); + + return 0; +} + +static int restore_i387_xsave(void __user *buf) +{ + struct _fpx_sw_bytes fx_sw_user; + struct _fpstate_ia32 __user *fx_user = + ((struct _fpstate_ia32 __user *) buf); + struct i387_fxsave_struct __user *fx = + (struct i387_fxsave_struct __user *) &fx_user->_fxsr_env[0]; + struct xsave_hdr_struct *xsave_hdr = + ¤t->thread.fpu.state->xsave.xsave_hdr; + u64 mask; + int err; + + if (check_for_xstate(fx, buf, &fx_sw_user)) + goto fx_only; + + mask = fx_sw_user.xstate_bv; + + err = restore_i387_fxsave(buf, fx_sw_user.xstate_size); + + xsave_hdr->xstate_bv &= pcntxt_mask; + /* + * These bits must be zero. + */ + xsave_hdr->reserved1[0] = xsave_hdr->reserved1[1] = 0; + + /* + * Init the state that is not present in the memory layout + * and enabled by the OS. + */ + mask = ~(pcntxt_mask & ~mask); + xsave_hdr->xstate_bv &= mask; + + return err; +fx_only: + /* + * Couldn't find the extended state information in the memory + * layout. Restore the FP/SSE and init the other extended state + * enabled by the OS. + */ + xsave_hdr->xstate_bv = XSTATE_FPSSE; + return restore_i387_fxsave(buf, sizeof(struct i387_fxsave_struct)); +} + +int restore_i387_xstate_ia32(void __user *buf) +{ + int err; + struct task_struct *tsk = current; + struct _fpstate_ia32 __user *fp = (struct _fpstate_ia32 __user *) buf; + + if (HAVE_HWFP) + clear_fpu(tsk); + + if (!buf) { + if (used_math()) { + clear_fpu(tsk); + clear_used_math(); + } + + return 0; + } else + if (!access_ok(VERIFY_READ, buf, sig_xstate_ia32_size)) + return -EACCES; + + if (!used_math()) { + err = init_fpu(tsk); + if (err) + return err; + } + + if (HAVE_HWFP) { + if (cpu_has_xsave) + err = restore_i387_xsave(buf); + else if (cpu_has_fxsr) + err = restore_i387_fxsave(fp, sizeof(struct + i387_fxsave_struct)); + else + err = restore_i387_fsave(fp); + } else { + err = fpregs_soft_set(current, NULL, + 0, sizeof(struct user_i387_ia32_struct), + NULL, fp) != 0; + } + set_used_math(); + + return err; +} + /* * FPU state for core dumps. * This is only used for a.out dumps now. diff --git a/trunk/arch/x86/kernel/i8259.c b/trunk/arch/x86/kernel/i8259.c index 9a5c460404dc..36d1853e91af 100644 --- a/trunk/arch/x86/kernel/i8259.c +++ b/trunk/arch/x86/kernel/i8259.c @@ -263,7 +263,7 @@ static void i8259A_shutdown(void) * out of. */ outb(0xff, PIC_MASTER_IMR); /* mask all of 8259A-1 */ - outb(0xff, PIC_SLAVE_IMR); /* mask all of 8259A-2 */ + outb(0xff, PIC_SLAVE_IMR); /* mask all of 8259A-1 */ } static struct syscore_ops i8259_syscore_ops = { diff --git a/trunk/arch/x86/kernel/irq.c b/trunk/arch/x86/kernel/irq.c index e4595f105910..1f5f1d5d2a02 100644 --- a/trunk/arch/x86/kernel/irq.c +++ b/trunk/arch/x86/kernel/irq.c @@ -92,8 +92,7 @@ int arch_show_interrupts(struct seq_file *p, int prec) seq_printf(p, " Rescheduling interrupts\n"); seq_printf(p, "%*s: ", prec, "CAL"); for_each_online_cpu(j) - seq_printf(p, "%10u ", irq_stats(j)->irq_call_count - - irq_stats(j)->irq_tlb_count); + seq_printf(p, "%10u ", irq_stats(j)->irq_call_count); seq_printf(p, " Function call interrupts\n"); seq_printf(p, "%*s: ", prec, "TLB"); for_each_online_cpu(j) @@ -148,6 +147,7 @@ u64 arch_irq_stat_cpu(unsigned int cpu) #ifdef CONFIG_SMP sum += irq_stats(cpu)->irq_resched_count; sum += irq_stats(cpu)->irq_call_count; + sum += irq_stats(cpu)->irq_tlb_count; #endif #ifdef CONFIG_X86_THERMAL_VECTOR sum += irq_stats(cpu)->irq_thermal_count; @@ -270,7 +270,7 @@ void fixup_irqs(void) if (cpumask_any_and(affinity, cpu_online_mask) >= nr_cpu_ids) { break_affinity = 1; - affinity = cpu_online_mask; + affinity = cpu_all_mask; } chip = irq_data_get_irq_chip(data); @@ -328,7 +328,6 @@ void fixup_irqs(void) chip->irq_retrigger(data); raw_spin_unlock(&desc->lock); } - __this_cpu_write(vector_irq[vector], -1); } } #endif diff --git a/trunk/arch/x86/kernel/kdebugfs.c b/trunk/arch/x86/kernel/kdebugfs.c index dc1404bf8e4b..1d5d31ea686b 100644 --- a/trunk/arch/x86/kernel/kdebugfs.c +++ b/trunk/arch/x86/kernel/kdebugfs.c @@ -107,7 +107,7 @@ static int __init create_setup_data_nodes(struct dentry *parent) { struct setup_data_node *node; struct setup_data *data; - int error; + int error = -ENOMEM; struct dentry *d; struct page *pg; u64 pa_data; @@ -121,10 +121,8 @@ static int __init create_setup_data_nodes(struct dentry *parent) while (pa_data) { node = kmalloc(sizeof(*node), GFP_KERNEL); - if (!node) { - error = -ENOMEM; + if (!node) goto err_dir; - } pg = pfn_to_page((pa_data+sizeof(*data)-1) >> PAGE_SHIFT); if (PageHighMem(pg)) { diff --git a/trunk/arch/x86/kernel/kprobes.c b/trunk/arch/x86/kernel/kprobes.c index 57916c0d3cf6..e2f751efb7b1 100644 --- a/trunk/arch/x86/kernel/kprobes.c +++ b/trunk/arch/x86/kernel/kprobes.c @@ -541,23 +541,6 @@ reenter_kprobe(struct kprobe *p, struct pt_regs *regs, struct kprobe_ctlblk *kcb return 1; } -#ifdef KPROBES_CAN_USE_FTRACE -static void __kprobes skip_singlestep(struct kprobe *p, struct pt_regs *regs, - struct kprobe_ctlblk *kcb) -{ - /* - * Emulate singlestep (and also recover regs->ip) - * as if there is a 5byte nop - */ - regs->ip = (unsigned long)p->addr + MCOUNT_INSN_SIZE; - if (unlikely(p->post_handler)) { - kcb->kprobe_status = KPROBE_HIT_SSDONE; - p->post_handler(p, regs, 0); - } - __this_cpu_write(current_kprobe, NULL); -} -#endif - /* * Interrupts are disabled on entry as trap3 is an interrupt gate and they * remain disabled throughout this function. @@ -616,12 +599,6 @@ static int __kprobes kprobe_handler(struct pt_regs *regs) } else if (kprobe_running()) { p = __this_cpu_read(current_kprobe); if (p->break_handler && p->break_handler(p, regs)) { -#ifdef KPROBES_CAN_USE_FTRACE - if (kprobe_ftrace(p)) { - skip_singlestep(p, regs, kcb); - return 1; - } -#endif setup_singlestep(p, regs, kcb, 0); return 1; } @@ -1075,50 +1052,6 @@ int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) return 0; } -#ifdef KPROBES_CAN_USE_FTRACE -/* Ftrace callback handler for kprobes */ -void __kprobes kprobe_ftrace_handler(unsigned long ip, unsigned long parent_ip, - struct ftrace_ops *ops, struct pt_regs *regs) -{ - struct kprobe *p; - struct kprobe_ctlblk *kcb; - unsigned long flags; - - /* Disable irq for emulating a breakpoint and avoiding preempt */ - local_irq_save(flags); - - p = get_kprobe((kprobe_opcode_t *)ip); - if (unlikely(!p) || kprobe_disabled(p)) - goto end; - - kcb = get_kprobe_ctlblk(); - if (kprobe_running()) { - kprobes_inc_nmissed_count(p); - } else { - /* Kprobe handler expects regs->ip = ip + 1 as breakpoint hit */ - regs->ip = ip + sizeof(kprobe_opcode_t); - - __this_cpu_write(current_kprobe, p); - kcb->kprobe_status = KPROBE_HIT_ACTIVE; - if (!p->pre_handler || !p->pre_handler(p, regs)) - skip_singlestep(p, regs, kcb); - /* - * If pre_handler returns !0, it sets regs->ip and - * resets current kprobe. - */ - } -end: - local_irq_restore(flags); -} - -int __kprobes arch_prepare_kprobe_ftrace(struct kprobe *p) -{ - p->ainsn.insn = NULL; - p->ainsn.boostable = -1; - return 0; -} -#endif - int __init arch_init_kprobes(void) { return arch_init_optprobes(); diff --git a/trunk/arch/x86/kernel/microcode_amd.c b/trunk/arch/x86/kernel/microcode_amd.c index 7720ff5a9ee2..8a2ce8fd41c0 100644 --- a/trunk/arch/x86/kernel/microcode_amd.c +++ b/trunk/arch/x86/kernel/microcode_amd.c @@ -75,113 +75,20 @@ struct microcode_amd { static struct equiv_cpu_entry *equiv_cpu_table; -struct ucode_patch { - struct list_head plist; - void *data; - u32 patch_id; - u16 equiv_cpu; -}; - -static LIST_HEAD(pcache); - -static u16 find_equiv_id(unsigned int cpu) -{ - struct ucode_cpu_info *uci = ucode_cpu_info + cpu; - int i = 0; - - if (!equiv_cpu_table) - return 0; - - while (equiv_cpu_table[i].installed_cpu != 0) { - if (uci->cpu_sig.sig == equiv_cpu_table[i].installed_cpu) - return equiv_cpu_table[i].equiv_cpu; - - i++; - } - return 0; -} - -static u32 find_cpu_family_by_equiv_cpu(u16 equiv_cpu) -{ - int i = 0; - - BUG_ON(!equiv_cpu_table); - - while (equiv_cpu_table[i].equiv_cpu != 0) { - if (equiv_cpu == equiv_cpu_table[i].equiv_cpu) - return equiv_cpu_table[i].installed_cpu; - i++; - } - return 0; -} - -/* - * a small, trivial cache of per-family ucode patches - */ -static struct ucode_patch *cache_find_patch(u16 equiv_cpu) -{ - struct ucode_patch *p; - - list_for_each_entry(p, &pcache, plist) - if (p->equiv_cpu == equiv_cpu) - return p; - return NULL; -} - -static void update_cache(struct ucode_patch *new_patch) -{ - struct ucode_patch *p; - - list_for_each_entry(p, &pcache, plist) { - if (p->equiv_cpu == new_patch->equiv_cpu) { - if (p->patch_id >= new_patch->patch_id) - /* we already have the latest patch */ - return; - - list_replace(&p->plist, &new_patch->plist); - kfree(p->data); - kfree(p); - return; - } - } - /* no patch found, add it */ - list_add_tail(&new_patch->plist, &pcache); -} - -static void free_cache(void) -{ - struct ucode_patch *p, *tmp; - - list_for_each_entry_safe(p, tmp, &pcache, plist) { - __list_del(p->plist.prev, p->plist.next); - kfree(p->data); - kfree(p); - } -} - -static struct ucode_patch *find_patch(unsigned int cpu) -{ - u16 equiv_id; - - equiv_id = find_equiv_id(cpu); - if (!equiv_id) - return NULL; - - return cache_find_patch(equiv_id); -} +/* page-sized ucode patch buffer */ +void *patch; static int collect_cpu_info_amd(int cpu, struct cpu_signature *csig) { struct cpuinfo_x86 *c = &cpu_data(cpu); - csig->sig = cpuid_eax(0x00000001); csig->rev = c->microcode; pr_info("CPU%d: patch_level=0x%08x\n", cpu, csig->rev); return 0; } -static unsigned int verify_patch_size(int cpu, u32 patch_size, +static unsigned int verify_ucode_size(int cpu, u32 patch_size, unsigned int size) { struct cpuinfo_x86 *c = &cpu_data(cpu); @@ -211,37 +118,94 @@ static unsigned int verify_patch_size(int cpu, u32 patch_size, return patch_size; } -static int apply_microcode_amd(int cpu) +static u16 find_equiv_id(void) { - struct cpuinfo_x86 *c = &cpu_data(cpu); - struct microcode_amd *mc_amd; - struct ucode_cpu_info *uci; - struct ucode_patch *p; - u32 rev, dummy; + unsigned int current_cpu_id, i = 0; - BUG_ON(raw_smp_processor_id() != cpu); + BUG_ON(equiv_cpu_table == NULL); - uci = ucode_cpu_info + cpu; + current_cpu_id = cpuid_eax(0x00000001); - p = find_patch(cpu); - if (!p) + while (equiv_cpu_table[i].installed_cpu != 0) { + if (current_cpu_id == equiv_cpu_table[i].installed_cpu) + return equiv_cpu_table[i].equiv_cpu; + + i++; + } + return 0; +} + +/* + * we signal a good patch is found by returning its size > 0 + */ +static int get_matching_microcode(int cpu, const u8 *ucode_ptr, + unsigned int leftover_size, int rev, + unsigned int *current_size) +{ + struct microcode_header_amd *mc_hdr; + unsigned int actual_size; + u16 equiv_cpu_id; + + /* size of the current patch we're staring at */ + *current_size = *(u32 *)(ucode_ptr + 4) + SECTION_HDR_SIZE; + + equiv_cpu_id = find_equiv_id(); + if (!equiv_cpu_id) return 0; - mc_amd = p->data; - uci->mc = p->data; + /* + * let's look at the patch header itself now + */ + mc_hdr = (struct microcode_header_amd *)(ucode_ptr + SECTION_HDR_SIZE); - rdmsr(MSR_AMD64_PATCH_LEVEL, rev, dummy); + if (mc_hdr->processor_rev_id != equiv_cpu_id) + return 0; - /* need to apply patch? */ - if (rev >= mc_amd->hdr.patch_id) { - c->microcode = rev; + /* ucode might be chipset specific -- currently we don't support this */ + if (mc_hdr->nb_dev_id || mc_hdr->sb_dev_id) { + pr_err("CPU%d: chipset specific code not yet supported\n", + cpu); return 0; } - wrmsrl(MSR_AMD64_PATCH_LOADER, (u64)(long)&mc_amd->hdr.data_code); + if (mc_hdr->patch_id <= rev) + return 0; + + /* + * now that the header looks sane, verify its size + */ + actual_size = verify_ucode_size(cpu, *current_size, leftover_size); + if (!actual_size) + return 0; + + /* clear the patch buffer */ + memset(patch, 0, PAGE_SIZE); + + /* all looks ok, get the binary patch */ + get_ucode_data(patch, ucode_ptr + SECTION_HDR_SIZE, actual_size); + + return actual_size; +} + +static int apply_microcode_amd(int cpu) +{ + u32 rev, dummy; + int cpu_num = raw_smp_processor_id(); + struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num; + struct microcode_amd *mc_amd = uci->mc; + struct cpuinfo_x86 *c = &cpu_data(cpu); + + /* We should bind the task to the CPU */ + BUG_ON(cpu_num != cpu); + + if (mc_amd == NULL) + return 0; - /* verify patch application was successful */ + wrmsrl(MSR_AMD64_PATCH_LOADER, (u64)(long)&mc_amd->hdr.data_code); + /* get patch id after patching */ rdmsr(MSR_AMD64_PATCH_LEVEL, rev, dummy); + + /* check current patch id and patch's id for match */ if (rev != mc_amd->hdr.patch_id) { pr_err("CPU%d: update failed for patch_level=0x%08x\n", cpu, mc_amd->hdr.patch_id); @@ -273,7 +237,7 @@ static int install_equiv_cpu_table(const u8 *buf) return -ENOMEM; } - memcpy(equiv_cpu_table, buf + CONTAINER_HDR_SZ, size); + get_ucode_data(equiv_cpu_table, buf + CONTAINER_HDR_SZ, size); /* add header length */ return size + CONTAINER_HDR_SZ; @@ -285,113 +249,61 @@ static void free_equiv_cpu_table(void) equiv_cpu_table = NULL; } -static void cleanup(void) -{ - free_equiv_cpu_table(); - free_cache(); -} - -/* - * We return the current size even if some of the checks failed so that - * we can skip over the next patch. If we return a negative value, we - * signal a grave error like a memory allocation has failed and the - * driver cannot continue functioning normally. In such cases, we tear - * down everything we've used up so far and exit. - */ -static int verify_and_add_patch(unsigned int cpu, u8 *fw, unsigned int leftover) -{ - struct cpuinfo_x86 *c = &cpu_data(cpu); - struct microcode_header_amd *mc_hdr; - struct ucode_patch *patch; - unsigned int patch_size, crnt_size, ret; - u32 proc_fam; - u16 proc_id; - - patch_size = *(u32 *)(fw + 4); - crnt_size = patch_size + SECTION_HDR_SIZE; - mc_hdr = (struct microcode_header_amd *)(fw + SECTION_HDR_SIZE); - proc_id = mc_hdr->processor_rev_id; - - proc_fam = find_cpu_family_by_equiv_cpu(proc_id); - if (!proc_fam) { - pr_err("No patch family for equiv ID: 0x%04x\n", proc_id); - return crnt_size; - } - - /* check if patch is for the current family */ - proc_fam = ((proc_fam >> 8) & 0xf) + ((proc_fam >> 20) & 0xff); - if (proc_fam != c->x86) - return crnt_size; - - if (mc_hdr->nb_dev_id || mc_hdr->sb_dev_id) { - pr_err("Patch-ID 0x%08x: chipset-specific code unsupported.\n", - mc_hdr->patch_id); - return crnt_size; - } - - ret = verify_patch_size(cpu, patch_size, leftover); - if (!ret) { - pr_err("Patch-ID 0x%08x: size mismatch.\n", mc_hdr->patch_id); - return crnt_size; - } - - patch = kzalloc(sizeof(*patch), GFP_KERNEL); - if (!patch) { - pr_err("Patch allocation failure.\n"); - return -EINVAL; - } - - patch->data = kzalloc(patch_size, GFP_KERNEL); - if (!patch->data) { - pr_err("Patch data allocation failure.\n"); - kfree(patch); - return -EINVAL; - } - - /* All looks ok, copy patch... */ - memcpy(patch->data, fw + SECTION_HDR_SIZE, patch_size); - INIT_LIST_HEAD(&patch->plist); - patch->patch_id = mc_hdr->patch_id; - patch->equiv_cpu = proc_id; - - /* ... and add to cache. */ - update_cache(patch); - - return crnt_size; -} - -static enum ucode_state load_microcode_amd(int cpu, const u8 *data, size_t size) +static enum ucode_state +generic_load_microcode(int cpu, const u8 *data, size_t size) { - enum ucode_state ret = UCODE_ERROR; - unsigned int leftover; - u8 *fw = (u8 *)data; - int crnt_size = 0; + struct ucode_cpu_info *uci = ucode_cpu_info + cpu; + struct microcode_header_amd *mc_hdr = NULL; + unsigned int mc_size, leftover, current_size = 0; int offset; + const u8 *ucode_ptr = data; + void *new_mc = NULL; + unsigned int new_rev = uci->cpu_sig.rev; + enum ucode_state state = UCODE_ERROR; - offset = install_equiv_cpu_table(data); + offset = install_equiv_cpu_table(ucode_ptr); if (offset < 0) { pr_err("failed to create equivalent cpu table\n"); - return ret; + goto out; } - fw += offset; + ucode_ptr += offset; leftover = size - offset; - if (*(u32 *)fw != UCODE_UCODE_TYPE) { + if (*(u32 *)ucode_ptr != UCODE_UCODE_TYPE) { pr_err("invalid type field in container file section header\n"); - free_equiv_cpu_table(); - return ret; + goto free_table; } while (leftover) { - crnt_size = verify_and_add_patch(cpu, fw, leftover); - if (crnt_size < 0) - return ret; + mc_size = get_matching_microcode(cpu, ucode_ptr, leftover, + new_rev, ¤t_size); + if (mc_size) { + mc_hdr = patch; + new_mc = patch; + new_rev = mc_hdr->patch_id; + goto out_ok; + } + + ucode_ptr += current_size; + leftover -= current_size; + } - fw += crnt_size; - leftover -= crnt_size; + if (!new_mc) { + state = UCODE_NFOUND; + goto free_table; } - return UCODE_OK; +out_ok: + uci->mc = new_mc; + state = UCODE_OK; + pr_debug("CPU%d update ucode (0x%08x -> 0x%08x)\n", + cpu, uci->cpu_sig.rev, new_rev); + +free_table: + free_equiv_cpu_table(); + +out: + return state; } /* @@ -402,7 +314,7 @@ static enum ucode_state load_microcode_amd(int cpu, const u8 *data, size_t size) * * This legacy file is always smaller than 2K in size. * - * Beginning with family 15h, they are in family-specific firmware files: + * Starting at family 15h they are in family specific firmware files: * * amd-ucode/microcode_amd_fam15h.bin * amd-ucode/microcode_amd_fam16h.bin @@ -410,17 +322,12 @@ static enum ucode_state load_microcode_amd(int cpu, const u8 *data, size_t size) * * These might be larger than 2K. */ -static enum ucode_state request_microcode_amd(int cpu, struct device *device, - bool refresh_fw) +static enum ucode_state request_microcode_amd(int cpu, struct device *device) { char fw_name[36] = "amd-ucode/microcode_amd.bin"; - struct cpuinfo_x86 *c = &cpu_data(cpu); - enum ucode_state ret = UCODE_NFOUND; const struct firmware *fw; - - /* reload ucode container only on the boot cpu */ - if (!refresh_fw || c->cpu_index != boot_cpu_data.cpu_index) - return UCODE_OK; + enum ucode_state ret = UCODE_NFOUND; + struct cpuinfo_x86 *c = &cpu_data(cpu); if (c->x86 >= 0x15) snprintf(fw_name, sizeof(fw_name), "amd-ucode/microcode_amd_fam%.2xh.bin", c->x86); @@ -436,17 +343,12 @@ static enum ucode_state request_microcode_amd(int cpu, struct device *device, goto fw_release; } - /* free old equiv table */ - free_equiv_cpu_table(); - - ret = load_microcode_amd(cpu, fw->data, fw->size); - if (ret != UCODE_OK) - cleanup(); + ret = generic_load_microcode(cpu, fw->data, fw->size); - fw_release: +fw_release: release_firmware(fw); - out: +out: return ret; } @@ -480,10 +382,14 @@ struct microcode_ops * __init init_amd_microcode(void) return NULL; } + patch = (void *)get_zeroed_page(GFP_KERNEL); + if (!patch) + return NULL; + return µcode_amd_ops; } void __exit exit_amd_microcode(void) { - cleanup(); + free_page((unsigned long)patch); } diff --git a/trunk/arch/x86/kernel/microcode_core.c b/trunk/arch/x86/kernel/microcode_core.c index 3a04b224d0c0..4873e62db6a1 100644 --- a/trunk/arch/x86/kernel/microcode_core.c +++ b/trunk/arch/x86/kernel/microcode_core.c @@ -225,9 +225,6 @@ static ssize_t microcode_write(struct file *file, const char __user *buf, if (do_microcode_update(buf, len) == 0) ret = (ssize_t)len; - if (ret > 0) - perf_check_microcode(); - mutex_unlock(µcode_mutex); put_online_cpus(); @@ -279,18 +276,19 @@ static struct platform_device *microcode_pdev; static int reload_for_cpu(int cpu) { struct ucode_cpu_info *uci = ucode_cpu_info + cpu; - enum ucode_state ustate; int err = 0; - if (!uci->valid) - return err; + if (uci->valid) { + enum ucode_state ustate; + + ustate = microcode_ops->request_microcode_fw(cpu, µcode_pdev->dev); + if (ustate == UCODE_OK) + apply_microcode_on_target(cpu); + else + if (ustate == UCODE_ERROR) + err = -EINVAL; + } - ustate = microcode_ops->request_microcode_fw(cpu, µcode_pdev->dev, true); - if (ustate == UCODE_OK) - apply_microcode_on_target(cpu); - else - if (ustate == UCODE_ERROR) - err = -EINVAL; return err; } @@ -372,15 +370,18 @@ static void microcode_fini_cpu(int cpu) static enum ucode_state microcode_resume_cpu(int cpu) { - pr_debug("CPU%d updated upon resume\n", cpu); + struct ucode_cpu_info *uci = ucode_cpu_info + cpu; - if (apply_microcode_on_target(cpu)) - return UCODE_ERROR; + if (!uci->mc) + return UCODE_NFOUND; + + pr_debug("CPU%d updated upon resume\n", cpu); + apply_microcode_on_target(cpu); return UCODE_OK; } -static enum ucode_state microcode_init_cpu(int cpu, bool refresh_fw) +static enum ucode_state microcode_init_cpu(int cpu) { enum ucode_state ustate; @@ -391,8 +392,7 @@ static enum ucode_state microcode_init_cpu(int cpu, bool refresh_fw) if (system_state != SYSTEM_RUNNING) return UCODE_NFOUND; - ustate = microcode_ops->request_microcode_fw(cpu, µcode_pdev->dev, - refresh_fw); + ustate = microcode_ops->request_microcode_fw(cpu, µcode_pdev->dev); if (ustate == UCODE_OK) { pr_debug("CPU%d updated upon init\n", cpu); @@ -405,11 +405,14 @@ static enum ucode_state microcode_init_cpu(int cpu, bool refresh_fw) static enum ucode_state microcode_update_cpu(int cpu) { struct ucode_cpu_info *uci = ucode_cpu_info + cpu; + enum ucode_state ustate; if (uci->valid) - return microcode_resume_cpu(cpu); + ustate = microcode_resume_cpu(cpu); + else + ustate = microcode_init_cpu(cpu); - return microcode_init_cpu(cpu, false); + return ustate; } static int mc_device_add(struct device *dev, struct subsys_interface *sif) @@ -425,7 +428,7 @@ static int mc_device_add(struct device *dev, struct subsys_interface *sif) if (err) return err; - if (microcode_init_cpu(cpu, true) == UCODE_ERROR) + if (microcode_init_cpu(cpu) == UCODE_ERROR) return -EINVAL; return err; @@ -474,41 +477,34 @@ mc_cpu_callback(struct notifier_block *nb, unsigned long action, void *hcpu) struct device *dev; dev = get_cpu_device(cpu); - - switch (action & ~CPU_TASKS_FROZEN) { + switch (action) { case CPU_ONLINE: + case CPU_ONLINE_FROZEN: microcode_update_cpu(cpu); - pr_debug("CPU%d added\n", cpu); - /* - * "break" is missing on purpose here because we want to fall - * through in order to create the sysfs group. - */ - case CPU_DOWN_FAILED: + case CPU_DOWN_FAILED_FROZEN: + pr_debug("CPU%d added\n", cpu); if (sysfs_create_group(&dev->kobj, &mc_attr_group)) pr_err("Failed to create group for CPU%d\n", cpu); break; - case CPU_DOWN_PREPARE: + case CPU_DOWN_PREPARE_FROZEN: /* Suspend is in progress, only remove the interface */ sysfs_remove_group(&dev->kobj, &mc_attr_group); pr_debug("CPU%d removed\n", cpu); break; /* - * case CPU_DEAD: - * * When a CPU goes offline, don't free up or invalidate the copy of * the microcode in kernel memory, so that we can reuse it when the * CPU comes back online without unnecessarily requesting the userspace * for it again. */ - } - - /* The CPU refused to come up during a system resume */ - if (action == CPU_UP_CANCELED_FROZEN) + case CPU_UP_CANCELED_FROZEN: + /* The CPU refused to come up during a system resume */ microcode_fini_cpu(cpu); - + break; + } return NOTIFY_OK; } diff --git a/trunk/arch/x86/kernel/microcode_intel.c b/trunk/arch/x86/kernel/microcode_intel.c index 3544aed39338..0327e2b3c408 100644 --- a/trunk/arch/x86/kernel/microcode_intel.c +++ b/trunk/arch/x86/kernel/microcode_intel.c @@ -405,8 +405,7 @@ static int get_ucode_fw(void *to, const void *from, size_t n) return 0; } -static enum ucode_state request_microcode_fw(int cpu, struct device *device, - bool refresh_fw) +static enum ucode_state request_microcode_fw(int cpu, struct device *device) { char name[30]; struct cpuinfo_x86 *c = &cpu_data(cpu); diff --git a/trunk/arch/x86/kernel/msr.c b/trunk/arch/x86/kernel/msr.c index a7c5661f8496..eb113693f043 100644 --- a/trunk/arch/x86/kernel/msr.c +++ b/trunk/arch/x86/kernel/msr.c @@ -257,14 +257,12 @@ static int __init msr_init(void) goto out_chrdev; } msr_class->devnode = msr_devnode; - get_online_cpus(); for_each_online_cpu(i) { err = msr_device_create(i); if (err != 0) goto out_class; } register_hotcpu_notifier(&msr_class_cpu_notifier); - put_online_cpus(); err = 0; goto out; @@ -273,7 +271,6 @@ static int __init msr_init(void) i = 0; for_each_online_cpu(i) msr_device_destroy(i); - put_online_cpus(); class_destroy(msr_class); out_chrdev: __unregister_chrdev(MSR_MAJOR, 0, NR_CPUS, "cpu/msr"); @@ -284,13 +281,11 @@ static int __init msr_init(void) static void __exit msr_exit(void) { int cpu = 0; - get_online_cpus(); for_each_online_cpu(cpu) msr_device_destroy(cpu); class_destroy(msr_class); __unregister_chrdev(MSR_MAJOR, 0, NR_CPUS, "cpu/msr"); unregister_hotcpu_notifier(&msr_class_cpu_notifier); - put_online_cpus(); } module_init(msr_init); diff --git a/trunk/arch/x86/kernel/perf_regs.c b/trunk/arch/x86/kernel/perf_regs.c deleted file mode 100644 index e309cc5c276e..000000000000 --- a/trunk/arch/x86/kernel/perf_regs.c +++ /dev/null @@ -1,105 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef CONFIG_X86_32 -#define PERF_REG_X86_MAX PERF_REG_X86_32_MAX -#else -#define PERF_REG_X86_MAX PERF_REG_X86_64_MAX -#endif - -#define PT_REGS_OFFSET(id, r) [id] = offsetof(struct pt_regs, r) - -static unsigned int pt_regs_offset[PERF_REG_X86_MAX] = { - PT_REGS_OFFSET(PERF_REG_X86_AX, ax), - PT_REGS_OFFSET(PERF_REG_X86_BX, bx), - PT_REGS_OFFSET(PERF_REG_X86_CX, cx), - PT_REGS_OFFSET(PERF_REG_X86_DX, dx), - PT_REGS_OFFSET(PERF_REG_X86_SI, si), - PT_REGS_OFFSET(PERF_REG_X86_DI, di), - PT_REGS_OFFSET(PERF_REG_X86_BP, bp), - PT_REGS_OFFSET(PERF_REG_X86_SP, sp), - PT_REGS_OFFSET(PERF_REG_X86_IP, ip), - PT_REGS_OFFSET(PERF_REG_X86_FLAGS, flags), - PT_REGS_OFFSET(PERF_REG_X86_CS, cs), - PT_REGS_OFFSET(PERF_REG_X86_SS, ss), -#ifdef CONFIG_X86_32 - PT_REGS_OFFSET(PERF_REG_X86_DS, ds), - PT_REGS_OFFSET(PERF_REG_X86_ES, es), - PT_REGS_OFFSET(PERF_REG_X86_FS, fs), - PT_REGS_OFFSET(PERF_REG_X86_GS, gs), -#else - /* - * The pt_regs struct does not store - * ds, es, fs, gs in 64 bit mode. - */ - (unsigned int) -1, - (unsigned int) -1, - (unsigned int) -1, - (unsigned int) -1, -#endif -#ifdef CONFIG_X86_64 - PT_REGS_OFFSET(PERF_REG_X86_R8, r8), - PT_REGS_OFFSET(PERF_REG_X86_R9, r9), - PT_REGS_OFFSET(PERF_REG_X86_R10, r10), - PT_REGS_OFFSET(PERF_REG_X86_R11, r11), - PT_REGS_OFFSET(PERF_REG_X86_R12, r12), - PT_REGS_OFFSET(PERF_REG_X86_R13, r13), - PT_REGS_OFFSET(PERF_REG_X86_R14, r14), - PT_REGS_OFFSET(PERF_REG_X86_R15, r15), -#endif -}; - -u64 perf_reg_value(struct pt_regs *regs, int idx) -{ - if (WARN_ON_ONCE(idx >= ARRAY_SIZE(pt_regs_offset))) - return 0; - - return regs_get_register(regs, pt_regs_offset[idx]); -} - -#define REG_RESERVED (~((1ULL << PERF_REG_X86_MAX) - 1ULL)) - -#ifdef CONFIG_X86_32 -int perf_reg_validate(u64 mask) -{ - if (!mask || mask & REG_RESERVED) - return -EINVAL; - - return 0; -} - -u64 perf_reg_abi(struct task_struct *task) -{ - return PERF_SAMPLE_REGS_ABI_32; -} -#else /* CONFIG_X86_64 */ -#define REG_NOSUPPORT ((1ULL << PERF_REG_X86_DS) | \ - (1ULL << PERF_REG_X86_ES) | \ - (1ULL << PERF_REG_X86_FS) | \ - (1ULL << PERF_REG_X86_GS)) - -int perf_reg_validate(u64 mask) -{ - if (!mask || mask & REG_RESERVED) - return -EINVAL; - - if (mask & REG_NOSUPPORT) - return -EINVAL; - - return 0; -} - -u64 perf_reg_abi(struct task_struct *task) -{ - if (test_tsk_thread_flag(task, TIF_IA32)) - return PERF_SAMPLE_REGS_ABI_32; - else - return PERF_SAMPLE_REGS_ABI_64; -} -#endif /* CONFIG_X86_32 */ diff --git a/trunk/arch/x86/kernel/probe_roms.c b/trunk/arch/x86/kernel/probe_roms.c index d5f15c3f7b25..0bc72e2069e3 100644 --- a/trunk/arch/x86/kernel/probe_roms.c +++ b/trunk/arch/x86/kernel/probe_roms.c @@ -150,7 +150,7 @@ static struct resource *find_oprom(struct pci_dev *pdev) return oprom; } -void __iomem *pci_map_biosrom(struct pci_dev *pdev) +void *pci_map_biosrom(struct pci_dev *pdev) { struct resource *oprom = find_oprom(pdev); diff --git a/trunk/arch/x86/kernel/process.c b/trunk/arch/x86/kernel/process.c index dc3567e083f9..ef6a8456f719 100644 --- a/trunk/arch/x86/kernel/process.c +++ b/trunk/arch/x86/kernel/process.c @@ -66,13 +66,15 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src) { int ret; + unlazy_fpu(src); + *dst = *src; if (fpu_allocated(&src->thread.fpu)) { memset(&dst->thread.fpu, 0, sizeof(dst->thread.fpu)); ret = fpu_alloc(&dst->thread.fpu); if (ret) return ret; - fpu_copy(dst, src); + fpu_copy(&dst->thread.fpu, &src->thread.fpu); } return 0; } @@ -95,6 +97,16 @@ void arch_task_cache_init(void) SLAB_PANIC | SLAB_NOTRACK, NULL); } +static inline void drop_fpu(struct task_struct *tsk) +{ + /* + * Forget coprocessor state.. + */ + tsk->fpu_counter = 0; + clear_fpu(tsk); + clear_used_math(); +} + /* * Free current thread data structures etc.. */ @@ -151,13 +163,7 @@ void flush_thread(void) flush_ptrace_hw_breakpoint(tsk); memset(tsk->thread.tls_array, 0, sizeof(tsk->thread.tls_array)); - drop_init_fpu(tsk); - /* - * Free the FPU state for non xsave platforms. They get reallocated - * lazily at the first use. - */ - if (!use_eager_fpu()) - free_thread_xstate(tsk); + drop_fpu(tsk); } static void hard_disable_TSC(void) diff --git a/trunk/arch/x86/kernel/process_32.c b/trunk/arch/x86/kernel/process_32.c index b9ff83c7135b..516fa186121b 100644 --- a/trunk/arch/x86/kernel/process_32.c +++ b/trunk/arch/x86/kernel/process_32.c @@ -190,6 +190,10 @@ start_thread(struct pt_regs *regs, unsigned long new_ip, unsigned long new_sp) regs->cs = __USER_CS; regs->ip = new_ip; regs->sp = new_sp; + /* + * Free the old FP and other extended state + */ + free_thread_xstate(current); } EXPORT_SYMBOL_GPL(start_thread); diff --git a/trunk/arch/x86/kernel/process_64.c b/trunk/arch/x86/kernel/process_64.c index 8a6d20ce1978..0a980c9d7cb8 100644 --- a/trunk/arch/x86/kernel/process_64.c +++ b/trunk/arch/x86/kernel/process_64.c @@ -232,6 +232,10 @@ start_thread_common(struct pt_regs *regs, unsigned long new_ip, regs->cs = _cs; regs->ss = _ss; regs->flags = X86_EFLAGS_IF; + /* + * Free the old FP and other extended state + */ + free_thread_xstate(current); } void diff --git a/trunk/arch/x86/kernel/ptrace.c b/trunk/arch/x86/kernel/ptrace.c index b00b33a18390..c4c6a5c2bf0f 100644 --- a/trunk/arch/x86/kernel/ptrace.c +++ b/trunk/arch/x86/kernel/ptrace.c @@ -21,7 +21,6 @@ #include #include #include -#include #include #include @@ -1333,6 +1332,9 @@ static const struct user_regset_view user_x86_64_view = { #define genregs32_get genregs_get #define genregs32_set genregs_set +#define user_i387_ia32_struct user_i387_struct +#define user32_fxsr_struct user_fxsr_struct + #endif /* CONFIG_X86_64 */ #if defined CONFIG_X86_32 || defined CONFIG_IA32_EMULATION @@ -1461,8 +1463,6 @@ long syscall_trace_enter(struct pt_regs *regs) { long ret = 0; - rcu_user_exit(); - /* * If we stepped into a sysenter/syscall insn, it trapped in * kernel mode; do_debug() cleared TF and set TIF_SINGLESTEP. @@ -1526,6 +1526,4 @@ void syscall_trace_leave(struct pt_regs *regs) !test_thread_flag(TIF_SYSCALL_EMU); if (step || test_thread_flag(TIF_SYSCALL_TRACE)) tracehook_report_syscall_exit(regs, step); - - rcu_user_enter(); } diff --git a/trunk/arch/x86/kernel/setup.c b/trunk/arch/x86/kernel/setup.c index 4f165479c453..f4b9b80e1b95 100644 --- a/trunk/arch/x86/kernel/setup.c +++ b/trunk/arch/x86/kernel/setup.c @@ -961,7 +961,9 @@ void __init setup_arch(char **cmdline_p) kvmclock_init(); #endif - x86_init.paging.pagetable_init(); + x86_init.paging.pagetable_setup_start(swapper_pg_dir); + paging_init(); + x86_init.paging.pagetable_setup_done(swapper_pg_dir); if (boot_cpu_data.cpuid_level >= 0) { /* A CPU has %cr4 if and only if it has CPUID */ diff --git a/trunk/arch/x86/kernel/signal.c b/trunk/arch/x86/kernel/signal.c index 3160c26db5e7..b280908a376e 100644 --- a/trunk/arch/x86/kernel/signal.c +++ b/trunk/arch/x86/kernel/signal.c @@ -114,7 +114,7 @@ int restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, regs->orig_ax = -1; /* disable syscall checks */ get_user_ex(buf, &sc->fpstate); - err |= restore_xstate_sig(buf, config_enabled(CONFIG_X86_32)); + err |= restore_i387_xstate(buf); get_user_ex(*pax, &sc->ax); } get_user_catch(err); @@ -206,32 +206,35 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size, void __user **fpstate) { /* Default to using normal stack */ - unsigned long math_size = 0; unsigned long sp = regs->sp; - unsigned long buf_fx = 0; int onsigstack = on_sig_stack(sp); +#ifdef CONFIG_X86_64 /* redzone */ - if (config_enabled(CONFIG_X86_64)) - sp -= 128; + sp -= 128; +#endif /* CONFIG_X86_64 */ if (!onsigstack) { /* This is the X/Open sanctioned signal stack switching. */ if (ka->sa.sa_flags & SA_ONSTACK) { if (current->sas_ss_size) sp = current->sas_ss_sp + current->sas_ss_size; - } else if (config_enabled(CONFIG_X86_32) && - (regs->ss & 0xffff) != __USER_DS && - !(ka->sa.sa_flags & SA_RESTORER) && - ka->sa.sa_restorer) { - /* This is the legacy signal stack switching. */ + } else { +#ifdef CONFIG_X86_32 + /* This is the legacy signal stack switching. */ + if ((regs->ss & 0xffff) != __USER_DS && + !(ka->sa.sa_flags & SA_RESTORER) && + ka->sa.sa_restorer) sp = (unsigned long) ka->sa.sa_restorer; +#endif /* CONFIG_X86_32 */ } } if (used_math()) { - sp = alloc_mathframe(sp, config_enabled(CONFIG_X86_32), - &buf_fx, &math_size); + sp -= sig_xstate_size; +#ifdef CONFIG_X86_64 + sp = round_down(sp, 64); +#endif /* CONFIG_X86_64 */ *fpstate = (void __user *)sp; } @@ -244,9 +247,8 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size, if (onsigstack && !likely(on_sig_stack(sp))) return (void __user *)-1L; - /* save i387 and extended state */ - if (used_math() && - save_xstate_sig(*fpstate, (void __user *)buf_fx, math_size) < 0) + /* save i387 state */ + if (used_math() && save_i387_xstate(*fpstate) < 0) return (void __user *)-1L; return (void __user *)sp; @@ -472,74 +474,6 @@ static int __setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, } #endif /* CONFIG_X86_32 */ -static int x32_setup_rt_frame(int sig, struct k_sigaction *ka, - siginfo_t *info, compat_sigset_t *set, - struct pt_regs *regs) -{ -#ifdef CONFIG_X86_X32_ABI - struct rt_sigframe_x32 __user *frame; - void __user *restorer; - int err = 0; - void __user *fpstate = NULL; - - frame = get_sigframe(ka, regs, sizeof(*frame), &fpstate); - - if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) - return -EFAULT; - - if (ka->sa.sa_flags & SA_SIGINFO) { - if (copy_siginfo_to_user32(&frame->info, info)) - return -EFAULT; - } - - put_user_try { - /* Create the ucontext. */ - if (cpu_has_xsave) - put_user_ex(UC_FP_XSTATE, &frame->uc.uc_flags); - else - put_user_ex(0, &frame->uc.uc_flags); - put_user_ex(0, &frame->uc.uc_link); - put_user_ex(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp); - put_user_ex(sas_ss_flags(regs->sp), - &frame->uc.uc_stack.ss_flags); - put_user_ex(current->sas_ss_size, &frame->uc.uc_stack.ss_size); - put_user_ex(0, &frame->uc.uc__pad0); - err |= setup_sigcontext(&frame->uc.uc_mcontext, fpstate, - regs, set->sig[0]); - err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); - - if (ka->sa.sa_flags & SA_RESTORER) { - restorer = ka->sa.sa_restorer; - } else { - /* could use a vstub here */ - restorer = NULL; - err |= -EFAULT; - } - put_user_ex(restorer, &frame->pretcode); - } put_user_catch(err); - - if (err) - return -EFAULT; - - /* Set up registers for signal handler */ - regs->sp = (unsigned long) frame; - regs->ip = (unsigned long) ka->sa.sa_handler; - - /* We use the x32 calling convention here... */ - regs->di = sig; - regs->si = (unsigned long) &frame->info; - regs->dx = (unsigned long) &frame->uc; - - loadsegment(ds, __USER_DS); - loadsegment(es, __USER_DS); - - regs->cs = __USER_CS; - regs->ss = __USER_DS; -#endif /* CONFIG_X86_X32_ABI */ - - return 0; -} - #ifdef CONFIG_X86_32 /* * Atomically swap in the new signal mask, and wait for a signal. @@ -678,22 +612,55 @@ static int signr_convert(int sig) return sig; } +#ifdef CONFIG_X86_32 + +#define is_ia32 1 +#define ia32_setup_frame __setup_frame +#define ia32_setup_rt_frame __setup_rt_frame + +#else /* !CONFIG_X86_32 */ + +#ifdef CONFIG_IA32_EMULATION +#define is_ia32 test_thread_flag(TIF_IA32) +#else /* !CONFIG_IA32_EMULATION */ +#define is_ia32 0 +#endif /* CONFIG_IA32_EMULATION */ + +#ifdef CONFIG_X86_X32_ABI +#define is_x32 test_thread_flag(TIF_X32) + +static int x32_setup_rt_frame(int sig, struct k_sigaction *ka, + siginfo_t *info, compat_sigset_t *set, + struct pt_regs *regs); +#else /* !CONFIG_X86_X32_ABI */ +#define is_x32 0 +#endif /* CONFIG_X86_X32_ABI */ + +int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, + sigset_t *set, struct pt_regs *regs); +int ia32_setup_frame(int sig, struct k_sigaction *ka, + sigset_t *set, struct pt_regs *regs); + +#endif /* CONFIG_X86_32 */ + static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, struct pt_regs *regs) { int usig = signr_convert(sig); sigset_t *set = sigmask_to_save(); - compat_sigset_t *cset = (compat_sigset_t *) set; /* Set up the stack frame */ - if (is_ia32_frame()) { + if (is_ia32) { if (ka->sa.sa_flags & SA_SIGINFO) - return ia32_setup_rt_frame(usig, ka, info, cset, regs); + return ia32_setup_rt_frame(usig, ka, info, set, regs); else - return ia32_setup_frame(usig, ka, cset, regs); - } else if (is_x32_frame()) { - return x32_setup_rt_frame(usig, ka, info, cset, regs); + return ia32_setup_frame(usig, ka, set, regs); +#ifdef CONFIG_X86_X32_ABI + } else if (is_x32) { + return x32_setup_rt_frame(usig, ka, info, + (compat_sigset_t *)set, regs); +#endif } else { return __setup_rt_frame(sig, ka, info, set, regs); } @@ -812,8 +779,6 @@ static void do_signal(struct pt_regs *regs) void do_notify_resume(struct pt_regs *regs, void *unused, __u32 thread_info_flags) { - rcu_user_exit(); - #ifdef CONFIG_X86_MCE /* notify userspace of pending MCEs */ if (thread_info_flags & _TIF_MCE_NOTIFY) @@ -839,8 +804,6 @@ do_notify_resume(struct pt_regs *regs, void *unused, __u32 thread_info_flags) #ifdef CONFIG_X86_32 clear_thread_flag(TIF_IRET); #endif /* CONFIG_X86_32 */ - - rcu_user_enter(); } void signal_fault(struct pt_regs *regs, void __user *frame, char *where) @@ -861,6 +824,72 @@ void signal_fault(struct pt_regs *regs, void __user *frame, char *where) } #ifdef CONFIG_X86_X32_ABI +static int x32_setup_rt_frame(int sig, struct k_sigaction *ka, + siginfo_t *info, compat_sigset_t *set, + struct pt_regs *regs) +{ + struct rt_sigframe_x32 __user *frame; + void __user *restorer; + int err = 0; + void __user *fpstate = NULL; + + frame = get_sigframe(ka, regs, sizeof(*frame), &fpstate); + + if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) + return -EFAULT; + + if (ka->sa.sa_flags & SA_SIGINFO) { + if (copy_siginfo_to_user32(&frame->info, info)) + return -EFAULT; + } + + put_user_try { + /* Create the ucontext. */ + if (cpu_has_xsave) + put_user_ex(UC_FP_XSTATE, &frame->uc.uc_flags); + else + put_user_ex(0, &frame->uc.uc_flags); + put_user_ex(0, &frame->uc.uc_link); + put_user_ex(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp); + put_user_ex(sas_ss_flags(regs->sp), + &frame->uc.uc_stack.ss_flags); + put_user_ex(current->sas_ss_size, &frame->uc.uc_stack.ss_size); + put_user_ex(0, &frame->uc.uc__pad0); + err |= setup_sigcontext(&frame->uc.uc_mcontext, fpstate, + regs, set->sig[0]); + err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); + + if (ka->sa.sa_flags & SA_RESTORER) { + restorer = ka->sa.sa_restorer; + } else { + /* could use a vstub here */ + restorer = NULL; + err |= -EFAULT; + } + put_user_ex(restorer, &frame->pretcode); + } put_user_catch(err); + + if (err) + return -EFAULT; + + /* Set up registers for signal handler */ + regs->sp = (unsigned long) frame; + regs->ip = (unsigned long) ka->sa.sa_handler; + + /* We use the x32 calling convention here... */ + regs->di = sig; + regs->si = (unsigned long) &frame->info; + regs->dx = (unsigned long) &frame->uc; + + loadsegment(ds, __USER_DS); + loadsegment(es, __USER_DS); + + regs->cs = __USER_CS; + regs->ss = __USER_DS; + + return 0; +} + asmlinkage long sys32_x32_rt_sigreturn(struct pt_regs *regs) { struct rt_sigframe_x32 __user *frame; diff --git a/trunk/arch/x86/kernel/smpboot.c b/trunk/arch/x86/kernel/smpboot.c index c80a33bc528b..7c5a8c314c02 100644 --- a/trunk/arch/x86/kernel/smpboot.c +++ b/trunk/arch/x86/kernel/smpboot.c @@ -665,8 +665,7 @@ static int __cpuinit do_boot_cpu(int apicid, int cpu, struct task_struct *idle) unsigned long boot_error = 0; int timeout; - /* Just in case we booted with a single CPU. */ - alternatives_enable_smp(); + alternatives_smp_switch(1); idle->thread.sp = (unsigned long) (((struct pt_regs *) (THREAD_SIZE + task_stack_page(idle))) - 1); @@ -1054,6 +1053,20 @@ void __init native_smp_prepare_cpus(unsigned int max_cpus) preempt_enable(); } +void arch_disable_nonboot_cpus_begin(void) +{ + /* + * Avoid the smp alternatives switch during the disable_nonboot_cpus(). + * In the suspend path, we will be back in the SMP mode shortly anyways. + */ + skip_smp_alternatives = true; +} + +void arch_disable_nonboot_cpus_end(void) +{ + skip_smp_alternatives = false; +} + void arch_enable_nonboot_cpus_begin(void) { set_mtrr_aps_delayed_init(); @@ -1243,6 +1256,9 @@ void native_cpu_die(unsigned int cpu) if (per_cpu(cpu_state, cpu) == CPU_DEAD) { if (system_state == SYSTEM_RUNNING) pr_info("CPU %u is now offline\n", cpu); + + if (1 == num_online_cpus()) + alternatives_smp_switch(0); return; } msleep(100); diff --git a/trunk/arch/x86/kernel/step.c b/trunk/arch/x86/kernel/step.c index cd3b2438a980..c346d1161488 100644 --- a/trunk/arch/x86/kernel/step.c +++ b/trunk/arch/x86/kernel/step.c @@ -157,33 +157,6 @@ static int enable_single_step(struct task_struct *child) return 1; } -void set_task_blockstep(struct task_struct *task, bool on) -{ - unsigned long debugctl; - - /* - * Ensure irq/preemption can't change debugctl in between. - * Note also that both TIF_BLOCKSTEP and debugctl should - * be changed atomically wrt preemption. - * FIXME: this means that set/clear TIF_BLOCKSTEP is simply - * wrong if task != current, SIGKILL can wakeup the stopped - * tracee and set/clear can play with the running task, this - * can confuse the next __switch_to_xtra(). - */ - local_irq_disable(); - debugctl = get_debugctlmsr(); - if (on) { - debugctl |= DEBUGCTLMSR_BTF; - set_tsk_thread_flag(task, TIF_BLOCKSTEP); - } else { - debugctl &= ~DEBUGCTLMSR_BTF; - clear_tsk_thread_flag(task, TIF_BLOCKSTEP); - } - if (task == current) - update_debugctlmsr(debugctl); - local_irq_enable(); -} - /* * Enable single or block step. */ @@ -196,10 +169,19 @@ static void enable_step(struct task_struct *child, bool block) * So no one should try to use debugger block stepping in a program * that uses user-mode single stepping itself. */ - if (enable_single_step(child) && block) - set_task_blockstep(child, true); - else if (test_tsk_thread_flag(child, TIF_BLOCKSTEP)) - set_task_blockstep(child, false); + if (enable_single_step(child) && block) { + unsigned long debugctl = get_debugctlmsr(); + + debugctl |= DEBUGCTLMSR_BTF; + update_debugctlmsr(debugctl); + set_tsk_thread_flag(child, TIF_BLOCKSTEP); + } else if (test_tsk_thread_flag(child, TIF_BLOCKSTEP)) { + unsigned long debugctl = get_debugctlmsr(); + + debugctl &= ~DEBUGCTLMSR_BTF; + update_debugctlmsr(debugctl); + clear_tsk_thread_flag(child, TIF_BLOCKSTEP); + } } void user_enable_single_step(struct task_struct *child) @@ -217,8 +199,13 @@ void user_disable_single_step(struct task_struct *child) /* * Make sure block stepping (BTF) is disabled. */ - if (test_tsk_thread_flag(child, TIF_BLOCKSTEP)) - set_task_blockstep(child, false); + if (test_tsk_thread_flag(child, TIF_BLOCKSTEP)) { + unsigned long debugctl = get_debugctlmsr(); + + debugctl &= ~DEBUGCTLMSR_BTF; + update_debugctlmsr(debugctl); + clear_tsk_thread_flag(child, TIF_BLOCKSTEP); + } /* Always clear TIF_SINGLESTEP... */ clear_tsk_thread_flag(child, TIF_SINGLESTEP); diff --git a/trunk/arch/x86/kernel/traps.c b/trunk/arch/x86/kernel/traps.c index 8276dc6794cc..b481341c9369 100644 --- a/trunk/arch/x86/kernel/traps.c +++ b/trunk/arch/x86/kernel/traps.c @@ -55,7 +55,6 @@ #include #include #include -#include #include @@ -108,45 +107,30 @@ static inline void preempt_conditional_cli(struct pt_regs *regs) dec_preempt_count(); } -static int __kprobes -do_trap_no_signal(struct task_struct *tsk, int trapnr, char *str, - struct pt_regs *regs, long error_code) +static void __kprobes +do_trap(int trapnr, int signr, char *str, struct pt_regs *regs, + long error_code, siginfo_t *info) { + struct task_struct *tsk = current; + #ifdef CONFIG_X86_32 if (regs->flags & X86_VM_MASK) { /* - * Traps 0, 1, 3, 4, and 5 should be forwarded to vm86. + * traps 0, 1, 3, 4, and 5 should be forwarded to vm86. * On nmi (interrupt 2), do_trap should not be called. */ - if (trapnr < X86_TRAP_UD) { - if (!handle_vm86_trap((struct kernel_vm86_regs *) regs, - error_code, trapnr)) - return 0; - } - return -1; + if (trapnr < X86_TRAP_UD) + goto vm86_trap; + goto trap_signal; } #endif - if (!user_mode(regs)) { - if (!fixup_exception(regs)) { - tsk->thread.error_code = error_code; - tsk->thread.trap_nr = trapnr; - die(str, regs, error_code); - } - return 0; - } - - return -1; -} - -static void __kprobes -do_trap(int trapnr, int signr, char *str, struct pt_regs *regs, - long error_code, siginfo_t *info) -{ - struct task_struct *tsk = current; + if (!user_mode(regs)) + goto kernel_trap; - if (!do_trap_no_signal(tsk, trapnr, str, regs, error_code)) - return; +#ifdef CONFIG_X86_32 +trap_signal: +#endif /* * We want error_code and trap_nr set for userspace faults and * kernelspace faults which result in die(), but not @@ -174,20 +158,33 @@ do_trap(int trapnr, int signr, char *str, struct pt_regs *regs, force_sig_info(signr, info, tsk); else force_sig(signr, tsk); + return; + +kernel_trap: + if (!fixup_exception(regs)) { + tsk->thread.error_code = error_code; + tsk->thread.trap_nr = trapnr; + die(str, regs, error_code); + } + return; + +#ifdef CONFIG_X86_32 +vm86_trap: + if (handle_vm86_trap((struct kernel_vm86_regs *) regs, + error_code, trapnr)) + goto trap_signal; + return; +#endif } #define DO_ERROR(trapnr, signr, str, name) \ dotraplinkage void do_##name(struct pt_regs *regs, long error_code) \ { \ - exception_enter(regs); \ - if (notify_die(DIE_TRAP, str, regs, error_code, \ - trapnr, signr) == NOTIFY_STOP) { \ - exception_exit(regs); \ + if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) \ + == NOTIFY_STOP) \ return; \ - } \ conditional_sti(regs); \ do_trap(trapnr, signr, str, regs, error_code, NULL); \ - exception_exit(regs); \ } #define DO_ERROR_INFO(trapnr, signr, str, name, sicode, siaddr) \ @@ -198,15 +195,11 @@ dotraplinkage void do_##name(struct pt_regs *regs, long error_code) \ info.si_errno = 0; \ info.si_code = sicode; \ info.si_addr = (void __user *)siaddr; \ - exception_enter(regs); \ - if (notify_die(DIE_TRAP, str, regs, error_code, \ - trapnr, signr) == NOTIFY_STOP) { \ - exception_exit(regs); \ + if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) \ + == NOTIFY_STOP) \ return; \ - } \ conditional_sti(regs); \ do_trap(trapnr, signr, str, regs, error_code, &info); \ - exception_exit(regs); \ } DO_ERROR_INFO(X86_TRAP_DE, SIGFPE, "divide error", divide_error, FPE_INTDIV, @@ -229,14 +222,12 @@ DO_ERROR_INFO(X86_TRAP_AC, SIGBUS, "alignment check", alignment_check, /* Runs on IST stack */ dotraplinkage void do_stack_segment(struct pt_regs *regs, long error_code) { - exception_enter(regs); if (notify_die(DIE_TRAP, "stack segment", regs, error_code, - X86_TRAP_SS, SIGBUS) != NOTIFY_STOP) { - preempt_conditional_sti(regs); - do_trap(X86_TRAP_SS, SIGBUS, "stack segment", regs, error_code, NULL); - preempt_conditional_cli(regs); - } - exception_exit(regs); + X86_TRAP_SS, SIGBUS) == NOTIFY_STOP) + return; + preempt_conditional_sti(regs); + do_trap(X86_TRAP_SS, SIGBUS, "stack segment", regs, error_code, NULL); + preempt_conditional_cli(regs); } dotraplinkage void do_double_fault(struct pt_regs *regs, long error_code) @@ -244,7 +235,6 @@ dotraplinkage void do_double_fault(struct pt_regs *regs, long error_code) static const char str[] = "double fault"; struct task_struct *tsk = current; - exception_enter(regs); /* Return not checked because double check cannot be ignored */ notify_die(DIE_TRAP, str, regs, error_code, X86_TRAP_DF, SIGSEGV); @@ -265,29 +255,16 @@ do_general_protection(struct pt_regs *regs, long error_code) { struct task_struct *tsk; - exception_enter(regs); conditional_sti(regs); #ifdef CONFIG_X86_32 - if (regs->flags & X86_VM_MASK) { - local_irq_enable(); - handle_vm86_fault((struct kernel_vm86_regs *) regs, error_code); - goto exit; - } + if (regs->flags & X86_VM_MASK) + goto gp_in_vm86; #endif tsk = current; - if (!user_mode(regs)) { - if (fixup_exception(regs)) - goto exit; - - tsk->thread.error_code = error_code; - tsk->thread.trap_nr = X86_TRAP_GP; - if (notify_die(DIE_GPF, "general protection fault", regs, error_code, - X86_TRAP_GP, SIGSEGV) != NOTIFY_STOP) - die("general protection fault", regs, error_code); - goto exit; - } + if (!user_mode(regs)) + goto gp_in_kernel; tsk->thread.error_code = error_code; tsk->thread.trap_nr = X86_TRAP_GP; @@ -302,8 +279,25 @@ do_general_protection(struct pt_regs *regs, long error_code) } force_sig(SIGSEGV, tsk); -exit: - exception_exit(regs); + return; + +#ifdef CONFIG_X86_32 +gp_in_vm86: + local_irq_enable(); + handle_vm86_fault((struct kernel_vm86_regs *) regs, error_code); + return; +#endif + +gp_in_kernel: + if (fixup_exception(regs)) + return; + + tsk->thread.error_code = error_code; + tsk->thread.trap_nr = X86_TRAP_GP; + if (notify_die(DIE_GPF, "general protection fault", regs, error_code, + X86_TRAP_GP, SIGSEGV) == NOTIFY_STOP) + return; + die("general protection fault", regs, error_code); } /* May run on IST stack. */ @@ -318,16 +312,15 @@ dotraplinkage void __kprobes notrace do_int3(struct pt_regs *regs, long error_co ftrace_int3_handler(regs)) return; #endif - exception_enter(regs); #ifdef CONFIG_KGDB_LOW_LEVEL_TRAP if (kgdb_ll_trap(DIE_INT3, "int3", regs, error_code, X86_TRAP_BP, SIGTRAP) == NOTIFY_STOP) - goto exit; + return; #endif /* CONFIG_KGDB_LOW_LEVEL_TRAP */ if (notify_die(DIE_INT3, "int3", regs, error_code, X86_TRAP_BP, SIGTRAP) == NOTIFY_STOP) - goto exit; + return; /* * Let others (NMI) know that the debug stack is in use @@ -338,8 +331,6 @@ dotraplinkage void __kprobes notrace do_int3(struct pt_regs *regs, long error_co do_trap(X86_TRAP_BP, SIGTRAP, "int3", regs, error_code, NULL); preempt_conditional_cli(regs); debug_stack_usage_dec(); -exit: - exception_exit(regs); } #ifdef CONFIG_X86_64 @@ -400,8 +391,6 @@ dotraplinkage void __kprobes do_debug(struct pt_regs *regs, long error_code) unsigned long dr6; int si_code; - exception_enter(regs); - get_debugreg(dr6, 6); /* Filter out all the reserved bits which are preset to 1 */ @@ -417,7 +406,7 @@ dotraplinkage void __kprobes do_debug(struct pt_regs *regs, long error_code) /* Catch kmemcheck conditions first of all! */ if ((dr6 & DR_STEP) && kmemcheck_trap(regs)) - goto exit; + return; /* DR6 may or may not be cleared by the CPU */ set_debugreg(0, 6); @@ -432,7 +421,7 @@ dotraplinkage void __kprobes do_debug(struct pt_regs *regs, long error_code) if (notify_die(DIE_DEBUG, "debug", regs, PTR_ERR(&dr6), error_code, SIGTRAP) == NOTIFY_STOP) - goto exit; + return; /* * Let others (NMI) know that the debug stack is in use @@ -448,7 +437,7 @@ dotraplinkage void __kprobes do_debug(struct pt_regs *regs, long error_code) X86_TRAP_DB); preempt_conditional_cli(regs); debug_stack_usage_dec(); - goto exit; + return; } /* @@ -469,8 +458,7 @@ dotraplinkage void __kprobes do_debug(struct pt_regs *regs, long error_code) preempt_conditional_cli(regs); debug_stack_usage_dec(); -exit: - exception_exit(regs); + return; } /* @@ -567,17 +555,14 @@ dotraplinkage void do_coprocessor_error(struct pt_regs *regs, long error_code) #ifdef CONFIG_X86_32 ignore_fpu_irq = 1; #endif - exception_enter(regs); + math_error(regs, error_code, X86_TRAP_MF); - exception_exit(regs); } dotraplinkage void do_simd_coprocessor_error(struct pt_regs *regs, long error_code) { - exception_enter(regs); math_error(regs, error_code, X86_TRAP_XF); - exception_exit(regs); } dotraplinkage void @@ -628,12 +613,11 @@ void math_state_restore(void) } __thread_fpu_begin(tsk); - /* * Paranoid restore. send a SIGSEGV if we fail to restore the state. */ if (unlikely(restore_fpu_checking(tsk))) { - drop_init_fpu(tsk); + __thread_fpu_end(tsk); force_sig(SIGSEGV, tsk); return; } @@ -645,9 +629,6 @@ EXPORT_SYMBOL_GPL(math_state_restore); dotraplinkage void __kprobes do_device_not_available(struct pt_regs *regs, long error_code) { - exception_enter(regs); - BUG_ON(use_eager_fpu()); - #ifdef CONFIG_MATH_EMULATION if (read_cr0() & X86_CR0_EM) { struct math_emu_info info = { }; @@ -656,7 +637,6 @@ do_device_not_available(struct pt_regs *regs, long error_code) info.regs = regs; math_emulate(&info); - exception_exit(regs); return; } #endif @@ -664,15 +644,12 @@ do_device_not_available(struct pt_regs *regs, long error_code) #ifdef CONFIG_X86_32 conditional_sti(regs); #endif - exception_exit(regs); } #ifdef CONFIG_X86_32 dotraplinkage void do_iret_error(struct pt_regs *regs, long error_code) { siginfo_t info; - - exception_enter(regs); local_irq_enable(); info.si_signo = SIGILL; @@ -680,11 +657,10 @@ dotraplinkage void do_iret_error(struct pt_regs *regs, long error_code) info.si_code = ILL_BADSTK; info.si_addr = NULL; if (notify_die(DIE_TRAP, "iret exception", regs, error_code, - X86_TRAP_IRET, SIGILL) != NOTIFY_STOP) { - do_trap(X86_TRAP_IRET, SIGILL, "iret exception", regs, error_code, - &info); - } - exception_exit(regs); + X86_TRAP_IRET, SIGILL) == NOTIFY_STOP) + return; + do_trap(X86_TRAP_IRET, SIGILL, "iret exception", regs, error_code, + &info); } #endif diff --git a/trunk/arch/x86/kernel/uprobes.c b/trunk/arch/x86/kernel/uprobes.c index 9538f00827a9..36fd42091fa7 100644 --- a/trunk/arch/x86/kernel/uprobes.c +++ b/trunk/arch/x86/kernel/uprobes.c @@ -41,9 +41,6 @@ /* Adjust the return address of a call insn */ #define UPROBE_FIX_CALL 0x2 -/* Instruction will modify TF, don't change it */ -#define UPROBE_FIX_SETF 0x4 - #define UPROBE_FIX_RIP_AX 0x8000 #define UPROBE_FIX_RIP_CX 0x4000 @@ -242,10 +239,6 @@ static void prepare_fixups(struct arch_uprobe *auprobe, struct insn *insn) insn_get_opcode(insn); /* should be a nop */ switch (OPCODE1(insn)) { - case 0x9d: - /* popf */ - auprobe->fixups |= UPROBE_FIX_SETF; - break; case 0xc3: /* ret/lret */ case 0xcb: case 0xc2: @@ -653,7 +646,7 @@ void arch_uprobe_abort_xol(struct arch_uprobe *auprobe, struct pt_regs *regs) * Skip these instructions as per the currently known x86 ISA. * 0x66* { 0x90 | 0x0f 0x1f | 0x0f 0x19 | 0x87 0xc0 } */ -static bool __skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs) +bool arch_uprobe_skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs) { int i; @@ -680,46 +673,3 @@ static bool __skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs) } return false; } - -bool arch_uprobe_skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs) -{ - bool ret = __skip_sstep(auprobe, regs); - if (ret && (regs->flags & X86_EFLAGS_TF)) - send_sig(SIGTRAP, current, 0); - return ret; -} - -void arch_uprobe_enable_step(struct arch_uprobe *auprobe) -{ - struct task_struct *task = current; - struct arch_uprobe_task *autask = &task->utask->autask; - struct pt_regs *regs = task_pt_regs(task); - - autask->saved_tf = !!(regs->flags & X86_EFLAGS_TF); - - regs->flags |= X86_EFLAGS_TF; - if (test_tsk_thread_flag(task, TIF_BLOCKSTEP)) - set_task_blockstep(task, false); -} - -void arch_uprobe_disable_step(struct arch_uprobe *auprobe) -{ - struct task_struct *task = current; - struct arch_uprobe_task *autask = &task->utask->autask; - bool trapped = (task->utask->state == UTASK_SSTEP_TRAPPED); - struct pt_regs *regs = task_pt_regs(task); - /* - * The state of TIF_BLOCKSTEP was not saved so we can get an extra - * SIGTRAP if we do not clear TF. We need to examine the opcode to - * make it right. - */ - if (unlikely(trapped)) { - if (!autask->saved_tf) - regs->flags &= ~X86_EFLAGS_TF; - } else { - if (autask->saved_tf) - send_sig(SIGTRAP, task, 0); - else if (!(auprobe->fixups & UPROBE_FIX_SETF)) - regs->flags &= ~X86_EFLAGS_TF; - } -} diff --git a/trunk/arch/x86/kernel/x8664_ksyms_64.c b/trunk/arch/x86/kernel/x8664_ksyms_64.c index 1330dd102950..6020f6f5927c 100644 --- a/trunk/arch/x86/kernel/x8664_ksyms_64.c +++ b/trunk/arch/x86/kernel/x8664_ksyms_64.c @@ -13,13 +13,9 @@ #include #ifdef CONFIG_FUNCTION_TRACER -/* mcount and __fentry__ are defined in assembly */ -#ifdef CC_USING_FENTRY -EXPORT_SYMBOL(__fentry__); -#else +/* mcount is defined in assembly */ EXPORT_SYMBOL(mcount); #endif -#endif EXPORT_SYMBOL(__get_user_1); EXPORT_SYMBOL(__get_user_2); diff --git a/trunk/arch/x86/kernel/x86_init.c b/trunk/arch/x86/kernel/x86_init.c index 7a3d075a814a..9f3167e891ef 100644 --- a/trunk/arch/x86/kernel/x86_init.c +++ b/trunk/arch/x86/kernel/x86_init.c @@ -26,6 +26,7 @@ void __cpuinit x86_init_noop(void) { } void __init x86_init_uint_noop(unsigned int unused) { } +void __init x86_init_pgd_noop(pgd_t *unused) { } int __init iommu_init_noop(void) { return 0; } void iommu_shutdown_noop(void) { } @@ -67,7 +68,8 @@ struct x86_init_ops x86_init __initdata = { }, .paging = { - .pagetable_init = native_pagetable_init, + .pagetable_setup_start = native_pagetable_setup_start, + .pagetable_setup_done = native_pagetable_setup_done, }, .timers = { diff --git a/trunk/arch/x86/kernel/xsave.c b/trunk/arch/x86/kernel/xsave.c index 4e89b3dd408d..3d3e20709119 100644 --- a/trunk/arch/x86/kernel/xsave.c +++ b/trunk/arch/x86/kernel/xsave.c @@ -10,7 +10,9 @@ #include #include #include -#include +#ifdef CONFIG_IA32_EMULATION +#include +#endif #include /* @@ -21,9 +23,13 @@ u64 pcntxt_mask; /* * Represents init state for the supported extended state. */ -struct xsave_struct *init_xstate_buf; +static struct xsave_struct *init_xstate_buf; + +struct _fpx_sw_bytes fx_sw_reserved; +#ifdef CONFIG_IA32_EMULATION +struct _fpx_sw_bytes fx_sw_reserved_ia32; +#endif -static struct _fpx_sw_bytes fx_sw_reserved, fx_sw_reserved_ia32; static unsigned int *xstate_offsets, *xstate_sizes, xstate_features; /* @@ -38,9 +44,9 @@ static unsigned int *xstate_offsets, *xstate_sizes, xstate_features; */ void __sanitize_i387_state(struct task_struct *tsk) { - struct i387_fxsave_struct *fx = &tsk->thread.fpu.state->fxsave; - int feature_bit = 0x2; u64 xstate_bv; + int feature_bit = 0x2; + struct i387_fxsave_struct *fx = &tsk->thread.fpu.state->fxsave; if (!fx) return; @@ -98,326 +104,213 @@ void __sanitize_i387_state(struct task_struct *tsk) * Check for the presence of extended state information in the * user fpstate pointer in the sigcontext. */ -static inline int check_for_xstate(struct i387_fxsave_struct __user *buf, - void __user *fpstate, - struct _fpx_sw_bytes *fx_sw) +int check_for_xstate(struct i387_fxsave_struct __user *buf, + void __user *fpstate, + struct _fpx_sw_bytes *fx_sw_user) { int min_xstate_size = sizeof(struct i387_fxsave_struct) + sizeof(struct xsave_hdr_struct); unsigned int magic2; + int err; - if (__copy_from_user(fx_sw, &buf->sw_reserved[0], sizeof(*fx_sw))) - return -1; + err = __copy_from_user(fx_sw_user, &buf->sw_reserved[0], + sizeof(struct _fpx_sw_bytes)); + if (err) + return -EFAULT; - /* Check for the first magic field and other error scenarios. */ - if (fx_sw->magic1 != FP_XSTATE_MAGIC1 || - fx_sw->xstate_size < min_xstate_size || - fx_sw->xstate_size > xstate_size || - fx_sw->xstate_size > fx_sw->extended_size) - return -1; + /* + * First Magic check failed. + */ + if (fx_sw_user->magic1 != FP_XSTATE_MAGIC1) + return -EINVAL; + /* + * Check for error scenarios. + */ + if (fx_sw_user->xstate_size < min_xstate_size || + fx_sw_user->xstate_size > xstate_size || + fx_sw_user->xstate_size > fx_sw_user->extended_size) + return -EINVAL; + + err = __get_user(magic2, (__u32 *) (((void *)fpstate) + + fx_sw_user->extended_size - + FP_XSTATE_MAGIC2_SIZE)); + if (err) + return err; /* * Check for the presence of second magic word at the end of memory * layout. This detects the case where the user just copied the legacy * fpstate layout with out copying the extended state information * in the memory layout. */ - if (__get_user(magic2, (__u32 __user *)(fpstate + fx_sw->xstate_size)) - || magic2 != FP_XSTATE_MAGIC2) - return -1; + if (magic2 != FP_XSTATE_MAGIC2) + return -EFAULT; return 0; } +#ifdef CONFIG_X86_64 /* * Signal frame handlers. */ -static inline int save_fsave_header(struct task_struct *tsk, void __user *buf) -{ - if (use_fxsr()) { - struct xsave_struct *xsave = &tsk->thread.fpu.state->xsave; - struct user_i387_ia32_struct env; - struct _fpstate_ia32 __user *fp = buf; - - convert_from_fxsr(&env, tsk); - - if (__copy_to_user(buf, &env, sizeof(env)) || - __put_user(xsave->i387.swd, &fp->status) || - __put_user(X86_FXSR_MAGIC, &fp->magic)) - return -1; - } else { - struct i387_fsave_struct __user *fp = buf; - u32 swd; - if (__get_user(swd, &fp->swd) || __put_user(swd, &fp->status)) - return -1; - } - return 0; -} - -static inline int save_xstate_epilog(void __user *buf, int ia32_frame) +int save_i387_xstate(void __user *buf) { - struct xsave_struct __user *x = buf; - struct _fpx_sw_bytes *sw_bytes; - u32 xstate_bv; - int err; - - /* Setup the bytes not touched by the [f]xsave and reserved for SW. */ - sw_bytes = ia32_frame ? &fx_sw_reserved_ia32 : &fx_sw_reserved; - err = __copy_to_user(&x->i387.sw_reserved, sw_bytes, sizeof(*sw_bytes)); - - if (!use_xsave()) - return err; - - err |= __put_user(FP_XSTATE_MAGIC2, (__u32 *)(buf + xstate_size)); - - /* - * Read the xstate_bv which we copied (directly from the cpu or - * from the state in task struct) to the user buffers. - */ - err |= __get_user(xstate_bv, (__u32 *)&x->xsave_hdr.xstate_bv); - - /* - * For legacy compatible, we always set FP/SSE bits in the bit - * vector while saving the state to the user context. This will - * enable us capturing any changes(during sigreturn) to - * the FP/SSE bits by the legacy applications which don't touch - * xstate_bv in the xsave header. - * - * xsave aware apps can change the xstate_bv in the xsave - * header as well as change any contents in the memory layout. - * xrestore as part of sigreturn will capture all the changes. - */ - xstate_bv |= XSTATE_FPSSE; - - err |= __put_user(xstate_bv, (__u32 *)&x->xsave_hdr.xstate_bv); - - return err; -} - -static inline int save_user_xstate(struct xsave_struct __user *buf) -{ - int err; - - if (use_xsave()) - err = xsave_user(buf); - else if (use_fxsr()) - err = fxsave_user((struct i387_fxsave_struct __user *) buf); - else - err = fsave_user((struct i387_fsave_struct __user *) buf); - - if (unlikely(err) && __clear_user(buf, xstate_size)) - err = -EFAULT; - return err; -} - -/* - * Save the fpu, extended register state to the user signal frame. - * - * 'buf_fx' is the 64-byte aligned pointer at which the [f|fx|x]save - * state is copied. - * 'buf' points to the 'buf_fx' or to the fsave header followed by 'buf_fx'. - * - * buf == buf_fx for 64-bit frames and 32-bit fsave frame. - * buf != buf_fx for 32-bit frames with fxstate. - * - * If the fpu, extended register state is live, save the state directly - * to the user frame pointed by the aligned pointer 'buf_fx'. Otherwise, - * copy the thread's fpu state to the user frame starting at 'buf_fx'. - * - * If this is a 32-bit frame with fxstate, put a fsave header before - * the aligned state at 'buf_fx'. - * - * For [f]xsave state, update the SW reserved fields in the [f]xsave frame - * indicating the absence/presence of the extended state to the user. - */ -int save_xstate_sig(void __user *buf, void __user *buf_fx, int size) -{ - struct xsave_struct *xsave = ¤t->thread.fpu.state->xsave; struct task_struct *tsk = current; - int ia32_fxstate = (buf != buf_fx); + int err = 0; - ia32_fxstate &= (config_enabled(CONFIG_X86_32) || - config_enabled(CONFIG_IA32_EMULATION)); - - if (!access_ok(VERIFY_WRITE, buf, size)) + if (!access_ok(VERIFY_WRITE, buf, sig_xstate_size)) return -EACCES; - if (!HAVE_HWFP) - return fpregs_soft_get(current, NULL, 0, - sizeof(struct user_i387_ia32_struct), NULL, - (struct _fpstate_ia32 __user *) buf) ? -1 : 1; + BUG_ON(sig_xstate_size < xstate_size); + + if ((unsigned long)buf % 64) + pr_err("%s: bad fpstate %p\n", __func__, buf); + + if (!used_math()) + return 0; if (user_has_fpu()) { - /* Save the live register state to the user directly. */ - if (save_user_xstate(buf_fx)) - return -1; - /* Update the thread's fxstate to save the fsave header. */ - if (ia32_fxstate) - fpu_fxsave(&tsk->thread.fpu); + if (use_xsave()) + err = xsave_user(buf); + else + err = fxsave_user(buf); + + if (err) + return err; + user_fpu_end(); } else { sanitize_i387_state(tsk); - if (__copy_to_user(buf_fx, xsave, xstate_size)) + if (__copy_to_user(buf, &tsk->thread.fpu.state->fxsave, + xstate_size)) return -1; } - /* Save the fsave header for the 32-bit frames. */ - if ((ia32_fxstate || !use_fxsr()) && save_fsave_header(tsk, buf)) - return -1; - - if (use_fxsr() && save_xstate_epilog(buf_fx, ia32_fxstate)) - return -1; - - drop_init_fpu(tsk); /* trigger finit */ + clear_used_math(); /* trigger finit */ - return 0; -} + if (use_xsave()) { + struct _fpstate __user *fx = buf; + struct _xstate __user *x = buf; + u64 xstate_bv; -static inline void -sanitize_restored_xstate(struct task_struct *tsk, - struct user_i387_ia32_struct *ia32_env, - u64 xstate_bv, int fx_only) -{ - struct xsave_struct *xsave = &tsk->thread.fpu.state->xsave; - struct xsave_hdr_struct *xsave_hdr = &xsave->xsave_hdr; + err = __copy_to_user(&fx->sw_reserved, &fx_sw_reserved, + sizeof(struct _fpx_sw_bytes)); - if (use_xsave()) { - /* These bits must be zero. */ - xsave_hdr->reserved1[0] = xsave_hdr->reserved1[1] = 0; + err |= __put_user(FP_XSTATE_MAGIC2, + (__u32 __user *) (buf + sig_xstate_size + - FP_XSTATE_MAGIC2_SIZE)); /* - * Init the state that is not present in the memory - * layout and not enabled by the OS. + * Read the xstate_bv which we copied (directly from the cpu or + * from the state in task struct) to the user buffers and + * set the FP/SSE bits. */ - if (fx_only) - xsave_hdr->xstate_bv = XSTATE_FPSSE; - else - xsave_hdr->xstate_bv &= (pcntxt_mask & xstate_bv); - } + err |= __get_user(xstate_bv, &x->xstate_hdr.xstate_bv); - if (use_fxsr()) { /* - * mscsr reserved bits must be masked to zero for security - * reasons. + * For legacy compatible, we always set FP/SSE bits in the bit + * vector while saving the state to the user context. This will + * enable us capturing any changes(during sigreturn) to + * the FP/SSE bits by the legacy applications which don't touch + * xstate_bv in the xsave header. + * + * xsave aware apps can change the xstate_bv in the xsave + * header as well as change any contents in the memory layout. + * xrestore as part of sigreturn will capture all the changes. */ - xsave->i387.mxcsr &= mxcsr_feature_mask; + xstate_bv |= XSTATE_FPSSE; + + err |= __put_user(xstate_bv, &x->xstate_hdr.xstate_bv); - convert_to_fxsr(tsk, ia32_env); + if (err) + return err; } + + return 1; } /* - * Restore the extended state if present. Otherwise, restore the FP/SSE state. + * Restore the extended state if present. Otherwise, restore the FP/SSE + * state. */ -static inline int restore_user_xstate(void __user *buf, u64 xbv, int fx_only) +static int restore_user_xstate(void __user *buf) { - if (use_xsave()) { - if ((unsigned long)buf % 64 || fx_only) { - u64 init_bv = pcntxt_mask & ~XSTATE_FPSSE; - xrstor_state(init_xstate_buf, init_bv); - return fxrstor_checking((__force void *) buf); - } else { - u64 init_bv = pcntxt_mask & ~xbv; - if (unlikely(init_bv)) - xrstor_state(init_xstate_buf, init_bv); - return xrestore_user(buf, xbv); - } - } else if (use_fxsr()) { - return fxrstor_checking((__force void *) buf); - } else - return frstor_checking((__force void *) buf); -} - -int __restore_xstate_sig(void __user *buf, void __user *buf_fx, int size) -{ - int ia32_fxstate = (buf != buf_fx); - struct task_struct *tsk = current; - int state_size = xstate_size; - u64 xstate_bv = 0; - int fx_only = 0; + struct _fpx_sw_bytes fx_sw_user; + u64 mask; + int err; - ia32_fxstate &= (config_enabled(CONFIG_X86_32) || - config_enabled(CONFIG_IA32_EMULATION)); + if (((unsigned long)buf % 64) || + check_for_xstate(buf, buf, &fx_sw_user)) + goto fx_only; - if (!buf) { - drop_init_fpu(tsk); - return 0; - } + mask = fx_sw_user.xstate_bv; - if (!access_ok(VERIFY_READ, buf, size)) - return -EACCES; + /* + * restore the state passed by the user. + */ + err = xrestore_user(buf, mask); + if (err) + return err; - if (!used_math() && init_fpu(tsk)) - return -1; + /* + * init the state skipped by the user. + */ + mask = pcntxt_mask & ~mask; + if (unlikely(mask)) + xrstor_state(init_xstate_buf, mask); - if (!HAVE_HWFP) { - return fpregs_soft_set(current, NULL, - 0, sizeof(struct user_i387_ia32_struct), - NULL, buf) != 0; - } + return 0; - if (use_xsave()) { - struct _fpx_sw_bytes fx_sw_user; - if (unlikely(check_for_xstate(buf_fx, buf_fx, &fx_sw_user))) { - /* - * Couldn't find the extended state information in the - * memory layout. Restore just the FP/SSE and init all - * the other extended state. - */ - state_size = sizeof(struct i387_fxsave_struct); - fx_only = 1; - } else { - state_size = fx_sw_user.xstate_size; - xstate_bv = fx_sw_user.xstate_bv; - } - } +fx_only: + /* + * couldn't find the extended state information in the + * memory layout. Restore just the FP/SSE and init all + * the other extended state. + */ + xrstor_state(init_xstate_buf, pcntxt_mask & ~XSTATE_FPSSE); + return fxrstor_checking((__force struct i387_fxsave_struct *)buf); +} - if (ia32_fxstate) { - /* - * For 32-bit frames with fxstate, copy the user state to the - * thread's fpu state, reconstruct fxstate from the fsave - * header. Sanitize the copied state etc. - */ - struct xsave_struct *xsave = &tsk->thread.fpu.state->xsave; - struct user_i387_ia32_struct env; - int err = 0; +/* + * This restores directly out of user space. Exceptions are handled. + */ +int restore_i387_xstate(void __user *buf) +{ + struct task_struct *tsk = current; + int err = 0; - /* - * Drop the current fpu which clears used_math(). This ensures - * that any context-switch during the copy of the new state, - * avoids the intermediate state from getting restored/saved. - * Thus avoiding the new restored state from getting corrupted. - * We will be ready to restore/save the state only after - * set_used_math() is again set. - */ - drop_fpu(tsk); - - if (__copy_from_user(xsave, buf_fx, state_size) || - __copy_from_user(&env, buf, sizeof(env))) { - err = -1; - } else { - sanitize_restored_xstate(tsk, &env, xstate_bv, fx_only); - set_used_math(); - } + if (!buf) { + if (used_math()) + goto clear; + return 0; + } else + if (!access_ok(VERIFY_READ, buf, sig_xstate_size)) + return -EACCES; - if (use_eager_fpu()) - math_state_restore(); + if (!used_math()) { + err = init_fpu(tsk); + if (err) + return err; + } - return err; - } else { + user_fpu_begin(); + if (use_xsave()) + err = restore_user_xstate(buf); + else + err = fxrstor_checking((__force struct i387_fxsave_struct *) + buf); + if (unlikely(err)) { /* - * For 64-bit frames and 32-bit fsave frames, restore the user - * state to the registers directly (with exceptions handled). + * Encountered an error while doing the restore from the + * user buffer, clear the fpu state. */ - user_fpu_begin(); - if (restore_user_xstate(buf_fx, xstate_bv, fx_only)) { - drop_init_fpu(tsk); - return -1; - } +clear: + clear_fpu(tsk); + clear_used_math(); } - - return 0; + return err; } +#endif /* * Prepare the SW reserved portion of the fxsave memory layout, indicating @@ -428,23 +321,32 @@ int __restore_xstate_sig(void __user *buf, void __user *buf_fx, int size) */ static void prepare_fx_sw_frame(void) { - int fsave_header_size = sizeof(struct i387_fsave_struct); - int size = xstate_size + FP_XSTATE_MAGIC2_SIZE; + int size_extended = (xstate_size - sizeof(struct i387_fxsave_struct)) + + FP_XSTATE_MAGIC2_SIZE; - if (config_enabled(CONFIG_X86_32)) - size += fsave_header_size; + sig_xstate_size = sizeof(struct _fpstate) + size_extended; + +#ifdef CONFIG_IA32_EMULATION + sig_xstate_ia32_size = sizeof(struct _fpstate_ia32) + size_extended; +#endif + + memset(&fx_sw_reserved, 0, sizeof(fx_sw_reserved)); fx_sw_reserved.magic1 = FP_XSTATE_MAGIC1; - fx_sw_reserved.extended_size = size; + fx_sw_reserved.extended_size = sig_xstate_size; fx_sw_reserved.xstate_bv = pcntxt_mask; fx_sw_reserved.xstate_size = xstate_size; - - if (config_enabled(CONFIG_IA32_EMULATION)) { - fx_sw_reserved_ia32 = fx_sw_reserved; - fx_sw_reserved_ia32.extended_size += fsave_header_size; - } +#ifdef CONFIG_IA32_EMULATION + memcpy(&fx_sw_reserved_ia32, &fx_sw_reserved, + sizeof(struct _fpx_sw_bytes)); + fx_sw_reserved_ia32.extended_size = sig_xstate_ia32_size; +#endif } +#ifdef CONFIG_X86_64 +unsigned int sig_xstate_size = sizeof(struct _fpstate); +#endif + /* * Enable the extended processor state save/restore feature */ @@ -482,21 +384,19 @@ static void __init setup_xstate_features(void) /* * setup the xstate image representing the init state */ -static void __init setup_init_fpu_buf(void) +static void __init setup_xstate_init(void) { + setup_xstate_features(); + /* * Setup init_xstate_buf to represent the init state of * all the features managed by the xsave */ init_xstate_buf = alloc_bootmem_align(xstate_size, __alignof__(struct xsave_struct)); - fx_finit(&init_xstate_buf->i387); - - if (!cpu_has_xsave) - return; - - setup_xstate_features(); + init_xstate_buf->i387.mxcsr = MXCSR_DEFAULT; + clts(); /* * Init all the features state with header_bv being 0x0 */ @@ -506,21 +406,9 @@ static void __init setup_init_fpu_buf(void) * of any feature which is not represented by all zero's. */ xsave_state(init_xstate_buf, -1); + stts(); } -static enum { AUTO, ENABLE, DISABLE } eagerfpu = AUTO; -static int __init eager_fpu_setup(char *s) -{ - if (!strcmp(s, "on")) - eagerfpu = ENABLE; - else if (!strcmp(s, "off")) - eagerfpu = DISABLE; - else if (!strcmp(s, "auto")) - eagerfpu = AUTO; - return 1; -} -__setup("eagerfpu=", eager_fpu_setup); - /* * Enable and initialize the xsave feature. */ @@ -557,11 +445,8 @@ static void __init xstate_enable_boot_cpu(void) update_regset_xstate_info(xstate_size, pcntxt_mask); prepare_fx_sw_frame(); - setup_init_fpu_buf(); - /* Auto enable eagerfpu for xsaveopt */ - if (cpu_has_xsaveopt && eagerfpu != DISABLE) - eagerfpu = ENABLE; + setup_xstate_init(); pr_info("enabled xstate_bv 0x%llx, cntxt size 0x%x\n", pcntxt_mask, xstate_size); @@ -586,43 +471,3 @@ void __cpuinit xsave_init(void) next_func = xstate_enable; this_func(); } - -static inline void __init eager_fpu_init_bp(void) -{ - current->thread.fpu.state = - alloc_bootmem_align(xstate_size, __alignof__(struct xsave_struct)); - if (!init_xstate_buf) - setup_init_fpu_buf(); -} - -void __cpuinit eager_fpu_init(void) -{ - static __refdata void (*boot_func)(void) = eager_fpu_init_bp; - - clear_used_math(); - current_thread_info()->status = 0; - - if (eagerfpu == ENABLE) - setup_force_cpu_cap(X86_FEATURE_EAGER_FPU); - - if (!cpu_has_eager_fpu) { - stts(); - return; - } - - if (boot_func) { - boot_func(); - boot_func = NULL; - } - - /* - * This is same as math_state_restore(). But use_xsave() is - * not yet patched to use math_state_restore(). - */ - init_fpu(current); - __thread_fpu_begin(current); - if (cpu_has_xsave) - xrstor_state(init_xstate_buf, -1); - else - fxrstor_checking(&init_xstate_buf->i387); -} diff --git a/trunk/arch/x86/kvm/emulate.c b/trunk/arch/x86/kvm/emulate.c index a3b57a27be88..97d9a9914ba8 100644 --- a/trunk/arch/x86/kvm/emulate.c +++ b/trunk/arch/x86/kvm/emulate.c @@ -475,26 +475,13 @@ register_address(struct x86_emulate_ctxt *ctxt, unsigned long reg) return address_mask(ctxt, reg); } -static void masked_increment(ulong *reg, ulong mask, int inc) -{ - assign_masked(reg, *reg + inc, mask); -} - static inline void register_address_increment(struct x86_emulate_ctxt *ctxt, unsigned long *reg, int inc) { - ulong mask; - if (ctxt->ad_bytes == sizeof(unsigned long)) - mask = ~0UL; + *reg += inc; else - mask = ad_mask(ctxt); - masked_increment(reg, mask, inc); -} - -static void rsp_increment(struct x86_emulate_ctxt *ctxt, int inc) -{ - masked_increment(&ctxt->regs[VCPU_REGS_RSP], stack_mask(ctxt), inc); + *reg = (*reg & ~ad_mask(ctxt)) | ((*reg + inc) & ad_mask(ctxt)); } static inline void jmp_rel(struct x86_emulate_ctxt *ctxt, int rel) @@ -1535,8 +1522,8 @@ static int push(struct x86_emulate_ctxt *ctxt, void *data, int bytes) { struct segmented_address addr; - rsp_increment(ctxt, -bytes); - addr.ea = ctxt->regs[VCPU_REGS_RSP] & stack_mask(ctxt); + register_address_increment(ctxt, &ctxt->regs[VCPU_REGS_RSP], -bytes); + addr.ea = register_address(ctxt, ctxt->regs[VCPU_REGS_RSP]); addr.seg = VCPU_SREG_SS; return segmented_write(ctxt, addr, data, bytes); @@ -1555,13 +1542,13 @@ static int emulate_pop(struct x86_emulate_ctxt *ctxt, int rc; struct segmented_address addr; - addr.ea = ctxt->regs[VCPU_REGS_RSP] & stack_mask(ctxt); + addr.ea = register_address(ctxt, ctxt->regs[VCPU_REGS_RSP]); addr.seg = VCPU_SREG_SS; rc = segmented_read(ctxt, addr, dest, len); if (rc != X86EMUL_CONTINUE) return rc; - rsp_increment(ctxt, len); + register_address_increment(ctxt, &ctxt->regs[VCPU_REGS_RSP], len); return rc; } @@ -1701,7 +1688,8 @@ static int em_popa(struct x86_emulate_ctxt *ctxt) while (reg >= VCPU_REGS_RAX) { if (reg == VCPU_REGS_RSP) { - rsp_increment(ctxt, ctxt->op_bytes); + register_address_increment(ctxt, &ctxt->regs[VCPU_REGS_RSP], + ctxt->op_bytes); --reg; } @@ -2837,7 +2825,7 @@ static int em_ret_near_imm(struct x86_emulate_ctxt *ctxt) rc = emulate_pop(ctxt, &ctxt->dst.val, ctxt->op_bytes); if (rc != X86EMUL_CONTINUE) return rc; - rsp_increment(ctxt, ctxt->src.val); + register_address_increment(ctxt, &ctxt->regs[VCPU_REGS_RSP], ctxt->src.val); return X86EMUL_CONTINUE; } diff --git a/trunk/arch/x86/kvm/i8259.c b/trunk/arch/x86/kvm/i8259.c index 9fc9aa7ac703..1df8fb9e1d5d 100644 --- a/trunk/arch/x86/kvm/i8259.c +++ b/trunk/arch/x86/kvm/i8259.c @@ -316,11 +316,6 @@ static void pic_ioport_write(void *opaque, u32 addr, u32 val) addr &= 1; if (addr == 0) { if (val & 0x10) { - u8 edge_irr = s->irr & ~s->elcr; - int i; - bool found = false; - struct kvm_vcpu *vcpu; - s->init4 = val & 1; s->last_irr = 0; s->irr &= s->elcr; @@ -338,18 +333,6 @@ static void pic_ioport_write(void *opaque, u32 addr, u32 val) if (val & 0x08) pr_pic_unimpl( "level sensitive irq not supported"); - - kvm_for_each_vcpu(i, vcpu, s->pics_state->kvm) - if (kvm_apic_accept_pic_intr(vcpu)) { - found = true; - break; - } - - - if (found) - for (irq = 0; irq < PIC_NUM_PINS/2; irq++) - if (edge_irr & (1 << irq)) - pic_clear_isr(s, irq); } else if (val & 0x08) { if (val & 0x04) s->poll = 1; diff --git a/trunk/arch/x86/kvm/mmu.c b/trunk/arch/x86/kvm/mmu.c index 7fbd0d273ea8..01ca00423938 100644 --- a/trunk/arch/x86/kvm/mmu.c +++ b/trunk/arch/x86/kvm/mmu.c @@ -4112,22 +4112,17 @@ static int mmu_shrink(struct shrinker *shrink, struct shrink_control *sc) int idx; LIST_HEAD(invalid_list); - /* - * Never scan more than sc->nr_to_scan VM instances. - * Will not hit this condition practically since we do not try - * to shrink more than one VM and it is very unlikely to see - * !n_used_mmu_pages so many times. - */ - if (!nr_to_scan--) - break; /* * n_used_mmu_pages is accessed without holding kvm->mmu_lock * here. We may skip a VM instance errorneosly, but we do not * want to shrink a VM that only started to populate its MMU * anyway. */ - if (!kvm->arch.n_used_mmu_pages) + if (kvm->arch.n_used_mmu_pages > 0) { + if (!nr_to_scan--) + break; continue; + } idx = srcu_read_lock(&kvm->srcu); spin_lock(&kvm->mmu_lock); diff --git a/trunk/arch/x86/kvm/trace.h b/trunk/arch/x86/kvm/trace.h index bca63f04dccb..a71faf727ff3 100644 --- a/trunk/arch/x86/kvm/trace.h +++ b/trunk/arch/x86/kvm/trace.h @@ -183,6 +183,95 @@ TRACE_EVENT(kvm_apic, #define KVM_ISA_VMX 1 #define KVM_ISA_SVM 2 +#define VMX_EXIT_REASONS \ + { EXIT_REASON_EXCEPTION_NMI, "EXCEPTION_NMI" }, \ + { EXIT_REASON_EXTERNAL_INTERRUPT, "EXTERNAL_INTERRUPT" }, \ + { EXIT_REASON_TRIPLE_FAULT, "TRIPLE_FAULT" }, \ + { EXIT_REASON_PENDING_INTERRUPT, "PENDING_INTERRUPT" }, \ + { EXIT_REASON_NMI_WINDOW, "NMI_WINDOW" }, \ + { EXIT_REASON_TASK_SWITCH, "TASK_SWITCH" }, \ + { EXIT_REASON_CPUID, "CPUID" }, \ + { EXIT_REASON_HLT, "HLT" }, \ + { EXIT_REASON_INVLPG, "INVLPG" }, \ + { EXIT_REASON_RDPMC, "RDPMC" }, \ + { EXIT_REASON_RDTSC, "RDTSC" }, \ + { EXIT_REASON_VMCALL, "VMCALL" }, \ + { EXIT_REASON_VMCLEAR, "VMCLEAR" }, \ + { EXIT_REASON_VMLAUNCH, "VMLAUNCH" }, \ + { EXIT_REASON_VMPTRLD, "VMPTRLD" }, \ + { EXIT_REASON_VMPTRST, "VMPTRST" }, \ + { EXIT_REASON_VMREAD, "VMREAD" }, \ + { EXIT_REASON_VMRESUME, "VMRESUME" }, \ + { EXIT_REASON_VMWRITE, "VMWRITE" }, \ + { EXIT_REASON_VMOFF, "VMOFF" }, \ + { EXIT_REASON_VMON, "VMON" }, \ + { EXIT_REASON_CR_ACCESS, "CR_ACCESS" }, \ + { EXIT_REASON_DR_ACCESS, "DR_ACCESS" }, \ + { EXIT_REASON_IO_INSTRUCTION, "IO_INSTRUCTION" }, \ + { EXIT_REASON_MSR_READ, "MSR_READ" }, \ + { EXIT_REASON_MSR_WRITE, "MSR_WRITE" }, \ + { EXIT_REASON_MWAIT_INSTRUCTION, "MWAIT_INSTRUCTION" }, \ + { EXIT_REASON_MONITOR_INSTRUCTION, "MONITOR_INSTRUCTION" }, \ + { EXIT_REASON_PAUSE_INSTRUCTION, "PAUSE_INSTRUCTION" }, \ + { EXIT_REASON_MCE_DURING_VMENTRY, "MCE_DURING_VMENTRY" }, \ + { EXIT_REASON_TPR_BELOW_THRESHOLD, "TPR_BELOW_THRESHOLD" }, \ + { EXIT_REASON_APIC_ACCESS, "APIC_ACCESS" }, \ + { EXIT_REASON_EPT_VIOLATION, "EPT_VIOLATION" }, \ + { EXIT_REASON_EPT_MISCONFIG, "EPT_MISCONFIG" }, \ + { EXIT_REASON_WBINVD, "WBINVD" } + +#define SVM_EXIT_REASONS \ + { SVM_EXIT_READ_CR0, "read_cr0" }, \ + { SVM_EXIT_READ_CR3, "read_cr3" }, \ + { SVM_EXIT_READ_CR4, "read_cr4" }, \ + { SVM_EXIT_READ_CR8, "read_cr8" }, \ + { SVM_EXIT_WRITE_CR0, "write_cr0" }, \ + { SVM_EXIT_WRITE_CR3, "write_cr3" }, \ + { SVM_EXIT_WRITE_CR4, "write_cr4" }, \ + { SVM_EXIT_WRITE_CR8, "write_cr8" }, \ + { SVM_EXIT_READ_DR0, "read_dr0" }, \ + { SVM_EXIT_READ_DR1, "read_dr1" }, \ + { SVM_EXIT_READ_DR2, "read_dr2" }, \ + { SVM_EXIT_READ_DR3, "read_dr3" }, \ + { SVM_EXIT_WRITE_DR0, "write_dr0" }, \ + { SVM_EXIT_WRITE_DR1, "write_dr1" }, \ + { SVM_EXIT_WRITE_DR2, "write_dr2" }, \ + { SVM_EXIT_WRITE_DR3, "write_dr3" }, \ + { SVM_EXIT_WRITE_DR5, "write_dr5" }, \ + { SVM_EXIT_WRITE_DR7, "write_dr7" }, \ + { SVM_EXIT_EXCP_BASE + DB_VECTOR, "DB excp" }, \ + { SVM_EXIT_EXCP_BASE + BP_VECTOR, "BP excp" }, \ + { SVM_EXIT_EXCP_BASE + UD_VECTOR, "UD excp" }, \ + { SVM_EXIT_EXCP_BASE + PF_VECTOR, "PF excp" }, \ + { SVM_EXIT_EXCP_BASE + NM_VECTOR, "NM excp" }, \ + { SVM_EXIT_EXCP_BASE + MC_VECTOR, "MC excp" }, \ + { SVM_EXIT_INTR, "interrupt" }, \ + { SVM_EXIT_NMI, "nmi" }, \ + { SVM_EXIT_SMI, "smi" }, \ + { SVM_EXIT_INIT, "init" }, \ + { SVM_EXIT_VINTR, "vintr" }, \ + { SVM_EXIT_CPUID, "cpuid" }, \ + { SVM_EXIT_INVD, "invd" }, \ + { SVM_EXIT_HLT, "hlt" }, \ + { SVM_EXIT_INVLPG, "invlpg" }, \ + { SVM_EXIT_INVLPGA, "invlpga" }, \ + { SVM_EXIT_IOIO, "io" }, \ + { SVM_EXIT_MSR, "msr" }, \ + { SVM_EXIT_TASK_SWITCH, "task_switch" }, \ + { SVM_EXIT_SHUTDOWN, "shutdown" }, \ + { SVM_EXIT_VMRUN, "vmrun" }, \ + { SVM_EXIT_VMMCALL, "hypercall" }, \ + { SVM_EXIT_VMLOAD, "vmload" }, \ + { SVM_EXIT_VMSAVE, "vmsave" }, \ + { SVM_EXIT_STGI, "stgi" }, \ + { SVM_EXIT_CLGI, "clgi" }, \ + { SVM_EXIT_SKINIT, "skinit" }, \ + { SVM_EXIT_WBINVD, "wbinvd" }, \ + { SVM_EXIT_MONITOR, "monitor" }, \ + { SVM_EXIT_MWAIT, "mwait" }, \ + { SVM_EXIT_XSETBV, "xsetbv" }, \ + { SVM_EXIT_NPF, "npf" } + /* * Tracepoint for kvm guest exit: */ diff --git a/trunk/arch/x86/kvm/vmx.c b/trunk/arch/x86/kvm/vmx.c index 851aa7c3b890..c39b60707e02 100644 --- a/trunk/arch/x86/kvm/vmx.c +++ b/trunk/arch/x86/kvm/vmx.c @@ -1488,17 +1488,20 @@ static void __vmx_load_host_state(struct vcpu_vmx *vmx) loadsegment(ds, vmx->host_state.ds_sel); loadsegment(es, vmx->host_state.es_sel); } +#else + /* + * The sysexit path does not restore ds/es, so we must set them to + * a reasonable value ourselves. + */ + loadsegment(ds, __USER_DS); + loadsegment(es, __USER_DS); #endif reload_tss(); #ifdef CONFIG_X86_64 wrmsrl(MSR_KERNEL_GS_BASE, vmx->msr_host_kernel_gs_base); #endif - /* - * If the FPU is not active (through the host task or - * the guest vcpu), then restore the cr0.TS bit. - */ - if (!user_has_fpu() && !vmx->vcpu.guest_fpu_loaded) - stts(); + if (user_has_fpu()) + clts(); load_gdt(&__get_cpu_var(host_gdt)); } @@ -3623,7 +3626,6 @@ static void seg_setup(int seg) static int alloc_apic_access_page(struct kvm *kvm) { - struct page *page; struct kvm_userspace_memory_region kvm_userspace_mem; int r = 0; @@ -3638,13 +3640,7 @@ static int alloc_apic_access_page(struct kvm *kvm) if (r) goto out; - page = gfn_to_page(kvm, 0xfee00); - if (is_error_page(page)) { - r = -EFAULT; - goto out; - } - - kvm->arch.apic_access_page = page; + kvm->arch.apic_access_page = gfn_to_page(kvm, 0xfee00); out: mutex_unlock(&kvm->slots_lock); return r; @@ -3652,7 +3648,6 @@ static int alloc_apic_access_page(struct kvm *kvm) static int alloc_identity_pagetable(struct kvm *kvm) { - struct page *page; struct kvm_userspace_memory_region kvm_userspace_mem; int r = 0; @@ -3668,13 +3663,8 @@ static int alloc_identity_pagetable(struct kvm *kvm) if (r) goto out; - page = gfn_to_page(kvm, kvm->arch.ept_identity_map_addr >> PAGE_SHIFT); - if (is_error_page(page)) { - r = -EFAULT; - goto out; - } - - kvm->arch.ept_identity_pagetable = page; + kvm->arch.ept_identity_pagetable = gfn_to_page(kvm, + kvm->arch.ept_identity_map_addr >> PAGE_SHIFT); out: mutex_unlock(&kvm->slots_lock); return r; @@ -3747,7 +3737,7 @@ static void vmx_set_constant_host_state(void) unsigned long tmpl; struct desc_ptr dt; - vmcs_writel(HOST_CR0, read_cr0() & ~X86_CR0_TS); /* 22.2.3 */ + vmcs_writel(HOST_CR0, read_cr0() | X86_CR0_TS); /* 22.2.3 */ vmcs_writel(HOST_CR4, read_cr4()); /* 22.2.3, 22.2.5 */ vmcs_writel(HOST_CR3, read_cr3()); /* 22.2.3 FIXME: shadow tables */ @@ -4547,7 +4537,7 @@ static int handle_cr(struct kvm_vcpu *vcpu) vcpu->run->exit_reason = KVM_EXIT_SET_TPR; return 0; } - } + }; break; case 2: /* clts */ handle_clts(vcpu); @@ -6380,19 +6370,6 @@ static void __noclone vmx_vcpu_run(struct kvm_vcpu *vcpu) #endif ); -#ifndef CONFIG_X86_64 - /* - * The sysexit path does not restore ds/es, so we must set them to - * a reasonable value ourselves. - * - * We can't defer this to vmx_load_host_state() since that function - * may be executed in interrupt context, which saves and restore segments - * around it, nullifying its effect. - */ - loadsegment(ds, __USER_DS); - loadsegment(es, __USER_DS); -#endif - vcpu->arch.regs_avail = ~((1 << VCPU_REGS_RIP) | (1 << VCPU_REGS_RSP) | (1 << VCPU_EXREG_RFLAGS) | (1 << VCPU_EXREG_CPL) @@ -6592,7 +6569,7 @@ static void vmx_cpuid_update(struct kvm_vcpu *vcpu) /* Exposing INVPCID only when PCID is exposed */ best = kvm_find_cpuid_entry(vcpu, 0x7, 0); if (vmx_invpcid_supported() && - best && (best->ebx & bit(X86_FEATURE_INVPCID)) && + best && (best->ecx & bit(X86_FEATURE_INVPCID)) && guest_cpuid_has_pcid(vcpu)) { exec_control |= SECONDARY_EXEC_ENABLE_INVPCID; vmcs_write32(SECONDARY_VM_EXEC_CONTROL, @@ -6602,7 +6579,7 @@ static void vmx_cpuid_update(struct kvm_vcpu *vcpu) vmcs_write32(SECONDARY_VM_EXEC_CONTROL, exec_control); if (best) - best->ebx &= ~bit(X86_FEATURE_INVPCID); + best->ecx &= ~bit(X86_FEATURE_INVPCID); } } diff --git a/trunk/arch/x86/kvm/x86.c b/trunk/arch/x86/kvm/x86.c index 1f09552572fa..59b59508ff07 100644 --- a/trunk/arch/x86/kvm/x86.c +++ b/trunk/arch/x86/kvm/x86.c @@ -806,7 +806,7 @@ EXPORT_SYMBOL_GPL(kvm_rdpmc); * kvm-specific. Those are put in the beginning of the list. */ -#define KVM_SAVE_MSRS_BEGIN 10 +#define KVM_SAVE_MSRS_BEGIN 9 static u32 msrs_to_save[] = { MSR_KVM_SYSTEM_TIME, MSR_KVM_WALL_CLOCK, MSR_KVM_SYSTEM_TIME_NEW, MSR_KVM_WALL_CLOCK_NEW, @@ -925,10 +925,6 @@ static void kvm_write_wall_clock(struct kvm *kvm, gpa_t wall_clock) */ getboottime(&boot); - if (kvm->arch.kvmclock_offset) { - struct timespec ts = ns_to_timespec(kvm->arch.kvmclock_offset); - boot = timespec_sub(boot, ts); - } wc.sec = boot.tv_sec; wc.nsec = boot.tv_nsec; wc.version = version; @@ -2000,9 +1996,6 @@ int kvm_get_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata) case MSR_KVM_STEAL_TIME: data = vcpu->arch.st.msr_val; break; - case MSR_KVM_PV_EOI_EN: - data = vcpu->arch.pv_eoi.msr_val; - break; case MSR_IA32_P5_MC_ADDR: case MSR_IA32_P5_MC_TYPE: case MSR_IA32_MCG_CAP: @@ -5113,20 +5106,17 @@ static void post_kvm_run_save(struct kvm_vcpu *vcpu) !kvm_event_needs_reinjection(vcpu); } -static int vapic_enter(struct kvm_vcpu *vcpu) +static void vapic_enter(struct kvm_vcpu *vcpu) { struct kvm_lapic *apic = vcpu->arch.apic; struct page *page; if (!apic || !apic->vapic_addr) - return 0; + return; page = gfn_to_page(vcpu->kvm, apic->vapic_addr >> PAGE_SHIFT); - if (is_error_page(page)) - return -EFAULT; vcpu->arch.apic->vapic_page = page; - return 0; } static void vapic_exit(struct kvm_vcpu *vcpu) @@ -5433,11 +5423,7 @@ static int __vcpu_run(struct kvm_vcpu *vcpu) } vcpu->srcu_idx = srcu_read_lock(&kvm->srcu); - r = vapic_enter(vcpu); - if (r) { - srcu_read_unlock(&kvm->srcu, vcpu->srcu_idx); - return r; - } + vapic_enter(vcpu); r = 1; while (r > 0) { @@ -5979,7 +5965,7 @@ void kvm_load_guest_fpu(struct kvm_vcpu *vcpu) */ kvm_put_guest_xcr0(vcpu); vcpu->guest_fpu_loaded = 1; - __kernel_fpu_begin(); + unlazy_fpu(current); fpu_restore_checking(&vcpu->arch.guest_fpu); trace_kvm_fpu(1); } @@ -5993,7 +5979,6 @@ void kvm_put_guest_fpu(struct kvm_vcpu *vcpu) vcpu->guest_fpu_loaded = 0; fpu_save_init(&vcpu->arch.guest_fpu); - __kernel_fpu_end(); ++vcpu->stat.fpu_reload; kvm_make_request(KVM_REQ_DEACTIVATE_FPU, vcpu); trace_kvm_fpu(0); diff --git a/trunk/arch/x86/mm/fault.c b/trunk/arch/x86/mm/fault.c index 7dde46d68a25..76dcd9d8e0bc 100644 --- a/trunk/arch/x86/mm/fault.c +++ b/trunk/arch/x86/mm/fault.c @@ -18,7 +18,6 @@ #include /* pgd_*(), ... */ #include /* kmemcheck_*(), ... */ #include /* VSYSCALL_START */ -#include /* exception_enter(), ... */ /* * Page fault error code bits: @@ -1001,8 +1000,8 @@ static int fault_in_kernel_space(unsigned long address) * and the problem, and then passes it off to one of the appropriate * routines. */ -static void __kprobes -__do_page_fault(struct pt_regs *regs, unsigned long error_code) +dotraplinkage void __kprobes +do_page_fault(struct pt_regs *regs, unsigned long error_code) { struct vm_area_struct *vma; struct task_struct *tsk; @@ -1210,11 +1209,3 @@ __do_page_fault(struct pt_regs *regs, unsigned long error_code) up_read(&mm->mmap_sem); } - -dotraplinkage void __kprobes -do_page_fault(struct pt_regs *regs, unsigned long error_code) -{ - exception_enter(regs); - __do_page_fault(regs, error_code); - exception_exit(regs); -} diff --git a/trunk/arch/x86/mm/hugetlbpage.c b/trunk/arch/x86/mm/hugetlbpage.c index b91e48512425..f6679a7fb8ca 100644 --- a/trunk/arch/x86/mm/hugetlbpage.c +++ b/trunk/arch/x86/mm/hugetlbpage.c @@ -56,16 +56,9 @@ static int vma_shareable(struct vm_area_struct *vma, unsigned long addr) } /* - * Search for a shareable pmd page for hugetlb. In any case calls pmd_alloc() - * and returns the corresponding pte. While this is not necessary for the - * !shared pmd case because we can allocate the pmd later as well, it makes the - * code much cleaner. pmd allocation is essential for the shared case because - * pud has to be populated inside the same i_mmap_mutex section - otherwise - * racing tasks could either miss the sharing (see huge_pte_offset) or select a - * bad pmd for sharing. + * search for a shareable pmd page for hugetlb. */ -static pte_t * -huge_pmd_share(struct mm_struct *mm, unsigned long addr, pud_t *pud) +static void huge_pmd_share(struct mm_struct *mm, unsigned long addr, pud_t *pud) { struct vm_area_struct *vma = find_vma(mm, addr); struct address_space *mapping = vma->vm_file->f_mapping; @@ -75,10 +68,9 @@ huge_pmd_share(struct mm_struct *mm, unsigned long addr, pud_t *pud) struct vm_area_struct *svma; unsigned long saddr; pte_t *spte = NULL; - pte_t *pte; if (!vma_shareable(vma, addr)) - return (pte_t *)pmd_alloc(mm, pud, addr); + return; mutex_lock(&mapping->i_mmap_mutex); vma_prio_tree_foreach(svma, &iter, &mapping->i_mmap, idx, idx) { @@ -105,9 +97,7 @@ huge_pmd_share(struct mm_struct *mm, unsigned long addr, pud_t *pud) put_page(virt_to_page(spte)); spin_unlock(&mm->page_table_lock); out: - pte = (pte_t *)pmd_alloc(mm, pud, addr); mutex_unlock(&mapping->i_mmap_mutex); - return pte; } /* @@ -152,9 +142,8 @@ pte_t *huge_pte_alloc(struct mm_struct *mm, } else { BUG_ON(sz != PMD_SIZE); if (pud_none(*pud)) - pte = huge_pmd_share(mm, addr, pud); - else - pte = (pte_t *)pmd_alloc(mm, pud, addr); + huge_pmd_share(mm, addr, pud); + pte = (pte_t *) pmd_alloc(mm, pud, addr); } } BUG_ON(pte && !pte_none(*pte) && !pte_huge(*pte)); diff --git a/trunk/arch/x86/mm/init.c b/trunk/arch/x86/mm/init.c index ab1f6a93b527..e0e6990723e9 100644 --- a/trunk/arch/x86/mm/init.c +++ b/trunk/arch/x86/mm/init.c @@ -319,7 +319,7 @@ unsigned long __init_refok init_memory_mapping(unsigned long start, */ int devmem_is_allowed(unsigned long pagenr) { - if (pagenr < 256) + if (pagenr <= 256) return 1; if (iomem_is_exclusive(pagenr << PAGE_SHIFT)) return 0; diff --git a/trunk/arch/x86/mm/init_32.c b/trunk/arch/x86/mm/init_32.c index 4f04db150027..575d86f85ce4 100644 --- a/trunk/arch/x86/mm/init_32.c +++ b/trunk/arch/x86/mm/init_32.c @@ -445,10 +445,10 @@ static inline void permanent_kmaps_init(pgd_t *pgd_base) } #endif /* CONFIG_HIGHMEM */ -void __init native_pagetable_init(void) +void __init native_pagetable_setup_start(pgd_t *base) { unsigned long pfn, va; - pgd_t *pgd, *base = swapper_pg_dir; + pgd_t *pgd; pud_t *pud; pmd_t *pmd; pte_t *pte; @@ -475,7 +475,10 @@ void __init native_pagetable_init(void) pte_clear(NULL, va, pte); } paravirt_alloc_pmd(&init_mm, __pa(base) >> PAGE_SHIFT); - paging_init(); +} + +void __init native_pagetable_setup_done(pgd_t *base) +{ } /* @@ -490,7 +493,7 @@ void __init native_pagetable_init(void) * If we're booting paravirtualized under a hypervisor, then there are * more options: we may already be running PAE, and the pagetable may * or may not be based in swapper_pg_dir. In any case, - * paravirt_pagetable_init() will set up swapper_pg_dir + * paravirt_pagetable_setup_start() will set up swapper_pg_dir * appropriately for the rest of the initialization to work. * * In general, pagetable_init() assumes that the pagetable may already diff --git a/trunk/arch/x86/mm/pageattr.c b/trunk/arch/x86/mm/pageattr.c index a718e0d23503..931930a96160 100644 --- a/trunk/arch/x86/mm/pageattr.c +++ b/trunk/arch/x86/mm/pageattr.c @@ -919,11 +919,13 @@ static int change_page_attr_set_clr(unsigned long *addr, int numpages, /* * On success we use clflush, when the CPU supports it to - * avoid the wbindv. If the CPU does not support it and in the - * error case we fall back to cpa_flush_all (which uses - * wbindv): + * avoid the wbindv. If the CPU does not support it, in the + * error case, and during early boot (for EFI) we fall back + * to cpa_flush_all (which uses wbinvd): */ - if (!ret && cpu_has_clflush) { + if (early_boot_irqs_disabled) + __cpa_flush_all((void *)(long)cache); + else if (!ret && cpu_has_clflush) { if (cpa.flags & (CPA_PAGES_ARRAY | CPA_ARRAY)) { cpa_flush_array(addr, numpages, cache, cpa.flags, pages); diff --git a/trunk/arch/x86/mm/srat.c b/trunk/arch/x86/mm/srat.c index 4ddf497ca65b..4599c3e8bcb6 100644 --- a/trunk/arch/x86/mm/srat.c +++ b/trunk/arch/x86/mm/srat.c @@ -142,23 +142,23 @@ static inline int save_add_info(void) {return 0;} #endif /* Callback for parsing of the Proximity Domain <-> Memory Area mappings */ -int __init +void __init acpi_numa_memory_affinity_init(struct acpi_srat_mem_affinity *ma) { u64 start, end; int node, pxm; if (srat_disabled()) - return -1; + return; if (ma->header.length != sizeof(struct acpi_srat_mem_affinity)) { bad_srat(); - return -1; + return; } if ((ma->flags & ACPI_SRAT_MEM_ENABLED) == 0) - return -1; + return; if ((ma->flags & ACPI_SRAT_MEM_HOT_PLUGGABLE) && !save_add_info()) - return -1; + return; start = ma->base_address; end = start + ma->length; pxm = ma->proximity_domain; @@ -168,12 +168,12 @@ acpi_numa_memory_affinity_init(struct acpi_srat_mem_affinity *ma) if (node < 0) { printk(KERN_ERR "SRAT: Too many proximity domains.\n"); bad_srat(); - return -1; + return; } if (numa_add_memblk(node, start, end) < 0) { bad_srat(); - return -1; + return; } node_set(node, numa_nodes_parsed); @@ -181,7 +181,6 @@ acpi_numa_memory_affinity_init(struct acpi_srat_mem_affinity *ma) printk(KERN_INFO "SRAT: Node %u PXM %u [mem %#010Lx-%#010Lx]\n", node, pxm, (unsigned long long) start, (unsigned long long) end - 1); - return 0; } void __init acpi_numa_arch_fixup(void) {} diff --git a/trunk/arch/x86/mm/tlb.c b/trunk/arch/x86/mm/tlb.c index 0777f042e400..613cd83e8c0c 100644 --- a/trunk/arch/x86/mm/tlb.c +++ b/trunk/arch/x86/mm/tlb.c @@ -98,8 +98,6 @@ static void flush_tlb_func(void *info) { struct flush_tlb_info *f = info; - inc_irq_stat(irq_tlb_count); - if (f->flush_mm != this_cpu_read(cpu_tlbstate.active_mm)) return; @@ -322,7 +320,7 @@ static ssize_t tlbflush_write_file(struct file *file, if (kstrtos8(buf, 0, &shift)) return -EINVAL; - if (shift < -1 || shift >= BITS_PER_LONG) + if (shift > 64) return -EINVAL; tlb_flushall_shift = shift; diff --git a/trunk/arch/x86/pci/acpi.c b/trunk/arch/x86/pci/acpi.c index 192397c98606..505acdd6d600 100644 --- a/trunk/arch/x86/pci/acpi.c +++ b/trunk/arch/x86/pci/acpi.c @@ -305,6 +305,7 @@ setup_resource(struct acpi_resource *acpi_res, void *data) res->flags = flags; res->start = start; res->end = end; + res->child = NULL; if (!pci_use_crs) { dev_printk(KERN_DEBUG, &info->bridge->dev, @@ -433,7 +434,7 @@ probe_pci_root_info(struct pci_root_info *info, struct acpi_device *device, size = sizeof(*info->res) * info->res_num; info->res_num = 0; - info->res = kzalloc(size, GFP_KERNEL); + info->res = kmalloc(size, GFP_KERNEL); if (!info->res) return; diff --git a/trunk/arch/x86/pci/mmconfig-shared.c b/trunk/arch/x86/pci/mmconfig-shared.c index 704b9ec043d7..937bcece7006 100644 --- a/trunk/arch/x86/pci/mmconfig-shared.c +++ b/trunk/arch/x86/pci/mmconfig-shared.c @@ -585,7 +585,7 @@ static int __init pci_parse_mcfg(struct acpi_table_header *header) while (i >= sizeof(struct acpi_mcfg_allocation)) { entries++; i -= sizeof(struct acpi_mcfg_allocation); - } + }; if (entries == 0) { pr_err(PREFIX "MMCONFIG has no entries\n"); return -ENODEV; diff --git a/trunk/arch/x86/pci/visws.c b/trunk/arch/x86/pci/visws.c index 3e6d2a6db866..6f2f8eeed171 100644 --- a/trunk/arch/x86/pci/visws.c +++ b/trunk/arch/x86/pci/visws.c @@ -62,6 +62,11 @@ static int __init visws_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) return irq; } +void __init pcibios_update_irq(struct pci_dev *dev, int irq) +{ + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq); +} + int __init pci_visws_init(void) { pcibios_enable_irq = &pci_visws_enable_irq; diff --git a/trunk/arch/x86/platform/efi/Makefile b/trunk/arch/x86/platform/efi/Makefile index 6db1cc4c7534..73b8be0f3675 100644 --- a/trunk/arch/x86/platform/efi/Makefile +++ b/trunk/arch/x86/platform/efi/Makefile @@ -1,2 +1 @@ obj-$(CONFIG_EFI) += efi.o efi_$(BITS).o efi_stub_$(BITS).o -obj-$(CONFIG_ACPI_BGRT) += efi-bgrt.o diff --git a/trunk/arch/x86/platform/efi/efi-bgrt.c b/trunk/arch/x86/platform/efi/efi-bgrt.c deleted file mode 100644 index f6a0c1b8e518..000000000000 --- a/trunk/arch/x86/platform/efi/efi-bgrt.c +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright 2012 Intel Corporation - * Author: Josh Triplett - * - * Based on the bgrt driver: - * Copyright 2012 Red Hat, Inc - * Author: Matthew Garrett - * - * 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 -#include -#include -#include - -struct acpi_table_bgrt *bgrt_tab; -void *bgrt_image; -size_t bgrt_image_size; - -struct bmp_header { - u16 id; - u32 size; -} __packed; - -void efi_bgrt_init(void) -{ - acpi_status status; - void __iomem *image; - bool ioremapped = false; - struct bmp_header bmp_header; - - if (acpi_disabled) - return; - - status = acpi_get_table("BGRT", 0, - (struct acpi_table_header **)&bgrt_tab); - if (ACPI_FAILURE(status)) - return; - - if (bgrt_tab->version != 1) - return; - if (bgrt_tab->image_type != 0 || !bgrt_tab->image_address) - return; - - image = efi_lookup_mapped_addr(bgrt_tab->image_address); - if (!image) { - image = ioremap(bgrt_tab->image_address, sizeof(bmp_header)); - ioremapped = true; - if (!image) - return; - } - - memcpy_fromio(&bmp_header, image, sizeof(bmp_header)); - if (ioremapped) - iounmap(image); - bgrt_image_size = bmp_header.size; - - bgrt_image = kmalloc(bgrt_image_size, GFP_KERNEL); - if (!bgrt_image) - return; - - if (ioremapped) { - image = ioremap(bgrt_tab->image_address, bmp_header.size); - if (!image) { - kfree(bgrt_image); - bgrt_image = NULL; - return; - } - } - - memcpy_fromio(bgrt_image, image, bgrt_image_size); - if (ioremapped) - iounmap(image); -} diff --git a/trunk/arch/x86/platform/efi/efi.c b/trunk/arch/x86/platform/efi/efi.c index aded2a91162a..2dc29f51e75a 100644 --- a/trunk/arch/x86/platform/efi/efi.c +++ b/trunk/arch/x86/platform/efi/efi.c @@ -31,7 +31,6 @@ #include #include #include -#include #include #include #include @@ -235,22 +234,7 @@ static efi_status_t __init phys_efi_set_virtual_address_map( return status; } -static efi_status_t __init phys_efi_get_time(efi_time_t *tm, - efi_time_cap_t *tc) -{ - unsigned long flags; - efi_status_t status; - - spin_lock_irqsave(&rtc_lock, flags); - efi_call_phys_prelog(); - status = efi_call_phys2(efi_phys.get_time, virt_to_phys(tm), - virt_to_phys(tc)); - efi_call_phys_epilog(); - spin_unlock_irqrestore(&rtc_lock, flags); - return status; -} - -int efi_set_rtc_mmss(unsigned long nowtime) +static int efi_set_rtc_mmss(unsigned long nowtime) { int real_seconds, real_minutes; efi_status_t status; @@ -279,7 +263,7 @@ int efi_set_rtc_mmss(unsigned long nowtime) return 0; } -unsigned long efi_get_time(void) +static unsigned long efi_get_time(void) { efi_status_t status; efi_time_t eft; @@ -420,21 +404,10 @@ void __init efi_reserve_boot_services(void) } } -static void __init efi_unmap_memmap(void) -{ - if (memmap.map) { - early_iounmap(memmap.map, memmap.nr_map * memmap.desc_size); - memmap.map = NULL; - } -} - -void __init efi_free_boot_services(void) +static void __init efi_free_boot_services(void) { void *p; - if (!efi_native) - return; - for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { efi_memory_desc_t *md = p; unsigned long long start = md->phys_addr; @@ -450,8 +423,6 @@ void __init efi_free_boot_services(void) free_bootmem_late(start, size); } - - efi_unmap_memmap(); } static int __init efi_systab_init(void *phys) @@ -635,18 +606,13 @@ static int __init efi_runtime_init(void) } /* * We will only need *early* access to the following - * two EFI runtime services before set_virtual_address_map + * EFI runtime service before set_virtual_address_map * is invoked. */ - efi_phys.get_time = (efi_get_time_t *)runtime->get_time; efi_phys.set_virtual_address_map = (efi_set_virtual_address_map_t *) runtime->set_virtual_address_map; - /* - * Make efi_get_time can be called before entering - * virtual mode. - */ - efi.get_time = phys_efi_get_time; + early_iounmap(runtime, sizeof(efi_runtime_services_t)); return 0; @@ -734,23 +700,16 @@ void __init efi_init(void) efi_enabled = 0; return; } -#ifdef CONFIG_X86_32 if (efi_native) { x86_platform.get_wallclock = efi_get_time; x86_platform.set_wallclock = efi_set_rtc_mmss; } -#endif #if EFI_DEBUG print_efi_memmap(); #endif } -void __init efi_late_init(void) -{ - efi_bgrt_init(); -} - void __init efi_set_executable(efi_memory_desc_t *md, bool executable) { u64 addr, npages; @@ -782,34 +741,6 @@ static void __init runtime_code_page_mkexec(void) } } -/* - * We can't ioremap data in EFI boot services RAM, because we've already mapped - * it as RAM. So, look it up in the existing EFI memory map instead. Only - * callable after efi_enter_virtual_mode and before efi_free_boot_services. - */ -void __iomem *efi_lookup_mapped_addr(u64 phys_addr) -{ - void *p; - if (WARN_ON(!memmap.map)) - return NULL; - for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { - efi_memory_desc_t *md = p; - u64 size = md->num_pages << EFI_PAGE_SHIFT; - u64 end = md->phys_addr + size; - if (!(md->attribute & EFI_MEMORY_RUNTIME) && - md->type != EFI_BOOT_SERVICES_CODE && - md->type != EFI_BOOT_SERVICES_DATA) - continue; - if (!md->virt_addr) - continue; - if (phys_addr >= md->phys_addr && phys_addr < end) { - phys_addr += md->virt_addr - md->phys_addr; - return (__force void __iomem *)(unsigned long)phys_addr; - } - } - return NULL; -} - /* * This function will switch the EFI runtime services to virtual mode. * Essentially, look through the EFI memmap and map every region that @@ -834,10 +765,8 @@ void __init efi_enter_virtual_mode(void) * non-native EFI */ - if (!efi_native) { - efi_unmap_memmap(); - return; - } + if (!efi_native) + goto out; /* Merge contiguous regions of the same type and attribute */ for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { @@ -926,13 +855,19 @@ void __init efi_enter_virtual_mode(void) panic("EFI call to SetVirtualAddressMap() failed!"); } + /* + * Thankfully, it does seem that no runtime services other than + * SetVirtualAddressMap() will touch boot services code, so we can + * get rid of it all at this point + */ + efi_free_boot_services(); + /* * Now that EFI is in virtual mode, update the function * pointers in the runtime service table to the new virtual addresses. * * Call EFI services through wrapper functions. */ - efi.runtime_version = efi_systab.fw_revision; efi.get_time = virt_efi_get_time; efi.set_time = virt_efi_set_time; efi.get_wakeup_time = virt_efi_get_wakeup_time; @@ -949,6 +884,9 @@ void __init efi_enter_virtual_mode(void) if (__supported_pte_mask & _PAGE_NX) runtime_code_page_mkexec(); +out: + early_iounmap(memmap.map, memmap.nr_map * memmap.desc_size); + memmap.map = NULL; kfree(new_memmap); } diff --git a/trunk/arch/x86/realmode/rm/Makefile b/trunk/arch/x86/realmode/rm/Makefile index 88692871823f..b2d534cab25f 100644 --- a/trunk/arch/x86/realmode/rm/Makefile +++ b/trunk/arch/x86/realmode/rm/Makefile @@ -72,7 +72,7 @@ KBUILD_CFLAGS := $(LINUXINCLUDE) -m32 -g -Os -D_SETUP -D__KERNEL__ -D_WAKEUP \ -Wall -Wstrict-prototypes \ -march=i386 -mregparm=3 \ -include $(srctree)/$(src)/../../boot/code16gcc.h \ - -fno-strict-aliasing -fomit-frame-pointer -fno-pic \ + -fno-strict-aliasing -fomit-frame-pointer \ $(call cc-option, -ffreestanding) \ $(call cc-option, -fno-toplevel-reorder,\ $(call cc-option, -fno-unit-at-a-time)) \ diff --git a/trunk/arch/x86/syscalls/syscall_64.tbl b/trunk/arch/x86/syscalls/syscall_64.tbl index a582bfed95bb..51171aeff0dc 100644 --- a/trunk/arch/x86/syscalls/syscall_64.tbl +++ b/trunk/arch/x86/syscalls/syscall_64.tbl @@ -60,8 +60,8 @@ 51 common getsockname sys_getsockname 52 common getpeername sys_getpeername 53 common socketpair sys_socketpair -54 64 setsockopt sys_setsockopt -55 64 getsockopt sys_getsockopt +54 common setsockopt sys_setsockopt +55 common getsockopt sys_getsockopt 56 common clone stub_clone 57 common fork stub_fork 58 common vfork stub_vfork @@ -318,7 +318,7 @@ 309 common getcpu sys_getcpu 310 64 process_vm_readv sys_process_vm_readv 311 64 process_vm_writev sys_process_vm_writev -312 common kcmp sys_kcmp +312 64 kcmp sys_kcmp # # x32-specific system call numbers start at 512 to avoid cache impact @@ -353,5 +353,3 @@ 538 x32 sendmmsg compat_sys_sendmmsg 539 x32 process_vm_readv compat_sys_process_vm_readv 540 x32 process_vm_writev compat_sys_process_vm_writev -541 x32 setsockopt compat_sys_setsockopt -542 x32 getsockopt compat_sys_getsockopt diff --git a/trunk/arch/x86/um/Kconfig b/trunk/arch/x86/um/Kconfig index aeaff8bef2f1..9926e11a772d 100644 --- a/trunk/arch/x86/um/Kconfig +++ b/trunk/arch/x86/um/Kconfig @@ -21,7 +21,6 @@ config 64BIT config X86_32 def_bool !64BIT select HAVE_AOUT - select ARCH_WANT_IPC_PARSE_VERSION config X86_64 def_bool 64BIT diff --git a/trunk/arch/x86/um/shared/sysdep/kernel-offsets.h b/trunk/arch/x86/um/shared/sysdep/kernel-offsets.h index 46a9df99f3c5..5868526b5eef 100644 --- a/trunk/arch/x86/um/shared/sysdep/kernel-offsets.h +++ b/trunk/arch/x86/um/shared/sysdep/kernel-offsets.h @@ -7,6 +7,9 @@ #define DEFINE(sym, val) \ asm volatile("\n->" #sym " %0 " #val : : "i" (val)) +#define STR(x) #x +#define DEFINE_STR(sym, val) asm volatile("\n->" #sym " " STR(val) " " #val: : ) + #define BLANK() asm volatile("\n->" : : ) #define OFFSET(sym, str, mem) \ diff --git a/trunk/arch/x86/um/shared/sysdep/syscalls.h b/trunk/arch/x86/um/shared/sysdep/syscalls.h index ca255a805ed9..bd9a89b67e41 100644 --- a/trunk/arch/x86/um/shared/sysdep/syscalls.h +++ b/trunk/arch/x86/um/shared/sysdep/syscalls.h @@ -1,5 +1,3 @@ -extern long sys_clone(unsigned long clone_flags, unsigned long newsp, - void __user *parent_tid, void __user *child_tid); #ifdef __i386__ #include "syscalls_32.h" #else diff --git a/trunk/arch/x86/um/signal.c b/trunk/arch/x86/um/signal.c index ba7363ecf896..a508cea13503 100644 --- a/trunk/arch/x86/um/signal.c +++ b/trunk/arch/x86/um/signal.c @@ -416,6 +416,9 @@ int setup_signal_stack_sc(unsigned long stack_top, int sig, PT_REGS_AX(regs) = (unsigned long) sig; PT_REGS_DX(regs) = (unsigned long) 0; PT_REGS_CX(regs) = (unsigned long) 0; + + if ((current->ptrace & PT_DTRACE) && (current->ptrace & PT_PTRACED)) + ptrace_notify(SIGTRAP); return 0; } @@ -463,6 +466,9 @@ int setup_signal_stack_si(unsigned long stack_top, int sig, PT_REGS_AX(regs) = (unsigned long) sig; PT_REGS_DX(regs) = (unsigned long) &frame->info; PT_REGS_CX(regs) = (unsigned long) &frame->uc; + + if ((current->ptrace & PT_DTRACE) && (current->ptrace & PT_PTRACED)) + ptrace_notify(SIGTRAP); return 0; } diff --git a/trunk/arch/x86/um/sys_call_table_32.c b/trunk/arch/x86/um/sys_call_table_32.c index b5408cecac6c..68d1dc91b37b 100644 --- a/trunk/arch/x86/um/sys_call_table_32.c +++ b/trunk/arch/x86/um/sys_call_table_32.c @@ -28,7 +28,7 @@ #define ptregs_execve sys_execve #define ptregs_iopl sys_iopl #define ptregs_vm86old sys_vm86old -#define ptregs_clone i386_clone +#define ptregs_clone sys_clone #define ptregs_vm86 sys_vm86 #define ptregs_sigaltstack sys_sigaltstack #define ptregs_vfork sys_vfork diff --git a/trunk/arch/x86/um/syscalls_32.c b/trunk/arch/x86/um/syscalls_32.c index db444c7218fe..b853e8600b9d 100644 --- a/trunk/arch/x86/um/syscalls_32.c +++ b/trunk/arch/x86/um/syscalls_32.c @@ -3,23 +3,36 @@ * Licensed under the GPL */ -#include -#include +#include "linux/sched.h" +#include "linux/shm.h" +#include "linux/ipc.h" +#include "linux/syscalls.h" +#include "asm/mman.h" +#include "asm/uaccess.h" +#include "asm/unistd.h" /* * The prototype on i386 is: * - * int clone(int flags, void * child_stack, int * parent_tidptr, struct user_desc * newtls + * int clone(int flags, void * child_stack, int * parent_tidptr, struct user_desc * newtls, int * child_tidptr) * * and the "newtls" arg. on i386 is read by copy_thread directly from the * register saved on the stack. */ -long i386_clone(unsigned long clone_flags, unsigned long newsp, - int __user *parent_tid, void *newtls, int __user *child_tid) +long sys_clone(unsigned long clone_flags, unsigned long newsp, + int __user *parent_tid, void *newtls, int __user *child_tid) { - return sys_clone(clone_flags, newsp, parent_tid, child_tid); -} + long ret; + + if (!newsp) + newsp = UPT_SP(¤t->thread.regs.regs); + current->thread.forking = 1; + ret = do_fork(clone_flags, newsp, ¤t->thread.regs, 0, parent_tid, + child_tid); + current->thread.forking = 0; + return ret; +} long sys_sigaction(int sig, const struct old_sigaction __user *act, struct old_sigaction __user *oact) diff --git a/trunk/arch/x86/um/syscalls_64.c b/trunk/arch/x86/um/syscalls_64.c index adb08eb5c22a..f3d82bb6e15a 100644 --- a/trunk/arch/x86/um/syscalls_64.c +++ b/trunk/arch/x86/um/syscalls_64.c @@ -5,9 +5,12 @@ * Licensed under the GPL */ -#include -#include /* XXX This should get the constants from libc */ -#include +#include "linux/linkage.h" +#include "linux/personality.h" +#include "linux/utsname.h" +#include "asm/prctl.h" /* XXX This should get the constants from libc */ +#include "asm/uaccess.h" +#include "os.h" long arch_prctl(struct task_struct *task, int code, unsigned long __user *addr) { @@ -76,6 +79,20 @@ long sys_arch_prctl(int code, unsigned long addr) return arch_prctl(current, code, (unsigned long __user *) addr); } +long sys_clone(unsigned long clone_flags, unsigned long newsp, + void __user *parent_tid, void __user *child_tid) +{ + long ret; + + if (!newsp) + newsp = UPT_SP(¤t->thread.regs.regs); + current->thread.forking = 1; + ret = do_fork(clone_flags, newsp, ¤t->thread.regs, 0, parent_tid, + child_tid); + current->thread.forking = 0; + return ret; +} + void arch_switch_to(struct task_struct *to) { if ((to->thread.arch.fs == 0) || (to->mm == NULL)) diff --git a/trunk/arch/x86/xen/enlighten.c b/trunk/arch/x86/xen/enlighten.c index 1fbe75a95f15..bf4bda6d3e9a 100644 --- a/trunk/arch/x86/xen/enlighten.c +++ b/trunk/arch/x86/xen/enlighten.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -1452,10 +1453,6 @@ asmlinkage void __init xen_start_kernel(void) pci_request_acs(); xen_acpi_sleep_register(); - - /* Avoid searching for BIOS MP tables */ - x86_init.mpparse.find_smp_config = x86_init_noop; - x86_init.mpparse.get_smp_config = x86_init_uint_noop; } #ifdef CONFIG_PCI /* PCI BIOS service won't work from a PV guest. */ @@ -1473,38 +1470,130 @@ asmlinkage void __init xen_start_kernel(void) #endif } -void __ref xen_hvm_init_shared_info(void) +#ifdef CONFIG_XEN_PVHVM +/* + * The pfn containing the shared_info is located somewhere in RAM. This + * will cause trouble if the current kernel is doing a kexec boot into a + * new kernel. The new kernel (and its startup code) can not know where + * the pfn is, so it can not reserve the page. The hypervisor will + * continue to update the pfn, and as a result memory corruption occours + * in the new kernel. + * + * One way to work around this issue is to allocate a page in the + * xen-platform pci device's BAR memory range. But pci init is done very + * late and the shared_info page is already in use very early to read + * the pvclock. So moving the pfn from RAM to MMIO is racy because some + * code paths on other vcpus could access the pfn during the small + * window when the old pfn is moved to the new pfn. There is even a + * small window were the old pfn is not backed by a mfn, and during that + * time all reads return -1. + * + * Because it is not known upfront where the MMIO region is located it + * can not be used right from the start in xen_hvm_init_shared_info. + * + * To minimise trouble the move of the pfn is done shortly before kexec. + * This does not eliminate the race because all vcpus are still online + * when the syscore_ops will be called. But hopefully there is no work + * pending at this point in time. Also the syscore_op is run last which + * reduces the risk further. + */ + +static struct shared_info *xen_hvm_shared_info; + +static void xen_hvm_connect_shared_info(unsigned long pfn) { - int cpu; struct xen_add_to_physmap xatp; - static struct shared_info *shared_info_page = 0; - if (!shared_info_page) - shared_info_page = (struct shared_info *) - extend_brk(PAGE_SIZE, PAGE_SIZE); xatp.domid = DOMID_SELF; xatp.idx = 0; xatp.space = XENMAPSPACE_shared_info; - xatp.gpfn = __pa(shared_info_page) >> PAGE_SHIFT; + xatp.gpfn = pfn; if (HYPERVISOR_memory_op(XENMEM_add_to_physmap, &xatp)) BUG(); - HYPERVISOR_shared_info = (struct shared_info *)shared_info_page; +} +static void xen_hvm_set_shared_info(struct shared_info *sip) +{ + int cpu; + + HYPERVISOR_shared_info = sip; /* xen_vcpu is a pointer to the vcpu_info struct in the shared_info * page, we use it in the event channel upcall and in some pvclock * related functions. We don't need the vcpu_info placement * optimizations because we don't use any pv_mmu or pv_irq op on * HVM. - * When xen_hvm_init_shared_info is run at boot time only vcpu 0 is - * online but xen_hvm_init_shared_info is run at resume time too and + * When xen_hvm_set_shared_info is run at boot time only vcpu 0 is + * online but xen_hvm_set_shared_info is run at resume time too and * in that case multiple vcpus might be online. */ for_each_online_cpu(cpu) { per_cpu(xen_vcpu, cpu) = &HYPERVISOR_shared_info->vcpu_info[cpu]; } } -#ifdef CONFIG_XEN_PVHVM +/* Reconnect the shared_info pfn to a mfn */ +void xen_hvm_resume_shared_info(void) +{ + xen_hvm_connect_shared_info(__pa(xen_hvm_shared_info) >> PAGE_SHIFT); +} + +#ifdef CONFIG_KEXEC +static struct shared_info *xen_hvm_shared_info_kexec; +static unsigned long xen_hvm_shared_info_pfn_kexec; + +/* Remember a pfn in MMIO space for kexec reboot */ +void __devinit xen_hvm_prepare_kexec(struct shared_info *sip, unsigned long pfn) +{ + xen_hvm_shared_info_kexec = sip; + xen_hvm_shared_info_pfn_kexec = pfn; +} + +static void xen_hvm_syscore_shutdown(void) +{ + struct xen_memory_reservation reservation = { + .domid = DOMID_SELF, + .nr_extents = 1, + }; + unsigned long prev_pfn; + int rc; + + if (!xen_hvm_shared_info_kexec) + return; + + prev_pfn = __pa(xen_hvm_shared_info) >> PAGE_SHIFT; + set_xen_guest_handle(reservation.extent_start, &prev_pfn); + + /* Move pfn to MMIO, disconnects previous pfn from mfn */ + xen_hvm_connect_shared_info(xen_hvm_shared_info_pfn_kexec); + + /* Update pointers, following hypercall is also a memory barrier */ + xen_hvm_set_shared_info(xen_hvm_shared_info_kexec); + + /* Allocate new mfn for previous pfn */ + do { + rc = HYPERVISOR_memory_op(XENMEM_populate_physmap, &reservation); + if (rc == 0) + msleep(123); + } while (rc == 0); + + /* Make sure the previous pfn is really connected to a (new) mfn */ + BUG_ON(rc != 1); +} + +static struct syscore_ops xen_hvm_syscore_ops = { + .shutdown = xen_hvm_syscore_shutdown, +}; +#endif + +/* Use a pfn in RAM, may move to MMIO before kexec. */ +static void __init xen_hvm_init_shared_info(void) +{ + /* Remember pointer for resume */ + xen_hvm_shared_info = extend_brk(PAGE_SIZE, PAGE_SIZE); + xen_hvm_connect_shared_info(__pa(xen_hvm_shared_info) >> PAGE_SHIFT); + xen_hvm_set_shared_info(xen_hvm_shared_info); +} + static void __init init_hvm_pv_info(void) { int major, minor; @@ -1555,6 +1644,9 @@ static void __init xen_hvm_guest_init(void) init_hvm_pv_info(); xen_hvm_init_shared_info(); +#ifdef CONFIG_KEXEC + register_syscore_ops(&xen_hvm_syscore_ops); +#endif if (xen_feature(XENFEAT_hvm_callback_vector)) xen_have_vector_callback = 1; diff --git a/trunk/arch/x86/xen/mmu.c b/trunk/arch/x86/xen/mmu.c index 7a769b7526cb..b65a76133f4f 100644 --- a/trunk/arch/x86/xen/mmu.c +++ b/trunk/arch/x86/xen/mmu.c @@ -1174,13 +1174,8 @@ static void xen_exit_mmap(struct mm_struct *mm) spin_unlock(&mm->page_table_lock); } -static void xen_post_allocator_init(void); - -static void __init xen_pagetable_init(void) +static void __init xen_pagetable_setup_start(pgd_t *base) { - paging_init(); - xen_setup_shared_info(); - xen_post_allocator_init(); } static __init void xen_mapping_pagetable_reserve(u64 start, u64 end) @@ -1197,6 +1192,14 @@ static __init void xen_mapping_pagetable_reserve(u64 start, u64 end) } } +static void xen_post_allocator_init(void); + +static void __init xen_pagetable_setup_done(pgd_t *base) +{ + xen_setup_shared_info(); + xen_post_allocator_init(); +} + static void xen_write_cr2(unsigned long cr2) { this_cpu_read(xen_vcpu)->arch.cr2 = cr2; @@ -1280,7 +1283,7 @@ static void xen_flush_tlb_others(const struct cpumask *cpus, cpumask_clear_cpu(smp_processor_id(), to_cpumask(args->mask)); args->op.cmd = MMUEXT_TLB_FLUSH_MULTI; - if (end != TLB_FLUSH_ALL && (end - start) <= PAGE_SIZE) { + if (start != TLB_FLUSH_ALL && (end - start) <= PAGE_SIZE) { args->op.cmd = MMUEXT_INVLPG_MULTI; args->op.arg1.linear_addr = start; } @@ -2065,7 +2068,8 @@ static const struct pv_mmu_ops xen_mmu_ops __initconst = { void __init xen_init_mmu_ops(void) { x86_init.mapping.pagetable_reserve = xen_mapping_pagetable_reserve; - x86_init.paging.pagetable_init = xen_pagetable_init; + x86_init.paging.pagetable_setup_start = xen_pagetable_setup_start; + x86_init.paging.pagetable_setup_done = xen_pagetable_setup_done; pv_mmu_ops = xen_mmu_ops; memset(dummy_mapping, 0xff, PAGE_SIZE); diff --git a/trunk/arch/x86/xen/p2m.c b/trunk/arch/x86/xen/p2m.c index 72213da605f5..64effdc6da94 100644 --- a/trunk/arch/x86/xen/p2m.c +++ b/trunk/arch/x86/xen/p2m.c @@ -194,13 +194,6 @@ RESERVE_BRK(p2m_mid_mfn, PAGE_SIZE * (MAX_DOMAIN_PAGES / (P2M_PER_PAGE * P2M_MID * boundary violation will require three middle nodes. */ RESERVE_BRK(p2m_mid_identity, PAGE_SIZE * 2 * 3); -/* When we populate back during bootup, the amount of pages can vary. The - * max we have is seen is 395979, but that does not mean it can't be more. - * Some machines can have 3GB I/O holes even. With early_can_reuse_p2m_middle - * it can re-use Xen provided mfn_list array, so we only need to allocate at - * most three P2M top nodes. */ -RESERVE_BRK(p2m_populated, PAGE_SIZE * 3); - static inline unsigned p2m_top_index(unsigned long pfn) { BUG_ON(pfn >= MAX_P2M_PFN); @@ -577,99 +570,12 @@ static bool __init early_alloc_p2m(unsigned long pfn) } return true; } - -/* - * Skim over the P2M tree looking at pages that are either filled with - * INVALID_P2M_ENTRY or with 1:1 PFNs. If found, re-use that page and - * replace the P2M leaf with a p2m_missing or p2m_identity. - * Stick the old page in the new P2M tree location. - */ -bool __init early_can_reuse_p2m_middle(unsigned long set_pfn, unsigned long set_mfn) -{ - unsigned topidx; - unsigned mididx; - unsigned ident_pfns; - unsigned inv_pfns; - unsigned long *p2m; - unsigned long *mid_mfn_p; - unsigned idx; - unsigned long pfn; - - /* We only look when this entails a P2M middle layer */ - if (p2m_index(set_pfn)) - return false; - - for (pfn = 0; pfn < MAX_DOMAIN_PAGES; pfn += P2M_PER_PAGE) { - topidx = p2m_top_index(pfn); - - if (!p2m_top[topidx]) - continue; - - if (p2m_top[topidx] == p2m_mid_missing) - continue; - - mididx = p2m_mid_index(pfn); - p2m = p2m_top[topidx][mididx]; - if (!p2m) - continue; - - if ((p2m == p2m_missing) || (p2m == p2m_identity)) - continue; - - if ((unsigned long)p2m == INVALID_P2M_ENTRY) - continue; - - ident_pfns = 0; - inv_pfns = 0; - for (idx = 0; idx < P2M_PER_PAGE; idx++) { - /* IDENTITY_PFNs are 1:1 */ - if (p2m[idx] == IDENTITY_FRAME(pfn + idx)) - ident_pfns++; - else if (p2m[idx] == INVALID_P2M_ENTRY) - inv_pfns++; - else - break; - } - if ((ident_pfns == P2M_PER_PAGE) || (inv_pfns == P2M_PER_PAGE)) - goto found; - } - return false; -found: - /* Found one, replace old with p2m_identity or p2m_missing */ - p2m_top[topidx][mididx] = (ident_pfns ? p2m_identity : p2m_missing); - /* And the other for save/restore.. */ - mid_mfn_p = p2m_top_mfn_p[topidx]; - /* NOTE: Even if it is a p2m_identity it should still be point to - * a page filled with INVALID_P2M_ENTRY entries. */ - mid_mfn_p[mididx] = virt_to_mfn(p2m_missing); - - /* Reset where we want to stick the old page in. */ - topidx = p2m_top_index(set_pfn); - mididx = p2m_mid_index(set_pfn); - - /* This shouldn't happen */ - if (WARN_ON(p2m_top[topidx] == p2m_mid_missing)) - early_alloc_p2m(set_pfn); - - if (WARN_ON(p2m_top[topidx][mididx] != p2m_missing)) - return false; - - p2m_init(p2m); - p2m_top[topidx][mididx] = p2m; - mid_mfn_p = p2m_top_mfn_p[topidx]; - mid_mfn_p[mididx] = virt_to_mfn(p2m); - - return true; -} bool __init early_set_phys_to_machine(unsigned long pfn, unsigned long mfn) { if (unlikely(!__set_phys_to_machine(pfn, mfn))) { if (!early_alloc_p2m(pfn)) return false; - if (early_can_reuse_p2m_middle(pfn, mfn)) - return __set_phys_to_machine(pfn, mfn); - if (!early_alloc_p2m_middle(pfn, false /* boundary crossover OK!*/)) return false; @@ -828,6 +734,9 @@ int m2p_add_override(unsigned long mfn, struct page *page, xen_mc_issue(PARAVIRT_LAZY_MMU); } + /* let's use dev_bus_addr to record the old mfn instead */ + kmap_op->dev_bus_addr = page->index; + page->index = (unsigned long) kmap_op; } spin_lock_irqsave(&m2p_override_lock, flags); list_add(&page->lru, &m2p_overrides[mfn_hash(mfn)]); @@ -854,8 +763,7 @@ int m2p_add_override(unsigned long mfn, struct page *page, return 0; } EXPORT_SYMBOL_GPL(m2p_add_override); -int m2p_remove_override(struct page *page, - struct gnttab_map_grant_ref *kmap_op) +int m2p_remove_override(struct page *page, bool clear_pte) { unsigned long flags; unsigned long mfn; @@ -885,8 +793,10 @@ int m2p_remove_override(struct page *page, WARN_ON(!PagePrivate(page)); ClearPagePrivate(page); - set_phys_to_machine(pfn, page->index); - if (kmap_op != NULL) { + if (clear_pte) { + struct gnttab_map_grant_ref *map_op = + (struct gnttab_map_grant_ref *) page->index; + set_phys_to_machine(pfn, map_op->dev_bus_addr); if (!PageHighMem(page)) { struct multicall_space mcs; struct gnttab_unmap_grant_ref *unmap_op; @@ -898,13 +808,13 @@ int m2p_remove_override(struct page *page, * issued. In this case handle is going to -1 because * it hasn't been modified yet. */ - if (kmap_op->handle == -1) + if (map_op->handle == -1) xen_mc_flush(); /* - * Now if kmap_op->handle is negative it means that the + * Now if map_op->handle is negative it means that the * hypercall actually returned an error. */ - if (kmap_op->handle == GNTST_general_error) { + if (map_op->handle == GNTST_general_error) { printk(KERN_WARNING "m2p_remove_override: " "pfn %lx mfn %lx, failed to modify kernel mappings", pfn, mfn); @@ -914,8 +824,8 @@ int m2p_remove_override(struct page *page, mcs = xen_mc_entry( sizeof(struct gnttab_unmap_grant_ref)); unmap_op = mcs.args; - unmap_op->host_addr = kmap_op->host_addr; - unmap_op->handle = kmap_op->handle; + unmap_op->host_addr = map_op->host_addr; + unmap_op->handle = map_op->handle; unmap_op->dev_bus_addr = 0; MULTI_grant_table_op(mcs.mc, @@ -926,9 +836,10 @@ int m2p_remove_override(struct page *page, set_pte_at(&init_mm, address, ptep, pfn_pte(pfn, PAGE_KERNEL)); __flush_tlb_single(address); - kmap_op->host_addr = 0; + map_op->host_addr = 0; } - } + } else + set_phys_to_machine(pfn, page->index); /* p2m(m2p(mfn)) == FOREIGN_FRAME(mfn): the mfn is already present * somewhere in this domain, even before being added to the diff --git a/trunk/arch/x86/xen/setup.c b/trunk/arch/x86/xen/setup.c index e2d62d697b5d..ead85576d54a 100644 --- a/trunk/arch/x86/xen/setup.c +++ b/trunk/arch/x86/xen/setup.c @@ -17,7 +17,6 @@ #include #include #include -#include #include #include @@ -79,16 +78,9 @@ static void __init xen_add_extra_mem(u64 start, u64 size) memblock_reserve(start, size); xen_max_p2m_pfn = PFN_DOWN(start + size); - for (pfn = PFN_DOWN(start); pfn < xen_max_p2m_pfn; pfn++) { - unsigned long mfn = pfn_to_mfn(pfn); - - if (WARN(mfn == pfn, "Trying to over-write 1-1 mapping (pfn: %lx)\n", pfn)) - continue; - WARN(mfn != INVALID_P2M_ENTRY, "Trying to remove %lx which has %lx mfn!\n", - pfn, mfn); + for (pfn = PFN_DOWN(start); pfn <= xen_max_p2m_pfn; pfn++) __set_phys_to_machine(pfn, INVALID_P2M_ENTRY); - } } static unsigned long __init xen_do_chunk(unsigned long start, @@ -545,7 +537,4 @@ void __init xen_arch_setup(void) disable_cpufreq(); WARN_ON(set_pm_idle_to_default()); fiddle_vdso(); -#ifdef CONFIG_NUMA - numa_off = 1; -#endif } diff --git a/trunk/arch/x86/xen/smp.c b/trunk/arch/x86/xen/smp.c index 353c50f18702..f58dca7a6e52 100644 --- a/trunk/arch/x86/xen/smp.c +++ b/trunk/arch/x86/xen/smp.c @@ -377,8 +377,7 @@ static int __cpuinit xen_cpu_up(unsigned int cpu, struct task_struct *idle) return rc; if (num_online_cpus() == 1) - /* Just in case we booted with a single CPU. */ - alternatives_enable_smp(); + alternatives_smp_switch(1); rc = xen_smp_intr_init(cpu); if (rc) @@ -425,6 +424,9 @@ static void xen_cpu_die(unsigned int cpu) unbind_from_irqhandler(per_cpu(xen_irq_work, cpu), NULL); xen_uninit_lock_cpu(cpu); xen_teardown_timer(cpu); + + if (num_online_cpus() == 1) + alternatives_smp_switch(0); } static void __cpuinit xen_play_dead(void) /* used only with HOTPLUG_CPU */ diff --git a/trunk/arch/x86/xen/suspend.c b/trunk/arch/x86/xen/suspend.c index 45329c8c226e..ae8a00c39de4 100644 --- a/trunk/arch/x86/xen/suspend.c +++ b/trunk/arch/x86/xen/suspend.c @@ -30,7 +30,7 @@ void xen_arch_hvm_post_suspend(int suspend_cancelled) { #ifdef CONFIG_XEN_PVHVM int cpu; - xen_hvm_init_shared_info(); + xen_hvm_resume_shared_info(); xen_callback_vector(); xen_unplug_emulated_devices(); if (xen_feature(XENFEAT_hvm_safe_pvclock)) { diff --git a/trunk/arch/x86/xen/xen-ops.h b/trunk/arch/x86/xen/xen-ops.h index 202d4c150154..1e4329e04e0f 100644 --- a/trunk/arch/x86/xen/xen-ops.h +++ b/trunk/arch/x86/xen/xen-ops.h @@ -41,7 +41,7 @@ void xen_enable_syscall(void); void xen_vcpu_restore(void); void xen_callback_vector(void); -void xen_hvm_init_shared_info(void); +void xen_hvm_resume_shared_info(void); void xen_unplug_emulated_devices(void); void __init xen_build_dynamic_phys_to_machine(void); diff --git a/trunk/arch/xtensa/Kconfig b/trunk/arch/xtensa/Kconfig index 744f5ee4ba41..8ed64cfae4ff 100644 --- a/trunk/arch/xtensa/Kconfig +++ b/trunk/arch/xtensa/Kconfig @@ -172,6 +172,24 @@ config CMDLINE source "mm/Kconfig" +config HOTPLUG + bool "Support for hot-pluggable devices" + help + Say Y here if you want to plug devices into your computer while + the system is running, and be able to use them quickly. In many + cases, the devices can likewise be unplugged at any time too. + + One well known example of this is PCMCIA- or PC-cards, credit-card + size devices such as network cards, modems or hard drives which are + plugged into slots found on all modern laptop computers. Another + example, used on modern desktops as well as laptops, is USB. + + Enable HOTPLUG and build a modular kernel. Get agent software + (from ) and install it. + Then your kernel will automatically call out to a user mode "policy + agent" (/sbin/hotplug) to load modules and set up software needed + to use devices as you hotplug them. + source "drivers/pcmcia/Kconfig" source "drivers/pci/hotplug/Kconfig" diff --git a/trunk/arch/xtensa/kernel/pci.c b/trunk/arch/xtensa/kernel/pci.c index 54354de38a70..69759e9cb3ea 100644 --- a/trunk/arch/xtensa/kernel/pci.c +++ b/trunk/arch/xtensa/kernel/pci.c @@ -210,6 +210,14 @@ void pcibios_set_master(struct pci_dev *dev) /* No special bus mastering setup handling */ } +/* the next one is stolen from the alpha port... */ + +void __init +pcibios_update_irq(struct pci_dev *dev, int irq) +{ + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq); +} + int pcibios_enable_device(struct pci_dev *dev, int mask) { u16 cmd, old_cmd; diff --git a/trunk/arch/xtensa/kernel/process.c b/trunk/arch/xtensa/kernel/process.c index bc44311aa18c..2c8d6a3d250a 100644 --- a/trunk/arch/xtensa/kernel/process.c +++ b/trunk/arch/xtensa/kernel/process.c @@ -31,7 +31,6 @@ #include #include #include -#include #include #include @@ -111,10 +110,8 @@ void cpu_idle(void) /* endless idle loop with no priority at all */ while (1) { - rcu_idle_enter(); while (!need_resched()) platform_idle(); - rcu_idle_exit(); schedule_preempt_disabled(); } } diff --git a/trunk/arch/xtensa/platforms/iss/console.c b/trunk/arch/xtensa/platforms/iss/console.c index 2cd3d3a3400b..f9726f6afdf1 100644 --- a/trunk/arch/xtensa/platforms/iss/console.c +++ b/trunk/arch/xtensa/platforms/iss/console.c @@ -223,7 +223,6 @@ int __init rs_init(void) serial_driver->flags = TTY_DRIVER_REAL_RAW; tty_set_operations(serial_driver, &serial_ops); - tty_port_link_device(&serial_port, serial_driver, 0); if (tty_register_driver(serial_driver)) panic("Couldn't register serial driver\n"); diff --git a/trunk/block/blk-core.c b/trunk/block/blk-core.c index ee3cb3a5e278..4b4dbdfbca89 100644 --- a/trunk/block/blk-core.c +++ b/trunk/block/blk-core.c @@ -2254,11 +2254,9 @@ bool blk_update_request(struct request *req, int error, unsigned int nr_bytes) error_type = "I/O"; break; } - printk_ratelimited(KERN_ERR "end_request: %s error, dev %s, sector %llu\n", - error_type, req->rq_disk ? - req->rq_disk->disk_name : "?", - (unsigned long long)blk_rq_pos(req)); - + printk(KERN_ERR "end_request: %s error, dev %s, sector %llu\n", + error_type, req->rq_disk ? req->rq_disk->disk_name : "?", + (unsigned long long)blk_rq_pos(req)); } blk_account_io_completion(req, nr_bytes); diff --git a/trunk/block/blk-lib.c b/trunk/block/blk-lib.c index 19cc761cacb2..2b461b496a78 100644 --- a/trunk/block/blk-lib.c +++ b/trunk/block/blk-lib.c @@ -44,7 +44,6 @@ int blkdev_issue_discard(struct block_device *bdev, sector_t sector, struct request_queue *q = bdev_get_queue(bdev); int type = REQ_WRITE | REQ_DISCARD; unsigned int max_discard_sectors; - unsigned int granularity, alignment, mask; struct bio_batch bb; struct bio *bio; int ret = 0; @@ -55,20 +54,18 @@ int blkdev_issue_discard(struct block_device *bdev, sector_t sector, if (!blk_queue_discard(q)) return -EOPNOTSUPP; - /* Zero-sector (unknown) and one-sector granularities are the same. */ - granularity = max(q->limits.discard_granularity >> 9, 1U); - mask = granularity - 1; - alignment = (bdev_discard_alignment(bdev) >> 9) & mask; - /* * Ensure that max_discard_sectors is of the proper - * granularity, so that requests stay aligned after a split. + * granularity */ max_discard_sectors = min(q->limits.max_discard_sectors, UINT_MAX >> 9); - max_discard_sectors = round_down(max_discard_sectors, granularity); if (unlikely(!max_discard_sectors)) { /* Avoid infinite loop below. Being cautious never hurts. */ return -EOPNOTSUPP; + } else if (q->limits.discard_granularity) { + unsigned int disc_sects = q->limits.discard_granularity >> 9; + + max_discard_sectors &= ~(disc_sects - 1); } if (flags & BLKDEV_DISCARD_SECURE) { @@ -82,37 +79,25 @@ int blkdev_issue_discard(struct block_device *bdev, sector_t sector, bb.wait = &wait; while (nr_sects) { - unsigned int req_sects; - sector_t end_sect; - bio = bio_alloc(gfp_mask, 1); if (!bio) { ret = -ENOMEM; break; } - req_sects = min_t(sector_t, nr_sects, max_discard_sectors); - - /* - * If splitting a request, and the next starting sector would be - * misaligned, stop the discard at the previous aligned sector. - */ - end_sect = sector + req_sects; - if (req_sects < nr_sects && (end_sect & mask) != alignment) { - end_sect = - round_down(end_sect - alignment, granularity) - + alignment; - req_sects = end_sect - sector; - } - bio->bi_sector = sector; bio->bi_end_io = bio_batch_end_io; bio->bi_bdev = bdev; bio->bi_private = &bb; - bio->bi_size = req_sects << 9; - nr_sects -= req_sects; - sector = end_sect; + if (nr_sects > max_discard_sectors) { + bio->bi_size = max_discard_sectors << 9; + nr_sects -= max_discard_sectors; + sector += max_discard_sectors; + } else { + bio->bi_size = nr_sects << 9; + nr_sects = 0; + } atomic_inc(&bb.done); submit_bio(type, bio); diff --git a/trunk/block/blk-merge.c b/trunk/block/blk-merge.c index e76279e41162..160035f54882 100644 --- a/trunk/block/blk-merge.c +++ b/trunk/block/blk-merge.c @@ -110,49 +110,6 @@ static int blk_phys_contig_segment(struct request_queue *q, struct bio *bio, return 0; } -static void -__blk_segment_map_sg(struct request_queue *q, struct bio_vec *bvec, - struct scatterlist *sglist, struct bio_vec **bvprv, - struct scatterlist **sg, int *nsegs, int *cluster) -{ - - int nbytes = bvec->bv_len; - - if (*bvprv && *cluster) { - if ((*sg)->length + nbytes > queue_max_segment_size(q)) - goto new_segment; - - if (!BIOVEC_PHYS_MERGEABLE(*bvprv, bvec)) - goto new_segment; - if (!BIOVEC_SEG_BOUNDARY(q, *bvprv, bvec)) - goto new_segment; - - (*sg)->length += nbytes; - } else { -new_segment: - if (!*sg) - *sg = sglist; - else { - /* - * If the driver previously mapped a shorter - * list, we could see a termination bit - * prematurely unless it fully inits the sg - * table on each mapping. We KNOW that there - * must be more entries here or the driver - * would be buggy, so force clear the - * termination bit to avoid doing a full - * sg_init_table() in drivers for each command. - */ - (*sg)->page_link &= ~0x02; - *sg = sg_next(*sg); - } - - sg_set_page(*sg, bvec->bv_page, nbytes, bvec->bv_offset); - (*nsegs)++; - } - *bvprv = bvec; -} - /* * map a request to scatterlist, return number of sg entries setup. Caller * must make sure sg can hold rq->nr_phys_segments entries @@ -174,8 +131,41 @@ int blk_rq_map_sg(struct request_queue *q, struct request *rq, bvprv = NULL; sg = NULL; rq_for_each_segment(bvec, rq, iter) { - __blk_segment_map_sg(q, bvec, sglist, &bvprv, &sg, - &nsegs, &cluster); + int nbytes = bvec->bv_len; + + if (bvprv && cluster) { + if (sg->length + nbytes > queue_max_segment_size(q)) + goto new_segment; + + if (!BIOVEC_PHYS_MERGEABLE(bvprv, bvec)) + goto new_segment; + if (!BIOVEC_SEG_BOUNDARY(q, bvprv, bvec)) + goto new_segment; + + sg->length += nbytes; + } else { +new_segment: + if (!sg) + sg = sglist; + else { + /* + * If the driver previously mapped a shorter + * list, we could see a termination bit + * prematurely unless it fully inits the sg + * table on each mapping. We KNOW that there + * must be more entries here or the driver + * would be buggy, so force clear the + * termination bit to avoid doing a full + * sg_init_table() in drivers for each command. + */ + sg->page_link &= ~0x02; + sg = sg_next(sg); + } + + sg_set_page(sg, bvec->bv_page, nbytes, bvec->bv_offset); + nsegs++; + } + bvprv = bvec; } /* segments in rq */ @@ -209,43 +199,6 @@ int blk_rq_map_sg(struct request_queue *q, struct request *rq, } EXPORT_SYMBOL(blk_rq_map_sg); -/** - * blk_bio_map_sg - map a bio to a scatterlist - * @q: request_queue in question - * @bio: bio being mapped - * @sglist: scatterlist being mapped - * - * Note: - * Caller must make sure sg can hold bio->bi_phys_segments entries - * - * Will return the number of sg entries setup - */ -int blk_bio_map_sg(struct request_queue *q, struct bio *bio, - struct scatterlist *sglist) -{ - struct bio_vec *bvec, *bvprv; - struct scatterlist *sg; - int nsegs, cluster; - unsigned long i; - - nsegs = 0; - cluster = blk_queue_cluster(q); - - bvprv = NULL; - sg = NULL; - bio_for_each_segment(bvec, bio, i) { - __blk_segment_map_sg(q, bvec, sglist, &bvprv, &sg, - &nsegs, &cluster); - } /* segments in bio */ - - if (sg) - sg_mark_end(sg); - - BUG_ON(bio->bi_phys_segments && nsegs > bio->bi_phys_segments); - return nsegs; -} -EXPORT_SYMBOL(blk_bio_map_sg); - static inline int ll_new_hw_segment(struct request_queue *q, struct request *req, struct bio *bio) diff --git a/trunk/block/genhd.c b/trunk/block/genhd.c index d839723303c8..cac7366957c3 100644 --- a/trunk/block/genhd.c +++ b/trunk/block/genhd.c @@ -835,7 +835,7 @@ static void disk_seqf_stop(struct seq_file *seqf, void *v) static void *show_partition_start(struct seq_file *seqf, loff_t *pos) { - void *p; + static void *p; p = disk_seqf_start(seqf, pos); if (!IS_ERR_OR_NULL(p) && !*pos) diff --git a/trunk/block/ioctl.c b/trunk/block/ioctl.c index 4a85096f5410..4476e0e85d16 100644 --- a/trunk/block/ioctl.c +++ b/trunk/block/ioctl.c @@ -41,7 +41,7 @@ static int blkpg_ioctl(struct block_device *bdev, struct blkpg_ioctl_arg __user sizeof(long long) > sizeof(long)) { long pstart = start, plength = length; if (pstart != start || plength != length - || pstart < 0 || plength < 0 || partno > 65535) + || pstart < 0 || plength < 0) return -EINVAL; } diff --git a/trunk/block/partitions/ibm.c b/trunk/block/partitions/ibm.c index 47a61474e795..1104acac780b 100644 --- a/trunk/block/partitions/ibm.c +++ b/trunk/block/partitions/ibm.c @@ -1,8 +1,9 @@ /* + * File...........: linux/fs/partitions/ibm.c * Author(s)......: Holger Smolinski * Volker Sameske * Bugreports.to..: - * Copyright IBM Corp. 1999, 2012 + * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000 */ #include @@ -16,23 +17,17 @@ #include "check.h" #include "ibm.h" - -union label_t { - struct vtoc_volume_label_cdl vol; - struct vtoc_volume_label_ldl lnx; - struct vtoc_cms_label cms; -}; - /* * compute the block number from a * cyl-cyl-head-head structure */ -static sector_t cchh2blk(struct vtoc_cchh *ptr, struct hd_geometry *geo) -{ +static sector_t +cchh2blk (struct vtoc_cchh *ptr, struct hd_geometry *geo) { + sector_t cyl; __u16 head; - /* decode cylinder and heads for large volumes */ + /*decode cylinder and heads for large volumes */ cyl = ptr->hh & 0xFFF0; cyl <<= 12; cyl |= ptr->cc; @@ -45,12 +40,13 @@ static sector_t cchh2blk(struct vtoc_cchh *ptr, struct hd_geometry *geo) * compute the block number from a * cyl-cyl-head-head-block structure */ -static sector_t cchhb2blk(struct vtoc_cchhb *ptr, struct hd_geometry *geo) -{ +static sector_t +cchhb2blk (struct vtoc_cchhb *ptr, struct hd_geometry *geo) { + sector_t cyl; __u16 head; - /* decode cylinder and heads for large volumes */ + /*decode cylinder and heads for large volumes */ cyl = ptr->hh & 0xFFF0; cyl <<= 12; cyl |= ptr->cc; @@ -60,243 +56,26 @@ static sector_t cchhb2blk(struct vtoc_cchhb *ptr, struct hd_geometry *geo) ptr->b; } -static int find_label(struct parsed_partitions *state, - dasd_information2_t *info, - struct hd_geometry *geo, - int blocksize, - sector_t *labelsect, - char name[], - char type[], - union label_t *label) -{ - Sector sect; - unsigned char *data; - sector_t testsect[3]; - unsigned char temp[5]; - int found = 0; - int i, testcount; - - /* There a three places where we may find a valid label: - * - on an ECKD disk it's block 2 - * - on an FBA disk it's block 1 - * - on an CMS formatted FBA disk it is sector 1, even if the block size - * is larger than 512 bytes (possible if the DIAG discipline is used) - * If we have a valid info structure, then we know exactly which case we - * have, otherwise we just search through all possebilities. - */ - if (info) { - if ((info->cu_type == 0x6310 && info->dev_type == 0x9336) || - (info->cu_type == 0x3880 && info->dev_type == 0x3370)) - testsect[0] = info->label_block; - else - testsect[0] = info->label_block * (blocksize >> 9); - testcount = 1; - } else { - testsect[0] = 1; - testsect[1] = (blocksize >> 9); - testsect[2] = 2 * (blocksize >> 9); - testcount = 3; - } - for (i = 0; i < testcount; ++i) { - data = read_part_sector(state, testsect[i], §); - if (data == NULL) - continue; - memcpy(label, data, sizeof(*label)); - memcpy(temp, data, 4); - temp[4] = 0; - EBCASC(temp, 4); - put_dev_sector(sect); - if (!strcmp(temp, "VOL1") || - !strcmp(temp, "LNX1") || - !strcmp(temp, "CMS1")) { - if (!strcmp(temp, "VOL1")) { - strncpy(type, label->vol.vollbl, 4); - strncpy(name, label->vol.volid, 6); - } else { - strncpy(type, label->lnx.vollbl, 4); - strncpy(name, label->lnx.volid, 6); - } - EBCASC(type, 4); - EBCASC(name, 6); - *labelsect = testsect[i]; - found = 1; - break; - } - } - if (!found) - memset(label, 0, sizeof(*label)); - - return found; -} - -static int find_vol1_partitions(struct parsed_partitions *state, - struct hd_geometry *geo, - int blocksize, - char name[], - union label_t *label) -{ - sector_t blk; - int counter; - char tmp[64]; - Sector sect; - unsigned char *data; - loff_t offset, size; - struct vtoc_format1_label f1; - int secperblk; - - snprintf(tmp, sizeof(tmp), "VOL1/%8s:", name); - strlcat(state->pp_buf, tmp, PAGE_SIZE); - /* - * get start of VTOC from the disk label and then search for format1 - * and format8 labels - */ - secperblk = blocksize >> 9; - blk = cchhb2blk(&label->vol.vtoc, geo) + 1; - counter = 0; - data = read_part_sector(state, blk * secperblk, §); - while (data != NULL) { - memcpy(&f1, data, sizeof(struct vtoc_format1_label)); - put_dev_sector(sect); - /* skip FMT4 / FMT5 / FMT7 labels */ - if (f1.DS1FMTID == _ascebc['4'] - || f1.DS1FMTID == _ascebc['5'] - || f1.DS1FMTID == _ascebc['7'] - || f1.DS1FMTID == _ascebc['9']) { - blk++; - data = read_part_sector(state, blk * secperblk, §); - continue; - } - /* only FMT1 and 8 labels valid at this point */ - if (f1.DS1FMTID != _ascebc['1'] && - f1.DS1FMTID != _ascebc['8']) - break; - /* OK, we got valid partition data */ - offset = cchh2blk(&f1.DS1EXT1.llimit, geo); - size = cchh2blk(&f1.DS1EXT1.ulimit, geo) - - offset + geo->sectors; - offset *= secperblk; - size *= secperblk; - if (counter >= state->limit) - break; - put_partition(state, counter + 1, offset, size); - counter++; - blk++; - data = read_part_sector(state, blk * secperblk, §); - } - strlcat(state->pp_buf, "\n", PAGE_SIZE); - - if (!data) - return -1; - - return 1; -} - -static int find_lnx1_partitions(struct parsed_partitions *state, - struct hd_geometry *geo, - int blocksize, - char name[], - union label_t *label, - sector_t labelsect, - loff_t i_size, - dasd_information2_t *info) -{ - loff_t offset, geo_size, size; - char tmp[64]; - int secperblk; - - snprintf(tmp, sizeof(tmp), "LNX1/%8s:", name); - strlcat(state->pp_buf, tmp, PAGE_SIZE); - secperblk = blocksize >> 9; - if (label->lnx.ldl_version == 0xf2) { - size = label->lnx.formatted_blocks * secperblk; - } else { - /* - * Formated w/o large volume support. If the sanity check - * 'size based on geo == size based on i_size' is true, then - * we can safely assume that we know the formatted size of - * the disk, otherwise we need additional information - * that we can only get from a real DASD device. - */ - geo_size = geo->cylinders * geo->heads - * geo->sectors * secperblk; - size = i_size >> 9; - if (size != geo_size) { - if (!info) { - strlcat(state->pp_buf, "\n", PAGE_SIZE); - return 1; - } - if (!strcmp(info->type, "ECKD")) - if (geo_size < size) - size = geo_size; - /* else keep size based on i_size */ - } - } - /* first and only partition starts in the first block after the label */ - offset = labelsect + secperblk; - put_partition(state, 1, offset, size - offset); - strlcat(state->pp_buf, "\n", PAGE_SIZE); - return 1; -} - -static int find_cms1_partitions(struct parsed_partitions *state, - struct hd_geometry *geo, - int blocksize, - char name[], - union label_t *label, - sector_t labelsect) -{ - loff_t offset, size; - char tmp[64]; - int secperblk; - - /* - * VM style CMS1 labeled disk - */ - blocksize = label->cms.block_size; - secperblk = blocksize >> 9; - if (label->cms.disk_offset != 0) { - snprintf(tmp, sizeof(tmp), "CMS1/%8s(MDSK):", name); - strlcat(state->pp_buf, tmp, PAGE_SIZE); - /* disk is reserved minidisk */ - offset = label->cms.disk_offset * secperblk; - size = (label->cms.block_count - 1) * secperblk; - } else { - snprintf(tmp, sizeof(tmp), "CMS1/%8s:", name); - strlcat(state->pp_buf, tmp, PAGE_SIZE); - /* - * Special case for FBA devices: - * If an FBA device is CMS formatted with blocksize > 512 byte - * and the DIAG discipline is used, then the CMS label is found - * in sector 1 instead of block 1. However, the partition is - * still supposed to start in block 2. - */ - if (labelsect == 1) - offset = 2 * secperblk; - else - offset = labelsect + secperblk; - size = label->cms.block_count * secperblk; - } - - put_partition(state, 1, offset, size-offset); - strlcat(state->pp_buf, "\n", PAGE_SIZE); - return 1; -} - - /* - * This is the main function, called by check.c */ int ibm_partition(struct parsed_partitions *state) { struct block_device *bdev = state->bdev; int blocksize, res; - loff_t i_size, offset, size; + loff_t i_size, offset, size, fmt_size; dasd_information2_t *info; struct hd_geometry *geo; char type[5] = {0,}; char name[7] = {0,}; + union label_t { + struct vtoc_volume_label_cdl vol; + struct vtoc_volume_label_ldl lnx; + struct vtoc_cms_label cms; + } *label; + unsigned char *data; + Sector sect; sector_t labelsect; - union label_t *label; + char tmp[64]; res = 0; blocksize = bdev_logical_block_size(bdev); @@ -305,6 +84,7 @@ int ibm_partition(struct parsed_partitions *state) i_size = i_size_read(bdev->bd_inode); if (i_size == 0) goto out_exit; + info = kmalloc(sizeof(dasd_information2_t), GFP_KERNEL); if (info == NULL) goto out_exit; @@ -314,45 +94,176 @@ int ibm_partition(struct parsed_partitions *state) label = kmalloc(sizeof(union label_t), GFP_KERNEL); if (label == NULL) goto out_nolab; - if (ioctl_by_bdev(bdev, HDIO_GETGEO, (unsigned long)geo) != 0) + + if (ioctl_by_bdev(bdev, BIODASDINFO2, (unsigned long)info) != 0 || + ioctl_by_bdev(bdev, HDIO_GETGEO, (unsigned long)geo) != 0) goto out_freeall; - if (ioctl_by_bdev(bdev, BIODASDINFO2, (unsigned long)info) != 0) { - kfree(info); - info = NULL; + + /* + * Special case for FBA disks: label sector does not depend on + * blocksize. + */ + if ((info->cu_type == 0x6310 && info->dev_type == 0x9336) || + (info->cu_type == 0x3880 && info->dev_type == 0x3370)) + labelsect = info->label_block; + else + labelsect = info->label_block * (blocksize >> 9); + + /* + * Get volume label, extract name and type. + */ + data = read_part_sector(state, labelsect, §); + if (data == NULL) + goto out_readerr; + + memcpy(label, data, sizeof(union label_t)); + put_dev_sector(sect); + + if ((!info->FBA_layout) && (!strcmp(info->type, "ECKD"))) { + strncpy(type, label->vol.vollbl, 4); + strncpy(name, label->vol.volid, 6); + } else { + strncpy(type, label->lnx.vollbl, 4); + strncpy(name, label->lnx.volid, 6); } + EBCASC(type, 4); + EBCASC(name, 6); + + res = 1; - if (find_label(state, info, geo, blocksize, &labelsect, name, type, - label)) { - if (!strncmp(type, "VOL1", 4)) { - res = find_vol1_partitions(state, geo, blocksize, name, - label); - } else if (!strncmp(type, "LNX1", 4)) { - res = find_lnx1_partitions(state, geo, blocksize, name, - label, labelsect, i_size, - info); - } else if (!strncmp(type, "CMS1", 4)) { - res = find_cms1_partitions(state, geo, blocksize, name, - label, labelsect); + /* + * Three different formats: LDL, CDL and unformated disk + * + * identified by info->format + * + * unformated disks we do not have to care about + */ + if (info->format == DASD_FORMAT_LDL) { + if (strncmp(type, "CMS1", 4) == 0) { + /* + * VM style CMS1 labeled disk + */ + blocksize = label->cms.block_size; + if (label->cms.disk_offset != 0) { + snprintf(tmp, sizeof(tmp), "CMS1/%8s(MDSK):", name); + strlcat(state->pp_buf, tmp, PAGE_SIZE); + /* disk is reserved minidisk */ + offset = label->cms.disk_offset; + size = (label->cms.block_count - 1) + * (blocksize >> 9); + } else { + snprintf(tmp, sizeof(tmp), "CMS1/%8s:", name); + strlcat(state->pp_buf, tmp, PAGE_SIZE); + offset = (info->label_block + 1); + size = label->cms.block_count + * (blocksize >> 9); + } + put_partition(state, 1, offset*(blocksize >> 9), + size-offset*(blocksize >> 9)); + } else { + if (strncmp(type, "LNX1", 4) == 0) { + snprintf(tmp, sizeof(tmp), "LNX1/%8s:", name); + strlcat(state->pp_buf, tmp, PAGE_SIZE); + if (label->lnx.ldl_version == 0xf2) { + fmt_size = label->lnx.formatted_blocks + * (blocksize >> 9); + } else if (!strcmp(info->type, "ECKD")) { + /* formated w/o large volume support */ + fmt_size = geo->cylinders * geo->heads + * geo->sectors * (blocksize >> 9); + } else { + /* old label and no usable disk geometry + * (e.g. DIAG) */ + fmt_size = i_size >> 9; + } + size = i_size >> 9; + if (fmt_size < size) + size = fmt_size; + offset = (info->label_block + 1); + } else { + /* unlabeled disk */ + strlcat(state->pp_buf, "(nonl)", PAGE_SIZE); + size = i_size >> 9; + offset = (info->label_block + 1); + } + put_partition(state, 1, offset*(blocksize >> 9), + size-offset*(blocksize >> 9)); } - } else if (info) { + } else if (info->format == DASD_FORMAT_CDL) { /* - * ugly but needed for backward compatibility: - * If the block device is a DASD (i.e. BIODASDINFO2 works), - * then we claim it in any case, even though it has no valid - * label. If it has the LDL format, then we simply define a - * partition as if it had an LNX1 label. + * New style CDL formatted disk */ - res = 1; - if (info->format == DASD_FORMAT_LDL) { - strlcat(state->pp_buf, "(nonl)", PAGE_SIZE); - size = i_size >> 9; - offset = (info->label_block + 1) * (blocksize >> 9); - put_partition(state, 1, offset, size-offset); - strlcat(state->pp_buf, "\n", PAGE_SIZE); - } - } else - res = 0; + sector_t blk; + int counter; + + /* + * check if VOL1 label is available + * if not, something is wrong, skipping partition detection + */ + if (strncmp(type, "VOL1", 4) == 0) { + snprintf(tmp, sizeof(tmp), "VOL1/%8s:", name); + strlcat(state->pp_buf, tmp, PAGE_SIZE); + /* + * get block number and read then go through format1 + * labels + */ + blk = cchhb2blk(&label->vol.vtoc, geo) + 1; + counter = 0; + data = read_part_sector(state, blk * (blocksize/512), + §); + while (data != NULL) { + struct vtoc_format1_label f1; + + memcpy(&f1, data, + sizeof(struct vtoc_format1_label)); + put_dev_sector(sect); + + /* skip FMT4 / FMT5 / FMT7 labels */ + if (f1.DS1FMTID == _ascebc['4'] + || f1.DS1FMTID == _ascebc['5'] + || f1.DS1FMTID == _ascebc['7'] + || f1.DS1FMTID == _ascebc['9']) { + blk++; + data = read_part_sector(state, + blk * (blocksize/512), §); + continue; + } + + /* only FMT1 and 8 labels valid at this point */ + if (f1.DS1FMTID != _ascebc['1'] && + f1.DS1FMTID != _ascebc['8']) + break; + + /* OK, we got valid partition data */ + offset = cchh2blk(&f1.DS1EXT1.llimit, geo); + size = cchh2blk(&f1.DS1EXT1.ulimit, geo) - + offset + geo->sectors; + if (counter >= state->limit) + break; + put_partition(state, counter + 1, + offset * (blocksize >> 9), + size * (blocksize >> 9)); + counter++; + blk++; + data = read_part_sector(state, + blk * (blocksize/512), §); + } + + if (!data) + /* Are we not supposed to report this ? */ + goto out_readerr; + } else + printk(KERN_INFO "Expected Label VOL1 not " + "found, treating as CDL formated Disk"); + + } + + strlcat(state->pp_buf, "\n", PAGE_SIZE); + goto out_freeall; + +out_readerr: + res = -1; out_freeall: kfree(label); out_nolab: diff --git a/trunk/crypto/authenc.c b/trunk/crypto/authenc.c index d0583a4489e6..5ef7ba6b6a76 100644 --- a/trunk/crypto/authenc.c +++ b/trunk/crypto/authenc.c @@ -336,7 +336,7 @@ static int crypto_authenc_genicv(struct aead_request *req, u8 *iv, cryptlen += ivsize; } - if (req->assoclen && sg_is_last(assoc)) { + if (sg_is_last(assoc)) { authenc_ahash_fn = crypto_authenc_ahash; sg_init_table(asg, 2); sg_set_page(asg, sg_page(assoc), assoc->length, assoc->offset); @@ -490,7 +490,7 @@ static int crypto_authenc_iverify(struct aead_request *req, u8 *iv, cryptlen += ivsize; } - if (req->assoclen && sg_is_last(assoc)) { + if (sg_is_last(assoc)) { authenc_ahash_fn = crypto_authenc_ahash; sg_init_table(asg, 2); sg_set_page(asg, sg_page(assoc), assoc->length, assoc->offset); diff --git a/trunk/drivers/acpi/Kconfig b/trunk/drivers/acpi/Kconfig index 119d58db8342..80998958cf45 100644 --- a/trunk/drivers/acpi/Kconfig +++ b/trunk/drivers/acpi/Kconfig @@ -385,8 +385,8 @@ config ACPI_CUSTOM_METHOD to override that restriction). config ACPI_BGRT - bool "Boottime Graphics Resource Table support" - depends on EFI + tristate "Boottime Graphics Resource Table support" + default n help This driver adds support for exposing the ACPI Boottime Graphics Resource Table, which allows the operating system to obtain diff --git a/trunk/drivers/acpi/ac.c b/trunk/drivers/acpi/ac.c index d5fdd36190cc..ac7034129f3f 100644 --- a/trunk/drivers/acpi/ac.c +++ b/trunk/drivers/acpi/ac.c @@ -69,9 +69,7 @@ static const struct acpi_device_id ac_device_ids[] = { }; MODULE_DEVICE_TABLE(acpi, ac_device_ids); -#ifdef CONFIG_PM_SLEEP static int acpi_ac_resume(struct device *dev); -#endif static SIMPLE_DEV_PM_OPS(acpi_ac_pm, NULL, acpi_ac_resume); static struct acpi_driver acpi_ac_driver = { @@ -315,7 +313,6 @@ static int acpi_ac_add(struct acpi_device *device) return result; } -#ifdef CONFIG_PM_SLEEP static int acpi_ac_resume(struct device *dev) { struct acpi_ac *ac; @@ -335,7 +332,6 @@ static int acpi_ac_resume(struct device *dev) kobject_uevent(&ac->charger.dev->kobj, KOBJ_CHANGE); return 0; } -#endif static int acpi_ac_remove(struct acpi_device *device, int type) { diff --git a/trunk/drivers/acpi/acpica/achware.h b/trunk/drivers/acpi/acpica/achware.h index 5de4ec72766d..5ccb99ae3a6f 100644 --- a/trunk/drivers/acpi/acpica/achware.h +++ b/trunk/drivers/acpi/acpica/achware.h @@ -83,22 +83,22 @@ acpi_status acpi_hw_clear_acpi_status(void); /* * hwsleep - sleep/wake support (Legacy sleep registers) */ -acpi_status acpi_hw_legacy_sleep(u8 sleep_state); +acpi_status acpi_hw_legacy_sleep(u8 sleep_state, u8 flags); -acpi_status acpi_hw_legacy_wake_prep(u8 sleep_state); +acpi_status acpi_hw_legacy_wake_prep(u8 sleep_state, u8 flags); -acpi_status acpi_hw_legacy_wake(u8 sleep_state); +acpi_status acpi_hw_legacy_wake(u8 sleep_state, u8 flags); /* * hwesleep - sleep/wake support (Extended FADT-V5 sleep registers) */ void acpi_hw_execute_sleep_method(char *method_name, u32 integer_argument); -acpi_status acpi_hw_extended_sleep(u8 sleep_state); +acpi_status acpi_hw_extended_sleep(u8 sleep_state, u8 flags); -acpi_status acpi_hw_extended_wake_prep(u8 sleep_state); +acpi_status acpi_hw_extended_wake_prep(u8 sleep_state, u8 flags); -acpi_status acpi_hw_extended_wake(u8 sleep_state); +acpi_status acpi_hw_extended_wake(u8 sleep_state, u8 flags); /* * hwvalid - Port I/O with validation diff --git a/trunk/drivers/acpi/acpica/hwesleep.c b/trunk/drivers/acpi/acpica/hwesleep.c index 94996f9ae3ad..48518dac5342 100644 --- a/trunk/drivers/acpi/acpica/hwesleep.c +++ b/trunk/drivers/acpi/acpica/hwesleep.c @@ -90,6 +90,7 @@ void acpi_hw_execute_sleep_method(char *method_pathname, u32 integer_argument) * FUNCTION: acpi_hw_extended_sleep * * PARAMETERS: sleep_state - Which sleep state to enter + * flags - ACPI_EXECUTE_GTS to run optional method * * RETURN: Status * @@ -99,7 +100,7 @@ void acpi_hw_execute_sleep_method(char *method_pathname, u32 integer_argument) * ******************************************************************************/ -acpi_status acpi_hw_extended_sleep(u8 sleep_state) +acpi_status acpi_hw_extended_sleep(u8 sleep_state, u8 flags) { acpi_status status; u8 sleep_type_value; @@ -124,6 +125,12 @@ acpi_status acpi_hw_extended_sleep(u8 sleep_state) acpi_gbl_system_awake_and_running = FALSE; + /* Optionally execute _GTS (Going To Sleep) */ + + if (flags & ACPI_EXECUTE_GTS) { + acpi_hw_execute_sleep_method(METHOD_PATHNAME__GTS, sleep_state); + } + /* Flush caches, as per ACPI specification */ ACPI_FLUSH_CPU_CACHE(); @@ -165,6 +172,7 @@ acpi_status acpi_hw_extended_sleep(u8 sleep_state) * FUNCTION: acpi_hw_extended_wake_prep * * PARAMETERS: sleep_state - Which sleep state we just exited + * flags - ACPI_EXECUTE_BFS to run optional method * * RETURN: Status * @@ -173,7 +181,7 @@ acpi_status acpi_hw_extended_sleep(u8 sleep_state) * ******************************************************************************/ -acpi_status acpi_hw_extended_wake_prep(u8 sleep_state) +acpi_status acpi_hw_extended_wake_prep(u8 sleep_state, u8 flags) { acpi_status status; u8 sleep_type_value; @@ -192,6 +200,11 @@ acpi_status acpi_hw_extended_wake_prep(u8 sleep_state) &acpi_gbl_FADT.sleep_control); } + /* Optionally execute _BFS (Back From Sleep) */ + + if (flags & ACPI_EXECUTE_BFS) { + acpi_hw_execute_sleep_method(METHOD_PATHNAME__BFS, sleep_state); + } return_ACPI_STATUS(AE_OK); } @@ -209,7 +222,7 @@ acpi_status acpi_hw_extended_wake_prep(u8 sleep_state) * ******************************************************************************/ -acpi_status acpi_hw_extended_wake(u8 sleep_state) +acpi_status acpi_hw_extended_wake(u8 sleep_state, u8 flags) { ACPI_FUNCTION_TRACE(hw_extended_wake); diff --git a/trunk/drivers/acpi/acpica/hwsleep.c b/trunk/drivers/acpi/acpica/hwsleep.c index 3fddde056a5e..9960fe9ef533 100644 --- a/trunk/drivers/acpi/acpica/hwsleep.c +++ b/trunk/drivers/acpi/acpica/hwsleep.c @@ -56,6 +56,7 @@ ACPI_MODULE_NAME("hwsleep") * FUNCTION: acpi_hw_legacy_sleep * * PARAMETERS: sleep_state - Which sleep state to enter + * flags - ACPI_EXECUTE_GTS to run optional method * * RETURN: Status * @@ -63,7 +64,7 @@ ACPI_MODULE_NAME("hwsleep") * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED * ******************************************************************************/ -acpi_status acpi_hw_legacy_sleep(u8 sleep_state) +acpi_status acpi_hw_legacy_sleep(u8 sleep_state, u8 flags) { struct acpi_bit_register_info *sleep_type_reg_info; struct acpi_bit_register_info *sleep_enable_reg_info; @@ -109,6 +110,12 @@ acpi_status acpi_hw_legacy_sleep(u8 sleep_state) return_ACPI_STATUS(status); } + /* Optionally execute _GTS (Going To Sleep) */ + + if (flags & ACPI_EXECUTE_GTS) { + acpi_hw_execute_sleep_method(METHOD_PATHNAME__GTS, sleep_state); + } + /* Get current value of PM1A control */ status = acpi_hw_register_read(ACPI_REGISTER_PM1_CONTROL, @@ -207,6 +214,7 @@ acpi_status acpi_hw_legacy_sleep(u8 sleep_state) * FUNCTION: acpi_hw_legacy_wake_prep * * PARAMETERS: sleep_state - Which sleep state we just exited + * flags - ACPI_EXECUTE_BFS to run optional method * * RETURN: Status * @@ -216,7 +224,7 @@ acpi_status acpi_hw_legacy_sleep(u8 sleep_state) * ******************************************************************************/ -acpi_status acpi_hw_legacy_wake_prep(u8 sleep_state) +acpi_status acpi_hw_legacy_wake_prep(u8 sleep_state, u8 flags) { acpi_status status; struct acpi_bit_register_info *sleep_type_reg_info; @@ -267,6 +275,11 @@ acpi_status acpi_hw_legacy_wake_prep(u8 sleep_state) } } + /* Optionally execute _BFS (Back From Sleep) */ + + if (flags & ACPI_EXECUTE_BFS) { + acpi_hw_execute_sleep_method(METHOD_PATHNAME__BFS, sleep_state); + } return_ACPI_STATUS(status); } @@ -275,6 +288,7 @@ acpi_status acpi_hw_legacy_wake_prep(u8 sleep_state) * FUNCTION: acpi_hw_legacy_wake * * PARAMETERS: sleep_state - Which sleep state we just exited + * flags - Reserved, set to zero * * RETURN: Status * @@ -283,7 +297,7 @@ acpi_status acpi_hw_legacy_wake_prep(u8 sleep_state) * ******************************************************************************/ -acpi_status acpi_hw_legacy_wake(u8 sleep_state) +acpi_status acpi_hw_legacy_wake(u8 sleep_state, u8 flags) { acpi_status status; diff --git a/trunk/drivers/acpi/acpica/hwxfsleep.c b/trunk/drivers/acpi/acpica/hwxfsleep.c index 1f165a750ae2..f8684bfe7907 100644 --- a/trunk/drivers/acpi/acpica/hwxfsleep.c +++ b/trunk/drivers/acpi/acpica/hwxfsleep.c @@ -50,7 +50,7 @@ ACPI_MODULE_NAME("hwxfsleep") /* Local prototypes */ static acpi_status -acpi_hw_sleep_dispatch(u8 sleep_state, u32 function_id); +acpi_hw_sleep_dispatch(u8 sleep_state, u8 flags, u32 function_id); /* * Dispatch table used to efficiently branch to the various sleep @@ -235,7 +235,7 @@ ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state_s4bios) * ******************************************************************************/ static acpi_status -acpi_hw_sleep_dispatch(u8 sleep_state, u32 function_id) +acpi_hw_sleep_dispatch(u8 sleep_state, u8 flags, u32 function_id) { acpi_status status; struct acpi_sleep_functions *sleep_functions = @@ -248,11 +248,11 @@ acpi_hw_sleep_dispatch(u8 sleep_state, u32 function_id) * use the extended sleep registers */ if (acpi_gbl_reduced_hardware || acpi_gbl_FADT.sleep_control.address) { - status = sleep_functions->extended_function(sleep_state); + status = sleep_functions->extended_function(sleep_state, flags); } else { /* Legacy sleep */ - status = sleep_functions->legacy_function(sleep_state); + status = sleep_functions->legacy_function(sleep_state, flags); } return (status); @@ -262,7 +262,7 @@ acpi_hw_sleep_dispatch(u8 sleep_state, u32 function_id) * For the case where reduced-hardware-only code is being generated, * we know that only the extended sleep registers are available */ - status = sleep_functions->extended_function(sleep_state); + status = sleep_functions->extended_function(sleep_state, flags); return (status); #endif /* !ACPI_REDUCED_HARDWARE */ @@ -349,6 +349,7 @@ ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state_prep) * FUNCTION: acpi_enter_sleep_state * * PARAMETERS: sleep_state - Which sleep state to enter + * flags - ACPI_EXECUTE_GTS to run optional method * * RETURN: Status * @@ -356,7 +357,7 @@ ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state_prep) * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED * ******************************************************************************/ -acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state) +acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state, u8 flags) { acpi_status status; @@ -370,7 +371,7 @@ acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state) } status = - acpi_hw_sleep_dispatch(sleep_state, ACPI_SLEEP_FUNCTION_ID); + acpi_hw_sleep_dispatch(sleep_state, flags, ACPI_SLEEP_FUNCTION_ID); return_ACPI_STATUS(status); } @@ -390,14 +391,14 @@ ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state) * Called with interrupts DISABLED. * ******************************************************************************/ -acpi_status acpi_leave_sleep_state_prep(u8 sleep_state) +acpi_status acpi_leave_sleep_state_prep(u8 sleep_state, u8 flags) { acpi_status status; ACPI_FUNCTION_TRACE(acpi_leave_sleep_state_prep); status = - acpi_hw_sleep_dispatch(sleep_state, + acpi_hw_sleep_dispatch(sleep_state, flags, ACPI_WAKE_PREP_FUNCTION_ID); return_ACPI_STATUS(status); } @@ -422,7 +423,8 @@ acpi_status acpi_leave_sleep_state(u8 sleep_state) ACPI_FUNCTION_TRACE(acpi_leave_sleep_state); - status = acpi_hw_sleep_dispatch(sleep_state, ACPI_WAKE_FUNCTION_ID); + + status = acpi_hw_sleep_dispatch(sleep_state, 0, ACPI_WAKE_FUNCTION_ID); return_ACPI_STATUS(status); } diff --git a/trunk/drivers/acpi/acpica/tbxface.c b/trunk/drivers/acpi/acpica/tbxface.c index 29e51bc01383..ea4c6d52605a 100644 --- a/trunk/drivers/acpi/acpica/tbxface.c +++ b/trunk/drivers/acpi/acpica/tbxface.c @@ -387,7 +387,6 @@ acpi_get_table_with_size(char *signature, return (AE_NOT_FOUND); } -ACPI_EXPORT_SYMBOL(acpi_get_table_with_size) acpi_status acpi_get_table(char *signature, diff --git a/trunk/drivers/acpi/battery.c b/trunk/drivers/acpi/battery.c index 45e3e1759fb8..ff2c876ec412 100644 --- a/trunk/drivers/acpi/battery.c +++ b/trunk/drivers/acpi/battery.c @@ -1052,7 +1052,6 @@ static int acpi_battery_remove(struct acpi_device *device, int type) return 0; } -#ifdef CONFIG_PM_SLEEP /* this is needed to learn about changes made in suspended state */ static int acpi_battery_resume(struct device *dev) { @@ -1069,7 +1068,6 @@ static int acpi_battery_resume(struct device *dev) acpi_battery_update(battery); return 0; } -#endif static SIMPLE_DEV_PM_OPS(acpi_battery_pm, NULL, acpi_battery_resume); diff --git a/trunk/drivers/acpi/bgrt.c b/trunk/drivers/acpi/bgrt.c index be6039958545..6680df36b963 100644 --- a/trunk/drivers/acpi/bgrt.c +++ b/trunk/drivers/acpi/bgrt.c @@ -1,6 +1,5 @@ /* * Copyright 2012 Red Hat, Inc - * Copyright 2012 Intel 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 @@ -12,10 +11,20 @@ #include #include #include -#include +#include +#include +#include +static struct acpi_table_bgrt *bgrt_tab; static struct kobject *bgrt_kobj; +struct bmp_header { + u16 id; + u32 size; +} __attribute ((packed)); + +static struct bmp_header bmp_header; + static ssize_t show_version(struct device *dev, struct device_attribute *attr, char *buf) { @@ -54,7 +63,18 @@ static DEVICE_ATTR(yoffset, S_IRUGO, show_yoffset, NULL); static ssize_t show_image(struct file *file, struct kobject *kobj, struct bin_attribute *attr, char *buf, loff_t off, size_t count) { - memcpy(buf, attr->private + off, count); + int size = attr->size; + void __iomem *image = attr->private; + + if (off >= size) { + count = 0; + } else { + if (off + count > size) + count = size - off; + + memcpy_fromio(buf, image+off, count); + } + return count; } @@ -81,18 +101,45 @@ static struct attribute_group bgrt_attribute_group = { static int __init bgrt_init(void) { + acpi_status status; int ret; + void __iomem *bgrt; - if (!bgrt_image) + if (acpi_disabled) + return -ENODEV; + + status = acpi_get_table("BGRT", 0, + (struct acpi_table_header **)&bgrt_tab); + + if (ACPI_FAILURE(status)) return -ENODEV; sysfs_bin_attr_init(&image_attr); - image_attr.private = bgrt_image; - image_attr.size = bgrt_image_size; + + bgrt = ioremap(bgrt_tab->image_address, sizeof(struct bmp_header)); + + if (!bgrt) { + ret = -EINVAL; + goto out_err; + } + + memcpy_fromio(&bmp_header, bgrt, sizeof(bmp_header)); + image_attr.size = bmp_header.size; + iounmap(bgrt); + + image_attr.private = ioremap(bgrt_tab->image_address, image_attr.size); + + if (!image_attr.private) { + ret = -EINVAL; + goto out_err; + } + bgrt_kobj = kobject_create_and_add("bgrt", acpi_kobj); - if (!bgrt_kobj) - return -EINVAL; + if (!bgrt_kobj) { + ret = -EINVAL; + goto out_iounmap; + } ret = sysfs_create_group(bgrt_kobj, &bgrt_attribute_group); if (ret) @@ -108,11 +155,22 @@ static int __init bgrt_init(void) sysfs_remove_group(bgrt_kobj, &bgrt_attribute_group); out_kobject: kobject_put(bgrt_kobj); +out_iounmap: + iounmap(image_attr.private); +out_err: return ret; } +static void __exit bgrt_exit(void) +{ + iounmap(image_attr.private); + sysfs_remove_group(bgrt_kobj, &bgrt_attribute_group); + sysfs_remove_bin_file(bgrt_kobj, &image_attr); +} + module_init(bgrt_init); +module_exit(bgrt_exit); -MODULE_AUTHOR("Matthew Garrett, Josh Triplett "); +MODULE_AUTHOR("Matthew Garrett"); MODULE_DESCRIPTION("BGRT boot graphic support"); MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/acpi/bus.c b/trunk/drivers/acpi/bus.c index e0596954290b..9628652e080c 100644 --- a/trunk/drivers/acpi/bus.c +++ b/trunk/drivers/acpi/bus.c @@ -237,16 +237,6 @@ static int __acpi_bus_get_power(struct acpi_device *device, int *state) } else if (result == ACPI_STATE_D3_HOT) { result = ACPI_STATE_D3; } - - /* - * If we were unsure about the device parent's power state up to this - * point, the fact that the device is in D0 implies that the parent has - * to be in D0 too. - */ - if (device->parent && device->parent->power.state == ACPI_STATE_UNKNOWN - && result == ACPI_STATE_D0) - device->parent->power.state = ACPI_STATE_D0; - *state = result; out: diff --git a/trunk/drivers/acpi/button.c b/trunk/drivers/acpi/button.c index 314a3b84bbc7..79d4c22f7a6d 100644 --- a/trunk/drivers/acpi/button.c +++ b/trunk/drivers/acpi/button.c @@ -78,9 +78,7 @@ static int acpi_button_add(struct acpi_device *device); static int acpi_button_remove(struct acpi_device *device, int type); static void acpi_button_notify(struct acpi_device *device, u32 event); -#ifdef CONFIG_PM_SLEEP static int acpi_button_resume(struct device *dev); -#endif static SIMPLE_DEV_PM_OPS(acpi_button_pm, NULL, acpi_button_resume); static struct acpi_driver acpi_button_driver = { @@ -312,7 +310,6 @@ static void acpi_button_notify(struct acpi_device *device, u32 event) } } -#ifdef CONFIG_PM_SLEEP static int acpi_button_resume(struct device *dev) { struct acpi_device *device = to_acpi_device(dev); @@ -322,7 +319,6 @@ static int acpi_button_resume(struct device *dev) return acpi_lid_send_state(device); return 0; } -#endif static int acpi_button_add(struct acpi_device *device) { diff --git a/trunk/drivers/acpi/fan.c b/trunk/drivers/acpi/fan.c index bc36a476f1ab..669d9ee80d16 100644 --- a/trunk/drivers/acpi/fan.c +++ b/trunk/drivers/acpi/fan.c @@ -53,10 +53,8 @@ static const struct acpi_device_id fan_device_ids[] = { }; MODULE_DEVICE_TABLE(acpi, fan_device_ids); -#ifdef CONFIG_PM_SLEEP static int acpi_fan_suspend(struct device *dev); static int acpi_fan_resume(struct device *dev); -#endif static SIMPLE_DEV_PM_OPS(acpi_fan_pm, acpi_fan_suspend, acpi_fan_resume); static struct acpi_driver acpi_fan_driver = { @@ -186,7 +184,6 @@ static int acpi_fan_remove(struct acpi_device *device, int type) return 0; } -#ifdef CONFIG_PM_SLEEP static int acpi_fan_suspend(struct device *dev) { if (!dev) @@ -210,7 +207,6 @@ static int acpi_fan_resume(struct device *dev) return result; } -#endif static int __init acpi_fan_init(void) { diff --git a/trunk/drivers/acpi/numa.c b/trunk/drivers/acpi/numa.c index cb31298ca684..e56f3be7b07d 100644 --- a/trunk/drivers/acpi/numa.c +++ b/trunk/drivers/acpi/numa.c @@ -237,8 +237,6 @@ acpi_parse_processor_affinity(struct acpi_subtable_header *header, return 0; } -static int __initdata parsed_numa_memblks; - static int __init acpi_parse_memory_affinity(struct acpi_subtable_header * header, const unsigned long end) @@ -252,8 +250,8 @@ acpi_parse_memory_affinity(struct acpi_subtable_header * header, acpi_table_print_srat_entry(header); /* let architecture-dependent part to do it */ - if (!acpi_numa_memory_affinity_init(memory_affinity)) - parsed_numa_memblks++; + acpi_numa_memory_affinity_init(memory_affinity); + return 0; } @@ -306,10 +304,8 @@ int __init acpi_numa_init(void) acpi_numa_arch_fixup(); - if (cnt < 0) - return cnt; - else if (!parsed_numa_memblks) - return -ENOENT; + if (cnt <= 0) + return cnt ?: -ENOENT; return 0; } diff --git a/trunk/drivers/acpi/pci_root.c b/trunk/drivers/acpi/pci_root.c index bce469c0b48a..ec54014c321c 100644 --- a/trunk/drivers/acpi/pci_root.c +++ b/trunk/drivers/acpi/pci_root.c @@ -27,7 +27,7 @@ #include #include #include -#include +#include #include #include #include @@ -71,11 +71,9 @@ static struct acpi_driver acpi_pci_root_driver = { }, }; -/* Lock to protect both acpi_pci_roots and acpi_pci_drivers lists */ -static DEFINE_MUTEX(acpi_pci_root_lock); static LIST_HEAD(acpi_pci_roots); -static LIST_HEAD(acpi_pci_drivers); +static struct acpi_pci_driver *sub_driver; static DEFINE_MUTEX(osc_lock); int acpi_pci_register_driver(struct acpi_pci_driver *driver) @@ -83,46 +81,55 @@ int acpi_pci_register_driver(struct acpi_pci_driver *driver) int n = 0; struct acpi_pci_root *root; - mutex_lock(&acpi_pci_root_lock); - list_add_tail(&driver->node, &acpi_pci_drivers); - if (driver->add) - list_for_each_entry(root, &acpi_pci_roots, node) { - driver->add(root); - n++; - } - mutex_unlock(&acpi_pci_root_lock); + struct acpi_pci_driver **pptr = &sub_driver; + while (*pptr) + pptr = &(*pptr)->next; + *pptr = driver; + + if (!driver->add) + return 0; + + list_for_each_entry(root, &acpi_pci_roots, node) { + driver->add(root->device->handle); + n++; + } return n; } + EXPORT_SYMBOL(acpi_pci_register_driver); void acpi_pci_unregister_driver(struct acpi_pci_driver *driver) { struct acpi_pci_root *root; - mutex_lock(&acpi_pci_root_lock); - list_del(&driver->node); - if (driver->remove) - list_for_each_entry(root, &acpi_pci_roots, node) - driver->remove(root); - mutex_unlock(&acpi_pci_root_lock); + struct acpi_pci_driver **pptr = &sub_driver; + while (*pptr) { + if (*pptr == driver) + break; + pptr = &(*pptr)->next; + } + BUG_ON(!*pptr); + *pptr = (*pptr)->next; + + if (!driver->remove) + return; + + list_for_each_entry(root, &acpi_pci_roots, node) + driver->remove(root->device->handle); } + EXPORT_SYMBOL(acpi_pci_unregister_driver); acpi_handle acpi_get_pci_rootbridge_handle(unsigned int seg, unsigned int bus) { struct acpi_pci_root *root; - acpi_handle handle = NULL; - mutex_lock(&acpi_pci_root_lock); list_for_each_entry(root, &acpi_pci_roots, node) if ((root->segment == (u16) seg) && - (root->secondary.start == (u16) bus)) { - handle = root->device->handle; - break; - } - mutex_unlock(&acpi_pci_root_lock); - return handle; + (root->secondary.start == (u16) bus)) + return root->device->handle; + return NULL; } EXPORT_SYMBOL_GPL(acpi_get_pci_rootbridge_handle); @@ -270,15 +277,12 @@ static acpi_status acpi_pci_osc_support(struct acpi_pci_root *root, u32 flags) struct acpi_pci_root *acpi_pci_find_root(acpi_handle handle) { struct acpi_pci_root *root; - struct acpi_device *device; - - if (acpi_bus_get_device(handle, &device) || - acpi_match_device_ids(device, root_device_ids)) - return NULL; - - root = acpi_driver_data(device); - return root; + list_for_each_entry(root, &acpi_pci_roots, node) { + if (root->device->handle == handle) + return root; + } + return NULL; } EXPORT_SYMBOL_GPL(acpi_pci_find_root); @@ -514,9 +518,8 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device) * TBD: Need PCI interface for enumeration/configuration of roots. */ - mutex_lock(&acpi_pci_root_lock); + /* TBD: Locking */ list_add_tail(&root->node, &acpi_pci_roots); - mutex_unlock(&acpi_pci_root_lock); printk(KERN_INFO PREFIX "%s [%s] (domain %04x %pR)\n", acpi_device_name(device), acpi_device_bid(device), @@ -535,7 +538,7 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device) "Bus %04x:%02x not present in PCI namespace\n", root->segment, (unsigned int)root->secondary.start); result = -ENODEV; - goto out_del_root; + goto end; } /* @@ -545,7 +548,7 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device) */ result = acpi_pci_bind_root(device); if (result) - goto out_del_root; + goto end; /* * PCI Routing Table @@ -570,15 +573,8 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device) OSC_CLOCK_PWR_CAPABILITY_SUPPORT; if (pci_msi_enabled()) flags |= OSC_MSI_SUPPORT; - if (flags != base_flags) { - status = acpi_pci_osc_support(root, flags); - if (ACPI_FAILURE(status)) { - dev_info(root->bus->bridge, "ACPI _OSC support " - "notification failed, disabling PCIe ASPM\n"); - pcie_no_aspm(); - flags = base_flags; - } - } + if (flags != base_flags) + acpi_pci_osc_support(root, flags); if (!pcie_ports_disabled && (flags & ACPI_PCIE_REQ_SUPPORT) == ACPI_PCIE_REQ_SUPPORT) { @@ -630,11 +626,9 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device) return 0; -out_del_root: - mutex_lock(&acpi_pci_root_lock); - list_del(&root->node); - mutex_unlock(&acpi_pci_root_lock); end: + if (!list_empty(&root->node)) + list_del(&root->node); kfree(root); return result; } @@ -642,34 +636,18 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device) static int acpi_pci_root_start(struct acpi_device *device) { struct acpi_pci_root *root = acpi_driver_data(device); - struct acpi_pci_driver *driver; - - mutex_lock(&acpi_pci_root_lock); - list_for_each_entry(driver, &acpi_pci_drivers, node) - if (driver->add) - driver->add(root); - mutex_unlock(&acpi_pci_root_lock); pci_bus_add_devices(root->bus); - return 0; } static int acpi_pci_root_remove(struct acpi_device *device, int type) { struct acpi_pci_root *root = acpi_driver_data(device); - struct acpi_pci_driver *driver; - - mutex_lock(&acpi_pci_root_lock); - list_for_each_entry(driver, &acpi_pci_drivers, node) - if (driver->remove) - driver->remove(root); device_set_run_wake(root->bus->bridge, false); pci_acpi_remove_bus_pm_notifier(device); - list_del(&root->node); - mutex_unlock(&acpi_pci_root_lock); kfree(root); return 0; } diff --git a/trunk/drivers/acpi/pci_slot.c b/trunk/drivers/acpi/pci_slot.c index d22585f21aeb..e50e31a518af 100644 --- a/trunk/drivers/acpi/pci_slot.c +++ b/trunk/drivers/acpi/pci_slot.c @@ -67,8 +67,8 @@ struct acpi_pci_slot { struct list_head list; /* node in the list of slots */ }; -static int acpi_pci_slot_add(struct acpi_pci_root *root); -static void acpi_pci_slot_remove(struct acpi_pci_root *root); +static int acpi_pci_slot_add(acpi_handle handle); +static void acpi_pci_slot_remove(acpi_handle handle); static LIST_HEAD(slot_list); static DEFINE_MUTEX(slot_list_lock); @@ -233,20 +233,45 @@ walk_p2p_bridge(acpi_handle handle, u32 lvl, void *context, void **rv) /* * walk_root_bridge - generic root bridge walker - * @root: poiner of an acpi_pci_root + * @handle: points to an acpi_pci_root * @user_function: user callback for slot objects * * Call user_function for all objects underneath this root bridge. * Walk p2p bridges underneath us and call user_function on those too. */ static int -walk_root_bridge(struct acpi_pci_root *root, acpi_walk_callback user_function) +walk_root_bridge(acpi_handle handle, acpi_walk_callback user_function) { + int seg, bus; + unsigned long long tmp; acpi_status status; - acpi_handle handle = root->device->handle; - struct pci_bus *pci_bus = root->bus; + acpi_handle dummy_handle; + struct pci_bus *pci_bus; struct callback_args context; + /* If the bridge doesn't have _STA, we assume it is always there */ + status = acpi_get_handle(handle, "_STA", &dummy_handle); + if (ACPI_SUCCESS(status)) { + status = acpi_evaluate_integer(handle, "_STA", NULL, &tmp); + if (ACPI_FAILURE(status)) { + info("%s: _STA evaluation failure\n", __func__); + return 0; + } + if ((tmp & ACPI_STA_DEVICE_FUNCTIONING) == 0) + /* don't register this object */ + return 0; + } + + status = acpi_evaluate_integer(handle, "_SEG", NULL, &tmp); + seg = ACPI_SUCCESS(status) ? tmp : 0; + + status = acpi_evaluate_integer(handle, "_BBN", NULL, &tmp); + bus = ACPI_SUCCESS(status) ? tmp : 0; + + pci_bus = pci_find_bus(seg, bus); + if (!pci_bus) + return 0; + context.pci_bus = pci_bus; context.user_function = user_function; context.root_handle = handle; @@ -270,11 +295,11 @@ walk_root_bridge(struct acpi_pci_root *root, acpi_walk_callback user_function) * @handle: points to an acpi_pci_root */ static int -acpi_pci_slot_add(struct acpi_pci_root *root) +acpi_pci_slot_add(acpi_handle handle) { acpi_status status; - status = walk_root_bridge(root, register_slot); + status = walk_root_bridge(handle, register_slot); if (ACPI_FAILURE(status)) err("%s: register_slot failure - %d\n", __func__, status); @@ -286,11 +311,10 @@ acpi_pci_slot_add(struct acpi_pci_root *root) * @handle: points to an acpi_pci_root */ static void -acpi_pci_slot_remove(struct acpi_pci_root *root) +acpi_pci_slot_remove(acpi_handle handle) { struct acpi_pci_slot *slot, *tmp; struct pci_bus *pbus; - acpi_handle handle = root->device->handle; mutex_lock(&slot_list_lock); list_for_each_entry_safe(slot, tmp, &slot_list, list) { diff --git a/trunk/drivers/acpi/power.c b/trunk/drivers/acpi/power.c index 40e38a06ba85..215ecd097408 100644 --- a/trunk/drivers/acpi/power.c +++ b/trunk/drivers/acpi/power.c @@ -67,9 +67,7 @@ static const struct acpi_device_id power_device_ids[] = { }; MODULE_DEVICE_TABLE(acpi, power_device_ids); -#ifdef CONFIG_PM_SLEEP static int acpi_power_resume(struct device *dev); -#endif static SIMPLE_DEV_PM_OPS(acpi_power_pm, NULL, acpi_power_resume); static struct acpi_driver acpi_power_driver = { @@ -107,7 +105,6 @@ struct acpi_power_resource { /* List of devices relying on this power resource */ struct acpi_power_resource_device *devices; - struct mutex devices_lock; }; static struct list_head acpi_power_resource_list; @@ -226,6 +223,7 @@ static void acpi_power_on_device(struct acpi_power_managed_device *device) static int __acpi_power_on(struct acpi_power_resource *resource) { + struct acpi_power_resource_device *device_list = resource->devices; acpi_status status = AE_OK; status = acpi_evaluate_object(resource->device->handle, "_ON", NULL, NULL); @@ -238,15 +236,19 @@ static int __acpi_power_on(struct acpi_power_resource *resource) ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Power resource [%s] turned on\n", resource->name)); + while (device_list) { + acpi_power_on_device(device_list->device); + + device_list = device_list->next; + } + return 0; } static int acpi_power_on(acpi_handle handle) { int result = 0; - bool resume_device = false; struct acpi_power_resource *resource = NULL; - struct acpi_power_resource_device *device_list; result = acpi_power_get_context(handle, &resource); if (result) @@ -262,25 +264,10 @@ static int acpi_power_on(acpi_handle handle) result = __acpi_power_on(resource); if (result) resource->ref_count--; - else - resume_device = true; } mutex_unlock(&resource->resource_lock); - if (!resume_device) - return result; - - mutex_lock(&resource->devices_lock); - - device_list = resource->devices; - while (device_list) { - acpi_power_on_device(device_list->device); - device_list = device_list->next; - } - - mutex_unlock(&resource->devices_lock); - return result; } @@ -366,7 +353,7 @@ static void __acpi_power_resource_unregister_device(struct device *dev, if (acpi_power_get_context(res_handle, &resource)) return; - mutex_lock(&resource->devices_lock); + mutex_lock(&resource->resource_lock); prev = NULL; curr = resource->devices; while (curr) { @@ -383,7 +370,7 @@ static void __acpi_power_resource_unregister_device(struct device *dev, prev = curr; curr = curr->next; } - mutex_unlock(&resource->devices_lock); + mutex_unlock(&resource->resource_lock); } /* Unlink dev from all power resources in _PR0 */ @@ -425,10 +412,10 @@ static int __acpi_power_resource_register_device( power_resource_device->device = powered_device; - mutex_lock(&resource->devices_lock); + mutex_lock(&resource->resource_lock); power_resource_device->next = resource->devices; resource->devices = power_resource_device; - mutex_unlock(&resource->devices_lock); + mutex_unlock(&resource->resource_lock); return 0; } @@ -473,7 +460,7 @@ int acpi_power_resource_register_device(struct device *dev, acpi_handle handle) return ret; no_power_resource: - printk(KERN_DEBUG PREFIX "Invalid Power Resource to register!"); + printk(KERN_WARNING PREFIX "Invalid Power Resource to register!"); return -ENODEV; } EXPORT_SYMBOL_GPL(acpi_power_resource_register_device); @@ -732,7 +719,6 @@ static int acpi_power_add(struct acpi_device *device) resource->device = device; mutex_init(&resource->resource_lock); - mutex_init(&resource->devices_lock); strcpy(resource->name, device->pnp.bus_id); strcpy(acpi_device_name(device), ACPI_POWER_DEVICE_NAME); strcpy(acpi_device_class(device), ACPI_POWER_CLASS); @@ -789,7 +775,6 @@ static int acpi_power_remove(struct acpi_device *device, int type) return 0; } -#ifdef CONFIG_PM_SLEEP static int acpi_power_resume(struct device *dev) { int result = 0, state; @@ -818,7 +803,6 @@ static int acpi_power_resume(struct device *dev) return result; } -#endif int __init acpi_power_init(void) { diff --git a/trunk/drivers/acpi/processor_driver.c b/trunk/drivers/acpi/processor_driver.c index bfc31cb0dd3e..ff8e04f2fab4 100644 --- a/trunk/drivers/acpi/processor_driver.c +++ b/trunk/drivers/acpi/processor_driver.c @@ -437,7 +437,7 @@ static int acpi_cpu_soft_notify(struct notifier_block *nfb, /* Normal CPU soft online event */ } else { acpi_processor_ppc_has_changed(pr, 0); - acpi_processor_hotplug(pr); + acpi_processor_cst_has_changed(pr); acpi_processor_reevaluate_tstate(pr, action); acpi_processor_tstate_has_changed(pr); } diff --git a/trunk/drivers/acpi/sbs.c b/trunk/drivers/acpi/sbs.c index ff0740e0a9c2..c0b9aa5faf4c 100644 --- a/trunk/drivers/acpi/sbs.c +++ b/trunk/drivers/acpi/sbs.c @@ -988,7 +988,6 @@ static void acpi_sbs_rmdirs(void) #endif } -#ifdef CONFIG_PM_SLEEP static int acpi_sbs_resume(struct device *dev) { struct acpi_sbs *sbs; @@ -998,7 +997,6 @@ static int acpi_sbs_resume(struct device *dev) acpi_sbs_callback(sbs); return 0; } -#endif static SIMPLE_DEV_PM_OPS(acpi_sbs_pm, NULL, acpi_sbs_resume); diff --git a/trunk/drivers/acpi/sleep.c b/trunk/drivers/acpi/sleep.c index fdcdbb652915..7a7a9c929247 100644 --- a/trunk/drivers/acpi/sleep.c +++ b/trunk/drivers/acpi/sleep.c @@ -28,7 +28,36 @@ #include "internal.h" #include "sleep.h" +u8 wake_sleep_flags = ACPI_NO_OPTIONAL_METHODS; +static unsigned int gts, bfs; +static int set_param_wake_flag(const char *val, struct kernel_param *kp) +{ + int ret = param_set_int(val, kp); + + if (ret) + return ret; + + if (kp->arg == (const char *)>s) { + if (gts) + wake_sleep_flags |= ACPI_EXECUTE_GTS; + else + wake_sleep_flags &= ~ACPI_EXECUTE_GTS; + } + if (kp->arg == (const char *)&bfs) { + if (bfs) + wake_sleep_flags |= ACPI_EXECUTE_BFS; + else + wake_sleep_flags &= ~ACPI_EXECUTE_BFS; + } + return ret; +} +module_param_call(gts, set_param_wake_flag, param_get_int, >s, 0644); +module_param_call(bfs, set_param_wake_flag, param_get_int, &bfs, 0644); +MODULE_PARM_DESC(gts, "Enable evaluation of _GTS on suspend."); +MODULE_PARM_DESC(bfs, "Enable evaluation of _BFS on resume".); + static u8 sleep_states[ACPI_S_STATE_COUNT]; +static bool pwr_btn_event_pending; static void acpi_sleep_tts_switch(u32 acpi_state) { @@ -81,7 +110,6 @@ static int acpi_sleep_prepare(u32 acpi_state) #ifdef CONFIG_ACPI_SLEEP static u32 acpi_target_sleep_state = ACPI_STATE_S0; -static bool pwr_btn_event_pending; /* * The ACPI specification wants us to save NVS memory regions during hibernation @@ -277,7 +305,7 @@ static int acpi_suspend_enter(suspend_state_t pm_state) switch (acpi_state) { case ACPI_STATE_S1: barrier(); - status = acpi_enter_sleep_state(acpi_state); + status = acpi_enter_sleep_state(acpi_state, wake_sleep_flags); break; case ACPI_STATE_S3: @@ -291,8 +319,8 @@ static int acpi_suspend_enter(suspend_state_t pm_state) /* This violates the spec but is required for bug compatibility. */ acpi_write_bit_register(ACPI_BITREG_SCI_ENABLE, 1); - /* Reprogram control registers */ - acpi_leave_sleep_state_prep(acpi_state); + /* Reprogram control registers and execute _BFS */ + acpi_leave_sleep_state_prep(acpi_state, wake_sleep_flags); /* ACPI 3.0 specs (P62) says that it's the responsibility * of the OSPM to clear the status bit [ implying that the @@ -575,9 +603,9 @@ static int acpi_hibernation_enter(void) ACPI_FLUSH_CPU_CACHE(); /* This shouldn't return. If it returns, we have a problem */ - status = acpi_enter_sleep_state(ACPI_STATE_S4); - /* Reprogram control registers */ - acpi_leave_sleep_state_prep(ACPI_STATE_S4); + status = acpi_enter_sleep_state(ACPI_STATE_S4, wake_sleep_flags); + /* Reprogram control registers and execute _BFS */ + acpi_leave_sleep_state_prep(ACPI_STATE_S4, wake_sleep_flags); return ACPI_SUCCESS(status) ? 0 : -EFAULT; } @@ -589,8 +617,8 @@ static void acpi_hibernation_leave(void) * enable it here. */ acpi_enable(); - /* Reprogram control registers */ - acpi_leave_sleep_state_prep(ACPI_STATE_S4); + /* Reprogram control registers and execute _BFS */ + acpi_leave_sleep_state_prep(ACPI_STATE_S4, wake_sleep_flags); /* Check the hardware signature */ if (facs && s4_hardware_signature != facs->hardware_signature) { printk(KERN_EMERG "ACPI: Hardware changed while hibernated, " @@ -864,7 +892,33 @@ static void acpi_power_off(void) /* acpi_sleep_prepare(ACPI_STATE_S5) should have already been called */ printk(KERN_DEBUG "%s called\n", __func__); local_irq_disable(); - acpi_enter_sleep_state(ACPI_STATE_S5); + acpi_enter_sleep_state(ACPI_STATE_S5, wake_sleep_flags); +} + +/* + * ACPI 2.0 created the optional _GTS and _BFS, + * but industry adoption has been neither rapid nor broad. + * + * Linux gets into trouble when it executes poorly validated + * paths through the BIOS, so disable _GTS and _BFS by default, + * but do speak up and offer the option to enable them. + */ +static void __init acpi_gts_bfs_check(void) +{ + acpi_handle dummy; + + if (ACPI_SUCCESS(acpi_get_handle(ACPI_ROOT_OBJECT, METHOD_PATHNAME__GTS, &dummy))) + { + printk(KERN_NOTICE PREFIX "BIOS offers _GTS\n"); + printk(KERN_NOTICE PREFIX "If \"acpi.gts=1\" improves suspend, " + "please notify linux-acpi@vger.kernel.org\n"); + } + if (ACPI_SUCCESS(acpi_get_handle(ACPI_ROOT_OBJECT, METHOD_PATHNAME__BFS, &dummy))) + { + printk(KERN_NOTICE PREFIX "BIOS offers _BFS\n"); + printk(KERN_NOTICE PREFIX "If \"acpi.bfs=1\" improves resume, " + "please notify linux-acpi@vger.kernel.org\n"); + } } int __init acpi_sleep_init(void) @@ -925,5 +979,6 @@ int __init acpi_sleep_init(void) * object can also be evaluated when the system enters S5. */ register_reboot_notifier(&tts_notifier); + acpi_gts_bfs_check(); return 0; } diff --git a/trunk/drivers/acpi/sysfs.c b/trunk/drivers/acpi/sysfs.c index 7c3f98ba4afe..240a24400976 100644 --- a/trunk/drivers/acpi/sysfs.c +++ b/trunk/drivers/acpi/sysfs.c @@ -173,7 +173,7 @@ static int param_set_trace_state(const char *val, struct kernel_param *kp) { int result = 0; - if (!strncmp(val, "enable", sizeof("enable") - 1)) { + if (!strncmp(val, "enable", strlen("enable"))) { result = acpi_debug_trace(trace_method_name, trace_debug_level, trace_debug_layer, 0); if (result) @@ -181,7 +181,7 @@ static int param_set_trace_state(const char *val, struct kernel_param *kp) goto exit; } - if (!strncmp(val, "disable", sizeof("disable") - 1)) { + if (!strncmp(val, "disable", strlen("disable"))) { int name = 0; result = acpi_debug_trace((char *)&name, trace_debug_level, trace_debug_layer, 0); diff --git a/trunk/drivers/acpi/thermal.c b/trunk/drivers/acpi/thermal.c index edda74a43406..9fe90e9fecb5 100644 --- a/trunk/drivers/acpi/thermal.c +++ b/trunk/drivers/acpi/thermal.c @@ -106,9 +106,7 @@ static const struct acpi_device_id thermal_device_ids[] = { }; MODULE_DEVICE_TABLE(acpi, thermal_device_ids); -#ifdef CONFIG_PM_SLEEP static int acpi_thermal_resume(struct device *dev); -#endif static SIMPLE_DEV_PM_OPS(acpi_thermal_pm, NULL, acpi_thermal_resume); static struct acpi_driver acpi_thermal_driver = { @@ -1043,7 +1041,6 @@ static int acpi_thermal_remove(struct acpi_device *device, int type) return 0; } -#ifdef CONFIG_PM_SLEEP static int acpi_thermal_resume(struct device *dev) { struct acpi_thermal *tz; @@ -1078,7 +1075,6 @@ static int acpi_thermal_resume(struct device *dev) return AE_OK; } -#endif static int thermal_act(const struct dmi_system_id *d) { diff --git a/trunk/drivers/ata/Kconfig b/trunk/drivers/ata/Kconfig index 27cecd313e75..2be8ef1d3093 100644 --- a/trunk/drivers/ata/Kconfig +++ b/trunk/drivers/ata/Kconfig @@ -115,7 +115,7 @@ config SATA_SIL24 If unsure, say N. config ATA_SFF - bool "ATA SFF support (for legacy IDE and PATA)" + bool "ATA SFF support" default y help This option adds support for ATA controllers with SFF diff --git a/trunk/drivers/ata/ahci.c b/trunk/drivers/ata/ahci.c index 7862d17976b7..062e6a1a248f 100644 --- a/trunk/drivers/ata/ahci.c +++ b/trunk/drivers/ata/ahci.c @@ -256,21 +256,10 @@ static const struct pci_device_id ahci_pci_tbl[] = { { PCI_VDEVICE(INTEL, 0x8c07), board_ahci }, /* Lynx Point RAID */ { PCI_VDEVICE(INTEL, 0x8c0e), board_ahci }, /* Lynx Point RAID */ { PCI_VDEVICE(INTEL, 0x8c0f), board_ahci }, /* Lynx Point RAID */ - { PCI_VDEVICE(INTEL, 0x9c02), board_ahci }, /* Lynx Point-LP AHCI */ - { PCI_VDEVICE(INTEL, 0x9c03), board_ahci }, /* Lynx Point-LP AHCI */ - { PCI_VDEVICE(INTEL, 0x9c04), board_ahci }, /* Lynx Point-LP RAID */ - { PCI_VDEVICE(INTEL, 0x9c05), board_ahci }, /* Lynx Point-LP RAID */ - { PCI_VDEVICE(INTEL, 0x9c06), board_ahci }, /* Lynx Point-LP RAID */ - { PCI_VDEVICE(INTEL, 0x9c07), board_ahci }, /* Lynx Point-LP RAID */ - { PCI_VDEVICE(INTEL, 0x9c0e), board_ahci }, /* Lynx Point-LP RAID */ - { PCI_VDEVICE(INTEL, 0x9c0f), board_ahci }, /* Lynx Point-LP RAID */ /* JMicron 360/1/3/5/6, match class to avoid IDE function */ { PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff, board_ahci_ign_iferr }, - /* JMicron 362B and 362C have an AHCI function with IDE class code */ - { PCI_VDEVICE(JMICRON, 0x2362), board_ahci_ign_iferr }, - { PCI_VDEVICE(JMICRON, 0x236f), board_ahci_ign_iferr }, /* ATI */ { PCI_VDEVICE(ATI, 0x4380), board_ahci_sb600 }, /* ATI SB600 */ @@ -396,8 +385,6 @@ static const struct pci_device_id ahci_pci_tbl[] = { .driver_data = board_ahci_yes_fbs }, /* 88se9125 */ { PCI_DEVICE(0x1b4b, 0x917a), .driver_data = board_ahci_yes_fbs }, /* 88se9172 */ - { PCI_DEVICE(0x1b4b, 0x9192), - .driver_data = board_ahci_yes_fbs }, /* 88se9172 on some Gigabyte */ { PCI_DEVICE(0x1b4b, 0x91a3), .driver_data = board_ahci_yes_fbs }, @@ -405,10 +392,7 @@ static const struct pci_device_id ahci_pci_tbl[] = { { PCI_VDEVICE(PROMISE, 0x3f20), board_ahci }, /* PDC42819 */ /* Asmedia */ - { PCI_VDEVICE(ASMEDIA, 0x0601), board_ahci }, /* ASM1060 */ - { PCI_VDEVICE(ASMEDIA, 0x0602), board_ahci }, /* ASM1060 */ - { PCI_VDEVICE(ASMEDIA, 0x0611), board_ahci }, /* ASM1061 */ - { PCI_VDEVICE(ASMEDIA, 0x0612), board_ahci }, /* ASM1062 */ + { PCI_VDEVICE(ASMEDIA, 0x0612), board_ahci }, /* ASM1061 */ /* Generic, PCI class code for AHCI */ { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, diff --git a/trunk/drivers/ata/ahci.h b/trunk/drivers/ata/ahci.h index 57eb1c212a4c..c2594ddf25b0 100644 --- a/trunk/drivers/ata/ahci.h +++ b/trunk/drivers/ata/ahci.h @@ -320,7 +320,6 @@ extern struct device_attribute *ahci_sdev_attrs[]; extern struct ata_port_operations ahci_ops; extern struct ata_port_operations ahci_pmp_retry_srst_ops; -unsigned int ahci_dev_classify(struct ata_port *ap); void ahci_fill_cmd_slot(struct ahci_port_priv *pp, unsigned int tag, u32 opts); void ahci_save_initial_config(struct device *dev, diff --git a/trunk/drivers/ata/ata_piix.c b/trunk/drivers/ata/ata_piix.c index ef773e12af79..3c809bfbccf5 100644 --- a/trunk/drivers/ata/ata_piix.c +++ b/trunk/drivers/ata/ata_piix.c @@ -329,14 +329,6 @@ static const struct pci_device_id piix_pci_tbl[] = { { 0x8086, 0x8c08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, /* SATA Controller IDE (Lynx Point) */ { 0x8086, 0x8c09, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, - /* SATA Controller IDE (Lynx Point-LP) */ - { 0x8086, 0x9c00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_snb }, - /* SATA Controller IDE (Lynx Point-LP) */ - { 0x8086, 0x9c01, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_snb }, - /* SATA Controller IDE (Lynx Point-LP) */ - { 0x8086, 0x9c08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, - /* SATA Controller IDE (Lynx Point-LP) */ - { 0x8086, 0x9c09, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, /* SATA Controller IDE (DH89xxCC) */ { 0x8086, 0x2326, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, { } /* terminate list */ diff --git a/trunk/drivers/ata/libahci.c b/trunk/drivers/ata/libahci.c index 555c07afa05b..f9eaa82311a9 100644 --- a/trunk/drivers/ata/libahci.c +++ b/trunk/drivers/ata/libahci.c @@ -1139,7 +1139,7 @@ static void ahci_dev_config(struct ata_device *dev) } } -unsigned int ahci_dev_classify(struct ata_port *ap) +static unsigned int ahci_dev_classify(struct ata_port *ap) { void __iomem *port_mmio = ahci_port_base(ap); struct ata_taskfile tf; @@ -1153,7 +1153,6 @@ unsigned int ahci_dev_classify(struct ata_port *ap) return ata_dev_classify(&tf); } -EXPORT_SYMBOL_GPL(ahci_dev_classify); void ahci_fill_cmd_slot(struct ahci_port_priv *pp, unsigned int tag, u32 opts) diff --git a/trunk/drivers/ata/libata-acpi.c b/trunk/drivers/ata/libata-acpi.c index fd9ecf74e631..902b5a457170 100644 --- a/trunk/drivers/ata/libata-acpi.c +++ b/trunk/drivers/ata/libata-acpi.c @@ -60,7 +60,17 @@ acpi_handle ata_ap_acpi_handle(struct ata_port *ap) if (ap->flags & ATA_FLAG_ACPI_SATA) return NULL; - return acpi_get_child(DEVICE_ACPI_HANDLE(ap->host->dev), ap->port_no); + /* + * If acpi bind operation has already happened, we can get the handle + * for the port by checking the corresponding scsi_host device's + * firmware node, otherwise we will need to find out the handle from + * its parent's acpi node. + */ + if (ap->scsi_host) + return DEVICE_ACPI_HANDLE(&ap->scsi_host->shost_gendev); + else + return acpi_get_child(DEVICE_ACPI_HANDLE(ap->host->dev), + ap->port_no); } EXPORT_SYMBOL(ata_ap_acpi_handle); @@ -1091,9 +1101,6 @@ static int ata_acpi_bind_host(struct ata_port *ap, acpi_handle *handle) if (!*handle) return -ENODEV; - if (ata_acpi_gtm(ap, &ap->__acpi_init_gtm) == 0) - ap->pflags |= ATA_PFLAG_INIT_GTM_VALID; - return 0; } diff --git a/trunk/drivers/ata/libata-core.c b/trunk/drivers/ata/libata-core.c index 8e1039c8e159..fadd5866d40f 100644 --- a/trunk/drivers/ata/libata-core.c +++ b/trunk/drivers/ata/libata-core.c @@ -4062,7 +4062,7 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = { { "_NEC DV5800A", NULL, ATA_HORKAGE_NODMA }, { "SAMSUNG CD-ROM SN-124", "N001", ATA_HORKAGE_NODMA }, { "Seagate STT20000A", NULL, ATA_HORKAGE_NODMA }, - { " 2GB ATA Flash Disk", "ADMA428M", ATA_HORKAGE_NODMA }, + { "2GB ATA Flash Disk", "ADMA428M", ATA_HORKAGE_NODMA }, /* Odd clown on sil3726/4726 PMPs */ { "Config Disk", NULL, ATA_HORKAGE_DISABLE }, @@ -4128,7 +4128,6 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = { /* Devices that do not need bridging limits applied */ { "MTRON MSP-SATA*", NULL, ATA_HORKAGE_BRIDGE_OK, }, - { "BUFFALO HD-QSU2/R5", NULL, ATA_HORKAGE_BRIDGE_OK, }, /* Devices which aren't very happy with higher link speeds */ { "WD My Book", NULL, ATA_HORKAGE_1_5_GBPS, }, diff --git a/trunk/drivers/ata/pata_atiixp.c b/trunk/drivers/ata/pata_atiixp.c index 24e51056ac26..361c75cea57b 100644 --- a/trunk/drivers/ata/pata_atiixp.c +++ b/trunk/drivers/ata/pata_atiixp.c @@ -20,7 +20,6 @@ #include #include #include -#include #define DRV_NAME "pata_atiixp" #define DRV_VERSION "0.4.6" @@ -34,26 +33,11 @@ enum { ATIIXP_IDE_UDMA_MODE = 0x56 }; -static const struct dmi_system_id attixp_cable_override_dmi_table[] = { - { - /* Board has onboard PATA<->SATA converters */ - .ident = "MSI E350DM-E33", - .matches = { - DMI_MATCH(DMI_BOARD_VENDOR, "MSI"), - DMI_MATCH(DMI_BOARD_NAME, "E350DM-E33(MS-7720)"), - }, - }, - { } -}; - static int atiixp_cable_detect(struct ata_port *ap) { struct pci_dev *pdev = to_pci_dev(ap->host->dev); u8 udma; - if (dmi_check_system(attixp_cable_override_dmi_table)) - return ATA_CBL_PATA40_SHORT; - /* Hack from drivers/ide/pci. Really we want to know how to do the raw detection not play follow the bios mode guess */ pci_read_config_byte(pdev, ATIIXP_IDE_UDMA_MODE + ap->port_no, &udma); diff --git a/trunk/drivers/atm/iphase.c b/trunk/drivers/atm/iphase.c index 96cce6d53195..d4386019af5d 100644 --- a/trunk/drivers/atm/iphase.c +++ b/trunk/drivers/atm/iphase.c @@ -2362,7 +2362,7 @@ static int __devinit ia_init(struct atm_dev *dev) { printk(DEV_LABEL " (itf %d): can't set up page mapping\n", dev->number); - return -ENOMEM; + return error; } IF_INIT(printk(DEV_LABEL " (itf %d): rev.%d,base=%p,irq=%d\n", dev->number, iadev->pci->revision, base, iadev->irq);) diff --git a/trunk/drivers/base/core.c b/trunk/drivers/base/core.c index abea76c36a4b..f338037a4f3d 100644 --- a/trunk/drivers/base/core.c +++ b/trunk/drivers/base/core.c @@ -184,17 +184,6 @@ static void device_release(struct kobject *kobj) struct device *dev = kobj_to_dev(kobj); struct device_private *p = dev->p; - /* - * Some platform devices are driven without driver attached - * and managed resources may have been acquired. Make sure - * all resources are released. - * - * Drivers still can add resources into device after device - * is deleted but alive, so release devres here to avoid - * possible memory leak. - */ - devres_release_all(dev); - if (dev->release) dev->release(dev); else if (dev->type && dev->type->release) @@ -1207,6 +1196,13 @@ void device_del(struct device *dev) bus_remove_device(dev); driver_deferred_probe_del(dev); + /* + * Some platform devices are driven without driver attached + * and managed resources may have been acquired. Make sure + * all resources are released. + */ + devres_release_all(dev); + /* Notify the platform of the removal, in case they * need to do anything... */ @@ -1865,20 +1861,25 @@ void device_shutdown(void) */ #ifdef CONFIG_PRINTK -static int -create_syslog_header(const struct device *dev, char *hdr, size_t hdrlen) +int __dev_printk(const char *level, const struct device *dev, + struct va_format *vaf) { + char dict[128]; + size_t dictlen = 0; const char *subsys; - size_t pos = 0; + + if (!dev) + return printk("%s(NULL device *): %pV", level, vaf); if (dev->class) subsys = dev->class->name; else if (dev->bus) subsys = dev->bus->name; else - return 0; + goto skip; - pos += snprintf(hdr + pos, hdrlen - pos, "SUBSYSTEM=%s", subsys); + dictlen += snprintf(dict + dictlen, sizeof(dict) - dictlen, + "SUBSYSTEM=%s", subsys); /* * Add device identifier DEVICE=: @@ -1894,63 +1895,28 @@ create_syslog_header(const struct device *dev, char *hdr, size_t hdrlen) c = 'b'; else c = 'c'; - pos++; - pos += snprintf(hdr + pos, hdrlen - pos, - "DEVICE=%c%u:%u", - c, MAJOR(dev->devt), MINOR(dev->devt)); + dictlen++; + dictlen += snprintf(dict + dictlen, sizeof(dict) - dictlen, + "DEVICE=%c%u:%u", + c, MAJOR(dev->devt), MINOR(dev->devt)); } else if (strcmp(subsys, "net") == 0) { struct net_device *net = to_net_dev(dev); - pos++; - pos += snprintf(hdr + pos, hdrlen - pos, - "DEVICE=n%u", net->ifindex); + dictlen++; + dictlen += snprintf(dict + dictlen, sizeof(dict) - dictlen, + "DEVICE=n%u", net->ifindex); } else { - pos++; - pos += snprintf(hdr + pos, hdrlen - pos, - "DEVICE=+%s:%s", subsys, dev_name(dev)); + dictlen++; + dictlen += snprintf(dict + dictlen, sizeof(dict) - dictlen, + "DEVICE=+%s:%s", subsys, dev_name(dev)); } - - return pos; -} -EXPORT_SYMBOL(create_syslog_header); - -int dev_vprintk_emit(int level, const struct device *dev, - const char *fmt, va_list args) -{ - char hdr[128]; - size_t hdrlen; - - hdrlen = create_syslog_header(dev, hdr, sizeof(hdr)); - - return vprintk_emit(0, level, hdrlen ? hdr : NULL, hdrlen, fmt, args); -} -EXPORT_SYMBOL(dev_vprintk_emit); - -int dev_printk_emit(int level, const struct device *dev, const char *fmt, ...) -{ - va_list args; - int r; - - va_start(args, fmt); - - r = dev_vprintk_emit(level, dev, fmt, args); - - va_end(args); - - return r; -} -EXPORT_SYMBOL(dev_printk_emit); - -static int __dev_printk(const char *level, const struct device *dev, - struct va_format *vaf) -{ - if (!dev) - return printk("%s(NULL device *): %pV", level, vaf); - - return dev_printk_emit(level[1] - '0', dev, - "%s %s: %pV", - dev_driver_string(dev), dev_name(dev), vaf); +skip: + return printk_emit(0, level[1] - '0', + dictlen ? dict : NULL, dictlen, + "%s %s: %pV", + dev_driver_string(dev), dev_name(dev), vaf); } +EXPORT_SYMBOL(__dev_printk); int dev_printk(const char *level, const struct device *dev, const char *fmt, ...) @@ -1965,7 +1931,6 @@ int dev_printk(const char *level, const struct device *dev, vaf.va = &args; r = __dev_printk(level, dev, &vaf); - va_end(args); return r; @@ -1985,7 +1950,6 @@ int func(const struct device *dev, const char *fmt, ...) \ vaf.va = &args; \ \ r = __dev_printk(kern_level, dev, &vaf); \ - \ va_end(args); \ \ return r; \ diff --git a/trunk/drivers/base/devres.c b/trunk/drivers/base/devres.c index 8731979d668a..2360adb7a58f 100644 --- a/trunk/drivers/base/devres.c +++ b/trunk/drivers/base/devres.c @@ -143,48 +143,6 @@ void * devres_alloc(dr_release_t release, size_t size, gfp_t gfp) EXPORT_SYMBOL_GPL(devres_alloc); #endif -/** - * devres_for_each_res - Resource iterator - * @dev: Device to iterate resource from - * @release: Look for resources associated with this release function - * @match: Match function (optional) - * @match_data: Data for the match function - * @fn: Function to be called for each matched resource. - * @data: Data for @fn, the 3rd parameter of @fn - * - * Call @fn for each devres of @dev which is associated with @release - * and for which @match returns 1. - * - * RETURNS: - * void - */ -void devres_for_each_res(struct device *dev, dr_release_t release, - dr_match_t match, void *match_data, - void (*fn)(struct device *, void *, void *), - void *data) -{ - struct devres_node *node; - struct devres_node *tmp; - unsigned long flags; - - if (!fn) - return; - - spin_lock_irqsave(&dev->devres_lock, flags); - list_for_each_entry_safe_reverse(node, tmp, - &dev->devres_head, entry) { - struct devres *dr = container_of(node, struct devres, node); - - if (node->release != release) - continue; - if (match && !match(dev, dr->data, match_data)) - continue; - fn(dev, dr->data, data); - } - spin_unlock_irqrestore(&dev->devres_lock, flags); -} -EXPORT_SYMBOL_GPL(devres_for_each_res); - /** * devres_free - Free device resource data * @res: Pointer to devres data to free diff --git a/trunk/drivers/base/dma-contiguous.c b/trunk/drivers/base/dma-contiguous.c index 34d94c762a1e..78efb0306a44 100644 --- a/trunk/drivers/base/dma-contiguous.c +++ b/trunk/drivers/base/dma-contiguous.c @@ -250,7 +250,7 @@ int __init dma_declare_contiguous(struct device *dev, unsigned long size, return -EINVAL; /* Sanitise input arguments */ - alignment = PAGE_SIZE << max(MAX_ORDER - 1, pageblock_order); + alignment = PAGE_SIZE << max(MAX_ORDER, pageblock_order); base = ALIGN(base, alignment); size = ALIGN(size, alignment); limit &= ~(alignment - 1); diff --git a/trunk/drivers/base/firmware_class.c b/trunk/drivers/base/firmware_class.c index 6e210802c37b..803cfc1597a9 100644 --- a/trunk/drivers/base/firmware_class.c +++ b/trunk/drivers/base/firmware_class.c @@ -21,13 +21,6 @@ #include #include #include -#include -#include -#include -#include -#include - -#include "base.h" MODULE_AUTHOR("Manuel Estrada Sainz"); MODULE_DESCRIPTION("Multi purpose firmware loading support"); @@ -92,168 +85,23 @@ static inline long firmware_loading_timeout(void) return loading_timeout > 0 ? loading_timeout * HZ : MAX_SCHEDULE_TIMEOUT; } -struct firmware_cache { - /* firmware_buf instance will be added into the below list */ - spinlock_t lock; - struct list_head head; - int state; - -#ifdef CONFIG_PM_SLEEP - /* - * Names of firmware images which have been cached successfully - * will be added into the below list so that device uncache - * helper can trace which firmware images have been cached - * before. - */ - spinlock_t name_lock; - struct list_head fw_names; - - wait_queue_head_t wait_queue; - int cnt; - struct delayed_work work; - - struct notifier_block pm_notify; -#endif -}; +/* fw_lock could be moved to 'struct firmware_priv' but since it is just + * guarding for corner cases a global lock should be OK */ +static DEFINE_MUTEX(fw_lock); -struct firmware_buf { - struct kref ref; - struct list_head list; +struct firmware_priv { struct completion completion; - struct firmware_cache *fwc; + struct firmware *fw; unsigned long status; - void *data; - size_t size; struct page **pages; int nr_pages; int page_array_size; - char fw_id[]; -}; - -struct fw_cache_entry { - struct list_head list; - char name[]; -}; - -struct firmware_priv { struct timer_list timeout; - bool nowait; struct device dev; - struct firmware_buf *buf; - struct firmware *fw; -}; - -struct fw_name_devm { - unsigned long magic; - char name[]; + bool nowait; + char fw_id[]; }; -#define to_fwbuf(d) container_of(d, struct firmware_buf, ref) - -#define FW_LOADER_NO_CACHE 0 -#define FW_LOADER_START_CACHE 1 - -static int fw_cache_piggyback_on_request(const char *name); - -/* fw_lock could be moved to 'struct firmware_priv' but since it is just - * guarding for corner cases a global lock should be OK */ -static DEFINE_MUTEX(fw_lock); - -static struct firmware_cache fw_cache; - -static struct firmware_buf *__allocate_fw_buf(const char *fw_name, - struct firmware_cache *fwc) -{ - struct firmware_buf *buf; - - buf = kzalloc(sizeof(*buf) + strlen(fw_name) + 1 , GFP_ATOMIC); - - if (!buf) - return buf; - - kref_init(&buf->ref); - strcpy(buf->fw_id, fw_name); - buf->fwc = fwc; - init_completion(&buf->completion); - - pr_debug("%s: fw-%s buf=%p\n", __func__, fw_name, buf); - - return buf; -} - -static struct firmware_buf *__fw_lookup_buf(const char *fw_name) -{ - struct firmware_buf *tmp; - struct firmware_cache *fwc = &fw_cache; - - list_for_each_entry(tmp, &fwc->head, list) - if (!strcmp(tmp->fw_id, fw_name)) - return tmp; - return NULL; -} - -static int fw_lookup_and_allocate_buf(const char *fw_name, - struct firmware_cache *fwc, - struct firmware_buf **buf) -{ - struct firmware_buf *tmp; - - spin_lock(&fwc->lock); - tmp = __fw_lookup_buf(fw_name); - if (tmp) { - kref_get(&tmp->ref); - spin_unlock(&fwc->lock); - *buf = tmp; - return 1; - } - tmp = __allocate_fw_buf(fw_name, fwc); - if (tmp) - list_add(&tmp->list, &fwc->head); - spin_unlock(&fwc->lock); - - *buf = tmp; - - return tmp ? 0 : -ENOMEM; -} - -static struct firmware_buf *fw_lookup_buf(const char *fw_name) -{ - struct firmware_buf *tmp; - struct firmware_cache *fwc = &fw_cache; - - spin_lock(&fwc->lock); - tmp = __fw_lookup_buf(fw_name); - spin_unlock(&fwc->lock); - - return tmp; -} - -static void __fw_free_buf(struct kref *ref) -{ - struct firmware_buf *buf = to_fwbuf(ref); - struct firmware_cache *fwc = buf->fwc; - int i; - - pr_debug("%s: fw-%s buf=%p data=%p size=%u\n", - __func__, buf->fw_id, buf, buf->data, - (unsigned int)buf->size); - - spin_lock(&fwc->lock); - list_del(&buf->list); - spin_unlock(&fwc->lock); - - vunmap(buf->data); - for (i = 0; i < buf->nr_pages; i++) - __free_page(buf->pages[i]); - kfree(buf->pages); - kfree(buf); -} - -static void fw_free_buf(struct firmware_buf *buf) -{ - kref_put(&buf->ref, __fw_free_buf); -} - static struct firmware_priv *to_firmware_priv(struct device *dev) { return container_of(dev, struct firmware_priv, dev); @@ -261,10 +109,9 @@ static struct firmware_priv *to_firmware_priv(struct device *dev) static void fw_load_abort(struct firmware_priv *fw_priv) { - struct firmware_buf *buf = fw_priv->buf; - - set_bit(FW_STATUS_ABORT, &buf->status); - complete_all(&buf->completion); + set_bit(FW_STATUS_ABORT, &fw_priv->status); + wmb(); + complete(&fw_priv->completion); } static ssize_t firmware_timeout_show(struct class *class, @@ -307,7 +154,11 @@ static struct class_attribute firmware_class_attrs[] = { static void fw_dev_release(struct device *dev) { struct firmware_priv *fw_priv = to_firmware_priv(dev); + int i; + for (i = 0; i < fw_priv->nr_pages; i++) + __free_page(fw_priv->pages[i]); + kfree(fw_priv->pages); kfree(fw_priv); module_put(THIS_MODULE); @@ -317,7 +168,7 @@ static int firmware_uevent(struct device *dev, struct kobj_uevent_env *env) { struct firmware_priv *fw_priv = to_firmware_priv(dev); - if (add_uevent_var(env, "FIRMWARE=%s", fw_priv->buf->fw_id)) + if (add_uevent_var(env, "FIRMWARE=%s", fw_priv->fw_id)) return -ENOMEM; if (add_uevent_var(env, "TIMEOUT=%i", loading_timeout)) return -ENOMEM; @@ -338,16 +189,20 @@ static ssize_t firmware_loading_show(struct device *dev, struct device_attribute *attr, char *buf) { struct firmware_priv *fw_priv = to_firmware_priv(dev); - int loading = test_bit(FW_STATUS_LOADING, &fw_priv->buf->status); + int loading = test_bit(FW_STATUS_LOADING, &fw_priv->status); return sprintf(buf, "%d\n", loading); } -/* firmware holds the ownership of pages */ static void firmware_free_data(const struct firmware *fw) { - WARN_ON(!fw->priv); - fw_free_buf(fw->priv); + int i; + vunmap(fw->data); + if (fw->pages) { + for (i = 0; i < PFN_UP(fw->size); i++) + __free_page(fw->pages[i]); + kfree(fw->pages); + } } /* Some architectures don't have PAGE_KERNEL_RO */ @@ -372,33 +227,45 @@ static ssize_t firmware_loading_store(struct device *dev, const char *buf, size_t count) { struct firmware_priv *fw_priv = to_firmware_priv(dev); - struct firmware_buf *fw_buf = fw_priv->buf; int loading = simple_strtol(buf, NULL, 10); int i; mutex_lock(&fw_lock); - if (!fw_buf) + if (!fw_priv->fw) goto out; switch (loading) { case 1: - /* discarding any previous partial load */ - if (!test_bit(FW_STATUS_DONE, &fw_buf->status)) { - for (i = 0; i < fw_buf->nr_pages; i++) - __free_page(fw_buf->pages[i]); - kfree(fw_buf->pages); - fw_buf->pages = NULL; - fw_buf->page_array_size = 0; - fw_buf->nr_pages = 0; - set_bit(FW_STATUS_LOADING, &fw_buf->status); - } + firmware_free_data(fw_priv->fw); + memset(fw_priv->fw, 0, sizeof(struct firmware)); + /* If the pages are not owned by 'struct firmware' */ + for (i = 0; i < fw_priv->nr_pages; i++) + __free_page(fw_priv->pages[i]); + kfree(fw_priv->pages); + fw_priv->pages = NULL; + fw_priv->page_array_size = 0; + fw_priv->nr_pages = 0; + set_bit(FW_STATUS_LOADING, &fw_priv->status); break; case 0: - if (test_bit(FW_STATUS_LOADING, &fw_buf->status)) { - set_bit(FW_STATUS_DONE, &fw_buf->status); - clear_bit(FW_STATUS_LOADING, &fw_buf->status); - complete_all(&fw_buf->completion); + if (test_bit(FW_STATUS_LOADING, &fw_priv->status)) { + vunmap(fw_priv->fw->data); + fw_priv->fw->data = vmap(fw_priv->pages, + fw_priv->nr_pages, + 0, PAGE_KERNEL_RO); + if (!fw_priv->fw->data) { + dev_err(dev, "%s: vmap() failed\n", __func__); + goto err; + } + /* Pages are now owned by 'struct firmware' */ + fw_priv->fw->pages = fw_priv->pages; + fw_priv->pages = NULL; + + fw_priv->page_array_size = 0; + fw_priv->nr_pages = 0; + complete(&fw_priv->completion); + clear_bit(FW_STATUS_LOADING, &fw_priv->status); break; } /* fallthrough */ @@ -406,6 +273,7 @@ static ssize_t firmware_loading_store(struct device *dev, dev_err(dev, "%s: unexpected value (%d)\n", __func__, loading); /* fallthrough */ case -1: + err: fw_load_abort(fw_priv); break; } @@ -422,21 +290,21 @@ static ssize_t firmware_data_read(struct file *filp, struct kobject *kobj, { struct device *dev = kobj_to_dev(kobj); struct firmware_priv *fw_priv = to_firmware_priv(dev); - struct firmware_buf *buf; + struct firmware *fw; ssize_t ret_count; mutex_lock(&fw_lock); - buf = fw_priv->buf; - if (!buf || test_bit(FW_STATUS_DONE, &buf->status)) { + fw = fw_priv->fw; + if (!fw || test_bit(FW_STATUS_DONE, &fw_priv->status)) { ret_count = -ENODEV; goto out; } - if (offset > buf->size) { + if (offset > fw->size) { ret_count = 0; goto out; } - if (count > buf->size - offset) - count = buf->size - offset; + if (count > fw->size - offset) + count = fw->size - offset; ret_count = count; @@ -446,11 +314,11 @@ static ssize_t firmware_data_read(struct file *filp, struct kobject *kobj, int page_ofs = offset & (PAGE_SIZE-1); int page_cnt = min_t(size_t, PAGE_SIZE - page_ofs, count); - page_data = kmap(buf->pages[page_nr]); + page_data = kmap(fw_priv->pages[page_nr]); memcpy(buffer, page_data + page_ofs, page_cnt); - kunmap(buf->pages[page_nr]); + kunmap(fw_priv->pages[page_nr]); buffer += page_cnt; offset += page_cnt; count -= page_cnt; @@ -462,13 +330,12 @@ static ssize_t firmware_data_read(struct file *filp, struct kobject *kobj, static int fw_realloc_buffer(struct firmware_priv *fw_priv, int min_size) { - struct firmware_buf *buf = fw_priv->buf; int pages_needed = ALIGN(min_size, PAGE_SIZE) >> PAGE_SHIFT; /* If the array of pages is too small, grow it... */ - if (buf->page_array_size < pages_needed) { + if (fw_priv->page_array_size < pages_needed) { int new_array_size = max(pages_needed, - buf->page_array_size * 2); + fw_priv->page_array_size * 2); struct page **new_pages; new_pages = kmalloc(new_array_size * sizeof(void *), @@ -477,24 +344,24 @@ static int fw_realloc_buffer(struct firmware_priv *fw_priv, int min_size) fw_load_abort(fw_priv); return -ENOMEM; } - memcpy(new_pages, buf->pages, - buf->page_array_size * sizeof(void *)); - memset(&new_pages[buf->page_array_size], 0, sizeof(void *) * - (new_array_size - buf->page_array_size)); - kfree(buf->pages); - buf->pages = new_pages; - buf->page_array_size = new_array_size; + memcpy(new_pages, fw_priv->pages, + fw_priv->page_array_size * sizeof(void *)); + memset(&new_pages[fw_priv->page_array_size], 0, sizeof(void *) * + (new_array_size - fw_priv->page_array_size)); + kfree(fw_priv->pages); + fw_priv->pages = new_pages; + fw_priv->page_array_size = new_array_size; } - while (buf->nr_pages < pages_needed) { - buf->pages[buf->nr_pages] = + while (fw_priv->nr_pages < pages_needed) { + fw_priv->pages[fw_priv->nr_pages] = alloc_page(GFP_KERNEL | __GFP_HIGHMEM); - if (!buf->pages[buf->nr_pages]) { + if (!fw_priv->pages[fw_priv->nr_pages]) { fw_load_abort(fw_priv); return -ENOMEM; } - buf->nr_pages++; + fw_priv->nr_pages++; } return 0; } @@ -517,19 +384,18 @@ static ssize_t firmware_data_write(struct file *filp, struct kobject *kobj, { struct device *dev = kobj_to_dev(kobj); struct firmware_priv *fw_priv = to_firmware_priv(dev); - struct firmware_buf *buf; + struct firmware *fw; ssize_t retval; if (!capable(CAP_SYS_RAWIO)) return -EPERM; mutex_lock(&fw_lock); - buf = fw_priv->buf; - if (!buf || test_bit(FW_STATUS_DONE, &buf->status)) { + fw = fw_priv->fw; + if (!fw || test_bit(FW_STATUS_DONE, &fw_priv->status)) { retval = -ENODEV; goto out; } - retval = fw_realloc_buffer(fw_priv, offset + count); if (retval) goto out; @@ -542,17 +408,17 @@ static ssize_t firmware_data_write(struct file *filp, struct kobject *kobj, int page_ofs = offset & (PAGE_SIZE - 1); int page_cnt = min_t(size_t, PAGE_SIZE - page_ofs, count); - page_data = kmap(buf->pages[page_nr]); + page_data = kmap(fw_priv->pages[page_nr]); memcpy(page_data + page_ofs, buffer, page_cnt); - kunmap(buf->pages[page_nr]); + kunmap(fw_priv->pages[page_nr]); buffer += page_cnt; offset += page_cnt; count -= page_cnt; } - buf->size = max_t(size_t, offset, buf->size); + fw->size = max_t(size_t, offset, fw->size); out: mutex_unlock(&fw_lock); return retval; @@ -579,110 +445,27 @@ fw_create_instance(struct firmware *firmware, const char *fw_name, struct firmware_priv *fw_priv; struct device *f_dev; - fw_priv = kzalloc(sizeof(*fw_priv), GFP_KERNEL); + fw_priv = kzalloc(sizeof(*fw_priv) + strlen(fw_name) + 1 , GFP_KERNEL); if (!fw_priv) { dev_err(device, "%s: kmalloc failed\n", __func__); - fw_priv = ERR_PTR(-ENOMEM); - goto exit; + return ERR_PTR(-ENOMEM); } - fw_priv->nowait = nowait; fw_priv->fw = firmware; + fw_priv->nowait = nowait; + strcpy(fw_priv->fw_id, fw_name); + init_completion(&fw_priv->completion); setup_timer(&fw_priv->timeout, firmware_class_timeout, (u_long) fw_priv); f_dev = &fw_priv->dev; device_initialize(f_dev); - dev_set_name(f_dev, "%s", fw_name); + dev_set_name(f_dev, "%s", dev_name(device)); f_dev->parent = device; f_dev->class = &firmware_class; -exit: - return fw_priv; -} - -/* one pages buffer is mapped/unmapped only once */ -static int fw_map_pages_buf(struct firmware_buf *buf) -{ - buf->data = vmap(buf->pages, buf->nr_pages, 0, PAGE_KERNEL_RO); - if (!buf->data) - return -ENOMEM; - return 0; -} - -/* store the pages buffer info firmware from buf */ -static void fw_set_page_data(struct firmware_buf *buf, struct firmware *fw) -{ - fw->priv = buf; - fw->pages = buf->pages; - fw->size = buf->size; - fw->data = buf->data; - - pr_debug("%s: fw-%s buf=%p data=%p size=%u\n", - __func__, buf->fw_id, buf, buf->data, - (unsigned int)buf->size); -} - -#ifdef CONFIG_PM_SLEEP -static void fw_name_devm_release(struct device *dev, void *res) -{ - struct fw_name_devm *fwn = res; - - if (fwn->magic == (unsigned long)&fw_cache) - pr_debug("%s: fw_name-%s devm-%p released\n", - __func__, fwn->name, res); -} - -static int fw_devm_match(struct device *dev, void *res, - void *match_data) -{ - struct fw_name_devm *fwn = res; - - return (fwn->magic == (unsigned long)&fw_cache) && - !strcmp(fwn->name, match_data); -} - -static struct fw_name_devm *fw_find_devm_name(struct device *dev, - const char *name) -{ - struct fw_name_devm *fwn; - - fwn = devres_find(dev, fw_name_devm_release, - fw_devm_match, (void *)name); - return fwn; -} -/* add firmware name into devres list */ -static int fw_add_devm_name(struct device *dev, const char *name) -{ - struct fw_name_devm *fwn; - - fwn = fw_find_devm_name(dev, name); - if (fwn) - return 1; - - fwn = devres_alloc(fw_name_devm_release, sizeof(struct fw_name_devm) + - strlen(name) + 1, GFP_KERNEL); - if (!fwn) - return -ENOMEM; - - fwn->magic = (unsigned long)&fw_cache; - strcpy(fwn->name, name); - devres_add(dev, fwn); - - return 0; -} -#else -static int fw_add_devm_name(struct device *dev, const char *name) -{ - return 0; -} -#endif - -static void _request_firmware_cleanup(const struct firmware **firmware_p) -{ - release_firmware(*firmware_p); - *firmware_p = NULL; + return fw_priv; } static struct firmware_priv * @@ -690,9 +473,7 @@ _request_firmware_prepare(const struct firmware **firmware_p, const char *name, struct device *device, bool uevent, bool nowait) { struct firmware *firmware; - struct firmware_priv *fw_priv = NULL; - struct firmware_buf *buf; - int ret; + struct firmware_priv *fw_priv; if (!firmware_p) return ERR_PTR(-EINVAL); @@ -709,55 +490,25 @@ _request_firmware_prepare(const struct firmware **firmware_p, const char *name, return NULL; } - ret = fw_lookup_and_allocate_buf(name, &fw_cache, &buf); - if (!ret) - fw_priv = fw_create_instance(firmware, name, device, - uevent, nowait); - - if (IS_ERR(fw_priv) || ret < 0) { - kfree(firmware); + fw_priv = fw_create_instance(firmware, name, device, uevent, nowait); + if (IS_ERR(fw_priv)) { + release_firmware(firmware); *firmware_p = NULL; - return ERR_PTR(-ENOMEM); - } else if (fw_priv) { - fw_priv->buf = buf; - - /* - * bind with 'buf' now to avoid warning in failure path - * of requesting firmware. - */ - firmware->priv = buf; - return fw_priv; } - - /* share the cached buf, which is inprogessing or completed */ - check_status: - mutex_lock(&fw_lock); - if (test_bit(FW_STATUS_ABORT, &buf->status)) { - fw_priv = ERR_PTR(-ENOENT); - firmware->priv = buf; - _request_firmware_cleanup(firmware_p); - goto exit; - } else if (test_bit(FW_STATUS_DONE, &buf->status)) { - fw_priv = NULL; - fw_set_page_data(buf, firmware); - goto exit; - } - mutex_unlock(&fw_lock); - wait_for_completion(&buf->completion); - goto check_status; - -exit: - mutex_unlock(&fw_lock); return fw_priv; } +static void _request_firmware_cleanup(const struct firmware **firmware_p) +{ + release_firmware(*firmware_p); + *firmware_p = NULL; +} + static int _request_firmware_load(struct firmware_priv *fw_priv, bool uevent, long timeout) { int retval = 0; struct device *f_dev = &fw_priv->dev; - struct firmware_buf *buf = fw_priv->buf; - struct firmware_cache *fwc = &fw_cache; dev_set_uevent_suppress(f_dev, true); @@ -784,7 +535,7 @@ static int _request_firmware_load(struct firmware_priv *fw_priv, bool uevent, if (uevent) { dev_set_uevent_suppress(f_dev, false); - dev_dbg(f_dev, "firmware: requesting %s\n", buf->fw_id); + dev_dbg(f_dev, "firmware: requesting %s\n", fw_priv->fw_id); if (timeout != MAX_SCHEDULE_TIMEOUT) mod_timer(&fw_priv->timeout, round_jiffies_up(jiffies + timeout)); @@ -792,40 +543,15 @@ static int _request_firmware_load(struct firmware_priv *fw_priv, bool uevent, kobject_uevent(&fw_priv->dev.kobj, KOBJ_ADD); } - wait_for_completion(&buf->completion); + wait_for_completion(&fw_priv->completion); + set_bit(FW_STATUS_DONE, &fw_priv->status); del_timer_sync(&fw_priv->timeout); mutex_lock(&fw_lock); - if (!buf->size || test_bit(FW_STATUS_ABORT, &buf->status)) + if (!fw_priv->fw->size || test_bit(FW_STATUS_ABORT, &fw_priv->status)) retval = -ENOENT; - - /* - * add firmware name into devres list so that we can auto cache - * and uncache firmware for device. - * - * f_dev->parent may has been deleted already, but the problem - * should be fixed in devres or driver core. - */ - if (!retval && f_dev->parent) - fw_add_devm_name(f_dev->parent, buf->fw_id); - - if (!retval) - retval = fw_map_pages_buf(buf); - - /* - * After caching firmware image is started, let it piggyback - * on request firmware. - */ - if (!retval && fwc->state == FW_LOADER_START_CACHE) { - if (fw_cache_piggyback_on_request(buf->fw_id)) - kref_get(&buf->ref); - } - - /* pass the pages buffer to driver at the last minute */ - fw_set_page_data(buf, fw_priv->fw); - - fw_priv->buf = NULL; + fw_priv->fw = NULL; mutex_unlock(&fw_lock); device_remove_file(f_dev, &dev_attr_loading); @@ -852,8 +578,6 @@ static int _request_firmware_load(struct firmware_priv *fw_priv, bool uevent, * @name will be used as $FIRMWARE in the uevent environment and * should be distinctive enough not to be confused with any other * firmware image for this or any other device. - * - * Caller must hold the reference count of @device. **/ int request_firmware(const struct firmware **firmware_p, const char *name, @@ -935,7 +659,6 @@ static void request_firmware_work_func(struct work_struct *work) out: fw_work->cont(fw, fw_work->context); - put_device(fw_work->device); module_put(fw_work->module); kfree(fw_work); @@ -954,15 +677,9 @@ static void request_firmware_work_func(struct work_struct *work) * @cont: function will be called asynchronously when the firmware * request is over. * - * Caller must hold the reference count of @device. - * - * Asynchronous variant of request_firmware() for user contexts: - * - sleep for as small periods as possible since it may - * increase kernel boot time of built-in device drivers - * requesting firmware in their ->probe() methods, if - * @gfp is GFP_KERNEL. - * - * - can't sleep at all if @gfp is GFP_ATOMIC. + * Asynchronous variant of request_firmware() for user contexts where + * it is not possible to sleep for long time. It can't be called + * in atomic contexts. **/ int request_firmware_nowait( @@ -988,363 +705,18 @@ request_firmware_nowait( return -EFAULT; } - get_device(fw_work->device); INIT_WORK(&fw_work->work, request_firmware_work_func); schedule_work(&fw_work->work); return 0; } -/** - * cache_firmware - cache one firmware image in kernel memory space - * @fw_name: the firmware image name - * - * Cache firmware in kernel memory so that drivers can use it when - * system isn't ready for them to request firmware image from userspace. - * Once it returns successfully, driver can use request_firmware or its - * nowait version to get the cached firmware without any interacting - * with userspace - * - * Return 0 if the firmware image has been cached successfully - * Return !0 otherwise - * - */ -int cache_firmware(const char *fw_name) -{ - int ret; - const struct firmware *fw; - - pr_debug("%s: %s\n", __func__, fw_name); - - ret = request_firmware(&fw, fw_name, NULL); - if (!ret) - kfree(fw); - - pr_debug("%s: %s ret=%d\n", __func__, fw_name, ret); - - return ret; -} - -/** - * uncache_firmware - remove one cached firmware image - * @fw_name: the firmware image name - * - * Uncache one firmware image which has been cached successfully - * before. - * - * Return 0 if the firmware cache has been removed successfully - * Return !0 otherwise - * - */ -int uncache_firmware(const char *fw_name) -{ - struct firmware_buf *buf; - struct firmware fw; - - pr_debug("%s: %s\n", __func__, fw_name); - - if (fw_get_builtin_firmware(&fw, fw_name)) - return 0; - - buf = fw_lookup_buf(fw_name); - if (buf) { - fw_free_buf(buf); - return 0; - } - - return -EINVAL; -} - -#ifdef CONFIG_PM_SLEEP -static struct fw_cache_entry *alloc_fw_cache_entry(const char *name) -{ - struct fw_cache_entry *fce; - - fce = kzalloc(sizeof(*fce) + strlen(name) + 1, GFP_ATOMIC); - if (!fce) - goto exit; - - strcpy(fce->name, name); -exit: - return fce; -} - -static int fw_cache_piggyback_on_request(const char *name) -{ - struct firmware_cache *fwc = &fw_cache; - struct fw_cache_entry *fce; - int ret = 0; - - spin_lock(&fwc->name_lock); - list_for_each_entry(fce, &fwc->fw_names, list) { - if (!strcmp(fce->name, name)) - goto found; - } - - fce = alloc_fw_cache_entry(name); - if (fce) { - ret = 1; - list_add(&fce->list, &fwc->fw_names); - pr_debug("%s: fw: %s\n", __func__, name); - } -found: - spin_unlock(&fwc->name_lock); - return ret; -} - -static void free_fw_cache_entry(struct fw_cache_entry *fce) -{ - kfree(fce); -} - -static void __async_dev_cache_fw_image(void *fw_entry, - async_cookie_t cookie) -{ - struct fw_cache_entry *fce = fw_entry; - struct firmware_cache *fwc = &fw_cache; - int ret; - - ret = cache_firmware(fce->name); - if (ret) { - spin_lock(&fwc->name_lock); - list_del(&fce->list); - spin_unlock(&fwc->name_lock); - - free_fw_cache_entry(fce); - } - - spin_lock(&fwc->name_lock); - fwc->cnt--; - spin_unlock(&fwc->name_lock); - - wake_up(&fwc->wait_queue); -} - -/* called with dev->devres_lock held */ -static void dev_create_fw_entry(struct device *dev, void *res, - void *data) -{ - struct fw_name_devm *fwn = res; - const char *fw_name = fwn->name; - struct list_head *head = data; - struct fw_cache_entry *fce; - - fce = alloc_fw_cache_entry(fw_name); - if (fce) - list_add(&fce->list, head); -} - -static int devm_name_match(struct device *dev, void *res, - void *match_data) -{ - struct fw_name_devm *fwn = res; - return (fwn->magic == (unsigned long)match_data); -} - -static void dev_cache_fw_image(struct device *dev, void *data) -{ - LIST_HEAD(todo); - struct fw_cache_entry *fce; - struct fw_cache_entry *fce_next; - struct firmware_cache *fwc = &fw_cache; - - devres_for_each_res(dev, fw_name_devm_release, - devm_name_match, &fw_cache, - dev_create_fw_entry, &todo); - - list_for_each_entry_safe(fce, fce_next, &todo, list) { - list_del(&fce->list); - - spin_lock(&fwc->name_lock); - fwc->cnt++; - list_add(&fce->list, &fwc->fw_names); - spin_unlock(&fwc->name_lock); - - async_schedule(__async_dev_cache_fw_image, (void *)fce); - } -} - -static void __device_uncache_fw_images(void) -{ - struct firmware_cache *fwc = &fw_cache; - struct fw_cache_entry *fce; - - spin_lock(&fwc->name_lock); - while (!list_empty(&fwc->fw_names)) { - fce = list_entry(fwc->fw_names.next, - struct fw_cache_entry, list); - list_del(&fce->list); - spin_unlock(&fwc->name_lock); - - uncache_firmware(fce->name); - free_fw_cache_entry(fce); - - spin_lock(&fwc->name_lock); - } - spin_unlock(&fwc->name_lock); -} - -/** - * device_cache_fw_images - cache devices' firmware - * - * If one device called request_firmware or its nowait version - * successfully before, the firmware names are recored into the - * device's devres link list, so device_cache_fw_images can call - * cache_firmware() to cache these firmwares for the device, - * then the device driver can load its firmwares easily at - * time when system is not ready to complete loading firmware. - */ -static void device_cache_fw_images(void) -{ - struct firmware_cache *fwc = &fw_cache; - int old_timeout; - DEFINE_WAIT(wait); - - pr_debug("%s\n", __func__); - - /* - * use small loading timeout for caching devices' firmware - * because all these firmware images have been loaded - * successfully at lease once, also system is ready for - * completing firmware loading now. The maximum size of - * firmware in current distributions is about 2M bytes, - * so 10 secs should be enough. - */ - old_timeout = loading_timeout; - loading_timeout = 10; - - mutex_lock(&fw_lock); - fwc->state = FW_LOADER_START_CACHE; - dpm_for_each_dev(NULL, dev_cache_fw_image); - mutex_unlock(&fw_lock); - - /* wait for completion of caching firmware for all devices */ - spin_lock(&fwc->name_lock); - for (;;) { - prepare_to_wait(&fwc->wait_queue, &wait, - TASK_UNINTERRUPTIBLE); - if (!fwc->cnt) - break; - - spin_unlock(&fwc->name_lock); - - schedule(); - - spin_lock(&fwc->name_lock); - } - spin_unlock(&fwc->name_lock); - finish_wait(&fwc->wait_queue, &wait); - - loading_timeout = old_timeout; -} - -/** - * device_uncache_fw_images - uncache devices' firmware - * - * uncache all firmwares which have been cached successfully - * by device_uncache_fw_images earlier - */ -static void device_uncache_fw_images(void) -{ - pr_debug("%s\n", __func__); - __device_uncache_fw_images(); -} - -static void device_uncache_fw_images_work(struct work_struct *work) -{ - device_uncache_fw_images(); -} - -/** - * device_uncache_fw_images_delay - uncache devices firmwares - * @delay: number of milliseconds to delay uncache device firmwares - * - * uncache all devices's firmwares which has been cached successfully - * by device_cache_fw_images after @delay milliseconds. - */ -static void device_uncache_fw_images_delay(unsigned long delay) -{ - schedule_delayed_work(&fw_cache.work, - msecs_to_jiffies(delay)); -} - -static int fw_pm_notify(struct notifier_block *notify_block, - unsigned long mode, void *unused) -{ - switch (mode) { - case PM_HIBERNATION_PREPARE: - case PM_SUSPEND_PREPARE: - device_cache_fw_images(); - break; - - case PM_POST_SUSPEND: - case PM_POST_HIBERNATION: - case PM_POST_RESTORE: - /* - * In case that system sleep failed and syscore_suspend is - * not called. - */ - mutex_lock(&fw_lock); - fw_cache.state = FW_LOADER_NO_CACHE; - mutex_unlock(&fw_lock); - - device_uncache_fw_images_delay(10 * MSEC_PER_SEC); - break; - } - - return 0; -} - -/* stop caching firmware once syscore_suspend is reached */ -static int fw_suspend(void) -{ - fw_cache.state = FW_LOADER_NO_CACHE; - return 0; -} - -static struct syscore_ops fw_syscore_ops = { - .suspend = fw_suspend, -}; -#else -static int fw_cache_piggyback_on_request(const char *name) -{ - return 0; -} -#endif - -static void __init fw_cache_init(void) -{ - spin_lock_init(&fw_cache.lock); - INIT_LIST_HEAD(&fw_cache.head); - fw_cache.state = FW_LOADER_NO_CACHE; - -#ifdef CONFIG_PM_SLEEP - spin_lock_init(&fw_cache.name_lock); - INIT_LIST_HEAD(&fw_cache.fw_names); - fw_cache.cnt = 0; - - init_waitqueue_head(&fw_cache.wait_queue); - INIT_DELAYED_WORK(&fw_cache.work, - device_uncache_fw_images_work); - - fw_cache.pm_notify.notifier_call = fw_pm_notify; - register_pm_notifier(&fw_cache.pm_notify); - - register_syscore_ops(&fw_syscore_ops); -#endif -} - static int __init firmware_class_init(void) { - fw_cache_init(); return class_register(&firmware_class); } static void __exit firmware_class_exit(void) { -#ifdef CONFIG_PM_SLEEP - unregister_syscore_ops(&fw_syscore_ops); - unregister_pm_notifier(&fw_cache.pm_notify); -#endif class_unregister(&firmware_class); } @@ -1354,5 +726,3 @@ module_exit(firmware_class_exit); EXPORT_SYMBOL(release_firmware); EXPORT_SYMBOL(request_firmware); EXPORT_SYMBOL(request_firmware_nowait); -EXPORT_SYMBOL_GPL(cache_firmware); -EXPORT_SYMBOL_GPL(uncache_firmware); diff --git a/trunk/drivers/base/platform.c b/trunk/drivers/base/platform.c index ddeca142293c..a1a722502587 100644 --- a/trunk/drivers/base/platform.c +++ b/trunk/drivers/base/platform.c @@ -20,13 +20,9 @@ #include #include #include -#include #include "base.h" -/* For automatically allocated device IDs */ -static DEFINE_IDA(platform_devid_ida); - #define to_platform_driver(drv) (container_of((drv), struct platform_driver, \ driver)) @@ -103,9 +99,6 @@ struct resource *platform_get_resource_byname(struct platform_device *dev, for (i = 0; i < dev->num_resources; i++) { struct resource *r = &dev->resource[i]; - if (unlikely(!r->name)) - continue; - if (type == resource_type(r) && !strcmp(r->name, name)) return r; } @@ -270,7 +263,7 @@ EXPORT_SYMBOL_GPL(platform_device_add_data); */ int platform_device_add(struct platform_device *pdev) { - int i, ret; + int i, ret = 0; if (!pdev) return -EINVAL; @@ -280,27 +273,10 @@ int platform_device_add(struct platform_device *pdev) pdev->dev.bus = &platform_bus_type; - switch (pdev->id) { - default: + if (pdev->id != -1) dev_set_name(&pdev->dev, "%s.%d", pdev->name, pdev->id); - break; - case PLATFORM_DEVID_NONE: + else dev_set_name(&pdev->dev, "%s", pdev->name); - break; - case PLATFORM_DEVID_AUTO: - /* - * Automatically allocated device ID. We mark it as such so - * that we remember it must be freed, and we append a suffix - * to avoid namespace collision with explicit IDs. - */ - ret = ida_simple_get(&platform_devid_ida, 0, 0, GFP_KERNEL); - if (ret < 0) - goto err_out; - pdev->id = ret; - pdev->id_auto = true; - dev_set_name(&pdev->dev, "%s.%d.auto", pdev->name, pdev->id); - break; - } for (i = 0; i < pdev->num_resources; i++) { struct resource *p, *r = &pdev->resource[i]; @@ -333,11 +309,6 @@ int platform_device_add(struct platform_device *pdev) return ret; failed: - if (pdev->id_auto) { - ida_simple_remove(&platform_devid_ida, pdev->id); - pdev->id = PLATFORM_DEVID_AUTO; - } - while (--i >= 0) { struct resource *r = &pdev->resource[i]; unsigned long type = resource_type(r); @@ -346,7 +317,6 @@ int platform_device_add(struct platform_device *pdev) release_resource(r); } - err_out: return ret; } EXPORT_SYMBOL_GPL(platform_device_add); @@ -366,11 +336,6 @@ void platform_device_del(struct platform_device *pdev) if (pdev) { device_del(&pdev->dev); - if (pdev->id_auto) { - ida_simple_remove(&platform_devid_ida, pdev->id); - pdev->id = PLATFORM_DEVID_AUTO; - } - for (i = 0; i < pdev->num_resources; i++) { struct resource *r = &pdev->resource[i]; unsigned long type = resource_type(r); diff --git a/trunk/drivers/base/power/clock_ops.c b/trunk/drivers/base/power/clock_ops.c index eb78e9640c4a..869d7ff2227f 100644 --- a/trunk/drivers/base/power/clock_ops.c +++ b/trunk/drivers/base/power/clock_ops.c @@ -169,7 +169,8 @@ void pm_clk_init(struct device *dev) */ int pm_clk_create(struct device *dev) { - return dev_pm_get_subsys_data(dev); + int ret = dev_pm_get_subsys_data(dev); + return ret < 0 ? ret : 0; } /** diff --git a/trunk/drivers/base/power/common.c b/trunk/drivers/base/power/common.c index 39c32529b833..a14085cc613f 100644 --- a/trunk/drivers/base/power/common.c +++ b/trunk/drivers/base/power/common.c @@ -24,6 +24,7 @@ int dev_pm_get_subsys_data(struct device *dev) { struct pm_subsys_data *psd; + int ret = 0; psd = kzalloc(sizeof(*psd), GFP_KERNEL); if (!psd) @@ -39,6 +40,7 @@ int dev_pm_get_subsys_data(struct device *dev) dev->power.subsys_data = psd; pm_clk_init(dev); psd = NULL; + ret = 1; } spin_unlock_irq(&dev->power.lock); @@ -46,7 +48,7 @@ int dev_pm_get_subsys_data(struct device *dev) /* kfree() verifies that its argument is nonzero. */ kfree(psd); - return 0; + return ret; } EXPORT_SYMBOL_GPL(dev_pm_get_subsys_data); diff --git a/trunk/drivers/base/power/main.c b/trunk/drivers/base/power/main.c index b0b072a88f5f..0113adc310dc 100644 --- a/trunk/drivers/base/power/main.c +++ b/trunk/drivers/base/power/main.c @@ -1324,25 +1324,3 @@ int device_pm_wait_for_dev(struct device *subordinate, struct device *dev) return async_error; } EXPORT_SYMBOL_GPL(device_pm_wait_for_dev); - -/** - * dpm_for_each_dev - device iterator. - * @data: data for the callback. - * @fn: function to be called for each device. - * - * Iterate over devices in dpm_list, and call @fn for each device, - * passing it @data. - */ -void dpm_for_each_dev(void *data, void (*fn)(struct device *, void *)) -{ - struct device *dev; - - if (!fn) - return; - - device_pm_lock(); - list_for_each_entry(dev, &dpm_list, power.entry) - fn(dev, data); - device_pm_unlock(); -} -EXPORT_SYMBOL_GPL(dpm_for_each_dev); diff --git a/trunk/drivers/base/power/runtime.c b/trunk/drivers/base/power/runtime.c index 7d9c1cb1c39a..59894873a3b3 100644 --- a/trunk/drivers/base/power/runtime.c +++ b/trunk/drivers/base/power/runtime.c @@ -147,8 +147,6 @@ static int rpm_check_suspend_allowed(struct device *dev) || (dev->power.request_pending && dev->power.request == RPM_REQ_RESUME)) retval = -EAGAIN; - else if (__dev_pm_qos_read_value(dev) < 0) - retval = -EPERM; else if (dev->power.runtime_status == RPM_SUSPENDED) retval = 1; @@ -390,6 +388,7 @@ static int rpm_suspend(struct device *dev, int rpmflags) goto repeat; } + dev->power.deferred_resume = false; if (dev->power.no_callbacks) goto no_callback; /* Assume success. */ @@ -404,6 +403,12 @@ static int rpm_suspend(struct device *dev, int rpmflags) goto out; } + if (__dev_pm_qos_read_value(dev) < 0) { + /* Negative PM QoS constraint means "never suspend". */ + retval = -EPERM; + goto out; + } + __update_runtime_status(dev, RPM_SUSPENDING); if (dev->pm_domain) @@ -435,7 +440,6 @@ static int rpm_suspend(struct device *dev, int rpmflags) wake_up_all(&dev->power.wait_queue); if (dev->power.deferred_resume) { - dev->power.deferred_resume = false; rpm_resume(dev, 0); retval = -EAGAIN; goto out; @@ -580,7 +584,6 @@ static int rpm_resume(struct device *dev, int rpmflags) || dev->parent->power.runtime_status == RPM_ACTIVE) { atomic_inc(&dev->parent->power.child_count); spin_unlock(&dev->parent->power.lock); - retval = 1; goto no_callback; /* Assume success. */ } spin_unlock(&dev->parent->power.lock); @@ -661,7 +664,7 @@ static int rpm_resume(struct device *dev, int rpmflags) } wake_up_all(&dev->power.wait_queue); - if (retval >= 0) + if (!retval) rpm_idle(dev, RPM_ASYNC); out: diff --git a/trunk/drivers/base/regmap/regmap-irq.c b/trunk/drivers/base/regmap/regmap-irq.c index 5b6b1d8e6cc0..a89734621e51 100644 --- a/trunk/drivers/base/regmap/regmap-irq.c +++ b/trunk/drivers/base/regmap/regmap-irq.c @@ -16,14 +16,12 @@ #include #include #include -#include #include #include "internal.h" struct regmap_irq_chip_data { struct mutex lock; - struct irq_chip irq_chip; struct regmap *map; const struct regmap_irq_chip *chip; @@ -61,14 +59,6 @@ static void regmap_irq_sync_unlock(struct irq_data *data) struct regmap_irq_chip_data *d = irq_data_get_irq_chip_data(data); struct regmap *map = d->map; int i, ret; - u32 reg; - - if (d->chip->runtime_pm) { - ret = pm_runtime_get_sync(map->dev); - if (ret < 0) - dev_err(map->dev, "IRQ sync failed to resume: %d\n", - ret); - } /* * If there's been a change in the mask write it back to the @@ -76,22 +66,15 @@ static void regmap_irq_sync_unlock(struct irq_data *data) * suppress pointless writes. */ for (i = 0; i < d->chip->num_regs; i++) { - reg = d->chip->mask_base + - (i * map->reg_stride * d->irq_reg_stride); - if (d->chip->mask_invert) - ret = regmap_update_bits(d->map, reg, - d->mask_buf_def[i], ~d->mask_buf[i]); - else - ret = regmap_update_bits(d->map, reg, + ret = regmap_update_bits(d->map, d->chip->mask_base + + (i * map->reg_stride * + d->irq_reg_stride), d->mask_buf_def[i], d->mask_buf[i]); if (ret != 0) dev_err(d->map->dev, "Failed to sync masks in %x\n", - reg); + d->chip->mask_base + (i * map->reg_stride)); } - if (d->chip->runtime_pm) - pm_runtime_put(map->dev); - /* If we've changed our wakeup count propagate it to the parent */ if (d->wake_count < 0) for (i = d->wake_count; i < 0; i++) @@ -145,7 +128,8 @@ static int regmap_irq_set_wake(struct irq_data *data, unsigned int on) return 0; } -static const struct irq_chip regmap_irq_chip = { +static struct irq_chip regmap_irq_chip = { + .name = "regmap", .irq_bus_lock = regmap_irq_lock, .irq_bus_sync_unlock = regmap_irq_sync_unlock, .irq_disable = regmap_irq_disable, @@ -160,16 +144,6 @@ static irqreturn_t regmap_irq_thread(int irq, void *d) struct regmap *map = data->map; int ret, i; bool handled = false; - u32 reg; - - if (chip->runtime_pm) { - ret = pm_runtime_get_sync(map->dev); - if (ret < 0) { - dev_err(map->dev, "IRQ thread failed to resume: %d\n", - ret); - return IRQ_NONE; - } - } /* * Ignore masked IRQs and ack if we need to; we ack early so @@ -186,20 +160,20 @@ static irqreturn_t regmap_irq_thread(int irq, void *d) if (ret != 0) { dev_err(map->dev, "Failed to read IRQ status: %d\n", ret); - if (chip->runtime_pm) - pm_runtime_put(map->dev); return IRQ_NONE; } data->status_buf[i] &= ~data->mask_buf[i]; if (data->status_buf[i] && chip->ack_base) { - reg = chip->ack_base + - (i * map->reg_stride * data->irq_reg_stride); - ret = regmap_write(map, reg, data->status_buf[i]); + ret = regmap_write(map, chip->ack_base + + (i * map->reg_stride * + data->irq_reg_stride), + data->status_buf[i]); if (ret != 0) dev_err(map->dev, "Failed to ack 0x%x: %d\n", - reg, ret); + chip->ack_base + (i * map->reg_stride), + ret); } } @@ -211,9 +185,6 @@ static irqreturn_t regmap_irq_thread(int irq, void *d) } } - if (chip->runtime_pm) - pm_runtime_put(map->dev); - if (handled) return IRQ_HANDLED; else @@ -226,7 +197,7 @@ static int regmap_irq_map(struct irq_domain *h, unsigned int virq, struct regmap_irq_chip_data *data = h->host_data; irq_set_chip_data(virq, data); - irq_set_chip(virq, &data->irq_chip); + irq_set_chip_and_handler(virq, ®map_irq_chip, handle_edge_irq); irq_set_nested_thread(virq, 1); /* ARM needs us to explicitly flag the IRQ as valid @@ -267,7 +238,6 @@ int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags, struct regmap_irq_chip_data *d; int i; int ret = -ENOMEM; - u32 reg; for (i = 0; i < chip->num_irqs; i++) { if (chip->irqs[i].reg_offset % map->reg_stride) @@ -314,13 +284,6 @@ int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags, goto err_alloc; } - d->irq_chip = regmap_irq_chip; - d->irq_chip.name = chip->name; - if (!chip->wake_base) { - d->irq_chip.irq_set_wake = NULL; - d->irq_chip.flags |= IRQCHIP_MASK_ON_SUSPEND | - IRQCHIP_SKIP_SET_WAKE; - } d->irq = irq; d->map = map; d->chip = chip; @@ -340,37 +303,16 @@ int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags, /* Mask all the interrupts by default */ for (i = 0; i < chip->num_regs; i++) { d->mask_buf[i] = d->mask_buf_def[i]; - reg = chip->mask_base + - (i * map->reg_stride * d->irq_reg_stride); - if (chip->mask_invert) - ret = regmap_update_bits(map, reg, - d->mask_buf[i], ~d->mask_buf[i]); - else - ret = regmap_update_bits(map, reg, - d->mask_buf[i], d->mask_buf[i]); + ret = regmap_write(map, chip->mask_base + (i * map->reg_stride + * d->irq_reg_stride), + d->mask_buf[i]); if (ret != 0) { dev_err(map->dev, "Failed to set masks in 0x%x: %d\n", - reg, ret); + chip->mask_base + (i * map->reg_stride), ret); goto err_alloc; } } - /* Wake is disabled by default */ - if (d->wake_buf) { - for (i = 0; i < chip->num_regs; i++) { - d->wake_buf[i] = d->mask_buf_def[i]; - reg = chip->wake_base + - (i * map->reg_stride * d->irq_reg_stride); - ret = regmap_update_bits(map, reg, d->wake_buf[i], - d->wake_buf[i]); - if (ret != 0) { - dev_err(map->dev, "Failed to set masks in 0x%x: %d\n", - reg, ret); - goto err_alloc; - } - } - } - if (irq_base) d->domain = irq_domain_add_legacy(map->dev->of_node, chip->num_irqs, irq_base, 0, diff --git a/trunk/drivers/base/regmap/regmap.c b/trunk/drivers/base/regmap/regmap.c index 52069d29ff12..c241ae2f2f10 100644 --- a/trunk/drivers/base/regmap/regmap.c +++ b/trunk/drivers/base/regmap/regmap.c @@ -659,12 +659,13 @@ EXPORT_SYMBOL_GPL(devm_regmap_init); * new cache. This can be used to restore the cache to defaults or to * update the cache configuration to reflect runtime discovery of the * hardware. - * - * No explicit locking is done here, the user needs to ensure that - * this function will not race with other calls to regmap. */ int regmap_reinit_cache(struct regmap *map, const struct regmap_config *config) { + int ret; + + map->lock(map); + regcache_exit(map); regmap_debugfs_exit(map); @@ -680,7 +681,11 @@ int regmap_reinit_cache(struct regmap *map, const struct regmap_config *config) map->cache_bypass = false; map->cache_only = false; - return regcache_init(map, config); + ret = regcache_init(map, config); + + map->unlock(map); + + return ret; } EXPORT_SYMBOL_GPL(regmap_reinit_cache); diff --git a/trunk/drivers/bcma/host_pci.c b/trunk/drivers/bcma/host_pci.c index a6e5672c67e7..11b32d2642df 100644 --- a/trunk/drivers/bcma/host_pci.c +++ b/trunk/drivers/bcma/host_pci.c @@ -272,7 +272,6 @@ static DEFINE_PCI_DEVICE_TABLE(bcma_pci_bridge_tbl) = { { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4331) }, { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4353) }, { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4357) }, - { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4359) }, { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4727) }, { 0, }, }; diff --git a/trunk/drivers/bcma/sprom.c b/trunk/drivers/bcma/sprom.c index 9ea4627dc0c2..26823d97fd9f 100644 --- a/trunk/drivers/bcma/sprom.c +++ b/trunk/drivers/bcma/sprom.c @@ -507,9 +507,7 @@ static bool bcma_sprom_onchip_available(struct bcma_bus *bus) /* for these chips OTP is always available */ present = true; break; - case BCMA_CHIP_ID_BCM43228: - present = chip_status & BCMA_CC_CHIPST_43228_OTP_PRESENT; - break; + default: present = false; break; diff --git a/trunk/drivers/block/aoe/aoecmd.c b/trunk/drivers/block/aoe/aoecmd.c index 887f68f6d79a..de0435e63b02 100644 --- a/trunk/drivers/block/aoe/aoecmd.c +++ b/trunk/drivers/block/aoe/aoecmd.c @@ -35,7 +35,6 @@ new_skb(ulong len) skb_reset_mac_header(skb); skb_reset_network_header(skb); skb->protocol = __constant_htons(ETH_P_AOE); - skb_checksum_none_assert(skb); } return skb; } diff --git a/trunk/drivers/block/cciss_scsi.c b/trunk/drivers/block/cciss_scsi.c index da3311129a0c..acda773b3720 100644 --- a/trunk/drivers/block/cciss_scsi.c +++ b/trunk/drivers/block/cciss_scsi.c @@ -763,7 +763,16 @@ static void complete_scsi_command(CommandList_struct *c, int timeout, { case CMD_TARGET_STATUS: /* Pass it up to the upper layers... */ - if (!ei->ScsiStatus) { + if( ei->ScsiStatus) + { +#if 0 + printk(KERN_WARNING "cciss: cmd %p " + "has SCSI Status = %x\n", + c, ei->ScsiStatus); +#endif + cmd->result |= (ei->ScsiStatus << 1); + } + else { /* scsi status is zero??? How??? */ /* Ordinarily, this case should never happen, but there is a bug in some released firmware revisions that allows it to happen @@ -795,7 +804,6 @@ static void complete_scsi_command(CommandList_struct *c, int timeout, } break; case CMD_PROTOCOL_ERR: - cmd->result = DID_ERROR << 16; dev_warn(&h->pdev->dev, "%p has protocol error\n", c); break; diff --git a/trunk/drivers/block/drbd/drbd_bitmap.c b/trunk/drivers/block/drbd/drbd_bitmap.c index d84566496746..ba91b408abad 100644 --- a/trunk/drivers/block/drbd/drbd_bitmap.c +++ b/trunk/drivers/block/drbd/drbd_bitmap.c @@ -889,7 +889,6 @@ struct bm_aio_ctx { unsigned int done; unsigned flags; #define BM_AIO_COPY_PAGES 1 -#define BM_WRITE_ALL_PAGES 2 int error; struct kref kref; }; @@ -1060,8 +1059,7 @@ static int bm_rw(struct drbd_conf *mdev, int rw, unsigned flags, unsigned lazy_w if (lazy_writeout_upper_idx && i == lazy_writeout_upper_idx) break; if (rw & WRITE) { - if (!(flags & BM_WRITE_ALL_PAGES) && - bm_test_page_unchanged(b->bm_pages[i])) { + if (bm_test_page_unchanged(b->bm_pages[i])) { dynamic_dev_dbg(DEV, "skipped bm write for idx %u\n", i); continue; } @@ -1142,17 +1140,6 @@ int drbd_bm_write(struct drbd_conf *mdev) __must_hold(local) return bm_rw(mdev, WRITE, 0, 0); } -/** - * drbd_bm_write_all() - Write the whole bitmap to its on disk location. - * @mdev: DRBD device. - * - * Will write all pages. - */ -int drbd_bm_write_all(struct drbd_conf *mdev) __must_hold(local) -{ - return bm_rw(mdev, WRITE, BM_WRITE_ALL_PAGES, 0); -} - /** * drbd_bm_lazy_write_out() - Write bitmap pages 0 to @upper_idx-1, if they have changed. * @mdev: DRBD device. diff --git a/trunk/drivers/block/drbd/drbd_int.h b/trunk/drivers/block/drbd/drbd_int.h index b953cc7c9c00..b2ca143d0053 100644 --- a/trunk/drivers/block/drbd/drbd_int.h +++ b/trunk/drivers/block/drbd/drbd_int.h @@ -1469,7 +1469,6 @@ extern int drbd_bm_e_weight(struct drbd_conf *mdev, unsigned long enr); extern int drbd_bm_write_page(struct drbd_conf *mdev, unsigned int idx) __must_hold(local); extern int drbd_bm_read(struct drbd_conf *mdev) __must_hold(local); extern int drbd_bm_write(struct drbd_conf *mdev) __must_hold(local); -extern int drbd_bm_write_all(struct drbd_conf *mdev) __must_hold(local); extern int drbd_bm_write_copy_pages(struct drbd_conf *mdev) __must_hold(local); extern unsigned long drbd_bm_ALe_set_all(struct drbd_conf *mdev, unsigned long al_enr); diff --git a/trunk/drivers/block/drbd/drbd_main.c b/trunk/drivers/block/drbd/drbd_main.c index f93a0320e952..2e0e7fc1dbba 100644 --- a/trunk/drivers/block/drbd/drbd_main.c +++ b/trunk/drivers/block/drbd/drbd_main.c @@ -79,7 +79,6 @@ static int w_md_sync(struct drbd_conf *mdev, struct drbd_work *w, int unused); static void md_sync_timer_fn(unsigned long data); static int w_bitmap_io(struct drbd_conf *mdev, struct drbd_work *w, int unused); static int w_go_diskless(struct drbd_conf *mdev, struct drbd_work *w, int unused); -static void _tl_clear(struct drbd_conf *mdev); MODULE_AUTHOR("Philipp Reisner , " "Lars Ellenberg "); @@ -433,10 +432,19 @@ static void _tl_restart(struct drbd_conf *mdev, enum drbd_req_event what) /* Actions operating on the disk state, also want to work on requests that got barrier acked. */ + switch (what) { + case fail_frozen_disk_io: + case restart_frozen_disk_io: + list_for_each_safe(le, tle, &mdev->barrier_acked_requests) { + req = list_entry(le, struct drbd_request, tl_requests); + _req_mod(req, what); + } - list_for_each_safe(le, tle, &mdev->barrier_acked_requests) { - req = list_entry(le, struct drbd_request, tl_requests); - _req_mod(req, what); + case connection_lost_while_pending: + case resend: + break; + default: + dev_err(DEV, "what = %d in _tl_restart()\n", what); } } @@ -450,17 +458,12 @@ static void _tl_restart(struct drbd_conf *mdev, enum drbd_req_event what) * receiver thread and the worker thread. */ void tl_clear(struct drbd_conf *mdev) -{ - spin_lock_irq(&mdev->req_lock); - _tl_clear(mdev); - spin_unlock_irq(&mdev->req_lock); -} - -static void _tl_clear(struct drbd_conf *mdev) { struct list_head *le, *tle; struct drbd_request *r; + spin_lock_irq(&mdev->req_lock); + _tl_restart(mdev, connection_lost_while_pending); /* we expect this list to be empty. */ @@ -479,6 +482,7 @@ static void _tl_clear(struct drbd_conf *mdev) memset(mdev->app_reads_hash, 0, APP_R_HSIZE*sizeof(void *)); + spin_unlock_irq(&mdev->req_lock); } void tl_restart(struct drbd_conf *mdev, enum drbd_req_event what) @@ -1472,12 +1476,12 @@ static void after_state_ch(struct drbd_conf *mdev, union drbd_state os, if (ns.susp_fen) { /* case1: The outdate peer handler is successful: */ if (os.pdsk > D_OUTDATED && ns.pdsk <= D_OUTDATED) { + tl_clear(mdev); if (test_bit(NEW_CUR_UUID, &mdev->flags)) { drbd_uuid_new_current(mdev); clear_bit(NEW_CUR_UUID, &mdev->flags); } spin_lock_irq(&mdev->req_lock); - _tl_clear(mdev); _drbd_set_state(_NS(mdev, susp_fen, 0), CS_VERBOSE, NULL); spin_unlock_irq(&mdev->req_lock); } @@ -3533,9 +3537,9 @@ static void drbd_cleanup(void) } /** - * drbd_congested() - Callback for the flusher thread + * drbd_congested() - Callback for pdflush * @congested_data: User data - * @bdi_bits: Bits the BDI flusher thread is currently interested in + * @bdi_bits: Bits pdflush is currently interested in * * Returns 1<rq_state & RQ_WRITE) && !req->w.cb) { - _req_may_be_done(req, m); - break; - } - /* If RQ_NET_OK is already set, we got a P_WRITE_ACK or P_RECV_ACK before the connection loss (B&C only); only P_BARRIER_ACK was missing. Trowing them out of the TL here by pretending we got a BARRIER_ACK @@ -840,15 +834,7 @@ static int drbd_make_request_common(struct drbd_conf *mdev, struct bio *bio, uns req->private_bio = NULL; } if (rw == WRITE) { - /* Need to replicate writes. Unless it is an empty flush, - * which is better mapped to a DRBD P_BARRIER packet, - * also for drbd wire protocol compatibility reasons. */ - if (unlikely(size == 0)) { - /* The only size==0 bios we expect are empty flushes. */ - D_ASSERT(bio->bi_rw & REQ_FLUSH); - remote = 0; - } else - remote = 1; + remote = 1; } else { /* READ || READA */ if (local) { @@ -884,11 +870,8 @@ static int drbd_make_request_common(struct drbd_conf *mdev, struct bio *bio, uns * extent. This waits for any resync activity in the corresponding * resync extent to finish, and, if necessary, pulls in the target * extent into the activity log, which involves further disk io because - * of transactional on-disk meta data updates. - * Empty flushes don't need to go into the activity log, they can only - * flush data for pending writes which are already in there. */ - if (rw == WRITE && local && size - && !test_bit(AL_SUSPENDED, &mdev->flags)) { + * of transactional on-disk meta data updates. */ + if (rw == WRITE && local && !test_bit(AL_SUSPENDED, &mdev->flags)) { req->rq_state |= RQ_IN_ACT_LOG; drbd_al_begin_io(mdev, sector); } @@ -1011,10 +994,7 @@ static int drbd_make_request_common(struct drbd_conf *mdev, struct bio *bio, uns if (rw == WRITE && _req_conflicts(req)) goto fail_conflicting; - /* no point in adding empty flushes to the transfer log, - * they are mapped to drbd barriers already. */ - if (likely(size!=0)) - list_add_tail(&req->tl_requests, &mdev->newest_tle->requests); + list_add_tail(&req->tl_requests, &mdev->newest_tle->requests); /* NOTE remote first: to get the concurrent write detection right, * we must register the request before start of local IO. */ @@ -1034,14 +1014,6 @@ static int drbd_make_request_common(struct drbd_conf *mdev, struct bio *bio, uns mdev->net_conf->on_congestion != OC_BLOCK && mdev->agreed_pro_version >= 96) maybe_pull_ahead(mdev); - /* If this was a flush, queue a drbd barrier/start a new epoch. - * Unless the current epoch was empty anyways, or we are not currently - * replicating, in which case there is no point. */ - if (unlikely(bio->bi_rw & REQ_FLUSH) - && mdev->newest_tle->n_writes - && drbd_should_do_remote(mdev->state)) - queue_barrier(mdev); - spin_unlock_irq(&mdev->req_lock); kfree(b); /* if someone else has beaten us to it... */ diff --git a/trunk/drivers/block/mtip32xx/mtip32xx.c b/trunk/drivers/block/mtip32xx/mtip32xx.c index f946d31d6917..a8fddeb3d638 100644 --- a/trunk/drivers/block/mtip32xx/mtip32xx.c +++ b/trunk/drivers/block/mtip32xx/mtip32xx.c @@ -1148,15 +1148,11 @@ static bool mtip_pause_ncq(struct mtip_port *port, reply = port->rxfis + RX_FIS_D2H_REG; task_file_data = readl(port->mmio+PORT_TFDATA); - if (fis->command == ATA_CMD_SEC_ERASE_UNIT) - clear_bit(MTIP_DDF_SEC_LOCK_BIT, &port->dd->dd_flag); - - if ((task_file_data & 1)) + if ((task_file_data & 1) || (fis->command == ATA_CMD_SEC_ERASE_UNIT)) return false; if (fis->command == ATA_CMD_SEC_ERASE_PREP) { set_bit(MTIP_PF_SE_ACTIVE_BIT, &port->flags); - set_bit(MTIP_DDF_SEC_LOCK_BIT, &port->dd->dd_flag); port->ic_pause_timer = jiffies; return true; } else if ((fis->command == ATA_CMD_DOWNLOAD_MICRO) && @@ -1904,7 +1900,7 @@ static int exec_drive_command(struct mtip_port *port, u8 *command, int rv = 0, xfer_sz = command[3]; if (xfer_sz) { - if (!user_buffer) + if (user_buffer) return -EFAULT; buf = dmam_alloc_coherent(&port->dd->pdev->dev, @@ -2047,7 +2043,7 @@ static void mtip_set_timeout(struct host_to_dev_fis *fis, unsigned int *timeout) *timeout = 240000; /* 4 minutes */ break; case ATA_CMD_STANDBYNOW1: - *timeout = 120000; /* 2 minutes */ + *timeout = 10000; /* 10 seconds */ break; case 0xF7: case 0xFA: @@ -2592,6 +2588,9 @@ static ssize_t mtip_hw_read_registers(struct file *f, char __user *ubuf, if (!len || size) return 0; + if (size < 0) + return -EINVAL; + size += sprintf(&buf[size], "H/ S ACTive : [ 0x"); for (n = dd->slot_groups-1; n >= 0; n--) @@ -2661,6 +2660,9 @@ static ssize_t mtip_hw_read_flags(struct file *f, char __user *ubuf, if (!len || size) return 0; + if (size < 0) + return -EINVAL; + size += sprintf(&buf[size], "Flag-port : [ %08lX ]\n", dd->port->flags); size += sprintf(&buf[size], "Flag-dd : [ %08lX ]\n", @@ -3212,8 +3214,8 @@ static int mtip_hw_init(struct driver_data *dd) "Unable to check write protect progress\n"); else dev_info(&dd->pdev->dev, - "Write protect progress: %u%% (%u blocks)\n", - attr242.cur, le32_to_cpu(attr242.data)); + "Write protect progress: %d%% (%d blocks)\n", + attr242.cur, attr242.data); return rv; out3: @@ -3617,10 +3619,6 @@ static void mtip_make_request(struct request_queue *queue, struct bio *bio) bio_endio(bio, -ENODATA); return; } - if (unlikely(test_bit(MTIP_DDF_SEC_LOCK_BIT, &dd->dd_flag))) { - bio_endio(bio, -ENODATA); - return; - } } if (unlikely(!bio_has_data(bio))) { @@ -4170,13 +4168,7 @@ static void mtip_pci_shutdown(struct pci_dev *pdev) /* Table of device ids supported by this driver. */ static DEFINE_PCI_DEVICE_TABLE(mtip_pci_tbl) = { - { PCI_DEVICE(PCI_VENDOR_ID_MICRON, P320H_DEVICE_ID) }, - { PCI_DEVICE(PCI_VENDOR_ID_MICRON, P320M_DEVICE_ID) }, - { PCI_DEVICE(PCI_VENDOR_ID_MICRON, P320S_DEVICE_ID) }, - { PCI_DEVICE(PCI_VENDOR_ID_MICRON, P325M_DEVICE_ID) }, - { PCI_DEVICE(PCI_VENDOR_ID_MICRON, P420H_DEVICE_ID) }, - { PCI_DEVICE(PCI_VENDOR_ID_MICRON, P420M_DEVICE_ID) }, - { PCI_DEVICE(PCI_VENDOR_ID_MICRON, P425M_DEVICE_ID) }, + { PCI_DEVICE(PCI_VENDOR_ID_MICRON, P320_DEVICE_ID) }, { 0 } }; @@ -4207,12 +4199,12 @@ static int __init mtip_init(void) { int error; - pr_info(MTIP_DRV_NAME " Version " MTIP_DRV_VERSION "\n"); + printk(KERN_INFO MTIP_DRV_NAME " Version " MTIP_DRV_VERSION "\n"); /* Allocate a major block device number to use with this driver. */ error = register_blkdev(0, MTIP_DRV_NAME); if (error <= 0) { - pr_err("Unable to register block device (%d)\n", + printk(KERN_ERR "Unable to register block device (%d)\n", error); return -EBUSY; } @@ -4221,7 +4213,7 @@ static int __init mtip_init(void) if (!dfs_parent) { dfs_parent = debugfs_create_dir("rssd", NULL); if (IS_ERR_OR_NULL(dfs_parent)) { - pr_warn("Error creating debugfs parent\n"); + printk(KERN_WARNING "Error creating debugfs parent\n"); dfs_parent = NULL; } } diff --git a/trunk/drivers/block/mtip32xx/mtip32xx.h b/trunk/drivers/block/mtip32xx/mtip32xx.h index 18627a1d04c5..f51fc23d17bb 100644 --- a/trunk/drivers/block/mtip32xx/mtip32xx.h +++ b/trunk/drivers/block/mtip32xx/mtip32xx.h @@ -76,13 +76,7 @@ /* Micron Vendor ID & P320x SSD Device ID */ #define PCI_VENDOR_ID_MICRON 0x1344 -#define P320H_DEVICE_ID 0x5150 -#define P320M_DEVICE_ID 0x5151 -#define P320S_DEVICE_ID 0x5152 -#define P325M_DEVICE_ID 0x5153 -#define P420H_DEVICE_ID 0x5160 -#define P420M_DEVICE_ID 0x5161 -#define P425M_DEVICE_ID 0x5163 +#define P320_DEVICE_ID 0x5150 /* Driver name and version strings */ #define MTIP_DRV_NAME "mtip32xx" @@ -137,12 +131,10 @@ enum { MTIP_PF_SVC_THD_STOP_BIT = 8, /* below are bit numbers in 'dd_flag' defined in driver_data */ - MTIP_DDF_SEC_LOCK_BIT = 0, MTIP_DDF_REMOVE_PENDING_BIT = 1, MTIP_DDF_OVER_TEMP_BIT = 2, MTIP_DDF_WRITE_PROTECT_BIT = 3, MTIP_DDF_STOP_IO = ((1 << MTIP_DDF_REMOVE_PENDING_BIT) | \ - (1 << MTIP_DDF_SEC_LOCK_BIT) | \ (1 << MTIP_DDF_OVER_TEMP_BIT) | \ (1 << MTIP_DDF_WRITE_PROTECT_BIT)), diff --git a/trunk/drivers/block/nbd.c b/trunk/drivers/block/nbd.c index 0c03411c59eb..d07c9f7fded6 100644 --- a/trunk/drivers/block/nbd.c +++ b/trunk/drivers/block/nbd.c @@ -449,14 +449,6 @@ static void nbd_clear_que(struct nbd_device *nbd) req->errors++; nbd_end_request(req); } - - while (!list_empty(&nbd->waiting_queue)) { - req = list_entry(nbd->waiting_queue.next, struct request, - queuelist); - list_del_init(&req->queuelist); - req->errors++; - nbd_end_request(req); - } } @@ -606,7 +598,6 @@ static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd, nbd->file = NULL; nbd_clear_que(nbd); BUG_ON(!list_empty(&nbd->queue_head)); - BUG_ON(!list_empty(&nbd->waiting_queue)); if (file) fput(file); return 0; diff --git a/trunk/drivers/block/nvme.c b/trunk/drivers/block/nvme.c index 931769e133e5..38a2d0631882 100644 --- a/trunk/drivers/block/nvme.c +++ b/trunk/drivers/block/nvme.c @@ -79,7 +79,6 @@ struct nvme_dev { char serial[20]; char model[40]; char firmware_rev[8]; - u32 max_hw_sectors; }; /* @@ -836,15 +835,15 @@ static int nvme_identify(struct nvme_dev *dev, unsigned nsid, unsigned cns, } static int nvme_get_features(struct nvme_dev *dev, unsigned fid, - unsigned nsid, dma_addr_t dma_addr) + unsigned dword11, dma_addr_t dma_addr) { struct nvme_command c; memset(&c, 0, sizeof(c)); c.features.opcode = nvme_admin_get_features; - c.features.nsid = cpu_to_le32(nsid); c.features.prp1 = cpu_to_le64(dma_addr); c.features.fid = cpu_to_le32(fid); + c.features.dword11 = cpu_to_le32(dword11); return nvme_submit_admin_cmd(dev, &c, NULL); } @@ -863,51 +862,11 @@ static int nvme_set_features(struct nvme_dev *dev, unsigned fid, return nvme_submit_admin_cmd(dev, &c, result); } -/** - * nvme_cancel_ios - Cancel outstanding I/Os - * @queue: The queue to cancel I/Os on - * @timeout: True to only cancel I/Os which have timed out - */ -static void nvme_cancel_ios(struct nvme_queue *nvmeq, bool timeout) -{ - int depth = nvmeq->q_depth - 1; - struct nvme_cmd_info *info = nvme_cmd_info(nvmeq); - unsigned long now = jiffies; - int cmdid; - - for_each_set_bit(cmdid, nvmeq->cmdid_data, depth) { - void *ctx; - nvme_completion_fn fn; - static struct nvme_completion cqe = { - .status = cpu_to_le16(NVME_SC_ABORT_REQ) << 1, - }; - - if (timeout && !time_after(now, info[cmdid].timeout)) - continue; - dev_warn(nvmeq->q_dmadev, "Cancelling I/O %d\n", cmdid); - ctx = cancel_cmdid(nvmeq, cmdid, &fn); - fn(nvmeq->dev, ctx, &cqe); - } -} - -static void nvme_free_queue_mem(struct nvme_queue *nvmeq) -{ - dma_free_coherent(nvmeq->q_dmadev, CQ_SIZE(nvmeq->q_depth), - (void *)nvmeq->cqes, nvmeq->cq_dma_addr); - dma_free_coherent(nvmeq->q_dmadev, SQ_SIZE(nvmeq->q_depth), - nvmeq->sq_cmds, nvmeq->sq_dma_addr); - kfree(nvmeq); -} - static void nvme_free_queue(struct nvme_dev *dev, int qid) { struct nvme_queue *nvmeq = dev->queues[qid]; int vector = dev->entry[nvmeq->cq_vector].vector; - spin_lock_irq(&nvmeq->q_lock); - nvme_cancel_ios(nvmeq, false); - spin_unlock_irq(&nvmeq->q_lock); - irq_set_affinity_hint(vector, NULL); free_irq(vector, nvmeq); @@ -917,15 +876,18 @@ static void nvme_free_queue(struct nvme_dev *dev, int qid) adapter_delete_cq(dev, qid); } - nvme_free_queue_mem(nvmeq); + dma_free_coherent(nvmeq->q_dmadev, CQ_SIZE(nvmeq->q_depth), + (void *)nvmeq->cqes, nvmeq->cq_dma_addr); + dma_free_coherent(nvmeq->q_dmadev, SQ_SIZE(nvmeq->q_depth), + nvmeq->sq_cmds, nvmeq->sq_dma_addr); + kfree(nvmeq); } static struct nvme_queue *nvme_alloc_queue(struct nvme_dev *dev, int qid, int depth, int vector) { struct device *dmadev = &dev->pci_dev->dev; - unsigned extra = DIV_ROUND_UP(depth, 8) + (depth * - sizeof(struct nvme_cmd_info)); + unsigned extra = (depth / 8) + (depth * sizeof(struct nvme_cmd_info)); struct nvme_queue *nvmeq = kzalloc(sizeof(*nvmeq) + extra, GFP_KERNEL); if (!nvmeq) return NULL; @@ -1013,7 +975,7 @@ static __devinit struct nvme_queue *nvme_create_queue(struct nvme_dev *dev, static int __devinit nvme_configure_admin_queue(struct nvme_dev *dev) { - int result = 0; + int result; u32 aqa; u64 cap; unsigned long timeout; @@ -1043,22 +1005,17 @@ static int __devinit nvme_configure_admin_queue(struct nvme_dev *dev) timeout = ((NVME_CAP_TIMEOUT(cap) + 1) * HZ / 2) + jiffies; dev->db_stride = NVME_CAP_STRIDE(cap); - while (!result && !(readl(&dev->bar->csts) & NVME_CSTS_RDY)) { + while (!(readl(&dev->bar->csts) & NVME_CSTS_RDY)) { msleep(100); if (fatal_signal_pending(current)) - result = -EINTR; + return -EINTR; if (time_after(jiffies, timeout)) { dev_err(&dev->pci_dev->dev, "Device not ready; aborting initialisation\n"); - result = -ENODEV; + return -ENODEV; } } - if (result) { - nvme_free_queue_mem(nvmeq); - return result; - } - result = queue_request_irq(dev, nvmeq, "nvme admin"); dev->queues[0] = nvmeq; return result; @@ -1080,8 +1037,6 @@ static struct nvme_iod *nvme_map_user_pages(struct nvme_dev *dev, int write, offset = offset_in_page(addr); count = DIV_ROUND_UP(offset + length, PAGE_SIZE); pages = kcalloc(count, sizeof(*pages), GFP_KERNEL); - if (!pages) - return ERR_PTR(-ENOMEM); err = get_user_pages_fast(addr, count, 1, pages); if (err < count) { @@ -1191,13 +1146,14 @@ static int nvme_submit_io(struct nvme_ns *ns, struct nvme_user_io __user *uio) return status; } -static int nvme_user_admin_cmd(struct nvme_dev *dev, +static int nvme_user_admin_cmd(struct nvme_ns *ns, struct nvme_admin_cmd __user *ucmd) { + struct nvme_dev *dev = ns->dev; struct nvme_admin_cmd cmd; struct nvme_command c; int status, length; - struct nvme_iod *uninitialized_var(iod); + struct nvme_iod *iod; if (!capable(CAP_SYS_ADMIN)) return -EACCES; @@ -1248,7 +1204,7 @@ static int nvme_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, case NVME_IOCTL_ID: return ns->ns_id; case NVME_IOCTL_ADMIN_CMD: - return nvme_user_admin_cmd(ns->dev, (void __user *)arg); + return nvme_user_admin_cmd(ns, (void __user *)arg); case NVME_IOCTL_SUBMIT_IO: return nvme_submit_io(ns, (void __user *)arg); default: @@ -1262,6 +1218,26 @@ static const struct block_device_operations nvme_fops = { .compat_ioctl = nvme_ioctl, }; +static void nvme_timeout_ios(struct nvme_queue *nvmeq) +{ + int depth = nvmeq->q_depth - 1; + struct nvme_cmd_info *info = nvme_cmd_info(nvmeq); + unsigned long now = jiffies; + int cmdid; + + for_each_set_bit(cmdid, nvmeq->cmdid_data, depth) { + void *ctx; + nvme_completion_fn fn; + static struct nvme_completion cqe = { .status = cpu_to_le16(NVME_SC_ABORT_REQ) << 1, }; + + if (!time_after(now, info[cmdid].timeout)) + continue; + dev_warn(nvmeq->q_dmadev, "Timing out I/O %d\n", cmdid); + ctx = cancel_cmdid(nvmeq, cmdid, &fn); + fn(nvmeq->dev, ctx, &cqe); + } +} + static void nvme_resubmit_bios(struct nvme_queue *nvmeq) { while (bio_list_peek(&nvmeq->sq_cong)) { @@ -1293,7 +1269,7 @@ static int nvme_kthread(void *data) spin_lock_irq(&nvmeq->q_lock); if (nvme_process_cq(nvmeq)) printk("process_cq did something\n"); - nvme_cancel_ios(nvmeq, true); + nvme_timeout_ios(nvmeq); nvme_resubmit_bios(nvmeq); spin_unlock_irq(&nvmeq->q_lock); } @@ -1363,9 +1339,6 @@ static struct nvme_ns *nvme_alloc_ns(struct nvme_dev *dev, int nsid, ns->disk = disk; lbaf = id->flbas & 0xf; ns->lba_shift = id->lbaf[lbaf].ds; - blk_queue_logical_block_size(ns->queue, 1 << ns->lba_shift); - if (dev->max_hw_sectors) - blk_queue_max_hw_sectors(ns->queue, dev->max_hw_sectors); disk->major = nvme_major; disk->minors = NVME_MINORS; @@ -1410,7 +1383,7 @@ static int set_queue_count(struct nvme_dev *dev, int count) static int __devinit nvme_setup_io_queues(struct nvme_dev *dev) { - int result, cpu, i, nr_io_queues, db_bar_size, q_depth; + int result, cpu, i, nr_io_queues, db_bar_size; nr_io_queues = num_online_cpus(); result = set_queue_count(dev, nr_io_queues); @@ -1456,10 +1429,9 @@ static int __devinit nvme_setup_io_queues(struct nvme_dev *dev) cpu = cpumask_next(cpu, cpu_online_mask); } - q_depth = min_t(int, NVME_CAP_MQES(readq(&dev->bar->cap)) + 1, - NVME_Q_DEPTH); for (i = 0; i < nr_io_queues; i++) { - dev->queues[i + 1] = nvme_create_queue(dev, i + 1, q_depth, i); + dev->queues[i + 1] = nvme_create_queue(dev, i + 1, + NVME_Q_DEPTH, i); if (IS_ERR(dev->queues[i + 1])) return PTR_ERR(dev->queues[i + 1]); dev->queue_count++; @@ -1508,10 +1480,6 @@ static int __devinit nvme_dev_add(struct nvme_dev *dev) memcpy(dev->serial, ctrl->sn, sizeof(ctrl->sn)); memcpy(dev->model, ctrl->mn, sizeof(ctrl->mn)); memcpy(dev->firmware_rev, ctrl->fr, sizeof(ctrl->fr)); - if (ctrl->mdts) { - int shift = NVME_CAP_MPSMIN(readq(&dev->bar->cap)) + 12; - dev->max_hw_sectors = 1 << (ctrl->mdts + shift - 9); - } id_ns = mem; for (i = 1; i <= nn; i++) { @@ -1555,6 +1523,8 @@ static int nvme_dev_remove(struct nvme_dev *dev) list_del(&dev->node); spin_unlock(&dev_list_lock); + /* TODO: wait all I/O finished or cancel them */ + list_for_each_entry_safe(ns, next, &dev->namespaces, list) { list_del(&ns->list); del_gendisk(ns->disk); @@ -1590,33 +1560,15 @@ static void nvme_release_prp_pools(struct nvme_dev *dev) dma_pool_destroy(dev->prp_small_pool); } -static DEFINE_IDA(nvme_instance_ida); - -static int nvme_set_instance(struct nvme_dev *dev) +/* XXX: Use an ida or something to let remove / add work correctly */ +static void nvme_set_instance(struct nvme_dev *dev) { - int instance, error; - - do { - if (!ida_pre_get(&nvme_instance_ida, GFP_KERNEL)) - return -ENODEV; - - spin_lock(&dev_list_lock); - error = ida_get_new(&nvme_instance_ida, &instance); - spin_unlock(&dev_list_lock); - } while (error == -EAGAIN); - - if (error) - return -ENODEV; - - dev->instance = instance; - return 0; + static int instance; + dev->instance = instance++; } static void nvme_release_instance(struct nvme_dev *dev) { - spin_lock(&dev_list_lock); - ida_remove(&nvme_instance_ida, dev->instance); - spin_unlock(&dev_list_lock); } static int __devinit nvme_probe(struct pci_dev *pdev, @@ -1649,10 +1601,7 @@ static int __devinit nvme_probe(struct pci_dev *pdev, pci_set_drvdata(pdev, dev); dma_set_mask(&pdev->dev, DMA_BIT_MASK(64)); dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(64)); - result = nvme_set_instance(dev); - if (result) - goto disable; - + nvme_set_instance(dev); dev->entry[0].vector = pdev->irq; result = nvme_setup_prp_pools(dev); @@ -1726,7 +1675,7 @@ static void __devexit nvme_remove(struct pci_dev *pdev) #define nvme_suspend NULL #define nvme_resume NULL -static const struct pci_error_handlers nvme_err_handler = { +static struct pci_error_handlers nvme_err_handler = { .error_detected = nvme_error_detected, .mmio_enabled = nvme_dump_registers, .link_reset = nvme_link_reset, @@ -1755,17 +1704,15 @@ static struct pci_driver nvme_driver = { static int __init nvme_init(void) { - int result; + int result = -EBUSY; nvme_thread = kthread_run(nvme_kthread, NULL, "nvme"); if (IS_ERR(nvme_thread)) return PTR_ERR(nvme_thread); - result = register_blkdev(nvme_major, "nvme"); - if (result < 0) + nvme_major = register_blkdev(nvme_major, "nvme"); + if (nvme_major <= 0) goto kill_kthread; - else if (result > 0) - nvme_major = result; result = pci_register_driver(&nvme_driver); if (result) diff --git a/trunk/drivers/block/rbd.c b/trunk/drivers/block/rbd.c index 54a55f03115d..9917943a3572 100644 --- a/trunk/drivers/block/rbd.c +++ b/trunk/drivers/block/rbd.c @@ -246,12 +246,13 @@ static int rbd_open(struct block_device *bdev, fmode_t mode) { struct rbd_device *rbd_dev = bdev->bd_disk->private_data; - if ((mode & FMODE_WRITE) && rbd_dev->read_only) - return -EROFS; - rbd_get_dev(rbd_dev); + set_device_ro(bdev, rbd_dev->read_only); + if ((mode & FMODE_WRITE) && rbd_dev->read_only) + return -EROFS; + return 0; } diff --git a/trunk/drivers/block/xen-blkback/blkback.c b/trunk/drivers/block/xen-blkback/blkback.c index c6decb901e5e..73f196ca713f 100644 --- a/trunk/drivers/block/xen-blkback/blkback.c +++ b/trunk/drivers/block/xen-blkback/blkback.c @@ -337,7 +337,7 @@ static void xen_blkbk_unmap(struct pending_req *req) invcount++; } - ret = gnttab_unmap_refs(unmap, NULL, pages, invcount); + ret = gnttab_unmap_refs(unmap, pages, invcount, false); BUG_ON(ret); } diff --git a/trunk/drivers/bluetooth/ath3k.c b/trunk/drivers/bluetooth/ath3k.c index fc2de5528dcc..10308cd8a7ed 100644 --- a/trunk/drivers/bluetooth/ath3k.c +++ b/trunk/drivers/bluetooth/ath3k.c @@ -79,14 +79,12 @@ static struct usb_device_id ath3k_table[] = { { USB_DEVICE(0x13d3, 0x3362) }, { USB_DEVICE(0x0CF3, 0xE004) }, { USB_DEVICE(0x0930, 0x0219) }, - { USB_DEVICE(0x0489, 0xe057) }, /* Atheros AR5BBU12 with sflash firmware */ { USB_DEVICE(0x0489, 0xE02C) }, /* Atheros AR5BBU22 with sflash firmware */ { USB_DEVICE(0x0489, 0xE03C) }, - { USB_DEVICE(0x0489, 0xE036) }, { } /* Terminating entry */ }; @@ -106,11 +104,9 @@ static struct usb_device_id ath3k_blist_tbl[] = { { USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 }, - { USB_DEVICE(0x0489, 0xe057), .driver_info = BTUSB_ATH3012 }, /* Atheros AR5BBU22 with sflash firmware */ { USB_DEVICE(0x0489, 0xE03C), .driver_info = BTUSB_ATH3012 }, - { USB_DEVICE(0x0489, 0xE036), .driver_info = BTUSB_ATH3012 }, { } /* Terminating entry */ }; diff --git a/trunk/drivers/bluetooth/btusb.c b/trunk/drivers/bluetooth/btusb.c index 654e248763ef..e27221411036 100644 --- a/trunk/drivers/bluetooth/btusb.c +++ b/trunk/drivers/bluetooth/btusb.c @@ -52,9 +52,6 @@ static struct usb_device_id btusb_table[] = { /* Generic Bluetooth USB device */ { USB_DEVICE_INFO(0xe0, 0x01, 0x01) }, - /* Apple-specific (Broadcom) devices */ - { USB_VENDOR_AND_INTERFACE_INFO(0x05ac, 0xff, 0x01, 0x01) }, - /* Broadcom SoftSailing reporting vendor specific */ { USB_DEVICE(0x0a5c, 0x21e1) }, @@ -97,14 +94,15 @@ static struct usb_device_id btusb_table[] = { /* Broadcom BCM20702A0 */ { USB_DEVICE(0x0489, 0xe042) }, + { USB_DEVICE(0x0a5c, 0x21e3) }, + { USB_DEVICE(0x0a5c, 0x21e6) }, + { USB_DEVICE(0x0a5c, 0x21e8) }, + { USB_DEVICE(0x0a5c, 0x21f3) }, { USB_DEVICE(0x413c, 0x8197) }, /* Foxconn - Hon Hai */ { USB_DEVICE(0x0489, 0xe033) }, - /*Broadcom devices with vendor specific id */ - { USB_VENDOR_AND_INTERFACE_INFO(0x0a5c, 0xff, 0x01, 0x01) }, - { } /* Terminating entry */ }; @@ -135,14 +133,12 @@ static struct usb_device_id blacklist_table[] = { { USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 }, - { USB_DEVICE(0x0489, 0xe057), .driver_info = BTUSB_ATH3012 }, /* Atheros AR5BBU12 with sflash firmware */ { USB_DEVICE(0x0489, 0xe02c), .driver_info = BTUSB_IGNORE }, /* Atheros AR5BBU12 with sflash firmware */ { USB_DEVICE(0x0489, 0xe03c), .driver_info = BTUSB_ATH3012 }, - { USB_DEVICE(0x0489, 0xe036), .driver_info = BTUSB_ATH3012 }, /* Broadcom BCM2035 */ { USB_DEVICE(0x0a5c, 0x2035), .driver_info = BTUSB_WRONG_SCO_MTU }, diff --git a/trunk/drivers/bluetooth/hci_ath.c b/trunk/drivers/bluetooth/hci_ath.c index 0bc8a6a6a148..12172a6a95c4 100644 --- a/trunk/drivers/bluetooth/hci_ath.c +++ b/trunk/drivers/bluetooth/hci_ath.c @@ -58,7 +58,7 @@ static int ath_wakeup_ar3k(struct tty_struct *tty) return status; /* Disable Automatic RTSCTS */ - ktermios = tty->termios; + memcpy(&ktermios, tty->termios, sizeof(ktermios)); ktermios.c_cflag &= ~CRTSCTS; tty_set_termios(tty, &ktermios); diff --git a/trunk/drivers/char/Kconfig b/trunk/drivers/char/Kconfig index 72bedad6bf8c..ea6f6325f9ba 100644 --- a/trunk/drivers/char/Kconfig +++ b/trunk/drivers/char/Kconfig @@ -418,8 +418,8 @@ config APPLICOM If unsure, say N. config SONYPI - tristate "Sony Vaio Programmable I/O Control Device support" - depends on X86 && PCI && INPUT && !64BIT + tristate "Sony Vaio Programmable I/O Control Device support (EXPERIMENTAL)" + depends on EXPERIMENTAL && X86 && PCI && INPUT && !64BIT ---help--- This driver enables access to the Sony Programmable I/O Control Device which can be found in many (all ?) Sony Vaio laptops. @@ -566,7 +566,7 @@ source "drivers/char/tpm/Kconfig" config TELCLOCK tristate "Telecom clock driver for ATCA SBC" - depends on X86 + depends on EXPERIMENTAL && X86 default n help The telecom clock device is specific to the MPCBL0010 and MPCBL0050 diff --git a/trunk/drivers/char/agp/intel-agp.h b/trunk/drivers/char/agp/intel-agp.h index 6ec0fff79bc2..57226424690c 100644 --- a/trunk/drivers/char/agp/intel-agp.h +++ b/trunk/drivers/char/agp/intel-agp.h @@ -64,7 +64,6 @@ #define I830_PTE_SYSTEM_CACHED 0x00000006 /* GT PTE cache control fields */ #define GEN6_PTE_UNCACHED 0x00000002 -#define HSW_PTE_UNCACHED 0x00000000 #define GEN6_PTE_LLC 0x00000004 #define GEN6_PTE_LLC_MLC 0x00000006 #define GEN6_PTE_GFDT 0x00000008 @@ -240,45 +239,16 @@ #define PCI_DEVICE_ID_INTEL_IVYBRIDGE_S_GT2_IG 0x016A #define PCI_DEVICE_ID_INTEL_VALLEYVIEW_HB 0x0F00 /* VLV1 */ #define PCI_DEVICE_ID_INTEL_VALLEYVIEW_IG 0x0F30 -#define PCI_DEVICE_ID_INTEL_HASWELL_HB 0x0400 /* Desktop */ +#define PCI_DEVICE_ID_INTEL_HASWELL_HB 0x0400 /* Desktop */ #define PCI_DEVICE_ID_INTEL_HASWELL_D_GT1_IG 0x0402 #define PCI_DEVICE_ID_INTEL_HASWELL_D_GT2_IG 0x0412 -#define PCI_DEVICE_ID_INTEL_HASWELL_D_GT2_PLUS_IG 0x0422 -#define PCI_DEVICE_ID_INTEL_HASWELL_M_HB 0x0404 /* Mobile */ +#define PCI_DEVICE_ID_INTEL_HASWELL_M_HB 0x0404 /* Mobile */ #define PCI_DEVICE_ID_INTEL_HASWELL_M_GT1_IG 0x0406 #define PCI_DEVICE_ID_INTEL_HASWELL_M_GT2_IG 0x0416 -#define PCI_DEVICE_ID_INTEL_HASWELL_M_GT2_PLUS_IG 0x0426 -#define PCI_DEVICE_ID_INTEL_HASWELL_S_HB 0x0408 /* Server */ +#define PCI_DEVICE_ID_INTEL_HASWELL_S_HB 0x0408 /* Server */ #define PCI_DEVICE_ID_INTEL_HASWELL_S_GT1_IG 0x040a #define PCI_DEVICE_ID_INTEL_HASWELL_S_GT2_IG 0x041a -#define PCI_DEVICE_ID_INTEL_HASWELL_S_GT2_PLUS_IG 0x042a -#define PCI_DEVICE_ID_INTEL_HASWELL_E_HB 0x0c04 -#define PCI_DEVICE_ID_INTEL_HASWELL_SDV_D_GT1_IG 0x0C02 -#define PCI_DEVICE_ID_INTEL_HASWELL_SDV_D_GT2_IG 0x0C12 -#define PCI_DEVICE_ID_INTEL_HASWELL_SDV_D_GT2_PLUS_IG 0x0C22 -#define PCI_DEVICE_ID_INTEL_HASWELL_SDV_M_GT1_IG 0x0C06 -#define PCI_DEVICE_ID_INTEL_HASWELL_SDV_M_GT2_IG 0x0C16 -#define PCI_DEVICE_ID_INTEL_HASWELL_SDV_M_GT2_PLUS_IG 0x0C26 -#define PCI_DEVICE_ID_INTEL_HASWELL_SDV_S_GT1_IG 0x0C0A -#define PCI_DEVICE_ID_INTEL_HASWELL_SDV_S_GT2_IG 0x0C1A -#define PCI_DEVICE_ID_INTEL_HASWELL_SDV_S_GT2_PLUS_IG 0x0C2A -#define PCI_DEVICE_ID_INTEL_HASWELL_ULT_D_GT1_IG 0x0A02 -#define PCI_DEVICE_ID_INTEL_HASWELL_ULT_D_GT2_IG 0x0A12 -#define PCI_DEVICE_ID_INTEL_HASWELL_ULT_D_GT2_PLUS_IG 0x0A22 -#define PCI_DEVICE_ID_INTEL_HASWELL_ULT_M_GT1_IG 0x0A06 -#define PCI_DEVICE_ID_INTEL_HASWELL_ULT_M_GT2_IG 0x0A16 -#define PCI_DEVICE_ID_INTEL_HASWELL_ULT_M_GT2_PLUS_IG 0x0A26 -#define PCI_DEVICE_ID_INTEL_HASWELL_ULT_S_GT1_IG 0x0A0A -#define PCI_DEVICE_ID_INTEL_HASWELL_ULT_S_GT2_IG 0x0A1A -#define PCI_DEVICE_ID_INTEL_HASWELL_ULT_S_GT2_PLUS_IG 0x0A2A -#define PCI_DEVICE_ID_INTEL_HASWELL_CRW_D_GT1_IG 0x0D12 -#define PCI_DEVICE_ID_INTEL_HASWELL_CRW_D_GT2_IG 0x0D22 -#define PCI_DEVICE_ID_INTEL_HASWELL_CRW_D_GT2_PLUS_IG 0x0D32 -#define PCI_DEVICE_ID_INTEL_HASWELL_CRW_M_GT1_IG 0x0D16 -#define PCI_DEVICE_ID_INTEL_HASWELL_CRW_M_GT2_IG 0x0D26 -#define PCI_DEVICE_ID_INTEL_HASWELL_CRW_M_GT2_PLUS_IG 0x0D36 -#define PCI_DEVICE_ID_INTEL_HASWELL_CRW_S_GT1_IG 0x0D1A -#define PCI_DEVICE_ID_INTEL_HASWELL_CRW_S_GT2_IG 0x0D2A -#define PCI_DEVICE_ID_INTEL_HASWELL_CRW_S_GT2_PLUS_IG 0x0D3A +#define PCI_DEVICE_ID_INTEL_HASWELL_SDV 0x0c16 /* SDV */ +#define PCI_DEVICE_ID_INTEL_HASWELL_E_HB 0x0c04 #endif diff --git a/trunk/drivers/char/agp/intel-gtt.c b/trunk/drivers/char/agp/intel-gtt.c index 58e32f7c3229..9ed92ef5829b 100644 --- a/trunk/drivers/char/agp/intel-gtt.c +++ b/trunk/drivers/char/agp/intel-gtt.c @@ -1156,30 +1156,6 @@ static bool gen6_check_flags(unsigned int flags) return true; } -static void haswell_write_entry(dma_addr_t addr, unsigned int entry, - unsigned int flags) -{ - unsigned int type_mask = flags & ~AGP_USER_CACHED_MEMORY_GFDT; - unsigned int gfdt = flags & AGP_USER_CACHED_MEMORY_GFDT; - u32 pte_flags; - - if (type_mask == AGP_USER_MEMORY) - pte_flags = HSW_PTE_UNCACHED | I810_PTE_VALID; - else if (type_mask == AGP_USER_CACHED_MEMORY_LLC_MLC) { - pte_flags = GEN6_PTE_LLC_MLC | I810_PTE_VALID; - if (gfdt) - pte_flags |= GEN6_PTE_GFDT; - } else { /* set 'normal'/'cached' to LLC by default */ - pte_flags = GEN6_PTE_LLC | I810_PTE_VALID; - if (gfdt) - pte_flags |= GEN6_PTE_GFDT; - } - - /* gen6 has bit11-4 for physical addr bit39-32 */ - addr |= (addr >> 28) & 0xff0; - writel(addr | pte_flags, intel_private.gtt + entry); -} - static void gen6_write_entry(dma_addr_t addr, unsigned int entry, unsigned int flags) { @@ -1406,15 +1382,6 @@ static const struct intel_gtt_driver sandybridge_gtt_driver = { .check_flags = gen6_check_flags, .chipset_flush = i9xx_chipset_flush, }; -static const struct intel_gtt_driver haswell_gtt_driver = { - .gen = 6, - .setup = i9xx_setup, - .cleanup = gen6_cleanup, - .write_entry = haswell_write_entry, - .dma_mask_size = 40, - .check_flags = gen6_check_flags, - .chipset_flush = i9xx_chipset_flush, -}; static const struct intel_gtt_driver valleyview_gtt_driver = { .gen = 7, .setup = i9xx_setup, @@ -1532,77 +1499,19 @@ static const struct intel_gtt_driver_description { { PCI_DEVICE_ID_INTEL_VALLEYVIEW_IG, "ValleyView", &valleyview_gtt_driver }, { PCI_DEVICE_ID_INTEL_HASWELL_D_GT1_IG, - "Haswell", &haswell_gtt_driver }, + "Haswell", &sandybridge_gtt_driver }, { PCI_DEVICE_ID_INTEL_HASWELL_D_GT2_IG, - "Haswell", &haswell_gtt_driver }, - { PCI_DEVICE_ID_INTEL_HASWELL_D_GT2_PLUS_IG, - "Haswell", &haswell_gtt_driver }, + "Haswell", &sandybridge_gtt_driver }, { PCI_DEVICE_ID_INTEL_HASWELL_M_GT1_IG, - "Haswell", &haswell_gtt_driver }, + "Haswell", &sandybridge_gtt_driver }, { PCI_DEVICE_ID_INTEL_HASWELL_M_GT2_IG, - "Haswell", &haswell_gtt_driver }, - { PCI_DEVICE_ID_INTEL_HASWELL_M_GT2_PLUS_IG, - "Haswell", &haswell_gtt_driver }, + "Haswell", &sandybridge_gtt_driver }, { PCI_DEVICE_ID_INTEL_HASWELL_S_GT1_IG, - "Haswell", &haswell_gtt_driver }, + "Haswell", &sandybridge_gtt_driver }, { PCI_DEVICE_ID_INTEL_HASWELL_S_GT2_IG, - "Haswell", &haswell_gtt_driver }, - { PCI_DEVICE_ID_INTEL_HASWELL_S_GT2_PLUS_IG, - "Haswell", &haswell_gtt_driver }, - { PCI_DEVICE_ID_INTEL_HASWELL_SDV_D_GT1_IG, - "Haswell", &haswell_gtt_driver }, - { PCI_DEVICE_ID_INTEL_HASWELL_SDV_D_GT2_IG, - "Haswell", &haswell_gtt_driver }, - { PCI_DEVICE_ID_INTEL_HASWELL_SDV_D_GT2_PLUS_IG, - "Haswell", &haswell_gtt_driver }, - { PCI_DEVICE_ID_INTEL_HASWELL_SDV_M_GT1_IG, - "Haswell", &haswell_gtt_driver }, - { PCI_DEVICE_ID_INTEL_HASWELL_SDV_M_GT2_IG, - "Haswell", &haswell_gtt_driver }, - { PCI_DEVICE_ID_INTEL_HASWELL_SDV_M_GT2_PLUS_IG, - "Haswell", &haswell_gtt_driver }, - { PCI_DEVICE_ID_INTEL_HASWELL_SDV_S_GT1_IG, - "Haswell", &haswell_gtt_driver }, - { PCI_DEVICE_ID_INTEL_HASWELL_SDV_S_GT2_IG, - "Haswell", &haswell_gtt_driver }, - { PCI_DEVICE_ID_INTEL_HASWELL_SDV_S_GT2_PLUS_IG, - "Haswell", &haswell_gtt_driver }, - { PCI_DEVICE_ID_INTEL_HASWELL_ULT_D_GT1_IG, - "Haswell", &haswell_gtt_driver }, - { PCI_DEVICE_ID_INTEL_HASWELL_ULT_D_GT2_IG, - "Haswell", &haswell_gtt_driver }, - { PCI_DEVICE_ID_INTEL_HASWELL_ULT_D_GT2_PLUS_IG, - "Haswell", &haswell_gtt_driver }, - { PCI_DEVICE_ID_INTEL_HASWELL_ULT_M_GT1_IG, - "Haswell", &haswell_gtt_driver }, - { PCI_DEVICE_ID_INTEL_HASWELL_ULT_M_GT2_IG, - "Haswell", &haswell_gtt_driver }, - { PCI_DEVICE_ID_INTEL_HASWELL_ULT_M_GT2_PLUS_IG, - "Haswell", &haswell_gtt_driver }, - { PCI_DEVICE_ID_INTEL_HASWELL_ULT_S_GT1_IG, - "Haswell", &haswell_gtt_driver }, - { PCI_DEVICE_ID_INTEL_HASWELL_ULT_S_GT2_IG, - "Haswell", &haswell_gtt_driver }, - { PCI_DEVICE_ID_INTEL_HASWELL_ULT_S_GT2_PLUS_IG, - "Haswell", &haswell_gtt_driver }, - { PCI_DEVICE_ID_INTEL_HASWELL_CRW_D_GT1_IG, - "Haswell", &haswell_gtt_driver }, - { PCI_DEVICE_ID_INTEL_HASWELL_CRW_D_GT2_IG, - "Haswell", &haswell_gtt_driver }, - { PCI_DEVICE_ID_INTEL_HASWELL_CRW_D_GT2_PLUS_IG, - "Haswell", &haswell_gtt_driver }, - { PCI_DEVICE_ID_INTEL_HASWELL_CRW_M_GT1_IG, - "Haswell", &haswell_gtt_driver }, - { PCI_DEVICE_ID_INTEL_HASWELL_CRW_M_GT2_IG, - "Haswell", &haswell_gtt_driver }, - { PCI_DEVICE_ID_INTEL_HASWELL_CRW_M_GT2_PLUS_IG, - "Haswell", &haswell_gtt_driver }, - { PCI_DEVICE_ID_INTEL_HASWELL_CRW_S_GT1_IG, - "Haswell", &haswell_gtt_driver }, - { PCI_DEVICE_ID_INTEL_HASWELL_CRW_S_GT2_IG, - "Haswell", &haswell_gtt_driver }, - { PCI_DEVICE_ID_INTEL_HASWELL_CRW_S_GT2_PLUS_IG, - "Haswell", &haswell_gtt_driver }, + "Haswell", &sandybridge_gtt_driver }, + { PCI_DEVICE_ID_INTEL_HASWELL_SDV, + "Haswell", &sandybridge_gtt_driver }, { 0, NULL, NULL } }; diff --git a/trunk/drivers/char/agp/sgi-agp.c b/trunk/drivers/char/agp/sgi-agp.c index 3a5af2f9b015..192000377737 100644 --- a/trunk/drivers/char/agp/sgi-agp.c +++ b/trunk/drivers/char/agp/sgi-agp.c @@ -289,11 +289,12 @@ static int __devinit agp_sgi_init(void) j = 0; list_for_each_entry(info, &tioca_list, ca_list) { + struct list_head *tmp; if (list_empty(info->ca_devices)) continue; - list_for_each_entry(pdev, info->ca_devices, bus_list) { + list_for_each(tmp, info->ca_devices) { u8 cap_ptr; - + pdev = pci_dev_b(tmp); if (pdev->class != (PCI_CLASS_DISPLAY_VGA << 8)) continue; cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP); diff --git a/trunk/drivers/char/hw_random/omap-rng.c b/trunk/drivers/char/hw_random/omap-rng.c index 4fbdceb6f773..d706bd0e9e80 100644 --- a/trunk/drivers/char/hw_random/omap-rng.c +++ b/trunk/drivers/char/hw_random/omap-rng.c @@ -160,7 +160,7 @@ static int __exit omap_rng_remove(struct platform_device *pdev) return 0; } -#ifdef CONFIG_PM_SLEEP +#ifdef CONFIG_PM static int omap_rng_suspend(struct device *dev) { diff --git a/trunk/drivers/char/mmtimer.c b/trunk/drivers/char/mmtimer.c index 3d6c0671e996..33dc2298af73 100644 --- a/trunk/drivers/char/mmtimer.c +++ b/trunk/drivers/char/mmtimer.c @@ -826,7 +826,7 @@ static int __init mmtimer_init(void) /* Allocate list of node ptrs to mmtimer_t's */ timers = kzalloc(sizeof(struct mmtimer_node)*maxn, GFP_KERNEL); - if (!timers) { + if (timers == NULL) { printk(KERN_ERR "%s: failed to allocate memory for device\n", MMTIMER_NAME); goto out3; @@ -848,6 +848,7 @@ static int __init mmtimer_init(void) return 0; out3: + kfree(timers); misc_deregister(&mmtimer_miscdev); out2: free_irq(SGI_MMTIMER_VECTOR, NULL); diff --git a/trunk/drivers/char/mwave/mwavedd.c b/trunk/drivers/char/mwave/mwavedd.c index 164544afd680..1d82d5838f0c 100644 --- a/trunk/drivers/char/mwave/mwavedd.c +++ b/trunk/drivers/char/mwave/mwavedd.c @@ -430,7 +430,7 @@ static ssize_t mwave_write(struct file *file, const char __user *buf, static int register_serial_portandirq(unsigned int port, int irq) { - struct uart_8250_port uart; + struct uart_port uart; switch ( port ) { case 0x3f8: @@ -462,14 +462,14 @@ static int register_serial_portandirq(unsigned int port, int irq) } /* switch */ /* irq is okay */ - memset(&uart, 0, sizeof(uart)); + memset(&uart, 0, sizeof(struct uart_port)); - uart.port.uartclk = 1843200; - uart.port.iobase = port; - uart.port.irq = irq; - uart.port.iotype = UPIO_PORT; - uart.port.flags = UPF_SHARE_IRQ; - return serial8250_register_8250_port(&uart); + uart.uartclk = 1843200; + uart.iobase = port; + uart.irq = irq; + uart.iotype = UPIO_PORT; + uart.flags = UPF_SHARE_IRQ; + return serial8250_register_port(&uart); } diff --git a/trunk/drivers/char/nwbutton.c b/trunk/drivers/char/nwbutton.c index cfdfe493c6af..04a480f86c6c 100644 --- a/trunk/drivers/char/nwbutton.c +++ b/trunk/drivers/char/nwbutton.c @@ -93,9 +93,9 @@ int button_del_callback (void (*callback) (void)) button_callback_list [lp].count = 0; callback_count--; return 0; - } + }; lp--; - } + }; return -EINVAL; } diff --git a/trunk/drivers/char/pcmcia/synclink_cs.c b/trunk/drivers/char/pcmcia/synclink_cs.c index 21721d25e388..0a484b4a1b02 100644 --- a/trunk/drivers/char/pcmcia/synclink_cs.c +++ b/trunk/drivers/char/pcmcia/synclink_cs.c @@ -891,14 +891,6 @@ static void rx_ready_async(MGSLPC_INFO *info, int tcd, struct tty_struct *tty) int work = 0; struct mgsl_icount *icount = &info->icount; - if (!tty) { - /* tty is not available anymore */ - issue_command(info, CHA, CMD_RXRESET); - if (debug_level >= DEBUG_LEVEL_ISR) - printk("%s(%d):rx_ready_async(tty=NULL)\n",__FILE__,__LINE__); - return; - } - if (tcd) { /* early termination, get FIFO count from RBCL register */ fifo_count = (unsigned char)(read_reg(info, CHA+RBCL) & 0x1f); @@ -988,7 +980,7 @@ static void tx_done(MGSLPC_INFO *info, struct tty_struct *tty) else #endif { - if (tty && (tty->stopped || tty->hw_stopped)) { + if (tty->stopped || tty->hw_stopped) { tx_stop(info); return; } @@ -1008,7 +1000,7 @@ static void tx_ready(MGSLPC_INFO *info, struct tty_struct *tty) if (!info->tx_active) return; } else { - if (tty && (tty->stopped || tty->hw_stopped)) { + if (tty->stopped || tty->hw_stopped) { tx_stop(info); return; } @@ -1058,12 +1050,13 @@ static void cts_change(MGSLPC_INFO *info, struct tty_struct *tty) wake_up_interruptible(&info->status_event_wait_q); wake_up_interruptible(&info->event_wait_q); - if (tty && tty_port_cts_enabled(&info->port)) { + if (info->port.flags & ASYNC_CTS_FLOW) { if (tty->hw_stopped) { if (info->serial_signals & SerialSignal_CTS) { if (debug_level >= DEBUG_LEVEL_ISR) printk("CTS tx start..."); - tty->hw_stopped = 0; + if (tty) + tty->hw_stopped = 0; tx_start(info, tty); info->pending_bh |= BH_TRANSMIT; return; @@ -1072,7 +1065,8 @@ static void cts_change(MGSLPC_INFO *info, struct tty_struct *tty) if (!(info->serial_signals & SerialSignal_CTS)) { if (debug_level >= DEBUG_LEVEL_ISR) printk("CTS tx stop..."); - tty->hw_stopped = 1; + if (tty) + tty->hw_stopped = 1; tx_stop(info); } } @@ -1350,7 +1344,7 @@ static void shutdown(MGSLPC_INFO * info, struct tty_struct *tty) /* TODO:disable interrupts instead of reset to preserve signal states */ reset_device(info); - if (!tty || tty->termios.c_cflag & HUPCL) { + if (!tty || tty->termios->c_cflag & HUPCL) { info->serial_signals &= ~(SerialSignal_DTR + SerialSignal_RTS); set_signals(info); } @@ -1391,7 +1385,7 @@ static void mgslpc_program_hw(MGSLPC_INFO *info, struct tty_struct *tty) port_irq_enable(info, (unsigned char) PVR_DSR | PVR_RI); get_signals(info); - if (info->netcount || (tty && (tty->termios.c_cflag & CREAD))) + if (info->netcount || (tty && (tty->termios->c_cflag & CREAD))) rx_start(info); spin_unlock_irqrestore(&info->lock,flags); @@ -1404,14 +1398,14 @@ static void mgslpc_change_params(MGSLPC_INFO *info, struct tty_struct *tty) unsigned cflag; int bits_per_char; - if (!tty) + if (!tty || !tty->termios) return; if (debug_level >= DEBUG_LEVEL_INFO) printk("%s(%d):mgslpc_change_params(%s)\n", __FILE__,__LINE__, info->device_name ); - cflag = tty->termios.c_cflag; + cflag = tty->termios->c_cflag; /* if B0 rate (hangup) specified then negate DTR and RTS */ /* otherwise assert DTR and RTS */ @@ -1734,7 +1728,7 @@ static void mgslpc_throttle(struct tty_struct * tty) if (I_IXOFF(tty)) mgslpc_send_xchar(tty, STOP_CHAR(tty)); - if (tty->termios.c_cflag & CRTSCTS) { + if (tty->termios->c_cflag & CRTSCTS) { spin_lock_irqsave(&info->lock,flags); info->serial_signals &= ~SerialSignal_RTS; set_signals(info); @@ -1763,7 +1757,7 @@ static void mgslpc_unthrottle(struct tty_struct * tty) mgslpc_send_xchar(tty, START_CHAR(tty)); } - if (tty->termios.c_cflag & CRTSCTS) { + if (tty->termios->c_cflag & CRTSCTS) { spin_lock_irqsave(&info->lock,flags); info->serial_signals |= SerialSignal_RTS; set_signals(info); @@ -2299,8 +2293,8 @@ static void mgslpc_set_termios(struct tty_struct *tty, struct ktermios *old_term tty->driver->name ); /* just return if nothing has changed */ - if ((tty->termios.c_cflag == old_termios->c_cflag) - && (RELEVANT_IFLAG(tty->termios.c_iflag) + if ((tty->termios->c_cflag == old_termios->c_cflag) + && (RELEVANT_IFLAG(tty->termios->c_iflag) == RELEVANT_IFLAG(old_termios->c_iflag))) return; @@ -2308,7 +2302,7 @@ static void mgslpc_set_termios(struct tty_struct *tty, struct ktermios *old_term /* Handle transition to B0 status */ if (old_termios->c_cflag & CBAUD && - !(tty->termios.c_cflag & CBAUD)) { + !(tty->termios->c_cflag & CBAUD)) { info->serial_signals &= ~(SerialSignal_RTS + SerialSignal_DTR); spin_lock_irqsave(&info->lock,flags); set_signals(info); @@ -2317,9 +2311,9 @@ static void mgslpc_set_termios(struct tty_struct *tty, struct ktermios *old_term /* Handle transition away from B0 status */ if (!(old_termios->c_cflag & CBAUD) && - tty->termios.c_cflag & CBAUD) { + tty->termios->c_cflag & CBAUD) { info->serial_signals |= SerialSignal_DTR; - if (!(tty->termios.c_cflag & CRTSCTS) || + if (!(tty->termios->c_cflag & CRTSCTS) || !test_bit(TTY_THROTTLED, &tty->flags)) { info->serial_signals |= SerialSignal_RTS; } @@ -2330,7 +2324,7 @@ static void mgslpc_set_termios(struct tty_struct *tty, struct ktermios *old_term /* Handle turning off CRTSCTS */ if (old_termios->c_cflag & CRTSCTS && - !(tty->termios.c_cflag & CRTSCTS)) { + !(tty->termios->c_cflag & CRTSCTS)) { tty->hw_stopped = 0; tx_release(tty); } @@ -2737,8 +2731,6 @@ static void mgslpc_add_device(MGSLPC_INFO *info) #if SYNCLINK_GENERIC_HDLC hdlcdev_init(info); #endif - tty_port_register_device(&info->port, serial_driver, info->line, - &info->p_dev->dev); } static void mgslpc_remove_device(MGSLPC_INFO *remove_info) @@ -2752,7 +2744,6 @@ static void mgslpc_remove_device(MGSLPC_INFO *remove_info) last->next_device = info->next_device; else mgslpc_device_list = info->next_device; - tty_unregister_device(serial_driver, info->line); #if SYNCLINK_GENERIC_HDLC hdlcdev_exit(info); #endif @@ -2807,63 +2798,77 @@ static const struct tty_operations mgslpc_ops = { .proc_fops = &mgslpc_proc_fops, }; -static int __init synclink_cs_init(void) +static void synclink_cs_cleanup(void) { int rc; - if (break_on_load) { - mgslpc_get_text_ptr(); - BREAKPOINT(); - } + while(mgslpc_device_list) + mgslpc_remove_device(mgslpc_device_list); - serial_driver = tty_alloc_driver(MAX_DEVICE_COUNT, - TTY_DRIVER_REAL_RAW | - TTY_DRIVER_DYNAMIC_DEV); - if (IS_ERR(serial_driver)) { - rc = PTR_ERR(serial_driver); - goto err; + if (serial_driver) { + if ((rc = tty_unregister_driver(serial_driver))) + printk("%s(%d) failed to unregister tty driver err=%d\n", + __FILE__,__LINE__,rc); + put_tty_driver(serial_driver); } - /* Initialize the tty_driver structure */ - serial_driver->driver_name = "synclink_cs"; - serial_driver->name = "ttySLP"; - serial_driver->major = ttymajor; - serial_driver->minor_start = 64; - serial_driver->type = TTY_DRIVER_TYPE_SERIAL; - serial_driver->subtype = SERIAL_TYPE_NORMAL; - serial_driver->init_termios = tty_std_termios; - serial_driver->init_termios.c_cflag = - B9600 | CS8 | CREAD | HUPCL | CLOCAL; - tty_set_operations(serial_driver, &mgslpc_ops); - - rc = tty_register_driver(serial_driver); - if (rc < 0) { - printk(KERN_ERR "%s(%d):Couldn't register serial driver\n", - __FILE__, __LINE__); - goto err_put_tty; - } + pcmcia_unregister_driver(&mgslpc_driver); +} - rc = pcmcia_register_driver(&mgslpc_driver); - if (rc < 0) - goto err_unreg_tty; +static int __init synclink_cs_init(void) +{ + int rc; - printk(KERN_INFO "%s %s, tty major#%d\n", driver_name, driver_version, - serial_driver->major); + if (break_on_load) { + mgslpc_get_text_ptr(); + BREAKPOINT(); + } - return 0; -err_unreg_tty: - tty_unregister_driver(serial_driver); -err_put_tty: - put_tty_driver(serial_driver); -err: - return rc; + if ((rc = pcmcia_register_driver(&mgslpc_driver)) < 0) + return rc; + + serial_driver = alloc_tty_driver(MAX_DEVICE_COUNT); + if (!serial_driver) { + rc = -ENOMEM; + goto error; + } + + /* Initialize the tty_driver structure */ + + serial_driver->driver_name = "synclink_cs"; + serial_driver->name = "ttySLP"; + serial_driver->major = ttymajor; + serial_driver->minor_start = 64; + serial_driver->type = TTY_DRIVER_TYPE_SERIAL; + serial_driver->subtype = SERIAL_TYPE_NORMAL; + serial_driver->init_termios = tty_std_termios; + serial_driver->init_termios.c_cflag = + B9600 | CS8 | CREAD | HUPCL | CLOCAL; + serial_driver->flags = TTY_DRIVER_REAL_RAW; + tty_set_operations(serial_driver, &mgslpc_ops); + + if ((rc = tty_register_driver(serial_driver)) < 0) { + printk("%s(%d):Couldn't register serial driver\n", + __FILE__,__LINE__); + put_tty_driver(serial_driver); + serial_driver = NULL; + goto error; + } + + printk("%s %s, tty major#%d\n", + driver_name, driver_version, + serial_driver->major); + + return 0; + +error: + synclink_cs_cleanup(); + return rc; } static void __exit synclink_cs_exit(void) { - pcmcia_unregister_driver(&mgslpc_driver); - tty_unregister_driver(serial_driver); - put_tty_driver(serial_driver); + synclink_cs_cleanup(); } module_init(synclink_cs_init); diff --git a/trunk/drivers/char/ppdev.c b/trunk/drivers/char/ppdev.c index d0d824ebf2c1..3fcf80ff12f2 100644 --- a/trunk/drivers/char/ppdev.c +++ b/trunk/drivers/char/ppdev.c @@ -783,8 +783,7 @@ static int __init ppdev_init (void) err = PTR_ERR(ppdev_class); goto out_chrdev; } - err = parport_register_driver(&pp_driver); - if (err < 0) { + if (parport_register_driver(&pp_driver)) { printk (KERN_WARNING CHRDEV ": unable to register with parport\n"); goto out_class; } diff --git a/trunk/drivers/char/rtc.c b/trunk/drivers/char/rtc.c index 91470fdbab2a..af9437488b6c 100644 --- a/trunk/drivers/char/rtc.c +++ b/trunk/drivers/char/rtc.c @@ -411,7 +411,7 @@ static int rtc_do_ioctl(unsigned int cmd, unsigned long arg, int kernel) case RTC_IRQP_READ: case RTC_IRQP_SET: return -EINVAL; - } + }; } #endif diff --git a/trunk/drivers/char/tlclk.c b/trunk/drivers/char/tlclk.c index e95e0ab0bd87..ce29e7cce528 100644 --- a/trunk/drivers/char/tlclk.c +++ b/trunk/drivers/char/tlclk.c @@ -784,10 +784,8 @@ static int __init tlclk_init(void) } tlclk_major = ret; alarm_events = kzalloc( sizeof(struct tlclk_alarms), GFP_KERNEL); - if (!alarm_events) { - ret = -ENOMEM; + if (!alarm_events) goto out1; - } /* Read telecom clock IRQ number (Set by BIOS) */ if (!request_region(TLCLK_BASE, 8, "telco_clock")) { diff --git a/trunk/drivers/char/tpm/tpm_tis.c b/trunk/drivers/char/tpm/tpm_tis.c index c4be3519a587..89682fa8801e 100644 --- a/trunk/drivers/char/tpm/tpm_tis.c +++ b/trunk/drivers/char/tpm/tpm_tis.c @@ -807,7 +807,6 @@ module_param_string(hid, tpm_pnp_tbl[TIS_HID_USR_IDX].id, MODULE_PARM_DESC(hid, "Set additional specific HID for this driver to probe"); #endif -#ifdef CONFIG_PM_SLEEP static int tpm_tis_resume(struct device *dev) { struct tpm_chip *chip = dev_get_drvdata(dev); @@ -817,7 +816,6 @@ static int tpm_tis_resume(struct device *dev) return tpm_pm_resume(dev); } -#endif static SIMPLE_DEV_PM_OPS(tpm_tis_pm, tpm_pm_suspend, tpm_tis_resume); diff --git a/trunk/drivers/char/ttyprintk.c b/trunk/drivers/char/ttyprintk.c index af98f6d6509b..46b77ede84c0 100644 --- a/trunk/drivers/char/ttyprintk.c +++ b/trunk/drivers/char/ttyprintk.c @@ -67,7 +67,7 @@ static int tpk_printk(const unsigned char *buf, int count) tmp[tpk_curr + 1] = '\0'; printk(KERN_INFO "%s%s", tpk_tag, tmp); tpk_curr = 0; - if ((i + 1) < count && buf[i + 1] == '\n') + if (buf[i + 1] == '\n') i++; break; case '\n': @@ -178,17 +178,11 @@ static struct tty_driver *ttyprintk_driver; static int __init ttyprintk_init(void) { int ret = -ENOMEM; + void *rp; - tty_port_init(&tpk_port.port); - tpk_port.port.ops = &null_ops; - mutex_init(&tpk_port.port_write_mutex); - - ttyprintk_driver = tty_alloc_driver(1, - TTY_DRIVER_RESET_TERMIOS | - TTY_DRIVER_REAL_RAW | - TTY_DRIVER_UNNUMBERED_NODE); - if (IS_ERR(ttyprintk_driver)) - return PTR_ERR(ttyprintk_driver); + ttyprintk_driver = alloc_tty_driver(1); + if (!ttyprintk_driver) + return ret; ttyprintk_driver->driver_name = "ttyprintk"; ttyprintk_driver->name = "ttyprintk"; @@ -197,8 +191,9 @@ static int __init ttyprintk_init(void) ttyprintk_driver->type = TTY_DRIVER_TYPE_CONSOLE; ttyprintk_driver->init_termios = tty_std_termios; ttyprintk_driver->init_termios.c_oflag = OPOST | OCRNL | ONOCR | ONLRET; + ttyprintk_driver->flags = TTY_DRIVER_RESET_TERMIOS | + TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV; tty_set_operations(ttyprintk_driver, &ttyprintk_ops); - tty_port_link_device(&tpk_port.port, ttyprintk_driver, 0); ret = tty_register_driver(ttyprintk_driver); if (ret < 0) { @@ -206,10 +201,22 @@ static int __init ttyprintk_init(void) goto error; } + /* create our unnumbered device */ + rp = device_create(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 3), NULL, + ttyprintk_driver->name); + if (IS_ERR(rp)) { + printk(KERN_ERR "Couldn't create ttyprintk device\n"); + ret = PTR_ERR(rp); + goto error; + } + + tty_port_init(&tpk_port.port); + tpk_port.port.ops = &null_ops; + mutex_init(&tpk_port.port_write_mutex); + return 0; error: - tty_unregister_driver(ttyprintk_driver); put_tty_driver(ttyprintk_driver); ttyprintk_driver = NULL; return ret; diff --git a/trunk/drivers/char/virtio_console.c b/trunk/drivers/char/virtio_console.c index 060a672ebb7b..cdf2f5451c76 100644 --- a/trunk/drivers/char/virtio_console.c +++ b/trunk/drivers/char/virtio_console.c @@ -1941,17 +1941,7 @@ static int __init init(void) INIT_LIST_HEAD(&pdrvdata.consoles); INIT_LIST_HEAD(&pdrvdata.portdevs); - err = register_virtio_driver(&virtio_console); - if (err < 0) { - pr_err("Error %d registering virtio driver\n", err); - goto free; - } - return 0; -free: - if (pdrvdata.debugfs_dir) - debugfs_remove_recursive(pdrvdata.debugfs_dir); - class_destroy(pdrvdata.class); - return err; + return register_virtio_driver(&virtio_console); } static void __exit fini(void) diff --git a/trunk/drivers/clk/Kconfig b/trunk/drivers/clk/Kconfig index bace9e98f75d..7f0b5ca78516 100644 --- a/trunk/drivers/clk/Kconfig +++ b/trunk/drivers/clk/Kconfig @@ -40,17 +40,4 @@ config COMMON_CLK_WM831X Supports the clocking subsystem of the WM831x/2x series of PMICs from Wolfson Microlectronics. -config COMMON_CLK_VERSATILE - bool "Clock driver for ARM Reference designs" - depends on ARCH_INTEGRATOR || ARCH_REALVIEW - ---help--- - Supports clocking on ARM Reference designs Integrator/AP, - Integrator/CP, RealView PB1176, EB, PB11MP and PBX. - -config COMMON_CLK_MAX77686 - tristate "Clock driver for Maxim 77686 MFD" - depends on MFD_MAX77686 - ---help--- - This driver supports Maxim 77686 crystal oscillator clock. - endmenu diff --git a/trunk/drivers/clk/Makefile b/trunk/drivers/clk/Makefile index b7b862077d88..5869ea387054 100644 --- a/trunk/drivers/clk/Makefile +++ b/trunk/drivers/clk/Makefile @@ -1,5 +1,4 @@ # common clock types -obj-$(CONFIG_HAVE_CLK) += clk-devres.o obj-$(CONFIG_CLKDEV_LOOKUP) += clkdev.o obj-$(CONFIG_COMMON_CLK) += clk.o clk-fixed-rate.o clk-gate.o \ clk-mux.o clk-divider.o clk-fixed-factor.o @@ -10,14 +9,7 @@ obj-$(CONFIG_ARCH_MXS) += mxs/ obj-$(CONFIG_ARCH_SOCFPGA) += socfpga/ obj-$(CONFIG_PLAT_SPEAR) += spear/ obj-$(CONFIG_ARCH_U300) += clk-u300.o -obj-$(CONFIG_COMMON_CLK_VERSATILE) += versatile/ -obj-$(CONFIG_ARCH_PRIMA2) += clk-prima2.o -ifeq ($(CONFIG_COMMON_CLK), y) -obj-$(CONFIG_ARCH_MMP) += mmp/ -endif -obj-$(CONFIG_MACH_LOONGSON1) += clk-ls1x.o -obj-$(CONFIG_ARCH_U8500) += ux500/ +obj-$(CONFIG_ARCH_INTEGRATOR) += versatile/ # Chip specific obj-$(CONFIG_COMMON_CLK_WM831X) += clk-wm831x.o -obj-$(CONFIG_COMMON_CLK_MAX77686) += clk-max77686.o diff --git a/trunk/drivers/clk/clk-devres.c b/trunk/drivers/clk/clk-devres.c deleted file mode 100644 index 8f571548870f..000000000000 --- a/trunk/drivers/clk/clk-devres.c +++ /dev/null @@ -1,55 +0,0 @@ -/* - * 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 -#include -#include -#include - -static void devm_clk_release(struct device *dev, void *res) -{ - clk_put(*(struct clk **)res); -} - -struct clk *devm_clk_get(struct device *dev, const char *id) -{ - struct clk **ptr, *clk; - - ptr = devres_alloc(devm_clk_release, sizeof(*ptr), GFP_KERNEL); - if (!ptr) - return ERR_PTR(-ENOMEM); - - clk = clk_get(dev, id); - if (!IS_ERR(clk)) { - *ptr = clk; - devres_add(dev, ptr); - } else { - devres_free(ptr); - } - - return clk; -} -EXPORT_SYMBOL(devm_clk_get); - -static int devm_clk_match(struct device *dev, void *res, void *data) -{ - struct clk **c = res; - if (!c || !*c) { - WARN_ON(!c || !*c); - return 0; - } - return *c == data; -} - -void devm_clk_put(struct device *dev, struct clk *clk) -{ - int ret; - - ret = devres_release(dev, devm_clk_release, devm_clk_match, clk); - - WARN_ON(ret); -} -EXPORT_SYMBOL(devm_clk_put); diff --git a/trunk/drivers/clk/clk-ls1x.c b/trunk/drivers/clk/clk-ls1x.c deleted file mode 100644 index f20b750235f6..000000000000 --- a/trunk/drivers/clk/clk-ls1x.c +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright (c) 2012 Zhang, Keguang - * - * 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 - -#define OSC 33 - -static DEFINE_SPINLOCK(_lock); - -static int ls1x_pll_clk_enable(struct clk_hw *hw) -{ - return 0; -} - -static void ls1x_pll_clk_disable(struct clk_hw *hw) -{ -} - -static unsigned long ls1x_pll_recalc_rate(struct clk_hw *hw, - unsigned long parent_rate) -{ - u32 pll, rate; - - pll = __raw_readl(LS1X_CLK_PLL_FREQ); - rate = ((12 + (pll & 0x3f)) * 1000000) + - ((((pll >> 8) & 0x3ff) * 1000000) >> 10); - rate *= OSC; - rate >>= 1; - - return rate; -} - -static const struct clk_ops ls1x_pll_clk_ops = { - .enable = ls1x_pll_clk_enable, - .disable = ls1x_pll_clk_disable, - .recalc_rate = ls1x_pll_recalc_rate, -}; - -static struct clk * __init clk_register_pll(struct device *dev, - const char *name, const char *parent_name, unsigned long flags) -{ - struct clk_hw *hw; - struct clk *clk; - struct clk_init_data init; - - /* allocate the divider */ - hw = kzalloc(sizeof(struct clk_hw), GFP_KERNEL); - if (!hw) { - pr_err("%s: could not allocate clk_hw\n", __func__); - return ERR_PTR(-ENOMEM); - } - - init.name = name; - init.ops = &ls1x_pll_clk_ops; - init.flags = flags | CLK_IS_BASIC; - init.parent_names = (parent_name ? &parent_name : NULL); - init.num_parents = (parent_name ? 1 : 0); - hw->init = &init; - - /* register the clock */ - clk = clk_register(dev, hw); - - if (IS_ERR(clk)) - kfree(hw); - - return clk; -} - -void __init ls1x_clk_init(void) -{ - struct clk *clk; - - clk = clk_register_pll(NULL, "pll_clk", NULL, CLK_IS_ROOT); - clk_prepare_enable(clk); - - clk = clk_register_divider(NULL, "cpu_clk", "pll_clk", - CLK_SET_RATE_PARENT, LS1X_CLK_PLL_DIV, DIV_CPU_SHIFT, - DIV_CPU_WIDTH, CLK_DIVIDER_ONE_BASED, &_lock); - clk_prepare_enable(clk); - clk_register_clkdev(clk, "cpu", NULL); - - clk = clk_register_divider(NULL, "dc_clk", "pll_clk", - CLK_SET_RATE_PARENT, LS1X_CLK_PLL_DIV, DIV_DC_SHIFT, - DIV_DC_WIDTH, CLK_DIVIDER_ONE_BASED, &_lock); - clk_prepare_enable(clk); - clk_register_clkdev(clk, "dc", NULL); - - clk = clk_register_divider(NULL, "ahb_clk", "pll_clk", - CLK_SET_RATE_PARENT, LS1X_CLK_PLL_DIV, DIV_DDR_SHIFT, - DIV_DDR_WIDTH, CLK_DIVIDER_ONE_BASED, &_lock); - clk_prepare_enable(clk); - clk_register_clkdev(clk, "ahb", NULL); - clk_register_clkdev(clk, "stmmaceth", NULL); - - clk = clk_register_fixed_factor(NULL, "apb_clk", "ahb_clk", 0, 1, 2); - clk_prepare_enable(clk); - clk_register_clkdev(clk, "apb", NULL); - clk_register_clkdev(clk, "serial8250", NULL); -} diff --git a/trunk/drivers/clk/clk-max77686.c b/trunk/drivers/clk/clk-max77686.c deleted file mode 100644 index ac5f5434cb9a..000000000000 --- a/trunk/drivers/clk/clk-max77686.c +++ /dev/null @@ -1,244 +0,0 @@ -/* - * clk-max77686.c - Clock driver for Maxim 77686 - * - * Copyright (C) 2012 Samsung Electornics - * Jonghwa Lee - * - * 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 - -enum { - MAX77686_CLK_AP = 0, - MAX77686_CLK_CP, - MAX77686_CLK_PMIC, - MAX77686_CLKS_NUM, -}; - -struct max77686_clk { - struct max77686_dev *iodev; - u32 mask; - struct clk_hw hw; - struct clk_lookup *lookup; -}; - -static struct max77686_clk *get_max77686_clk(struct clk_hw *hw) -{ - return container_of(hw, struct max77686_clk, hw); -} - -static int max77686_clk_prepare(struct clk_hw *hw) -{ - struct max77686_clk *max77686; - int ret; - - max77686 = get_max77686_clk(hw); - if (!max77686) - return -ENOMEM; - - ret = regmap_update_bits(max77686->iodev->regmap, - MAX77686_REG_32KHZ, max77686->mask, max77686->mask); - - return ret; -} - -static void max77686_clk_unprepare(struct clk_hw *hw) -{ - struct max77686_clk *max77686; - - max77686 = get_max77686_clk(hw); - if (!max77686) - return; - - regmap_update_bits(max77686->iodev->regmap, - MAX77686_REG_32KHZ, max77686->mask, ~max77686->mask); -} - -static int max77686_clk_is_enabled(struct clk_hw *hw) -{ - struct max77686_clk *max77686; - int ret; - u32 val; - - max77686 = get_max77686_clk(hw); - if (!max77686) - return -ENOMEM; - - ret = regmap_read(max77686->iodev->regmap, - MAX77686_REG_32KHZ, &val); - - if (ret < 0) - return -EINVAL; - - return val & max77686->mask; -} - -static struct clk_ops max77686_clk_ops = { - .prepare = max77686_clk_prepare, - .unprepare = max77686_clk_unprepare, - .is_enabled = max77686_clk_is_enabled, -}; - -static struct clk_init_data max77686_clks_init[MAX77686_CLKS_NUM] = { - [MAX77686_CLK_AP] = { - .name = "32khz_ap", - .ops = &max77686_clk_ops, - .flags = CLK_IS_ROOT, - }, - [MAX77686_CLK_CP] = { - .name = "32khz_cp", - .ops = &max77686_clk_ops, - .flags = CLK_IS_ROOT, - }, - [MAX77686_CLK_PMIC] = { - .name = "32khz_pmic", - .ops = &max77686_clk_ops, - .flags = CLK_IS_ROOT, - }, -}; - -static int max77686_clk_register(struct device *dev, - struct max77686_clk *max77686) -{ - struct clk *clk; - struct clk_hw *hw = &max77686->hw; - - clk = clk_register(dev, hw); - - if (IS_ERR(clk)) - return -ENOMEM; - - max77686->lookup = devm_kzalloc(dev, sizeof(struct clk_lookup), - GFP_KERNEL); - if (IS_ERR(max77686->lookup)) - return -ENOMEM; - - max77686->lookup->con_id = hw->init->name; - max77686->lookup->clk = clk; - - clkdev_add(max77686->lookup); - - return 0; -} - -static __devinit int max77686_clk_probe(struct platform_device *pdev) -{ - struct max77686_dev *iodev = dev_get_drvdata(pdev->dev.parent); - struct max77686_clk **max77686_clks; - int i, ret; - - max77686_clks = devm_kzalloc(&pdev->dev, sizeof(struct max77686_clk *) - * MAX77686_CLKS_NUM, GFP_KERNEL); - if (IS_ERR(max77686_clks)) - return -ENOMEM; - - for (i = 0; i < MAX77686_CLKS_NUM; i++) { - max77686_clks[i] = devm_kzalloc(&pdev->dev, - sizeof(struct max77686_clk), GFP_KERNEL); - if (IS_ERR(max77686_clks[i])) - return -ENOMEM; - } - - for (i = 0; i < MAX77686_CLKS_NUM; i++) { - max77686_clks[i]->iodev = iodev; - max77686_clks[i]->mask = 1 << i; - max77686_clks[i]->hw.init = &max77686_clks_init[i]; - - ret = max77686_clk_register(&pdev->dev, max77686_clks[i]); - if (ret) { - switch (i) { - case MAX77686_CLK_AP: - dev_err(&pdev->dev, "Fail to register CLK_AP\n"); - goto err_clk_ap; - break; - case MAX77686_CLK_CP: - dev_err(&pdev->dev, "Fail to register CLK_CP\n"); - goto err_clk_cp; - break; - case MAX77686_CLK_PMIC: - dev_err(&pdev->dev, "Fail to register CLK_PMIC\n"); - goto err_clk_pmic; - } - } - } - - platform_set_drvdata(pdev, max77686_clks); - - goto out; - -err_clk_pmic: - clkdev_drop(max77686_clks[MAX77686_CLK_CP]->lookup); - kfree(max77686_clks[MAX77686_CLK_CP]->hw.clk); -err_clk_cp: - clkdev_drop(max77686_clks[MAX77686_CLK_AP]->lookup); - kfree(max77686_clks[MAX77686_CLK_AP]->hw.clk); -err_clk_ap: -out: - return ret; -} - -static int __devexit max77686_clk_remove(struct platform_device *pdev) -{ - struct max77686_clk **max77686_clks = platform_get_drvdata(pdev); - int i; - - for (i = 0; i < MAX77686_CLKS_NUM; i++) { - clkdev_drop(max77686_clks[i]->lookup); - kfree(max77686_clks[i]->hw.clk); - } - return 0; -} - -static const struct platform_device_id max77686_clk_id[] = { - { "max77686-clk", 0}, - { }, -}; -MODULE_DEVICE_TABLE(platform, max77686_clk_id); - -static struct platform_driver max77686_clk_driver = { - .driver = { - .name = "max77686-clk", - .owner = THIS_MODULE, - }, - .probe = max77686_clk_probe, - .remove = __devexit_p(max77686_clk_remove), - .id_table = max77686_clk_id, -}; - -static int __init max77686_clk_init(void) -{ - return platform_driver_register(&max77686_clk_driver); -} -subsys_initcall(max77686_clk_init); - -static void __init max77686_clk_cleanup(void) -{ - platform_driver_unregister(&max77686_clk_driver); -} -module_exit(max77686_clk_cleanup); - -MODULE_DESCRIPTION("MAXIM 77686 Clock Driver"); -MODULE_AUTHOR("Jonghwa Lee "); -MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/clk/clk-prima2.c b/trunk/drivers/clk/clk-prima2.c deleted file mode 100644 index 517874fa6858..000000000000 --- a/trunk/drivers/clk/clk-prima2.c +++ /dev/null @@ -1,1171 +0,0 @@ -/* - * Clock tree for CSR SiRFprimaII - * - * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company. - * - * Licensed under GPLv2 or later. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#define SIRFSOC_CLKC_CLK_EN0 0x0000 -#define SIRFSOC_CLKC_CLK_EN1 0x0004 -#define SIRFSOC_CLKC_REF_CFG 0x0014 -#define SIRFSOC_CLKC_CPU_CFG 0x0018 -#define SIRFSOC_CLKC_MEM_CFG 0x001c -#define SIRFSOC_CLKC_SYS_CFG 0x0020 -#define SIRFSOC_CLKC_IO_CFG 0x0024 -#define SIRFSOC_CLKC_DSP_CFG 0x0028 -#define SIRFSOC_CLKC_GFX_CFG 0x002c -#define SIRFSOC_CLKC_MM_CFG 0x0030 -#define SIRFSOC_CLKC_LCD_CFG 0x0034 -#define SIRFSOC_CLKC_MMC_CFG 0x0038 -#define SIRFSOC_CLKC_PLL1_CFG0 0x0040 -#define SIRFSOC_CLKC_PLL2_CFG0 0x0044 -#define SIRFSOC_CLKC_PLL3_CFG0 0x0048 -#define SIRFSOC_CLKC_PLL1_CFG1 0x004c -#define SIRFSOC_CLKC_PLL2_CFG1 0x0050 -#define SIRFSOC_CLKC_PLL3_CFG1 0x0054 -#define SIRFSOC_CLKC_PLL1_CFG2 0x0058 -#define SIRFSOC_CLKC_PLL2_CFG2 0x005c -#define SIRFSOC_CLKC_PLL3_CFG2 0x0060 -#define SIRFSOC_USBPHY_PLL_CTRL 0x0008 -#define SIRFSOC_USBPHY_PLL_POWERDOWN BIT(1) -#define SIRFSOC_USBPHY_PLL_BYPASS BIT(2) -#define SIRFSOC_USBPHY_PLL_LOCK BIT(3) - -static void *sirfsoc_clk_vbase, *sirfsoc_rsc_vbase; - -#define KHZ 1000 -#define MHZ (KHZ * KHZ) - -/* - * SiRFprimaII clock controller - * - 2 oscillators: osc-26MHz, rtc-32.768KHz - * - 3 standard configurable plls: pll1, pll2 & pll3 - * - 2 exclusive plls: usb phy pll and sata phy pll - * - 8 clock domains: cpu/cpudiv, mem/memdiv, sys/io, dsp, graphic, multimedia, - * display and sdphy. - * Each clock domain can select its own clock source from five clock sources, - * X_XIN, X_XINW, PLL1, PLL2 and PLL3. The domain clock is used as the source - * clock of the group clock. - * - dsp domain: gps, mf - * - io domain: dmac, nand, audio, uart, i2c, spi, usp, pwm, pulse - * - sys domain: security - */ - -struct clk_pll { - struct clk_hw hw; - unsigned short regofs; /* register offset */ -}; - -#define to_pllclk(_hw) container_of(_hw, struct clk_pll, hw) - -struct clk_dmn { - struct clk_hw hw; - signed char enable_bit; /* enable bit: 0 ~ 63 */ - unsigned short regofs; /* register offset */ -}; - -#define to_dmnclk(_hw) container_of(_hw, struct clk_dmn, hw) - -struct clk_std { - struct clk_hw hw; - signed char enable_bit; /* enable bit: 0 ~ 63 */ -}; - -#define to_stdclk(_hw) container_of(_hw, struct clk_std, hw) - -static int std_clk_is_enabled(struct clk_hw *hw); -static int std_clk_enable(struct clk_hw *hw); -static void std_clk_disable(struct clk_hw *hw); - -static inline unsigned long clkc_readl(unsigned reg) -{ - return readl(sirfsoc_clk_vbase + reg); -} - -static inline void clkc_writel(u32 val, unsigned reg) -{ - writel(val, sirfsoc_clk_vbase + reg); -} - -/* - * std pll - */ - -static unsigned long pll_clk_recalc_rate(struct clk_hw *hw, - unsigned long parent_rate) -{ - unsigned long fin = parent_rate; - struct clk_pll *clk = to_pllclk(hw); - u32 regcfg2 = clk->regofs + SIRFSOC_CLKC_PLL1_CFG2 - - SIRFSOC_CLKC_PLL1_CFG0; - - if (clkc_readl(regcfg2) & BIT(2)) { - /* pll bypass mode */ - return fin; - } else { - /* fout = fin * nf / nr / od */ - u32 cfg0 = clkc_readl(clk->regofs); - u32 nf = (cfg0 & (BIT(13) - 1)) + 1; - u32 nr = ((cfg0 >> 13) & (BIT(6) - 1)) + 1; - u32 od = ((cfg0 >> 19) & (BIT(4) - 1)) + 1; - WARN_ON(fin % MHZ); - return fin / MHZ * nf / nr / od * MHZ; - } -} - -static long pll_clk_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *parent_rate) -{ - unsigned long fin, nf, nr, od; - - /* - * fout = fin * nf / (nr * od); - * set od = 1, nr = fin/MHz, so fout = nf * MHz - */ - rate = rate - rate % MHZ; - - nf = rate / MHZ; - if (nf > BIT(13)) - nf = BIT(13); - if (nf < 1) - nf = 1; - - fin = *parent_rate; - - nr = fin / MHZ; - if (nr > BIT(6)) - nr = BIT(6); - od = 1; - - return fin * nf / (nr * od); -} - -static int pll_clk_set_rate(struct clk_hw *hw, unsigned long rate, - unsigned long parent_rate) -{ - struct clk_pll *clk = to_pllclk(hw); - unsigned long fin, nf, nr, od, reg; - - /* - * fout = fin * nf / (nr * od); - * set od = 1, nr = fin/MHz, so fout = nf * MHz - */ - - nf = rate / MHZ; - if (unlikely((rate % MHZ) || nf > BIT(13) || nf < 1)) - return -EINVAL; - - fin = parent_rate; - BUG_ON(fin < MHZ); - - nr = fin / MHZ; - BUG_ON((fin % MHZ) || nr > BIT(6)); - - od = 1; - - reg = (nf - 1) | ((nr - 1) << 13) | ((od - 1) << 19); - clkc_writel(reg, clk->regofs); - - reg = clk->regofs + SIRFSOC_CLKC_PLL1_CFG1 - SIRFSOC_CLKC_PLL1_CFG0; - clkc_writel((nf >> 1) - 1, reg); - - reg = clk->regofs + SIRFSOC_CLKC_PLL1_CFG2 - SIRFSOC_CLKC_PLL1_CFG0; - while (!(clkc_readl(reg) & BIT(6))) - cpu_relax(); - - return 0; -} - -static struct clk_ops std_pll_ops = { - .recalc_rate = pll_clk_recalc_rate, - .round_rate = pll_clk_round_rate, - .set_rate = pll_clk_set_rate, -}; - -static const char *pll_clk_parents[] = { - "osc", -}; - -static struct clk_init_data clk_pll1_init = { - .name = "pll1", - .ops = &std_pll_ops, - .parent_names = pll_clk_parents, - .num_parents = ARRAY_SIZE(pll_clk_parents), -}; - -static struct clk_init_data clk_pll2_init = { - .name = "pll2", - .ops = &std_pll_ops, - .parent_names = pll_clk_parents, - .num_parents = ARRAY_SIZE(pll_clk_parents), -}; - -static struct clk_init_data clk_pll3_init = { - .name = "pll3", - .ops = &std_pll_ops, - .parent_names = pll_clk_parents, - .num_parents = ARRAY_SIZE(pll_clk_parents), -}; - -static struct clk_pll clk_pll1 = { - .regofs = SIRFSOC_CLKC_PLL1_CFG0, - .hw = { - .init = &clk_pll1_init, - }, -}; - -static struct clk_pll clk_pll2 = { - .regofs = SIRFSOC_CLKC_PLL2_CFG0, - .hw = { - .init = &clk_pll2_init, - }, -}; - -static struct clk_pll clk_pll3 = { - .regofs = SIRFSOC_CLKC_PLL3_CFG0, - .hw = { - .init = &clk_pll3_init, - }, -}; - -/* - * usb uses specified pll - */ - -static int usb_pll_clk_enable(struct clk_hw *hw) -{ - u32 reg = readl(sirfsoc_rsc_vbase + SIRFSOC_USBPHY_PLL_CTRL); - reg &= ~(SIRFSOC_USBPHY_PLL_POWERDOWN | SIRFSOC_USBPHY_PLL_BYPASS); - writel(reg, sirfsoc_rsc_vbase + SIRFSOC_USBPHY_PLL_CTRL); - while (!(readl(sirfsoc_rsc_vbase + SIRFSOC_USBPHY_PLL_CTRL) & - SIRFSOC_USBPHY_PLL_LOCK)) - cpu_relax(); - - return 0; -} - -static void usb_pll_clk_disable(struct clk_hw *clk) -{ - u32 reg = readl(sirfsoc_rsc_vbase + SIRFSOC_USBPHY_PLL_CTRL); - reg |= (SIRFSOC_USBPHY_PLL_POWERDOWN | SIRFSOC_USBPHY_PLL_BYPASS); - writel(reg, sirfsoc_rsc_vbase + SIRFSOC_USBPHY_PLL_CTRL); -} - -static unsigned long usb_pll_clk_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) -{ - u32 reg = readl(sirfsoc_rsc_vbase + SIRFSOC_USBPHY_PLL_CTRL); - return (reg & SIRFSOC_USBPHY_PLL_BYPASS) ? parent_rate : 48*MHZ; -} - -static struct clk_ops usb_pll_ops = { - .enable = usb_pll_clk_enable, - .disable = usb_pll_clk_disable, - .recalc_rate = usb_pll_clk_recalc_rate, -}; - -static struct clk_init_data clk_usb_pll_init = { - .name = "usb_pll", - .ops = &usb_pll_ops, - .parent_names = pll_clk_parents, - .num_parents = ARRAY_SIZE(pll_clk_parents), -}; - -static struct clk_hw usb_pll_clk_hw = { - .init = &clk_usb_pll_init, -}; - -/* - * clock domains - cpu, mem, sys/io, dsp, gfx - */ - -static const char *dmn_clk_parents[] = { - "rtc", - "osc", - "pll1", - "pll2", - "pll3", -}; - -static u8 dmn_clk_get_parent(struct clk_hw *hw) -{ - struct clk_dmn *clk = to_dmnclk(hw); - u32 cfg = clkc_readl(clk->regofs); - - /* parent of io domain can only be pll3 */ - if (strcmp(hw->init->name, "io") == 0) - return 4; - - WARN_ON((cfg & (BIT(3) - 1)) > 4); - - return cfg & (BIT(3) - 1); -} - -static int dmn_clk_set_parent(struct clk_hw *hw, u8 parent) -{ - struct clk_dmn *clk = to_dmnclk(hw); - u32 cfg = clkc_readl(clk->regofs); - - /* parent of io domain can only be pll3 */ - if (strcmp(hw->init->name, "io") == 0) - return -EINVAL; - - cfg &= ~(BIT(3) - 1); - clkc_writel(cfg | parent, clk->regofs); - /* BIT(3) - switching status: 1 - busy, 0 - done */ - while (clkc_readl(clk->regofs) & BIT(3)) - cpu_relax(); - - return 0; -} - -static unsigned long dmn_clk_recalc_rate(struct clk_hw *hw, - unsigned long parent_rate) - -{ - unsigned long fin = parent_rate; - struct clk_dmn *clk = to_dmnclk(hw); - - u32 cfg = clkc_readl(clk->regofs); - - if (cfg & BIT(24)) { - /* fcd bypass mode */ - return fin; - } else { - /* - * wait count: bit[19:16], hold count: bit[23:20] - */ - u32 wait = (cfg >> 16) & (BIT(4) - 1); - u32 hold = (cfg >> 20) & (BIT(4) - 1); - - return fin / (wait + hold + 2); - } -} - -static long dmn_clk_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *parent_rate) -{ - unsigned long fin; - unsigned ratio, wait, hold; - unsigned bits = (strcmp(hw->init->name, "mem") == 0) ? 3 : 4; - - fin = *parent_rate; - ratio = fin / rate; - - if (ratio < 2) - ratio = 2; - if (ratio > BIT(bits + 1)) - ratio = BIT(bits + 1); - - wait = (ratio >> 1) - 1; - hold = ratio - wait - 2; - - return fin / (wait + hold + 2); -} - -static int dmn_clk_set_rate(struct clk_hw *hw, unsigned long rate, - unsigned long parent_rate) -{ - struct clk_dmn *clk = to_dmnclk(hw); - unsigned long fin; - unsigned ratio, wait, hold, reg; - unsigned bits = (strcmp(hw->init->name, "mem") == 0) ? 3 : 4; - - fin = parent_rate; - ratio = fin / rate; - - if (unlikely(ratio < 2 || ratio > BIT(bits + 1))) - return -EINVAL; - - WARN_ON(fin % rate); - - wait = (ratio >> 1) - 1; - hold = ratio - wait - 2; - - reg = clkc_readl(clk->regofs); - reg &= ~(((BIT(bits) - 1) << 16) | ((BIT(bits) - 1) << 20)); - reg |= (wait << 16) | (hold << 20) | BIT(25); - clkc_writel(reg, clk->regofs); - - /* waiting FCD been effective */ - while (clkc_readl(clk->regofs) & BIT(25)) - cpu_relax(); - - return 0; -} - -static struct clk_ops msi_ops = { - .set_rate = dmn_clk_set_rate, - .round_rate = dmn_clk_round_rate, - .recalc_rate = dmn_clk_recalc_rate, - .set_parent = dmn_clk_set_parent, - .get_parent = dmn_clk_get_parent, -}; - -static struct clk_init_data clk_mem_init = { - .name = "mem", - .ops = &msi_ops, - .parent_names = dmn_clk_parents, - .num_parents = ARRAY_SIZE(dmn_clk_parents), -}; - -static struct clk_dmn clk_mem = { - .regofs = SIRFSOC_CLKC_MEM_CFG, - .hw = { - .init = &clk_mem_init, - }, -}; - -static struct clk_init_data clk_sys_init = { - .name = "sys", - .ops = &msi_ops, - .parent_names = dmn_clk_parents, - .num_parents = ARRAY_SIZE(dmn_clk_parents), - .flags = CLK_SET_RATE_GATE, -}; - -static struct clk_dmn clk_sys = { - .regofs = SIRFSOC_CLKC_SYS_CFG, - .hw = { - .init = &clk_sys_init, - }, -}; - -static struct clk_init_data clk_io_init = { - .name = "io", - .ops = &msi_ops, - .parent_names = dmn_clk_parents, - .num_parents = ARRAY_SIZE(dmn_clk_parents), -}; - -static struct clk_dmn clk_io = { - .regofs = SIRFSOC_CLKC_IO_CFG, - .hw = { - .init = &clk_io_init, - }, -}; - -static struct clk_ops cpu_ops = { - .set_parent = dmn_clk_set_parent, - .get_parent = dmn_clk_get_parent, -}; - -static struct clk_init_data clk_cpu_init = { - .name = "cpu", - .ops = &cpu_ops, - .parent_names = dmn_clk_parents, - .num_parents = ARRAY_SIZE(dmn_clk_parents), - .flags = CLK_SET_RATE_PARENT, -}; - -static struct clk_dmn clk_cpu = { - .regofs = SIRFSOC_CLKC_CPU_CFG, - .hw = { - .init = &clk_cpu_init, - }, -}; - -static struct clk_ops dmn_ops = { - .is_enabled = std_clk_is_enabled, - .enable = std_clk_enable, - .disable = std_clk_disable, - .set_rate = dmn_clk_set_rate, - .round_rate = dmn_clk_round_rate, - .recalc_rate = dmn_clk_recalc_rate, - .set_parent = dmn_clk_set_parent, - .get_parent = dmn_clk_get_parent, -}; - -/* dsp, gfx, mm, lcd and vpp domain */ - -static struct clk_init_data clk_dsp_init = { - .name = "dsp", - .ops = &dmn_ops, - .parent_names = dmn_clk_parents, - .num_parents = ARRAY_SIZE(dmn_clk_parents), -}; - -static struct clk_dmn clk_dsp = { - .regofs = SIRFSOC_CLKC_DSP_CFG, - .enable_bit = 0, - .hw = { - .init = &clk_dsp_init, - }, -}; - -static struct clk_init_data clk_gfx_init = { - .name = "gfx", - .ops = &dmn_ops, - .parent_names = dmn_clk_parents, - .num_parents = ARRAY_SIZE(dmn_clk_parents), -}; - -static struct clk_dmn clk_gfx = { - .regofs = SIRFSOC_CLKC_GFX_CFG, - .enable_bit = 8, - .hw = { - .init = &clk_gfx_init, - }, -}; - -static struct clk_init_data clk_mm_init = { - .name = "mm", - .ops = &dmn_ops, - .parent_names = dmn_clk_parents, - .num_parents = ARRAY_SIZE(dmn_clk_parents), -}; - -static struct clk_dmn clk_mm = { - .regofs = SIRFSOC_CLKC_MM_CFG, - .enable_bit = 9, - .hw = { - .init = &clk_mm_init, - }, -}; - -static struct clk_init_data clk_lcd_init = { - .name = "lcd", - .ops = &dmn_ops, - .parent_names = dmn_clk_parents, - .num_parents = ARRAY_SIZE(dmn_clk_parents), -}; - -static struct clk_dmn clk_lcd = { - .regofs = SIRFSOC_CLKC_LCD_CFG, - .enable_bit = 10, - .hw = { - .init = &clk_lcd_init, - }, -}; - -static struct clk_init_data clk_vpp_init = { - .name = "vpp", - .ops = &dmn_ops, - .parent_names = dmn_clk_parents, - .num_parents = ARRAY_SIZE(dmn_clk_parents), -}; - -static struct clk_dmn clk_vpp = { - .regofs = SIRFSOC_CLKC_LCD_CFG, - .enable_bit = 11, - .hw = { - .init = &clk_vpp_init, - }, -}; - -static struct clk_init_data clk_mmc01_init = { - .name = "mmc01", - .ops = &dmn_ops, - .parent_names = dmn_clk_parents, - .num_parents = ARRAY_SIZE(dmn_clk_parents), -}; - -static struct clk_dmn clk_mmc01 = { - .regofs = SIRFSOC_CLKC_MMC_CFG, - .enable_bit = 59, - .hw = { - .init = &clk_mmc01_init, - }, -}; - -static struct clk_init_data clk_mmc23_init = { - .name = "mmc23", - .ops = &dmn_ops, - .parent_names = dmn_clk_parents, - .num_parents = ARRAY_SIZE(dmn_clk_parents), -}; - -static struct clk_dmn clk_mmc23 = { - .regofs = SIRFSOC_CLKC_MMC_CFG, - .enable_bit = 60, - .hw = { - .init = &clk_mmc23_init, - }, -}; - -static struct clk_init_data clk_mmc45_init = { - .name = "mmc45", - .ops = &dmn_ops, - .parent_names = dmn_clk_parents, - .num_parents = ARRAY_SIZE(dmn_clk_parents), -}; - -static struct clk_dmn clk_mmc45 = { - .regofs = SIRFSOC_CLKC_MMC_CFG, - .enable_bit = 61, - .hw = { - .init = &clk_mmc45_init, - }, -}; - -/* - * peripheral controllers in io domain - */ - -static int std_clk_is_enabled(struct clk_hw *hw) -{ - u32 reg; - int bit; - struct clk_std *clk = to_stdclk(hw); - - bit = clk->enable_bit % 32; - reg = clk->enable_bit / 32; - reg = SIRFSOC_CLKC_CLK_EN0 + reg * sizeof(reg); - - return !!(clkc_readl(reg) & BIT(bit)); -} - -static int std_clk_enable(struct clk_hw *hw) -{ - u32 val, reg; - int bit; - struct clk_std *clk = to_stdclk(hw); - - BUG_ON(clk->enable_bit < 0 || clk->enable_bit > 63); - - bit = clk->enable_bit % 32; - reg = clk->enable_bit / 32; - reg = SIRFSOC_CLKC_CLK_EN0 + reg * sizeof(reg); - - val = clkc_readl(reg) | BIT(bit); - clkc_writel(val, reg); - return 0; -} - -static void std_clk_disable(struct clk_hw *hw) -{ - u32 val, reg; - int bit; - struct clk_std *clk = to_stdclk(hw); - - BUG_ON(clk->enable_bit < 0 || clk->enable_bit > 63); - - bit = clk->enable_bit % 32; - reg = clk->enable_bit / 32; - reg = SIRFSOC_CLKC_CLK_EN0 + reg * sizeof(reg); - - val = clkc_readl(reg) & ~BIT(bit); - clkc_writel(val, reg); -} - -static const char *std_clk_io_parents[] = { - "io", -}; - -static struct clk_ops ios_ops = { - .is_enabled = std_clk_is_enabled, - .enable = std_clk_enable, - .disable = std_clk_disable, -}; - -static struct clk_init_data clk_dmac0_init = { - .name = "dmac0", - .ops = &ios_ops, - .parent_names = std_clk_io_parents, - .num_parents = ARRAY_SIZE(std_clk_io_parents), -}; - -static struct clk_std clk_dmac0 = { - .enable_bit = 32, - .hw = { - .init = &clk_dmac0_init, - }, -}; - -static struct clk_init_data clk_dmac1_init = { - .name = "dmac1", - .ops = &ios_ops, - .parent_names = std_clk_io_parents, - .num_parents = ARRAY_SIZE(std_clk_io_parents), -}; - -static struct clk_std clk_dmac1 = { - .enable_bit = 33, - .hw = { - .init = &clk_dmac1_init, - }, -}; - -static struct clk_init_data clk_nand_init = { - .name = "nand", - .ops = &ios_ops, - .parent_names = std_clk_io_parents, - .num_parents = ARRAY_SIZE(std_clk_io_parents), -}; - -static struct clk_std clk_nand = { - .enable_bit = 34, - .hw = { - .init = &clk_nand_init, - }, -}; - -static struct clk_init_data clk_audio_init = { - .name = "audio", - .ops = &ios_ops, - .parent_names = std_clk_io_parents, - .num_parents = ARRAY_SIZE(std_clk_io_parents), -}; - -static struct clk_std clk_audio = { - .enable_bit = 35, - .hw = { - .init = &clk_audio_init, - }, -}; - -static struct clk_init_data clk_uart0_init = { - .name = "uart0", - .ops = &ios_ops, - .parent_names = std_clk_io_parents, - .num_parents = ARRAY_SIZE(std_clk_io_parents), -}; - -static struct clk_std clk_uart0 = { - .enable_bit = 36, - .hw = { - .init = &clk_uart0_init, - }, -}; - -static struct clk_init_data clk_uart1_init = { - .name = "uart1", - .ops = &ios_ops, - .parent_names = std_clk_io_parents, - .num_parents = ARRAY_SIZE(std_clk_io_parents), -}; - -static struct clk_std clk_uart1 = { - .enable_bit = 37, - .hw = { - .init = &clk_uart1_init, - }, -}; - -static struct clk_init_data clk_uart2_init = { - .name = "uart2", - .ops = &ios_ops, - .parent_names = std_clk_io_parents, - .num_parents = ARRAY_SIZE(std_clk_io_parents), -}; - -static struct clk_std clk_uart2 = { - .enable_bit = 38, - .hw = { - .init = &clk_uart2_init, - }, -}; - -static struct clk_init_data clk_usp0_init = { - .name = "usp0", - .ops = &ios_ops, - .parent_names = std_clk_io_parents, - .num_parents = ARRAY_SIZE(std_clk_io_parents), -}; - -static struct clk_std clk_usp0 = { - .enable_bit = 39, - .hw = { - .init = &clk_usp0_init, - }, -}; - -static struct clk_init_data clk_usp1_init = { - .name = "usp1", - .ops = &ios_ops, - .parent_names = std_clk_io_parents, - .num_parents = ARRAY_SIZE(std_clk_io_parents), -}; - -static struct clk_std clk_usp1 = { - .enable_bit = 40, - .hw = { - .init = &clk_usp1_init, - }, -}; - -static struct clk_init_data clk_usp2_init = { - .name = "usp2", - .ops = &ios_ops, - .parent_names = std_clk_io_parents, - .num_parents = ARRAY_SIZE(std_clk_io_parents), -}; - -static struct clk_std clk_usp2 = { - .enable_bit = 41, - .hw = { - .init = &clk_usp2_init, - }, -}; - -static struct clk_init_data clk_vip_init = { - .name = "vip", - .ops = &ios_ops, - .parent_names = std_clk_io_parents, - .num_parents = ARRAY_SIZE(std_clk_io_parents), -}; - -static struct clk_std clk_vip = { - .enable_bit = 42, - .hw = { - .init = &clk_vip_init, - }, -}; - -static struct clk_init_data clk_spi0_init = { - .name = "spi0", - .ops = &ios_ops, - .parent_names = std_clk_io_parents, - .num_parents = ARRAY_SIZE(std_clk_io_parents), -}; - -static struct clk_std clk_spi0 = { - .enable_bit = 43, - .hw = { - .init = &clk_spi0_init, - }, -}; - -static struct clk_init_data clk_spi1_init = { - .name = "spi1", - .ops = &ios_ops, - .parent_names = std_clk_io_parents, - .num_parents = ARRAY_SIZE(std_clk_io_parents), -}; - -static struct clk_std clk_spi1 = { - .enable_bit = 44, - .hw = { - .init = &clk_spi1_init, - }, -}; - -static struct clk_init_data clk_tsc_init = { - .name = "tsc", - .ops = &ios_ops, - .parent_names = std_clk_io_parents, - .num_parents = ARRAY_SIZE(std_clk_io_parents), -}; - -static struct clk_std clk_tsc = { - .enable_bit = 45, - .hw = { - .init = &clk_tsc_init, - }, -}; - -static struct clk_init_data clk_i2c0_init = { - .name = "i2c0", - .ops = &ios_ops, - .parent_names = std_clk_io_parents, - .num_parents = ARRAY_SIZE(std_clk_io_parents), -}; - -static struct clk_std clk_i2c0 = { - .enable_bit = 46, - .hw = { - .init = &clk_i2c0_init, - }, -}; - -static struct clk_init_data clk_i2c1_init = { - .name = "i2c1", - .ops = &ios_ops, - .parent_names = std_clk_io_parents, - .num_parents = ARRAY_SIZE(std_clk_io_parents), -}; - -static struct clk_std clk_i2c1 = { - .enable_bit = 47, - .hw = { - .init = &clk_i2c1_init, - }, -}; - -static struct clk_init_data clk_pwmc_init = { - .name = "pwmc", - .ops = &ios_ops, - .parent_names = std_clk_io_parents, - .num_parents = ARRAY_SIZE(std_clk_io_parents), -}; - -static struct clk_std clk_pwmc = { - .enable_bit = 48, - .hw = { - .init = &clk_pwmc_init, - }, -}; - -static struct clk_init_data clk_efuse_init = { - .name = "efuse", - .ops = &ios_ops, - .parent_names = std_clk_io_parents, - .num_parents = ARRAY_SIZE(std_clk_io_parents), -}; - -static struct clk_std clk_efuse = { - .enable_bit = 49, - .hw = { - .init = &clk_efuse_init, - }, -}; - -static struct clk_init_data clk_pulse_init = { - .name = "pulse", - .ops = &ios_ops, - .parent_names = std_clk_io_parents, - .num_parents = ARRAY_SIZE(std_clk_io_parents), -}; - -static struct clk_std clk_pulse = { - .enable_bit = 50, - .hw = { - .init = &clk_pulse_init, - }, -}; - -static const char *std_clk_dsp_parents[] = { - "dsp", -}; - -static struct clk_init_data clk_gps_init = { - .name = "gps", - .ops = &ios_ops, - .parent_names = std_clk_dsp_parents, - .num_parents = ARRAY_SIZE(std_clk_dsp_parents), -}; - -static struct clk_std clk_gps = { - .enable_bit = 1, - .hw = { - .init = &clk_gps_init, - }, -}; - -static struct clk_init_data clk_mf_init = { - .name = "mf", - .ops = &ios_ops, - .parent_names = std_clk_io_parents, - .num_parents = ARRAY_SIZE(std_clk_io_parents), -}; - -static struct clk_std clk_mf = { - .enable_bit = 2, - .hw = { - .init = &clk_mf_init, - }, -}; - -static const char *std_clk_sys_parents[] = { - "sys", -}; - -static struct clk_init_data clk_security_init = { - .name = "mf", - .ops = &ios_ops, - .parent_names = std_clk_sys_parents, - .num_parents = ARRAY_SIZE(std_clk_sys_parents), -}; - -static struct clk_std clk_security = { - .enable_bit = 19, - .hw = { - .init = &clk_security_init, - }, -}; - -static const char *std_clk_usb_parents[] = { - "usb_pll", -}; - -static struct clk_init_data clk_usb0_init = { - .name = "usb0", - .ops = &ios_ops, - .parent_names = std_clk_usb_parents, - .num_parents = ARRAY_SIZE(std_clk_usb_parents), -}; - -static struct clk_std clk_usb0 = { - .enable_bit = 16, - .hw = { - .init = &clk_usb0_init, - }, -}; - -static struct clk_init_data clk_usb1_init = { - .name = "usb1", - .ops = &ios_ops, - .parent_names = std_clk_usb_parents, - .num_parents = ARRAY_SIZE(std_clk_usb_parents), -}; - -static struct clk_std clk_usb1 = { - .enable_bit = 17, - .hw = { - .init = &clk_usb1_init, - }, -}; - -static struct of_device_id clkc_ids[] = { - { .compatible = "sirf,prima2-clkc" }, - {}, -}; - -static struct of_device_id rsc_ids[] = { - { .compatible = "sirf,prima2-rsc" }, - {}, -}; - -void __init sirfsoc_of_clk_init(void) -{ - struct clk *clk; - struct device_node *np; - - np = of_find_matching_node(NULL, clkc_ids); - if (!np) - panic("unable to find compatible clkc node in dtb\n"); - - sirfsoc_clk_vbase = of_iomap(np, 0); - if (!sirfsoc_clk_vbase) - panic("unable to map clkc registers\n"); - - of_node_put(np); - - np = of_find_matching_node(NULL, rsc_ids); - if (!np) - panic("unable to find compatible rsc node in dtb\n"); - - sirfsoc_rsc_vbase = of_iomap(np, 0); - if (!sirfsoc_rsc_vbase) - panic("unable to map rsc registers\n"); - - of_node_put(np); - - - /* These are always available (RTC and 26MHz OSC)*/ - clk = clk_register_fixed_rate(NULL, "rtc", NULL, - CLK_IS_ROOT, 32768); - BUG_ON(!clk); - clk = clk_register_fixed_rate(NULL, "osc", NULL, - CLK_IS_ROOT, 26000000); - BUG_ON(!clk); - - clk = clk_register(NULL, &clk_pll1.hw); - BUG_ON(!clk); - clk = clk_register(NULL, &clk_pll2.hw); - BUG_ON(!clk); - clk = clk_register(NULL, &clk_pll3.hw); - BUG_ON(!clk); - clk = clk_register(NULL, &clk_mem.hw); - BUG_ON(!clk); - clk = clk_register(NULL, &clk_sys.hw); - BUG_ON(!clk); - clk = clk_register(NULL, &clk_security.hw); - BUG_ON(!clk); - clk_register_clkdev(clk, NULL, "b8030000.security"); - clk = clk_register(NULL, &clk_dsp.hw); - BUG_ON(!clk); - clk = clk_register(NULL, &clk_gps.hw); - BUG_ON(!clk); - clk_register_clkdev(clk, NULL, "a8010000.gps"); - clk = clk_register(NULL, &clk_mf.hw); - BUG_ON(!clk); - clk = clk_register(NULL, &clk_io.hw); - BUG_ON(!clk); - clk_register_clkdev(clk, NULL, "io"); - clk = clk_register(NULL, &clk_cpu.hw); - BUG_ON(!clk); - clk_register_clkdev(clk, NULL, "cpu"); - clk = clk_register(NULL, &clk_uart0.hw); - BUG_ON(!clk); - clk_register_clkdev(clk, NULL, "b0050000.uart"); - clk = clk_register(NULL, &clk_uart1.hw); - BUG_ON(!clk); - clk_register_clkdev(clk, NULL, "b0060000.uart"); - clk = clk_register(NULL, &clk_uart2.hw); - BUG_ON(!clk); - clk_register_clkdev(clk, NULL, "b0070000.uart"); - clk = clk_register(NULL, &clk_tsc.hw); - BUG_ON(!clk); - clk_register_clkdev(clk, NULL, "b0110000.tsc"); - clk = clk_register(NULL, &clk_i2c0.hw); - BUG_ON(!clk); - clk_register_clkdev(clk, NULL, "b00e0000.i2c"); - clk = clk_register(NULL, &clk_i2c1.hw); - BUG_ON(!clk); - clk_register_clkdev(clk, NULL, "b00f0000.i2c"); - clk = clk_register(NULL, &clk_spi0.hw); - BUG_ON(!clk); - clk_register_clkdev(clk, NULL, "b00d0000.spi"); - clk = clk_register(NULL, &clk_spi1.hw); - BUG_ON(!clk); - clk_register_clkdev(clk, NULL, "b0170000.spi"); - clk = clk_register(NULL, &clk_pwmc.hw); - BUG_ON(!clk); - clk_register_clkdev(clk, NULL, "b0130000.pwm"); - clk = clk_register(NULL, &clk_efuse.hw); - BUG_ON(!clk); - clk_register_clkdev(clk, NULL, "b0140000.efusesys"); - clk = clk_register(NULL, &clk_pulse.hw); - BUG_ON(!clk); - clk_register_clkdev(clk, NULL, "b0150000.pulsec"); - clk = clk_register(NULL, &clk_dmac0.hw); - BUG_ON(!clk); - clk_register_clkdev(clk, NULL, "b00b0000.dma-controller"); - clk = clk_register(NULL, &clk_dmac1.hw); - BUG_ON(!clk); - clk_register_clkdev(clk, NULL, "b0160000.dma-controller"); - clk = clk_register(NULL, &clk_nand.hw); - BUG_ON(!clk); - clk_register_clkdev(clk, NULL, "b0030000.nand"); - clk = clk_register(NULL, &clk_audio.hw); - BUG_ON(!clk); - clk_register_clkdev(clk, NULL, "b0040000.audio"); - clk = clk_register(NULL, &clk_usp0.hw); - BUG_ON(!clk); - clk_register_clkdev(clk, NULL, "b0080000.usp"); - clk = clk_register(NULL, &clk_usp1.hw); - BUG_ON(!clk); - clk_register_clkdev(clk, NULL, "b0090000.usp"); - clk = clk_register(NULL, &clk_usp2.hw); - BUG_ON(!clk); - clk_register_clkdev(clk, NULL, "b00a0000.usp"); - clk = clk_register(NULL, &clk_vip.hw); - BUG_ON(!clk); - clk_register_clkdev(clk, NULL, "b00c0000.vip"); - clk = clk_register(NULL, &clk_gfx.hw); - BUG_ON(!clk); - clk_register_clkdev(clk, NULL, "98000000.graphics"); - clk = clk_register(NULL, &clk_mm.hw); - BUG_ON(!clk); - clk_register_clkdev(clk, NULL, "a0000000.multimedia"); - clk = clk_register(NULL, &clk_lcd.hw); - BUG_ON(!clk); - clk_register_clkdev(clk, NULL, "90010000.display"); - clk = clk_register(NULL, &clk_vpp.hw); - BUG_ON(!clk); - clk_register_clkdev(clk, NULL, "90020000.vpp"); - clk = clk_register(NULL, &clk_mmc01.hw); - BUG_ON(!clk); - clk = clk_register(NULL, &clk_mmc23.hw); - BUG_ON(!clk); - clk = clk_register(NULL, &clk_mmc45.hw); - BUG_ON(!clk); - clk = clk_register(NULL, &usb_pll_clk_hw); - BUG_ON(!clk); - clk = clk_register(NULL, &clk_usb0.hw); - BUG_ON(!clk); - clk_register_clkdev(clk, NULL, "b00e0000.usb"); - clk = clk_register(NULL, &clk_usb1.hw); - BUG_ON(!clk); - clk_register_clkdev(clk, NULL, "b00f0000.usb"); -} diff --git a/trunk/drivers/clk/clk.c b/trunk/drivers/clk/clk.c index 56e4495ebeb1..efdfd009c270 100644 --- a/trunk/drivers/clk/clk.c +++ b/trunk/drivers/clk/clk.c @@ -557,6 +557,25 @@ int clk_enable(struct clk *clk) } EXPORT_SYMBOL_GPL(clk_enable); +/** + * clk_get_rate - return the rate of clk + * @clk: the clk whose rate is being returned + * + * Simply returns the cached rate of the clk. Does not query the hardware. If + * clk is NULL then returns 0. + */ +unsigned long clk_get_rate(struct clk *clk) +{ + unsigned long rate; + + mutex_lock(&prepare_lock); + rate = __clk_get_rate(clk); + mutex_unlock(&prepare_lock); + + return rate; +} +EXPORT_SYMBOL_GPL(clk_get_rate); + /** * __clk_round_rate - round the given rate for a clk * @clk: round the rate of this clock @@ -682,30 +701,6 @@ static void __clk_recalc_rates(struct clk *clk, unsigned long msg) __clk_recalc_rates(child, msg); } -/** - * clk_get_rate - return the rate of clk - * @clk: the clk whose rate is being returned - * - * Simply returns the cached rate of the clk, unless CLK_GET_RATE_NOCACHE flag - * is set, which means a recalc_rate will be issued. - * If clk is NULL then returns 0. - */ -unsigned long clk_get_rate(struct clk *clk) -{ - unsigned long rate; - - mutex_lock(&prepare_lock); - - if (clk && (clk->flags & CLK_GET_RATE_NOCACHE)) - __clk_recalc_rates(clk, 0); - - rate = __clk_get_rate(clk); - mutex_unlock(&prepare_lock); - - return rate; -} -EXPORT_SYMBOL_GPL(clk_get_rate); - /** * __clk_speculate_rates * @clk: first clk in the subtree @@ -1587,20 +1582,6 @@ struct clk *of_clk_src_simple_get(struct of_phandle_args *clkspec, } EXPORT_SYMBOL_GPL(of_clk_src_simple_get); -struct clk *of_clk_src_onecell_get(struct of_phandle_args *clkspec, void *data) -{ - struct clk_onecell_data *clk_data = data; - unsigned int idx = clkspec->args[0]; - - if (idx >= clk_data->clk_num) { - pr_err("%s: invalid clock index %d\n", __func__, idx); - return ERR_PTR(-EINVAL); - } - - return clk_data->clks[idx]; -} -EXPORT_SYMBOL_GPL(of_clk_src_onecell_get); - /** * of_clk_add_provider() - Register a clock provider for a node * @np: Device node pointer associated with clock provider diff --git a/trunk/drivers/clk/clkdev.c b/trunk/drivers/clk/clkdev.c index 442a31363873..d423c9bdd71a 100644 --- a/trunk/drivers/clk/clkdev.c +++ b/trunk/drivers/clk/clkdev.c @@ -171,6 +171,51 @@ void clk_put(struct clk *clk) } EXPORT_SYMBOL(clk_put); +static void devm_clk_release(struct device *dev, void *res) +{ + clk_put(*(struct clk **)res); +} + +struct clk *devm_clk_get(struct device *dev, const char *id) +{ + struct clk **ptr, *clk; + + ptr = devres_alloc(devm_clk_release, sizeof(*ptr), GFP_KERNEL); + if (!ptr) + return ERR_PTR(-ENOMEM); + + clk = clk_get(dev, id); + if (!IS_ERR(clk)) { + *ptr = clk; + devres_add(dev, ptr); + } else { + devres_free(ptr); + } + + return clk; +} +EXPORT_SYMBOL(devm_clk_get); + +static int devm_clk_match(struct device *dev, void *res, void *data) +{ + struct clk **c = res; + if (!c || !*c) { + WARN_ON(!c || !*c); + return 0; + } + return *c == data; +} + +void devm_clk_put(struct device *dev, struct clk *clk) +{ + int ret; + + ret = devres_destroy(dev, devm_clk_release, devm_clk_match, clk); + + WARN_ON(ret); +} +EXPORT_SYMBOL(devm_clk_put); + void clkdev_add(struct clk_lookup *cl) { mutex_lock(&clocks_mutex); diff --git a/trunk/drivers/clk/mmp/Makefile b/trunk/drivers/clk/mmp/Makefile deleted file mode 100644 index 392d78044ce3..000000000000 --- a/trunk/drivers/clk/mmp/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -# -# Makefile for mmp specific clk -# - -obj-y += clk-apbc.o clk-apmu.o clk-frac.o - -obj-$(CONFIG_CPU_PXA168) += clk-pxa168.o -obj-$(CONFIG_CPU_PXA910) += clk-pxa910.o -obj-$(CONFIG_CPU_MMP2) += clk-mmp2.o diff --git a/trunk/drivers/clk/mmp/clk-apbc.c b/trunk/drivers/clk/mmp/clk-apbc.c deleted file mode 100644 index d14120eaa71f..000000000000 --- a/trunk/drivers/clk/mmp/clk-apbc.c +++ /dev/null @@ -1,152 +0,0 @@ -/* - * mmp APB clock operation source file - * - * Copyright (C) 2012 Marvell - * Chao Xie - * - * 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 "clk.h" - -/* Common APB clock register bit definitions */ -#define APBC_APBCLK (1 << 0) /* APB Bus Clock Enable */ -#define APBC_FNCLK (1 << 1) /* Functional Clock Enable */ -#define APBC_RST (1 << 2) /* Reset Generation */ -#define APBC_POWER (1 << 7) /* Reset Generation */ - -#define to_clk_apbc(hw) container_of(hw, struct clk_apbc, hw) -struct clk_apbc { - struct clk_hw hw; - void __iomem *base; - unsigned int delay; - unsigned int flags; - spinlock_t *lock; -}; - -static int clk_apbc_prepare(struct clk_hw *hw) -{ - struct clk_apbc *apbc = to_clk_apbc(hw); - unsigned int data; - unsigned long flags = 0; - - /* - * It may share same register as MUX clock, - * and it will impact FNCLK enable. Spinlock is needed - */ - if (apbc->lock) - spin_lock_irqsave(apbc->lock, flags); - - data = readl_relaxed(apbc->base); - if (apbc->flags & APBC_POWER_CTRL) - data |= APBC_POWER; - data |= APBC_FNCLK; - writel_relaxed(data, apbc->base); - - if (apbc->lock) - spin_unlock_irqrestore(apbc->lock, flags); - - udelay(apbc->delay); - - if (apbc->lock) - spin_lock_irqsave(apbc->lock, flags); - - data = readl_relaxed(apbc->base); - data |= APBC_APBCLK; - writel_relaxed(data, apbc->base); - - if (apbc->lock) - spin_unlock_irqrestore(apbc->lock, flags); - - udelay(apbc->delay); - - if (!(apbc->flags & APBC_NO_BUS_CTRL)) { - if (apbc->lock) - spin_lock_irqsave(apbc->lock, flags); - - data = readl_relaxed(apbc->base); - data &= ~APBC_RST; - writel_relaxed(data, apbc->base); - - if (apbc->lock) - spin_unlock_irqrestore(apbc->lock, flags); - } - - return 0; -} - -static void clk_apbc_unprepare(struct clk_hw *hw) -{ - struct clk_apbc *apbc = to_clk_apbc(hw); - unsigned long data; - unsigned long flags = 0; - - if (apbc->lock) - spin_lock_irqsave(apbc->lock, flags); - - data = readl_relaxed(apbc->base); - if (apbc->flags & APBC_POWER_CTRL) - data &= ~APBC_POWER; - data &= ~APBC_FNCLK; - writel_relaxed(data, apbc->base); - - if (apbc->lock) - spin_unlock_irqrestore(apbc->lock, flags); - - udelay(10); - - if (apbc->lock) - spin_lock_irqsave(apbc->lock, flags); - - data = readl_relaxed(apbc->base); - data &= ~APBC_APBCLK; - writel_relaxed(data, apbc->base); - - if (apbc->lock) - spin_unlock_irqrestore(apbc->lock, flags); -} - -struct clk_ops clk_apbc_ops = { - .prepare = clk_apbc_prepare, - .unprepare = clk_apbc_unprepare, -}; - -struct clk *mmp_clk_register_apbc(const char *name, const char *parent_name, - void __iomem *base, unsigned int delay, - unsigned int apbc_flags, spinlock_t *lock) -{ - struct clk_apbc *apbc; - struct clk *clk; - struct clk_init_data init; - - apbc = kzalloc(sizeof(*apbc), GFP_KERNEL); - if (!apbc) - return NULL; - - init.name = name; - init.ops = &clk_apbc_ops; - init.flags = CLK_SET_RATE_PARENT; - init.parent_names = (parent_name ? &parent_name : NULL); - init.num_parents = (parent_name ? 1 : 0); - - apbc->base = base; - apbc->delay = delay; - apbc->flags = apbc_flags; - apbc->lock = lock; - apbc->hw.init = &init; - - clk = clk_register(NULL, &apbc->hw); - if (IS_ERR(clk)) - kfree(apbc); - - return clk; -} diff --git a/trunk/drivers/clk/mmp/clk-apmu.c b/trunk/drivers/clk/mmp/clk-apmu.c deleted file mode 100644 index abe182b2377f..000000000000 --- a/trunk/drivers/clk/mmp/clk-apmu.c +++ /dev/null @@ -1,97 +0,0 @@ -/* - * mmp AXI peripharal clock operation source file - * - * Copyright (C) 2012 Marvell - * Chao Xie - * - * 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 "clk.h" - -#define to_clk_apmu(clk) (container_of(clk, struct clk_apmu, clk)) -struct clk_apmu { - struct clk_hw hw; - void __iomem *base; - u32 rst_mask; - u32 enable_mask; - spinlock_t *lock; -}; - -static int clk_apmu_enable(struct clk_hw *hw) -{ - struct clk_apmu *apmu = to_clk_apmu(hw); - unsigned long data; - unsigned long flags = 0; - - if (apmu->lock) - spin_lock_irqsave(apmu->lock, flags); - - data = readl_relaxed(apmu->base) | apmu->enable_mask; - writel_relaxed(data, apmu->base); - - if (apmu->lock) - spin_unlock_irqrestore(apmu->lock, flags); - - return 0; -} - -static void clk_apmu_disable(struct clk_hw *hw) -{ - struct clk_apmu *apmu = to_clk_apmu(hw); - unsigned long data; - unsigned long flags = 0; - - if (apmu->lock) - spin_lock_irqsave(apmu->lock, flags); - - data = readl_relaxed(apmu->base) & ~apmu->enable_mask; - writel_relaxed(data, apmu->base); - - if (apmu->lock) - spin_unlock_irqrestore(apmu->lock, flags); -} - -struct clk_ops clk_apmu_ops = { - .enable = clk_apmu_enable, - .disable = clk_apmu_disable, -}; - -struct clk *mmp_clk_register_apmu(const char *name, const char *parent_name, - void __iomem *base, u32 enable_mask, spinlock_t *lock) -{ - struct clk_apmu *apmu; - struct clk *clk; - struct clk_init_data init; - - apmu = kzalloc(sizeof(*apmu), GFP_KERNEL); - if (!apmu) - return NULL; - - init.name = name; - init.ops = &clk_apmu_ops; - init.flags = CLK_SET_RATE_PARENT; - init.parent_names = (parent_name ? &parent_name : NULL); - init.num_parents = (parent_name ? 1 : 0); - - apmu->base = base; - apmu->enable_mask = enable_mask; - apmu->lock = lock; - apmu->hw.init = &init; - - clk = clk_register(NULL, &apmu->hw); - - if (IS_ERR(clk)) - kfree(apmu); - - return clk; -} diff --git a/trunk/drivers/clk/mmp/clk-frac.c b/trunk/drivers/clk/mmp/clk-frac.c deleted file mode 100644 index 80c1dd15d15c..000000000000 --- a/trunk/drivers/clk/mmp/clk-frac.c +++ /dev/null @@ -1,153 +0,0 @@ -/* - * mmp factor clock operation source file - * - * Copyright (C) 2012 Marvell - * Chao Xie - * - * 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 "clk.h" -/* - * It is M/N clock - * - * Fout from synthesizer can be given from two equations: - * numerator/denominator = Fin / (Fout * factor) - */ - -#define to_clk_factor(hw) container_of(hw, struct clk_factor, hw) -struct clk_factor { - struct clk_hw hw; - void __iomem *base; - struct clk_factor_masks *masks; - struct clk_factor_tbl *ftbl; - unsigned int ftbl_cnt; -}; - -static long clk_factor_round_rate(struct clk_hw *hw, unsigned long drate, - unsigned long *prate) -{ - struct clk_factor *factor = to_clk_factor(hw); - unsigned long rate = 0, prev_rate; - int i; - - for (i = 0; i < factor->ftbl_cnt; i++) { - prev_rate = rate; - rate = (((*prate / 10000) * factor->ftbl[i].num) / - (factor->ftbl[i].den * factor->masks->factor)) * 10000; - if (rate > drate) - break; - } - if (i == 0) - return rate; - else - return prev_rate; -} - -static unsigned long clk_factor_recalc_rate(struct clk_hw *hw, - unsigned long parent_rate) -{ - struct clk_factor *factor = to_clk_factor(hw); - struct clk_factor_masks *masks = factor->masks; - unsigned int val, num, den; - - val = readl_relaxed(factor->base); - - /* calculate numerator */ - num = (val >> masks->num_shift) & masks->num_mask; - - /* calculate denominator */ - den = (val >> masks->den_shift) & masks->num_mask; - - if (!den) - return 0; - - return (((parent_rate / 10000) * den) / - (num * factor->masks->factor)) * 10000; -} - -/* Configures new clock rate*/ -static int clk_factor_set_rate(struct clk_hw *hw, unsigned long drate, - unsigned long prate) -{ - struct clk_factor *factor = to_clk_factor(hw); - struct clk_factor_masks *masks = factor->masks; - int i; - unsigned long val; - unsigned long prev_rate, rate = 0; - - for (i = 0; i < factor->ftbl_cnt; i++) { - prev_rate = rate; - rate = (((prate / 10000) * factor->ftbl[i].num) / - (factor->ftbl[i].den * factor->masks->factor)) * 10000; - if (rate > drate) - break; - } - if (i > 0) - i--; - - val = readl_relaxed(factor->base); - - val &= ~(masks->num_mask << masks->num_shift); - val |= (factor->ftbl[i].num & masks->num_mask) << masks->num_shift; - - val &= ~(masks->den_mask << masks->den_shift); - val |= (factor->ftbl[i].den & masks->den_mask) << masks->den_shift; - - writel_relaxed(val, factor->base); - - return 0; -} - -static struct clk_ops clk_factor_ops = { - .recalc_rate = clk_factor_recalc_rate, - .round_rate = clk_factor_round_rate, - .set_rate = clk_factor_set_rate, -}; - -struct clk *mmp_clk_register_factor(const char *name, const char *parent_name, - unsigned long flags, void __iomem *base, - struct clk_factor_masks *masks, struct clk_factor_tbl *ftbl, - unsigned int ftbl_cnt) -{ - struct clk_factor *factor; - struct clk_init_data init; - struct clk *clk; - - if (!masks) { - pr_err("%s: must pass a clk_factor_mask\n", __func__); - return ERR_PTR(-EINVAL); - } - - factor = kzalloc(sizeof(*factor), GFP_KERNEL); - if (!factor) { - pr_err("%s: could not allocate factor clk\n", __func__); - return ERR_PTR(-ENOMEM); - } - - /* struct clk_aux assignments */ - factor->base = base; - factor->masks = masks; - factor->ftbl = ftbl; - factor->ftbl_cnt = ftbl_cnt; - factor->hw.init = &init; - - init.name = name; - init.ops = &clk_factor_ops; - init.flags = flags; - init.parent_names = &parent_name; - init.num_parents = 1; - - clk = clk_register(NULL, &factor->hw); - if (IS_ERR_OR_NULL(clk)) - kfree(factor); - - return clk; -} diff --git a/trunk/drivers/clk/mmp/clk-mmp2.c b/trunk/drivers/clk/mmp/clk-mmp2.c deleted file mode 100644 index ade435820c7e..000000000000 --- a/trunk/drivers/clk/mmp/clk-mmp2.c +++ /dev/null @@ -1,449 +0,0 @@ -/* - * mmp2 clock framework source file - * - * Copyright (C) 2012 Marvell - * Chao Xie - * - * 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 "clk.h" - -#define APBC_RTC 0x0 -#define APBC_TWSI0 0x4 -#define APBC_TWSI1 0x8 -#define APBC_TWSI2 0xc -#define APBC_TWSI3 0x10 -#define APBC_TWSI4 0x7c -#define APBC_TWSI5 0x80 -#define APBC_KPC 0x18 -#define APBC_UART0 0x2c -#define APBC_UART1 0x30 -#define APBC_UART2 0x34 -#define APBC_UART3 0x88 -#define APBC_GPIO 0x38 -#define APBC_PWM0 0x3c -#define APBC_PWM1 0x40 -#define APBC_PWM2 0x44 -#define APBC_PWM3 0x48 -#define APBC_SSP0 0x50 -#define APBC_SSP1 0x54 -#define APBC_SSP2 0x58 -#define APBC_SSP3 0x5c -#define APMU_SDH0 0x54 -#define APMU_SDH1 0x58 -#define APMU_SDH2 0xe8 -#define APMU_SDH3 0xec -#define APMU_USB 0x5c -#define APMU_DISP0 0x4c -#define APMU_DISP1 0x110 -#define APMU_CCIC0 0x50 -#define APMU_CCIC1 0xf4 -#define MPMU_UART_PLL 0x14 - -static DEFINE_SPINLOCK(clk_lock); - -static struct clk_factor_masks uart_factor_masks = { - .factor = 2, - .num_mask = 0x1fff, - .den_mask = 0x1fff, - .num_shift = 16, - .den_shift = 0, -}; - -static struct clk_factor_tbl uart_factor_tbl[] = { - {.num = 14634, .den = 2165}, /*14.745MHZ */ - {.num = 3521, .den = 689}, /*19.23MHZ */ - {.num = 9679, .den = 5728}, /*58.9824MHZ */ - {.num = 15850, .den = 9451}, /*59.429MHZ */ -}; - -static const char *uart_parent[] = {"uart_pll", "vctcxo"}; -static const char *ssp_parent[] = {"vctcxo_4", "vctcxo_2", "vctcxo", "pll1_16"}; -static const char *sdh_parent[] = {"pll1_4", "pll2", "usb_pll", "pll1"}; -static const char *disp_parent[] = {"pll1", "pll1_16", "pll2", "vctcxo"}; -static const char *ccic_parent[] = {"pll1_2", "pll1_16", "vctcxo"}; - -void __init mmp2_clk_init(void) -{ - struct clk *clk; - struct clk *vctcxo; - void __iomem *mpmu_base; - void __iomem *apmu_base; - void __iomem *apbc_base; - - mpmu_base = ioremap(APB_PHYS_BASE + 0x50000, SZ_4K); - if (mpmu_base == NULL) { - pr_err("error to ioremap MPMU base\n"); - return; - } - - apmu_base = ioremap(AXI_PHYS_BASE + 0x82800, SZ_4K); - if (apmu_base == NULL) { - pr_err("error to ioremap APMU base\n"); - return; - } - - apbc_base = ioremap(APB_PHYS_BASE + 0x15000, SZ_4K); - if (apbc_base == NULL) { - pr_err("error to ioremap APBC base\n"); - return; - } - - clk = clk_register_fixed_rate(NULL, "clk32", NULL, CLK_IS_ROOT, 3200); - clk_register_clkdev(clk, "clk32", NULL); - - vctcxo = clk_register_fixed_rate(NULL, "vctcxo", NULL, CLK_IS_ROOT, - 26000000); - clk_register_clkdev(vctcxo, "vctcxo", NULL); - - clk = clk_register_fixed_rate(NULL, "pll1", NULL, CLK_IS_ROOT, - 800000000); - clk_register_clkdev(clk, "pll1", NULL); - - clk = clk_register_fixed_rate(NULL, "usb_pll", NULL, CLK_IS_ROOT, - 480000000); - clk_register_clkdev(clk, "usb_pll", NULL); - - clk = clk_register_fixed_rate(NULL, "pll2", NULL, CLK_IS_ROOT, - 960000000); - clk_register_clkdev(clk, "pll2", NULL); - - clk = clk_register_fixed_factor(NULL, "pll1_2", "pll1", - CLK_SET_RATE_PARENT, 1, 2); - clk_register_clkdev(clk, "pll1_2", NULL); - - clk = clk_register_fixed_factor(NULL, "pll1_4", "pll1_2", - CLK_SET_RATE_PARENT, 1, 2); - clk_register_clkdev(clk, "pll1_4", NULL); - - clk = clk_register_fixed_factor(NULL, "pll1_8", "pll1_4", - CLK_SET_RATE_PARENT, 1, 2); - clk_register_clkdev(clk, "pll1_8", NULL); - - clk = clk_register_fixed_factor(NULL, "pll1_16", "pll1_8", - CLK_SET_RATE_PARENT, 1, 2); - clk_register_clkdev(clk, "pll1_16", NULL); - - clk = clk_register_fixed_factor(NULL, "pll1_20", "pll1_4", - CLK_SET_RATE_PARENT, 1, 5); - clk_register_clkdev(clk, "pll1_20", NULL); - - clk = clk_register_fixed_factor(NULL, "pll1_3", "pll1", - CLK_SET_RATE_PARENT, 1, 3); - clk_register_clkdev(clk, "pll1_3", NULL); - - clk = clk_register_fixed_factor(NULL, "pll1_6", "pll1_3", - CLK_SET_RATE_PARENT, 1, 2); - clk_register_clkdev(clk, "pll1_6", NULL); - - clk = clk_register_fixed_factor(NULL, "pll1_12", "pll1_6", - CLK_SET_RATE_PARENT, 1, 2); - clk_register_clkdev(clk, "pll1_12", NULL); - - clk = clk_register_fixed_factor(NULL, "pll2_2", "pll2", - CLK_SET_RATE_PARENT, 1, 2); - clk_register_clkdev(clk, "pll2_2", NULL); - - clk = clk_register_fixed_factor(NULL, "pll2_4", "pll2_2", - CLK_SET_RATE_PARENT, 1, 2); - clk_register_clkdev(clk, "pll2_4", NULL); - - clk = clk_register_fixed_factor(NULL, "pll2_8", "pll2_4", - CLK_SET_RATE_PARENT, 1, 2); - clk_register_clkdev(clk, "pll2_8", NULL); - - clk = clk_register_fixed_factor(NULL, "pll2_16", "pll2_8", - CLK_SET_RATE_PARENT, 1, 2); - clk_register_clkdev(clk, "pll2_16", NULL); - - clk = clk_register_fixed_factor(NULL, "pll2_3", "pll2", - CLK_SET_RATE_PARENT, 1, 3); - clk_register_clkdev(clk, "pll2_3", NULL); - - clk = clk_register_fixed_factor(NULL, "pll2_6", "pll2_3", - CLK_SET_RATE_PARENT, 1, 2); - clk_register_clkdev(clk, "pll2_6", NULL); - - clk = clk_register_fixed_factor(NULL, "pll2_12", "pll2_6", - CLK_SET_RATE_PARENT, 1, 2); - clk_register_clkdev(clk, "pll2_12", NULL); - - clk = clk_register_fixed_factor(NULL, "vctcxo_2", "vctcxo", - CLK_SET_RATE_PARENT, 1, 2); - clk_register_clkdev(clk, "vctcxo_2", NULL); - - clk = clk_register_fixed_factor(NULL, "vctcxo_4", "vctcxo_2", - CLK_SET_RATE_PARENT, 1, 2); - clk_register_clkdev(clk, "vctcxo_4", NULL); - - clk = mmp_clk_register_factor("uart_pll", "pll1_4", 0, - mpmu_base + MPMU_UART_PLL, - &uart_factor_masks, uart_factor_tbl, - ARRAY_SIZE(uart_factor_tbl)); - clk_set_rate(clk, 14745600); - clk_register_clkdev(clk, "uart_pll", NULL); - - clk = mmp_clk_register_apbc("twsi0", "vctcxo", - apbc_base + APBC_TWSI0, 10, 0, &clk_lock); - clk_register_clkdev(clk, NULL, "pxa2xx-i2c.0"); - - clk = mmp_clk_register_apbc("twsi1", "vctcxo", - apbc_base + APBC_TWSI1, 10, 0, &clk_lock); - clk_register_clkdev(clk, NULL, "pxa2xx-i2c.1"); - - clk = mmp_clk_register_apbc("twsi2", "vctcxo", - apbc_base + APBC_TWSI2, 10, 0, &clk_lock); - clk_register_clkdev(clk, NULL, "pxa2xx-i2c.2"); - - clk = mmp_clk_register_apbc("twsi3", "vctcxo", - apbc_base + APBC_TWSI3, 10, 0, &clk_lock); - clk_register_clkdev(clk, NULL, "pxa2xx-i2c.3"); - - clk = mmp_clk_register_apbc("twsi4", "vctcxo", - apbc_base + APBC_TWSI4, 10, 0, &clk_lock); - clk_register_clkdev(clk, NULL, "pxa2xx-i2c.4"); - - clk = mmp_clk_register_apbc("twsi5", "vctcxo", - apbc_base + APBC_TWSI5, 10, 0, &clk_lock); - clk_register_clkdev(clk, NULL, "pxa2xx-i2c.5"); - - clk = mmp_clk_register_apbc("gpio", "vctcxo", - apbc_base + APBC_GPIO, 10, 0, &clk_lock); - clk_register_clkdev(clk, NULL, "pxa-gpio"); - - clk = mmp_clk_register_apbc("kpc", "clk32", - apbc_base + APBC_KPC, 10, 0, &clk_lock); - clk_register_clkdev(clk, NULL, "pxa27x-keypad"); - - clk = mmp_clk_register_apbc("rtc", "clk32", - apbc_base + APBC_RTC, 10, 0, &clk_lock); - clk_register_clkdev(clk, NULL, "mmp-rtc"); - - clk = mmp_clk_register_apbc("pwm0", "vctcxo", - apbc_base + APBC_PWM0, 10, 0, &clk_lock); - clk_register_clkdev(clk, NULL, "mmp2-pwm.0"); - - clk = mmp_clk_register_apbc("pwm1", "vctcxo", - apbc_base + APBC_PWM1, 10, 0, &clk_lock); - clk_register_clkdev(clk, NULL, "mmp2-pwm.1"); - - clk = mmp_clk_register_apbc("pwm2", "vctcxo", - apbc_base + APBC_PWM2, 10, 0, &clk_lock); - clk_register_clkdev(clk, NULL, "mmp2-pwm.2"); - - clk = mmp_clk_register_apbc("pwm3", "vctcxo", - apbc_base + APBC_PWM3, 10, 0, &clk_lock); - clk_register_clkdev(clk, NULL, "mmp2-pwm.3"); - - clk = clk_register_mux(NULL, "uart0_mux", uart_parent, - ARRAY_SIZE(uart_parent), CLK_SET_RATE_PARENT, - apbc_base + APBC_UART0, 4, 3, 0, &clk_lock); - clk_set_parent(clk, vctcxo); - clk_register_clkdev(clk, "uart_mux.0", NULL); - - clk = mmp_clk_register_apbc("uart0", "uart0_mux", - apbc_base + APBC_UART0, 10, 0, &clk_lock); - clk_register_clkdev(clk, NULL, "pxa2xx-uart.0"); - - clk = clk_register_mux(NULL, "uart1_mux", uart_parent, - ARRAY_SIZE(uart_parent), CLK_SET_RATE_PARENT, - apbc_base + APBC_UART1, 4, 3, 0, &clk_lock); - clk_set_parent(clk, vctcxo); - clk_register_clkdev(clk, "uart_mux.1", NULL); - - clk = mmp_clk_register_apbc("uart1", "uart1_mux", - apbc_base + APBC_UART1, 10, 0, &clk_lock); - clk_register_clkdev(clk, NULL, "pxa2xx-uart.1"); - - clk = clk_register_mux(NULL, "uart2_mux", uart_parent, - ARRAY_SIZE(uart_parent), CLK_SET_RATE_PARENT, - apbc_base + APBC_UART2, 4, 3, 0, &clk_lock); - clk_set_parent(clk, vctcxo); - clk_register_clkdev(clk, "uart_mux.2", NULL); - - clk = mmp_clk_register_apbc("uart2", "uart2_mux", - apbc_base + APBC_UART2, 10, 0, &clk_lock); - clk_register_clkdev(clk, NULL, "pxa2xx-uart.2"); - - clk = clk_register_mux(NULL, "uart3_mux", uart_parent, - ARRAY_SIZE(uart_parent), CLK_SET_RATE_PARENT, - apbc_base + APBC_UART3, 4, 3, 0, &clk_lock); - clk_set_parent(clk, vctcxo); - clk_register_clkdev(clk, "uart_mux.3", NULL); - - clk = mmp_clk_register_apbc("uart3", "uart3_mux", - apbc_base + APBC_UART3, 10, 0, &clk_lock); - clk_register_clkdev(clk, NULL, "pxa2xx-uart.3"); - - clk = clk_register_mux(NULL, "ssp0_mux", ssp_parent, - ARRAY_SIZE(ssp_parent), CLK_SET_RATE_PARENT, - apbc_base + APBC_SSP0, 4, 3, 0, &clk_lock); - clk_register_clkdev(clk, "uart_mux.0", NULL); - - clk = mmp_clk_register_apbc("ssp0", "ssp0_mux", - apbc_base + APBC_SSP0, 10, 0, &clk_lock); - clk_register_clkdev(clk, NULL, "mmp-ssp.0"); - - clk = clk_register_mux(NULL, "ssp1_mux", ssp_parent, - ARRAY_SIZE(ssp_parent), CLK_SET_RATE_PARENT, - apbc_base + APBC_SSP1, 4, 3, 0, &clk_lock); - clk_register_clkdev(clk, "ssp_mux.1", NULL); - - clk = mmp_clk_register_apbc("ssp1", "ssp1_mux", - apbc_base + APBC_SSP1, 10, 0, &clk_lock); - clk_register_clkdev(clk, NULL, "mmp-ssp.1"); - - clk = clk_register_mux(NULL, "ssp2_mux", ssp_parent, - ARRAY_SIZE(ssp_parent), CLK_SET_RATE_PARENT, - apbc_base + APBC_SSP2, 4, 3, 0, &clk_lock); - clk_register_clkdev(clk, "ssp_mux.2", NULL); - - clk = mmp_clk_register_apbc("ssp2", "ssp2_mux", - apbc_base + APBC_SSP2, 10, 0, &clk_lock); - clk_register_clkdev(clk, NULL, "mmp-ssp.2"); - - clk = clk_register_mux(NULL, "ssp3_mux", ssp_parent, - ARRAY_SIZE(ssp_parent), CLK_SET_RATE_PARENT, - apbc_base + APBC_SSP3, 4, 3, 0, &clk_lock); - clk_register_clkdev(clk, "ssp_mux.3", NULL); - - clk = mmp_clk_register_apbc("ssp3", "ssp3_mux", - apbc_base + APBC_SSP3, 10, 0, &clk_lock); - clk_register_clkdev(clk, NULL, "mmp-ssp.3"); - - clk = clk_register_mux(NULL, "sdh_mux", sdh_parent, - ARRAY_SIZE(sdh_parent), CLK_SET_RATE_PARENT, - apmu_base + APMU_SDH0, 8, 2, 0, &clk_lock); - clk_register_clkdev(clk, "sdh_mux", NULL); - - clk = clk_register_divider(NULL, "sdh_div", "sdh_mux", - CLK_SET_RATE_PARENT, apmu_base + APMU_SDH0, - 10, 4, CLK_DIVIDER_ONE_BASED, &clk_lock); - clk_register_clkdev(clk, "sdh_div", NULL); - - clk = mmp_clk_register_apmu("sdh0", "sdh_div", apmu_base + APMU_SDH0, - 0x1b, &clk_lock); - clk_register_clkdev(clk, NULL, "sdhci-pxav3.0"); - - clk = mmp_clk_register_apmu("sdh1", "sdh_div", apmu_base + APMU_SDH1, - 0x1b, &clk_lock); - clk_register_clkdev(clk, NULL, "sdhci-pxav3.1"); - - clk = mmp_clk_register_apmu("sdh2", "sdh_div", apmu_base + APMU_SDH2, - 0x1b, &clk_lock); - clk_register_clkdev(clk, NULL, "sdhci-pxav3.2"); - - clk = mmp_clk_register_apmu("sdh3", "sdh_div", apmu_base + APMU_SDH3, - 0x1b, &clk_lock); - clk_register_clkdev(clk, NULL, "sdhci-pxav3.3"); - - clk = mmp_clk_register_apmu("usb", "usb_pll", apmu_base + APMU_USB, - 0x9, &clk_lock); - clk_register_clkdev(clk, "usb_clk", NULL); - - clk = clk_register_mux(NULL, "disp0_mux", disp_parent, - ARRAY_SIZE(disp_parent), CLK_SET_RATE_PARENT, - apmu_base + APMU_DISP0, 6, 2, 0, &clk_lock); - clk_register_clkdev(clk, "disp_mux.0", NULL); - - clk = clk_register_divider(NULL, "disp0_div", "disp0_mux", - CLK_SET_RATE_PARENT, apmu_base + APMU_DISP0, - 8, 4, CLK_DIVIDER_ONE_BASED, &clk_lock); - clk_register_clkdev(clk, "disp_div.0", NULL); - - clk = mmp_clk_register_apmu("disp0", "disp0_div", - apmu_base + APMU_DISP0, 0x1b, &clk_lock); - clk_register_clkdev(clk, NULL, "mmp-disp.0"); - - clk = clk_register_divider(NULL, "disp0_sphy_div", "disp0_mux", 0, - apmu_base + APMU_DISP0, 15, 5, 0, &clk_lock); - clk_register_clkdev(clk, "disp_sphy_div.0", NULL); - - clk = mmp_clk_register_apmu("disp0_sphy", "disp0_sphy_div", - apmu_base + APMU_DISP0, 0x1024, &clk_lock); - clk_register_clkdev(clk, "disp_sphy.0", NULL); - - clk = clk_register_mux(NULL, "disp1_mux", disp_parent, - ARRAY_SIZE(disp_parent), CLK_SET_RATE_PARENT, - apmu_base + APMU_DISP1, 6, 2, 0, &clk_lock); - clk_register_clkdev(clk, "disp_mux.1", NULL); - - clk = clk_register_divider(NULL, "disp1_div", "disp1_mux", - CLK_SET_RATE_PARENT, apmu_base + APMU_DISP1, - 8, 4, CLK_DIVIDER_ONE_BASED, &clk_lock); - clk_register_clkdev(clk, "disp_div.1", NULL); - - clk = mmp_clk_register_apmu("disp1", "disp1_div", - apmu_base + APMU_DISP1, 0x1b, &clk_lock); - clk_register_clkdev(clk, NULL, "mmp-disp.1"); - - clk = mmp_clk_register_apmu("ccic_arbiter", "vctcxo", - apmu_base + APMU_CCIC0, 0x1800, &clk_lock); - clk_register_clkdev(clk, "ccic_arbiter", NULL); - - clk = clk_register_mux(NULL, "ccic0_mux", ccic_parent, - ARRAY_SIZE(ccic_parent), CLK_SET_RATE_PARENT, - apmu_base + APMU_CCIC0, 6, 2, 0, &clk_lock); - clk_register_clkdev(clk, "ccic_mux.0", NULL); - - clk = clk_register_divider(NULL, "ccic0_div", "ccic0_mux", - CLK_SET_RATE_PARENT, apmu_base + APMU_CCIC0, - 17, 4, CLK_DIVIDER_ONE_BASED, &clk_lock); - clk_register_clkdev(clk, "ccic_div.0", NULL); - - clk = mmp_clk_register_apmu("ccic0", "ccic0_div", - apmu_base + APMU_CCIC0, 0x1b, &clk_lock); - clk_register_clkdev(clk, "fnclk", "mmp-ccic.0"); - - clk = mmp_clk_register_apmu("ccic0_phy", "ccic0_div", - apmu_base + APMU_CCIC0, 0x24, &clk_lock); - clk_register_clkdev(clk, "phyclk", "mmp-ccic.0"); - - clk = clk_register_divider(NULL, "ccic0_sphy_div", "ccic0_div", - CLK_SET_RATE_PARENT, apmu_base + APMU_CCIC0, - 10, 5, 0, &clk_lock); - clk_register_clkdev(clk, "sphyclk_div", "mmp-ccic.0"); - - clk = mmp_clk_register_apmu("ccic0_sphy", "ccic0_sphy_div", - apmu_base + APMU_CCIC0, 0x300, &clk_lock); - clk_register_clkdev(clk, "sphyclk", "mmp-ccic.0"); - - clk = clk_register_mux(NULL, "ccic1_mux", ccic_parent, - ARRAY_SIZE(ccic_parent), CLK_SET_RATE_PARENT, - apmu_base + APMU_CCIC1, 6, 2, 0, &clk_lock); - clk_register_clkdev(clk, "ccic_mux.1", NULL); - - clk = clk_register_divider(NULL, "ccic1_div", "ccic1_mux", - CLK_SET_RATE_PARENT, apmu_base + APMU_CCIC1, - 16, 4, CLK_DIVIDER_ONE_BASED, &clk_lock); - clk_register_clkdev(clk, "ccic_div.1", NULL); - - clk = mmp_clk_register_apmu("ccic1", "ccic1_div", - apmu_base + APMU_CCIC1, 0x1b, &clk_lock); - clk_register_clkdev(clk, "fnclk", "mmp-ccic.1"); - - clk = mmp_clk_register_apmu("ccic1_phy", "ccic1_div", - apmu_base + APMU_CCIC1, 0x24, &clk_lock); - clk_register_clkdev(clk, "phyclk", "mmp-ccic.1"); - - clk = clk_register_divider(NULL, "ccic1_sphy_div", "ccic1_div", - CLK_SET_RATE_PARENT, apmu_base + APMU_CCIC1, - 10, 5, 0, &clk_lock); - clk_register_clkdev(clk, "sphyclk_div", "mmp-ccic.1"); - - clk = mmp_clk_register_apmu("ccic1_sphy", "ccic1_sphy_div", - apmu_base + APMU_CCIC1, 0x300, &clk_lock); - clk_register_clkdev(clk, "sphyclk", "mmp-ccic.1"); -} diff --git a/trunk/drivers/clk/mmp/clk-pxa168.c b/trunk/drivers/clk/mmp/clk-pxa168.c deleted file mode 100644 index e8d036c12cbf..000000000000 --- a/trunk/drivers/clk/mmp/clk-pxa168.c +++ /dev/null @@ -1,346 +0,0 @@ -/* - * pxa168 clock framework source file - * - * Copyright (C) 2012 Marvell - * Chao Xie - * - * 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 "clk.h" - -#define APBC_RTC 0x28 -#define APBC_TWSI0 0x2c -#define APBC_KPC 0x30 -#define APBC_UART0 0x0 -#define APBC_UART1 0x4 -#define APBC_GPIO 0x8 -#define APBC_PWM0 0xc -#define APBC_PWM1 0x10 -#define APBC_PWM2 0x14 -#define APBC_PWM3 0x18 -#define APBC_SSP0 0x81c -#define APBC_SSP1 0x820 -#define APBC_SSP2 0x84c -#define APBC_SSP3 0x858 -#define APBC_SSP4 0x85c -#define APBC_TWSI1 0x6c -#define APBC_UART2 0x70 -#define APMU_SDH0 0x54 -#define APMU_SDH1 0x58 -#define APMU_USB 0x5c -#define APMU_DISP0 0x4c -#define APMU_CCIC0 0x50 -#define APMU_DFC 0x60 -#define MPMU_UART_PLL 0x14 - -static DEFINE_SPINLOCK(clk_lock); - -static struct clk_factor_masks uart_factor_masks = { - .factor = 2, - .num_mask = 0x1fff, - .den_mask = 0x1fff, - .num_shift = 16, - .den_shift = 0, -}; - -static struct clk_factor_tbl uart_factor_tbl[] = { - {.num = 8125, .den = 1536}, /*14.745MHZ */ -}; - -static const char *uart_parent[] = {"pll1_3_16", "uart_pll"}; -static const char *ssp_parent[] = {"pll1_96", "pll1_48", "pll1_24", "pll1_12"}; -static const char *sdh_parent[] = {"pll1_12", "pll1_13"}; -static const char *disp_parent[] = {"pll1_2", "pll1_12"}; -static const char *ccic_parent[] = {"pll1_2", "pll1_12"}; -static const char *ccic_phy_parent[] = {"pll1_6", "pll1_12"}; - -void __init pxa168_clk_init(void) -{ - struct clk *clk; - struct clk *uart_pll; - void __iomem *mpmu_base; - void __iomem *apmu_base; - void __iomem *apbc_base; - - mpmu_base = ioremap(APB_PHYS_BASE + 0x50000, SZ_4K); - if (mpmu_base == NULL) { - pr_err("error to ioremap MPMU base\n"); - return; - } - - apmu_base = ioremap(AXI_PHYS_BASE + 0x82800, SZ_4K); - if (apmu_base == NULL) { - pr_err("error to ioremap APMU base\n"); - return; - } - - apbc_base = ioremap(APB_PHYS_BASE + 0x15000, SZ_4K); - if (apbc_base == NULL) { - pr_err("error to ioremap APBC base\n"); - return; - } - - clk = clk_register_fixed_rate(NULL, "clk32", NULL, CLK_IS_ROOT, 3200); - clk_register_clkdev(clk, "clk32", NULL); - - clk = clk_register_fixed_rate(NULL, "vctcxo", NULL, CLK_IS_ROOT, - 26000000); - clk_register_clkdev(clk, "vctcxo", NULL); - - clk = clk_register_fixed_rate(NULL, "pll1", NULL, CLK_IS_ROOT, - 624000000); - clk_register_clkdev(clk, "pll1", NULL); - - clk = clk_register_fixed_factor(NULL, "pll1_2", "pll1", - CLK_SET_RATE_PARENT, 1, 2); - clk_register_clkdev(clk, "pll1_2", NULL); - - clk = clk_register_fixed_factor(NULL, "pll1_4", "pll1_2", - CLK_SET_RATE_PARENT, 1, 2); - clk_register_clkdev(clk, "pll1_4", NULL); - - clk = clk_register_fixed_factor(NULL, "pll1_8", "pll1_4", - CLK_SET_RATE_PARENT, 1, 2); - clk_register_clkdev(clk, "pll1_8", NULL); - - clk = clk_register_fixed_factor(NULL, "pll1_16", "pll1_8", - CLK_SET_RATE_PARENT, 1, 2); - clk_register_clkdev(clk, "pll1_16", NULL); - - clk = clk_register_fixed_factor(NULL, "pll1_6", "pll1_2", - CLK_SET_RATE_PARENT, 1, 3); - clk_register_clkdev(clk, "pll1_6", NULL); - - clk = clk_register_fixed_factor(NULL, "pll1_12", "pll1_6", - CLK_SET_RATE_PARENT, 1, 2); - clk_register_clkdev(clk, "pll1_12", NULL); - - clk = clk_register_fixed_factor(NULL, "pll1_24", "pll1_12", - CLK_SET_RATE_PARENT, 1, 2); - clk_register_clkdev(clk, "pll1_24", NULL); - - clk = clk_register_fixed_factor(NULL, "pll1_48", "pll1_24", - CLK_SET_RATE_PARENT, 1, 2); - clk_register_clkdev(clk, "pll1_48", NULL); - - clk = clk_register_fixed_factor(NULL, "pll1_96", "pll1_48", - CLK_SET_RATE_PARENT, 1, 2); - clk_register_clkdev(clk, "pll1_96", NULL); - - clk = clk_register_fixed_factor(NULL, "pll1_13", "pll1", - CLK_SET_RATE_PARENT, 1, 13); - clk_register_clkdev(clk, "pll1_13", NULL); - - clk = clk_register_fixed_factor(NULL, "pll1_13_1_5", "pll1", - CLK_SET_RATE_PARENT, 2, 3); - clk_register_clkdev(clk, "pll1_13_1_5", NULL); - - clk = clk_register_fixed_factor(NULL, "pll1_2_1_5", "pll1", - CLK_SET_RATE_PARENT, 2, 3); - clk_register_clkdev(clk, "pll1_2_1_5", NULL); - - clk = clk_register_fixed_factor(NULL, "pll1_3_16", "pll1", - CLK_SET_RATE_PARENT, 3, 16); - clk_register_clkdev(clk, "pll1_3_16", NULL); - - uart_pll = mmp_clk_register_factor("uart_pll", "pll1_4", 0, - mpmu_base + MPMU_UART_PLL, - &uart_factor_masks, uart_factor_tbl, - ARRAY_SIZE(uart_factor_tbl)); - clk_set_rate(uart_pll, 14745600); - clk_register_clkdev(uart_pll, "uart_pll", NULL); - - clk = mmp_clk_register_apbc("twsi0", "pll1_13_1_5", - apbc_base + APBC_TWSI0, 10, 0, &clk_lock); - clk_register_clkdev(clk, NULL, "pxa2xx-i2c.0"); - - clk = mmp_clk_register_apbc("twsi1", "pll1_13_1_5", - apbc_base + APBC_TWSI1, 10, 0, &clk_lock); - clk_register_clkdev(clk, NULL, "pxa2xx-i2c.1"); - - clk = mmp_clk_register_apbc("gpio", "vctcxo", - apbc_base + APBC_GPIO, 10, 0, &clk_lock); - clk_register_clkdev(clk, NULL, "pxa-gpio"); - - clk = mmp_clk_register_apbc("kpc", "clk32", - apbc_base + APBC_KPC, 10, 0, &clk_lock); - clk_register_clkdev(clk, NULL, "pxa27x-keypad"); - - clk = mmp_clk_register_apbc("rtc", "clk32", - apbc_base + APBC_RTC, 10, 0, &clk_lock); - clk_register_clkdev(clk, NULL, "sa1100-rtc"); - - clk = mmp_clk_register_apbc("pwm0", "pll1_48", - apbc_base + APBC_PWM0, 10, 0, &clk_lock); - clk_register_clkdev(clk, NULL, "pxa168-pwm.0"); - - clk = mmp_clk_register_apbc("pwm1", "pll1_48", - apbc_base + APBC_PWM1, 10, 0, &clk_lock); - clk_register_clkdev(clk, NULL, "pxa168-pwm.1"); - - clk = mmp_clk_register_apbc("pwm2", "pll1_48", - apbc_base + APBC_PWM2, 10, 0, &clk_lock); - clk_register_clkdev(clk, NULL, "pxa168-pwm.2"); - - clk = mmp_clk_register_apbc("pwm3", "pll1_48", - apbc_base + APBC_PWM3, 10, 0, &clk_lock); - clk_register_clkdev(clk, NULL, "pxa168-pwm.3"); - - clk = clk_register_mux(NULL, "uart0_mux", uart_parent, - ARRAY_SIZE(uart_parent), CLK_SET_RATE_PARENT, - apbc_base + APBC_UART0, 4, 3, 0, &clk_lock); - clk_set_parent(clk, uart_pll); - clk_register_clkdev(clk, "uart_mux.0", NULL); - - clk = mmp_clk_register_apbc("uart0", "uart0_mux", - apbc_base + APBC_UART0, 10, 0, &clk_lock); - clk_register_clkdev(clk, NULL, "pxa2xx-uart.0"); - - clk = clk_register_mux(NULL, "uart1_mux", uart_parent, - ARRAY_SIZE(uart_parent), CLK_SET_RATE_PARENT, - apbc_base + APBC_UART1, 4, 3, 0, &clk_lock); - clk_set_parent(clk, uart_pll); - clk_register_clkdev(clk, "uart_mux.1", NULL); - - clk = mmp_clk_register_apbc("uart1", "uart1_mux", - apbc_base + APBC_UART1, 10, 0, &clk_lock); - clk_register_clkdev(clk, NULL, "pxa2xx-uart.1"); - - clk = clk_register_mux(NULL, "uart2_mux", uart_parent, - ARRAY_SIZE(uart_parent), CLK_SET_RATE_PARENT, - apbc_base + APBC_UART2, 4, 3, 0, &clk_lock); - clk_set_parent(clk, uart_pll); - clk_register_clkdev(clk, "uart_mux.2", NULL); - - clk = mmp_clk_register_apbc("uart2", "uart2_mux", - apbc_base + APBC_UART2, 10, 0, &clk_lock); - clk_register_clkdev(clk, NULL, "pxa2xx-uart.2"); - - clk = clk_register_mux(NULL, "ssp0_mux", ssp_parent, - ARRAY_SIZE(ssp_parent), CLK_SET_RATE_PARENT, - apbc_base + APBC_SSP0, 4, 3, 0, &clk_lock); - clk_register_clkdev(clk, "uart_mux.0", NULL); - - clk = mmp_clk_register_apbc("ssp0", "ssp0_mux", apbc_base + APBC_SSP0, - 10, 0, &clk_lock); - clk_register_clkdev(clk, NULL, "mmp-ssp.0"); - - clk = clk_register_mux(NULL, "ssp1_mux", ssp_parent, - ARRAY_SIZE(ssp_parent), CLK_SET_RATE_PARENT, - apbc_base + APBC_SSP1, 4, 3, 0, &clk_lock); - clk_register_clkdev(clk, "ssp_mux.1", NULL); - - clk = mmp_clk_register_apbc("ssp1", "ssp1_mux", apbc_base + APBC_SSP1, - 10, 0, &clk_lock); - clk_register_clkdev(clk, NULL, "mmp-ssp.1"); - - clk = clk_register_mux(NULL, "ssp2_mux", ssp_parent, - ARRAY_SIZE(ssp_parent), CLK_SET_RATE_PARENT, - apbc_base + APBC_SSP2, 4, 3, 0, &clk_lock); - clk_register_clkdev(clk, "ssp_mux.2", NULL); - - clk = mmp_clk_register_apbc("ssp2", "ssp1_mux", apbc_base + APBC_SSP2, - 10, 0, &clk_lock); - clk_register_clkdev(clk, NULL, "mmp-ssp.2"); - - clk = clk_register_mux(NULL, "ssp3_mux", ssp_parent, - ARRAY_SIZE(ssp_parent), CLK_SET_RATE_PARENT, - apbc_base + APBC_SSP3, 4, 3, 0, &clk_lock); - clk_register_clkdev(clk, "ssp_mux.3", NULL); - - clk = mmp_clk_register_apbc("ssp3", "ssp1_mux", apbc_base + APBC_SSP3, - 10, 0, &clk_lock); - clk_register_clkdev(clk, NULL, "mmp-ssp.3"); - - clk = clk_register_mux(NULL, "ssp4_mux", ssp_parent, - ARRAY_SIZE(ssp_parent), CLK_SET_RATE_PARENT, - apbc_base + APBC_SSP4, 4, 3, 0, &clk_lock); - clk_register_clkdev(clk, "ssp_mux.4", NULL); - - clk = mmp_clk_register_apbc("ssp4", "ssp1_mux", apbc_base + APBC_SSP4, - 10, 0, &clk_lock); - clk_register_clkdev(clk, NULL, "mmp-ssp.4"); - - clk = mmp_clk_register_apmu("dfc", "pll1_4", apmu_base + APMU_DFC, - 0x19b, &clk_lock); - clk_register_clkdev(clk, NULL, "pxa3xx-nand.0"); - - clk = clk_register_mux(NULL, "sdh0_mux", sdh_parent, - ARRAY_SIZE(sdh_parent), CLK_SET_RATE_PARENT, - apmu_base + APMU_SDH0, 6, 1, 0, &clk_lock); - clk_register_clkdev(clk, "sdh0_mux", NULL); - - clk = mmp_clk_register_apmu("sdh0", "sdh_mux", apmu_base + APMU_SDH0, - 0x1b, &clk_lock); - clk_register_clkdev(clk, NULL, "sdhci-pxa.0"); - - clk = clk_register_mux(NULL, "sdh1_mux", sdh_parent, - ARRAY_SIZE(sdh_parent), CLK_SET_RATE_PARENT, - apmu_base + APMU_SDH1, 6, 1, 0, &clk_lock); - clk_register_clkdev(clk, "sdh1_mux", NULL); - - clk = mmp_clk_register_apmu("sdh1", "sdh1_mux", apmu_base + APMU_SDH1, - 0x1b, &clk_lock); - clk_register_clkdev(clk, NULL, "sdhci-pxa.1"); - - clk = mmp_clk_register_apmu("usb", "usb_pll", apmu_base + APMU_USB, - 0x9, &clk_lock); - clk_register_clkdev(clk, "usb_clk", NULL); - - clk = mmp_clk_register_apmu("sph", "usb_pll", apmu_base + APMU_USB, - 0x12, &clk_lock); - clk_register_clkdev(clk, "sph_clk", NULL); - - clk = clk_register_mux(NULL, "disp0_mux", disp_parent, - ARRAY_SIZE(disp_parent), CLK_SET_RATE_PARENT, - apmu_base + APMU_DISP0, 6, 1, 0, &clk_lock); - clk_register_clkdev(clk, "disp_mux.0", NULL); - - clk = mmp_clk_register_apmu("disp0", "disp0_mux", - apmu_base + APMU_DISP0, 0x1b, &clk_lock); - clk_register_clkdev(clk, "fnclk", "mmp-disp.0"); - - clk = mmp_clk_register_apmu("disp0_hclk", "disp0_mux", - apmu_base + APMU_DISP0, 0x24, &clk_lock); - clk_register_clkdev(clk, "hclk", "mmp-disp.0"); - - clk = clk_register_mux(NULL, "ccic0_mux", ccic_parent, - ARRAY_SIZE(ccic_parent), CLK_SET_RATE_PARENT, - apmu_base + APMU_CCIC0, 6, 1, 0, &clk_lock); - clk_register_clkdev(clk, "ccic_mux.0", NULL); - - clk = mmp_clk_register_apmu("ccic0", "ccic0_mux", - apmu_base + APMU_CCIC0, 0x1b, &clk_lock); - clk_register_clkdev(clk, "fnclk", "mmp-ccic.0"); - - clk = clk_register_mux(NULL, "ccic0_phy_mux", ccic_phy_parent, - ARRAY_SIZE(ccic_phy_parent), - CLK_SET_RATE_PARENT, apmu_base + APMU_CCIC0, - 7, 1, 0, &clk_lock); - clk_register_clkdev(clk, "ccic_phy_mux.0", NULL); - - clk = mmp_clk_register_apmu("ccic0_phy", "ccic0_phy_mux", - apmu_base + APMU_CCIC0, 0x24, &clk_lock); - clk_register_clkdev(clk, "phyclk", "mmp-ccic.0"); - - clk = clk_register_divider(NULL, "ccic0_sphy_div", "ccic0_mux", - CLK_SET_RATE_PARENT, apmu_base + APMU_CCIC0, - 10, 5, 0, &clk_lock); - clk_register_clkdev(clk, "sphyclk_div", NULL); - - clk = mmp_clk_register_apmu("ccic0_sphy", "ccic0_sphy_div", - apmu_base + APMU_CCIC0, 0x300, &clk_lock); - clk_register_clkdev(clk, "sphyclk", "mmp-ccic.0"); -} diff --git a/trunk/drivers/clk/mmp/clk-pxa910.c b/trunk/drivers/clk/mmp/clk-pxa910.c deleted file mode 100644 index 7048c31d6e7e..000000000000 --- a/trunk/drivers/clk/mmp/clk-pxa910.c +++ /dev/null @@ -1,320 +0,0 @@ -/* - * pxa910 clock framework source file - * - * Copyright (C) 2012 Marvell - * Chao Xie - * - * 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 "clk.h" - -#define APBC_RTC 0x28 -#define APBC_TWSI0 0x2c -#define APBC_KPC 0x18 -#define APBC_UART0 0x0 -#define APBC_UART1 0x4 -#define APBC_GPIO 0x8 -#define APBC_PWM0 0xc -#define APBC_PWM1 0x10 -#define APBC_PWM2 0x14 -#define APBC_PWM3 0x18 -#define APBC_SSP0 0x1c -#define APBC_SSP1 0x20 -#define APBC_SSP2 0x4c -#define APBCP_TWSI1 0x28 -#define APBCP_UART2 0x1c -#define APMU_SDH0 0x54 -#define APMU_SDH1 0x58 -#define APMU_USB 0x5c -#define APMU_DISP0 0x4c -#define APMU_CCIC0 0x50 -#define APMU_DFC 0x60 -#define MPMU_UART_PLL 0x14 - -static DEFINE_SPINLOCK(clk_lock); - -static struct clk_factor_masks uart_factor_masks = { - .factor = 2, - .num_mask = 0x1fff, - .den_mask = 0x1fff, - .num_shift = 16, - .den_shift = 0, -}; - -static struct clk_factor_tbl uart_factor_tbl[] = { - {.num = 8125, .den = 1536}, /*14.745MHZ */ -}; - -static const char *uart_parent[] = {"pll1_3_16", "uart_pll"}; -static const char *ssp_parent[] = {"pll1_96", "pll1_48", "pll1_24", "pll1_12"}; -static const char *sdh_parent[] = {"pll1_12", "pll1_13"}; -static const char *disp_parent[] = {"pll1_2", "pll1_12"}; -static const char *ccic_parent[] = {"pll1_2", "pll1_12"}; -static const char *ccic_phy_parent[] = {"pll1_6", "pll1_12"}; - -void __init pxa910_clk_init(void) -{ - struct clk *clk; - struct clk *uart_pll; - void __iomem *mpmu_base; - void __iomem *apmu_base; - void __iomem *apbcp_base; - void __iomem *apbc_base; - - mpmu_base = ioremap(APB_PHYS_BASE + 0x50000, SZ_4K); - if (mpmu_base == NULL) { - pr_err("error to ioremap MPMU base\n"); - return; - } - - apmu_base = ioremap(AXI_PHYS_BASE + 0x82800, SZ_4K); - if (apmu_base == NULL) { - pr_err("error to ioremap APMU base\n"); - return; - } - - apbcp_base = ioremap(APB_PHYS_BASE + 0x3b000, SZ_4K); - if (apbcp_base == NULL) { - pr_err("error to ioremap APBC extension base\n"); - return; - } - - apbc_base = ioremap(APB_PHYS_BASE + 0x15000, SZ_4K); - if (apbc_base == NULL) { - pr_err("error to ioremap APBC base\n"); - return; - } - - clk = clk_register_fixed_rate(NULL, "clk32", NULL, CLK_IS_ROOT, 3200); - clk_register_clkdev(clk, "clk32", NULL); - - clk = clk_register_fixed_rate(NULL, "vctcxo", NULL, CLK_IS_ROOT, - 26000000); - clk_register_clkdev(clk, "vctcxo", NULL); - - clk = clk_register_fixed_rate(NULL, "pll1", NULL, CLK_IS_ROOT, - 624000000); - clk_register_clkdev(clk, "pll1", NULL); - - clk = clk_register_fixed_factor(NULL, "pll1_2", "pll1", - CLK_SET_RATE_PARENT, 1, 2); - clk_register_clkdev(clk, "pll1_2", NULL); - - clk = clk_register_fixed_factor(NULL, "pll1_4", "pll1_2", - CLK_SET_RATE_PARENT, 1, 2); - clk_register_clkdev(clk, "pll1_4", NULL); - - clk = clk_register_fixed_factor(NULL, "pll1_8", "pll1_4", - CLK_SET_RATE_PARENT, 1, 2); - clk_register_clkdev(clk, "pll1_8", NULL); - - clk = clk_register_fixed_factor(NULL, "pll1_16", "pll1_8", - CLK_SET_RATE_PARENT, 1, 2); - clk_register_clkdev(clk, "pll1_16", NULL); - - clk = clk_register_fixed_factor(NULL, "pll1_6", "pll1_2", - CLK_SET_RATE_PARENT, 1, 3); - clk_register_clkdev(clk, "pll1_6", NULL); - - clk = clk_register_fixed_factor(NULL, "pll1_12", "pll1_6", - CLK_SET_RATE_PARENT, 1, 2); - clk_register_clkdev(clk, "pll1_12", NULL); - - clk = clk_register_fixed_factor(NULL, "pll1_24", "pll1_12", - CLK_SET_RATE_PARENT, 1, 2); - clk_register_clkdev(clk, "pll1_24", NULL); - - clk = clk_register_fixed_factor(NULL, "pll1_48", "pll1_24", - CLK_SET_RATE_PARENT, 1, 2); - clk_register_clkdev(clk, "pll1_48", NULL); - - clk = clk_register_fixed_factor(NULL, "pll1_96", "pll1_48", - CLK_SET_RATE_PARENT, 1, 2); - clk_register_clkdev(clk, "pll1_96", NULL); - - clk = clk_register_fixed_factor(NULL, "pll1_13", "pll1", - CLK_SET_RATE_PARENT, 1, 13); - clk_register_clkdev(clk, "pll1_13", NULL); - - clk = clk_register_fixed_factor(NULL, "pll1_13_1_5", "pll1", - CLK_SET_RATE_PARENT, 2, 3); - clk_register_clkdev(clk, "pll1_13_1_5", NULL); - - clk = clk_register_fixed_factor(NULL, "pll1_2_1_5", "pll1", - CLK_SET_RATE_PARENT, 2, 3); - clk_register_clkdev(clk, "pll1_2_1_5", NULL); - - clk = clk_register_fixed_factor(NULL, "pll1_3_16", "pll1", - CLK_SET_RATE_PARENT, 3, 16); - clk_register_clkdev(clk, "pll1_3_16", NULL); - - uart_pll = mmp_clk_register_factor("uart_pll", "pll1_4", 0, - mpmu_base + MPMU_UART_PLL, - &uart_factor_masks, uart_factor_tbl, - ARRAY_SIZE(uart_factor_tbl)); - clk_set_rate(uart_pll, 14745600); - clk_register_clkdev(uart_pll, "uart_pll", NULL); - - clk = mmp_clk_register_apbc("twsi0", "pll1_13_1_5", - apbc_base + APBC_TWSI0, 10, 0, &clk_lock); - clk_register_clkdev(clk, NULL, "pxa2xx-i2c.0"); - - clk = mmp_clk_register_apbc("twsi1", "pll1_13_1_5", - apbcp_base + APBCP_TWSI1, 10, 0, &clk_lock); - clk_register_clkdev(clk, NULL, "pxa2xx-i2c.1"); - - clk = mmp_clk_register_apbc("gpio", "vctcxo", - apbc_base + APBC_GPIO, 10, 0, &clk_lock); - clk_register_clkdev(clk, NULL, "pxa-gpio"); - - clk = mmp_clk_register_apbc("kpc", "clk32", - apbc_base + APBC_KPC, 10, 0, &clk_lock); - clk_register_clkdev(clk, NULL, "pxa27x-keypad"); - - clk = mmp_clk_register_apbc("rtc", "clk32", - apbc_base + APBC_RTC, 10, 0, &clk_lock); - clk_register_clkdev(clk, NULL, "sa1100-rtc"); - - clk = mmp_clk_register_apbc("pwm0", "pll1_48", - apbc_base + APBC_PWM0, 10, 0, &clk_lock); - clk_register_clkdev(clk, NULL, "pxa910-pwm.0"); - - clk = mmp_clk_register_apbc("pwm1", "pll1_48", - apbc_base + APBC_PWM1, 10, 0, &clk_lock); - clk_register_clkdev(clk, NULL, "pxa910-pwm.1"); - - clk = mmp_clk_register_apbc("pwm2", "pll1_48", - apbc_base + APBC_PWM2, 10, 0, &clk_lock); - clk_register_clkdev(clk, NULL, "pxa910-pwm.2"); - - clk = mmp_clk_register_apbc("pwm3", "pll1_48", - apbc_base + APBC_PWM3, 10, 0, &clk_lock); - clk_register_clkdev(clk, NULL, "pxa910-pwm.3"); - - clk = clk_register_mux(NULL, "uart0_mux", uart_parent, - ARRAY_SIZE(uart_parent), CLK_SET_RATE_PARENT, - apbc_base + APBC_UART0, 4, 3, 0, &clk_lock); - clk_set_parent(clk, uart_pll); - clk_register_clkdev(clk, "uart_mux.0", NULL); - - clk = mmp_clk_register_apbc("uart0", "uart0_mux", - apbc_base + APBC_UART0, 10, 0, &clk_lock); - clk_register_clkdev(clk, NULL, "pxa2xx-uart.0"); - - clk = clk_register_mux(NULL, "uart1_mux", uart_parent, - ARRAY_SIZE(uart_parent), CLK_SET_RATE_PARENT, - apbc_base + APBC_UART1, 4, 3, 0, &clk_lock); - clk_set_parent(clk, uart_pll); - clk_register_clkdev(clk, "uart_mux.1", NULL); - - clk = mmp_clk_register_apbc("uart1", "uart1_mux", - apbc_base + APBC_UART1, 10, 0, &clk_lock); - clk_register_clkdev(clk, NULL, "pxa2xx-uart.1"); - - clk = clk_register_mux(NULL, "uart2_mux", uart_parent, - ARRAY_SIZE(uart_parent), CLK_SET_RATE_PARENT, - apbcp_base + APBCP_UART2, 4, 3, 0, &clk_lock); - clk_set_parent(clk, uart_pll); - clk_register_clkdev(clk, "uart_mux.2", NULL); - - clk = mmp_clk_register_apbc("uart2", "uart2_mux", - apbcp_base + APBCP_UART2, 10, 0, &clk_lock); - clk_register_clkdev(clk, NULL, "pxa2xx-uart.2"); - - clk = clk_register_mux(NULL, "ssp0_mux", ssp_parent, - ARRAY_SIZE(ssp_parent), CLK_SET_RATE_PARENT, - apbc_base + APBC_SSP0, 4, 3, 0, &clk_lock); - clk_register_clkdev(clk, "uart_mux.0", NULL); - - clk = mmp_clk_register_apbc("ssp0", "ssp0_mux", - apbc_base + APBC_SSP0, 10, 0, &clk_lock); - clk_register_clkdev(clk, NULL, "mmp-ssp.0"); - - clk = clk_register_mux(NULL, "ssp1_mux", ssp_parent, - ARRAY_SIZE(ssp_parent), CLK_SET_RATE_PARENT, - apbc_base + APBC_SSP1, 4, 3, 0, &clk_lock); - clk_register_clkdev(clk, "ssp_mux.1", NULL); - - clk = mmp_clk_register_apbc("ssp1", "ssp1_mux", - apbc_base + APBC_SSP1, 10, 0, &clk_lock); - clk_register_clkdev(clk, NULL, "mmp-ssp.1"); - - clk = mmp_clk_register_apmu("dfc", "pll1_4", - apmu_base + APMU_DFC, 0x19b, &clk_lock); - clk_register_clkdev(clk, NULL, "pxa3xx-nand.0"); - - clk = clk_register_mux(NULL, "sdh0_mux", sdh_parent, - ARRAY_SIZE(sdh_parent), CLK_SET_RATE_PARENT, - apmu_base + APMU_SDH0, 6, 1, 0, &clk_lock); - clk_register_clkdev(clk, "sdh0_mux", NULL); - - clk = mmp_clk_register_apmu("sdh0", "sdh_mux", - apmu_base + APMU_SDH0, 0x1b, &clk_lock); - clk_register_clkdev(clk, NULL, "sdhci-pxa.0"); - - clk = clk_register_mux(NULL, "sdh1_mux", sdh_parent, - ARRAY_SIZE(sdh_parent), CLK_SET_RATE_PARENT, - apmu_base + APMU_SDH1, 6, 1, 0, &clk_lock); - clk_register_clkdev(clk, "sdh1_mux", NULL); - - clk = mmp_clk_register_apmu("sdh1", "sdh1_mux", - apmu_base + APMU_SDH1, 0x1b, &clk_lock); - clk_register_clkdev(clk, NULL, "sdhci-pxa.1"); - - clk = mmp_clk_register_apmu("usb", "usb_pll", - apmu_base + APMU_USB, 0x9, &clk_lock); - clk_register_clkdev(clk, "usb_clk", NULL); - - clk = mmp_clk_register_apmu("sph", "usb_pll", - apmu_base + APMU_USB, 0x12, &clk_lock); - clk_register_clkdev(clk, "sph_clk", NULL); - - clk = clk_register_mux(NULL, "disp0_mux", disp_parent, - ARRAY_SIZE(disp_parent), CLK_SET_RATE_PARENT, - apmu_base + APMU_DISP0, 6, 1, 0, &clk_lock); - clk_register_clkdev(clk, "disp_mux.0", NULL); - - clk = mmp_clk_register_apmu("disp0", "disp0_mux", - apmu_base + APMU_DISP0, 0x1b, &clk_lock); - clk_register_clkdev(clk, NULL, "mmp-disp.0"); - - clk = clk_register_mux(NULL, "ccic0_mux", ccic_parent, - ARRAY_SIZE(ccic_parent), CLK_SET_RATE_PARENT, - apmu_base + APMU_CCIC0, 6, 1, 0, &clk_lock); - clk_register_clkdev(clk, "ccic_mux.0", NULL); - - clk = mmp_clk_register_apmu("ccic0", "ccic0_mux", - apmu_base + APMU_CCIC0, 0x1b, &clk_lock); - clk_register_clkdev(clk, "fnclk", "mmp-ccic.0"); - - clk = clk_register_mux(NULL, "ccic0_phy_mux", ccic_phy_parent, - ARRAY_SIZE(ccic_phy_parent), - CLK_SET_RATE_PARENT, apmu_base + APMU_CCIC0, - 7, 1, 0, &clk_lock); - clk_register_clkdev(clk, "ccic_phy_mux.0", NULL); - - clk = mmp_clk_register_apmu("ccic0_phy", "ccic0_phy_mux", - apmu_base + APMU_CCIC0, 0x24, &clk_lock); - clk_register_clkdev(clk, "phyclk", "mmp-ccic.0"); - - clk = clk_register_divider(NULL, "ccic0_sphy_div", "ccic0_mux", - CLK_SET_RATE_PARENT, apmu_base + APMU_CCIC0, - 10, 5, 0, &clk_lock); - clk_register_clkdev(clk, "sphyclk_div", NULL); - - clk = mmp_clk_register_apmu("ccic0_sphy", "ccic0_sphy_div", - apmu_base + APMU_CCIC0, 0x300, &clk_lock); - clk_register_clkdev(clk, "sphyclk", "mmp-ccic.0"); -} diff --git a/trunk/drivers/clk/mmp/clk.h b/trunk/drivers/clk/mmp/clk.h deleted file mode 100644 index ab86dd4a416a..000000000000 --- a/trunk/drivers/clk/mmp/clk.h +++ /dev/null @@ -1,35 +0,0 @@ -#ifndef __MACH_MMP_CLK_H -#define __MACH_MMP_CLK_H - -#include -#include - -#define APBC_NO_BUS_CTRL BIT(0) -#define APBC_POWER_CTRL BIT(1) - -struct clk_factor_masks { - unsigned int factor; - unsigned int num_mask; - unsigned int den_mask; - unsigned int num_shift; - unsigned int den_shift; -}; - -struct clk_factor_tbl { - unsigned int num; - unsigned int den; -}; - -extern struct clk *mmp_clk_register_pll2(const char *name, - const char *parent_name, unsigned long flags); -extern struct clk *mmp_clk_register_apbc(const char *name, - const char *parent_name, void __iomem *base, - unsigned int delay, unsigned int apbc_flags, spinlock_t *lock); -extern struct clk *mmp_clk_register_apmu(const char *name, - const char *parent_name, void __iomem *base, u32 enable_mask, - spinlock_t *lock); -extern struct clk *mmp_clk_register_factor(const char *name, - const char *parent_name, unsigned long flags, - void __iomem *base, struct clk_factor_masks *masks, - struct clk_factor_tbl *ftbl, unsigned int ftbl_cnt); -#endif diff --git a/trunk/drivers/clk/ux500/Makefile b/trunk/drivers/clk/ux500/Makefile deleted file mode 100644 index 858fbfe66281..000000000000 --- a/trunk/drivers/clk/ux500/Makefile +++ /dev/null @@ -1,12 +0,0 @@ -# -# Makefile for ux500 clocks -# - -# Clock types -obj-y += clk-prcc.o -obj-y += clk-prcmu.o - -# Clock definitions -obj-y += u8500_clk.o -obj-y += u9540_clk.o -obj-y += u8540_clk.o diff --git a/trunk/drivers/clk/ux500/clk-prcc.c b/trunk/drivers/clk/ux500/clk-prcc.c deleted file mode 100644 index 7eee7f768355..000000000000 --- a/trunk/drivers/clk/ux500/clk-prcc.c +++ /dev/null @@ -1,164 +0,0 @@ -/* - * PRCC clock implementation for ux500 platform. - * - * Copyright (C) 2012 ST-Ericsson SA - * Author: Ulf Hansson - * - * License terms: GNU General Public License (GPL) version 2 - */ - -#include -#include -#include -#include -#include -#include -#include - -#include "clk.h" - -#define PRCC_PCKEN 0x000 -#define PRCC_PCKDIS 0x004 -#define PRCC_KCKEN 0x008 -#define PRCC_KCKDIS 0x00C -#define PRCC_PCKSR 0x010 -#define PRCC_KCKSR 0x014 - -#define to_clk_prcc(_hw) container_of(_hw, struct clk_prcc, hw) - -struct clk_prcc { - struct clk_hw hw; - void __iomem *base; - u32 cg_sel; - int is_enabled; -}; - -/* PRCC clock operations. */ - -static int clk_prcc_pclk_enable(struct clk_hw *hw) -{ - struct clk_prcc *clk = to_clk_prcc(hw); - - writel(clk->cg_sel, (clk->base + PRCC_PCKEN)); - while (!(readl(clk->base + PRCC_PCKSR) & clk->cg_sel)) - cpu_relax(); - - clk->is_enabled = 1; - return 0; -} - -static void clk_prcc_pclk_disable(struct clk_hw *hw) -{ - struct clk_prcc *clk = to_clk_prcc(hw); - - writel(clk->cg_sel, (clk->base + PRCC_PCKDIS)); - clk->is_enabled = 0; -} - -static int clk_prcc_kclk_enable(struct clk_hw *hw) -{ - struct clk_prcc *clk = to_clk_prcc(hw); - - writel(clk->cg_sel, (clk->base + PRCC_KCKEN)); - while (!(readl(clk->base + PRCC_KCKSR) & clk->cg_sel)) - cpu_relax(); - - clk->is_enabled = 1; - return 0; -} - -static void clk_prcc_kclk_disable(struct clk_hw *hw) -{ - struct clk_prcc *clk = to_clk_prcc(hw); - - writel(clk->cg_sel, (clk->base + PRCC_KCKDIS)); - clk->is_enabled = 0; -} - -static int clk_prcc_is_enabled(struct clk_hw *hw) -{ - struct clk_prcc *clk = to_clk_prcc(hw); - return clk->is_enabled; -} - -static struct clk_ops clk_prcc_pclk_ops = { - .enable = clk_prcc_pclk_enable, - .disable = clk_prcc_pclk_disable, - .is_enabled = clk_prcc_is_enabled, -}; - -static struct clk_ops clk_prcc_kclk_ops = { - .enable = clk_prcc_kclk_enable, - .disable = clk_prcc_kclk_disable, - .is_enabled = clk_prcc_is_enabled, -}; - -static struct clk *clk_reg_prcc(const char *name, - const char *parent_name, - resource_size_t phy_base, - u32 cg_sel, - unsigned long flags, - struct clk_ops *clk_prcc_ops) -{ - struct clk_prcc *clk; - struct clk_init_data clk_prcc_init; - struct clk *clk_reg; - - if (!name) { - pr_err("clk_prcc: %s invalid arguments passed\n", __func__); - return ERR_PTR(-EINVAL); - } - - clk = kzalloc(sizeof(struct clk_prcc), GFP_KERNEL); - if (!clk) { - pr_err("clk_prcc: %s could not allocate clk\n", __func__); - return ERR_PTR(-ENOMEM); - } - - clk->base = ioremap(phy_base, SZ_4K); - if (!clk->base) - goto free_clk; - - clk->cg_sel = cg_sel; - clk->is_enabled = 1; - - clk_prcc_init.name = name; - clk_prcc_init.ops = clk_prcc_ops; - clk_prcc_init.flags = flags; - clk_prcc_init.parent_names = (parent_name ? &parent_name : NULL); - clk_prcc_init.num_parents = (parent_name ? 1 : 0); - clk->hw.init = &clk_prcc_init; - - clk_reg = clk_register(NULL, &clk->hw); - if (IS_ERR_OR_NULL(clk_reg)) - goto unmap_clk; - - return clk_reg; - -unmap_clk: - iounmap(clk->base); -free_clk: - kfree(clk); - pr_err("clk_prcc: %s failed to register clk\n", __func__); - return ERR_PTR(-ENOMEM); -} - -struct clk *clk_reg_prcc_pclk(const char *name, - const char *parent_name, - resource_size_t phy_base, - u32 cg_sel, - unsigned long flags) -{ - return clk_reg_prcc(name, parent_name, phy_base, cg_sel, flags, - &clk_prcc_pclk_ops); -} - -struct clk *clk_reg_prcc_kclk(const char *name, - const char *parent_name, - resource_size_t phy_base, - u32 cg_sel, - unsigned long flags) -{ - return clk_reg_prcc(name, parent_name, phy_base, cg_sel, flags, - &clk_prcc_kclk_ops); -} diff --git a/trunk/drivers/clk/ux500/clk-prcmu.c b/trunk/drivers/clk/ux500/clk-prcmu.c deleted file mode 100644 index 930cdfeb47ab..000000000000 --- a/trunk/drivers/clk/ux500/clk-prcmu.c +++ /dev/null @@ -1,252 +0,0 @@ -/* - * PRCMU clock implementation for ux500 platform. - * - * Copyright (C) 2012 ST-Ericsson SA - * Author: Ulf Hansson - * - * License terms: GNU General Public License (GPL) version 2 - */ - -#include -#include -#include -#include -#include -#include -#include "clk.h" - -#define to_clk_prcmu(_hw) container_of(_hw, struct clk_prcmu, hw) - -struct clk_prcmu { - struct clk_hw hw; - u8 cg_sel; - int is_enabled; -}; - -/* PRCMU clock operations. */ - -static int clk_prcmu_prepare(struct clk_hw *hw) -{ - struct clk_prcmu *clk = to_clk_prcmu(hw); - return prcmu_request_clock(clk->cg_sel, true); -} - -static void clk_prcmu_unprepare(struct clk_hw *hw) -{ - struct clk_prcmu *clk = to_clk_prcmu(hw); - if (prcmu_request_clock(clk->cg_sel, false)) - pr_err("clk_prcmu: %s failed to disable %s.\n", __func__, - hw->init->name); -} - -static int clk_prcmu_enable(struct clk_hw *hw) -{ - struct clk_prcmu *clk = to_clk_prcmu(hw); - clk->is_enabled = 1; - return 0; -} - -static void clk_prcmu_disable(struct clk_hw *hw) -{ - struct clk_prcmu *clk = to_clk_prcmu(hw); - clk->is_enabled = 0; -} - -static int clk_prcmu_is_enabled(struct clk_hw *hw) -{ - struct clk_prcmu *clk = to_clk_prcmu(hw); - return clk->is_enabled; -} - -static unsigned long clk_prcmu_recalc_rate(struct clk_hw *hw, - unsigned long parent_rate) -{ - struct clk_prcmu *clk = to_clk_prcmu(hw); - return prcmu_clock_rate(clk->cg_sel); -} - -static long clk_prcmu_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *parent_rate) -{ - struct clk_prcmu *clk = to_clk_prcmu(hw); - return prcmu_round_clock_rate(clk->cg_sel, rate); -} - -static int clk_prcmu_set_rate(struct clk_hw *hw, unsigned long rate, - unsigned long parent_rate) -{ - struct clk_prcmu *clk = to_clk_prcmu(hw); - return prcmu_set_clock_rate(clk->cg_sel, rate); -} - -static int request_ape_opp100(bool enable) -{ - static int reqs; - int err = 0; - - if (enable) { - if (!reqs) - err = prcmu_qos_add_requirement(PRCMU_QOS_APE_OPP, - "clock", 100); - if (!err) - reqs++; - } else { - reqs--; - if (!reqs) - prcmu_qos_remove_requirement(PRCMU_QOS_APE_OPP, - "clock"); - } - return err; -} - -static int clk_prcmu_opp_prepare(struct clk_hw *hw) -{ - int err; - struct clk_prcmu *clk = to_clk_prcmu(hw); - - err = request_ape_opp100(true); - if (err) { - pr_err("clk_prcmu: %s failed to request APE OPP100 for %s.\n", - __func__, hw->init->name); - return err; - } - - err = prcmu_request_clock(clk->cg_sel, true); - if (err) - request_ape_opp100(false); - - return err; -} - -static void clk_prcmu_opp_unprepare(struct clk_hw *hw) -{ - struct clk_prcmu *clk = to_clk_prcmu(hw); - - if (prcmu_request_clock(clk->cg_sel, false)) - goto out_error; - if (request_ape_opp100(false)) - goto out_error; - return; - -out_error: - pr_err("clk_prcmu: %s failed to disable %s.\n", __func__, - hw->init->name); -} - -static struct clk_ops clk_prcmu_scalable_ops = { - .prepare = clk_prcmu_prepare, - .unprepare = clk_prcmu_unprepare, - .enable = clk_prcmu_enable, - .disable = clk_prcmu_disable, - .is_enabled = clk_prcmu_is_enabled, - .recalc_rate = clk_prcmu_recalc_rate, - .round_rate = clk_prcmu_round_rate, - .set_rate = clk_prcmu_set_rate, -}; - -static struct clk_ops clk_prcmu_gate_ops = { - .prepare = clk_prcmu_prepare, - .unprepare = clk_prcmu_unprepare, - .enable = clk_prcmu_enable, - .disable = clk_prcmu_disable, - .is_enabled = clk_prcmu_is_enabled, - .recalc_rate = clk_prcmu_recalc_rate, -}; - -static struct clk_ops clk_prcmu_rate_ops = { - .is_enabled = clk_prcmu_is_enabled, - .recalc_rate = clk_prcmu_recalc_rate, -}; - -static struct clk_ops clk_prcmu_opp_gate_ops = { - .prepare = clk_prcmu_opp_prepare, - .unprepare = clk_prcmu_opp_unprepare, - .enable = clk_prcmu_enable, - .disable = clk_prcmu_disable, - .is_enabled = clk_prcmu_is_enabled, - .recalc_rate = clk_prcmu_recalc_rate, -}; - -static struct clk *clk_reg_prcmu(const char *name, - const char *parent_name, - u8 cg_sel, - unsigned long rate, - unsigned long flags, - struct clk_ops *clk_prcmu_ops) -{ - struct clk_prcmu *clk; - struct clk_init_data clk_prcmu_init; - struct clk *clk_reg; - - if (!name) { - pr_err("clk_prcmu: %s invalid arguments passed\n", __func__); - return ERR_PTR(-EINVAL); - } - - clk = kzalloc(sizeof(struct clk_prcmu), GFP_KERNEL); - if (!clk) { - pr_err("clk_prcmu: %s could not allocate clk\n", __func__); - return ERR_PTR(-ENOMEM); - } - - clk->cg_sel = cg_sel; - clk->is_enabled = 1; - /* "rate" can be used for changing the initial frequency */ - if (rate) - prcmu_set_clock_rate(cg_sel, rate); - - clk_prcmu_init.name = name; - clk_prcmu_init.ops = clk_prcmu_ops; - clk_prcmu_init.flags = flags; - clk_prcmu_init.parent_names = (parent_name ? &parent_name : NULL); - clk_prcmu_init.num_parents = (parent_name ? 1 : 0); - clk->hw.init = &clk_prcmu_init; - - clk_reg = clk_register(NULL, &clk->hw); - if (IS_ERR_OR_NULL(clk_reg)) - goto free_clk; - - return clk_reg; - -free_clk: - kfree(clk); - pr_err("clk_prcmu: %s failed to register clk\n", __func__); - return ERR_PTR(-ENOMEM); -} - -struct clk *clk_reg_prcmu_scalable(const char *name, - const char *parent_name, - u8 cg_sel, - unsigned long rate, - unsigned long flags) -{ - return clk_reg_prcmu(name, parent_name, cg_sel, rate, flags, - &clk_prcmu_scalable_ops); -} - -struct clk *clk_reg_prcmu_gate(const char *name, - const char *parent_name, - u8 cg_sel, - unsigned long flags) -{ - return clk_reg_prcmu(name, parent_name, cg_sel, 0, flags, - &clk_prcmu_gate_ops); -} - -struct clk *clk_reg_prcmu_rate(const char *name, - const char *parent_name, - u8 cg_sel, - unsigned long flags) -{ - return clk_reg_prcmu(name, parent_name, cg_sel, 0, flags, - &clk_prcmu_rate_ops); -} - -struct clk *clk_reg_prcmu_opp_gate(const char *name, - const char *parent_name, - u8 cg_sel, - unsigned long flags) -{ - return clk_reg_prcmu(name, parent_name, cg_sel, 0, flags, - &clk_prcmu_opp_gate_ops); -} diff --git a/trunk/drivers/clk/ux500/clk.h b/trunk/drivers/clk/ux500/clk.h deleted file mode 100644 index 836d7d16751e..000000000000 --- a/trunk/drivers/clk/ux500/clk.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Clocks for ux500 platforms - * - * Copyright (C) 2012 ST-Ericsson SA - * Author: Ulf Hansson - * - * License terms: GNU General Public License (GPL) version 2 - */ - -#ifndef __UX500_CLK_H -#define __UX500_CLK_H - -#include - -struct clk *clk_reg_prcc_pclk(const char *name, - const char *parent_name, - unsigned int phy_base, - u32 cg_sel, - unsigned long flags); - -struct clk *clk_reg_prcc_kclk(const char *name, - const char *parent_name, - unsigned int phy_base, - u32 cg_sel, - unsigned long flags); - -struct clk *clk_reg_prcmu_scalable(const char *name, - const char *parent_name, - u8 cg_sel, - unsigned long rate, - unsigned long flags); - -struct clk *clk_reg_prcmu_gate(const char *name, - const char *parent_name, - u8 cg_sel, - unsigned long flags); - -struct clk *clk_reg_prcmu_rate(const char *name, - const char *parent_name, - u8 cg_sel, - unsigned long flags); - -struct clk *clk_reg_prcmu_opp_gate(const char *name, - const char *parent_name, - u8 cg_sel, - unsigned long flags); - -#endif /* __UX500_CLK_H */ diff --git a/trunk/drivers/clk/ux500/u8500_clk.c b/trunk/drivers/clk/ux500/u8500_clk.c deleted file mode 100644 index ca4a25ed844c..000000000000 --- a/trunk/drivers/clk/ux500/u8500_clk.c +++ /dev/null @@ -1,477 +0,0 @@ -/* - * Clock definitions for u8500 platform. - * - * Copyright (C) 2012 ST-Ericsson SA - * Author: Ulf Hansson - * - * License terms: GNU General Public License (GPL) version 2 - */ - -#include -#include -#include -#include -#include - -#include "clk.h" - -void u8500_clk_init(void) -{ - struct prcmu_fw_version *fw_version; - const char *sgaclk_parent = NULL; - struct clk *clk; - - /* Clock sources */ - clk = clk_reg_prcmu_gate("soc0_pll", NULL, PRCMU_PLLSOC0, - CLK_IS_ROOT|CLK_IGNORE_UNUSED); - clk_register_clkdev(clk, "soc0_pll", NULL); - - clk = clk_reg_prcmu_gate("soc1_pll", NULL, PRCMU_PLLSOC1, - CLK_IS_ROOT|CLK_IGNORE_UNUSED); - clk_register_clkdev(clk, "soc1_pll", NULL); - - clk = clk_reg_prcmu_gate("ddr_pll", NULL, PRCMU_PLLDDR, - CLK_IS_ROOT|CLK_IGNORE_UNUSED); - clk_register_clkdev(clk, "ddr_pll", NULL); - - /* FIXME: Add sys, ulp and int clocks here. */ - - clk = clk_register_fixed_rate(NULL, "rtc32k", "NULL", - CLK_IS_ROOT|CLK_IGNORE_UNUSED, - 32768); - clk_register_clkdev(clk, "clk32k", NULL); - clk_register_clkdev(clk, NULL, "rtc-pl031"); - - /* PRCMU clocks */ - fw_version = prcmu_get_fw_version(); - if (fw_version != NULL) { - switch (fw_version->project) { - case PRCMU_FW_PROJECT_U8500_C2: - case PRCMU_FW_PROJECT_U8520: - case PRCMU_FW_PROJECT_U8420: - sgaclk_parent = "soc0_pll"; - break; - default: - break; - } - } - - if (sgaclk_parent) - clk = clk_reg_prcmu_gate("sgclk", sgaclk_parent, - PRCMU_SGACLK, 0); - else - clk = clk_reg_prcmu_gate("sgclk", NULL, - PRCMU_SGACLK, CLK_IS_ROOT); - clk_register_clkdev(clk, NULL, "mali"); - - clk = clk_reg_prcmu_gate("uartclk", NULL, PRCMU_UARTCLK, CLK_IS_ROOT); - clk_register_clkdev(clk, NULL, "UART"); - - clk = clk_reg_prcmu_gate("msp02clk", NULL, PRCMU_MSP02CLK, CLK_IS_ROOT); - clk_register_clkdev(clk, NULL, "MSP02"); - - clk = clk_reg_prcmu_gate("msp1clk", NULL, PRCMU_MSP1CLK, CLK_IS_ROOT); - clk_register_clkdev(clk, NULL, "MSP1"); - - clk = clk_reg_prcmu_gate("i2cclk", NULL, PRCMU_I2CCLK, CLK_IS_ROOT); - clk_register_clkdev(clk, NULL, "I2C"); - - clk = clk_reg_prcmu_gate("slimclk", NULL, PRCMU_SLIMCLK, CLK_IS_ROOT); - clk_register_clkdev(clk, NULL, "slim"); - - clk = clk_reg_prcmu_gate("per1clk", NULL, PRCMU_PER1CLK, CLK_IS_ROOT); - clk_register_clkdev(clk, NULL, "PERIPH1"); - - clk = clk_reg_prcmu_gate("per2clk", NULL, PRCMU_PER2CLK, CLK_IS_ROOT); - clk_register_clkdev(clk, NULL, "PERIPH2"); - - clk = clk_reg_prcmu_gate("per3clk", NULL, PRCMU_PER3CLK, CLK_IS_ROOT); - clk_register_clkdev(clk, NULL, "PERIPH3"); - - clk = clk_reg_prcmu_gate("per5clk", NULL, PRCMU_PER5CLK, CLK_IS_ROOT); - clk_register_clkdev(clk, NULL, "PERIPH5"); - - clk = clk_reg_prcmu_gate("per6clk", NULL, PRCMU_PER6CLK, CLK_IS_ROOT); - clk_register_clkdev(clk, NULL, "PERIPH6"); - - clk = clk_reg_prcmu_gate("per7clk", NULL, PRCMU_PER7CLK, CLK_IS_ROOT); - clk_register_clkdev(clk, NULL, "PERIPH7"); - - clk = clk_reg_prcmu_scalable("lcdclk", NULL, PRCMU_LCDCLK, 0, - CLK_IS_ROOT|CLK_SET_RATE_GATE); - clk_register_clkdev(clk, NULL, "lcd"); - clk_register_clkdev(clk, "lcd", "mcde"); - - clk = clk_reg_prcmu_opp_gate("bmlclk", NULL, PRCMU_BMLCLK, CLK_IS_ROOT); - clk_register_clkdev(clk, NULL, "bml"); - - clk = clk_reg_prcmu_scalable("hsitxclk", NULL, PRCMU_HSITXCLK, 0, - CLK_IS_ROOT|CLK_SET_RATE_GATE); - - clk = clk_reg_prcmu_scalable("hsirxclk", NULL, PRCMU_HSIRXCLK, 0, - CLK_IS_ROOT|CLK_SET_RATE_GATE); - - clk = clk_reg_prcmu_scalable("hdmiclk", NULL, PRCMU_HDMICLK, 0, - CLK_IS_ROOT|CLK_SET_RATE_GATE); - clk_register_clkdev(clk, NULL, "hdmi"); - clk_register_clkdev(clk, "hdmi", "mcde"); - - clk = clk_reg_prcmu_gate("apeatclk", NULL, PRCMU_APEATCLK, CLK_IS_ROOT); - clk_register_clkdev(clk, NULL, "apeat"); - - clk = clk_reg_prcmu_gate("apetraceclk", NULL, PRCMU_APETRACECLK, - CLK_IS_ROOT); - clk_register_clkdev(clk, NULL, "apetrace"); - - clk = clk_reg_prcmu_gate("mcdeclk", NULL, PRCMU_MCDECLK, CLK_IS_ROOT); - clk_register_clkdev(clk, NULL, "mcde"); - clk_register_clkdev(clk, "mcde", "mcde"); - clk_register_clkdev(clk, "dsisys", "dsilink.0"); - clk_register_clkdev(clk, "dsisys", "dsilink.1"); - clk_register_clkdev(clk, "dsisys", "dsilink.2"); - - clk = clk_reg_prcmu_opp_gate("ipi2cclk", NULL, PRCMU_IPI2CCLK, - CLK_IS_ROOT); - clk_register_clkdev(clk, NULL, "ipi2"); - - clk = clk_reg_prcmu_gate("dsialtclk", NULL, PRCMU_DSIALTCLK, - CLK_IS_ROOT); - clk_register_clkdev(clk, NULL, "dsialt"); - - clk = clk_reg_prcmu_gate("dmaclk", NULL, PRCMU_DMACLK, CLK_IS_ROOT); - clk_register_clkdev(clk, NULL, "dma40.0"); - - clk = clk_reg_prcmu_gate("b2r2clk", NULL, PRCMU_B2R2CLK, CLK_IS_ROOT); - clk_register_clkdev(clk, NULL, "b2r2"); - clk_register_clkdev(clk, NULL, "b2r2_core"); - clk_register_clkdev(clk, NULL, "U8500-B2R2.0"); - - clk = clk_reg_prcmu_scalable("tvclk", NULL, PRCMU_TVCLK, 0, - CLK_IS_ROOT|CLK_SET_RATE_GATE); - clk_register_clkdev(clk, NULL, "tv"); - clk_register_clkdev(clk, "tv", "mcde"); - - clk = clk_reg_prcmu_gate("sspclk", NULL, PRCMU_SSPCLK, CLK_IS_ROOT); - clk_register_clkdev(clk, NULL, "SSP"); - - clk = clk_reg_prcmu_gate("rngclk", NULL, PRCMU_RNGCLK, CLK_IS_ROOT); - clk_register_clkdev(clk, NULL, "rngclk"); - - clk = clk_reg_prcmu_gate("uiccclk", NULL, PRCMU_UICCCLK, CLK_IS_ROOT); - clk_register_clkdev(clk, NULL, "uicc"); - - /* - * FIXME: The MTU clocks might need some kind of "parent muxed join" - * and these have no K-clocks. For now, we ignore the missing - * connection to the corresponding P-clocks, p6_mtu0_clk and - * p6_mtu1_clk. Instead timclk is used which is the valid parent. - */ - clk = clk_reg_prcmu_gate("timclk", NULL, PRCMU_TIMCLK, CLK_IS_ROOT); - clk_register_clkdev(clk, NULL, "mtu0"); - clk_register_clkdev(clk, NULL, "mtu1"); - - clk = clk_reg_prcmu_gate("sdmmcclk", NULL, PRCMU_SDMMCCLK, CLK_IS_ROOT); - clk_register_clkdev(clk, NULL, "sdmmc"); - - - clk = clk_reg_prcmu_scalable("dsi_pll", "hdmiclk", - PRCMU_PLLDSI, 0, CLK_SET_RATE_GATE); - clk_register_clkdev(clk, "dsihs2", "mcde"); - clk_register_clkdev(clk, "dsihs2", "dsilink.2"); - - - clk = clk_reg_prcmu_scalable("dsi0clk", "dsi_pll", - PRCMU_DSI0CLK, 0, CLK_SET_RATE_GATE); - clk_register_clkdev(clk, "dsihs0", "mcde"); - clk_register_clkdev(clk, "dsihs0", "dsilink.0"); - - clk = clk_reg_prcmu_scalable("dsi1clk", "dsi_pll", - PRCMU_DSI1CLK, 0, CLK_SET_RATE_GATE); - clk_register_clkdev(clk, "dsihs1", "mcde"); - clk_register_clkdev(clk, "dsihs1", "dsilink.1"); - - clk = clk_reg_prcmu_scalable("dsi0escclk", "tvclk", - PRCMU_DSI0ESCCLK, 0, CLK_SET_RATE_GATE); - clk_register_clkdev(clk, "dsilp0", "dsilink.0"); - clk_register_clkdev(clk, "dsilp0", "mcde"); - - clk = clk_reg_prcmu_scalable("dsi1escclk", "tvclk", - PRCMU_DSI1ESCCLK, 0, CLK_SET_RATE_GATE); - clk_register_clkdev(clk, "dsilp1", "dsilink.1"); - clk_register_clkdev(clk, "dsilp1", "mcde"); - - clk = clk_reg_prcmu_scalable("dsi2escclk", "tvclk", - PRCMU_DSI2ESCCLK, 0, CLK_SET_RATE_GATE); - clk_register_clkdev(clk, "dsilp2", "dsilink.2"); - clk_register_clkdev(clk, "dsilp2", "mcde"); - - clk = clk_reg_prcmu_rate("smp_twd", NULL, PRCMU_ARMSS, - CLK_IS_ROOT|CLK_GET_RATE_NOCACHE| - CLK_IGNORE_UNUSED); - clk_register_clkdev(clk, NULL, "smp_twd"); - - /* - * FIXME: Add special handled PRCMU clocks here: - * 1. clk_arm, use PRCMU_ARMCLK. - * 2. clkout0yuv, use PRCMU as parent + need regulator + pinctrl. - * 3. ab9540_clkout1yuv, see clkout0yuv - */ - - /* PRCC P-clocks */ - clk = clk_reg_prcc_pclk("p1_pclk0", "per1clk", U8500_CLKRST1_BASE, - BIT(0), 0); - clk_register_clkdev(clk, "apb_pclk", "uart0"); - - clk = clk_reg_prcc_pclk("p1_pclk1", "per1clk", U8500_CLKRST1_BASE, - BIT(1), 0); - clk_register_clkdev(clk, "apb_pclk", "uart1"); - - clk = clk_reg_prcc_pclk("p1_pclk2", "per1clk", U8500_CLKRST1_BASE, - BIT(2), 0); - clk = clk_reg_prcc_pclk("p1_pclk3", "per1clk", U8500_CLKRST1_BASE, - BIT(3), 0); - clk = clk_reg_prcc_pclk("p1_pclk4", "per1clk", U8500_CLKRST1_BASE, - BIT(4), 0); - - clk = clk_reg_prcc_pclk("p1_pclk5", "per1clk", U8500_CLKRST1_BASE, - BIT(5), 0); - clk_register_clkdev(clk, "apb_pclk", "sdi0"); - - clk = clk_reg_prcc_pclk("p1_pclk6", "per1clk", U8500_CLKRST1_BASE, - BIT(6), 0); - - clk = clk_reg_prcc_pclk("p1_pclk7", "per1clk", U8500_CLKRST1_BASE, - BIT(7), 0); - clk_register_clkdev(clk, NULL, "spi3"); - - clk = clk_reg_prcc_pclk("p1_pclk8", "per1clk", U8500_CLKRST1_BASE, - BIT(8), 0); - - clk = clk_reg_prcc_pclk("p1_pclk9", "per1clk", U8500_CLKRST1_BASE, - BIT(9), 0); - clk_register_clkdev(clk, NULL, "gpio.0"); - clk_register_clkdev(clk, NULL, "gpio.1"); - clk_register_clkdev(clk, NULL, "gpioblock0"); - - clk = clk_reg_prcc_pclk("p1_pclk10", "per1clk", U8500_CLKRST1_BASE, - BIT(10), 0); - clk = clk_reg_prcc_pclk("p1_pclk11", "per1clk", U8500_CLKRST1_BASE, - BIT(11), 0); - - clk = clk_reg_prcc_pclk("p2_pclk0", "per2clk", U8500_CLKRST2_BASE, - BIT(0), 0); - - clk = clk_reg_prcc_pclk("p2_pclk1", "per2clk", U8500_CLKRST2_BASE, - BIT(1), 0); - clk_register_clkdev(clk, NULL, "spi2"); - - clk = clk_reg_prcc_pclk("p2_pclk2", "per2clk", U8500_CLKRST2_BASE, - BIT(2), 0); - clk_register_clkdev(clk, NULL, "spi1"); - - clk = clk_reg_prcc_pclk("p2_pclk3", "per2clk", U8500_CLKRST2_BASE, - BIT(3), 0); - clk_register_clkdev(clk, NULL, "pwl"); - - clk = clk_reg_prcc_pclk("p2_pclk4", "per2clk", U8500_CLKRST2_BASE, - BIT(4), 0); - clk_register_clkdev(clk, "apb_pclk", "sdi4"); - - clk = clk_reg_prcc_pclk("p2_pclk5", "per2clk", U8500_CLKRST2_BASE, - BIT(5), 0); - - clk = clk_reg_prcc_pclk("p2_pclk6", "per2clk", U8500_CLKRST2_BASE, - BIT(6), 0); - clk_register_clkdev(clk, "apb_pclk", "sdi1"); - - - clk = clk_reg_prcc_pclk("p2_pclk7", "per2clk", U8500_CLKRST2_BASE, - BIT(7), 0); - clk_register_clkdev(clk, "apb_pclk", "sdi3"); - - clk = clk_reg_prcc_pclk("p2_pclk8", "per2clk", U8500_CLKRST2_BASE, - BIT(8), 0); - clk_register_clkdev(clk, NULL, "spi0"); - - clk = clk_reg_prcc_pclk("p2_pclk9", "per2clk", U8500_CLKRST2_BASE, - BIT(9), 0); - clk_register_clkdev(clk, "hsir_hclk", "ste_hsi.0"); - - clk = clk_reg_prcc_pclk("p2_pclk10", "per2clk", U8500_CLKRST2_BASE, - BIT(10), 0); - clk_register_clkdev(clk, "hsit_hclk", "ste_hsi.0"); - - clk = clk_reg_prcc_pclk("p2_pclk11", "per2clk", U8500_CLKRST2_BASE, - BIT(11), 0); - clk_register_clkdev(clk, NULL, "gpio.6"); - clk_register_clkdev(clk, NULL, "gpio.7"); - clk_register_clkdev(clk, NULL, "gpioblock1"); - - clk = clk_reg_prcc_pclk("p2_pclk12", "per2clk", U8500_CLKRST2_BASE, - BIT(11), 0); - - clk = clk_reg_prcc_pclk("p3_pclk0", "per3clk", U8500_CLKRST3_BASE, - BIT(0), 0); - clk_register_clkdev(clk, NULL, "fsmc"); - - clk = clk_reg_prcc_pclk("p3_pclk1", "per3clk", U8500_CLKRST3_BASE, - BIT(1), 0); - clk = clk_reg_prcc_pclk("p3_pclk2", "per3clk", U8500_CLKRST3_BASE, - BIT(2), 0); - clk = clk_reg_prcc_pclk("p3_pclk3", "per3clk", U8500_CLKRST3_BASE, - BIT(3), 0); - - clk = clk_reg_prcc_pclk("p3_pclk4", "per3clk", U8500_CLKRST3_BASE, - BIT(4), 0); - clk_register_clkdev(clk, "apb_pclk", "sdi2"); - - clk = clk_reg_prcc_pclk("p3_pclk5", "per3clk", U8500_CLKRST3_BASE, - BIT(5), 0); - - clk = clk_reg_prcc_pclk("p3_pclk6", "per3clk", U8500_CLKRST3_BASE, - BIT(6), 0); - clk_register_clkdev(clk, "apb_pclk", "uart2"); - - clk = clk_reg_prcc_pclk("p3_pclk7", "per3clk", U8500_CLKRST3_BASE, - BIT(7), 0); - clk_register_clkdev(clk, "apb_pclk", "sdi5"); - - clk = clk_reg_prcc_pclk("p3_pclk8", "per3clk", U8500_CLKRST3_BASE, - BIT(8), 0); - clk_register_clkdev(clk, NULL, "gpio.2"); - clk_register_clkdev(clk, NULL, "gpio.3"); - clk_register_clkdev(clk, NULL, "gpio.4"); - clk_register_clkdev(clk, NULL, "gpio.5"); - clk_register_clkdev(clk, NULL, "gpioblock2"); - - clk = clk_reg_prcc_pclk("p5_pclk0", "per5clk", U8500_CLKRST5_BASE, - BIT(0), 0); - clk_register_clkdev(clk, "usb", "musb-ux500.0"); - - clk = clk_reg_prcc_pclk("p5_pclk1", "per5clk", U8500_CLKRST5_BASE, - BIT(1), 0); - clk_register_clkdev(clk, NULL, "gpio.8"); - clk_register_clkdev(clk, NULL, "gpioblock3"); - - clk = clk_reg_prcc_pclk("p6_pclk0", "per6clk", U8500_CLKRST6_BASE, - BIT(0), 0); - - clk = clk_reg_prcc_pclk("p6_pclk1", "per6clk", U8500_CLKRST6_BASE, - BIT(1), 0); - clk_register_clkdev(clk, NULL, "cryp0"); - clk_register_clkdev(clk, NULL, "cryp1"); - - clk = clk_reg_prcc_pclk("p6_pclk2", "per6clk", U8500_CLKRST6_BASE, - BIT(2), 0); - clk_register_clkdev(clk, NULL, "hash0"); - - clk = clk_reg_prcc_pclk("p6_pclk3", "per6clk", U8500_CLKRST6_BASE, - BIT(3), 0); - clk_register_clkdev(clk, NULL, "pka"); - - clk = clk_reg_prcc_pclk("p6_pclk4", "per6clk", U8500_CLKRST6_BASE, - BIT(4), 0); - clk_register_clkdev(clk, NULL, "hash1"); - - clk = clk_reg_prcc_pclk("p6_pclk5", "per6clk", U8500_CLKRST6_BASE, - BIT(5), 0); - clk_register_clkdev(clk, NULL, "cfgreg"); - - clk = clk_reg_prcc_pclk("p6_pclk6", "per6clk", U8500_CLKRST6_BASE, - BIT(6), 0); - clk = clk_reg_prcc_pclk("p6_pclk7", "per6clk", U8500_CLKRST6_BASE, - BIT(7), 0); - - /* PRCC K-clocks - * - * FIXME: Some drivers requires PERPIH[n| to be automatically enabled - * by enabling just the K-clock, even if it is not a valid parent to - * the K-clock. Until drivers get fixed we might need some kind of - * "parent muxed join". - */ - - /* Periph1 */ - clk = clk_reg_prcc_kclk("p1_uart0_kclk", "uartclk", - U8500_CLKRST1_BASE, BIT(0), CLK_SET_RATE_GATE); - clk_register_clkdev(clk, NULL, "uart0"); - - clk = clk_reg_prcc_kclk("p1_uart1_kclk", "uartclk", - U8500_CLKRST1_BASE, BIT(1), CLK_SET_RATE_GATE); - clk_register_clkdev(clk, NULL, "uart1"); - - clk = clk_reg_prcc_kclk("p1_i2c1_kclk", "i2cclk", - U8500_CLKRST1_BASE, BIT(2), CLK_SET_RATE_GATE); - clk = clk_reg_prcc_kclk("p1_msp0_kclk", "msp02clk", - U8500_CLKRST1_BASE, BIT(3), CLK_SET_RATE_GATE); - clk = clk_reg_prcc_kclk("p1_msp1_kclk", "msp1clk", - U8500_CLKRST1_BASE, BIT(4), CLK_SET_RATE_GATE); - - clk = clk_reg_prcc_kclk("p1_sdi0_kclk", "sdmmcclk", - U8500_CLKRST1_BASE, BIT(5), CLK_SET_RATE_GATE); - clk_register_clkdev(clk, NULL, "sdi0"); - - clk = clk_reg_prcc_kclk("p1_i2c2_kclk", "i2cclk", - U8500_CLKRST1_BASE, BIT(6), CLK_SET_RATE_GATE); - clk = clk_reg_prcc_kclk("p1_slimbus0_kclk", "slimclk", - U8500_CLKRST1_BASE, BIT(3), CLK_SET_RATE_GATE); - /* FIXME: Redefinition of BIT(3). */ - clk = clk_reg_prcc_kclk("p1_i2c4_kclk", "i2cclk", - U8500_CLKRST1_BASE, BIT(9), CLK_SET_RATE_GATE); - clk = clk_reg_prcc_kclk("p1_msp3_kclk", "msp1clk", - U8500_CLKRST1_BASE, BIT(10), CLK_SET_RATE_GATE); - - /* Periph2 */ - clk = clk_reg_prcc_kclk("p2_i2c3_kclk", "i2cclk", - U8500_CLKRST2_BASE, BIT(0), CLK_SET_RATE_GATE); - - clk = clk_reg_prcc_kclk("p2_sdi4_kclk", "sdmmcclk", - U8500_CLKRST2_BASE, BIT(2), CLK_SET_RATE_GATE); - clk_register_clkdev(clk, NULL, "sdi4"); - - clk = clk_reg_prcc_kclk("p2_msp2_kclk", "msp02clk", - U8500_CLKRST2_BASE, BIT(3), CLK_SET_RATE_GATE); - - clk = clk_reg_prcc_kclk("p2_sdi1_kclk", "sdmmcclk", - U8500_CLKRST2_BASE, BIT(4), CLK_SET_RATE_GATE); - clk_register_clkdev(clk, NULL, "sdi1"); - - clk = clk_reg_prcc_kclk("p2_sdi3_kclk", "sdmmcclk", - U8500_CLKRST2_BASE, BIT(5), CLK_SET_RATE_GATE); - clk_register_clkdev(clk, NULL, "sdi3"); - - /* Note that rate is received from parent. */ - clk = clk_reg_prcc_kclk("p2_ssirx_kclk", "hsirxclk", - U8500_CLKRST2_BASE, BIT(6), - CLK_SET_RATE_GATE|CLK_SET_RATE_PARENT); - clk = clk_reg_prcc_kclk("p2_ssitx_kclk", "hsitxclk", - U8500_CLKRST2_BASE, BIT(7), - CLK_SET_RATE_GATE|CLK_SET_RATE_PARENT); - - /* Periph3 */ - clk = clk_reg_prcc_kclk("p3_ssp0_kclk", "sspclk", - U8500_CLKRST3_BASE, BIT(1), CLK_SET_RATE_GATE); - clk = clk_reg_prcc_kclk("p3_ssp1_kclk", "sspclk", - U8500_CLKRST3_BASE, BIT(2), CLK_SET_RATE_GATE); - clk = clk_reg_prcc_kclk("p3_i2c0_kclk", "i2cclk", - U8500_CLKRST3_BASE, BIT(3), CLK_SET_RATE_GATE); - - clk = clk_reg_prcc_kclk("p3_sdi2_kclk", "sdmmcclk", - U8500_CLKRST3_BASE, BIT(4), CLK_SET_RATE_GATE); - clk_register_clkdev(clk, NULL, "sdi2"); - - clk = clk_reg_prcc_kclk("p3_ske_kclk", "rtc32k", - U8500_CLKRST3_BASE, BIT(5), CLK_SET_RATE_GATE); - - clk = clk_reg_prcc_kclk("p3_uart2_kclk", "uartclk", - U8500_CLKRST3_BASE, BIT(6), CLK_SET_RATE_GATE); - clk_register_clkdev(clk, NULL, "uart2"); - - clk = clk_reg_prcc_kclk("p3_sdi5_kclk", "sdmmcclk", - U8500_CLKRST3_BASE, BIT(7), CLK_SET_RATE_GATE); - clk_register_clkdev(clk, NULL, "sdi5"); - - /* Periph6 */ - clk = clk_reg_prcc_kclk("p3_rng_kclk", "rngclk", - U8500_CLKRST6_BASE, BIT(0), CLK_SET_RATE_GATE); - -} diff --git a/trunk/drivers/clk/ux500/u8540_clk.c b/trunk/drivers/clk/ux500/u8540_clk.c deleted file mode 100644 index 10adfd2ead21..000000000000 --- a/trunk/drivers/clk/ux500/u8540_clk.c +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Clock definitions for u8540 platform. - * - * Copyright (C) 2012 ST-Ericsson SA - * Author: Ulf Hansson - * - * License terms: GNU General Public License (GPL) version 2 - */ - -#include -#include -#include -#include -#include - -#include "clk.h" - -void u8540_clk_init(void) -{ - /* register clocks here */ -} diff --git a/trunk/drivers/clk/ux500/u9540_clk.c b/trunk/drivers/clk/ux500/u9540_clk.c deleted file mode 100644 index dbc0191e16c8..000000000000 --- a/trunk/drivers/clk/ux500/u9540_clk.c +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Clock definitions for u9540 platform. - * - * Copyright (C) 2012 ST-Ericsson SA - * Author: Ulf Hansson - * - * License terms: GNU General Public License (GPL) version 2 - */ - -#include -#include -#include -#include -#include - -#include "clk.h" - -void u9540_clk_init(void) -{ - /* register clocks here */ -} diff --git a/trunk/drivers/clk/versatile/Makefile b/trunk/drivers/clk/versatile/Makefile index c0a0f6478798..50cf6a2ee693 100644 --- a/trunk/drivers/clk/versatile/Makefile +++ b/trunk/drivers/clk/versatile/Makefile @@ -1,4 +1,3 @@ # Makefile for Versatile-specific clocks obj-$(CONFIG_ICST) += clk-icst.o obj-$(CONFIG_ARCH_INTEGRATOR) += clk-integrator.o -obj-$(CONFIG_ARCH_REALVIEW) += clk-realview.o diff --git a/trunk/drivers/clk/versatile/clk-realview.c b/trunk/drivers/clk/versatile/clk-realview.c deleted file mode 100644 index e21a99cef378..000000000000 --- a/trunk/drivers/clk/versatile/clk-realview.c +++ /dev/null @@ -1,114 +0,0 @@ -#include -#include -#include -#include -#include - -#include -#include - -#include "clk-icst.h" - -/* - * Implementation of the ARM RealView clock trees. - */ - -static void __iomem *sys_lock; -static void __iomem *sys_vcoreg; - -/** - * realview_oscvco_get() - get ICST OSC settings for the RealView - */ -static struct icst_vco realview_oscvco_get(void) -{ - u32 val; - struct icst_vco vco; - - val = readl(sys_vcoreg); - vco.v = val & 0x1ff; - vco.r = (val >> 9) & 0x7f; - vco.s = (val >> 16) & 03; - return vco; -} - -static void realview_oscvco_set(struct icst_vco vco) -{ - u32 val; - - val = readl(sys_vcoreg) & ~0x7ffff; - val |= vco.v | (vco.r << 9) | (vco.s << 16); - - /* This magic unlocks the CM VCO so it can be controlled */ - writel(0xa05f, sys_lock); - writel(val, sys_vcoreg); - /* This locks the CM again */ - writel(0, sys_lock); -} - -static const struct icst_params realview_oscvco_params = { - .ref = 24000000, - .vco_max = ICST307_VCO_MAX, - .vco_min = ICST307_VCO_MIN, - .vd_min = 4 + 8, - .vd_max = 511 + 8, - .rd_min = 1 + 2, - .rd_max = 127 + 2, - .s2div = icst307_s2div, - .idx2s = icst307_idx2s, -}; - -static const struct clk_icst_desc __initdata realview_icst_desc = { - .params = &realview_oscvco_params, - .getvco = realview_oscvco_get, - .setvco = realview_oscvco_set, -}; - -/* - * realview_clk_init() - set up the RealView clock tree - */ -void __init realview_clk_init(void __iomem *sysbase, bool is_pb1176) -{ - struct clk *clk; - - sys_lock = sysbase + REALVIEW_SYS_LOCK_OFFSET; - if (is_pb1176) - sys_vcoreg = sysbase + REALVIEW_SYS_OSC0_OFFSET; - else - sys_vcoreg = sysbase + REALVIEW_SYS_OSC4_OFFSET; - - - /* APB clock dummy */ - clk = clk_register_fixed_rate(NULL, "apb_pclk", NULL, CLK_IS_ROOT, 0); - clk_register_clkdev(clk, "apb_pclk", NULL); - - /* 24 MHz clock */ - clk = clk_register_fixed_rate(NULL, "clk24mhz", NULL, CLK_IS_ROOT, - 24000000); - clk_register_clkdev(clk, NULL, "dev:uart0"); - clk_register_clkdev(clk, NULL, "dev:uart1"); - clk_register_clkdev(clk, NULL, "dev:uart2"); - clk_register_clkdev(clk, NULL, "fpga:kmi0"); - clk_register_clkdev(clk, NULL, "fpga:kmi1"); - clk_register_clkdev(clk, NULL, "fpga:mmc0"); - clk_register_clkdev(clk, NULL, "dev:ssp0"); - if (is_pb1176) { - /* - * UART3 is on the dev chip in PB1176 - * UART4 only exists in PB1176 - */ - clk_register_clkdev(clk, NULL, "dev:uart3"); - clk_register_clkdev(clk, NULL, "dev:uart4"); - } else - clk_register_clkdev(clk, NULL, "fpga:uart3"); - - - /* 1 MHz clock */ - clk = clk_register_fixed_rate(NULL, "clk1mhz", NULL, CLK_IS_ROOT, - 1000000); - clk_register_clkdev(clk, NULL, "sp804"); - - /* ICST VCO clock */ - clk = icst_clk_register(NULL, &realview_icst_desc); - clk_register_clkdev(clk, NULL, "dev:clcd"); - clk_register_clkdev(clk, NULL, "issp:clcd"); -} diff --git a/trunk/drivers/clocksource/Kconfig b/trunk/drivers/clocksource/Kconfig index 6a78073c3808..d53cd0afc200 100644 --- a/trunk/drivers/clocksource/Kconfig +++ b/trunk/drivers/clocksource/Kconfig @@ -35,8 +35,3 @@ config CLKSRC_DBX500_PRCMU_SCHED_CLOCK default y help Use the always on PRCMU Timer as sched_clock - -config CLKSRC_ARM_GENERIC - def_bool y if ARM64 - help - This option enables support for the ARM generic timer. diff --git a/trunk/drivers/clocksource/Makefile b/trunk/drivers/clocksource/Makefile index 65919901a301..b65d0c56ab35 100644 --- a/trunk/drivers/clocksource/Makefile +++ b/trunk/drivers/clocksource/Makefile @@ -13,4 +13,3 @@ obj-$(CONFIG_DW_APB_TIMER) += dw_apb_timer.o obj-$(CONFIG_DW_APB_TIMER_OF) += dw_apb_timer_of.o obj-$(CONFIG_CLKSRC_DBX500_PRCMU) += clksrc-dbx500-prcmu.o obj-$(CONFIG_ARMADA_370_XP_TIMER) += time-armada-370-xp.o -obj-$(CONFIG_CLKSRC_ARM_GENERIC) += arm_generic.o diff --git a/trunk/drivers/clocksource/arm_generic.c b/trunk/drivers/clocksource/arm_generic.c deleted file mode 100644 index c4d9f9566c64..000000000000 --- a/trunk/drivers/clocksource/arm_generic.c +++ /dev/null @@ -1,232 +0,0 @@ -/* - * Generic timers support - * - * Copyright (C) 2012 ARM Ltd. - * Author: Marc Zyngier - * - * 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 -#include -#include -#include -#include -#include -#include - -#include - -#include - -static u32 arch_timer_rate; -static u64 sched_clock_mult __read_mostly; -static DEFINE_PER_CPU(struct clock_event_device, arch_timer_evt); -static int arch_timer_ppi; - -static irqreturn_t arch_timer_handle_irq(int irq, void *dev_id) -{ - struct clock_event_device *evt = dev_id; - unsigned long ctrl; - - ctrl = arch_timer_reg_read(ARCH_TIMER_REG_CTRL); - if (ctrl & ARCH_TIMER_CTRL_ISTATUS) { - ctrl |= ARCH_TIMER_CTRL_IMASK; - arch_timer_reg_write(ARCH_TIMER_REG_CTRL, ctrl); - evt->event_handler(evt); - return IRQ_HANDLED; - } - - return IRQ_NONE; -} - -static void arch_timer_stop(void) -{ - unsigned long ctrl; - - ctrl = arch_timer_reg_read(ARCH_TIMER_REG_CTRL); - ctrl &= ~ARCH_TIMER_CTRL_ENABLE; - arch_timer_reg_write(ARCH_TIMER_REG_CTRL, ctrl); -} - -static void arch_timer_set_mode(enum clock_event_mode mode, - struct clock_event_device *clk) -{ - switch (mode) { - case CLOCK_EVT_MODE_UNUSED: - case CLOCK_EVT_MODE_SHUTDOWN: - arch_timer_stop(); - break; - default: - break; - } -} - -static int arch_timer_set_next_event(unsigned long evt, - struct clock_event_device *unused) -{ - unsigned long ctrl; - - ctrl = arch_timer_reg_read(ARCH_TIMER_REG_CTRL); - ctrl |= ARCH_TIMER_CTRL_ENABLE; - ctrl &= ~ARCH_TIMER_CTRL_IMASK; - - arch_timer_reg_write(ARCH_TIMER_REG_TVAL, evt); - arch_timer_reg_write(ARCH_TIMER_REG_CTRL, ctrl); - - return 0; -} - -static void __cpuinit arch_timer_setup(struct clock_event_device *clk) -{ - /* Let's make sure the timer is off before doing anything else */ - arch_timer_stop(); - - clk->features = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_C3STOP; - clk->name = "arch_sys_timer"; - clk->rating = 400; - clk->set_mode = arch_timer_set_mode; - clk->set_next_event = arch_timer_set_next_event; - clk->irq = arch_timer_ppi; - clk->cpumask = cpumask_of(smp_processor_id()); - - clockevents_config_and_register(clk, arch_timer_rate, - 0xf, 0x7fffffff); - - enable_percpu_irq(clk->irq, 0); - - /* Ensure the physical counter is visible to userspace for the vDSO. */ - arch_counter_enable_user_access(); -} - -static void __init arch_timer_calibrate(void) -{ - if (arch_timer_rate == 0) { - arch_timer_reg_write(ARCH_TIMER_REG_CTRL, 0); - arch_timer_rate = arch_timer_reg_read(ARCH_TIMER_REG_FREQ); - - /* Check the timer frequency. */ - if (arch_timer_rate == 0) - panic("Architected timer frequency is set to zero.\n" - "You must set this in your .dts file\n"); - } - - /* Cache the sched_clock multiplier to save a divide in the hot path. */ - - sched_clock_mult = NSEC_PER_SEC / arch_timer_rate; - - pr_info("Architected local timer running at %u.%02uMHz.\n", - arch_timer_rate / 1000000, (arch_timer_rate / 10000) % 100); -} - -static cycle_t arch_counter_read(struct clocksource *cs) -{ - return arch_counter_get_cntpct(); -} - -static struct clocksource clocksource_counter = { - .name = "arch_sys_counter", - .rating = 400, - .read = arch_counter_read, - .mask = CLOCKSOURCE_MASK(56), - .flags = (CLOCK_SOURCE_IS_CONTINUOUS | CLOCK_SOURCE_VALID_FOR_HRES), -}; - -int read_current_timer(unsigned long *timer_value) -{ - *timer_value = arch_counter_get_cntpct(); - return 0; -} - -unsigned long long notrace sched_clock(void) -{ - return arch_counter_get_cntvct() * sched_clock_mult; -} - -static int __cpuinit arch_timer_cpu_notify(struct notifier_block *self, - unsigned long action, void *hcpu) -{ - int cpu = (long)hcpu; - struct clock_event_device *clk = per_cpu_ptr(&arch_timer_evt, cpu); - - switch(action) { - case CPU_STARTING: - case CPU_STARTING_FROZEN: - arch_timer_setup(clk); - break; - - case CPU_DYING: - case CPU_DYING_FROZEN: - pr_debug("arch_timer_teardown disable IRQ%d cpu #%d\n", - clk->irq, cpu); - disable_percpu_irq(clk->irq); - arch_timer_set_mode(CLOCK_EVT_MODE_UNUSED, clk); - break; - } - - return NOTIFY_OK; -} - -static struct notifier_block __cpuinitdata arch_timer_cpu_nb = { - .notifier_call = arch_timer_cpu_notify, -}; - -static const struct of_device_id arch_timer_of_match[] __initconst = { - { .compatible = "arm,armv8-timer" }, - {}, -}; - -int __init arm_generic_timer_init(void) -{ - struct device_node *np; - int err; - u32 freq; - - np = of_find_matching_node(NULL, arch_timer_of_match); - if (!np) { - pr_err("arch_timer: can't find DT node\n"); - return -ENODEV; - } - - /* Try to determine the frequency from the device tree or CNTFRQ */ - if (!of_property_read_u32(np, "clock-frequency", &freq)) - arch_timer_rate = freq; - arch_timer_calibrate(); - - arch_timer_ppi = irq_of_parse_and_map(np, 0); - pr_info("arch_timer: found %s irq %d\n", np->name, arch_timer_ppi); - - err = request_percpu_irq(arch_timer_ppi, arch_timer_handle_irq, - np->name, &arch_timer_evt); - if (err) { - pr_err("arch_timer: can't register interrupt %d (%d)\n", - arch_timer_ppi, err); - return err; - } - - clocksource_register_hz(&clocksource_counter, arch_timer_rate); - - /* Calibrate the delay loop directly */ - lpj_fine = arch_timer_rate / HZ; - - /* Immediately configure the timer on the boot CPU */ - arch_timer_setup(per_cpu_ptr(&arch_timer_evt, smp_processor_id())); - - register_cpu_notifier(&arch_timer_cpu_nb); - - return 0; -} diff --git a/trunk/drivers/clocksource/cs5535-clockevt.c b/trunk/drivers/clocksource/cs5535-clockevt.c index d9279385304d..540795cd0760 100644 --- a/trunk/drivers/clocksource/cs5535-clockevt.c +++ b/trunk/drivers/clocksource/cs5535-clockevt.c @@ -53,7 +53,7 @@ static struct cs5535_mfgpt_timer *cs5535_event_clock; #define MFGPT_PERIODIC (MFGPT_HZ / HZ) /* - * The MFGPT timers on the CS5536 provide us with suitable timers to use + * The MFPGT timers on the CS5536 provide us with suitable timers to use * as clock event sources - not as good as a HPET or APIC, but certainly * better than the PIT. This isn't a general purpose MFGPT driver, but * a simplified one designed specifically to act as a clock event source. @@ -144,7 +144,7 @@ static int __init cs5535_mfgpt_init(void) timer = cs5535_mfgpt_alloc_timer(MFGPT_TIMER_ANY, MFGPT_DOMAIN_WORKING); if (!timer) { - printk(KERN_ERR DRV_NAME ": Could not allocate MFGPT timer\n"); + printk(KERN_ERR DRV_NAME ": Could not allocate MFPGT timer\n"); return -ENODEV; } cs5535_event_clock = timer; diff --git a/trunk/drivers/cpufreq/omap-cpufreq.c b/trunk/drivers/cpufreq/omap-cpufreq.c index b47034e650a5..17fa04d08be9 100644 --- a/trunk/drivers/cpufreq/omap-cpufreq.c +++ b/trunk/drivers/cpufreq/omap-cpufreq.c @@ -218,7 +218,7 @@ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy) policy->cur = policy->min = policy->max = omap_getspeed(policy->cpu); - if (!freq_table) + if (atomic_inc_return(&freq_table_users) == 1) result = opp_init_cpufreq_table(mpu_dev, &freq_table); if (result) { @@ -227,8 +227,6 @@ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy) goto fail_ck; } - atomic_inc_return(&freq_table_users); - result = cpufreq_frequency_table_cpuinfo(policy, freq_table); if (result) goto fail_table; diff --git a/trunk/drivers/cpufreq/pcc-cpufreq.c b/trunk/drivers/cpufreq/pcc-cpufreq.c index 503996a94a6a..cdc02ac8f41a 100644 --- a/trunk/drivers/cpufreq/pcc-cpufreq.c +++ b/trunk/drivers/cpufreq/pcc-cpufreq.c @@ -454,7 +454,6 @@ static int __init pcc_cpufreq_probe(void) mem_resource->address_length); if (pcch_virt_addr == NULL) { pr_debug("probe: could not map shared mem region\n"); - ret = -ENOMEM; goto out_free; } pcch_hdr = pcch_virt_addr; diff --git a/trunk/drivers/cpufreq/powernow-k8.c b/trunk/drivers/cpufreq/powernow-k8.c index 1a40935c85fd..c0e816468e30 100644 --- a/trunk/drivers/cpufreq/powernow-k8.c +++ b/trunk/drivers/cpufreq/powernow-k8.c @@ -35,6 +35,7 @@ #include #include #include +#include /* for current / set_cpus_allowed() */ #include #include @@ -1138,23 +1139,16 @@ static int transition_frequency_pstate(struct powernow_k8_data *data, return res; } -struct powernowk8_target_arg { - struct cpufreq_policy *pol; - unsigned targfreq; - unsigned relation; -}; - -static long powernowk8_target_fn(void *arg) +/* Driver entry point to switch to the target frequency */ +static int powernowk8_target(struct cpufreq_policy *pol, + unsigned targfreq, unsigned relation) { - struct powernowk8_target_arg *pta = arg; - struct cpufreq_policy *pol = pta->pol; - unsigned targfreq = pta->targfreq; - unsigned relation = pta->relation; + cpumask_var_t oldmask; struct powernow_k8_data *data = per_cpu(powernow_data, pol->cpu); u32 checkfid; u32 checkvid; unsigned int newstate; - int ret; + int ret = -EIO; if (!data) return -EINVAL; @@ -1162,16 +1156,29 @@ static long powernowk8_target_fn(void *arg) checkfid = data->currfid; checkvid = data->currvid; + /* only run on specific CPU from here on. */ + /* This is poor form: use a workqueue or smp_call_function_single */ + if (!alloc_cpumask_var(&oldmask, GFP_KERNEL)) + return -ENOMEM; + + cpumask_copy(oldmask, tsk_cpus_allowed(current)); + set_cpus_allowed_ptr(current, cpumask_of(pol->cpu)); + + if (smp_processor_id() != pol->cpu) { + printk(KERN_ERR PFX "limiting to cpu %u failed\n", pol->cpu); + goto err_out; + } + if (pending_bit_stuck()) { printk(KERN_ERR PFX "failing targ, change pending bit set\n"); - return -EIO; + goto err_out; } pr_debug("targ: cpu %d, %d kHz, min %d, max %d, relation %d\n", pol->cpu, targfreq, pol->min, pol->max, relation); if (query_current_values_with_pending_wait(data)) - return -EIO; + goto err_out; if (cpu_family != CPU_HW_PSTATE) { pr_debug("targ: curr fid 0x%x, vid 0x%x\n", @@ -1189,7 +1196,7 @@ static long powernowk8_target_fn(void *arg) if (cpufreq_frequency_table_target(pol, data->powernow_table, targfreq, relation, &newstate)) - return -EIO; + goto err_out; mutex_lock(&fidvid_mutex); @@ -1202,8 +1209,9 @@ static long powernowk8_target_fn(void *arg) ret = transition_frequency_fidvid(data, newstate); if (ret) { printk(KERN_ERR PFX "transition frequency failed\n"); + ret = 1; mutex_unlock(&fidvid_mutex); - return 1; + goto err_out; } mutex_unlock(&fidvid_mutex); @@ -1212,25 +1220,12 @@ static long powernowk8_target_fn(void *arg) data->powernow_table[newstate].index); else pol->cur = find_khz_freq_from_fid(data->currfid); + ret = 0; - return 0; -} - -/* Driver entry point to switch to the target frequency */ -static int powernowk8_target(struct cpufreq_policy *pol, - unsigned targfreq, unsigned relation) -{ - struct powernowk8_target_arg pta = { .pol = pol, .targfreq = targfreq, - .relation = relation }; - - /* - * Must run on @pol->cpu. cpufreq core is responsible for ensuring - * that we're bound to the current CPU and pol->cpu stays online. - */ - if (smp_processor_id() == pol->cpu) - return powernowk8_target_fn(&pta); - else - return work_on_cpu(pol->cpu, powernowk8_target_fn, &pta); +err_out: + set_cpus_allowed_ptr(current, oldmask); + free_cpumask_var(oldmask); + return ret; } /* Driver entry point to verify the policy and range of frequencies */ diff --git a/trunk/drivers/cpuidle/coupled.c b/trunk/drivers/cpuidle/coupled.c index 3265844839bf..2c9bf2692232 100644 --- a/trunk/drivers/cpuidle/coupled.c +++ b/trunk/drivers/cpuidle/coupled.c @@ -678,22 +678,10 @@ static int cpuidle_coupled_cpu_notify(struct notifier_block *nb, int cpu = (unsigned long)hcpu; struct cpuidle_device *dev; - switch (action & ~CPU_TASKS_FROZEN) { - case CPU_UP_PREPARE: - case CPU_DOWN_PREPARE: - case CPU_ONLINE: - case CPU_DEAD: - case CPU_UP_CANCELED: - case CPU_DOWN_FAILED: - break; - default: - return NOTIFY_OK; - } - mutex_lock(&cpuidle_lock); dev = per_cpu(cpuidle_devices, cpu); - if (!dev || !dev->coupled) + if (!dev->coupled) goto out; switch (action & ~CPU_TASKS_FROZEN) { diff --git a/trunk/drivers/crypto/caam/jr.c b/trunk/drivers/crypto/caam/jr.c index 93d14070141a..53c8c51d5881 100644 --- a/trunk/drivers/crypto/caam/jr.c +++ b/trunk/drivers/crypto/caam/jr.c @@ -63,7 +63,7 @@ static void caam_jr_dequeue(unsigned long devarg) head = ACCESS_ONCE(jrp->head); - spin_lock(&jrp->outlock); + spin_lock_bh(&jrp->outlock); sw_idx = tail = jrp->tail; hw_idx = jrp->out_ring_read_index; @@ -115,7 +115,7 @@ static void caam_jr_dequeue(unsigned long devarg) jrp->tail = tail; } - spin_unlock(&jrp->outlock); + spin_unlock_bh(&jrp->outlock); /* Finally, execute user's callback */ usercall(dev, userdesc, userstatus, userarg); @@ -236,14 +236,14 @@ int caam_jr_enqueue(struct device *dev, u32 *desc, return -EIO; } - spin_lock_bh(&jrp->inplock); + spin_lock(&jrp->inplock); head = jrp->head; tail = ACCESS_ONCE(jrp->tail); if (!rd_reg32(&jrp->rregs->inpring_avail) || CIRC_SPACE(head, tail, JOBR_DEPTH) <= 0) { - spin_unlock_bh(&jrp->inplock); + spin_unlock(&jrp->inplock); dma_unmap_single(dev, desc_dma, desc_size, DMA_TO_DEVICE); return -EBUSY; } @@ -265,7 +265,7 @@ int caam_jr_enqueue(struct device *dev, u32 *desc, wr_reg32(&jrp->rregs->inpring_jobadd, 1); - spin_unlock_bh(&jrp->inplock); + spin_unlock(&jrp->inplock); return 0; } diff --git a/trunk/drivers/crypto/caam/key_gen.c b/trunk/drivers/crypto/caam/key_gen.c index d216cd3cc569..002888185f17 100644 --- a/trunk/drivers/crypto/caam/key_gen.c +++ b/trunk/drivers/crypto/caam/key_gen.c @@ -120,4 +120,3 @@ u32 gen_split_key(struct device *jrdev, u8 *key_out, int split_key_len, return ret; } -EXPORT_SYMBOL(gen_split_key); diff --git a/trunk/drivers/crypto/hifn_795x.c b/trunk/drivers/crypto/hifn_795x.c index df14358d7fa1..c9c4befb5a8d 100644 --- a/trunk/drivers/crypto/hifn_795x.c +++ b/trunk/drivers/crypto/hifn_795x.c @@ -821,8 +821,8 @@ static int hifn_register_rng(struct hifn_device *dev) /* * We must wait at least 256 Pk_clk cycles between two reads of the rng. */ - dev->rng_wait_time = DIV_ROUND_UP_ULL(NSEC_PER_SEC, - dev->pk_clk_freq) * 256; + dev->rng_wait_time = DIV_ROUND_UP(NSEC_PER_SEC, dev->pk_clk_freq) * + 256; dev->rng.name = dev->name; dev->rng.data_present = hifn_rng_data_present, diff --git a/trunk/drivers/dma/at_hdmac.c b/trunk/drivers/dma/at_hdmac.c index 17d6958342e7..3934fcc4e00b 100644 --- a/trunk/drivers/dma/at_hdmac.c +++ b/trunk/drivers/dma/at_hdmac.c @@ -168,9 +168,9 @@ static void atc_desc_put(struct at_dma_chan *atchan, struct at_desc *desc) } /** - * atc_desc_chain - build chain adding a descriptor - * @first: address of first descriptor of the chain - * @prev: address of previous descriptor of the chain + * atc_desc_chain - build chain adding a descripor + * @first: address of first descripor of the chain + * @prev: address of previous descripor of the chain * @desc: descriptor to queue * * Called from prep_* functions @@ -661,7 +661,7 @@ atc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, flags); if (unlikely(!atslave || !sg_len)) { - dev_dbg(chan2dev(chan), "prep_slave_sg: sg length is zero!\n"); + dev_dbg(chan2dev(chan), "prep_dma_memcpy: length is zero!\n"); return NULL; } @@ -689,11 +689,6 @@ atc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, mem = sg_dma_address(sg); len = sg_dma_len(sg); - if (unlikely(!len)) { - dev_dbg(chan2dev(chan), - "prep_slave_sg: sg(%d) data length is zero\n", i); - goto err; - } mem_width = 2; if (unlikely(mem & 3 || len & 3)) mem_width = 0; @@ -729,11 +724,6 @@ atc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, mem = sg_dma_address(sg); len = sg_dma_len(sg); - if (unlikely(!len)) { - dev_dbg(chan2dev(chan), - "prep_slave_sg: sg(%d) data length is zero\n", i); - goto err; - } mem_width = 2; if (unlikely(mem & 3 || len & 3)) mem_width = 0; @@ -767,7 +757,6 @@ atc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, err_desc_get: dev_err(chan2dev(chan), "not enough descriptors available\n"); -err: atc_desc_put(atchan, first); return NULL; } @@ -796,7 +785,7 @@ atc_dma_cyclic_check_values(unsigned int reg_width, dma_addr_t buf_addr, } /** - * atc_dma_cyclic_fill_desc - Fill one period descriptor + * atc_dma_cyclic_fill_desc - Fill one period decriptor */ static int atc_dma_cyclic_fill_desc(struct dma_chan *chan, struct at_desc *desc, diff --git a/trunk/drivers/dma/ep93xx_dma.c b/trunk/drivers/dma/ep93xx_dma.c index bb02fd981afb..c64917ec313d 100644 --- a/trunk/drivers/dma/ep93xx_dma.c +++ b/trunk/drivers/dma/ep93xx_dma.c @@ -1118,7 +1118,7 @@ ep93xx_dma_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, * @chan: channel * @dma_addr: DMA mapped address of the buffer * @buf_len: length of the buffer (in bytes) - * @period_len: length of a single period + * @period_len: lenght of a single period * @dir: direction of the operation * @context: operation context (ignored) * diff --git a/trunk/drivers/dma/fsldma.c b/trunk/drivers/dma/fsldma.c index 094437b9d823..8f84761f98ba 100644 --- a/trunk/drivers/dma/fsldma.c +++ b/trunk/drivers/dma/fsldma.c @@ -1015,7 +1015,7 @@ static irqreturn_t fsldma_chan_irq(int irq, void *data) /* * Programming Error * The DMA_INTERRUPT async_tx is a NULL transfer, which will - * trigger a PE interrupt. + * triger a PE interrupt. */ if (stat & FSL_DMA_SR_PE) { chan_dbg(chan, "irq: Programming Error INT\n"); diff --git a/trunk/drivers/dma/imx-dma.c b/trunk/drivers/dma/imx-dma.c index 54f580bb993c..fcfeb3cd8d31 100644 --- a/trunk/drivers/dma/imx-dma.c +++ b/trunk/drivers/dma/imx-dma.c @@ -172,8 +172,7 @@ struct imxdma_engine { struct device_dma_parameters dma_parms; struct dma_device dma_device; void __iomem *base; - struct clk *dma_ahb; - struct clk *dma_ipg; + struct clk *dma_clk; spinlock_t lock; struct imx_dma_2d_config slots_2d[IMX_DMA_2D_SLOTS]; struct imxdma_channel channel[IMX_DMA_CHANNELS]; @@ -572,8 +571,8 @@ static void imxdma_tasklet(unsigned long data) if (desc->desc.callback) desc->desc.callback(desc->desc.callback_param); - /* If we are dealing with a cyclic descriptor, keep it on ld_active - * and dont mark the descriptor as complete. + /* If we are dealing with a cyclic descriptor keep it on ld_active + * and dont mark the descripor as complete. * Only in non-cyclic cases it would be marked as complete */ if (imxdma_chan_is_doing_cyclic(imxdmac)) @@ -977,20 +976,10 @@ static int __init imxdma_probe(struct platform_device *pdev) return 0; } - imxdma->dma_ipg = devm_clk_get(&pdev->dev, "ipg"); - if (IS_ERR(imxdma->dma_ipg)) { - ret = PTR_ERR(imxdma->dma_ipg); - goto err_clk; - } - - imxdma->dma_ahb = devm_clk_get(&pdev->dev, "ahb"); - if (IS_ERR(imxdma->dma_ahb)) { - ret = PTR_ERR(imxdma->dma_ahb); - goto err_clk; - } - - clk_prepare_enable(imxdma->dma_ipg); - clk_prepare_enable(imxdma->dma_ahb); + imxdma->dma_clk = clk_get(NULL, "dma"); + if (IS_ERR(imxdma->dma_clk)) + return PTR_ERR(imxdma->dma_clk); + clk_enable(imxdma->dma_clk); /* reset DMA module */ imx_dmav1_writel(imxdma, DCR_DRST, DMA_DCR); @@ -999,14 +988,16 @@ static int __init imxdma_probe(struct platform_device *pdev) ret = request_irq(MX1_DMA_INT, dma_irq_handler, 0, "DMA", imxdma); if (ret) { dev_warn(imxdma->dev, "Can't register IRQ for DMA\n"); - goto err_enable; + kfree(imxdma); + return ret; } ret = request_irq(MX1_DMA_ERR, imxdma_err_handler, 0, "DMA", imxdma); if (ret) { dev_warn(imxdma->dev, "Can't register ERRIRQ for DMA\n"); free_irq(MX1_DMA_INT, NULL); - goto err_enable; + kfree(imxdma); + return ret; } } @@ -1103,10 +1094,7 @@ static int __init imxdma_probe(struct platform_device *pdev) free_irq(MX1_DMA_INT, NULL); free_irq(MX1_DMA_ERR, NULL); } -err_enable: - clk_disable_unprepare(imxdma->dma_ipg); - clk_disable_unprepare(imxdma->dma_ahb); -err_clk: + kfree(imxdma); return ret; } @@ -1126,9 +1114,7 @@ static int __exit imxdma_remove(struct platform_device *pdev) free_irq(MX1_DMA_ERR, NULL); } - clk_disable_unprepare(imxdma->dma_ipg); - clk_disable_unprepare(imxdma->dma_ahb); - kfree(imxdma); + kfree(imxdma); return 0; } diff --git a/trunk/drivers/dma/intel_mid_dma.c b/trunk/drivers/dma/intel_mid_dma.c index 02b21d7d38e5..222e907bfaaa 100644 --- a/trunk/drivers/dma/intel_mid_dma.c +++ b/trunk/drivers/dma/intel_mid_dma.c @@ -427,7 +427,7 @@ DMA engine callback Functions*/ * intel_mid_dma_tx_submit - callback to submit DMA transaction * @tx: dma engine descriptor * - * Submit the DMA transaction for this descriptor, start if ch idle + * Submit the DMA trasaction for this descriptor, start if ch idle */ static dma_cookie_t intel_mid_dma_tx_submit(struct dma_async_tx_descriptor *tx) { diff --git a/trunk/drivers/dma/intel_mid_dma_regs.h b/trunk/drivers/dma/intel_mid_dma_regs.h index 17b42192ea58..1bfa9268feaf 100644 --- a/trunk/drivers/dma/intel_mid_dma_regs.h +++ b/trunk/drivers/dma/intel_mid_dma_regs.h @@ -168,9 +168,9 @@ union intel_mid_dma_cfg_hi { * @active_list: current active descriptors * @queue: current queued up descriptors * @free_list: current free descriptors - * @slave: dma slave structure - * @descs_allocated: total number of descriptors allocated - * @dma: dma device structure pointer + * @slave: dma slave struture + * @descs_allocated: total number of decsiptors allocated + * @dma: dma device struture pointer * @busy: bool representing if ch is busy (active txn) or not * @in_use: bool representing if ch is in use or not * @raw_tfr: raw trf interrupt received diff --git a/trunk/drivers/dma/ioat/hw.h b/trunk/drivers/dma/ioat/hw.h index d2ff3fda0b18..60e675455b6a 100644 --- a/trunk/drivers/dma/ioat/hw.h +++ b/trunk/drivers/dma/ioat/hw.h @@ -22,6 +22,7 @@ #define _IOAT_HW_H_ /* PCI Configuration Space Values */ +#define IOAT_PCI_VID 0x8086 #define IOAT_MMIO_BAR 0 /* CB device ID's */ @@ -30,6 +31,9 @@ #define IOAT_PCI_DID_SCNB 0x65FF #define IOAT_PCI_DID_SNB 0x402F +#define IOAT_PCI_RID 0x00 +#define IOAT_PCI_SVID 0x8086 +#define IOAT_PCI_SID 0x8086 #define IOAT_VER_1_2 0x12 /* Version 1.2 */ #define IOAT_VER_2_0 0x20 /* Version 2.0 */ #define IOAT_VER_3_0 0x30 /* Version 3.0 */ diff --git a/trunk/drivers/dma/pl330.c b/trunk/drivers/dma/pl330.c index 5d3bbcd279b4..e4feba6b03c0 100644 --- a/trunk/drivers/dma/pl330.c +++ b/trunk/drivers/dma/pl330.c @@ -522,7 +522,7 @@ enum desc_status { /* In the DMAC pool */ FREE, /* - * Allocated to some channel during prep_xxx + * Allocted to some channel during prep_xxx * Also may be sitting on the work_list. */ PREP, @@ -1567,19 +1567,17 @@ static int pl330_submit_req(void *ch_id, struct pl330_req *r) goto xfer_exit; } + /* Prefer Secure Channel */ + if (!_manager_ns(thrd)) + r->cfg->nonsecure = 0; + else + r->cfg->nonsecure = 1; /* Use last settings, if not provided */ - if (r->cfg) { - /* Prefer Secure Channel */ - if (!_manager_ns(thrd)) - r->cfg->nonsecure = 0; - else - r->cfg->nonsecure = 1; - + if (r->cfg) ccr = _prepare_ccr(r->cfg); - } else { + else ccr = readl(regs + CC(thrd->id)); - } /* If this req doesn't have valid xfer settings */ if (!_is_valid(ccr)) { @@ -2930,11 +2928,6 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id) num_chan = max_t(int, pi->pcfg.num_peri, pi->pcfg.num_chan); pdmac->peripherals = kzalloc(num_chan * sizeof(*pch), GFP_KERNEL); - if (!pdmac->peripherals) { - ret = -ENOMEM; - dev_err(&adev->dev, "unable to allocate pdmac->peripherals\n"); - goto probe_err5; - } for (i = 0; i < num_chan; i++) { pch = &pdmac->peripherals[i]; diff --git a/trunk/drivers/dma/ppc4xx/adma.c b/trunk/drivers/dma/ppc4xx/adma.c index f72348d0bc41..ced98826684a 100644 --- a/trunk/drivers/dma/ppc4xx/adma.c +++ b/trunk/drivers/dma/ppc4xx/adma.c @@ -4446,7 +4446,7 @@ static int __devinit ppc440spe_adma_probe(struct platform_device *ofdev) ret = -ENOMEM; goto err_dma_alloc; } - dev_dbg(&ofdev->dev, "allocated descriptor pool virt 0x%p phys 0x%llx\n", + dev_dbg(&ofdev->dev, "allocted descriptor pool virt 0x%p phys 0x%llx\n", adev->dma_desc_pool_virt, (u64)adev->dma_desc_pool); regs = ioremap(res.start, resource_size(&res)); diff --git a/trunk/drivers/dma/ste_dma40_ll.h b/trunk/drivers/dma/ste_dma40_ll.h index 6d47373f3f58..51e8e5396e9b 100644 --- a/trunk/drivers/dma/ste_dma40_ll.h +++ b/trunk/drivers/dma/ste_dma40_ll.h @@ -202,7 +202,7 @@ /* LLI related structures */ /** - * struct d40_phy_lli - The basic configuration register for each physical + * struct d40_phy_lli - The basic configration register for each physical * channel. * * @reg_cfg: The configuration register. diff --git a/trunk/drivers/dma/tegra20-apb-dma.c b/trunk/drivers/dma/tegra20-apb-dma.c index 24acd711e032..d52dbc6c54ab 100644 --- a/trunk/drivers/dma/tegra20-apb-dma.c +++ b/trunk/drivers/dma/tegra20-apb-dma.c @@ -1119,21 +1119,15 @@ struct dma_async_tx_descriptor *tegra_dma_prep_dma_cyclic( static int tegra_dma_alloc_chan_resources(struct dma_chan *dc) { struct tegra_dma_channel *tdc = to_tegra_dma_chan(dc); - struct tegra_dma *tdma = tdc->tdma; - int ret; dma_cookie_init(&tdc->dma_chan); tdc->config_init = false; - ret = clk_prepare_enable(tdma->dma_clk); - if (ret < 0) - dev_err(tdc2dev(tdc), "clk_prepare_enable failed: %d\n", ret); - return ret; + return 0; } static void tegra_dma_free_chan_resources(struct dma_chan *dc) { struct tegra_dma_channel *tdc = to_tegra_dma_chan(dc); - struct tegra_dma *tdma = tdc->tdma; struct tegra_dma_desc *dma_desc; struct tegra_dma_sg_req *sg_req; @@ -1169,7 +1163,6 @@ static void tegra_dma_free_chan_resources(struct dma_chan *dc) list_del(&sg_req->node); kfree(sg_req); } - clk_disable_unprepare(tdma->dma_clk); } /* Tegra20 specific DMA controller information */ @@ -1262,13 +1255,6 @@ static int __devinit tegra_dma_probe(struct platform_device *pdev) } } - /* Enable clock before accessing registers */ - ret = clk_prepare_enable(tdma->dma_clk); - if (ret < 0) { - dev_err(&pdev->dev, "clk_prepare_enable failed: %d\n", ret); - goto err_pm_disable; - } - /* Reset DMA controller */ tegra_periph_reset_assert(tdma->dma_clk); udelay(2); @@ -1279,8 +1265,6 @@ static int __devinit tegra_dma_probe(struct platform_device *pdev) tdma_write(tdma, TEGRA_APBDMA_CONTROL, 0); tdma_write(tdma, TEGRA_APBDMA_IRQ_MASK_SET, 0xFFFFFFFFul); - clk_disable_unprepare(tdma->dma_clk); - INIT_LIST_HEAD(&tdma->dma_dev.channels); for (i = 0; i < cdata->nr_channels; i++) { struct tegra_dma_channel *tdc = &tdma->channels[i]; diff --git a/trunk/drivers/edac/edac_mc.c b/trunk/drivers/edac/edac_mc.c index d5dc9da7f99f..616d90bcb3a4 100644 --- a/trunk/drivers/edac/edac_mc.c +++ b/trunk/drivers/edac/edac_mc.c @@ -199,36 +199,6 @@ void *edac_align_ptr(void **p, unsigned size, int n_elems) return (void *)(((unsigned long)ptr) + align - r); } -static void _edac_mc_free(struct mem_ctl_info *mci) -{ - int i, chn, row; - struct csrow_info *csr; - const unsigned int tot_dimms = mci->tot_dimms; - const unsigned int tot_channels = mci->num_cschannel; - const unsigned int tot_csrows = mci->nr_csrows; - - if (mci->dimms) { - for (i = 0; i < tot_dimms; i++) - kfree(mci->dimms[i]); - kfree(mci->dimms); - } - if (mci->csrows) { - for (row = 0; row < tot_csrows; row++) { - csr = mci->csrows[row]; - if (csr) { - if (csr->channels) { - for (chn = 0; chn < tot_channels; chn++) - kfree(csr->channels[chn]); - kfree(csr->channels); - } - kfree(csr); - } - } - kfree(mci->csrows); - } - kfree(mci); -} - /** * edac_mc_alloc: Allocate and partially fill a struct mem_ctl_info structure * @mc_num: Memory controller number @@ -443,7 +413,24 @@ struct mem_ctl_info *edac_mc_alloc(unsigned mc_num, return mci; error: - _edac_mc_free(mci); + if (mci->dimms) { + for (i = 0; i < tot_dimms; i++) + kfree(mci->dimms[i]); + kfree(mci->dimms); + } + if (mci->csrows) { + for (chn = 0; chn < tot_channels; chn++) { + csr = mci->csrows[chn]; + if (csr) { + for (chn = 0; chn < tot_channels; chn++) + kfree(csr->channels[chn]); + kfree(csr); + } + kfree(mci->csrows[i]); + } + kfree(mci->csrows); + } + kfree(mci); return NULL; } @@ -458,14 +445,6 @@ void edac_mc_free(struct mem_ctl_info *mci) { edac_dbg(1, "\n"); - /* If we're not yet registered with sysfs free only what was allocated - * in edac_mc_alloc(). - */ - if (!device_is_registered(&mci->dev)) { - _edac_mc_free(mci); - return; - } - /* the mci instance is freed here, when the sysfs object is dropped */ edac_unregister_sysfs(mci); } diff --git a/trunk/drivers/edac/i3200_edac.c b/trunk/drivers/edac/i3200_edac.c index b6653a6fc5d5..47180a08edad 100644 --- a/trunk/drivers/edac/i3200_edac.c +++ b/trunk/drivers/edac/i3200_edac.c @@ -391,7 +391,7 @@ static int i3200_probe1(struct pci_dev *pdev, int dev_idx) for (j = 0; j < nr_channels; j++) { struct dimm_info *dimm = csrow->channels[j]->dimm; - dimm->nr_pages = nr_pages; + dimm->nr_pages = nr_pages / nr_channels; dimm->grain = nr_pages << PAGE_SHIFT; dimm->mtype = MEM_DDR2; dimm->dtype = DEV_UNKNOWN; diff --git a/trunk/drivers/edac/i5000_edac.c b/trunk/drivers/edac/i5000_edac.c index 6a49dd00b81b..39c63757c2a1 100644 --- a/trunk/drivers/edac/i5000_edac.c +++ b/trunk/drivers/edac/i5000_edac.c @@ -1012,10 +1012,6 @@ static void handle_channel(struct i5000_pvt *pvt, int slot, int channel, /* add the number of COLUMN bits */ addrBits += MTR_DIMM_COLS_ADDR_BITS(mtr); - /* Dual-rank memories have twice the size */ - if (dinfo->dual_rank) - addrBits++; - addrBits += 6; /* add 64 bits per DIMM */ addrBits -= 20; /* divide by 2^^20 */ addrBits -= 3; /* 8 bits per bytes */ diff --git a/trunk/drivers/edac/sb_edac.c b/trunk/drivers/edac/sb_edac.c index 5715b7c2c517..f3b1f9fafa4b 100644 --- a/trunk/drivers/edac/sb_edac.c +++ b/trunk/drivers/edac/sb_edac.c @@ -513,8 +513,7 @@ static int get_dimm_config(struct mem_ctl_info *mci) { struct sbridge_pvt *pvt = mci->pvt_info; struct dimm_info *dimm; - unsigned i, j, banks, ranks, rows, cols, npages; - u64 size; + int i, j, banks, ranks, rows, cols, size, npages; u32 reg; enum edac_type mode; enum mem_type mtype; @@ -586,10 +585,10 @@ static int get_dimm_config(struct mem_ctl_info *mci) cols = numcol(mtr); /* DDR3 has 8 I/O banks */ - size = ((u64)rows * cols * banks * ranks) >> (20 - 3); + size = (rows * cols * banks * ranks) >> (20 - 3); npages = MiB_TO_PAGES(size); - edac_dbg(0, "mc#%d: channel %d, dimm %d, %Ld Mb (%d pages) bank: %d, rank: %d, row: %#x, col: %#x\n", + edac_dbg(0, "mc#%d: channel %d, dimm %d, %d Mb (%d pages) bank: %d, rank: %d, row: %#x, col: %#x\n", pvt->sbridge_dev->mc, i, j, size, npages, banks, ranks, rows, cols); diff --git a/trunk/drivers/extcon/Kconfig b/trunk/drivers/extcon/Kconfig index 07122a9ef36e..e175c8ed4ec4 100644 --- a/trunk/drivers/extcon/Kconfig +++ b/trunk/drivers/extcon/Kconfig @@ -21,12 +21,6 @@ config EXTCON_GPIO Say Y here to enable GPIO based extcon support. Note that GPIO extcon supports single state per extcon instance. -config EXTCON_ADC_JACK - tristate "ADC Jack extcon support" - depends on IIO - help - Say Y here to enable extcon device driver based on ADC values. - config EXTCON_MAX77693 tristate "MAX77693 EXTCON Support" depends on MFD_MAX77693 @@ -47,7 +41,7 @@ config EXTCON_MAX8997 config EXTCON_ARIZONA tristate "Wolfson Arizona EXTCON support" - depends on MFD_ARIZONA && INPUT + depends on MFD_ARIZONA help Say Y here to enable support for external accessory detection with Wolfson Arizona devices. These are audio CODECs with diff --git a/trunk/drivers/extcon/Makefile b/trunk/drivers/extcon/Makefile index f98a3c4d46e0..88961b332348 100644 --- a/trunk/drivers/extcon/Makefile +++ b/trunk/drivers/extcon/Makefile @@ -2,9 +2,8 @@ # Makefile for external connector class (extcon) devices # -obj-$(CONFIG_EXTCON) += extcon-class.o -obj-$(CONFIG_EXTCON_GPIO) += extcon-gpio.o -obj-$(CONFIG_EXTCON_ADC_JACK) += extcon-adc-jack.o +obj-$(CONFIG_EXTCON) += extcon_class.o +obj-$(CONFIG_EXTCON_GPIO) += extcon_gpio.o obj-$(CONFIG_EXTCON_MAX77693) += extcon-max77693.o obj-$(CONFIG_EXTCON_MAX8997) += extcon-max8997.o obj-$(CONFIG_EXTCON_ARIZONA) += extcon-arizona.o diff --git a/trunk/drivers/extcon/extcon-adc-jack.c b/trunk/drivers/extcon/extcon-adc-jack.c deleted file mode 100644 index 60ac3fbb4cde..000000000000 --- a/trunk/drivers/extcon/extcon-adc-jack.c +++ /dev/null @@ -1,198 +0,0 @@ -/* - * drivers/extcon/extcon-adc-jack.c - * - * Analog Jack extcon driver with ADC-based detection capability. - * - * Copyright (C) 2012 Samsung Electronics - * MyungJoo Ham - * - * Modified for calling to IIO to get adc by - * - * 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 -#include -#include -#include -#include -#include -#include -#include -#include - -/** - * struct adc_jack_data - internal data for adc_jack device driver - * @edev - extcon device. - * @cable_names - list of supported cables. - * @num_cables - size of cable_names. - * @adc_conditions - list of adc value conditions. - * @num_conditions - size of adc_conditions. - * @irq - irq number of attach/detach event (0 if not exist). - * @handling_delay - interrupt handler will schedule extcon event - * handling at handling_delay jiffies. - * @handler - extcon event handler called by interrupt handler. - * @chan - iio channel being queried. - */ -struct adc_jack_data { - struct extcon_dev edev; - - const char **cable_names; - int num_cables; - struct adc_jack_cond *adc_conditions; - int num_conditions; - - int irq; - unsigned long handling_delay; /* in jiffies */ - struct delayed_work handler; - - struct iio_channel *chan; -}; - -static void adc_jack_handler(struct work_struct *work) -{ - struct adc_jack_data *data = container_of(to_delayed_work(work), - struct adc_jack_data, - handler); - u32 state = 0; - int ret, adc_val; - int i; - - ret = iio_read_channel_raw(data->chan, &adc_val); - if (ret < 0) { - dev_err(data->edev.dev, "read channel() error: %d\n", ret); - return; - } - - /* Get state from adc value with adc_conditions */ - for (i = 0; i < data->num_conditions; i++) { - struct adc_jack_cond *def = &data->adc_conditions[i]; - if (!def->state) - break; - if (def->min_adc <= adc_val && def->max_adc >= adc_val) { - state = def->state; - break; - } - } - /* if no def has met, it means state = 0 (no cables attached) */ - - extcon_set_state(&data->edev, state); -} - -static irqreturn_t adc_jack_irq_thread(int irq, void *_data) -{ - struct adc_jack_data *data = _data; - - schedule_delayed_work(&data->handler, data->handling_delay); - return IRQ_HANDLED; -} - -static int __devinit adc_jack_probe(struct platform_device *pdev) -{ - struct adc_jack_data *data; - struct adc_jack_pdata *pdata = pdev->dev.platform_data; - int i, err = 0; - - data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); - if (!data) - return -ENOMEM; - - data->edev.name = pdata->name; - - if (!pdata->cable_names) { - err = -EINVAL; - dev_err(&pdev->dev, "error: cable_names not defined.\n"); - goto out; - } - - data->edev.supported_cable = pdata->cable_names; - - /* Check the length of array and set num_cables */ - for (i = 0; data->edev.supported_cable[i]; i++) - ; - if (i == 0 || i > SUPPORTED_CABLE_MAX) { - err = -EINVAL; - dev_err(&pdev->dev, "error: pdata->cable_names size = %d\n", - i - 1); - goto out; - } - data->num_cables = i; - - if (!pdata->adc_conditions || - !pdata->adc_conditions[0].state) { - err = -EINVAL; - dev_err(&pdev->dev, "error: adc_conditions not defined.\n"); - goto out; - } - data->adc_conditions = pdata->adc_conditions; - - /* Check the length of array and set num_conditions */ - for (i = 0; data->adc_conditions[i].state; i++) - ; - data->num_conditions = i; - - data->chan = iio_channel_get(dev_name(&pdev->dev), - pdata->consumer_channel); - if (IS_ERR(data->chan)) { - err = PTR_ERR(data->chan); - goto out; - } - - data->handling_delay = msecs_to_jiffies(pdata->handling_delay_ms); - - INIT_DELAYED_WORK_DEFERRABLE(&data->handler, adc_jack_handler); - - platform_set_drvdata(pdev, data); - - err = extcon_dev_register(&data->edev, &pdev->dev); - if (err) - goto out; - - data->irq = platform_get_irq(pdev, 0); - if (!data->irq) { - dev_err(&pdev->dev, "platform_get_irq failed\n"); - err = -ENODEV; - goto err_irq; - } - - err = request_any_context_irq(data->irq, adc_jack_irq_thread, - pdata->irq_flags, pdata->name, data); - - if (err) { - dev_err(&pdev->dev, "error: irq %d\n", data->irq); - err = -EINVAL; - goto err_irq; - } - - goto out; - -err_irq: - extcon_dev_unregister(&data->edev); -out: - return err; -} - -static int __devexit adc_jack_remove(struct platform_device *pdev) -{ - struct adc_jack_data *data = platform_get_drvdata(pdev); - - free_irq(data->irq, data); - cancel_work_sync(&data->handler.work); - extcon_dev_unregister(&data->edev); - - return 0; -} - -static struct platform_driver adc_jack_driver = { - .probe = adc_jack_probe, - .remove = __devexit_p(adc_jack_remove), - .driver = { - .name = "adc-jack", - .owner = THIS_MODULE, - }, -}; - -module_platform_driver(adc_jack_driver); diff --git a/trunk/drivers/extcon/extcon-arizona.c b/trunk/drivers/extcon/extcon-arizona.c index cdab9e598297..427a289f32a5 100644 --- a/trunk/drivers/extcon/extcon-arizona.c +++ b/trunk/drivers/extcon/extcon-arizona.c @@ -21,7 +21,6 @@ #include #include #include -#include #include #include #include @@ -31,14 +30,11 @@ #include #include -#define ARIZONA_NUM_BUTTONS 6 - struct arizona_extcon_info { struct device *dev; struct arizona *arizona; struct mutex lock; struct regulator *micvdd; - struct input_dev *input; int micd_mode; const struct arizona_micd_config *micd_modes; @@ -58,18 +54,6 @@ static const struct arizona_micd_config micd_default_modes[] = { { 0, 2 << ARIZONA_MICD_BIAS_SRC_SHIFT, 1 }, }; -static struct { - u16 status; - int report; -} arizona_lvl_to_key[ARIZONA_NUM_BUTTONS] = { - { 0x1, BTN_0 }, - { 0x2, BTN_1 }, - { 0x4, BTN_2 }, - { 0x8, BTN_3 }, - { 0x10, BTN_4 }, - { 0x20, BTN_5 }, -}; - #define ARIZONA_CABLE_MECHANICAL 0 #define ARIZONA_CABLE_MICROPHONE 1 #define ARIZONA_CABLE_HEADPHONE 2 @@ -149,7 +133,6 @@ static void arizona_stop_mic(struct arizona_extcon_info *info) if (change) { regulator_disable(info->micvdd); - pm_runtime_mark_last_busy(info->dev); pm_runtime_put_autosuspend(info->dev); } } @@ -158,8 +141,8 @@ static irqreturn_t arizona_micdet(int irq, void *data) { struct arizona_extcon_info *info = data; struct arizona *arizona = info->arizona; - unsigned int val, lvl; - int ret, i; + unsigned int val; + int ret; mutex_lock(&info->lock); @@ -236,22 +219,13 @@ static irqreturn_t arizona_micdet(int irq, void *data) /* * If we're still detecting and we detect a short then we've - * got a headphone. Otherwise it's a button press. + * got a headphone. Otherwise it's a button press, the + * button reporting is stubbed out for now. */ if (val & 0x3fc) { if (info->mic) { dev_dbg(arizona->dev, "Mic button detected\n"); - lvl = val & ARIZONA_MICD_LVL_MASK; - lvl >>= ARIZONA_MICD_LVL_SHIFT; - - for (i = 0; i < ARIZONA_NUM_BUTTONS; i++) - if (lvl & arizona_lvl_to_key[i].status) - input_report_key(info->input, - arizona_lvl_to_key[i].report, - 1); - input_sync(info->input); - } else if (info->detecting) { dev_dbg(arizona->dev, "Headphone detected\n"); info->detecting = false; @@ -270,10 +244,6 @@ static irqreturn_t arizona_micdet(int irq, void *data) } } else { dev_dbg(arizona->dev, "Mic button released\n"); - for (i = 0; i < ARIZONA_NUM_BUTTONS; i++) - input_report_key(info->input, - arizona_lvl_to_key[i].report, 0); - input_sync(info->input); } handled: @@ -288,7 +258,7 @@ static irqreturn_t arizona_jackdet(int irq, void *data) struct arizona_extcon_info *info = data; struct arizona *arizona = info->arizona; unsigned int val; - int ret, i; + int ret; pm_runtime_get_sync(info->dev); @@ -318,11 +288,6 @@ static irqreturn_t arizona_jackdet(int irq, void *data) arizona_stop_mic(info); - for (i = 0; i < ARIZONA_NUM_BUTTONS; i++) - input_report_key(info->input, - arizona_lvl_to_key[i].report, 0); - input_sync(info->input); - ret = extcon_update_state(&info->edev, 0xffffffff, 0); if (ret != 0) dev_err(arizona->dev, "Removal report failed: %d\n", @@ -342,13 +307,13 @@ static int __devinit arizona_extcon_probe(struct platform_device *pdev) struct arizona *arizona = dev_get_drvdata(pdev->dev.parent); struct arizona_pdata *pdata; struct arizona_extcon_info *info; - int ret, mode, i; + int ret, mode; pdata = dev_get_platdata(arizona->dev); info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL); if (!info) { - dev_err(&pdev->dev, "Failed to allocate memory\n"); + dev_err(&pdev->dev, "failed to allocate memory\n"); ret = -ENOMEM; goto err; } @@ -385,7 +350,7 @@ static int __devinit arizona_extcon_probe(struct platform_device *pdev) ret = extcon_dev_register(&info->edev, arizona->dev); if (ret < 0) { - dev_err(arizona->dev, "extcon_dev_register() failed: %d\n", + dev_err(arizona->dev, "extcon_dev_regster() failed: %d\n", ret); goto err; } @@ -417,20 +382,6 @@ static int __devinit arizona_extcon_probe(struct platform_device *pdev) arizona_extcon_set_mode(info, 0); - info->input = input_allocate_device(); - if (!info->input) { - dev_err(arizona->dev, "Can't allocate input dev\n"); - ret = -ENOMEM; - goto err_register; - } - - for (i = 0; i < ARIZONA_NUM_BUTTONS; i++) - input_set_capability(info->input, EV_KEY, - arizona_lvl_to_key[i].report); - info->input->name = "Headset"; - info->input->phys = "arizona/extcon"; - info->input->dev.parent = &pdev->dev; - pm_runtime_enable(&pdev->dev); pm_runtime_idle(&pdev->dev); pm_runtime_get_sync(&pdev->dev); @@ -440,7 +391,7 @@ static int __devinit arizona_extcon_probe(struct platform_device *pdev) if (ret != 0) { dev_err(&pdev->dev, "Failed to get JACKDET rise IRQ: %d\n", ret); - goto err_input; + goto err_register; } ret = arizona_set_irq_wake(arizona, ARIZONA_IRQ_JD_RISE, 1); @@ -483,23 +434,10 @@ static int __devinit arizona_extcon_probe(struct platform_device *pdev) regmap_update_bits(arizona->regmap, ARIZONA_JACK_DETECT_ANALOGUE, ARIZONA_JD1_ENA, ARIZONA_JD1_ENA); - ret = regulator_allow_bypass(info->micvdd, true); - if (ret != 0) - dev_warn(arizona->dev, "Failed to set MICVDD to bypass: %d\n", - ret); - pm_runtime_put(&pdev->dev); - ret = input_register_device(info->input); - if (ret) { - dev_err(&pdev->dev, "Can't register input device: %d\n", ret); - goto err_micdet; - } - return 0; -err_micdet: - arizona_free_irq(arizona, ARIZONA_IRQ_MICDET, info); err_fall_wake: arizona_set_irq_wake(arizona, ARIZONA_IRQ_JD_FALL, 0); err_fall: @@ -508,8 +446,6 @@ static int __devinit arizona_extcon_probe(struct platform_device *pdev) arizona_set_irq_wake(arizona, ARIZONA_IRQ_JD_RISE, 0); err_rise: arizona_free_irq(arizona, ARIZONA_IRQ_JD_RISE, info); -err_input: - input_free_device(info->input); err_register: pm_runtime_disable(&pdev->dev); extcon_dev_unregister(&info->edev); @@ -532,7 +468,6 @@ static int __devexit arizona_extcon_remove(struct platform_device *pdev) regmap_update_bits(arizona->regmap, ARIZONA_JACK_DETECT_ANALOGUE, ARIZONA_JD1_ENA, 0); arizona_clk32k_disable(arizona); - input_unregister_device(info->input); extcon_dev_unregister(&info->edev); return 0; diff --git a/trunk/drivers/extcon/extcon-max77693.c b/trunk/drivers/extcon/extcon-max77693.c index e21387e2da5c..920a609b2c35 100644 --- a/trunk/drivers/extcon/extcon-max77693.c +++ b/trunk/drivers/extcon/extcon-max77693.c @@ -356,7 +356,7 @@ static int max77693_muic_adc_ground_handler(struct max77693_muic_info *info, extcon_set_cable_state(info->edev, "MHL", attached); break; default: - dev_err(info->dev, "failed to detect %s accessory\n", + dev_err(info->dev, "faild to detect %s accessory\n", attached ? "attached" : "detached"); dev_err(info->dev, "- adc:0x%x, adclow:0x%x, adc1k:0x%x\n", adc, adclow, adc1k); @@ -548,7 +548,7 @@ static void max77693_muic_irq_work(struct work_struct *work) curr_adc = info->status[0] & STATUS1_ADC_MASK; curr_adc >>= STATUS1_ADC_SHIFT; - /* Check accessory state which is either detached or attached */ + /* Check accossory state which is either detached or attached */ if (curr_adc == MAX77693_MUIC_ADC_OPEN) attached = false; @@ -564,7 +564,7 @@ static void max77693_muic_irq_work(struct work_struct *work) curr_chg_type = info->status[1] & STATUS2_CHGTYP_MASK; curr_chg_type >>= STATUS2_CHGTYP_SHIFT; - /* Check charger accessory state which + /* Check charger accossory state which is either detached or attached */ if (curr_chg_type == MAX77693_CHARGER_TYPE_NONE) attached = false; @@ -669,18 +669,13 @@ static int __devinit max77693_muic_probe(struct platform_device *pdev) } info->dev = &pdev->dev; info->max77693 = max77693; - if (info->max77693->regmap_muic) - dev_dbg(&pdev->dev, "allocate register map\n"); - else { - info->max77693->regmap_muic = devm_regmap_init_i2c( - info->max77693->muic, - &max77693_muic_regmap_config); - if (IS_ERR(info->max77693->regmap_muic)) { - ret = PTR_ERR(info->max77693->regmap_muic); - dev_err(max77693->dev, - "failed to allocate register map: %d\n", ret); - goto err_regmap; - } + info->max77693->regmap_muic = regmap_init_i2c(info->max77693->muic, + &max77693_muic_regmap_config); + if (IS_ERR(info->max77693->regmap_muic)) { + ret = PTR_ERR(info->max77693->regmap_muic); + dev_err(max77693->dev, + "failed to allocate register map: %d\n", ret); + goto err_regmap; } platform_set_drvdata(pdev, info); mutex_init(&info->mutex); @@ -699,7 +694,7 @@ static int __devinit max77693_muic_probe(struct platform_device *pdev) ret = request_threaded_irq(virq, NULL, max77693_muic_irq_handler, - IRQF_ONESHOT, muic_irq->name, info); + 0, muic_irq->name, info); if (ret) { dev_err(&pdev->dev, "failed: irq request (IRQ: %d," diff --git a/trunk/drivers/extcon/extcon-class.c b/trunk/drivers/extcon/extcon_class.c similarity index 98% rename from trunk/drivers/extcon/extcon-class.c rename to trunk/drivers/extcon/extcon_class.c index 946a3188b2b7..f6419f9db76c 100644 --- a/trunk/drivers/extcon/extcon-class.c +++ b/trunk/drivers/extcon/extcon_class.c @@ -30,7 +30,6 @@ #include #include #include -#include /* * extcon_cable_name suggests the standard cable names for commonly used @@ -443,7 +442,7 @@ static int _call_per_cable(struct notifier_block *nb, unsigned long val, /** * extcon_register_interest() - Register a notifier for a state change of a - * specific cable, not an entier set of cables of a + * specific cable, not a entier set of cables of a * extcon device. * @obj: an empty extcon_specific_cable_nb object to be returned. * @extcon_name: the name of extcon device. @@ -499,7 +498,7 @@ int extcon_unregister_interest(struct extcon_specific_cable_nb *obj) } /** - * extcon_register_notifier() - Register a notifiee to get notified by + * extcon_register_notifier() - Register a notifee to get notified by * any attach status changes from the extcon. * @edev: the extcon device. * @nb: a notifier block to be registered. @@ -516,7 +515,7 @@ int extcon_register_notifier(struct extcon_dev *edev, EXPORT_SYMBOL_GPL(extcon_register_notifier); /** - * extcon_unregister_notifier() - Unregister a notifiee from the extcon device. + * extcon_unregister_notifier() - Unregister a notifee from the extcon device. * @edev: the extcon device. * @nb: a registered notifier block to be unregistered. */ @@ -674,12 +673,10 @@ int extcon_dev_register(struct extcon_dev *edev, struct device *dev) cable->attr_g.name = str; cable->attr_g.attrs = cable->attrs; - sysfs_attr_init(&cable->attr_name.attr); cable->attr_name.attr.name = "name"; cable->attr_name.attr.mode = 0444; cable->attr_name.show = cable_name_show; - sysfs_attr_init(&cable->attr_state.attr); cable->attr_state.attr.name = "state"; cable->attr_state.attr.mode = 0644; cable->attr_state.show = cable_state_show; @@ -725,7 +722,6 @@ int extcon_dev_register(struct extcon_dev *edev, struct device *dev) goto err_muex; } strcpy(name, buf); - sysfs_attr_init(&edev->d_attrs_muex[index].attr); edev->d_attrs_muex[index].attr.name = name; edev->d_attrs_muex[index].attr.mode = 0000; edev->attrs_muex[index] = &edev->d_attrs_muex[index] @@ -806,7 +802,7 @@ EXPORT_SYMBOL_GPL(extcon_dev_register); /** * extcon_dev_unregister() - Unregister the extcon device. - * @edev: the extcon device instance to be unregistered. + * @edev: the extcon device instance to be unregitered. * * Note that this does not call kfree(edev) because edev was not allocated * by this class. diff --git a/trunk/drivers/extcon/extcon-gpio.c b/trunk/drivers/extcon/extcon_gpio.c similarity index 97% rename from trunk/drivers/extcon/extcon-gpio.c rename to trunk/drivers/extcon/extcon_gpio.c index 3cc152e690b0..fe3db45fa83c 100644 --- a/trunk/drivers/extcon/extcon-gpio.c +++ b/trunk/drivers/extcon/extcon_gpio.c @@ -107,8 +107,7 @@ static int __devinit gpio_extcon_probe(struct platform_device *pdev) if (ret < 0) return ret; - ret = devm_gpio_request_one(&pdev->dev, extcon_data->gpio, GPIOF_DIR_IN, - pdev->name); + ret = gpio_request_one(extcon_data->gpio, GPIOF_DIR_IN, pdev->name); if (ret < 0) goto err; diff --git a/trunk/drivers/firmware/efivars.c b/trunk/drivers/firmware/efivars.c index d10c9873dd9a..47408e802ab6 100644 --- a/trunk/drivers/firmware/efivars.c +++ b/trunk/drivers/firmware/efivars.c @@ -435,23 +435,12 @@ efivar_attr_read(struct efivar_entry *entry, char *buf) if (status != EFI_SUCCESS) return -EIO; - if (var->Attributes & EFI_VARIABLE_NON_VOLATILE) + if (var->Attributes & 0x1) str += sprintf(str, "EFI_VARIABLE_NON_VOLATILE\n"); - if (var->Attributes & EFI_VARIABLE_BOOTSERVICE_ACCESS) + if (var->Attributes & 0x2) str += sprintf(str, "EFI_VARIABLE_BOOTSERVICE_ACCESS\n"); - if (var->Attributes & EFI_VARIABLE_RUNTIME_ACCESS) + if (var->Attributes & 0x4) str += sprintf(str, "EFI_VARIABLE_RUNTIME_ACCESS\n"); - if (var->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) - str += sprintf(str, "EFI_VARIABLE_HARDWARE_ERROR_RECORD\n"); - if (var->Attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) - str += sprintf(str, - "EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS\n"); - if (var->Attributes & - EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) - str += sprintf(str, - "EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS\n"); - if (var->Attributes & EFI_VARIABLE_APPEND_WRITE) - str += sprintf(str, "EFI_VARIABLE_APPEND_WRITE\n"); return str - buf; } diff --git a/trunk/drivers/gpio/Kconfig b/trunk/drivers/gpio/Kconfig index ba7926f5c099..b16c8a72a2e2 100644 --- a/trunk/drivers/gpio/Kconfig +++ b/trunk/drivers/gpio/Kconfig @@ -294,7 +294,7 @@ config GPIO_MAX732X_IRQ config GPIO_MC9S08DZ60 bool "MX35 3DS BOARD MC9S08DZ60 GPIO functions" - depends on I2C=y && MACH_MX35_3DS + depends on I2C && MACH_MX35_3DS help Select this to enable the MC9S08DZ60 GPIO driver diff --git a/trunk/drivers/gpio/gpio-em.c b/trunk/drivers/gpio/gpio-em.c index ec48ed512628..150d9768811d 100644 --- a/trunk/drivers/gpio/gpio-em.c +++ b/trunk/drivers/gpio/gpio-em.c @@ -247,9 +247,9 @@ static int __devinit em_gio_irq_domain_init(struct em_gio_priv *p) p->irq_base = irq_alloc_descs(pdata->irq_base, 0, pdata->number_of_pins, numa_node_id()); - if (p->irq_base < 0) { + if (IS_ERR_VALUE(p->irq_base)) { dev_err(&pdev->dev, "cannot get irq_desc\n"); - return p->irq_base; + return -ENXIO; } pr_debug("gio: hw base = %d, nr = %d, sw base = %d\n", pdata->gpio_base, pdata->number_of_pins, p->irq_base); @@ -266,7 +266,7 @@ static int __devinit em_gio_irq_domain_init(struct em_gio_priv *p) return 0; } -static void em_gio_irq_domain_cleanup(struct em_gio_priv *p) +static void __devexit em_gio_irq_domain_cleanup(struct em_gio_priv *p) { struct gpio_em_config *pdata = p->pdev->dev.platform_data; diff --git a/trunk/drivers/gpio/gpio-langwell.c b/trunk/drivers/gpio/gpio-langwell.c index 202a99207b7d..a1c8754f52cf 100644 --- a/trunk/drivers/gpio/gpio-langwell.c +++ b/trunk/drivers/gpio/gpio-langwell.c @@ -339,7 +339,7 @@ static int __devinit lnw_gpio_probe(struct pci_dev *pdev, resource_size_t start, len; struct lnw_gpio *lnw; u32 gpio_base; - int retval; + int retval = 0; int ngpio = id->driver_data; retval = pci_enable_device(pdev); @@ -357,7 +357,6 @@ static int __devinit lnw_gpio_probe(struct pci_dev *pdev, base = ioremap_nocache(start, len); if (!base) { dev_err(&pdev->dev, "error mapping bar1\n"); - retval = -EFAULT; goto err3; } gpio_base = *((u32 *)base + 1); @@ -382,10 +381,8 @@ static int __devinit lnw_gpio_probe(struct pci_dev *pdev, lnw->domain = irq_domain_add_linear(pdev->dev.of_node, ngpio, &lnw_gpio_irq_ops, lnw); - if (!lnw->domain) { - retval = -ENOMEM; + if (!lnw->domain) goto err3; - } lnw->reg_base = base; lnw->chip.label = dev_name(&pdev->dev); diff --git a/trunk/drivers/gpio/gpio-lpc32xx.c b/trunk/drivers/gpio/gpio-lpc32xx.c index ed94b4ea72e9..8a420f13905e 100644 --- a/trunk/drivers/gpio/gpio-lpc32xx.c +++ b/trunk/drivers/gpio/gpio-lpc32xx.c @@ -308,7 +308,6 @@ static int lpc32xx_gpio_dir_output_p012(struct gpio_chip *chip, unsigned pin, { struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip); - __set_gpio_level_p012(group, pin, value); __set_gpio_dir_p012(group, pin, 0); return 0; @@ -319,7 +318,6 @@ static int lpc32xx_gpio_dir_output_p3(struct gpio_chip *chip, unsigned pin, { struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip); - __set_gpio_level_p3(group, pin, value); __set_gpio_dir_p3(group, pin, 0); return 0; @@ -328,9 +326,6 @@ static int lpc32xx_gpio_dir_output_p3(struct gpio_chip *chip, unsigned pin, static int lpc32xx_gpio_dir_out_always(struct gpio_chip *chip, unsigned pin, int value) { - struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip); - - __set_gpo_level_p3(group, pin, value); return 0; } diff --git a/trunk/drivers/gpio/gpio-msic.c b/trunk/drivers/gpio/gpio-msic.c index b38986285868..71a838f44501 100644 --- a/trunk/drivers/gpio/gpio-msic.c +++ b/trunk/drivers/gpio/gpio-msic.c @@ -99,7 +99,7 @@ static int msic_gpio_to_oreg(unsigned offset) if (offset < 20) return INTEL_MSIC_GPIO0HV0CTLO - offset + 16; - return INTEL_MSIC_GPIO1HV0CTLO - offset + 20; + return INTEL_MSIC_GPIO1HV0CTLO + offset + 20; } static int msic_gpio_direction_input(struct gpio_chip *chip, unsigned offset) diff --git a/trunk/drivers/gpio/gpio-mxc.c b/trunk/drivers/gpio/gpio-mxc.c index 80f44bb64a87..4db460b6ecf7 100644 --- a/trunk/drivers/gpio/gpio-mxc.c +++ b/trunk/drivers/gpio/gpio-mxc.c @@ -465,8 +465,9 @@ static int __devinit mxc_gpio_probe(struct platform_device *pdev) goto out_iounmap; port->bgc.gc.to_irq = mxc_gpio_to_irq; - port->bgc.gc.base = (pdev->id < 0) ? of_alias_get_id(np, "gpio") * 32 : - pdev->id * 32; + port->bgc.gc.base = pdev->id * 32; + port->bgc.dir = port->bgc.read_reg(port->bgc.reg_dir); + port->bgc.data = port->bgc.read_reg(port->bgc.reg_set); err = gpiochip_add(&port->bgc.gc); if (err) diff --git a/trunk/drivers/gpio/gpio-pxa.c b/trunk/drivers/gpio/gpio-pxa.c index 9cac88a65f78..58a6a63a6ece 100644 --- a/trunk/drivers/gpio/gpio-pxa.c +++ b/trunk/drivers/gpio/gpio-pxa.c @@ -62,7 +62,6 @@ int pxa_last_gpio; #ifdef CONFIG_OF static struct irq_domain *domain; -static struct device_node *pxa_gpio_of_node; #endif struct pxa_gpio_chip { @@ -278,24 +277,6 @@ static void pxa_gpio_set(struct gpio_chip *chip, unsigned offset, int value) (value ? GPSR_OFFSET : GPCR_OFFSET)); } -#ifdef CONFIG_OF_GPIO -static int pxa_gpio_of_xlate(struct gpio_chip *gc, - const struct of_phandle_args *gpiospec, - u32 *flags) -{ - if (gpiospec->args[0] > pxa_last_gpio) - return -EINVAL; - - if (gc != &pxa_gpio_chips[gpiospec->args[0] / 32].chip) - return -EINVAL; - - if (flags) - *flags = gpiospec->args[1]; - - return gpiospec->args[0] % 32; -} -#endif - static int __devinit pxa_init_gpio_chip(int gpio_end, int (*set_wake)(unsigned int, unsigned int)) { @@ -323,11 +304,6 @@ static int __devinit pxa_init_gpio_chip(int gpio_end, c->get = pxa_gpio_get; c->set = pxa_gpio_set; c->to_irq = pxa_gpio_to_irq; -#ifdef CONFIG_OF_GPIO - c->of_node = pxa_gpio_of_node; - c->of_xlate = pxa_gpio_of_xlate; - c->of_gpio_n_cells = 2; -#endif /* number of GPIOs on last bank may be less than 32 */ c->ngpio = (gpio + 31 > gpio_end) ? (gpio_end - gpio + 1) : 32; @@ -512,7 +488,6 @@ static int pxa_gpio_nums(void) return count; } -#ifdef CONFIG_OF static struct of_device_id pxa_gpio_dt_ids[] = { { .compatible = "mrvl,pxa-gpio" }, { .compatible = "mrvl,mmp-gpio", .data = (void *)MMP_GPIO }, @@ -530,9 +505,9 @@ static int pxa_irq_domain_map(struct irq_domain *d, unsigned int irq, const struct irq_domain_ops pxa_irq_domain_ops = { .map = pxa_irq_domain_map, - .xlate = irq_domain_xlate_twocell, }; +#ifdef CONFIG_OF static int __devinit pxa_gpio_probe_dt(struct platform_device *pdev) { int ret, nr_banks, nr_gpios, irq_base; @@ -570,7 +545,6 @@ static int __devinit pxa_gpio_probe_dt(struct platform_device *pdev) } domain = irq_domain_add_legacy(np, nr_gpios, irq_base, 0, &pxa_irq_domain_ops, NULL); - pxa_gpio_of_node = np; return 0; err: iounmap(gpio_reg_base); @@ -679,7 +653,7 @@ static struct platform_driver pxa_gpio_driver = { .probe = pxa_gpio_probe, .driver = { .name = "pxa-gpio", - .of_match_table = of_match_ptr(pxa_gpio_dt_ids), + .of_match_table = pxa_gpio_dt_ids, }, }; diff --git a/trunk/drivers/gpio/gpio-rdc321x.c b/trunk/drivers/gpio/gpio-rdc321x.c index b62d443e9a59..e97016af6443 100644 --- a/trunk/drivers/gpio/gpio-rdc321x.c +++ b/trunk/drivers/gpio/gpio-rdc321x.c @@ -170,7 +170,6 @@ static int __devinit rdc321x_gpio_probe(struct platform_device *pdev) rdc321x_gpio_dev->reg2_data_base = r->start + 0x4; rdc321x_gpio_dev->chip.label = "rdc321x-gpio"; - rdc321x_gpio_dev->chip.owner = THIS_MODULE; rdc321x_gpio_dev->chip.direction_input = rdc_gpio_direction_input; rdc321x_gpio_dev->chip.direction_output = rdc_gpio_config; rdc321x_gpio_dev->chip.get = rdc_gpio_get_value; diff --git a/trunk/drivers/gpio/gpio-samsung.c b/trunk/drivers/gpio/gpio-samsung.c index ba126cc04073..92f7b2bb79d4 100644 --- a/trunk/drivers/gpio/gpio-samsung.c +++ b/trunk/drivers/gpio/gpio-samsung.c @@ -2452,6 +2452,12 @@ static struct samsung_gpio_chip exynos5_gpios_1[] = { .ngpio = EXYNOS5_GPIO_C3_NR, .label = "GPC3", }, + }, { + .chip = { + .base = EXYNOS5_GPC4(0), + .ngpio = EXYNOS5_GPIO_C4_NR, + .label = "GPC4", + }, }, { .chip = { .base = EXYNOS5_GPD0(0), @@ -2506,12 +2512,6 @@ static struct samsung_gpio_chip exynos5_gpios_1[] = { .ngpio = EXYNOS5_GPIO_Y6_NR, .label = "GPY6", }, - }, { - .chip = { - .base = EXYNOS5_GPC4(0), - .ngpio = EXYNOS5_GPIO_C4_NR, - .label = "GPC4", - }, }, { .config = &samsung_gpio_cfgs[9], .irq_base = IRQ_EINT(0), @@ -2836,7 +2836,7 @@ static __init void exynos5_gpiolib_init(void) } /* need to set base address for gpc4 */ - exynos5_gpios_1[20].base = gpio_base1 + 0x2E0; + exynos5_gpios_1[11].base = gpio_base1 + 0x2E0; /* need to set base address for gpx */ chip = &exynos5_gpios_1[21]; diff --git a/trunk/drivers/gpio/gpio-sch.c b/trunk/drivers/gpio/gpio-sch.c index 8707d4572a06..424dce8e3f30 100644 --- a/trunk/drivers/gpio/gpio-sch.c +++ b/trunk/drivers/gpio/gpio-sch.c @@ -241,8 +241,7 @@ static int __devinit sch_gpio_probe(struct platform_device *pdev) break; default: - err = -ENODEV; - goto err_sch_gpio_core; + return -ENODEV; } sch_gpio_core.dev = &pdev->dev; diff --git a/trunk/drivers/gpio/gpiolib-of.c b/trunk/drivers/gpio/gpiolib-of.c index f1a45997aea8..a18c4aa68b1e 100644 --- a/trunk/drivers/gpio/gpiolib-of.c +++ b/trunk/drivers/gpio/gpiolib-of.c @@ -82,7 +82,7 @@ int of_get_named_gpio_flags(struct device_node *np, const char *propname, gpiochip_find(&gg_data, of_gpiochip_find_and_xlate); of_node_put(gg_data.gpiospec.np); - pr_debug("%s exited with status %d\n", __func__, gg_data.out_gpio); + pr_debug("%s exited with status %d\n", __func__, ret); return gg_data.out_gpio; } EXPORT_SYMBOL(of_get_named_gpio_flags); diff --git a/trunk/drivers/gpu/drm/Kconfig b/trunk/drivers/gpu/drm/Kconfig index 90e28081712d..23120c00a881 100644 --- a/trunk/drivers/gpu/drm/Kconfig +++ b/trunk/drivers/gpu/drm/Kconfig @@ -22,7 +22,6 @@ menuconfig DRM config DRM_USB tristate depends on DRM - depends on USB_ARCH_HAS_HCD select USB config DRM_KMS_HELPER diff --git a/trunk/drivers/gpu/drm/ast/ast_drv.c b/trunk/drivers/gpu/drm/ast/ast_drv.c index 36164806b9d4..d0c4574ef49c 100644 --- a/trunk/drivers/gpu/drm/ast/ast_drv.c +++ b/trunk/drivers/gpu/drm/ast/ast_drv.c @@ -193,9 +193,6 @@ static const struct file_operations ast_fops = { .mmap = ast_mmap, .poll = drm_poll, .fasync = drm_fasync, -#ifdef CONFIG_COMPAT - .compat_ioctl = drm_compat_ioctl, -#endif .read = drm_read, }; diff --git a/trunk/drivers/gpu/drm/ast/ast_mode.c b/trunk/drivers/gpu/drm/ast/ast_mode.c index a712cafcfa1d..7282c081fb53 100644 --- a/trunk/drivers/gpu/drm/ast/ast_mode.c +++ b/trunk/drivers/gpu/drm/ast/ast_mode.c @@ -841,7 +841,7 @@ int ast_cursor_init(struct drm_device *dev) ast->cursor_cache = obj; ast->cursor_cache_gpu_addr = gpu_addr; - DRM_DEBUG_KMS("pinned cursor cache at %llx\n", ast->cursor_cache_gpu_addr); + DRM_ERROR("pinned cursor cache at %llx\n", ast->cursor_cache_gpu_addr); return 0; fail: return ret; diff --git a/trunk/drivers/gpu/drm/cirrus/cirrus_drv.c b/trunk/drivers/gpu/drm/cirrus/cirrus_drv.c index b83a2d7ddd1a..7053140c6596 100644 --- a/trunk/drivers/gpu/drm/cirrus/cirrus_drv.c +++ b/trunk/drivers/gpu/drm/cirrus/cirrus_drv.c @@ -74,9 +74,6 @@ static const struct file_operations cirrus_driver_fops = { .unlocked_ioctl = drm_ioctl, .mmap = cirrus_mmap, .poll = drm_poll, -#ifdef CONFIG_COMPAT - .compat_ioctl = drm_compat_ioctl, -#endif .fasync = drm_fasync, }; static struct drm_driver driver = { diff --git a/trunk/drivers/gpu/drm/drm_crtc.c b/trunk/drivers/gpu/drm/drm_crtc.c index 6fbfc244748f..08a7aa722d6b 100644 --- a/trunk/drivers/gpu/drm/drm_crtc.c +++ b/trunk/drivers/gpu/drm/drm_crtc.c @@ -1981,7 +1981,7 @@ int drm_mode_cursor_ioctl(struct drm_device *dev, if (!drm_core_check_feature(dev, DRIVER_MODESET)) return -EINVAL; - if (!req->flags || (~DRM_MODE_CURSOR_FLAGS & req->flags)) + if (!req->flags) return -EINVAL; mutex_lock(&dev->mode_config.mutex); diff --git a/trunk/drivers/gpu/drm/drm_edid.c b/trunk/drivers/gpu/drm/drm_edid.c index b7ee230572b7..a8743c399e83 100644 --- a/trunk/drivers/gpu/drm/drm_edid.c +++ b/trunk/drivers/gpu/drm/drm_edid.c @@ -87,9 +87,6 @@ static struct edid_quirk { int product_id; u32 quirks; } edid_quirk_list[] = { - /* ASUS VW222S */ - { "ACI", 0x22a2, EDID_QUIRK_FORCE_REDUCED_BLANKING }, - /* Acer AL1706 */ { "ACR", 44358, EDID_QUIRK_PREFER_LARGE_60 }, /* Acer F51 */ diff --git a/trunk/drivers/gpu/drm/drm_edid_load.c b/trunk/drivers/gpu/drm/drm_edid_load.c index 0303935d10e2..66d4a28ad5a2 100644 --- a/trunk/drivers/gpu/drm/drm_edid_load.c +++ b/trunk/drivers/gpu/drm/drm_edid_load.c @@ -119,7 +119,7 @@ static int edid_load(struct drm_connector *connector, char *name, { const struct firmware *fw; struct platform_device *pdev; - u8 *fwdata = NULL, *edid, *new_edid; + u8 *fwdata = NULL, *edid; int fwsize, expected; int builtin = 0, err = 0; int i, valid_extensions = 0; @@ -195,14 +195,12 @@ static int edid_load(struct drm_connector *connector, char *name, "\"%s\" for connector \"%s\"\n", valid_extensions, edid[0x7e], name, connector_name); edid[0x7e] = valid_extensions; - new_edid = krealloc(edid, (valid_extensions + 1) * EDID_LENGTH, + edid = krealloc(edid, (valid_extensions + 1) * EDID_LENGTH, GFP_KERNEL); - if (new_edid == NULL) { + if (edid == NULL) { err = -ENOMEM; - kfree(edid); goto relfw_out; } - edid = new_edid; } connector->display_info.raw_edid = edid; diff --git a/trunk/drivers/gpu/drm/drm_modes.c b/trunk/drivers/gpu/drm/drm_modes.c index 28637c181b15..b7adb4a967fd 100644 --- a/trunk/drivers/gpu/drm/drm_modes.c +++ b/trunk/drivers/gpu/drm/drm_modes.c @@ -706,6 +706,9 @@ void drm_mode_set_crtcinfo(struct drm_display_mode *p, int adjust_flags) p->crtc_vblank_end = max(p->crtc_vsync_end, p->crtc_vtotal); p->crtc_hblank_start = min(p->crtc_hsync_start, p->crtc_hdisplay); p->crtc_hblank_end = max(p->crtc_hsync_end, p->crtc_htotal); + + p->crtc_hadjusted = false; + p->crtc_vadjusted = false; } EXPORT_SYMBOL(drm_mode_set_crtcinfo); diff --git a/trunk/drivers/gpu/drm/drm_proc.c b/trunk/drivers/gpu/drm/drm_proc.c index da457b18eaaf..371c695322d9 100644 --- a/trunk/drivers/gpu/drm/drm_proc.c +++ b/trunk/drivers/gpu/drm/drm_proc.c @@ -89,7 +89,7 @@ static const struct file_operations drm_proc_fops = { * Create a given set of proc files represented by an array of * gdm_proc_lists in the given root directory. */ -static int drm_proc_create_files(struct drm_info_list *files, int count, +int drm_proc_create_files(struct drm_info_list *files, int count, struct proc_dir_entry *root, struct drm_minor *minor) { struct drm_device *dev = minor->dev; @@ -172,7 +172,7 @@ int drm_proc_init(struct drm_minor *minor, int minor_id, return 0; } -static int drm_proc_remove_files(struct drm_info_list *files, int count, +int drm_proc_remove_files(struct drm_info_list *files, int count, struct drm_minor *minor) { struct list_head *pos, *q; diff --git a/trunk/drivers/gpu/drm/exynos/Kconfig b/trunk/drivers/gpu/drm/exynos/Kconfig index 59a26e577b57..7f5096763b7d 100644 --- a/trunk/drivers/gpu/drm/exynos/Kconfig +++ b/trunk/drivers/gpu/drm/exynos/Kconfig @@ -36,6 +36,6 @@ config DRM_EXYNOS_VIDI config DRM_EXYNOS_G2D bool "Exynos DRM G2D" - depends on DRM_EXYNOS && !VIDEO_SAMSUNG_S5P_G2D + depends on DRM_EXYNOS help Choose this option if you want to use Exynos G2D for DRM. diff --git a/trunk/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c b/trunk/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c index ae13febe0eaa..613bf8a5d9b2 100644 --- a/trunk/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c +++ b/trunk/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c @@ -163,12 +163,6 @@ static void exynos_gem_dmabuf_kunmap(struct dma_buf *dma_buf, /* TODO */ } -static int exynos_gem_dmabuf_mmap(struct dma_buf *dma_buf, - struct vm_area_struct *vma) -{ - return -ENOTTY; -} - static struct dma_buf_ops exynos_dmabuf_ops = { .map_dma_buf = exynos_gem_map_dma_buf, .unmap_dma_buf = exynos_gem_unmap_dma_buf, @@ -176,7 +170,6 @@ static struct dma_buf_ops exynos_dmabuf_ops = { .kmap_atomic = exynos_gem_dmabuf_kmap_atomic, .kunmap = exynos_gem_dmabuf_kunmap, .kunmap_atomic = exynos_gem_dmabuf_kunmap_atomic, - .mmap = exynos_gem_dmabuf_mmap, .release = exynos_dmabuf_release, }; diff --git a/trunk/drivers/gpu/drm/exynos/exynos_drm_drv.c b/trunk/drivers/gpu/drm/exynos/exynos_drm_drv.c index d07071937453..ebacec6f1e48 100644 --- a/trunk/drivers/gpu/drm/exynos/exynos_drm_drv.c +++ b/trunk/drivers/gpu/drm/exynos/exynos_drm_drv.c @@ -160,6 +160,7 @@ static int exynos_drm_open(struct drm_device *dev, struct drm_file *file) if (!file_priv) return -ENOMEM; + drm_prime_init_file_private(&file->prime); file->driver_priv = file_priv; return exynos_drm_subdrv_open(dev, file); @@ -183,6 +184,7 @@ static void exynos_drm_preclose(struct drm_device *dev, e->base.destroy(&e->base); } } + drm_prime_destroy_file_private(&file->prime); spin_unlock_irqrestore(&dev->event_lock, flags); exynos_drm_subdrv_close(dev, file); @@ -239,9 +241,6 @@ static const struct file_operations exynos_drm_driver_fops = { .poll = drm_poll, .read = drm_read, .unlocked_ioctl = drm_ioctl, -#ifdef CONFIG_COMPAT - .compat_ioctl = drm_compat_ioctl, -#endif .release = drm_release, }; diff --git a/trunk/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/trunk/drivers/gpu/drm/exynos/exynos_drm_fimd.c index b19cd93e7047..a68d2b313f03 100644 --- a/trunk/drivers/gpu/drm/exynos/exynos_drm_fimd.c +++ b/trunk/drivers/gpu/drm/exynos/exynos_drm_fimd.c @@ -831,6 +831,11 @@ static int __devinit fimd_probe(struct platform_device *pdev) } res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(dev, "failed to find registers\n"); + ret = -ENOENT; + goto err_clk; + } ctx->regs = devm_request_and_ioremap(&pdev->dev, res); if (!ctx->regs) { diff --git a/trunk/drivers/gpu/drm/exynos/exynos_drm_g2d.c b/trunk/drivers/gpu/drm/exynos/exynos_drm_g2d.c index 1065e90d0919..d2d88f22a037 100644 --- a/trunk/drivers/gpu/drm/exynos/exynos_drm_g2d.c +++ b/trunk/drivers/gpu/drm/exynos/exynos_drm_g2d.c @@ -129,6 +129,7 @@ struct g2d_runqueue_node { struct g2d_data { struct device *dev; struct clk *gate_clk; + struct resource *regs_res; void __iomem *regs; int irq; struct workqueue_struct *g2d_workq; @@ -750,7 +751,7 @@ static int __devinit g2d_probe(struct platform_device *pdev) struct exynos_drm_subdrv *subdrv; int ret; - g2d = devm_kzalloc(&pdev->dev, sizeof(*g2d), GFP_KERNEL); + g2d = kzalloc(sizeof(*g2d), GFP_KERNEL); if (!g2d) { dev_err(dev, "failed to allocate driver data\n"); return -ENOMEM; @@ -758,8 +759,10 @@ static int __devinit g2d_probe(struct platform_device *pdev) g2d->runqueue_slab = kmem_cache_create("g2d_runqueue_slab", sizeof(struct g2d_runqueue_node), 0, 0, NULL); - if (!g2d->runqueue_slab) - return -ENOMEM; + if (!g2d->runqueue_slab) { + ret = -ENOMEM; + goto err_free_mem; + } g2d->dev = dev; @@ -791,26 +794,38 @@ static int __devinit g2d_probe(struct platform_device *pdev) pm_runtime_enable(dev); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(dev, "failed to get I/O memory\n"); + ret = -ENOENT; + goto err_put_clk; + } - g2d->regs = devm_request_and_ioremap(&pdev->dev, res); + g2d->regs_res = request_mem_region(res->start, resource_size(res), + dev_name(dev)); + if (!g2d->regs_res) { + dev_err(dev, "failed to request I/O memory\n"); + ret = -ENOENT; + goto err_put_clk; + } + + g2d->regs = ioremap(res->start, resource_size(res)); if (!g2d->regs) { dev_err(dev, "failed to remap I/O memory\n"); ret = -ENXIO; - goto err_put_clk; + goto err_release_res; } g2d->irq = platform_get_irq(pdev, 0); if (g2d->irq < 0) { dev_err(dev, "failed to get irq\n"); ret = g2d->irq; - goto err_put_clk; + goto err_unmap_base; } - ret = devm_request_irq(&pdev->dev, g2d->irq, g2d_irq_handler, 0, - "drm_g2d", g2d); + ret = request_irq(g2d->irq, g2d_irq_handler, 0, "drm_g2d", g2d); if (ret < 0) { dev_err(dev, "irq request failed\n"); - goto err_put_clk; + goto err_unmap_base; } platform_set_drvdata(pdev, g2d); @@ -823,7 +838,7 @@ static int __devinit g2d_probe(struct platform_device *pdev) ret = exynos_drm_subdrv_register(subdrv); if (ret < 0) { dev_err(dev, "failed to register drm g2d device\n"); - goto err_put_clk; + goto err_free_irq; } dev_info(dev, "The exynos g2d(ver %d.%d) successfully probed\n", @@ -831,6 +846,13 @@ static int __devinit g2d_probe(struct platform_device *pdev) return 0; +err_free_irq: + free_irq(g2d->irq, g2d); +err_unmap_base: + iounmap(g2d->regs); +err_release_res: + release_resource(g2d->regs_res); + kfree(g2d->regs_res); err_put_clk: pm_runtime_disable(dev); clk_put(g2d->gate_clk); @@ -840,6 +862,8 @@ static int __devinit g2d_probe(struct platform_device *pdev) destroy_workqueue(g2d->g2d_workq); err_destroy_slab: kmem_cache_destroy(g2d->runqueue_slab); +err_free_mem: + kfree(g2d); return ret; } @@ -849,18 +873,24 @@ static int __devexit g2d_remove(struct platform_device *pdev) cancel_work_sync(&g2d->runqueue_work); exynos_drm_subdrv_unregister(&g2d->subdrv); + free_irq(g2d->irq, g2d); while (g2d->runqueue_node) { g2d_free_runqueue_node(g2d, g2d->runqueue_node); g2d->runqueue_node = g2d_get_runqueue_node(g2d); } + iounmap(g2d->regs); + release_resource(g2d->regs_res); + kfree(g2d->regs_res); + pm_runtime_disable(&pdev->dev); clk_put(g2d->gate_clk); g2d_fini_cmdlist(g2d); destroy_workqueue(g2d->g2d_workq); kmem_cache_destroy(g2d->runqueue_slab); + kfree(g2d); return 0; } @@ -894,7 +924,7 @@ static int g2d_resume(struct device *dev) } #endif -static SIMPLE_DEV_PM_OPS(g2d_pm_ops, g2d_suspend, g2d_resume); +SIMPLE_DEV_PM_OPS(g2d_pm_ops, g2d_suspend, g2d_resume); struct platform_driver g2d_driver = { .probe = g2d_probe, diff --git a/trunk/drivers/gpu/drm/exynos/exynos_drm_gem.c b/trunk/drivers/gpu/drm/exynos/exynos_drm_gem.c index a38051c95ec4..f9efde40c097 100644 --- a/trunk/drivers/gpu/drm/exynos/exynos_drm_gem.c +++ b/trunk/drivers/gpu/drm/exynos/exynos_drm_gem.c @@ -122,7 +122,7 @@ struct page **exynos_gem_get_pages(struct drm_gem_object *obj, __free_page(pages[i]); drm_free_large(pages); - return ERR_CAST(p); + return ERR_PTR(PTR_ERR(p)); } static void exynos_gem_put_pages(struct drm_gem_object *obj, @@ -662,7 +662,7 @@ int exynos_drm_gem_dumb_create(struct drm_file *file_priv, */ args->pitch = args->width * ((args->bpp + 7) / 8); - args->size = args->pitch * args->height; + args->size = PAGE_ALIGN(args->pitch * args->height); exynos_gem_obj = exynos_drm_gem_create(dev, args->flags, args->size); if (IS_ERR(exynos_gem_obj)) diff --git a/trunk/drivers/gpu/drm/exynos/exynos_drm_hdmi.c b/trunk/drivers/gpu/drm/exynos/exynos_drm_hdmi.c index 3fdf0b65f47e..8ffcdf8b9e22 100644 --- a/trunk/drivers/gpu/drm/exynos/exynos_drm_hdmi.c +++ b/trunk/drivers/gpu/drm/exynos/exynos_drm_hdmi.c @@ -345,7 +345,7 @@ static int __devinit exynos_drm_hdmi_probe(struct platform_device *pdev) DRM_DEBUG_KMS("%s\n", __FILE__); - ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL); + ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); if (!ctx) { DRM_LOG_KMS("failed to alloc common hdmi context.\n"); return -ENOMEM; @@ -371,6 +371,7 @@ static int __devexit exynos_drm_hdmi_remove(struct platform_device *pdev) DRM_DEBUG_KMS("%s\n", __FILE__); exynos_drm_subdrv_unregister(&ctx->subdrv); + kfree(ctx); return 0; } diff --git a/trunk/drivers/gpu/drm/exynos/exynos_drm_plane.c b/trunk/drivers/gpu/drm/exynos/exynos_drm_plane.c index e1f94b746bd7..b89829e5043a 100644 --- a/trunk/drivers/gpu/drm/exynos/exynos_drm_plane.c +++ b/trunk/drivers/gpu/drm/exynos/exynos_drm_plane.c @@ -29,6 +29,7 @@ static const uint32_t formats[] = { DRM_FORMAT_XRGB8888, DRM_FORMAT_ARGB8888, DRM_FORMAT_NV12, + DRM_FORMAT_NV12M, DRM_FORMAT_NV12MT, }; diff --git a/trunk/drivers/gpu/drm/exynos/exynos_drm_vidi.c b/trunk/drivers/gpu/drm/exynos/exynos_drm_vidi.c index 537027a74fd5..bb1550c4dd57 100644 --- a/trunk/drivers/gpu/drm/exynos/exynos_drm_vidi.c +++ b/trunk/drivers/gpu/drm/exynos/exynos_drm_vidi.c @@ -633,7 +633,7 @@ static int __devinit vidi_probe(struct platform_device *pdev) DRM_DEBUG_KMS("%s\n", __FILE__); - ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL); + ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); if (!ctx) return -ENOMEM; @@ -673,6 +673,8 @@ static int __devexit vidi_remove(struct platform_device *pdev) ctx->raw_edid = NULL; } + kfree(ctx); + return 0; } diff --git a/trunk/drivers/gpu/drm/exynos/exynos_hdmi.c b/trunk/drivers/gpu/drm/exynos/exynos_hdmi.c index a6aea6f3ea1a..409e2ec1207c 100644 --- a/trunk/drivers/gpu/drm/exynos/exynos_hdmi.c +++ b/trunk/drivers/gpu/drm/exynos/exynos_hdmi.c @@ -2172,7 +2172,7 @@ static int __devinit hdmi_resources_init(struct hdmi_context *hdata) DRM_DEBUG_KMS("HDMI resource init\n"); - memset(res, 0, sizeof(*res)); + memset(res, 0, sizeof *res); /* get clocks, power */ res->hdmi = clk_get(dev, "hdmi"); @@ -2204,7 +2204,7 @@ static int __devinit hdmi_resources_init(struct hdmi_context *hdata) clk_set_parent(res->sclk_hdmi, res->sclk_pixel); res->regul_bulk = kzalloc(ARRAY_SIZE(supply) * - sizeof(res->regul_bulk[0]), GFP_KERNEL); + sizeof res->regul_bulk[0], GFP_KERNEL); if (!res->regul_bulk) { DRM_ERROR("failed to get memory for regulators\n"); goto fail; @@ -2243,7 +2243,7 @@ static int hdmi_resources_cleanup(struct hdmi_context *hdata) clk_put(res->sclk_hdmi); if (!IS_ERR_OR_NULL(res->hdmi)) clk_put(res->hdmi); - memset(res, 0, sizeof(*res)); + memset(res, 0, sizeof *res); return 0; } @@ -2312,6 +2312,11 @@ static int __devinit hdmi_probe(struct platform_device *pdev) } res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + DRM_ERROR("failed to find registers\n"); + ret = -ENOENT; + goto err_resource; + } hdata->regs = devm_request_and_ioremap(&pdev->dev, res); if (!hdata->regs) { diff --git a/trunk/drivers/gpu/drm/exynos/exynos_mixer.c b/trunk/drivers/gpu/drm/exynos/exynos_mixer.c index 25b97d5e5fcb..30fcc12f81dd 100644 --- a/trunk/drivers/gpu/drm/exynos/exynos_mixer.c +++ b/trunk/drivers/gpu/drm/exynos/exynos_mixer.c @@ -236,11 +236,11 @@ static inline void vp_filter_set(struct mixer_resources *res, static void vp_default_filter(struct mixer_resources *res) { vp_filter_set(res, VP_POLY8_Y0_LL, - filter_y_horiz_tap8, sizeof(filter_y_horiz_tap8)); + filter_y_horiz_tap8, sizeof filter_y_horiz_tap8); vp_filter_set(res, VP_POLY4_Y0_LL, - filter_y_vert_tap4, sizeof(filter_y_vert_tap4)); + filter_y_vert_tap4, sizeof filter_y_vert_tap4); vp_filter_set(res, VP_POLY4_C0_LL, - filter_cr_horiz_tap4, sizeof(filter_cr_horiz_tap4)); + filter_cr_horiz_tap4, sizeof filter_cr_horiz_tap4); } static void mixer_vsync_set_update(struct mixer_context *ctx, bool enable) diff --git a/trunk/drivers/gpu/drm/gma500/oaktrail_device.c b/trunk/drivers/gpu/drm/gma500/oaktrail_device.c index cf49ba5a54bf..0f9b7db80f6b 100644 --- a/trunk/drivers/gpu/drm/gma500/oaktrail_device.c +++ b/trunk/drivers/gpu/drm/gma500/oaktrail_device.c @@ -476,7 +476,6 @@ static const struct psb_offset oaktrail_regmap[2] = { .pos = DSPAPOS, .surf = DSPASURF, .addr = MRST_DSPABASE, - .base = MRST_DSPABASE, .status = PIPEASTAT, .linoff = DSPALINOFF, .tileoff = DSPATILEOFF, @@ -500,7 +499,6 @@ static const struct psb_offset oaktrail_regmap[2] = { .pos = DSPBPOS, .surf = DSPBSURF, .addr = DSPBBASE, - .base = DSPBBASE, .status = PIPEBSTAT, .linoff = DSPBLINOFF, .tileoff = DSPBTILEOFF, diff --git a/trunk/drivers/gpu/drm/gma500/psb_intel_display.c b/trunk/drivers/gpu/drm/gma500/psb_intel_display.c index 8033526bb53b..30dc22a7156c 100644 --- a/trunk/drivers/gpu/drm/gma500/psb_intel_display.c +++ b/trunk/drivers/gpu/drm/gma500/psb_intel_display.c @@ -1362,9 +1362,6 @@ void psb_intel_crtc_init(struct drm_device *dev, int pipe, (struct drm_connector **) (psb_intel_crtc + 1); psb_intel_crtc->mode_set.num_connectors = 0; psb_intel_cursor_init(dev, psb_intel_crtc); - - /* Set to true so that the pipe is forced off on initial config. */ - psb_intel_crtc->active = true; } int psb_intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data, diff --git a/trunk/drivers/gpu/drm/i810/i810_dma.c b/trunk/drivers/gpu/drm/i810/i810_dma.c index 463ec6871fe9..57d892eaaa6e 100644 --- a/trunk/drivers/gpu/drm/i810/i810_dma.c +++ b/trunk/drivers/gpu/drm/i810/i810_dma.c @@ -115,9 +115,6 @@ static const struct file_operations i810_buffer_fops = { .unlocked_ioctl = drm_ioctl, .mmap = i810_mmap_buffers, .fasync = drm_fasync, -#ifdef CONFIG_COMPAT - .compat_ioctl = drm_compat_ioctl, -#endif .llseek = noop_llseek, }; diff --git a/trunk/drivers/gpu/drm/i810/i810_drv.c b/trunk/drivers/gpu/drm/i810/i810_drv.c index 48cfcca2b350..f9924ad04d09 100644 --- a/trunk/drivers/gpu/drm/i810/i810_drv.c +++ b/trunk/drivers/gpu/drm/i810/i810_drv.c @@ -51,9 +51,6 @@ static const struct file_operations i810_driver_fops = { .mmap = drm_mmap, .poll = drm_poll, .fasync = drm_fasync, -#ifdef CONFIG_COMPAT - .compat_ioctl = drm_compat_ioctl, -#endif .llseek = noop_llseek, }; diff --git a/trunk/drivers/gpu/drm/i915/i915_dma.c b/trunk/drivers/gpu/drm/i915/i915_dma.c index 914c0dfabe60..9cf7dfe022b9 100644 --- a/trunk/drivers/gpu/drm/i915/i915_dma.c +++ b/trunk/drivers/gpu/drm/i915/i915_dma.c @@ -1587,7 +1587,6 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) spin_lock_init(&dev_priv->irq_lock); spin_lock_init(&dev_priv->error_lock); spin_lock_init(&dev_priv->rps_lock); - spin_lock_init(&dev_priv->dpio_lock); if (IS_IVYBRIDGE(dev) || IS_HASWELL(dev)) dev_priv->num_pipe = 3; diff --git a/trunk/drivers/gpu/drm/i915/i915_drv.c b/trunk/drivers/gpu/drm/i915/i915_drv.c index a24ffbe97c01..ed22612bc847 100644 --- a/trunk/drivers/gpu/drm/i915/i915_drv.c +++ b/trunk/drivers/gpu/drm/i915/i915_drv.c @@ -346,40 +346,11 @@ static const struct pci_device_id pciidlist[] = { /* aka */ INTEL_VGA_DEVICE(0x016a, &intel_ivybridge_d_info), /* GT2 server */ INTEL_VGA_DEVICE(0x0402, &intel_haswell_d_info), /* GT1 desktop */ INTEL_VGA_DEVICE(0x0412, &intel_haswell_d_info), /* GT2 desktop */ - INTEL_VGA_DEVICE(0x0422, &intel_haswell_d_info), /* GT2 desktop */ INTEL_VGA_DEVICE(0x040a, &intel_haswell_d_info), /* GT1 server */ INTEL_VGA_DEVICE(0x041a, &intel_haswell_d_info), /* GT2 server */ - INTEL_VGA_DEVICE(0x042a, &intel_haswell_d_info), /* GT2 server */ INTEL_VGA_DEVICE(0x0406, &intel_haswell_m_info), /* GT1 mobile */ INTEL_VGA_DEVICE(0x0416, &intel_haswell_m_info), /* GT2 mobile */ - INTEL_VGA_DEVICE(0x0426, &intel_haswell_m_info), /* GT2 mobile */ - INTEL_VGA_DEVICE(0x0C02, &intel_haswell_d_info), /* SDV GT1 desktop */ - INTEL_VGA_DEVICE(0x0C12, &intel_haswell_d_info), /* SDV GT2 desktop */ - INTEL_VGA_DEVICE(0x0C22, &intel_haswell_d_info), /* SDV GT2 desktop */ - INTEL_VGA_DEVICE(0x0C0A, &intel_haswell_d_info), /* SDV GT1 server */ - INTEL_VGA_DEVICE(0x0C1A, &intel_haswell_d_info), /* SDV GT2 server */ - INTEL_VGA_DEVICE(0x0C2A, &intel_haswell_d_info), /* SDV GT2 server */ - INTEL_VGA_DEVICE(0x0C06, &intel_haswell_m_info), /* SDV GT1 mobile */ - INTEL_VGA_DEVICE(0x0C16, &intel_haswell_m_info), /* SDV GT2 mobile */ - INTEL_VGA_DEVICE(0x0C26, &intel_haswell_m_info), /* SDV GT2 mobile */ - INTEL_VGA_DEVICE(0x0A02, &intel_haswell_d_info), /* ULT GT1 desktop */ - INTEL_VGA_DEVICE(0x0A12, &intel_haswell_d_info), /* ULT GT2 desktop */ - INTEL_VGA_DEVICE(0x0A22, &intel_haswell_d_info), /* ULT GT2 desktop */ - INTEL_VGA_DEVICE(0x0A0A, &intel_haswell_d_info), /* ULT GT1 server */ - INTEL_VGA_DEVICE(0x0A1A, &intel_haswell_d_info), /* ULT GT2 server */ - INTEL_VGA_DEVICE(0x0A2A, &intel_haswell_d_info), /* ULT GT2 server */ - INTEL_VGA_DEVICE(0x0A06, &intel_haswell_m_info), /* ULT GT1 mobile */ - INTEL_VGA_DEVICE(0x0A16, &intel_haswell_m_info), /* ULT GT2 mobile */ - INTEL_VGA_DEVICE(0x0A26, &intel_haswell_m_info), /* ULT GT2 mobile */ - INTEL_VGA_DEVICE(0x0D12, &intel_haswell_d_info), /* CRW GT1 desktop */ - INTEL_VGA_DEVICE(0x0D22, &intel_haswell_d_info), /* CRW GT2 desktop */ - INTEL_VGA_DEVICE(0x0D32, &intel_haswell_d_info), /* CRW GT2 desktop */ - INTEL_VGA_DEVICE(0x0D1A, &intel_haswell_d_info), /* CRW GT1 server */ - INTEL_VGA_DEVICE(0x0D2A, &intel_haswell_d_info), /* CRW GT2 server */ - INTEL_VGA_DEVICE(0x0D3A, &intel_haswell_d_info), /* CRW GT2 server */ - INTEL_VGA_DEVICE(0x0D16, &intel_haswell_m_info), /* CRW GT1 mobile */ - INTEL_VGA_DEVICE(0x0D26, &intel_haswell_m_info), /* CRW GT2 mobile */ - INTEL_VGA_DEVICE(0x0D36, &intel_haswell_m_info), /* CRW GT2 mobile */ + INTEL_VGA_DEVICE(0x0c16, &intel_haswell_d_info), /* SDV */ INTEL_VGA_DEVICE(0x0f30, &intel_valleyview_m_info), INTEL_VGA_DEVICE(0x0157, &intel_valleyview_m_info), INTEL_VGA_DEVICE(0x0155, &intel_valleyview_d_info), diff --git a/trunk/drivers/gpu/drm/i915/i915_gem.c b/trunk/drivers/gpu/drm/i915/i915_gem.c index 274d25de521e..5c4657a54f97 100644 --- a/trunk/drivers/gpu/drm/i915/i915_gem.c +++ b/trunk/drivers/gpu/drm/i915/i915_gem.c @@ -2365,10 +2365,6 @@ int i915_gpu_idle(struct drm_device *dev) /* Flush everything onto the inactive list. */ for_each_ring(ring, dev_priv, i) { - ret = i915_switch_context(ring, NULL, DEFAULT_CONTEXT_ID); - if (ret) - return ret; - ret = i915_ring_idle(ring); if (ret) return ret; @@ -2376,6 +2372,10 @@ int i915_gpu_idle(struct drm_device *dev) /* Is the device fubar? */ if (WARN_ON(!list_empty(&ring->gpu_write_list))) return -EBUSY; + + ret = i915_switch_context(ring, NULL, DEFAULT_CONTEXT_ID); + if (ret) + return ret; } return 0; @@ -3242,8 +3242,7 @@ i915_gem_object_pin(struct drm_i915_gem_object *obj, { int ret; - if (WARN_ON(obj->pin_count == DRM_I915_GEM_OBJECT_MAX_PIN_COUNT)) - return -EBUSY; + BUG_ON(obj->pin_count == DRM_I915_GEM_OBJECT_MAX_PIN_COUNT); if (obj->gtt_space != NULL) { if ((alignment && obj->gtt_offset & (alignment - 1)) || diff --git a/trunk/drivers/gpu/drm/i915/i915_gem_context.c b/trunk/drivers/gpu/drm/i915/i915_gem_context.c index a9d58d72bb4d..da8b01fb1bf8 100644 --- a/trunk/drivers/gpu/drm/i915/i915_gem_context.c +++ b/trunk/drivers/gpu/drm/i915/i915_gem_context.c @@ -451,6 +451,7 @@ int i915_switch_context(struct intel_ring_buffer *ring, struct drm_i915_file_private *file_priv = NULL; struct i915_hw_context *to; struct drm_i915_gem_object *from_obj = ring->last_context_obj; + int ret; if (dev_priv->hw_contexts_disabled) return 0; diff --git a/trunk/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/trunk/drivers/gpu/drm/i915/i915_gem_execbuffer.c index ff2819ea0813..5af631e788c8 100644 --- a/trunk/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/trunk/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -291,16 +291,6 @@ i915_gem_execbuffer_relocate_entry(struct drm_i915_gem_object *obj, target_i915_obj = to_intel_bo(target_obj); target_offset = target_i915_obj->gtt_offset; - /* Sandybridge PPGTT errata: We need a global gtt mapping for MI and - * pipe_control writes because the gpu doesn't properly redirect them - * through the ppgtt for non_secure batchbuffers. */ - if (unlikely(IS_GEN6(dev) && - reloc->write_domain == I915_GEM_DOMAIN_INSTRUCTION && - !target_i915_obj->has_global_gtt_mapping)) { - i915_gem_gtt_bind_object(target_i915_obj, - target_i915_obj->cache_level); - } - /* The target buffer should have appeared before us in the * exec_object list, so it should have a GTT space bound by now. */ @@ -409,6 +399,16 @@ i915_gem_execbuffer_relocate_entry(struct drm_i915_gem_object *obj, io_mapping_unmap_atomic(reloc_page); } + /* Sandybridge PPGTT errata: We need a global gtt mapping for MI and + * pipe_control writes because the gpu doesn't properly redirect them + * through the ppgtt for non_secure batchbuffers. */ + if (unlikely(IS_GEN6(dev) && + reloc->write_domain == I915_GEM_DOMAIN_INSTRUCTION && + !target_i915_obj->has_global_gtt_mapping)) { + i915_gem_gtt_bind_object(target_i915_obj, + target_i915_obj->cache_level); + } + /* and update the user's relocation entry */ reloc->presumed_offset = target_offset; diff --git a/trunk/drivers/gpu/drm/i915/i915_gem_gtt.c b/trunk/drivers/gpu/drm/i915/i915_gem_gtt.c index 60815b861ec2..9fd25a435536 100644 --- a/trunk/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/trunk/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -72,7 +72,7 @@ int i915_gem_init_aliasing_ppgtt(struct drm_device *dev) /* ppgtt PDEs reside in the global gtt pagetable, which has 512*1024 * entries. For aliasing ppgtt support we just steal them at the end for * now. */ - first_pd_entry_in_global_pt = dev_priv->mm.gtt->gtt_total_entries - I915_PPGTT_PD_ENTRIES; + first_pd_entry_in_global_pt = 512*1024 - I915_PPGTT_PD_ENTRIES; ppgtt = kzalloc(sizeof(*ppgtt), GFP_KERNEL); if (!ppgtt) @@ -261,10 +261,7 @@ void i915_ppgtt_bind_object(struct i915_hw_ppgtt *ppgtt, pte_flags |= GEN6_PTE_CACHE_LLC; break; case I915_CACHE_NONE: - if (IS_HASWELL(dev)) - pte_flags |= HSW_PTE_UNCACHED; - else - pte_flags |= GEN6_PTE_UNCACHED; + pte_flags |= GEN6_PTE_UNCACHED; break; default: BUG(); @@ -364,8 +361,7 @@ int i915_gem_gtt_prepare_object(struct drm_i915_gem_object *obj) struct drm_device *dev = obj->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; - /* don't map imported dma buf objects */ - if (dev_priv->mm.gtt->needs_dmar && !obj->sg_table) + if (dev_priv->mm.gtt->needs_dmar) return intel_gtt_map_memory(obj->pages, obj->base.size >> PAGE_SHIFT, &obj->sg_list, diff --git a/trunk/drivers/gpu/drm/i915/i915_irq.c b/trunk/drivers/gpu/drm/i915/i915_irq.c index 5249640cce13..8a3828528b9d 100644 --- a/trunk/drivers/gpu/drm/i915/i915_irq.c +++ b/trunk/drivers/gpu/drm/i915/i915_irq.c @@ -2700,6 +2700,9 @@ void intel_irq_init(struct drm_device *dev) dev->driver->irq_handler = i8xx_irq_handler; dev->driver->irq_uninstall = i8xx_irq_uninstall; } else if (INTEL_INFO(dev)->gen == 3) { + /* IIR "flip pending" means done if this bit is set */ + I915_WRITE(ECOSKPD, _MASKED_BIT_DISABLE(ECO_FLIP_DONE)); + dev->driver->irq_preinstall = i915_irq_preinstall; dev->driver->irq_postinstall = i915_irq_postinstall; dev->driver->irq_uninstall = i915_irq_uninstall; diff --git a/trunk/drivers/gpu/drm/i915/i915_reg.h b/trunk/drivers/gpu/drm/i915/i915_reg.h index 28725ce5b82c..acc99b21e0b6 100644 --- a/trunk/drivers/gpu/drm/i915/i915_reg.h +++ b/trunk/drivers/gpu/drm/i915/i915_reg.h @@ -115,7 +115,6 @@ #define GEN6_PTE_VALID (1 << 0) #define GEN6_PTE_UNCACHED (1 << 1) -#define HSW_PTE_UNCACHED (0) #define GEN6_PTE_CACHE_LLC (2 << 1) #define GEN6_PTE_CACHE_LLC_MLC (3 << 1) #define GEN6_PTE_CACHE_BITS (3 << 1) diff --git a/trunk/drivers/gpu/drm/i915/i915_sysfs.c b/trunk/drivers/gpu/drm/i915/i915_sysfs.c index 7631807a2788..2f5388af8df9 100644 --- a/trunk/drivers/gpu/drm/i915/i915_sysfs.c +++ b/trunk/drivers/gpu/drm/i915/i915_sysfs.c @@ -32,7 +32,6 @@ #include "intel_drv.h" #include "i915_drv.h" -#ifdef CONFIG_PM static u32 calc_residency(struct drm_device *dev, const u32 reg) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -225,14 +224,3 @@ void i915_teardown_sysfs(struct drm_device *dev) device_remove_bin_file(&dev->primary->kdev, &dpf_attrs); sysfs_unmerge_group(&dev->primary->kdev.kobj, &rc6_attr_group); } -#else -void i915_setup_sysfs(struct drm_device *dev) -{ - return; -} - -void i915_teardown_sysfs(struct drm_device *dev) -{ - return; -} -#endif /* CONFIG_PM */ diff --git a/trunk/drivers/gpu/drm/i915/intel_crt.c b/trunk/drivers/gpu/drm/i915/intel_crt.c index 23bdc8cd1458..7ed4a41c3965 100644 --- a/trunk/drivers/gpu/drm/i915/intel_crt.c +++ b/trunk/drivers/gpu/drm/i915/intel_crt.c @@ -326,36 +326,6 @@ static bool intel_crt_detect_hotplug(struct drm_connector *connector) return ret; } -static struct edid *intel_crt_get_edid(struct drm_connector *connector, - struct i2c_adapter *i2c) -{ - struct edid *edid; - - edid = drm_get_edid(connector, i2c); - - if (!edid && !intel_gmbus_is_forced_bit(i2c)) { - DRM_DEBUG_KMS("CRT GMBUS EDID read failed, retry using GPIO bit-banging\n"); - intel_gmbus_force_bit(i2c, true); - edid = drm_get_edid(connector, i2c); - intel_gmbus_force_bit(i2c, false); - } - - return edid; -} - -/* local version of intel_ddc_get_modes() to use intel_crt_get_edid() */ -static int intel_crt_ddc_get_modes(struct drm_connector *connector, - struct i2c_adapter *adapter) -{ - struct edid *edid; - - edid = intel_crt_get_edid(connector, adapter); - if (!edid) - return 0; - - return intel_connector_update_modes(connector, edid); -} - static bool intel_crt_detect_ddc(struct drm_connector *connector) { struct intel_crt *crt = intel_attached_crt(connector); @@ -366,7 +336,7 @@ static bool intel_crt_detect_ddc(struct drm_connector *connector) BUG_ON(crt->base.type != INTEL_OUTPUT_ANALOG); i2c = intel_gmbus_get_adapter(dev_priv, dev_priv->crt_ddc_pin); - edid = intel_crt_get_edid(connector, i2c); + edid = drm_get_edid(connector, i2c); if (edid) { bool is_digital = edid->input & DRM_EDID_INPUT_DIGITAL; @@ -574,13 +544,13 @@ static int intel_crt_get_modes(struct drm_connector *connector) struct i2c_adapter *i2c; i2c = intel_gmbus_get_adapter(dev_priv, dev_priv->crt_ddc_pin); - ret = intel_crt_ddc_get_modes(connector, i2c); + ret = intel_ddc_get_modes(connector, i2c); if (ret || !IS_G4X(dev)) return ret; /* Try to probe digital port for output in DVI-I -> VGA mode. */ i2c = intel_gmbus_get_adapter(dev_priv, GMBUS_PORT_DPB); - return intel_crt_ddc_get_modes(connector, i2c); + return intel_ddc_get_modes(connector, i2c); } static int intel_crt_set_property(struct drm_connector *connector, diff --git a/trunk/drivers/gpu/drm/i915/intel_display.c b/trunk/drivers/gpu/drm/i915/intel_display.c index c040aee1341c..f6159765f1eb 100644 --- a/trunk/drivers/gpu/drm/i915/intel_display.c +++ b/trunk/drivers/gpu/drm/i915/intel_display.c @@ -869,7 +869,6 @@ intel_vlv_find_best_pll(const intel_limit_t *limit, struct drm_crtc *crtc, unsigned long bestppm, ppm, absppm; int dotclk, flag; - flag = 0; dotclk = target * 1000; bestppm = 1000000; ppm = absppm = 0; @@ -1376,8 +1375,7 @@ static void assert_pch_dp_disabled(struct drm_i915_private *dev_priv, "PCH DP (0x%08x) enabled on transcoder %c, should be disabled\n", reg, pipe_name(pipe)); - WARN(HAS_PCH_IBX(dev_priv->dev) && (val & DP_PORT_EN) == 0 - && (val & DP_PIPEB_SELECT), + WARN(HAS_PCH_IBX(dev_priv->dev) && (val & SDVO_PIPE_B_SELECT), "IBX PCH dp port still using transcoder B\n"); } @@ -1385,12 +1383,11 @@ static void assert_pch_hdmi_disabled(struct drm_i915_private *dev_priv, enum pipe pipe, int reg) { u32 val = I915_READ(reg); - WARN(hdmi_pipe_enabled(dev_priv, pipe, val), + WARN(hdmi_pipe_enabled(dev_priv, val, pipe), "PCH HDMI (0x%08x) enabled on transcoder %c, should be disabled\n", reg, pipe_name(pipe)); - WARN(HAS_PCH_IBX(dev_priv->dev) && (val & PORT_ENABLE) == 0 - && (val & SDVO_PIPE_B_SELECT), + WARN(HAS_PCH_IBX(dev_priv->dev) && (val & SDVO_PIPE_B_SELECT), "IBX PCH hdmi port still using transcoder B\n"); } @@ -1406,13 +1403,13 @@ static void assert_pch_ports_disabled(struct drm_i915_private *dev_priv, reg = PCH_ADPA; val = I915_READ(reg); - WARN(adpa_pipe_enabled(dev_priv, pipe, val), + WARN(adpa_pipe_enabled(dev_priv, val, pipe), "PCH VGA enabled on transcoder %c, should be disabled\n", pipe_name(pipe)); reg = PCH_LVDS; val = I915_READ(reg); - WARN(lvds_pipe_enabled(dev_priv, pipe, val), + WARN(lvds_pipe_enabled(dev_priv, val, pipe), "PCH LVDS enabled on transcoder %c, should be disabled\n", pipe_name(pipe)); @@ -1874,7 +1871,7 @@ static void disable_pch_hdmi(struct drm_i915_private *dev_priv, enum pipe pipe, int reg) { u32 val = I915_READ(reg); - if (hdmi_pipe_enabled(dev_priv, pipe, val)) { + if (hdmi_pipe_enabled(dev_priv, val, pipe)) { DRM_DEBUG_KMS("Disabling pch HDMI %x on pipe %d\n", reg, pipe); I915_WRITE(reg, val & ~PORT_ENABLE); @@ -1896,12 +1893,12 @@ static void intel_disable_pch_ports(struct drm_i915_private *dev_priv, reg = PCH_ADPA; val = I915_READ(reg); - if (adpa_pipe_enabled(dev_priv, pipe, val)) + if (adpa_pipe_enabled(dev_priv, val, pipe)) I915_WRITE(reg, val & ~ADPA_DAC_ENABLE); reg = PCH_LVDS; val = I915_READ(reg); - if (lvds_pipe_enabled(dev_priv, pipe, val)) { + if (lvds_pipe_enabled(dev_priv, val, pipe)) { DRM_DEBUG_KMS("disable lvds on pipe %d val 0x%08x\n", pipe, val); I915_WRITE(reg, val & ~LVDS_PORT_EN); POSTING_READ(reg); @@ -3756,6 +3753,17 @@ static bool intel_choose_pipe_bpp_dither(struct drm_crtc *crtc, continue; } + if (intel_encoder->type == INTEL_OUTPUT_EDP) { + /* Use VBT settings if we have an eDP panel */ + unsigned int edp_bpc = dev_priv->edp.bpp / 3; + + if (edp_bpc < display_bpc) { + DRM_DEBUG_KMS("clamping display bpc (was %d) to eDP (%d)\n", display_bpc, edp_bpc); + display_bpc = edp_bpc; + } + continue; + } + /* Not one of the known troublemakers, check the EDID */ list_for_each_entry(connector, &dev->mode_config.connector_list, head) { @@ -4191,6 +4199,12 @@ static void i8xx_update_pll(struct drm_crtc *crtc, POSTING_READ(DPLL(pipe)); udelay(150); + I915_WRITE(DPLL(pipe), dpll); + + /* Wait for the clocks to stabilize. */ + POSTING_READ(DPLL(pipe)); + udelay(150); + /* The LVDS pin pair needs to be on before the DPLLs are enabled. * This is an exception to the general rule that mode_set doesn't turn * things on. @@ -4198,12 +4212,6 @@ static void i8xx_update_pll(struct drm_crtc *crtc, if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) intel_update_lvds(crtc, clock, adjusted_mode); - I915_WRITE(DPLL(pipe), dpll); - - /* Wait for the clocks to stabilize. */ - POSTING_READ(DPLL(pipe)); - udelay(150); - /* The pixel multiplier can only be updated once the * DPLL is enabled and the clocks are stable. * diff --git a/trunk/drivers/gpu/drm/i915/intel_dp.c b/trunk/drivers/gpu/drm/i915/intel_dp.c index ace757af9133..0a56b9ab0f58 100644 --- a/trunk/drivers/gpu/drm/i915/intel_dp.c +++ b/trunk/drivers/gpu/drm/i915/intel_dp.c @@ -1174,14 +1174,10 @@ static void ironlake_edp_panel_off(struct intel_dp *intel_dp) WARN(!intel_dp->want_panel_vdd, "Need VDD to turn off panel\n"); pp = ironlake_get_pp_control(dev_priv); - /* We need to switch off panel power _and_ force vdd, for otherwise some - * panels get very unhappy and cease to work. */ - pp &= ~(POWER_TARGET_ON | EDP_FORCE_VDD | PANEL_POWER_RESET | EDP_BLC_ENABLE); + pp &= ~(POWER_TARGET_ON | PANEL_POWER_RESET | EDP_BLC_ENABLE); I915_WRITE(PCH_PP_CONTROL, pp); POSTING_READ(PCH_PP_CONTROL); - intel_dp->want_panel_vdd = false; - ironlake_wait_panel_off(intel_dp); } @@ -1291,9 +1287,11 @@ static void intel_dp_prepare(struct drm_encoder *encoder) * ensure that we have vdd while we switch off the panel. */ ironlake_edp_panel_vdd_on(intel_dp); ironlake_edp_backlight_off(intel_dp); - intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON); ironlake_edp_panel_off(intel_dp); + + intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON); intel_dp_link_down(intel_dp); + ironlake_edp_panel_vdd_off(intel_dp, false); } static void intel_dp_commit(struct drm_encoder *encoder) @@ -1328,9 +1326,11 @@ intel_dp_dpms(struct drm_encoder *encoder, int mode) /* Switching the panel off requires vdd. */ ironlake_edp_panel_vdd_on(intel_dp); ironlake_edp_backlight_off(intel_dp); - intel_dp_sink_dpms(intel_dp, mode); ironlake_edp_panel_off(intel_dp); + + intel_dp_sink_dpms(intel_dp, mode); intel_dp_link_down(intel_dp); + ironlake_edp_panel_vdd_off(intel_dp, false); if (is_cpu_edp(intel_dp)) ironlake_edp_pll_off(encoder); @@ -2533,10 +2533,14 @@ intel_dp_init(struct drm_device *dev, int output_reg) break; } + intel_dp_i2c_init(intel_dp, intel_connector, name); + /* Cache some DPCD data in the eDP case */ if (is_edp(intel_dp)) { + bool ret; struct edp_power_seq cur, vbt; u32 pp_on, pp_off, pp_div; + struct edid *edid; pp_on = I915_READ(PCH_PP_ON_DELAYS); pp_off = I915_READ(PCH_PP_OFF_DELAYS); @@ -2587,13 +2591,6 @@ intel_dp_init(struct drm_device *dev, int output_reg) DRM_DEBUG_KMS("backlight on delay %d, off delay %d\n", intel_dp->backlight_on_delay, intel_dp->backlight_off_delay); - } - - intel_dp_i2c_init(intel_dp, intel_connector, name); - - if (is_edp(intel_dp)) { - bool ret; - struct edid *edid; ironlake_edp_panel_vdd_on(intel_dp); ret = intel_dp_get_dpcd(intel_dp); diff --git a/trunk/drivers/gpu/drm/i915/intel_drv.h b/trunk/drivers/gpu/drm/i915/intel_drv.h index cd54cf88a28f..84353559441c 100644 --- a/trunk/drivers/gpu/drm/i915/intel_drv.h +++ b/trunk/drivers/gpu/drm/i915/intel_drv.h @@ -46,16 +46,15 @@ }) #define wait_for_atomic_us(COND, US) ({ \ - unsigned long timeout__ = jiffies + usecs_to_jiffies(US); \ - int ret__ = 0; \ - while (!(COND)) { \ - if (time_after(jiffies, timeout__)) { \ - ret__ = -ETIMEDOUT; \ - break; \ - } \ - cpu_relax(); \ - } \ - ret__; \ + int i, ret__ = -ETIMEDOUT; \ + for (i = 0; i < (US); i++) { \ + if ((COND)) { \ + ret__ = 0; \ + break; \ + } \ + udelay(1); \ + } \ + ret__; \ }) #define wait_for(COND, MS) _wait_for(COND, MS, 1) @@ -342,8 +341,6 @@ struct intel_fbc_work { int interval; }; -int intel_connector_update_modes(struct drm_connector *connector, - struct edid *edid); int intel_ddc_get_modes(struct drm_connector *c, struct i2c_adapter *adapter); extern void intel_attach_force_audio_property(struct drm_connector *connector); @@ -383,6 +380,7 @@ extern void intel_pch_panel_fitting(struct drm_device *dev, const struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode); extern u32 intel_panel_get_max_backlight(struct drm_device *dev); +extern u32 intel_panel_get_backlight(struct drm_device *dev); extern void intel_panel_set_backlight(struct drm_device *dev, u32 level); extern int intel_panel_setup_backlight(struct drm_device *dev); extern void intel_panel_enable_backlight(struct drm_device *dev, diff --git a/trunk/drivers/gpu/drm/i915/intel_hdmi.c b/trunk/drivers/gpu/drm/i915/intel_hdmi.c index 12dc3308ab8c..98f602427eb8 100644 --- a/trunk/drivers/gpu/drm/i915/intel_hdmi.c +++ b/trunk/drivers/gpu/drm/i915/intel_hdmi.c @@ -609,7 +609,7 @@ static void intel_hdmi_dpms(struct drm_encoder *encoder, int mode) u32 temp; u32 enable_bits = SDVO_ENABLE; - if (intel_hdmi->has_audio || mode != DRM_MODE_DPMS_ON) + if (intel_hdmi->has_audio) enable_bits |= SDVO_AUDIO_ENABLE; temp = I915_READ(intel_hdmi->sdvox_reg); diff --git a/trunk/drivers/gpu/drm/i915/intel_i2c.c b/trunk/drivers/gpu/drm/i915/intel_i2c.c index b9755f6378d8..1991a4408cf9 100644 --- a/trunk/drivers/gpu/drm/i915/intel_i2c.c +++ b/trunk/drivers/gpu/drm/i915/intel_i2c.c @@ -486,6 +486,9 @@ int intel_setup_gmbus(struct drm_device *dev) bus->dev_priv = dev_priv; bus->adapter.algo = &gmbus_algorithm; + ret = i2c_add_adapter(&bus->adapter); + if (ret) + goto err; /* By default use a conservative clock rate */ bus->reg0 = port | GMBUS_RATE_100KHZ; @@ -495,10 +498,6 @@ int intel_setup_gmbus(struct drm_device *dev) bus->force_bit = true; intel_gpio_setup(bus, port); - - ret = i2c_add_adapter(&bus->adapter); - if (ret) - goto err; } intel_i2c_reset(dev_priv->dev); @@ -541,6 +540,9 @@ void intel_teardown_gmbus(struct drm_device *dev) struct drm_i915_private *dev_priv = dev->dev_private; int i; + if (dev_priv->gmbus == NULL) + return; + for (i = 0; i < GMBUS_NUM_PORTS; i++) { struct intel_gmbus *bus = &dev_priv->gmbus[i]; i2c_del_adapter(&bus->adapter); diff --git a/trunk/drivers/gpu/drm/i915/intel_lvds.c b/trunk/drivers/gpu/drm/i915/intel_lvds.c index e9a6f6aaed85..e05c0d3e3440 100644 --- a/trunk/drivers/gpu/drm/i915/intel_lvds.c +++ b/trunk/drivers/gpu/drm/i915/intel_lvds.c @@ -780,14 +780,6 @@ static const struct dmi_system_id intel_no_lvds[] = { DMI_MATCH(DMI_BOARD_NAME, "ZBOXSD-ID12/ID13"), }, }, - { - .callback = intel_no_lvds_dmi_callback, - .ident = "Gigabyte GA-D525TUD", - .matches = { - DMI_MATCH(DMI_BOARD_VENDOR, "Gigabyte Technology Co., Ltd."), - DMI_MATCH(DMI_BOARD_NAME, "D525TUD"), - }, - }, { } /* terminating entry */ }; diff --git a/trunk/drivers/gpu/drm/i915/intel_modes.c b/trunk/drivers/gpu/drm/i915/intel_modes.c index 29b72593fbb2..45848b9b670b 100644 --- a/trunk/drivers/gpu/drm/i915/intel_modes.c +++ b/trunk/drivers/gpu/drm/i915/intel_modes.c @@ -32,25 +32,6 @@ #include "intel_drv.h" #include "i915_drv.h" -/** - * intel_connector_update_modes - update connector from edid - * @connector: DRM connector device to use - * @edid: previously read EDID information - */ -int intel_connector_update_modes(struct drm_connector *connector, - struct edid *edid) -{ - int ret; - - drm_mode_connector_update_edid_property(connector, edid); - ret = drm_add_edid_modes(connector, edid); - drm_edid_to_eld(connector, edid); - connector->display_info.raw_edid = NULL; - kfree(edid); - - return ret; -} - /** * intel_ddc_get_modes - get modelist from monitor * @connector: DRM connector device to use @@ -62,12 +43,18 @@ int intel_ddc_get_modes(struct drm_connector *connector, struct i2c_adapter *adapter) { struct edid *edid; + int ret = 0; edid = drm_get_edid(connector, adapter); - if (!edid) - return 0; + if (edid) { + drm_mode_connector_update_edid_property(connector, edid); + ret = drm_add_edid_modes(connector, edid); + drm_edid_to_eld(connector, edid); + connector->display_info.raw_edid = NULL; + kfree(edid); + } - return intel_connector_update_modes(connector, edid); + return ret; } static const struct drm_prop_enum_list force_audio_names[] = { diff --git a/trunk/drivers/gpu/drm/i915/intel_panel.c b/trunk/drivers/gpu/drm/i915/intel_panel.c index e019b2369861..10c7d39034e1 100644 --- a/trunk/drivers/gpu/drm/i915/intel_panel.c +++ b/trunk/drivers/gpu/drm/i915/intel_panel.c @@ -162,12 +162,19 @@ static u32 i915_read_blc_pwm_ctl(struct drm_i915_private *dev_priv) return val; } -static u32 _intel_panel_get_max_backlight(struct drm_device *dev) +u32 intel_panel_get_max_backlight(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; u32 max; max = i915_read_blc_pwm_ctl(dev_priv); + if (max == 0) { + /* XXX add code here to query mode clock or hardware clock + * and program max PWM appropriately. + */ + pr_warn_once("fixme: max PWM is zero\n"); + return 1; + } if (HAS_PCH_SPLIT(dev)) { max >>= 16; @@ -181,22 +188,6 @@ static u32 _intel_panel_get_max_backlight(struct drm_device *dev) max *= 0xff; } - return max; -} - -u32 intel_panel_get_max_backlight(struct drm_device *dev) -{ - u32 max; - - max = _intel_panel_get_max_backlight(dev); - if (max == 0) { - /* XXX add code here to query mode clock or hardware clock - * and program max PWM appropriately. - */ - pr_warn_once("fixme: max PWM is zero\n"); - return 1; - } - DRM_DEBUG_DRIVER("max backlight PWM = %d\n", max); return max; } @@ -222,7 +213,7 @@ static u32 intel_panel_compute_brightness(struct drm_device *dev, u32 val) return val; } -static u32 intel_panel_get_backlight(struct drm_device *dev) +u32 intel_panel_get_backlight(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; u32 val; @@ -320,6 +311,9 @@ void intel_panel_enable_backlight(struct drm_device *dev, if (dev_priv->backlight_level == 0) dev_priv->backlight_level = intel_panel_get_max_backlight(dev); + dev_priv->backlight_enabled = true; + intel_panel_actually_set_backlight(dev, dev_priv->backlight_level); + if (INTEL_INFO(dev)->gen >= 4) { uint32_t reg, tmp; @@ -332,7 +326,7 @@ void intel_panel_enable_backlight(struct drm_device *dev, * we don't track the backlight dpms state, hence check whether * we have to do anything first. */ if (tmp & BLM_PWM_ENABLE) - goto set_level; + return; if (dev_priv->num_pipe == 3) tmp &= ~BLM_PIPE_SELECT_IVB; @@ -353,14 +347,6 @@ void intel_panel_enable_backlight(struct drm_device *dev, I915_WRITE(BLC_PWM_PCH_CTL1, tmp); } } - -set_level: - /* Call below after setting BLC_PWM_CPU_CTL2 and BLC_PWM_PCH_CTL1. - * BLC_PWM_CPU_CTL may be cleared to zero automatically when these - * registers are set. - */ - dev_priv->backlight_enabled = true; - intel_panel_actually_set_backlight(dev, dev_priv->backlight_level); } static void intel_panel_init_backlight(struct drm_device *dev) @@ -433,11 +419,7 @@ int intel_panel_setup_backlight(struct drm_device *dev) memset(&props, 0, sizeof(props)); props.type = BACKLIGHT_RAW; - props.max_brightness = _intel_panel_get_max_backlight(dev); - if (props.max_brightness == 0) { - DRM_ERROR("Failed to get maximum backlight value\n"); - return -ENODEV; - } + props.max_brightness = intel_panel_get_max_backlight(dev); dev_priv->backlight = backlight_device_register("intel_backlight", &connector->kdev, dev, diff --git a/trunk/drivers/gpu/drm/i915/intel_pm.c b/trunk/drivers/gpu/drm/i915/intel_pm.c index ba8a27b1757a..94aabcaa3a67 100644 --- a/trunk/drivers/gpu/drm/i915/intel_pm.c +++ b/trunk/drivers/gpu/drm/i915/intel_pm.c @@ -2441,10 +2441,17 @@ static void gen6_enable_rps(struct drm_device *dev) dev_priv->max_delay << 24 | dev_priv->min_delay << 16); - I915_WRITE(GEN6_RP_UP_THRESHOLD, 59400); - I915_WRITE(GEN6_RP_DOWN_THRESHOLD, 245000); - I915_WRITE(GEN6_RP_UP_EI, 66000); - I915_WRITE(GEN6_RP_DOWN_EI, 350000); + if (IS_HASWELL(dev)) { + I915_WRITE(GEN6_RP_UP_THRESHOLD, 59400); + I915_WRITE(GEN6_RP_DOWN_THRESHOLD, 245000); + I915_WRITE(GEN6_RP_UP_EI, 66000); + I915_WRITE(GEN6_RP_DOWN_EI, 350000); + } else { + I915_WRITE(GEN6_RP_UP_THRESHOLD, 10000); + I915_WRITE(GEN6_RP_DOWN_THRESHOLD, 1000000); + I915_WRITE(GEN6_RP_UP_EI, 100000); + I915_WRITE(GEN6_RP_DOWN_EI, 5000000); + } I915_WRITE(GEN6_RP_IDLE_HYSTERSIS, 10); I915_WRITE(GEN6_RP_CONTROL, @@ -3672,9 +3679,6 @@ static void gen3_init_clock_gating(struct drm_device *dev) if (IS_PINEVIEW(dev)) I915_WRITE(ECOSKPD, _MASKED_BIT_ENABLE(ECO_GATING_CX_ONLY)); - - /* IIR "flip pending" means done if this bit is set */ - I915_WRITE(ECOSKPD, _MASKED_BIT_DISABLE(ECO_FLIP_DONE)); } static void i85x_init_clock_gating(struct drm_device *dev) @@ -3959,7 +3963,6 @@ static void __gen6_gt_force_wake_get(struct drm_i915_private *dev_priv) DRM_ERROR("Force wake wait timed out\n"); I915_WRITE_NOTRACE(FORCEWAKE, 1); - POSTING_READ(FORCEWAKE); if (wait_for_atomic_us((I915_READ_NOTRACE(forcewake_ack) & 1), 500)) DRM_ERROR("Force wake wait timed out\n"); @@ -3980,7 +3983,6 @@ static void __gen6_gt_force_wake_mt_get(struct drm_i915_private *dev_priv) DRM_ERROR("Force wake wait timed out\n"); I915_WRITE_NOTRACE(FORCEWAKE_MT, _MASKED_BIT_ENABLE(1)); - POSTING_READ(FORCEWAKE_MT); if (wait_for_atomic_us((I915_READ_NOTRACE(forcewake_ack) & 1), 500)) DRM_ERROR("Force wake wait timed out\n"); @@ -4016,14 +4018,14 @@ void gen6_gt_check_fifodbg(struct drm_i915_private *dev_priv) static void __gen6_gt_force_wake_put(struct drm_i915_private *dev_priv) { I915_WRITE_NOTRACE(FORCEWAKE, 0); - POSTING_READ(FORCEWAKE); + /* The below doubles as a POSTING_READ */ gen6_gt_check_fifodbg(dev_priv); } static void __gen6_gt_force_wake_mt_put(struct drm_i915_private *dev_priv) { I915_WRITE_NOTRACE(FORCEWAKE_MT, _MASKED_BIT_DISABLE(1)); - POSTING_READ(FORCEWAKE_MT); + /* The below doubles as a POSTING_READ */ gen6_gt_check_fifodbg(dev_priv); } diff --git a/trunk/drivers/gpu/drm/i915/intel_ringbuffer.c b/trunk/drivers/gpu/drm/i915/intel_ringbuffer.c index e2a73b38abe9..bf0195a96d53 100644 --- a/trunk/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/trunk/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -227,36 +227,31 @@ gen6_render_ring_flush(struct intel_ring_buffer *ring, * number of bits based on the write domains has little performance * impact. */ - if (flush_domains) { - flags |= PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH; - flags |= PIPE_CONTROL_DEPTH_CACHE_FLUSH; - /* - * Ensure that any following seqno writes only happen - * when the render cache is indeed flushed. - */ + flags |= PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH; + flags |= PIPE_CONTROL_TLB_INVALIDATE; + flags |= PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE; + flags |= PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE; + flags |= PIPE_CONTROL_DEPTH_CACHE_FLUSH; + flags |= PIPE_CONTROL_VF_CACHE_INVALIDATE; + flags |= PIPE_CONTROL_CONST_CACHE_INVALIDATE; + flags |= PIPE_CONTROL_STATE_CACHE_INVALIDATE; + /* + * Ensure that any following seqno writes only happen when the render + * cache is indeed flushed (but only if the caller actually wants that). + */ + if (flush_domains) flags |= PIPE_CONTROL_CS_STALL; - } - if (invalidate_domains) { - flags |= PIPE_CONTROL_TLB_INVALIDATE; - flags |= PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE; - flags |= PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE; - flags |= PIPE_CONTROL_VF_CACHE_INVALIDATE; - flags |= PIPE_CONTROL_CONST_CACHE_INVALIDATE; - flags |= PIPE_CONTROL_STATE_CACHE_INVALIDATE; - /* - * TLB invalidate requires a post-sync write. - */ - flags |= PIPE_CONTROL_QW_WRITE; - } - ret = intel_ring_begin(ring, 4); + ret = intel_ring_begin(ring, 6); if (ret) return ret; - intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(4)); + intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(5)); intel_ring_emit(ring, flags); intel_ring_emit(ring, scratch_addr | PIPE_CONTROL_GLOBAL_GTT); - intel_ring_emit(ring, 0); + intel_ring_emit(ring, 0); /* lower dword */ + intel_ring_emit(ring, 0); /* uppwer dword */ + intel_ring_emit(ring, MI_NOOP); intel_ring_advance(ring); return 0; @@ -294,6 +289,8 @@ static int init_ring_common(struct intel_ring_buffer *ring) I915_WRITE_HEAD(ring, 0); ring->write_tail(ring, 0); + /* Initialize the ring. */ + I915_WRITE_START(ring, obj->gtt_offset); head = I915_READ_HEAD(ring) & HEAD_ADDR; /* G45 ring initialization fails to reset head to zero */ @@ -319,11 +316,6 @@ static int init_ring_common(struct intel_ring_buffer *ring) } } - /* Initialize the ring. This must happen _after_ we've cleared the ring - * registers with the above sequence (the readback of the HEAD registers - * also enforces ordering), otherwise the hw might lose the new ring - * register values. */ - I915_WRITE_START(ring, obj->gtt_offset); I915_WRITE_CTL(ring, ((ring->size - PAGE_SIZE) & RING_NR_PAGES) | RING_VALID); diff --git a/trunk/drivers/gpu/drm/i915/intel_sdvo.c b/trunk/drivers/gpu/drm/i915/intel_sdvo.c index 123afd357611..26a6a4d0d078 100644 --- a/trunk/drivers/gpu/drm/i915/intel_sdvo.c +++ b/trunk/drivers/gpu/drm/i915/intel_sdvo.c @@ -444,16 +444,13 @@ static bool intel_sdvo_write_cmd(struct intel_sdvo *intel_sdvo, u8 cmd, struct i2c_msg *msgs; int i, ret = true; - /* Would be simpler to allocate both in one go ? */ buf = (u8 *)kzalloc(args_len * 2 + 2, GFP_KERNEL); if (!buf) return false; msgs = kcalloc(args_len + 3, sizeof(*msgs), GFP_KERNEL); - if (!msgs) { - kfree(buf); + if (!msgs) return false; - } intel_sdvo_debug_write(intel_sdvo, cmd, args, args_len); @@ -1692,7 +1689,6 @@ static bool intel_sdvo_detect_hdmi_audio(struct drm_connector *connector) edid = intel_sdvo_get_edid(connector); if (edid != NULL && edid->input & DRM_EDID_INPUT_DIGITAL) has_audio = drm_detect_monitor_audio(edid); - kfree(edid); return has_audio; } @@ -2573,6 +2569,7 @@ bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob) hotplug_mask = intel_sdvo->is_sdvob ? SDVOB_HOTPLUG_INT_STATUS_I915 : SDVOC_HOTPLUG_INT_STATUS_I915; } + dev_priv->hotplug_supported_mask |= hotplug_mask; drm_encoder_helper_add(&intel_encoder->base, &intel_sdvo_helper_funcs); @@ -2580,6 +2577,14 @@ bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob) if (!intel_sdvo_get_capabilities(intel_sdvo, &intel_sdvo->caps)) goto err; + /* Set up hotplug command - note paranoia about contents of reply. + * We assume that the hardware is in a sane state, and only touch + * the bits we think we understand. + */ + intel_sdvo_get_value(intel_sdvo, SDVO_CMD_GET_ACTIVE_HOT_PLUG, + &intel_sdvo->hotplug_active, 2); + intel_sdvo->hotplug_active[0] &= ~0x3; + if (intel_sdvo_output_setup(intel_sdvo, intel_sdvo->caps.output_flags) != true) { DRM_DEBUG_KMS("SDVO output failed to setup on %s\n", @@ -2587,12 +2592,6 @@ bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob) goto err; } - /* Only enable the hotplug irq if we need it, to work around noisy - * hotplug lines. - */ - if (intel_sdvo->hotplug_active[0]) - dev_priv->hotplug_supported_mask |= hotplug_mask; - intel_sdvo_select_ddc_bus(dev_priv, intel_sdvo, sdvo_reg); /* Set the input timing to the screen. Assume always input 0. */ diff --git a/trunk/drivers/gpu/drm/i915/intel_sprite.c b/trunk/drivers/gpu/drm/i915/intel_sprite.c index 7644f31a3778..cc8df4de2d92 100644 --- a/trunk/drivers/gpu/drm/i915/intel_sprite.c +++ b/trunk/drivers/gpu/drm/i915/intel_sprite.c @@ -60,11 +60,11 @@ ivb_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb, switch (fb->pixel_format) { case DRM_FORMAT_XBGR8888: - sprctl |= SPRITE_FORMAT_RGBX888 | SPRITE_RGB_ORDER_RGBX; + sprctl |= SPRITE_FORMAT_RGBX888; pixel_size = 4; break; case DRM_FORMAT_XRGB8888: - sprctl |= SPRITE_FORMAT_RGBX888; + sprctl |= SPRITE_FORMAT_RGBX888 | SPRITE_RGB_ORDER_RGBX; pixel_size = 4; break; case DRM_FORMAT_YUYV: diff --git a/trunk/drivers/gpu/drm/mgag200/mgag200_drv.c b/trunk/drivers/gpu/drm/mgag200/mgag200_drv.c index e5f145d2cb3b..ea1024d79974 100644 --- a/trunk/drivers/gpu/drm/mgag200/mgag200_drv.c +++ b/trunk/drivers/gpu/drm/mgag200/mgag200_drv.c @@ -84,9 +84,6 @@ static const struct file_operations mgag200_driver_fops = { .mmap = mgag200_mmap, .poll = drm_poll, .fasync = drm_fasync, -#ifdef CONFIG_COMPAT - .compat_ioctl = drm_compat_ioctl, -#endif .read = drm_read, }; diff --git a/trunk/drivers/gpu/drm/mgag200/mgag200_mode.c b/trunk/drivers/gpu/drm/mgag200/mgag200_mode.c index b69642d5d850..a4d7c500c97b 100644 --- a/trunk/drivers/gpu/drm/mgag200/mgag200_mode.c +++ b/trunk/drivers/gpu/drm/mgag200/mgag200_mode.c @@ -468,11 +468,10 @@ static int mga_g200er_set_plls(struct mga_device *mdev, long clock) { unsigned int vcomax, vcomin, pllreffreq; unsigned int delta, tmpdelta; - int testr, testn, testm, testo; + unsigned int testr, testn, testm, testo; unsigned int p, m, n; - unsigned int computed, vco; + unsigned int computed; int tmp; - const unsigned int m_div_val[] = { 1, 2, 4, 8 }; m = n = p = 0; vcomax = 1488000; @@ -491,13 +490,12 @@ static int mga_g200er_set_plls(struct mga_device *mdev, long clock) if (delta == 0) break; for (testo = 5; testo < 33; testo++) { - vco = pllreffreq * (testn + 1) / + computed = pllreffreq * (testn + 1) / (testr + 1); - if (vco < vcomin) + if (computed < vcomin) continue; - if (vco > vcomax) + if (computed > vcomax) continue; - computed = vco / (m_div_val[testm] * (testo + 1)); if (computed > clock) tmpdelta = computed - clock; else diff --git a/trunk/drivers/gpu/drm/nouveau/nouveau_abi16.c b/trunk/drivers/gpu/drm/nouveau/nouveau_abi16.c index 3ca240b4413d..ff23d88880e5 100644 --- a/trunk/drivers/gpu/drm/nouveau/nouveau_abi16.c +++ b/trunk/drivers/gpu/drm/nouveau/nouveau_abi16.c @@ -179,7 +179,7 @@ nouveau_abi16_ioctl_grobj_alloc(ABI16_IOCTL_ARGS) return 0; } else if (init->class == 0x906e) { - NV_DEBUG(dev, "906e not supported yet\n"); + NV_ERROR(dev, "906e not supported yet\n"); return -EINVAL; } diff --git a/trunk/drivers/gpu/drm/nouveau/nouveau_acpi.c b/trunk/drivers/gpu/drm/nouveau/nouveau_acpi.c index 26ebffebe710..fc841e87b343 100644 --- a/trunk/drivers/gpu/drm/nouveau/nouveau_acpi.c +++ b/trunk/drivers/gpu/drm/nouveau/nouveau_acpi.c @@ -211,6 +211,11 @@ static int nouveau_dsm_power_state(enum vga_switcheroo_client_id id, return nouveau_dsm_set_discrete_state(nouveau_dsm_priv.dhandle, state); } +static int nouveau_dsm_init(void) +{ + return 0; +} + static int nouveau_dsm_get_client_id(struct pci_dev *pdev) { /* easy option one - intel vendor ID means Integrated */ @@ -227,6 +232,7 @@ static int nouveau_dsm_get_client_id(struct pci_dev *pdev) static struct vga_switcheroo_handler nouveau_dsm_handler = { .switchto = nouveau_dsm_switchto, .power_state = nouveau_dsm_power_state, + .init = nouveau_dsm_init, .get_client_id = nouveau_dsm_get_client_id, }; diff --git a/trunk/drivers/gpu/drm/nouveau/nouveau_display.c b/trunk/drivers/gpu/drm/nouveau/nouveau_display.c index 7e16dc5e6467..69688ef5cf46 100644 --- a/trunk/drivers/gpu/drm/nouveau/nouveau_display.c +++ b/trunk/drivers/gpu/drm/nouveau/nouveau_display.c @@ -598,7 +598,7 @@ nouveau_display_dumb_create(struct drm_file *file_priv, struct drm_device *dev, args->size = args->pitch * args->height; args->size = roundup(args->size, PAGE_SIZE); - ret = nouveau_gem_new(dev, args->size, 0, NOUVEAU_GEM_DOMAIN_VRAM, 0, 0, &bo); + ret = nouveau_gem_new(dev, args->size, 0, TTM_PL_FLAG_VRAM, 0, 0, &bo); if (ret) return ret; diff --git a/trunk/drivers/gpu/drm/nouveau/nouveau_i2c.c b/trunk/drivers/gpu/drm/nouveau/nouveau_i2c.c index 240cf962c999..77e564667b5c 100644 --- a/trunk/drivers/gpu/drm/nouveau/nouveau_i2c.c +++ b/trunk/drivers/gpu/drm/nouveau/nouveau_i2c.c @@ -229,7 +229,7 @@ nouveau_i2c_init(struct drm_device *dev) } break; case 6: /* NV50- DP AUX */ - port->drive = entry[0] & 0x0f; + port->drive = entry[0]; port->sense = port->drive; port->adapter.algo = &nouveau_dp_i2c_algo; break; diff --git a/trunk/drivers/gpu/drm/nouveau/nouveau_state.c b/trunk/drivers/gpu/drm/nouveau/nouveau_state.c index c61014442aa9..1cdfd6e757ce 100644 --- a/trunk/drivers/gpu/drm/nouveau/nouveau_state.c +++ b/trunk/drivers/gpu/drm/nouveau/nouveau_state.c @@ -731,16 +731,15 @@ nouveau_card_init(struct drm_device *dev) case 0xa3: case 0xa5: case 0xa8: + case 0xaf: nva3_copy_create(dev); break; } break; case NV_C0: - if (!(nv_rd32(dev, 0x022500) & 0x00000200)) - nvc0_copy_create(dev, 1); + nvc0_copy_create(dev, 1); case NV_D0: - if (!(nv_rd32(dev, 0x022500) & 0x00000100)) - nvc0_copy_create(dev, 0); + nvc0_copy_create(dev, 0); break; default: break; diff --git a/trunk/drivers/gpu/drm/nouveau/nv50_gpio.c b/trunk/drivers/gpu/drm/nouveau/nv50_gpio.c index c399d510b27a..f429e6a8ca7a 100644 --- a/trunk/drivers/gpu/drm/nouveau/nv50_gpio.c +++ b/trunk/drivers/gpu/drm/nouveau/nv50_gpio.c @@ -22,7 +22,6 @@ * Authors: Ben Skeggs */ -#include #include "drmP.h" #include "nouveau_drv.h" #include "nouveau_hw.h" @@ -111,26 +110,11 @@ nv50_gpio_isr(struct drm_device *dev) nv_wr32(dev, 0xe074, intr1); } -static struct dmi_system_id gpio_reset_ids[] = { - { - .ident = "Apple Macbook 10,1", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro10,1"), - } - }, - { } -}; - int nv50_gpio_init(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; - /* initialise gpios and routing to vbios defaults */ - if (dmi_check_system(gpio_reset_ids)) - nouveau_gpio_reset(dev); - /* disable, and ack any pending gpio interrupts */ nv_wr32(dev, 0xe050, 0x00000000); nv_wr32(dev, 0xe054, 0xffffffff); diff --git a/trunk/drivers/gpu/drm/nouveau/nv84_fifo.c b/trunk/drivers/gpu/drm/nouveau/nv84_fifo.c index c564c5e4c30a..cc82d799fc3b 100644 --- a/trunk/drivers/gpu/drm/nouveau/nv84_fifo.c +++ b/trunk/drivers/gpu/drm/nouveau/nv84_fifo.c @@ -117,22 +117,17 @@ nv84_fifo_context_del(struct nouveau_channel *chan, int engine) struct drm_device *dev = chan->dev; struct drm_nouveau_private *dev_priv = dev->dev_private; unsigned long flags; - u32 save; /* remove channel from playlist, will context switch if active */ spin_lock_irqsave(&dev_priv->context_switch_lock, flags); nv_mask(dev, 0x002600 + (chan->id * 4), 0x80000000, 0x00000000); nv50_fifo_playlist_update(dev); - save = nv_mask(dev, 0x002520, 0x0000003f, 0x15); - /* tell any engines on this channel to unload their contexts */ nv_wr32(dev, 0x0032fc, chan->ramin->vinst >> 12); if (!nv_wait_ne(dev, 0x0032fc, 0xffffffff, 0xffffffff)) NV_INFO(dev, "PFIFO: channel %d unload timeout\n", chan->id); - nv_wr32(dev, 0x002520, save); - nv_wr32(dev, 0x002600 + (chan->id * 4), 0x00000000); spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); @@ -189,13 +184,10 @@ nv84_fifo_fini(struct drm_device *dev, int engine, bool suspend) struct drm_nouveau_private *dev_priv = dev->dev_private; struct nv84_fifo_priv *priv = nv_engine(dev, engine); int i; - u32 save; /* set playlist length to zero, fifo will unload context */ nv_wr32(dev, 0x0032ec, 0); - save = nv_mask(dev, 0x002520, 0x0000003f, 0x15); - /* tell all connected engines to unload their contexts */ for (i = 0; i < priv->base.channels; i++) { struct nouveau_channel *chan = dev_priv->channels.ptr[i]; @@ -207,7 +199,6 @@ nv84_fifo_fini(struct drm_device *dev, int engine, bool suspend) } } - nv_wr32(dev, 0x002520, save); nv_wr32(dev, 0x002140, 0); return 0; } diff --git a/trunk/drivers/gpu/drm/nouveau/nvc0_fb.c b/trunk/drivers/gpu/drm/nouveau/nvc0_fb.c index f376c39310df..f704e942372e 100644 --- a/trunk/drivers/gpu/drm/nouveau/nvc0_fb.c +++ b/trunk/drivers/gpu/drm/nouveau/nvc0_fb.c @@ -124,7 +124,6 @@ nvc0_fb_init(struct drm_device *dev) priv = dev_priv->engine.fb.priv; nv_wr32(dev, 0x100c10, priv->r100c10 >> 8); - nv_mask(dev, 0x17e820, 0x00100000, 0x00000000); /* NV_PLTCG_INTR_EN */ return 0; } diff --git a/trunk/drivers/gpu/drm/nouveau/nvc0_fifo.c b/trunk/drivers/gpu/drm/nouveau/nvc0_fifo.c index cd39eb99f5b1..7d85553d518c 100644 --- a/trunk/drivers/gpu/drm/nouveau/nvc0_fifo.c +++ b/trunk/drivers/gpu/drm/nouveau/nvc0_fifo.c @@ -373,8 +373,7 @@ nvc0_fifo_isr_subfifo_intr(struct drm_device *dev, int unit) static void nvc0_fifo_isr(struct drm_device *dev) { - u32 mask = nv_rd32(dev, 0x002140); - u32 stat = nv_rd32(dev, 0x002100) & mask; + u32 stat = nv_rd32(dev, 0x002100); if (stat & 0x00000100) { NV_INFO(dev, "PFIFO: unknown status 0x00000100\n"); diff --git a/trunk/drivers/gpu/drm/nouveau/nvc0_pm.c b/trunk/drivers/gpu/drm/nouveau/nvc0_pm.c index 4e712b10ebdb..7c95c44e2887 100644 --- a/trunk/drivers/gpu/drm/nouveau/nvc0_pm.c +++ b/trunk/drivers/gpu/drm/nouveau/nvc0_pm.c @@ -557,7 +557,7 @@ prog_mem(struct drm_device *dev, struct nvc0_pm_state *info) nouveau_mem_exec(&exec, info->perflvl); if (dev_priv->chipset < 0xd0) - nv_wr32(dev, 0x611200, 0x00003330); + nv_wr32(dev, 0x611200, 0x00003300); else nv_wr32(dev, 0x62c000, 0x03030300); } diff --git a/trunk/drivers/gpu/drm/nouveau/nvd0_display.c b/trunk/drivers/gpu/drm/nouveau/nvd0_display.c index 8a2fc89b7763..d0d60e1e7f95 100644 --- a/trunk/drivers/gpu/drm/nouveau/nvd0_display.c +++ b/trunk/drivers/gpu/drm/nouveau/nvd0_display.c @@ -790,7 +790,7 @@ nvd0_crtc_cursor_move(struct drm_crtc *crtc, int x, int y) struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); int ch = EVO_CURS(nv_crtc->index); - evo_piow(crtc->dev, ch, 0x0084, (y << 16) | (x & 0xffff)); + evo_piow(crtc->dev, ch, 0x0084, (y << 16) | x); evo_piow(crtc->dev, ch, 0x0080, 0x00000000); return 0; } @@ -1510,10 +1510,10 @@ nvd0_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *umode, case OUTPUT_DP: if (nv_connector->base.display_info.bpc == 6) { nv_encoder->dp.datarate = mode->clock * 18 / 8; - syncs |= 0x00000002 << 6; + syncs |= 0x00000140; } else { nv_encoder->dp.datarate = mode->clock * 24 / 8; - syncs |= 0x00000005 << 6; + syncs |= 0x00000180; } if (nv_encoder->dcb->sorconf.link & 1) diff --git a/trunk/drivers/gpu/drm/nouveau/nve0_fifo.c b/trunk/drivers/gpu/drm/nouveau/nve0_fifo.c index 281bece751b6..1855ecbd843b 100644 --- a/trunk/drivers/gpu/drm/nouveau/nve0_fifo.c +++ b/trunk/drivers/gpu/drm/nouveau/nve0_fifo.c @@ -294,25 +294,6 @@ nve0_fifo_isr_vm_fault(struct drm_device *dev, int unit) printk(" on channel 0x%010llx\n", (u64)inst << 12); } -static int -nve0_fifo_page_flip(struct drm_device *dev, u32 chid) -{ - struct nve0_fifo_priv *priv = nv_engine(dev, NVOBJ_ENGINE_FIFO); - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_channel *chan = NULL; - unsigned long flags; - int ret = -EINVAL; - - spin_lock_irqsave(&dev_priv->channels.lock, flags); - if (likely(chid >= 0 && chid < priv->base.channels)) { - chan = dev_priv->channels.ptr[chid]; - if (likely(chan)) - ret = nouveau_finish_page_flip(chan, NULL); - } - spin_unlock_irqrestore(&dev_priv->channels.lock, flags); - return ret; -} - static void nve0_fifo_isr_subfifo_intr(struct drm_device *dev, int unit) { @@ -322,21 +303,11 @@ nve0_fifo_isr_subfifo_intr(struct drm_device *dev, int unit) u32 chid = nv_rd32(dev, 0x040120 + (unit * 0x2000)) & 0x7f; u32 subc = (addr & 0x00070000); u32 mthd = (addr & 0x00003ffc); - u32 show = stat; - - if (stat & 0x00200000) { - if (mthd == 0x0054) { - if (!nve0_fifo_page_flip(dev, chid)) - show &= ~0x00200000; - } - } - if (show) { - NV_INFO(dev, "PFIFO%d:", unit); - nouveau_bitfield_print(nve0_fifo_subfifo_intr, show); - NV_INFO(dev, "PFIFO%d: ch %d subc %d mthd 0x%04x data 0x%08x\n", - unit, chid, subc, mthd, data); - } + NV_INFO(dev, "PSUBFIFO %d:", unit); + nouveau_bitfield_print(nve0_fifo_subfifo_intr, stat); + NV_INFO(dev, "PSUBFIFO %d: ch %d subc %d mthd 0x%04x data 0x%08x\n", + unit, chid, subc, mthd, data); nv_wr32(dev, 0x0400c0 + (unit * 0x2000), 0x80600008); nv_wr32(dev, 0x040108 + (unit * 0x2000), stat); @@ -345,8 +316,7 @@ nve0_fifo_isr_subfifo_intr(struct drm_device *dev, int unit) static void nve0_fifo_isr(struct drm_device *dev) { - u32 mask = nv_rd32(dev, 0x002140); - u32 stat = nv_rd32(dev, 0x002100) & mask; + u32 stat = nv_rd32(dev, 0x002100); if (stat & 0x00000100) { NV_INFO(dev, "PFIFO: unknown status 0x00000100\n"); diff --git a/trunk/drivers/gpu/drm/radeon/atombios_crtc.c b/trunk/drivers/gpu/drm/radeon/atombios_crtc.c index 2817101fb167..9e6f76fec527 100644 --- a/trunk/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/trunk/drivers/gpu/drm/radeon/atombios_crtc.c @@ -258,7 +258,8 @@ void atombios_crtc_dpms(struct drm_crtc *crtc, int mode) radeon_crtc->enabled = true; /* adjust pm to dpms changes BEFORE enabling crtcs */ radeon_pm_compute_clocks(rdev); - if (ASIC_IS_DCE6(rdev) && !radeon_crtc->in_mode_set) + /* disable crtc pair power gating before programming */ + if (ASIC_IS_DCE6(rdev)) atombios_powergate_crtc(crtc, ATOM_DISABLE); atombios_enable_crtc(crtc, ATOM_ENABLE); if (ASIC_IS_DCE3(rdev) && !ASIC_IS_DCE6(rdev)) @@ -277,8 +278,25 @@ void atombios_crtc_dpms(struct drm_crtc *crtc, int mode) atombios_enable_crtc_memreq(crtc, ATOM_DISABLE); atombios_enable_crtc(crtc, ATOM_DISABLE); radeon_crtc->enabled = false; - if (ASIC_IS_DCE6(rdev) && !radeon_crtc->in_mode_set) - atombios_powergate_crtc(crtc, ATOM_ENABLE); + /* power gating is per-pair */ + if (ASIC_IS_DCE6(rdev)) { + struct drm_crtc *other_crtc; + struct radeon_crtc *other_radeon_crtc; + list_for_each_entry(other_crtc, &rdev->ddev->mode_config.crtc_list, head) { + other_radeon_crtc = to_radeon_crtc(other_crtc); + if (((radeon_crtc->crtc_id == 0) && (other_radeon_crtc->crtc_id == 1)) || + ((radeon_crtc->crtc_id == 1) && (other_radeon_crtc->crtc_id == 0)) || + ((radeon_crtc->crtc_id == 2) && (other_radeon_crtc->crtc_id == 3)) || + ((radeon_crtc->crtc_id == 3) && (other_radeon_crtc->crtc_id == 2)) || + ((radeon_crtc->crtc_id == 4) && (other_radeon_crtc->crtc_id == 5)) || + ((radeon_crtc->crtc_id == 5) && (other_radeon_crtc->crtc_id == 4))) { + /* if both crtcs in the pair are off, enable power gating */ + if (other_radeon_crtc->enabled == false) + atombios_powergate_crtc(crtc, ATOM_ENABLE); + break; + } + } + } /* adjust pm to dpms changes AFTER disabling crtcs */ radeon_pm_compute_clocks(rdev); break; @@ -426,28 +444,11 @@ union atom_enable_ss { static void atombios_crtc_program_ss(struct radeon_device *rdev, int enable, int pll_id, - int crtc_id, struct radeon_atom_ss *ss) { - unsigned i; int index = GetIndexIntoMasterTable(COMMAND, EnableSpreadSpectrumOnPPLL); union atom_enable_ss args; - if (!enable) { - for (i = 0; i < rdev->num_crtc; i++) { - if (rdev->mode_info.crtcs[i] && - rdev->mode_info.crtcs[i]->enabled && - i != crtc_id && - pll_id == rdev->mode_info.crtcs[i]->pll_id) { - /* one other crtc is using this pll don't turn - * off spread spectrum as it might turn off - * display on active crtc - */ - return; - } - } - } - memset(&args, 0, sizeof(args)); if (ASIC_IS_DCE5(rdev)) { @@ -1027,7 +1028,7 @@ static void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode radeon_compute_pll_legacy(pll, adjusted_clock, &pll_clock, &fb_div, &frac_fb_div, &ref_div, &post_div); - atombios_crtc_program_ss(rdev, ATOM_DISABLE, radeon_crtc->pll_id, radeon_crtc->crtc_id, &ss); + atombios_crtc_program_ss(rdev, ATOM_DISABLE, radeon_crtc->pll_id, &ss); atombios_crtc_program_pll(crtc, radeon_crtc->crtc_id, radeon_crtc->pll_id, encoder_mode, radeon_encoder->encoder_id, mode->clock, @@ -1050,7 +1051,7 @@ static void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode ss.step = step_size; } - atombios_crtc_program_ss(rdev, ATOM_ENABLE, radeon_crtc->pll_id, radeon_crtc->crtc_id, &ss); + atombios_crtc_program_ss(rdev, ATOM_ENABLE, radeon_crtc->pll_id, &ss); } } @@ -1530,12 +1531,12 @@ static int radeon_atom_pick_pll(struct drm_crtc *crtc) * crtc virtual pixel clock. */ if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(test_encoder))) { - if (rdev->clock.dp_extclk) - return ATOM_PPLL_INVALID; + if (ASIC_IS_DCE5(rdev)) + return ATOM_DCPLL; else if (ASIC_IS_DCE6(rdev)) return ATOM_PPLL0; - else if (ASIC_IS_DCE5(rdev)) - return ATOM_DCPLL; + else if (rdev->clock.dp_extclk) + return ATOM_PPLL_INVALID; } } } @@ -1571,11 +1572,11 @@ void radeon_atom_disp_eng_pll_init(struct radeon_device *rdev) ASIC_INTERNAL_SS_ON_DCPLL, rdev->clock.default_dispclk); if (ss_enabled) - atombios_crtc_program_ss(rdev, ATOM_DISABLE, ATOM_DCPLL, -1, &ss); + atombios_crtc_program_ss(rdev, ATOM_DISABLE, ATOM_DCPLL, &ss); /* XXX: DCE5, make sure voltage, dispclk is high enough */ atombios_crtc_set_disp_eng_pll(rdev, rdev->clock.default_dispclk); if (ss_enabled) - atombios_crtc_program_ss(rdev, ATOM_ENABLE, ATOM_DCPLL, -1, &ss); + atombios_crtc_program_ss(rdev, ATOM_ENABLE, ATOM_DCPLL, &ss); } } @@ -1634,28 +1635,18 @@ static bool atombios_crtc_mode_fixup(struct drm_crtc *crtc, static void atombios_crtc_prepare(struct drm_crtc *crtc) { struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); - struct drm_device *dev = crtc->dev; - struct radeon_device *rdev = dev->dev_private; - radeon_crtc->in_mode_set = true; /* pick pll */ radeon_crtc->pll_id = radeon_atom_pick_pll(crtc); - /* disable crtc pair power gating before programming */ - if (ASIC_IS_DCE6(rdev)) - atombios_powergate_crtc(crtc, ATOM_DISABLE); - atombios_lock_crtc(crtc, ATOM_ENABLE); atombios_crtc_dpms(crtc, DRM_MODE_DPMS_OFF); } static void atombios_crtc_commit(struct drm_crtc *crtc) { - struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); - atombios_crtc_dpms(crtc, DRM_MODE_DPMS_ON); atombios_lock_crtc(crtc, ATOM_DISABLE); - radeon_crtc->in_mode_set = false; } static void atombios_crtc_disable(struct drm_crtc *crtc) @@ -1664,22 +1655,9 @@ static void atombios_crtc_disable(struct drm_crtc *crtc) struct drm_device *dev = crtc->dev; struct radeon_device *rdev = dev->dev_private; struct radeon_atom_ss ss; - int i; atombios_crtc_dpms(crtc, DRM_MODE_DPMS_OFF); - for (i = 0; i < rdev->num_crtc; i++) { - if (rdev->mode_info.crtcs[i] && - rdev->mode_info.crtcs[i]->enabled && - i != radeon_crtc->crtc_id && - radeon_crtc->pll_id == rdev->mode_info.crtcs[i]->pll_id) { - /* one other crtc is using this pll don't turn - * off the pll - */ - goto done; - } - } - switch (radeon_crtc->pll_id) { case ATOM_PPLL1: case ATOM_PPLL2: @@ -1696,7 +1674,6 @@ static void atombios_crtc_disable(struct drm_crtc *crtc) default: break; } -done: radeon_crtc->pll_id = -1; } diff --git a/trunk/drivers/gpu/drm/radeon/atombios_dp.c b/trunk/drivers/gpu/drm/radeon/atombios_dp.c index 3623b98ed3fe..7712cf5ab33b 100644 --- a/trunk/drivers/gpu/drm/radeon/atombios_dp.c +++ b/trunk/drivers/gpu/drm/radeon/atombios_dp.c @@ -577,25 +577,30 @@ int radeon_dp_get_panel_mode(struct drm_encoder *encoder, struct radeon_device *rdev = dev->dev_private; struct radeon_connector *radeon_connector = to_radeon_connector(connector); int panel_mode = DP_PANEL_MODE_EXTERNAL_DP_MODE; - u16 dp_bridge = radeon_connector_encoder_get_dp_bridge_encoder_id(connector); - u8 tmp; if (!ASIC_IS_DCE4(rdev)) return panel_mode; - if (dp_bridge != ENCODER_OBJECT_ID_NONE) { - /* DP bridge chips */ - tmp = radeon_read_dpcd_reg(radeon_connector, DP_EDP_CONFIGURATION_CAP); - if (tmp & 1) - panel_mode = DP_PANEL_MODE_INTERNAL_DP2_MODE; - else if ((dp_bridge == ENCODER_OBJECT_ID_NUTMEG) || - (dp_bridge == ENCODER_OBJECT_ID_TRAVIS)) + if (radeon_connector_encoder_get_dp_bridge_encoder_id(connector) == + ENCODER_OBJECT_ID_NUTMEG) + panel_mode = DP_PANEL_MODE_INTERNAL_DP1_MODE; + else if (radeon_connector_encoder_get_dp_bridge_encoder_id(connector) == + ENCODER_OBJECT_ID_TRAVIS) { + u8 id[6]; + int i; + for (i = 0; i < 6; i++) + id[i] = radeon_read_dpcd_reg(radeon_connector, 0x503 + i); + if (id[0] == 0x73 && + id[1] == 0x69 && + id[2] == 0x76 && + id[3] == 0x61 && + id[4] == 0x72 && + id[5] == 0x54) panel_mode = DP_PANEL_MODE_INTERNAL_DP1_MODE; else - panel_mode = DP_PANEL_MODE_EXTERNAL_DP_MODE; + panel_mode = DP_PANEL_MODE_INTERNAL_DP2_MODE; } else if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) { - /* eDP */ - tmp = radeon_read_dpcd_reg(radeon_connector, DP_EDP_CONFIGURATION_CAP); + u8 tmp = radeon_read_dpcd_reg(radeon_connector, DP_EDP_CONFIGURATION_CAP); if (tmp & 1) panel_mode = DP_PANEL_MODE_INTERNAL_DP2_MODE; } diff --git a/trunk/drivers/gpu/drm/radeon/atombios_encoders.c b/trunk/drivers/gpu/drm/radeon/atombios_encoders.c index 6e8803a1170c..f9bc27fe269a 100644 --- a/trunk/drivers/gpu/drm/radeon/atombios_encoders.c +++ b/trunk/drivers/gpu/drm/radeon/atombios_encoders.c @@ -1379,8 +1379,6 @@ radeon_atom_encoder_dpms_dig(struct drm_encoder *encoder, int mode) struct drm_device *dev = encoder->dev; struct radeon_device *rdev = dev->dev_private; struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); - struct drm_encoder *ext_encoder = radeon_get_external_encoder(encoder); - struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); struct radeon_connector *radeon_connector = NULL; struct radeon_connector_atom_dig *radeon_dig_connector = NULL; @@ -1392,37 +1390,19 @@ radeon_atom_encoder_dpms_dig(struct drm_encoder *encoder, int mode) switch (mode) { case DRM_MODE_DPMS_ON: - if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE5(rdev)) { - if (!connector) - dig->panel_mode = DP_PANEL_MODE_EXTERNAL_DP_MODE; - else - dig->panel_mode = radeon_dp_get_panel_mode(encoder, connector); - - /* setup and enable the encoder */ - atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_SETUP, 0); - atombios_dig_encoder_setup(encoder, - ATOM_ENCODER_CMD_SETUP_PANEL_MODE, - dig->panel_mode); - if (ext_encoder) { - if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE61(rdev)) - atombios_external_encoder_setup(encoder, ext_encoder, - EXTERNAL_ENCODER_ACTION_V3_ENCODER_SETUP); + /* some early dce3.2 boards have a bug in their transmitter control table */ + if ((rdev->family == CHIP_RV710) || (rdev->family == CHIP_RV730) || + ASIC_IS_DCE41(rdev) || ASIC_IS_DCE5(rdev)) { + if (ASIC_IS_DCE6(rdev)) { + /* It seems we need to call ATOM_ENCODER_CMD_SETUP again + * before reenabling encoder on DPMS ON, otherwise we never + * get picture + */ + atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_SETUP, 0); } atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0); - } else if (ASIC_IS_DCE4(rdev)) { - /* setup and enable the encoder */ - atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_SETUP, 0); - /* enable the transmitter */ - atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0); - atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0); } else { - /* setup and enable the encoder and transmitter */ - atombios_dig_encoder_setup(encoder, ATOM_ENABLE, 0); - atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_SETUP, 0, 0); - atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0); - /* some early dce3.2 boards have a bug in their transmitter control table */ - if ((rdev->family != CHIP_RV710) || (rdev->family != CHIP_RV730)) - atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0); + atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0); } if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) && connector) { if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) { @@ -1440,19 +1420,10 @@ radeon_atom_encoder_dpms_dig(struct drm_encoder *encoder, int mode) case DRM_MODE_DPMS_STANDBY: case DRM_MODE_DPMS_SUSPEND: case DRM_MODE_DPMS_OFF: - if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE5(rdev)) { - /* disable the transmitter */ - atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0); - } else if (ASIC_IS_DCE4(rdev)) { - /* disable the transmitter */ - atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE_OUTPUT, 0, 0); + if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE5(rdev)) atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0); - } else { - /* disable the encoder and transmitter */ + else atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE_OUTPUT, 0, 0); - atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0); - atombios_dig_encoder_setup(encoder, ATOM_DISABLE, 0); - } if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) && connector) { if (ASIC_IS_DCE4(rdev)) atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_OFF, 0); @@ -1769,34 +1740,13 @@ static int radeon_atom_pick_dig_encoder(struct drm_encoder *encoder) struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc); struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); struct drm_encoder *test_encoder; - struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; + struct radeon_encoder_atom_dig *dig; uint32_t dig_enc_in_use = 0; - if (ASIC_IS_DCE6(rdev)) { - /* DCE6 */ - switch (radeon_encoder->encoder_id) { - case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: - if (dig->linkb) - return 1; - else - return 0; - break; - case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: - if (dig->linkb) - return 3; - else - return 2; - break; - case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: - if (dig->linkb) - return 5; - else - return 4; - break; - } - } else if (ASIC_IS_DCE4(rdev)) { - /* DCE4/5 */ - if (ASIC_IS_DCE41(rdev) && !ASIC_IS_DCE61(rdev)) { + /* DCE4/5 */ + if (ASIC_IS_DCE4(rdev)) { + dig = radeon_encoder->enc_priv; + if (ASIC_IS_DCE41(rdev)) { /* ontario follows DCE4 */ if (rdev->family == CHIP_PALM) { if (dig->linkb) @@ -1898,12 +1848,10 @@ radeon_atom_encoder_mode_set(struct drm_encoder *encoder, struct drm_device *dev = encoder->dev; struct radeon_device *rdev = dev->dev_private; struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + struct drm_encoder *ext_encoder = radeon_get_external_encoder(encoder); radeon_encoder->pixel_clock = adjusted_mode->clock; - /* need to call this here rather than in prepare() since we need some crtc info */ - radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_OFF); - if (ASIC_IS_AVIVO(rdev) && !ASIC_IS_DCE4(rdev)) { if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT | ATOM_DEVICE_TV_SUPPORT)) atombios_yuv_setup(encoder, true); @@ -1922,7 +1870,38 @@ radeon_atom_encoder_mode_set(struct drm_encoder *encoder, case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: - /* handled in dpms */ + if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE5(rdev)) { + struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); + struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; + + if (!connector) + dig->panel_mode = DP_PANEL_MODE_EXTERNAL_DP_MODE; + else + dig->panel_mode = radeon_dp_get_panel_mode(encoder, connector); + + /* setup and enable the encoder */ + atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_SETUP, 0); + atombios_dig_encoder_setup(encoder, + ATOM_ENCODER_CMD_SETUP_PANEL_MODE, + dig->panel_mode); + } else if (ASIC_IS_DCE4(rdev)) { + /* disable the transmitter */ + atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0); + /* setup and enable the encoder */ + atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_SETUP, 0); + + /* enable the transmitter */ + atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0); + } else { + /* disable the encoder and transmitter */ + atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0); + atombios_dig_encoder_setup(encoder, ATOM_DISABLE, 0); + + /* setup and enable the encoder and transmitter */ + atombios_dig_encoder_setup(encoder, ATOM_ENABLE, 0); + atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_SETUP, 0, 0); + atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0); + } break; case ENCODER_OBJECT_ID_INTERNAL_DDI: case ENCODER_OBJECT_ID_INTERNAL_DVO1: @@ -1943,6 +1922,14 @@ radeon_atom_encoder_mode_set(struct drm_encoder *encoder, break; } + if (ext_encoder) { + if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE61(rdev)) + atombios_external_encoder_setup(encoder, ext_encoder, + EXTERNAL_ENCODER_ACTION_V3_ENCODER_SETUP); + else + atombios_external_encoder_setup(encoder, ext_encoder, ATOM_ENABLE); + } + atombios_apply_encoder_quirks(encoder, adjusted_mode); if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_HDMI) { @@ -2129,6 +2116,7 @@ static void radeon_atom_encoder_prepare(struct drm_encoder *encoder) } radeon_atom_output_lock(encoder, true); + radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_OFF); if (connector) { struct radeon_connector *radeon_connector = to_radeon_connector(connector); @@ -2149,7 +2137,6 @@ static void radeon_atom_encoder_prepare(struct drm_encoder *encoder) static void radeon_atom_encoder_commit(struct drm_encoder *encoder) { - /* need to call this here as we need the crtc set up */ radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_ON); radeon_atom_output_lock(encoder, false); } @@ -2190,7 +2177,14 @@ static void radeon_atom_encoder_disable(struct drm_encoder *encoder) case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: - /* handled in dpms */ + if (ASIC_IS_DCE4(rdev)) + /* disable the transmitter */ + atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0); + else { + /* disable the encoder and transmitter */ + atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0); + atombios_dig_encoder_setup(encoder, ATOM_DISABLE, 0); + } break; case ENCODER_OBJECT_ID_INTERNAL_DDI: case ENCODER_OBJECT_ID_INTERNAL_DVO1: diff --git a/trunk/drivers/gpu/drm/radeon/evergreen.c b/trunk/drivers/gpu/drm/radeon/evergreen.c index ed3340adeb6f..e585a3b947eb 100644 --- a/trunk/drivers/gpu/drm/radeon/evergreen.c +++ b/trunk/drivers/gpu/drm/radeon/evergreen.c @@ -77,9 +77,13 @@ void evergreen_tiling_fields(unsigned tiling_flags, unsigned *bankw, void evergreen_fix_pci_max_read_req_size(struct radeon_device *rdev) { u16 ctl, v; - int err; + int cap, err; - err = pcie_capability_read_word(rdev->pdev, PCI_EXP_DEVCTL, &ctl); + cap = pci_pcie_cap(rdev->pdev); + if (!cap) + return; + + err = pci_read_config_word(rdev->pdev, cap + PCI_EXP_DEVCTL, &ctl); if (err) return; @@ -91,7 +95,7 @@ void evergreen_fix_pci_max_read_req_size(struct radeon_device *rdev) if ((v == 0) || (v == 6) || (v == 7)) { ctl &= ~PCI_EXP_DEVCTL_READRQ; ctl |= (2 << 12); - pcie_capability_write_word(rdev->pdev, PCI_EXP_DEVCTL, ctl); + pci_write_config_word(rdev->pdev, cap + PCI_EXP_DEVCTL, ctl); } } @@ -1225,8 +1229,24 @@ void evergreen_agp_enable(struct radeon_device *rdev) void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *save) { + save->vga_control[0] = RREG32(D1VGA_CONTROL); + save->vga_control[1] = RREG32(D2VGA_CONTROL); save->vga_render_control = RREG32(VGA_RENDER_CONTROL); save->vga_hdp_control = RREG32(VGA_HDP_CONTROL); + save->crtc_control[0] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET); + save->crtc_control[1] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET); + if (rdev->num_crtc >= 4) { + save->vga_control[2] = RREG32(EVERGREEN_D3VGA_CONTROL); + save->vga_control[3] = RREG32(EVERGREEN_D4VGA_CONTROL); + save->crtc_control[2] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET); + save->crtc_control[3] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET); + } + if (rdev->num_crtc >= 6) { + save->vga_control[4] = RREG32(EVERGREEN_D5VGA_CONTROL); + save->vga_control[5] = RREG32(EVERGREEN_D6VGA_CONTROL); + save->crtc_control[4] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET); + save->crtc_control[5] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET); + } /* Stop all video */ WREG32(VGA_RENDER_CONTROL, 0); @@ -1337,6 +1357,47 @@ void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_save *s /* Unlock host access */ WREG32(VGA_HDP_CONTROL, save->vga_hdp_control); mdelay(1); + /* Restore video state */ + WREG32(D1VGA_CONTROL, save->vga_control[0]); + WREG32(D2VGA_CONTROL, save->vga_control[1]); + if (rdev->num_crtc >= 4) { + WREG32(EVERGREEN_D3VGA_CONTROL, save->vga_control[2]); + WREG32(EVERGREEN_D4VGA_CONTROL, save->vga_control[3]); + } + if (rdev->num_crtc >= 6) { + WREG32(EVERGREEN_D5VGA_CONTROL, save->vga_control[4]); + WREG32(EVERGREEN_D6VGA_CONTROL, save->vga_control[5]); + } + WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC0_REGISTER_OFFSET, 1); + WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC1_REGISTER_OFFSET, 1); + if (rdev->num_crtc >= 4) { + WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC2_REGISTER_OFFSET, 1); + WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC3_REGISTER_OFFSET, 1); + } + if (rdev->num_crtc >= 6) { + WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC4_REGISTER_OFFSET, 1); + WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC5_REGISTER_OFFSET, 1); + } + WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET, save->crtc_control[0]); + WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET, save->crtc_control[1]); + if (rdev->num_crtc >= 4) { + WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET, save->crtc_control[2]); + WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET, save->crtc_control[3]); + } + if (rdev->num_crtc >= 6) { + WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET, save->crtc_control[4]); + WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, save->crtc_control[5]); + } + WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC0_REGISTER_OFFSET, 0); + WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC1_REGISTER_OFFSET, 0); + if (rdev->num_crtc >= 4) { + WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC2_REGISTER_OFFSET, 0); + WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC3_REGISTER_OFFSET, 0); + } + if (rdev->num_crtc >= 6) { + WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC4_REGISTER_OFFSET, 0); + WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC5_REGISTER_OFFSET, 0); + } WREG32(VGA_RENDER_CONTROL, save->vga_render_control); } @@ -1925,18 +1986,10 @@ static void evergreen_gpu_init(struct radeon_device *rdev) if (rdev->flags & RADEON_IS_IGP) rdev->config.evergreen.tile_config |= 1 << 4; else { - switch ((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT) { - case 0: /* four banks */ - rdev->config.evergreen.tile_config |= 0 << 4; - break; - case 1: /* eight banks */ + if ((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT) rdev->config.evergreen.tile_config |= 1 << 4; - break; - case 2: /* sixteen banks */ - default: - rdev->config.evergreen.tile_config |= 2 << 4; - break; - } + else + rdev->config.evergreen.tile_config |= 0 << 4; } rdev->config.evergreen.tile_config |= 0 << 8; rdev->config.evergreen.tile_config |= diff --git a/trunk/drivers/gpu/drm/radeon/evergreen_cs.c b/trunk/drivers/gpu/drm/radeon/evergreen_cs.c index e44a62a07fe3..c16554122ccd 100644 --- a/trunk/drivers/gpu/drm/radeon/evergreen_cs.c +++ b/trunk/drivers/gpu/drm/radeon/evergreen_cs.c @@ -788,13 +788,6 @@ static int evergreen_cs_track_validate_texture(struct radeon_cs_parser *p, case V_030000_SQ_TEX_DIM_1D_ARRAY: case V_030000_SQ_TEX_DIM_2D_ARRAY: depth = 1; - break; - case V_030000_SQ_TEX_DIM_2D_MSAA: - case V_030000_SQ_TEX_DIM_2D_ARRAY_MSAA: - surf.nsamples = 1 << llevel; - llevel = 0; - depth = 1; - break; case V_030000_SQ_TEX_DIM_3D: break; default: @@ -968,15 +961,13 @@ static int evergreen_cs_track_check(struct radeon_cs_parser *p) if (track->db_dirty) { /* Check stencil buffer */ - if (G_028044_FORMAT(track->db_s_info) != V_028044_STENCIL_INVALID && - G_028800_STENCIL_ENABLE(track->db_depth_control)) { + if (G_028800_STENCIL_ENABLE(track->db_depth_control)) { r = evergreen_cs_track_validate_stencil(p); if (r) return r; } /* Check depth buffer */ - if (G_028040_FORMAT(track->db_z_info) != V_028040_Z_INVALID && - G_028800_Z_ENABLE(track->db_depth_control)) { + if (G_028800_Z_ENABLE(track->db_depth_control)) { r = evergreen_cs_track_validate_depth(p); if (r) return r; diff --git a/trunk/drivers/gpu/drm/radeon/evergreend.h b/trunk/drivers/gpu/drm/radeon/evergreend.h index 79347855d9bf..d3bd098e4e19 100644 --- a/trunk/drivers/gpu/drm/radeon/evergreend.h +++ b/trunk/drivers/gpu/drm/radeon/evergreend.h @@ -1277,8 +1277,6 @@ #define S_028044_FORMAT(x) (((x) & 0x1) << 0) #define G_028044_FORMAT(x) (((x) >> 0) & 0x1) #define C_028044_FORMAT 0xFFFFFFFE -#define V_028044_STENCIL_INVALID 0 -#define V_028044_STENCIL_8 1 #define G_028044_TILE_SPLIT(x) (((x) >> 8) & 0x7) #define DB_Z_READ_BASE 0x28048 #define DB_STENCIL_READ_BASE 0x2804c diff --git a/trunk/drivers/gpu/drm/radeon/ni.c b/trunk/drivers/gpu/drm/radeon/ni.c index 853800e8582f..9945d86d9001 100644 --- a/trunk/drivers/gpu/drm/radeon/ni.c +++ b/trunk/drivers/gpu/drm/radeon/ni.c @@ -574,18 +574,10 @@ static void cayman_gpu_init(struct radeon_device *rdev) if (rdev->flags & RADEON_IS_IGP) rdev->config.cayman.tile_config |= 1 << 4; else { - switch ((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT) { - case 0: /* four banks */ - rdev->config.cayman.tile_config |= 0 << 4; - break; - case 1: /* eight banks */ + if ((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT) rdev->config.cayman.tile_config |= 1 << 4; - break; - case 2: /* sixteen banks */ - default: - rdev->config.cayman.tile_config |= 2 << 4; - break; - } + else + rdev->config.cayman.tile_config |= 0 << 4; } rdev->config.cayman.tile_config |= ((gb_addr_config & PIPE_INTERLEAVE_SIZE_MASK) >> PIPE_INTERLEAVE_SIZE_SHIFT) << 8; diff --git a/trunk/drivers/gpu/drm/radeon/r100.c b/trunk/drivers/gpu/drm/radeon/r100.c index 8d7e33a0b243..8acb34fd3fd5 100644 --- a/trunk/drivers/gpu/drm/radeon/r100.c +++ b/trunk/drivers/gpu/drm/radeon/r100.c @@ -1182,8 +1182,7 @@ int r100_cp_init(struct radeon_device *rdev, unsigned ring_size) ring->ready = true; radeon_ttm_set_active_vram_size(rdev, rdev->mc.real_vram_size); - if (!ring->rptr_save_reg /* not resuming from suspend */ - && radeon_ring_supports_scratch_reg(rdev, ring)) { + if (radeon_ring_supports_scratch_reg(rdev, ring)) { r = radeon_scratch_get(rdev, &ring->rptr_save_reg); if (r) { DRM_ERROR("failed to get scratch reg for rptr save (%d).\n", r); diff --git a/trunk/drivers/gpu/drm/radeon/r600.c b/trunk/drivers/gpu/drm/radeon/r600.c index d79c639ae739..637280f541a3 100644 --- a/trunk/drivers/gpu/drm/radeon/r600.c +++ b/trunk/drivers/gpu/drm/radeon/r600.c @@ -3789,23 +3789,3 @@ static void r600_pcie_gen2_enable(struct radeon_device *rdev) WREG32_PCIE_P(PCIE_LC_LINK_WIDTH_CNTL, link_width_cntl); } } - -/** - * r600_get_gpu_clock - return GPU clock counter snapshot - * - * @rdev: radeon_device pointer - * - * Fetches a GPU clock counter snapshot (R6xx-cayman). - * Returns the 64 bit clock counter snapshot. - */ -uint64_t r600_get_gpu_clock(struct radeon_device *rdev) -{ - uint64_t clock; - - mutex_lock(&rdev->gpu_clock_mutex); - WREG32(RLC_CAPTURE_GPU_CLOCK_COUNT, 1); - clock = (uint64_t)RREG32(RLC_GPU_CLOCK_COUNT_LSB) | - ((uint64_t)RREG32(RLC_GPU_CLOCK_COUNT_MSB) << 32ULL); - mutex_unlock(&rdev->gpu_clock_mutex); - return clock; -} diff --git a/trunk/drivers/gpu/drm/radeon/r600_cs.c b/trunk/drivers/gpu/drm/radeon/r600_cs.c index f37676d7f217..ca87f7afaf23 100644 --- a/trunk/drivers/gpu/drm/radeon/r600_cs.c +++ b/trunk/drivers/gpu/drm/radeon/r600_cs.c @@ -47,23 +47,18 @@ struct r600_cs_track { u32 npipes; /* value we track */ u32 sq_config; - u32 log_nsamples; u32 nsamples; u32 cb_color_base_last[8]; struct radeon_bo *cb_color_bo[8]; u64 cb_color_bo_mc[8]; - u64 cb_color_bo_offset[8]; - struct radeon_bo *cb_color_frag_bo[8]; - u64 cb_color_frag_offset[8]; - struct radeon_bo *cb_color_tile_bo[8]; - u64 cb_color_tile_offset[8]; - u32 cb_color_mask[8]; + u32 cb_color_bo_offset[8]; + struct radeon_bo *cb_color_frag_bo[8]; /* unused */ + struct radeon_bo *cb_color_tile_bo[8]; /* unused */ u32 cb_color_info[8]; u32 cb_color_view[8]; u32 cb_color_size_idx[8]; /* unused */ u32 cb_target_mask; u32 cb_shader_mask; /* unused */ - bool is_resolve; u32 cb_color_size[8]; u32 vgt_strmout_en; u32 vgt_strmout_buffer_en; @@ -316,15 +311,7 @@ static void r600_cs_track_init(struct r600_cs_track *track) track->cb_color_bo[i] = NULL; track->cb_color_bo_offset[i] = 0xFFFFFFFF; track->cb_color_bo_mc[i] = 0xFFFFFFFF; - track->cb_color_frag_bo[i] = NULL; - track->cb_color_frag_offset[i] = 0xFFFFFFFF; - track->cb_color_tile_bo[i] = NULL; - track->cb_color_tile_offset[i] = 0xFFFFFFFF; - track->cb_color_mask[i] = 0xFFFFFFFF; - } - track->is_resolve = false; - track->nsamples = 16; - track->log_nsamples = 4; + } track->cb_target_mask = 0xFFFFFFFF; track->cb_shader_mask = 0xFFFFFFFF; track->cb_dirty = true; @@ -361,9 +348,11 @@ static int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i) volatile u32 *ib = p->ib.ptr; unsigned array_mode; u32 format; - /* When resolve is used, the second colorbuffer has always 1 sample. */ - unsigned nsamples = track->is_resolve && i == 1 ? 1 : track->nsamples; + if (G_0280A0_TILE_MODE(track->cb_color_info[i])) { + dev_warn(p->dev, "FMASK or CMASK buffer are not supported by this kernel\n"); + return -EINVAL; + } size = radeon_bo_size(track->cb_color_bo[i]) - track->cb_color_bo_offset[i]; format = G_0280A0_FORMAT(track->cb_color_info[i]); if (!r600_fmt_is_valid_color(format)) { @@ -386,7 +375,7 @@ static int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i) array_check.group_size = track->group_size; array_check.nbanks = track->nbanks; array_check.npipes = track->npipes; - array_check.nsamples = nsamples; + array_check.nsamples = track->nsamples; array_check.blocksize = r600_fmt_get_blocksize(format); if (r600_get_array_mode_alignment(&array_check, &pitch_align, &height_align, &depth_align, &base_align)) { @@ -431,8 +420,7 @@ static int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i) } /* check offset */ - tmp = r600_fmt_get_nblocksy(format, height) * r600_fmt_get_nblocksx(format, pitch) * - r600_fmt_get_blocksize(format) * nsamples; + tmp = r600_fmt_get_nblocksy(format, height) * r600_fmt_get_nblocksx(format, pitch) * r600_fmt_get_blocksize(format); switch (array_mode) { default: case V_0280A0_ARRAY_LINEAR_GENERAL: @@ -453,7 +441,7 @@ static int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i) * broken userspace. */ } else { - dev_warn(p->dev, "%s offset[%d] %d %llu %d %lu too big (%d %d) (%d %d %d)\n", + dev_warn(p->dev, "%s offset[%d] %d %d %d %lu too big (%d %d) (%d %d %d)\n", __func__, i, array_mode, track->cb_color_bo_offset[i], tmp, radeon_bo_size(track->cb_color_bo[i]), @@ -470,51 +458,6 @@ static int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i) tmp = S_028060_PITCH_TILE_MAX((pitch / 8) - 1) | S_028060_SLICE_TILE_MAX(slice_tile_max - 1); ib[track->cb_color_size_idx[i]] = tmp; - - /* FMASK/CMASK */ - switch (G_0280A0_TILE_MODE(track->cb_color_info[i])) { - case V_0280A0_TILE_DISABLE: - break; - case V_0280A0_FRAG_ENABLE: - if (track->nsamples > 1) { - uint32_t tile_max = G_028100_FMASK_TILE_MAX(track->cb_color_mask[i]); - /* the tile size is 8x8, but the size is in units of bits. - * for bytes, do just * 8. */ - uint32_t bytes = track->nsamples * track->log_nsamples * 8 * (tile_max + 1); - - if (bytes + track->cb_color_frag_offset[i] > - radeon_bo_size(track->cb_color_frag_bo[i])) { - dev_warn(p->dev, "%s FMASK_TILE_MAX too large " - "(tile_max=%u, bytes=%u, offset=%llu, bo_size=%lu)\n", - __func__, tile_max, bytes, - track->cb_color_frag_offset[i], - radeon_bo_size(track->cb_color_frag_bo[i])); - return -EINVAL; - } - } - /* fall through */ - case V_0280A0_CLEAR_ENABLE: - { - uint32_t block_max = G_028100_CMASK_BLOCK_MAX(track->cb_color_mask[i]); - /* One block = 128x128 pixels, one 8x8 tile has 4 bits.. - * (128*128) / (8*8) / 2 = 128 bytes per block. */ - uint32_t bytes = (block_max + 1) * 128; - - if (bytes + track->cb_color_tile_offset[i] > - radeon_bo_size(track->cb_color_tile_bo[i])) { - dev_warn(p->dev, "%s CMASK_BLOCK_MAX too large " - "(block_max=%u, bytes=%u, offset=%llu, bo_size=%lu)\n", - __func__, block_max, bytes, - track->cb_color_tile_offset[i], - radeon_bo_size(track->cb_color_tile_bo[i])); - return -EINVAL; - } - break; - } - default: - dev_warn(p->dev, "%s invalid tile mode\n", __func__); - return -EINVAL; - } return 0; } @@ -623,7 +566,7 @@ static int r600_cs_track_validate_db(struct radeon_cs_parser *p) ntiles = G_028000_SLICE_TILE_MAX(track->db_depth_size) + 1; nviews = G_028004_SLICE_MAX(track->db_depth_view) + 1; - tmp = ntiles * bpe * 64 * nviews * track->nsamples; + tmp = ntiles * bpe * 64 * nviews; if ((tmp + track->db_offset) > radeon_bo_size(track->db_bo)) { dev_warn(p->dev, "z/stencil buffer (%d) too small (0x%08X %d %d %d -> %u have %lu)\n", array_mode, @@ -803,12 +746,6 @@ static int r600_cs_track_check(struct radeon_cs_parser *p) */ if (track->cb_dirty) { tmp = track->cb_target_mask; - - /* We must check both colorbuffers for RESOLVE. */ - if (track->is_resolve) { - tmp |= 0xff; - } - for (i = 0; i < 8; i++) { if ((tmp >> (i * 4)) & 0xF) { /* at least one component is enabled */ @@ -827,10 +764,8 @@ static int r600_cs_track_check(struct radeon_cs_parser *p) } /* Check depth buffer */ - if (track->db_dirty && - G_028010_FORMAT(track->db_depth_info) != V_028010_DEPTH_INVALID && - (G_028800_STENCIL_ENABLE(track->db_depth_control) || - G_028800_Z_ENABLE(track->db_depth_control))) { + if (track->db_dirty && (G_028800_STENCIL_ENABLE(track->db_depth_control) || + G_028800_Z_ENABLE(track->db_depth_control))) { r = r600_cs_track_validate_db(p); if (r) return r; @@ -1294,15 +1229,9 @@ static int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) break; case R_028C04_PA_SC_AA_CONFIG: tmp = G_028C04_MSAA_NUM_SAMPLES(radeon_get_ib_value(p, idx)); - track->log_nsamples = tmp; track->nsamples = 1 << tmp; track->cb_dirty = true; break; - case R_028808_CB_COLOR_CONTROL: - tmp = G_028808_SPECIAL_OP(radeon_get_ib_value(p, idx)); - track->is_resolve = tmp == V_028808_SPECIAL_RESOLVE_BOX; - track->cb_dirty = true; - break; case R_0280A0_CB_COLOR0_INFO: case R_0280A4_CB_COLOR1_INFO: case R_0280A8_CB_COLOR2_INFO: @@ -1381,21 +1310,16 @@ static int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) dev_err(p->dev, "Broken old userspace ? no cb_color0_base supplied before trying to write 0x%08X\n", reg); return -EINVAL; } - track->cb_color_frag_bo[tmp] = track->cb_color_bo[tmp]; - track->cb_color_frag_offset[tmp] = track->cb_color_bo_offset[tmp]; ib[idx] = track->cb_color_base_last[tmp]; + track->cb_color_frag_bo[tmp] = track->cb_color_bo[tmp]; } else { r = r600_cs_packet_next_reloc(p, &reloc); if (r) { dev_err(p->dev, "bad SET_CONTEXT_REG 0x%04X\n", reg); return -EINVAL; } - track->cb_color_frag_bo[tmp] = reloc->robj; - track->cb_color_frag_offset[tmp] = (u64)ib[idx] << 8; ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); - } - if (G_0280A0_TILE_MODE(track->cb_color_info[tmp])) { - track->cb_dirty = true; + track->cb_color_frag_bo[tmp] = reloc->robj; } break; case R_0280C0_CB_COLOR0_TILE: @@ -1412,35 +1336,16 @@ static int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) dev_err(p->dev, "Broken old userspace ? no cb_color0_base supplied before trying to write 0x%08X\n", reg); return -EINVAL; } - track->cb_color_tile_bo[tmp] = track->cb_color_bo[tmp]; - track->cb_color_tile_offset[tmp] = track->cb_color_bo_offset[tmp]; ib[idx] = track->cb_color_base_last[tmp]; + track->cb_color_tile_bo[tmp] = track->cb_color_bo[tmp]; } else { r = r600_cs_packet_next_reloc(p, &reloc); if (r) { dev_err(p->dev, "bad SET_CONTEXT_REG 0x%04X\n", reg); return -EINVAL; } - track->cb_color_tile_bo[tmp] = reloc->robj; - track->cb_color_tile_offset[tmp] = (u64)ib[idx] << 8; ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); - } - if (G_0280A0_TILE_MODE(track->cb_color_info[tmp])) { - track->cb_dirty = true; - } - break; - case R_028100_CB_COLOR0_MASK: - case R_028104_CB_COLOR1_MASK: - case R_028108_CB_COLOR2_MASK: - case R_02810C_CB_COLOR3_MASK: - case R_028110_CB_COLOR4_MASK: - case R_028114_CB_COLOR5_MASK: - case R_028118_CB_COLOR6_MASK: - case R_02811C_CB_COLOR7_MASK: - tmp = (reg - R_028100_CB_COLOR0_MASK) / 4; - track->cb_color_mask[tmp] = radeon_get_ib_value(p, idx); - if (G_0280A0_TILE_MODE(track->cb_color_info[tmp])) { - track->cb_dirty = true; + track->cb_color_tile_bo[tmp] = reloc->robj; } break; case CB_COLOR0_BASE: @@ -1585,7 +1490,7 @@ unsigned r600_mip_minify(unsigned size, unsigned level) } static void r600_texture_size(unsigned nfaces, unsigned blevel, unsigned llevel, - unsigned w0, unsigned h0, unsigned d0, unsigned nsamples, unsigned format, + unsigned w0, unsigned h0, unsigned d0, unsigned format, unsigned block_align, unsigned height_align, unsigned base_align, unsigned *l0_size, unsigned *mipmap_size) { @@ -1613,7 +1518,7 @@ static void r600_texture_size(unsigned nfaces, unsigned blevel, unsigned llevel, depth = r600_mip_minify(d0, i); - size = nbx * nby * blocksize * nsamples; + size = nbx * nby * blocksize; if (nfaces) size *= nfaces; else @@ -1652,14 +1557,13 @@ static int r600_check_texture_resource(struct radeon_cs_parser *p, u32 idx, u32 tiling_flags) { struct r600_cs_track *track = p->track; - u32 dim, nfaces, llevel, blevel, w0, h0, d0; - u32 word0, word1, l0_size, mipmap_size, word2, word3, word4, word5; + u32 nfaces, llevel, blevel, w0, h0, d0; + u32 word0, word1, l0_size, mipmap_size, word2, word3; u32 height_align, pitch, pitch_align, depth_align; - u32 barray, larray; + u32 array, barray, larray; u64 base_align; struct array_mode_checker array_check; u32 format; - bool is_array; /* on legacy kernel we don't perform advanced check */ if (p->rdev == NULL) @@ -1677,28 +1581,12 @@ static int r600_check_texture_resource(struct radeon_cs_parser *p, u32 idx, word0 |= S_038000_TILE_MODE(V_038000_ARRAY_1D_TILED_THIN1); } word1 = radeon_get_ib_value(p, idx + 1); - word2 = radeon_get_ib_value(p, idx + 2) << 8; - word3 = radeon_get_ib_value(p, idx + 3) << 8; - word4 = radeon_get_ib_value(p, idx + 4); - word5 = radeon_get_ib_value(p, idx + 5); - dim = G_038000_DIM(word0); w0 = G_038000_TEX_WIDTH(word0) + 1; - pitch = (G_038000_PITCH(word0) + 1) * 8; h0 = G_038004_TEX_HEIGHT(word1) + 1; d0 = G_038004_TEX_DEPTH(word1); - format = G_038004_DATA_FORMAT(word1); - blevel = G_038010_BASE_LEVEL(word4); - llevel = G_038014_LAST_LEVEL(word5); - /* pitch in texels */ - array_check.array_mode = G_038000_TILE_MODE(word0); - array_check.group_size = track->group_size; - array_check.nbanks = track->nbanks; - array_check.npipes = track->npipes; - array_check.nsamples = 1; - array_check.blocksize = r600_fmt_get_blocksize(format); nfaces = 1; - is_array = false; - switch (dim) { + array = 0; + switch (G_038000_DIM(word0)) { case V_038000_SQ_TEX_DIM_1D: case V_038000_SQ_TEX_DIM_2D: case V_038000_SQ_TEX_DIM_3D: @@ -1711,25 +1599,29 @@ static int r600_check_texture_resource(struct radeon_cs_parser *p, u32 idx, break; case V_038000_SQ_TEX_DIM_1D_ARRAY: case V_038000_SQ_TEX_DIM_2D_ARRAY: - is_array = true; + array = 1; break; - case V_038000_SQ_TEX_DIM_2D_ARRAY_MSAA: - is_array = true; - /* fall through */ case V_038000_SQ_TEX_DIM_2D_MSAA: - array_check.nsamples = 1 << llevel; - llevel = 0; - break; + case V_038000_SQ_TEX_DIM_2D_ARRAY_MSAA: default: dev_warn(p->dev, "this kernel doesn't support %d texture dim\n", G_038000_DIM(word0)); return -EINVAL; } + format = G_038004_DATA_FORMAT(word1); if (!r600_fmt_is_valid_texture(format, p->family)) { dev_warn(p->dev, "%s:%d texture invalid format %d\n", __func__, __LINE__, format); return -EINVAL; } + /* pitch in texels */ + pitch = (G_038000_PITCH(word0) + 1) * 8; + array_check.array_mode = G_038000_TILE_MODE(word0); + array_check.group_size = track->group_size; + array_check.nbanks = track->nbanks; + array_check.npipes = track->npipes; + array_check.nsamples = 1; + array_check.blocksize = r600_fmt_get_blocksize(format); if (r600_get_array_mode_alignment(&array_check, &pitch_align, &height_align, &depth_align, &base_align)) { dev_warn(p->dev, "%s:%d tex array mode (%d) invalid\n", @@ -1755,17 +1647,24 @@ static int r600_check_texture_resource(struct radeon_cs_parser *p, u32 idx, return -EINVAL; } + word2 = radeon_get_ib_value(p, idx + 2) << 8; + word3 = radeon_get_ib_value(p, idx + 3) << 8; + + word0 = radeon_get_ib_value(p, idx + 4); + word1 = radeon_get_ib_value(p, idx + 5); + blevel = G_038010_BASE_LEVEL(word0); + llevel = G_038014_LAST_LEVEL(word1); if (blevel > llevel) { dev_warn(p->dev, "texture blevel %d > llevel %d\n", blevel, llevel); } - if (is_array) { - barray = G_038014_BASE_ARRAY(word5); - larray = G_038014_LAST_ARRAY(word5); + if (array == 1) { + barray = G_038014_BASE_ARRAY(word1); + larray = G_038014_LAST_ARRAY(word1); nfaces = larray - barray + 1; } - r600_texture_size(nfaces, blevel, llevel, w0, h0, d0, array_check.nsamples, format, + r600_texture_size(nfaces, blevel, llevel, w0, h0, d0, format, pitch_align, height_align, base_align, &l0_size, &mipmap_size); /* using get ib will give us the offset into the texture bo */ @@ -1778,6 +1677,7 @@ static int r600_check_texture_resource(struct radeon_cs_parser *p, u32 idx, return -EINVAL; } /* using get ib will give us the offset into the mipmap bo */ + word3 = radeon_get_ib_value(p, idx + 3) << 8; if ((mipmap_size + word3) > radeon_bo_size(mipmap)) { /*dev_warn(p->dev, "mipmap bo too small (%d %d %d %d %d %d -> %d have %ld)\n", w0, h0, format, blevel, nlevels, word3, mipmap_size, radeon_bo_size(texture));*/ diff --git a/trunk/drivers/gpu/drm/radeon/r600d.h b/trunk/drivers/gpu/drm/radeon/r600d.h index fa6f37099ba9..4b116ae75fc2 100644 --- a/trunk/drivers/gpu/drm/radeon/r600d.h +++ b/trunk/drivers/gpu/drm/radeon/r600d.h @@ -66,14 +66,6 @@ #define CC_RB_BACKEND_DISABLE 0x98F4 #define BACKEND_DISABLE(x) ((x) << 16) -#define R_028808_CB_COLOR_CONTROL 0x28808 -#define S_028808_SPECIAL_OP(x) (((x) & 0x7) << 4) -#define G_028808_SPECIAL_OP(x) (((x) >> 4) & 0x7) -#define C_028808_SPECIAL_OP 0xFFFFFF8F -#define V_028808_SPECIAL_NORMAL 0x00 -#define V_028808_SPECIAL_DISABLE 0x01 -#define V_028808_SPECIAL_RESOLVE_BOX 0x07 - #define CB_COLOR0_BASE 0x28040 #define CB_COLOR1_BASE 0x28044 #define CB_COLOR2_BASE 0x28048 @@ -100,20 +92,6 @@ #define R_028094_CB_COLOR5_VIEW 0x028094 #define R_028098_CB_COLOR6_VIEW 0x028098 #define R_02809C_CB_COLOR7_VIEW 0x02809C -#define R_028100_CB_COLOR0_MASK 0x028100 -#define S_028100_CMASK_BLOCK_MAX(x) (((x) & 0xFFF) << 0) -#define G_028100_CMASK_BLOCK_MAX(x) (((x) >> 0) & 0xFFF) -#define C_028100_CMASK_BLOCK_MAX 0xFFFFF000 -#define S_028100_FMASK_TILE_MAX(x) (((x) & 0xFFFFF) << 12) -#define G_028100_FMASK_TILE_MAX(x) (((x) >> 12) & 0xFFFFF) -#define C_028100_FMASK_TILE_MAX 0x00000FFF -#define R_028104_CB_COLOR1_MASK 0x028104 -#define R_028108_CB_COLOR2_MASK 0x028108 -#define R_02810C_CB_COLOR3_MASK 0x02810C -#define R_028110_CB_COLOR4_MASK 0x028110 -#define R_028114_CB_COLOR5_MASK 0x028114 -#define R_028118_CB_COLOR6_MASK 0x028118 -#define R_02811C_CB_COLOR7_MASK 0x02811C #define CB_COLOR0_INFO 0x280a0 # define CB_FORMAT(x) ((x) << 2) # define CB_ARRAY_MODE(x) ((x) << 8) @@ -624,9 +602,6 @@ #define RLC_HB_WPTR 0x3f1c #define RLC_HB_WPTR_LSB_ADDR 0x3f14 #define RLC_HB_WPTR_MSB_ADDR 0x3f18 -#define RLC_GPU_CLOCK_COUNT_LSB 0x3f38 -#define RLC_GPU_CLOCK_COUNT_MSB 0x3f3c -#define RLC_CAPTURE_GPU_CLOCK_COUNT 0x3f40 #define RLC_MC_CNTL 0x3f44 #define RLC_UCODE_CNTL 0x3f48 #define RLC_UCODE_ADDR 0x3f2c @@ -1422,9 +1397,6 @@ #define S_0280A0_TILE_MODE(x) (((x) & 0x3) << 18) #define G_0280A0_TILE_MODE(x) (((x) >> 18) & 0x3) #define C_0280A0_TILE_MODE 0xFFF3FFFF -#define V_0280A0_TILE_DISABLE 0 -#define V_0280A0_CLEAR_ENABLE 1 -#define V_0280A0_FRAG_ENABLE 2 #define S_0280A0_BLEND_CLAMP(x) (((x) & 0x1) << 20) #define G_0280A0_BLEND_CLAMP(x) (((x) >> 20) & 0x1) #define C_0280A0_BLEND_CLAMP 0xFFEFFFFF diff --git a/trunk/drivers/gpu/drm/radeon/radeon.h b/trunk/drivers/gpu/drm/radeon/radeon.h index 59a15315ae9f..5431af292408 100644 --- a/trunk/drivers/gpu/drm/radeon/radeon.h +++ b/trunk/drivers/gpu/drm/radeon/radeon.h @@ -142,6 +142,21 @@ struct radeon_device; /* * BIOS. */ +#define ATRM_BIOS_PAGE 4096 + +#if defined(CONFIG_VGA_SWITCHEROO) +bool radeon_atrm_supported(struct pci_dev *pdev); +int radeon_atrm_get_bios_chunk(uint8_t *bios, int offset, int len); +#else +static inline bool radeon_atrm_supported(struct pci_dev *pdev) +{ + return false; +} + +static inline int radeon_atrm_get_bios_chunk(uint8_t *bios, int offset, int len){ + return -EINVAL; +} +#endif bool radeon_get_bios(struct radeon_device *rdev); /* @@ -285,7 +300,6 @@ struct radeon_bo_va { uint64_t soffset; uint64_t eoffset; uint32_t flags; - struct radeon_fence *fence; bool valid; }; @@ -1519,7 +1533,6 @@ struct radeon_device { unsigned debugfs_count; /* virtual memory */ struct radeon_vm_manager vm_manager; - struct mutex gpu_clock_mutex; }; int radeon_device_init(struct radeon_device *rdev, @@ -1720,11 +1733,11 @@ void radeon_ring_write(struct radeon_ring *ring, uint32_t v); #define radeon_pm_finish(rdev) (rdev)->asic->pm.finish((rdev)) #define radeon_pm_init_profile(rdev) (rdev)->asic->pm.init_profile((rdev)) #define radeon_pm_get_dynpm_state(rdev) (rdev)->asic->pm.get_dynpm_state((rdev)) -#define radeon_pre_page_flip(rdev, crtc) (rdev)->asic->pflip.pre_page_flip((rdev), (crtc)) -#define radeon_page_flip(rdev, crtc, base) (rdev)->asic->pflip.page_flip((rdev), (crtc), (base)) -#define radeon_post_page_flip(rdev, crtc) (rdev)->asic->pflip.post_page_flip((rdev), (crtc)) -#define radeon_wait_for_vblank(rdev, crtc) (rdev)->asic->display.wait_for_vblank((rdev), (crtc)) -#define radeon_mc_wait_for_idle(rdev) (rdev)->asic->mc_wait_for_idle((rdev)) +#define radeon_pre_page_flip(rdev, crtc) rdev->asic->pflip.pre_page_flip((rdev), (crtc)) +#define radeon_page_flip(rdev, crtc, base) rdev->asic->pflip.page_flip((rdev), (crtc), (base)) +#define radeon_post_page_flip(rdev, crtc) rdev->asic->pflip.post_page_flip((rdev), (crtc)) +#define radeon_wait_for_vblank(rdev, crtc) rdev->asic->display.wait_for_vblank((rdev), (crtc)) +#define radeon_mc_wait_for_idle(rdev) rdev->asic->mc_wait_for_idle((rdev)) /* Common functions */ /* AGP */ diff --git a/trunk/drivers/gpu/drm/radeon/radeon_asic.h b/trunk/drivers/gpu/drm/radeon/radeon_asic.h index 18c38d14c8cd..f4af24310438 100644 --- a/trunk/drivers/gpu/drm/radeon/radeon_asic.h +++ b/trunk/drivers/gpu/drm/radeon/radeon_asic.h @@ -255,10 +255,13 @@ extern int rs690_mc_wait_for_idle(struct radeon_device *rdev); * rv515 */ struct rv515_mc_save { + u32 d1vga_control; + u32 d2vga_control; u32 vga_render_control; u32 vga_hdp_control; + u32 d1crtc_control; + u32 d2crtc_control; }; - int rv515_init(struct radeon_device *rdev); void rv515_fini(struct radeon_device *rdev); uint32_t rv515_mc_rreg(struct radeon_device *rdev, uint32_t reg); @@ -368,7 +371,6 @@ void r600_kms_blit_copy(struct radeon_device *rdev, unsigned num_gpu_pages, struct radeon_sa_bo *vb); int r600_mc_wait_for_idle(struct radeon_device *rdev); -uint64_t r600_get_gpu_clock(struct radeon_device *rdev); /* * rv770,rv730,rv710,rv740 @@ -387,10 +389,11 @@ void r700_cp_fini(struct radeon_device *rdev); * evergreen */ struct evergreen_mc_save { + u32 vga_control[6]; u32 vga_render_control; u32 vga_hdp_control; + u32 crtc_control[6]; }; - void evergreen_pcie_gart_tlb_flush(struct radeon_device *rdev); int evergreen_init(struct radeon_device *rdev); void evergreen_fini(struct radeon_device *rdev); @@ -469,6 +472,5 @@ int si_vm_bind(struct radeon_device *rdev, struct radeon_vm *vm, int id); void si_vm_unbind(struct radeon_device *rdev, struct radeon_vm *vm); void si_vm_tlb_flush(struct radeon_device *rdev, struct radeon_vm *vm); int si_ib_parse(struct radeon_device *rdev, struct radeon_ib *ib); -uint64_t si_get_gpu_clock(struct radeon_device *rdev); #endif diff --git a/trunk/drivers/gpu/drm/radeon/radeon_atombios.c b/trunk/drivers/gpu/drm/radeon/radeon_atombios.c index d67d4f3eb6f4..b1e3820df363 100644 --- a/trunk/drivers/gpu/drm/radeon/radeon_atombios.c +++ b/trunk/drivers/gpu/drm/radeon/radeon_atombios.c @@ -452,7 +452,7 @@ static bool radeon_atom_apply_quirks(struct drm_device *dev, } /* Fujitsu D3003-S2 board lists DVI-I as DVI-D and VGA */ - if (((dev->pdev->device == 0x9802) || (dev->pdev->device == 0x9806)) && + if ((dev->pdev->device == 0x9802) && (dev->pdev->subsystem_vendor == 0x1734) && (dev->pdev->subsystem_device == 0x11bd)) { if (*connector_type == DRM_MODE_CONNECTOR_VGA) { @@ -1263,8 +1263,6 @@ bool radeon_atom_get_clock_info(struct drm_device *dev) union igp_info { struct _ATOM_INTEGRATED_SYSTEM_INFO info; struct _ATOM_INTEGRATED_SYSTEM_INFO_V2 info_2; - struct _ATOM_INTEGRATED_SYSTEM_INFO_V6 info_6; - struct _ATOM_INTEGRATED_SYSTEM_INFO_V1_7 info_7; }; bool radeon_atombios_sideport_present(struct radeon_device *rdev) @@ -1392,50 +1390,27 @@ static void radeon_atombios_get_igp_ss_overrides(struct radeon_device *rdev, struct radeon_mode_info *mode_info = &rdev->mode_info; int index = GetIndexIntoMasterTable(DATA, IntegratedSystemInfo); u16 data_offset, size; - union igp_info *igp_info; + struct _ATOM_INTEGRATED_SYSTEM_INFO_V6 *igp_info; u8 frev, crev; u16 percentage = 0, rate = 0; /* get any igp specific overrides */ if (atom_parse_data_header(mode_info->atom_context, index, &size, &frev, &crev, &data_offset)) { - igp_info = (union igp_info *) + igp_info = (struct _ATOM_INTEGRATED_SYSTEM_INFO_V6 *) (mode_info->atom_context->bios + data_offset); - switch (crev) { - case 6: - switch (id) { - case ASIC_INTERNAL_SS_ON_TMDS: - percentage = le16_to_cpu(igp_info->info_6.usDVISSPercentage); - rate = le16_to_cpu(igp_info->info_6.usDVISSpreadRateIn10Hz); - break; - case ASIC_INTERNAL_SS_ON_HDMI: - percentage = le16_to_cpu(igp_info->info_6.usHDMISSPercentage); - rate = le16_to_cpu(igp_info->info_6.usHDMISSpreadRateIn10Hz); - break; - case ASIC_INTERNAL_SS_ON_LVDS: - percentage = le16_to_cpu(igp_info->info_6.usLvdsSSPercentage); - rate = le16_to_cpu(igp_info->info_6.usLvdsSSpreadRateIn10Hz); - break; - } + switch (id) { + case ASIC_INTERNAL_SS_ON_TMDS: + percentage = le16_to_cpu(igp_info->usDVISSPercentage); + rate = le16_to_cpu(igp_info->usDVISSpreadRateIn10Hz); break; - case 7: - switch (id) { - case ASIC_INTERNAL_SS_ON_TMDS: - percentage = le16_to_cpu(igp_info->info_7.usDVISSPercentage); - rate = le16_to_cpu(igp_info->info_7.usDVISSpreadRateIn10Hz); - break; - case ASIC_INTERNAL_SS_ON_HDMI: - percentage = le16_to_cpu(igp_info->info_7.usHDMISSPercentage); - rate = le16_to_cpu(igp_info->info_7.usHDMISSpreadRateIn10Hz); - break; - case ASIC_INTERNAL_SS_ON_LVDS: - percentage = le16_to_cpu(igp_info->info_7.usLvdsSSPercentage); - rate = le16_to_cpu(igp_info->info_7.usLvdsSSpreadRateIn10Hz); - break; - } + case ASIC_INTERNAL_SS_ON_HDMI: + percentage = le16_to_cpu(igp_info->usHDMISSPercentage); + rate = le16_to_cpu(igp_info->usHDMISSpreadRateIn10Hz); break; - default: - DRM_ERROR("Unsupported IGP table: %d %d\n", frev, crev); + case ASIC_INTERNAL_SS_ON_LVDS: + percentage = le16_to_cpu(igp_info->usLvdsSSPercentage); + rate = le16_to_cpu(igp_info->usLvdsSSpreadRateIn10Hz); break; } if (percentage) diff --git a/trunk/drivers/gpu/drm/radeon/radeon_atpx_handler.c b/trunk/drivers/gpu/drm/radeon/radeon_atpx_handler.c index 2a2cf0b88a28..98724fcb0088 100644 --- a/trunk/drivers/gpu/drm/radeon/radeon_atpx_handler.c +++ b/trunk/drivers/gpu/drm/radeon/radeon_atpx_handler.c @@ -30,8 +30,57 @@ static struct radeon_atpx_priv { /* handle for device - and atpx */ acpi_handle dhandle; acpi_handle atpx_handle; + acpi_handle atrm_handle; } radeon_atpx_priv; +/* retrieve the ROM in 4k blocks */ +static int radeon_atrm_call(acpi_handle atrm_handle, uint8_t *bios, + int offset, int len) +{ + acpi_status status; + union acpi_object atrm_arg_elements[2], *obj; + struct acpi_object_list atrm_arg; + struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL}; + + atrm_arg.count = 2; + atrm_arg.pointer = &atrm_arg_elements[0]; + + atrm_arg_elements[0].type = ACPI_TYPE_INTEGER; + atrm_arg_elements[0].integer.value = offset; + + atrm_arg_elements[1].type = ACPI_TYPE_INTEGER; + atrm_arg_elements[1].integer.value = len; + + status = acpi_evaluate_object(atrm_handle, NULL, &atrm_arg, &buffer); + if (ACPI_FAILURE(status)) { + printk("failed to evaluate ATRM got %s\n", acpi_format_exception(status)); + return -ENODEV; + } + + obj = (union acpi_object *)buffer.pointer; + memcpy(bios+offset, obj->buffer.pointer, obj->buffer.length); + len = obj->buffer.length; + kfree(buffer.pointer); + return len; +} + +bool radeon_atrm_supported(struct pci_dev *pdev) +{ + /* get the discrete ROM only via ATRM */ + if (!radeon_atpx_priv.atpx_detected) + return false; + + if (radeon_atpx_priv.dhandle == DEVICE_ACPI_HANDLE(&pdev->dev)) + return false; + return true; +} + + +int radeon_atrm_get_bios_chunk(uint8_t *bios, int offset, int len) +{ + return radeon_atrm_call(radeon_atpx_priv.atrm_handle, bios, offset, len); +} + static int radeon_atpx_get_version(acpi_handle handle) { acpi_status status; @@ -149,7 +198,7 @@ static int radeon_atpx_power_state(enum vga_switcheroo_client_id id, static bool radeon_atpx_pci_probe_handle(struct pci_dev *pdev) { - acpi_handle dhandle, atpx_handle; + acpi_handle dhandle, atpx_handle, atrm_handle; acpi_status status; dhandle = DEVICE_ACPI_HANDLE(&pdev->dev); @@ -160,8 +209,13 @@ static bool radeon_atpx_pci_probe_handle(struct pci_dev *pdev) if (ACPI_FAILURE(status)) return false; + status = acpi_get_handle(dhandle, "ATRM", &atrm_handle); + if (ACPI_FAILURE(status)) + return false; + radeon_atpx_priv.dhandle = dhandle; radeon_atpx_priv.atpx_handle = atpx_handle; + radeon_atpx_priv.atrm_handle = atrm_handle; return true; } diff --git a/trunk/drivers/gpu/drm/radeon/radeon_bios.c b/trunk/drivers/gpu/drm/radeon/radeon_bios.c index d306cc8fdeaa..501f4881e5aa 100644 --- a/trunk/drivers/gpu/drm/radeon/radeon_bios.c +++ b/trunk/drivers/gpu/drm/radeon/radeon_bios.c @@ -32,7 +32,6 @@ #include #include -#include /* * BIOS. */ @@ -99,81 +98,16 @@ static bool radeon_read_bios(struct radeon_device *rdev) return true; } -#ifdef CONFIG_ACPI /* ATRM is used to get the BIOS on the discrete cards in * dual-gpu systems. */ -/* retrieve the ROM in 4k blocks */ -#define ATRM_BIOS_PAGE 4096 -/** - * radeon_atrm_call - fetch a chunk of the vbios - * - * @atrm_handle: acpi ATRM handle - * @bios: vbios image pointer - * @offset: offset of vbios image data to fetch - * @len: length of vbios image data to fetch - * - * Executes ATRM to fetch a chunk of the discrete - * vbios image on PX systems (all asics). - * Returns the length of the buffer fetched. - */ -static int radeon_atrm_call(acpi_handle atrm_handle, uint8_t *bios, - int offset, int len) -{ - acpi_status status; - union acpi_object atrm_arg_elements[2], *obj; - struct acpi_object_list atrm_arg; - struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL}; - - atrm_arg.count = 2; - atrm_arg.pointer = &atrm_arg_elements[0]; - - atrm_arg_elements[0].type = ACPI_TYPE_INTEGER; - atrm_arg_elements[0].integer.value = offset; - - atrm_arg_elements[1].type = ACPI_TYPE_INTEGER; - atrm_arg_elements[1].integer.value = len; - - status = acpi_evaluate_object(atrm_handle, NULL, &atrm_arg, &buffer); - if (ACPI_FAILURE(status)) { - printk("failed to evaluate ATRM got %s\n", acpi_format_exception(status)); - return -ENODEV; - } - - obj = (union acpi_object *)buffer.pointer; - memcpy(bios+offset, obj->buffer.pointer, obj->buffer.length); - len = obj->buffer.length; - kfree(buffer.pointer); - return len; -} - static bool radeon_atrm_get_bios(struct radeon_device *rdev) { int ret; int size = 256 * 1024; int i; - struct pci_dev *pdev = NULL; - acpi_handle dhandle, atrm_handle; - acpi_status status; - bool found = false; - - /* ATRM is for the discrete card only */ - if (rdev->flags & RADEON_IS_IGP) - return false; - - while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, pdev)) != NULL) { - dhandle = DEVICE_ACPI_HANDLE(&pdev->dev); - if (!dhandle) - continue; - - status = acpi_get_handle(dhandle, "ATRM", &atrm_handle); - if (!ACPI_FAILURE(status)) { - found = true; - break; - } - } - if (!found) + if (!radeon_atrm_supported(rdev->pdev)) return false; rdev->bios = kmalloc(size, GFP_KERNEL); @@ -183,10 +117,9 @@ static bool radeon_atrm_get_bios(struct radeon_device *rdev) } for (i = 0; i < size / ATRM_BIOS_PAGE; i++) { - ret = radeon_atrm_call(atrm_handle, - rdev->bios, - (i * ATRM_BIOS_PAGE), - ATRM_BIOS_PAGE); + ret = radeon_atrm_get_bios_chunk(rdev->bios, + (i * ATRM_BIOS_PAGE), + ATRM_BIOS_PAGE); if (ret < ATRM_BIOS_PAGE) break; } @@ -197,12 +130,6 @@ static bool radeon_atrm_get_bios(struct radeon_device *rdev) } return true; } -#else -static inline bool radeon_atrm_get_bios(struct radeon_device *rdev) -{ - return false; -} -#endif static bool ni_read_disabled_bios(struct radeon_device *rdev) { @@ -549,61 +476,6 @@ static bool radeon_read_disabled_bios(struct radeon_device *rdev) return legacy_read_disabled_bios(rdev); } -#ifdef CONFIG_ACPI -static bool radeon_acpi_vfct_bios(struct radeon_device *rdev) -{ - bool ret = false; - struct acpi_table_header *hdr; - acpi_size tbl_size; - UEFI_ACPI_VFCT *vfct; - GOP_VBIOS_CONTENT *vbios; - VFCT_IMAGE_HEADER *vhdr; - - if (!ACPI_SUCCESS(acpi_get_table_with_size("VFCT", 1, &hdr, &tbl_size))) - return false; - if (tbl_size < sizeof(UEFI_ACPI_VFCT)) { - DRM_ERROR("ACPI VFCT table present but broken (too short #1)\n"); - goto out_unmap; - } - - vfct = (UEFI_ACPI_VFCT *)hdr; - if (vfct->VBIOSImageOffset + sizeof(VFCT_IMAGE_HEADER) > tbl_size) { - DRM_ERROR("ACPI VFCT table present but broken (too short #2)\n"); - goto out_unmap; - } - - vbios = (GOP_VBIOS_CONTENT *)((char *)hdr + vfct->VBIOSImageOffset); - vhdr = &vbios->VbiosHeader; - DRM_INFO("ACPI VFCT contains a BIOS for %02x:%02x.%d %04x:%04x, size %d\n", - vhdr->PCIBus, vhdr->PCIDevice, vhdr->PCIFunction, - vhdr->VendorID, vhdr->DeviceID, vhdr->ImageLength); - - if (vhdr->PCIBus != rdev->pdev->bus->number || - vhdr->PCIDevice != PCI_SLOT(rdev->pdev->devfn) || - vhdr->PCIFunction != PCI_FUNC(rdev->pdev->devfn) || - vhdr->VendorID != rdev->pdev->vendor || - vhdr->DeviceID != rdev->pdev->device) { - DRM_INFO("ACPI VFCT table is not for this card\n"); - goto out_unmap; - }; - - if (vfct->VBIOSImageOffset + sizeof(VFCT_IMAGE_HEADER) + vhdr->ImageLength > tbl_size) { - DRM_ERROR("ACPI VFCT image truncated\n"); - goto out_unmap; - } - - rdev->bios = kmemdup(&vbios->VbiosContent, vhdr->ImageLength, GFP_KERNEL); - ret = !!rdev->bios; - -out_unmap: - return ret; -} -#else -static inline bool radeon_acpi_vfct_bios(struct radeon_device *rdev) -{ - return false; -} -#endif bool radeon_get_bios(struct radeon_device *rdev) { @@ -611,8 +483,6 @@ bool radeon_get_bios(struct radeon_device *rdev) uint16_t tmp; r = radeon_atrm_get_bios(rdev); - if (r == false) - r = radeon_acpi_vfct_bios(rdev); if (r == false) r = igp_read_bios_from_vram(rdev); if (r == false) diff --git a/trunk/drivers/gpu/drm/radeon/radeon_combios.c b/trunk/drivers/gpu/drm/radeon/radeon_combios.c index f75247d42ffd..576f4f6919f2 100644 --- a/trunk/drivers/gpu/drm/radeon/radeon_combios.c +++ b/trunk/drivers/gpu/drm/radeon/radeon_combios.c @@ -719,34 +719,6 @@ static struct radeon_i2c_bus_rec combios_setup_i2c_bus(struct radeon_device *rde return i2c; } -static struct radeon_i2c_bus_rec radeon_combios_get_i2c_info_from_table(struct radeon_device *rdev) -{ - struct drm_device *dev = rdev->ddev; - struct radeon_i2c_bus_rec i2c; - u16 offset; - u8 id, blocks, clk, data; - int i; - - i2c.valid = false; - - offset = combios_get_table_offset(dev, COMBIOS_I2C_INFO_TABLE); - if (offset) { - blocks = RBIOS8(offset + 2); - for (i = 0; i < blocks; i++) { - id = RBIOS8(offset + 3 + (i * 5) + 0); - if (id == 136) { - clk = RBIOS8(offset + 3 + (i * 5) + 3); - data = RBIOS8(offset + 3 + (i * 5) + 4); - /* gpiopad */ - i2c = combios_setup_i2c_bus(rdev, DDC_MONID, - (1 << clk), (1 << data)); - break; - } - } - } - return i2c; -} - void radeon_combios_i2c_init(struct radeon_device *rdev) { struct drm_device *dev = rdev->ddev; @@ -783,14 +755,30 @@ void radeon_combios_i2c_init(struct radeon_device *rdev) } else if (rdev->family == CHIP_RS300 || rdev->family == CHIP_RS400 || rdev->family == CHIP_RS480) { + u16 offset; + u8 id, blocks, clk, data; + int i; + /* 0x68 */ i2c = combios_setup_i2c_bus(rdev, DDC_CRT2, 0, 0); rdev->i2c_bus[3] = radeon_i2c_create(dev, &i2c, "MONID"); - /* gpiopad */ - i2c = radeon_combios_get_i2c_info_from_table(rdev); - if (i2c.valid) - rdev->i2c_bus[4] = radeon_i2c_create(dev, &i2c, "GPIOPAD_MASK"); + offset = combios_get_table_offset(dev, COMBIOS_I2C_INFO_TABLE); + if (offset) { + blocks = RBIOS8(offset + 2); + for (i = 0; i < blocks; i++) { + id = RBIOS8(offset + 3 + (i * 5) + 0); + if (id == 136) { + clk = RBIOS8(offset + 3 + (i * 5) + 3); + data = RBIOS8(offset + 3 + (i * 5) + 4); + /* gpiopad */ + i2c = combios_setup_i2c_bus(rdev, DDC_MONID, + (1 << clk), (1 << data)); + rdev->i2c_bus[4] = radeon_i2c_create(dev, &i2c, "GPIOPAD_MASK"); + break; + } + } + } } else if ((rdev->family == CHIP_R200) || (rdev->family >= CHIP_R300)) { /* 0x68 */ @@ -2333,10 +2321,7 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev) connector = (tmp >> 12) & 0xf; ddc_type = (tmp >> 8) & 0xf; - if (ddc_type == 5) - ddc_i2c = radeon_combios_get_i2c_info_from_table(rdev); - else - ddc_i2c = combios_setup_i2c_bus(rdev, ddc_type, 0, 0); + ddc_i2c = combios_setup_i2c_bus(rdev, ddc_type, 0, 0); switch (connector) { case CONNECTOR_PROPRIETARY_LEGACY: diff --git a/trunk/drivers/gpu/drm/radeon/radeon_cs.c b/trunk/drivers/gpu/drm/radeon/radeon_cs.c index b4a0db24f4dd..8a4c49ef0cc4 100644 --- a/trunk/drivers/gpu/drm/radeon/radeon_cs.c +++ b/trunk/drivers/gpu/drm/radeon/radeon_cs.c @@ -278,30 +278,6 @@ int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data) return 0; } -static void radeon_bo_vm_fence_va(struct radeon_cs_parser *parser, - struct radeon_fence *fence) -{ - struct radeon_fpriv *fpriv = parser->filp->driver_priv; - struct radeon_vm *vm = &fpriv->vm; - struct radeon_bo_list *lobj; - - if (parser->chunk_ib_idx == -1) { - return; - } - if ((parser->cs_flags & RADEON_CS_USE_VM) == 0) { - return; - } - - list_for_each_entry(lobj, &parser->validated, tv.head) { - struct radeon_bo_va *bo_va; - struct radeon_bo *rbo = lobj->bo; - - bo_va = radeon_bo_va(rbo, vm); - radeon_fence_unref(&bo_va->fence); - bo_va->fence = radeon_fence_ref(fence); - } -} - /** * cs_parser_fini() - clean parser states * @parser: parser structure holding parsing context. @@ -314,14 +290,11 @@ static void radeon_cs_parser_fini(struct radeon_cs_parser *parser, int error) { unsigned i; - if (!error) { - /* fence all bo va before ttm_eu_fence_buffer_objects so bo are still reserved */ - radeon_bo_vm_fence_va(parser, parser->ib.fence); + if (!error) ttm_eu_fence_buffer_objects(&parser->validated, parser->ib.fence); - } else { + else ttm_eu_backoff_reservation(&parser->validated); - } if (parser->relocs != NULL) { for (i = 0; i < parser->nrelocs; i++) { @@ -415,6 +388,7 @@ static int radeon_cs_ib_vm_chunk(struct radeon_device *rdev, if (parser->chunk_ib_idx == -1) return 0; + if ((parser->cs_flags & RADEON_CS_USE_VM) == 0) return 0; diff --git a/trunk/drivers/gpu/drm/radeon/radeon_cursor.c b/trunk/drivers/gpu/drm/radeon/radeon_cursor.c index 8794744cdf1a..711e95ad39bf 100644 --- a/trunk/drivers/gpu/drm/radeon/radeon_cursor.c +++ b/trunk/drivers/gpu/drm/radeon/radeon_cursor.c @@ -67,8 +67,7 @@ static void radeon_hide_cursor(struct drm_crtc *crtc) if (ASIC_IS_DCE4(rdev)) { WREG32(RADEON_MM_INDEX, EVERGREEN_CUR_CONTROL + radeon_crtc->crtc_offset); - WREG32(RADEON_MM_DATA, EVERGREEN_CURSOR_MODE(EVERGREEN_CURSOR_24_8_PRE_MULT) | - EVERGREEN_CURSOR_URGENT_CONTROL(EVERGREEN_CURSOR_URGENT_1_2)); + WREG32(RADEON_MM_DATA, EVERGREEN_CURSOR_MODE(EVERGREEN_CURSOR_24_8_PRE_MULT)); } else if (ASIC_IS_AVIVO(rdev)) { WREG32(RADEON_MM_INDEX, AVIVO_D1CUR_CONTROL + radeon_crtc->crtc_offset); WREG32(RADEON_MM_DATA, (AVIVO_D1CURSOR_MODE_24BPP << AVIVO_D1CURSOR_MODE_SHIFT)); @@ -95,8 +94,7 @@ static void radeon_show_cursor(struct drm_crtc *crtc) if (ASIC_IS_DCE4(rdev)) { WREG32(RADEON_MM_INDEX, EVERGREEN_CUR_CONTROL + radeon_crtc->crtc_offset); WREG32(RADEON_MM_DATA, EVERGREEN_CURSOR_EN | - EVERGREEN_CURSOR_MODE(EVERGREEN_CURSOR_24_8_PRE_MULT) | - EVERGREEN_CURSOR_URGENT_CONTROL(EVERGREEN_CURSOR_URGENT_1_2)); + EVERGREEN_CURSOR_MODE(EVERGREEN_CURSOR_24_8_PRE_MULT)); } else if (ASIC_IS_AVIVO(rdev)) { WREG32(RADEON_MM_INDEX, AVIVO_D1CUR_CONTROL + radeon_crtc->crtc_offset); WREG32(RADEON_MM_DATA, AVIVO_D1CURSOR_EN | diff --git a/trunk/drivers/gpu/drm/radeon/radeon_device.c b/trunk/drivers/gpu/drm/radeon/radeon_device.c index 7a3daebd732d..742af8244e89 100644 --- a/trunk/drivers/gpu/drm/radeon/radeon_device.c +++ b/trunk/drivers/gpu/drm/radeon/radeon_device.c @@ -1009,7 +1009,6 @@ int radeon_device_init(struct radeon_device *rdev, atomic_set(&rdev->ih.lock, 0); mutex_init(&rdev->gem.mutex); mutex_init(&rdev->pm.mutex); - mutex_init(&rdev->gpu_clock_mutex); init_rwsem(&rdev->pm.mclk_lock); init_rwsem(&rdev->exclusive_lock); init_waitqueue_head(&rdev->irq.vblank_queue); @@ -1051,7 +1050,7 @@ int radeon_device_init(struct radeon_device *rdev, if (rdev->flags & RADEON_IS_AGP) rdev->need_dma32 = true; if ((rdev->flags & RADEON_IS_PCI) && - (rdev->family <= CHIP_RS740)) + (rdev->family < CHIP_RS400)) rdev->need_dma32 = true; dma_bits = rdev->need_dma32 ? 32 : 40; @@ -1346,15 +1345,12 @@ int radeon_gpu_reset(struct radeon_device *rdev) for (i = 0; i < RADEON_NUM_RINGS; ++i) { radeon_ring_restore(rdev, &rdev->ring[i], ring_sizes[i], ring_data[i]); - ring_sizes[i] = 0; - ring_data[i] = NULL; } r = radeon_ib_ring_tests(rdev); if (r) { dev_err(rdev->dev, "ib ring test failed (%d).\n", r); if (saved) { - saved = false; radeon_suspend(rdev); goto retry; } diff --git a/trunk/drivers/gpu/drm/radeon/radeon_drv.c b/trunk/drivers/gpu/drm/radeon/radeon_drv.c index 8c593ea82c41..dcea6f01ae4e 100644 --- a/trunk/drivers/gpu/drm/radeon/radeon_drv.c +++ b/trunk/drivers/gpu/drm/radeon/radeon_drv.c @@ -59,14 +59,9 @@ * 2.15.0 - add max_pipes query * 2.16.0 - fix evergreen 2D tiled surface calculation * 2.17.0 - add STRMOUT_BASE_UPDATE for r7xx - * 2.18.0 - r600-eg: allow "invalid" DB formats - * 2.19.0 - r600-eg: MSAA textures - * 2.20.0 - r600-si: RADEON_INFO_TIMESTAMP query - * 2.21.0 - r600-r700: FMASK and CMASK - * 2.22.0 - r600 only: RESOLVE_BOX allowed */ #define KMS_DRIVER_MAJOR 2 -#define KMS_DRIVER_MINOR 22 +#define KMS_DRIVER_MINOR 17 #define KMS_DRIVER_PATCHLEVEL 0 int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags); int radeon_driver_unload_kms(struct drm_device *dev); diff --git a/trunk/drivers/gpu/drm/radeon/radeon_fence.c b/trunk/drivers/gpu/drm/radeon/radeon_fence.c index 2a59375dbe52..7b737b9339ad 100644 --- a/trunk/drivers/gpu/drm/radeon/radeon_fence.c +++ b/trunk/drivers/gpu/drm/radeon/radeon_fence.c @@ -131,7 +131,7 @@ int radeon_fence_emit(struct radeon_device *rdev, */ void radeon_fence_process(struct radeon_device *rdev, int ring) { - uint64_t seq, last_seq, last_emitted; + uint64_t seq, last_seq; unsigned count_loop = 0; bool wake = false; @@ -158,15 +158,13 @@ void radeon_fence_process(struct radeon_device *rdev, int ring) */ last_seq = atomic64_read(&rdev->fence_drv[ring].last_seq); do { - last_emitted = rdev->fence_drv[ring].sync_seq[ring]; seq = radeon_fence_read(rdev, ring); seq |= last_seq & 0xffffffff00000000LL; if (seq < last_seq) { - seq &= 0xffffffff; - seq |= last_emitted & 0xffffffff00000000LL; + seq += 0x100000000LL; } - if (seq <= last_seq || seq > last_emitted) { + if (seq == last_seq) { break; } /* If we loop over we don't want to return without diff --git a/trunk/drivers/gpu/drm/radeon/radeon_gart.c b/trunk/drivers/gpu/drm/radeon/radeon_gart.c index bb3b7fe05ccd..b3720054614d 100644 --- a/trunk/drivers/gpu/drm/radeon/radeon_gart.c +++ b/trunk/drivers/gpu/drm/radeon/radeon_gart.c @@ -814,7 +814,7 @@ int radeon_vm_bo_update_pte(struct radeon_device *rdev, return -EINVAL; } - if (bo_va->valid && mem) + if (bo_va->valid) return 0; ngpu_pages = radeon_bo_ngpu_pages(bo); @@ -859,27 +859,11 @@ int radeon_vm_bo_rmv(struct radeon_device *rdev, struct radeon_bo *bo) { struct radeon_bo_va *bo_va; - int r; bo_va = radeon_bo_va(bo, vm); if (bo_va == NULL) return 0; - /* wait for va use to end */ - while (bo_va->fence) { - r = radeon_fence_wait(bo_va->fence, false); - if (r) { - DRM_ERROR("error while waiting for fence: %d\n", r); - } - if (r == -EDEADLK) { - r = radeon_gpu_reset(rdev); - if (!r) - continue; - } - break; - } - radeon_fence_unref(&bo_va->fence); - mutex_lock(&rdev->vm_manager.lock); mutex_lock(&vm->mutex); radeon_vm_bo_update_pte(rdev, vm, bo, NULL); @@ -950,7 +934,7 @@ int radeon_vm_init(struct radeon_device *rdev, struct radeon_vm *vm) } /** - * radeon_vm_fini - tear down a vm instance + * radeon_vm_init - tear down a vm instance * * @rdev: radeon_device pointer * @vm: requested vm @@ -968,15 +952,12 @@ void radeon_vm_fini(struct radeon_device *rdev, struct radeon_vm *vm) radeon_vm_unbind_locked(rdev, vm); mutex_unlock(&rdev->vm_manager.lock); - /* remove all bo at this point non are busy any more because unbind - * waited for the last vm fence to signal - */ + /* remove all bo */ r = radeon_bo_reserve(rdev->ring_tmp_bo.bo, false); if (!r) { bo_va = radeon_bo_va(rdev->ring_tmp_bo.bo, vm); list_del_init(&bo_va->bo_list); list_del_init(&bo_va->vm_list); - radeon_fence_unref(&bo_va->fence); radeon_bo_unreserve(rdev->ring_tmp_bo.bo); kfree(bo_va); } @@ -988,7 +969,6 @@ void radeon_vm_fini(struct radeon_device *rdev, struct radeon_vm *vm) r = radeon_bo_reserve(bo_va->bo, false); if (!r) { list_del_init(&bo_va->bo_list); - radeon_fence_unref(&bo_va->fence); radeon_bo_unreserve(bo_va->bo); kfree(bo_va); } diff --git a/trunk/drivers/gpu/drm/radeon/radeon_gem.c b/trunk/drivers/gpu/drm/radeon/radeon_gem.c index 1b57b0058ad6..84d045245739 100644 --- a/trunk/drivers/gpu/drm/radeon/radeon_gem.c +++ b/trunk/drivers/gpu/drm/radeon/radeon_gem.c @@ -134,16 +134,25 @@ void radeon_gem_object_close(struct drm_gem_object *obj, struct radeon_device *rdev = rbo->rdev; struct radeon_fpriv *fpriv = file_priv->driver_priv; struct radeon_vm *vm = &fpriv->vm; + struct radeon_bo_va *bo_va, *tmp; if (rdev->family < CHIP_CAYMAN) { return; } if (radeon_bo_reserve(rbo, false)) { - dev_err(rdev->dev, "leaking bo va because we fail to reserve bo\n"); return; } - radeon_vm_bo_rmv(rdev, vm, rbo); + list_for_each_entry_safe(bo_va, tmp, &rbo->va, bo_list) { + if (bo_va->vm == vm) { + /* remove from this vm address space */ + mutex_lock(&vm->mutex); + list_del(&bo_va->vm_list); + mutex_unlock(&vm->mutex); + list_del(&bo_va->bo_list); + kfree(bo_va); + } + } radeon_bo_unreserve(rbo); } diff --git a/trunk/drivers/gpu/drm/radeon/radeon_kms.c b/trunk/drivers/gpu/drm/radeon/radeon_kms.c index 414b4acf6947..1d73f16b5d97 100644 --- a/trunk/drivers/gpu/drm/radeon/radeon_kms.c +++ b/trunk/drivers/gpu/drm/radeon/radeon_kms.c @@ -29,7 +29,6 @@ #include "drm_sarea.h" #include "radeon.h" #include "radeon_drm.h" -#include "radeon_asic.h" #include #include @@ -168,39 +167,17 @@ static void radeon_set_filp_rights(struct drm_device *dev, int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) { struct radeon_device *rdev = dev->dev_private; - struct drm_radeon_info *info = data; + struct drm_radeon_info *info; struct radeon_mode_info *minfo = &rdev->mode_info; - uint32_t value, *value_ptr; - uint64_t value64, *value_ptr64; + uint32_t *value_ptr; + uint32_t value; struct drm_crtc *crtc; int i, found; - /* TIMESTAMP is a 64-bit value, needs special handling. */ - if (info->request == RADEON_INFO_TIMESTAMP) { - if (rdev->family >= CHIP_R600) { - value_ptr64 = (uint64_t*)((unsigned long)info->value); - if (rdev->family >= CHIP_TAHITI) { - value64 = si_get_gpu_clock(rdev); - } else { - value64 = r600_get_gpu_clock(rdev); - } - - if (DRM_COPY_TO_USER(value_ptr64, &value64, sizeof(value64))) { - DRM_ERROR("copy_to_user %s:%u\n", __func__, __LINE__); - return -EFAULT; - } - return 0; - } else { - DRM_DEBUG_KMS("timestamp is r6xx+ only!\n"); - return -EINVAL; - } - } - + info = data; value_ptr = (uint32_t *)((unsigned long)info->value); - if (DRM_COPY_FROM_USER(&value, value_ptr, sizeof(value))) { - DRM_ERROR("copy_from_user %s:%u\n", __func__, __LINE__); + if (DRM_COPY_FROM_USER(&value, value_ptr, sizeof(value))) return -EFAULT; - } switch (info->request) { case RADEON_INFO_DEVICE_ID: @@ -360,7 +337,7 @@ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) return -EINVAL; } if (DRM_COPY_TO_USER(value_ptr, &value, sizeof(uint32_t))) { - DRM_ERROR("copy_to_user %s:%u\n", __func__, __LINE__); + DRM_ERROR("copy_to_user\n"); return -EFAULT; } return 0; diff --git a/trunk/drivers/gpu/drm/radeon/radeon_legacy_crtc.c b/trunk/drivers/gpu/drm/radeon/radeon_legacy_crtc.c index 94b4a1c12893..d5fd615897ec 100644 --- a/trunk/drivers/gpu/drm/radeon/radeon_legacy_crtc.c +++ b/trunk/drivers/gpu/drm/radeon/radeon_legacy_crtc.c @@ -1025,11 +1025,9 @@ static int radeon_crtc_mode_set(struct drm_crtc *crtc, static void radeon_crtc_prepare(struct drm_crtc *crtc) { - struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); struct drm_device *dev = crtc->dev; struct drm_crtc *crtci; - radeon_crtc->in_mode_set = true; /* * The hardware wedges sometimes if you reconfigure one CRTC * whilst another is running (see fdo bug #24611). @@ -1040,7 +1038,6 @@ static void radeon_crtc_prepare(struct drm_crtc *crtc) static void radeon_crtc_commit(struct drm_crtc *crtc) { - struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); struct drm_device *dev = crtc->dev; struct drm_crtc *crtci; @@ -1051,7 +1048,6 @@ static void radeon_crtc_commit(struct drm_crtc *crtc) if (crtci->enabled) radeon_crtc_dpms(crtci, DRM_MODE_DPMS_ON); } - radeon_crtc->in_mode_set = false; } static const struct drm_crtc_helper_funcs legacy_helper_funcs = { diff --git a/trunk/drivers/gpu/drm/radeon/radeon_mode.h b/trunk/drivers/gpu/drm/radeon/radeon_mode.h index d56978949f34..f380d59c5763 100644 --- a/trunk/drivers/gpu/drm/radeon/radeon_mode.h +++ b/trunk/drivers/gpu/drm/radeon/radeon_mode.h @@ -275,7 +275,6 @@ struct radeon_crtc { u16 lut_r[256], lut_g[256], lut_b[256]; bool enabled; bool can_tile; - bool in_mode_set; uint32_t crtc_offset; struct drm_gem_object *cursor_bo; uint64_t cursor_addr; diff --git a/trunk/drivers/gpu/drm/radeon/radeon_object.c b/trunk/drivers/gpu/drm/radeon/radeon_object.c index 9024e7222839..1f1a4c803c1d 100644 --- a/trunk/drivers/gpu/drm/radeon/radeon_object.c +++ b/trunk/drivers/gpu/drm/radeon/radeon_object.c @@ -52,7 +52,11 @@ void radeon_bo_clear_va(struct radeon_bo *bo) list_for_each_entry_safe(bo_va, tmp, &bo->va, bo_list) { /* remove from all vm address space */ - radeon_vm_bo_rmv(bo->rdev, bo_va->vm, bo); + mutex_lock(&bo_va->vm->mutex); + list_del(&bo_va->vm_list); + mutex_unlock(&bo_va->vm->mutex); + list_del(&bo_va->bo_list); + kfree(bo_va); } } @@ -132,7 +136,6 @@ int radeon_bo_create(struct radeon_device *rdev, acc_size = ttm_bo_dma_acc_size(&rdev->mman.bdev, size, sizeof(struct radeon_bo)); -retry: bo = kzalloc(sizeof(struct radeon_bo), GFP_KERNEL); if (bo == NULL) return -ENOMEM; @@ -146,6 +149,8 @@ int radeon_bo_create(struct radeon_device *rdev, bo->surface_reg = -1; INIT_LIST_HEAD(&bo->list); INIT_LIST_HEAD(&bo->va); + +retry: radeon_ttm_placement_from_domain(bo, domain); /* Kernel allocation are uninterruptible */ down_read(&rdev->pm.mclk_lock); diff --git a/trunk/drivers/gpu/drm/radeon/radeon_ring.c b/trunk/drivers/gpu/drm/radeon/radeon_ring.c index 43c431a2686d..ec79b3750430 100644 --- a/trunk/drivers/gpu/drm/radeon/radeon_ring.c +++ b/trunk/drivers/gpu/drm/radeon/radeon_ring.c @@ -706,7 +706,6 @@ int radeon_ring_init(struct radeon_device *rdev, struct radeon_ring *ring, unsig if (radeon_debugfs_ring_init(rdev, ring)) { DRM_ERROR("Failed to register debugfs file for rings !\n"); } - radeon_ring_lockup_update(ring); return 0; } diff --git a/trunk/drivers/gpu/drm/radeon/reg_srcs/r600 b/trunk/drivers/gpu/drm/radeon/reg_srcs/r600 index 20bfbda7b3f1..5e659b034d9a 100644 --- a/trunk/drivers/gpu/drm/radeon/reg_srcs/r600 +++ b/trunk/drivers/gpu/drm/radeon/reg_srcs/r600 @@ -744,6 +744,15 @@ r600 0x9400 0x00028C38 CB_CLRCMP_DST 0x00028C3C CB_CLRCMP_MSK 0x00028C34 CB_CLRCMP_SRC +0x00028100 CB_COLOR0_MASK +0x00028104 CB_COLOR1_MASK +0x00028108 CB_COLOR2_MASK +0x0002810C CB_COLOR3_MASK +0x00028110 CB_COLOR4_MASK +0x00028114 CB_COLOR5_MASK +0x00028118 CB_COLOR6_MASK +0x0002811C CB_COLOR7_MASK +0x00028808 CB_COLOR_CONTROL 0x0002842C CB_FOG_BLUE 0x00028428 CB_FOG_GREEN 0x00028424 CB_FOG_RED diff --git a/trunk/drivers/gpu/drm/radeon/rv515.c b/trunk/drivers/gpu/drm/radeon/rv515.c index aa8ef491ef3c..a12fbcc8ccb6 100644 --- a/trunk/drivers/gpu/drm/radeon/rv515.c +++ b/trunk/drivers/gpu/drm/radeon/rv515.c @@ -281,8 +281,12 @@ int rv515_debugfs_ga_info_init(struct radeon_device *rdev) void rv515_mc_stop(struct radeon_device *rdev, struct rv515_mc_save *save) { + save->d1vga_control = RREG32(R_000330_D1VGA_CONTROL); + save->d2vga_control = RREG32(R_000338_D2VGA_CONTROL); save->vga_render_control = RREG32(R_000300_VGA_RENDER_CONTROL); save->vga_hdp_control = RREG32(R_000328_VGA_HDP_CONTROL); + save->d1crtc_control = RREG32(R_006080_D1CRTC_CONTROL); + save->d2crtc_control = RREG32(R_006880_D2CRTC_CONTROL); /* Stop all video */ WREG32(R_0068E8_D2CRTC_UPDATE_LOCK, 0); @@ -307,6 +311,15 @@ void rv515_mc_resume(struct radeon_device *rdev, struct rv515_mc_save *save) /* Unlock host access */ WREG32(R_000328_VGA_HDP_CONTROL, save->vga_hdp_control); mdelay(1); + /* Restore video state */ + WREG32(R_000330_D1VGA_CONTROL, save->d1vga_control); + WREG32(R_000338_D2VGA_CONTROL, save->d2vga_control); + WREG32(R_0060E8_D1CRTC_UPDATE_LOCK, 1); + WREG32(R_0068E8_D2CRTC_UPDATE_LOCK, 1); + WREG32(R_006080_D1CRTC_CONTROL, save->d1crtc_control); + WREG32(R_006880_D2CRTC_CONTROL, save->d2crtc_control); + WREG32(R_0060E8_D1CRTC_UPDATE_LOCK, 0); + WREG32(R_0068E8_D2CRTC_UPDATE_LOCK, 0); WREG32(R_000300_VGA_RENDER_CONTROL, save->vga_render_control); } diff --git a/trunk/drivers/gpu/drm/radeon/si.c b/trunk/drivers/gpu/drm/radeon/si.c index 0139e227e3c7..c053f8193771 100644 --- a/trunk/drivers/gpu/drm/radeon/si.c +++ b/trunk/drivers/gpu/drm/radeon/si.c @@ -1639,19 +1639,11 @@ static void si_gpu_init(struct radeon_device *rdev) /* XXX what about 12? */ rdev->config.si.tile_config |= (3 << 0); break; - } - switch ((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT) { - case 0: /* four banks */ - rdev->config.si.tile_config |= 0 << 4; - break; - case 1: /* eight banks */ - rdev->config.si.tile_config |= 1 << 4; - break; - case 2: /* sixteen banks */ - default: - rdev->config.si.tile_config |= 2 << 4; - break; } + if ((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT) + rdev->config.si.tile_config |= 1 << 4; + else + rdev->config.si.tile_config |= 0 << 4; rdev->config.si.tile_config |= ((gb_addr_config & PIPE_INTERLEAVE_SIZE_MASK) >> PIPE_INTERLEAVE_SIZE_SHIFT) << 8; rdev->config.si.tile_config |= @@ -3968,22 +3960,3 @@ void si_fini(struct radeon_device *rdev) rdev->bios = NULL; } -/** - * si_get_gpu_clock - return GPU clock counter snapshot - * - * @rdev: radeon_device pointer - * - * Fetches a GPU clock counter snapshot (SI). - * Returns the 64 bit clock counter snapshot. - */ -uint64_t si_get_gpu_clock(struct radeon_device *rdev) -{ - uint64_t clock; - - mutex_lock(&rdev->gpu_clock_mutex); - WREG32(RLC_CAPTURE_GPU_CLOCK_COUNT, 1); - clock = (uint64_t)RREG32(RLC_GPU_CLOCK_COUNT_LSB) | - ((uint64_t)RREG32(RLC_GPU_CLOCK_COUNT_MSB) << 32ULL); - mutex_unlock(&rdev->gpu_clock_mutex); - return clock; -} diff --git a/trunk/drivers/gpu/drm/radeon/sid.h b/trunk/drivers/gpu/drm/radeon/sid.h index ef4815c27b1c..7869089e8761 100644 --- a/trunk/drivers/gpu/drm/radeon/sid.h +++ b/trunk/drivers/gpu/drm/radeon/sid.h @@ -698,9 +698,6 @@ #define RLC_UCODE_ADDR 0xC32C #define RLC_UCODE_DATA 0xC330 -#define RLC_GPU_CLOCK_COUNT_LSB 0xC338 -#define RLC_GPU_CLOCK_COUNT_MSB 0xC33C -#define RLC_CAPTURE_GPU_CLOCK_COUNT 0xC340 #define RLC_MC_CNTL 0xC344 #define RLC_UCODE_CNTL 0xC348 diff --git a/trunk/drivers/gpu/drm/savage/savage_drv.c b/trunk/drivers/gpu/drm/savage/savage_drv.c index c5a164337bd5..d31d4cca9a4c 100644 --- a/trunk/drivers/gpu/drm/savage/savage_drv.c +++ b/trunk/drivers/gpu/drm/savage/savage_drv.c @@ -43,9 +43,6 @@ static const struct file_operations savage_driver_fops = { .mmap = drm_mmap, .poll = drm_poll, .fasync = drm_fasync, -#ifdef CONFIG_COMPAT - .compat_ioctl = drm_compat_ioctl, -#endif .llseek = noop_llseek, }; diff --git a/trunk/drivers/gpu/drm/sis/sis_drv.c b/trunk/drivers/gpu/drm/sis/sis_drv.c index 867dc03000e6..7f119870147c 100644 --- a/trunk/drivers/gpu/drm/sis/sis_drv.c +++ b/trunk/drivers/gpu/drm/sis/sis_drv.c @@ -74,9 +74,6 @@ static const struct file_operations sis_driver_fops = { .mmap = drm_mmap, .poll = drm_poll, .fasync = drm_fasync, -#ifdef CONFIG_COMPAT - .compat_ioctl = drm_compat_ioctl, -#endif .llseek = noop_llseek, }; diff --git a/trunk/drivers/gpu/drm/tdfx/tdfx_drv.c b/trunk/drivers/gpu/drm/tdfx/tdfx_drv.c index a7f4d6bd1330..90f6b13acfac 100644 --- a/trunk/drivers/gpu/drm/tdfx/tdfx_drv.c +++ b/trunk/drivers/gpu/drm/tdfx/tdfx_drv.c @@ -49,9 +49,6 @@ static const struct file_operations tdfx_driver_fops = { .mmap = drm_mmap, .poll = drm_poll, .fasync = drm_fasync, -#ifdef CONFIG_COMPAT - .compat_ioctl = drm_compat_ioctl, -#endif .llseek = noop_llseek, }; diff --git a/trunk/drivers/gpu/drm/udl/Kconfig b/trunk/drivers/gpu/drm/udl/Kconfig index 56e0bf31d425..0b5e096d39a6 100644 --- a/trunk/drivers/gpu/drm/udl/Kconfig +++ b/trunk/drivers/gpu/drm/udl/Kconfig @@ -1,7 +1,6 @@ config DRM_UDL tristate "DisplayLink" depends on DRM && EXPERIMENTAL - depends on USB_ARCH_HAS_HCD select DRM_USB select FB_SYS_FILLRECT select FB_SYS_COPYAREA diff --git a/trunk/drivers/gpu/drm/udl/udl_connector.c b/trunk/drivers/gpu/drm/udl/udl_connector.c index 8d9dc44f1f94..ba055e9ca007 100644 --- a/trunk/drivers/gpu/drm/udl/udl_connector.c +++ b/trunk/drivers/gpu/drm/udl/udl_connector.c @@ -69,13 +69,6 @@ static int udl_get_modes(struct drm_connector *connector) static int udl_mode_valid(struct drm_connector *connector, struct drm_display_mode *mode) { - struct udl_device *udl = connector->dev->dev_private; - if (!udl->sku_pixel_limit) - return 0; - - if (mode->vdisplay * mode->hdisplay > udl->sku_pixel_limit) - return MODE_VIRTUAL_Y; - return 0; } diff --git a/trunk/drivers/gpu/drm/udl/udl_drv.c b/trunk/drivers/gpu/drm/udl/udl_drv.c index 9f84128505bb..6e52069894b3 100644 --- a/trunk/drivers/gpu/drm/udl/udl_drv.c +++ b/trunk/drivers/gpu/drm/udl/udl_drv.c @@ -66,9 +66,6 @@ static const struct file_operations udl_driver_fops = { .unlocked_ioctl = drm_ioctl, .release = drm_release, .fasync = drm_fasync, -#ifdef CONFIG_COMPAT - .compat_ioctl = drm_compat_ioctl, -#endif .llseek = noop_llseek, }; diff --git a/trunk/drivers/gpu/drm/udl/udl_gem.c b/trunk/drivers/gpu/drm/udl/udl_gem.c index 291ecc145585..7bd65bdd15a8 100644 --- a/trunk/drivers/gpu/drm/udl/udl_gem.c +++ b/trunk/drivers/gpu/drm/udl/udl_gem.c @@ -308,7 +308,7 @@ struct drm_gem_object *udl_gem_prime_import(struct drm_device *dev, /* need to attach */ attach = dma_buf_attach(dma_buf, dev->dev); if (IS_ERR(attach)) - return ERR_CAST(attach); + return ERR_PTR(PTR_ERR(attach)); sg = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL); if (IS_ERR(sg)) { diff --git a/trunk/drivers/gpu/drm/udl/udl_modeset.c b/trunk/drivers/gpu/drm/udl/udl_modeset.c index 9159d48d1dfd..f5dd89e891de 100644 --- a/trunk/drivers/gpu/drm/udl/udl_modeset.c +++ b/trunk/drivers/gpu/drm/udl/udl_modeset.c @@ -354,7 +354,8 @@ static int udl_crtc_mode_set(struct drm_crtc *crtc, static void udl_crtc_disable(struct drm_crtc *crtc) { - udl_crtc_dpms(crtc, DRM_MODE_DPMS_OFF); + + } static void udl_crtc_destroy(struct drm_crtc *crtc) diff --git a/trunk/drivers/gpu/drm/via/via_drv.c b/trunk/drivers/gpu/drm/via/via_drv.c index af1b914b17e3..e927b4c052f5 100644 --- a/trunk/drivers/gpu/drm/via/via_drv.c +++ b/trunk/drivers/gpu/drm/via/via_drv.c @@ -65,9 +65,6 @@ static const struct file_operations via_driver_fops = { .mmap = drm_mmap, .poll = drm_poll, .fasync = drm_fasync, -#ifdef CONFIG_COMPAT - .compat_ioctl = drm_compat_ioctl, -#endif .llseek = noop_llseek, }; diff --git a/trunk/drivers/gpu/drm/vmwgfx/Kconfig b/trunk/drivers/gpu/drm/vmwgfx/Kconfig index b71bcd0bfbbf..794ff67c5701 100644 --- a/trunk/drivers/gpu/drm/vmwgfx/Kconfig +++ b/trunk/drivers/gpu/drm/vmwgfx/Kconfig @@ -12,11 +12,3 @@ config DRM_VMWGFX This is a KMS enabled DRM driver for the VMware SVGA2 virtual hardware. The compiled module will be called "vmwgfx.ko". - -config DRM_VMWGFX_FBCON - depends on DRM_VMWGFX - bool "Enable framebuffer console under vmwgfx by default" - help - Choose this option if you are shipping a new vmwgfx - userspace driver that supports using the kernel driver. - diff --git a/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c index ba2c35dbf10e..4d9edead01ac 100644 --- a/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +++ b/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c @@ -182,9 +182,8 @@ static struct pci_device_id vmw_pci_id_list[] = { {0x15ad, 0x0405, PCI_ANY_ID, PCI_ANY_ID, 0, 0, VMWGFX_CHIP_SVGAII}, {0, 0, 0} }; -MODULE_DEVICE_TABLE(pci, vmw_pci_id_list); -static int enable_fbdev = IS_ENABLED(CONFIG_DRM_VMWGFX_FBCON); +static int enable_fbdev; static int vmw_probe(struct pci_dev *, const struct pci_device_id *); static void vmw_master_init(struct vmw_master *); @@ -1155,11 +1154,6 @@ static struct drm_driver driver = { .open = vmw_driver_open, .preclose = vmw_preclose, .postclose = vmw_postclose, - - .dumb_create = vmw_dumb_create, - .dumb_map_offset = vmw_dumb_map_offset, - .dumb_destroy = vmw_dumb_destroy, - .fops = &vmwgfx_driver_fops, .name = VMWGFX_DRIVER_NAME, .desc = VMWGFX_DRIVER_DESC, diff --git a/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h index 29c984ff7f23..d0f2c079ee27 100644 --- a/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h +++ b/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h @@ -645,16 +645,6 @@ int vmw_kms_readback(struct vmw_private *dev_priv, int vmw_kms_update_layout_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); -int vmw_dumb_create(struct drm_file *file_priv, - struct drm_device *dev, - struct drm_mode_create_dumb *args); - -int vmw_dumb_map_offset(struct drm_file *file_priv, - struct drm_device *dev, uint32_t handle, - uint64_t *offset); -int vmw_dumb_destroy(struct drm_file *file_priv, - struct drm_device *dev, - uint32_t handle); /** * Overlay control - vmwgfx_overlay.c */ diff --git a/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c b/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c index 7e0743358dff..f2fb8f15e2f1 100644 --- a/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c +++ b/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c @@ -1018,7 +1018,7 @@ int vmw_event_fence_action_create(struct drm_file *file_priv, } - event = kzalloc(sizeof(*event), GFP_KERNEL); + event = kzalloc(sizeof(event->event), GFP_KERNEL); if (unlikely(event == NULL)) { DRM_ERROR("Failed to allocate an event.\n"); ret = -ENOMEM; diff --git a/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c index c50724bd30f6..6b0078ffa763 100644 --- a/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +++ b/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c @@ -1688,19 +1688,15 @@ int vmw_du_page_flip(struct drm_crtc *crtc, struct vmw_private *dev_priv = vmw_priv(crtc->dev); struct drm_framebuffer *old_fb = crtc->fb; struct vmw_framebuffer *vfb = vmw_framebuffer_to_vfb(fb); - struct drm_file *file_priv ; + struct drm_file *file_priv = event->base.file_priv; struct vmw_fence_obj *fence = NULL; struct drm_clip_rect clips; int ret; - if (event == NULL) - return -EINVAL; - /* require ScreenObject support for page flipping */ if (!dev_priv->sou_priv) return -ENOSYS; - file_priv = event->base.file_priv; if (!vmw_kms_screen_object_flippable(dev_priv, crtc)) return -EINVAL; diff --git a/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c b/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c index 2c6ffe0e2c07..22bf9a21ec71 100644 --- a/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c +++ b/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c @@ -1917,76 +1917,3 @@ int vmw_user_stream_lookup(struct vmw_private *dev_priv, vmw_resource_unreference(&res); return ret; } - - -int vmw_dumb_create(struct drm_file *file_priv, - struct drm_device *dev, - struct drm_mode_create_dumb *args) -{ - struct vmw_private *dev_priv = vmw_priv(dev); - struct vmw_master *vmaster = vmw_master(file_priv->master); - struct vmw_user_dma_buffer *vmw_user_bo; - struct ttm_buffer_object *tmp; - int ret; - - args->pitch = args->width * ((args->bpp + 7) / 8); - args->size = args->pitch * args->height; - - vmw_user_bo = kzalloc(sizeof(*vmw_user_bo), GFP_KERNEL); - if (vmw_user_bo == NULL) - return -ENOMEM; - - ret = ttm_read_lock(&vmaster->lock, true); - if (ret != 0) { - kfree(vmw_user_bo); - return ret; - } - - ret = vmw_dmabuf_init(dev_priv, &vmw_user_bo->dma, args->size, - &vmw_vram_sys_placement, true, - &vmw_user_dmabuf_destroy); - if (ret != 0) - goto out_no_dmabuf; - - tmp = ttm_bo_reference(&vmw_user_bo->dma.base); - ret = ttm_base_object_init(vmw_fpriv(file_priv)->tfile, - &vmw_user_bo->base, - false, - ttm_buffer_type, - &vmw_user_dmabuf_release, NULL); - if (unlikely(ret != 0)) - goto out_no_base_object; - - args->handle = vmw_user_bo->base.hash.key; - -out_no_base_object: - ttm_bo_unref(&tmp); -out_no_dmabuf: - ttm_read_unlock(&vmaster->lock); - return ret; -} - -int vmw_dumb_map_offset(struct drm_file *file_priv, - struct drm_device *dev, uint32_t handle, - uint64_t *offset) -{ - struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile; - struct vmw_dma_buffer *out_buf; - int ret; - - ret = vmw_user_dmabuf_lookup(tfile, handle, &out_buf); - if (ret != 0) - return -EINVAL; - - *offset = out_buf->base.addr_space_offset; - vmw_dmabuf_unreference(&out_buf); - return 0; -} - -int vmw_dumb_destroy(struct drm_file *file_priv, - struct drm_device *dev, - uint32_t handle) -{ - return ttm_ref_object_base_unref(vmw_fpriv(file_priv)->tfile, - handle, TTM_REF_USAGE); -} diff --git a/trunk/drivers/gpu/vga/vga_switcheroo.c b/trunk/drivers/gpu/vga/vga_switcheroo.c index e25cf31faab2..5b3c7d135dc9 100644 --- a/trunk/drivers/gpu/vga/vga_switcheroo.c +++ b/trunk/drivers/gpu/vga/vga_switcheroo.c @@ -70,12 +70,27 @@ static struct vgasr_priv vgasr_priv = { .clients = LIST_HEAD_INIT(vgasr_priv.clients), }; -static bool vga_switcheroo_ready(void) +int vga_switcheroo_register_handler(struct vga_switcheroo_handler *handler) +{ + mutex_lock(&vgasr_mutex); + if (vgasr_priv.handler) { + mutex_unlock(&vgasr_mutex); + return -EINVAL; + } + + vgasr_priv.handler = handler; + mutex_unlock(&vgasr_mutex); + return 0; +} +EXPORT_SYMBOL(vga_switcheroo_register_handler); + +void vga_switcheroo_unregister_handler(void) { - /* we're ready if we get two clients + handler */ - return !vgasr_priv.active && - vgasr_priv.registered_clients == 2 && vgasr_priv.handler; + mutex_lock(&vgasr_mutex); + vgasr_priv.handler = NULL; + mutex_unlock(&vgasr_mutex); } +EXPORT_SYMBOL(vga_switcheroo_unregister_handler); static void vga_switcheroo_enable(void) { @@ -83,8 +98,7 @@ static void vga_switcheroo_enable(void) struct vga_switcheroo_client *client; /* call the handler to init */ - if (vgasr_priv.handler->init) - vgasr_priv.handler->init(); + vgasr_priv.handler->init(); list_for_each_entry(client, &vgasr_priv.clients, list) { if (client->id != -1) @@ -99,37 +113,6 @@ static void vga_switcheroo_enable(void) vgasr_priv.active = true; } -int vga_switcheroo_register_handler(struct vga_switcheroo_handler *handler) -{ - mutex_lock(&vgasr_mutex); - if (vgasr_priv.handler) { - mutex_unlock(&vgasr_mutex); - return -EINVAL; - } - - vgasr_priv.handler = handler; - if (vga_switcheroo_ready()) { - printk(KERN_INFO "vga_switcheroo: enabled\n"); - vga_switcheroo_enable(); - } - mutex_unlock(&vgasr_mutex); - return 0; -} -EXPORT_SYMBOL(vga_switcheroo_register_handler); - -void vga_switcheroo_unregister_handler(void) -{ - mutex_lock(&vgasr_mutex); - vgasr_priv.handler = NULL; - if (vgasr_priv.active) { - pr_info("vga_switcheroo: disabled\n"); - vga_switcheroo_debugfs_fini(&vgasr_priv); - vgasr_priv.active = false; - } - mutex_unlock(&vgasr_mutex); -} -EXPORT_SYMBOL(vga_switcheroo_unregister_handler); - static int register_client(struct pci_dev *pdev, const struct vga_switcheroo_client_ops *ops, int id, bool active) @@ -151,7 +134,9 @@ static int register_client(struct pci_dev *pdev, if (client_is_vga(client)) vgasr_priv.registered_clients++; - if (vga_switcheroo_ready()) { + /* if we get two clients + handler */ + if (!vgasr_priv.active && + vgasr_priv.registered_clients == 2 && vgasr_priv.handler) { printk(KERN_INFO "vga_switcheroo: enabled\n"); vga_switcheroo_enable(); } diff --git a/trunk/drivers/gpu/vga/vgaarb.c b/trunk/drivers/gpu/vga/vgaarb.c index e893f6e1937d..3df8fc0ec01a 100644 --- a/trunk/drivers/gpu/vga/vgaarb.c +++ b/trunk/drivers/gpu/vga/vgaarb.c @@ -141,11 +141,7 @@ EXPORT_SYMBOL_GPL(vga_default_device); void vga_set_default_device(struct pci_dev *pdev) { - if (vga_default == pdev) - return; - - pci_dev_put(vga_default); - vga_default = pci_dev_get(pdev); + vga_default = pdev; } #endif @@ -581,7 +577,7 @@ static bool vga_arbiter_add_pci_device(struct pci_dev *pdev) #ifndef __ARCH_HAS_VGA_DEFAULT_DEVICE if (vga_default == NULL && ((vgadev->owns & VGA_RSRC_LEGACY_MASK) == VGA_RSRC_LEGACY_MASK)) - vga_set_default_device(pdev); + vga_default = pci_dev_get(pdev); #endif vga_arbiter_check_bridge_sharing(vgadev); @@ -617,8 +613,10 @@ static bool vga_arbiter_del_pci_device(struct pci_dev *pdev) } #ifndef __ARCH_HAS_VGA_DEFAULT_DEVICE - if (vga_default == pdev) - vga_set_default_device(NULL); + if (vga_default == pdev) { + pci_dev_put(vga_default); + vga_default = NULL; + } #endif if (vgadev->decodes & (VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM)) @@ -1068,6 +1066,7 @@ static ssize_t vga_arb_write(struct file *file, const char __user * buf, } } else if (strncmp(curr_pos, "target ", 7) == 0) { + struct pci_bus *pbus; unsigned int domain, bus, devfn; struct vga_device *vgadev; @@ -1086,11 +1085,19 @@ static ssize_t vga_arb_write(struct file *file, const char __user * buf, pr_debug("vgaarb: %s ==> %x:%x:%x.%x\n", curr_pos, domain, bus, PCI_SLOT(devfn), PCI_FUNC(devfn)); - pdev = pci_get_domain_bus_and_slot(domain, bus, devfn); + pbus = pci_find_bus(domain, bus); + pr_debug("vgaarb: pbus %p\n", pbus); + if (pbus == NULL) { + pr_err("vgaarb: invalid PCI domain and/or bus address %x:%x\n", + domain, bus); + ret_val = -ENODEV; + goto done; + } + pdev = pci_get_slot(pbus, devfn); pr_debug("vgaarb: pdev %p\n", pdev); if (!pdev) { - pr_err("vgaarb: invalid PCI address %x:%x:%x\n", - domain, bus, devfn); + pr_err("vgaarb: invalid PCI address %x:%x\n", + bus, devfn); ret_val = -ENODEV; goto done; } diff --git a/trunk/drivers/hid/Kconfig b/trunk/drivers/hid/Kconfig index 1630150ad2b1..fbf49503508d 100644 --- a/trunk/drivers/hid/Kconfig +++ b/trunk/drivers/hid/Kconfig @@ -307,6 +307,7 @@ config HID_LOGITECH config HID_LOGITECH_DJ tristate "Logitech Unifying receivers full support" depends on HID_LOGITECH + default m ---help--- Say Y if you want support for Logitech Unifying receivers and devices. Unifying receivers are capable of pairing up to 6 Logitech compliant @@ -526,14 +527,6 @@ config HID_PICOLCD_LEDS ---help--- Provide access to PicoLCD's GPO pins via leds class. -config HID_PICOLCD_CIR - bool "CIR via RC class" if EXPERT - default !EXPERT - depends on HID_PICOLCD - depends on HID_PICOLCD=RC_CORE || RC_CORE=y - ---help--- - Provide access to PicoLCD's CIR interface via remote control (LIRC). - config HID_PRIMAX tristate "Primax non-fully HID-compliant devices" depends on USB_HID @@ -541,15 +534,6 @@ config HID_PRIMAX Support for Primax devices that are not fully compliant with the HID standard. -config HID_PS3REMOTE - tristate "Sony PS3 BD Remote Control" - depends on BT_HIDP - ---help--- - Support for the Sony PS3 Blue-ray Disk Remote Control and Logitech - Harmony Adapter for PS3, which connect over Bluetooth. - - Support for the 6-axis controllers is provided by HID_SONY. - config HID_ROCCAT tristate "Roccat device support" depends on USB_HID @@ -577,9 +561,7 @@ config HID_SONY tristate "Sony PS3 controller" depends on USB_HID ---help--- - Support for Sony PS3 6-axis controllers. - - Support for the Sony PS3 BD Remote is provided by HID_PS3REMOTE. + Support for Sony PS3 controller. config HID_SPEEDLINK tristate "Speedlink VAD Cezanne mouse support" @@ -708,20 +690,6 @@ config HID_ZYDACRON ---help--- Support for Zydacron remote control. -config HID_SENSOR_HUB - tristate "HID Sensors framework support" - depends on USB_HID - select MFD_CORE - default n - -- help--- - Support for HID Sensor framework. This creates a MFD instance - for a sensor hub and identifies all the sensors connected to it. - Each sensor is registered as a MFD cell, so that sensor specific - processing can be done in a separate driver. Each sensor - drivers can use the service provided by this driver to register - for events and handle data streams. Each sensor driver can format - data and present to user mode using input or IIO interface. - endmenu endif # HID diff --git a/trunk/drivers/hid/Makefile b/trunk/drivers/hid/Makefile index cef68ca859d3..f975485f88b2 100644 --- a/trunk/drivers/hid/Makefile +++ b/trunk/drivers/hid/Makefile @@ -69,28 +69,7 @@ obj-$(CONFIG_HID_PRODIKEYS) += hid-prodikeys.o obj-$(CONFIG_HID_PANTHERLORD) += hid-pl.o obj-$(CONFIG_HID_PETALYNX) += hid-petalynx.o obj-$(CONFIG_HID_PICOLCD) += hid-picolcd.o -hid-picolcd-y += hid-picolcd_core.o -ifdef CONFIG_HID_PICOLCD_FB -hid-picolcd-y += hid-picolcd_fb.o -endif -ifdef CONFIG_HID_PICOLCD_BACKLIGHT -hid-picolcd-y += hid-picolcd_backlight.o -endif -ifdef CONFIG_HID_PICOLCD_LCD -hid-picolcd-y += hid-picolcd_lcd.o -endif -ifdef CONFIG_HID_PICOLCD_LEDS -hid-picolcd-y += hid-picolcd_leds.o -endif -ifdef CONFIG_HID_PICOLCD_CIR -hid-picolcd-y += hid-picolcd_cir.o -endif -ifdef CONFIG_DEBUG_FS -hid-picolcd-y += hid-picolcd_debugfs.o -endif - obj-$(CONFIG_HID_PRIMAX) += hid-primax.o -obj-$(CONFIG_HID_PS3REMOTE) += hid-ps3remote.o obj-$(CONFIG_HID_ROCCAT) += hid-roccat.o hid-roccat-common.o \ hid-roccat-arvo.o hid-roccat-isku.o hid-roccat-kone.o \ hid-roccat-koneplus.o hid-roccat-kovaplus.o hid-roccat-pyra.o \ @@ -112,7 +91,6 @@ obj-$(CONFIG_HID_ZYDACRON) += hid-zydacron.o obj-$(CONFIG_HID_WACOM) += hid-wacom.o obj-$(CONFIG_HID_WALTOP) += hid-waltop.o obj-$(CONFIG_HID_WIIMOTE) += hid-wiimote.o -obj-$(CONFIG_HID_SENSOR_HUB) += hid-sensor-hub.o obj-$(CONFIG_USB_HID) += usbhid/ obj-$(CONFIG_USB_MOUSE) += usbhid/ diff --git a/trunk/drivers/hid/hid-a4tech.c b/trunk/drivers/hid/hid-a4tech.c index 0a239885e67c..902d1dfeb1b5 100644 --- a/trunk/drivers/hid/hid-a4tech.c +++ b/trunk/drivers/hid/hid-a4tech.c @@ -5,6 +5,7 @@ * Copyright (c) 2000-2005 Vojtech Pavlik * Copyright (c) 2005 Michael Haboustak for Concept2, Inc * Copyright (c) 2006-2007 Jiri Kosina + * Copyright (c) 2007 Paul Walmsley * Copyright (c) 2008 Jiri Slaby */ diff --git a/trunk/drivers/hid/hid-apple.c b/trunk/drivers/hid/hid-apple.c index 06ebdbb6ea02..585344b6d338 100644 --- a/trunk/drivers/hid/hid-apple.c +++ b/trunk/drivers/hid/hid-apple.c @@ -5,6 +5,7 @@ * Copyright (c) 2000-2005 Vojtech Pavlik * Copyright (c) 2005 Michael Haboustak for Concept2, Inc * Copyright (c) 2006-2007 Jiri Kosina + * Copyright (c) 2007 Paul Walmsley * Copyright (c) 2008 Jiri Slaby */ diff --git a/trunk/drivers/hid/hid-aureal.c b/trunk/drivers/hid/hid-aureal.c index 7968187ddf7b..ba64b041b8bf 100644 --- a/trunk/drivers/hid/hid-aureal.c +++ b/trunk/drivers/hid/hid-aureal.c @@ -9,6 +9,7 @@ * Copyright (c) 2000-2005 Vojtech Pavlik * Copyright (c) 2005 Michael Haboustak for Concept2, Inc * Copyright (c) 2006-2007 Jiri Kosina + * Copyright (c) 2007 Paul Walmsley * Copyright (c) 2008 Jiri Slaby */ #include diff --git a/trunk/drivers/hid/hid-belkin.c b/trunk/drivers/hid/hid-belkin.c index a1a5a12c3a6b..a1a765a5b08a 100644 --- a/trunk/drivers/hid/hid-belkin.c +++ b/trunk/drivers/hid/hid-belkin.c @@ -5,6 +5,7 @@ * Copyright (c) 2000-2005 Vojtech Pavlik * Copyright (c) 2005 Michael Haboustak for Concept2, Inc * Copyright (c) 2006-2007 Jiri Kosina + * Copyright (c) 2007 Paul Walmsley * Copyright (c) 2008 Jiri Slaby */ diff --git a/trunk/drivers/hid/hid-cherry.c b/trunk/drivers/hid/hid-cherry.c index af034d3d9256..888ece68a47c 100644 --- a/trunk/drivers/hid/hid-cherry.c +++ b/trunk/drivers/hid/hid-cherry.c @@ -5,6 +5,7 @@ * Copyright (c) 2000-2005 Vojtech Pavlik * Copyright (c) 2005 Michael Haboustak for Concept2, Inc * Copyright (c) 2006-2007 Jiri Kosina + * Copyright (c) 2007 Paul Walmsley * Copyright (c) 2008 Jiri Slaby */ diff --git a/trunk/drivers/hid/hid-core.c b/trunk/drivers/hid/hid-core.c index bd3971bf31bf..60ea284407ce 100644 --- a/trunk/drivers/hid/hid-core.c +++ b/trunk/drivers/hid/hid-core.c @@ -126,7 +126,7 @@ static int open_collection(struct hid_parser *parser, unsigned type) if (parser->collection_stack_ptr == HID_COLLECTION_STACK_SIZE) { hid_err(parser->device, "collection stack overflow\n"); - return -EINVAL; + return -1; } if (parser->device->maxcollection == parser->device->collection_size) { @@ -134,7 +134,7 @@ static int open_collection(struct hid_parser *parser, unsigned type) parser->device->collection_size * 2, GFP_KERNEL); if (collection == NULL) { hid_err(parser->device, "failed to reallocate collection array\n"); - return -ENOMEM; + return -1; } memcpy(collection, parser->device->collection, sizeof(struct hid_collection) * @@ -170,7 +170,7 @@ static int close_collection(struct hid_parser *parser) { if (!parser->collection_stack_ptr) { hid_err(parser->device, "collection stack underflow\n"); - return -EINVAL; + return -1; } parser->collection_stack_ptr--; return 0; @@ -374,7 +374,7 @@ static int hid_parser_global(struct hid_parser *parser, struct hid_item *item) case HID_GLOBAL_ITEM_TAG_REPORT_SIZE: parser->global.report_size = item_udata(item); - if (parser->global.report_size > 128) { + if (parser->global.report_size > 96) { hid_err(parser->device, "invalid report_size %d\n", parser->global.report_size); return -1; @@ -757,7 +757,6 @@ int hid_open_report(struct hid_device *device) struct hid_item item; unsigned int size; __u8 *start; - __u8 *buf; __u8 *end; int ret; static int (*dispatch_type[])(struct hid_parser *parser, @@ -776,21 +775,12 @@ int hid_open_report(struct hid_device *device) return -ENODEV; size = device->dev_rsize; - buf = kmemdup(start, size, GFP_KERNEL); - if (buf == NULL) - return -ENOMEM; - if (device->driver->report_fixup) - start = device->driver->report_fixup(device, buf, &size); - else - start = buf; + start = device->driver->report_fixup(device, start, &size); - start = kmemdup(start, size, GFP_KERNEL); - kfree(buf); - if (start == NULL) + device->rdesc = kmemdup(start, size, GFP_KERNEL); + if (device->rdesc == NULL) return -ENOMEM; - - device->rdesc = start; device->rsize = size; parser = vzalloc(sizeof(struct hid_parser)); @@ -1006,8 +996,7 @@ static void hid_process_event(struct hid_device *hid, struct hid_field *field, struct hid_driver *hdrv = hid->driver; int ret; - if (!list_empty(&hid->debug_list)) - hid_dump_input(hid, usage, value); + hid_dump_input(hid, usage, value); if (hdrv && hdrv->event && hid_match_usage(hid, usage)) { ret = hdrv->event(hid, field, usage, value); @@ -1458,14 +1447,7 @@ void hid_disconnect(struct hid_device *hdev) } EXPORT_SYMBOL_GPL(hid_disconnect); -/* - * A list of devices for which there is a specialized driver on HID bus. - * - * Please note that for multitouch devices (driven by hid-multitouch driver), - * there is a proper autodetection and autoloading in place (based on presence - * of HID_DG_CONTACTID), so those devices don't need to be added to this list, - * as we are doing the right thing in hid_scan_usage(). - */ +/* a list of devices for which there is a specialized driver on HID bus */ static const struct hid_device_id hid_have_special_driver[] = { { HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_WCP32PU) }, { HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_X5_005D) }, @@ -1568,10 +1550,6 @@ static const struct hid_device_id hid_have_special_driver[] = { { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_3) }, { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK, USB_DEVICE_ID_HOLTEK_ON_LINE_GRIP) }, { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_KEYBOARD) }, - { HID_USB_DEVICE(USB_VENDOR_ID_INTEL_8086, USB_DEVICE_ID_SENSOR_HUB_1020) }, - { HID_USB_DEVICE(USB_VENDOR_ID_INTEL_8086, USB_DEVICE_ID_SENSOR_HUB_09FA) }, - { HID_USB_DEVICE(USB_VENDOR_ID_INTEL_8087, USB_DEVICE_ID_SENSOR_HUB_1020) }, - { HID_USB_DEVICE(USB_VENDOR_ID_INTEL_8087, USB_DEVICE_ID_SENSOR_HUB_09FA) }, { HID_USB_DEVICE(USB_VENDOR_ID_KENSINGTON, USB_DEVICE_ID_KS_SLIMBLADE) }, { HID_USB_DEVICE(USB_VENDOR_ID_KEYTOUCH, USB_DEVICE_ID_KEYTOUCH_IEC) }, { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_ERGO_525V) }, @@ -1580,14 +1558,11 @@ static const struct hid_device_id hid_have_special_driver[] = { { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_EASYPEN_M610X) }, { HID_USB_DEVICE(USB_VENDOR_ID_LABTEC, USB_DEVICE_ID_LABTEC_WIRELESS_KEYBOARD) }, { HID_USB_DEVICE(USB_VENDOR_ID_LCPOWER, USB_DEVICE_ID_LCPOWER_LC1000 ) }, -#if IS_ENABLED(CONFIG_HID_LENOVO_TPKBD) - { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_TPKBD) }, -#endif + { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_TPKBD) }, { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER) }, { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER) }, { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER_2) }, { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RECEIVER) }, - { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_PS3) }, { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_DESKTOP) }, { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_EDGE) }, { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_MINI) }, @@ -1649,7 +1624,7 @@ static const struct hid_device_id hid_have_special_driver[] = { { HID_USB_DEVICE(USB_VENDOR_ID_ORTEK, USB_DEVICE_ID_ORTEK_WKB2000) }, { HID_USB_DEVICE(USB_VENDOR_ID_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE) }, { HID_USB_DEVICE(USB_VENDOR_ID_PRIMAX, USB_DEVICE_ID_PRIMAX_KEYBOARD) }, -#if IS_ENABLED(CONFIG_HID_ROCCAT) + { HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_PIXART_IMAGING_INC_OPTICAL_TOUCH_SCREEN) }, { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONE) }, { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_ARVO) }, { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_ISKU) }, @@ -1658,18 +1633,15 @@ static const struct hid_device_id hid_have_special_driver[] = { { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_PYRA_WIRED) }, { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_PYRA_WIRELESS) }, { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_SAVU) }, -#endif { HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_PS1000) }, { HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_IR_REMOTE) }, { HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_WIRELESS_KBD_MOUSE) }, { HID_USB_DEVICE(USB_VENDOR_ID_SKYCABLE, USB_DEVICE_ID_SKYCABLE_WIRELESS_PRESENTER) }, - { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_BDREMOTE) }, { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) }, { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_NAVIGATION_CONTROLLER) }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) }, { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE) }, { HID_USB_DEVICE(USB_VENDOR_ID_SUNPLUS, USB_DEVICE_ID_SUNPLUS_WDESKTOP) }, - { HID_USB_DEVICE(USB_VENDOR_ID_STANTUM_STM, USB_DEVICE_ID_SENSOR_HUB_7014) }, { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb300) }, { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb304) }, { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb323) }, @@ -1689,7 +1661,6 @@ static const struct hid_device_id hid_have_special_driver[] = { { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U) }, { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP1062) }, { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_WIRELESS_TABLET_TWHL850) }, - { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_TWHA60) }, { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_SMARTJOY_PLUS) }, { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_SUPER_JOY_BOX_3) }, { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_DUAL_USB_JOYPAD) }, diff --git a/trunk/drivers/hid/hid-cypress.c b/trunk/drivers/hid/hid-cypress.c index 3e159a50dac7..9e43aaca9774 100644 --- a/trunk/drivers/hid/hid-cypress.c +++ b/trunk/drivers/hid/hid-cypress.c @@ -5,6 +5,7 @@ * Copyright (c) 2000-2005 Vojtech Pavlik * Copyright (c) 2005 Michael Haboustak for Concept2, Inc * Copyright (c) 2006-2007 Jiri Kosina + * Copyright (c) 2007 Paul Walmsley * Copyright (c) 2008 Jiri Slaby */ diff --git a/trunk/drivers/hid/hid-debug.c b/trunk/drivers/hid/hid-debug.c index 933fff0fff1f..01dd9a7daf7a 100644 --- a/trunk/drivers/hid/hid-debug.c +++ b/trunk/drivers/hid/hid-debug.c @@ -911,21 +911,15 @@ static void hid_dump_input_mapping(struct hid_device *hid, struct seq_file *f) } + static int hid_debug_rdesc_show(struct seq_file *f, void *p) { struct hid_device *hdev = f->private; - const __u8 *rdesc = hdev->rdesc; - unsigned rsize = hdev->rsize; int i; - if (!rdesc) { - rdesc = hdev->dev_rdesc; - rsize = hdev->dev_rsize; - } - /* dump HID report descriptor */ - for (i = 0; i < rsize; i++) - seq_printf(f, "%02x ", rdesc[i]); + for (i = 0; i < hdev->rsize; i++) + seq_printf(f, "%02x ", hdev->rdesc[i]); seq_printf(f, "\n\n"); /* dump parsed data and input mappings */ diff --git a/trunk/drivers/hid/hid-ezkey.c b/trunk/drivers/hid/hid-ezkey.c index 6540af2871a7..ca1163e9d42d 100644 --- a/trunk/drivers/hid/hid-ezkey.c +++ b/trunk/drivers/hid/hid-ezkey.c @@ -5,6 +5,7 @@ * Copyright (c) 2000-2005 Vojtech Pavlik * Copyright (c) 2005 Michael Haboustak for Concept2, Inc * Copyright (c) 2006-2007 Jiri Kosina + * Copyright (c) 2007 Paul Walmsley * Copyright (c) 2008 Jiri Slaby */ diff --git a/trunk/drivers/hid/hid-gyration.c b/trunk/drivers/hid/hid-gyration.c index 4442c30ef531..e88b951cd10d 100644 --- a/trunk/drivers/hid/hid-gyration.c +++ b/trunk/drivers/hid/hid-gyration.c @@ -4,6 +4,7 @@ * Copyright (c) 1999 Andreas Gal * Copyright (c) 2000-2005 Vojtech Pavlik * Copyright (c) 2005 Michael Haboustak for Concept2, Inc + * Copyright (c) 2007 Paul Walmsley * Copyright (c) 2008 Jiri Slaby * Copyright (c) 2006-2008 Jiri Kosina */ diff --git a/trunk/drivers/hid/hid-holtekff.c b/trunk/drivers/hid/hid-holtekff.c index ff295e60059b..4e7542151e22 100644 --- a/trunk/drivers/hid/hid-holtekff.c +++ b/trunk/drivers/hid/hid-holtekff.c @@ -100,7 +100,8 @@ static void holtekff_send(struct holtekff_device *holtekff, holtekff->field->value[i] = data[i]; } - dbg_hid("sending %*ph\n", 7, data); + dbg_hid("sending %02x %02x %02x %02x %02x %02x %02x\n", data[0], + data[1], data[2], data[3], data[4], data[5], data[6]); usbhid_submit_report(hid, holtekff->field->report, USB_DIR_OUT); } diff --git a/trunk/drivers/hid/hid-ids.h b/trunk/drivers/hid/hid-ids.h index 269b50912a4a..1dcb76ff51e3 100644 --- a/trunk/drivers/hid/hid-ids.h +++ b/trunk/drivers/hid/hid-ids.h @@ -5,6 +5,7 @@ * Copyright (c) 2000-2005 Vojtech Pavlik * Copyright (c) 2005 Michael Haboustak for Concept2, Inc * Copyright (c) 2006-2007 Jiri Kosina + * Copyright (c) 2007 Paul Walmsley */ /* @@ -268,11 +269,7 @@ #define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_72FA 0x72fa #define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_7302 0x7302 #define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_7349 0x7349 -#define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_73F7 0x73f7 #define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_A001 0xa001 -#define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_7224 0x7224 -#define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_72D0 0x72d0 -#define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_72C4 0x72c4 #define USB_VENDOR_ID_ELECOM 0x056e #define USB_DEVICE_ID_ELECOM_BM084 0x0061 @@ -286,9 +283,6 @@ #define USB_VENDOR_ID_EMS 0x2006 #define USB_DEVICE_ID_EMS_TRIO_LINKER_PLUS_II 0x0118 -#define USB_VENDOR_ID_FLATFROG 0x25b5 -#define USB_DEVICE_ID_MULTITOUCH_3200 0x0002 - #define USB_VENDOR_ID_ESSENTIAL_REALITY 0x0d7f #define USB_DEVICE_ID_ESSENTIAL_REALITY_P5 0x0100 @@ -302,9 +296,6 @@ #define USB_VENDOR_ID_EZKEY 0x0518 #define USB_DEVICE_ID_BTC_8193 0x0002 -#define USB_VENDOR_ID_FREESCALE 0x15A2 -#define USB_DEVICE_ID_FREESCALE_MX28 0x004F - #define USB_VENDOR_ID_FRUCTEL 0x25B6 #define USB_DEVICE_ID_GAMETEL_MT_MODE 0x0002 @@ -314,7 +305,6 @@ #define USB_VENDOR_ID_GENERAL_TOUCH 0x0dfc #define USB_DEVICE_ID_GENERAL_TOUCH_WIN7_TWOFINGERS 0x0003 -#define USB_DEVICE_ID_GENERAL_TOUCH_WIN8_PWT_TENFINGERS 0x0100 #define USB_VENDOR_ID_GLAB 0x06c2 #define USB_DEVICE_ID_4_PHIDGETSERVO_30 0x0038 @@ -429,11 +419,6 @@ #define USB_VENDOR_ID_IMATION 0x0718 #define USB_DEVICE_ID_DISC_STAKKA 0xd000 -#define USB_VENDOR_ID_INTEL_8086 0x8086 -#define USB_VENDOR_ID_INTEL_8087 0x8087 -#define USB_DEVICE_ID_SENSOR_HUB_1020 0x1020 -#define USB_DEVICE_ID_SENSOR_HUB_09FA 0x09FA - #define USB_VENDOR_ID_IRTOUCHSYSTEMS 0x6615 #define USB_DEVICE_ID_IRTOUCH_INFRARED_USB 0x0070 @@ -511,7 +496,6 @@ #define USB_DEVICE_ID_LOGITECH_RECEIVER 0xc101 #define USB_DEVICE_ID_LOGITECH_HARMONY_FIRST 0xc110 #define USB_DEVICE_ID_LOGITECH_HARMONY_LAST 0xc14f -#define USB_DEVICE_ID_LOGITECH_HARMONY_PS3 0x0306 #define USB_DEVICE_ID_LOGITECH_RUMBLEPAD_CORD 0xc20a #define USB_DEVICE_ID_LOGITECH_RUMBLEPAD 0xc211 #define USB_DEVICE_ID_LOGITECH_EXTREME_3D 0xc215 @@ -668,6 +652,7 @@ #define USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH 0x3000 #define USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3001 0x3001 #define USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3008 0x3008 +#define USB_DEVICE_ID_PIXART_IMAGING_INC_OPTICAL_TOUCH_SCREEN 0x3001 #define USB_VENDOR_ID_ROCCAT 0x1e7d #define USB_DEVICE_ID_ROCCAT_ARVO 0x30d4 @@ -698,7 +683,6 @@ #define USB_VENDOR_ID_SONY 0x054c #define USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE 0x024b -#define USB_DEVICE_ID_SONY_PS3_BDREMOTE 0x0306 #define USB_DEVICE_ID_SONY_PS3_CONTROLLER 0x0268 #define USB_DEVICE_ID_SONY_NAVIGATION_CONTROLLER 0x042f @@ -711,7 +695,6 @@ #define USB_VENDOR_ID_STANTUM_STM 0x0483 #define USB_DEVICE_ID_MTP_STM 0x3261 -#define USB_DEVICE_ID_SENSOR_HUB_7014 0x7014 #define USB_VENDOR_ID_STANTUM_SITRONIX 0x1403 #define USB_DEVICE_ID_MTP_SITRONIX 0x5001 @@ -775,7 +758,6 @@ #define USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U 0x0005 #define USB_DEVICE_ID_UCLOGIC_TABLET_WP1062 0x0064 #define USB_DEVICE_ID_UCLOGIC_WIRELESS_TABLET_TWHL850 0x0522 -#define USB_DEVICE_ID_UCLOGIC_TABLET_TWHA60 0x0781 #define USB_VENDOR_ID_UNITEC 0x227d #define USB_DEVICE_ID_UNITEC_USB_TOUCH_0709 0x0709 diff --git a/trunk/drivers/hid/hid-input.c b/trunk/drivers/hid/hid-input.c index d917c0d53685..811bfad64609 100644 --- a/trunk/drivers/hid/hid-input.c +++ b/trunk/drivers/hid/hid-input.c @@ -1154,7 +1154,6 @@ static void report_features(struct hid_device *hid) int hidinput_connect(struct hid_device *hid, unsigned int force) { - struct hid_driver *drv = hid->driver; struct hid_report *report; struct hid_input *hidinput = NULL; struct input_dev *input_dev; @@ -1229,8 +1228,6 @@ int hidinput_connect(struct hid_device *hid, unsigned int force) * UGCI) cram a lot of unrelated inputs into the * same interface. */ hidinput->report = report; - if (drv->input_configured) - drv->input_configured(hid, hidinput); if (input_register_device(hidinput->input)) goto out_cleanup; hidinput = NULL; @@ -1238,12 +1235,8 @@ int hidinput_connect(struct hid_device *hid, unsigned int force) } } - if (hidinput) { - if (drv->input_configured) - drv->input_configured(hid, hidinput); - if (input_register_device(hidinput->input)) - goto out_cleanup; - } + if (hidinput && input_register_device(hidinput->input)) + goto out_cleanup; return 0; diff --git a/trunk/drivers/hid/hid-lcpower.c b/trunk/drivers/hid/hid-lcpower.c index 22bc14abdfa3..c4fe9bd095b7 100644 --- a/trunk/drivers/hid/hid-lcpower.c +++ b/trunk/drivers/hid/hid-lcpower.c @@ -24,7 +24,7 @@ static int ts_input_mapping(struct hid_device *hdev, struct hid_input *hi, struct hid_field *field, struct hid_usage *usage, unsigned long **bit, int *max) { - if ((usage->hid & HID_USAGE_PAGE) != HID_UP_LOGIVENDOR) + if ((usage->hid & HID_USAGE_PAGE) != 0x0ffbc0000) return 0; switch (usage->hid & HID_USAGE) { diff --git a/trunk/drivers/hid/hid-lenovo-tpkbd.c b/trunk/drivers/hid/hid-lenovo-tpkbd.c index cea016e94f43..77d2df04c97b 100644 --- a/trunk/drivers/hid/hid-lenovo-tpkbd.c +++ b/trunk/drivers/hid/hid-lenovo-tpkbd.c @@ -56,8 +56,9 @@ static int tpkbd_input_mapping(struct hid_device *hdev, static int tpkbd_features_set(struct hid_device *hdev) { struct hid_report *report; - struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev); + struct tpkbd_data_pointer *data_pointer; + data_pointer = (struct tpkbd_data_pointer *) hid_get_drvdata(hdev); report = hdev->report_enum[HID_FEATURE_REPORT].report_id_hash[4]; report->field[0]->value[0] = data_pointer->press_to_select ? 0x01 : 0x02; @@ -76,8 +77,14 @@ static ssize_t pointer_press_to_select_show(struct device *dev, struct device_attribute *attr, char *buf) { - struct hid_device *hdev = container_of(dev, struct hid_device, dev); - struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev); + struct hid_device *hdev; + struct tpkbd_data_pointer *data_pointer; + + hdev = container_of(dev, struct hid_device, dev); + if (hdev == NULL) + return -ENODEV; + + data_pointer = (struct tpkbd_data_pointer *) hid_get_drvdata(hdev); return snprintf(buf, PAGE_SIZE, "%u\n", data_pointer->press_to_select); } @@ -87,10 +94,16 @@ static ssize_t pointer_press_to_select_store(struct device *dev, const char *buf, size_t count) { - struct hid_device *hdev = container_of(dev, struct hid_device, dev); - struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev); + struct hid_device *hdev; + struct tpkbd_data_pointer *data_pointer; int value; + hdev = container_of(dev, struct hid_device, dev); + if (hdev == NULL) + return -ENODEV; + + data_pointer = (struct tpkbd_data_pointer *) hid_get_drvdata(hdev); + if (kstrtoint(buf, 10, &value)) return -EINVAL; if (value < 0 || value > 1) @@ -106,8 +119,14 @@ static ssize_t pointer_dragging_show(struct device *dev, struct device_attribute *attr, char *buf) { - struct hid_device *hdev = container_of(dev, struct hid_device, dev); - struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev); + struct hid_device *hdev; + struct tpkbd_data_pointer *data_pointer; + + hdev = container_of(dev, struct hid_device, dev); + if (hdev == NULL) + return -ENODEV; + + data_pointer = (struct tpkbd_data_pointer *) hid_get_drvdata(hdev); return snprintf(buf, PAGE_SIZE, "%u\n", data_pointer->dragging); } @@ -117,10 +136,16 @@ static ssize_t pointer_dragging_store(struct device *dev, const char *buf, size_t count) { - struct hid_device *hdev = container_of(dev, struct hid_device, dev); - struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev); + struct hid_device *hdev; + struct tpkbd_data_pointer *data_pointer; int value; + hdev = container_of(dev, struct hid_device, dev); + if (hdev == NULL) + return -ENODEV; + + data_pointer = (struct tpkbd_data_pointer *) hid_get_drvdata(hdev); + if (kstrtoint(buf, 10, &value)) return -EINVAL; if (value < 0 || value > 1) @@ -136,8 +161,14 @@ static ssize_t pointer_release_to_select_show(struct device *dev, struct device_attribute *attr, char *buf) { - struct hid_device *hdev = container_of(dev, struct hid_device, dev); - struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev); + struct hid_device *hdev; + struct tpkbd_data_pointer *data_pointer; + + hdev = container_of(dev, struct hid_device, dev); + if (hdev == NULL) + return -ENODEV; + + data_pointer = (struct tpkbd_data_pointer *) hid_get_drvdata(hdev); return snprintf(buf, PAGE_SIZE, "%u\n", data_pointer->release_to_select); } @@ -147,10 +178,16 @@ static ssize_t pointer_release_to_select_store(struct device *dev, const char *buf, size_t count) { - struct hid_device *hdev = container_of(dev, struct hid_device, dev); - struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev); + struct hid_device *hdev; + struct tpkbd_data_pointer *data_pointer; int value; + hdev = container_of(dev, struct hid_device, dev); + if (hdev == NULL) + return -ENODEV; + + data_pointer = (struct tpkbd_data_pointer *) hid_get_drvdata(hdev); + if (kstrtoint(buf, 10, &value)) return -EINVAL; if (value < 0 || value > 1) @@ -166,8 +203,14 @@ static ssize_t pointer_select_right_show(struct device *dev, struct device_attribute *attr, char *buf) { - struct hid_device *hdev = container_of(dev, struct hid_device, dev); - struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev); + struct hid_device *hdev; + struct tpkbd_data_pointer *data_pointer; + + hdev = container_of(dev, struct hid_device, dev); + if (hdev == NULL) + return -ENODEV; + + data_pointer = (struct tpkbd_data_pointer *) hid_get_drvdata(hdev); return snprintf(buf, PAGE_SIZE, "%u\n", data_pointer->select_right); } @@ -177,10 +220,16 @@ static ssize_t pointer_select_right_store(struct device *dev, const char *buf, size_t count) { - struct hid_device *hdev = container_of(dev, struct hid_device, dev); - struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev); + struct hid_device *hdev; + struct tpkbd_data_pointer *data_pointer; int value; + hdev = container_of(dev, struct hid_device, dev); + if (hdev == NULL) + return -ENODEV; + + data_pointer = (struct tpkbd_data_pointer *) hid_get_drvdata(hdev); + if (kstrtoint(buf, 10, &value)) return -EINVAL; if (value < 0 || value > 1) @@ -196,8 +245,14 @@ static ssize_t pointer_sensitivity_show(struct device *dev, struct device_attribute *attr, char *buf) { - struct hid_device *hdev = container_of(dev, struct hid_device, dev); - struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev); + struct hid_device *hdev; + struct tpkbd_data_pointer *data_pointer; + + hdev = container_of(dev, struct hid_device, dev); + if (hdev == NULL) + return -ENODEV; + + data_pointer = (struct tpkbd_data_pointer *) hid_get_drvdata(hdev); return snprintf(buf, PAGE_SIZE, "%u\n", data_pointer->sensitivity); @@ -208,10 +263,16 @@ static ssize_t pointer_sensitivity_store(struct device *dev, const char *buf, size_t count) { - struct hid_device *hdev = container_of(dev, struct hid_device, dev); - struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev); + struct hid_device *hdev; + struct tpkbd_data_pointer *data_pointer; int value; + hdev = container_of(dev, struct hid_device, dev); + if (hdev == NULL) + return -ENODEV; + + data_pointer = (struct tpkbd_data_pointer *) hid_get_drvdata(hdev); + if (kstrtoint(buf, 10, &value) || value < 1 || value > 255) return -EINVAL; @@ -225,10 +286,14 @@ static ssize_t pointer_press_speed_show(struct device *dev, struct device_attribute *attr, char *buf) { - struct hid_device *hdev = container_of(dev, struct hid_device, dev); - struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev); + struct hid_device *hdev; + struct tpkbd_data_pointer *data_pointer; - data_pointer = hid_get_drvdata(hdev); + hdev = container_of(dev, struct hid_device, dev); + if (hdev == NULL) + return -ENODEV; + + data_pointer = (struct tpkbd_data_pointer *) hid_get_drvdata(hdev); return snprintf(buf, PAGE_SIZE, "%u\n", data_pointer->press_speed); @@ -239,10 +304,16 @@ static ssize_t pointer_press_speed_store(struct device *dev, const char *buf, size_t count) { - struct hid_device *hdev = container_of(dev, struct hid_device, dev); - struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev); + struct hid_device *hdev; + struct tpkbd_data_pointer *data_pointer; int value; + hdev = container_of(dev, struct hid_device, dev); + if (hdev == NULL) + return -ENODEV; + + data_pointer = (struct tpkbd_data_pointer *) hid_get_drvdata(hdev); + if (kstrtoint(buf, 10, &value) || value < 1 || value > 255) return -EINVAL; @@ -299,11 +370,15 @@ static const struct attribute_group tpkbd_attr_group_pointer = { static enum led_brightness tpkbd_led_brightness_get( struct led_classdev *led_cdev) { - struct device *dev = led_cdev->dev->parent; - struct hid_device *hdev = container_of(dev, struct hid_device, dev); - struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev); + struct device *dev; + struct hid_device *hdev; + struct tpkbd_data_pointer *data_pointer; int led_nr = 0; + dev = led_cdev->dev->parent; + hdev = container_of(dev, struct hid_device, dev); + data_pointer = (struct tpkbd_data_pointer *) hid_get_drvdata(hdev); + if (led_cdev == &data_pointer->led_micmute) led_nr = 1; @@ -315,12 +390,16 @@ static enum led_brightness tpkbd_led_brightness_get( static void tpkbd_led_brightness_set(struct led_classdev *led_cdev, enum led_brightness value) { - struct device *dev = led_cdev->dev->parent; - struct hid_device *hdev = container_of(dev, struct hid_device, dev); - struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev); + struct device *dev; + struct hid_device *hdev; struct hid_report *report; + struct tpkbd_data_pointer *data_pointer; int led_nr = 0; + dev = led_cdev->dev->parent; + hdev = container_of(dev, struct hid_device, dev); + data_pointer = (struct tpkbd_data_pointer *) hid_get_drvdata(hdev); + if (led_cdev == &data_pointer->led_micmute) led_nr = 1; @@ -429,17 +508,17 @@ static int tpkbd_probe(struct hid_device *hdev, static void tpkbd_remove_tp(struct hid_device *hdev) { - struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev); + struct tpkbd_data_pointer *data_pointer; sysfs_remove_group(&hdev->dev.kobj, &tpkbd_attr_group_pointer); + data_pointer = (struct tpkbd_data_pointer *) hid_get_drvdata(hdev); + led_classdev_unregister(&data_pointer->led_micmute); led_classdev_unregister(&data_pointer->led_mute); hid_set_drvdata(hdev, NULL); - kfree(data_pointer->led_micmute.name); - kfree(data_pointer->led_mute.name); kfree(data_pointer); } diff --git a/trunk/drivers/hid/hid-lg.c b/trunk/drivers/hid/hid-lg.c index a2f8e88b9fa2..fc37ed6b108c 100644 --- a/trunk/drivers/hid/hid-lg.c +++ b/trunk/drivers/hid/hid-lg.c @@ -5,6 +5,7 @@ * Copyright (c) 2000-2005 Vojtech Pavlik * Copyright (c) 2005 Michael Haboustak for Concept2, Inc * Copyright (c) 2006-2007 Jiri Kosina + * Copyright (c) 2007 Paul Walmsley * Copyright (c) 2008 Jiri Slaby * Copyright (c) 2010 Hendrik Iben */ @@ -108,7 +109,7 @@ static __u8 dfp_rdesc_fixed[] = { static __u8 *lg_report_fixup(struct hid_device *hdev, __u8 *rdesc, unsigned int *rsize) { - struct lg_drv_data *drv_data = hid_get_drvdata(hdev); + struct lg_drv_data *drv_data = (struct lg_drv_data *)hid_get_drvdata(hdev); if ((drv_data->quirks & LG_RDESC) && *rsize >= 90 && rdesc[83] == 0x26 && rdesc[84] == 0x8c && rdesc[85] == 0x02) { @@ -277,7 +278,7 @@ static int lg_input_mapping(struct hid_device *hdev, struct hid_input *hi, 0, 0, 0, 0, 0,183,184,185,186,187, 188,189,190,191,192,193,194, 0, 0, 0 }; - struct lg_drv_data *drv_data = hid_get_drvdata(hdev); + struct lg_drv_data *drv_data = (struct lg_drv_data *)hid_get_drvdata(hdev); unsigned int hid = usage->hid; if (hdev->product == USB_DEVICE_ID_LOGITECH_RECEIVER && @@ -318,7 +319,7 @@ static int lg_input_mapped(struct hid_device *hdev, struct hid_input *hi, struct hid_field *field, struct hid_usage *usage, unsigned long **bit, int *max) { - struct lg_drv_data *drv_data = hid_get_drvdata(hdev); + struct lg_drv_data *drv_data = (struct lg_drv_data *)hid_get_drvdata(hdev); if ((drv_data->quirks & LG_BAD_RELATIVE_KEYS) && usage->type == EV_KEY && (field->flags & HID_MAIN_ITEM_RELATIVE)) @@ -334,16 +335,13 @@ static int lg_input_mapped(struct hid_device *hdev, struct hid_input *hi, static int lg_event(struct hid_device *hdev, struct hid_field *field, struct hid_usage *usage, __s32 value) { - struct lg_drv_data *drv_data = hid_get_drvdata(hdev); + struct lg_drv_data *drv_data = (struct lg_drv_data *)hid_get_drvdata(hdev); if ((drv_data->quirks & LG_INVERT_HWHEEL) && usage->code == REL_HWHEEL) { input_event(field->hidinput->input, usage->type, usage->code, -value); return 1; } - if (drv_data->quirks & LG_FF4) { - return lg4ff_adjust_input_event(hdev, field, usage, value, drv_data); - } return 0; } @@ -360,7 +358,7 @@ static int lg_probe(struct hid_device *hdev, const struct hid_device_id *id) return -ENOMEM; } drv_data->quirks = id->driver_data; - + hid_set_drvdata(hdev, (void *)drv_data); if (drv_data->quirks & LG_NOGET) @@ -382,7 +380,7 @@ static int lg_probe(struct hid_device *hdev, const struct hid_device_id *id) } /* Setup wireless link with Logitech Wii wheel */ - if (hdev->product == USB_DEVICE_ID_LOGITECH_WII_WHEEL) { + if(hdev->product == USB_DEVICE_ID_LOGITECH_WII_WHEEL) { unsigned char buf[] = { 0x00, 0xAF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; ret = hdev->hid_output_raw_report(hdev, buf, sizeof(buf), HID_FEATURE_REPORT); @@ -418,7 +416,7 @@ static int lg_probe(struct hid_device *hdev, const struct hid_device_id *id) static void lg_remove(struct hid_device *hdev) { - struct lg_drv_data *drv_data = hid_get_drvdata(hdev); + struct lg_drv_data *drv_data = (struct lg_drv_data *)hid_get_drvdata(hdev); if (drv_data->quirks & LG_FF4) lg4ff_deinit(hdev); @@ -478,7 +476,7 @@ static const struct hid_device_id lg_devices[] = { .driver_data = LG_NOGET | LG_FF4 }, { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WII_WHEEL), .driver_data = LG_FF4 }, - { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WINGMAN_FFG), + { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WINGMAN_FFG ), .driver_data = LG_FF }, { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2), .driver_data = LG_FF2 }, diff --git a/trunk/drivers/hid/hid-lg.h b/trunk/drivers/hid/hid-lg.h index 142ce3f5f055..d64cf8d2751e 100644 --- a/trunk/drivers/hid/hid-lg.h +++ b/trunk/drivers/hid/hid-lg.h @@ -25,13 +25,9 @@ static inline int lg3ff_init(struct hid_device *hdev) { return -1; } #endif #ifdef CONFIG_LOGIWHEELS_FF -int lg4ff_adjust_input_event(struct hid_device *hid, struct hid_field *field, - struct hid_usage *usage, __s32 value, struct lg_drv_data *drv_data); int lg4ff_init(struct hid_device *hdev); int lg4ff_deinit(struct hid_device *hdev); #else -static inline int lg4ff_adjust_input_event(struct hid_device *hid, struct hid_field *field, - struct hid_usage *usage, __s32 value, struct lg_drv_data *drv_data) { return 0; } static inline int lg4ff_init(struct hid_device *hdev) { return -1; } static inline int lg4ff_deinit(struct hid_device *hdev) { return -1; } #endif diff --git a/trunk/drivers/hid/hid-lg4ff.c b/trunk/drivers/hid/hid-lg4ff.c index d7947c701f30..f3390ee6105c 100644 --- a/trunk/drivers/hid/hid-lg4ff.c +++ b/trunk/drivers/hid/hid-lg4ff.c @@ -43,11 +43,6 @@ #define G27_REV_MAJ 0x12 #define G27_REV_MIN 0x38 -#define DFP_X_MIN 0 -#define DFP_X_MAX 16383 -#define DFP_PEDAL_MIN 0 -#define DFP_PEDAL_MAX 255 - #define to_hid_device(pdev) container_of(pdev, struct hid_device, dev) static void hid_lg4ff_set_range_dfp(struct hid_device *hid, u16 range); @@ -58,7 +53,6 @@ static ssize_t lg4ff_range_store(struct device *dev, struct device_attribute *at static DEVICE_ATTR(range, S_IRWXU | S_IRWXG | S_IRWXO, lg4ff_range_show, lg4ff_range_store); struct lg4ff_device_entry { - __u32 product_id; __u16 range; __u16 min_range; __u16 max_range; @@ -135,77 +129,26 @@ static const struct lg4ff_usb_revision lg4ff_revs[] = { {G27_REV_MAJ, G27_REV_MIN, &native_g27}, /* G27 */ }; -/* Recalculates X axis value accordingly to currently selected range */ -static __s32 lg4ff_adjust_dfp_x_axis(__s32 value, __u16 range) -{ - __u16 max_range; - __s32 new_value; - - if (range == 900) - return value; - else if (range == 200) - return value; - else if (range < 200) - max_range = 200; - else - max_range = 900; - - new_value = 8192 + mult_frac(value - 8192, max_range, range); - if (new_value < 0) - return 0; - else if (new_value > 16383) - return 16383; - else - return new_value; -} - -int lg4ff_adjust_input_event(struct hid_device *hid, struct hid_field *field, - struct hid_usage *usage, __s32 value, struct lg_drv_data *drv_data) -{ - struct lg4ff_device_entry *entry = drv_data->device_props; - __s32 new_value = 0; - - if (!entry) { - hid_err(hid, "Device properties not found"); - return 0; - } - - switch (entry->product_id) { - case USB_DEVICE_ID_LOGITECH_DFP_WHEEL: - switch (usage->code) { - case ABS_X: - new_value = lg4ff_adjust_dfp_x_axis(value, entry->range); - input_event(field->hidinput->input, usage->type, usage->code, new_value); - return 1; - default: - return 0; - } - default: - return 0; - } -} - static int hid_lg4ff_play(struct input_dev *dev, void *data, struct ff_effect *effect) { struct hid_device *hid = input_get_drvdata(dev); struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; struct hid_report *report = list_entry(report_list->next, struct hid_report, list); - __s32 *value = report->field[0]->value; int x; -#define CLAMP(x) do { if (x < 0) x = 0; else if (x > 0xff) x = 0xff; } while (0) +#define CLAMP(x) if (x < 0) x = 0; if (x > 0xff) x = 0xff switch (effect->type) { case FF_CONSTANT: x = effect->u.ramp.start_level + 0x80; /* 0x80 is no force */ CLAMP(x); - value[0] = 0x11; /* Slot 1 */ - value[1] = 0x08; - value[2] = x; - value[3] = 0x80; - value[4] = 0x00; - value[5] = 0x00; - value[6] = 0x00; + report->field[0]->value[0] = 0x11; /* Slot 1 */ + report->field[0]->value[1] = 0x08; + report->field[0]->value[2] = x; + report->field[0]->value[3] = 0x80; + report->field[0]->value[4] = 0x00; + report->field[0]->value[5] = 0x00; + report->field[0]->value[6] = 0x00; usbhid_submit_report(hid, report, USB_DIR_OUT); break; @@ -220,15 +163,14 @@ static void hid_lg4ff_set_autocenter_default(struct input_dev *dev, u16 magnitud struct hid_device *hid = input_get_drvdata(dev); struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; struct hid_report *report = list_entry(report_list->next, struct hid_report, list); - __s32 *value = report->field[0]->value; - value[0] = 0xfe; - value[1] = 0x0d; - value[2] = magnitude >> 13; - value[3] = magnitude >> 13; - value[4] = magnitude >> 8; - value[5] = 0x00; - value[6] = 0x00; + report->field[0]->value[0] = 0xfe; + report->field[0]->value[1] = 0x0d; + report->field[0]->value[2] = magnitude >> 13; + report->field[0]->value[3] = magnitude >> 13; + report->field[0]->value[4] = magnitude >> 8; + report->field[0]->value[5] = 0x00; + report->field[0]->value[6] = 0x00; usbhid_submit_report(hid, report, USB_DIR_OUT); } @@ -239,16 +181,16 @@ static void hid_lg4ff_set_autocenter_ffex(struct input_dev *dev, u16 magnitude) struct hid_device *hid = input_get_drvdata(dev); struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; struct hid_report *report = list_entry(report_list->next, struct hid_report, list); - __s32 *value = report->field[0]->value; magnitude = magnitude * 90 / 65535; + - value[0] = 0xfe; - value[1] = 0x03; - value[2] = magnitude >> 14; - value[3] = magnitude >> 14; - value[4] = magnitude; - value[5] = 0x00; - value[6] = 0x00; + report->field[0]->value[0] = 0xfe; + report->field[0]->value[1] = 0x03; + report->field[0]->value[2] = magnitude >> 14; + report->field[0]->value[3] = magnitude >> 14; + report->field[0]->value[4] = magnitude; + report->field[0]->value[5] = 0x00; + report->field[0]->value[6] = 0x00; usbhid_submit_report(hid, report, USB_DIR_OUT); } @@ -258,17 +200,15 @@ static void hid_lg4ff_set_range_g25(struct hid_device *hid, u16 range) { struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; struct hid_report *report = list_entry(report_list->next, struct hid_report, list); - __s32 *value = report->field[0]->value; - dbg_hid("G25/G27/DFGT: setting range to %u\n", range); - value[0] = 0xf8; - value[1] = 0x81; - value[2] = range & 0x00ff; - value[3] = (range & 0xff00) >> 8; - value[4] = 0x00; - value[5] = 0x00; - value[6] = 0x00; + report->field[0]->value[0] = 0xf8; + report->field[0]->value[1] = 0x81; + report->field[0]->value[2] = range & 0x00ff; + report->field[0]->value[3] = (range & 0xff00) >> 8; + report->field[0]->value[4] = 0x00; + report->field[0]->value[5] = 0x00; + report->field[0]->value[6] = 0x00; usbhid_submit_report(hid, report, USB_DIR_OUT); } @@ -279,18 +219,16 @@ static void hid_lg4ff_set_range_dfp(struct hid_device *hid, __u16 range) struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; struct hid_report *report = list_entry(report_list->next, struct hid_report, list); int start_left, start_right, full_range; - __s32 *value = report->field[0]->value; - dbg_hid("Driving Force Pro: setting range to %u\n", range); /* Prepare "coarse" limit command */ - value[0] = 0xf8; - value[1] = 0x00; /* Set later */ - value[2] = 0x00; - value[3] = 0x00; - value[4] = 0x00; - value[5] = 0x00; - value[6] = 0x00; + report->field[0]->value[0] = 0xf8; + report->field[0]->value[1] = 0x00; /* Set later */ + report->field[0]->value[2] = 0x00; + report->field[0]->value[3] = 0x00; + report->field[0]->value[4] = 0x00; + report->field[0]->value[5] = 0x00; + report->field[0]->value[6] = 0x00; if (range > 200) { report->field[0]->value[1] = 0x03; @@ -302,13 +240,13 @@ static void hid_lg4ff_set_range_dfp(struct hid_device *hid, __u16 range) usbhid_submit_report(hid, report, USB_DIR_OUT); /* Prepare "fine" limit command */ - value[0] = 0x81; - value[1] = 0x0b; - value[2] = 0x00; - value[3] = 0x00; - value[4] = 0x00; - value[5] = 0x00; - value[6] = 0x00; + report->field[0]->value[0] = 0x81; + report->field[0]->value[1] = 0x0b; + report->field[0]->value[2] = 0x00; + report->field[0]->value[3] = 0x00; + report->field[0]->value[4] = 0x00; + report->field[0]->value[5] = 0x00; + report->field[0]->value[6] = 0x00; if (range == 200 || range == 900) { /* Do not apply any fine limit */ usbhid_submit_report(hid, report, USB_DIR_OUT); @@ -319,11 +257,11 @@ static void hid_lg4ff_set_range_dfp(struct hid_device *hid, __u16 range) start_left = (((full_range - range + 1) * 2047) / full_range); start_right = 0xfff - start_left; - value[2] = start_left >> 4; - value[3] = start_right >> 4; - value[4] = 0xff; - value[5] = (start_right & 0xe) << 4 | (start_left & 0xe); - value[6] = 0xff; + report->field[0]->value[2] = start_left >> 4; + report->field[0]->value[3] = start_right >> 4; + report->field[0]->value[4] = 0xff; + report->field[0]->value[5] = (start_right & 0xe) << 4 | (start_left & 0xe); + report->field[0]->value[6] = 0xff; usbhid_submit_report(hid, report, USB_DIR_OUT); } @@ -406,15 +344,14 @@ static void lg4ff_set_leds(struct hid_device *hid, __u8 leds) { struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; struct hid_report *report = list_entry(report_list->next, struct hid_report, list); - __s32 *value = report->field[0]->value; - - value[0] = 0xf8; - value[1] = 0x12; - value[2] = leds; - value[3] = 0x00; - value[4] = 0x00; - value[5] = 0x00; - value[6] = 0x00; + + report->field[0]->value[0] = 0xf8; + report->field[0]->value[1] = 0x12; + report->field[0]->value[2] = leds; + report->field[0]->value[3] = 0x00; + report->field[0]->value[4] = 0x00; + report->field[0]->value[5] = 0x00; + report->field[0]->value[6] = 0x00; usbhid_submit_report(hid, report, USB_DIR_OUT); } @@ -423,7 +360,7 @@ static void lg4ff_led_set_brightness(struct led_classdev *led_cdev, { struct device *dev = led_cdev->dev->parent; struct hid_device *hid = container_of(dev, struct hid_device, dev); - struct lg_drv_data *drv_data = hid_get_drvdata(hid); + struct lg_drv_data *drv_data = (struct lg_drv_data *)hid_get_drvdata(hid); struct lg4ff_device_entry *entry; int i, state = 0; @@ -458,7 +395,7 @@ static enum led_brightness lg4ff_led_get_brightness(struct led_classdev *led_cde { struct device *dev = led_cdev->dev->parent; struct hid_device *hid = container_of(dev, struct hid_device, dev); - struct lg_drv_data *drv_data = hid_get_drvdata(hid); + struct lg_drv_data *drv_data = (struct lg_drv_data *)hid_get_drvdata(hid); struct lg4ff_device_entry *entry; int i, value = 0; @@ -564,7 +501,7 @@ int lg4ff_init(struct hid_device *hid) /* Check if autocentering is available and * set the centering force to zero by default */ if (test_bit(FF_AUTOCENTER, dev->ffbit)) { - if (rev_maj == FFEX_REV_MAJ && rev_min == FFEX_REV_MIN) /* Formula Force EX expects different autocentering command */ + if(rev_maj == FFEX_REV_MAJ && rev_min == FFEX_REV_MIN) /* Formula Force EX expects different autocentering command */ dev->ff->set_autocenter = hid_lg4ff_set_autocenter_ffex; else dev->ff->set_autocenter = hid_lg4ff_set_autocenter_default; @@ -587,7 +524,6 @@ int lg4ff_init(struct hid_device *hid) } drv_data->device_props = entry; - entry->product_id = lg4ff_devices[i].product_id; entry->min_range = lg4ff_devices[i].min_range; entry->max_range = lg4ff_devices[i].max_range; entry->set_range = lg4ff_devices[i].set_range; @@ -598,18 +534,6 @@ int lg4ff_init(struct hid_device *hid) return error; dbg_hid("sysfs interface created\n"); - /* Set default axes parameters */ - switch (lg4ff_devices[i].product_id) { - case USB_DEVICE_ID_LOGITECH_DFP_WHEEL: - dbg_hid("Setting axes parameters for Driving Force Pro\n"); - input_set_abs_params(dev, ABS_X, DFP_X_MIN, DFP_X_MAX, 0, 0); - input_set_abs_params(dev, ABS_Y, DFP_PEDAL_MIN, DFP_PEDAL_MAX, 0, 0); - input_set_abs_params(dev, ABS_RZ, DFP_PEDAL_MIN, DFP_PEDAL_MAX, 0, 0); - break; - default: - break; - } - /* Set the maximum range to start with */ entry->range = entry->max_range; if (entry->set_range != NULL) @@ -670,8 +594,6 @@ int lg4ff_init(struct hid_device *hid) return 0; } - - int lg4ff_deinit(struct hid_device *hid) { struct lg4ff_device_entry *entry; diff --git a/trunk/drivers/hid/hid-logitech-dj.c b/trunk/drivers/hid/hid-logitech-dj.c index 9500f2f3f8fe..0f9c146fc00d 100644 --- a/trunk/drivers/hid/hid-logitech-dj.c +++ b/trunk/drivers/hid/hid-logitech-dj.c @@ -193,7 +193,6 @@ static struct hid_ll_driver logi_dj_ll_driver; static int logi_dj_output_hidraw_report(struct hid_device *hid, u8 * buf, size_t count, unsigned char report_type); -static int logi_dj_recv_query_paired_devices(struct dj_receiver_dev *djrcv_dev); static void logi_dj_recv_destroy_djhid_device(struct dj_receiver_dev *djrcv_dev, struct dj_report *dj_report) @@ -234,7 +233,6 @@ static void logi_dj_recv_add_djhid_device(struct dj_receiver_dev *djrcv_dev, if (dj_report->report_params[DEVICE_PAIRED_PARAM_SPFUNCTION] & SPFUNCTION_DEVICE_LIST_EMPTY) { dbg_hid("%s: device list is empty\n", __func__); - djrcv_dev->querying_devices = false; return; } @@ -245,12 +243,6 @@ static void logi_dj_recv_add_djhid_device(struct dj_receiver_dev *djrcv_dev, return; } - if (djrcv_dev->paired_dj_devices[dj_report->device_index]) { - /* The device is already known. No need to reallocate it. */ - dbg_hid("%s: device is already known\n", __func__); - return; - } - dj_hiddev = hid_allocate_device(); if (IS_ERR(dj_hiddev)) { dev_err(&djrcv_hdev->dev, "%s: hid_allocate_device failed\n", @@ -314,7 +306,6 @@ static void delayedwork_callback(struct work_struct *work) struct dj_report dj_report; unsigned long flags; int count; - int retval; dbg_hid("%s\n", __func__); @@ -347,25 +338,6 @@ static void delayedwork_callback(struct work_struct *work) logi_dj_recv_destroy_djhid_device(djrcv_dev, &dj_report); break; default: - /* A normal report (i. e. not belonging to a pair/unpair notification) - * arriving here, means that the report arrived but we did not have a - * paired dj_device associated to the report's device_index, this - * means that the original "device paired" notification corresponding - * to this dj_device never arrived to this driver. The reason is that - * hid-core discards all packets coming from a device while probe() is - * executing. */ - if (!djrcv_dev->paired_dj_devices[dj_report.device_index]) { - /* ok, we don't know the device, just re-ask the - * receiver for the list of connected devices. */ - retval = logi_dj_recv_query_paired_devices(djrcv_dev); - if (!retval) { - /* everything went fine, so just leave */ - break; - } - dev_err(&djrcv_dev->hdev->dev, - "%s:logi_dj_recv_query_paired_devices " - "error:%d\n", __func__, retval); - } dbg_hid("%s: unexpected report type\n", __func__); } } @@ -396,12 +368,6 @@ static void logi_dj_recv_forward_null_report(struct dj_receiver_dev *djrcv_dev, if (!djdev) { dbg_hid("djrcv_dev->paired_dj_devices[dj_report->device_index]" " is NULL, index %d\n", dj_report->device_index); - kfifo_in(&djrcv_dev->notif_fifo, dj_report, sizeof(struct dj_report)); - - if (schedule_work(&djrcv_dev->work) == 0) { - dbg_hid("%s: did not schedule the work item, was already " - "queued\n", __func__); - } return; } @@ -432,12 +398,6 @@ static void logi_dj_recv_forward_report(struct dj_receiver_dev *djrcv_dev, if (dj_device == NULL) { dbg_hid("djrcv_dev->paired_dj_devices[dj_report->device_index]" " is NULL, index %d\n", dj_report->device_index); - kfifo_in(&djrcv_dev->notif_fifo, dj_report, sizeof(struct dj_report)); - - if (schedule_work(&djrcv_dev->work) == 0) { - dbg_hid("%s: did not schedule the work item, was already " - "queued\n", __func__); - } return; } @@ -479,11 +439,7 @@ static int logi_dj_recv_query_paired_devices(struct dj_receiver_dev *djrcv_dev) struct dj_report *dj_report; int retval; - /* no need to protect djrcv_dev->querying_devices */ - if (djrcv_dev->querying_devices) - return 0; - - dj_report = kzalloc(sizeof(struct dj_report), GFP_KERNEL); + dj_report = kzalloc(sizeof(dj_report), GFP_KERNEL); if (!dj_report) return -ENOMEM; dj_report->report_id = REPORT_ID_DJ_SHORT; @@ -494,14 +450,13 @@ static int logi_dj_recv_query_paired_devices(struct dj_receiver_dev *djrcv_dev) return retval; } - static int logi_dj_recv_switch_to_dj_mode(struct dj_receiver_dev *djrcv_dev, unsigned timeout) { struct dj_report *dj_report; int retval; - dj_report = kzalloc(sizeof(struct dj_report), GFP_KERNEL); + dj_report = kzalloc(sizeof(dj_report), GFP_KERNEL); if (!dj_report) return -ENOMEM; dj_report->report_id = REPORT_ID_DJ_SHORT; diff --git a/trunk/drivers/hid/hid-logitech-dj.h b/trunk/drivers/hid/hid-logitech-dj.h index 4a4000340ce1..fd28a5e0ca3b 100644 --- a/trunk/drivers/hid/hid-logitech-dj.h +++ b/trunk/drivers/hid/hid-logitech-dj.h @@ -101,7 +101,6 @@ struct dj_receiver_dev { struct work_struct work; struct kfifo notif_fifo; spinlock_t lock; - bool querying_devices; }; struct dj_device { diff --git a/trunk/drivers/hid/hid-magicmouse.c b/trunk/drivers/hid/hid-magicmouse.c index 25ddf3e3aec6..73647266daad 100644 --- a/trunk/drivers/hid/hid-magicmouse.c +++ b/trunk/drivers/hid/hid-magicmouse.c @@ -392,7 +392,7 @@ static int magicmouse_setup_input(struct input_dev *input, struct hid_device *hd __set_bit(EV_ABS, input->evbit); - error = input_mt_init_slots(input, 16, 0); + error = input_mt_init_slots(input, 16); if (error) return error; input_set_abs_params(input, ABS_MT_TOUCH_MAJOR, 0, 255 << 2, diff --git a/trunk/drivers/hid/hid-microsoft.c b/trunk/drivers/hid/hid-microsoft.c index 3acdcfcc17df..e5c699b6c6f3 100644 --- a/trunk/drivers/hid/hid-microsoft.c +++ b/trunk/drivers/hid/hid-microsoft.c @@ -5,6 +5,7 @@ * Copyright (c) 2000-2005 Vojtech Pavlik * Copyright (c) 2005 Michael Haboustak for Concept2, Inc * Copyright (c) 2006-2007 Jiri Kosina + * Copyright (c) 2007 Paul Walmsley * Copyright (c) 2008 Jiri Slaby */ diff --git a/trunk/drivers/hid/hid-monterey.c b/trunk/drivers/hid/hid-monterey.c index cd3643e06fa6..dedf757781ae 100644 --- a/trunk/drivers/hid/hid-monterey.c +++ b/trunk/drivers/hid/hid-monterey.c @@ -5,6 +5,7 @@ * Copyright (c) 2000-2005 Vojtech Pavlik * Copyright (c) 2005 Michael Haboustak for Concept2, Inc * Copyright (c) 2006-2007 Jiri Kosina + * Copyright (c) 2007 Paul Walmsley * Copyright (c) 2008 Jiri Slaby */ diff --git a/trunk/drivers/hid/hid-multitouch.c b/trunk/drivers/hid/hid-multitouch.c index 3eb02b94fc87..59c8b5c1d2de 100644 --- a/trunk/drivers/hid/hid-multitouch.c +++ b/trunk/drivers/hid/hid-multitouch.c @@ -51,12 +51,12 @@ MODULE_LICENSE("GPL"); #define MT_QUIRK_VALID_IS_INRANGE (1 << 5) #define MT_QUIRK_VALID_IS_CONFIDENCE (1 << 6) #define MT_QUIRK_SLOT_IS_CONTACTID_MINUS_ONE (1 << 8) -#define MT_QUIRK_NO_AREA (1 << 9) struct mt_slot { __s32 x, y, p, w, h; __s32 contactid; /* the device ContactID assigned to this slot */ bool touch_state; /* is the touch valid? */ + bool seen_in_this_frame;/* has this slot been updated */ }; struct mt_class { @@ -92,9 +92,8 @@ struct mt_device { __u8 touches_by_report; /* how many touches are present in one report: * 1 means we should use a serial protocol * > 1 means hybrid (multitouch) protocol */ - bool serial_maybe; /* need to check for serial protocol */ bool curvalid; /* is the current contact valid? */ - unsigned mt_flags; /* flags to pass to input-mt */ + struct mt_slot *slots; }; /* classes of device behavior */ @@ -116,9 +115,6 @@ struct mt_device { #define MT_CLS_EGALAX_SERIAL 0x0104 #define MT_CLS_TOPSEED 0x0105 #define MT_CLS_PANASONIC 0x0106 -#define MT_CLS_FLATFROG 0x0107 -#define MT_CLS_GENERALTOUCH_TWOFINGERS 0x0108 -#define MT_CLS_GENERALTOUCH_PWT_TENFINGERS 0x0109 #define MT_DEFAULT_MAXCONTACT 10 @@ -138,6 +134,25 @@ static int cypress_compute_slot(struct mt_device *td) return -1; } +static int find_slot_from_contactid(struct mt_device *td) +{ + int i; + for (i = 0; i < td->maxcontacts; ++i) { + if (td->slots[i].contactid == td->curdata.contactid && + td->slots[i].touch_state) + return i; + } + for (i = 0; i < td->maxcontacts; ++i) { + if (!td->slots[i].seen_in_this_frame && + !td->slots[i].touch_state) + return i; + } + /* should not occurs. If this happens that means + * that the device sent more touches that it says + * in the report descriptor. It is ignored then. */ + return -1; +} + static struct mt_class mt_classes[] = { { .name = MT_CLS_DEFAULT, .quirks = MT_QUIRK_NOT_SEEN_MEANS_UP }, @@ -175,9 +190,7 @@ static struct mt_class mt_classes[] = { MT_QUIRK_SLOT_IS_CONTACTID, .sn_move = 2048, .sn_width = 128, - .sn_height = 128, - .maxcontacts = 60, - }, + .sn_height = 128 }, { .name = MT_CLS_CYPRESS, .quirks = MT_QUIRK_NOT_SEEN_MEANS_UP | MT_QUIRK_CYPRESS, @@ -202,24 +215,7 @@ static struct mt_class mt_classes[] = { { .name = MT_CLS_PANASONIC, .quirks = MT_QUIRK_NOT_SEEN_MEANS_UP, .maxcontacts = 4 }, - { .name = MT_CLS_GENERALTOUCH_TWOFINGERS, - .quirks = MT_QUIRK_NOT_SEEN_MEANS_UP | - MT_QUIRK_VALID_IS_INRANGE | - MT_QUIRK_SLOT_IS_CONTACTNUMBER, - .maxcontacts = 2 - }, - { .name = MT_CLS_GENERALTOUCH_PWT_TENFINGERS, - .quirks = MT_QUIRK_NOT_SEEN_MEANS_UP | - MT_QUIRK_SLOT_IS_CONTACTNUMBER, - .maxcontacts = 10 - }, - { .name = MT_CLS_FLATFROG, - .quirks = MT_QUIRK_NOT_SEEN_MEANS_UP | - MT_QUIRK_NO_AREA, - .sn_move = 2048, - .maxcontacts = 40, - }, { } }; @@ -323,16 +319,24 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, * We need to ignore fields that belong to other collections * such as Mouse that might have the same GenericDesktop usages. */ if (field->application == HID_DG_TOUCHSCREEN) - td->mt_flags |= INPUT_MT_DIRECT; + set_bit(INPUT_PROP_DIRECT, hi->input->propbit); else if (field->application != HID_DG_TOUCHPAD) return 0; - /* - * Model touchscreens providing buttons as touchpads. + /* In case of an indirect device (touchpad), we need to add + * specific BTN_TOOL_* to be handled by the synaptics xorg + * driver. + * We also consider that touchscreens providing buttons are touchpads. */ if (field->application == HID_DG_TOUCHPAD || - (usage->hid & HID_USAGE_PAGE) == HID_UP_BUTTON) - td->mt_flags |= INPUT_MT_POINTER; + (usage->hid & HID_USAGE_PAGE) == HID_UP_BUTTON || + cls->is_indirect) { + set_bit(INPUT_PROP_POINTER, hi->input->propbit); + set_bit(BTN_TOOL_FINGER, hi->input->keybit); + set_bit(BTN_TOOL_DOUBLETAP, hi->input->keybit); + set_bit(BTN_TOOL_TRIPLETAP, hi->input->keybit); + set_bit(BTN_TOOL_QUADTAP, hi->input->keybit); + } /* eGalax devices provide a Digitizer.Stylus input which overrides * the correct Digitizers.Finger X/Y ranges. @@ -349,6 +353,8 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, EV_ABS, ABS_MT_POSITION_X); set_abs(hi->input, ABS_MT_POSITION_X, field, cls->sn_move); + /* touchscreen emulation */ + set_abs(hi->input, ABS_X, field, cls->sn_move); mt_store_field(usage, td, hi); td->last_field_index = field->index; return 1; @@ -357,6 +363,8 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, EV_ABS, ABS_MT_POSITION_Y); set_abs(hi->input, ABS_MT_POSITION_Y, field, cls->sn_move); + /* touchscreen emulation */ + set_abs(hi->input, ABS_Y, field, cls->sn_move); mt_store_field(usage, td, hi); td->last_field_index = field->index; return 1; @@ -380,6 +388,9 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, td->last_field_index = field->index; return 1; case HID_DG_CONTACTID: + if (!td->maxcontacts) + td->maxcontacts = MT_DEFAULT_MAXCONTACT; + input_mt_init_slots(hi->input, td->maxcontacts); mt_store_field(usage, td, hi); td->last_field_index = field->index; td->touches_by_report++; @@ -387,21 +398,18 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, case HID_DG_WIDTH: hid_map_usage(hi, usage, bit, max, EV_ABS, ABS_MT_TOUCH_MAJOR); - if (!(cls->quirks & MT_QUIRK_NO_AREA)) - set_abs(hi->input, ABS_MT_TOUCH_MAJOR, field, - cls->sn_width); + set_abs(hi->input, ABS_MT_TOUCH_MAJOR, field, + cls->sn_width); mt_store_field(usage, td, hi); td->last_field_index = field->index; return 1; case HID_DG_HEIGHT: hid_map_usage(hi, usage, bit, max, EV_ABS, ABS_MT_TOUCH_MINOR); - if (!(cls->quirks & MT_QUIRK_NO_AREA)) { - set_abs(hi->input, ABS_MT_TOUCH_MINOR, field, - cls->sn_height); - input_set_abs_params(hi->input, + set_abs(hi->input, ABS_MT_TOUCH_MINOR, field, + cls->sn_height); + input_set_abs_params(hi->input, ABS_MT_ORIENTATION, 0, 1, 0, 0); - } mt_store_field(usage, td, hi); td->last_field_index = field->index; return 1; @@ -410,6 +418,9 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, EV_ABS, ABS_MT_PRESSURE); set_abs(hi->input, ABS_MT_PRESSURE, field, cls->sn_pressure); + /* touchscreen emulation */ + set_abs(hi->input, ABS_PRESSURE, field, + cls->sn_pressure); mt_store_field(usage, td, hi); td->last_field_index = field->index; return 1; @@ -453,7 +464,7 @@ static int mt_input_mapped(struct hid_device *hdev, struct hid_input *hi, return -1; } -static int mt_compute_slot(struct mt_device *td, struct input_dev *input) +static int mt_compute_slot(struct mt_device *td) { __s32 quirks = td->mtclass.quirks; @@ -469,23 +480,42 @@ static int mt_compute_slot(struct mt_device *td, struct input_dev *input) if (quirks & MT_QUIRK_SLOT_IS_CONTACTID_MINUS_ONE) return td->curdata.contactid - 1; - return input_mt_get_slot_by_key(input, td->curdata.contactid); + return find_slot_from_contactid(td); } /* * this function is called when a whole contact has been processed, * so that it can assign it to a slot and store the data there */ -static void mt_complete_slot(struct mt_device *td, struct input_dev *input) +static void mt_complete_slot(struct mt_device *td) { + td->curdata.seen_in_this_frame = true; if (td->curvalid) { - int slotnum = mt_compute_slot(td, input); - struct mt_slot *s = &td->curdata; + int slotnum = mt_compute_slot(td); + + if (slotnum >= 0 && slotnum < td->maxcontacts) + td->slots[slotnum] = td->curdata; + } + td->num_received++; +} - if (slotnum < 0 || slotnum >= td->maxcontacts) - return; - input_mt_slot(input, slotnum); +/* + * this function is called when a whole packet has been received and processed, + * so that it can decide what to send to the input layer. + */ +static void mt_emit_event(struct mt_device *td, struct input_dev *input) +{ + int i; + + for (i = 0; i < td->maxcontacts; ++i) { + struct mt_slot *s = &(td->slots[i]); + if ((td->mtclass.quirks & MT_QUIRK_NOT_SEEN_MEANS_UP) && + !s->seen_in_this_frame) { + s->touch_state = false; + } + + input_mt_slot(input, i); input_mt_report_slot_state(input, MT_TOOL_FINGER, s->touch_state); if (s->touch_state) { @@ -502,29 +532,24 @@ static void mt_complete_slot(struct mt_device *td, struct input_dev *input) input_event(input, EV_ABS, ABS_MT_TOUCH_MAJOR, major); input_event(input, EV_ABS, ABS_MT_TOUCH_MINOR, minor); } - } + s->seen_in_this_frame = false; - td->num_received++; -} + } -/* - * this function is called when a whole packet has been received and processed, - * so that it can decide what to send to the input layer. - */ -static void mt_sync_frame(struct mt_device *td, struct input_dev *input) -{ - input_mt_sync_frame(input); + input_mt_report_pointer_emulation(input, true); input_sync(input); td->num_received = 0; } + + static int mt_event(struct hid_device *hid, struct hid_field *field, struct hid_usage *usage, __s32 value) { struct mt_device *td = hid_get_drvdata(hid); __s32 quirks = td->mtclass.quirks; - if (hid->claimed & HID_CLAIMED_INPUT) { + if (hid->claimed & HID_CLAIMED_INPUT && td->slots) { switch (usage->hid) { case HID_DG_INRANGE: if (quirks & MT_QUIRK_ALWAYS_VALID) @@ -577,11 +602,11 @@ static int mt_event(struct hid_device *hid, struct hid_field *field, } if (usage->hid == td->last_slot_field) - mt_complete_slot(td, field->hidinput->input); + mt_complete_slot(td); if (field->index == td->last_field_index && td->num_received >= td->num_expected) - mt_sync_frame(td, field->hidinput->input); + mt_emit_event(td, field->hidinput->input); } @@ -660,45 +685,18 @@ static void mt_post_parse(struct mt_device *td) } } -static void mt_input_configured(struct hid_device *hdev, struct hid_input *hi) - -{ - struct mt_device *td = hid_get_drvdata(hdev); - struct mt_class *cls = &td->mtclass; - struct input_dev *input = hi->input; - - /* Only initialize slots for MT input devices */ - if (!test_bit(ABS_MT_POSITION_X, input->absbit)) - return; - - if (!td->maxcontacts) - td->maxcontacts = MT_DEFAULT_MAXCONTACT; - - mt_post_parse(td); - if (td->serial_maybe) - mt_post_parse_default_settings(td); - - if (cls->is_indirect) - td->mt_flags |= INPUT_MT_POINTER; - - if (cls->quirks & MT_QUIRK_NOT_SEEN_MEANS_UP) - td->mt_flags |= INPUT_MT_DROP_UNUSED; - - input_mt_init_slots(input, td->maxcontacts, td->mt_flags); - - td->mt_flags = 0; -} - static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id) { int ret, i; struct mt_device *td; struct mt_class *mtclass = mt_classes; /* MT_CLS_DEFAULT */ - for (i = 0; mt_classes[i].name ; i++) { - if (id->driver_data == mt_classes[i].name) { - mtclass = &(mt_classes[i]); - break; + if (id) { + for (i = 0; mt_classes[i].name ; i++) { + if (id->driver_data == mt_classes[i].name) { + mtclass = &(mt_classes[i]); + break; + } } } @@ -724,9 +722,6 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id) goto fail; } - if (id->vendor == HID_ANY_ID && id->product == HID_ANY_ID) - td->serial_maybe = true; - ret = hid_parse(hdev); if (ret != 0) goto fail; @@ -735,6 +730,20 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id) if (ret) goto fail; + mt_post_parse(td); + + if (id->vendor == HID_ANY_ID && id->product == HID_ANY_ID) + mt_post_parse_default_settings(td); + + td->slots = kzalloc(td->maxcontacts * sizeof(struct mt_slot), + GFP_KERNEL); + if (!td->slots) { + dev_err(&hdev->dev, "cannot allocate multitouch slots\n"); + hid_hw_stop(hdev); + ret = -ENOMEM; + goto fail; + } + ret = sysfs_create_group(&hdev->dev.kobj, &mt_attribute_group); mt_set_maxcontacts(hdev); @@ -758,32 +767,6 @@ static int mt_reset_resume(struct hid_device *hdev) mt_set_input_mode(hdev); return 0; } - -static int mt_resume(struct hid_device *hdev) -{ - struct usb_interface *intf; - struct usb_host_interface *interface; - struct usb_device *dev; - - if (hdev->bus != BUS_USB) - return 0; - - intf = to_usb_interface(hdev->dev.parent); - interface = intf->cur_altsetting; - dev = hid_to_usb_dev(hdev); - - /* Some Elan legacy devices require SET_IDLE to be set on resume. - * It should be safe to send it to other devices too. - * Tested on 3M, Stantum, Cypress, Zytronic, eGalax, and Elan panels. */ - - usb_control_msg(dev, usb_sndctrlpipe(dev, 0), - HID_REQ_SET_IDLE, - USB_TYPE_CLASS | USB_RECIP_INTERFACE, - 0, interface->desc.bInterfaceNumber, - NULL, 0, USB_CTRL_SET_TIMEOUT); - - return 0; -} #endif static void mt_remove(struct hid_device *hdev) @@ -791,6 +774,7 @@ static void mt_remove(struct hid_device *hdev) struct mt_device *td = hid_get_drvdata(hdev); sysfs_remove_group(&hdev->dev.kobj, &mt_attribute_group); hid_hw_stop(hdev); + kfree(td->slots); kfree(td); hid_set_drvdata(hdev, NULL); } @@ -899,39 +883,19 @@ static const struct hid_device_id mt_devices[] = { { .driver_data = MT_CLS_EGALAX_SERIAL, MT_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_7349) }, - { .driver_data = MT_CLS_EGALAX_SERIAL, - MT_USB_DEVICE(USB_VENDOR_ID_DWAV, - USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_73F7) }, { .driver_data = MT_CLS_EGALAX_SERIAL, MT_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_A001) }, - { .driver_data = MT_CLS_EGALAX, - HID_USB_DEVICE(USB_VENDOR_ID_DWAV, - USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_7224) }, - { .driver_data = MT_CLS_EGALAX, - HID_USB_DEVICE(USB_VENDOR_ID_DWAV, - USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_72D0) }, - { .driver_data = MT_CLS_EGALAX, - HID_USB_DEVICE(USB_VENDOR_ID_DWAV, - USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_72C4) }, /* Elo TouchSystems IntelliTouch Plus panel */ { .driver_data = MT_CLS_DUAL_NSMU_CONTACTID, MT_USB_DEVICE(USB_VENDOR_ID_ELO, USB_DEVICE_ID_ELO_TS2515) }, - /* Flatfrog Panels */ - { .driver_data = MT_CLS_FLATFROG, - MT_USB_DEVICE(USB_VENDOR_ID_FLATFROG, - USB_DEVICE_ID_MULTITOUCH_3200) }, - /* GeneralTouch panel */ - { .driver_data = MT_CLS_GENERALTOUCH_TWOFINGERS, + { .driver_data = MT_CLS_DUAL_INRANGE_CONTACTNUMBER, MT_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, USB_DEVICE_ID_GENERAL_TOUCH_WIN7_TWOFINGERS) }, - { .driver_data = MT_CLS_GENERALTOUCH_PWT_TENFINGERS, - MT_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, - USB_DEVICE_ID_GENERAL_TOUCH_WIN8_PWT_TENFINGERS) }, /* Gametel game controller */ { .driver_data = MT_CLS_DEFAULT, @@ -1123,13 +1087,11 @@ static struct hid_driver mt_driver = { .remove = mt_remove, .input_mapping = mt_input_mapping, .input_mapped = mt_input_mapped, - .input_configured = mt_input_configured, .feature_mapping = mt_feature_mapping, .usage_table = mt_grabbed_usages, .event = mt_event, #ifdef CONFIG_PM .reset_resume = mt_reset_resume, - .resume = mt_resume, #endif }; diff --git a/trunk/drivers/hid/hid-ntrig.c b/trunk/drivers/hid/hid-ntrig.c index 86a969f63292..9fae2ebdd758 100644 --- a/trunk/drivers/hid/hid-ntrig.c +++ b/trunk/drivers/hid/hid-ntrig.c @@ -882,10 +882,10 @@ static int ntrig_probe(struct hid_device *hdev, const struct hid_device_id *id) nd->activate_slack = activate_slack; nd->act_state = activate_slack; nd->deactivate_slack = -deactivate_slack; - nd->sensor_logical_width = 1; - nd->sensor_logical_height = 1; - nd->sensor_physical_width = 1; - nd->sensor_physical_height = 1; + nd->sensor_logical_width = 0; + nd->sensor_logical_height = 0; + nd->sensor_physical_width = 0; + nd->sensor_physical_height = 0; hid_set_drvdata(hdev, nd); diff --git a/trunk/drivers/hid/hid-petalynx.c b/trunk/drivers/hid/hid-petalynx.c index 4c521de4e7e6..f1ea3ff8a98d 100644 --- a/trunk/drivers/hid/hid-petalynx.c +++ b/trunk/drivers/hid/hid-petalynx.c @@ -5,6 +5,7 @@ * Copyright (c) 2000-2005 Vojtech Pavlik * Copyright (c) 2005 Michael Haboustak for Concept2, Inc * Copyright (c) 2006-2007 Jiri Kosina + * Copyright (c) 2007 Paul Walmsley * Copyright (c) 2008 Jiri Slaby */ diff --git a/trunk/drivers/hid/hid-picolcd.c b/trunk/drivers/hid/hid-picolcd.c new file mode 100644 index 000000000000..27c8ebdfad01 --- /dev/null +++ b/trunk/drivers/hid/hid-picolcd.c @@ -0,0 +1,2748 @@ +/*************************************************************************** + * Copyright (C) 2010 by Bruno Prémont * + * * + * Based on Logitech G13 driver (v0.4) * + * Copyright (C) 2009 by Rick L. Vinyard, Jr. * + * * + * 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 driver 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 software. If not see . * + ***************************************************************************/ + +#include +#include +#include +#include "hid-ids.h" +#include "usbhid/usbhid.h" +#include + +#include +#include +#include +#include + +#include + +#include +#include + +#include +#include +#include + +#define PICOLCD_NAME "PicoLCD (graphic)" + +/* Report numbers */ +#define REPORT_ERROR_CODE 0x10 /* LCD: IN[16] */ +#define ERR_SUCCESS 0x00 +#define ERR_PARAMETER_MISSING 0x01 +#define ERR_DATA_MISSING 0x02 +#define ERR_BLOCK_READ_ONLY 0x03 +#define ERR_BLOCK_NOT_ERASABLE 0x04 +#define ERR_BLOCK_TOO_BIG 0x05 +#define ERR_SECTION_OVERFLOW 0x06 +#define ERR_INVALID_CMD_LEN 0x07 +#define ERR_INVALID_DATA_LEN 0x08 +#define REPORT_KEY_STATE 0x11 /* LCD: IN[2] */ +#define REPORT_IR_DATA 0x21 /* LCD: IN[63] */ +#define REPORT_EE_DATA 0x32 /* LCD: IN[63] */ +#define REPORT_MEMORY 0x41 /* LCD: IN[63] */ +#define REPORT_LED_STATE 0x81 /* LCD: OUT[1] */ +#define REPORT_BRIGHTNESS 0x91 /* LCD: OUT[1] */ +#define REPORT_CONTRAST 0x92 /* LCD: OUT[1] */ +#define REPORT_RESET 0x93 /* LCD: OUT[2] */ +#define REPORT_LCD_CMD 0x94 /* LCD: OUT[63] */ +#define REPORT_LCD_DATA 0x95 /* LCD: OUT[63] */ +#define REPORT_LCD_CMD_DATA 0x96 /* LCD: OUT[63] */ +#define REPORT_EE_READ 0xa3 /* LCD: OUT[63] */ +#define REPORT_EE_WRITE 0xa4 /* LCD: OUT[63] */ +#define REPORT_ERASE_MEMORY 0xb2 /* LCD: OUT[2] */ +#define REPORT_READ_MEMORY 0xb3 /* LCD: OUT[3] */ +#define REPORT_WRITE_MEMORY 0xb4 /* LCD: OUT[63] */ +#define REPORT_SPLASH_RESTART 0xc1 /* LCD: OUT[1] */ +#define REPORT_EXIT_KEYBOARD 0xef /* LCD: OUT[2] */ +#define REPORT_VERSION 0xf1 /* LCD: IN[2],OUT[1] Bootloader: IN[2],OUT[1] */ +#define REPORT_BL_ERASE_MEMORY 0xf2 /* Bootloader: IN[36],OUT[4] */ +#define REPORT_BL_READ_MEMORY 0xf3 /* Bootloader: IN[36],OUT[4] */ +#define REPORT_BL_WRITE_MEMORY 0xf4 /* Bootloader: IN[36],OUT[36] */ +#define REPORT_DEVID 0xf5 /* LCD: IN[5], OUT[1] Bootloader: IN[5],OUT[1] */ +#define REPORT_SPLASH_SIZE 0xf6 /* LCD: IN[4], OUT[1] */ +#define REPORT_HOOK_VERSION 0xf7 /* LCD: IN[2], OUT[1] */ +#define REPORT_EXIT_FLASHER 0xff /* Bootloader: OUT[2] */ + +#ifdef CONFIG_HID_PICOLCD_FB +/* Framebuffer + * + * The PicoLCD use a Topway LCD module of 256x64 pixel + * This display area is tiled over 4 controllers with 8 tiles + * each. Each tile has 8x64 pixel, each data byte representing + * a 1-bit wide vertical line of the tile. + * + * The display can be updated at a tile granularity. + * + * Chip 1 Chip 2 Chip 3 Chip 4 + * +----------------+----------------+----------------+----------------+ + * | Tile 1 | Tile 1 | Tile 1 | Tile 1 | + * +----------------+----------------+----------------+----------------+ + * | Tile 2 | Tile 2 | Tile 2 | Tile 2 | + * +----------------+----------------+----------------+----------------+ + * ... + * +----------------+----------------+----------------+----------------+ + * | Tile 8 | Tile 8 | Tile 8 | Tile 8 | + * +----------------+----------------+----------------+----------------+ + */ +#define PICOLCDFB_NAME "picolcdfb" +#define PICOLCDFB_WIDTH (256) +#define PICOLCDFB_HEIGHT (64) +#define PICOLCDFB_SIZE (PICOLCDFB_WIDTH * PICOLCDFB_HEIGHT / 8) + +#define PICOLCDFB_UPDATE_RATE_LIMIT 10 +#define PICOLCDFB_UPDATE_RATE_DEFAULT 2 + +/* Framebuffer visual structures */ +static const struct fb_fix_screeninfo picolcdfb_fix = { + .id = PICOLCDFB_NAME, + .type = FB_TYPE_PACKED_PIXELS, + .visual = FB_VISUAL_MONO01, + .xpanstep = 0, + .ypanstep = 0, + .ywrapstep = 0, + .line_length = PICOLCDFB_WIDTH / 8, + .accel = FB_ACCEL_NONE, +}; + +static const struct fb_var_screeninfo picolcdfb_var = { + .xres = PICOLCDFB_WIDTH, + .yres = PICOLCDFB_HEIGHT, + .xres_virtual = PICOLCDFB_WIDTH, + .yres_virtual = PICOLCDFB_HEIGHT, + .width = 103, + .height = 26, + .bits_per_pixel = 1, + .grayscale = 1, + .red = { + .offset = 0, + .length = 1, + .msb_right = 0, + }, + .green = { + .offset = 0, + .length = 1, + .msb_right = 0, + }, + .blue = { + .offset = 0, + .length = 1, + .msb_right = 0, + }, + .transp = { + .offset = 0, + .length = 0, + .msb_right = 0, + }, +}; +#endif /* CONFIG_HID_PICOLCD_FB */ + +/* Input device + * + * The PicoLCD has an IR receiver header, a built-in keypad with 5 keys + * and header for 4x4 key matrix. The built-in keys are part of the matrix. + */ +static const unsigned short def_keymap[] = { + KEY_RESERVED, /* none */ + KEY_BACK, /* col 4 + row 1 */ + KEY_HOMEPAGE, /* col 3 + row 1 */ + KEY_RESERVED, /* col 2 + row 1 */ + KEY_RESERVED, /* col 1 + row 1 */ + KEY_SCROLLUP, /* col 4 + row 2 */ + KEY_OK, /* col 3 + row 2 */ + KEY_SCROLLDOWN, /* col 2 + row 2 */ + KEY_RESERVED, /* col 1 + row 2 */ + KEY_RESERVED, /* col 4 + row 3 */ + KEY_RESERVED, /* col 3 + row 3 */ + KEY_RESERVED, /* col 2 + row 3 */ + KEY_RESERVED, /* col 1 + row 3 */ + KEY_RESERVED, /* col 4 + row 4 */ + KEY_RESERVED, /* col 3 + row 4 */ + KEY_RESERVED, /* col 2 + row 4 */ + KEY_RESERVED, /* col 1 + row 4 */ +}; +#define PICOLCD_KEYS ARRAY_SIZE(def_keymap) + +/* Description of in-progress IO operation, used for operations + * that trigger response from device */ +struct picolcd_pending { + struct hid_report *out_report; + struct hid_report *in_report; + struct completion ready; + int raw_size; + u8 raw_data[64]; +}; + +/* Per device data structure */ +struct picolcd_data { + struct hid_device *hdev; +#ifdef CONFIG_DEBUG_FS + struct dentry *debug_reset; + struct dentry *debug_eeprom; + struct dentry *debug_flash; + struct mutex mutex_flash; + int addr_sz; +#endif + u8 version[2]; + unsigned short opmode_delay; + /* input stuff */ + u8 pressed_keys[2]; + struct input_dev *input_keys; + struct input_dev *input_cir; + unsigned short keycode[PICOLCD_KEYS]; + +#ifdef CONFIG_HID_PICOLCD_FB + /* Framebuffer stuff */ + u8 fb_update_rate; + u8 fb_bpp; + u8 fb_force; + u8 *fb_vbitmap; /* local copy of what was sent to PicoLCD */ + u8 *fb_bitmap; /* framebuffer */ + struct fb_info *fb_info; + struct fb_deferred_io fb_defio; +#endif /* CONFIG_HID_PICOLCD_FB */ +#ifdef CONFIG_HID_PICOLCD_LCD + struct lcd_device *lcd; + u8 lcd_contrast; +#endif /* CONFIG_HID_PICOLCD_LCD */ +#ifdef CONFIG_HID_PICOLCD_BACKLIGHT + struct backlight_device *backlight; + u8 lcd_brightness; + u8 lcd_power; +#endif /* CONFIG_HID_PICOLCD_BACKLIGHT */ +#ifdef CONFIG_HID_PICOLCD_LEDS + /* LED stuff */ + u8 led_state; + struct led_classdev *led[8]; +#endif /* CONFIG_HID_PICOLCD_LEDS */ + + /* Housekeeping stuff */ + spinlock_t lock; + struct mutex mutex; + struct picolcd_pending *pending; + int status; +#define PICOLCD_BOOTLOADER 1 +#define PICOLCD_FAILED 2 +#define PICOLCD_READY_FB 4 +}; + + +/* Find a given report */ +#define picolcd_in_report(id, dev) picolcd_report(id, dev, HID_INPUT_REPORT) +#define picolcd_out_report(id, dev) picolcd_report(id, dev, HID_OUTPUT_REPORT) + +static struct hid_report *picolcd_report(int id, struct hid_device *hdev, int dir) +{ + struct list_head *feature_report_list = &hdev->report_enum[dir].report_list; + struct hid_report *report = NULL; + + list_for_each_entry(report, feature_report_list, list) { + if (report->id == id) + return report; + } + hid_warn(hdev, "No report with id 0x%x found\n", id); + return NULL; +} + +#ifdef CONFIG_DEBUG_FS +static void picolcd_debug_out_report(struct picolcd_data *data, + struct hid_device *hdev, struct hid_report *report); +#define usbhid_submit_report(a, b, c) \ + do { \ + picolcd_debug_out_report(hid_get_drvdata(a), a, b); \ + usbhid_submit_report(a, b, c); \ + } while (0) +#endif + +/* Submit a report and wait for a reply from device - if device fades away + * or does not respond in time, return NULL */ +static struct picolcd_pending *picolcd_send_and_wait(struct hid_device *hdev, + int report_id, const u8 *raw_data, int size) +{ + struct picolcd_data *data = hid_get_drvdata(hdev); + struct picolcd_pending *work; + struct hid_report *report = picolcd_out_report(report_id, hdev); + unsigned long flags; + int i, j, k; + + if (!report || !data) + return NULL; + if (data->status & PICOLCD_FAILED) + return NULL; + work = kzalloc(sizeof(*work), GFP_KERNEL); + if (!work) + return NULL; + + init_completion(&work->ready); + work->out_report = report; + work->in_report = NULL; + work->raw_size = 0; + + mutex_lock(&data->mutex); + spin_lock_irqsave(&data->lock, flags); + for (i = k = 0; i < report->maxfield; i++) + for (j = 0; j < report->field[i]->report_count; j++) { + hid_set_field(report->field[i], j, k < size ? raw_data[k] : 0); + k++; + } + data->pending = work; + usbhid_submit_report(data->hdev, report, USB_DIR_OUT); + spin_unlock_irqrestore(&data->lock, flags); + wait_for_completion_interruptible_timeout(&work->ready, HZ*2); + spin_lock_irqsave(&data->lock, flags); + data->pending = NULL; + spin_unlock_irqrestore(&data->lock, flags); + mutex_unlock(&data->mutex); + return work; +} + +#ifdef CONFIG_HID_PICOLCD_FB +/* Send a given tile to PicoLCD */ +static int picolcd_fb_send_tile(struct hid_device *hdev, int chip, int tile) +{ + struct picolcd_data *data = hid_get_drvdata(hdev); + struct hid_report *report1 = picolcd_out_report(REPORT_LCD_CMD_DATA, hdev); + struct hid_report *report2 = picolcd_out_report(REPORT_LCD_DATA, hdev); + unsigned long flags; + u8 *tdata; + int i; + + if (!report1 || report1->maxfield != 1 || !report2 || report2->maxfield != 1) + return -ENODEV; + + spin_lock_irqsave(&data->lock, flags); + hid_set_field(report1->field[0], 0, chip << 2); + hid_set_field(report1->field[0], 1, 0x02); + hid_set_field(report1->field[0], 2, 0x00); + hid_set_field(report1->field[0], 3, 0x00); + hid_set_field(report1->field[0], 4, 0xb8 | tile); + hid_set_field(report1->field[0], 5, 0x00); + hid_set_field(report1->field[0], 6, 0x00); + hid_set_field(report1->field[0], 7, 0x40); + hid_set_field(report1->field[0], 8, 0x00); + hid_set_field(report1->field[0], 9, 0x00); + hid_set_field(report1->field[0], 10, 32); + + hid_set_field(report2->field[0], 0, (chip << 2) | 0x01); + hid_set_field(report2->field[0], 1, 0x00); + hid_set_field(report2->field[0], 2, 0x00); + hid_set_field(report2->field[0], 3, 32); + + tdata = data->fb_vbitmap + (tile * 4 + chip) * 64; + for (i = 0; i < 64; i++) + if (i < 32) + hid_set_field(report1->field[0], 11 + i, tdata[i]); + else + hid_set_field(report2->field[0], 4 + i - 32, tdata[i]); + + usbhid_submit_report(data->hdev, report1, USB_DIR_OUT); + usbhid_submit_report(data->hdev, report2, USB_DIR_OUT); + spin_unlock_irqrestore(&data->lock, flags); + return 0; +} + +/* Translate a single tile*/ +static int picolcd_fb_update_tile(u8 *vbitmap, const u8 *bitmap, int bpp, + int chip, int tile) +{ + int i, b, changed = 0; + u8 tdata[64]; + u8 *vdata = vbitmap + (tile * 4 + chip) * 64; + + if (bpp == 1) { + for (b = 7; b >= 0; b--) { + const u8 *bdata = bitmap + tile * 256 + chip * 8 + b * 32; + for (i = 0; i < 64; i++) { + tdata[i] <<= 1; + tdata[i] |= (bdata[i/8] >> (i % 8)) & 0x01; + } + } + } else if (bpp == 8) { + for (b = 7; b >= 0; b--) { + const u8 *bdata = bitmap + (tile * 256 + chip * 8 + b * 32) * 8; + for (i = 0; i < 64; i++) { + tdata[i] <<= 1; + tdata[i] |= (bdata[i] & 0x80) ? 0x01 : 0x00; + } + } + } else { + /* Oops, we should never get here! */ + WARN_ON(1); + return 0; + } + + for (i = 0; i < 64; i++) + if (tdata[i] != vdata[i]) { + changed = 1; + vdata[i] = tdata[i]; + } + return changed; +} + +/* Reconfigure LCD display */ +static int picolcd_fb_reset(struct picolcd_data *data, int clear) +{ + struct hid_report *report = picolcd_out_report(REPORT_LCD_CMD, data->hdev); + int i, j; + unsigned long flags; + static const u8 mapcmd[8] = { 0x00, 0x02, 0x00, 0x64, 0x3f, 0x00, 0x64, 0xc0 }; + + if (!report || report->maxfield != 1) + return -ENODEV; + + spin_lock_irqsave(&data->lock, flags); + for (i = 0; i < 4; i++) { + for (j = 0; j < report->field[0]->maxusage; j++) + if (j == 0) + hid_set_field(report->field[0], j, i << 2); + else if (j < sizeof(mapcmd)) + hid_set_field(report->field[0], j, mapcmd[j]); + else + hid_set_field(report->field[0], j, 0); + usbhid_submit_report(data->hdev, report, USB_DIR_OUT); + } + + data->status |= PICOLCD_READY_FB; + spin_unlock_irqrestore(&data->lock, flags); + + if (data->fb_bitmap) { + if (clear) { + memset(data->fb_vbitmap, 0, PICOLCDFB_SIZE); + memset(data->fb_bitmap, 0, PICOLCDFB_SIZE*data->fb_bpp); + } + data->fb_force = 1; + } + + /* schedule first output of framebuffer */ + if (data->fb_info) + schedule_delayed_work(&data->fb_info->deferred_work, 0); + + return 0; +} + +/* Update fb_vbitmap from the screen_base and send changed tiles to device */ +static void picolcd_fb_update(struct picolcd_data *data) +{ + int chip, tile, n; + unsigned long flags; + + if (!data) + return; + + spin_lock_irqsave(&data->lock, flags); + if (!(data->status & PICOLCD_READY_FB)) { + spin_unlock_irqrestore(&data->lock, flags); + picolcd_fb_reset(data, 0); + } else { + spin_unlock_irqrestore(&data->lock, flags); + } + + /* + * Translate the framebuffer into the format needed by the PicoLCD. + * See display layout above. + * Do this one tile after the other and push those tiles that changed. + * + * Wait for our IO to complete as otherwise we might flood the queue! + */ + n = 0; + for (chip = 0; chip < 4; chip++) + for (tile = 0; tile < 8; tile++) + if (picolcd_fb_update_tile(data->fb_vbitmap, + data->fb_bitmap, data->fb_bpp, chip, tile) || + data->fb_force) { + n += 2; + if (!data->fb_info->par) + return; /* device lost! */ + if (n >= HID_OUTPUT_FIFO_SIZE / 2) { + usbhid_wait_io(data->hdev); + n = 0; + } + picolcd_fb_send_tile(data->hdev, chip, tile); + } + data->fb_force = false; + if (n) + usbhid_wait_io(data->hdev); +} + +/* Stub to call the system default and update the image on the picoLCD */ +static void picolcd_fb_fillrect(struct fb_info *info, + const struct fb_fillrect *rect) +{ + if (!info->par) + return; + sys_fillrect(info, rect); + + schedule_delayed_work(&info->deferred_work, 0); +} + +/* Stub to call the system default and update the image on the picoLCD */ +static void picolcd_fb_copyarea(struct fb_info *info, + const struct fb_copyarea *area) +{ + if (!info->par) + return; + sys_copyarea(info, area); + + schedule_delayed_work(&info->deferred_work, 0); +} + +/* Stub to call the system default and update the image on the picoLCD */ +static void picolcd_fb_imageblit(struct fb_info *info, const struct fb_image *image) +{ + if (!info->par) + return; + sys_imageblit(info, image); + + schedule_delayed_work(&info->deferred_work, 0); +} + +/* + * this is the slow path from userspace. they can seek and write to + * the fb. it's inefficient to do anything less than a full screen draw + */ +static ssize_t picolcd_fb_write(struct fb_info *info, const char __user *buf, + size_t count, loff_t *ppos) +{ + ssize_t ret; + if (!info->par) + return -ENODEV; + ret = fb_sys_write(info, buf, count, ppos); + if (ret >= 0) + schedule_delayed_work(&info->deferred_work, 0); + return ret; +} + +static int picolcd_fb_blank(int blank, struct fb_info *info) +{ + if (!info->par) + return -ENODEV; + /* We let fb notification do this for us via lcd/backlight device */ + return 0; +} + +static void picolcd_fb_destroy(struct fb_info *info) +{ + struct picolcd_data *data = info->par; + u32 *ref_cnt = info->pseudo_palette; + int may_release; + + info->par = NULL; + if (data) + data->fb_info = NULL; + fb_deferred_io_cleanup(info); + + ref_cnt--; + mutex_lock(&info->lock); + (*ref_cnt)--; + may_release = !*ref_cnt; + mutex_unlock(&info->lock); + if (may_release) { + vfree((u8 *)info->fix.smem_start); + framebuffer_release(info); + } +} + +static int picolcd_fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) +{ + __u32 bpp = var->bits_per_pixel; + __u32 activate = var->activate; + + /* only allow 1/8 bit depth (8-bit is grayscale) */ + *var = picolcdfb_var; + var->activate = activate; + if (bpp >= 8) { + var->bits_per_pixel = 8; + var->red.length = 8; + var->green.length = 8; + var->blue.length = 8; + } else { + var->bits_per_pixel = 1; + var->red.length = 1; + var->green.length = 1; + var->blue.length = 1; + } + return 0; +} + +static int picolcd_set_par(struct fb_info *info) +{ + struct picolcd_data *data = info->par; + u8 *tmp_fb, *o_fb; + if (!data) + return -ENODEV; + if (info->var.bits_per_pixel == data->fb_bpp) + return 0; + /* switch between 1/8 bit depths */ + if (info->var.bits_per_pixel != 1 && info->var.bits_per_pixel != 8) + return -EINVAL; + + o_fb = data->fb_bitmap; + tmp_fb = kmalloc(PICOLCDFB_SIZE*info->var.bits_per_pixel, GFP_KERNEL); + if (!tmp_fb) + return -ENOMEM; + + /* translate FB content to new bits-per-pixel */ + if (info->var.bits_per_pixel == 1) { + int i, b; + for (i = 0; i < PICOLCDFB_SIZE; i++) { + u8 p = 0; + for (b = 0; b < 8; b++) { + p <<= 1; + p |= o_fb[i*8+b] ? 0x01 : 0x00; + } + tmp_fb[i] = p; + } + memcpy(o_fb, tmp_fb, PICOLCDFB_SIZE); + info->fix.visual = FB_VISUAL_MONO01; + info->fix.line_length = PICOLCDFB_WIDTH / 8; + } else { + int i; + memcpy(tmp_fb, o_fb, PICOLCDFB_SIZE); + for (i = 0; i < PICOLCDFB_SIZE * 8; i++) + o_fb[i] = tmp_fb[i/8] & (0x01 << (7 - i % 8)) ? 0xff : 0x00; + info->fix.visual = FB_VISUAL_DIRECTCOLOR; + info->fix.line_length = PICOLCDFB_WIDTH; + } + + kfree(tmp_fb); + data->fb_bpp = info->var.bits_per_pixel; + return 0; +} + +/* Do refcounting on our FB and cleanup per worker if FB is + * closed after unplug of our device + * (fb_release holds info->lock and still touches info after + * we return so we can't release it immediately. + */ +struct picolcd_fb_cleanup_item { + struct fb_info *info; + struct picolcd_fb_cleanup_item *next; +}; +static struct picolcd_fb_cleanup_item *fb_pending; +static DEFINE_SPINLOCK(fb_pending_lock); + +static void picolcd_fb_do_cleanup(struct work_struct *data) +{ + struct picolcd_fb_cleanup_item *item; + unsigned long flags; + + do { + spin_lock_irqsave(&fb_pending_lock, flags); + item = fb_pending; + fb_pending = item ? item->next : NULL; + spin_unlock_irqrestore(&fb_pending_lock, flags); + + if (item) { + u8 *fb = (u8 *)item->info->fix.smem_start; + /* make sure we do not race against fb core when + * releasing */ + mutex_lock(&item->info->lock); + mutex_unlock(&item->info->lock); + framebuffer_release(item->info); + vfree(fb); + } + } while (item); +} + +static DECLARE_WORK(picolcd_fb_cleanup, picolcd_fb_do_cleanup); + +static int picolcd_fb_open(struct fb_info *info, int u) +{ + u32 *ref_cnt = info->pseudo_palette; + ref_cnt--; + + (*ref_cnt)++; + return 0; +} + +static int picolcd_fb_release(struct fb_info *info, int u) +{ + u32 *ref_cnt = info->pseudo_palette; + ref_cnt--; + + (*ref_cnt)++; + if (!*ref_cnt) { + unsigned long flags; + struct picolcd_fb_cleanup_item *item = (struct picolcd_fb_cleanup_item *)ref_cnt; + item--; + spin_lock_irqsave(&fb_pending_lock, flags); + item->next = fb_pending; + fb_pending = item; + spin_unlock_irqrestore(&fb_pending_lock, flags); + schedule_work(&picolcd_fb_cleanup); + } + return 0; +} + +/* Note this can't be const because of struct fb_info definition */ +static struct fb_ops picolcdfb_ops = { + .owner = THIS_MODULE, + .fb_destroy = picolcd_fb_destroy, + .fb_open = picolcd_fb_open, + .fb_release = picolcd_fb_release, + .fb_read = fb_sys_read, + .fb_write = picolcd_fb_write, + .fb_blank = picolcd_fb_blank, + .fb_fillrect = picolcd_fb_fillrect, + .fb_copyarea = picolcd_fb_copyarea, + .fb_imageblit = picolcd_fb_imageblit, + .fb_check_var = picolcd_fb_check_var, + .fb_set_par = picolcd_set_par, +}; + + +/* Callback from deferred IO workqueue */ +static void picolcd_fb_deferred_io(struct fb_info *info, struct list_head *pagelist) +{ + picolcd_fb_update(info->par); +} + +static const struct fb_deferred_io picolcd_fb_defio = { + .delay = HZ / PICOLCDFB_UPDATE_RATE_DEFAULT, + .deferred_io = picolcd_fb_deferred_io, +}; + + +/* + * The "fb_update_rate" sysfs attribute + */ +static ssize_t picolcd_fb_update_rate_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct picolcd_data *data = dev_get_drvdata(dev); + unsigned i, fb_update_rate = data->fb_update_rate; + size_t ret = 0; + + for (i = 1; i <= PICOLCDFB_UPDATE_RATE_LIMIT; i++) + if (ret >= PAGE_SIZE) + break; + else if (i == fb_update_rate) + ret += snprintf(buf+ret, PAGE_SIZE-ret, "[%u] ", i); + else + ret += snprintf(buf+ret, PAGE_SIZE-ret, "%u ", i); + if (ret > 0) + buf[min(ret, (size_t)PAGE_SIZE)-1] = '\n'; + return ret; +} + +static ssize_t picolcd_fb_update_rate_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct picolcd_data *data = dev_get_drvdata(dev); + int i; + unsigned u; + + if (count < 1 || count > 10) + return -EINVAL; + + i = sscanf(buf, "%u", &u); + if (i != 1) + return -EINVAL; + + if (u > PICOLCDFB_UPDATE_RATE_LIMIT) + return -ERANGE; + else if (u == 0) + u = PICOLCDFB_UPDATE_RATE_DEFAULT; + + data->fb_update_rate = u; + data->fb_defio.delay = HZ / data->fb_update_rate; + return count; +} + +static DEVICE_ATTR(fb_update_rate, 0666, picolcd_fb_update_rate_show, + picolcd_fb_update_rate_store); + +/* initialize Framebuffer device */ +static int picolcd_init_framebuffer(struct picolcd_data *data) +{ + struct device *dev = &data->hdev->dev; + struct fb_info *info = NULL; + int i, error = -ENOMEM; + u8 *fb_vbitmap = NULL; + u8 *fb_bitmap = NULL; + u32 *palette; + + fb_bitmap = vmalloc(PICOLCDFB_SIZE*8); + if (fb_bitmap == NULL) { + dev_err(dev, "can't get a free page for framebuffer\n"); + goto err_nomem; + } + + fb_vbitmap = kmalloc(PICOLCDFB_SIZE, GFP_KERNEL); + if (fb_vbitmap == NULL) { + dev_err(dev, "can't alloc vbitmap image buffer\n"); + goto err_nomem; + } + + data->fb_update_rate = PICOLCDFB_UPDATE_RATE_DEFAULT; + data->fb_defio = picolcd_fb_defio; + /* The extra memory is: + * - struct picolcd_fb_cleanup_item + * - u32 for ref_count + * - 256*u32 for pseudo_palette + */ + info = framebuffer_alloc(257 * sizeof(u32) + sizeof(struct picolcd_fb_cleanup_item), dev); + if (info == NULL) { + dev_err(dev, "failed to allocate a framebuffer\n"); + goto err_nomem; + } + + palette = info->par + sizeof(struct picolcd_fb_cleanup_item); + *palette = 1; + palette++; + for (i = 0; i < 256; i++) + palette[i] = i > 0 && i < 16 ? 0xff : 0; + info->pseudo_palette = palette; + info->fbdefio = &data->fb_defio; + info->screen_base = (char __force __iomem *)fb_bitmap; + info->fbops = &picolcdfb_ops; + info->var = picolcdfb_var; + info->fix = picolcdfb_fix; + info->fix.smem_len = PICOLCDFB_SIZE*8; + info->fix.smem_start = (unsigned long)fb_bitmap; + info->par = data; + info->flags = FBINFO_FLAG_DEFAULT; + + data->fb_vbitmap = fb_vbitmap; + data->fb_bitmap = fb_bitmap; + data->fb_bpp = picolcdfb_var.bits_per_pixel; + error = picolcd_fb_reset(data, 1); + if (error) { + dev_err(dev, "failed to configure display\n"); + goto err_cleanup; + } + error = device_create_file(dev, &dev_attr_fb_update_rate); + if (error) { + dev_err(dev, "failed to create sysfs attributes\n"); + goto err_cleanup; + } + fb_deferred_io_init(info); + data->fb_info = info; + error = register_framebuffer(info); + if (error) { + dev_err(dev, "failed to register framebuffer\n"); + goto err_sysfs; + } + /* schedule first output of framebuffer */ + data->fb_force = 1; + schedule_delayed_work(&info->deferred_work, 0); + return 0; + +err_sysfs: + fb_deferred_io_cleanup(info); + device_remove_file(dev, &dev_attr_fb_update_rate); +err_cleanup: + data->fb_vbitmap = NULL; + data->fb_bitmap = NULL; + data->fb_bpp = 0; + data->fb_info = NULL; + +err_nomem: + framebuffer_release(info); + vfree(fb_bitmap); + kfree(fb_vbitmap); + return error; +} + +static void picolcd_exit_framebuffer(struct picolcd_data *data) +{ + struct fb_info *info = data->fb_info; + u8 *fb_vbitmap = data->fb_vbitmap; + + if (!info) + return; + + info->par = NULL; + device_remove_file(&data->hdev->dev, &dev_attr_fb_update_rate); + unregister_framebuffer(info); + data->fb_vbitmap = NULL; + data->fb_bitmap = NULL; + data->fb_bpp = 0; + data->fb_info = NULL; + kfree(fb_vbitmap); +} + +#define picolcd_fbinfo(d) ((d)->fb_info) +#else +static inline int picolcd_fb_reset(struct picolcd_data *data, int clear) +{ + return 0; +} +static inline int picolcd_init_framebuffer(struct picolcd_data *data) +{ + return 0; +} +static inline void picolcd_exit_framebuffer(struct picolcd_data *data) +{ +} +#define picolcd_fbinfo(d) NULL +#endif /* CONFIG_HID_PICOLCD_FB */ + +#ifdef CONFIG_HID_PICOLCD_BACKLIGHT +/* + * backlight class device + */ +static int picolcd_get_brightness(struct backlight_device *bdev) +{ + struct picolcd_data *data = bl_get_data(bdev); + return data->lcd_brightness; +} + +static int picolcd_set_brightness(struct backlight_device *bdev) +{ + struct picolcd_data *data = bl_get_data(bdev); + struct hid_report *report = picolcd_out_report(REPORT_BRIGHTNESS, data->hdev); + unsigned long flags; + + if (!report || report->maxfield != 1 || report->field[0]->report_count != 1) + return -ENODEV; + + data->lcd_brightness = bdev->props.brightness & 0x0ff; + data->lcd_power = bdev->props.power; + spin_lock_irqsave(&data->lock, flags); + hid_set_field(report->field[0], 0, data->lcd_power == FB_BLANK_UNBLANK ? data->lcd_brightness : 0); + usbhid_submit_report(data->hdev, report, USB_DIR_OUT); + spin_unlock_irqrestore(&data->lock, flags); + return 0; +} + +static int picolcd_check_bl_fb(struct backlight_device *bdev, struct fb_info *fb) +{ + return fb && fb == picolcd_fbinfo((struct picolcd_data *)bl_get_data(bdev)); +} + +static const struct backlight_ops picolcd_blops = { + .update_status = picolcd_set_brightness, + .get_brightness = picolcd_get_brightness, + .check_fb = picolcd_check_bl_fb, +}; + +static int picolcd_init_backlight(struct picolcd_data *data, struct hid_report *report) +{ + struct device *dev = &data->hdev->dev; + struct backlight_device *bdev; + struct backlight_properties props; + if (!report) + return -ENODEV; + if (report->maxfield != 1 || report->field[0]->report_count != 1 || + report->field[0]->report_size != 8) { + dev_err(dev, "unsupported BRIGHTNESS report"); + return -EINVAL; + } + + memset(&props, 0, sizeof(props)); + props.type = BACKLIGHT_RAW; + props.max_brightness = 0xff; + bdev = backlight_device_register(dev_name(dev), dev, data, + &picolcd_blops, &props); + if (IS_ERR(bdev)) { + dev_err(dev, "failed to register backlight\n"); + return PTR_ERR(bdev); + } + bdev->props.brightness = 0xff; + data->lcd_brightness = 0xff; + data->backlight = bdev; + picolcd_set_brightness(bdev); + return 0; +} + +static void picolcd_exit_backlight(struct picolcd_data *data) +{ + struct backlight_device *bdev = data->backlight; + + data->backlight = NULL; + if (bdev) + backlight_device_unregister(bdev); +} + +static inline int picolcd_resume_backlight(struct picolcd_data *data) +{ + if (!data->backlight) + return 0; + return picolcd_set_brightness(data->backlight); +} + +#ifdef CONFIG_PM +static void picolcd_suspend_backlight(struct picolcd_data *data) +{ + int bl_power = data->lcd_power; + if (!data->backlight) + return; + + data->backlight->props.power = FB_BLANK_POWERDOWN; + picolcd_set_brightness(data->backlight); + data->lcd_power = data->backlight->props.power = bl_power; +} +#endif /* CONFIG_PM */ +#else +static inline int picolcd_init_backlight(struct picolcd_data *data, + struct hid_report *report) +{ + return 0; +} +static inline void picolcd_exit_backlight(struct picolcd_data *data) +{ +} +static inline int picolcd_resume_backlight(struct picolcd_data *data) +{ + return 0; +} +static inline void picolcd_suspend_backlight(struct picolcd_data *data) +{ +} +#endif /* CONFIG_HID_PICOLCD_BACKLIGHT */ + +#ifdef CONFIG_HID_PICOLCD_LCD +/* + * lcd class device + */ +static int picolcd_get_contrast(struct lcd_device *ldev) +{ + struct picolcd_data *data = lcd_get_data(ldev); + return data->lcd_contrast; +} + +static int picolcd_set_contrast(struct lcd_device *ldev, int contrast) +{ + struct picolcd_data *data = lcd_get_data(ldev); + struct hid_report *report = picolcd_out_report(REPORT_CONTRAST, data->hdev); + unsigned long flags; + + if (!report || report->maxfield != 1 || report->field[0]->report_count != 1) + return -ENODEV; + + data->lcd_contrast = contrast & 0x0ff; + spin_lock_irqsave(&data->lock, flags); + hid_set_field(report->field[0], 0, data->lcd_contrast); + usbhid_submit_report(data->hdev, report, USB_DIR_OUT); + spin_unlock_irqrestore(&data->lock, flags); + return 0; +} + +static int picolcd_check_lcd_fb(struct lcd_device *ldev, struct fb_info *fb) +{ + return fb && fb == picolcd_fbinfo((struct picolcd_data *)lcd_get_data(ldev)); +} + +static struct lcd_ops picolcd_lcdops = { + .get_contrast = picolcd_get_contrast, + .set_contrast = picolcd_set_contrast, + .check_fb = picolcd_check_lcd_fb, +}; + +static int picolcd_init_lcd(struct picolcd_data *data, struct hid_report *report) +{ + struct device *dev = &data->hdev->dev; + struct lcd_device *ldev; + + if (!report) + return -ENODEV; + if (report->maxfield != 1 || report->field[0]->report_count != 1 || + report->field[0]->report_size != 8) { + dev_err(dev, "unsupported CONTRAST report"); + return -EINVAL; + } + + ldev = lcd_device_register(dev_name(dev), dev, data, &picolcd_lcdops); + if (IS_ERR(ldev)) { + dev_err(dev, "failed to register LCD\n"); + return PTR_ERR(ldev); + } + ldev->props.max_contrast = 0x0ff; + data->lcd_contrast = 0xe5; + data->lcd = ldev; + picolcd_set_contrast(ldev, 0xe5); + return 0; +} + +static void picolcd_exit_lcd(struct picolcd_data *data) +{ + struct lcd_device *ldev = data->lcd; + + data->lcd = NULL; + if (ldev) + lcd_device_unregister(ldev); +} + +static inline int picolcd_resume_lcd(struct picolcd_data *data) +{ + if (!data->lcd) + return 0; + return picolcd_set_contrast(data->lcd, data->lcd_contrast); +} +#else +static inline int picolcd_init_lcd(struct picolcd_data *data, + struct hid_report *report) +{ + return 0; +} +static inline void picolcd_exit_lcd(struct picolcd_data *data) +{ +} +static inline int picolcd_resume_lcd(struct picolcd_data *data) +{ + return 0; +} +#endif /* CONFIG_HID_PICOLCD_LCD */ + +#ifdef CONFIG_HID_PICOLCD_LEDS +/** + * LED class device + */ +static void picolcd_leds_set(struct picolcd_data *data) +{ + struct hid_report *report; + unsigned long flags; + + if (!data->led[0]) + return; + report = picolcd_out_report(REPORT_LED_STATE, data->hdev); + if (!report || report->maxfield != 1 || report->field[0]->report_count != 1) + return; + + spin_lock_irqsave(&data->lock, flags); + hid_set_field(report->field[0], 0, data->led_state); + usbhid_submit_report(data->hdev, report, USB_DIR_OUT); + spin_unlock_irqrestore(&data->lock, flags); +} + +static void picolcd_led_set_brightness(struct led_classdev *led_cdev, + enum led_brightness value) +{ + struct device *dev; + struct hid_device *hdev; + struct picolcd_data *data; + int i, state = 0; + + dev = led_cdev->dev->parent; + hdev = container_of(dev, struct hid_device, dev); + data = hid_get_drvdata(hdev); + for (i = 0; i < 8; i++) { + if (led_cdev != data->led[i]) + continue; + state = (data->led_state >> i) & 1; + if (value == LED_OFF && state) { + data->led_state &= ~(1 << i); + picolcd_leds_set(data); + } else if (value != LED_OFF && !state) { + data->led_state |= 1 << i; + picolcd_leds_set(data); + } + break; + } +} + +static enum led_brightness picolcd_led_get_brightness(struct led_classdev *led_cdev) +{ + struct device *dev; + struct hid_device *hdev; + struct picolcd_data *data; + int i, value = 0; + + dev = led_cdev->dev->parent; + hdev = container_of(dev, struct hid_device, dev); + data = hid_get_drvdata(hdev); + for (i = 0; i < 8; i++) + if (led_cdev == data->led[i]) { + value = (data->led_state >> i) & 1; + break; + } + return value ? LED_FULL : LED_OFF; +} + +static int picolcd_init_leds(struct picolcd_data *data, struct hid_report *report) +{ + struct device *dev = &data->hdev->dev; + struct led_classdev *led; + size_t name_sz = strlen(dev_name(dev)) + 8; + char *name; + int i, ret = 0; + + if (!report) + return -ENODEV; + if (report->maxfield != 1 || report->field[0]->report_count != 1 || + report->field[0]->report_size != 8) { + dev_err(dev, "unsupported LED_STATE report"); + return -EINVAL; + } + + for (i = 0; i < 8; i++) { + led = kzalloc(sizeof(struct led_classdev)+name_sz, GFP_KERNEL); + if (!led) { + dev_err(dev, "can't allocate memory for LED %d\n", i); + ret = -ENOMEM; + goto err; + } + name = (void *)(&led[1]); + snprintf(name, name_sz, "%s::GPO%d", dev_name(dev), i); + led->name = name; + led->brightness = 0; + led->max_brightness = 1; + led->brightness_get = picolcd_led_get_brightness; + led->brightness_set = picolcd_led_set_brightness; + + data->led[i] = led; + ret = led_classdev_register(dev, data->led[i]); + if (ret) { + data->led[i] = NULL; + kfree(led); + dev_err(dev, "can't register LED %d\n", i); + goto err; + } + } + return 0; +err: + for (i = 0; i < 8; i++) + if (data->led[i]) { + led = data->led[i]; + data->led[i] = NULL; + led_classdev_unregister(led); + kfree(led); + } + return ret; +} + +static void picolcd_exit_leds(struct picolcd_data *data) +{ + struct led_classdev *led; + int i; + + for (i = 0; i < 8; i++) { + led = data->led[i]; + data->led[i] = NULL; + if (!led) + continue; + led_classdev_unregister(led); + kfree(led); + } +} + +#else +static inline int picolcd_init_leds(struct picolcd_data *data, + struct hid_report *report) +{ + return 0; +} +static inline void picolcd_exit_leds(struct picolcd_data *data) +{ +} +static inline int picolcd_leds_set(struct picolcd_data *data) +{ + return 0; +} +#endif /* CONFIG_HID_PICOLCD_LEDS */ + +/* + * input class device + */ +static int picolcd_raw_keypad(struct picolcd_data *data, + struct hid_report *report, u8 *raw_data, int size) +{ + /* + * Keypad event + * First and second data bytes list currently pressed keys, + * 0x00 means no key and at most 2 keys may be pressed at same time + */ + int i, j; + + /* determine newly pressed keys */ + for (i = 0; i < size; i++) { + unsigned int key_code; + if (raw_data[i] == 0) + continue; + for (j = 0; j < sizeof(data->pressed_keys); j++) + if (data->pressed_keys[j] == raw_data[i]) + goto key_already_down; + for (j = 0; j < sizeof(data->pressed_keys); j++) + if (data->pressed_keys[j] == 0) { + data->pressed_keys[j] = raw_data[i]; + break; + } + input_event(data->input_keys, EV_MSC, MSC_SCAN, raw_data[i]); + if (raw_data[i] < PICOLCD_KEYS) + key_code = data->keycode[raw_data[i]]; + else + key_code = KEY_UNKNOWN; + if (key_code != KEY_UNKNOWN) { + dbg_hid(PICOLCD_NAME " got key press for %u:%d", + raw_data[i], key_code); + input_report_key(data->input_keys, key_code, 1); + } + input_sync(data->input_keys); +key_already_down: + continue; + } + + /* determine newly released keys */ + for (j = 0; j < sizeof(data->pressed_keys); j++) { + unsigned int key_code; + if (data->pressed_keys[j] == 0) + continue; + for (i = 0; i < size; i++) + if (data->pressed_keys[j] == raw_data[i]) + goto key_still_down; + input_event(data->input_keys, EV_MSC, MSC_SCAN, data->pressed_keys[j]); + if (data->pressed_keys[j] < PICOLCD_KEYS) + key_code = data->keycode[data->pressed_keys[j]]; + else + key_code = KEY_UNKNOWN; + if (key_code != KEY_UNKNOWN) { + dbg_hid(PICOLCD_NAME " got key release for %u:%d", + data->pressed_keys[j], key_code); + input_report_key(data->input_keys, key_code, 0); + } + input_sync(data->input_keys); + data->pressed_keys[j] = 0; +key_still_down: + continue; + } + return 1; +} + +static int picolcd_raw_cir(struct picolcd_data *data, + struct hid_report *report, u8 *raw_data, int size) +{ + /* Need understanding of CIR data format to implement ... */ + return 1; +} + +static int picolcd_check_version(struct hid_device *hdev) +{ + struct picolcd_data *data = hid_get_drvdata(hdev); + struct picolcd_pending *verinfo; + int ret = 0; + + if (!data) + return -ENODEV; + + verinfo = picolcd_send_and_wait(hdev, REPORT_VERSION, NULL, 0); + if (!verinfo) { + hid_err(hdev, "no version response from PicoLCD\n"); + return -ENODEV; + } + + if (verinfo->raw_size == 2) { + data->version[0] = verinfo->raw_data[1]; + data->version[1] = verinfo->raw_data[0]; + if (data->status & PICOLCD_BOOTLOADER) { + hid_info(hdev, "PicoLCD, bootloader version %d.%d\n", + verinfo->raw_data[1], verinfo->raw_data[0]); + } else { + hid_info(hdev, "PicoLCD, firmware version %d.%d\n", + verinfo->raw_data[1], verinfo->raw_data[0]); + } + } else { + hid_err(hdev, "confused, got unexpected version response from PicoLCD\n"); + ret = -EINVAL; + } + kfree(verinfo); + return ret; +} + +/* + * Reset our device and wait for answer to VERSION request + */ +static int picolcd_reset(struct hid_device *hdev) +{ + struct picolcd_data *data = hid_get_drvdata(hdev); + struct hid_report *report = picolcd_out_report(REPORT_RESET, hdev); + unsigned long flags; + int error; + + if (!data || !report || report->maxfield != 1) + return -ENODEV; + + spin_lock_irqsave(&data->lock, flags); + if (hdev->product == USB_DEVICE_ID_PICOLCD_BOOTLOADER) + data->status |= PICOLCD_BOOTLOADER; + + /* perform the reset */ + hid_set_field(report->field[0], 0, 1); + usbhid_submit_report(hdev, report, USB_DIR_OUT); + spin_unlock_irqrestore(&data->lock, flags); + + error = picolcd_check_version(hdev); + if (error) + return error; + + picolcd_resume_lcd(data); + picolcd_resume_backlight(data); +#ifdef CONFIG_HID_PICOLCD_FB + if (data->fb_info) + schedule_delayed_work(&data->fb_info->deferred_work, 0); +#endif /* CONFIG_HID_PICOLCD_FB */ + + picolcd_leds_set(data); + return 0; +} + +/* + * The "operation_mode" sysfs attribute + */ +static ssize_t picolcd_operation_mode_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct picolcd_data *data = dev_get_drvdata(dev); + + if (data->status & PICOLCD_BOOTLOADER) + return snprintf(buf, PAGE_SIZE, "[bootloader] lcd\n"); + else + return snprintf(buf, PAGE_SIZE, "bootloader [lcd]\n"); +} + +static ssize_t picolcd_operation_mode_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct picolcd_data *data = dev_get_drvdata(dev); + struct hid_report *report = NULL; + size_t cnt = count; + int timeout = data->opmode_delay; + unsigned long flags; + + if (cnt >= 3 && strncmp("lcd", buf, 3) == 0) { + if (data->status & PICOLCD_BOOTLOADER) + report = picolcd_out_report(REPORT_EXIT_FLASHER, data->hdev); + buf += 3; + cnt -= 3; + } else if (cnt >= 10 && strncmp("bootloader", buf, 10) == 0) { + if (!(data->status & PICOLCD_BOOTLOADER)) + report = picolcd_out_report(REPORT_EXIT_KEYBOARD, data->hdev); + buf += 10; + cnt -= 10; + } + if (!report) + return -EINVAL; + + while (cnt > 0 && (buf[cnt-1] == '\n' || buf[cnt-1] == '\r')) + cnt--; + if (cnt != 0) + return -EINVAL; + + spin_lock_irqsave(&data->lock, flags); + hid_set_field(report->field[0], 0, timeout & 0xff); + hid_set_field(report->field[0], 1, (timeout >> 8) & 0xff); + usbhid_submit_report(data->hdev, report, USB_DIR_OUT); + spin_unlock_irqrestore(&data->lock, flags); + return count; +} + +static DEVICE_ATTR(operation_mode, 0644, picolcd_operation_mode_show, + picolcd_operation_mode_store); + +/* + * The "operation_mode_delay" sysfs attribute + */ +static ssize_t picolcd_operation_mode_delay_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct picolcd_data *data = dev_get_drvdata(dev); + + return snprintf(buf, PAGE_SIZE, "%hu\n", data->opmode_delay); +} + +static ssize_t picolcd_operation_mode_delay_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct picolcd_data *data = dev_get_drvdata(dev); + unsigned u; + if (sscanf(buf, "%u", &u) != 1) + return -EINVAL; + if (u > 30000) + return -EINVAL; + else + data->opmode_delay = u; + return count; +} + +static DEVICE_ATTR(operation_mode_delay, 0644, picolcd_operation_mode_delay_show, + picolcd_operation_mode_delay_store); + + +#ifdef CONFIG_DEBUG_FS +/* + * The "reset" file + */ +static int picolcd_debug_reset_show(struct seq_file *f, void *p) +{ + if (picolcd_fbinfo((struct picolcd_data *)f->private)) + seq_printf(f, "all fb\n"); + else + seq_printf(f, "all\n"); + return 0; +} + +static int picolcd_debug_reset_open(struct inode *inode, struct file *f) +{ + return single_open(f, picolcd_debug_reset_show, inode->i_private); +} + +static ssize_t picolcd_debug_reset_write(struct file *f, const char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct picolcd_data *data = ((struct seq_file *)f->private_data)->private; + char buf[32]; + size_t cnt = min(count, sizeof(buf)-1); + if (copy_from_user(buf, user_buf, cnt)) + return -EFAULT; + + while (cnt > 0 && (buf[cnt-1] == ' ' || buf[cnt-1] == '\n')) + cnt--; + buf[cnt] = '\0'; + if (strcmp(buf, "all") == 0) { + picolcd_reset(data->hdev); + picolcd_fb_reset(data, 1); + } else if (strcmp(buf, "fb") == 0) { + picolcd_fb_reset(data, 1); + } else { + return -EINVAL; + } + return count; +} + +static const struct file_operations picolcd_debug_reset_fops = { + .owner = THIS_MODULE, + .open = picolcd_debug_reset_open, + .read = seq_read, + .llseek = seq_lseek, + .write = picolcd_debug_reset_write, + .release = single_release, +}; + +/* + * The "eeprom" file + */ +static ssize_t picolcd_debug_eeprom_read(struct file *f, char __user *u, + size_t s, loff_t *off) +{ + struct picolcd_data *data = f->private_data; + struct picolcd_pending *resp; + u8 raw_data[3]; + ssize_t ret = -EIO; + + if (s == 0) + return -EINVAL; + if (*off > 0x0ff) + return 0; + + /* prepare buffer with info about what we want to read (addr & len) */ + raw_data[0] = *off & 0xff; + raw_data[1] = (*off >> 8) & 0xff; + raw_data[2] = s < 20 ? s : 20; + if (*off + raw_data[2] > 0xff) + raw_data[2] = 0x100 - *off; + resp = picolcd_send_and_wait(data->hdev, REPORT_EE_READ, raw_data, + sizeof(raw_data)); + if (!resp) + return -EIO; + + if (resp->in_report && resp->in_report->id == REPORT_EE_DATA) { + /* successful read :) */ + ret = resp->raw_data[2]; + if (ret > s) + ret = s; + if (copy_to_user(u, resp->raw_data+3, ret)) + ret = -EFAULT; + else + *off += ret; + } /* anything else is some kind of IO error */ + + kfree(resp); + return ret; +} + +static ssize_t picolcd_debug_eeprom_write(struct file *f, const char __user *u, + size_t s, loff_t *off) +{ + struct picolcd_data *data = f->private_data; + struct picolcd_pending *resp; + ssize_t ret = -EIO; + u8 raw_data[23]; + + if (s == 0) + return -EINVAL; + if (*off > 0x0ff) + return -ENOSPC; + + memset(raw_data, 0, sizeof(raw_data)); + raw_data[0] = *off & 0xff; + raw_data[1] = (*off >> 8) & 0xff; + raw_data[2] = min((size_t)20, s); + if (*off + raw_data[2] > 0xff) + raw_data[2] = 0x100 - *off; + + if (copy_from_user(raw_data+3, u, min((u8)20, raw_data[2]))) + return -EFAULT; + resp = picolcd_send_and_wait(data->hdev, REPORT_EE_WRITE, raw_data, + sizeof(raw_data)); + + if (!resp) + return -EIO; + + if (resp->in_report && resp->in_report->id == REPORT_EE_DATA) { + /* check if written data matches */ + if (memcmp(raw_data, resp->raw_data, 3+raw_data[2]) == 0) { + *off += raw_data[2]; + ret = raw_data[2]; + } + } + kfree(resp); + return ret; +} + +/* + * Notes: + * - read/write happens in chunks of at most 20 bytes, it's up to userspace + * to loop in order to get more data. + * - on write errors on otherwise correct write request the bytes + * that should have been written are in undefined state. + */ +static const struct file_operations picolcd_debug_eeprom_fops = { + .owner = THIS_MODULE, + .open = simple_open, + .read = picolcd_debug_eeprom_read, + .write = picolcd_debug_eeprom_write, + .llseek = generic_file_llseek, +}; + +/* + * The "flash" file + */ +/* record a flash address to buf (bounds check to be done by caller) */ +static int _picolcd_flash_setaddr(struct picolcd_data *data, u8 *buf, long off) +{ + buf[0] = off & 0xff; + buf[1] = (off >> 8) & 0xff; + if (data->addr_sz == 3) + buf[2] = (off >> 16) & 0xff; + return data->addr_sz == 2 ? 2 : 3; +} + +/* read a given size of data (bounds check to be done by caller) */ +static ssize_t _picolcd_flash_read(struct picolcd_data *data, int report_id, + char __user *u, size_t s, loff_t *off) +{ + struct picolcd_pending *resp; + u8 raw_data[4]; + ssize_t ret = 0; + int len_off, err = -EIO; + + while (s > 0) { + err = -EIO; + len_off = _picolcd_flash_setaddr(data, raw_data, *off); + raw_data[len_off] = s > 32 ? 32 : s; + resp = picolcd_send_and_wait(data->hdev, report_id, raw_data, len_off+1); + if (!resp || !resp->in_report) + goto skip; + if (resp->in_report->id == REPORT_MEMORY || + resp->in_report->id == REPORT_BL_READ_MEMORY) { + if (memcmp(raw_data, resp->raw_data, len_off+1) != 0) + goto skip; + if (copy_to_user(u+ret, resp->raw_data+len_off+1, raw_data[len_off])) { + err = -EFAULT; + goto skip; + } + *off += raw_data[len_off]; + s -= raw_data[len_off]; + ret += raw_data[len_off]; + err = 0; + } +skip: + kfree(resp); + if (err) + return ret > 0 ? ret : err; + } + return ret; +} + +static ssize_t picolcd_debug_flash_read(struct file *f, char __user *u, + size_t s, loff_t *off) +{ + struct picolcd_data *data = f->private_data; + + if (s == 0) + return -EINVAL; + if (*off > 0x05fff) + return 0; + if (*off + s > 0x05fff) + s = 0x06000 - *off; + + if (data->status & PICOLCD_BOOTLOADER) + return _picolcd_flash_read(data, REPORT_BL_READ_MEMORY, u, s, off); + else + return _picolcd_flash_read(data, REPORT_READ_MEMORY, u, s, off); +} + +/* erase block aligned to 64bytes boundary */ +static ssize_t _picolcd_flash_erase64(struct picolcd_data *data, int report_id, + loff_t *off) +{ + struct picolcd_pending *resp; + u8 raw_data[3]; + int len_off; + ssize_t ret = -EIO; + + if (*off & 0x3f) + return -EINVAL; + + len_off = _picolcd_flash_setaddr(data, raw_data, *off); + resp = picolcd_send_and_wait(data->hdev, report_id, raw_data, len_off); + if (!resp || !resp->in_report) + goto skip; + if (resp->in_report->id == REPORT_MEMORY || + resp->in_report->id == REPORT_BL_ERASE_MEMORY) { + if (memcmp(raw_data, resp->raw_data, len_off) != 0) + goto skip; + ret = 0; + } +skip: + kfree(resp); + return ret; +} + +/* write a given size of data (bounds check to be done by caller) */ +static ssize_t _picolcd_flash_write(struct picolcd_data *data, int report_id, + const char __user *u, size_t s, loff_t *off) +{ + struct picolcd_pending *resp; + u8 raw_data[36]; + ssize_t ret = 0; + int len_off, err = -EIO; + + while (s > 0) { + err = -EIO; + len_off = _picolcd_flash_setaddr(data, raw_data, *off); + raw_data[len_off] = s > 32 ? 32 : s; + if (copy_from_user(raw_data+len_off+1, u, raw_data[len_off])) { + err = -EFAULT; + break; + } + resp = picolcd_send_and_wait(data->hdev, report_id, raw_data, + len_off+1+raw_data[len_off]); + if (!resp || !resp->in_report) + goto skip; + if (resp->in_report->id == REPORT_MEMORY || + resp->in_report->id == REPORT_BL_WRITE_MEMORY) { + if (memcmp(raw_data, resp->raw_data, len_off+1+raw_data[len_off]) != 0) + goto skip; + *off += raw_data[len_off]; + s -= raw_data[len_off]; + ret += raw_data[len_off]; + err = 0; + } +skip: + kfree(resp); + if (err) + break; + } + return ret > 0 ? ret : err; +} + +static ssize_t picolcd_debug_flash_write(struct file *f, const char __user *u, + size_t s, loff_t *off) +{ + struct picolcd_data *data = f->private_data; + ssize_t err, ret = 0; + int report_erase, report_write; + + if (s == 0) + return -EINVAL; + if (*off > 0x5fff) + return -ENOSPC; + if (s & 0x3f) + return -EINVAL; + if (*off & 0x3f) + return -EINVAL; + + if (data->status & PICOLCD_BOOTLOADER) { + report_erase = REPORT_BL_ERASE_MEMORY; + report_write = REPORT_BL_WRITE_MEMORY; + } else { + report_erase = REPORT_ERASE_MEMORY; + report_write = REPORT_WRITE_MEMORY; + } + mutex_lock(&data->mutex_flash); + while (s > 0) { + err = _picolcd_flash_erase64(data, report_erase, off); + if (err) + break; + err = _picolcd_flash_write(data, report_write, u, 64, off); + if (err < 0) + break; + ret += err; + *off += err; + s -= err; + if (err != 64) + break; + } + mutex_unlock(&data->mutex_flash); + return ret > 0 ? ret : err; +} + +/* + * Notes: + * - concurrent writing is prevented by mutex and all writes must be + * n*64 bytes and 64-byte aligned, each write being preceded by an + * ERASE which erases a 64byte block. + * If less than requested was written or an error is returned for an + * otherwise correct write request the next 64-byte block which should + * have been written is in undefined state (mostly: original, erased, + * (half-)written with write error) + * - reading can happen without special restriction + */ +static const struct file_operations picolcd_debug_flash_fops = { + .owner = THIS_MODULE, + .open = simple_open, + .read = picolcd_debug_flash_read, + .write = picolcd_debug_flash_write, + .llseek = generic_file_llseek, +}; + + +/* + * Helper code for HID report level dumping/debugging + */ +static const char *error_codes[] = { + "success", "parameter missing", "data_missing", "block readonly", + "block not erasable", "block too big", "section overflow", + "invalid command length", "invalid data length", +}; + +static void dump_buff_as_hex(char *dst, size_t dst_sz, const u8 *data, + const size_t data_len) +{ + int i, j; + for (i = j = 0; i < data_len && j + 3 < dst_sz; i++) { + dst[j++] = hex_asc[(data[i] >> 4) & 0x0f]; + dst[j++] = hex_asc[data[i] & 0x0f]; + dst[j++] = ' '; + } + if (j < dst_sz) { + dst[j--] = '\0'; + dst[j] = '\n'; + } else + dst[j] = '\0'; +} + +static void picolcd_debug_out_report(struct picolcd_data *data, + struct hid_device *hdev, struct hid_report *report) +{ + u8 raw_data[70]; + int raw_size = (report->size >> 3) + 1; + char *buff; +#define BUFF_SZ 256 + + /* Avoid unnecessary overhead if debugfs is disabled */ + if (list_empty(&hdev->debug_list)) + return; + + buff = kmalloc(BUFF_SZ, GFP_ATOMIC); + if (!buff) + return; + + snprintf(buff, BUFF_SZ, "\nout report %d (size %d) = ", + report->id, raw_size); + hid_debug_event(hdev, buff); + if (raw_size + 5 > sizeof(raw_data)) { + kfree(buff); + hid_debug_event(hdev, " TOO BIG\n"); + return; + } else { + raw_data[0] = report->id; + hid_output_report(report, raw_data); + dump_buff_as_hex(buff, BUFF_SZ, raw_data, raw_size); + hid_debug_event(hdev, buff); + } + + switch (report->id) { + case REPORT_LED_STATE: + /* 1 data byte with GPO state */ + snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n", + "REPORT_LED_STATE", report->id, raw_size-1); + hid_debug_event(hdev, buff); + snprintf(buff, BUFF_SZ, "\tGPO state: 0x%02x\n", raw_data[1]); + hid_debug_event(hdev, buff); + break; + case REPORT_BRIGHTNESS: + /* 1 data byte with brightness */ + snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n", + "REPORT_BRIGHTNESS", report->id, raw_size-1); + hid_debug_event(hdev, buff); + snprintf(buff, BUFF_SZ, "\tBrightness: 0x%02x\n", raw_data[1]); + hid_debug_event(hdev, buff); + break; + case REPORT_CONTRAST: + /* 1 data byte with contrast */ + snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n", + "REPORT_CONTRAST", report->id, raw_size-1); + hid_debug_event(hdev, buff); + snprintf(buff, BUFF_SZ, "\tContrast: 0x%02x\n", raw_data[1]); + hid_debug_event(hdev, buff); + break; + case REPORT_RESET: + /* 2 data bytes with reset duration in ms */ + snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n", + "REPORT_RESET", report->id, raw_size-1); + hid_debug_event(hdev, buff); + snprintf(buff, BUFF_SZ, "\tDuration: 0x%02x%02x (%dms)\n", + raw_data[2], raw_data[1], raw_data[2] << 8 | raw_data[1]); + hid_debug_event(hdev, buff); + break; + case REPORT_LCD_CMD: + /* 63 data bytes with LCD commands */ + snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n", + "REPORT_LCD_CMD", report->id, raw_size-1); + hid_debug_event(hdev, buff); + /* TODO: format decoding */ + break; + case REPORT_LCD_DATA: + /* 63 data bytes with LCD data */ + snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n", + "REPORT_LCD_CMD", report->id, raw_size-1); + /* TODO: format decoding */ + hid_debug_event(hdev, buff); + break; + case REPORT_LCD_CMD_DATA: + /* 63 data bytes with LCD commands and data */ + snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n", + "REPORT_LCD_CMD", report->id, raw_size-1); + /* TODO: format decoding */ + hid_debug_event(hdev, buff); + break; + case REPORT_EE_READ: + /* 3 data bytes with read area description */ + snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n", + "REPORT_EE_READ", report->id, raw_size-1); + hid_debug_event(hdev, buff); + snprintf(buff, BUFF_SZ, "\tData address: 0x%02x%02x\n", + raw_data[2], raw_data[1]); + hid_debug_event(hdev, buff); + snprintf(buff, BUFF_SZ, "\tData length: %d\n", raw_data[3]); + hid_debug_event(hdev, buff); + break; + case REPORT_EE_WRITE: + /* 3+1..20 data bytes with write area description */ + snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n", + "REPORT_EE_WRITE", report->id, raw_size-1); + hid_debug_event(hdev, buff); + snprintf(buff, BUFF_SZ, "\tData address: 0x%02x%02x\n", + raw_data[2], raw_data[1]); + hid_debug_event(hdev, buff); + snprintf(buff, BUFF_SZ, "\tData length: %d\n", raw_data[3]); + hid_debug_event(hdev, buff); + if (raw_data[3] == 0) { + snprintf(buff, BUFF_SZ, "\tNo data\n"); + } else if (raw_data[3] + 4 <= raw_size) { + snprintf(buff, BUFF_SZ, "\tData: "); + hid_debug_event(hdev, buff); + dump_buff_as_hex(buff, BUFF_SZ, raw_data+4, raw_data[3]); + } else { + snprintf(buff, BUFF_SZ, "\tData overflowed\n"); + } + hid_debug_event(hdev, buff); + break; + case REPORT_ERASE_MEMORY: + case REPORT_BL_ERASE_MEMORY: + /* 3 data bytes with pointer inside erase block */ + snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n", + "REPORT_ERASE_MEMORY", report->id, raw_size-1); + hid_debug_event(hdev, buff); + switch (data->addr_sz) { + case 2: + snprintf(buff, BUFF_SZ, "\tAddress inside 64 byte block: 0x%02x%02x\n", + raw_data[2], raw_data[1]); + break; + case 3: + snprintf(buff, BUFF_SZ, "\tAddress inside 64 byte block: 0x%02x%02x%02x\n", + raw_data[3], raw_data[2], raw_data[1]); + break; + default: + snprintf(buff, BUFF_SZ, "\tNot supported\n"); + } + hid_debug_event(hdev, buff); + break; + case REPORT_READ_MEMORY: + case REPORT_BL_READ_MEMORY: + /* 4 data bytes with read area description */ + snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n", + "REPORT_READ_MEMORY", report->id, raw_size-1); + hid_debug_event(hdev, buff); + switch (data->addr_sz) { + case 2: + snprintf(buff, BUFF_SZ, "\tData address: 0x%02x%02x\n", + raw_data[2], raw_data[1]); + hid_debug_event(hdev, buff); + snprintf(buff, BUFF_SZ, "\tData length: %d\n", raw_data[3]); + break; + case 3: + snprintf(buff, BUFF_SZ, "\tData address: 0x%02x%02x%02x\n", + raw_data[3], raw_data[2], raw_data[1]); + hid_debug_event(hdev, buff); + snprintf(buff, BUFF_SZ, "\tData length: %d\n", raw_data[4]); + break; + default: + snprintf(buff, BUFF_SZ, "\tNot supported\n"); + } + hid_debug_event(hdev, buff); + break; + case REPORT_WRITE_MEMORY: + case REPORT_BL_WRITE_MEMORY: + /* 4+1..32 data bytes with write adrea description */ + snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n", + "REPORT_WRITE_MEMORY", report->id, raw_size-1); + hid_debug_event(hdev, buff); + switch (data->addr_sz) { + case 2: + snprintf(buff, BUFF_SZ, "\tData address: 0x%02x%02x\n", + raw_data[2], raw_data[1]); + hid_debug_event(hdev, buff); + snprintf(buff, BUFF_SZ, "\tData length: %d\n", raw_data[3]); + hid_debug_event(hdev, buff); + if (raw_data[3] == 0) { + snprintf(buff, BUFF_SZ, "\tNo data\n"); + } else if (raw_data[3] + 4 <= raw_size) { + snprintf(buff, BUFF_SZ, "\tData: "); + hid_debug_event(hdev, buff); + dump_buff_as_hex(buff, BUFF_SZ, raw_data+4, raw_data[3]); + } else { + snprintf(buff, BUFF_SZ, "\tData overflowed\n"); + } + break; + case 3: + snprintf(buff, BUFF_SZ, "\tData address: 0x%02x%02x%02x\n", + raw_data[3], raw_data[2], raw_data[1]); + hid_debug_event(hdev, buff); + snprintf(buff, BUFF_SZ, "\tData length: %d\n", raw_data[4]); + hid_debug_event(hdev, buff); + if (raw_data[4] == 0) { + snprintf(buff, BUFF_SZ, "\tNo data\n"); + } else if (raw_data[4] + 5 <= raw_size) { + snprintf(buff, BUFF_SZ, "\tData: "); + hid_debug_event(hdev, buff); + dump_buff_as_hex(buff, BUFF_SZ, raw_data+5, raw_data[4]); + } else { + snprintf(buff, BUFF_SZ, "\tData overflowed\n"); + } + break; + default: + snprintf(buff, BUFF_SZ, "\tNot supported\n"); + } + hid_debug_event(hdev, buff); + break; + case REPORT_SPLASH_RESTART: + /* TODO */ + break; + case REPORT_EXIT_KEYBOARD: + snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n", + "REPORT_EXIT_KEYBOARD", report->id, raw_size-1); + hid_debug_event(hdev, buff); + snprintf(buff, BUFF_SZ, "\tRestart delay: %dms (0x%02x%02x)\n", + raw_data[1] | (raw_data[2] << 8), + raw_data[2], raw_data[1]); + hid_debug_event(hdev, buff); + break; + case REPORT_VERSION: + snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n", + "REPORT_VERSION", report->id, raw_size-1); + hid_debug_event(hdev, buff); + break; + case REPORT_DEVID: + snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n", + "REPORT_DEVID", report->id, raw_size-1); + hid_debug_event(hdev, buff); + break; + case REPORT_SPLASH_SIZE: + snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n", + "REPORT_SPLASH_SIZE", report->id, raw_size-1); + hid_debug_event(hdev, buff); + break; + case REPORT_HOOK_VERSION: + snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n", + "REPORT_HOOK_VERSION", report->id, raw_size-1); + hid_debug_event(hdev, buff); + break; + case REPORT_EXIT_FLASHER: + snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n", + "REPORT_VERSION", report->id, raw_size-1); + hid_debug_event(hdev, buff); + snprintf(buff, BUFF_SZ, "\tRestart delay: %dms (0x%02x%02x)\n", + raw_data[1] | (raw_data[2] << 8), + raw_data[2], raw_data[1]); + hid_debug_event(hdev, buff); + break; + default: + snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n", + "", report->id, raw_size-1); + hid_debug_event(hdev, buff); + break; + } + wake_up_interruptible(&hdev->debug_wait); + kfree(buff); +} + +static void picolcd_debug_raw_event(struct picolcd_data *data, + struct hid_device *hdev, struct hid_report *report, + u8 *raw_data, int size) +{ + char *buff; + +#define BUFF_SZ 256 + /* Avoid unnecessary overhead if debugfs is disabled */ + if (!hdev->debug_events) + return; + + buff = kmalloc(BUFF_SZ, GFP_ATOMIC); + if (!buff) + return; + + switch (report->id) { + case REPORT_ERROR_CODE: + /* 2 data bytes with affected report and error code */ + snprintf(buff, BUFF_SZ, "report %s (%d, size=%d)\n", + "REPORT_ERROR_CODE", report->id, size-1); + hid_debug_event(hdev, buff); + if (raw_data[2] < ARRAY_SIZE(error_codes)) + snprintf(buff, BUFF_SZ, "\tError code 0x%02x (%s) in reply to report 0x%02x\n", + raw_data[2], error_codes[raw_data[2]], raw_data[1]); + else + snprintf(buff, BUFF_SZ, "\tError code 0x%02x in reply to report 0x%02x\n", + raw_data[2], raw_data[1]); + hid_debug_event(hdev, buff); + break; + case REPORT_KEY_STATE: + /* 2 data bytes with key state */ + snprintf(buff, BUFF_SZ, "report %s (%d, size=%d)\n", + "REPORT_KEY_STATE", report->id, size-1); + hid_debug_event(hdev, buff); + if (raw_data[1] == 0) + snprintf(buff, BUFF_SZ, "\tNo key pressed\n"); + else if (raw_data[2] == 0) + snprintf(buff, BUFF_SZ, "\tOne key pressed: 0x%02x (%d)\n", + raw_data[1], raw_data[1]); + else + snprintf(buff, BUFF_SZ, "\tTwo keys pressed: 0x%02x (%d), 0x%02x (%d)\n", + raw_data[1], raw_data[1], raw_data[2], raw_data[2]); + hid_debug_event(hdev, buff); + break; + case REPORT_IR_DATA: + /* Up to 20 byes of IR scancode data */ + snprintf(buff, BUFF_SZ, "report %s (%d, size=%d)\n", + "REPORT_IR_DATA", report->id, size-1); + hid_debug_event(hdev, buff); + if (raw_data[1] == 0) { + snprintf(buff, BUFF_SZ, "\tUnexpectedly 0 data length\n"); + hid_debug_event(hdev, buff); + } else if (raw_data[1] + 1 <= size) { + snprintf(buff, BUFF_SZ, "\tData length: %d\n\tIR Data: ", + raw_data[1]-1); + hid_debug_event(hdev, buff); + dump_buff_as_hex(buff, BUFF_SZ, raw_data+2, raw_data[1]-1); + hid_debug_event(hdev, buff); + } else { + snprintf(buff, BUFF_SZ, "\tOverflowing data length: %d\n", + raw_data[1]-1); + hid_debug_event(hdev, buff); + } + break; + case REPORT_EE_DATA: + /* Data buffer in response to REPORT_EE_READ or REPORT_EE_WRITE */ + snprintf(buff, BUFF_SZ, "report %s (%d, size=%d)\n", + "REPORT_EE_DATA", report->id, size-1); + hid_debug_event(hdev, buff); + snprintf(buff, BUFF_SZ, "\tData address: 0x%02x%02x\n", + raw_data[2], raw_data[1]); + hid_debug_event(hdev, buff); + snprintf(buff, BUFF_SZ, "\tData length: %d\n", raw_data[3]); + hid_debug_event(hdev, buff); + if (raw_data[3] == 0) { + snprintf(buff, BUFF_SZ, "\tNo data\n"); + hid_debug_event(hdev, buff); + } else if (raw_data[3] + 4 <= size) { + snprintf(buff, BUFF_SZ, "\tData: "); + hid_debug_event(hdev, buff); + dump_buff_as_hex(buff, BUFF_SZ, raw_data+4, raw_data[3]); + hid_debug_event(hdev, buff); + } else { + snprintf(buff, BUFF_SZ, "\tData overflowed\n"); + hid_debug_event(hdev, buff); + } + break; + case REPORT_MEMORY: + /* Data buffer in response to REPORT_READ_MEMORY or REPORT_WRTIE_MEMORY */ + snprintf(buff, BUFF_SZ, "report %s (%d, size=%d)\n", + "REPORT_MEMORY", report->id, size-1); + hid_debug_event(hdev, buff); + switch (data->addr_sz) { + case 2: + snprintf(buff, BUFF_SZ, "\tData address: 0x%02x%02x\n", + raw_data[2], raw_data[1]); + hid_debug_event(hdev, buff); + snprintf(buff, BUFF_SZ, "\tData length: %d\n", raw_data[3]); + hid_debug_event(hdev, buff); + if (raw_data[3] == 0) { + snprintf(buff, BUFF_SZ, "\tNo data\n"); + } else if (raw_data[3] + 4 <= size) { + snprintf(buff, BUFF_SZ, "\tData: "); + hid_debug_event(hdev, buff); + dump_buff_as_hex(buff, BUFF_SZ, raw_data+4, raw_data[3]); + } else { + snprintf(buff, BUFF_SZ, "\tData overflowed\n"); + } + break; + case 3: + snprintf(buff, BUFF_SZ, "\tData address: 0x%02x%02x%02x\n", + raw_data[3], raw_data[2], raw_data[1]); + hid_debug_event(hdev, buff); + snprintf(buff, BUFF_SZ, "\tData length: %d\n", raw_data[4]); + hid_debug_event(hdev, buff); + if (raw_data[4] == 0) { + snprintf(buff, BUFF_SZ, "\tNo data\n"); + } else if (raw_data[4] + 5 <= size) { + snprintf(buff, BUFF_SZ, "\tData: "); + hid_debug_event(hdev, buff); + dump_buff_as_hex(buff, BUFF_SZ, raw_data+5, raw_data[4]); + } else { + snprintf(buff, BUFF_SZ, "\tData overflowed\n"); + } + break; + default: + snprintf(buff, BUFF_SZ, "\tNot supported\n"); + } + hid_debug_event(hdev, buff); + break; + case REPORT_VERSION: + snprintf(buff, BUFF_SZ, "report %s (%d, size=%d)\n", + "REPORT_VERSION", report->id, size-1); + hid_debug_event(hdev, buff); + snprintf(buff, BUFF_SZ, "\tFirmware version: %d.%d\n", + raw_data[2], raw_data[1]); + hid_debug_event(hdev, buff); + break; + case REPORT_BL_ERASE_MEMORY: + snprintf(buff, BUFF_SZ, "report %s (%d, size=%d)\n", + "REPORT_BL_ERASE_MEMORY", report->id, size-1); + hid_debug_event(hdev, buff); + /* TODO */ + break; + case REPORT_BL_READ_MEMORY: + snprintf(buff, BUFF_SZ, "report %s (%d, size=%d)\n", + "REPORT_BL_READ_MEMORY", report->id, size-1); + hid_debug_event(hdev, buff); + /* TODO */ + break; + case REPORT_BL_WRITE_MEMORY: + snprintf(buff, BUFF_SZ, "report %s (%d, size=%d)\n", + "REPORT_BL_WRITE_MEMORY", report->id, size-1); + hid_debug_event(hdev, buff); + /* TODO */ + break; + case REPORT_DEVID: + snprintf(buff, BUFF_SZ, "report %s (%d, size=%d)\n", + "REPORT_DEVID", report->id, size-1); + hid_debug_event(hdev, buff); + snprintf(buff, BUFF_SZ, "\tSerial: 0x%02x%02x%02x%02x\n", + raw_data[1], raw_data[2], raw_data[3], raw_data[4]); + hid_debug_event(hdev, buff); + snprintf(buff, BUFF_SZ, "\tType: 0x%02x\n", + raw_data[5]); + hid_debug_event(hdev, buff); + break; + case REPORT_SPLASH_SIZE: + snprintf(buff, BUFF_SZ, "report %s (%d, size=%d)\n", + "REPORT_SPLASH_SIZE", report->id, size-1); + hid_debug_event(hdev, buff); + snprintf(buff, BUFF_SZ, "\tTotal splash space: %d\n", + (raw_data[2] << 8) | raw_data[1]); + hid_debug_event(hdev, buff); + snprintf(buff, BUFF_SZ, "\tUsed splash space: %d\n", + (raw_data[4] << 8) | raw_data[3]); + hid_debug_event(hdev, buff); + break; + case REPORT_HOOK_VERSION: + snprintf(buff, BUFF_SZ, "report %s (%d, size=%d)\n", + "REPORT_HOOK_VERSION", report->id, size-1); + hid_debug_event(hdev, buff); + snprintf(buff, BUFF_SZ, "\tFirmware version: %d.%d\n", + raw_data[1], raw_data[2]); + hid_debug_event(hdev, buff); + break; + default: + snprintf(buff, BUFF_SZ, "report %s (%d, size=%d)\n", + "", report->id, size-1); + hid_debug_event(hdev, buff); + break; + } + wake_up_interruptible(&hdev->debug_wait); + kfree(buff); +} + +static void picolcd_init_devfs(struct picolcd_data *data, + struct hid_report *eeprom_r, struct hid_report *eeprom_w, + struct hid_report *flash_r, struct hid_report *flash_w, + struct hid_report *reset) +{ + struct hid_device *hdev = data->hdev; + + mutex_init(&data->mutex_flash); + + /* reset */ + if (reset) + data->debug_reset = debugfs_create_file("reset", 0600, + hdev->debug_dir, data, &picolcd_debug_reset_fops); + + /* eeprom */ + if (eeprom_r || eeprom_w) + data->debug_eeprom = debugfs_create_file("eeprom", + (eeprom_w ? S_IWUSR : 0) | (eeprom_r ? S_IRUSR : 0), + hdev->debug_dir, data, &picolcd_debug_eeprom_fops); + + /* flash */ + if (flash_r && flash_r->maxfield == 1 && flash_r->field[0]->report_size == 8) + data->addr_sz = flash_r->field[0]->report_count - 1; + else + data->addr_sz = -1; + if (data->addr_sz == 2 || data->addr_sz == 3) { + data->debug_flash = debugfs_create_file("flash", + (flash_w ? S_IWUSR : 0) | (flash_r ? S_IRUSR : 0), + hdev->debug_dir, data, &picolcd_debug_flash_fops); + } else if (flash_r || flash_w) + hid_warn(hdev, "Unexpected FLASH access reports, please submit rdesc for review\n"); +} + +static void picolcd_exit_devfs(struct picolcd_data *data) +{ + struct dentry *dent; + + dent = data->debug_reset; + data->debug_reset = NULL; + if (dent) + debugfs_remove(dent); + dent = data->debug_eeprom; + data->debug_eeprom = NULL; + if (dent) + debugfs_remove(dent); + dent = data->debug_flash; + data->debug_flash = NULL; + if (dent) + debugfs_remove(dent); + mutex_destroy(&data->mutex_flash); +} +#else +static inline void picolcd_debug_raw_event(struct picolcd_data *data, + struct hid_device *hdev, struct hid_report *report, + u8 *raw_data, int size) +{ +} +static inline void picolcd_init_devfs(struct picolcd_data *data, + struct hid_report *eeprom_r, struct hid_report *eeprom_w, + struct hid_report *flash_r, struct hid_report *flash_w, + struct hid_report *reset) +{ +} +static inline void picolcd_exit_devfs(struct picolcd_data *data) +{ +} +#endif /* CONFIG_DEBUG_FS */ + +/* + * Handle raw report as sent by device + */ +static int picolcd_raw_event(struct hid_device *hdev, + struct hid_report *report, u8 *raw_data, int size) +{ + struct picolcd_data *data = hid_get_drvdata(hdev); + unsigned long flags; + int ret = 0; + + if (!data) + return 1; + + if (report->id == REPORT_KEY_STATE) { + if (data->input_keys) + ret = picolcd_raw_keypad(data, report, raw_data+1, size-1); + } else if (report->id == REPORT_IR_DATA) { + if (data->input_cir) + ret = picolcd_raw_cir(data, report, raw_data+1, size-1); + } else { + spin_lock_irqsave(&data->lock, flags); + /* + * We let the caller of picolcd_send_and_wait() check if the + * report we got is one of the expected ones or not. + */ + if (data->pending) { + memcpy(data->pending->raw_data, raw_data+1, size-1); + data->pending->raw_size = size-1; + data->pending->in_report = report; + complete(&data->pending->ready); + } + spin_unlock_irqrestore(&data->lock, flags); + } + + picolcd_debug_raw_event(data, hdev, report, raw_data, size); + return 1; +} + +#ifdef CONFIG_PM +static int picolcd_suspend(struct hid_device *hdev, pm_message_t message) +{ + if (PMSG_IS_AUTO(message)) + return 0; + + picolcd_suspend_backlight(hid_get_drvdata(hdev)); + dbg_hid(PICOLCD_NAME " device ready for suspend\n"); + return 0; +} + +static int picolcd_resume(struct hid_device *hdev) +{ + int ret; + ret = picolcd_resume_backlight(hid_get_drvdata(hdev)); + if (ret) + dbg_hid(PICOLCD_NAME " restoring backlight failed: %d\n", ret); + return 0; +} + +static int picolcd_reset_resume(struct hid_device *hdev) +{ + int ret; + ret = picolcd_reset(hdev); + if (ret) + dbg_hid(PICOLCD_NAME " resetting our device failed: %d\n", ret); + ret = picolcd_fb_reset(hid_get_drvdata(hdev), 0); + if (ret) + dbg_hid(PICOLCD_NAME " restoring framebuffer content failed: %d\n", ret); + ret = picolcd_resume_lcd(hid_get_drvdata(hdev)); + if (ret) + dbg_hid(PICOLCD_NAME " restoring lcd failed: %d\n", ret); + ret = picolcd_resume_backlight(hid_get_drvdata(hdev)); + if (ret) + dbg_hid(PICOLCD_NAME " restoring backlight failed: %d\n", ret); + picolcd_leds_set(hid_get_drvdata(hdev)); + return 0; +} +#endif + +/* initialize keypad input device */ +static int picolcd_init_keys(struct picolcd_data *data, + struct hid_report *report) +{ + struct hid_device *hdev = data->hdev; + struct input_dev *idev; + int error, i; + + if (!report) + return -ENODEV; + if (report->maxfield != 1 || report->field[0]->report_count != 2 || + report->field[0]->report_size != 8) { + hid_err(hdev, "unsupported KEY_STATE report\n"); + return -EINVAL; + } + + idev = input_allocate_device(); + if (idev == NULL) { + hid_err(hdev, "failed to allocate input device\n"); + return -ENOMEM; + } + input_set_drvdata(idev, hdev); + memcpy(data->keycode, def_keymap, sizeof(def_keymap)); + idev->name = hdev->name; + idev->phys = hdev->phys; + idev->uniq = hdev->uniq; + idev->id.bustype = hdev->bus; + idev->id.vendor = hdev->vendor; + idev->id.product = hdev->product; + idev->id.version = hdev->version; + idev->dev.parent = hdev->dev.parent; + idev->keycode = &data->keycode; + idev->keycodemax = PICOLCD_KEYS; + idev->keycodesize = sizeof(data->keycode[0]); + input_set_capability(idev, EV_MSC, MSC_SCAN); + set_bit(EV_REP, idev->evbit); + for (i = 0; i < PICOLCD_KEYS; i++) + input_set_capability(idev, EV_KEY, data->keycode[i]); + error = input_register_device(idev); + if (error) { + hid_err(hdev, "error registering the input device\n"); + input_free_device(idev); + return error; + } + data->input_keys = idev; + return 0; +} + +static void picolcd_exit_keys(struct picolcd_data *data) +{ + struct input_dev *idev = data->input_keys; + + data->input_keys = NULL; + if (idev) + input_unregister_device(idev); +} + +/* initialize CIR input device */ +static inline int picolcd_init_cir(struct picolcd_data *data, struct hid_report *report) +{ + /* support not implemented yet */ + return 0; +} + +static inline void picolcd_exit_cir(struct picolcd_data *data) +{ +} + +static int picolcd_probe_lcd(struct hid_device *hdev, struct picolcd_data *data) +{ + int error; + + error = picolcd_check_version(hdev); + if (error) + return error; + + if (data->version[0] != 0 && data->version[1] != 3) + hid_info(hdev, "Device with untested firmware revision, please submit /sys/kernel/debug/hid/%s/rdesc for this device.\n", + dev_name(&hdev->dev)); + + /* Setup keypad input device */ + error = picolcd_init_keys(data, picolcd_in_report(REPORT_KEY_STATE, hdev)); + if (error) + goto err; + + /* Setup CIR input device */ + error = picolcd_init_cir(data, picolcd_in_report(REPORT_IR_DATA, hdev)); + if (error) + goto err; + + /* Set up the framebuffer device */ + error = picolcd_init_framebuffer(data); + if (error) + goto err; + + /* Setup lcd class device */ + error = picolcd_init_lcd(data, picolcd_out_report(REPORT_CONTRAST, hdev)); + if (error) + goto err; + + /* Setup backlight class device */ + error = picolcd_init_backlight(data, picolcd_out_report(REPORT_BRIGHTNESS, hdev)); + if (error) + goto err; + + /* Setup the LED class devices */ + error = picolcd_init_leds(data, picolcd_out_report(REPORT_LED_STATE, hdev)); + if (error) + goto err; + + picolcd_init_devfs(data, picolcd_out_report(REPORT_EE_READ, hdev), + picolcd_out_report(REPORT_EE_WRITE, hdev), + picolcd_out_report(REPORT_READ_MEMORY, hdev), + picolcd_out_report(REPORT_WRITE_MEMORY, hdev), + picolcd_out_report(REPORT_RESET, hdev)); + return 0; +err: + picolcd_exit_leds(data); + picolcd_exit_backlight(data); + picolcd_exit_lcd(data); + picolcd_exit_framebuffer(data); + picolcd_exit_cir(data); + picolcd_exit_keys(data); + return error; +} + +static int picolcd_probe_bootloader(struct hid_device *hdev, struct picolcd_data *data) +{ + int error; + + error = picolcd_check_version(hdev); + if (error) + return error; + + if (data->version[0] != 1 && data->version[1] != 0) + hid_info(hdev, "Device with untested bootloader revision, please submit /sys/kernel/debug/hid/%s/rdesc for this device.\n", + dev_name(&hdev->dev)); + + picolcd_init_devfs(data, NULL, NULL, + picolcd_out_report(REPORT_BL_READ_MEMORY, hdev), + picolcd_out_report(REPORT_BL_WRITE_MEMORY, hdev), NULL); + return 0; +} + +static int picolcd_probe(struct hid_device *hdev, + const struct hid_device_id *id) +{ + struct picolcd_data *data; + int error = -ENOMEM; + + dbg_hid(PICOLCD_NAME " hardware probe...\n"); + + /* + * Let's allocate the picolcd data structure, set some reasonable + * defaults, and associate it with the device + */ + data = kzalloc(sizeof(struct picolcd_data), GFP_KERNEL); + if (data == NULL) { + hid_err(hdev, "can't allocate space for Minibox PicoLCD device data\n"); + error = -ENOMEM; + goto err_no_cleanup; + } + + spin_lock_init(&data->lock); + mutex_init(&data->mutex); + data->hdev = hdev; + data->opmode_delay = 5000; + if (hdev->product == USB_DEVICE_ID_PICOLCD_BOOTLOADER) + data->status |= PICOLCD_BOOTLOADER; + hid_set_drvdata(hdev, data); + + /* Parse the device reports and start it up */ + error = hid_parse(hdev); + if (error) { + hid_err(hdev, "device report parse failed\n"); + goto err_cleanup_data; + } + + error = hid_hw_start(hdev, 0); + if (error) { + hid_err(hdev, "hardware start failed\n"); + goto err_cleanup_data; + } + + error = hid_hw_open(hdev); + if (error) { + hid_err(hdev, "failed to open input interrupt pipe for key and IR events\n"); + goto err_cleanup_hid_hw; + } + + error = device_create_file(&hdev->dev, &dev_attr_operation_mode_delay); + if (error) { + hid_err(hdev, "failed to create sysfs attributes\n"); + goto err_cleanup_hid_ll; + } + + error = device_create_file(&hdev->dev, &dev_attr_operation_mode); + if (error) { + hid_err(hdev, "failed to create sysfs attributes\n"); + goto err_cleanup_sysfs1; + } + + if (data->status & PICOLCD_BOOTLOADER) + error = picolcd_probe_bootloader(hdev, data); + else + error = picolcd_probe_lcd(hdev, data); + if (error) + goto err_cleanup_sysfs2; + + dbg_hid(PICOLCD_NAME " activated and initialized\n"); + return 0; + +err_cleanup_sysfs2: + device_remove_file(&hdev->dev, &dev_attr_operation_mode); +err_cleanup_sysfs1: + device_remove_file(&hdev->dev, &dev_attr_operation_mode_delay); +err_cleanup_hid_ll: + hid_hw_close(hdev); +err_cleanup_hid_hw: + hid_hw_stop(hdev); +err_cleanup_data: + kfree(data); +err_no_cleanup: + hid_set_drvdata(hdev, NULL); + + return error; +} + +static void picolcd_remove(struct hid_device *hdev) +{ + struct picolcd_data *data = hid_get_drvdata(hdev); + unsigned long flags; + + dbg_hid(PICOLCD_NAME " hardware remove...\n"); + spin_lock_irqsave(&data->lock, flags); + data->status |= PICOLCD_FAILED; + spin_unlock_irqrestore(&data->lock, flags); +#ifdef CONFIG_HID_PICOLCD_FB + /* short-circuit FB as early as possible in order to + * avoid long delays if we host console. + */ + if (data->fb_info) + data->fb_info->par = NULL; +#endif + + picolcd_exit_devfs(data); + device_remove_file(&hdev->dev, &dev_attr_operation_mode); + device_remove_file(&hdev->dev, &dev_attr_operation_mode_delay); + hid_hw_close(hdev); + hid_hw_stop(hdev); + hid_set_drvdata(hdev, NULL); + + /* Shortcut potential pending reply that will never arrive */ + spin_lock_irqsave(&data->lock, flags); + if (data->pending) + complete(&data->pending->ready); + spin_unlock_irqrestore(&data->lock, flags); + + /* Cleanup LED */ + picolcd_exit_leds(data); + /* Clean up the framebuffer */ + picolcd_exit_backlight(data); + picolcd_exit_lcd(data); + picolcd_exit_framebuffer(data); + /* Cleanup input */ + picolcd_exit_cir(data); + picolcd_exit_keys(data); + + mutex_destroy(&data->mutex); + /* Finally, clean up the picolcd data itself */ + kfree(data); +} + +static const struct hid_device_id picolcd_devices[] = { + { HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICOLCD) }, + { HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICOLCD_BOOTLOADER) }, + { } +}; +MODULE_DEVICE_TABLE(hid, picolcd_devices); + +static struct hid_driver picolcd_driver = { + .name = "hid-picolcd", + .id_table = picolcd_devices, + .probe = picolcd_probe, + .remove = picolcd_remove, + .raw_event = picolcd_raw_event, +#ifdef CONFIG_PM + .suspend = picolcd_suspend, + .resume = picolcd_resume, + .reset_resume = picolcd_reset_resume, +#endif +}; + +static int __init picolcd_init(void) +{ + return hid_register_driver(&picolcd_driver); +} + +static void __exit picolcd_exit(void) +{ + hid_unregister_driver(&picolcd_driver); +#ifdef CONFIG_HID_PICOLCD_FB + flush_work_sync(&picolcd_fb_cleanup); + WARN_ON(fb_pending); +#endif +} + +module_init(picolcd_init); +module_exit(picolcd_exit); +MODULE_DESCRIPTION("Minibox graphics PicoLCD Driver"); +MODULE_LICENSE("GPL v2"); diff --git a/trunk/drivers/hid/hid-picolcd.h b/trunk/drivers/hid/hid-picolcd.h deleted file mode 100644 index 020cef69f6a1..000000000000 --- a/trunk/drivers/hid/hid-picolcd.h +++ /dev/null @@ -1,309 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2010-2012 by Bruno Prémont * - * * - * Based on Logitech G13 driver (v0.4) * - * Copyright (C) 2009 by Rick L. Vinyard, Jr. * - * * - * 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 driver 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 software. If not see . * - ***************************************************************************/ - -#define PICOLCD_NAME "PicoLCD (graphic)" - -/* Report numbers */ -#define REPORT_ERROR_CODE 0x10 /* LCD: IN[16] */ -#define ERR_SUCCESS 0x00 -#define ERR_PARAMETER_MISSING 0x01 -#define ERR_DATA_MISSING 0x02 -#define ERR_BLOCK_READ_ONLY 0x03 -#define ERR_BLOCK_NOT_ERASABLE 0x04 -#define ERR_BLOCK_TOO_BIG 0x05 -#define ERR_SECTION_OVERFLOW 0x06 -#define ERR_INVALID_CMD_LEN 0x07 -#define ERR_INVALID_DATA_LEN 0x08 -#define REPORT_KEY_STATE 0x11 /* LCD: IN[2] */ -#define REPORT_IR_DATA 0x21 /* LCD: IN[63] */ -#define REPORT_EE_DATA 0x32 /* LCD: IN[63] */ -#define REPORT_MEMORY 0x41 /* LCD: IN[63] */ -#define REPORT_LED_STATE 0x81 /* LCD: OUT[1] */ -#define REPORT_BRIGHTNESS 0x91 /* LCD: OUT[1] */ -#define REPORT_CONTRAST 0x92 /* LCD: OUT[1] */ -#define REPORT_RESET 0x93 /* LCD: OUT[2] */ -#define REPORT_LCD_CMD 0x94 /* LCD: OUT[63] */ -#define REPORT_LCD_DATA 0x95 /* LCD: OUT[63] */ -#define REPORT_LCD_CMD_DATA 0x96 /* LCD: OUT[63] */ -#define REPORT_EE_READ 0xa3 /* LCD: OUT[63] */ -#define REPORT_EE_WRITE 0xa4 /* LCD: OUT[63] */ -#define REPORT_ERASE_MEMORY 0xb2 /* LCD: OUT[2] */ -#define REPORT_READ_MEMORY 0xb3 /* LCD: OUT[3] */ -#define REPORT_WRITE_MEMORY 0xb4 /* LCD: OUT[63] */ -#define REPORT_SPLASH_RESTART 0xc1 /* LCD: OUT[1] */ -#define REPORT_EXIT_KEYBOARD 0xef /* LCD: OUT[2] */ -#define REPORT_VERSION 0xf1 /* LCD: IN[2],OUT[1] Bootloader: IN[2],OUT[1] */ -#define REPORT_BL_ERASE_MEMORY 0xf2 /* Bootloader: IN[36],OUT[4] */ -#define REPORT_BL_READ_MEMORY 0xf3 /* Bootloader: IN[36],OUT[4] */ -#define REPORT_BL_WRITE_MEMORY 0xf4 /* Bootloader: IN[36],OUT[36] */ -#define REPORT_DEVID 0xf5 /* LCD: IN[5], OUT[1] Bootloader: IN[5],OUT[1] */ -#define REPORT_SPLASH_SIZE 0xf6 /* LCD: IN[4], OUT[1] */ -#define REPORT_HOOK_VERSION 0xf7 /* LCD: IN[2], OUT[1] */ -#define REPORT_EXIT_FLASHER 0xff /* Bootloader: OUT[2] */ - -/* Description of in-progress IO operation, used for operations - * that trigger response from device */ -struct picolcd_pending { - struct hid_report *out_report; - struct hid_report *in_report; - struct completion ready; - int raw_size; - u8 raw_data[64]; -}; - - -#define PICOLCD_KEYS 17 - -/* Per device data structure */ -struct picolcd_data { - struct hid_device *hdev; -#ifdef CONFIG_DEBUG_FS - struct dentry *debug_reset; - struct dentry *debug_eeprom; - struct dentry *debug_flash; - struct mutex mutex_flash; - int addr_sz; -#endif - u8 version[2]; - unsigned short opmode_delay; - /* input stuff */ - u8 pressed_keys[2]; - struct input_dev *input_keys; -#ifdef CONFIG_HID_PICOLCD_CIR - struct rc_dev *rc_dev; -#endif - unsigned short keycode[PICOLCD_KEYS]; - -#ifdef CONFIG_HID_PICOLCD_FB - /* Framebuffer stuff */ - struct fb_info *fb_info; -#endif /* CONFIG_HID_PICOLCD_FB */ -#ifdef CONFIG_HID_PICOLCD_LCD - struct lcd_device *lcd; - u8 lcd_contrast; -#endif /* CONFIG_HID_PICOLCD_LCD */ -#ifdef CONFIG_HID_PICOLCD_BACKLIGHT - struct backlight_device *backlight; - u8 lcd_brightness; - u8 lcd_power; -#endif /* CONFIG_HID_PICOLCD_BACKLIGHT */ -#ifdef CONFIG_HID_PICOLCD_LEDS - /* LED stuff */ - u8 led_state; - struct led_classdev *led[8]; -#endif /* CONFIG_HID_PICOLCD_LEDS */ - - /* Housekeeping stuff */ - spinlock_t lock; - struct mutex mutex; - struct picolcd_pending *pending; - int status; -#define PICOLCD_BOOTLOADER 1 -#define PICOLCD_FAILED 2 -#define PICOLCD_CIR_SHUN 4 -}; - -#ifdef CONFIG_HID_PICOLCD_FB -struct picolcd_fb_data { - /* Framebuffer stuff */ - spinlock_t lock; - struct picolcd_data *picolcd; - u8 update_rate; - u8 bpp; - u8 force; - u8 ready; - u8 *vbitmap; /* local copy of what was sent to PicoLCD */ - u8 *bitmap; /* framebuffer */ -}; -#endif /* CONFIG_HID_PICOLCD_FB */ - -/* Find a given report */ -#define picolcd_in_report(id, dev) picolcd_report(id, dev, HID_INPUT_REPORT) -#define picolcd_out_report(id, dev) picolcd_report(id, dev, HID_OUTPUT_REPORT) - -struct hid_report *picolcd_report(int id, struct hid_device *hdev, int dir); - -#ifdef CONFIG_DEBUG_FS -void picolcd_debug_out_report(struct picolcd_data *data, - struct hid_device *hdev, struct hid_report *report); -#define usbhid_submit_report(a, b, c) \ - do { \ - picolcd_debug_out_report(hid_get_drvdata(a), a, b); \ - usbhid_submit_report(a, b, c); \ - } while (0) - -void picolcd_debug_raw_event(struct picolcd_data *data, - struct hid_device *hdev, struct hid_report *report, - u8 *raw_data, int size); - -void picolcd_init_devfs(struct picolcd_data *data, - struct hid_report *eeprom_r, struct hid_report *eeprom_w, - struct hid_report *flash_r, struct hid_report *flash_w, - struct hid_report *reset); - -void picolcd_exit_devfs(struct picolcd_data *data); -#else -static inline void picolcd_debug_out_report(struct picolcd_data *data, - struct hid_device *hdev, struct hid_report *report) -{ -} -static inline void picolcd_debug_raw_event(struct picolcd_data *data, - struct hid_device *hdev, struct hid_report *report, - u8 *raw_data, int size) -{ -} -static inline void picolcd_init_devfs(struct picolcd_data *data, - struct hid_report *eeprom_r, struct hid_report *eeprom_w, - struct hid_report *flash_r, struct hid_report *flash_w, - struct hid_report *reset) -{ -} -static inline void picolcd_exit_devfs(struct picolcd_data *data) -{ -} -#endif /* CONFIG_DEBUG_FS */ - - -#ifdef CONFIG_HID_PICOLCD_FB -int picolcd_fb_reset(struct picolcd_data *data, int clear); - -int picolcd_init_framebuffer(struct picolcd_data *data); - -void picolcd_exit_framebuffer(struct picolcd_data *data); - -void picolcd_fb_refresh(struct picolcd_data *data); -#define picolcd_fbinfo(d) ((d)->fb_info) -#else -static inline int picolcd_fb_reset(struct picolcd_data *data, int clear) -{ - return 0; -} -static inline int picolcd_init_framebuffer(struct picolcd_data *data) -{ - return 0; -} -static inline void picolcd_exit_framebuffer(struct picolcd_data *data) -{ -} -static inline void picolcd_fb_refresh(struct picolcd_data *data) -{ -} -#define picolcd_fbinfo(d) NULL -#endif /* CONFIG_HID_PICOLCD_FB */ - - -#ifdef CONFIG_HID_PICOLCD_BACKLIGHT -int picolcd_init_backlight(struct picolcd_data *data, - struct hid_report *report); - -void picolcd_exit_backlight(struct picolcd_data *data); - -int picolcd_resume_backlight(struct picolcd_data *data); - -void picolcd_suspend_backlight(struct picolcd_data *data); -#else -static inline int picolcd_init_backlight(struct picolcd_data *data, - struct hid_report *report) -{ - return 0; -} -static inline void picolcd_exit_backlight(struct picolcd_data *data) -{ -} -static inline int picolcd_resume_backlight(struct picolcd_data *data) -{ - return 0; -} -static inline void picolcd_suspend_backlight(struct picolcd_data *data) -{ -} - -#endif /* CONFIG_HID_PICOLCD_BACKLIGHT */ - - -#ifdef CONFIG_HID_PICOLCD_LCD -int picolcd_init_lcd(struct picolcd_data *data, - struct hid_report *report); - -void picolcd_exit_lcd(struct picolcd_data *data); - -int picolcd_resume_lcd(struct picolcd_data *data); -#else -static inline int picolcd_init_lcd(struct picolcd_data *data, - struct hid_report *report) -{ - return 0; -} -static inline void picolcd_exit_lcd(struct picolcd_data *data) -{ -} -static inline int picolcd_resume_lcd(struct picolcd_data *data) -{ - return 0; -} -#endif /* CONFIG_HID_PICOLCD_LCD */ - - -#ifdef CONFIG_HID_PICOLCD_LEDS -int picolcd_init_leds(struct picolcd_data *data, - struct hid_report *report); - -void picolcd_exit_leds(struct picolcd_data *data); - -void picolcd_leds_set(struct picolcd_data *data); -#else -static inline int picolcd_init_leds(struct picolcd_data *data, - struct hid_report *report) -{ - return 0; -} -static inline void picolcd_exit_leds(struct picolcd_data *data) -{ -} -static inline void picolcd_leds_set(struct picolcd_data *data) -{ -} -#endif /* CONFIG_HID_PICOLCD_LEDS */ - - -#ifdef CONFIG_HID_PICOLCD_CIR -int picolcd_raw_cir(struct picolcd_data *data, - struct hid_report *report, u8 *raw_data, int size); - -int picolcd_init_cir(struct picolcd_data *data, struct hid_report *report); - -void picolcd_exit_cir(struct picolcd_data *data); -#else -static inline int picolcd_raw_cir(struct picolcd_data *data, - struct hid_report *report, u8 *raw_data, int size) -{ - return 1; -} -static inline int picolcd_init_cir(struct picolcd_data *data, struct hid_report *report) -{ - return 0; -} -static inline void picolcd_exit_cir(struct picolcd_data *data) -{ -} -#endif /* CONFIG_HID_PICOLCD_LIRC */ - -int picolcd_reset(struct hid_device *hdev); -struct picolcd_pending *picolcd_send_and_wait(struct hid_device *hdev, - int report_id, const u8 *raw_data, int size); diff --git a/trunk/drivers/hid/hid-picolcd_backlight.c b/trunk/drivers/hid/hid-picolcd_backlight.c deleted file mode 100644 index b91f30945f9c..000000000000 --- a/trunk/drivers/hid/hid-picolcd_backlight.c +++ /dev/null @@ -1,122 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2010-2012 by Bruno Prémont * - * * - * Based on Logitech G13 driver (v0.4) * - * Copyright (C) 2009 by Rick L. Vinyard, Jr. * - * * - * 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 driver 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 software. If not see . * - ***************************************************************************/ - -#include -#include "usbhid/usbhid.h" -#include - -#include -#include - -#include "hid-picolcd.h" - -static int picolcd_get_brightness(struct backlight_device *bdev) -{ - struct picolcd_data *data = bl_get_data(bdev); - return data->lcd_brightness; -} - -static int picolcd_set_brightness(struct backlight_device *bdev) -{ - struct picolcd_data *data = bl_get_data(bdev); - struct hid_report *report = picolcd_out_report(REPORT_BRIGHTNESS, data->hdev); - unsigned long flags; - - if (!report || report->maxfield != 1 || report->field[0]->report_count != 1) - return -ENODEV; - - data->lcd_brightness = bdev->props.brightness & 0x0ff; - data->lcd_power = bdev->props.power; - spin_lock_irqsave(&data->lock, flags); - hid_set_field(report->field[0], 0, data->lcd_power == FB_BLANK_UNBLANK ? data->lcd_brightness : 0); - if (!(data->status & PICOLCD_FAILED)) - usbhid_submit_report(data->hdev, report, USB_DIR_OUT); - spin_unlock_irqrestore(&data->lock, flags); - return 0; -} - -static int picolcd_check_bl_fb(struct backlight_device *bdev, struct fb_info *fb) -{ - return fb && fb == picolcd_fbinfo((struct picolcd_data *)bl_get_data(bdev)); -} - -static const struct backlight_ops picolcd_blops = { - .update_status = picolcd_set_brightness, - .get_brightness = picolcd_get_brightness, - .check_fb = picolcd_check_bl_fb, -}; - -int picolcd_init_backlight(struct picolcd_data *data, struct hid_report *report) -{ - struct device *dev = &data->hdev->dev; - struct backlight_device *bdev; - struct backlight_properties props; - if (!report) - return -ENODEV; - if (report->maxfield != 1 || report->field[0]->report_count != 1 || - report->field[0]->report_size != 8) { - dev_err(dev, "unsupported BRIGHTNESS report"); - return -EINVAL; - } - - memset(&props, 0, sizeof(props)); - props.type = BACKLIGHT_RAW; - props.max_brightness = 0xff; - bdev = backlight_device_register(dev_name(dev), dev, data, - &picolcd_blops, &props); - if (IS_ERR(bdev)) { - dev_err(dev, "failed to register backlight\n"); - return PTR_ERR(bdev); - } - bdev->props.brightness = 0xff; - data->lcd_brightness = 0xff; - data->backlight = bdev; - picolcd_set_brightness(bdev); - return 0; -} - -void picolcd_exit_backlight(struct picolcd_data *data) -{ - struct backlight_device *bdev = data->backlight; - - data->backlight = NULL; - if (bdev) - backlight_device_unregister(bdev); -} - -int picolcd_resume_backlight(struct picolcd_data *data) -{ - if (!data->backlight) - return 0; - return picolcd_set_brightness(data->backlight); -} - -#ifdef CONFIG_PM -void picolcd_suspend_backlight(struct picolcd_data *data) -{ - int bl_power = data->lcd_power; - if (!data->backlight) - return; - - data->backlight->props.power = FB_BLANK_POWERDOWN; - picolcd_set_brightness(data->backlight); - data->lcd_power = data->backlight->props.power = bl_power; -} -#endif /* CONFIG_PM */ - diff --git a/trunk/drivers/hid/hid-picolcd_cir.c b/trunk/drivers/hid/hid-picolcd_cir.c deleted file mode 100644 index 13ca9191b630..000000000000 --- a/trunk/drivers/hid/hid-picolcd_cir.c +++ /dev/null @@ -1,152 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2010-2012 by Bruno Prémont * - * * - * Based on Logitech G13 driver (v0.4) * - * Copyright (C) 2009 by Rick L. Vinyard, Jr. * - * * - * 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 driver 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 software. If not see . * - ***************************************************************************/ - -#include -#include -#include -#include "hid-ids.h" -#include "usbhid/usbhid.h" -#include - -#include -#include -#include -#include - -#include - -#include -#include - -#include -#include -#include -#include - -#include "hid-picolcd.h" - - -int picolcd_raw_cir(struct picolcd_data *data, - struct hid_report *report, u8 *raw_data, int size) -{ - unsigned long flags; - int i, w, sz; - DEFINE_IR_RAW_EVENT(rawir); - - /* ignore if rc_dev is NULL or status is shunned */ - spin_lock_irqsave(&data->lock, flags); - if (!data->rc_dev || (data->status & PICOLCD_CIR_SHUN)) { - spin_unlock_irqrestore(&data->lock, flags); - return 1; - } - spin_unlock_irqrestore(&data->lock, flags); - - /* PicoLCD USB packets contain 16-bit intervals in network order, - * with value negated for pulse. Intervals are in microseconds. - * - * Note: some userspace LIRC code for PicoLCD says negated values - * for space - is it a matter of IR chip? (pulse for my TSOP2236) - * - * In addition, the first interval seems to be around 15000 + base - * interval for non-first report of IR data - thus the quirk below - * to get RC_CODE to understand Sony and JVC remotes I have at hand - */ - sz = size > 0 ? min((int)raw_data[0], size-1) : 0; - for (i = 0; i+1 < sz; i += 2) { - init_ir_raw_event(&rawir); - w = (raw_data[i] << 8) | (raw_data[i+1]); - rawir.pulse = !!(w & 0x8000); - rawir.duration = US_TO_NS(rawir.pulse ? (65536 - w) : w); - /* Quirk!! - see above */ - if (i == 0 && rawir.duration > 15000000) - rawir.duration -= 15000000; - ir_raw_event_store(data->rc_dev, &rawir); - } - ir_raw_event_handle(data->rc_dev); - - return 1; -} - -static int picolcd_cir_open(struct rc_dev *dev) -{ - struct picolcd_data *data = dev->priv; - unsigned long flags; - - spin_lock_irqsave(&data->lock, flags); - data->status &= ~PICOLCD_CIR_SHUN; - spin_unlock_irqrestore(&data->lock, flags); - return 0; -} - -static void picolcd_cir_close(struct rc_dev *dev) -{ - struct picolcd_data *data = dev->priv; - unsigned long flags; - - spin_lock_irqsave(&data->lock, flags); - data->status |= PICOLCD_CIR_SHUN; - spin_unlock_irqrestore(&data->lock, flags); -} - -/* initialize CIR input device */ -int picolcd_init_cir(struct picolcd_data *data, struct hid_report *report) -{ - struct rc_dev *rdev; - int ret = 0; - - rdev = rc_allocate_device(); - if (!rdev) - return -ENOMEM; - - rdev->priv = data; - rdev->driver_type = RC_DRIVER_IR_RAW; - rdev->allowed_protos = RC_TYPE_ALL; - rdev->open = picolcd_cir_open; - rdev->close = picolcd_cir_close; - rdev->input_name = data->hdev->name; - rdev->input_phys = data->hdev->phys; - rdev->input_id.bustype = data->hdev->bus; - rdev->input_id.vendor = data->hdev->vendor; - rdev->input_id.product = data->hdev->product; - rdev->input_id.version = data->hdev->version; - rdev->dev.parent = &data->hdev->dev; - rdev->driver_name = PICOLCD_NAME; - rdev->map_name = RC_MAP_RC6_MCE; - rdev->timeout = MS_TO_NS(100); - rdev->rx_resolution = US_TO_NS(1); - - ret = rc_register_device(rdev); - if (ret) - goto err; - data->rc_dev = rdev; - return 0; - -err: - rc_free_device(rdev); - return ret; -} - -void picolcd_exit_cir(struct picolcd_data *data) -{ - struct rc_dev *rdev = data->rc_dev; - - data->rc_dev = NULL; - rc_unregister_device(rdev); -} - diff --git a/trunk/drivers/hid/hid-picolcd_core.c b/trunk/drivers/hid/hid-picolcd_core.c deleted file mode 100644 index 86df26e58aba..000000000000 --- a/trunk/drivers/hid/hid-picolcd_core.c +++ /dev/null @@ -1,689 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2010-2012 by Bruno Prémont * - * * - * Based on Logitech G13 driver (v0.4) * - * Copyright (C) 2009 by Rick L. Vinyard, Jr. * - * * - * 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 driver 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 software. If not see . * - ***************************************************************************/ - -#include -#include -#include -#include "hid-ids.h" -#include "usbhid/usbhid.h" -#include - -#include -#include - -#include -#include -#include - -#include "hid-picolcd.h" - - -/* Input device - * - * The PicoLCD has an IR receiver header, a built-in keypad with 5 keys - * and header for 4x4 key matrix. The built-in keys are part of the matrix. - */ -static const unsigned short def_keymap[PICOLCD_KEYS] = { - KEY_RESERVED, /* none */ - KEY_BACK, /* col 4 + row 1 */ - KEY_HOMEPAGE, /* col 3 + row 1 */ - KEY_RESERVED, /* col 2 + row 1 */ - KEY_RESERVED, /* col 1 + row 1 */ - KEY_SCROLLUP, /* col 4 + row 2 */ - KEY_OK, /* col 3 + row 2 */ - KEY_SCROLLDOWN, /* col 2 + row 2 */ - KEY_RESERVED, /* col 1 + row 2 */ - KEY_RESERVED, /* col 4 + row 3 */ - KEY_RESERVED, /* col 3 + row 3 */ - KEY_RESERVED, /* col 2 + row 3 */ - KEY_RESERVED, /* col 1 + row 3 */ - KEY_RESERVED, /* col 4 + row 4 */ - KEY_RESERVED, /* col 3 + row 4 */ - KEY_RESERVED, /* col 2 + row 4 */ - KEY_RESERVED, /* col 1 + row 4 */ -}; - - -/* Find a given report */ -struct hid_report *picolcd_report(int id, struct hid_device *hdev, int dir) -{ - struct list_head *feature_report_list = &hdev->report_enum[dir].report_list; - struct hid_report *report = NULL; - - list_for_each_entry(report, feature_report_list, list) { - if (report->id == id) - return report; - } - hid_warn(hdev, "No report with id 0x%x found\n", id); - return NULL; -} - -/* Submit a report and wait for a reply from device - if device fades away - * or does not respond in time, return NULL */ -struct picolcd_pending *picolcd_send_and_wait(struct hid_device *hdev, - int report_id, const u8 *raw_data, int size) -{ - struct picolcd_data *data = hid_get_drvdata(hdev); - struct picolcd_pending *work; - struct hid_report *report = picolcd_out_report(report_id, hdev); - unsigned long flags; - int i, j, k; - - if (!report || !data) - return NULL; - if (data->status & PICOLCD_FAILED) - return NULL; - work = kzalloc(sizeof(*work), GFP_KERNEL); - if (!work) - return NULL; - - init_completion(&work->ready); - work->out_report = report; - work->in_report = NULL; - work->raw_size = 0; - - mutex_lock(&data->mutex); - spin_lock_irqsave(&data->lock, flags); - for (i = k = 0; i < report->maxfield; i++) - for (j = 0; j < report->field[i]->report_count; j++) { - hid_set_field(report->field[i], j, k < size ? raw_data[k] : 0); - k++; - } - if (data->status & PICOLCD_FAILED) { - kfree(work); - work = NULL; - } else { - data->pending = work; - usbhid_submit_report(data->hdev, report, USB_DIR_OUT); - spin_unlock_irqrestore(&data->lock, flags); - wait_for_completion_interruptible_timeout(&work->ready, HZ*2); - spin_lock_irqsave(&data->lock, flags); - data->pending = NULL; - } - spin_unlock_irqrestore(&data->lock, flags); - mutex_unlock(&data->mutex); - return work; -} - -/* - * input class device - */ -static int picolcd_raw_keypad(struct picolcd_data *data, - struct hid_report *report, u8 *raw_data, int size) -{ - /* - * Keypad event - * First and second data bytes list currently pressed keys, - * 0x00 means no key and at most 2 keys may be pressed at same time - */ - int i, j; - - /* determine newly pressed keys */ - for (i = 0; i < size; i++) { - unsigned int key_code; - if (raw_data[i] == 0) - continue; - for (j = 0; j < sizeof(data->pressed_keys); j++) - if (data->pressed_keys[j] == raw_data[i]) - goto key_already_down; - for (j = 0; j < sizeof(data->pressed_keys); j++) - if (data->pressed_keys[j] == 0) { - data->pressed_keys[j] = raw_data[i]; - break; - } - input_event(data->input_keys, EV_MSC, MSC_SCAN, raw_data[i]); - if (raw_data[i] < PICOLCD_KEYS) - key_code = data->keycode[raw_data[i]]; - else - key_code = KEY_UNKNOWN; - if (key_code != KEY_UNKNOWN) { - dbg_hid(PICOLCD_NAME " got key press for %u:%d", - raw_data[i], key_code); - input_report_key(data->input_keys, key_code, 1); - } - input_sync(data->input_keys); -key_already_down: - continue; - } - - /* determine newly released keys */ - for (j = 0; j < sizeof(data->pressed_keys); j++) { - unsigned int key_code; - if (data->pressed_keys[j] == 0) - continue; - for (i = 0; i < size; i++) - if (data->pressed_keys[j] == raw_data[i]) - goto key_still_down; - input_event(data->input_keys, EV_MSC, MSC_SCAN, data->pressed_keys[j]); - if (data->pressed_keys[j] < PICOLCD_KEYS) - key_code = data->keycode[data->pressed_keys[j]]; - else - key_code = KEY_UNKNOWN; - if (key_code != KEY_UNKNOWN) { - dbg_hid(PICOLCD_NAME " got key release for %u:%d", - data->pressed_keys[j], key_code); - input_report_key(data->input_keys, key_code, 0); - } - input_sync(data->input_keys); - data->pressed_keys[j] = 0; -key_still_down: - continue; - } - return 1; -} - -static int picolcd_check_version(struct hid_device *hdev) -{ - struct picolcd_data *data = hid_get_drvdata(hdev); - struct picolcd_pending *verinfo; - int ret = 0; - - if (!data) - return -ENODEV; - - verinfo = picolcd_send_and_wait(hdev, REPORT_VERSION, NULL, 0); - if (!verinfo) { - hid_err(hdev, "no version response from PicoLCD\n"); - return -ENODEV; - } - - if (verinfo->raw_size == 2) { - data->version[0] = verinfo->raw_data[1]; - data->version[1] = verinfo->raw_data[0]; - if (data->status & PICOLCD_BOOTLOADER) { - hid_info(hdev, "PicoLCD, bootloader version %d.%d\n", - verinfo->raw_data[1], verinfo->raw_data[0]); - } else { - hid_info(hdev, "PicoLCD, firmware version %d.%d\n", - verinfo->raw_data[1], verinfo->raw_data[0]); - } - } else { - hid_err(hdev, "confused, got unexpected version response from PicoLCD\n"); - ret = -EINVAL; - } - kfree(verinfo); - return ret; -} - -/* - * Reset our device and wait for answer to VERSION request - */ -int picolcd_reset(struct hid_device *hdev) -{ - struct picolcd_data *data = hid_get_drvdata(hdev); - struct hid_report *report = picolcd_out_report(REPORT_RESET, hdev); - unsigned long flags; - int error; - - if (!data || !report || report->maxfield != 1) - return -ENODEV; - - spin_lock_irqsave(&data->lock, flags); - if (hdev->product == USB_DEVICE_ID_PICOLCD_BOOTLOADER) - data->status |= PICOLCD_BOOTLOADER; - - /* perform the reset */ - hid_set_field(report->field[0], 0, 1); - if (data->status & PICOLCD_FAILED) { - spin_unlock_irqrestore(&data->lock, flags); - return -ENODEV; - } - usbhid_submit_report(hdev, report, USB_DIR_OUT); - spin_unlock_irqrestore(&data->lock, flags); - - error = picolcd_check_version(hdev); - if (error) - return error; - - picolcd_resume_lcd(data); - picolcd_resume_backlight(data); - picolcd_fb_refresh(data); - picolcd_leds_set(data); - return 0; -} - -/* - * The "operation_mode" sysfs attribute - */ -static ssize_t picolcd_operation_mode_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct picolcd_data *data = dev_get_drvdata(dev); - - if (data->status & PICOLCD_BOOTLOADER) - return snprintf(buf, PAGE_SIZE, "[bootloader] lcd\n"); - else - return snprintf(buf, PAGE_SIZE, "bootloader [lcd]\n"); -} - -static ssize_t picolcd_operation_mode_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - struct picolcd_data *data = dev_get_drvdata(dev); - struct hid_report *report = NULL; - size_t cnt = count; - int timeout = data->opmode_delay; - unsigned long flags; - - if (cnt >= 3 && strncmp("lcd", buf, 3) == 0) { - if (data->status & PICOLCD_BOOTLOADER) - report = picolcd_out_report(REPORT_EXIT_FLASHER, data->hdev); - buf += 3; - cnt -= 3; - } else if (cnt >= 10 && strncmp("bootloader", buf, 10) == 0) { - if (!(data->status & PICOLCD_BOOTLOADER)) - report = picolcd_out_report(REPORT_EXIT_KEYBOARD, data->hdev); - buf += 10; - cnt -= 10; - } - if (!report) - return -EINVAL; - - while (cnt > 0 && (buf[cnt-1] == '\n' || buf[cnt-1] == '\r')) - cnt--; - if (cnt != 0) - return -EINVAL; - - spin_lock_irqsave(&data->lock, flags); - hid_set_field(report->field[0], 0, timeout & 0xff); - hid_set_field(report->field[0], 1, (timeout >> 8) & 0xff); - usbhid_submit_report(data->hdev, report, USB_DIR_OUT); - spin_unlock_irqrestore(&data->lock, flags); - return count; -} - -static DEVICE_ATTR(operation_mode, 0644, picolcd_operation_mode_show, - picolcd_operation_mode_store); - -/* - * The "operation_mode_delay" sysfs attribute - */ -static ssize_t picolcd_operation_mode_delay_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct picolcd_data *data = dev_get_drvdata(dev); - - return snprintf(buf, PAGE_SIZE, "%hu\n", data->opmode_delay); -} - -static ssize_t picolcd_operation_mode_delay_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - struct picolcd_data *data = dev_get_drvdata(dev); - unsigned u; - if (sscanf(buf, "%u", &u) != 1) - return -EINVAL; - if (u > 30000) - return -EINVAL; - else - data->opmode_delay = u; - return count; -} - -static DEVICE_ATTR(operation_mode_delay, 0644, picolcd_operation_mode_delay_show, - picolcd_operation_mode_delay_store); - -/* - * Handle raw report as sent by device - */ -static int picolcd_raw_event(struct hid_device *hdev, - struct hid_report *report, u8 *raw_data, int size) -{ - struct picolcd_data *data = hid_get_drvdata(hdev); - unsigned long flags; - int ret = 0; - - if (!data) - return 1; - - if (report->id == REPORT_KEY_STATE) { - if (data->input_keys) - ret = picolcd_raw_keypad(data, report, raw_data+1, size-1); - } else if (report->id == REPORT_IR_DATA) { - ret = picolcd_raw_cir(data, report, raw_data+1, size-1); - } else { - spin_lock_irqsave(&data->lock, flags); - /* - * We let the caller of picolcd_send_and_wait() check if the - * report we got is one of the expected ones or not. - */ - if (data->pending) { - memcpy(data->pending->raw_data, raw_data+1, size-1); - data->pending->raw_size = size-1; - data->pending->in_report = report; - complete(&data->pending->ready); - } - spin_unlock_irqrestore(&data->lock, flags); - } - - picolcd_debug_raw_event(data, hdev, report, raw_data, size); - return 1; -} - -#ifdef CONFIG_PM -static int picolcd_suspend(struct hid_device *hdev, pm_message_t message) -{ - if (PMSG_IS_AUTO(message)) - return 0; - - picolcd_suspend_backlight(hid_get_drvdata(hdev)); - dbg_hid(PICOLCD_NAME " device ready for suspend\n"); - return 0; -} - -static int picolcd_resume(struct hid_device *hdev) -{ - int ret; - ret = picolcd_resume_backlight(hid_get_drvdata(hdev)); - if (ret) - dbg_hid(PICOLCD_NAME " restoring backlight failed: %d\n", ret); - return 0; -} - -static int picolcd_reset_resume(struct hid_device *hdev) -{ - int ret; - ret = picolcd_reset(hdev); - if (ret) - dbg_hid(PICOLCD_NAME " resetting our device failed: %d\n", ret); - ret = picolcd_fb_reset(hid_get_drvdata(hdev), 0); - if (ret) - dbg_hid(PICOLCD_NAME " restoring framebuffer content failed: %d\n", ret); - ret = picolcd_resume_lcd(hid_get_drvdata(hdev)); - if (ret) - dbg_hid(PICOLCD_NAME " restoring lcd failed: %d\n", ret); - ret = picolcd_resume_backlight(hid_get_drvdata(hdev)); - if (ret) - dbg_hid(PICOLCD_NAME " restoring backlight failed: %d\n", ret); - picolcd_leds_set(hid_get_drvdata(hdev)); - return 0; -} -#endif - -/* initialize keypad input device */ -static int picolcd_init_keys(struct picolcd_data *data, - struct hid_report *report) -{ - struct hid_device *hdev = data->hdev; - struct input_dev *idev; - int error, i; - - if (!report) - return -ENODEV; - if (report->maxfield != 1 || report->field[0]->report_count != 2 || - report->field[0]->report_size != 8) { - hid_err(hdev, "unsupported KEY_STATE report\n"); - return -EINVAL; - } - - idev = input_allocate_device(); - if (idev == NULL) { - hid_err(hdev, "failed to allocate input device\n"); - return -ENOMEM; - } - input_set_drvdata(idev, hdev); - memcpy(data->keycode, def_keymap, sizeof(def_keymap)); - idev->name = hdev->name; - idev->phys = hdev->phys; - idev->uniq = hdev->uniq; - idev->id.bustype = hdev->bus; - idev->id.vendor = hdev->vendor; - idev->id.product = hdev->product; - idev->id.version = hdev->version; - idev->dev.parent = &hdev->dev; - idev->keycode = &data->keycode; - idev->keycodemax = PICOLCD_KEYS; - idev->keycodesize = sizeof(data->keycode[0]); - input_set_capability(idev, EV_MSC, MSC_SCAN); - set_bit(EV_REP, idev->evbit); - for (i = 0; i < PICOLCD_KEYS; i++) - input_set_capability(idev, EV_KEY, data->keycode[i]); - error = input_register_device(idev); - if (error) { - hid_err(hdev, "error registering the input device\n"); - input_free_device(idev); - return error; - } - data->input_keys = idev; - return 0; -} - -static void picolcd_exit_keys(struct picolcd_data *data) -{ - struct input_dev *idev = data->input_keys; - - data->input_keys = NULL; - if (idev) - input_unregister_device(idev); -} - -static int picolcd_probe_lcd(struct hid_device *hdev, struct picolcd_data *data) -{ - int error; - - /* Setup keypad input device */ - error = picolcd_init_keys(data, picolcd_in_report(REPORT_KEY_STATE, hdev)); - if (error) - goto err; - - /* Setup CIR input device */ - error = picolcd_init_cir(data, picolcd_in_report(REPORT_IR_DATA, hdev)); - if (error) - goto err; - - /* Set up the framebuffer device */ - error = picolcd_init_framebuffer(data); - if (error) - goto err; - - /* Setup lcd class device */ - error = picolcd_init_lcd(data, picolcd_out_report(REPORT_CONTRAST, hdev)); - if (error) - goto err; - - /* Setup backlight class device */ - error = picolcd_init_backlight(data, picolcd_out_report(REPORT_BRIGHTNESS, hdev)); - if (error) - goto err; - - /* Setup the LED class devices */ - error = picolcd_init_leds(data, picolcd_out_report(REPORT_LED_STATE, hdev)); - if (error) - goto err; - - picolcd_init_devfs(data, picolcd_out_report(REPORT_EE_READ, hdev), - picolcd_out_report(REPORT_EE_WRITE, hdev), - picolcd_out_report(REPORT_READ_MEMORY, hdev), - picolcd_out_report(REPORT_WRITE_MEMORY, hdev), - picolcd_out_report(REPORT_RESET, hdev)); - return 0; -err: - picolcd_exit_leds(data); - picolcd_exit_backlight(data); - picolcd_exit_lcd(data); - picolcd_exit_framebuffer(data); - picolcd_exit_cir(data); - picolcd_exit_keys(data); - return error; -} - -static int picolcd_probe_bootloader(struct hid_device *hdev, struct picolcd_data *data) -{ - picolcd_init_devfs(data, NULL, NULL, - picolcd_out_report(REPORT_BL_READ_MEMORY, hdev), - picolcd_out_report(REPORT_BL_WRITE_MEMORY, hdev), NULL); - return 0; -} - -static int picolcd_probe(struct hid_device *hdev, - const struct hid_device_id *id) -{ - struct picolcd_data *data; - int error = -ENOMEM; - - dbg_hid(PICOLCD_NAME " hardware probe...\n"); - - /* - * Let's allocate the picolcd data structure, set some reasonable - * defaults, and associate it with the device - */ - data = kzalloc(sizeof(struct picolcd_data), GFP_KERNEL); - if (data == NULL) { - hid_err(hdev, "can't allocate space for Minibox PicoLCD device data\n"); - error = -ENOMEM; - goto err_no_cleanup; - } - - spin_lock_init(&data->lock); - mutex_init(&data->mutex); - data->hdev = hdev; - data->opmode_delay = 5000; - if (hdev->product == USB_DEVICE_ID_PICOLCD_BOOTLOADER) - data->status |= PICOLCD_BOOTLOADER; - hid_set_drvdata(hdev, data); - - /* Parse the device reports and start it up */ - error = hid_parse(hdev); - if (error) { - hid_err(hdev, "device report parse failed\n"); - goto err_cleanup_data; - } - - error = hid_hw_start(hdev, 0); - if (error) { - hid_err(hdev, "hardware start failed\n"); - goto err_cleanup_data; - } - - error = hid_hw_open(hdev); - if (error) { - hid_err(hdev, "failed to open input interrupt pipe for key and IR events\n"); - goto err_cleanup_hid_hw; - } - - error = device_create_file(&hdev->dev, &dev_attr_operation_mode_delay); - if (error) { - hid_err(hdev, "failed to create sysfs attributes\n"); - goto err_cleanup_hid_ll; - } - - error = device_create_file(&hdev->dev, &dev_attr_operation_mode); - if (error) { - hid_err(hdev, "failed to create sysfs attributes\n"); - goto err_cleanup_sysfs1; - } - - if (data->status & PICOLCD_BOOTLOADER) - error = picolcd_probe_bootloader(hdev, data); - else - error = picolcd_probe_lcd(hdev, data); - if (error) - goto err_cleanup_sysfs2; - - dbg_hid(PICOLCD_NAME " activated and initialized\n"); - return 0; - -err_cleanup_sysfs2: - device_remove_file(&hdev->dev, &dev_attr_operation_mode); -err_cleanup_sysfs1: - device_remove_file(&hdev->dev, &dev_attr_operation_mode_delay); -err_cleanup_hid_ll: - hid_hw_close(hdev); -err_cleanup_hid_hw: - hid_hw_stop(hdev); -err_cleanup_data: - kfree(data); -err_no_cleanup: - hid_set_drvdata(hdev, NULL); - - return error; -} - -static void picolcd_remove(struct hid_device *hdev) -{ - struct picolcd_data *data = hid_get_drvdata(hdev); - unsigned long flags; - - dbg_hid(PICOLCD_NAME " hardware remove...\n"); - spin_lock_irqsave(&data->lock, flags); - data->status |= PICOLCD_FAILED; - spin_unlock_irqrestore(&data->lock, flags); - - picolcd_exit_devfs(data); - device_remove_file(&hdev->dev, &dev_attr_operation_mode); - device_remove_file(&hdev->dev, &dev_attr_operation_mode_delay); - hid_hw_close(hdev); - hid_hw_stop(hdev); - - /* Shortcut potential pending reply that will never arrive */ - spin_lock_irqsave(&data->lock, flags); - if (data->pending) - complete(&data->pending->ready); - spin_unlock_irqrestore(&data->lock, flags); - - /* Cleanup LED */ - picolcd_exit_leds(data); - /* Clean up the framebuffer */ - picolcd_exit_backlight(data); - picolcd_exit_lcd(data); - picolcd_exit_framebuffer(data); - /* Cleanup input */ - picolcd_exit_cir(data); - picolcd_exit_keys(data); - - hid_set_drvdata(hdev, NULL); - mutex_destroy(&data->mutex); - /* Finally, clean up the picolcd data itself */ - kfree(data); -} - -static const struct hid_device_id picolcd_devices[] = { - { HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICOLCD) }, - { HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICOLCD_BOOTLOADER) }, - { } -}; -MODULE_DEVICE_TABLE(hid, picolcd_devices); - -static struct hid_driver picolcd_driver = { - .name = "hid-picolcd", - .id_table = picolcd_devices, - .probe = picolcd_probe, - .remove = picolcd_remove, - .raw_event = picolcd_raw_event, -#ifdef CONFIG_PM - .suspend = picolcd_suspend, - .resume = picolcd_resume, - .reset_resume = picolcd_reset_resume, -#endif -}; - -static int __init picolcd_init(void) -{ - return hid_register_driver(&picolcd_driver); -} - -static void __exit picolcd_exit(void) -{ - hid_unregister_driver(&picolcd_driver); -} - -module_init(picolcd_init); -module_exit(picolcd_exit); -MODULE_DESCRIPTION("Minibox graphics PicoLCD Driver"); -MODULE_LICENSE("GPL v2"); diff --git a/trunk/drivers/hid/hid-picolcd_debugfs.c b/trunk/drivers/hid/hid-picolcd_debugfs.c deleted file mode 100644 index 4809aa1bdb9c..000000000000 --- a/trunk/drivers/hid/hid-picolcd_debugfs.c +++ /dev/null @@ -1,899 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2010-2012 by Bruno Prémont * - * * - * Based on Logitech G13 driver (v0.4) * - * Copyright (C) 2009 by Rick L. Vinyard, Jr. * - * * - * 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 driver 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 software. If not see . * - ***************************************************************************/ - -#include -#include -#include "usbhid/usbhid.h" -#include - -#include -#include -#include - -#include -#include - -#include "hid-picolcd.h" - - -static int picolcd_debug_reset_show(struct seq_file *f, void *p) -{ - if (picolcd_fbinfo((struct picolcd_data *)f->private)) - seq_printf(f, "all fb\n"); - else - seq_printf(f, "all\n"); - return 0; -} - -static int picolcd_debug_reset_open(struct inode *inode, struct file *f) -{ - return single_open(f, picolcd_debug_reset_show, inode->i_private); -} - -static ssize_t picolcd_debug_reset_write(struct file *f, const char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct picolcd_data *data = ((struct seq_file *)f->private_data)->private; - char buf[32]; - size_t cnt = min(count, sizeof(buf)-1); - if (copy_from_user(buf, user_buf, cnt)) - return -EFAULT; - - while (cnt > 0 && (buf[cnt-1] == ' ' || buf[cnt-1] == '\n')) - cnt--; - buf[cnt] = '\0'; - if (strcmp(buf, "all") == 0) { - picolcd_reset(data->hdev); - picolcd_fb_reset(data, 1); - } else if (strcmp(buf, "fb") == 0) { - picolcd_fb_reset(data, 1); - } else { - return -EINVAL; - } - return count; -} - -static const struct file_operations picolcd_debug_reset_fops = { - .owner = THIS_MODULE, - .open = picolcd_debug_reset_open, - .read = seq_read, - .llseek = seq_lseek, - .write = picolcd_debug_reset_write, - .release = single_release, -}; - -/* - * The "eeprom" file - */ -static ssize_t picolcd_debug_eeprom_read(struct file *f, char __user *u, - size_t s, loff_t *off) -{ - struct picolcd_data *data = f->private_data; - struct picolcd_pending *resp; - u8 raw_data[3]; - ssize_t ret = -EIO; - - if (s == 0) - return -EINVAL; - if (*off > 0x0ff) - return 0; - - /* prepare buffer with info about what we want to read (addr & len) */ - raw_data[0] = *off & 0xff; - raw_data[1] = (*off >> 8) & 0xff; - raw_data[2] = s < 20 ? s : 20; - if (*off + raw_data[2] > 0xff) - raw_data[2] = 0x100 - *off; - resp = picolcd_send_and_wait(data->hdev, REPORT_EE_READ, raw_data, - sizeof(raw_data)); - if (!resp) - return -EIO; - - if (resp->in_report && resp->in_report->id == REPORT_EE_DATA) { - /* successful read :) */ - ret = resp->raw_data[2]; - if (ret > s) - ret = s; - if (copy_to_user(u, resp->raw_data+3, ret)) - ret = -EFAULT; - else - *off += ret; - } /* anything else is some kind of IO error */ - - kfree(resp); - return ret; -} - -static ssize_t picolcd_debug_eeprom_write(struct file *f, const char __user *u, - size_t s, loff_t *off) -{ - struct picolcd_data *data = f->private_data; - struct picolcd_pending *resp; - ssize_t ret = -EIO; - u8 raw_data[23]; - - if (s == 0) - return -EINVAL; - if (*off > 0x0ff) - return -ENOSPC; - - memset(raw_data, 0, sizeof(raw_data)); - raw_data[0] = *off & 0xff; - raw_data[1] = (*off >> 8) & 0xff; - raw_data[2] = min_t(size_t, 20, s); - if (*off + raw_data[2] > 0xff) - raw_data[2] = 0x100 - *off; - - if (copy_from_user(raw_data+3, u, min((u8)20, raw_data[2]))) - return -EFAULT; - resp = picolcd_send_and_wait(data->hdev, REPORT_EE_WRITE, raw_data, - sizeof(raw_data)); - - if (!resp) - return -EIO; - - if (resp->in_report && resp->in_report->id == REPORT_EE_DATA) { - /* check if written data matches */ - if (memcmp(raw_data, resp->raw_data, 3+raw_data[2]) == 0) { - *off += raw_data[2]; - ret = raw_data[2]; - } - } - kfree(resp); - return ret; -} - -/* - * Notes: - * - read/write happens in chunks of at most 20 bytes, it's up to userspace - * to loop in order to get more data. - * - on write errors on otherwise correct write request the bytes - * that should have been written are in undefined state. - */ -static const struct file_operations picolcd_debug_eeprom_fops = { - .owner = THIS_MODULE, - .open = simple_open, - .read = picolcd_debug_eeprom_read, - .write = picolcd_debug_eeprom_write, - .llseek = generic_file_llseek, -}; - -/* - * The "flash" file - */ -/* record a flash address to buf (bounds check to be done by caller) */ -static int _picolcd_flash_setaddr(struct picolcd_data *data, u8 *buf, long off) -{ - buf[0] = off & 0xff; - buf[1] = (off >> 8) & 0xff; - if (data->addr_sz == 3) - buf[2] = (off >> 16) & 0xff; - return data->addr_sz == 2 ? 2 : 3; -} - -/* read a given size of data (bounds check to be done by caller) */ -static ssize_t _picolcd_flash_read(struct picolcd_data *data, int report_id, - char __user *u, size_t s, loff_t *off) -{ - struct picolcd_pending *resp; - u8 raw_data[4]; - ssize_t ret = 0; - int len_off, err = -EIO; - - while (s > 0) { - err = -EIO; - len_off = _picolcd_flash_setaddr(data, raw_data, *off); - raw_data[len_off] = s > 32 ? 32 : s; - resp = picolcd_send_and_wait(data->hdev, report_id, raw_data, len_off+1); - if (!resp || !resp->in_report) - goto skip; - if (resp->in_report->id == REPORT_MEMORY || - resp->in_report->id == REPORT_BL_READ_MEMORY) { - if (memcmp(raw_data, resp->raw_data, len_off+1) != 0) - goto skip; - if (copy_to_user(u+ret, resp->raw_data+len_off+1, raw_data[len_off])) { - err = -EFAULT; - goto skip; - } - *off += raw_data[len_off]; - s -= raw_data[len_off]; - ret += raw_data[len_off]; - err = 0; - } -skip: - kfree(resp); - if (err) - return ret > 0 ? ret : err; - } - return ret; -} - -static ssize_t picolcd_debug_flash_read(struct file *f, char __user *u, - size_t s, loff_t *off) -{ - struct picolcd_data *data = f->private_data; - - if (s == 0) - return -EINVAL; - if (*off > 0x05fff) - return 0; - if (*off + s > 0x05fff) - s = 0x06000 - *off; - - if (data->status & PICOLCD_BOOTLOADER) - return _picolcd_flash_read(data, REPORT_BL_READ_MEMORY, u, s, off); - else - return _picolcd_flash_read(data, REPORT_READ_MEMORY, u, s, off); -} - -/* erase block aligned to 64bytes boundary */ -static ssize_t _picolcd_flash_erase64(struct picolcd_data *data, int report_id, - loff_t *off) -{ - struct picolcd_pending *resp; - u8 raw_data[3]; - int len_off; - ssize_t ret = -EIO; - - if (*off & 0x3f) - return -EINVAL; - - len_off = _picolcd_flash_setaddr(data, raw_data, *off); - resp = picolcd_send_and_wait(data->hdev, report_id, raw_data, len_off); - if (!resp || !resp->in_report) - goto skip; - if (resp->in_report->id == REPORT_MEMORY || - resp->in_report->id == REPORT_BL_ERASE_MEMORY) { - if (memcmp(raw_data, resp->raw_data, len_off) != 0) - goto skip; - ret = 0; - } -skip: - kfree(resp); - return ret; -} - -/* write a given size of data (bounds check to be done by caller) */ -static ssize_t _picolcd_flash_write(struct picolcd_data *data, int report_id, - const char __user *u, size_t s, loff_t *off) -{ - struct picolcd_pending *resp; - u8 raw_data[36]; - ssize_t ret = 0; - int len_off, err = -EIO; - - while (s > 0) { - err = -EIO; - len_off = _picolcd_flash_setaddr(data, raw_data, *off); - raw_data[len_off] = s > 32 ? 32 : s; - if (copy_from_user(raw_data+len_off+1, u, raw_data[len_off])) { - err = -EFAULT; - break; - } - resp = picolcd_send_and_wait(data->hdev, report_id, raw_data, - len_off+1+raw_data[len_off]); - if (!resp || !resp->in_report) - goto skip; - if (resp->in_report->id == REPORT_MEMORY || - resp->in_report->id == REPORT_BL_WRITE_MEMORY) { - if (memcmp(raw_data, resp->raw_data, len_off+1+raw_data[len_off]) != 0) - goto skip; - *off += raw_data[len_off]; - s -= raw_data[len_off]; - ret += raw_data[len_off]; - err = 0; - } -skip: - kfree(resp); - if (err) - break; - } - return ret > 0 ? ret : err; -} - -static ssize_t picolcd_debug_flash_write(struct file *f, const char __user *u, - size_t s, loff_t *off) -{ - struct picolcd_data *data = f->private_data; - ssize_t err, ret = 0; - int report_erase, report_write; - - if (s == 0) - return -EINVAL; - if (*off > 0x5fff) - return -ENOSPC; - if (s & 0x3f) - return -EINVAL; - if (*off & 0x3f) - return -EINVAL; - - if (data->status & PICOLCD_BOOTLOADER) { - report_erase = REPORT_BL_ERASE_MEMORY; - report_write = REPORT_BL_WRITE_MEMORY; - } else { - report_erase = REPORT_ERASE_MEMORY; - report_write = REPORT_WRITE_MEMORY; - } - mutex_lock(&data->mutex_flash); - while (s > 0) { - err = _picolcd_flash_erase64(data, report_erase, off); - if (err) - break; - err = _picolcd_flash_write(data, report_write, u, 64, off); - if (err < 0) - break; - ret += err; - *off += err; - s -= err; - if (err != 64) - break; - } - mutex_unlock(&data->mutex_flash); - return ret > 0 ? ret : err; -} - -/* - * Notes: - * - concurrent writing is prevented by mutex and all writes must be - * n*64 bytes and 64-byte aligned, each write being preceded by an - * ERASE which erases a 64byte block. - * If less than requested was written or an error is returned for an - * otherwise correct write request the next 64-byte block which should - * have been written is in undefined state (mostly: original, erased, - * (half-)written with write error) - * - reading can happen without special restriction - */ -static const struct file_operations picolcd_debug_flash_fops = { - .owner = THIS_MODULE, - .open = simple_open, - .read = picolcd_debug_flash_read, - .write = picolcd_debug_flash_write, - .llseek = generic_file_llseek, -}; - - -/* - * Helper code for HID report level dumping/debugging - */ -static const char * const error_codes[] = { - "success", "parameter missing", "data_missing", "block readonly", - "block not erasable", "block too big", "section overflow", - "invalid command length", "invalid data length", -}; - -static void dump_buff_as_hex(char *dst, size_t dst_sz, const u8 *data, - const size_t data_len) -{ - int i, j; - for (i = j = 0; i < data_len && j + 4 < dst_sz; i++) { - dst[j++] = hex_asc[(data[i] >> 4) & 0x0f]; - dst[j++] = hex_asc[data[i] & 0x0f]; - dst[j++] = ' '; - } - dst[j] = '\0'; - if (j > 0) - dst[j-1] = '\n'; - if (i < data_len && j > 2) - dst[j-2] = dst[j-3] = '.'; -} - -void picolcd_debug_out_report(struct picolcd_data *data, - struct hid_device *hdev, struct hid_report *report) -{ - u8 raw_data[70]; - int raw_size = (report->size >> 3) + 1; - char *buff; -#define BUFF_SZ 256 - - /* Avoid unnecessary overhead if debugfs is disabled */ - if (list_empty(&hdev->debug_list)) - return; - - buff = kmalloc(BUFF_SZ, GFP_ATOMIC); - if (!buff) - return; - - snprintf(buff, BUFF_SZ, "\nout report %d (size %d) = ", - report->id, raw_size); - hid_debug_event(hdev, buff); - if (raw_size + 5 > sizeof(raw_data)) { - kfree(buff); - hid_debug_event(hdev, " TOO BIG\n"); - return; - } else { - raw_data[0] = report->id; - hid_output_report(report, raw_data); - dump_buff_as_hex(buff, BUFF_SZ, raw_data, raw_size); - hid_debug_event(hdev, buff); - } - - switch (report->id) { - case REPORT_LED_STATE: - /* 1 data byte with GPO state */ - snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n", - "REPORT_LED_STATE", report->id, raw_size-1); - hid_debug_event(hdev, buff); - snprintf(buff, BUFF_SZ, "\tGPO state: 0x%02x\n", raw_data[1]); - hid_debug_event(hdev, buff); - break; - case REPORT_BRIGHTNESS: - /* 1 data byte with brightness */ - snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n", - "REPORT_BRIGHTNESS", report->id, raw_size-1); - hid_debug_event(hdev, buff); - snprintf(buff, BUFF_SZ, "\tBrightness: 0x%02x\n", raw_data[1]); - hid_debug_event(hdev, buff); - break; - case REPORT_CONTRAST: - /* 1 data byte with contrast */ - snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n", - "REPORT_CONTRAST", report->id, raw_size-1); - hid_debug_event(hdev, buff); - snprintf(buff, BUFF_SZ, "\tContrast: 0x%02x\n", raw_data[1]); - hid_debug_event(hdev, buff); - break; - case REPORT_RESET: - /* 2 data bytes with reset duration in ms */ - snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n", - "REPORT_RESET", report->id, raw_size-1); - hid_debug_event(hdev, buff); - snprintf(buff, BUFF_SZ, "\tDuration: 0x%02x%02x (%dms)\n", - raw_data[2], raw_data[1], raw_data[2] << 8 | raw_data[1]); - hid_debug_event(hdev, buff); - break; - case REPORT_LCD_CMD: - /* 63 data bytes with LCD commands */ - snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n", - "REPORT_LCD_CMD", report->id, raw_size-1); - hid_debug_event(hdev, buff); - /* TODO: format decoding */ - break; - case REPORT_LCD_DATA: - /* 63 data bytes with LCD data */ - snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n", - "REPORT_LCD_CMD", report->id, raw_size-1); - /* TODO: format decoding */ - hid_debug_event(hdev, buff); - break; - case REPORT_LCD_CMD_DATA: - /* 63 data bytes with LCD commands and data */ - snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n", - "REPORT_LCD_CMD", report->id, raw_size-1); - /* TODO: format decoding */ - hid_debug_event(hdev, buff); - break; - case REPORT_EE_READ: - /* 3 data bytes with read area description */ - snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n", - "REPORT_EE_READ", report->id, raw_size-1); - hid_debug_event(hdev, buff); - snprintf(buff, BUFF_SZ, "\tData address: 0x%02x%02x\n", - raw_data[2], raw_data[1]); - hid_debug_event(hdev, buff); - snprintf(buff, BUFF_SZ, "\tData length: %d\n", raw_data[3]); - hid_debug_event(hdev, buff); - break; - case REPORT_EE_WRITE: - /* 3+1..20 data bytes with write area description */ - snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n", - "REPORT_EE_WRITE", report->id, raw_size-1); - hid_debug_event(hdev, buff); - snprintf(buff, BUFF_SZ, "\tData address: 0x%02x%02x\n", - raw_data[2], raw_data[1]); - hid_debug_event(hdev, buff); - snprintf(buff, BUFF_SZ, "\tData length: %d\n", raw_data[3]); - hid_debug_event(hdev, buff); - if (raw_data[3] == 0) { - snprintf(buff, BUFF_SZ, "\tNo data\n"); - } else if (raw_data[3] + 4 <= raw_size) { - snprintf(buff, BUFF_SZ, "\tData: "); - hid_debug_event(hdev, buff); - dump_buff_as_hex(buff, BUFF_SZ, raw_data+4, raw_data[3]); - } else { - snprintf(buff, BUFF_SZ, "\tData overflowed\n"); - } - hid_debug_event(hdev, buff); - break; - case REPORT_ERASE_MEMORY: - case REPORT_BL_ERASE_MEMORY: - /* 3 data bytes with pointer inside erase block */ - snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n", - "REPORT_ERASE_MEMORY", report->id, raw_size-1); - hid_debug_event(hdev, buff); - switch (data->addr_sz) { - case 2: - snprintf(buff, BUFF_SZ, "\tAddress inside 64 byte block: 0x%02x%02x\n", - raw_data[2], raw_data[1]); - break; - case 3: - snprintf(buff, BUFF_SZ, "\tAddress inside 64 byte block: 0x%02x%02x%02x\n", - raw_data[3], raw_data[2], raw_data[1]); - break; - default: - snprintf(buff, BUFF_SZ, "\tNot supported\n"); - } - hid_debug_event(hdev, buff); - break; - case REPORT_READ_MEMORY: - case REPORT_BL_READ_MEMORY: - /* 4 data bytes with read area description */ - snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n", - "REPORT_READ_MEMORY", report->id, raw_size-1); - hid_debug_event(hdev, buff); - switch (data->addr_sz) { - case 2: - snprintf(buff, BUFF_SZ, "\tData address: 0x%02x%02x\n", - raw_data[2], raw_data[1]); - hid_debug_event(hdev, buff); - snprintf(buff, BUFF_SZ, "\tData length: %d\n", raw_data[3]); - break; - case 3: - snprintf(buff, BUFF_SZ, "\tData address: 0x%02x%02x%02x\n", - raw_data[3], raw_data[2], raw_data[1]); - hid_debug_event(hdev, buff); - snprintf(buff, BUFF_SZ, "\tData length: %d\n", raw_data[4]); - break; - default: - snprintf(buff, BUFF_SZ, "\tNot supported\n"); - } - hid_debug_event(hdev, buff); - break; - case REPORT_WRITE_MEMORY: - case REPORT_BL_WRITE_MEMORY: - /* 4+1..32 data bytes with write adrea description */ - snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n", - "REPORT_WRITE_MEMORY", report->id, raw_size-1); - hid_debug_event(hdev, buff); - switch (data->addr_sz) { - case 2: - snprintf(buff, BUFF_SZ, "\tData address: 0x%02x%02x\n", - raw_data[2], raw_data[1]); - hid_debug_event(hdev, buff); - snprintf(buff, BUFF_SZ, "\tData length: %d\n", raw_data[3]); - hid_debug_event(hdev, buff); - if (raw_data[3] == 0) { - snprintf(buff, BUFF_SZ, "\tNo data\n"); - } else if (raw_data[3] + 4 <= raw_size) { - snprintf(buff, BUFF_SZ, "\tData: "); - hid_debug_event(hdev, buff); - dump_buff_as_hex(buff, BUFF_SZ, raw_data+4, raw_data[3]); - } else { - snprintf(buff, BUFF_SZ, "\tData overflowed\n"); - } - break; - case 3: - snprintf(buff, BUFF_SZ, "\tData address: 0x%02x%02x%02x\n", - raw_data[3], raw_data[2], raw_data[1]); - hid_debug_event(hdev, buff); - snprintf(buff, BUFF_SZ, "\tData length: %d\n", raw_data[4]); - hid_debug_event(hdev, buff); - if (raw_data[4] == 0) { - snprintf(buff, BUFF_SZ, "\tNo data\n"); - } else if (raw_data[4] + 5 <= raw_size) { - snprintf(buff, BUFF_SZ, "\tData: "); - hid_debug_event(hdev, buff); - dump_buff_as_hex(buff, BUFF_SZ, raw_data+5, raw_data[4]); - } else { - snprintf(buff, BUFF_SZ, "\tData overflowed\n"); - } - break; - default: - snprintf(buff, BUFF_SZ, "\tNot supported\n"); - } - hid_debug_event(hdev, buff); - break; - case REPORT_SPLASH_RESTART: - /* TODO */ - break; - case REPORT_EXIT_KEYBOARD: - snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n", - "REPORT_EXIT_KEYBOARD", report->id, raw_size-1); - hid_debug_event(hdev, buff); - snprintf(buff, BUFF_SZ, "\tRestart delay: %dms (0x%02x%02x)\n", - raw_data[1] | (raw_data[2] << 8), - raw_data[2], raw_data[1]); - hid_debug_event(hdev, buff); - break; - case REPORT_VERSION: - snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n", - "REPORT_VERSION", report->id, raw_size-1); - hid_debug_event(hdev, buff); - break; - case REPORT_DEVID: - snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n", - "REPORT_DEVID", report->id, raw_size-1); - hid_debug_event(hdev, buff); - break; - case REPORT_SPLASH_SIZE: - snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n", - "REPORT_SPLASH_SIZE", report->id, raw_size-1); - hid_debug_event(hdev, buff); - break; - case REPORT_HOOK_VERSION: - snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n", - "REPORT_HOOK_VERSION", report->id, raw_size-1); - hid_debug_event(hdev, buff); - break; - case REPORT_EXIT_FLASHER: - snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n", - "REPORT_VERSION", report->id, raw_size-1); - hid_debug_event(hdev, buff); - snprintf(buff, BUFF_SZ, "\tRestart delay: %dms (0x%02x%02x)\n", - raw_data[1] | (raw_data[2] << 8), - raw_data[2], raw_data[1]); - hid_debug_event(hdev, buff); - break; - default: - snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n", - "", report->id, raw_size-1); - hid_debug_event(hdev, buff); - break; - } - wake_up_interruptible(&hdev->debug_wait); - kfree(buff); -} - -void picolcd_debug_raw_event(struct picolcd_data *data, - struct hid_device *hdev, struct hid_report *report, - u8 *raw_data, int size) -{ - char *buff; - -#define BUFF_SZ 256 - /* Avoid unnecessary overhead if debugfs is disabled */ - if (list_empty(&hdev->debug_list)) - return; - - buff = kmalloc(BUFF_SZ, GFP_ATOMIC); - if (!buff) - return; - - switch (report->id) { - case REPORT_ERROR_CODE: - /* 2 data bytes with affected report and error code */ - snprintf(buff, BUFF_SZ, "report %s (%d, size=%d)\n", - "REPORT_ERROR_CODE", report->id, size-1); - hid_debug_event(hdev, buff); - if (raw_data[2] < ARRAY_SIZE(error_codes)) - snprintf(buff, BUFF_SZ, "\tError code 0x%02x (%s) in reply to report 0x%02x\n", - raw_data[2], error_codes[raw_data[2]], raw_data[1]); - else - snprintf(buff, BUFF_SZ, "\tError code 0x%02x in reply to report 0x%02x\n", - raw_data[2], raw_data[1]); - hid_debug_event(hdev, buff); - break; - case REPORT_KEY_STATE: - /* 2 data bytes with key state */ - snprintf(buff, BUFF_SZ, "report %s (%d, size=%d)\n", - "REPORT_KEY_STATE", report->id, size-1); - hid_debug_event(hdev, buff); - if (raw_data[1] == 0) - snprintf(buff, BUFF_SZ, "\tNo key pressed\n"); - else if (raw_data[2] == 0) - snprintf(buff, BUFF_SZ, "\tOne key pressed: 0x%02x (%d)\n", - raw_data[1], raw_data[1]); - else - snprintf(buff, BUFF_SZ, "\tTwo keys pressed: 0x%02x (%d), 0x%02x (%d)\n", - raw_data[1], raw_data[1], raw_data[2], raw_data[2]); - hid_debug_event(hdev, buff); - break; - case REPORT_IR_DATA: - /* Up to 20 byes of IR scancode data */ - snprintf(buff, BUFF_SZ, "report %s (%d, size=%d)\n", - "REPORT_IR_DATA", report->id, size-1); - hid_debug_event(hdev, buff); - if (raw_data[1] == 0) { - snprintf(buff, BUFF_SZ, "\tUnexpectedly 0 data length\n"); - hid_debug_event(hdev, buff); - } else if (raw_data[1] + 1 <= size) { - snprintf(buff, BUFF_SZ, "\tData length: %d\n\tIR Data: ", - raw_data[1]); - hid_debug_event(hdev, buff); - dump_buff_as_hex(buff, BUFF_SZ, raw_data+2, raw_data[1]); - hid_debug_event(hdev, buff); - } else { - snprintf(buff, BUFF_SZ, "\tOverflowing data length: %d\n", - raw_data[1]-1); - hid_debug_event(hdev, buff); - } - break; - case REPORT_EE_DATA: - /* Data buffer in response to REPORT_EE_READ or REPORT_EE_WRITE */ - snprintf(buff, BUFF_SZ, "report %s (%d, size=%d)\n", - "REPORT_EE_DATA", report->id, size-1); - hid_debug_event(hdev, buff); - snprintf(buff, BUFF_SZ, "\tData address: 0x%02x%02x\n", - raw_data[2], raw_data[1]); - hid_debug_event(hdev, buff); - snprintf(buff, BUFF_SZ, "\tData length: %d\n", raw_data[3]); - hid_debug_event(hdev, buff); - if (raw_data[3] == 0) { - snprintf(buff, BUFF_SZ, "\tNo data\n"); - hid_debug_event(hdev, buff); - } else if (raw_data[3] + 4 <= size) { - snprintf(buff, BUFF_SZ, "\tData: "); - hid_debug_event(hdev, buff); - dump_buff_as_hex(buff, BUFF_SZ, raw_data+4, raw_data[3]); - hid_debug_event(hdev, buff); - } else { - snprintf(buff, BUFF_SZ, "\tData overflowed\n"); - hid_debug_event(hdev, buff); - } - break; - case REPORT_MEMORY: - /* Data buffer in response to REPORT_READ_MEMORY or REPORT_WRTIE_MEMORY */ - snprintf(buff, BUFF_SZ, "report %s (%d, size=%d)\n", - "REPORT_MEMORY", report->id, size-1); - hid_debug_event(hdev, buff); - switch (data->addr_sz) { - case 2: - snprintf(buff, BUFF_SZ, "\tData address: 0x%02x%02x\n", - raw_data[2], raw_data[1]); - hid_debug_event(hdev, buff); - snprintf(buff, BUFF_SZ, "\tData length: %d\n", raw_data[3]); - hid_debug_event(hdev, buff); - if (raw_data[3] == 0) { - snprintf(buff, BUFF_SZ, "\tNo data\n"); - } else if (raw_data[3] + 4 <= size) { - snprintf(buff, BUFF_SZ, "\tData: "); - hid_debug_event(hdev, buff); - dump_buff_as_hex(buff, BUFF_SZ, raw_data+4, raw_data[3]); - } else { - snprintf(buff, BUFF_SZ, "\tData overflowed\n"); - } - break; - case 3: - snprintf(buff, BUFF_SZ, "\tData address: 0x%02x%02x%02x\n", - raw_data[3], raw_data[2], raw_data[1]); - hid_debug_event(hdev, buff); - snprintf(buff, BUFF_SZ, "\tData length: %d\n", raw_data[4]); - hid_debug_event(hdev, buff); - if (raw_data[4] == 0) { - snprintf(buff, BUFF_SZ, "\tNo data\n"); - } else if (raw_data[4] + 5 <= size) { - snprintf(buff, BUFF_SZ, "\tData: "); - hid_debug_event(hdev, buff); - dump_buff_as_hex(buff, BUFF_SZ, raw_data+5, raw_data[4]); - } else { - snprintf(buff, BUFF_SZ, "\tData overflowed\n"); - } - break; - default: - snprintf(buff, BUFF_SZ, "\tNot supported\n"); - } - hid_debug_event(hdev, buff); - break; - case REPORT_VERSION: - snprintf(buff, BUFF_SZ, "report %s (%d, size=%d)\n", - "REPORT_VERSION", report->id, size-1); - hid_debug_event(hdev, buff); - snprintf(buff, BUFF_SZ, "\tFirmware version: %d.%d\n", - raw_data[2], raw_data[1]); - hid_debug_event(hdev, buff); - break; - case REPORT_BL_ERASE_MEMORY: - snprintf(buff, BUFF_SZ, "report %s (%d, size=%d)\n", - "REPORT_BL_ERASE_MEMORY", report->id, size-1); - hid_debug_event(hdev, buff); - /* TODO */ - break; - case REPORT_BL_READ_MEMORY: - snprintf(buff, BUFF_SZ, "report %s (%d, size=%d)\n", - "REPORT_BL_READ_MEMORY", report->id, size-1); - hid_debug_event(hdev, buff); - /* TODO */ - break; - case REPORT_BL_WRITE_MEMORY: - snprintf(buff, BUFF_SZ, "report %s (%d, size=%d)\n", - "REPORT_BL_WRITE_MEMORY", report->id, size-1); - hid_debug_event(hdev, buff); - /* TODO */ - break; - case REPORT_DEVID: - snprintf(buff, BUFF_SZ, "report %s (%d, size=%d)\n", - "REPORT_DEVID", report->id, size-1); - hid_debug_event(hdev, buff); - snprintf(buff, BUFF_SZ, "\tSerial: 0x%02x%02x%02x%02x\n", - raw_data[1], raw_data[2], raw_data[3], raw_data[4]); - hid_debug_event(hdev, buff); - snprintf(buff, BUFF_SZ, "\tType: 0x%02x\n", - raw_data[5]); - hid_debug_event(hdev, buff); - break; - case REPORT_SPLASH_SIZE: - snprintf(buff, BUFF_SZ, "report %s (%d, size=%d)\n", - "REPORT_SPLASH_SIZE", report->id, size-1); - hid_debug_event(hdev, buff); - snprintf(buff, BUFF_SZ, "\tTotal splash space: %d\n", - (raw_data[2] << 8) | raw_data[1]); - hid_debug_event(hdev, buff); - snprintf(buff, BUFF_SZ, "\tUsed splash space: %d\n", - (raw_data[4] << 8) | raw_data[3]); - hid_debug_event(hdev, buff); - break; - case REPORT_HOOK_VERSION: - snprintf(buff, BUFF_SZ, "report %s (%d, size=%d)\n", - "REPORT_HOOK_VERSION", report->id, size-1); - hid_debug_event(hdev, buff); - snprintf(buff, BUFF_SZ, "\tFirmware version: %d.%d\n", - raw_data[1], raw_data[2]); - hid_debug_event(hdev, buff); - break; - default: - snprintf(buff, BUFF_SZ, "report %s (%d, size=%d)\n", - "", report->id, size-1); - hid_debug_event(hdev, buff); - break; - } - wake_up_interruptible(&hdev->debug_wait); - kfree(buff); -} - -void picolcd_init_devfs(struct picolcd_data *data, - struct hid_report *eeprom_r, struct hid_report *eeprom_w, - struct hid_report *flash_r, struct hid_report *flash_w, - struct hid_report *reset) -{ - struct hid_device *hdev = data->hdev; - - mutex_init(&data->mutex_flash); - - /* reset */ - if (reset) - data->debug_reset = debugfs_create_file("reset", 0600, - hdev->debug_dir, data, &picolcd_debug_reset_fops); - - /* eeprom */ - if (eeprom_r || eeprom_w) - data->debug_eeprom = debugfs_create_file("eeprom", - (eeprom_w ? S_IWUSR : 0) | (eeprom_r ? S_IRUSR : 0), - hdev->debug_dir, data, &picolcd_debug_eeprom_fops); - - /* flash */ - if (flash_r && flash_r->maxfield == 1 && flash_r->field[0]->report_size == 8) - data->addr_sz = flash_r->field[0]->report_count - 1; - else - data->addr_sz = -1; - if (data->addr_sz == 2 || data->addr_sz == 3) { - data->debug_flash = debugfs_create_file("flash", - (flash_w ? S_IWUSR : 0) | (flash_r ? S_IRUSR : 0), - hdev->debug_dir, data, &picolcd_debug_flash_fops); - } else if (flash_r || flash_w) - hid_warn(hdev, "Unexpected FLASH access reports, please submit rdesc for review\n"); -} - -void picolcd_exit_devfs(struct picolcd_data *data) -{ - struct dentry *dent; - - dent = data->debug_reset; - data->debug_reset = NULL; - if (dent) - debugfs_remove(dent); - dent = data->debug_eeprom; - data->debug_eeprom = NULL; - if (dent) - debugfs_remove(dent); - dent = data->debug_flash; - data->debug_flash = NULL; - if (dent) - debugfs_remove(dent); - mutex_destroy(&data->mutex_flash); -} - diff --git a/trunk/drivers/hid/hid-picolcd_fb.c b/trunk/drivers/hid/hid-picolcd_fb.c deleted file mode 100644 index 0008a512211d..000000000000 --- a/trunk/drivers/hid/hid-picolcd_fb.c +++ /dev/null @@ -1,615 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2010-2012 by Bruno Prémont * - * * - * Based on Logitech G13 driver (v0.4) * - * Copyright (C) 2009 by Rick L. Vinyard, Jr. * - * * - * 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 driver 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 software. If not see . * - ***************************************************************************/ - -#include -#include -#include "usbhid/usbhid.h" -#include - -#include -#include - -#include "hid-picolcd.h" - -/* Framebuffer - * - * The PicoLCD use a Topway LCD module of 256x64 pixel - * This display area is tiled over 4 controllers with 8 tiles - * each. Each tile has 8x64 pixel, each data byte representing - * a 1-bit wide vertical line of the tile. - * - * The display can be updated at a tile granularity. - * - * Chip 1 Chip 2 Chip 3 Chip 4 - * +----------------+----------------+----------------+----------------+ - * | Tile 1 | Tile 1 | Tile 1 | Tile 1 | - * +----------------+----------------+----------------+----------------+ - * | Tile 2 | Tile 2 | Tile 2 | Tile 2 | - * +----------------+----------------+----------------+----------------+ - * ... - * +----------------+----------------+----------------+----------------+ - * | Tile 8 | Tile 8 | Tile 8 | Tile 8 | - * +----------------+----------------+----------------+----------------+ - */ -#define PICOLCDFB_NAME "picolcdfb" -#define PICOLCDFB_WIDTH (256) -#define PICOLCDFB_HEIGHT (64) -#define PICOLCDFB_SIZE (PICOLCDFB_WIDTH * PICOLCDFB_HEIGHT / 8) - -#define PICOLCDFB_UPDATE_RATE_LIMIT 10 -#define PICOLCDFB_UPDATE_RATE_DEFAULT 2 - -/* Framebuffer visual structures */ -static const struct fb_fix_screeninfo picolcdfb_fix = { - .id = PICOLCDFB_NAME, - .type = FB_TYPE_PACKED_PIXELS, - .visual = FB_VISUAL_MONO01, - .xpanstep = 0, - .ypanstep = 0, - .ywrapstep = 0, - .line_length = PICOLCDFB_WIDTH / 8, - .accel = FB_ACCEL_NONE, -}; - -static const struct fb_var_screeninfo picolcdfb_var = { - .xres = PICOLCDFB_WIDTH, - .yres = PICOLCDFB_HEIGHT, - .xres_virtual = PICOLCDFB_WIDTH, - .yres_virtual = PICOLCDFB_HEIGHT, - .width = 103, - .height = 26, - .bits_per_pixel = 1, - .grayscale = 1, - .red = { - .offset = 0, - .length = 1, - .msb_right = 0, - }, - .green = { - .offset = 0, - .length = 1, - .msb_right = 0, - }, - .blue = { - .offset = 0, - .length = 1, - .msb_right = 0, - }, - .transp = { - .offset = 0, - .length = 0, - .msb_right = 0, - }, -}; - -/* Send a given tile to PicoLCD */ -static int picolcd_fb_send_tile(struct picolcd_data *data, u8 *vbitmap, - int chip, int tile) -{ - struct hid_report *report1, *report2; - unsigned long flags; - u8 *tdata; - int i; - - report1 = picolcd_out_report(REPORT_LCD_CMD_DATA, data->hdev); - if (!report1 || report1->maxfield != 1) - return -ENODEV; - report2 = picolcd_out_report(REPORT_LCD_DATA, data->hdev); - if (!report2 || report2->maxfield != 1) - return -ENODEV; - - spin_lock_irqsave(&data->lock, flags); - if ((data->status & PICOLCD_FAILED)) { - spin_unlock_irqrestore(&data->lock, flags); - return -ENODEV; - } - hid_set_field(report1->field[0], 0, chip << 2); - hid_set_field(report1->field[0], 1, 0x02); - hid_set_field(report1->field[0], 2, 0x00); - hid_set_field(report1->field[0], 3, 0x00); - hid_set_field(report1->field[0], 4, 0xb8 | tile); - hid_set_field(report1->field[0], 5, 0x00); - hid_set_field(report1->field[0], 6, 0x00); - hid_set_field(report1->field[0], 7, 0x40); - hid_set_field(report1->field[0], 8, 0x00); - hid_set_field(report1->field[0], 9, 0x00); - hid_set_field(report1->field[0], 10, 32); - - hid_set_field(report2->field[0], 0, (chip << 2) | 0x01); - hid_set_field(report2->field[0], 1, 0x00); - hid_set_field(report2->field[0], 2, 0x00); - hid_set_field(report2->field[0], 3, 32); - - tdata = vbitmap + (tile * 4 + chip) * 64; - for (i = 0; i < 64; i++) - if (i < 32) - hid_set_field(report1->field[0], 11 + i, tdata[i]); - else - hid_set_field(report2->field[0], 4 + i - 32, tdata[i]); - - usbhid_submit_report(data->hdev, report1, USB_DIR_OUT); - usbhid_submit_report(data->hdev, report2, USB_DIR_OUT); - spin_unlock_irqrestore(&data->lock, flags); - return 0; -} - -/* Translate a single tile*/ -static int picolcd_fb_update_tile(u8 *vbitmap, const u8 *bitmap, int bpp, - int chip, int tile) -{ - int i, b, changed = 0; - u8 tdata[64]; - u8 *vdata = vbitmap + (tile * 4 + chip) * 64; - - if (bpp == 1) { - for (b = 7; b >= 0; b--) { - const u8 *bdata = bitmap + tile * 256 + chip * 8 + b * 32; - for (i = 0; i < 64; i++) { - tdata[i] <<= 1; - tdata[i] |= (bdata[i/8] >> (i % 8)) & 0x01; - } - } - } else if (bpp == 8) { - for (b = 7; b >= 0; b--) { - const u8 *bdata = bitmap + (tile * 256 + chip * 8 + b * 32) * 8; - for (i = 0; i < 64; i++) { - tdata[i] <<= 1; - tdata[i] |= (bdata[i] & 0x80) ? 0x01 : 0x00; - } - } - } else { - /* Oops, we should never get here! */ - WARN_ON(1); - return 0; - } - - for (i = 0; i < 64; i++) - if (tdata[i] != vdata[i]) { - changed = 1; - vdata[i] = tdata[i]; - } - return changed; -} - -void picolcd_fb_refresh(struct picolcd_data *data) -{ - if (data->fb_info) - schedule_delayed_work(&data->fb_info->deferred_work, 0); -} - -/* Reconfigure LCD display */ -int picolcd_fb_reset(struct picolcd_data *data, int clear) -{ - struct hid_report *report = picolcd_out_report(REPORT_LCD_CMD, data->hdev); - struct picolcd_fb_data *fbdata = data->fb_info->par; - int i, j; - unsigned long flags; - static const u8 mapcmd[8] = { 0x00, 0x02, 0x00, 0x64, 0x3f, 0x00, 0x64, 0xc0 }; - - if (!report || report->maxfield != 1) - return -ENODEV; - - spin_lock_irqsave(&data->lock, flags); - for (i = 0; i < 4; i++) { - for (j = 0; j < report->field[0]->maxusage; j++) - if (j == 0) - hid_set_field(report->field[0], j, i << 2); - else if (j < sizeof(mapcmd)) - hid_set_field(report->field[0], j, mapcmd[j]); - else - hid_set_field(report->field[0], j, 0); - usbhid_submit_report(data->hdev, report, USB_DIR_OUT); - } - spin_unlock_irqrestore(&data->lock, flags); - - if (clear) { - memset(fbdata->vbitmap, 0, PICOLCDFB_SIZE); - memset(fbdata->bitmap, 0, PICOLCDFB_SIZE*fbdata->bpp); - } - fbdata->force = 1; - - /* schedule first output of framebuffer */ - if (fbdata->ready) - schedule_delayed_work(&data->fb_info->deferred_work, 0); - else - fbdata->ready = 1; - - return 0; -} - -/* Update fb_vbitmap from the screen_base and send changed tiles to device */ -static void picolcd_fb_update(struct fb_info *info) -{ - int chip, tile, n; - unsigned long flags; - struct picolcd_fb_data *fbdata = info->par; - struct picolcd_data *data; - - mutex_lock(&info->lock); - - spin_lock_irqsave(&fbdata->lock, flags); - if (!fbdata->ready && fbdata->picolcd) - picolcd_fb_reset(fbdata->picolcd, 0); - spin_unlock_irqrestore(&fbdata->lock, flags); - - /* - * Translate the framebuffer into the format needed by the PicoLCD. - * See display layout above. - * Do this one tile after the other and push those tiles that changed. - * - * Wait for our IO to complete as otherwise we might flood the queue! - */ - n = 0; - for (chip = 0; chip < 4; chip++) - for (tile = 0; tile < 8; tile++) { - if (!fbdata->force && !picolcd_fb_update_tile( - fbdata->vbitmap, fbdata->bitmap, - fbdata->bpp, chip, tile)) - continue; - n += 2; - if (n >= HID_OUTPUT_FIFO_SIZE / 2) { - spin_lock_irqsave(&fbdata->lock, flags); - data = fbdata->picolcd; - spin_unlock_irqrestore(&fbdata->lock, flags); - mutex_unlock(&info->lock); - if (!data) - return; - usbhid_wait_io(data->hdev); - mutex_lock(&info->lock); - n = 0; - } - spin_lock_irqsave(&fbdata->lock, flags); - data = fbdata->picolcd; - spin_unlock_irqrestore(&fbdata->lock, flags); - if (!data || picolcd_fb_send_tile(data, - fbdata->vbitmap, chip, tile)) - goto out; - } - fbdata->force = false; - if (n) { - spin_lock_irqsave(&fbdata->lock, flags); - data = fbdata->picolcd; - spin_unlock_irqrestore(&fbdata->lock, flags); - mutex_unlock(&info->lock); - if (data) - usbhid_wait_io(data->hdev); - return; - } -out: - mutex_unlock(&info->lock); -} - -/* Stub to call the system default and update the image on the picoLCD */ -static void picolcd_fb_fillrect(struct fb_info *info, - const struct fb_fillrect *rect) -{ - if (!info->par) - return; - sys_fillrect(info, rect); - - schedule_delayed_work(&info->deferred_work, 0); -} - -/* Stub to call the system default and update the image on the picoLCD */ -static void picolcd_fb_copyarea(struct fb_info *info, - const struct fb_copyarea *area) -{ - if (!info->par) - return; - sys_copyarea(info, area); - - schedule_delayed_work(&info->deferred_work, 0); -} - -/* Stub to call the system default and update the image on the picoLCD */ -static void picolcd_fb_imageblit(struct fb_info *info, const struct fb_image *image) -{ - if (!info->par) - return; - sys_imageblit(info, image); - - schedule_delayed_work(&info->deferred_work, 0); -} - -/* - * this is the slow path from userspace. they can seek and write to - * the fb. it's inefficient to do anything less than a full screen draw - */ -static ssize_t picolcd_fb_write(struct fb_info *info, const char __user *buf, - size_t count, loff_t *ppos) -{ - ssize_t ret; - if (!info->par) - return -ENODEV; - ret = fb_sys_write(info, buf, count, ppos); - if (ret >= 0) - schedule_delayed_work(&info->deferred_work, 0); - return ret; -} - -static int picolcd_fb_blank(int blank, struct fb_info *info) -{ - /* We let fb notification do this for us via lcd/backlight device */ - return 0; -} - -static void picolcd_fb_destroy(struct fb_info *info) -{ - struct picolcd_fb_data *fbdata = info->par; - - /* make sure no work is deferred */ - fb_deferred_io_cleanup(info); - - /* No thridparty should ever unregister our framebuffer! */ - WARN_ON(fbdata->picolcd != NULL); - - vfree((u8 *)info->fix.smem_start); - framebuffer_release(info); -} - -static int picolcd_fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) -{ - __u32 bpp = var->bits_per_pixel; - __u32 activate = var->activate; - - /* only allow 1/8 bit depth (8-bit is grayscale) */ - *var = picolcdfb_var; - var->activate = activate; - if (bpp >= 8) { - var->bits_per_pixel = 8; - var->red.length = 8; - var->green.length = 8; - var->blue.length = 8; - } else { - var->bits_per_pixel = 1; - var->red.length = 1; - var->green.length = 1; - var->blue.length = 1; - } - return 0; -} - -static int picolcd_set_par(struct fb_info *info) -{ - struct picolcd_fb_data *fbdata = info->par; - u8 *tmp_fb, *o_fb; - if (info->var.bits_per_pixel == fbdata->bpp) - return 0; - /* switch between 1/8 bit depths */ - if (info->var.bits_per_pixel != 1 && info->var.bits_per_pixel != 8) - return -EINVAL; - - o_fb = fbdata->bitmap; - tmp_fb = kmalloc(PICOLCDFB_SIZE*info->var.bits_per_pixel, GFP_KERNEL); - if (!tmp_fb) - return -ENOMEM; - - /* translate FB content to new bits-per-pixel */ - if (info->var.bits_per_pixel == 1) { - int i, b; - for (i = 0; i < PICOLCDFB_SIZE; i++) { - u8 p = 0; - for (b = 0; b < 8; b++) { - p <<= 1; - p |= o_fb[i*8+b] ? 0x01 : 0x00; - } - tmp_fb[i] = p; - } - memcpy(o_fb, tmp_fb, PICOLCDFB_SIZE); - info->fix.visual = FB_VISUAL_MONO01; - info->fix.line_length = PICOLCDFB_WIDTH / 8; - } else { - int i; - memcpy(tmp_fb, o_fb, PICOLCDFB_SIZE); - for (i = 0; i < PICOLCDFB_SIZE * 8; i++) - o_fb[i] = tmp_fb[i/8] & (0x01 << (7 - i % 8)) ? 0xff : 0x00; - info->fix.visual = FB_VISUAL_DIRECTCOLOR; - info->fix.line_length = PICOLCDFB_WIDTH; - } - - kfree(tmp_fb); - fbdata->bpp = info->var.bits_per_pixel; - return 0; -} - -/* Note this can't be const because of struct fb_info definition */ -static struct fb_ops picolcdfb_ops = { - .owner = THIS_MODULE, - .fb_destroy = picolcd_fb_destroy, - .fb_read = fb_sys_read, - .fb_write = picolcd_fb_write, - .fb_blank = picolcd_fb_blank, - .fb_fillrect = picolcd_fb_fillrect, - .fb_copyarea = picolcd_fb_copyarea, - .fb_imageblit = picolcd_fb_imageblit, - .fb_check_var = picolcd_fb_check_var, - .fb_set_par = picolcd_set_par, -}; - - -/* Callback from deferred IO workqueue */ -static void picolcd_fb_deferred_io(struct fb_info *info, struct list_head *pagelist) -{ - picolcd_fb_update(info); -} - -static const struct fb_deferred_io picolcd_fb_defio = { - .delay = HZ / PICOLCDFB_UPDATE_RATE_DEFAULT, - .deferred_io = picolcd_fb_deferred_io, -}; - - -/* - * The "fb_update_rate" sysfs attribute - */ -static ssize_t picolcd_fb_update_rate_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct picolcd_data *data = dev_get_drvdata(dev); - struct picolcd_fb_data *fbdata = data->fb_info->par; - unsigned i, fb_update_rate = fbdata->update_rate; - size_t ret = 0; - - for (i = 1; i <= PICOLCDFB_UPDATE_RATE_LIMIT; i++) - if (ret >= PAGE_SIZE) - break; - else if (i == fb_update_rate) - ret += snprintf(buf+ret, PAGE_SIZE-ret, "[%u] ", i); - else - ret += snprintf(buf+ret, PAGE_SIZE-ret, "%u ", i); - if (ret > 0) - buf[min(ret, (size_t)PAGE_SIZE)-1] = '\n'; - return ret; -} - -static ssize_t picolcd_fb_update_rate_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - struct picolcd_data *data = dev_get_drvdata(dev); - struct picolcd_fb_data *fbdata = data->fb_info->par; - int i; - unsigned u; - - if (count < 1 || count > 10) - return -EINVAL; - - i = sscanf(buf, "%u", &u); - if (i != 1) - return -EINVAL; - - if (u > PICOLCDFB_UPDATE_RATE_LIMIT) - return -ERANGE; - else if (u == 0) - u = PICOLCDFB_UPDATE_RATE_DEFAULT; - - fbdata->update_rate = u; - data->fb_info->fbdefio->delay = HZ / fbdata->update_rate; - return count; -} - -static DEVICE_ATTR(fb_update_rate, 0666, picolcd_fb_update_rate_show, - picolcd_fb_update_rate_store); - -/* initialize Framebuffer device */ -int picolcd_init_framebuffer(struct picolcd_data *data) -{ - struct device *dev = &data->hdev->dev; - struct fb_info *info = NULL; - struct picolcd_fb_data *fbdata = NULL; - int i, error = -ENOMEM; - u32 *palette; - - /* The extra memory is: - * - 256*u32 for pseudo_palette - * - struct fb_deferred_io - */ - info = framebuffer_alloc(256 * sizeof(u32) + - sizeof(struct fb_deferred_io) + - sizeof(struct picolcd_fb_data) + - PICOLCDFB_SIZE, dev); - if (info == NULL) { - dev_err(dev, "failed to allocate a framebuffer\n"); - goto err_nomem; - } - - info->fbdefio = info->par; - *info->fbdefio = picolcd_fb_defio; - info->par += sizeof(struct fb_deferred_io); - palette = info->par; - info->par += 256 * sizeof(u32); - for (i = 0; i < 256; i++) - palette[i] = i > 0 && i < 16 ? 0xff : 0; - info->pseudo_palette = palette; - info->fbops = &picolcdfb_ops; - info->var = picolcdfb_var; - info->fix = picolcdfb_fix; - info->fix.smem_len = PICOLCDFB_SIZE*8; - info->flags = FBINFO_FLAG_DEFAULT; - - fbdata = info->par; - spin_lock_init(&fbdata->lock); - fbdata->picolcd = data; - fbdata->update_rate = PICOLCDFB_UPDATE_RATE_DEFAULT; - fbdata->bpp = picolcdfb_var.bits_per_pixel; - fbdata->force = 1; - fbdata->vbitmap = info->par + sizeof(struct picolcd_fb_data); - fbdata->bitmap = vmalloc(PICOLCDFB_SIZE*8); - if (fbdata->bitmap == NULL) { - dev_err(dev, "can't get a free page for framebuffer\n"); - goto err_nomem; - } - info->screen_base = (char __force __iomem *)fbdata->bitmap; - info->fix.smem_start = (unsigned long)fbdata->bitmap; - memset(fbdata->vbitmap, 0xff, PICOLCDFB_SIZE); - data->fb_info = info; - - error = picolcd_fb_reset(data, 1); - if (error) { - dev_err(dev, "failed to configure display\n"); - goto err_cleanup; - } - - error = device_create_file(dev, &dev_attr_fb_update_rate); - if (error) { - dev_err(dev, "failed to create sysfs attributes\n"); - goto err_cleanup; - } - - fb_deferred_io_init(info); - error = register_framebuffer(info); - if (error) { - dev_err(dev, "failed to register framebuffer\n"); - goto err_sysfs; - } - return 0; - -err_sysfs: - device_remove_file(dev, &dev_attr_fb_update_rate); - fb_deferred_io_cleanup(info); -err_cleanup: - data->fb_info = NULL; - -err_nomem: - if (fbdata) - vfree(fbdata->bitmap); - framebuffer_release(info); - return error; -} - -void picolcd_exit_framebuffer(struct picolcd_data *data) -{ - struct fb_info *info = data->fb_info; - struct picolcd_fb_data *fbdata = info->par; - unsigned long flags; - - device_remove_file(&data->hdev->dev, &dev_attr_fb_update_rate); - - /* disconnect framebuffer from HID dev */ - spin_lock_irqsave(&fbdata->lock, flags); - fbdata->picolcd = NULL; - spin_unlock_irqrestore(&fbdata->lock, flags); - - /* make sure there is no running update - thus that fbdata->picolcd - * once obtained under lock is guaranteed not to get free() under - * the feet of the deferred work */ - flush_delayed_work_sync(&info->deferred_work); - - data->fb_info = NULL; - unregister_framebuffer(info); -} diff --git a/trunk/drivers/hid/hid-picolcd_lcd.c b/trunk/drivers/hid/hid-picolcd_lcd.c deleted file mode 100644 index 2d0ddc5ac65f..000000000000 --- a/trunk/drivers/hid/hid-picolcd_lcd.c +++ /dev/null @@ -1,107 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2010-2012 by Bruno Prémont * - * * - * Based on Logitech G13 driver (v0.4) * - * Copyright (C) 2009 by Rick L. Vinyard, Jr. * - * * - * 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 driver 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 software. If not see . * - ***************************************************************************/ - -#include -#include "usbhid/usbhid.h" -#include - -#include -#include - -#include "hid-picolcd.h" - -/* - * lcd class device - */ -static int picolcd_get_contrast(struct lcd_device *ldev) -{ - struct picolcd_data *data = lcd_get_data(ldev); - return data->lcd_contrast; -} - -static int picolcd_set_contrast(struct lcd_device *ldev, int contrast) -{ - struct picolcd_data *data = lcd_get_data(ldev); - struct hid_report *report = picolcd_out_report(REPORT_CONTRAST, data->hdev); - unsigned long flags; - - if (!report || report->maxfield != 1 || report->field[0]->report_count != 1) - return -ENODEV; - - data->lcd_contrast = contrast & 0x0ff; - spin_lock_irqsave(&data->lock, flags); - hid_set_field(report->field[0], 0, data->lcd_contrast); - if (!(data->status & PICOLCD_FAILED)) - usbhid_submit_report(data->hdev, report, USB_DIR_OUT); - spin_unlock_irqrestore(&data->lock, flags); - return 0; -} - -static int picolcd_check_lcd_fb(struct lcd_device *ldev, struct fb_info *fb) -{ - return fb && fb == picolcd_fbinfo((struct picolcd_data *)lcd_get_data(ldev)); -} - -static struct lcd_ops picolcd_lcdops = { - .get_contrast = picolcd_get_contrast, - .set_contrast = picolcd_set_contrast, - .check_fb = picolcd_check_lcd_fb, -}; - -int picolcd_init_lcd(struct picolcd_data *data, struct hid_report *report) -{ - struct device *dev = &data->hdev->dev; - struct lcd_device *ldev; - - if (!report) - return -ENODEV; - if (report->maxfield != 1 || report->field[0]->report_count != 1 || - report->field[0]->report_size != 8) { - dev_err(dev, "unsupported CONTRAST report"); - return -EINVAL; - } - - ldev = lcd_device_register(dev_name(dev), dev, data, &picolcd_lcdops); - if (IS_ERR(ldev)) { - dev_err(dev, "failed to register LCD\n"); - return PTR_ERR(ldev); - } - ldev->props.max_contrast = 0x0ff; - data->lcd_contrast = 0xe5; - data->lcd = ldev; - picolcd_set_contrast(ldev, 0xe5); - return 0; -} - -void picolcd_exit_lcd(struct picolcd_data *data) -{ - struct lcd_device *ldev = data->lcd; - - data->lcd = NULL; - if (ldev) - lcd_device_unregister(ldev); -} - -int picolcd_resume_lcd(struct picolcd_data *data) -{ - if (!data->lcd) - return 0; - return picolcd_set_contrast(data->lcd, data->lcd_contrast); -} - diff --git a/trunk/drivers/hid/hid-picolcd_leds.c b/trunk/drivers/hid/hid-picolcd_leds.c deleted file mode 100644 index 28cb6a4f9634..000000000000 --- a/trunk/drivers/hid/hid-picolcd_leds.c +++ /dev/null @@ -1,175 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2010-2012 by Bruno Prémont * - * * - * Based on Logitech G13 driver (v0.4) * - * Copyright (C) 2009 by Rick L. Vinyard, Jr. * - * * - * 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 driver 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 software. If not see . * - ***************************************************************************/ - -#include -#include -#include -#include "hid-ids.h" -#include "usbhid/usbhid.h" -#include - -#include -#include -#include -#include - -#include - -#include -#include - -#include -#include -#include - -#include "hid-picolcd.h" - - -void picolcd_leds_set(struct picolcd_data *data) -{ - struct hid_report *report; - unsigned long flags; - - if (!data->led[0]) - return; - report = picolcd_out_report(REPORT_LED_STATE, data->hdev); - if (!report || report->maxfield != 1 || report->field[0]->report_count != 1) - return; - - spin_lock_irqsave(&data->lock, flags); - hid_set_field(report->field[0], 0, data->led_state); - if (!(data->status & PICOLCD_FAILED)) - usbhid_submit_report(data->hdev, report, USB_DIR_OUT); - spin_unlock_irqrestore(&data->lock, flags); -} - -static void picolcd_led_set_brightness(struct led_classdev *led_cdev, - enum led_brightness value) -{ - struct device *dev; - struct hid_device *hdev; - struct picolcd_data *data; - int i, state = 0; - - dev = led_cdev->dev->parent; - hdev = container_of(dev, struct hid_device, dev); - data = hid_get_drvdata(hdev); - if (!data) - return; - for (i = 0; i < 8; i++) { - if (led_cdev != data->led[i]) - continue; - state = (data->led_state >> i) & 1; - if (value == LED_OFF && state) { - data->led_state &= ~(1 << i); - picolcd_leds_set(data); - } else if (value != LED_OFF && !state) { - data->led_state |= 1 << i; - picolcd_leds_set(data); - } - break; - } -} - -static enum led_brightness picolcd_led_get_brightness(struct led_classdev *led_cdev) -{ - struct device *dev; - struct hid_device *hdev; - struct picolcd_data *data; - int i, value = 0; - - dev = led_cdev->dev->parent; - hdev = container_of(dev, struct hid_device, dev); - data = hid_get_drvdata(hdev); - for (i = 0; i < 8; i++) - if (led_cdev == data->led[i]) { - value = (data->led_state >> i) & 1; - break; - } - return value ? LED_FULL : LED_OFF; -} - -int picolcd_init_leds(struct picolcd_data *data, struct hid_report *report) -{ - struct device *dev = &data->hdev->dev; - struct led_classdev *led; - size_t name_sz = strlen(dev_name(dev)) + 8; - char *name; - int i, ret = 0; - - if (!report) - return -ENODEV; - if (report->maxfield != 1 || report->field[0]->report_count != 1 || - report->field[0]->report_size != 8) { - dev_err(dev, "unsupported LED_STATE report"); - return -EINVAL; - } - - for (i = 0; i < 8; i++) { - led = kzalloc(sizeof(struct led_classdev)+name_sz, GFP_KERNEL); - if (!led) { - dev_err(dev, "can't allocate memory for LED %d\n", i); - ret = -ENOMEM; - goto err; - } - name = (void *)(&led[1]); - snprintf(name, name_sz, "%s::GPO%d", dev_name(dev), i); - led->name = name; - led->brightness = 0; - led->max_brightness = 1; - led->brightness_get = picolcd_led_get_brightness; - led->brightness_set = picolcd_led_set_brightness; - - data->led[i] = led; - ret = led_classdev_register(dev, data->led[i]); - if (ret) { - data->led[i] = NULL; - kfree(led); - dev_err(dev, "can't register LED %d\n", i); - goto err; - } - } - return 0; -err: - for (i = 0; i < 8; i++) - if (data->led[i]) { - led = data->led[i]; - data->led[i] = NULL; - led_classdev_unregister(led); - kfree(led); - } - return ret; -} - -void picolcd_exit_leds(struct picolcd_data *data) -{ - struct led_classdev *led; - int i; - - for (i = 0; i < 8; i++) { - led = data->led[i]; - data->led[i] = NULL; - if (!led) - continue; - led_classdev_unregister(led); - kfree(led); - } -} - - diff --git a/trunk/drivers/hid/hid-primax.c b/trunk/drivers/hid/hid-primax.c index c15adb0c98a1..4d3c60d88318 100644 --- a/trunk/drivers/hid/hid-primax.c +++ b/trunk/drivers/hid/hid-primax.c @@ -64,6 +64,29 @@ static int px_raw_event(struct hid_device *hid, struct hid_report *report, return 0; } +static int px_probe(struct hid_device *hid, const struct hid_device_id *id) +{ + int ret; + + ret = hid_parse(hid); + if (ret) { + hid_err(hid, "parse failed\n"); + goto fail; + } + + ret = hid_hw_start(hid, HID_CONNECT_DEFAULT); + if (ret) + hid_err(hid, "hw start failed\n"); + +fail: + return ret; +} + +static void px_remove(struct hid_device *hid) +{ + hid_hw_stop(hid); +} + static const struct hid_device_id px_devices[] = { { HID_USB_DEVICE(USB_VENDOR_ID_PRIMAX, USB_DEVICE_ID_PRIMAX_KEYBOARD) }, { } @@ -74,6 +97,8 @@ static struct hid_driver px_driver = { .name = "primax", .id_table = px_devices, .raw_event = px_raw_event, + .probe = px_probe, + .remove = px_remove, }; static int __init px_init(void) diff --git a/trunk/drivers/hid/hid-prodikeys.c b/trunk/drivers/hid/hid-prodikeys.c index ec8ca3336315..b71b77ab0dc7 100644 --- a/trunk/drivers/hid/hid-prodikeys.c +++ b/trunk/drivers/hid/hid-prodikeys.c @@ -105,7 +105,7 @@ static ssize_t show_channel(struct device *dev, struct device_attribute *attr, char *buf) { struct hid_device *hdev = container_of(dev, struct hid_device, dev); - struct pk_device *pk = hid_get_drvdata(hdev); + struct pk_device *pk = (struct pk_device *)hid_get_drvdata(hdev); dbg_hid("pcmidi sysfs read channel=%u\n", pk->pm->midi_channel); @@ -118,7 +118,7 @@ static ssize_t store_channel(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct hid_device *hdev = container_of(dev, struct hid_device, dev); - struct pk_device *pk = hid_get_drvdata(hdev); + struct pk_device *pk = (struct pk_device *)hid_get_drvdata(hdev); unsigned channel = 0; @@ -142,7 +142,7 @@ static ssize_t show_sustain(struct device *dev, struct device_attribute *attr, char *buf) { struct hid_device *hdev = container_of(dev, struct hid_device, dev); - struct pk_device *pk = hid_get_drvdata(hdev); + struct pk_device *pk = (struct pk_device *)hid_get_drvdata(hdev); dbg_hid("pcmidi sysfs read sustain=%u\n", pk->pm->midi_sustain); @@ -155,7 +155,7 @@ static ssize_t store_sustain(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct hid_device *hdev = container_of(dev, struct hid_device, dev); - struct pk_device *pk = hid_get_drvdata(hdev); + struct pk_device *pk = (struct pk_device *)hid_get_drvdata(hdev); unsigned sustain = 0; @@ -181,7 +181,7 @@ static ssize_t show_octave(struct device *dev, struct device_attribute *attr, char *buf) { struct hid_device *hdev = container_of(dev, struct hid_device, dev); - struct pk_device *pk = hid_get_drvdata(hdev); + struct pk_device *pk = (struct pk_device *)hid_get_drvdata(hdev); dbg_hid("pcmidi sysfs read octave=%d\n", pk->pm->midi_octave); @@ -194,7 +194,7 @@ static ssize_t store_octave(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct hid_device *hdev = container_of(dev, struct hid_device, dev); - struct pk_device *pk = hid_get_drvdata(hdev); + struct pk_device *pk = (struct pk_device *)hid_get_drvdata(hdev); int octave = 0; @@ -759,7 +759,7 @@ static int pk_input_mapping(struct hid_device *hdev, struct hid_input *hi, struct hid_field *field, struct hid_usage *usage, unsigned long **bit, int *max) { - struct pk_device *pk = hid_get_drvdata(hdev); + struct pk_device *pk = (struct pk_device *)hid_get_drvdata(hdev); struct pcmidi_snd *pm; pm = pk->pm; @@ -777,7 +777,7 @@ static int pk_input_mapping(struct hid_device *hdev, struct hid_input *hi, static int pk_raw_event(struct hid_device *hdev, struct hid_report *report, u8 *data, int size) { - struct pk_device *pk = hid_get_drvdata(hdev); + struct pk_device *pk = (struct pk_device *)hid_get_drvdata(hdev); int ret = 0; if (1 == pk->pm->ifnum) { @@ -858,7 +858,7 @@ static int pk_probe(struct hid_device *hdev, const struct hid_device_id *id) static void pk_remove(struct hid_device *hdev) { - struct pk_device *pk = hid_get_drvdata(hdev); + struct pk_device *pk = (struct pk_device *)hid_get_drvdata(hdev); struct pcmidi_snd *pm; pm = pk->pm; diff --git a/trunk/drivers/hid/hid-ps3remote.c b/trunk/drivers/hid/hid-ps3remote.c deleted file mode 100644 index 03811e539d71..000000000000 --- a/trunk/drivers/hid/hid-ps3remote.c +++ /dev/null @@ -1,215 +0,0 @@ -/* - * HID driver for Sony PS3 BD Remote Control - * - * Copyright (c) 2012 David Dillow - * Based on a blend of the bluez fakehid user-space code by Marcel Holtmann - * and other kernel HID drivers. - */ - -/* - * 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. - */ - -/* NOTE: in order for the Sony PS3 BD Remote Control to be found by - * a Bluetooth host, the key combination Start+Enter has to be kept pressed - * for about 7 seconds with the Bluetooth Host Controller in discovering mode. - * - * There will be no PIN request from the device. - */ - -#include -#include -#include - -#include "hid-ids.h" - -static __u8 ps3remote_rdesc[] = { - 0x05, 0x01, /* GUsagePage Generic Desktop */ - 0x09, 0x05, /* LUsage 0x05 [Game Pad] */ - 0xA1, 0x01, /* MCollection Application (mouse, keyboard) */ - - /* Use collection 1 for joypad buttons */ - 0xA1, 0x02, /* MCollection Logical (interrelated data) */ - - /* Ignore the 1st byte, maybe it is used for a controller - * number but it's not needed for correct operation */ - 0x75, 0x08, /* GReportSize 0x08 [8] */ - 0x95, 0x01, /* GReportCount 0x01 [1] */ - 0x81, 0x01, /* MInput 0x01 (Const[0] Arr[1] Abs[2]) */ - - /* Bytes from 2nd to 4th are a bitmap for joypad buttons, for these - * buttons multiple keypresses are allowed */ - 0x05, 0x09, /* GUsagePage Button */ - 0x19, 0x01, /* LUsageMinimum 0x01 [Button 1 (primary/trigger)] */ - 0x29, 0x18, /* LUsageMaximum 0x18 [Button 24] */ - 0x14, /* GLogicalMinimum [0] */ - 0x25, 0x01, /* GLogicalMaximum 0x01 [1] */ - 0x75, 0x01, /* GReportSize 0x01 [1] */ - 0x95, 0x18, /* GReportCount 0x18 [24] */ - 0x81, 0x02, /* MInput 0x02 (Data[0] Var[1] Abs[2]) */ - - 0xC0, /* MEndCollection */ - - /* Use collection 2 for remote control buttons */ - 0xA1, 0x02, /* MCollection Logical (interrelated data) */ - - /* 5th byte is used for remote control buttons */ - 0x05, 0x09, /* GUsagePage Button */ - 0x18, /* LUsageMinimum [No button pressed] */ - 0x29, 0xFE, /* LUsageMaximum 0xFE [Button 254] */ - 0x14, /* GLogicalMinimum [0] */ - 0x26, 0xFE, 0x00, /* GLogicalMaximum 0x00FE [254] */ - 0x75, 0x08, /* GReportSize 0x08 [8] */ - 0x95, 0x01, /* GReportCount 0x01 [1] */ - 0x80, /* MInput */ - - /* Ignore bytes from 6th to 11th, 6th to 10th are always constant at - * 0xff and 11th is for press indication */ - 0x75, 0x08, /* GReportSize 0x08 [8] */ - 0x95, 0x06, /* GReportCount 0x06 [6] */ - 0x81, 0x01, /* MInput 0x01 (Const[0] Arr[1] Abs[2]) */ - - /* 12th byte is for battery strength */ - 0x05, 0x06, /* GUsagePage Generic Device Controls */ - 0x09, 0x20, /* LUsage 0x20 [Battery Strength] */ - 0x14, /* GLogicalMinimum [0] */ - 0x25, 0x05, /* GLogicalMaximum 0x05 [5] */ - 0x75, 0x08, /* GReportSize 0x08 [8] */ - 0x95, 0x01, /* GReportCount 0x01 [1] */ - 0x81, 0x02, /* MInput 0x02 (Data[0] Var[1] Abs[2]) */ - - 0xC0, /* MEndCollection */ - - 0xC0 /* MEndCollection [Game Pad] */ -}; - -static const unsigned int ps3remote_keymap_joypad_buttons[] = { - [0x01] = KEY_SELECT, - [0x02] = BTN_THUMBL, /* L3 */ - [0x03] = BTN_THUMBR, /* R3 */ - [0x04] = BTN_START, - [0x05] = KEY_UP, - [0x06] = KEY_RIGHT, - [0x07] = KEY_DOWN, - [0x08] = KEY_LEFT, - [0x09] = BTN_TL2, /* L2 */ - [0x0a] = BTN_TR2, /* R2 */ - [0x0b] = BTN_TL, /* L1 */ - [0x0c] = BTN_TR, /* R1 */ - [0x0d] = KEY_OPTION, /* options/triangle */ - [0x0e] = KEY_BACK, /* back/circle */ - [0x0f] = BTN_0, /* cross */ - [0x10] = KEY_SCREEN, /* view/square */ - [0x11] = KEY_HOMEPAGE, /* PS button */ - [0x14] = KEY_ENTER, -}; -static const unsigned int ps3remote_keymap_remote_buttons[] = { - [0x00] = KEY_1, - [0x01] = KEY_2, - [0x02] = KEY_3, - [0x03] = KEY_4, - [0x04] = KEY_5, - [0x05] = KEY_6, - [0x06] = KEY_7, - [0x07] = KEY_8, - [0x08] = KEY_9, - [0x09] = KEY_0, - [0x0e] = KEY_ESC, /* return */ - [0x0f] = KEY_CLEAR, - [0x16] = KEY_EJECTCD, - [0x1a] = KEY_MENU, /* top menu */ - [0x28] = KEY_TIME, - [0x30] = KEY_PREVIOUS, - [0x31] = KEY_NEXT, - [0x32] = KEY_PLAY, - [0x33] = KEY_REWIND, /* scan back */ - [0x34] = KEY_FORWARD, /* scan forward */ - [0x38] = KEY_STOP, - [0x39] = KEY_PAUSE, - [0x40] = KEY_CONTEXT_MENU, /* pop up/menu */ - [0x60] = KEY_FRAMEBACK, /* slow/step back */ - [0x61] = KEY_FRAMEFORWARD, /* slow/step forward */ - [0x63] = KEY_SUBTITLE, - [0x64] = KEY_AUDIO, - [0x65] = KEY_ANGLE, - [0x70] = KEY_INFO, /* display */ - [0x80] = KEY_BLUE, - [0x81] = KEY_RED, - [0x82] = KEY_GREEN, - [0x83] = KEY_YELLOW, -}; - -static __u8 *ps3remote_fixup(struct hid_device *hdev, __u8 *rdesc, - unsigned int *rsize) -{ - *rsize = sizeof(ps3remote_rdesc); - return ps3remote_rdesc; -} - -static int ps3remote_mapping(struct hid_device *hdev, struct hid_input *hi, - struct hid_field *field, struct hid_usage *usage, - unsigned long **bit, int *max) -{ - unsigned int key = usage->hid & HID_USAGE; - - if ((usage->hid & HID_USAGE_PAGE) != HID_UP_BUTTON) - return -1; - - switch (usage->collection_index) { - case 1: - if (key >= ARRAY_SIZE(ps3remote_keymap_joypad_buttons)) - return -1; - - key = ps3remote_keymap_joypad_buttons[key]; - if (!key) - return -1; - break; - case 2: - if (key >= ARRAY_SIZE(ps3remote_keymap_remote_buttons)) - return -1; - - key = ps3remote_keymap_remote_buttons[key]; - if (!key) - return -1; - break; - default: - return -1; - } - - hid_map_usage_clear(hi, usage, bit, max, EV_KEY, key); - return 1; -} - -static const struct hid_device_id ps3remote_devices[] = { - /* PS3 BD Remote Control */ - { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_BDREMOTE) }, - /* Logitech Harmony Adapter for PS3 */ - { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_PS3) }, - { } -}; -MODULE_DEVICE_TABLE(hid, ps3remote_devices); - -static struct hid_driver ps3remote_driver = { - .name = "ps3_remote", - .id_table = ps3remote_devices, - .report_fixup = ps3remote_fixup, - .input_mapping = ps3remote_mapping, -}; - -static int __init ps3remote_init(void) -{ - return hid_register_driver(&ps3remote_driver); -} - -static void __exit ps3remote_exit(void) -{ - hid_unregister_driver(&ps3remote_driver); -} - -module_init(ps3remote_init); -module_exit(ps3remote_exit); -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("David Dillow , Antonio Ospite "); diff --git a/trunk/drivers/hid/hid-samsung.c b/trunk/drivers/hid/hid-samsung.c index a5821d317229..3c1fd8af5e0c 100644 --- a/trunk/drivers/hid/hid-samsung.c +++ b/trunk/drivers/hid/hid-samsung.c @@ -5,6 +5,7 @@ * Copyright (c) 2000-2005 Vojtech Pavlik * Copyright (c) 2005 Michael Haboustak for Concept2, Inc * Copyright (c) 2006-2007 Jiri Kosina + * Copyright (c) 2007 Paul Walmsley * Copyright (c) 2008 Jiri Slaby * Copyright (c) 2010 Don Prince * diff --git a/trunk/drivers/hid/hid-sensor-hub.c b/trunk/drivers/hid/hid-sensor-hub.c deleted file mode 100644 index d9d73e9163eb..000000000000 --- a/trunk/drivers/hid/hid-sensor-hub.c +++ /dev/null @@ -1,680 +0,0 @@ -/* - * HID Sensors Driver - * Copyright (c) 2012, Intel Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * - */ -#include -#include -#include -#include "usbhid/usbhid.h" -#include -#include -#include -#include -#include -#include -#include "hid-ids.h" - -/** - * struct sensor_hub_pending - Synchronous read pending information - * @status: Pending status true/false. - * @ready: Completion synchronization data. - * @usage_id: Usage id for physical device, E.g. Gyro usage id. - * @attr_usage_id: Usage Id of a field, E.g. X-AXIS for a gyro. - * @raw_size: Response size for a read request. - * @raw_data: Place holder for received response. - */ -struct sensor_hub_pending { - bool status; - struct completion ready; - u32 usage_id; - u32 attr_usage_id; - int raw_size; - u8 *raw_data; -}; - -/** - * struct sensor_hub_data - Hold a instance data for a HID hub device - * @hsdev: Stored hid instance for current hub device. - * @mutex: Mutex to serialize synchronous request. - * @lock: Spin lock to protect pending request structure. - * @pending: Holds information of pending sync read request. - * @dyn_callback_list: Holds callback function - * @dyn_callback_lock: spin lock to protect callback list - * @hid_sensor_hub_client_devs: Stores all MFD cells for a hub instance. - * @hid_sensor_client_cnt: Number of MFD cells, (no of sensors attached). - */ -struct sensor_hub_data { - struct hid_sensor_hub_device *hsdev; - struct mutex mutex; - spinlock_t lock; - struct sensor_hub_pending pending; - struct list_head dyn_callback_list; - spinlock_t dyn_callback_lock; - struct mfd_cell *hid_sensor_hub_client_devs; - int hid_sensor_client_cnt; -}; - -/** - * struct hid_sensor_hub_callbacks_list - Stores callback list - * @list: list head. - * @usage_id: usage id for a physical device. - * @usage_callback: Stores registered callback functions. - * @priv: Private data for a physical device. - */ -struct hid_sensor_hub_callbacks_list { - struct list_head list; - u32 usage_id; - struct hid_sensor_hub_callbacks *usage_callback; - void *priv; -}; - -static int sensor_hub_check_for_sensor_page(struct hid_device *hdev) -{ - int i; - int ret = -EINVAL; - - for (i = 0; i < hdev->maxcollection; i++) { - struct hid_collection *col = &hdev->collection[i]; - if (col->type == HID_COLLECTION_PHYSICAL && - (col->usage & HID_USAGE_PAGE) == HID_UP_SENSOR) { - ret = 0; - break; - } - } - - return ret; -} - -static struct hid_report *sensor_hub_report(int id, struct hid_device *hdev, - int dir) -{ - struct hid_report *report; - - list_for_each_entry(report, &hdev->report_enum[dir].report_list, list) { - if (report->id == id) - return report; - } - hid_warn(hdev, "No report with id 0x%x found\n", id); - - return NULL; -} - -static int sensor_hub_get_physical_device_count( - struct hid_report_enum *report_enum) -{ - struct hid_report *report; - struct hid_field *field; - int cnt = 0; - - list_for_each_entry(report, &report_enum->report_list, list) { - field = report->field[0]; - if (report->maxfield && field && - field->physical) - cnt++; - } - - return cnt; -} - -static void sensor_hub_fill_attr_info( - struct hid_sensor_hub_attribute_info *info, - s32 index, s32 report_id, s32 units, s32 unit_expo, s32 size) -{ - info->index = index; - info->report_id = report_id; - info->units = units; - info->unit_expo = unit_expo; - info->size = size/8; -} - -static struct hid_sensor_hub_callbacks *sensor_hub_get_callback( - struct hid_device *hdev, - u32 usage_id, void **priv) -{ - struct hid_sensor_hub_callbacks_list *callback; - struct sensor_hub_data *pdata = hid_get_drvdata(hdev); - - spin_lock(&pdata->dyn_callback_lock); - list_for_each_entry(callback, &pdata->dyn_callback_list, list) - if (callback->usage_id == usage_id) { - *priv = callback->priv; - spin_unlock(&pdata->dyn_callback_lock); - return callback->usage_callback; - } - spin_unlock(&pdata->dyn_callback_lock); - - return NULL; -} - -int sensor_hub_register_callback(struct hid_sensor_hub_device *hsdev, - u32 usage_id, - struct hid_sensor_hub_callbacks *usage_callback) -{ - struct hid_sensor_hub_callbacks_list *callback; - struct sensor_hub_data *pdata = hid_get_drvdata(hsdev->hdev); - - spin_lock(&pdata->dyn_callback_lock); - list_for_each_entry(callback, &pdata->dyn_callback_list, list) - if (callback->usage_id == usage_id) { - spin_unlock(&pdata->dyn_callback_lock); - return -EINVAL; - } - callback = kzalloc(sizeof(*callback), GFP_ATOMIC); - if (!callback) { - spin_unlock(&pdata->dyn_callback_lock); - return -ENOMEM; - } - callback->usage_callback = usage_callback; - callback->usage_id = usage_id; - callback->priv = NULL; - list_add_tail(&callback->list, &pdata->dyn_callback_list); - spin_unlock(&pdata->dyn_callback_lock); - - return 0; -} -EXPORT_SYMBOL_GPL(sensor_hub_register_callback); - -int sensor_hub_remove_callback(struct hid_sensor_hub_device *hsdev, - u32 usage_id) -{ - struct hid_sensor_hub_callbacks_list *callback; - struct sensor_hub_data *pdata = hid_get_drvdata(hsdev->hdev); - - spin_lock(&pdata->dyn_callback_lock); - list_for_each_entry(callback, &pdata->dyn_callback_list, list) - if (callback->usage_id == usage_id) { - list_del(&callback->list); - kfree(callback); - break; - } - spin_unlock(&pdata->dyn_callback_lock); - - return 0; -} -EXPORT_SYMBOL_GPL(sensor_hub_remove_callback); - -int sensor_hub_set_feature(struct hid_sensor_hub_device *hsdev, u32 report_id, - u32 field_index, s32 value) -{ - struct hid_report *report; - struct sensor_hub_data *data = hid_get_drvdata(hsdev->hdev); - int ret = 0; - - mutex_lock(&data->mutex); - report = sensor_hub_report(report_id, hsdev->hdev, HID_FEATURE_REPORT); - if (!report || (field_index >= report->maxfield)) { - ret = -EINVAL; - goto done_proc; - } - hid_set_field(report->field[field_index], 0, value); - usbhid_submit_report(hsdev->hdev, report, USB_DIR_OUT); - usbhid_wait_io(hsdev->hdev); - -done_proc: - mutex_unlock(&data->mutex); - - return ret; -} -EXPORT_SYMBOL_GPL(sensor_hub_set_feature); - -int sensor_hub_get_feature(struct hid_sensor_hub_device *hsdev, u32 report_id, - u32 field_index, s32 *value) -{ - struct hid_report *report; - struct sensor_hub_data *data = hid_get_drvdata(hsdev->hdev); - int ret = 0; - - mutex_lock(&data->mutex); - report = sensor_hub_report(report_id, hsdev->hdev, HID_FEATURE_REPORT); - if (!report || (field_index >= report->maxfield)) { - ret = -EINVAL; - goto done_proc; - } - usbhid_submit_report(hsdev->hdev, report, USB_DIR_IN); - usbhid_wait_io(hsdev->hdev); - *value = report->field[field_index]->value[0]; - -done_proc: - mutex_unlock(&data->mutex); - - return ret; -} -EXPORT_SYMBOL_GPL(sensor_hub_get_feature); - - -int sensor_hub_input_attr_get_raw_value(struct hid_sensor_hub_device *hsdev, - u32 usage_id, - u32 attr_usage_id, u32 report_id) -{ - struct sensor_hub_data *data = hid_get_drvdata(hsdev->hdev); - unsigned long flags; - struct hid_report *report; - int ret_val = 0; - - mutex_lock(&data->mutex); - memset(&data->pending, 0, sizeof(data->pending)); - init_completion(&data->pending.ready); - data->pending.usage_id = usage_id; - data->pending.attr_usage_id = attr_usage_id; - data->pending.raw_size = 0; - - spin_lock_irqsave(&data->lock, flags); - data->pending.status = true; - report = sensor_hub_report(report_id, hsdev->hdev, HID_INPUT_REPORT); - if (!report) { - spin_unlock_irqrestore(&data->lock, flags); - goto err_free; - } - usbhid_submit_report(hsdev->hdev, report, USB_DIR_IN); - spin_unlock_irqrestore(&data->lock, flags); - wait_for_completion_interruptible_timeout(&data->pending.ready, HZ*5); - switch (data->pending.raw_size) { - case 1: - ret_val = *(u8 *)data->pending.raw_data; - break; - case 2: - ret_val = *(u16 *)data->pending.raw_data; - break; - case 4: - ret_val = *(u32 *)data->pending.raw_data; - break; - default: - ret_val = 0; - } - kfree(data->pending.raw_data); - -err_free: - data->pending.status = false; - mutex_unlock(&data->mutex); - - return ret_val; -} -EXPORT_SYMBOL_GPL(sensor_hub_input_attr_get_raw_value); - -int sensor_hub_input_get_attribute_info(struct hid_sensor_hub_device *hsdev, - u8 type, - u32 usage_id, - u32 attr_usage_id, - struct hid_sensor_hub_attribute_info *info) -{ - int ret = -1; - int i, j; - int collection_index = -1; - struct hid_report *report; - struct hid_field *field; - struct hid_report_enum *report_enum; - struct hid_device *hdev = hsdev->hdev; - - /* Initialize with defaults */ - info->usage_id = usage_id; - info->attrib_id = attr_usage_id; - info->report_id = -1; - info->index = -1; - info->units = -1; - info->unit_expo = -1; - - for (i = 0; i < hdev->maxcollection; ++i) { - struct hid_collection *collection = &hdev->collection[i]; - if (usage_id == collection->usage) { - collection_index = i; - break; - } - } - if (collection_index == -1) - goto err_ret; - - report_enum = &hdev->report_enum[type]; - list_for_each_entry(report, &report_enum->report_list, list) { - for (i = 0; i < report->maxfield; ++i) { - field = report->field[i]; - if (field->physical == usage_id && - field->logical == attr_usage_id) { - sensor_hub_fill_attr_info(info, i, report->id, - field->unit, field->unit_exponent, - field->report_size); - ret = 0; - } else { - for (j = 0; j < field->maxusage; ++j) { - if (field->usage[j].hid == - attr_usage_id && - field->usage[j].collection_index == - collection_index) { - sensor_hub_fill_attr_info(info, - i, report->id, - field->unit, - field->unit_exponent, - field->report_size); - ret = 0; - break; - } - } - } - if (ret == 0) - break; - } - } - -err_ret: - return ret; -} -EXPORT_SYMBOL_GPL(sensor_hub_input_get_attribute_info); - -#ifdef CONFIG_PM -static int sensor_hub_suspend(struct hid_device *hdev, pm_message_t message) -{ - struct sensor_hub_data *pdata = hid_get_drvdata(hdev); - struct hid_sensor_hub_callbacks_list *callback; - - hid_dbg(hdev, " sensor_hub_suspend\n"); - spin_lock(&pdata->dyn_callback_lock); - list_for_each_entry(callback, &pdata->dyn_callback_list, list) { - if (callback->usage_callback->suspend) - callback->usage_callback->suspend( - pdata->hsdev, callback->priv); - } - spin_unlock(&pdata->dyn_callback_lock); - - return 0; -} - -static int sensor_hub_resume(struct hid_device *hdev) -{ - struct sensor_hub_data *pdata = hid_get_drvdata(hdev); - struct hid_sensor_hub_callbacks_list *callback; - - hid_dbg(hdev, " sensor_hub_resume\n"); - spin_lock(&pdata->dyn_callback_lock); - list_for_each_entry(callback, &pdata->dyn_callback_list, list) { - if (callback->usage_callback->resume) - callback->usage_callback->resume( - pdata->hsdev, callback->priv); - } - spin_unlock(&pdata->dyn_callback_lock); - - return 0; -} - -static int sensor_hub_reset_resume(struct hid_device *hdev) -{ - return 0; -} -#endif -/* - * Handle raw report as sent by device - */ -static int sensor_hub_raw_event(struct hid_device *hdev, - struct hid_report *report, u8 *raw_data, int size) -{ - int i; - u8 *ptr; - int sz; - struct sensor_hub_data *pdata = hid_get_drvdata(hdev); - unsigned long flags; - struct hid_sensor_hub_callbacks *callback = NULL; - struct hid_collection *collection = NULL; - void *priv = NULL; - - hid_dbg(hdev, "sensor_hub_raw_event report id:0x%x size:%d type:%d\n", - report->id, size, report->type); - hid_dbg(hdev, "maxfield:%d\n", report->maxfield); - if (report->type != HID_INPUT_REPORT) - return 1; - - ptr = raw_data; - ptr++; /*Skip report id*/ - - if (!report) - goto err_report; - - spin_lock_irqsave(&pdata->lock, flags); - - for (i = 0; i < report->maxfield; ++i) { - - hid_dbg(hdev, "%d collection_index:%x hid:%x sz:%x\n", - i, report->field[i]->usage->collection_index, - report->field[i]->usage->hid, - report->field[i]->report_size/8); - - sz = report->field[i]->report_size/8; - if (pdata->pending.status && pdata->pending.attr_usage_id == - report->field[i]->usage->hid) { - hid_dbg(hdev, "data was pending ...\n"); - pdata->pending.raw_data = kmalloc(sz, GFP_ATOMIC); - if (pdata->pending.raw_data) { - memcpy(pdata->pending.raw_data, ptr, sz); - pdata->pending.raw_size = sz; - } else - pdata->pending.raw_size = 0; - complete(&pdata->pending.ready); - } - collection = &hdev->collection[ - report->field[i]->usage->collection_index]; - hid_dbg(hdev, "collection->usage %x\n", - collection->usage); - callback = sensor_hub_get_callback(pdata->hsdev->hdev, - report->field[i]->physical, - &priv); - if (callback && callback->capture_sample) { - if (report->field[i]->logical) - callback->capture_sample(pdata->hsdev, - report->field[i]->logical, sz, ptr, - callback->pdev); - else - callback->capture_sample(pdata->hsdev, - report->field[i]->usage->hid, sz, ptr, - callback->pdev); - } - ptr += sz; - } - if (callback && collection && callback->send_event) - callback->send_event(pdata->hsdev, collection->usage, - callback->pdev); - spin_unlock_irqrestore(&pdata->lock, flags); - -err_report: - return 1; -} - -static int sensor_hub_probe(struct hid_device *hdev, - const struct hid_device_id *id) -{ - int ret; - struct sensor_hub_data *sd; - int i; - char *name; - struct hid_report *report; - struct hid_report_enum *report_enum; - struct hid_field *field; - int dev_cnt; - - sd = kzalloc(sizeof(struct sensor_hub_data), GFP_KERNEL); - if (!sd) { - hid_err(hdev, "cannot allocate Sensor data\n"); - return -ENOMEM; - } - sd->hsdev = kzalloc(sizeof(struct hid_sensor_hub_device), GFP_KERNEL); - if (!sd->hsdev) { - hid_err(hdev, "cannot allocate hid_sensor_hub_device\n"); - ret = -ENOMEM; - goto err_free_hub; - } - hid_set_drvdata(hdev, sd); - sd->hsdev->hdev = hdev; - sd->hsdev->vendor_id = hdev->vendor; - sd->hsdev->product_id = hdev->product; - spin_lock_init(&sd->lock); - spin_lock_init(&sd->dyn_callback_lock); - mutex_init(&sd->mutex); - ret = hid_parse(hdev); - if (ret) { - hid_err(hdev, "parse failed\n"); - goto err_free; - } - if (sensor_hub_check_for_sensor_page(hdev) < 0) { - hid_err(hdev, "sensor page not found\n"); - goto err_free; - } - INIT_LIST_HEAD(&hdev->inputs); - - ret = hid_hw_start(hdev, 0); - if (ret) { - hid_err(hdev, "hw start failed\n"); - goto err_free; - } - ret = hid_hw_open(hdev); - if (ret) { - hid_err(hdev, "failed to open input interrupt pipe\n"); - goto err_stop_hw; - } - - INIT_LIST_HEAD(&sd->dyn_callback_list); - sd->hid_sensor_client_cnt = 0; - report_enum = &hdev->report_enum[HID_INPUT_REPORT]; - - dev_cnt = sensor_hub_get_physical_device_count(report_enum); - if (dev_cnt > HID_MAX_PHY_DEVICES) { - hid_err(hdev, "Invalid Physical device count\n"); - ret = -EINVAL; - goto err_close; - } - sd->hid_sensor_hub_client_devs = kzalloc(dev_cnt * - sizeof(struct mfd_cell), - GFP_KERNEL); - if (sd->hid_sensor_hub_client_devs == NULL) { - hid_err(hdev, "Failed to allocate memory for mfd cells\n"); - ret = -ENOMEM; - goto err_close; - } - list_for_each_entry(report, &report_enum->report_list, list) { - hid_dbg(hdev, "Report id:%x\n", report->id); - field = report->field[0]; - if (report->maxfield && field && - field->physical) { - name = kasprintf(GFP_KERNEL, "HID-SENSOR-%x", - field->physical); - if (name == NULL) { - hid_err(hdev, "Failed MFD device name\n"); - ret = -ENOMEM; - goto err_free_names; - } - sd->hid_sensor_hub_client_devs[ - sd->hid_sensor_client_cnt].name = name; - sd->hid_sensor_hub_client_devs[ - sd->hid_sensor_client_cnt].platform_data = - sd->hsdev; - sd->hid_sensor_hub_client_devs[ - sd->hid_sensor_client_cnt].pdata_size = - sizeof(*sd->hsdev); - hid_dbg(hdev, "Adding %s:%p\n", name, sd); - sd->hid_sensor_client_cnt++; - } - } - ret = mfd_add_devices(&hdev->dev, 0, sd->hid_sensor_hub_client_devs, - sd->hid_sensor_client_cnt, NULL, 0, NULL); - if (ret < 0) - goto err_free_names; - - return ret; - -err_free_names: - for (i = 0; i < sd->hid_sensor_client_cnt ; ++i) - kfree(sd->hid_sensor_hub_client_devs[i].name); - kfree(sd->hid_sensor_hub_client_devs); -err_close: - hid_hw_close(hdev); -err_stop_hw: - hid_hw_stop(hdev); -err_free: - kfree(sd->hsdev); -err_free_hub: - kfree(sd); - - return ret; -} - -static void sensor_hub_remove(struct hid_device *hdev) -{ - struct sensor_hub_data *data = hid_get_drvdata(hdev); - unsigned long flags; - int i; - - hid_dbg(hdev, " hardware removed\n"); - hid_hw_close(hdev); - hid_hw_stop(hdev); - spin_lock_irqsave(&data->lock, flags); - if (data->pending.status) - complete(&data->pending.ready); - spin_unlock_irqrestore(&data->lock, flags); - mfd_remove_devices(&hdev->dev); - for (i = 0; i < data->hid_sensor_client_cnt ; ++i) - kfree(data->hid_sensor_hub_client_devs[i].name); - kfree(data->hid_sensor_hub_client_devs); - hid_set_drvdata(hdev, NULL); - mutex_destroy(&data->mutex); - kfree(data->hsdev); - kfree(data); -} - -static const struct hid_device_id sensor_hub_devices[] = { - { HID_USB_DEVICE(USB_VENDOR_ID_INTEL_8086, - USB_DEVICE_ID_SENSOR_HUB_1020) }, - { HID_USB_DEVICE(USB_VENDOR_ID_INTEL_8087, - USB_DEVICE_ID_SENSOR_HUB_1020) }, - { HID_USB_DEVICE(USB_VENDOR_ID_INTEL_8086, - USB_DEVICE_ID_SENSOR_HUB_09FA) }, - { HID_USB_DEVICE(USB_VENDOR_ID_INTEL_8087, - USB_DEVICE_ID_SENSOR_HUB_09FA) }, - { HID_USB_DEVICE(USB_VENDOR_ID_STANTUM_STM, - USB_DEVICE_ID_SENSOR_HUB_7014) }, - { } -}; -MODULE_DEVICE_TABLE(hid, sensor_hub_devices); - -static const struct hid_usage_id sensor_hub_grabbed_usages[] = { - { HID_ANY_ID, HID_ANY_ID, HID_ANY_ID }, - { HID_ANY_ID - 1, HID_ANY_ID - 1, HID_ANY_ID - 1 } -}; - -static struct hid_driver sensor_hub_driver = { - .name = "hid-sensor-hub", - .id_table = sensor_hub_devices, - .probe = sensor_hub_probe, - .remove = sensor_hub_remove, - .raw_event = sensor_hub_raw_event, -#ifdef CONFIG_PM - .suspend = sensor_hub_suspend, - .resume = sensor_hub_resume, - .reset_resume = sensor_hub_reset_resume, -#endif -}; - -static int __init sensor_hub_init(void) -{ - return hid_register_driver(&sensor_hub_driver); -} - -static void __exit sensor_hub_exit(void) -{ - hid_unregister_driver(&sensor_hub_driver); -} - -module_init(sensor_hub_init); -module_exit(sensor_hub_exit); - -MODULE_DESCRIPTION("HID Sensor Hub driver"); -MODULE_AUTHOR("Srinivas Pandruvada "); -MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/hid/hid-sony.c b/trunk/drivers/hid/hid-sony.c index 7f33ebf299c2..5cd25bd907f8 100644 --- a/trunk/drivers/hid/hid-sony.c +++ b/trunk/drivers/hid/hid-sony.c @@ -4,6 +4,7 @@ * Copyright (c) 1999 Andreas Gal * Copyright (c) 2000-2005 Vojtech Pavlik * Copyright (c) 2005 Michael Haboustak for Concept2, Inc + * Copyright (c) 2007 Paul Walmsley * Copyright (c) 2008 Jiri Slaby * Copyright (c) 2006-2008 Jiri Kosina */ diff --git a/trunk/drivers/hid/hid-sunplus.c b/trunk/drivers/hid/hid-sunplus.c index 45b4b066a262..d484a0043dd4 100644 --- a/trunk/drivers/hid/hid-sunplus.c +++ b/trunk/drivers/hid/hid-sunplus.c @@ -5,6 +5,7 @@ * Copyright (c) 2000-2005 Vojtech Pavlik * Copyright (c) 2005 Michael Haboustak for Concept2, Inc * Copyright (c) 2006-2007 Jiri Kosina + * Copyright (c) 2007 Paul Walmsley * Copyright (c) 2008 Jiri Slaby */ diff --git a/trunk/drivers/hid/hid-uclogic.c b/trunk/drivers/hid/hid-uclogic.c index 2e56a1fd2375..3aba02be1f26 100644 --- a/trunk/drivers/hid/hid-uclogic.c +++ b/trunk/drivers/hid/hid-uclogic.c @@ -466,86 +466,6 @@ static __u8 twhl850_rdesc_fixed2[] = { 0xC0 /* End Collection */ }; -/* - * See TWHA60 description, device and HID report descriptors at - * http://sf.net/apps/mediawiki/digimend/?title=UC-Logic_Tablet_TWHA60 - */ - -/* Size of the original descriptors of TWHA60 tablet */ -#define TWHA60_RDESC_ORIG_SIZE0 254 -#define TWHA60_RDESC_ORIG_SIZE1 139 - -/* Fixed TWHA60 report descriptor, interface 0 (stylus) */ -static __u8 twha60_rdesc_fixed0[] = { - 0x05, 0x0D, /* Usage Page (Digitizer), */ - 0x09, 0x02, /* Usage (Pen), */ - 0xA1, 0x01, /* Collection (Application), */ - 0x85, 0x09, /* Report ID (9), */ - 0x09, 0x20, /* Usage (Stylus), */ - 0xA0, /* Collection (Physical), */ - 0x75, 0x01, /* Report Size (1), */ - 0x09, 0x42, /* Usage (Tip Switch), */ - 0x09, 0x44, /* Usage (Barrel Switch), */ - 0x09, 0x46, /* Usage (Tablet Pick), */ - 0x14, /* Logical Minimum (0), */ - 0x25, 0x01, /* Logical Maximum (1), */ - 0x95, 0x03, /* Report Count (3), */ - 0x81, 0x02, /* Input (Variable), */ - 0x95, 0x04, /* Report Count (4), */ - 0x81, 0x01, /* Input (Constant), */ - 0x09, 0x32, /* Usage (In Range), */ - 0x95, 0x01, /* Report Count (1), */ - 0x81, 0x02, /* Input (Variable), */ - 0x75, 0x10, /* Report Size (16), */ - 0x95, 0x01, /* Report Count (1), */ - 0x14, /* Logical Minimum (0), */ - 0xA4, /* Push, */ - 0x05, 0x01, /* Usage Page (Desktop), */ - 0x55, 0xFD, /* Unit Exponent (-3), */ - 0x65, 0x13, /* Unit (Inch), */ - 0x34, /* Physical Minimum (0), */ - 0x09, 0x30, /* Usage (X), */ - 0x46, 0x10, 0x27, /* Physical Maximum (10000), */ - 0x27, 0x3F, 0x9C, - 0x00, 0x00, /* Logical Maximum (39999), */ - 0x81, 0x02, /* Input (Variable), */ - 0x09, 0x31, /* Usage (Y), */ - 0x46, 0x6A, 0x18, /* Physical Maximum (6250), */ - 0x26, 0xA7, 0x61, /* Logical Maximum (24999), */ - 0x81, 0x02, /* Input (Variable), */ - 0xB4, /* Pop, */ - 0x09, 0x30, /* Usage (Tip Pressure), */ - 0x26, 0xFF, 0x03, /* Logical Maximum (1023), */ - 0x81, 0x02, /* Input (Variable), */ - 0xC0, /* End Collection, */ - 0xC0 /* End Collection */ -}; - -/* Fixed TWHA60 report descriptor, interface 1 (frame buttons) */ -static __u8 twha60_rdesc_fixed1[] = { - 0x05, 0x01, /* Usage Page (Desktop), */ - 0x09, 0x06, /* Usage (Keyboard), */ - 0xA1, 0x01, /* Collection (Application), */ - 0x85, 0x05, /* Report ID (5), */ - 0x05, 0x07, /* Usage Page (Keyboard), */ - 0x14, /* Logical Minimum (0), */ - 0x25, 0x01, /* Logical Maximum (1), */ - 0x75, 0x01, /* Report Size (1), */ - 0x95, 0x08, /* Report Count (8), */ - 0x81, 0x01, /* Input (Constant), */ - 0x95, 0x0C, /* Report Count (12), */ - 0x19, 0x3A, /* Usage Minimum (KB F1), */ - 0x29, 0x45, /* Usage Maximum (KB F12), */ - 0x81, 0x02, /* Input (Variable), */ - 0x95, 0x0C, /* Report Count (12), */ - 0x19, 0x68, /* Usage Minimum (KB F13), */ - 0x29, 0x73, /* Usage Maximum (KB F24), */ - 0x81, 0x02, /* Input (Variable), */ - 0x95, 0x08, /* Report Count (8), */ - 0x81, 0x01, /* Input (Constant), */ - 0xC0 /* End Collection */ -}; - static __u8 *uclogic_report_fixup(struct hid_device *hdev, __u8 *rdesc, unsigned int *rsize) { @@ -605,22 +525,6 @@ static __u8 *uclogic_report_fixup(struct hid_device *hdev, __u8 *rdesc, break; } break; - case USB_DEVICE_ID_UCLOGIC_TABLET_TWHA60: - switch (iface_num) { - case 0: - if (*rsize == TWHA60_RDESC_ORIG_SIZE0) { - rdesc = twha60_rdesc_fixed0; - *rsize = sizeof(twha60_rdesc_fixed0); - } - break; - case 1: - if (*rsize == TWHA60_RDESC_ORIG_SIZE1) { - rdesc = twha60_rdesc_fixed1; - *rsize = sizeof(twha60_rdesc_fixed1); - } - break; - } - break; } return rdesc; @@ -639,8 +543,6 @@ static const struct hid_device_id uclogic_devices[] = { USB_DEVICE_ID_UCLOGIC_TABLET_WP1062) }, { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_WIRELESS_TABLET_TWHL850) }, - { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, - USB_DEVICE_ID_UCLOGIC_TABLET_TWHA60) }, { } }; MODULE_DEVICE_TABLE(hid, uclogic_devices); diff --git a/trunk/drivers/hid/hid-wacom.c b/trunk/drivers/hid/hid-wacom.c index 2f60da9ed066..fe23a1eb586b 100644 --- a/trunk/drivers/hid/hid-wacom.c +++ b/trunk/drivers/hid/hid-wacom.c @@ -5,6 +5,7 @@ * Copyright (c) 2000-2005 Vojtech Pavlik * Copyright (c) 2005 Michael Haboustak for Concept2, Inc * Copyright (c) 2006-2007 Jiri Kosina + * Copyright (c) 2007 Paul Walmsley * Copyright (c) 2008 Jiri Slaby * Copyright (c) 2006 Andrew Zabolotny * Copyright (c) 2009 Bastien Nocera @@ -32,8 +33,6 @@ #define PAD_DEVICE_ID 0x0F #define WAC_CMD_LED_CONTROL 0x20 -#define WAC_CMD_ICON_START_STOP 0x21 -#define WAC_CMD_ICON_TRANSFER 0x26 struct wacom_data { __u16 tool; @@ -70,91 +69,6 @@ static enum power_supply_property wacom_ac_props[] = { POWER_SUPPLY_PROP_SCOPE, }; -static void wacom_scramble(__u8 *image) -{ - __u16 mask; - __u16 s1; - __u16 s2; - __u16 r1 ; - __u16 r2 ; - __u16 r; - __u8 buf[256]; - int i, w, x, y, z; - - for (x = 0; x < 32; x++) { - for (y = 0; y < 8; y++) - buf[(8 * x) + (7 - y)] = image[(8 * x) + y]; - } - - /* Change 76543210 into GECA6420 as required by Intuos4 WL - * HGFEDCBA HFDB7531 - */ - for (x = 0; x < 4; x++) { - for (y = 0; y < 4; y++) { - for (z = 0; z < 8; z++) { - mask = 0x0001; - r1 = 0; - r2 = 0; - i = (x << 6) + (y << 4) + z; - s1 = buf[i]; - s2 = buf[i+8]; - for (w = 0; w < 8; w++) { - r1 |= (s1 & mask); - r2 |= (s2 & mask); - s1 <<= 1; - s2 <<= 1; - mask <<= 2; - } - r = r1 | (r2 << 1); - i = (x << 6) + (y << 4) + (z << 1); - image[i] = 0xFF & r; - image[i+1] = (0xFF00 & r) >> 8; - } - } - } -} - -static void wacom_set_image(struct hid_device *hdev, const char *image, - __u8 icon_no) -{ - __u8 rep_data[68]; - __u8 p[256]; - int ret, i, j; - - for (i = 0; i < 256; i++) - p[i] = image[i]; - - rep_data[0] = WAC_CMD_ICON_START_STOP; - rep_data[1] = 0; - ret = hdev->hid_output_raw_report(hdev, rep_data, 2, - HID_FEATURE_REPORT); - if (ret < 0) - goto err; - - rep_data[0] = WAC_CMD_ICON_TRANSFER; - rep_data[1] = icon_no & 0x07; - - wacom_scramble(p); - - for (i = 0; i < 4; i++) { - for (j = 0; j < 64; j++) - rep_data[j + 3] = p[(i << 6) + j]; - - rep_data[2] = i; - ret = hdev->hid_output_raw_report(hdev, rep_data, 67, - HID_FEATURE_REPORT); - } - - rep_data[0] = WAC_CMD_ICON_START_STOP; - rep_data[1] = 0; - - ret = hdev->hid_output_raw_report(hdev, rep_data, 2, - HID_FEATURE_REPORT); - -err: - return; -} - static void wacom_leds_set_brightness(struct led_classdev *led_dev, enum led_brightness value) { @@ -177,10 +91,7 @@ static void wacom_leds_set_brightness(struct led_classdev *led_dev, if (buf) { buf[0] = WAC_CMD_LED_CONTROL; buf[1] = led; - buf[2] = value >> 2; - buf[3] = value; - /* use fixed brightness for OLEDs */ - buf[4] = 0x08; + buf[2] = value; hdev->hid_output_raw_report(hdev, buf, 9, HID_FEATURE_REPORT); kfree(buf); } @@ -406,34 +317,6 @@ static ssize_t wacom_store_speed(struct device *dev, static DEVICE_ATTR(speed, S_IRUGO | S_IWUSR | S_IWGRP, wacom_show_speed, wacom_store_speed); -#define WACOM_STORE(OLED_ID) \ -static ssize_t wacom_oled##OLED_ID##_store(struct device *dev, \ - struct device_attribute *attr, \ - const char *buf, size_t count) \ -{ \ - struct hid_device *hdev = container_of(dev, struct hid_device, \ - dev); \ - \ - if (count != 256) \ - return -EINVAL; \ - \ - wacom_set_image(hdev, buf, OLED_ID); \ - \ - return count; \ -} \ - \ -static DEVICE_ATTR(oled##OLED_ID##_img, S_IWUSR | S_IWGRP, NULL, \ - wacom_oled##OLED_ID##_store) - -WACOM_STORE(0); -WACOM_STORE(1); -WACOM_STORE(2); -WACOM_STORE(3); -WACOM_STORE(4); -WACOM_STORE(5); -WACOM_STORE(6); -WACOM_STORE(7); - static int wacom_gr_parse_report(struct hid_device *hdev, struct wacom_data *wdata, struct input_dev *input, unsigned char *data) @@ -834,33 +717,17 @@ static int wacom_probe(struct hid_device *hdev, hid_warn(hdev, "can't create sysfs speed attribute err: %d\n", ret); -#define OLED_INIT(OLED_ID) \ - do { \ - ret = device_create_file(&hdev->dev, \ - &dev_attr_oled##OLED_ID##_img); \ - if (ret) \ - hid_warn(hdev, \ - "can't create sysfs oled attribute, err: %d\n", ret);\ - } while (0) - -OLED_INIT(0); -OLED_INIT(1); -OLED_INIT(2); -OLED_INIT(3); -OLED_INIT(4); -OLED_INIT(5); -OLED_INIT(6); -OLED_INIT(7); - wdata->features = 0; wacom_set_features(hdev, 1); if (hdev->product == USB_DEVICE_ID_WACOM_INTUOS4_BLUETOOTH) { sprintf(hdev->name, "%s", "Wacom Intuos4 WL"); ret = wacom_initialize_leds(hdev); - if (ret) + if (ret) { hid_warn(hdev, "can't create led attribute, err: %d\n", ret); + goto destroy_leds; + } } wdata->battery.properties = wacom_battery_props; @@ -873,8 +740,8 @@ OLED_INIT(7); ret = power_supply_register(&hdev->dev, &wdata->battery); if (ret) { - hid_err(hdev, "can't create sysfs battery attribute, err: %d\n", - ret); + hid_warn(hdev, "can't create sysfs battery attribute, err: %d\n", + ret); goto err_battery; } @@ -889,8 +756,8 @@ OLED_INIT(7); ret = power_supply_register(&hdev->dev, &wdata->ac); if (ret) { - hid_err(hdev, - "can't create ac battery attribute, err: %d\n", ret); + hid_warn(hdev, + "can't create ac battery attribute, err: %d\n", ret); goto err_ac; } @@ -900,17 +767,10 @@ OLED_INIT(7); err_ac: power_supply_unregister(&wdata->battery); err_battery: - wacom_destroy_leds(hdev); - device_remove_file(&hdev->dev, &dev_attr_oled0_img); - device_remove_file(&hdev->dev, &dev_attr_oled1_img); - device_remove_file(&hdev->dev, &dev_attr_oled2_img); - device_remove_file(&hdev->dev, &dev_attr_oled3_img); - device_remove_file(&hdev->dev, &dev_attr_oled4_img); - device_remove_file(&hdev->dev, &dev_attr_oled5_img); - device_remove_file(&hdev->dev, &dev_attr_oled6_img); - device_remove_file(&hdev->dev, &dev_attr_oled7_img); device_remove_file(&hdev->dev, &dev_attr_speed); hid_hw_stop(hdev); +destroy_leds: + wacom_destroy_leds(hdev); err_free: kfree(wdata); return ret; @@ -921,14 +781,6 @@ static void wacom_remove(struct hid_device *hdev) struct wacom_data *wdata = hid_get_drvdata(hdev); wacom_destroy_leds(hdev); - device_remove_file(&hdev->dev, &dev_attr_oled0_img); - device_remove_file(&hdev->dev, &dev_attr_oled1_img); - device_remove_file(&hdev->dev, &dev_attr_oled2_img); - device_remove_file(&hdev->dev, &dev_attr_oled3_img); - device_remove_file(&hdev->dev, &dev_attr_oled4_img); - device_remove_file(&hdev->dev, &dev_attr_oled5_img); - device_remove_file(&hdev->dev, &dev_attr_oled6_img); - device_remove_file(&hdev->dev, &dev_attr_oled7_img); device_remove_file(&hdev->dev, &dev_attr_speed); hid_hw_stop(hdev); diff --git a/trunk/drivers/hid/hid-waltop.c b/trunk/drivers/hid/hid-waltop.c index bb536ab5941e..745e4e9a8cf2 100644 --- a/trunk/drivers/hid/hid-waltop.c +++ b/trunk/drivers/hid/hid-waltop.c @@ -638,6 +638,28 @@ static __u8 sirius_battery_free_tablet_rdesc_fixed[] = { 0xC0 /* End Collection */ }; +static int waltop_probe(struct hid_device *hdev, + const struct hid_device_id *id) +{ + int ret; + + ret = hid_parse(hdev); + if (ret) { + hid_err(hdev, "parse failed\n"); + goto err; + } + + ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); + if (ret) { + hid_err(hdev, "hw start failed\n"); + goto err; + } + + return 0; +err: + return ret; +} + static __u8 *waltop_report_fixup(struct hid_device *hdev, __u8 *rdesc, unsigned int *rsize) { @@ -754,6 +776,11 @@ static int waltop_raw_event(struct hid_device *hdev, struct hid_report *report, return 0; } +static void waltop_remove(struct hid_device *hdev) +{ + hid_hw_stop(hdev); +} + static const struct hid_device_id waltop_devices[] = { { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_SLIM_TABLET_5_8_INCH) }, @@ -776,8 +803,10 @@ MODULE_DEVICE_TABLE(hid, waltop_devices); static struct hid_driver waltop_driver = { .name = "waltop", .id_table = waltop_devices, + .probe = waltop_probe, .report_fixup = waltop_report_fixup, .raw_event = waltop_raw_event, + .remove = waltop_remove, }; static int __init waltop_init(void) diff --git a/trunk/drivers/hid/hid-wiimote-ext.c b/trunk/drivers/hid/hid-wiimote-ext.c index bc85bf29062e..0a1805c9b0e5 100644 --- a/trunk/drivers/hid/hid-wiimote-ext.c +++ b/trunk/drivers/hid/hid-wiimote-ext.c @@ -28,14 +28,12 @@ struct wiimote_ext { bool mp_plugged; bool motionp; __u8 ext_type; - __u16 calib[4][3]; }; enum wiiext_type { WIIEXT_NONE, /* placeholder */ WIIEXT_CLASSIC, /* Nintendo classic controller */ WIIEXT_NUNCHUCK, /* Nintendo nunchuck controller */ - WIIEXT_BALANCE_BOARD, /* Nintendo balance board controller */ }; enum wiiext_keys { @@ -128,7 +126,6 @@ static bool motionp_read(struct wiimote_ext *ext) static __u8 ext_read(struct wiimote_ext *ext) { ssize_t ret; - __u8 buf[24], i, j, offs = 0; __u8 rmem[2], wmem; __u8 type = WIIEXT_NONE; @@ -154,28 +151,6 @@ static __u8 ext_read(struct wiimote_ext *ext) type = WIIEXT_NUNCHUCK; else if (rmem[0] == 0x01 && rmem[1] == 0x01) type = WIIEXT_CLASSIC; - else if (rmem[0] == 0x04 && rmem[1] == 0x02) - type = WIIEXT_BALANCE_BOARD; - } - - /* get balance board calibration data */ - if (type == WIIEXT_BALANCE_BOARD) { - ret = wiimote_cmd_read(ext->wdata, 0xa40024, buf, 12); - ret += wiimote_cmd_read(ext->wdata, 0xa40024 + 12, - buf + 12, 12); - - if (ret != 24) { - type = WIIEXT_NONE; - } else { - for (i = 0; i < 3; i++) { - for (j = 0; j < 4; j++) { - ext->calib[j][i] = buf[offs]; - ext->calib[j][i] <<= 8; - ext->calib[j][i] |= buf[offs + 1]; - offs += 2; - } - } - } } wiimote_cmd_release(ext->wdata); @@ -534,71 +509,6 @@ static void handler_classic(struct wiimote_ext *ext, const __u8 *payload) input_sync(ext->input); } -static void handler_balance_board(struct wiimote_ext *ext, const __u8 *payload) -{ - __s32 val[4], tmp; - unsigned int i; - - /* Byte | 8 7 6 5 4 3 2 1 | - * -----+--------------------------+ - * 1 | Top Right <15:8> | - * 2 | Top Right <7:0> | - * -----+--------------------------+ - * 3 | Bottom Right <15:8> | - * 4 | Bottom Right <7:0> | - * -----+--------------------------+ - * 5 | Top Left <15:8> | - * 6 | Top Left <7:0> | - * -----+--------------------------+ - * 7 | Bottom Left <15:8> | - * 8 | Bottom Left <7:0> | - * -----+--------------------------+ - * - * These values represent the weight-measurements of the Wii-balance - * board with 16bit precision. - * - * The balance-board is never reported interleaved with motionp. - */ - - val[0] = payload[0]; - val[0] <<= 8; - val[0] |= payload[1]; - - val[1] = payload[2]; - val[1] <<= 8; - val[1] |= payload[3]; - - val[2] = payload[4]; - val[2] <<= 8; - val[2] |= payload[5]; - - val[3] = payload[6]; - val[3] <<= 8; - val[3] |= payload[7]; - - /* apply calibration data */ - for (i = 0; i < 4; i++) { - if (val[i] < ext->calib[i][1]) { - tmp = val[i] - ext->calib[i][0]; - tmp *= 1700; - tmp /= ext->calib[i][1] - ext->calib[i][0]; - } else { - tmp = val[i] - ext->calib[i][1]; - tmp *= 1700; - tmp /= ext->calib[i][2] - ext->calib[i][1]; - tmp += 1700; - } - val[i] = tmp; - } - - input_report_abs(ext->input, ABS_HAT0X, val[0]); - input_report_abs(ext->input, ABS_HAT0Y, val[1]); - input_report_abs(ext->input, ABS_HAT1X, val[2]); - input_report_abs(ext->input, ABS_HAT1Y, val[3]); - - input_sync(ext->input); -} - /* call this with state.lock spinlock held */ void wiiext_handle(struct wiimote_data *wdata, const __u8 *payload) { @@ -613,8 +523,6 @@ void wiiext_handle(struct wiimote_data *wdata, const __u8 *payload) handler_nunchuck(ext, payload); } else if (ext->ext_type == WIIEXT_CLASSIC) { handler_classic(ext, payload); - } else if (ext->ext_type == WIIEXT_BALANCE_BOARD) { - handler_balance_board(ext, payload); } } @@ -643,11 +551,6 @@ static ssize_t wiiext_show(struct device *dev, struct device_attribute *attr, return sprintf(buf, "motionp+classic\n"); else return sprintf(buf, "classic\n"); - } else if (type == WIIEXT_BALANCE_BOARD) { - if (motionp) - return sprintf(buf, "motionp+balanceboard\n"); - else - return sprintf(buf, "balanceboard\n"); } else { if (motionp) return sprintf(buf, "motionp\n"); diff --git a/trunk/drivers/hid/hidraw.c b/trunk/drivers/hid/hidraw.c index 17d15bb610d1..3b6f7bf5a77e 100644 --- a/trunk/drivers/hid/hidraw.c +++ b/trunk/drivers/hid/hidraw.c @@ -42,7 +42,6 @@ static struct cdev hidraw_cdev; static struct class *hidraw_class; static struct hidraw *hidraw_table[HIDRAW_MAX_DEVICES]; static DEFINE_MUTEX(minors_lock); -static void drop_ref(struct hidraw *hid, int exists_bit); static ssize_t hidraw_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) { @@ -114,7 +113,7 @@ static ssize_t hidraw_send_report(struct file *file, const char __user *buffer, __u8 *buf; int ret = 0; - if (!hidraw_table[minor] || !hidraw_table[minor]->exist) { + if (!hidraw_table[minor]) { ret = -ENODEV; goto out; } @@ -262,7 +261,7 @@ static int hidraw_open(struct inode *inode, struct file *file) } mutex_lock(&minors_lock); - if (!hidraw_table[minor] || !hidraw_table[minor]->exist) { + if (!hidraw_table[minor]) { err = -ENODEV; goto out_unlock; } @@ -299,12 +298,36 @@ static int hidraw_open(struct inode *inode, struct file *file) static int hidraw_release(struct inode * inode, struct file * file) { unsigned int minor = iminor(inode); + struct hidraw *dev; struct hidraw_list *list = file->private_data; + int ret; + int i; + + mutex_lock(&minors_lock); + if (!hidraw_table[minor]) { + ret = -ENODEV; + goto unlock; + } - drop_ref(hidraw_table[minor], 0); list_del(&list->node); + dev = hidraw_table[minor]; + if (!--dev->open) { + if (list->hidraw->exist) { + hid_hw_power(dev->hid, PM_HINT_NORMAL); + hid_hw_close(dev->hid); + } else { + kfree(list->hidraw); + } + } + + for (i = 0; i < HIDRAW_BUFFER_SIZE; ++i) + kfree(list->buffer[i].value); kfree(list); - return 0; + ret = 0; +unlock: + mutex_unlock(&minors_lock); + + return ret; } static long hidraw_ioctl(struct file *file, unsigned int cmd, @@ -506,7 +529,21 @@ EXPORT_SYMBOL_GPL(hidraw_connect); void hidraw_disconnect(struct hid_device *hid) { struct hidraw *hidraw = hid->hidraw; - drop_ref(hidraw, 1); + + mutex_lock(&minors_lock); + hidraw->exist = 0; + + device_destroy(hidraw_class, MKDEV(hidraw_major, hidraw->minor)); + + hidraw_table[hidraw->minor] = NULL; + + if (hidraw->open) { + hid_hw_close(hid); + wake_up_interruptible(&hidraw->wait); + } else { + kfree(hidraw); + } + mutex_unlock(&minors_lock); } EXPORT_SYMBOL_GPL(hidraw_disconnect); @@ -522,28 +559,21 @@ int __init hidraw_init(void) if (result < 0) { pr_warn("can't get major number\n"); + result = 0; goto out; } hidraw_class = class_create(THIS_MODULE, "hidraw"); if (IS_ERR(hidraw_class)) { result = PTR_ERR(hidraw_class); - goto error_cdev; + unregister_chrdev(hidraw_major, "hidraw"); + goto out; } cdev_init(&hidraw_cdev, &hidraw_ops); - result = cdev_add(&hidraw_cdev, dev_id, HIDRAW_MAX_DEVICES); - if (result < 0) - goto error_class; - + cdev_add(&hidraw_cdev, dev_id, HIDRAW_MAX_DEVICES); out: return result; - -error_class: - class_destroy(hidraw_class); -error_cdev: - unregister_chrdev_region(dev_id, HIDRAW_MAX_DEVICES); - goto out; } void hidraw_exit(void) @@ -555,23 +585,3 @@ void hidraw_exit(void) unregister_chrdev_region(dev_id, HIDRAW_MAX_DEVICES); } - -static void drop_ref(struct hidraw *hidraw, int exists_bit) -{ - mutex_lock(&minors_lock); - if (exists_bit) { - hid_hw_close(hidraw->hid); - hidraw->exist = 0; - if (hidraw->open) - wake_up_interruptible(&hidraw->wait); - } else { - --hidraw->open; - } - - if (!hidraw->open && !hidraw->exist) { - device_destroy(hidraw_class, MKDEV(hidraw_major, hidraw->minor)); - hidraw_table[hidraw->minor] = NULL; - kfree(hidraw); - } - mutex_unlock(&minors_lock); -} diff --git a/trunk/drivers/hid/usbhid/hid-core.c b/trunk/drivers/hid/usbhid/hid-core.c index 8e0c4bf94ebc..dedd8e4e5c6d 100644 --- a/trunk/drivers/hid/usbhid/hid-core.c +++ b/trunk/drivers/hid/usbhid/hid-core.c @@ -1415,20 +1415,20 @@ static int hid_post_reset(struct usb_interface *intf) * configuration descriptors passed, we already know that * the size of the HID report descriptor has not changed. */ - rdesc = kmalloc(hid->dev_rsize, GFP_KERNEL); + rdesc = kmalloc(hid->rsize, GFP_KERNEL); if (!rdesc) { dbg_hid("couldn't allocate rdesc memory (post_reset)\n"); return 1; } status = hid_get_class_descriptor(dev, interface->desc.bInterfaceNumber, - HID_DT_REPORT, rdesc, hid->dev_rsize); + HID_DT_REPORT, rdesc, hid->rsize); if (status < 0) { dbg_hid("reading report descriptor failed (post_reset)\n"); kfree(rdesc); return 1; } - status = memcmp(rdesc, hid->dev_rdesc, hid->dev_rsize); + status = memcmp(rdesc, hid->rdesc, hid->rsize); kfree(rdesc); if (status != 0) { dbg_hid("report descriptor changed\n"); diff --git a/trunk/drivers/hid/usbhid/hid-quirks.c b/trunk/drivers/hid/usbhid/hid-quirks.c index 11c7932dc7e6..903eef3d3e10 100644 --- a/trunk/drivers/hid/usbhid/hid-quirks.c +++ b/trunk/drivers/hid/usbhid/hid-quirks.c @@ -70,13 +70,11 @@ static const struct hid_blacklist { { USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_AXIS_295, HID_QUIRK_NOGET }, { USB_VENDOR_ID_DMI, USB_DEVICE_ID_DMI_ENC, HID_QUIRK_NOGET }, { USB_VENDOR_ID_ELO, USB_DEVICE_ID_ELO_TS2700, HID_QUIRK_NOGET }, - { USB_VENDOR_ID_FREESCALE, USB_DEVICE_ID_FREESCALE_MX28, HID_QUIRK_NOGET }, - { USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS, HID_QUIRK_NOGET }, { USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN, HID_QUIRK_NO_INIT_REPORTS }, { USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN1, HID_QUIRK_NO_INIT_REPORTS }, { USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN2, HID_QUIRK_NO_INIT_REPORTS }, { USB_VENDOR_ID_PRODIGE, USB_DEVICE_ID_PRODIGE_CORDLESS, HID_QUIRK_NOGET }, - { USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3001, HID_QUIRK_NOGET }, + { USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_PIXART_IMAGING_INC_OPTICAL_TOUCH_SCREEN, HID_QUIRK_NOGET }, { USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3008, HID_QUIRK_NOGET }, { USB_VENDOR_ID_SENNHEISER, USB_DEVICE_ID_SENNHEISER_BTD500USB, HID_QUIRK_NOGET }, { USB_VENDOR_ID_SUN, USB_DEVICE_ID_RARITAN_KVM_DONGLE, HID_QUIRK_NOGET }, diff --git a/trunk/drivers/hv/hv.c b/trunk/drivers/hv/hv.c index 3648f8f0f368..86f8885aeb45 100644 --- a/trunk/drivers/hv/hv.c +++ b/trunk/drivers/hv/hv.c @@ -26,7 +26,6 @@ #include #include #include -#include #include #include "hyperv_vmbus.h" @@ -38,6 +37,28 @@ struct hv_context hv_context = { .signal_event_buffer = NULL, }; +/* + * query_hypervisor_presence + * - Query the cpuid for presence of windows hypervisor + */ +static int query_hypervisor_presence(void) +{ + unsigned int eax; + unsigned int ebx; + unsigned int ecx; + unsigned int edx; + unsigned int op; + + eax = 0; + ebx = 0; + ecx = 0; + edx = 0; + op = HVCPUID_VERSION_FEATURES; + cpuid(op, &eax, &ebx, &ecx, &edx); + + return ecx & HV_PRESENT_BIT; +} + /* * query_hypervisor_info - Get version info of the windows hypervisor */ @@ -138,13 +159,14 @@ int hv_init(void) memset(hv_context.synic_message_page, 0, sizeof(void *) * NR_CPUS); + if (!query_hypervisor_presence()) + goto cleanup; + max_leaf = query_hypervisor_info(); - /* - * Write our OS ID. - */ - hv_context.guestid = generate_guest_id(0, LINUX_VERSION_CODE, 0); - wrmsrl(HV_X64_MSR_GUEST_OS_ID, hv_context.guestid); + /* Write our OS info */ + wrmsrl(HV_X64_MSR_GUEST_OS_ID, HV_LINUX_GUEST_ID); + hv_context.guestid = HV_LINUX_GUEST_ID; /* See if the hypercall page is already set */ rdmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64); diff --git a/trunk/drivers/hv/hv_kvp.c b/trunk/drivers/hv/hv_kvp.c index ed50e9e83c61..0012eed6d872 100644 --- a/trunk/drivers/hv/hv_kvp.c +++ b/trunk/drivers/hv/hv_kvp.c @@ -48,24 +48,13 @@ static struct { void *kvp_context; /* for the channel callback */ } kvp_transaction; -/* - * Before we can accept KVP messages from the host, we need - * to handshake with the user level daemon. This state tracks - * if we are in the handshake phase. - */ -static bool in_hand_shake = true; - -/* - * This state maintains the version number registered by the daemon. - */ -static int dm_reg_value; - static void kvp_send_key(struct work_struct *dummy); +#define TIMEOUT_FIRED 1 -static void kvp_respond_to_host(struct hv_kvp_msg *msg, int error); +static void kvp_respond_to_host(char *key, char *value, int error); static void kvp_work_func(struct work_struct *dummy); -static void kvp_register(int); +static void kvp_register(void); static DECLARE_DELAYED_WORK(kvp_work, kvp_work_func); static DECLARE_WORK(kvp_sendkey_work, kvp_send_key); @@ -79,7 +68,7 @@ static u8 *recv_buffer; */ static void -kvp_register(int reg_value) +kvp_register(void) { struct cn_msg *msg; @@ -94,7 +83,7 @@ kvp_register(int reg_value) msg->id.idx = CN_KVP_IDX; msg->id.val = CN_KVP_VAL; - kvp_msg->kvp_hdr.operation = reg_value; + kvp_msg->kvp_hdr.operation = KVP_OP_REGISTER; strcpy(version, HV_DRV_VERSION); msg->len = sizeof(struct hv_kvp_msg); cn_netlink_send(msg, 0, GFP_ATOMIC); @@ -108,43 +97,9 @@ kvp_work_func(struct work_struct *dummy) * If the timer fires, the user-mode component has not responded; * process the pending transaction. */ - kvp_respond_to_host(NULL, HV_E_FAIL); -} - -static int kvp_handle_handshake(struct hv_kvp_msg *msg) -{ - int ret = 1; - - switch (msg->kvp_hdr.operation) { - case KVP_OP_REGISTER: - dm_reg_value = KVP_OP_REGISTER; - pr_info("KVP: IP injection functionality not available\n"); - pr_info("KVP: Upgrade the KVP daemon\n"); - break; - case KVP_OP_REGISTER1: - dm_reg_value = KVP_OP_REGISTER1; - break; - default: - pr_info("KVP: incompatible daemon\n"); - pr_info("KVP: KVP version: %d, Daemon version: %d\n", - KVP_OP_REGISTER1, msg->kvp_hdr.operation); - ret = 0; - } - - if (ret) { - /* - * We have a compatible daemon; complete the handshake. - */ - pr_info("KVP: user-mode registering done.\n"); - kvp_register(dm_reg_value); - kvp_transaction.active = false; - if (kvp_transaction.kvp_context) - hv_kvp_onchannelcallback(kvp_transaction.kvp_context); - } - return ret; + kvp_respond_to_host("Unknown key", "Guest timed out", TIMEOUT_FIRED); } - /* * Callback when data is received from user mode. */ @@ -154,165 +109,29 @@ kvp_cn_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp) { struct hv_kvp_msg *message; struct hv_kvp_msg_enumerate *data; - int error = 0; message = (struct hv_kvp_msg *)msg->data; - - /* - * If we are negotiating the version information - * with the daemon; handle that first. - */ - - if (in_hand_shake) { - if (kvp_handle_handshake(message)) - in_hand_shake = false; - return; - } - - /* - * Based on the version of the daemon, we propagate errors from the - * daemon differently. - */ - - data = &message->body.kvp_enum_data; - - switch (dm_reg_value) { + switch (message->kvp_hdr.operation) { case KVP_OP_REGISTER: - /* - * Null string is used to pass back error condition. - */ - if (data->data.key[0] == 0) - error = HV_S_CONT; - break; - - case KVP_OP_REGISTER1: - /* - * We use the message header information from - * the user level daemon to transmit errors. - */ - error = message->error; + pr_info("KVP: user-mode registering done.\n"); + kvp_register(); + kvp_transaction.active = false; + hv_kvp_onchannelcallback(kvp_transaction.kvp_context); break; - } - - /* - * Complete the transaction by forwarding the key value - * to the host. But first, cancel the timeout. - */ - if (cancel_delayed_work_sync(&kvp_work)) - kvp_respond_to_host(message, error); -} - - -static int process_ob_ipinfo(void *in_msg, void *out_msg, int op) -{ - struct hv_kvp_msg *in = in_msg; - struct hv_kvp_ip_msg *out = out_msg; - int len; - - switch (op) { - case KVP_OP_GET_IP_INFO: - /* - * Transform all parameters into utf16 encoding. - */ - len = utf8s_to_utf16s((char *)in->body.kvp_ip_val.ip_addr, - strlen((char *)in->body.kvp_ip_val.ip_addr), - UTF16_HOST_ENDIAN, - (wchar_t *)out->kvp_ip_val.ip_addr, - MAX_IP_ADDR_SIZE); - if (len < 0) - return len; - - len = utf8s_to_utf16s((char *)in->body.kvp_ip_val.sub_net, - strlen((char *)in->body.kvp_ip_val.sub_net), - UTF16_HOST_ENDIAN, - (wchar_t *)out->kvp_ip_val.sub_net, - MAX_IP_ADDR_SIZE); - if (len < 0) - return len; - - len = utf8s_to_utf16s((char *)in->body.kvp_ip_val.gate_way, - strlen((char *)in->body.kvp_ip_val.gate_way), - UTF16_HOST_ENDIAN, - (wchar_t *)out->kvp_ip_val.gate_way, - MAX_GATEWAY_SIZE); - if (len < 0) - return len; - - len = utf8s_to_utf16s((char *)in->body.kvp_ip_val.dns_addr, - strlen((char *)in->body.kvp_ip_val.dns_addr), - UTF16_HOST_ENDIAN, - (wchar_t *)out->kvp_ip_val.dns_addr, - MAX_IP_ADDR_SIZE); - if (len < 0) - return len; - - len = utf8s_to_utf16s((char *)in->body.kvp_ip_val.adapter_id, - strlen((char *)in->body.kvp_ip_val.adapter_id), - UTF16_HOST_ENDIAN, - (wchar_t *)out->kvp_ip_val.adapter_id, - MAX_IP_ADDR_SIZE); - if (len < 0) - return len; - - out->kvp_ip_val.dhcp_enabled = - in->body.kvp_ip_val.dhcp_enabled; - out->kvp_ip_val.addr_family = - in->body.kvp_ip_val.addr_family; - } - - return 0; -} - -static void process_ib_ipinfo(void *in_msg, void *out_msg, int op) -{ - struct hv_kvp_ip_msg *in = in_msg; - struct hv_kvp_msg *out = out_msg; - switch (op) { - case KVP_OP_SET_IP_INFO: + default: + data = &message->body.kvp_enum_data; /* - * Transform all parameters into utf8 encoding. + * Complete the transaction by forwarding the key value + * to the host. But first, cancel the timeout. */ - utf16s_to_utf8s((wchar_t *)in->kvp_ip_val.ip_addr, - MAX_IP_ADDR_SIZE, - UTF16_LITTLE_ENDIAN, - (__u8 *)out->body.kvp_ip_val.ip_addr, - MAX_IP_ADDR_SIZE); - - utf16s_to_utf8s((wchar_t *)in->kvp_ip_val.sub_net, - MAX_IP_ADDR_SIZE, - UTF16_LITTLE_ENDIAN, - (__u8 *)out->body.kvp_ip_val.sub_net, - MAX_IP_ADDR_SIZE); - - utf16s_to_utf8s((wchar_t *)in->kvp_ip_val.gate_way, - MAX_GATEWAY_SIZE, - UTF16_LITTLE_ENDIAN, - (__u8 *)out->body.kvp_ip_val.gate_way, - MAX_GATEWAY_SIZE); - - utf16s_to_utf8s((wchar_t *)in->kvp_ip_val.dns_addr, - MAX_IP_ADDR_SIZE, - UTF16_LITTLE_ENDIAN, - (__u8 *)out->body.kvp_ip_val.dns_addr, - MAX_IP_ADDR_SIZE); - - out->body.kvp_ip_val.dhcp_enabled = in->kvp_ip_val.dhcp_enabled; - - default: - utf16s_to_utf8s((wchar_t *)in->kvp_ip_val.adapter_id, - MAX_ADAPTER_ID_SIZE, - UTF16_LITTLE_ENDIAN, - (__u8 *)out->body.kvp_ip_val.adapter_id, - MAX_ADAPTER_ID_SIZE); - - out->body.kvp_ip_val.addr_family = in->kvp_ip_val.addr_family; + if (cancel_delayed_work_sync(&kvp_work)) + kvp_respond_to_host(data->data.key, + data->data.value, + !strlen(data->data.key)); } } - - - static void kvp_send_key(struct work_struct *dummy) { @@ -348,12 +167,6 @@ kvp_send_key(struct work_struct *dummy) */ switch (message->kvp_hdr.operation) { - case KVP_OP_SET_IP_INFO: - process_ib_ipinfo(in_msg, message, KVP_OP_SET_IP_INFO); - break; - case KVP_OP_GET_IP_INFO: - process_ib_ipinfo(in_msg, message, KVP_OP_GET_IP_INFO); - break; case KVP_OP_SET: switch (in_msg->body.kvp_set.data.value_type) { case REG_SZ: @@ -430,19 +243,17 @@ kvp_send_key(struct work_struct *dummy) */ static void -kvp_respond_to_host(struct hv_kvp_msg *msg_to_host, int error) +kvp_respond_to_host(char *key, char *value, int error) { struct hv_kvp_msg *kvp_msg; struct hv_kvp_exchg_msg_value *kvp_data; char *key_name; - char *value; struct icmsg_hdr *icmsghdrp; int keylen = 0; int valuelen = 0; u32 buf_len; struct vmbus_channel *channel; u64 req_id; - int ret; /* * If a transaction is not active; log and return. @@ -476,7 +287,6 @@ kvp_respond_to_host(struct hv_kvp_msg *msg_to_host, int error) */ return; - icmsghdrp->status = error; /* * If the error parameter is set, terminate the host's enumeration @@ -484,27 +294,20 @@ kvp_respond_to_host(struct hv_kvp_msg *msg_to_host, int error) */ if (error) { /* - * Something failed or we have timedout; - * terminate the current host-side iteration. + * Something failed or the we have timedout; + * terminate the current host-side iteration. */ + icmsghdrp->status = HV_S_CONT; goto response_done; } + icmsghdrp->status = HV_S_OK; + kvp_msg = (struct hv_kvp_msg *) &recv_buffer[sizeof(struct vmbuspipe_hdr) + sizeof(struct icmsg_hdr)]; switch (kvp_transaction.kvp_msg->kvp_hdr.operation) { - case KVP_OP_GET_IP_INFO: - ret = process_ob_ipinfo(msg_to_host, - (struct hv_kvp_ip_msg *)kvp_msg, - KVP_OP_GET_IP_INFO); - if (ret < 0) - icmsghdrp->status = HV_E_FAIL; - - goto response_done; - case KVP_OP_SET_IP_INFO: - goto response_done; case KVP_OP_GET: kvp_data = &kvp_msg->body.kvp_get.data; goto copy_value; @@ -518,7 +321,7 @@ kvp_respond_to_host(struct hv_kvp_msg *msg_to_host, int error) } kvp_data = &kvp_msg->body.kvp_enum_data.data; - key_name = msg_to_host->body.kvp_enum_data.data.key; + key_name = key; /* * The windows host expects the key/value pair to be encoded @@ -532,7 +335,6 @@ kvp_respond_to_host(struct hv_kvp_msg *msg_to_host, int error) kvp_data->key_size = 2*(keylen + 1); /* utf16 encoding */ copy_value: - value = msg_to_host->body.kvp_enum_data.data.value; valuelen = utf8s_to_utf16s(value, strlen(value), UTF16_HOST_ENDIAN, (wchar_t *) kvp_data->value, (HV_KVP_EXCHANGE_MAX_VALUE_SIZE / 2) - 2); @@ -585,8 +387,7 @@ void hv_kvp_onchannelcallback(void *context) return; } - vmbus_recvpacket(channel, recv_buffer, PAGE_SIZE * 2, &recvlen, - &requestid); + vmbus_recvpacket(channel, recv_buffer, PAGE_SIZE, &recvlen, &requestid); if (recvlen > 0) { icmsghdrp = (struct icmsg_hdr *)&recv_buffer[ diff --git a/trunk/drivers/hv/hv_util.c b/trunk/drivers/hv/hv_util.c index a0667de7a04c..d3ac6a40118b 100644 --- a/trunk/drivers/hv/hv_util.c +++ b/trunk/drivers/hv/hv_util.c @@ -263,7 +263,7 @@ static int util_probe(struct hv_device *dev, (struct hv_util_service *)dev_id->driver_data; int ret; - srv->recv_buffer = kmalloc(PAGE_SIZE * 2, GFP_KERNEL); + srv->recv_buffer = kmalloc(PAGE_SIZE, GFP_KERNEL); if (!srv->recv_buffer) return -ENOMEM; if (srv->util_init) { @@ -274,7 +274,7 @@ static int util_probe(struct hv_device *dev, } } - ret = vmbus_open(dev->channel, 4 * PAGE_SIZE, 4 * PAGE_SIZE, NULL, 0, + ret = vmbus_open(dev->channel, 2 * PAGE_SIZE, 2 * PAGE_SIZE, NULL, 0, srv->util_cb, dev->channel); if (ret) goto error; diff --git a/trunk/drivers/hv/hyperv_vmbus.h b/trunk/drivers/hv/hyperv_vmbus.h index d8d1fadb398a..0614ff3a7d7e 100644 --- a/trunk/drivers/hv/hyperv_vmbus.h +++ b/trunk/drivers/hv/hyperv_vmbus.h @@ -410,49 +410,10 @@ enum { #define HV_PRESENT_BIT 0x80000000 -/* - * The guest OS needs to register the guest ID with the hypervisor. - * The guest ID is a 64 bit entity and the structure of this ID is - * specified in the Hyper-V specification: - * - * http://msdn.microsoft.com/en-us/library/windows/hardware/ff542653%28v=vs.85%29.aspx - * - * While the current guideline does not specify how Linux guest ID(s) - * need to be generated, our plan is to publish the guidelines for - * Linux and other guest operating systems that currently are hosted - * on Hyper-V. The implementation here conforms to this yet - * unpublished guidelines. - * - * - * Bit(s) - * 63 - Indicates if the OS is Open Source or not; 1 is Open Source - * 62:56 - Os Type; Linux is 0x100 - * 55:48 - Distro specific identification - * 47:16 - Linux kernel version number - * 15:0 - Distro specific identification - * - * - */ - -#define HV_LINUX_VENDOR_ID 0x8100 - -/* - * Generate the guest ID based on the guideline described above. - */ - -static inline __u64 generate_guest_id(__u8 d_info1, __u32 kernel_version, - __u16 d_info2) -{ - __u64 guest_id = 0; - - guest_id = (((__u64)HV_LINUX_VENDOR_ID) << 48); - guest_id |= (((__u64)(d_info1)) << 48); - guest_id |= (((__u64)(kernel_version)) << 16); - guest_id |= ((__u64)(d_info2)); - - return guest_id; -} - +#define HV_LINUX_GUEST_ID_LO 0x00000000 +#define HV_LINUX_GUEST_ID_HI 2976579765 +#define HV_LINUX_GUEST_ID (((u64)HV_LINUX_GUEST_ID_HI << 32) | \ + HV_LINUX_GUEST_ID_LO) #define HV_CPU_POWER_MANAGEMENT (1 << 0) #define HV_RECOMMENDATIONS_MAX 4 diff --git a/trunk/drivers/hv/vmbus_drv.c b/trunk/drivers/hv/vmbus_drv.c index 8e1a9ec53003..4748086eaaf2 100644 --- a/trunk/drivers/hv/vmbus_drv.c +++ b/trunk/drivers/hv/vmbus_drv.c @@ -34,7 +34,6 @@ #include #include #include -#include #include "hyperv_vmbus.h" @@ -147,9 +146,43 @@ static ssize_t vmbus_show_device_attr(struct device *dev, get_channel_info(hv_dev, device_info); if (!strcmp(dev_attr->attr.name, "class_id")) { - ret = sprintf(buf, "{%pUl}\n", device_info->chn_type.b); + ret = sprintf(buf, "{%02x%02x%02x%02x-%02x%02x-%02x%02x-" + "%02x%02x%02x%02x%02x%02x%02x%02x}\n", + device_info->chn_type.b[3], + device_info->chn_type.b[2], + device_info->chn_type.b[1], + device_info->chn_type.b[0], + device_info->chn_type.b[5], + device_info->chn_type.b[4], + device_info->chn_type.b[7], + device_info->chn_type.b[6], + device_info->chn_type.b[8], + device_info->chn_type.b[9], + device_info->chn_type.b[10], + device_info->chn_type.b[11], + device_info->chn_type.b[12], + device_info->chn_type.b[13], + device_info->chn_type.b[14], + device_info->chn_type.b[15]); } else if (!strcmp(dev_attr->attr.name, "device_id")) { - ret = sprintf(buf, "{%pUl}\n", device_info->chn_instance.b); + ret = sprintf(buf, "{%02x%02x%02x%02x-%02x%02x-%02x%02x-" + "%02x%02x%02x%02x%02x%02x%02x%02x}\n", + device_info->chn_instance.b[3], + device_info->chn_instance.b[2], + device_info->chn_instance.b[1], + device_info->chn_instance.b[0], + device_info->chn_instance.b[5], + device_info->chn_instance.b[4], + device_info->chn_instance.b[7], + device_info->chn_instance.b[6], + device_info->chn_instance.b[8], + device_info->chn_instance.b[9], + device_info->chn_instance.b[10], + device_info->chn_instance.b[11], + device_info->chn_instance.b[12], + device_info->chn_instance.b[13], + device_info->chn_instance.b[14], + device_info->chn_instance.b[15]); } else if (!strcmp(dev_attr->attr.name, "modalias")) { print_alias_name(hv_dev, alias_name); ret = sprintf(buf, "vmbus:%s\n", alias_name); @@ -724,9 +757,6 @@ static int __init hv_acpi_init(void) { int ret, t; - if (x86_hyper != &x86_hyper_ms_hyperv) - return -ENODEV; - init_completion(&probe_event); /* diff --git a/trunk/drivers/hwmon/ad7314.c b/trunk/drivers/hwmon/ad7314.c index f915eb1c29f7..cfec802cf9ca 100644 --- a/trunk/drivers/hwmon/ad7314.c +++ b/trunk/drivers/hwmon/ad7314.c @@ -87,18 +87,10 @@ static ssize_t ad7314_show_temperature(struct device *dev, } } -static ssize_t ad7314_show_name(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - return sprintf(buf, "%s\n", to_spi_device(dev)->modalias); -} - -static DEVICE_ATTR(name, S_IRUGO, ad7314_show_name, NULL); static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, ad7314_show_temperature, NULL, 0); static struct attribute *ad7314_attributes[] = { - &dev_attr_name.attr, &sensor_dev_attr_temp1_input.dev_attr.attr, NULL, }; diff --git a/trunk/drivers/hwmon/ads7871.c b/trunk/drivers/hwmon/ads7871.c index 7bf4ce3d405e..e65c6e45d36b 100644 --- a/trunk/drivers/hwmon/ads7871.c +++ b/trunk/drivers/hwmon/ads7871.c @@ -139,12 +139,6 @@ static ssize_t show_voltage(struct device *dev, } } -static ssize_t ads7871_show_name(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - return sprintf(buf, "%s\n", to_spi_device(dev)->modalias); -} - static SENSOR_DEVICE_ATTR(in0_input, S_IRUGO, show_voltage, NULL, 0); static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, show_voltage, NULL, 1); static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, show_voltage, NULL, 2); @@ -154,8 +148,6 @@ static SENSOR_DEVICE_ATTR(in5_input, S_IRUGO, show_voltage, NULL, 5); static SENSOR_DEVICE_ATTR(in6_input, S_IRUGO, show_voltage, NULL, 6); static SENSOR_DEVICE_ATTR(in7_input, S_IRUGO, show_voltage, NULL, 7); -static DEVICE_ATTR(name, S_IRUGO, ads7871_show_name, NULL); - static struct attribute *ads7871_attributes[] = { &sensor_dev_attr_in0_input.dev_attr.attr, &sensor_dev_attr_in1_input.dev_attr.attr, @@ -165,7 +157,6 @@ static struct attribute *ads7871_attributes[] = { &sensor_dev_attr_in5_input.dev_attr.attr, &sensor_dev_attr_in6_input.dev_attr.attr, &sensor_dev_attr_in7_input.dev_attr.attr, - &dev_attr_name.attr, NULL }; diff --git a/trunk/drivers/hwmon/applesmc.c b/trunk/drivers/hwmon/applesmc.c index 8f3f6f2c45fd..282708860517 100644 --- a/trunk/drivers/hwmon/applesmc.c +++ b/trunk/drivers/hwmon/applesmc.c @@ -53,10 +53,10 @@ #define APPLESMC_MAX_DATA_LENGTH 32 -/* wait up to 128 ms for a status change. */ +/* wait up to 32 ms for a status change. */ #define APPLESMC_MIN_WAIT 0x0010 #define APPLESMC_RETRY_WAIT 0x0100 -#define APPLESMC_MAX_WAIT 0x20000 +#define APPLESMC_MAX_WAIT 0x8000 #define APPLESMC_READ_CMD 0x10 #define APPLESMC_WRITE_CMD 0x11 diff --git a/trunk/drivers/hwmon/asus_atk0110.c b/trunk/drivers/hwmon/asus_atk0110.c index 4ee578948723..351d1f4593e7 100644 --- a/trunk/drivers/hwmon/asus_atk0110.c +++ b/trunk/drivers/hwmon/asus_atk0110.c @@ -34,12 +34,6 @@ static const struct dmi_system_id __initconst atk_force_new_if[] = { .matches = { DMI_MATCH(DMI_BOARD_NAME, "SABERTOOTH X58") } - }, { - /* Old interface reads the same sensor for fan0 and fan1 */ - .ident = "Asus M5A78L", - .matches = { - DMI_MATCH(DMI_BOARD_NAME, "M5A78L") - } }, { } }; diff --git a/trunk/drivers/hwmon/coretemp.c b/trunk/drivers/hwmon/coretemp.c index 984a3f13923b..faa16f80db9c 100644 --- a/trunk/drivers/hwmon/coretemp.c +++ b/trunk/drivers/hwmon/coretemp.c @@ -196,7 +196,7 @@ struct tjmax { int tjmax; }; -static const struct tjmax __cpuinitconst tjmax_table[] = { +static struct tjmax __cpuinitconst tjmax_table[] = { { "CPU D410", 100000 }, { "CPU D425", 100000 }, { "CPU D510", 100000 }, @@ -815,20 +815,17 @@ static int __init coretemp_init(void) if (err) goto exit; - get_online_cpus(); for_each_online_cpu(i) get_core_online(i); #ifndef CONFIG_HOTPLUG_CPU if (list_empty(&pdev_list)) { - put_online_cpus(); err = -ENODEV; goto exit_driver_unreg; } #endif register_hotcpu_notifier(&coretemp_cpu_notifier); - put_online_cpus(); return 0; #ifndef CONFIG_HOTPLUG_CPU @@ -843,7 +840,6 @@ static void __exit coretemp_exit(void) { struct pdev_entry *p, *n; - get_online_cpus(); unregister_hotcpu_notifier(&coretemp_cpu_notifier); mutex_lock(&pdev_list_mutex); list_for_each_entry_safe(p, n, &pdev_list, list) { @@ -852,7 +848,6 @@ static void __exit coretemp_exit(void) kfree(p); } mutex_unlock(&pdev_list_mutex); - put_online_cpus(); platform_driver_unregister(&coretemp_driver); } diff --git a/trunk/drivers/hwmon/fam15h_power.c b/trunk/drivers/hwmon/fam15h_power.c index af69073b3fe8..2764b78a784b 100644 --- a/trunk/drivers/hwmon/fam15h_power.c +++ b/trunk/drivers/hwmon/fam15h_power.c @@ -129,12 +129,12 @@ static bool __devinit fam15h_power_is_internal_node0(struct pci_dev *f4) * counter saturations resulting in bogus power readings. * We correct this value ourselves to cope with older BIOSes. */ -static const struct pci_device_id affected_device[] = { +static DEFINE_PCI_DEVICE_TABLE(affected_device) = { { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_NB_F4) }, { 0 } }; -static void tweak_runavg_range(struct pci_dev *pdev) +static void __devinit tweak_runavg_range(struct pci_dev *pdev) { u32 val; @@ -158,16 +158,6 @@ static void tweak_runavg_range(struct pci_dev *pdev) REG_TDP_RUNNING_AVERAGE, val); } -#ifdef CONFIG_PM -static int fam15h_power_resume(struct pci_dev *pdev) -{ - tweak_runavg_range(pdev); - return 0; -} -#else -#define fam15h_power_resume NULL -#endif - static void __devinit fam15h_power_init_data(struct pci_dev *f4, struct fam15h_power_data *data) { @@ -266,7 +256,6 @@ static struct pci_driver fam15h_power_driver = { .id_table = fam15h_power_id_table, .probe = fam15h_power_probe, .remove = __devexit_p(fam15h_power_remove), - .resume = fam15h_power_resume, }; module_pci_driver(fam15h_power_driver); diff --git a/trunk/drivers/hwmon/ina2xx.c b/trunk/drivers/hwmon/ina2xx.c index 602148299f68..7f3f4a385729 100644 --- a/trunk/drivers/hwmon/ina2xx.c +++ b/trunk/drivers/hwmon/ina2xx.c @@ -69,6 +69,22 @@ struct ina2xx_data { u16 regs[INA2XX_MAX_REGISTERS]; }; +int ina2xx_read_word(struct i2c_client *client, int reg) +{ + int val = i2c_smbus_read_word_data(client, reg); + if (unlikely(val < 0)) { + dev_dbg(&client->dev, + "Failed to read register: %d\n", reg); + return val; + } + return be16_to_cpu(val); +} + +void ina2xx_write_word(struct i2c_client *client, int reg, int data) +{ + i2c_smbus_write_word_data(client, reg, cpu_to_be16(data)); +} + static struct ina2xx_data *ina2xx_update_device(struct device *dev) { struct i2c_client *client = to_i2c_client(dev); @@ -86,7 +102,7 @@ static struct ina2xx_data *ina2xx_update_device(struct device *dev) /* Read all registers */ for (i = 0; i < data->registers; i++) { - int rv = i2c_smbus_read_word_swapped(client, i); + int rv = ina2xx_read_word(client, i); if (rv < 0) { ret = ERR_PTR(rv); goto abort; @@ -263,26 +279,22 @@ static int ina2xx_probe(struct i2c_client *client, switch (data->kind) { case ina219: /* device configuration */ - i2c_smbus_write_word_swapped(client, INA2XX_CONFIG, - INA219_CONFIG_DEFAULT); + ina2xx_write_word(client, INA2XX_CONFIG, INA219_CONFIG_DEFAULT); /* set current LSB to 1mA, shunt is in uOhms */ /* (equation 13 in datasheet) */ - i2c_smbus_write_word_swapped(client, INA2XX_CALIBRATION, - 40960000 / shunt); + ina2xx_write_word(client, INA2XX_CALIBRATION, 40960000 / shunt); dev_info(&client->dev, "power monitor INA219 (Rshunt = %li uOhm)\n", shunt); data->registers = INA219_REGISTERS; break; case ina226: /* device configuration */ - i2c_smbus_write_word_swapped(client, INA2XX_CONFIG, - INA226_CONFIG_DEFAULT); + ina2xx_write_word(client, INA2XX_CONFIG, INA226_CONFIG_DEFAULT); /* set current LSB to 1mA, shunt is in uOhms */ /* (equation 1 in datasheet)*/ - i2c_smbus_write_word_swapped(client, INA2XX_CALIBRATION, - 5120000 / shunt); + ina2xx_write_word(client, INA2XX_CALIBRATION, 5120000 / shunt); dev_info(&client->dev, "power monitor INA226 (Rshunt = %li uOhm)\n", shunt); data->registers = INA226_REGISTERS; diff --git a/trunk/drivers/hwmon/twl4030-madc-hwmon.c b/trunk/drivers/hwmon/twl4030-madc-hwmon.c index 1a174f0a3cde..0018c7dd0097 100644 --- a/trunk/drivers/hwmon/twl4030-madc-hwmon.c +++ b/trunk/drivers/hwmon/twl4030-madc-hwmon.c @@ -44,13 +44,12 @@ static ssize_t madc_read(struct device *dev, struct device_attribute *devattr, char *buf) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct twl4030_madc_request req = { - .channels = 1 << attr->index, - .method = TWL4030_MADC_SW2, - .type = TWL4030_MADC_WAIT, - }; + struct twl4030_madc_request req; long val; + req.channels = (1 << attr->index); + req.method = TWL4030_MADC_SW2; + req.func_cb = NULL; val = twl4030_madc_conversion(&req); if (val < 0) return val; diff --git a/trunk/drivers/hwmon/via-cputemp.c b/trunk/drivers/hwmon/via-cputemp.c index 2e56c6ce9fb6..ee4ebc198a94 100644 --- a/trunk/drivers/hwmon/via-cputemp.c +++ b/trunk/drivers/hwmon/via-cputemp.c @@ -328,7 +328,6 @@ static int __init via_cputemp_init(void) if (err) goto exit; - get_online_cpus(); for_each_online_cpu(i) { struct cpuinfo_x86 *c = &cpu_data(i); @@ -348,14 +347,12 @@ static int __init via_cputemp_init(void) #ifndef CONFIG_HOTPLUG_CPU if (list_empty(&pdev_list)) { - put_online_cpus(); err = -ENODEV; goto exit_driver_unreg; } #endif register_hotcpu_notifier(&via_cputemp_cpu_notifier); - put_online_cpus(); return 0; #ifndef CONFIG_HOTPLUG_CPU @@ -370,7 +367,6 @@ static void __exit via_cputemp_exit(void) { struct pdev_entry *p, *n; - get_online_cpus(); unregister_hotcpu_notifier(&via_cputemp_cpu_notifier); mutex_lock(&pdev_list_mutex); list_for_each_entry_safe(p, n, &pdev_list, list) { @@ -379,7 +375,6 @@ static void __exit via_cputemp_exit(void) kfree(p); } mutex_unlock(&pdev_list_mutex); - put_online_cpus(); platform_driver_unregister(&via_cputemp_driver); } diff --git a/trunk/drivers/hwmon/w83627hf.c b/trunk/drivers/hwmon/w83627hf.c index 5b1a6a666441..ab4825205a9d 100644 --- a/trunk/drivers/hwmon/w83627hf.c +++ b/trunk/drivers/hwmon/w83627hf.c @@ -1206,7 +1206,7 @@ static int __init w83627hf_find(int sioaddr, unsigned short *addr, int err = -ENODEV; u16 val; - static __initconst char *const names[] = { + static const __initdata char *names[] = { "W83627HF", "W83627THF", "W83697HF", diff --git a/trunk/drivers/hwspinlock/hwspinlock_core.c b/trunk/drivers/hwspinlock/hwspinlock_core.c index db713c0dfba4..1201a15784c3 100644 --- a/trunk/drivers/hwspinlock/hwspinlock_core.c +++ b/trunk/drivers/hwspinlock/hwspinlock_core.c @@ -552,7 +552,7 @@ EXPORT_SYMBOL_GPL(hwspin_lock_request_specific); */ int hwspin_lock_free(struct hwspinlock *hwlock) { - struct device *dev; + struct device *dev = hwlock->bank->dev; struct hwspinlock *tmp; int ret; @@ -561,7 +561,6 @@ int hwspin_lock_free(struct hwspinlock *hwlock) return -EINVAL; } - dev = hwlock->bank->dev; mutex_lock(&hwspinlock_tree_lock); /* make sure the hwspinlock is used */ diff --git a/trunk/drivers/i2c/algos/i2c-algo-pca.c b/trunk/drivers/i2c/algos/i2c-algo-pca.c index 6f5f98d69af7..73133b1063f0 100644 --- a/trunk/drivers/i2c/algos/i2c-algo-pca.c +++ b/trunk/drivers/i2c/algos/i2c-algo-pca.c @@ -476,17 +476,17 @@ static int pca_init(struct i2c_adapter *adap) /* To avoid integer overflow, use clock/100 for calculations */ clock = pca_clock(pca_data) / 100; - if (pca_data->i2c_clock > 1000000) { + if (pca_data->i2c_clock > 10000) { mode = I2C_PCA_MODE_TURBO; min_tlow = 14; min_thi = 5; raise_fall_time = 22; /* Raise 11e-8s, Fall 11e-8s */ - } else if (pca_data->i2c_clock > 400000) { + } else if (pca_data->i2c_clock > 4000) { mode = I2C_PCA_MODE_FASTP; min_tlow = 17; min_thi = 9; raise_fall_time = 22; /* Raise 11e-8s, Fall 11e-8s */ - } else if (pca_data->i2c_clock > 100000) { + } else if (pca_data->i2c_clock > 1000) { mode = I2C_PCA_MODE_FAST; min_tlow = 44; min_thi = 20; diff --git a/trunk/drivers/i2c/busses/Kconfig b/trunk/drivers/i2c/busses/Kconfig index 970a1612e795..b4aaa1bd6728 100644 --- a/trunk/drivers/i2c/busses/Kconfig +++ b/trunk/drivers/i2c/busses/Kconfig @@ -104,7 +104,6 @@ config I2C_I801 DH89xxCC (PCH) Panther Point (PCH) Lynx Point (PCH) - Lynx Point-LP (PCH) This driver can also be built as a module. If so, the module will be called i2c-i801. @@ -355,13 +354,9 @@ config I2C_DAVINCI devices such as DaVinci NIC. For details please see http://www.ti.com/davinci -config I2C_DESIGNWARE_CORE - tristate - config I2C_DESIGNWARE_PLATFORM tristate "Synopsys DesignWare Platform" depends on HAVE_CLK - select I2C_DESIGNWARE_CORE help If you say yes to this option, support will be included for the Synopsys DesignWare I2C adapter. Only master mode is supported. @@ -372,7 +367,6 @@ config I2C_DESIGNWARE_PLATFORM config I2C_DESIGNWARE_PCI tristate "Synopsys DesignWare PCI" depends on PCI - select I2C_DESIGNWARE_CORE help If you say yes to this option, support will be included for the Synopsys DesignWare I2C adapter. Only master mode is supported. diff --git a/trunk/drivers/i2c/busses/Makefile b/trunk/drivers/i2c/busses/Makefile index 37c4182cc98b..ce3c2be7fb40 100644 --- a/trunk/drivers/i2c/busses/Makefile +++ b/trunk/drivers/i2c/busses/Makefile @@ -33,11 +33,10 @@ obj-$(CONFIG_I2C_AU1550) += i2c-au1550.o obj-$(CONFIG_I2C_BLACKFIN_TWI) += i2c-bfin-twi.o obj-$(CONFIG_I2C_CPM) += i2c-cpm.o obj-$(CONFIG_I2C_DAVINCI) += i2c-davinci.o -obj-$(CONFIG_I2C_DESIGNWARE_CORE) += i2c-designware-core.o obj-$(CONFIG_I2C_DESIGNWARE_PLATFORM) += i2c-designware-platform.o -i2c-designware-platform-objs := i2c-designware-platdrv.o +i2c-designware-platform-objs := i2c-designware-platdrv.o i2c-designware-core.o obj-$(CONFIG_I2C_DESIGNWARE_PCI) += i2c-designware-pci.o -i2c-designware-pci-objs := i2c-designware-pcidrv.o +i2c-designware-pci-objs := i2c-designware-pcidrv.o i2c-designware-core.o obj-$(CONFIG_I2C_EG20T) += i2c-eg20t.o obj-$(CONFIG_I2C_GPIO) += i2c-gpio.o obj-$(CONFIG_I2C_HIGHLANDER) += i2c-highlander.o diff --git a/trunk/drivers/i2c/busses/i2c-designware-core.c b/trunk/drivers/i2c/busses/i2c-designware-core.c index 7b8ebbefb581..1e48bec80edf 100644 --- a/trunk/drivers/i2c/busses/i2c-designware-core.c +++ b/trunk/drivers/i2c/busses/i2c-designware-core.c @@ -25,7 +25,6 @@ * ---------------------------------------------------------------------------- * */ -#include #include #include #include @@ -317,7 +316,6 @@ int i2c_dw_init(struct dw_i2c_dev *dev) dw_writel(dev, dev->master_cfg , DW_IC_CON); return 0; } -EXPORT_SYMBOL_GPL(i2c_dw_init); /* * Waiting for bus not busy @@ -570,14 +568,12 @@ i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) return ret; } -EXPORT_SYMBOL_GPL(i2c_dw_xfer); u32 i2c_dw_func(struct i2c_adapter *adap) { struct dw_i2c_dev *dev = i2c_get_adapdata(adap); return dev->functionality; } -EXPORT_SYMBOL_GPL(i2c_dw_func); static u32 i2c_dw_read_clear_intrbits(struct dw_i2c_dev *dev) { @@ -682,20 +678,17 @@ irqreturn_t i2c_dw_isr(int this_irq, void *dev_id) return IRQ_HANDLED; } -EXPORT_SYMBOL_GPL(i2c_dw_isr); void i2c_dw_enable(struct dw_i2c_dev *dev) { /* Enable the adapter */ dw_writel(dev, 1, DW_IC_ENABLE); } -EXPORT_SYMBOL_GPL(i2c_dw_enable); u32 i2c_dw_is_enabled(struct dw_i2c_dev *dev) { return dw_readl(dev, DW_IC_ENABLE); } -EXPORT_SYMBOL_GPL(i2c_dw_is_enabled); void i2c_dw_disable(struct dw_i2c_dev *dev) { @@ -706,22 +699,18 @@ void i2c_dw_disable(struct dw_i2c_dev *dev) dw_writel(dev, 0, DW_IC_INTR_MASK); dw_readl(dev, DW_IC_CLR_INTR); } -EXPORT_SYMBOL_GPL(i2c_dw_disable); void i2c_dw_clear_int(struct dw_i2c_dev *dev) { dw_readl(dev, DW_IC_CLR_INTR); } -EXPORT_SYMBOL_GPL(i2c_dw_clear_int); void i2c_dw_disable_int(struct dw_i2c_dev *dev) { dw_writel(dev, 0, DW_IC_INTR_MASK); } -EXPORT_SYMBOL_GPL(i2c_dw_disable_int); u32 i2c_dw_read_comp_param(struct dw_i2c_dev *dev) { return dw_readl(dev, DW_IC_COMP_PARAM_1); } -EXPORT_SYMBOL_GPL(i2c_dw_read_comp_param); diff --git a/trunk/drivers/i2c/busses/i2c-diolan-u2c.c b/trunk/drivers/i2c/busses/i2c-diolan-u2c.c index dae3ddfe7619..aedb94f34bf7 100644 --- a/trunk/drivers/i2c/busses/i2c-diolan-u2c.c +++ b/trunk/drivers/i2c/busses/i2c-diolan-u2c.c @@ -405,7 +405,6 @@ static int diolan_usb_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, } } } - ret = num; abort: sret = diolan_i2c_stop(dev); if (sret < 0 && ret >= 0) diff --git a/trunk/drivers/i2c/busses/i2c-i801.c b/trunk/drivers/i2c/busses/i2c-i801.c index 33e9b0c09af2..898dcf9c7ade 100644 --- a/trunk/drivers/i2c/busses/i2c-i801.c +++ b/trunk/drivers/i2c/busses/i2c-i801.c @@ -52,7 +52,6 @@ DH89xxCC (PCH) 0x2330 32 hard yes yes yes Panther Point (PCH) 0x1e22 32 hard yes yes yes Lynx Point (PCH) 0x8c22 32 hard yes yes yes - Lynx Point-LP (PCH) 0x9c22 32 hard yes yes yes Features supported by this driver: Software PEC no @@ -156,7 +155,6 @@ #define PCI_DEVICE_ID_INTEL_DH89XXCC_SMBUS 0x2330 #define PCI_DEVICE_ID_INTEL_5_3400_SERIES_SMBUS 0x3b30 #define PCI_DEVICE_ID_INTEL_LYNXPOINT_SMBUS 0x8c22 -#define PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_SMBUS 0x9c22 struct i801_priv { struct i2c_adapter adapter; @@ -773,7 +771,6 @@ static DEFINE_PCI_DEVICE_TABLE(i801_ids) = { { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_DH89XXCC_SMBUS) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PANTHERPOINT_SMBUS) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_LYNXPOINT_SMBUS) }, - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_SMBUS) }, { 0, } }; diff --git a/trunk/drivers/i2c/busses/i2c-mxs.c b/trunk/drivers/i2c/busses/i2c-mxs.c index 51f05b8520ed..088c5c1ed17d 100644 --- a/trunk/drivers/i2c/busses/i2c-mxs.c +++ b/trunk/drivers/i2c/busses/i2c-mxs.c @@ -365,6 +365,10 @@ static int mxs_i2c_get_ofdata(struct mxs_i2c_dev *i2c) struct device_node *node = dev->of_node; int ret; + if (!node) + return -EINVAL; + + i2c->speed = &mxs_i2c_95kHz_config; ret = of_property_read_u32(node, "clock-frequency", &speed); if (ret) dev_warn(dev, "No I2C speed selected, using 100kHz\n"); @@ -415,13 +419,10 @@ static int __devinit mxs_i2c_probe(struct platform_device *pdev) return err; i2c->dev = dev; - i2c->speed = &mxs_i2c_95kHz_config; - if (dev->of_node) { - err = mxs_i2c_get_ofdata(i2c); - if (err) - return err; - } + err = mxs_i2c_get_ofdata(i2c); + if (err) + return err; platform_set_drvdata(pdev, i2c); diff --git a/trunk/drivers/i2c/busses/i2c-nomadik.c b/trunk/drivers/i2c/busses/i2c-nomadik.c index 61b00edacb08..5e6f1eed4f83 100644 --- a/trunk/drivers/i2c/busses/i2c-nomadik.c +++ b/trunk/drivers/i2c/busses/i2c-nomadik.c @@ -350,6 +350,10 @@ static void setup_i2c_controller(struct nmk_i2c_dev *dev) i2c_clk = clk_get_rate(dev->clk); + /* fallback to std. mode if machine has not provided it */ + if (dev->cfg.clk_freq == 0) + dev->cfg.clk_freq = 100000; + /* * The spec says, in case of std. mode the divider is * 2 whereas it is 3 for fast and fastplus mode of @@ -907,32 +911,20 @@ static const struct i2c_algorithm nmk_i2c_algo = { .functionality = nmk_i2c_functionality }; -static struct nmk_i2c_controller u8500_i2c = { - /* - * Slave data setup time; 250ns, 100ns, and 10ns, which - * is 14, 6 and 2 respectively for a 48Mhz i2c clock. - */ - .slsu = 0xe, - .tft = 1, /* Tx FIFO threshold */ - .rft = 8, /* Rx FIFO threshold */ - .clk_freq = 400000, /* fast mode operation */ - .timeout = 200, /* Slave response timeout(ms) */ - .sm = I2C_FREQ_MODE_FAST, -}; - static atomic_t adapter_id = ATOMIC_INIT(0); static int nmk_i2c_probe(struct amba_device *adev, const struct amba_id *id) { int ret = 0; - struct nmk_i2c_controller *pdata = adev->dev.platform_data; + struct nmk_i2c_controller *pdata = + adev->dev.platform_data; struct nmk_i2c_dev *dev; struct i2c_adapter *adap; - if (!pdata) - /* No i2c configuration found, using the default. */ - pdata = &u8500_i2c; - + if (!pdata) { + dev_warn(&adev->dev, "no platform data\n"); + return -ENODEV; + } dev = kzalloc(sizeof(struct nmk_i2c_dev), GFP_KERNEL); if (!dev) { dev_err(&adev->dev, "cannot allocate memory\n"); diff --git a/trunk/drivers/i2c/busses/i2c-omap.c b/trunk/drivers/i2c/busses/i2c-omap.c index 5d19a49803c1..6849635b268a 100644 --- a/trunk/drivers/i2c/busses/i2c-omap.c +++ b/trunk/drivers/i2c/busses/i2c-omap.c @@ -584,7 +584,7 @@ omap_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) r = pm_runtime_get_sync(dev->dev); if (IS_ERR_VALUE(r)) - goto out; + return r; r = omap_i2c_wait_for_bb(dev); if (r < 0) diff --git a/trunk/drivers/i2c/busses/i2c-pnx.c b/trunk/drivers/i2c/busses/i2c-pnx.c index 8488bddfe465..5d54416770b0 100644 --- a/trunk/drivers/i2c/busses/i2c-pnx.c +++ b/trunk/drivers/i2c/busses/i2c-pnx.c @@ -48,9 +48,8 @@ enum { mcntrl_afie = 0x00000002, mcntrl_naie = 0x00000004, mcntrl_drmie = 0x00000008, - mcntrl_drsie = 0x00000010, - mcntrl_rffie = 0x00000020, - mcntrl_daie = 0x00000040, + mcntrl_daie = 0x00000020, + mcntrl_rffie = 0x00000040, mcntrl_tffie = 0x00000080, mcntrl_reset = 0x00000100, mcntrl_cdbmode = 0x00000400, @@ -291,37 +290,31 @@ static int i2c_pnx_master_rcv(struct i2c_pnx_algo_data *alg_data) * or we didn't 'ask' for it yet. */ if (ioread32(I2C_REG_STS(alg_data)) & mstatus_rfe) { - /* 'Asking' is done asynchronously, e.g. dummy TX of several - * bytes is done before the first actual RX arrives in FIFO. - * Therefore, ordered bytes (via TX) are counted separately. - */ - if (alg_data->mif.order) { - dev_dbg(&alg_data->adapter.dev, - "%s(): Write dummy data to fill Rx-fifo...\n", - __func__); + dev_dbg(&alg_data->adapter.dev, + "%s(): Write dummy data to fill Rx-fifo...\n", + __func__); - if (alg_data->mif.order == 1) { - /* Last byte, do not acknowledge next rcv. */ - val |= stop_bit; - - /* - * Enable interrupt RFDAIE (data in Rx fifo), - * and disable DRMIE (need data for Tx) - */ - ctl = ioread32(I2C_REG_CTL(alg_data)); - ctl |= mcntrl_rffie | mcntrl_daie; - ctl &= ~mcntrl_drmie; - iowrite32(ctl, I2C_REG_CTL(alg_data)); - } + if (alg_data->mif.len == 1) { + /* Last byte, do not acknowledge next rcv. */ + val |= stop_bit; /* - * Now we'll 'ask' for data: - * For each byte we want to receive, we must - * write a (dummy) byte to the Tx-FIFO. + * Enable interrupt RFDAIE (data in Rx fifo), + * and disable DRMIE (need data for Tx) */ - iowrite32(val, I2C_REG_TX(alg_data)); - alg_data->mif.order--; + ctl = ioread32(I2C_REG_CTL(alg_data)); + ctl |= mcntrl_rffie | mcntrl_daie; + ctl &= ~mcntrl_drmie; + iowrite32(ctl, I2C_REG_CTL(alg_data)); } + + /* + * Now we'll 'ask' for data: + * For each byte we want to receive, we must + * write a (dummy) byte to the Tx-FIFO. + */ + iowrite32(val, I2C_REG_TX(alg_data)); + return 0; } @@ -521,7 +514,6 @@ i2c_pnx_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) alg_data->mif.buf = pmsg->buf; alg_data->mif.len = pmsg->len; - alg_data->mif.order = pmsg->len; alg_data->mif.mode = (pmsg->flags & I2C_M_RD) ? I2C_SMBUS_READ : I2C_SMBUS_WRITE; alg_data->mif.ret = 0; @@ -574,7 +566,6 @@ i2c_pnx_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) /* Cleanup to be sure... */ alg_data->mif.buf = NULL; alg_data->mif.len = 0; - alg_data->mif.order = 0; dev_dbg(&alg_data->adapter.dev, "%s(): exiting, stat = %x\n", __func__, ioread32(I2C_REG_STS(alg_data))); diff --git a/trunk/drivers/i2c/busses/i2c-tegra.c b/trunk/drivers/i2c/busses/i2c-tegra.c index 9a08c57bc936..66eb53fac202 100644 --- a/trunk/drivers/i2c/busses/i2c-tegra.c +++ b/trunk/drivers/i2c/busses/i2c-tegra.c @@ -712,7 +712,7 @@ static int __devexit tegra_i2c_remove(struct platform_device *pdev) return 0; } -#ifdef CONFIG_PM_SLEEP +#ifdef CONFIG_PM static int tegra_i2c_suspend(struct device *dev) { struct tegra_i2c_dev *i2c_dev = dev_get_drvdata(dev); diff --git a/trunk/drivers/i2c/i2c-core.c b/trunk/drivers/i2c/i2c-core.c index 2091ae8f539a..2efa56c5ff2c 100644 --- a/trunk/drivers/i2c/i2c-core.c +++ b/trunk/drivers/i2c/i2c-core.c @@ -636,22 +636,6 @@ static void i2c_adapter_dev_release(struct device *dev) complete(&adap->dev_released); } -/* - * This function is only needed for mutex_lock_nested, so it is never - * called unless locking correctness checking is enabled. Thus we - * make it inline to avoid a compiler warning. That's what gcc ends up - * doing anyway. - */ -static inline unsigned int i2c_adapter_depth(struct i2c_adapter *adapter) -{ - unsigned int depth = 0; - - while ((adapter = i2c_parent_is_i2c_adapter(adapter))) - depth++; - - return depth; -} - /* * Let users instantiate I2C devices through sysfs. This can be used when * platform initialization code doesn't contain the proper data for @@ -742,8 +726,7 @@ i2c_sysfs_delete_device(struct device *dev, struct device_attribute *attr, /* Make sure the device was added through sysfs */ res = -ENOENT; - mutex_lock_nested(&adap->userspace_clients_lock, - i2c_adapter_depth(adap)); + mutex_lock(&adap->userspace_clients_lock); list_for_each_entry_safe(client, next, &adap->userspace_clients, detected) { if (client->addr == addr) { @@ -1090,8 +1073,7 @@ int i2c_del_adapter(struct i2c_adapter *adap) return res; /* Remove devices instantiated from sysfs */ - mutex_lock_nested(&adap->userspace_clients_lock, - i2c_adapter_depth(adap)); + mutex_lock(&adap->userspace_clients_lock); list_for_each_entry_safe(client, next, &adap->userspace_clients, detected) { dev_dbg(&adap->dev, "Removing %s at 0x%x\n", client->name, diff --git a/trunk/drivers/ide/ide-pm.c b/trunk/drivers/ide/ide-pm.c index 8d1e32d7cd97..92406097efeb 100644 --- a/trunk/drivers/ide/ide-pm.c +++ b/trunk/drivers/ide/ide-pm.c @@ -4,7 +4,7 @@ int generic_ide_suspend(struct device *dev, pm_message_t mesg) { - ide_drive_t *drive = to_ide_device(dev); + ide_drive_t *drive = dev_get_drvdata(dev); ide_drive_t *pair = ide_get_pair_dev(drive); ide_hwif_t *hwif = drive->hwif; struct request *rq; @@ -40,7 +40,7 @@ int generic_ide_suspend(struct device *dev, pm_message_t mesg) int generic_ide_resume(struct device *dev) { - ide_drive_t *drive = to_ide_device(dev); + ide_drive_t *drive = dev_get_drvdata(dev); ide_drive_t *pair = ide_get_pair_dev(drive); ide_hwif_t *hwif = drive->hwif; struct request *rq; diff --git a/trunk/drivers/idle/intel_idle.c b/trunk/drivers/idle/intel_idle.c index e8726177d103..f559088869f6 100644 --- a/trunk/drivers/idle/intel_idle.c +++ b/trunk/drivers/idle/intel_idle.c @@ -606,9 +606,8 @@ static int __init intel_idle_init(void) intel_idle_cpuidle_driver_init(); retval = cpuidle_register_driver(&intel_idle_driver); if (retval) { - struct cpuidle_driver *drv = cpuidle_get_driver(); printk(KERN_DEBUG PREFIX "intel_idle yielding to %s", - drv ? drv->name : "none"); + cpuidle_get_driver()->name); return retval; } diff --git a/trunk/drivers/iio/Kconfig b/trunk/drivers/iio/Kconfig index 6e3f143fc71d..d4984c8be973 100644 --- a/trunk/drivers/iio/Kconfig +++ b/trunk/drivers/iio/Kconfig @@ -1,5 +1,5 @@ # -# Industrial I/O subsystem configuration +# Industrial I/O subsytem configuration # menuconfig IIO @@ -54,15 +54,10 @@ config IIO_CONSUMERS_PER_TRIGGER This value controls the maximum number of consumers that a given trigger may handle. Default is 2. -source "drivers/iio/accel/Kconfig" source "drivers/iio/adc/Kconfig" source "drivers/iio/amplifiers/Kconfig" source "drivers/iio/light/Kconfig" source "drivers/iio/frequency/Kconfig" source "drivers/iio/dac/Kconfig" -source "drivers/iio/common/Kconfig" -source "drivers/iio/gyro/Kconfig" -source "drivers/iio/light/Kconfig" -source "drivers/iio/magnetometer/Kconfig" endif # IIO diff --git a/trunk/drivers/iio/Makefile b/trunk/drivers/iio/Makefile index f7fa3c0867b4..34309abb7979 100644 --- a/trunk/drivers/iio/Makefile +++ b/trunk/drivers/iio/Makefile @@ -10,13 +10,8 @@ industrialio-$(CONFIG_IIO_TRIGGER) += industrialio-trigger.o obj-$(CONFIG_IIO_TRIGGERED_BUFFER) += industrialio-triggered-buffer.o obj-$(CONFIG_IIO_KFIFO_BUF) += kfifo_buf.o -obj-y += accel/ obj-y += adc/ obj-y += amplifiers/ obj-y += light/ obj-y += frequency/ obj-y += dac/ -obj-y += common/ -obj-y += gyro/ -obj-y += light/ -obj-y += magnetometer/ diff --git a/trunk/drivers/iio/accel/Kconfig b/trunk/drivers/iio/accel/Kconfig deleted file mode 100644 index b2510c4d9a5a..000000000000 --- a/trunk/drivers/iio/accel/Kconfig +++ /dev/null @@ -1,16 +0,0 @@ -# -# Accelerometer drivers -# -menu "Accelerometers" - -config HID_SENSOR_ACCEL_3D - depends on HID_SENSOR_HUB - select IIO_BUFFER - select IIO_TRIGGERED_BUFFER - select HID_SENSOR_IIO_COMMON - tristate "HID Acelerometers 3D" - help - Say yes here to build support for the HID SENSOR - accelerometers 3D. - -endmenu diff --git a/trunk/drivers/iio/accel/Makefile b/trunk/drivers/iio/accel/Makefile deleted file mode 100644 index 5bc6855a973e..000000000000 --- a/trunk/drivers/iio/accel/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -# -# Makefile for industrial I/O accelerometer drivers -# - -obj-$(CONFIG_HID_SENSOR_ACCEL_3D) += hid-sensor-accel-3d.o diff --git a/trunk/drivers/iio/accel/hid-sensor-accel-3d.c b/trunk/drivers/iio/accel/hid-sensor-accel-3d.c deleted file mode 100644 index 314a4057879e..000000000000 --- a/trunk/drivers/iio/accel/hid-sensor-accel-3d.c +++ /dev/null @@ -1,418 +0,0 @@ -/* - * HID Sensors Driver - * Copyright (c) 2012, Intel Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "../common/hid-sensors/hid-sensor-attributes.h" -#include "../common/hid-sensors/hid-sensor-trigger.h" - -/*Format: HID-SENSOR-usage_id_in_hex*/ -/*Usage ID from spec for Accelerometer-3D: 0x200073*/ -#define DRIVER_NAME "HID-SENSOR-200073" - -enum accel_3d_channel { - CHANNEL_SCAN_INDEX_X, - CHANNEL_SCAN_INDEX_Y, - CHANNEL_SCAN_INDEX_Z, - ACCEL_3D_CHANNEL_MAX, -}; - -struct accel_3d_state { - struct hid_sensor_hub_callbacks callbacks; - struct hid_sensor_iio_common common_attributes; - struct hid_sensor_hub_attribute_info accel[ACCEL_3D_CHANNEL_MAX]; - u32 accel_val[ACCEL_3D_CHANNEL_MAX]; -}; - -static const u32 accel_3d_addresses[ACCEL_3D_CHANNEL_MAX] = { - HID_USAGE_SENSOR_ACCEL_X_AXIS, - HID_USAGE_SENSOR_ACCEL_Y_AXIS, - HID_USAGE_SENSOR_ACCEL_Z_AXIS -}; - -/* Channel definitions */ -static const struct iio_chan_spec accel_3d_channels[] = { - { - .type = IIO_ACCEL, - .modified = 1, - .channel2 = IIO_MOD_X, - .info_mask = IIO_CHAN_INFO_OFFSET_SHARED_BIT | - IIO_CHAN_INFO_SCALE_SHARED_BIT | - IIO_CHAN_INFO_SAMP_FREQ_SHARED_BIT | - IIO_CHAN_INFO_HYSTERESIS_SHARED_BIT, - .scan_index = CHANNEL_SCAN_INDEX_X, - }, { - .type = IIO_ACCEL, - .modified = 1, - .channel2 = IIO_MOD_Y, - .info_mask = IIO_CHAN_INFO_OFFSET_SHARED_BIT | - IIO_CHAN_INFO_SCALE_SHARED_BIT | - IIO_CHAN_INFO_SAMP_FREQ_SHARED_BIT | - IIO_CHAN_INFO_HYSTERESIS_SHARED_BIT, - .scan_index = CHANNEL_SCAN_INDEX_Y, - }, { - .type = IIO_ACCEL, - .modified = 1, - .channel2 = IIO_MOD_Z, - .info_mask = IIO_CHAN_INFO_OFFSET_SHARED_BIT | - IIO_CHAN_INFO_SCALE_SHARED_BIT | - IIO_CHAN_INFO_SAMP_FREQ_SHARED_BIT | - IIO_CHAN_INFO_HYSTERESIS_SHARED_BIT, - .scan_index = CHANNEL_SCAN_INDEX_Z, - } -}; - -/* Adjust channel real bits based on report descriptor */ -static void accel_3d_adjust_channel_bit_mask(struct iio_chan_spec *channels, - int channel, int size) -{ - channels[channel].scan_type.sign = 's'; - /* Real storage bits will change based on the report desc. */ - channels[channel].scan_type.realbits = size * 8; - /* Maximum size of a sample to capture is u32 */ - channels[channel].scan_type.storagebits = sizeof(u32) * 8; -} - -/* Channel read_raw handler */ -static int accel_3d_read_raw(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, - int *val, int *val2, - long mask) -{ - struct accel_3d_state *accel_state = iio_priv(indio_dev); - int report_id = -1; - u32 address; - int ret; - int ret_type; - - *val = 0; - *val2 = 0; - switch (mask) { - case 0: - report_id = accel_state->accel[chan->scan_index].report_id; - address = accel_3d_addresses[chan->scan_index]; - if (report_id >= 0) - *val = sensor_hub_input_attr_get_raw_value( - accel_state->common_attributes.hsdev, - HID_USAGE_SENSOR_ACCEL_3D, address, - report_id); - else { - *val = 0; - return -EINVAL; - } - ret_type = IIO_VAL_INT; - break; - case IIO_CHAN_INFO_SCALE: - *val = accel_state->accel[CHANNEL_SCAN_INDEX_X].units; - ret_type = IIO_VAL_INT; - break; - case IIO_CHAN_INFO_OFFSET: - *val = hid_sensor_convert_exponent( - accel_state->accel[CHANNEL_SCAN_INDEX_X].unit_expo); - ret_type = IIO_VAL_INT; - break; - case IIO_CHAN_INFO_SAMP_FREQ: - ret = hid_sensor_read_samp_freq_value( - &accel_state->common_attributes, val, val2); - ret_type = IIO_VAL_INT_PLUS_MICRO; - break; - case IIO_CHAN_INFO_HYSTERESIS: - ret = hid_sensor_read_raw_hyst_value( - &accel_state->common_attributes, val, val2); - ret_type = IIO_VAL_INT_PLUS_MICRO; - break; - default: - ret_type = -EINVAL; - break; - } - - return ret_type; -} - -/* Channel write_raw handler */ -static int accel_3d_write_raw(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, - int val, - int val2, - long mask) -{ - struct accel_3d_state *accel_state = iio_priv(indio_dev); - int ret = 0; - - switch (mask) { - case IIO_CHAN_INFO_SAMP_FREQ: - ret = hid_sensor_write_samp_freq_value( - &accel_state->common_attributes, val, val2); - break; - case IIO_CHAN_INFO_HYSTERESIS: - ret = hid_sensor_write_raw_hyst_value( - &accel_state->common_attributes, val, val2); - break; - default: - ret = -EINVAL; - } - - return ret; -} - -static int accel_3d_write_raw_get_fmt(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, - long mask) -{ - return IIO_VAL_INT_PLUS_MICRO; -} - -static const struct iio_info accel_3d_info = { - .driver_module = THIS_MODULE, - .read_raw = &accel_3d_read_raw, - .write_raw = &accel_3d_write_raw, - .write_raw_get_fmt = &accel_3d_write_raw_get_fmt, -}; - -/* Function to push data to buffer */ -static void hid_sensor_push_data(struct iio_dev *indio_dev, u8 *data, int len) -{ - struct iio_buffer *buffer = indio_dev->buffer; - int datum_sz; - - dev_dbg(&indio_dev->dev, "hid_sensor_push_data\n"); - if (!buffer) { - dev_err(&indio_dev->dev, "Buffer == NULL\n"); - return; - } - datum_sz = buffer->access->get_bytes_per_datum(buffer); - if (len > datum_sz) { - dev_err(&indio_dev->dev, "Datum size mismatch %d:%d\n", len, - datum_sz); - return; - } - iio_push_to_buffer(buffer, (u8 *)data); -} - -/* Callback handler to send event after all samples are received and captured */ -static int accel_3d_proc_event(struct hid_sensor_hub_device *hsdev, - unsigned usage_id, - void *priv) -{ - struct iio_dev *indio_dev = platform_get_drvdata(priv); - struct accel_3d_state *accel_state = iio_priv(indio_dev); - - dev_dbg(&indio_dev->dev, "accel_3d_proc_event [%d]\n", - accel_state->common_attributes.data_ready); - if (accel_state->common_attributes.data_ready) - hid_sensor_push_data(indio_dev, - (u8 *)accel_state->accel_val, - sizeof(accel_state->accel_val)); - - return 0; -} - -/* Capture samples in local storage */ -static int accel_3d_capture_sample(struct hid_sensor_hub_device *hsdev, - unsigned usage_id, - size_t raw_len, char *raw_data, - void *priv) -{ - struct iio_dev *indio_dev = platform_get_drvdata(priv); - struct accel_3d_state *accel_state = iio_priv(indio_dev); - int offset; - int ret = -EINVAL; - - switch (usage_id) { - case HID_USAGE_SENSOR_ACCEL_X_AXIS: - case HID_USAGE_SENSOR_ACCEL_Y_AXIS: - case HID_USAGE_SENSOR_ACCEL_Z_AXIS: - offset = usage_id - HID_USAGE_SENSOR_ACCEL_X_AXIS; - accel_state->accel_val[CHANNEL_SCAN_INDEX_X + offset] = - *(u32 *)raw_data; - ret = 0; - break; - default: - break; - } - - return ret; -} - -/* Parse report which is specific to an usage id*/ -static int accel_3d_parse_report(struct platform_device *pdev, - struct hid_sensor_hub_device *hsdev, - struct iio_chan_spec *channels, - unsigned usage_id, - struct accel_3d_state *st) -{ - int ret; - int i; - - for (i = 0; i <= CHANNEL_SCAN_INDEX_Z; ++i) { - ret = sensor_hub_input_get_attribute_info(hsdev, - HID_INPUT_REPORT, - usage_id, - HID_USAGE_SENSOR_ACCEL_X_AXIS + i, - &st->accel[CHANNEL_SCAN_INDEX_X + i]); - if (ret < 0) - break; - accel_3d_adjust_channel_bit_mask(channels, - CHANNEL_SCAN_INDEX_X + i, - st->accel[CHANNEL_SCAN_INDEX_X + i].size); - } - dev_dbg(&pdev->dev, "accel_3d %x:%x, %x:%x, %x:%x\n", - st->accel[0].index, - st->accel[0].report_id, - st->accel[1].index, st->accel[1].report_id, - st->accel[2].index, st->accel[2].report_id); - - return ret; -} - -/* Function to initialize the processing for usage id */ -static int __devinit hid_accel_3d_probe(struct platform_device *pdev) -{ - int ret = 0; - static const char *name = "accel_3d"; - struct iio_dev *indio_dev; - struct accel_3d_state *accel_state; - struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data; - struct iio_chan_spec *channels; - - indio_dev = iio_device_alloc(sizeof(struct accel_3d_state)); - if (indio_dev == NULL) { - ret = -ENOMEM; - goto error_ret; - } - platform_set_drvdata(pdev, indio_dev); - - accel_state = iio_priv(indio_dev); - accel_state->common_attributes.hsdev = hsdev; - accel_state->common_attributes.pdev = pdev; - - ret = hid_sensor_parse_common_attributes(hsdev, - HID_USAGE_SENSOR_ACCEL_3D, - &accel_state->common_attributes); - if (ret) { - dev_err(&pdev->dev, "failed to setup common attributes\n"); - goto error_free_dev; - } - - channels = kmemdup(accel_3d_channels, - sizeof(accel_3d_channels), - GFP_KERNEL); - if (!channels) { - dev_err(&pdev->dev, "failed to duplicate channels\n"); - goto error_free_dev; - } - - ret = accel_3d_parse_report(pdev, hsdev, channels, - HID_USAGE_SENSOR_ACCEL_3D, accel_state); - if (ret) { - dev_err(&pdev->dev, "failed to setup attributes\n"); - goto error_free_dev_mem; - } - - indio_dev->channels = channels; - indio_dev->num_channels = ARRAY_SIZE(accel_3d_channels); - indio_dev->dev.parent = &pdev->dev; - indio_dev->info = &accel_3d_info; - indio_dev->name = name; - indio_dev->modes = INDIO_DIRECT_MODE; - - ret = iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time, - NULL, NULL); - if (ret) { - dev_err(&pdev->dev, "failed to initialize trigger buffer\n"); - goto error_free_dev_mem; - } - accel_state->common_attributes.data_ready = false; - ret = hid_sensor_setup_trigger(indio_dev, name, - &accel_state->common_attributes); - if (ret < 0) { - dev_err(&pdev->dev, "trigger setup failed\n"); - goto error_unreg_buffer_funcs; - } - - ret = iio_device_register(indio_dev); - if (ret) { - dev_err(&pdev->dev, "device register failed\n"); - goto error_remove_trigger; - } - - accel_state->callbacks.send_event = accel_3d_proc_event; - accel_state->callbacks.capture_sample = accel_3d_capture_sample; - accel_state->callbacks.pdev = pdev; - ret = sensor_hub_register_callback(hsdev, HID_USAGE_SENSOR_ACCEL_3D, - &accel_state->callbacks); - if (ret < 0) { - dev_err(&pdev->dev, "callback reg failed\n"); - goto error_iio_unreg; - } - - return ret; - -error_iio_unreg: - iio_device_unregister(indio_dev); -error_remove_trigger: - hid_sensor_remove_trigger(indio_dev); -error_unreg_buffer_funcs: - iio_triggered_buffer_cleanup(indio_dev); -error_free_dev_mem: - kfree(indio_dev->channels); -error_free_dev: - iio_device_free(indio_dev); -error_ret: - return ret; -} - -/* Function to deinitialize the processing for usage id */ -static int __devinit hid_accel_3d_remove(struct platform_device *pdev) -{ - struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data; - struct iio_dev *indio_dev = platform_get_drvdata(pdev); - - sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_ACCEL_3D); - iio_device_unregister(indio_dev); - hid_sensor_remove_trigger(indio_dev); - iio_triggered_buffer_cleanup(indio_dev); - kfree(indio_dev->channels); - iio_device_free(indio_dev); - - return 0; -} - -static struct platform_driver hid_accel_3d_platform_driver = { - .driver = { - .name = DRIVER_NAME, - .owner = THIS_MODULE, - }, - .probe = hid_accel_3d_probe, - .remove = hid_accel_3d_remove, -}; -module_platform_driver(hid_accel_3d_platform_driver); - -MODULE_DESCRIPTION("HID Sensor Accel 3D"); -MODULE_AUTHOR("Srinivas Pandruvada "); -MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/iio/adc/Kconfig b/trunk/drivers/iio/adc/Kconfig index 492758120338..8a78b4f3ef58 100644 --- a/trunk/drivers/iio/adc/Kconfig +++ b/trunk/drivers/iio/adc/Kconfig @@ -3,11 +3,6 @@ # menu "Analog to digital converters" -config AD_SIGMA_DELTA - tristate - select IIO_BUFFER - select IIO_TRIGGERED_BUFFER - config AD7266 tristate "Analog Devices AD7265/AD7266 ADC driver" depends on SPI_MASTER @@ -18,33 +13,6 @@ config AD7266 Say yes here to build support for Analog Devices AD7265 and AD7266 ADCs. -config AD7791 - tristate "Analog Devices AD7791 ADC driver" - depends on SPI - select AD_SIGMA_DELTA - help - Say yes here to build support for Analog Devices AD7787, AD7788, AD7789, - AD7790 and AD7791 SPI analog to digital converters (ADC). If unsure, say - N (but it is safe to say "Y"). - - To compile this driver as a module, choose M here: the module will be - called ad7791. - -config AD7476 - tristate "Analog Devices AD7476 and similar 1-channel ADCs driver" - depends on SPI - select IIO_BUFFER - select IIO_TRIGGERED_BUFFER - help - Say yes here to build support for Analog Devices AD7273, AD7274, AD7276, - AD7277, AD7278, AD7475, AD7476, AD7477, AD7478, AD7466, AD7467, AD7468, - AD7495, AD7910, AD7920, AD7920 SPI analog to digital converters (ADC). - - If unsure, say N (but it's safe to say "Y"). - - To compile this driver as a module, choose M here: the - module will be called ad7476. - config AT91_ADC tristate "Atmel AT91 ADC" depends on ARCH_AT91 @@ -54,10 +22,4 @@ config AT91_ADC help Say yes here to build support for Atmel AT91 ADC. -config LP8788_ADC - bool "LP8788 ADC driver" - depends on MFD_LP8788 - help - Say yes here to build support for TI LP8788 ADC. - endmenu diff --git a/trunk/drivers/iio/adc/Makefile b/trunk/drivers/iio/adc/Makefile index 900995d5e179..52eec254c38c 100644 --- a/trunk/drivers/iio/adc/Makefile +++ b/trunk/drivers/iio/adc/Makefile @@ -2,9 +2,5 @@ # Makefile for IIO ADC drivers # -obj-$(CONFIG_AD_SIGMA_DELTA) += ad_sigma_delta.o obj-$(CONFIG_AD7266) += ad7266.o -obj-$(CONFIG_AD7476) += ad7476.o -obj-$(CONFIG_AD7791) += ad7791.o obj-$(CONFIG_AT91_ADC) += at91_adc.o -obj-$(CONFIG_LP8788_ADC) += lp8788_adc.o diff --git a/trunk/drivers/iio/adc/ad7266.c b/trunk/drivers/iio/adc/ad7266.c index b11f214779a2..5c3f1ba5a06d 100644 --- a/trunk/drivers/iio/adc/ad7266.c +++ b/trunk/drivers/iio/adc/ad7266.c @@ -99,7 +99,7 @@ static irqreturn_t ad7266_trigger_handler(int irq, void *p) if (ret == 0) { if (indio_dev->scan_timestamp) ((s64 *)st->data)[1] = pf->timestamp; - iio_push_to_buffer(buffer, (u8 *)st->data); + iio_push_to_buffer(buffer, (u8 *)st->data, pf->timestamp); } iio_trigger_notify_done(indio_dev->trig); diff --git a/trunk/drivers/iio/adc/ad7791.c b/trunk/drivers/iio/adc/ad7791.c deleted file mode 100644 index e93740843b2b..000000000000 --- a/trunk/drivers/iio/adc/ad7791.c +++ /dev/null @@ -1,460 +0,0 @@ -/* - * AD7787/AD7788/AD7789/AD7790/AD7791 SPI ADC driver - * - * Copyright 2012 Analog Devices Inc. - * Author: Lars-Peter Clausen - * - * Licensed under the GPL-2. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include - -#define AD7791_REG_COMM 0x0 /* For writes */ -#define AD7791_REG_STATUS 0x0 /* For reads */ -#define AD7791_REG_MODE 0x1 -#define AD7791_REG_FILTER 0x2 -#define AD7791_REG_DATA 0x3 - -#define AD7791_MODE_CONTINUOUS 0x00 -#define AD7791_MODE_SINGLE 0x02 -#define AD7791_MODE_POWERDOWN 0x03 - -#define AD7791_CH_AIN1P_AIN1N 0x00 -#define AD7791_CH_AIN2 0x01 -#define AD7791_CH_AIN1N_AIN1N 0x02 -#define AD7791_CH_AVDD_MONITOR 0x03 - -#define AD7791_FILTER_CLK_DIV_1 (0x0 << 4) -#define AD7791_FILTER_CLK_DIV_2 (0x1 << 4) -#define AD7791_FILTER_CLK_DIV_4 (0x2 << 4) -#define AD7791_FILTER_CLK_DIV_8 (0x3 << 4) -#define AD7791_FILTER_CLK_MASK (0x3 << 4) -#define AD7791_FILTER_RATE_120 0x0 -#define AD7791_FILTER_RATE_100 0x1 -#define AD7791_FILTER_RATE_33_3 0x2 -#define AD7791_FILTER_RATE_20 0x3 -#define AD7791_FILTER_RATE_16_6 0x4 -#define AD7791_FILTER_RATE_16_7 0x5 -#define AD7791_FILTER_RATE_13_3 0x6 -#define AD7791_FILTER_RATE_9_5 0x7 -#define AD7791_FILTER_RATE_MASK 0x7 - -#define AD7791_MODE_BUFFER BIT(1) -#define AD7791_MODE_UNIPOLAR BIT(2) -#define AD7791_MODE_BURNOUT BIT(3) -#define AD7791_MODE_SEL_MASK (0x3 << 6) -#define AD7791_MODE_SEL(x) ((x) << 6) - -#define DECLARE_AD7787_CHANNELS(name, bits, storagebits) \ -const struct iio_chan_spec name[] = { \ - AD_SD_DIFF_CHANNEL(0, 0, 0, AD7791_CH_AIN1P_AIN1N, \ - (bits), (storagebits), 0), \ - AD_SD_CHANNEL(1, 1, AD7791_CH_AIN2, (bits), (storagebits), 0), \ - AD_SD_SHORTED_CHANNEL(2, 0, AD7791_CH_AIN1N_AIN1N, \ - (bits), (storagebits), 0), \ - AD_SD_SUPPLY_CHANNEL(3, 2, AD7791_CH_AVDD_MONITOR, \ - (bits), (storagebits), 0), \ - IIO_CHAN_SOFT_TIMESTAMP(4), \ -} - -#define DECLARE_AD7791_CHANNELS(name, bits, storagebits) \ -const struct iio_chan_spec name[] = { \ - AD_SD_DIFF_CHANNEL(0, 0, 0, AD7791_CH_AIN1P_AIN1N, \ - (bits), (storagebits), 0), \ - AD_SD_SHORTED_CHANNEL(1, 0, AD7791_CH_AIN1N_AIN1N, \ - (bits), (storagebits), 0), \ - AD_SD_SUPPLY_CHANNEL(2, 1, AD7791_CH_AVDD_MONITOR, \ - (bits), (storagebits), 0), \ - IIO_CHAN_SOFT_TIMESTAMP(3), \ -} - -static DECLARE_AD7787_CHANNELS(ad7787_channels, 24, 32); -static DECLARE_AD7791_CHANNELS(ad7790_channels, 16, 16); -static DECLARE_AD7791_CHANNELS(ad7791_channels, 24, 32); - -enum { - AD7787, - AD7788, - AD7789, - AD7790, - AD7791, -}; - -enum ad7791_chip_info_flags { - AD7791_FLAG_HAS_FILTER = (1 << 0), - AD7791_FLAG_HAS_BUFFER = (1 << 1), - AD7791_FLAG_HAS_UNIPOLAR = (1 << 2), - AD7791_FLAG_HAS_BURNOUT = (1 << 3), -}; - -struct ad7791_chip_info { - const struct iio_chan_spec *channels; - unsigned int num_channels; - enum ad7791_chip_info_flags flags; -}; - -static const struct ad7791_chip_info ad7791_chip_infos[] = { - [AD7787] = { - .channels = ad7787_channels, - .num_channels = ARRAY_SIZE(ad7787_channels), - .flags = AD7791_FLAG_HAS_FILTER | AD7791_FLAG_HAS_BUFFER | - AD7791_FLAG_HAS_UNIPOLAR | AD7791_FLAG_HAS_BURNOUT, - }, - [AD7788] = { - .channels = ad7790_channels, - .num_channels = ARRAY_SIZE(ad7790_channels), - .flags = AD7791_FLAG_HAS_UNIPOLAR, - }, - [AD7789] = { - .channels = ad7791_channels, - .num_channels = ARRAY_SIZE(ad7791_channels), - .flags = AD7791_FLAG_HAS_UNIPOLAR, - }, - [AD7790] = { - .channels = ad7790_channels, - .num_channels = ARRAY_SIZE(ad7790_channels), - .flags = AD7791_FLAG_HAS_FILTER | AD7791_FLAG_HAS_BUFFER | - AD7791_FLAG_HAS_BURNOUT, - }, - [AD7791] = { - .channels = ad7791_channels, - .num_channels = ARRAY_SIZE(ad7791_channels), - .flags = AD7791_FLAG_HAS_FILTER | AD7791_FLAG_HAS_BUFFER | - AD7791_FLAG_HAS_UNIPOLAR | AD7791_FLAG_HAS_BURNOUT, - }, -}; - -struct ad7791_state { - struct ad_sigma_delta sd; - uint8_t mode; - uint8_t filter; - - struct regulator *reg; - const struct ad7791_chip_info *info; -}; - -static struct ad7791_state *ad_sigma_delta_to_ad7791(struct ad_sigma_delta *sd) -{ - return container_of(sd, struct ad7791_state, sd); -} - -static int ad7791_set_channel(struct ad_sigma_delta *sd, unsigned int channel) -{ - ad_sd_set_comm(sd, channel); - - return 0; -} - -static int ad7791_set_mode(struct ad_sigma_delta *sd, - enum ad_sigma_delta_mode mode) -{ - struct ad7791_state *st = ad_sigma_delta_to_ad7791(sd); - - switch (mode) { - case AD_SD_MODE_CONTINUOUS: - mode = AD7791_MODE_CONTINUOUS; - break; - case AD_SD_MODE_SINGLE: - mode = AD7791_MODE_SINGLE; - break; - case AD_SD_MODE_IDLE: - case AD_SD_MODE_POWERDOWN: - mode = AD7791_MODE_POWERDOWN; - break; - } - - st->mode &= ~AD7791_MODE_SEL_MASK; - st->mode |= AD7791_MODE_SEL(mode); - - return ad_sd_write_reg(sd, AD7791_REG_MODE, sizeof(st->mode), st->mode); -} - -static const struct ad_sigma_delta_info ad7791_sigma_delta_info = { - .set_channel = ad7791_set_channel, - .set_mode = ad7791_set_mode, - .has_registers = true, - .addr_shift = 4, - .read_mask = BIT(3), -}; - -static int ad7791_read_raw(struct iio_dev *indio_dev, - const struct iio_chan_spec *chan, int *val, int *val2, long info) -{ - struct ad7791_state *st = iio_priv(indio_dev); - bool unipolar = !!(st->mode & AD7791_MODE_UNIPOLAR); - unsigned long long scale_pv; - - switch (info) { - case IIO_CHAN_INFO_RAW: - return ad_sigma_delta_single_conversion(indio_dev, chan, val); - case IIO_CHAN_INFO_OFFSET: - /** - * Unipolar: 0 to VREF - * Bipolar -VREF to VREF - **/ - if (unipolar) - *val = 0; - else - *val = -(1 << (chan->scan_type.realbits - 1)); - return IIO_VAL_INT; - case IIO_CHAN_INFO_SCALE: - /* The monitor channel uses an internal reference. */ - if (chan->address == AD7791_CH_AVDD_MONITOR) { - scale_pv = 5850000000000ULL; - } else { - int voltage_uv; - - voltage_uv = regulator_get_voltage(st->reg); - if (voltage_uv < 0) - return voltage_uv; - scale_pv = (unsigned long long)voltage_uv * 1000000; - } - if (unipolar) - scale_pv >>= chan->scan_type.realbits; - else - scale_pv >>= chan->scan_type.realbits - 1; - *val2 = do_div(scale_pv, 1000000000); - *val = scale_pv; - - return IIO_VAL_INT_PLUS_NANO; - } - - return -EINVAL; -} - -static const char * const ad7791_sample_freq_avail[] = { - [AD7791_FILTER_RATE_120] = "120", - [AD7791_FILTER_RATE_100] = "100", - [AD7791_FILTER_RATE_33_3] = "33.3", - [AD7791_FILTER_RATE_20] = "20", - [AD7791_FILTER_RATE_16_6] = "16.6", - [AD7791_FILTER_RATE_16_7] = "16.7", - [AD7791_FILTER_RATE_13_3] = "13.3", - [AD7791_FILTER_RATE_9_5] = "9.5", -}; - -static ssize_t ad7791_read_frequency(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct ad7791_state *st = iio_priv(indio_dev); - unsigned int rate = st->filter & AD7791_FILTER_RATE_MASK; - - return sprintf(buf, "%s\n", ad7791_sample_freq_avail[rate]); -} - -static ssize_t ad7791_write_frequency(struct device *dev, - struct device_attribute *attr, const char *buf, size_t len) -{ - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct ad7791_state *st = iio_priv(indio_dev); - int i, ret; - - mutex_lock(&indio_dev->mlock); - if (iio_buffer_enabled(indio_dev)) { - mutex_unlock(&indio_dev->mlock); - return -EBUSY; - } - mutex_unlock(&indio_dev->mlock); - - ret = -EINVAL; - - for (i = 0; i < ARRAY_SIZE(ad7791_sample_freq_avail); i++) { - if (sysfs_streq(ad7791_sample_freq_avail[i], buf)) { - - mutex_lock(&indio_dev->mlock); - st->filter &= ~AD7791_FILTER_RATE_MASK; - st->filter |= i; - ad_sd_write_reg(&st->sd, AD7791_REG_FILTER, - sizeof(st->filter), st->filter); - mutex_unlock(&indio_dev->mlock); - ret = 0; - break; - } - } - - return ret ? ret : len; -} - -static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO, - ad7791_read_frequency, - ad7791_write_frequency); - -static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("120 100 33.3 20 16.7 16.6 13.3 9.5"); - -static struct attribute *ad7791_attributes[] = { - &iio_dev_attr_sampling_frequency.dev_attr.attr, - &iio_const_attr_sampling_frequency_available.dev_attr.attr, - NULL -}; - -static const struct attribute_group ad7791_attribute_group = { - .attrs = ad7791_attributes, -}; - -static const struct iio_info ad7791_info = { - .read_raw = &ad7791_read_raw, - .attrs = &ad7791_attribute_group, - .validate_trigger = ad_sd_validate_trigger, - .driver_module = THIS_MODULE, -}; - -static const struct iio_info ad7791_no_filter_info = { - .read_raw = &ad7791_read_raw, - .validate_trigger = ad_sd_validate_trigger, - .driver_module = THIS_MODULE, -}; - -static int __devinit ad7791_setup(struct ad7791_state *st, - struct ad7791_platform_data *pdata) -{ - /* Set to poweron-reset default values */ - st->mode = AD7791_MODE_BUFFER; - st->filter = AD7791_FILTER_RATE_16_6; - - if (!pdata) - return 0; - - if ((st->info->flags & AD7791_FLAG_HAS_BUFFER) && !pdata->buffered) - st->mode &= ~AD7791_MODE_BUFFER; - - if ((st->info->flags & AD7791_FLAG_HAS_BURNOUT) && - pdata->burnout_current) - st->mode |= AD7791_MODE_BURNOUT; - - if ((st->info->flags & AD7791_FLAG_HAS_UNIPOLAR) && pdata->unipolar) - st->mode |= AD7791_MODE_UNIPOLAR; - - return ad_sd_write_reg(&st->sd, AD7791_REG_MODE, sizeof(st->mode), - st->mode); -} - -static int __devinit ad7791_probe(struct spi_device *spi) -{ - struct ad7791_platform_data *pdata = spi->dev.platform_data; - struct iio_dev *indio_dev; - struct ad7791_state *st; - int ret; - - if (!spi->irq) { - dev_err(&spi->dev, "Missing IRQ.\n"); - return -ENXIO; - } - - indio_dev = iio_device_alloc(sizeof(*st)); - if (!indio_dev) - return -ENOMEM; - - st = iio_priv(indio_dev); - - st->reg = regulator_get(&spi->dev, "refin"); - if (IS_ERR(st->reg)) { - ret = PTR_ERR(st->reg); - goto err_iio_free; - } - - ret = regulator_enable(st->reg); - if (ret) - goto error_put_reg; - - st->info = &ad7791_chip_infos[spi_get_device_id(spi)->driver_data]; - ad_sd_init(&st->sd, indio_dev, spi, &ad7791_sigma_delta_info); - - spi_set_drvdata(spi, indio_dev); - - indio_dev->dev.parent = &spi->dev; - indio_dev->name = spi_get_device_id(spi)->name; - indio_dev->modes = INDIO_DIRECT_MODE; - indio_dev->channels = st->info->channels; - indio_dev->num_channels = st->info->num_channels; - if (st->info->flags & AD7791_FLAG_HAS_FILTER) - indio_dev->info = &ad7791_info; - else - indio_dev->info = &ad7791_no_filter_info; - - ret = ad_sd_setup_buffer_and_trigger(indio_dev); - if (ret) - goto error_disable_reg; - - ret = ad7791_setup(st, pdata); - if (ret) - goto error_remove_trigger; - - ret = iio_device_register(indio_dev); - if (ret) - goto error_remove_trigger; - - return 0; - -error_remove_trigger: - ad_sd_cleanup_buffer_and_trigger(indio_dev); -error_disable_reg: - regulator_disable(st->reg); -error_put_reg: - regulator_put(st->reg); -err_iio_free: - iio_device_free(indio_dev); - - return ret; -} - -static int __devexit ad7791_remove(struct spi_device *spi) -{ - struct iio_dev *indio_dev = spi_get_drvdata(spi); - struct ad7791_state *st = iio_priv(indio_dev); - - iio_device_unregister(indio_dev); - ad_sd_cleanup_buffer_and_trigger(indio_dev); - - regulator_disable(st->reg); - regulator_put(st->reg); - - iio_device_free(indio_dev); - - return 0; -} - -static const struct spi_device_id ad7791_spi_ids[] = { - { "ad7787", AD7787 }, - { "ad7788", AD7788 }, - { "ad7789", AD7789 }, - { "ad7790", AD7790 }, - { "ad7791", AD7791 }, - {} -}; -MODULE_DEVICE_TABLE(spi, ad7791_spi_ids); - -static struct spi_driver ad7791_driver = { - .driver = { - .name = "ad7791", - .owner = THIS_MODULE, - }, - .probe = ad7791_probe, - .remove = __devexit_p(ad7791_remove), - .id_table = ad7791_spi_ids, -}; -module_spi_driver(ad7791_driver); - -MODULE_AUTHOR("Lars-Peter Clausen "); -MODULE_DESCRIPTION("Analog Device AD7787/AD7788/AD7789/AD7790/AD7791 ADC driver"); -MODULE_LICENSE("GPL v2"); diff --git a/trunk/drivers/iio/adc/ad_sigma_delta.c b/trunk/drivers/iio/adc/ad_sigma_delta.c deleted file mode 100644 index 67baa1363d7a..000000000000 --- a/trunk/drivers/iio/adc/ad_sigma_delta.c +++ /dev/null @@ -1,558 +0,0 @@ -/* - * Support code for Analog Devices Sigma-Delta ADCs - * - * Copyright 2012 Analog Devices Inc. - * Author: Lars-Peter Clausen - * - * Licensed under the GPL-2. - */ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include - - -#define AD_SD_COMM_CHAN_MASK 0x3 - -#define AD_SD_REG_COMM 0x00 -#define AD_SD_REG_DATA 0x03 - -/** - * ad_sd_set_comm() - Set communications register - * - * @sigma_delta: The sigma delta device - * @comm: New value for the communications register - */ -void ad_sd_set_comm(struct ad_sigma_delta *sigma_delta, uint8_t comm) -{ - /* Some variants use the lower two bits of the communications register - * to select the channel */ - sigma_delta->comm = comm & AD_SD_COMM_CHAN_MASK; -} -EXPORT_SYMBOL_GPL(ad_sd_set_comm); - -/** - * ad_sd_write_reg() - Write a register - * - * @sigma_delta: The sigma delta device - * @reg: Address of the register - * @size: Size of the register (0-3) - * @val: Value to write to the register - * - * Returns 0 on success, an error code otherwise. - **/ -int ad_sd_write_reg(struct ad_sigma_delta *sigma_delta, unsigned int reg, - unsigned int size, unsigned int val) -{ - uint8_t *data = sigma_delta->data; - struct spi_transfer t = { - .tx_buf = data, - .len = size + 1, - .cs_change = sigma_delta->bus_locked, - }; - struct spi_message m; - int ret; - - data[0] = (reg << sigma_delta->info->addr_shift) | sigma_delta->comm; - - switch (size) { - case 3: - data[1] = val >> 16; - data[2] = val >> 8; - data[3] = val; - break; - case 2: - put_unaligned_be16(val, &data[1]); - break; - case 1: - data[1] = val; - break; - case 0: - break; - default: - return -EINVAL; - } - - spi_message_init(&m); - spi_message_add_tail(&t, &m); - - if (sigma_delta->bus_locked) - ret = spi_sync_locked(sigma_delta->spi, &m); - else - ret = spi_sync(sigma_delta->spi, &m); - - return ret; -} -EXPORT_SYMBOL_GPL(ad_sd_write_reg); - -static int ad_sd_read_reg_raw(struct ad_sigma_delta *sigma_delta, - unsigned int reg, unsigned int size, uint8_t *val) -{ - uint8_t *data = sigma_delta->data; - int ret; - struct spi_transfer t[] = { - { - .tx_buf = data, - .len = 1, - }, { - .rx_buf = val, - .len = size, - .cs_change = sigma_delta->bus_locked, - }, - }; - struct spi_message m; - - spi_message_init(&m); - - if (sigma_delta->info->has_registers) { - data[0] = reg << sigma_delta->info->addr_shift; - data[0] |= sigma_delta->info->read_mask; - spi_message_add_tail(&t[0], &m); - } - spi_message_add_tail(&t[1], &m); - - if (sigma_delta->bus_locked) - ret = spi_sync_locked(sigma_delta->spi, &m); - else - ret = spi_sync(sigma_delta->spi, &m); - - return ret; -} - -/** - * ad_sd_read_reg() - Read a register - * - * @sigma_delta: The sigma delta device - * @reg: Address of the register - * @size: Size of the register (1-4) - * @val: Read value - * - * Returns 0 on success, an error code otherwise. - **/ -int ad_sd_read_reg(struct ad_sigma_delta *sigma_delta, - unsigned int reg, unsigned int size, unsigned int *val) -{ - int ret; - - ret = ad_sd_read_reg_raw(sigma_delta, reg, size, sigma_delta->data); - if (ret < 0) - goto out; - - switch (size) { - case 4: - *val = get_unaligned_be32(sigma_delta->data); - break; - case 3: - *val = (sigma_delta->data[0] << 16) | - (sigma_delta->data[1] << 8) | - sigma_delta->data[2]; - break; - case 2: - *val = get_unaligned_be16(sigma_delta->data); - break; - case 1: - *val = sigma_delta->data[0]; - break; - default: - ret = -EINVAL; - break; - } - -out: - return ret; -} -EXPORT_SYMBOL_GPL(ad_sd_read_reg); - -static int ad_sd_calibrate(struct ad_sigma_delta *sigma_delta, - unsigned int mode, unsigned int channel) -{ - int ret; - - ret = ad_sigma_delta_set_channel(sigma_delta, channel); - if (ret) - return ret; - - spi_bus_lock(sigma_delta->spi->master); - sigma_delta->bus_locked = true; - INIT_COMPLETION(sigma_delta->completion); - - ret = ad_sigma_delta_set_mode(sigma_delta, mode); - if (ret < 0) - goto out; - - sigma_delta->irq_dis = false; - enable_irq(sigma_delta->spi->irq); - ret = wait_for_completion_timeout(&sigma_delta->completion, 2*HZ); - if (ret == 0) { - sigma_delta->irq_dis = true; - disable_irq_nosync(sigma_delta->spi->irq); - ret = -EIO; - } else { - ret = 0; - } -out: - sigma_delta->bus_locked = false; - spi_bus_unlock(sigma_delta->spi->master); - ad_sigma_delta_set_mode(sigma_delta, AD_SD_MODE_IDLE); - - return ret; -} - -/** - * ad_sd_calibrate_all() - Performs channel calibration - * @sigma_delta: The sigma delta device - * @cb: Array of channels and calibration type to perform - * @n: Number of items in cb - * - * Returns 0 on success, an error code otherwise. - **/ -int ad_sd_calibrate_all(struct ad_sigma_delta *sigma_delta, - const struct ad_sd_calib_data *cb, unsigned int n) -{ - unsigned int i; - int ret; - - for (i = 0; i < n; i++) { - ret = ad_sd_calibrate(sigma_delta, cb[i].mode, cb[i].channel); - if (ret) - return ret; - } - - return 0; -} -EXPORT_SYMBOL_GPL(ad_sd_calibrate_all); - -/** - * ad_sigma_delta_single_conversion() - Performs a single data conversion - * @indio_dev: The IIO device - * @chan: The conversion is done for this channel - * @val: Pointer to the location where to store the read value - * - * Returns: 0 on success, an error value otherwise. - */ -int ad_sigma_delta_single_conversion(struct iio_dev *indio_dev, - const struct iio_chan_spec *chan, int *val) -{ - struct ad_sigma_delta *sigma_delta = iio_device_get_drvdata(indio_dev); - unsigned int sample, raw_sample; - int ret = 0; - - if (iio_buffer_enabled(indio_dev)) - return -EBUSY; - - mutex_lock(&indio_dev->mlock); - ad_sigma_delta_set_channel(sigma_delta, chan->address); - - spi_bus_lock(sigma_delta->spi->master); - sigma_delta->bus_locked = true; - INIT_COMPLETION(sigma_delta->completion); - - ad_sigma_delta_set_mode(sigma_delta, AD_SD_MODE_SINGLE); - - sigma_delta->irq_dis = false; - enable_irq(sigma_delta->spi->irq); - ret = wait_for_completion_interruptible_timeout( - &sigma_delta->completion, HZ); - - sigma_delta->bus_locked = false; - spi_bus_unlock(sigma_delta->spi->master); - - if (ret == 0) - ret = -EIO; - if (ret < 0) - goto out; - - ret = ad_sd_read_reg(sigma_delta, AD_SD_REG_DATA, - DIV_ROUND_UP(chan->scan_type.realbits + chan->scan_type.shift, 8), - &raw_sample); - -out: - if (!sigma_delta->irq_dis) { - disable_irq_nosync(sigma_delta->spi->irq); - sigma_delta->irq_dis = true; - } - - ad_sigma_delta_set_mode(sigma_delta, AD_SD_MODE_IDLE); - mutex_unlock(&indio_dev->mlock); - - if (ret) - return ret; - - sample = raw_sample >> chan->scan_type.shift; - sample &= (1 << chan->scan_type.realbits) - 1; - *val = sample; - - ret = ad_sigma_delta_postprocess_sample(sigma_delta, raw_sample); - if (ret) - return ret; - - return IIO_VAL_INT; -} -EXPORT_SYMBOL_GPL(ad_sigma_delta_single_conversion); - -static int ad_sd_buffer_postenable(struct iio_dev *indio_dev) -{ - struct ad_sigma_delta *sigma_delta = iio_device_get_drvdata(indio_dev); - unsigned int channel; - int ret; - - ret = iio_triggered_buffer_postenable(indio_dev); - if (ret < 0) - return ret; - - channel = find_first_bit(indio_dev->active_scan_mask, - indio_dev->masklength); - ret = ad_sigma_delta_set_channel(sigma_delta, - indio_dev->channels[channel].address); - if (ret) - goto err_predisable; - - spi_bus_lock(sigma_delta->spi->master); - sigma_delta->bus_locked = true; - ret = ad_sigma_delta_set_mode(sigma_delta, AD_SD_MODE_CONTINUOUS); - if (ret) - goto err_unlock; - - sigma_delta->irq_dis = false; - enable_irq(sigma_delta->spi->irq); - - return 0; - -err_unlock: - spi_bus_unlock(sigma_delta->spi->master); -err_predisable: - - return ret; -} - -static int ad_sd_buffer_postdisable(struct iio_dev *indio_dev) -{ - struct ad_sigma_delta *sigma_delta = iio_device_get_drvdata(indio_dev); - - INIT_COMPLETION(sigma_delta->completion); - wait_for_completion_timeout(&sigma_delta->completion, HZ); - - if (!sigma_delta->irq_dis) { - disable_irq_nosync(sigma_delta->spi->irq); - sigma_delta->irq_dis = true; - } - - ad_sigma_delta_set_mode(sigma_delta, AD_SD_MODE_IDLE); - - sigma_delta->bus_locked = false; - return spi_bus_unlock(sigma_delta->spi->master); -} - -static irqreturn_t ad_sd_trigger_handler(int irq, void *p) -{ - struct iio_poll_func *pf = p; - struct iio_dev *indio_dev = pf->indio_dev; - struct ad_sigma_delta *sigma_delta = iio_device_get_drvdata(indio_dev); - unsigned int reg_size; - uint8_t data[16]; - int ret; - - memset(data, 0x00, 16); - - /* Guaranteed to be aligned with 8 byte boundary */ - if (indio_dev->scan_timestamp) - ((s64 *)data)[1] = pf->timestamp; - - reg_size = indio_dev->channels[0].scan_type.realbits + - indio_dev->channels[0].scan_type.shift; - reg_size = DIV_ROUND_UP(reg_size, 8); - - switch (reg_size) { - case 4: - case 2: - case 1: - ret = ad_sd_read_reg_raw(sigma_delta, AD_SD_REG_DATA, - reg_size, &data[0]); - break; - case 3: - /* We store 24 bit samples in a 32 bit word. Keep the upper - * byte set to zero. */ - ret = ad_sd_read_reg_raw(sigma_delta, AD_SD_REG_DATA, - reg_size, &data[1]); - break; - } - - iio_push_to_buffer(indio_dev->buffer, (uint8_t *)data); - - iio_trigger_notify_done(indio_dev->trig); - sigma_delta->irq_dis = false; - enable_irq(sigma_delta->spi->irq); - - return IRQ_HANDLED; -} - -static const struct iio_buffer_setup_ops ad_sd_buffer_setup_ops = { - .preenable = &iio_sw_buffer_preenable, - .postenable = &ad_sd_buffer_postenable, - .predisable = &iio_triggered_buffer_predisable, - .postdisable = &ad_sd_buffer_postdisable, - .validate_scan_mask = &iio_validate_scan_mask_onehot, -}; - -static irqreturn_t ad_sd_data_rdy_trig_poll(int irq, void *private) -{ - struct ad_sigma_delta *sigma_delta = private; - - complete(&sigma_delta->completion); - disable_irq_nosync(irq); - sigma_delta->irq_dis = true; - iio_trigger_poll(sigma_delta->trig, iio_get_time_ns()); - - return IRQ_HANDLED; -} - -/** - * ad_sd_validate_trigger() - validate_trigger callback for ad_sigma_delta devices - * @indio_dev: The IIO device - * @trig: The new trigger - * - * Returns: 0 if the 'trig' matches the trigger registered by the ad_sigma_delta - * device, -EINVAL otherwise. - */ -int ad_sd_validate_trigger(struct iio_dev *indio_dev, struct iio_trigger *trig) -{ - struct ad_sigma_delta *sigma_delta = iio_device_get_drvdata(indio_dev); - - if (sigma_delta->trig != trig) - return -EINVAL; - - return 0; -} -EXPORT_SYMBOL_GPL(ad_sd_validate_trigger); - -static const struct iio_trigger_ops ad_sd_trigger_ops = { - .owner = THIS_MODULE, -}; - -static int ad_sd_probe_trigger(struct iio_dev *indio_dev) -{ - struct ad_sigma_delta *sigma_delta = iio_device_get_drvdata(indio_dev); - int ret; - - sigma_delta->trig = iio_trigger_alloc("%s-dev%d", indio_dev->name, - indio_dev->id); - if (sigma_delta->trig == NULL) { - ret = -ENOMEM; - goto error_ret; - } - sigma_delta->trig->ops = &ad_sd_trigger_ops; - init_completion(&sigma_delta->completion); - - ret = request_irq(sigma_delta->spi->irq, - ad_sd_data_rdy_trig_poll, - IRQF_TRIGGER_LOW, - indio_dev->name, - sigma_delta); - if (ret) - goto error_free_trig; - - if (!sigma_delta->irq_dis) { - sigma_delta->irq_dis = true; - disable_irq_nosync(sigma_delta->spi->irq); - } - sigma_delta->trig->dev.parent = &sigma_delta->spi->dev; - sigma_delta->trig->private_data = sigma_delta; - - ret = iio_trigger_register(sigma_delta->trig); - if (ret) - goto error_free_irq; - - /* select default trigger */ - indio_dev->trig = sigma_delta->trig; - - return 0; - -error_free_irq: - free_irq(sigma_delta->spi->irq, sigma_delta); -error_free_trig: - iio_trigger_free(sigma_delta->trig); -error_ret: - return ret; -} - -static void ad_sd_remove_trigger(struct iio_dev *indio_dev) -{ - struct ad_sigma_delta *sigma_delta = iio_device_get_drvdata(indio_dev); - - iio_trigger_unregister(sigma_delta->trig); - free_irq(sigma_delta->spi->irq, sigma_delta); - iio_trigger_free(sigma_delta->trig); -} - -/** - * ad_sd_setup_buffer_and_trigger() - - * @indio_dev: The IIO device - */ -int ad_sd_setup_buffer_and_trigger(struct iio_dev *indio_dev) -{ - int ret; - - ret = iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time, - &ad_sd_trigger_handler, &ad_sd_buffer_setup_ops); - if (ret) - return ret; - - ret = ad_sd_probe_trigger(indio_dev); - if (ret) { - iio_triggered_buffer_cleanup(indio_dev); - return ret; - } - - return 0; -} -EXPORT_SYMBOL_GPL(ad_sd_setup_buffer_and_trigger); - -/** - * ad_sd_cleanup_buffer_and_trigger() - - * @indio_dev: The IIO device - */ -void ad_sd_cleanup_buffer_and_trigger(struct iio_dev *indio_dev) -{ - ad_sd_remove_trigger(indio_dev); - iio_triggered_buffer_cleanup(indio_dev); -} -EXPORT_SYMBOL_GPL(ad_sd_cleanup_buffer_and_trigger); - -/** - * ad_sd_init() - Initializes a ad_sigma_delta struct - * @sigma_delta: The ad_sigma_delta device - * @indio_dev: The IIO device which the Sigma Delta device is used for - * @spi: The SPI device for the ad_sigma_delta device - * @info: Device specific callbacks and options - * - * This function needs to be called before any other operations are performed on - * the ad_sigma_delta struct. - */ -int ad_sd_init(struct ad_sigma_delta *sigma_delta, struct iio_dev *indio_dev, - struct spi_device *spi, const struct ad_sigma_delta_info *info) -{ - sigma_delta->spi = spi; - sigma_delta->info = info; - iio_device_set_drvdata(indio_dev, sigma_delta); - - return 0; -} -EXPORT_SYMBOL_GPL(ad_sd_init); - -MODULE_AUTHOR("Lars-Peter Clausen "); -MODULE_DESCRIPTION("Analog Devices Sigma-Delta ADCs"); -MODULE_LICENSE("GPL v2"); diff --git a/trunk/drivers/iio/adc/at91_adc.c b/trunk/drivers/iio/adc/at91_adc.c index 3ed94bf80596..f61780a02374 100644 --- a/trunk/drivers/iio/adc/at91_adc.c +++ b/trunk/drivers/iio/adc/at91_adc.c @@ -82,7 +82,7 @@ static irqreturn_t at91_adc_trigger_handler(int irq, void *p) *timestamp = pf->timestamp; } - buffer->access->store_to(buffer, (u8 *)st->buffer); + buffer->access->store_to(buffer, (u8 *)st->buffer, pf->timestamp); iio_trigger_notify_done(idev->trig); st->irq_enabled = true; @@ -545,6 +545,13 @@ static int __devinit at91_adc_probe(struct platform_device *pdev) goto error_free_device; } + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(&pdev->dev, "No resource defined\n"); + ret = -ENXIO; + goto error_ret; + } + platform_set_drvdata(pdev, idev); idev->dev.parent = &pdev->dev; @@ -559,12 +566,18 @@ static int __devinit at91_adc_probe(struct platform_device *pdev) goto error_free_device; } - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!request_mem_region(res->start, resource_size(res), + "AT91 adc registers")) { + dev_err(&pdev->dev, "Resources are unavailable.\n"); + ret = -EBUSY; + goto error_free_device; + } - st->reg_base = devm_request_and_ioremap(&pdev->dev, res); + st->reg_base = ioremap(res->start, resource_size(res)); if (!st->reg_base) { + dev_err(&pdev->dev, "Failed to map registers.\n"); ret = -ENOMEM; - goto error_free_device; + goto error_release_mem; } /* @@ -579,35 +592,45 @@ static int __devinit at91_adc_probe(struct platform_device *pdev) idev); if (ret) { dev_err(&pdev->dev, "Failed to allocate IRQ.\n"); - goto error_free_device; + goto error_unmap_reg; } - st->clk = devm_clk_get(&pdev->dev, "adc_clk"); + st->clk = clk_get(&pdev->dev, "adc_clk"); if (IS_ERR(st->clk)) { dev_err(&pdev->dev, "Failed to get the clock.\n"); ret = PTR_ERR(st->clk); goto error_free_irq; } - ret = clk_prepare_enable(st->clk); + ret = clk_prepare(st->clk); if (ret) { - dev_err(&pdev->dev, - "Could not prepare or enable the clock.\n"); - goto error_free_irq; + dev_err(&pdev->dev, "Could not prepare the clock.\n"); + goto error_free_clk; } - st->adc_clk = devm_clk_get(&pdev->dev, "adc_op_clk"); + ret = clk_enable(st->clk); + if (ret) { + dev_err(&pdev->dev, "Could not enable the clock.\n"); + goto error_unprepare_clk; + } + + st->adc_clk = clk_get(&pdev->dev, "adc_op_clk"); if (IS_ERR(st->adc_clk)) { dev_err(&pdev->dev, "Failed to get the ADC clock.\n"); - ret = PTR_ERR(st->adc_clk); + ret = PTR_ERR(st->clk); goto error_disable_clk; } - ret = clk_prepare_enable(st->adc_clk); + ret = clk_prepare(st->adc_clk); if (ret) { - dev_err(&pdev->dev, - "Could not prepare or enable the ADC clock.\n"); - goto error_disable_clk; + dev_err(&pdev->dev, "Could not prepare the ADC clock.\n"); + goto error_free_adc_clk; + } + + ret = clk_enable(st->adc_clk); + if (ret) { + dev_err(&pdev->dev, "Could not enable the ADC clock.\n"); + goto error_unprepare_adc_clk; } /* @@ -671,11 +694,23 @@ static int __devinit at91_adc_probe(struct platform_device *pdev) error_unregister_buffer: at91_adc_buffer_remove(idev); error_disable_adc_clk: - clk_disable_unprepare(st->adc_clk); + clk_disable(st->adc_clk); +error_unprepare_adc_clk: + clk_unprepare(st->adc_clk); +error_free_adc_clk: + clk_put(st->adc_clk); error_disable_clk: - clk_disable_unprepare(st->clk); + clk_disable(st->clk); +error_unprepare_clk: + clk_unprepare(st->clk); +error_free_clk: + clk_put(st->clk); error_free_irq: free_irq(st->irq, idev); +error_unmap_reg: + iounmap(st->reg_base); +error_release_mem: + release_mem_region(res->start, resource_size(res)); error_free_device: iio_device_free(idev); error_ret: @@ -685,14 +720,20 @@ static int __devinit at91_adc_probe(struct platform_device *pdev) static int __devexit at91_adc_remove(struct platform_device *pdev) { struct iio_dev *idev = platform_get_drvdata(pdev); + struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); struct at91_adc_state *st = iio_priv(idev); iio_device_unregister(idev); at91_adc_trigger_remove(idev); at91_adc_buffer_remove(idev); clk_disable_unprepare(st->adc_clk); - clk_disable_unprepare(st->clk); + clk_put(st->adc_clk); + clk_disable(st->clk); + clk_unprepare(st->clk); + clk_put(st->clk); free_irq(st->irq, idev); + iounmap(st->reg_base); + release_mem_region(res->start, resource_size(res)); iio_device_free(idev); return 0; diff --git a/trunk/drivers/iio/adc/lp8788_adc.c b/trunk/drivers/iio/adc/lp8788_adc.c deleted file mode 100644 index a93aaf0bb841..000000000000 --- a/trunk/drivers/iio/adc/lp8788_adc.c +++ /dev/null @@ -1,264 +0,0 @@ -/* - * TI LP8788 MFD - ADC driver - * - * Copyright 2012 Texas Instruments - * - * Author: Milo(Woogyom) Kim - * - * 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 -#include -#include -#include -#include -#include -#include -#include -#include - -/* register address */ -#define LP8788_ADC_CONF 0x60 -#define LP8788_ADC_RAW 0x61 -#define LP8788_ADC_DONE 0x63 - -#define ADC_CONV_START 1 - -struct lp8788_adc { - struct lp8788 *lp; - struct iio_map *map; - struct mutex lock; -}; - -static const int lp8788_scale[LPADC_MAX] = { - [LPADC_VBATT_5P5] = 1343101, - [LPADC_VIN_CHG] = 3052503, - [LPADC_IBATT] = 610500, - [LPADC_IC_TEMP] = 61050, - [LPADC_VBATT_6P0] = 1465201, - [LPADC_VBATT_5P0] = 1221001, - [LPADC_ADC1] = 610500, - [LPADC_ADC2] = 610500, - [LPADC_VDD] = 1025641, - [LPADC_VCOIN] = 757020, - [LPADC_ADC3] = 610500, - [LPADC_ADC4] = 610500, -}; - -static int lp8788_get_adc_result(struct lp8788_adc *adc, enum lp8788_adc_id id, - int *val) -{ - unsigned int msb; - unsigned int lsb; - unsigned int result; - u8 data; - u8 rawdata[2]; - int size = ARRAY_SIZE(rawdata); - int retry = 5; - int ret; - - data = (id << 1) | ADC_CONV_START; - ret = lp8788_write_byte(adc->lp, LP8788_ADC_CONF, data); - if (ret) - goto err_io; - - /* retry until adc conversion is done */ - data = 0; - while (retry--) { - usleep_range(100, 200); - - ret = lp8788_read_byte(adc->lp, LP8788_ADC_DONE, &data); - if (ret) - goto err_io; - - /* conversion done */ - if (data) - break; - } - - ret = lp8788_read_multi_bytes(adc->lp, LP8788_ADC_RAW, rawdata, size); - if (ret) - goto err_io; - - msb = (rawdata[0] << 4) & 0x00000ff0; - lsb = (rawdata[1] >> 4) & 0x0000000f; - result = msb | lsb; - *val = result; - - return 0; - -err_io: - return ret; -} - -static int lp8788_adc_read_raw(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, - int *val, int *val2, long mask) -{ - struct lp8788_adc *adc = iio_priv(indio_dev); - enum lp8788_adc_id id = chan->channel; - int ret; - - mutex_lock(&adc->lock); - - switch (mask) { - case IIO_CHAN_INFO_RAW: - ret = lp8788_get_adc_result(adc, id, val) ? -EIO : IIO_VAL_INT; - break; - case IIO_CHAN_INFO_SCALE: - *val = lp8788_scale[id] / 1000000; - *val2 = lp8788_scale[id] % 1000000; - ret = IIO_VAL_INT_PLUS_MICRO; - break; - default: - ret = -EINVAL; - break; - } - - mutex_unlock(&adc->lock); - - return ret; -} - -static const struct iio_info lp8788_adc_info = { - .read_raw = &lp8788_adc_read_raw, - .driver_module = THIS_MODULE, -}; - -#define LP8788_CHAN(_id, _type) { \ - .type = _type, \ - .indexed = 1, \ - .channel = LPADC_##_id, \ - .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \ - IIO_CHAN_INFO_SCALE_SEPARATE_BIT, \ - .datasheet_name = #_id, \ -} - -static const struct iio_chan_spec lp8788_adc_channels[] = { - [LPADC_VBATT_5P5] = LP8788_CHAN(VBATT_5P5, IIO_VOLTAGE), - [LPADC_VIN_CHG] = LP8788_CHAN(VIN_CHG, IIO_VOLTAGE), - [LPADC_IBATT] = LP8788_CHAN(IBATT, IIO_CURRENT), - [LPADC_IC_TEMP] = LP8788_CHAN(IC_TEMP, IIO_TEMP), - [LPADC_VBATT_6P0] = LP8788_CHAN(VBATT_6P0, IIO_VOLTAGE), - [LPADC_VBATT_5P0] = LP8788_CHAN(VBATT_5P0, IIO_VOLTAGE), - [LPADC_ADC1] = LP8788_CHAN(ADC1, IIO_VOLTAGE), - [LPADC_ADC2] = LP8788_CHAN(ADC2, IIO_VOLTAGE), - [LPADC_VDD] = LP8788_CHAN(VDD, IIO_VOLTAGE), - [LPADC_VCOIN] = LP8788_CHAN(VCOIN, IIO_VOLTAGE), - [LPADC_ADC3] = LP8788_CHAN(ADC3, IIO_VOLTAGE), - [LPADC_ADC4] = LP8788_CHAN(ADC4, IIO_VOLTAGE), -}; - -/* default maps used by iio consumer (lp8788-charger driver) */ -static struct iio_map lp8788_default_iio_maps[] = { - { - .consumer_dev_name = "lp8788-charger", - .consumer_channel = "lp8788_vbatt_5p0", - .adc_channel_label = "VBATT_5P0", - }, - { - .consumer_dev_name = "lp8788-charger", - .consumer_channel = "lp8788_adc1", - .adc_channel_label = "ADC1", - }, - { } -}; - -static int lp8788_iio_map_register(struct iio_dev *indio_dev, - struct lp8788_platform_data *pdata, - struct lp8788_adc *adc) -{ - struct iio_map *map; - int ret; - - map = (!pdata || !pdata->adc_pdata) ? - lp8788_default_iio_maps : pdata->adc_pdata; - - ret = iio_map_array_register(indio_dev, map); - if (ret) { - dev_err(adc->lp->dev, "iio map err: %d\n", ret); - return ret; - } - - adc->map = map; - return 0; -} - -static inline void lp8788_iio_map_unregister(struct iio_dev *indio_dev, - struct lp8788_adc *adc) -{ - iio_map_array_unregister(indio_dev, adc->map); -} - -static int __devinit lp8788_adc_probe(struct platform_device *pdev) -{ - struct lp8788 *lp = dev_get_drvdata(pdev->dev.parent); - struct iio_dev *indio_dev; - struct lp8788_adc *adc; - int ret; - - indio_dev = iio_device_alloc(sizeof(*adc)); - if (!indio_dev) - return -ENOMEM; - - adc = iio_priv(indio_dev); - adc->lp = lp; - platform_set_drvdata(pdev, indio_dev); - - ret = lp8788_iio_map_register(indio_dev, lp->pdata, adc); - if (ret) - goto err_iio_map; - - mutex_init(&adc->lock); - - indio_dev->dev.parent = lp->dev; - indio_dev->name = pdev->name; - indio_dev->modes = INDIO_DIRECT_MODE; - indio_dev->info = &lp8788_adc_info; - indio_dev->channels = lp8788_adc_channels; - indio_dev->num_channels = ARRAY_SIZE(lp8788_adc_channels); - - ret = iio_device_register(indio_dev); - if (ret) { - dev_err(lp->dev, "iio dev register err: %d\n", ret); - goto err_iio_device; - } - - return 0; - -err_iio_device: - lp8788_iio_map_unregister(indio_dev, adc); -err_iio_map: - iio_device_free(indio_dev); - return ret; -} - -static int __devexit lp8788_adc_remove(struct platform_device *pdev) -{ - struct iio_dev *indio_dev = platform_get_drvdata(pdev); - struct lp8788_adc *adc = iio_priv(indio_dev); - - iio_device_unregister(indio_dev); - lp8788_iio_map_unregister(indio_dev, adc); - iio_device_free(indio_dev); - - return 0; -} - -static struct platform_driver lp8788_adc_driver = { - .probe = lp8788_adc_probe, - .remove = __devexit_p(lp8788_adc_remove), - .driver = { - .name = LP8788_DEV_ADC, - .owner = THIS_MODULE, - }, -}; -module_platform_driver(lp8788_adc_driver); - -MODULE_DESCRIPTION("Texas Instruments LP8788 ADC Driver"); -MODULE_AUTHOR("Milo Kim"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:lp8788-adc"); diff --git a/trunk/drivers/iio/common/Kconfig b/trunk/drivers/iio/common/Kconfig deleted file mode 100644 index ed45ee54500c..000000000000 --- a/trunk/drivers/iio/common/Kconfig +++ /dev/null @@ -1,5 +0,0 @@ -# -# IIO common modules -# - -source "drivers/iio/common/hid-sensors/Kconfig" diff --git a/trunk/drivers/iio/common/Makefile b/trunk/drivers/iio/common/Makefile deleted file mode 100644 index 81584009b21b..000000000000 --- a/trunk/drivers/iio/common/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -# -# Makefile for the IIO common modules. -# Common modules contains modules, which can be shared among multiple -# IIO modules. For example if the trigger processing is common for -# multiple IIO modules then this can be moved to a common module -# instead of duplicating in each module. -# - -obj-y += hid-sensors/ diff --git a/trunk/drivers/iio/common/hid-sensors/Kconfig b/trunk/drivers/iio/common/hid-sensors/Kconfig deleted file mode 100644 index 8e63d81d652a..000000000000 --- a/trunk/drivers/iio/common/hid-sensors/Kconfig +++ /dev/null @@ -1,26 +0,0 @@ -# -# Hid Sensor common modules -# -menu "Hid Sensor IIO Common" - -config HID_SENSOR_IIO_COMMON - tristate "Common modules for all HID Sensor IIO drivers" - depends on HID_SENSOR_HUB - select IIO_TRIGGER if IIO_BUFFER - help - Say yes here to build support for HID sensor to use - HID sensor common processing for attributes and IIO triggers. - There are many attributes which can be shared among multiple - HID sensor drivers, this module contains processing for those - attributes. - -config HID_SENSOR_ENUM_BASE_QUIRKS - tristate "ENUM base quirks for HID Sensor IIO drivers" - depends on HID_SENSOR_IIO_COMMON - help - Say yes here to build support for sensor hub FW using - enumeration, which is using 1 as base instead of 0. - Since logical minimum is still set 0 instead of 1, - there is no easy way to differentiate. - -endmenu diff --git a/trunk/drivers/iio/common/hid-sensors/Makefile b/trunk/drivers/iio/common/hid-sensors/Makefile deleted file mode 100644 index 1f463e00c242..000000000000 --- a/trunk/drivers/iio/common/hid-sensors/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -# -# Makefile for the Hid sensor common modules. -# - -obj-$(CONFIG_HID_SENSOR_IIO_COMMON) += hid-sensor-iio-common.o -hid-sensor-iio-common-y := hid-sensor-attributes.o hid-sensor-trigger.o diff --git a/trunk/drivers/iio/common/hid-sensors/hid-sensor-attributes.c b/trunk/drivers/iio/common/hid-sensors/hid-sensor-attributes.c deleted file mode 100644 index 75374955caba..000000000000 --- a/trunk/drivers/iio/common/hid-sensors/hid-sensor-attributes.c +++ /dev/null @@ -1,250 +0,0 @@ -/* - * HID Sensors Driver - * Copyright (c) 2012, Intel Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "hid-sensor-attributes.h" - -static int pow_10(unsigned power) -{ - int i; - int ret = 1; - for (i = 0; i < power; ++i) - ret = ret * 10; - - return ret; -} - -static void simple_div(int dividend, int divisor, int *whole, - int *micro_frac) -{ - int rem; - int exp = 0; - - *micro_frac = 0; - if (divisor == 0) { - *whole = 0; - return; - } - *whole = dividend/divisor; - rem = dividend % divisor; - if (rem) { - while (rem <= divisor) { - rem *= 10; - exp++; - } - *micro_frac = (rem / divisor) * pow_10(6-exp); - } -} - -static void split_micro_fraction(unsigned int no, int exp, int *val1, int *val2) -{ - *val1 = no/pow_10(exp); - *val2 = no%pow_10(exp) * pow_10(6-exp); -} - -/* -VTF format uses exponent and variable size format. -For example if the size is 2 bytes -0x0067 with VTF16E14 format -> +1.03 -To convert just change to 0x67 to decimal and use two decimal as E14 stands -for 10^-2. -Negative numbers are 2's complement -*/ -static void convert_from_vtf_format(u32 value, int size, int exp, - int *val1, int *val2) -{ - int sign = 1; - - if (value & BIT(size*8 - 1)) { - value = ((1LL << (size * 8)) - value); - sign = -1; - } - exp = hid_sensor_convert_exponent(exp); - if (exp >= 0) { - *val1 = sign * value * pow_10(exp); - *val2 = 0; - } else { - split_micro_fraction(value, -exp, val1, val2); - if (*val1) - *val1 = sign * (*val1); - else - *val2 = sign * (*val2); - } -} - -static u32 convert_to_vtf_format(int size, int exp, int val1, int val2) -{ - u32 value; - int sign = 1; - - if (val1 < 0 || val2 < 0) - sign = -1; - exp = hid_sensor_convert_exponent(exp); - if (exp < 0) { - value = abs(val1) * pow_10(-exp); - value += abs(val2) / pow_10(6+exp); - } else - value = abs(val1) / pow_10(exp); - if (sign < 0) - value = ((1LL << (size * 8)) - value); - - return value; -} - -int hid_sensor_read_samp_freq_value(struct hid_sensor_iio_common *st, - int *val1, int *val2) -{ - s32 value; - int ret; - - ret = sensor_hub_get_feature(st->hsdev, - st->poll.report_id, - st->poll.index, &value); - if (ret < 0 || value < 0) { - *val1 = *val2 = 0; - return -EINVAL; - } else { - if (st->poll.units == HID_USAGE_SENSOR_UNITS_MILLISECOND) - simple_div(1000, value, val1, val2); - else if (st->poll.units == HID_USAGE_SENSOR_UNITS_SECOND) - simple_div(1, value, val1, val2); - else { - *val1 = *val2 = 0; - return -EINVAL; - } - } - - return IIO_VAL_INT_PLUS_MICRO; -} -EXPORT_SYMBOL(hid_sensor_read_samp_freq_value); - -int hid_sensor_write_samp_freq_value(struct hid_sensor_iio_common *st, - int val1, int val2) -{ - s32 value; - int ret; - - if (val1 < 0 || val2 < 0) - ret = -EINVAL; - - value = val1 * pow_10(6) + val2; - if (value) { - if (st->poll.units == HID_USAGE_SENSOR_UNITS_MILLISECOND) - value = pow_10(9)/value; - else if (st->poll.units == HID_USAGE_SENSOR_UNITS_SECOND) - value = pow_10(6)/value; - else - value = 0; - } - ret = sensor_hub_set_feature(st->hsdev, - st->poll.report_id, - st->poll.index, value); - if (ret < 0 || value < 0) - ret = -EINVAL; - - return ret; -} -EXPORT_SYMBOL(hid_sensor_write_samp_freq_value); - -int hid_sensor_read_raw_hyst_value(struct hid_sensor_iio_common *st, - int *val1, int *val2) -{ - s32 value; - int ret; - - ret = sensor_hub_get_feature(st->hsdev, - st->sensitivity.report_id, - st->sensitivity.index, &value); - if (ret < 0 || value < 0) { - *val1 = *val2 = 0; - return -EINVAL; - } else { - convert_from_vtf_format(value, st->sensitivity.size, - st->sensitivity.unit_expo, - val1, val2); - } - - return IIO_VAL_INT_PLUS_MICRO; -} -EXPORT_SYMBOL(hid_sensor_read_raw_hyst_value); - -int hid_sensor_write_raw_hyst_value(struct hid_sensor_iio_common *st, - int val1, int val2) -{ - s32 value; - int ret; - - value = convert_to_vtf_format(st->sensitivity.size, - st->sensitivity.unit_expo, - val1, val2); - ret = sensor_hub_set_feature(st->hsdev, - st->sensitivity.report_id, - st->sensitivity.index, value); - if (ret < 0 || value < 0) - ret = -EINVAL; - - return ret; -} -EXPORT_SYMBOL(hid_sensor_write_raw_hyst_value); - -int hid_sensor_parse_common_attributes(struct hid_sensor_hub_device *hsdev, - u32 usage_id, - struct hid_sensor_iio_common *st) -{ - - sensor_hub_input_get_attribute_info(hsdev, - HID_FEATURE_REPORT, usage_id, - HID_USAGE_SENSOR_PROP_REPORT_INTERVAL, - &st->poll); - - sensor_hub_input_get_attribute_info(hsdev, - HID_FEATURE_REPORT, usage_id, - HID_USAGE_SENSOR_PROP_REPORT_STATE, - &st->report_state); - - sensor_hub_input_get_attribute_info(hsdev, - HID_FEATURE_REPORT, usage_id, - HID_USAGE_SENSOR_PROY_POWER_STATE, - &st->power_state); - - sensor_hub_input_get_attribute_info(hsdev, - HID_FEATURE_REPORT, usage_id, - HID_USAGE_SENSOR_PROP_SENSITIVITY_ABS, - &st->sensitivity); - - hid_dbg(hsdev->hdev, "common attributes: %x:%x, %x:%x, %x:%x %x:%x\n", - st->poll.index, st->poll.report_id, - st->report_state.index, st->report_state.report_id, - st->power_state.index, st->power_state.report_id, - st->sensitivity.index, st->sensitivity.report_id); - - return 0; -} -EXPORT_SYMBOL(hid_sensor_parse_common_attributes); - -MODULE_AUTHOR("Srinivas Pandruvada "); -MODULE_DESCRIPTION("HID Sensor common attribute processing"); -MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/iio/common/hid-sensors/hid-sensor-attributes.h b/trunk/drivers/iio/common/hid-sensors/hid-sensor-attributes.h deleted file mode 100644 index a4676a0c3de5..000000000000 --- a/trunk/drivers/iio/common/hid-sensors/hid-sensor-attributes.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * HID Sensors Driver - * Copyright (c) 2012, Intel Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * - */ -#ifndef _HID_SENSORS_ATTRIBUTES_H -#define _HID_SENSORS_ATTRIBUTES_H - -/* Common hid sensor iio structure */ -struct hid_sensor_iio_common { - struct hid_sensor_hub_device *hsdev; - struct platform_device *pdev; - unsigned usage_id; - bool data_ready; - struct hid_sensor_hub_attribute_info poll; - struct hid_sensor_hub_attribute_info report_state; - struct hid_sensor_hub_attribute_info power_state; - struct hid_sensor_hub_attribute_info sensitivity; -}; - -/*Convert from hid unit expo to regular exponent*/ -static inline int hid_sensor_convert_exponent(int unit_expo) -{ - if (unit_expo < 0x08) - return unit_expo; - else if (unit_expo <= 0x0f) - return -(0x0f-unit_expo+1); - else - return 0; -} - -int hid_sensor_parse_common_attributes(struct hid_sensor_hub_device *hsdev, - u32 usage_id, - struct hid_sensor_iio_common *st); -int hid_sensor_write_raw_hyst_value(struct hid_sensor_iio_common *st, - int val1, int val2); -int hid_sensor_read_raw_hyst_value(struct hid_sensor_iio_common *st, - int *val1, int *val2); -int hid_sensor_write_samp_freq_value(struct hid_sensor_iio_common *st, - int val1, int val2); -int hid_sensor_read_samp_freq_value(struct hid_sensor_iio_common *st, - int *val1, int *val2); - -#endif diff --git a/trunk/drivers/iio/common/hid-sensors/hid-sensor-trigger.c b/trunk/drivers/iio/common/hid-sensors/hid-sensor-trigger.c deleted file mode 100644 index d4b790d18efb..000000000000 --- a/trunk/drivers/iio/common/hid-sensors/hid-sensor-trigger.c +++ /dev/null @@ -1,103 +0,0 @@ -/* - * HID Sensors Driver - * Copyright (c) 2012, Intel Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "hid-sensor-attributes.h" -#include "hid-sensor-trigger.h" - -static int hid_sensor_data_rdy_trigger_set_state(struct iio_trigger *trig, - bool state) -{ - struct hid_sensor_iio_common *st = trig->private_data; - int state_val; - - state_val = state ? 1 : 0; -#if (defined CONFIG_HID_SENSOR_ENUM_BASE_QUIRKS) || \ - (defined CONFIG_HID_SENSOR_ENUM_BASE_QUIRKS_MODULE) - ++state_val; -#endif - st->data_ready = state; - sensor_hub_set_feature(st->hsdev, st->power_state.report_id, - st->power_state.index, - (s32)state_val); - - sensor_hub_set_feature(st->hsdev, st->report_state.report_id, - st->report_state.index, - (s32)state_val); - - return 0; -} - -void hid_sensor_remove_trigger(struct iio_dev *indio_dev) -{ - iio_trigger_unregister(indio_dev->trig); - iio_trigger_free(indio_dev->trig); - indio_dev->trig = NULL; -} -EXPORT_SYMBOL(hid_sensor_remove_trigger); - -static const struct iio_trigger_ops hid_sensor_trigger_ops = { - .owner = THIS_MODULE, - .set_trigger_state = &hid_sensor_data_rdy_trigger_set_state, -}; - -int hid_sensor_setup_trigger(struct iio_dev *indio_dev, const char *name, - struct hid_sensor_iio_common *attrb) -{ - int ret; - struct iio_trigger *trig; - - trig = iio_trigger_alloc("%s-dev%d", name, indio_dev->id); - if (trig == NULL) { - dev_err(&indio_dev->dev, "Trigger Allocate Failed\n"); - ret = -ENOMEM; - goto error_ret; - } - - trig->dev.parent = indio_dev->dev.parent; - trig->private_data = attrb; - trig->ops = &hid_sensor_trigger_ops; - ret = iio_trigger_register(trig); - - if (ret) { - dev_err(&indio_dev->dev, "Trigger Register Failed\n"); - goto error_free_trig; - } - indio_dev->trig = trig; - - return ret; - -error_free_trig: - iio_trigger_free(trig); -error_ret: - return ret; -} -EXPORT_SYMBOL(hid_sensor_setup_trigger); - -MODULE_AUTHOR("Srinivas Pandruvada "); -MODULE_DESCRIPTION("HID Sensor trigger processing"); -MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/iio/common/hid-sensors/hid-sensor-trigger.h b/trunk/drivers/iio/common/hid-sensors/hid-sensor-trigger.h deleted file mode 100644 index fd982971b1b8..000000000000 --- a/trunk/drivers/iio/common/hid-sensors/hid-sensor-trigger.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * HID Sensors Driver - * Copyright (c) 2012, Intel Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * - */ -#ifndef _HID_SENSOR_TRIGGER_H -#define _HID_SENSOR_TRIGGER_H - -int hid_sensor_setup_trigger(struct iio_dev *indio_dev, const char *name, - struct hid_sensor_iio_common *attrb); -void hid_sensor_remove_trigger(struct iio_dev *indio_dev); - -#endif diff --git a/trunk/drivers/iio/dac/Kconfig b/trunk/drivers/iio/dac/Kconfig index b1c0ee5294ca..1be15fa9d618 100644 --- a/trunk/drivers/iio/dac/Kconfig +++ b/trunk/drivers/iio/dac/Kconfig @@ -57,12 +57,11 @@ config AD5624R_SPI config AD5446 tristate "Analog Devices AD5446 and similar single channel DACs driver" - depends on (SPI_MASTER || I2C) + depends on SPI help - Say yes here to build support for Analog Devices AD5300, AD5301, AD5310, - AD5311, AD5320, AD5321, AD5444, AD5446, AD5450, AD5451, AD5452, AD5453, - AD5512A, AD5541A, AD5542A, AD5543, AD5553, AD5601, AD5602, AD5611, AD5612, - AD5620, AD5621, AD5622, AD5640, AD5660, AD5662 DACs. + Say yes here to build support for Analog Devices AD5444, AD5446, AD5450, + AD5451, AD5452, AD5453, AD5512A, AD5541A, AD5542A, AD5543, AD5553, AD5601, + AD5611, AD5620, AD5621, AD5640, AD5660, AD5662 DACs. To compile this driver as a module, choose M here: the module will be called ad5446. @@ -77,17 +76,6 @@ config AD5504 To compile this driver as a module, choose M here: the module will be called ad5504. -config AD5755 - tristate "Analog Devices AD5755/AD5755-1/AD5757/AD5735/AD5737 DAC driver" - depends on SPI_MASTER - help - Say yes here to build support for Analog Devices AD5755, AD5755-1, - AD5757, AD5735, AD5737 quad channel Digital to - Analog Converter. - - To compile this driver as a module, choose M here: the - module will be called ad5755. - config AD5764 tristate "Analog Devices AD5764/64R/44/44R DAC driver" depends on SPI_MASTER diff --git a/trunk/drivers/iio/dac/Makefile b/trunk/drivers/iio/dac/Makefile index c0d333b23ba3..9ea3ceeefc07 100644 --- a/trunk/drivers/iio/dac/Makefile +++ b/trunk/drivers/iio/dac/Makefile @@ -9,7 +9,6 @@ obj-$(CONFIG_AD5624R_SPI) += ad5624r_spi.o obj-$(CONFIG_AD5064) += ad5064.o obj-$(CONFIG_AD5504) += ad5504.o obj-$(CONFIG_AD5446) += ad5446.o -obj-$(CONFIG_AD5755) += ad5755.o obj-$(CONFIG_AD5764) += ad5764.o obj-$(CONFIG_AD5791) += ad5791.o obj-$(CONFIG_AD5686) += ad5686.o diff --git a/trunk/drivers/iio/dac/ad5446.c b/trunk/drivers/iio/dac/ad5446.c index 3310cbbd41e7..2ca5059ef89e 100644 --- a/trunk/drivers/iio/dac/ad5446.c +++ b/trunk/drivers/iio/dac/ad5446.c @@ -14,7 +14,6 @@ #include #include #include -#include #include #include #include @@ -22,40 +21,24 @@ #include #include -#define MODE_PWRDWN_1k 0x1 -#define MODE_PWRDWN_100k 0x2 -#define MODE_PWRDWN_TRISTATE 0x3 +#include "ad5446.h" -/** - * struct ad5446_state - driver instance specific data - * @spi: spi_device - * @chip_info: chip model specific constants, available modes etc - * @reg: supply regulator - * @vref_mv: actual reference voltage used - */ +static int ad5446_write(struct ad5446_state *st, unsigned val) +{ + __be16 data = cpu_to_be16(val); + return spi_write(st->spi, &data, sizeof(data)); +} -struct ad5446_state { - struct device *dev; - const struct ad5446_chip_info *chip_info; - struct regulator *reg; - unsigned short vref_mv; - unsigned cached_val; - unsigned pwr_down_mode; - unsigned pwr_down; -}; +static int ad5660_write(struct ad5446_state *st, unsigned val) +{ + uint8_t data[3]; -/** - * struct ad5446_chip_info - chip specific information - * @channel: channel spec for the DAC - * @int_vref_mv: AD5620/40/60: the internal reference voltage - * @write: chip specific helper function to write to the register - */ + data[0] = (val >> 16) & 0xFF; + data[1] = (val >> 8) & 0xFF; + data[2] = val & 0xFF; -struct ad5446_chip_info { - struct iio_chan_spec channel; - u16 int_vref_mv; - int (*write)(struct ad5446_state *st, unsigned val); -}; + return spi_write(st->spi, data, sizeof(data)); +} static const char * const ad5446_powerdown_modes[] = { "1kohm_to_gnd", "100kohm_to_gnd", "three_state" @@ -127,7 +110,7 @@ static ssize_t ad5446_write_dac_powerdown(struct iio_dev *indio_dev, return ret ? ret : len; } -static const struct iio_chan_spec_ext_info ad5446_ext_info_powerdown[] = { +static const struct iio_chan_spec_ext_info ad5064_ext_info_powerdown[] = { { .name = "powerdown", .read = ad5446_read_dac_powerdown, @@ -153,7 +136,84 @@ static const struct iio_chan_spec_ext_info ad5446_ext_info_powerdown[] = { _AD5446_CHANNEL(bits, storage, shift, NULL) #define AD5446_CHANNEL_POWERDOWN(bits, storage, shift) \ - _AD5446_CHANNEL(bits, storage, shift, ad5446_ext_info_powerdown) + _AD5446_CHANNEL(bits, storage, shift, ad5064_ext_info_powerdown) + +static const struct ad5446_chip_info ad5446_chip_info_tbl[] = { + [ID_AD5444] = { + .channel = AD5446_CHANNEL(12, 16, 2), + .write = ad5446_write, + }, + [ID_AD5446] = { + .channel = AD5446_CHANNEL(14, 16, 0), + .write = ad5446_write, + }, + [ID_AD5450] = { + .channel = AD5446_CHANNEL(8, 16, 6), + .write = ad5446_write, + }, + [ID_AD5451] = { + .channel = AD5446_CHANNEL(10, 16, 4), + .write = ad5446_write, + }, + [ID_AD5541A] = { + .channel = AD5446_CHANNEL(16, 16, 0), + .write = ad5446_write, + }, + [ID_AD5512A] = { + .channel = AD5446_CHANNEL(12, 16, 4), + .write = ad5446_write, + }, + [ID_AD5553] = { + .channel = AD5446_CHANNEL(14, 16, 0), + .write = ad5446_write, + }, + [ID_AD5601] = { + .channel = AD5446_CHANNEL_POWERDOWN(8, 16, 6), + .write = ad5446_write, + }, + [ID_AD5611] = { + .channel = AD5446_CHANNEL_POWERDOWN(10, 16, 4), + .write = ad5446_write, + }, + [ID_AD5621] = { + .channel = AD5446_CHANNEL_POWERDOWN(12, 16, 2), + .write = ad5446_write, + }, + [ID_AD5620_2500] = { + .channel = AD5446_CHANNEL_POWERDOWN(12, 16, 2), + .int_vref_mv = 2500, + .write = ad5446_write, + }, + [ID_AD5620_1250] = { + .channel = AD5446_CHANNEL_POWERDOWN(12, 16, 2), + .int_vref_mv = 1250, + .write = ad5446_write, + }, + [ID_AD5640_2500] = { + .channel = AD5446_CHANNEL_POWERDOWN(14, 16, 0), + .int_vref_mv = 2500, + .write = ad5446_write, + }, + [ID_AD5640_1250] = { + .channel = AD5446_CHANNEL_POWERDOWN(14, 16, 0), + .int_vref_mv = 1250, + .write = ad5446_write, + }, + [ID_AD5660_2500] = { + .channel = AD5446_CHANNEL_POWERDOWN(16, 16, 0), + .int_vref_mv = 2500, + .write = ad5660_write, + }, + [ID_AD5660_1250] = { + .channel = AD5446_CHANNEL_POWERDOWN(16, 16, 0), + .int_vref_mv = 1250, + .write = ad5660_write, + }, + [ID_AD5662] = { + .channel = AD5446_CHANNEL_POWERDOWN(16, 16, 0), + .write = ad5660_write, + }, +}; static int ad5446_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, @@ -212,15 +272,14 @@ static const struct iio_info ad5446_info = { .driver_module = THIS_MODULE, }; -static int __devinit ad5446_probe(struct device *dev, const char *name, - const struct ad5446_chip_info *chip_info) +static int __devinit ad5446_probe(struct spi_device *spi) { struct ad5446_state *st; struct iio_dev *indio_dev; struct regulator *reg; int ret, voltage_uv = 0; - reg = regulator_get(dev, "vcc"); + reg = regulator_get(&spi->dev, "vcc"); if (!IS_ERR(reg)) { ret = regulator_enable(reg); if (ret) @@ -235,15 +294,16 @@ static int __devinit ad5446_probe(struct device *dev, const char *name, goto error_disable_reg; } st = iio_priv(indio_dev); - st->chip_info = chip_info; + st->chip_info = + &ad5446_chip_info_tbl[spi_get_device_id(spi)->driver_data]; - dev_set_drvdata(dev, indio_dev); + spi_set_drvdata(spi, indio_dev); st->reg = reg; - st->dev = dev; + st->spi = spi; - /* Establish that the iio_dev is a child of the device */ - indio_dev->dev.parent = dev; - indio_dev->name = name; + /* Establish that the iio_dev is a child of the spi device */ + indio_dev->dev.parent = &spi->dev; + indio_dev->name = spi_get_device_id(spi)->name; indio_dev->info = &ad5446_info; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->channels = &st->chip_info->channel; @@ -256,7 +316,7 @@ static int __devinit ad5446_probe(struct device *dev, const char *name, else if (voltage_uv) st->vref_mv = voltage_uv / 1000; else - dev_warn(dev, "reference voltage unspecified\n"); + dev_warn(&spi->dev, "reference voltage unspecified\n"); ret = iio_device_register(indio_dev); if (ret) @@ -276,9 +336,9 @@ static int __devinit ad5446_probe(struct device *dev, const char *name, return ret; } -static int ad5446_remove(struct device *dev) +static int ad5446_remove(struct spi_device *spi) { - struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev *indio_dev = spi_get_drvdata(spi); struct ad5446_state *st = iio_priv(indio_dev); iio_device_unregister(indio_dev); @@ -291,151 +351,7 @@ static int ad5446_remove(struct device *dev) return 0; } -#if IS_ENABLED(CONFIG_SPI_MASTER) - -static int ad5446_write(struct ad5446_state *st, unsigned val) -{ - struct spi_device *spi = to_spi_device(st->dev); - __be16 data = cpu_to_be16(val); - - return spi_write(spi, &data, sizeof(data)); -} - -static int ad5660_write(struct ad5446_state *st, unsigned val) -{ - struct spi_device *spi = to_spi_device(st->dev); - uint8_t data[3]; - - data[0] = (val >> 16) & 0xFF; - data[1] = (val >> 8) & 0xFF; - data[2] = val & 0xFF; - - return spi_write(spi, data, sizeof(data)); -} - -/** - * ad5446_supported_spi_device_ids: - * The AD5620/40/60 parts are available in different fixed internal reference - * voltage options. The actual part numbers may look differently - * (and a bit cryptic), however this style is used to make clear which - * parts are supported here. - */ -enum ad5446_supported_spi_device_ids { - ID_AD5300, - ID_AD5310, - ID_AD5320, - ID_AD5444, - ID_AD5446, - ID_AD5450, - ID_AD5451, - ID_AD5541A, - ID_AD5512A, - ID_AD5553, - ID_AD5601, - ID_AD5611, - ID_AD5621, - ID_AD5620_2500, - ID_AD5620_1250, - ID_AD5640_2500, - ID_AD5640_1250, - ID_AD5660_2500, - ID_AD5660_1250, - ID_AD5662, -}; - -static const struct ad5446_chip_info ad5446_spi_chip_info[] = { - [ID_AD5300] = { - .channel = AD5446_CHANNEL_POWERDOWN(8, 16, 4), - .write = ad5446_write, - }, - [ID_AD5310] = { - .channel = AD5446_CHANNEL_POWERDOWN(10, 16, 2), - .write = ad5446_write, - }, - [ID_AD5320] = { - .channel = AD5446_CHANNEL_POWERDOWN(12, 16, 0), - .write = ad5446_write, - }, - [ID_AD5444] = { - .channel = AD5446_CHANNEL(12, 16, 2), - .write = ad5446_write, - }, - [ID_AD5446] = { - .channel = AD5446_CHANNEL(14, 16, 0), - .write = ad5446_write, - }, - [ID_AD5450] = { - .channel = AD5446_CHANNEL(8, 16, 6), - .write = ad5446_write, - }, - [ID_AD5451] = { - .channel = AD5446_CHANNEL(10, 16, 4), - .write = ad5446_write, - }, - [ID_AD5541A] = { - .channel = AD5446_CHANNEL(16, 16, 0), - .write = ad5446_write, - }, - [ID_AD5512A] = { - .channel = AD5446_CHANNEL(12, 16, 4), - .write = ad5446_write, - }, - [ID_AD5553] = { - .channel = AD5446_CHANNEL(14, 16, 0), - .write = ad5446_write, - }, - [ID_AD5601] = { - .channel = AD5446_CHANNEL_POWERDOWN(8, 16, 6), - .write = ad5446_write, - }, - [ID_AD5611] = { - .channel = AD5446_CHANNEL_POWERDOWN(10, 16, 4), - .write = ad5446_write, - }, - [ID_AD5621] = { - .channel = AD5446_CHANNEL_POWERDOWN(12, 16, 2), - .write = ad5446_write, - }, - [ID_AD5620_2500] = { - .channel = AD5446_CHANNEL_POWERDOWN(12, 16, 2), - .int_vref_mv = 2500, - .write = ad5446_write, - }, - [ID_AD5620_1250] = { - .channel = AD5446_CHANNEL_POWERDOWN(12, 16, 2), - .int_vref_mv = 1250, - .write = ad5446_write, - }, - [ID_AD5640_2500] = { - .channel = AD5446_CHANNEL_POWERDOWN(14, 16, 0), - .int_vref_mv = 2500, - .write = ad5446_write, - }, - [ID_AD5640_1250] = { - .channel = AD5446_CHANNEL_POWERDOWN(14, 16, 0), - .int_vref_mv = 1250, - .write = ad5446_write, - }, - [ID_AD5660_2500] = { - .channel = AD5446_CHANNEL_POWERDOWN(16, 16, 0), - .int_vref_mv = 2500, - .write = ad5660_write, - }, - [ID_AD5660_1250] = { - .channel = AD5446_CHANNEL_POWERDOWN(16, 16, 0), - .int_vref_mv = 1250, - .write = ad5660_write, - }, - [ID_AD5662] = { - .channel = AD5446_CHANNEL_POWERDOWN(16, 16, 0), - .write = ad5660_write, - }, -}; - -static const struct spi_device_id ad5446_spi_ids[] = { - {"ad5300", ID_AD5300}, - {"ad5310", ID_AD5310}, - {"ad5320", ID_AD5320}, +static const struct spi_device_id ad5446_id[] = { {"ad5444", ID_AD5444}, {"ad5446", ID_AD5446}, {"ad5450", ID_AD5450}, @@ -459,160 +375,18 @@ static const struct spi_device_id ad5446_spi_ids[] = { {"ad5662", ID_AD5662}, {} }; -MODULE_DEVICE_TABLE(spi, ad5446_spi_ids); - -static int __devinit ad5446_spi_probe(struct spi_device *spi) -{ - const struct spi_device_id *id = spi_get_device_id(spi); +MODULE_DEVICE_TABLE(spi, ad5446_id); - return ad5446_probe(&spi->dev, id->name, - &ad5446_spi_chip_info[id->driver_data]); -} - -static int __devexit ad5446_spi_remove(struct spi_device *spi) -{ - return ad5446_remove(&spi->dev); -} - -static struct spi_driver ad5446_spi_driver = { +static struct spi_driver ad5446_driver = { .driver = { .name = "ad5446", .owner = THIS_MODULE, }, - .probe = ad5446_spi_probe, - .remove = __devexit_p(ad5446_spi_remove), - .id_table = ad5446_spi_ids, + .probe = ad5446_probe, + .remove = __devexit_p(ad5446_remove), + .id_table = ad5446_id, }; - -static int __init ad5446_spi_register_driver(void) -{ - return spi_register_driver(&ad5446_spi_driver); -} - -static void ad5446_spi_unregister_driver(void) -{ - spi_unregister_driver(&ad5446_spi_driver); -} - -#else - -static inline int ad5446_spi_register_driver(void) { return 0; } -static inline void ad5446_spi_unregister_driver(void) { } - -#endif - -#if IS_ENABLED(CONFIG_I2C) - -static int ad5622_write(struct ad5446_state *st, unsigned val) -{ - struct i2c_client *client = to_i2c_client(st->dev); - __be16 data = cpu_to_be16(val); - - return i2c_master_send(client, (char *)&data, sizeof(data)); -} - -/** - * ad5446_supported_i2c_device_ids: - * The AD5620/40/60 parts are available in different fixed internal reference - * voltage options. The actual part numbers may look differently - * (and a bit cryptic), however this style is used to make clear which - * parts are supported here. - */ -enum ad5446_supported_i2c_device_ids { - ID_AD5602, - ID_AD5612, - ID_AD5622, -}; - -static const struct ad5446_chip_info ad5446_i2c_chip_info[] = { - [ID_AD5602] = { - .channel = AD5446_CHANNEL_POWERDOWN(8, 16, 4), - .write = ad5622_write, - }, - [ID_AD5612] = { - .channel = AD5446_CHANNEL_POWERDOWN(10, 16, 2), - .write = ad5622_write, - }, - [ID_AD5622] = { - .channel = AD5446_CHANNEL_POWERDOWN(12, 16, 0), - .write = ad5622_write, - }, -}; - -static int __devinit ad5446_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) -{ - return ad5446_probe(&i2c->dev, id->name, - &ad5446_i2c_chip_info[id->driver_data]); -} - -static int __devexit ad5446_i2c_remove(struct i2c_client *i2c) -{ - return ad5446_remove(&i2c->dev); -} - -static const struct i2c_device_id ad5446_i2c_ids[] = { - {"ad5301", ID_AD5602}, - {"ad5311", ID_AD5612}, - {"ad5321", ID_AD5622}, - {"ad5602", ID_AD5602}, - {"ad5612", ID_AD5612}, - {"ad5622", ID_AD5622}, - {} -}; -MODULE_DEVICE_TABLE(i2c, ad5446_i2c_ids); - -static struct i2c_driver ad5446_i2c_driver = { - .driver = { - .name = "ad5446", - .owner = THIS_MODULE, - }, - .probe = ad5446_i2c_probe, - .remove = __devexit_p(ad5446_i2c_remove), - .id_table = ad5446_i2c_ids, -}; - -static int __init ad5446_i2c_register_driver(void) -{ - return i2c_add_driver(&ad5446_i2c_driver); -} - -static void __exit ad5446_i2c_unregister_driver(void) -{ - i2c_del_driver(&ad5446_i2c_driver); -} - -#else - -static inline int ad5446_i2c_register_driver(void) { return 0; } -static inline void ad5446_i2c_unregister_driver(void) { } - -#endif - -static int __init ad5446_init(void) -{ - int ret; - - ret = ad5446_spi_register_driver(); - if (ret) - return ret; - - ret = ad5446_i2c_register_driver(); - if (ret) { - ad5446_spi_unregister_driver(); - return ret; - } - - return 0; -} -module_init(ad5446_init); - -static void __exit ad5446_exit(void) -{ - ad5446_i2c_unregister_driver(); - ad5446_spi_unregister_driver(); -} -module_exit(ad5446_exit); +module_spi_driver(ad5446_driver); MODULE_AUTHOR("Michael Hennerich "); MODULE_DESCRIPTION("Analog Devices AD5444/AD5446 DAC"); diff --git a/trunk/drivers/iio/dac/ad5446.h b/trunk/drivers/iio/dac/ad5446.h new file mode 100644 index 000000000000..2934269a56d5 --- /dev/null +++ b/trunk/drivers/iio/dac/ad5446.h @@ -0,0 +1,91 @@ +/* + * AD5446 SPI DAC driver + * + * Copyright 2010 Analog Devices Inc. + * + * Licensed under the GPL-2 or later. + */ +#ifndef IIO_DAC_AD5446_H_ +#define IIO_DAC_AD5446_H_ + +/* DAC Control Bits */ + +#define AD5446_LOAD (0x0 << 14) /* Load and update */ +#define AD5446_SDO_DIS (0x1 << 14) /* Disable SDO */ +#define AD5446_NOP (0x2 << 14) /* No operation */ +#define AD5446_CLK_RISING (0x3 << 14) /* Clock data on rising edge */ + +#define AD5620_LOAD (0x0 << 14) /* Load and update Norm Operation*/ +#define AD5620_PWRDWN_1k (0x1 << 14) /* Power-down: 1kOhm to GND */ +#define AD5620_PWRDWN_100k (0x2 << 14) /* Power-down: 100kOhm to GND */ +#define AD5620_PWRDWN_TRISTATE (0x3 << 14) /* Power-down: Three-state */ + +#define AD5660_LOAD (0x0 << 16) /* Load and update Norm Operation*/ +#define AD5660_PWRDWN_1k (0x1 << 16) /* Power-down: 1kOhm to GND */ +#define AD5660_PWRDWN_100k (0x2 << 16) /* Power-down: 100kOhm to GND */ +#define AD5660_PWRDWN_TRISTATE (0x3 << 16) /* Power-down: Three-state */ + +#define MODE_PWRDWN_1k 0x1 +#define MODE_PWRDWN_100k 0x2 +#define MODE_PWRDWN_TRISTATE 0x3 + +/** + * struct ad5446_state - driver instance specific data + * @spi: spi_device + * @chip_info: chip model specific constants, available modes etc + * @reg: supply regulator + * @vref_mv: actual reference voltage used + */ + +struct ad5446_state { + struct spi_device *spi; + const struct ad5446_chip_info *chip_info; + struct regulator *reg; + unsigned short vref_mv; + unsigned cached_val; + unsigned pwr_down_mode; + unsigned pwr_down; +}; + +/** + * struct ad5446_chip_info - chip specific information + * @channel: channel spec for the DAC + * @int_vref_mv: AD5620/40/60: the internal reference voltage + * @write: chip specific helper function to write to the register + */ + +struct ad5446_chip_info { + struct iio_chan_spec channel; + u16 int_vref_mv; + int (*write)(struct ad5446_state *st, unsigned val); +}; + +/** + * ad5446_supported_device_ids: + * The AD5620/40/60 parts are available in different fixed internal reference + * voltage options. The actual part numbers may look differently + * (and a bit cryptic), however this style is used to make clear which + * parts are supported here. + */ + +enum ad5446_supported_device_ids { + ID_AD5444, + ID_AD5446, + ID_AD5450, + ID_AD5451, + ID_AD5541A, + ID_AD5512A, + ID_AD5553, + ID_AD5601, + ID_AD5611, + ID_AD5621, + ID_AD5620_2500, + ID_AD5620_1250, + ID_AD5640_2500, + ID_AD5640_1250, + ID_AD5660_2500, + ID_AD5660_1250, + ID_AD5662, +}; + +#endif /* IIO_DAC_AD5446_H_ */ diff --git a/trunk/drivers/iio/dac/ad5755.c b/trunk/drivers/iio/dac/ad5755.c deleted file mode 100644 index 5db3506034c5..000000000000 --- a/trunk/drivers/iio/dac/ad5755.c +++ /dev/null @@ -1,650 +0,0 @@ -/* - * AD5755, AD5755-1, AD5757, AD5735, AD5737 Digital to analog converters driver - * - * Copyright 2012 Analog Devices Inc. - * - * Licensed under the GPL-2. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define AD5755_NUM_CHANNELS 4 - -#define AD5755_ADDR(x) ((x) << 16) - -#define AD5755_WRITE_REG_DATA(chan) (chan) -#define AD5755_WRITE_REG_GAIN(chan) (0x08 | (chan)) -#define AD5755_WRITE_REG_OFFSET(chan) (0x10 | (chan)) -#define AD5755_WRITE_REG_CTRL(chan) (0x1c | (chan)) - -#define AD5755_READ_REG_DATA(chan) (chan) -#define AD5755_READ_REG_CTRL(chan) (0x4 | (chan)) -#define AD5755_READ_REG_GAIN(chan) (0x8 | (chan)) -#define AD5755_READ_REG_OFFSET(chan) (0xc | (chan)) -#define AD5755_READ_REG_CLEAR(chan) (0x10 | (chan)) -#define AD5755_READ_REG_SLEW(chan) (0x14 | (chan)) -#define AD5755_READ_REG_STATUS 0x18 -#define AD5755_READ_REG_MAIN 0x19 -#define AD5755_READ_REG_DC_DC 0x1a - -#define AD5755_CTRL_REG_SLEW 0x0 -#define AD5755_CTRL_REG_MAIN 0x1 -#define AD5755_CTRL_REG_DAC 0x2 -#define AD5755_CTRL_REG_DC_DC 0x3 -#define AD5755_CTRL_REG_SW 0x4 - -#define AD5755_READ_FLAG 0x800000 - -#define AD5755_NOOP 0x1CE000 - -#define AD5755_DAC_INT_EN BIT(8) -#define AD5755_DAC_CLR_EN BIT(7) -#define AD5755_DAC_OUT_EN BIT(6) -#define AD5755_DAC_INT_CURRENT_SENSE_RESISTOR BIT(5) -#define AD5755_DAC_DC_DC_EN BIT(4) -#define AD5755_DAC_VOLTAGE_OVERRANGE_EN BIT(3) - -#define AD5755_DC_DC_MAXV 0 -#define AD5755_DC_DC_FREQ_SHIFT 2 -#define AD5755_DC_DC_PHASE_SHIFT 4 -#define AD5755_EXT_DC_DC_COMP_RES BIT(6) - -#define AD5755_SLEW_STEP_SIZE_SHIFT 0 -#define AD5755_SLEW_RATE_SHIFT 3 -#define AD5755_SLEW_ENABLE BIT(12) - -/** - * struct ad5755_chip_info - chip specific information - * @channel_template: channel specification - * @calib_shift: shift for the calibration data registers - * @has_voltage_out: whether the chip has voltage outputs - */ -struct ad5755_chip_info { - const struct iio_chan_spec channel_template; - unsigned int calib_shift; - bool has_voltage_out; -}; - -/** - * struct ad5755_state - driver instance specific data - * @spi: spi device the driver is attached to - * @chip_info: chip model specific constants, available modes etc - * @pwr_down: bitmask which contains hether a channel is powered down or not - * @ctrl: software shadow of the channel ctrl registers - * @channels: iio channel spec for the device - * @data: spi transfer buffers - */ -struct ad5755_state { - struct spi_device *spi; - const struct ad5755_chip_info *chip_info; - unsigned int pwr_down; - unsigned int ctrl[AD5755_NUM_CHANNELS]; - struct iio_chan_spec channels[AD5755_NUM_CHANNELS]; - - /* - * DMA (thus cache coherency maintenance) requires the - * transfer buffers to live in their own cache lines. - */ - - union { - u32 d32; - u8 d8[4]; - } data[2] ____cacheline_aligned; -}; - -enum ad5755_type { - ID_AD5755, - ID_AD5757, - ID_AD5735, - ID_AD5737, -}; - -static int ad5755_write_unlocked(struct iio_dev *indio_dev, - unsigned int reg, unsigned int val) -{ - struct ad5755_state *st = iio_priv(indio_dev); - - st->data[0].d32 = cpu_to_be32((reg << 16) | val); - - return spi_write(st->spi, &st->data[0].d8[1], 3); -} - -static int ad5755_write_ctrl_unlocked(struct iio_dev *indio_dev, - unsigned int channel, unsigned int reg, unsigned int val) -{ - return ad5755_write_unlocked(indio_dev, - AD5755_WRITE_REG_CTRL(channel), (reg << 13) | val); -} - -static int ad5755_write(struct iio_dev *indio_dev, unsigned int reg, - unsigned int val) -{ - int ret; - - mutex_lock(&indio_dev->mlock); - ret = ad5755_write_unlocked(indio_dev, reg, val); - mutex_unlock(&indio_dev->mlock); - - return ret; -} - -static int ad5755_write_ctrl(struct iio_dev *indio_dev, unsigned int channel, - unsigned int reg, unsigned int val) -{ - int ret; - - mutex_lock(&indio_dev->mlock); - ret = ad5755_write_ctrl_unlocked(indio_dev, channel, reg, val); - mutex_unlock(&indio_dev->mlock); - - return ret; -} - -static int ad5755_read(struct iio_dev *indio_dev, unsigned int addr) -{ - struct ad5755_state *st = iio_priv(indio_dev); - struct spi_message m; - int ret; - struct spi_transfer t[] = { - { - .tx_buf = &st->data[0].d8[1], - .len = 3, - .cs_change = 1, - }, { - .tx_buf = &st->data[1].d8[1], - .rx_buf = &st->data[1].d8[1], - .len = 3, - }, - }; - - spi_message_init(&m); - spi_message_add_tail(&t[0], &m); - spi_message_add_tail(&t[1], &m); - - mutex_lock(&indio_dev->mlock); - - st->data[0].d32 = cpu_to_be32(AD5755_READ_FLAG | (addr << 16)); - st->data[1].d32 = cpu_to_be32(AD5755_NOOP); - - ret = spi_sync(st->spi, &m); - if (ret >= 0) - ret = be32_to_cpu(st->data[1].d32) & 0xffff; - - mutex_unlock(&indio_dev->mlock); - - return ret; -} - -static int ad5755_update_dac_ctrl(struct iio_dev *indio_dev, - unsigned int channel, unsigned int set, unsigned int clr) -{ - struct ad5755_state *st = iio_priv(indio_dev); - int ret; - - st->ctrl[channel] |= set; - st->ctrl[channel] &= ~clr; - - ret = ad5755_write_ctrl_unlocked(indio_dev, channel, - AD5755_CTRL_REG_DAC, st->ctrl[channel]); - - return ret; -} - -static int ad5755_set_channel_pwr_down(struct iio_dev *indio_dev, - unsigned int channel, bool pwr_down) -{ - struct ad5755_state *st = iio_priv(indio_dev); - unsigned int mask = BIT(channel); - - mutex_lock(&indio_dev->mlock); - - if ((bool)(st->pwr_down & mask) == pwr_down) - goto out_unlock; - - if (!pwr_down) { - st->pwr_down &= ~mask; - ad5755_update_dac_ctrl(indio_dev, channel, - AD5755_DAC_INT_EN | AD5755_DAC_DC_DC_EN, 0); - udelay(200); - ad5755_update_dac_ctrl(indio_dev, channel, - AD5755_DAC_OUT_EN, 0); - } else { - st->pwr_down |= mask; - ad5755_update_dac_ctrl(indio_dev, channel, - 0, AD5755_DAC_INT_EN | AD5755_DAC_OUT_EN | - AD5755_DAC_DC_DC_EN); - } - -out_unlock: - mutex_unlock(&indio_dev->mlock); - - return 0; -} - -static const int ad5755_min_max_table[][2] = { - [AD5755_MODE_VOLTAGE_0V_5V] = { 0, 5000 }, - [AD5755_MODE_VOLTAGE_0V_10V] = { 0, 10000 }, - [AD5755_MODE_VOLTAGE_PLUSMINUS_5V] = { -5000, 5000 }, - [AD5755_MODE_VOLTAGE_PLUSMINUS_10V] = { -10000, 10000 }, - [AD5755_MODE_CURRENT_4mA_20mA] = { 4, 20 }, - [AD5755_MODE_CURRENT_0mA_20mA] = { 0, 20 }, - [AD5755_MODE_CURRENT_0mA_24mA] = { 0, 24 }, -}; - -static void ad5755_get_min_max(struct ad5755_state *st, - struct iio_chan_spec const *chan, int *min, int *max) -{ - enum ad5755_mode mode = st->ctrl[chan->channel] & 7; - *min = ad5755_min_max_table[mode][0]; - *max = ad5755_min_max_table[mode][1]; -} - -static inline int ad5755_get_offset(struct ad5755_state *st, - struct iio_chan_spec const *chan) -{ - int min, max; - - ad5755_get_min_max(st, chan, &min, &max); - return (min * (1 << chan->scan_type.realbits)) / (max - min); -} - -static inline int ad5755_get_scale(struct ad5755_state *st, - struct iio_chan_spec const *chan) -{ - int min, max; - - ad5755_get_min_max(st, chan, &min, &max); - return ((max - min) * 1000000000ULL) >> chan->scan_type.realbits; -} - -static int ad5755_chan_reg_info(struct ad5755_state *st, - struct iio_chan_spec const *chan, long info, bool write, - unsigned int *reg, unsigned int *shift, unsigned int *offset) -{ - switch (info) { - case IIO_CHAN_INFO_RAW: - if (write) - *reg = AD5755_WRITE_REG_DATA(chan->address); - else - *reg = AD5755_READ_REG_DATA(chan->address); - *shift = chan->scan_type.shift; - *offset = 0; - break; - case IIO_CHAN_INFO_CALIBBIAS: - if (write) - *reg = AD5755_WRITE_REG_OFFSET(chan->address); - else - *reg = AD5755_READ_REG_OFFSET(chan->address); - *shift = st->chip_info->calib_shift; - *offset = 32768; - break; - case IIO_CHAN_INFO_CALIBSCALE: - if (write) - *reg = AD5755_WRITE_REG_GAIN(chan->address); - else - *reg = AD5755_READ_REG_GAIN(chan->address); - *shift = st->chip_info->calib_shift; - *offset = 0; - break; - default: - return -EINVAL; - } - - return 0; -} - -static int ad5755_read_raw(struct iio_dev *indio_dev, - const struct iio_chan_spec *chan, int *val, int *val2, long info) -{ - struct ad5755_state *st = iio_priv(indio_dev); - unsigned int reg, shift, offset; - int ret; - - switch (info) { - case IIO_CHAN_INFO_SCALE: - *val = 0; - *val2 = ad5755_get_scale(st, chan); - return IIO_VAL_INT_PLUS_NANO; - case IIO_CHAN_INFO_OFFSET: - *val = ad5755_get_offset(st, chan); - return IIO_VAL_INT; - default: - ret = ad5755_chan_reg_info(st, chan, info, false, - ®, &shift, &offset); - if (ret) - return ret; - - ret = ad5755_read(indio_dev, reg); - if (ret < 0) - return ret; - - *val = (ret - offset) >> shift; - - return IIO_VAL_INT; - } - - return -EINVAL; -} - -static int ad5755_write_raw(struct iio_dev *indio_dev, - const struct iio_chan_spec *chan, int val, int val2, long info) -{ - struct ad5755_state *st = iio_priv(indio_dev); - unsigned int shift, reg, offset; - int ret; - - ret = ad5755_chan_reg_info(st, chan, info, true, - ®, &shift, &offset); - if (ret) - return ret; - - val <<= shift; - val += offset; - - if (val < 0 || val > 0xffff) - return -EINVAL; - - return ad5755_write(indio_dev, reg, val); -} - -static ssize_t ad5755_read_powerdown(struct iio_dev *indio_dev, uintptr_t priv, - const struct iio_chan_spec *chan, char *buf) -{ - struct ad5755_state *st = iio_priv(indio_dev); - - return sprintf(buf, "%d\n", - (bool)(st->pwr_down & (1 << chan->channel))); -} - -static ssize_t ad5755_write_powerdown(struct iio_dev *indio_dev, uintptr_t priv, - struct iio_chan_spec const *chan, const char *buf, size_t len) -{ - bool pwr_down; - int ret; - - ret = strtobool(buf, &pwr_down); - if (ret) - return ret; - - ret = ad5755_set_channel_pwr_down(indio_dev, chan->channel, pwr_down); - return ret ? ret : len; -} - -static const struct iio_info ad5755_info = { - .read_raw = ad5755_read_raw, - .write_raw = ad5755_write_raw, - .driver_module = THIS_MODULE, -}; - -static const struct iio_chan_spec_ext_info ad5755_ext_info[] = { - { - .name = "powerdown", - .read = ad5755_read_powerdown, - .write = ad5755_write_powerdown, - }, - { }, -}; - -#define AD5755_CHANNEL(_bits) { \ - .indexed = 1, \ - .output = 1, \ - .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \ - IIO_CHAN_INFO_SCALE_SEPARATE_BIT | \ - IIO_CHAN_INFO_OFFSET_SEPARATE_BIT | \ - IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT | \ - IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT, \ - .scan_type = IIO_ST('u', (_bits), 16, 16 - (_bits)), \ - .ext_info = ad5755_ext_info, \ -} - -static const struct ad5755_chip_info ad5755_chip_info_tbl[] = { - [ID_AD5735] = { - .channel_template = AD5755_CHANNEL(14), - .has_voltage_out = true, - .calib_shift = 4, - }, - [ID_AD5737] = { - .channel_template = AD5755_CHANNEL(14), - .has_voltage_out = false, - .calib_shift = 4, - }, - [ID_AD5755] = { - .channel_template = AD5755_CHANNEL(16), - .has_voltage_out = true, - .calib_shift = 0, - }, - [ID_AD5757] = { - .channel_template = AD5755_CHANNEL(16), - .has_voltage_out = false, - .calib_shift = 0, - }, -}; - -static bool ad5755_is_valid_mode(struct ad5755_state *st, enum ad5755_mode mode) -{ - switch (mode) { - case AD5755_MODE_VOLTAGE_0V_5V: - case AD5755_MODE_VOLTAGE_0V_10V: - case AD5755_MODE_VOLTAGE_PLUSMINUS_5V: - case AD5755_MODE_VOLTAGE_PLUSMINUS_10V: - return st->chip_info->has_voltage_out; - case AD5755_MODE_CURRENT_4mA_20mA: - case AD5755_MODE_CURRENT_0mA_20mA: - case AD5755_MODE_CURRENT_0mA_24mA: - return true; - default: - return false; - } -} - -static int __devinit ad5755_setup_pdata(struct iio_dev *indio_dev, - const struct ad5755_platform_data *pdata) -{ - struct ad5755_state *st = iio_priv(indio_dev); - unsigned int val; - unsigned int i; - int ret; - - if (pdata->dc_dc_phase > AD5755_DC_DC_PHASE_90_DEGREE || - pdata->dc_dc_freq > AD5755_DC_DC_FREQ_650kHZ || - pdata->dc_dc_maxv > AD5755_DC_DC_MAXV_29V5) - return -EINVAL; - - val = pdata->dc_dc_maxv << AD5755_DC_DC_MAXV; - val |= pdata->dc_dc_freq << AD5755_DC_DC_FREQ_SHIFT; - val |= pdata->dc_dc_phase << AD5755_DC_DC_PHASE_SHIFT; - if (pdata->ext_dc_dc_compenstation_resistor) - val |= AD5755_EXT_DC_DC_COMP_RES; - - ret = ad5755_write_ctrl(indio_dev, 0, AD5755_CTRL_REG_DC_DC, val); - if (ret < 0) - return ret; - - for (i = 0; i < ARRAY_SIZE(pdata->dac); ++i) { - val = pdata->dac[i].slew.step_size << - AD5755_SLEW_STEP_SIZE_SHIFT; - val |= pdata->dac[i].slew.rate << - AD5755_SLEW_RATE_SHIFT; - if (pdata->dac[i].slew.enable) - val |= AD5755_SLEW_ENABLE; - - ret = ad5755_write_ctrl(indio_dev, i, - AD5755_CTRL_REG_SLEW, val); - if (ret < 0) - return ret; - } - - for (i = 0; i < ARRAY_SIZE(pdata->dac); ++i) { - if (!ad5755_is_valid_mode(st, pdata->dac[i].mode)) - return -EINVAL; - - val = 0; - if (!pdata->dac[i].ext_current_sense_resistor) - val |= AD5755_DAC_INT_CURRENT_SENSE_RESISTOR; - if (pdata->dac[i].enable_voltage_overrange) - val |= AD5755_DAC_VOLTAGE_OVERRANGE_EN; - val |= pdata->dac[i].mode; - - ret = ad5755_update_dac_ctrl(indio_dev, i, val, 0); - if (ret < 0) - return ret; - } - - return 0; -} - -static bool __devinit ad5755_is_voltage_mode(enum ad5755_mode mode) -{ - switch (mode) { - case AD5755_MODE_VOLTAGE_0V_5V: - case AD5755_MODE_VOLTAGE_0V_10V: - case AD5755_MODE_VOLTAGE_PLUSMINUS_5V: - case AD5755_MODE_VOLTAGE_PLUSMINUS_10V: - return true; - default: - return false; - } -} - -static int __devinit ad5755_init_channels(struct iio_dev *indio_dev, - const struct ad5755_platform_data *pdata) -{ - struct ad5755_state *st = iio_priv(indio_dev); - struct iio_chan_spec *channels = st->channels; - unsigned int i; - - for (i = 0; i < AD5755_NUM_CHANNELS; ++i) { - channels[i] = st->chip_info->channel_template; - channels[i].channel = i; - channels[i].address = i; - if (pdata && ad5755_is_voltage_mode(pdata->dac[i].mode)) - channels[i].type = IIO_VOLTAGE; - else - channels[i].type = IIO_CURRENT; - } - - indio_dev->channels = channels; - - return 0; -} - -#define AD5755_DEFAULT_DAC_PDATA { \ - .mode = AD5755_MODE_CURRENT_4mA_20mA, \ - .ext_current_sense_resistor = true, \ - .enable_voltage_overrange = false, \ - .slew = { \ - .enable = false, \ - .rate = AD5755_SLEW_RATE_64k, \ - .step_size = AD5755_SLEW_STEP_SIZE_1, \ - }, \ - } - -static const struct ad5755_platform_data ad5755_default_pdata = { - .ext_dc_dc_compenstation_resistor = false, - .dc_dc_phase = AD5755_DC_DC_PHASE_ALL_SAME_EDGE, - .dc_dc_freq = AD5755_DC_DC_FREQ_410kHZ, - .dc_dc_maxv = AD5755_DC_DC_MAXV_23V, - .dac = { - [0] = AD5755_DEFAULT_DAC_PDATA, - [1] = AD5755_DEFAULT_DAC_PDATA, - [2] = AD5755_DEFAULT_DAC_PDATA, - [3] = AD5755_DEFAULT_DAC_PDATA, - }, -}; - -static int __devinit ad5755_probe(struct spi_device *spi) -{ - enum ad5755_type type = spi_get_device_id(spi)->driver_data; - const struct ad5755_platform_data *pdata = dev_get_platdata(&spi->dev); - struct iio_dev *indio_dev; - struct ad5755_state *st; - int ret; - - indio_dev = iio_device_alloc(sizeof(*st)); - if (indio_dev == NULL) { - dev_err(&spi->dev, "Failed to allocate iio device\n"); - return -ENOMEM; - } - - st = iio_priv(indio_dev); - spi_set_drvdata(spi, indio_dev); - - st->chip_info = &ad5755_chip_info_tbl[type]; - st->spi = spi; - st->pwr_down = 0xf; - - indio_dev->dev.parent = &spi->dev; - indio_dev->name = spi_get_device_id(spi)->name; - indio_dev->info = &ad5755_info; - indio_dev->modes = INDIO_DIRECT_MODE; - indio_dev->num_channels = AD5755_NUM_CHANNELS; - - if (!pdata) - pdata = &ad5755_default_pdata; - - ret = ad5755_init_channels(indio_dev, pdata); - if (ret) - goto error_free; - - ret = ad5755_setup_pdata(indio_dev, pdata); - if (ret) - goto error_free; - - ret = iio_device_register(indio_dev); - if (ret) { - dev_err(&spi->dev, "Failed to register iio device: %d\n", ret); - goto error_free; - } - - return 0; - -error_free: - iio_device_free(indio_dev); - - return ret; -} - -static int __devexit ad5755_remove(struct spi_device *spi) -{ - struct iio_dev *indio_dev = spi_get_drvdata(spi); - - iio_device_unregister(indio_dev); - iio_device_free(indio_dev); - - return 0; -} - -static const struct spi_device_id ad5755_id[] = { - { "ad5755", ID_AD5755 }, - { "ad5755-1", ID_AD5755 }, - { "ad5757", ID_AD5757 }, - { "ad5735", ID_AD5735 }, - { "ad5737", ID_AD5737 }, - {} -}; -MODULE_DEVICE_TABLE(spi, ad5755_id); - -static struct spi_driver ad5755_driver = { - .driver = { - .name = "ad5755", - .owner = THIS_MODULE, - }, - .probe = ad5755_probe, - .remove = __devexit_p(ad5755_remove), - .id_table = ad5755_id, -}; -module_spi_driver(ad5755_driver); - -MODULE_AUTHOR("Lars-Peter Clausen "); -MODULE_DESCRIPTION("Analog Devices AD5755/55-1/57/35/37 DAC"); -MODULE_LICENSE("GPL v2"); diff --git a/trunk/drivers/iio/frequency/adf4350.c b/trunk/drivers/iio/frequency/adf4350.c index e35bb8f6fe75..59fbb3ae40e7 100644 --- a/trunk/drivers/iio/frequency/adf4350.c +++ b/trunk/drivers/iio/frequency/adf4350.c @@ -129,7 +129,7 @@ static int adf4350_set_freq(struct adf4350_state *st, unsigned long long freq) { struct adf4350_platform_data *pdata = st->pdata; u64 tmp; - u32 div_gcd, prescaler, chspc; + u32 div_gcd, prescaler; u16 mdiv, r_cnt = 0; u8 band_sel_div; @@ -158,20 +158,14 @@ static int adf4350_set_freq(struct adf4350_state *st, unsigned long long freq) if (pdata->ref_div_factor) r_cnt = pdata->ref_div_factor - 1; - chspc = st->chspc; - do { - do { - do { - r_cnt = adf4350_tune_r_cnt(st, r_cnt); - st->r1_mod = st->fpfd / chspc; - if (r_cnt > ADF4350_MAX_R_CNT) { - /* try higher spacing values */ - chspc++; - r_cnt = 0; - } - } while ((st->r1_mod > ADF4350_MAX_MODULUS) && r_cnt); - } while (r_cnt == 0); + r_cnt = adf4350_tune_r_cnt(st, r_cnt); + + st->r1_mod = st->fpfd / st->chspc; + while (st->r1_mod > ADF4350_MAX_MODULUS) { + r_cnt = adf4350_tune_r_cnt(st, r_cnt); + st->r1_mod = st->fpfd / st->chspc; + } tmp = freq * (u64)st->r1_mod + (st->fpfd > 1); do_div(tmp, st->fpfd); /* Div round closest (n + d/2)/d */ @@ -200,7 +194,7 @@ static int adf4350_set_freq(struct adf4350_state *st, unsigned long long freq) st->regs[ADF4350_REG0] = ADF4350_REG0_INT(st->r0_int) | ADF4350_REG0_FRACT(st->r0_fract); - st->regs[ADF4350_REG1] = ADF4350_REG1_PHASE(1) | + st->regs[ADF4350_REG1] = ADF4350_REG1_PHASE(0) | ADF4350_REG1_MOD(st->r1_mod) | prescaler; diff --git a/trunk/drivers/iio/gyro/Kconfig b/trunk/drivers/iio/gyro/Kconfig deleted file mode 100644 index 21e27e2fc68c..000000000000 --- a/trunk/drivers/iio/gyro/Kconfig +++ /dev/null @@ -1,16 +0,0 @@ -# -# IIO Digital Gyroscope Sensor drivers configuration -# -menu "Digital gyroscope sensors" - -config HID_SENSOR_GYRO_3D - depends on HID_SENSOR_HUB - select IIO_BUFFER - select IIO_TRIGGERED_BUFFER - select HID_SENSOR_IIO_COMMON - tristate "HID Gyroscope 3D" - help - Say yes here to build support for the HID SENSOR - Gyroscope 3D. - -endmenu diff --git a/trunk/drivers/iio/gyro/Makefile b/trunk/drivers/iio/gyro/Makefile deleted file mode 100644 index 8a895d9fcbce..000000000000 --- a/trunk/drivers/iio/gyro/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -# -# Makefile for industrial I/O gyroscope sensor drivers -# - -obj-$(CONFIG_HID_SENSOR_GYRO_3D) += hid-sensor-gyro-3d.o diff --git a/trunk/drivers/iio/gyro/hid-sensor-gyro-3d.c b/trunk/drivers/iio/gyro/hid-sensor-gyro-3d.c deleted file mode 100644 index 4c56ada51c39..000000000000 --- a/trunk/drivers/iio/gyro/hid-sensor-gyro-3d.c +++ /dev/null @@ -1,418 +0,0 @@ -/* - * HID Sensors Driver - * Copyright (c) 2012, Intel Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "../common/hid-sensors/hid-sensor-attributes.h" -#include "../common/hid-sensors/hid-sensor-trigger.h" - -/*Format: HID-SENSOR-usage_id_in_hex*/ -/*Usage ID from spec for Gyro-3D: 0x200076*/ -#define DRIVER_NAME "HID-SENSOR-200076" - -enum gyro_3d_channel { - CHANNEL_SCAN_INDEX_X, - CHANNEL_SCAN_INDEX_Y, - CHANNEL_SCAN_INDEX_Z, - GYRO_3D_CHANNEL_MAX, -}; - -struct gyro_3d_state { - struct hid_sensor_hub_callbacks callbacks; - struct hid_sensor_iio_common common_attributes; - struct hid_sensor_hub_attribute_info gyro[GYRO_3D_CHANNEL_MAX]; - u32 gyro_val[GYRO_3D_CHANNEL_MAX]; -}; - -static const u32 gyro_3d_addresses[GYRO_3D_CHANNEL_MAX] = { - HID_USAGE_SENSOR_ANGL_VELOCITY_X_AXIS, - HID_USAGE_SENSOR_ANGL_VELOCITY_Y_AXIS, - HID_USAGE_SENSOR_ANGL_VELOCITY_Z_AXIS -}; - -/* Channel definitions */ -static const struct iio_chan_spec gyro_3d_channels[] = { - { - .type = IIO_ANGL_VEL, - .modified = 1, - .channel2 = IIO_MOD_X, - .info_mask = IIO_CHAN_INFO_OFFSET_SHARED_BIT | - IIO_CHAN_INFO_SCALE_SHARED_BIT | - IIO_CHAN_INFO_SAMP_FREQ_SHARED_BIT | - IIO_CHAN_INFO_HYSTERESIS_SHARED_BIT, - .scan_index = CHANNEL_SCAN_INDEX_X, - }, { - .type = IIO_ANGL_VEL, - .modified = 1, - .channel2 = IIO_MOD_Y, - .info_mask = IIO_CHAN_INFO_OFFSET_SHARED_BIT | - IIO_CHAN_INFO_SCALE_SHARED_BIT | - IIO_CHAN_INFO_SAMP_FREQ_SHARED_BIT | - IIO_CHAN_INFO_HYSTERESIS_SHARED_BIT, - .scan_index = CHANNEL_SCAN_INDEX_Y, - }, { - .type = IIO_ANGL_VEL, - .modified = 1, - .channel2 = IIO_MOD_Z, - .info_mask = IIO_CHAN_INFO_OFFSET_SHARED_BIT | - IIO_CHAN_INFO_SCALE_SHARED_BIT | - IIO_CHAN_INFO_SAMP_FREQ_SHARED_BIT | - IIO_CHAN_INFO_HYSTERESIS_SHARED_BIT, - .scan_index = CHANNEL_SCAN_INDEX_Z, - } -}; - -/* Adjust channel real bits based on report descriptor */ -static void gyro_3d_adjust_channel_bit_mask(struct iio_chan_spec *channels, - int channel, int size) -{ - channels[channel].scan_type.sign = 's'; - /* Real storage bits will change based on the report desc. */ - channels[channel].scan_type.realbits = size * 8; - /* Maximum size of a sample to capture is u32 */ - channels[channel].scan_type.storagebits = sizeof(u32) * 8; -} - -/* Channel read_raw handler */ -static int gyro_3d_read_raw(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, - int *val, int *val2, - long mask) -{ - struct gyro_3d_state *gyro_state = iio_priv(indio_dev); - int report_id = -1; - u32 address; - int ret; - int ret_type; - - *val = 0; - *val2 = 0; - switch (mask) { - case 0: - report_id = gyro_state->gyro[chan->scan_index].report_id; - address = gyro_3d_addresses[chan->scan_index]; - if (report_id >= 0) - *val = sensor_hub_input_attr_get_raw_value( - gyro_state->common_attributes.hsdev, - HID_USAGE_SENSOR_GYRO_3D, address, - report_id); - else { - *val = 0; - return -EINVAL; - } - ret_type = IIO_VAL_INT; - break; - case IIO_CHAN_INFO_SCALE: - *val = gyro_state->gyro[CHANNEL_SCAN_INDEX_X].units; - ret_type = IIO_VAL_INT; - break; - case IIO_CHAN_INFO_OFFSET: - *val = hid_sensor_convert_exponent( - gyro_state->gyro[CHANNEL_SCAN_INDEX_X].unit_expo); - ret_type = IIO_VAL_INT; - break; - case IIO_CHAN_INFO_SAMP_FREQ: - ret = hid_sensor_read_samp_freq_value( - &gyro_state->common_attributes, val, val2); - ret_type = IIO_VAL_INT_PLUS_MICRO; - break; - case IIO_CHAN_INFO_HYSTERESIS: - ret = hid_sensor_read_raw_hyst_value( - &gyro_state->common_attributes, val, val2); - ret_type = IIO_VAL_INT_PLUS_MICRO; - break; - default: - ret_type = -EINVAL; - break; - } - - return ret_type; -} - -/* Channel write_raw handler */ -static int gyro_3d_write_raw(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, - int val, - int val2, - long mask) -{ - struct gyro_3d_state *gyro_state = iio_priv(indio_dev); - int ret = 0; - - switch (mask) { - case IIO_CHAN_INFO_SAMP_FREQ: - ret = hid_sensor_write_samp_freq_value( - &gyro_state->common_attributes, val, val2); - break; - case IIO_CHAN_INFO_HYSTERESIS: - ret = hid_sensor_write_raw_hyst_value( - &gyro_state->common_attributes, val, val2); - break; - default: - ret = -EINVAL; - } - - return ret; -} - -static int gyro_3d_write_raw_get_fmt(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, - long mask) -{ - return IIO_VAL_INT_PLUS_MICRO; -} - -static const struct iio_info gyro_3d_info = { - .driver_module = THIS_MODULE, - .read_raw = &gyro_3d_read_raw, - .write_raw = &gyro_3d_write_raw, - .write_raw_get_fmt = &gyro_3d_write_raw_get_fmt, -}; - -/* Function to push data to buffer */ -static void hid_sensor_push_data(struct iio_dev *indio_dev, u8 *data, int len) -{ - struct iio_buffer *buffer = indio_dev->buffer; - int datum_sz; - - dev_dbg(&indio_dev->dev, "hid_sensor_push_data\n"); - if (!buffer) { - dev_err(&indio_dev->dev, "Buffer == NULL\n"); - return; - } - datum_sz = buffer->access->get_bytes_per_datum(buffer); - if (len > datum_sz) { - dev_err(&indio_dev->dev, "Datum size mismatch %d:%d\n", len, - datum_sz); - return; - } - iio_push_to_buffer(buffer, (u8 *)data); -} - -/* Callback handler to send event after all samples are received and captured */ -static int gyro_3d_proc_event(struct hid_sensor_hub_device *hsdev, - unsigned usage_id, - void *priv) -{ - struct iio_dev *indio_dev = platform_get_drvdata(priv); - struct gyro_3d_state *gyro_state = iio_priv(indio_dev); - - dev_dbg(&indio_dev->dev, "gyro_3d_proc_event [%d]\n", - gyro_state->common_attributes.data_ready); - if (gyro_state->common_attributes.data_ready) - hid_sensor_push_data(indio_dev, - (u8 *)gyro_state->gyro_val, - sizeof(gyro_state->gyro_val)); - - return 0; -} - -/* Capture samples in local storage */ -static int gyro_3d_capture_sample(struct hid_sensor_hub_device *hsdev, - unsigned usage_id, - size_t raw_len, char *raw_data, - void *priv) -{ - struct iio_dev *indio_dev = platform_get_drvdata(priv); - struct gyro_3d_state *gyro_state = iio_priv(indio_dev); - int offset; - int ret = -EINVAL; - - switch (usage_id) { - case HID_USAGE_SENSOR_ANGL_VELOCITY_X_AXIS: - case HID_USAGE_SENSOR_ANGL_VELOCITY_Y_AXIS: - case HID_USAGE_SENSOR_ANGL_VELOCITY_Z_AXIS: - offset = usage_id - HID_USAGE_SENSOR_ANGL_VELOCITY_X_AXIS; - gyro_state->gyro_val[CHANNEL_SCAN_INDEX_X + offset] = - *(u32 *)raw_data; - ret = 0; - break; - default: - break; - } - - return ret; -} - -/* Parse report which is specific to an usage id*/ -static int gyro_3d_parse_report(struct platform_device *pdev, - struct hid_sensor_hub_device *hsdev, - struct iio_chan_spec *channels, - unsigned usage_id, - struct gyro_3d_state *st) -{ - int ret; - int i; - - for (i = 0; i <= CHANNEL_SCAN_INDEX_Z; ++i) { - ret = sensor_hub_input_get_attribute_info(hsdev, - HID_INPUT_REPORT, - usage_id, - HID_USAGE_SENSOR_ANGL_VELOCITY_X_AXIS + i, - &st->gyro[CHANNEL_SCAN_INDEX_X + i]); - if (ret < 0) - break; - gyro_3d_adjust_channel_bit_mask(channels, - CHANNEL_SCAN_INDEX_X + i, - st->gyro[CHANNEL_SCAN_INDEX_X + i].size); - } - dev_dbg(&pdev->dev, "gyro_3d %x:%x, %x:%x, %x:%x\n", - st->gyro[0].index, - st->gyro[0].report_id, - st->gyro[1].index, st->gyro[1].report_id, - st->gyro[2].index, st->gyro[2].report_id); - - return ret; -} - -/* Function to initialize the processing for usage id */ -static int __devinit hid_gyro_3d_probe(struct platform_device *pdev) -{ - int ret = 0; - static const char *name = "gyro_3d"; - struct iio_dev *indio_dev; - struct gyro_3d_state *gyro_state; - struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data; - struct iio_chan_spec *channels; - - indio_dev = iio_device_alloc(sizeof(struct gyro_3d_state)); - if (indio_dev == NULL) { - ret = -ENOMEM; - goto error_ret; - } - platform_set_drvdata(pdev, indio_dev); - - gyro_state = iio_priv(indio_dev); - gyro_state->common_attributes.hsdev = hsdev; - gyro_state->common_attributes.pdev = pdev; - - ret = hid_sensor_parse_common_attributes(hsdev, - HID_USAGE_SENSOR_GYRO_3D, - &gyro_state->common_attributes); - if (ret) { - dev_err(&pdev->dev, "failed to setup common attributes\n"); - goto error_free_dev; - } - - channels = kmemdup(gyro_3d_channels, - sizeof(gyro_3d_channels), - GFP_KERNEL); - if (!channels) { - dev_err(&pdev->dev, "failed to duplicate channels\n"); - goto error_free_dev; - } - - ret = gyro_3d_parse_report(pdev, hsdev, channels, - HID_USAGE_SENSOR_GYRO_3D, gyro_state); - if (ret) { - dev_err(&pdev->dev, "failed to setup attributes\n"); - goto error_free_dev_mem; - } - - indio_dev->channels = channels; - indio_dev->num_channels = ARRAY_SIZE(gyro_3d_channels); - indio_dev->dev.parent = &pdev->dev; - indio_dev->info = &gyro_3d_info; - indio_dev->name = name; - indio_dev->modes = INDIO_DIRECT_MODE; - - ret = iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time, - NULL, NULL); - if (ret) { - dev_err(&pdev->dev, "failed to initialize trigger buffer\n"); - goto error_free_dev_mem; - } - gyro_state->common_attributes.data_ready = false; - ret = hid_sensor_setup_trigger(indio_dev, name, - &gyro_state->common_attributes); - if (ret < 0) { - dev_err(&pdev->dev, "trigger setup failed\n"); - goto error_unreg_buffer_funcs; - } - - ret = iio_device_register(indio_dev); - if (ret) { - dev_err(&pdev->dev, "device register failed\n"); - goto error_remove_trigger; - } - - gyro_state->callbacks.send_event = gyro_3d_proc_event; - gyro_state->callbacks.capture_sample = gyro_3d_capture_sample; - gyro_state->callbacks.pdev = pdev; - ret = sensor_hub_register_callback(hsdev, HID_USAGE_SENSOR_GYRO_3D, - &gyro_state->callbacks); - if (ret < 0) { - dev_err(&pdev->dev, "callback reg failed\n"); - goto error_iio_unreg; - } - - return ret; - -error_iio_unreg: - iio_device_unregister(indio_dev); -error_remove_trigger: - hid_sensor_remove_trigger(indio_dev); -error_unreg_buffer_funcs: - iio_triggered_buffer_cleanup(indio_dev); -error_free_dev_mem: - kfree(indio_dev->channels); -error_free_dev: - iio_device_free(indio_dev); -error_ret: - return ret; -} - -/* Function to deinitialize the processing for usage id */ -static int __devinit hid_gyro_3d_remove(struct platform_device *pdev) -{ - struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data; - struct iio_dev *indio_dev = platform_get_drvdata(pdev); - - sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_GYRO_3D); - iio_device_unregister(indio_dev); - hid_sensor_remove_trigger(indio_dev); - iio_triggered_buffer_cleanup(indio_dev); - kfree(indio_dev->channels); - iio_device_free(indio_dev); - - return 0; -} - -static struct platform_driver hid_gyro_3d_platform_driver = { - .driver = { - .name = DRIVER_NAME, - .owner = THIS_MODULE, - }, - .probe = hid_gyro_3d_probe, - .remove = hid_gyro_3d_remove, -}; -module_platform_driver(hid_gyro_3d_platform_driver); - -MODULE_DESCRIPTION("HID Sensor Gyroscope 3D"); -MODULE_AUTHOR("Srinivas Pandruvada "); -MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/iio/industrialio-buffer.c b/trunk/drivers/iio/industrialio-buffer.c index d4ad37455a67..4add9bb40eeb 100644 --- a/trunk/drivers/iio/industrialio-buffer.c +++ b/trunk/drivers/iio/industrialio-buffer.c @@ -422,7 +422,7 @@ ssize_t iio_buffer_store_enable(struct device *dev, ret = indio_dev->setup_ops->preenable(indio_dev); if (ret) { printk(KERN_ERR - "Buffer not started: " + "Buffer not started:" "buffer preenable failed\n"); goto error_ret; } @@ -431,12 +431,12 @@ ssize_t iio_buffer_store_enable(struct device *dev, ret = buffer->access->request_update(buffer); if (ret) { printk(KERN_INFO - "Buffer not started: " + "Buffer not started:" "buffer parameter update failed\n"); goto error_ret; } } - /* Definitely possible for devices to support both of these. */ + /* Definitely possible for devices to support both of these.*/ if (indio_dev->modes & INDIO_BUFFER_TRIGGERED) { if (!indio_dev->trig) { printk(KERN_INFO @@ -456,7 +456,7 @@ ssize_t iio_buffer_store_enable(struct device *dev, ret = indio_dev->setup_ops->postenable(indio_dev); if (ret) { printk(KERN_INFO - "Buffer not started: " + "Buffer not started:" "postenable failed\n"); indio_dev->currentmode = previous_mode; if (indio_dev->setup_ops->postdisable) @@ -657,7 +657,7 @@ EXPORT_SYMBOL_GPL(iio_scan_mask_query); /** * struct iio_demux_table() - table describing demux memcpy ops * @from: index to copy from - * @to: index to copy to + * @to: index to copy to * @length: how many bytes to copy * @l: list head used for management */ @@ -682,11 +682,12 @@ static unsigned char *iio_demux(struct iio_buffer *buffer, return buffer->demux_bounce; } -int iio_push_to_buffer(struct iio_buffer *buffer, unsigned char *data) +int iio_push_to_buffer(struct iio_buffer *buffer, unsigned char *data, + s64 timestamp) { unsigned char *dataout = iio_demux(buffer, data); - return buffer->access->store_to(buffer, dataout); + return buffer->access->store_to(buffer, dataout, timestamp); } EXPORT_SYMBOL_GPL(iio_push_to_buffer); diff --git a/trunk/drivers/iio/industrialio-core.c b/trunk/drivers/iio/industrialio-core.c index 6eb24dbc081e..2ec266ef41a3 100644 --- a/trunk/drivers/iio/industrialio-core.c +++ b/trunk/drivers/iio/industrialio-core.c @@ -29,7 +29,7 @@ #include #include -/* IDA to assign each registered device a unique id */ +/* IDA to assign each registered device a unique id*/ static DEFINE_IDA(iio_ida); static dev_t iio_devt; @@ -99,7 +99,6 @@ static const char * const iio_chan_info_postfix[] = { [IIO_CHAN_INFO_FREQUENCY] = "frequency", [IIO_CHAN_INFO_PHASE] = "phase", [IIO_CHAN_INFO_HARDWAREGAIN] = "hardwaregain", - [IIO_CHAN_INFO_HYSTERESIS] = "hysteresis", }; const struct iio_chan_spec @@ -366,7 +365,6 @@ static ssize_t iio_read_channel_info(struct device *dev, { struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - unsigned long long tmp; int val, val2; bool scale_db = false; int ret = indio_dev->info->read_raw(indio_dev, this_attr->c, @@ -392,11 +390,6 @@ static ssize_t iio_read_channel_info(struct device *dev, return sprintf(buf, "-%d.%09u\n", val, -val2); else return sprintf(buf, "%d.%09u\n", val, val2); - case IIO_VAL_FRACTIONAL: - tmp = div_s64((s64)val * 1000000000LL, val2); - val2 = do_div(tmp, 1000000000LL); - val = tmp; - return sprintf(buf, "%d.%09u\n", val, val2); default: return 0; } @@ -736,7 +729,7 @@ static int iio_device_register_sysfs(struct iio_dev *indio_dev) attrcount = attrcount_orig; /* * New channel registration method - relies on the fact a group does - * not need to be initialized if its name is NULL. + * not need to be initialized if it is name is NULL. */ if (indio_dev->channels) for (i = 0; i < indio_dev->num_channels; i++) { @@ -987,6 +980,6 @@ EXPORT_SYMBOL(iio_device_unregister); subsys_initcall(iio_init); module_exit(iio_exit); -MODULE_AUTHOR("Jonathan Cameron "); +MODULE_AUTHOR("Jonathan Cameron "); MODULE_DESCRIPTION("Industrial I/O core"); MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/iio/inkern.c b/trunk/drivers/iio/inkern.c index f2b78d4fe457..b5afc2ff34fd 100644 --- a/trunk/drivers/iio/inkern.c +++ b/trunk/drivers/iio/inkern.c @@ -111,7 +111,6 @@ struct iio_channel *iio_channel_get(const char *name, const char *channel_name) { struct iio_map_internal *c_i = NULL, *c = NULL; struct iio_channel *channel; - int err; if (name == NULL && channel_name == NULL) return ERR_PTR(-ENODEV); @@ -131,32 +130,18 @@ struct iio_channel *iio_channel_get(const char *name, const char *channel_name) if (c == NULL) return ERR_PTR(-ENODEV); - channel = kzalloc(sizeof(*channel), GFP_KERNEL); - if (channel == NULL) { - err = -ENOMEM; - goto error_no_mem; - } + channel = kmalloc(sizeof(*channel), GFP_KERNEL); + if (channel == NULL) + return ERR_PTR(-ENOMEM); channel->indio_dev = c->indio_dev; - if (c->map->adc_channel_label) { + if (c->map->adc_channel_label) channel->channel = iio_chan_spec_from_name(channel->indio_dev, c->map->adc_channel_label); - if (channel->channel == NULL) { - err = -EINVAL; - goto error_no_chan; - } - } - return channel; - -error_no_chan: - kfree(channel); -error_no_mem: - iio_device_put(c->indio_dev); - return ERR_PTR(err); } EXPORT_SYMBOL_GPL(iio_channel_get); @@ -244,21 +229,9 @@ void iio_channel_release_all(struct iio_channel *channels) } EXPORT_SYMBOL_GPL(iio_channel_release_all); -static int iio_channel_read(struct iio_channel *chan, int *val, int *val2, - enum iio_chan_info_enum info) -{ - int unused; - - if (val2 == NULL) - val2 = &unused; - - return chan->indio_dev->info->read_raw(chan->indio_dev, chan->channel, - val, val2, info); -} - int iio_read_channel_raw(struct iio_channel *chan, int *val) { - int ret; + int val2, ret; mutex_lock(&chan->indio_dev->info_exist_lock); if (chan->indio_dev->info == NULL) { @@ -266,7 +239,8 @@ int iio_read_channel_raw(struct iio_channel *chan, int *val) goto err_unlock; } - ret = iio_channel_read(chan, val, NULL, IIO_CHAN_INFO_RAW); + ret = chan->indio_dev->info->read_raw(chan->indio_dev, chan->channel, + val, &val2, 0); err_unlock: mutex_unlock(&chan->indio_dev->info_exist_lock); @@ -274,100 +248,6 @@ int iio_read_channel_raw(struct iio_channel *chan, int *val) } EXPORT_SYMBOL_GPL(iio_read_channel_raw); -static int iio_convert_raw_to_processed_unlocked(struct iio_channel *chan, - int raw, int *processed, unsigned int scale) -{ - int scale_type, scale_val, scale_val2, offset; - s64 raw64 = raw; - int ret; - - ret = iio_channel_read(chan, &offset, NULL, IIO_CHAN_INFO_SCALE); - if (ret == 0) - raw64 += offset; - - scale_type = iio_channel_read(chan, &scale_val, &scale_val2, - IIO_CHAN_INFO_SCALE); - if (scale_type < 0) - return scale_type; - - switch (scale_type) { - case IIO_VAL_INT: - *processed = raw64 * scale_val; - break; - case IIO_VAL_INT_PLUS_MICRO: - if (scale_val2 < 0) - *processed = -raw64 * scale_val; - else - *processed = raw64 * scale_val; - *processed += div_s64(raw64 * (s64)scale_val2 * scale, - 1000000LL); - break; - case IIO_VAL_INT_PLUS_NANO: - if (scale_val2 < 0) - *processed = -raw64 * scale_val; - else - *processed = raw64 * scale_val; - *processed += div_s64(raw64 * (s64)scale_val2 * scale, - 1000000000LL); - break; - case IIO_VAL_FRACTIONAL: - *processed = div_s64(raw64 * (s64)scale_val * scale, - scale_val2); - break; - default: - return -EINVAL; - } - - return 0; -} - -int iio_convert_raw_to_processed(struct iio_channel *chan, int raw, - int *processed, unsigned int scale) -{ - int ret; - - mutex_lock(&chan->indio_dev->info_exist_lock); - if (chan->indio_dev->info == NULL) { - ret = -ENODEV; - goto err_unlock; - } - - ret = iio_convert_raw_to_processed_unlocked(chan, raw, processed, - scale); -err_unlock: - mutex_unlock(&chan->indio_dev->info_exist_lock); - - return ret; -} -EXPORT_SYMBOL_GPL(iio_convert_raw_to_processed); - -int iio_read_channel_processed(struct iio_channel *chan, int *val) -{ - int ret; - - mutex_lock(&chan->indio_dev->info_exist_lock); - if (chan->indio_dev->info == NULL) { - ret = -ENODEV; - goto err_unlock; - } - - if (iio_channel_has_info(chan->channel, IIO_CHAN_INFO_PROCESSED)) { - ret = iio_channel_read(chan, val, NULL, - IIO_CHAN_INFO_PROCESSED); - } else { - ret = iio_channel_read(chan, val, NULL, IIO_CHAN_INFO_RAW); - if (ret < 0) - goto err_unlock; - ret = iio_convert_raw_to_processed_unlocked(chan, *val, val, 1); - } - -err_unlock: - mutex_unlock(&chan->indio_dev->info_exist_lock); - - return ret; -} -EXPORT_SYMBOL_GPL(iio_read_channel_processed); - int iio_read_channel_scale(struct iio_channel *chan, int *val, int *val2) { int ret; @@ -378,7 +258,10 @@ int iio_read_channel_scale(struct iio_channel *chan, int *val, int *val2) goto err_unlock; } - ret = iio_channel_read(chan, val, val2, IIO_CHAN_INFO_SCALE); + ret = chan->indio_dev->info->read_raw(chan->indio_dev, + chan->channel, + val, val2, + IIO_CHAN_INFO_SCALE); err_unlock: mutex_unlock(&chan->indio_dev->info_exist_lock); diff --git a/trunk/drivers/iio/kfifo_buf.c b/trunk/drivers/iio/kfifo_buf.c index 5bc5c860e9ca..6bf9d05f4841 100644 --- a/trunk/drivers/iio/kfifo_buf.c +++ b/trunk/drivers/iio/kfifo_buf.c @@ -6,7 +6,6 @@ #include #include #include -#include struct iio_kfifo { struct iio_buffer buffer; @@ -23,8 +22,7 @@ static inline int __iio_allocate_kfifo(struct iio_kfifo *buf, return -EINVAL; __iio_update_buffer(&buf->buffer, bytes_per_datum, length); - return __kfifo_alloc((struct __kfifo *)&buf->kf, length, - bytes_per_datum, GFP_KERNEL); + return kfifo_alloc(&buf->kf, bytes_per_datum*length, GFP_KERNEL); } static int iio_request_update_kfifo(struct iio_buffer *r) @@ -37,7 +35,6 @@ static int iio_request_update_kfifo(struct iio_buffer *r) kfifo_free(&buf->kf); ret = __iio_allocate_kfifo(buf, buf->buffer.bytes_per_datum, buf->buffer.length); - r->stufftoread = false; error_ret: return ret; } @@ -84,9 +81,6 @@ static int iio_set_bytes_per_datum_kfifo(struct iio_buffer *r, size_t bpd) static int iio_set_length_kfifo(struct iio_buffer *r, int length) { - /* Avoid an invalid state */ - if (length < 2) - length = 2; if (r->length != length) { r->length = length; iio_mark_update_needed_kfifo(r); @@ -95,16 +89,14 @@ static int iio_set_length_kfifo(struct iio_buffer *r, int length) } static int iio_store_to_kfifo(struct iio_buffer *r, - u8 *data) + u8 *data, + s64 timestamp) { int ret; struct iio_kfifo *kf = iio_to_kfifo(r); - ret = kfifo_in(&kf->kf, data, 1); - if (ret != 1) + ret = kfifo_in(&kf->kf, data, r->bytes_per_datum); + if (ret != r->bytes_per_datum) return -EBUSY; - r->stufftoread = true; - wake_up_interruptible(&r->pollq); - return 0; } @@ -114,18 +106,11 @@ static int iio_read_first_n_kfifo(struct iio_buffer *r, int ret, copied; struct iio_kfifo *kf = iio_to_kfifo(r); - if (n < r->bytes_per_datum || r->bytes_per_datum == 0) + if (n < r->bytes_per_datum) return -EINVAL; + n = rounddown(n, r->bytes_per_datum); ret = kfifo_to_user(&kf->kf, buf, n, &copied); - if (ret < 0) - return ret; - - if (kfifo_is_empty(&kf->kf)) - r->stufftoread = false; - /* verify it is still empty to avoid race */ - if (!kfifo_is_empty(&kf->kf)) - r->stufftoread = true; return copied; } @@ -151,7 +136,7 @@ struct iio_buffer *iio_kfifo_allocate(struct iio_dev *indio_dev) iio_buffer_init(&kf->buffer); kf->buffer.attrs = &iio_kfifo_attribute_group; kf->buffer.access = &kfifo_access_funcs; - kf->buffer.length = 2; + return &kf->buffer; } EXPORT_SYMBOL(iio_kfifo_allocate); diff --git a/trunk/drivers/iio/light/Kconfig b/trunk/drivers/iio/light/Kconfig index 1763c9bcb98a..91d15d2f694f 100644 --- a/trunk/drivers/iio/light/Kconfig +++ b/trunk/drivers/iio/light/Kconfig @@ -42,14 +42,4 @@ config VCNL4000 To compile this driver as a module, choose M here: the module will be called vcnl4000. -config HID_SENSOR_ALS - depends on HID_SENSOR_HUB - select IIO_BUFFER - select IIO_TRIGGERED_BUFFER - select HID_SENSOR_IIO_COMMON - tristate "HID ALS" - help - Say yes here to build support for the HID SENSOR - Ambient light sensor. - endmenu diff --git a/trunk/drivers/iio/light/Makefile b/trunk/drivers/iio/light/Makefile index 21a8f0df1407..13f8a782d292 100644 --- a/trunk/drivers/iio/light/Makefile +++ b/trunk/drivers/iio/light/Makefile @@ -5,4 +5,3 @@ obj-$(CONFIG_ADJD_S311) += adjd_s311.o obj-$(CONFIG_SENSORS_LM3533) += lm3533-als.o obj-$(CONFIG_VCNL4000) += vcnl4000.o -obj-$(CONFIG_HID_SENSOR_ALS) += hid-sensor-als.o diff --git a/trunk/drivers/iio/light/adjd_s311.c b/trunk/drivers/iio/light/adjd_s311.c index 164b62b91a4b..1cbb449b319a 100644 --- a/trunk/drivers/iio/light/adjd_s311.c +++ b/trunk/drivers/iio/light/adjd_s311.c @@ -187,7 +187,7 @@ static irqreturn_t adjd_s311_trigger_handler(int irq, void *p) if (indio_dev->scan_timestamp) *(s64 *)((u8 *)data->buffer + ALIGN(len, sizeof(s64))) = time_ns; - iio_push_to_buffer(buffer, (u8 *)data->buffer); + iio_push_to_buffer(buffer, (u8 *)data->buffer, time_ns); done: iio_trigger_notify_done(indio_dev->trig); @@ -271,10 +271,9 @@ static int adjd_s311_update_scan_mode(struct iio_dev *indio_dev, const unsigned long *scan_mask) { struct adjd_s311_data *data = iio_priv(indio_dev); - - kfree(data->buffer); - data->buffer = kmalloc(indio_dev->scan_bytes, GFP_KERNEL); - if (data->buffer == NULL) + data->buffer = krealloc(data->buffer, indio_dev->scan_bytes, + GFP_KERNEL); + if (!data->buffer) return -ENOMEM; return 0; diff --git a/trunk/drivers/iio/light/hid-sensor-als.c b/trunk/drivers/iio/light/hid-sensor-als.c deleted file mode 100644 index 96e3691e42c4..000000000000 --- a/trunk/drivers/iio/light/hid-sensor-als.c +++ /dev/null @@ -1,385 +0,0 @@ -/* - * HID Sensors Driver - * Copyright (c) 2012, Intel Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "../common/hid-sensors/hid-sensor-attributes.h" -#include "../common/hid-sensors/hid-sensor-trigger.h" - -/*Format: HID-SENSOR-usage_id_in_hex*/ -/*Usage ID from spec for Accelerometer-3D: 0x200041*/ -#define DRIVER_NAME "HID-SENSOR-200041" - -#define CHANNEL_SCAN_INDEX_ILLUM 0 - -struct als_state { - struct hid_sensor_hub_callbacks callbacks; - struct hid_sensor_iio_common common_attributes; - struct hid_sensor_hub_attribute_info als_illum; - u32 illum; -}; - -/* Channel definitions */ -static const struct iio_chan_spec als_channels[] = { - { - .type = IIO_INTENSITY, - .modified = 1, - .channel2 = IIO_MOD_LIGHT_BOTH, - .info_mask = IIO_CHAN_INFO_OFFSET_SHARED_BIT | - IIO_CHAN_INFO_SCALE_SHARED_BIT | - IIO_CHAN_INFO_SAMP_FREQ_SHARED_BIT | - IIO_CHAN_INFO_HYSTERESIS_SHARED_BIT, - .scan_index = CHANNEL_SCAN_INDEX_ILLUM, - } -}; - -/* Adjust channel real bits based on report descriptor */ -static void als_adjust_channel_bit_mask(struct iio_chan_spec *channels, - int channel, int size) -{ - channels[channel].scan_type.sign = 's'; - /* Real storage bits will change based on the report desc. */ - channels[channel].scan_type.realbits = size * 8; - /* Maximum size of a sample to capture is u32 */ - channels[channel].scan_type.storagebits = sizeof(u32) * 8; -} - -/* Channel read_raw handler */ -static int als_read_raw(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, - int *val, int *val2, - long mask) -{ - struct als_state *als_state = iio_priv(indio_dev); - int report_id = -1; - u32 address; - int ret; - int ret_type; - - *val = 0; - *val2 = 0; - switch (mask) { - case 0: - switch (chan->scan_index) { - case CHANNEL_SCAN_INDEX_ILLUM: - report_id = als_state->als_illum.report_id; - address = - HID_USAGE_SENSOR_LIGHT_ILLUM; - break; - default: - report_id = -1; - break; - } - if (report_id >= 0) - *val = sensor_hub_input_attr_get_raw_value( - als_state->common_attributes.hsdev, - HID_USAGE_SENSOR_ALS, address, - report_id); - else { - *val = 0; - return -EINVAL; - } - ret_type = IIO_VAL_INT; - break; - case IIO_CHAN_INFO_SCALE: - *val = als_state->als_illum.units; - ret_type = IIO_VAL_INT; - break; - case IIO_CHAN_INFO_OFFSET: - *val = hid_sensor_convert_exponent( - als_state->als_illum.unit_expo); - ret_type = IIO_VAL_INT; - break; - case IIO_CHAN_INFO_SAMP_FREQ: - ret = hid_sensor_read_samp_freq_value( - &als_state->common_attributes, val, val2); - ret_type = IIO_VAL_INT_PLUS_MICRO; - break; - case IIO_CHAN_INFO_HYSTERESIS: - ret = hid_sensor_read_raw_hyst_value( - &als_state->common_attributes, val, val2); - ret_type = IIO_VAL_INT_PLUS_MICRO; - break; - default: - ret_type = -EINVAL; - break; - } - - return ret_type; -} - -/* Channel write_raw handler */ -static int als_write_raw(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, - int val, - int val2, - long mask) -{ - struct als_state *als_state = iio_priv(indio_dev); - int ret = 0; - - switch (mask) { - case IIO_CHAN_INFO_SAMP_FREQ: - ret = hid_sensor_write_samp_freq_value( - &als_state->common_attributes, val, val2); - break; - case IIO_CHAN_INFO_HYSTERESIS: - ret = hid_sensor_write_raw_hyst_value( - &als_state->common_attributes, val, val2); - break; - default: - ret = -EINVAL; - } - - return ret; -} - -static int als_write_raw_get_fmt(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, - long mask) -{ - return IIO_VAL_INT_PLUS_MICRO; -} - -static const struct iio_info als_info = { - .driver_module = THIS_MODULE, - .read_raw = &als_read_raw, - .write_raw = &als_write_raw, - .write_raw_get_fmt = &als_write_raw_get_fmt, -}; - -/* Function to push data to buffer */ -static void hid_sensor_push_data(struct iio_dev *indio_dev, u8 *data, int len) -{ - struct iio_buffer *buffer = indio_dev->buffer; - int datum_sz; - - dev_dbg(&indio_dev->dev, "hid_sensor_push_data\n"); - if (!buffer) { - dev_err(&indio_dev->dev, "Buffer == NULL\n"); - return; - } - datum_sz = buffer->access->get_bytes_per_datum(buffer); - if (len > datum_sz) { - dev_err(&indio_dev->dev, "Datum size mismatch %d:%d\n", len, - datum_sz); - return; - } - iio_push_to_buffer(buffer, (u8 *)data); -} - -/* Callback handler to send event after all samples are received and captured */ -static int als_proc_event(struct hid_sensor_hub_device *hsdev, - unsigned usage_id, - void *priv) -{ - struct iio_dev *indio_dev = platform_get_drvdata(priv); - struct als_state *als_state = iio_priv(indio_dev); - - dev_dbg(&indio_dev->dev, "als_proc_event [%d]\n", - als_state->common_attributes.data_ready); - if (als_state->common_attributes.data_ready) - hid_sensor_push_data(indio_dev, - (u8 *)&als_state->illum, - sizeof(als_state->illum)); - - return 0; -} - -/* Capture samples in local storage */ -static int als_capture_sample(struct hid_sensor_hub_device *hsdev, - unsigned usage_id, - size_t raw_len, char *raw_data, - void *priv) -{ - struct iio_dev *indio_dev = platform_get_drvdata(priv); - struct als_state *als_state = iio_priv(indio_dev); - int ret = -EINVAL; - - switch (usage_id) { - case HID_USAGE_SENSOR_LIGHT_ILLUM: - als_state->illum = *(u32 *)raw_data; - ret = 0; - break; - default: - break; - } - - return ret; -} - -/* Parse report which is specific to an usage id*/ -static int als_parse_report(struct platform_device *pdev, - struct hid_sensor_hub_device *hsdev, - struct iio_chan_spec *channels, - unsigned usage_id, - struct als_state *st) -{ - int ret; - - ret = sensor_hub_input_get_attribute_info(hsdev, HID_INPUT_REPORT, - usage_id, - HID_USAGE_SENSOR_LIGHT_ILLUM, - &st->als_illum); - if (ret < 0) - return ret; - als_adjust_channel_bit_mask(channels, CHANNEL_SCAN_INDEX_ILLUM, - st->als_illum.size); - - dev_dbg(&pdev->dev, "als %x:%x\n", st->als_illum.index, - st->als_illum.report_id); - - return ret; -} - -/* Function to initialize the processing for usage id */ -static int __devinit hid_als_probe(struct platform_device *pdev) -{ - int ret = 0; - static const char *name = "als"; - struct iio_dev *indio_dev; - struct als_state *als_state; - struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data; - struct iio_chan_spec *channels; - - indio_dev = iio_device_alloc(sizeof(struct als_state)); - if (indio_dev == NULL) { - ret = -ENOMEM; - goto error_ret; - } - platform_set_drvdata(pdev, indio_dev); - - als_state = iio_priv(indio_dev); - als_state->common_attributes.hsdev = hsdev; - als_state->common_attributes.pdev = pdev; - - ret = hid_sensor_parse_common_attributes(hsdev, HID_USAGE_SENSOR_ALS, - &als_state->common_attributes); - if (ret) { - dev_err(&pdev->dev, "failed to setup common attributes\n"); - goto error_free_dev; - } - - channels = kmemdup(als_channels, - sizeof(als_channels), - GFP_KERNEL); - if (!channels) { - dev_err(&pdev->dev, "failed to duplicate channels\n"); - goto error_free_dev; - } - - ret = als_parse_report(pdev, hsdev, channels, - HID_USAGE_SENSOR_ALS, als_state); - if (ret) { - dev_err(&pdev->dev, "failed to setup attributes\n"); - goto error_free_dev_mem; - } - - indio_dev->channels = channels; - indio_dev->num_channels = - ARRAY_SIZE(als_channels); - indio_dev->dev.parent = &pdev->dev; - indio_dev->info = &als_info; - indio_dev->name = name; - indio_dev->modes = INDIO_DIRECT_MODE; - - ret = iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time, - NULL, NULL); - if (ret) { - dev_err(&pdev->dev, "failed to initialize trigger buffer\n"); - goto error_free_dev_mem; - } - als_state->common_attributes.data_ready = false; - ret = hid_sensor_setup_trigger(indio_dev, name, - &als_state->common_attributes); - if (ret < 0) { - dev_err(&pdev->dev, "trigger setup failed\n"); - goto error_unreg_buffer_funcs; - } - - ret = iio_device_register(indio_dev); - if (ret) { - dev_err(&pdev->dev, "device register failed\n"); - goto error_remove_trigger; - } - - als_state->callbacks.send_event = als_proc_event; - als_state->callbacks.capture_sample = als_capture_sample; - als_state->callbacks.pdev = pdev; - ret = sensor_hub_register_callback(hsdev, HID_USAGE_SENSOR_ALS, - &als_state->callbacks); - if (ret < 0) { - dev_err(&pdev->dev, "callback reg failed\n"); - goto error_iio_unreg; - } - - return ret; - -error_iio_unreg: - iio_device_unregister(indio_dev); -error_remove_trigger: - hid_sensor_remove_trigger(indio_dev); -error_unreg_buffer_funcs: - iio_triggered_buffer_cleanup(indio_dev); -error_free_dev_mem: - kfree(indio_dev->channels); -error_free_dev: - iio_device_free(indio_dev); -error_ret: - return ret; -} - -/* Function to deinitialize the processing for usage id */ -static int __devinit hid_als_remove(struct platform_device *pdev) -{ - struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data; - struct iio_dev *indio_dev = platform_get_drvdata(pdev); - - sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_ALS); - iio_device_unregister(indio_dev); - hid_sensor_remove_trigger(indio_dev); - iio_triggered_buffer_cleanup(indio_dev); - kfree(indio_dev->channels); - iio_device_free(indio_dev); - - return 0; -} - -static struct platform_driver hid_als_platform_driver = { - .driver = { - .name = DRIVER_NAME, - .owner = THIS_MODULE, - }, - .probe = hid_als_probe, - .remove = hid_als_remove, -}; -module_platform_driver(hid_als_platform_driver); - -MODULE_DESCRIPTION("HID Sensor ALS"); -MODULE_AUTHOR("Srinivas Pandruvada "); -MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/iio/light/lm3533-als.c b/trunk/drivers/iio/light/lm3533-als.c index e45712a921ce..c3e7bac13123 100644 --- a/trunk/drivers/iio/light/lm3533-als.c +++ b/trunk/drivers/iio/light/lm3533-als.c @@ -404,7 +404,7 @@ static int lm3533_als_get_hysteresis(struct iio_dev *indio_dev, unsigned nr, return ret; } -static ssize_t show_thresh_either_en(struct device *dev, +static int show_thresh_either_en(struct device *dev, struct device_attribute *attr, char *buf) { @@ -424,7 +424,7 @@ static ssize_t show_thresh_either_en(struct device *dev, return scnprintf(buf, PAGE_SIZE, "%u\n", enable); } -static ssize_t store_thresh_either_en(struct device *dev, +static int store_thresh_either_en(struct device *dev, struct device_attribute *attr, const char *buf, size_t len) { diff --git a/trunk/drivers/iio/magnetometer/Kconfig b/trunk/drivers/iio/magnetometer/Kconfig deleted file mode 100644 index c1f0cdd57037..000000000000 --- a/trunk/drivers/iio/magnetometer/Kconfig +++ /dev/null @@ -1,16 +0,0 @@ -# -# Magnetometer sensors -# -menu "Magnetometer sensors" - -config HID_SENSOR_MAGNETOMETER_3D - depends on HID_SENSOR_HUB - select IIO_BUFFER - select IIO_TRIGGERED_BUFFER - select HID_SENSOR_IIO_COMMON - tristate "HID Magenetometer 3D" - help - Say yes here to build support for the HID SENSOR - Magnetometer 3D. - -endmenu diff --git a/trunk/drivers/iio/magnetometer/Makefile b/trunk/drivers/iio/magnetometer/Makefile deleted file mode 100644 index 60dc4f2b1963..000000000000 --- a/trunk/drivers/iio/magnetometer/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -# -# Makefile for industrial I/O Magnetometer sensor drivers -# - -obj-$(CONFIG_HID_SENSOR_MAGNETOMETER_3D) += hid-sensor-magn-3d.o diff --git a/trunk/drivers/iio/magnetometer/hid-sensor-magn-3d.c b/trunk/drivers/iio/magnetometer/hid-sensor-magn-3d.c deleted file mode 100644 index c4f0d274f577..000000000000 --- a/trunk/drivers/iio/magnetometer/hid-sensor-magn-3d.c +++ /dev/null @@ -1,419 +0,0 @@ -/* - * HID Sensors Driver - * Copyright (c) 2012, Intel Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "../common/hid-sensors/hid-sensor-attributes.h" -#include "../common/hid-sensors/hid-sensor-trigger.h" - -/*Format: HID-SENSOR-usage_id_in_hex*/ -/*Usage ID from spec for Magnetometer-3D: 0x200083*/ -#define DRIVER_NAME "HID-SENSOR-200083" - -enum magn_3d_channel { - CHANNEL_SCAN_INDEX_X, - CHANNEL_SCAN_INDEX_Y, - CHANNEL_SCAN_INDEX_Z, - MAGN_3D_CHANNEL_MAX, -}; - -struct magn_3d_state { - struct hid_sensor_hub_callbacks callbacks; - struct hid_sensor_iio_common common_attributes; - struct hid_sensor_hub_attribute_info magn[MAGN_3D_CHANNEL_MAX]; - u32 magn_val[MAGN_3D_CHANNEL_MAX]; -}; - -static const u32 magn_3d_addresses[MAGN_3D_CHANNEL_MAX] = { - HID_USAGE_SENSOR_ORIENT_MAGN_FLUX_X_AXIS, - HID_USAGE_SENSOR_ORIENT_MAGN_FLUX_Y_AXIS, - HID_USAGE_SENSOR_ORIENT_MAGN_FLUX_Z_AXIS -}; - -/* Channel definitions */ -static const struct iio_chan_spec magn_3d_channels[] = { - { - .type = IIO_MAGN, - .modified = 1, - .channel2 = IIO_MOD_X, - .info_mask = IIO_CHAN_INFO_OFFSET_SHARED_BIT | - IIO_CHAN_INFO_SCALE_SHARED_BIT | - IIO_CHAN_INFO_SAMP_FREQ_SHARED_BIT | - IIO_CHAN_INFO_HYSTERESIS_SHARED_BIT, - .scan_index = CHANNEL_SCAN_INDEX_X, - }, { - .type = IIO_MAGN, - .modified = 1, - .channel2 = IIO_MOD_Y, - .info_mask = IIO_CHAN_INFO_OFFSET_SHARED_BIT | - IIO_CHAN_INFO_SCALE_SHARED_BIT | - IIO_CHAN_INFO_SAMP_FREQ_SHARED_BIT | - IIO_CHAN_INFO_HYSTERESIS_SHARED_BIT, - .scan_index = CHANNEL_SCAN_INDEX_Y, - }, { - .type = IIO_MAGN, - .modified = 1, - .channel2 = IIO_MOD_Z, - .info_mask = IIO_CHAN_INFO_OFFSET_SHARED_BIT | - IIO_CHAN_INFO_SCALE_SHARED_BIT | - IIO_CHAN_INFO_SAMP_FREQ_SHARED_BIT | - IIO_CHAN_INFO_HYSTERESIS_SHARED_BIT, - .scan_index = CHANNEL_SCAN_INDEX_Z, - } -}; - -/* Adjust channel real bits based on report descriptor */ -static void magn_3d_adjust_channel_bit_mask(struct iio_chan_spec *channels, - int channel, int size) -{ - channels[channel].scan_type.sign = 's'; - /* Real storage bits will change based on the report desc. */ - channels[channel].scan_type.realbits = size * 8; - /* Maximum size of a sample to capture is u32 */ - channels[channel].scan_type.storagebits = sizeof(u32) * 8; -} - -/* Channel read_raw handler */ -static int magn_3d_read_raw(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, - int *val, int *val2, - long mask) -{ - struct magn_3d_state *magn_state = iio_priv(indio_dev); - int report_id = -1; - u32 address; - int ret; - int ret_type; - - *val = 0; - *val2 = 0; - switch (mask) { - case 0: - report_id = - magn_state->magn[chan->scan_index].report_id; - address = magn_3d_addresses[chan->scan_index]; - if (report_id >= 0) - *val = sensor_hub_input_attr_get_raw_value( - magn_state->common_attributes.hsdev, - HID_USAGE_SENSOR_COMPASS_3D, address, - report_id); - else { - *val = 0; - return -EINVAL; - } - ret_type = IIO_VAL_INT; - break; - case IIO_CHAN_INFO_SCALE: - *val = magn_state->magn[CHANNEL_SCAN_INDEX_X].units; - ret_type = IIO_VAL_INT; - break; - case IIO_CHAN_INFO_OFFSET: - *val = hid_sensor_convert_exponent( - magn_state->magn[CHANNEL_SCAN_INDEX_X].unit_expo); - ret_type = IIO_VAL_INT; - break; - case IIO_CHAN_INFO_SAMP_FREQ: - ret = hid_sensor_read_samp_freq_value( - &magn_state->common_attributes, val, val2); - ret_type = IIO_VAL_INT_PLUS_MICRO; - break; - case IIO_CHAN_INFO_HYSTERESIS: - ret = hid_sensor_read_raw_hyst_value( - &magn_state->common_attributes, val, val2); - ret_type = IIO_VAL_INT_PLUS_MICRO; - break; - default: - ret_type = -EINVAL; - break; - } - - return ret_type; -} - -/* Channel write_raw handler */ -static int magn_3d_write_raw(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, - int val, - int val2, - long mask) -{ - struct magn_3d_state *magn_state = iio_priv(indio_dev); - int ret = 0; - - switch (mask) { - case IIO_CHAN_INFO_SAMP_FREQ: - ret = hid_sensor_write_samp_freq_value( - &magn_state->common_attributes, val, val2); - break; - case IIO_CHAN_INFO_HYSTERESIS: - ret = hid_sensor_write_raw_hyst_value( - &magn_state->common_attributes, val, val2); - break; - default: - ret = -EINVAL; - } - - return ret; -} - -static int magn_3d_write_raw_get_fmt(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, - long mask) -{ - return IIO_VAL_INT_PLUS_MICRO; -} - -static const struct iio_info magn_3d_info = { - .driver_module = THIS_MODULE, - .read_raw = &magn_3d_read_raw, - .write_raw = &magn_3d_write_raw, - .write_raw_get_fmt = &magn_3d_write_raw_get_fmt, -}; - -/* Function to push data to buffer */ -static void hid_sensor_push_data(struct iio_dev *indio_dev, u8 *data, int len) -{ - struct iio_buffer *buffer = indio_dev->buffer; - int datum_sz; - - dev_dbg(&indio_dev->dev, "hid_sensor_push_data\n"); - if (!buffer) { - dev_err(&indio_dev->dev, "Buffer == NULL\n"); - return; - } - datum_sz = buffer->access->get_bytes_per_datum(buffer); - if (len > datum_sz) { - dev_err(&indio_dev->dev, "Datum size mismatch %d:%d\n", len, - datum_sz); - return; - } - iio_push_to_buffer(buffer, (u8 *)data); -} - -/* Callback handler to send event after all samples are received and captured */ -static int magn_3d_proc_event(struct hid_sensor_hub_device *hsdev, - unsigned usage_id, - void *priv) -{ - struct iio_dev *indio_dev = platform_get_drvdata(priv); - struct magn_3d_state *magn_state = iio_priv(indio_dev); - - dev_dbg(&indio_dev->dev, "magn_3d_proc_event [%d]\n", - magn_state->common_attributes.data_ready); - if (magn_state->common_attributes.data_ready) - hid_sensor_push_data(indio_dev, - (u8 *)magn_state->magn_val, - sizeof(magn_state->magn_val)); - - return 0; -} - -/* Capture samples in local storage */ -static int magn_3d_capture_sample(struct hid_sensor_hub_device *hsdev, - unsigned usage_id, - size_t raw_len, char *raw_data, - void *priv) -{ - struct iio_dev *indio_dev = platform_get_drvdata(priv); - struct magn_3d_state *magn_state = iio_priv(indio_dev); - int offset; - int ret = -EINVAL; - - switch (usage_id) { - case HID_USAGE_SENSOR_ORIENT_MAGN_FLUX_X_AXIS: - case HID_USAGE_SENSOR_ORIENT_MAGN_FLUX_Y_AXIS: - case HID_USAGE_SENSOR_ORIENT_MAGN_FLUX_Z_AXIS: - offset = usage_id - HID_USAGE_SENSOR_ORIENT_MAGN_FLUX_X_AXIS; - magn_state->magn_val[CHANNEL_SCAN_INDEX_X + offset] = - *(u32 *)raw_data; - ret = 0; - break; - default: - break; - } - - return ret; -} - -/* Parse report which is specific to an usage id*/ -static int magn_3d_parse_report(struct platform_device *pdev, - struct hid_sensor_hub_device *hsdev, - struct iio_chan_spec *channels, - unsigned usage_id, - struct magn_3d_state *st) -{ - int ret; - int i; - - for (i = 0; i <= CHANNEL_SCAN_INDEX_Z; ++i) { - ret = sensor_hub_input_get_attribute_info(hsdev, - HID_INPUT_REPORT, - usage_id, - HID_USAGE_SENSOR_ORIENT_MAGN_FLUX_X_AXIS + i, - &st->magn[CHANNEL_SCAN_INDEX_X + i]); - if (ret < 0) - break; - magn_3d_adjust_channel_bit_mask(channels, - CHANNEL_SCAN_INDEX_X + i, - st->magn[CHANNEL_SCAN_INDEX_X + i].size); - } - dev_dbg(&pdev->dev, "magn_3d %x:%x, %x:%x, %x:%x\n", - st->magn[0].index, - st->magn[0].report_id, - st->magn[1].index, st->magn[1].report_id, - st->magn[2].index, st->magn[2].report_id); - - return ret; -} - -/* Function to initialize the processing for usage id */ -static int __devinit hid_magn_3d_probe(struct platform_device *pdev) -{ - int ret = 0; - static char *name = "magn_3d"; - struct iio_dev *indio_dev; - struct magn_3d_state *magn_state; - struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data; - struct iio_chan_spec *channels; - - indio_dev = iio_device_alloc(sizeof(struct magn_3d_state)); - if (indio_dev == NULL) { - ret = -ENOMEM; - goto error_ret; - } - platform_set_drvdata(pdev, indio_dev); - - magn_state = iio_priv(indio_dev); - magn_state->common_attributes.hsdev = hsdev; - magn_state->common_attributes.pdev = pdev; - - ret = hid_sensor_parse_common_attributes(hsdev, - HID_USAGE_SENSOR_COMPASS_3D, - &magn_state->common_attributes); - if (ret) { - dev_err(&pdev->dev, "failed to setup common attributes\n"); - goto error_free_dev; - } - - channels = kmemdup(magn_3d_channels, - sizeof(magn_3d_channels), - GFP_KERNEL); - if (!channels) { - dev_err(&pdev->dev, "failed to duplicate channels\n"); - goto error_free_dev; - } - - ret = magn_3d_parse_report(pdev, hsdev, channels, - HID_USAGE_SENSOR_COMPASS_3D, magn_state); - if (ret) { - dev_err(&pdev->dev, "failed to setup attributes\n"); - goto error_free_dev_mem; - } - - indio_dev->channels = channels; - indio_dev->num_channels = ARRAY_SIZE(magn_3d_channels); - indio_dev->dev.parent = &pdev->dev; - indio_dev->info = &magn_3d_info; - indio_dev->name = name; - indio_dev->modes = INDIO_DIRECT_MODE; - - ret = iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time, - NULL, NULL); - if (ret) { - dev_err(&pdev->dev, "failed to initialize trigger buffer\n"); - goto error_free_dev_mem; - } - magn_state->common_attributes.data_ready = false; - ret = hid_sensor_setup_trigger(indio_dev, name, - &magn_state->common_attributes); - if (ret < 0) { - dev_err(&pdev->dev, "trigger setup failed\n"); - goto error_unreg_buffer_funcs; - } - - ret = iio_device_register(indio_dev); - if (ret) { - dev_err(&pdev->dev, "device register failed\n"); - goto error_remove_trigger; - } - - magn_state->callbacks.send_event = magn_3d_proc_event; - magn_state->callbacks.capture_sample = magn_3d_capture_sample; - magn_state->callbacks.pdev = pdev; - ret = sensor_hub_register_callback(hsdev, HID_USAGE_SENSOR_COMPASS_3D, - &magn_state->callbacks); - if (ret < 0) { - dev_err(&pdev->dev, "callback reg failed\n"); - goto error_iio_unreg; - } - - return ret; - -error_iio_unreg: - iio_device_unregister(indio_dev); -error_remove_trigger: - hid_sensor_remove_trigger(indio_dev); -error_unreg_buffer_funcs: - iio_triggered_buffer_cleanup(indio_dev); -error_free_dev_mem: - kfree(indio_dev->channels); -error_free_dev: - iio_device_free(indio_dev); -error_ret: - return ret; -} - -/* Function to deinitialize the processing for usage id */ -static int __devinit hid_magn_3d_remove(struct platform_device *pdev) -{ - struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data; - struct iio_dev *indio_dev = platform_get_drvdata(pdev); - - sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_COMPASS_3D); - iio_device_unregister(indio_dev); - hid_sensor_remove_trigger(indio_dev); - iio_triggered_buffer_cleanup(indio_dev); - kfree(indio_dev->channels); - iio_device_free(indio_dev); - - return 0; -} - -static struct platform_driver hid_magn_3d_platform_driver = { - .driver = { - .name = DRIVER_NAME, - .owner = THIS_MODULE, - }, - .probe = hid_magn_3d_probe, - .remove = hid_magn_3d_remove, -}; -module_platform_driver(hid_magn_3d_platform_driver); - -MODULE_DESCRIPTION("HID Sensor Magnetometer 3D"); -MODULE_AUTHOR("Srinivas Pandruvada "); -MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/infiniband/core/ucma.c b/trunk/drivers/infiniband/core/ucma.c index 055ed59838dc..6bf850422895 100644 --- a/trunk/drivers/infiniband/core/ucma.c +++ b/trunk/drivers/infiniband/core/ucma.c @@ -267,7 +267,6 @@ static int ucma_event_handler(struct rdma_cm_id *cm_id, if (!uevent) return event->event == RDMA_CM_EVENT_CONNECT_REQUEST; - mutex_lock(&ctx->file->mut); uevent->cm_id = cm_id; ucma_set_event_context(ctx, event, uevent); uevent->resp.event = event->event; @@ -278,6 +277,7 @@ static int ucma_event_handler(struct rdma_cm_id *cm_id, ucma_copy_conn_event(&uevent->resp.param.conn, &event->param.conn); + mutex_lock(&ctx->file->mut); if (event->event == RDMA_CM_EVENT_CONNECT_REQUEST) { if (!ctx->backlog) { ret = -ENOMEM; diff --git a/trunk/drivers/infiniband/hw/amso1100/c2_rnic.c b/trunk/drivers/infiniband/hw/amso1100/c2_rnic.c index e4a73158fc7f..8c81992fa6db 100644 --- a/trunk/drivers/infiniband/hw/amso1100/c2_rnic.c +++ b/trunk/drivers/infiniband/hw/amso1100/c2_rnic.c @@ -439,7 +439,7 @@ static int c2_rnic_close(struct c2_dev *c2dev) /* * Called by c2_probe to initialize the RNIC. This principally - * involves initializing the various limits and resource pools that + * involves initalizing the various limits and resouce pools that * comprise the RNIC instance. */ int __devinit c2_rnic_init(struct c2_dev *c2dev) diff --git a/trunk/drivers/infiniband/hw/cxgb3/iwch_cm.c b/trunk/drivers/infiniband/hw/cxgb3/iwch_cm.c index aaf88ef9409c..77b6b182778a 100644 --- a/trunk/drivers/infiniband/hw/cxgb3/iwch_cm.c +++ b/trunk/drivers/infiniband/hw/cxgb3/iwch_cm.c @@ -1680,7 +1680,7 @@ static int close_con_rpl(struct t3cdev *tdev, struct sk_buff *skb, void *ctx) * T3A does 3 things when a TERM is received: * 1) send up a CPL_RDMA_TERMINATE message with the TERM packet * 2) generate an async event on the QP with the TERMINATE opcode - * 3) post a TERMINATE opcode cqe into the associated CQ. + * 3) post a TERMINATE opcde cqe into the associated CQ. * * For (1), we save the message in the qp for later consumer consumption. * For (2), we move the QP into TERMINATE, post a QP event and disconnect. diff --git a/trunk/drivers/infiniband/hw/cxgb4/cm.c b/trunk/drivers/infiniband/hw/cxgb4/cm.c index 6cfd4d8fd0bd..51f42061dae9 100644 --- a/trunk/drivers/infiniband/hw/cxgb4/cm.c +++ b/trunk/drivers/infiniband/hw/cxgb4/cm.c @@ -1361,11 +1361,11 @@ static int abort_rpl(struct c4iw_dev *dev, struct sk_buff *skb) struct tid_info *t = dev->rdev.lldi.tids; ep = lookup_tid(t, tid); + PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid); if (!ep) { printk(KERN_WARNING MOD "Abort rpl to freed endpoint\n"); return 0; } - PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid); mutex_lock(&ep->com.mutex); switch (ep->com.state) { case ABORTING: diff --git a/trunk/drivers/infiniband/hw/ehca/ehca_irq.c b/trunk/drivers/infiniband/hw/ehca/ehca_irq.c index 8615d7cf7e01..53589000fd07 100644 --- a/trunk/drivers/infiniband/hw/ehca/ehca_irq.c +++ b/trunk/drivers/infiniband/hw/ehca/ehca_irq.c @@ -42,7 +42,6 @@ */ #include -#include #include "ehca_classes.h" #include "ehca_irq.h" @@ -653,7 +652,7 @@ void ehca_tasklet_eq(unsigned long data) ehca_process_eq((struct ehca_shca*)data, 1); } -static int find_next_online_cpu(struct ehca_comp_pool *pool) +static inline int find_next_online_cpu(struct ehca_comp_pool *pool) { int cpu; unsigned long flags; @@ -663,20 +662,17 @@ static int find_next_online_cpu(struct ehca_comp_pool *pool) ehca_dmp(cpu_online_mask, cpumask_size(), ""); spin_lock_irqsave(&pool->last_cpu_lock, flags); - do { - cpu = cpumask_next(pool->last_cpu, cpu_online_mask); - if (cpu >= nr_cpu_ids) - cpu = cpumask_first(cpu_online_mask); - pool->last_cpu = cpu; - } while (!per_cpu_ptr(pool->cpu_comp_tasks, cpu)->active); + cpu = cpumask_next(pool->last_cpu, cpu_online_mask); + if (cpu >= nr_cpu_ids) + cpu = cpumask_first(cpu_online_mask); + pool->last_cpu = cpu; spin_unlock_irqrestore(&pool->last_cpu_lock, flags); return cpu; } static void __queue_comp_task(struct ehca_cq *__cq, - struct ehca_cpu_comp_task *cct, - struct task_struct *thread) + struct ehca_cpu_comp_task *cct) { unsigned long flags; @@ -687,7 +683,7 @@ static void __queue_comp_task(struct ehca_cq *__cq, __cq->nr_callbacks++; list_add_tail(&__cq->entry, &cct->cq_list); cct->cq_jobs++; - wake_up_process(thread); + wake_up(&cct->wait_queue); } else __cq->nr_callbacks++; @@ -699,7 +695,6 @@ static void queue_comp_task(struct ehca_cq *__cq) { int cpu_id; struct ehca_cpu_comp_task *cct; - struct task_struct *thread; int cq_jobs; unsigned long flags; @@ -707,8 +702,7 @@ static void queue_comp_task(struct ehca_cq *__cq) BUG_ON(!cpu_online(cpu_id)); cct = per_cpu_ptr(pool->cpu_comp_tasks, cpu_id); - thread = *per_cpu_ptr(pool->cpu_comp_threads, cpu_id); - BUG_ON(!cct || !thread); + BUG_ON(!cct); spin_lock_irqsave(&cct->task_lock, flags); cq_jobs = cct->cq_jobs; @@ -716,25 +710,28 @@ static void queue_comp_task(struct ehca_cq *__cq) if (cq_jobs > 0) { cpu_id = find_next_online_cpu(pool); cct = per_cpu_ptr(pool->cpu_comp_tasks, cpu_id); - thread = *per_cpu_ptr(pool->cpu_comp_threads, cpu_id); - BUG_ON(!cct || !thread); + BUG_ON(!cct); } - __queue_comp_task(__cq, cct, thread); + + __queue_comp_task(__cq, cct); } static void run_comp_task(struct ehca_cpu_comp_task *cct) { struct ehca_cq *cq; + unsigned long flags; + + spin_lock_irqsave(&cct->task_lock, flags); while (!list_empty(&cct->cq_list)) { cq = list_entry(cct->cq_list.next, struct ehca_cq, entry); - spin_unlock_irq(&cct->task_lock); + spin_unlock_irqrestore(&cct->task_lock, flags); comp_event_callback(cq); if (atomic_dec_and_test(&cq->nr_events)) wake_up(&cq->wait_completion); - spin_lock_irq(&cct->task_lock); + spin_lock_irqsave(&cct->task_lock, flags); spin_lock(&cq->task_lock); cq->nr_callbacks--; if (!cq->nr_callbacks) { @@ -743,76 +740,159 @@ static void run_comp_task(struct ehca_cpu_comp_task *cct) } spin_unlock(&cq->task_lock); } + + spin_unlock_irqrestore(&cct->task_lock, flags); } -static void comp_task_park(unsigned int cpu) +static int comp_task(void *__cct) { - struct ehca_cpu_comp_task *cct = per_cpu_ptr(pool->cpu_comp_tasks, cpu); - struct ehca_cpu_comp_task *target; - struct task_struct *thread; - struct ehca_cq *cq, *tmp; - LIST_HEAD(list); + struct ehca_cpu_comp_task *cct = __cct; + int cql_empty; + DECLARE_WAITQUEUE(wait, current); - spin_lock_irq(&cct->task_lock); - cct->cq_jobs = 0; - cct->active = 0; - list_splice_init(&cct->cq_list, &list); - spin_unlock_irq(&cct->task_lock); + set_current_state(TASK_INTERRUPTIBLE); + while (!kthread_should_stop()) { + add_wait_queue(&cct->wait_queue, &wait); - cpu = find_next_online_cpu(pool); - target = per_cpu_ptr(pool->cpu_comp_tasks, cpu); - thread = *per_cpu_ptr(pool->cpu_comp_threads, cpu); - spin_lock_irq(&target->task_lock); - list_for_each_entry_safe(cq, tmp, &list, entry) { - list_del(&cq->entry); - __queue_comp_task(cq, target, thread); + spin_lock_irq(&cct->task_lock); + cql_empty = list_empty(&cct->cq_list); + spin_unlock_irq(&cct->task_lock); + if (cql_empty) + schedule(); + else + __set_current_state(TASK_RUNNING); + + remove_wait_queue(&cct->wait_queue, &wait); + + spin_lock_irq(&cct->task_lock); + cql_empty = list_empty(&cct->cq_list); + spin_unlock_irq(&cct->task_lock); + if (!cql_empty) + run_comp_task(__cct); + + set_current_state(TASK_INTERRUPTIBLE); } - spin_unlock_irq(&target->task_lock); + __set_current_state(TASK_RUNNING); + + return 0; } -static void comp_task_stop(unsigned int cpu, bool online) +static struct task_struct *create_comp_task(struct ehca_comp_pool *pool, + int cpu) { - struct ehca_cpu_comp_task *cct = per_cpu_ptr(pool->cpu_comp_tasks, cpu); + struct ehca_cpu_comp_task *cct; + + cct = per_cpu_ptr(pool->cpu_comp_tasks, cpu); + spin_lock_init(&cct->task_lock); + INIT_LIST_HEAD(&cct->cq_list); + init_waitqueue_head(&cct->wait_queue); + cct->task = kthread_create_on_node(comp_task, cct, cpu_to_node(cpu), + "ehca_comp/%d", cpu); - spin_lock_irq(&cct->task_lock); + return cct->task; +} + +static void destroy_comp_task(struct ehca_comp_pool *pool, + int cpu) +{ + struct ehca_cpu_comp_task *cct; + struct task_struct *task; + unsigned long flags_cct; + + cct = per_cpu_ptr(pool->cpu_comp_tasks, cpu); + + spin_lock_irqsave(&cct->task_lock, flags_cct); + + task = cct->task; + cct->task = NULL; cct->cq_jobs = 0; - cct->active = 0; - WARN_ON(!list_empty(&cct->cq_list)); - spin_unlock_irq(&cct->task_lock); + + spin_unlock_irqrestore(&cct->task_lock, flags_cct); + + if (task) + kthread_stop(task); } -static int comp_task_should_run(unsigned int cpu) +static void __cpuinit take_over_work(struct ehca_comp_pool *pool, int cpu) { struct ehca_cpu_comp_task *cct = per_cpu_ptr(pool->cpu_comp_tasks, cpu); + LIST_HEAD(list); + struct ehca_cq *cq; + unsigned long flags_cct; + + spin_lock_irqsave(&cct->task_lock, flags_cct); + + list_splice_init(&cct->cq_list, &list); + + while (!list_empty(&list)) { + cq = list_entry(cct->cq_list.next, struct ehca_cq, entry); + + list_del(&cq->entry); + __queue_comp_task(cq, this_cpu_ptr(pool->cpu_comp_tasks)); + } + + spin_unlock_irqrestore(&cct->task_lock, flags_cct); - return cct->cq_jobs; } -static void comp_task(unsigned int cpu) +static int __cpuinit comp_pool_callback(struct notifier_block *nfb, + unsigned long action, + void *hcpu) { - struct ehca_cpu_comp_task *cct = this_cpu_ptr(pool->cpu_comp_tasks); - int cql_empty; + unsigned int cpu = (unsigned long)hcpu; + struct ehca_cpu_comp_task *cct; - spin_lock_irq(&cct->task_lock); - cql_empty = list_empty(&cct->cq_list); - if (!cql_empty) { - __set_current_state(TASK_RUNNING); - run_comp_task(cct); + switch (action) { + case CPU_UP_PREPARE: + case CPU_UP_PREPARE_FROZEN: + ehca_gen_dbg("CPU: %x (CPU_PREPARE)", cpu); + if (!create_comp_task(pool, cpu)) { + ehca_gen_err("Can't create comp_task for cpu: %x", cpu); + return notifier_from_errno(-ENOMEM); + } + break; + case CPU_UP_CANCELED: + case CPU_UP_CANCELED_FROZEN: + ehca_gen_dbg("CPU: %x (CPU_CANCELED)", cpu); + cct = per_cpu_ptr(pool->cpu_comp_tasks, cpu); + kthread_bind(cct->task, cpumask_any(cpu_online_mask)); + destroy_comp_task(pool, cpu); + break; + case CPU_ONLINE: + case CPU_ONLINE_FROZEN: + ehca_gen_dbg("CPU: %x (CPU_ONLINE)", cpu); + cct = per_cpu_ptr(pool->cpu_comp_tasks, cpu); + kthread_bind(cct->task, cpu); + wake_up_process(cct->task); + break; + case CPU_DOWN_PREPARE: + case CPU_DOWN_PREPARE_FROZEN: + ehca_gen_dbg("CPU: %x (CPU_DOWN_PREPARE)", cpu); + break; + case CPU_DOWN_FAILED: + case CPU_DOWN_FAILED_FROZEN: + ehca_gen_dbg("CPU: %x (CPU_DOWN_FAILED)", cpu); + break; + case CPU_DEAD: + case CPU_DEAD_FROZEN: + ehca_gen_dbg("CPU: %x (CPU_DEAD)", cpu); + destroy_comp_task(pool, cpu); + take_over_work(pool, cpu); + break; } - spin_unlock_irq(&cct->task_lock); + + return NOTIFY_OK; } -static struct smp_hotplug_thread comp_pool_threads = { - .thread_should_run = comp_task_should_run, - .thread_fn = comp_task, - .thread_comm = "ehca_comp/%u", - .cleanup = comp_task_stop, - .park = comp_task_park, +static struct notifier_block comp_pool_callback_nb __cpuinitdata = { + .notifier_call = comp_pool_callback, + .priority = 0, }; int ehca_create_comp_pool(void) { - int cpu, ret = -ENOMEM; + int cpu; + struct task_struct *task; if (!ehca_scaling_code) return 0; @@ -825,46 +905,38 @@ int ehca_create_comp_pool(void) pool->last_cpu = cpumask_any(cpu_online_mask); pool->cpu_comp_tasks = alloc_percpu(struct ehca_cpu_comp_task); - if (!pool->cpu_comp_tasks) - goto out_pool; - - pool->cpu_comp_threads = alloc_percpu(struct task_struct *); - if (!pool->cpu_comp_threads) - goto out_tasks; - - for_each_present_cpu(cpu) { - struct ehca_cpu_comp_task *cct; + if (pool->cpu_comp_tasks == NULL) { + kfree(pool); + return -EINVAL; + } - cct = per_cpu_ptr(pool->cpu_comp_tasks, cpu); - spin_lock_init(&cct->task_lock); - INIT_LIST_HEAD(&cct->cq_list); + for_each_online_cpu(cpu) { + task = create_comp_task(pool, cpu); + if (task) { + kthread_bind(task, cpu); + wake_up_process(task); + } } - comp_pool_threads.store = pool->cpu_comp_threads; - ret = smpboot_register_percpu_thread(&comp_pool_threads); - if (ret) - goto out_threads; + register_hotcpu_notifier(&comp_pool_callback_nb); - pr_info("eHCA scaling code enabled\n"); - return ret; + printk(KERN_INFO "eHCA scaling code enabled\n"); -out_threads: - free_percpu(pool->cpu_comp_threads); -out_tasks: - free_percpu(pool->cpu_comp_tasks); -out_pool: - kfree(pool); - return ret; + return 0; } void ehca_destroy_comp_pool(void) { + int i; + if (!ehca_scaling_code) return; - smpboot_unregister_percpu_thread(&comp_pool_threads); + unregister_hotcpu_notifier(&comp_pool_callback_nb); + + for_each_online_cpu(i) + destroy_comp_task(pool, i); - free_percpu(pool->cpu_comp_threads); free_percpu(pool->cpu_comp_tasks); kfree(pool); } diff --git a/trunk/drivers/infiniband/hw/ehca/ehca_irq.h b/trunk/drivers/infiniband/hw/ehca/ehca_irq.h index 5370199f08c7..3346cb06cea6 100644 --- a/trunk/drivers/infiniband/hw/ehca/ehca_irq.h +++ b/trunk/drivers/infiniband/hw/ehca/ehca_irq.h @@ -58,15 +58,15 @@ void ehca_tasklet_eq(unsigned long data); void ehca_process_eq(struct ehca_shca *shca, int is_irq); struct ehca_cpu_comp_task { + wait_queue_head_t wait_queue; struct list_head cq_list; + struct task_struct *task; spinlock_t task_lock; int cq_jobs; - int active; }; struct ehca_comp_pool { - struct ehca_cpu_comp_task __percpu *cpu_comp_tasks; - struct task_struct * __percpu *cpu_comp_threads; + struct ehca_cpu_comp_task *cpu_comp_tasks; int last_cpu; spinlock_t last_cpu_lock; }; diff --git a/trunk/drivers/infiniband/hw/mlx4/mad.c b/trunk/drivers/infiniband/hw/mlx4/mad.c index 9c2ae7efd00f..c27141fef1ab 100644 --- a/trunk/drivers/infiniband/hw/mlx4/mad.c +++ b/trunk/drivers/infiniband/hw/mlx4/mad.c @@ -125,7 +125,6 @@ static void update_sm_ah(struct mlx4_ib_dev *dev, u8 port_num, u16 lid, u8 sl) { struct ib_ah *new_ah; struct ib_ah_attr ah_attr; - unsigned long flags; if (!dev->send_agent[port_num - 1][0]) return; @@ -140,11 +139,11 @@ static void update_sm_ah(struct mlx4_ib_dev *dev, u8 port_num, u16 lid, u8 sl) if (IS_ERR(new_ah)) return; - spin_lock_irqsave(&dev->sm_lock, flags); + spin_lock(&dev->sm_lock); if (dev->sm_ah[port_num - 1]) ib_destroy_ah(dev->sm_ah[port_num - 1]); dev->sm_ah[port_num - 1] = new_ah; - spin_unlock_irqrestore(&dev->sm_lock, flags); + spin_unlock(&dev->sm_lock); } /* @@ -198,15 +197,13 @@ static void smp_snoop(struct ib_device *ibdev, u8 port_num, struct ib_mad *mad, static void node_desc_override(struct ib_device *dev, struct ib_mad *mad) { - unsigned long flags; - if ((mad->mad_hdr.mgmt_class == IB_MGMT_CLASS_SUBN_LID_ROUTED || mad->mad_hdr.mgmt_class == IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE) && mad->mad_hdr.method == IB_MGMT_METHOD_GET_RESP && mad->mad_hdr.attr_id == IB_SMP_ATTR_NODE_DESC) { - spin_lock_irqsave(&to_mdev(dev)->sm_lock, flags); + spin_lock(&to_mdev(dev)->sm_lock); memcpy(((struct ib_smp *) mad)->data, dev->node_desc, 64); - spin_unlock_irqrestore(&to_mdev(dev)->sm_lock, flags); + spin_unlock(&to_mdev(dev)->sm_lock); } } @@ -216,7 +213,6 @@ static void forward_trap(struct mlx4_ib_dev *dev, u8 port_num, struct ib_mad *ma struct ib_mad_send_buf *send_buf; struct ib_mad_agent *agent = dev->send_agent[port_num - 1][qpn]; int ret; - unsigned long flags; if (agent) { send_buf = ib_create_send_mad(agent, qpn, 0, 0, IB_MGMT_MAD_HDR, @@ -229,13 +225,13 @@ static void forward_trap(struct mlx4_ib_dev *dev, u8 port_num, struct ib_mad *ma * wrong following the IB spec strictly, but we know * it's OK for our devices). */ - spin_lock_irqsave(&dev->sm_lock, flags); + spin_lock(&dev->sm_lock); memcpy(send_buf->mad, mad, sizeof *mad); if ((send_buf->ah = dev->sm_ah[port_num - 1])) ret = ib_post_send_mad(send_buf, NULL); else ret = -EINVAL; - spin_unlock_irqrestore(&dev->sm_lock, flags); + spin_unlock(&dev->sm_lock); if (ret) ib_free_send_mad(send_buf); diff --git a/trunk/drivers/infiniband/hw/mlx4/main.c b/trunk/drivers/infiniband/hw/mlx4/main.c index cc05579ebce7..fe2088cfa6ee 100644 --- a/trunk/drivers/infiniband/hw/mlx4/main.c +++ b/trunk/drivers/infiniband/hw/mlx4/main.c @@ -423,7 +423,6 @@ static int mlx4_ib_modify_device(struct ib_device *ibdev, int mask, struct ib_device_modify *props) { struct mlx4_cmd_mailbox *mailbox; - unsigned long flags; if (mask & ~IB_DEVICE_MODIFY_NODE_DESC) return -EOPNOTSUPP; @@ -431,9 +430,9 @@ static int mlx4_ib_modify_device(struct ib_device *ibdev, int mask, if (!(mask & IB_DEVICE_MODIFY_NODE_DESC)) return 0; - spin_lock_irqsave(&to_mdev(ibdev)->sm_lock, flags); + spin_lock(&to_mdev(ibdev)->sm_lock); memcpy(ibdev->node_desc, props->node_desc, 64); - spin_unlock_irqrestore(&to_mdev(ibdev)->sm_lock, flags); + spin_unlock(&to_mdev(ibdev)->sm_lock); /* * If possible, pass node desc to FW, so it can generate diff --git a/trunk/drivers/infiniband/hw/mlx4/qp.c b/trunk/drivers/infiniband/hw/mlx4/qp.c index f585eddef4b7..a6d8ea060ea8 100644 --- a/trunk/drivers/infiniband/hw/mlx4/qp.c +++ b/trunk/drivers/infiniband/hw/mlx4/qp.c @@ -1407,7 +1407,6 @@ static int build_mlx_header(struct mlx4_ib_sqp *sqp, struct ib_send_wr *wr, struct mlx4_wqe_mlx_seg *mlx = wqe; struct mlx4_wqe_inline_seg *inl = wqe + sizeof *mlx; struct mlx4_ib_ah *ah = to_mah(wr->wr.ud.ah); - struct net_device *ndev; union ib_gid sgid; u16 pkey; int send_size; @@ -1484,10 +1483,7 @@ static int build_mlx_header(struct mlx4_ib_sqp *sqp, struct ib_send_wr *wr, memcpy(sqp->ud_header.eth.dmac_h, ah->av.eth.mac, 6); /* FIXME: cache smac value? */ - ndev = to_mdev(sqp->qp.ibqp.device)->iboe.netdevs[sqp->qp.port - 1]; - if (!ndev) - return -ENODEV; - smac = ndev->dev_addr; + smac = to_mdev(sqp->qp.ibqp.device)->iboe.netdevs[sqp->qp.port - 1]->dev_addr; memcpy(sqp->ud_header.eth.smac_h, smac, 6); if (!memcmp(sqp->ud_header.eth.smac_h, sqp->ud_header.eth.dmac_h, 6)) mlx->flags |= cpu_to_be32(MLX4_WQE_CTRL_FORCE_LOOPBACK); diff --git a/trunk/drivers/infiniband/hw/mthca/mthca_reset.c b/trunk/drivers/infiniband/hw/mthca/mthca_reset.c index 74c6a9426047..4fa3534ec233 100644 --- a/trunk/drivers/infiniband/hw/mthca/mthca_reset.c +++ b/trunk/drivers/infiniband/hw/mthca/mthca_reset.c @@ -241,16 +241,16 @@ int mthca_reset(struct mthca_dev *mdev) if (hca_pcie_cap) { devctl = hca_header[(hca_pcie_cap + PCI_EXP_DEVCTL) / 4]; - if (pcie_capability_write_word(mdev->pdev, PCI_EXP_DEVCTL, - devctl)) { + if (pci_write_config_word(mdev->pdev, hca_pcie_cap + PCI_EXP_DEVCTL, + devctl)) { err = -ENODEV; mthca_err(mdev, "Couldn't restore HCA PCI Express " "Device Control register, aborting.\n"); goto out; } linkctl = hca_header[(hca_pcie_cap + PCI_EXP_LNKCTL) / 4]; - if (pcie_capability_write_word(mdev->pdev, PCI_EXP_LNKCTL, - linkctl)) { + if (pci_write_config_word(mdev->pdev, hca_pcie_cap + PCI_EXP_LNKCTL, + linkctl)) { err = -ENODEV; mthca_err(mdev, "Couldn't restore HCA PCI Express " "Link control register, aborting.\n"); diff --git a/trunk/drivers/infiniband/hw/ocrdma/ocrdma_main.c b/trunk/drivers/infiniband/hw/ocrdma/ocrdma_main.c index c4e0131f1b57..5a044526e4f4 100644 --- a/trunk/drivers/infiniband/hw/ocrdma/ocrdma_main.c +++ b/trunk/drivers/infiniband/hw/ocrdma/ocrdma_main.c @@ -161,7 +161,7 @@ static void ocrdma_add_default_sgid(struct ocrdma_dev *dev) ocrdma_get_guid(dev, &sgid->raw[8]); } -#if IS_ENABLED(CONFIG_VLAN_8021Q) +#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) static void ocrdma_add_vlan_sgids(struct ocrdma_dev *dev) { struct net_device *netdev, *tmp; @@ -202,13 +202,14 @@ static int ocrdma_build_sgid_tbl(struct ocrdma_dev *dev) return 0; } -#if IS_ENABLED(CONFIG_IPV6) +#if IS_ENABLED(CONFIG_IPV6) || IS_ENABLED(CONFIG_VLAN_8021Q) static int ocrdma_inet6addr_event(struct notifier_block *notifier, unsigned long event, void *ptr) { struct inet6_ifaddr *ifa = (struct inet6_ifaddr *)ptr; - struct net_device *netdev = ifa->idev->dev; + struct net_device *event_netdev = ifa->idev->dev; + struct net_device *netdev = NULL; struct ib_event gid_event; struct ocrdma_dev *dev; bool found = false; @@ -216,12 +217,11 @@ static int ocrdma_inet6addr_event(struct notifier_block *notifier, bool is_vlan = false; u16 vid = 0; - is_vlan = netdev->priv_flags & IFF_802_1Q_VLAN; - if (is_vlan) { - vid = vlan_dev_vlan_id(netdev); - netdev = vlan_dev_real_dev(netdev); + netdev = vlan_dev_real_dev(event_netdev); + if (netdev != event_netdev) { + is_vlan = true; + vid = vlan_dev_vlan_id(event_netdev); } - rcu_read_lock(); list_for_each_entry_rcu(dev, &ocrdma_dev_list, entry) { if (dev->nic_info.netdev == netdev) { diff --git a/trunk/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c b/trunk/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c index b29a4246ef41..cb5b7f7d4d38 100644 --- a/trunk/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c +++ b/trunk/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c @@ -2219,6 +2219,7 @@ static bool ocrdma_poll_success_scqe(struct ocrdma_qp *qp, u32 wqe_idx; if (!qp->wqe_wr_id_tbl[tail].signaled) { + expand = true; /* CQE cannot be consumed yet */ *polled = false; /* WC cannot be consumed yet */ } else { ibwc->status = IB_WC_SUCCESS; @@ -2226,11 +2227,10 @@ static bool ocrdma_poll_success_scqe(struct ocrdma_qp *qp, ibwc->qp = &qp->ibqp; ocrdma_update_wc(qp, ibwc, tail); *polled = true; + wqe_idx = le32_to_cpu(cqe->wq.wqeidx) & OCRDMA_CQE_WQEIDX_MASK; + if (tail != wqe_idx) + expand = true; /* Coalesced CQE can't be consumed yet */ } - wqe_idx = le32_to_cpu(cqe->wq.wqeidx) & OCRDMA_CQE_WQEIDX_MASK; - if (tail != wqe_idx) - expand = true; /* Coalesced CQE can't be consumed yet */ - ocrdma_hwq_inc_tail(&qp->sq); return expand; } diff --git a/trunk/drivers/infiniband/hw/qib/qib.h b/trunk/drivers/infiniband/hw/qib/qib.h index 4d11575c2010..7b1b86690024 100644 --- a/trunk/drivers/infiniband/hw/qib/qib.h +++ b/trunk/drivers/infiniband/hw/qib/qib.h @@ -87,7 +87,7 @@ struct qlogic_ib_stats { }; extern struct qlogic_ib_stats qib_stats; -extern const struct pci_error_handlers qib_pci_err_handler; +extern struct pci_error_handlers qib_pci_err_handler; extern struct pci_driver qib_driver; #define QIB_CHIP_SWVERSION QIB_CHIP_VERS_MAJ diff --git a/trunk/drivers/infiniband/hw/qib/qib_iba7322.c b/trunk/drivers/infiniband/hw/qib/qib_iba7322.c index 3f6b21e9dc11..0d7280af99bc 100644 --- a/trunk/drivers/infiniband/hw/qib/qib_iba7322.c +++ b/trunk/drivers/infiniband/hw/qib/qib_iba7322.c @@ -6346,10 +6346,8 @@ static int qib_init_7322_variables(struct qib_devdata *dd) dd->piobcnt4k * dd->align4k; dd->piovl15base = ioremap_nocache(vl15off, NUM_VL15_BUFS * dd->align4k); - if (!dd->piovl15base) { - ret = -ENOMEM; + if (!dd->piovl15base) goto bail; - } } qib_7322_set_baseaddrs(dd); /* set chip access pointers now */ diff --git a/trunk/drivers/infiniband/hw/qib/qib_mad.c b/trunk/drivers/infiniband/hw/qib/qib_mad.c index ccb119143d20..19f1e6c45fb6 100644 --- a/trunk/drivers/infiniband/hw/qib/qib_mad.c +++ b/trunk/drivers/infiniband/hw/qib/qib_mad.c @@ -471,10 +471,9 @@ static int subn_get_portinfo(struct ib_smp *smp, struct ib_device *ibdev, if (port_num != port) { ibp = to_iport(ibdev, port_num); ret = check_mkey(ibp, smp, 0); - if (ret) { + if (ret) ret = IB_MAD_RESULT_FAILURE; goto bail; - } } } diff --git a/trunk/drivers/infiniband/hw/qib/qib_pcie.c b/trunk/drivers/infiniband/hw/qib/qib_pcie.c index c574ec7c85e6..062c301ebf53 100644 --- a/trunk/drivers/infiniband/hw/qib/qib_pcie.c +++ b/trunk/drivers/infiniband/hw/qib/qib_pcie.c @@ -273,9 +273,10 @@ int qib_pcie_params(struct qib_devdata *dd, u32 minw, u32 *nent, struct qib_msix_entry *entry) { u16 linkstat, speed; - int pos = 0, ret = 1; + int pos = 0, pose, ret = 1; - if (!pci_is_pcie(dd->pcidev)) { + pose = pci_pcie_cap(dd->pcidev); + if (!pose) { qib_dev_err(dd, "Can't find PCI Express capability!\n"); /* set up something... */ dd->lbus_width = 1; @@ -297,7 +298,7 @@ int qib_pcie_params(struct qib_devdata *dd, u32 minw, u32 *nent, if (!pos) qib_enable_intx(dd->pcidev); - pcie_capability_read_word(dd->pcidev, PCI_EXP_LNKSTA, &linkstat); + pci_read_config_word(dd->pcidev, pose + PCI_EXP_LNKSTA, &linkstat); /* * speed is bits 0-3, linkwidth is bits 4-8 * no defines for them in headers @@ -515,6 +516,7 @@ static int qib_tune_pcie_coalesce(struct qib_devdata *dd) { int r; struct pci_dev *parent; + int ppos; u16 devid; u32 mask, bits, val; @@ -527,7 +529,8 @@ static int qib_tune_pcie_coalesce(struct qib_devdata *dd) qib_devinfo(dd->pcidev, "Parent not root\n"); return 1; } - if (!pci_is_pcie(parent)) + ppos = pci_pcie_cap(parent); + if (!ppos) return 1; if (parent->vendor != 0x8086) return 1; @@ -584,6 +587,7 @@ static int qib_tune_pcie_caps(struct qib_devdata *dd) { int ret = 1; /* Assume the worst */ struct pci_dev *parent; + int ppos, epos; u16 pcaps, pctl, ecaps, ectl; int rc_sup, ep_sup; int rc_cur, ep_cur; @@ -594,15 +598,19 @@ static int qib_tune_pcie_caps(struct qib_devdata *dd) qib_devinfo(dd->pcidev, "Parent not root\n"); goto bail; } - - if (!pci_is_pcie(parent) || !pci_is_pcie(dd->pcidev)) + ppos = pci_pcie_cap(parent); + if (ppos) { + pci_read_config_word(parent, ppos + PCI_EXP_DEVCAP, &pcaps); + pci_read_config_word(parent, ppos + PCI_EXP_DEVCTL, &pctl); + } else goto bail; - pcie_capability_read_word(parent, PCI_EXP_DEVCAP, &pcaps); - pcie_capability_read_word(parent, PCI_EXP_DEVCTL, &pctl); /* Find out supported and configured values for endpoint (us) */ - pcie_capability_read_word(dd->pcidev, PCI_EXP_DEVCAP, &ecaps); - pcie_capability_read_word(dd->pcidev, PCI_EXP_DEVCTL, &ectl); - + epos = pci_pcie_cap(dd->pcidev); + if (epos) { + pci_read_config_word(dd->pcidev, epos + PCI_EXP_DEVCAP, &ecaps); + pci_read_config_word(dd->pcidev, epos + PCI_EXP_DEVCTL, &ectl); + } else + goto bail; ret = 0; /* Find max payload supported by root, endpoint */ rc_sup = fld2val(pcaps, PCI_EXP_DEVCAP_PAYLOAD); @@ -621,14 +629,14 @@ static int qib_tune_pcie_caps(struct qib_devdata *dd) rc_cur = rc_sup; pctl = (pctl & ~PCI_EXP_DEVCTL_PAYLOAD) | val2fld(rc_cur, PCI_EXP_DEVCTL_PAYLOAD); - pcie_capability_write_word(parent, PCI_EXP_DEVCTL, pctl); + pci_write_config_word(parent, ppos + PCI_EXP_DEVCTL, pctl); } /* If less than (allowed, supported), bump endpoint payload */ if (rc_sup > ep_cur) { ep_cur = rc_sup; ectl = (ectl & ~PCI_EXP_DEVCTL_PAYLOAD) | val2fld(ep_cur, PCI_EXP_DEVCTL_PAYLOAD); - pcie_capability_write_word(dd->pcidev, PCI_EXP_DEVCTL, ectl); + pci_write_config_word(dd->pcidev, epos + PCI_EXP_DEVCTL, ectl); } /* @@ -646,13 +654,13 @@ static int qib_tune_pcie_caps(struct qib_devdata *dd) rc_cur = rc_sup; pctl = (pctl & ~PCI_EXP_DEVCTL_READRQ) | val2fld(rc_cur, PCI_EXP_DEVCTL_READRQ); - pcie_capability_write_word(parent, PCI_EXP_DEVCTL, pctl); + pci_write_config_word(parent, ppos + PCI_EXP_DEVCTL, pctl); } if (rc_sup > ep_cur) { ep_cur = rc_sup; ectl = (ectl & ~PCI_EXP_DEVCTL_READRQ) | val2fld(ep_cur, PCI_EXP_DEVCTL_READRQ); - pcie_capability_write_word(dd->pcidev, PCI_EXP_DEVCTL, ectl); + pci_write_config_word(dd->pcidev, epos + PCI_EXP_DEVCTL, ectl); } bail: return ret; @@ -745,7 +753,7 @@ qib_pci_resume(struct pci_dev *pdev) qib_init(dd, 1); /* same as re-init after reset */ } -const struct pci_error_handlers qib_pci_err_handler = { +struct pci_error_handlers qib_pci_err_handler = { .error_detected = qib_pci_error_detected, .mmio_enabled = qib_pci_mmio_enabled, .link_reset = qib_pci_link_reset, diff --git a/trunk/drivers/infiniband/hw/qib/qib_sd7220.c b/trunk/drivers/infiniband/hw/qib/qib_sd7220.c index 50a8a0d4fe67..a322d5171a2c 100644 --- a/trunk/drivers/infiniband/hw/qib/qib_sd7220.c +++ b/trunk/drivers/infiniband/hw/qib/qib_sd7220.c @@ -372,7 +372,7 @@ static void qib_sd_trimdone_monitor(struct qib_devdata *dd, /* Read CTRL reg for each channel to check TRIMDONE */ if (baduns & (1 << chn)) { qib_dev_err(dd, - "Resetting TRIMDONE on chn %d (%s)\n", + "Reseting TRIMDONE on chn %d (%s)\n", chn, where); ret = qib_sd7220_reg_mod(dd, IB_7220_SERDES, IB_CTRL2(chn), 0x10, 0x10); diff --git a/trunk/drivers/infiniband/ulp/ipoib/ipoib.h b/trunk/drivers/infiniband/ulp/ipoib/ipoib.h index 0af216d21f87..ca43901ed861 100644 --- a/trunk/drivers/infiniband/ulp/ipoib/ipoib.h +++ b/trunk/drivers/infiniband/ulp/ipoib/ipoib.h @@ -262,10 +262,7 @@ struct ipoib_ethtool_st { u16 max_coalesced_frames; }; -struct ipoib_neigh_table; - struct ipoib_neigh_hash { - struct ipoib_neigh_table *ntbl; struct ipoib_neigh __rcu **buckets; struct rcu_head rcu; u32 mask; @@ -274,9 +271,9 @@ struct ipoib_neigh_hash { struct ipoib_neigh_table { struct ipoib_neigh_hash __rcu *htbl; + rwlock_t rwlock; atomic_t entries; struct completion flushed; - struct completion deleted; }; /* diff --git a/trunk/drivers/infiniband/ulp/ipoib/ipoib_cm.c b/trunk/drivers/infiniband/ulp/ipoib/ipoib_cm.c index 24683fda8e21..95ecf4eadf5f 100644 --- a/trunk/drivers/infiniband/ulp/ipoib/ipoib_cm.c +++ b/trunk/drivers/infiniband/ulp/ipoib/ipoib_cm.c @@ -1271,15 +1271,12 @@ struct ipoib_cm_tx *ipoib_cm_create_tx(struct net_device *dev, struct ipoib_path void ipoib_cm_destroy_tx(struct ipoib_cm_tx *tx) { struct ipoib_dev_priv *priv = netdev_priv(tx->dev); - unsigned long flags; if (test_and_clear_bit(IPOIB_FLAG_INITIALIZED, &tx->flags)) { - spin_lock_irqsave(&priv->lock, flags); list_move(&tx->list, &priv->cm.reap_list); queue_work(ipoib_workqueue, &priv->cm.reap_task); ipoib_dbg(priv, "Reap connection for gid %pI6\n", tx->neigh->daddr + 4); tx->neigh = NULL; - spin_unlock_irqrestore(&priv->lock, flags); } } diff --git a/trunk/drivers/infiniband/ulp/ipoib/ipoib_main.c b/trunk/drivers/infiniband/ulp/ipoib/ipoib_main.c index 1e19b5ae7c47..97920b77a5d0 100644 --- a/trunk/drivers/infiniband/ulp/ipoib/ipoib_main.c +++ b/trunk/drivers/infiniband/ulp/ipoib/ipoib_main.c @@ -546,15 +546,15 @@ static void neigh_add_path(struct sk_buff *skb, u8 *daddr, struct ipoib_neigh *neigh; unsigned long flags; - spin_lock_irqsave(&priv->lock, flags); neigh = ipoib_neigh_alloc(daddr, dev); if (!neigh) { - spin_unlock_irqrestore(&priv->lock, flags); ++dev->stats.tx_dropped; dev_kfree_skb_any(skb); return; } + spin_lock_irqsave(&priv->lock, flags); + path = __path_find(dev, daddr + 4); if (!path) { path = path_rec_create(dev, daddr + 4); @@ -863,10 +863,10 @@ static void __ipoib_reap_neigh(struct ipoib_dev_priv *priv) if (test_bit(IPOIB_STOP_NEIGH_GC, &priv->flags)) return; - spin_lock_irqsave(&priv->lock, flags); + write_lock_bh(&ntbl->rwlock); htbl = rcu_dereference_protected(ntbl->htbl, - lockdep_is_held(&priv->lock)); + lockdep_is_held(&ntbl->rwlock)); if (!htbl) goto out_unlock; @@ -883,14 +883,16 @@ static void __ipoib_reap_neigh(struct ipoib_dev_priv *priv) struct ipoib_neigh __rcu **np = &htbl->buckets[i]; while ((neigh = rcu_dereference_protected(*np, - lockdep_is_held(&priv->lock))) != NULL) { + lockdep_is_held(&ntbl->rwlock))) != NULL) { /* was the neigh idle for two GC periods */ if (time_after(neigh_obsolete, neigh->alive)) { rcu_assign_pointer(*np, rcu_dereference_protected(neigh->hnext, - lockdep_is_held(&priv->lock))); + lockdep_is_held(&ntbl->rwlock))); /* remove from path/mc list */ + spin_lock_irqsave(&priv->lock, flags); list_del(&neigh->list); + spin_unlock_irqrestore(&priv->lock, flags); call_rcu(&neigh->rcu, ipoib_neigh_reclaim); } else { np = &neigh->hnext; @@ -900,7 +902,7 @@ static void __ipoib_reap_neigh(struct ipoib_dev_priv *priv) } out_unlock: - spin_unlock_irqrestore(&priv->lock, flags); + write_unlock_bh(&ntbl->rwlock); } static void ipoib_reap_neigh(struct work_struct *work) @@ -945,8 +947,10 @@ struct ipoib_neigh *ipoib_neigh_alloc(u8 *daddr, struct ipoib_neigh *neigh; u32 hash_val; + write_lock_bh(&ntbl->rwlock); + htbl = rcu_dereference_protected(ntbl->htbl, - lockdep_is_held(&priv->lock)); + lockdep_is_held(&ntbl->rwlock)); if (!htbl) { neigh = NULL; goto out_unlock; @@ -957,10 +961,10 @@ struct ipoib_neigh *ipoib_neigh_alloc(u8 *daddr, */ hash_val = ipoib_addr_hash(htbl, daddr); for (neigh = rcu_dereference_protected(htbl->buckets[hash_val], - lockdep_is_held(&priv->lock)); + lockdep_is_held(&ntbl->rwlock)); neigh != NULL; neigh = rcu_dereference_protected(neigh->hnext, - lockdep_is_held(&priv->lock))) { + lockdep_is_held(&ntbl->rwlock))) { if (memcmp(daddr, neigh->daddr, INFINIBAND_ALEN) == 0) { /* found, take one ref on behalf of the caller */ if (!atomic_inc_not_zero(&neigh->refcnt)) { @@ -983,11 +987,12 @@ struct ipoib_neigh *ipoib_neigh_alloc(u8 *daddr, /* put in hash */ rcu_assign_pointer(neigh->hnext, rcu_dereference_protected(htbl->buckets[hash_val], - lockdep_is_held(&priv->lock))); + lockdep_is_held(&ntbl->rwlock))); rcu_assign_pointer(htbl->buckets[hash_val], neigh); atomic_inc(&ntbl->entries); out_unlock: + write_unlock_bh(&ntbl->rwlock); return neigh; } @@ -1035,29 +1040,35 @@ void ipoib_neigh_free(struct ipoib_neigh *neigh) struct ipoib_neigh *n; u32 hash_val; + write_lock_bh(&ntbl->rwlock); + htbl = rcu_dereference_protected(ntbl->htbl, - lockdep_is_held(&priv->lock)); + lockdep_is_held(&ntbl->rwlock)); if (!htbl) - return; + goto out_unlock; hash_val = ipoib_addr_hash(htbl, neigh->daddr); np = &htbl->buckets[hash_val]; for (n = rcu_dereference_protected(*np, - lockdep_is_held(&priv->lock)); + lockdep_is_held(&ntbl->rwlock)); n != NULL; - n = rcu_dereference_protected(*np, - lockdep_is_held(&priv->lock))) { + n = rcu_dereference_protected(neigh->hnext, + lockdep_is_held(&ntbl->rwlock))) { if (n == neigh) { /* found */ rcu_assign_pointer(*np, rcu_dereference_protected(neigh->hnext, - lockdep_is_held(&priv->lock))); + lockdep_is_held(&ntbl->rwlock))); call_rcu(&neigh->rcu, ipoib_neigh_reclaim); - return; + goto out_unlock; } else { np = &n->hnext; } } + +out_unlock: + write_unlock_bh(&ntbl->rwlock); + } static int ipoib_neigh_hash_init(struct ipoib_dev_priv *priv) @@ -1069,6 +1080,7 @@ static int ipoib_neigh_hash_init(struct ipoib_dev_priv *priv) clear_bit(IPOIB_NEIGH_TBL_FLUSH, &priv->flags); ntbl->htbl = NULL; + rwlock_init(&ntbl->rwlock); htbl = kzalloc(sizeof(*htbl), GFP_KERNEL); if (!htbl) return -ENOMEM; @@ -1083,7 +1095,6 @@ static int ipoib_neigh_hash_init(struct ipoib_dev_priv *priv) htbl->mask = (size - 1); htbl->buckets = buckets; ntbl->htbl = htbl; - htbl->ntbl = ntbl; atomic_set(&ntbl->entries, 0); /* start garbage collection */ @@ -1100,11 +1111,9 @@ static void neigh_hash_free_rcu(struct rcu_head *head) struct ipoib_neigh_hash, rcu); struct ipoib_neigh __rcu **buckets = htbl->buckets; - struct ipoib_neigh_table *ntbl = htbl->ntbl; kfree(buckets); kfree(htbl); - complete(&ntbl->deleted); } void ipoib_del_neighs_by_gid(struct net_device *dev, u8 *gid) @@ -1116,10 +1125,10 @@ void ipoib_del_neighs_by_gid(struct net_device *dev, u8 *gid) int i; /* remove all neigh connected to a given path or mcast */ - spin_lock_irqsave(&priv->lock, flags); + write_lock_bh(&ntbl->rwlock); htbl = rcu_dereference_protected(ntbl->htbl, - lockdep_is_held(&priv->lock)); + lockdep_is_held(&ntbl->rwlock)); if (!htbl) goto out_unlock; @@ -1129,14 +1138,16 @@ void ipoib_del_neighs_by_gid(struct net_device *dev, u8 *gid) struct ipoib_neigh __rcu **np = &htbl->buckets[i]; while ((neigh = rcu_dereference_protected(*np, - lockdep_is_held(&priv->lock))) != NULL) { + lockdep_is_held(&ntbl->rwlock))) != NULL) { /* delete neighs belong to this parent */ if (!memcmp(gid, neigh->daddr + 4, sizeof (union ib_gid))) { rcu_assign_pointer(*np, rcu_dereference_protected(neigh->hnext, - lockdep_is_held(&priv->lock))); + lockdep_is_held(&ntbl->rwlock))); /* remove from parent list */ + spin_lock_irqsave(&priv->lock, flags); list_del(&neigh->list); + spin_unlock_irqrestore(&priv->lock, flags); call_rcu(&neigh->rcu, ipoib_neigh_reclaim); } else { np = &neigh->hnext; @@ -1145,7 +1156,7 @@ void ipoib_del_neighs_by_gid(struct net_device *dev, u8 *gid) } } out_unlock: - spin_unlock_irqrestore(&priv->lock, flags); + write_unlock_bh(&ntbl->rwlock); } static void ipoib_flush_neighs(struct ipoib_dev_priv *priv) @@ -1153,44 +1164,37 @@ static void ipoib_flush_neighs(struct ipoib_dev_priv *priv) struct ipoib_neigh_table *ntbl = &priv->ntbl; struct ipoib_neigh_hash *htbl; unsigned long flags; - int i, wait_flushed = 0; - - init_completion(&priv->ntbl.flushed); + int i; - spin_lock_irqsave(&priv->lock, flags); + write_lock_bh(&ntbl->rwlock); htbl = rcu_dereference_protected(ntbl->htbl, - lockdep_is_held(&priv->lock)); + lockdep_is_held(&ntbl->rwlock)); if (!htbl) goto out_unlock; - wait_flushed = atomic_read(&priv->ntbl.entries); - if (!wait_flushed) - goto free_htbl; - for (i = 0; i < htbl->size; i++) { struct ipoib_neigh *neigh; struct ipoib_neigh __rcu **np = &htbl->buckets[i]; while ((neigh = rcu_dereference_protected(*np, - lockdep_is_held(&priv->lock))) != NULL) { + lockdep_is_held(&ntbl->rwlock))) != NULL) { rcu_assign_pointer(*np, rcu_dereference_protected(neigh->hnext, - lockdep_is_held(&priv->lock))); + lockdep_is_held(&ntbl->rwlock))); /* remove from path/mc list */ + spin_lock_irqsave(&priv->lock, flags); list_del(&neigh->list); + spin_unlock_irqrestore(&priv->lock, flags); call_rcu(&neigh->rcu, ipoib_neigh_reclaim); } } -free_htbl: rcu_assign_pointer(ntbl->htbl, NULL); call_rcu(&htbl->rcu, neigh_hash_free_rcu); out_unlock: - spin_unlock_irqrestore(&priv->lock, flags); - if (wait_flushed) - wait_for_completion(&priv->ntbl.flushed); + write_unlock_bh(&ntbl->rwlock); } static void ipoib_neigh_hash_uninit(struct net_device *dev) @@ -1199,7 +1203,7 @@ static void ipoib_neigh_hash_uninit(struct net_device *dev) int stopped; ipoib_dbg(priv, "ipoib_neigh_hash_uninit\n"); - init_completion(&priv->ntbl.deleted); + init_completion(&priv->ntbl.flushed); set_bit(IPOIB_NEIGH_TBL_FLUSH, &priv->flags); /* Stop GC if called at init fail need to cancel work */ @@ -1207,9 +1211,10 @@ static void ipoib_neigh_hash_uninit(struct net_device *dev) if (!stopped) cancel_delayed_work(&priv->neigh_reap_task); - ipoib_flush_neighs(priv); - - wait_for_completion(&priv->ntbl.deleted); + if (atomic_read(&priv->ntbl.entries)) { + ipoib_flush_neighs(priv); + wait_for_completion(&priv->ntbl.flushed); + } } diff --git a/trunk/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/trunk/drivers/infiniband/ulp/ipoib/ipoib_multicast.c index 75367249f447..13f4aa7593c8 100644 --- a/trunk/drivers/infiniband/ulp/ipoib/ipoib_multicast.c +++ b/trunk/drivers/infiniband/ulp/ipoib/ipoib_multicast.c @@ -707,7 +707,9 @@ void ipoib_mcast_send(struct net_device *dev, u8 *daddr, struct sk_buff *skb) neigh = ipoib_neigh_get(dev, daddr); spin_lock_irqsave(&priv->lock, flags); if (!neigh) { + spin_unlock_irqrestore(&priv->lock, flags); neigh = ipoib_neigh_alloc(daddr, dev); + spin_lock_irqsave(&priv->lock, flags); if (neigh) { kref_get(&mcast->ah->ref); neigh->ah = mcast->ah; diff --git a/trunk/drivers/infiniband/ulp/srp/ib_srp.c b/trunk/drivers/infiniband/ulp/srp/ib_srp.c index 1b5b0c730054..bcbf22ee0aa7 100644 --- a/trunk/drivers/infiniband/ulp/srp/ib_srp.c +++ b/trunk/drivers/infiniband/ulp/srp/ib_srp.c @@ -586,62 +586,24 @@ static void srp_unmap_data(struct scsi_cmnd *scmnd, scmnd->sc_data_direction); } -/** - * srp_claim_req - Take ownership of the scmnd associated with a request. - * @target: SRP target port. - * @req: SRP request. - * @scmnd: If NULL, take ownership of @req->scmnd. If not NULL, only take - * ownership of @req->scmnd if it equals @scmnd. - * - * Return value: - * Either NULL or a pointer to the SCSI command the caller became owner of. - */ -static struct scsi_cmnd *srp_claim_req(struct srp_target_port *target, - struct srp_request *req, - struct scsi_cmnd *scmnd) -{ - unsigned long flags; - - spin_lock_irqsave(&target->lock, flags); - if (!scmnd) { - scmnd = req->scmnd; - req->scmnd = NULL; - } else if (req->scmnd == scmnd) { - req->scmnd = NULL; - } else { - scmnd = NULL; - } - spin_unlock_irqrestore(&target->lock, flags); - - return scmnd; -} - -/** - * srp_free_req() - Unmap data and add request to the free request list. - */ -static void srp_free_req(struct srp_target_port *target, - struct srp_request *req, struct scsi_cmnd *scmnd, - s32 req_lim_delta) +static void srp_remove_req(struct srp_target_port *target, + struct srp_request *req, s32 req_lim_delta) { unsigned long flags; - srp_unmap_data(scmnd, target, req); - + srp_unmap_data(req->scmnd, target, req); spin_lock_irqsave(&target->lock, flags); target->req_lim += req_lim_delta; + req->scmnd = NULL; list_add_tail(&req->list, &target->free_reqs); spin_unlock_irqrestore(&target->lock, flags); } static void srp_reset_req(struct srp_target_port *target, struct srp_request *req) { - struct scsi_cmnd *scmnd = srp_claim_req(target, req, NULL); - - if (scmnd) { - scmnd->result = DID_RESET << 16; - scmnd->scsi_done(scmnd); - srp_free_req(target, req, scmnd, 0); - } + req->scmnd->result = DID_RESET << 16; + req->scmnd->scsi_done(req->scmnd); + srp_remove_req(target, req, 0); } static int srp_reconnect_target(struct srp_target_port *target) @@ -1111,18 +1073,11 @@ static void srp_process_rsp(struct srp_target_port *target, struct srp_rsp *rsp) complete(&target->tsk_mgmt_done); } else { req = &target->req_ring[rsp->tag]; - scmnd = srp_claim_req(target, req, NULL); - if (!scmnd) { + scmnd = req->scmnd; + if (!scmnd) shost_printk(KERN_ERR, target->scsi_host, "Null scmnd for RSP w/tag %016llx\n", (unsigned long long) rsp->tag); - - spin_lock_irqsave(&target->lock, flags); - target->req_lim += be32_to_cpu(rsp->req_lim_delta); - spin_unlock_irqrestore(&target->lock, flags); - - return; - } scmnd->result = rsp->status; if (rsp->flags & SRP_RSP_FLAG_SNSVALID) { @@ -1137,9 +1092,7 @@ static void srp_process_rsp(struct srp_target_port *target, struct srp_rsp *rsp) else if (rsp->flags & (SRP_RSP_FLAG_DIOVER | SRP_RSP_FLAG_DIUNDER)) scsi_set_resid(scmnd, be32_to_cpu(rsp->data_in_res_cnt)); - srp_free_req(target, req, scmnd, - be32_to_cpu(rsp->req_lim_delta)); - + srp_remove_req(target, req, be32_to_cpu(rsp->req_lim_delta)); scmnd->host_scribble = NULL; scmnd->scsi_done(scmnd); } @@ -1678,17 +1631,25 @@ static int srp_abort(struct scsi_cmnd *scmnd) { struct srp_target_port *target = host_to_target(scmnd->device->host); struct srp_request *req = (struct srp_request *) scmnd->host_scribble; + int ret = SUCCESS; shost_printk(KERN_ERR, target->scsi_host, "SRP abort called\n"); - if (!req || target->qp_in_error || !srp_claim_req(target, req, scmnd)) + if (!req || target->qp_in_error) + return FAILED; + if (srp_send_tsk_mgmt(target, req->index, scmnd->device->lun, + SRP_TSK_ABORT_TASK)) return FAILED; - srp_send_tsk_mgmt(target, req->index, scmnd->device->lun, - SRP_TSK_ABORT_TASK); - srp_free_req(target, req, scmnd, 0); - scmnd->result = DID_ABORT << 16; - return SUCCESS; + if (req->scmnd) { + if (!target->tsk_mgmt_status) { + srp_remove_req(target, req, 0); + scmnd->result = DID_ABORT << 16; + } else + ret = FAILED; + } + + return ret; } static int srp_reset_device(struct scsi_cmnd *scmnd) diff --git a/trunk/drivers/infiniband/ulp/srpt/ib_srpt.c b/trunk/drivers/infiniband/ulp/srpt/ib_srpt.c index 9e1449f8c6a2..7a0ce8d42887 100644 --- a/trunk/drivers/infiniband/ulp/srpt/ib_srpt.c +++ b/trunk/drivers/infiniband/ulp/srpt/ib_srpt.c @@ -1469,7 +1469,7 @@ static void srpt_handle_send_comp(struct srpt_rdma_ch *ch, * * XXX: what is now target_execute_cmd used to be asynchronous, and unmapping * the data that has been transferred via IB RDMA had to be postponed until the - * check_stop_free() callback. None of this is necessary anymore and needs to + * check_stop_free() callback. None of this is nessecary anymore and needs to * be cleaned up. */ static void srpt_handle_rdma_comp(struct srpt_rdma_ch *ch, diff --git a/trunk/drivers/input/evdev.c b/trunk/drivers/input/evdev.c index 118d0300f1fb..6c58bfff01a3 100644 --- a/trunk/drivers/input/evdev.c +++ b/trunk/drivers/input/evdev.c @@ -54,9 +54,16 @@ struct evdev_client { static struct evdev *evdev_table[EVDEV_MINORS]; static DEFINE_MUTEX(evdev_table_mutex); -static void __pass_event(struct evdev_client *client, - const struct input_event *event) +static void evdev_pass_event(struct evdev_client *client, + struct input_event *event, + ktime_t mono, ktime_t real) { + event->time = ktime_to_timeval(client->clkid == CLOCK_MONOTONIC ? + mono : real); + + /* Interrupts are disabled, just acquire the lock. */ + spin_lock(&client->buffer_lock); + client->buffer[client->head++] = *event; client->head &= client->bufsize - 1; @@ -79,74 +86,42 @@ static void __pass_event(struct evdev_client *client, client->packet_head = client->head; kill_fasync(&client->fasync, SIGIO, POLL_IN); } -} - -static void evdev_pass_values(struct evdev_client *client, - const struct input_value *vals, unsigned int count, - ktime_t mono, ktime_t real) -{ - struct evdev *evdev = client->evdev; - const struct input_value *v; - struct input_event event; - bool wakeup = false; - - event.time = ktime_to_timeval(client->clkid == CLOCK_MONOTONIC ? - mono : real); - - /* Interrupts are disabled, just acquire the lock. */ - spin_lock(&client->buffer_lock); - - for (v = vals; v != vals + count; v++) { - event.type = v->type; - event.code = v->code; - event.value = v->value; - __pass_event(client, &event); - if (v->type == EV_SYN && v->code == SYN_REPORT) - wakeup = true; - } spin_unlock(&client->buffer_lock); - - if (wakeup) - wake_up_interruptible(&evdev->wait); } /* - * Pass incoming events to all connected clients. + * Pass incoming event to all connected clients. */ -static void evdev_events(struct input_handle *handle, - const struct input_value *vals, unsigned int count) +static void evdev_event(struct input_handle *handle, + unsigned int type, unsigned int code, int value) { struct evdev *evdev = handle->private; struct evdev_client *client; + struct input_event event; ktime_t time_mono, time_real; time_mono = ktime_get(); time_real = ktime_sub(time_mono, ktime_get_monotonic_offset()); + event.type = type; + event.code = code; + event.value = value; + rcu_read_lock(); client = rcu_dereference(evdev->grab); if (client) - evdev_pass_values(client, vals, count, time_mono, time_real); + evdev_pass_event(client, &event, time_mono, time_real); else list_for_each_entry_rcu(client, &evdev->client_list, node) - evdev_pass_values(client, vals, count, - time_mono, time_real); + evdev_pass_event(client, &event, time_mono, time_real); rcu_read_unlock(); -} - -/* - * Pass incoming event to all connected clients. - */ -static void evdev_event(struct input_handle *handle, - unsigned int type, unsigned int code, int value) -{ - struct input_value vals[] = { { type, code, value } }; - evdev_events(handle, vals, 1); + if (type == EV_SYN && code == SYN_REPORT) + wake_up_interruptible(&evdev->wait); } static int evdev_fasync(int fd, struct file *file, int on) @@ -678,22 +653,20 @@ static int evdev_handle_mt_request(struct input_dev *dev, unsigned int size, int __user *ip) { - const struct input_mt *mt = dev->mt; + const struct input_mt_slot *mt = dev->mt; unsigned int code; int max_slots; int i; if (get_user(code, &ip[0])) return -EFAULT; - if (!mt || !input_is_mt_value(code)) + if (!input_is_mt_value(code)) return -EINVAL; max_slots = (size - sizeof(__u32)) / sizeof(__s32); - for (i = 0; i < mt->num_slots && i < max_slots; i++) { - int value = input_mt_get_value(&mt->slots[i], code); - if (put_user(value, &ip[1 + i])) + for (i = 0; i < dev->mtsize && i < max_slots; i++) + if (put_user(input_mt_get_value(&mt[i], code), &ip[1 + i])) return -EFAULT; - } return 0; } @@ -1075,7 +1048,6 @@ MODULE_DEVICE_TABLE(input, evdev_ids); static struct input_handler evdev_handler = { .event = evdev_event, - .events = evdev_events, .connect = evdev_connect, .disconnect = evdev_disconnect, .fops = &evdev_fops, diff --git a/trunk/drivers/input/input-mt.c b/trunk/drivers/input/input-mt.c index c0ec7d42c3be..70a16c7da8cc 100644 --- a/trunk/drivers/input/input-mt.c +++ b/trunk/drivers/input/input-mt.c @@ -14,14 +14,6 @@ #define TRKID_SGN ((TRKID_MAX + 1) >> 1) -static void copy_abs(struct input_dev *dev, unsigned int dst, unsigned int src) -{ - if (dev->absinfo && test_bit(src, dev->absbit)) { - dev->absinfo[dst] = dev->absinfo[src]; - dev->absbit[BIT_WORD(dst)] |= BIT_MASK(dst); - } -} - /** * input_mt_init_slots() - initialize MT input slots * @dev: input device supporting MT events and finger tracking @@ -33,63 +25,29 @@ static void copy_abs(struct input_dev *dev, unsigned int dst, unsigned int src) * May be called repeatedly. Returns -EINVAL if attempting to * reinitialize with a different number of slots. */ -int input_mt_init_slots(struct input_dev *dev, unsigned int num_slots, - unsigned int flags) +int input_mt_init_slots(struct input_dev *dev, unsigned int num_slots) { - struct input_mt *mt = dev->mt; int i; if (!num_slots) return 0; - if (mt) - return mt->num_slots != num_slots ? -EINVAL : 0; + if (dev->mt) + return dev->mtsize != num_slots ? -EINVAL : 0; - mt = kzalloc(sizeof(*mt) + num_slots * sizeof(*mt->slots), GFP_KERNEL); - if (!mt) - goto err_mem; + dev->mt = kcalloc(num_slots, sizeof(struct input_mt_slot), GFP_KERNEL); + if (!dev->mt) + return -ENOMEM; - mt->num_slots = num_slots; - mt->flags = flags; + dev->mtsize = num_slots; input_set_abs_params(dev, ABS_MT_SLOT, 0, num_slots - 1, 0, 0); input_set_abs_params(dev, ABS_MT_TRACKING_ID, 0, TRKID_MAX, 0, 0); - - if (flags & (INPUT_MT_POINTER | INPUT_MT_DIRECT)) { - __set_bit(EV_KEY, dev->evbit); - __set_bit(BTN_TOUCH, dev->keybit); - - copy_abs(dev, ABS_X, ABS_MT_POSITION_X); - copy_abs(dev, ABS_Y, ABS_MT_POSITION_Y); - copy_abs(dev, ABS_PRESSURE, ABS_MT_PRESSURE); - } - if (flags & INPUT_MT_POINTER) { - __set_bit(BTN_TOOL_FINGER, dev->keybit); - __set_bit(BTN_TOOL_DOUBLETAP, dev->keybit); - if (num_slots >= 3) - __set_bit(BTN_TOOL_TRIPLETAP, dev->keybit); - if (num_slots >= 4) - __set_bit(BTN_TOOL_QUADTAP, dev->keybit); - if (num_slots >= 5) - __set_bit(BTN_TOOL_QUINTTAP, dev->keybit); - __set_bit(INPUT_PROP_POINTER, dev->propbit); - } - if (flags & INPUT_MT_DIRECT) - __set_bit(INPUT_PROP_DIRECT, dev->propbit); - if (flags & INPUT_MT_TRACK) { - unsigned int n2 = num_slots * num_slots; - mt->red = kcalloc(n2, sizeof(*mt->red), GFP_KERNEL); - if (!mt->red) - goto err_mem; - } + input_set_events_per_packet(dev, 6 * num_slots); /* Mark slots as 'unused' */ for (i = 0; i < num_slots; i++) - input_mt_set_value(&mt->slots[i], ABS_MT_TRACKING_ID, -1); + input_mt_set_value(&dev->mt[i], ABS_MT_TRACKING_ID, -1); - dev->mt = mt; return 0; -err_mem: - kfree(mt); - return -ENOMEM; } EXPORT_SYMBOL(input_mt_init_slots); @@ -102,11 +60,11 @@ EXPORT_SYMBOL(input_mt_init_slots); */ void input_mt_destroy_slots(struct input_dev *dev) { - if (dev->mt) { - kfree(dev->mt->red); - kfree(dev->mt); - } + kfree(dev->mt); dev->mt = NULL; + dev->mtsize = 0; + dev->slot = 0; + dev->trkid = 0; } EXPORT_SYMBOL(input_mt_destroy_slots); @@ -125,24 +83,18 @@ EXPORT_SYMBOL(input_mt_destroy_slots); void input_mt_report_slot_state(struct input_dev *dev, unsigned int tool_type, bool active) { - struct input_mt *mt = dev->mt; - struct input_mt_slot *slot; + struct input_mt_slot *mt; int id; - if (!mt) - return; - - slot = &mt->slots[mt->slot]; - slot->frame = mt->frame; - - if (!active) { + if (!dev->mt || !active) { input_event(dev, EV_ABS, ABS_MT_TRACKING_ID, -1); return; } - id = input_mt_get_value(slot, ABS_MT_TRACKING_ID); - if (id < 0 || input_mt_get_value(slot, ABS_MT_TOOL_TYPE) != tool_type) - id = input_mt_new_trkid(mt); + mt = &dev->mt[dev->slot]; + id = input_mt_get_value(mt, ABS_MT_TRACKING_ID); + if (id < 0 || input_mt_get_value(mt, ABS_MT_TOOL_TYPE) != tool_type) + id = input_mt_new_trkid(dev); input_event(dev, EV_ABS, ABS_MT_TRACKING_ID, id); input_event(dev, EV_ABS, ABS_MT_TOOL_TYPE, tool_type); @@ -183,19 +135,13 @@ EXPORT_SYMBOL(input_mt_report_finger_count); */ void input_mt_report_pointer_emulation(struct input_dev *dev, bool use_count) { - struct input_mt *mt = dev->mt; - struct input_mt_slot *oldest; - int oldid, count, i; - - if (!mt) - return; - - oldest = 0; - oldid = mt->trkid; - count = 0; + struct input_mt_slot *oldest = NULL; + int oldid = dev->trkid; + int count = 0; + int i; - for (i = 0; i < mt->num_slots; ++i) { - struct input_mt_slot *ps = &mt->slots[i]; + for (i = 0; i < dev->mtsize; ++i) { + struct input_mt_slot *ps = &dev->mt[i]; int id = input_mt_get_value(ps, ABS_MT_TRACKING_ID); if (id < 0) @@ -214,208 +160,13 @@ void input_mt_report_pointer_emulation(struct input_dev *dev, bool use_count) if (oldest) { int x = input_mt_get_value(oldest, ABS_MT_POSITION_X); int y = input_mt_get_value(oldest, ABS_MT_POSITION_Y); + int p = input_mt_get_value(oldest, ABS_MT_PRESSURE); input_event(dev, EV_ABS, ABS_X, x); input_event(dev, EV_ABS, ABS_Y, y); - - if (test_bit(ABS_MT_PRESSURE, dev->absbit)) { - int p = input_mt_get_value(oldest, ABS_MT_PRESSURE); - input_event(dev, EV_ABS, ABS_PRESSURE, p); - } + input_event(dev, EV_ABS, ABS_PRESSURE, p); } else { - if (test_bit(ABS_MT_PRESSURE, dev->absbit)) - input_event(dev, EV_ABS, ABS_PRESSURE, 0); + input_event(dev, EV_ABS, ABS_PRESSURE, 0); } } EXPORT_SYMBOL(input_mt_report_pointer_emulation); - -/** - * input_mt_sync_frame() - synchronize mt frame - * @dev: input device with allocated MT slots - * - * Close the frame and prepare the internal state for a new one. - * Depending on the flags, marks unused slots as inactive and performs - * pointer emulation. - */ -void input_mt_sync_frame(struct input_dev *dev) -{ - struct input_mt *mt = dev->mt; - struct input_mt_slot *s; - - if (!mt) - return; - - if (mt->flags & INPUT_MT_DROP_UNUSED) { - for (s = mt->slots; s != mt->slots + mt->num_slots; s++) { - if (s->frame == mt->frame) - continue; - input_mt_slot(dev, s - mt->slots); - input_event(dev, EV_ABS, ABS_MT_TRACKING_ID, -1); - } - } - - input_mt_report_pointer_emulation(dev, (mt->flags & INPUT_MT_POINTER)); - - mt->frame++; -} -EXPORT_SYMBOL(input_mt_sync_frame); - -static int adjust_dual(int *begin, int step, int *end, int eq) -{ - int f, *p, s, c; - - if (begin == end) - return 0; - - f = *begin; - p = begin + step; - s = p == end ? f + 1 : *p; - - for (; p != end; p += step) - if (*p < f) - s = f, f = *p; - else if (*p < s) - s = *p; - - c = (f + s + 1) / 2; - if (c == 0 || (c > 0 && !eq)) - return 0; - if (s < 0) - c *= 2; - - for (p = begin; p != end; p += step) - *p -= c; - - return (c < s && s <= 0) || (f >= 0 && f < c); -} - -static void find_reduced_matrix(int *w, int nr, int nc, int nrc) -{ - int i, k, sum; - - for (k = 0; k < nrc; k++) { - for (i = 0; i < nr; i++) - adjust_dual(w + i, nr, w + i + nrc, nr <= nc); - sum = 0; - for (i = 0; i < nrc; i += nr) - sum += adjust_dual(w + i, 1, w + i + nr, nc <= nr); - if (!sum) - break; - } -} - -static int input_mt_set_matrix(struct input_mt *mt, - const struct input_mt_pos *pos, int num_pos) -{ - const struct input_mt_pos *p; - struct input_mt_slot *s; - int *w = mt->red; - int x, y; - - for (s = mt->slots; s != mt->slots + mt->num_slots; s++) { - if (!input_mt_is_active(s)) - continue; - x = input_mt_get_value(s, ABS_MT_POSITION_X); - y = input_mt_get_value(s, ABS_MT_POSITION_Y); - for (p = pos; p != pos + num_pos; p++) { - int dx = x - p->x, dy = y - p->y; - *w++ = dx * dx + dy * dy; - } - } - - return w - mt->red; -} - -static void input_mt_set_slots(struct input_mt *mt, - int *slots, int num_pos) -{ - struct input_mt_slot *s; - int *w = mt->red, *p; - - for (p = slots; p != slots + num_pos; p++) - *p = -1; - - for (s = mt->slots; s != mt->slots + mt->num_slots; s++) { - if (!input_mt_is_active(s)) - continue; - for (p = slots; p != slots + num_pos; p++) - if (*w++ < 0) - *p = s - mt->slots; - } - - for (s = mt->slots; s != mt->slots + mt->num_slots; s++) { - if (input_mt_is_active(s)) - continue; - for (p = slots; p != slots + num_pos; p++) - if (*p < 0) { - *p = s - mt->slots; - break; - } - } -} - -/** - * input_mt_assign_slots() - perform a best-match assignment - * @dev: input device with allocated MT slots - * @slots: the slot assignment to be filled - * @pos: the position array to match - * @num_pos: number of positions - * - * Performs a best match against the current contacts and returns - * the slot assignment list. New contacts are assigned to unused - * slots. - * - * Returns zero on success, or negative error in case of failure. - */ -int input_mt_assign_slots(struct input_dev *dev, int *slots, - const struct input_mt_pos *pos, int num_pos) -{ - struct input_mt *mt = dev->mt; - int nrc; - - if (!mt || !mt->red) - return -ENXIO; - if (num_pos > mt->num_slots) - return -EINVAL; - if (num_pos < 1) - return 0; - - nrc = input_mt_set_matrix(mt, pos, num_pos); - find_reduced_matrix(mt->red, num_pos, nrc / num_pos, nrc); - input_mt_set_slots(mt, slots, num_pos); - - return 0; -} -EXPORT_SYMBOL(input_mt_assign_slots); - -/** - * input_mt_get_slot_by_key() - return slot matching key - * @dev: input device with allocated MT slots - * @key: the key of the sought slot - * - * Returns the slot of the given key, if it exists, otherwise - * set the key on the first unused slot and return. - * - * If no available slot can be found, -1 is returned. - */ -int input_mt_get_slot_by_key(struct input_dev *dev, int key) -{ - struct input_mt *mt = dev->mt; - struct input_mt_slot *s; - - if (!mt) - return -1; - - for (s = mt->slots; s != mt->slots + mt->num_slots; s++) - if (input_mt_is_active(s) && s->key == key) - return s - mt->slots; - - for (s = mt->slots; s != mt->slots + mt->num_slots; s++) - if (!input_mt_is_active(s)) { - s->key = key; - return s - mt->slots; - } - - return -1; -} -EXPORT_SYMBOL(input_mt_get_slot_by_key); diff --git a/trunk/drivers/input/input.c b/trunk/drivers/input/input.c index 5244f3d05b12..8921c6180c51 100644 --- a/trunk/drivers/input/input.c +++ b/trunk/drivers/input/input.c @@ -47,8 +47,6 @@ static DEFINE_MUTEX(input_mutex); static struct input_handler *input_table[8]; -static const struct input_value input_value_sync = { EV_SYN, SYN_REPORT, 1 }; - static inline int is_event_supported(unsigned int code, unsigned long *bm, unsigned int max) { @@ -71,102 +69,42 @@ static int input_defuzz_abs_event(int value, int old_val, int fuzz) return value; } -static void input_start_autorepeat(struct input_dev *dev, int code) -{ - if (test_bit(EV_REP, dev->evbit) && - dev->rep[REP_PERIOD] && dev->rep[REP_DELAY] && - dev->timer.data) { - dev->repeat_key = code; - mod_timer(&dev->timer, - jiffies + msecs_to_jiffies(dev->rep[REP_DELAY])); - } -} - -static void input_stop_autorepeat(struct input_dev *dev) -{ - del_timer(&dev->timer); -} - /* * Pass event first through all filters and then, if event has not been * filtered out, through all open handles. This function is called with * dev->event_lock held and interrupts disabled. */ -static unsigned int input_to_handler(struct input_handle *handle, - struct input_value *vals, unsigned int count) -{ - struct input_handler *handler = handle->handler; - struct input_value *end = vals; - struct input_value *v; - - for (v = vals; v != vals + count; v++) { - if (handler->filter && - handler->filter(handle, v->type, v->code, v->value)) - continue; - if (end != v) - *end = *v; - end++; - } - - count = end - vals; - if (!count) - return 0; - - if (handler->events) - handler->events(handle, vals, count); - else if (handler->event) - for (v = vals; v != end; v++) - handler->event(handle, v->type, v->code, v->value); - - return count; -} - -/* - * Pass values first through all filters and then, if event has not been - * filtered out, through all open handles. This function is called with - * dev->event_lock held and interrupts disabled. - */ -static void input_pass_values(struct input_dev *dev, - struct input_value *vals, unsigned int count) +static void input_pass_event(struct input_dev *dev, + unsigned int type, unsigned int code, int value) { + struct input_handler *handler; struct input_handle *handle; - struct input_value *v; - - if (!count) - return; rcu_read_lock(); handle = rcu_dereference(dev->grab); - if (handle) { - count = input_to_handler(handle, vals, count); - } else { - list_for_each_entry_rcu(handle, &dev->h_list, d_node) - if (handle->open) - count = input_to_handler(handle, vals, count); - } + if (handle) + handle->handler->event(handle, type, code, value); + else { + bool filtered = false; - rcu_read_unlock(); + list_for_each_entry_rcu(handle, &dev->h_list, d_node) { + if (!handle->open) + continue; - add_input_randomness(vals->type, vals->code, vals->value); + handler = handle->handler; + if (!handler->filter) { + if (filtered) + break; - /* trigger auto repeat for key events */ - for (v = vals; v != vals + count; v++) { - if (v->type == EV_KEY && v->value != 2) { - if (v->value) - input_start_autorepeat(dev, v->code); - else - input_stop_autorepeat(dev); + handler->event(handle, type, code, value); + + } else if (handler->filter(handle, type, code, value)) + filtered = true; } } -} - -static void input_pass_event(struct input_dev *dev, - unsigned int type, unsigned int code, int value) -{ - struct input_value vals[] = { { type, code, value } }; - input_pass_values(dev, vals, ARRAY_SIZE(vals)); + rcu_read_unlock(); } /* @@ -183,12 +121,18 @@ static void input_repeat_key(unsigned long data) if (test_bit(dev->repeat_key, dev->key) && is_event_supported(dev->repeat_key, dev->keybit, KEY_MAX)) { - struct input_value vals[] = { - { EV_KEY, dev->repeat_key, 2 }, - input_value_sync - }; - input_pass_values(dev, vals, ARRAY_SIZE(vals)); + input_pass_event(dev, EV_KEY, dev->repeat_key, 2); + + if (dev->sync) { + /* + * Only send SYN_REPORT if we are not in a middle + * of driver parsing a new hardware packet. + * Otherwise assume that the driver will send + * SYN_REPORT once it's done. + */ + input_pass_event(dev, EV_SYN, SYN_REPORT, 1); + } if (dev->rep[REP_PERIOD]) mod_timer(&dev->timer, jiffies + @@ -198,17 +142,30 @@ static void input_repeat_key(unsigned long data) spin_unlock_irqrestore(&dev->event_lock, flags); } +static void input_start_autorepeat(struct input_dev *dev, int code) +{ + if (test_bit(EV_REP, dev->evbit) && + dev->rep[REP_PERIOD] && dev->rep[REP_DELAY] && + dev->timer.data) { + dev->repeat_key = code; + mod_timer(&dev->timer, + jiffies + msecs_to_jiffies(dev->rep[REP_DELAY])); + } +} + +static void input_stop_autorepeat(struct input_dev *dev) +{ + del_timer(&dev->timer); +} + #define INPUT_IGNORE_EVENT 0 #define INPUT_PASS_TO_HANDLERS 1 #define INPUT_PASS_TO_DEVICE 2 -#define INPUT_SLOT 4 -#define INPUT_FLUSH 8 #define INPUT_PASS_TO_ALL (INPUT_PASS_TO_HANDLERS | INPUT_PASS_TO_DEVICE) static int input_handle_abs_event(struct input_dev *dev, unsigned int code, int *pval) { - struct input_mt *mt = dev->mt; bool is_mt_event; int *pold; @@ -217,8 +174,8 @@ static int input_handle_abs_event(struct input_dev *dev, * "Stage" the event; we'll flush it later, when we * get actual touch data. */ - if (mt && *pval >= 0 && *pval < mt->num_slots) - mt->slot = *pval; + if (*pval >= 0 && *pval < dev->mtsize) + dev->slot = *pval; return INPUT_IGNORE_EVENT; } @@ -227,8 +184,9 @@ static int input_handle_abs_event(struct input_dev *dev, if (!is_mt_event) { pold = &dev->absinfo[code].value; - } else if (mt) { - pold = &mt->slots[mt->slot].abs[code - ABS_MT_FIRST]; + } else if (dev->mt) { + struct input_mt_slot *mtslot = &dev->mt[dev->slot]; + pold = &mtslot->abs[code - ABS_MT_FIRST]; } else { /* * Bypass filtering for multi-touch events when @@ -247,16 +205,16 @@ static int input_handle_abs_event(struct input_dev *dev, } /* Flush pending "slot" event */ - if (is_mt_event && mt && mt->slot != input_abs_get_val(dev, ABS_MT_SLOT)) { - input_abs_set_val(dev, ABS_MT_SLOT, mt->slot); - return INPUT_PASS_TO_HANDLERS | INPUT_SLOT; + if (is_mt_event && dev->slot != input_abs_get_val(dev, ABS_MT_SLOT)) { + input_abs_set_val(dev, ABS_MT_SLOT, dev->slot); + input_pass_event(dev, EV_ABS, ABS_MT_SLOT, dev->slot); } return INPUT_PASS_TO_HANDLERS; } -static int input_get_disposition(struct input_dev *dev, - unsigned int type, unsigned int code, int value) +static void input_handle_event(struct input_dev *dev, + unsigned int type, unsigned int code, int value) { int disposition = INPUT_IGNORE_EVENT; @@ -269,34 +227,37 @@ static int input_get_disposition(struct input_dev *dev, break; case SYN_REPORT: - disposition = INPUT_PASS_TO_HANDLERS | INPUT_FLUSH; + if (!dev->sync) { + dev->sync = true; + disposition = INPUT_PASS_TO_HANDLERS; + } break; case SYN_MT_REPORT: + dev->sync = false; disposition = INPUT_PASS_TO_HANDLERS; break; } break; case EV_KEY: - if (is_event_supported(code, dev->keybit, KEY_MAX)) { - - /* auto-repeat bypasses state updates */ - if (value == 2) { - disposition = INPUT_PASS_TO_HANDLERS; - break; - } - - if (!!test_bit(code, dev->key) != !!value) { + if (is_event_supported(code, dev->keybit, KEY_MAX) && + !!test_bit(code, dev->key) != value) { + if (value != 2) { __change_bit(code, dev->key); - disposition = INPUT_PASS_TO_HANDLERS; + if (value) + input_start_autorepeat(dev, code); + else + input_stop_autorepeat(dev); } + + disposition = INPUT_PASS_TO_HANDLERS; } break; case EV_SW: if (is_event_supported(code, dev->swbit, SW_MAX) && - !!test_bit(code, dev->sw) != !!value) { + !!test_bit(code, dev->sw) != value) { __change_bit(code, dev->sw); disposition = INPUT_PASS_TO_HANDLERS; @@ -323,7 +284,7 @@ static int input_get_disposition(struct input_dev *dev, case EV_LED: if (is_event_supported(code, dev->ledbit, LED_MAX) && - !!test_bit(code, dev->led) != !!value) { + !!test_bit(code, dev->led) != value) { __change_bit(code, dev->led); disposition = INPUT_PASS_TO_ALL; @@ -356,48 +317,14 @@ static int input_get_disposition(struct input_dev *dev, break; } - return disposition; -} - -static void input_handle_event(struct input_dev *dev, - unsigned int type, unsigned int code, int value) -{ - int disposition; - - disposition = input_get_disposition(dev, type, code, value); + if (disposition != INPUT_IGNORE_EVENT && type != EV_SYN) + dev->sync = false; if ((disposition & INPUT_PASS_TO_DEVICE) && dev->event) dev->event(dev, type, code, value); - if (!dev->vals) - return; - - if (disposition & INPUT_PASS_TO_HANDLERS) { - struct input_value *v; - - if (disposition & INPUT_SLOT) { - v = &dev->vals[dev->num_vals++]; - v->type = EV_ABS; - v->code = ABS_MT_SLOT; - v->value = dev->mt->slot; - } - - v = &dev->vals[dev->num_vals++]; - v->type = type; - v->code = code; - v->value = value; - } - - if (disposition & INPUT_FLUSH) { - if (dev->num_vals >= 2) - input_pass_values(dev, dev->vals, dev->num_vals); - dev->num_vals = 0; - } else if (dev->num_vals >= dev->max_vals - 2) { - dev->vals[dev->num_vals++] = input_value_sync; - input_pass_values(dev, dev->vals, dev->num_vals); - dev->num_vals = 0; - } - + if (disposition & INPUT_PASS_TO_HANDLERS) + input_pass_event(dev, type, code, value); } /** @@ -425,6 +352,7 @@ void input_event(struct input_dev *dev, if (is_event_supported(type, dev->evbit, EV_MAX)) { spin_lock_irqsave(&dev->event_lock, flags); + add_input_randomness(type, code, value); input_handle_event(dev, type, code, value); spin_unlock_irqrestore(&dev->event_lock, flags); } @@ -903,12 +831,10 @@ int input_set_keycode(struct input_dev *dev, if (test_bit(EV_KEY, dev->evbit) && !is_event_supported(old_keycode, dev->keybit, KEY_MAX) && __test_and_clear_bit(old_keycode, dev->key)) { - struct input_value vals[] = { - { EV_KEY, old_keycode, 0 }, - input_value_sync - }; - input_pass_values(dev, vals, ARRAY_SIZE(vals)); + input_pass_event(dev, EV_KEY, old_keycode, 0); + if (dev->sync) + input_pass_event(dev, EV_SYN, SYN_REPORT, 1); } out: @@ -1490,7 +1416,6 @@ static void input_dev_release(struct device *device) input_ff_destroy(dev); input_mt_destroy_slots(dev); kfree(dev->absinfo); - kfree(dev->vals); kfree(dev); module_put(THIS_MODULE); @@ -1826,8 +1751,8 @@ static unsigned int input_estimate_events_per_packet(struct input_dev *dev) int i; unsigned int events; - if (dev->mt) { - mt_slots = dev->mt->num_slots; + if (dev->mtsize) { + mt_slots = dev->mtsize; } else if (test_bit(ABS_MT_TRACKING_ID, dev->absbit)) { mt_slots = dev->absinfo[ABS_MT_TRACKING_ID].maximum - dev->absinfo[ABS_MT_TRACKING_ID].minimum + 1, @@ -1853,9 +1778,6 @@ static unsigned int input_estimate_events_per_packet(struct input_dev *dev) if (test_bit(i, dev->relbit)) events++; - /* Make room for KEY and MSC events */ - events += 7; - return events; } @@ -1894,7 +1816,6 @@ int input_register_device(struct input_dev *dev) { static atomic_t input_no = ATOMIC_INIT(0); struct input_handler *handler; - unsigned int packet_size; const char *path; int error; @@ -1907,14 +1828,9 @@ int input_register_device(struct input_dev *dev) /* Make sure that bitmasks not mentioned in dev->evbit are clean. */ input_cleanse_bitmasks(dev); - packet_size = input_estimate_events_per_packet(dev); - if (dev->hint_events_per_packet < packet_size) - dev->hint_events_per_packet = packet_size; - - dev->max_vals = max(dev->hint_events_per_packet, packet_size) + 2; - dev->vals = kcalloc(dev->max_vals, sizeof(*dev->vals), GFP_KERNEL); - if (!dev->vals) - return -ENOMEM; + if (!dev->hint_events_per_packet) + dev->hint_events_per_packet = + input_estimate_events_per_packet(dev); /* * If delay and period are pre-set by the driver, then autorepeating diff --git a/trunk/drivers/input/keyboard/imx_keypad.c b/trunk/drivers/input/keyboard/imx_keypad.c index cdc252612c0b..ff4c0a87a25f 100644 --- a/trunk/drivers/input/keyboard/imx_keypad.c +++ b/trunk/drivers/input/keyboard/imx_keypad.c @@ -358,7 +358,6 @@ static void imx_keypad_inhibit(struct imx_keypad *keypad) /* Inhibit KDI and KRI interrupts. */ reg_val = readw(keypad->mmio_base + KPSR); reg_val &= ~(KBD_STAT_KRIE | KBD_STAT_KDIE); - reg_val |= KBD_STAT_KPKR | KBD_STAT_KPKD; writew(reg_val, keypad->mmio_base + KPSR); /* Colums as open drain and disable all rows */ @@ -516,9 +515,7 @@ static int __devinit imx_keypad_probe(struct platform_device *pdev) input_set_drvdata(input_dev, keypad); /* Ensure that the keypad will stay dormant until opened */ - clk_prepare_enable(keypad->clk); imx_keypad_inhibit(keypad); - clk_disable_unprepare(keypad->clk); error = request_irq(irq, imx_keypad_irq_handler, 0, pdev->name, keypad); diff --git a/trunk/drivers/input/misc/ab8500-ponkey.c b/trunk/drivers/input/misc/ab8500-ponkey.c index 84ec691c05aa..f06231b7cab1 100644 --- a/trunk/drivers/input/misc/ab8500-ponkey.c +++ b/trunk/drivers/input/misc/ab8500-ponkey.c @@ -74,8 +74,8 @@ static int __devinit ab8500_ponkey_probe(struct platform_device *pdev) ponkey->idev = input; ponkey->ab8500 = ab8500; - ponkey->irq_dbf = irq_dbf; - ponkey->irq_dbr = irq_dbr; + ponkey->irq_dbf = ab8500_irq_get_virq(ab8500, irq_dbf); + ponkey->irq_dbr = ab8500_irq_get_virq(ab8500, irq_dbr); input->name = "AB8500 POn(PowerOn) Key"; input->dev.parent = &pdev->dev; diff --git a/trunk/drivers/input/misc/uinput.c b/trunk/drivers/input/misc/uinput.c index 6b1797503e34..736056897e50 100644 --- a/trunk/drivers/input/misc/uinput.c +++ b/trunk/drivers/input/misc/uinput.c @@ -405,7 +405,7 @@ static int uinput_setup_device(struct uinput_device *udev, const char __user *bu goto exit; if (test_bit(ABS_MT_SLOT, dev->absbit)) { int nslot = input_abs_get_max(dev, ABS_MT_SLOT) + 1; - input_mt_init_slots(dev, nslot, 0); + input_mt_init_slots(dev, nslot); } else if (test_bit(ABS_MT_POSITION_X, dev->absbit)) { input_set_events_per_packet(dev, 60); } diff --git a/trunk/drivers/input/mouse/alps.c b/trunk/drivers/input/mouse/alps.c index cf5af1f495ec..4a1347e91bdc 100644 --- a/trunk/drivers/input/mouse/alps.c +++ b/trunk/drivers/input/mouse/alps.c @@ -1620,7 +1620,7 @@ int alps_init(struct psmouse *psmouse) case ALPS_PROTO_V3: case ALPS_PROTO_V4: set_bit(INPUT_PROP_SEMI_MT, dev1->propbit); - input_mt_init_slots(dev1, 2, 0); + input_mt_init_slots(dev1, 2); input_set_abs_params(dev1, ABS_MT_POSITION_X, 0, ALPS_V3_X_MAX, 0, 0); input_set_abs_params(dev1, ABS_MT_POSITION_Y, 0, ALPS_V3_Y_MAX, 0, 0); diff --git a/trunk/drivers/input/mouse/bcm5974.c b/trunk/drivers/input/mouse/bcm5974.c index 3a78f235fa3e..d528c23e194f 100644 --- a/trunk/drivers/input/mouse/bcm5974.c +++ b/trunk/drivers/input/mouse/bcm5974.c @@ -40,7 +40,6 @@ #include #include #include -#include #define USB_VENDOR_ID_APPLE 0x05ac @@ -184,26 +183,26 @@ struct tp_finger { __le16 abs_y; /* absolute y coodinate */ __le16 rel_x; /* relative x coodinate */ __le16 rel_y; /* relative y coodinate */ - __le16 tool_major; /* tool area, major axis */ - __le16 tool_minor; /* tool area, minor axis */ + __le16 size_major; /* finger size, major axis? */ + __le16 size_minor; /* finger size, minor axis? */ __le16 orientation; /* 16384 when point, else 15 bit angle */ - __le16 touch_major; /* touch area, major axis */ - __le16 touch_minor; /* touch area, minor axis */ + __le16 force_major; /* trackpad force, major axis? */ + __le16 force_minor; /* trackpad force, minor axis? */ __le16 unused[3]; /* zeros */ __le16 multi; /* one finger: varies, more fingers: constant */ } __attribute__((packed,aligned(2))); /* trackpad finger data size, empirically at least ten fingers */ -#define MAX_FINGERS 16 #define SIZEOF_FINGER sizeof(struct tp_finger) -#define SIZEOF_ALL_FINGERS (MAX_FINGERS * SIZEOF_FINGER) +#define SIZEOF_ALL_FINGERS (16 * SIZEOF_FINGER) #define MAX_FINGER_ORIENTATION 16384 /* device-specific parameters */ struct bcm5974_param { - int snratio; /* signal-to-noise ratio */ - int min; /* device minimum reading */ - int max; /* device maximum reading */ + int dim; /* logical dimension */ + int fuzz; /* logical noise value */ + int devmin; /* device minimum reading */ + int devmax; /* device maximum reading */ }; /* device-specific configuration */ @@ -220,7 +219,6 @@ struct bcm5974_config { struct bcm5974_param w; /* finger width limits */ struct bcm5974_param x; /* horizontal limits */ struct bcm5974_param y; /* vertical limits */ - struct bcm5974_param o; /* orientation limits */ }; /* logical device structure */ @@ -236,16 +234,23 @@ struct bcm5974 { struct bt_data *bt_data; /* button transferred data */ struct urb *tp_urb; /* trackpad usb request block */ u8 *tp_data; /* trackpad transferred data */ - const struct tp_finger *index[MAX_FINGERS]; /* finger index data */ - struct input_mt_pos pos[MAX_FINGERS]; /* position array */ - int slots[MAX_FINGERS]; /* slot assignments */ + int fingers; /* number of fingers on trackpad */ }; +/* logical dimensions */ +#define DIM_PRESSURE 256 /* maximum finger pressure */ +#define DIM_WIDTH 16 /* maximum finger width */ +#define DIM_X 1280 /* maximum trackpad x value */ +#define DIM_Y 800 /* maximum trackpad y value */ + /* logical signal quality */ #define SN_PRESSURE 45 /* pressure signal-to-noise ratio */ -#define SN_WIDTH 25 /* width signal-to-noise ratio */ +#define SN_WIDTH 100 /* width signal-to-noise ratio */ #define SN_COORD 250 /* coordinate signal-to-noise ratio */ -#define SN_ORIENT 10 /* orientation signal-to-noise ratio */ + +/* pressure thresholds */ +#define PRESSURE_LOW (2 * DIM_PRESSURE / SN_PRESSURE) +#define PRESSURE_HIGH (3 * PRESSURE_LOW) /* device constants */ static const struct bcm5974_config bcm5974_config_table[] = { @@ -256,11 +261,10 @@ static const struct bcm5974_config bcm5974_config_table[] = { 0, 0x84, sizeof(struct bt_data), 0x81, TYPE1, FINGER_TYPE1, FINGER_TYPE1 + SIZEOF_ALL_FINGERS, - { SN_PRESSURE, 0, 256 }, - { SN_WIDTH, 0, 2048 }, - { SN_COORD, -4824, 5342 }, - { SN_COORD, -172, 5820 }, - { SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION } + { DIM_PRESSURE, DIM_PRESSURE / SN_PRESSURE, 0, 256 }, + { DIM_WIDTH, DIM_WIDTH / SN_WIDTH, 0, 2048 }, + { DIM_X, DIM_X / SN_COORD, -4824, 5342 }, + { DIM_Y, DIM_Y / SN_COORD, -172, 5820 } }, { USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI, @@ -269,11 +273,10 @@ static const struct bcm5974_config bcm5974_config_table[] = { 0, 0x84, sizeof(struct bt_data), 0x81, TYPE1, FINGER_TYPE1, FINGER_TYPE1 + SIZEOF_ALL_FINGERS, - { SN_PRESSURE, 0, 256 }, - { SN_WIDTH, 0, 2048 }, - { SN_COORD, -4824, 4824 }, - { SN_COORD, -172, 4290 }, - { SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION } + { DIM_PRESSURE, DIM_PRESSURE / SN_PRESSURE, 0, 256 }, + { DIM_WIDTH, DIM_WIDTH / SN_WIDTH, 0, 2048 }, + { DIM_X, DIM_X / SN_COORD, -4824, 4824 }, + { DIM_Y, DIM_Y / SN_COORD, -172, 4290 } }, { USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI, @@ -282,11 +285,10 @@ static const struct bcm5974_config bcm5974_config_table[] = { HAS_INTEGRATED_BUTTON, 0x84, sizeof(struct bt_data), 0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS, - { SN_PRESSURE, 0, 300 }, - { SN_WIDTH, 0, 2048 }, - { SN_COORD, -4460, 5166 }, - { SN_COORD, -75, 6700 }, - { SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION } + { DIM_PRESSURE, DIM_PRESSURE / SN_PRESSURE, 0, 300 }, + { DIM_WIDTH, DIM_WIDTH / SN_WIDTH, 0, 2048 }, + { DIM_X, DIM_X / SN_COORD, -4460, 5166 }, + { DIM_Y, DIM_Y / SN_COORD, -75, 6700 } }, { USB_DEVICE_ID_APPLE_WELLSPRING4_ANSI, @@ -295,11 +297,10 @@ static const struct bcm5974_config bcm5974_config_table[] = { HAS_INTEGRATED_BUTTON, 0x84, sizeof(struct bt_data), 0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS, - { SN_PRESSURE, 0, 300 }, - { SN_WIDTH, 0, 2048 }, - { SN_COORD, -4620, 5140 }, - { SN_COORD, -150, 6600 }, - { SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION } + { DIM_PRESSURE, DIM_PRESSURE / SN_PRESSURE, 0, 300 }, + { DIM_WIDTH, DIM_WIDTH / SN_WIDTH, 0, 2048 }, + { DIM_X, DIM_X / SN_COORD, -4620, 5140 }, + { DIM_Y, DIM_Y / SN_COORD, -150, 6600 } }, { USB_DEVICE_ID_APPLE_WELLSPRING4A_ANSI, @@ -308,11 +309,10 @@ static const struct bcm5974_config bcm5974_config_table[] = { HAS_INTEGRATED_BUTTON, 0x84, sizeof(struct bt_data), 0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS, - { SN_PRESSURE, 0, 300 }, - { SN_WIDTH, 0, 2048 }, - { SN_COORD, -4616, 5112 }, - { SN_COORD, -142, 5234 }, - { SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION } + { DIM_PRESSURE, DIM_PRESSURE / SN_PRESSURE, 0, 300 }, + { DIM_WIDTH, DIM_WIDTH / SN_WIDTH, 0, 2048 }, + { DIM_X, DIM_X / SN_COORD, -4616, 5112 }, + { DIM_Y, DIM_Y / SN_COORD, -142, 5234 } }, { USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI, @@ -321,11 +321,10 @@ static const struct bcm5974_config bcm5974_config_table[] = { HAS_INTEGRATED_BUTTON, 0x84, sizeof(struct bt_data), 0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS, - { SN_PRESSURE, 0, 300 }, - { SN_WIDTH, 0, 2048 }, - { SN_COORD, -4415, 5050 }, - { SN_COORD, -55, 6680 }, - { SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION } + { DIM_PRESSURE, DIM_PRESSURE / SN_PRESSURE, 0, 300 }, + { DIM_WIDTH, DIM_WIDTH / SN_WIDTH, 0, 2048 }, + { DIM_X, DIM_X / SN_COORD, -4415, 5050 }, + { DIM_Y, DIM_Y / SN_COORD, -55, 6680 } }, { USB_DEVICE_ID_APPLE_WELLSPRING6_ANSI, @@ -334,11 +333,10 @@ static const struct bcm5974_config bcm5974_config_table[] = { HAS_INTEGRATED_BUTTON, 0x84, sizeof(struct bt_data), 0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS, - { SN_PRESSURE, 0, 300 }, - { SN_WIDTH, 0, 2048 }, - { SN_COORD, -4620, 5140 }, - { SN_COORD, -150, 6600 }, - { SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION } + { DIM_PRESSURE, DIM_PRESSURE / SN_PRESSURE, 0, 300 }, + { DIM_WIDTH, DIM_WIDTH / SN_WIDTH, 0, 2048 }, + { DIM_X, DIM_X / SN_COORD, -4620, 5140 }, + { DIM_Y, DIM_Y / SN_COORD, -150, 6600 } }, { USB_DEVICE_ID_APPLE_WELLSPRING5A_ANSI, @@ -347,11 +345,10 @@ static const struct bcm5974_config bcm5974_config_table[] = { HAS_INTEGRATED_BUTTON, 0x84, sizeof(struct bt_data), 0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS, - { SN_PRESSURE, 0, 300 }, - { SN_WIDTH, 0, 2048 }, - { SN_COORD, -4750, 5280 }, - { SN_COORD, -150, 6730 }, - { SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION } + { DIM_PRESSURE, DIM_PRESSURE / SN_PRESSURE, 0, 300 }, + { DIM_WIDTH, DIM_WIDTH / SN_WIDTH, 0, 2048 }, + { DIM_X, DIM_X / SN_COORD, -4750, 5280 }, + { DIM_Y, DIM_Y / SN_COORD, -150, 6730 } }, { USB_DEVICE_ID_APPLE_WELLSPRING6A_ANSI, @@ -360,11 +357,10 @@ static const struct bcm5974_config bcm5974_config_table[] = { HAS_INTEGRATED_BUTTON, 0x84, sizeof(struct bt_data), 0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS, - { SN_PRESSURE, 0, 300 }, - { SN_WIDTH, 0, 2048 }, - { SN_COORD, -4620, 5140 }, - { SN_COORD, -150, 6600 }, - { SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION } + { DIM_PRESSURE, DIM_PRESSURE / SN_PRESSURE, 0, 300 }, + { DIM_WIDTH, DIM_WIDTH / SN_WIDTH, 0, 2048 }, + { DIM_X, DIM_X / SN_COORD, -4620, 5140 }, + { DIM_Y, DIM_Y / SN_COORD, -150, 6600 } }, { USB_DEVICE_ID_APPLE_WELLSPRING7_ANSI, @@ -373,11 +369,10 @@ static const struct bcm5974_config bcm5974_config_table[] = { HAS_INTEGRATED_BUTTON, 0x84, sizeof(struct bt_data), 0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS, - { SN_PRESSURE, 0, 300 }, - { SN_WIDTH, 0, 2048 }, - { SN_COORD, -4750, 5280 }, - { SN_COORD, -150, 6730 }, - { SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION } + { DIM_PRESSURE, DIM_PRESSURE / SN_PRESSURE, 0, 300 }, + { DIM_WIDTH, DIM_WIDTH / SN_WIDTH, 0, 2048 }, + { DIM_X, DIM_X / SN_COORD, -4750, 5280 }, + { DIM_Y, DIM_Y / SN_COORD, -150, 6730 } }, {} }; @@ -401,11 +396,18 @@ static inline int raw2int(__le16 x) return (signed short)le16_to_cpu(x); } -static void set_abs(struct input_dev *input, unsigned int code, - const struct bcm5974_param *p) +/* scale device data to logical dimensions (asserts devmin < devmax) */ +static inline int int2scale(const struct bcm5974_param *p, int x) +{ + return x * p->dim / (p->devmax - p->devmin); +} + +/* all logical value ranges are [0,dim). */ +static inline int int2bound(const struct bcm5974_param *p, int x) { - int fuzz = p->snratio ? (p->max - p->min) / p->snratio : 0; - input_set_abs_params(input, code, p->min, p->max, fuzz, 0); + int s = int2scale(p, x); + + return clamp_val(s, 0, p->dim - 1); } /* setup which logical events to report */ @@ -414,30 +416,48 @@ static void setup_events_to_report(struct input_dev *input_dev, { __set_bit(EV_ABS, input_dev->evbit); - /* for synaptics only */ - input_set_abs_params(input_dev, ABS_PRESSURE, 0, 256, 5, 0); - input_set_abs_params(input_dev, ABS_TOOL_WIDTH, 0, 16, 0, 0); + input_set_abs_params(input_dev, ABS_PRESSURE, + 0, cfg->p.dim, cfg->p.fuzz, 0); + input_set_abs_params(input_dev, ABS_TOOL_WIDTH, + 0, cfg->w.dim, cfg->w.fuzz, 0); + input_set_abs_params(input_dev, ABS_X, + 0, cfg->x.dim, cfg->x.fuzz, 0); + input_set_abs_params(input_dev, ABS_Y, + 0, cfg->y.dim, cfg->y.fuzz, 0); /* finger touch area */ - set_abs(input_dev, ABS_MT_TOUCH_MAJOR, &cfg->w); - set_abs(input_dev, ABS_MT_TOUCH_MINOR, &cfg->w); + input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, + cfg->w.devmin, cfg->w.devmax, 0, 0); + input_set_abs_params(input_dev, ABS_MT_TOUCH_MINOR, + cfg->w.devmin, cfg->w.devmax, 0, 0); /* finger approach area */ - set_abs(input_dev, ABS_MT_WIDTH_MAJOR, &cfg->w); - set_abs(input_dev, ABS_MT_WIDTH_MINOR, &cfg->w); + input_set_abs_params(input_dev, ABS_MT_WIDTH_MAJOR, + cfg->w.devmin, cfg->w.devmax, 0, 0); + input_set_abs_params(input_dev, ABS_MT_WIDTH_MINOR, + cfg->w.devmin, cfg->w.devmax, 0, 0); /* finger orientation */ - set_abs(input_dev, ABS_MT_ORIENTATION, &cfg->o); + input_set_abs_params(input_dev, ABS_MT_ORIENTATION, + -MAX_FINGER_ORIENTATION, + MAX_FINGER_ORIENTATION, 0, 0); /* finger position */ - set_abs(input_dev, ABS_MT_POSITION_X, &cfg->x); - set_abs(input_dev, ABS_MT_POSITION_Y, &cfg->y); + input_set_abs_params(input_dev, ABS_MT_POSITION_X, + cfg->x.devmin, cfg->x.devmax, 0, 0); + input_set_abs_params(input_dev, ABS_MT_POSITION_Y, + cfg->y.devmin, cfg->y.devmax, 0, 0); __set_bit(EV_KEY, input_dev->evbit); + __set_bit(BTN_TOUCH, input_dev->keybit); + __set_bit(BTN_TOOL_FINGER, input_dev->keybit); + __set_bit(BTN_TOOL_DOUBLETAP, input_dev->keybit); + __set_bit(BTN_TOOL_TRIPLETAP, input_dev->keybit); + __set_bit(BTN_TOOL_QUADTAP, input_dev->keybit); __set_bit(BTN_LEFT, input_dev->keybit); + __set_bit(INPUT_PROP_POINTER, input_dev->propbit); if (cfg->caps & HAS_INTEGRATED_BUTTON) __set_bit(INPUT_PROP_BUTTONPAD, input_dev->propbit); - input_mt_init_slots(input_dev, MAX_FINGERS, - INPUT_MT_POINTER | INPUT_MT_DROP_UNUSED | INPUT_MT_TRACK); + input_set_events_per_packet(input_dev, 60); } /* report button data as logical button state */ @@ -457,44 +477,24 @@ static int report_bt_state(struct bcm5974 *dev, int size) return 0; } -static void report_finger_data(struct input_dev *input, int slot, - const struct input_mt_pos *pos, +static void report_finger_data(struct input_dev *input, + const struct bcm5974_config *cfg, const struct tp_finger *f) { - input_mt_slot(input, slot); - input_mt_report_slot_state(input, MT_TOOL_FINGER, true); - input_report_abs(input, ABS_MT_TOUCH_MAJOR, - raw2int(f->touch_major) << 1); + raw2int(f->force_major) << 1); input_report_abs(input, ABS_MT_TOUCH_MINOR, - raw2int(f->touch_minor) << 1); + raw2int(f->force_minor) << 1); input_report_abs(input, ABS_MT_WIDTH_MAJOR, - raw2int(f->tool_major) << 1); + raw2int(f->size_major) << 1); input_report_abs(input, ABS_MT_WIDTH_MINOR, - raw2int(f->tool_minor) << 1); + raw2int(f->size_minor) << 1); input_report_abs(input, ABS_MT_ORIENTATION, MAX_FINGER_ORIENTATION - raw2int(f->orientation)); - input_report_abs(input, ABS_MT_POSITION_X, pos->x); - input_report_abs(input, ABS_MT_POSITION_Y, pos->y); -} - -static void report_synaptics_data(struct input_dev *input, - const struct bcm5974_config *cfg, - const struct tp_finger *f, int raw_n) -{ - int abs_p = 0, abs_w = 0; - - if (raw_n) { - int p = raw2int(f->touch_major); - int w = raw2int(f->tool_major); - if (p > 0 && raw2int(f->origin)) { - abs_p = clamp_val(256 * p / cfg->p.max, 0, 255); - abs_w = clamp_val(16 * w / cfg->w.max, 0, 15); - } - } - - input_report_abs(input, ABS_PRESSURE, abs_p); - input_report_abs(input, ABS_TOOL_WIDTH, abs_w); + input_report_abs(input, ABS_MT_POSITION_X, raw2int(f->abs_x)); + input_report_abs(input, ABS_MT_POSITION_Y, + cfg->y.devmin + cfg->y.devmax - raw2int(f->abs_y)); + input_mt_sync(input); } /* report trackpad data as logical trackpad state */ @@ -503,7 +503,9 @@ static int report_tp_state(struct bcm5974 *dev, int size) const struct bcm5974_config *c = &dev->cfg; const struct tp_finger *f; struct input_dev *input = dev->input; - int raw_n, i, n = 0; + int raw_p, raw_w, raw_x, raw_y, raw_n, i; + int ptest, origin, ibt = 0, nmin = 0, nmax = 0; + int abs_p = 0, abs_w = 0, abs_x = 0, abs_y = 0; if (size < c->tp_offset || (size - c->tp_offset) % SIZEOF_FINGER != 0) return -EIO; @@ -512,29 +514,76 @@ static int report_tp_state(struct bcm5974 *dev, int size) f = (const struct tp_finger *)(dev->tp_data + c->tp_offset); raw_n = (size - c->tp_offset) / SIZEOF_FINGER; - for (i = 0; i < raw_n; i++) { - if (raw2int(f[i].touch_major) == 0) - continue; - dev->pos[n].x = raw2int(f[i].abs_x); - dev->pos[n].y = c->y.min + c->y.max - raw2int(f[i].abs_y); - dev->index[n++] = &f[i]; + /* always track the first finger; when detached, start over */ + if (raw_n) { + + /* report raw trackpad data */ + for (i = 0; i < raw_n; i++) + report_finger_data(input, c, &f[i]); + + raw_p = raw2int(f->force_major); + raw_w = raw2int(f->size_major); + raw_x = raw2int(f->abs_x); + raw_y = raw2int(f->abs_y); + + dprintk(9, + "bcm5974: " + "raw: p: %+05d w: %+05d x: %+05d y: %+05d n: %d\n", + raw_p, raw_w, raw_x, raw_y, raw_n); + + ptest = int2bound(&c->p, raw_p); + origin = raw2int(f->origin); + + /* while tracking finger still valid, count all fingers */ + if (ptest > PRESSURE_LOW && origin) { + abs_p = ptest; + abs_w = int2bound(&c->w, raw_w); + abs_x = int2bound(&c->x, raw_x - c->x.devmin); + abs_y = int2bound(&c->y, c->y.devmax - raw_y); + while (raw_n--) { + ptest = int2bound(&c->p, + raw2int(f->force_major)); + if (ptest > PRESSURE_LOW) + nmax++; + if (ptest > PRESSURE_HIGH) + nmin++; + f++; + } + } } - input_mt_assign_slots(input, dev->slots, dev->pos, n); + /* set the integrated button if applicable */ + if (c->tp_type == TYPE2) + ibt = raw2int(dev->tp_data[BUTTON_TYPE2]); + + if (dev->fingers < nmin) + dev->fingers = nmin; + if (dev->fingers > nmax) + dev->fingers = nmax; + + input_report_key(input, BTN_TOUCH, dev->fingers > 0); + input_report_key(input, BTN_TOOL_FINGER, dev->fingers == 1); + input_report_key(input, BTN_TOOL_DOUBLETAP, dev->fingers == 2); + input_report_key(input, BTN_TOOL_TRIPLETAP, dev->fingers == 3); + input_report_key(input, BTN_TOOL_QUADTAP, dev->fingers > 3); + + input_report_abs(input, ABS_PRESSURE, abs_p); + input_report_abs(input, ABS_TOOL_WIDTH, abs_w); - for (i = 0; i < n; i++) - report_finger_data(input, dev->slots[i], - &dev->pos[i], dev->index[i]); + if (abs_p) { + input_report_abs(input, ABS_X, abs_x); + input_report_abs(input, ABS_Y, abs_y); - input_mt_sync_frame(input); + dprintk(8, + "bcm5974: abs: p: %+05d w: %+05d x: %+05d y: %+05d " + "nmin: %d nmax: %d n: %d ibt: %d\n", abs_p, abs_w, + abs_x, abs_y, nmin, nmax, dev->fingers, ibt); - report_synaptics_data(input, c, f, raw_n); + } /* type 2 reports button events via ibt only */ - if (c->tp_type == TYPE2) { - int ibt = raw2int(dev->tp_data[BUTTON_TYPE2]); + if (c->tp_type == TYPE2) input_report_key(input, BTN_LEFT, ibt); - } input_sync(input); @@ -693,11 +742,9 @@ static int bcm5974_start_traffic(struct bcm5974 *dev) goto err_out; } - if (dev->bt_urb) { - error = usb_submit_urb(dev->bt_urb, GFP_KERNEL); - if (error) - goto err_reset_mode; - } + error = usb_submit_urb(dev->bt_urb, GFP_KERNEL); + if (error) + goto err_reset_mode; error = usb_submit_urb(dev->tp_urb, GFP_KERNEL); if (error) @@ -821,23 +868,19 @@ static int bcm5974_probe(struct usb_interface *iface, mutex_init(&dev->pm_mutex); /* setup urbs */ - if (cfg->tp_type == TYPE1) { - dev->bt_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!dev->bt_urb) - goto err_free_devs; - } + dev->bt_urb = usb_alloc_urb(0, GFP_KERNEL); + if (!dev->bt_urb) + goto err_free_devs; dev->tp_urb = usb_alloc_urb(0, GFP_KERNEL); if (!dev->tp_urb) goto err_free_bt_urb; - if (dev->bt_urb) { - dev->bt_data = usb_alloc_coherent(dev->udev, + dev->bt_data = usb_alloc_coherent(dev->udev, dev->cfg.bt_datalen, GFP_KERNEL, &dev->bt_urb->transfer_dma); - if (!dev->bt_data) - goto err_free_urb; - } + if (!dev->bt_data) + goto err_free_urb; dev->tp_data = usb_alloc_coherent(dev->udev, dev->cfg.tp_datalen, GFP_KERNEL, @@ -845,11 +888,10 @@ static int bcm5974_probe(struct usb_interface *iface, if (!dev->tp_data) goto err_free_bt_buffer; - if (dev->bt_urb) - usb_fill_int_urb(dev->bt_urb, udev, - usb_rcvintpipe(udev, cfg->bt_ep), - dev->bt_data, dev->cfg.bt_datalen, - bcm5974_irq_button, dev, 1); + usb_fill_int_urb(dev->bt_urb, udev, + usb_rcvintpipe(udev, cfg->bt_ep), + dev->bt_data, dev->cfg.bt_datalen, + bcm5974_irq_button, dev, 1); usb_fill_int_urb(dev->tp_urb, udev, usb_rcvintpipe(udev, cfg->tp_ep), @@ -887,9 +929,8 @@ static int bcm5974_probe(struct usb_interface *iface, usb_free_coherent(dev->udev, dev->cfg.tp_datalen, dev->tp_data, dev->tp_urb->transfer_dma); err_free_bt_buffer: - if (dev->bt_urb) - usb_free_coherent(dev->udev, dev->cfg.bt_datalen, - dev->bt_data, dev->bt_urb->transfer_dma); + usb_free_coherent(dev->udev, dev->cfg.bt_datalen, + dev->bt_data, dev->bt_urb->transfer_dma); err_free_urb: usb_free_urb(dev->tp_urb); err_free_bt_urb: @@ -910,9 +951,8 @@ static void bcm5974_disconnect(struct usb_interface *iface) input_unregister_device(dev->input); usb_free_coherent(dev->udev, dev->cfg.tp_datalen, dev->tp_data, dev->tp_urb->transfer_dma); - if (dev->bt_urb) - usb_free_coherent(dev->udev, dev->cfg.bt_datalen, - dev->bt_data, dev->bt_urb->transfer_dma); + usb_free_coherent(dev->udev, dev->cfg.bt_datalen, + dev->bt_data, dev->bt_urb->transfer_dma); usb_free_urb(dev->tp_urb); usb_free_urb(dev->bt_urb); kfree(dev); diff --git a/trunk/drivers/input/mouse/elantech.c b/trunk/drivers/input/mouse/elantech.c index 1e8e42fb03a4..479011004a11 100644 --- a/trunk/drivers/input/mouse/elantech.c +++ b/trunk/drivers/input/mouse/elantech.c @@ -1004,7 +1004,7 @@ static int elantech_set_input_params(struct psmouse *psmouse) input_set_abs_params(dev, ABS_TOOL_WIDTH, ETP_WMIN_V2, ETP_WMAX_V2, 0, 0); } - input_mt_init_slots(dev, 2, 0); + input_mt_init_slots(dev, 2); input_set_abs_params(dev, ABS_MT_POSITION_X, x_min, x_max, 0, 0); input_set_abs_params(dev, ABS_MT_POSITION_Y, y_min, y_max, 0, 0); break; @@ -1035,7 +1035,7 @@ static int elantech_set_input_params(struct psmouse *psmouse) input_set_abs_params(dev, ABS_TOOL_WIDTH, ETP_WMIN_V2, ETP_WMAX_V2, 0, 0); /* Multitouch capable pad, up to 5 fingers. */ - input_mt_init_slots(dev, ETP_MAX_FINGERS, 0); + input_mt_init_slots(dev, ETP_MAX_FINGERS); input_set_abs_params(dev, ABS_MT_POSITION_X, x_min, x_max, 0, 0); input_set_abs_params(dev, ABS_MT_POSITION_Y, y_min, y_max, 0, 0); input_abs_set_res(dev, ABS_MT_POSITION_X, x_res); diff --git a/trunk/drivers/input/mouse/sentelic.c b/trunk/drivers/input/mouse/sentelic.c index e582922bacf7..3f5649f19082 100644 --- a/trunk/drivers/input/mouse/sentelic.c +++ b/trunk/drivers/input/mouse/sentelic.c @@ -721,17 +721,6 @@ static psmouse_ret_t fsp_process_byte(struct psmouse *psmouse) switch (psmouse->packet[0] >> FSP_PKT_TYPE_SHIFT) { case FSP_PKT_TYPE_ABS: - - if ((packet[0] == 0x48 || packet[0] == 0x49) && - packet[1] == 0 && packet[2] == 0) { - /* - * Ignore coordinate noise when finger leaving the - * surface, otherwise cursor may jump to upper-left - * corner. - */ - packet[3] &= 0xf0; - } - abs_x = GET_ABS_X(packet); abs_y = GET_ABS_Y(packet); @@ -971,7 +960,7 @@ static int fsp_set_input_params(struct psmouse *psmouse) input_set_abs_params(dev, ABS_X, 0, abs_x, 0, 0); input_set_abs_params(dev, ABS_Y, 0, abs_y, 0, 0); - input_mt_init_slots(dev, 2, 0); + input_mt_init_slots(dev, 2); input_set_abs_params(dev, ABS_MT_POSITION_X, 0, abs_x, 0, 0); input_set_abs_params(dev, ABS_MT_POSITION_Y, 0, abs_y, 0, 0); } diff --git a/trunk/drivers/input/mouse/synaptics.c b/trunk/drivers/input/mouse/synaptics.c index 37033ade79d3..14eaecea2b70 100644 --- a/trunk/drivers/input/mouse/synaptics.c +++ b/trunk/drivers/input/mouse/synaptics.c @@ -1232,7 +1232,7 @@ static void set_input_params(struct input_dev *dev, struct synaptics_data *priv) input_set_abs_params(dev, ABS_PRESSURE, 0, 255, 0, 0); if (SYN_CAP_IMAGE_SENSOR(priv->ext_cap_0c)) { - input_mt_init_slots(dev, 2, 0); + input_mt_init_slots(dev, 2); set_abs_position_params(dev, priv, ABS_MT_POSITION_X, ABS_MT_POSITION_Y); /* Image sensors can report per-contact pressure */ @@ -1244,7 +1244,7 @@ static void set_input_params(struct input_dev *dev, struct synaptics_data *priv) } else if (SYN_CAP_ADV_GESTURE(priv->ext_cap_0c)) { /* Non-image sensors with AGM use semi-mt */ __set_bit(INPUT_PROP_SEMI_MT, dev->propbit); - input_mt_init_slots(dev, 2, 0); + input_mt_init_slots(dev, 2); set_abs_position_params(dev, priv, ABS_MT_POSITION_X, ABS_MT_POSITION_Y); } diff --git a/trunk/drivers/input/serio/ambakmi.c b/trunk/drivers/input/serio/ambakmi.c index 2e77246c2e5a..2ffd110bd5bc 100644 --- a/trunk/drivers/input/serio/ambakmi.c +++ b/trunk/drivers/input/serio/ambakmi.c @@ -72,7 +72,7 @@ static int amba_kmi_open(struct serio *io) unsigned int divisor; int ret; - ret = clk_prepare_enable(kmi->clk); + ret = clk_enable(kmi->clk); if (ret) goto out; @@ -92,7 +92,7 @@ static int amba_kmi_open(struct serio *io) return 0; clk_disable: - clk_disable_unprepare(kmi->clk); + clk_disable(kmi->clk); out: return ret; } @@ -104,7 +104,7 @@ static void amba_kmi_close(struct serio *io) writeb(0, KMICR); free_irq(kmi->irq, kmi); - clk_disable_unprepare(kmi->clk); + clk_disable(kmi->clk); } static int __devinit amba_kmi_probe(struct amba_device *dev, diff --git a/trunk/drivers/input/serio/i8042-x86ia64io.h b/trunk/drivers/input/serio/i8042-x86ia64io.h index d6cc77a53c7e..5ec774d6c82b 100644 --- a/trunk/drivers/input/serio/i8042-x86ia64io.h +++ b/trunk/drivers/input/serio/i8042-x86ia64io.h @@ -176,20 +176,6 @@ static const struct dmi_system_id __initconst i8042_dmi_noloop_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "Spring Peak"), }, }, - { - /* Gigabyte T1005 - defines wrong chassis type ("Other") */ - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "GIGABYTE"), - DMI_MATCH(DMI_PRODUCT_NAME, "T1005"), - }, - }, - { - /* Gigabyte T1005M/P - defines wrong chassis type ("Other") */ - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "GIGABYTE"), - DMI_MATCH(DMI_PRODUCT_NAME, "T1005M/P"), - }, - }, { .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), @@ -333,12 +319,6 @@ static const struct dmi_system_id __initconst i8042_dmi_nomux_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "EQUIUM A110"), }, }, - { - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), - DMI_MATCH(DMI_PRODUCT_NAME, "SATELLITE C850D"), - }, - }, { .matches = { DMI_MATCH(DMI_SYS_VENDOR, "ALIENWARE"), diff --git a/trunk/drivers/input/tablet/wacom_wac.c b/trunk/drivers/input/tablet/wacom_wac.c index 2a81ce375f75..002041975de9 100644 --- a/trunk/drivers/input/tablet/wacom_wac.c +++ b/trunk/drivers/input/tablet/wacom_wac.c @@ -1530,7 +1530,7 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev, __set_bit(BTN_TOOL_TRIPLETAP, input_dev->keybit); __set_bit(BTN_TOOL_QUADTAP, input_dev->keybit); - input_mt_init_slots(input_dev, features->touch_max, 0); + input_mt_init_slots(input_dev, features->touch_max); input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0); @@ -1575,7 +1575,7 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev, case TABLETPC2FG: if (features->device_type == BTN_TOOL_FINGER) { - input_mt_init_slots(input_dev, features->touch_max, 0); + input_mt_init_slots(input_dev, features->touch_max); input_set_abs_params(input_dev, ABS_MT_TOOL_TYPE, 0, MT_TOOL_MAX, 0, 0); input_set_abs_params(input_dev, ABS_MT_POSITION_X, @@ -1631,7 +1631,7 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev, __set_bit(BTN_TOOL_FINGER, input_dev->keybit); __set_bit(BTN_TOOL_DOUBLETAP, input_dev->keybit); - input_mt_init_slots(input_dev, features->touch_max, 0); + input_mt_init_slots(input_dev, features->touch_max); if (features->pktlen == WACOM_PKGLEN_BBTOUCH3) { __set_bit(BTN_TOOL_TRIPLETAP, @@ -1848,10 +1848,7 @@ static const struct wacom_features wacom_features_0x2A = { "Wacom Intuos5 M", WACOM_PKGLEN_INTUOS, 44704, 27940, 2047, 63, INTUOS5, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; static const struct wacom_features wacom_features_0xF4 = - { "Wacom Cintiq 24HD", WACOM_PKGLEN_INTUOS, 104480, 65600, 2047, - 63, WACOM_24HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; -static const struct wacom_features wacom_features_0xF8 = - { "Wacom Cintiq 24HD touch", WACOM_PKGLEN_INTUOS, 104480, 65600, 2047, + { "Wacom Cintiq 24HD", WACOM_PKGLEN_INTUOS, 104480, 65600, 2047, 63, WACOM_24HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; static const struct wacom_features wacom_features_0x3F = { "Wacom Cintiq 21UX", WACOM_PKGLEN_INTUOS, 87200, 65600, 1023, @@ -2094,7 +2091,6 @@ const struct usb_device_id wacom_ids[] = { { USB_DEVICE_WACOM(0xEF) }, { USB_DEVICE_WACOM(0x47) }, { USB_DEVICE_WACOM(0xF4) }, - { USB_DEVICE_WACOM(0xF8) }, { USB_DEVICE_WACOM(0xFA) }, { USB_DEVICE_LENOVO(0x6004) }, { } diff --git a/trunk/drivers/input/touchscreen/atmel_mxt_ts.c b/trunk/drivers/input/touchscreen/atmel_mxt_ts.c index e92615d0b1b0..4623cc69fc60 100644 --- a/trunk/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/trunk/drivers/input/touchscreen/atmel_mxt_ts.c @@ -1152,7 +1152,7 @@ static int __devinit mxt_probe(struct i2c_client *client, /* For multi touch */ num_mt_slots = data->T9_reportid_max - data->T9_reportid_min + 1; - error = input_mt_init_slots(input_dev, num_mt_slots, 0); + error = input_mt_init_slots(input_dev, num_mt_slots); if (error) goto err_free_object; input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, diff --git a/trunk/drivers/input/touchscreen/cyttsp_core.c b/trunk/drivers/input/touchscreen/cyttsp_core.c index 8e60437ac85b..f030d9ec795d 100644 --- a/trunk/drivers/input/touchscreen/cyttsp_core.c +++ b/trunk/drivers/input/touchscreen/cyttsp_core.c @@ -571,7 +571,7 @@ struct cyttsp *cyttsp_probe(const struct cyttsp_bus_ops *bus_ops, input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0, CY_MAXZ, 0, 0); - input_mt_init_slots(input_dev, CY_MAX_ID, 0); + input_mt_init_slots(input_dev, CY_MAX_ID); error = request_threaded_irq(ts->irq, NULL, cyttsp_irq, IRQF_TRIGGER_FALLING | IRQF_ONESHOT, diff --git a/trunk/drivers/input/touchscreen/edt-ft5x06.c b/trunk/drivers/input/touchscreen/edt-ft5x06.c index 099d144ab7c9..9afc777a40a7 100644 --- a/trunk/drivers/input/touchscreen/edt-ft5x06.c +++ b/trunk/drivers/input/touchscreen/edt-ft5x06.c @@ -566,12 +566,9 @@ static ssize_t edt_ft5x06_debugfs_raw_data_read(struct file *file, } read = min_t(size_t, count, tsdata->raw_bufsize - *off); - if (copy_to_user(buf, tsdata->raw_buffer + *off, read)) { - error = -EFAULT; - goto out; - } - - *off += read; + error = copy_to_user(buf, tsdata->raw_buffer + *off, read); + if (!error) + *off += read; out: mutex_unlock(&tsdata->mutex); return error ?: read; @@ -605,7 +602,6 @@ edt_ft5x06_ts_teardown_debugfs(struct edt_ft5x06_ts_data *tsdata) { if (tsdata->debug_dir) debugfs_remove_recursive(tsdata->debug_dir); - kfree(tsdata->raw_buffer); } #else @@ -782,7 +778,7 @@ static int __devinit edt_ft5x06_ts_probe(struct i2c_client *client, 0, tsdata->num_x * 64 - 1, 0, 0); input_set_abs_params(input, ABS_MT_POSITION_Y, 0, tsdata->num_y * 64 - 1, 0, 0); - error = input_mt_init_slots(input, MAX_SUPPORT_POINTS, 0); + error = input_mt_init_slots(input, MAX_SUPPORT_POINTS); if (error) { dev_err(&client->dev, "Unable to init MT slots.\n"); goto err_free_mem; @@ -847,6 +843,7 @@ static int __devexit edt_ft5x06_ts_remove(struct i2c_client *client) if (gpio_is_valid(pdata->reset_pin)) gpio_free(pdata->reset_pin); + kfree(tsdata->raw_buffer); kfree(tsdata); return 0; diff --git a/trunk/drivers/input/touchscreen/eeti_ts.c b/trunk/drivers/input/touchscreen/eeti_ts.c index 908407efc672..503c7096ed36 100644 --- a/trunk/drivers/input/touchscreen/eeti_ts.c +++ b/trunk/drivers/input/touchscreen/eeti_ts.c @@ -48,7 +48,7 @@ struct eeti_ts_priv { struct input_dev *input; struct work_struct work; struct mutex mutex; - int irq_gpio, irq, irq_active_high; + int irq, irq_active_high; }; #define EETI_TS_BITDEPTH (11) @@ -62,7 +62,7 @@ struct eeti_ts_priv { static inline int eeti_ts_irq_active(struct eeti_ts_priv *priv) { - return gpio_get_value(priv->irq_gpio) == priv->irq_active_high; + return gpio_get_value(irq_to_gpio(priv->irq)) == priv->irq_active_high; } static void eeti_ts_read(struct work_struct *work) @@ -157,7 +157,7 @@ static void eeti_ts_close(struct input_dev *dev) static int __devinit eeti_ts_probe(struct i2c_client *client, const struct i2c_device_id *idp) { - struct eeti_ts_platform_data *pdata = client->dev.platform_data; + struct eeti_ts_platform_data *pdata; struct eeti_ts_priv *priv; struct input_dev *input; unsigned int irq_flags; @@ -199,12 +199,9 @@ static int __devinit eeti_ts_probe(struct i2c_client *client, priv->client = client; priv->input = input; - priv->irq_gpio = pdata->irq_gpio; - priv->irq = gpio_to_irq(pdata->irq_gpio); + priv->irq = client->irq; - err = gpio_request_one(pdata->irq_gpio, GPIOF_IN, client->name); - if (err < 0) - goto err1; + pdata = client->dev.platform_data; if (pdata) priv->irq_active_high = pdata->irq_active_high; @@ -218,13 +215,13 @@ static int __devinit eeti_ts_probe(struct i2c_client *client, err = input_register_device(input); if (err) - goto err2; + goto err1; err = request_irq(priv->irq, eeti_ts_isr, irq_flags, client->name, priv); if (err) { dev_err(&client->dev, "Unable to request touchscreen IRQ.\n"); - goto err3; + goto err2; } /* @@ -236,11 +233,9 @@ static int __devinit eeti_ts_probe(struct i2c_client *client, device_init_wakeup(&client->dev, 0); return 0; -err3: +err2: input_unregister_device(input); input = NULL; /* so we dont try to free it below */ -err2: - gpio_free(pdata->irq_gpio); err1: input_free_device(input); kfree(priv); diff --git a/trunk/drivers/input/touchscreen/egalax_ts.c b/trunk/drivers/input/touchscreen/egalax_ts.c index c1e3460f1195..70524dd34f42 100644 --- a/trunk/drivers/input/touchscreen/egalax_ts.c +++ b/trunk/drivers/input/touchscreen/egalax_ts.c @@ -204,7 +204,7 @@ static int __devinit egalax_ts_probe(struct i2c_client *client, ABS_MT_POSITION_X, 0, EGALAX_MAX_X, 0, 0); input_set_abs_params(input_dev, ABS_MT_POSITION_X, 0, EGALAX_MAX_Y, 0, 0); - input_mt_init_slots(input_dev, MAX_SUPPORT_POINTS, 0); + input_mt_init_slots(input_dev, MAX_SUPPORT_POINTS); input_set_drvdata(input_dev, ts); diff --git a/trunk/drivers/input/touchscreen/ili210x.c b/trunk/drivers/input/touchscreen/ili210x.c index 4ac69760ec08..c0044175a921 100644 --- a/trunk/drivers/input/touchscreen/ili210x.c +++ b/trunk/drivers/input/touchscreen/ili210x.c @@ -252,7 +252,7 @@ static int __devinit ili210x_i2c_probe(struct i2c_client *client, input_set_abs_params(input, ABS_Y, 0, ymax, 0, 0); /* Multi touch */ - input_mt_init_slots(input, MAX_TOUCHES, 0); + input_mt_init_slots(input, MAX_TOUCHES); input_set_abs_params(input, ABS_MT_POSITION_X, 0, xmax, 0, 0); input_set_abs_params(input, ABS_MT_POSITION_Y, 0, ymax, 0, 0); diff --git a/trunk/drivers/input/touchscreen/mms114.c b/trunk/drivers/input/touchscreen/mms114.c index 560cf09d1c5a..49c44bbf548d 100644 --- a/trunk/drivers/input/touchscreen/mms114.c +++ b/trunk/drivers/input/touchscreen/mms114.c @@ -404,7 +404,7 @@ static int __devinit mms114_probe(struct i2c_client *client, input_set_abs_params(input_dev, ABS_Y, 0, data->pdata->y_size, 0, 0); /* For multi touch */ - input_mt_init_slots(input_dev, MMS114_MAX_TOUCH, 0); + input_mt_init_slots(input_dev, MMS114_MAX_TOUCH); input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0, MMS114_MAX_AREA, 0, 0); input_set_abs_params(input_dev, ABS_MT_POSITION_X, diff --git a/trunk/drivers/input/touchscreen/penmount.c b/trunk/drivers/input/touchscreen/penmount.c index b49f0b836925..4ccde45b9da2 100644 --- a/trunk/drivers/input/touchscreen/penmount.c +++ b/trunk/drivers/input/touchscreen/penmount.c @@ -264,7 +264,7 @@ static int pm_connect(struct serio *serio, struct serio_driver *drv) input_set_abs_params(pm->dev, ABS_Y, 0, max_y, 0, 0); if (pm->maxcontacts > 1) { - input_mt_init_slots(pm->dev, pm->maxcontacts, 0); + input_mt_init_slots(pm->dev, pm->maxcontacts); input_set_abs_params(pm->dev, ABS_MT_POSITION_X, 0, max_x, 0, 0); input_set_abs_params(pm->dev, diff --git a/trunk/drivers/input/touchscreen/usbtouchscreen.c b/trunk/drivers/input/touchscreen/usbtouchscreen.c index 721fdb3597ca..e32709e0dd65 100644 --- a/trunk/drivers/input/touchscreen/usbtouchscreen.c +++ b/trunk/drivers/input/touchscreen/usbtouchscreen.c @@ -304,45 +304,6 @@ static int e2i_read_data(struct usbtouch_usb *dev, unsigned char *pkt) #define EGALAX_PKT_TYPE_REPT 0x80 #define EGALAX_PKT_TYPE_DIAG 0x0A -static int egalax_init(struct usbtouch_usb *usbtouch) -{ - int ret, i; - unsigned char *buf; - struct usb_device *udev = interface_to_usbdev(usbtouch->interface); - - /* - * An eGalax diagnostic packet kicks the device into using the right - * protocol. We send a "check active" packet. The response will be - * read later and ignored. - */ - - buf = kmalloc(3, GFP_KERNEL); - if (!buf) - return -ENOMEM; - - buf[0] = EGALAX_PKT_TYPE_DIAG; - buf[1] = 1; /* length */ - buf[2] = 'A'; /* command - check active */ - - for (i = 0; i < 3; i++) { - ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), - 0, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 0, 0, buf, 3, - USB_CTRL_SET_TIMEOUT); - if (ret >= 0) { - ret = 0; - break; - } - if (ret != -EPIPE) - break; - } - - kfree(buf); - - return ret; -} - static int egalax_read_data(struct usbtouch_usb *dev, unsigned char *pkt) { if ((pkt[0] & EGALAX_PKT_TYPE_MASK) != EGALAX_PKT_TYPE_REPT) @@ -1095,7 +1056,6 @@ static struct usbtouch_device_info usbtouch_dev_info[] = { .process_pkt = usbtouch_process_multi, .get_pkt_len = egalax_get_pkt_len, .read_data = egalax_read_data, - .init = egalax_init, }, #endif diff --git a/trunk/drivers/input/touchscreen/wacom_w8001.c b/trunk/drivers/input/touchscreen/wacom_w8001.c index 9a83be6b6584..8f9ad2f893b8 100644 --- a/trunk/drivers/input/touchscreen/wacom_w8001.c +++ b/trunk/drivers/input/touchscreen/wacom_w8001.c @@ -471,7 +471,7 @@ static int w8001_setup(struct w8001 *w8001) case 5: w8001->pktlen = W8001_PKTLEN_TOUCH2FG; - input_mt_init_slots(dev, 2, 0); + input_mt_init_slots(dev, 2); input_set_abs_params(dev, ABS_MT_POSITION_X, 0, touch.x, 0, 0); input_set_abs_params(dev, ABS_MT_POSITION_Y, diff --git a/trunk/drivers/iommu/amd_iommu.c b/trunk/drivers/iommu/amd_iommu.c index e89daf1b21b4..6d1cbdfc9b2a 100644 --- a/trunk/drivers/iommu/amd_iommu.c +++ b/trunk/drivers/iommu/amd_iommu.c @@ -266,7 +266,7 @@ static void swap_pci_ref(struct pci_dev **from, struct pci_dev *to) static int iommu_init_device(struct device *dev) { - struct pci_dev *dma_pdev = NULL, *pdev = to_pci_dev(dev); + struct pci_dev *dma_pdev, *pdev = to_pci_dev(dev); struct iommu_dev_data *dev_data; struct iommu_group *group; u16 alias; @@ -293,18 +293,11 @@ static int iommu_init_device(struct device *dev) dev_data->alias_data = alias_data; dma_pdev = pci_get_bus_and_slot(alias >> 8, alias & 0xff); - } - - if (dma_pdev == NULL) + } else dma_pdev = pci_dev_get(pdev); - /* Account for quirked devices */ swap_pci_ref(&dma_pdev, pci_get_dma_source(dma_pdev)); - /* - * If it's a multifunction device that does not support our - * required ACS flags, add to the same group as function 0. - */ if (dma_pdev->multifunction && !pci_acs_enabled(dma_pdev, REQ_ACS_FLAGS)) swap_pci_ref(&dma_pdev, @@ -312,28 +305,14 @@ static int iommu_init_device(struct device *dev) PCI_DEVFN(PCI_SLOT(dma_pdev->devfn), 0))); - /* - * Devices on the root bus go through the iommu. If that's not us, - * find the next upstream device and test ACS up to the root bus. - * Finding the next device may require skipping virtual buses. - */ while (!pci_is_root_bus(dma_pdev->bus)) { - struct pci_bus *bus = dma_pdev->bus; - - while (!bus->self) { - if (!pci_is_root_bus(bus)) - bus = bus->parent; - else - goto root_bus; - } - - if (pci_acs_path_enabled(bus->self, NULL, REQ_ACS_FLAGS)) + if (pci_acs_path_enabled(dma_pdev->bus->self, + NULL, REQ_ACS_FLAGS)) break; - swap_pci_ref(&dma_pdev, pci_dev_get(bus->self)); + swap_pci_ref(&dma_pdev, pci_dev_get(dma_pdev->bus->self)); } -root_bus: group = iommu_group_get(&dma_pdev->dev); pci_dev_put(dma_pdev); if (!group) { diff --git a/trunk/drivers/iommu/amd_iommu_init.c b/trunk/drivers/iommu/amd_iommu_init.c index 18a89b760aaa..500e7f15f5c2 100644 --- a/trunk/drivers/iommu/amd_iommu_init.c +++ b/trunk/drivers/iommu/amd_iommu_init.c @@ -1111,7 +1111,7 @@ static void print_iommu_info(void) if (iommu->cap & (1 << IOMMU_CAP_EFR)) { pr_info("AMD-Vi: Extended features: "); - for (i = 0; i < ARRAY_SIZE(feat_str); ++i) { + for (i = 0; ARRAY_SIZE(feat_str); ++i) { if (iommu_feature(iommu, (1ULL << i))) pr_cont(" %s", feat_str[i]); } @@ -1131,6 +1131,9 @@ static int __init amd_iommu_init_pci(void) break; } + /* Make sure ACS will be enabled */ + pci_request_acs(); + ret = amd_iommu_init_devices(); print_iommu_info(); @@ -1649,9 +1652,6 @@ static bool detect_ivrs(void) early_acpi_os_unmap_memory((char __iomem *)ivrs_base, ivrs_size); - /* Make sure ACS will be enabled during PCI probe */ - pci_request_acs(); - return true; } diff --git a/trunk/drivers/iommu/exynos-iommu.c b/trunk/drivers/iommu/exynos-iommu.c index 80bad32aa463..45350ff5e93c 100644 --- a/trunk/drivers/iommu/exynos-iommu.c +++ b/trunk/drivers/iommu/exynos-iommu.c @@ -732,9 +732,9 @@ static int exynos_iommu_domain_init(struct iommu_domain *domain) spin_lock_init(&priv->pgtablelock); INIT_LIST_HEAD(&priv->clients); - domain->geometry.aperture_start = 0; - domain->geometry.aperture_end = ~0UL; - domain->geometry.force_aperture = true; + dom->geometry.aperture_start = 0; + dom->geometry.aperture_end = ~0UL; + dom->geometry.force_aperture = true; domain->priv = priv; return 0; diff --git a/trunk/drivers/iommu/intel-iommu.c b/trunk/drivers/iommu/intel-iommu.c index db820d7dd0bc..7469b5346643 100644 --- a/trunk/drivers/iommu/intel-iommu.c +++ b/trunk/drivers/iommu/intel-iommu.c @@ -2008,7 +2008,6 @@ static struct dmar_domain *get_domain_for_dev(struct pci_dev *pdev, int gaw) if (!drhd) { printk(KERN_ERR "IOMMU: can't find DMAR for device %s\n", pci_name(pdev)); - free_domain_mem(domain); return NULL; } iommu = drhd->iommu; @@ -2351,7 +2350,7 @@ static int iommu_should_identity_map(struct pci_dev *pdev, int startup) return 0; if (pdev->class >> 8 == PCI_CLASS_BRIDGE_PCI) return 0; - } else if (pci_pcie_type(pdev) == PCI_EXP_TYPE_PCI_BRIDGE) + } else if (pdev->pcie_type == PCI_EXP_TYPE_PCI_BRIDGE) return 0; /* @@ -3546,10 +3545,10 @@ int dmar_find_matched_atsr_unit(struct pci_dev *dev) struct pci_dev *bridge = bus->self; if (!bridge || !pci_is_pcie(bridge) || - pci_pcie_type(bridge) == PCI_EXP_TYPE_PCI_BRIDGE) + bridge->pcie_type == PCI_EXP_TYPE_PCI_BRIDGE) return 0; - if (pci_pcie_type(bridge) == PCI_EXP_TYPE_ROOT_PORT) { + if (bridge->pcie_type == PCI_EXP_TYPE_ROOT_PORT) { for (i = 0; i < atsru->devices_cnt; i++) if (atsru->devices[i] == bridge) return 1; @@ -4125,13 +4124,8 @@ static int intel_iommu_add_device(struct device *dev) } else dma_pdev = pci_dev_get(pdev); - /* Account for quirked devices */ swap_pci_ref(&dma_pdev, pci_get_dma_source(dma_pdev)); - /* - * If it's a multifunction device that does not support our - * required ACS flags, add to the same group as function 0. - */ if (dma_pdev->multifunction && !pci_acs_enabled(dma_pdev, REQ_ACS_FLAGS)) swap_pci_ref(&dma_pdev, @@ -4139,28 +4133,14 @@ static int intel_iommu_add_device(struct device *dev) PCI_DEVFN(PCI_SLOT(dma_pdev->devfn), 0))); - /* - * Devices on the root bus go through the iommu. If that's not us, - * find the next upstream device and test ACS up to the root bus. - * Finding the next device may require skipping virtual buses. - */ while (!pci_is_root_bus(dma_pdev->bus)) { - struct pci_bus *bus = dma_pdev->bus; - - while (!bus->self) { - if (!pci_is_root_bus(bus)) - bus = bus->parent; - else - goto root_bus; - } - - if (pci_acs_path_enabled(bus->self, NULL, REQ_ACS_FLAGS)) + if (pci_acs_path_enabled(dma_pdev->bus->self, + NULL, REQ_ACS_FLAGS)) break; - swap_pci_ref(&dma_pdev, pci_dev_get(bus->self)); + swap_pci_ref(&dma_pdev, pci_dev_get(dma_pdev->bus->self)); } -root_bus: group = iommu_group_get(&dma_pdev->dev); pci_dev_put(dma_pdev); if (!group) { diff --git a/trunk/drivers/iommu/intel_irq_remapping.c b/trunk/drivers/iommu/intel_irq_remapping.c index af8904de1d44..e0b18f3ae9a8 100644 --- a/trunk/drivers/iommu/intel_irq_remapping.c +++ b/trunk/drivers/iommu/intel_irq_remapping.c @@ -736,7 +736,6 @@ int __init parse_ioapics_under_ir(void) { struct dmar_drhd_unit *drhd; int ir_supported = 0; - int ioapic_idx; for_each_drhd_unit(drhd) { struct intel_iommu *iommu = drhd->iommu; @@ -749,20 +748,13 @@ int __init parse_ioapics_under_ir(void) } } - if (!ir_supported) - return 0; - - for (ioapic_idx = 0; ioapic_idx < nr_ioapics; ioapic_idx++) { - int ioapic_id = mpc_ioapic_id(ioapic_idx); - if (!map_ioapic_to_ir(ioapic_id)) { - pr_err(FW_BUG "ioapic %d has no mapping iommu, " - "interrupt remapping will be disabled\n", - ioapic_id); - return -1; - } + if (ir_supported && ir_ioapic_num != nr_ioapics) { + printk(KERN_WARNING + "Not all IO-APIC's listed under remapping hardware\n"); + return -1; } - return 1; + return ir_supported; } int __init ir_dev_scope_init(void) diff --git a/trunk/drivers/iommu/tegra-smmu.c b/trunk/drivers/iommu/tegra-smmu.c index 2a4bb36bc688..4ba325ab6262 100644 --- a/trunk/drivers/iommu/tegra-smmu.c +++ b/trunk/drivers/iommu/tegra-smmu.c @@ -799,14 +799,14 @@ static void smmu_iommu_detach_dev(struct iommu_domain *domain, goto out; } } - dev_err(smmu->dev, "Couldn't find %s\n", dev_name(dev)); + dev_err(smmu->dev, "Couldn't find %s\n", dev_name(c->dev)); out: spin_unlock(&as->client_lock); } static int smmu_iommu_domain_init(struct iommu_domain *domain) { - int i, err = -EAGAIN; + int i, err = -ENODEV; unsigned long flags; struct smmu_as *as; struct smmu_device *smmu = smmu_handle; @@ -814,14 +814,11 @@ static int smmu_iommu_domain_init(struct iommu_domain *domain) /* Look for a free AS with lock held */ for (i = 0; i < smmu->num_as; i++) { as = &smmu->as[i]; - - if (as->pdir_page) - continue; - - err = alloc_pdir(as); - if (!err) - goto found; - + if (!as->pdir_page) { + err = alloc_pdir(as); + if (!err) + goto found; + } if (err != -EAGAIN) break; } diff --git a/trunk/drivers/isdn/capi/capi.c b/trunk/drivers/isdn/capi/capi.c index c679867c2ccd..38c4bd87b2c9 100644 --- a/trunk/drivers/isdn/capi/capi.c +++ b/trunk/drivers/isdn/capi/capi.c @@ -234,8 +234,7 @@ static struct capiminor *capiminor_alloc(struct capi20_appl *ap, u32 ncci) mp->minor = minor; - dev = tty_port_register_device(&mp->port, capinc_tty_driver, minor, - NULL); + dev = tty_register_device(capinc_tty_driver, minor, NULL); if (IS_ERR(dev)) goto err_out2; diff --git a/trunk/drivers/isdn/gigaset/interface.c b/trunk/drivers/isdn/gigaset/interface.c index 67abf3ff45e8..a6d9fd2858f7 100644 --- a/trunk/drivers/isdn/gigaset/interface.c +++ b/trunk/drivers/isdn/gigaset/interface.c @@ -446,8 +446,8 @@ static void if_set_termios(struct tty_struct *tty, struct ktermios *old) goto out; } - iflag = tty->termios.c_iflag; - cflag = tty->termios.c_cflag; + iflag = tty->termios->c_iflag; + cflag = tty->termios->c_cflag; old_cflag = old ? old->c_cflag : cflag; gig_dbg(DEBUG_IF, "%u: iflag %x cflag %x old %x", cs->minor_index, iflag, cflag, old_cflag); @@ -524,8 +524,7 @@ void gigaset_if_init(struct cardstate *cs) tasklet_init(&cs->if_wake_tasklet, if_wake, (unsigned long) cs); mutex_lock(&cs->mutex); - cs->tty_dev = tty_port_register_device(&cs->port, drv->tty, - cs->minor_index, NULL); + cs->tty_dev = tty_register_device(drv->tty, cs->minor_index, NULL); if (!IS_ERR(cs->tty_dev)) dev_set_drvdata(cs->tty_dev, cs); diff --git a/trunk/drivers/isdn/hardware/mISDN/avmfritz.c b/trunk/drivers/isdn/hardware/mISDN/avmfritz.c index dceaec821b0e..fa6ca4733725 100644 --- a/trunk/drivers/isdn/hardware/mISDN/avmfritz.c +++ b/trunk/drivers/isdn/hardware/mISDN/avmfritz.c @@ -857,9 +857,8 @@ avm_bctrl(struct mISDNchannel *ch, u32 cmd, void *arg) switch (cmd) { case CLOSE_CHANNEL: test_and_clear_bit(FLG_OPEN, &bch->Flags); - cancel_work_sync(&bch->workq); spin_lock_irqsave(&fc->lock, flags); - mISDN_clear_bchannel(bch); + mISDN_freebchannel(bch); modehdlc(bch, ISDN_P_NONE); spin_unlock_irqrestore(&fc->lock, flags); ch->protocol = ISDN_P_NONE; diff --git a/trunk/drivers/isdn/hardware/mISDN/hfcmulti.c b/trunk/drivers/isdn/hardware/mISDN/hfcmulti.c index f02794203bb1..5e402cf2e795 100644 --- a/trunk/drivers/isdn/hardware/mISDN/hfcmulti.c +++ b/trunk/drivers/isdn/hardware/mISDN/hfcmulti.c @@ -5059,7 +5059,6 @@ hfcmulti_init(struct hm_map *m, struct pci_dev *pdev, printk(KERN_INFO "HFC-E1 #%d has overlapping B-channels on fragment #%d\n", E1_cnt + 1, pt); - kfree(hc); return -EINVAL; } maskcheck |= hc->bmask[pt]; @@ -5087,7 +5086,6 @@ hfcmulti_init(struct hm_map *m, struct pci_dev *pdev, if ((poll >> 1) > sizeof(hc->silence_data)) { printk(KERN_ERR "HFCMULTI error: silence_data too small, " "please fix\n"); - kfree(hc); return -EINVAL; } for (i = 0; i < (poll >> 1); i++) diff --git a/trunk/drivers/isdn/hardware/mISDN/mISDNipac.c b/trunk/drivers/isdn/hardware/mISDN/mISDNipac.c index ccd7d851be26..752e0825591f 100644 --- a/trunk/drivers/isdn/hardware/mISDN/mISDNipac.c +++ b/trunk/drivers/isdn/hardware/mISDN/mISDNipac.c @@ -1406,9 +1406,8 @@ hscx_bctrl(struct mISDNchannel *ch, u32 cmd, void *arg) switch (cmd) { case CLOSE_CHANNEL: test_and_clear_bit(FLG_OPEN, &bch->Flags); - cancel_work_sync(&bch->workq); spin_lock_irqsave(hx->ip->hwlock, flags); - mISDN_clear_bchannel(bch); + mISDN_freebchannel(bch); hscx_mode(hx, ISDN_P_NONE); spin_unlock_irqrestore(hx->ip->hwlock, flags); ch->protocol = ISDN_P_NONE; diff --git a/trunk/drivers/isdn/hardware/mISDN/mISDNisar.c b/trunk/drivers/isdn/hardware/mISDN/mISDNisar.c index 182ecf0626c2..be5973ded6d6 100644 --- a/trunk/drivers/isdn/hardware/mISDN/mISDNisar.c +++ b/trunk/drivers/isdn/hardware/mISDN/mISDNisar.c @@ -1588,9 +1588,8 @@ isar_bctrl(struct mISDNchannel *ch, u32 cmd, void *arg) switch (cmd) { case CLOSE_CHANNEL: test_and_clear_bit(FLG_OPEN, &bch->Flags); - cancel_work_sync(&bch->workq); spin_lock_irqsave(ich->is->hwlock, flags); - mISDN_clear_bchannel(bch); + mISDN_freebchannel(bch); modeisar(ich, ISDN_P_NONE); spin_unlock_irqrestore(ich->is->hwlock, flags); ch->protocol = ISDN_P_NONE; diff --git a/trunk/drivers/isdn/hardware/mISDN/netjet.c b/trunk/drivers/isdn/hardware/mISDN/netjet.c index 9bcade59eb73..c3e3e7686273 100644 --- a/trunk/drivers/isdn/hardware/mISDN/netjet.c +++ b/trunk/drivers/isdn/hardware/mISDN/netjet.c @@ -812,9 +812,8 @@ nj_bctrl(struct mISDNchannel *ch, u32 cmd, void *arg) switch (cmd) { case CLOSE_CHANNEL: test_and_clear_bit(FLG_OPEN, &bch->Flags); - cancel_work_sync(&bch->workq); spin_lock_irqsave(&card->lock, flags); - mISDN_clear_bchannel(bch); + mISDN_freebchannel(bch); mode_tiger(bc, ISDN_P_NONE); spin_unlock_irqrestore(&card->lock, flags); ch->protocol = ISDN_P_NONE; diff --git a/trunk/drivers/isdn/hardware/mISDN/w6692.c b/trunk/drivers/isdn/hardware/mISDN/w6692.c index 335fe6455002..26a86b846099 100644 --- a/trunk/drivers/isdn/hardware/mISDN/w6692.c +++ b/trunk/drivers/isdn/hardware/mISDN/w6692.c @@ -1054,9 +1054,8 @@ w6692_bctrl(struct mISDNchannel *ch, u32 cmd, void *arg) switch (cmd) { case CLOSE_CHANNEL: test_and_clear_bit(FLG_OPEN, &bch->Flags); - cancel_work_sync(&bch->workq); spin_lock_irqsave(&card->lock, flags); - mISDN_clear_bchannel(bch); + mISDN_freebchannel(bch); w6692_mode(bc, ISDN_P_NONE); spin_unlock_irqrestore(&card->lock, flags); ch->protocol = ISDN_P_NONE; diff --git a/trunk/drivers/isdn/i4l/isdn_tty.c b/trunk/drivers/isdn/i4l/isdn_tty.c index b817809f763c..7bc50670d7d9 100644 --- a/trunk/drivers/isdn/i4l/isdn_tty.c +++ b/trunk/drivers/isdn/i4l/isdn_tty.c @@ -1009,15 +1009,15 @@ isdn_tty_change_speed(modem_info *info) quot; int i; - if (!port->tty) + if (!port->tty || !port->tty->termios) return; - cflag = port->tty->termios.c_cflag; + cflag = port->tty->termios->c_cflag; quot = i = cflag & CBAUD; if (i & CBAUDEX) { i &= ~CBAUDEX; if (i < 1 || i > 2) - port->tty->termios.c_cflag &= ~CBAUDEX; + port->tty->termios->c_cflag &= ~CBAUDEX; else i += 15; } @@ -1097,7 +1097,7 @@ isdn_tty_shutdown(modem_info *info) #endif isdn_unlock_drivers(); info->msr &= ~UART_MSR_RI; - if (!info->port.tty || (info->port.tty->termios.c_cflag & HUPCL)) { + if (!info->port.tty || (info->port.tty->termios->c_cflag & HUPCL)) { info->mcr &= ~(UART_MCR_DTR | UART_MCR_RTS); if (info->emu.mdmreg[REG_DTRHUP] & BIT_DTRHUP) { isdn_tty_modem_reset_regs(info, 0); @@ -1469,13 +1469,13 @@ isdn_tty_set_termios(struct tty_struct *tty, struct ktermios *old_termios) if (!old_termios) isdn_tty_change_speed(info); else { - if (tty->termios.c_cflag == old_termios->c_cflag && - tty->termios.c_ispeed == old_termios->c_ispeed && - tty->termios.c_ospeed == old_termios->c_ospeed) + if (tty->termios->c_cflag == old_termios->c_cflag && + tty->termios->c_ispeed == old_termios->c_ispeed && + tty->termios->c_ospeed == old_termios->c_ospeed) return; isdn_tty_change_speed(info); if ((old_termios->c_cflag & CRTSCTS) && - !(tty->termios.c_cflag & CRTSCTS)) + !(tty->termios->c_cflag & CRTSCTS)) tty->hw_stopped = 0; } } @@ -1486,18 +1486,6 @@ isdn_tty_set_termios(struct tty_struct *tty, struct ktermios *old_termios) * ------------------------------------------------------------ */ -static int isdn_tty_install(struct tty_driver *driver, struct tty_struct *tty) -{ - modem_info *info = &dev->mdm.info[tty->index]; - - if (isdn_tty_paranoia_check(info, tty->name, __func__)) - return -ENODEV; - - tty->driver_data = info; - - return tty_port_install(&info->port, driver, tty); -} - /* * This routine is called whenever a serial port is opened. It * enables interrupts for a serial port, linking in its async structure into @@ -1507,16 +1495,22 @@ static int isdn_tty_install(struct tty_driver *driver, struct tty_struct *tty) static int isdn_tty_open(struct tty_struct *tty, struct file *filp) { - modem_info *info = tty->driver_data; - struct tty_port *port = &info->port; + struct tty_port *port; + modem_info *info; int retval; + info = &dev->mdm.info[tty->index]; + if (isdn_tty_paranoia_check(info, tty->name, "isdn_tty_open")) + return -ENODEV; + port = &info->port; #ifdef ISDN_DEBUG_MODEM_OPEN printk(KERN_DEBUG "isdn_tty_open %s, count = %d\n", tty->name, port->count); #endif port->count++; + tty->driver_data = info; port->tty = tty; + tty->port = port; /* * Start up serial port */ @@ -1744,7 +1738,6 @@ modem_write_profile(atemu *m) } static const struct tty_operations modem_ops = { - .install = isdn_tty_install, .open = isdn_tty_open, .close = isdn_tty_close, .write = isdn_tty_write, @@ -1789,7 +1782,7 @@ isdn_tty_modem_init(void) m->tty_modem->subtype = SERIAL_TYPE_NORMAL; m->tty_modem->init_termios = tty_std_termios; m->tty_modem->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; - m->tty_modem->flags = TTY_DRIVER_REAL_RAW; + m->tty_modem->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV; m->tty_modem->driver_name = "isdn_tty"; tty_set_operations(m->tty_modem, &modem_ops); retval = tty_register_driver(m->tty_modem); diff --git a/trunk/drivers/isdn/isdnloop/isdnloop.c b/trunk/drivers/isdn/isdnloop/isdnloop.c index baf2686aa8eb..5405ec644db3 100644 --- a/trunk/drivers/isdn/isdnloop/isdnloop.c +++ b/trunk/drivers/isdn/isdnloop/isdnloop.c @@ -16,6 +16,7 @@ #include #include "isdnloop.h" +static char *revision = "$Revision: 1.11.6.7 $"; static char *isdnloop_id = "loop0"; MODULE_DESCRIPTION("ISDN4Linux: Pseudo Driver that simulates an ISDN card"); @@ -1493,6 +1494,17 @@ isdnloop_addcard(char *id1) static int __init isdnloop_init(void) { + char *p; + char rev[10]; + + if ((p = strchr(revision, ':'))) { + strcpy(rev, p + 1); + p = strchr(rev, '$'); + *p = 0; + } else + strcpy(rev, " ??? "); + printk(KERN_NOTICE "isdnloop-ISDN-driver Rev%s\n", rev); + if (isdnloop_id) return (isdnloop_addcard(isdnloop_id)); diff --git a/trunk/drivers/isdn/mISDN/hwchannel.c b/trunk/drivers/isdn/mISDN/hwchannel.c index 2602be23f341..ef34fd40867c 100644 --- a/trunk/drivers/isdn/mISDN/hwchannel.c +++ b/trunk/drivers/isdn/mISDN/hwchannel.c @@ -148,16 +148,17 @@ mISDN_clear_bchannel(struct bchannel *ch) ch->next_minlen = ch->init_minlen; ch->maxlen = ch->init_maxlen; ch->next_maxlen = ch->init_maxlen; - skb_queue_purge(&ch->rqueue); - ch->rcount = 0; } EXPORT_SYMBOL(mISDN_clear_bchannel); -void +int mISDN_freebchannel(struct bchannel *ch) { - cancel_work_sync(&ch->workq); mISDN_clear_bchannel(ch); + skb_queue_purge(&ch->rqueue); + ch->rcount = 0; + flush_work_sync(&ch->workq); + return 0; } EXPORT_SYMBOL(mISDN_freebchannel); diff --git a/trunk/drivers/isdn/mISDN/layer2.c b/trunk/drivers/isdn/mISDN/layer2.c index 949cabb88f1c..0dc8abca1407 100644 --- a/trunk/drivers/isdn/mISDN/layer2.c +++ b/trunk/drivers/isdn/mISDN/layer2.c @@ -2222,7 +2222,7 @@ create_l2(struct mISDNchannel *ch, u_int protocol, u_long options, int tei, InitWin(l2); l2->l2m.fsm = &l2fsm; if (test_bit(FLG_LAPB, &l2->flag) || - test_bit(FLG_FIXED_TEI, &l2->flag) || + test_bit(FLG_PTP, &l2->flag) || test_bit(FLG_LAPD_NET, &l2->flag)) l2->l2m.state = ST_L2_4; else diff --git a/trunk/drivers/leds/led-triggers.c b/trunk/drivers/leds/led-triggers.c index 363975b3c925..6157cbbf4113 100644 --- a/trunk/drivers/leds/led-triggers.c +++ b/trunk/drivers/leds/led-triggers.c @@ -224,7 +224,7 @@ void led_trigger_event(struct led_trigger *trig, struct led_classdev *led_cdev; led_cdev = list_entry(entry, struct led_classdev, trig_list); - __led_set_brightness(led_cdev, brightness); + led_set_brightness(led_cdev, brightness); } read_unlock(&trig->leddev_list_lock); } diff --git a/trunk/drivers/leds/leds-lp8788.c b/trunk/drivers/leds/leds-lp8788.c index 0ade6ebfc914..53bd136f1ef0 100644 --- a/trunk/drivers/leds/leds-lp8788.c +++ b/trunk/drivers/leds/leds-lp8788.c @@ -63,7 +63,7 @@ static int lp8788_led_init_device(struct lp8788_led *led, /* scale configuration */ addr = LP8788_ISINK_CTRL; mask = 1 << (cfg->num + LP8788_ISINK_SCALE_OFFSET); - val = cfg->scale << (cfg->num + LP8788_ISINK_SCALE_OFFSET); + val = cfg->scale << cfg->num; ret = lp8788_update_bits(led->lp, addr, mask, val); if (ret) return ret; diff --git a/trunk/drivers/leds/leds-renesas-tpu.c b/trunk/drivers/leds/leds-renesas-tpu.c index 771ea067e680..9ee12c28059a 100644 --- a/trunk/drivers/leds/leds-renesas-tpu.c +++ b/trunk/drivers/leds/leds-renesas-tpu.c @@ -247,7 +247,7 @@ static int __devinit r_tpu_probe(struct platform_device *pdev) if (!cfg) { dev_err(&pdev->dev, "missing platform data\n"); - return -ENODEV; + goto err0; } p = devm_kzalloc(&pdev->dev, sizeof(*p), GFP_KERNEL); diff --git a/trunk/drivers/lguest/x86/core.c b/trunk/drivers/lguest/x86/core.c index 4af12e1844d5..39809035320a 100644 --- a/trunk/drivers/lguest/x86/core.c +++ b/trunk/drivers/lguest/x86/core.c @@ -203,8 +203,8 @@ void lguest_arch_run_guest(struct lg_cpu *cpu) * we set it now, so we can trap and pass that trap to the Guest if it * uses the FPU. */ - if (cpu->ts && user_has_fpu()) - stts(); + if (cpu->ts) + unlazy_fpu(current); /* * SYSENTER is an optimized way of doing system calls. We can't allow @@ -234,10 +234,6 @@ void lguest_arch_run_guest(struct lg_cpu *cpu) if (boot_cpu_has(X86_FEATURE_SEP)) wrmsr(MSR_IA32_SYSENTER_CS, __KERNEL_CS, 0); - /* Clear the host TS bit if it was set above. */ - if (cpu->ts && user_has_fpu()) - clts(); - /* * If the Guest page faulted, then the cr2 register will tell us the * bad virtual address. We have to grab this now, because once we @@ -253,7 +249,7 @@ void lguest_arch_run_guest(struct lg_cpu *cpu) * a different CPU. So all the critical stuff should be done * before this. */ - else if (cpu->regs->trapnum == 7 && !user_has_fpu()) + else if (cpu->regs->trapnum == 7) math_state_restore(); } diff --git a/trunk/drivers/md/dm-mpath.c b/trunk/drivers/md/dm-mpath.c index 034233eefc82..d8abb90a6c2f 100644 --- a/trunk/drivers/md/dm-mpath.c +++ b/trunk/drivers/md/dm-mpath.c @@ -1555,7 +1555,6 @@ static int multipath_ioctl(struct dm_target *ti, unsigned int cmd, unsigned long arg) { struct multipath *m = ti->private; - struct pgpath *pgpath; struct block_device *bdev; fmode_t mode; unsigned long flags; @@ -1571,14 +1570,12 @@ static int multipath_ioctl(struct dm_target *ti, unsigned int cmd, if (!m->current_pgpath) __choose_pgpath(m, 0); - pgpath = m->current_pgpath; - - if (pgpath) { - bdev = pgpath->path.dev->bdev; - mode = pgpath->path.dev->mode; + if (m->current_pgpath) { + bdev = m->current_pgpath->path.dev->bdev; + mode = m->current_pgpath->path.dev->mode; } - if ((pgpath && m->queue_io) || (!pgpath && m->queue_if_no_path)) + if (m->queue_io) r = -EAGAIN; else if (!bdev) r = -EIO; diff --git a/trunk/drivers/md/dm-table.c b/trunk/drivers/md/dm-table.c index 100368eb7991..f90069029aae 100644 --- a/trunk/drivers/md/dm-table.c +++ b/trunk/drivers/md/dm-table.c @@ -1212,41 +1212,6 @@ struct dm_target *dm_table_find_target(struct dm_table *t, sector_t sector) return &t->targets[(KEYS_PER_NODE * n) + k]; } -static int count_device(struct dm_target *ti, struct dm_dev *dev, - sector_t start, sector_t len, void *data) -{ - unsigned *num_devices = data; - - (*num_devices)++; - - return 0; -} - -/* - * Check whether a table has no data devices attached using each - * target's iterate_devices method. - * Returns false if the result is unknown because a target doesn't - * support iterate_devices. - */ -bool dm_table_has_no_data_devices(struct dm_table *table) -{ - struct dm_target *uninitialized_var(ti); - unsigned i = 0, num_devices = 0; - - while (i < dm_table_get_num_targets(table)) { - ti = dm_table_get_target(table, i++); - - if (!ti->type->iterate_devices) - return false; - - ti->type->iterate_devices(ti, count_device, &num_devices); - if (num_devices) - return false; - } - - return true; -} - /* * Establish the new table's queue_limits and validate them. */ @@ -1389,25 +1354,17 @@ static int device_is_nonrot(struct dm_target *ti, struct dm_dev *dev, return q && blk_queue_nonrot(q); } -static int device_is_not_random(struct dm_target *ti, struct dm_dev *dev, - sector_t start, sector_t len, void *data) -{ - struct request_queue *q = bdev_get_queue(dev->bdev); - - return q && !blk_queue_add_random(q); -} - -static bool dm_table_all_devices_attribute(struct dm_table *t, - iterate_devices_callout_fn func) +static bool dm_table_is_nonrot(struct dm_table *t) { struct dm_target *ti; unsigned i = 0; + /* Ensure that all underlying device are non-rotational. */ while (i < dm_table_get_num_targets(t)) { ti = dm_table_get_target(t, i++); if (!ti->type->iterate_devices || - !ti->type->iterate_devices(ti, func, NULL)) + !ti->type->iterate_devices(ti, device_is_nonrot, NULL)) return 0; } @@ -1439,23 +1396,13 @@ void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q, if (!dm_table_discard_zeroes_data(t)) q->limits.discard_zeroes_data = 0; - /* Ensure that all underlying devices are non-rotational. */ - if (dm_table_all_devices_attribute(t, device_is_nonrot)) + if (dm_table_is_nonrot(t)) queue_flag_set_unlocked(QUEUE_FLAG_NONROT, q); else queue_flag_clear_unlocked(QUEUE_FLAG_NONROT, q); dm_table_set_integrity(t); - /* - * Determine whether or not this queue's I/O timings contribute - * to the entropy pool, Only request-based targets use this. - * Clear QUEUE_FLAG_ADD_RANDOM if any underlying device does not - * have it set. - */ - if (blk_queue_add_random(q) && dm_table_all_devices_attribute(t, device_is_not_random)) - queue_flag_clear_unlocked(QUEUE_FLAG_ADD_RANDOM, q); - /* * QUEUE_FLAG_STACKABLE must be set after all queue settings are * visible to other CPUs because, once the flag is set, incoming bios diff --git a/trunk/drivers/md/dm-thin.c b/trunk/drivers/md/dm-thin.c index c29410af1e22..af1fc3b2c2ad 100644 --- a/trunk/drivers/md/dm-thin.c +++ b/trunk/drivers/md/dm-thin.c @@ -509,9 +509,9 @@ enum pool_mode { struct pool_features { enum pool_mode mode; - bool zero_new_blocks:1; - bool discard_enabled:1; - bool discard_passdown:1; + unsigned zero_new_blocks:1; + unsigned discard_enabled:1; + unsigned discard_passdown:1; }; struct thin_c; @@ -580,8 +580,7 @@ struct pool_c { struct dm_target_callbacks callbacks; dm_block_t low_water_blocks; - struct pool_features requested_pf; /* Features requested during table load */ - struct pool_features adjusted_pf; /* Features used after adjusting for constituent devices */ + struct pool_features pf; }; /* @@ -1840,47 +1839,6 @@ static void __requeue_bios(struct pool *pool) /*---------------------------------------------------------------- * Binding of control targets to a pool object *--------------------------------------------------------------*/ -static bool data_dev_supports_discard(struct pool_c *pt) -{ - struct request_queue *q = bdev_get_queue(pt->data_dev->bdev); - - return q && blk_queue_discard(q); -} - -/* - * If discard_passdown was enabled verify that the data device - * supports discards. Disable discard_passdown if not. - */ -static void disable_passdown_if_not_supported(struct pool_c *pt) -{ - struct pool *pool = pt->pool; - struct block_device *data_bdev = pt->data_dev->bdev; - struct queue_limits *data_limits = &bdev_get_queue(data_bdev)->limits; - sector_t block_size = pool->sectors_per_block << SECTOR_SHIFT; - const char *reason = NULL; - char buf[BDEVNAME_SIZE]; - - if (!pt->adjusted_pf.discard_passdown) - return; - - if (!data_dev_supports_discard(pt)) - reason = "discard unsupported"; - - else if (data_limits->max_discard_sectors < pool->sectors_per_block) - reason = "max discard sectors smaller than a block"; - - else if (data_limits->discard_granularity > block_size) - reason = "discard granularity larger than a block"; - - else if (block_size & (data_limits->discard_granularity - 1)) - reason = "discard granularity not a factor of block size"; - - if (reason) { - DMWARN("Data device (%s) %s: Disabling discard passdown.", bdevname(data_bdev, buf), reason); - pt->adjusted_pf.discard_passdown = false; - } -} - static int bind_control_target(struct pool *pool, struct dm_target *ti) { struct pool_c *pt = ti->private; @@ -1889,17 +1847,32 @@ static int bind_control_target(struct pool *pool, struct dm_target *ti) * We want to make sure that degraded pools are never upgraded. */ enum pool_mode old_mode = pool->pf.mode; - enum pool_mode new_mode = pt->adjusted_pf.mode; + enum pool_mode new_mode = pt->pf.mode; if (old_mode > new_mode) new_mode = old_mode; pool->ti = ti; pool->low_water_blocks = pt->low_water_blocks; - pool->pf = pt->adjusted_pf; - + pool->pf = pt->pf; set_pool_mode(pool, new_mode); + /* + * If discard_passdown was enabled verify that the data device + * supports discards. Disable discard_passdown if not; otherwise + * -EOPNOTSUPP will be returned. + */ + /* FIXME: pull this out into a sep fn. */ + if (pt->pf.discard_passdown) { + struct request_queue *q = bdev_get_queue(pt->data_dev->bdev); + if (!q || !blk_queue_discard(q)) { + char buf[BDEVNAME_SIZE]; + DMWARN("Discard unsupported by data device (%s): Disabling discard passdown.", + bdevname(pt->data_dev->bdev, buf)); + pool->pf.discard_passdown = 0; + } + } + return 0; } @@ -1916,9 +1889,9 @@ static void unbind_control_target(struct pool *pool, struct dm_target *ti) static void pool_features_init(struct pool_features *pf) { pf->mode = PM_WRITE; - pf->zero_new_blocks = true; - pf->discard_enabled = true; - pf->discard_passdown = true; + pf->zero_new_blocks = 1; + pf->discard_enabled = 1; + pf->discard_passdown = 1; } static void __pool_destroy(struct pool *pool) @@ -2146,13 +2119,13 @@ static int parse_pool_features(struct dm_arg_set *as, struct pool_features *pf, argc--; if (!strcasecmp(arg_name, "skip_block_zeroing")) - pf->zero_new_blocks = false; + pf->zero_new_blocks = 0; else if (!strcasecmp(arg_name, "ignore_discard")) - pf->discard_enabled = false; + pf->discard_enabled = 0; else if (!strcasecmp(arg_name, "no_discard_passdown")) - pf->discard_passdown = false; + pf->discard_passdown = 0; else if (!strcasecmp(arg_name, "read_only")) pf->mode = PM_READ_ONLY; @@ -2286,9 +2259,8 @@ static int pool_ctr(struct dm_target *ti, unsigned argc, char **argv) pt->metadata_dev = metadata_dev; pt->data_dev = data_dev; pt->low_water_blocks = low_water_blocks; - pt->adjusted_pf = pt->requested_pf = pf; + pt->pf = pf; ti->num_flush_requests = 1; - /* * Only need to enable discards if the pool should pass * them down to the data device. The thin device's discard @@ -2296,14 +2268,12 @@ static int pool_ctr(struct dm_target *ti, unsigned argc, char **argv) */ if (pf.discard_enabled && pf.discard_passdown) { ti->num_discard_requests = 1; - /* * Setting 'discards_supported' circumvents the normal * stacking of discard limits (this keeps the pool and * thin devices' discard limits consistent). */ ti->discards_supported = true; - ti->discard_zeroes_data_unsupported = true; } ti->private = pt; @@ -2733,7 +2703,7 @@ static int pool_status(struct dm_target *ti, status_type_t type, format_dev_t(buf2, pt->data_dev->bdev->bd_dev), (unsigned long)pool->sectors_per_block, (unsigned long long)pt->low_water_blocks); - emit_flags(&pt->requested_pf, result, sz, maxlen); + emit_flags(&pt->pf, result, sz, maxlen); break; } @@ -2762,21 +2732,20 @@ static int pool_merge(struct dm_target *ti, struct bvec_merge_data *bvm, return min(max_size, q->merge_bvec_fn(q, bvm, biovec)); } -static void set_discard_limits(struct pool_c *pt, struct queue_limits *limits) +static void set_discard_limits(struct pool *pool, struct queue_limits *limits) { - struct pool *pool = pt->pool; - struct queue_limits *data_limits; - + /* + * FIXME: these limits may be incompatible with the pool's data device + */ limits->max_discard_sectors = pool->sectors_per_block; /* - * discard_granularity is just a hint, and not enforced. + * This is just a hint, and not enforced. We have to cope with + * bios that cover a block partially. A discard that spans a block + * boundary is not sent to this target. */ - if (pt->adjusted_pf.discard_passdown) { - data_limits = &bdev_get_queue(pt->data_dev->bdev)->limits; - limits->discard_granularity = data_limits->discard_granularity; - } else - limits->discard_granularity = pool->sectors_per_block << SECTOR_SHIFT; + limits->discard_granularity = pool->sectors_per_block << SECTOR_SHIFT; + limits->discard_zeroes_data = pool->pf.zero_new_blocks; } static void pool_io_hints(struct dm_target *ti, struct queue_limits *limits) @@ -2786,25 +2755,15 @@ static void pool_io_hints(struct dm_target *ti, struct queue_limits *limits) blk_limits_io_min(limits, 0); blk_limits_io_opt(limits, pool->sectors_per_block << SECTOR_SHIFT); - - /* - * pt->adjusted_pf is a staging area for the actual features to use. - * They get transferred to the live pool in bind_control_target() - * called from pool_preresume(). - */ - if (!pt->adjusted_pf.discard_enabled) - return; - - disable_passdown_if_not_supported(pt); - - set_discard_limits(pt, limits); + if (pool->pf.discard_enabled) + set_discard_limits(pool, limits); } static struct target_type pool_target = { .name = "thin-pool", .features = DM_TARGET_SINGLETON | DM_TARGET_ALWAYS_WRITEABLE | DM_TARGET_IMMUTABLE, - .version = {1, 4, 0}, + .version = {1, 3, 0}, .module = THIS_MODULE, .ctr = pool_ctr, .dtr = pool_dtr, @@ -3083,19 +3042,19 @@ static int thin_iterate_devices(struct dm_target *ti, return 0; } -/* - * A thin device always inherits its queue limits from its pool. - */ static void thin_io_hints(struct dm_target *ti, struct queue_limits *limits) { struct thin_c *tc = ti->private; + struct pool *pool = tc->pool; - *limits = bdev_get_queue(tc->pool_dev->bdev)->limits; + blk_limits_io_min(limits, 0); + blk_limits_io_opt(limits, pool->sectors_per_block << SECTOR_SHIFT); + set_discard_limits(pool, limits); } static struct target_type thin_target = { .name = "thin", - .version = {1, 4, 0}, + .version = {1, 3, 0}, .module = THIS_MODULE, .ctr = thin_ctr, .dtr = thin_dtr, diff --git a/trunk/drivers/md/dm-verity.c b/trunk/drivers/md/dm-verity.c index 892ae2766aa6..254d19268ad2 100644 --- a/trunk/drivers/md/dm-verity.c +++ b/trunk/drivers/md/dm-verity.c @@ -718,8 +718,8 @@ static int verity_ctr(struct dm_target *ti, unsigned argc, char **argv) v->hash_dev_block_bits = ffs(num) - 1; if (sscanf(argv[5], "%llu%c", &num_ll, &dummy) != 1 || - (sector_t)(num_ll << (v->data_dev_block_bits - SECTOR_SHIFT)) - >> (v->data_dev_block_bits - SECTOR_SHIFT) != num_ll) { + num_ll << (v->data_dev_block_bits - SECTOR_SHIFT) != + (sector_t)num_ll << (v->data_dev_block_bits - SECTOR_SHIFT)) { ti->error = "Invalid data blocks"; r = -EINVAL; goto bad; @@ -733,8 +733,8 @@ static int verity_ctr(struct dm_target *ti, unsigned argc, char **argv) } if (sscanf(argv[6], "%llu%c", &num_ll, &dummy) != 1 || - (sector_t)(num_ll << (v->hash_dev_block_bits - SECTOR_SHIFT)) - >> (v->hash_dev_block_bits - SECTOR_SHIFT) != num_ll) { + num_ll << (v->hash_dev_block_bits - SECTOR_SHIFT) != + (sector_t)num_ll << (v->hash_dev_block_bits - SECTOR_SHIFT)) { ti->error = "Invalid hash start"; r = -EINVAL; goto bad; diff --git a/trunk/drivers/md/dm.c b/trunk/drivers/md/dm.c index 67ffa391edcf..4e09b6ff5b49 100644 --- a/trunk/drivers/md/dm.c +++ b/trunk/drivers/md/dm.c @@ -865,14 +865,10 @@ static void dm_done(struct request *clone, int error, bool mapped) { int r = error; struct dm_rq_target_io *tio = clone->end_io_data; - dm_request_endio_fn rq_end_io = NULL; + dm_request_endio_fn rq_end_io = tio->ti->type->rq_end_io; - if (tio->ti) { - rq_end_io = tio->ti->type->rq_end_io; - - if (mapped && rq_end_io) - r = rq_end_io(tio->ti, clone, error, &tio->info); - } + if (mapped && rq_end_io) + r = rq_end_io(tio->ti, clone, error, &tio->info); if (r <= 0) /* The target wants to complete the I/O */ @@ -1592,6 +1588,15 @@ static int map_request(struct dm_target *ti, struct request *clone, int r, requeued = 0; struct dm_rq_target_io *tio = clone->end_io_data; + /* + * Hold the md reference here for the in-flight I/O. + * We can't rely on the reference count by device opener, + * because the device may be closed during the request completion + * when all bios are completed. + * See the comment in rq_completed() too. + */ + dm_get(md); + tio->ti = ti; r = ti->type->map_rq(ti, clone, &tio->info); switch (r) { @@ -1623,26 +1628,6 @@ static int map_request(struct dm_target *ti, struct request *clone, return requeued; } -static struct request *dm_start_request(struct mapped_device *md, struct request *orig) -{ - struct request *clone; - - blk_start_request(orig); - clone = orig->special; - atomic_inc(&md->pending[rq_data_dir(clone)]); - - /* - * Hold the md reference here for the in-flight I/O. - * We can't rely on the reference count by device opener, - * because the device may be closed during the request completion - * when all bios are completed. - * See the comment in rq_completed() too. - */ - dm_get(md); - - return clone; -} - /* * q->request_fn for request-based dm. * Called with the queue lock held. @@ -1672,21 +1657,14 @@ static void dm_request_fn(struct request_queue *q) pos = blk_rq_pos(rq); ti = dm_table_find_target(map, pos); - if (!dm_target_is_valid(ti)) { - /* - * Must perform setup, that dm_done() requires, - * before calling dm_kill_unmapped_request - */ - DMERR_LIMIT("request attempted access beyond the end of device"); - clone = dm_start_request(md, rq); - dm_kill_unmapped_request(clone, -EIO); - continue; - } + BUG_ON(!dm_target_is_valid(ti)); if (ti->type->busy && ti->type->busy(ti)) goto delay_and_out; - clone = dm_start_request(md, rq); + blk_start_request(rq); + clone = rq->special; + atomic_inc(&md->pending[rq_data_dir(clone)]); spin_unlock(q->queue_lock); if (map_request(ti, clone, md)) @@ -1706,6 +1684,8 @@ static void dm_request_fn(struct request_queue *q) blk_delay_queue(q, HZ / 10); out: dm_table_put(map); + + return; } int dm_underlying_device_busy(struct request_queue *q) @@ -2429,7 +2409,7 @@ static void dm_queue_flush(struct mapped_device *md) */ struct dm_table *dm_swap_table(struct mapped_device *md, struct dm_table *table) { - struct dm_table *live_map, *map = ERR_PTR(-EINVAL); + struct dm_table *map = ERR_PTR(-EINVAL); struct queue_limits limits; int r; @@ -2439,19 +2419,6 @@ struct dm_table *dm_swap_table(struct mapped_device *md, struct dm_table *table) if (!dm_suspended_md(md)) goto out; - /* - * If the new table has no data devices, retain the existing limits. - * This helps multipath with queue_if_no_path if all paths disappear, - * then new I/O is queued based on these limits, and then some paths - * reappear. - */ - if (dm_table_has_no_data_devices(table)) { - live_map = dm_get_live_table(md); - if (live_map) - limits = md->queue->limits; - dm_table_put(live_map); - } - r = dm_calculate_queue_limits(table, &limits); if (r) { map = ERR_PTR(r); diff --git a/trunk/drivers/md/dm.h b/trunk/drivers/md/dm.h index 6a99fefaa743..52eef493d266 100644 --- a/trunk/drivers/md/dm.h +++ b/trunk/drivers/md/dm.h @@ -54,7 +54,6 @@ void dm_table_event_callback(struct dm_table *t, void (*fn)(void *), void *context); struct dm_target *dm_table_get_target(struct dm_table *t, unsigned int index); struct dm_target *dm_table_find_target(struct dm_table *t, sector_t sector); -bool dm_table_has_no_data_devices(struct dm_table *table); int dm_calculate_queue_limits(struct dm_table *table, struct queue_limits *limits); void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q, diff --git a/trunk/drivers/md/md.c b/trunk/drivers/md/md.c index 308e87b417e0..fcd098794d37 100644 --- a/trunk/drivers/md/md.c +++ b/trunk/drivers/md/md.c @@ -1108,11 +1108,8 @@ static int super_90_load(struct md_rdev *rdev, struct md_rdev *refdev, int minor ret = 0; } rdev->sectors = rdev->sb_start; - /* Limit to 4TB as metadata cannot record more than that. - * (not needed for Linear and RAID0 as metadata doesn't - * record this size) - */ - if (rdev->sectors >= (2ULL << 32) && sb->level >= 1) + /* Limit to 4TB as metadata cannot record more than that */ + if (rdev->sectors >= (2ULL << 32)) rdev->sectors = (2ULL << 32) - 2; if (rdev->sectors < ((sector_t)sb->size) * 2 && sb->level >= 1) @@ -1403,7 +1400,7 @@ super_90_rdev_size_change(struct md_rdev *rdev, sector_t num_sectors) /* Limit to 4TB as metadata cannot record more than that. * 4TB == 2^32 KB, or 2*2^32 sectors. */ - if (num_sectors >= (2ULL << 32) && rdev->mddev->level >= 1) + if (num_sectors >= (2ULL << 32)) num_sectors = (2ULL << 32) - 2; md_super_write(rdev->mddev, rdev, rdev->sb_start, rdev->sb_size, rdev->sb_page); @@ -7619,8 +7616,6 @@ static int remove_and_add_spares(struct mddev *mddev) } } } - if (removed) - set_bit(MD_CHANGE_DEVS, &mddev->flags); return spares; } @@ -7634,11 +7629,9 @@ static void reap_sync_thread(struct mddev *mddev) !test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery)) { /* success...*/ /* activate any spares */ - if (mddev->pers->spare_active(mddev)) { + if (mddev->pers->spare_active(mddev)) sysfs_notify(&mddev->kobj, NULL, "degraded"); - set_bit(MD_CHANGE_DEVS, &mddev->flags); - } } if (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery) && mddev->pers->finish_reshape) diff --git a/trunk/drivers/md/raid10.c b/trunk/drivers/md/raid10.c index 0138a727c1f3..de5ed6fd8806 100644 --- a/trunk/drivers/md/raid10.c +++ b/trunk/drivers/md/raid10.c @@ -659,11 +659,7 @@ static int raid10_mergeable_bvec(struct request_queue *q, max = biovec->bv_len; if (mddev->merge_check_needed) { - struct { - struct r10bio r10_bio; - struct r10dev devs[conf->copies]; - } on_stack; - struct r10bio *r10_bio = &on_stack.r10_bio; + struct r10bio r10_bio; int s; if (conf->reshape_progress != MaxSector) { /* Cannot give any guidance during reshape */ @@ -671,18 +667,18 @@ static int raid10_mergeable_bvec(struct request_queue *q, return biovec->bv_len; return 0; } - r10_bio->sector = sector; - raid10_find_phys(conf, r10_bio); + r10_bio.sector = sector; + raid10_find_phys(conf, &r10_bio); rcu_read_lock(); for (s = 0; s < conf->copies; s++) { - int disk = r10_bio->devs[s].devnum; + int disk = r10_bio.devs[s].devnum; struct md_rdev *rdev = rcu_dereference( conf->mirrors[disk].rdev); if (rdev && !test_bit(Faulty, &rdev->flags)) { struct request_queue *q = bdev_get_queue(rdev->bdev); if (q->merge_bvec_fn) { - bvm->bi_sector = r10_bio->devs[s].addr + bvm->bi_sector = r10_bio.devs[s].addr + rdev->data_offset; bvm->bi_bdev = rdev->bdev; max = min(max, q->merge_bvec_fn( @@ -694,7 +690,7 @@ static int raid10_mergeable_bvec(struct request_queue *q, struct request_queue *q = bdev_get_queue(rdev->bdev); if (q->merge_bvec_fn) { - bvm->bi_sector = r10_bio->devs[s].addr + bvm->bi_sector = r10_bio.devs[s].addr + rdev->data_offset; bvm->bi_bdev = rdev->bdev; max = min(max, q->merge_bvec_fn( @@ -1512,16 +1508,14 @@ static int _enough(struct r10conf *conf, struct geom *geo, int ignore) do { int n = conf->copies; int cnt = 0; - int this = first; while (n--) { - if (conf->mirrors[this].rdev && - this != ignore) + if (conf->mirrors[first].rdev && + first != ignore) cnt++; - this = (this+1) % geo->raid_disks; + first = (first+1) % geo->raid_disks; } if (cnt == 0) return 0; - first = (first + geo->near_copies) % geo->raid_disks; } while (first != 0); return 1; } @@ -4420,18 +4414,14 @@ static int handle_reshape_read_error(struct mddev *mddev, { /* Use sync reads to get the blocks from somewhere else */ int sectors = r10_bio->sectors; + struct r10bio r10b; struct r10conf *conf = mddev->private; - struct { - struct r10bio r10_bio; - struct r10dev devs[conf->copies]; - } on_stack; - struct r10bio *r10b = &on_stack.r10_bio; int slot = 0; int idx = 0; struct bio_vec *bvec = r10_bio->master_bio->bi_io_vec; - r10b->sector = r10_bio->sector; - __raid10_find_phys(&conf->prev, r10b); + r10b.sector = r10_bio->sector; + __raid10_find_phys(&conf->prev, &r10b); while (sectors) { int s = sectors; @@ -4442,7 +4432,7 @@ static int handle_reshape_read_error(struct mddev *mddev, s = PAGE_SIZE >> 9; while (!success) { - int d = r10b->devs[slot].devnum; + int d = r10b.devs[slot].devnum; struct md_rdev *rdev = conf->mirrors[d].rdev; sector_t addr; if (rdev == NULL || @@ -4450,7 +4440,7 @@ static int handle_reshape_read_error(struct mddev *mddev, !test_bit(In_sync, &rdev->flags)) goto failed; - addr = r10b->devs[slot].addr + idx * PAGE_SIZE; + addr = r10b.devs[slot].addr + idx * PAGE_SIZE; success = sync_page_io(rdev, addr, s << 9, diff --git a/trunk/drivers/md/raid10.h b/trunk/drivers/md/raid10.h index 1054cf602345..007c2c68dd83 100644 --- a/trunk/drivers/md/raid10.h +++ b/trunk/drivers/md/raid10.h @@ -110,7 +110,7 @@ struct r10bio { * We choose the number when they are allocated. * We sometimes need an extra bio to write to the replacement. */ - struct r10dev { + struct { struct bio *bio; union { struct bio *repl_bio; /* used for resync and diff --git a/trunk/drivers/md/raid5.c b/trunk/drivers/md/raid5.c index 0689173fd9f5..adda94df5eb2 100644 --- a/trunk/drivers/md/raid5.c +++ b/trunk/drivers/md/raid5.c @@ -393,8 +393,6 @@ static int calc_degraded(struct r5conf *conf) degraded = 0; for (i = 0; i < conf->previous_raid_disks; i++) { struct md_rdev *rdev = rcu_dereference(conf->disks[i].rdev); - if (rdev && test_bit(Faulty, &rdev->flags)) - rdev = rcu_dereference(conf->disks[i].replacement); if (!rdev || test_bit(Faulty, &rdev->flags)) degraded++; else if (test_bit(In_sync, &rdev->flags)) @@ -419,8 +417,6 @@ static int calc_degraded(struct r5conf *conf) degraded2 = 0; for (i = 0; i < conf->raid_disks; i++) { struct md_rdev *rdev = rcu_dereference(conf->disks[i].rdev); - if (rdev && test_bit(Faulty, &rdev->flags)) - rdev = rcu_dereference(conf->disks[i].replacement); if (!rdev || test_bit(Faulty, &rdev->flags)) degraded2++; else if (test_bit(In_sync, &rdev->flags)) @@ -1591,7 +1587,6 @@ static int resize_stripes(struct r5conf *conf, int newsize) #ifdef CONFIG_MULTICORE_RAID456 init_waitqueue_head(&nsh->ops.wait_for_ops); #endif - spin_lock_init(&nsh->stripe_lock); list_add(&nsh->lru, &newstripes); } @@ -4197,7 +4192,7 @@ static void make_request(struct mddev *mddev, struct bio * bi) finish_wait(&conf->wait_for_overlap, &w); set_bit(STRIPE_HANDLE, &sh->state); clear_bit(STRIPE_DELAYED, &sh->state); - if ((bi->bi_rw & REQ_SYNC) && + if ((bi->bi_rw & REQ_NOIDLE) && !test_and_set_bit(STRIPE_PREREAD_ACTIVE, &sh->state)) atomic_inc(&conf->preread_active_stripes); release_stripe_plug(mddev, sh); diff --git a/trunk/drivers/media/dvb/ngene/ngene-cards.c b/trunk/drivers/media/dvb/ngene/ngene-cards.c index 0a497be97af8..72ee8de02260 100644 --- a/trunk/drivers/media/dvb/ngene/ngene-cards.c +++ b/trunk/drivers/media/dvb/ngene/ngene-cards.c @@ -524,7 +524,7 @@ static void ngene_resume(struct pci_dev *dev) printk(KERN_INFO DEVICE_NAME ": resume\n"); } -static const struct pci_error_handlers ngene_errors = { +static struct pci_error_handlers ngene_errors = { .error_detected = ngene_error_detected, .link_reset = ngene_link_reset, .slot_reset = ngene_slot_reset, diff --git a/trunk/drivers/media/dvb/siano/smsusb.c b/trunk/drivers/media/dvb/siano/smsusb.c index aac622200e99..664e460f247b 100644 --- a/trunk/drivers/media/dvb/siano/smsusb.c +++ b/trunk/drivers/media/dvb/siano/smsusb.c @@ -481,7 +481,7 @@ static int smsusb_resume(struct usb_interface *intf) return 0; } -static const struct usb_device_id smsusb_id_table[] = { +static const struct usb_device_id smsusb_id_table[] __devinitconst = { { USB_DEVICE(0x187f, 0x0010), .driver_info = SMS1XXX_BOARD_SIANO_STELLAR }, { USB_DEVICE(0x187f, 0x0100), diff --git a/trunk/drivers/media/radio/radio-shark.c b/trunk/drivers/media/radio/radio-shark.c index 72ded29728bb..d0b6bb507634 100644 --- a/trunk/drivers/media/radio/radio-shark.c +++ b/trunk/drivers/media/radio/radio-shark.c @@ -35,11 +35,6 @@ #include #include -#if defined(CONFIG_LEDS_CLASS) || \ - (defined(CONFIG_LEDS_CLASS_MODULE) && defined(CONFIG_RADIO_SHARK_MODULE)) -#define SHARK_USE_LEDS 1 -#endif - /* * Version Information */ @@ -61,18 +56,44 @@ MODULE_LICENSE("GPL"); enum { BLUE_LED, BLUE_PULSE_LED, RED_LED, NO_LEDS }; +static void shark_led_set_blue(struct led_classdev *led_cdev, + enum led_brightness value); +static void shark_led_set_blue_pulse(struct led_classdev *led_cdev, + enum led_brightness value); +static void shark_led_set_red(struct led_classdev *led_cdev, + enum led_brightness value); + +static const struct led_classdev shark_led_templates[NO_LEDS] = { + [BLUE_LED] = { + .name = "%s:blue:", + .brightness = LED_OFF, + .max_brightness = 127, + .brightness_set = shark_led_set_blue, + }, + [BLUE_PULSE_LED] = { + .name = "%s:blue-pulse:", + .brightness = LED_OFF, + .max_brightness = 255, + .brightness_set = shark_led_set_blue_pulse, + }, + [RED_LED] = { + .name = "%s:red:", + .brightness = LED_OFF, + .max_brightness = 1, + .brightness_set = shark_led_set_red, + }, +}; + struct shark_device { struct usb_device *usbdev; struct v4l2_device v4l2_dev; struct snd_tea575x tea; -#ifdef SHARK_USE_LEDS struct work_struct led_work; struct led_classdev leds[NO_LEDS]; char led_names[NO_LEDS][32]; atomic_t brightness[NO_LEDS]; unsigned long brightness_new; -#endif u8 *transfer_buffer; u32 last_val; @@ -154,13 +175,20 @@ static struct snd_tea575x_ops shark_tea_ops = { .read_val = shark_read_val, }; -#ifdef SHARK_USE_LEDS static void shark_led_work(struct work_struct *work) { struct shark_device *shark = container_of(work, struct shark_device, led_work); int i, res, brightness, actual_len; + /* + * We use the v4l2_dev lock and registered bit to ensure the device + * does not get unplugged and unreffed while we're running. + */ + mutex_lock(&shark->tea.mutex); + if (!video_is_registered(&shark->tea.vd)) + goto leave; + for (i = 0; i < 3; i++) { if (!test_and_clear_bit(i, &shark->brightness_new)) continue; @@ -180,6 +208,8 @@ static void shark_led_work(struct work_struct *work) v4l2_err(&shark->v4l2_dev, "set LED %s error: %d\n", shark->led_names[i], res); } +leave: + mutex_unlock(&shark->tea.mutex); } static void shark_led_set_blue(struct led_classdev *led_cdev, @@ -215,78 +245,19 @@ static void shark_led_set_red(struct led_classdev *led_cdev, schedule_work(&shark->led_work); } -static const struct led_classdev shark_led_templates[NO_LEDS] = { - [BLUE_LED] = { - .name = "%s:blue:", - .brightness = LED_OFF, - .max_brightness = 127, - .brightness_set = shark_led_set_blue, - }, - [BLUE_PULSE_LED] = { - .name = "%s:blue-pulse:", - .brightness = LED_OFF, - .max_brightness = 255, - .brightness_set = shark_led_set_blue_pulse, - }, - [RED_LED] = { - .name = "%s:red:", - .brightness = LED_OFF, - .max_brightness = 1, - .brightness_set = shark_led_set_red, - }, -}; - -static int shark_register_leds(struct shark_device *shark, struct device *dev) -{ - int i, retval; - - INIT_WORK(&shark->led_work, shark_led_work); - for (i = 0; i < NO_LEDS; i++) { - shark->leds[i] = shark_led_templates[i]; - snprintf(shark->led_names[i], sizeof(shark->led_names[0]), - shark->leds[i].name, shark->v4l2_dev.name); - shark->leds[i].name = shark->led_names[i]; - retval = led_classdev_register(dev, &shark->leds[i]); - if (retval) { - v4l2_err(&shark->v4l2_dev, - "couldn't register led: %s\n", - shark->led_names[i]); - return retval; - } - } - return 0; -} - -static void shark_unregister_leds(struct shark_device *shark) -{ - int i; - - for (i = 0; i < NO_LEDS; i++) - led_classdev_unregister(&shark->leds[i]); - - cancel_work_sync(&shark->led_work); -} -#else -static int shark_register_leds(struct shark_device *shark, struct device *dev) -{ - v4l2_warn(&shark->v4l2_dev, - "CONFIG_LED_CLASS not enabled, LED support disabled\n"); - return 0; -} -static inline void shark_unregister_leds(struct shark_device *shark) { } -#endif - static void usb_shark_disconnect(struct usb_interface *intf) { struct v4l2_device *v4l2_dev = usb_get_intfdata(intf); struct shark_device *shark = v4l2_dev_to_shark(v4l2_dev); + int i; mutex_lock(&shark->tea.mutex); v4l2_device_disconnect(&shark->v4l2_dev); snd_tea575x_exit(&shark->tea); mutex_unlock(&shark->tea.mutex); - shark_unregister_leds(shark); + for (i = 0; i < NO_LEDS; i++) + led_classdev_unregister(&shark->leds[i]); v4l2_device_put(&shark->v4l2_dev); } @@ -295,6 +266,7 @@ static void usb_shark_release(struct v4l2_device *v4l2_dev) { struct shark_device *shark = v4l2_dev_to_shark(v4l2_dev); + cancel_work_sync(&shark->led_work); v4l2_device_unregister(&shark->v4l2_dev); kfree(shark->transfer_buffer); kfree(shark); @@ -304,7 +276,7 @@ static int usb_shark_probe(struct usb_interface *intf, const struct usb_device_id *id) { struct shark_device *shark; - int retval = -ENOMEM; + int i, retval = -ENOMEM; shark = kzalloc(sizeof(struct shark_device), GFP_KERNEL); if (!shark) @@ -314,13 +286,17 @@ static int usb_shark_probe(struct usb_interface *intf, if (!shark->transfer_buffer) goto err_alloc_buffer; - v4l2_device_set_name(&shark->v4l2_dev, DRV_NAME, &shark_instance); - - retval = shark_register_leds(shark, &intf->dev); - if (retval) - goto err_reg_leds; + /* + * Work around a bug in usbhid/hid-core.c, where it leaves a dangling + * pointer in intfdata causing v4l2-device.c to not set it. Which + * results in usb_shark_disconnect() referencing the dangling pointer + * + * REMOVE (as soon as the above bug is fixed, patch submitted) + */ + usb_set_intfdata(intf, NULL); shark->v4l2_dev.release = usb_shark_release; + v4l2_device_set_name(&shark->v4l2_dev, DRV_NAME, &shark_instance); retval = v4l2_device_register(&intf->dev, &shark->v4l2_dev); if (retval) { v4l2_err(&shark->v4l2_dev, "couldn't register v4l2_device\n"); @@ -344,13 +320,32 @@ static int usb_shark_probe(struct usb_interface *intf, goto err_init_tea; } + INIT_WORK(&shark->led_work, shark_led_work); + for (i = 0; i < NO_LEDS; i++) { + shark->leds[i] = shark_led_templates[i]; + snprintf(shark->led_names[i], sizeof(shark->led_names[0]), + shark->leds[i].name, shark->v4l2_dev.name); + shark->leds[i].name = shark->led_names[i]; + /* + * We don't fail the probe if we fail to register the leds, + * because once we've called snd_tea575x_init, the /dev/radio0 + * node may be opened from userspace holding a reference to us! + * + * Note we cannot register the leds first instead as + * shark_led_work depends on the v4l2 mutex and registered bit. + */ + retval = led_classdev_register(&intf->dev, &shark->leds[i]); + if (retval) + v4l2_err(&shark->v4l2_dev, + "couldn't register led: %s\n", + shark->led_names[i]); + } + return 0; err_init_tea: v4l2_device_unregister(&shark->v4l2_dev); err_reg_dev: - shark_unregister_leds(shark); -err_reg_leds: kfree(shark->transfer_buffer); err_alloc_buffer: kfree(shark); diff --git a/trunk/drivers/media/radio/radio-shark2.c b/trunk/drivers/media/radio/radio-shark2.c index 7b4efdfaae28..b9575de3e7e8 100644 --- a/trunk/drivers/media/radio/radio-shark2.c +++ b/trunk/drivers/media/radio/radio-shark2.c @@ -35,11 +35,6 @@ #include #include "radio-tea5777.h" -#if defined(CONFIG_LEDS_CLASS) || \ - (defined(CONFIG_LEDS_CLASS_MODULE) && defined(CONFIG_RADIO_SHARK2_MODULE)) -#define SHARK_USE_LEDS 1 -#endif - MODULE_AUTHOR("Hans de Goede "); MODULE_DESCRIPTION("Griffin radioSHARK2, USB radio receiver driver"); MODULE_LICENSE("GPL"); @@ -48,6 +43,7 @@ static int debug; module_param(debug, int, 0); MODULE_PARM_DESC(debug, "Debug level (0-1)"); + #define SHARK_IN_EP 0x83 #define SHARK_OUT_EP 0x05 @@ -58,18 +54,36 @@ MODULE_PARM_DESC(debug, "Debug level (0-1)"); enum { BLUE_LED, RED_LED, NO_LEDS }; +static void shark_led_set_blue(struct led_classdev *led_cdev, + enum led_brightness value); +static void shark_led_set_red(struct led_classdev *led_cdev, + enum led_brightness value); + +static const struct led_classdev shark_led_templates[NO_LEDS] = { + [BLUE_LED] = { + .name = "%s:blue:", + .brightness = LED_OFF, + .max_brightness = 127, + .brightness_set = shark_led_set_blue, + }, + [RED_LED] = { + .name = "%s:red:", + .brightness = LED_OFF, + .max_brightness = 1, + .brightness_set = shark_led_set_red, + }, +}; + struct shark_device { struct usb_device *usbdev; struct v4l2_device v4l2_dev; struct radio_tea5777 tea; -#ifdef SHARK_USE_LEDS struct work_struct led_work; struct led_classdev leds[NO_LEDS]; char led_names[NO_LEDS][32]; atomic_t brightness[NO_LEDS]; unsigned long brightness_new; -#endif u8 *transfer_buffer; }; @@ -147,12 +161,18 @@ static struct radio_tea5777_ops shark_tea_ops = { .read_reg = shark_read_reg, }; -#ifdef SHARK_USE_LEDS static void shark_led_work(struct work_struct *work) { struct shark_device *shark = container_of(work, struct shark_device, led_work); int i, res, brightness, actual_len; + /* + * We use the v4l2_dev lock and registered bit to ensure the device + * does not get unplugged and unreffed while we're running. + */ + mutex_lock(&shark->tea.mutex); + if (!video_is_registered(&shark->tea.vd)) + goto leave; for (i = 0; i < 2; i++) { if (!test_and_clear_bit(i, &shark->brightness_new)) @@ -171,6 +191,8 @@ static void shark_led_work(struct work_struct *work) v4l2_err(&shark->v4l2_dev, "set LED %s error: %d\n", shark->led_names[i], res); } +leave: + mutex_unlock(&shark->tea.mutex); } static void shark_led_set_blue(struct led_classdev *led_cdev, @@ -195,72 +217,19 @@ static void shark_led_set_red(struct led_classdev *led_cdev, schedule_work(&shark->led_work); } -static const struct led_classdev shark_led_templates[NO_LEDS] = { - [BLUE_LED] = { - .name = "%s:blue:", - .brightness = LED_OFF, - .max_brightness = 127, - .brightness_set = shark_led_set_blue, - }, - [RED_LED] = { - .name = "%s:red:", - .brightness = LED_OFF, - .max_brightness = 1, - .brightness_set = shark_led_set_red, - }, -}; - -static int shark_register_leds(struct shark_device *shark, struct device *dev) -{ - int i, retval; - - INIT_WORK(&shark->led_work, shark_led_work); - for (i = 0; i < NO_LEDS; i++) { - shark->leds[i] = shark_led_templates[i]; - snprintf(shark->led_names[i], sizeof(shark->led_names[0]), - shark->leds[i].name, shark->v4l2_dev.name); - shark->leds[i].name = shark->led_names[i]; - retval = led_classdev_register(dev, &shark->leds[i]); - if (retval) { - v4l2_err(&shark->v4l2_dev, - "couldn't register led: %s\n", - shark->led_names[i]); - return retval; - } - } - return 0; -} - -static void shark_unregister_leds(struct shark_device *shark) -{ - int i; - - for (i = 0; i < NO_LEDS; i++) - led_classdev_unregister(&shark->leds[i]); - - cancel_work_sync(&shark->led_work); -} -#else -static int shark_register_leds(struct shark_device *shark, struct device *dev) -{ - v4l2_warn(&shark->v4l2_dev, - "CONFIG_LED_CLASS not enabled, LED support disabled\n"); - return 0; -} -static inline void shark_unregister_leds(struct shark_device *shark) { } -#endif - static void usb_shark_disconnect(struct usb_interface *intf) { struct v4l2_device *v4l2_dev = usb_get_intfdata(intf); struct shark_device *shark = v4l2_dev_to_shark(v4l2_dev); + int i; mutex_lock(&shark->tea.mutex); v4l2_device_disconnect(&shark->v4l2_dev); radio_tea5777_exit(&shark->tea); mutex_unlock(&shark->tea.mutex); - shark_unregister_leds(shark); + for (i = 0; i < NO_LEDS; i++) + led_classdev_unregister(&shark->leds[i]); v4l2_device_put(&shark->v4l2_dev); } @@ -269,6 +238,7 @@ static void usb_shark_release(struct v4l2_device *v4l2_dev) { struct shark_device *shark = v4l2_dev_to_shark(v4l2_dev); + cancel_work_sync(&shark->led_work); v4l2_device_unregister(&shark->v4l2_dev); kfree(shark->transfer_buffer); kfree(shark); @@ -278,7 +248,7 @@ static int usb_shark_probe(struct usb_interface *intf, const struct usb_device_id *id) { struct shark_device *shark; - int retval = -ENOMEM; + int i, retval = -ENOMEM; shark = kzalloc(sizeof(struct shark_device), GFP_KERNEL); if (!shark) @@ -288,13 +258,17 @@ static int usb_shark_probe(struct usb_interface *intf, if (!shark->transfer_buffer) goto err_alloc_buffer; - v4l2_device_set_name(&shark->v4l2_dev, DRV_NAME, &shark_instance); - - retval = shark_register_leds(shark, &intf->dev); - if (retval) - goto err_reg_leds; + /* + * Work around a bug in usbhid/hid-core.c, where it leaves a dangling + * pointer in intfdata causing v4l2-device.c to not set it. Which + * results in usb_shark_disconnect() referencing the dangling pointer + * + * REMOVE (as soon as the above bug is fixed, patch submitted) + */ + usb_set_intfdata(intf, NULL); shark->v4l2_dev.release = usb_shark_release; + v4l2_device_set_name(&shark->v4l2_dev, DRV_NAME, &shark_instance); retval = v4l2_device_register(&intf->dev, &shark->v4l2_dev); if (retval) { v4l2_err(&shark->v4l2_dev, "couldn't register v4l2_device\n"); @@ -318,13 +292,32 @@ static int usb_shark_probe(struct usb_interface *intf, goto err_init_tea; } + INIT_WORK(&shark->led_work, shark_led_work); + for (i = 0; i < NO_LEDS; i++) { + shark->leds[i] = shark_led_templates[i]; + snprintf(shark->led_names[i], sizeof(shark->led_names[0]), + shark->leds[i].name, shark->v4l2_dev.name); + shark->leds[i].name = shark->led_names[i]; + /* + * We don't fail the probe if we fail to register the leds, + * because once we've called radio_tea5777_init, the /dev/radio0 + * node may be opened from userspace holding a reference to us! + * + * Note we cannot register the leds first instead as + * shark_led_work depends on the v4l2 mutex and registered bit. + */ + retval = led_classdev_register(&intf->dev, &shark->leds[i]); + if (retval) + v4l2_err(&shark->v4l2_dev, + "couldn't register led: %s\n", + shark->led_names[i]); + } + return 0; err_init_tea: v4l2_device_unregister(&shark->v4l2_dev); err_reg_dev: - shark_unregister_leds(shark); -err_reg_leds: kfree(shark->transfer_buffer); err_alloc_buffer: kfree(shark); diff --git a/trunk/drivers/media/radio/si470x/radio-si470x-common.c b/trunk/drivers/media/radio/si470x/radio-si470x-common.c index 9bb65e170d99..9e38132afec6 100644 --- a/trunk/drivers/media/radio/si470x/radio-si470x-common.c +++ b/trunk/drivers/media/radio/si470x/radio-si470x-common.c @@ -151,7 +151,6 @@ static const struct v4l2_frequency_band bands[] = { .index = 0, .capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_RDS | V4L2_TUNER_CAP_RDS_BLOCK_IO | - V4L2_TUNER_CAP_FREQ_BANDS | V4L2_TUNER_CAP_HWSEEK_BOUNDED | V4L2_TUNER_CAP_HWSEEK_WRAP, .rangelow = 87500 * 16, @@ -163,7 +162,6 @@ static const struct v4l2_frequency_band bands[] = { .index = 1, .capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_RDS | V4L2_TUNER_CAP_RDS_BLOCK_IO | - V4L2_TUNER_CAP_FREQ_BANDS | V4L2_TUNER_CAP_HWSEEK_BOUNDED | V4L2_TUNER_CAP_HWSEEK_WRAP, .rangelow = 76000 * 16, @@ -175,7 +173,6 @@ static const struct v4l2_frequency_band bands[] = { .index = 2, .capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_RDS | V4L2_TUNER_CAP_RDS_BLOCK_IO | - V4L2_TUNER_CAP_FREQ_BANDS | V4L2_TUNER_CAP_HWSEEK_BOUNDED | V4L2_TUNER_CAP_HWSEEK_WRAP, .rangelow = 76000 * 16, diff --git a/trunk/drivers/media/radio/si470x/radio-si470x-i2c.c b/trunk/drivers/media/radio/si470x/radio-si470x-i2c.c index f867f04cccc9..643a6ff7c5d0 100644 --- a/trunk/drivers/media/radio/si470x/radio-si470x-i2c.c +++ b/trunk/drivers/media/radio/si470x/radio-si470x-i2c.c @@ -225,9 +225,8 @@ int si470x_vidioc_querycap(struct file *file, void *priv, { strlcpy(capability->driver, DRIVER_NAME, sizeof(capability->driver)); strlcpy(capability->card, DRIVER_CARD, sizeof(capability->card)); - capability->device_caps = V4L2_CAP_HW_FREQ_SEEK | V4L2_CAP_READWRITE | - V4L2_CAP_TUNER | V4L2_CAP_RADIO | V4L2_CAP_RDS_CAPTURE; - capability->capabilities = capability->device_caps | V4L2_CAP_DEVICE_CAPS; + capability->capabilities = V4L2_CAP_HW_FREQ_SEEK | + V4L2_CAP_TUNER | V4L2_CAP_RADIO; return 0; } diff --git a/trunk/drivers/media/radio/si470x/radio-si470x-usb.c b/trunk/drivers/media/radio/si470x/radio-si470x-usb.c index be076f7181e7..146be4263ea1 100644 --- a/trunk/drivers/media/radio/si470x/radio-si470x-usb.c +++ b/trunk/drivers/media/radio/si470x/radio-si470x-usb.c @@ -531,7 +531,7 @@ int si470x_vidioc_querycap(struct file *file, void *priv, strlcpy(capability->card, DRIVER_CARD, sizeof(capability->card)); usb_make_path(radio->usbdev, capability->bus_info, sizeof(capability->bus_info)); - capability->device_caps = V4L2_CAP_HW_FREQ_SEEK | V4L2_CAP_READWRITE | + capability->device_caps = V4L2_CAP_HW_FREQ_SEEK | V4L2_CAP_TUNER | V4L2_CAP_RADIO | V4L2_CAP_RDS_CAPTURE; capability->capabilities = capability->device_caps | V4L2_CAP_DEVICE_CAPS; return 0; diff --git a/trunk/drivers/media/rc/Kconfig b/trunk/drivers/media/rc/Kconfig index 8be57634ba60..5180390be7ab 100644 --- a/trunk/drivers/media/rc/Kconfig +++ b/trunk/drivers/media/rc/Kconfig @@ -261,7 +261,6 @@ config IR_WINBOND_CIR config IR_IGUANA tristate "IguanaWorks USB IR Transceiver" - depends on USB_ARCH_HAS_HCD depends on RC_CORE select USB ---help--- diff --git a/trunk/drivers/media/video/gspca/jl2005bcd.c b/trunk/drivers/media/video/gspca/jl2005bcd.c index 234777116e5f..cf9d9fca5b84 100644 --- a/trunk/drivers/media/video/gspca/jl2005bcd.c +++ b/trunk/drivers/media/video/gspca/jl2005bcd.c @@ -512,7 +512,7 @@ static const struct sd_desc sd_desc = { }; /* -- module initialisation -- */ -static const struct usb_device_id device_table[] = { +static const __devinitdata struct usb_device_id device_table[] = { {USB_DEVICE(0x0979, 0x0227)}, {} }; diff --git a/trunk/drivers/media/video/gspca/spca506.c b/trunk/drivers/media/video/gspca/spca506.c index bab01c86c315..969bb5a4cd93 100644 --- a/trunk/drivers/media/video/gspca/spca506.c +++ b/trunk/drivers/media/video/gspca/spca506.c @@ -579,7 +579,7 @@ static const struct sd_desc sd_desc = { }; /* -- module initialisation -- */ -static const struct usb_device_id device_table[] = { +static const struct usb_device_id device_table[] __devinitconst = { {USB_DEVICE(0x06e1, 0xa190)}, /*fixme: may be IntelPCCameraPro BRIDGE_SPCA505 {USB_DEVICE(0x0733, 0x0430)}, */ diff --git a/trunk/drivers/media/video/mem2mem_testdev.c b/trunk/drivers/media/video/mem2mem_testdev.c index 0b91a5cd38eb..7efe9ad7acc7 100644 --- a/trunk/drivers/media/video/mem2mem_testdev.c +++ b/trunk/drivers/media/video/mem2mem_testdev.c @@ -431,7 +431,7 @@ static int vidioc_querycap(struct file *file, void *priv, strncpy(cap->driver, MEM2MEM_NAME, sizeof(cap->driver) - 1); strncpy(cap->card, MEM2MEM_NAME, sizeof(cap->card) - 1); strlcpy(cap->bus_info, MEM2MEM_NAME, sizeof(cap->bus_info)); - cap->device_caps = V4L2_CAP_VIDEO_M2M | V4L2_CAP_STREAMING; + cap->capabilities = V4L2_CAP_VIDEO_M2M | V4L2_CAP_STREAMING; cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; return 0; } diff --git a/trunk/drivers/media/video/mx1_camera.c b/trunk/drivers/media/video/mx1_camera.c index 560a65aa7038..d2e6f82ecfac 100644 --- a/trunk/drivers/media/video/mx1_camera.c +++ b/trunk/drivers/media/video/mx1_camera.c @@ -403,7 +403,7 @@ static void mx1_camera_activate(struct mx1_camera_dev *pcdev) dev_dbg(pcdev->icd->parent, "Activate device\n"); - clk_prepare_enable(pcdev->clk); + clk_enable(pcdev->clk); /* enable CSI before doing anything else */ __raw_writel(csicr1, pcdev->base + CSICR1); @@ -422,7 +422,7 @@ static void mx1_camera_deactivate(struct mx1_camera_dev *pcdev) /* Disable all CSI interface */ __raw_writel(0x00, pcdev->base + CSICR1); - clk_disable_unprepare(pcdev->clk); + clk_disable(pcdev->clk); } /* diff --git a/trunk/drivers/media/video/mx2_camera.c b/trunk/drivers/media/video/mx2_camera.c index ac175406e582..637bde8aca28 100644 --- a/trunk/drivers/media/video/mx2_camera.c +++ b/trunk/drivers/media/video/mx2_camera.c @@ -272,7 +272,7 @@ struct mx2_camera_dev { struct device *dev; struct soc_camera_host soc_host; struct soc_camera_device *icd; - struct clk *clk_csi, *clk_emma_ahb, *clk_emma_ipg; + struct clk *clk_csi, *clk_emma; unsigned int irq_csi, irq_emma; void __iomem *base_csi, *base_emma; @@ -407,7 +407,7 @@ static void mx2_camera_deactivate(struct mx2_camera_dev *pcdev) { unsigned long flags; - clk_disable_unprepare(pcdev->clk_csi); + clk_disable(pcdev->clk_csi); writel(0, pcdev->base_csi + CSICR1); if (cpu_is_mx27()) { writel(0, pcdev->base_emma + PRP_CNTL); @@ -435,7 +435,7 @@ static int mx2_camera_add_device(struct soc_camera_device *icd) if (pcdev->icd) return -EBUSY; - ret = clk_prepare_enable(pcdev->clk_csi); + ret = clk_enable(pcdev->clk_csi); if (ret < 0) return ret; @@ -1633,34 +1633,23 @@ static int __devinit mx27_camera_emma_init(struct mx2_camera_dev *pcdev) goto exit_iounmap; } - pcdev->clk_emma_ipg = clk_get(pcdev->dev, "emma-ipg"); - if (IS_ERR(pcdev->clk_emma_ipg)) { - err = PTR_ERR(pcdev->clk_emma_ipg); + pcdev->clk_emma = clk_get(NULL, "emma"); + if (IS_ERR(pcdev->clk_emma)) { + err = PTR_ERR(pcdev->clk_emma); goto exit_free_irq; } - clk_prepare_enable(pcdev->clk_emma_ipg); - - pcdev->clk_emma_ahb = clk_get(pcdev->dev, "emma-ahb"); - if (IS_ERR(pcdev->clk_emma_ahb)) { - err = PTR_ERR(pcdev->clk_emma_ahb); - goto exit_clk_emma_ipg_put; - } - - clk_prepare_enable(pcdev->clk_emma_ahb); + clk_enable(pcdev->clk_emma); err = mx27_camera_emma_prp_reset(pcdev); if (err) - goto exit_clk_emma_ahb_put; + goto exit_clk_emma_put; return err; -exit_clk_emma_ahb_put: - clk_disable_unprepare(pcdev->clk_emma_ahb); - clk_put(pcdev->clk_emma_ahb); -exit_clk_emma_ipg_put: - clk_disable_unprepare(pcdev->clk_emma_ipg); - clk_put(pcdev->clk_emma_ipg); +exit_clk_emma_put: + clk_disable(pcdev->clk_emma); + clk_put(pcdev->clk_emma); exit_free_irq: free_irq(pcdev->irq_emma, pcdev); exit_iounmap: @@ -1696,7 +1685,7 @@ static int __devinit mx2_camera_probe(struct platform_device *pdev) goto exit; } - pcdev->clk_csi = clk_get(&pdev->dev, "ahb"); + pcdev->clk_csi = clk_get(&pdev->dev, NULL); if (IS_ERR(pcdev->clk_csi)) { dev_err(&pdev->dev, "Could not get csi clock\n"); err = PTR_ERR(pcdev->clk_csi); @@ -1796,10 +1785,8 @@ static int __devinit mx2_camera_probe(struct platform_device *pdev) eallocctx: if (cpu_is_mx27()) { free_irq(pcdev->irq_emma, pcdev); - clk_disable_unprepare(pcdev->clk_emma_ipg); - clk_put(pcdev->clk_emma_ipg); - clk_disable_unprepare(pcdev->clk_emma_ahb); - clk_put(pcdev->clk_emma_ahb); + clk_disable(pcdev->clk_emma); + clk_put(pcdev->clk_emma); iounmap(pcdev->base_emma); release_mem_region(pcdev->res_emma->start, resource_size(pcdev->res_emma)); } @@ -1838,10 +1825,8 @@ static int __devexit mx2_camera_remove(struct platform_device *pdev) iounmap(pcdev->base_csi); if (cpu_is_mx27()) { - clk_disable_unprepare(pcdev->clk_emma_ipg); - clk_put(pcdev->clk_emma_ipg); - clk_disable_unprepare(pcdev->clk_emma_ahb); - clk_put(pcdev->clk_emma_ahb); + clk_disable(pcdev->clk_emma); + clk_put(pcdev->clk_emma); iounmap(pcdev->base_emma); res = pcdev->res_emma; release_mem_region(res->start, resource_size(res)); diff --git a/trunk/drivers/media/video/mx3_camera.c b/trunk/drivers/media/video/mx3_camera.c index af2297dd49c8..f13643d31353 100644 --- a/trunk/drivers/media/video/mx3_camera.c +++ b/trunk/drivers/media/video/mx3_camera.c @@ -61,9 +61,15 @@ #define MAX_VIDEO_MEM 16 +enum csi_buffer_state { + CSI_BUF_NEEDS_INIT, + CSI_BUF_PREPARED, +}; + struct mx3_camera_buffer { /* common v4l buffer stuff -- must be first */ struct vb2_buffer vb; + enum csi_buffer_state state; struct list_head queue; /* One descriptot per scatterlist (per frame) */ @@ -279,7 +285,7 @@ static void mx3_videobuf_queue(struct vb2_buffer *vb) goto error; } - if (!buf->txd) { + if (buf->state == CSI_BUF_NEEDS_INIT) { sg_dma_address(sg) = vb2_dma_contig_plane_dma_addr(vb, 0); sg_dma_len(sg) = new_size; @@ -292,6 +298,7 @@ static void mx3_videobuf_queue(struct vb2_buffer *vb) txd->callback_param = txd; txd->callback = mx3_cam_dma_done; + buf->state = CSI_BUF_PREPARED; buf->txd = txd; } else { txd = buf->txd; @@ -378,6 +385,7 @@ static void mx3_videobuf_release(struct vb2_buffer *vb) /* Doesn't hurt also if the list is empty */ list_del_init(&buf->queue); + buf->state = CSI_BUF_NEEDS_INIT; if (txd) { buf->txd = NULL; @@ -397,13 +405,13 @@ static int mx3_videobuf_init(struct vb2_buffer *vb) struct mx3_camera_dev *mx3_cam = ici->priv; struct mx3_camera_buffer *buf = to_mx3_vb(vb); - if (!buf->txd) { - /* This is for locking debugging only */ - INIT_LIST_HEAD(&buf->queue); - sg_init_table(&buf->sg, 1); + /* This is for locking debugging only */ + INIT_LIST_HEAD(&buf->queue); + sg_init_table(&buf->sg, 1); - mx3_cam->buf_total += vb2_plane_size(vb, 0); - } + buf->state = CSI_BUF_NEEDS_INIT; + + mx3_cam->buf_total += vb2_plane_size(vb, 0); return 0; } diff --git a/trunk/drivers/media/video/soc_camera.c b/trunk/drivers/media/video/soc_camera.c index 1bde255e45df..b03ffecb7438 100644 --- a/trunk/drivers/media/video/soc_camera.c +++ b/trunk/drivers/media/video/soc_camera.c @@ -171,8 +171,7 @@ static int soc_camera_try_fmt(struct soc_camera_device *icd, dev_dbg(icd->pdev, "TRY_FMT(%c%c%c%c, %ux%u)\n", pixfmtstr(pix->pixelformat), pix->width, pix->height); - if (pix->pixelformat != V4L2_PIX_FMT_JPEG && - !(ici->capabilities & SOCAM_HOST_CAP_STRIDE)) { + if (!(ici->capabilities & SOCAM_HOST_CAP_STRIDE)) { pix->bytesperline = 0; pix->sizeimage = 0; } diff --git a/trunk/drivers/media/video/soc_mediabus.c b/trunk/drivers/media/video/soc_mediabus.c index a397812635d6..89dce097a827 100644 --- a/trunk/drivers/media/video/soc_mediabus.c +++ b/trunk/drivers/media/video/soc_mediabus.c @@ -378,9 +378,6 @@ EXPORT_SYMBOL(soc_mbus_samples_per_pixel); s32 soc_mbus_bytes_per_line(u32 width, const struct soc_mbus_pixelfmt *mf) { - if (mf->fourcc == V4L2_PIX_FMT_JPEG) - return 0; - if (mf->layout != SOC_MBUS_LAYOUT_PACKED) return width * mf->bits_per_sample / 8; @@ -403,9 +400,6 @@ EXPORT_SYMBOL(soc_mbus_bytes_per_line); s32 soc_mbus_image_size(const struct soc_mbus_pixelfmt *mf, u32 bytes_per_line, u32 height) { - if (mf->fourcc == V4L2_PIX_FMT_JPEG) - return 0; - if (mf->layout == SOC_MBUS_LAYOUT_PACKED) return bytes_per_line * height; diff --git a/trunk/drivers/media/video/uvc/uvc_queue.c b/trunk/drivers/media/video/uvc/uvc_queue.c index 5577381b5bf0..9288fbd5001b 100644 --- a/trunk/drivers/media/video/uvc/uvc_queue.c +++ b/trunk/drivers/media/video/uvc/uvc_queue.c @@ -338,7 +338,6 @@ struct uvc_buffer *uvc_queue_next_buffer(struct uvc_video_queue *queue, if ((queue->flags & UVC_QUEUE_DROP_CORRUPTED) && buf->error) { buf->error = 0; buf->state = UVC_BUF_STATE_QUEUED; - buf->bytesused = 0; vb2_set_plane_payload(&buf->buf, 0, 0); return buf; } diff --git a/trunk/drivers/media/video/v4l2-ioctl.c b/trunk/drivers/media/video/v4l2-ioctl.c index 6bc47fc82fe2..c3b7b5f59b32 100644 --- a/trunk/drivers/media/video/v4l2-ioctl.c +++ b/trunk/drivers/media/video/v4l2-ioctl.c @@ -402,10 +402,8 @@ static void v4l_print_hw_freq_seek(const void *arg, bool write_only) { const struct v4l2_hw_freq_seek *p = arg; - pr_cont("tuner=%u, type=%u, seek_upward=%u, wrap_around=%u, spacing=%u, " - "rangelow=%u, rangehigh=%u\n", - p->tuner, p->type, p->seek_upward, p->wrap_around, p->spacing, - p->rangelow, p->rangehigh); + pr_cont("tuner=%u, type=%u, seek_upward=%u, wrap_around=%u, spacing=%u\n", + p->tuner, p->type, p->seek_upward, p->wrap_around, p->spacing); } static void v4l_print_requestbuffers(const void *arg, bool write_only) @@ -1855,8 +1853,6 @@ static int v4l_enum_freq_bands(const struct v4l2_ioctl_ops *ops, .type = type, }; - if (p->index) - return -EINVAL; err = ops->vidioc_g_tuner(file, fh, &t); if (err) return err; @@ -1874,8 +1870,6 @@ static int v4l_enum_freq_bands(const struct v4l2_ioctl_ops *ops, if (type != V4L2_TUNER_RADIO) return -EINVAL; - if (p->index) - return -EINVAL; err = ops->vidioc_g_modulator(file, fh, &m); if (err) return err; diff --git a/trunk/drivers/memory/Makefile b/trunk/drivers/memory/Makefile index 9cce5d70ed52..42b3ce9d80fc 100644 --- a/trunk/drivers/memory/Makefile +++ b/trunk/drivers/memory/Makefile @@ -2,9 +2,6 @@ # Makefile for memory devices # -ifeq ($(CONFIG_DDR),y) -obj-$(CONFIG_OF) += of_memory.o -endif obj-$(CONFIG_TI_EMIF) += emif.o obj-$(CONFIG_TEGRA20_MC) += tegra20-mc.o obj-$(CONFIG_TEGRA30_MC) += tegra30-mc.o diff --git a/trunk/drivers/memory/emif.c b/trunk/drivers/memory/emif.c index 06d31c99e6ac..33a4396b24cb 100644 --- a/trunk/drivers/memory/emif.c +++ b/trunk/drivers/memory/emif.c @@ -18,7 +18,6 @@ #include #include #include -#include #include #include #include @@ -26,7 +25,6 @@ #include #include #include "emif.h" -#include "of_memory.h" /** * struct emif_data - Per device static data for driver's use @@ -51,7 +49,6 @@ * frequency in effect at the moment) * @plat_data: Pointer to saved platform data. * @debugfs_root: dentry to the root folder for EMIF in debugfs - * @np_ddr: Pointer to ddr device tree node */ struct emif_data { u8 duplicate; @@ -66,7 +63,6 @@ struct emif_data { struct emif_regs *curr_regs; struct emif_platform_data *plat_data; struct dentry *debugfs_root; - struct device_node *np_ddr; }; static struct emif_data *emif1; @@ -75,7 +71,6 @@ static unsigned long irq_state; static u32 t_ck; /* DDR clock period in ps */ static LIST_HEAD(device_list); -#ifdef CONFIG_DEBUG_FS static void do_emif_regdump_show(struct seq_file *s, struct emif_data *emif, struct emif_regs *regs) { @@ -167,23 +162,23 @@ static int __init_or_module emif_debugfs_init(struct emif_data *emif) int ret; dentry = debugfs_create_dir(dev_name(emif->dev), NULL); - if (!dentry) { - ret = -ENOMEM; + if (IS_ERR(dentry)) { + ret = PTR_ERR(dentry); goto err0; } emif->debugfs_root = dentry; dentry = debugfs_create_file("regcache_dump", S_IRUGO, emif->debugfs_root, emif, &emif_regdump_fops); - if (!dentry) { - ret = -ENOMEM; + if (IS_ERR(dentry)) { + ret = PTR_ERR(dentry); goto err1; } dentry = debugfs_create_file("mr4", S_IRUGO, emif->debugfs_root, emif, &emif_mr4_fops); - if (!dentry) { - ret = -ENOMEM; + if (IS_ERR(dentry)) { + ret = PTR_ERR(dentry); goto err1; } @@ -199,16 +194,6 @@ static void __exit emif_debugfs_exit(struct emif_data *emif) debugfs_remove_recursive(emif->debugfs_root); emif->debugfs_root = NULL; } -#else -static inline int __init_or_module emif_debugfs_init(struct emif_data *emif) -{ - return 0; -} - -static inline void __exit emif_debugfs_exit(struct emif_data *emif) -{ -} -#endif /* * Calculate the period of DDR clock from frequency value @@ -1163,168 +1148,6 @@ static int is_custom_config_valid(struct emif_custom_configs *cust_cfgs, return valid; } -#if defined(CONFIG_OF) -static void __init_or_module of_get_custom_configs(struct device_node *np_emif, - struct emif_data *emif) -{ - struct emif_custom_configs *cust_cfgs = NULL; - int len; - const int *lpmode, *poll_intvl; - - lpmode = of_get_property(np_emif, "low-power-mode", &len); - poll_intvl = of_get_property(np_emif, "temp-alert-poll-interval", &len); - - if (lpmode || poll_intvl) - cust_cfgs = devm_kzalloc(emif->dev, sizeof(*cust_cfgs), - GFP_KERNEL); - - if (!cust_cfgs) - return; - - if (lpmode) { - cust_cfgs->mask |= EMIF_CUSTOM_CONFIG_LPMODE; - cust_cfgs->lpmode = *lpmode; - of_property_read_u32(np_emif, - "low-power-mode-timeout-performance", - &cust_cfgs->lpmode_timeout_performance); - of_property_read_u32(np_emif, - "low-power-mode-timeout-power", - &cust_cfgs->lpmode_timeout_power); - of_property_read_u32(np_emif, - "low-power-mode-freq-threshold", - &cust_cfgs->lpmode_freq_threshold); - } - - if (poll_intvl) { - cust_cfgs->mask |= - EMIF_CUSTOM_CONFIG_TEMP_ALERT_POLL_INTERVAL; - cust_cfgs->temp_alert_poll_interval_ms = *poll_intvl; - } - - if (!is_custom_config_valid(cust_cfgs, emif->dev)) { - devm_kfree(emif->dev, cust_cfgs); - return; - } - - emif->plat_data->custom_configs = cust_cfgs; -} - -static void __init_or_module of_get_ddr_info(struct device_node *np_emif, - struct device_node *np_ddr, - struct ddr_device_info *dev_info) -{ - u32 density = 0, io_width = 0; - int len; - - if (of_find_property(np_emif, "cs1-used", &len)) - dev_info->cs1_used = true; - - if (of_find_property(np_emif, "cal-resistor-per-cs", &len)) - dev_info->cal_resistors_per_cs = true; - - if (of_device_is_compatible(np_ddr , "jedec,lpddr2-s4")) - dev_info->type = DDR_TYPE_LPDDR2_S4; - else if (of_device_is_compatible(np_ddr , "jedec,lpddr2-s2")) - dev_info->type = DDR_TYPE_LPDDR2_S2; - - of_property_read_u32(np_ddr, "density", &density); - of_property_read_u32(np_ddr, "io-width", &io_width); - - /* Convert from density in Mb to the density encoding in jedc_ddr.h */ - if (density & (density - 1)) - dev_info->density = 0; - else - dev_info->density = __fls(density) - 5; - - /* Convert from io_width in bits to io_width encoding in jedc_ddr.h */ - if (io_width & (io_width - 1)) - dev_info->io_width = 0; - else - dev_info->io_width = __fls(io_width) - 1; -} - -static struct emif_data * __init_or_module of_get_memory_device_details( - struct device_node *np_emif, struct device *dev) -{ - struct emif_data *emif = NULL; - struct ddr_device_info *dev_info = NULL; - struct emif_platform_data *pd = NULL; - struct device_node *np_ddr; - int len; - - np_ddr = of_parse_phandle(np_emif, "device-handle", 0); - if (!np_ddr) - goto error; - emif = devm_kzalloc(dev, sizeof(struct emif_data), GFP_KERNEL); - pd = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL); - dev_info = devm_kzalloc(dev, sizeof(*dev_info), GFP_KERNEL); - - if (!emif || !pd || !dev_info) { - dev_err(dev, "%s: Out of memory!!\n", - __func__); - goto error; - } - - emif->plat_data = pd; - pd->device_info = dev_info; - emif->dev = dev; - emif->np_ddr = np_ddr; - emif->temperature_level = SDRAM_TEMP_NOMINAL; - - if (of_device_is_compatible(np_emif, "ti,emif-4d")) - emif->plat_data->ip_rev = EMIF_4D; - else if (of_device_is_compatible(np_emif, "ti,emif-4d5")) - emif->plat_data->ip_rev = EMIF_4D5; - - of_property_read_u32(np_emif, "phy-type", &pd->phy_type); - - if (of_find_property(np_emif, "hw-caps-ll-interface", &len)) - pd->hw_caps |= EMIF_HW_CAPS_LL_INTERFACE; - - of_get_ddr_info(np_emif, np_ddr, dev_info); - if (!is_dev_data_valid(pd->device_info->type, pd->device_info->density, - pd->device_info->io_width, pd->phy_type, pd->ip_rev, - emif->dev)) { - dev_err(dev, "%s: invalid device data!!\n", __func__); - goto error; - } - /* - * For EMIF instances other than EMIF1 see if the devices connected - * are exactly same as on EMIF1(which is typically the case). If so, - * mark it as a duplicate of EMIF1. This will save some memory and - * computation. - */ - if (emif1 && emif1->np_ddr == np_ddr) { - emif->duplicate = true; - goto out; - } else if (emif1) { - dev_warn(emif->dev, "%s: Non-symmetric DDR geometry\n", - __func__); - } - - of_get_custom_configs(np_emif, emif); - emif->plat_data->timings = of_get_ddr_timings(np_ddr, emif->dev, - emif->plat_data->device_info->type, - &emif->plat_data->timings_arr_size); - - emif->plat_data->min_tck = of_get_min_tck(np_ddr, emif->dev); - goto out; - -error: - return NULL; -out: - return emif; -} - -#else - -static struct emif_data * __init_or_module of_get_memory_device_details( - struct device_node *np_emif, struct device *dev) -{ - return NULL; -} -#endif - static struct emif_data *__init_or_module get_device_details( struct platform_device *pdev) { @@ -1444,11 +1267,7 @@ static int __init_or_module emif_probe(struct platform_device *pdev) struct resource *res; int irq; - if (pdev->dev.of_node) - emif = of_get_memory_device_details(pdev->dev.of_node, &pdev->dev); - else - emif = get_device_details(pdev); - + emif = get_device_details(pdev); if (!emif) { pr_err("%s: error getting device data\n", __func__); goto error; @@ -1825,21 +1644,11 @@ static void __attribute__((unused)) freq_post_notify_handling(void) spin_unlock_irqrestore(&emif_lock, irq_state); } -#if defined(CONFIG_OF) -static const struct of_device_id emif_of_match[] = { - { .compatible = "ti,emif-4d" }, - { .compatible = "ti,emif-4d5" }, - {}, -}; -MODULE_DEVICE_TABLE(of, emif_of_match); -#endif - static struct platform_driver emif_driver = { .remove = __exit_p(emif_remove), .shutdown = emif_shutdown, .driver = { .name = "emif", - .of_match_table = of_match_ptr(emif_of_match), }, }; diff --git a/trunk/drivers/memory/of_memory.c b/trunk/drivers/memory/of_memory.c deleted file mode 100644 index 60074351f17e..000000000000 --- a/trunk/drivers/memory/of_memory.c +++ /dev/null @@ -1,153 +0,0 @@ -/* - * OpenFirmware helpers for memory drivers - * - * Copyright (C) 2012 Texas Instruments, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#include -#include -#include -#include -#include -#include -#include - -/** - * of_get_min_tck() - extract min timing values for ddr - * @np: pointer to ddr device tree node - * @device: device requesting for min timing values - * - * Populates the lpddr2_min_tck structure by extracting data - * from device tree node. Returns a pointer to the populated - * structure. If any error in populating the structure, returns - * default min timings provided by JEDEC. - */ -const struct lpddr2_min_tck *of_get_min_tck(struct device_node *np, - struct device *dev) -{ - int ret = 0; - struct lpddr2_min_tck *min; - - min = devm_kzalloc(dev, sizeof(*min), GFP_KERNEL); - if (!min) - goto default_min_tck; - - ret |= of_property_read_u32(np, "tRPab-min-tck", &min->tRPab); - ret |= of_property_read_u32(np, "tRCD-min-tck", &min->tRCD); - ret |= of_property_read_u32(np, "tWR-min-tck", &min->tWR); - ret |= of_property_read_u32(np, "tRASmin-min-tck", &min->tRASmin); - ret |= of_property_read_u32(np, "tRRD-min-tck", &min->tRRD); - ret |= of_property_read_u32(np, "tWTR-min-tck", &min->tWTR); - ret |= of_property_read_u32(np, "tXP-min-tck", &min->tXP); - ret |= of_property_read_u32(np, "tRTP-min-tck", &min->tRTP); - ret |= of_property_read_u32(np, "tCKE-min-tck", &min->tCKE); - ret |= of_property_read_u32(np, "tCKESR-min-tck", &min->tCKESR); - ret |= of_property_read_u32(np, "tFAW-min-tck", &min->tFAW); - - if (ret) { - devm_kfree(dev, min); - goto default_min_tck; - } - - return min; - -default_min_tck: - dev_warn(dev, "%s: using default min-tck values\n", __func__); - return &lpddr2_jedec_min_tck; -} -EXPORT_SYMBOL(of_get_min_tck); - -static int of_do_get_timings(struct device_node *np, - struct lpddr2_timings *tim) -{ - int ret; - - ret = of_property_read_u32(np, "max-freq", &tim->max_freq); - ret |= of_property_read_u32(np, "min-freq", &tim->min_freq); - ret |= of_property_read_u32(np, "tRPab", &tim->tRPab); - ret |= of_property_read_u32(np, "tRCD", &tim->tRCD); - ret |= of_property_read_u32(np, "tWR", &tim->tWR); - ret |= of_property_read_u32(np, "tRAS-min", &tim->tRAS_min); - ret |= of_property_read_u32(np, "tRRD", &tim->tRRD); - ret |= of_property_read_u32(np, "tWTR", &tim->tWTR); - ret |= of_property_read_u32(np, "tXP", &tim->tXP); - ret |= of_property_read_u32(np, "tRTP", &tim->tRTP); - ret |= of_property_read_u32(np, "tCKESR", &tim->tCKESR); - ret |= of_property_read_u32(np, "tDQSCK-max", &tim->tDQSCK_max); - ret |= of_property_read_u32(np, "tFAW", &tim->tFAW); - ret |= of_property_read_u32(np, "tZQCS", &tim->tZQCS); - ret |= of_property_read_u32(np, "tZQCL", &tim->tZQCL); - ret |= of_property_read_u32(np, "tZQinit", &tim->tZQinit); - ret |= of_property_read_u32(np, "tRAS-max-ns", &tim->tRAS_max_ns); - ret |= of_property_read_u32(np, "tDQSCK-max-derated", - &tim->tDQSCK_max_derated); - - return ret; -} - -/** - * of_get_ddr_timings() - extracts the ddr timings and updates no of - * frequencies available. - * @np_ddr: Pointer to ddr device tree node - * @dev: Device requesting for ddr timings - * @device_type: Type of ddr(LPDDR2 S2/S4) - * @nr_frequencies: No of frequencies available for ddr - * (updated by this function) - * - * Populates lpddr2_timings structure by extracting data from device - * tree node. Returns pointer to populated structure. If any error - * while populating, returns default timings provided by JEDEC. - */ -const struct lpddr2_timings *of_get_ddr_timings(struct device_node *np_ddr, - struct device *dev, u32 device_type, u32 *nr_frequencies) -{ - struct lpddr2_timings *timings = NULL; - u32 arr_sz = 0, i = 0; - struct device_node *np_tim; - char *tim_compat; - - switch (device_type) { - case DDR_TYPE_LPDDR2_S2: - case DDR_TYPE_LPDDR2_S4: - tim_compat = "jedec,lpddr2-timings"; - break; - default: - dev_warn(dev, "%s: un-supported memory type\n", __func__); - } - - for_each_child_of_node(np_ddr, np_tim) - if (of_device_is_compatible(np_tim, tim_compat)) - arr_sz++; - - if (arr_sz) - timings = devm_kzalloc(dev, sizeof(*timings) * arr_sz, - GFP_KERNEL); - - if (!timings) - goto default_timings; - - for_each_child_of_node(np_ddr, np_tim) { - if (of_device_is_compatible(np_tim, tim_compat)) { - if (of_do_get_timings(np_tim, &timings[i])) { - devm_kfree(dev, timings); - goto default_timings; - } - i++; - } - } - - *nr_frequencies = arr_sz; - - return timings; - -default_timings: - dev_warn(dev, "%s: using default timings\n", __func__); - *nr_frequencies = ARRAY_SIZE(lpddr2_jedec_timings); - return lpddr2_jedec_timings; -} -EXPORT_SYMBOL(of_get_ddr_timings); diff --git a/trunk/drivers/memory/of_memory.h b/trunk/drivers/memory/of_memory.h deleted file mode 100644 index ef2514f553d3..000000000000 --- a/trunk/drivers/memory/of_memory.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * OpenFirmware helpers for memory drivers - * - * Copyright (C) 2012 Texas Instruments, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#ifndef __LINUX_MEMORY_OF_REG_H -#define __LINUX_MEMORY_OF_REG_H - -#if defined(CONFIG_OF) && defined(CONFIG_DDR) -extern const struct lpddr2_min_tck *of_get_min_tck(struct device_node *np, - struct device *dev); -extern const struct lpddr2_timings - *of_get_ddr_timings(struct device_node *np_ddr, struct device *dev, - u32 device_type, u32 *nr_frequencies); -#else -static inline const struct lpddr2_min_tck - *of_get_min_tck(struct device_node *np, struct device *dev) -{ - return NULL; -} - -static inline const struct lpddr2_timings - *of_get_ddr_timings(struct device_node *np_ddr, struct device *dev, - u32 device_type, u32 *nr_frequencies) -{ - return NULL; -} -#endif /* CONFIG_OF && CONFIG_DDR */ - -#endif /* __LINUX_MEMORY_OF_REG_ */ diff --git a/trunk/drivers/memory/tegra20-mc.c b/trunk/drivers/memory/tegra20-mc.c index e6764bb41cb9..3ed49c1c2b91 100644 --- a/trunk/drivers/memory/tegra20-mc.c +++ b/trunk/drivers/memory/tegra20-mc.c @@ -57,7 +57,7 @@ static inline u32 mc_readl(struct tegra20_mc *mc, u32 offs) if (offs < 0x24) val = readl(mc->regs[0] + offs); - else if (offs < 0x400) + if (offs < 0x400) val = readl(mc->regs[1] + offs - 0x3c); return val; @@ -65,10 +65,14 @@ static inline u32 mc_readl(struct tegra20_mc *mc, u32 offs) static inline void mc_writel(struct tegra20_mc *mc, u32 val, u32 offs) { - if (offs < 0x24) + if (offs < 0x24) { writel(val, mc->regs[0] + offs); - else if (offs < 0x400) + return; + } + if (offs < 0x400) { writel(val, mc->regs[1] + offs - 0x3c); + return; + } } static const char * const tegra20_mc_client[] = { diff --git a/trunk/drivers/memory/tegra30-mc.c b/trunk/drivers/memory/tegra30-mc.c index 802b9ea431fa..e56ff04eb5cc 100644 --- a/trunk/drivers/memory/tegra30-mc.c +++ b/trunk/drivers/memory/tegra30-mc.c @@ -95,11 +95,11 @@ static inline u32 mc_readl(struct tegra30_mc *mc, u32 offs) if (offs < 0x10) val = readl(mc->regs[0] + offs); - else if (offs < 0x1f0) + if (offs < 0x1f0) val = readl(mc->regs[1] + offs - 0x3c); - else if (offs < 0x228) + if (offs < 0x228) val = readl(mc->regs[2] + offs - 0x200); - else if (offs < 0x400) + if (offs < 0x400) val = readl(mc->regs[3] + offs - 0x284); return val; @@ -107,14 +107,22 @@ static inline u32 mc_readl(struct tegra30_mc *mc, u32 offs) static inline void mc_writel(struct tegra30_mc *mc, u32 val, u32 offs) { - if (offs < 0x10) + if (offs < 0x10) { writel(val, mc->regs[0] + offs); - else if (offs < 0x1f0) + return; + } + if (offs < 0x1f0) { writel(val, mc->regs[1] + offs - 0x3c); - else if (offs < 0x228) + return; + } + if (offs < 0x228) { writel(val, mc->regs[2] + offs - 0x200); - else if (offs < 0x400) + return; + } + if (offs < 0x400) { writel(val, mc->regs[3] + offs - 0x284); + return; + } } static const char * const tegra30_mc_client[] = { diff --git a/trunk/drivers/mfd/88pm800.c b/trunk/drivers/mfd/88pm800.c index ce229ea933d1..b67a3018b136 100644 --- a/trunk/drivers/mfd/88pm800.c +++ b/trunk/drivers/mfd/88pm800.c @@ -470,8 +470,7 @@ static int __devinit device_800_init(struct pm80x_chip *chip, ret = mfd_add_devices(chip->dev, 0, &onkey_devs[0], - ARRAY_SIZE(onkey_devs), &onkey_resources[0], 0, - NULL); + ARRAY_SIZE(onkey_devs), &onkey_resources[0], 0); if (ret < 0) { dev_err(chip->dev, "Failed to add onkey subdev\n"); goto out_dev; @@ -482,7 +481,7 @@ static int __devinit device_800_init(struct pm80x_chip *chip, rtc_devs[0].platform_data = pdata->rtc; rtc_devs[0].pdata_size = sizeof(struct pm80x_rtc_pdata); ret = mfd_add_devices(chip->dev, 0, &rtc_devs[0], - ARRAY_SIZE(rtc_devs), NULL, 0, NULL); + ARRAY_SIZE(rtc_devs), NULL, 0); if (ret < 0) { dev_err(chip->dev, "Failed to add rtc subdev\n"); goto out_dev; diff --git a/trunk/drivers/mfd/88pm805.c b/trunk/drivers/mfd/88pm805.c index c20a31136f04..6146583589f6 100644 --- a/trunk/drivers/mfd/88pm805.c +++ b/trunk/drivers/mfd/88pm805.c @@ -216,8 +216,7 @@ static int __devinit device_805_init(struct pm80x_chip *chip) } ret = mfd_add_devices(chip->dev, 0, &codec_devs[0], - ARRAY_SIZE(codec_devs), &codec_resources[0], 0, - NULL); + ARRAY_SIZE(codec_devs), &codec_resources[0], 0); if (ret < 0) { dev_err(chip->dev, "Failed to add codec subdev\n"); goto out_codec; diff --git a/trunk/drivers/mfd/88pm860x-core.c b/trunk/drivers/mfd/88pm860x-core.c index b73f033b2c60..d09918cf1b15 100644 --- a/trunk/drivers/mfd/88pm860x-core.c +++ b/trunk/drivers/mfd/88pm860x-core.c @@ -637,7 +637,7 @@ static void __devinit device_bk_init(struct pm860x_chip *chip, bk_devs[i].resources = &bk_resources[j]; ret = mfd_add_devices(chip->dev, 0, &bk_devs[i], 1, - &bk_resources[j], 0, NULL); + &bk_resources[j], 0); if (ret < 0) { dev_err(chip->dev, "Failed to add " "backlight subdev\n"); @@ -672,7 +672,7 @@ static void __devinit device_led_init(struct pm860x_chip *chip, led_devs[i].resources = &led_resources[j], ret = mfd_add_devices(chip->dev, 0, &led_devs[i], 1, - &led_resources[j], 0, NULL); + &led_resources[j], 0); if (ret < 0) { dev_err(chip->dev, "Failed to add " "led subdev\n"); @@ -709,7 +709,7 @@ static void __devinit device_regulator_init(struct pm860x_chip *chip, regulator_devs[i].resources = ®ulator_resources[seq]; ret = mfd_add_devices(chip->dev, 0, ®ulator_devs[i], 1, - ®ulator_resources[seq], 0, NULL); + ®ulator_resources[seq], 0); if (ret < 0) { dev_err(chip->dev, "Failed to add regulator subdev\n"); goto out; @@ -733,7 +733,7 @@ static void __devinit device_rtc_init(struct pm860x_chip *chip, rtc_devs[0].resources = &rtc_resources[0]; ret = mfd_add_devices(chip->dev, 0, &rtc_devs[0], ARRAY_SIZE(rtc_devs), &rtc_resources[0], - chip->irq_base, NULL); + chip->irq_base); if (ret < 0) dev_err(chip->dev, "Failed to add rtc subdev\n"); } @@ -752,7 +752,7 @@ static void __devinit device_touch_init(struct pm860x_chip *chip, touch_devs[0].resources = &touch_resources[0]; ret = mfd_add_devices(chip->dev, 0, &touch_devs[0], ARRAY_SIZE(touch_devs), &touch_resources[0], - chip->irq_base, NULL); + chip->irq_base); if (ret < 0) dev_err(chip->dev, "Failed to add touch subdev\n"); } @@ -770,7 +770,7 @@ static void __devinit device_power_init(struct pm860x_chip *chip, power_devs[0].num_resources = ARRAY_SIZE(battery_resources); power_devs[0].resources = &battery_resources[0], ret = mfd_add_devices(chip->dev, 0, &power_devs[0], 1, - &battery_resources[0], chip->irq_base, NULL); + &battery_resources[0], chip->irq_base); if (ret < 0) dev_err(chip->dev, "Failed to add battery subdev\n"); @@ -779,7 +779,7 @@ static void __devinit device_power_init(struct pm860x_chip *chip, power_devs[1].num_resources = ARRAY_SIZE(charger_resources); power_devs[1].resources = &charger_resources[0], ret = mfd_add_devices(chip->dev, 0, &power_devs[1], 1, - &charger_resources[0], chip->irq_base, NULL); + &charger_resources[0], chip->irq_base); if (ret < 0) dev_err(chip->dev, "Failed to add charger subdev\n"); @@ -788,7 +788,7 @@ static void __devinit device_power_init(struct pm860x_chip *chip, power_devs[2].num_resources = ARRAY_SIZE(preg_resources); power_devs[2].resources = &preg_resources[0], ret = mfd_add_devices(chip->dev, 0, &power_devs[2], 1, - &preg_resources[0], chip->irq_base, NULL); + &preg_resources[0], chip->irq_base); if (ret < 0) dev_err(chip->dev, "Failed to add preg subdev\n"); } @@ -802,7 +802,7 @@ static void __devinit device_onkey_init(struct pm860x_chip *chip, onkey_devs[0].resources = &onkey_resources[0], ret = mfd_add_devices(chip->dev, 0, &onkey_devs[0], ARRAY_SIZE(onkey_devs), &onkey_resources[0], - chip->irq_base, NULL); + chip->irq_base); if (ret < 0) dev_err(chip->dev, "Failed to add onkey subdev\n"); } @@ -815,8 +815,7 @@ static void __devinit device_codec_init(struct pm860x_chip *chip, codec_devs[0].num_resources = ARRAY_SIZE(codec_resources); codec_devs[0].resources = &codec_resources[0], ret = mfd_add_devices(chip->dev, 0, &codec_devs[0], - ARRAY_SIZE(codec_devs), &codec_resources[0], 0, - NULL); + ARRAY_SIZE(codec_devs), &codec_resources[0], 0); if (ret < 0) dev_err(chip->dev, "Failed to add codec subdev\n"); } diff --git a/trunk/drivers/mfd/Kconfig b/trunk/drivers/mfd/Kconfig index b1a146205c08..d1facef28a60 100644 --- a/trunk/drivers/mfd/Kconfig +++ b/trunk/drivers/mfd/Kconfig @@ -395,8 +395,7 @@ config MFD_TC6387XB config MFD_TC6393XB bool "Support Toshiba TC6393XB" - depends on ARM && HAVE_CLK - select GPIOLIB + depends on GPIOLIB && ARM && HAVE_CLK select MFD_CORE select MFD_TMIO help diff --git a/trunk/drivers/mfd/aat2870-core.c b/trunk/drivers/mfd/aat2870-core.c index f1beb4971f87..44a3fdbadef4 100644 --- a/trunk/drivers/mfd/aat2870-core.c +++ b/trunk/drivers/mfd/aat2870-core.c @@ -424,7 +424,7 @@ static int aat2870_i2c_probe(struct i2c_client *client, } ret = mfd_add_devices(aat2870->dev, 0, aat2870_devs, - ARRAY_SIZE(aat2870_devs), NULL, 0, NULL); + ARRAY_SIZE(aat2870_devs), NULL, 0); if (ret != 0) { dev_err(aat2870->dev, "Failed to add subdev: %d\n", ret); goto out_disable; diff --git a/trunk/drivers/mfd/ab3100-core.c b/trunk/drivers/mfd/ab3100-core.c index 01781ae5d0d7..78fca2902c8d 100644 --- a/trunk/drivers/mfd/ab3100-core.c +++ b/trunk/drivers/mfd/ab3100-core.c @@ -946,7 +946,7 @@ static int __devinit ab3100_probe(struct i2c_client *client, } err = mfd_add_devices(&client->dev, 0, ab3100_devs, - ARRAY_SIZE(ab3100_devs), NULL, 0, NULL); + ARRAY_SIZE(ab3100_devs), NULL, 0); ab3100_setup_debugfs(ab3100); diff --git a/trunk/drivers/mfd/ab8500-core.c b/trunk/drivers/mfd/ab8500-core.c index 47adf800024e..626b4ecaf647 100644 --- a/trunk/drivers/mfd/ab8500-core.c +++ b/trunk/drivers/mfd/ab8500-core.c @@ -1418,25 +1418,25 @@ static int __devinit ab8500_probe(struct platform_device *pdev) ret = mfd_add_devices(ab8500->dev, 0, abx500_common_devs, ARRAY_SIZE(abx500_common_devs), NULL, - ab8500->irq_base, ab8500->domain); + ab8500->irq_base); if (ret) goto out_freeirq; if (is_ab9540(ab8500)) ret = mfd_add_devices(ab8500->dev, 0, ab9540_devs, ARRAY_SIZE(ab9540_devs), NULL, - ab8500->irq_base, ab8500->domain); + ab8500->irq_base); else ret = mfd_add_devices(ab8500->dev, 0, ab8500_devs, ARRAY_SIZE(ab8500_devs), NULL, - ab8500->irq_base, ab8500->domain); + ab8500->irq_base); if (ret) goto out_freeirq; if (is_ab9540(ab8500) || is_ab8505(ab8500)) ret = mfd_add_devices(ab8500->dev, 0, ab9540_ab8505_devs, ARRAY_SIZE(ab9540_ab8505_devs), NULL, - ab8500->irq_base, ab8500->domain); + ab8500->irq_base); if (ret) goto out_freeirq; @@ -1444,7 +1444,7 @@ static int __devinit ab8500_probe(struct platform_device *pdev) /* Add battery management devices */ ret = mfd_add_devices(ab8500->dev, 0, ab8500_bm_devs, ARRAY_SIZE(ab8500_bm_devs), NULL, - ab8500->irq_base, ab8500->domain); + ab8500->irq_base); if (ret) dev_err(ab8500->dev, "error adding bm devices\n"); } diff --git a/trunk/drivers/mfd/ab8500-gpadc.c b/trunk/drivers/mfd/ab8500-gpadc.c index 29d72a259c85..866f95960b4b 100644 --- a/trunk/drivers/mfd/ab8500-gpadc.c +++ b/trunk/drivers/mfd/ab8500-gpadc.c @@ -342,7 +342,7 @@ int ab8500_gpadc_read_raw(struct ab8500_gpadc *gpadc, u8 channel) /* * Delay might be needed for ABB8500 cut 3.0, if not, remove - * when hardware will be available + * when hardware will be availible */ msleep(1); break; diff --git a/trunk/drivers/mfd/arizona-core.c b/trunk/drivers/mfd/arizona-core.c index 1b48f2094806..c7983e862549 100644 --- a/trunk/drivers/mfd/arizona-core.c +++ b/trunk/drivers/mfd/arizona-core.c @@ -316,7 +316,7 @@ int __devinit arizona_dev_init(struct arizona *arizona) } ret = mfd_add_devices(arizona->dev, -1, early_devs, - ARRAY_SIZE(early_devs), NULL, 0, NULL); + ARRAY_SIZE(early_devs), NULL, 0); if (ret != 0) { dev_err(dev, "Failed to add early children: %d\n", ret); return ret; @@ -516,11 +516,11 @@ int __devinit arizona_dev_init(struct arizona *arizona) switch (arizona->type) { case WM5102: ret = mfd_add_devices(arizona->dev, -1, wm5102_devs, - ARRAY_SIZE(wm5102_devs), NULL, 0, NULL); + ARRAY_SIZE(wm5102_devs), NULL, 0); break; case WM5110: ret = mfd_add_devices(arizona->dev, -1, wm5110_devs, - ARRAY_SIZE(wm5102_devs), NULL, 0, NULL); + ARRAY_SIZE(wm5102_devs), NULL, 0); break; } diff --git a/trunk/drivers/mfd/asic3.c b/trunk/drivers/mfd/asic3.c index 62f0883a7630..383421bf5760 100644 --- a/trunk/drivers/mfd/asic3.c +++ b/trunk/drivers/mfd/asic3.c @@ -913,19 +913,18 @@ static int __init asic3_mfd_probe(struct platform_device *pdev, if (pdata->clock_rate) { ds1wm_pdata.clock_rate = pdata->clock_rate; ret = mfd_add_devices(&pdev->dev, pdev->id, - &asic3_cell_ds1wm, 1, mem, asic->irq_base, NULL); + &asic3_cell_ds1wm, 1, mem, asic->irq_base); if (ret < 0) goto out; } if (mem_sdio && (irq >= 0)) { ret = mfd_add_devices(&pdev->dev, pdev->id, - &asic3_cell_mmc, 1, mem_sdio, irq, NULL); + &asic3_cell_mmc, 1, mem_sdio, irq); if (ret < 0) goto out; } - ret = 0; if (pdata->leds) { int i; @@ -934,7 +933,7 @@ static int __init asic3_mfd_probe(struct platform_device *pdev, asic3_cell_leds[i].pdata_size = sizeof(pdata->leds[i]); } ret = mfd_add_devices(&pdev->dev, 0, - asic3_cell_leds, ASIC3_NUM_LEDS, NULL, 0, NULL); + asic3_cell_leds, ASIC3_NUM_LEDS, NULL, 0); } out: diff --git a/trunk/drivers/mfd/cs5535-mfd.c b/trunk/drivers/mfd/cs5535-mfd.c index 2b282133c725..3419e726de47 100644 --- a/trunk/drivers/mfd/cs5535-mfd.c +++ b/trunk/drivers/mfd/cs5535-mfd.c @@ -149,7 +149,7 @@ static int __devinit cs5535_mfd_probe(struct pci_dev *pdev, } err = mfd_add_devices(&pdev->dev, -1, cs5535_mfd_cells, - ARRAY_SIZE(cs5535_mfd_cells), NULL, 0, NULL); + ARRAY_SIZE(cs5535_mfd_cells), NULL, 0); if (err) { dev_err(&pdev->dev, "MFD add devices failed: %d\n", err); goto err_disable; diff --git a/trunk/drivers/mfd/da9052-core.c b/trunk/drivers/mfd/da9052-core.c index a0a62b24621b..2544910e1fd6 100644 --- a/trunk/drivers/mfd/da9052-core.c +++ b/trunk/drivers/mfd/da9052-core.c @@ -803,7 +803,7 @@ int __devinit da9052_device_init(struct da9052 *da9052, u8 chip_id) dev_err(da9052->dev, "DA9052 ADC IRQ failed ret=%d\n", ret); ret = mfd_add_devices(da9052->dev, -1, da9052_subdev_info, - ARRAY_SIZE(da9052_subdev_info), NULL, 0, NULL); + ARRAY_SIZE(da9052_subdev_info), NULL, 0); if (ret) goto err; diff --git a/trunk/drivers/mfd/davinci_voicecodec.c b/trunk/drivers/mfd/davinci_voicecodec.c index 45e83a68641b..4e2af2cb2d26 100644 --- a/trunk/drivers/mfd/davinci_voicecodec.c +++ b/trunk/drivers/mfd/davinci_voicecodec.c @@ -129,7 +129,7 @@ static int __init davinci_vc_probe(struct platform_device *pdev) cell->pdata_size = sizeof(*davinci_vc); ret = mfd_add_devices(&pdev->dev, pdev->id, davinci_vc->cells, - DAVINCI_VC_CELLS, NULL, 0, NULL); + DAVINCI_VC_CELLS, NULL, 0); if (ret != 0) { dev_err(&pdev->dev, "fail to register client devices\n"); goto fail4; diff --git a/trunk/drivers/mfd/db8500-prcmu.c b/trunk/drivers/mfd/db8500-prcmu.c index 6b67edbdbd01..7040a0081130 100644 --- a/trunk/drivers/mfd/db8500-prcmu.c +++ b/trunk/drivers/mfd/db8500-prcmu.c @@ -418,9 +418,6 @@ static struct { static atomic_t ac_wake_req_state = ATOMIC_INIT(0); -/* Functions definition */ -static void compute_armss_rate(void); - /* Spinlocks */ static DEFINE_SPINLOCK(prcmu_lock); static DEFINE_SPINLOCK(clkout_lock); @@ -520,7 +517,6 @@ static struct dsiescclk dsiescclk[3] = { } }; - /* * Used by MCDE to setup all necessary PRCMU registers */ @@ -1017,7 +1013,6 @@ int db8500_prcmu_set_arm_opp(u8 opp) (mb1_transfer.ack.arm_opp != opp)) r = -EIO; - compute_armss_rate(); mutex_unlock(&mb1_transfer.lock); return r; @@ -1617,7 +1612,6 @@ static unsigned long pll_rate(void __iomem *reg, unsigned long src_rate, if ((branch == PLL_FIX) || ((branch == PLL_DIV) && (val & PRCM_PLL_FREQ_DIV2EN) && ((reg == PRCM_PLLSOC0_FREQ) || - (reg == PRCM_PLLARM_FREQ) || (reg == PRCM_PLLDDR_FREQ)))) div *= 2; @@ -1667,39 +1661,6 @@ static unsigned long clock_rate(u8 clock) else return 0; } -static unsigned long latest_armss_rate; -static unsigned long armss_rate(void) -{ - return latest_armss_rate; -} - -static void compute_armss_rate(void) -{ - u32 r; - unsigned long rate; - - r = readl(PRCM_ARM_CHGCLKREQ); - - if (r & PRCM_ARM_CHGCLKREQ_PRCM_ARM_CHGCLKREQ) { - /* External ARMCLKFIX clock */ - - rate = pll_rate(PRCM_PLLDDR_FREQ, ROOT_CLOCK_RATE, PLL_FIX); - - /* Check PRCM_ARM_CHGCLKREQ divider */ - if (!(r & PRCM_ARM_CHGCLKREQ_PRCM_ARM_DIVSEL)) - rate /= 2; - - /* Check PRCM_ARMCLKFIX_MGT divider */ - r = readl(PRCM_ARMCLKFIX_MGT); - r &= PRCM_CLK_MGT_CLKPLLDIV_MASK; - rate /= r; - - } else {/* ARM PLL */ - rate = pll_rate(PRCM_PLLARM_FREQ, ROOT_CLOCK_RATE, PLL_DIV); - } - - latest_armss_rate = rate; -} static unsigned long dsiclk_rate(u8 n) { @@ -1746,8 +1707,6 @@ unsigned long prcmu_clock_rate(u8 clock) return pll_rate(PRCM_PLLSOC0_FREQ, ROOT_CLOCK_RATE, PLL_RAW); else if (clock == PRCMU_PLLSOC1) return pll_rate(PRCM_PLLSOC1_FREQ, ROOT_CLOCK_RATE, PLL_RAW); - else if (clock == PRCMU_ARMSS) - return armss_rate(); else if (clock == PRCMU_PLLDDR) return pll_rate(PRCM_PLLDDR_FREQ, ROOT_CLOCK_RATE, PLL_RAW); else if (clock == PRCMU_PLLDSI) @@ -2734,7 +2693,6 @@ void __init db8500_prcmu_early_init(void) handle_simple_irq); set_irq_flags(irq, IRQF_VALID); } - compute_armss_rate(); } static void __init init_prcm_registers(void) @@ -3052,7 +3010,7 @@ static int __devinit db8500_prcmu_probe(struct platform_device *pdev) prcmu_config_esram0_deep_sleep(ESRAM0_DEEP_SLEEP_STATE_RET); err = mfd_add_devices(&pdev->dev, 0, db8500_prcmu_devs, - ARRAY_SIZE(db8500_prcmu_devs), NULL, 0, NULL); + ARRAY_SIZE(db8500_prcmu_devs), NULL, 0); if (err) { pr_err("prcmu: Failed to add subdevices\n"); return err; diff --git a/trunk/drivers/mfd/dbx500-prcmu-regs.h b/trunk/drivers/mfd/dbx500-prcmu-regs.h index 79c76ebdba52..23108a6e3167 100644 --- a/trunk/drivers/mfd/dbx500-prcmu-regs.h +++ b/trunk/drivers/mfd/dbx500-prcmu-regs.h @@ -61,8 +61,7 @@ #define PRCM_PLLARM_LOCKP_PRCM_PLLARM_LOCKP3 0x2 #define PRCM_ARM_CHGCLKREQ (_PRCMU_BASE + 0x114) -#define PRCM_ARM_CHGCLKREQ_PRCM_ARM_CHGCLKREQ BIT(0) -#define PRCM_ARM_CHGCLKREQ_PRCM_ARM_DIVSEL BIT(16) +#define PRCM_ARM_CHGCLKREQ_PRCM_ARM_CHGCLKREQ 0x1 #define PRCM_PLLARM_ENABLE (_PRCMU_BASE + 0x98) #define PRCM_PLLARM_ENABLE_PRCM_PLLARM_ENABLE 0x1 @@ -141,7 +140,6 @@ /* PRCMU clock/PLL/reset registers */ #define PRCM_PLLSOC0_FREQ (_PRCMU_BASE + 0x080) #define PRCM_PLLSOC1_FREQ (_PRCMU_BASE + 0x084) -#define PRCM_PLLARM_FREQ (_PRCMU_BASE + 0x088) #define PRCM_PLLDDR_FREQ (_PRCMU_BASE + 0x08C) #define PRCM_PLL_FREQ_D_SHIFT 0 #define PRCM_PLL_FREQ_D_MASK BITS(0, 7) diff --git a/trunk/drivers/mfd/ezx-pcap.c b/trunk/drivers/mfd/ezx-pcap.c index db662e2dcfa5..43a76c41cfcc 100644 --- a/trunk/drivers/mfd/ezx-pcap.c +++ b/trunk/drivers/mfd/ezx-pcap.c @@ -202,7 +202,7 @@ static void pcap_isr_work(struct work_struct *work) } local_irq_enable(); ezx_pcap_write(pcap, PCAP_REG_MSR, pcap->msr); - } while (gpio_get_value(pdata->gpio)); + } while (gpio_get_value(irq_to_gpio(pcap->spi->irq))); } static void pcap_irq_handler(unsigned int irq, struct irq_desc *desc) diff --git a/trunk/drivers/mfd/htc-pasic3.c b/trunk/drivers/mfd/htc-pasic3.c index 9e5453d21a68..04c7093d6499 100644 --- a/trunk/drivers/mfd/htc-pasic3.c +++ b/trunk/drivers/mfd/htc-pasic3.c @@ -168,7 +168,7 @@ static int __init pasic3_probe(struct platform_device *pdev) /* the first 5 PASIC3 registers control the DS1WM */ ds1wm_resources[0].end = (5 << asic->bus_shift) - 1; ret = mfd_add_devices(&pdev->dev, pdev->id, - &ds1wm_cell, 1, r, irq, NULL); + &ds1wm_cell, 1, r, irq); if (ret < 0) dev_warn(dev, "failed to register DS1WM\n"); } @@ -176,8 +176,7 @@ static int __init pasic3_probe(struct platform_device *pdev) if (pdata && pdata->led_pdata) { led_cell.platform_data = pdata->led_pdata; led_cell.pdata_size = sizeof(struct pasic3_leds_machinfo); - ret = mfd_add_devices(&pdev->dev, pdev->id, &led_cell, 1, r, - 0, NULL); + ret = mfd_add_devices(&pdev->dev, pdev->id, &led_cell, 1, r, 0); if (ret < 0) dev_warn(dev, "failed to register LED device\n"); } diff --git a/trunk/drivers/mfd/intel_msic.c b/trunk/drivers/mfd/intel_msic.c index 266bdc5bd96d..59df5584cb58 100644 --- a/trunk/drivers/mfd/intel_msic.c +++ b/trunk/drivers/mfd/intel_msic.c @@ -344,13 +344,13 @@ static int __devinit intel_msic_init_devices(struct intel_msic *msic) continue; ret = mfd_add_devices(&pdev->dev, -1, &msic_devs[i], 1, NULL, - pdata->irq[i], NULL); + pdata->irq[i]); if (ret) goto fail; } ret = mfd_add_devices(&pdev->dev, 0, msic_other_devs, - ARRAY_SIZE(msic_other_devs), NULL, 0, NULL); + ARRAY_SIZE(msic_other_devs), NULL, 0); if (ret) goto fail; diff --git a/trunk/drivers/mfd/janz-cmodio.c b/trunk/drivers/mfd/janz-cmodio.c index 965c4801df8a..2ea99989551a 100644 --- a/trunk/drivers/mfd/janz-cmodio.c +++ b/trunk/drivers/mfd/janz-cmodio.c @@ -147,7 +147,7 @@ static int __devinit cmodio_probe_submodules(struct cmodio_device *priv) } return mfd_add_devices(&pdev->dev, 0, priv->cells, - num_probed, NULL, pdev->irq, NULL); + num_probed, NULL, pdev->irq); } /* diff --git a/trunk/drivers/mfd/jz4740-adc.c b/trunk/drivers/mfd/jz4740-adc.c index c6b6d7dda517..87662a17dec6 100644 --- a/trunk/drivers/mfd/jz4740-adc.c +++ b/trunk/drivers/mfd/jz4740-adc.c @@ -287,8 +287,7 @@ static int __devinit jz4740_adc_probe(struct platform_device *pdev) writeb(0xff, adc->base + JZ_REG_ADC_CTRL); ret = mfd_add_devices(&pdev->dev, 0, jz4740_adc_cells, - ARRAY_SIZE(jz4740_adc_cells), mem_base, - irq_base, NULL); + ARRAY_SIZE(jz4740_adc_cells), mem_base, irq_base); if (ret < 0) goto err_clk_put; diff --git a/trunk/drivers/mfd/lm3533-core.c b/trunk/drivers/mfd/lm3533-core.c index 24212f45b201..0b2879b87fd9 100644 --- a/trunk/drivers/mfd/lm3533-core.c +++ b/trunk/drivers/mfd/lm3533-core.c @@ -393,8 +393,7 @@ static int __devinit lm3533_device_als_init(struct lm3533 *lm3533) lm3533_als_devs[0].platform_data = pdata->als; lm3533_als_devs[0].pdata_size = sizeof(*pdata->als); - ret = mfd_add_devices(lm3533->dev, 0, lm3533_als_devs, 1, NULL, - 0, NULL); + ret = mfd_add_devices(lm3533->dev, 0, lm3533_als_devs, 1, NULL, 0); if (ret) { dev_err(lm3533->dev, "failed to add ALS device\n"); return ret; @@ -423,7 +422,7 @@ static int __devinit lm3533_device_bl_init(struct lm3533 *lm3533) } ret = mfd_add_devices(lm3533->dev, 0, lm3533_bl_devs, - pdata->num_backlights, NULL, 0, NULL); + pdata->num_backlights, NULL, 0); if (ret) { dev_err(lm3533->dev, "failed to add backlight devices\n"); return ret; @@ -452,7 +451,7 @@ static int __devinit lm3533_device_led_init(struct lm3533 *lm3533) } ret = mfd_add_devices(lm3533->dev, 0, lm3533_led_devs, - pdata->num_leds, NULL, 0, NULL); + pdata->num_leds, NULL, 0); if (ret) { dev_err(lm3533->dev, "failed to add LED devices\n"); return ret; diff --git a/trunk/drivers/mfd/lpc_ich.c b/trunk/drivers/mfd/lpc_ich.c index 092ad4b44b6d..027cc8f86132 100644 --- a/trunk/drivers/mfd/lpc_ich.c +++ b/trunk/drivers/mfd/lpc_ich.c @@ -750,7 +750,7 @@ static int __devinit lpc_ich_init_gpio(struct pci_dev *dev, lpc_ich_finalize_cell(&lpc_ich_cells[LPC_GPIO], id); ret = mfd_add_devices(&dev->dev, -1, &lpc_ich_cells[LPC_GPIO], - 1, NULL, 0, NULL); + 1, NULL, 0); gpio_done: if (acpi_conflict) @@ -765,6 +765,7 @@ static int __devinit lpc_ich_init_wdt(struct pci_dev *dev, u32 base_addr_cfg; u32 base_addr; int ret; + bool acpi_conflict = false; struct resource *res; /* Setup power management base register */ @@ -779,11 +780,20 @@ static int __devinit lpc_ich_init_wdt(struct pci_dev *dev, res = wdt_io_res(ICH_RES_IO_TCO); res->start = base_addr + ACPIBASE_TCO_OFF; res->end = base_addr + ACPIBASE_TCO_END; + ret = acpi_check_resource_conflict(res); + if (ret) { + acpi_conflict = true; + goto wdt_done; + } res = wdt_io_res(ICH_RES_IO_SMI); res->start = base_addr + ACPIBASE_SMI_OFF; res->end = base_addr + ACPIBASE_SMI_END; - + ret = acpi_check_resource_conflict(res); + if (ret) { + acpi_conflict = true; + goto wdt_done; + } lpc_ich_enable_acpi_space(dev); /* @@ -803,13 +813,21 @@ static int __devinit lpc_ich_init_wdt(struct pci_dev *dev, res = wdt_mem_res(ICH_RES_MEM_GCS); res->start = base_addr + ACPIBASE_GCS_OFF; res->end = base_addr + ACPIBASE_GCS_END; + ret = acpi_check_resource_conflict(res); + if (ret) { + acpi_conflict = true; + goto wdt_done; + } } lpc_ich_finalize_cell(&lpc_ich_cells[LPC_WDT], id); ret = mfd_add_devices(&dev->dev, -1, &lpc_ich_cells[LPC_WDT], - 1, NULL, 0, NULL); + 1, NULL, 0); wdt_done: + if (acpi_conflict) + pr_warn("Resource conflict(s) found affecting %s\n", + lpc_ich_cells[LPC_WDT].name); return ret; } diff --git a/trunk/drivers/mfd/lpc_sch.c b/trunk/drivers/mfd/lpc_sch.c index f6b9c5c96b24..9f20abc5e393 100644 --- a/trunk/drivers/mfd/lpc_sch.c +++ b/trunk/drivers/mfd/lpc_sch.c @@ -127,8 +127,7 @@ static int __devinit lpc_sch_probe(struct pci_dev *dev, lpc_sch_cells[i].id = id->device; ret = mfd_add_devices(&dev->dev, 0, - lpc_sch_cells, ARRAY_SIZE(lpc_sch_cells), NULL, - 0, NULL); + lpc_sch_cells, ARRAY_SIZE(lpc_sch_cells), NULL, 0); if (ret) goto out_dev; @@ -154,8 +153,7 @@ static int __devinit lpc_sch_probe(struct pci_dev *dev, tunnelcreek_cells[i].id = id->device; ret = mfd_add_devices(&dev->dev, 0, tunnelcreek_cells, - ARRAY_SIZE(tunnelcreek_cells), NULL, - 0, NULL); + ARRAY_SIZE(tunnelcreek_cells), NULL, 0); } return ret; diff --git a/trunk/drivers/mfd/max77686.c b/trunk/drivers/mfd/max77686.c index d9e24c849a00..c03e12b51924 100644 --- a/trunk/drivers/mfd/max77686.c +++ b/trunk/drivers/mfd/max77686.c @@ -126,7 +126,7 @@ static int max77686_i2c_probe(struct i2c_client *i2c, max77686_irq_init(max77686); ret = mfd_add_devices(max77686->dev, -1, max77686_devs, - ARRAY_SIZE(max77686_devs), NULL, 0, NULL); + ARRAY_SIZE(max77686_devs), NULL, 0); if (ret < 0) goto err_mfd; diff --git a/trunk/drivers/mfd/max77693-irq.c b/trunk/drivers/mfd/max77693-irq.c index 1029d018c739..2b403569e0a6 100644 --- a/trunk/drivers/mfd/max77693-irq.c +++ b/trunk/drivers/mfd/max77693-irq.c @@ -137,9 +137,6 @@ static void max77693_irq_mask(struct irq_data *data) const struct max77693_irq_data *irq_data = irq_to_max77693_irq(max77693, data->irq); - if (irq_data->group >= MAX77693_IRQ_GROUP_NR) - return; - if (irq_data->group >= MUIC_INT1 && irq_data->group <= MUIC_INT3) max77693->irq_masks_cur[irq_data->group] &= ~irq_data->mask; else @@ -152,9 +149,6 @@ static void max77693_irq_unmask(struct irq_data *data) const struct max77693_irq_data *irq_data = irq_to_max77693_irq(max77693, data->irq); - if (irq_data->group >= MAX77693_IRQ_GROUP_NR) - return; - if (irq_data->group >= MUIC_INT1 && irq_data->group <= MUIC_INT3) max77693->irq_masks_cur[irq_data->group] |= irq_data->mask; else @@ -206,7 +200,7 @@ static irqreturn_t max77693_irq_thread(int irq, void *data) if (irq_src & MAX77693_IRQSRC_MUIC) /* MUIC INT1 ~ INT3 */ - max77693_bulk_read(max77693->regmap_muic, MAX77693_MUIC_REG_INT1, + max77693_bulk_read(max77693->regmap, MAX77693_MUIC_REG_INT1, MAX77693_NUM_IRQ_MUIC_REGS, &irq_reg[MUIC_INT1]); /* Apply masking */ @@ -261,8 +255,7 @@ int max77693_irq_init(struct max77693_dev *max77693) { struct irq_domain *domain; int i; - int ret = 0; - u8 intsrc_mask; + int ret; mutex_init(&max77693->irqlock); @@ -294,38 +287,19 @@ int max77693_irq_init(struct max77693_dev *max77693) &max77693_irq_domain_ops, max77693); if (!domain) { dev_err(max77693->dev, "could not create irq domain\n"); - ret = -ENODEV; - goto err_irq; + return -ENODEV; } max77693->irq_domain = domain; - /* Unmask max77693 interrupt */ - ret = max77693_read_reg(max77693->regmap, - MAX77693_PMIC_REG_INTSRC_MASK, &intsrc_mask); - if (ret < 0) { - dev_err(max77693->dev, "fail to read PMIC register\n"); - goto err_irq; - } - - intsrc_mask &= ~(MAX77693_IRQSRC_CHG); - intsrc_mask &= ~(MAX77693_IRQSRC_FLASH); - intsrc_mask &= ~(MAX77693_IRQSRC_MUIC); - ret = max77693_write_reg(max77693->regmap, - MAX77693_PMIC_REG_INTSRC_MASK, intsrc_mask); - if (ret < 0) { - dev_err(max77693->dev, "fail to write PMIC register\n"); - goto err_irq; - } - ret = request_threaded_irq(max77693->irq, NULL, max77693_irq_thread, IRQF_TRIGGER_FALLING | IRQF_ONESHOT, "max77693-irq", max77693); + if (ret) dev_err(max77693->dev, "Failed to request IRQ %d: %d\n", max77693->irq, ret); -err_irq: - return ret; + return 0; } void max77693_irq_exit(struct max77693_dev *max77693) diff --git a/trunk/drivers/mfd/max77693.c b/trunk/drivers/mfd/max77693.c index cc5155e20494..a1811cb50ec7 100644 --- a/trunk/drivers/mfd/max77693.c +++ b/trunk/drivers/mfd/max77693.c @@ -152,20 +152,6 @@ static int max77693_i2c_probe(struct i2c_client *i2c, max77693->haptic = i2c_new_dummy(i2c->adapter, I2C_ADDR_HAPTIC); i2c_set_clientdata(max77693->haptic, max77693); - /* - * Initialize register map for MUIC device because use regmap-muic - * instance of MUIC device when irq of max77693 is initialized - * before call max77693-muic probe() function. - */ - max77693->regmap_muic = devm_regmap_init_i2c(max77693->muic, - &max77693_regmap_config); - if (IS_ERR(max77693->regmap_muic)) { - ret = PTR_ERR(max77693->regmap_muic); - dev_err(max77693->dev, - "failed to allocate register map: %d\n", ret); - goto err_regmap; - } - ret = max77693_irq_init(max77693); if (ret < 0) goto err_irq; @@ -173,7 +159,7 @@ static int max77693_i2c_probe(struct i2c_client *i2c, pm_runtime_set_active(max77693->dev); ret = mfd_add_devices(max77693->dev, -1, max77693_devs, - ARRAY_SIZE(max77693_devs), NULL, 0, NULL); + ARRAY_SIZE(max77693_devs), NULL, 0); if (ret < 0) goto err_mfd; diff --git a/trunk/drivers/mfd/max8925-core.c b/trunk/drivers/mfd/max8925-core.c index ee53757beca7..825a7f06d9ba 100644 --- a/trunk/drivers/mfd/max8925-core.c +++ b/trunk/drivers/mfd/max8925-core.c @@ -598,7 +598,7 @@ int __devinit max8925_device_init(struct max8925_chip *chip, ret = mfd_add_devices(chip->dev, 0, &rtc_devs[0], ARRAY_SIZE(rtc_devs), - &rtc_resources[0], chip->irq_base, NULL); + &rtc_resources[0], chip->irq_base); if (ret < 0) { dev_err(chip->dev, "Failed to add rtc subdev\n"); goto out; @@ -606,7 +606,7 @@ int __devinit max8925_device_init(struct max8925_chip *chip, ret = mfd_add_devices(chip->dev, 0, &onkey_devs[0], ARRAY_SIZE(onkey_devs), - &onkey_resources[0], 0, NULL); + &onkey_resources[0], 0); if (ret < 0) { dev_err(chip->dev, "Failed to add onkey subdev\n"); goto out_dev; @@ -615,7 +615,7 @@ int __devinit max8925_device_init(struct max8925_chip *chip, if (pdata) { ret = mfd_add_devices(chip->dev, 0, ®ulator_devs[0], ARRAY_SIZE(regulator_devs), - ®ulator_resources[0], 0, NULL); + ®ulator_resources[0], 0); if (ret < 0) { dev_err(chip->dev, "Failed to add regulator subdev\n"); goto out_dev; @@ -625,7 +625,7 @@ int __devinit max8925_device_init(struct max8925_chip *chip, if (pdata && pdata->backlight) { ret = mfd_add_devices(chip->dev, 0, &backlight_devs[0], ARRAY_SIZE(backlight_devs), - &backlight_resources[0], 0, NULL); + &backlight_resources[0], 0); if (ret < 0) { dev_err(chip->dev, "Failed to add backlight subdev\n"); goto out_dev; @@ -635,7 +635,7 @@ int __devinit max8925_device_init(struct max8925_chip *chip, if (pdata && pdata->power) { ret = mfd_add_devices(chip->dev, 0, &power_devs[0], ARRAY_SIZE(power_devs), - &power_supply_resources[0], 0, NULL); + &power_supply_resources[0], 0); if (ret < 0) { dev_err(chip->dev, "Failed to add power supply " "subdev\n"); @@ -646,7 +646,7 @@ int __devinit max8925_device_init(struct max8925_chip *chip, if (pdata && pdata->touch) { ret = mfd_add_devices(chip->dev, 0, &touch_devs[0], ARRAY_SIZE(touch_devs), - &touch_resources[0], 0, NULL); + &touch_resources[0], 0); if (ret < 0) { dev_err(chip->dev, "Failed to add touch subdev\n"); goto out_dev; diff --git a/trunk/drivers/mfd/max8997.c b/trunk/drivers/mfd/max8997.c index f123517065ec..10b629c245b6 100644 --- a/trunk/drivers/mfd/max8997.c +++ b/trunk/drivers/mfd/max8997.c @@ -160,7 +160,7 @@ static int max8997_i2c_probe(struct i2c_client *i2c, mfd_add_devices(max8997->dev, -1, max8997_devs, ARRAY_SIZE(max8997_devs), - NULL, 0, NULL); + NULL, 0); /* * TODO: enable others (flash, muic, rtc, battery, ...) and diff --git a/trunk/drivers/mfd/max8998.c b/trunk/drivers/mfd/max8998.c index d7218cc90945..6ef56d28c056 100644 --- a/trunk/drivers/mfd/max8998.c +++ b/trunk/drivers/mfd/max8998.c @@ -161,13 +161,13 @@ static int max8998_i2c_probe(struct i2c_client *i2c, switch (id->driver_data) { case TYPE_LP3974: ret = mfd_add_devices(max8998->dev, -1, - lp3974_devs, ARRAY_SIZE(lp3974_devs), - NULL, 0, NULL); + lp3974_devs, ARRAY_SIZE(lp3974_devs), + NULL, 0); break; case TYPE_MAX8998: ret = mfd_add_devices(max8998->dev, -1, - max8998_devs, ARRAY_SIZE(max8998_devs), - NULL, 0, NULL); + max8998_devs, ARRAY_SIZE(max8998_devs), + NULL, 0); break; default: ret = -EINVAL; diff --git a/trunk/drivers/mfd/mc13xxx-core.c b/trunk/drivers/mfd/mc13xxx-core.c index 1ec79b54bd2f..b801dc72f041 100644 --- a/trunk/drivers/mfd/mc13xxx-core.c +++ b/trunk/drivers/mfd/mc13xxx-core.c @@ -612,7 +612,7 @@ static int mc13xxx_add_subdevice_pdata(struct mc13xxx *mc13xxx, if (!cell.name) return -ENOMEM; - return mfd_add_devices(mc13xxx->dev, -1, &cell, 1, NULL, 0, NULL); + return mfd_add_devices(mc13xxx->dev, -1, &cell, 1, NULL, 0); } static int mc13xxx_add_subdevice(struct mc13xxx *mc13xxx, const char *format) diff --git a/trunk/drivers/mfd/mfd-core.c b/trunk/drivers/mfd/mfd-core.c index f8b77711ad2d..0c3a01cde2f7 100644 --- a/trunk/drivers/mfd/mfd-core.c +++ b/trunk/drivers/mfd/mfd-core.c @@ -74,11 +74,12 @@ static int mfd_platform_add_cell(struct platform_device *pdev, static int mfd_add_device(struct device *parent, int id, const struct mfd_cell *cell, struct resource *mem_base, - int irq_base, struct irq_domain *domain) + int irq_base) { struct resource *res; struct platform_device *pdev; struct device_node *np = NULL; + struct irq_domain *domain = NULL; int ret = -ENOMEM; int r; @@ -96,6 +97,7 @@ static int mfd_add_device(struct device *parent, int id, for_each_child_of_node(parent->of_node, np) { if (of_device_is_compatible(np, cell->of_compatible)) { pdev->dev.of_node = np; + domain = irq_find_host(parent->of_node); break; } } @@ -175,7 +177,7 @@ static int mfd_add_device(struct device *parent, int id, int mfd_add_devices(struct device *parent, int id, struct mfd_cell *cells, int n_devs, struct resource *mem_base, - int irq_base, struct irq_domain *domain) + int irq_base) { int i; int ret = 0; @@ -189,8 +191,7 @@ int mfd_add_devices(struct device *parent, int id, for (i = 0; i < n_devs; i++) { atomic_set(&cnts[i], 0); cells[i].usage_count = &cnts[i]; - ret = mfd_add_device(parent, id, cells + i, mem_base, - irq_base, domain); + ret = mfd_add_device(parent, id, cells + i, mem_base, irq_base); if (ret) break; } @@ -246,8 +247,7 @@ int mfd_clone_cell(const char *cell, const char **clones, size_t n_clones) for (i = 0; i < n_clones; i++) { cell_entry.name = clones[i]; /* don't give up if a single call fails; just report error */ - if (mfd_add_device(pdev->dev.parent, -1, &cell_entry, NULL, 0, - NULL)) + if (mfd_add_device(pdev->dev.parent, -1, &cell_entry, NULL, 0)) dev_err(dev, "failed to create platform device '%s'\n", clones[i]); } diff --git a/trunk/drivers/mfd/palmas.c b/trunk/drivers/mfd/palmas.c index a345f9bb7b47..c4a69f193a1d 100644 --- a/trunk/drivers/mfd/palmas.c +++ b/trunk/drivers/mfd/palmas.c @@ -453,8 +453,7 @@ static int __devinit palmas_i2c_probe(struct i2c_client *i2c, ret = mfd_add_devices(palmas->dev, -1, children, ARRAY_SIZE(palmas_children), - NULL, regmap_irq_chip_get_base(palmas->irq_data), - NULL); + NULL, regmap_irq_chip_get_base(palmas->irq_data)); kfree(children); if (ret < 0) diff --git a/trunk/drivers/mfd/rc5t583.c b/trunk/drivers/mfd/rc5t583.c index ff61efc76ce2..cdc1df7fa0e9 100644 --- a/trunk/drivers/mfd/rc5t583.c +++ b/trunk/drivers/mfd/rc5t583.c @@ -281,7 +281,7 @@ static int __devinit rc5t583_i2c_probe(struct i2c_client *i2c, if (i2c->irq) { ret = rc5t583_irq_init(rc5t583, i2c->irq, pdata->irq_base); - /* Still continue with warning, if irq init fails */ + /* Still continue with waring if irq init fails */ if (ret) dev_warn(&i2c->dev, "IRQ init failed: %d\n", ret); else @@ -289,7 +289,7 @@ static int __devinit rc5t583_i2c_probe(struct i2c_client *i2c, } ret = mfd_add_devices(rc5t583->dev, -1, rc5t583_subdevs, - ARRAY_SIZE(rc5t583_subdevs), NULL, 0, NULL); + ARRAY_SIZE(rc5t583_subdevs), NULL, 0); if (ret) { dev_err(&i2c->dev, "add mfd devices failed: %d\n", ret); goto err_add_devs; diff --git a/trunk/drivers/mfd/rdc321x-southbridge.c b/trunk/drivers/mfd/rdc321x-southbridge.c index fbabc3cbe350..685d61e431ad 100644 --- a/trunk/drivers/mfd/rdc321x-southbridge.c +++ b/trunk/drivers/mfd/rdc321x-southbridge.c @@ -1,5 +1,5 @@ /* - * RDC321x MFD southbridge driver + * RDC321x MFD southbrige driver * * Copyright (C) 2007-2010 Florian Fainelli * Copyright (C) 2010 Bernhard Loos @@ -87,8 +87,7 @@ static int __devinit rdc321x_sb_probe(struct pci_dev *pdev, rdc321x_wdt_pdata.sb_pdev = pdev; return mfd_add_devices(&pdev->dev, -1, - rdc321x_sb_cells, ARRAY_SIZE(rdc321x_sb_cells), - NULL, 0, NULL); + rdc321x_sb_cells, ARRAY_SIZE(rdc321x_sb_cells), NULL, 0); } static void __devexit rdc321x_sb_remove(struct pci_dev *pdev) diff --git a/trunk/drivers/mfd/sec-core.c b/trunk/drivers/mfd/sec-core.c index 49d361a618d0..2988efde11eb 100644 --- a/trunk/drivers/mfd/sec-core.c +++ b/trunk/drivers/mfd/sec-core.c @@ -141,19 +141,19 @@ static int sec_pmic_probe(struct i2c_client *i2c, switch (sec_pmic->device_type) { case S5M8751X: ret = mfd_add_devices(sec_pmic->dev, -1, s5m8751_devs, - ARRAY_SIZE(s5m8751_devs), NULL, 0, NULL); + ARRAY_SIZE(s5m8751_devs), NULL, 0); break; case S5M8763X: ret = mfd_add_devices(sec_pmic->dev, -1, s5m8763_devs, - ARRAY_SIZE(s5m8763_devs), NULL, 0, NULL); + ARRAY_SIZE(s5m8763_devs), NULL, 0); break; case S5M8767X: ret = mfd_add_devices(sec_pmic->dev, -1, s5m8767_devs, - ARRAY_SIZE(s5m8767_devs), NULL, 0, NULL); + ARRAY_SIZE(s5m8767_devs), NULL, 0); break; case S2MPS11X: ret = mfd_add_devices(sec_pmic->dev, -1, s2mps11_devs, - ARRAY_SIZE(s2mps11_devs), NULL, 0, NULL); + ARRAY_SIZE(s2mps11_devs), NULL, 0); break; default: /* If this happens the probe function is problem */ diff --git a/trunk/drivers/mfd/sta2x11-mfd.c b/trunk/drivers/mfd/sta2x11-mfd.c index d35da6820bea..d31fed07aefb 100644 --- a/trunk/drivers/mfd/sta2x11-mfd.c +++ b/trunk/drivers/mfd/sta2x11-mfd.c @@ -407,7 +407,7 @@ static int __devinit sta2x11_mfd_probe(struct pci_dev *pdev, sta2x11_mfd_bar0, ARRAY_SIZE(sta2x11_mfd_bar0), &pdev->resource[0], - 0, NULL); + 0); if (err) { dev_err(&pdev->dev, "mfd_add_devices[0] failed: %d\n", err); goto err_disable; @@ -417,7 +417,7 @@ static int __devinit sta2x11_mfd_probe(struct pci_dev *pdev, sta2x11_mfd_bar1, ARRAY_SIZE(sta2x11_mfd_bar1), &pdev->resource[1], - 0, NULL); + 0); if (err) { dev_err(&pdev->dev, "mfd_add_devices[1] failed: %d\n", err); goto err_disable; diff --git a/trunk/drivers/mfd/stmpe.c b/trunk/drivers/mfd/stmpe.c index c94f521f392c..2dd8d49cb30b 100644 --- a/trunk/drivers/mfd/stmpe.c +++ b/trunk/drivers/mfd/stmpe.c @@ -962,7 +962,7 @@ static int __devinit stmpe_add_device(struct stmpe *stmpe, struct mfd_cell *cell, int irq) { return mfd_add_devices(stmpe->dev, stmpe->pdata->id, cell, 1, - NULL, stmpe->irq_base + irq, NULL); + NULL, stmpe->irq_base + irq); } static int __devinit stmpe_devices_init(struct stmpe *stmpe) diff --git a/trunk/drivers/mfd/t7l66xb.c b/trunk/drivers/mfd/t7l66xb.c index b32940ec9034..2d9e8799e733 100644 --- a/trunk/drivers/mfd/t7l66xb.c +++ b/trunk/drivers/mfd/t7l66xb.c @@ -388,7 +388,7 @@ static int t7l66xb_probe(struct platform_device *dev) ret = mfd_add_devices(&dev->dev, dev->id, t7l66xb_cells, ARRAY_SIZE(t7l66xb_cells), - iomem, t7l66xb->irq_base, NULL); + iomem, t7l66xb->irq_base); if (!ret) return 0; diff --git a/trunk/drivers/mfd/tc3589x.c b/trunk/drivers/mfd/tc3589x.c index b56ba6b43294..048bf0532a09 100644 --- a/trunk/drivers/mfd/tc3589x.c +++ b/trunk/drivers/mfd/tc3589x.c @@ -262,8 +262,8 @@ static int __devinit tc3589x_device_init(struct tc3589x *tc3589x) if (blocks & TC3589x_BLOCK_GPIO) { ret = mfd_add_devices(tc3589x->dev, -1, tc3589x_dev_gpio, - ARRAY_SIZE(tc3589x_dev_gpio), NULL, - tc3589x->irq_base, NULL); + ARRAY_SIZE(tc3589x_dev_gpio), NULL, + tc3589x->irq_base); if (ret) { dev_err(tc3589x->dev, "failed to add gpio child\n"); return ret; @@ -273,8 +273,8 @@ static int __devinit tc3589x_device_init(struct tc3589x *tc3589x) if (blocks & TC3589x_BLOCK_KEYPAD) { ret = mfd_add_devices(tc3589x->dev, -1, tc3589x_dev_keypad, - ARRAY_SIZE(tc3589x_dev_keypad), NULL, - tc3589x->irq_base, NULL); + ARRAY_SIZE(tc3589x_dev_keypad), NULL, + tc3589x->irq_base); if (ret) { dev_err(tc3589x->dev, "failed to keypad child\n"); return ret; diff --git a/trunk/drivers/mfd/tc6387xb.c b/trunk/drivers/mfd/tc6387xb.c index 413c891102f8..d20a284ad4ba 100644 --- a/trunk/drivers/mfd/tc6387xb.c +++ b/trunk/drivers/mfd/tc6387xb.c @@ -192,7 +192,7 @@ static int __devinit tc6387xb_probe(struct platform_device *dev) printk(KERN_INFO "Toshiba tc6387xb initialised\n"); ret = mfd_add_devices(&dev->dev, dev->id, tc6387xb_cells, - ARRAY_SIZE(tc6387xb_cells), iomem, irq, NULL); + ARRAY_SIZE(tc6387xb_cells), iomem, irq); if (!ret) return 0; diff --git a/trunk/drivers/mfd/tc6393xb.c b/trunk/drivers/mfd/tc6393xb.c index dcab026fcbb2..9612264f0e6d 100644 --- a/trunk/drivers/mfd/tc6393xb.c +++ b/trunk/drivers/mfd/tc6393xb.c @@ -700,8 +700,8 @@ static int __devinit tc6393xb_probe(struct platform_device *dev) tc6393xb_cells[TC6393XB_CELL_FB].pdata_size = sizeof(*tcpd->fb_data); ret = mfd_add_devices(&dev->dev, dev->id, - tc6393xb_cells, ARRAY_SIZE(tc6393xb_cells), - iomem, tcpd->irq_base, NULL); + tc6393xb_cells, ARRAY_SIZE(tc6393xb_cells), + iomem, tcpd->irq_base); if (!ret) return 0; diff --git a/trunk/drivers/mfd/ti-ssp.c b/trunk/drivers/mfd/ti-ssp.c index 7c3675a74f93..4fb0e6c8e8fe 100644 --- a/trunk/drivers/mfd/ti-ssp.c +++ b/trunk/drivers/mfd/ti-ssp.c @@ -412,7 +412,7 @@ static int __devinit ti_ssp_probe(struct platform_device *pdev) cells[id].data_size = data->pdata_size; } - error = mfd_add_devices(dev, 0, cells, 2, NULL, 0, NULL); + error = mfd_add_devices(dev, 0, cells, 2, NULL, 0); if (error < 0) { dev_err(dev, "cannot add mfd cells\n"); goto error_enable; diff --git a/trunk/drivers/mfd/timberdale.c b/trunk/drivers/mfd/timberdale.c index cccc626c83c8..a447f4ec11fb 100644 --- a/trunk/drivers/mfd/timberdale.c +++ b/trunk/drivers/mfd/timberdale.c @@ -757,25 +757,25 @@ static int __devinit timb_probe(struct pci_dev *dev, err = mfd_add_devices(&dev->dev, -1, timberdale_cells_bar0_cfg0, ARRAY_SIZE(timberdale_cells_bar0_cfg0), - &dev->resource[0], msix_entries[0].vector, NULL); + &dev->resource[0], msix_entries[0].vector); break; case TIMB_HW_VER1: err = mfd_add_devices(&dev->dev, -1, timberdale_cells_bar0_cfg1, ARRAY_SIZE(timberdale_cells_bar0_cfg1), - &dev->resource[0], msix_entries[0].vector, NULL); + &dev->resource[0], msix_entries[0].vector); break; case TIMB_HW_VER2: err = mfd_add_devices(&dev->dev, -1, timberdale_cells_bar0_cfg2, ARRAY_SIZE(timberdale_cells_bar0_cfg2), - &dev->resource[0], msix_entries[0].vector, NULL); + &dev->resource[0], msix_entries[0].vector); break; case TIMB_HW_VER3: err = mfd_add_devices(&dev->dev, -1, timberdale_cells_bar0_cfg3, ARRAY_SIZE(timberdale_cells_bar0_cfg3), - &dev->resource[0], msix_entries[0].vector, NULL); + &dev->resource[0], msix_entries[0].vector); break; default: dev_err(&dev->dev, "Uknown IP setup: %d.%d.%d\n", @@ -792,7 +792,7 @@ static int __devinit timb_probe(struct pci_dev *dev, err = mfd_add_devices(&dev->dev, 0, timberdale_cells_bar1, ARRAY_SIZE(timberdale_cells_bar1), - &dev->resource[1], msix_entries[0].vector, NULL); + &dev->resource[1], msix_entries[0].vector); if (err) { dev_err(&dev->dev, "mfd_add_devices failed: %d\n", err); goto err_mfd2; @@ -803,7 +803,7 @@ static int __devinit timb_probe(struct pci_dev *dev, ((priv->fw.config & TIMB_HW_VER_MASK) == TIMB_HW_VER3)) { err = mfd_add_devices(&dev->dev, 1, timberdale_cells_bar2, ARRAY_SIZE(timberdale_cells_bar2), - &dev->resource[2], msix_entries[0].vector, NULL); + &dev->resource[2], msix_entries[0].vector); if (err) { dev_err(&dev->dev, "mfd_add_devices failed: %d\n", err); goto err_mfd2; diff --git a/trunk/drivers/mfd/tps6105x.c b/trunk/drivers/mfd/tps6105x.c index 14051bdc714b..a293b978e27c 100644 --- a/trunk/drivers/mfd/tps6105x.c +++ b/trunk/drivers/mfd/tps6105x.c @@ -188,7 +188,7 @@ static int __devinit tps6105x_probe(struct i2c_client *client, } ret = mfd_add_devices(&client->dev, 0, tps6105x_cells, - ARRAY_SIZE(tps6105x_cells), NULL, 0, NULL); + ARRAY_SIZE(tps6105x_cells), NULL, 0); if (ret) goto fail; diff --git a/trunk/drivers/mfd/tps6507x.c b/trunk/drivers/mfd/tps6507x.c index 1b203499c744..33ba7723c967 100644 --- a/trunk/drivers/mfd/tps6507x.c +++ b/trunk/drivers/mfd/tps6507x.c @@ -100,7 +100,7 @@ static int tps6507x_i2c_probe(struct i2c_client *i2c, ret = mfd_add_devices(tps6507x->dev, -1, tps6507x_devs, ARRAY_SIZE(tps6507x_devs), - NULL, 0, NULL); + NULL, 0); if (ret < 0) goto err; diff --git a/trunk/drivers/mfd/tps65090.c b/trunk/drivers/mfd/tps65090.c index 50fd87c87a1c..80e24f4b47bf 100644 --- a/trunk/drivers/mfd/tps65090.c +++ b/trunk/drivers/mfd/tps65090.c @@ -292,7 +292,7 @@ static int __devinit tps65090_i2c_probe(struct i2c_client *client, } ret = mfd_add_devices(tps65090->dev, -1, tps65090s, - ARRAY_SIZE(tps65090s), NULL, 0, NULL); + ARRAY_SIZE(tps65090s), NULL, 0); if (ret) { dev_err(&client->dev, "add mfd devices failed with err: %d\n", ret); diff --git a/trunk/drivers/mfd/tps65217.c b/trunk/drivers/mfd/tps65217.c index a95e9421b735..61c097a98f5d 100644 --- a/trunk/drivers/mfd/tps65217.c +++ b/trunk/drivers/mfd/tps65217.c @@ -24,18 +24,11 @@ #include #include #include -#include -#include +#include #include #include -static struct mfd_cell tps65217s[] = { - { - .name = "tps65217-pmic", - }, -}; - /** * tps65217_reg_read: Read a single tps65217 register. * @@ -140,48 +133,83 @@ int tps65217_clear_bits(struct tps65217 *tps, unsigned int reg, } EXPORT_SYMBOL_GPL(tps65217_clear_bits); +#ifdef CONFIG_OF +static struct of_regulator_match reg_matches[] = { + { .name = "dcdc1", .driver_data = (void *)TPS65217_DCDC_1 }, + { .name = "dcdc2", .driver_data = (void *)TPS65217_DCDC_2 }, + { .name = "dcdc3", .driver_data = (void *)TPS65217_DCDC_3 }, + { .name = "ldo1", .driver_data = (void *)TPS65217_LDO_1 }, + { .name = "ldo2", .driver_data = (void *)TPS65217_LDO_2 }, + { .name = "ldo3", .driver_data = (void *)TPS65217_LDO_3 }, + { .name = "ldo4", .driver_data = (void *)TPS65217_LDO_4 }, +}; + +static struct tps65217_board *tps65217_parse_dt(struct i2c_client *client) +{ + struct device_node *node = client->dev.of_node; + struct tps65217_board *pdata; + struct device_node *regs; + int count = ARRAY_SIZE(reg_matches); + int ret, i; + + regs = of_find_node_by_name(node, "regulators"); + if (!regs) + return NULL; + + ret = of_regulator_match(&client->dev, regs, reg_matches, count); + of_node_put(regs); + if ((ret < 0) || (ret > count)) + return NULL; + + count = ret; + pdata = devm_kzalloc(&client->dev, count * sizeof(*pdata), GFP_KERNEL); + if (!pdata) + return NULL; + + for (i = 0; i < count; i++) { + if (!reg_matches[i].init_data || !reg_matches[i].of_node) + continue; + + pdata->tps65217_init_data[i] = reg_matches[i].init_data; + pdata->of_node[i] = reg_matches[i].of_node; + } + + return pdata; +} + +static struct of_device_id tps65217_of_match[] = { + { .compatible = "ti,tps65217", }, + { }, +}; +#else +static struct tps65217_board *tps65217_parse_dt(struct i2c_client *client) +{ + return NULL; +} +#endif + static struct regmap_config tps65217_regmap_config = { .reg_bits = 8, .val_bits = 8, }; -static const struct of_device_id tps65217_of_match[] = { - { .compatible = "ti,tps65217", .data = (void *)TPS65217 }, - { /* sentinel */ }, -}; - static int __devinit tps65217_probe(struct i2c_client *client, const struct i2c_device_id *ids) { struct tps65217 *tps; + struct regulator_init_data *reg_data; + struct tps65217_board *pdata = client->dev.platform_data; + int i, ret; unsigned int version; - unsigned int chip_id = ids->driver_data; - const struct of_device_id *match; - int ret; - if (client->dev.of_node) { - match = of_match_device(tps65217_of_match, &client->dev); - if (!match) { - dev_err(&client->dev, - "Failed to find matching dt id\n"); - return -EINVAL; - } - chip_id = (unsigned int)match->data; - } - - if (!chip_id) { - dev_err(&client->dev, "id is null.\n"); - return -ENODEV; - } + if (!pdata && client->dev.of_node) + pdata = tps65217_parse_dt(client); tps = devm_kzalloc(&client->dev, sizeof(*tps), GFP_KERNEL); if (!tps) return -ENOMEM; - i2c_set_clientdata(client, tps); - tps->dev = &client->dev; - tps->id = chip_id; - + tps->pdata = pdata; tps->regmap = devm_regmap_init_i2c(client, &tps65217_regmap_config); if (IS_ERR(tps->regmap)) { ret = PTR_ERR(tps->regmap); @@ -190,12 +218,8 @@ static int __devinit tps65217_probe(struct i2c_client *client, return ret; } - ret = mfd_add_devices(tps->dev, -1, tps65217s, - ARRAY_SIZE(tps65217s), NULL, 0, NULL); - if (ret < 0) { - dev_err(tps->dev, "mfd_add_devices failed: %d\n", ret); - return ret; - } + i2c_set_clientdata(client, tps); + tps->dev = &client->dev; ret = tps65217_reg_read(tps, TPS65217_REG_CHIPID, &version); if (ret < 0) { @@ -208,21 +232,41 @@ static int __devinit tps65217_probe(struct i2c_client *client, (version & TPS65217_CHIPID_CHIP_MASK) >> 4, version & TPS65217_CHIPID_REV_MASK); + for (i = 0; i < TPS65217_NUM_REGULATOR; i++) { + struct platform_device *pdev; + + pdev = platform_device_alloc("tps65217-pmic", i); + if (!pdev) { + dev_err(tps->dev, "Cannot create regulator %d\n", i); + continue; + } + + pdev->dev.parent = tps->dev; + pdev->dev.of_node = pdata->of_node[i]; + reg_data = pdata->tps65217_init_data[i]; + platform_device_add_data(pdev, reg_data, sizeof(*reg_data)); + tps->regulator_pdev[i] = pdev; + + platform_device_add(pdev); + } + return 0; } static int __devexit tps65217_remove(struct i2c_client *client) { struct tps65217 *tps = i2c_get_clientdata(client); + int i; - mfd_remove_devices(tps->dev); + for (i = 0; i < TPS65217_NUM_REGULATOR; i++) + platform_device_unregister(tps->regulator_pdev[i]); return 0; } static const struct i2c_device_id tps65217_id_table[] = { - {"tps65217", TPS65217}, - { /* sentinel */ } + {"tps65217", 0xF0}, + {/* end of list */} }; MODULE_DEVICE_TABLE(i2c, tps65217_id_table); diff --git a/trunk/drivers/mfd/tps6586x.c b/trunk/drivers/mfd/tps6586x.c index 345960ca2fd8..353c34812120 100644 --- a/trunk/drivers/mfd/tps6586x.c +++ b/trunk/drivers/mfd/tps6586x.c @@ -25,7 +25,6 @@ #include #include #include -#include #include #include @@ -347,7 +346,6 @@ static int __devinit tps6586x_add_subdevs(struct tps6586x *tps6586x, #ifdef CONFIG_OF static struct of_regulator_match tps6586x_matches[] = { - { .name = "sys", .driver_data = (void *)TPS6586X_ID_SYS }, { .name = "sm0", .driver_data = (void *)TPS6586X_ID_SM_0 }, { .name = "sm1", .driver_data = (void *)TPS6586X_ID_SM_1 }, { .name = "sm2", .driver_data = (void *)TPS6586X_ID_SM_2 }, @@ -371,7 +369,6 @@ static struct tps6586x_platform_data *tps6586x_parse_dt(struct i2c_client *clien struct tps6586x_platform_data *pdata; struct tps6586x_subdev_info *devs; struct device_node *regs; - const char *sys_rail_name = NULL; unsigned int count; unsigned int i, j; int err; @@ -394,22 +391,12 @@ static struct tps6586x_platform_data *tps6586x_parse_dt(struct i2c_client *clien return NULL; for (i = 0, j = 0; i < num && j < count; i++) { - struct regulator_init_data *reg_idata; - if (!tps6586x_matches[i].init_data) continue; - reg_idata = tps6586x_matches[i].init_data; devs[j].name = "tps6586x-regulator"; devs[j].platform_data = tps6586x_matches[i].init_data; devs[j].id = (int)tps6586x_matches[i].driver_data; - if (devs[j].id == TPS6586X_ID_SYS) - sys_rail_name = reg_idata->constraints.name; - - if ((devs[j].id == TPS6586X_ID_LDO_5) || - (devs[j].id == TPS6586X_ID_LDO_RTC)) - reg_idata->supply_regulator = sys_rail_name; - devs[j].of_node = tps6586x_matches[i].of_node; j++; } @@ -506,8 +493,7 @@ static int __devinit tps6586x_i2c_probe(struct i2c_client *client, } ret = mfd_add_devices(tps6586x->dev, -1, - tps6586x_cell, ARRAY_SIZE(tps6586x_cell), - NULL, 0, NULL); + tps6586x_cell, ARRAY_SIZE(tps6586x_cell), NULL, 0); if (ret < 0) { dev_err(&client->dev, "mfd_add_devices failed: %d\n", ret); goto err_mfd_add; diff --git a/trunk/drivers/mfd/tps65910.c b/trunk/drivers/mfd/tps65910.c index d3ce4d569deb..1c563792c777 100644 --- a/trunk/drivers/mfd/tps65910.c +++ b/trunk/drivers/mfd/tps65910.c @@ -254,7 +254,7 @@ static __devinit int tps65910_i2c_probe(struct i2c_client *i2c, ret = mfd_add_devices(tps65910->dev, -1, tps65910s, ARRAY_SIZE(tps65910s), - NULL, 0, NULL); + NULL, 0); if (ret < 0) { dev_err(&i2c->dev, "mfd_add_devices failed: %d\n", ret); return ret; diff --git a/trunk/drivers/mfd/tps65911-comparator.c b/trunk/drivers/mfd/tps65911-comparator.c index 0b6e361432c4..5a62e6bf89ae 100644 --- a/trunk/drivers/mfd/tps65911-comparator.c +++ b/trunk/drivers/mfd/tps65911-comparator.c @@ -136,7 +136,7 @@ static __devinit int tps65911_comparator_probe(struct platform_device *pdev) ret = comp_threshold_set(tps65910, COMP2, pdata->vmbch2_threshold); if (ret < 0) { - dev_err(&pdev->dev, "cannot set COMP2 threshold\n"); + dev_err(&pdev->dev, "cannot set COMP2 theshold\n"); return ret; } diff --git a/trunk/drivers/mfd/tps65912-core.c b/trunk/drivers/mfd/tps65912-core.c index 4658b5bdcd84..74fd8cb5f372 100644 --- a/trunk/drivers/mfd/tps65912-core.c +++ b/trunk/drivers/mfd/tps65912-core.c @@ -146,7 +146,7 @@ int tps65912_device_init(struct tps65912 *tps65912) ret = mfd_add_devices(tps65912->dev, -1, tps65912s, ARRAY_SIZE(tps65912s), - NULL, 0, NULL); + NULL, 0); if (ret < 0) goto err; diff --git a/trunk/drivers/mfd/twl4030-audio.c b/trunk/drivers/mfd/twl4030-audio.c index 77c9acb14583..838ce4eb444e 100644 --- a/trunk/drivers/mfd/twl4030-audio.c +++ b/trunk/drivers/mfd/twl4030-audio.c @@ -223,7 +223,7 @@ static int __devinit twl4030_audio_probe(struct platform_device *pdev) if (childs) ret = mfd_add_devices(&pdev->dev, pdev->id, audio->cells, - childs, NULL, 0, NULL); + childs, NULL, 0); else { dev_err(&pdev->dev, "No platform data found for childs\n"); ret = -ENODEV; diff --git a/trunk/drivers/mfd/twl6040-core.c b/trunk/drivers/mfd/twl6040-core.c index 3dca5c195a20..b0fad0ffca56 100644 --- a/trunk/drivers/mfd/twl6040-core.c +++ b/trunk/drivers/mfd/twl6040-core.c @@ -632,7 +632,7 @@ static int __devinit twl6040_probe(struct i2c_client *client, } ret = mfd_add_devices(&client->dev, -1, twl6040->cells, children, - NULL, 0, NULL); + NULL, 0); if (ret) goto mfd_err; diff --git a/trunk/drivers/mfd/vx855.c b/trunk/drivers/mfd/vx855.c index b9a636d44c7f..872aff21e4be 100644 --- a/trunk/drivers/mfd/vx855.c +++ b/trunk/drivers/mfd/vx855.c @@ -102,7 +102,7 @@ static __devinit int vx855_probe(struct pci_dev *pdev, vx855_gpio_resources[1].end = vx855_gpio_resources[1].start + 3; ret = mfd_add_devices(&pdev->dev, -1, vx855_cells, ARRAY_SIZE(vx855_cells), - NULL, 0, NULL); + NULL, 0); /* we always return -ENODEV here in order to enable other * drivers like old, not-yet-platform_device ported i2c-viapro */ diff --git a/trunk/drivers/mfd/wl1273-core.c b/trunk/drivers/mfd/wl1273-core.c index 86e0e4309fc2..f39b756df561 100644 --- a/trunk/drivers/mfd/wl1273-core.c +++ b/trunk/drivers/mfd/wl1273-core.c @@ -241,7 +241,7 @@ static int __devinit wl1273_core_probe(struct i2c_client *client, __func__, children); r = mfd_add_devices(&client->dev, -1, core->cells, - children, NULL, 0, NULL); + children, NULL, 0); if (r) goto err; diff --git a/trunk/drivers/mfd/wm831x-core.c b/trunk/drivers/mfd/wm831x-core.c index 301731035940..946698fd2dc6 100644 --- a/trunk/drivers/mfd/wm831x-core.c +++ b/trunk/drivers/mfd/wm831x-core.c @@ -1813,27 +1813,27 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq) case WM8310: ret = mfd_add_devices(wm831x->dev, wm831x_num, wm8310_devs, ARRAY_SIZE(wm8310_devs), - NULL, 0, NULL); + NULL, 0); break; case WM8311: ret = mfd_add_devices(wm831x->dev, wm831x_num, wm8311_devs, ARRAY_SIZE(wm8311_devs), - NULL, 0, NULL); + NULL, 0); if (!pdata || !pdata->disable_touch) mfd_add_devices(wm831x->dev, wm831x_num, touch_devs, ARRAY_SIZE(touch_devs), - NULL, 0, NULL); + NULL, 0); break; case WM8312: ret = mfd_add_devices(wm831x->dev, wm831x_num, wm8312_devs, ARRAY_SIZE(wm8312_devs), - NULL, 0, NULL); + NULL, 0); if (!pdata || !pdata->disable_touch) mfd_add_devices(wm831x->dev, wm831x_num, touch_devs, ARRAY_SIZE(touch_devs), - NULL, 0, NULL); + NULL, 0); break; case WM8320: @@ -1842,7 +1842,7 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq) case WM8326: ret = mfd_add_devices(wm831x->dev, wm831x_num, wm8320_devs, ARRAY_SIZE(wm8320_devs), - NULL, 0, NULL); + NULL, 0); break; default: @@ -1867,7 +1867,7 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq) if (ret & WM831X_XTAL_ENA) { ret = mfd_add_devices(wm831x->dev, wm831x_num, rtc_devs, ARRAY_SIZE(rtc_devs), - NULL, 0, NULL); + NULL, 0); if (ret != 0) { dev_err(wm831x->dev, "Failed to add RTC: %d\n", ret); goto err_irq; @@ -1880,7 +1880,7 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq) /* Treat errors as non-critical */ ret = mfd_add_devices(wm831x->dev, wm831x_num, backlight_devs, ARRAY_SIZE(backlight_devs), NULL, - 0, NULL); + 0); if (ret < 0) dev_err(wm831x->dev, "Failed to add backlight: %d\n", ret); diff --git a/trunk/drivers/mfd/wm8400-core.c b/trunk/drivers/mfd/wm8400-core.c index 639ca359242f..4b7d378551d5 100644 --- a/trunk/drivers/mfd/wm8400-core.c +++ b/trunk/drivers/mfd/wm8400-core.c @@ -70,7 +70,7 @@ static int wm8400_register_codec(struct wm8400 *wm8400) .pdata_size = sizeof(*wm8400), }; - return mfd_add_devices(wm8400->dev, -1, &cell, 1, NULL, 0, NULL); + return mfd_add_devices(wm8400->dev, -1, &cell, 1, NULL, 0); } /* diff --git a/trunk/drivers/mfd/wm8994-core.c b/trunk/drivers/mfd/wm8994-core.c index 2febf88cfce8..eec74aa55fdf 100644 --- a/trunk/drivers/mfd/wm8994-core.c +++ b/trunk/drivers/mfd/wm8994-core.c @@ -414,7 +414,7 @@ static __devinit int wm8994_device_init(struct wm8994 *wm8994, int irq) ret = mfd_add_devices(wm8994->dev, -1, wm8994_regulator_devs, ARRAY_SIZE(wm8994_regulator_devs), - NULL, 0, NULL); + NULL, 0); if (ret != 0) { dev_err(wm8994->dev, "Failed to add children: %d\n", ret); goto err; @@ -648,7 +648,7 @@ static __devinit int wm8994_device_init(struct wm8994 *wm8994, int irq) ret = mfd_add_devices(wm8994->dev, -1, wm8994_devs, ARRAY_SIZE(wm8994_devs), - NULL, 0, NULL); + NULL, 0); if (ret != 0) { dev_err(wm8994->dev, "Failed to add children: %d\n", ret); goto err_irq; diff --git a/trunk/drivers/mfd/wm8994-irq.c b/trunk/drivers/mfd/wm8994-irq.c index a050e56a9bbd..0aac4aff17a5 100644 --- a/trunk/drivers/mfd/wm8994-irq.c +++ b/trunk/drivers/mfd/wm8994-irq.c @@ -135,7 +135,6 @@ static struct regmap_irq_chip wm8994_irq_chip = { .status_base = WM8994_INTERRUPT_STATUS_1, .mask_base = WM8994_INTERRUPT_STATUS_1_MASK, .ack_base = WM8994_INTERRUPT_STATUS_1, - .runtime_pm = true, }; int wm8994_irq_init(struct wm8994 *wm8994) diff --git a/trunk/drivers/misc/Kconfig b/trunk/drivers/misc/Kconfig index 99c73352c430..98a442da892a 100644 --- a/trunk/drivers/misc/Kconfig +++ b/trunk/drivers/misc/Kconfig @@ -105,7 +105,7 @@ config ATMEL_TCB_CLKSRC_BLOCK config IBM_ASM tristate "Device driver for IBM RSA service processor" - depends on X86 && PCI && INPUT + depends on X86 && PCI && INPUT && EXPERIMENTAL ---help--- This option enables device driver support for in-band access to the IBM RSA (Condor) service processor in eServer xSeries systems. @@ -162,8 +162,8 @@ config SGI_IOC4 Otherwise say N. config TIFM_CORE - tristate "TI Flash Media interface support" - depends on PCI + tristate "TI Flash Media interface support (EXPERIMENTAL)" + depends on EXPERIMENTAL && PCI help If you want support for Texas Instruments(R) Flash Media adapters you should select this option and then also choose an appropriate @@ -178,8 +178,8 @@ config TIFM_CORE be called tifm_core. config TIFM_7XX1 - tristate "TI Flash Media PCI74xx/PCI76xx host adapter support" - depends on PCI && TIFM_CORE + tristate "TI Flash Media PCI74xx/PCI76xx host adapter support (EXPERIMENTAL)" + depends on PCI && TIFM_CORE && EXPERIMENTAL default TIFM_CORE help This option enables support for Texas Instruments(R) PCI74xx and @@ -192,7 +192,7 @@ config TIFM_7XX1 config ICS932S401 tristate "Integrated Circuits ICS932S401" - depends on I2C + depends on I2C && EXPERIMENTAL help If you say yes here you get support for the Integrated Circuits ICS932S401 clock control chips. @@ -398,7 +398,7 @@ config EP93XX_PWM config DS1682 tristate "Dallas DS1682 Total Elapsed Time Recorder with Alarm" - depends on I2C + depends on I2C && EXPERIMENTAL help If you say yes here you get support for Dallas Semiconductor DS1682 Total Elapsed Time Recorder. diff --git a/trunk/drivers/misc/bmp085-i2c.c b/trunk/drivers/misc/bmp085-i2c.c index a4f33c995ea1..9943971c13e3 100644 --- a/trunk/drivers/misc/bmp085-i2c.c +++ b/trunk/drivers/misc/bmp085-i2c.c @@ -57,6 +57,12 @@ static int bmp085_i2c_remove(struct i2c_client *client) return bmp085_remove(&client->dev); } +static const struct of_device_id bmp085_of_match[] = { + { .compatible = "bosch,bmp085", }, + { }, +}; +MODULE_DEVICE_TABLE(of, bmp085_of_match); + static const struct i2c_device_id bmp085_id[] = { { BMP085_NAME, 0 }, { "bmp180", 0 }, @@ -68,6 +74,7 @@ static struct i2c_driver bmp085_i2c_driver = { .driver = { .owner = THIS_MODULE, .name = BMP085_NAME, + .of_match_table = bmp085_of_match }, .id_table = bmp085_id, .probe = bmp085_i2c_probe, diff --git a/trunk/drivers/misc/bmp085-spi.c b/trunk/drivers/misc/bmp085-spi.c index 5e982af99730..78aaff9b5231 100644 --- a/trunk/drivers/misc/bmp085-spi.c +++ b/trunk/drivers/misc/bmp085-spi.c @@ -73,8 +73,19 @@ static struct spi_driver bmp085_spi_driver = { .remove = __devexit_p(bmp085_spi_remove) }; -module_spi_driver(bmp085_spi_driver); +static int __init bmp085_spi_init(void) +{ + return spi_register_driver(&bmp085_spi_driver); +} + +static void __exit bmp085_spi_exit(void) +{ + spi_unregister_driver(&bmp085_spi_driver); +} MODULE_AUTHOR("Eric Andersson "); MODULE_DESCRIPTION("BMP085 SPI bus driver"); MODULE_LICENSE("GPL"); + +module_init(bmp085_spi_init); +module_exit(bmp085_spi_exit); diff --git a/trunk/drivers/misc/c2port/Kconfig b/trunk/drivers/misc/c2port/Kconfig index 0dd690e61d3c..33ee834e1b83 100644 --- a/trunk/drivers/misc/c2port/Kconfig +++ b/trunk/drivers/misc/c2port/Kconfig @@ -3,7 +3,8 @@ # menuconfig C2PORT - tristate "Silicon Labs C2 port support" + tristate "Silicon Labs C2 port support (EXPERIMENTAL)" + depends on EXPERIMENTAL default n help This option enables support for Silicon Labs C2 port used to @@ -21,7 +22,7 @@ menuconfig C2PORT if C2PORT config C2PORT_DURAMAR_2150 - tristate "C2 port support for Eurotech's Duramar 2150" + tristate "C2 port support for Eurotech's Duramar 2150 (EXPERIMENTAL)" depends on X86 default n help diff --git a/trunk/drivers/misc/carma/carma-fpga-program.c b/trunk/drivers/misc/carma/carma-fpga-program.c index eaddfe9db149..a2d25e4857e3 100644 --- a/trunk/drivers/misc/carma/carma-fpga-program.c +++ b/trunk/drivers/misc/carma/carma-fpga-program.c @@ -978,6 +978,7 @@ static int fpga_of_probe(struct platform_device *op) dev_set_drvdata(priv->dev, priv); dma_cap_zero(mask); dma_cap_set(DMA_MEMCPY, mask); + dma_cap_set(DMA_INTERRUPT, mask); dma_cap_set(DMA_SLAVE, mask); dma_cap_set(DMA_SG, mask); diff --git a/trunk/drivers/misc/carma/carma-fpga.c b/trunk/drivers/misc/carma/carma-fpga.c index 0c43297ed9ac..8c279da07410 100644 --- a/trunk/drivers/misc/carma/carma-fpga.c +++ b/trunk/drivers/misc/carma/carma-fpga.c @@ -666,7 +666,7 @@ static int data_submit_dma(struct fpga_device *priv, struct data_buf *buf) src = SYS_FPGA_BLOCK; tx = chan->device->device_prep_dma_memcpy(chan, dst, src, REG_BLOCK_SIZE, - 0); + DMA_PREP_INTERRUPT); if (!tx) { dev_err(priv->dev, "unable to prep SYS-FPGA DMA\n"); return -ENOMEM; diff --git a/trunk/drivers/misc/eeprom/Kconfig b/trunk/drivers/misc/eeprom/Kconfig index c9e695ea7c9a..701edf658970 100644 --- a/trunk/drivers/misc/eeprom/Kconfig +++ b/trunk/drivers/misc/eeprom/Kconfig @@ -50,7 +50,7 @@ config EEPROM_LEGACY config EEPROM_MAX6875 tristate "Maxim MAX6874/5 power supply supervisor" - depends on I2C + depends on I2C && EXPERIMENTAL help If you say yes here you get read-only support for the user EEPROM of the Maxim MAX6874/5 EEPROM-programmable, quad power-supply diff --git a/trunk/drivers/misc/eeprom/at25.c b/trunk/drivers/misc/eeprom/at25.c index 4ed93dd54116..25003d6ceb56 100644 --- a/trunk/drivers/misc/eeprom/at25.c +++ b/trunk/drivers/misc/eeprom/at25.c @@ -302,61 +302,6 @@ static ssize_t at25_mem_write(struct memory_accessor *mem, const char *buf, /*-------------------------------------------------------------------------*/ -static int at25_np_to_chip(struct device *dev, - struct device_node *np, - struct spi_eeprom *chip) -{ - u32 val; - - memset(chip, 0, sizeof(*chip)); - strncpy(chip->name, np->name, sizeof(chip->name)); - - if (of_property_read_u32(np, "size", &val) == 0 || - of_property_read_u32(np, "at25,byte-len", &val) == 0) { - chip->byte_len = val; - } else { - dev_err(dev, "Error: missing \"size\" property\n"); - return -ENODEV; - } - - if (of_property_read_u32(np, "pagesize", &val) == 0 || - of_property_read_u32(np, "at25,page-size", &val) == 0) { - chip->page_size = (u16)val; - } else { - dev_err(dev, "Error: missing \"pagesize\" property\n"); - return -ENODEV; - } - - if (of_property_read_u32(np, "at25,addr-mode", &val) == 0) { - chip->flags = (u16)val; - } else { - if (of_property_read_u32(np, "address-width", &val)) { - dev_err(dev, - "Error: missing \"address-width\" property\n"); - return -ENODEV; - } - switch (val) { - case 8: - chip->flags |= EE_ADDR1; - break; - case 16: - chip->flags |= EE_ADDR2; - break; - case 24: - chip->flags |= EE_ADDR3; - break; - default: - dev_err(dev, - "Error: bad \"address-width\" property: %u\n", - val); - return -ENODEV; - } - if (of_find_property(np, "read-only", NULL)) - chip->flags |= EE_READONLY; - } - return 0; -} - static int at25_probe(struct spi_device *spi) { struct at25_data *at25 = NULL; @@ -369,11 +314,33 @@ static int at25_probe(struct spi_device *spi) /* Chip description */ if (!spi->dev.platform_data) { if (np) { - err = at25_np_to_chip(&spi->dev, np, &chip); - if (err) + u32 val; + + memset(&chip, 0, sizeof(chip)); + strncpy(chip.name, np->name, 10); + + err = of_property_read_u32(np, "at25,byte-len", &val); + if (err) { + dev_dbg(&spi->dev, "invalid chip dt description\n"); + goto fail; + } + chip.byte_len = val; + + err = of_property_read_u32(np, "at25,addr-mode", &val); + if (err) { + dev_dbg(&spi->dev, "invalid chip dt description\n"); + goto fail; + } + chip.flags = (u16)val; + + err = of_property_read_u32(np, "at25,page-size", &val); + if (err) { + dev_dbg(&spi->dev, "invalid chip dt description\n"); goto fail; + } + chip.page_size = (u16)val; } else { - dev_err(&spi->dev, "Error: no chip description\n"); + dev_dbg(&spi->dev, "no chip description\n"); err = -ENODEV; goto fail; } diff --git a/trunk/drivers/misc/hpilo.c b/trunk/drivers/misc/hpilo.c index 12ccdf94e4fa..6df0da4085e3 100644 --- a/trunk/drivers/misc/hpilo.c +++ b/trunk/drivers/misc/hpilo.c @@ -736,14 +736,7 @@ static void ilo_remove(struct pci_dev *pdev) free_irq(pdev->irq, ilo_hw); ilo_unmap_device(pdev, ilo_hw); pci_release_regions(pdev); - /* - * pci_disable_device(pdev) used to be here. But this PCI device has - * two functions with interrupt lines connected to a single pin. The - * other one is a USB host controller. So when we disable the PIN here - * e.g. by rmmod hpilo, the controller stops working. It is because - * the interrupt link is disabled in ACPI since it is not refcounted - * yet. See acpi_pci_link_free_irq called from acpi_pci_irq_disable. - */ + pci_disable_device(pdev); kfree(ilo_hw); ilo_hwdev[(minor / max_ccb)] = 0; } @@ -833,7 +826,7 @@ static int __devinit ilo_probe(struct pci_dev *pdev, free_regions: pci_release_regions(pdev); disable: -/* pci_disable_device(pdev); see comment in ilo_remove */ + pci_disable_device(pdev); free: kfree(ilo_hw); out: diff --git a/trunk/drivers/misc/ibmasm/uart.c b/trunk/drivers/misc/ibmasm/uart.c index 01e2b0d7e590..1dcb9ae1905a 100644 --- a/trunk/drivers/misc/ibmasm/uart.c +++ b/trunk/drivers/misc/ibmasm/uart.c @@ -33,7 +33,7 @@ void ibmasm_register_uart(struct service_processor *sp) { - struct uart_8250_port uart; + struct uart_port uport; void __iomem *iomem_base; iomem_base = sp->base_address + SCOUT_COM_B_BASE; @@ -47,14 +47,14 @@ void ibmasm_register_uart(struct service_processor *sp) return; } - memset(&uart, 0, sizeof(uart)); - uart.port.irq = sp->irq; - uart.port.uartclk = 3686400; - uart.port.flags = UPF_SHARE_IRQ; - uart.port.iotype = UPIO_MEM; - uart.port.membase = iomem_base; + memset(&uport, 0, sizeof(struct uart_port)); + uport.irq = sp->irq; + uport.uartclk = 3686400; + uport.flags = UPF_SHARE_IRQ; + uport.iotype = UPIO_MEM; + uport.membase = iomem_base; - sp->serial_line = serial8250_register_8250_port(&uart); + sp->serial_line = serial8250_register_port(&uport); if (sp->serial_line < 0) { dev_err(sp->dev, "Failed to register serial port\n"); return; diff --git a/trunk/drivers/misc/lis3lv02d/lis3lv02d.c b/trunk/drivers/misc/lis3lv02d/lis3lv02d.c index 4a87e5c0a320..a981e2a42f92 100644 --- a/trunk/drivers/misc/lis3lv02d/lis3lv02d.c +++ b/trunk/drivers/misc/lis3lv02d/lis3lv02d.c @@ -39,7 +39,6 @@ #include #include #include -#include #include "lis3lv02d.h" #define DRIVER_NAME "lis3lv02d" @@ -81,15 +80,6 @@ #define LIS3_SENSITIVITY_12B ((LIS3_ACCURACY * 1000) / 1024) #define LIS3_SENSITIVITY_8B (18 * LIS3_ACCURACY) -/* - * LIS331DLH spec says 1LSBs corresponds 4G/4096 -> 1LSB is 1000/1024 mG. - * Below macros defines sensitivity values for +/-2G. Dataout bits for - * +/-2G range is 12 bits so 4 bits adjustment must be done to get 12bit - * data from 16bit value. Currently this driver supports only 2G range. - */ -#define LIS3DLH_SENSITIVITY_2G ((LIS3_ACCURACY * 1000) / 1024) -#define SHIFT_ADJ_2G 4 - #define LIS3_DEFAULT_FUZZ_12B 3 #define LIS3_DEFAULT_FLAT_12B 3 #define LIS3_DEFAULT_FUZZ_8B 1 @@ -145,19 +135,6 @@ static s16 lis3lv02d_read_12(struct lis3lv02d *lis3, int reg) return (s16)((hi << 8) | lo); } -/* 12bits for 2G range, 13 bits for 4G range and 14 bits for 8G range */ -static s16 lis331dlh_read_data(struct lis3lv02d *lis3, int reg) -{ - u8 lo, hi; - int v; - - lis3->read(lis3, reg - 1, &lo); - lis3->read(lis3, reg, &hi); - v = (int) ((hi << 8) | lo); - - return (s16) v >> lis3->shift_adj; -} - /** * lis3lv02d_get_axis - For the given axis, give the value converted * @axis: 1,2,3 - can also be negative @@ -218,7 +195,6 @@ static void lis3lv02d_get_xyz(struct lis3lv02d *lis3, int *x, int *y, int *z) static int lis3_12_rates[4] = {40, 160, 640, 2560}; static int lis3_8_rates[2] = {100, 400}; static int lis3_3dc_rates[16] = {0, 1, 10, 25, 50, 100, 200, 400, 1600, 5000}; -static int lis3_3dlh_rates[4] = {50, 100, 400, 1000}; /* ODR is Output Data Rate */ static int lis3lv02d_get_odr(struct lis3lv02d *lis3) @@ -291,7 +267,7 @@ static int lis3lv02d_selftest(struct lis3lv02d *lis3, s16 results[3]) (LIS3_IRQ1_DATA_READY | LIS3_IRQ2_DATA_READY)); } - if ((lis3->whoami == WAI_3DC) || (lis3->whoami == WAI_3DLH)) { + if (lis3->whoami == WAI_3DC) { ctlreg = CTRL_REG4; selftest = CTRL4_ST0; } else { @@ -422,17 +398,9 @@ int lis3lv02d_poweron(struct lis3lv02d *lis3) lis3->read(lis3, CTRL_REG2, ®); if (lis3->whoami == WAI_12B) reg |= CTRL2_BDU | CTRL2_BOOT; - else if (lis3->whoami == WAI_3DLH) - reg |= CTRL2_BOOT_3DLH; else reg |= CTRL2_BOOT_8B; lis3->write(lis3, CTRL_REG2, reg); - - if (lis3->whoami == WAI_3DLH) { - lis3->read(lis3, CTRL_REG4, ®); - reg |= CTRL4_BDU; - lis3->write(lis3, CTRL_REG4, reg); - } } err = lis3lv02d_get_pwron_wait(lis3); @@ -944,154 +912,6 @@ static void lis3lv02d_8b_configure(struct lis3lv02d *lis3, } } -#ifdef CONFIG_OF -int lis3lv02d_init_dt(struct lis3lv02d *lis3) -{ - struct lis3lv02d_platform_data *pdata; - struct device_node *np = lis3->of_node; - u32 val; - - if (!lis3->of_node) - return 0; - - pdata = kzalloc(sizeof(*pdata), GFP_KERNEL); - if (!pdata) - return -ENOMEM; - - if (of_get_property(np, "st,click-single-x", NULL)) - pdata->click_flags |= LIS3_CLICK_SINGLE_X; - if (of_get_property(np, "st,click-double-x", NULL)) - pdata->click_flags |= LIS3_CLICK_DOUBLE_X; - - if (of_get_property(np, "st,click-single-y", NULL)) - pdata->click_flags |= LIS3_CLICK_SINGLE_Y; - if (of_get_property(np, "st,click-double-y", NULL)) - pdata->click_flags |= LIS3_CLICK_DOUBLE_Y; - - if (of_get_property(np, "st,click-single-z", NULL)) - pdata->click_flags |= LIS3_CLICK_SINGLE_Z; - if (of_get_property(np, "st,click-double-z", NULL)) - pdata->click_flags |= LIS3_CLICK_DOUBLE_Z; - - if (!of_property_read_u32(np, "st,click-threshold-x", &val)) - pdata->click_thresh_x = val; - if (!of_property_read_u32(np, "st,click-threshold-y", &val)) - pdata->click_thresh_y = val; - if (!of_property_read_u32(np, "st,click-threshold-z", &val)) - pdata->click_thresh_z = val; - - if (!of_property_read_u32(np, "st,click-time-limit", &val)) - pdata->click_time_limit = val; - if (!of_property_read_u32(np, "st,click-latency", &val)) - pdata->click_latency = val; - if (!of_property_read_u32(np, "st,click-window", &val)) - pdata->click_window = val; - - if (of_get_property(np, "st,irq1-disable", NULL)) - pdata->irq_cfg |= LIS3_IRQ1_DISABLE; - if (of_get_property(np, "st,irq1-ff-wu-1", NULL)) - pdata->irq_cfg |= LIS3_IRQ1_FF_WU_1; - if (of_get_property(np, "st,irq1-ff-wu-2", NULL)) - pdata->irq_cfg |= LIS3_IRQ1_FF_WU_2; - if (of_get_property(np, "st,irq1-data-ready", NULL)) - pdata->irq_cfg |= LIS3_IRQ1_DATA_READY; - if (of_get_property(np, "st,irq1-click", NULL)) - pdata->irq_cfg |= LIS3_IRQ1_CLICK; - - if (of_get_property(np, "st,irq2-disable", NULL)) - pdata->irq_cfg |= LIS3_IRQ2_DISABLE; - if (of_get_property(np, "st,irq2-ff-wu-1", NULL)) - pdata->irq_cfg |= LIS3_IRQ2_FF_WU_1; - if (of_get_property(np, "st,irq2-ff-wu-2", NULL)) - pdata->irq_cfg |= LIS3_IRQ2_FF_WU_2; - if (of_get_property(np, "st,irq2-data-ready", NULL)) - pdata->irq_cfg |= LIS3_IRQ2_DATA_READY; - if (of_get_property(np, "st,irq2-click", NULL)) - pdata->irq_cfg |= LIS3_IRQ2_CLICK; - - if (of_get_property(np, "st,irq-open-drain", NULL)) - pdata->irq_cfg |= LIS3_IRQ_OPEN_DRAIN; - if (of_get_property(np, "st,irq-active-low", NULL)) - pdata->irq_cfg |= LIS3_IRQ_ACTIVE_LOW; - - if (!of_property_read_u32(np, "st,wu-duration-1", &val)) - pdata->duration1 = val; - if (!of_property_read_u32(np, "st,wu-duration-2", &val)) - pdata->duration2 = val; - - if (of_get_property(np, "st,wakeup-x-lo", NULL)) - pdata->wakeup_flags |= LIS3_WAKEUP_X_LO; - if (of_get_property(np, "st,wakeup-x-hi", NULL)) - pdata->wakeup_flags |= LIS3_WAKEUP_X_HI; - if (of_get_property(np, "st,wakeup-y-lo", NULL)) - pdata->wakeup_flags |= LIS3_WAKEUP_Y_LO; - if (of_get_property(np, "st,wakeup-y-hi", NULL)) - pdata->wakeup_flags |= LIS3_WAKEUP_Y_HI; - if (of_get_property(np, "st,wakeup-z-lo", NULL)) - pdata->wakeup_flags |= LIS3_WAKEUP_Z_LO; - if (of_get_property(np, "st,wakeup-z-hi", NULL)) - pdata->wakeup_flags |= LIS3_WAKEUP_Z_HI; - - if (!of_property_read_u32(np, "st,highpass-cutoff-hz", &val)) { - switch (val) { - case 1: - pdata->hipass_ctrl = LIS3_HIPASS_CUTFF_1HZ; - break; - case 2: - pdata->hipass_ctrl = LIS3_HIPASS_CUTFF_2HZ; - break; - case 4: - pdata->hipass_ctrl = LIS3_HIPASS_CUTFF_4HZ; - break; - case 8: - pdata->hipass_ctrl = LIS3_HIPASS_CUTFF_8HZ; - break; - } - } - - if (of_get_property(np, "st,hipass1-disable", NULL)) - pdata->hipass_ctrl |= LIS3_HIPASS1_DISABLE; - if (of_get_property(np, "st,hipass2-disable", NULL)) - pdata->hipass_ctrl |= LIS3_HIPASS2_DISABLE; - - if (of_get_property(np, "st,axis-x", &val)) - pdata->axis_x = val; - if (of_get_property(np, "st,axis-y", &val)) - pdata->axis_y = val; - if (of_get_property(np, "st,axis-z", &val)) - pdata->axis_z = val; - - if (of_get_property(np, "st,default-rate", NULL)) - pdata->default_rate = val; - - if (of_get_property(np, "st,min-limit-x", &val)) - pdata->st_min_limits[0] = val; - if (of_get_property(np, "st,min-limit-y", &val)) - pdata->st_min_limits[1] = val; - if (of_get_property(np, "st,min-limit-z", &val)) - pdata->st_min_limits[2] = val; - - if (of_get_property(np, "st,max-limit-x", &val)) - pdata->st_max_limits[0] = val; - if (of_get_property(np, "st,max-limit-y", &val)) - pdata->st_max_limits[1] = val; - if (of_get_property(np, "st,max-limit-z", &val)) - pdata->st_max_limits[2] = val; - - - lis3->pdata = pdata; - - return 0; -} - -#else -int lis3lv02d_init_dt(struct lis3lv02d *lis3) -{ - return 0; -} -#endif -EXPORT_SYMBOL_GPL(lis3lv02d_init_dt); - /* * Initialise the accelerometer and the various subsystems. * Should be rather independent of the bus system. @@ -1136,16 +956,6 @@ int lis3lv02d_init_device(struct lis3lv02d *lis3) lis3->odr_mask = CTRL1_ODR0|CTRL1_ODR1|CTRL1_ODR2|CTRL1_ODR3; lis3->scale = LIS3_SENSITIVITY_8B; break; - case WAI_3DLH: - pr_info("16 bits lis331dlh sensor found\n"); - lis3->read_data = lis331dlh_read_data; - lis3->mdps_max_val = 2048; /* 12 bits for 2G */ - lis3->shift_adj = SHIFT_ADJ_2G; - lis3->pwron_delay = LIS3_PWRON_DELAY_WAI_8B; - lis3->odrs = lis3_3dlh_rates; - lis3->odr_mask = CTRL1_DR0 | CTRL1_DR1; - lis3->scale = LIS3DLH_SENSITIVITY_2G; - break; default: pr_err("unknown sensor type 0x%X\n", lis3->whoami); return -EINVAL; diff --git a/trunk/drivers/misc/lis3lv02d/lis3lv02d.h b/trunk/drivers/misc/lis3lv02d/lis3lv02d.h index c439c827eea8..2b1482ad3f16 100644 --- a/trunk/drivers/misc/lis3lv02d/lis3lv02d.h +++ b/trunk/drivers/misc/lis3lv02d/lis3lv02d.h @@ -26,12 +26,12 @@ /* * This driver tries to support the "digital" accelerometer chips from * STMicroelectronics such as LIS3LV02DL, LIS302DL, LIS3L02DQ, LIS331DL, - * LIS331DLH, LIS35DE, or LIS202DL. They are very similar in terms of - * programming, with almost the same registers. In addition to differing - * on physical properties, they differ on the number of axes (2/3), - * precision (8/12 bits), and special features (freefall detection, - * click...). Unfortunately, not all the differences can be probed via - * a register. They can be connected either via I²C or SPI. + * LIS35DE, or LIS202DL. They are very similar in terms of programming, with + * almost the same registers. In addition to differing on physical properties, + * they differ on the number of axes (2/3), precision (8/12 bits), and special + * features (freefall detection, click...). Unfortunately, not all the + * differences can be probed via a register. + * They can be connected either via I²C or SPI. */ #include @@ -96,22 +96,12 @@ enum lis3lv02d_reg { }; enum lis3_who_am_i { - WAI_3DLH = 0x32, /* 16 bits: LIS331DLH */ WAI_3DC = 0x33, /* 8 bits: LIS3DC, HP3DC */ WAI_12B = 0x3A, /* 12 bits: LIS3LV02D[LQ]... */ WAI_8B = 0x3B, /* 8 bits: LIS[23]02D[LQ]... */ WAI_6B = 0x52, /* 6 bits: LIS331DLF - not supported */ }; -enum lis3_type { - LIS3LV02D, - LIS3DC, - HP3DC, - LIS2302D, - LIS331DLF, - LIS331DLH, -}; - enum lis3lv02d_ctrl1_12b { CTRL1_Xen = 0x01, CTRL1_Yen = 0x02, @@ -139,27 +129,6 @@ enum lis3lv02d_ctrl1_3dc { CTRL1_ODR3 = 0x80, }; -enum lis331dlh_ctrl1 { - CTRL1_DR0 = 0x08, - CTRL1_DR1 = 0x10, - CTRL1_PM0 = 0x20, - CTRL1_PM1 = 0x40, - CTRL1_PM2 = 0x80, -}; - -enum lis331dlh_ctrl2 { - CTRL2_HPEN1 = 0x04, - CTRL2_HPEN2 = 0x08, - CTRL2_FDS_3DLH = 0x10, - CTRL2_BOOT_3DLH = 0x80, -}; - -enum lis331dlh_ctrl4 { - CTRL4_STSIGN = 0x08, - CTRL4_BLE = 0x40, - CTRL4_BDU = 0x80, -}; - enum lis3lv02d_ctrl2 { CTRL2_DAS = 0x01, CTRL2_SIM = 0x02, @@ -310,14 +279,9 @@ struct lis3lv02d { int data_ready_count[2]; atomic_t wake_thread; unsigned char irq_cfg; - unsigned int shift_adj; struct lis3lv02d_platform_data *pdata; /* for passing board config */ struct mutex mutex; /* Serialize poll and selftest */ - -#ifdef CONFIG_OF - struct device_node *of_node; -#endif }; int lis3lv02d_init_device(struct lis3lv02d *lis3); @@ -326,6 +290,5 @@ void lis3lv02d_joystick_disable(struct lis3lv02d *lis3); void lis3lv02d_poweroff(struct lis3lv02d *lis3); int lis3lv02d_poweron(struct lis3lv02d *lis3); int lis3lv02d_remove_fs(struct lis3lv02d *lis3); -int lis3lv02d_init_dt(struct lis3lv02d *lis3); extern struct lis3lv02d lis3_dev; diff --git a/trunk/drivers/misc/lis3lv02d/lis3lv02d_i2c.c b/trunk/drivers/misc/lis3lv02d/lis3lv02d_i2c.c index 60ec8689d6e3..e8c0019da97a 100644 --- a/trunk/drivers/misc/lis3lv02d/lis3lv02d_i2c.c +++ b/trunk/drivers/misc/lis3lv02d/lis3lv02d_i2c.c @@ -31,10 +31,6 @@ #include #include #include -#include -#include -#include - #include "lis3lv02d.h" #define DRV_NAME "lis3lv02d_i2c" @@ -94,11 +90,7 @@ static int lis3_i2c_init(struct lis3lv02d *lis3) if (ret < 0) return ret; - if (lis3->whoami == WAI_3DLH) - reg |= CTRL1_PM0 | CTRL1_Xen | CTRL1_Yen | CTRL1_Zen; - else - reg |= CTRL1_PD0 | CTRL1_Xen | CTRL1_Yen | CTRL1_Zen; - + reg |= CTRL1_PD0 | CTRL1_Xen | CTRL1_Yen | CTRL1_Zen; return lis3->write(lis3, CTRL_REG1, reg); } @@ -106,30 +98,12 @@ static int lis3_i2c_init(struct lis3lv02d *lis3) static union axis_conversion lis3lv02d_axis_map = { .as_array = { LIS3_DEV_X, LIS3_DEV_Y, LIS3_DEV_Z } }; -#ifdef CONFIG_OF -static struct of_device_id lis3lv02d_i2c_dt_ids[] = { - { .compatible = "st,lis3lv02d" }, - {} -}; -MODULE_DEVICE_TABLE(of, lis3lv02d_i2c_dt_ids); -#endif - static int __devinit lis3lv02d_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) { int ret = 0; struct lis3lv02d_platform_data *pdata = client->dev.platform_data; -#ifdef CONFIG_OF - if (of_match_device(lis3lv02d_i2c_dt_ids, &client->dev)) { - lis3_dev.of_node = client->dev.of_node; - ret = lis3lv02d_init_dt(&lis3_dev); - if (ret) - return ret; - pdata = lis3_dev.pdata; - } -#endif - if (pdata) { if ((pdata->driver_features & LIS3_USE_BLOCK_READ) && (i2c_check_functionality(client->adapter, @@ -257,8 +231,7 @@ static int lis3_i2c_runtime_resume(struct device *dev) #endif /* CONFIG_PM_RUNTIME */ static const struct i2c_device_id lis3lv02d_id[] = { - {"lis3lv02d", LIS3LV02D}, - {"lis331dlh", LIS331DLH}, + {"lis3lv02d", 0 }, {} }; @@ -277,7 +250,6 @@ static struct i2c_driver lis3lv02d_i2c_driver = { .name = DRV_NAME, .owner = THIS_MODULE, .pm = &lis3_pm_ops, - .of_match_table = of_match_ptr(lis3lv02d_i2c_dt_ids), }, .probe = lis3lv02d_i2c_probe, .remove = __devexit_p(lis3lv02d_i2c_remove), diff --git a/trunk/drivers/misc/lis3lv02d/lis3lv02d_spi.c b/trunk/drivers/misc/lis3lv02d/lis3lv02d_spi.c index ccb6475fa059..80880e984b4f 100644 --- a/trunk/drivers/misc/lis3lv02d/lis3lv02d_spi.c +++ b/trunk/drivers/misc/lis3lv02d/lis3lv02d_spi.c @@ -17,9 +17,6 @@ #include #include #include -#include -#include -#include #include "lis3lv02d.h" @@ -61,14 +58,6 @@ static int lis3_spi_init(struct lis3lv02d *lis3) static union axis_conversion lis3lv02d_axis_normal = { .as_array = { 1, 2, 3 } }; -#ifdef CONFIG_OF -static struct of_device_id lis302dl_spi_dt_ids[] = { - { .compatible = "st,lis302dl-spi" }, - {} -}; -MODULE_DEVICE_TABLE(of, lis302dl_spi_dt_ids); -#endif - static int __devinit lis302dl_spi_probe(struct spi_device *spi) { int ret; @@ -86,15 +75,6 @@ static int __devinit lis302dl_spi_probe(struct spi_device *spi) lis3_dev.irq = spi->irq; lis3_dev.ac = lis3lv02d_axis_normal; lis3_dev.pdata = spi->dev.platform_data; - -#ifdef CONFIG_OF - if (of_match_device(lis302dl_spi_dt_ids, &spi->dev)) { - lis3_dev.of_node = spi->dev.of_node; - ret = lis3lv02d_init_dt(&lis3_dev); - if (ret) - return ret; - } -#endif spi_set_drvdata(spi, &lis3_dev); return lis3lv02d_init_device(&lis3_dev); @@ -141,7 +121,6 @@ static struct spi_driver lis302dl_spi_driver = { .name = DRV_NAME, .owner = THIS_MODULE, .pm = &lis3lv02d_spi_pm, - .of_match_table = of_match_ptr(lis302dl_spi_dt_ids), }, .probe = lis302dl_spi_probe, .remove = __devexit_p(lis302dl_spi_remove), diff --git a/trunk/drivers/misc/mei/Kconfig b/trunk/drivers/misc/mei/Kconfig index 5a79ccde2fdf..47d78a72db2e 100644 --- a/trunk/drivers/misc/mei/Kconfig +++ b/trunk/drivers/misc/mei/Kconfig @@ -1,6 +1,6 @@ config INTEL_MEI tristate "Intel Management Engine Interface (Intel MEI)" - depends on X86 && PCI && WATCHDOG_CORE + depends on X86 && PCI && EXPERIMENTAL && WATCHDOG_CORE help The Intel Management Engine (Intel ME) provides Manageability, Security and Media services for system containing Intel chipsets. diff --git a/trunk/drivers/misc/mei/hw.h b/trunk/drivers/misc/mei/hw.h index 9700532f02f6..24c4c962819e 100644 --- a/trunk/drivers/misc/mei/hw.h +++ b/trunk/drivers/misc/mei/hw.h @@ -40,48 +40,47 @@ /* * MEI device IDs */ -#define MEI_DEV_ID_82946GZ 0x2974 /* 82946GZ/GL */ -#define MEI_DEV_ID_82G35 0x2984 /* 82G35 Express */ -#define MEI_DEV_ID_82Q965 0x2994 /* 82Q963/Q965 */ -#define MEI_DEV_ID_82G965 0x29A4 /* 82P965/G965 */ - -#define MEI_DEV_ID_82GM965 0x2A04 /* Mobile PM965/GM965 */ -#define MEI_DEV_ID_82GME965 0x2A14 /* Mobile GME965/GLE960 */ - -#define MEI_DEV_ID_ICH9_82Q35 0x29B4 /* 82Q35 Express */ -#define MEI_DEV_ID_ICH9_82G33 0x29C4 /* 82G33/G31/P35/P31 Express */ -#define MEI_DEV_ID_ICH9_82Q33 0x29D4 /* 82Q33 Express */ -#define MEI_DEV_ID_ICH9_82X38 0x29E4 /* 82X38/X48 Express */ -#define MEI_DEV_ID_ICH9_3200 0x29F4 /* 3200/3210 Server */ - -#define MEI_DEV_ID_ICH9_6 0x28B4 /* Bearlake */ -#define MEI_DEV_ID_ICH9_7 0x28C4 /* Bearlake */ -#define MEI_DEV_ID_ICH9_8 0x28D4 /* Bearlake */ -#define MEI_DEV_ID_ICH9_9 0x28E4 /* Bearlake */ -#define MEI_DEV_ID_ICH9_10 0x28F4 /* Bearlake */ - -#define MEI_DEV_ID_ICH9M_1 0x2A44 /* Cantiga */ -#define MEI_DEV_ID_ICH9M_2 0x2A54 /* Cantiga */ -#define MEI_DEV_ID_ICH9M_3 0x2A64 /* Cantiga */ -#define MEI_DEV_ID_ICH9M_4 0x2A74 /* Cantiga */ - -#define MEI_DEV_ID_ICH10_1 0x2E04 /* Eaglelake */ -#define MEI_DEV_ID_ICH10_2 0x2E14 /* Eaglelake */ -#define MEI_DEV_ID_ICH10_3 0x2E24 /* Eaglelake */ -#define MEI_DEV_ID_ICH10_4 0x2E34 /* Eaglelake */ - -#define MEI_DEV_ID_IBXPK_1 0x3B64 /* Calpella */ -#define MEI_DEV_ID_IBXPK_2 0x3B65 /* Calpella */ - -#define MEI_DEV_ID_CPT_1 0x1C3A /* Couger Point */ -#define MEI_DEV_ID_PBG_1 0x1D3A /* C600/X79 Patsburg */ - -#define MEI_DEV_ID_PPT_1 0x1E3A /* Panther Point */ -#define MEI_DEV_ID_PPT_2 0x1CBA /* Panther Point */ -#define MEI_DEV_ID_PPT_3 0x1DBA /* Panther Point */ - -#define MEI_DEV_ID_LPT 0x8C3A /* Lynx Point */ -#define MEI_DEV_ID_LPT_LP 0x9C3A /* Lynx Point LP */ +#define MEI_DEV_ID_82946GZ 0x2974 /* 82946GZ/GL */ +#define MEI_DEV_ID_82G35 0x2984 /* 82G35 Express */ +#define MEI_DEV_ID_82Q965 0x2994 /* 82Q963/Q965 */ +#define MEI_DEV_ID_82G965 0x29A4 /* 82P965/G965 */ + +#define MEI_DEV_ID_82GM965 0x2A04 /* Mobile PM965/GM965 */ +#define MEI_DEV_ID_82GME965 0x2A14 /* Mobile GME965/GLE960 */ + +#define MEI_DEV_ID_ICH9_82Q35 0x29B4 /* 82Q35 Express */ +#define MEI_DEV_ID_ICH9_82G33 0x29C4 /* 82G33/G31/P35/P31 Express */ +#define MEI_DEV_ID_ICH9_82Q33 0x29D4 /* 82Q33 Express */ +#define MEI_DEV_ID_ICH9_82X38 0x29E4 /* 82X38/X48 Express */ +#define MEI_DEV_ID_ICH9_3200 0x29F4 /* 3200/3210 Server */ + +#define MEI_DEV_ID_ICH9_6 0x28B4 /* Bearlake */ +#define MEI_DEV_ID_ICH9_7 0x28C4 /* Bearlake */ +#define MEI_DEV_ID_ICH9_8 0x28D4 /* Bearlake */ +#define MEI_DEV_ID_ICH9_9 0x28E4 /* Bearlake */ +#define MEI_DEV_ID_ICH9_10 0x28F4 /* Bearlake */ + +#define MEI_DEV_ID_ICH9M_1 0x2A44 /* Cantiga */ +#define MEI_DEV_ID_ICH9M_2 0x2A54 /* Cantiga */ +#define MEI_DEV_ID_ICH9M_3 0x2A64 /* Cantiga */ +#define MEI_DEV_ID_ICH9M_4 0x2A74 /* Cantiga */ + +#define MEI_DEV_ID_ICH10_1 0x2E04 /* Eaglelake */ +#define MEI_DEV_ID_ICH10_2 0x2E14 /* Eaglelake */ +#define MEI_DEV_ID_ICH10_3 0x2E24 /* Eaglelake */ +#define MEI_DEV_ID_ICH10_4 0x2E34 /* Eaglelake */ + +#define MEI_DEV_ID_IBXPK_1 0x3B64 /* Calpella */ +#define MEI_DEV_ID_IBXPK_2 0x3B65 /* Calpella */ + +#define MEI_DEV_ID_CPT_1 0x1C3A /* Cougerpoint */ +#define MEI_DEV_ID_PBG_1 0x1D3A /* PBG */ + +#define MEI_DEV_ID_PPT_1 0x1E3A /* Pantherpoint PPT */ +#define MEI_DEV_ID_PPT_2 0x1CBA /* Pantherpoint PPT */ +#define MEI_DEV_ID_PPT_3 0x1DBA /* Pantherpoint PPT */ + + /* * MEI HW Section */ diff --git a/trunk/drivers/misc/mei/init.c b/trunk/drivers/misc/mei/init.c index 98f1430e3e14..e77f86e69fb5 100644 --- a/trunk/drivers/misc/mei/init.c +++ b/trunk/drivers/misc/mei/init.c @@ -24,25 +24,6 @@ #include "interface.h" #include -const char *mei_dev_state_str(int state) -{ -#define MEI_DEV_STATE(state) case MEI_DEV_##state: return #state - switch (state) { - MEI_DEV_STATE(INITIALIZING); - MEI_DEV_STATE(INIT_CLIENTS); - MEI_DEV_STATE(ENABLED); - MEI_DEV_STATE(RESETING); - MEI_DEV_STATE(DISABLED); - MEI_DEV_STATE(RECOVERING_FROM_RESET); - MEI_DEV_STATE(POWER_DOWN); - MEI_DEV_STATE(POWER_UP); - default: - return "unkown"; - } -#undef MEI_DEV_STATE -} - - const uuid_le mei_amthi_guid = UUID_LE(0x12f80028, 0xb4b7, 0x4b2d, 0xac, 0xa8, 0x46, 0xe0, 0xff, 0x65, 0x81, 0x4c); @@ -142,7 +123,7 @@ struct mei_device *mei_device_init(struct pci_dev *pdev) mutex_init(&dev->device_lock); init_waitqueue_head(&dev->wait_recvd_msg); init_waitqueue_head(&dev->wait_stop_wd); - dev->dev_state = MEI_DEV_INITIALIZING; + dev->mei_state = MEI_INITIALIZING; dev->iamthif_state = MEI_IAMTHIF_IDLE; dev->wd_interface_reg = false; @@ -201,7 +182,7 @@ int mei_hw_init(struct mei_device *dev) } if (err <= 0 && !dev->recvd_msg) { - dev->dev_state = MEI_DEV_DISABLED; + dev->mei_state = MEI_DISABLED; dev_dbg(&dev->pdev->dev, "wait_event_interruptible_timeout failed" "on wait for ME to turn on ME_RDY.\n"); @@ -211,7 +192,7 @@ int mei_hw_init(struct mei_device *dev) if (!(((dev->host_hw_state & H_RDY) == H_RDY) && ((dev->me_hw_state & ME_RDY_HRA) == ME_RDY_HRA))) { - dev->dev_state = MEI_DEV_DISABLED; + dev->mei_state = MEI_DISABLED; dev_dbg(&dev->pdev->dev, "host_hw_state = 0x%08x, me_hw_state = 0x%08x.\n", dev->host_hw_state, dev->me_hw_state); @@ -277,15 +258,15 @@ void mei_reset(struct mei_device *dev, int interrupts_enabled) struct mei_cl_cb *cb_next = NULL; bool unexpected; - if (dev->dev_state == MEI_DEV_RECOVERING_FROM_RESET) { + if (dev->mei_state == MEI_RECOVERING_FROM_RESET) { dev->need_reset = true; return; } - unexpected = (dev->dev_state != MEI_DEV_INITIALIZING && - dev->dev_state != MEI_DEV_DISABLED && - dev->dev_state != MEI_DEV_POWER_DOWN && - dev->dev_state != MEI_DEV_POWER_UP); + unexpected = (dev->mei_state != MEI_INITIALIZING && + dev->mei_state != MEI_DISABLED && + dev->mei_state != MEI_POWER_DOWN && + dev->mei_state != MEI_POWER_UP); dev->host_hw_state = mei_hcsr_read(dev); @@ -304,10 +285,10 @@ void mei_reset(struct mei_device *dev, int interrupts_enabled) dev->need_reset = false; - if (dev->dev_state != MEI_DEV_INITIALIZING) { - if (dev->dev_state != MEI_DEV_DISABLED && - dev->dev_state != MEI_DEV_POWER_DOWN) - dev->dev_state = MEI_DEV_RESETING; + if (dev->mei_state != MEI_INITIALIZING) { + if (dev->mei_state != MEI_DISABLED && + dev->mei_state != MEI_POWER_DOWN) + dev->mei_state = MEI_RESETING; list_for_each_entry_safe(cl_pos, cl_next, &dev->file_list, link) { @@ -330,6 +311,7 @@ void mei_reset(struct mei_device *dev, int interrupts_enabled) dev->me_clients_num = 0; dev->rd_msg_hdr = 0; + dev->stop = false; dev->wd_pending = false; /* update the state of the registers after reset */ @@ -340,8 +322,7 @@ void mei_reset(struct mei_device *dev, int interrupts_enabled) dev->host_hw_state, dev->me_hw_state); if (unexpected) - dev_warn(&dev->pdev->dev, "unexpected reset: dev_state = %s\n", - mei_dev_state_str(dev->dev_state)); + dev_warn(&dev->pdev->dev, "unexpected reset.\n"); /* Wake up all readings so they can be interrupted */ list_for_each_entry_safe(cl_pos, cl_next, &dev->file_list, link) { @@ -390,7 +371,7 @@ void mei_host_start_message(struct mei_device *dev) if (mei_write_message(dev, mei_hdr, (unsigned char *)host_start_req, mei_hdr->length)) { dev_dbg(&dev->pdev->dev, "write send version message to FW fail.\n"); - dev->dev_state = MEI_DEV_RESETING; + dev->mei_state = MEI_RESETING; mei_reset(dev, 1); } dev->init_clients_state = MEI_START_MESSAGE; @@ -422,7 +403,7 @@ void mei_host_enum_clients_message(struct mei_device *dev) host_enum_req->hbm_cmd = HOST_ENUM_REQ_CMD; if (mei_write_message(dev, mei_hdr, (unsigned char *)host_enum_req, mei_hdr->length)) { - dev->dev_state = MEI_DEV_RESETING; + dev->mei_state = MEI_RESETING; dev_dbg(&dev->pdev->dev, "write send enumeration request message to FW fail.\n"); mei_reset(dev, 1); } @@ -463,7 +444,7 @@ void mei_allocate_me_clients_storage(struct mei_device *dev) sizeof(struct mei_me_client), GFP_KERNEL); if (!clients) { dev_dbg(&dev->pdev->dev, "memory allocation for ME clients failed.\n"); - dev->dev_state = MEI_DEV_RESETING; + dev->mei_state = MEI_RESETING; mei_reset(dev, 1); return ; } @@ -509,7 +490,7 @@ int mei_host_client_properties(struct mei_device *dev) if (mei_write_message(dev, mei_header, (unsigned char *)host_cli_req, mei_header->length)) { - dev->dev_state = MEI_DEV_RESETING; + dev->mei_state = MEI_RESETING; dev_dbg(&dev->pdev->dev, "write send enumeration request message to FW fail.\n"); mei_reset(dev, 1); return -EIO; @@ -541,12 +522,12 @@ void mei_cl_init(struct mei_cl *priv, struct mei_device *dev) priv->dev = dev; } -int mei_me_cl_by_uuid(const struct mei_device *dev, const uuid_le *cuuid) +int mei_find_me_client_index(const struct mei_device *dev, uuid_le cuuid) { - int i, res = -ENOENT; + int i, res = -1; for (i = 0; i < dev->me_clients_num; ++i) - if (uuid_le_cmp(*cuuid, + if (uuid_le_cmp(cuuid, dev->me_clients[i].props.protocol_name) == 0) { res = i; break; @@ -557,35 +538,35 @@ int mei_me_cl_by_uuid(const struct mei_device *dev, const uuid_le *cuuid) /** - * mei_me_cl_update_filext - searches for ME client guid + * mei_find_me_client_update_filext - searches for ME client guid * sets client_id in mei_file_private if found * @dev: the device structure - * @cl: private file structure to set client_id in - * @cuuid: searched uuid of ME client + * @priv: private file structure to set client_id in + * @cguid: searched guid of ME client * @client_id: id of host client to be set in file private structure * * returns ME client index */ -int mei_me_cl_update_filext(struct mei_device *dev, struct mei_cl *cl, - const uuid_le *cuuid, u8 host_cl_id) +u8 mei_find_me_client_update_filext(struct mei_device *dev, struct mei_cl *priv, + const uuid_le *cguid, u8 client_id) { int i; - if (!dev || !cl || !cuuid) - return -EINVAL; + if (!dev || !priv || !cguid) + return 0; /* check for valid client id */ - i = mei_me_cl_by_uuid(dev, cuuid); + i = mei_find_me_client_index(dev, *cguid); if (i >= 0) { - cl->me_client_id = dev->me_clients[i].client_id; - cl->state = MEI_FILE_CONNECTING; - cl->host_client_id = host_cl_id; + priv->me_client_id = dev->me_clients[i].client_id; + priv->state = MEI_FILE_CONNECTING; + priv->host_client_id = client_id; - list_add_tail(&cl->link, &dev->file_list); + list_add_tail(&priv->link, &dev->file_list); return (u8)i; } - return -ENOENT; + return 0; } /** @@ -596,16 +577,16 @@ int mei_me_cl_update_filext(struct mei_device *dev, struct mei_cl *cl, */ void mei_host_init_iamthif(struct mei_device *dev) { - int i; + u8 i; unsigned char *msg_buf; mei_cl_init(&dev->iamthif_cl, dev); dev->iamthif_cl.state = MEI_FILE_DISCONNECTED; /* find ME amthi client */ - i = mei_me_cl_update_filext(dev, &dev->iamthif_cl, + i = mei_find_me_client_update_filext(dev, &dev->iamthif_cl, &mei_amthi_guid, MEI_IAMTHIF_HOST_CLIENT_ID); - if (i < 0) { + if (dev->iamthif_cl.state != MEI_FILE_CONNECTING) { dev_dbg(&dev->pdev->dev, "failed to find iamthif client.\n"); return; } diff --git a/trunk/drivers/misc/mei/interface.h b/trunk/drivers/misc/mei/interface.h index ec6c785a3961..fb5c7db4723b 100644 --- a/trunk/drivers/misc/mei/interface.h +++ b/trunk/drivers/misc/mei/interface.h @@ -23,6 +23,14 @@ #include "mei_dev.h" +#define AMT_WD_DEFAULT_TIMEOUT 120 /* seconds */ +#define AMT_WD_MIN_TIMEOUT 120 /* seconds */ +#define AMT_WD_MAX_TIMEOUT 65535 /* seconds */ + +#define MEI_WATCHDOG_DATA_SIZE 16 +#define MEI_START_WD_DATA_SIZE 20 +#define MEI_WD_PARAMS_SIZE 4 + void mei_read_slots(struct mei_device *dev, unsigned char *buffer, @@ -56,7 +64,7 @@ int mei_flow_ctrl_creds(struct mei_device *dev, struct mei_cl *cl); int mei_wd_send(struct mei_device *dev); -int mei_wd_stop(struct mei_device *dev); +int mei_wd_stop(struct mei_device *dev, bool preserve); int mei_wd_host_init(struct mei_device *dev); /* * mei_watchdog_register - Registering watchdog interface diff --git a/trunk/drivers/misc/mei/interrupt.c b/trunk/drivers/misc/mei/interrupt.c index 3533edde04a5..c6ffbbe5a6c0 100644 --- a/trunk/drivers/misc/mei/interrupt.c +++ b/trunk/drivers/misc/mei/interrupt.c @@ -221,10 +221,17 @@ static int mei_irq_thread_read_client_message(struct mei_io_list *complete_list, cl->status = 0; list_del(&cb_pos->cb_list); dev_dbg(&dev->pdev->dev, - "completed read H cl = %d, ME cl = %d, length = %lu\n", + "completed read host client = %d," + "ME client = %d, " + "data length = %lu\n", cl->host_client_id, cl->me_client_id, cb_pos->information); + + *(cb_pos->response_buffer.data + + cb_pos->information) = '\0'; + dev_dbg(&dev->pdev->dev, "cb_pos->res_buffer - %s\n", + cb_pos->response_buffer.data); list_add_tail(&cb_pos->cb_list, &complete_list->mei_cb.cb_list); } @@ -626,7 +633,7 @@ static void mei_irq_thread_read_bus_message(struct mei_device *dev, if (version_res->host_version_supported) { dev->version.major_version = HBM_MAJOR_VERSION; dev->version.minor_version = HBM_MINOR_VERSION; - if (dev->dev_state == MEI_DEV_INIT_CLIENTS && + if (dev->mei_state == MEI_INIT_CLIENTS && dev->init_clients_state == MEI_START_MESSAGE) { dev->init_clients_timer = 0; mei_host_enum_clients_message(dev); @@ -700,7 +707,7 @@ static void mei_irq_thread_read_bus_message(struct mei_device *dev, dev->me_clients[dev->me_client_presentation_num].props = props_res->client_properties; - if (dev->dev_state == MEI_DEV_INIT_CLIENTS && + if (dev->mei_state == MEI_INIT_CLIENTS && dev->init_clients_state == MEI_CLIENT_PROPERTIES_MESSAGE) { dev->me_client_index++; @@ -727,7 +734,7 @@ static void mei_irq_thread_read_bus_message(struct mei_device *dev, * Client ID 2 - Reserved for AMTHI */ bitmap_set(dev->host_clients_map, 0, 3); - dev->dev_state = MEI_DEV_ENABLED; + dev->mei_state = MEI_ENABLED; /* if wd initialization fails, initialization the AMTHI client, * otherwise the AMTHI client will be initialized after the WD client connect response @@ -752,7 +759,7 @@ static void mei_irq_thread_read_bus_message(struct mei_device *dev, case HOST_ENUM_RES_CMD: enum_res = (struct hbm_host_enum_response *) mei_msg; memcpy(dev->me_clients_map, enum_res->valid_addresses, 32); - if (dev->dev_state == MEI_DEV_INIT_CLIENTS && + if (dev->mei_state == MEI_INIT_CLIENTS && dev->init_clients_state == MEI_ENUM_CLIENTS_MESSAGE) { dev->init_clients_timer = 0; dev->me_client_presentation_num = 0; @@ -769,7 +776,7 @@ static void mei_irq_thread_read_bus_message(struct mei_device *dev, break; case HOST_STOP_RES_CMD: - dev->dev_state = MEI_DEV_DISABLED; + dev->mei_state = MEI_DISABLED; dev_dbg(&dev->pdev->dev, "resetting because of FW stop response.\n"); mei_reset(dev, 1); break; @@ -1217,9 +1224,10 @@ static int mei_irq_thread_write_handler(struct mei_io_list *cmpl_list, } } - if (dev->wd_state == MEI_WD_STOPPING) { - dev->wd_state = MEI_WD_IDLE; + if (dev->stop && !dev->wd_pending) { + dev->wd_stopped = true; wake_up_interruptible(&dev->wait_stop_wd); + return 0; } if (dev->extra_write_index) { @@ -1232,7 +1240,7 @@ static int mei_irq_thread_write_handler(struct mei_io_list *cmpl_list, *slots -= dev->extra_write_index; dev->extra_write_index = 0; } - if (dev->dev_state == MEI_DEV_ENABLED) { + if (dev->mei_state == MEI_ENABLED) { if (dev->wd_pending && mei_flow_ctrl_creds(dev, &dev->wd_cl) > 0) { if (mei_wd_send(dev)) @@ -1242,12 +1250,14 @@ static int mei_irq_thread_write_handler(struct mei_io_list *cmpl_list, dev->wd_pending = false; - if (dev->wd_state == MEI_WD_RUNNING) - *slots -= mei_data2slots(MEI_WD_START_MSG_SIZE); + if (dev->wd_timeout) + *slots -= mei_data2slots(MEI_START_WD_DATA_SIZE); else - *slots -= mei_data2slots(MEI_WD_STOP_MSG_SIZE); + *slots -= mei_data2slots(MEI_START_WD_DATA_SIZE); } } + if (dev->stop) + return -ENODEV; /* complete control write list CB */ dev_dbg(&dev->pdev->dev, "complete control write list cb.\n"); @@ -1351,8 +1361,8 @@ void mei_timer(struct work_struct *work) mutex_lock(&dev->device_lock); - if (dev->dev_state != MEI_DEV_ENABLED) { - if (dev->dev_state == MEI_DEV_INIT_CLIENTS) { + if (dev->mei_state != MEI_ENABLED) { + if (dev->mei_state == MEI_INIT_CLIENTS) { if (dev->init_clients_timer) { if (--dev->init_clients_timer == 0) { dev_dbg(&dev->pdev->dev, "IMEI reset due to init clients timeout ,init clients state = %d.\n", @@ -1474,8 +1484,8 @@ irqreturn_t mei_interrupt_thread_handler(int irq, void *dev_id) /* check if ME wants a reset */ if ((dev->me_hw_state & ME_RDY_HRA) == 0 && - dev->dev_state != MEI_DEV_RESETING && - dev->dev_state != MEI_DEV_INITIALIZING) { + dev->mei_state != MEI_RESETING && + dev->mei_state != MEI_INITIALIZING) { dev_dbg(&dev->pdev->dev, "FW not ready.\n"); mei_reset(dev, 1); mutex_unlock(&dev->device_lock); @@ -1488,7 +1498,7 @@ irqreturn_t mei_interrupt_thread_handler(int irq, void *dev_id) dev_dbg(&dev->pdev->dev, "we need to start the dev.\n"); dev->host_hw_state |= (H_IE | H_IG | H_RDY); mei_hcsr_set(dev); - dev->dev_state = MEI_DEV_INIT_CLIENTS; + dev->mei_state = MEI_INIT_CLIENTS; dev_dbg(&dev->pdev->dev, "link is established start sending messages.\n"); /* link is established * start sending messages. diff --git a/trunk/drivers/misc/mei/iorw.c b/trunk/drivers/misc/mei/iorw.c index fcba98eb892e..50f52e21f587 100644 --- a/trunk/drivers/misc/mei/iorw.c +++ b/trunk/drivers/misc/mei/iorw.c @@ -38,31 +38,7 @@ #include #include "interface.h" -/** - * mei_me_cl_by_id return index to me_clients for client_id - * - * @dev: the device structure - * @client_id: me client id - * - * Locking: called under "dev->device_lock" lock - * - * returns index on success, -ENOENT on failure. - */ -int mei_me_cl_by_id(struct mei_device *dev, u8 client_id) -{ - int i; - for (i = 0; i < dev->me_clients_num; i++) - if (dev->me_clients[i].client_id == client_id) - break; - if (WARN_ON(dev->me_clients[i].client_id != client_id)) - return -ENOENT; - - if (i == dev->me_clients_num) - return -ENOENT; - - return i; -} /** * mei_ioctl_connect_client - the connect to fw client IOCTL function @@ -108,7 +84,7 @@ int mei_ioctl_connect_client(struct file *file, cb->major_file_operations = MEI_IOCTL; - if (dev->dev_state != MEI_DEV_ENABLED) { + if (dev->mei_state != MEI_ENABLED) { rets = -ENODEV; goto end; } @@ -119,7 +95,7 @@ int mei_ioctl_connect_client(struct file *file, } /* find ME client we're trying to connect to */ - i = mei_me_cl_by_uuid(dev, &data->in_client_uuid); + i = mei_find_me_client_index(dev, data->in_client_uuid); if (i >= 0 && !dev->me_clients[i].props.fixed_address) { cl->me_client_id = dev->me_clients[i].client_id; cl->state = MEI_FILE_CONNECTING; @@ -297,12 +273,19 @@ int amthi_read(struct mei_device *dev, struct file *file, return -ETIMEDOUT; } - i = mei_me_cl_by_id(dev, dev->iamthif_cl.me_client_id); + for (i = 0; i < dev->me_clients_num; i++) { + if (dev->me_clients[i].client_id == + dev->iamthif_cl.me_client_id) + break; + } - if (i < 0) { + if (i == dev->me_clients_num) { dev_dbg(&dev->pdev->dev, "amthi client not found.\n"); return -ENODEV; } + if (WARN_ON(dev->me_clients[i].client_id != cl->me_client_id)) + return -ENODEV; + dev_dbg(&dev->pdev->dev, "checking amthi data\n"); cb = find_amthi_read_list_entry(dev, file); @@ -333,7 +316,8 @@ int amthi_read(struct mei_device *dev, struct file *file, dev->iamthif_timer = 0; if (cb) { - timeout = cb->read_time + msecs_to_jiffies(IAMTHIF_READ_TIMER); + timeout = cb->read_time + + msecs_to_jiffies(IAMTHIF_READ_TIMER); dev_dbg(&dev->pdev->dev, "amthi timeout = %lud\n", timeout); @@ -402,7 +386,7 @@ int mei_start_read(struct mei_device *dev, struct mei_cl *cl) if (cl->state != MEI_FILE_CONNECTED) return -ENODEV; - if (dev->dev_state != MEI_DEV_ENABLED) + if (dev->mei_state != MEI_ENABLED) return -ENODEV; dev_dbg(&dev->pdev->dev, "check if read is pending.\n"); @@ -417,8 +401,19 @@ int mei_start_read(struct mei_device *dev, struct mei_cl *cl) dev_dbg(&dev->pdev->dev, "allocation call back successful. host client = %d, ME client = %d\n", cl->host_client_id, cl->me_client_id); - i = mei_me_cl_by_id(dev, cl->me_client_id); - if (i < 0) { + + for (i = 0; i < dev->me_clients_num; i++) { + if (dev->me_clients[i].client_id == cl->me_client_id) + break; + + } + + if (WARN_ON(dev->me_clients[i].client_id != cl->me_client_id)) { + rets = -ENODEV; + goto unlock; + } + + if (i == dev->me_clients_num) { rets = -ENODEV; goto unlock; } diff --git a/trunk/drivers/misc/mei/main.c b/trunk/drivers/misc/mei/main.c index e8b0858132c1..092330208869 100644 --- a/trunk/drivers/misc/mei/main.c +++ b/trunk/drivers/misc/mei/main.c @@ -41,8 +41,11 @@ #include #include "interface.h" -/* AMT device is a singleton on the platform */ -static struct pci_dev *mei_pdev; +static const char mei_driver_name[] = "mei"; + +/* The device pointer */ +/* Currently this driver works as long as there is only a single AMT device. */ +struct pci_dev *mei_device; /* mei_pci_tbl - PCI Device ID Table */ static DEFINE_PCI_DEVICE_TABLE(mei_pci_tbl) = { @@ -77,8 +80,6 @@ static DEFINE_PCI_DEVICE_TABLE(mei_pci_tbl) = { {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_PPT_1)}, {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_PPT_2)}, {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_PPT_3)}, - {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_LPT)}, - {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_LPT_LP)}, /* required last entry */ {0, } @@ -219,10 +220,10 @@ static int mei_open(struct inode *inode, struct file *file) int err; err = -ENODEV; - if (!mei_pdev) + if (!mei_device) goto out; - dev = pci_get_drvdata(mei_pdev); + dev = pci_get_drvdata(mei_device); if (!dev) goto out; @@ -233,24 +234,18 @@ static int mei_open(struct inode *inode, struct file *file) goto out_unlock; err = -ENODEV; - if (dev->dev_state != MEI_DEV_ENABLED) { - dev_dbg(&dev->pdev->dev, "dev_state != MEI_ENABLED dev_state = %s\n", - mei_dev_state_str(dev->dev_state)); + if (dev->mei_state != MEI_ENABLED) { + dev_dbg(&dev->pdev->dev, "mei_state != MEI_ENABLED mei_state= %d\n", + dev->mei_state); goto out_unlock; } err = -EMFILE; - if (dev->open_handle_count >= MEI_MAX_OPEN_HANDLE_COUNT) { - dev_err(&dev->pdev->dev, "open_handle_count exceded %d", - MEI_MAX_OPEN_HANDLE_COUNT); + if (dev->open_handle_count >= MEI_MAX_OPEN_HANDLE_COUNT) goto out_unlock; - } cl_id = find_first_zero_bit(dev->host_clients_map, MEI_CLIENTS_MAX); - if (cl_id >= MEI_CLIENTS_MAX) { - dev_err(&dev->pdev->dev, "client_id exceded %d", - MEI_CLIENTS_MAX) ; + if (cl_id >= MEI_CLIENTS_MAX) goto out_unlock; - } cl->host_client_id = cl_id; @@ -391,16 +386,17 @@ static ssize_t mei_read(struct file *file, char __user *ubuf, dev = cl->dev; mutex_lock(&dev->device_lock); - if (dev->dev_state != MEI_DEV_ENABLED) { + if (dev->mei_state != MEI_ENABLED) { rets = -ENODEV; goto out; } if ((cl->sm_state & MEI_WD_STATE_INDEPENDENCE_MSG_SENT) == 0) { /* Do not allow to read watchdog client */ - i = mei_me_cl_by_uuid(dev, &mei_wd_guid); + i = mei_find_me_client_index(dev, mei_wd_guid); if (i >= 0) { struct mei_me_client *me_client = &dev->me_clients[i]; + if (cl->me_client_id == me_client->client_id) { rets = -EBADF; goto out; @@ -545,7 +541,7 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf, mutex_lock(&dev->device_lock); - if (dev->dev_state != MEI_DEV_ENABLED) { + if (dev->mei_state != MEI_ENABLED) { mutex_unlock(&dev->device_lock); return -ENODEV; } @@ -620,16 +616,26 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf, rets = -ENOMEM; goto unlock_dev; } - if (dev->dev_state != MEI_DEV_ENABLED) { + if (dev->mei_state != MEI_ENABLED) { rets = -ENODEV; goto unlock_dev; } - i = mei_me_cl_by_id(dev, dev->iamthif_cl.me_client_id); - if (i < 0) { + for (i = 0; i < dev->me_clients_num; i++) { + if (dev->me_clients[i].client_id == + dev->iamthif_cl.me_client_id) + break; + } + + if (WARN_ON(dev->me_clients[i].client_id != cl->me_client_id)) { rets = -ENODEV; goto unlock_dev; } - if (length > dev->me_clients[i].props.max_msg_length || + if (i == dev->me_clients_num || + (dev->me_clients[i].client_id != + dev->iamthif_cl.me_client_id)) { + rets = -ENODEV; + goto unlock_dev; + } else if (length > dev->me_clients[i].props.max_msg_length || length <= 0) { rets = -EMSGSIZE; goto unlock_dev; @@ -682,8 +688,16 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf, cl->me_client_id); goto unlock_dev; } - i = mei_me_cl_by_id(dev, cl->me_client_id); - if (i < 0) { + for (i = 0; i < dev->me_clients_num; i++) { + if (dev->me_clients[i].client_id == + cl->me_client_id) + break; + } + if (WARN_ON(dev->me_clients[i].client_id != cl->me_client_id)) { + rets = -ENODEV; + goto unlock_dev; + } + if (i == dev->me_clients_num) { rets = -ENODEV; goto unlock_dev; } @@ -776,7 +790,7 @@ static long mei_ioctl(struct file *file, unsigned int cmd, unsigned long data) dev_dbg(&dev->pdev->dev, "IOCTL cmd = 0x%x", cmd); mutex_lock(&dev->device_lock); - if (dev->dev_state != MEI_DEV_ENABLED) { + if (dev->mei_state != MEI_ENABLED) { rets = -ENODEV; goto out; } @@ -855,7 +869,7 @@ static unsigned int mei_poll(struct file *file, poll_table *wait) mutex_lock(&dev->device_lock); - if (dev->dev_state != MEI_DEV_ENABLED) + if (dev->mei_state != MEI_ENABLED) goto out; @@ -910,27 +924,6 @@ static struct miscdevice mei_misc_device = { .minor = MISC_DYNAMIC_MINOR, }; -/** - * mei_quirk_probe - probe for devices that doesn't valid ME interface - * @pdev: PCI device structure - * @ent: entry into pci_device_table - * - * returns true if ME Interface is valid, false otherwise - */ -static bool __devinit mei_quirk_probe(struct pci_dev *pdev, - const struct pci_device_id *ent) -{ - u32 reg; - if (ent->device == MEI_DEV_ID_PBG_1) { - pci_read_config_dword(pdev, 0x48, ®); - /* make sure that bit 9 is up and bit 10 is down */ - if ((reg & 0x600) == 0x200) { - dev_info(&pdev->dev, "Device doesn't have valid ME Interface\n"); - return false; - } - } - return true; -} /** * mei_probe - Device Initialization Routine * @@ -946,13 +939,7 @@ static int __devinit mei_probe(struct pci_dev *pdev, int err; mutex_lock(&mei_mutex); - - if (!mei_quirk_probe(pdev, ent)) { - err = -ENODEV; - goto end; - } - - if (mei_pdev) { + if (mei_device) { err = -EEXIST; goto end; } @@ -965,7 +952,7 @@ static int __devinit mei_probe(struct pci_dev *pdev, /* set PCI host mastering */ pci_set_master(pdev); /* pci request regions for mei driver */ - err = pci_request_regions(pdev, KBUILD_MODNAME); + err = pci_request_regions(pdev, mei_driver_name); if (err) { dev_err(&pdev->dev, "failed to get pci regions.\n"); goto disable_device; @@ -990,12 +977,12 @@ static int __devinit mei_probe(struct pci_dev *pdev, err = request_threaded_irq(pdev->irq, NULL, mei_interrupt_thread_handler, - IRQF_ONESHOT, KBUILD_MODNAME, dev); + IRQF_ONESHOT, mei_driver_name, dev); else err = request_threaded_irq(pdev->irq, mei_interrupt_quick_handler, mei_interrupt_thread_handler, - IRQF_SHARED, KBUILD_MODNAME, dev); + IRQF_SHARED, mei_driver_name, dev); if (err) { dev_err(&pdev->dev, "request_threaded_irq failure. irq = %d\n", @@ -1013,7 +1000,7 @@ static int __devinit mei_probe(struct pci_dev *pdev, if (err) goto release_irq; - mei_pdev = pdev; + mei_device = pdev; pci_set_drvdata(pdev, dev); @@ -1058,7 +1045,7 @@ static void __devexit mei_remove(struct pci_dev *pdev) { struct mei_device *dev; - if (mei_pdev != pdev) + if (mei_device != pdev) return; dev = pci_get_drvdata(pdev); @@ -1067,11 +1054,9 @@ static void __devexit mei_remove(struct pci_dev *pdev) mutex_lock(&dev->device_lock); - cancel_delayed_work(&dev->timer_work); + mei_wd_stop(dev, false); - mei_wd_stop(dev); - - mei_pdev = NULL; + mei_device = NULL; if (dev->iamthif_cl.state == MEI_FILE_CONNECTED) { dev->iamthif_cl.state = MEI_FILE_DISCONNECTING; @@ -1124,15 +1109,12 @@ static int mei_pci_suspend(struct device *device) if (!dev) return -ENODEV; mutex_lock(&dev->device_lock); - - cancel_delayed_work(&dev->timer_work); - /* Stop watchdog if exists */ - err = mei_wd_stop(dev); + err = mei_wd_stop(dev, true); /* Set new mei state */ - if (dev->dev_state == MEI_DEV_ENABLED || - dev->dev_state == MEI_DEV_RECOVERING_FROM_RESET) { - dev->dev_state = MEI_DEV_POWER_DOWN; + if (dev->mei_state == MEI_ENABLED || + dev->mei_state == MEI_RECOVERING_FROM_RESET) { + dev->mei_state = MEI_POWER_DOWN; mei_reset(dev, 0); } mutex_unlock(&dev->device_lock); @@ -1160,12 +1142,12 @@ static int mei_pci_resume(struct device *device) err = request_threaded_irq(pdev->irq, NULL, mei_interrupt_thread_handler, - IRQF_ONESHOT, KBUILD_MODNAME, dev); + IRQF_ONESHOT, mei_driver_name, dev); else err = request_threaded_irq(pdev->irq, mei_interrupt_quick_handler, mei_interrupt_thread_handler, - IRQF_SHARED, KBUILD_MODNAME, dev); + IRQF_SHARED, mei_driver_name, dev); if (err) { dev_err(&pdev->dev, "request_threaded_irq failed: irq = %d.\n", @@ -1174,7 +1156,7 @@ static int mei_pci_resume(struct device *device) } mutex_lock(&dev->device_lock); - dev->dev_state = MEI_DEV_POWER_UP; + dev->mei_state = MEI_POWER_UP; mei_reset(dev, 1); mutex_unlock(&dev->device_lock); @@ -1192,7 +1174,7 @@ static SIMPLE_DEV_PM_OPS(mei_pm_ops, mei_pci_suspend, mei_pci_resume); * PCI driver structure */ static struct pci_driver mei_driver = { - .name = KBUILD_MODNAME, + .name = mei_driver_name, .id_table = mei_pci_tbl, .probe = mei_probe, .remove = __devexit_p(mei_remove), diff --git a/trunk/drivers/misc/mei/mei_dev.h b/trunk/drivers/misc/mei/mei_dev.h index adb35fb9281c..d61c4ddfc80c 100644 --- a/trunk/drivers/misc/mei/mei_dev.h +++ b/trunk/drivers/misc/mei/mei_dev.h @@ -25,20 +25,18 @@ /* * watch dog definition */ -#define MEI_WD_HDR_SIZE 4 -#define MEI_WD_STOP_MSG_SIZE MEI_WD_HDR_SIZE -#define MEI_WD_START_MSG_SIZE (MEI_WD_HDR_SIZE + 16) - -#define MEI_WD_DEFAULT_TIMEOUT 120 /* seconds */ -#define MEI_WD_MIN_TIMEOUT 120 /* seconds */ -#define MEI_WD_MAX_TIMEOUT 65535 /* seconds */ - -#define MEI_WD_STOP_TIMEOUT 10 /* msecs */ - +#define MEI_WATCHDOG_DATA_SIZE 16 +#define MEI_START_WD_DATA_SIZE 20 +#define MEI_WD_PARAMS_SIZE 4 #define MEI_WD_STATE_INDEPENDENCE_MSG_SENT (1 << 0) #define MEI_RD_MSG_BUF_SIZE (128 * sizeof(u32)) +/* + * MEI PCI Device object + */ +extern struct pci_dev *mei_device; + /* * AMTHI Client UUID @@ -55,22 +53,20 @@ extern const uuid_le mei_wd_guid; */ extern const u8 mei_wd_state_independence_msg[3][4]; -/* - * Number of Maximum MEI Clients - */ -#define MEI_CLIENTS_MAX 256 - /* * Number of File descriptors/handles * that can be opened to the driver. * - * Limit to 253: 256 Total Clients - * minus internal client for MEI Bus Messags + * Limit to 253: 255 Total Clients * minus internal client for AMTHI * minus internal client for Watchdog */ -#define MEI_MAX_OPEN_HANDLE_COUNT (MEI_CLIENTS_MAX - 3) +#define MEI_MAX_OPEN_HANDLE_COUNT 253 +/* + * Number of Maximum MEI Clients + */ +#define MEI_CLIENTS_MAX 255 /* File state */ enum file_state { @@ -82,19 +78,17 @@ enum file_state { }; /* MEI device states */ -enum mei_dev_state { - MEI_DEV_INITIALIZING = 0, - MEI_DEV_INIT_CLIENTS, - MEI_DEV_ENABLED, - MEI_DEV_RESETING, - MEI_DEV_DISABLED, - MEI_DEV_RECOVERING_FROM_RESET, - MEI_DEV_POWER_DOWN, - MEI_DEV_POWER_UP +enum mei_states { + MEI_INITIALIZING = 0, + MEI_INIT_CLIENTS, + MEI_ENABLED, + MEI_RESETING, + MEI_DISABLED, + MEI_RECOVERING_FROM_RESET, + MEI_POWER_DOWN, + MEI_POWER_UP }; -const char *mei_dev_state_str(int state); - /* init clients states*/ enum mei_init_clients_states { MEI_START_MESSAGE = 0, @@ -119,12 +113,6 @@ enum mei_file_transaction_states { MEI_READ_COMPLETE }; -enum mei_wd_states { - MEI_WD_IDLE, - MEI_WD_RUNNING, - MEI_WD_STOPPING, -}; - /* MEI CB */ enum mei_cb_major_types { MEI_READ = 0, @@ -140,7 +128,7 @@ enum mei_cb_major_types { struct mei_message_data { u32 size; unsigned char *data; -}; +} __packed; struct mei_cl_cb { @@ -230,9 +218,10 @@ struct mei_device { /* * mei device states */ - enum mei_dev_state dev_state; + enum mei_states mei_state; enum mei_init_clients_states init_clients_state; u16 init_clients_timer; + bool stop; bool need_reset; u32 extra_write_index; @@ -252,11 +241,12 @@ struct mei_device { bool mei_host_buffer_is_empty; struct mei_cl wd_cl; - enum mei_wd_states wd_state; bool wd_interface_reg; bool wd_pending; - u16 wd_timeout; - unsigned char wd_data[MEI_WD_START_MSG_SIZE]; + bool wd_stopped; + bool wd_bypass; /* if false, don't refresh watchdog ME client */ + u16 wd_timeout; /* seconds ((wd_data[1] << 8) + wd_data[0]) */ + unsigned char wd_data[MEI_START_WD_DATA_SIZE]; struct file *iamthif_file_object; @@ -289,10 +279,9 @@ void mei_host_init_iamthif(struct mei_device *dev); void mei_allocate_me_clients_storage(struct mei_device *dev); -int mei_me_cl_update_filext(struct mei_device *dev, struct mei_cl *cl, - const uuid_le *cguid, u8 host_client_id); -int mei_me_cl_by_uuid(const struct mei_device *dev, const uuid_le *cuuid); -int mei_me_cl_by_id(struct mei_device *dev, u8 client_id); +u8 mei_find_me_client_update_filext(struct mei_device *dev, + struct mei_cl *priv, + const uuid_le *cguid, u8 client_id); /* * MEI IO List Functions @@ -359,6 +348,7 @@ void mei_run_next_iamthif_cmd(struct mei_device *dev); void mei_free_cb_private(struct mei_cl_cb *priv_cb); +int mei_find_me_client_index(const struct mei_device *dev, uuid_le cuuid); /* * Register Access Function diff --git a/trunk/drivers/misc/mei/wd.c b/trunk/drivers/misc/mei/wd.c index d96c537f046f..5133fd77b91c 100644 --- a/trunk/drivers/misc/mei/wd.c +++ b/trunk/drivers/misc/mei/wd.c @@ -48,8 +48,8 @@ const uuid_le mei_wd_guid = UUID_LE(0x05B79A6F, 0x4628, 0x4D7F, 0x89, static void mei_wd_set_start_timeout(struct mei_device *dev, u16 timeout) { dev_dbg(&dev->pdev->dev, "wd: set timeout=%d.\n", timeout); - memcpy(dev->wd_data, mei_start_wd_params, MEI_WD_HDR_SIZE); - memcpy(dev->wd_data + MEI_WD_HDR_SIZE, &timeout, sizeof(u16)); + memcpy(dev->wd_data, mei_start_wd_params, MEI_WD_PARAMS_SIZE); + memcpy(dev->wd_data + MEI_WD_PARAMS_SIZE, &timeout, sizeof(u16)); } /** @@ -66,11 +66,10 @@ int mei_wd_host_init(struct mei_device *dev) /* look for WD client and connect to it */ dev->wd_cl.state = MEI_FILE_DISCONNECTED; - dev->wd_timeout = MEI_WD_DEFAULT_TIMEOUT; - dev->wd_state = MEI_WD_IDLE; + dev->wd_timeout = AMT_WD_DEFAULT_TIMEOUT; /* find ME WD client */ - mei_me_cl_update_filext(dev, &dev->wd_cl, + mei_find_me_client_update_filext(dev, &dev->wd_cl, &mei_wd_guid, MEI_WD_HOST_CLIENT_ID); dev_dbg(&dev->pdev->dev, "wd: check client\n"); @@ -109,10 +108,10 @@ int mei_wd_send(struct mei_device *dev) mei_hdr->msg_complete = 1; mei_hdr->reserved = 0; - if (!memcmp(dev->wd_data, mei_start_wd_params, MEI_WD_HDR_SIZE)) - mei_hdr->length = MEI_WD_START_MSG_SIZE; - else if (!memcmp(dev->wd_data, mei_stop_wd_params, MEI_WD_HDR_SIZE)) - mei_hdr->length = MEI_WD_STOP_MSG_SIZE; + if (!memcmp(dev->wd_data, mei_start_wd_params, MEI_WD_PARAMS_SIZE)) + mei_hdr->length = MEI_START_WD_DATA_SIZE; + else if (!memcmp(dev->wd_data, mei_stop_wd_params, MEI_WD_PARAMS_SIZE)) + mei_hdr->length = MEI_WD_PARAMS_SIZE; else return -EINVAL; @@ -129,17 +128,18 @@ int mei_wd_send(struct mei_device *dev) * -EIO when message send fails * -EINVAL when invalid message is to be sent */ -int mei_wd_stop(struct mei_device *dev) +int mei_wd_stop(struct mei_device *dev, bool preserve) { int ret; + u16 wd_timeout = dev->wd_timeout; - if (dev->wd_cl.state != MEI_FILE_CONNECTED || - dev->wd_state != MEI_WD_RUNNING) + cancel_delayed_work(&dev->timer_work); + if (dev->wd_cl.state != MEI_FILE_CONNECTED || !dev->wd_timeout) return 0; - memcpy(dev->wd_data, mei_stop_wd_params, MEI_WD_STOP_MSG_SIZE); - - dev->wd_state = MEI_WD_STOPPING; + dev->wd_timeout = 0; + memcpy(dev->wd_data, mei_stop_wd_params, MEI_WD_PARAMS_SIZE); + dev->stop = true; ret = mei_flow_ctrl_creds(dev, &dev->wd_cl); if (ret < 0) @@ -161,14 +161,13 @@ int mei_wd_stop(struct mei_device *dev) } else { dev->wd_pending = true; } - + dev->wd_stopped = false; mutex_unlock(&dev->device_lock); ret = wait_event_interruptible_timeout(dev->wait_stop_wd, - dev->wd_state == MEI_WD_IDLE, - msecs_to_jiffies(MEI_WD_STOP_TIMEOUT)); + dev->wd_stopped, 10 * HZ); mutex_lock(&dev->device_lock); - if (dev->wd_state == MEI_WD_IDLE) { + if (dev->wd_stopped) { dev_dbg(&dev->pdev->dev, "wd: stop completed ret=%d.\n", ret); ret = 0; } else { @@ -178,6 +177,9 @@ int mei_wd_stop(struct mei_device *dev) "wd: stop failed to complete ret=%d.\n", ret); } + if (preserve) + dev->wd_timeout = wd_timeout; + out: return ret; } @@ -194,16 +196,16 @@ static int mei_wd_ops_start(struct watchdog_device *wd_dev) int err = -ENODEV; struct mei_device *dev; - dev = watchdog_get_drvdata(wd_dev); + dev = pci_get_drvdata(mei_device); if (!dev) return -ENODEV; mutex_lock(&dev->device_lock); - if (dev->dev_state != MEI_DEV_ENABLED) { + if (dev->mei_state != MEI_ENABLED) { dev_dbg(&dev->pdev->dev, - "wd: dev_state != MEI_DEV_ENABLED dev_state = %s\n", - mei_dev_state_str(dev->dev_state)); + "wd: mei_state != MEI_ENABLED mei_state = %d\n", + dev->mei_state); goto end_unlock; } @@ -231,13 +233,13 @@ static int mei_wd_ops_start(struct watchdog_device *wd_dev) static int mei_wd_ops_stop(struct watchdog_device *wd_dev) { struct mei_device *dev; + dev = pci_get_drvdata(mei_device); - dev = watchdog_get_drvdata(wd_dev); if (!dev) return -ENODEV; mutex_lock(&dev->device_lock); - mei_wd_stop(dev); + mei_wd_stop(dev, false); mutex_unlock(&dev->device_lock); return 0; @@ -254,8 +256,8 @@ static int mei_wd_ops_ping(struct watchdog_device *wd_dev) { int ret = 0; struct mei_device *dev; + dev = pci_get_drvdata(mei_device); - dev = watchdog_get_drvdata(wd_dev); if (!dev) return -ENODEV; @@ -267,8 +269,6 @@ static int mei_wd_ops_ping(struct watchdog_device *wd_dev) goto end; } - dev->wd_state = MEI_WD_RUNNING; - /* Check if we can send the ping to HW*/ if (dev->mei_host_buffer_is_empty && mei_flow_ctrl_creds(dev, &dev->wd_cl) > 0) { @@ -309,13 +309,13 @@ static int mei_wd_ops_ping(struct watchdog_device *wd_dev) static int mei_wd_ops_set_timeout(struct watchdog_device *wd_dev, unsigned int timeout) { struct mei_device *dev; + dev = pci_get_drvdata(mei_device); - dev = watchdog_get_drvdata(wd_dev); if (!dev) return -ENODEV; /* Check Timeout value */ - if (timeout < MEI_WD_MIN_TIMEOUT || timeout > MEI_WD_MAX_TIMEOUT) + if (timeout < AMT_WD_MIN_TIMEOUT || timeout > AMT_WD_MAX_TIMEOUT) return -EINVAL; mutex_lock(&dev->device_lock); @@ -341,42 +341,37 @@ static const struct watchdog_ops wd_ops = { }; static const struct watchdog_info wd_info = { .identity = INTEL_AMT_WATCHDOG_ID, - .options = WDIOF_KEEPALIVEPING | - WDIOF_SETTIMEOUT | - WDIOF_ALARMONLY, + .options = WDIOF_KEEPALIVEPING | WDIOF_ALARMONLY, }; static struct watchdog_device amt_wd_dev = { .info = &wd_info, .ops = &wd_ops, - .timeout = MEI_WD_DEFAULT_TIMEOUT, - .min_timeout = MEI_WD_MIN_TIMEOUT, - .max_timeout = MEI_WD_MAX_TIMEOUT, + .timeout = AMT_WD_DEFAULT_TIMEOUT, + .min_timeout = AMT_WD_MIN_TIMEOUT, + .max_timeout = AMT_WD_MAX_TIMEOUT, }; -void mei_watchdog_register(struct mei_device *dev) +void mei_watchdog_register(struct mei_device *dev) { + dev_dbg(&dev->pdev->dev, "dev->wd_timeout =%d.\n", dev->wd_timeout); + if (watchdog_register_device(&amt_wd_dev)) { dev_err(&dev->pdev->dev, "wd: unable to register watchdog device.\n"); dev->wd_interface_reg = false; - return; + } else { + dev_dbg(&dev->pdev->dev, + "wd: successfully register watchdog interface.\n"); + dev->wd_interface_reg = true; } - - dev_dbg(&dev->pdev->dev, - "wd: successfully register watchdog interface.\n"); - dev->wd_interface_reg = true; - watchdog_set_drvdata(&amt_wd_dev, dev); } void mei_watchdog_unregister(struct mei_device *dev) { - if (!dev->wd_interface_reg) - return; - - watchdog_set_drvdata(&amt_wd_dev, NULL); - watchdog_unregister_device(&amt_wd_dev); + if (dev->wd_interface_reg) + watchdog_unregister_device(&amt_wd_dev); dev->wd_interface_reg = false; } diff --git a/trunk/drivers/misc/pch_phub.c b/trunk/drivers/misc/pch_phub.c index c9f20dae1855..9fbcacd703d5 100644 --- a/trunk/drivers/misc/pch_phub.c +++ b/trunk/drivers/misc/pch_phub.c @@ -699,7 +699,7 @@ static int __devinit pch_phub_probe(struct pci_dev *pdev, chip->pch_phub_base_address = pci_iomap(pdev, 1, 0); - if (chip->pch_phub_base_address == NULL) { + if (chip->pch_phub_base_address == 0) { dev_err(&pdev->dev, "%s : pci_iomap FAILED", __func__); ret = -ENOMEM; goto err_pci_iomap; @@ -893,7 +893,18 @@ static struct pci_driver pch_phub_driver = { .resume = pch_phub_resume }; -module_pci_driver(pch_phub_driver); +static int __init pch_phub_pci_init(void) +{ + return pci_register_driver(&pch_phub_driver); +} + +static void __exit pch_phub_pci_exit(void) +{ + pci_unregister_driver(&pch_phub_driver); +} + +module_init(pch_phub_pci_init); +module_exit(pch_phub_pci_exit); MODULE_DESCRIPTION("Intel EG20T PCH/LAPIS Semiconductor IOH(ML7213/ML7223) PHUB"); MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/misc/pti.c b/trunk/drivers/misc/pti.c index 4999b34b7a60..b7eb545394b1 100644 --- a/trunk/drivers/misc/pti.c +++ b/trunk/drivers/misc/pti.c @@ -60,7 +60,7 @@ struct pti_tty { }; struct pti_dev { - struct tty_port port[PTITTY_MINOR_NUM]; + struct tty_port port; unsigned long pti_addr; unsigned long aperture_base; void __iomem *pti_ioaddr; @@ -76,7 +76,7 @@ struct pti_dev { */ static DEFINE_MUTEX(alloclock); -static const struct pci_device_id pci_ids[] __devinitconst = { +static struct pci_device_id pci_ids[] __devinitconst = { {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x82B)}, {0} }; @@ -393,6 +393,25 @@ void pti_writedata(struct pti_masterchannel *mc, u8 *buf, int count) } EXPORT_SYMBOL_GPL(pti_writedata); +/** + * pti_pci_remove()- Driver exit method to remove PTI from + * PCI bus. + * @pdev: variable containing pci info of PTI. + */ +static void __devexit pti_pci_remove(struct pci_dev *pdev) +{ + struct pti_dev *drv_data; + + drv_data = pci_get_drvdata(pdev); + if (drv_data != NULL) { + pci_iounmap(pdev, drv_data->pti_ioaddr); + pci_set_drvdata(pdev, NULL); + kfree(drv_data); + pci_release_region(pdev, 1); + pci_disable_device(pdev); + } +} + /* * for the tty_driver_*() basic function descriptions, see tty_driver.h. * Specific header comments made for PTI-related specifics. @@ -427,7 +446,7 @@ static int pti_tty_driver_open(struct tty_struct *tty, struct file *filp) * also removes a locking requirement for the actual write * procedure. */ - return tty_port_open(tty->port, tty, filp); + return tty_port_open(&drv_data->port, tty, filp); } /** @@ -443,7 +462,7 @@ static int pti_tty_driver_open(struct tty_struct *tty, struct file *filp) */ static void pti_tty_driver_close(struct tty_struct *tty, struct file *filp) { - tty_port_close(tty->port, tty, filp); + tty_port_close(&drv_data->port, tty, filp); } /** @@ -799,7 +818,6 @@ static const struct tty_port_operations tty_port_ops = { static int __devinit pti_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { - unsigned int a; int retval = -EINVAL; int pci_bar = 1; @@ -812,7 +830,7 @@ static int __devinit pti_pci_probe(struct pci_dev *pdev, __func__, __LINE__); pr_err("%s(%d): Error value returned: %d\n", __func__, __LINE__, retval); - goto err; + return retval; } retval = pci_enable_device(pdev); @@ -820,16 +838,17 @@ static int __devinit pti_pci_probe(struct pci_dev *pdev, dev_err(&pdev->dev, "%s: pci_enable_device() returned error %d\n", __func__, retval); - goto err_unreg_misc; + return retval; } drv_data = kzalloc(sizeof(*drv_data), GFP_KERNEL); + if (drv_data == NULL) { retval = -ENOMEM; dev_err(&pdev->dev, "%s(%d): kmalloc() returned NULL memory.\n", __func__, __LINE__); - goto err_disable_pci; + return retval; } drv_data->pti_addr = pci_resource_start(pdev, pci_bar); @@ -838,65 +857,33 @@ static int __devinit pti_pci_probe(struct pci_dev *pdev, dev_err(&pdev->dev, "%s(%d): pci_request_region() returned error %d\n", __func__, __LINE__, retval); - goto err_free_dd; + kfree(drv_data); + return retval; } drv_data->aperture_base = drv_data->pti_addr+APERTURE_14; drv_data->pti_ioaddr = ioremap_nocache((u32)drv_data->aperture_base, APERTURE_LEN); if (!drv_data->pti_ioaddr) { + pci_release_region(pdev, pci_bar); retval = -ENOMEM; - goto err_rel_reg; + kfree(drv_data); + return retval; } pci_set_drvdata(pdev, drv_data); - for (a = 0; a < PTITTY_MINOR_NUM; a++) { - struct tty_port *port = &drv_data->port[a]; - tty_port_init(port); - port->ops = &tty_port_ops; + tty_port_init(&drv_data->port); + drv_data->port.ops = &tty_port_ops; - tty_port_register_device(port, pti_tty_driver, a, &pdev->dev); - } + tty_register_device(pti_tty_driver, 0, &pdev->dev); + tty_register_device(pti_tty_driver, 1, &pdev->dev); register_console(&pti_console); - return 0; -err_rel_reg: - pci_release_region(pdev, pci_bar); -err_free_dd: - kfree(drv_data); -err_disable_pci: - pci_disable_device(pdev); -err_unreg_misc: - misc_deregister(&pti_char_driver); -err: return retval; } -/** - * pti_pci_remove()- Driver exit method to remove PTI from - * PCI bus. - * @pdev: variable containing pci info of PTI. - */ -static void __devexit pti_pci_remove(struct pci_dev *pdev) -{ - struct pti_dev *drv_data = pci_get_drvdata(pdev); - - unregister_console(&pti_console); - - tty_unregister_device(pti_tty_driver, 0); - tty_unregister_device(pti_tty_driver, 1); - - iounmap(drv_data->pti_ioaddr); - pci_set_drvdata(pdev, NULL); - kfree(drv_data); - pci_release_region(pdev, 1); - pci_disable_device(pdev); - - misc_deregister(&pti_char_driver); -} - static struct pci_driver pti_pci_driver = { .name = PCINAME, .id_table = pci_ids, @@ -946,24 +933,25 @@ static int __init pti_init(void) pr_err("%s(%d): Error value returned: %d\n", __func__, __LINE__, retval); - goto put_tty; + pti_tty_driver = NULL; + return retval; } retval = pci_register_driver(&pti_pci_driver); + if (retval) { pr_err("%s(%d): PCI registration failed of pti driver\n", __func__, __LINE__); pr_err("%s(%d): Error value returned: %d\n", __func__, __LINE__, retval); - goto unreg_tty; + + tty_unregister_driver(pti_tty_driver); + pr_err("%s(%d): Unregistering TTY part of pti driver\n", + __func__, __LINE__); + pti_tty_driver = NULL; + return retval; } - return 0; -unreg_tty: - tty_unregister_driver(pti_tty_driver); -put_tty: - put_tty_driver(pti_tty_driver); - pti_tty_driver = NULL; return retval; } @@ -972,9 +960,31 @@ static int __init pti_init(void) */ static void __exit pti_exit(void) { - tty_unregister_driver(pti_tty_driver); + int retval; + + tty_unregister_device(pti_tty_driver, 0); + tty_unregister_device(pti_tty_driver, 1); + + retval = tty_unregister_driver(pti_tty_driver); + if (retval) { + pr_err("%s(%d): TTY unregistration failed of pti driver\n", + __func__, __LINE__); + pr_err("%s(%d): Error value returned: %d\n", + __func__, __LINE__, retval); + } + pci_unregister_driver(&pti_pci_driver); - put_tty_driver(pti_tty_driver); + + retval = misc_deregister(&pti_char_driver); + if (retval) { + pr_err("%s(%d): CHAR unregistration failed of pti driver\n", + __func__, __LINE__); + pr_err("%s(%d): Error value returned: %d\n", + __func__, __LINE__, retval); + } + + unregister_console(&pti_console); + return; } module_init(pti_init); diff --git a/trunk/drivers/misc/sgi-xp/xpc_uv.c b/trunk/drivers/misc/sgi-xp/xpc_uv.c index b9e2000969f0..87b251ab6ec5 100644 --- a/trunk/drivers/misc/sgi-xp/xpc_uv.c +++ b/trunk/drivers/misc/sgi-xp/xpc_uv.c @@ -18,8 +18,6 @@ #include #include #include -#include -#include #include #include #include @@ -61,8 +59,6 @@ static struct xpc_heartbeat_uv *xpc_heartbeat_uv; XPC_NOTIFY_MSG_SIZE_UV) #define XPC_NOTIFY_IRQ_NAME "xpc_notify" -static int xpc_mq_node = -1; - static struct xpc_gru_mq_uv *xpc_activate_mq_uv; static struct xpc_gru_mq_uv *xpc_notify_mq_uv; @@ -113,8 +109,11 @@ xpc_get_gru_mq_irq_uv(struct xpc_gru_mq_uv *mq, int cpu, char *irq_name) #if defined CONFIG_X86_64 mq->irq = uv_setup_irq(irq_name, cpu, mq->mmr_blade, mq->mmr_offset, UV_AFFINITY_CPU); - if (mq->irq < 0) + if (mq->irq < 0) { + dev_err(xpc_part, "uv_setup_irq() returned error=%d\n", + -mq->irq); return mq->irq; + } mq->mmr_value = uv_read_global_mmr64(mmr_pnode, mq->mmr_offset); @@ -239,9 +238,8 @@ xpc_create_gru_mq_uv(unsigned int mq_size, int cpu, char *irq_name, mq->mmr_blade = uv_cpu_to_blade_id(cpu); nid = cpu_to_node(cpu); - page = alloc_pages_exact_node(nid, - GFP_KERNEL | __GFP_ZERO | GFP_THISNODE, - pg_order); + page = alloc_pages_exact_node(nid, GFP_KERNEL | __GFP_ZERO | GFP_THISNODE, + pg_order); if (page == NULL) { dev_err(xpc_part, "xpc_create_gru_mq_uv() failed to alloc %d " "bytes of memory on nid=%d for GRU mq\n", mq_size, nid); @@ -1733,50 +1731,9 @@ static struct xpc_arch_operations xpc_arch_ops_uv = { .notify_senders_of_disconnect = xpc_notify_senders_of_disconnect_uv, }; -static int -xpc_init_mq_node(int nid) -{ - int cpu; - - get_online_cpus(); - - for_each_cpu(cpu, cpumask_of_node(nid)) { - xpc_activate_mq_uv = - xpc_create_gru_mq_uv(XPC_ACTIVATE_MQ_SIZE_UV, nid, - XPC_ACTIVATE_IRQ_NAME, - xpc_handle_activate_IRQ_uv); - if (!IS_ERR(xpc_activate_mq_uv)) - break; - } - if (IS_ERR(xpc_activate_mq_uv)) { - put_online_cpus(); - return PTR_ERR(xpc_activate_mq_uv); - } - - for_each_cpu(cpu, cpumask_of_node(nid)) { - xpc_notify_mq_uv = - xpc_create_gru_mq_uv(XPC_NOTIFY_MQ_SIZE_UV, nid, - XPC_NOTIFY_IRQ_NAME, - xpc_handle_notify_IRQ_uv); - if (!IS_ERR(xpc_notify_mq_uv)) - break; - } - if (IS_ERR(xpc_notify_mq_uv)) { - xpc_destroy_gru_mq_uv(xpc_activate_mq_uv); - put_online_cpus(); - return PTR_ERR(xpc_notify_mq_uv); - } - - put_online_cpus(); - return 0; -} - int xpc_init_uv(void) { - int nid; - int ret = 0; - xpc_arch_ops = xpc_arch_ops_uv; if (sizeof(struct xpc_notify_mq_msghdr_uv) > XPC_MSG_HDR_MAX_SIZE) { @@ -1785,21 +1742,21 @@ xpc_init_uv(void) return -E2BIG; } - if (xpc_mq_node < 0) - for_each_online_node(nid) { - ret = xpc_init_mq_node(nid); - - if (!ret) - break; - } - else - ret = xpc_init_mq_node(xpc_mq_node); + xpc_activate_mq_uv = xpc_create_gru_mq_uv(XPC_ACTIVATE_MQ_SIZE_UV, 0, + XPC_ACTIVATE_IRQ_NAME, + xpc_handle_activate_IRQ_uv); + if (IS_ERR(xpc_activate_mq_uv)) + return PTR_ERR(xpc_activate_mq_uv); - if (ret < 0) - dev_err(xpc_part, "xpc_init_mq_node() returned error=%d\n", - -ret); + xpc_notify_mq_uv = xpc_create_gru_mq_uv(XPC_NOTIFY_MQ_SIZE_UV, 0, + XPC_NOTIFY_IRQ_NAME, + xpc_handle_notify_IRQ_uv); + if (IS_ERR(xpc_notify_mq_uv)) { + xpc_destroy_gru_mq_uv(xpc_activate_mq_uv); + return PTR_ERR(xpc_notify_mq_uv); + } - return ret; + return 0; } void @@ -1808,6 +1765,3 @@ xpc_exit_uv(void) xpc_destroy_gru_mq_uv(xpc_notify_mq_uv); xpc_destroy_gru_mq_uv(xpc_activate_mq_uv); } - -module_param(xpc_mq_node, int, 0); -MODULE_PARM_DESC(xpc_mq_node, "Node number on which to allocate message queues."); diff --git a/trunk/drivers/misc/ti-st/st_core.c b/trunk/drivers/misc/ti-st/st_core.c index 46937b107261..acfaeeb9e01a 100644 --- a/trunk/drivers/misc/ti-st/st_core.c +++ b/trunk/drivers/misc/ti-st/st_core.c @@ -30,13 +30,11 @@ #include -extern void st_kim_recv(void *, const unsigned char *, long); -void st_int_recv(void *, const unsigned char *, long); /* function pointer pointing to either, * st_kim_recv during registration to receive fw download responses * st_int_recv after registration to receive proto stack responses */ -static void (*st_recv) (void *, const unsigned char *, long); +void (*st_recv) (void*, const unsigned char*, long); /********************************************************************/ static void add_channel_to_table(struct st_data_s *st_gdata, @@ -102,7 +100,7 @@ int st_int_write(struct st_data_s *st_gdata, * push the skb received to relevant * protocol stacks */ -static void st_send_frame(unsigned char chnl_id, struct st_data_s *st_gdata) +void st_send_frame(unsigned char chnl_id, struct st_data_s *st_gdata) { pr_debug(" %s(prot:%d) ", __func__, chnl_id); @@ -142,7 +140,7 @@ static void st_send_frame(unsigned char chnl_id, struct st_data_s *st_gdata) * This function is being called with spin lock held, protocol drivers are * only expected to complete their waits and do nothing more than that. */ -static void st_reg_complete(struct st_data_s *st_gdata, char err) +void st_reg_complete(struct st_data_s *st_gdata, char err) { unsigned char i = 0; pr_info(" %s ", __func__); @@ -381,7 +379,7 @@ void st_int_recv(void *disc_data, * completely, return that skb which has the pending data. * In normal cases, return top of txq. */ -static struct sk_buff *st_int_dequeue(struct st_data_s *st_gdata) +struct sk_buff *st_int_dequeue(struct st_data_s *st_gdata) { struct sk_buff *returning_skb; @@ -403,7 +401,7 @@ static struct sk_buff *st_int_dequeue(struct st_data_s *st_gdata) * txq and waitq needs protection since the other contexts * may be sending data, waking up chip. */ -static void st_int_enqueue(struct st_data_s *st_gdata, struct sk_buff *skb) +void st_int_enqueue(struct st_data_s *st_gdata, struct sk_buff *skb) { unsigned long flags = 0; diff --git a/trunk/drivers/misc/ti-st/st_kim.c b/trunk/drivers/misc/ti-st/st_kim.c index 04a819944f6b..7c14f8fd98db 100644 --- a/trunk/drivers/misc/ti-st/st_kim.c +++ b/trunk/drivers/misc/ti-st/st_kim.c @@ -63,27 +63,10 @@ static struct platform_device *st_get_plat_device(int id) * in case of error don't complete so that waiting for proper * response times out */ -static void validate_firmware_response(struct kim_data_s *kim_gdata) +void validate_firmware_response(struct kim_data_s *kim_gdata) { struct sk_buff *skb = kim_gdata->rx_skb; - if (!skb) - return; - - /* these magic numbers are the position in the response buffer which - * allows us to distinguish whether the response is for the read - * version info. command - */ - if (skb->data[2] == 0x01 && skb->data[3] == 0x01 && - skb->data[4] == 0x10 && skb->data[5] == 0x00) { - /* fw version response */ - memcpy(kim_gdata->resp_buffer, - kim_gdata->rx_skb->data, - kim_gdata->rx_skb->len); - complete_all(&kim_gdata->kim_rcvd); - kim_gdata->rx_state = ST_W4_PACKET_TYPE; - kim_gdata->rx_skb = NULL; - kim_gdata->rx_count = 0; - } else if (unlikely(skb->data[5] != 0)) { + if (unlikely(skb->data[5] != 0)) { pr_err("no proper response during fw download"); pr_err("data6 %x", skb->data[5]); kfree_skb(skb); @@ -136,7 +119,7 @@ static inline int kim_check_data_len(struct kim_data_s *kim_gdata, int len) * have been observed to come in bursts of different * tty_receive and hence the logic */ -static void kim_int_recv(struct kim_data_s *kim_gdata, +void kim_int_recv(struct kim_data_s *kim_gdata, const unsigned char *data, long count) { const unsigned char *ptr; @@ -224,19 +207,16 @@ static long read_local_version(struct kim_data_s *kim_gdata, char *bts_scr_name) return -EIO; } - if (!wait_for_completion_interruptible_timeout( - &kim_gdata->kim_rcvd, msecs_to_jiffies(CMD_RESP_TIME))) { + if (!wait_for_completion_timeout + (&kim_gdata->kim_rcvd, msecs_to_jiffies(CMD_RESP_TIME))) { pr_err(" waiting for ver info- timed out "); return -ETIMEDOUT; } INIT_COMPLETION(kim_gdata->kim_rcvd); - /* the positions 12 & 13 in the response buffer provide with the - * chip, major & minor numbers - */ version = - MAKEWORD(kim_gdata->resp_buffer[12], - kim_gdata->resp_buffer[13]); + MAKEWORD(kim_gdata->resp_buffer[13], + kim_gdata->resp_buffer[14]); chip = (version & 0x7C00) >> 10; min_ver = (version & 0x007F); maj_ver = (version & 0x0380) >> 7; @@ -256,7 +236,7 @@ static long read_local_version(struct kim_data_s *kim_gdata, char *bts_scr_name) return 0; } -static void skip_change_remote_baud(unsigned char **ptr, long *len) +void skip_change_remote_baud(unsigned char **ptr, long *len) { unsigned char *nxt_action, *cur_action; cur_action = *ptr; @@ -390,9 +370,9 @@ static long download_firmware(struct kim_data_s *kim_gdata) break; case ACTION_WAIT_EVENT: /* wait */ pr_debug("W"); - if (!wait_for_completion_interruptible_timeout( - &kim_gdata->kim_rcvd, - msecs_to_jiffies(CMD_RESP_TIME))) { + if (!wait_for_completion_timeout + (&kim_gdata->kim_rcvd, + msecs_to_jiffies(CMD_RESP_TIME))) { pr_err("response timeout during fw download "); /* timed out */ release_firmware(kim_gdata->fw_entry); @@ -430,10 +410,16 @@ void st_kim_recv(void *disc_data, const unsigned char *data, long count) struct st_data_s *st_gdata = (struct st_data_s *)disc_data; struct kim_data_s *kim_gdata = st_gdata->kim_data; - /* proceed to gather all data and distinguish read fw version response - * from other fw responses when data gathering is complete - */ - kim_int_recv(kim_gdata, data, count); + /* copy to local buffer */ + if (unlikely(data[4] == 0x01 && data[5] == 0x10 && data[0] == 0x04)) { + /* must be the read_ver_cmd */ + memcpy(kim_gdata->resp_buffer, data, count); + complete_all(&kim_gdata->kim_rcvd); + return; + } else { + kim_int_recv(kim_gdata, data, count); + /* either completes or times out */ + } return; } @@ -468,6 +454,11 @@ long st_kim_start(void *kim_data) if (pdata->chip_enable) pdata->chip_enable(kim_gdata); + /* Configure BT nShutdown to HIGH state */ + gpio_set_value(kim_gdata->nshutdown, GPIO_LOW); + mdelay(5); /* FIXME: a proper toggle */ + gpio_set_value(kim_gdata->nshutdown, GPIO_HIGH); + mdelay(100); /* re-initialize the completion */ INIT_COMPLETION(kim_gdata->ldisc_installed); /* send notification to UIM */ @@ -476,8 +467,8 @@ long st_kim_start(void *kim_data) sysfs_notify(&kim_gdata->kim_pdev->dev.kobj, NULL, "install"); /* wait for ldisc to be installed */ - err = wait_for_completion_interruptible_timeout( - &kim_gdata->ldisc_installed, msecs_to_jiffies(LDISC_TIME)); + err = wait_for_completion_timeout(&kim_gdata->ldisc_installed, + msecs_to_jiffies(LDISC_TIME)); if (!err) { /* ldisc installation timeout, * flush uart, power cycle BT_EN */ @@ -509,7 +500,8 @@ long st_kim_start(void *kim_data) * (b) upon failure to either install ldisc or download firmware. * The function is responsible to (a) notify UIM about un-installation, * (b) flush UART if the ldisc was installed. - * (c) invoke platform's chip disabling routine. + * (c) reset BT_EN - pull down nshutdown at the end. + * (d) invoke platform's chip disabling routine. */ long st_kim_stop(void *kim_data) { @@ -534,13 +526,20 @@ long st_kim_stop(void *kim_data) sysfs_notify(&kim_gdata->kim_pdev->dev.kobj, NULL, "install"); /* wait for ldisc to be un-installed */ - err = wait_for_completion_interruptible_timeout( - &kim_gdata->ldisc_installed, msecs_to_jiffies(LDISC_TIME)); + err = wait_for_completion_timeout(&kim_gdata->ldisc_installed, + msecs_to_jiffies(LDISC_TIME)); if (!err) { /* timeout */ pr_err(" timed out waiting for ldisc to be un-installed"); - err = -ETIMEDOUT; + return -ETIMEDOUT; } + /* By default configure BT nShutdown to LOW state */ + gpio_set_value(kim_gdata->nshutdown, GPIO_LOW); + mdelay(1); + gpio_set_value(kim_gdata->nshutdown, GPIO_HIGH); + mdelay(1); + gpio_set_value(kim_gdata->nshutdown, GPIO_LOW); + /* platform specific disable */ if (pdata->chip_disable) pdata->chip_disable(kim_gdata); @@ -702,7 +701,7 @@ static const struct file_operations list_debugfs_fops = { * board-*.c file */ -static struct dentry *kim_debugfs_dir; +struct dentry *kim_debugfs_dir; static int kim_probe(struct platform_device *pdev) { long status; @@ -732,6 +731,20 @@ static int kim_probe(struct platform_device *pdev) /* refer to itself */ kim_gdata->core_data->kim_data = kim_gdata; + /* Claim the chip enable nShutdown gpio from the system */ + kim_gdata->nshutdown = pdata->nshutdown_gpio; + status = gpio_request(kim_gdata->nshutdown, "kim"); + if (unlikely(status)) { + pr_err(" gpio %ld request failed ", kim_gdata->nshutdown); + return status; + } + + /* Configure nShutdown GPIO as output=0 */ + status = gpio_direction_output(kim_gdata->nshutdown, 0); + if (unlikely(status)) { + pr_err(" unable to configure gpio %ld", kim_gdata->nshutdown); + return status; + } /* get reference of pdev for request_firmware */ kim_gdata->kim_pdev = pdev; @@ -767,10 +780,18 @@ static int kim_probe(struct platform_device *pdev) static int kim_remove(struct platform_device *pdev) { + /* free the GPIOs requested */ + struct ti_st_plat_data *pdata = pdev->dev.platform_data; struct kim_data_s *kim_gdata; kim_gdata = dev_get_drvdata(&pdev->dev); + /* Free the Bluetooth/FM/GPIO + * nShutdown gpio from the system + */ + gpio_free(pdata->nshutdown_gpio); + pr_info("nshutdown GPIO Freed"); + debugfs_remove_recursive(kim_debugfs_dir); sysfs_remove_group(&pdev->dev.kobj, &uim_attr_grp); pr_info("sysfs entries removed"); @@ -783,7 +804,7 @@ static int kim_remove(struct platform_device *pdev) return 0; } -static int kim_suspend(struct platform_device *pdev, pm_message_t state) +int kim_suspend(struct platform_device *pdev, pm_message_t state) { struct ti_st_plat_data *pdata = pdev->dev.platform_data; @@ -793,7 +814,7 @@ static int kim_suspend(struct platform_device *pdev, pm_message_t state) return -EOPNOTSUPP; } -static int kim_resume(struct platform_device *pdev) +int kim_resume(struct platform_device *pdev) { struct ti_st_plat_data *pdata = pdev->dev.platform_data; diff --git a/trunk/drivers/misc/ti-st/st_ll.c b/trunk/drivers/misc/ti-st/st_ll.c index 93b4d67cc4a3..1ff460a8e9c7 100644 --- a/trunk/drivers/misc/ti-st/st_ll.c +++ b/trunk/drivers/misc/ti-st/st_ll.c @@ -87,7 +87,7 @@ static void ll_device_want_to_wakeup(struct st_data_s *st_data) /* communicate to platform about chip wakeup */ kim_data = st_data->kim_data; pdata = kim_data->kim_pdev->dev.platform_data; - if (pdata->chip_awake) + if (pdata->chip_asleep) pdata->chip_awake(NULL); } diff --git a/trunk/drivers/misc/tifm_7xx1.c b/trunk/drivers/misc/tifm_7xx1.c index f8d6654391e5..ba2479022670 100644 --- a/trunk/drivers/misc/tifm_7xx1.c +++ b/trunk/drivers/misc/tifm_7xx1.c @@ -434,9 +434,21 @@ static struct pci_driver tifm_7xx1_driver = { .resume = tifm_7xx1_resume, }; -module_pci_driver(tifm_7xx1_driver); +static int __init tifm_7xx1_init(void) +{ + return pci_register_driver(&tifm_7xx1_driver); +} + +static void __exit tifm_7xx1_exit(void) +{ + pci_unregister_driver(&tifm_7xx1_driver); +} + MODULE_AUTHOR("Alex Dubov"); MODULE_DESCRIPTION("TI FlashMedia host driver"); MODULE_LICENSE("GPL"); MODULE_DEVICE_TABLE(pci, tifm_7xx1_pci_tbl); MODULE_VERSION(DRIVER_VERSION); + +module_init(tifm_7xx1_init); +module_exit(tifm_7xx1_exit); diff --git a/trunk/drivers/mmc/card/block.c b/trunk/drivers/mmc/card/block.c index 172a768036d8..f1c84decb192 100644 --- a/trunk/drivers/mmc/card/block.c +++ b/trunk/drivers/mmc/card/block.c @@ -1411,8 +1411,7 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) /* complete ongoing async transfer before issuing discard */ if (card->host->areq) mmc_blk_issue_rw_rq(mq, NULL); - if (req->cmd_flags & REQ_SECURE && - !(card->quirks & MMC_QUIRK_SEC_ERASE_TRIM_BROKEN)) + if (req->cmd_flags & REQ_SECURE) ret = mmc_blk_issue_secdiscard_rq(mq, req); else ret = mmc_blk_issue_discard_rq(mq, req); @@ -1717,7 +1716,6 @@ static int mmc_add_disk(struct mmc_blk_data *md) #define CID_MANFID_SANDISK 0x2 #define CID_MANFID_TOSHIBA 0x11 #define CID_MANFID_MICRON 0x13 -#define CID_MANFID_SAMSUNG 0x15 static const struct mmc_fixup blk_fixups[] = { @@ -1754,28 +1752,6 @@ static const struct mmc_fixup blk_fixups[] = MMC_FIXUP(CID_NAME_ANY, CID_MANFID_MICRON, 0x200, add_quirk_mmc, MMC_QUIRK_LONG_READ_TIME), - /* - * On these Samsung MoviNAND parts, performing secure erase or - * secure trim can result in unrecoverable corruption due to a - * firmware bug. - */ - MMC_FIXUP("M8G2FA", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc, - MMC_QUIRK_SEC_ERASE_TRIM_BROKEN), - MMC_FIXUP("MAG4FA", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc, - MMC_QUIRK_SEC_ERASE_TRIM_BROKEN), - MMC_FIXUP("MBG8FA", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc, - MMC_QUIRK_SEC_ERASE_TRIM_BROKEN), - MMC_FIXUP("MCGAFA", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc, - MMC_QUIRK_SEC_ERASE_TRIM_BROKEN), - MMC_FIXUP("VAL00M", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc, - MMC_QUIRK_SEC_ERASE_TRIM_BROKEN), - MMC_FIXUP("VYL00M", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc, - MMC_QUIRK_SEC_ERASE_TRIM_BROKEN), - MMC_FIXUP("KYL00M", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc, - MMC_QUIRK_SEC_ERASE_TRIM_BROKEN), - MMC_FIXUP("VZL00M", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc, - MMC_QUIRK_SEC_ERASE_TRIM_BROKEN), - END_FIXUP }; diff --git a/trunk/drivers/mmc/card/sdio_uart.c b/trunk/drivers/mmc/card/sdio_uart.c index d2339ea37815..5a2cbfac66d2 100644 --- a/trunk/drivers/mmc/card/sdio_uart.c +++ b/trunk/drivers/mmc/card/sdio_uart.c @@ -518,7 +518,7 @@ static void sdio_uart_check_modem_status(struct sdio_uart_port *port) if (status & UART_MSR_DCTS) { port->icount.cts++; tty = tty_port_tty_get(&port->port); - if (tty && (tty->termios.c_cflag & CRTSCTS)) { + if (tty && (tty->termios->c_cflag & CRTSCTS)) { int cts = (status & UART_MSR_CTS); if (tty->hw_stopped) { if (cts) { @@ -671,12 +671,12 @@ static int sdio_uart_activate(struct tty_port *tport, struct tty_struct *tty) port->ier = UART_IER_RLSI|UART_IER_RDI|UART_IER_RTOIE|UART_IER_UUE; port->mctrl = TIOCM_OUT2; - sdio_uart_change_speed(port, &tty->termios, NULL); + sdio_uart_change_speed(port, tty->termios, NULL); - if (tty->termios.c_cflag & CBAUD) + if (tty->termios->c_cflag & CBAUD) sdio_uart_set_mctrl(port, TIOCM_RTS | TIOCM_DTR); - if (tty->termios.c_cflag & CRTSCTS) + if (tty->termios->c_cflag & CRTSCTS) if (!(sdio_uart_get_mctrl(port) & TIOCM_CTS)) tty->hw_stopped = 1; @@ -850,7 +850,7 @@ static void sdio_uart_throttle(struct tty_struct *tty) { struct sdio_uart_port *port = tty->driver_data; - if (!I_IXOFF(tty) && !(tty->termios.c_cflag & CRTSCTS)) + if (!I_IXOFF(tty) && !(tty->termios->c_cflag & CRTSCTS)) return; if (sdio_uart_claim_func(port) != 0) @@ -861,7 +861,7 @@ static void sdio_uart_throttle(struct tty_struct *tty) sdio_uart_start_tx(port); } - if (tty->termios.c_cflag & CRTSCTS) + if (tty->termios->c_cflag & CRTSCTS) sdio_uart_clear_mctrl(port, TIOCM_RTS); sdio_uart_irq(port->func); @@ -872,7 +872,7 @@ static void sdio_uart_unthrottle(struct tty_struct *tty) { struct sdio_uart_port *port = tty->driver_data; - if (!I_IXOFF(tty) && !(tty->termios.c_cflag & CRTSCTS)) + if (!I_IXOFF(tty) && !(tty->termios->c_cflag & CRTSCTS)) return; if (sdio_uart_claim_func(port) != 0) @@ -887,7 +887,7 @@ static void sdio_uart_unthrottle(struct tty_struct *tty) } } - if (tty->termios.c_cflag & CRTSCTS) + if (tty->termios->c_cflag & CRTSCTS) sdio_uart_set_mctrl(port, TIOCM_RTS); sdio_uart_irq(port->func); @@ -898,12 +898,12 @@ static void sdio_uart_set_termios(struct tty_struct *tty, struct ktermios *old_termios) { struct sdio_uart_port *port = tty->driver_data; - unsigned int cflag = tty->termios.c_cflag; + unsigned int cflag = tty->termios->c_cflag; if (sdio_uart_claim_func(port) != 0) return; - sdio_uart_change_speed(port, &tty->termios, old_termios); + sdio_uart_change_speed(port, tty->termios, old_termios); /* Handle transition to B0 status */ if ((old_termios->c_cflag & CBAUD) && !(cflag & CBAUD)) @@ -1132,8 +1132,8 @@ static int sdio_uart_probe(struct sdio_func *func, kfree(port); } else { struct device *dev; - dev = tty_port_register_device(&port->port, - sdio_uart_tty_driver, port->index, &func->dev); + dev = tty_register_device(sdio_uart_tty_driver, + port->index, &func->dev); if (IS_ERR(dev)) { sdio_uart_port_remove(port); ret = PTR_ERR(dev); diff --git a/trunk/drivers/mmc/core/sdio.c b/trunk/drivers/mmc/core/sdio.c index 2273ce6b6c1a..d4619e2ec030 100644 --- a/trunk/drivers/mmc/core/sdio.c +++ b/trunk/drivers/mmc/core/sdio.c @@ -641,7 +641,7 @@ static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr, /* * If the host and card support UHS-I mode request the card * to switch to 1.8V signaling level. No 1.8v signalling if - * UHS mode is not enabled to maintain compatibility and some + * UHS mode is not enabled to maintain compatibilty and some * systems that claim 1.8v signalling in fact do not support * it. */ diff --git a/trunk/drivers/mmc/host/at91_mci.c b/trunk/drivers/mmc/host/at91_mci.c index 74bed0fc23e7..efdb81d21c44 100644 --- a/trunk/drivers/mmc/host/at91_mci.c +++ b/trunk/drivers/mmc/host/at91_mci.c @@ -356,7 +356,7 @@ static void at91_mci_handle_transmitted(struct at91mci_host *host) } /* - * Update bytes transfered count during a write operation + * Update bytes tranfered count during a write operation */ static void at91_mci_update_bytes_xfered(struct at91mci_host *host) { diff --git a/trunk/drivers/mmc/host/atmel-mci.c b/trunk/drivers/mmc/host/atmel-mci.c index 852d5fbda630..322412cec4ee 100644 --- a/trunk/drivers/mmc/host/atmel-mci.c +++ b/trunk/drivers/mmc/host/atmel-mci.c @@ -81,7 +81,6 @@ struct atmel_mci_caps { bool has_bad_data_ordering; bool need_reset_after_xfer; bool need_blksz_mul_4; - bool need_notbusy_for_read_ops; }; struct atmel_mci_dma { @@ -1022,7 +1021,7 @@ static void atmci_stop_transfer(struct atmel_mci *host) } /* - * Stop data transfer because error(s) occurred. + * Stop data transfer because error(s) occured. */ static void atmci_stop_transfer_pdc(struct atmel_mci *host) { @@ -1626,8 +1625,7 @@ static void atmci_tasklet_func(unsigned long priv) __func__); atmci_set_completed(host, EVENT_XFER_COMPLETE); - if (host->caps.need_notbusy_for_read_ops || - (host->data->flags & MMC_DATA_WRITE)) { + if (host->data->flags & MMC_DATA_WRITE) { atmci_writel(host, ATMCI_IER, ATMCI_NOTBUSY); state = STATE_WAITING_NOTBUSY; } else if (host->mrq->stop) { @@ -2220,7 +2218,6 @@ static void __init atmci_get_cap(struct atmel_mci *host) host->caps.has_bad_data_ordering = 1; host->caps.need_reset_after_xfer = 1; host->caps.need_blksz_mul_4 = 1; - host->caps.need_notbusy_for_read_ops = 0; /* keep only major version number */ switch (version & 0xf00) { @@ -2241,7 +2238,6 @@ static void __init atmci_get_cap(struct atmel_mci *host) case 0x200: host->caps.has_rwproof = 1; host->caps.need_blksz_mul_4 = 0; - host->caps.need_notbusy_for_read_ops = 1; case 0x100: host->caps.has_bad_data_ordering = 0; host->caps.need_reset_after_xfer = 0; diff --git a/trunk/drivers/mmc/host/bfin_sdh.c b/trunk/drivers/mmc/host/bfin_sdh.c index a17dd7363ceb..03666174ca48 100644 --- a/trunk/drivers/mmc/host/bfin_sdh.c +++ b/trunk/drivers/mmc/host/bfin_sdh.c @@ -49,6 +49,13 @@ #define bfin_write_SDH_CFG bfin_write_RSI_CFG #endif +struct dma_desc_array { + unsigned long start_addr; + unsigned short cfg; + unsigned short x_count; + short x_modify; +} __packed; + struct sdh_host { struct mmc_host *mmc; spinlock_t lock; diff --git a/trunk/drivers/mmc/host/dw_mmc.c b/trunk/drivers/mmc/host/dw_mmc.c index af40d227bece..72dc3cde646d 100644 --- a/trunk/drivers/mmc/host/dw_mmc.c +++ b/trunk/drivers/mmc/host/dw_mmc.c @@ -627,7 +627,6 @@ static void dw_mci_setup_bus(struct dw_mci_slot *slot) { struct dw_mci *host = slot->host; u32 div; - u32 clk_en_a; if (slot->clock != host->current_speed) { div = host->bus_hz / slot->clock; @@ -660,11 +659,9 @@ static void dw_mci_setup_bus(struct dw_mci_slot *slot) mci_send_cmd(slot, SDMMC_CMD_UPD_CLK | SDMMC_CMD_PRV_DAT_WAIT, 0); - /* enable clock; only low power if no SDIO */ - clk_en_a = SDMMC_CLKEN_ENABLE << slot->id; - if (!(mci_readl(host, INTMASK) & SDMMC_INT_SDIO(slot->id))) - clk_en_a |= SDMMC_CLKEN_LOW_PWR << slot->id; - mci_writel(host, CLKENA, clk_en_a); + /* enable clock */ + mci_writel(host, CLKENA, ((SDMMC_CLKEN_ENABLE | + SDMMC_CLKEN_LOW_PWR) << slot->id)); /* inform CIU */ mci_send_cmd(slot, @@ -865,30 +862,6 @@ static int dw_mci_get_cd(struct mmc_host *mmc) return present; } -/* - * Disable lower power mode. - * - * Low power mode will stop the card clock when idle. According to the - * description of the CLKENA register we should disable low power mode - * for SDIO cards if we need SDIO interrupts to work. - * - * This function is fast if low power mode is already disabled. - */ -static void dw_mci_disable_low_power(struct dw_mci_slot *slot) -{ - struct dw_mci *host = slot->host; - u32 clk_en_a; - const u32 clken_low_pwr = SDMMC_CLKEN_LOW_PWR << slot->id; - - clk_en_a = mci_readl(host, CLKENA); - - if (clk_en_a & clken_low_pwr) { - mci_writel(host, CLKENA, clk_en_a & ~clken_low_pwr); - mci_send_cmd(slot, SDMMC_CMD_UPD_CLK | - SDMMC_CMD_PRV_DAT_WAIT, 0); - } -} - static void dw_mci_enable_sdio_irq(struct mmc_host *mmc, int enb) { struct dw_mci_slot *slot = mmc_priv(mmc); @@ -898,14 +871,6 @@ static void dw_mci_enable_sdio_irq(struct mmc_host *mmc, int enb) /* Enable/disable Slot Specific SDIO interrupt */ int_mask = mci_readl(host, INTMASK); if (enb) { - /* - * Turn off low power mode if it was enabled. This is a bit of - * a heavy operation and we disable / enable IRQs a lot, so - * we'll leave low power mode disabled and it will get - * re-enabled again in dw_mci_setup_bus(). - */ - dw_mci_disable_low_power(slot); - mci_writel(host, INTMASK, (int_mask | SDMMC_INT_SDIO(slot->id))); } else { @@ -1464,10 +1429,22 @@ static void dw_mci_read_data_pio(struct dw_mci *host) nbytes += len; remain -= len; } while (remain); - sg_miter->consumed = offset; + status = mci_readl(host, MINTSTS); mci_writel(host, RINTSTS, SDMMC_INT_RXDR); + if (status & DW_MCI_DATA_ERROR_FLAGS) { + host->data_status = status; + data->bytes_xfered += nbytes; + sg_miter_stop(sg_miter); + host->sg = NULL; + smp_wmb(); + + set_bit(EVENT_DATA_ERROR, &host->pending_events); + + tasklet_schedule(&host->tasklet); + return; + } } while (status & SDMMC_INT_RXDR); /*if the RXDR is ready read again*/ data->bytes_xfered += nbytes; @@ -1520,10 +1497,23 @@ static void dw_mci_write_data_pio(struct dw_mci *host) nbytes += len; remain -= len; } while (remain); - sg_miter->consumed = offset; + status = mci_readl(host, MINTSTS); mci_writel(host, RINTSTS, SDMMC_INT_TXDR); + if (status & DW_MCI_DATA_ERROR_FLAGS) { + host->data_status = status; + data->bytes_xfered += nbytes; + sg_miter_stop(sg_miter); + host->sg = NULL; + + smp_wmb(); + + set_bit(EVENT_DATA_ERROR, &host->pending_events); + + tasklet_schedule(&host->tasklet); + return; + } } while (status & SDMMC_INT_TXDR); /* if TXDR write again */ data->bytes_xfered += nbytes; @@ -1557,11 +1547,12 @@ static void dw_mci_cmd_interrupt(struct dw_mci *host, u32 status) static irqreturn_t dw_mci_interrupt(int irq, void *dev_id) { struct dw_mci *host = dev_id; - u32 pending; + u32 status, pending; unsigned int pass_count = 0; int i; do { + status = mci_readl(host, RINTSTS); pending = mci_readl(host, MINTSTS); /* read-only mask reg */ /* @@ -1579,7 +1570,7 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id) if (pending & DW_MCI_CMD_ERROR_FLAGS) { mci_writel(host, RINTSTS, DW_MCI_CMD_ERROR_FLAGS); - host->cmd_status = pending; + host->cmd_status = status; smp_wmb(); set_bit(EVENT_CMD_COMPLETE, &host->pending_events); } @@ -1587,16 +1578,18 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id) if (pending & DW_MCI_DATA_ERROR_FLAGS) { /* if there is an error report DATA_ERROR */ mci_writel(host, RINTSTS, DW_MCI_DATA_ERROR_FLAGS); - host->data_status = pending; + host->data_status = status; smp_wmb(); set_bit(EVENT_DATA_ERROR, &host->pending_events); - tasklet_schedule(&host->tasklet); + if (!(pending & (SDMMC_INT_DTO | SDMMC_INT_DCRC | + SDMMC_INT_SBE | SDMMC_INT_EBE))) + tasklet_schedule(&host->tasklet); } if (pending & SDMMC_INT_DATA_OVER) { mci_writel(host, RINTSTS, SDMMC_INT_DATA_OVER); if (!host->data_status) - host->data_status = pending; + host->data_status = status; smp_wmb(); if (host->dir_status == DW_MCI_RECV_STATUS) { if (host->sg != NULL) @@ -1620,7 +1613,7 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id) if (pending & SDMMC_INT_CMD_DONE) { mci_writel(host, RINTSTS, SDMMC_INT_CMD_DONE); - dw_mci_cmd_interrupt(host, pending); + dw_mci_cmd_interrupt(host, status); } if (pending & SDMMC_INT_CD) { diff --git a/trunk/drivers/mmc/host/mxs-mmc.c b/trunk/drivers/mmc/host/mxs-mmc.c index ad3fcea1269e..a51f9309ffbb 100644 --- a/trunk/drivers/mmc/host/mxs-mmc.c +++ b/trunk/drivers/mmc/host/mxs-mmc.c @@ -285,11 +285,11 @@ static irqreturn_t mxs_mmc_irq_handler(int irq, void *dev_id) writel(stat & MXS_MMC_IRQ_BITS, host->base + HW_SSP_CTRL1(host) + STMP_OFFSET_REG_CLR); - spin_unlock(&host->lock); - if ((stat & BM_SSP_CTRL1_SDIO_IRQ) && (stat & BM_SSP_CTRL1_SDIO_IRQ_EN)) mmc_signal_sdio_irq(host->mmc); + spin_unlock(&host->lock); + if (stat & BM_SSP_CTRL1_RESP_TIMEOUT_IRQ) cmd->error = -ETIMEDOUT; else if (stat & BM_SSP_CTRL1_RESP_ERR_IRQ) @@ -644,6 +644,11 @@ static void mxs_mmc_enable_sdio_irq(struct mmc_host *mmc, int enable) host->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_SET); writel(BM_SSP_CTRL1_SDIO_IRQ_EN, host->base + HW_SSP_CTRL1(host) + STMP_OFFSET_REG_SET); + + if (readl(host->base + HW_SSP_STATUS(host)) & + BM_SSP_STATUS_SDIO_IRQ) + mmc_signal_sdio_irq(host->mmc); + } else { writel(BM_SSP_CTRL0_SDIO_IRQ_CHECK, host->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_CLR); @@ -652,11 +657,6 @@ static void mxs_mmc_enable_sdio_irq(struct mmc_host *mmc, int enable) } spin_unlock_irqrestore(&host->lock, flags); - - if (enable && readl(host->base + HW_SSP_STATUS(host)) & - BM_SSP_STATUS_SDIO_IRQ) - mmc_signal_sdio_irq(host->mmc); - } static const struct mmc_host_ops mxs_mmc_ops = { diff --git a/trunk/drivers/mmc/host/omap.c b/trunk/drivers/mmc/host/omap.c index a5999a74496a..50e08f03aa65 100644 --- a/trunk/drivers/mmc/host/omap.c +++ b/trunk/drivers/mmc/host/omap.c @@ -668,7 +668,7 @@ mmc_omap_clk_timer(unsigned long data) static void mmc_omap_xfer_data(struct mmc_omap_host *host, int write) { - int n, nwords; + int n; if (host->buffer_bytes_left == 0) { host->sg_idx++; @@ -678,23 +678,15 @@ mmc_omap_xfer_data(struct mmc_omap_host *host, int write) n = 64; if (n > host->buffer_bytes_left) n = host->buffer_bytes_left; - - nwords = n / 2; - nwords += n & 1; /* handle odd number of bytes to transfer */ - host->buffer_bytes_left -= n; host->total_bytes_left -= n; host->data->bytes_xfered += n; if (write) { - __raw_writesw(host->virt_base + OMAP_MMC_REG(host, DATA), - host->buffer, nwords); + __raw_writesw(host->virt_base + OMAP_MMC_REG(host, DATA), host->buffer, n); } else { - __raw_readsw(host->virt_base + OMAP_MMC_REG(host, DATA), - host->buffer, nwords); + __raw_readsw(host->virt_base + OMAP_MMC_REG(host, DATA), host->buffer, n); } - - host->buffer += nwords; } static inline void mmc_omap_report_irq(u16 status) diff --git a/trunk/drivers/mmc/host/omap_hsmmc.c b/trunk/drivers/mmc/host/omap_hsmmc.c index 686e256764c8..3a09f93cc3b6 100644 --- a/trunk/drivers/mmc/host/omap_hsmmc.c +++ b/trunk/drivers/mmc/host/omap_hsmmc.c @@ -447,7 +447,7 @@ static void omap_hsmmc_stop_clock(struct omap_hsmmc_host *host) OMAP_HSMMC_WRITE(host->base, SYSCTL, OMAP_HSMMC_READ(host->base, SYSCTL) & ~CEN); if ((OMAP_HSMMC_READ(host->base, SYSCTL) & CEN) != 0x0) - dev_dbg(mmc_dev(host->mmc), "MMC Clock is not stopped\n"); + dev_dbg(mmc_dev(host->mmc), "MMC Clock is not stoped\n"); } static void omap_hsmmc_enable_irq(struct omap_hsmmc_host *host, diff --git a/trunk/drivers/mmc/host/sdhci-esdhc-imx.c b/trunk/drivers/mmc/host/sdhci-esdhc-imx.c index 32f4a070551f..e23f8134591c 100644 --- a/trunk/drivers/mmc/host/sdhci-esdhc-imx.c +++ b/trunk/drivers/mmc/host/sdhci-esdhc-imx.c @@ -315,7 +315,7 @@ static void esdhc_writeb_le(struct sdhci_host *host, u8 val, int reg) new_val = val & (SDHCI_CTRL_LED | \ SDHCI_CTRL_4BITBUS | \ SDHCI_CTRL_D3CD); - /* ensure the endianness */ + /* ensure the endianess */ new_val |= ESDHC_HOST_CONTROL_LE; /* bits 8&9 are reserved on mx25 */ if (!is_imx25_esdhc(imx_data)) { diff --git a/trunk/drivers/mmc/host/sdhci-esdhc.h b/trunk/drivers/mmc/host/sdhci-esdhc.h index d25f9ab9a54d..b97b2f5dafdb 100644 --- a/trunk/drivers/mmc/host/sdhci-esdhc.h +++ b/trunk/drivers/mmc/host/sdhci-esdhc.h @@ -48,14 +48,14 @@ static inline void esdhc_set_clock(struct sdhci_host *host, unsigned int clock) int div = 1; u32 temp; - if (clock == 0) - goto out; - temp = sdhci_readl(host, ESDHC_SYSTEM_CONTROL); temp &= ~(ESDHC_CLOCK_IPGEN | ESDHC_CLOCK_HCKEN | ESDHC_CLOCK_PEREN | ESDHC_CLOCK_MASK); sdhci_writel(host, temp, ESDHC_SYSTEM_CONTROL); + if (clock == 0) + goto out; + while (host->max_clk / pre_div / 16 > clock && pre_div < 256) pre_div *= 2; diff --git a/trunk/drivers/mmc/host/vub300.c b/trunk/drivers/mmc/host/vub300.c index 58eab9ac1d01..3135a1a5d75d 100644 --- a/trunk/drivers/mmc/host/vub300.c +++ b/trunk/drivers/mmc/host/vub300.c @@ -806,7 +806,7 @@ static void command_res_completed(struct urb *urb) * we suspect a buggy USB host controller */ } else if (!vub300->data) { - /* this means that the command (typically CMD52) succeeded */ + /* this means that the command (typically CMD52) suceeded */ } else if (vub300->resp.common.header_type != 0x02) { /* * this is an error response from the VUB300 chip diff --git a/trunk/drivers/mtd/maps/uclinux.c b/trunk/drivers/mtd/maps/uclinux.c index c3bb304eca07..cfff454f628b 100644 --- a/trunk/drivers/mtd/maps/uclinux.c +++ b/trunk/drivers/mtd/maps/uclinux.c @@ -19,13 +19,14 @@ #include #include #include -#include /****************************************************************************/ +extern char _ebss; + struct map_info uclinux_ram_map = { .name = "RAM", - .phys = (unsigned long)__bss_stop, + .phys = (unsigned long)&_ebss, .size = 0, }; diff --git a/trunk/drivers/mtd/mtdchar.c b/trunk/drivers/mtd/mtdchar.c index a6e74514e662..f2f482bec573 100644 --- a/trunk/drivers/mtd/mtdchar.c +++ b/trunk/drivers/mtd/mtdchar.c @@ -1123,33 +1123,6 @@ static unsigned long mtdchar_get_unmapped_area(struct file *file, } #endif -static inline unsigned long get_vm_size(struct vm_area_struct *vma) -{ - return vma->vm_end - vma->vm_start; -} - -static inline resource_size_t get_vm_offset(struct vm_area_struct *vma) -{ - return (resource_size_t) vma->vm_pgoff << PAGE_SHIFT; -} - -/* - * Set a new vm offset. - * - * Verify that the incoming offset really works as a page offset, - * and that the offset and size fit in a resource_size_t. - */ -static inline int set_vm_offset(struct vm_area_struct *vma, resource_size_t off) -{ - pgoff_t pgoff = off >> PAGE_SHIFT; - if (off != (resource_size_t) pgoff << PAGE_SHIFT) - return -EINVAL; - if (off + get_vm_size(vma) - 1 < off) - return -EINVAL; - vma->vm_pgoff = pgoff; - return 0; -} - /* * set up a mapping for shared memory segments */ @@ -1159,29 +1132,20 @@ static int mtdchar_mmap(struct file *file, struct vm_area_struct *vma) struct mtd_file_info *mfi = file->private_data; struct mtd_info *mtd = mfi->mtd; struct map_info *map = mtd->priv; - resource_size_t start, off; - unsigned long len, vma_len; + unsigned long start; + unsigned long off; + u32 len; if (mtd->type == MTD_RAM || mtd->type == MTD_ROM) { - off = get_vm_offset(vma); + off = vma->vm_pgoff << PAGE_SHIFT; start = map->phys; len = PAGE_ALIGN((start & ~PAGE_MASK) + map->size); start &= PAGE_MASK; - vma_len = get_vm_size(vma); - - /* Overflow in off+len? */ - if (vma_len + off < off) - return -EINVAL; - /* Does it fit in the mapping? */ - if (vma_len + off > len) + if ((vma->vm_end - vma->vm_start + off) > len) return -EINVAL; off += start; - /* Did that overflow? */ - if (off < start) - return -EINVAL; - if (set_vm_offset(vma, off) < 0) - return -EINVAL; + vma->vm_pgoff = off >> PAGE_SHIFT; vma->vm_flags |= VM_IO | VM_RESERVED; #ifdef pgprot_noncached diff --git a/trunk/drivers/mtd/nand/Kconfig b/trunk/drivers/mtd/nand/Kconfig index 8ca417614c57..31bb7e5b504a 100644 --- a/trunk/drivers/mtd/nand/Kconfig +++ b/trunk/drivers/mtd/nand/Kconfig @@ -480,7 +480,7 @@ config MTD_NAND_NANDSIM config MTD_NAND_GPMI_NAND bool "GPMI NAND Flash Controller driver" - depends on MTD_NAND && MXS_DMA + depends on MTD_NAND && (SOC_IMX23 || SOC_IMX28 || SOC_IMX6Q) help Enables NAND Flash support for IMX23 or IMX28. The GPMI controller is very powerful, with the help of BCH diff --git a/trunk/drivers/mtd/nand/omap2.c b/trunk/drivers/mtd/nand/omap2.c index ac4fd756eda3..e9309b3659e7 100644 --- a/trunk/drivers/mtd/nand/omap2.c +++ b/trunk/drivers/mtd/nand/omap2.c @@ -1245,6 +1245,7 @@ static int __devinit omap_nand_probe(struct platform_device *pdev) goto out_release_mem_region; } else { struct dma_slave_config cfg; + int rc; memset(&cfg, 0, sizeof(cfg)); cfg.src_addr = info->phys_base; @@ -1253,10 +1254,10 @@ static int __devinit omap_nand_probe(struct platform_device *pdev) cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; cfg.src_maxburst = 16; cfg.dst_maxburst = 16; - err = dmaengine_slave_config(info->dma, &cfg); - if (err) { + rc = dmaengine_slave_config(info->dma, &cfg); + if (rc) { dev_err(&pdev->dev, "DMA engine slave config failed: %d\n", - err); + rc); goto out_release_mem_region; } info->nand.read_buf = omap_read_buf_dma_pref; diff --git a/trunk/drivers/mtd/ubi/vtbl.c b/trunk/drivers/mtd/ubi/vtbl.c index 568307cc7caf..437bc193e170 100644 --- a/trunk/drivers/mtd/ubi/vtbl.c +++ b/trunk/drivers/mtd/ubi/vtbl.c @@ -340,7 +340,7 @@ static int create_vtbl(struct ubi_device *ubi, struct ubi_attach_info *ai, * of this LEB as it will be deleted and freed in 'ubi_add_to_av()'. */ err = ubi_add_to_av(ubi, ai, new_aeb->pnum, new_aeb->ec, vid_hdr, 0); - kmem_cache_free(ai->aeb_slab_cache, new_aeb); + kfree(new_aeb); ubi_free_vid_hdr(ubi, vid_hdr); return err; @@ -353,7 +353,7 @@ static int create_vtbl(struct ubi_device *ubi, struct ubi_attach_info *ai, list_add(&new_aeb->u.list, &ai->erase); goto retry; } - kmem_cache_free(ai->aeb_slab_cache, new_aeb); + kfree(new_aeb); out_free: ubi_free_vid_hdr(ubi, vid_hdr); return err; diff --git a/trunk/drivers/net/appletalk/cops.c b/trunk/drivers/net/appletalk/cops.c index cff6f023c03a..545c09ed9079 100644 --- a/trunk/drivers/net/appletalk/cops.c +++ b/trunk/drivers/net/appletalk/cops.c @@ -996,7 +996,9 @@ static int __init cops_module_init(void) printk(KERN_WARNING "%s: You shouldn't autoprobe with insmod\n", cardname); cops_dev = cops_probe(-1); - return PTR_RET(cops_dev); + if (IS_ERR(cops_dev)) + return PTR_ERR(cops_dev); + return 0; } static void __exit cops_module_exit(void) diff --git a/trunk/drivers/net/appletalk/ltpc.c b/trunk/drivers/net/appletalk/ltpc.c index b5782cdf0bca..0910dce3996d 100644 --- a/trunk/drivers/net/appletalk/ltpc.c +++ b/trunk/drivers/net/appletalk/ltpc.c @@ -1243,7 +1243,9 @@ static int __init ltpc_module_init(void) "ltpc: Autoprobing is not recommended for modules\n"); dev_ltpc = ltpc_probe(); - return PTR_RET(dev_ltpc); + if (IS_ERR(dev_ltpc)) + return PTR_ERR(dev_ltpc); + return 0; } module_init(ltpc_module_init); #endif diff --git a/trunk/drivers/net/bonding/bond_main.c b/trunk/drivers/net/bonding/bond_main.c index d688a8af432c..6fae5f3ec7f6 100644 --- a/trunk/drivers/net/bonding/bond_main.c +++ b/trunk/drivers/net/bonding/bond_main.c @@ -398,7 +398,7 @@ int bond_dev_queue_xmit(struct bonding *bond, struct sk_buff *skb, sizeof(qdisc_skb_cb(skb)->slave_dev_queue_mapping)); skb->queue_mapping = qdisc_skb_cb(skb)->slave_dev_queue_mapping; - if (unlikely(netpoll_tx_running(bond->dev))) + if (unlikely(netpoll_tx_running(slave_dev))) bond_netpoll_send_skb(bond_get_slave_by_dev(bond, slave_dev), skb); else dev_queue_xmit(skb); @@ -1235,12 +1235,12 @@ static inline int slave_enable_netpoll(struct slave *slave) struct netpoll *np; int err = 0; - np = kzalloc(sizeof(*np), GFP_ATOMIC); + np = kzalloc(sizeof(*np), GFP_KERNEL); err = -ENOMEM; if (!np) goto out; - err = __netpoll_setup(np, slave->dev, GFP_ATOMIC); + err = __netpoll_setup(np, slave->dev); if (err) { kfree(np); goto out; @@ -1257,7 +1257,9 @@ static inline void slave_disable_netpoll(struct slave *slave) return; slave->np = NULL; - __netpoll_free_rcu(np); + synchronize_rcu_bh(); + __netpoll_cleanup(np); + kfree(np); } static inline bool slave_dev_support_netpoll(struct net_device *slave_dev) { @@ -1290,7 +1292,7 @@ static void bond_netpoll_cleanup(struct net_device *bond_dev) read_unlock(&bond->lock); } -static int bond_netpoll_setup(struct net_device *dev, struct netpoll_info *ni, gfp_t gfp) +static int bond_netpoll_setup(struct net_device *dev, struct netpoll_info *ni) { struct bonding *bond = netdev_priv(dev); struct slave *slave; diff --git a/trunk/drivers/net/can/janz-ican3.c b/trunk/drivers/net/can/janz-ican3.c index 7edadee487ba..98ee43819911 100644 --- a/trunk/drivers/net/can/janz-ican3.c +++ b/trunk/drivers/net/can/janz-ican3.c @@ -1391,6 +1391,7 @@ static irqreturn_t ican3_irq(int irq, void *dev_id) */ static int ican3_reset_module(struct ican3_dev *mod) { + u8 val = 1 << mod->num; unsigned long start; u8 runold, runnew; @@ -1404,7 +1405,8 @@ static int ican3_reset_module(struct ican3_dev *mod) runold = ioread8(mod->dpm + TARGET_RUNNING); /* reset the module */ - iowrite8(0x00, &mod->dpmctrl->hwreset); + iowrite8(val, &mod->ctrl->reset_assert); + iowrite8(val, &mod->ctrl->reset_deassert); /* wait until the module has finished resetting and is running */ start = jiffies; diff --git a/trunk/drivers/net/can/mcp251x.c b/trunk/drivers/net/can/mcp251x.c index 26e7129332ab..a580db29e503 100644 --- a/trunk/drivers/net/can/mcp251x.c +++ b/trunk/drivers/net/can/mcp251x.c @@ -83,11 +83,6 @@ #define INSTRUCTION_LOAD_TXB(n) (0x40 + 2 * (n)) #define INSTRUCTION_READ_RXB(n) (((n) == 0) ? 0x90 : 0x94) #define INSTRUCTION_RESET 0xC0 -#define RTS_TXB0 0x01 -#define RTS_TXB1 0x02 -#define RTS_TXB2 0x04 -#define INSTRUCTION_RTS(n) (0x80 | ((n) & 0x07)) - /* MPC251x registers */ #define CANSTAT 0x0e @@ -402,7 +397,6 @@ static void mcp251x_hw_tx_frame(struct spi_device *spi, u8 *buf, static void mcp251x_hw_tx(struct spi_device *spi, struct can_frame *frame, int tx_buf_idx) { - struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev); u32 sid, eid, exide, rtr; u8 buf[SPI_TRANSFER_BUF_LEN]; @@ -424,10 +418,7 @@ static void mcp251x_hw_tx(struct spi_device *spi, struct can_frame *frame, buf[TXBDLC_OFF] = (rtr << DLC_RTR_SHIFT) | frame->can_dlc; memcpy(buf + TXBDAT_OFF, frame->data, frame->can_dlc); mcp251x_hw_tx_frame(spi, buf, frame->can_dlc, tx_buf_idx); - - /* use INSTRUCTION_RTS, to avoid "repeated frame problem" */ - priv->spi_tx_buf[0] = INSTRUCTION_RTS(1 << tx_buf_idx); - mcp251x_spi_trans(priv->spi, 1); + mcp251x_write_reg(spi, TXBCTRL(tx_buf_idx), TXBCTRL_TXREQ); } static void mcp251x_hw_rx_frame(struct spi_device *spi, u8 *buf, diff --git a/trunk/drivers/net/can/sja1000/sja1000_platform.c b/trunk/drivers/net/can/sja1000/sja1000_platform.c index 662c5f7eb0c5..4f50145f6483 100644 --- a/trunk/drivers/net/can/sja1000/sja1000_platform.c +++ b/trunk/drivers/net/can/sja1000/sja1000_platform.c @@ -109,9 +109,7 @@ static int sp_probe(struct platform_device *pdev) priv = netdev_priv(dev); dev->irq = res_irq->start; - priv->irq_flags = res_irq->flags & IRQF_TRIGGER_MASK; - if (res_irq->flags & IORESOURCE_IRQ_SHAREABLE) - priv->irq_flags |= IRQF_SHARED; + priv->irq_flags = res_irq->flags & (IRQF_TRIGGER_MASK | IRQF_SHARED); priv->reg_base = addr; /* The CAN clock frequency is half the oscillator clock frequency */ priv->can.clock.freq = pdata->osc_freq / 2; diff --git a/trunk/drivers/net/can/softing/softing_fw.c b/trunk/drivers/net/can/softing/softing_fw.c index b595d3422b9f..310596175676 100644 --- a/trunk/drivers/net/can/softing/softing_fw.c +++ b/trunk/drivers/net/can/softing/softing_fw.c @@ -150,7 +150,7 @@ int softing_load_fw(const char *file, struct softing *card, const uint8_t *mem, *end, *dat; uint16_t type, len; uint32_t addr; - uint8_t *buf = NULL, *new_buf; + uint8_t *buf = NULL; int buflen = 0; int8_t type_end = 0; @@ -199,12 +199,11 @@ int softing_load_fw(const char *file, struct softing *card, if (len > buflen) { /* align buflen */ buflen = (len + (1024-1)) & ~(1024-1); - new_buf = krealloc(buf, buflen, GFP_KERNEL); - if (!new_buf) { + buf = krealloc(buf, buflen, GFP_KERNEL); + if (!buf) { ret = -ENOMEM; goto failed; } - buf = new_buf; } /* verify record data */ memcpy_fromio(buf, &dpram[addr + offset], len); diff --git a/trunk/drivers/net/can/ti_hecc.c b/trunk/drivers/net/can/ti_hecc.c index 9ded21e79db5..527dbcf95335 100644 --- a/trunk/drivers/net/can/ti_hecc.c +++ b/trunk/drivers/net/can/ti_hecc.c @@ -984,12 +984,12 @@ static int __devexit ti_hecc_remove(struct platform_device *pdev) struct net_device *ndev = platform_get_drvdata(pdev); struct ti_hecc_priv *priv = netdev_priv(ndev); - unregister_candev(ndev); clk_disable(priv->clk); clk_put(priv->clk); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); iounmap(priv->base); release_mem_region(res->start, resource_size(res)); + unregister_candev(ndev); free_candev(ndev); platform_set_drvdata(pdev, NULL); diff --git a/trunk/drivers/net/cris/eth_v10.c b/trunk/drivers/net/cris/eth_v10.c index 021d69c5d9bc..f0c8bd54ce29 100644 --- a/trunk/drivers/net/cris/eth_v10.c +++ b/trunk/drivers/net/cris/eth_v10.c @@ -1712,7 +1712,7 @@ e100_set_network_leds(int active) static void e100_netpoll(struct net_device* netdev) { - e100rxtx_interrupt(NETWORK_DMA_TX_IRQ_NBR, netdev); + e100rxtx_interrupt(NETWORK_DMA_TX_IRQ_NBR, netdev, NULL); } #endif diff --git a/trunk/drivers/net/ethernet/3com/typhoon.c b/trunk/drivers/net/ethernet/3com/typhoon.c index bb9670f29b59..b15366635147 100644 --- a/trunk/drivers/net/ethernet/3com/typhoon.c +++ b/trunk/drivers/net/ethernet/3com/typhoon.c @@ -364,7 +364,7 @@ typhoon_inc_rxfree_index(u32 *index, const int count) static inline void typhoon_inc_tx_index(u32 *index, const int count) { - /* if we start using the Hi Tx ring, this needs updating */ + /* if we start using the Hi Tx ring, this needs updateing */ typhoon_inc_index(index, count, TXLO_ENTRIES); } diff --git a/trunk/drivers/net/ethernet/atheros/atl1c/atl1c_main.c b/trunk/drivers/net/ethernet/atheros/atl1c/atl1c_main.c index 55a2e3795055..1bf5bbfe778e 100644 --- a/trunk/drivers/net/ethernet/atheros/atl1c/atl1c_main.c +++ b/trunk/drivers/net/ethernet/atheros/atl1c/atl1c_main.c @@ -149,7 +149,7 @@ static void atl1c_reset_pcie(struct atl1c_hw *hw, u32 flag) data &= ~(PCI_ERR_UNC_DLP | PCI_ERR_UNC_FCP); pci_write_config_dword(pdev, pos + PCI_ERR_UNCOR_SEVER, data); /* clear error status */ - pcie_capability_write_word(pdev, PCI_EXP_DEVSTA, + pci_write_config_word(pdev, pci_pcie_cap(pdev) + PCI_EXP_DEVSTA, PCI_EXP_DEVSTA_NFED | PCI_EXP_DEVSTA_FED | PCI_EXP_DEVSTA_CED | @@ -2685,7 +2685,7 @@ static void atl1c_io_resume(struct pci_dev *pdev) netif_device_attach(netdev); } -static const struct pci_error_handlers atl1c_err_handler = { +static struct pci_error_handlers atl1c_err_handler = { .error_detected = atl1c_io_error_detected, .slot_reset = atl1c_io_slot_reset, .resume = atl1c_io_resume, diff --git a/trunk/drivers/net/ethernet/atheros/atl1e/atl1e_main.c b/trunk/drivers/net/ethernet/atheros/atl1e/atl1e_main.c index e213da29e73d..a98acc8a956f 100644 --- a/trunk/drivers/net/ethernet/atheros/atl1e/atl1e_main.c +++ b/trunk/drivers/net/ethernet/atheros/atl1e/atl1e_main.c @@ -2489,7 +2489,7 @@ static void atl1e_io_resume(struct pci_dev *pdev) netif_device_attach(netdev); } -static const struct pci_error_handlers atl1e_err_handler = { +static struct pci_error_handlers atl1e_err_handler = { .error_detected = atl1e_io_error_detected, .slot_reset = atl1e_io_slot_reset, .resume = atl1e_io_resume, diff --git a/trunk/drivers/net/ethernet/broadcom/bnx2.c b/trunk/drivers/net/ethernet/broadcom/bnx2.c index d4310700c7a7..79cebd8525ce 100644 --- a/trunk/drivers/net/ethernet/broadcom/bnx2.c +++ b/trunk/drivers/net/ethernet/broadcom/bnx2.c @@ -8564,7 +8564,7 @@ bnx2_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) return 0; error: - pci_iounmap(pdev, bp->regview); + iounmap(bp->regview); pci_release_regions(pdev); pci_disable_device(pdev); pci_set_drvdata(pdev, NULL); @@ -8742,7 +8742,7 @@ static void bnx2_io_resume(struct pci_dev *pdev) rtnl_unlock(); } -static const struct pci_error_handlers bnx2_err_handler = { +static struct pci_error_handlers bnx2_err_handler = { .error_detected = bnx2_io_error_detected, .slot_reset = bnx2_io_slot_reset, .resume = bnx2_io_resume, diff --git a/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h b/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h index eac25236856c..77bcd4cb4ffb 100644 --- a/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h +++ b/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h @@ -1278,7 +1278,7 @@ struct bnx2x { #define BNX2X_FW_RX_ALIGN_START (1UL << BNX2X_RX_ALIGN_SHIFT) #define BNX2X_FW_RX_ALIGN_END \ - max_t(u64, 1UL << BNX2X_RX_ALIGN_SHIFT, \ + max(1UL << BNX2X_RX_ALIGN_SHIFT, \ SKB_DATA_ALIGN(sizeof(struct skb_shared_info))) #define BNX2X_PXP_DRAM_ALIGN (BNX2X_RX_ALIGN_SHIFT - 5) @@ -1458,7 +1458,7 @@ struct bnx2x { int fw_stats_req_sz; /* - * FW statistics data shortcut (points at the beginning of + * FW statistics data shortcut (points at the begining of * fw_stats buffer + fw_stats_req_sz). */ struct bnx2x_fw_stats_data *fw_stats_data; @@ -1708,6 +1708,9 @@ struct bnx2x_func_init_params { continue; \ else +#define for_each_napi_rx_queue(bp, var) \ + for ((var) = 0; (var) < bp->num_napi_queues; (var)++) + /* Skip OOO FP */ #define for_each_tx_queue(bp, var) \ for ((var) = 0; (var) < BNX2X_NUM_QUEUES(bp); (var)++) \ diff --git a/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c index e8e97a7d1d06..e879e19eb0d6 100644 --- a/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c +++ b/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c @@ -662,16 +662,14 @@ void bnx2x_csum_validate(struct sk_buff *skb, union eth_rx_cqe *cqe, struct bnx2x_fastpath *fp, struct bnx2x_eth_q_stats *qstats) { - /* Do nothing if no L4 csum validation was done. - * We do not check whether IP csum was validated. For IPv4 we assume - * that if the card got as far as validating the L4 csum, it also - * validated the IP csum. IPv6 has no IP csum. - */ + /* Do nothing if no IP/L4 csum validation was done */ + if (cqe->fast_path_cqe.status_flags & - ETH_FAST_PATH_RX_CQE_L4_XSUM_NO_VALIDATION_FLG) + (ETH_FAST_PATH_RX_CQE_IP_XSUM_NO_VALIDATION_FLG | + ETH_FAST_PATH_RX_CQE_L4_XSUM_NO_VALIDATION_FLG)) return; - /* If L4 validation was done, check if an error was found. */ + /* If both IP/L4 validation were done, check if an error was found. */ if (cqe->fast_path_cqe.type_error_flags & (ETH_FAST_PATH_RX_CQE_IP_BAD_XSUM_FLG | @@ -2048,8 +2046,6 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode) */ bnx2x_setup_tc(bp->dev, bp->max_cos); - /* Add all NAPI objects */ - bnx2x_add_all_napi(bp); bnx2x_napi_enable(bp); /* set pf load just before approaching the MCP */ @@ -2412,8 +2408,6 @@ int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode) /* Disable HW interrupts, NAPI */ bnx2x_netif_stop(bp, 1); - /* Delete all NAPI objects */ - bnx2x_del_all_napi(bp); /* Release IRQs */ bnx2x_free_irq(bp); diff --git a/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h b/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h index dfd86a55f1dc..dfa757e74296 100644 --- a/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h +++ b/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h @@ -710,15 +710,17 @@ static inline u16 bnx2x_tx_avail(struct bnx2x *bp, prod = txdata->tx_bd_prod; cons = txdata->tx_bd_cons; - used = SUB_S16(prod, cons); + /* NUM_TX_RINGS = number of "next-page" entries + It will be used as a threshold */ + used = SUB_S16(prod, cons) + (s16)NUM_TX_RINGS; #ifdef BNX2X_STOP_ON_ERROR WARN_ON(used < 0); - WARN_ON(used > txdata->tx_ring_size); - WARN_ON((txdata->tx_ring_size - used) > MAX_TX_AVAIL); + WARN_ON(used > bp->tx_ring_size); + WARN_ON((bp->tx_ring_size - used) > MAX_TX_AVAIL); #endif - return (s16)(txdata->tx_ring_size) - used; + return (s16)(bp->tx_ring_size) - used; } static inline int bnx2x_tx_queue_has_work(struct bnx2x_fp_txdata *txdata) @@ -790,7 +792,7 @@ static inline void bnx2x_add_all_napi(struct bnx2x *bp) bp->num_napi_queues = bp->num_queues; /* Add NAPI objects */ - for_each_rx_queue(bp, i) + for_each_napi_rx_queue(bp, i) netif_napi_add(bp->dev, &bnx2x_fp(bp, i, napi), bnx2x_poll, BNX2X_NAPI_WEIGHT); } @@ -799,7 +801,7 @@ static inline void bnx2x_del_all_napi(struct bnx2x *bp) { int i; - for_each_rx_queue(bp, i) + for_each_napi_rx_queue(bp, i) netif_napi_del(&bnx2x_fp(bp, i, napi)); } @@ -1086,7 +1088,6 @@ static inline void bnx2x_init_txdata(struct bnx2x *bp, txdata->txq_index = txq_index; txdata->tx_cons_sb = tx_cons_sb; txdata->parent_fp = fp; - txdata->tx_ring_size = IS_FCOE_FP(fp) ? MAX_TX_AVAIL : bp->tx_ring_size; DP(NETIF_MSG_IFUP, "created tx data cid %d, txq %d\n", txdata->cid, txdata->txq_index); diff --git a/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dump.h b/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dump.h index b926f58e983b..3e4cff9b1ebe 100644 --- a/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dump.h +++ b/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dump.h @@ -401,11 +401,11 @@ static const struct reg_addr reg_addrs[] = { { 0x70000, 8, RI_ALL_ONLINE }, { 0x70020, 8184, RI_ALL_OFFLINE }, { 0x78000, 8192, RI_E3E3B0_OFFLINE }, - { 0x85000, 3, RI_ALL_OFFLINE }, - { 0x8501c, 7, RI_ALL_OFFLINE }, - { 0x85048, 1, RI_ALL_OFFLINE }, - { 0x85200, 32, RI_ALL_OFFLINE }, - { 0xb0000, 16384, RI_E1H_OFFLINE }, + { 0x85000, 3, RI_ALL_ONLINE }, + { 0x8501c, 7, RI_ALL_ONLINE }, + { 0x85048, 1, RI_ALL_ONLINE }, + { 0x85200, 32, RI_ALL_ONLINE }, + { 0xb0000, 16384, RI_E1H_ONLINE }, { 0xc1000, 7, RI_ALL_ONLINE }, { 0xc103c, 2, RI_E2E3E3B0_ONLINE }, { 0xc1800, 2, RI_ALL_ONLINE }, @@ -581,12 +581,17 @@ static const struct reg_addr reg_addrs[] = { { 0x140188, 3, RI_E1E1HE2E3_ONLINE }, { 0x140194, 13, RI_ALL_ONLINE }, { 0x140200, 6, RI_E1E1HE2E3_ONLINE }, + { 0x140220, 4, RI_E2E3_ONLINE }, + { 0x140240, 4, RI_E2E3_ONLINE }, { 0x140260, 4, RI_E2E3_ONLINE }, { 0x140280, 4, RI_E2E3_ONLINE }, + { 0x1402a0, 4, RI_E2E3_ONLINE }, + { 0x1402c0, 4, RI_E2E3_ONLINE }, { 0x1402e0, 2, RI_E2E3_ONLINE }, { 0x1402e8, 2, RI_E2E3E3B0_ONLINE }, { 0x1402f0, 9, RI_E2E3_ONLINE }, { 0x140314, 44, RI_E3B0_ONLINE }, + { 0x1403d0, 70, RI_E3B0_ONLINE }, { 0x144000, 4, RI_E1E1H_ONLINE }, { 0x148000, 4, RI_E1E1H_ONLINE }, { 0x14c000, 4, RI_E1E1H_ONLINE }, @@ -699,6 +704,7 @@ static const struct reg_addr reg_addrs[] = { { 0x180398, 1, RI_E2E3E3B0_ONLINE }, { 0x1803a0, 5, RI_E2E3E3B0_ONLINE }, { 0x1803b4, 2, RI_E3E3B0_ONLINE }, + { 0x180400, 1, RI_ALL_ONLINE }, { 0x180404, 255, RI_E1E1H_OFFLINE }, { 0x181000, 4, RI_ALL_ONLINE }, { 0x181010, 1020, RI_ALL_OFFLINE }, @@ -794,9 +800,9 @@ static const struct reg_addr reg_addrs[] = { { 0x1b905c, 1, RI_E3E3B0_ONLINE }, { 0x1b9064, 1, RI_E3B0_ONLINE }, { 0x1b9080, 10, RI_E3B0_ONLINE }, - { 0x1b9400, 14, RI_E2E3E3B0_OFFLINE }, - { 0x1b943c, 19, RI_E2E3E3B0_OFFLINE }, - { 0x1b9490, 10, RI_E2E3E3B0_OFFLINE }, + { 0x1b9400, 14, RI_E2E3E3B0_ONLINE }, + { 0x1b943c, 19, RI_E2E3E3B0_ONLINE }, + { 0x1b9490, 10, RI_E2E3E3B0_ONLINE }, { 0x1c0000, 2, RI_ALL_ONLINE }, { 0x200000, 65, RI_ALL_ONLINE }, { 0x20014c, 2, RI_E1HE2E3E3B0_ONLINE }, @@ -808,6 +814,7 @@ static const struct reg_addr reg_addrs[] = { { 0x200398, 1, RI_E2E3E3B0_ONLINE }, { 0x2003a0, 1, RI_E2E3E3B0_ONLINE }, { 0x2003a8, 2, RI_E2E3E3B0_ONLINE }, + { 0x200400, 1, RI_ALL_ONLINE }, { 0x200404, 255, RI_E1E1H_OFFLINE }, { 0x202000, 4, RI_ALL_ONLINE }, { 0x202010, 2044, RI_ALL_OFFLINE }, @@ -914,6 +921,7 @@ static const struct reg_addr reg_addrs[] = { { 0x280398, 1, RI_E2E3E3B0_ONLINE }, { 0x2803a0, 1, RI_E2E3E3B0_ONLINE }, { 0x2803a8, 2, RI_E2E3E3B0_ONLINE }, + { 0x280400, 1, RI_ALL_ONLINE }, { 0x280404, 255, RI_E1E1H_OFFLINE }, { 0x282000, 4, RI_ALL_ONLINE }, { 0x282010, 2044, RI_ALL_OFFLINE }, @@ -1023,6 +1031,7 @@ static const struct reg_addr reg_addrs[] = { { 0x300398, 1, RI_E2E3E3B0_ONLINE }, { 0x3003a0, 1, RI_E2E3E3B0_ONLINE }, { 0x3003a8, 2, RI_E2E3E3B0_ONLINE }, + { 0x300400, 1, RI_ALL_ONLINE }, { 0x300404, 255, RI_E1E1H_OFFLINE }, { 0x302000, 4, RI_ALL_ONLINE }, { 0x302010, 2044, RI_ALL_OFFLINE }, diff --git a/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c b/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c index ebf40cd7aa10..fc4e0e3885b0 100644 --- a/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c +++ b/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c @@ -775,7 +775,7 @@ static void bnx2x_get_regs(struct net_device *dev, struct bnx2x *bp = netdev_priv(dev); struct dump_hdr dump_hdr = {0}; - regs->version = 1; + regs->version = 0; memset(p, 0, regs->len); if (!netif_running(bp->dev)) @@ -1587,12 +1587,6 @@ static int bnx2x_set_pauseparam(struct net_device *dev, bp->link_params.req_flow_ctrl[cfg_idx] = BNX2X_FLOW_CTRL_AUTO; } - bp->link_params.req_fc_auto_adv = BNX2X_FLOW_CTRL_NONE; - if (epause->rx_pause) - bp->link_params.req_fc_auto_adv |= BNX2X_FLOW_CTRL_RX; - - if (epause->tx_pause) - bp->link_params.req_fc_auto_adv |= BNX2X_FLOW_CTRL_TX; } DP(BNX2X_MSG_ETHTOOL, @@ -2894,9 +2888,11 @@ static void bnx2x_get_channels(struct net_device *dev, */ static void bnx2x_change_num_queues(struct bnx2x *bp, int num_rss) { + bnx2x_del_all_napi(bp); bnx2x_disable_msi(bp); BNX2X_NUM_QUEUES(bp) = num_rss + NON_ETH_CONTEXT_USE; bnx2x_set_int_mode(bp); + bnx2x_add_all_napi(bp); } /** diff --git a/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c b/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c index b046beb435b2..f4beb46c4709 100644 --- a/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c +++ b/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c @@ -2667,11 +2667,9 @@ int bnx2x_update_pfc(struct link_params *params, return bnx2x_status; DP(NETIF_MSG_LINK, "About to update PFC in BMAC\n"); - - if (CHIP_IS_E3(bp)) { - if (vars->mac_type == MAC_TYPE_XMAC) - bnx2x_update_pfc_xmac(params, vars, 0); - } else { + if (CHIP_IS_E3(bp)) + bnx2x_update_pfc_xmac(params, vars, 0); + else { val = REG_RD(bp, MISC_REG_RESET_REG_2); if ((val & (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << params->port)) @@ -5434,7 +5432,7 @@ static int bnx2x_get_link_speed_duplex(struct bnx2x_phy *phy, switch (speed_mask) { case GP_STATUS_10M: vars->line_speed = SPEED_10; - if (is_duplex == DUPLEX_FULL) + if (vars->duplex == DUPLEX_FULL) vars->link_status |= LINK_10TFD; else vars->link_status |= LINK_10THD; @@ -5442,7 +5440,7 @@ static int bnx2x_get_link_speed_duplex(struct bnx2x_phy *phy, case GP_STATUS_100M: vars->line_speed = SPEED_100; - if (is_duplex == DUPLEX_FULL) + if (vars->duplex == DUPLEX_FULL) vars->link_status |= LINK_100TXFD; else vars->link_status |= LINK_100TXHD; @@ -5451,7 +5449,7 @@ static int bnx2x_get_link_speed_duplex(struct bnx2x_phy *phy, case GP_STATUS_1G: case GP_STATUS_1G_KX: vars->line_speed = SPEED_1000; - if (is_duplex == DUPLEX_FULL) + if (vars->duplex == DUPLEX_FULL) vars->link_status |= LINK_1000TFD; else vars->link_status |= LINK_1000THD; @@ -5459,7 +5457,7 @@ static int bnx2x_get_link_speed_duplex(struct bnx2x_phy *phy, case GP_STATUS_2_5G: vars->line_speed = SPEED_2500; - if (is_duplex == DUPLEX_FULL) + if (vars->duplex == DUPLEX_FULL) vars->link_status |= LINK_2500TFD; else vars->link_status |= LINK_2500THD; @@ -5533,7 +5531,6 @@ static int bnx2x_link_settings_status(struct bnx2x_phy *phy, if (gp_status & MDIO_GP_STATUS_TOP_AN_STATUS1_LINK_STATUS) { if (SINGLE_MEDIA_DIRECT(params)) { - vars->duplex = duplex; bnx2x_flow_ctrl_resolve(phy, params, vars, gp_status); if (phy->req_line_speed == SPEED_AUTO_NEG) bnx2x_xgxs_an_resolve(phy, params, vars, @@ -5628,7 +5625,6 @@ static int bnx2x_warpcore_read_status(struct bnx2x_phy *phy, LINK_STATUS_PARALLEL_DETECTION_USED; } bnx2x_ext_phy_resolve_fc(phy, params, vars); - vars->duplex = duplex; } } diff --git a/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c index e11485ca037d..dd451c3dd83d 100644 --- a/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +++ b/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c @@ -1162,9 +1162,14 @@ static int bnx2x_send_final_clnup(struct bnx2x *bp, u8 clnup_func, static u8 bnx2x_is_pcie_pending(struct pci_dev *dev) { + int pos; u16 status; - pcie_capability_read_word(dev, PCI_EXP_DEVSTA, &status); + pos = pci_pcie_cap(dev); + if (!pos) + return false; + + pci_read_config_word(dev, pos + PCI_EXP_DEVSTA, &status); return status & PCI_EXP_DEVSTA_TRPND; } @@ -4036,6 +4041,20 @@ static bool bnx2x_get_load_status(struct bnx2x *bp, int engine) return val != 0; } +/* + * Reset the load status for the current engine. + */ +static void bnx2x_clear_load_status(struct bnx2x *bp) +{ + u32 val; + u32 mask = (BP_PATH(bp) ? BNX2X_PATH1_LOAD_CNT_MASK : + BNX2X_PATH0_LOAD_CNT_MASK); + bnx2x_acquire_hw_lock(bp, HW_LOCK_RESOURCE_RECOVERY_REG); + val = REG_RD(bp, BNX2X_RECOVERY_GLOB_REG); + REG_WR(bp, BNX2X_RECOVERY_GLOB_REG, val & (~mask)); + bnx2x_release_hw_lock(bp, HW_LOCK_RESOURCE_RECOVERY_REG); +} + static void _print_next_block(int idx, const char *blk) { pr_cont("%s%s", idx ? ", " : "", blk); @@ -6130,7 +6149,8 @@ static void bnx2x_init_pxp(struct bnx2x *bp) u16 devctl; int r_order, w_order; - pcie_capability_read_word(bp->pdev, PCI_EXP_DEVCTL, &devctl); + pci_read_config_word(bp->pdev, + pci_pcie_cap(bp->pdev) + PCI_EXP_DEVCTL, &devctl); DP(NETIF_MSG_HW, "read 0x%x from devctl\n", devctl); w_order = ((devctl & PCI_EXP_DEVCTL_PAYLOAD) >> 5); if (bp->mrrs == -1) @@ -7555,14 +7575,8 @@ int bnx2x_set_mac_one(struct bnx2x *bp, u8 *mac, } rc = bnx2x_config_vlan_mac(bp, &ramrod_param); - - if (rc == -EEXIST) { - DP(BNX2X_MSG_SP, "Failed to schedule ADD operations: %d\n", rc); - /* do not treat adding same MAC as error */ - rc = 0; - } else if (rc < 0) + if (rc < 0) BNX2X_ERR("%s MAC failed\n", (set ? "Set" : "Del")); - return rc; } @@ -8427,8 +8441,6 @@ void bnx2x_chip_cleanup(struct bnx2x *bp, int unload_mode) /* Disable HW interrupts, NAPI */ bnx2x_netif_stop(bp, 1); - /* Delete all NAPI objects */ - bnx2x_del_all_napi(bp); /* Release IRQs */ bnx2x_free_irq(bp); @@ -9372,31 +9384,43 @@ static int __devinit bnx2x_prev_mark_path(struct bnx2x *bp) return rc; } +static bool __devinit bnx2x_can_flr(struct bnx2x *bp) +{ + int pos; + u32 cap; + struct pci_dev *dev = bp->pdev; + + pos = pci_pcie_cap(dev); + if (!pos) + return false; + + pci_read_config_dword(dev, pos + PCI_EXP_DEVCAP, &cap); + if (!(cap & PCI_EXP_DEVCAP_FLR)) + return false; + + return true; +} + static int __devinit bnx2x_do_flr(struct bnx2x *bp) { - int i; + int i, pos; u16 status; struct pci_dev *dev = bp->pdev; + /* probe the capability first */ + if (bnx2x_can_flr(bp)) + return -ENOTTY; - if (CHIP_IS_E1x(bp)) { - BNX2X_DEV_INFO("FLR not supported in E1/E1H\n"); - return -EINVAL; - } - - /* only bootcode REQ_BC_VER_4_INITIATE_FLR and onwards support flr */ - if (bp->common.bc_ver < REQ_BC_VER_4_INITIATE_FLR) { - BNX2X_ERR("FLR not supported by BC_VER: 0x%x\n", - bp->common.bc_ver); - return -EINVAL; - } + pos = pci_pcie_cap(dev); + if (!pos) + return -ENOTTY; /* Wait for Transaction Pending bit clean */ for (i = 0; i < 4; i++) { if (i) msleep((1 << (i - 1)) * 100); - pcie_capability_read_word(dev, PCI_EXP_DEVSTA, &status); + pci_read_config_word(dev, pos + PCI_EXP_DEVSTA, &status); if (!(status & PCI_EXP_DEVSTA_TRPND)) goto clear; } @@ -9405,8 +9429,12 @@ static int __devinit bnx2x_do_flr(struct bnx2x *bp) "transaction is not cleared; proceeding with reset anyway\n"); clear: + if (bp->common.bc_ver < REQ_BC_VER_4_INITIATE_FLR) { + BNX2X_ERR("FLR not supported by BC_VER: 0x%x\n", + bp->common.bc_ver); + return -EINVAL; + } - BNX2X_DEV_INFO("Initiating FLR\n"); bnx2x_fw_command(bp, DRV_MSG_CODE_INITIATE_FLR, 0); return 0; @@ -9426,21 +9454,8 @@ static int __devinit bnx2x_prev_unload_uncommon(struct bnx2x *bp) * the one required, then FLR will be sufficient to clean any residue * left by previous driver */ - rc = bnx2x_test_firmware_version(bp, false); - - if (!rc) { - /* fw version is good */ - BNX2X_DEV_INFO("FW version matches our own. Attempting FLR\n"); - rc = bnx2x_do_flr(bp); - } - - if (!rc) { - /* FLR was performed */ - BNX2X_DEV_INFO("FLR successful\n"); - return 0; - } - - BNX2X_DEV_INFO("Could not FLR\n"); + if (bnx2x_test_firmware_version(bp, false) && bnx2x_can_flr(bp)) + return bnx2x_do_flr(bp); /* Close the MCP request, return failure*/ rc = bnx2x_prev_mcp_done(bp); @@ -9821,13 +9836,12 @@ static void __devinit bnx2x_get_igu_cam_info(struct bnx2x *bp) } #ifdef CONFIG_PCI_MSI - /* Due to new PF resource allocation by MFW T7.4 and above, it's - * optional that number of CAM entries will not be equal to the value - * advertised in PCI. - * Driver should use the minimal value of both as the actual status - * block count + /* + * It's expected that number of CAM entries for this functions is equal + * to the number evaluated based on the MSI-X table size. We want a + * harsh warning if these values are different! */ - bp->igu_sb_cnt = min_t(int, bp->igu_sb_cnt, igu_sb_cnt); + WARN_ON(bp->igu_sb_cnt != igu_sb_cnt); #endif if (igu_sb_cnt == 0) @@ -10291,11 +10305,13 @@ static void __devinit bnx2x_get_fcoe_info(struct bnx2x *bp) dev_info.port_hw_config[port]. fcoe_wwn_node_name_lower); } else if (!IS_MF_SD(bp)) { + u32 cfg = MF_CFG_RD(bp, func_ext_config[func].func_cfg); + /* * Read the WWN info only if the FCoE feature is enabled for * this function. */ - if (BNX2X_MF_EXT_PROTOCOL_FCOE(bp) && !CHIP_IS_E1x(bp)) + if (cfg & MACP_FUNC_CFG_FLAGS_FCOE_OFFLOAD) bnx2x_get_ext_wwn_info(bp, func); } else if (IS_MF_FCOE_SD(bp)) @@ -11068,14 +11084,7 @@ static int bnx2x_set_uc_list(struct bnx2x *bp) netdev_for_each_uc_addr(ha, dev) { rc = bnx2x_set_mac_one(bp, bnx2x_uc_addr(ha), mac_obj, true, BNX2X_UC_LIST_MAC, &ramrod_flags); - if (rc == -EEXIST) { - DP(BNX2X_MSG_SP, - "Failed to schedule ADD operations: %d\n", rc); - /* do not treat adding same MAC as error */ - rc = 0; - - } else if (rc < 0) { - + if (rc < 0) { BNX2X_ERR("Failed to schedule ADD operations: %d\n", rc); return rc; @@ -11233,12 +11242,10 @@ static int bnx2x_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) static void poll_bnx2x(struct net_device *dev) { struct bnx2x *bp = netdev_priv(dev); - int i; - for_each_eth_queue(bp, i) { - struct bnx2x_fastpath *fp = &bp->fp[i]; - napi_schedule(&bnx2x_fp(bp, fp->index, napi)); - } + disable_irq(bp->pdev->irq); + bnx2x_interrupt(bp->pdev->irq, dev); + enable_irq(bp->pdev->irq); } #endif @@ -11420,6 +11427,9 @@ static int __devinit bnx2x_init_dev(struct pci_dev *pdev, if (!chip_is_e1x) REG_WR(bp, PGLUE_B_REG_INTERNAL_PFID_ENABLE_TARGET_READ, 1); + /* Reset the load counter */ + bnx2x_clear_load_status(bp); + dev->watchdog_timeo = TX_TIMEOUT; dev->netdev_ops = &bnx2x_netdev_ops; @@ -11905,6 +11915,9 @@ static int __devinit bnx2x_init_one(struct pci_dev *pdev, */ bnx2x_set_int_mode(bp); + /* Add all NAPI objects */ + bnx2x_add_all_napi(bp); + rc = register_netdev(dev); if (rc) { dev_err(&pdev->dev, "Cannot register net device\n"); @@ -11979,6 +11992,9 @@ static void __devexit bnx2x_remove_one(struct pci_dev *pdev) unregister_netdev(dev); + /* Delete all NAPI objects */ + bnx2x_del_all_napi(bp); + /* Power on: we can't let PCI layer write to us while we are in D3 */ bnx2x_set_power_state(bp, PCI_D0); @@ -12025,8 +12041,6 @@ static int bnx2x_eeh_nic_unload(struct bnx2x *bp) bnx2x_tx_disable(bp); bnx2x_netif_stop(bp, 0); - /* Delete all NAPI objects */ - bnx2x_del_all_napi(bp); del_timer_sync(&bp->timer); @@ -12157,7 +12171,7 @@ static void bnx2x_io_resume(struct pci_dev *pdev) rtnl_unlock(); } -static const struct pci_error_handlers bnx2x_err_handler = { +static struct pci_error_handlers bnx2x_err_handler = { .error_detected = bnx2x_io_error_detected, .slot_reset = bnx2x_io_slot_reset, .resume = bnx2x_io_resume, diff --git a/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c b/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c index 62f754bd0dfe..734fd87cd990 100644 --- a/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c +++ b/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c @@ -2485,7 +2485,6 @@ static int bnx2x_mcast_enqueue_cmd(struct bnx2x *bp, break; default: - kfree(new_cmd); BNX2X_ERR("Unknown command: %d\n", cmd); return -EINVAL; } diff --git a/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h b/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h index acf2fe4ca608..f83e033da6da 100644 --- a/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h +++ b/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h @@ -1321,7 +1321,7 @@ void bnx2x_init_mcast_obj(struct bnx2x *bp, * the current command will be enqueued to the tail of the * pending commands list. * - * Return: 0 is operation was successfull and there are no pending completions, + * Return: 0 is operation was sucessfull and there are no pending completions, * negative if there were errors, positive if there are pending * completions. */ diff --git a/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.c b/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.c index a1d0446b39b3..332db64dd5be 100644 --- a/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.c +++ b/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.c @@ -101,11 +101,6 @@ static void bnx2x_hw_stats_post(struct bnx2x *bp) if (CHIP_REV_IS_SLOW(bp)) return; - /* Update MCP's statistics if possible */ - if (bp->func_stx) - memcpy(bnx2x_sp(bp, func_stats), &bp->func_stats, - sizeof(bp->func_stats)); - /* loader */ if (bp->executer_idx) { int loader_idx = PMF_DMAE_C(bp); @@ -133,6 +128,8 @@ static void bnx2x_hw_stats_post(struct bnx2x *bp) } else if (bp->func_stx) { *stats_comp = 0; + memcpy(bnx2x_sp(bp, func_stats), &bp->func_stats, + sizeof(bp->func_stats)); bnx2x_post_dmae(bp, dmae, INIT_DMAE_C(bp)); } } @@ -1154,11 +1151,9 @@ static void bnx2x_stats_update(struct bnx2x *bp) if (bp->port.pmf) bnx2x_hw_stats_update(bp); - if (bnx2x_storm_stats_update(bp)) { - if (bp->stats_pending++ == 3) { - BNX2X_ERR("storm stats were not updated for 3 times\n"); - bnx2x_panic(); - } + if (bnx2x_storm_stats_update(bp) && (bp->stats_pending++ == 3)) { + BNX2X_ERR("storm stats were not updated for 3 times\n"); + bnx2x_panic(); return; } diff --git a/trunk/drivers/net/ethernet/broadcom/tg3.c b/trunk/drivers/net/ethernet/broadcom/tg3.c index 388d32213937..bf906c51d82a 100644 --- a/trunk/drivers/net/ethernet/broadcom/tg3.c +++ b/trunk/drivers/net/ethernet/broadcom/tg3.c @@ -3653,9 +3653,17 @@ static int tg3_power_down_prepare(struct tg3 *tp) tg3_enable_register_access(tp); /* Restore the CLKREQ setting. */ - if (tg3_flag(tp, CLKREQ_BUG)) - pcie_capability_set_word(tp->pdev, PCI_EXP_LNKCTL, - PCI_EXP_LNKCTL_CLKREQ_EN); + if (tg3_flag(tp, CLKREQ_BUG)) { + u16 lnkctl; + + pci_read_config_word(tp->pdev, + pci_pcie_cap(tp->pdev) + PCI_EXP_LNKCTL, + &lnkctl); + lnkctl |= PCI_EXP_LNKCTL_CLKREQ_EN; + pci_write_config_word(tp->pdev, + pci_pcie_cap(tp->pdev) + PCI_EXP_LNKCTL, + lnkctl); + } misc_host_ctrl = tr32(TG3PCI_MISC_HOST_CTRL); tw32(TG3PCI_MISC_HOST_CTRL, @@ -4426,13 +4434,20 @@ static int tg3_setup_copper_phy(struct tg3 *tp, int force_reset) /* Prevent send BD corruption. */ if (tg3_flag(tp, CLKREQ_BUG)) { + u16 oldlnkctl, newlnkctl; + + pci_read_config_word(tp->pdev, + pci_pcie_cap(tp->pdev) + PCI_EXP_LNKCTL, + &oldlnkctl); if (tp->link_config.active_speed == SPEED_100 || tp->link_config.active_speed == SPEED_10) - pcie_capability_clear_word(tp->pdev, PCI_EXP_LNKCTL, - PCI_EXP_LNKCTL_CLKREQ_EN); + newlnkctl = oldlnkctl & ~PCI_EXP_LNKCTL_CLKREQ_EN; else - pcie_capability_set_word(tp->pdev, PCI_EXP_LNKCTL, - PCI_EXP_LNKCTL_CLKREQ_EN); + newlnkctl = oldlnkctl | PCI_EXP_LNKCTL_CLKREQ_EN; + if (newlnkctl != oldlnkctl) + pci_write_config_word(tp->pdev, + pci_pcie_cap(tp->pdev) + + PCI_EXP_LNKCTL, newlnkctl); } if (current_link_up != netif_carrier_ok(tp->dev)) { @@ -8039,7 +8054,7 @@ static int tg3_chip_reset(struct tg3 *tp) udelay(120); - if (tg3_flag(tp, PCI_EXPRESS) && pci_is_pcie(tp->pdev)) { + if (tg3_flag(tp, PCI_EXPRESS) && pci_pcie_cap(tp->pdev)) { u16 val16; if (tp->pci_chip_rev_id == CHIPREV_ID_5750_A0) { @@ -8056,17 +8071,24 @@ static int tg3_chip_reset(struct tg3 *tp) } /* Clear the "no snoop" and "relaxed ordering" bits. */ - val16 = PCI_EXP_DEVCTL_RELAX_EN | PCI_EXP_DEVCTL_NOSNOOP_EN; + pci_read_config_word(tp->pdev, + pci_pcie_cap(tp->pdev) + PCI_EXP_DEVCTL, + &val16); + val16 &= ~(PCI_EXP_DEVCTL_RELAX_EN | + PCI_EXP_DEVCTL_NOSNOOP_EN); /* * Older PCIe devices only support the 128 byte * MPS setting. Enforce the restriction. */ if (!tg3_flag(tp, CPMU_PRESENT)) - val16 |= PCI_EXP_DEVCTL_PAYLOAD; - pcie_capability_clear_word(tp->pdev, PCI_EXP_DEVCTL, val16); + val16 &= ~PCI_EXP_DEVCTL_PAYLOAD; + pci_write_config_word(tp->pdev, + pci_pcie_cap(tp->pdev) + PCI_EXP_DEVCTL, + val16); /* Clear error status */ - pcie_capability_write_word(tp->pdev, PCI_EXP_DEVSTA, + pci_write_config_word(tp->pdev, + pci_pcie_cap(tp->pdev) + PCI_EXP_DEVSTA, PCI_EXP_DEVSTA_CED | PCI_EXP_DEVSTA_NFED | PCI_EXP_DEVSTA_FED | @@ -14543,7 +14565,9 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) tg3_flag_set(tp, PCI_EXPRESS); - pcie_capability_read_word(tp->pdev, PCI_EXP_LNKCTL, &lnkctl); + pci_read_config_word(tp->pdev, + pci_pcie_cap(tp->pdev) + PCI_EXP_LNKCTL, + &lnkctl); if (lnkctl & PCI_EXP_LNKCTL_CLKREQ_EN) { if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) { @@ -16373,7 +16397,7 @@ static void tg3_io_resume(struct pci_dev *pdev) rtnl_unlock(); } -static const struct pci_error_handlers tg3_err_handler = { +static struct pci_error_handlers tg3_err_handler = { .error_detected = tg3_io_error_detected, .slot_reset = tg3_io_slot_reset, .resume = tg3_io_resume diff --git a/trunk/drivers/net/ethernet/cadence/at91_ether.c b/trunk/drivers/net/ethernet/cadence/at91_ether.c index 4e980a7886fb..77884191a8c6 100644 --- a/trunk/drivers/net/ethernet/cadence/at91_ether.c +++ b/trunk/drivers/net/ethernet/cadence/at91_ether.c @@ -1086,7 +1086,7 @@ static int __init at91ether_probe(struct platform_device *pdev) /* Clock */ lp->ether_clk = clk_get(&pdev->dev, "ether_clk"); if (IS_ERR(lp->ether_clk)) { - res = PTR_ERR(lp->ether_clk); + res = -ENODEV; goto err_ioumap; } clk_enable(lp->ether_clk); diff --git a/trunk/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c b/trunk/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c index 875bbb999aa2..6505070abcfa 100644 --- a/trunk/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c +++ b/trunk/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c @@ -3036,7 +3036,7 @@ static void t3_io_resume(struct pci_dev *pdev) t3_resume_ports(adapter); } -static const struct pci_error_handlers t3_err_handler = { +static struct pci_error_handlers t3_err_handler = { .error_detected = t3_io_error_detected, .slot_reset = t3_io_slot_reset, .resume = t3_io_resume, diff --git a/trunk/drivers/net/ethernet/chelsio/cxgb3/t3_hw.c b/trunk/drivers/net/ethernet/chelsio/cxgb3/t3_hw.c index aef45d3113ba..bff8a3cdd3df 100644 --- a/trunk/drivers/net/ethernet/chelsio/cxgb3/t3_hw.c +++ b/trunk/drivers/net/ethernet/chelsio/cxgb3/t3_hw.c @@ -3289,18 +3289,22 @@ static void config_pcie(struct adapter *adap) unsigned int log2_width, pldsize; unsigned int fst_trn_rx, fst_trn_tx, acklat, rpllmt; - pcie_capability_read_word(adap->pdev, PCI_EXP_DEVCTL, &val); + pci_read_config_word(adap->pdev, + adap->pdev->pcie_cap + PCI_EXP_DEVCTL, + &val); pldsize = (val & PCI_EXP_DEVCTL_PAYLOAD) >> 5; pci_read_config_word(adap->pdev, 0x2, &devid); if (devid == 0x37) { - pcie_capability_write_word(adap->pdev, PCI_EXP_DEVCTL, - val & ~PCI_EXP_DEVCTL_READRQ & - ~PCI_EXP_DEVCTL_PAYLOAD); + pci_write_config_word(adap->pdev, + adap->pdev->pcie_cap + PCI_EXP_DEVCTL, + val & ~PCI_EXP_DEVCTL_READRQ & + ~PCI_EXP_DEVCTL_PAYLOAD); pldsize = 0; } - pcie_capability_read_word(adap->pdev, PCI_EXP_LNKCTL, &val); + pci_read_config_word(adap->pdev, adap->pdev->pcie_cap + PCI_EXP_LNKCTL, + &val); fst_trn_tx = G_NUMFSTTRNSEQ(t3_read_reg(adap, A_PCIE_PEX_CTRL0)); fst_trn_rx = adap->params.rev == 0 ? fst_trn_tx : @@ -3421,13 +3425,15 @@ int t3_init_hw(struct adapter *adapter, u32 fw_params) static void get_pci_mode(struct adapter *adapter, struct pci_params *p) { static unsigned short speed_map[] = { 33, 66, 100, 133 }; - u32 pci_mode; + u32 pci_mode, pcie_cap; - if (pci_is_pcie(adapter->pdev)) { + pcie_cap = pci_pcie_cap(adapter->pdev); + if (pcie_cap) { u16 val; p->variant = PCI_VARIANT_PCIE; - pcie_capability_read_word(adapter->pdev, PCI_EXP_LNKSTA, &val); + pci_read_config_word(adapter->pdev, pcie_cap + PCI_EXP_LNKSTA, + &val); p->width = (val >> 4) & 0x3f; return; } diff --git a/trunk/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/trunk/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c index 933985420acb..5ed49af23d6a 100644 --- a/trunk/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c +++ b/trunk/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c @@ -3453,7 +3453,7 @@ static void eeh_resume(struct pci_dev *pdev) rtnl_unlock(); } -static const struct pci_error_handlers cxgb4_eeh = { +static struct pci_error_handlers cxgb4_eeh = { .error_detected = eeh_err_detected, .slot_reset = eeh_slot_reset, .resume = eeh_resume, @@ -3694,7 +3694,15 @@ static void __devinit print_port_info(const struct net_device *dev) static void __devinit enable_pcie_relaxed_ordering(struct pci_dev *dev) { - pcie_capability_set_word(dev, PCI_EXP_DEVCTL, PCI_EXP_DEVCTL_RELAX_EN); + u16 v; + int pos; + + pos = pci_pcie_cap(dev); + if (pos > 0) { + pci_read_config_word(dev, pos + PCI_EXP_DEVCTL, &v); + v |= PCI_EXP_DEVCTL_RELAX_EN; + pci_write_config_word(dev, pos + PCI_EXP_DEVCTL, v); + } } /* diff --git a/trunk/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c b/trunk/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c index af1601323173..fa947dfa4c30 100644 --- a/trunk/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c +++ b/trunk/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c @@ -2741,9 +2741,11 @@ static void __devinit get_pci_mode(struct adapter *adapter, struct pci_params *p) { u16 val; + u32 pcie_cap = pci_pcie_cap(adapter->pdev); - if (pci_is_pcie(adapter->pdev)) { - pcie_capability_read_word(adapter->pdev, PCI_EXP_LNKSTA, &val); + if (pcie_cap) { + pci_read_config_word(adapter->pdev, pcie_cap + PCI_EXP_LNKSTA, + &val); p->speed = val & PCI_EXP_LNKSTA_CLS; p->width = (val & PCI_EXP_LNKSTA_NLW) >> 4; } diff --git a/trunk/drivers/net/ethernet/cirrus/cs89x0.c b/trunk/drivers/net/ethernet/cirrus/cs89x0.c index 138446957786..845b2020f291 100644 --- a/trunk/drivers/net/ethernet/cirrus/cs89x0.c +++ b/trunk/drivers/net/ethernet/cirrus/cs89x0.c @@ -1243,7 +1243,6 @@ static void set_multicast_list(struct net_device *dev) { struct net_local *lp = netdev_priv(dev); unsigned long flags; - u16 cfg; spin_lock_irqsave(&lp->lock, flags); if (dev->flags & IFF_PROMISC) @@ -1261,10 +1260,11 @@ static void set_multicast_list(struct net_device *dev) /* in promiscuous mode, we accept errored packets, * so we have to enable interrupts on them also */ - cfg = lp->curr_rx_cfg; - if (lp->rx_mode == RX_ALL_ACCEPT) - cfg |= RX_CRC_ERROR_ENBL | RX_RUNT_ENBL | RX_EXTRA_DATA_ENBL; - writereg(dev, PP_RxCFG, cfg); + writereg(dev, PP_RxCFG, + (lp->curr_rx_cfg | + (lp->rx_mode == RX_ALL_ACCEPT) + ? (RX_CRC_ERROR_ENBL | RX_RUNT_ENBL | RX_EXTRA_DATA_ENBL) + : 0)); spin_unlock_irqrestore(&lp->lock, flags); } diff --git a/trunk/drivers/net/ethernet/emulex/benet/be_cmds.c b/trunk/drivers/net/ethernet/emulex/benet/be_cmds.c index 8c63d06ab12b..7fac97b4bb59 100644 --- a/trunk/drivers/net/ethernet/emulex/benet/be_cmds.c +++ b/trunk/drivers/net/ethernet/emulex/benet/be_cmds.c @@ -259,7 +259,7 @@ int be_process_mcc(struct be_adapter *adapter) int num = 0, status = 0; struct be_mcc_obj *mcc_obj = &adapter->mcc_obj; - spin_lock(&adapter->mcc_cq_lock); + spin_lock_bh(&adapter->mcc_cq_lock); while ((compl = be_mcc_compl_get(adapter))) { if (compl->flags & CQE_FLAGS_ASYNC_MASK) { /* Interpret flags as an async trailer */ @@ -280,7 +280,7 @@ int be_process_mcc(struct be_adapter *adapter) if (num) be_cq_notify(adapter, mcc_obj->cq.id, mcc_obj->rearm_cq, num); - spin_unlock(&adapter->mcc_cq_lock); + spin_unlock_bh(&adapter->mcc_cq_lock); return status; } @@ -295,9 +295,7 @@ static int be_mcc_wait_compl(struct be_adapter *adapter) if (be_error(adapter)) return -EIO; - local_bh_disable(); status = be_process_mcc(adapter); - local_bh_enable(); if (atomic_read(&mcc_obj->q.used) == 0) break; diff --git a/trunk/drivers/net/ethernet/emulex/benet/be_main.c b/trunk/drivers/net/ethernet/emulex/benet/be_main.c index 95d10472f236..c60de89b6669 100644 --- a/trunk/drivers/net/ethernet/emulex/benet/be_main.c +++ b/trunk/drivers/net/ethernet/emulex/benet/be_main.c @@ -1948,7 +1948,7 @@ static int be_rx_cqs_create(struct be_adapter *adapter) if (adapter->num_rx_qs != MAX_RX_QS) dev_info(&adapter->pdev->dev, - "Created only %d receive queues\n", adapter->num_rx_qs); + "Created only %d receive queues", adapter->num_rx_qs); return 0; } @@ -3763,9 +3763,7 @@ static void be_worker(struct work_struct *work) /* when interrupts are not yet enabled, just reap any pending * mcc completions */ if (!netif_running(adapter->netdev)) { - local_bh_disable(); be_process_mcc(adapter); - local_bh_enable(); goto reschedule; } @@ -4106,7 +4104,7 @@ static void be_eeh_resume(struct pci_dev *pdev) dev_err(&adapter->pdev->dev, "EEH resume failed\n"); } -static const struct pci_error_handlers be_eeh_handlers = { +static struct pci_error_handlers be_eeh_handlers = { .error_detected = be_eeh_err_detected, .slot_reset = be_eeh_reset, .resume = be_eeh_resume, diff --git a/trunk/drivers/net/ethernet/freescale/fs_enet/mii-bitbang.c b/trunk/drivers/net/ethernet/freescale/fs_enet/mii-bitbang.c index 151453309401..0f2d1a710909 100644 --- a/trunk/drivers/net/ethernet/freescale/fs_enet/mii-bitbang.c +++ b/trunk/drivers/net/ethernet/freescale/fs_enet/mii-bitbang.c @@ -174,10 +174,8 @@ static int __devinit fs_enet_mdio_probe(struct platform_device *ofdev) new_bus->phy_mask = ~0; new_bus->irq = kmalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL); - if (!new_bus->irq) { - ret = -ENOMEM; + if (!new_bus->irq) goto out_unmap_regs; - } new_bus->parent = &ofdev->dev; dev_set_drvdata(&ofdev->dev, new_bus); diff --git a/trunk/drivers/net/ethernet/freescale/fs_enet/mii-fec.c b/trunk/drivers/net/ethernet/freescale/fs_enet/mii-fec.c index cdf702a59485..55bb867258e6 100644 --- a/trunk/drivers/net/ethernet/freescale/fs_enet/mii-fec.c +++ b/trunk/drivers/net/ethernet/freescale/fs_enet/mii-fec.c @@ -137,10 +137,8 @@ static int __devinit fs_enet_mdio_probe(struct platform_device *ofdev) snprintf(new_bus->id, MII_BUS_ID_SIZE, "%x", res.start); fec->fecp = ioremap(res.start, resource_size(&res)); - if (!fec->fecp) { - ret = -ENOMEM; + if (!fec->fecp) goto out_fec; - } if (get_bus_freq) { clock = get_bus_freq(ofdev->dev.of_node); @@ -174,10 +172,8 @@ static int __devinit fs_enet_mdio_probe(struct platform_device *ofdev) new_bus->phy_mask = ~0; new_bus->irq = kmalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL); - if (!new_bus->irq) { - ret = -ENOMEM; + if (!new_bus->irq) goto out_unmap_regs; - } new_bus->parent = &ofdev->dev; dev_set_drvdata(&ofdev->dev, new_bus); diff --git a/trunk/drivers/net/ethernet/freescale/gianfar.c b/trunk/drivers/net/ethernet/freescale/gianfar.c index d3233f59a82e..4605f7246687 100644 --- a/trunk/drivers/net/ethernet/freescale/gianfar.c +++ b/trunk/drivers/net/ethernet/freescale/gianfar.c @@ -1041,7 +1041,7 @@ static int gfar_probe(struct platform_device *ofdev) if (priv->device_flags & FSL_GIANFAR_DEV_HAS_VLAN) { dev->hw_features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; - dev->features |= NETIF_F_HW_VLAN_RX; + dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; } if (priv->device_flags & FSL_GIANFAR_DEV_HAS_EXTENDED_HASH) { diff --git a/trunk/drivers/net/ethernet/freescale/gianfar_ethtool.c b/trunk/drivers/net/ethernet/freescale/gianfar_ethtool.c index ab6762caa957..8971921cc1c8 100644 --- a/trunk/drivers/net/ethernet/freescale/gianfar_ethtool.c +++ b/trunk/drivers/net/ethernet/freescale/gianfar_ethtool.c @@ -1773,7 +1773,6 @@ static int gfar_get_nfc(struct net_device *dev, struct ethtool_rxnfc *cmd, } int gfar_phc_index = -1; -EXPORT_SYMBOL(gfar_phc_index); static int gfar_get_ts_info(struct net_device *dev, struct ethtool_ts_info *info) diff --git a/trunk/drivers/net/ethernet/freescale/gianfar_ptp.c b/trunk/drivers/net/ethernet/freescale/gianfar_ptp.c index 0daa66b8eca0..c08e5d40fecb 100644 --- a/trunk/drivers/net/ethernet/freescale/gianfar_ptp.c +++ b/trunk/drivers/net/ethernet/freescale/gianfar_ptp.c @@ -515,7 +515,7 @@ static int gianfar_ptp_probe(struct platform_device *dev) err = PTR_ERR(etsects->clock); goto no_clock; } - gfar_phc_index = ptp_clock_index(etsects->clock); + gfar_phc_clock = ptp_clock_index(etsects->clock); dev_set_drvdata(&dev->dev, etsects); @@ -539,7 +539,7 @@ static int gianfar_ptp_remove(struct platform_device *dev) gfar_write(&etsects->regs->tmr_temask, 0); gfar_write(&etsects->regs->tmr_ctrl, 0); - gfar_phc_index = -1; + gfar_phc_clock = -1; ptp_clock_unregister(etsects->clock); iounmap(etsects->regs); release_resource(etsects->rsrc); diff --git a/trunk/drivers/net/ethernet/i825xx/znet.c b/trunk/drivers/net/ethernet/i825xx/znet.c index ba4e0cea3506..bd1f1ef91e19 100644 --- a/trunk/drivers/net/ethernet/i825xx/znet.c +++ b/trunk/drivers/net/ethernet/i825xx/znet.c @@ -139,11 +139,8 @@ struct znet_private { /* Only one can be built-in;-> */ static struct net_device *znet_dev; -#define NETIDBLK_MAGIC "NETIDBLK" -#define NETIDBLK_MAGIC_SIZE 8 - struct netidblk { - char magic[NETIDBLK_MAGIC_SIZE]; /* The magic number (string) "NETIDBLK" */ + char magic[8]; /* The magic number (string) "NETIDBLK" */ unsigned char netid[8]; /* The physical station address */ char nettype, globalopt; char vendor[8]; /* The machine vendor and product name. */ @@ -376,16 +373,14 @@ static int __init znet_probe (void) struct znet_private *znet; struct net_device *dev; char *p; - char *plast = phys_to_virt(0x100000 - NETIDBLK_MAGIC_SIZE); int err = -ENOMEM; /* This code scans the region 0xf0000 to 0xfffff for a "NETIDBLK". */ - for(p = (char *)phys_to_virt(0xf0000); p <= plast; p++) - if (*p == 'N' && - strncmp(p, NETIDBLK_MAGIC, NETIDBLK_MAGIC_SIZE) == 0) + for(p = (char *)phys_to_virt(0xf0000); p < (char *)phys_to_virt(0x100000); p++) + if (*p == 'N' && strncmp(p, "NETIDBLK", 8) == 0) break; - if (p > plast) { + if (p >= (char *)phys_to_virt(0x100000)) { if (znet_debug > 1) printk(KERN_INFO "No Z-Note ethernet adaptor found.\n"); return -ENODEV; diff --git a/trunk/drivers/net/ethernet/ibm/ibmveth.c b/trunk/drivers/net/ethernet/ibm/ibmveth.c index b68d28a130e6..9010cea68bc3 100644 --- a/trunk/drivers/net/ethernet/ibm/ibmveth.c +++ b/trunk/drivers/net/ethernet/ibm/ibmveth.c @@ -472,9 +472,14 @@ static void ibmveth_cleanup(struct ibmveth_adapter *adapter) } if (adapter->rx_queue.queue_addr != NULL) { - dma_free_coherent(dev, adapter->rx_queue.queue_len, - adapter->rx_queue.queue_addr, - adapter->rx_queue.queue_dma); + if (!dma_mapping_error(dev, adapter->rx_queue.queue_dma)) { + dma_unmap_single(dev, + adapter->rx_queue.queue_dma, + adapter->rx_queue.queue_len, + DMA_BIDIRECTIONAL); + adapter->rx_queue.queue_dma = DMA_ERROR_CODE; + } + kfree(adapter->rx_queue.queue_addr); adapter->rx_queue.queue_addr = NULL; } @@ -551,13 +556,10 @@ static int ibmveth_open(struct net_device *netdev) goto err_out; } - dev = &adapter->vdev->dev; - adapter->rx_queue.queue_len = sizeof(struct ibmveth_rx_q_entry) * rxq_entries; - adapter->rx_queue.queue_addr = - dma_alloc_coherent(dev, adapter->rx_queue.queue_len, - &adapter->rx_queue.queue_dma, GFP_KERNEL); + adapter->rx_queue.queue_addr = kmalloc(adapter->rx_queue.queue_len, + GFP_KERNEL); if (!adapter->rx_queue.queue_addr) { netdev_err(netdev, "unable to allocate rx queue pages\n"); @@ -565,13 +567,19 @@ static int ibmveth_open(struct net_device *netdev) goto err_out; } + dev = &adapter->vdev->dev; + adapter->buffer_list_dma = dma_map_single(dev, adapter->buffer_list_addr, 4096, DMA_BIDIRECTIONAL); adapter->filter_list_dma = dma_map_single(dev, adapter->filter_list_addr, 4096, DMA_BIDIRECTIONAL); + adapter->rx_queue.queue_dma = dma_map_single(dev, + adapter->rx_queue.queue_addr, + adapter->rx_queue.queue_len, DMA_BIDIRECTIONAL); if ((dma_mapping_error(dev, adapter->buffer_list_dma)) || - (dma_mapping_error(dev, adapter->filter_list_dma))) { + (dma_mapping_error(dev, adapter->filter_list_dma)) || + (dma_mapping_error(dev, adapter->rx_queue.queue_dma))) { netdev_err(netdev, "unable to map filter or buffer list " "pages\n"); rc = -ENOMEM; diff --git a/trunk/drivers/net/ethernet/intel/e100.c b/trunk/drivers/net/ethernet/intel/e100.c index 29ce9bd27f94..535f94fac4a1 100644 --- a/trunk/drivers/net/ethernet/intel/e100.c +++ b/trunk/drivers/net/ethernet/intel/e100.c @@ -3157,7 +3157,7 @@ static void e100_io_resume(struct pci_dev *pdev) } } -static const struct pci_error_handlers e100_err_handler = { +static struct pci_error_handlers e100_err_handler = { .error_detected = e100_io_error_detected, .slot_reset = e100_io_slot_reset, .resume = e100_io_resume, diff --git a/trunk/drivers/net/ethernet/intel/e1000/e1000_main.c b/trunk/drivers/net/ethernet/intel/e1000/e1000_main.c index f3f9aeb7d1e1..3bfbb8df8989 100644 --- a/trunk/drivers/net/ethernet/intel/e1000/e1000_main.c +++ b/trunk/drivers/net/ethernet/intel/e1000/e1000_main.c @@ -192,7 +192,7 @@ static pci_ers_result_t e1000_io_error_detected(struct pci_dev *pdev, static pci_ers_result_t e1000_io_slot_reset(struct pci_dev *pdev); static void e1000_io_resume(struct pci_dev *pdev); -static const struct pci_error_handlers e1000_err_handler = { +static struct pci_error_handlers e1000_err_handler = { .error_detected = e1000_io_error_detected, .slot_reset = e1000_io_slot_reset, .resume = e1000_io_resume, @@ -3149,17 +3149,6 @@ static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb, return NETDEV_TX_OK; } - /* On PCI/PCI-X HW, if packet size is less than ETH_ZLEN, - * packets may get corrupted during padding by HW. - * To WA this issue, pad all small packets manually. - */ - if (skb->len < ETH_ZLEN) { - if (skb_pad(skb, ETH_ZLEN - skb->len)) - return NETDEV_TX_OK; - skb->len = ETH_ZLEN; - skb_set_tail_pointer(skb, ETH_ZLEN); - } - mss = skb_shinfo(skb)->gso_size; /* The controller does a simple calculation to * make sure there is enough room in the FIFO before diff --git a/trunk/drivers/net/ethernet/intel/e1000e/82571.c b/trunk/drivers/net/ethernet/intel/e1000e/82571.c index 080c89093feb..0b3bade957fd 100644 --- a/trunk/drivers/net/ethernet/intel/e1000e/82571.c +++ b/trunk/drivers/net/ethernet/intel/e1000e/82571.c @@ -999,7 +999,7 @@ static s32 e1000_set_d0_lplu_state_82571(struct e1000_hw *hw, bool active) **/ static s32 e1000_reset_hw_82571(struct e1000_hw *hw) { - u32 ctrl, ctrl_ext, eecd, tctl; + u32 ctrl, ctrl_ext, eecd; s32 ret_val; /* @@ -1014,9 +1014,7 @@ static s32 e1000_reset_hw_82571(struct e1000_hw *hw) ew32(IMC, 0xffffffff); ew32(RCTL, 0); - tctl = er32(TCTL); - tctl &= ~E1000_TCTL_EN; - ew32(TCTL, tctl); + ew32(TCTL, E1000_TCTL_PSP); e1e_flush(); usleep_range(10000, 20000); @@ -1603,8 +1601,10 @@ static s32 e1000_check_for_serdes_link_82571(struct e1000_hw *hw) * auto-negotiation in the TXCW register and disable * forced link in the Device Control register in an * attempt to auto-negotiate with our link partner. + * If the partner code word is null, stop forcing + * and restart auto negotiation. */ - if (rxcw & E1000_RXCW_C) { + if ((rxcw & E1000_RXCW_C) || !(rxcw & E1000_RXCW_CW)) { /* Enable autoneg, and unforce link up */ ew32(TXCW, mac->txcw); ew32(CTRL, (ctrl & ~E1000_CTRL_SLU)); diff --git a/trunk/drivers/net/ethernet/intel/e1000e/e1000.h b/trunk/drivers/net/ethernet/intel/e1000e/e1000.h index cb3356c9af80..cd153326c3cf 100644 --- a/trunk/drivers/net/ethernet/intel/e1000e/e1000.h +++ b/trunk/drivers/net/ethernet/intel/e1000e/e1000.h @@ -310,7 +310,6 @@ struct e1000_adapter { */ struct e1000_ring *tx_ring /* One per active queue */ ____cacheline_aligned_in_smp; - u32 tx_fifo_limit; struct napi_struct napi; diff --git a/trunk/drivers/net/ethernet/intel/e1000e/netdev.c b/trunk/drivers/net/ethernet/intel/e1000e/netdev.c index 3f0223ac4c7c..95b245310f17 100644 --- a/trunk/drivers/net/ethernet/intel/e1000e/netdev.c +++ b/trunk/drivers/net/ethernet/intel/e1000e/netdev.c @@ -178,24 +178,6 @@ static void e1000_regdump(struct e1000_hw *hw, struct e1000_reg_info *reginfo) pr_info("%-15s %08x %08x\n", rname, regs[0], regs[1]); } -static void e1000e_dump_ps_pages(struct e1000_adapter *adapter, - struct e1000_buffer *bi) -{ - int i; - struct e1000_ps_page *ps_page; - - for (i = 0; i < adapter->rx_ps_pages; i++) { - ps_page = &bi->ps_pages[i]; - - if (ps_page->page) { - pr_info("packet dump for ps_page %d:\n", i); - print_hex_dump(KERN_INFO, "", DUMP_PREFIX_ADDRESS, - 16, 1, page_address(ps_page->page), - PAGE_SIZE, true); - } - } -} - /* * e1000e_dump - Print registers, Tx-ring and Rx-ring */ @@ -317,10 +299,10 @@ static void e1000e_dump(struct e1000_adapter *adapter) (unsigned long long)buffer_info->time_stamp, buffer_info->skb, next_desc); - if (netif_msg_pktdata(adapter) && buffer_info->skb) + if (netif_msg_pktdata(adapter) && buffer_info->dma != 0) print_hex_dump(KERN_INFO, "", DUMP_PREFIX_ADDRESS, - 16, 1, buffer_info->skb->data, - buffer_info->skb->len, true); + 16, 1, phys_to_virt(buffer_info->dma), + buffer_info->length, true); } /* Print Rx Ring Summary */ @@ -399,8 +381,10 @@ static void e1000e_dump(struct e1000_adapter *adapter) buffer_info->skb, next_desc); if (netif_msg_pktdata(adapter)) - e1000e_dump_ps_pages(adapter, - buffer_info); + print_hex_dump(KERN_INFO, "", + DUMP_PREFIX_ADDRESS, 16, 1, + phys_to_virt(buffer_info->dma), + adapter->rx_ps_bsize0, true); } } break; @@ -460,12 +444,12 @@ static void e1000e_dump(struct e1000_adapter *adapter) (unsigned long long)buffer_info->dma, buffer_info->skb, next_desc); - if (netif_msg_pktdata(adapter) && - buffer_info->skb) + if (netif_msg_pktdata(adapter)) print_hex_dump(KERN_INFO, "", DUMP_PREFIX_ADDRESS, 16, 1, - buffer_info->skb->data, + phys_to_virt + (buffer_info->dma), adapter->rx_buffer_len, true); } @@ -3516,15 +3500,6 @@ void e1000e_reset(struct e1000_adapter *adapter) break; } - /* - * Alignment of Tx data is on an arbitrary byte boundary with the - * maximum size per Tx descriptor limited only to the transmit - * allocation of the packet buffer minus 96 bytes with an upper - * limit of 24KB due to receive synchronization limitations. - */ - adapter->tx_fifo_limit = min_t(u32, ((er32(PBA) >> 16) << 10) - 96, - 24 << 10); - /* * Disable Adaptive Interrupt Moderation if 2 full packets cannot * fit in receive buffer. @@ -4794,9 +4769,12 @@ static bool e1000_tx_csum(struct e1000_ring *tx_ring, struct sk_buff *skb) return 1; } +#define E1000_MAX_PER_TXD 8192 +#define E1000_MAX_TXD_PWR 12 + static int e1000_tx_map(struct e1000_ring *tx_ring, struct sk_buff *skb, unsigned int first, unsigned int max_per_txd, - unsigned int nr_frags) + unsigned int nr_frags, unsigned int mss) { struct e1000_adapter *adapter = tx_ring->adapter; struct pci_dev *pdev = adapter->pdev; @@ -5029,19 +5007,20 @@ static int __e1000_maybe_stop_tx(struct e1000_ring *tx_ring, int size) static int e1000_maybe_stop_tx(struct e1000_ring *tx_ring, int size) { - BUG_ON(size > tx_ring->count); - if (e1000_desc_unused(tx_ring) >= size) return 0; return __e1000_maybe_stop_tx(tx_ring, size); } +#define TXD_USE_COUNT(S, X) (((S) >> (X)) + 1) static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev) { struct e1000_adapter *adapter = netdev_priv(netdev); struct e1000_ring *tx_ring = adapter->tx_ring; unsigned int first; + unsigned int max_per_txd = E1000_MAX_PER_TXD; + unsigned int max_txd_pwr = E1000_MAX_TXD_PWR; unsigned int tx_flags = 0; unsigned int len = skb_headlen(skb); unsigned int nr_frags; @@ -5061,8 +5040,18 @@ static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb, } mss = skb_shinfo(skb)->gso_size; + /* + * The controller does a simple calculation to + * make sure there is enough room in the FIFO before + * initiating the DMA for each buffer. The calc is: + * 4 = ceil(buffer len/mss). To make sure we don't + * overrun the FIFO, adjust the max buffer len if mss + * drops. + */ if (mss) { u8 hdr_len; + max_per_txd = min(mss << 2, max_per_txd); + max_txd_pwr = fls(max_per_txd) - 1; /* * TSO Workaround for 82571/2/3 Controllers -- if skb->data @@ -5092,12 +5081,12 @@ static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb, count++; count++; - count += DIV_ROUND_UP(len, adapter->tx_fifo_limit); + count += TXD_USE_COUNT(len, max_txd_pwr); nr_frags = skb_shinfo(skb)->nr_frags; for (f = 0; f < nr_frags; f++) - count += DIV_ROUND_UP(skb_frag_size(&skb_shinfo(skb)->frags[f]), - adapter->tx_fifo_limit); + count += TXD_USE_COUNT(skb_frag_size(&skb_shinfo(skb)->frags[f]), + max_txd_pwr); if (adapter->hw.mac.tx_pkt_filtering) e1000_transfer_dhcp_info(adapter, skb); @@ -5139,18 +5128,15 @@ static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb, tx_flags |= E1000_TX_FLAGS_NO_FCS; /* if count is 0 then mapping error has occurred */ - count = e1000_tx_map(tx_ring, skb, first, adapter->tx_fifo_limit, - nr_frags); + count = e1000_tx_map(tx_ring, skb, first, max_per_txd, nr_frags, mss); if (count) { skb_tx_timestamp(skb); netdev_sent_queue(netdev, skb->len); e1000_tx_queue(tx_ring, tx_flags, count); /* Make sure there is space in the ring for the next send. */ - e1000_maybe_stop_tx(tx_ring, - (MAX_SKB_FRAGS * - DIV_ROUND_UP(PAGE_SIZE, - adapter->tx_fifo_limit) + 2)); + e1000_maybe_stop_tx(tx_ring, MAX_SKB_FRAGS + 2); + } else { dev_kfree_skb_any(skb); tx_ring->buffer_info[first].time_stamp = 0; @@ -5584,15 +5570,16 @@ static void e1000_complete_shutdown(struct pci_dev *pdev, bool sleep, */ if (adapter->flags & FLAG_IS_QUAD_PORT) { struct pci_dev *us_dev = pdev->bus->self; + int pos = pci_pcie_cap(us_dev); u16 devctl; - pcie_capability_read_word(us_dev, PCI_EXP_DEVCTL, &devctl); - pcie_capability_write_word(us_dev, PCI_EXP_DEVCTL, - (devctl & ~PCI_EXP_DEVCTL_CERE)); + pci_read_config_word(us_dev, pos + PCI_EXP_DEVCTL, &devctl); + pci_write_config_word(us_dev, pos + PCI_EXP_DEVCTL, + (devctl & ~PCI_EXP_DEVCTL_CERE)); e1000_power_off(pdev, sleep, wake); - pcie_capability_write_word(us_dev, PCI_EXP_DEVCTL, devctl); + pci_write_config_word(us_dev, pos + PCI_EXP_DEVCTL, devctl); } else { e1000_power_off(pdev, sleep, wake); } @@ -5606,15 +5593,25 @@ static void __e1000e_disable_aspm(struct pci_dev *pdev, u16 state) #else static void __e1000e_disable_aspm(struct pci_dev *pdev, u16 state) { + int pos; + u16 reg16; + /* * Both device and parent should have the same ASPM setting. * Disable ASPM in downstream component first and then upstream. */ - pcie_capability_clear_word(pdev, PCI_EXP_LNKCTL, state); + pos = pci_pcie_cap(pdev); + pci_read_config_word(pdev, pos + PCI_EXP_LNKCTL, ®16); + reg16 &= ~state; + pci_write_config_word(pdev, pos + PCI_EXP_LNKCTL, reg16); + + if (!pdev->bus->self) + return; - if (pdev->bus->self) - pcie_capability_clear_word(pdev->bus->self, PCI_EXP_LNKCTL, - state); + pos = pci_pcie_cap(pdev->bus->self); + pci_read_config_word(pdev->bus->self, pos + PCI_EXP_LNKCTL, ®16); + reg16 &= ~state; + pci_write_config_word(pdev->bus->self, pos + PCI_EXP_LNKCTL, reg16); } #endif static void e1000e_disable_aspm(struct pci_dev *pdev, u16 state) @@ -6314,8 +6311,8 @@ static int __devinit e1000_probe(struct pci_dev *pdev, adapter->hw.phy.autoneg_advertised = 0x2f; /* ring size defaults */ - adapter->rx_ring->count = E1000_DEFAULT_RXD; - adapter->tx_ring->count = E1000_DEFAULT_TXD; + adapter->rx_ring->count = 256; + adapter->tx_ring->count = 256; /* * Initial Wake on LAN setting - If APM wake is enabled in @@ -6475,7 +6472,7 @@ static void __devexit e1000_remove(struct pci_dev *pdev) } /* PCI Error Recovery (ERS) */ -static const struct pci_error_handlers e1000_err_handler = { +static struct pci_error_handlers e1000_err_handler = { .error_detected = e1000_io_error_detected, .slot_reset = e1000_io_slot_reset, .resume = e1000_io_resume, diff --git a/trunk/drivers/net/ethernet/intel/igb/e1000_82575.c b/trunk/drivers/net/ethernet/intel/igb/e1000_82575.c index ba994fb4cec6..5e84eaac48c1 100644 --- a/trunk/drivers/net/ethernet/intel/igb/e1000_82575.c +++ b/trunk/drivers/net/ethernet/intel/igb/e1000_82575.c @@ -254,14 +254,6 @@ static s32 igb_get_invariants_82575(struct e1000_hw *hw) */ size += NVM_WORD_SIZE_BASE_SHIFT; - /* - * Check for invalid size - */ - if ((hw->mac.type == e1000_82576) && (size > 15)) { - pr_notice("The NVM size is not valid, defaulting to 32K\n"); - size = 15; - } - nvm->word_size = 1 << size; if (hw->mac.type < e1000_i210) { nvm->opcode_bits = 8; @@ -289,6 +281,14 @@ static s32 igb_get_invariants_82575(struct e1000_hw *hw) } else nvm->type = e1000_nvm_flash_hw; + /* + * Check for invalid size + */ + if ((hw->mac.type == e1000_82576) && (size > 15)) { + pr_notice("The NVM size is not valid, defaulting to 32K\n"); + size = 15; + } + /* NVM Function Pointers */ switch (hw->mac.type) { case e1000_82580: diff --git a/trunk/drivers/net/ethernet/intel/igb/e1000_regs.h b/trunk/drivers/net/ethernet/intel/igb/e1000_regs.h index 28394bea5253..10efcd88dca0 100644 --- a/trunk/drivers/net/ethernet/intel/igb/e1000_regs.h +++ b/trunk/drivers/net/ethernet/intel/igb/e1000_regs.h @@ -156,12 +156,8 @@ : (0x0E018 + ((_n) * 0x40))) #define E1000_TXDCTL(_n) ((_n) < 4 ? (0x03828 + ((_n) * 0x100)) \ : (0x0E028 + ((_n) * 0x40))) -#define E1000_RXCTL(_n) ((_n) < 4 ? (0x02814 + ((_n) * 0x100)) : \ - (0x0C014 + ((_n) * 0x40))) -#define E1000_DCA_RXCTRL(_n) E1000_RXCTL(_n) -#define E1000_TXCTL(_n) ((_n) < 4 ? (0x03814 + ((_n) * 0x100)) : \ - (0x0E014 + ((_n) * 0x40))) -#define E1000_DCA_TXCTRL(_n) E1000_TXCTL(_n) +#define E1000_DCA_TXCTRL(_n) (0x03814 + (_n << 8)) +#define E1000_DCA_RXCTRL(_n) (0x02814 + (_n << 8)) #define E1000_TDWBAL(_n) ((_n) < 4 ? (0x03838 + ((_n) * 0x100)) \ : (0x0E038 + ((_n) * 0x40))) #define E1000_TDWBAH(_n) ((_n) < 4 ? (0x0383C + ((_n) * 0x100)) \ diff --git a/trunk/drivers/net/ethernet/intel/igb/igb_ethtool.c b/trunk/drivers/net/ethernet/intel/igb/igb_ethtool.c index 70591117051b..a19c84cad0e9 100644 --- a/trunk/drivers/net/ethernet/intel/igb/igb_ethtool.c +++ b/trunk/drivers/net/ethernet/intel/igb/igb_ethtool.c @@ -209,8 +209,8 @@ static int igb_set_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) /* When SoL/IDER sessions are active, autoneg/speed/duplex * cannot be changed */ if (igb_check_reset_block(hw)) { - dev_err(&adapter->pdev->dev, - "Cannot change link characteristics when SoL/IDER is active.\n"); + dev_err(&adapter->pdev->dev, "Cannot change link " + "characteristics when SoL/IDER is active.\n"); return -EINVAL; } @@ -1089,8 +1089,8 @@ static bool reg_pattern_test(struct igb_adapter *adapter, u64 *data, wr32(reg, (_test[pat] & write)); val = rd32(reg) & mask; if (val != (_test[pat] & write & mask)) { - dev_err(&adapter->pdev->dev, - "pattern test reg %04X failed: got 0x%08X expected 0x%08X\n", + dev_err(&adapter->pdev->dev, "pattern test reg %04X " + "failed: got 0x%08X expected 0x%08X\n", reg, val, (_test[pat] & write & mask)); *data = reg; return 1; @@ -1108,8 +1108,8 @@ static bool reg_set_and_check(struct igb_adapter *adapter, u64 *data, wr32(reg, write & mask); val = rd32(reg); if ((write & mask) != (val & mask)) { - dev_err(&adapter->pdev->dev, - "set/check reg %04X test failed: got 0x%08X expected 0x%08X\n", reg, + dev_err(&adapter->pdev->dev, "set/check reg %04X test failed:" + " got 0x%08X expected 0x%08X\n", reg, (val & mask), (write & mask)); *data = reg; return 1; @@ -1171,9 +1171,8 @@ static int igb_reg_test(struct igb_adapter *adapter, u64 *data) wr32(E1000_STATUS, toggle); after = rd32(E1000_STATUS) & toggle; if (value != after) { - dev_err(&adapter->pdev->dev, - "failed STATUS register test got: 0x%08X expected: 0x%08X\n", - after, value); + dev_err(&adapter->pdev->dev, "failed STATUS register test " + "got: 0x%08X expected: 0x%08X\n", after, value); *data = 1; return 1; } @@ -1498,9 +1497,6 @@ static int igb_integrated_phy_loopback(struct igb_adapter *adapter) break; } - /* add small delay to avoid loopback test failure */ - msleep(50); - /* force 1000, set loopback */ igb_write_phy_reg(hw, PHY_CONTROL, 0x4140); @@ -1781,14 +1777,16 @@ static int igb_loopback_test(struct igb_adapter *adapter, u64 *data) * sessions are active */ if (igb_check_reset_block(&adapter->hw)) { dev_err(&adapter->pdev->dev, - "Cannot do PHY loopback test when SoL/IDER is active.\n"); + "Cannot do PHY loopback test " + "when SoL/IDER is active.\n"); *data = 0; goto out; } if ((adapter->hw.mac.type == e1000_i210) - || (adapter->hw.mac.type == e1000_i211)) { + || (adapter->hw.mac.type == e1000_i210)) { dev_err(&adapter->pdev->dev, - "Loopback test not supported on this part at this time.\n"); + "Loopback test not supported " + "on this part at this time.\n"); *data = 0; goto out; } diff --git a/trunk/drivers/net/ethernet/intel/igb/igb_main.c b/trunk/drivers/net/ethernet/intel/igb/igb_main.c index f88c822e57a6..b7c2d5050572 100644 --- a/trunk/drivers/net/ethernet/intel/igb/igb_main.c +++ b/trunk/drivers/net/ethernet/intel/igb/igb_main.c @@ -217,7 +217,7 @@ static pci_ers_result_t igb_io_error_detected(struct pci_dev *, static pci_ers_result_t igb_io_slot_reset(struct pci_dev *); static void igb_io_resume(struct pci_dev *); -static const struct pci_error_handlers igb_err_handler = { +static struct pci_error_handlers igb_err_handler = { .error_detected = igb_io_error_detected, .slot_reset = igb_io_slot_reset, .resume = igb_io_resume, @@ -462,10 +462,10 @@ static void igb_dump(struct igb_adapter *adapter) (u64)buffer_info->time_stamp, buffer_info->skb, next_desc); - if (netif_msg_pktdata(adapter) && buffer_info->skb) + if (netif_msg_pktdata(adapter) && buffer_info->dma != 0) print_hex_dump(KERN_INFO, "", DUMP_PREFIX_ADDRESS, - 16, 1, buffer_info->skb->data, + 16, 1, phys_to_virt(buffer_info->dma), buffer_info->length, true); } } @@ -547,17 +547,18 @@ static void igb_dump(struct igb_adapter *adapter) (u64)buffer_info->dma, buffer_info->skb, next_desc); - if (netif_msg_pktdata(adapter) && - buffer_info->dma && buffer_info->skb) { + if (netif_msg_pktdata(adapter)) { print_hex_dump(KERN_INFO, "", - DUMP_PREFIX_ADDRESS, - 16, 1, buffer_info->skb->data, - IGB_RX_HDR_LEN, true); + DUMP_PREFIX_ADDRESS, + 16, 1, + phys_to_virt(buffer_info->dma), + IGB_RX_HDR_LEN, true); print_hex_dump(KERN_INFO, "", DUMP_PREFIX_ADDRESS, 16, 1, - page_address(buffer_info->page) + - buffer_info->page_offset, + phys_to_virt( + buffer_info->page_dma + + buffer_info->page_offset), PAGE_SIZE/2, true); } } @@ -6538,20 +6539,28 @@ static int igb_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) s32 igb_read_pcie_cap_reg(struct e1000_hw *hw, u32 reg, u16 *value) { struct igb_adapter *adapter = hw->back; + u16 cap_offset; - if (pcie_capability_read_word(adapter->pdev, reg, value)) + cap_offset = adapter->pdev->pcie_cap; + if (!cap_offset) return -E1000_ERR_CONFIG; + pci_read_config_word(adapter->pdev, cap_offset + reg, value); + return 0; } s32 igb_write_pcie_cap_reg(struct e1000_hw *hw, u32 reg, u16 *value) { struct igb_adapter *adapter = hw->back; + u16 cap_offset; - if (pcie_capability_write_word(adapter->pdev, reg, *value)) + cap_offset = adapter->pdev->pcie_cap; + if (!cap_offset) return -E1000_ERR_CONFIG; + pci_write_config_word(adapter->pdev, cap_offset + reg, *value); + return 0; } diff --git a/trunk/drivers/net/ethernet/intel/igbvf/netdev.c b/trunk/drivers/net/ethernet/intel/igbvf/netdev.c index 0ac11f527a84..0696abfe9944 100644 --- a/trunk/drivers/net/ethernet/intel/igbvf/netdev.c +++ b/trunk/drivers/net/ethernet/intel/igbvf/netdev.c @@ -2833,7 +2833,7 @@ static void __devexit igbvf_remove(struct pci_dev *pdev) } /* PCI Error Recovery (ERS) */ -static const struct pci_error_handlers igbvf_err_handler = { +static struct pci_error_handlers igbvf_err_handler = { .error_detected = igbvf_io_error_detected, .slot_reset = igbvf_io_slot_reset, .resume = igbvf_io_resume, diff --git a/trunk/drivers/net/ethernet/intel/ixgb/ixgb_main.c b/trunk/drivers/net/ethernet/intel/ixgb/ixgb_main.c index d99a2d51b948..d05fc95befc5 100644 --- a/trunk/drivers/net/ethernet/intel/ixgb/ixgb_main.c +++ b/trunk/drivers/net/ethernet/intel/ixgb/ixgb_main.c @@ -115,7 +115,7 @@ static pci_ers_result_t ixgb_io_error_detected (struct pci_dev *pdev, static pci_ers_result_t ixgb_io_slot_reset (struct pci_dev *pdev); static void ixgb_io_resume (struct pci_dev *pdev); -static const struct pci_error_handlers ixgb_err_handler = { +static struct pci_error_handlers ixgb_err_handler = { .error_detected = ixgb_io_error_detected, .slot_reset = ixgb_io_slot_reset, .resume = ixgb_io_resume, diff --git a/trunk/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c b/trunk/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c index 18bf08c9d7a4..50fc137501da 100644 --- a/trunk/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c +++ b/trunk/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c @@ -804,13 +804,12 @@ static s32 ixgbe_setup_mac_link_82599(struct ixgbe_hw *hw, link_mode == IXGBE_AUTOC_LMS_KX4_KX_KR_SGMII) { /* Set KX4/KX/KR support according to speed requested */ autoc &= ~(IXGBE_AUTOC_KX4_KX_SUPP_MASK | IXGBE_AUTOC_KR_SUPP); - if (speed & IXGBE_LINK_SPEED_10GB_FULL) { + if (speed & IXGBE_LINK_SPEED_10GB_FULL) if (orig_autoc & IXGBE_AUTOC_KX4_SUPP) autoc |= IXGBE_AUTOC_KX4_SUPP; if ((orig_autoc & IXGBE_AUTOC_KR_SUPP) && (hw->phy.smart_speed_active == false)) autoc |= IXGBE_AUTOC_KR_SUPP; - } if (speed & IXGBE_LINK_SPEED_1GB_FULL) autoc |= IXGBE_AUTOC_KX_SUPP; } else if ((pma_pmd_1g == IXGBE_AUTOC_1G_SFI) && diff --git a/trunk/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/trunk/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index ee61819d6088..4326f74f7137 100644 --- a/trunk/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/trunk/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -7527,7 +7527,7 @@ static pci_ers_result_t ixgbe_io_error_detected(struct pci_dev *pdev, goto skip_bad_vf_detection; bdev = pdev->bus->self; - while (bdev && (pci_pcie_type(bdev) != PCI_EXP_TYPE_ROOT_PORT)) + while (bdev && (bdev->pcie_type != PCI_EXP_TYPE_ROOT_PORT)) bdev = bdev->bus->self; if (!bdev) @@ -7677,7 +7677,7 @@ static void ixgbe_io_resume(struct pci_dev *pdev) netif_device_attach(netdev); } -static const struct pci_error_handlers ixgbe_err_handler = { +static struct pci_error_handlers ixgbe_err_handler = { .error_detected = ixgbe_io_error_detected, .slot_reset = ixgbe_io_slot_reset, .resume = ixgbe_io_resume, diff --git a/trunk/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c b/trunk/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c index 6647383c4ddc..60ef64587412 100644 --- a/trunk/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c +++ b/trunk/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c @@ -3256,7 +3256,7 @@ static void ixgbevf_io_resume(struct pci_dev *pdev) } /* PCI Error Recovery (ERS) */ -static const struct pci_error_handlers ixgbevf_err_handler = { +static struct pci_error_handlers ixgbevf_err_handler = { .error_detected = ixgbevf_io_error_detected, .slot_reset = ixgbevf_io_slot_reset, .resume = ixgbevf_io_resume, diff --git a/trunk/drivers/net/ethernet/mellanox/mlx4/en_rx.c b/trunk/drivers/net/ethernet/mellanox/mlx4/en_rx.c index 5aba5ecdf1e2..f32e70300770 100644 --- a/trunk/drivers/net/ethernet/mellanox/mlx4/en_rx.c +++ b/trunk/drivers/net/ethernet/mellanox/mlx4/en_rx.c @@ -614,8 +614,8 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud /* If source MAC is equal to our own MAC and not performing * the selftest or flb disabled - drop the packet */ if (s_mac == priv->mac && - !((dev->features & NETIF_F_LOOPBACK) || - priv->validate_loopback)) + (!(dev->features & NETIF_F_LOOPBACK) || + !priv->validate_loopback)) goto next; /* diff --git a/trunk/drivers/net/ethernet/mellanox/mlx4/en_tx.c b/trunk/drivers/net/ethernet/mellanox/mlx4/en_tx.c index 10bba09c44ea..019d856b1334 100644 --- a/trunk/drivers/net/ethernet/mellanox/mlx4/en_tx.c +++ b/trunk/drivers/net/ethernet/mellanox/mlx4/en_tx.c @@ -164,6 +164,7 @@ int mlx4_en_activate_tx_ring(struct mlx4_en_priv *priv, 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); @@ -364,13 +365,14 @@ static void mlx4_en_process_tx_cq(struct net_device *dev, struct mlx4_en_cq *cq) ring->cons += txbbs_skipped; netdev_tx_completed_queue(ring->tx_queue, packets, bytes); - /* - * Wakeup Tx queue if this stopped, and at least 1 packet - * was completed - */ - if (netif_tx_queue_stopped(ring->tx_queue) && txbbs_skipped > 0) { - netif_tx_wake_queue(ring->tx_queue); - priv->port_stats.wake_queue++; + /* Wakeup Tx queue if this ring stopped it */ + if (unlikely(ring->blocked)) { + if ((u32) (ring->prod - ring->cons) <= + ring->size - HEADROOM - MAX_DESC_TXBBS) { + ring->blocked = 0; + netif_tx_wake_queue(ring->tx_queue); + priv->port_stats.wake_queue++; + } } } @@ -590,6 +592,7 @@ netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev) ring->size - HEADROOM - MAX_DESC_TXBBS)) { /* every full Tx ring stops queue */ netif_tx_stop_queue(ring->tx_queue); + ring->blocked = 1; priv->port_stats.queue_stopped++; return NETDEV_TX_BUSY; diff --git a/trunk/drivers/net/ethernet/mellanox/mlx4/icm.c b/trunk/drivers/net/ethernet/mellanox/mlx4/icm.c index 31d02649be41..88b7b3e75ab1 100644 --- a/trunk/drivers/net/ethernet/mellanox/mlx4/icm.c +++ b/trunk/drivers/net/ethernet/mellanox/mlx4/icm.c @@ -227,10 +227,9 @@ int mlx4_UNMAP_ICM_AUX(struct mlx4_dev *dev) MLX4_CMD_TIME_CLASS_B, MLX4_CMD_NATIVE); } -int mlx4_table_get(struct mlx4_dev *dev, struct mlx4_icm_table *table, u32 obj) +int mlx4_table_get(struct mlx4_dev *dev, struct mlx4_icm_table *table, int obj) { - u32 i = (obj & (table->num_obj - 1)) / - (MLX4_TABLE_CHUNK_SIZE / table->obj_size); + int i = (obj & (table->num_obj - 1)) / (MLX4_TABLE_CHUNK_SIZE / table->obj_size); int ret = 0; mutex_lock(&table->mutex); @@ -263,18 +262,16 @@ int mlx4_table_get(struct mlx4_dev *dev, struct mlx4_icm_table *table, u32 obj) return ret; } -void mlx4_table_put(struct mlx4_dev *dev, struct mlx4_icm_table *table, u32 obj) +void mlx4_table_put(struct mlx4_dev *dev, struct mlx4_icm_table *table, int obj) { - u32 i; - u64 offset; + int i; i = (obj & (table->num_obj - 1)) / (MLX4_TABLE_CHUNK_SIZE / table->obj_size); mutex_lock(&table->mutex); if (--table->icm[i]->refcount == 0) { - offset = (u64) i * MLX4_TABLE_CHUNK_SIZE; - mlx4_UNMAP_ICM(dev, table->virt + offset, + mlx4_UNMAP_ICM(dev, table->virt + i * MLX4_TABLE_CHUNK_SIZE, MLX4_TABLE_CHUNK_SIZE / MLX4_ICM_PAGE_SIZE); mlx4_free_icm(dev, table->icm[i], table->coherent); table->icm[i] = NULL; @@ -283,11 +280,9 @@ void mlx4_table_put(struct mlx4_dev *dev, struct mlx4_icm_table *table, u32 obj) mutex_unlock(&table->mutex); } -void *mlx4_table_find(struct mlx4_icm_table *table, u32 obj, - dma_addr_t *dma_handle) +void *mlx4_table_find(struct mlx4_icm_table *table, int obj, dma_addr_t *dma_handle) { - int offset, dma_offset, i; - u64 idx; + int idx, offset, dma_offset, i; struct mlx4_icm_chunk *chunk; struct mlx4_icm *icm; struct page *page = NULL; @@ -297,7 +292,7 @@ void *mlx4_table_find(struct mlx4_icm_table *table, u32 obj, mutex_lock(&table->mutex); - idx = (u64) (obj & (table->num_obj - 1)) * table->obj_size; + idx = (obj & (table->num_obj - 1)) * table->obj_size; icm = table->icm[idx / MLX4_TABLE_CHUNK_SIZE]; dma_offset = offset = idx % MLX4_TABLE_CHUNK_SIZE; @@ -331,11 +326,10 @@ void *mlx4_table_find(struct mlx4_icm_table *table, u32 obj, } int mlx4_table_get_range(struct mlx4_dev *dev, struct mlx4_icm_table *table, - u32 start, u32 end) + int start, int end) { int inc = MLX4_TABLE_CHUNK_SIZE / table->obj_size; - int err; - u32 i; + int i, err; for (i = start; i <= end; i += inc) { err = mlx4_table_get(dev, table, i); @@ -355,23 +349,22 @@ int mlx4_table_get_range(struct mlx4_dev *dev, struct mlx4_icm_table *table, } void mlx4_table_put_range(struct mlx4_dev *dev, struct mlx4_icm_table *table, - u32 start, u32 end) + int start, int end) { - u32 i; + int i; for (i = start; i <= end; i += MLX4_TABLE_CHUNK_SIZE / table->obj_size) mlx4_table_put(dev, table, i); } int mlx4_init_icm_table(struct mlx4_dev *dev, struct mlx4_icm_table *table, - u64 virt, int obj_size, u32 nobj, int reserved, + u64 virt, int obj_size, int nobj, int reserved, int use_lowmem, int use_coherent) { int obj_per_chunk; int num_icm; unsigned chunk_size; int i; - u64 size; obj_per_chunk = MLX4_TABLE_CHUNK_SIZE / obj_size; num_icm = (nobj + obj_per_chunk - 1) / obj_per_chunk; @@ -387,12 +380,10 @@ int mlx4_init_icm_table(struct mlx4_dev *dev, struct mlx4_icm_table *table, table->coherent = use_coherent; mutex_init(&table->mutex); - size = (u64) nobj * obj_size; for (i = 0; i * MLX4_TABLE_CHUNK_SIZE < reserved * obj_size; ++i) { chunk_size = MLX4_TABLE_CHUNK_SIZE; - if ((i + 1) * MLX4_TABLE_CHUNK_SIZE > size) - chunk_size = PAGE_ALIGN(size - - i * MLX4_TABLE_CHUNK_SIZE); + if ((i + 1) * MLX4_TABLE_CHUNK_SIZE > nobj * obj_size) + chunk_size = PAGE_ALIGN(nobj * obj_size - i * MLX4_TABLE_CHUNK_SIZE); table->icm[i] = mlx4_alloc_icm(dev, chunk_size >> PAGE_SHIFT, (use_lowmem ? GFP_KERNEL : GFP_HIGHUSER) | diff --git a/trunk/drivers/net/ethernet/mellanox/mlx4/icm.h b/trunk/drivers/net/ethernet/mellanox/mlx4/icm.h index dee67fa39107..19e4efc0b342 100644 --- a/trunk/drivers/net/ethernet/mellanox/mlx4/icm.h +++ b/trunk/drivers/net/ethernet/mellanox/mlx4/icm.h @@ -71,17 +71,17 @@ struct mlx4_icm *mlx4_alloc_icm(struct mlx4_dev *dev, int npages, gfp_t gfp_mask, int coherent); void mlx4_free_icm(struct mlx4_dev *dev, struct mlx4_icm *icm, int coherent); -int mlx4_table_get(struct mlx4_dev *dev, struct mlx4_icm_table *table, u32 obj); -void mlx4_table_put(struct mlx4_dev *dev, struct mlx4_icm_table *table, u32 obj); +int mlx4_table_get(struct mlx4_dev *dev, struct mlx4_icm_table *table, int obj); +void mlx4_table_put(struct mlx4_dev *dev, struct mlx4_icm_table *table, int obj); int mlx4_table_get_range(struct mlx4_dev *dev, struct mlx4_icm_table *table, - u32 start, u32 end); + int start, int end); void mlx4_table_put_range(struct mlx4_dev *dev, struct mlx4_icm_table *table, - u32 start, u32 end); + int start, int end); int mlx4_init_icm_table(struct mlx4_dev *dev, struct mlx4_icm_table *table, - u64 virt, int obj_size, u32 nobj, int reserved, + u64 virt, int obj_size, int nobj, int reserved, int use_lowmem, int use_coherent); void mlx4_cleanup_icm_table(struct mlx4_dev *dev, struct mlx4_icm_table *table); -void *mlx4_table_find(struct mlx4_icm_table *table, u32 obj, dma_addr_t *dma_handle); +void *mlx4_table_find(struct mlx4_icm_table *table, int obj, dma_addr_t *dma_handle); static inline void mlx4_icm_first(struct mlx4_icm *icm, struct mlx4_icm_iter *iter) diff --git a/trunk/drivers/net/ethernet/mellanox/mlx4/main.c b/trunk/drivers/net/ethernet/mellanox/mlx4/main.c index dd6ea942625c..48d0e90194cb 100644 --- a/trunk/drivers/net/ethernet/mellanox/mlx4/main.c +++ b/trunk/drivers/net/ethernet/mellanox/mlx4/main.c @@ -157,6 +157,9 @@ int mlx4_check_port_params(struct mlx4_dev *dev, "on this HCA, aborting.\n"); return -EINVAL; } + if (port_type[i] == MLX4_PORT_TYPE_ETH && + port_type[i + 1] == MLX4_PORT_TYPE_IB) + return -EINVAL; } } @@ -1234,13 +1237,13 @@ static int mlx4_init_hca(struct mlx4_dev *dev) mlx4_info(dev, "non-primary physical function, skipping.\n"); else mlx4_err(dev, "QUERY_FW command failed, aborting.\n"); - return err; + goto unmap_bf; } err = mlx4_load_fw(dev); if (err) { mlx4_err(dev, "Failed to start FW, aborting.\n"); - return err; + goto unmap_bf; } mlx4_cfg.log_pg_sz_m = 1; @@ -1304,7 +1307,7 @@ static int mlx4_init_hca(struct mlx4_dev *dev) err = mlx4_init_slave(dev); if (err) { mlx4_err(dev, "Failed to initialize slave\n"); - return err; + goto unmap_bf; } err = mlx4_slave_cap(dev); @@ -1324,7 +1327,7 @@ static int mlx4_init_hca(struct mlx4_dev *dev) err = mlx4_QUERY_ADAPTER(dev, &adapter); if (err) { mlx4_err(dev, "QUERY_ADAPTER command failed, aborting.\n"); - goto unmap_bf; + goto err_close; } priv->eq_table.inta_pin = adapter.inta_pin; @@ -1332,9 +1335,6 @@ static int mlx4_init_hca(struct mlx4_dev *dev) return 0; -unmap_bf: - unmap_bf_area(dev); - err_close: mlx4_close_hca(dev); @@ -1347,6 +1347,8 @@ static int mlx4_init_hca(struct mlx4_dev *dev) mlx4_UNMAP_FA(dev); mlx4_free_icm(dev, priv->fw.fw_icm, 0); } +unmap_bf: + unmap_bf_area(dev); return err; } @@ -1997,8 +1999,7 @@ static int __mlx4_init_one(struct pci_dev *pdev, const struct pci_device_id *id) } slave_start: - err = mlx4_cmd_init(dev); - if (err) { + if (mlx4_cmd_init(dev)) { mlx4_err(dev, "Failed to init command interface, aborting.\n"); goto err_sriov; } @@ -2300,7 +2301,7 @@ static pci_ers_result_t mlx4_pci_slot_reset(struct pci_dev *pdev) return ret ? PCI_ERS_RESULT_DISCONNECT : PCI_ERS_RESULT_RECOVERED; } -static const struct pci_error_handlers mlx4_err_handler = { +static struct pci_error_handlers mlx4_err_handler = { .error_detected = mlx4_pci_err_detected, .slot_reset = mlx4_pci_slot_reset, }; diff --git a/trunk/drivers/net/ethernet/mellanox/mlx4/mcg.c b/trunk/drivers/net/ethernet/mellanox/mlx4/mcg.c index e151c21baf2b..4ec3835e1bc2 100644 --- a/trunk/drivers/net/ethernet/mellanox/mlx4/mcg.c +++ b/trunk/drivers/net/ethernet/mellanox/mlx4/mcg.c @@ -137,11 +137,11 @@ static int mlx4_GID_HASH(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox, return err; } -static struct mlx4_promisc_qp *get_promisc_qp(struct mlx4_dev *dev, u8 port, +static struct mlx4_promisc_qp *get_promisc_qp(struct mlx4_dev *dev, u8 pf_num, enum mlx4_steer_type steer, u32 qpn) { - struct mlx4_steer *s_steer = &mlx4_priv(dev)->steer[port - 1]; + struct mlx4_steer *s_steer = &mlx4_priv(dev)->steer[pf_num]; struct mlx4_promisc_qp *pqp; list_for_each_entry(pqp, &s_steer->promisc_qps[steer], list) { @@ -182,7 +182,7 @@ static int new_steering_entry(struct mlx4_dev *dev, u8 port, /* If the given qpn is also a promisc qp, * it should be inserted to duplicates list */ - pqp = get_promisc_qp(dev, port, steer, qpn); + pqp = get_promisc_qp(dev, 0, steer, qpn); if (pqp) { dqp = kmalloc(sizeof *dqp, GFP_KERNEL); if (!dqp) { @@ -256,7 +256,7 @@ static int existing_steering_entry(struct mlx4_dev *dev, u8 port, s_steer = &mlx4_priv(dev)->steer[port - 1]; - pqp = get_promisc_qp(dev, port, steer, qpn); + pqp = get_promisc_qp(dev, 0, steer, qpn); if (!pqp) return 0; /* nothing to do */ @@ -302,7 +302,7 @@ static bool check_duplicate_entry(struct mlx4_dev *dev, u8 port, s_steer = &mlx4_priv(dev)->steer[port - 1]; /* if qp is not promisc, it cannot be duplicated */ - if (!get_promisc_qp(dev, port, steer, qpn)) + if (!get_promisc_qp(dev, 0, steer, qpn)) return false; /* The qp is promisc qp so it is a duplicate on this index @@ -352,7 +352,7 @@ static bool can_remove_steering_entry(struct mlx4_dev *dev, u8 port, members_count = be32_to_cpu(mgm->members_count) & 0xffffff; for (i = 0; i < members_count; i++) { qpn = be32_to_cpu(mgm->qp[i]) & MGM_QPN_MASK; - if (!get_promisc_qp(dev, port, steer, qpn) && qpn != tqpn) { + if (!get_promisc_qp(dev, 0, steer, qpn) && qpn != tqpn) { /* the qp is not promisc, the entry can't be removed */ goto out; } @@ -398,7 +398,7 @@ static int add_promisc_qp(struct mlx4_dev *dev, u8 port, mutex_lock(&priv->mcg_table.mutex); - if (get_promisc_qp(dev, port, steer, qpn)) { + if (get_promisc_qp(dev, 0, steer, qpn)) { err = 0; /* Noting to do, already exists */ goto out_mutex; } @@ -432,10 +432,8 @@ static int add_promisc_qp(struct mlx4_dev *dev, u8 port, if ((be32_to_cpu(mgm->qp[i]) & MGM_QPN_MASK) == qpn) { /* Entry already exists, add to duplicates */ dqp = kmalloc(sizeof *dqp, GFP_KERNEL); - if (!dqp) { - err = -ENOMEM; + if (!dqp) goto out_mailbox; - } dqp->qpn = qpn; list_add_tail(&dqp->list, &entry->duplicates); found = true; @@ -503,7 +501,7 @@ static int remove_promisc_qp(struct mlx4_dev *dev, u8 port, s_steer = &mlx4_priv(dev)->steer[port - 1]; mutex_lock(&priv->mcg_table.mutex); - pqp = get_promisc_qp(dev, port, steer, qpn); + pqp = get_promisc_qp(dev, 0, steer, qpn); if (unlikely(!pqp)) { mlx4_warn(dev, "QP %x is not promiscuous QP\n", qpn); /* nothing to do */ @@ -650,6 +648,13 @@ static int find_entry(struct mlx4_dev *dev, u8 port, return err; } +struct mlx4_net_trans_rule_hw_ctrl { + __be32 ctrl; + __be32 vf_vep_port; + __be32 qpn; + __be32 reserved; +}; + static void trans_rule_ctrl_to_hw(struct mlx4_net_trans_rule *ctrl, struct mlx4_net_trans_rule_hw_ctrl *hw) { @@ -673,18 +678,87 @@ static void trans_rule_ctrl_to_hw(struct mlx4_net_trans_rule *ctrl, hw->qpn = cpu_to_be32(ctrl->qpn); } -const u16 __sw_id_hw[] = { - [MLX4_NET_TRANS_RULE_ID_ETH] = 0xE001, - [MLX4_NET_TRANS_RULE_ID_IB] = 0xE005, - [MLX4_NET_TRANS_RULE_ID_IPV6] = 0xE003, - [MLX4_NET_TRANS_RULE_ID_IPV4] = 0xE002, - [MLX4_NET_TRANS_RULE_ID_TCP] = 0xE004, - [MLX4_NET_TRANS_RULE_ID_UDP] = 0xE006 +struct mlx4_net_trans_rule_hw_ib { + u8 size; + u8 rsvd1; + __be16 id; + u32 rsvd2; + __be32 qpn; + __be32 qpn_mask; + u8 dst_gid[16]; + u8 dst_gid_msk[16]; +} __packed; + +struct mlx4_net_trans_rule_hw_eth { + u8 size; + u8 rsvd; + __be16 id; + u8 rsvd1[6]; + u8 dst_mac[6]; + u16 rsvd2; + u8 dst_mac_msk[6]; + u16 rsvd3; + u8 src_mac[6]; + u16 rsvd4; + u8 src_mac_msk[6]; + u8 rsvd5; + u8 ether_type_enable; + __be16 ether_type; + __be16 vlan_id_msk; + __be16 vlan_id; +} __packed; + +struct mlx4_net_trans_rule_hw_tcp_udp { + u8 size; + u8 rsvd; + __be16 id; + __be16 rsvd1[3]; + __be16 dst_port; + __be16 rsvd2; + __be16 dst_port_msk; + __be16 rsvd3; + __be16 src_port; + __be16 rsvd4; + __be16 src_port_msk; +} __packed; + +struct mlx4_net_trans_rule_hw_ipv4 { + u8 size; + u8 rsvd; + __be16 id; + __be32 rsvd1; + __be32 dst_ip; + __be32 dst_ip_msk; + __be32 src_ip; + __be32 src_ip_msk; +} __packed; + +struct _rule_hw { + union { + struct { + u8 size; + u8 rsvd; + __be16 id; + }; + struct mlx4_net_trans_rule_hw_eth eth; + struct mlx4_net_trans_rule_hw_ib ib; + struct mlx4_net_trans_rule_hw_ipv4 ipv4; + struct mlx4_net_trans_rule_hw_tcp_udp tcp_udp; + }; }; static int parse_trans_rule(struct mlx4_dev *dev, struct mlx4_spec_list *spec, struct _rule_hw *rule_hw) { + static const u16 __sw_id_hw[] = { + [MLX4_NET_TRANS_RULE_ID_ETH] = 0xE001, + [MLX4_NET_TRANS_RULE_ID_IB] = 0xE005, + [MLX4_NET_TRANS_RULE_ID_IPV6] = 0xE003, + [MLX4_NET_TRANS_RULE_ID_IPV4] = 0xE002, + [MLX4_NET_TRANS_RULE_ID_TCP] = 0xE004, + [MLX4_NET_TRANS_RULE_ID_UDP] = 0xE006 + }; + static const size_t __rule_hw_sz[] = { [MLX4_NET_TRANS_RULE_ID_ETH] = sizeof(struct mlx4_net_trans_rule_hw_eth), diff --git a/trunk/drivers/net/ethernet/mellanox/mlx4/mlx4.h b/trunk/drivers/net/ethernet/mellanox/mlx4/mlx4.h index dba69d98734a..59ebc0339638 100644 --- a/trunk/drivers/net/ethernet/mellanox/mlx4/mlx4.h +++ b/trunk/drivers/net/ethernet/mellanox/mlx4/mlx4.h @@ -249,7 +249,7 @@ struct mlx4_bitmap { struct mlx4_buddy { unsigned long **bits; unsigned int *num_free; - u32 max_order; + int max_order; spinlock_t lock; }; @@ -258,7 +258,7 @@ struct mlx4_icm; struct mlx4_icm_table { u64 virt; int num_icm; - u32 num_obj; + int num_obj; int obj_size; int lowmem; int coherent; @@ -690,82 +690,6 @@ struct mlx4_steer { struct list_head steer_entries[MLX4_NUM_STEERS]; }; -struct mlx4_net_trans_rule_hw_ctrl { - __be32 ctrl; - __be32 vf_vep_port; - __be32 qpn; - __be32 reserved; -}; - -struct mlx4_net_trans_rule_hw_ib { - u8 size; - u8 rsvd1; - __be16 id; - u32 rsvd2; - __be32 qpn; - __be32 qpn_mask; - u8 dst_gid[16]; - u8 dst_gid_msk[16]; -} __packed; - -struct mlx4_net_trans_rule_hw_eth { - u8 size; - u8 rsvd; - __be16 id; - u8 rsvd1[6]; - u8 dst_mac[6]; - u16 rsvd2; - u8 dst_mac_msk[6]; - u16 rsvd3; - u8 src_mac[6]; - u16 rsvd4; - u8 src_mac_msk[6]; - u8 rsvd5; - u8 ether_type_enable; - __be16 ether_type; - __be16 vlan_id_msk; - __be16 vlan_id; -} __packed; - -struct mlx4_net_trans_rule_hw_tcp_udp { - u8 size; - u8 rsvd; - __be16 id; - __be16 rsvd1[3]; - __be16 dst_port; - __be16 rsvd2; - __be16 dst_port_msk; - __be16 rsvd3; - __be16 src_port; - __be16 rsvd4; - __be16 src_port_msk; -} __packed; - -struct mlx4_net_trans_rule_hw_ipv4 { - u8 size; - u8 rsvd; - __be16 id; - __be32 rsvd1; - __be32 dst_ip; - __be32 dst_ip_msk; - __be32 src_ip; - __be32 src_ip_msk; -} __packed; - -struct _rule_hw { - union { - struct { - u8 size; - u8 rsvd; - __be16 id; - }; - struct mlx4_net_trans_rule_hw_eth eth; - struct mlx4_net_trans_rule_hw_ib ib; - struct mlx4_net_trans_rule_hw_ipv4 ipv4; - struct mlx4_net_trans_rule_hw_tcp_udp tcp_udp; - }; -}; - struct mlx4_priv { struct mlx4_dev dev; diff --git a/trunk/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h b/trunk/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h index 9d27e42264e2..5f1ab105debc 100644 --- a/trunk/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h +++ b/trunk/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h @@ -248,6 +248,7 @@ struct mlx4_en_tx_ring { u32 doorbell_qpn; void *buf; u16 poll_cnt; + int blocked; struct mlx4_en_tx_info *tx_info; u8 *bounce_buf; u32 last_nr_txbb; diff --git a/trunk/drivers/net/ethernet/mellanox/mlx4/mr.c b/trunk/drivers/net/ethernet/mellanox/mlx4/mr.c index c202d3ad2a0e..af55b7ce5341 100644 --- a/trunk/drivers/net/ethernet/mellanox/mlx4/mr.c +++ b/trunk/drivers/net/ethernet/mellanox/mlx4/mr.c @@ -37,7 +37,6 @@ #include #include #include -#include #include @@ -121,7 +120,7 @@ static int mlx4_buddy_init(struct mlx4_buddy *buddy, int max_order) buddy->max_order = max_order; spin_lock_init(&buddy->lock); - buddy->bits = kcalloc(buddy->max_order + 1, sizeof (long *), + buddy->bits = kzalloc((buddy->max_order + 1) * sizeof (long *), GFP_KERNEL); buddy->num_free = kcalloc((buddy->max_order + 1), sizeof *buddy->num_free, GFP_KERNEL); @@ -130,12 +129,10 @@ static int mlx4_buddy_init(struct mlx4_buddy *buddy, int max_order) for (i = 0; i <= buddy->max_order; ++i) { s = BITS_TO_LONGS(1 << (buddy->max_order - i)); - buddy->bits[i] = kcalloc(s, sizeof (long), GFP_KERNEL | __GFP_NOWARN); - if (!buddy->bits[i]) { - buddy->bits[i] = vzalloc(s * sizeof(long)); - if (!buddy->bits[i]) - goto err_out_free; - } + buddy->bits[i] = kmalloc(s * sizeof (long), GFP_KERNEL); + if (!buddy->bits[i]) + goto err_out_free; + bitmap_zero(buddy->bits[i], 1 << (buddy->max_order - i)); } set_bit(0, buddy->bits[buddy->max_order]); @@ -145,10 +142,7 @@ static int mlx4_buddy_init(struct mlx4_buddy *buddy, int max_order) err_out_free: for (i = 0; i <= buddy->max_order; ++i) - if (buddy->bits[i] && is_vmalloc_addr(buddy->bits[i])) - vfree(buddy->bits[i]); - else - kfree(buddy->bits[i]); + kfree(buddy->bits[i]); err_out: kfree(buddy->bits); @@ -162,10 +156,7 @@ static void mlx4_buddy_cleanup(struct mlx4_buddy *buddy) int i; for (i = 0; i <= buddy->max_order; ++i) - if (is_vmalloc_addr(buddy->bits[i])) - vfree(buddy->bits[i]); - else - kfree(buddy->bits[i]); + kfree(buddy->bits[i]); kfree(buddy->bits); kfree(buddy->num_free); @@ -677,7 +668,7 @@ int mlx4_init_mr_table(struct mlx4_dev *dev) return err; err = mlx4_buddy_init(&mr_table->mtt_buddy, - ilog2((u32)dev->caps.num_mtts / + ilog2(dev->caps.num_mtts / (1 << log_mtts_per_seg))); if (err) goto err_buddy; @@ -687,7 +678,7 @@ int mlx4_init_mr_table(struct mlx4_dev *dev) mlx4_alloc_mtt_range(dev, fls(dev->caps.reserved_mtts - 1)); if (priv->reserved_mtts < 0) { - mlx4_warn(dev, "MTT table of order %u is too small.\n", + mlx4_warn(dev, "MTT table of order %d is too small.\n", mr_table->mtt_buddy.max_order); err = -ENOMEM; goto err_reserve_mtts; diff --git a/trunk/drivers/net/ethernet/mellanox/mlx4/profile.c b/trunk/drivers/net/ethernet/mellanox/mlx4/profile.c index 8e0c3cc2a1ec..9ee4725363d5 100644 --- a/trunk/drivers/net/ethernet/mellanox/mlx4/profile.c +++ b/trunk/drivers/net/ethernet/mellanox/mlx4/profile.c @@ -76,7 +76,7 @@ u64 mlx4_make_profile(struct mlx4_dev *dev, u64 size; u64 start; int type; - u32 num; + int num; int log_num; }; @@ -105,7 +105,7 @@ u64 mlx4_make_profile(struct mlx4_dev *dev, si_meminfo(&si); request->num_mtt = roundup_pow_of_two(max_t(unsigned, request->num_mtt, - min(1UL << (31 - log_mtts_per_seg), + min(1UL << 31, si.totalram >> (log_mtts_per_seg - 1)))); profile[MLX4_RES_QP].size = dev_cap->qpc_entry_sz; diff --git a/trunk/drivers/net/ethernet/mellanox/mlx4/reset.c b/trunk/drivers/net/ethernet/mellanox/mlx4/reset.c index dd1b5093d8b1..11e7c1cb99bf 100644 --- a/trunk/drivers/net/ethernet/mellanox/mlx4/reset.c +++ b/trunk/drivers/net/ethernet/mellanox/mlx4/reset.c @@ -141,16 +141,16 @@ int mlx4_reset(struct mlx4_dev *dev) /* Now restore the PCI headers */ if (pcie_cap) { devctl = hca_header[(pcie_cap + PCI_EXP_DEVCTL) / 4]; - if (pcie_capability_write_word(dev->pdev, PCI_EXP_DEVCTL, - devctl)) { + if (pci_write_config_word(dev->pdev, pcie_cap + PCI_EXP_DEVCTL, + devctl)) { err = -ENODEV; mlx4_err(dev, "Couldn't restore HCA PCI Express " "Device Control register, aborting.\n"); goto out; } linkctl = hca_header[(pcie_cap + PCI_EXP_LNKCTL) / 4]; - if (pcie_capability_write_word(dev->pdev, PCI_EXP_LNKCTL, - linkctl)) { + if (pci_write_config_word(dev->pdev, pcie_cap + PCI_EXP_LNKCTL, + linkctl)) { err = -ENODEV; mlx4_err(dev, "Couldn't restore HCA PCI Express " "Link control register, aborting.\n"); diff --git a/trunk/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c b/trunk/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c index 293c9e820c49..94ceddd17ab2 100644 --- a/trunk/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c +++ b/trunk/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c @@ -42,7 +42,6 @@ #include #include #include -#include #include "mlx4.h" #include "fw.h" @@ -2777,133 +2776,18 @@ int mlx4_QP_ATTACH_wrapper(struct mlx4_dev *dev, int slave, return err; } -/* - * MAC validation for Flow Steering rules. - * VF can attach rules only with a mac address which is assigned to it. - */ -static int validate_eth_header_mac(int slave, struct _rule_hw *eth_header, - struct list_head *rlist) -{ - struct mac_res *res, *tmp; - __be64 be_mac; - - /* make sure it isn't multicast or broadcast mac*/ - if (!is_multicast_ether_addr(eth_header->eth.dst_mac) && - !is_broadcast_ether_addr(eth_header->eth.dst_mac)) { - list_for_each_entry_safe(res, tmp, rlist, list) { - be_mac = cpu_to_be64(res->mac << 16); - if (!memcmp(&be_mac, eth_header->eth.dst_mac, ETH_ALEN)) - return 0; - } - pr_err("MAC %pM doesn't belong to VF %d, Steering rule rejected\n", - eth_header->eth.dst_mac, slave); - return -EINVAL; - } - return 0; -} - -/* - * In case of missing eth header, append eth header with a MAC address - * assigned to the VF. - */ -static int add_eth_header(struct mlx4_dev *dev, int slave, - struct mlx4_cmd_mailbox *inbox, - struct list_head *rlist, int header_id) -{ - struct mac_res *res, *tmp; - u8 port; - struct mlx4_net_trans_rule_hw_ctrl *ctrl; - struct mlx4_net_trans_rule_hw_eth *eth_header; - struct mlx4_net_trans_rule_hw_ipv4 *ip_header; - struct mlx4_net_trans_rule_hw_tcp_udp *l4_header; - __be64 be_mac = 0; - __be64 mac_msk = cpu_to_be64(MLX4_MAC_MASK << 16); - - ctrl = (struct mlx4_net_trans_rule_hw_ctrl *)inbox->buf; - port = be32_to_cpu(ctrl->vf_vep_port) & 0xff; - eth_header = (struct mlx4_net_trans_rule_hw_eth *)(ctrl + 1); - - /* Clear a space in the inbox for eth header */ - switch (header_id) { - case MLX4_NET_TRANS_RULE_ID_IPV4: - ip_header = - (struct mlx4_net_trans_rule_hw_ipv4 *)(eth_header + 1); - memmove(ip_header, eth_header, - sizeof(*ip_header) + sizeof(*l4_header)); - break; - case MLX4_NET_TRANS_RULE_ID_TCP: - case MLX4_NET_TRANS_RULE_ID_UDP: - l4_header = (struct mlx4_net_trans_rule_hw_tcp_udp *) - (eth_header + 1); - memmove(l4_header, eth_header, sizeof(*l4_header)); - break; - default: - return -EINVAL; - } - list_for_each_entry_safe(res, tmp, rlist, list) { - if (port == res->port) { - be_mac = cpu_to_be64(res->mac << 16); - break; - } - } - if (!be_mac) { - pr_err("Failed adding eth header to FS rule, Can't find matching MAC for port %d .\n", - port); - return -EINVAL; - } - - memset(eth_header, 0, sizeof(*eth_header)); - eth_header->size = sizeof(*eth_header) >> 2; - eth_header->id = cpu_to_be16(__sw_id_hw[MLX4_NET_TRANS_RULE_ID_ETH]); - memcpy(eth_header->dst_mac, &be_mac, ETH_ALEN); - memcpy(eth_header->dst_mac_msk, &mac_msk, ETH_ALEN); - - return 0; - -} - int mlx4_QP_FLOW_STEERING_ATTACH_wrapper(struct mlx4_dev *dev, int slave, struct mlx4_vhcr *vhcr, struct mlx4_cmd_mailbox *inbox, struct mlx4_cmd_mailbox *outbox, struct mlx4_cmd_info *cmd) { - - struct mlx4_priv *priv = mlx4_priv(dev); - struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker; - struct list_head *rlist = &tracker->slave_list[slave].res_list[RES_MAC]; int err; - struct mlx4_net_trans_rule_hw_ctrl *ctrl; - struct _rule_hw *rule_header; - int header_id; if (dev->caps.steering_mode != MLX4_STEERING_MODE_DEVICE_MANAGED) return -EOPNOTSUPP; - ctrl = (struct mlx4_net_trans_rule_hw_ctrl *)inbox->buf; - rule_header = (struct _rule_hw *)(ctrl + 1); - header_id = map_hw_to_sw_id(be16_to_cpu(rule_header->id)); - - switch (header_id) { - case MLX4_NET_TRANS_RULE_ID_ETH: - if (validate_eth_header_mac(slave, rule_header, rlist)) - return -EINVAL; - break; - case MLX4_NET_TRANS_RULE_ID_IPV4: - case MLX4_NET_TRANS_RULE_ID_TCP: - case MLX4_NET_TRANS_RULE_ID_UDP: - pr_warn("Can't attach FS rule without L2 headers, adding L2 header.\n"); - if (add_eth_header(dev, slave, inbox, rlist, header_id)) - return -EINVAL; - vhcr->in_modifier += - sizeof(struct mlx4_net_trans_rule_hw_eth) >> 2; - break; - default: - pr_err("Corrupted mailbox.\n"); - return -EINVAL; - } - err = mlx4_cmd_imm(dev, inbox->dma, &vhcr->out_param, vhcr->in_modifier, 0, MLX4_QP_FLOW_STEERING_ATTACH, MLX4_CMD_TIME_CLASS_A, diff --git a/trunk/drivers/net/ethernet/mellanox/mlx4/sense.c b/trunk/drivers/net/ethernet/mellanox/mlx4/sense.c index 34ee09bae36e..802498293528 100644 --- a/trunk/drivers/net/ethernet/mellanox/mlx4/sense.c +++ b/trunk/drivers/net/ethernet/mellanox/mlx4/sense.c @@ -80,6 +80,20 @@ void mlx4_do_sense_ports(struct mlx4_dev *dev, stype[i - 1] = defaults[i - 1]; } + /* + * Adjust port configuration: + * If port 1 sensed nothing and port 2 is IB, set both as IB + * If port 2 sensed nothing and port 1 is Eth, set both as Eth + */ + if (stype[0] == MLX4_PORT_TYPE_ETH) { + for (i = 1; i < dev->caps.num_ports; i++) + stype[i] = stype[i] ? stype[i] : MLX4_PORT_TYPE_ETH; + } + if (stype[dev->caps.num_ports - 1] == MLX4_PORT_TYPE_IB) { + for (i = 0; i < dev->caps.num_ports - 1; i++) + stype[i] = stype[i] ? stype[i] : MLX4_PORT_TYPE_IB; + } + /* * If sensed nothing, remain in current configuration. */ diff --git a/trunk/drivers/net/ethernet/myricom/myri10ge/myri10ge.c b/trunk/drivers/net/ethernet/myricom/myri10ge/myri10ge.c index 83516e3369c9..fa85cf1353fd 100644 --- a/trunk/drivers/net/ethernet/myricom/myri10ge/myri10ge.c +++ b/trunk/drivers/net/ethernet/myricom/myri10ge/myri10ge.c @@ -1078,16 +1078,22 @@ static int myri10ge_reset(struct myri10ge_priv *mgp) #ifdef CONFIG_MYRI10GE_DCA static int myri10ge_toggle_relaxed(struct pci_dev *pdev, int on) { - int ret; + int ret, cap, err; u16 ctl; - pcie_capability_read_word(pdev, PCI_EXP_DEVCTL, &ctl); + cap = pci_pcie_cap(pdev); + if (!cap) + return 0; + + err = pci_read_config_word(pdev, cap + PCI_EXP_DEVCTL, &ctl); + if (err) + return 0; ret = (ctl & PCI_EXP_DEVCTL_RELAX_EN) >> 4; if (ret != on) { ctl &= ~PCI_EXP_DEVCTL_RELAX_EN; ctl |= (on << 4); - pcie_capability_write_word(pdev, PCI_EXP_DEVCTL, ctl); + pci_write_config_word(pdev, cap + PCI_EXP_DEVCTL, ctl); } return ret; } @@ -3186,13 +3192,18 @@ static void myri10ge_enable_ecrc(struct myri10ge_priv *mgp) struct device *dev = &mgp->pdev->dev; int cap; unsigned err_cap; + u16 val; + u8 ext_type; int ret; if (!myri10ge_ecrc_enable || !bridge) return; /* check that the bridge is a root port */ - if (pci_pcie_type(bridge) != PCI_EXP_TYPE_ROOT_PORT) { + cap = pci_pcie_cap(bridge); + pci_read_config_word(bridge, cap + PCI_CAP_FLAGS, &val); + ext_type = (val & PCI_EXP_FLAGS_TYPE) >> 4; + if (ext_type != PCI_EXP_TYPE_ROOT_PORT) { if (myri10ge_ecrc_enable > 1) { struct pci_dev *prev_bridge, *old_bridge = bridge; @@ -3207,8 +3218,11 @@ static void myri10ge_enable_ecrc(struct myri10ge_priv *mgp) " to force ECRC\n"); return; } - } while (pci_pcie_type(bridge) != - PCI_EXP_TYPE_ROOT_PORT); + cap = pci_pcie_cap(bridge); + pci_read_config_word(bridge, + cap + PCI_CAP_FLAGS, &val); + ext_type = (val & PCI_EXP_FLAGS_TYPE) >> 4; + } while (ext_type != PCI_EXP_TYPE_ROOT_PORT); dev_info(dev, "Forcing ECRC on non-root port %s" @@ -3321,10 +3335,11 @@ static void myri10ge_select_firmware(struct myri10ge_priv *mgp) int overridden = 0; if (myri10ge_force_firmware == 0) { - int link_width; + int link_width, exp_cap; u16 lnk; - pcie_capability_read_word(mgp->pdev, PCI_EXP_LNKSTA, &lnk); + exp_cap = pci_pcie_cap(mgp->pdev); + pci_read_config_word(mgp->pdev, exp_cap + PCI_EXP_LNKSTA, &lnk); link_width = (lnk >> 4) & 0x3f; /* Check to see if Link is less than 8 or if the diff --git a/trunk/drivers/net/ethernet/neterion/s2io.c b/trunk/drivers/net/ethernet/neterion/s2io.c index de50547c187d..d958c2299372 100644 --- a/trunk/drivers/net/ethernet/neterion/s2io.c +++ b/trunk/drivers/net/ethernet/neterion/s2io.c @@ -484,7 +484,7 @@ static DEFINE_PCI_DEVICE_TABLE(s2io_tbl) = { MODULE_DEVICE_TABLE(pci, s2io_tbl); -static const struct pci_error_handlers s2io_err_handler = { +static struct pci_error_handlers s2io_err_handler = { .error_detected = s2io_io_error_detected, .slot_reset = s2io_io_slot_reset, .resume = s2io_io_resume, diff --git a/trunk/drivers/net/ethernet/neterion/vxge/vxge-config.c b/trunk/drivers/net/ethernet/neterion/vxge/vxge-config.c index c2e420a84d22..32d06824fe3e 100644 --- a/trunk/drivers/net/ethernet/neterion/vxge/vxge-config.c +++ b/trunk/drivers/net/ethernet/neterion/vxge/vxge-config.c @@ -757,7 +757,7 @@ __vxge_hw_verify_pci_e_info(struct __vxge_hw_device *hldev) u16 lnk; /* Get the negotiated link width and speed from PCI config space */ - pcie_capability_read_word(dev, PCI_EXP_LNKSTA, &lnk); + pci_read_config_word(dev, dev->pcie_cap + PCI_EXP_LNKSTA, &lnk); if ((lnk & PCI_EXP_LNKSTA_CLS) != 1) return VXGE_HW_ERR_INVALID_PCI_INFO; @@ -1982,7 +1982,7 @@ u16 vxge_hw_device_link_width_get(struct __vxge_hw_device *hldev) struct pci_dev *dev = hldev->pdev; u16 lnk; - pcie_capability_read_word(dev, PCI_EXP_LNKSTA, &lnk); + pci_read_config_word(dev, dev->pcie_cap + PCI_EXP_LNKSTA, &lnk); return (lnk & VXGE_HW_PCI_EXP_LNKCAP_LNK_WIDTH) >> 4; } diff --git a/trunk/drivers/net/ethernet/neterion/vxge/vxge-main.c b/trunk/drivers/net/ethernet/neterion/vxge/vxge-main.c index cfa71a30dc8d..de2190443510 100644 --- a/trunk/drivers/net/ethernet/neterion/vxge/vxge-main.c +++ b/trunk/drivers/net/ethernet/neterion/vxge/vxge-main.c @@ -4799,7 +4799,7 @@ static void __devexit vxge_remove(struct pci_dev *pdev) __LINE__); } -static const struct pci_error_handlers vxge_err_handler = { +static struct pci_error_handlers vxge_err_handler = { .error_detected = vxge_io_error_detected, .slot_reset = vxge_io_slot_reset, .resume = vxge_io_resume, diff --git a/trunk/drivers/net/ethernet/nxp/lpc_eth.c b/trunk/drivers/net/ethernet/nxp/lpc_eth.c index 53743f7a2ca9..4069edab229e 100644 --- a/trunk/drivers/net/ethernet/nxp/lpc_eth.c +++ b/trunk/drivers/net/ethernet/nxp/lpc_eth.c @@ -346,15 +346,28 @@ static phy_interface_t lpc_phy_interface_mode(struct device *dev) "phy-mode", NULL); if (mode && !strcmp(mode, "mii")) return PHY_INTERFACE_MODE_MII; + return PHY_INTERFACE_MODE_RMII; } + + /* non-DT */ +#ifdef CONFIG_ARCH_LPC32XX_MII_SUPPORT + return PHY_INTERFACE_MODE_MII; +#else return PHY_INTERFACE_MODE_RMII; +#endif } static bool use_iram_for_net(struct device *dev) { if (dev && dev->of_node) return of_property_read_bool(dev->of_node, "use-iram"); + + /* non-DT */ +#ifdef CONFIG_ARCH_LPC32XX_IRAM_FOR_NET + return true; +#else return false; +#endif } /* Receive Status information word */ diff --git a/trunk/drivers/net/ethernet/octeon/octeon_mgmt.c b/trunk/drivers/net/ethernet/octeon/octeon_mgmt.c index a688a2ddcfd6..c42bbb16cdae 100644 --- a/trunk/drivers/net/ethernet/octeon/octeon_mgmt.c +++ b/trunk/drivers/net/ethernet/octeon/octeon_mgmt.c @@ -722,8 +722,10 @@ static int octeon_mgmt_init_phy(struct net_device *netdev) octeon_mgmt_adjust_link, 0, PHY_INTERFACE_MODE_MII); - if (!p->phydev) + if (IS_ERR(p->phydev)) { + p->phydev = NULL; return -1; + } phy_start_aneg(p->phydev); diff --git a/trunk/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c b/trunk/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c index b2a94d02a521..feb85d56c750 100644 --- a/trunk/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c +++ b/trunk/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c @@ -2795,7 +2795,7 @@ static const struct dev_pm_ops pch_gbe_pm_ops = { }; #endif -static const struct pci_error_handlers pch_gbe_err_handler = { +static struct pci_error_handlers pch_gbe_err_handler = { .error_detected = pch_gbe_io_error_detected, .slot_reset = pch_gbe_io_slot_reset, .resume = pch_gbe_io_resume diff --git a/trunk/drivers/net/ethernet/pasemi/pasemi_mac.c b/trunk/drivers/net/ethernet/pasemi/pasemi_mac.c index 6fa74d530e44..e559dfa06d6a 100644 --- a/trunk/drivers/net/ethernet/pasemi/pasemi_mac.c +++ b/trunk/drivers/net/ethernet/pasemi/pasemi_mac.c @@ -1101,9 +1101,9 @@ static int pasemi_mac_phy_init(struct net_device *dev) phydev = of_phy_connect(dev, phy_dn, &pasemi_adjust_link, 0, PHY_INTERFACE_MODE_SGMII); - if (!phydev) { + if (IS_ERR(phydev)) { printk(KERN_ERR "%s: Could not attach to phy\n", dev->name); - return -ENODEV; + return PTR_ERR(phydev); } mac->phydev = phydev; diff --git a/trunk/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c b/trunk/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c index df450616ab37..342b3a79bd0f 100644 --- a/trunk/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c +++ b/trunk/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c @@ -1378,15 +1378,11 @@ static void netxen_mask_aer_correctable(struct netxen_adapter *adapter) struct pci_dev *root = pdev->bus->self; u32 aer_pos; - /* root bus? */ - if (!root) - return; - if (adapter->ahw.board_type != NETXEN_BRDTYPE_P3_4_GB_MM && adapter->ahw.board_type != NETXEN_BRDTYPE_P3_10G_TP) return; - if (pci_pcie_type(root) != PCI_EXP_TYPE_ROOT_PORT) + if (root->pcie_type != PCI_EXP_TYPE_ROOT_PORT) return; aer_pos = pci_find_ext_capability(root, PCI_EXT_CAP_ID_ERR); @@ -3340,7 +3336,7 @@ netxen_free_vlan_ip_list(struct netxen_adapter *adapter) { } #endif -static const struct pci_error_handlers netxen_err_handler = { +static struct pci_error_handlers netxen_err_handler = { .error_detected = netxen_io_error_detected, .slot_reset = netxen_io_slot_reset, .resume = netxen_io_resume, diff --git a/trunk/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c b/trunk/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c index 2a179d087207..b8ead696141e 100644 --- a/trunk/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c +++ b/trunk/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c @@ -15,7 +15,7 @@ qlcnic_poll_rsp(struct qlcnic_adapter *adapter) do { /* give atleast 1ms for firmware to respond */ - mdelay(1); + msleep(1); if (++timeout > QLCNIC_OS_CRB_RETRY_COUNT) return QLCNIC_CDRP_RSP_TIMEOUT; @@ -601,7 +601,7 @@ void qlcnic_fw_destroy_ctx(struct qlcnic_adapter *adapter) qlcnic_fw_cmd_destroy_tx_ctx(adapter); /* Allow dma queues to drain after context reset */ - mdelay(20); + msleep(20); } } diff --git a/trunk/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/trunk/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c index 473ce134ca63..212c12193275 100644 --- a/trunk/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c +++ b/trunk/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c @@ -4522,7 +4522,7 @@ static void qlcnic_restore_indev_addr(struct net_device *dev, unsigned long event) { } #endif -static const struct pci_error_handlers qlcnic_err_handler = { +static struct pci_error_handlers qlcnic_err_handler = { .error_detected = qlcnic_io_error_detected, .slot_reset = qlcnic_io_slot_reset, .resume = qlcnic_io_resume, diff --git a/trunk/drivers/net/ethernet/qlogic/qlge/qlge_main.c b/trunk/drivers/net/ethernet/qlogic/qlge/qlge_main.c index b262d6156816..b53a3b60b648 100644 --- a/trunk/drivers/net/ethernet/qlogic/qlge/qlge_main.c +++ b/trunk/drivers/net/ethernet/qlogic/qlge/qlge_main.c @@ -4847,7 +4847,7 @@ static void qlge_io_resume(struct pci_dev *pdev) netif_device_attach(ndev); } -static const struct pci_error_handlers qlge_err_handler = { +static struct pci_error_handlers qlge_err_handler = { .error_detected = qlge_io_error_detected, .slot_reset = qlge_io_slot_reset, .resume = qlge_io_resume, diff --git a/trunk/drivers/net/ethernet/realtek/r8169.c b/trunk/drivers/net/ethernet/realtek/r8169.c index a7cc56007b33..b47d5b35024e 100644 --- a/trunk/drivers/net/ethernet/realtek/r8169.c +++ b/trunk/drivers/net/ethernet/realtek/r8169.c @@ -833,8 +833,15 @@ static void rtl_unlock_work(struct rtl8169_private *tp) static void rtl_tx_performance_tweak(struct pci_dev *pdev, u16 force) { - pcie_capability_clear_and_set_word(pdev, PCI_EXP_DEVCTL, - PCI_EXP_DEVCTL_READRQ, force); + int cap = pci_pcie_cap(pdev); + + if (cap) { + u16 ctl; + + pci_read_config_word(pdev, cap + PCI_EXP_DEVCTL, &ctl); + ctl = (ctl & ~PCI_EXP_DEVCTL_READRQ) | force; + pci_write_config_word(pdev, cap + PCI_EXP_DEVCTL, ctl); + } } struct rtl_cond { @@ -4732,14 +4739,28 @@ static void rtl_ephy_init(struct rtl8169_private *tp, const struct ephy_info *e, static void rtl_disable_clock_request(struct pci_dev *pdev) { - pcie_capability_clear_word(pdev, PCI_EXP_LNKCTL, - PCI_EXP_LNKCTL_CLKREQ_EN); + int cap = pci_pcie_cap(pdev); + + if (cap) { + u16 ctl; + + pci_read_config_word(pdev, cap + PCI_EXP_LNKCTL, &ctl); + ctl &= ~PCI_EXP_LNKCTL_CLKREQ_EN; + pci_write_config_word(pdev, cap + PCI_EXP_LNKCTL, ctl); + } } static void rtl_enable_clock_request(struct pci_dev *pdev) { - pcie_capability_set_word(pdev, PCI_EXP_LNKCTL, - PCI_EXP_LNKCTL_CLKREQ_EN); + int cap = pci_pcie_cap(pdev); + + if (cap) { + u16 ctl; + + pci_read_config_word(pdev, cap + PCI_EXP_LNKCTL, &ctl); + ctl |= PCI_EXP_LNKCTL_CLKREQ_EN; + pci_write_config_word(pdev, cap + PCI_EXP_LNKCTL, ctl); + } } #define R8168_CPCMD_QUIRK_MASK (\ @@ -5384,9 +5405,14 @@ static void rtl_hw_start_8101(struct net_device *dev) tp->event_slow &= ~RxFIFOOver; if (tp->mac_version == RTL_GIGA_MAC_VER_13 || - tp->mac_version == RTL_GIGA_MAC_VER_16) - pcie_capability_set_word(pdev, PCI_EXP_DEVCTL, - PCI_EXP_DEVCTL_NOSNOOP_EN); + tp->mac_version == RTL_GIGA_MAC_VER_16) { + int cap = pci_pcie_cap(pdev); + + if (cap) { + pci_write_config_word(pdev, cap + PCI_EXP_DEVCTL, + PCI_EXP_DEVCTL_NOSNOOP_EN); + } + } RTL_W8(Cfg9346, Cfg9346_Unlock); diff --git a/trunk/drivers/net/ethernet/renesas/Kconfig b/trunk/drivers/net/ethernet/renesas/Kconfig index 24c2305d7948..46df3a04030c 100644 --- a/trunk/drivers/net/ethernet/renesas/Kconfig +++ b/trunk/drivers/net/ethernet/renesas/Kconfig @@ -8,7 +8,7 @@ config SH_ETH (CPU_SUBTYPE_SH7710 || CPU_SUBTYPE_SH7712 || \ CPU_SUBTYPE_SH7763 || CPU_SUBTYPE_SH7619 || \ CPU_SUBTYPE_SH7724 || CPU_SUBTYPE_SH7734 || \ - CPU_SUBTYPE_SH7757 || ARCH_R8A7740 || ARCH_R8A7779) + CPU_SUBTYPE_SH7757 || ARCH_R8A7740) select CRC32 select NET_CORE select MII @@ -18,4 +18,4 @@ config SH_ETH Renesas SuperH Ethernet device driver. This driver supporting CPUs are: - SH7619, SH7710, SH7712, SH7724, SH7734, SH7763, SH7757, - R8A7740 and R8A7779. + and R8A7740. diff --git a/trunk/drivers/net/ethernet/renesas/sh_eth.c b/trunk/drivers/net/ethernet/renesas/sh_eth.c index bad8f2eec9b4..af0b867a6cf6 100644 --- a/trunk/drivers/net/ethernet/renesas/sh_eth.c +++ b/trunk/drivers/net/ethernet/renesas/sh_eth.c @@ -78,7 +78,7 @@ static void sh_eth_select_mii(struct net_device *ndev) #endif /* There is CPU dependent code */ -#if defined(CONFIG_CPU_SUBTYPE_SH7724) || defined(CONFIG_ARCH_R8A7779) +#if defined(CONFIG_CPU_SUBTYPE_SH7724) #define SH_ETH_RESET_DEFAULT 1 static void sh_eth_set_duplex(struct net_device *ndev) { @@ -93,18 +93,13 @@ static void sh_eth_set_duplex(struct net_device *ndev) static void sh_eth_set_rate(struct net_device *ndev) { struct sh_eth_private *mdp = netdev_priv(ndev); - unsigned int bits = ECMR_RTM; - -#if defined(CONFIG_ARCH_R8A7779) - bits |= ECMR_ELB; -#endif switch (mdp->speed) { case 10: /* 10BASE */ - sh_eth_write(ndev, sh_eth_read(ndev, ECMR) & ~bits, ECMR); + sh_eth_write(ndev, sh_eth_read(ndev, ECMR) & ~ECMR_RTM, ECMR); break; case 100:/* 100BASE */ - sh_eth_write(ndev, sh_eth_read(ndev, ECMR) | bits, ECMR); + sh_eth_write(ndev, sh_eth_read(ndev, ECMR) | ECMR_RTM, ECMR); break; default: break; diff --git a/trunk/drivers/net/ethernet/seeq/sgiseeq.c b/trunk/drivers/net/ethernet/seeq/sgiseeq.c index 4d15bf413bdc..bb8c8222122b 100644 --- a/trunk/drivers/net/ethernet/seeq/sgiseeq.c +++ b/trunk/drivers/net/ethernet/seeq/sgiseeq.c @@ -751,7 +751,6 @@ static int __devinit sgiseeq_probe(struct platform_device *pdev) sp->srings = sr; sp->rx_desc = sp->srings->rxvector; sp->tx_desc = sp->srings->txvector; - spin_lock_init(&sp->tx_lock); /* A couple calculations now, saves many cycles later. */ setup_rx_ring(dev, sp->rx_desc, SEEQ_RX_BUFFERS); diff --git a/trunk/drivers/net/ethernet/sfc/efx.c b/trunk/drivers/net/ethernet/sfc/efx.c index 65a8d49106a4..70554a1b2b02 100644 --- a/trunk/drivers/net/ethernet/sfc/efx.c +++ b/trunk/drivers/net/ethernet/sfc/efx.c @@ -1503,11 +1503,6 @@ static int efx_probe_all(struct efx_nic *efx) goto fail2; } - BUILD_BUG_ON(EFX_DEFAULT_DMAQ_SIZE < EFX_RXQ_MIN_ENT); - if (WARN_ON(EFX_DEFAULT_DMAQ_SIZE < EFX_TXQ_MIN_ENT(efx))) { - rc = -EINVAL; - goto fail3; - } efx->rxq_entries = efx->txq_entries = EFX_DEFAULT_DMAQ_SIZE; rc = efx_probe_filters(efx); @@ -2075,7 +2070,6 @@ static int efx_register_netdev(struct efx_nic *efx) net_dev->irq = efx->pci_dev->irq; net_dev->netdev_ops = &efx_netdev_ops; SET_ETHTOOL_OPS(net_dev, &efx_ethtool_ops); - net_dev->gso_max_segs = EFX_TSO_MAX_SEGS; rtnl_lock(); diff --git a/trunk/drivers/net/ethernet/sfc/efx.h b/trunk/drivers/net/ethernet/sfc/efx.h index 70755c97251a..be8f9158a714 100644 --- a/trunk/drivers/net/ethernet/sfc/efx.h +++ b/trunk/drivers/net/ethernet/sfc/efx.h @@ -30,7 +30,6 @@ extern netdev_tx_t efx_enqueue_skb(struct efx_tx_queue *tx_queue, struct sk_buff *skb); extern void efx_xmit_done(struct efx_tx_queue *tx_queue, unsigned int index); extern int efx_setup_tc(struct net_device *net_dev, u8 num_tc); -extern unsigned int efx_tx_max_skb_descs(struct efx_nic *efx); /* RX */ extern int efx_probe_rx_queue(struct efx_rx_queue *rx_queue); @@ -53,15 +52,10 @@ extern void efx_schedule_slow_fill(struct efx_rx_queue *rx_queue); #define EFX_MAX_EVQ_SIZE 16384UL #define EFX_MIN_EVQ_SIZE 512UL -/* Maximum number of TCP segments we support for soft-TSO */ -#define EFX_TSO_MAX_SEGS 100 - -/* The smallest [rt]xq_entries that the driver supports. RX minimum - * is a bit arbitrary. For TX, we must have space for at least 2 - * TSO skbs. - */ -#define EFX_RXQ_MIN_ENT 128U -#define EFX_TXQ_MIN_ENT(efx) (2 * efx_tx_max_skb_descs(efx)) +/* The smallest [rt]xq_entries that the driver supports. Callers of + * efx_wake_queue() assume that they can subsequently send at least one + * skb. Falcon/A1 may require up to three descriptors per skb_frag. */ +#define EFX_MIN_RING_SIZE (roundup_pow_of_two(2 * 3 * MAX_SKB_FRAGS)) /* Filters */ extern int efx_probe_filters(struct efx_nic *efx); diff --git a/trunk/drivers/net/ethernet/sfc/ethtool.c b/trunk/drivers/net/ethernet/sfc/ethtool.c index 5faedd855b77..10536f93b561 100644 --- a/trunk/drivers/net/ethernet/sfc/ethtool.c +++ b/trunk/drivers/net/ethernet/sfc/ethtool.c @@ -680,27 +680,21 @@ static int efx_ethtool_set_ringparam(struct net_device *net_dev, struct ethtool_ringparam *ring) { struct efx_nic *efx = netdev_priv(net_dev); - u32 txq_entries; if (ring->rx_mini_pending || ring->rx_jumbo_pending || ring->rx_pending > EFX_MAX_DMAQ_SIZE || ring->tx_pending > EFX_MAX_DMAQ_SIZE) return -EINVAL; - if (ring->rx_pending < EFX_RXQ_MIN_ENT) { + if (ring->rx_pending < EFX_MIN_RING_SIZE || + ring->tx_pending < EFX_MIN_RING_SIZE) { netif_err(efx, drv, efx->net_dev, - "RX queues cannot be smaller than %u\n", - EFX_RXQ_MIN_ENT); + "TX and RX queues cannot be smaller than %ld\n", + EFX_MIN_RING_SIZE); return -EINVAL; } - txq_entries = max(ring->tx_pending, EFX_TXQ_MIN_ENT(efx)); - if (txq_entries != ring->tx_pending) - netif_warn(efx, drv, efx->net_dev, - "increasing TX queue size to minimum of %u\n", - txq_entries); - - return efx_realloc_channels(efx, ring->rx_pending, txq_entries); + return efx_realloc_channels(efx, ring->rx_pending, ring->tx_pending); } static int efx_ethtool_set_pauseparam(struct net_device *net_dev, @@ -863,8 +857,8 @@ static int efx_ethtool_get_class_rule(struct efx_nic *efx, &ip_entry->ip4dst, &ip_entry->pdst); if (rc != 0) { rc = efx_filter_get_ipv4_full( - &spec, &proto, &ip_entry->ip4dst, &ip_entry->pdst, - &ip_entry->ip4src, &ip_entry->psrc); + &spec, &proto, &ip_entry->ip4src, &ip_entry->psrc, + &ip_entry->ip4dst, &ip_entry->pdst); EFX_WARN_ON_PARANOID(rc); ip_mask->ip4src = ~0; ip_mask->psrc = ~0; diff --git a/trunk/drivers/net/ethernet/sfc/tx.c b/trunk/drivers/net/ethernet/sfc/tx.c index 18713436b443..9b225a7769f7 100644 --- a/trunk/drivers/net/ethernet/sfc/tx.c +++ b/trunk/drivers/net/ethernet/sfc/tx.c @@ -119,25 +119,6 @@ efx_max_tx_len(struct efx_nic *efx, dma_addr_t dma_addr) return len; } -unsigned int efx_tx_max_skb_descs(struct efx_nic *efx) -{ - /* Header and payload descriptor for each output segment, plus - * one for every input fragment boundary within a segment - */ - unsigned int max_descs = EFX_TSO_MAX_SEGS * 2 + MAX_SKB_FRAGS; - - /* Possibly one more per segment for the alignment workaround */ - if (EFX_WORKAROUND_5391(efx)) - max_descs += EFX_TSO_MAX_SEGS; - - /* Possibly more for PCIe page boundaries within input fragments */ - if (PAGE_SIZE > EFX_PAGE_SIZE) - max_descs += max_t(unsigned int, MAX_SKB_FRAGS, - DIV_ROUND_UP(GSO_MAX_SIZE, EFX_PAGE_SIZE)); - - return max_descs; -} - /* * Add a socket buffer to a TX queue * diff --git a/trunk/drivers/net/ethernet/sgi/ioc3-eth.c b/trunk/drivers/net/ethernet/sgi/ioc3-eth.c index 3e5519a0acc7..b5ba3084c7fc 100644 --- a/trunk/drivers/net/ethernet/sgi/ioc3-eth.c +++ b/trunk/drivers/net/ethernet/sgi/ioc3-eth.c @@ -1147,17 +1147,15 @@ static void __devinit ioc3_8250_register(struct ioc3_uartregs __iomem *uart) { #define COSMISC_CONSTANT 6 - struct uart_8250_port port = { - .port = { - .irq = 0, - .flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF, - .iotype = UPIO_MEM, - .regshift = 0, - .uartclk = (22000000 << 1) / COSMISC_CONSTANT, - - .membase = (unsigned char __iomem *) uart, - .mapbase = (unsigned long) uart, - } + struct uart_port port = { + .irq = 0, + .flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF, + .iotype = UPIO_MEM, + .regshift = 0, + .uartclk = (22000000 << 1) / COSMISC_CONSTANT, + + .membase = (unsigned char __iomem *) uart, + .mapbase = (unsigned long) uart, }; unsigned char lcr; @@ -1166,7 +1164,7 @@ static void __devinit ioc3_8250_register(struct ioc3_uartregs __iomem *uart) uart->iu_scr = COSMISC_CONSTANT, uart->iu_lcr = lcr; uart->iu_lcr; - serial8250_register_8250_port(&port); + serial8250_register_port(&port); } static void __devinit ioc3_serial_probe(struct pci_dev *pdev, struct ioc3 *ioc3) diff --git a/trunk/drivers/net/ethernet/stmicro/stmmac/common.h b/trunk/drivers/net/ethernet/stmicro/stmmac/common.h index 719be3912aa9..e2d083228f3a 100644 --- a/trunk/drivers/net/ethernet/stmicro/stmmac/common.h +++ b/trunk/drivers/net/ethernet/stmicro/stmmac/common.h @@ -22,9 +22,6 @@ Author: Giuseppe Cavallaro *******************************************************************************/ -#ifndef __COMMON_H__ -#define __COMMON_H__ - #include #include #include @@ -369,5 +366,3 @@ extern void stmmac_set_mac(void __iomem *ioaddr, bool enable); extern void dwmac_dma_flush_tx_fifo(void __iomem *ioaddr); extern const struct stmmac_ring_mode_ops ring_mode_ops; - -#endif /* __COMMON_H__ */ diff --git a/trunk/drivers/net/ethernet/stmicro/stmmac/descs.h b/trunk/drivers/net/ethernet/stmicro/stmmac/descs.h index 223adf95fd03..9820ec842cc0 100644 --- a/trunk/drivers/net/ethernet/stmicro/stmmac/descs.h +++ b/trunk/drivers/net/ethernet/stmicro/stmmac/descs.h @@ -20,10 +20,6 @@ Author: Giuseppe Cavallaro *******************************************************************************/ - -#ifndef __DESCS_H__ -#define __DESCS_H__ - struct dma_desc { /* Receive descriptor */ union { @@ -170,5 +166,3 @@ enum tdes_csum_insertion { * is not calculated */ cic_full = 3, /* IP header and pseudoheader */ }; - -#endif /* __DESCS_H__ */ diff --git a/trunk/drivers/net/ethernet/stmicro/stmmac/descs_com.h b/trunk/drivers/net/ethernet/stmicro/stmmac/descs_com.h index 7ee9499a6e38..dd8d6e19dff6 100644 --- a/trunk/drivers/net/ethernet/stmicro/stmmac/descs_com.h +++ b/trunk/drivers/net/ethernet/stmicro/stmmac/descs_com.h @@ -27,9 +27,6 @@ Author: Giuseppe Cavallaro *******************************************************************************/ -#ifndef __DESC_COM_H__ -#define __DESC_COM_H__ - #if defined(CONFIG_STMMAC_RING) static inline void ehn_desc_rx_set_on_ring_chain(struct dma_desc *p, int end) { @@ -127,5 +124,3 @@ static inline void norm_set_tx_desc_len(struct dma_desc *p, int len) p->des01.tx.buffer1_size = len; } #endif - -#endif /* __DESC_COM_H__ */ diff --git a/trunk/drivers/net/ethernet/stmicro/stmmac/dwmac100.h b/trunk/drivers/net/ethernet/stmicro/stmmac/dwmac100.h index 2ec6aeae349e..7c6d857a9cc7 100644 --- a/trunk/drivers/net/ethernet/stmicro/stmmac/dwmac100.h +++ b/trunk/drivers/net/ethernet/stmicro/stmmac/dwmac100.h @@ -22,9 +22,6 @@ Author: Giuseppe Cavallaro *******************************************************************************/ -#ifndef __DWMAC100_H__ -#define __DWMAC100_H__ - #include #include "common.h" @@ -122,5 +119,3 @@ enum ttc_control { #define DMA_MISSED_FRAME_M_CNTR 0x0000ffff /* Missed Frame Couinter */ extern const struct stmmac_dma_ops dwmac100_dma_ops; - -#endif /* __DWMAC100_H__ */ diff --git a/trunk/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h b/trunk/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h index 0e4cacedc1f0..f90fcb5f9573 100644 --- a/trunk/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h +++ b/trunk/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h @@ -19,8 +19,6 @@ Author: Giuseppe Cavallaro *******************************************************************************/ -#ifndef __DWMAC1000_H__ -#define __DWMAC1000_H__ #include #include "common.h" @@ -231,7 +229,6 @@ enum rtc_control { #define GMAC_MMC_RX_CSUM_OFFLOAD 0x208 /* Synopsys Core versions */ -#define DWMAC_CORE_3_40 0x34 +#define DWMAC_CORE_3_40 34 extern const struct stmmac_dma_ops dwmac1000_dma_ops; -#endif /* __DWMAC1000_H__ */ diff --git a/trunk/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h b/trunk/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h index e49c9a0fd6ff..e678ce39d014 100644 --- a/trunk/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h +++ b/trunk/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h @@ -22,9 +22,6 @@ Author: Giuseppe Cavallaro *******************************************************************************/ -#ifndef __DWMAC_DMA_H__ -#define __DWMAC_DMA_H__ - /* DMA CRS Control and Status Register Mapping */ #define DMA_BUS_MODE 0x00001000 /* Bus Mode */ #define DMA_XMT_POLL_DEMAND 0x00001004 /* Transmit Poll Demand */ @@ -112,5 +109,3 @@ extern void dwmac_dma_start_rx(void __iomem *ioaddr); extern void dwmac_dma_stop_rx(void __iomem *ioaddr); extern int dwmac_dma_interrupt(void __iomem *ioaddr, struct stmmac_extra_stats *x); - -#endif /* __DWMAC_DMA_H__ */ diff --git a/trunk/drivers/net/ethernet/stmicro/stmmac/mmc.h b/trunk/drivers/net/ethernet/stmicro/stmmac/mmc.h index 67995ef25251..a38352024cb8 100644 --- a/trunk/drivers/net/ethernet/stmicro/stmmac/mmc.h +++ b/trunk/drivers/net/ethernet/stmicro/stmmac/mmc.h @@ -22,9 +22,6 @@ Author: Giuseppe Cavallaro *******************************************************************************/ -#ifndef __MMC_H__ -#define __MMC_H__ - /* MMC control register */ /* When set, all counter are reset */ #define MMC_CNTRL_COUNTER_RESET 0x1 @@ -132,5 +129,3 @@ struct stmmac_counters { extern void dwmac_mmc_ctrl(void __iomem *ioaddr, unsigned int mode); extern void dwmac_mmc_intr_all_mask(void __iomem *ioaddr); extern void dwmac_mmc_read(void __iomem *ioaddr, struct stmmac_counters *mmc); - -#endif /* __MMC_H__ */ diff --git a/trunk/drivers/net/ethernet/stmicro/stmmac/mmc_core.c b/trunk/drivers/net/ethernet/stmicro/stmmac/mmc_core.c index 0c74a702d461..c07cfe989f6e 100644 --- a/trunk/drivers/net/ethernet/stmicro/stmmac/mmc_core.c +++ b/trunk/drivers/net/ethernet/stmicro/stmmac/mmc_core.c @@ -33,7 +33,7 @@ #define MMC_TX_INTR 0x00000108 /* MMC TX Interrupt */ #define MMC_RX_INTR_MASK 0x0000010c /* MMC Interrupt Mask */ #define MMC_TX_INTR_MASK 0x00000110 /* MMC Interrupt Mask */ -#define MMC_DEFAULT_MASK 0xffffffff +#define MMC_DEFAUL_MASK 0xffffffff /* MMC TX counter registers */ @@ -147,8 +147,8 @@ void dwmac_mmc_ctrl(void __iomem *ioaddr, unsigned int mode) /* To mask all all interrupts.*/ void dwmac_mmc_intr_all_mask(void __iomem *ioaddr) { - writel(MMC_DEFAULT_MASK, ioaddr + MMC_RX_INTR_MASK); - writel(MMC_DEFAULT_MASK, ioaddr + MMC_TX_INTR_MASK); + writel(MMC_DEFAUL_MASK, ioaddr + MMC_RX_INTR_MASK); + writel(MMC_DEFAUL_MASK, ioaddr + MMC_TX_INTR_MASK); } /* This reads the MAC core counters (if actaully supported). diff --git a/trunk/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/trunk/drivers/net/ethernet/stmicro/stmmac/stmmac.h index e872e1da3137..f2d3665430ad 100644 --- a/trunk/drivers/net/ethernet/stmicro/stmmac/stmmac.h +++ b/trunk/drivers/net/ethernet/stmicro/stmmac/stmmac.h @@ -20,9 +20,6 @@ Author: Giuseppe Cavallaro *******************************************************************************/ -#ifndef __STMMAC_H__ -#define __STMMAC_H__ - #define STMMAC_RESOURCE_NAME "stmmaceth" #define DRV_MODULE_VERSION "March_2012" @@ -169,5 +166,3 @@ static inline void stmmac_unregister_pci(void) { } #endif /* CONFIG_STMMAC_PCI */ - -#endif /* __STMMAC_H__ */ diff --git a/trunk/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/trunk/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index 3be88331d17a..fd8882f9602a 100644 --- a/trunk/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/trunk/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -1066,7 +1066,7 @@ static int stmmac_open(struct net_device *dev) } else priv->tm->enable = 1; #endif - clk_prepare_enable(priv->stmmac_clk); + clk_enable(priv->stmmac_clk); stmmac_check_ether_addr(priv); @@ -1188,7 +1188,7 @@ static int stmmac_open(struct net_device *dev) if (priv->phydev) phy_disconnect(priv->phydev); - clk_disable_unprepare(priv->stmmac_clk); + clk_disable(priv->stmmac_clk); return ret; } @@ -1246,7 +1246,7 @@ static int stmmac_release(struct net_device *dev) #ifdef CONFIG_STMMAC_DEBUG_FS stmmac_exit_fs(); #endif - clk_disable_unprepare(priv->stmmac_clk); + clk_disable(priv->stmmac_clk); return 0; } @@ -2077,7 +2077,7 @@ struct stmmac_priv *stmmac_dvr_probe(struct device *device, goto error_netdev_register; } - priv->stmmac_clk = clk_get(priv->device, STMMAC_RESOURCE_NAME); + priv->stmmac_clk = clk_get(priv->device, NULL); if (IS_ERR(priv->stmmac_clk)) { pr_warning("%s: warning: cannot get CSR clock\n", __func__); goto error_clk_get; @@ -2178,7 +2178,7 @@ int stmmac_suspend(struct net_device *ndev) else { stmmac_set_mac(priv->ioaddr, false); /* Disable clock in case of PWM is off */ - clk_disable_unprepare(priv->stmmac_clk); + clk_disable(priv->stmmac_clk); } spin_unlock_irqrestore(&priv->lock, flags); return 0; @@ -2203,7 +2203,7 @@ int stmmac_resume(struct net_device *ndev) priv->hw->mac->pmt(priv->ioaddr, 0); else /* enable the clk prevously disabled */ - clk_prepare_enable(priv->stmmac_clk); + clk_enable(priv->stmmac_clk); netif_device_attach(ndev); diff --git a/trunk/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/trunk/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c index b93245c11995..cd01ee7ecef1 100644 --- a/trunk/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c +++ b/trunk/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c @@ -74,7 +74,7 @@ static int __devinit stmmac_probe_config_dt(struct platform_device *pdev, * the necessary resources and invokes the main to init * the net device, register the mdio bus etc. */ -static int __devinit stmmac_pltfr_probe(struct platform_device *pdev) +static int stmmac_pltfr_probe(struct platform_device *pdev) { int ret = 0; struct resource *res; diff --git a/trunk/drivers/net/ethernet/stmicro/stmmac/stmmac_timer.c b/trunk/drivers/net/ethernet/stmicro/stmmac/stmmac_timer.c index 4ccd4e2977b7..2a0e1abde7e7 100644 --- a/trunk/drivers/net/ethernet/stmicro/stmmac/stmmac_timer.c +++ b/trunk/drivers/net/ethernet/stmicro/stmmac/stmmac_timer.c @@ -97,19 +97,19 @@ static struct clk *timer_clock; static void stmmac_tmu_start(unsigned int new_freq) { clk_set_rate(timer_clock, new_freq); - clk_prepare_enable(timer_clock); + clk_enable(timer_clock); } static void stmmac_tmu_stop(void) { - clk_disable_unprepare(timer_clock); + clk_disable(timer_clock); } int stmmac_open_ext_timer(struct net_device *dev, struct stmmac_timer *tm) { timer_clock = clk_get(NULL, TMU_CHANNEL); - if (IS_ERR(timer_clock)) + if (timer_clock == NULL) return -1; if (tmu2_register_user(stmmac_timer_handler, (void *)dev) < 0) { @@ -126,7 +126,7 @@ int stmmac_open_ext_timer(struct net_device *dev, struct stmmac_timer *tm) int stmmac_close_ext_timer(void) { - clk_disable_unprepare(timer_clock); + clk_disable(timer_clock); tmu2_unregister_user(); clk_put(timer_clock); return 0; diff --git a/trunk/drivers/net/ethernet/stmicro/stmmac/stmmac_timer.h b/trunk/drivers/net/ethernet/stmicro/stmmac/stmmac_timer.h index aea9b14cdfbe..6863590d184b 100644 --- a/trunk/drivers/net/ethernet/stmicro/stmmac/stmmac_timer.h +++ b/trunk/drivers/net/ethernet/stmicro/stmmac/stmmac_timer.h @@ -21,8 +21,6 @@ Author: Giuseppe Cavallaro *******************************************************************************/ -#ifndef __STMMAC_TIMER_H__ -#define __STMMAC_TIMER_H__ struct stmmac_timer { void (*timer_start) (unsigned int new_freq); @@ -42,5 +40,3 @@ void stmmac_schedule(struct net_device *dev); extern int tmu2_register_user(void *fnt, void *data); extern void tmu2_unregister_user(void); #endif - -#endif /* __STMMAC_TIMER_H__ */ diff --git a/trunk/drivers/net/ethernet/sun/niu.c b/trunk/drivers/net/ethernet/sun/niu.c index 3208dca66758..c2a0fe393267 100644 --- a/trunk/drivers/net/ethernet/sun/niu.c +++ b/trunk/drivers/net/ethernet/sun/niu.c @@ -9762,8 +9762,9 @@ static int __devinit niu_pci_init_one(struct pci_dev *pdev, union niu_parent_id parent_id; struct net_device *dev; struct niu *np; - int err; + int err, pos; u64 dma_mask; + u16 val16; niu_driver_version(); @@ -9786,7 +9787,8 @@ static int __devinit niu_pci_init_one(struct pci_dev *pdev, goto err_out_disable_pdev; } - if (!pci_is_pcie(pdev)) { + pos = pci_pcie_cap(pdev); + if (pos <= 0) { dev_err(&pdev->dev, "Cannot find PCI Express capability, aborting\n"); goto err_out_free_res; } @@ -9811,11 +9813,14 @@ static int __devinit niu_pci_init_one(struct pci_dev *pdev, goto err_out_free_dev; } - pcie_capability_clear_and_set_word(pdev, PCI_EXP_DEVCTL, - PCI_EXP_DEVCTL_NOSNOOP_EN, - PCI_EXP_DEVCTL_CERE | PCI_EXP_DEVCTL_NFERE | - PCI_EXP_DEVCTL_FERE | PCI_EXP_DEVCTL_URRE | - PCI_EXP_DEVCTL_RELAX_EN); + pci_read_config_word(pdev, pos + PCI_EXP_DEVCTL, &val16); + val16 &= ~PCI_EXP_DEVCTL_NOSNOOP_EN; + val16 |= (PCI_EXP_DEVCTL_CERE | + PCI_EXP_DEVCTL_NFERE | + PCI_EXP_DEVCTL_FERE | + PCI_EXP_DEVCTL_URRE | + PCI_EXP_DEVCTL_RELAX_EN); + pci_write_config_word(pdev, pos + PCI_EXP_DEVCTL, val16); dma_mask = DMA_BIT_MASK(44); err = pci_set_dma_mask(pdev, dma_mask); diff --git a/trunk/drivers/net/ethernet/ti/davinci_cpdma.c b/trunk/drivers/net/ethernet/ti/davinci_cpdma.c index d15c888e9df8..3b5c4571b55e 100644 --- a/trunk/drivers/net/ethernet/ti/davinci_cpdma.c +++ b/trunk/drivers/net/ethernet/ti/davinci_cpdma.c @@ -538,12 +538,11 @@ EXPORT_SYMBOL_GPL(cpdma_chan_create); int cpdma_chan_destroy(struct cpdma_chan *chan) { - struct cpdma_ctlr *ctlr; + struct cpdma_ctlr *ctlr = chan->ctlr; unsigned long flags; if (!chan) return -EINVAL; - ctlr = chan->ctlr; spin_lock_irqsave(&ctlr->lock, flags); if (chan->state != CPDMA_STATE_IDLE) diff --git a/trunk/drivers/net/ethernet/ti/davinci_mdio.c b/trunk/drivers/net/ethernet/ti/davinci_mdio.c index a9ca4a03d31b..cd7ee204e94a 100644 --- a/trunk/drivers/net/ethernet/ti/davinci_mdio.c +++ b/trunk/drivers/net/ethernet/ti/davinci_mdio.c @@ -394,10 +394,8 @@ static int __devexit davinci_mdio_remove(struct platform_device *pdev) struct device *dev = &pdev->dev; struct davinci_mdio_data *data = dev_get_drvdata(dev); - if (data->bus) { - mdiobus_unregister(data->bus); + if (data->bus) mdiobus_free(data->bus); - } if (data->clk) clk_put(data->clk); diff --git a/trunk/drivers/net/ethernet/xscale/ixp4xx_eth.c b/trunk/drivers/net/ethernet/xscale/ixp4xx_eth.c index 98934bdf6acf..482648fcf0b6 100644 --- a/trunk/drivers/net/ethernet/xscale/ixp4xx_eth.c +++ b/trunk/drivers/net/ethernet/xscale/ixp4xx_eth.c @@ -1003,7 +1003,6 @@ static int ixp4xx_nway_reset(struct net_device *dev) } int ixp46x_phc_index = -1; -EXPORT_SYMBOL_GPL(ixp46x_phc_index); static int ixp4xx_get_ts_info(struct net_device *dev, struct ethtool_ts_info *info) diff --git a/trunk/drivers/net/fddi/skfp/pmf.c b/trunk/drivers/net/fddi/skfp/pmf.c index 441b4dc79450..24d8566cfd8b 100644 --- a/trunk/drivers/net/fddi/skfp/pmf.c +++ b/trunk/drivers/net/fddi/skfp/pmf.c @@ -673,7 +673,7 @@ void smt_add_para(struct s_smc *smc, struct s_pcon *pcon, u_short para, sm_pm_get_ls(smc,port_to_mib(smc,port))) ; break ; case SMT_P_REASON : - *(u32 *)to = 0 ; + * (u_long *) to = 0 ; sp_len = 4 ; goto sp_done ; case SMT_P1033 : /* time stamp */ diff --git a/trunk/drivers/net/hyperv/netvsc.c b/trunk/drivers/net/hyperv/netvsc.c index 4a1a5f58fa73..6cee2917eb02 100644 --- a/trunk/drivers/net/hyperv/netvsc.c +++ b/trunk/drivers/net/hyperv/netvsc.c @@ -383,6 +383,13 @@ int netvsc_device_remove(struct hv_device *device) unsigned long flags; net_device = hv_get_drvdata(device); + spin_lock_irqsave(&device->channel->inbound_lock, flags); + net_device->destroy = true; + spin_unlock_irqrestore(&device->channel->inbound_lock, flags); + + /* Wait for all send completions */ + wait_event(net_device->wait_drain, + atomic_read(&net_device->num_outstanding_sends) == 0); netvsc_disconnect_vsp(net_device); diff --git a/trunk/drivers/net/hyperv/rndis_filter.c b/trunk/drivers/net/hyperv/rndis_filter.c index 1e88a1095934..e5d6146937fa 100644 --- a/trunk/drivers/net/hyperv/rndis_filter.c +++ b/trunk/drivers/net/hyperv/rndis_filter.c @@ -718,9 +718,6 @@ static void rndis_filter_halt_device(struct rndis_device *dev) { struct rndis_request *request; struct rndis_halt_request *halt; - struct netvsc_device *nvdev = dev->net_dev; - struct hv_device *hdev = nvdev->dev; - ulong flags; /* Attempt to do a rndis device halt */ request = get_rndis_request(dev, RNDIS_MSG_HALT, @@ -738,14 +735,6 @@ static void rndis_filter_halt_device(struct rndis_device *dev) dev->state = RNDIS_DEV_UNINITIALIZED; cleanup: - spin_lock_irqsave(&hdev->channel->inbound_lock, flags); - nvdev->destroy = true; - spin_unlock_irqrestore(&hdev->channel->inbound_lock, flags); - - /* Wait for all send completions */ - wait_event(nvdev->wait_drain, - atomic_read(&nvdev->num_outstanding_sends) == 0); - if (request) put_rndis_request(dev, request); return; diff --git a/trunk/drivers/net/irda/bfin_sir.c b/trunk/drivers/net/irda/bfin_sir.c index c6a0299aa9f9..a561ae44a9ac 100644 --- a/trunk/drivers/net/irda/bfin_sir.c +++ b/trunk/drivers/net/irda/bfin_sir.c @@ -158,7 +158,7 @@ static int bfin_sir_set_speed(struct bfin_sir_port *port, int speed) /* If not add the 'RPOLC', we can't catch the receive interrupt. * It's related with the HW layout and the IR transiver. */ - val |= UMOD_IRDA | RPOLC; + val |= IREN | RPOLC; UART_PUT_GCTL(port, val); return ret; } @@ -432,7 +432,7 @@ static void bfin_sir_shutdown(struct bfin_sir_port *port, struct net_device *dev bfin_sir_stop_rx(port); val = UART_GET_GCTL(port); - val &= ~(UCEN | UMOD_MASK | RPOLC); + val &= ~(UCEN | IREN | RPOLC); UART_PUT_GCTL(port, val); #ifdef CONFIG_SIR_BFIN_DMA @@ -518,10 +518,10 @@ static void bfin_sir_send_work(struct work_struct *work) * reset all the UART. */ val = UART_GET_GCTL(port); - val &= ~(UMOD_MASK | RPOLC); + val &= ~(IREN | RPOLC); UART_PUT_GCTL(port, val); SSYNC(); - val |= UMOD_IRDA | RPOLC; + val |= IREN | RPOLC; UART_PUT_GCTL(port, val); SSYNC(); /* bfin_sir_set_speed(port, self->speed); */ diff --git a/trunk/drivers/net/irda/irtty-sir.c b/trunk/drivers/net/irda/irtty-sir.c index 30087ca23a0f..3352b2443e58 100644 --- a/trunk/drivers/net/irda/irtty-sir.c +++ b/trunk/drivers/net/irda/irtty-sir.c @@ -124,8 +124,8 @@ static int irtty_change_speed(struct sir_dev *dev, unsigned speed) tty = priv->tty; mutex_lock(&tty->termios_mutex); - old_termios = tty->termios; - cflag = tty->termios.c_cflag; + old_termios = *(tty->termios); + cflag = tty->termios->c_cflag; tty_encode_baud_rate(tty, speed, speed); if (tty->ops->set_termios) tty->ops->set_termios(tty, &old_termios); @@ -281,15 +281,15 @@ static inline void irtty_stop_receiver(struct tty_struct *tty, int stop) int cflag; mutex_lock(&tty->termios_mutex); - old_termios = tty->termios; - cflag = tty->termios.c_cflag; + old_termios = *(tty->termios); + cflag = tty->termios->c_cflag; if (stop) cflag &= ~CREAD; else cflag |= CREAD; - tty->termios.c_cflag = cflag; + tty->termios->c_cflag = cflag; if (tty->ops->set_termios) tty->ops->set_termios(tty, &old_termios); mutex_unlock(&tty->termios_mutex); diff --git a/trunk/drivers/net/irda/ks959-sir.c b/trunk/drivers/net/irda/ks959-sir.c index 5f3aeac3f86d..824e2a93fe8a 100644 --- a/trunk/drivers/net/irda/ks959-sir.c +++ b/trunk/drivers/net/irda/ks959-sir.c @@ -542,7 +542,6 @@ static int ks959_net_open(struct net_device *netdev) sprintf(hwname, "usb#%d", kingsun->usbdev->devnum); kingsun->irlap = irlap_open(netdev, &kingsun->qos, hwname); if (!kingsun->irlap) { - err = -ENOMEM; dev_err(&kingsun->usbdev->dev, "irlap_open failed\n"); goto free_mem; } diff --git a/trunk/drivers/net/irda/ksdazzle-sir.c b/trunk/drivers/net/irda/ksdazzle-sir.c index 2d4b6a1ab202..5a278ab83c2f 100644 --- a/trunk/drivers/net/irda/ksdazzle-sir.c +++ b/trunk/drivers/net/irda/ksdazzle-sir.c @@ -436,7 +436,6 @@ static int ksdazzle_net_open(struct net_device *netdev) sprintf(hwname, "usb#%d", kingsun->usbdev->devnum); kingsun->irlap = irlap_open(netdev, &kingsun->qos, hwname); if (!kingsun->irlap) { - err = -ENOMEM; dev_err(&kingsun->usbdev->dev, "irlap_open failed\n"); goto free_mem; } diff --git a/trunk/drivers/net/irda/sh_sir.c b/trunk/drivers/net/irda/sh_sir.c index 795109425568..256eddf1f75a 100644 --- a/trunk/drivers/net/irda/sh_sir.c +++ b/trunk/drivers/net/irda/sh_sir.c @@ -280,7 +280,7 @@ static int sh_sir_set_baudrate(struct sh_sir_self *self, u32 baudrate) } clk = clk_get(NULL, "irda_clk"); - if (IS_ERR(clk)) { + if (!clk) { dev_err(dev, "can not get irda_clk\n"); return -EIO; } diff --git a/trunk/drivers/net/macvtap.c b/trunk/drivers/net/macvtap.c index 0f0f9ce3a776..0737bd4d1669 100644 --- a/trunk/drivers/net/macvtap.c +++ b/trunk/drivers/net/macvtap.c @@ -94,8 +94,7 @@ static int get_slot(struct macvlan_dev *vlan, struct macvtap_queue *q) int i; for (i = 0; i < MAX_MACVTAP_QUEUES; i++) { - if (rcu_dereference_protected(vlan->taps[i], - lockdep_is_held(&macvtap_lock)) == q) + if (rcu_dereference(vlan->taps[i]) == q) return i; } diff --git a/trunk/drivers/net/netconsole.c b/trunk/drivers/net/netconsole.c index b3321129a83c..f9347ea3d381 100644 --- a/trunk/drivers/net/netconsole.c +++ b/trunk/drivers/net/netconsole.c @@ -640,9 +640,15 @@ static int netconsole_netdev_event(struct notifier_block *this, * rtnl_lock already held */ if (nt->np.dev) { + spin_unlock_irqrestore( + &target_list_lock, + flags); __netpoll_cleanup(&nt->np); + spin_lock_irqsave(&target_list_lock, + flags); dev_put(nt->np.dev); nt->np.dev = NULL; + netconsole_target_put(nt); } nt->enabled = 0; stopped = true; diff --git a/trunk/drivers/net/phy/bcm87xx.c b/trunk/drivers/net/phy/bcm87xx.c index 799789518e87..2346b38b9837 100644 --- a/trunk/drivers/net/phy/bcm87xx.c +++ b/trunk/drivers/net/phy/bcm87xx.c @@ -229,5 +229,3 @@ static void __exit bcm87xx_exit(void) ARRAY_SIZE(bcm87xx_driver)); } module_exit(bcm87xx_exit); - -MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/net/phy/mdio-mux-gpio.c b/trunk/drivers/net/phy/mdio-mux-gpio.c index eefe49e8713c..e0cc4ef33dee 100644 --- a/trunk/drivers/net/phy/mdio-mux-gpio.c +++ b/trunk/drivers/net/phy/mdio-mux-gpio.c @@ -101,6 +101,7 @@ static int __devinit mdio_mux_gpio_probe(struct platform_device *pdev) n--; gpio_free(s->gpio[n]); } + devm_kfree(&pdev->dev, s); return r; } diff --git a/trunk/drivers/net/phy/mdio-mux.c b/trunk/drivers/net/phy/mdio-mux.c index 4d4d25efc1e1..5c120189ec86 100644 --- a/trunk/drivers/net/phy/mdio-mux.c +++ b/trunk/drivers/net/phy/mdio-mux.c @@ -132,7 +132,7 @@ int mdio_mux_init(struct device *dev, pb->mii_bus = parent_bus; ret_val = -ENODEV; - for_each_available_child_of_node(dev->of_node, child_bus_node) { + for_each_child_of_node(dev->of_node, child_bus_node) { u32 v; r = of_property_read_u32(child_bus_node, "reg", &v); diff --git a/trunk/drivers/net/phy/micrel.c b/trunk/drivers/net/phy/micrel.c index 2165d5fdb8c0..cf287e0eb408 100644 --- a/trunk/drivers/net/phy/micrel.c +++ b/trunk/drivers/net/phy/micrel.c @@ -21,12 +21,6 @@ #include #include -/* Operation Mode Strap Override */ -#define MII_KSZPHY_OMSO 0x16 -#define KSZPHY_OMSO_B_CAST_OFF (1 << 9) -#define KSZPHY_OMSO_RMII_OVERRIDE (1 << 1) -#define KSZPHY_OMSO_MII_OVERRIDE (1 << 0) - /* general Interrupt control/status reg in vendor specific block. */ #define MII_KSZPHY_INTCS 0x1B #define KSZPHY_INTCS_JABBER (1 << 15) @@ -107,13 +101,6 @@ static int kszphy_config_init(struct phy_device *phydev) return 0; } -static int ksz8021_config_init(struct phy_device *phydev) -{ - const u16 val = KSZPHY_OMSO_B_CAST_OFF | KSZPHY_OMSO_RMII_OVERRIDE; - phy_write(phydev, MII_KSZPHY_OMSO, val); - return 0; -} - static int ks8051_config_init(struct phy_device *phydev) { int regval; @@ -141,22 +128,9 @@ static struct phy_driver ksphy_driver[] = { .config_intr = ks8737_config_intr, .driver = { .owner = THIS_MODULE,}, }, { - .phy_id = PHY_ID_KSZ8021, - .phy_id_mask = 0x00ffffff, - .name = "Micrel KSZ8021", - .features = (PHY_BASIC_FEATURES | SUPPORTED_Pause | - SUPPORTED_Asym_Pause), - .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT, - .config_init = ksz8021_config_init, - .config_aneg = genphy_config_aneg, - .read_status = genphy_read_status, - .ack_interrupt = kszphy_ack_interrupt, - .config_intr = kszphy_config_intr, - .driver = { .owner = THIS_MODULE,}, -}, { - .phy_id = PHY_ID_KSZ8041, + .phy_id = PHY_ID_KS8041, .phy_id_mask = 0x00fffff0, - .name = "Micrel KSZ8041", + .name = "Micrel KS8041", .features = (PHY_BASIC_FEATURES | SUPPORTED_Pause | SUPPORTED_Asym_Pause), .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT, @@ -167,9 +141,9 @@ static struct phy_driver ksphy_driver[] = { .config_intr = kszphy_config_intr, .driver = { .owner = THIS_MODULE,}, }, { - .phy_id = PHY_ID_KSZ8051, + .phy_id = PHY_ID_KS8051, .phy_id_mask = 0x00fffff0, - .name = "Micrel KSZ8051", + .name = "Micrel KS8051", .features = (PHY_BASIC_FEATURES | SUPPORTED_Pause | SUPPORTED_Asym_Pause), .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT, @@ -180,8 +154,8 @@ static struct phy_driver ksphy_driver[] = { .config_intr = kszphy_config_intr, .driver = { .owner = THIS_MODULE,}, }, { - .phy_id = PHY_ID_KSZ8001, - .name = "Micrel KSZ8001 or KS8721", + .phy_id = PHY_ID_KS8001, + .name = "Micrel KS8001 or KS8721", .phy_id_mask = 0x00ffffff, .features = (PHY_BASIC_FEATURES | SUPPORTED_Pause), .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT, @@ -227,11 +201,10 @@ MODULE_LICENSE("GPL"); static struct mdio_device_id __maybe_unused micrel_tbl[] = { { PHY_ID_KSZ9021, 0x000ffffe }, - { PHY_ID_KSZ8001, 0x00ffffff }, + { PHY_ID_KS8001, 0x00ffffff }, { PHY_ID_KS8737, 0x00fffff0 }, - { PHY_ID_KSZ8021, 0x00ffffff }, - { PHY_ID_KSZ8041, 0x00fffff0 }, - { PHY_ID_KSZ8051, 0x00fffff0 }, + { PHY_ID_KS8041, 0x00fffff0 }, + { PHY_ID_KS8051, 0x00fffff0 }, { } }; diff --git a/trunk/drivers/net/phy/smsc.c b/trunk/drivers/net/phy/smsc.c index 88e3991464e7..6d6192316b30 100644 --- a/trunk/drivers/net/phy/smsc.c +++ b/trunk/drivers/net/phy/smsc.c @@ -56,32 +56,6 @@ static int smsc_phy_config_init(struct phy_device *phydev) return smsc_phy_ack_interrupt (phydev); } -static int lan87xx_config_init(struct phy_device *phydev) -{ - /* - * Make sure the EDPWRDOWN bit is NOT set. Setting this bit on - * LAN8710/LAN8720 PHY causes the PHY to misbehave, likely due - * to a bug on the chip. - * - * When the system is powered on with the network cable being - * disconnected all the way until after ifconfig ethX up is - * issued for the LAN port with this PHY, connecting the cable - * afterwards does not cause LINK change detection, while the - * expected behavior is the Link UP being detected. - */ - int rc = phy_read(phydev, MII_LAN83C185_CTRL_STATUS); - if (rc < 0) - return rc; - - rc &= ~MII_LAN83C185_EDPWRDOWN; - - rc = phy_write(phydev, MII_LAN83C185_CTRL_STATUS, rc); - if (rc < 0) - return rc; - - return smsc_phy_ack_interrupt(phydev); -} - static int lan911x_config_init(struct phy_device *phydev) { return smsc_phy_ack_interrupt(phydev); @@ -188,7 +162,7 @@ static struct phy_driver smsc_phy_driver[] = { /* basic functions */ .config_aneg = genphy_config_aneg, .read_status = genphy_read_status, - .config_init = lan87xx_config_init, + .config_init = smsc_phy_config_init, /* IRQ related */ .ack_interrupt = smsc_phy_ack_interrupt, diff --git a/trunk/drivers/net/ppp/pppoe.c b/trunk/drivers/net/ppp/pppoe.c index 20f31d0d1536..cbf7047decc0 100644 --- a/trunk/drivers/net/ppp/pppoe.c +++ b/trunk/drivers/net/ppp/pppoe.c @@ -570,7 +570,7 @@ static int pppoe_release(struct socket *sock) po = pppox_sk(sk); - if (sk->sk_state & (PPPOX_CONNECTED | PPPOX_BOUND | PPPOX_ZOMBIE)) { + if (sk->sk_state & (PPPOX_CONNECTED | PPPOX_BOUND)) { dev_put(po->pppoe_dev); po->pppoe_dev = NULL; } diff --git a/trunk/drivers/net/ppp/pptp.c b/trunk/drivers/net/ppp/pptp.c index 162464fe86bf..1c98321b56cc 100644 --- a/trunk/drivers/net/ppp/pptp.c +++ b/trunk/drivers/net/ppp/pptp.c @@ -189,7 +189,7 @@ static int pptp_xmit(struct ppp_channel *chan, struct sk_buff *skb) if (sk_pppox(po)->sk_state & PPPOX_DEAD) goto tx_error; - rt = ip_route_output_ports(sock_net(sk), &fl4, NULL, + rt = ip_route_output_ports(&init_net, &fl4, NULL, opt->dst_addr.sin_addr.s_addr, opt->src_addr.sin_addr.s_addr, 0, 0, IPPROTO_GRE, @@ -468,7 +468,7 @@ static int pptp_connect(struct socket *sock, struct sockaddr *uservaddr, po->chan.private = sk; po->chan.ops = &pptp_chan_ops; - rt = ip_route_output_ports(sock_net(sk), &fl4, sk, + rt = ip_route_output_ports(&init_net, &fl4, sk, opt->dst_addr.sin_addr.s_addr, opt->src_addr.sin_addr.s_addr, 0, 0, diff --git a/trunk/drivers/net/team/team.c b/trunk/drivers/net/team/team.c index f8cd61f449a4..87707ab39430 100644 --- a/trunk/drivers/net/team/team.c +++ b/trunk/drivers/net/team/team.c @@ -795,17 +795,16 @@ static void team_port_leave(struct team *team, struct team_port *port) } #ifdef CONFIG_NET_POLL_CONTROLLER -static int team_port_enable_netpoll(struct team *team, struct team_port *port, - gfp_t gfp) +static int team_port_enable_netpoll(struct team *team, struct team_port *port) { struct netpoll *np; int err; - np = kzalloc(sizeof(*np), gfp); + np = kzalloc(sizeof(*np), GFP_KERNEL); if (!np) return -ENOMEM; - err = __netpoll_setup(np, port->dev, gfp); + err = __netpoll_setup(np, port->dev); if (err) { kfree(np); return err; @@ -834,8 +833,7 @@ static struct netpoll_info *team_netpoll_info(struct team *team) } #else -static int team_port_enable_netpoll(struct team *team, struct team_port *port, - gfp_t gfp) +static int team_port_enable_netpoll(struct team *team, struct team_port *port) { return 0; } @@ -848,7 +846,7 @@ static struct netpoll_info *team_netpoll_info(struct team *team) } #endif -static void __team_port_change_port_added(struct team_port *port, bool linkup); +static void __team_port_change_check(struct team_port *port, bool linkup); static int team_port_add(struct team *team, struct net_device *port_dev) { @@ -915,7 +913,7 @@ static int team_port_add(struct team *team, struct net_device *port_dev) } if (team_netpoll_info(team)) { - err = team_port_enable_netpoll(team, port, GFP_KERNEL); + err = team_port_enable_netpoll(team, port); if (err) { netdev_err(dev, "Failed to enable netpoll on device %s\n", portname); @@ -948,7 +946,7 @@ static int team_port_add(struct team *team, struct net_device *port_dev) team_port_enable(team, port); list_add_tail_rcu(&port->list, &team->port_list); __team_compute_features(team); - __team_port_change_port_added(port, !!netif_carrier_ok(port_dev)); + __team_port_change_check(port, !!netif_carrier_ok(port_dev)); __team_options_change_check(team); netdev_info(dev, "Port device %s added\n", portname); @@ -983,8 +981,6 @@ static int team_port_add(struct team *team, struct net_device *port_dev) return err; } -static void __team_port_change_port_removed(struct team_port *port); - static int team_port_del(struct team *team, struct net_device *port_dev) { struct net_device *dev = team->dev; @@ -1001,7 +997,8 @@ static int team_port_del(struct team *team, struct net_device *port_dev) __team_option_inst_mark_removed_port(team, port); __team_options_change_check(team); __team_option_inst_del_port(team, port); - __team_port_change_port_removed(port); + port->removed = true; + __team_port_change_check(port, false); team_port_disable(team, port); list_del_rcu(&port->list); netdev_rx_handler_unregister(port_dev); @@ -1446,7 +1443,7 @@ static void team_netpoll_cleanup(struct net_device *dev) } static int team_netpoll_setup(struct net_device *dev, - struct netpoll_info *npifo, gfp_t gfp) + struct netpoll_info *npifo) { struct team *team = netdev_priv(dev); struct team_port *port; @@ -1454,7 +1451,7 @@ static int team_netpoll_setup(struct net_device *dev, mutex_lock(&team->lock); list_for_each_entry(port, &team->port_list, list) { - err = team_port_enable_netpoll(team, port, gfp); + err = team_port_enable_netpoll(team, port); if (err) { __team_netpoll_cleanup(team); break; @@ -1653,8 +1650,8 @@ static int team_nl_cmd_noop(struct sk_buff *skb, struct genl_info *info) hdr = genlmsg_put(msg, info->snd_pid, info->snd_seq, &team_nl_family, 0, TEAM_CMD_NOOP); - if (!hdr) { - err = -EMSGSIZE; + if (IS_ERR(hdr)) { + err = PTR_ERR(hdr); goto err_msg_put; } @@ -1848,8 +1845,8 @@ static int team_nl_send_options_get(struct team *team, u32 pid, u32 seq, hdr = genlmsg_put(skb, pid, seq, &team_nl_family, flags | NLM_F_MULTI, TEAM_CMD_OPTIONS_GET); - if (!hdr) - return -EMSGSIZE; + if (IS_ERR(hdr)) + return PTR_ERR(hdr); if (nla_put_u32(skb, TEAM_ATTR_TEAM_IFINDEX, team->dev->ifindex)) goto nla_put_failure; @@ -2068,8 +2065,8 @@ static int team_nl_fill_port_list_get(struct sk_buff *skb, hdr = genlmsg_put(skb, pid, seq, &team_nl_family, flags, TEAM_CMD_PORT_LIST_GET); - if (!hdr) - return -EMSGSIZE; + if (IS_ERR(hdr)) + return PTR_ERR(hdr); if (nla_put_u32(skb, TEAM_ATTR_TEAM_IFINDEX, team->dev->ifindex)) goto nla_put_failure; @@ -2252,11 +2249,13 @@ static void __team_options_change_check(struct team *team) } /* rtnl lock is held */ - -static void __team_port_change_send(struct team_port *port, bool linkup) +static void __team_port_change_check(struct team_port *port, bool linkup) { int err; + if (!port->removed && port->state.linkup == linkup) + return; + port->changed = true; port->state.linkup = linkup; team_refresh_port_linkup(port); @@ -2281,23 +2280,6 @@ static void __team_port_change_send(struct team_port *port, bool linkup) } -static void __team_port_change_check(struct team_port *port, bool linkup) -{ - if (port->state.linkup != linkup) - __team_port_change_send(port, linkup); -} - -static void __team_port_change_port_added(struct team_port *port, bool linkup) -{ - __team_port_change_send(port, linkup); -} - -static void __team_port_change_port_removed(struct team_port *port) -{ - port->removed = true; - __team_port_change_send(port, false); -} - static void team_port_change_check(struct team_port *port, bool linkup) { struct team *team = port->team; diff --git a/trunk/drivers/net/tun.c b/trunk/drivers/net/tun.c index 3a16d4fdaa05..926d4db5cb38 100644 --- a/trunk/drivers/net/tun.c +++ b/trunk/drivers/net/tun.c @@ -187,6 +187,7 @@ static void __tun_detach(struct tun_struct *tun) netif_tx_lock_bh(tun->dev); netif_carrier_off(tun->dev); tun->tfile = NULL; + tun->socket.file = NULL; netif_tx_unlock_bh(tun->dev); /* Drop read queue */ diff --git a/trunk/drivers/net/usb/asix_devices.c b/trunk/drivers/net/usb/asix_devices.c index 32e31c5c5dc6..4fd48df6b989 100644 --- a/trunk/drivers/net/usb/asix_devices.c +++ b/trunk/drivers/net/usb/asix_devices.c @@ -961,10 +961,6 @@ static const struct usb_device_id products [] = { // DLink DUB-E100 H/W Ver B1 Alternate USB_DEVICE (0x2001, 0x3c05), .driver_info = (unsigned long) &ax88772_info, -}, { - // DLink DUB-E100 H/W Ver C1 - USB_DEVICE (0x2001, 0x1a02), - .driver_info = (unsigned long) &ax88772_info, }, { // Linksys USB1000 USB_DEVICE (0x1737, 0x0039), diff --git a/trunk/drivers/net/usb/cdc-phonet.c b/trunk/drivers/net/usb/cdc-phonet.c index 7d78669000d7..64610048ce87 100644 --- a/trunk/drivers/net/usb/cdc-phonet.c +++ b/trunk/drivers/net/usb/cdc-phonet.c @@ -232,7 +232,6 @@ static int usbpn_open(struct net_device *dev) struct urb *req = usb_alloc_urb(0, GFP_KERNEL); if (!req || rx_submit(pnd, req, GFP_KERNEL | __GFP_COLD)) { - usb_free_urb(req); usbpn_close(dev); return -ENOMEM; } diff --git a/trunk/drivers/net/usb/cdc_ncm.c b/trunk/drivers/net/usb/cdc_ncm.c index 4cd582a4f625..f4ce5957df32 100644 --- a/trunk/drivers/net/usb/cdc_ncm.c +++ b/trunk/drivers/net/usb/cdc_ncm.c @@ -1225,26 +1225,6 @@ static const struct usb_device_id cdc_devs[] = { .driver_info = (unsigned long) &wwan_info, }, - /* Dell branded MBM devices like DW5550 */ - { .match_flags = USB_DEVICE_ID_MATCH_INT_INFO - | USB_DEVICE_ID_MATCH_VENDOR, - .idVendor = 0x413c, - .bInterfaceClass = USB_CLASS_COMM, - .bInterfaceSubClass = USB_CDC_SUBCLASS_NCM, - .bInterfaceProtocol = USB_CDC_PROTO_NONE, - .driver_info = (unsigned long) &wwan_info, - }, - - /* Toshiba branded MBM devices */ - { .match_flags = USB_DEVICE_ID_MATCH_INT_INFO - | USB_DEVICE_ID_MATCH_VENDOR, - .idVendor = 0x0930, - .bInterfaceClass = USB_CLASS_COMM, - .bInterfaceSubClass = USB_CDC_SUBCLASS_NCM, - .bInterfaceProtocol = USB_CDC_PROTO_NONE, - .driver_info = (unsigned long) &wwan_info, - }, - /* Generic CDC-NCM devices */ { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_NCM, USB_CDC_PROTO_NONE), diff --git a/trunk/drivers/net/usb/hso.c b/trunk/drivers/net/usb/hso.c index 605a4baa9b7b..62f30b46fa42 100644 --- a/trunk/drivers/net/usb/hso.c +++ b/trunk/drivers/net/usb/hso.c @@ -1107,6 +1107,7 @@ static void _hso_serial_set_termios(struct tty_struct *tty, struct ktermios *old) { struct hso_serial *serial = tty->driver_data; + struct ktermios *termios; if (!serial) { printk(KERN_ERR "%s: no tty structures", __func__); @@ -1118,15 +1119,16 @@ static void _hso_serial_set_termios(struct tty_struct *tty, /* * Fix up unsupported bits */ - tty->termios.c_iflag &= ~IXON; /* disable enable XON/XOFF flow control */ + termios = tty->termios; + termios->c_iflag &= ~IXON; /* disable enable XON/XOFF flow control */ - tty->termios.c_cflag &= + termios->c_cflag &= ~(CSIZE /* no size */ | PARENB /* disable parity bit */ | CBAUD /* clear current baud rate */ | CBAUDEX); /* clear current buad rate */ - tty->termios.c_cflag |= CS8; /* character size 8 bits */ + termios->c_cflag |= CS8; /* character size 8 bits */ /* baud rate 115200 */ tty_encode_baud_rate(tty, 115200, 115200); @@ -1423,14 +1425,14 @@ static void hso_serial_set_termios(struct tty_struct *tty, struct ktermios *old) if (old) D5("Termios called with: cflags new[%d] - old[%d]", - tty->termios.c_cflag, old->c_cflag); + tty->termios->c_cflag, old->c_cflag); /* the actual setup */ spin_lock_irqsave(&serial->serial_lock, flags); if (serial->port.count) _hso_serial_set_termios(tty, old); else - tty->termios = *old; + tty->termios = old; spin_unlock_irqrestore(&serial->serial_lock, flags); /* done */ @@ -2287,11 +2289,9 @@ static int hso_serial_common_create(struct hso_serial *serial, int num_urbs, if (minor < 0) goto exit; - tty_port_init(&serial->port); - /* register our minor number */ - serial->parent->dev = tty_port_register_device(&serial->port, tty_drv, - minor, &serial->parent->interface->dev); + serial->parent->dev = tty_register_device(tty_drv, minor, + &serial->parent->interface->dev); dev = serial->parent->dev; dev_set_drvdata(dev, serial->parent); i = device_create_file(dev, &dev_attr_hsotype); @@ -2300,6 +2300,7 @@ static int hso_serial_common_create(struct hso_serial *serial, int num_urbs, serial->minor = minor; serial->magic = HSO_SERIAL_MAGIC; spin_lock_init(&serial->serial_lock); + tty_port_init(&serial->port); serial->num_rx_urbs = num_urbs; /* RX, allocate urb and initialize */ diff --git a/trunk/drivers/net/usb/qmi_wwan.c b/trunk/drivers/net/usb/qmi_wwan.c index 3543c9e57824..2ea126a16d79 100644 --- a/trunk/drivers/net/usb/qmi_wwan.c +++ b/trunk/drivers/net/usb/qmi_wwan.c @@ -247,12 +247,30 @@ static int qmi_wwan_bind(struct usbnet *dev, struct usb_interface *intf) */ static int qmi_wwan_bind_shared(struct usbnet *dev, struct usb_interface *intf) { + int rv; struct qmi_wwan_state *info = (void *)&dev->data; + /* ZTE makes devices where the interface descriptors and endpoint + * configurations of two or more interfaces are identical, even + * though the functions are completely different. If set, then + * driver_info->data is a bitmap of acceptable interface numbers + * allowing us to bind to one such interface without binding to + * all of them + */ + if (dev->driver_info->data && + !test_bit(intf->cur_altsetting->desc.bInterfaceNumber, &dev->driver_info->data)) { + dev_info(&intf->dev, "not on our whitelist - ignored"); + rv = -ENODEV; + goto err; + } + /* control and data is shared */ info->control = intf; info->data = intf; - return qmi_wwan_register_subdriver(dev); + rv = qmi_wwan_register_subdriver(dev); + +err: + return rv; } static void qmi_wwan_unbind(struct usbnet *dev, struct usb_interface *intf) @@ -297,7 +315,7 @@ static int qmi_wwan_suspend(struct usb_interface *intf, pm_message_t message) if (ret < 0) goto err; - if (intf == info->control && info->subdriver && info->subdriver->suspend) + if (info->subdriver && info->subdriver->suspend) ret = info->subdriver->suspend(intf, message); if (ret < 0) usbnet_resume(intf); @@ -310,14 +328,13 @@ static int qmi_wwan_resume(struct usb_interface *intf) struct usbnet *dev = usb_get_intfdata(intf); struct qmi_wwan_state *info = (void *)&dev->data; int ret = 0; - bool callsub = (intf == info->control && info->subdriver && info->subdriver->resume); - if (callsub) + if (info->subdriver && info->subdriver->resume) ret = info->subdriver->resume(intf); if (ret < 0) goto err; ret = usbnet_resume(intf); - if (ret < 0 && callsub && info->subdriver->suspend) + if (ret < 0 && info->subdriver && info->subdriver->resume && info->subdriver->suspend) info->subdriver->suspend(intf, PMSG_SUSPEND); err: return ret; @@ -339,71 +356,217 @@ static const struct driver_info qmi_wwan_shared = { .manage_power = qmi_wwan_manage_power, }; -#define HUAWEI_VENDOR_ID 0x12D1 +static const struct driver_info qmi_wwan_force_int0 = { + .description = "Qualcomm WWAN/QMI device", + .flags = FLAG_WWAN, + .bind = qmi_wwan_bind_shared, + .unbind = qmi_wwan_unbind, + .manage_power = qmi_wwan_manage_power, + .data = BIT(0), /* interface whitelist bitmap */ +}; + +static const struct driver_info qmi_wwan_force_int1 = { + .description = "Qualcomm WWAN/QMI device", + .flags = FLAG_WWAN, + .bind = qmi_wwan_bind_shared, + .unbind = qmi_wwan_unbind, + .manage_power = qmi_wwan_manage_power, + .data = BIT(1), /* interface whitelist bitmap */ +}; + +static const struct driver_info qmi_wwan_force_int2 = { + .description = "Qualcomm WWAN/QMI device", + .flags = FLAG_WWAN, + .bind = qmi_wwan_bind_shared, + .unbind = qmi_wwan_unbind, + .manage_power = qmi_wwan_manage_power, + .data = BIT(2), /* interface whitelist bitmap */ +}; -/* map QMI/wwan function by a fixed interface number */ -#define QMI_FIXED_INTF(vend, prod, num) \ - USB_DEVICE_INTERFACE_NUMBER(vend, prod, num), \ - .driver_info = (unsigned long)&qmi_wwan_shared +static const struct driver_info qmi_wwan_force_int3 = { + .description = "Qualcomm WWAN/QMI device", + .flags = FLAG_WWAN, + .bind = qmi_wwan_bind_shared, + .unbind = qmi_wwan_unbind, + .manage_power = qmi_wwan_manage_power, + .data = BIT(3), /* interface whitelist bitmap */ +}; + +static const struct driver_info qmi_wwan_force_int4 = { + .description = "Qualcomm WWAN/QMI device", + .flags = FLAG_WWAN, + .bind = qmi_wwan_bind_shared, + .unbind = qmi_wwan_unbind, + .manage_power = qmi_wwan_manage_power, + .data = BIT(4), /* interface whitelist bitmap */ +}; + +/* Sierra Wireless provide equally useless interface descriptors + * Devices in QMI mode can be switched between two different + * configurations: + * a) USB interface #8 is QMI/wwan + * b) USB interfaces #8, #19 and #20 are QMI/wwan + * + * Both configurations provide a number of other interfaces (serial++), + * some of which have the same endpoint configuration as we expect, so + * a whitelist or blacklist is necessary. + * + * FIXME: The below whitelist should include BIT(20). It does not + * because I cannot get it to work... + */ +static const struct driver_info qmi_wwan_sierra = { + .description = "Sierra Wireless wwan/QMI device", + .flags = FLAG_WWAN, + .bind = qmi_wwan_bind_shared, + .unbind = qmi_wwan_unbind, + .manage_power = qmi_wwan_manage_power, + .data = BIT(8) | BIT(19), /* interface whitelist bitmap */ +}; + +#define HUAWEI_VENDOR_ID 0x12D1 /* Gobi 1000 QMI/wwan interface number is 3 according to qcserial */ #define QMI_GOBI1K_DEVICE(vend, prod) \ - QMI_FIXED_INTF(vend, prod, 3) + USB_DEVICE(vend, prod), \ + .driver_info = (unsigned long)&qmi_wwan_force_int3 -/* Gobi 2000/3000 QMI/wwan interface number is 0 according to qcserial */ +/* Gobi 2000 and Gobi 3000 QMI/wwan interface number is 0 according to qcserial */ #define QMI_GOBI_DEVICE(vend, prod) \ - QMI_FIXED_INTF(vend, prod, 0) + USB_DEVICE(vend, prod), \ + .driver_info = (unsigned long)&qmi_wwan_force_int0 static const struct usb_device_id products[] = { - /* 1. CDC ECM like devices match on the control interface */ { /* Huawei E392, E398 and possibly others sharing both device id and more... */ - USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, USB_CLASS_VENDOR_SPEC, 1, 9), + .match_flags = USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_INT_INFO, + .idVendor = HUAWEI_VENDOR_ID, + .bInterfaceClass = USB_CLASS_VENDOR_SPEC, + .bInterfaceSubClass = 1, + .bInterfaceProtocol = 9, /* CDC Ethernet *control* interface */ .driver_info = (unsigned long)&qmi_wwan_info, }, { /* Vodafone/Huawei K5005 (12d1:14c8) and similar modems */ - USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, USB_CLASS_VENDOR_SPEC, 1, 57), + .match_flags = USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_INT_INFO, + .idVendor = HUAWEI_VENDOR_ID, + .bInterfaceClass = USB_CLASS_VENDOR_SPEC, + .bInterfaceSubClass = 1, + .bInterfaceProtocol = 57, /* CDC Ethernet *control* interface */ .driver_info = (unsigned long)&qmi_wwan_info, }, - - /* 2. Combined interface devices matching on class+protocol */ - { /* Huawei E367 and possibly others in "Windows mode" */ - USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, USB_CLASS_VENDOR_SPEC, 1, 7), - .driver_info = (unsigned long)&qmi_wwan_info, - }, - { /* Huawei E392, E398 and possibly others in "Windows mode" */ - USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, USB_CLASS_VENDOR_SPEC, 1, 17), + { /* Huawei E392, E398 and possibly others in "Windows mode" + * using a combined control and data interface without any CDC + * functional descriptors + */ + .match_flags = USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_INT_INFO, + .idVendor = HUAWEI_VENDOR_ID, + .bInterfaceClass = USB_CLASS_VENDOR_SPEC, + .bInterfaceSubClass = 1, + .bInterfaceProtocol = 17, .driver_info = (unsigned long)&qmi_wwan_shared, }, - { /* Pantech UML290, P4200 and more */ - USB_VENDOR_AND_INTERFACE_INFO(0x106c, USB_CLASS_VENDOR_SPEC, 0xf0, 0xff), + { /* Pantech UML290 */ + .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, + .idVendor = 0x106c, + .idProduct = 0x3718, + .bInterfaceClass = 0xff, + .bInterfaceSubClass = 0xf0, + .bInterfaceProtocol = 0xff, .driver_info = (unsigned long)&qmi_wwan_shared, }, - { /* Pantech UML290 - newer firmware */ - USB_VENDOR_AND_INTERFACE_INFO(0x106c, USB_CLASS_VENDOR_SPEC, 0xf1, 0xff), - .driver_info = (unsigned long)&qmi_wwan_shared, + { /* ZTE MF820D */ + .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, + .idVendor = 0x19d2, + .idProduct = 0x0167, + .bInterfaceClass = 0xff, + .bInterfaceSubClass = 0xff, + .bInterfaceProtocol = 0xff, + .driver_info = (unsigned long)&qmi_wwan_force_int4, + }, + { /* ZTE MF821D */ + .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, + .idVendor = 0x19d2, + .idProduct = 0x0326, + .bInterfaceClass = 0xff, + .bInterfaceSubClass = 0xff, + .bInterfaceProtocol = 0xff, + .driver_info = (unsigned long)&qmi_wwan_force_int4, + }, + { /* ZTE (Vodafone) K3520-Z */ + .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, + .idVendor = 0x19d2, + .idProduct = 0x0055, + .bInterfaceClass = 0xff, + .bInterfaceSubClass = 0xff, + .bInterfaceProtocol = 0xff, + .driver_info = (unsigned long)&qmi_wwan_force_int1, + }, + { /* ZTE (Vodafone) K3565-Z */ + .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, + .idVendor = 0x19d2, + .idProduct = 0x0063, + .bInterfaceClass = 0xff, + .bInterfaceSubClass = 0xff, + .bInterfaceProtocol = 0xff, + .driver_info = (unsigned long)&qmi_wwan_force_int4, + }, + { /* ZTE (Vodafone) K3570-Z */ + .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, + .idVendor = 0x19d2, + .idProduct = 0x1008, + .bInterfaceClass = 0xff, + .bInterfaceSubClass = 0xff, + .bInterfaceProtocol = 0xff, + .driver_info = (unsigned long)&qmi_wwan_force_int4, + }, + { /* ZTE (Vodafone) K3571-Z */ + .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, + .idVendor = 0x19d2, + .idProduct = 0x1010, + .bInterfaceClass = 0xff, + .bInterfaceSubClass = 0xff, + .bInterfaceProtocol = 0xff, + .driver_info = (unsigned long)&qmi_wwan_force_int4, + }, + { /* ZTE (Vodafone) K3765-Z */ + .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, + .idVendor = 0x19d2, + .idProduct = 0x2002, + .bInterfaceClass = 0xff, + .bInterfaceSubClass = 0xff, + .bInterfaceProtocol = 0xff, + .driver_info = (unsigned long)&qmi_wwan_force_int4, + }, + { /* ZTE (Vodafone) K4505-Z */ + .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, + .idVendor = 0x19d2, + .idProduct = 0x0104, + .bInterfaceClass = 0xff, + .bInterfaceSubClass = 0xff, + .bInterfaceProtocol = 0xff, + .driver_info = (unsigned long)&qmi_wwan_force_int4, + }, + { /* ZTE MF60 */ + .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, + .idVendor = 0x19d2, + .idProduct = 0x1402, + .bInterfaceClass = 0xff, + .bInterfaceSubClass = 0xff, + .bInterfaceProtocol = 0xff, + .driver_info = (unsigned long)&qmi_wwan_force_int2, + }, + { /* Sierra Wireless MC77xx in QMI mode */ + .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, + .idVendor = 0x1199, + .idProduct = 0x68a2, + .bInterfaceClass = 0xff, + .bInterfaceSubClass = 0xff, + .bInterfaceProtocol = 0xff, + .driver_info = (unsigned long)&qmi_wwan_sierra, }, - /* 3. Combined interface devices matching on interface number */ - {QMI_FIXED_INTF(0x19d2, 0x0055, 1)}, /* ZTE (Vodafone) K3520-Z */ - {QMI_FIXED_INTF(0x19d2, 0x0063, 4)}, /* ZTE (Vodafone) K3565-Z */ - {QMI_FIXED_INTF(0x19d2, 0x0104, 4)}, /* ZTE (Vodafone) K4505-Z */ - {QMI_FIXED_INTF(0x19d2, 0x0157, 5)}, /* ZTE MF683 */ - {QMI_FIXED_INTF(0x19d2, 0x0167, 4)}, /* ZTE MF820D */ - {QMI_FIXED_INTF(0x19d2, 0x0326, 4)}, /* ZTE MF821D */ - {QMI_FIXED_INTF(0x19d2, 0x1008, 4)}, /* ZTE (Vodafone) K3570-Z */ - {QMI_FIXED_INTF(0x19d2, 0x1010, 4)}, /* ZTE (Vodafone) K3571-Z */ - {QMI_FIXED_INTF(0x19d2, 0x1018, 3)}, /* ZTE (Vodafone) K5006-Z */ - {QMI_FIXED_INTF(0x19d2, 0x1402, 2)}, /* ZTE MF60 */ - {QMI_FIXED_INTF(0x19d2, 0x2002, 4)}, /* ZTE (Vodafone) K3765-Z */ - {QMI_FIXED_INTF(0x0f3d, 0x68a2, 8)}, /* Sierra Wireless MC7700 */ - {QMI_FIXED_INTF(0x114f, 0x68a2, 8)}, /* Sierra Wireless MC7750 */ - {QMI_FIXED_INTF(0x1199, 0x68a2, 8)}, /* Sierra Wireless MC7710 in QMI mode */ - {QMI_FIXED_INTF(0x1199, 0x68a2, 19)}, /* Sierra Wireless MC7710 in QMI mode */ - {QMI_FIXED_INTF(0x1199, 0x901c, 8)}, /* Sierra Wireless EM7700 */ - - /* 4. Gobi 1000 devices */ + /* Gobi 1000 devices */ {QMI_GOBI1K_DEVICE(0x05c6, 0x9212)}, /* Acer Gobi Modem Device */ {QMI_GOBI1K_DEVICE(0x03f0, 0x1f1d)}, /* HP un2400 Gobi Modem Device */ + {QMI_GOBI1K_DEVICE(0x03f0, 0x371d)}, /* HP un2430 Mobile Broadband Module */ {QMI_GOBI1K_DEVICE(0x04da, 0x250d)}, /* Panasonic Gobi Modem device */ {QMI_GOBI1K_DEVICE(0x413c, 0x8172)}, /* Dell Gobi Modem device */ {QMI_GOBI1K_DEVICE(0x1410, 0xa001)}, /* Novatel Gobi Modem device */ @@ -416,11 +579,9 @@ static const struct usb_device_id products[] = { {QMI_GOBI1K_DEVICE(0x05c6, 0x9222)}, /* Generic Gobi Modem device */ {QMI_GOBI1K_DEVICE(0x05c6, 0x9009)}, /* Generic Gobi Modem device */ - /* 5. Gobi 2000 and 3000 devices */ + /* Gobi 2000 and 3000 devices */ {QMI_GOBI_DEVICE(0x413c, 0x8186)}, /* Dell Gobi 2000 Modem device (N0218, VU936) */ - {QMI_GOBI_DEVICE(0x413c, 0x8194)}, /* Dell Gobi 3000 Composite */ {QMI_GOBI_DEVICE(0x05c6, 0x920b)}, /* Generic Gobi 2000 Modem device */ - {QMI_GOBI_DEVICE(0x05c6, 0x920d)}, /* Gobi 3000 Composite */ {QMI_GOBI_DEVICE(0x05c6, 0x9225)}, /* Sony Gobi 2000 Modem device (N0279, VU730) */ {QMI_GOBI_DEVICE(0x05c6, 0x9245)}, /* Samsung Gobi 2000 Modem device (VL176) */ {QMI_GOBI_DEVICE(0x03f0, 0x251d)}, /* HP Gobi 2000 Modem device (VP412) */ @@ -428,8 +589,6 @@ static const struct usb_device_id products[] = { {QMI_GOBI_DEVICE(0x05c6, 0x9265)}, /* Asus Gobi 2000 Modem device (VR305) */ {QMI_GOBI_DEVICE(0x05c6, 0x9235)}, /* Top Global Gobi 2000 Modem device (VR306) */ {QMI_GOBI_DEVICE(0x05c6, 0x9275)}, /* iRex Technologies Gobi 2000 Modem device (VR307) */ - {QMI_GOBI_DEVICE(0x1199, 0x68a5)}, /* Sierra Wireless Modem */ - {QMI_GOBI_DEVICE(0x1199, 0x68a9)}, /* Sierra Wireless Modem */ {QMI_GOBI_DEVICE(0x1199, 0x9001)}, /* Sierra Wireless Gobi 2000 Modem device (VT773) */ {QMI_GOBI_DEVICE(0x1199, 0x9002)}, /* Sierra Wireless Gobi 2000 Modem device (VT773) */ {QMI_GOBI_DEVICE(0x1199, 0x9003)}, /* Sierra Wireless Gobi 2000 Modem device (VT773) */ @@ -441,17 +600,11 @@ static const struct usb_device_id products[] = { {QMI_GOBI_DEVICE(0x1199, 0x9009)}, /* Sierra Wireless Gobi 2000 Modem device (VT773) */ {QMI_GOBI_DEVICE(0x1199, 0x900a)}, /* Sierra Wireless Gobi 2000 Modem device (VT773) */ {QMI_GOBI_DEVICE(0x1199, 0x9011)}, /* Sierra Wireless Gobi 2000 Modem device (MC8305) */ - {QMI_FIXED_INTF(0x1199, 0x9011, 5)}, /* alternate interface number!? */ {QMI_GOBI_DEVICE(0x16d8, 0x8002)}, /* CMDTech Gobi 2000 Modem device (VU922) */ {QMI_GOBI_DEVICE(0x05c6, 0x9205)}, /* Gobi 2000 Modem device */ {QMI_GOBI_DEVICE(0x1199, 0x9013)}, /* Sierra Wireless Gobi 3000 Modem device (MC8355) */ - {QMI_GOBI_DEVICE(0x03f0, 0x371d)}, /* HP un2430 Mobile Broadband Module */ {QMI_GOBI_DEVICE(0x1199, 0x9015)}, /* Sierra Wireless Gobi 3000 Modem device */ {QMI_GOBI_DEVICE(0x1199, 0x9019)}, /* Sierra Wireless Gobi 3000 Modem device */ - {QMI_GOBI_DEVICE(0x1199, 0x901b)}, /* Sierra Wireless MC7770 */ - {QMI_GOBI_DEVICE(0x12d1, 0x14f1)}, /* Sony Gobi 3000 Composite */ - {QMI_GOBI_DEVICE(0x1410, 0xa021)}, /* Foxconn Gobi 3000 Modem device (Novatel E396) */ - { } /* END */ }; MODULE_DEVICE_TABLE(usb, products); diff --git a/trunk/drivers/net/usb/sierra_net.c b/trunk/drivers/net/usb/sierra_net.c index 8e22417fa6c1..d75d1f56becf 100644 --- a/trunk/drivers/net/usb/sierra_net.c +++ b/trunk/drivers/net/usb/sierra_net.c @@ -68,8 +68,15 @@ static atomic_t iface_counter = ATOMIC_INIT(0); */ #define SIERRA_NET_USBCTL_BUF_LEN 1024 +/* list of interface numbers - used for constructing interface lists */ +struct sierra_net_iface_info { + const u32 infolen; /* number of interface numbers on list */ + const u8 *ifaceinfo; /* pointer to the array holding the numbers */ +}; + struct sierra_net_info_data { u16 rx_urb_size; + struct sierra_net_iface_info whitelist; }; /* Private data structure */ @@ -630,6 +637,21 @@ static int sierra_net_change_mtu(struct net_device *net, int new_mtu) return usbnet_change_mtu(net, new_mtu); } +static int is_whitelisted(const u8 ifnum, + const struct sierra_net_iface_info *whitelist) +{ + if (whitelist) { + const u8 *list = whitelist->ifaceinfo; + int i; + + for (i = 0; i < whitelist->infolen; i++) { + if (list[i] == ifnum) + return 1; + } + } + return 0; +} + static int sierra_net_get_fw_attr(struct usbnet *dev, u16 *datap) { int result = 0; @@ -656,7 +678,7 @@ static int sierra_net_get_fw_attr(struct usbnet *dev, u16 *datap) return -EIO; } - *datap = le16_to_cpu(*attrdata); + *datap = *attrdata; kfree(attrdata); return result; @@ -684,6 +706,11 @@ static int sierra_net_bind(struct usbnet *dev, struct usb_interface *intf) dev_dbg(&dev->udev->dev, "%s", __func__); ifacenum = intf->cur_altsetting->desc.bInterfaceNumber; + /* We only accept certain interfaces */ + if (!is_whitelisted(ifacenum, &data->whitelist)) { + dev_dbg(&dev->udev->dev, "Ignoring interface: %d", ifacenum); + return -ENODEV; + } numendpoints = intf->cur_altsetting->desc.bNumEndpoints; /* We have three endpoints, bulk in and out, and a status */ if (numendpoints != 3) { @@ -918,8 +945,13 @@ struct sk_buff *sierra_net_tx_fixup(struct usbnet *dev, struct sk_buff *skb, return NULL; } +static const u8 sierra_net_ifnum_list[] = { 7, 10, 11 }; static const struct sierra_net_info_data sierra_net_info_data_direct_ip = { .rx_urb_size = 8 * 1024, + .whitelist = { + .infolen = ARRAY_SIZE(sierra_net_ifnum_list), + .ifaceinfo = sierra_net_ifnum_list + } }; static const struct driver_info sierra_net_info_direct_ip = { @@ -933,19 +965,15 @@ static const struct driver_info sierra_net_info_direct_ip = { .data = (unsigned long)&sierra_net_info_data_direct_ip, }; -#define DIRECT_IP_DEVICE(vend, prod) \ - {USB_DEVICE_INTERFACE_NUMBER(vend, prod, 7), \ - .driver_info = (unsigned long)&sierra_net_info_direct_ip}, \ - {USB_DEVICE_INTERFACE_NUMBER(vend, prod, 10), \ - .driver_info = (unsigned long)&sierra_net_info_direct_ip}, \ - {USB_DEVICE_INTERFACE_NUMBER(vend, prod, 11), \ - .driver_info = (unsigned long)&sierra_net_info_direct_ip} - static const struct usb_device_id products[] = { - DIRECT_IP_DEVICE(0x1199, 0x68A3), /* Sierra Wireless USB-to-WWAN modem */ - DIRECT_IP_DEVICE(0x0F3D, 0x68A3), /* AT&T Direct IP modem */ - DIRECT_IP_DEVICE(0x1199, 0x68AA), /* Sierra Wireless Direct IP LTE modem */ - DIRECT_IP_DEVICE(0x0F3D, 0x68AA), /* AT&T Direct IP LTE modem */ + {USB_DEVICE(0x1199, 0x68A3), /* Sierra Wireless USB-to-WWAN modem */ + .driver_info = (unsigned long) &sierra_net_info_direct_ip}, + {USB_DEVICE(0x0F3D, 0x68A3), /* AT&T Direct IP modem */ + .driver_info = (unsigned long) &sierra_net_info_direct_ip}, + {USB_DEVICE(0x1199, 0x68AA), /* Sierra Wireless Direct IP LTE modem */ + .driver_info = (unsigned long) &sierra_net_info_direct_ip}, + {USB_DEVICE(0x0F3D, 0x68AA), /* AT&T Direct IP LTE modem */ + .driver_info = (unsigned long) &sierra_net_info_direct_ip}, {}, /* last item */ }; diff --git a/trunk/drivers/net/usb/smsc75xx.c b/trunk/drivers/net/usb/smsc75xx.c index 376143e8a1aa..f5ab6e613ec8 100644 --- a/trunk/drivers/net/usb/smsc75xx.c +++ b/trunk/drivers/net/usb/smsc75xx.c @@ -1253,7 +1253,6 @@ static struct usb_driver smsc75xx_driver = { .probe = usbnet_probe, .suspend = usbnet_suspend, .resume = usbnet_resume, - .reset_resume = usbnet_resume, .disconnect = usbnet_disconnect, .disable_hub_initiated_lpm = 1, }; diff --git a/trunk/drivers/net/usb/usbnet.c b/trunk/drivers/net/usb/usbnet.c index fc9f578a1e25..8531c1caac28 100644 --- a/trunk/drivers/net/usb/usbnet.c +++ b/trunk/drivers/net/usb/usbnet.c @@ -1201,26 +1201,19 @@ netdev_tx_t usbnet_start_xmit (struct sk_buff *skb, } EXPORT_SYMBOL_GPL(usbnet_start_xmit); -static int rx_alloc_submit(struct usbnet *dev, gfp_t flags) +static void rx_alloc_submit(struct usbnet *dev, gfp_t flags) { struct urb *urb; int i; - int ret = 0; /* don't refill the queue all at once */ for (i = 0; i < 10 && dev->rxq.qlen < RX_QLEN(dev); i++) { urb = usb_alloc_urb(0, flags); if (urb != NULL) { - ret = rx_submit(dev, urb, flags); - if (ret) - goto err; - } else { - ret = -ENOMEM; - goto err; + if (rx_submit(dev, urb, flags) == -ENOLINK) + return; } } -err: - return ret; } /*-------------------------------------------------------------------------*/ @@ -1264,8 +1257,7 @@ static void usbnet_bh (unsigned long param) int temp = dev->rxq.qlen; if (temp < RX_QLEN(dev)) { - if (rx_alloc_submit(dev, GFP_ATOMIC) == -ENOLINK) - return; + rx_alloc_submit(dev, GFP_ATOMIC); if (temp != dev->rxq.qlen) netif_dbg(dev, link, dev->net, "rxqlen %d --> %d\n", @@ -1581,7 +1573,7 @@ int usbnet_resume (struct usb_interface *intf) netif_device_present(dev->net) && !timer_pending(&dev->delay) && !test_bit(EVENT_RX_HALT, &dev->flags)) - rx_alloc_submit(dev, GFP_NOIO); + rx_alloc_submit(dev, GFP_KERNEL); if (!(dev->txq.qlen >= TX_QLEN(dev))) netif_tx_wake_all_queues(dev->net); diff --git a/trunk/drivers/net/vmxnet3/vmxnet3_drv.c b/trunk/drivers/net/vmxnet3/vmxnet3_drv.c index ce9d4f2c9776..93e0cfb739b8 100644 --- a/trunk/drivers/net/vmxnet3/vmxnet3_drv.c +++ b/trunk/drivers/net/vmxnet3/vmxnet3_drv.c @@ -3019,7 +3019,6 @@ vmxnet3_probe_device(struct pci_dev *pdev, netdev->watchdog_timeo = 5 * HZ; INIT_WORK(&adapter->work, vmxnet3_reset_work); - set_bit(VMXNET3_STATE_BIT_QUIESCED, &adapter->state); if (adapter->intr.type == VMXNET3_IT_MSIX) { int i; @@ -3044,6 +3043,7 @@ vmxnet3_probe_device(struct pci_dev *pdev, goto err_register; } + set_bit(VMXNET3_STATE_BIT_QUIESCED, &adapter->state); vmxnet3_check_link(adapter, false); atomic_inc(&devices_found); return 0; diff --git a/trunk/drivers/net/wan/dscc4.c b/trunk/drivers/net/wan/dscc4.c index ef36cafd44b7..9eb6479306d6 100644 --- a/trunk/drivers/net/wan/dscc4.c +++ b/trunk/drivers/net/wan/dscc4.c @@ -774,15 +774,14 @@ static int __devinit dscc4_init_one(struct pci_dev *pdev, } /* Global interrupt queue */ writel((u32)(((IRQ_RING_SIZE >> 5) - 1) << 20), ioaddr + IQLENR1); - - rc = -ENOMEM; - priv->iqcfg = (__le32 *) pci_alloc_consistent(pdev, IRQ_RING_SIZE*sizeof(__le32), &priv->iqcfg_dma); if (!priv->iqcfg) goto err_free_irq_5; writel(priv->iqcfg_dma, ioaddr + IQCFG); + rc = -ENOMEM; + /* * SCC 0-3 private rx/tx irq structures * IQRX/TXi needs to be set soon. Learned it the hard way... diff --git a/trunk/drivers/net/wan/ixp4xx_hss.c b/trunk/drivers/net/wan/ixp4xx_hss.c index 3f575afd8cfc..aaaca9aa2293 100644 --- a/trunk/drivers/net/wan/ixp4xx_hss.c +++ b/trunk/drivers/net/wan/ixp4xx_hss.c @@ -10,7 +10,6 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -#include #include #include #include diff --git a/trunk/drivers/net/wimax/i2400m/fw.c b/trunk/drivers/net/wimax/i2400m/fw.c index def12b38cbf7..283237f6f074 100644 --- a/trunk/drivers/net/wimax/i2400m/fw.c +++ b/trunk/drivers/net/wimax/i2400m/fw.c @@ -326,10 +326,8 @@ int i2400m_barker_db_init(const char *_options) unsigned barker; options_orig = kstrdup(_options, GFP_KERNEL); - if (options_orig == NULL) { - result = -ENOMEM; + if (options_orig == NULL) goto error_parse; - } options = options_orig; while ((token = strsep(&options, ",")) != NULL) { diff --git a/trunk/drivers/net/wireless/at76c50x-usb.c b/trunk/drivers/net/wireless/at76c50x-usb.c index 88b8d64c90f1..efc162e0b511 100644 --- a/trunk/drivers/net/wireless/at76c50x-usb.c +++ b/trunk/drivers/net/wireless/at76c50x-usb.c @@ -342,7 +342,7 @@ static int at76_dfu_get_status(struct usb_device *udev, return ret; } -static int at76_dfu_get_state(struct usb_device *udev, u8 *state) +static u8 at76_dfu_get_state(struct usb_device *udev, u8 *state) { int ret; diff --git a/trunk/drivers/net/wireless/ath/ath5k/base.c b/trunk/drivers/net/wireless/ath/ath5k/base.c index 2aab20ee9f38..8c4c040a47b8 100644 --- a/trunk/drivers/net/wireless/ath/ath5k/base.c +++ b/trunk/drivers/net/wireless/ath/ath5k/base.c @@ -2056,7 +2056,9 @@ ath5k_beacon_update_timers(struct ath5k_hw *ah, u64 bc_tsf) void ath5k_beacon_config(struct ath5k_hw *ah) { - spin_lock_bh(&ah->block); + unsigned long flags; + + spin_lock_irqsave(&ah->block, flags); ah->bmisscount = 0; ah->imask &= ~(AR5K_INT_BMISS | AR5K_INT_SWBA); @@ -2083,7 +2085,7 @@ ath5k_beacon_config(struct ath5k_hw *ah) ath5k_hw_set_imr(ah, ah->imask); mmiowb(); - spin_unlock_bh(&ah->block); + spin_unlock_irqrestore(&ah->block, flags); } static void ath5k_tasklet_beacon(unsigned long data) diff --git a/trunk/drivers/net/wireless/ath/ath5k/eeprom.c b/trunk/drivers/net/wireless/ath/ath5k/eeprom.c index b7e0258887e7..4026c906cc7b 100644 --- a/trunk/drivers/net/wireless/ath/ath5k/eeprom.c +++ b/trunk/drivers/net/wireless/ath/ath5k/eeprom.c @@ -1482,7 +1482,7 @@ ath5k_eeprom_read_target_rate_pwr_info(struct ath5k_hw *ah, unsigned int mode) case AR5K_EEPROM_MODE_11A: offset += AR5K_EEPROM_TARGET_PWR_OFF_11A(ee->ee_version); rate_pcal_info = ee->ee_rate_tpwr_a; - ee->ee_rate_target_pwr_num[mode] = AR5K_EEPROM_N_5GHZ_RATE_CHAN; + ee->ee_rate_target_pwr_num[mode] = AR5K_EEPROM_N_5GHZ_CHAN; break; case AR5K_EEPROM_MODE_11B: offset += AR5K_EEPROM_TARGET_PWR_OFF_11B(ee->ee_version); diff --git a/trunk/drivers/net/wireless/ath/ath5k/eeprom.h b/trunk/drivers/net/wireless/ath/ath5k/eeprom.h index 94a9bbea6874..dc2bcfeadeb4 100644 --- a/trunk/drivers/net/wireless/ath/ath5k/eeprom.h +++ b/trunk/drivers/net/wireless/ath/ath5k/eeprom.h @@ -182,7 +182,6 @@ #define AR5K_EEPROM_EEP_DELTA 10 #define AR5K_EEPROM_N_MODES 3 #define AR5K_EEPROM_N_5GHZ_CHAN 10 -#define AR5K_EEPROM_N_5GHZ_RATE_CHAN 8 #define AR5K_EEPROM_N_2GHZ_CHAN 3 #define AR5K_EEPROM_N_2GHZ_CHAN_2413 4 #define AR5K_EEPROM_N_2GHZ_CHAN_MAX 4 diff --git a/trunk/drivers/net/wireless/ath/ath5k/mac80211-ops.c b/trunk/drivers/net/wireless/ath/ath5k/mac80211-ops.c index d56453e43d7e..260e7dc7f751 100644 --- a/trunk/drivers/net/wireless/ath/ath5k/mac80211-ops.c +++ b/trunk/drivers/net/wireless/ath/ath5k/mac80211-ops.c @@ -254,6 +254,7 @@ ath5k_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ath5k_vif *avf = (void *)vif->drv_priv; struct ath5k_hw *ah = hw->priv; struct ath_common *common = ath5k_hw_common(ah); + unsigned long flags; mutex_lock(&ah->lock); @@ -299,9 +300,9 @@ ath5k_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, } if (changes & BSS_CHANGED_BEACON) { - spin_lock_bh(&ah->block); + spin_lock_irqsave(&ah->block, flags); ath5k_beacon_update(hw, vif); - spin_unlock_bh(&ah->block); + spin_unlock_irqrestore(&ah->block, flags); } if (changes & BSS_CHANGED_BEACON_ENABLED) diff --git a/trunk/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/trunk/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c index d066f2516e47..2588848f4a82 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c +++ b/trunk/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c @@ -2982,10 +2982,6 @@ static u32 ath9k_hw_ar9300_get_eeprom(struct ath_hw *ah, case EEP_RX_MASK: return pBase->txrxMask & 0xf; case EEP_PAPRD: - if (AR_SREV_9462(ah)) - return false; - if (!ah->config.enable_paprd); - return false; return !!(pBase->featureEnable & BIT(5)); case EEP_CHAIN_MASK_REDUCE: return (pBase->miscConfiguration >> 0x3) & 0x1; diff --git a/trunk/drivers/net/wireless/ath/ath9k/ar9003_paprd.c b/trunk/drivers/net/wireless/ath/ath9k/ar9003_paprd.c index 0ed3846f9cbb..2c9f7d7ed4cc 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/ar9003_paprd.c +++ b/trunk/drivers/net/wireless/ath/ath9k/ar9003_paprd.c @@ -142,7 +142,6 @@ static int ar9003_paprd_setup_single_table(struct ath_hw *ah) }; int training_power; int i, val; - u32 am2pm_mask = ah->paprd_ratemask; if (IS_CHAN_2GHZ(ah->curchan)) training_power = ar9003_get_training_power_2g(ah); @@ -159,13 +158,10 @@ static int ar9003_paprd_setup_single_table(struct ath_hw *ah) } ah->paprd_training_power = training_power; - if (AR_SREV_9330(ah)) - am2pm_mask = 0; - REG_RMW_FIELD(ah, AR_PHY_PAPRD_AM2AM, AR_PHY_PAPRD_AM2AM_MASK, ah->paprd_ratemask); REG_RMW_FIELD(ah, AR_PHY_PAPRD_AM2PM, AR_PHY_PAPRD_AM2PM_MASK, - am2pm_mask); + ah->paprd_ratemask); REG_RMW_FIELD(ah, AR_PHY_PAPRD_HT40, AR_PHY_PAPRD_HT40_MASK, ah->paprd_ratemask_ht40); @@ -786,102 +782,6 @@ int ar9003_paprd_setup_gain_table(struct ath_hw *ah, int chain) } EXPORT_SYMBOL(ar9003_paprd_setup_gain_table); -static bool ar9003_paprd_retrain_pa_in(struct ath_hw *ah, - struct ath9k_hw_cal_data *caldata, - int chain) -{ - u32 *pa_in = caldata->pa_table[chain]; - int capdiv_offset, quick_drop_offset; - int capdiv2g, quick_drop; - int count = 0; - int i; - - if (!AR_SREV_9485(ah) && !AR_SREV_9330(ah)) - return false; - - capdiv2g = REG_READ_FIELD(ah, AR_PHY_65NM_CH0_TXRF3, - AR_PHY_65NM_CH0_TXRF3_CAPDIV2G); - - quick_drop = REG_READ_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3, - AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_QUICK_DROP); - - if (quick_drop) - quick_drop -= 0x40; - - for (i = 0; i < NUM_BIN + 1; i++) { - if (pa_in[i] == 1400) - count++; - } - - if (AR_SREV_9485(ah)) { - if (pa_in[23] < 800) { - capdiv_offset = (int)((1000 - pa_in[23] + 75) / 150); - capdiv2g += capdiv_offset; - if (capdiv2g > 7) { - capdiv2g = 7; - if (pa_in[23] < 600) { - quick_drop++; - if (quick_drop > 0) - quick_drop = 0; - } - } - } else if (pa_in[23] == 1400) { - quick_drop_offset = min_t(int, count / 3, 2); - quick_drop += quick_drop_offset; - capdiv2g += quick_drop_offset / 2; - - if (capdiv2g > 7) - capdiv2g = 7; - - if (quick_drop > 0) { - quick_drop = 0; - capdiv2g -= quick_drop_offset; - if (capdiv2g < 0) - capdiv2g = 0; - } - } else { - return false; - } - } else if (AR_SREV_9330(ah)) { - if (pa_in[23] < 1000) { - capdiv_offset = (1000 - pa_in[23]) / 100; - capdiv2g += capdiv_offset; - if (capdiv_offset > 3) { - capdiv_offset = 1; - quick_drop--; - } - - capdiv2g += capdiv_offset; - if (capdiv2g > 6) - capdiv2g = 6; - if (quick_drop < -4) - quick_drop = -4; - } else if (pa_in[23] == 1400) { - if (count > 3) { - quick_drop++; - capdiv2g -= count / 4; - if (quick_drop > -2) - quick_drop = -2; - } else { - capdiv2g--; - } - - if (capdiv2g < 0) - capdiv2g = 0; - } else { - return false; - } - } - - REG_RMW_FIELD(ah, AR_PHY_65NM_CH0_TXRF3, - AR_PHY_65NM_CH0_TXRF3_CAPDIV2G, capdiv2g); - REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3, - AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_QUICK_DROP, - quick_drop); - - return true; -} - int ar9003_paprd_create_curve(struct ath_hw *ah, struct ath9k_hw_cal_data *caldata, int chain) { @@ -917,9 +817,6 @@ int ar9003_paprd_create_curve(struct ath_hw *ah, if (!create_pa_curve(data_L, data_U, pa_table, small_signal_gain)) status = -2; - if (ar9003_paprd_retrain_pa_in(ah, caldata, chain)) - status = -EINPROGRESS; - REG_CLR_BIT(ah, AR_PHY_PAPRD_TRAINER_STAT1, AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_TRAIN_DONE); diff --git a/trunk/drivers/net/wireless/ath/ath9k/ar9003_phy.h b/trunk/drivers/net/wireless/ath/ath9k/ar9003_phy.h index 84d3d4956861..7bfbaf065a43 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/ar9003_phy.h +++ b/trunk/drivers/net/wireless/ath/ath9k/ar9003_phy.h @@ -625,10 +625,6 @@ #define AR_PHY_AIC_CTRL_4_B0 (AR_SM_BASE + 0x4c0) #define AR_PHY_AIC_STAT_2_B0 (AR_SM_BASE + 0x4cc) -#define AR_PHY_65NM_CH0_TXRF3 0x16048 -#define AR_PHY_65NM_CH0_TXRF3_CAPDIV2G 0x0000001e -#define AR_PHY_65NM_CH0_TXRF3_CAPDIV2G_S 1 - #define AR_PHY_65NM_CH0_SYNTH4 0x1608c #define AR_PHY_SYNTH4_LONG_SHIFT_SELECT (AR_SREV_9462(ah) ? 0x00000001 : 0x00000002) #define AR_PHY_SYNTH4_LONG_SHIFT_SELECT_S (AR_SREV_9462(ah) ? 0 : 1) diff --git a/trunk/drivers/net/wireless/ath/ath9k/debug.c b/trunk/drivers/net/wireless/ath/ath9k/debug.c index c8ef30127adb..68b643c8943c 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/debug.c +++ b/trunk/drivers/net/wireless/ath/ath9k/debug.c @@ -1577,8 +1577,6 @@ int ath9k_init_debug(struct ath_hw *ah) sc->debug.debugfs_phy, sc, &fops_tx_chainmask); debugfs_create_file("disable_ani", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, sc, &fops_disable_ani); - debugfs_create_bool("paprd", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, - &sc->sc_ah->config.enable_paprd); debugfs_create_file("regidx", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, sc, &fops_regidx); debugfs_create_file("regval", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, diff --git a/trunk/drivers/net/wireless/ath/ath9k/gpio.c b/trunk/drivers/net/wireless/ath/ath9k/gpio.c index 9f83f71742a5..bacdb8fb4ef4 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/gpio.c +++ b/trunk/drivers/net/wireless/ath/ath9k/gpio.c @@ -341,8 +341,7 @@ void ath9k_btcoex_stop_gen_timer(struct ath_softc *sc) { struct ath_btcoex *btcoex = &sc->btcoex; - if (btcoex->hw_timer_enabled) - ath9k_gen_timer_stop(sc->sc_ah, btcoex->no_stomp_timer); + ath9k_gen_timer_stop(sc->sc_ah, btcoex->no_stomp_timer); } u16 ath9k_btcoex_aggr_limit(struct ath_softc *sc, u32 max_4ms_framelen) diff --git a/trunk/drivers/net/wireless/ath/ath9k/hw.c b/trunk/drivers/net/wireless/ath/ath9k/hw.c index 4faf0a395876..cfa91ab7acf8 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/hw.c +++ b/trunk/drivers/net/wireless/ath/ath9k/hw.c @@ -463,6 +463,9 @@ static void ath9k_hw_init_config(struct ath_hw *ah) ah->config.spurchans[i][1] = AR_NO_SPUR; } + /* PAPRD needs some more work to be enabled */ + ah->config.paprd_disable = 1; + ah->config.rx_intr_mitigation = true; ah->config.pcieSerDesWrite = true; @@ -727,7 +730,6 @@ int ath9k_hw_init(struct ath_hw *ah) case AR9300_DEVID_QCA955X: case AR9300_DEVID_AR9580: case AR9300_DEVID_AR9462: - case AR9485_DEVID_AR1111: break; default: if (common->bus_ops->ath_bus_type == ATH_USB) @@ -975,6 +977,9 @@ static void ath9k_hw_init_interrupt_masks(struct ath_hw *ah, else imr_reg |= AR_IMR_TXOK; + if (opmode == NL80211_IFTYPE_AP) + imr_reg |= AR_IMR_MIB; + ENABLE_REGWRITE_BUFFER(ah); REG_WRITE(ah, AR_IMR, imr_reg); @@ -1772,8 +1777,6 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, /* Operating channel changed, reset channel calibration data */ memset(caldata, 0, sizeof(*caldata)); ath9k_init_nfcal_hist_buffer(ah, chan); - } else if (caldata) { - caldata->paprd_packet_sent = false; } ah->noise = ath9k_hw_getchan_noise(ah, chan); @@ -2497,6 +2500,9 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) pCap->rx_status_len = sizeof(struct ar9003_rxs); pCap->tx_desc_len = sizeof(struct ar9003_txc); pCap->txs_len = sizeof(struct ar9003_txs); + if (!ah->config.paprd_disable && + ah->eep_ops->get_eeprom(ah, EEP_PAPRD)) + pCap->hw_caps |= ATH9K_HW_CAP_PAPRD; } else { pCap->tx_desc_len = sizeof(struct ath_desc); if (AR_SREV_9280_20(ah)) diff --git a/trunk/drivers/net/wireless/ath/ath9k/hw.h b/trunk/drivers/net/wireless/ath/ath9k/hw.h index de6968fc64f4..dd0c146d81dc 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/hw.h +++ b/trunk/drivers/net/wireless/ath/ath9k/hw.h @@ -49,7 +49,6 @@ #define AR9300_DEVID_AR9462 0x0034 #define AR9300_DEVID_AR9330 0x0035 #define AR9300_DEVID_QCA955X 0x0038 -#define AR9485_DEVID_AR1111 0x0037 #define AR5416_AR9100_DEVID 0x000b @@ -236,6 +235,7 @@ enum ath9k_hw_caps { ATH9K_HW_CAP_LDPC = BIT(6), ATH9K_HW_CAP_FASTCLOCK = BIT(7), ATH9K_HW_CAP_SGI_20 = BIT(8), + ATH9K_HW_CAP_PAPRD = BIT(9), ATH9K_HW_CAP_ANT_DIV_COMB = BIT(10), ATH9K_HW_CAP_2GHZ = BIT(11), ATH9K_HW_CAP_5GHZ = BIT(12), @@ -286,12 +286,12 @@ struct ath9k_ops_config { u8 pcie_clock_req; u32 pcie_waen; u8 analog_shiftreg; + u8 paprd_disable; u32 ofdm_trig_low; u32 ofdm_trig_high; u32 cck_trig_high; u32 cck_trig_low; u32 enable_ani; - u32 enable_paprd; int serialize_regmode; bool rx_intr_mitigation; bool tx_intr_mitigation; @@ -404,7 +404,6 @@ struct ath9k_hw_cal_data { int8_t iCoff; int8_t qCoff; bool rtt_done; - bool paprd_packet_sent; bool paprd_done; bool nfcal_pending; bool nfcal_interference; diff --git a/trunk/drivers/net/wireless/ath/ath9k/link.c b/trunk/drivers/net/wireless/ath/ath9k/link.c index 7b88b9c39ccd..d4549e9aac5c 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/link.c +++ b/trunk/drivers/net/wireless/ath/ath9k/link.c @@ -254,9 +254,8 @@ void ath_paprd_calibrate(struct work_struct *work) int chain_ok = 0; int chain; int len = 1800; - int ret; - if (!caldata || !caldata->paprd_packet_sent || caldata->paprd_done) + if (!caldata) return; ath9k_ps_wakeup(sc); @@ -283,6 +282,13 @@ void ath_paprd_calibrate(struct work_struct *work) continue; chain_ok = 0; + + ath_dbg(common, CALIBRATE, + "Sending PAPRD frame for thermal measurement on chain %d\n", + chain); + if (!ath_paprd_send_frame(sc, skb, chain)) + goto fail_paprd; + ar9003_paprd_setup_gain_table(ah, chain); ath_dbg(common, CALIBRATE, @@ -296,13 +302,7 @@ void ath_paprd_calibrate(struct work_struct *work) break; } - ret = ar9003_paprd_create_curve(ah, caldata, chain); - if (ret == -EINPROGRESS) { - ath_dbg(common, CALIBRATE, - "PAPRD curve on chain %d needs to be re-trained\n", - chain); - break; - } else if (ret) { + if (ar9003_paprd_create_curve(ah, caldata, chain)) { ath_dbg(common, CALIBRATE, "PAPRD create curve failed on chain %d\n", chain); @@ -423,7 +423,7 @@ void ath_ani_calibrate(unsigned long data) cal_interval = min(cal_interval, (u32)short_cal_interval); mod_timer(&common->ani.timer, jiffies + msecs_to_jiffies(cal_interval)); - if (ah->eep_ops->get_eeprom(ah, EEP_PAPRD) && ah->caldata) { + if ((sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_PAPRD) && ah->caldata) { if (!ah->caldata->paprd_done) ieee80211_queue_work(sc->hw, &sc->paprd_work); else if (!ah->paprd_table_write_done) diff --git a/trunk/drivers/net/wireless/ath/ath9k/mac.c b/trunk/drivers/net/wireless/ath/ath9k/mac.c index b42be910a83d..7990cd55599c 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/mac.c +++ b/trunk/drivers/net/wireless/ath/ath9k/mac.c @@ -773,10 +773,15 @@ bool ath9k_hw_intrpend(struct ath_hw *ah) } EXPORT_SYMBOL(ath9k_hw_intrpend); -void ath9k_hw_kill_interrupts(struct ath_hw *ah) +void ath9k_hw_disable_interrupts(struct ath_hw *ah) { struct ath_common *common = ath9k_hw_common(ah); + if (!(ah->imask & ATH9K_INT_GLOBAL)) + atomic_set(&ah->intr_ref_cnt, -1); + else + atomic_dec(&ah->intr_ref_cnt); + ath_dbg(common, INTERRUPT, "disable IER\n"); REG_WRITE(ah, AR_IER, AR_IER_DISABLE); (void) REG_READ(ah, AR_IER); @@ -788,17 +793,6 @@ void ath9k_hw_kill_interrupts(struct ath_hw *ah) (void) REG_READ(ah, AR_INTR_SYNC_ENABLE); } } -EXPORT_SYMBOL(ath9k_hw_kill_interrupts); - -void ath9k_hw_disable_interrupts(struct ath_hw *ah) -{ - if (!(ah->imask & ATH9K_INT_GLOBAL)) - atomic_set(&ah->intr_ref_cnt, -1); - else - atomic_dec(&ah->intr_ref_cnt); - - ath9k_hw_kill_interrupts(ah); -} EXPORT_SYMBOL(ath9k_hw_disable_interrupts); void ath9k_hw_enable_interrupts(struct ath_hw *ah) diff --git a/trunk/drivers/net/wireless/ath/ath9k/mac.h b/trunk/drivers/net/wireless/ath/ath9k/mac.h index 4a745e68dd94..0eba36dca6f8 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/mac.h +++ b/trunk/drivers/net/wireless/ath/ath9k/mac.h @@ -738,7 +738,6 @@ bool ath9k_hw_intrpend(struct ath_hw *ah); void ath9k_hw_set_interrupts(struct ath_hw *ah); void ath9k_hw_enable_interrupts(struct ath_hw *ah); void ath9k_hw_disable_interrupts(struct ath_hw *ah); -void ath9k_hw_kill_interrupts(struct ath_hw *ah); void ar9002_hw_attach_mac_ops(struct ath_hw *ah); diff --git a/trunk/drivers/net/wireless/ath/ath9k/main.c b/trunk/drivers/net/wireless/ath/ath9k/main.c index a22df749b8db..6049d8b82855 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/main.c +++ b/trunk/drivers/net/wireless/ath/ath9k/main.c @@ -462,10 +462,8 @@ irqreturn_t ath_isr(int irq, void *dev) if (!ath9k_hw_intrpend(ah)) return IRQ_NONE; - if (test_bit(SC_OP_HW_RESET, &sc->sc_flags)) { - ath9k_hw_kill_interrupts(ah); + if(test_bit(SC_OP_HW_RESET, &sc->sc_flags)) return IRQ_HANDLED; - } /* * Figure out the reason(s) for the interrupt. Note diff --git a/trunk/drivers/net/wireless/ath/ath9k/pci.c b/trunk/drivers/net/wireless/ath/ath9k/pci.c index ef11dc639461..87b89d55e637 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/pci.c +++ b/trunk/drivers/net/wireless/ath/ath9k/pci.c @@ -37,7 +37,6 @@ static DEFINE_PCI_DEVICE_TABLE(ath_pci_id_table) = { { PCI_VDEVICE(ATHEROS, 0x0032) }, /* PCI-E AR9485 */ { PCI_VDEVICE(ATHEROS, 0x0033) }, /* PCI-E AR9580 */ { PCI_VDEVICE(ATHEROS, 0x0034) }, /* PCI-E AR9462 */ - { PCI_VDEVICE(ATHEROS, 0x0037) }, /* PCI-E AR1111/AR9485 */ { 0 } }; @@ -113,32 +112,41 @@ static void ath_pci_aspm_init(struct ath_common *common) struct ath_hw *ah = sc->sc_ah; struct pci_dev *pdev = to_pci_dev(sc->dev); struct pci_dev *parent; - u16 aspm; + int pos; + u8 aspm; if (!ah->is_pciexpress) return; + pos = pci_pcie_cap(pdev); + if (!pos) + return; + parent = pdev->bus->self; if (!parent) return; if (ath9k_hw_get_btcoex_scheme(ah) != ATH_BTCOEX_CFG_NONE) { /* Bluetooth coexistance requires disabling ASPM. */ - pcie_capability_clear_word(pdev, PCI_EXP_LNKCTL, - PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1); + pci_read_config_byte(pdev, pos + PCI_EXP_LNKCTL, &aspm); + aspm &= ~(PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1); + pci_write_config_byte(pdev, pos + PCI_EXP_LNKCTL, aspm); /* * Both upstream and downstream PCIe components should * have the same ASPM settings. */ - pcie_capability_clear_word(parent, PCI_EXP_LNKCTL, - PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1); + pos = pci_pcie_cap(parent); + pci_read_config_byte(parent, pos + PCI_EXP_LNKCTL, &aspm); + aspm &= ~(PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1); + pci_write_config_byte(parent, pos + PCI_EXP_LNKCTL, aspm); ath_info(common, "Disabling ASPM since BTCOEX is enabled\n"); return; } - pcie_capability_read_word(parent, PCI_EXP_LNKCTL, &aspm); + pos = pci_pcie_cap(parent); + pci_read_config_byte(parent, pos + PCI_EXP_LNKCTL, &aspm); if (aspm & (PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1)) { ah->aspm_enabled = true; /* Initialize PCIe PM and SERDES registers. */ @@ -312,7 +320,6 @@ static int ath_pci_suspend(struct device *device) * Otherwise the chip never moved to full sleep, * when no interface is up. */ - ath9k_stop_btcoex(sc); ath9k_hw_disable(sc->sc_ah); ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_FULL_SLEEP); diff --git a/trunk/drivers/net/wireless/ath/ath9k/recv.c b/trunk/drivers/net/wireless/ath/ath9k/recv.c index 4480c0cc655f..12aca02228c2 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/recv.c +++ b/trunk/drivers/net/wireless/ath/ath9k/recv.c @@ -1044,6 +1044,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) struct ieee80211_hw *hw = sc->hw; struct ieee80211_hdr *hdr; int retval; + bool decrypt_error = false; struct ath_rx_status rs; enum ath9k_rx_qtype qtype; bool edma = !!(ah->caps.hw_caps & ATH9K_HW_CAP_EDMA); @@ -1065,7 +1066,6 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) tsf_lower = tsf & 0xffffffff; do { - bool decrypt_error = false; /* If handling rx interrupt and flush is in progress => exit */ if (test_bit(SC_OP_RXFLUSH, &sc->sc_flags) && (flush == 0)) break; diff --git a/trunk/drivers/net/wireless/ath/ath9k/xmit.c b/trunk/drivers/net/wireless/ath/ath9k/xmit.c index 0d4155aec48d..2c9da6b2ecb1 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/xmit.c +++ b/trunk/drivers/net/wireless/ath/ath9k/xmit.c @@ -2018,9 +2018,6 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, ath_dbg(common, XMIT, "TX complete: skb: %p\n", skb); - if (sc->sc_ah->caldata) - sc->sc_ah->caldata->paprd_packet_sent = true; - if (!(tx_flags & ATH_TX_ERROR)) /* Frame was ACKed */ tx_info->flags |= IEEE80211_TX_STAT_ACK; diff --git a/trunk/drivers/net/wireless/b43/Kconfig b/trunk/drivers/net/wireless/b43/Kconfig index 7a28d21ac389..3876c7ea54f4 100644 --- a/trunk/drivers/net/wireless/b43/Kconfig +++ b/trunk/drivers/net/wireless/b43/Kconfig @@ -34,8 +34,8 @@ config B43_BCMA config B43_BCMA_EXTRA bool "Hardware support that overlaps with the brcmsmac driver" depends on B43_BCMA - default n if BRCMSMAC - default y + default n if BRCMSMAC || BRCMSMAC_MODULE + default y config B43_SSB bool diff --git a/trunk/drivers/net/wireless/b43/main.c b/trunk/drivers/net/wireless/b43/main.c index a140165dfee0..b80352b308d5 100644 --- a/trunk/drivers/net/wireless/b43/main.c +++ b/trunk/drivers/net/wireless/b43/main.c @@ -2719,37 +2719,32 @@ static int b43_gpio_init(struct b43_wldev *dev) if (dev->dev->chip_id == 0x4301) { mask |= 0x0060; set |= 0x0060; - } else if (dev->dev->chip_id == 0x5354) { - /* Don't allow overtaking buttons GPIOs */ - set &= 0x2; /* 0x2 is LED GPIO on BCM5354 */ } - + if (dev->dev->chip_id == 0x5354) + set &= 0xff02; if (0 /* FIXME: conditional unknown */ ) { b43_write16(dev, B43_MMIO_GPIO_MASK, b43_read16(dev, B43_MMIO_GPIO_MASK) | 0x0100); - /* BT Coexistance Input */ - mask |= 0x0080; - set |= 0x0080; - /* BT Coexistance Out */ - mask |= 0x0100; - set |= 0x0100; + mask |= 0x0180; + set |= 0x0180; } if (dev->dev->bus_sprom->boardflags_lo & B43_BFL_PACTRL) { - /* PA is controlled by gpio 9, let ucode handle it */ b43_write16(dev, B43_MMIO_GPIO_MASK, b43_read16(dev, B43_MMIO_GPIO_MASK) | 0x0200); mask |= 0x0200; set |= 0x0200; } + if (dev->dev->core_rev >= 2) + mask |= 0x0010; /* FIXME: This is redundant. */ switch (dev->dev->bus_type) { #ifdef CONFIG_B43_BCMA case B43_BUS_BCMA: bcma_cc_write32(&dev->dev->bdev->bus->drv_cc, BCMA_CC_GPIOCTL, (bcma_cc_read32(&dev->dev->bdev->bus->drv_cc, - BCMA_CC_GPIOCTL) & ~mask) | set); + BCMA_CC_GPIOCTL) & mask) | set); break; #endif #ifdef CONFIG_B43_SSB @@ -2758,7 +2753,7 @@ static int b43_gpio_init(struct b43_wldev *dev) if (gpiodev) ssb_write32(gpiodev, B43_GPIO_CONTROL, (ssb_read32(gpiodev, B43_GPIO_CONTROL) - & ~mask) | set); + & mask) | set); break; #endif } diff --git a/trunk/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c b/trunk/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c index 7c4ee72f9d56..49765d34b4e0 100644 --- a/trunk/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c +++ b/trunk/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c @@ -638,8 +638,6 @@ static int brcmf_sdio_pd_probe(struct platform_device *pdev) oobirq_entry = kzalloc(sizeof(struct brcmf_sdio_oobirq), GFP_KERNEL); - if (!oobirq_entry) - return -ENOMEM; oobirq_entry->irq = res->start; oobirq_entry->flags = res->flags & IRQF_TRIGGER_MASK; list_add_tail(&oobirq_entry->list, &oobirq_lh); diff --git a/trunk/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c b/trunk/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c index 6f70953f0bad..2621dd3d7dcd 100644 --- a/trunk/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c +++ b/trunk/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c @@ -764,11 +764,8 @@ static void brcmf_c_arp_offload_set(struct brcmf_pub *drvr, int arp_mode) { char iovbuf[32]; int retcode; - __le32 arp_mode_le; - arp_mode_le = cpu_to_le32(arp_mode); - brcmf_c_mkiovar("arp_ol", (char *)&arp_mode_le, 4, iovbuf, - sizeof(iovbuf)); + brcmf_c_mkiovar("arp_ol", (char *)&arp_mode, 4, iovbuf, sizeof(iovbuf)); retcode = brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, iovbuf, sizeof(iovbuf)); retcode = retcode >= 0 ? 0 : retcode; @@ -784,11 +781,8 @@ static void brcmf_c_arp_offload_enable(struct brcmf_pub *drvr, int arp_enable) { char iovbuf[32]; int retcode; - __le32 arp_enable_le; - arp_enable_le = cpu_to_le32(arp_enable); - - brcmf_c_mkiovar("arpoe", (char *)&arp_enable_le, 4, + brcmf_c_mkiovar("arpoe", (char *)&arp_enable, 4, iovbuf, sizeof(iovbuf)); retcode = brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, iovbuf, sizeof(iovbuf)); @@ -806,10 +800,10 @@ int brcmf_c_preinit_dcmds(struct brcmf_pub *drvr) char iovbuf[BRCMF_EVENTING_MASK_LEN + 12]; /* Room for "event_msgs" + '\0' + bitvec */ char buf[128], *ptr; - __le32 roaming_le = cpu_to_le32(1); - __le32 bcn_timeout_le = cpu_to_le32(3); - __le32 scan_assoc_time_le = cpu_to_le32(40); - __le32 scan_unassoc_time_le = cpu_to_le32(40); + u32 roaming = 1; + uint bcn_timeout = 3; + int scan_assoc_time = 40; + int scan_unassoc_time = 40; int i; struct brcmf_bus_dcmd *cmdlst; struct list_head *cur, *q; @@ -835,14 +829,14 @@ int brcmf_c_preinit_dcmds(struct brcmf_pub *drvr) /* Setup timeout if Beacons are lost and roam is off to report link down */ - brcmf_c_mkiovar("bcn_timeout", (char *)&bcn_timeout_le, 4, iovbuf, + brcmf_c_mkiovar("bcn_timeout", (char *)&bcn_timeout, 4, iovbuf, sizeof(iovbuf)); brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, iovbuf, sizeof(iovbuf)); /* Enable/Disable build-in roaming to allowed ext supplicant to take of romaing */ - brcmf_c_mkiovar("roam_off", (char *)&roaming_le, 4, + brcmf_c_mkiovar("roam_off", (char *)&roaming, 4, iovbuf, sizeof(iovbuf)); brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, iovbuf, sizeof(iovbuf)); @@ -854,9 +848,9 @@ int brcmf_c_preinit_dcmds(struct brcmf_pub *drvr) sizeof(iovbuf)); brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_SCAN_CHANNEL_TIME, - (char *)&scan_assoc_time_le, sizeof(scan_assoc_time_le)); + (char *)&scan_assoc_time, sizeof(scan_assoc_time)); brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_SCAN_UNASSOC_TIME, - (char *)&scan_unassoc_time_le, sizeof(scan_unassoc_time_le)); + (char *)&scan_unassoc_time, sizeof(scan_unassoc_time)); /* Set and enable ARP offload feature */ brcmf_c_arp_offload_set(drvr, BRCMF_ARPOL_MODE); diff --git a/trunk/drivers/net/wireless/brcm80211/brcmfmac/usb.c b/trunk/drivers/net/wireless/brcm80211/brcmfmac/usb.c index 58f89fa9c9f8..a299d42da8e7 100644 --- a/trunk/drivers/net/wireless/brcm80211/brcmfmac/usb.c +++ b/trunk/drivers/net/wireless/brcm80211/brcmfmac/usb.c @@ -519,7 +519,7 @@ static void brcmf_usb_tx_complete(struct urb *urb) else devinfo->bus_pub.bus->dstats.tx_errors++; - brcmu_pkt_buf_free_skb(req->skb); + dev_kfree_skb(req->skb); req->skb = NULL; brcmf_usb_enq(devinfo, &devinfo->tx_freeq, req); @@ -540,7 +540,7 @@ static void brcmf_usb_rx_complete(struct urb *urb) devinfo->bus_pub.bus->dstats.rx_packets++; } else { devinfo->bus_pub.bus->dstats.rx_errors++; - brcmu_pkt_buf_free_skb(skb); + dev_kfree_skb(skb); brcmf_usb_enq(devinfo, &devinfo->rx_freeq, req); return; } @@ -550,15 +550,13 @@ static void brcmf_usb_rx_complete(struct urb *urb) if (brcmf_proto_hdrpull(devinfo->dev, &ifidx, skb) != 0) { brcmf_dbg(ERROR, "rx protocol error\n"); brcmu_pkt_buf_free_skb(skb); - brcmf_usb_enq(devinfo, &devinfo->rx_freeq, req); devinfo->bus_pub.bus->dstats.rx_errors++; } else { brcmf_rx_packet(devinfo->dev, ifidx, skb); brcmf_usb_rx_refill(devinfo, req); } } else { - brcmu_pkt_buf_free_skb(skb); - brcmf_usb_enq(devinfo, &devinfo->rx_freeq, req); + dev_kfree_skb(skb); } return; @@ -583,13 +581,14 @@ static void brcmf_usb_rx_refill(struct brcmf_usbdev_info *devinfo, usb_fill_bulk_urb(req->urb, devinfo->usbdev, devinfo->rx_pipe, skb->data, skb_tailroom(skb), brcmf_usb_rx_complete, req); + req->urb->transfer_flags |= URB_ZERO_PACKET; req->devinfo = devinfo; - brcmf_usb_enq(devinfo, &devinfo->rx_postq, req); ret = usb_submit_urb(req->urb, GFP_ATOMIC); - if (ret) { - brcmf_usb_del_fromq(devinfo, req); - brcmu_pkt_buf_free_skb(req->skb); + if (ret == 0) { + brcmf_usb_enq(devinfo, &devinfo->rx_postq, req); + } else { + dev_kfree_skb(req->skb); req->skb = NULL; brcmf_usb_enq(devinfo, &devinfo->rx_freeq, req); } @@ -684,22 +683,23 @@ static int brcmf_usb_tx(struct device *dev, struct sk_buff *skb) req = brcmf_usb_deq(devinfo, &devinfo->tx_freeq); if (!req) { - brcmu_pkt_buf_free_skb(skb); brcmf_dbg(ERROR, "no req to send\n"); return -ENOMEM; } + if (!req->urb) { + brcmf_dbg(ERROR, "no urb for req %p\n", req); + return -ENOBUFS; + } req->skb = skb; req->devinfo = devinfo; usb_fill_bulk_urb(req->urb, devinfo->usbdev, devinfo->tx_pipe, skb->data, skb->len, brcmf_usb_tx_complete, req); req->urb->transfer_flags |= URB_ZERO_PACKET; - brcmf_usb_enq(devinfo, &devinfo->tx_postq, req); ret = usb_submit_urb(req->urb, GFP_ATOMIC); - if (ret) { - brcmf_dbg(ERROR, "brcmf_usb_tx usb_submit_urb FAILED\n"); - brcmf_usb_del_fromq(devinfo, req); - brcmu_pkt_buf_free_skb(req->skb); + if (!ret) { + brcmf_usb_enq(devinfo, &devinfo->tx_postq, req); + } else { req->skb = NULL; brcmf_usb_enq(devinfo, &devinfo->tx_freeq, req); } diff --git a/trunk/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c b/trunk/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c index 50b5553b6964..28c5fbb4af26 100644 --- a/trunk/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c +++ b/trunk/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c @@ -500,10 +500,8 @@ static void wl_iscan_prep(struct brcmf_scan_params_le *params_le, params_le->active_time = cpu_to_le32(-1); params_le->passive_time = cpu_to_le32(-1); params_le->home_time = cpu_to_le32(-1); - if (ssid && ssid->SSID_len) { - params_le->ssid_le.SSID_len = cpu_to_le32(ssid->SSID_len); - memcpy(¶ms_le->ssid_le.SSID, ssid->SSID, ssid->SSID_len); - } + if (ssid && ssid->SSID_len) + memcpy(¶ms_le->ssid_le, ssid, sizeof(struct brcmf_ssid)); } static s32 @@ -1878,17 +1876,16 @@ brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev, } if (test_bit(WL_STATUS_CONNECTED, &cfg_priv->status)) { - memset(&scb_val, 0, sizeof(scb_val)); + scb_val.val = cpu_to_le32(0); err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_RSSI, &scb_val, sizeof(struct brcmf_scb_val_le)); - if (err) { + if (err) WL_ERR("Could not get rssi (%d)\n", err); - } else { - rssi = le32_to_cpu(scb_val.val); - sinfo->filled |= STATION_INFO_SIGNAL; - sinfo->signal = rssi; - WL_CONN("RSSI %d dBm\n", rssi); - } + + rssi = le32_to_cpu(scb_val.val); + sinfo->filled |= STATION_INFO_SIGNAL; + sinfo->signal = rssi; + WL_CONN("RSSI %d dBm\n", rssi); } done: diff --git a/trunk/drivers/net/wireless/brcm80211/brcmsmac/channel.c b/trunk/drivers/net/wireless/brcm80211/brcmsmac/channel.c index 64a48f06d68b..9a4c63f927cb 100644 --- a/trunk/drivers/net/wireless/brcm80211/brcmsmac/channel.c +++ b/trunk/drivers/net/wireless/brcm80211/brcmsmac/channel.c @@ -77,7 +77,7 @@ NL80211_RRF_NO_IBSS) static const struct ieee80211_regdomain brcms_regdom_x2 = { - .n_reg_rules = 6, + .n_reg_rules = 7, .alpha2 = "X2", .reg_rules = { BRCM_2GHZ_2412_2462, @@ -382,7 +382,9 @@ brcms_c_channel_set_chanspec(struct brcms_cm_info *wlc_cm, u16 chanspec, { struct brcms_c_info *wlc = wlc_cm->wlc; struct ieee80211_channel *ch = wlc->pub->ieee_hw->conf.channel; + const struct ieee80211_reg_rule *reg_rule; struct txpwr_limits txpwr; + int ret; brcms_c_channel_reg_limits(wlc_cm, chanspec, &txpwr); @@ -391,7 +393,8 @@ brcms_c_channel_set_chanspec(struct brcms_cm_info *wlc_cm, u16 chanspec, ); /* set or restore gmode as required by regulatory */ - if (ch->flags & IEEE80211_CHAN_NO_OFDM) + ret = freq_reg_info(wlc->wiphy, ch->center_freq, 0, ®_rule); + if (!ret && (reg_rule->flags & NL80211_RRF_NO_OFDM)) brcms_c_set_gmode(wlc, GMODE_LEGACY_B, false); else brcms_c_set_gmode(wlc, wlc->protection->gmode_user, false); diff --git a/trunk/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c b/trunk/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c index a5edebeb0b4f..9e79d47e077f 100644 --- a/trunk/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c +++ b/trunk/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c @@ -121,8 +121,7 @@ static struct ieee80211_channel brcms_2ghz_chantable[] = { IEEE80211_CHAN_NO_HT40PLUS), CHAN2GHZ(14, 2484, IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_IBSS | - IEEE80211_CHAN_NO_HT40PLUS | IEEE80211_CHAN_NO_HT40MINUS | - IEEE80211_CHAN_NO_OFDM) + IEEE80211_CHAN_NO_HT40PLUS | IEEE80211_CHAN_NO_HT40MINUS) }; static struct ieee80211_channel brcms_5ghz_nphy_chantable[] = { @@ -1233,9 +1232,6 @@ uint brcms_reset(struct brcms_info *wl) /* dpc will not be rescheduled */ wl->resched = false; - /* inform publicly that interface is down */ - wl->pub->up = false; - return 0; } diff --git a/trunk/drivers/net/wireless/ipw2x00/ipw2100.c b/trunk/drivers/net/wireless/ipw2x00/ipw2100.c index 83324b321652..95aa8e1683ec 100644 --- a/trunk/drivers/net/wireless/ipw2x00/ipw2100.c +++ b/trunk/drivers/net/wireless/ipw2x00/ipw2100.c @@ -2042,8 +2042,7 @@ static void isr_indicate_associated(struct ipw2100_priv *priv, u32 status) return; } len = ETH_ALEN; - ret = ipw2100_get_ordinal(priv, IPW_ORD_STAT_ASSN_AP_BSSID, bssid, - &len); + ipw2100_get_ordinal(priv, IPW_ORD_STAT_ASSN_AP_BSSID, &bssid, &len); if (ret) { IPW_DEBUG_INFO("failed querying ordinals at line %d\n", __LINE__); diff --git a/trunk/drivers/net/wireless/iwlegacy/common.h b/trunk/drivers/net/wireless/iwlegacy/common.h index 724682669060..5f5017767b99 100644 --- a/trunk/drivers/net/wireless/iwlegacy/common.h +++ b/trunk/drivers/net/wireless/iwlegacy/common.h @@ -1832,8 +1832,10 @@ int il_enqueue_hcmd(struct il_priv *il, struct il_host_cmd *cmd); static inline u16 il_pcie_link_ctl(struct il_priv *il) { + int pos; u16 pci_lnk_ctl; - pcie_capability_read_word(il->pci_dev, PCI_EXP_LNKCTL, &pci_lnk_ctl); + pos = pci_pcie_cap(il->pci_dev); + pci_read_config_word(il->pci_dev, pos + PCI_EXP_LNKCTL, &pci_lnk_ctl); return pci_lnk_ctl; } diff --git a/trunk/drivers/net/wireless/iwlwifi/dvm/debugfs.c b/trunk/drivers/net/wireless/iwlwifi/dvm/debugfs.c index a47b306b522c..46782f1102ac 100644 --- a/trunk/drivers/net/wireless/iwlwifi/dvm/debugfs.c +++ b/trunk/drivers/net/wireless/iwlwifi/dvm/debugfs.c @@ -124,9 +124,6 @@ static ssize_t iwl_dbgfs_sram_read(struct file *file, const struct fw_img *img; size_t bufsz; - if (!iwl_is_ready_rf(priv)) - return -EAGAIN; - /* default is to dump the entire data segment */ if (!priv->dbgfs_sram_offset && !priv->dbgfs_sram_len) { priv->dbgfs_sram_offset = 0x800000; diff --git a/trunk/drivers/net/wireless/iwlwifi/dvm/rs.c b/trunk/drivers/net/wireless/iwlwifi/dvm/rs.c index a82f46c10f5e..6fddd2785e6e 100644 --- a/trunk/drivers/net/wireless/iwlwifi/dvm/rs.c +++ b/trunk/drivers/net/wireless/iwlwifi/dvm/rs.c @@ -707,14 +707,11 @@ static int rs_toggle_antenna(u32 valid_ant, u32 *rate_n_flags, */ static bool rs_use_green(struct ieee80211_sta *sta) { - /* - * There's a bug somewhere in this code that causes the - * scaling to get stuck because GF+SGI can't be combined - * in SISO rates. Until we find that bug, disable GF, it - * has only limited benefit and we still interoperate with - * GF APs since we can always receive GF transmissions. - */ - return false; + struct iwl_station_priv *sta_priv = (void *)sta->drv_priv; + struct iwl_rxon_context *ctx = sta_priv->ctx; + + return (sta->ht_cap.cap & IEEE80211_HT_CAP_GRN_FLD) && + !(ctx->ht.non_gf_sta_present); } /** diff --git a/trunk/drivers/net/wireless/iwlwifi/pcie/internal.h b/trunk/drivers/net/wireless/iwlwifi/pcie/internal.h index 4ffc18dc3a57..d9694c58208c 100644 --- a/trunk/drivers/net/wireless/iwlwifi/pcie/internal.h +++ b/trunk/drivers/net/wireless/iwlwifi/pcie/internal.h @@ -350,7 +350,7 @@ int iwl_queue_space(const struct iwl_queue *q); /***************************************************** * Error handling ******************************************************/ -int iwl_dump_fh(struct iwl_trans *trans, char **buf); +int iwl_dump_fh(struct iwl_trans *trans, char **buf, bool display); void iwl_dump_csr(struct iwl_trans *trans); /***************************************************** diff --git a/trunk/drivers/net/wireless/iwlwifi/pcie/rx.c b/trunk/drivers/net/wireless/iwlwifi/pcie/rx.c index d1a61ba6247a..39a6ca1f009c 100644 --- a/trunk/drivers/net/wireless/iwlwifi/pcie/rx.c +++ b/trunk/drivers/net/wireless/iwlwifi/pcie/rx.c @@ -555,7 +555,7 @@ static void iwl_irq_handle_error(struct iwl_trans *trans) } iwl_dump_csr(trans); - iwl_dump_fh(trans, NULL); + iwl_dump_fh(trans, NULL, false); iwl_op_mode_nic_error(trans->op_mode); } diff --git a/trunk/drivers/net/wireless/iwlwifi/pcie/trans.c b/trunk/drivers/net/wireless/iwlwifi/pcie/trans.c index 063ecaff5b56..939c2f78df58 100644 --- a/trunk/drivers/net/wireless/iwlwifi/pcie/trans.c +++ b/trunk/drivers/net/wireless/iwlwifi/pcie/trans.c @@ -675,10 +675,13 @@ static void iwl_set_pwr_vmain(struct iwl_trans *trans) static u16 iwl_pciexp_link_ctrl(struct iwl_trans *trans) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); + int pos; u16 pci_lnk_ctl; - pcie_capability_read_word(trans_pcie->pci_dev, PCI_EXP_LNKCTL, - &pci_lnk_ctl); + struct pci_dev *pci_dev = trans_pcie->pci_dev; + + pos = pci_pcie_cap(pci_dev); + pci_read_config_word(pci_dev, pos + PCI_EXP_LNKCTL, &pci_lnk_ctl); return pci_lnk_ctl; } @@ -1439,7 +1442,6 @@ static int iwl_trans_pcie_start_hw(struct iwl_trans *trans) return err; err_free_irq: - trans_pcie->irq_requested = false; free_irq(trans_pcie->irq, trans); error: iwl_free_isr_ict(trans); @@ -1647,9 +1649,13 @@ static const char *get_fh_string(int cmd) #undef IWL_CMD } -int iwl_dump_fh(struct iwl_trans *trans, char **buf) +int iwl_dump_fh(struct iwl_trans *trans, char **buf, bool display) { int i; +#ifdef CONFIG_IWLWIFI_DEBUG + int pos = 0; + size_t bufsz = 0; +#endif static const u32 fh_tbl[] = { FH_RSCSR_CHNL0_STTS_WPTR_REG, FH_RSCSR_CHNL0_RBDCB_BASE_REG, @@ -1661,35 +1667,29 @@ int iwl_dump_fh(struct iwl_trans *trans, char **buf) FH_TSSR_TX_STATUS_REG, FH_TSSR_TX_ERROR_REG }; - -#ifdef CONFIG_IWLWIFI_DEBUGFS - if (buf) { - int pos = 0; - size_t bufsz = ARRAY_SIZE(fh_tbl) * 48 + 40; - +#ifdef CONFIG_IWLWIFI_DEBUG + if (display) { + bufsz = ARRAY_SIZE(fh_tbl) * 48 + 40; *buf = kmalloc(bufsz, GFP_KERNEL); if (!*buf) return -ENOMEM; - pos += scnprintf(*buf + pos, bufsz - pos, "FH register values:\n"); - - for (i = 0; i < ARRAY_SIZE(fh_tbl); i++) + for (i = 0; i < ARRAY_SIZE(fh_tbl); i++) { pos += scnprintf(*buf + pos, bufsz - pos, " %34s: 0X%08x\n", get_fh_string(fh_tbl[i]), iwl_read_direct32(trans, fh_tbl[i])); - + } return pos; } #endif - IWL_ERR(trans, "FH register values:\n"); - for (i = 0; i < ARRAY_SIZE(fh_tbl); i++) + for (i = 0; i < ARRAY_SIZE(fh_tbl); i++) { IWL_ERR(trans, " %34s: 0X%08x\n", get_fh_string(fh_tbl[i]), iwl_read_direct32(trans, fh_tbl[i])); - + } return 0; } @@ -1982,11 +1982,11 @@ static ssize_t iwl_dbgfs_fh_reg_read(struct file *file, size_t count, loff_t *ppos) { struct iwl_trans *trans = file->private_data; - char *buf = NULL; + char *buf; int pos = 0; ssize_t ret = -EFAULT; - ret = pos = iwl_dump_fh(trans, &buf); + ret = pos = iwl_dump_fh(trans, &buf, true); if (buf) { ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); diff --git a/trunk/drivers/net/wireless/libertas/cfg.c b/trunk/drivers/net/wireless/libertas/cfg.c index 1c10b542ab23..eb5de800ed90 100644 --- a/trunk/drivers/net/wireless/libertas/cfg.c +++ b/trunk/drivers/net/wireless/libertas/cfg.c @@ -1254,7 +1254,6 @@ static int lbs_associate(struct lbs_private *priv, netif_tx_wake_all_queues(priv->dev); } - kfree(cmd); done: lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret); return ret; diff --git a/trunk/drivers/net/wireless/libertas/if_sdio.c b/trunk/drivers/net/wireless/libertas/if_sdio.c index 4cb234349fbf..76caebaa4397 100644 --- a/trunk/drivers/net/wireless/libertas/if_sdio.c +++ b/trunk/drivers/net/wireless/libertas/if_sdio.c @@ -1314,7 +1314,6 @@ static void if_sdio_remove(struct sdio_func *func) kfree(packet); } - kfree(card); lbs_deb_leave(LBS_DEB_SDIO); } @@ -1326,11 +1325,6 @@ static int if_sdio_suspend(struct device *dev) mmc_pm_flag_t flags = sdio_get_host_pm_caps(func); - /* If we're powered off anyway, just let the mmc layer remove the - * card. */ - if (!lbs_iface_active(card->priv)) - return -ENOSYS; - dev_info(dev, "%s: suspend: PM flags = 0x%x\n", sdio_func_id(func), flags); diff --git a/trunk/drivers/net/wireless/libertas/main.c b/trunk/drivers/net/wireless/libertas/main.c index fe1ea43c5149..58048189bd24 100644 --- a/trunk/drivers/net/wireless/libertas/main.c +++ b/trunk/drivers/net/wireless/libertas/main.c @@ -571,10 +571,7 @@ static int lbs_thread(void *data) netdev_info(dev, "Timeout submitting command 0x%04x\n", le16_to_cpu(cmdnode->cmdbuf->command)); lbs_complete_command(priv, cmdnode, -ETIMEDOUT); - - /* Reset card, but only when it isn't in the process - * of being shutdown anyway. */ - if (!dev->dismantle && priv->reset_card) + if (priv->reset_card) priv->reset_card(priv); } priv->cmd_timed_out = 0; diff --git a/trunk/drivers/net/wireless/mwifiex/cmdevt.c b/trunk/drivers/net/wireless/mwifiex/cmdevt.c index 565527aee0ea..c68adec3cc8b 100644 --- a/trunk/drivers/net/wireless/mwifiex/cmdevt.c +++ b/trunk/drivers/net/wireless/mwifiex/cmdevt.c @@ -170,20 +170,7 @@ static int mwifiex_dnld_cmd_to_fw(struct mwifiex_private *priv, cmd_code = le16_to_cpu(host_cmd->command); cmd_size = le16_to_cpu(host_cmd->size); - /* Adjust skb length */ - if (cmd_node->cmd_skb->len > cmd_size) - /* - * cmd_size is less than sizeof(struct host_cmd_ds_command). - * Trim off the unused portion. - */ - skb_trim(cmd_node->cmd_skb, cmd_size); - else if (cmd_node->cmd_skb->len < cmd_size) - /* - * cmd_size is larger than sizeof(struct host_cmd_ds_command) - * because we have appended custom IE TLV. Increase skb length - * accordingly. - */ - skb_put(cmd_node->cmd_skb, cmd_size - cmd_node->cmd_skb->len); + skb_trim(cmd_node->cmd_skb, cmd_size); do_gettimeofday(&tstamp); dev_dbg(adapter->dev, "cmd: DNLD_CMD: (%lu.%lu): %#x, act %#x, len %d," diff --git a/trunk/drivers/net/wireless/p54/p54usb.c b/trunk/drivers/net/wireless/p54/p54usb.c index effb044a8a9d..7f207b6e9552 100644 --- a/trunk/drivers/net/wireless/p54/p54usb.c +++ b/trunk/drivers/net/wireless/p54/p54usb.c @@ -42,7 +42,7 @@ MODULE_FIRMWARE("isl3887usb"); * whenever you add a new device. */ -static struct usb_device_id p54u_table[] = { +static struct usb_device_id p54u_table[] __devinitdata = { /* Version 1 devices (pci chip + net2280) */ {USB_DEVICE(0x0411, 0x0050)}, /* Buffalo WLI2-USB2-G54 */ {USB_DEVICE(0x045e, 0x00c2)}, /* Microsoft MN-710 */ diff --git a/trunk/drivers/net/wireless/rndis_wlan.c b/trunk/drivers/net/wireless/rndis_wlan.c index 7a4ae9ee1c63..241162e8111d 100644 --- a/trunk/drivers/net/wireless/rndis_wlan.c +++ b/trunk/drivers/net/wireless/rndis_wlan.c @@ -1803,7 +1803,6 @@ static struct ndis_80211_pmkid *update_pmkid(struct usbnet *usbdev, struct cfg80211_pmksa *pmksa, int max_pmkids) { - struct ndis_80211_pmkid *new_pmkids; int i, err, newlen; unsigned int count; @@ -1834,12 +1833,11 @@ static struct ndis_80211_pmkid *update_pmkid(struct usbnet *usbdev, /* add new pmkid */ newlen = sizeof(*pmkids) + (count + 1) * sizeof(pmkids->bssid_info[0]); - new_pmkids = krealloc(pmkids, newlen, GFP_KERNEL); - if (!new_pmkids) { + pmkids = krealloc(pmkids, newlen, GFP_KERNEL); + if (!pmkids) { err = -ENOMEM; goto error; } - pmkids = new_pmkids; pmkids->length = cpu_to_le32(newlen); pmkids->bssid_info_count = cpu_to_le32(count + 1); diff --git a/trunk/drivers/net/wireless/rt2x00/rt2400pci.c b/trunk/drivers/net/wireless/rt2x00/rt2400pci.c index 64328af496f5..8b9dbd76a252 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/trunk/drivers/net/wireless/rt2x00/rt2400pci.c @@ -1611,7 +1611,6 @@ static int rt2400pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev) static int rt2400pci_probe_hw(struct rt2x00_dev *rt2x00dev) { int retval; - u32 reg; /* * Allocate eeprom data. @@ -1624,14 +1623,6 @@ static int rt2400pci_probe_hw(struct rt2x00_dev *rt2x00dev) if (retval) return retval; - /* - * Enable rfkill polling by setting GPIO direction of the - * rfkill switch GPIO pin correctly. - */ - rt2x00pci_register_read(rt2x00dev, GPIOCSR, ®); - rt2x00_set_field32(®, GPIOCSR_BIT8, 1); - rt2x00pci_register_write(rt2x00dev, GPIOCSR, reg); - /* * Initialize hw specifications. */ diff --git a/trunk/drivers/net/wireless/rt2x00/rt2400pci.h b/trunk/drivers/net/wireless/rt2x00/rt2400pci.h index 7564ae992b73..d3a4a68cc439 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt2400pci.h +++ b/trunk/drivers/net/wireless/rt2x00/rt2400pci.h @@ -670,7 +670,6 @@ #define GPIOCSR_BIT5 FIELD32(0x00000020) #define GPIOCSR_BIT6 FIELD32(0x00000040) #define GPIOCSR_BIT7 FIELD32(0x00000080) -#define GPIOCSR_BIT8 FIELD32(0x00000100) /* * BBPPCSR: BBP Pin control register. diff --git a/trunk/drivers/net/wireless/rt2x00/rt2500pci.c b/trunk/drivers/net/wireless/rt2x00/rt2500pci.c index 3de0406735f6..d2cf8a4bc8b5 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/trunk/drivers/net/wireless/rt2x00/rt2500pci.c @@ -1929,7 +1929,6 @@ static int rt2500pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev) static int rt2500pci_probe_hw(struct rt2x00_dev *rt2x00dev) { int retval; - u32 reg; /* * Allocate eeprom data. @@ -1942,14 +1941,6 @@ static int rt2500pci_probe_hw(struct rt2x00_dev *rt2x00dev) if (retval) return retval; - /* - * Enable rfkill polling by setting GPIO direction of the - * rfkill switch GPIO pin correctly. - */ - rt2x00pci_register_read(rt2x00dev, GPIOCSR, ®); - rt2x00_set_field32(®, GPIOCSR_DIR0, 1); - rt2x00pci_register_write(rt2x00dev, GPIOCSR, reg); - /* * Initialize hw specifications. */ diff --git a/trunk/drivers/net/wireless/rt2x00/rt2500usb.c b/trunk/drivers/net/wireless/rt2x00/rt2500usb.c index 89fee311d8fd..3aae36bb0a9e 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/trunk/drivers/net/wireless/rt2x00/rt2500usb.c @@ -283,7 +283,7 @@ static int rt2500usb_rfkill_poll(struct rt2x00_dev *rt2x00dev) u16 reg; rt2500usb_register_read(rt2x00dev, MAC_CSR19, ®); - return rt2x00_get_field16(reg, MAC_CSR19_BIT7); + return rt2x00_get_field32(reg, MAC_CSR19_BIT7); } #ifdef CONFIG_RT2X00_LIB_LEDS @@ -1768,7 +1768,6 @@ static int rt2500usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev) static int rt2500usb_probe_hw(struct rt2x00_dev *rt2x00dev) { int retval; - u16 reg; /* * Allocate eeprom data. @@ -1781,14 +1780,6 @@ static int rt2500usb_probe_hw(struct rt2x00_dev *rt2x00dev) if (retval) return retval; - /* - * Enable rfkill polling by setting GPIO direction of the - * rfkill switch GPIO pin correctly. - */ - rt2500usb_register_read(rt2x00dev, MAC_CSR19, ®); - rt2x00_set_field16(®, MAC_CSR19_BIT8, 0); - rt2500usb_register_write(rt2x00dev, MAC_CSR19, reg); - /* * Initialize hw specifications. */ diff --git a/trunk/drivers/net/wireless/rt2x00/rt2500usb.h b/trunk/drivers/net/wireless/rt2x00/rt2500usb.h index 196bd5103e4f..b493306a7eed 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt2500usb.h +++ b/trunk/drivers/net/wireless/rt2x00/rt2500usb.h @@ -189,15 +189,14 @@ * MAC_CSR19: GPIO control register. */ #define MAC_CSR19 0x0426 -#define MAC_CSR19_BIT0 FIELD16(0x0001) -#define MAC_CSR19_BIT1 FIELD16(0x0002) -#define MAC_CSR19_BIT2 FIELD16(0x0004) -#define MAC_CSR19_BIT3 FIELD16(0x0008) -#define MAC_CSR19_BIT4 FIELD16(0x0010) -#define MAC_CSR19_BIT5 FIELD16(0x0020) -#define MAC_CSR19_BIT6 FIELD16(0x0040) -#define MAC_CSR19_BIT7 FIELD16(0x0080) -#define MAC_CSR19_BIT8 FIELD16(0x0100) +#define MAC_CSR19_BIT0 FIELD32(0x0001) +#define MAC_CSR19_BIT1 FIELD32(0x0002) +#define MAC_CSR19_BIT2 FIELD32(0x0004) +#define MAC_CSR19_BIT3 FIELD32(0x0008) +#define MAC_CSR19_BIT4 FIELD32(0x0010) +#define MAC_CSR19_BIT5 FIELD32(0x0020) +#define MAC_CSR19_BIT6 FIELD32(0x0040) +#define MAC_CSR19_BIT7 FIELD32(0x0080) /* * MAC_CSR20: LED control register. diff --git a/trunk/drivers/net/wireless/rt2x00/rt2800lib.c b/trunk/drivers/net/wireless/rt2x00/rt2800lib.c index b93516d832fb..88455b1b9fe0 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/trunk/drivers/net/wireless/rt2x00/rt2800lib.c @@ -221,67 +221,6 @@ static void rt2800_rf_write(struct rt2x00_dev *rt2x00dev, mutex_unlock(&rt2x00dev->csr_mutex); } -static int rt2800_enable_wlan_rt3290(struct rt2x00_dev *rt2x00dev) -{ - u32 reg; - int i, count; - - rt2800_register_read(rt2x00dev, WLAN_FUN_CTRL, ®); - if (rt2x00_get_field32(reg, WLAN_EN)) - return 0; - - rt2x00_set_field32(®, WLAN_GPIO_OUT_OE_BIT_ALL, 0xff); - rt2x00_set_field32(®, FRC_WL_ANT_SET, 1); - rt2x00_set_field32(®, WLAN_CLK_EN, 0); - rt2x00_set_field32(®, WLAN_EN, 1); - rt2800_register_write(rt2x00dev, WLAN_FUN_CTRL, reg); - - udelay(REGISTER_BUSY_DELAY); - - count = 0; - do { - /* - * Check PLL_LD & XTAL_RDY. - */ - for (i = 0; i < REGISTER_BUSY_COUNT; i++) { - rt2800_register_read(rt2x00dev, CMB_CTRL, ®); - if (rt2x00_get_field32(reg, PLL_LD) && - rt2x00_get_field32(reg, XTAL_RDY)) - break; - udelay(REGISTER_BUSY_DELAY); - } - - if (i >= REGISTER_BUSY_COUNT) { - - if (count >= 10) - return -EIO; - - rt2800_register_write(rt2x00dev, 0x58, 0x018); - udelay(REGISTER_BUSY_DELAY); - rt2800_register_write(rt2x00dev, 0x58, 0x418); - udelay(REGISTER_BUSY_DELAY); - rt2800_register_write(rt2x00dev, 0x58, 0x618); - udelay(REGISTER_BUSY_DELAY); - count++; - } else { - count = 0; - } - - rt2800_register_read(rt2x00dev, WLAN_FUN_CTRL, ®); - rt2x00_set_field32(®, PCIE_APP0_CLK_REQ, 0); - rt2x00_set_field32(®, WLAN_CLK_EN, 1); - rt2x00_set_field32(®, WLAN_RESET, 1); - rt2800_register_write(rt2x00dev, WLAN_FUN_CTRL, reg); - udelay(10); - rt2x00_set_field32(®, WLAN_RESET, 0); - rt2800_register_write(rt2x00dev, WLAN_FUN_CTRL, reg); - udelay(10); - rt2800_register_write(rt2x00dev, INT_SOURCE_CSR, 0x7fffffff); - } while (count != 0); - - return 0; -} - void rt2800_mcu_request(struct rt2x00_dev *rt2x00dev, const u8 command, const u8 token, const u8 arg0, const u8 arg1) @@ -461,13 +400,6 @@ int rt2800_load_firmware(struct rt2x00_dev *rt2x00dev, { unsigned int i; u32 reg; - int retval; - - if (rt2x00_rt(rt2x00dev, RT3290)) { - retval = rt2800_enable_wlan_rt3290(rt2x00dev); - if (retval) - return -EBUSY; - } /* * If driver doesn't wake up firmware here, @@ -4089,7 +4021,6 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) rt2800_register_write(rt2x00dev, LDO_CFG0, reg); msleep(1); rt2800_register_read(rt2x00dev, LDO_CFG0, ®); - rt2x00_set_field32(®, LDO_CFG0_LDO_CORE_VLEVEL, 0); rt2x00_set_field32(®, LDO_CFG0_BGSEL, 1); rt2800_register_write(rt2x00dev, LDO_CFG0, reg); } diff --git a/trunk/drivers/net/wireless/rt2x00/rt2800pci.c b/trunk/drivers/net/wireless/rt2x00/rt2800pci.c index 4765bbd654cd..235376e9cb04 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/trunk/drivers/net/wireless/rt2x00/rt2800pci.c @@ -980,10 +980,69 @@ static int rt2800pci_validate_eeprom(struct rt2x00_dev *rt2x00dev) return rt2800_validate_eeprom(rt2x00dev); } +static int rt2800_enable_wlan_rt3290(struct rt2x00_dev *rt2x00dev) +{ + u32 reg; + int i, count; + + rt2800_register_read(rt2x00dev, WLAN_FUN_CTRL, ®); + if (rt2x00_get_field32(reg, WLAN_EN)) + return 0; + + rt2x00_set_field32(®, WLAN_GPIO_OUT_OE_BIT_ALL, 0xff); + rt2x00_set_field32(®, FRC_WL_ANT_SET, 1); + rt2x00_set_field32(®, WLAN_CLK_EN, 0); + rt2x00_set_field32(®, WLAN_EN, 1); + rt2800_register_write(rt2x00dev, WLAN_FUN_CTRL, reg); + + udelay(REGISTER_BUSY_DELAY); + + count = 0; + do { + /* + * Check PLL_LD & XTAL_RDY. + */ + for (i = 0; i < REGISTER_BUSY_COUNT; i++) { + rt2800_register_read(rt2x00dev, CMB_CTRL, ®); + if (rt2x00_get_field32(reg, PLL_LD) && + rt2x00_get_field32(reg, XTAL_RDY)) + break; + udelay(REGISTER_BUSY_DELAY); + } + + if (i >= REGISTER_BUSY_COUNT) { + + if (count >= 10) + return -EIO; + + rt2800_register_write(rt2x00dev, 0x58, 0x018); + udelay(REGISTER_BUSY_DELAY); + rt2800_register_write(rt2x00dev, 0x58, 0x418); + udelay(REGISTER_BUSY_DELAY); + rt2800_register_write(rt2x00dev, 0x58, 0x618); + udelay(REGISTER_BUSY_DELAY); + count++; + } else { + count = 0; + } + + rt2800_register_read(rt2x00dev, WLAN_FUN_CTRL, ®); + rt2x00_set_field32(®, PCIE_APP0_CLK_REQ, 0); + rt2x00_set_field32(®, WLAN_CLK_EN, 1); + rt2x00_set_field32(®, WLAN_RESET, 1); + rt2800_register_write(rt2x00dev, WLAN_FUN_CTRL, reg); + udelay(10); + rt2x00_set_field32(®, WLAN_RESET, 0); + rt2800_register_write(rt2x00dev, WLAN_FUN_CTRL, reg); + udelay(10); + rt2800_register_write(rt2x00dev, INT_SOURCE_CSR, 0x7fffffff); + } while (count != 0); + + return 0; +} static int rt2800pci_probe_hw(struct rt2x00_dev *rt2x00dev) { int retval; - u32 reg; /* * Allocate eeprom data. @@ -996,14 +1055,6 @@ static int rt2800pci_probe_hw(struct rt2x00_dev *rt2x00dev) if (retval) return retval; - /* - * Enable rfkill polling by setting GPIO direction of the - * rfkill switch GPIO pin correctly. - */ - rt2x00pci_register_read(rt2x00dev, GPIO_CTRL_CFG, ®); - rt2x00_set_field32(®, GPIO_CTRL_CFG_GPIOD_BIT2, 1); - rt2x00pci_register_write(rt2x00dev, GPIO_CTRL_CFG, reg); - /* * Initialize hw specifications. */ @@ -1011,6 +1062,17 @@ static int rt2800pci_probe_hw(struct rt2x00_dev *rt2x00dev) if (retval) return retval; + /* + * In probe phase call rt2800_enable_wlan_rt3290 to enable wlan + * clk for rt3290. That avoid the MCU fail in start phase. + */ + if (rt2x00_rt(rt2x00dev, RT3290)) { + retval = rt2800_enable_wlan_rt3290(rt2x00dev); + + if (retval) + return retval; + } + /* * This device has multiple filters for control frames * and has a separate filter for PS Poll frames. diff --git a/trunk/drivers/net/wireless/rt2x00/rt2800usb.c b/trunk/drivers/net/wireless/rt2x00/rt2800usb.c index 6b4226b71618..6cf336595e25 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/trunk/drivers/net/wireless/rt2x00/rt2800usb.c @@ -667,16 +667,8 @@ static void rt2800usb_fill_rxdone(struct queue_entry *entry, skb_pull(entry->skb, RXINFO_DESC_SIZE); /* - * Check for rx_pkt_len validity. Return if invalid, leaving - * rxdesc->size zeroed out by the upper level. + * FIXME: we need to check for rx_pkt_len validity */ - if (unlikely(rx_pkt_len == 0 || - rx_pkt_len > entry->queue->data_size)) { - ERROR(entry->queue->rt2x00dev, - "Bad frame size %d, forcing to 0\n", rx_pkt_len); - return; - } - rxd = (__le32 *)(entry->skb->data + rx_pkt_len); /* @@ -744,7 +736,6 @@ static int rt2800usb_validate_eeprom(struct rt2x00_dev *rt2x00dev) static int rt2800usb_probe_hw(struct rt2x00_dev *rt2x00dev) { int retval; - u32 reg; /* * Allocate eeprom data. @@ -757,14 +748,6 @@ static int rt2800usb_probe_hw(struct rt2x00_dev *rt2x00dev) if (retval) return retval; - /* - * Enable rfkill polling by setting GPIO direction of the - * rfkill switch GPIO pin correctly. - */ - rt2x00usb_register_read(rt2x00dev, GPIO_CTRL_CFG, ®); - rt2x00_set_field32(®, GPIO_CTRL_CFG_GPIOD_BIT2, 1); - rt2x00usb_register_write(rt2x00dev, GPIO_CTRL_CFG, reg); - /* * Initialize hw specifications. */ @@ -1174,8 +1157,6 @@ static struct usb_device_id rt2800usb_device_table[] = { { USB_DEVICE(0x1690, 0x0744) }, { USB_DEVICE(0x1690, 0x0761) }, { USB_DEVICE(0x1690, 0x0764) }, - /* ASUS */ - { USB_DEVICE(0x0b05, 0x179d) }, /* Cisco */ { USB_DEVICE(0x167b, 0x4001) }, /* EnGenius */ @@ -1241,6 +1222,7 @@ static struct usb_device_id rt2800usb_device_table[] = { { USB_DEVICE(0x0b05, 0x1760) }, { USB_DEVICE(0x0b05, 0x1761) }, { USB_DEVICE(0x0b05, 0x1790) }, + { USB_DEVICE(0x0b05, 0x179d) }, /* AzureWave */ { USB_DEVICE(0x13d3, 0x3262) }, { USB_DEVICE(0x13d3, 0x3284) }, diff --git a/trunk/drivers/net/wireless/rt2x00/rt2x00dev.c b/trunk/drivers/net/wireless/rt2x00/rt2x00dev.c index 3f07e36f462b..a6b88bd4a1a5 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/trunk/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -629,7 +629,7 @@ void rt2x00lib_rxdone(struct queue_entry *entry, gfp_t gfp) */ if (unlikely(rxdesc.size == 0 || rxdesc.size > entry->queue->data_size)) { - ERROR(rt2x00dev, "Wrong frame size %d max %d.\n", + WARNING(rt2x00dev, "Wrong frame size %d max %d.\n", rxdesc.size, entry->queue->data_size); dev_kfree_skb(entry->skb); goto renew_skb; diff --git a/trunk/drivers/net/wireless/rt2x00/rt61pci.c b/trunk/drivers/net/wireless/rt2x00/rt61pci.c index b8ec96163922..f32259686b45 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt61pci.c +++ b/trunk/drivers/net/wireless/rt2x00/rt61pci.c @@ -2243,7 +2243,8 @@ static void rt61pci_txdone(struct rt2x00_dev *rt2x00dev) static void rt61pci_wakeup(struct rt2x00_dev *rt2x00dev) { - struct rt2x00lib_conf libconf = { .conf = &rt2x00dev->hw->conf }; + struct ieee80211_conf conf = { .flags = 0 }; + struct rt2x00lib_conf libconf = { .conf = &conf }; rt61pci_config(rt2x00dev, &libconf, IEEE80211_CONF_CHANGE_PS); } @@ -2832,7 +2833,6 @@ static int rt61pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev) static int rt61pci_probe_hw(struct rt2x00_dev *rt2x00dev) { int retval; - u32 reg; /* * Disable power saving. @@ -2850,14 +2850,6 @@ static int rt61pci_probe_hw(struct rt2x00_dev *rt2x00dev) if (retval) return retval; - /* - * Enable rfkill polling by setting GPIO direction of the - * rfkill switch GPIO pin correctly. - */ - rt2x00pci_register_read(rt2x00dev, MAC_CSR13, ®); - rt2x00_set_field32(®, MAC_CSR13_BIT13, 1); - rt2x00pci_register_write(rt2x00dev, MAC_CSR13, reg); - /* * Initialize hw specifications. */ diff --git a/trunk/drivers/net/wireless/rt2x00/rt61pci.h b/trunk/drivers/net/wireless/rt2x00/rt61pci.h index 8f3da5a56766..e3cd6db76b0e 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt61pci.h +++ b/trunk/drivers/net/wireless/rt2x00/rt61pci.h @@ -372,7 +372,6 @@ struct hw_pairwise_ta_entry { #define MAC_CSR13_BIT10 FIELD32(0x00000400) #define MAC_CSR13_BIT11 FIELD32(0x00000800) #define MAC_CSR13_BIT12 FIELD32(0x00001000) -#define MAC_CSR13_BIT13 FIELD32(0x00002000) /* * MAC_CSR14: LED control register. diff --git a/trunk/drivers/net/wireless/rt2x00/rt73usb.c b/trunk/drivers/net/wireless/rt2x00/rt73usb.c index 248436c13ce0..ba6e434b859d 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt73usb.c +++ b/trunk/drivers/net/wireless/rt2x00/rt73usb.c @@ -2177,7 +2177,6 @@ static int rt73usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev) static int rt73usb_probe_hw(struct rt2x00_dev *rt2x00dev) { int retval; - u32 reg; /* * Allocate eeprom data. @@ -2190,14 +2189,6 @@ static int rt73usb_probe_hw(struct rt2x00_dev *rt2x00dev) if (retval) return retval; - /* - * Enable rfkill polling by setting GPIO direction of the - * rfkill switch GPIO pin correctly. - */ - rt2x00usb_register_read(rt2x00dev, MAC_CSR13, ®); - rt2x00_set_field32(®, MAC_CSR13_BIT15, 0); - rt2x00usb_register_write(rt2x00dev, MAC_CSR13, reg); - /* * Initialize hw specifications. */ diff --git a/trunk/drivers/net/wireless/rt2x00/rt73usb.h b/trunk/drivers/net/wireless/rt2x00/rt73usb.h index df1cc116b83b..9f6b470414d3 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt73usb.h +++ b/trunk/drivers/net/wireless/rt2x00/rt73usb.h @@ -282,9 +282,6 @@ struct hw_pairwise_ta_entry { #define MAC_CSR13_BIT10 FIELD32(0x00000400) #define MAC_CSR13_BIT11 FIELD32(0x00000800) #define MAC_CSR13_BIT12 FIELD32(0x00001000) -#define MAC_CSR13_BIT13 FIELD32(0x00002000) -#define MAC_CSR13_BIT14 FIELD32(0x00004000) -#define MAC_CSR13_BIT15 FIELD32(0x00008000) /* * MAC_CSR14: LED control register. diff --git a/trunk/drivers/net/wireless/rtl818x/rtl8187/dev.c b/trunk/drivers/net/wireless/rtl818x/rtl8187/dev.c index 533024095c43..71a30b026089 100644 --- a/trunk/drivers/net/wireless/rtl818x/rtl8187/dev.c +++ b/trunk/drivers/net/wireless/rtl818x/rtl8187/dev.c @@ -44,7 +44,7 @@ MODULE_AUTHOR("Larry Finger "); MODULE_DESCRIPTION("RTL8187/RTL8187B USB wireless driver"); MODULE_LICENSE("GPL"); -static struct usb_device_id rtl8187_table[] = { +static struct usb_device_id rtl8187_table[] __devinitdata = { /* Asus */ {USB_DEVICE(0x0b05, 0x171d), .driver_info = DEVICE_RTL8187}, /* Belkin */ diff --git a/trunk/drivers/net/wireless/rtlwifi/pci.c b/trunk/drivers/net/wireless/rtlwifi/pci.c index 5983631a1b1a..80f75d3ba84a 100644 --- a/trunk/drivers/net/wireless/rtlwifi/pci.c +++ b/trunk/drivers/net/wireless/rtlwifi/pci.c @@ -372,11 +372,13 @@ static void rtl_pci_parse_configuration(struct pci_dev *pdev, struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); u8 tmp; - u16 linkctrl_reg; + int pos; + u8 linkctrl_reg; /*Link Control Register */ - pcie_capability_read_word(pdev, PCI_EXP_LNKCTL, &linkctrl_reg); - pcipriv->ndis_adapter.linkctrl_reg = (u8)linkctrl_reg; + pos = pci_pcie_cap(pdev); + pci_read_config_byte(pdev, pos + PCI_EXP_LNKCTL, &linkctrl_reg); + pcipriv->ndis_adapter.linkctrl_reg = linkctrl_reg; RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "Link Control Register =%x\n", pcipriv->ndis_adapter.linkctrl_reg); diff --git a/trunk/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c b/trunk/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c index 8a7b864faca3..44febfde9493 100644 --- a/trunk/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c +++ b/trunk/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c @@ -315,7 +315,7 @@ static void _rtl92c_fill_h2c_command(struct ieee80211_hw *hw, u16 box_reg = 0, box_extreg = 0; u8 u1b_tmp; bool isfw_read = false; - bool bwrite_success = false; + bool bwrite_sucess = false; u8 wait_h2c_limmit = 100; u8 wait_writeh2c_limmit = 100; u8 boxcontent[4], boxextcontent[2]; @@ -354,7 +354,7 @@ static void _rtl92c_fill_h2c_command(struct ieee80211_hw *hw, } } - while (!bwrite_success) { + while (!bwrite_sucess) { wait_writeh2c_limmit--; if (wait_writeh2c_limmit == 0) { RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, @@ -491,7 +491,7 @@ static void _rtl92c_fill_h2c_command(struct ieee80211_hw *hw, break; } - bwrite_success = true; + bwrite_sucess = true; rtlhal->last_hmeboxnum = boxnum + 1; if (rtlhal->last_hmeboxnum == 4) diff --git a/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/def.h b/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/def.h index 2925094b2d91..04c3aef8a4f6 100644 --- a/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/def.h +++ b/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/def.h @@ -117,7 +117,6 @@ #define CHIP_VER_B BIT(4) #define CHIP_92C_BITMASK BIT(0) -#define CHIP_UNKNOWN BIT(7) #define CHIP_92C_1T2R 0x03 #define CHIP_92C 0x01 #define CHIP_88C 0x00 diff --git a/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c b/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c index dd4bb0950a57..bd0da7ef290b 100644 --- a/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c +++ b/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c @@ -994,16 +994,8 @@ static enum version_8192c _rtl92ce_read_chip_version(struct ieee80211_hw *hw) version = (value32 & TYPE_ID) ? VERSION_A_CHIP_92C : VERSION_A_CHIP_88C; } else { - version = (enum version_8192c) (CHIP_VER_B | - ((value32 & TYPE_ID) ? CHIP_92C_BITMASK : 0) | - ((value32 & VENDOR_ID) ? CHIP_VENDOR_UMC : 0)); - if ((!IS_CHIP_VENDOR_UMC(version)) && (value32 & - CHIP_VER_RTL_MASK)) { - version = (enum version_8192c)(version | - ((((value32 & CHIP_VER_RTL_MASK) == BIT(12)) - ? CHIP_VENDOR_UMC_B_CUT : CHIP_UNKNOWN) | - CHIP_VENDOR_UMC)); - } + version = (value32 & TYPE_ID) ? VERSION_B_CHIP_92C : + VERSION_B_CHIP_88C; } switch (version) { diff --git a/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c b/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c index 7d8f96405f42..3aa927f8b9b9 100644 --- a/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c +++ b/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c @@ -162,12 +162,10 @@ int rtl92c_init_sw_vars(struct ieee80211_hw *hw) /* request fw */ if (IS_VENDOR_UMC_A_CUT(rtlhal->version) && - !IS_92C_SERIAL(rtlhal->version)) { + !IS_92C_SERIAL(rtlhal->version)) rtlpriv->cfg->fw_name = "rtlwifi/rtl8192cfwU.bin"; - } else if (IS_81xxC_VENDOR_UMC_B_CUT(rtlhal->version)) { + else if (IS_81xxC_VENDOR_UMC_B_CUT(rtlhal->version)) rtlpriv->cfg->fw_name = "rtlwifi/rtl8192cfwU_B.bin"; - pr_info("****** This B_CUT device may not work with kernels 3.6 and earlier\n"); - } rtlpriv->max_fw_size = 0x4000; pr_info("Using firmware %s\n", rtlpriv->cfg->fw_name); diff --git a/trunk/drivers/net/wireless/rtlwifi/rtl8192de/fw.c b/trunk/drivers/net/wireless/rtlwifi/rtl8192de/fw.c index eb22dccc418b..895ae6c1f354 100644 --- a/trunk/drivers/net/wireless/rtlwifi/rtl8192de/fw.c +++ b/trunk/drivers/net/wireless/rtlwifi/rtl8192de/fw.c @@ -365,7 +365,7 @@ static void _rtl92d_fill_h2c_command(struct ieee80211_hw *hw, u8 u1b_tmp; bool isfw_read = false; u8 buf_index = 0; - bool bwrite_success = false; + bool bwrite_sucess = false; u8 wait_h2c_limmit = 100; u8 wait_writeh2c_limmit = 100; u8 boxcontent[4], boxextcontent[2]; @@ -408,7 +408,7 @@ static void _rtl92d_fill_h2c_command(struct ieee80211_hw *hw, break; } } - while (!bwrite_success) { + while (!bwrite_sucess) { wait_writeh2c_limmit--; if (wait_writeh2c_limmit == 0) { RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, @@ -515,7 +515,7 @@ static void _rtl92d_fill_h2c_command(struct ieee80211_hw *hw, "switch case not processed\n"); break; } - bwrite_success = true; + bwrite_sucess = true; rtlhal->last_hmeboxnum = boxnum + 1; if (rtlhal->last_hmeboxnum == 4) rtlhal->last_hmeboxnum = 0; diff --git a/trunk/drivers/net/xen-netfront.c b/trunk/drivers/net/xen-netfront.c index 650f79a1f2bd..30899901aef5 100644 --- a/trunk/drivers/net/xen-netfront.c +++ b/trunk/drivers/net/xen-netfront.c @@ -57,7 +57,8 @@ static const struct ethtool_ops xennet_ethtool_ops; struct netfront_cb { - int pull_to; + struct page *page; + unsigned offset; }; #define NETFRONT_SKB_CB(skb) ((struct netfront_cb *)((skb)->cb)) @@ -866,9 +867,15 @@ static int handle_incoming_queue(struct net_device *dev, struct sk_buff *skb; while ((skb = __skb_dequeue(rxq)) != NULL) { - int pull_to = NETFRONT_SKB_CB(skb)->pull_to; + struct page *page = NETFRONT_SKB_CB(skb)->page; + void *vaddr = page_address(page); + unsigned offset = NETFRONT_SKB_CB(skb)->offset; + + memcpy(skb->data, vaddr + offset, + skb_headlen(skb)); - __pskb_pull_tail(skb, pull_to - skb_headlen(skb)); + if (page != skb_frag_page(&skb_shinfo(skb)->frags[0])) + __free_page(page); /* Ethernet work: Delayed to here as it peeks the header. */ skb->protocol = eth_type_trans(skb, dev); @@ -906,6 +913,7 @@ static int xennet_poll(struct napi_struct *napi, int budget) struct sk_buff_head errq; struct sk_buff_head tmpq; unsigned long flags; + unsigned int len; int err; spin_lock(&np->rx_lock); @@ -947,13 +955,24 @@ static int xennet_poll(struct napi_struct *napi, int budget) } } - NETFRONT_SKB_CB(skb)->pull_to = rx->status; - if (NETFRONT_SKB_CB(skb)->pull_to > RX_COPY_THRESHOLD) - NETFRONT_SKB_CB(skb)->pull_to = RX_COPY_THRESHOLD; + NETFRONT_SKB_CB(skb)->page = + skb_frag_page(&skb_shinfo(skb)->frags[0]); + NETFRONT_SKB_CB(skb)->offset = rx->offset; + + len = rx->status; + if (len > RX_COPY_THRESHOLD) + len = RX_COPY_THRESHOLD; + skb_put(skb, len); - skb_shinfo(skb)->frags[0].page_offset = rx->offset; - skb_frag_size_set(&skb_shinfo(skb)->frags[0], rx->status); - skb->data_len = rx->status; + if (rx->status > len) { + skb_shinfo(skb)->frags[0].page_offset = + rx->offset + len; + skb_frag_size_set(&skb_shinfo(skb)->frags[0], rx->status - len); + skb->data_len = rx->status - len; + } else { + __skb_fill_page_desc(skb, 0, NULL, 0, 0); + skb_shinfo(skb)->nr_frags = 0; + } i = xennet_fill_frags(np, skb, &tmpq); @@ -980,7 +999,7 @@ static int xennet_poll(struct napi_struct *napi, int budget) * receive throughout using the standard receive * buffer size was cut by 25%(!!!). */ - skb->truesize += skb->data_len - RX_COPY_THRESHOLD; + skb->truesize += skb->data_len - (RX_COPY_THRESHOLD - len); skb->len += skb->data_len; if (rx->flags & XEN_NETRXF_csum_blank) diff --git a/trunk/drivers/of/base.c b/trunk/drivers/of/base.c index d4a1c9a043e1..c181b94abc36 100644 --- a/trunk/drivers/of/base.c +++ b/trunk/drivers/of/base.c @@ -363,33 +363,6 @@ struct device_node *of_get_next_child(const struct device_node *node, } EXPORT_SYMBOL(of_get_next_child); -/** - * of_get_next_available_child - Find the next available child node - * @node: parent node - * @prev: previous child of the parent node, or NULL to get first - * - * This function is like of_get_next_child(), except that it - * automatically skips any disabled nodes (i.e. status = "disabled"). - */ -struct device_node *of_get_next_available_child(const struct device_node *node, - struct device_node *prev) -{ - struct device_node *next; - - read_lock(&devtree_lock); - next = prev ? prev->sibling : node->child; - for (; next; next = next->sibling) { - if (!of_device_is_available(next)) - continue; - if (of_node_get(next)) - break; - } - of_node_put(prev); - read_unlock(&devtree_lock); - return next; -} -EXPORT_SYMBOL(of_get_next_available_child); - /** * of_find_node_by_path - Find a node matching a full OF path * @path: The full path to match diff --git a/trunk/drivers/oprofile/cpu_buffer.c b/trunk/drivers/oprofile/cpu_buffer.c index 8aa73fac6ad4..b8ef8ddcc292 100644 --- a/trunk/drivers/oprofile/cpu_buffer.c +++ b/trunk/drivers/oprofile/cpu_buffer.c @@ -451,9 +451,14 @@ static void wq_sync_buffer(struct work_struct *work) { struct oprofile_cpu_buffer *b = container_of(work, struct oprofile_cpu_buffer, work.work); - if (b->cpu != smp_processor_id() && !cpu_online(b->cpu)) { - cancel_delayed_work(&b->work); - return; + if (b->cpu != smp_processor_id()) { + printk(KERN_DEBUG "WQ on CPU%d, prefer CPU%d\n", + smp_processor_id(), b->cpu); + + if (!cpu_online(b->cpu)) { + cancel_delayed_work(&b->work); + return; + } } sync_buffer(b->cpu); diff --git a/trunk/drivers/parisc/dino.c b/trunk/drivers/parisc/dino.c index fb6a1fe21b93..ffddc4f64268 100644 --- a/trunk/drivers/parisc/dino.c +++ b/trunk/drivers/parisc/dino.c @@ -477,12 +477,14 @@ dino_card_setup(struct pci_bus *bus, void __iomem *base_addr) if (ccio_allocate_resource(dino_dev->hba.dev, res, _8MB, F_EXTEND(0xf0000000UL) | _8MB, F_EXTEND(0xffffffffUL) &~ _8MB, _8MB) < 0) { - struct pci_dev *dev, *tmp; + struct list_head *ln, *tmp_ln; printk(KERN_ERR "Dino: cannot attach bus %s\n", dev_name(bus->bridge)); /* kill the bus, we can't do anything with it */ - list_for_each_entry_safe(dev, tmp, &bus->devices, bus_list) { + list_for_each_safe(ln, tmp_ln, &bus->devices) { + struct pci_dev *dev = pci_dev_b(ln); + list_del(&dev->bus_list); } @@ -547,6 +549,7 @@ dino_card_fixup(struct pci_dev *dev) static void __init dino_fixup_bus(struct pci_bus *bus) { + struct list_head *ln; struct pci_dev *dev; struct dino_device *dino_dev = DINO_DEV(parisc_walk_tree(bus->bridge)); @@ -593,7 +596,8 @@ dino_fixup_bus(struct pci_bus *bus) } - list_for_each_entry(dev, &bus->devices, bus_list) { + list_for_each(ln, &bus->devices) { + dev = pci_dev_b(ln); if (is_card_dino(&dino_dev->hba.dev->id)) dino_card_fixup(dev); diff --git a/trunk/drivers/parisc/lba_pci.c b/trunk/drivers/parisc/lba_pci.c index fdd63a6a62d6..4f9cf2456f4e 100644 --- a/trunk/drivers/parisc/lba_pci.c +++ b/trunk/drivers/parisc/lba_pci.c @@ -629,7 +629,7 @@ truncate_pat_collision(struct resource *root, struct resource *new) static void lba_fixup_bus(struct pci_bus *bus) { - struct pci_dev *dev; + struct list_head *ln; #ifdef FBB_SUPPORT u16 status; #endif @@ -710,8 +710,9 @@ lba_fixup_bus(struct pci_bus *bus) } - list_for_each_entry(dev, &bus->devices, bus_list) { + list_for_each(ln, &bus->devices) { int i; + struct pci_dev *dev = pci_dev_b(ln); DBG("lba_fixup_bus() %s\n", pci_name(dev)); @@ -769,7 +770,7 @@ lba_fixup_bus(struct pci_bus *bus) } /* Lastly enable FBB/PERR/SERR on all devices too */ - list_for_each_entry(dev, &bus->devices, bus_list) { + list_for_each(ln, &bus->devices) { (void) pci_read_config_word(dev, PCI_COMMAND, &status); status |= PCI_COMMAND_PARITY | PCI_COMMAND_SERR | fbb_enable; (void) pci_write_config_word(dev, PCI_COMMAND, status); diff --git a/trunk/drivers/parport/parport_gsc.c b/trunk/drivers/parport/parport_gsc.c index 352f96180bc7..5d6de380e42b 100644 --- a/trunk/drivers/parport/parport_gsc.c +++ b/trunk/drivers/parport/parport_gsc.c @@ -271,7 +271,6 @@ struct parport *__devinit parport_gsc_probe_port (unsigned long base, if (!parport_SPP_supported (p)) { /* No port. */ kfree (priv); - kfree(ops); return NULL; } parport_PS2_supported (p); diff --git a/trunk/drivers/parport/parport_serial.c b/trunk/drivers/parport/parport_serial.c index 1631eeaf440e..e9c32274df3f 100644 --- a/trunk/drivers/parport/parport_serial.c +++ b/trunk/drivers/parport/parport_serial.c @@ -62,7 +62,6 @@ enum parport_pc_pci_cards { timedia_9079a, timedia_9079b, timedia_9079c, - wch_ch353_2s1p, }; /* each element directly indexed from enum list, above */ @@ -146,7 +145,6 @@ static struct parport_pc_pci cards[] __devinitdata = { /* timedia_9079a */ { 1, { { 2, 3 }, } }, /* timedia_9079b */ { 1, { { 2, 3 }, } }, /* timedia_9079c */ { 1, { { 2, 3 }, } }, - /* wch_ch353_2s1p*/ { 1, { { 2, -1}, } }, }; static struct pci_device_id parport_serial_pci_tbl[] = { @@ -245,8 +243,7 @@ static struct pci_device_id parport_serial_pci_tbl[] = { { 0x1409, 0x7168, 0x1409, 0xb079, 0, 0, timedia_9079a }, { 0x1409, 0x7168, 0x1409, 0xc079, 0, 0, timedia_9079b }, { 0x1409, 0x7168, 0x1409, 0xd079, 0, 0, timedia_9079c }, - /* WCH CARDS */ - { 0x4348, 0x7053, 0x4348, 0x3253, 0, 0, wch_ch353_2s1p}, + { 0, } /* terminate list */ }; MODULE_DEVICE_TABLE(pci,parport_serial_pci_tbl); @@ -463,12 +460,6 @@ static struct pciserial_board pci_parport_serial_boards[] __devinitdata = { .base_baud = 921600, .uart_offset = 8, }, - [wch_ch353_2s1p] = { - .flags = FL_BASE0|FL_BASE_BARS, - .num_ports = 2, - .base_baud = 115200, - .uart_offset = 8, - }, }; struct parport_serial_private { diff --git a/trunk/drivers/pci/.gitignore b/trunk/drivers/pci/.gitignore new file mode 100644 index 000000000000..f297ca8d313e --- /dev/null +++ b/trunk/drivers/pci/.gitignore @@ -0,0 +1,4 @@ +classlist.h +devlist.h +gen-devlist + diff --git a/trunk/drivers/pci/Kconfig b/trunk/drivers/pci/Kconfig index 6d51aa68ec7a..848bfb84c04c 100644 --- a/trunk/drivers/pci/Kconfig +++ b/trunk/drivers/pci/Kconfig @@ -3,6 +3,7 @@ # config ARCH_SUPPORTS_MSI bool + default n config PCI_MSI bool "Message Signaled Interrupts (MSI and MSI-X)" diff --git a/trunk/drivers/pci/access.c b/trunk/drivers/pci/access.c index 3af0478c057b..ba91a7e17519 100644 --- a/trunk/drivers/pci/access.c +++ b/trunk/drivers/pci/access.c @@ -469,205 +469,3 @@ void pci_cfg_access_unlock(struct pci_dev *dev) raw_spin_unlock_irqrestore(&pci_lock, flags); } EXPORT_SYMBOL_GPL(pci_cfg_access_unlock); - -static inline int pcie_cap_version(const struct pci_dev *dev) -{ - return dev->pcie_flags_reg & PCI_EXP_FLAGS_VERS; -} - -static inline bool pcie_cap_has_devctl(const struct pci_dev *dev) -{ - return true; -} - -static inline bool pcie_cap_has_lnkctl(const struct pci_dev *dev) -{ - int type = pci_pcie_type(dev); - - return pcie_cap_version(dev) > 1 || - type == PCI_EXP_TYPE_ROOT_PORT || - type == PCI_EXP_TYPE_ENDPOINT || - type == PCI_EXP_TYPE_LEG_END; -} - -static inline bool pcie_cap_has_sltctl(const struct pci_dev *dev) -{ - int type = pci_pcie_type(dev); - - return pcie_cap_version(dev) > 1 || - type == PCI_EXP_TYPE_ROOT_PORT || - (type == PCI_EXP_TYPE_DOWNSTREAM && - dev->pcie_flags_reg & PCI_EXP_FLAGS_SLOT); -} - -static inline bool pcie_cap_has_rtctl(const struct pci_dev *dev) -{ - int type = pci_pcie_type(dev); - - return pcie_cap_version(dev) > 1 || - type == PCI_EXP_TYPE_ROOT_PORT || - type == PCI_EXP_TYPE_RC_EC; -} - -static bool pcie_capability_reg_implemented(struct pci_dev *dev, int pos) -{ - if (!pci_is_pcie(dev)) - return false; - - switch (pos) { - case PCI_EXP_FLAGS_TYPE: - return true; - case PCI_EXP_DEVCAP: - case PCI_EXP_DEVCTL: - case PCI_EXP_DEVSTA: - return pcie_cap_has_devctl(dev); - case PCI_EXP_LNKCAP: - case PCI_EXP_LNKCTL: - case PCI_EXP_LNKSTA: - return pcie_cap_has_lnkctl(dev); - case PCI_EXP_SLTCAP: - case PCI_EXP_SLTCTL: - case PCI_EXP_SLTSTA: - return pcie_cap_has_sltctl(dev); - case PCI_EXP_RTCTL: - case PCI_EXP_RTCAP: - case PCI_EXP_RTSTA: - return pcie_cap_has_rtctl(dev); - case PCI_EXP_DEVCAP2: - case PCI_EXP_DEVCTL2: - case PCI_EXP_LNKCAP2: - case PCI_EXP_LNKCTL2: - case PCI_EXP_LNKSTA2: - return pcie_cap_version(dev) > 1; - default: - return false; - } -} - -/* - * Note that these accessor functions are only for the "PCI Express - * Capability" (see PCIe spec r3.0, sec 7.8). They do not apply to the - * other "PCI Express Extended Capabilities" (AER, VC, ACS, MFVC, etc.) - */ -int pcie_capability_read_word(struct pci_dev *dev, int pos, u16 *val) -{ - int ret; - - *val = 0; - if (pos & 1) - return -EINVAL; - - if (pcie_capability_reg_implemented(dev, pos)) { - ret = pci_read_config_word(dev, pci_pcie_cap(dev) + pos, val); - /* - * Reset *val to 0 if pci_read_config_word() fails, it may - * have been written as 0xFFFF if hardware error happens - * during pci_read_config_word(). - */ - if (ret) - *val = 0; - return ret; - } - - /* - * For Functions that do not implement the Slot Capabilities, - * Slot Status, and Slot Control registers, these spaces must - * be hardwired to 0b, with the exception of the Presence Detect - * State bit in the Slot Status register of Downstream Ports, - * which must be hardwired to 1b. (PCIe Base Spec 3.0, sec 7.8) - */ - if (pci_is_pcie(dev) && pos == PCI_EXP_SLTSTA && - pci_pcie_type(dev) == PCI_EXP_TYPE_DOWNSTREAM) { - *val = PCI_EXP_SLTSTA_PDS; - } - - return 0; -} -EXPORT_SYMBOL(pcie_capability_read_word); - -int pcie_capability_read_dword(struct pci_dev *dev, int pos, u32 *val) -{ - int ret; - - *val = 0; - if (pos & 3) - return -EINVAL; - - if (pcie_capability_reg_implemented(dev, pos)) { - ret = pci_read_config_dword(dev, pci_pcie_cap(dev) + pos, val); - /* - * Reset *val to 0 if pci_read_config_dword() fails, it may - * have been written as 0xFFFFFFFF if hardware error happens - * during pci_read_config_dword(). - */ - if (ret) - *val = 0; - return ret; - } - - if (pci_is_pcie(dev) && pos == PCI_EXP_SLTCTL && - pci_pcie_type(dev) == PCI_EXP_TYPE_DOWNSTREAM) { - *val = PCI_EXP_SLTSTA_PDS; - } - - return 0; -} -EXPORT_SYMBOL(pcie_capability_read_dword); - -int pcie_capability_write_word(struct pci_dev *dev, int pos, u16 val) -{ - if (pos & 1) - return -EINVAL; - - if (!pcie_capability_reg_implemented(dev, pos)) - return 0; - - return pci_write_config_word(dev, pci_pcie_cap(dev) + pos, val); -} -EXPORT_SYMBOL(pcie_capability_write_word); - -int pcie_capability_write_dword(struct pci_dev *dev, int pos, u32 val) -{ - if (pos & 3) - return -EINVAL; - - if (!pcie_capability_reg_implemented(dev, pos)) - return 0; - - return pci_write_config_dword(dev, pci_pcie_cap(dev) + pos, val); -} -EXPORT_SYMBOL(pcie_capability_write_dword); - -int pcie_capability_clear_and_set_word(struct pci_dev *dev, int pos, - u16 clear, u16 set) -{ - int ret; - u16 val; - - ret = pcie_capability_read_word(dev, pos, &val); - if (!ret) { - val &= ~clear; - val |= set; - ret = pcie_capability_write_word(dev, pos, val); - } - - return ret; -} -EXPORT_SYMBOL(pcie_capability_clear_and_set_word); - -int pcie_capability_clear_and_set_dword(struct pci_dev *dev, int pos, - u32 clear, u32 set) -{ - int ret; - u32 val; - - ret = pcie_capability_read_dword(dev, pos, &val); - if (!ret) { - val &= ~clear; - val |= set; - ret = pcie_capability_write_dword(dev, pos, val); - } - - return ret; -} -EXPORT_SYMBOL(pcie_capability_clear_and_set_dword); diff --git a/trunk/drivers/pci/bus.c b/trunk/drivers/pci/bus.c index 6241fd05bd41..4b0970b46e0b 100644 --- a/trunk/drivers/pci/bus.c +++ b/trunk/drivers/pci/bus.c @@ -87,15 +87,11 @@ EXPORT_SYMBOL_GPL(pci_bus_resource_n); void pci_bus_remove_resources(struct pci_bus *bus) { int i; - struct pci_bus_resource *bus_res, *tmp; for (i = 0; i < PCI_BRIDGE_RESOURCE_NUM; i++) bus->resource[i] = NULL; - list_for_each_entry_safe(bus_res, tmp, &bus->resources, list) { - list_del(&bus_res->list); - kfree(bus_res); - } + pci_free_resource_list(&bus->resources); } /** diff --git a/trunk/drivers/pci/hotplug/Kconfig b/trunk/drivers/pci/hotplug/Kconfig index b0e46dede1a9..66f29bc00be4 100644 --- a/trunk/drivers/pci/hotplug/Kconfig +++ b/trunk/drivers/pci/hotplug/Kconfig @@ -17,6 +17,28 @@ menuconfig HOTPLUG_PCI if HOTPLUG_PCI +config HOTPLUG_PCI_FAKE + tristate "Fake PCI Hotplug driver" + help + Say Y here if you want to use the fake PCI hotplug driver. It can + be used to simulate PCI hotplug events if even if your system is + not PCI hotplug capable. + + This driver will "emulate" removing PCI devices from the system. + If the "power" file is written to with "0" then the specified PCI + device will be completely removed from the kernel. + + WARNING, this does NOT turn off the power to the PCI device. + This is a "logical" removal, not a physical or electrical + removal. + + Use this module at your own risk. You have been warned! + + To compile this driver as a module, choose M here: the + module will be called fakephp. + + When in doubt, say N. + config HOTPLUG_PCI_COMPAQ tristate "Compaq PCI Hotplug driver" depends on X86 && PCI_BIOS @@ -121,7 +143,7 @@ config HOTPLUG_PCI_SHPC config HOTPLUG_PCI_RPA tristate "RPA PCI Hotplug driver" - depends on PPC_PSERIES && EEH + depends on PPC_PSERIES && EEH && !HOTPLUG_PCI_FAKE help Say Y here if you have a RPA system that supports PCI Hotplug. diff --git a/trunk/drivers/pci/hotplug/Makefile b/trunk/drivers/pci/hotplug/Makefile index c459cd4e39c2..6cd9f3c9887d 100644 --- a/trunk/drivers/pci/hotplug/Makefile +++ b/trunk/drivers/pci/hotplug/Makefile @@ -23,6 +23,9 @@ obj-$(CONFIG_HOTPLUG_PCI_ACPI) += acpiphp.o obj-$(CONFIG_HOTPLUG_PCI_ACPI_IBM) += acpiphp_ibm.o +# Link this last so it doesn't claim devices that have a real hotplug driver +obj-$(CONFIG_HOTPLUG_PCI_FAKE) += fakephp.o + pci_hotplug-objs := pci_hotplug_core.o pcihp_slot.o ifdef CONFIG_HOTPLUG_PCI_CPCI diff --git a/trunk/drivers/pci/hotplug/acpiphp_glue.c b/trunk/drivers/pci/hotplug/acpiphp_glue.c index 3d6d4fd1e3c5..ad6fd6695495 100644 --- a/trunk/drivers/pci/hotplug/acpiphp_glue.c +++ b/trunk/drivers/pci/hotplug/acpiphp_glue.c @@ -115,35 +115,6 @@ static const struct acpi_dock_ops acpiphp_dock_ops = { .handler = handle_hotplug_event_func, }; -/* Check whether the PCI device is managed by native PCIe hotplug driver */ -static bool device_is_managed_by_native_pciehp(struct pci_dev *pdev) -{ - u32 reg32; - acpi_handle tmp; - struct acpi_pci_root *root; - - /* Check whether the PCIe port supports native PCIe hotplug */ - if (pcie_capability_read_dword(pdev, PCI_EXP_SLTCAP, ®32)) - return false; - if (!(reg32 & PCI_EXP_SLTCAP_HPC)) - return false; - - /* - * Check whether native PCIe hotplug has been enabled for - * this PCIe hierarchy. - */ - tmp = acpi_find_root_bridge_handle(pdev); - if (!tmp) - return false; - root = acpi_pci_find_root(tmp); - if (!root) - return false; - if (!(root->osc_control_set & OSC_PCI_EXPRESS_NATIVE_HP_CONTROL)) - return false; - - return true; -} - /* callback routine to register each ACPI PCI slot object */ static acpi_status register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) @@ -171,8 +142,16 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) function = adr & 0xffff; pdev = pbus->self; - if (pdev && device_is_managed_by_native_pciehp(pdev)) - return AE_OK; + if (pdev && pci_is_pcie(pdev)) { + tmp = acpi_find_root_bridge_handle(pdev); + if (tmp) { + struct acpi_pci_root *root = acpi_pci_find_root(tmp); + + if (root && (root->osc_control_set & + OSC_PCI_EXPRESS_NATIVE_HP_CONTROL)) + return AE_OK; + } + } newfunc = kzalloc(sizeof(struct acpiphp_func), GFP_KERNEL); if (!newfunc) @@ -403,10 +382,10 @@ static inline void config_p2p_bridge_flags(struct acpiphp_bridge *bridge) /* allocate and initialize host bridge data structure */ -static void add_host_bridge(struct acpi_pci_root *root) +static void add_host_bridge(acpi_handle *handle) { struct acpiphp_bridge *bridge; - acpi_handle handle = root->device->handle; + struct acpi_pci_root *root = acpi_pci_find_root(handle); bridge = kzalloc(sizeof(struct acpiphp_bridge), GFP_KERNEL); if (bridge == NULL) @@ -489,12 +468,11 @@ find_p2p_bridge(acpi_handle handle, u32 lvl, void *context, void **rv) /* find hot-pluggable slots, and then find P2P bridge */ -static int add_bridge(struct acpi_pci_root *root) +static int add_bridge(acpi_handle handle) { acpi_status status; unsigned long long tmp; acpi_handle dummy_handle; - acpi_handle handle = root->device->handle; /* if the bridge doesn't have _STA, we assume it is always there */ status = acpi_get_handle(handle, "_STA", &dummy_handle); @@ -512,7 +490,7 @@ static int add_bridge(struct acpi_pci_root *root) /* check if this bridge has ejectable slots */ if (detect_ejectable_slots(handle) > 0) { dbg("found PCI host-bus bridge with hot-pluggable slots\n"); - add_host_bridge(root); + add_host_bridge(handle); } /* search P2P bridges under this host bridge */ @@ -610,10 +588,9 @@ cleanup_p2p_bridge(acpi_handle handle, u32 lvl, void *context, void **rv) return AE_OK; } -static void remove_bridge(struct acpi_pci_root *root) +static void remove_bridge(acpi_handle handle) { struct acpiphp_bridge *bridge; - acpi_handle handle = root->device->handle; /* cleanup p2p bridges under this host bridge in a depth-first manner */ @@ -892,6 +869,17 @@ static int __ref enable_device(struct acpiphp_slot *slot) return retval; } +static void disable_bridges(struct pci_bus *bus) +{ + struct pci_dev *dev; + list_for_each_entry(dev, &bus->devices, bus_list) { + if (dev->subordinate) { + disable_bridges(dev->subordinate); + pci_disable_device(dev); + } + } +} + /* return first device in slot, acquiring a reference on it */ static struct pci_dev *dev_in_slot(struct acpiphp_slot *slot) { @@ -943,7 +931,12 @@ static int disable_device(struct acpiphp_slot *slot) * here. */ while ((pdev = dev_in_slot(slot))) { - pci_stop_and_remove_bus_device(pdev); + pci_stop_bus_device(pdev); + if (pdev->subordinate) { + disable_bridges(pdev->subordinate); + pci_disable_device(pdev); + } + __pci_remove_bus_device(pdev); pci_dev_put(pdev); } @@ -1484,6 +1477,34 @@ int __init acpiphp_get_num_slots(void) } +#if 0 +/** + * acpiphp_for_each_slot - call function for each slot + * @fn: callback function + * @data: context to be passed to callback function + */ +static int acpiphp_for_each_slot(acpiphp_callback fn, void *data) +{ + struct list_head *node; + struct acpiphp_bridge *bridge; + struct acpiphp_slot *slot; + int retval = 0; + + list_for_each (node, &bridge_list) { + bridge = (struct acpiphp_bridge *)node; + for (slot = bridge->slots; slot; slot = slot->next) { + retval = fn(slot, data); + if (!retval) + goto err_exit; + } + } + + err_exit: + return retval; +} +#endif + + /** * acpiphp_enable_slot - power on slot * @slot: ACPI PHP slot diff --git a/trunk/drivers/pci/hotplug/cpcihp_generic.c b/trunk/drivers/pci/hotplug/cpcihp_generic.c index a6a71c41cdf8..81af764c629b 100644 --- a/trunk/drivers/pci/hotplug/cpcihp_generic.c +++ b/trunk/drivers/pci/hotplug/cpcihp_generic.c @@ -154,8 +154,12 @@ static int __init cpcihp_generic_init(void) if(!r) return -EBUSY; - dev = pci_get_domain_bus_and_slot(0, bridge_busnr, - PCI_DEVFN(bridge_slot, 0)); + bus = pci_find_bus(0, bridge_busnr); + if (!bus) { + err("Invalid bus number %d", bridge_busnr); + return -EINVAL; + } + dev = pci_get_slot(bus, PCI_DEVFN(bridge_slot, 0)); if(!dev || dev->hdr_type != PCI_HEADER_TYPE_BRIDGE) { err("Invalid bridge device %s", bridge); pci_dev_put(dev); diff --git a/trunk/drivers/pci/hotplug/cpqphp_ctrl.c b/trunk/drivers/pci/hotplug/cpqphp_ctrl.c index 36112fe212d3..e43908d9b5df 100644 --- a/trunk/drivers/pci/hotplug/cpqphp_ctrl.c +++ b/trunk/drivers/pci/hotplug/cpqphp_ctrl.c @@ -2890,8 +2890,27 @@ static int configure_new_function(struct controller *ctrl, struct pci_func *func func->mem_head = mem_node; } else return -ENOMEM; + } else if ((temp_register & 0x0BL) == 0x04) { + /* Map memory */ + base = temp_register & 0xFFFFFFF0; + base = ~base + 1; + + dbg("CND: length = 0x%x\n", base); + mem_node = get_resource(&(resources->mem_head), base); + + /* allocate the resource to the board */ + if (mem_node) { + base = mem_node->base; + + mem_node->next = func->mem_head; + func->mem_head = mem_node; + } else + return -ENOMEM; + } else if ((temp_register & 0x0BL) == 0x06) { + /* Those bits are reserved, we can't handle this */ + return 1; } else { - /* Reserved bits or requesting space below 1M */ + /* Requesting space below 1M */ return NOT_ENOUGH_RESOURCES; } diff --git a/trunk/drivers/pci/hotplug/fakephp.c b/trunk/drivers/pci/hotplug/fakephp.c new file mode 100644 index 000000000000..a019c9a712be --- /dev/null +++ b/trunk/drivers/pci/hotplug/fakephp.c @@ -0,0 +1,164 @@ +/* Works like the fakephp driver used to, except a little better. + * + * - It's possible to remove devices with subordinate busses. + * - New PCI devices that appear via any method, not just a fakephp triggered + * rescan, will be noticed. + * - Devices that are removed via any method, not just a fakephp triggered + * removal, will also be noticed. + * + * Uses nothing from the pci-hotplug subsystem. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../pci.h" + +struct legacy_slot { + struct kobject kobj; + struct pci_dev *dev; + struct list_head list; +}; + +static LIST_HEAD(legacy_list); + +static ssize_t legacy_show(struct kobject *kobj, struct attribute *attr, + char *buf) +{ + struct legacy_slot *slot = container_of(kobj, typeof(*slot), kobj); + strcpy(buf, "1\n"); + return 2; +} + +static void remove_callback(void *data) +{ + pci_stop_and_remove_bus_device((struct pci_dev *)data); +} + +static ssize_t legacy_store(struct kobject *kobj, struct attribute *attr, + const char *buf, size_t len) +{ + struct legacy_slot *slot = container_of(kobj, typeof(*slot), kobj); + unsigned long val; + + if (strict_strtoul(buf, 0, &val) < 0) + return -EINVAL; + + if (val) + pci_rescan_bus(slot->dev->bus); + else + sysfs_schedule_callback(&slot->dev->dev.kobj, remove_callback, + slot->dev, THIS_MODULE); + return len; +} + +static struct attribute *legacy_attrs[] = { + &(struct attribute){ .name = "power", .mode = 0644 }, + NULL, +}; + +static void legacy_release(struct kobject *kobj) +{ + struct legacy_slot *slot = container_of(kobj, typeof(*slot), kobj); + + pci_dev_put(slot->dev); + kfree(slot); +} + +static struct kobj_type legacy_ktype = { + .sysfs_ops = &(const struct sysfs_ops){ + .store = legacy_store, .show = legacy_show + }, + .release = &legacy_release, + .default_attrs = legacy_attrs, +}; + +static int legacy_add_slot(struct pci_dev *pdev) +{ + struct legacy_slot *slot = kzalloc(sizeof(*slot), GFP_KERNEL); + + if (!slot) + return -ENOMEM; + + if (kobject_init_and_add(&slot->kobj, &legacy_ktype, + &pci_slots_kset->kobj, "%s", + dev_name(&pdev->dev))) { + dev_warn(&pdev->dev, "Failed to created legacy fake slot\n"); + return -EINVAL; + } + slot->dev = pci_dev_get(pdev); + + list_add(&slot->list, &legacy_list); + + return 0; +} + +static int legacy_notify(struct notifier_block *nb, + unsigned long action, void *data) +{ + struct pci_dev *pdev = to_pci_dev(data); + + if (action == BUS_NOTIFY_ADD_DEVICE) { + legacy_add_slot(pdev); + } else if (action == BUS_NOTIFY_DEL_DEVICE) { + struct legacy_slot *slot; + + list_for_each_entry(slot, &legacy_list, list) + if (slot->dev == pdev) + goto found; + + dev_warn(&pdev->dev, "Missing legacy fake slot?"); + return -ENODEV; +found: + kobject_del(&slot->kobj); + list_del(&slot->list); + kobject_put(&slot->kobj); + } + + return 0; +} + +static struct notifier_block legacy_notifier = { + .notifier_call = legacy_notify +}; + +static int __init init_legacy(void) +{ + struct pci_dev *pdev = NULL; + + /* Add existing devices */ + for_each_pci_dev(pdev) + legacy_add_slot(pdev); + + /* Be alerted of any new ones */ + bus_register_notifier(&pci_bus_type, &legacy_notifier); + return 0; +} +module_init(init_legacy); + +static void __exit remove_legacy(void) +{ + struct legacy_slot *slot, *tmp; + + bus_unregister_notifier(&pci_bus_type, &legacy_notifier); + + list_for_each_entry_safe(slot, tmp, &legacy_list, list) { + list_del(&slot->list); + kobject_del(&slot->kobj); + kobject_put(&slot->kobj); + } +} +module_exit(remove_legacy); + + +MODULE_AUTHOR("Trent Piepho "); +MODULE_DESCRIPTION("Legacy version of the fakephp interface"); +MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/pci/hotplug/pciehp_acpi.c b/trunk/drivers/pci/hotplug/pciehp_acpi.c index 24d709b7388c..376d70d17176 100644 --- a/trunk/drivers/pci/hotplug/pciehp_acpi.c +++ b/trunk/drivers/pci/hotplug/pciehp_acpi.c @@ -81,12 +81,16 @@ static struct list_head __initdata dummy_slots = LIST_HEAD_INIT(dummy_slots); /* Dummy driver for dumplicate name detection */ static int __init dummy_probe(struct pcie_device *dev) { + int pos; u32 slot_cap; acpi_handle handle; struct dummy_slot *slot, *tmp; struct pci_dev *pdev = dev->port; - pcie_capability_read_dword(pdev, PCI_EXP_SLTCAP, &slot_cap); + pos = pci_pcie_cap(pdev); + if (!pos) + return -ENODEV; + pci_read_config_dword(pdev, pos + PCI_EXP_SLTCAP, &slot_cap); slot = kzalloc(sizeof(*slot), GFP_KERNEL); if (!slot) return -ENOMEM; diff --git a/trunk/drivers/pci/hotplug/pciehp_core.c b/trunk/drivers/pci/hotplug/pciehp_core.c index 916bf4f53aba..365c6b96c642 100644 --- a/trunk/drivers/pci/hotplug/pciehp_core.c +++ b/trunk/drivers/pci/hotplug/pciehp_core.c @@ -300,24 +300,24 @@ static int pciehp_suspend (struct pcie_device *dev) static int pciehp_resume (struct pcie_device *dev) { - struct controller *ctrl; - struct slot *slot; - u8 status; - dev_info(&dev->device, "%s ENTRY\n", __func__); - ctrl = get_service_data(dev); + if (pciehp_force) { + struct controller *ctrl = get_service_data(dev); + struct slot *slot; + u8 status; - /* reinitialize the chipset's event detection logic */ - pcie_enable_notification(ctrl); + /* reinitialize the chipset's event detection logic */ + pcie_enable_notification(ctrl); - slot = ctrl->slot; + slot = ctrl->slot; - /* Check if slot is occupied */ - pciehp_get_adapter_status(slot, &status); - if (status) - pciehp_enable_slot(slot); - else - pciehp_disable_slot(slot); + /* Check if slot is occupied */ + pciehp_get_adapter_status(slot, &status); + if (status) + pciehp_enable_slot(slot); + else + pciehp_disable_slot(slot); + } return 0; } #endif /* PM */ diff --git a/trunk/drivers/pci/hotplug/pciehp_hpc.c b/trunk/drivers/pci/hotplug/pciehp_hpc.c index 13b2eaf7ba43..302451e8289d 100644 --- a/trunk/drivers/pci/hotplug/pciehp_hpc.c +++ b/trunk/drivers/pci/hotplug/pciehp_hpc.c @@ -44,25 +44,25 @@ static inline int pciehp_readw(struct controller *ctrl, int reg, u16 *value) { struct pci_dev *dev = ctrl->pcie->port; - return pcie_capability_read_word(dev, reg, value); + return pci_read_config_word(dev, pci_pcie_cap(dev) + reg, value); } static inline int pciehp_readl(struct controller *ctrl, int reg, u32 *value) { struct pci_dev *dev = ctrl->pcie->port; - return pcie_capability_read_dword(dev, reg, value); + return pci_read_config_dword(dev, pci_pcie_cap(dev) + reg, value); } static inline int pciehp_writew(struct controller *ctrl, int reg, u16 value) { struct pci_dev *dev = ctrl->pcie->port; - return pcie_capability_write_word(dev, reg, value); + return pci_write_config_word(dev, pci_pcie_cap(dev) + reg, value); } static inline int pciehp_writel(struct controller *ctrl, int reg, u32 value) { struct pci_dev *dev = ctrl->pcie->port; - return pcie_capability_write_dword(dev, reg, value); + return pci_write_config_dword(dev, pci_pcie_cap(dev) + reg, value); } /* Power Control Command */ @@ -855,6 +855,10 @@ struct controller *pcie_init(struct pcie_device *dev) goto abort; } ctrl->pcie = dev; + if (!pci_pcie_cap(pdev)) { + ctrl_err(ctrl, "Cannot find PCI Express capability\n"); + goto abort_ctrl; + } if (pciehp_readl(ctrl, PCI_EXP_SLTCAP, &slot_cap)) { ctrl_err(ctrl, "Cannot read SLOTCAP register\n"); goto abort_ctrl; diff --git a/trunk/drivers/pci/hotplug/pcihp_slot.c b/trunk/drivers/pci/hotplug/pcihp_slot.c index fec2d5b75440..8c05a18c9770 100644 --- a/trunk/drivers/pci/hotplug/pcihp_slot.c +++ b/trunk/drivers/pci/hotplug/pcihp_slot.c @@ -96,11 +96,17 @@ static void program_hpp_type1(struct pci_dev *dev, struct hpp_type1 *hpp) static void program_hpp_type2(struct pci_dev *dev, struct hpp_type2 *hpp) { int pos; + u16 reg16; u32 reg32; if (!hpp) return; + /* Find PCI Express capability */ + pos = pci_pcie_cap(dev); + if (!pos) + return; + if (hpp->revision > 1) { dev_warn(&dev->dev, "PCIe settings rev %d not supported\n", hpp->revision); @@ -108,13 +114,17 @@ static void program_hpp_type2(struct pci_dev *dev, struct hpp_type2 *hpp) } /* Initialize Device Control Register */ - pcie_capability_clear_and_set_word(dev, PCI_EXP_DEVCTL, - ~hpp->pci_exp_devctl_and, hpp->pci_exp_devctl_or); + pci_read_config_word(dev, pos + PCI_EXP_DEVCTL, ®16); + reg16 = (reg16 & hpp->pci_exp_devctl_and) | hpp->pci_exp_devctl_or; + pci_write_config_word(dev, pos + PCI_EXP_DEVCTL, reg16); /* Initialize Link Control Register */ - if (dev->subordinate) - pcie_capability_clear_and_set_word(dev, PCI_EXP_LNKCTL, - ~hpp->pci_exp_lnkctl_and, hpp->pci_exp_lnkctl_or); + if (dev->subordinate) { + pci_read_config_word(dev, pos + PCI_EXP_LNKCTL, ®16); + reg16 = (reg16 & hpp->pci_exp_lnkctl_and) + | hpp->pci_exp_lnkctl_or; + pci_write_config_word(dev, pos + PCI_EXP_LNKCTL, reg16); + } /* Find Advanced Error Reporting Enhanced Capability */ pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR); diff --git a/trunk/drivers/pci/iov.c b/trunk/drivers/pci/iov.c index aeccc911abb8..74bbaf82638d 100644 --- a/trunk/drivers/pci/iov.c +++ b/trunk/drivers/pci/iov.c @@ -433,8 +433,8 @@ static int sriov_init(struct pci_dev *dev, int pos) struct resource *res; struct pci_dev *pdev; - if (pci_pcie_type(dev) != PCI_EXP_TYPE_RC_END && - pci_pcie_type(dev) != PCI_EXP_TYPE_ENDPOINT) + if (dev->pcie_type != PCI_EXP_TYPE_RC_END && + dev->pcie_type != PCI_EXP_TYPE_ENDPOINT) return -ENODEV; pci_read_config_word(dev, pos + PCI_SRIOV_CTRL, &ctrl); @@ -503,7 +503,7 @@ static int sriov_init(struct pci_dev *dev, int pos) iov->self = dev; pci_read_config_dword(dev, pos + PCI_SRIOV_CAP, &iov->cap); pci_read_config_byte(dev, pos + PCI_SRIOV_FUNC_LINK, &iov->link); - if (pci_pcie_type(dev) == PCI_EXP_TYPE_RC_END) + if (dev->pcie_type == PCI_EXP_TYPE_RC_END) iov->link = PCI_DEVFN(PCI_SLOT(dev->devfn), iov->link); if (pdev) diff --git a/trunk/drivers/pci/pci-acpi.c b/trunk/drivers/pci/pci-acpi.c index c5792d622dc4..fbf7b26c7c8a 100644 --- a/trunk/drivers/pci/pci-acpi.c +++ b/trunk/drivers/pci/pci-acpi.c @@ -266,8 +266,8 @@ static int acpi_pci_set_power_state(struct pci_dev *dev, pci_power_t state) } if (!error) - dev_info(&dev->dev, "power state changed by ACPI to %s\n", - pci_power_name(state)); + dev_printk(KERN_INFO, &dev->dev, + "power state changed by ACPI to D%d\n", state); return error; } diff --git a/trunk/drivers/pci/pci-driver.c b/trunk/drivers/pci/pci-driver.c index 9e1d2959e226..185be3703343 100644 --- a/trunk/drivers/pci/pci-driver.c +++ b/trunk/drivers/pci/pci-driver.c @@ -139,6 +139,7 @@ store_new_id(struct device_driver *driver, const char *buf, size_t count) return retval; return count; } +static DRIVER_ATTR(new_id, S_IWUSR, NULL, store_new_id); /** * store_remove_id - remove a PCI device ID from this driver @@ -184,16 +185,38 @@ store_remove_id(struct device_driver *driver, const char *buf, size_t count) return retval; return count; } +static DRIVER_ATTR(remove_id, S_IWUSR, NULL, store_remove_id); -static struct driver_attribute pci_drv_attrs[] = { - __ATTR(new_id, S_IWUSR, NULL, store_new_id), - __ATTR(remove_id, S_IWUSR, NULL, store_remove_id), - __ATTR_NULL, -}; +static int +pci_create_newid_files(struct pci_driver *drv) +{ + int error = 0; + + if (drv->probe != NULL) { + error = driver_create_file(&drv->driver, &driver_attr_new_id); + if (error == 0) { + error = driver_create_file(&drv->driver, + &driver_attr_remove_id); + if (error) + driver_remove_file(&drv->driver, + &driver_attr_new_id); + } + } + return error; +} -#else -#define pci_drv_attrs NULL -#endif /* CONFIG_HOTPLUG */ +static void pci_remove_newid_files(struct pci_driver *drv) +{ + driver_remove_file(&drv->driver, &driver_attr_remove_id); + driver_remove_file(&drv->driver, &driver_attr_new_id); +} +#else /* !CONFIG_HOTPLUG */ +static inline int pci_create_newid_files(struct pci_driver *drv) +{ + return 0; +} +static inline void pci_remove_newid_files(struct pci_driver *drv) {} +#endif /** * pci_match_id - See if a pci device matches a given pci_id table @@ -257,12 +280,8 @@ static long local_pci_probe(void *_ddi) { struct drv_dev_and_id *ddi = _ddi; struct device *dev = &ddi->dev->dev; - struct device *parent = dev->parent; int rc; - /* The parent bridge must be in active state when probing */ - if (parent) - pm_runtime_get_sync(parent); /* Unbound PCI devices are always set to disabled and suspended. * During probe, the device is set to enabled and active and the * usage count is incremented. If the driver supports runtime PM, @@ -279,8 +298,6 @@ static long local_pci_probe(void *_ddi) pm_runtime_set_suspended(dev); pm_runtime_put_noidle(dev); } - if (parent) - pm_runtime_put(parent); return rc; } @@ -942,13 +959,6 @@ static int pci_pm_poweroff_noirq(struct device *dev) if (!pci_dev->state_saved && !pci_is_bridge(pci_dev)) pci_prepare_to_sleep(pci_dev); - /* - * The reason for doing this here is the same as for the analogous code - * in pci_pm_suspend_noirq(). - */ - if (pci_dev->class == PCI_CLASS_SERIAL_USB_EHCI) - pci_write_config_word(pci_dev, PCI_COMMAND, 0); - return 0; } @@ -1139,6 +1149,8 @@ const struct dev_pm_ops pci_dev_pm_ops = { int __pci_register_driver(struct pci_driver *drv, struct module *owner, const char *mod_name) { + int error; + /* initialize common driver fields */ drv->driver.name = drv->name; drv->driver.bus = &pci_bus_type; @@ -1149,7 +1161,19 @@ int __pci_register_driver(struct pci_driver *drv, struct module *owner, INIT_LIST_HEAD(&drv->dynids.list); /* register with core */ - return driver_register(&drv->driver); + error = driver_register(&drv->driver); + if (error) + goto out; + + error = pci_create_newid_files(drv); + if (error) + goto out_newid; +out: + return error; + +out_newid: + driver_unregister(&drv->driver); + goto out; } /** @@ -1165,6 +1189,7 @@ int __pci_register_driver(struct pci_driver *drv, struct module *owner, void pci_unregister_driver(struct pci_driver *drv) { + pci_remove_newid_files(drv); driver_unregister(&drv->driver); pci_free_dynids(drv); } @@ -1264,7 +1289,6 @@ struct bus_type pci_bus_type = { .shutdown = pci_device_shutdown, .dev_attrs = pci_dev_attrs, .bus_attrs = pci_bus_attrs, - .drv_attrs = pci_drv_attrs, .pm = PCI_PM_OPS_PTR, }; diff --git a/trunk/drivers/pci/pci-sysfs.c b/trunk/drivers/pci/pci-sysfs.c index 02d107b15281..6869009c7393 100644 --- a/trunk/drivers/pci/pci-sysfs.c +++ b/trunk/drivers/pci/pci-sysfs.c @@ -458,40 +458,6 @@ boot_vga_show(struct device *dev, struct device_attribute *attr, char *buf) } struct device_attribute vga_attr = __ATTR_RO(boot_vga); -static void -pci_config_pm_runtime_get(struct pci_dev *pdev) -{ - struct device *dev = &pdev->dev; - struct device *parent = dev->parent; - - if (parent) - pm_runtime_get_sync(parent); - pm_runtime_get_noresume(dev); - /* - * pdev->current_state is set to PCI_D3cold during suspending, - * so wait until suspending completes - */ - pm_runtime_barrier(dev); - /* - * Only need to resume devices in D3cold, because config - * registers are still accessible for devices suspended but - * not in D3cold. - */ - if (pdev->current_state == PCI_D3cold) - pm_runtime_resume(dev); -} - -static void -pci_config_pm_runtime_put(struct pci_dev *pdev) -{ - struct device *dev = &pdev->dev; - struct device *parent = dev->parent; - - pm_runtime_put(dev); - if (parent) - pm_runtime_put_sync(parent); -} - static ssize_t pci_read_config(struct file *filp, struct kobject *kobj, struct bin_attribute *bin_attr, @@ -518,8 +484,6 @@ pci_read_config(struct file *filp, struct kobject *kobj, size = count; } - pci_config_pm_runtime_get(dev); - if ((off & 1) && size) { u8 val; pci_user_read_config_byte(dev, off, &val); @@ -565,8 +529,6 @@ pci_read_config(struct file *filp, struct kobject *kobj, --size; } - pci_config_pm_runtime_put(dev); - return count; } @@ -587,8 +549,6 @@ pci_write_config(struct file* filp, struct kobject *kobj, count = size; } - pci_config_pm_runtime_get(dev); - if ((off & 1) && size) { pci_user_write_config_byte(dev, off, data[off - init_off]); off++; @@ -627,8 +587,6 @@ pci_write_config(struct file* filp, struct kobject *kobj, --size; } - pci_config_pm_runtime_put(dev); - return count; } diff --git a/trunk/drivers/pci/pci.c b/trunk/drivers/pci/pci.c index 54858838f098..f3ea977a5b1b 100644 --- a/trunk/drivers/pci/pci.c +++ b/trunk/drivers/pci/pci.c @@ -254,17 +254,52 @@ int pci_bus_find_capability(struct pci_bus *bus, unsigned int devfn, int cap) } /** - * pci_find_next_ext_capability - Find an extended capability + * pci_pcie_cap2 - query for devices' PCI_CAP_ID_EXP v2 capability structure + * @dev: PCI device to check + * + * Like pci_pcie_cap() but also checks that the PCIe capability version is + * >= 2. Note that v1 capability structures could be sparse in that not + * all register fields were required. v2 requires the entire structure to + * be present size wise, while still allowing for non-implemented registers + * to exist but they must be hardwired to 0. + * + * Due to the differences in the versions of capability structures, one + * must be careful not to try and access non-existant registers that may + * exist in early versions - v1 - of Express devices. + * + * Returns the offset of the PCIe capability structure as long as the + * capability version is >= 2; otherwise 0 is returned. + */ +static int pci_pcie_cap2(struct pci_dev *dev) +{ + u16 flags; + int pos; + + pos = pci_pcie_cap(dev); + if (pos) { + pci_read_config_word(dev, pos + PCI_EXP_FLAGS, &flags); + if ((flags & PCI_EXP_FLAGS_VERS) < 2) + pos = 0; + } + + return pos; +} + +/** + * pci_find_ext_capability - Find an extended capability * @dev: PCI device to query - * @start: address at which to start looking (0 to start at beginning of list) * @cap: capability code * - * Returns the address of the next matching extended capability structure + * Returns the address of the requested extended capability structure * within the device's PCI configuration space or 0 if the device does - * not support it. Some capabilities can occur several times, e.g., the - * vendor-specific capability, and this provides a way to find them all. + * not support it. Possible values for @cap: + * + * %PCI_EXT_CAP_ID_ERR Advanced Error Reporting + * %PCI_EXT_CAP_ID_VC Virtual Channel + * %PCI_EXT_CAP_ID_DSN Device Serial Number + * %PCI_EXT_CAP_ID_PWR Power Budgeting */ -int pci_find_next_ext_capability(struct pci_dev *dev, int start, int cap) +int pci_find_ext_capability(struct pci_dev *dev, int cap) { u32 header; int ttl; @@ -276,9 +311,6 @@ int pci_find_next_ext_capability(struct pci_dev *dev, int start, int cap) if (dev->cfg_size <= PCI_CFG_SPACE_SIZE) return 0; - if (start) - pos = start; - if (pci_read_config_dword(dev, pos, &header) != PCIBIOS_SUCCESSFUL) return 0; @@ -290,7 +322,7 @@ int pci_find_next_ext_capability(struct pci_dev *dev, int start, int cap) return 0; while (ttl-- > 0) { - if (PCI_EXT_CAP_ID(header) == cap && pos != start) + if (PCI_EXT_CAP_ID(header) == cap) return pos; pos = PCI_EXT_CAP_NEXT(header); @@ -303,26 +335,6 @@ int pci_find_next_ext_capability(struct pci_dev *dev, int start, int cap) return 0; } -EXPORT_SYMBOL_GPL(pci_find_next_ext_capability); - -/** - * pci_find_ext_capability - Find an extended capability - * @dev: PCI device to query - * @cap: capability code - * - * Returns the address of the requested extended capability structure - * within the device's PCI configuration space or 0 if the device does - * not support it. Possible values for @cap: - * - * %PCI_EXT_CAP_ID_ERR Advanced Error Reporting - * %PCI_EXT_CAP_ID_VC Virtual Channel - * %PCI_EXT_CAP_ID_DSN Device Serial Number - * %PCI_EXT_CAP_ID_PWR Power Budgeting - */ -int pci_find_ext_capability(struct pci_dev *dev, int cap) -{ - return pci_find_next_ext_capability(dev, 0, cap); -} EXPORT_SYMBOL_GPL(pci_find_ext_capability); static int __pci_find_next_ht_cap(struct pci_dev *dev, int pos, int ht_cap) @@ -842,6 +854,21 @@ EXPORT_SYMBOL(pci_choose_state); #define PCI_EXP_SAVE_REGS 7 +#define pcie_cap_has_devctl(type, flags) 1 +#define pcie_cap_has_lnkctl(type, flags) \ + ((flags & PCI_EXP_FLAGS_VERS) > 1 || \ + (type == PCI_EXP_TYPE_ROOT_PORT || \ + type == PCI_EXP_TYPE_ENDPOINT || \ + type == PCI_EXP_TYPE_LEG_END)) +#define pcie_cap_has_sltctl(type, flags) \ + ((flags & PCI_EXP_FLAGS_VERS) > 1 || \ + ((type == PCI_EXP_TYPE_ROOT_PORT) || \ + (type == PCI_EXP_TYPE_DOWNSTREAM && \ + (flags & PCI_EXP_FLAGS_SLOT)))) +#define pcie_cap_has_rtctl(type, flags) \ + ((flags & PCI_EXP_FLAGS_VERS) > 1 || \ + (type == PCI_EXP_TYPE_ROOT_PORT || \ + type == PCI_EXP_TYPE_RC_EC)) static struct pci_cap_saved_state *pci_find_saved_cap( struct pci_dev *pci_dev, char cap) @@ -858,11 +885,13 @@ static struct pci_cap_saved_state *pci_find_saved_cap( static int pci_save_pcie_state(struct pci_dev *dev) { - int i = 0; + int pos, i = 0; struct pci_cap_saved_state *save_state; u16 *cap; + u16 flags; - if (!pci_is_pcie(dev)) + pos = pci_pcie_cap(dev); + if (!pos) return 0; save_state = pci_find_saved_cap(dev, PCI_CAP_ID_EXP); @@ -870,37 +899,60 @@ static int pci_save_pcie_state(struct pci_dev *dev) dev_err(&dev->dev, "buffer not found in %s\n", __func__); return -ENOMEM; } - cap = (u16 *)&save_state->cap.data[0]; - pcie_capability_read_word(dev, PCI_EXP_DEVCTL, &cap[i++]); - pcie_capability_read_word(dev, PCI_EXP_LNKCTL, &cap[i++]); - pcie_capability_read_word(dev, PCI_EXP_SLTCTL, &cap[i++]); - pcie_capability_read_word(dev, PCI_EXP_RTCTL, &cap[i++]); - pcie_capability_read_word(dev, PCI_EXP_DEVCTL2, &cap[i++]); - pcie_capability_read_word(dev, PCI_EXP_LNKCTL2, &cap[i++]); - pcie_capability_read_word(dev, PCI_EXP_SLTCTL2, &cap[i++]); + pci_read_config_word(dev, pos + PCI_EXP_FLAGS, &flags); + + if (pcie_cap_has_devctl(dev->pcie_type, flags)) + pci_read_config_word(dev, pos + PCI_EXP_DEVCTL, &cap[i++]); + if (pcie_cap_has_lnkctl(dev->pcie_type, flags)) + pci_read_config_word(dev, pos + PCI_EXP_LNKCTL, &cap[i++]); + if (pcie_cap_has_sltctl(dev->pcie_type, flags)) + pci_read_config_word(dev, pos + PCI_EXP_SLTCTL, &cap[i++]); + if (pcie_cap_has_rtctl(dev->pcie_type, flags)) + pci_read_config_word(dev, pos + PCI_EXP_RTCTL, &cap[i++]); + + pos = pci_pcie_cap2(dev); + if (!pos) + return 0; + + pci_read_config_word(dev, pos + PCI_EXP_DEVCTL2, &cap[i++]); + pci_read_config_word(dev, pos + PCI_EXP_LNKCTL2, &cap[i++]); + pci_read_config_word(dev, pos + PCI_EXP_SLTCTL2, &cap[i++]); return 0; } static void pci_restore_pcie_state(struct pci_dev *dev) { - int i = 0; + int i = 0, pos; struct pci_cap_saved_state *save_state; u16 *cap; + u16 flags; save_state = pci_find_saved_cap(dev, PCI_CAP_ID_EXP); - if (!save_state) + pos = pci_find_capability(dev, PCI_CAP_ID_EXP); + if (!save_state || pos <= 0) return; - cap = (u16 *)&save_state->cap.data[0]; - pcie_capability_write_word(dev, PCI_EXP_DEVCTL, cap[i++]); - pcie_capability_write_word(dev, PCI_EXP_LNKCTL, cap[i++]); - pcie_capability_write_word(dev, PCI_EXP_SLTCTL, cap[i++]); - pcie_capability_write_word(dev, PCI_EXP_RTCTL, cap[i++]); - pcie_capability_write_word(dev, PCI_EXP_DEVCTL2, cap[i++]); - pcie_capability_write_word(dev, PCI_EXP_LNKCTL2, cap[i++]); - pcie_capability_write_word(dev, PCI_EXP_SLTCTL2, cap[i++]); + + pci_read_config_word(dev, pos + PCI_EXP_FLAGS, &flags); + + if (pcie_cap_has_devctl(dev->pcie_type, flags)) + pci_write_config_word(dev, pos + PCI_EXP_DEVCTL, cap[i++]); + if (pcie_cap_has_lnkctl(dev->pcie_type, flags)) + pci_write_config_word(dev, pos + PCI_EXP_LNKCTL, cap[i++]); + if (pcie_cap_has_sltctl(dev->pcie_type, flags)) + pci_write_config_word(dev, pos + PCI_EXP_SLTCTL, cap[i++]); + if (pcie_cap_has_rtctl(dev->pcie_type, flags)) + pci_write_config_word(dev, pos + PCI_EXP_RTCTL, cap[i++]); + + pos = pci_pcie_cap2(dev); + if (!pos) + return; + + pci_write_config_word(dev, pos + PCI_EXP_DEVCTL2, cap[i++]); + pci_write_config_word(dev, pos + PCI_EXP_LNKCTL2, cap[i++]); + pci_write_config_word(dev, pos + PCI_EXP_SLTCTL2, cap[i++]); } @@ -1491,7 +1543,7 @@ void pci_pme_wakeup_bus(struct pci_bus *bus) /** * pci_wakeup - Wake up a PCI device - * @pci_dev: Device to handle. + * @dev: Device to handle. * @ign: ignored parameter */ static int pci_wakeup(struct pci_dev *pci_dev, void *ign) @@ -1889,7 +1941,6 @@ void pci_pm_init(struct pci_dev *dev) dev->pm_cap = pm; dev->d3_delay = PCI_PM_D3_WAIT; dev->d3cold_delay = PCI_PM_D3COLD_WAIT; - dev->d3cold_allowed = true; dev->d1_support = false; dev->d2_support = false; @@ -2015,24 +2066,35 @@ void pci_free_cap_save_buffers(struct pci_dev *dev) */ void pci_enable_ari(struct pci_dev *dev) { + int pos; u32 cap; + u16 ctrl; struct pci_dev *bridge; if (pcie_ari_disabled || !pci_is_pcie(dev) || dev->devfn) return; - if (!pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ARI)) + pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ARI); + if (!pos) return; bridge = dev->bus->self; if (!bridge) return; - pcie_capability_read_dword(bridge, PCI_EXP_DEVCAP2, &cap); + /* ARI is a PCIe cap v2 feature */ + pos = pci_pcie_cap2(bridge); + if (!pos) + return; + + pci_read_config_dword(bridge, pos + PCI_EXP_DEVCAP2, &cap); if (!(cap & PCI_EXP_DEVCAP2_ARI)) return; - pcie_capability_set_word(bridge, PCI_EXP_DEVCTL2, PCI_EXP_DEVCTL2_ARI); + pci_read_config_word(bridge, pos + PCI_EXP_DEVCTL2, &ctrl); + ctrl |= PCI_EXP_DEVCTL2_ARI; + pci_write_config_word(bridge, pos + PCI_EXP_DEVCTL2, ctrl); + bridge->ari_enabled = 1; } @@ -2047,14 +2109,20 @@ void pci_enable_ari(struct pci_dev *dev) */ void pci_enable_ido(struct pci_dev *dev, unsigned long type) { - u16 ctrl = 0; + int pos; + u16 ctrl; + /* ID-based Ordering is a PCIe cap v2 feature */ + pos = pci_pcie_cap2(dev); + if (!pos) + return; + + pci_read_config_word(dev, pos + PCI_EXP_DEVCTL2, &ctrl); if (type & PCI_EXP_IDO_REQUEST) ctrl |= PCI_EXP_IDO_REQ_EN; if (type & PCI_EXP_IDO_COMPLETION) ctrl |= PCI_EXP_IDO_CMP_EN; - if (ctrl) - pcie_capability_set_word(dev, PCI_EXP_DEVCTL2, ctrl); + pci_write_config_word(dev, pos + PCI_EXP_DEVCTL2, ctrl); } EXPORT_SYMBOL(pci_enable_ido); @@ -2065,14 +2133,20 @@ EXPORT_SYMBOL(pci_enable_ido); */ void pci_disable_ido(struct pci_dev *dev, unsigned long type) { - u16 ctrl = 0; + int pos; + u16 ctrl; + /* ID-based Ordering is a PCIe cap v2 feature */ + pos = pci_pcie_cap2(dev); + if (!pos) + return; + + pci_read_config_word(dev, pos + PCI_EXP_DEVCTL2, &ctrl); if (type & PCI_EXP_IDO_REQUEST) - ctrl |= PCI_EXP_IDO_REQ_EN; + ctrl &= ~PCI_EXP_IDO_REQ_EN; if (type & PCI_EXP_IDO_COMPLETION) - ctrl |= PCI_EXP_IDO_CMP_EN; - if (ctrl) - pcie_capability_clear_word(dev, PCI_EXP_DEVCTL2, ctrl); + ctrl &= ~PCI_EXP_IDO_CMP_EN; + pci_write_config_word(dev, pos + PCI_EXP_DEVCTL2, ctrl); } EXPORT_SYMBOL(pci_disable_ido); @@ -2097,11 +2171,17 @@ EXPORT_SYMBOL(pci_disable_ido); */ int pci_enable_obff(struct pci_dev *dev, enum pci_obff_signal_type type) { + int pos; u32 cap; u16 ctrl; int ret; - pcie_capability_read_dword(dev, PCI_EXP_DEVCAP2, &cap); + /* OBFF is a PCIe cap v2 feature */ + pos = pci_pcie_cap2(dev); + if (!pos) + return -ENOTSUPP; + + pci_read_config_dword(dev, pos + PCI_EXP_DEVCAP2, &cap); if (!(cap & PCI_EXP_OBFF_MASK)) return -ENOTSUPP; /* no OBFF support at all */ @@ -2112,7 +2192,7 @@ int pci_enable_obff(struct pci_dev *dev, enum pci_obff_signal_type type) return ret; } - pcie_capability_read_word(dev, PCI_EXP_DEVCTL2, &ctrl); + pci_read_config_word(dev, pos + PCI_EXP_DEVCTL2, &ctrl); if (cap & PCI_EXP_OBFF_WAKE) ctrl |= PCI_EXP_OBFF_WAKE_EN; else { @@ -2130,7 +2210,7 @@ int pci_enable_obff(struct pci_dev *dev, enum pci_obff_signal_type type) return -ENOTSUPP; } } - pcie_capability_write_word(dev, PCI_EXP_DEVCTL2, ctrl); + pci_write_config_word(dev, pos + PCI_EXP_DEVCTL2, ctrl); return 0; } @@ -2144,7 +2224,17 @@ EXPORT_SYMBOL(pci_enable_obff); */ void pci_disable_obff(struct pci_dev *dev) { - pcie_capability_clear_word(dev, PCI_EXP_DEVCTL2, PCI_EXP_OBFF_WAKE_EN); + int pos; + u16 ctrl; + + /* OBFF is a PCIe cap v2 feature */ + pos = pci_pcie_cap2(dev); + if (!pos) + return; + + pci_read_config_word(dev, pos + PCI_EXP_DEVCTL2, &ctrl); + ctrl &= ~PCI_EXP_OBFF_WAKE_EN; + pci_write_config_word(dev, pos + PCI_EXP_DEVCTL2, ctrl); } EXPORT_SYMBOL(pci_disable_obff); @@ -2157,9 +2247,15 @@ EXPORT_SYMBOL(pci_disable_obff); */ static bool pci_ltr_supported(struct pci_dev *dev) { + int pos; u32 cap; - pcie_capability_read_dword(dev, PCI_EXP_DEVCAP2, &cap); + /* LTR is a PCIe cap v2 feature */ + pos = pci_pcie_cap2(dev); + if (!pos) + return false; + + pci_read_config_dword(dev, pos + PCI_EXP_DEVCAP2, &cap); return cap & PCI_EXP_DEVCAP2_LTR; } @@ -2176,15 +2272,22 @@ static bool pci_ltr_supported(struct pci_dev *dev) */ int pci_enable_ltr(struct pci_dev *dev) { + int pos; + u16 ctrl; int ret; + if (!pci_ltr_supported(dev)) + return -ENOTSUPP; + + /* LTR is a PCIe cap v2 feature */ + pos = pci_pcie_cap2(dev); + if (!pos) + return -ENOTSUPP; + /* Only primary function can enable/disable LTR */ if (PCI_FUNC(dev->devfn) != 0) return -EINVAL; - if (!pci_ltr_supported(dev)) - return -ENOTSUPP; - /* Enable upstream ports first */ if (dev->bus->self) { ret = pci_enable_ltr(dev->bus->self); @@ -2192,7 +2295,11 @@ int pci_enable_ltr(struct pci_dev *dev) return ret; } - return pcie_capability_set_word(dev, PCI_EXP_DEVCTL2, PCI_EXP_LTR_EN); + pci_read_config_word(dev, pos + PCI_EXP_DEVCTL2, &ctrl); + ctrl |= PCI_EXP_LTR_EN; + pci_write_config_word(dev, pos + PCI_EXP_DEVCTL2, ctrl); + + return 0; } EXPORT_SYMBOL(pci_enable_ltr); @@ -2202,14 +2309,24 @@ EXPORT_SYMBOL(pci_enable_ltr); */ void pci_disable_ltr(struct pci_dev *dev) { - /* Only primary function can enable/disable LTR */ - if (PCI_FUNC(dev->devfn) != 0) - return; + int pos; + u16 ctrl; if (!pci_ltr_supported(dev)) return; - pcie_capability_clear_word(dev, PCI_EXP_DEVCTL2, PCI_EXP_LTR_EN); + /* LTR is a PCIe cap v2 feature */ + pos = pci_pcie_cap2(dev); + if (!pos) + return; + + /* Only primary function can enable/disable LTR */ + if (PCI_FUNC(dev->devfn) != 0) + return; + + pci_read_config_word(dev, pos + PCI_EXP_DEVCTL2, &ctrl); + ctrl &= ~PCI_EXP_LTR_EN; + pci_write_config_word(dev, pos + PCI_EXP_DEVCTL2, ctrl); } EXPORT_SYMBOL(pci_disable_ltr); @@ -2292,6 +2409,9 @@ void pci_enable_acs(struct pci_dev *dev) if (!pci_acs_enable) return; + if (!pci_is_pcie(dev)) + return; + pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ACS); if (!pos) return; @@ -2339,8 +2459,8 @@ bool pci_acs_enabled(struct pci_dev *pdev, u16 acs_flags) acs_flags &= (PCI_ACS_RR | PCI_ACS_CR | PCI_ACS_EC | PCI_ACS_DT); - if (pci_pcie_type(pdev) == PCI_EXP_TYPE_DOWNSTREAM || - pci_pcie_type(pdev) == PCI_EXP_TYPE_ROOT_PORT || + if (pdev->pcie_type == PCI_EXP_TYPE_DOWNSTREAM || + pdev->pcie_type == PCI_EXP_TYPE_ROOT_PORT || pdev->multifunction) { pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ACS); if (!pos) @@ -3056,10 +3176,15 @@ EXPORT_SYMBOL(pci_set_dma_seg_boundary); static int pcie_flr(struct pci_dev *dev, int probe) { int i; + int pos; u32 cap; - u16 status; + u16 status, control; - pcie_capability_read_dword(dev, PCI_EXP_DEVCAP, &cap); + pos = pci_pcie_cap(dev); + if (!pos) + return -ENOTTY; + + pci_read_config_dword(dev, pos + PCI_EXP_DEVCAP, &cap); if (!(cap & PCI_EXP_DEVCAP_FLR)) return -ENOTTY; @@ -3071,7 +3196,7 @@ static int pcie_flr(struct pci_dev *dev, int probe) if (i) msleep((1 << (i - 1)) * 100); - pcie_capability_read_word(dev, PCI_EXP_DEVSTA, &status); + pci_read_config_word(dev, pos + PCI_EXP_DEVSTA, &status); if (!(status & PCI_EXP_DEVSTA_TRPND)) goto clear; } @@ -3080,7 +3205,9 @@ static int pcie_flr(struct pci_dev *dev, int probe) "proceeding with reset anyway\n"); clear: - pcie_capability_set_word(dev, PCI_EXP_DEVCTL, PCI_EXP_DEVCTL_BCR_FLR); + pci_read_config_word(dev, pos + PCI_EXP_DEVCTL, &control); + control |= PCI_EXP_DEVCTL_BCR_FLR; + pci_write_config_word(dev, pos + PCI_EXP_DEVCTL, control); msleep(100); @@ -3448,11 +3575,18 @@ EXPORT_SYMBOL(pcix_set_mmrbc); */ int pcie_get_readrq(struct pci_dev *dev) { + int ret, cap; u16 ctl; - pcie_capability_read_word(dev, PCI_EXP_DEVCTL, &ctl); + cap = pci_pcie_cap(dev); + if (!cap) + return -EINVAL; + + ret = pci_read_config_word(dev, cap + PCI_EXP_DEVCTL, &ctl); + if (!ret) + ret = 128 << ((ctl & PCI_EXP_DEVCTL_READRQ) >> 12); - return 128 << ((ctl & PCI_EXP_DEVCTL_READRQ) >> 12); + return ret; } EXPORT_SYMBOL(pcie_get_readrq); @@ -3466,11 +3600,19 @@ EXPORT_SYMBOL(pcie_get_readrq); */ int pcie_set_readrq(struct pci_dev *dev, int rq) { - u16 v; + int cap, err = -EINVAL; + u16 ctl, v; if (rq < 128 || rq > 4096 || !is_power_of_2(rq)) - return -EINVAL; + goto out; + cap = pci_pcie_cap(dev); + if (!cap) + goto out; + + err = pci_read_config_word(dev, cap + PCI_EXP_DEVCTL, &ctl); + if (err) + goto out; /* * If using the "performance" PCIe config, we clamp the * read rq size to the max packet size to prevent the @@ -3488,8 +3630,14 @@ int pcie_set_readrq(struct pci_dev *dev, int rq) v = (ffs(rq) - 8) << 12; - return pcie_capability_clear_and_set_word(dev, PCI_EXP_DEVCTL, - PCI_EXP_DEVCTL_READRQ, v); + if ((ctl & PCI_EXP_DEVCTL_READRQ) != v) { + ctl &= ~PCI_EXP_DEVCTL_READRQ; + ctl |= v; + err = pci_write_config_word(dev, cap + PCI_EXP_DEVCTL, ctl); + } + +out: + return err; } EXPORT_SYMBOL(pcie_set_readrq); @@ -3502,11 +3650,18 @@ EXPORT_SYMBOL(pcie_set_readrq); */ int pcie_get_mps(struct pci_dev *dev) { + int ret, cap; u16 ctl; - pcie_capability_read_word(dev, PCI_EXP_DEVCTL, &ctl); + cap = pci_pcie_cap(dev); + if (!cap) + return -EINVAL; + + ret = pci_read_config_word(dev, cap + PCI_EXP_DEVCTL, &ctl); + if (!ret) + ret = 128 << ((ctl & PCI_EXP_DEVCTL_PAYLOAD) >> 5); - return 128 << ((ctl & PCI_EXP_DEVCTL_PAYLOAD) >> 5); + return ret; } /** @@ -3519,18 +3674,32 @@ int pcie_get_mps(struct pci_dev *dev) */ int pcie_set_mps(struct pci_dev *dev, int mps) { - u16 v; + int cap, err = -EINVAL; + u16 ctl, v; if (mps < 128 || mps > 4096 || !is_power_of_2(mps)) - return -EINVAL; + goto out; v = ffs(mps) - 8; if (v > dev->pcie_mpss) - return -EINVAL; + goto out; v <<= 5; - return pcie_capability_clear_and_set_word(dev, PCI_EXP_DEVCTL, - PCI_EXP_DEVCTL_PAYLOAD, v); + cap = pci_pcie_cap(dev); + if (!cap) + goto out; + + err = pci_read_config_word(dev, cap + PCI_EXP_DEVCTL, &ctl); + if (err) + goto out; + + if ((ctl & PCI_EXP_DEVCTL_PAYLOAD) != v) { + ctl &= ~PCI_EXP_DEVCTL_PAYLOAD; + ctl |= v; + err = pci_write_config_word(dev, cap + PCI_EXP_DEVCTL, ctl); + } +out: + return err; } /** diff --git a/trunk/drivers/pci/pcie/aer/aer_inject.c b/trunk/drivers/pci/pcie/aer/aer_inject.c index 4e24cb8a94ae..52229863e9fe 100644 --- a/trunk/drivers/pci/pcie/aer/aer_inject.c +++ b/trunk/drivers/pci/pcie/aer/aer_inject.c @@ -288,7 +288,7 @@ static struct pci_dev *pcie_find_root_port(struct pci_dev *dev) while (1) { if (!pci_is_pcie(dev)) break; - if (pci_pcie_type(dev) == PCI_EXP_TYPE_ROOT_PORT) + if (dev->pcie_type == PCI_EXP_TYPE_ROOT_PORT) return dev; if (!dev->bus->self) break; diff --git a/trunk/drivers/pci/pcie/aer/aerdrv.c b/trunk/drivers/pci/pcie/aer/aerdrv.c index 030cf12d5468..58ad7917553c 100644 --- a/trunk/drivers/pci/pcie/aer/aerdrv.c +++ b/trunk/drivers/pci/pcie/aer/aerdrv.c @@ -48,7 +48,7 @@ static pci_ers_result_t aer_error_detected(struct pci_dev *dev, static void aer_error_resume(struct pci_dev *dev); static pci_ers_result_t aer_root_reset(struct pci_dev *dev); -static const struct pci_error_handlers aer_error_handlers = { +static struct pci_error_handlers aer_error_handlers = { .error_detected = aer_error_detected, .resume = aer_error_resume, }; @@ -81,11 +81,10 @@ bool pci_aer_available(void) static int set_device_error_reporting(struct pci_dev *dev, void *data) { bool enable = *((bool *)data); - int type = pci_pcie_type(dev); - if ((type == PCI_EXP_TYPE_ROOT_PORT) || - (type == PCI_EXP_TYPE_UPSTREAM) || - (type == PCI_EXP_TYPE_DOWNSTREAM)) { + if ((dev->pcie_type == PCI_EXP_TYPE_ROOT_PORT) || + (dev->pcie_type == PCI_EXP_TYPE_UPSTREAM) || + (dev->pcie_type == PCI_EXP_TYPE_DOWNSTREAM)) { if (enable) pci_enable_pcie_error_reporting(dev); else @@ -122,17 +121,19 @@ static void set_downstream_devices_error_reporting(struct pci_dev *dev, static void aer_enable_rootport(struct aer_rpc *rpc) { struct pci_dev *pdev = rpc->rpd->port; - int aer_pos; + int pos, aer_pos; u16 reg16; u32 reg32; + pos = pci_pcie_cap(pdev); /* Clear PCIe Capability's Device Status */ - pcie_capability_read_word(pdev, PCI_EXP_DEVSTA, ®16); - pcie_capability_write_word(pdev, PCI_EXP_DEVSTA, reg16); + pci_read_config_word(pdev, pos+PCI_EXP_DEVSTA, ®16); + pci_write_config_word(pdev, pos+PCI_EXP_DEVSTA, reg16); /* Disable system error generation in response to error messages */ - pcie_capability_clear_word(pdev, PCI_EXP_RTCTL, - SYSTEM_ERROR_INTR_ON_MESG_MASK); + pci_read_config_word(pdev, pos + PCI_EXP_RTCTL, ®16); + reg16 &= ~(SYSTEM_ERROR_INTR_ON_MESG_MASK); + pci_write_config_word(pdev, pos + PCI_EXP_RTCTL, reg16); aer_pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ERR); /* Clear error status */ @@ -394,8 +395,9 @@ static void aer_error_resume(struct pci_dev *dev) u16 reg16; /* Clean up Root device status */ - pcie_capability_read_word(dev, PCI_EXP_DEVSTA, ®16); - pcie_capability_write_word(dev, PCI_EXP_DEVSTA, reg16); + pos = pci_pcie_cap(dev); + pci_read_config_word(dev, pos + PCI_EXP_DEVSTA, ®16); + pci_write_config_word(dev, pos + PCI_EXP_DEVSTA, reg16); /* Clean AER Root Error Status */ pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR); diff --git a/trunk/drivers/pci/pcie/aer/aerdrv_acpi.c b/trunk/drivers/pci/pcie/aer/aerdrv_acpi.c index 5194a7d41730..124f20ff11b2 100644 --- a/trunk/drivers/pci/pcie/aer/aerdrv_acpi.c +++ b/trunk/drivers/pci/pcie/aer/aerdrv_acpi.c @@ -60,7 +60,7 @@ static int aer_hest_parse(struct acpi_hest_header *hest_hdr, void *data) p = (struct acpi_hest_aer_common *)(hest_hdr + 1); if (p->flags & ACPI_HEST_GLOBAL) { if ((pci_is_pcie(info->pci_dev) && - pci_pcie_type(info->pci_dev) == pcie_type) || bridge) + info->pci_dev->pcie_type == pcie_type) || bridge) ff = !!(p->flags & ACPI_HEST_FIRMWARE_FIRST); } else if (hest_match_pci(p, info->pci_dev)) diff --git a/trunk/drivers/pci/pcie/aer/aerdrv_core.c b/trunk/drivers/pci/pcie/aer/aerdrv_core.c index 06bad96af415..0ca053538146 100644 --- a/trunk/drivers/pci/pcie/aer/aerdrv_core.c +++ b/trunk/drivers/pci/pcie/aer/aerdrv_core.c @@ -32,28 +32,53 @@ static bool nosourceid; module_param(forceload, bool, 0); module_param(nosourceid, bool, 0); -#define PCI_EXP_AER_FLAGS (PCI_EXP_DEVCTL_CERE | PCI_EXP_DEVCTL_NFERE | \ - PCI_EXP_DEVCTL_FERE | PCI_EXP_DEVCTL_URRE) - int pci_enable_pcie_error_reporting(struct pci_dev *dev) { + u16 reg16 = 0; + int pos; + if (pcie_aer_get_firmware_first(dev)) return -EIO; - if (!pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR)) + pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR); + if (!pos) return -EIO; - return pcie_capability_set_word(dev, PCI_EXP_DEVCTL, PCI_EXP_AER_FLAGS); + pos = pci_pcie_cap(dev); + if (!pos) + return -EIO; + + pci_read_config_word(dev, pos + PCI_EXP_DEVCTL, ®16); + reg16 |= (PCI_EXP_DEVCTL_CERE | + PCI_EXP_DEVCTL_NFERE | + PCI_EXP_DEVCTL_FERE | + PCI_EXP_DEVCTL_URRE); + pci_write_config_word(dev, pos + PCI_EXP_DEVCTL, reg16); + + return 0; } EXPORT_SYMBOL_GPL(pci_enable_pcie_error_reporting); int pci_disable_pcie_error_reporting(struct pci_dev *dev) { + u16 reg16 = 0; + int pos; + if (pcie_aer_get_firmware_first(dev)) return -EIO; - return pcie_capability_clear_word(dev, PCI_EXP_DEVCTL, - PCI_EXP_AER_FLAGS); + pos = pci_pcie_cap(dev); + if (!pos) + return -EIO; + + pci_read_config_word(dev, pos + PCI_EXP_DEVCTL, ®16); + reg16 &= ~(PCI_EXP_DEVCTL_CERE | + PCI_EXP_DEVCTL_NFERE | + PCI_EXP_DEVCTL_FERE | + PCI_EXP_DEVCTL_URRE); + pci_write_config_word(dev, pos + PCI_EXP_DEVCTL, reg16); + + return 0; } EXPORT_SYMBOL_GPL(pci_disable_pcie_error_reporting); @@ -126,12 +151,18 @@ static bool is_error_source(struct pci_dev *dev, struct aer_err_info *e_info) */ if (atomic_read(&dev->enable_cnt) == 0) return false; + pos = pci_pcie_cap(dev); + if (!pos) + return false; /* Check if AER is enabled */ - pcie_capability_read_word(dev, PCI_EXP_DEVCTL, ®16); - if (!(reg16 & PCI_EXP_AER_FLAGS)) + pci_read_config_word(dev, pos + PCI_EXP_DEVCTL, ®16); + if (!(reg16 & ( + PCI_EXP_DEVCTL_CERE | + PCI_EXP_DEVCTL_NFERE | + PCI_EXP_DEVCTL_FERE | + PCI_EXP_DEVCTL_URRE))) return false; - pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR); if (!pos) return false; @@ -209,7 +240,7 @@ static bool find_source_device(struct pci_dev *parent, static int report_error_detected(struct pci_dev *dev, void *data) { pci_ers_result_t vote; - const struct pci_error_handlers *err_handler; + struct pci_error_handlers *err_handler; struct aer_broadcast_data *result_data; result_data = (struct aer_broadcast_data *) data; @@ -243,7 +274,7 @@ static int report_error_detected(struct pci_dev *dev, void *data) static int report_mmio_enabled(struct pci_dev *dev, void *data) { pci_ers_result_t vote; - const struct pci_error_handlers *err_handler; + struct pci_error_handlers *err_handler; struct aer_broadcast_data *result_data; result_data = (struct aer_broadcast_data *) data; @@ -261,7 +292,7 @@ static int report_mmio_enabled(struct pci_dev *dev, void *data) static int report_slot_reset(struct pci_dev *dev, void *data) { pci_ers_result_t vote; - const struct pci_error_handlers *err_handler; + struct pci_error_handlers *err_handler; struct aer_broadcast_data *result_data; result_data = (struct aer_broadcast_data *) data; @@ -278,7 +309,7 @@ static int report_slot_reset(struct pci_dev *dev, void *data) static int report_resume(struct pci_dev *dev, void *data) { - const struct pci_error_handlers *err_handler; + struct pci_error_handlers *err_handler; dev->error_state = pci_channel_io_normal; @@ -434,7 +465,7 @@ static pci_ers_result_t reset_link(struct pci_dev *dev) if (driver && driver->reset_link) { status = driver->reset_link(udev); - } else if (pci_pcie_type(udev) == PCI_EXP_TYPE_DOWNSTREAM) { + } else if (udev->pcie_type == PCI_EXP_TYPE_DOWNSTREAM) { status = default_downstream_reset_link(udev); } else { dev_printk(KERN_DEBUG, &dev->dev, @@ -509,12 +540,14 @@ static void do_recovery(struct pci_dev *dev, int severity) "resume", report_resume); - dev_info(&dev->dev, "AER: Device recovery successful\n"); + dev_printk(KERN_DEBUG, &dev->dev, + "AER driver successfully recovered\n"); return; failed: /* TODO: Should kernel panic here? */ - dev_info(&dev->dev, "AER: Device recovery failed\n"); + dev_printk(KERN_DEBUG, &dev->dev, + "AER driver didn't recover\n"); } /** diff --git a/trunk/drivers/pci/pcie/aspm.c b/trunk/drivers/pci/pcie/aspm.c index 213753b283a6..b500840a143b 100644 --- a/trunk/drivers/pci/pcie/aspm.c +++ b/trunk/drivers/pci/pcie/aspm.c @@ -125,16 +125,21 @@ static int policy_to_clkpm_state(struct pcie_link_state *link) static void pcie_set_clkpm_nocheck(struct pcie_link_state *link, int enable) { + int pos; + u16 reg16; struct pci_dev *child; struct pci_bus *linkbus = link->pdev->subordinate; list_for_each_entry(child, &linkbus->devices, bus_list) { + pos = pci_pcie_cap(child); + if (!pos) + return; + pci_read_config_word(child, pos + PCI_EXP_LNKCTL, ®16); if (enable) - pcie_capability_set_word(child, PCI_EXP_LNKCTL, - PCI_EXP_LNKCTL_CLKREQ_EN); + reg16 |= PCI_EXP_LNKCTL_CLKREQ_EN; else - pcie_capability_clear_word(child, PCI_EXP_LNKCTL, - PCI_EXP_LNKCTL_CLKREQ_EN); + reg16 &= ~PCI_EXP_LNKCTL_CLKREQ_EN; + pci_write_config_word(child, pos + PCI_EXP_LNKCTL, reg16); } link->clkpm_enabled = !!enable; } @@ -152,7 +157,7 @@ static void pcie_set_clkpm(struct pcie_link_state *link, int enable) static void pcie_clkpm_cap_init(struct pcie_link_state *link, int blacklist) { - int capable = 1, enabled = 1; + int pos, capable = 1, enabled = 1; u32 reg32; u16 reg16; struct pci_dev *child; @@ -160,13 +165,16 @@ static void pcie_clkpm_cap_init(struct pcie_link_state *link, int blacklist) /* All functions should have the same cap and state, take the worst */ list_for_each_entry(child, &linkbus->devices, bus_list) { - pcie_capability_read_dword(child, PCI_EXP_LNKCAP, ®32); + pos = pci_pcie_cap(child); + if (!pos) + return; + pci_read_config_dword(child, pos + PCI_EXP_LNKCAP, ®32); if (!(reg32 & PCI_EXP_LNKCAP_CLKPM)) { capable = 0; enabled = 0; break; } - pcie_capability_read_word(child, PCI_EXP_LNKCTL, ®16); + pci_read_config_word(child, pos + PCI_EXP_LNKCTL, ®16); if (!(reg16 & PCI_EXP_LNKCTL_CLKREQ_EN)) enabled = 0; } @@ -182,7 +190,7 @@ static void pcie_clkpm_cap_init(struct pcie_link_state *link, int blacklist) */ static void pcie_aspm_configure_common_clock(struct pcie_link_state *link) { - int same_clock = 1; + int ppos, cpos, same_clock = 1; u16 reg16, parent_reg, child_reg[8]; unsigned long start_jiffies; struct pci_dev *child, *parent = link->pdev; @@ -195,43 +203,46 @@ static void pcie_aspm_configure_common_clock(struct pcie_link_state *link) BUG_ON(!pci_is_pcie(child)); /* Check downstream component if bit Slot Clock Configuration is 1 */ - pcie_capability_read_word(child, PCI_EXP_LNKSTA, ®16); + cpos = pci_pcie_cap(child); + pci_read_config_word(child, cpos + PCI_EXP_LNKSTA, ®16); if (!(reg16 & PCI_EXP_LNKSTA_SLC)) same_clock = 0; /* Check upstream component if bit Slot Clock Configuration is 1 */ - pcie_capability_read_word(parent, PCI_EXP_LNKSTA, ®16); + ppos = pci_pcie_cap(parent); + pci_read_config_word(parent, ppos + PCI_EXP_LNKSTA, ®16); if (!(reg16 & PCI_EXP_LNKSTA_SLC)) same_clock = 0; /* Configure downstream component, all functions */ list_for_each_entry(child, &linkbus->devices, bus_list) { - pcie_capability_read_word(child, PCI_EXP_LNKCTL, ®16); + cpos = pci_pcie_cap(child); + pci_read_config_word(child, cpos + PCI_EXP_LNKCTL, ®16); child_reg[PCI_FUNC(child->devfn)] = reg16; if (same_clock) reg16 |= PCI_EXP_LNKCTL_CCC; else reg16 &= ~PCI_EXP_LNKCTL_CCC; - pcie_capability_write_word(child, PCI_EXP_LNKCTL, reg16); + pci_write_config_word(child, cpos + PCI_EXP_LNKCTL, reg16); } /* Configure upstream component */ - pcie_capability_read_word(parent, PCI_EXP_LNKCTL, ®16); + pci_read_config_word(parent, ppos + PCI_EXP_LNKCTL, ®16); parent_reg = reg16; if (same_clock) reg16 |= PCI_EXP_LNKCTL_CCC; else reg16 &= ~PCI_EXP_LNKCTL_CCC; - pcie_capability_write_word(parent, PCI_EXP_LNKCTL, reg16); + pci_write_config_word(parent, ppos + PCI_EXP_LNKCTL, reg16); /* Retrain link */ reg16 |= PCI_EXP_LNKCTL_RL; - pcie_capability_write_word(parent, PCI_EXP_LNKCTL, reg16); + pci_write_config_word(parent, ppos + PCI_EXP_LNKCTL, reg16); /* Wait for link training end. Break out after waiting for timeout */ start_jiffies = jiffies; for (;;) { - pcie_capability_read_word(parent, PCI_EXP_LNKSTA, ®16); + pci_read_config_word(parent, ppos + PCI_EXP_LNKSTA, ®16); if (!(reg16 & PCI_EXP_LNKSTA_LT)) break; if (time_after(jiffies, start_jiffies + LINK_RETRAIN_TIMEOUT)) @@ -244,10 +255,12 @@ static void pcie_aspm_configure_common_clock(struct pcie_link_state *link) /* Training failed. Restore common clock configurations */ dev_printk(KERN_ERR, &parent->dev, "ASPM: Could not configure common clock\n"); - list_for_each_entry(child, &linkbus->devices, bus_list) - pcie_capability_write_word(child, PCI_EXP_LNKCTL, - child_reg[PCI_FUNC(child->devfn)]); - pcie_capability_write_word(parent, PCI_EXP_LNKCTL, parent_reg); + list_for_each_entry(child, &linkbus->devices, bus_list) { + cpos = pci_pcie_cap(child); + pci_write_config_word(child, cpos + PCI_EXP_LNKCTL, + child_reg[PCI_FUNC(child->devfn)]); + } + pci_write_config_word(parent, ppos + PCI_EXP_LNKCTL, parent_reg); } /* Convert L0s latency encoding to ns */ @@ -292,14 +305,16 @@ struct aspm_register_info { static void pcie_get_aspm_reg(struct pci_dev *pdev, struct aspm_register_info *info) { + int pos; u16 reg16; u32 reg32; - pcie_capability_read_dword(pdev, PCI_EXP_LNKCAP, ®32); + pos = pci_pcie_cap(pdev); + pci_read_config_dword(pdev, pos + PCI_EXP_LNKCAP, ®32); info->support = (reg32 & PCI_EXP_LNKCAP_ASPMS) >> 10; info->latency_encoding_l0s = (reg32 & PCI_EXP_LNKCAP_L0SEL) >> 12; info->latency_encoding_l1 = (reg32 & PCI_EXP_LNKCAP_L1EL) >> 15; - pcie_capability_read_word(pdev, PCI_EXP_LNKCTL, ®16); + pci_read_config_word(pdev, pos + PCI_EXP_LNKCTL, ®16); info->enabled = reg16 & PCI_EXP_LNKCTL_ASPMC; } @@ -397,7 +412,7 @@ static void pcie_aspm_cap_init(struct pcie_link_state *link, int blacklist) * do ASPM for now. */ list_for_each_entry(child, &linkbus->devices, bus_list) { - if (pci_pcie_type(child) == PCI_EXP_TYPE_PCI_BRIDGE) { + if (child->pcie_type == PCI_EXP_TYPE_PCI_BRIDGE) { link->aspm_disable = ASPM_STATE_ALL; break; } @@ -405,15 +420,17 @@ static void pcie_aspm_cap_init(struct pcie_link_state *link, int blacklist) /* Get and check endpoint acceptable latencies */ list_for_each_entry(child, &linkbus->devices, bus_list) { + int pos; u32 reg32, encoding; struct aspm_latency *acceptable = &link->acceptable[PCI_FUNC(child->devfn)]; - if (pci_pcie_type(child) != PCI_EXP_TYPE_ENDPOINT && - pci_pcie_type(child) != PCI_EXP_TYPE_LEG_END) + if (child->pcie_type != PCI_EXP_TYPE_ENDPOINT && + child->pcie_type != PCI_EXP_TYPE_LEG_END) continue; - pcie_capability_read_dword(child, PCI_EXP_DEVCAP, ®32); + pos = pci_pcie_cap(child); + pci_read_config_dword(child, pos + PCI_EXP_DEVCAP, ®32); /* Calculate endpoint L0s acceptable latency */ encoding = (reg32 & PCI_EXP_DEVCAP_L0S) >> 6; acceptable->l0s = calc_l0s_acceptable(encoding); @@ -427,7 +444,13 @@ static void pcie_aspm_cap_init(struct pcie_link_state *link, int blacklist) static void pcie_config_aspm_dev(struct pci_dev *pdev, u32 val) { - pcie_capability_clear_and_set_word(pdev, PCI_EXP_LNKCTL, 0x3, val); + u16 reg16; + int pos = pci_pcie_cap(pdev); + + pci_read_config_word(pdev, pos + PCI_EXP_LNKCTL, ®16); + reg16 &= ~0x3; + reg16 |= val; + pci_write_config_word(pdev, pos + PCI_EXP_LNKCTL, reg16); } static void pcie_config_aspm_link(struct pcie_link_state *link, u32 state) @@ -482,6 +505,7 @@ static void free_link_state(struct pcie_link_state *link) static int pcie_aspm_sanity_check(struct pci_dev *pdev) { struct pci_dev *child; + int pos; u32 reg32; /* @@ -489,7 +513,8 @@ static int pcie_aspm_sanity_check(struct pci_dev *pdev) * very strange. Disable ASPM for the whole slot */ list_for_each_entry(child, &pdev->subordinate->devices, bus_list) { - if (!pci_is_pcie(child)) + pos = pci_pcie_cap(child); + if (!pos) return -EINVAL; /* @@ -505,7 +530,7 @@ static int pcie_aspm_sanity_check(struct pci_dev *pdev) * Disable ASPM for pre-1.1 PCIe device, we follow MS to use * RBER bit to determine if a function is 1.1 version device */ - pcie_capability_read_dword(child, PCI_EXP_DEVCAP, ®32); + pci_read_config_dword(child, pos + PCI_EXP_DEVCAP, ®32); if (!(reg32 & PCI_EXP_DEVCAP_RBER) && !aspm_force) { dev_printk(KERN_INFO, &child->dev, "disabling ASPM" " on pre-1.1 PCIe device. You can enable it" @@ -527,7 +552,7 @@ static struct pcie_link_state *alloc_pcie_link_state(struct pci_dev *pdev) INIT_LIST_HEAD(&link->children); INIT_LIST_HEAD(&link->link); link->pdev = pdev; - if (pci_pcie_type(pdev) == PCI_EXP_TYPE_DOWNSTREAM) { + if (pdev->pcie_type == PCI_EXP_TYPE_DOWNSTREAM) { struct pcie_link_state *parent; parent = pdev->bus->parent->self->link_state; if (!parent) { @@ -560,12 +585,12 @@ void pcie_aspm_init_link_state(struct pci_dev *pdev) if (!pci_is_pcie(pdev) || pdev->link_state) return; - if (pci_pcie_type(pdev) != PCI_EXP_TYPE_ROOT_PORT && - pci_pcie_type(pdev) != PCI_EXP_TYPE_DOWNSTREAM) + if (pdev->pcie_type != PCI_EXP_TYPE_ROOT_PORT && + pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM) return; /* VIA has a strange chipset, root port is under a bridge */ - if (pci_pcie_type(pdev) == PCI_EXP_TYPE_ROOT_PORT && + if (pdev->pcie_type == PCI_EXP_TYPE_ROOT_PORT && pdev->bus->self) return; @@ -622,8 +647,8 @@ static void pcie_update_aspm_capable(struct pcie_link_state *root) if (link->root != root) continue; list_for_each_entry(child, &linkbus->devices, bus_list) { - if ((pci_pcie_type(child) != PCI_EXP_TYPE_ENDPOINT) && - (pci_pcie_type(child) != PCI_EXP_TYPE_LEG_END)) + if ((child->pcie_type != PCI_EXP_TYPE_ENDPOINT) && + (child->pcie_type != PCI_EXP_TYPE_LEG_END)) continue; pcie_aspm_check_latency(child); } @@ -638,8 +663,8 @@ void pcie_aspm_exit_link_state(struct pci_dev *pdev) if (!pci_is_pcie(pdev) || !parent || !parent->link_state) return; - if ((pci_pcie_type(parent) != PCI_EXP_TYPE_ROOT_PORT) && - (pci_pcie_type(parent) != PCI_EXP_TYPE_DOWNSTREAM)) + if ((parent->pcie_type != PCI_EXP_TYPE_ROOT_PORT) && + (parent->pcie_type != PCI_EXP_TYPE_DOWNSTREAM)) return; down_read(&pci_bus_sem); @@ -679,8 +704,8 @@ void pcie_aspm_pm_state_change(struct pci_dev *pdev) if (aspm_disabled || !pci_is_pcie(pdev) || !link) return; - if ((pci_pcie_type(pdev) != PCI_EXP_TYPE_ROOT_PORT) && - (pci_pcie_type(pdev) != PCI_EXP_TYPE_DOWNSTREAM)) + if ((pdev->pcie_type != PCI_EXP_TYPE_ROOT_PORT) && + (pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM)) return; /* * Devices changed PM state, we should recheck if latency @@ -704,8 +729,8 @@ void pcie_aspm_powersave_config_link(struct pci_dev *pdev) if (aspm_policy != POLICY_POWERSAVE) return; - if ((pci_pcie_type(pdev) != PCI_EXP_TYPE_ROOT_PORT) && - (pci_pcie_type(pdev) != PCI_EXP_TYPE_DOWNSTREAM)) + if ((pdev->pcie_type != PCI_EXP_TYPE_ROOT_PORT) && + (pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM)) return; down_read(&pci_bus_sem); @@ -732,8 +757,8 @@ static void __pci_disable_link_state(struct pci_dev *pdev, int state, bool sem, if (!pci_is_pcie(pdev)) return; - if (pci_pcie_type(pdev) == PCI_EXP_TYPE_ROOT_PORT || - pci_pcie_type(pdev) == PCI_EXP_TYPE_DOWNSTREAM) + if (pdev->pcie_type == PCI_EXP_TYPE_ROOT_PORT || + pdev->pcie_type == PCI_EXP_TYPE_DOWNSTREAM) parent = pdev; if (!parent || !parent->link_state) return; @@ -908,8 +933,8 @@ void pcie_aspm_create_sysfs_dev_files(struct pci_dev *pdev) struct pcie_link_state *link_state = pdev->link_state; if (!pci_is_pcie(pdev) || - (pci_pcie_type(pdev) != PCI_EXP_TYPE_ROOT_PORT && - pci_pcie_type(pdev) != PCI_EXP_TYPE_DOWNSTREAM) || !link_state) + (pdev->pcie_type != PCI_EXP_TYPE_ROOT_PORT && + pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM) || !link_state) return; if (link_state->aspm_support) @@ -925,8 +950,8 @@ void pcie_aspm_remove_sysfs_dev_files(struct pci_dev *pdev) struct pcie_link_state *link_state = pdev->link_state; if (!pci_is_pcie(pdev) || - (pci_pcie_type(pdev) != PCI_EXP_TYPE_ROOT_PORT && - pci_pcie_type(pdev) != PCI_EXP_TYPE_DOWNSTREAM) || !link_state) + (pdev->pcie_type != PCI_EXP_TYPE_ROOT_PORT && + pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM) || !link_state) return; if (link_state->aspm_support) diff --git a/trunk/drivers/pci/pcie/pme.c b/trunk/drivers/pci/pcie/pme.c index 9ca0dc9ffd84..001f1b78f39c 100644 --- a/trunk/drivers/pci/pcie/pme.c +++ b/trunk/drivers/pci/pcie/pme.c @@ -57,12 +57,17 @@ struct pcie_pme_service_data { */ void pcie_pme_interrupt_enable(struct pci_dev *dev, bool enable) { + int rtctl_pos; + u16 rtctl; + + rtctl_pos = pci_pcie_cap(dev) + PCI_EXP_RTCTL; + + pci_read_config_word(dev, rtctl_pos, &rtctl); if (enable) - pcie_capability_set_word(dev, PCI_EXP_RTCTL, - PCI_EXP_RTCTL_PMEIE); + rtctl |= PCI_EXP_RTCTL_PMEIE; else - pcie_capability_clear_word(dev, PCI_EXP_RTCTL, - PCI_EXP_RTCTL_PMEIE); + rtctl &= ~PCI_EXP_RTCTL_PMEIE; + pci_write_config_word(dev, rtctl_pos, rtctl); } /** @@ -115,7 +120,7 @@ static bool pcie_pme_from_pci_bridge(struct pci_bus *bus, u8 devfn) if (!dev) return false; - if (pci_is_pcie(dev) && pci_pcie_type(dev) == PCI_EXP_TYPE_PCI_BRIDGE) { + if (pci_is_pcie(dev) && dev->pcie_type == PCI_EXP_TYPE_PCI_BRIDGE) { down_read(&pci_bus_sem); if (pcie_pme_walk_bus(bus)) found = true; @@ -221,15 +226,18 @@ static void pcie_pme_work_fn(struct work_struct *work) struct pcie_pme_service_data *data = container_of(work, struct pcie_pme_service_data, work); struct pci_dev *port = data->srv->port; + int rtsta_pos; u32 rtsta; + rtsta_pos = pci_pcie_cap(port) + PCI_EXP_RTSTA; + spin_lock_irq(&data->lock); for (;;) { if (data->noirq) break; - pcie_capability_read_dword(port, PCI_EXP_RTSTA, &rtsta); + pci_read_config_dword(port, rtsta_pos, &rtsta); if (rtsta & PCI_EXP_RTSTA_PME) { /* * Clear PME status of the port. If there are other @@ -268,14 +276,17 @@ static irqreturn_t pcie_pme_irq(int irq, void *context) { struct pci_dev *port; struct pcie_pme_service_data *data; + int rtsta_pos; u32 rtsta; unsigned long flags; port = ((struct pcie_device *)context)->port; data = get_service_data((struct pcie_device *)context); + rtsta_pos = pci_pcie_cap(port) + PCI_EXP_RTSTA; + spin_lock_irqsave(&data->lock, flags); - pcie_capability_read_dword(port, PCI_EXP_RTSTA, &rtsta); + pci_read_config_dword(port, rtsta_pos, &rtsta); if (!(rtsta & PCI_EXP_RTSTA_PME)) { spin_unlock_irqrestore(&data->lock, flags); @@ -324,13 +335,13 @@ static void pcie_pme_mark_devices(struct pci_dev *port) struct pci_dev *dev; /* Check if this is a root port event collector. */ - if (pci_pcie_type(port) != PCI_EXP_TYPE_RC_EC || !bus) + if (port->pcie_type != PCI_EXP_TYPE_RC_EC || !bus) return; down_read(&pci_bus_sem); list_for_each_entry(dev, &bus->devices, bus_list) if (pci_is_pcie(dev) - && pci_pcie_type(dev) == PCI_EXP_TYPE_RC_END) + && dev->pcie_type == PCI_EXP_TYPE_RC_END) pcie_pme_set_native(dev, NULL); up_read(&pci_bus_sem); } diff --git a/trunk/drivers/pci/pcie/portdrv_bus.c b/trunk/drivers/pci/pcie/portdrv_bus.c index 67be55a7f260..18bf90f748f6 100644 --- a/trunk/drivers/pci/pcie/portdrv_bus.c +++ b/trunk/drivers/pci/pcie/portdrv_bus.c @@ -38,7 +38,7 @@ static int pcie_port_bus_match(struct device *dev, struct device_driver *drv) return 0; if ((driver->port_type != PCIE_ANY_PORT) && - (driver->port_type != pci_pcie_type(pciedev->port))) + (driver->port_type != pciedev->port->pcie_type)) return 0; return 1; diff --git a/trunk/drivers/pci/pcie/portdrv_core.c b/trunk/drivers/pci/pcie/portdrv_core.c index d03a7a39b2d8..75915b30ad19 100644 --- a/trunk/drivers/pci/pcie/portdrv_core.c +++ b/trunk/drivers/pci/pcie/portdrv_core.c @@ -200,13 +200,10 @@ static int init_service_irqs(struct pci_dev *dev, int *irqs, int mask) { int i, irq = -1; - /* - * If MSI cannot be used for PCIe PME or hotplug, we have to use - * INTx or other interrupts, e.g. system shared interrupt. - */ + /* We have to use INTx if MSI cannot be used for PCIe PME or pciehp. */ if (((mask & PCIE_PORT_SERVICE_PME) && pcie_pme_no_msi()) || ((mask & PCIE_PORT_SERVICE_HP) && pciehp_no_msi())) { - if (dev->irq) + if (dev->pin) irq = dev->irq; goto no_msi; } @@ -215,12 +212,8 @@ static int init_service_irqs(struct pci_dev *dev, int *irqs, int mask) if (!pcie_port_enable_msix(dev, irqs, mask)) return 0; - /* - * We're not going to use MSI-X, so try MSI and fall back to INTx. - * If neither MSI/MSI-X nor INTx available, try other interrupt. On - * some platforms, root port doesn't support MSI/MSI-X/INTx in RC mode. - */ - if (!pci_enable_msi(dev) || dev->irq) + /* We're not going to use MSI-X, so try MSI and fall back to INTx */ + if (!pci_enable_msi(dev) || dev->pin) irq = dev->irq; no_msi: @@ -253,7 +246,8 @@ static void cleanup_service_irqs(struct pci_dev *dev) */ static int get_port_device_capability(struct pci_dev *dev) { - int services = 0; + int services = 0, pos; + u16 reg16; u32 reg32; int cap_mask = 0; int err; @@ -271,9 +265,11 @@ static int get_port_device_capability(struct pci_dev *dev) return 0; } + pos = pci_pcie_cap(dev); + pci_read_config_word(dev, pos + PCI_EXP_FLAGS, ®16); /* Hot-Plug Capable */ - if (cap_mask & PCIE_PORT_SERVICE_HP) { - pcie_capability_read_dword(dev, PCI_EXP_SLTCAP, ®32); + if ((cap_mask & PCIE_PORT_SERVICE_HP) && (reg16 & PCI_EXP_FLAGS_SLOT)) { + pci_read_config_dword(dev, pos + PCI_EXP_SLTCAP, ®32); if (reg32 & PCI_EXP_SLTCAP_HPC) { services |= PCIE_PORT_SERVICE_HP; /* @@ -281,8 +277,10 @@ static int get_port_device_capability(struct pci_dev *dev) * enabled by the BIOS and the hot-plug service driver * is not loaded. */ - pcie_capability_clear_word(dev, PCI_EXP_SLTCTL, - PCI_EXP_SLTCTL_CCIE | PCI_EXP_SLTCTL_HPIE); + pos += PCI_EXP_SLTCTL; + pci_read_config_word(dev, pos, ®16); + reg16 &= ~(PCI_EXP_SLTCTL_CCIE | PCI_EXP_SLTCTL_HPIE); + pci_write_config_word(dev, pos, reg16); } } /* AER capable */ @@ -300,7 +298,7 @@ static int get_port_device_capability(struct pci_dev *dev) services |= PCIE_PORT_SERVICE_VC; /* Root ports are capable of generating PME too */ if ((cap_mask & PCIE_PORT_SERVICE_PME) - && pci_pcie_type(dev) == PCI_EXP_TYPE_ROOT_PORT) { + && dev->pcie_type == PCI_EXP_TYPE_ROOT_PORT) { services |= PCIE_PORT_SERVICE_PME; /* * Disable PME interrupt on this port in case it's been enabled @@ -338,7 +336,7 @@ static int pcie_device_init(struct pci_dev *pdev, int service, int irq) device->release = release_pcie_device; /* callback to free pcie dev */ dev_set_name(device, "%s:pcie%02x", pci_name(pdev), - get_descriptor_id(pci_pcie_type(pdev), service)); + get_descriptor_id(pdev->pcie_type, service)); device->parent = &pdev->dev; device_enable_async_suspend(device); diff --git a/trunk/drivers/pci/pcie/portdrv_pci.c b/trunk/drivers/pci/pcie/portdrv_pci.c index 0761d90ca279..3a7eefcb270a 100644 --- a/trunk/drivers/pci/pcie/portdrv_pci.c +++ b/trunk/drivers/pci/pcie/portdrv_pci.c @@ -64,7 +64,14 @@ __setup("pcie_ports=", pcie_port_setup); */ void pcie_clear_root_pme_status(struct pci_dev *dev) { - pcie_capability_set_dword(dev, PCI_EXP_RTSTA, PCI_EXP_RTSTA_PME); + int rtsta_pos; + u32 rtsta; + + rtsta_pos = pci_pcie_cap(dev) + PCI_EXP_RTSTA; + + pci_read_config_dword(dev, rtsta_pos, &rtsta); + rtsta |= PCI_EXP_RTSTA_PME; + pci_write_config_dword(dev, rtsta_pos, rtsta); } static int pcie_portdrv_restore_config(struct pci_dev *dev) @@ -88,7 +95,7 @@ static int pcie_port_resume_noirq(struct device *dev) * which breaks ACPI-based runtime wakeup on PCI Express, so clear those * bits now just in case (shouldn't hurt). */ - if (pci_pcie_type(pdev) == PCI_EXP_TYPE_ROOT_PORT) + if(pdev->pcie_type == PCI_EXP_TYPE_ROOT_PORT) pcie_clear_root_pme_status(pdev); return 0; } @@ -133,17 +140,9 @@ static int pcie_port_runtime_resume(struct device *dev) { return 0; } - -static int pcie_port_runtime_idle(struct device *dev) -{ - /* Delay for a short while to prevent too frequent suspend/resume */ - pm_schedule_suspend(dev, 10); - return -EBUSY; -} #else #define pcie_port_runtime_suspend NULL #define pcie_port_runtime_resume NULL -#define pcie_port_runtime_idle NULL #endif static const struct dev_pm_ops pcie_portdrv_pm_ops = { @@ -156,7 +155,6 @@ static const struct dev_pm_ops pcie_portdrv_pm_ops = { .resume_noirq = pcie_port_resume_noirq, .runtime_suspend = pcie_port_runtime_suspend, .runtime_resume = pcie_port_runtime_resume, - .runtime_idle = pcie_port_runtime_idle, }; #define PCIE_PORTDRV_PM_OPS (&pcie_portdrv_pm_ops) @@ -188,9 +186,9 @@ static int __devinit pcie_portdrv_probe(struct pci_dev *dev, int status; if (!pci_is_pcie(dev) || - ((pci_pcie_type(dev) != PCI_EXP_TYPE_ROOT_PORT) && - (pci_pcie_type(dev) != PCI_EXP_TYPE_UPSTREAM) && - (pci_pcie_type(dev) != PCI_EXP_TYPE_DOWNSTREAM))) + ((dev->pcie_type != PCI_EXP_TYPE_ROOT_PORT) && + (dev->pcie_type != PCI_EXP_TYPE_UPSTREAM) && + (dev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM))) return -ENODEV; if (!dev->irq && dev->pin) { @@ -202,11 +200,6 @@ static int __devinit pcie_portdrv_probe(struct pci_dev *dev, return status; pci_save_state(dev); - /* - * D3cold may not work properly on some PCIe port, so disable - * it by default. - */ - dev->d3cold_allowed = false; if (!pci_match_id(port_runtime_pm_black_list, dev)) pm_runtime_put_noidle(&dev->dev); @@ -378,11 +371,11 @@ static const struct pci_device_id port_pci_ids[] = { { }; MODULE_DEVICE_TABLE(pci, port_pci_ids); -static const struct pci_error_handlers pcie_portdrv_err_handler = { - .error_detected = pcie_portdrv_error_detected, - .mmio_enabled = pcie_portdrv_mmio_enabled, - .slot_reset = pcie_portdrv_slot_reset, - .resume = pcie_portdrv_err_resume, +static struct pci_error_handlers pcie_portdrv_err_handler = { + .error_detected = pcie_portdrv_error_detected, + .mmio_enabled = pcie_portdrv_mmio_enabled, + .slot_reset = pcie_portdrv_slot_reset, + .resume = pcie_portdrv_err_resume, }; static struct pci_driver pcie_portdriver = { diff --git a/trunk/drivers/pci/probe.c b/trunk/drivers/pci/probe.c index ec909afa90b6..6c143b4497ca 100644 --- a/trunk/drivers/pci/probe.c +++ b/trunk/drivers/pci/probe.c @@ -144,13 +144,15 @@ static inline unsigned long decode_bar(struct pci_dev *dev, u32 bar) case PCI_BASE_ADDRESS_MEM_TYPE_32: break; case PCI_BASE_ADDRESS_MEM_TYPE_1M: - /* 1M mem BAR treated as 32-bit BAR */ + dev_info(&dev->dev, "1M mem BAR treated as 32-bit BAR\n"); break; case PCI_BASE_ADDRESS_MEM_TYPE_64: flags |= IORESOURCE_MEM_64; break; default: - /* mem unknown type treated as 32-bit BAR */ + dev_warn(&dev->dev, + "mem unknown type %x treated as 32-bit BAR\n", + mem_type); break; } return flags; @@ -171,11 +173,9 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type, u32 l, sz, mask; u16 orig_cmd; struct pci_bus_region region; - bool bar_too_big = false, bar_disabled = false; mask = type ? PCI_ROM_ADDRESS_MASK : ~0; - /* No printks while decoding is disabled! */ if (!dev->mmio_always_on) { pci_read_config_word(dev, PCI_COMMAND, &orig_cmd); pci_write_config_word(dev, PCI_COMMAND, @@ -240,7 +240,8 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type, goto fail; if ((sizeof(resource_size_t) < 8) && (sz64 > 0x100000000ULL)) { - bar_too_big = true; + dev_err(&dev->dev, "reg %x: can't handle 64-bit BAR\n", + pos); goto fail; } @@ -251,11 +252,12 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type, region.start = 0; region.end = sz64; pcibios_bus_to_resource(dev, res, ®ion); - bar_disabled = true; } else { region.start = l64; region.end = l64 + sz64; pcibios_bus_to_resource(dev, res, ®ion); + dev_printk(KERN_DEBUG, &dev->dev, "reg %x: %pR\n", + pos, res); } } else { sz = pci_size(l, sz, mask); @@ -266,23 +268,18 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type, region.start = l; region.end = l + sz; pcibios_bus_to_resource(dev, res, ®ion); - } - - goto out; + dev_printk(KERN_DEBUG, &dev->dev, "reg %x: %pR\n", pos, res); + } -fail: - res->flags = 0; -out: + out: if (!dev->mmio_always_on) pci_write_config_word(dev, PCI_COMMAND, orig_cmd); - if (bar_too_big) - dev_err(&dev->dev, "reg %x: can't handle 64-bit BAR\n", pos); - if (res->flags && !bar_disabled) - dev_printk(KERN_DEBUG, &dev->dev, "reg %x: %pR\n", pos, res); - return (res->flags & IORESOURCE_MEM_64) ? 1 : 0; + fail: + res->flags = 0; + goto out; } static void pci_read_bases(struct pci_dev *dev, unsigned int howmany, int rom) @@ -606,10 +603,10 @@ static void pci_set_bus_speed(struct pci_bus *bus) u32 linkcap; u16 linksta; - pcie_capability_read_dword(bridge, PCI_EXP_LNKCAP, &linkcap); + pci_read_config_dword(bridge, pos + PCI_EXP_LNKCAP, &linkcap); bus->max_bus_speed = pcie_link_speed[linkcap & 0xf]; - pcie_capability_read_word(bridge, PCI_EXP_LNKSTA, &linksta); + pci_read_config_word(bridge, pos + PCI_EXP_LNKSTA, &linksta); pcie_update_link_speed(bus, linksta); } } @@ -729,10 +726,8 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max, /* Check if setup is sensible at all */ if (!pass && - (primary != bus->number || secondary <= bus->number || - secondary > subordinate)) { - dev_info(&dev->dev, "bridge configuration invalid ([bus %02x-%02x]), reconfiguring\n", - secondary, subordinate); + (primary != bus->number || secondary <= bus->number)) { + dev_dbg(&dev->dev, "bus configuration invalid, reconfiguring\n"); broken = 1; } @@ -934,16 +929,24 @@ void set_pcie_port_type(struct pci_dev *pdev) pdev->is_pcie = 1; pdev->pcie_cap = pos; pci_read_config_word(pdev, pos + PCI_EXP_FLAGS, ®16); - pdev->pcie_flags_reg = reg16; + pdev->pcie_type = (reg16 & PCI_EXP_FLAGS_TYPE) >> 4; pci_read_config_word(pdev, pos + PCI_EXP_DEVCAP, ®16); pdev->pcie_mpss = reg16 & PCI_EXP_DEVCAP_PAYLOAD; } void set_pcie_hotplug_bridge(struct pci_dev *pdev) { + int pos; + u16 reg16; u32 reg32; - pcie_capability_read_dword(pdev, PCI_EXP_SLTCAP, ®32); + pos = pci_pcie_cap(pdev); + if (!pos) + return; + pci_read_config_word(pdev, pos + PCI_EXP_FLAGS, ®16); + if (!(reg16 & PCI_EXP_FLAGS_SLOT)) + return; + pci_read_config_dword(pdev, pos + PCI_EXP_SLTCAP, ®32); if (reg32 & PCI_EXP_SLTCAP_HPC) pdev->is_hotplug_bridge = 1; } @@ -1157,7 +1160,8 @@ int pci_cfg_space_size(struct pci_dev *dev) if (class == PCI_CLASS_BRIDGE_HOST) return pci_cfg_space_size_ext(dev); - if (!pci_is_pcie(dev)) { + pos = pci_pcie_cap(dev); + if (!pos) { pos = pci_find_capability(dev, PCI_CAP_ID_PCIX); if (!pos) goto fail; @@ -1379,9 +1383,9 @@ static int only_one_child(struct pci_bus *bus) if (!parent || !pci_is_pcie(parent)) return 0; - if (pci_pcie_type(parent) == PCI_EXP_TYPE_ROOT_PORT) + if (parent->pcie_type == PCI_EXP_TYPE_ROOT_PORT) return 1; - if (pci_pcie_type(parent) == PCI_EXP_TYPE_DOWNSTREAM && + if (parent->pcie_type == PCI_EXP_TYPE_DOWNSTREAM && !pci_has_flag(PCI_SCAN_ALL_PCIE_DEVS)) return 1; return 0; @@ -1458,7 +1462,7 @@ static int pcie_find_smpss(struct pci_dev *dev, void *data) */ if (dev->is_hotplug_bridge && (!list_is_singular(&dev->bus->devices) || (dev->bus->self && - pci_pcie_type(dev->bus->self) != PCI_EXP_TYPE_ROOT_PORT))) + dev->bus->self->pcie_type != PCI_EXP_TYPE_ROOT_PORT))) *smpss = 0; if (*smpss > dev->pcie_mpss) @@ -1474,8 +1478,7 @@ static void pcie_write_mps(struct pci_dev *dev, int mps) if (pcie_bus_config == PCIE_BUS_PERFORMANCE) { mps = 128 << dev->pcie_mpss; - if (pci_pcie_type(dev) != PCI_EXP_TYPE_ROOT_PORT && - dev->bus->self) + if (dev->pcie_type != PCI_EXP_TYPE_ROOT_PORT && dev->bus->self) /* For "Performance", the assumption is made that * downstream communication will never be larger than * the MRRS. So, the MPS only needs to be configured @@ -1750,6 +1753,11 @@ int pci_bus_insert_busn_res(struct pci_bus *b, int bus, int bus_max) "busn_res: can not insert %pR under %s%pR (conflicts with %s %pR)\n", res, pci_is_root_bus(b) ? "domain " : "", parent_res, conflict->name, conflict); + else + dev_printk(KERN_DEBUG, &b->dev, + "busn_res: %pR is inserted under %s%pR\n", + res, pci_is_root_bus(b) ? "domain " : "", + parent_res); return conflict == NULL; } diff --git a/trunk/drivers/pci/proc.c b/trunk/drivers/pci/proc.c index eb907a8faf2a..27911b55c2a5 100644 --- a/trunk/drivers/pci/proc.c +++ b/trunk/drivers/pci/proc.c @@ -434,6 +434,25 @@ int pci_proc_detach_device(struct pci_dev *dev) return 0; } +#if 0 +int pci_proc_attach_bus(struct pci_bus* bus) +{ + struct proc_dir_entry *de = bus->procdir; + + if (!proc_initialized) + return -EACCES; + + if (!de) { + char name[16]; + sprintf(name, "%02x", bus->number); + de = bus->procdir = proc_mkdir(name, proc_bus_pci_dir); + if (!de) + return -ENOMEM; + } + return 0; +} +#endif /* 0 */ + int pci_proc_detach_bus(struct pci_bus* bus) { struct proc_dir_entry *de = bus->procdir; diff --git a/trunk/drivers/pci/quirks.c b/trunk/drivers/pci/quirks.c index 7a451ff56ecc..51553179e967 100644 --- a/trunk/drivers/pci/quirks.c +++ b/trunk/drivers/pci/quirks.c @@ -3081,36 +3081,17 @@ static int reset_intel_generic_dev(struct pci_dev *dev, int probe) static int reset_intel_82599_sfp_virtfn(struct pci_dev *dev, int probe) { - int i; - u16 status; + int pos; - /* - * http://www.intel.com/content/dam/doc/datasheet/82599-10-gbe-controller-datasheet.pdf - * - * The 82599 supports FLR on VFs, but FLR support is reported only - * in the PF DEVCAP (sec 9.3.10.4), not in the VF DEVCAP (sec 9.5). - * Therefore, we can't use pcie_flr(), which checks the VF DEVCAP. - */ + pos = pci_find_capability(dev, PCI_CAP_ID_EXP); + if (!pos) + return -ENOTTY; if (probe) return 0; - /* Wait for Transaction Pending bit clean */ - for (i = 0; i < 4; i++) { - if (i) - msleep((1 << (i - 1)) * 100); - - pcie_capability_read_word(dev, PCI_EXP_DEVSTA, &status); - if (!(status & PCI_EXP_DEVSTA_TRPND)) - goto clear; - } - - dev_err(&dev->dev, "transaction is not cleared; " - "proceeding with reset anyway\n"); - -clear: - pcie_capability_set_word(dev, PCI_EXP_DEVCTL, PCI_EXP_DEVCTL_BCR_FLR); - + pci_write_config_word(dev, pos + PCI_EXP_DEVCTL, + PCI_EXP_DEVCTL_BCR_FLR); msleep(100); return 0; diff --git a/trunk/drivers/pci/remove.c b/trunk/drivers/pci/remove.c index 513972f3ed13..04a4861b4749 100644 --- a/trunk/drivers/pci/remove.c +++ b/trunk/drivers/pci/remove.c @@ -32,82 +32,152 @@ static void pci_stop_dev(struct pci_dev *dev) static void pci_destroy_dev(struct pci_dev *dev) { + /* Remove the device from the device lists, and prevent any further + * list accesses from this device */ down_write(&pci_bus_sem); list_del(&dev->bus_list); + dev->bus_list.next = dev->bus_list.prev = NULL; up_write(&pci_bus_sem); pci_free_resources(dev); pci_dev_put(dev); } -void pci_remove_bus(struct pci_bus *bus) +/** + * pci_remove_device_safe - remove an unused hotplug device + * @dev: the device to remove + * + * Delete the device structure from the device lists and + * notify userspace (/sbin/hotplug), but only if the device + * in question is not being used by a driver. + * Returns 0 on success. + */ +#if 0 +int pci_remove_device_safe(struct pci_dev *dev) +{ + if (pci_dev_driver(dev)) + return -EBUSY; + pci_destroy_dev(dev); + return 0; +} +#endif /* 0 */ + +void pci_remove_bus(struct pci_bus *pci_bus) { - pci_proc_detach_bus(bus); + pci_proc_detach_bus(pci_bus); down_write(&pci_bus_sem); - list_del(&bus->node); - pci_bus_release_busn_res(bus); + list_del(&pci_bus->node); + pci_bus_release_busn_res(pci_bus); up_write(&pci_bus_sem); - if (!bus->is_added) + if (!pci_bus->is_added) return; - pci_remove_legacy_files(bus); - device_unregister(&bus->dev); + pci_remove_legacy_files(pci_bus); + device_unregister(&pci_bus->dev); } EXPORT_SYMBOL(pci_remove_bus); -static void pci_stop_bus_device(struct pci_dev *dev) +static void __pci_remove_behind_bridge(struct pci_dev *dev); +/** + * pci_stop_and_remove_bus_device - remove a PCI device and any children + * @dev: the device to remove + * + * Remove a PCI device from the device lists, informing the drivers + * that the device has been removed. We also remove any subordinate + * buses and children in a depth-first manner. + * + * For each device we remove, delete the device structure from the + * device lists, remove the /proc entry, and notify userspace + * (/sbin/hotplug). + */ +void __pci_remove_bus_device(struct pci_dev *dev) { - struct pci_bus *bus = dev->subordinate; - struct pci_dev *child, *tmp; + if (dev->subordinate) { + struct pci_bus *b = dev->subordinate; - /* - * Stopping an SR-IOV PF device removes all the associated VFs, - * which will update the bus->devices list and confuse the - * iterator. Therefore, iterate in reverse so we remove the VFs - * first, then the PF. - */ - if (bus) { - list_for_each_entry_safe_reverse(child, tmp, - &bus->devices, bus_list) - pci_stop_bus_device(child); + __pci_remove_behind_bridge(dev); + pci_remove_bus(b); + dev->subordinate = NULL; } - pci_stop_dev(dev); + pci_destroy_dev(dev); } +EXPORT_SYMBOL(__pci_remove_bus_device); -static void pci_remove_bus_device(struct pci_dev *dev) +void pci_stop_and_remove_bus_device(struct pci_dev *dev) { - struct pci_bus *bus = dev->subordinate; - struct pci_dev *child, *tmp; + pci_stop_bus_device(dev); + __pci_remove_bus_device(dev); +} - if (bus) { - list_for_each_entry_safe(child, tmp, - &bus->devices, bus_list) - pci_remove_bus_device(child); +static void __pci_remove_behind_bridge(struct pci_dev *dev) +{ + struct list_head *l, *n; - pci_remove_bus(bus); - dev->subordinate = NULL; - } + if (dev->subordinate) + list_for_each_safe(l, n, &dev->subordinate->devices) + __pci_remove_bus_device(pci_dev_b(l)); +} - pci_destroy_dev(dev); +static void pci_stop_behind_bridge(struct pci_dev *dev) +{ + struct list_head *l, *n; + + if (dev->subordinate) + list_for_each_safe(l, n, &dev->subordinate->devices) + pci_stop_bus_device(pci_dev_b(l)); } /** - * pci_stop_and_remove_bus_device - remove a PCI device and any children - * @dev: the device to remove + * pci_stop_and_remove_behind_bridge - stop and remove all devices behind + * a PCI bridge + * @dev: PCI bridge device * - * Remove a PCI device from the device lists, informing the drivers - * that the device has been removed. We also remove any subordinate - * buses and children in a depth-first manner. + * Remove all devices on the bus, except for the parent bridge. + * This also removes any child buses, and any devices they may + * contain in a depth-first manner. + */ +void pci_stop_and_remove_behind_bridge(struct pci_dev *dev) +{ + pci_stop_behind_bridge(dev); + __pci_remove_behind_bridge(dev); +} + +static void pci_stop_bus_devices(struct pci_bus *bus) +{ + struct list_head *l, *n; + + /* + * VFs could be removed by pci_stop_and_remove_bus_device() in the + * pci_stop_bus_devices() code path for PF. + * aka, bus->devices get updated in the process. + * but VFs are inserted after PFs when SRIOV is enabled for PF, + * We can iterate the list backwards to get prev valid PF instead + * of removed VF. + */ + list_for_each_prev_safe(l, n, &bus->devices) { + struct pci_dev *dev = pci_dev_b(l); + pci_stop_bus_device(dev); + } +} + +/** + * pci_stop_bus_device - stop a PCI device and any children + * @dev: the device to stop * - * For each device we remove, delete the device structure from the - * device lists, remove the /proc entry, and notify userspace - * (/sbin/hotplug). + * Stop a PCI device (detach the driver, remove from the global list + * and so on). This also stop any subordinate buses and children in a + * depth-first manner. */ -void pci_stop_and_remove_bus_device(struct pci_dev *dev) +void pci_stop_bus_device(struct pci_dev *dev) { - pci_stop_bus_device(dev); - pci_remove_bus_device(dev); + if (dev->subordinate) + pci_stop_bus_devices(dev->subordinate); + + pci_stop_dev(dev); } + EXPORT_SYMBOL(pci_stop_and_remove_bus_device); +EXPORT_SYMBOL(pci_stop_and_remove_behind_bridge); +EXPORT_SYMBOL_GPL(pci_stop_bus_device); diff --git a/trunk/drivers/pci/rom.c b/trunk/drivers/pci/rom.c index 0b3037ab8b93..48ebdb237f3f 100644 --- a/trunk/drivers/pci/rom.c +++ b/trunk/drivers/pci/rom.c @@ -167,6 +167,44 @@ void __iomem *pci_map_rom(struct pci_dev *pdev, size_t *size) return rom; } +#if 0 +/** + * pci_map_rom_copy - map a PCI ROM to kernel space, create a copy + * @pdev: pointer to pci device struct + * @size: pointer to receive size of pci window over ROM + * + * Return: kernel virtual pointer to image of ROM + * + * Map a PCI ROM into kernel space. If ROM is boot video ROM, + * the shadow BIOS copy will be returned instead of the + * actual ROM. + */ +void __iomem *pci_map_rom_copy(struct pci_dev *pdev, size_t *size) +{ + struct resource *res = &pdev->resource[PCI_ROM_RESOURCE]; + void __iomem *rom; + + rom = pci_map_rom(pdev, size); + if (!rom) + return NULL; + + if (res->flags & (IORESOURCE_ROM_COPY | IORESOURCE_ROM_SHADOW | + IORESOURCE_ROM_BIOS_COPY)) + return rom; + + res->start = (unsigned long)kmalloc(*size, GFP_KERNEL); + if (!res->start) + return rom; + + res->end = res->start + *size; + memcpy_fromio((void*)(unsigned long)res->start, rom, *size); + pci_unmap_rom(pdev, rom); + res->flags |= IORESOURCE_ROM_COPY; + + return (void __iomem *)(unsigned long)res->start; +} +#endif /* 0 */ + /** * pci_unmap_rom - unmap the ROM from kernel space * @pdev: pointer to pci device struct @@ -188,6 +226,27 @@ void pci_unmap_rom(struct pci_dev *pdev, void __iomem *rom) pci_disable_rom(pdev); } +#if 0 +/** + * pci_remove_rom - disable the ROM and remove its sysfs attribute + * @pdev: pointer to pci device struct + * + * Remove the rom file in sysfs and disable ROM decoding. + */ +void pci_remove_rom(struct pci_dev *pdev) +{ + struct resource *res = &pdev->resource[PCI_ROM_RESOURCE]; + + if (pci_resource_len(pdev, PCI_ROM_RESOURCE)) + sysfs_remove_bin_file(&pdev->dev.kobj, pdev->rom_attr); + if (!(res->flags & (IORESOURCE_ROM_ENABLE | + IORESOURCE_ROM_SHADOW | + IORESOURCE_ROM_BIOS_COPY | + IORESOURCE_ROM_COPY))) + pci_disable_rom(pdev); +} +#endif /* 0 */ + /** * pci_cleanup_rom - free the ROM copy created by pci_map_rom_copy * @pdev: pointer to pci device struct diff --git a/trunk/drivers/pci/search.c b/trunk/drivers/pci/search.c index bf969ba58e59..993d4a0a2469 100644 --- a/trunk/drivers/pci/search.c +++ b/trunk/drivers/pci/search.c @@ -41,7 +41,7 @@ pci_find_upstream_pcie_bridge(struct pci_dev *pdev) continue; } /* PCI device should connect to a PCIe bridge */ - if (pci_pcie_type(pdev) != PCI_EXP_TYPE_PCI_BRIDGE) { + if (pdev->pcie_type != PCI_EXP_TYPE_PCI_BRIDGE) { /* Busted hardware? */ WARN_ON_ONCE(1); return NULL; @@ -130,14 +130,16 @@ pci_find_next_bus(const struct pci_bus *from) * decrement the reference count by calling pci_dev_put(). * If no device is found, %NULL is returned. */ -struct pci_dev *pci_get_slot(struct pci_bus *bus, unsigned int devfn) +struct pci_dev * pci_get_slot(struct pci_bus *bus, unsigned int devfn) { + struct list_head *tmp; struct pci_dev *dev; WARN_ON(in_interrupt()); down_read(&pci_bus_sem); - list_for_each_entry(dev, &bus->devices, bus_list) { + list_for_each(tmp, &bus->devices) { + dev = pci_dev_b(tmp); if (dev->devfn == devfn) goto out; } @@ -243,14 +245,30 @@ struct pci_dev *pci_get_subsys(unsigned int vendor, unsigned int device, unsigned int ss_vendor, unsigned int ss_device, struct pci_dev *from) { - struct pci_device_id id = { - .vendor = vendor, - .device = device, - .subvendor = ss_vendor, - .subdevice = ss_device, - }; - - return pci_get_dev_by_id(&id, from); + struct pci_dev *pdev; + struct pci_device_id *id; + + /* + * pci_find_subsys() can be called on the ide_setup() path, + * super-early in boot. But the down_read() will enable local + * interrupts, which can cause some machines to crash. So here we + * detect and flag that situation and bail out early. + */ + if (unlikely(no_pci_devices())) + return NULL; + + id = kzalloc(sizeof(*id), GFP_KERNEL); + if (!id) + return NULL; + id->vendor = vendor; + id->device = device; + id->subvendor = ss_vendor; + id->subdevice = ss_device; + + pdev = pci_get_dev_by_id(id, from); + kfree(id); + + return pdev; } /** @@ -289,16 +307,19 @@ pci_get_device(unsigned int vendor, unsigned int device, struct pci_dev *from) */ struct pci_dev *pci_get_class(unsigned int class, struct pci_dev *from) { - struct pci_device_id id = { - .vendor = PCI_ANY_ID, - .device = PCI_ANY_ID, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .class_mask = PCI_ANY_ID, - .class = class, - }; - - return pci_get_dev_by_id(&id, from); + struct pci_dev *dev; + struct pci_device_id *id; + + id = kzalloc(sizeof(*id), GFP_KERNEL); + if (!id) + return NULL; + id->vendor = id->device = id->subvendor = id->subdevice = PCI_ANY_ID; + id->class_mask = PCI_ANY_ID; + id->class = class; + + dev = pci_get_dev_by_id(id, from); + kfree(id); + return dev; } /** diff --git a/trunk/drivers/pci/setup-bus.c b/trunk/drivers/pci/setup-bus.c index 1e808ca338f8..fb506137aaee 100644 --- a/trunk/drivers/pci/setup-bus.c +++ b/trunk/drivers/pci/setup-bus.c @@ -697,38 +697,6 @@ static resource_size_t calculate_memsize(resource_size_t size, return size; } -resource_size_t __weak pcibios_window_alignment(struct pci_bus *bus, - unsigned long type) -{ - return 1; -} - -#define PCI_P2P_DEFAULT_MEM_ALIGN 0x100000 /* 1MiB */ -#define PCI_P2P_DEFAULT_IO_ALIGN 0x1000 /* 4KiB */ -#define PCI_P2P_DEFAULT_IO_ALIGN_1K 0x400 /* 1KiB */ - -static resource_size_t window_alignment(struct pci_bus *bus, - unsigned long type) -{ - resource_size_t align = 1, arch_align; - - if (type & IORESOURCE_MEM) - align = PCI_P2P_DEFAULT_MEM_ALIGN; - else if (type & IORESOURCE_IO) { - /* - * Per spec, I/O windows are 4K-aligned, but some - * bridges have an extension to support 1K alignment. - */ - if (bus->self->io_window_1k) - align = PCI_P2P_DEFAULT_IO_ALIGN_1K; - else - align = PCI_P2P_DEFAULT_IO_ALIGN; - } - - arch_align = pcibios_window_alignment(bus, type); - return max(align, arch_align); -} - /** * pbus_size_io() - size the io window of a given bus * @@ -749,12 +717,17 @@ static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size, struct resource *b_res = find_free_bus_resource(bus, IORESOURCE_IO); unsigned long size = 0, size0 = 0, size1 = 0; resource_size_t children_add_size = 0; - resource_size_t min_align, io_align, align; + resource_size_t min_align = 4096, align; if (!b_res) return; - io_align = min_align = window_alignment(bus, IORESOURCE_IO); + /* + * Per spec, I/O windows are 4K-aligned, but some bridges have an + * extension to support 1K alignment. + */ + if (bus->self->io_window_1k) + min_align = 1024; list_for_each_entry(dev, &bus->devices, bus_list) { int i; @@ -781,8 +754,8 @@ static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size, } } - if (min_align > io_align) - min_align = io_align; + if (min_align > 4096) + min_align = 4096; size0 = calculate_iosize(size, min_size, size1, resource_size(b_res), min_align); @@ -812,28 +785,6 @@ static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size, } } -static inline resource_size_t calculate_mem_align(resource_size_t *aligns, - int max_order) -{ - resource_size_t align = 0; - resource_size_t min_align = 0; - int order; - - for (order = 0; order <= max_order; order++) { - resource_size_t align1 = 1; - - align1 <<= (order + 20); - - if (!align) - min_align = align1; - else if (ALIGN(align + min_align, min_align) < align1) - min_align = align1 >> 1; - align += aligns[order]; - } - - return min_align; -} - /** * pbus_size_mem() - size the memory window of a given bus * @@ -913,9 +864,19 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, children_add_size += get_res_add_size(realloc_head, r); } } + align = 0; + min_align = 0; + for (order = 0; order <= max_order; order++) { + resource_size_t align1 = 1; - min_align = calculate_mem_align(aligns, max_order); - min_align = max(min_align, window_alignment(bus, b_res->flags & mask)); + align1 <<= (order + 20); + + if (!align) + min_align = align1; + else if (ALIGN(align + min_align, min_align) < align1) + min_align = align1 >> 1; + align += aligns[order]; + } size0 = calculate_memsize(size, min_size, 0, resource_size(b_res), min_align); if (children_add_size > add_size) add_size = children_add_size; diff --git a/trunk/drivers/pci/setup-irq.c b/trunk/drivers/pci/setup-irq.c index 9bd6864ec5d3..eb219a1d16f7 100644 --- a/trunk/drivers/pci/setup-irq.c +++ b/trunk/drivers/pci/setup-irq.c @@ -17,13 +17,8 @@ #include #include -void __weak pcibios_update_irq(struct pci_dev *dev, int irq) -{ - dev_dbg(&dev->dev, "assigning IRQ %02d\n", irq); - pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq); -} -static void +static void __init pdev_fixup_irq(struct pci_dev *dev, u8 (*swizzle)(struct pci_dev *, u8 *), int (*map_irq)(const struct pci_dev *, u8, u8)) @@ -59,7 +54,7 @@ pdev_fixup_irq(struct pci_dev *dev, pcibios_update_irq(dev, irq); } -void +void __init pci_fixup_irqs(u8 (*swizzle)(struct pci_dev *, u8 *), int (*map_irq)(const struct pci_dev *, u8, u8)) { diff --git a/trunk/drivers/pci/xen-pcifront.c b/trunk/drivers/pci/xen-pcifront.c index def8d0b5620c..d6cc62cb4cf7 100644 --- a/trunk/drivers/pci/xen-pcifront.c +++ b/trunk/drivers/pci/xen-pcifront.c @@ -982,6 +982,7 @@ static int pcifront_detach_devices(struct pcifront_device *pdev) int err = 0; int i, num_devs; unsigned int domain, bus, slot, func; + struct pci_bus *pci_bus; struct pci_dev *pci_dev; char str[64]; @@ -1031,8 +1032,13 @@ static int pcifront_detach_devices(struct pcifront_device *pdev) goto out; } - pci_dev = pci_get_domain_bus_and_slot(domain, bus, - PCI_DEVFN(slot, func)); + pci_bus = pci_find_bus(domain, bus); + if (!pci_bus) { + dev_dbg(&pdev->xdev->dev, "Cannot get bus %04x:%02x\n", + domain, bus); + continue; + } + pci_dev = pci_get_slot(pci_bus, PCI_DEVFN(slot, func)); if (!pci_dev) { dev_dbg(&pdev->xdev->dev, "Cannot get PCI device %04x:%02x:%02x.%d\n", diff --git a/trunk/drivers/pcmcia/cardbus.c b/trunk/drivers/pcmcia/cardbus.c index 9d3ac998fc1f..24caeaf50529 100644 --- a/trunk/drivers/pcmcia/cardbus.c +++ b/trunk/drivers/pcmcia/cardbus.c @@ -105,17 +105,8 @@ int __ref cb_alloc(struct pcmcia_socket *s) */ void cb_free(struct pcmcia_socket *s) { - struct pci_dev *bridge, *dev, *tmp; - struct pci_bus *bus; + struct pci_dev *bridge = s->cb_dev; - bridge = s->cb_dev; - if (!bridge) - return; - - bus = bridge->subordinate; - if (!bus) - return; - - list_for_each_entry_safe(dev, tmp, &bus->devices, bus_list) - pci_stop_and_remove_bus_device(dev); + if (bridge) + pci_stop_and_remove_behind_bridge(bridge); } diff --git a/trunk/drivers/pinctrl/core.c b/trunk/drivers/pinctrl/core.c index dc5c126e398a..fb7f3bebdc69 100644 --- a/trunk/drivers/pinctrl/core.c +++ b/trunk/drivers/pinctrl/core.c @@ -657,7 +657,11 @@ static struct pinctrl *pinctrl_get_locked(struct device *dev) if (p != NULL) return ERR_PTR(-EBUSY); - return create_pinctrl(dev); + p = create_pinctrl(dev); + if (IS_ERR(p)) + return p; + + return p; } /** @@ -734,8 +738,11 @@ static struct pinctrl_state *pinctrl_lookup_state_locked(struct pinctrl *p, dev_dbg(p->dev, "using pinctrl dummy state (%s)\n", name); state = create_state(p, name); - } else - state = ERR_PTR(-ENODEV); + if (IS_ERR(state)) + return state; + } else { + return ERR_PTR(-ENODEV); + } } return state; diff --git a/trunk/drivers/pinctrl/pinctrl-imx23.c b/trunk/drivers/pinctrl/pinctrl-imx23.c index 3674d877ed7c..75d3eff94296 100644 --- a/trunk/drivers/pinctrl/pinctrl-imx23.c +++ b/trunk/drivers/pinctrl/pinctrl-imx23.c @@ -292,7 +292,7 @@ static int __init imx23_pinctrl_init(void) { return platform_driver_register(&imx23_pinctrl_driver); } -postcore_initcall(imx23_pinctrl_init); +arch_initcall(imx23_pinctrl_init); static void __exit imx23_pinctrl_exit(void) { diff --git a/trunk/drivers/pinctrl/pinctrl-imx28.c b/trunk/drivers/pinctrl/pinctrl-imx28.c index 0f5b2122b1ba..b973026811a2 100644 --- a/trunk/drivers/pinctrl/pinctrl-imx28.c +++ b/trunk/drivers/pinctrl/pinctrl-imx28.c @@ -408,7 +408,7 @@ static int __init imx28_pinctrl_init(void) { return platform_driver_register(&imx28_pinctrl_driver); } -postcore_initcall(imx28_pinctrl_init); +arch_initcall(imx28_pinctrl_init); static void __exit imx28_pinctrl_exit(void) { diff --git a/trunk/drivers/pinctrl/pinctrl-imx51.c b/trunk/drivers/pinctrl/pinctrl-imx51.c index 9fd02162a3c2..689b3c88dd2e 100644 --- a/trunk/drivers/pinctrl/pinctrl-imx51.c +++ b/trunk/drivers/pinctrl/pinctrl-imx51.c @@ -974,7 +974,7 @@ static struct imx_pin_reg imx51_pin_regs[] = { IMX_PIN_REG(MX51_PAD_EIM_DA13, NO_PAD, 0x050, 0, 0x000, 0), /* MX51_PAD_EIM_DA13__EIM_DA13 */ IMX_PIN_REG(MX51_PAD_EIM_DA14, NO_PAD, 0x054, 0, 0x000, 0), /* MX51_PAD_EIM_DA14__EIM_DA14 */ IMX_PIN_REG(MX51_PAD_EIM_DA15, NO_PAD, 0x058, 0, 0x000, 0), /* MX51_PAD_EIM_DA15__EIM_DA15 */ - IMX_PIN_REG(MX51_PAD_SD2_CMD, 0x7bc, 0x3b4, 2, 0x91c, 3), /* MX51_PAD_SD2_CMD__CSPI_MOSI */ + IMX_PIN_REG(MX51_PAD_SD2_CMD, NO_PAD, 0x3b4, 2, 0x91c, 3), /* MX51_PAD_SD2_CMD__CSPI_MOSI */ IMX_PIN_REG(MX51_PAD_SD2_CMD, 0x7bc, 0x3b4, 1, 0x9b0, 2), /* MX51_PAD_SD2_CMD__I2C1_SCL */ IMX_PIN_REG(MX51_PAD_SD2_CMD, 0x7bc, 0x3b4, 0, 0x000, 0), /* MX51_PAD_SD2_CMD__SD2_CMD */ IMX_PIN_REG(MX51_PAD_SD2_CLK, 0x7c0, 0x3b8, 2, 0x914, 3), /* MX51_PAD_SD2_CLK__CSPI_SCLK */ diff --git a/trunk/drivers/pinctrl/pinctrl-nomadik-db8500.c b/trunk/drivers/pinctrl/pinctrl-nomadik-db8500.c index a39fb7a6fc51..6f99769c6733 100644 --- a/trunk/drivers/pinctrl/pinctrl-nomadik-db8500.c +++ b/trunk/drivers/pinctrl/pinctrl-nomadik-db8500.c @@ -505,8 +505,6 @@ static const unsigned kp_b_1_pins[] = { DB8500_PIN_F3, DB8500_PIN_F1, DB8500_PIN_J3, DB8500_PIN_H2, DB8500_PIN_J2, DB8500_PIN_H1, DB8500_PIN_F4, DB8500_PIN_E3, DB8500_PIN_E4, DB8500_PIN_D2, DB8500_PIN_C1, DB8500_PIN_D3, DB8500_PIN_C2, DB8500_PIN_D5 }; -static const unsigned kp_b_2_pins[] = { DB8500_PIN_F3, DB8500_PIN_F1, - DB8500_PIN_G3, DB8500_PIN_G2, DB8500_PIN_F4, DB8500_PIN_E3}; static const unsigned sm_b_1_pins[] = { DB8500_PIN_C6, DB8500_PIN_B3, DB8500_PIN_C4, DB8500_PIN_E6, DB8500_PIN_A3, DB8500_PIN_B6, DB8500_PIN_D6, DB8500_PIN_B7, DB8500_PIN_D7, DB8500_PIN_D8, @@ -664,7 +662,6 @@ static const struct nmk_pingroup nmk_db8500_groups[] = { DB8500_PIN_GROUP(spi3_b_1, NMK_GPIO_ALT_B), DB8500_PIN_GROUP(msp1txrx_b_1, NMK_GPIO_ALT_B), DB8500_PIN_GROUP(kp_b_1, NMK_GPIO_ALT_B), - DB8500_PIN_GROUP(kp_b_2, NMK_GPIO_ALT_B), DB8500_PIN_GROUP(sm_b_1, NMK_GPIO_ALT_B), DB8500_PIN_GROUP(smcs0_b_1, NMK_GPIO_ALT_B), DB8500_PIN_GROUP(smcs1_b_1, NMK_GPIO_ALT_B), @@ -754,7 +751,7 @@ DB8500_FUNC_GROUPS(msp1, "msp1txrx_a_1", "msp1_a_1", "msp1txrx_b_1"); DB8500_FUNC_GROUPS(lcdb, "lcdb_a_1"); DB8500_FUNC_GROUPS(lcd, "lcdvsi0_a_1", "lcdvsi1_a_1", "lcd_d0_d7_a_1", "lcd_d8_d11_a_1", "lcd_d12_d23_a_1", "lcd_b_1"); -DB8500_FUNC_GROUPS(kp, "kp_a_1", "kp_b_1", "kp_b_2", "kp_c_1", "kp_oc1_1"); +DB8500_FUNC_GROUPS(kp, "kp_a_1", "kp_b_1", "kp_c_1", "kp_oc1_1"); DB8500_FUNC_GROUPS(mc2, "mc2_a_1", "mc2rstn_c_1"); DB8500_FUNC_GROUPS(ssp1, "ssp1_a_1"); DB8500_FUNC_GROUPS(ssp0, "ssp0_a_1"); @@ -769,7 +766,7 @@ DB8500_FUNC_GROUPS(ipgpio, "ipgpio0_a_1", "ipgpio1_a_1", "ipgpio7_b_1", DB8500_FUNC_GROUPS(msp2, "msp2sck_a_1", "msp2_a_1"); DB8500_FUNC_GROUPS(mc4, "mc4_a_1", "mc4rstn_c_1"); DB8500_FUNC_GROUPS(mc1, "mc1_a_1", "mc1dir_a_1"); -DB8500_FUNC_GROUPS(hsi, "hsir_a_1", "hsit_a_1", "hsit_a_2"); +DB8500_FUNC_GROUPS(hsi, "hsir1_a_1", "hsit1_a_1", "hsit_a_2"); DB8500_FUNC_GROUPS(clkout, "clkout_a_1", "clkout_a_2", "clkout_c_1"); DB8500_FUNC_GROUPS(usb, "usb_a_1"); DB8500_FUNC_GROUPS(trig, "trig_b_1"); diff --git a/trunk/drivers/pinctrl/pinctrl-nomadik.c b/trunk/drivers/pinctrl/pinctrl-nomadik.c index 3dde6537adb8..53b0d49a7a1c 100644 --- a/trunk/drivers/pinctrl/pinctrl-nomadik.c +++ b/trunk/drivers/pinctrl/pinctrl-nomadik.c @@ -1292,7 +1292,7 @@ static int __devinit nmk_gpio_probe(struct platform_device *dev) NOMADIK_GPIO_TO_IRQ(pdata->first_gpio), 0, &nmk_gpio_irq_simple_ops, nmk_chip); if (!nmk_chip->domain) { - dev_err(&dev->dev, "failed to create irqdomain\n"); + pr_err("%s: Failed to create irqdomain\n", np->full_name); ret = -ENOSYS; goto out; } @@ -1731,6 +1731,7 @@ static int __devinit nmk_pinctrl_probe(struct platform_device *pdev) for (i = 0; i < npct->soc->gpio_num_ranges; i++) { if (!nmk_gpio_chips[i]) { dev_warn(&pdev->dev, "GPIO chip %d not registered yet\n", i); + devm_kfree(&pdev->dev, npct); return -EPROBE_DEFER; } npct->soc->gpio_ranges[i].gc = &nmk_gpio_chips[i]->chip; diff --git a/trunk/drivers/pinctrl/pinctrl-sirf.c b/trunk/drivers/pinctrl/pinctrl-sirf.c index 7fca6ce5952b..2aae8a8978e9 100644 --- a/trunk/drivers/pinctrl/pinctrl-sirf.c +++ b/trunk/drivers/pinctrl/pinctrl-sirf.c @@ -1217,6 +1217,7 @@ static int __devinit sirfsoc_pinmux_probe(struct platform_device *pdev) iounmap(spmx->gpio_virtbase); out_no_gpio_remap: platform_set_drvdata(pdev, NULL); + devm_kfree(&pdev->dev, spmx); return ret; } diff --git a/trunk/drivers/pinctrl/pinctrl-u300.c b/trunk/drivers/pinctrl/pinctrl-u300.c index 309f5b9a70ec..a7ad8c112d91 100644 --- a/trunk/drivers/pinctrl/pinctrl-u300.c +++ b/trunk/drivers/pinctrl/pinctrl-u300.c @@ -1121,8 +1121,10 @@ static int __devinit u300_pmx_probe(struct platform_device *pdev) upmx->dev = &pdev->dev; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) - return -ENOENT; + if (!res) { + ret = -ENOENT; + goto out_no_resource; + } upmx->phybase = res->start; upmx->physize = resource_size(res); @@ -1163,6 +1165,8 @@ static int __devinit u300_pmx_probe(struct platform_device *pdev) platform_set_drvdata(pdev, NULL); out_no_memregion: release_mem_region(upmx->phybase, upmx->physize); +out_no_resource: + devm_kfree(&pdev->dev, upmx); return ret; } diff --git a/trunk/drivers/platform/x86/Kconfig b/trunk/drivers/platform/x86/Kconfig index c86bae828c28..2a262f5c5c0c 100644 --- a/trunk/drivers/platform/x86/Kconfig +++ b/trunk/drivers/platform/x86/Kconfig @@ -289,7 +289,6 @@ config IDEAPAD_LAPTOP tristate "Lenovo IdeaPad Laptop Extras" depends on ACPI depends on RFKILL && INPUT - depends on SERIO_I8042 select INPUT_SPARSEKMAP help This is a driver for the rfkill switches on Lenovo IdeaPad netbooks. @@ -759,11 +758,8 @@ config SAMSUNG_Q10 config APPLE_GMUX tristate "Apple Gmux Driver" - depends on ACPI depends on PNP - depends on BACKLIGHT_CLASS_DEVICE - depends on BACKLIGHT_APPLE=n || BACKLIGHT_APPLE - depends on ACPI_VIDEO=n || ACPI_VIDEO + select BACKLIGHT_CLASS_DEVICE ---help--- This driver provides support for the gmux device found on many Apple laptops, which controls the display mux for the hybrid diff --git a/trunk/drivers/platform/x86/acer-wmi.c b/trunk/drivers/platform/x86/acer-wmi.c index 934d861a3235..3782e1cd3697 100644 --- a/trunk/drivers/platform/x86/acer-wmi.c +++ b/trunk/drivers/platform/x86/acer-wmi.c @@ -2196,8 +2196,10 @@ static int __init acer_wmi_init(void) interface->capability &= ~ACER_CAP_BRIGHTNESS; pr_info("Brightness must be controlled by acpi video driver\n"); } else { +#ifdef CONFIG_ACPI_VIDEO pr_info("Disabling ACPI video driver\n"); acpi_video_unregister(); +#endif } if (wmi_has_guid(WMID_GUID3)) { diff --git a/trunk/drivers/platform/x86/apple-gmux.c b/trunk/drivers/platform/x86/apple-gmux.c index db8f63841b42..905fa01ac8df 100644 --- a/trunk/drivers/platform/x86/apple-gmux.c +++ b/trunk/drivers/platform/x86/apple-gmux.c @@ -2,7 +2,6 @@ * Gmux driver for Apple laptops * * Copyright (C) Canonical Ltd. - * Copyright (C) 2010-2012 Andreas Heider * * 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 @@ -19,30 +18,16 @@ #include #include #include -#include -#include -#include #include #include struct apple_gmux_data { unsigned long iostart; unsigned long iolen; - bool indexed; - struct mutex index_lock; struct backlight_device *bdev; - - /* switcheroo data */ - acpi_handle dhandle; - int gpe; - enum vga_switcheroo_client_id resume_client_id; - enum vga_switcheroo_state power_state; - struct completion powerchange_done; }; -static struct apple_gmux_data *apple_gmux_data; - /* * gmux port offsets. Many of these are not yet used, but may be in the * future, and it's useful to have them documented here anyhow. @@ -60,9 +45,6 @@ static struct apple_gmux_data *apple_gmux_data; #define GMUX_PORT_DISCRETE_POWER 0x50 #define GMUX_PORT_MAX_BRIGHTNESS 0x70 #define GMUX_PORT_BRIGHTNESS 0x74 -#define GMUX_PORT_VALUE 0xc2 -#define GMUX_PORT_READ 0xd0 -#define GMUX_PORT_WRITE 0xd4 #define GMUX_MIN_IO_LEN (GMUX_PORT_BRIGHTNESS + 4) @@ -77,174 +59,22 @@ static struct apple_gmux_data *apple_gmux_data; #define GMUX_BRIGHTNESS_MASK 0x00ffffff #define GMUX_MAX_BRIGHTNESS GMUX_BRIGHTNESS_MASK -static u8 gmux_pio_read8(struct apple_gmux_data *gmux_data, int port) +static inline u8 gmux_read8(struct apple_gmux_data *gmux_data, int port) { return inb(gmux_data->iostart + port); } -static void gmux_pio_write8(struct apple_gmux_data *gmux_data, int port, +static inline void gmux_write8(struct apple_gmux_data *gmux_data, int port, u8 val) { outb(val, gmux_data->iostart + port); } -static u32 gmux_pio_read32(struct apple_gmux_data *gmux_data, int port) +static inline u32 gmux_read32(struct apple_gmux_data *gmux_data, int port) { return inl(gmux_data->iostart + port); } -static void gmux_pio_write32(struct apple_gmux_data *gmux_data, int port, - u32 val) -{ - int i; - u8 tmpval; - - for (i = 0; i < 4; i++) { - tmpval = (val >> (i * 8)) & 0xff; - outb(tmpval, gmux_data->iostart + port + i); - } -} - -static int gmux_index_wait_ready(struct apple_gmux_data *gmux_data) -{ - int i = 200; - u8 gwr = inb(gmux_data->iostart + GMUX_PORT_WRITE); - - while (i && (gwr & 0x01)) { - inb(gmux_data->iostart + GMUX_PORT_READ); - gwr = inb(gmux_data->iostart + GMUX_PORT_WRITE); - udelay(100); - i--; - } - - return !!i; -} - -static int gmux_index_wait_complete(struct apple_gmux_data *gmux_data) -{ - int i = 200; - u8 gwr = inb(gmux_data->iostart + GMUX_PORT_WRITE); - - while (i && !(gwr & 0x01)) { - gwr = inb(gmux_data->iostart + GMUX_PORT_WRITE); - udelay(100); - i--; - } - - if (gwr & 0x01) - inb(gmux_data->iostart + GMUX_PORT_READ); - - return !!i; -} - -static u8 gmux_index_read8(struct apple_gmux_data *gmux_data, int port) -{ - u8 val; - - mutex_lock(&gmux_data->index_lock); - gmux_index_wait_ready(gmux_data); - outb((port & 0xff), gmux_data->iostart + GMUX_PORT_READ); - gmux_index_wait_complete(gmux_data); - val = inb(gmux_data->iostart + GMUX_PORT_VALUE); - mutex_unlock(&gmux_data->index_lock); - - return val; -} - -static void gmux_index_write8(struct apple_gmux_data *gmux_data, int port, - u8 val) -{ - mutex_lock(&gmux_data->index_lock); - outb(val, gmux_data->iostart + GMUX_PORT_VALUE); - gmux_index_wait_ready(gmux_data); - outb(port & 0xff, gmux_data->iostart + GMUX_PORT_WRITE); - gmux_index_wait_complete(gmux_data); - mutex_unlock(&gmux_data->index_lock); -} - -static u32 gmux_index_read32(struct apple_gmux_data *gmux_data, int port) -{ - u32 val; - - mutex_lock(&gmux_data->index_lock); - gmux_index_wait_ready(gmux_data); - outb((port & 0xff), gmux_data->iostart + GMUX_PORT_READ); - gmux_index_wait_complete(gmux_data); - val = inl(gmux_data->iostart + GMUX_PORT_VALUE); - mutex_unlock(&gmux_data->index_lock); - - return val; -} - -static void gmux_index_write32(struct apple_gmux_data *gmux_data, int port, - u32 val) -{ - int i; - u8 tmpval; - - mutex_lock(&gmux_data->index_lock); - - for (i = 0; i < 4; i++) { - tmpval = (val >> (i * 8)) & 0xff; - outb(tmpval, gmux_data->iostart + GMUX_PORT_VALUE + i); - } - - gmux_index_wait_ready(gmux_data); - outb(port & 0xff, gmux_data->iostart + GMUX_PORT_WRITE); - gmux_index_wait_complete(gmux_data); - mutex_unlock(&gmux_data->index_lock); -} - -static u8 gmux_read8(struct apple_gmux_data *gmux_data, int port) -{ - if (gmux_data->indexed) - return gmux_index_read8(gmux_data, port); - else - return gmux_pio_read8(gmux_data, port); -} - -static void gmux_write8(struct apple_gmux_data *gmux_data, int port, u8 val) -{ - if (gmux_data->indexed) - gmux_index_write8(gmux_data, port, val); - else - gmux_pio_write8(gmux_data, port, val); -} - -static u32 gmux_read32(struct apple_gmux_data *gmux_data, int port) -{ - if (gmux_data->indexed) - return gmux_index_read32(gmux_data, port); - else - return gmux_pio_read32(gmux_data, port); -} - -static void gmux_write32(struct apple_gmux_data *gmux_data, int port, - u32 val) -{ - if (gmux_data->indexed) - gmux_index_write32(gmux_data, port, val); - else - gmux_pio_write32(gmux_data, port, val); -} - -static bool gmux_is_indexed(struct apple_gmux_data *gmux_data) -{ - u16 val; - - outb(0xaa, gmux_data->iostart + 0xcc); - outb(0x55, gmux_data->iostart + 0xcd); - outb(0x00, gmux_data->iostart + 0xce); - - val = inb(gmux_data->iostart + 0xcc) | - (inb(gmux_data->iostart + 0xcd) << 8); - - if (val == 0x55aa) - return true; - - return false; -} - static int gmux_get_brightness(struct backlight_device *bd) { struct apple_gmux_data *gmux_data = bl_get_data(bd); @@ -260,7 +90,16 @@ static int gmux_update_status(struct backlight_device *bd) if (bd->props.state & BL_CORE_SUSPENDED) return 0; - gmux_write32(gmux_data, GMUX_PORT_BRIGHTNESS, brightness); + /* + * Older gmux versions require writing out lower bytes first then + * setting the upper byte to 0 to flush the values. Newer versions + * accept a single u32 write, but the old method also works, so we + * just use the old method for all gmux versions. + */ + gmux_write8(gmux_data, GMUX_PORT_BRIGHTNESS, brightness); + gmux_write8(gmux_data, GMUX_PORT_BRIGHTNESS + 1, brightness >> 8); + gmux_write8(gmux_data, GMUX_PORT_BRIGHTNESS + 2, brightness >> 16); + gmux_write8(gmux_data, GMUX_PORT_BRIGHTNESS + 3, 0); return 0; } @@ -271,146 +110,6 @@ static const struct backlight_ops gmux_bl_ops = { .update_status = gmux_update_status, }; -static int gmux_switchto(enum vga_switcheroo_client_id id) -{ - if (id == VGA_SWITCHEROO_IGD) { - gmux_write8(apple_gmux_data, GMUX_PORT_SWITCH_DDC, 1); - gmux_write8(apple_gmux_data, GMUX_PORT_SWITCH_DISPLAY, 2); - gmux_write8(apple_gmux_data, GMUX_PORT_SWITCH_EXTERNAL, 2); - } else { - gmux_write8(apple_gmux_data, GMUX_PORT_SWITCH_DDC, 2); - gmux_write8(apple_gmux_data, GMUX_PORT_SWITCH_DISPLAY, 3); - gmux_write8(apple_gmux_data, GMUX_PORT_SWITCH_EXTERNAL, 3); - } - - return 0; -} - -static int gmux_set_discrete_state(struct apple_gmux_data *gmux_data, - enum vga_switcheroo_state state) -{ - INIT_COMPLETION(gmux_data->powerchange_done); - - if (state == VGA_SWITCHEROO_ON) { - gmux_write8(gmux_data, GMUX_PORT_DISCRETE_POWER, 1); - gmux_write8(gmux_data, GMUX_PORT_DISCRETE_POWER, 3); - pr_debug("Discrete card powered up\n"); - } else { - gmux_write8(gmux_data, GMUX_PORT_DISCRETE_POWER, 1); - gmux_write8(gmux_data, GMUX_PORT_DISCRETE_POWER, 0); - pr_debug("Discrete card powered down\n"); - } - - gmux_data->power_state = state; - - if (gmux_data->gpe >= 0 && - !wait_for_completion_interruptible_timeout(&gmux_data->powerchange_done, - msecs_to_jiffies(200))) - pr_warn("Timeout waiting for gmux switch to complete\n"); - - return 0; -} - -static int gmux_set_power_state(enum vga_switcheroo_client_id id, - enum vga_switcheroo_state state) -{ - if (id == VGA_SWITCHEROO_IGD) - return 0; - - return gmux_set_discrete_state(apple_gmux_data, state); -} - -static int gmux_get_client_id(struct pci_dev *pdev) -{ - /* - * Early Macbook Pros with switchable graphics use nvidia - * integrated graphics. Hardcode that the 9400M is integrated. - */ - if (pdev->vendor == PCI_VENDOR_ID_INTEL) - return VGA_SWITCHEROO_IGD; - else if (pdev->vendor == PCI_VENDOR_ID_NVIDIA && - pdev->device == 0x0863) - return VGA_SWITCHEROO_IGD; - else - return VGA_SWITCHEROO_DIS; -} - -static enum vga_switcheroo_client_id -gmux_active_client(struct apple_gmux_data *gmux_data) -{ - if (gmux_read8(gmux_data, GMUX_PORT_SWITCH_DISPLAY) == 2) - return VGA_SWITCHEROO_IGD; - - return VGA_SWITCHEROO_DIS; -} - -static struct vga_switcheroo_handler gmux_handler = { - .switchto = gmux_switchto, - .power_state = gmux_set_power_state, - .get_client_id = gmux_get_client_id, -}; - -static inline void gmux_disable_interrupts(struct apple_gmux_data *gmux_data) -{ - gmux_write8(gmux_data, GMUX_PORT_INTERRUPT_ENABLE, - GMUX_INTERRUPT_DISABLE); -} - -static inline void gmux_enable_interrupts(struct apple_gmux_data *gmux_data) -{ - gmux_write8(gmux_data, GMUX_PORT_INTERRUPT_ENABLE, - GMUX_INTERRUPT_ENABLE); -} - -static inline u8 gmux_interrupt_get_status(struct apple_gmux_data *gmux_data) -{ - return gmux_read8(gmux_data, GMUX_PORT_INTERRUPT_STATUS); -} - -static void gmux_clear_interrupts(struct apple_gmux_data *gmux_data) -{ - u8 status; - - /* to clear interrupts write back current status */ - status = gmux_interrupt_get_status(gmux_data); - gmux_write8(gmux_data, GMUX_PORT_INTERRUPT_STATUS, status); -} - -static void gmux_notify_handler(acpi_handle device, u32 value, void *context) -{ - u8 status; - struct pnp_dev *pnp = (struct pnp_dev *)context; - struct apple_gmux_data *gmux_data = pnp_get_drvdata(pnp); - - status = gmux_interrupt_get_status(gmux_data); - gmux_disable_interrupts(gmux_data); - pr_debug("Notify handler called: status %d\n", status); - - gmux_clear_interrupts(gmux_data); - gmux_enable_interrupts(gmux_data); - - if (status & GMUX_INTERRUPT_STATUS_POWER) - complete(&gmux_data->powerchange_done); -} - -static int gmux_suspend(struct pnp_dev *pnp, pm_message_t state) -{ - struct apple_gmux_data *gmux_data = pnp_get_drvdata(pnp); - gmux_data->resume_client_id = gmux_active_client(gmux_data); - gmux_disable_interrupts(gmux_data); - return 0; -} - -static int gmux_resume(struct pnp_dev *pnp) -{ - struct apple_gmux_data *gmux_data = pnp_get_drvdata(pnp); - gmux_enable_interrupts(gmux_data); - gmux_switchto(gmux_data->resume_client_id); - if (gmux_data->power_state == VGA_SWITCHEROO_OFF) - gmux_set_discrete_state(gmux_data, gmux_data->power_state); - return 0; -} - static int __devinit gmux_probe(struct pnp_dev *pnp, const struct pnp_device_id *id) { @@ -420,11 +119,6 @@ static int __devinit gmux_probe(struct pnp_dev *pnp, struct backlight_device *bdev; u8 ver_major, ver_minor, ver_release; int ret = -ENXIO; - acpi_status status; - unsigned long long gpe; - - if (apple_gmux_data) - return -EBUSY; gmux_data = kzalloc(sizeof(*gmux_data), GFP_KERNEL); if (!gmux_data) @@ -453,32 +147,21 @@ static int __devinit gmux_probe(struct pnp_dev *pnp, } /* - * Invalid version information may indicate either that the gmux - * device isn't present or that it's a new one that uses indexed - * io + * On some machines the gmux is in ACPI even thought the machine + * doesn't really have a gmux. Check for invalid version information + * to detect this. */ - ver_major = gmux_read8(gmux_data, GMUX_PORT_VERSION_MAJOR); ver_minor = gmux_read8(gmux_data, GMUX_PORT_VERSION_MINOR); ver_release = gmux_read8(gmux_data, GMUX_PORT_VERSION_RELEASE); if (ver_major == 0xff && ver_minor == 0xff && ver_release == 0xff) { - if (gmux_is_indexed(gmux_data)) { - u32 version; - mutex_init(&gmux_data->index_lock); - gmux_data->indexed = true; - version = gmux_read32(gmux_data, - GMUX_PORT_VERSION_MAJOR); - ver_major = (version >> 24) & 0xff; - ver_minor = (version >> 16) & 0xff; - ver_release = (version >> 8) & 0xff; - } else { - pr_info("gmux device not present\n"); - ret = -ENODEV; - goto err_release; - } + pr_info("gmux device not present\n"); + ret = -ENODEV; + goto err_release; } - pr_info("Found gmux version %d.%d.%d [%s]\n", ver_major, ver_minor, - ver_release, (gmux_data->indexed ? "indexed" : "classic")); + + pr_info("Found gmux version %d.%d.%d\n", ver_major, ver_minor, + ver_release); memset(&props, 0, sizeof(props)); props.type = BACKLIGHT_PLATFORM; @@ -511,65 +194,13 @@ static int __devinit gmux_probe(struct pnp_dev *pnp, * Disable the other backlight choices. */ acpi_video_dmi_promote_vendor(); +#ifdef CONFIG_ACPI_VIDEO acpi_video_unregister(); +#endif apple_bl_unregister(); - gmux_data->power_state = VGA_SWITCHEROO_ON; - - gmux_data->dhandle = DEVICE_ACPI_HANDLE(&pnp->dev); - if (!gmux_data->dhandle) { - pr_err("Cannot find acpi handle for pnp device %s\n", - dev_name(&pnp->dev)); - ret = -ENODEV; - goto err_notify; - } - - status = acpi_evaluate_integer(gmux_data->dhandle, "GMGP", NULL, &gpe); - if (ACPI_SUCCESS(status)) { - gmux_data->gpe = (int)gpe; - - status = acpi_install_notify_handler(gmux_data->dhandle, - ACPI_DEVICE_NOTIFY, - &gmux_notify_handler, pnp); - if (ACPI_FAILURE(status)) { - pr_err("Install notify handler failed: %s\n", - acpi_format_exception(status)); - ret = -ENODEV; - goto err_notify; - } - - status = acpi_enable_gpe(NULL, gmux_data->gpe); - if (ACPI_FAILURE(status)) { - pr_err("Cannot enable gpe: %s\n", - acpi_format_exception(status)); - goto err_enable_gpe; - } - } else { - pr_warn("No GPE found for gmux\n"); - gmux_data->gpe = -1; - } - - if (vga_switcheroo_register_handler(&gmux_handler)) { - ret = -ENODEV; - goto err_register_handler; - } - - init_completion(&gmux_data->powerchange_done); - apple_gmux_data = gmux_data; - gmux_enable_interrupts(gmux_data); - return 0; -err_register_handler: - if (gmux_data->gpe >= 0) - acpi_disable_gpe(NULL, gmux_data->gpe); -err_enable_gpe: - if (gmux_data->gpe >= 0) - acpi_remove_notify_handler(gmux_data->dhandle, - ACPI_DEVICE_NOTIFY, - &gmux_notify_handler); -err_notify: - backlight_device_unregister(bdev); err_release: release_region(gmux_data->iostart, gmux_data->iolen); err_free: @@ -581,23 +212,14 @@ static void __devexit gmux_remove(struct pnp_dev *pnp) { struct apple_gmux_data *gmux_data = pnp_get_drvdata(pnp); - vga_switcheroo_unregister_handler(); - gmux_disable_interrupts(gmux_data); - if (gmux_data->gpe >= 0) { - acpi_disable_gpe(NULL, gmux_data->gpe); - acpi_remove_notify_handler(gmux_data->dhandle, - ACPI_DEVICE_NOTIFY, - &gmux_notify_handler); - } - backlight_device_unregister(gmux_data->bdev); - release_region(gmux_data->iostart, gmux_data->iolen); - apple_gmux_data = NULL; kfree(gmux_data); acpi_video_dmi_demote_vendor(); +#ifdef CONFIG_ACPI_VIDEO acpi_video_register(); +#endif apple_bl_register(); } @@ -611,8 +233,6 @@ static struct pnp_driver gmux_pnp_driver = { .probe = gmux_probe, .remove = __devexit_p(gmux_remove), .id_table = gmux_device_ids, - .suspend = gmux_suspend, - .resume = gmux_resume }; static int __init apple_gmux_init(void) diff --git a/trunk/drivers/platform/x86/asus-laptop.c b/trunk/drivers/platform/x86/asus-laptop.c index 4b568df56643..e38f91be0b10 100644 --- a/trunk/drivers/platform/x86/asus-laptop.c +++ b/trunk/drivers/platform/x86/asus-laptop.c @@ -85,7 +85,7 @@ static char *wled_type = "unknown"; static char *bled_type = "unknown"; module_param(wled_type, charp, 0444); -MODULE_PARM_DESC(wled_type, "Set the wled type on boot " +MODULE_PARM_DESC(wlan_status, "Set the wled type on boot " "(unknown, led or rfkill). " "default is unknown"); @@ -863,9 +863,9 @@ static ssize_t show_infos(struct device *dev, * The significance of others is yet to be found. * If we don't find the method, we assume the device are present. */ - rv = acpi_evaluate_integer(asus->handle, "HWRS", NULL, &temp); + rv = acpi_evaluate_integer(asus->handle, "HRWS", NULL, &temp); if (!ACPI_FAILURE(rv)) - len += sprintf(page + len, "HWRS value : %#x\n", + len += sprintf(page + len, "HRWS value : %#x\n", (uint) temp); /* * Another value for userspace: the ASYM method returns 0x02 for @@ -1751,9 +1751,9 @@ static int asus_laptop_get_info(struct asus_laptop *asus) * The significance of others is yet to be found. */ status = - acpi_evaluate_integer(asus->handle, "HWRS", NULL, &hwrs_result); + acpi_evaluate_integer(asus->handle, "HRWS", NULL, &hwrs_result); if (!ACPI_FAILURE(status)) - pr_notice(" HWRS returned %x", (int)hwrs_result); + pr_notice(" HRWS returned %x", (int)hwrs_result); if (!acpi_check_handle(asus->handle, METHOD_WL_STATUS, NULL)) asus->have_rsts = true; diff --git a/trunk/drivers/platform/x86/asus-wmi.c b/trunk/drivers/platform/x86/asus-wmi.c index c0e9ff489b24..c7a36f6b0580 100644 --- a/trunk/drivers/platform/x86/asus-wmi.c +++ b/trunk/drivers/platform/x86/asus-wmi.c @@ -47,7 +47,9 @@ #include #include #include +#ifdef CONFIG_ACPI_VIDEO #include +#endif #include "asus-wmi.h" @@ -99,7 +101,6 @@ MODULE_LICENSE("GPL"); #define ASUS_WMI_DEVID_WIRELESS_LED 0x00010002 #define ASUS_WMI_DEVID_CWAP 0x00010003 #define ASUS_WMI_DEVID_WLAN 0x00010011 -#define ASUS_WMI_DEVID_WLAN_LED 0x00010012 #define ASUS_WMI_DEVID_BLUETOOTH 0x00010013 #define ASUS_WMI_DEVID_GPS 0x00010015 #define ASUS_WMI_DEVID_WIMAX 0x00010017 @@ -730,21 +731,8 @@ static int asus_rfkill_set(void *data, bool blocked) { struct asus_rfkill *priv = data; u32 ctrl_param = !blocked; - u32 dev_id = priv->dev_id; - /* - * If the user bit is set, BIOS can't set and record the wlan status, - * it will report the value read from id ASUS_WMI_DEVID_WLAN_LED - * while we query the wlan status through WMI(ASUS_WMI_DEVID_WLAN). - * So, we have to record wlan status in id ASUS_WMI_DEVID_WLAN_LED - * while setting the wlan status through WMI. - * This is also the behavior that windows app will do. - */ - if ((dev_id == ASUS_WMI_DEVID_WLAN) && - priv->asus->driver->wlan_ctrl_by_user) - dev_id = ASUS_WMI_DEVID_WLAN_LED; - - return asus_wmi_set_devstate(dev_id, ctrl_param, NULL); + return asus_wmi_set_devstate(priv->dev_id, ctrl_param, NULL); } static void asus_rfkill_query(struct rfkill *rfkill, void *data) @@ -1665,7 +1653,6 @@ static int asus_wmi_add(struct platform_device *pdev) struct asus_wmi *asus; acpi_status status; int err; - u32 result; asus = kzalloc(sizeof(struct asus_wmi), GFP_KERNEL); if (!asus) @@ -1702,8 +1689,10 @@ static int asus_wmi_add(struct platform_device *pdev) if (asus->driver->quirks->wmi_backlight_power) acpi_video_dmi_promote_vendor(); if (!acpi_video_backlight_support()) { +#ifdef CONFIG_ACPI_VIDEO pr_info("Disabling ACPI video driver\n"); acpi_video_unregister(); +#endif err = asus_wmi_backlight_init(asus); if (err && err != -ENODEV) goto fail_backlight; @@ -1722,10 +1711,6 @@ static int asus_wmi_add(struct platform_device *pdev) if (err) goto fail_debugfs; - asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_WLAN, &result); - if (result & (ASUS_WMI_DSTS_PRESENCE_BIT | ASUS_WMI_DSTS_USER_BIT)) - asus->driver->wlan_ctrl_by_user = 1; - return 0; fail_debugfs: diff --git a/trunk/drivers/platform/x86/asus-wmi.h b/trunk/drivers/platform/x86/asus-wmi.h index 4c9bd38bb0a2..9c1da8b81bea 100644 --- a/trunk/drivers/platform/x86/asus-wmi.h +++ b/trunk/drivers/platform/x86/asus-wmi.h @@ -46,7 +46,6 @@ struct quirk_entry { struct asus_wmi_driver { int brightness; int panel_power; - int wlan_ctrl_by_user; const char *name; struct module *owner; diff --git a/trunk/drivers/platform/x86/classmate-laptop.c b/trunk/drivers/platform/x86/classmate-laptop.c index c87ff16873f9..2ca7dd1ab3e4 100644 --- a/trunk/drivers/platform/x86/classmate-laptop.c +++ b/trunk/drivers/platform/x86/classmate-laptop.c @@ -350,7 +350,6 @@ static void cmpc_accel_idev_init_v4(struct input_dev *inputdev) inputdev->close = cmpc_accel_close_v4; } -#ifdef CONFIG_PM_SLEEP static int cmpc_accel_suspend_v4(struct device *dev) { struct input_dev *inputdev; @@ -385,7 +384,6 @@ static int cmpc_accel_resume_v4(struct device *dev) return 0; } -#endif static int cmpc_accel_add_v4(struct acpi_device *acpi) { @@ -725,10 +723,8 @@ static void cmpc_tablet_handler(struct acpi_device *dev, u32 event) struct input_dev *inputdev = dev_get_drvdata(&dev->dev); if (event == 0x81) { - if (ACPI_SUCCESS(cmpc_get_tablet(dev->handle, &val))) { + if (ACPI_SUCCESS(cmpc_get_tablet(dev->handle, &val))) input_report_switch(inputdev, SW_TABLET_MODE, !val); - input_sync(inputdev); - } } } @@ -741,10 +737,8 @@ static void cmpc_tablet_idev_init(struct input_dev *inputdev) set_bit(SW_TABLET_MODE, inputdev->swbit); acpi = to_acpi_device(inputdev->dev.parent); - if (ACPI_SUCCESS(cmpc_get_tablet(acpi->handle, &val))) { + if (ACPI_SUCCESS(cmpc_get_tablet(acpi->handle, &val))) input_report_switch(inputdev, SW_TABLET_MODE, !val); - input_sync(inputdev); - } } static int cmpc_tablet_add(struct acpi_device *acpi) @@ -758,19 +752,15 @@ static int cmpc_tablet_remove(struct acpi_device *acpi, int type) return cmpc_remove_acpi_notify_device(acpi); } -#ifdef CONFIG_PM_SLEEP static int cmpc_tablet_resume(struct device *dev) { struct input_dev *inputdev = dev_get_drvdata(dev); unsigned long long val = 0; - if (ACPI_SUCCESS(cmpc_get_tablet(to_acpi_device(dev)->handle, &val))) { + if (ACPI_SUCCESS(cmpc_get_tablet(to_acpi_device(dev)->handle, &val))) input_report_switch(inputdev, SW_TABLET_MODE, !val); - input_sync(inputdev); - } return 0; } -#endif static SIMPLE_DEV_PM_OPS(cmpc_tablet_pm, NULL, cmpc_tablet_resume); diff --git a/trunk/drivers/platform/x86/dell-laptop.c b/trunk/drivers/platform/x86/dell-laptop.c index 927c33af67ec..4e96e8c0b60f 100644 --- a/trunk/drivers/platform/x86/dell-laptop.c +++ b/trunk/drivers/platform/x86/dell-laptop.c @@ -211,7 +211,7 @@ static struct dmi_system_id __devinitdata dell_quirks[] = { .ident = "Dell Inspiron 5420", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 5420"), + DMI_MATCH(DMI_PRODUCT_NAME, "Isnpiron 5420"), }, .driver_data = &quirk_dell_vostro_v130, }, @@ -220,7 +220,7 @@ static struct dmi_system_id __devinitdata dell_quirks[] = { .ident = "Dell Inspiron 5520", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 5520"), + DMI_MATCH(DMI_PRODUCT_NAME, "Isnpiron 5520"), }, .driver_data = &quirk_dell_vostro_v130, }, @@ -229,7 +229,7 @@ static struct dmi_system_id __devinitdata dell_quirks[] = { .ident = "Dell Inspiron 5720", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 5720"), + DMI_MATCH(DMI_PRODUCT_NAME, "Isnpiron 5720"), }, .driver_data = &quirk_dell_vostro_v130, }, @@ -238,7 +238,7 @@ static struct dmi_system_id __devinitdata dell_quirks[] = { .ident = "Dell Inspiron 7420", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 7420"), + DMI_MATCH(DMI_PRODUCT_NAME, "Isnpiron 7420"), }, .driver_data = &quirk_dell_vostro_v130, }, @@ -247,7 +247,7 @@ static struct dmi_system_id __devinitdata dell_quirks[] = { .ident = "Dell Inspiron 7520", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 7520"), + DMI_MATCH(DMI_PRODUCT_NAME, "Isnpiron 7520"), }, .driver_data = &quirk_dell_vostro_v130, }, @@ -256,7 +256,7 @@ static struct dmi_system_id __devinitdata dell_quirks[] = { .ident = "Dell Inspiron 7720", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 7720"), + DMI_MATCH(DMI_PRODUCT_NAME, "Isnpiron 7720"), }, .driver_data = &quirk_dell_vostro_v130, }, diff --git a/trunk/drivers/platform/x86/eeepc-laptop.c b/trunk/drivers/platform/x86/eeepc-laptop.c index 5ca264179f4e..dab91b48d22c 100644 --- a/trunk/drivers/platform/x86/eeepc-laptop.c +++ b/trunk/drivers/platform/x86/eeepc-laptop.c @@ -610,12 +610,12 @@ static void eeepc_rfkill_hotplug(struct eeepc_laptop *eeepc, acpi_handle handle) if (!bus) { pr_warn("Unable to find PCI bus 1?\n"); - goto out_put_dev; + goto out_unlock; } if (pci_bus_read_config_dword(bus, 0, PCI_VENDOR_ID, &l)) { pr_err("Unable to read PCI config space?\n"); - goto out_put_dev; + goto out_unlock; } absent = (l == 0xffffffff); @@ -627,7 +627,7 @@ static void eeepc_rfkill_hotplug(struct eeepc_laptop *eeepc, acpi_handle handle) absent ? "absent" : "present"); pr_warn("skipped wireless hotplug as probably " "inappropriate for this model\n"); - goto out_put_dev; + goto out_unlock; } if (!blocked) { @@ -635,7 +635,7 @@ static void eeepc_rfkill_hotplug(struct eeepc_laptop *eeepc, acpi_handle handle) if (dev) { /* Device already present */ pci_dev_put(dev); - goto out_put_dev; + goto out_unlock; } dev = pci_scan_single_device(bus, 0); if (dev) { @@ -650,8 +650,6 @@ static void eeepc_rfkill_hotplug(struct eeepc_laptop *eeepc, acpi_handle handle) pci_dev_put(dev); } } -out_put_dev: - pci_dev_put(port); } out_unlock: diff --git a/trunk/drivers/platform/x86/fujitsu-tablet.c b/trunk/drivers/platform/x86/fujitsu-tablet.c index 7acae3f85f3b..d2e41735a47b 100644 --- a/trunk/drivers/platform/x86/fujitsu-tablet.c +++ b/trunk/drivers/platform/x86/fujitsu-tablet.c @@ -440,13 +440,11 @@ static int __devexit acpi_fujitsu_remove(struct acpi_device *adev, int type) return 0; } -#ifdef CONFIG_PM_SLEEP static int acpi_fujitsu_resume(struct device *dev) { fujitsu_reset(); return 0; } -#endif static SIMPLE_DEV_PM_OPS(acpi_fujitsu_pm, NULL, acpi_fujitsu_resume); diff --git a/trunk/drivers/platform/x86/hdaps.c b/trunk/drivers/platform/x86/hdaps.c index 777c7e3dda51..d9ab6f64dcec 100644 --- a/trunk/drivers/platform/x86/hdaps.c +++ b/trunk/drivers/platform/x86/hdaps.c @@ -305,12 +305,10 @@ static int hdaps_probe(struct platform_device *dev) return 0; } -#ifdef CONFIG_PM_SLEEP static int hdaps_resume(struct device *dev) { return hdaps_device_init(); } -#endif static SIMPLE_DEV_PM_OPS(hdaps_pm, NULL, hdaps_resume); diff --git a/trunk/drivers/platform/x86/hp_accel.c b/trunk/drivers/platform/x86/hp_accel.c index 6b9af989632b..f4d91154ad67 100644 --- a/trunk/drivers/platform/x86/hp_accel.c +++ b/trunk/drivers/platform/x86/hp_accel.c @@ -352,7 +352,7 @@ static int lis3lv02d_remove(struct acpi_device *device, int type) } -#ifdef CONFIG_PM_SLEEP +#ifdef CONFIG_PM static int lis3lv02d_suspend(struct device *dev) { /* make sure the device is off when we suspend */ diff --git a/trunk/drivers/platform/x86/ideapad-laptop.c b/trunk/drivers/platform/x86/ideapad-laptop.c index dae7abe1d711..17f6dfd8dbfb 100644 --- a/trunk/drivers/platform/x86/ideapad-laptop.c +++ b/trunk/drivers/platform/x86/ideapad-laptop.c @@ -36,7 +36,6 @@ #include #include #include -#include #define IDEAPAD_RFKILL_DEV_NUM (3) @@ -64,11 +63,8 @@ enum { VPCCMD_R_3G, VPCCMD_W_3G, VPCCMD_R_ODD, /* 0x21 */ - VPCCMD_W_FAN, - VPCCMD_R_RF, + VPCCMD_R_RF = 0x23, VPCCMD_W_RF, - VPCCMD_R_FAN = 0x2B, - VPCCMD_R_SPECIAL_BUTTONS = 0x31, VPCCMD_W_BL_POWER = 0x33, }; @@ -360,46 +356,14 @@ static ssize_t store_ideapad_cam(struct device *dev, return -EINVAL; ret = write_ec_cmd(ideapad_handle, VPCCMD_W_CAMERA, state); if (ret < 0) - return -EIO; + return ret; return count; } static DEVICE_ATTR(camera_power, 0644, show_ideapad_cam, store_ideapad_cam); -static ssize_t show_ideapad_fan(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - unsigned long result; - - if (read_ec_data(ideapad_handle, VPCCMD_R_FAN, &result)) - return sprintf(buf, "-1\n"); - return sprintf(buf, "%lu\n", result); -} - -static ssize_t store_ideapad_fan(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - int ret, state; - - if (!count) - return 0; - if (sscanf(buf, "%i", &state) != 1) - return -EINVAL; - if (state < 0 || state > 4 || state == 3) - return -EINVAL; - ret = write_ec_cmd(ideapad_handle, VPCCMD_W_FAN, state); - if (ret < 0) - return -EIO; - return count; -} - -static DEVICE_ATTR(fan_mode, 0644, show_ideapad_fan, store_ideapad_fan); - static struct attribute *ideapad_attributes[] = { &dev_attr_camera_power.attr, - &dev_attr_fan_mode.attr, NULL }; @@ -413,10 +377,7 @@ static umode_t ideapad_is_visible(struct kobject *kobj, if (attr == &dev_attr_camera_power.attr) supported = test_bit(CFG_CAMERA_BIT, &(priv->cfg)); - else if (attr == &dev_attr_fan_mode.attr) { - unsigned long value; - supported = !read_ec_data(ideapad_handle, VPCCMD_R_FAN, &value); - } else + else supported = true; return supported ? attr->mode : 0; @@ -557,15 +518,9 @@ static void ideapad_platform_exit(struct ideapad_private *priv) */ static const struct key_entry ideapad_keymap[] = { { KE_KEY, 6, { KEY_SWITCHVIDEOMODE } }, - { KE_KEY, 7, { KEY_CAMERA } }, - { KE_KEY, 11, { KEY_F16 } }, { KE_KEY, 13, { KEY_WLAN } }, { KE_KEY, 16, { KEY_PROG1 } }, { KE_KEY, 17, { KEY_PROG2 } }, - { KE_KEY, 64, { KEY_PROG3 } }, - { KE_KEY, 65, { KEY_PROG4 } }, - { KE_KEY, 66, { KEY_TOUCHPAD_OFF } }, - { KE_KEY, 67, { KEY_TOUCHPAD_ON } }, { KE_END, 0 }, }; @@ -632,28 +587,6 @@ static void ideapad_input_novokey(struct ideapad_private *priv) ideapad_input_report(priv, 16); } -static void ideapad_check_special_buttons(struct ideapad_private *priv) -{ - unsigned long bit, value; - - read_ec_data(ideapad_handle, VPCCMD_R_SPECIAL_BUTTONS, &value); - - for (bit = 0; bit < 16; bit++) { - if (test_bit(bit, &value)) { - switch (bit) { - case 6: - /* Thermal Management button */ - ideapad_input_report(priv, 65); - break; - case 1: - /* OneKey Theater button */ - ideapad_input_report(priv, 64); - break; - } - } - } -} - /* * backlight */ @@ -758,24 +691,6 @@ static const struct acpi_device_id ideapad_device_ids[] = { }; MODULE_DEVICE_TABLE(acpi, ideapad_device_ids); -static void ideapad_sync_touchpad_state(struct acpi_device *adevice) -{ - struct ideapad_private *priv = dev_get_drvdata(&adevice->dev); - unsigned long value; - - /* Without reading from EC touchpad LED doesn't switch state */ - if (!read_ec_data(adevice->handle, VPCCMD_R_TOUCHPAD, &value)) { - /* Some IdeaPads don't really turn off touchpad - they only - * switch the LED state. We (de)activate KBC AUX port to turn - * touchpad off and on. We send KEY_TOUCHPAD_OFF and - * KEY_TOUCHPAD_ON to not to get out of sync with LED */ - unsigned char param; - i8042_command(¶m, value ? I8042_CMD_AUX_ENABLE : - I8042_CMD_AUX_DISABLE); - ideapad_input_report(priv, value ? 67 : 66); - } -} - static int __devinit ideapad_acpi_add(struct acpi_device *adevice) { int ret, i; @@ -812,7 +727,6 @@ static int __devinit ideapad_acpi_add(struct acpi_device *adevice) priv->rfk[i] = NULL; } ideapad_sync_rfk_state(priv); - ideapad_sync_touchpad_state(adevice); if (!acpi_video_backlight_support()) { ret = ideapad_backlight_init(priv); @@ -871,14 +785,9 @@ static void ideapad_acpi_notify(struct acpi_device *adevice, u32 event) ideapad_sync_rfk_state(priv); break; case 13: - case 11: - case 7: case 6: ideapad_input_report(priv, vpc_bit); break; - case 5: - ideapad_sync_touchpad_state(adevice); - break; case 4: ideapad_backlight_notify_brightness(priv); break; @@ -888,9 +797,6 @@ static void ideapad_acpi_notify(struct acpi_device *adevice, u32 event) case 2: ideapad_backlight_notify_power(priv); break; - case 0: - ideapad_check_special_buttons(priv); - break; default: pr_info("Unknown event: %lu\n", vpc_bit); } @@ -898,15 +804,6 @@ static void ideapad_acpi_notify(struct acpi_device *adevice, u32 event) } } -static int ideapad_acpi_resume(struct device *device) -{ - ideapad_sync_rfk_state(ideapad_priv); - ideapad_sync_touchpad_state(to_acpi_device(device)); - return 0; -} - -static SIMPLE_DEV_PM_OPS(ideapad_pm, NULL, ideapad_acpi_resume); - static struct acpi_driver ideapad_acpi_driver = { .name = "ideapad_acpi", .class = "IdeaPad", @@ -914,7 +811,6 @@ static struct acpi_driver ideapad_acpi_driver = { .ops.add = ideapad_acpi_add, .ops.remove = ideapad_acpi_remove, .ops.notify = ideapad_acpi_notify, - .drv.pm = &ideapad_pm, .owner = THIS_MODULE, }; diff --git a/trunk/drivers/platform/x86/msi-laptop.c b/trunk/drivers/platform/x86/msi-laptop.c index 2111dbb7e1e3..f64441844317 100644 --- a/trunk/drivers/platform/x86/msi-laptop.c +++ b/trunk/drivers/platform/x86/msi-laptop.c @@ -85,9 +85,7 @@ #define MSI_STANDARD_EC_TOUCHPAD_ADDRESS 0xe4 #define MSI_STANDARD_EC_TOUCHPAD_MASK (1 << 4) -#ifdef CONFIG_PM_SLEEP static int msi_laptop_resume(struct device *device); -#endif static SIMPLE_DEV_PM_OPS(msi_laptop_pm, NULL, msi_laptop_resume); #define MSI_STANDARD_EC_DEVICES_EXISTS_ADDRESS 0x2f @@ -755,7 +753,6 @@ static int rfkill_init(struct platform_device *sdev) return retval; } -#ifdef CONFIG_PM_SLEEP static int msi_laptop_resume(struct device *device) { u8 data; @@ -776,7 +773,6 @@ static int msi_laptop_resume(struct device *device) return 0; } -#endif static int __init msi_laptop_input_setup(void) { diff --git a/trunk/drivers/platform/x86/panasonic-laptop.c b/trunk/drivers/platform/x86/panasonic-laptop.c index 8e8caa767d6a..24480074bcf0 100644 --- a/trunk/drivers/platform/x86/panasonic-laptop.c +++ b/trunk/drivers/platform/x86/panasonic-laptop.c @@ -188,9 +188,7 @@ static const struct acpi_device_id pcc_device_ids[] = { }; MODULE_DEVICE_TABLE(acpi, pcc_device_ids); -#ifdef CONFIG_PM_SLEEP static int acpi_pcc_hotkey_resume(struct device *dev); -#endif static SIMPLE_DEV_PM_OPS(acpi_pcc_hotkey_pm, NULL, acpi_pcc_hotkey_resume); static struct acpi_driver acpi_pcc_driver = { @@ -542,7 +540,6 @@ static void acpi_pcc_destroy_input(struct pcc_acpi *pcc) /* kernel module interface */ -#ifdef CONFIG_PM_SLEEP static int acpi_pcc_hotkey_resume(struct device *dev) { struct pcc_acpi *pcc; @@ -559,7 +556,6 @@ static int acpi_pcc_hotkey_resume(struct device *dev) return acpi_pcc_write_sset(pcc, SINF_STICKY_KEY, pcc->sticky_mode); } -#endif static int acpi_pcc_hotkey_add(struct acpi_device *device) { diff --git a/trunk/drivers/platform/x86/samsung-laptop.c b/trunk/drivers/platform/x86/samsung-laptop.c index dd90d15f5210..c1ca7bcebb66 100644 --- a/trunk/drivers/platform/x86/samsung-laptop.c +++ b/trunk/drivers/platform/x86/samsung-laptop.c @@ -26,7 +26,9 @@ #include #include #include +#ifdef CONFIG_ACPI_VIDEO #include +#endif /* * This driver is needed because a number of Samsung laptops do not hook @@ -1556,7 +1558,9 @@ static int __init samsung_init(void) samsung->handle_backlight = false; } else if (samsung->quirks->broken_acpi_video) { pr_info("Disabling ACPI video driver\n"); +#ifdef CONFIG_ACPI_VIDEO acpi_video_unregister(); +#endif } #endif diff --git a/trunk/drivers/platform/x86/sony-laptop.c b/trunk/drivers/platform/x86/sony-laptop.c index daaddec68def..9363969ad07a 100644 --- a/trunk/drivers/platform/x86/sony-laptop.c +++ b/trunk/drivers/platform/x86/sony-laptop.c @@ -140,10 +140,7 @@ MODULE_PARM_DESC(kbd_backlight_timeout, "1 for 30 seconds, 2 for 60 seconds and 3 to disable timeout " "(default: 0)"); -#ifdef CONFIG_PM_SLEEP static void sony_nc_kbd_backlight_resume(void); -static void sony_nc_thermal_resume(void); -#endif static int sony_nc_kbd_backlight_setup(struct platform_device *pd, unsigned int handle); static void sony_nc_kbd_backlight_cleanup(struct platform_device *pd); @@ -154,6 +151,7 @@ static void sony_nc_battery_care_cleanup(struct platform_device *pd); static int sony_nc_thermal_setup(struct platform_device *pd); static void sony_nc_thermal_cleanup(struct platform_device *pd); +static void sony_nc_thermal_resume(void); static int sony_nc_lid_resume_setup(struct platform_device *pd); static void sony_nc_lid_resume_cleanup(struct platform_device *pd); @@ -1433,7 +1431,6 @@ static void sony_nc_function_cleanup(struct platform_device *pd) sony_nc_handles_cleanup(pd); } -#ifdef CONFIG_PM_SLEEP static void sony_nc_function_resume(void) { unsigned int i, result, bitmask, arg; @@ -1511,7 +1508,6 @@ static int sony_nc_resume(struct device *dev) return 0; } -#endif static SIMPLE_DEV_PM_OPS(sony_nc_pm, NULL, sony_nc_resume); @@ -1876,7 +1872,6 @@ static void sony_nc_kbd_backlight_cleanup(struct platform_device *pd) } } -#ifdef CONFIG_PM_SLEEP static void sony_nc_kbd_backlight_resume(void) { int ignore = 0; @@ -1893,7 +1888,6 @@ static void sony_nc_kbd_backlight_resume(void) (kbdbl_ctl->base + 0x200) | (kbdbl_ctl->timeout << 0x10), &ignore); } -#endif struct battery_care_control { struct device_attribute attrs[2]; @@ -2216,7 +2210,6 @@ static void sony_nc_thermal_cleanup(struct platform_device *pd) } } -#ifdef CONFIG_PM_SLEEP static void sony_nc_thermal_resume(void) { unsigned int status = sony_nc_thermal_mode_get(); @@ -2224,7 +2217,6 @@ static void sony_nc_thermal_resume(void) if (status != th_handle->mode) sony_nc_thermal_mode_set(th_handle->mode); } -#endif /* resume on LID open */ struct snc_lid_resume_control { @@ -4295,7 +4287,6 @@ static int sony_pic_add(struct acpi_device *device) return result; } -#ifdef CONFIG_PM_SLEEP static int sony_pic_suspend(struct device *dev) { if (sony_pic_disable(to_acpi_device(dev))) @@ -4309,7 +4300,6 @@ static int sony_pic_resume(struct device *dev) spic_dev.cur_ioport, spic_dev.cur_irq); return 0; } -#endif static SIMPLE_DEV_PM_OPS(sony_pic_pm, sony_pic_suspend, sony_pic_resume); diff --git a/trunk/drivers/platform/x86/thinkpad_acpi.c b/trunk/drivers/platform/x86/thinkpad_acpi.c index 52daaa816e53..e7f73287636c 100644 --- a/trunk/drivers/platform/x86/thinkpad_acpi.c +++ b/trunk/drivers/platform/x86/thinkpad_acpi.c @@ -545,7 +545,7 @@ TPACPI_HANDLE(hkey, ec, "\\_SB.HKEY", /* 600e/x, 770e, 770x */ */ static int acpi_evalf(acpi_handle handle, - int *res, char *method, char *fmt, ...) + void *res, char *method, char *fmt, ...) { char *fmt0 = fmt; struct acpi_object_list params; @@ -606,7 +606,7 @@ static int acpi_evalf(acpi_handle handle, success = (status == AE_OK && out_obj.type == ACPI_TYPE_INTEGER); if (success && res) - *res = out_obj.integer.value; + *(int *)res = out_obj.integer.value; break; case 'v': /* void */ success = status == AE_OK; @@ -922,7 +922,6 @@ static struct input_dev *tpacpi_inputdev; static struct mutex tpacpi_inputdev_send_mutex; static LIST_HEAD(tpacpi_all_drivers); -#ifdef CONFIG_PM_SLEEP static int tpacpi_suspend_handler(struct device *dev) { struct ibm_struct *ibm, *itmp; @@ -950,7 +949,6 @@ static int tpacpi_resume_handler(struct device *dev) return 0; } -#endif static SIMPLE_DEV_PM_OPS(tpacpi_pm, tpacpi_suspend_handler, tpacpi_resume_handler); @@ -7386,18 +7384,17 @@ static int fan_get_status(u8 *status) * Add TPACPI_FAN_RD_ACPI_FANS ? */ switch (fan_status_access_mode) { - case TPACPI_FAN_RD_ACPI_GFAN: { + case TPACPI_FAN_RD_ACPI_GFAN: /* 570, 600e/x, 770e, 770x */ - int res; - if (unlikely(!acpi_evalf(gfan_handle, &res, NULL, "d"))) + if (unlikely(!acpi_evalf(gfan_handle, &s, NULL, "d"))) return -EIO; if (likely(status)) - *status = res & 0x07; + *status = s & 0x07; break; - } + case TPACPI_FAN_RD_TPEC: /* all except 570, 600e/x, 770e, 770x */ if (unlikely(!acpi_ec_read(fan_status_offset, &s))) @@ -8665,13 +8662,6 @@ static int __must_check __init get_thinkpad_model_data( tp->model_str = kstrdup(s, GFP_KERNEL); if (!tp->model_str) return -ENOMEM; - } else { - s = dmi_get_system_info(DMI_BIOS_VENDOR); - if (s && !(strnicmp(s, "Lenovo", 6))) { - tp->model_str = kstrdup(s, GFP_KERNEL); - if (!tp->model_str) - return -ENOMEM; - } } s = dmi_get_system_info(DMI_PRODUCT_NAME); diff --git a/trunk/drivers/platform/x86/toshiba_acpi.c b/trunk/drivers/platform/x86/toshiba_acpi.c index 5f1256d5e933..c13ba5bac93f 100644 --- a/trunk/drivers/platform/x86/toshiba_acpi.c +++ b/trunk/drivers/platform/x86/toshiba_acpi.c @@ -1296,7 +1296,6 @@ static void toshiba_acpi_notify(struct acpi_device *acpi_dev, u32 event) } } -#ifdef CONFIG_PM_SLEEP static int toshiba_acpi_suspend(struct device *device) { struct toshiba_acpi_dev *dev = acpi_driver_data(to_acpi_device(device)); @@ -1318,7 +1317,6 @@ static int toshiba_acpi_resume(struct device *device) return 0; } -#endif static SIMPLE_DEV_PM_OPS(toshiba_acpi_pm, toshiba_acpi_suspend, toshiba_acpi_resume); diff --git a/trunk/drivers/platform/x86/toshiba_bluetooth.c b/trunk/drivers/platform/x86/toshiba_bluetooth.c index 5e5d6317d690..715a43cb5e3c 100644 --- a/trunk/drivers/platform/x86/toshiba_bluetooth.c +++ b/trunk/drivers/platform/x86/toshiba_bluetooth.c @@ -41,9 +41,7 @@ static const struct acpi_device_id bt_device_ids[] = { }; MODULE_DEVICE_TABLE(acpi, bt_device_ids); -#ifdef CONFIG_PM_SLEEP static int toshiba_bt_resume(struct device *dev); -#endif static SIMPLE_DEV_PM_OPS(toshiba_bt_pm, NULL, toshiba_bt_resume); static struct acpi_driver toshiba_bt_rfkill_driver = { @@ -92,12 +90,10 @@ static void toshiba_bt_rfkill_notify(struct acpi_device *device, u32 event) toshiba_bluetooth_enable(device->handle); } -#ifdef CONFIG_PM_SLEEP static int toshiba_bt_resume(struct device *dev) { return toshiba_bluetooth_enable(to_acpi_device(dev)->handle); } -#endif static int toshiba_bt_rfkill_add(struct acpi_device *device) { diff --git a/trunk/drivers/platform/x86/xo15-ebook.c b/trunk/drivers/platform/x86/xo15-ebook.c index 38ba39d7ca7d..849c07c13bf6 100644 --- a/trunk/drivers/platform/x86/xo15-ebook.c +++ b/trunk/drivers/platform/x86/xo15-ebook.c @@ -77,12 +77,10 @@ static void ebook_switch_notify(struct acpi_device *device, u32 event) } } -#ifdef CONFIG_PM_SLEEP static int ebook_switch_resume(struct device *dev) { return ebook_send_state(to_acpi_device(dev)); } -#endif static SIMPLE_DEV_PM_OPS(ebook_switch_pm, NULL, ebook_switch_resume); diff --git a/trunk/drivers/power/Kconfig b/trunk/drivers/power/Kconfig index 80978196aae8..c1892f321c46 100644 --- a/trunk/drivers/power/Kconfig +++ b/trunk/drivers/power/Kconfig @@ -29,13 +29,6 @@ config APM_POWER Say Y here to enable support APM status emulation using battery class devices. -config GENERIC_ADC_BATTERY - tristate "Generic battery support using IIO" - depends on IIO - help - Say Y here to enable support for the generic battery driver - which uses IIO framework to read adc. - config MAX8925_POWER tristate "MAX8925 battery charger support" depends on MFD_MAX8925 diff --git a/trunk/drivers/power/Makefile b/trunk/drivers/power/Makefile index e0b4d4284e1d..ee58afb1e71f 100644 --- a/trunk/drivers/power/Makefile +++ b/trunk/drivers/power/Makefile @@ -5,7 +5,6 @@ power_supply-$(CONFIG_SYSFS) += power_supply_sysfs.o power_supply-$(CONFIG_LEDS_TRIGGERS) += power_supply_leds.o obj-$(CONFIG_POWER_SUPPLY) += power_supply.o -obj-$(CONFIG_GENERIC_ADC_BATTERY) += generic-adc-battery.o obj-$(CONFIG_PDA_POWER) += pda_power.o obj-$(CONFIG_APM_POWER) += apm_power.o diff --git a/trunk/drivers/power/generic-adc-battery.c b/trunk/drivers/power/generic-adc-battery.c deleted file mode 100644 index 9bdf44470396..000000000000 --- a/trunk/drivers/power/generic-adc-battery.c +++ /dev/null @@ -1,422 +0,0 @@ -/* - * Generic battery driver code using IIO - * Copyright (C) 2012, Anish Kumar - * based on jz4740-battery.c - * based on s3c_adc_battery.c - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file COPYING in the main directory of this archive for - * more details. - * - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define JITTER_DEFAULT 10 /* hope 10ms is enough */ - -enum gab_chan_type { - GAB_VOLTAGE = 0, - GAB_CURRENT, - GAB_POWER, - GAB_MAX_CHAN_TYPE -}; - -/* - * gab_chan_name suggests the standard channel names for commonly used - * channel types. - */ -static const char *const gab_chan_name[] = { - [GAB_VOLTAGE] = "voltage", - [GAB_CURRENT] = "current", - [GAB_POWER] = "power", -}; - -struct gab { - struct power_supply psy; - struct iio_channel *channel[GAB_MAX_CHAN_TYPE]; - struct gab_platform_data *pdata; - struct delayed_work bat_work; - int level; - int status; - bool cable_plugged; -}; - -static struct gab *to_generic_bat(struct power_supply *psy) -{ - return container_of(psy, struct gab, psy); -} - -static void gab_ext_power_changed(struct power_supply *psy) -{ - struct gab *adc_bat = to_generic_bat(psy); - - schedule_delayed_work(&adc_bat->bat_work, msecs_to_jiffies(0)); -} - -static const enum power_supply_property gab_props[] = { - POWER_SUPPLY_PROP_STATUS, - POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, - POWER_SUPPLY_PROP_CHARGE_EMPTY_DESIGN, - POWER_SUPPLY_PROP_CHARGE_NOW, - POWER_SUPPLY_PROP_VOLTAGE_NOW, - POWER_SUPPLY_PROP_CURRENT_NOW, - POWER_SUPPLY_PROP_TECHNOLOGY, - POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN, - POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN, - POWER_SUPPLY_PROP_MODEL_NAME, -}; - -/* - * This properties are set based on the received platform data and this - * should correspond one-to-one with enum chan_type. - */ -static const enum power_supply_property gab_dyn_props[] = { - POWER_SUPPLY_PROP_VOLTAGE_NOW, - POWER_SUPPLY_PROP_CURRENT_NOW, - POWER_SUPPLY_PROP_POWER_NOW, -}; - -static bool gab_charge_finished(struct gab *adc_bat) -{ - struct gab_platform_data *pdata = adc_bat->pdata; - bool ret = gpio_get_value(pdata->gpio_charge_finished); - bool inv = pdata->gpio_inverted; - - if (!gpio_is_valid(pdata->gpio_charge_finished)) - return false; - return ret ^ inv; -} - -static int gab_get_status(struct gab *adc_bat) -{ - struct gab_platform_data *pdata = adc_bat->pdata; - struct power_supply_info *bat_info; - - bat_info = &pdata->battery_info; - if (adc_bat->level == bat_info->charge_full_design) - return POWER_SUPPLY_STATUS_FULL; - return adc_bat->status; -} - -static enum gab_chan_type gab_prop_to_chan(enum power_supply_property psp) -{ - switch (psp) { - case POWER_SUPPLY_PROP_POWER_NOW: - return GAB_POWER; - case POWER_SUPPLY_PROP_VOLTAGE_NOW: - return GAB_VOLTAGE; - case POWER_SUPPLY_PROP_CURRENT_NOW: - return GAB_CURRENT; - default: - WARN_ON(1); - break; - } - return GAB_POWER; -} - -static int read_channel(struct gab *adc_bat, enum power_supply_property psp, - int *result) -{ - int ret; - int chan_index; - - chan_index = gab_prop_to_chan(psp); - ret = iio_read_channel_processed(adc_bat->channel[chan_index], - result); - if (ret < 0) - pr_err("read channel error\n"); - return ret; -} - -static int gab_get_property(struct power_supply *psy, - enum power_supply_property psp, union power_supply_propval *val) -{ - struct gab *adc_bat; - struct gab_platform_data *pdata; - struct power_supply_info *bat_info; - int result = 0; - int ret = 0; - - adc_bat = to_generic_bat(psy); - if (!adc_bat) { - dev_err(psy->dev, "no battery infos ?!\n"); - return -EINVAL; - } - pdata = adc_bat->pdata; - bat_info = &pdata->battery_info; - - switch (psp) { - case POWER_SUPPLY_PROP_STATUS: - gab_get_status(adc_bat); - break; - case POWER_SUPPLY_PROP_CHARGE_EMPTY_DESIGN: - val->intval = 0; - break; - case POWER_SUPPLY_PROP_CHARGE_NOW: - val->intval = pdata->cal_charge(result); - break; - case POWER_SUPPLY_PROP_VOLTAGE_NOW: - case POWER_SUPPLY_PROP_CURRENT_NOW: - case POWER_SUPPLY_PROP_POWER_NOW: - ret = read_channel(adc_bat, psp, &result); - if (ret < 0) - goto err; - val->intval = result; - break; - case POWER_SUPPLY_PROP_TECHNOLOGY: - val->intval = bat_info->technology; - break; - case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN: - val->intval = bat_info->voltage_min_design; - break; - case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN: - val->intval = bat_info->voltage_max_design; - break; - case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN: - val->intval = bat_info->charge_full_design; - break; - case POWER_SUPPLY_PROP_MODEL_NAME: - val->strval = bat_info->name; - break; - default: - return -EINVAL; - } -err: - return ret; -} - -static void gab_work(struct work_struct *work) -{ - struct gab *adc_bat; - struct gab_platform_data *pdata; - struct delayed_work *delayed_work; - bool is_plugged; - int status; - - delayed_work = container_of(work, struct delayed_work, work); - adc_bat = container_of(delayed_work, struct gab, bat_work); - pdata = adc_bat->pdata; - status = adc_bat->status; - - is_plugged = power_supply_am_i_supplied(&adc_bat->psy); - adc_bat->cable_plugged = is_plugged; - - if (!is_plugged) - adc_bat->status = POWER_SUPPLY_STATUS_DISCHARGING; - else if (gab_charge_finished(adc_bat)) - adc_bat->status = POWER_SUPPLY_STATUS_NOT_CHARGING; - else - adc_bat->status = POWER_SUPPLY_STATUS_CHARGING; - - if (status != adc_bat->status) - power_supply_changed(&adc_bat->psy); -} - -static irqreturn_t gab_charged(int irq, void *dev_id) -{ - struct gab *adc_bat = dev_id; - struct gab_platform_data *pdata = adc_bat->pdata; - int delay; - - delay = pdata->jitter_delay ? pdata->jitter_delay : JITTER_DEFAULT; - schedule_delayed_work(&adc_bat->bat_work, - msecs_to_jiffies(delay)); - return IRQ_HANDLED; -} - -static int __devinit gab_probe(struct platform_device *pdev) -{ - struct gab *adc_bat; - struct power_supply *psy; - struct gab_platform_data *pdata = pdev->dev.platform_data; - enum power_supply_property *properties; - int ret = 0; - int chan; - int index = 0; - - adc_bat = devm_kzalloc(&pdev->dev, sizeof(*adc_bat), GFP_KERNEL); - if (!adc_bat) { - dev_err(&pdev->dev, "failed to allocate memory\n"); - return -ENOMEM; - } - - psy = &adc_bat->psy; - psy->name = pdata->battery_info.name; - - /* bootup default values for the battery */ - adc_bat->cable_plugged = false; - adc_bat->status = POWER_SUPPLY_STATUS_DISCHARGING; - psy->type = POWER_SUPPLY_TYPE_BATTERY; - psy->get_property = gab_get_property; - psy->external_power_changed = gab_ext_power_changed; - adc_bat->pdata = pdata; - - /* calculate the total number of channels */ - chan = ARRAY_SIZE(gab_chan_name); - - /* - * copying the static properties and allocating extra memory for holding - * the extra configurable properties received from platform data. - */ - psy->properties = kcalloc(ARRAY_SIZE(gab_props) + - ARRAY_SIZE(gab_chan_name), - sizeof(*psy->properties), GFP_KERNEL); - if (!psy->properties) { - ret = -ENOMEM; - goto first_mem_fail; - } - - memcpy(psy->properties, gab_props, sizeof(gab_props)); - properties = psy->properties + sizeof(gab_props); - - /* - * getting channel from iio and copying the battery properties - * based on the channel supported by consumer device. - */ - for (chan = 0; chan < ARRAY_SIZE(gab_chan_name); chan++) { - adc_bat->channel[chan] = iio_channel_get(dev_name(&pdev->dev), - gab_chan_name[chan]); - if (IS_ERR(adc_bat->channel[chan])) { - ret = PTR_ERR(adc_bat->channel[chan]); - } else { - /* copying properties for supported channels only */ - memcpy(properties + sizeof(*(psy->properties)) * index, - &gab_dyn_props[chan], - sizeof(gab_dyn_props[chan])); - index++; - } - } - - /* none of the channels are supported so let's bail out */ - if (index == ARRAY_SIZE(gab_chan_name)) - goto second_mem_fail; - - /* - * Total number of properties is equal to static properties - * plus the dynamic properties.Some properties may not be set - * as come channels may be not be supported by the device.So - * we need to take care of that. - */ - psy->num_properties = ARRAY_SIZE(gab_props) + index; - - ret = power_supply_register(&pdev->dev, psy); - if (ret) - goto err_reg_fail; - - INIT_DELAYED_WORK(&adc_bat->bat_work, gab_work); - - if (gpio_is_valid(pdata->gpio_charge_finished)) { - int irq; - ret = gpio_request(pdata->gpio_charge_finished, "charged"); - if (ret) - goto gpio_req_fail; - - irq = gpio_to_irq(pdata->gpio_charge_finished); - ret = request_any_context_irq(irq, gab_charged, - IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, - "battery charged", adc_bat); - if (ret) - goto err_gpio; - } - - platform_set_drvdata(pdev, adc_bat); - - /* Schedule timer to check current status */ - schedule_delayed_work(&adc_bat->bat_work, - msecs_to_jiffies(0)); - return 0; - -err_gpio: - gpio_free(pdata->gpio_charge_finished); -gpio_req_fail: - power_supply_unregister(psy); -err_reg_fail: - for (chan = 0; ARRAY_SIZE(gab_chan_name); chan++) - iio_channel_release(adc_bat->channel[chan]); -second_mem_fail: - kfree(psy->properties); -first_mem_fail: - return ret; -} - -static int __devexit gab_remove(struct platform_device *pdev) -{ - int chan; - struct gab *adc_bat = platform_get_drvdata(pdev); - struct gab_platform_data *pdata = adc_bat->pdata; - - power_supply_unregister(&adc_bat->psy); - - if (gpio_is_valid(pdata->gpio_charge_finished)) { - free_irq(gpio_to_irq(pdata->gpio_charge_finished), adc_bat); - gpio_free(pdata->gpio_charge_finished); - } - - for (chan = 0; ARRAY_SIZE(gab_chan_name); chan++) - iio_channel_release(adc_bat->channel[chan]); - - kfree(adc_bat->psy.properties); - cancel_delayed_work(&adc_bat->bat_work); - return 0; -} - -#ifdef CONFIG_PM -static int gab_suspend(struct device *dev) -{ - struct gab *adc_bat = dev_get_drvdata(dev); - - cancel_delayed_work_sync(&adc_bat->bat_work); - adc_bat->status = POWER_SUPPLY_STATUS_UNKNOWN; - return 0; -} - -static int gab_resume(struct device *dev) -{ - struct gab *adc_bat = dev_get_drvdata(dev); - struct gab_platform_data *pdata = adc_bat->pdata; - int delay; - - delay = pdata->jitter_delay ? pdata->jitter_delay : JITTER_DEFAULT; - - /* Schedule timer to check current status */ - schedule_delayed_work(&adc_bat->bat_work, - msecs_to_jiffies(delay)); - return 0; -} - -static const struct dev_pm_ops gab_pm_ops = { - .suspend = gab_suspend, - .resume = gab_resume, -}; - -#define GAB_PM_OPS (&gab_pm_ops) -#else -#define GAB_PM_OPS (NULL) -#endif - -static struct platform_driver gab_driver = { - .driver = { - .name = "generic-adc-battery", - .owner = THIS_MODULE, - .pm = GAB_PM_OPS - }, - .probe = gab_probe, - .remove = __devexit_p(gab_remove), -}; -module_platform_driver(gab_driver); - -MODULE_AUTHOR("anish kumar "); -MODULE_DESCRIPTION("generic battery driver using IIO"); -MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/pwm/Kconfig b/trunk/drivers/pwm/Kconfig index 90c5c7357a50..8fc3808d7a3e 100644 --- a/trunk/drivers/pwm/Kconfig +++ b/trunk/drivers/pwm/Kconfig @@ -1,31 +1,12 @@ menuconfig PWM - bool "Pulse-Width Modulation (PWM) Support" + bool "PWM Support" depends on !MACH_JZ4740 && !PUV3_PWM help - Generic Pulse-Width Modulation (PWM) support. - - In Pulse-Width Modulation, a variation of the width of pulses - in a rectangular pulse signal is used as a means to alter the - average power of the signal. Applications include efficient - power delivery and voltage regulation. In computer systems, - PWMs are commonly used to control fans or the brightness of - display backlights. - - This framework provides a generic interface to PWM devices - within the Linux kernel. On the driver side it provides an API - to register and unregister a PWM chip, an abstraction of a PWM - controller, that supports one or more PWM devices. Client - drivers can request PWM devices and use the generic framework - to configure as well as enable and disable them. - - This generic framework replaces the legacy PWM framework which - allows only a single driver implementing the required API. Not - all legacy implementations have been ported to the framework - yet. The framework provides an API that is backward compatible - with the legacy framework so that existing client drivers - continue to work as expected. - - If unsure, say no. + This enables PWM support through the generic PWM framework. + You only need to enable this, if you also want to enable + one or more of the PWM drivers below. + + If unsure, say N. if PWM diff --git a/trunk/drivers/pwm/core.c b/trunk/drivers/pwm/core.c index c6e05078d3ad..ecb76909e946 100644 --- a/trunk/drivers/pwm/core.c +++ b/trunk/drivers/pwm/core.c @@ -129,8 +129,8 @@ static int pwm_device_request(struct pwm_device *pwm, const char *label) return 0; } -static struct pwm_device * -of_pwm_simple_xlate(struct pwm_chip *pc, const struct of_phandle_args *args) +static struct pwm_device *of_pwm_simple_xlate(struct pwm_chip *pc, + const struct of_phandle_args *args) { struct pwm_device *pwm; @@ -149,7 +149,7 @@ of_pwm_simple_xlate(struct pwm_chip *pc, const struct of_phandle_args *args) return pwm; } -static void of_pwmchip_add(struct pwm_chip *chip) +void of_pwmchip_add(struct pwm_chip *chip) { if (!chip->dev || !chip->dev->of_node) return; @@ -162,7 +162,7 @@ static void of_pwmchip_add(struct pwm_chip *chip) of_node_get(chip->dev->of_node); } -static void of_pwmchip_remove(struct pwm_chip *chip) +void of_pwmchip_remove(struct pwm_chip *chip) { if (chip->dev && chip->dev->of_node) of_node_put(chip->dev->of_node); @@ -527,7 +527,7 @@ void __init pwm_add_table(struct pwm_lookup *table, size_t num) struct pwm_device *pwm_get(struct device *dev, const char *con_id) { struct pwm_device *pwm = ERR_PTR(-EPROBE_DEFER); - const char *dev_id = dev ? dev_name(dev) : NULL; + const char *dev_id = dev ? dev_name(dev): NULL; struct pwm_chip *chip = NULL; unsigned int index = 0; unsigned int best = 0; @@ -609,7 +609,7 @@ void pwm_put(struct pwm_device *pwm) mutex_lock(&pwm_lock); if (!test_and_clear_bit(PWMF_REQUESTED, &pwm->flags)) { - pr_warn("PWM device already freed\n"); + pr_warning("PWM device already freed\n"); goto out; } diff --git a/trunk/drivers/pwm/pwm-samsung.c b/trunk/drivers/pwm/pwm-samsung.c index e5187c0ade9f..d10386528c9c 100644 --- a/trunk/drivers/pwm/pwm-samsung.c +++ b/trunk/drivers/pwm/pwm-samsung.c @@ -225,7 +225,6 @@ static int s3c_pwm_probe(struct platform_device *pdev) /* calculate base of control bits in TCON */ s3c->tcon_base = id == 0 ? 0 : (id * 4) + 4; - s3c->chip.dev = &pdev->dev; s3c->chip.ops = &s3c_pwm_ops; s3c->chip.base = -1; s3c->chip.npwm = 1; diff --git a/trunk/drivers/pwm/pwm-tegra.c b/trunk/drivers/pwm/pwm-tegra.c index 057465e0553c..02ce18d5e49a 100644 --- a/trunk/drivers/pwm/pwm-tegra.c +++ b/trunk/drivers/pwm/pwm-tegra.c @@ -187,8 +187,10 @@ static int tegra_pwm_probe(struct platform_device *pdev) } pwm->mmio_base = devm_request_and_ioremap(&pdev->dev, r); - if (!pwm->mmio_base) + if (!pwm->mmio_base) { + dev_err(&pdev->dev, "failed to ioremap() region\n"); return -EADDRNOTAVAIL; + } platform_set_drvdata(pdev, pwm); diff --git a/trunk/drivers/pwm/pwm-tiecap.c b/trunk/drivers/pwm/pwm-tiecap.c index 4b6688909fee..3c2ad284ee3e 100644 --- a/trunk/drivers/pwm/pwm-tiecap.c +++ b/trunk/drivers/pwm/pwm-tiecap.c @@ -100,13 +100,6 @@ static int ecap_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, writel(period_cycles, pc->mmio_base + CAP3); } - if (!test_bit(PWMF_ENABLED, &pwm->flags)) { - reg_val = readw(pc->mmio_base + ECCTL2); - /* Disable APWM mode to put APWM output Low */ - reg_val &= ~ECCTL2_APWM_MODE; - writew(reg_val, pc->mmio_base + ECCTL2); - } - pm_runtime_put_sync(pc->chip.dev); return 0; } @@ -199,8 +192,10 @@ static int __devinit ecap_pwm_probe(struct platform_device *pdev) } pc->mmio_base = devm_request_and_ioremap(&pdev->dev, r); - if (!pc->mmio_base) + if (!pc->mmio_base) { + dev_err(&pdev->dev, "failed to ioremap() registers\n"); return -EADDRNOTAVAIL; + } ret = pwmchip_add(&pc->chip); if (ret < 0) { diff --git a/trunk/drivers/pwm/pwm-tiehrpwm.c b/trunk/drivers/pwm/pwm-tiehrpwm.c index b1996bcd5b78..010d232cb0c8 100644 --- a/trunk/drivers/pwm/pwm-tiehrpwm.c +++ b/trunk/drivers/pwm/pwm-tiehrpwm.c @@ -104,7 +104,6 @@ struct ehrpwm_pwm_chip { struct pwm_chip chip; unsigned int clk_rate; void __iomem *mmio_base; - unsigned long period_cycles[NUM_PWM_CHANNEL]; }; static inline struct ehrpwm_pwm_chip *to_ehrpwm_pwm_chip(struct pwm_chip *chip) @@ -211,7 +210,6 @@ static int ehrpwm_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, unsigned long long c; unsigned long period_cycles, duty_cycles; unsigned short ps_divval, tb_divval; - int i; if (period_ns < 0 || duty_ns < 0 || period_ns > NSEC_PER_SEC) return -ERANGE; @@ -231,28 +229,6 @@ static int ehrpwm_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, duty_cycles = (unsigned long)c; } - /* - * Period values should be same for multiple PWM channels as IP uses - * same period register for multiple channels. - */ - for (i = 0; i < NUM_PWM_CHANNEL; i++) { - if (pc->period_cycles[i] && - (pc->period_cycles[i] != period_cycles)) { - /* - * Allow channel to reconfigure period if no other - * channels being configured. - */ - if (i == pwm->hwpwm) - continue; - - dev_err(chip->dev, "Period value conflicts with channel %d\n", - i); - return -EINVAL; - } - } - - pc->period_cycles[pwm->hwpwm] = period_cycles; - /* Configure clock prescaler to support Low frequency PWM wave */ if (set_prescale_div(period_cycles/PERIOD_MAX, &ps_divval, &tb_divval)) { @@ -344,15 +320,10 @@ static void ehrpwm_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) static void ehrpwm_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm) { - struct ehrpwm_pwm_chip *pc = to_ehrpwm_pwm_chip(chip); - if (test_bit(PWMF_ENABLED, &pwm->flags)) { dev_warn(chip->dev, "Removing PWM device without disabling\n"); pm_runtime_put_sync(chip->dev); } - - /* set period value to zero on free */ - pc->period_cycles[pwm->hwpwm] = 0; } static const struct pwm_ops ehrpwm_pwm_ops = { @@ -400,8 +371,10 @@ static int __devinit ehrpwm_pwm_probe(struct platform_device *pdev) } pc->mmio_base = devm_request_and_ioremap(&pdev->dev, r); - if (!pc->mmio_base) + if (!pc->mmio_base) { + dev_err(&pdev->dev, "failed to ioremap() registers\n"); return -EADDRNOTAVAIL; + } ret = pwmchip_add(&pc->chip); if (ret < 0) { diff --git a/trunk/drivers/pwm/pwm-vt8500.c b/trunk/drivers/pwm/pwm-vt8500.c index ad14389b7144..548021439f0c 100644 --- a/trunk/drivers/pwm/pwm-vt8500.c +++ b/trunk/drivers/pwm/pwm-vt8500.c @@ -41,7 +41,7 @@ static inline void pwm_busy_wait(void __iomem *reg, u8 bitmask) cpu_relax(); if (unlikely(!loops)) - pr_warn("Waiting for status bits 0x%x to clear timed out\n", + pr_warning("Waiting for status bits 0x%x to clear timed out\n", bitmask); } diff --git a/trunk/drivers/rapidio/devices/tsi721.c b/trunk/drivers/rapidio/devices/tsi721.c index d5e1625bbac2..722246cf20ab 100644 --- a/trunk/drivers/rapidio/devices/tsi721.c +++ b/trunk/drivers/rapidio/devices/tsi721.c @@ -435,9 +435,6 @@ static void tsi721_db_dpc(struct work_struct *work) " info %4.4x\n", DBELL_SID(idb.bytes), DBELL_TID(idb.bytes), DBELL_INF(idb.bytes)); } - - wr_ptr = ioread32(priv->regs + - TSI721_IDQ_WP(IDB_QUEUE)) % IDB_QSIZE; } iowrite32(rd_ptr & (IDB_QSIZE - 1), @@ -448,10 +445,6 @@ static void tsi721_db_dpc(struct work_struct *work) regval |= TSI721_SR_CHINT_IDBQRCV; iowrite32(regval, priv->regs + TSI721_SR_CHINTE(IDB_QUEUE)); - - wr_ptr = ioread32(priv->regs + TSI721_IDQ_WP(IDB_QUEUE)) % IDB_QSIZE; - if (wr_ptr != rd_ptr) - schedule_work(&priv->idb_work); } /** @@ -2219,7 +2212,9 @@ static int __devinit tsi721_probe(struct pci_dev *pdev, const struct pci_device_id *id) { struct tsi721_device *priv; + int i, cap; int err; + u32 regval; priv = kzalloc(sizeof(struct tsi721_device), GFP_KERNEL); if (priv == NULL) { @@ -2237,15 +2232,12 @@ static int __devinit tsi721_probe(struct pci_dev *pdev, priv->pdev = pdev; #ifdef DEBUG - { - int i; for (i = 0; i <= PCI_STD_RESOURCE_END; i++) { dev_dbg(&pdev->dev, "res[%d] @ 0x%llx (0x%lx, 0x%lx)\n", i, (unsigned long long)pci_resource_start(pdev, i), (unsigned long)pci_resource_len(pdev, i), pci_resource_flags(pdev, i)); } - } #endif /* * Verify BAR configuration @@ -2328,16 +2320,20 @@ static int __devinit tsi721_probe(struct pci_dev *pdev, dev_info(&pdev->dev, "Unable to set consistent DMA mask\n"); } - BUG_ON(!pci_is_pcie(pdev)); + cap = pci_pcie_cap(pdev); + BUG_ON(cap == 0); /* Clear "no snoop" and "relaxed ordering" bits, use default MRRS. */ - pcie_capability_clear_and_set_word(pdev, PCI_EXP_DEVCTL, - PCI_EXP_DEVCTL_READRQ | PCI_EXP_DEVCTL_RELAX_EN | - PCI_EXP_DEVCTL_NOSNOOP_EN, - 0x2 << MAX_READ_REQUEST_SZ_SHIFT); + pci_read_config_dword(pdev, cap + PCI_EXP_DEVCTL, ®val); + regval &= ~(PCI_EXP_DEVCTL_READRQ | PCI_EXP_DEVCTL_RELAX_EN | + PCI_EXP_DEVCTL_NOSNOOP_EN); + regval |= 0x2 << MAX_READ_REQUEST_SZ_SHIFT; + pci_write_config_dword(pdev, cap + PCI_EXP_DEVCTL, regval); /* Adjust PCIe completion timeout. */ - pcie_capability_clear_and_set_word(pdev, PCI_EXP_DEVCTL2, 0xf, 0x2); + pci_read_config_dword(pdev, cap + PCI_EXP_DEVCTL2, ®val); + regval &= ~(0x0f); + pci_write_config_dword(pdev, cap + PCI_EXP_DEVCTL2, regval | 0x2); /* * FIXUP: correct offsets of MSI-X tables in the MSI-X Capability Block diff --git a/trunk/drivers/regulator/Kconfig b/trunk/drivers/regulator/Kconfig index e98a5e7827df..4e932cc695e9 100644 --- a/trunk/drivers/regulator/Kconfig +++ b/trunk/drivers/regulator/Kconfig @@ -33,8 +33,9 @@ config REGULATOR_DUMMY help If this option is enabled then when a regulator lookup fails and the board has not specified that it has provided full - constraints the regulator core will provide an always - enabled dummy regulator, allowing consumer drivers to continue. + constraints then the regulator core will provide an always + enabled dummy regulator will be provided, allowing consumer + drivers to continue. A warning will be generated when this substitution is done. @@ -49,11 +50,11 @@ config REGULATOR_VIRTUAL_CONSUMER tristate "Virtual regulator consumer support" help This driver provides a virtual consumer for the voltage and - current regulator API which provides sysfs controls for - configuring the supplies requested. This is mainly useful - for test purposes. + current regulator API which provides sysfs controls for + configuring the supplies requested. This is mainly useful + for test purposes. - If unsure, say no. + If unsure, say no. config REGULATOR_USERSPACE_CONSUMER tristate "Userspace regulator consumer support" @@ -62,7 +63,7 @@ config REGULATOR_USERSPACE_CONSUMER from user space. Userspace consumer driver provides ability to control power supplies for such devices. - If unsure, say no. + If unsure, say no. config REGULATOR_GPIO tristate "GPIO regulator support" @@ -109,17 +110,6 @@ config REGULATOR_DA9052 This driver supports the voltage regulators of DA9052-BC and DA9053-AA/Bx PMIC. -config REGULATOR_FAN53555 - tristate "Fairchild FAN53555 Regulator" - depends on I2C - select REGMAP_I2C - help - This driver supports Fairchild FAN53555 Digitally Programmable - TinyBuck Regulator. The FAN53555 is a step-down switching voltage - regulator that delivers a digitally programmable output from an - input voltage supply of 2.5V to 5.5V. The output voltage is - programmed through an I2C interface. - config REGULATOR_ANATOP tristate "Freescale i.MX on-chip ANATOP LDO regulators" depends on MFD_ANATOP @@ -182,14 +172,6 @@ config REGULATOR_MAX8660 This driver controls a Maxim 8660/8661 voltage output regulator via I2C bus. -config REGULATOR_MAX8907 - tristate "Maxim 8907 voltage regulator" - depends on MFD_MAX8907 - help - This driver controls a Maxim 8907 voltage output regulator - via I2C bus. The provided regulator is suitable for Tegra - chip to control Step-Down DC-DC and LDOs. - config REGULATOR_MAX8925 tristate "Maxim MAX8925 Power Management IC" depends on MFD_MAX8925 @@ -265,7 +247,7 @@ config REGULATOR_LP8788 config REGULATOR_PCF50633 tristate "NXP PCF50633 regulator driver" - depends on MFD_PCF50633 + depends on MFD_PCF50633 help Say Y here to support the voltage regulators and convertors on PCF50633 @@ -434,7 +416,7 @@ config REGULATOR_WM8350 depends on MFD_WM8350 help This driver provides support for the voltage and current regulators - of the WM8350 AudioPlus PMIC. + of the WM8350 AudioPlus PMIC. config REGULATOR_WM8400 tristate "Wolfson Microelectronics WM8400 AudioPlus PMIC" diff --git a/trunk/drivers/regulator/Makefile b/trunk/drivers/regulator/Makefile index e431eed8a878..3342615cf25e 100644 --- a/trunk/drivers/regulator/Makefile +++ b/trunk/drivers/regulator/Makefile @@ -20,7 +20,6 @@ obj-$(CONFIG_REGULATOR_DA903X) += da903x.o obj-$(CONFIG_REGULATOR_DA9052) += da9052-regulator.o obj-$(CONFIG_REGULATOR_DBX500_PRCMU) += dbx500-prcmu.o obj-$(CONFIG_REGULATOR_DB8500_PRCMU) += db8500-prcmu.o -obj-$(CONFIG_REGULATOR_FAN53555) += fan53555.o obj-$(CONFIG_REGULATOR_GPIO) += gpio-regulator.o obj-$(CONFIG_REGULATOR_ISL6271A) += isl6271a-regulator.o obj-$(CONFIG_REGULATOR_LP3971) += lp3971.o @@ -31,7 +30,6 @@ obj-$(CONFIG_REGULATOR_LP8788) += lp8788-ldo.o obj-$(CONFIG_REGULATOR_MAX1586) += max1586.o obj-$(CONFIG_REGULATOR_MAX8649) += max8649.o obj-$(CONFIG_REGULATOR_MAX8660) += max8660.o -obj-$(CONFIG_REGULATOR_MAX8907) += max8907-regulator.o obj-$(CONFIG_REGULATOR_MAX8925) += max8925-regulator.o obj-$(CONFIG_REGULATOR_MAX8952) += max8952.o obj-$(CONFIG_REGULATOR_MAX8997) += max8997.o diff --git a/trunk/drivers/regulator/aat2870-regulator.c b/trunk/drivers/regulator/aat2870-regulator.c index 167c93f21981..6f45bfd22e83 100644 --- a/trunk/drivers/regulator/aat2870-regulator.c +++ b/trunk/drivers/regulator/aat2870-regulator.c @@ -162,7 +162,7 @@ static struct aat2870_regulator *aat2870_get_regulator(int id) static int aat2870_regulator_probe(struct platform_device *pdev) { struct aat2870_regulator *ri; - struct regulator_config config = { }; + struct regulator_config config = { 0 }; struct regulator_dev *rdev; ri = aat2870_get_regulator(pdev->id); diff --git a/trunk/drivers/regulator/ab3100.c b/trunk/drivers/regulator/ab3100.c index 65ad2b36ce36..182b553059c9 100644 --- a/trunk/drivers/regulator/ab3100.c +++ b/trunk/drivers/regulator/ab3100.c @@ -347,11 +347,17 @@ static int ab3100_get_voltage_regulator_external(struct regulator_dev *reg) return abreg->plfdata->external_voltage; } +static int ab3100_get_fixed_voltage_regulator(struct regulator_dev *reg) +{ + return reg->desc->min_uV; +} + static struct regulator_ops regulator_ops_fixed = { .list_voltage = regulator_list_voltage_linear, .enable = ab3100_enable_regulator, .disable = ab3100_disable_regulator, .is_enabled = ab3100_is_enabled_regulator, + .get_voltage = ab3100_get_fixed_voltage_regulator, }; static struct regulator_ops regulator_ops_variable = { @@ -480,7 +486,6 @@ ab3100_regulator_desc[AB3100_NUM_REGULATORS] = { .id = AB3100_BUCK, .ops = ®ulator_ops_variable_sleepable, .n_voltages = ARRAY_SIZE(ldo_e_buck_typ_voltages), - .volt_table = ldo_e_buck_typ_voltages, .type = REGULATOR_VOLTAGE, .owner = THIS_MODULE, .enable_time = 1000, diff --git a/trunk/drivers/regulator/ab8500.c b/trunk/drivers/regulator/ab8500.c index e3d1d063025a..10f2f4d4d190 100644 --- a/trunk/drivers/regulator/ab8500.c +++ b/trunk/drivers/regulator/ab8500.c @@ -37,7 +37,6 @@ * @voltage_bank: bank to control regulator voltage * @voltage_reg: register to control regulator voltage * @voltage_mask: mask to control regulator voltage - * @voltage_shift: shift to control regulator voltage * @delay: startup/set voltage delay in us */ struct ab8500_regulator_info { @@ -51,7 +50,6 @@ struct ab8500_regulator_info { u8 voltage_bank; u8 voltage_reg; u8 voltage_mask; - u8 voltage_shift; unsigned int delay; }; @@ -197,14 +195,17 @@ static int ab8500_regulator_get_voltage_sel(struct regulator_dev *rdev) } dev_vdbg(rdev_get_dev(rdev), - "%s-get_voltage (bank, reg, mask, shift, value): " - "0x%x, 0x%x, 0x%x, 0x%x, 0x%x\n", - info->desc.name, info->voltage_bank, - info->voltage_reg, info->voltage_mask, - info->voltage_shift, regval); + "%s-get_voltage (bank, reg, mask, value): 0x%x, 0x%x, 0x%x," + " 0x%x\n", + info->desc.name, info->voltage_bank, info->voltage_reg, + info->voltage_mask, regval); + /* vintcore has a different layout */ val = regval & info->voltage_mask; - return val >> info->voltage_shift; + if (info->desc.id == AB8500_LDO_INTCORE) + return val >> 0x3; + else + return val; } static int ab8500_regulator_set_voltage_sel(struct regulator_dev *rdev, @@ -220,7 +221,7 @@ static int ab8500_regulator_set_voltage_sel(struct regulator_dev *rdev, } /* set the registers for the request */ - regval = (u8)selector << info->voltage_shift; + regval = (u8)selector; ret = abx500_mask_and_set_register_interruptible(info->dev, info->voltage_bank, info->voltage_reg, info->voltage_mask, regval); @@ -237,6 +238,13 @@ static int ab8500_regulator_set_voltage_sel(struct regulator_dev *rdev, return ret; } +static int ab8500_regulator_enable_time(struct regulator_dev *rdev) +{ + struct ab8500_regulator_info *info = rdev_get_drvdata(rdev); + + return info->delay; +} + static int ab8500_regulator_set_voltage_time_sel(struct regulator_dev *rdev, unsigned int old_sel, unsigned int new_sel) @@ -253,14 +261,22 @@ static struct regulator_ops ab8500_regulator_ops = { .get_voltage_sel = ab8500_regulator_get_voltage_sel, .set_voltage_sel = ab8500_regulator_set_voltage_sel, .list_voltage = regulator_list_voltage_table, + .enable_time = ab8500_regulator_enable_time, .set_voltage_time_sel = ab8500_regulator_set_voltage_time_sel, }; +static int ab8500_fixed_get_voltage(struct regulator_dev *rdev) +{ + return rdev->desc->min_uV; +} + static struct regulator_ops ab8500_regulator_fixed_ops = { .enable = ab8500_regulator_enable, .disable = ab8500_regulator_disable, .is_enabled = ab8500_regulator_is_enabled, + .get_voltage = ab8500_fixed_get_voltage, .list_voltage = regulator_list_voltage_linear, + .enable_time = ab8500_regulator_enable_time, }; static struct ab8500_regulator_info @@ -342,7 +358,6 @@ static struct ab8500_regulator_info .voltage_bank = 0x03, .voltage_reg = 0x80, .voltage_mask = 0x38, - .voltage_shift = 3, }, /* @@ -359,7 +374,6 @@ static struct ab8500_regulator_info .owner = THIS_MODULE, .n_voltages = 1, .min_uV = 2000000, - .enable_time = 10000, }, .delay = 10000, .update_bank = 0x03, diff --git a/trunk/drivers/regulator/anatop-regulator.c b/trunk/drivers/regulator/anatop-regulator.c index ce0fe72a428e..e9c2085f9dfb 100644 --- a/trunk/drivers/regulator/anatop-regulator.c +++ b/trunk/drivers/regulator/anatop-regulator.c @@ -64,15 +64,14 @@ static int anatop_set_voltage_sel(struct regulator_dev *reg, unsigned selector) static int anatop_get_voltage_sel(struct regulator_dev *reg) { struct anatop_regulator *anatop_reg = rdev_get_drvdata(reg); - u32 val, mask; + u32 val; if (!anatop_reg->control_reg) return -ENOTSUPP; val = anatop_read_reg(anatop_reg->mfd, anatop_reg->control_reg); - mask = ((1 << anatop_reg->vol_bit_width) - 1) << + val = (val & ((1 << anatop_reg->vol_bit_width) - 1)) >> anatop_reg->vol_bit_shift; - val = (val & mask) >> anatop_reg->vol_bit_shift; return val - anatop_reg->min_bit_val; } diff --git a/trunk/drivers/regulator/arizona-ldo1.c b/trunk/drivers/regulator/arizona-ldo1.c index d184aa35abcb..c8f95c07adb6 100644 --- a/trunk/drivers/regulator/arizona-ldo1.c +++ b/trunk/drivers/regulator/arizona-ldo1.c @@ -39,8 +39,6 @@ static struct regulator_ops arizona_ldo1_ops = { .map_voltage = regulator_map_voltage_linear, .get_voltage_sel = regulator_get_voltage_sel_regmap, .set_voltage_sel = regulator_set_voltage_sel_regmap, - .get_bypass = regulator_get_bypass_regmap, - .set_bypass = regulator_set_bypass_regmap, }; static const struct regulator_desc arizona_ldo1 = { @@ -51,11 +49,9 @@ static const struct regulator_desc arizona_ldo1 = { .vsel_reg = ARIZONA_LDO1_CONTROL_1, .vsel_mask = ARIZONA_LDO1_VSEL_MASK, - .bypass_reg = ARIZONA_LDO1_CONTROL_1, - .bypass_mask = ARIZONA_LDO1_BYPASS, .min_uV = 900000, .uV_step = 50000, - .n_voltages = 6, + .n_voltages = 7, .owner = THIS_MODULE, }; diff --git a/trunk/drivers/regulator/arizona-micsupp.c b/trunk/drivers/regulator/arizona-micsupp.c index d9b1f82cc5bd..450a069aa9b6 100644 --- a/trunk/drivers/regulator/arizona-micsupp.c +++ b/trunk/drivers/regulator/arizona-micsupp.c @@ -82,9 +82,6 @@ static struct regulator_ops arizona_micsupp_ops = { .get_voltage_sel = regulator_get_voltage_sel_regmap, .set_voltage_sel = regulator_set_voltage_sel_regmap, - - .get_bypass = regulator_get_bypass_regmap, - .set_bypass = regulator_set_bypass_regmap, }; static const struct regulator_desc arizona_micsupp = { @@ -98,8 +95,6 @@ static const struct regulator_desc arizona_micsupp = { .vsel_mask = ARIZONA_LDO2_VSEL_MASK, .enable_reg = ARIZONA_MIC_CHARGE_PUMP_1, .enable_mask = ARIZONA_CPMIC_ENA, - .bypass_reg = ARIZONA_MIC_CHARGE_PUMP_1, - .bypass_mask = ARIZONA_CPMIC_BYPASS, .owner = THIS_MODULE, }; diff --git a/trunk/drivers/regulator/core.c b/trunk/drivers/regulator/core.c index 2e0352dc26bd..f092588a078c 100644 --- a/trunk/drivers/regulator/core.c +++ b/trunk/drivers/regulator/core.c @@ -77,7 +77,6 @@ struct regulator { struct device *dev; struct list_head list; unsigned int always_on:1; - unsigned int bypass:1; int uA_load; int min_uV; int max_uV; @@ -395,9 +394,6 @@ static ssize_t regulator_status_show(struct device *dev, case REGULATOR_STATUS_STANDBY: label = "standby"; break; - case REGULATOR_STATUS_BYPASS: - label = "bypass"; - break; case REGULATOR_STATUS_UNDEFINED: label = "undefined"; break; @@ -589,27 +585,6 @@ static ssize_t regulator_suspend_standby_state_show(struct device *dev, static DEVICE_ATTR(suspend_standby_state, 0444, regulator_suspend_standby_state_show, NULL); -static ssize_t regulator_bypass_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct regulator_dev *rdev = dev_get_drvdata(dev); - const char *report; - bool bypass; - int ret; - - ret = rdev->desc->ops->get_bypass(rdev, &bypass); - - if (ret != 0) - report = "unknown"; - else if (bypass) - report = "enabled"; - else - report = "disabled"; - - return sprintf(buf, "%s\n", report); -} -static DEVICE_ATTR(bypass, 0444, - regulator_bypass_show, NULL); /* * These are the only attributes are present for all regulators. @@ -803,9 +778,6 @@ static void print_constraints(struct regulator_dev *rdev) if (constraints->valid_modes_mask & REGULATOR_MODE_STANDBY) count += sprintf(buf + count, "standby"); - if (!count) - sprintf(buf, "no parameters"); - rdev_info(rdev, "%s\n", buf); if ((constraints->min_uV != constraints->max_uV) && @@ -1002,7 +974,6 @@ static int set_supply(struct regulator_dev *rdev, err = -ENOMEM; return err; } - supply_rdev->open_count++; return 0; } @@ -1749,9 +1720,6 @@ int regulator_disable_deferred(struct regulator *regulator, int ms) if (regulator->always_on) return 0; - if (!ms) - return regulator_disable(regulator); - mutex_lock(&rdev->mutex); rdev->deferred_disables++; mutex_unlock(&rdev->mutex); @@ -2210,12 +2178,9 @@ static int _regulator_do_set_voltage(struct regulator_dev *rdev, } } - if (ret == 0 && best_val >= 0) { - unsigned long data = best_val; - + if (ret == 0 && best_val >= 0) _notifier_call_chain(rdev, REGULATOR_EVENT_VOLTAGE_CHANGE, - (void *)data); - } + (void *)best_val); trace_regulator_set_voltage_complete(rdev_get_name(rdev), best_val); @@ -2326,8 +2291,8 @@ int regulator_set_voltage_time(struct regulator *regulator, EXPORT_SYMBOL_GPL(regulator_set_voltage_time); /** - * regulator_set_voltage_time_sel - get raise/fall time - * @rdev: regulator source device + *regulator_set_voltage_time_sel - get raise/fall time + * @regulator: regulator source * @old_selector: selector for starting voltage * @new_selector: selector for target voltage * @@ -2423,8 +2388,6 @@ static int _regulator_get_voltage(struct regulator_dev *rdev) ret = rdev->desc->ops->list_voltage(rdev, sel); } else if (rdev->desc->ops->get_voltage) { ret = rdev->desc->ops->get_voltage(rdev); - } else if (rdev->desc->ops->list_voltage) { - ret = rdev->desc->ops->list_voltage(rdev, 0); } else { return -EINVAL; } @@ -2710,100 +2673,6 @@ int regulator_set_optimum_mode(struct regulator *regulator, int uA_load) } EXPORT_SYMBOL_GPL(regulator_set_optimum_mode); -/** - * regulator_set_bypass_regmap - Default set_bypass() using regmap - * - * @rdev: device to operate on. - * @enable: state to set. - */ -int regulator_set_bypass_regmap(struct regulator_dev *rdev, bool enable) -{ - unsigned int val; - - if (enable) - val = rdev->desc->bypass_mask; - else - val = 0; - - return regmap_update_bits(rdev->regmap, rdev->desc->bypass_reg, - rdev->desc->bypass_mask, val); -} -EXPORT_SYMBOL_GPL(regulator_set_bypass_regmap); - -/** - * regulator_get_bypass_regmap - Default get_bypass() using regmap - * - * @rdev: device to operate on. - * @enable: current state. - */ -int regulator_get_bypass_regmap(struct regulator_dev *rdev, bool *enable) -{ - unsigned int val; - int ret; - - ret = regmap_read(rdev->regmap, rdev->desc->bypass_reg, &val); - if (ret != 0) - return ret; - - *enable = val & rdev->desc->bypass_mask; - - return 0; -} -EXPORT_SYMBOL_GPL(regulator_get_bypass_regmap); - -/** - * regulator_allow_bypass - allow the regulator to go into bypass mode - * - * @regulator: Regulator to configure - * @allow: enable or disable bypass mode - * - * Allow the regulator to go into bypass mode if all other consumers - * for the regulator also enable bypass mode and the machine - * constraints allow this. Bypass mode means that the regulator is - * simply passing the input directly to the output with no regulation. - */ -int regulator_allow_bypass(struct regulator *regulator, bool enable) -{ - struct regulator_dev *rdev = regulator->rdev; - int ret = 0; - - if (!rdev->desc->ops->set_bypass) - return 0; - - if (rdev->constraints && - !(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_BYPASS)) - return 0; - - mutex_lock(&rdev->mutex); - - if (enable && !regulator->bypass) { - rdev->bypass_count++; - - if (rdev->bypass_count == rdev->open_count) { - ret = rdev->desc->ops->set_bypass(rdev, enable); - if (ret != 0) - rdev->bypass_count--; - } - - } else if (!enable && regulator->bypass) { - rdev->bypass_count--; - - if (rdev->bypass_count != rdev->open_count) { - ret = rdev->desc->ops->set_bypass(rdev, enable); - if (ret != 0) - rdev->bypass_count++; - } - } - - if (ret == 0) - regulator->bypass = enable; - - mutex_unlock(&rdev->mutex); - - return ret; -} -EXPORT_SYMBOL_GPL(regulator_allow_bypass); - /** * regulator_register_notifier - register regulator event notifier * @regulator: regulator source @@ -3142,8 +3011,7 @@ static int add_regulator_attributes(struct regulator_dev *rdev) /* some attributes need specific methods to be displayed */ if ((ops->get_voltage && ops->get_voltage(rdev) >= 0) || - (ops->get_voltage_sel && ops->get_voltage_sel(rdev) >= 0) || - (ops->list_voltage && ops->list_voltage(rdev, 0) >= 0)) { + (ops->get_voltage_sel && ops->get_voltage_sel(rdev) >= 0)) { status = device_create_file(dev, &dev_attr_microvolts); if (status < 0) return status; @@ -3168,11 +3036,6 @@ static int add_regulator_attributes(struct regulator_dev *rdev) if (status < 0) return status; } - if (ops->get_bypass) { - status = device_create_file(dev, &dev_attr_bypass); - if (status < 0) - return status; - } /* some attributes are type-specific */ if (rdev->desc->type == REGULATOR_CURRENT) { @@ -3261,8 +3124,6 @@ static void rdev_init_debugfs(struct regulator_dev *rdev) &rdev->use_count); debugfs_create_u32("open_count", 0444, rdev->debugfs, &rdev->open_count); - debugfs_create_u32("bypass_count", 0444, rdev->debugfs, - &rdev->bypass_count); } /** @@ -3328,10 +3189,8 @@ regulator_register(const struct regulator_desc *regulator_desc, rdev->desc = regulator_desc; if (config->regmap) rdev->regmap = config->regmap; - else if (dev_get_regmap(dev, NULL)) + else rdev->regmap = dev_get_regmap(dev, NULL); - else if (dev->parent) - rdev->regmap = dev_get_regmap(dev->parent, NULL); INIT_LIST_HEAD(&rdev->consumer_list); INIT_LIST_HEAD(&rdev->list); BLOCKING_INIT_NOTIFIER_HEAD(&rdev->notifier); @@ -3358,7 +3217,7 @@ regulator_register(const struct regulator_desc *regulator_desc, dev_set_drvdata(&rdev->dev, rdev); - if (config->ena_gpio && gpio_is_valid(config->ena_gpio)) { + if (config->ena_gpio) { ret = gpio_request_one(config->ena_gpio, GPIOF_DIR_OUT | config->ena_gpio_flags, rdev_get_name(rdev)); diff --git a/trunk/drivers/regulator/da9052-regulator.c b/trunk/drivers/regulator/da9052-regulator.c index 27355b1199e5..903299cf15cf 100644 --- a/trunk/drivers/regulator/da9052-regulator.c +++ b/trunk/drivers/regulator/da9052-regulator.c @@ -133,8 +133,8 @@ static int da9052_dcdc_set_current_limit(struct regulator_dev *rdev, int min_uA, max_uA < da9052_current_limits[row][DA9052_MIN_UA]) return -EINVAL; - for (i = DA9052_CURRENT_RANGE - 1; i >= 0; i--) { - if (da9052_current_limits[row][i] <= max_uA) { + for (i = 0; i < DA9052_CURRENT_RANGE; i++) { + if (min_uA <= da9052_current_limits[row][i]) { reg_val = i; break; } diff --git a/trunk/drivers/regulator/dummy.c b/trunk/drivers/regulator/dummy.c index 03a1d7c11ef2..86f655c7f7a1 100644 --- a/trunk/drivers/regulator/dummy.c +++ b/trunk/drivers/regulator/dummy.c @@ -30,7 +30,7 @@ static struct regulator_init_data dummy_initdata; static struct regulator_ops dummy_ops; static struct regulator_desc dummy_desc = { - .name = "regulator-dummy", + .name = "dummy", .id = -1, .type = REGULATOR_VOLTAGE, .owner = THIS_MODULE, diff --git a/trunk/drivers/regulator/fan53555.c b/trunk/drivers/regulator/fan53555.c deleted file mode 100644 index 339f4d732e97..000000000000 --- a/trunk/drivers/regulator/fan53555.c +++ /dev/null @@ -1,322 +0,0 @@ -/* - * FAN53555 Fairchild Digitally Programmable TinyBuck Regulator Driver. - * - * Supported Part Numbers: - * FAN53555UC00X/01X/03X/04X/05X - * - * Copyright (c) 2012 Marvell Technology Ltd. - * Yunfan Zhang - * - * This package 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* Voltage setting */ -#define FAN53555_VSEL0 0x00 -#define FAN53555_VSEL1 0x01 -/* Control register */ -#define FAN53555_CONTROL 0x02 -/* IC Type */ -#define FAN53555_ID1 0x03 -/* IC mask version */ -#define FAN53555_ID2 0x04 -/* Monitor register */ -#define FAN53555_MONITOR 0x05 - -/* VSEL bit definitions */ -#define VSEL_BUCK_EN (1 << 7) -#define VSEL_MODE (1 << 6) -#define VSEL_NSEL_MASK 0x3F -/* Chip ID and Verison */ -#define DIE_ID 0x0F /* ID1 */ -#define DIE_REV 0x0F /* ID2 */ -/* Control bit definitions */ -#define CTL_OUTPUT_DISCHG (1 << 7) -#define CTL_SLEW_MASK (0x7 << 4) -#define CTL_SLEW_SHIFT 4 -#define CTL_RESET (1 << 2) - -#define FAN53555_NVOLTAGES 64 /* Numbers of voltages */ - -/* IC Type */ -enum { - FAN53555_CHIP_ID_00 = 0, - FAN53555_CHIP_ID_01, - FAN53555_CHIP_ID_02, - FAN53555_CHIP_ID_03, - FAN53555_CHIP_ID_04, - FAN53555_CHIP_ID_05, -}; - -struct fan53555_device_info { - struct regmap *regmap; - struct device *dev; - struct regulator_desc desc; - struct regulator_dev *rdev; - struct regulator_init_data *regulator; - /* IC Type and Rev */ - int chip_id; - int chip_rev; - /* Voltage setting register */ - unsigned int vol_reg; - unsigned int sleep_reg; - /* Voltage range and step(linear) */ - unsigned int vsel_min; - unsigned int vsel_step; - /* Voltage slew rate limiting */ - unsigned int slew_rate; - /* Sleep voltage cache */ - unsigned int sleep_vol_cache; -}; - -static int fan53555_set_suspend_voltage(struct regulator_dev *rdev, int uV) -{ - struct fan53555_device_info *di = rdev_get_drvdata(rdev); - int ret; - - if (di->sleep_vol_cache == uV) - return 0; - ret = regulator_map_voltage_linear(rdev, uV, uV); - if (ret < 0) - return -EINVAL; - ret = regmap_update_bits(di->regmap, di->sleep_reg, - VSEL_NSEL_MASK, ret); - if (ret < 0) - return -EINVAL; - /* Cache the sleep voltage setting. - * Might not be the real voltage which is rounded */ - di->sleep_vol_cache = uV; - - return 0; -} - -static int fan53555_set_mode(struct regulator_dev *rdev, unsigned int mode) -{ - struct fan53555_device_info *di = rdev_get_drvdata(rdev); - - switch (mode) { - case REGULATOR_MODE_FAST: - regmap_update_bits(di->regmap, di->vol_reg, - VSEL_MODE, VSEL_MODE); - break; - case REGULATOR_MODE_NORMAL: - regmap_update_bits(di->regmap, di->vol_reg, VSEL_MODE, 0); - break; - default: - return -EINVAL; - } - return 0; -} - -static unsigned int fan53555_get_mode(struct regulator_dev *rdev) -{ - struct fan53555_device_info *di = rdev_get_drvdata(rdev); - unsigned int val; - int ret = 0; - - ret = regmap_read(di->regmap, di->vol_reg, &val); - if (ret < 0) - return ret; - if (val & VSEL_MODE) - return REGULATOR_MODE_FAST; - else - return REGULATOR_MODE_NORMAL; -} - -static struct regulator_ops fan53555_regulator_ops = { - .set_voltage_sel = regulator_set_voltage_sel_regmap, - .get_voltage_sel = regulator_get_voltage_sel_regmap, - .map_voltage = regulator_map_voltage_linear, - .list_voltage = regulator_list_voltage_linear, - .set_suspend_voltage = fan53555_set_suspend_voltage, - .enable = regulator_enable_regmap, - .disable = regulator_disable_regmap, - .is_enabled = regulator_is_enabled_regmap, - .set_mode = fan53555_set_mode, - .get_mode = fan53555_get_mode, -}; - -/* For 00,01,03,05 options: - * VOUT = 0.60V + NSELx * 10mV, from 0.60 to 1.23V. - * For 04 option: - * VOUT = 0.603V + NSELx * 12.826mV, from 0.603 to 1.411V. - * */ -static int fan53555_device_setup(struct fan53555_device_info *di, - struct fan53555_platform_data *pdata) -{ - unsigned int reg, data, mask; - - /* Setup voltage control register */ - switch (pdata->sleep_vsel_id) { - case FAN53555_VSEL_ID_0: - di->sleep_reg = FAN53555_VSEL0; - di->vol_reg = FAN53555_VSEL1; - break; - case FAN53555_VSEL_ID_1: - di->sleep_reg = FAN53555_VSEL1; - di->vol_reg = FAN53555_VSEL0; - break; - default: - dev_err(di->dev, "Invalid VSEL ID!\n"); - return -EINVAL; - } - /* Init voltage range and step */ - switch (di->chip_id) { - case FAN53555_CHIP_ID_00: - case FAN53555_CHIP_ID_01: - case FAN53555_CHIP_ID_03: - case FAN53555_CHIP_ID_05: - di->vsel_min = 600000; - di->vsel_step = 10000; - break; - case FAN53555_CHIP_ID_04: - di->vsel_min = 603000; - di->vsel_step = 12826; - break; - default: - dev_err(di->dev, - "Chip ID[%d]\n not supported!\n", di->chip_id); - return -EINVAL; - } - /* Init slew rate */ - if (pdata->slew_rate & 0x7) - di->slew_rate = pdata->slew_rate; - else - di->slew_rate = FAN53555_SLEW_RATE_64MV; - reg = FAN53555_CONTROL; - data = di->slew_rate << CTL_SLEW_SHIFT; - mask = CTL_SLEW_MASK; - return regmap_update_bits(di->regmap, reg, mask, data); -} - -static int fan53555_regulator_register(struct fan53555_device_info *di, - struct regulator_config *config) -{ - struct regulator_desc *rdesc = &di->desc; - - rdesc->name = "fan53555-reg"; - rdesc->ops = &fan53555_regulator_ops; - rdesc->type = REGULATOR_VOLTAGE; - rdesc->n_voltages = FAN53555_NVOLTAGES; - rdesc->enable_reg = di->vol_reg; - rdesc->enable_mask = VSEL_BUCK_EN; - rdesc->min_uV = di->vsel_min; - rdesc->uV_step = di->vsel_step; - rdesc->vsel_reg = di->vol_reg; - rdesc->vsel_mask = VSEL_NSEL_MASK; - rdesc->owner = THIS_MODULE; - - di->rdev = regulator_register(&di->desc, config); - if (IS_ERR(di->rdev)) - return PTR_ERR(di->rdev); - return 0; - -} - -static struct regmap_config fan53555_regmap_config = { - .reg_bits = 8, - .val_bits = 8, -}; - -static int __devinit fan53555_regulator_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct fan53555_device_info *di; - struct fan53555_platform_data *pdata; - struct regulator_config config = { }; - unsigned int val; - int ret; - - pdata = client->dev.platform_data; - if (!pdata || !pdata->regulator) { - dev_err(&client->dev, "Platform data not found!\n"); - return -ENODEV; - } - - di = devm_kzalloc(&client->dev, sizeof(struct fan53555_device_info), - GFP_KERNEL); - if (!di) { - dev_err(&client->dev, "Failed to allocate device info data!\n"); - return -ENOMEM; - } - di->regmap = devm_regmap_init_i2c(client, &fan53555_regmap_config); - if (IS_ERR(di->regmap)) { - dev_err(&client->dev, "Failed to allocate regmap!\n"); - return PTR_ERR(di->regmap); - } - di->dev = &client->dev; - di->regulator = pdata->regulator; - i2c_set_clientdata(client, di); - /* Get chip ID */ - ret = regmap_read(di->regmap, FAN53555_ID1, &val); - if (ret < 0) { - dev_err(&client->dev, "Failed to get chip ID!\n"); - return -ENODEV; - } - di->chip_id = val & DIE_ID; - /* Get chip revision */ - ret = regmap_read(di->regmap, FAN53555_ID2, &val); - if (ret < 0) { - dev_err(&client->dev, "Failed to get chip Rev!\n"); - return -ENODEV; - } - di->chip_rev = val & DIE_REV; - dev_info(&client->dev, "FAN53555 Option[%d] Rev[%d] Detected!\n", - di->chip_id, di->chip_rev); - /* Device init */ - ret = fan53555_device_setup(di, pdata); - if (ret < 0) { - dev_err(&client->dev, "Failed to setup device!\n"); - return ret; - } - /* Register regulator */ - config.dev = di->dev; - config.init_data = di->regulator; - config.regmap = di->regmap; - config.driver_data = di; - ret = fan53555_regulator_register(di, &config); - if (ret < 0) - dev_err(&client->dev, "Failed to register regulator!\n"); - return ret; - -} - -static int __devexit fan53555_regulator_remove(struct i2c_client *client) -{ - struct fan53555_device_info *di = i2c_get_clientdata(client); - - regulator_unregister(di->rdev); - return 0; -} - -static const struct i2c_device_id fan53555_id[] = { - {"fan53555", -1}, - { }, -}; - -static struct i2c_driver fan53555_regulator_driver = { - .driver = { - .name = "fan53555-regulator", - }, - .probe = fan53555_regulator_probe, - .remove = __devexit_p(fan53555_regulator_remove), - .id_table = fan53555_id, -}; - -module_i2c_driver(fan53555_regulator_driver); - -MODULE_AUTHOR("Yunfan Zhang "); -MODULE_DESCRIPTION("FAN53555 regulator driver"); -MODULE_LICENSE("GPL v2"); diff --git a/trunk/drivers/regulator/gpio-regulator.c b/trunk/drivers/regulator/gpio-regulator.c index 8b5944f2d7d1..34b67bee9323 100644 --- a/trunk/drivers/regulator/gpio-regulator.c +++ b/trunk/drivers/regulator/gpio-regulator.c @@ -57,17 +57,16 @@ static int gpio_regulator_get_value(struct regulator_dev *dev) return -EINVAL; } -static int gpio_regulator_set_voltage(struct regulator_dev *dev, - int min_uV, int max_uV, - unsigned *selector) +static int gpio_regulator_set_value(struct regulator_dev *dev, + int min, int max, unsigned *selector) { struct gpio_regulator_data *data = rdev_get_drvdata(dev); int ptr, target = 0, state, best_val = INT_MAX; for (ptr = 0; ptr < data->nr_states; ptr++) if (data->states[ptr].value < best_val && - data->states[ptr].value >= min_uV && - data->states[ptr].value <= max_uV) { + data->states[ptr].value >= min && + data->states[ptr].value <= max) { target = data->states[ptr].gpios; best_val = data->states[ptr].value; if (selector) @@ -86,6 +85,13 @@ static int gpio_regulator_set_voltage(struct regulator_dev *dev, return 0; } +static int gpio_regulator_set_voltage(struct regulator_dev *dev, + int min_uV, int max_uV, + unsigned *selector) +{ + return gpio_regulator_set_value(dev, min_uV, max_uV, selector); +} + static int gpio_regulator_list_voltage(struct regulator_dev *dev, unsigned selector) { @@ -100,27 +106,7 @@ static int gpio_regulator_list_voltage(struct regulator_dev *dev, static int gpio_regulator_set_current_limit(struct regulator_dev *dev, int min_uA, int max_uA) { - struct gpio_regulator_data *data = rdev_get_drvdata(dev); - int ptr, target = 0, state, best_val = 0; - - for (ptr = 0; ptr < data->nr_states; ptr++) - if (data->states[ptr].value > best_val && - data->states[ptr].value >= min_uA && - data->states[ptr].value <= max_uA) { - target = data->states[ptr].gpios; - best_val = data->states[ptr].value; - } - - if (best_val == 0) - return -EINVAL; - - for (ptr = 0; ptr < data->nr_gpios; ptr++) { - state = (target & (1 << ptr)) >> ptr; - gpio_set_value(data->gpios[ptr].gpio, state); - } - data->state = target; - - return 0; + return gpio_regulator_set_value(dev, min_uA, max_uA, NULL); } static struct regulator_ops gpio_regulator_voltage_ops = { diff --git a/trunk/drivers/regulator/isl6271a-regulator.c b/trunk/drivers/regulator/isl6271a-regulator.c index d8ecf49a5777..1d145a07ada9 100644 --- a/trunk/drivers/regulator/isl6271a-regulator.c +++ b/trunk/drivers/regulator/isl6271a-regulator.c @@ -73,7 +73,13 @@ static struct regulator_ops isl_core_ops = { .map_voltage = regulator_map_voltage_linear, }; +static int isl6271a_get_fixed_voltage(struct regulator_dev *dev) +{ + return dev->desc->min_uV; +} + static struct regulator_ops isl_fixed_ops = { + .get_voltage = isl6271a_get_fixed_voltage, .list_voltage = regulator_list_voltage_linear, }; diff --git a/trunk/drivers/regulator/lp872x.c b/trunk/drivers/regulator/lp872x.c index 708f4b6a17dc..212c38eaba70 100644 --- a/trunk/drivers/regulator/lp872x.c +++ b/trunk/drivers/regulator/lp872x.c @@ -86,10 +86,6 @@ #define EXTERN_DVS_USED 0 #define MAX_DELAY 6 -/* Default DVS Mode */ -#define LP8720_DEFAULT_DVS 0 -#define LP8725_DEFAULT_DVS BIT(2) - /* dump registers in regmap-debugfs */ #define MAX_REGISTERS 0x0F @@ -273,9 +269,9 @@ static int lp872x_regulator_enable_time(struct regulator_dev *rdev) return val > MAX_DELAY ? 0 : val * time_step_us; } -static void lp872x_set_dvs(struct lp872x *lp, enum lp872x_dvs_sel dvs_sel, - int gpio) +static void lp872x_set_dvs(struct lp872x *lp, int gpio) { + enum lp872x_dvs_sel dvs_sel = lp->pdata->dvs->vsel; enum lp872x_dvs_state state; state = dvs_sel == SEL_V1 ? DVS_HIGH : DVS_LOW; @@ -343,10 +339,10 @@ static int lp872x_buck_set_voltage_sel(struct regulator_dev *rdev, struct lp872x *lp = rdev_get_drvdata(rdev); enum lp872x_regulator_id buck = rdev_get_id(rdev); u8 addr, mask = LP872X_VOUT_M; - struct lp872x_dvs *dvs = lp->pdata ? lp->pdata->dvs : NULL; + struct lp872x_dvs *dvs = lp->pdata->dvs; if (dvs && gpio_is_valid(dvs->gpio)) - lp872x_set_dvs(lp, dvs->vsel, dvs->gpio); + lp872x_set_dvs(lp, dvs->gpio); addr = lp872x_select_buck_vout_addr(lp, buck); if (!lp872x_is_valid_buck_addr(addr)) @@ -378,8 +374,8 @@ static int lp8725_buck_set_current_limit(struct regulator_dev *rdev, { struct lp872x *lp = rdev_get_drvdata(rdev); enum lp872x_regulator_id buck = rdev_get_id(rdev); - int i; - u8 addr; + int i, max = ARRAY_SIZE(lp8725_buck_uA); + u8 addr, val; switch (buck) { case LP8725_ID_BUCK1: @@ -392,15 +388,17 @@ static int lp8725_buck_set_current_limit(struct regulator_dev *rdev, return -EINVAL; } - for (i = ARRAY_SIZE(lp8725_buck_uA) - 1 ; i >= 0; i--) { + for (i = 0 ; i < max ; i++) if (lp8725_buck_uA[i] >= min_uA && lp8725_buck_uA[i] <= max_uA) - return lp872x_update_bits(lp, addr, - LP8725_BUCK_CL_M, - i << LP8725_BUCK_CL_S); - } + break; - return -EINVAL; + if (i == max) + return -EINVAL; + + val = i << LP8725_BUCK_CL_S; + + return lp872x_update_bits(lp, addr, LP8725_BUCK_CL_M, val); } static int lp8725_buck_get_current_limit(struct regulator_dev *rdev) @@ -729,16 +727,39 @@ static struct regulator_desc lp8725_regulator_desc[] = { }, }; +static int lp872x_check_dvs_validity(struct lp872x *lp) +{ + struct lp872x_dvs *dvs = lp->pdata->dvs; + u8 val = 0; + int ret; + + ret = lp872x_read_byte(lp, LP872X_GENERAL_CFG, &val); + if (ret) + return ret; + + ret = 0; + if (lp->chipid == LP8720) { + if (val & LP8720_EXT_DVS_M) + ret = dvs ? 0 : -EINVAL; + } else { + if ((val & LP8725_DVS1_M) == EXTERN_DVS_USED) + ret = dvs ? 0 : -EINVAL; + } + + return ret; +} + static int lp872x_init_dvs(struct lp872x *lp) { int ret, gpio; - struct lp872x_dvs *dvs = lp->pdata ? lp->pdata->dvs : NULL; + struct lp872x_dvs *dvs = lp->pdata->dvs; enum lp872x_dvs_state pinstate; - u8 mask[] = { LP8720_EXT_DVS_M, LP8725_DVS1_M | LP8725_DVS2_M }; - u8 default_dvs_mode[] = { LP8720_DEFAULT_DVS, LP8725_DEFAULT_DVS }; - if (!dvs) - goto set_default_dvs_mode; + ret = lp872x_check_dvs_validity(lp); + if (ret) { + dev_warn(lp->dev, "invalid dvs data: %d\n", ret); + return ret; + } gpio = dvs->gpio; if (!gpio_is_valid(gpio)) { @@ -757,10 +778,6 @@ static int lp872x_init_dvs(struct lp872x *lp) lp->dvs_gpio = gpio; return 0; - -set_default_dvs_mode: - return lp872x_update_bits(lp, LP872X_GENERAL_CFG, mask[lp->chipid], - default_dvs_mode[lp->chipid]); } static int lp872x_config(struct lp872x *lp) @@ -768,29 +785,24 @@ static int lp872x_config(struct lp872x *lp) struct lp872x_platform_data *pdata = lp->pdata; int ret; - if (!pdata || !pdata->update_config) - goto init_dvs; + if (!pdata->update_config) + return 0; ret = lp872x_write_byte(lp, LP872X_GENERAL_CFG, pdata->general_config); if (ret) return ret; -init_dvs: return lp872x_init_dvs(lp); } static struct regulator_init_data *lp872x_find_regulator_init_data(int id, struct lp872x *lp) { - struct lp872x_platform_data *pdata = lp->pdata; int i; - if (!pdata) - return NULL; - for (i = 0; i < lp->num_regulators; i++) { - if (pdata->regulator_data[i].id == id) - return pdata->regulator_data[i].init_data; + if (lp->pdata->regulator_data[i].id == id) + return lp->pdata->regulator_data[i].init_data; } return NULL; @@ -851,12 +863,18 @@ static const struct regmap_config lp872x_regmap_config = { static int lp872x_probe(struct i2c_client *cl, const struct i2c_device_id *id) { struct lp872x *lp; + struct lp872x_platform_data *pdata = cl->dev.platform_data; int ret, size, num_regulators; const int lp872x_num_regulators[] = { [LP8720] = LP8720_NUM_REGULATORS, [LP8725] = LP8725_NUM_REGULATORS, }; + if (!pdata) { + dev_err(&cl->dev, "no platform data\n"); + return -EINVAL; + } + lp = devm_kzalloc(&cl->dev, sizeof(struct lp872x), GFP_KERNEL); if (!lp) goto err_mem; @@ -876,7 +894,7 @@ static int lp872x_probe(struct i2c_client *cl, const struct i2c_device_id *id) } lp->dev = &cl->dev; - lp->pdata = cl->dev.platform_data; + lp->pdata = pdata; lp->chipid = id->driver_data; lp->num_regulators = num_regulators; i2c_set_clientdata(cl, lp); diff --git a/trunk/drivers/regulator/lp8788-buck.c b/trunk/drivers/regulator/lp8788-buck.c index ba3e0aa402de..6356e821400f 100644 --- a/trunk/drivers/regulator/lp8788-buck.c +++ b/trunk/drivers/regulator/lp8788-buck.c @@ -69,9 +69,6 @@ #define PIN_HIGH 1 #define ENABLE_TIME_USEC 32 -#define BUCK_FPWM_MASK(x) (1 << (x)) -#define BUCK_FPWM_SHIFT(x) (x) - enum lp8788_dvs_state { DVS_LOW = GPIOF_OUT_INIT_LOW, DVS_HIGH = GPIOF_OUT_INIT_HIGH, @@ -89,9 +86,15 @@ enum lp8788_buck_id { BUCK4, }; +struct lp8788_pwm_map { + u8 mask; + u8 shift; +}; + struct lp8788_buck { struct lp8788 *lp; struct regulator_dev *regulator; + struct lp8788_pwm_map *pmap; void *dvs; }; @@ -103,6 +106,29 @@ static const int lp8788_buck_vtbl[] = { 1950000, 2000000, }; +/* buck pwm mode selection : used for set/get_mode in regulator ops + * @forced pwm : fast mode + * @auto pwm : normal mode + */ +static struct lp8788_pwm_map buck_pmap[] = { + [BUCK1] = { + .mask = LP8788_FPWM_BUCK1_M, + .shift = LP8788_FPWM_BUCK1_S, + }, + [BUCK2] = { + .mask = LP8788_FPWM_BUCK2_M, + .shift = LP8788_FPWM_BUCK2_S, + }, + [BUCK3] = { + .mask = LP8788_FPWM_BUCK3_M, + .shift = LP8788_FPWM_BUCK3_S, + }, + [BUCK4] = { + .mask = LP8788_FPWM_BUCK4_M, + .shift = LP8788_FPWM_BUCK4_S, + }, +}; + static const u8 buck1_vout_addr[] = { LP8788_BUCK1_VOUT0, LP8788_BUCK1_VOUT1, LP8788_BUCK1_VOUT2, LP8788_BUCK1_VOUT3, @@ -321,37 +347,41 @@ static int lp8788_buck_enable_time(struct regulator_dev *rdev) static int lp8788_buck_set_mode(struct regulator_dev *rdev, unsigned int mode) { struct lp8788_buck *buck = rdev_get_drvdata(rdev); - enum lp8788_buck_id id = rdev_get_id(rdev); - u8 mask, val; + struct lp8788_pwm_map *pmap = buck->pmap; + u8 val; + + if (!pmap) + return -EINVAL; - mask = BUCK_FPWM_MASK(id); switch (mode) { case REGULATOR_MODE_FAST: - val = LP8788_FORCE_PWM << BUCK_FPWM_SHIFT(id); + val = LP8788_FORCE_PWM << pmap->shift; break; case REGULATOR_MODE_NORMAL: - val = LP8788_AUTO_PWM << BUCK_FPWM_SHIFT(id); + val = LP8788_AUTO_PWM << pmap->shift; break; default: return -EINVAL; } - return lp8788_update_bits(buck->lp, LP8788_BUCK_PWM, mask, val); + return lp8788_update_bits(buck->lp, LP8788_BUCK_PWM, pmap->mask, val); } static unsigned int lp8788_buck_get_mode(struct regulator_dev *rdev) { struct lp8788_buck *buck = rdev_get_drvdata(rdev); - enum lp8788_buck_id id = rdev_get_id(rdev); + struct lp8788_pwm_map *pmap = buck->pmap; u8 val; int ret; + if (!pmap) + return -EINVAL; + ret = lp8788_read_byte(buck->lp, LP8788_BUCK_PWM, &val); if (ret) return ret; - return val & BUCK_FPWM_MASK(id) ? - REGULATOR_MODE_FAST : REGULATOR_MODE_NORMAL; + return val & pmap->mask ? REGULATOR_MODE_FAST : REGULATOR_MODE_NORMAL; } static struct regulator_ops lp8788_buck12_ops = { @@ -429,6 +459,27 @@ static struct regulator_desc lp8788_buck_desc[] = { }, }; +static int lp8788_set_default_dvs_ctrl_mode(struct lp8788 *lp, + enum lp8788_buck_id id) +{ + u8 mask, val; + + switch (id) { + case BUCK1: + mask = LP8788_BUCK1_DVS_SEL_M; + val = LP8788_BUCK1_DVS_I2C; + break; + case BUCK2: + mask = LP8788_BUCK2_DVS_SEL_M; + val = LP8788_BUCK2_DVS_I2C; + break; + default: + return 0; + } + + return lp8788_update_bits(lp, LP8788_BUCK_DVS_SEL, mask, val); +} + static int _gpio_request(struct lp8788_buck *buck, int gpio, char *name) { struct device *dev = buck->lp->dev; @@ -479,7 +530,6 @@ static int lp8788_init_dvs(struct lp8788_buck *buck, enum lp8788_buck_id id) struct lp8788_platform_data *pdata = buck->lp->pdata; u8 mask[] = { LP8788_BUCK1_DVS_SEL_M, LP8788_BUCK2_DVS_SEL_M }; u8 val[] = { LP8788_BUCK1_DVS_PIN, LP8788_BUCK2_DVS_PIN }; - u8 default_dvs_mode[] = { LP8788_BUCK1_DVS_I2C, LP8788_BUCK2_DVS_I2C }; /* no dvs for buck3, 4 */ if (id == BUCK3 || id == BUCK4) @@ -500,8 +550,7 @@ static int lp8788_init_dvs(struct lp8788_buck *buck, enum lp8788_buck_id id) val[id]); set_default_dvs_mode: - return lp8788_update_bits(buck->lp, LP8788_BUCK_DVS_SEL, mask[id], - default_dvs_mode[id]); + return lp8788_set_default_dvs_ctrl_mode(buck->lp, id); } static __devinit int lp8788_buck_probe(struct platform_device *pdev) @@ -518,6 +567,7 @@ static __devinit int lp8788_buck_probe(struct platform_device *pdev) return -ENOMEM; buck->lp = lp; + buck->pmap = &buck_pmap[id]; ret = lp8788_init_dvs(buck, id); if (ret) diff --git a/trunk/drivers/regulator/lp8788-ldo.c b/trunk/drivers/regulator/lp8788-ldo.c index 6796eeb47dc6..d2122e41a96d 100644 --- a/trunk/drivers/regulator/lp8788-ldo.c +++ b/trunk/drivers/regulator/lp8788-ldo.c @@ -496,7 +496,6 @@ static struct regulator_desc lp8788_dldo_desc[] = { .name = "dldo12", .id = DLDO12, .ops = &lp8788_ldo_voltage_fixed_ops, - .n_voltages = 1, .type = REGULATOR_VOLTAGE, .owner = THIS_MODULE, .enable_reg = LP8788_EN_LDO_B, @@ -522,7 +521,6 @@ static struct regulator_desc lp8788_aldo_desc[] = { .name = "aldo2", .id = ALDO2, .ops = &lp8788_ldo_voltage_fixed_ops, - .n_voltages = 1, .type = REGULATOR_VOLTAGE, .owner = THIS_MODULE, .enable_reg = LP8788_EN_LDO_B, @@ -532,7 +530,6 @@ static struct regulator_desc lp8788_aldo_desc[] = { .name = "aldo3", .id = ALDO3, .ops = &lp8788_ldo_voltage_fixed_ops, - .n_voltages = 1, .type = REGULATOR_VOLTAGE, .owner = THIS_MODULE, .enable_reg = LP8788_EN_LDO_B, @@ -542,7 +539,6 @@ static struct regulator_desc lp8788_aldo_desc[] = { .name = "aldo4", .id = ALDO4, .ops = &lp8788_ldo_voltage_fixed_ops, - .n_voltages = 1, .type = REGULATOR_VOLTAGE, .owner = THIS_MODULE, .enable_reg = LP8788_EN_LDO_B, @@ -552,7 +548,6 @@ static struct regulator_desc lp8788_aldo_desc[] = { .name = "aldo5", .id = ALDO5, .ops = &lp8788_ldo_voltage_fixed_ops, - .n_voltages = 1, .type = REGULATOR_VOLTAGE, .owner = THIS_MODULE, .enable_reg = LP8788_EN_LDO_C, @@ -588,7 +583,6 @@ static struct regulator_desc lp8788_aldo_desc[] = { .name = "aldo8", .id = ALDO8, .ops = &lp8788_ldo_voltage_fixed_ops, - .n_voltages = 1, .type = REGULATOR_VOLTAGE, .owner = THIS_MODULE, .enable_reg = LP8788_EN_LDO_C, @@ -598,7 +592,6 @@ static struct regulator_desc lp8788_aldo_desc[] = { .name = "aldo9", .id = ALDO9, .ops = &lp8788_ldo_voltage_fixed_ops, - .n_voltages = 1, .type = REGULATOR_VOLTAGE, .owner = THIS_MODULE, .enable_reg = LP8788_EN_LDO_C, @@ -608,7 +601,6 @@ static struct regulator_desc lp8788_aldo_desc[] = { .name = "aldo10", .id = ALDO10, .ops = &lp8788_ldo_voltage_fixed_ops, - .n_voltages = 1, .type = REGULATOR_VOLTAGE, .owner = THIS_MODULE, .enable_reg = LP8788_EN_LDO_C, diff --git a/trunk/drivers/regulator/max77686.c b/trunk/drivers/regulator/max77686.c index 2a67d08658ad..c564af6f05a3 100644 --- a/trunk/drivers/regulator/max77686.c +++ b/trunk/drivers/regulator/max77686.c @@ -66,7 +66,7 @@ enum max77686_ramp_rate { }; struct max77686_data { - struct regulator_dev *rdev[MAX77686_REGULATORS]; + struct regulator_dev **rdev; }; static int max77686_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay) @@ -265,7 +265,6 @@ static int max77686_pmic_dt_parse_pdata(struct max77686_dev *iodev, rmatch.of_node = NULL; of_regulator_match(iodev->dev, regulators_np, &rmatch, 1); rdata[i].initdata = rmatch.init_data; - rdata[i].of_node = rmatch.of_node; } pdata->regulators = rdata; @@ -284,8 +283,10 @@ static __devinit int max77686_pmic_probe(struct platform_device *pdev) { struct max77686_dev *iodev = dev_get_drvdata(pdev->dev.parent); struct max77686_platform_data *pdata = dev_get_platdata(iodev->dev); + struct regulator_dev **rdev; struct max77686_data *max77686; - int i, ret = 0; + int i, size; + int ret = 0; struct regulator_config config = { }; dev_dbg(&pdev->dev, "%s\n", __func__); @@ -312,38 +313,45 @@ static __devinit int max77686_pmic_probe(struct platform_device *pdev) if (!max77686) return -ENOMEM; + size = sizeof(struct regulator_dev *) * MAX77686_REGULATORS; + max77686->rdev = devm_kzalloc(&pdev->dev, size, GFP_KERNEL); + if (!max77686->rdev) + return -ENOMEM; + + rdev = max77686->rdev; config.dev = &pdev->dev; config.regmap = iodev->regmap; platform_set_drvdata(pdev, max77686); for (i = 0; i < MAX77686_REGULATORS; i++) { config.init_data = pdata->regulators[i].initdata; - config.of_node = pdata->regulators[i].of_node; - max77686->rdev[i] = regulator_register(®ulators[i], &config); - if (IS_ERR(max77686->rdev[i])) { - ret = PTR_ERR(max77686->rdev[i]); + rdev[i] = regulator_register(®ulators[i], &config); + if (IS_ERR(rdev[i])) { + ret = PTR_ERR(rdev[i]); dev_err(&pdev->dev, "regulator init failed for %d\n", i); - max77686->rdev[i] = NULL; - goto err; + rdev[i] = NULL; + goto err; } } return 0; err: while (--i >= 0) - regulator_unregister(max77686->rdev[i]); + regulator_unregister(rdev[i]); return ret; } static int __devexit max77686_pmic_remove(struct platform_device *pdev) { struct max77686_data *max77686 = platform_get_drvdata(pdev); + struct regulator_dev **rdev = max77686->rdev; int i; for (i = 0; i < MAX77686_REGULATORS; i++) - regulator_unregister(max77686->rdev[i]); + if (rdev[i]) + regulator_unregister(rdev[i]); return 0; } diff --git a/trunk/drivers/regulator/max8907-regulator.c b/trunk/drivers/regulator/max8907-regulator.c deleted file mode 100644 index af7607515ab9..000000000000 --- a/trunk/drivers/regulator/max8907-regulator.c +++ /dev/null @@ -1,408 +0,0 @@ -/* - * max8907-regulator.c -- support regulators in max8907 - * - * Copyright (C) 2010 Gyungoh Yoo - * Copyright (C) 2010-2012, NVIDIA CORPORATION. All rights reserved. - * - * Portions based on drivers/regulator/tps65910-regulator.c, - * Copyright 2010 Texas Instruments Inc. - * Author: Graeme Gregory - * Author: Jorge Eduardo Candelaria - * - * 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define MAX8907_II2RR_VERSION_MASK 0xF0 -#define MAX8907_II2RR_VERSION_REV_A 0x00 -#define MAX8907_II2RR_VERSION_REV_B 0x10 -#define MAX8907_II2RR_VERSION_REV_C 0x30 - -struct max8907_regulator { - struct regulator_desc desc[MAX8907_NUM_REGULATORS]; - struct regulator_dev *rdev[MAX8907_NUM_REGULATORS]; -}; - -#define REG_MBATT() \ - [MAX8907_MBATT] = { \ - .name = "MBATT", \ - .supply_name = "mbatt", \ - .id = MAX8907_MBATT, \ - .ops = &max8907_mbatt_ops, \ - .type = REGULATOR_VOLTAGE, \ - .owner = THIS_MODULE, \ - } - -#define REG_LDO(ids, supply, base, min, max, step) \ - [MAX8907_##ids] = { \ - .name = #ids, \ - .supply_name = supply, \ - .id = MAX8907_##ids, \ - .n_voltages = ((max) - (min)) / (step) + 1, \ - .ops = &max8907_ldo_ops, \ - .type = REGULATOR_VOLTAGE, \ - .owner = THIS_MODULE, \ - .min_uV = (min), \ - .uV_step = (step), \ - .vsel_reg = (base) + MAX8907_VOUT, \ - .vsel_mask = 0x3f, \ - .enable_reg = (base) + MAX8907_CTL, \ - .enable_mask = MAX8907_MASK_LDO_EN, \ - } - -#define REG_FIXED(ids, supply, voltage) \ - [MAX8907_##ids] = { \ - .name = #ids, \ - .supply_name = supply, \ - .id = MAX8907_##ids, \ - .n_voltages = 1, \ - .ops = &max8907_fixed_ops, \ - .type = REGULATOR_VOLTAGE, \ - .owner = THIS_MODULE, \ - .min_uV = (voltage), \ - } - -#define REG_OUT5V(ids, supply, base, voltage) \ - [MAX8907_##ids] = { \ - .name = #ids, \ - .supply_name = supply, \ - .id = MAX8907_##ids, \ - .n_voltages = 1, \ - .ops = &max8907_out5v_ops, \ - .type = REGULATOR_VOLTAGE, \ - .owner = THIS_MODULE, \ - .min_uV = (voltage), \ - .enable_reg = (base), \ - .enable_mask = MAX8907_MASK_OUT5V_EN, \ - } - -#define REG_BBAT(ids, supply, base, min, max, step) \ - [MAX8907_##ids] = { \ - .name = #ids, \ - .supply_name = supply, \ - .id = MAX8907_##ids, \ - .n_voltages = ((max) - (min)) / (step) + 1, \ - .ops = &max8907_bbat_ops, \ - .type = REGULATOR_VOLTAGE, \ - .owner = THIS_MODULE, \ - .min_uV = (min), \ - .uV_step = (step), \ - .vsel_reg = (base), \ - .vsel_mask = MAX8907_MASK_VBBATTCV, \ - } - -#define LDO_750_50(id, supply, base) REG_LDO(id, supply, (base), \ - 750000, 3900000, 50000) -#define LDO_650_25(id, supply, base) REG_LDO(id, supply, (base), \ - 650000, 2225000, 25000) - -static struct regulator_ops max8907_mbatt_ops = { -}; - -static struct regulator_ops max8907_ldo_ops = { - .list_voltage = regulator_list_voltage_linear, - .set_voltage_sel = regulator_set_voltage_sel_regmap, - .get_voltage_sel = regulator_get_voltage_sel_regmap, - .enable = regulator_enable_regmap, - .disable = regulator_disable_regmap, - .is_enabled = regulator_is_enabled_regmap, -}; - -static struct regulator_ops max8907_ldo_hwctl_ops = { - .list_voltage = regulator_list_voltage_linear, - .set_voltage_sel = regulator_set_voltage_sel_regmap, - .get_voltage_sel = regulator_get_voltage_sel_regmap, -}; - -static struct regulator_ops max8907_fixed_ops = { - .list_voltage = regulator_list_voltage_linear, -}; - -static struct regulator_ops max8907_out5v_ops = { - .list_voltage = regulator_list_voltage_linear, - .enable = regulator_enable_regmap, - .disable = regulator_disable_regmap, - .is_enabled = regulator_is_enabled_regmap, -}; - -static struct regulator_ops max8907_out5v_hwctl_ops = { - .list_voltage = regulator_list_voltage_linear, -}; - -static struct regulator_ops max8907_bbat_ops = { - .list_voltage = regulator_list_voltage_linear, - .set_voltage_sel = regulator_set_voltage_sel_regmap, - .get_voltage_sel = regulator_get_voltage_sel_regmap, -}; - -static struct regulator_desc max8907_regulators[] = { - REG_MBATT(), - REG_LDO(SD1, "in-v1", MAX8907_REG_SDCTL1, 650000, 2225000, 25000), - REG_LDO(SD2, "in-v2", MAX8907_REG_SDCTL2, 637500, 1425000, 12500), - REG_LDO(SD3, "in-v3", MAX8907_REG_SDCTL3, 750000, 3900000, 50000), - LDO_750_50(LDO1, "in1", MAX8907_REG_LDOCTL1), - LDO_650_25(LDO2, "in2", MAX8907_REG_LDOCTL2), - LDO_650_25(LDO3, "in3", MAX8907_REG_LDOCTL3), - LDO_750_50(LDO4, "in4", MAX8907_REG_LDOCTL4), - LDO_750_50(LDO5, "in5", MAX8907_REG_LDOCTL5), - LDO_750_50(LDO6, "in6", MAX8907_REG_LDOCTL6), - LDO_750_50(LDO7, "in7", MAX8907_REG_LDOCTL7), - LDO_750_50(LDO8, "in8", MAX8907_REG_LDOCTL8), - LDO_750_50(LDO9, "in9", MAX8907_REG_LDOCTL9), - LDO_750_50(LDO10, "in10", MAX8907_REG_LDOCTL10), - LDO_750_50(LDO11, "in11", MAX8907_REG_LDOCTL11), - LDO_750_50(LDO12, "in12", MAX8907_REG_LDOCTL12), - LDO_750_50(LDO13, "in13", MAX8907_REG_LDOCTL13), - LDO_750_50(LDO14, "in14", MAX8907_REG_LDOCTL14), - LDO_750_50(LDO15, "in15", MAX8907_REG_LDOCTL15), - LDO_750_50(LDO16, "in16", MAX8907_REG_LDOCTL16), - LDO_650_25(LDO17, "in17", MAX8907_REG_LDOCTL17), - LDO_650_25(LDO18, "in18", MAX8907_REG_LDOCTL18), - LDO_750_50(LDO19, "in19", MAX8907_REG_LDOCTL19), - LDO_750_50(LDO20, "in20", MAX8907_REG_LDOCTL20), - REG_OUT5V(OUT5V, "mbatt", MAX8907_REG_OUT5VEN, 5000000), - REG_OUT5V(OUT33V, "mbatt", MAX8907_REG_OUT33VEN, 3300000), - REG_BBAT(BBAT, "MBATT", MAX8907_REG_BBAT_CNFG, - 2400000, 3000000, 200000), - REG_FIXED(SDBY, "MBATT", 1200000), - REG_FIXED(VRTC, "MBATT", 3300000), -}; - -#ifdef CONFIG_OF - -#define MATCH(_name, _id) \ - [MAX8907_##_id] = { \ - .name = #_name, \ - .driver_data = (void *)&max8907_regulators[MAX8907_##_id], \ - } - -static struct of_regulator_match max8907_matches[] = { - MATCH(mbatt, MBATT), - MATCH(sd1, SD1), - MATCH(sd2, SD2), - MATCH(sd3, SD3), - MATCH(ldo1, LDO1), - MATCH(ldo2, LDO2), - MATCH(ldo3, LDO3), - MATCH(ldo4, LDO4), - MATCH(ldo5, LDO5), - MATCH(ldo6, LDO6), - MATCH(ldo7, LDO7), - MATCH(ldo8, LDO8), - MATCH(ldo9, LDO9), - MATCH(ldo10, LDO10), - MATCH(ldo11, LDO11), - MATCH(ldo12, LDO12), - MATCH(ldo13, LDO13), - MATCH(ldo14, LDO14), - MATCH(ldo15, LDO15), - MATCH(ldo16, LDO16), - MATCH(ldo17, LDO17), - MATCH(ldo18, LDO18), - MATCH(ldo19, LDO19), - MATCH(ldo20, LDO20), - MATCH(out5v, OUT5V), - MATCH(out33v, OUT33V), - MATCH(bbat, BBAT), - MATCH(sdby, SDBY), - MATCH(vrtc, VRTC), -}; - -static int max8907_regulator_parse_dt(struct platform_device *pdev) -{ - struct device_node *np = pdev->dev.parent->of_node; - struct device_node *regulators; - int ret; - - if (!pdev->dev.parent->of_node) - return 0; - - regulators = of_find_node_by_name(np, "regulators"); - if (!regulators) { - dev_err(&pdev->dev, "regulators node not found\n"); - return -EINVAL; - } - - ret = of_regulator_match(pdev->dev.parent, regulators, - max8907_matches, - ARRAY_SIZE(max8907_matches)); - if (ret < 0) { - dev_err(&pdev->dev, "Error parsing regulator init data: %d\n", - ret); - return ret; - } - - return 0; -} - -static inline struct regulator_init_data *match_init_data(int index) -{ - return max8907_matches[index].init_data; -} - -static inline struct device_node *match_of_node(int index) -{ - return max8907_matches[index].of_node; -} -#else -static int max8907_regulator_parse_dt(struct platform_device *pdev) -{ - return 0; -} - -static inline struct regulator_init_data *match_init_data(int index) -{ - return NULL; -} - -static inline struct device_node *match_of_node(int index) -{ - return NULL; -} -#endif - -static __devinit int max8907_regulator_probe(struct platform_device *pdev) -{ - struct max8907 *max8907 = dev_get_drvdata(pdev->dev.parent); - struct max8907_platform_data *pdata = dev_get_platdata(max8907->dev); - int ret; - struct max8907_regulator *pmic; - unsigned int val; - int i; - struct regulator_config config = {}; - struct regulator_init_data *idata; - const char *mbatt_rail_name = NULL; - - ret = max8907_regulator_parse_dt(pdev); - if (ret) - return ret; - - pmic = devm_kzalloc(&pdev->dev, sizeof(*pmic), GFP_KERNEL); - if (!pmic) { - dev_err(&pdev->dev, "Failed to alloc pmic\n"); - return -ENOMEM; - } - platform_set_drvdata(pdev, pmic); - - memcpy(pmic->desc, max8907_regulators, sizeof(pmic->desc)); - - /* Backwards compatibility with MAX8907B; SD1 uses different voltages */ - regmap_read(max8907->regmap_gen, MAX8907_REG_II2RR, &val); - if ((val & MAX8907_II2RR_VERSION_MASK) == - MAX8907_II2RR_VERSION_REV_B) { - pmic->desc[MAX8907_SD1].min_uV = 637500; - pmic->desc[MAX8907_SD1].uV_step = 12500; - pmic->desc[MAX8907_SD1].n_voltages = - (1425000 - 637500) / 12500 + 1; - } - - for (i = 0; i < MAX8907_NUM_REGULATORS; i++) { - config.dev = pdev->dev.parent; - if (pdata) - idata = pdata->init_data[i]; - else - idata = match_init_data(i); - config.init_data = idata; - config.driver_data = pmic; - config.regmap = max8907->regmap_gen; - config.of_node = match_of_node(i); - - switch (pmic->desc[i].id) { - case MAX8907_MBATT: - if (idata && idata->constraints.name) - mbatt_rail_name = idata->constraints.name; - else - mbatt_rail_name = pmic->desc[i].name; - break; - case MAX8907_BBAT: - case MAX8907_SDBY: - case MAX8907_VRTC: - idata->supply_regulator = mbatt_rail_name; - break; - } - - if (pmic->desc[i].ops == &max8907_ldo_ops) { - regmap_read(config.regmap, pmic->desc[i].enable_reg, - &val); - if ((val & MAX8907_MASK_LDO_SEQ) != - MAX8907_MASK_LDO_SEQ) - pmic->desc[i].ops = &max8907_ldo_hwctl_ops; - } else if (pmic->desc[i].ops == &max8907_out5v_ops) { - regmap_read(config.regmap, pmic->desc[i].enable_reg, - &val); - if ((val & (MAX8907_MASK_OUT5V_VINEN | - MAX8907_MASK_OUT5V_ENSRC)) != - MAX8907_MASK_OUT5V_ENSRC) - pmic->desc[i].ops = &max8907_out5v_hwctl_ops; - } - - pmic->rdev[i] = regulator_register(&pmic->desc[i], &config); - if (IS_ERR(pmic->rdev[i])) { - dev_err(&pdev->dev, - "failed to register %s regulator\n", - pmic->desc[i].name); - ret = PTR_ERR(pmic->rdev[i]); - goto err_unregister_regulator; - } - } - - return 0; - -err_unregister_regulator: - while (--i >= 0) - regulator_unregister(pmic->rdev[i]); - return ret; -} - -static __devexit int max8907_regulator_remove(struct platform_device *pdev) -{ - struct max8907_regulator *pmic = platform_get_drvdata(pdev); - int i; - - for (i = 0; i < MAX8907_NUM_REGULATORS; i++) - regulator_unregister(pmic->rdev[i]); - - return 0; -} - -static struct platform_driver max8907_regulator_driver = { - .driver = { - .name = "max8907-regulator", - .owner = THIS_MODULE, - }, - .probe = max8907_regulator_probe, - .remove = __devexit_p(max8907_regulator_remove), -}; - -static int __init max8907_regulator_init(void) -{ - return platform_driver_register(&max8907_regulator_driver); -} - -subsys_initcall(max8907_regulator_init); - -static void __exit max8907_reg_exit(void) -{ - platform_driver_unregister(&max8907_regulator_driver); -} - -module_exit(max8907_reg_exit); - -MODULE_DESCRIPTION("MAX8907 regulator driver"); -MODULE_AUTHOR("Gyungoh Yoo "); -MODULE_LICENSE("GPL v2"); -MODULE_ALIAS("platform:max8907-regulator"); diff --git a/trunk/drivers/regulator/mc13783-regulator.c b/trunk/drivers/regulator/mc13783-regulator.c index 0801a6d0c122..4932e3449fe1 100644 --- a/trunk/drivers/regulator/mc13783-regulator.c +++ b/trunk/drivers/regulator/mc13783-regulator.c @@ -21,30 +21,6 @@ #include #include "mc13xxx.h" -#define MC13783_REG_SWITCHERS0 24 -/* Enable does not exist for SW1A */ -#define MC13783_REG_SWITCHERS0_SW1AEN 0 -#define MC13783_REG_SWITCHERS0_SW1AVSEL 0 -#define MC13783_REG_SWITCHERS0_SW1AVSEL_M (63 << 0) - -#define MC13783_REG_SWITCHERS1 25 -/* Enable does not exist for SW1B */ -#define MC13783_REG_SWITCHERS1_SW1BEN 0 -#define MC13783_REG_SWITCHERS1_SW1BVSEL 0 -#define MC13783_REG_SWITCHERS1_SW1BVSEL_M (63 << 0) - -#define MC13783_REG_SWITCHERS2 26 -/* Enable does not exist for SW2A */ -#define MC13783_REG_SWITCHERS2_SW2AEN 0 -#define MC13783_REG_SWITCHERS2_SW2AVSEL 0 -#define MC13783_REG_SWITCHERS2_SW2AVSEL_M (63 << 0) - -#define MC13783_REG_SWITCHERS3 27 -/* Enable does not exist for SW2B */ -#define MC13783_REG_SWITCHERS3_SW2BEN 0 -#define MC13783_REG_SWITCHERS3_SW2BVSEL 0 -#define MC13783_REG_SWITCHERS3_SW2BVSEL_M (63 << 0) - #define MC13783_REG_SWITCHERS5 29 #define MC13783_REG_SWITCHERS5_SW3EN (1 << 20) #define MC13783_REG_SWITCHERS5_SW3VSEL 18 @@ -117,44 +93,6 @@ /* Voltage Values */ -static const int mc13783_sw1x_val[] = { - 900000, 925000, 950000, 975000, - 1000000, 1025000, 1050000, 1075000, - 1100000, 1125000, 1150000, 1175000, - 1200000, 1225000, 1250000, 1275000, - 1300000, 1325000, 1350000, 1375000, - 1400000, 1425000, 1450000, 1475000, - 1500000, 1525000, 1550000, 1575000, - 1600000, 1625000, 1650000, 1675000, - 1700000, 1700000, 1700000, 1700000, - 1800000, 1800000, 1800000, 1800000, - 1850000, 1850000, 1850000, 1850000, - 2000000, 2000000, 2000000, 2000000, - 2100000, 2100000, 2100000, 2100000, - 2200000, 2200000, 2200000, 2200000, - 2200000, 2200000, 2200000, 2200000, - 2200000, 2200000, 2200000, 2200000, -}; - -static const int mc13783_sw2x_val[] = { - 900000, 925000, 950000, 975000, - 1000000, 1025000, 1050000, 1075000, - 1100000, 1125000, 1150000, 1175000, - 1200000, 1225000, 1250000, 1275000, - 1300000, 1325000, 1350000, 1375000, - 1400000, 1425000, 1450000, 1475000, - 1500000, 1525000, 1550000, 1575000, - 1600000, 1625000, 1650000, 1675000, - 1700000, 1700000, 1700000, 1700000, - 1800000, 1800000, 1800000, 1800000, - 1900000, 1900000, 1900000, 1900000, - 2000000, 2000000, 2000000, 2000000, - 2100000, 2100000, 2100000, 2100000, - 2200000, 2200000, 2200000, 2200000, - 2200000, 2200000, 2200000, 2200000, - 2200000, 2200000, 2200000, 2200000, -}; - static const unsigned int mc13783_sw3_val[] = { 5000000, 5000000, 5000000, 5500000, }; @@ -250,10 +188,6 @@ static struct regulator_ops mc13783_gpo_regulator_ops; MC13783_DEFINE(REG, _name, _reg, _vsel_reg, _voltages) static struct mc13xxx_regulator mc13783_regulators[] = { - MC13783_DEFINE_SW(SW1A, SWITCHERS0, SWITCHERS0, mc13783_sw1x_val), - MC13783_DEFINE_SW(SW1B, SWITCHERS1, SWITCHERS1, mc13783_sw1x_val), - MC13783_DEFINE_SW(SW2A, SWITCHERS2, SWITCHERS2, mc13783_sw2x_val), - MC13783_DEFINE_SW(SW2B, SWITCHERS3, SWITCHERS3, mc13783_sw2x_val), MC13783_DEFINE_SW(SW3, SWITCHERS5, SWITCHERS5, mc13783_sw3_val), MC13783_FIXED_DEFINE(REG, VAUDIO, REGULATORMODE0, mc13783_vaudio_val), @@ -304,10 +238,9 @@ static int mc13783_powermisc_rmw(struct mc13xxx_regulator_priv *priv, u32 mask, BUG_ON(val & ~mask); - mc13xxx_lock(priv->mc13xxx); ret = mc13xxx_reg_read(mc13783, MC13783_REG_POWERMISC, &valread); if (ret) - goto out; + return ret; /* Update the stored state for Power Gates. */ priv->powermisc_pwgt_state = @@ -320,10 +253,7 @@ static int mc13783_powermisc_rmw(struct mc13xxx_regulator_priv *priv, u32 mask, valread = (valread & ~MC13783_REG_POWERMISC_PWGTSPI_M) | priv->powermisc_pwgt_state; - ret = mc13xxx_reg_write(mc13783, MC13783_REG_POWERMISC, valread); -out: - mc13xxx_unlock(priv->mc13xxx); - return ret; + return mc13xxx_reg_write(mc13783, MC13783_REG_POWERMISC, valread); } static int mc13783_gpo_regulator_enable(struct regulator_dev *rdev) @@ -331,6 +261,7 @@ static int mc13783_gpo_regulator_enable(struct regulator_dev *rdev) struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev); struct mc13xxx_regulator *mc13xxx_regulators = priv->mc13xxx_regulators; int id = rdev_get_id(rdev); + int ret; u32 en_val = mc13xxx_regulators[id].enable_bit; dev_dbg(rdev_get_dev(rdev), "%s id: %d\n", __func__, id); @@ -340,8 +271,12 @@ static int mc13783_gpo_regulator_enable(struct regulator_dev *rdev) id == MC13783_REG_PWGT2SPI) en_val = 0; - return mc13783_powermisc_rmw(priv, mc13xxx_regulators[id].enable_bit, + mc13xxx_lock(priv->mc13xxx); + ret = mc13783_powermisc_rmw(priv, mc13xxx_regulators[id].enable_bit, en_val); + mc13xxx_unlock(priv->mc13xxx); + + return ret; } static int mc13783_gpo_regulator_disable(struct regulator_dev *rdev) @@ -349,6 +284,7 @@ static int mc13783_gpo_regulator_disable(struct regulator_dev *rdev) struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev); struct mc13xxx_regulator *mc13xxx_regulators = priv->mc13xxx_regulators; int id = rdev_get_id(rdev); + int ret; u32 dis_val = 0; dev_dbg(rdev_get_dev(rdev), "%s id: %d\n", __func__, id); @@ -358,8 +294,12 @@ static int mc13783_gpo_regulator_disable(struct regulator_dev *rdev) id == MC13783_REG_PWGT2SPI) dis_val = mc13xxx_regulators[id].enable_bit; - return mc13783_powermisc_rmw(priv, mc13xxx_regulators[id].enable_bit, + mc13xxx_lock(priv->mc13xxx); + ret = mc13783_powermisc_rmw(priv, mc13xxx_regulators[id].enable_bit, dis_val); + mc13xxx_unlock(priv->mc13xxx); + + return ret; } static int mc13783_gpo_regulator_is_enabled(struct regulator_dev *rdev) @@ -390,6 +330,7 @@ static struct regulator_ops mc13783_gpo_regulator_ops = { .is_enabled = mc13783_gpo_regulator_is_enabled, .list_voltage = regulator_list_voltage_table, .set_voltage = mc13xxx_fixed_regulator_set_voltage, + .get_voltage = mc13xxx_fixed_regulator_get_voltage, }; static int __devinit mc13783_regulator_probe(struct platform_device *pdev) diff --git a/trunk/drivers/regulator/mc13892-regulator.c b/trunk/drivers/regulator/mc13892-regulator.c index 1fa63812f7ac..b388b746452e 100644 --- a/trunk/drivers/regulator/mc13892-regulator.c +++ b/trunk/drivers/regulator/mc13892-regulator.c @@ -305,10 +305,9 @@ static int mc13892_powermisc_rmw(struct mc13xxx_regulator_priv *priv, u32 mask, BUG_ON(val & ~mask); - mc13xxx_lock(priv->mc13xxx); ret = mc13xxx_reg_read(mc13892, MC13892_POWERMISC, &valread); if (ret) - goto out; + return ret; /* Update the stored state for Power Gates. */ priv->powermisc_pwgt_state = @@ -321,16 +320,14 @@ static int mc13892_powermisc_rmw(struct mc13xxx_regulator_priv *priv, u32 mask, valread = (valread & ~MC13892_POWERMISC_PWGTSPI_M) | priv->powermisc_pwgt_state; - ret = mc13xxx_reg_write(mc13892, MC13892_POWERMISC, valread); -out: - mc13xxx_unlock(priv->mc13xxx); - return ret; + return mc13xxx_reg_write(mc13892, MC13892_POWERMISC, valread); } static int mc13892_gpo_regulator_enable(struct regulator_dev *rdev) { struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev); int id = rdev_get_id(rdev); + int ret; u32 en_val = mc13892_regulators[id].enable_bit; u32 mask = mc13892_regulators[id].enable_bit; @@ -343,13 +340,18 @@ static int mc13892_gpo_regulator_enable(struct regulator_dev *rdev) if (id == MC13892_GPO4) mask |= MC13892_POWERMISC_GPO4ADINEN; - return mc13892_powermisc_rmw(priv, mask, en_val); + mc13xxx_lock(priv->mc13xxx); + ret = mc13892_powermisc_rmw(priv, mask, en_val); + mc13xxx_unlock(priv->mc13xxx); + + return ret; } static int mc13892_gpo_regulator_disable(struct regulator_dev *rdev) { struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev); int id = rdev_get_id(rdev); + int ret; u32 dis_val = 0; dev_dbg(rdev_get_dev(rdev), "%s id: %d\n", __func__, id); @@ -358,8 +360,12 @@ static int mc13892_gpo_regulator_disable(struct regulator_dev *rdev) if (id == MC13892_PWGT1SPI || id == MC13892_PWGT2SPI) dis_val = mc13892_regulators[id].enable_bit; - return mc13892_powermisc_rmw(priv, mc13892_regulators[id].enable_bit, + mc13xxx_lock(priv->mc13xxx); + ret = mc13892_powermisc_rmw(priv, mc13892_regulators[id].enable_bit, dis_val); + mc13xxx_unlock(priv->mc13xxx); + + return ret; } static int mc13892_gpo_regulator_is_enabled(struct regulator_dev *rdev) @@ -390,13 +396,14 @@ static struct regulator_ops mc13892_gpo_regulator_ops = { .is_enabled = mc13892_gpo_regulator_is_enabled, .list_voltage = regulator_list_voltage_table, .set_voltage = mc13xxx_fixed_regulator_set_voltage, + .get_voltage = mc13xxx_fixed_regulator_get_voltage, }; -static int mc13892_sw_regulator_get_voltage_sel(struct regulator_dev *rdev) +static int mc13892_sw_regulator_get_voltage(struct regulator_dev *rdev) { struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev); int ret, id = rdev_get_id(rdev); - unsigned int val; + unsigned int val, hi; dev_dbg(rdev_get_dev(rdev), "%s id: %d\n", __func__, id); @@ -407,11 +414,17 @@ static int mc13892_sw_regulator_get_voltage_sel(struct regulator_dev *rdev) if (ret) return ret; + hi = val & MC13892_SWITCHERS0_SWxHI; val = (val & mc13892_regulators[id].vsel_mask) >> mc13892_regulators[id].vsel_shift; dev_dbg(rdev_get_dev(rdev), "%s id: %d val: %d\n", __func__, id, val); + if (hi) + val = (25000 * val) + 1100000; + else + val = (25000 * val) + 600000; + return val; } @@ -419,25 +432,37 @@ static int mc13892_sw_regulator_set_voltage_sel(struct regulator_dev *rdev, unsigned selector) { struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev); - int volt, mask, id = rdev_get_id(rdev); - u32 reg_value; + int hi, value, mask, id = rdev_get_id(rdev); + u32 valread; int ret; - volt = rdev->desc->volt_table[selector]; - mask = mc13892_regulators[id].vsel_mask; - reg_value = selector << mc13892_regulators[id].vsel_shift; - - if (volt > 1375000) { - mask |= MC13892_SWITCHERS0_SWxHI; - reg_value |= MC13892_SWITCHERS0_SWxHI; - } else if (volt < 1100000) { - mask |= MC13892_SWITCHERS0_SWxHI; - reg_value &= ~MC13892_SWITCHERS0_SWxHI; - } + value = rdev->desc->volt_table[selector]; mc13xxx_lock(priv->mc13xxx); - ret = mc13xxx_reg_rmw(priv->mc13xxx, mc13892_regulators[id].reg, mask, - reg_value); + ret = mc13xxx_reg_read(priv->mc13xxx, + mc13892_regulators[id].vsel_reg, &valread); + if (ret) + goto err; + + if (value > 1375000) + hi = 1; + else if (value < 1100000) + hi = 0; + else + hi = valread & MC13892_SWITCHERS0_SWxHI; + + if (hi) { + value = (value - 1100000) / 25000; + value |= MC13892_SWITCHERS0_SWxHI; + } else + value = (value - 600000) / 25000; + + mask = mc13892_regulators[id].vsel_mask | MC13892_SWITCHERS0_SWxHI; + valread = (valread & ~mask) | + (value << mc13892_regulators[id].vsel_shift); + ret = mc13xxx_reg_write(priv->mc13xxx, mc13892_regulators[id].vsel_reg, + valread); +err: mc13xxx_unlock(priv->mc13xxx); return ret; @@ -446,7 +471,7 @@ static int mc13892_sw_regulator_set_voltage_sel(struct regulator_dev *rdev, static struct regulator_ops mc13892_sw_regulator_ops = { .list_voltage = regulator_list_voltage_table, .set_voltage_sel = mc13892_sw_regulator_set_voltage_sel, - .get_voltage_sel = mc13892_sw_regulator_get_voltage_sel, + .get_voltage = mc13892_sw_regulator_get_voltage, }; static int mc13892_vcam_set_mode(struct regulator_dev *rdev, unsigned int mode) diff --git a/trunk/drivers/regulator/mc13xxx-regulator-core.c b/trunk/drivers/regulator/mc13xxx-regulator-core.c index 88cbb832d555..d6eda28ca5d0 100644 --- a/trunk/drivers/regulator/mc13xxx-regulator-core.c +++ b/trunk/drivers/regulator/mc13xxx-regulator-core.c @@ -143,21 +143,30 @@ int mc13xxx_fixed_regulator_set_voltage(struct regulator_dev *rdev, int min_uV, __func__, id, min_uV, max_uV); if (min_uV <= rdev->desc->volt_table[0] && - rdev->desc->volt_table[0] <= max_uV) { - *selector = 0; + rdev->desc->volt_table[0] <= max_uV) return 0; - } else { + else return -EINVAL; - } } EXPORT_SYMBOL_GPL(mc13xxx_fixed_regulator_set_voltage); +int mc13xxx_fixed_regulator_get_voltage(struct regulator_dev *rdev) +{ + int id = rdev_get_id(rdev); + + dev_dbg(rdev_get_dev(rdev), "%s id: %d\n", __func__, id); + + return rdev->desc->volt_table[0]; +} +EXPORT_SYMBOL_GPL(mc13xxx_fixed_regulator_get_voltage); + struct regulator_ops mc13xxx_fixed_regulator_ops = { .enable = mc13xxx_regulator_enable, .disable = mc13xxx_regulator_disable, .is_enabled = mc13xxx_regulator_is_enabled, .list_voltage = regulator_list_voltage_table, .set_voltage = mc13xxx_fixed_regulator_set_voltage, + .get_voltage = mc13xxx_fixed_regulator_get_voltage, }; EXPORT_SYMBOL_GPL(mc13xxx_fixed_regulator_ops); diff --git a/trunk/drivers/regulator/mc13xxx.h b/trunk/drivers/regulator/mc13xxx.h index 06c8903f182a..eaff5510b6df 100644 --- a/trunk/drivers/regulator/mc13xxx.h +++ b/trunk/drivers/regulator/mc13xxx.h @@ -34,6 +34,7 @@ struct mc13xxx_regulator_priv { extern int mc13xxx_fixed_regulator_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV, unsigned *selector); +extern int mc13xxx_fixed_regulator_get_voltage(struct regulator_dev *rdev); #ifdef CONFIG_OF extern int mc13xxx_get_num_regulators_dt(struct platform_device *pdev); diff --git a/trunk/drivers/regulator/of_regulator.c b/trunk/drivers/regulator/of_regulator.c index 6f684916fd79..3e4106f2bda9 100644 --- a/trunk/drivers/regulator/of_regulator.c +++ b/trunk/drivers/regulator/of_regulator.c @@ -92,18 +92,16 @@ struct regulator_init_data *of_get_regulator_init_data(struct device *dev, EXPORT_SYMBOL_GPL(of_get_regulator_init_data); /** - * of_regulator_match - extract multiple regulator init data from device tree. + * of_regulator_match - extract regulator init data when node + * property "regulator-compatible" matches with the regulator name. * @dev: device requesting the data * @node: parent device node of the regulators * @matches: match table for the regulators * @num_matches: number of entries in match table * - * This function uses a match table specified by the regulator driver to - * parse regulator init data from the device tree. @node is expected to - * contain a set of child nodes, each providing the init data for one - * regulator. The data parsed from a child node will be matched to a regulator - * based on either the deprecated property regulator-compatible if present, - * or otherwise the child node's name. Note that the match table is modified + * This function uses a match table specified by the regulator driver and + * looks up the corresponding init data in the device tree if + * regulator-compatible matches. Note that the match table is modified * in place. * * Returns the number of matches found or a negative error code on failure. @@ -114,23 +112,26 @@ int of_regulator_match(struct device *dev, struct device_node *node, { unsigned int count = 0; unsigned int i; - const char *name; + const char *regulator_comp; struct device_node *child; if (!dev || !node) return -EINVAL; for_each_child_of_node(node, child) { - name = of_get_property(child, + regulator_comp = of_get_property(child, "regulator-compatible", NULL); - if (!name) - name = child->name; + if (!regulator_comp) { + dev_err(dev, "regulator-compatible is missing for node %s\n", + child->name); + continue; + } for (i = 0; i < num_matches; i++) { struct of_regulator_match *match = &matches[i]; if (match->of_node) continue; - if (strcmp(match->name, name)) + if (strcmp(match->name, regulator_comp)) continue; match->init_data = diff --git a/trunk/drivers/regulator/palmas-regulator.c b/trunk/drivers/regulator/palmas-regulator.c index 2ba7502fa3b2..17d19fbbc490 100644 --- a/trunk/drivers/regulator/palmas-regulator.c +++ b/trunk/drivers/regulator/palmas-regulator.c @@ -443,17 +443,52 @@ static int palmas_list_voltage_ldo(struct regulator_dev *dev, return 850000 + (selector * 50000); } +static int palmas_get_voltage_ldo_sel(struct regulator_dev *dev) +{ + struct palmas_pmic *pmic = rdev_get_drvdata(dev); + int id = rdev_get_id(dev); + int selector; + unsigned int reg; + unsigned int addr; + + addr = palmas_regs_info[id].vsel_addr; + + palmas_ldo_read(pmic->palmas, addr, ®); + + selector = reg & PALMAS_LDO1_VOLTAGE_VSEL_MASK; + + /* Adjust selector to match list_voltage ranges */ + if (selector > 49) + selector = 49; + + return selector; +} + +static int palmas_set_voltage_ldo_sel(struct regulator_dev *dev, + unsigned selector) +{ + struct palmas_pmic *pmic = rdev_get_drvdata(dev); + int id = rdev_get_id(dev); + unsigned int reg = 0; + unsigned int addr; + + addr = palmas_regs_info[id].vsel_addr; + + reg = selector; + + palmas_ldo_write(pmic->palmas, addr, reg); + + return 0; +} + static int palmas_map_voltage_ldo(struct regulator_dev *rdev, int min_uV, int max_uV) { int ret, voltage; - if (min_uV == 0) - return 0; - - if (min_uV < 900000) - min_uV = 900000; - ret = DIV_ROUND_UP(min_uV - 900000, 50000) + 1; + ret = ((min_uV - 900000) / 50000) + 1; + if (ret < 0) + return ret; /* Map back into a voltage to verify we're still in bounds */ voltage = palmas_list_voltage_ldo(rdev, ret); @@ -467,8 +502,8 @@ static struct regulator_ops palmas_ops_ldo = { .is_enabled = palmas_is_enabled_ldo, .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, - .get_voltage_sel = regulator_get_voltage_sel_regmap, - .set_voltage_sel = regulator_set_voltage_sel_regmap, + .get_voltage_sel = palmas_get_voltage_ldo_sel, + .set_voltage_sel = palmas_set_voltage_ldo_sel, .list_voltage = palmas_list_voltage_ldo, .map_voltage = palmas_map_voltage_ldo, }; @@ -551,7 +586,7 @@ static int palmas_ldo_init(struct palmas *palmas, int id, addr = palmas_regs_info[id].ctrl_addr; - ret = palmas_ldo_read(palmas, addr, ®); + ret = palmas_smps_read(palmas, addr, ®); if (ret) return ret; @@ -561,7 +596,7 @@ static int palmas_ldo_init(struct palmas *palmas, int id, if (reg_init->mode_sleep) reg |= PALMAS_LDO1_CTRL_MODE_SLEEP; - ret = palmas_ldo_write(palmas, addr, reg); + ret = palmas_smps_write(palmas, addr, reg); if (ret) return ret; @@ -595,7 +630,7 @@ static __devinit int palmas_probe(struct platform_device *pdev) ret = palmas_smps_read(palmas, PALMAS_SMPS_CTRL, ®); if (ret) - return ret; + goto err_unregister_regulator; if (reg & PALMAS_SMPS_CTRL_SMPS12_SMPS123_EN) pmic->smps123 = 1; @@ -641,9 +676,7 @@ static __devinit int palmas_probe(struct platform_device *pdev) case PALMAS_REG_SMPS10: pmic->desc[id].n_voltages = PALMAS_SMPS10_NUM_VOLTAGES; pmic->desc[id].ops = &palmas_ops_smps10; - pmic->desc[id].vsel_reg = - PALMAS_BASE_TO_REG(PALMAS_SMPS_BASE, - PALMAS_SMPS10_CTRL); + pmic->desc[id].vsel_reg = PALMAS_SMPS10_CTRL; pmic->desc[id].vsel_mask = SMPS10_VSEL; pmic->desc[id].enable_reg = PALMAS_BASE_TO_REG(PALMAS_SMPS_BASE, @@ -719,9 +752,6 @@ static __devinit int palmas_probe(struct platform_device *pdev) pmic->desc[id].type = REGULATOR_VOLTAGE; pmic->desc[id].owner = THIS_MODULE; - pmic->desc[id].vsel_reg = PALMAS_BASE_TO_REG(PALMAS_LDO_BASE, - palmas_regs_info[id].vsel_addr); - pmic->desc[id].vsel_mask = PALMAS_LDO1_VOLTAGE_VSEL_MASK; pmic->desc[id].enable_reg = PALMAS_BASE_TO_REG(PALMAS_LDO_BASE, palmas_regs_info[id].ctrl_addr); pmic->desc[id].enable_mask = PALMAS_LDO1_CTRL_MODE_ACTIVE; @@ -748,10 +778,8 @@ static __devinit int palmas_probe(struct platform_device *pdev) reg_init = pdata->reg_init[id]; if (reg_init) { ret = palmas_ldo_init(palmas, id, reg_init); - if (ret) { - regulator_unregister(pmic->rdev[id]); + if (ret) goto err_unregister_regulator; - } } } } diff --git a/trunk/drivers/regulator/s2mps11.c b/trunk/drivers/regulator/s2mps11.c index 926f9c8f2fac..4669dc9ac74a 100644 --- a/trunk/drivers/regulator/s2mps11.c +++ b/trunk/drivers/regulator/s2mps11.c @@ -24,7 +24,7 @@ #include struct s2mps11_info { - struct regulator_dev *rdev[S2MPS11_REGULATOR_MAX]; + struct regulator_dev **rdev; int ramp_delay2; int ramp_delay34; @@ -236,8 +236,9 @@ static __devinit int s2mps11_pmic_probe(struct platform_device *pdev) struct sec_pmic_dev *iodev = dev_get_drvdata(pdev->dev.parent); struct sec_platform_data *pdata = dev_get_platdata(iodev->dev); struct regulator_config config = { }; + struct regulator_dev **rdev; struct s2mps11_info *s2mps11; - int i, ret; + int i, ret, size; unsigned char ramp_enable, ramp_reg = 0; if (!pdata) { @@ -250,6 +251,13 @@ static __devinit int s2mps11_pmic_probe(struct platform_device *pdev) if (!s2mps11) return -ENOMEM; + size = sizeof(struct regulator_dev *) * S2MPS11_REGULATOR_MAX; + s2mps11->rdev = devm_kzalloc(&pdev->dev, size, GFP_KERNEL); + if (!s2mps11->rdev) { + return -ENOMEM; + } + + rdev = s2mps11->rdev; platform_set_drvdata(pdev, s2mps11); s2mps11->ramp_delay2 = pdata->buck2_ramp_delay; @@ -289,12 +297,12 @@ static __devinit int s2mps11_pmic_probe(struct platform_device *pdev) config.init_data = pdata->regulators[i].initdata; config.driver_data = s2mps11; - s2mps11->rdev[i] = regulator_register(®ulators[i], &config); - if (IS_ERR(s2mps11->rdev[i])) { - ret = PTR_ERR(s2mps11->rdev[i]); + rdev[i] = regulator_register(®ulators[i], &config); + if (IS_ERR(rdev[i])) { + ret = PTR_ERR(rdev[i]); dev_err(&pdev->dev, "regulator init failed for %d\n", i); - s2mps11->rdev[i] = NULL; + rdev[i] = NULL; goto err; } } @@ -302,7 +310,8 @@ static __devinit int s2mps11_pmic_probe(struct platform_device *pdev) return 0; err: for (i = 0; i < S2MPS11_REGULATOR_MAX; i++) - regulator_unregister(s2mps11->rdev[i]); + if (rdev[i]) + regulator_unregister(rdev[i]); return ret; } @@ -310,10 +319,12 @@ static __devinit int s2mps11_pmic_probe(struct platform_device *pdev) static int __devexit s2mps11_pmic_remove(struct platform_device *pdev) { struct s2mps11_info *s2mps11 = platform_get_drvdata(pdev); + struct regulator_dev **rdev = s2mps11->rdev; int i; for (i = 0; i < S2MPS11_REGULATOR_MAX; i++) - regulator_unregister(s2mps11->rdev[i]); + if (rdev[i]) + regulator_unregister(rdev[i]); return 0; } diff --git a/trunk/drivers/regulator/tps65217-regulator.c b/trunk/drivers/regulator/tps65217-regulator.c index ab00cab905b7..6caa222af77a 100644 --- a/trunk/drivers/regulator/tps65217-regulator.c +++ b/trunk/drivers/regulator/tps65217-regulator.c @@ -22,7 +22,6 @@ #include #include -#include #include #include #include @@ -282,130 +281,37 @@ static const struct regulator_desc regulators[] = { NULL), }; -#ifdef CONFIG_OF -static struct of_regulator_match reg_matches[] = { - { .name = "dcdc1", .driver_data = (void *)TPS65217_DCDC_1 }, - { .name = "dcdc2", .driver_data = (void *)TPS65217_DCDC_2 }, - { .name = "dcdc3", .driver_data = (void *)TPS65217_DCDC_3 }, - { .name = "ldo1", .driver_data = (void *)TPS65217_LDO_1 }, - { .name = "ldo2", .driver_data = (void *)TPS65217_LDO_2 }, - { .name = "ldo3", .driver_data = (void *)TPS65217_LDO_3 }, - { .name = "ldo4", .driver_data = (void *)TPS65217_LDO_4 }, -}; - -static struct tps65217_board *tps65217_parse_dt(struct platform_device *pdev) -{ - struct tps65217 *tps = dev_get_drvdata(pdev->dev.parent); - struct device_node *node = tps->dev->of_node; - struct tps65217_board *pdata; - struct device_node *regs; - int i, count; - - regs = of_find_node_by_name(node, "regulators"); - if (!regs) - return NULL; - - count = of_regulator_match(pdev->dev.parent, regs, - reg_matches, TPS65217_NUM_REGULATOR); - of_node_put(regs); - if ((count < 0) || (count > TPS65217_NUM_REGULATOR)) - return NULL; - - pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); - if (!pdata) - return NULL; - - for (i = 0; i < count; i++) { - if (!reg_matches[i].init_data || !reg_matches[i].of_node) - continue; - - pdata->tps65217_init_data[i] = reg_matches[i].init_data; - pdata->of_node[i] = reg_matches[i].of_node; - } - - return pdata; -} -#else -static struct tps65217_board *tps65217_parse_dt(struct platform_device *pdev) -{ - return NULL; -} -#endif - static int __devinit tps65217_regulator_probe(struct platform_device *pdev) { - struct tps65217 *tps = dev_get_drvdata(pdev->dev.parent); - struct tps65217_board *pdata = dev_get_platdata(tps->dev); - struct regulator_init_data *reg_data; struct regulator_dev *rdev; + struct tps65217 *tps; + struct tps_info *info = &tps65217_pmic_regs[pdev->id]; struct regulator_config config = { }; - int i, ret; - if (tps->dev->of_node) - pdata = tps65217_parse_dt(pdev); + /* Already set by core driver */ + tps = dev_to_tps65217(pdev->dev.parent); + tps->info[pdev->id] = info; - if (!pdata) { - dev_err(&pdev->dev, "Platform data not found\n"); - return -EINVAL; - } + config.dev = &pdev->dev; + config.of_node = pdev->dev.of_node; + config.init_data = pdev->dev.platform_data; + config.driver_data = tps; - if (tps65217_chip_id(tps) != TPS65217) { - dev_err(&pdev->dev, "Invalid tps chip version\n"); - return -ENODEV; - } + rdev = regulator_register(®ulators[pdev->id], &config); + if (IS_ERR(rdev)) + return PTR_ERR(rdev); - platform_set_drvdata(pdev, tps); + platform_set_drvdata(pdev, rdev); - for (i = 0; i < TPS65217_NUM_REGULATOR; i++) { - - reg_data = pdata->tps65217_init_data[i]; - - /* - * Regulator API handles empty constraints but not NULL - * constraints - */ - if (!reg_data) - continue; - - /* Register the regulators */ - tps->info[i] = &tps65217_pmic_regs[i]; - - config.dev = tps->dev; - config.init_data = reg_data; - config.driver_data = tps; - config.regmap = tps->regmap; - if (tps->dev->of_node) - config.of_node = pdata->of_node[i]; - - rdev = regulator_register(®ulators[i], &config); - if (IS_ERR(rdev)) { - dev_err(tps->dev, "failed to register %s regulator\n", - pdev->name); - ret = PTR_ERR(rdev); - goto err_unregister_regulator; - } - - /* Save regulator for cleanup */ - tps->rdev[i] = rdev; - } return 0; - -err_unregister_regulator: - while (--i >= 0) - regulator_unregister(tps->rdev[i]); - - return ret; } static int __devexit tps65217_regulator_remove(struct platform_device *pdev) { - struct tps65217 *tps = platform_get_drvdata(pdev); - unsigned int i; - - for (i = 0; i < TPS65217_NUM_REGULATOR; i++) - regulator_unregister(tps->rdev[i]); + struct regulator_dev *rdev = platform_get_drvdata(pdev); platform_set_drvdata(pdev, NULL); + regulator_unregister(rdev); return 0; } diff --git a/trunk/drivers/regulator/tps6524x-regulator.c b/trunk/drivers/regulator/tps6524x-regulator.c index 058d2f2675e9..947ece933d90 100644 --- a/trunk/drivers/regulator/tps6524x-regulator.c +++ b/trunk/drivers/regulator/tps6524x-regulator.c @@ -502,13 +502,15 @@ static int set_current_limit(struct regulator_dev *rdev, int min_uA, if (info->n_ilimsels == 1) return -EINVAL; - for (i = info->n_ilimsels - 1; i >= 0; i--) { + for (i = 0; i < info->n_ilimsels; i++) if (min_uA <= info->ilimsels[i] && max_uA >= info->ilimsels[i]) - return write_field(hw, &info->ilimsel, i); - } + break; + + if (i >= info->n_ilimsels) + return -EINVAL; - return -EINVAL; + return write_field(hw, &info->ilimsel, i); } static int get_current_limit(struct regulator_dev *rdev) diff --git a/trunk/drivers/regulator/tps6586x-regulator.c b/trunk/drivers/regulator/tps6586x-regulator.c index ce1e7cb8d513..e6da90ab5153 100644 --- a/trunk/drivers/regulator/tps6586x-regulator.c +++ b/trunk/drivers/regulator/tps6586x-regulator.c @@ -57,6 +57,9 @@ struct tps6586x_regulator { struct regulator_desc desc; + int volt_reg; + int volt_shift; + int volt_nbits; int enable_bit[2]; int enable_reg[2]; @@ -78,10 +81,10 @@ static int tps6586x_set_voltage_sel(struct regulator_dev *rdev, int ret, val, rid = rdev_get_id(rdev); uint8_t mask; - val = selector << (ffs(rdev->desc->vsel_mask) - 1); - mask = rdev->desc->vsel_mask; + val = selector << ri->volt_shift; + mask = ((1 << ri->volt_nbits) - 1) << ri->volt_shift; - ret = tps6586x_update(parent, rdev->desc->vsel_reg, val, mask); + ret = tps6586x_update(parent, ri->volt_reg, val, mask); if (ret) return ret; @@ -97,17 +100,66 @@ static int tps6586x_set_voltage_sel(struct regulator_dev *rdev, return ret; } +static int tps6586x_get_voltage_sel(struct regulator_dev *rdev) +{ + struct tps6586x_regulator *ri = rdev_get_drvdata(rdev); + struct device *parent = to_tps6586x_dev(rdev); + uint8_t val, mask; + int ret; + + ret = tps6586x_read(parent, ri->volt_reg, &val); + if (ret) + return ret; + + mask = ((1 << ri->volt_nbits) - 1) << ri->volt_shift; + val = (val & mask) >> ri->volt_shift; + + if (val >= ri->desc.n_voltages) + BUG(); + + return val; +} + +static int tps6586x_regulator_enable(struct regulator_dev *rdev) +{ + struct tps6586x_regulator *ri = rdev_get_drvdata(rdev); + struct device *parent = to_tps6586x_dev(rdev); + + return tps6586x_set_bits(parent, ri->enable_reg[0], + 1 << ri->enable_bit[0]); +} + +static int tps6586x_regulator_disable(struct regulator_dev *rdev) +{ + struct tps6586x_regulator *ri = rdev_get_drvdata(rdev); + struct device *parent = to_tps6586x_dev(rdev); + + return tps6586x_clr_bits(parent, ri->enable_reg[0], + 1 << ri->enable_bit[0]); +} + +static int tps6586x_regulator_is_enabled(struct regulator_dev *rdev) +{ + struct tps6586x_regulator *ri = rdev_get_drvdata(rdev); + struct device *parent = to_tps6586x_dev(rdev); + uint8_t reg_val; + int ret; + + ret = tps6586x_read(parent, ri->enable_reg[0], ®_val); + if (ret) + return ret; + + return !!(reg_val & (1 << ri->enable_bit[0])); +} + static struct regulator_ops tps6586x_regulator_ops = { .list_voltage = regulator_list_voltage_table, - .get_voltage_sel = regulator_get_voltage_sel_regmap, + .get_voltage_sel = tps6586x_get_voltage_sel, .set_voltage_sel = tps6586x_set_voltage_sel, - .is_enabled = regulator_is_enabled_regmap, - .enable = regulator_enable_regmap, - .disable = regulator_disable_regmap, -}; - -static struct regulator_ops tps6586x_sys_regulator_ops = { + .is_enabled = tps6586x_regulator_is_enabled, + .enable = tps6586x_regulator_enable, + .disable = tps6586x_regulator_disable, }; static const unsigned int tps6586x_ldo0_voltages[] = { @@ -150,11 +202,10 @@ static const unsigned int tps6586x_dvm_voltages[] = { .n_voltages = ARRAY_SIZE(tps6586x_##vdata##_voltages), \ .volt_table = tps6586x_##vdata##_voltages, \ .owner = THIS_MODULE, \ - .enable_reg = TPS6586X_SUPPLY##ereg0, \ - .enable_mask = 1 << (ebit0), \ - .vsel_reg = TPS6586X_##vreg, \ - .vsel_mask = ((1 << (nbits)) - 1) << (shift), \ }, \ + .volt_reg = TPS6586X_##vreg, \ + .volt_shift = (shift), \ + .volt_nbits = (nbits), \ .enable_reg[0] = TPS6586X_SUPPLY##ereg0, \ .enable_bit[0] = (ebit0), \ .enable_reg[1] = TPS6586X_SUPPLY##ereg1, \ @@ -179,39 +230,24 @@ static const unsigned int tps6586x_dvm_voltages[] = { TPS6586X_REGULATOR_DVM_GOREG(goreg, gobit) \ } -#define TPS6586X_SYS_REGULATOR() \ -{ \ - .desc = { \ - .supply_name = "sys", \ - .name = "REG-SYS", \ - .ops = &tps6586x_sys_regulator_ops, \ - .type = REGULATOR_VOLTAGE, \ - .id = TPS6586X_ID_SYS, \ - .owner = THIS_MODULE, \ - }, \ -} - static struct tps6586x_regulator tps6586x_regulator[] = { - TPS6586X_SYS_REGULATOR(), TPS6586X_LDO(LDO_0, "vinldo01", ldo0, SUPPLYV1, 5, 3, ENC, 0, END, 0), TPS6586X_LDO(LDO_3, "vinldo23", ldo, SUPPLYV4, 0, 3, ENC, 2, END, 2), - TPS6586X_LDO(LDO_5, "REG-SYS", ldo, SUPPLYV6, 0, 3, ENE, 6, ENE, 6), + TPS6586X_LDO(LDO_5, NULL, ldo, SUPPLYV6, 0, 3, ENE, 6, ENE, 6), TPS6586X_LDO(LDO_6, "vinldo678", ldo, SUPPLYV3, 0, 3, ENC, 4, END, 4), TPS6586X_LDO(LDO_7, "vinldo678", ldo, SUPPLYV3, 3, 3, ENC, 5, END, 5), TPS6586X_LDO(LDO_8, "vinldo678", ldo, SUPPLYV2, 5, 3, ENC, 6, END, 6), TPS6586X_LDO(LDO_9, "vinldo9", ldo, SUPPLYV6, 3, 3, ENE, 7, ENE, 7), - TPS6586X_LDO(LDO_RTC, "REG-SYS", ldo, SUPPLYV4, 3, 3, V4, 7, V4, 7), + TPS6586X_LDO(LDO_RTC, NULL, ldo, SUPPLYV4, 3, 3, V4, 7, V4, 7), TPS6586X_LDO(LDO_1, "vinldo01", dvm, SUPPLYV1, 0, 5, ENC, 1, END, 1), - TPS6586X_LDO(SM_2, "vin-sm2", sm2, SUPPLYV2, 0, 5, ENC, 7, END, 7), + TPS6586X_LDO(SM_2, "sm2", sm2, SUPPLYV2, 0, 5, ENC, 7, END, 7), TPS6586X_DVM(LDO_2, "vinldo23", dvm, LDO2BV1, 0, 5, ENA, 3, ENB, 3, VCC2, 6), TPS6586X_DVM(LDO_4, "vinldo4", ldo4, LDO4V1, 0, 5, ENC, 3, END, 3, VCC1, 6), - TPS6586X_DVM(SM_0, "vin-sm0", dvm, SM0V1, 0, 5, ENA, 1, - ENB, 1, VCC1, 2), - TPS6586X_DVM(SM_1, "vin-sm1", dvm, SM1V1, 0, 5, ENA, 0, - ENB, 0, VCC1, 0), + TPS6586X_DVM(SM_0, "sm0", dvm, SM0V1, 0, 5, ENA, 1, ENB, 1, VCC1, 2), + TPS6586X_DVM(SM_1, "sm1", dvm, SM1V1, 0, 5, ENA, 0, ENB, 0, VCC1, 0), }; /* diff --git a/trunk/drivers/regulator/twl-regulator.c b/trunk/drivers/regulator/twl-regulator.c index 7eb986a40746..242fe90dc565 100644 --- a/trunk/drivers/regulator/twl-regulator.c +++ b/trunk/drivers/regulator/twl-regulator.c @@ -10,8 +10,6 @@ */ #include -#include -#include #include #include #include @@ -626,9 +624,18 @@ static int twlfixed_list_voltage(struct regulator_dev *rdev, unsigned index) return info->min_mV * 1000; } +static int twlfixed_get_voltage(struct regulator_dev *rdev) +{ + struct twlreg_info *info = rdev_get_drvdata(rdev); + + return info->min_mV * 1000; +} + static struct regulator_ops twl4030fixed_ops = { .list_voltage = twlfixed_list_voltage, + .get_voltage = twlfixed_get_voltage, + .enable = twl4030reg_enable, .disable = twl4030reg_disable, .is_enabled = twl4030reg_is_enabled, @@ -641,6 +648,8 @@ static struct regulator_ops twl4030fixed_ops = { static struct regulator_ops twl6030fixed_ops = { .list_voltage = twlfixed_list_voltage, + .get_voltage = twlfixed_get_voltage, + .enable = twl6030reg_enable, .disable = twl6030reg_disable, .is_enabled = twl6030reg_is_enabled, @@ -650,6 +659,13 @@ static struct regulator_ops twl6030fixed_ops = { .get_status = twl6030reg_get_status, }; +static struct regulator_ops twl6030_fixed_resource = { + .enable = twl6030reg_enable, + .disable = twl6030reg_disable, + .is_enabled = twl6030reg_is_enabled, + .get_status = twl6030reg_get_status, +}; + /* * SMPS status and control */ @@ -741,32 +757,37 @@ static int twl6030smps_list_voltage(struct regulator_dev *rdev, unsigned index) return voltage; } -static int twl6030smps_map_voltage(struct regulator_dev *rdev, int min_uV, - int max_uV) +static int +twl6030smps_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV, + unsigned int *selector) { - struct twlreg_info *info = rdev_get_drvdata(rdev); - int vsel = 0; + struct twlreg_info *info = rdev_get_drvdata(rdev); + int vsel = 0; switch (info->flags) { case 0: if (min_uV == 0) vsel = 0; else if ((min_uV >= 600000) && (min_uV <= 1300000)) { + int calc_uV; vsel = DIV_ROUND_UP(min_uV - 600000, 12500); vsel++; + calc_uV = twl6030smps_list_voltage(rdev, vsel); + if (calc_uV > max_uV) + return -EINVAL; } /* Values 1..57 for vsel are linear and can be calculated * values 58..62 are non linear. */ - else if ((min_uV > 1900000) && (min_uV <= 2100000)) + else if ((min_uV > 1900000) && (max_uV >= 2100000)) vsel = 62; - else if ((min_uV > 1800000) && (min_uV <= 1900000)) + else if ((min_uV > 1800000) && (max_uV >= 1900000)) vsel = 61; - else if ((min_uV > 1500000) && (min_uV <= 1800000)) + else if ((min_uV > 1500000) && (max_uV >= 1800000)) vsel = 60; - else if ((min_uV > 1350000) && (min_uV <= 1500000)) + else if ((min_uV > 1350000) && (max_uV >= 1500000)) vsel = 59; - else if ((min_uV > 1300000) && (min_uV <= 1350000)) + else if ((min_uV > 1300000) && (max_uV >= 1350000)) vsel = 58; else return -EINVAL; @@ -775,21 +796,25 @@ static int twl6030smps_map_voltage(struct regulator_dev *rdev, int min_uV, if (min_uV == 0) vsel = 0; else if ((min_uV >= 700000) && (min_uV <= 1420000)) { + int calc_uV; vsel = DIV_ROUND_UP(min_uV - 700000, 12500); vsel++; + calc_uV = twl6030smps_list_voltage(rdev, vsel); + if (calc_uV > max_uV) + return -EINVAL; } /* Values 1..57 for vsel are linear and can be calculated * values 58..62 are non linear. */ - else if ((min_uV > 1900000) && (min_uV <= 2100000)) + else if ((min_uV > 1900000) && (max_uV >= 2100000)) vsel = 62; - else if ((min_uV > 1800000) && (min_uV <= 1900000)) + else if ((min_uV > 1800000) && (max_uV >= 1900000)) vsel = 61; - else if ((min_uV > 1350000) && (min_uV <= 1800000)) + else if ((min_uV > 1350000) && (max_uV >= 1800000)) vsel = 60; - else if ((min_uV > 1350000) && (min_uV <= 1500000)) + else if ((min_uV > 1350000) && (max_uV >= 1500000)) vsel = 59; - else if ((min_uV > 1300000) && (min_uV <= 1350000)) + else if ((min_uV > 1300000) && (max_uV >= 1350000)) vsel = 58; else return -EINVAL; @@ -805,23 +830,17 @@ static int twl6030smps_map_voltage(struct regulator_dev *rdev, int min_uV, case SMPS_OFFSET_EN|SMPS_EXTENDED_EN: if (min_uV == 0) { vsel = 0; - } else if ((min_uV >= 2161000) && (min_uV <= 4321000)) { + } else if ((min_uV >= 2161000) && (max_uV <= 4321000)) { vsel = DIV_ROUND_UP(min_uV - 2161000, 38600); vsel++; } break; } - return vsel; -} - -static int twl6030smps_set_voltage_sel(struct regulator_dev *rdev, - unsigned int selector) -{ - struct twlreg_info *info = rdev_get_drvdata(rdev); + *selector = vsel; return twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_VOLTAGE_SMPS, - selector); + vsel); } static int twl6030smps_get_voltage_sel(struct regulator_dev *rdev) @@ -833,9 +852,8 @@ static int twl6030smps_get_voltage_sel(struct regulator_dev *rdev) static struct regulator_ops twlsmps_ops = { .list_voltage = twl6030smps_list_voltage, - .map_voltage = twl6030smps_map_voltage, - .set_voltage_sel = twl6030smps_set_voltage_sel, + .set_voltage = twl6030smps_set_voltage, .get_voltage_sel = twl6030smps_get_voltage_sel, .enable = twl6030reg_enable, @@ -858,7 +876,7 @@ static struct regulator_ops twlsmps_ops = { 0x0, TWL6030, twl6030fixed_ops) #define TWL4030_ADJUSTABLE_LDO(label, offset, num, turnon_delay, remap_conf) \ -static const struct twlreg_info TWL4030_INFO_##label = { \ +static struct twlreg_info TWL4030_INFO_##label = { \ .base = offset, \ .id = num, \ .table_len = ARRAY_SIZE(label##_VSEL_table), \ @@ -876,7 +894,7 @@ static const struct twlreg_info TWL4030_INFO_##label = { \ } #define TWL4030_ADJUSTABLE_SMPS(label, offset, num, turnon_delay, remap_conf) \ -static const struct twlreg_info TWL4030_INFO_##label = { \ +static struct twlreg_info TWL4030_INFO_##label = { \ .base = offset, \ .id = num, \ .remap = remap_conf, \ @@ -891,7 +909,7 @@ static const struct twlreg_info TWL4030_INFO_##label = { \ } #define TWL6030_ADJUSTABLE_SMPS(label) \ -static const struct twlreg_info TWL6030_INFO_##label = { \ +static struct twlreg_info TWL6030_INFO_##label = { \ .desc = { \ .name = #label, \ .id = TWL6030_REG_##label, \ @@ -902,7 +920,7 @@ static const struct twlreg_info TWL6030_INFO_##label = { \ } #define TWL6030_ADJUSTABLE_LDO(label, offset, min_mVolts, max_mVolts) \ -static const struct twlreg_info TWL6030_INFO_##label = { \ +static struct twlreg_info TWL6030_INFO_##label = { \ .base = offset, \ .min_mV = min_mVolts, \ .max_mV = max_mVolts, \ @@ -917,7 +935,7 @@ static const struct twlreg_info TWL6030_INFO_##label = { \ } #define TWL6025_ADJUSTABLE_LDO(label, offset, min_mVolts, max_mVolts) \ -static const struct twlreg_info TWL6025_INFO_##label = { \ +static struct twlreg_info TWL6025_INFO_##label = { \ .base = offset, \ .min_mV = min_mVolts, \ .max_mV = max_mVolts, \ @@ -933,7 +951,7 @@ static const struct twlreg_info TWL6025_INFO_##label = { \ #define TWL_FIXED_LDO(label, offset, mVolts, num, turnon_delay, remap_conf, \ family, operations) \ -static const struct twlreg_info TWLFIXED_INFO_##label = { \ +static struct twlreg_info TWLFIXED_INFO_##label = { \ .base = offset, \ .id = num, \ .min_mV = mVolts, \ @@ -963,7 +981,7 @@ static struct twlreg_info TWLRES_INFO_##label = { \ } #define TWL6025_ADJUSTABLE_SMPS(label, offset) \ -static const struct twlreg_info TWLSMPS_INFO_##label = { \ +static struct twlreg_info TWLSMPS_INFO_##label = { \ .base = offset, \ .min_mV = 600, \ .max_mV = 2100, \ @@ -1019,7 +1037,7 @@ TWL6025_ADJUSTABLE_LDO(LDO7, 0x74, 1000, 3300); TWL6025_ADJUSTABLE_LDO(LDO6, 0x60, 1000, 3300); TWL6025_ADJUSTABLE_LDO(LDOLN, 0x64, 1000, 3300); TWL6025_ADJUSTABLE_LDO(LDOUSB, 0x70, 1000, 3300); -TWL4030_FIXED_LDO(VINTANA1, 0x3f, 1500, 11, 100, 0x08); +TWL4030_FIXED_LDO(VINTANA2, 0x3f, 1500, 11, 100, 0x08); TWL4030_FIXED_LDO(VINTDIG, 0x47, 1500, 13, 100, 0x08); TWL4030_FIXED_LDO(VUSB1V5, 0x71, 1500, 17, 100, 0x08); TWL4030_FIXED_LDO(VUSB1V8, 0x74, 1800, 18, 100, 0x08); @@ -1030,6 +1048,7 @@ TWL6030_FIXED_LDO(VDAC, 0x64, 1800, 0); TWL6030_FIXED_LDO(VUSB, 0x70, 3300, 0); TWL6030_FIXED_LDO(V1V8, 0x16, 1800, 0); TWL6030_FIXED_LDO(V2V1, 0x1c, 2100, 0); +TWL6030_FIXED_RESOURCE(CLK32KG, 0x8C, 0); TWL6025_ADJUSTABLE_SMPS(SMPS3, 0x34); TWL6025_ADJUSTABLE_SMPS(SMPS4, 0x10); TWL6025_ADJUSTABLE_SMPS(VIO, 0x16); @@ -1098,7 +1117,7 @@ static const struct of_device_id twl_of_match[] __devinitconst = { TWL6025_OF_MATCH("ti,twl6025-ldo6", LDO6), TWL6025_OF_MATCH("ti,twl6025-ldoln", LDOLN), TWL6025_OF_MATCH("ti,twl6025-ldousb", LDOUSB), - TWLFIXED_OF_MATCH("ti,twl4030-vintana1", VINTANA1), + TWLFIXED_OF_MATCH("ti,twl4030-vintana2", VINTANA2), TWLFIXED_OF_MATCH("ti,twl4030-vintdig", VINTDIG), TWLFIXED_OF_MATCH("ti,twl4030-vusb1v5", VUSB1V5), TWLFIXED_OF_MATCH("ti,twl4030-vusb1v8", VUSB1V8), @@ -1120,7 +1139,6 @@ static int __devinit twlreg_probe(struct platform_device *pdev) { int i, id; struct twlreg_info *info; - const struct twlreg_info *template; struct regulator_init_data *initdata; struct regulation_constraints *c; struct regulator_dev *rdev; @@ -1130,17 +1148,17 @@ static int __devinit twlreg_probe(struct platform_device *pdev) match = of_match_device(twl_of_match, &pdev->dev); if (match) { - template = match->data; - id = template->desc.id; + info = match->data; + id = info->desc.id; initdata = of_get_regulator_init_data(&pdev->dev, pdev->dev.of_node); drvdata = NULL; } else { id = pdev->id; initdata = pdev->dev.platform_data; - for (i = 0, template = NULL; i < ARRAY_SIZE(twl_of_match); i++) { - template = twl_of_match[i].data; - if (template && template->desc.id == id) + for (i = 0, info = NULL; i < ARRAY_SIZE(twl_of_match); i++) { + info = twl_of_match[i].data; + if (info && info->desc.id == id) break; } if (i == ARRAY_SIZE(twl_of_match)) @@ -1151,16 +1169,12 @@ static int __devinit twlreg_probe(struct platform_device *pdev) return -EINVAL; } - if (!template) + if (!info) return -ENODEV; if (!initdata) return -EINVAL; - info = kmemdup(template, sizeof (*info), GFP_KERNEL); - if (!info) - return -ENOMEM; - if (drvdata) { /* copy the driver data into regulator data */ info->features = drvdata->features; @@ -1221,7 +1235,6 @@ static int __devinit twlreg_probe(struct platform_device *pdev) if (IS_ERR(rdev)) { dev_err(&pdev->dev, "can't register %s, %ld\n", info->desc.name, PTR_ERR(rdev)); - kfree(info); return PTR_ERR(rdev); } platform_set_drvdata(pdev, rdev); @@ -1243,11 +1256,7 @@ static int __devinit twlreg_probe(struct platform_device *pdev) static int __devexit twlreg_remove(struct platform_device *pdev) { - struct regulator_dev *rdev = platform_get_drvdata(pdev); - struct twlreg_info *info = rdev->reg_data; - - regulator_unregister(rdev); - kfree(info); + regulator_unregister(platform_get_drvdata(pdev)); return 0; } diff --git a/trunk/drivers/regulator/wm831x-dcdc.c b/trunk/drivers/regulator/wm831x-dcdc.c index 90cbcc683704..7413885be01b 100644 --- a/trunk/drivers/regulator/wm831x-dcdc.c +++ b/trunk/drivers/regulator/wm831x-dcdc.c @@ -339,15 +339,16 @@ static int wm831x_buckv_set_current_limit(struct regulator_dev *rdev, u16 reg = dcdc->base + WM831X_DCDC_CONTROL_2; int i; - for (i = ARRAY_SIZE(wm831x_dcdc_ilim) - 1; i >= 0; i--) { + for (i = 0; i < ARRAY_SIZE(wm831x_dcdc_ilim); i++) { if ((min_uA <= wm831x_dcdc_ilim[i]) && (wm831x_dcdc_ilim[i] <= max_uA)) - return wm831x_set_bits(wm831x, reg, - WM831X_DC1_HC_THR_MASK, - i << WM831X_DC1_HC_THR_SHIFT); + break; } + if (i == ARRAY_SIZE(wm831x_dcdc_ilim)) + return -EINVAL; - return -EINVAL; + return wm831x_set_bits(wm831x, reg, WM831X_DC1_HC_THR_MASK, + i << WM831X_DC1_HC_THR_SHIFT); } static int wm831x_buckv_get_current_limit(struct regulator_dev *rdev) diff --git a/trunk/drivers/regulator/wm831x-ldo.c b/trunk/drivers/regulator/wm831x-ldo.c index 9af512672be1..5cb70ca1e98d 100644 --- a/trunk/drivers/regulator/wm831x-ldo.c +++ b/trunk/drivers/regulator/wm831x-ldo.c @@ -205,8 +205,6 @@ static int wm831x_gp_ldo_get_status(struct regulator_dev *rdev) /* Is it reporting under voltage? */ ret = wm831x_reg_read(wm831x, WM831X_LDO_UV_STATUS); - if (ret < 0) - return ret; if (ret & mask) return REGULATOR_STATUS_ERROR; @@ -239,8 +237,6 @@ static struct regulator_ops wm831x_gp_ldo_ops = { .set_mode = wm831x_gp_ldo_set_mode, .get_status = wm831x_gp_ldo_get_status, .get_optimum_mode = wm831x_gp_ldo_get_optimum_mode, - .get_bypass = regulator_get_bypass_regmap, - .set_bypass = regulator_set_bypass_regmap, .is_enabled = regulator_is_enabled_regmap, .enable = regulator_enable_regmap, @@ -297,8 +293,6 @@ static __devinit int wm831x_gp_ldo_probe(struct platform_device *pdev) ldo->desc.vsel_mask = WM831X_LDO1_ON_VSEL_MASK; ldo->desc.enable_reg = WM831X_LDO_ENABLE; ldo->desc.enable_mask = 1 << id; - ldo->desc.bypass_reg = ldo->base; - ldo->desc.bypass_mask = WM831X_LDO1_SWI; config.dev = pdev->dev.parent; if (pdata) @@ -475,8 +469,6 @@ static int wm831x_aldo_get_status(struct regulator_dev *rdev) /* Is it reporting under voltage? */ ret = wm831x_reg_read(wm831x, WM831X_LDO_UV_STATUS); - if (ret < 0) - return ret; if (ret & mask) return REGULATOR_STATUS_ERROR; @@ -496,8 +488,6 @@ static struct regulator_ops wm831x_aldo_ops = { .get_mode = wm831x_aldo_get_mode, .set_mode = wm831x_aldo_set_mode, .get_status = wm831x_aldo_get_status, - .set_bypass = regulator_set_bypass_regmap, - .get_bypass = regulator_get_bypass_regmap, .is_enabled = regulator_is_enabled_regmap, .enable = regulator_enable_regmap, @@ -554,8 +544,6 @@ static __devinit int wm831x_aldo_probe(struct platform_device *pdev) ldo->desc.vsel_mask = WM831X_LDO7_ON_VSEL_MASK; ldo->desc.enable_reg = WM831X_LDO_ENABLE; ldo->desc.enable_mask = 1 << id; - ldo->desc.bypass_reg = ldo->base; - ldo->desc.bypass_mask = WM831X_LDO7_SWI; config.dev = pdev->dev.parent; if (pdata) diff --git a/trunk/drivers/regulator/wm8400-regulator.c b/trunk/drivers/regulator/wm8400-regulator.c index 27c746ef0636..9035dd053611 100644 --- a/trunk/drivers/regulator/wm8400-regulator.c +++ b/trunk/drivers/regulator/wm8400-regulator.c @@ -120,8 +120,13 @@ static int wm8400_dcdc_set_mode(struct regulator_dev *dev, unsigned int mode) case REGULATOR_MODE_IDLE: /* Datasheet: standby */ + ret = wm8400_set_bits(wm8400, WM8400_DCDC1_CONTROL_1 + offset, + WM8400_DC1_ACTIVE, 0); + if (ret != 0) + return ret; return wm8400_set_bits(wm8400, WM8400_DCDC1_CONTROL_1 + offset, - WM8400_DC1_ACTIVE | WM8400_DC1_SLEEP, 0); + WM8400_DC1_SLEEP, 0); + default: return -EINVAL; } diff --git a/trunk/drivers/rpmsg/virtio_rpmsg_bus.c b/trunk/drivers/rpmsg/virtio_rpmsg_bus.c index 1859f71372e2..590cfafc7c17 100644 --- a/trunk/drivers/rpmsg/virtio_rpmsg_bus.c +++ b/trunk/drivers/rpmsg/virtio_rpmsg_bus.c @@ -1008,8 +1008,8 @@ static int rpmsg_probe(struct virtio_device *vdev) return 0; free_coherent: - dma_free_coherent(vdev->dev.parent->parent, RPMSG_TOTAL_BUF_SPACE, - bufs_va, vrp->bufs_dma); + dma_free_coherent(vdev->dev.parent, RPMSG_TOTAL_BUF_SPACE, bufs_va, + vrp->bufs_dma); vqs_del: vdev->config->del_vqs(vrp->vdev); free_vrp: @@ -1043,7 +1043,7 @@ static void __devexit rpmsg_remove(struct virtio_device *vdev) vdev->config->del_vqs(vrp->vdev); - dma_free_coherent(vdev->dev.parent->parent, RPMSG_TOTAL_BUF_SPACE, + dma_free_coherent(vdev->dev.parent, RPMSG_TOTAL_BUF_SPACE, vrp->rbufs, vrp->bufs_dma); kfree(vrp); diff --git a/trunk/drivers/rtc/interface.c b/trunk/drivers/rtc/interface.c index 9592b936b71b..eb415bd76494 100644 --- a/trunk/drivers/rtc/interface.c +++ b/trunk/drivers/rtc/interface.c @@ -582,7 +582,6 @@ enum hrtimer_restart rtc_pie_update_irq(struct hrtimer *timer) void rtc_update_irq(struct rtc_device *rtc, unsigned long num, unsigned long events) { - pm_stay_awake(rtc->dev.parent); schedule_work(&rtc->irqwork); } EXPORT_SYMBOL_GPL(rtc_update_irq); @@ -845,7 +844,6 @@ void rtc_timer_do_work(struct work_struct *work) mutex_lock(&rtc->ops_lock); again: - pm_relax(rtc->dev.parent); __rtc_read_time(rtc, &tm); now = rtc_tm_to_ktime(tm); while ((next = timerqueue_getnext(&rtc->timerqueue))) { diff --git a/trunk/drivers/rtc/rtc-at91sam9.c b/trunk/drivers/rtc/rtc-at91sam9.c index 1dd61f402b04..831868904e02 100644 --- a/trunk/drivers/rtc/rtc-at91sam9.c +++ b/trunk/drivers/rtc/rtc-at91sam9.c @@ -58,7 +58,6 @@ struct sam9_rtc { struct rtc_device *rtcdev; u32 imr; void __iomem *gpbr; - int irq; }; #define rtt_readl(rtc, field) \ @@ -293,7 +292,7 @@ static int __devinit at91_rtc_probe(struct platform_device *pdev) { struct resource *r, *r_gpbr; struct sam9_rtc *rtc; - int ret, irq; + int ret; u32 mr; r = platform_get_resource(pdev, IORESOURCE_MEM, 0); @@ -303,18 +302,10 @@ static int __devinit at91_rtc_probe(struct platform_device *pdev) return -ENODEV; } - irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(&pdev->dev, "failed to get interrupt resource\n"); - return irq; - } - rtc = kzalloc(sizeof *rtc, GFP_KERNEL); if (!rtc) return -ENOMEM; - rtc->irq = irq; - /* platform setup code should have handled this; sigh */ if (!device_can_wakeup(&pdev->dev)) device_init_wakeup(&pdev->dev, 1); @@ -354,10 +345,11 @@ static int __devinit at91_rtc_probe(struct platform_device *pdev) } /* register irq handler after we know what name we'll use */ - ret = request_irq(rtc->irq, at91_rtc_interrupt, IRQF_SHARED, + ret = request_irq(AT91_ID_SYS, at91_rtc_interrupt, + IRQF_SHARED, dev_name(&rtc->rtcdev->dev), rtc); if (ret) { - dev_dbg(&pdev->dev, "can't share IRQ %d?\n", rtc->irq); + dev_dbg(&pdev->dev, "can't share IRQ %d?\n", AT91_ID_SYS); rtc_device_unregister(rtc->rtcdev); goto fail_register; } @@ -394,7 +386,7 @@ static int __devexit at91_rtc_remove(struct platform_device *pdev) /* disable all interrupts */ rtt_writel(rtc, MR, mr & ~(AT91_RTT_ALMIEN | AT91_RTT_RTTINCIEN)); - free_irq(rtc->irq, rtc); + free_irq(AT91_ID_SYS, rtc); rtc_device_unregister(rtc->rtcdev); @@ -431,7 +423,7 @@ static int at91_rtc_suspend(struct platform_device *pdev, rtc->imr = mr & (AT91_RTT_ALMIEN | AT91_RTT_RTTINCIEN); if (rtc->imr) { if (device_may_wakeup(&pdev->dev) && (mr & AT91_RTT_ALMIEN)) { - enable_irq_wake(rtc->irq); + enable_irq_wake(AT91_ID_SYS); /* don't let RTTINC cause wakeups */ if (mr & AT91_RTT_RTTINCIEN) rtt_writel(rtc, MR, mr & ~AT91_RTT_RTTINCIEN); @@ -449,7 +441,7 @@ static int at91_rtc_resume(struct platform_device *pdev) if (rtc->imr) { if (device_may_wakeup(&pdev->dev)) - disable_irq_wake(rtc->irq); + disable_irq_wake(AT91_ID_SYS); mr = rtt_readl(rtc, MR); rtt_writel(rtc, MR, mr | rtc->imr); } diff --git a/trunk/drivers/rtc/rtc-cmos.c b/trunk/drivers/rtc/rtc-cmos.c index 4267789ca995..132333d75408 100644 --- a/trunk/drivers/rtc/rtc-cmos.c +++ b/trunk/drivers/rtc/rtc-cmos.c @@ -568,6 +568,7 @@ static irqreturn_t cmos_interrupt(int irq, void *p) hpet_mask_rtc_irq_bit(RTC_AIE); CMOS_READ(RTC_INTR_FLAGS); + pm_wakeup_event(cmos_rtc.dev, 0); } spin_unlock(&rtc_lock); diff --git a/trunk/drivers/rtc/rtc-pcf2123.c b/trunk/drivers/rtc/rtc-pcf2123.c index 13e4df63974f..836118795c0b 100644 --- a/trunk/drivers/rtc/rtc-pcf2123.c +++ b/trunk/drivers/rtc/rtc-pcf2123.c @@ -43,7 +43,6 @@ #include #include #include -#include #define DRV_VERSION "0.6" @@ -293,7 +292,6 @@ static int __devinit pcf2123_probe(struct spi_device *spi) pdata->rtc = rtc; for (i = 0; i < 16; i++) { - sysfs_attr_init(&pdata->regs[i].attr.attr); sprintf(pdata->regs[i].name, "%1x", i); pdata->regs[i].attr.attr.mode = S_IRUGO | S_IWUSR; pdata->regs[i].attr.attr.name = pdata->regs[i].name; diff --git a/trunk/drivers/rtc/rtc-rs5c348.c b/trunk/drivers/rtc/rtc-rs5c348.c index fd5c7af04ae5..77074ccd2850 100644 --- a/trunk/drivers/rtc/rtc-rs5c348.c +++ b/trunk/drivers/rtc/rtc-rs5c348.c @@ -122,12 +122,9 @@ rs5c348_rtc_read_time(struct device *dev, struct rtc_time *tm) tm->tm_min = bcd2bin(rxbuf[RS5C348_REG_MINS] & RS5C348_MINS_MASK); tm->tm_hour = bcd2bin(rxbuf[RS5C348_REG_HOURS] & RS5C348_HOURS_MASK); if (!pdata->rtc_24h) { - if (rxbuf[RS5C348_REG_HOURS] & RS5C348_BIT_PM) { - tm->tm_hour -= 20; - tm->tm_hour %= 12; + tm->tm_hour %= 12; + if (rxbuf[RS5C348_REG_HOURS] & RS5C348_BIT_PM) tm->tm_hour += 12; - } else - tm->tm_hour %= 12; } tm->tm_wday = bcd2bin(rxbuf[RS5C348_REG_WDAY] & RS5C348_WDAY_MASK); tm->tm_mday = bcd2bin(rxbuf[RS5C348_REG_DAY] & RS5C348_DAY_MASK); diff --git a/trunk/drivers/rtc/rtc-twl.c b/trunk/drivers/rtc/rtc-twl.c index 9277d945bf48..c5d06fe83bba 100644 --- a/trunk/drivers/rtc/rtc-twl.c +++ b/trunk/drivers/rtc/rtc-twl.c @@ -495,11 +495,6 @@ static int __devinit twl_rtc_probe(struct platform_device *pdev) if (ret < 0) goto out1; - /* ensure interrupts are disabled, bootloaders can be strange */ - ret = twl_rtc_write_u8(0, REG_RTC_INTERRUPTS_REG); - if (ret < 0) - dev_warn(&pdev->dev, "unable to disable interrupt\n"); - /* init cached IRQ enable bits */ ret = twl_rtc_read_u8(&rtc_irq_bits, REG_RTC_INTERRUPTS_REG); if (ret < 0) diff --git a/trunk/drivers/s390/block/Kconfig b/trunk/drivers/s390/block/Kconfig index 4a3b62326183..8e477bb1f3f6 100644 --- a/trunk/drivers/s390/block/Kconfig +++ b/trunk/drivers/s390/block/Kconfig @@ -70,21 +70,3 @@ config DASD_EER This driver provides a character device interface to the DASD extended error reporting. This is only needed if you want to use applications written for the EER facility. - -config SCM_BLOCK - def_tristate m - prompt "Support for Storage Class Memory" - depends on S390 && BLOCK && EADM_SCH && SCM_BUS - help - Block device driver for Storage Class Memory (SCM). This driver - provides a block device interface for each available SCM increment. - - To compile this driver as a module, choose M here: the - module will be called scm_block. - -config SCM_BLOCK_CLUSTER_WRITE - def_bool y - prompt "SCM force cluster writes" - depends on SCM_BLOCK - help - Force writes to Storage Class Memory (SCM) to be in done in clusters. diff --git a/trunk/drivers/s390/block/Makefile b/trunk/drivers/s390/block/Makefile index c2f4e673e031..0a89e080b389 100644 --- a/trunk/drivers/s390/block/Makefile +++ b/trunk/drivers/s390/block/Makefile @@ -17,9 +17,3 @@ obj-$(CONFIG_DASD_ECKD) += dasd_eckd_mod.o obj-$(CONFIG_DASD_FBA) += dasd_fba_mod.o obj-$(CONFIG_BLK_DEV_XPRAM) += xpram.o obj-$(CONFIG_DCSSBLK) += dcssblk.o - -scm_block-objs := scm_drv.o scm_blk.o -ifdef CONFIG_SCM_BLOCK_CLUSTER_WRITE -scm_block-objs += scm_blk_cluster.o -endif -obj-$(CONFIG_SCM_BLOCK) += scm_block.o diff --git a/trunk/drivers/s390/block/dasd.c b/trunk/drivers/s390/block/dasd.c index 0595c763dafd..15370a2c5ff0 100644 --- a/trunk/drivers/s390/block/dasd.c +++ b/trunk/drivers/s390/block/dasd.c @@ -534,11 +534,11 @@ static void dasd_change_state(struct dasd_device *device) if (rc) device->target = device->state; - /* let user-space know that the device status changed */ - kobject_uevent(&device->cdev->dev.kobj, KOBJ_CHANGE); - if (device->state == device->target) wake_up(&dasd_init_waitq); + + /* let user-space know that the device status changed */ + kobject_uevent(&device->cdev->dev.kobj, KOBJ_CHANGE); } /* @@ -2157,7 +2157,6 @@ static int _dasd_sleep_on(struct dasd_ccw_req *maincqr, int interruptible) test_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags) && (!dasd_eer_enabled(device))) { cqr->status = DASD_CQR_FAILED; - cqr->intrc = -EAGAIN; continue; } /* Don't try to start requests if device is stopped */ @@ -3271,16 +3270,6 @@ void dasd_generic_path_event(struct ccw_device *cdev, int *path_event) dasd_schedule_device_bh(device); } if (path_event[chp] & PE_PATHGROUP_ESTABLISHED) { - if (!(device->path_data.opm & eventlpm) && - !(device->path_data.tbvpm & eventlpm)) { - /* - * we can not establish a pathgroup on an - * unavailable path, so trigger a path - * verification first - */ - device->path_data.tbvpm |= eventlpm; - dasd_schedule_device_bh(device); - } DBF_DEV_EVENT(DBF_WARNING, device, "%s", "Pathgroup re-established\n"); if (device->discipline->kick_validate) diff --git a/trunk/drivers/s390/block/dasd_alias.c b/trunk/drivers/s390/block/dasd_alias.c index 6b556995bb33..157defe5e069 100644 --- a/trunk/drivers/s390/block/dasd_alias.c +++ b/trunk/drivers/s390/block/dasd_alias.c @@ -384,29 +384,6 @@ static void _remove_device_from_lcu(struct alias_lcu *lcu, group->next = NULL; }; -static int -suborder_not_supported(struct dasd_ccw_req *cqr) -{ - char *sense; - char reason; - char msg_format; - char msg_no; - - sense = dasd_get_sense(&cqr->irb); - if (!sense) - return 0; - - reason = sense[0]; - msg_format = (sense[7] & 0xF0); - msg_no = (sense[7] & 0x0F); - - /* command reject, Format 0 MSG 4 - invalid parameter */ - if ((reason == 0x80) && (msg_format == 0x00) && (msg_no == 0x04)) - return 1; - - return 0; -} - static int read_unit_address_configuration(struct dasd_device *device, struct alias_lcu *lcu) { @@ -458,8 +435,6 @@ static int read_unit_address_configuration(struct dasd_device *device, do { rc = dasd_sleep_on(cqr); - if (rc && suborder_not_supported(cqr)) - return -EOPNOTSUPP; } while (rc && (cqr->retries > 0)); if (rc) { spin_lock_irqsave(&lcu->lock, flags); @@ -546,7 +521,7 @@ static void lcu_update_work(struct work_struct *work) * processing the data */ spin_lock_irqsave(&lcu->lock, flags); - if ((rc && (rc != -EOPNOTSUPP)) || (lcu->flags & NEED_UAC_UPDATE)) { + if (rc || (lcu->flags & NEED_UAC_UPDATE)) { DBF_DEV_EVENT(DBF_WARNING, device, "could not update" " alias data in lcu (rc = %d), retry later", rc); schedule_delayed_work(&lcu->ruac_data.dwork, 30*HZ); diff --git a/trunk/drivers/s390/block/dasd_eckd.c b/trunk/drivers/s390/block/dasd_eckd.c index 108332b44d98..40a826a7295f 100644 --- a/trunk/drivers/s390/block/dasd_eckd.c +++ b/trunk/drivers/s390/block/dasd_eckd.c @@ -20,7 +20,6 @@ #include #include -#include #include #include #include @@ -32,6 +31,8 @@ #include "dasd_int.h" #include "dasd_eckd.h" +#include "../cio/chsc.h" + #ifdef PRINTK_HEADER #undef PRINTK_HEADER @@ -139,10 +140,6 @@ dasd_eckd_set_online(struct ccw_device *cdev) static const int sizes_trk0[] = { 28, 148, 84 }; #define LABEL_SIZE 140 -/* head and record addresses of count_area read in analysis ccw */ -static const int count_area_head[] = { 0, 0, 0, 0, 2 }; -static const int count_area_rec[] = { 1, 2, 3, 4, 1 }; - static inline unsigned int round_up_multiple(unsigned int no, unsigned int mult) { @@ -215,7 +212,7 @@ check_XRC (struct ccw1 *de_ccw, rc = get_sync_clock(&data->ep_sys_time); /* Ignore return code if sync clock is switched off. */ - if (rc == -EOPNOTSUPP || rc == -EACCES) + if (rc == -ENOSYS || rc == -EACCES) rc = 0; de_ccw->count = sizeof(struct DE_eckd_data); @@ -326,7 +323,7 @@ static int check_XRC_on_prefix(struct PFX_eckd_data *pfxdata, rc = get_sync_clock(&pfxdata->define_extent.ep_sys_time); /* Ignore return code if sync clock is switched off. */ - if (rc == -EOPNOTSUPP || rc == -EACCES) + if (rc == -ENOSYS || rc == -EACCES) rc = 0; return rc; } @@ -1510,8 +1507,7 @@ static struct dasd_ccw_req *dasd_eckd_build_psf_ssc(struct dasd_device *device, * call might change behaviour of DASD devices. */ static int -dasd_eckd_psf_ssc(struct dasd_device *device, int enable_pav, - unsigned long flags) +dasd_eckd_psf_ssc(struct dasd_device *device, int enable_pav) { struct dasd_ccw_req *cqr; int rc; @@ -1520,19 +1516,10 @@ dasd_eckd_psf_ssc(struct dasd_device *device, int enable_pav, if (IS_ERR(cqr)) return PTR_ERR(cqr); - /* - * set flags e.g. turn on failfast, to prevent blocking - * the calling function should handle failed requests - */ - cqr->flags |= flags; - rc = dasd_sleep_on(cqr); if (!rc) /* trigger CIO to reprobe devices */ css_schedule_reprobe(); - else if (cqr->intrc == -EAGAIN) - rc = -EAGAIN; - dasd_sfree_request(cqr, cqr->memdev); return rc; } @@ -1540,8 +1527,7 @@ dasd_eckd_psf_ssc(struct dasd_device *device, int enable_pav, /* * Valide storage server of current device. */ -static int dasd_eckd_validate_server(struct dasd_device *device, - unsigned long flags) +static void dasd_eckd_validate_server(struct dasd_device *device) { int rc; struct dasd_eckd_private *private; @@ -1550,18 +1536,17 @@ static int dasd_eckd_validate_server(struct dasd_device *device, private = (struct dasd_eckd_private *) device->private; if (private->uid.type == UA_BASE_PAV_ALIAS || private->uid.type == UA_HYPER_PAV_ALIAS) - return 0; + return; if (dasd_nopav || MACHINE_IS_VM) enable_pav = 0; else enable_pav = 1; - rc = dasd_eckd_psf_ssc(device, enable_pav, flags); + rc = dasd_eckd_psf_ssc(device, enable_pav); /* may be requested feature is not available on server, * therefore just report error and go ahead */ DBF_EVENT_DEVID(DBF_WARNING, device->cdev, "PSF-SSC for SSID %04x " "returned rc=%d", private->uid.ssid, rc); - return rc; } /* @@ -1571,13 +1556,7 @@ static void dasd_eckd_do_validate_server(struct work_struct *work) { struct dasd_device *device = container_of(work, struct dasd_device, kick_validate); - if (dasd_eckd_validate_server(device, DASD_CQR_FLAGS_FAILFAST) - == -EAGAIN) { - /* schedule worker again if failed */ - schedule_work(&device->kick_validate); - return; - } - + dasd_eckd_validate_server(device); dasd_put_device(device); } @@ -1706,7 +1685,7 @@ dasd_eckd_check_characteristics(struct dasd_device *device) if (rc) goto out_err2; - dasd_eckd_validate_server(device, 0); + dasd_eckd_validate_server(device); /* device may report different configuration data after LCU setup */ rc = dasd_eckd_read_conf(device); @@ -1943,10 +1922,7 @@ static int dasd_eckd_end_analysis(struct dasd_block *block) count_area = NULL; for (i = 0; i < 3; i++) { if (private->count_area[i].kl != 4 || - private->count_area[i].dl != dasd_eckd_cdl_reclen(i) - 4 || - private->count_area[i].cyl != 0 || - private->count_area[i].head != count_area_head[i] || - private->count_area[i].record != count_area_rec[i]) { + private->count_area[i].dl != dasd_eckd_cdl_reclen(i) - 4) { private->uses_cdl = 0; break; } @@ -1958,10 +1934,7 @@ static int dasd_eckd_end_analysis(struct dasd_block *block) for (i = 0; i < 5; i++) { if ((private->count_area[i].kl != 0) || (private->count_area[i].dl != - private->count_area[0].dl) || - private->count_area[i].cyl != 0 || - private->count_area[i].head != count_area_head[i] || - private->count_area[i].record != count_area_rec[i]) + private->count_area[0].dl)) break; } if (i == 5) @@ -3831,7 +3804,7 @@ dasd_eckd_ioctl(struct dasd_block *block, unsigned int cmd, void __user *argp) case BIODASDSYMMIO: return dasd_symm_io(device, argp); default: - return -ENOTTY; + return -ENOIOCTLCMD; } } @@ -4180,7 +4153,7 @@ static int dasd_eckd_restore_device(struct dasd_device *device) rc = dasd_alias_make_device_known_to_lcu(device); if (rc) return rc; - dasd_eckd_validate_server(device, DASD_CQR_FLAGS_FAILFAST); + dasd_eckd_validate_server(device); /* RE-Read Configuration Data */ rc = dasd_eckd_read_conf(device); diff --git a/trunk/drivers/s390/block/dasd_ioctl.c b/trunk/drivers/s390/block/dasd_ioctl.c index 8252f37d04ed..cceae70279f6 100644 --- a/trunk/drivers/s390/block/dasd_ioctl.c +++ b/trunk/drivers/s390/block/dasd_ioctl.c @@ -292,12 +292,12 @@ static int dasd_ioctl_read_profile(struct dasd_block *block, void __user *argp) #else static int dasd_ioctl_reset_profile(struct dasd_block *block) { - return -ENOTTY; + return -ENOSYS; } static int dasd_ioctl_read_profile(struct dasd_block *block, void __user *argp) { - return -ENOTTY; + return -ENOSYS; } #endif @@ -498,9 +498,12 @@ int dasd_ioctl(struct block_device *bdev, fmode_t mode, break; default: /* if the discipline has an ioctl method try it. */ - rc = -ENOTTY; - if (base->discipline->ioctl) + if (base->discipline->ioctl) { rc = base->discipline->ioctl(block, cmd, argp); + if (rc == -ENOIOCTLCMD) + rc = -EINVAL; + } else + rc = -EINVAL; } dasd_put_device(base); return rc; diff --git a/trunk/drivers/s390/block/scm_blk.c b/trunk/drivers/s390/block/scm_blk.c deleted file mode 100644 index 9978ad4433cb..000000000000 --- a/trunk/drivers/s390/block/scm_blk.c +++ /dev/null @@ -1,445 +0,0 @@ -/* - * Block driver for s390 storage class memory. - * - * Copyright IBM Corp. 2012 - * Author(s): Sebastian Ott - */ - -#define KMSG_COMPONENT "scm_block" -#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt - -#include -#include -#include -#include -#include -#include -#include -#include -#include "scm_blk.h" - -debug_info_t *scm_debug; -static int scm_major; -static DEFINE_SPINLOCK(list_lock); -static LIST_HEAD(inactive_requests); -static unsigned int nr_requests = 64; -static atomic_t nr_devices = ATOMIC_INIT(0); -module_param(nr_requests, uint, S_IRUGO); -MODULE_PARM_DESC(nr_requests, "Number of parallel requests."); - -MODULE_DESCRIPTION("Block driver for s390 storage class memory."); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("scm:scmdev*"); - -static void __scm_free_rq(struct scm_request *scmrq) -{ - struct aob_rq_header *aobrq = to_aobrq(scmrq); - - free_page((unsigned long) scmrq->aob); - free_page((unsigned long) scmrq->aidaw); - __scm_free_rq_cluster(scmrq); - kfree(aobrq); -} - -static void scm_free_rqs(void) -{ - struct list_head *iter, *safe; - struct scm_request *scmrq; - - spin_lock_irq(&list_lock); - list_for_each_safe(iter, safe, &inactive_requests) { - scmrq = list_entry(iter, struct scm_request, list); - list_del(&scmrq->list); - __scm_free_rq(scmrq); - } - spin_unlock_irq(&list_lock); -} - -static int __scm_alloc_rq(void) -{ - struct aob_rq_header *aobrq; - struct scm_request *scmrq; - - aobrq = kzalloc(sizeof(*aobrq) + sizeof(*scmrq), GFP_KERNEL); - if (!aobrq) - return -ENOMEM; - - scmrq = (void *) aobrq->data; - scmrq->aidaw = (void *) get_zeroed_page(GFP_DMA); - scmrq->aob = (void *) get_zeroed_page(GFP_DMA); - if (!scmrq->aob || !scmrq->aidaw) { - __scm_free_rq(scmrq); - return -ENOMEM; - } - - if (__scm_alloc_rq_cluster(scmrq)) { - __scm_free_rq(scmrq); - return -ENOMEM; - } - - INIT_LIST_HEAD(&scmrq->list); - spin_lock_irq(&list_lock); - list_add(&scmrq->list, &inactive_requests); - spin_unlock_irq(&list_lock); - - return 0; -} - -static int scm_alloc_rqs(unsigned int nrqs) -{ - int ret = 0; - - while (nrqs-- && !ret) - ret = __scm_alloc_rq(); - - return ret; -} - -static struct scm_request *scm_request_fetch(void) -{ - struct scm_request *scmrq = NULL; - - spin_lock(&list_lock); - if (list_empty(&inactive_requests)) - goto out; - scmrq = list_first_entry(&inactive_requests, struct scm_request, list); - list_del(&scmrq->list); -out: - spin_unlock(&list_lock); - return scmrq; -} - -static void scm_request_done(struct scm_request *scmrq) -{ - unsigned long flags; - - spin_lock_irqsave(&list_lock, flags); - list_add(&scmrq->list, &inactive_requests); - spin_unlock_irqrestore(&list_lock, flags); -} - -static int scm_open(struct block_device *blkdev, fmode_t mode) -{ - return scm_get_ref(); -} - -static int scm_release(struct gendisk *gendisk, fmode_t mode) -{ - scm_put_ref(); - return 0; -} - -static const struct block_device_operations scm_blk_devops = { - .owner = THIS_MODULE, - .open = scm_open, - .release = scm_release, -}; - -static void scm_request_prepare(struct scm_request *scmrq) -{ - struct scm_blk_dev *bdev = scmrq->bdev; - struct scm_device *scmdev = bdev->gendisk->private_data; - struct aidaw *aidaw = scmrq->aidaw; - struct msb *msb = &scmrq->aob->msb[0]; - struct req_iterator iter; - struct bio_vec *bv; - - msb->bs = MSB_BS_4K; - scmrq->aob->request.msb_count = 1; - msb->scm_addr = scmdev->address + - ((u64) blk_rq_pos(scmrq->request) << 9); - msb->oc = (rq_data_dir(scmrq->request) == READ) ? - MSB_OC_READ : MSB_OC_WRITE; - msb->flags |= MSB_FLAG_IDA; - msb->data_addr = (u64) aidaw; - - rq_for_each_segment(bv, scmrq->request, iter) { - WARN_ON(bv->bv_offset); - msb->blk_count += bv->bv_len >> 12; - aidaw->data_addr = (u64) page_address(bv->bv_page); - aidaw++; - } -} - -static inline void scm_request_init(struct scm_blk_dev *bdev, - struct scm_request *scmrq, - struct request *req) -{ - struct aob_rq_header *aobrq = to_aobrq(scmrq); - struct aob *aob = scmrq->aob; - - memset(aob, 0, sizeof(*aob)); - memset(scmrq->aidaw, 0, PAGE_SIZE); - aobrq->scmdev = bdev->scmdev; - aob->request.cmd_code = ARQB_CMD_MOVE; - aob->request.data = (u64) aobrq; - scmrq->request = req; - scmrq->bdev = bdev; - scmrq->retries = 4; - scmrq->error = 0; - scm_request_cluster_init(scmrq); -} - -static void scm_ensure_queue_restart(struct scm_blk_dev *bdev) -{ - if (atomic_read(&bdev->queued_reqs)) { - /* Queue restart is triggered by the next interrupt. */ - return; - } - blk_delay_queue(bdev->rq, SCM_QUEUE_DELAY); -} - -void scm_request_requeue(struct scm_request *scmrq) -{ - struct scm_blk_dev *bdev = scmrq->bdev; - - scm_release_cluster(scmrq); - blk_requeue_request(bdev->rq, scmrq->request); - scm_request_done(scmrq); - scm_ensure_queue_restart(bdev); -} - -void scm_request_finish(struct scm_request *scmrq) -{ - scm_release_cluster(scmrq); - blk_end_request_all(scmrq->request, scmrq->error); - scm_request_done(scmrq); -} - -static void scm_blk_request(struct request_queue *rq) -{ - struct scm_device *scmdev = rq->queuedata; - struct scm_blk_dev *bdev = dev_get_drvdata(&scmdev->dev); - struct scm_request *scmrq; - struct request *req; - int ret; - - while ((req = blk_peek_request(rq))) { - if (req->cmd_type != REQ_TYPE_FS) - continue; - - scmrq = scm_request_fetch(); - if (!scmrq) { - SCM_LOG(5, "no request"); - scm_ensure_queue_restart(bdev); - return; - } - scm_request_init(bdev, scmrq, req); - if (!scm_reserve_cluster(scmrq)) { - SCM_LOG(5, "cluster busy"); - scm_request_done(scmrq); - return; - } - if (scm_need_cluster_request(scmrq)) { - blk_start_request(req); - scm_initiate_cluster_request(scmrq); - return; - } - scm_request_prepare(scmrq); - blk_start_request(req); - - ret = scm_start_aob(scmrq->aob); - if (ret) { - SCM_LOG(5, "no subchannel"); - scm_request_requeue(scmrq); - return; - } - atomic_inc(&bdev->queued_reqs); - } -} - -static void __scmrq_log_error(struct scm_request *scmrq) -{ - struct aob *aob = scmrq->aob; - - if (scmrq->error == -ETIMEDOUT) - SCM_LOG(1, "Request timeout"); - else { - SCM_LOG(1, "Request error"); - SCM_LOG_HEX(1, &aob->response, sizeof(aob->response)); - } - if (scmrq->retries) - SCM_LOG(1, "Retry request"); - else - pr_err("An I/O operation to SCM failed with rc=%d\n", - scmrq->error); -} - -void scm_blk_irq(struct scm_device *scmdev, void *data, int error) -{ - struct scm_request *scmrq = data; - struct scm_blk_dev *bdev = scmrq->bdev; - - scmrq->error = error; - if (error) - __scmrq_log_error(scmrq); - - spin_lock(&bdev->lock); - list_add_tail(&scmrq->list, &bdev->finished_requests); - spin_unlock(&bdev->lock); - tasklet_hi_schedule(&bdev->tasklet); -} - -static void scm_blk_tasklet(struct scm_blk_dev *bdev) -{ - struct scm_request *scmrq; - unsigned long flags; - - spin_lock_irqsave(&bdev->lock, flags); - while (!list_empty(&bdev->finished_requests)) { - scmrq = list_first_entry(&bdev->finished_requests, - struct scm_request, list); - list_del(&scmrq->list); - spin_unlock_irqrestore(&bdev->lock, flags); - - if (scmrq->error && scmrq->retries-- > 0) { - if (scm_start_aob(scmrq->aob)) { - spin_lock_irqsave(&bdev->rq_lock, flags); - scm_request_requeue(scmrq); - spin_unlock_irqrestore(&bdev->rq_lock, flags); - } - /* Request restarted or requeued, handle next. */ - spin_lock_irqsave(&bdev->lock, flags); - continue; - } - - if (scm_test_cluster_request(scmrq)) { - scm_cluster_request_irq(scmrq); - spin_lock_irqsave(&bdev->lock, flags); - continue; - } - - scm_request_finish(scmrq); - atomic_dec(&bdev->queued_reqs); - spin_lock_irqsave(&bdev->lock, flags); - } - spin_unlock_irqrestore(&bdev->lock, flags); - /* Look out for more requests. */ - blk_run_queue(bdev->rq); -} - -int scm_blk_dev_setup(struct scm_blk_dev *bdev, struct scm_device *scmdev) -{ - struct request_queue *rq; - int len, ret = -ENOMEM; - unsigned int devindex, nr_max_blk; - - devindex = atomic_inc_return(&nr_devices) - 1; - /* scma..scmz + scmaa..scmzz */ - if (devindex > 701) { - ret = -ENODEV; - goto out; - } - - bdev->scmdev = scmdev; - spin_lock_init(&bdev->rq_lock); - spin_lock_init(&bdev->lock); - INIT_LIST_HEAD(&bdev->finished_requests); - atomic_set(&bdev->queued_reqs, 0); - tasklet_init(&bdev->tasklet, - (void (*)(unsigned long)) scm_blk_tasklet, - (unsigned long) bdev); - - rq = blk_init_queue(scm_blk_request, &bdev->rq_lock); - if (!rq) - goto out; - - bdev->rq = rq; - nr_max_blk = min(scmdev->nr_max_block, - (unsigned int) (PAGE_SIZE / sizeof(struct aidaw))); - - blk_queue_logical_block_size(rq, 1 << 12); - blk_queue_max_hw_sectors(rq, nr_max_blk << 3); /* 8 * 512 = blk_size */ - blk_queue_max_segments(rq, nr_max_blk); - queue_flag_set_unlocked(QUEUE_FLAG_NONROT, rq); - scm_blk_dev_cluster_setup(bdev); - - bdev->gendisk = alloc_disk(SCM_NR_PARTS); - if (!bdev->gendisk) - goto out_queue; - - rq->queuedata = scmdev; - bdev->gendisk->driverfs_dev = &scmdev->dev; - bdev->gendisk->private_data = scmdev; - bdev->gendisk->fops = &scm_blk_devops; - bdev->gendisk->queue = rq; - bdev->gendisk->major = scm_major; - bdev->gendisk->first_minor = devindex * SCM_NR_PARTS; - - len = snprintf(bdev->gendisk->disk_name, DISK_NAME_LEN, "scm"); - if (devindex > 25) { - len += snprintf(bdev->gendisk->disk_name + len, - DISK_NAME_LEN - len, "%c", - 'a' + (devindex / 26) - 1); - devindex = devindex % 26; - } - snprintf(bdev->gendisk->disk_name + len, DISK_NAME_LEN - len, "%c", - 'a' + devindex); - - /* 512 byte sectors */ - set_capacity(bdev->gendisk, scmdev->size >> 9); - add_disk(bdev->gendisk); - return 0; - -out_queue: - blk_cleanup_queue(rq); -out: - atomic_dec(&nr_devices); - return ret; -} - -void scm_blk_dev_cleanup(struct scm_blk_dev *bdev) -{ - tasklet_kill(&bdev->tasklet); - del_gendisk(bdev->gendisk); - blk_cleanup_queue(bdev->gendisk->queue); - put_disk(bdev->gendisk); -} - -static int __init scm_blk_init(void) -{ - int ret = -EINVAL; - - if (!scm_cluster_size_valid()) - goto out; - - ret = register_blkdev(0, "scm"); - if (ret < 0) - goto out; - - scm_major = ret; - if (scm_alloc_rqs(nr_requests)) - goto out_unreg; - - scm_debug = debug_register("scm_log", 16, 1, 16); - if (!scm_debug) - goto out_free; - - debug_register_view(scm_debug, &debug_hex_ascii_view); - debug_set_level(scm_debug, 2); - - ret = scm_drv_init(); - if (ret) - goto out_dbf; - - return ret; - -out_dbf: - debug_unregister(scm_debug); -out_free: - scm_free_rqs(); -out_unreg: - unregister_blkdev(scm_major, "scm"); -out: - return ret; -} -module_init(scm_blk_init); - -static void __exit scm_blk_cleanup(void) -{ - scm_drv_cleanup(); - debug_unregister(scm_debug); - scm_free_rqs(); - unregister_blkdev(scm_major, "scm"); -} -module_exit(scm_blk_cleanup); diff --git a/trunk/drivers/s390/block/scm_blk.h b/trunk/drivers/s390/block/scm_blk.h deleted file mode 100644 index 7ac6bad919ef..000000000000 --- a/trunk/drivers/s390/block/scm_blk.h +++ /dev/null @@ -1,117 +0,0 @@ -#ifndef SCM_BLK_H -#define SCM_BLK_H - -#include -#include -#include -#include -#include - -#include -#include - -#define SCM_NR_PARTS 8 -#define SCM_QUEUE_DELAY 5 - -struct scm_blk_dev { - struct tasklet_struct tasklet; - struct request_queue *rq; - struct gendisk *gendisk; - struct scm_device *scmdev; - spinlock_t rq_lock; /* guard the request queue */ - spinlock_t lock; /* guard the rest of the blockdev */ - atomic_t queued_reqs; - struct list_head finished_requests; -#ifdef CONFIG_SCM_BLOCK_CLUSTER_WRITE - struct list_head cluster_list; -#endif -}; - -struct scm_request { - struct scm_blk_dev *bdev; - struct request *request; - struct aidaw *aidaw; - struct aob *aob; - struct list_head list; - u8 retries; - int error; -#ifdef CONFIG_SCM_BLOCK_CLUSTER_WRITE - struct { - enum {CLUSTER_NONE, CLUSTER_READ, CLUSTER_WRITE} state; - struct list_head list; - void **buf; - } cluster; -#endif -}; - -#define to_aobrq(rq) container_of((void *) rq, struct aob_rq_header, data) - -int scm_blk_dev_setup(struct scm_blk_dev *, struct scm_device *); -void scm_blk_dev_cleanup(struct scm_blk_dev *); -void scm_blk_irq(struct scm_device *, void *, int); - -void scm_request_finish(struct scm_request *); -void scm_request_requeue(struct scm_request *); - -int scm_drv_init(void); -void scm_drv_cleanup(void); - -#ifdef CONFIG_SCM_BLOCK_CLUSTER_WRITE -void __scm_free_rq_cluster(struct scm_request *); -int __scm_alloc_rq_cluster(struct scm_request *); -void scm_request_cluster_init(struct scm_request *); -bool scm_reserve_cluster(struct scm_request *); -void scm_release_cluster(struct scm_request *); -void scm_blk_dev_cluster_setup(struct scm_blk_dev *); -bool scm_need_cluster_request(struct scm_request *); -void scm_initiate_cluster_request(struct scm_request *); -void scm_cluster_request_irq(struct scm_request *); -bool scm_test_cluster_request(struct scm_request *); -bool scm_cluster_size_valid(void); -#else -#define __scm_free_rq_cluster(scmrq) {} -#define __scm_alloc_rq_cluster(scmrq) 0 -#define scm_request_cluster_init(scmrq) {} -#define scm_reserve_cluster(scmrq) true -#define scm_release_cluster(scmrq) {} -#define scm_blk_dev_cluster_setup(bdev) {} -#define scm_need_cluster_request(scmrq) false -#define scm_initiate_cluster_request(scmrq) {} -#define scm_cluster_request_irq(scmrq) {} -#define scm_test_cluster_request(scmrq) false -#define scm_cluster_size_valid() true -#endif - -extern debug_info_t *scm_debug; - -#define SCM_LOG(imp, txt) do { \ - debug_text_event(scm_debug, imp, txt); \ - } while (0) - -static inline void SCM_LOG_HEX(int level, void *data, int length) -{ - if (level > scm_debug->level) - return; - while (length > 0) { - debug_event(scm_debug, level, data, length); - length -= scm_debug->buf_size; - data += scm_debug->buf_size; - } -} - -static inline void SCM_LOG_STATE(int level, struct scm_device *scmdev) -{ - struct { - u64 address; - u8 oper_state; - u8 rank; - } __packed data = { - .address = scmdev->address, - .oper_state = scmdev->attrs.oper_state, - .rank = scmdev->attrs.rank, - }; - - SCM_LOG_HEX(level, &data, sizeof(data)); -} - -#endif /* SCM_BLK_H */ diff --git a/trunk/drivers/s390/block/scm_blk_cluster.c b/trunk/drivers/s390/block/scm_blk_cluster.c deleted file mode 100644 index f4bb61b0cea1..000000000000 --- a/trunk/drivers/s390/block/scm_blk_cluster.c +++ /dev/null @@ -1,228 +0,0 @@ -/* - * Block driver for s390 storage class memory. - * - * Copyright IBM Corp. 2012 - * Author(s): Sebastian Ott - */ - -#include -#include -#include -#include -#include -#include -#include -#include "scm_blk.h" - -static unsigned int write_cluster_size = 64; -module_param(write_cluster_size, uint, S_IRUGO); -MODULE_PARM_DESC(write_cluster_size, - "Number of pages used for contiguous writes."); - -#define CLUSTER_SIZE (write_cluster_size * PAGE_SIZE) - -void __scm_free_rq_cluster(struct scm_request *scmrq) -{ - int i; - - if (!scmrq->cluster.buf) - return; - - for (i = 0; i < 2 * write_cluster_size; i++) - free_page((unsigned long) scmrq->cluster.buf[i]); - - kfree(scmrq->cluster.buf); -} - -int __scm_alloc_rq_cluster(struct scm_request *scmrq) -{ - int i; - - scmrq->cluster.buf = kzalloc(sizeof(void *) * 2 * write_cluster_size, - GFP_KERNEL); - if (!scmrq->cluster.buf) - return -ENOMEM; - - for (i = 0; i < 2 * write_cluster_size; i++) { - scmrq->cluster.buf[i] = (void *) get_zeroed_page(GFP_DMA); - if (!scmrq->cluster.buf[i]) - return -ENOMEM; - } - INIT_LIST_HEAD(&scmrq->cluster.list); - return 0; -} - -void scm_request_cluster_init(struct scm_request *scmrq) -{ - scmrq->cluster.state = CLUSTER_NONE; -} - -static bool clusters_intersect(struct scm_request *A, struct scm_request *B) -{ - unsigned long firstA, lastA, firstB, lastB; - - firstA = ((u64) blk_rq_pos(A->request) << 9) / CLUSTER_SIZE; - lastA = (((u64) blk_rq_pos(A->request) << 9) + - blk_rq_bytes(A->request) - 1) / CLUSTER_SIZE; - - firstB = ((u64) blk_rq_pos(B->request) << 9) / CLUSTER_SIZE; - lastB = (((u64) blk_rq_pos(B->request) << 9) + - blk_rq_bytes(B->request) - 1) / CLUSTER_SIZE; - - return (firstB <= lastA && firstA <= lastB); -} - -bool scm_reserve_cluster(struct scm_request *scmrq) -{ - struct scm_blk_dev *bdev = scmrq->bdev; - struct scm_request *iter; - - if (write_cluster_size == 0) - return true; - - spin_lock(&bdev->lock); - list_for_each_entry(iter, &bdev->cluster_list, cluster.list) { - if (clusters_intersect(scmrq, iter) && - (rq_data_dir(scmrq->request) == WRITE || - rq_data_dir(iter->request) == WRITE)) { - spin_unlock(&bdev->lock); - return false; - } - } - list_add(&scmrq->cluster.list, &bdev->cluster_list); - spin_unlock(&bdev->lock); - - return true; -} - -void scm_release_cluster(struct scm_request *scmrq) -{ - struct scm_blk_dev *bdev = scmrq->bdev; - unsigned long flags; - - if (write_cluster_size == 0) - return; - - spin_lock_irqsave(&bdev->lock, flags); - list_del(&scmrq->cluster.list); - spin_unlock_irqrestore(&bdev->lock, flags); -} - -void scm_blk_dev_cluster_setup(struct scm_blk_dev *bdev) -{ - INIT_LIST_HEAD(&bdev->cluster_list); - blk_queue_io_opt(bdev->rq, CLUSTER_SIZE); -} - -static void scm_prepare_cluster_request(struct scm_request *scmrq) -{ - struct scm_blk_dev *bdev = scmrq->bdev; - struct scm_device *scmdev = bdev->gendisk->private_data; - struct request *req = scmrq->request; - struct aidaw *aidaw = scmrq->aidaw; - struct msb *msb = &scmrq->aob->msb[0]; - struct req_iterator iter; - struct bio_vec *bv; - int i = 0; - u64 addr; - - switch (scmrq->cluster.state) { - case CLUSTER_NONE: - scmrq->cluster.state = CLUSTER_READ; - /* fall through */ - case CLUSTER_READ: - scmrq->aob->request.msb_count = 1; - msb->bs = MSB_BS_4K; - msb->oc = MSB_OC_READ; - msb->flags = MSB_FLAG_IDA; - msb->data_addr = (u64) aidaw; - msb->blk_count = write_cluster_size; - - addr = scmdev->address + ((u64) blk_rq_pos(req) << 9); - msb->scm_addr = round_down(addr, CLUSTER_SIZE); - - if (msb->scm_addr != - round_down(addr + (u64) blk_rq_bytes(req) - 1, - CLUSTER_SIZE)) - msb->blk_count = 2 * write_cluster_size; - - for (i = 0; i < msb->blk_count; i++) { - aidaw->data_addr = (u64) scmrq->cluster.buf[i]; - aidaw++; - } - - break; - case CLUSTER_WRITE: - msb->oc = MSB_OC_WRITE; - - for (addr = msb->scm_addr; - addr < scmdev->address + ((u64) blk_rq_pos(req) << 9); - addr += PAGE_SIZE) { - aidaw->data_addr = (u64) scmrq->cluster.buf[i]; - aidaw++; - i++; - } - rq_for_each_segment(bv, req, iter) { - aidaw->data_addr = (u64) page_address(bv->bv_page); - aidaw++; - i++; - } - for (; i < msb->blk_count; i++) { - aidaw->data_addr = (u64) scmrq->cluster.buf[i]; - aidaw++; - } - break; - } -} - -bool scm_need_cluster_request(struct scm_request *scmrq) -{ - if (rq_data_dir(scmrq->request) == READ) - return false; - - return blk_rq_bytes(scmrq->request) < CLUSTER_SIZE; -} - -/* Called with queue lock held. */ -void scm_initiate_cluster_request(struct scm_request *scmrq) -{ - scm_prepare_cluster_request(scmrq); - if (scm_start_aob(scmrq->aob)) - scm_request_requeue(scmrq); -} - -bool scm_test_cluster_request(struct scm_request *scmrq) -{ - return scmrq->cluster.state != CLUSTER_NONE; -} - -void scm_cluster_request_irq(struct scm_request *scmrq) -{ - struct scm_blk_dev *bdev = scmrq->bdev; - unsigned long flags; - - switch (scmrq->cluster.state) { - case CLUSTER_NONE: - BUG(); - break; - case CLUSTER_READ: - if (scmrq->error) { - scm_request_finish(scmrq); - break; - } - scmrq->cluster.state = CLUSTER_WRITE; - spin_lock_irqsave(&bdev->rq_lock, flags); - scm_initiate_cluster_request(scmrq); - spin_unlock_irqrestore(&bdev->rq_lock, flags); - break; - case CLUSTER_WRITE: - scm_request_finish(scmrq); - break; - } -} - -bool scm_cluster_size_valid(void) -{ - return write_cluster_size == 0 || write_cluster_size == 32 || - write_cluster_size == 64 || write_cluster_size == 128; -} diff --git a/trunk/drivers/s390/block/scm_drv.c b/trunk/drivers/s390/block/scm_drv.c deleted file mode 100644 index 9fa0a908607b..000000000000 --- a/trunk/drivers/s390/block/scm_drv.c +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Device driver for s390 storage class memory. - * - * Copyright IBM Corp. 2012 - * Author(s): Sebastian Ott - */ - -#define KMSG_COMPONENT "scm_block" -#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt - -#include -#include -#include -#include "scm_blk.h" - -static void notify(struct scm_device *scmdev) -{ - pr_info("%lu: The capabilities of the SCM increment changed\n", - (unsigned long) scmdev->address); - SCM_LOG(2, "State changed"); - SCM_LOG_STATE(2, scmdev); -} - -static int scm_probe(struct scm_device *scmdev) -{ - struct scm_blk_dev *bdev; - int ret; - - SCM_LOG(2, "probe"); - SCM_LOG_STATE(2, scmdev); - - if (scmdev->attrs.oper_state != OP_STATE_GOOD) - return -EINVAL; - - bdev = kzalloc(sizeof(*bdev), GFP_KERNEL); - if (!bdev) - return -ENOMEM; - - dev_set_drvdata(&scmdev->dev, bdev); - ret = scm_blk_dev_setup(bdev, scmdev); - if (ret) { - dev_set_drvdata(&scmdev->dev, NULL); - kfree(bdev); - goto out; - } - -out: - return ret; -} - -static int scm_remove(struct scm_device *scmdev) -{ - struct scm_blk_dev *bdev = dev_get_drvdata(&scmdev->dev); - - scm_blk_dev_cleanup(bdev); - dev_set_drvdata(&scmdev->dev, NULL); - kfree(bdev); - - return 0; -} - -static struct scm_driver scm_drv = { - .drv = { - .name = "scm_block", - .owner = THIS_MODULE, - }, - .notify = notify, - .probe = scm_probe, - .remove = scm_remove, - .handler = scm_blk_irq, -}; - -int __init scm_drv_init(void) -{ - return scm_driver_register(&scm_drv); -} - -void scm_drv_cleanup(void) -{ - scm_driver_unregister(&scm_drv); -} diff --git a/trunk/drivers/s390/char/con3215.c b/trunk/drivers/s390/char/con3215.c index 9ffb6d5f17aa..6c0116d48c74 100644 --- a/trunk/drivers/s390/char/con3215.c +++ b/trunk/drivers/s390/char/con3215.c @@ -716,17 +716,10 @@ static int raw3215_probe (struct ccw_device *cdev) static void raw3215_remove (struct ccw_device *cdev) { struct raw3215_info *raw; - unsigned int line; ccw_device_set_offline(cdev); raw = dev_get_drvdata(&cdev->dev); if (raw) { - spin_lock(&raw3215_device_lock); - for (line = 0; line < NR_3215; line++) - if (raw3215[line] == raw) - break; - raw3215[line] = NULL; - spin_unlock(&raw3215_device_lock); dev_set_drvdata(&cdev->dev, NULL); raw3215_free_info(raw); } @@ -942,19 +935,6 @@ static int __init con3215_init(void) console_initcall(con3215_init); #endif -static int tty3215_install(struct tty_driver *driver, struct tty_struct *tty) -{ - struct raw3215_info *raw; - - raw = raw3215[tty->index]; - if (raw == NULL) - return -ENODEV; - - tty->driver_data = raw; - - return tty_port_install(&raw->port, driver, tty); -} - /* * tty3215_open * @@ -962,9 +942,14 @@ static int tty3215_install(struct tty_driver *driver, struct tty_struct *tty) */ static int tty3215_open(struct tty_struct *tty, struct file * filp) { - struct raw3215_info *raw = tty->driver_data; + struct raw3215_info *raw; int retval; + raw = raw3215[tty->index]; + if (raw == NULL) + return -ENODEV; + + tty->driver_data = raw; tty_port_tty_set(&raw->port, tty); tty->low_latency = 0; /* don't use bottom half for pushing chars */ @@ -1125,7 +1110,6 @@ static void tty3215_start(struct tty_struct *tty) } static const struct tty_operations tty3215_ops = { - .install = tty3215_install, .open = tty3215_open, .close = tty3215_close, .write = tty3215_write, diff --git a/trunk/drivers/s390/char/con3270.c b/trunk/drivers/s390/char/con3270.c index 699fd3e363df..bb07577e8fd4 100644 --- a/trunk/drivers/s390/char/con3270.c +++ b/trunk/drivers/s390/char/con3270.c @@ -35,6 +35,7 @@ static struct raw3270_fn con3270_fn; */ struct con3270 { struct raw3270_view view; + spinlock_t lock; struct list_head freemem; /* list of free memory for strings. */ /* Output stuff. */ diff --git a/trunk/drivers/s390/char/monreader.c b/trunk/drivers/s390/char/monreader.c index f4ff515db251..5b8b8592d311 100644 --- a/trunk/drivers/s390/char/monreader.c +++ b/trunk/drivers/s390/char/monreader.c @@ -571,11 +571,8 @@ static int __init mon_init(void) if (rc) goto out_iucv; monreader_device = kzalloc(sizeof(struct device), GFP_KERNEL); - if (!monreader_device) { - rc = -ENOMEM; + if (!monreader_device) goto out_driver; - } - dev_set_name(monreader_device, "monreader-dev"); monreader_device->bus = &iucv_bus; monreader_device->parent = iucv_root; diff --git a/trunk/drivers/s390/char/sclp.c b/trunk/drivers/s390/char/sclp.c index 4fa21f7e2308..3fcc000efc53 100644 --- a/trunk/drivers/s390/char/sclp.c +++ b/trunk/drivers/s390/char/sclp.c @@ -334,7 +334,7 @@ sclp_dispatch_evbufs(struct sccb_header *sccb) reg->receiver_fn(evbuf); spin_lock_irqsave(&sclp_lock, flags); } else if (reg == NULL) - rc = -EOPNOTSUPP; + rc = -ENOSYS; } spin_unlock_irqrestore(&sclp_lock, flags); return rc; diff --git a/trunk/drivers/s390/char/sclp_rw.c b/trunk/drivers/s390/char/sclp_rw.c index 3b13d58fe87b..4be63be73445 100644 --- a/trunk/drivers/s390/char/sclp_rw.c +++ b/trunk/drivers/s390/char/sclp_rw.c @@ -463,7 +463,7 @@ sclp_emit_buffer(struct sclp_buffer *buffer, /* Use write priority message */ sccb->msg_buf.header.type = EVTYP_PMSGCMD; else - return -EOPNOTSUPP; + return -ENOSYS; buffer->request.command = SCLP_CMDW_WRITE_EVENT_DATA; buffer->request.status = SCLP_REQ_FILLED; buffer->request.callback = sclp_writedata_callback; diff --git a/trunk/drivers/s390/char/sclp_sdias.c b/trunk/drivers/s390/char/sclp_sdias.c index b1032931a1c4..6a6f76bf6e3d 100644 --- a/trunk/drivers/s390/char/sclp_sdias.c +++ b/trunk/drivers/s390/char/sclp_sdias.c @@ -242,13 +242,11 @@ int sclp_sdias_copy(void *dest, int start_blk, int nr_blks) switch (sdias_evbuf.event_status) { case EVSTATE_ALL_STORED: TRACE("all stored\n"); - break; case EVSTATE_PART_STORED: TRACE("part stored: %i\n", sdias_evbuf.blk_cnt); break; case EVSTATE_NO_DATA: TRACE("no data\n"); - /* fall through */ default: pr_err("Error from SCLP while copying hsa. " "Event status = %x\n", diff --git a/trunk/drivers/s390/char/sclp_tty.c b/trunk/drivers/s390/char/sclp_tty.c index 30ec09e3d037..0792c85baafe 100644 --- a/trunk/drivers/s390/char/sclp_tty.c +++ b/trunk/drivers/s390/char/sclp_tty.c @@ -567,7 +567,6 @@ sclp_tty_init(void) driver->init_termios.c_lflag = ISIG | ECHO; driver->flags = TTY_DRIVER_REAL_RAW; tty_set_operations(driver, &sclp_ops); - tty_port_link_device(&sclp_port, driver, 0); rc = tty_register_driver(driver); if (rc) { put_tty_driver(driver); diff --git a/trunk/drivers/s390/char/sclp_vt220.c b/trunk/drivers/s390/char/sclp_vt220.c index 7e60f3d2f3f9..edfc0fd73dc6 100644 --- a/trunk/drivers/s390/char/sclp_vt220.c +++ b/trunk/drivers/s390/char/sclp_vt220.c @@ -691,7 +691,6 @@ static int __init sclp_vt220_tty_init(void) driver->init_termios = tty_std_termios; driver->flags = TTY_DRIVER_REAL_RAW; tty_set_operations(driver, &sclp_vt220_ops); - tty_port_link_device(&sclp_vt220_port, driver, 0); rc = tty_register_driver(driver); if (rc) diff --git a/trunk/drivers/s390/char/tape.h b/trunk/drivers/s390/char/tape.h index ea664dd4f56d..c06be6cc2fc3 100644 --- a/trunk/drivers/s390/char/tape.h +++ b/trunk/drivers/s390/char/tape.h @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include diff --git a/trunk/drivers/s390/char/tape_std.h b/trunk/drivers/s390/char/tape_std.h index 8c760c036832..c5816ad9ed7d 100644 --- a/trunk/drivers/s390/char/tape_std.h +++ b/trunk/drivers/s390/char/tape_std.h @@ -100,7 +100,11 @@ struct tape_request *tape_std_read_block(struct tape_device *, size_t); void tape_std_read_backward(struct tape_device *device, struct tape_request *request); struct tape_request *tape_std_write_block(struct tape_device *, size_t); +struct tape_request *tape_std_bread(struct tape_device *, struct request *); +void tape_std_free_bread(struct tape_request *); void tape_std_check_locate(struct tape_device *, struct tape_request *); +struct tape_request *tape_std_bwrite(struct request *, + struct tape_device *, int); /* Some non-mtop commands. */ int tape_std_assign(struct tape_device *); diff --git a/trunk/drivers/s390/char/tty3270.c b/trunk/drivers/s390/char/tty3270.c index 482ee028f842..1928f3458d10 100644 --- a/trunk/drivers/s390/char/tty3270.c +++ b/trunk/drivers/s390/char/tty3270.c @@ -842,14 +842,17 @@ static struct raw3270_fn tty3270_fn = { }; /* - * This routine is called whenever a 3270 tty is opened first time. + * This routine is called whenever a 3270 tty is opened. */ -static int tty3270_install(struct tty_driver *driver, struct tty_struct *tty) +static int +tty3270_open(struct tty_struct *tty, struct file * filp) { struct raw3270_view *view; struct tty3270 *tp; int i, rc; + if (tty->count > 1) + return 0; /* Check if the tty3270 is already there. */ view = raw3270_find_view(&tty3270_fn, tty->index + RAW3270_FIRSTMINOR); @@ -862,7 +865,7 @@ static int tty3270_install(struct tty_driver *driver, struct tty_struct *tty) /* why to reassign? */ tty_port_tty_set(&tp->port, tty); tp->inattr = TF_INPUT; - return tty_port_install(&tp->port, driver, tty); + return 0; } if (tty3270_max_index < tty->index + 1) tty3270_max_index = tty->index + 1; @@ -892,6 +895,7 @@ static int tty3270_install(struct tty_driver *driver, struct tty_struct *tty) tty_port_tty_set(&tp->port, tty); tty->low_latency = 0; + tty->driver_data = tp; tty->winsize.ws_row = tp->view.rows - 2; tty->winsize.ws_col = tp->view.cols; @@ -911,15 +915,6 @@ static int tty3270_install(struct tty_driver *driver, struct tty_struct *tty) kbd_ascebc(tp->kbd, tp->view.ascebc); raw3270_activate_view(&tp->view); - - rc = tty_port_install(&tp->port, driver, tty); - if (rc) { - raw3270_put_view(&tp->view); - return rc; - } - - tty->driver_data = tp; - return 0; } @@ -937,15 +932,8 @@ tty3270_close(struct tty_struct *tty, struct file * filp) if (tp) { tty->driver_data = NULL; tty_port_tty_set(&tp->port, NULL); - } -} - -static void tty3270_cleanup(struct tty_struct *tty) -{ - struct tty3270 *tp = tty->driver_data; - - if (tp) raw3270_put_view(&tp->view); + } } /* @@ -1749,8 +1737,7 @@ static long tty3270_compat_ioctl(struct tty_struct *tty, #endif static const struct tty_operations tty3270_ops = { - .install = tty3270_install, - .cleanup = tty3270_cleanup, + .open = tty3270_open, .close = tty3270_close, .write = tty3270_write, .put_char = tty3270_put_char, @@ -1794,7 +1781,7 @@ static int __init tty3270_init(void) driver->type = TTY_DRIVER_TYPE_SYSTEM; driver->subtype = SYSTEM_TYPE_TTY; driver->init_termios = tty_std_termios; - driver->flags = TTY_DRIVER_RESET_TERMIOS; + driver->flags = TTY_DRIVER_RESET_TERMIOS | TTY_DRIVER_DYNAMIC_DEV; tty_set_operations(driver, &tty3270_ops); ret = tty_register_driver(driver); if (ret) { @@ -1813,7 +1800,6 @@ tty3270_exit(void) driver = tty3270_driver; tty3270_driver = NULL; tty_unregister_driver(driver); - put_tty_driver(driver); tty3270_del_views(); } diff --git a/trunk/drivers/s390/char/vmlogrdr.c b/trunk/drivers/s390/char/vmlogrdr.c index 9b3a24e8d3a0..c131bc40f962 100644 --- a/trunk/drivers/s390/char/vmlogrdr.c +++ b/trunk/drivers/s390/char/vmlogrdr.c @@ -321,7 +321,7 @@ static int vmlogrdr_open (struct inode *inode, struct file *filp) * only allow for blocking reads to be open */ if (filp->f_flags & O_NONBLOCK) - return -EOPNOTSUPP; + return -ENOSYS; /* Besure this device hasn't already been opened */ spin_lock_bh(&logptr->priv_lock); diff --git a/trunk/drivers/s390/cio/Makefile b/trunk/drivers/s390/cio/Makefile index 8c4a386e97f6..e1b700a19648 100644 --- a/trunk/drivers/s390/cio/Makefile +++ b/trunk/drivers/s390/cio/Makefile @@ -8,8 +8,6 @@ ccw_device-objs += device.o device_fsm.o device_ops.o ccw_device-objs += device_id.o device_pgid.o device_status.o obj-y += ccw_device.o cmf.o obj-$(CONFIG_CHSC_SCH) += chsc_sch.o -obj-$(CONFIG_EADM_SCH) += eadm_sch.o -obj-$(CONFIG_SCM_BUS) += scm.o obj-$(CONFIG_CCWGROUP) += ccwgroup.o qdio-objs := qdio_main.o qdio_thinint.o qdio_debug.o qdio_setup.o diff --git a/trunk/drivers/s390/cio/chsc.c b/trunk/drivers/s390/cio/chsc.c index 4d51a7c4eb8b..cfe0c087fe5c 100644 --- a/trunk/drivers/s390/cio/chsc.c +++ b/trunk/drivers/s390/cio/chsc.c @@ -52,11 +52,6 @@ int chsc_error_from_response(int response) return -EINVAL; case 0x0004: return -EOPNOTSUPP; - case 0x000b: - return -EBUSY; - case 0x0100: - case 0x0102: - return -ENOMEM; default: return -EIO; } @@ -398,20 +393,6 @@ static void chsc_process_sei_chp_config(struct chsc_sei_area *sei_area) } } -static void chsc_process_sei_scm_change(struct chsc_sei_area *sei_area) -{ - int ret; - - CIO_CRW_EVENT(4, "chsc: scm change notification\n"); - if (sei_area->rs != 7) - return; - - ret = scm_update_information(); - if (ret) - CIO_CRW_EVENT(0, "chsc: updating change notification" - " failed (rc=%d).\n", ret); -} - static void chsc_process_sei(struct chsc_sei_area *sei_area) { /* Check if we might have lost some information. */ @@ -433,9 +414,6 @@ static void chsc_process_sei(struct chsc_sei_area *sei_area) case 8: /* channel-path-configuration notification */ chsc_process_sei_chp_config(sei_area); break; - case 12: /* scm change notification */ - chsc_process_sei_scm_change(sei_area); - break; default: /* other stuff */ CIO_CRW_EVENT(4, "chsc: unhandled sei content code %d\n", sei_area->cc); @@ -1069,33 +1047,3 @@ int chsc_siosl(struct subchannel_id schid) return rc; } EXPORT_SYMBOL_GPL(chsc_siosl); - -/** - * chsc_scm_info() - store SCM information (SSI) - * @scm_area: request and response block for SSI - * @token: continuation token - * - * Returns 0 on success. - */ -int chsc_scm_info(struct chsc_scm_info *scm_area, u64 token) -{ - int ccode, ret; - - memset(scm_area, 0, sizeof(*scm_area)); - scm_area->request.length = 0x0020; - scm_area->request.code = 0x004C; - scm_area->reqtok = token; - - ccode = chsc(scm_area); - if (ccode > 0) { - ret = (ccode == 3) ? -ENODEV : -EBUSY; - goto out; - } - ret = chsc_error_from_response(scm_area->response.code); - if (ret != 0) - CIO_MSG_EVENT(2, "chsc: scm info failed (rc=%04x)\n", - scm_area->response.code); -out: - return ret; -} -EXPORT_SYMBOL_GPL(chsc_scm_info); diff --git a/trunk/drivers/s390/cio/chsc.h b/trunk/drivers/s390/cio/chsc.h index 662dab4b93e6..3f15b2aaeaea 100644 --- a/trunk/drivers/s390/cio/chsc.h +++ b/trunk/drivers/s390/cio/chsc.h @@ -3,7 +3,6 @@ #include #include -#include #include #include #include @@ -119,46 +118,4 @@ int chsc_error_from_response(int response); int chsc_siosl(struct subchannel_id schid); -/* Functions and definitions to query storage-class memory. */ -struct sale { - u64 sa; - u32 p:4; - u32 op_state:4; - u32 data_state:4; - u32 rank:4; - u32 r:1; - u32:7; - u32 rid:8; - u32:32; -} __packed; - -struct chsc_scm_info { - struct chsc_header request; - u32:32; - u64 reqtok; - u32 reserved1[4]; - struct chsc_header response; - u64:56; - u8 rq; - u32 mbc; - u64 msa; - u16 is; - u16 mmc; - u32 mci; - u64 nr_scm_ini; - u64 nr_scm_unini; - u32 reserved2[10]; - u64 restok; - struct sale scmal[248]; -} __packed; - -int chsc_scm_info(struct chsc_scm_info *scm_area, u64 token); - -#ifdef CONFIG_SCM_BUS -int scm_update_information(void); -#else /* CONFIG_SCM_BUS */ -#define scm_update_information() 0 -#endif /* CONFIG_SCM_BUS */ - - #endif diff --git a/trunk/drivers/s390/cio/cio.c b/trunk/drivers/s390/cio/cio.c index 8e927b9f285f..33d1ef703593 100644 --- a/trunk/drivers/s390/cio/cio.c +++ b/trunk/drivers/s390/cio/cio.c @@ -1029,7 +1029,7 @@ extern void do_reipl_asm(__u32 schid); /* Make sure all subchannels are quiet before we re-ipl an lpar. */ void reipl_ccw_dev(struct ccw_dev_id *devid) { - struct subchannel_id uninitialized_var(schid); + struct subchannel_id schid; s390_reset_system(NULL, NULL); if (reipl_find_schid(devid, &schid) != 0) diff --git a/trunk/drivers/s390/cio/css.c b/trunk/drivers/s390/cio/css.c index b4d572f65f07..21908e67bf67 100644 --- a/trunk/drivers/s390/cio/css.c +++ b/trunk/drivers/s390/cio/css.c @@ -445,7 +445,6 @@ void css_sched_sch_todo(struct subchannel *sch, enum sch_todo todo) put_device(&sch->dev); } } -EXPORT_SYMBOL_GPL(css_sched_sch_todo); static void css_sch_todo(struct work_struct *work) { diff --git a/trunk/drivers/s390/cio/device.c b/trunk/drivers/s390/cio/device.c index fc916f5d7314..ed25c8740a9c 100644 --- a/trunk/drivers/s390/cio/device.c +++ b/trunk/drivers/s390/cio/device.c @@ -1426,8 +1426,6 @@ static enum io_sch_action sch_get_action(struct subchannel *sch) return IO_SCH_REPROBE; if (cdev->online) return IO_SCH_VERIFY; - if (cdev->private->state == DEV_STATE_NOT_OPER) - return IO_SCH_UNREG_ATTACH; return IO_SCH_NOP; } @@ -1521,14 +1519,11 @@ static int io_subchannel_sch_event(struct subchannel *sch, int process) goto out; break; case IO_SCH_UNREG_ATTACH: - spin_lock_irqsave(sch->lock, flags); if (cdev->private->flags.resuming) { /* Device will be handled later. */ rc = 0; - goto out_unlock; + goto out; } - sch_set_cdev(sch, NULL); - spin_unlock_irqrestore(sch->lock, flags); /* Unregister ccw device. */ ccw_device_unregister(cdev); break; diff --git a/trunk/drivers/s390/cio/eadm_sch.c b/trunk/drivers/s390/cio/eadm_sch.c deleted file mode 100644 index 6c9673400464..000000000000 --- a/trunk/drivers/s390/cio/eadm_sch.c +++ /dev/null @@ -1,401 +0,0 @@ -/* - * Driver for s390 eadm subchannels - * - * Copyright IBM Corp. 2012 - * Author(s): Sebastian Ott - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include "eadm_sch.h" -#include "ioasm.h" -#include "cio.h" -#include "css.h" -#include "orb.h" - -MODULE_DESCRIPTION("driver for s390 eadm subchannels"); -MODULE_LICENSE("GPL"); - -#define EADM_TIMEOUT (5 * HZ) -static DEFINE_SPINLOCK(list_lock); -static LIST_HEAD(eadm_list); - -static debug_info_t *eadm_debug; - -#define EADM_LOG(imp, txt) do { \ - debug_text_event(eadm_debug, imp, txt); \ - } while (0) - -static void EADM_LOG_HEX(int level, void *data, int length) -{ - if (level > eadm_debug->level) - return; - while (length > 0) { - debug_event(eadm_debug, level, data, length); - length -= eadm_debug->buf_size; - data += eadm_debug->buf_size; - } -} - -static void orb_init(union orb *orb) -{ - memset(orb, 0, sizeof(union orb)); - orb->eadm.compat1 = 1; - orb->eadm.compat2 = 1; - orb->eadm.fmt = 1; - orb->eadm.x = 1; -} - -static int eadm_subchannel_start(struct subchannel *sch, struct aob *aob) -{ - union orb *orb = &get_eadm_private(sch)->orb; - int cc; - - orb_init(orb); - orb->eadm.aob = (u32)__pa(aob); - orb->eadm.intparm = (u32)(addr_t)sch; - orb->eadm.key = PAGE_DEFAULT_KEY >> 4; - - EADM_LOG(6, "start"); - EADM_LOG_HEX(6, &sch->schid, sizeof(sch->schid)); - - cc = ssch(sch->schid, orb); - switch (cc) { - case 0: - sch->schib.scsw.eadm.actl |= SCSW_ACTL_START_PEND; - break; - case 1: /* status pending */ - case 2: /* busy */ - return -EBUSY; - case 3: /* not operational */ - return -ENODEV; - } - return 0; -} - -static int eadm_subchannel_clear(struct subchannel *sch) -{ - int cc; - - cc = csch(sch->schid); - if (cc) - return -ENODEV; - - sch->schib.scsw.eadm.actl |= SCSW_ACTL_CLEAR_PEND; - return 0; -} - -static void eadm_subchannel_timeout(unsigned long data) -{ - struct subchannel *sch = (struct subchannel *) data; - - spin_lock_irq(sch->lock); - EADM_LOG(1, "timeout"); - EADM_LOG_HEX(1, &sch->schid, sizeof(sch->schid)); - if (eadm_subchannel_clear(sch)) - EADM_LOG(0, "clear failed"); - spin_unlock_irq(sch->lock); -} - -static void eadm_subchannel_set_timeout(struct subchannel *sch, int expires) -{ - struct eadm_private *private = get_eadm_private(sch); - - if (expires == 0) { - del_timer(&private->timer); - return; - } - if (timer_pending(&private->timer)) { - if (mod_timer(&private->timer, jiffies + expires)) - return; - } - private->timer.function = eadm_subchannel_timeout; - private->timer.data = (unsigned long) sch; - private->timer.expires = jiffies + expires; - add_timer(&private->timer); -} - -static void eadm_subchannel_irq(struct subchannel *sch) -{ - struct eadm_private *private = get_eadm_private(sch); - struct eadm_scsw *scsw = &sch->schib.scsw.eadm; - struct irb *irb = (struct irb *)&S390_lowcore.irb; - int error = 0; - - EADM_LOG(6, "irq"); - EADM_LOG_HEX(6, irb, sizeof(*irb)); - - kstat_cpu(smp_processor_id()).irqs[IOINT_ADM]++; - - if ((scsw->stctl & (SCSW_STCTL_ALERT_STATUS | SCSW_STCTL_STATUS_PEND)) - && scsw->eswf == 1 && irb->esw.eadm.erw.r) - error = -EIO; - - if (scsw->fctl & SCSW_FCTL_CLEAR_FUNC) - error = -ETIMEDOUT; - - eadm_subchannel_set_timeout(sch, 0); - - if (private->state != EADM_BUSY) { - EADM_LOG(1, "irq unsol"); - EADM_LOG_HEX(1, irb, sizeof(*irb)); - private->state = EADM_NOT_OPER; - css_sched_sch_todo(sch, SCH_TODO_EVAL); - return; - } - scm_irq_handler((struct aob *)(unsigned long)scsw->aob, error); - private->state = EADM_IDLE; -} - -static struct subchannel *eadm_get_idle_sch(void) -{ - struct eadm_private *private; - struct subchannel *sch; - unsigned long flags; - - spin_lock_irqsave(&list_lock, flags); - list_for_each_entry(private, &eadm_list, head) { - sch = private->sch; - spin_lock(sch->lock); - if (private->state == EADM_IDLE) { - private->state = EADM_BUSY; - list_move_tail(&private->head, &eadm_list); - spin_unlock(sch->lock); - spin_unlock_irqrestore(&list_lock, flags); - - return sch; - } - spin_unlock(sch->lock); - } - spin_unlock_irqrestore(&list_lock, flags); - - return NULL; -} - -static int eadm_start_aob(struct aob *aob) -{ - struct eadm_private *private; - struct subchannel *sch; - unsigned long flags; - int ret; - - sch = eadm_get_idle_sch(); - if (!sch) - return -EBUSY; - - spin_lock_irqsave(sch->lock, flags); - eadm_subchannel_set_timeout(sch, EADM_TIMEOUT); - ret = eadm_subchannel_start(sch, aob); - if (!ret) - goto out_unlock; - - /* Handle start subchannel failure. */ - eadm_subchannel_set_timeout(sch, 0); - private = get_eadm_private(sch); - private->state = EADM_NOT_OPER; - css_sched_sch_todo(sch, SCH_TODO_EVAL); - -out_unlock: - spin_unlock_irqrestore(sch->lock, flags); - - return ret; -} - -static int eadm_subchannel_probe(struct subchannel *sch) -{ - struct eadm_private *private; - int ret; - - private = kzalloc(sizeof(*private), GFP_KERNEL | GFP_DMA); - if (!private) - return -ENOMEM; - - INIT_LIST_HEAD(&private->head); - init_timer(&private->timer); - - spin_lock_irq(sch->lock); - set_eadm_private(sch, private); - private->state = EADM_IDLE; - private->sch = sch; - sch->isc = EADM_SCH_ISC; - ret = cio_enable_subchannel(sch, (u32)(unsigned long)sch); - if (ret) { - set_eadm_private(sch, NULL); - spin_unlock_irq(sch->lock); - kfree(private); - goto out; - } - spin_unlock_irq(sch->lock); - - spin_lock_irq(&list_lock); - list_add(&private->head, &eadm_list); - spin_unlock_irq(&list_lock); - - if (dev_get_uevent_suppress(&sch->dev)) { - dev_set_uevent_suppress(&sch->dev, 0); - kobject_uevent(&sch->dev.kobj, KOBJ_ADD); - } -out: - return ret; -} - -static void eadm_quiesce(struct subchannel *sch) -{ - int ret; - - do { - spin_lock_irq(sch->lock); - ret = cio_disable_subchannel(sch); - spin_unlock_irq(sch->lock); - } while (ret == -EBUSY); -} - -static int eadm_subchannel_remove(struct subchannel *sch) -{ - struct eadm_private *private = get_eadm_private(sch); - - spin_lock_irq(&list_lock); - list_del(&private->head); - spin_unlock_irq(&list_lock); - - eadm_quiesce(sch); - - spin_lock_irq(sch->lock); - set_eadm_private(sch, NULL); - spin_unlock_irq(sch->lock); - - kfree(private); - - return 0; -} - -static void eadm_subchannel_shutdown(struct subchannel *sch) -{ - eadm_quiesce(sch); -} - -static int eadm_subchannel_freeze(struct subchannel *sch) -{ - return cio_disable_subchannel(sch); -} - -static int eadm_subchannel_restore(struct subchannel *sch) -{ - return cio_enable_subchannel(sch, (u32)(unsigned long)sch); -} - -/** - * eadm_subchannel_sch_event - process subchannel event - * @sch: subchannel - * @process: non-zero if function is called in process context - * - * An unspecified event occurred for this subchannel. Adjust data according - * to the current operational state of the subchannel. Return zero when the - * event has been handled sufficiently or -EAGAIN when this function should - * be called again in process context. - */ -static int eadm_subchannel_sch_event(struct subchannel *sch, int process) -{ - struct eadm_private *private; - unsigned long flags; - int ret = 0; - - spin_lock_irqsave(sch->lock, flags); - if (!device_is_registered(&sch->dev)) - goto out_unlock; - - if (work_pending(&sch->todo_work)) - goto out_unlock; - - if (cio_update_schib(sch)) { - css_sched_sch_todo(sch, SCH_TODO_UNREG); - goto out_unlock; - } - private = get_eadm_private(sch); - if (private->state == EADM_NOT_OPER) - private->state = EADM_IDLE; - -out_unlock: - spin_unlock_irqrestore(sch->lock, flags); - - return ret; -} - -static struct css_device_id eadm_subchannel_ids[] = { - { .match_flags = 0x1, .type = SUBCHANNEL_TYPE_ADM, }, - { /* end of list */ }, -}; -MODULE_DEVICE_TABLE(css, eadm_subchannel_ids); - -static struct css_driver eadm_subchannel_driver = { - .drv = { - .name = "eadm_subchannel", - .owner = THIS_MODULE, - }, - .subchannel_type = eadm_subchannel_ids, - .irq = eadm_subchannel_irq, - .probe = eadm_subchannel_probe, - .remove = eadm_subchannel_remove, - .shutdown = eadm_subchannel_shutdown, - .sch_event = eadm_subchannel_sch_event, - .freeze = eadm_subchannel_freeze, - .thaw = eadm_subchannel_restore, - .restore = eadm_subchannel_restore, -}; - -static struct eadm_ops eadm_ops = { - .eadm_start = eadm_start_aob, - .owner = THIS_MODULE, -}; - -static int __init eadm_sch_init(void) -{ - int ret; - - if (!css_general_characteristics.eadm) - return -ENXIO; - - eadm_debug = debug_register("eadm_log", 16, 1, 16); - if (!eadm_debug) - return -ENOMEM; - - debug_register_view(eadm_debug, &debug_hex_ascii_view); - debug_set_level(eadm_debug, 2); - - isc_register(EADM_SCH_ISC); - ret = css_driver_register(&eadm_subchannel_driver); - if (ret) - goto cleanup; - - register_eadm_ops(&eadm_ops); - return ret; - -cleanup: - isc_unregister(EADM_SCH_ISC); - debug_unregister(eadm_debug); - return ret; -} - -static void __exit eadm_sch_exit(void) -{ - unregister_eadm_ops(&eadm_ops); - css_driver_unregister(&eadm_subchannel_driver); - isc_unregister(EADM_SCH_ISC); - debug_unregister(eadm_debug); -} -module_init(eadm_sch_init); -module_exit(eadm_sch_exit); diff --git a/trunk/drivers/s390/cio/eadm_sch.h b/trunk/drivers/s390/cio/eadm_sch.h deleted file mode 100644 index 2779be093982..000000000000 --- a/trunk/drivers/s390/cio/eadm_sch.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef EADM_SCH_H -#define EADM_SCH_H - -#include -#include -#include -#include "orb.h" - -struct eadm_private { - union orb orb; - enum {EADM_IDLE, EADM_BUSY, EADM_NOT_OPER} state; - struct timer_list timer; - struct list_head head; - struct subchannel *sch; -} __aligned(8); - -#define get_eadm_private(n) ((struct eadm_private *)dev_get_drvdata(&n->dev)) -#define set_eadm_private(n, p) (dev_set_drvdata(&n->dev, p)) - -#endif diff --git a/trunk/drivers/s390/cio/orb.h b/trunk/drivers/s390/cio/orb.h index 7a640530e7f5..45a9865c2b36 100644 --- a/trunk/drivers/s390/cio/orb.h +++ b/trunk/drivers/s390/cio/orb.h @@ -59,33 +59,9 @@ struct tm_orb { u32:32; } __packed __aligned(4); -/* - * eadm operation request block - */ -struct eadm_orb { - u32 intparm; - u32 key:4; - u32:4; - u32 compat1:1; - u32 compat2:1; - u32:21; - u32 x:1; - u32 aob; - u32 css_prio:8; - u32:8; - u32 scm_prio:8; - u32:8; - u32:29; - u32 fmt:3; - u32:32; - u32:32; - u32:32; -} __packed __aligned(4); - union orb { struct cmd_orb cmd; struct tm_orb tm; - struct eadm_orb eadm; } __packed __aligned(4); #endif /* S390_ORB_H */ diff --git a/trunk/drivers/s390/cio/qdio_debug.h b/trunk/drivers/s390/cio/qdio_debug.h index 7f8b973da298..e1f646800ddb 100644 --- a/trunk/drivers/s390/cio/qdio_debug.h +++ b/trunk/drivers/s390/cio/qdio_debug.h @@ -37,14 +37,10 @@ static inline int qdio_dbf_passes(debug_info_t *dbf_grp, int level) debug_text_event(qdio_dbf_setup, DBF_ERR, debug_buffer); \ } while (0) -static inline void DBF_HEX(void *addr, int len) -{ - while (len > 0) { - debug_event(qdio_dbf_setup, DBF_ERR, addr, len); - len -= qdio_dbf_setup->buf_size; - addr += qdio_dbf_setup->buf_size; - } -} +#define DBF_HEX(addr, len) \ + do { \ + debug_event(qdio_dbf_setup, DBF_ERR, (void*)(addr), len); \ + } while (0) #define DBF_ERROR(text...) \ do { \ @@ -53,14 +49,11 @@ static inline void DBF_HEX(void *addr, int len) debug_text_event(qdio_dbf_error, DBF_ERR, debug_buffer); \ } while (0) -static inline void DBF_ERROR_HEX(void *addr, int len) -{ - while (len > 0) { - debug_event(qdio_dbf_error, DBF_ERR, addr, len); - len -= qdio_dbf_error->buf_size; - addr += qdio_dbf_error->buf_size; - } -} +#define DBF_ERROR_HEX(addr, len) \ + do { \ + debug_event(qdio_dbf_error, DBF_ERR, (void*)(addr), len); \ + } while (0) + #define DBF_DEV_EVENT(level, device, text...) \ do { \ @@ -71,15 +64,10 @@ static inline void DBF_ERROR_HEX(void *addr, int len) } \ } while (0) -static inline void DBF_DEV_HEX(struct qdio_irq *dev, void *addr, - int len, int level) -{ - while (len > 0) { - debug_event(dev->debug_area, level, addr, len); - len -= dev->debug_area->buf_size; - addr += dev->debug_area->buf_size; - } -} +#define DBF_DEV_HEX(level, device, addr, len) \ + do { \ + debug_event(device->debug_area, level, (void*)(addr), len); \ + } while (0) void qdio_allocate_dbf(struct qdio_initialize *init_data, struct qdio_irq *irq_ptr); diff --git a/trunk/drivers/s390/cio/scm.c b/trunk/drivers/s390/cio/scm.c deleted file mode 100644 index bcf20f3aa51b..000000000000 --- a/trunk/drivers/s390/cio/scm.c +++ /dev/null @@ -1,317 +0,0 @@ -/* - * Recognize and maintain s390 storage class memory. - * - * Copyright IBM Corp. 2012 - * Author(s): Sebastian Ott - */ - -#include -#include -#include -#include -#include -#include -#include -#include "chsc.h" - -static struct device *scm_root; -static struct eadm_ops *eadm_ops; -static DEFINE_MUTEX(eadm_ops_mutex); - -#define to_scm_dev(n) container_of(n, struct scm_device, dev) -#define to_scm_drv(d) container_of(d, struct scm_driver, drv) - -static int scmdev_probe(struct device *dev) -{ - struct scm_device *scmdev = to_scm_dev(dev); - struct scm_driver *scmdrv = to_scm_drv(dev->driver); - - return scmdrv->probe ? scmdrv->probe(scmdev) : -ENODEV; -} - -static int scmdev_remove(struct device *dev) -{ - struct scm_device *scmdev = to_scm_dev(dev); - struct scm_driver *scmdrv = to_scm_drv(dev->driver); - - return scmdrv->remove ? scmdrv->remove(scmdev) : -ENODEV; -} - -static int scmdev_uevent(struct device *dev, struct kobj_uevent_env *env) -{ - return add_uevent_var(env, "MODALIAS=scm:scmdev"); -} - -static struct bus_type scm_bus_type = { - .name = "scm", - .probe = scmdev_probe, - .remove = scmdev_remove, - .uevent = scmdev_uevent, -}; - -/** - * scm_driver_register() - register a scm driver - * @scmdrv: driver to be registered - */ -int scm_driver_register(struct scm_driver *scmdrv) -{ - struct device_driver *drv = &scmdrv->drv; - - drv->bus = &scm_bus_type; - - return driver_register(drv); -} -EXPORT_SYMBOL_GPL(scm_driver_register); - -/** - * scm_driver_unregister() - deregister a scm driver - * @scmdrv: driver to be deregistered - */ -void scm_driver_unregister(struct scm_driver *scmdrv) -{ - driver_unregister(&scmdrv->drv); -} -EXPORT_SYMBOL_GPL(scm_driver_unregister); - -int scm_get_ref(void) -{ - int ret = 0; - - mutex_lock(&eadm_ops_mutex); - if (!eadm_ops || !try_module_get(eadm_ops->owner)) - ret = -ENOENT; - mutex_unlock(&eadm_ops_mutex); - - return ret; -} -EXPORT_SYMBOL_GPL(scm_get_ref); - -void scm_put_ref(void) -{ - mutex_lock(&eadm_ops_mutex); - module_put(eadm_ops->owner); - mutex_unlock(&eadm_ops_mutex); -} -EXPORT_SYMBOL_GPL(scm_put_ref); - -void register_eadm_ops(struct eadm_ops *ops) -{ - mutex_lock(&eadm_ops_mutex); - eadm_ops = ops; - mutex_unlock(&eadm_ops_mutex); -} -EXPORT_SYMBOL_GPL(register_eadm_ops); - -void unregister_eadm_ops(struct eadm_ops *ops) -{ - mutex_lock(&eadm_ops_mutex); - eadm_ops = NULL; - mutex_unlock(&eadm_ops_mutex); -} -EXPORT_SYMBOL_GPL(unregister_eadm_ops); - -int scm_start_aob(struct aob *aob) -{ - return eadm_ops->eadm_start(aob); -} -EXPORT_SYMBOL_GPL(scm_start_aob); - -void scm_irq_handler(struct aob *aob, int error) -{ - struct aob_rq_header *aobrq = (void *) aob->request.data; - struct scm_device *scmdev = aobrq->scmdev; - struct scm_driver *scmdrv = to_scm_drv(scmdev->dev.driver); - - scmdrv->handler(scmdev, aobrq->data, error); -} -EXPORT_SYMBOL_GPL(scm_irq_handler); - -#define scm_attr(name) \ -static ssize_t show_##name(struct device *dev, \ - struct device_attribute *attr, char *buf) \ -{ \ - struct scm_device *scmdev = to_scm_dev(dev); \ - int ret; \ - \ - device_lock(dev); \ - ret = sprintf(buf, "%u\n", scmdev->attrs.name); \ - device_unlock(dev); \ - \ - return ret; \ -} \ -static DEVICE_ATTR(name, S_IRUGO, show_##name, NULL); - -scm_attr(persistence); -scm_attr(oper_state); -scm_attr(data_state); -scm_attr(rank); -scm_attr(release); -scm_attr(res_id); - -static struct attribute *scmdev_attrs[] = { - &dev_attr_persistence.attr, - &dev_attr_oper_state.attr, - &dev_attr_data_state.attr, - &dev_attr_rank.attr, - &dev_attr_release.attr, - &dev_attr_res_id.attr, - NULL, -}; - -static struct attribute_group scmdev_attr_group = { - .attrs = scmdev_attrs, -}; - -static const struct attribute_group *scmdev_attr_groups[] = { - &scmdev_attr_group, - NULL, -}; - -static void scmdev_release(struct device *dev) -{ - struct scm_device *scmdev = to_scm_dev(dev); - - kfree(scmdev); -} - -static void scmdev_setup(struct scm_device *scmdev, struct sale *sale, - unsigned int size, unsigned int max_blk_count) -{ - dev_set_name(&scmdev->dev, "%016llx", (unsigned long long) sale->sa); - scmdev->nr_max_block = max_blk_count; - scmdev->address = sale->sa; - scmdev->size = 1UL << size; - scmdev->attrs.rank = sale->rank; - scmdev->attrs.persistence = sale->p; - scmdev->attrs.oper_state = sale->op_state; - scmdev->attrs.data_state = sale->data_state; - scmdev->attrs.rank = sale->rank; - scmdev->attrs.release = sale->r; - scmdev->attrs.res_id = sale->rid; - scmdev->dev.parent = scm_root; - scmdev->dev.bus = &scm_bus_type; - scmdev->dev.release = scmdev_release; - scmdev->dev.groups = scmdev_attr_groups; -} - -/* - * Check for state-changes, notify the driver and userspace. - */ -static void scmdev_update(struct scm_device *scmdev, struct sale *sale) -{ - struct scm_driver *scmdrv; - bool changed; - - device_lock(&scmdev->dev); - changed = scmdev->attrs.rank != sale->rank || - scmdev->attrs.oper_state != sale->op_state; - scmdev->attrs.rank = sale->rank; - scmdev->attrs.oper_state = sale->op_state; - if (!scmdev->dev.driver) - goto out; - scmdrv = to_scm_drv(scmdev->dev.driver); - if (changed && scmdrv->notify) - scmdrv->notify(scmdev); -out: - device_unlock(&scmdev->dev); - if (changed) - kobject_uevent(&scmdev->dev.kobj, KOBJ_CHANGE); -} - -static int check_address(struct device *dev, void *data) -{ - struct scm_device *scmdev = to_scm_dev(dev); - struct sale *sale = data; - - return scmdev->address == sale->sa; -} - -static struct scm_device *scmdev_find(struct sale *sale) -{ - struct device *dev; - - dev = bus_find_device(&scm_bus_type, NULL, sale, check_address); - - return dev ? to_scm_dev(dev) : NULL; -} - -static int scm_add(struct chsc_scm_info *scm_info, size_t num) -{ - struct sale *sale, *scmal = scm_info->scmal; - struct scm_device *scmdev; - int ret; - - for (sale = scmal; sale < scmal + num; sale++) { - scmdev = scmdev_find(sale); - if (scmdev) { - scmdev_update(scmdev, sale); - /* Release reference from scm_find(). */ - put_device(&scmdev->dev); - continue; - } - scmdev = kzalloc(sizeof(*scmdev), GFP_KERNEL); - if (!scmdev) - return -ENODEV; - scmdev_setup(scmdev, sale, scm_info->is, scm_info->mbc); - ret = device_register(&scmdev->dev); - if (ret) { - /* Release reference from device_initialize(). */ - put_device(&scmdev->dev); - return ret; - } - } - - return 0; -} - -int scm_update_information(void) -{ - struct chsc_scm_info *scm_info; - u64 token = 0; - size_t num; - int ret; - - scm_info = (void *)__get_free_page(GFP_KERNEL | GFP_DMA); - if (!scm_info) - return -ENOMEM; - - do { - ret = chsc_scm_info(scm_info, token); - if (ret) - break; - - num = (scm_info->response.length - - (offsetof(struct chsc_scm_info, scmal) - - offsetof(struct chsc_scm_info, response)) - ) / sizeof(struct sale); - - ret = scm_add(scm_info, num); - if (ret) - break; - - token = scm_info->restok; - } while (token); - - free_page((unsigned long)scm_info); - - return ret; -} - -static int __init scm_init(void) -{ - int ret; - - ret = bus_register(&scm_bus_type); - if (ret) - return ret; - - scm_root = root_device_register("scm"); - if (IS_ERR(scm_root)) { - bus_unregister(&scm_bus_type); - return PTR_ERR(scm_root); - } - - scm_update_information(); - return 0; -} -subsys_initcall_sync(scm_init); diff --git a/trunk/drivers/s390/crypto/Makefile b/trunk/drivers/s390/crypto/Makefile index 771faf7094d6..af3c7f16ea88 100644 --- a/trunk/drivers/s390/crypto/Makefile +++ b/trunk/drivers/s390/crypto/Makefile @@ -4,5 +4,4 @@ ap-objs := ap_bus.o obj-$(CONFIG_ZCRYPT) += ap.o zcrypt_api.o zcrypt_pcicc.o zcrypt_pcixcc.o -obj-$(CONFIG_ZCRYPT) += zcrypt_pcica.o zcrypt_cex2a.o zcrypt_cex4.o -obj-$(CONFIG_ZCRYPT) += zcrypt_msgtype6.o zcrypt_msgtype50.o +obj-$(CONFIG_ZCRYPT) += zcrypt_pcica.o zcrypt_cex2a.o diff --git a/trunk/drivers/s390/crypto/ap_bus.c b/trunk/drivers/s390/crypto/ap_bus.c index 7b865a7300e6..ae258a4b4e5e 100644 --- a/trunk/drivers/s390/crypto/ap_bus.c +++ b/trunk/drivers/s390/crypto/ap_bus.c @@ -1,5 +1,5 @@ /* - * Copyright IBM Corp. 2006, 2012 + * Copyright IBM Corp. 2006 * Author(s): Cornelia Huck * Martin Schwidefsky * Ralph Wuerthner @@ -62,14 +62,13 @@ static void ap_interrupt_handler(void *unused1, void *unused2); static void ap_reset(struct ap_device *ap_dev); static void ap_config_timeout(unsigned long ptr); static int ap_select_domain(void); -static void ap_query_configuration(void); /* * Module description. */ MODULE_AUTHOR("IBM Corporation"); -MODULE_DESCRIPTION("Adjunct Processor Bus driver, " \ - "Copyright IBM Corp. 2006, 2012"); +MODULE_DESCRIPTION("Adjunct Processor Bus driver, " + "Copyright IBM Corp. 2006"); MODULE_LICENSE("GPL"); /* @@ -85,7 +84,6 @@ module_param_named(poll_thread, ap_thread_flag, int, 0000); MODULE_PARM_DESC(poll_thread, "Turn on/off poll thread, default is 0 (off)."); static struct device *ap_root_device = NULL; -static struct ap_config_info *ap_configuration; static DEFINE_SPINLOCK(ap_device_list_lock); static LIST_HEAD(ap_device_list); @@ -159,19 +157,6 @@ static int ap_interrupts_available(void) return test_facility(2) && test_facility(65); } -/** - * ap_configuration_available(): Test if AP configuration - * information is available. - * - * Returns 1 if AP configuration information is available. - */ -#ifdef CONFIG_64BIT -static int ap_configuration_available(void) -{ - return test_facility(2) && test_facility(12); -} -#endif - /** * ap_test_queue(): Test adjunct processor queue. * @qid: The AP queue number @@ -257,26 +242,6 @@ __ap_query_functions(ap_qid_t qid, unsigned int *functions) } #endif -#ifdef CONFIG_64BIT -static inline int __ap_query_configuration(struct ap_config_info *config) -{ - register unsigned long reg0 asm ("0") = 0x04000000UL; - register unsigned long reg1 asm ("1") = -EINVAL; - register unsigned char *reg2 asm ("2") = (unsigned char *)config; - - asm volatile( - ".long 0xb2af0000\n" /* PQAP(QCI) */ - "0: la %1,0\n" - "1:\n" - EX_TABLE(0b, 1b) - : "+d" (reg0), "+d" (reg1), "+d" (reg2) - : - : "cc"); - - return reg1; -} -#endif - /** * ap_query_functions(): Query supported functions. * @qid: The AP queue number @@ -326,6 +291,25 @@ static int ap_query_functions(ap_qid_t qid, unsigned int *functions) #endif } +/** + * ap_4096_commands_availablen(): Check for availability of 4096 bit RSA + * support. + * @qid: The AP queue number + * + * Returns 1 if 4096 bit RSA keys are support fo the AP, returns 0 if not. + */ +int ap_4096_commands_available(ap_qid_t qid) +{ + unsigned int functions; + + if (ap_query_functions(qid, &functions)) + return 0; + + return test_ap_facility(functions, 1) && + test_ap_facility(functions, 2); +} +EXPORT_SYMBOL(ap_4096_commands_available); + /** * ap_queue_enable_interruption(): Enable interruption on an AP. * @qid: The AP queue number @@ -673,34 +657,6 @@ static ssize_t ap_request_count_show(struct device *dev, static DEVICE_ATTR(request_count, 0444, ap_request_count_show, NULL); -static ssize_t ap_requestq_count_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct ap_device *ap_dev = to_ap_dev(dev); - int rc; - - spin_lock_bh(&ap_dev->lock); - rc = snprintf(buf, PAGE_SIZE, "%d\n", ap_dev->requestq_count); - spin_unlock_bh(&ap_dev->lock); - return rc; -} - -static DEVICE_ATTR(requestq_count, 0444, ap_requestq_count_show, NULL); - -static ssize_t ap_pendingq_count_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct ap_device *ap_dev = to_ap_dev(dev); - int rc; - - spin_lock_bh(&ap_dev->lock); - rc = snprintf(buf, PAGE_SIZE, "%d\n", ap_dev->pendingq_count); - spin_unlock_bh(&ap_dev->lock); - return rc; -} - -static DEVICE_ATTR(pendingq_count, 0444, ap_pendingq_count_show, NULL); - static ssize_t ap_modalias_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -709,23 +665,11 @@ static ssize_t ap_modalias_show(struct device *dev, static DEVICE_ATTR(modalias, 0444, ap_modalias_show, NULL); -static ssize_t ap_functions_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct ap_device *ap_dev = to_ap_dev(dev); - return snprintf(buf, PAGE_SIZE, "0x%08X\n", ap_dev->functions); -} - -static DEVICE_ATTR(ap_functions, 0444, ap_functions_show, NULL); - static struct attribute *ap_dev_attrs[] = { &dev_attr_hwtype.attr, &dev_attr_depth.attr, &dev_attr_request_count.attr, - &dev_attr_requestq_count.attr, - &dev_attr_pendingq_count.attr, &dev_attr_modalias.attr, - &dev_attr_ap_functions.attr, NULL }; static struct attribute_group ap_dev_attr_group = { @@ -828,7 +772,6 @@ static int ap_bus_resume(struct device *dev) ap_suspend_flag = 0; if (!ap_interrupts_available()) ap_interrupt_indicator = NULL; - ap_query_configuration(); if (!user_set_domain) { ap_domain_index = -1; ap_select_domain(); @@ -952,20 +895,6 @@ void ap_driver_unregister(struct ap_driver *ap_drv) } EXPORT_SYMBOL(ap_driver_unregister); -void ap_bus_force_rescan(void) -{ - /* Delete the AP bus rescan timer. */ - del_timer(&ap_config_timer); - - /* processing a synchonuous bus rescan */ - ap_scan_bus(NULL); - - /* Setup the AP bus rescan timer again. */ - ap_config_timer.expires = jiffies + ap_config_time * HZ; - add_timer(&ap_config_timer); -} -EXPORT_SYMBOL(ap_bus_force_rescan); - /* * AP bus attributes. */ @@ -1068,65 +997,6 @@ static struct bus_attribute *const ap_bus_attrs[] = { NULL, }; -static inline int ap_test_config(unsigned int *field, unsigned int nr) -{ - if (nr > 0xFFu) - return 0; - return ap_test_bit((field + (nr >> 5)), (nr & 0x1f)); -} - -/* - * ap_test_config_card_id(): Test, whether an AP card ID is configured. - * @id AP card ID - * - * Returns 0 if the card is not configured - * 1 if the card is configured or - * if the configuration information is not available - */ -static inline int ap_test_config_card_id(unsigned int id) -{ - if (!ap_configuration) - return 1; - return ap_test_config(ap_configuration->apm, id); -} - -/* - * ap_test_config_domain(): Test, whether an AP usage domain is configured. - * @domain AP usage domain ID - * - * Returns 0 if the usage domain is not configured - * 1 if the usage domain is configured or - * if the configuration information is not available - */ -static inline int ap_test_config_domain(unsigned int domain) -{ - if (!ap_configuration) - return 1; - return ap_test_config(ap_configuration->aqm, domain); -} - -/** - * ap_query_configuration(): Query AP configuration information. - * - * Query information of installed cards and configured domains from AP. - */ -static void ap_query_configuration(void) -{ -#ifdef CONFIG_64BIT - if (ap_configuration_available()) { - if (!ap_configuration) - ap_configuration = - kzalloc(sizeof(struct ap_config_info), - GFP_KERNEL); - if (ap_configuration) - __ap_query_configuration(ap_configuration); - } else - ap_configuration = NULL; -#else - ap_configuration = NULL; -#endif -} - /** * ap_select_domain(): Select an AP domain. * @@ -1135,7 +1005,6 @@ static void ap_query_configuration(void) static int ap_select_domain(void) { int queue_depth, device_type, count, max_count, best_domain; - ap_qid_t qid; int rc, i, j; /* @@ -1149,13 +1018,9 @@ static int ap_select_domain(void) best_domain = -1; max_count = 0; for (i = 0; i < AP_DOMAINS; i++) { - if (!ap_test_config_domain(i)) - continue; count = 0; for (j = 0; j < AP_DEVICES; j++) { - if (!ap_test_config_card_id(j)) - continue; - qid = AP_MKQID(j, i); + ap_qid_t qid = AP_MKQID(j, i); rc = ap_query_queue(qid, &queue_depth, &device_type); if (rc) continue; @@ -1304,7 +1169,6 @@ static void ap_scan_bus(struct work_struct *unused) unsigned int device_functions; int rc, i; - ap_query_configuration(); if (ap_select_domain() != 0) return; for (i = 0; i < AP_DEVICES; i++) { @@ -1312,10 +1176,7 @@ static void ap_scan_bus(struct work_struct *unused) dev = bus_find_device(&ap_bus_type, NULL, (void *)(unsigned long)qid, __ap_scan_bus); - if (ap_test_config_card_id(i)) - rc = ap_query_queue(qid, &queue_depth, &device_type); - else - rc = -ENODEV; + rc = ap_query_queue(qid, &queue_depth, &device_type); if (dev) { if (rc == -EBUSY) { set_current_state(TASK_UNINTERRUPTIBLE); @@ -1356,22 +1217,29 @@ static void ap_scan_bus(struct work_struct *unused) (unsigned long) ap_dev); switch (device_type) { case 0: - /* device type probing for old cards */ if (ap_probe_device_type(ap_dev)) { kfree(ap_dev); continue; } break; + case 10: + if (ap_query_functions(qid, &device_functions)) { + kfree(ap_dev); + continue; + } + if (test_ap_facility(device_functions, 3)) + ap_dev->device_type = AP_DEVICE_TYPE_CEX3C; + else if (test_ap_facility(device_functions, 4)) + ap_dev->device_type = AP_DEVICE_TYPE_CEX3A; + else { + kfree(ap_dev); + continue; + } + break; default: ap_dev->device_type = device_type; } - rc = ap_query_functions(qid, &device_functions); - if (!rc) - ap_dev->functions = device_functions; - else - ap_dev->functions = 0u; - ap_dev->device.bus = &ap_bus_type; ap_dev->device.parent = ap_root_device; if (dev_set_name(&ap_dev->device, "card%02x", @@ -1917,7 +1785,6 @@ int __init ap_module_init(void) goto out_root; } - ap_query_configuration(); if (ap_select_domain() == 0) ap_scan_bus(NULL); diff --git a/trunk/drivers/s390/crypto/ap_bus.h b/trunk/drivers/s390/crypto/ap_bus.h index 685f6cc022f9..52d61995af88 100644 --- a/trunk/drivers/s390/crypto/ap_bus.h +++ b/trunk/drivers/s390/crypto/ap_bus.h @@ -1,5 +1,5 @@ /* - * Copyright IBM Corp. 2006, 2012 + * Copyright IBM Corp. 2006 * Author(s): Cornelia Huck * Martin Schwidefsky * Ralph Wuerthner @@ -83,12 +83,13 @@ int ap_queue_status_invalid_test(struct ap_queue_status *status) return !(memcmp(status, &invalid, sizeof(struct ap_queue_status))); } -#define AP_MAX_BITS 31 -static inline int ap_test_bit(unsigned int *ptr, unsigned int nr) +#define MAX_AP_FACILITY 31 + +static inline int test_ap_facility(unsigned int function, unsigned int nr) { - if (nr > AP_MAX_BITS) + if (nr > MAX_AP_FACILITY) return 0; - return (*ptr & (0x80000000u >> nr)) != 0; + return function & (unsigned int)(0x80000000 >> nr); } #define AP_RESPONSE_NORMAL 0x00 @@ -116,15 +117,6 @@ static inline int ap_test_bit(unsigned int *ptr, unsigned int nr) #define AP_DEVICE_TYPE_CEX2C 7 #define AP_DEVICE_TYPE_CEX3A 8 #define AP_DEVICE_TYPE_CEX3C 9 -#define AP_DEVICE_TYPE_CEX4 10 - -/* - * Known function facilities - */ -#define AP_FUNC_MEX4K 1 -#define AP_FUNC_CRT4K 2 -#define AP_FUNC_COPRO 3 -#define AP_FUNC_ACCEL 4 /* * AP reset flag states @@ -159,7 +151,6 @@ struct ap_device { ap_qid_t qid; /* AP queue id. */ int queue_depth; /* AP queue depth.*/ int device_type; /* AP device type. */ - unsigned int functions; /* AP device function bitfield. */ int unregistered; /* marks AP device as unregistered */ struct timer_list timeout; /* Timer for request timeouts. */ int reset; /* Reset required after req. timeout. */ @@ -192,17 +183,6 @@ struct ap_message { struct ap_message *); }; -struct ap_config_info { - unsigned int special_command:1; - unsigned int ap_extended:1; - unsigned char reserved1:6; - unsigned char reserved2[15]; - unsigned int apm[8]; /* AP ID mask */ - unsigned int aqm[8]; /* AP queue mask */ - unsigned int adm[8]; /* AP domain mask */ - unsigned char reserved4[16]; -} __packed; - #define AP_DEVICE(dt) \ .dev_type=(dt), \ .match_flags=AP_DEVICE_ID_MATCH_DEVICE_TYPE, @@ -231,9 +211,10 @@ int ap_recv(ap_qid_t, unsigned long long *, void *, size_t); void ap_queue_message(struct ap_device *ap_dev, struct ap_message *ap_msg); void ap_cancel_message(struct ap_device *ap_dev, struct ap_message *ap_msg); void ap_flush_queue(struct ap_device *ap_dev); -void ap_bus_force_rescan(void); int ap_module_init(void); void ap_module_exit(void); +int ap_4096_commands_available(ap_qid_t qid); + #endif /* _AP_BUS_H_ */ diff --git a/trunk/drivers/s390/crypto/zcrypt_api.c b/trunk/drivers/s390/crypto/zcrypt_api.c index 31cfaa556072..2f94132246a1 100644 --- a/trunk/drivers/s390/crypto/zcrypt_api.c +++ b/trunk/drivers/s390/crypto/zcrypt_api.c @@ -1,7 +1,7 @@ /* * zcrypt 2.1.0 * - * Copyright IBM Corp. 2001, 2012 + * Copyright IBM Corp. 2001, 2006 * Author(s): Robert Burroughs * Eric Rossman (edrossma@us.ibm.com) * Cornelia Huck @@ -9,7 +9,6 @@ * Hotplug & misc device support: Jochen Roehrig (roehrig@de.ibm.com) * Major cleanup & driver split: Martin Schwidefsky * Ralph Wuerthner - * MSGTYPE restruct: Holger Dengler * * 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 @@ -38,39 +37,25 @@ #include #include #include -#include -#include -#include "zcrypt_debug.h" #include "zcrypt_api.h" /* * Module description. */ MODULE_AUTHOR("IBM Corporation"); -MODULE_DESCRIPTION("Cryptographic Coprocessor interface, " \ - "Copyright IBM Corp. 2001, 2012"); +MODULE_DESCRIPTION("Cryptographic Coprocessor interface, " + "Copyright IBM Corp. 2001, 2006"); MODULE_LICENSE("GPL"); static DEFINE_SPINLOCK(zcrypt_device_lock); static LIST_HEAD(zcrypt_device_list); static int zcrypt_device_count = 0; static atomic_t zcrypt_open_count = ATOMIC_INIT(0); -static atomic_t zcrypt_rescan_count = ATOMIC_INIT(0); - -atomic_t zcrypt_rescan_req = ATOMIC_INIT(0); -EXPORT_SYMBOL(zcrypt_rescan_req); static int zcrypt_rng_device_add(void); static void zcrypt_rng_device_remove(void); -static DEFINE_SPINLOCK(zcrypt_ops_list_lock); -static LIST_HEAD(zcrypt_ops_list); - -static debug_info_t *zcrypt_dbf_common; -static debug_info_t *zcrypt_dbf_devices; -static struct dentry *debugfs_root; - /* * Device attributes common for all crypto devices. */ @@ -100,8 +85,6 @@ static ssize_t zcrypt_online_store(struct device *dev, if (sscanf(buf, "%d\n", &online) != 1 || online < 0 || online > 1) return -EINVAL; zdev->online = online; - ZCRYPT_DBF_DEV(DBF_INFO, zdev, "dev%04xo%dman", zdev->ap_dev->qid, - zdev->online); if (!online) ap_flush_queue(zdev->ap_dev); return count; @@ -119,24 +102,6 @@ static struct attribute_group zcrypt_device_attr_group = { .attrs = zcrypt_device_attrs, }; -/** - * Process a rescan of the transport layer. - * - * Returns 1, if the rescan has been processed, otherwise 0. - */ -static inline int zcrypt_process_rescan(void) -{ - if (atomic_read(&zcrypt_rescan_req)) { - atomic_set(&zcrypt_rescan_req, 0); - atomic_inc(&zcrypt_rescan_count); - ap_bus_force_rescan(); - ZCRYPT_DBF_COMMON(DBF_INFO, "rescan%07d", - atomic_inc_return(&zcrypt_rescan_count)); - return 1; - } - return 0; -} - /** * __zcrypt_increase_preference(): Increase preference of a crypto device. * @zdev: Pointer the crypto device @@ -225,7 +190,6 @@ struct zcrypt_device *zcrypt_device_alloc(size_t max_response_size) zdev->reply.length = max_response_size; spin_lock_init(&zdev->lock); INIT_LIST_HEAD(&zdev->list); - zdev->dbf_area = zcrypt_dbf_devices; return zdev; out_free: @@ -251,8 +215,6 @@ int zcrypt_device_register(struct zcrypt_device *zdev) { int rc; - if (!zdev->ops) - return -ENODEV; rc = sysfs_create_group(&zdev->ap_dev->device.kobj, &zcrypt_device_attr_group); if (rc) @@ -261,8 +223,6 @@ int zcrypt_device_register(struct zcrypt_device *zdev) kref_init(&zdev->refcount); spin_lock_bh(&zcrypt_device_lock); zdev->online = 1; /* New devices are online by default. */ - ZCRYPT_DBF_DEV(DBF_INFO, zdev, "dev%04xo%dreg", zdev->ap_dev->qid, - zdev->online); list_add_tail(&zdev->list, &zcrypt_device_list); __zcrypt_increase_preference(zdev); zcrypt_device_count++; @@ -309,67 +269,6 @@ void zcrypt_device_unregister(struct zcrypt_device *zdev) } EXPORT_SYMBOL(zcrypt_device_unregister); -void zcrypt_msgtype_register(struct zcrypt_ops *zops) -{ - if (zops->owner) { - spin_lock_bh(&zcrypt_ops_list_lock); - list_add_tail(&zops->list, &zcrypt_ops_list); - spin_unlock_bh(&zcrypt_ops_list_lock); - } -} -EXPORT_SYMBOL(zcrypt_msgtype_register); - -void zcrypt_msgtype_unregister(struct zcrypt_ops *zops) -{ - spin_lock_bh(&zcrypt_ops_list_lock); - list_del_init(&zops->list); - spin_unlock_bh(&zcrypt_ops_list_lock); -} -EXPORT_SYMBOL(zcrypt_msgtype_unregister); - -static inline -struct zcrypt_ops *__ops_lookup(unsigned char *name, int variant) -{ - struct zcrypt_ops *zops; - int found = 0; - - spin_lock_bh(&zcrypt_ops_list_lock); - list_for_each_entry(zops, &zcrypt_ops_list, list) { - if ((zops->variant == variant) && - (!strncmp(zops->owner->name, name, MODULE_NAME_LEN))) { - found = 1; - break; - } - } - spin_unlock_bh(&zcrypt_ops_list_lock); - - if (!found) - return NULL; - return zops; -} - -struct zcrypt_ops *zcrypt_msgtype_request(unsigned char *name, int variant) -{ - struct zcrypt_ops *zops = NULL; - - zops = __ops_lookup(name, variant); - if (!zops) { - request_module(name); - zops = __ops_lookup(name, variant); - } - if ((!zops) || (!try_module_get(zops->owner))) - return NULL; - return zops; -} -EXPORT_SYMBOL(zcrypt_msgtype_request); - -void zcrypt_msgtype_release(struct zcrypt_ops *zops) -{ - if (zops) - module_put(zops->owner); -} -EXPORT_SYMBOL(zcrypt_msgtype_release); - /** * zcrypt_read (): Not supported beyond zcrypt 1.3.1. * @@ -741,11 +640,6 @@ static long zcrypt_unlocked_ioctl(struct file *filp, unsigned int cmd, do { rc = zcrypt_rsa_modexpo(&mex); } while (rc == -EAGAIN); - /* on failure: retry once again after a requested rescan */ - if ((rc == -ENODEV) && (zcrypt_process_rescan())) - do { - rc = zcrypt_rsa_modexpo(&mex); - } while (rc == -EAGAIN); if (rc) return rc; return put_user(mex.outputdatalength, &umex->outputdatalength); @@ -758,11 +652,6 @@ static long zcrypt_unlocked_ioctl(struct file *filp, unsigned int cmd, do { rc = zcrypt_rsa_crt(&crt); } while (rc == -EAGAIN); - /* on failure: retry once again after a requested rescan */ - if ((rc == -ENODEV) && (zcrypt_process_rescan())) - do { - rc = zcrypt_rsa_crt(&crt); - } while (rc == -EAGAIN); if (rc) return rc; return put_user(crt.outputdatalength, &ucrt->outputdatalength); @@ -775,11 +664,6 @@ static long zcrypt_unlocked_ioctl(struct file *filp, unsigned int cmd, do { rc = zcrypt_send_cprb(&xcRB); } while (rc == -EAGAIN); - /* on failure: retry once again after a requested rescan */ - if ((rc == -ENODEV) && (zcrypt_process_rescan())) - do { - rc = zcrypt_send_cprb(&xcRB); - } while (rc == -EAGAIN); if (copy_to_user(uxcRB, &xcRB, sizeof(xcRB))) return -EFAULT; return rc; @@ -886,15 +770,10 @@ static long trans_modexpo32(struct file *filp, unsigned int cmd, do { rc = zcrypt_rsa_modexpo(&mex64); } while (rc == -EAGAIN); - /* on failure: retry once again after a requested rescan */ - if ((rc == -ENODEV) && (zcrypt_process_rescan())) - do { - rc = zcrypt_rsa_modexpo(&mex64); - } while (rc == -EAGAIN); - if (rc) - return rc; - return put_user(mex64.outputdatalength, - &umex32->outputdatalength); + if (!rc) + rc = put_user(mex64.outputdatalength, + &umex32->outputdatalength); + return rc; } struct compat_ica_rsa_modexpo_crt { @@ -931,15 +810,10 @@ static long trans_modexpo_crt32(struct file *filp, unsigned int cmd, do { rc = zcrypt_rsa_crt(&crt64); } while (rc == -EAGAIN); - /* on failure: retry once again after a requested rescan */ - if ((rc == -ENODEV) && (zcrypt_process_rescan())) - do { - rc = zcrypt_rsa_crt(&crt64); - } while (rc == -EAGAIN); - if (rc) - return rc; - return put_user(crt64.outputdatalength, - &ucrt32->outputdatalength); + if (!rc) + rc = put_user(crt64.outputdatalength, + &ucrt32->outputdatalength); + return rc; } struct compat_ica_xcRB { @@ -995,11 +869,6 @@ static long trans_xcRB32(struct file *filp, unsigned int cmd, do { rc = zcrypt_send_cprb(&xcRB64); } while (rc == -EAGAIN); - /* on failure: retry once again after a requested rescan */ - if ((rc == -ENODEV) && (zcrypt_process_rescan())) - do { - rc = zcrypt_send_cprb(&xcRB64); - } while (rc == -EAGAIN); xcRB32.reply_control_blk_length = xcRB64.reply_control_blk_length; xcRB32.reply_data_length = xcRB64.reply_data_length; xcRB32.status = xcRB64.status; @@ -1257,9 +1126,6 @@ static int zcrypt_rng_data_read(struct hwrng *rng, u32 *data) */ if (zcrypt_rng_buffer_index == 0) { rc = zcrypt_rng((char *) zcrypt_rng_buffer); - /* on failure: retry once again after a requested rescan */ - if ((rc == -ENODEV) && (zcrypt_process_rescan())) - rc = zcrypt_rng((char *) zcrypt_rng_buffer); if (rc < 0) return -EIO; zcrypt_rng_buffer_index = rc / sizeof *data; @@ -1312,30 +1178,6 @@ static void zcrypt_rng_device_remove(void) mutex_unlock(&zcrypt_rng_mutex); } -int __init zcrypt_debug_init(void) -{ - debugfs_root = debugfs_create_dir("zcrypt", NULL); - - zcrypt_dbf_common = debug_register("zcrypt_common", 1, 1, 16); - debug_register_view(zcrypt_dbf_common, &debug_hex_ascii_view); - debug_set_level(zcrypt_dbf_common, DBF_ERR); - - zcrypt_dbf_devices = debug_register("zcrypt_devices", 1, 1, 16); - debug_register_view(zcrypt_dbf_devices, &debug_hex_ascii_view); - debug_set_level(zcrypt_dbf_devices, DBF_ERR); - - return 0; -} - -void zcrypt_debug_exit(void) -{ - debugfs_remove(debugfs_root); - if (zcrypt_dbf_common) - debug_unregister(zcrypt_dbf_common); - if (zcrypt_dbf_devices) - debug_unregister(zcrypt_dbf_devices); -} - /** * zcrypt_api_init(): Module initialization. * @@ -1345,12 +1187,6 @@ int __init zcrypt_api_init(void) { int rc; - rc = zcrypt_debug_init(); - if (rc) - goto out; - - atomic_set(&zcrypt_rescan_req, 0); - /* Register the request sprayer. */ rc = misc_register(&zcrypt_misc_device); if (rc < 0) @@ -1380,7 +1216,6 @@ void zcrypt_api_exit(void) { remove_proc_entry("driver/z90crypt", NULL); misc_deregister(&zcrypt_misc_device); - zcrypt_debug_exit(); } module_init(zcrypt_api_init); diff --git a/trunk/drivers/s390/crypto/zcrypt_api.h b/trunk/drivers/s390/crypto/zcrypt_api.h index 89632919c993..7a32c4bc8ef9 100644 --- a/trunk/drivers/s390/crypto/zcrypt_api.h +++ b/trunk/drivers/s390/crypto/zcrypt_api.h @@ -1,7 +1,7 @@ /* * zcrypt 2.1.0 * - * Copyright IBM Corp. 2001, 2012 + * Copyright IBM Corp. 2001, 2006 * Author(s): Robert Burroughs * Eric Rossman (edrossma@us.ibm.com) * Cornelia Huck @@ -9,7 +9,6 @@ * Hotplug & misc device support: Jochen Roehrig (roehrig@de.ibm.com) * Major cleanup & driver split: Martin Schwidefsky * Ralph Wuerthner - * MSGTYPE restruct: Holger Dengler * * 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 @@ -29,10 +28,8 @@ #ifndef _ZCRYPT_API_H_ #define _ZCRYPT_API_H_ -#include -#include -#include #include "ap_bus.h" +#include /* deprecated status calls */ #define ICAZ90STATUS _IOR(ZCRYPT_IOCTL_MAGIC, 0x10, struct ica_z90_status) @@ -90,9 +87,6 @@ struct zcrypt_ops { struct ica_rsa_modexpo_crt *); long (*send_cprb)(struct zcrypt_device *, struct ica_xcRB *); long (*rng)(struct zcrypt_device *, char *); - struct list_head list; /* zcrypt ops list. */ - struct module *owner; - int variant; }; struct zcrypt_device { @@ -114,23 +108,14 @@ struct zcrypt_device { struct ap_message reply; /* Per-device reply structure. */ int max_exp_bit_length; - - debug_info_t *dbf_area; /* debugging */ }; -/* transport layer rescanning */ -extern atomic_t zcrypt_rescan_req; - struct zcrypt_device *zcrypt_device_alloc(size_t); void zcrypt_device_free(struct zcrypt_device *); void zcrypt_device_get(struct zcrypt_device *); int zcrypt_device_put(struct zcrypt_device *); int zcrypt_device_register(struct zcrypt_device *); void zcrypt_device_unregister(struct zcrypt_device *); -void zcrypt_msgtype_register(struct zcrypt_ops *); -void zcrypt_msgtype_unregister(struct zcrypt_ops *); -struct zcrypt_ops *zcrypt_msgtype_request(unsigned char *, int); -void zcrypt_msgtype_release(struct zcrypt_ops *); int zcrypt_api_init(void); void zcrypt_api_exit(void); diff --git a/trunk/drivers/s390/crypto/zcrypt_cex2a.c b/trunk/drivers/s390/crypto/zcrypt_cex2a.c index 1e849d6e1dfe..744c668f586c 100644 --- a/trunk/drivers/s390/crypto/zcrypt_cex2a.c +++ b/trunk/drivers/s390/crypto/zcrypt_cex2a.c @@ -1,14 +1,13 @@ /* * zcrypt 2.1.0 * - * Copyright IBM Corp. 2001, 2012 + * Copyright IBM Corp. 2001, 2006 * Author(s): Robert Burroughs * Eric Rossman (edrossma@us.ibm.com) * * Hotplug & misc device support: Jochen Roehrig (roehrig@de.ibm.com) * Major cleanup & driver split: Martin Schwidefsky * Ralph Wuerthner - * MSGTYPE restruct: Holger Dengler * * 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 @@ -36,7 +35,6 @@ #include "zcrypt_api.h" #include "zcrypt_error.h" #include "zcrypt_cex2a.h" -#include "zcrypt_msgtype50.h" #define CEX2A_MIN_MOD_SIZE 1 /* 8 bits */ #define CEX2A_MAX_MOD_SIZE 256 /* 2048 bits */ @@ -65,12 +63,14 @@ static struct ap_device_id zcrypt_cex2a_ids[] = { MODULE_DEVICE_TABLE(ap, zcrypt_cex2a_ids); MODULE_AUTHOR("IBM Corporation"); -MODULE_DESCRIPTION("CEX2A Cryptographic Coprocessor device driver, " \ - "Copyright IBM Corp. 2001, 2012"); +MODULE_DESCRIPTION("CEX2A Cryptographic Coprocessor device driver, " + "Copyright IBM Corp. 2001, 2006"); MODULE_LICENSE("GPL"); static int zcrypt_cex2a_probe(struct ap_device *ap_dev); static void zcrypt_cex2a_remove(struct ap_device *ap_dev); +static void zcrypt_cex2a_receive(struct ap_device *, struct ap_message *, + struct ap_message *); static struct ap_driver zcrypt_cex2a_driver = { .probe = zcrypt_cex2a_probe, @@ -79,6 +79,344 @@ static struct ap_driver zcrypt_cex2a_driver = { .request_timeout = CEX2A_CLEANUP_TIME, }; +/** + * Convert a ICAMEX message to a type50 MEX message. + * + * @zdev: crypto device pointer + * @zreq: crypto request pointer + * @mex: pointer to user input data + * + * Returns 0 on success or -EFAULT. + */ +static int ICAMEX_msg_to_type50MEX_msg(struct zcrypt_device *zdev, + struct ap_message *ap_msg, + struct ica_rsa_modexpo *mex) +{ + unsigned char *mod, *exp, *inp; + int mod_len; + + mod_len = mex->inputdatalength; + + if (mod_len <= 128) { + struct type50_meb1_msg *meb1 = ap_msg->message; + memset(meb1, 0, sizeof(*meb1)); + ap_msg->length = sizeof(*meb1); + meb1->header.msg_type_code = TYPE50_TYPE_CODE; + meb1->header.msg_len = sizeof(*meb1); + meb1->keyblock_type = TYPE50_MEB1_FMT; + mod = meb1->modulus + sizeof(meb1->modulus) - mod_len; + exp = meb1->exponent + sizeof(meb1->exponent) - mod_len; + inp = meb1->message + sizeof(meb1->message) - mod_len; + } else if (mod_len <= 256) { + struct type50_meb2_msg *meb2 = ap_msg->message; + memset(meb2, 0, sizeof(*meb2)); + ap_msg->length = sizeof(*meb2); + meb2->header.msg_type_code = TYPE50_TYPE_CODE; + meb2->header.msg_len = sizeof(*meb2); + meb2->keyblock_type = TYPE50_MEB2_FMT; + mod = meb2->modulus + sizeof(meb2->modulus) - mod_len; + exp = meb2->exponent + sizeof(meb2->exponent) - mod_len; + inp = meb2->message + sizeof(meb2->message) - mod_len; + } else { + /* mod_len > 256 = 4096 bit RSA Key */ + struct type50_meb3_msg *meb3 = ap_msg->message; + memset(meb3, 0, sizeof(*meb3)); + ap_msg->length = sizeof(*meb3); + meb3->header.msg_type_code = TYPE50_TYPE_CODE; + meb3->header.msg_len = sizeof(*meb3); + meb3->keyblock_type = TYPE50_MEB3_FMT; + mod = meb3->modulus + sizeof(meb3->modulus) - mod_len; + exp = meb3->exponent + sizeof(meb3->exponent) - mod_len; + inp = meb3->message + sizeof(meb3->message) - mod_len; + } + + if (copy_from_user(mod, mex->n_modulus, mod_len) || + copy_from_user(exp, mex->b_key, mod_len) || + copy_from_user(inp, mex->inputdata, mod_len)) + return -EFAULT; + return 0; +} + +/** + * Convert a ICACRT message to a type50 CRT message. + * + * @zdev: crypto device pointer + * @zreq: crypto request pointer + * @crt: pointer to user input data + * + * Returns 0 on success or -EFAULT. + */ +static int ICACRT_msg_to_type50CRT_msg(struct zcrypt_device *zdev, + struct ap_message *ap_msg, + struct ica_rsa_modexpo_crt *crt) +{ + int mod_len, short_len, long_len, long_offset, limit; + unsigned char *p, *q, *dp, *dq, *u, *inp; + + mod_len = crt->inputdatalength; + short_len = mod_len / 2; + long_len = mod_len / 2 + 8; + + /* + * CEX2A cannot handle p, dp, or U > 128 bytes. + * If we have one of these, we need to do extra checking. + * For CEX3A the limit is 256 bytes. + */ + if (zdev->max_mod_size == CEX3A_MAX_MOD_SIZE) + limit = 256; + else + limit = 128; + + if (long_len > limit) { + /* + * zcrypt_rsa_crt already checked for the leading + * zeroes of np_prime, bp_key and u_mult_inc. + */ + long_offset = long_len - limit; + long_len = limit; + } else + long_offset = 0; + + /* + * Instead of doing extra work for p, dp, U > 64 bytes, we'll just use + * the larger message structure. + */ + if (long_len <= 64) { + struct type50_crb1_msg *crb1 = ap_msg->message; + memset(crb1, 0, sizeof(*crb1)); + ap_msg->length = sizeof(*crb1); + crb1->header.msg_type_code = TYPE50_TYPE_CODE; + crb1->header.msg_len = sizeof(*crb1); + crb1->keyblock_type = TYPE50_CRB1_FMT; + p = crb1->p + sizeof(crb1->p) - long_len; + q = crb1->q + sizeof(crb1->q) - short_len; + dp = crb1->dp + sizeof(crb1->dp) - long_len; + dq = crb1->dq + sizeof(crb1->dq) - short_len; + u = crb1->u + sizeof(crb1->u) - long_len; + inp = crb1->message + sizeof(crb1->message) - mod_len; + } else if (long_len <= 128) { + struct type50_crb2_msg *crb2 = ap_msg->message; + memset(crb2, 0, sizeof(*crb2)); + ap_msg->length = sizeof(*crb2); + crb2->header.msg_type_code = TYPE50_TYPE_CODE; + crb2->header.msg_len = sizeof(*crb2); + crb2->keyblock_type = TYPE50_CRB2_FMT; + p = crb2->p + sizeof(crb2->p) - long_len; + q = crb2->q + sizeof(crb2->q) - short_len; + dp = crb2->dp + sizeof(crb2->dp) - long_len; + dq = crb2->dq + sizeof(crb2->dq) - short_len; + u = crb2->u + sizeof(crb2->u) - long_len; + inp = crb2->message + sizeof(crb2->message) - mod_len; + } else { + /* long_len >= 256 */ + struct type50_crb3_msg *crb3 = ap_msg->message; + memset(crb3, 0, sizeof(*crb3)); + ap_msg->length = sizeof(*crb3); + crb3->header.msg_type_code = TYPE50_TYPE_CODE; + crb3->header.msg_len = sizeof(*crb3); + crb3->keyblock_type = TYPE50_CRB3_FMT; + p = crb3->p + sizeof(crb3->p) - long_len; + q = crb3->q + sizeof(crb3->q) - short_len; + dp = crb3->dp + sizeof(crb3->dp) - long_len; + dq = crb3->dq + sizeof(crb3->dq) - short_len; + u = crb3->u + sizeof(crb3->u) - long_len; + inp = crb3->message + sizeof(crb3->message) - mod_len; + } + + if (copy_from_user(p, crt->np_prime + long_offset, long_len) || + copy_from_user(q, crt->nq_prime, short_len) || + copy_from_user(dp, crt->bp_key + long_offset, long_len) || + copy_from_user(dq, crt->bq_key, short_len) || + copy_from_user(u, crt->u_mult_inv + long_offset, long_len) || + copy_from_user(inp, crt->inputdata, mod_len)) + return -EFAULT; + + return 0; +} + +/** + * Copy results from a type 80 reply message back to user space. + * + * @zdev: crypto device pointer + * @reply: reply AP message. + * @data: pointer to user output data + * @length: size of user output data + * + * Returns 0 on success or -EFAULT. + */ +static int convert_type80(struct zcrypt_device *zdev, + struct ap_message *reply, + char __user *outputdata, + unsigned int outputdatalength) +{ + struct type80_hdr *t80h = reply->message; + unsigned char *data; + + if (t80h->len < sizeof(*t80h) + outputdatalength) { + /* The result is too short, the CEX2A card may not do that.. */ + zdev->online = 0; + return -EAGAIN; /* repeat the request on a different device. */ + } + if (zdev->user_space_type == ZCRYPT_CEX2A) + BUG_ON(t80h->len > CEX2A_MAX_RESPONSE_SIZE); + else + BUG_ON(t80h->len > CEX3A_MAX_RESPONSE_SIZE); + data = reply->message + t80h->len - outputdatalength; + if (copy_to_user(outputdata, data, outputdatalength)) + return -EFAULT; + return 0; +} + +static int convert_response(struct zcrypt_device *zdev, + struct ap_message *reply, + char __user *outputdata, + unsigned int outputdatalength) +{ + /* Response type byte is the second byte in the response. */ + switch (((unsigned char *) reply->message)[1]) { + case TYPE82_RSP_CODE: + case TYPE88_RSP_CODE: + return convert_error(zdev, reply); + case TYPE80_RSP_CODE: + return convert_type80(zdev, reply, + outputdata, outputdatalength); + default: /* Unknown response type, this should NEVER EVER happen */ + zdev->online = 0; + return -EAGAIN; /* repeat the request on a different device. */ + } +} + +/** + * This function is called from the AP bus code after a crypto request + * "msg" has finished with the reply message "reply". + * It is called from tasklet context. + * @ap_dev: pointer to the AP device + * @msg: pointer to the AP message + * @reply: pointer to the AP reply message + */ +static void zcrypt_cex2a_receive(struct ap_device *ap_dev, + struct ap_message *msg, + struct ap_message *reply) +{ + static struct error_hdr error_reply = { + .type = TYPE82_RSP_CODE, + .reply_code = REP82_ERROR_MACHINE_FAILURE, + }; + struct type80_hdr *t80h; + int length; + + /* Copy the reply message to the request message buffer. */ + if (IS_ERR(reply)) { + memcpy(msg->message, &error_reply, sizeof(error_reply)); + goto out; + } + t80h = reply->message; + if (t80h->type == TYPE80_RSP_CODE) { + if (ap_dev->device_type == AP_DEVICE_TYPE_CEX2A) + length = min(CEX2A_MAX_RESPONSE_SIZE, (int) t80h->len); + else + length = min(CEX3A_MAX_RESPONSE_SIZE, (int) t80h->len); + memcpy(msg->message, reply->message, length); + } else + memcpy(msg->message, reply->message, sizeof error_reply); +out: + complete((struct completion *) msg->private); +} + +static atomic_t zcrypt_step = ATOMIC_INIT(0); + +/** + * The request distributor calls this function if it picked the CEX2A + * device to handle a modexpo request. + * @zdev: pointer to zcrypt_device structure that identifies the + * CEX2A device to the request distributor + * @mex: pointer to the modexpo request buffer + */ +static long zcrypt_cex2a_modexpo(struct zcrypt_device *zdev, + struct ica_rsa_modexpo *mex) +{ + struct ap_message ap_msg; + struct completion work; + int rc; + + ap_init_message(&ap_msg); + if (zdev->user_space_type == ZCRYPT_CEX2A) + ap_msg.message = kmalloc(CEX2A_MAX_MESSAGE_SIZE, GFP_KERNEL); + else + ap_msg.message = kmalloc(CEX3A_MAX_MESSAGE_SIZE, GFP_KERNEL); + if (!ap_msg.message) + return -ENOMEM; + ap_msg.receive = zcrypt_cex2a_receive; + ap_msg.psmid = (((unsigned long long) current->pid) << 32) + + atomic_inc_return(&zcrypt_step); + ap_msg.private = &work; + rc = ICAMEX_msg_to_type50MEX_msg(zdev, &ap_msg, mex); + if (rc) + goto out_free; + init_completion(&work); + ap_queue_message(zdev->ap_dev, &ap_msg); + rc = wait_for_completion_interruptible(&work); + if (rc == 0) + rc = convert_response(zdev, &ap_msg, mex->outputdata, + mex->outputdatalength); + else + /* Signal pending. */ + ap_cancel_message(zdev->ap_dev, &ap_msg); +out_free: + kfree(ap_msg.message); + return rc; +} + +/** + * The request distributor calls this function if it picked the CEX2A + * device to handle a modexpo_crt request. + * @zdev: pointer to zcrypt_device structure that identifies the + * CEX2A device to the request distributor + * @crt: pointer to the modexpoc_crt request buffer + */ +static long zcrypt_cex2a_modexpo_crt(struct zcrypt_device *zdev, + struct ica_rsa_modexpo_crt *crt) +{ + struct ap_message ap_msg; + struct completion work; + int rc; + + ap_init_message(&ap_msg); + if (zdev->user_space_type == ZCRYPT_CEX2A) + ap_msg.message = kmalloc(CEX2A_MAX_MESSAGE_SIZE, GFP_KERNEL); + else + ap_msg.message = kmalloc(CEX3A_MAX_MESSAGE_SIZE, GFP_KERNEL); + if (!ap_msg.message) + return -ENOMEM; + ap_msg.receive = zcrypt_cex2a_receive; + ap_msg.psmid = (((unsigned long long) current->pid) << 32) + + atomic_inc_return(&zcrypt_step); + ap_msg.private = &work; + rc = ICACRT_msg_to_type50CRT_msg(zdev, &ap_msg, crt); + if (rc) + goto out_free; + init_completion(&work); + ap_queue_message(zdev->ap_dev, &ap_msg); + rc = wait_for_completion_interruptible(&work); + if (rc == 0) + rc = convert_response(zdev, &ap_msg, crt->outputdata, + crt->outputdatalength); + else + /* Signal pending. */ + ap_cancel_message(zdev->ap_dev, &ap_msg); +out_free: + kfree(ap_msg.message); + return rc; +} + +/** + * The crypto operations for a CEX2A card. + */ +static struct zcrypt_ops zcrypt_cex2a_ops = { + .rsa_modexpo = zcrypt_cex2a_modexpo, + .rsa_modexpo_crt = zcrypt_cex2a_modexpo_crt, +}; + /** * Probe function for CEX2A cards. It always accepts the AP device * since the bus_match already checked the hardware type. @@ -111,8 +449,7 @@ static int zcrypt_cex2a_probe(struct ap_device *ap_dev) zdev->min_mod_size = CEX2A_MIN_MOD_SIZE; zdev->max_mod_size = CEX2A_MAX_MOD_SIZE; zdev->max_exp_bit_length = CEX2A_MAX_MOD_SIZE; - if (ap_test_bit(&ap_dev->functions, AP_FUNC_MEX4K) && - ap_test_bit(&ap_dev->functions, AP_FUNC_CRT4K)) { + if (ap_4096_commands_available(ap_dev->qid)) { zdev->max_mod_size = CEX3A_MAX_MOD_SIZE; zdev->max_exp_bit_length = CEX3A_MAX_MOD_SIZE; } @@ -120,18 +457,16 @@ static int zcrypt_cex2a_probe(struct ap_device *ap_dev) zdev->speed_rating = CEX3A_SPEED_RATING; break; } - if (!zdev) - return -ENODEV; - zdev->ops = zcrypt_msgtype_request(MSGTYPE50_NAME, - MSGTYPE50_VARIANT_DEFAULT); - zdev->ap_dev = ap_dev; - zdev->online = 1; - ap_dev->reply = &zdev->reply; - ap_dev->private = zdev; - rc = zcrypt_device_register(zdev); + if (zdev != NULL) { + zdev->ap_dev = ap_dev; + zdev->ops = &zcrypt_cex2a_ops; + zdev->online = 1; + ap_dev->reply = &zdev->reply; + ap_dev->private = zdev; + rc = zcrypt_device_register(zdev); + } if (rc) { ap_dev->private = NULL; - zcrypt_msgtype_release(zdev->ops); zcrypt_device_free(zdev); } return rc; @@ -144,10 +479,8 @@ static int zcrypt_cex2a_probe(struct ap_device *ap_dev) static void zcrypt_cex2a_remove(struct ap_device *ap_dev) { struct zcrypt_device *zdev = ap_dev->private; - struct zcrypt_ops *zops = zdev->ops; zcrypt_device_unregister(zdev); - zcrypt_msgtype_release(zops); } int __init zcrypt_cex2a_init(void) diff --git a/trunk/drivers/s390/crypto/zcrypt_cex4.c b/trunk/drivers/s390/crypto/zcrypt_cex4.c deleted file mode 100644 index ce1226398ac9..000000000000 --- a/trunk/drivers/s390/crypto/zcrypt_cex4.c +++ /dev/null @@ -1,149 +0,0 @@ -/* - * Copyright IBM Corp. 2012 - * Author(s): Holger Dengler - */ - -#include -#include -#include -#include -#include -#include - -#include "ap_bus.h" -#include "zcrypt_api.h" -#include "zcrypt_msgtype6.h" -#include "zcrypt_msgtype50.h" -#include "zcrypt_error.h" -#include "zcrypt_cex4.h" - -#define CEX4A_MIN_MOD_SIZE 1 /* 8 bits */ -#define CEX4A_MAX_MOD_SIZE_2K 256 /* 2048 bits */ -#define CEX4A_MAX_MOD_SIZE_4K 512 /* 4096 bits */ - -#define CEX4C_MIN_MOD_SIZE 16 /* 256 bits */ -#define CEX4C_MAX_MOD_SIZE 512 /* 4096 bits */ - -#define CEX4A_SPEED_RATING 900 /* TODO new card, new speed rating */ -#define CEX4C_SPEED_RATING 6500 /* TODO new card, new speed rating */ - -#define CEX4A_MAX_MESSAGE_SIZE MSGTYPE50_CRB3_MAX_MSG_SIZE -#define CEX4C_MAX_MESSAGE_SIZE MSGTYPE06_MAX_MSG_SIZE - -#define CEX4_CLEANUP_TIME (15*HZ) - -static struct ap_device_id zcrypt_cex4_ids[] = { - { AP_DEVICE(AP_DEVICE_TYPE_CEX4) }, - { /* end of list */ }, -}; - -MODULE_DEVICE_TABLE(ap, zcrypt_cex4_ids); -MODULE_AUTHOR("IBM Corporation"); -MODULE_DESCRIPTION("CEX4 Cryptographic Card device driver, " \ - "Copyright IBM Corp. 2012"); -MODULE_LICENSE("GPL"); - -static int zcrypt_cex4_probe(struct ap_device *ap_dev); -static void zcrypt_cex4_remove(struct ap_device *ap_dev); - -static struct ap_driver zcrypt_cex4_driver = { - .probe = zcrypt_cex4_probe, - .remove = zcrypt_cex4_remove, - .ids = zcrypt_cex4_ids, - .request_timeout = CEX4_CLEANUP_TIME, -}; - -/** - * Probe function for CEX4 cards. It always accepts the AP device - * since the bus_match already checked the hardware type. - * @ap_dev: pointer to the AP device. - */ -static int zcrypt_cex4_probe(struct ap_device *ap_dev) -{ - struct zcrypt_device *zdev = NULL; - int rc = 0; - - switch (ap_dev->device_type) { - case AP_DEVICE_TYPE_CEX4: - if (ap_test_bit(&ap_dev->functions, AP_FUNC_ACCEL)) { - zdev = zcrypt_device_alloc(CEX4A_MAX_MESSAGE_SIZE); - if (!zdev) - return -ENOMEM; - zdev->type_string = "CEX4A"; - zdev->user_space_type = ZCRYPT_CEX3A; - zdev->min_mod_size = CEX4A_MIN_MOD_SIZE; - if (ap_test_bit(&ap_dev->functions, AP_FUNC_MEX4K) && - ap_test_bit(&ap_dev->functions, AP_FUNC_CRT4K)) { - zdev->max_mod_size = - CEX4A_MAX_MOD_SIZE_4K; - zdev->max_exp_bit_length = - CEX4A_MAX_MOD_SIZE_4K; - } else { - zdev->max_mod_size = - CEX4A_MAX_MOD_SIZE_2K; - zdev->max_exp_bit_length = - CEX4A_MAX_MOD_SIZE_2K; - } - zdev->short_crt = 1; - zdev->speed_rating = CEX4A_SPEED_RATING; - zdev->ops = zcrypt_msgtype_request(MSGTYPE50_NAME, - MSGTYPE50_VARIANT_DEFAULT); - } else if (ap_test_bit(&ap_dev->functions, AP_FUNC_COPRO)) { - zdev = zcrypt_device_alloc(CEX4C_MAX_MESSAGE_SIZE); - if (!zdev) - return -ENOMEM; - zdev->type_string = "CEX4C"; - zdev->user_space_type = ZCRYPT_CEX3C; - zdev->min_mod_size = CEX4C_MIN_MOD_SIZE; - zdev->max_mod_size = CEX4C_MAX_MOD_SIZE; - zdev->max_exp_bit_length = CEX4C_MAX_MOD_SIZE; - zdev->short_crt = 0; - zdev->speed_rating = CEX4C_SPEED_RATING; - zdev->ops = zcrypt_msgtype_request(MSGTYPE06_NAME, - MSGTYPE06_VARIANT_DEFAULT); - } - break; - } - if (!zdev) - return -ENODEV; - zdev->ap_dev = ap_dev; - zdev->online = 1; - ap_dev->reply = &zdev->reply; - ap_dev->private = zdev; - rc = zcrypt_device_register(zdev); - if (rc) { - zcrypt_msgtype_release(zdev->ops); - ap_dev->private = NULL; - zcrypt_device_free(zdev); - } - return rc; -} - -/** - * This is called to remove the extended CEX4 driver information - * if an AP device is removed. - */ -static void zcrypt_cex4_remove(struct ap_device *ap_dev) -{ - struct zcrypt_device *zdev = ap_dev->private; - struct zcrypt_ops *zops; - - if (zdev) { - zops = zdev->ops; - zcrypt_device_unregister(zdev); - zcrypt_msgtype_release(zops); - } -} - -int __init zcrypt_cex4_init(void) -{ - return ap_driver_register(&zcrypt_cex4_driver, THIS_MODULE, "cex4"); -} - -void __exit zcrypt_cex4_exit(void) -{ - ap_driver_unregister(&zcrypt_cex4_driver); -} - -module_init(zcrypt_cex4_init); -module_exit(zcrypt_cex4_exit); diff --git a/trunk/drivers/s390/crypto/zcrypt_cex4.h b/trunk/drivers/s390/crypto/zcrypt_cex4.h deleted file mode 100644 index 719571375ccc..000000000000 --- a/trunk/drivers/s390/crypto/zcrypt_cex4.h +++ /dev/null @@ -1,12 +0,0 @@ -/* - * Copyright IBM Corp. 2012 - * Author(s): Holger Dengler - */ - -#ifndef _ZCRYPT_CEX4_H_ -#define _ZCRYPT_CEX4_H_ - -int zcrypt_cex4_init(void); -void zcrypt_cex4_exit(void); - -#endif /* _ZCRYPT_CEX4_H_ */ diff --git a/trunk/drivers/s390/crypto/zcrypt_debug.h b/trunk/drivers/s390/crypto/zcrypt_debug.h deleted file mode 100644 index 841ea72e4a4e..000000000000 --- a/trunk/drivers/s390/crypto/zcrypt_debug.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright IBM Corp. 2012 - * Author(s): Holger Dengler (hd@linux.vnet.ibm.com) - */ -#ifndef ZCRYPT_DEBUG_H -#define ZCRYPT_DEBUG_H - -#include -#include "zcrypt_api.h" - -/* that gives us 15 characters in the text event views */ -#define ZCRYPT_DBF_LEN 16 - -/* sort out low debug levels early to avoid wasted sprints */ -static inline int zcrypt_dbf_passes(debug_info_t *dbf_grp, int level) -{ - return (level <= dbf_grp->level); -} - -#define DBF_ERR 3 /* error conditions */ -#define DBF_WARN 4 /* warning conditions */ -#define DBF_INFO 6 /* informational */ - -#define RC2WARN(rc) ((rc) ? DBF_WARN : DBF_INFO) - -#define ZCRYPT_DBF_COMMON(level, text...) \ - do { \ - if (zcrypt_dbf_passes(zcrypt_dbf_common, level)) { \ - char debug_buffer[ZCRYPT_DBF_LEN]; \ - snprintf(debug_buffer, ZCRYPT_DBF_LEN, text); \ - debug_text_event(zcrypt_dbf_common, level, \ - debug_buffer); \ - } \ - } while (0) - -#define ZCRYPT_DBF_DEVICES(level, text...) \ - do { \ - if (zcrypt_dbf_passes(zcrypt_dbf_devices, level)) { \ - char debug_buffer[ZCRYPT_DBF_LEN]; \ - snprintf(debug_buffer, ZCRYPT_DBF_LEN, text); \ - debug_text_event(zcrypt_dbf_devices, level, \ - debug_buffer); \ - } \ - } while (0) - -#define ZCRYPT_DBF_DEV(level, device, text...) \ - do { \ - if (zcrypt_dbf_passes(device->dbf_area, level)) { \ - char debug_buffer[ZCRYPT_DBF_LEN]; \ - snprintf(debug_buffer, ZCRYPT_DBF_LEN, text); \ - debug_text_event(device->dbf_area, level, \ - debug_buffer); \ - } \ - } while (0) - -int zcrypt_debug_init(void); -void zcrypt_debug_exit(void); - -#endif /* ZCRYPT_DEBUG_H */ diff --git a/trunk/drivers/s390/crypto/zcrypt_error.h b/trunk/drivers/s390/crypto/zcrypt_error.h index 0079b6617211..0965e2626d18 100644 --- a/trunk/drivers/s390/crypto/zcrypt_error.h +++ b/trunk/drivers/s390/crypto/zcrypt_error.h @@ -26,8 +26,6 @@ #ifndef _ZCRYPT_ERROR_H_ #define _ZCRYPT_ERROR_H_ -#include -#include "zcrypt_debug.h" #include "zcrypt_api.h" /** @@ -110,27 +108,16 @@ static inline int convert_error(struct zcrypt_device *zdev, * and then repeat the request. */ WARN_ON(1); - atomic_set(&zcrypt_rescan_req, 1); zdev->online = 0; - ZCRYPT_DBF_DEV(DBF_ERR, zdev, "dev%04xo%drc%d", - zdev->ap_dev->qid, - zdev->online, ehdr->reply_code); return -EAGAIN; case REP82_ERROR_TRANSPORT_FAIL: case REP82_ERROR_MACHINE_FAILURE: // REP88_ERROR_MODULE_FAILURE // '10' CEX2A /* If a card fails disable it and repeat the request. */ - atomic_set(&zcrypt_rescan_req, 1); zdev->online = 0; - ZCRYPT_DBF_DEV(DBF_ERR, zdev, "dev%04xo%drc%d", - zdev->ap_dev->qid, - zdev->online, ehdr->reply_code); return -EAGAIN; default: zdev->online = 0; - ZCRYPT_DBF_DEV(DBF_ERR, zdev, "dev%04xo%drc%d", - zdev->ap_dev->qid, - zdev->online, ehdr->reply_code); return -EAGAIN; /* repeat the request on a different device. */ } } diff --git a/trunk/drivers/s390/crypto/zcrypt_msgtype50.c b/trunk/drivers/s390/crypto/zcrypt_msgtype50.c deleted file mode 100644 index 035b6dc31b71..000000000000 --- a/trunk/drivers/s390/crypto/zcrypt_msgtype50.c +++ /dev/null @@ -1,531 +0,0 @@ -/* - * zcrypt 2.1.0 - * - * Copyright IBM Corp. 2001, 2012 - * Author(s): Robert Burroughs - * Eric Rossman (edrossma@us.ibm.com) - * - * Hotplug & misc device support: Jochen Roehrig (roehrig@de.ibm.com) - * Major cleanup & driver split: Martin Schwidefsky - * Ralph Wuerthner - * MSGTYPE restruct: Holger Dengler - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include -#include -#include -#include - -#include "ap_bus.h" -#include "zcrypt_api.h" -#include "zcrypt_error.h" -#include "zcrypt_msgtype50.h" - -#define CEX3A_MAX_MOD_SIZE 512 /* 4096 bits */ - -#define CEX2A_MAX_RESPONSE_SIZE 0x110 /* max outputdatalength + type80_hdr */ - -#define CEX3A_MAX_RESPONSE_SIZE 0x210 /* 512 bit modulus - * (max outputdatalength) + - * type80_hdr*/ - -MODULE_AUTHOR("IBM Corporation"); -MODULE_DESCRIPTION("Cryptographic Accelerator (message type 50), " \ - "Copyright IBM Corp. 2001, 2012"); -MODULE_LICENSE("GPL"); - -static void zcrypt_cex2a_receive(struct ap_device *, struct ap_message *, - struct ap_message *); - -/** - * The type 50 message family is associated with a CEX2A card. - * - * The four members of the family are described below. - * - * Note that all unsigned char arrays are right-justified and left-padded - * with zeroes. - * - * Note that all reserved fields must be zeroes. - */ -struct type50_hdr { - unsigned char reserved1; - unsigned char msg_type_code; /* 0x50 */ - unsigned short msg_len; - unsigned char reserved2; - unsigned char ignored; - unsigned short reserved3; -} __packed; - -#define TYPE50_TYPE_CODE 0x50 - -#define TYPE50_MEB1_FMT 0x0001 -#define TYPE50_MEB2_FMT 0x0002 -#define TYPE50_MEB3_FMT 0x0003 -#define TYPE50_CRB1_FMT 0x0011 -#define TYPE50_CRB2_FMT 0x0012 -#define TYPE50_CRB3_FMT 0x0013 - -/* Mod-Exp, with a small modulus */ -struct type50_meb1_msg { - struct type50_hdr header; - unsigned short keyblock_type; /* 0x0001 */ - unsigned char reserved[6]; - unsigned char exponent[128]; - unsigned char modulus[128]; - unsigned char message[128]; -} __packed; - -/* Mod-Exp, with a large modulus */ -struct type50_meb2_msg { - struct type50_hdr header; - unsigned short keyblock_type; /* 0x0002 */ - unsigned char reserved[6]; - unsigned char exponent[256]; - unsigned char modulus[256]; - unsigned char message[256]; -} __packed; - -/* Mod-Exp, with a larger modulus */ -struct type50_meb3_msg { - struct type50_hdr header; - unsigned short keyblock_type; /* 0x0003 */ - unsigned char reserved[6]; - unsigned char exponent[512]; - unsigned char modulus[512]; - unsigned char message[512]; -} __packed; - -/* CRT, with a small modulus */ -struct type50_crb1_msg { - struct type50_hdr header; - unsigned short keyblock_type; /* 0x0011 */ - unsigned char reserved[6]; - unsigned char p[64]; - unsigned char q[64]; - unsigned char dp[64]; - unsigned char dq[64]; - unsigned char u[64]; - unsigned char message[128]; -} __packed; - -/* CRT, with a large modulus */ -struct type50_crb2_msg { - struct type50_hdr header; - unsigned short keyblock_type; /* 0x0012 */ - unsigned char reserved[6]; - unsigned char p[128]; - unsigned char q[128]; - unsigned char dp[128]; - unsigned char dq[128]; - unsigned char u[128]; - unsigned char message[256]; -} __packed; - -/* CRT, with a larger modulus */ -struct type50_crb3_msg { - struct type50_hdr header; - unsigned short keyblock_type; /* 0x0013 */ - unsigned char reserved[6]; - unsigned char p[256]; - unsigned char q[256]; - unsigned char dp[256]; - unsigned char dq[256]; - unsigned char u[256]; - unsigned char message[512]; -} __packed; - -/** - * The type 80 response family is associated with a CEX2A card. - * - * Note that all unsigned char arrays are right-justified and left-padded - * with zeroes. - * - * Note that all reserved fields must be zeroes. - */ - -#define TYPE80_RSP_CODE 0x80 - -struct type80_hdr { - unsigned char reserved1; - unsigned char type; /* 0x80 */ - unsigned short len; - unsigned char code; /* 0x00 */ - unsigned char reserved2[3]; - unsigned char reserved3[8]; -} __packed; - -/** - * Convert a ICAMEX message to a type50 MEX message. - * - * @zdev: crypto device pointer - * @zreq: crypto request pointer - * @mex: pointer to user input data - * - * Returns 0 on success or -EFAULT. - */ -static int ICAMEX_msg_to_type50MEX_msg(struct zcrypt_device *zdev, - struct ap_message *ap_msg, - struct ica_rsa_modexpo *mex) -{ - unsigned char *mod, *exp, *inp; - int mod_len; - - mod_len = mex->inputdatalength; - - if (mod_len <= 128) { - struct type50_meb1_msg *meb1 = ap_msg->message; - memset(meb1, 0, sizeof(*meb1)); - ap_msg->length = sizeof(*meb1); - meb1->header.msg_type_code = TYPE50_TYPE_CODE; - meb1->header.msg_len = sizeof(*meb1); - meb1->keyblock_type = TYPE50_MEB1_FMT; - mod = meb1->modulus + sizeof(meb1->modulus) - mod_len; - exp = meb1->exponent + sizeof(meb1->exponent) - mod_len; - inp = meb1->message + sizeof(meb1->message) - mod_len; - } else if (mod_len <= 256) { - struct type50_meb2_msg *meb2 = ap_msg->message; - memset(meb2, 0, sizeof(*meb2)); - ap_msg->length = sizeof(*meb2); - meb2->header.msg_type_code = TYPE50_TYPE_CODE; - meb2->header.msg_len = sizeof(*meb2); - meb2->keyblock_type = TYPE50_MEB2_FMT; - mod = meb2->modulus + sizeof(meb2->modulus) - mod_len; - exp = meb2->exponent + sizeof(meb2->exponent) - mod_len; - inp = meb2->message + sizeof(meb2->message) - mod_len; - } else { - /* mod_len > 256 = 4096 bit RSA Key */ - struct type50_meb3_msg *meb3 = ap_msg->message; - memset(meb3, 0, sizeof(*meb3)); - ap_msg->length = sizeof(*meb3); - meb3->header.msg_type_code = TYPE50_TYPE_CODE; - meb3->header.msg_len = sizeof(*meb3); - meb3->keyblock_type = TYPE50_MEB3_FMT; - mod = meb3->modulus + sizeof(meb3->modulus) - mod_len; - exp = meb3->exponent + sizeof(meb3->exponent) - mod_len; - inp = meb3->message + sizeof(meb3->message) - mod_len; - } - - if (copy_from_user(mod, mex->n_modulus, mod_len) || - copy_from_user(exp, mex->b_key, mod_len) || - copy_from_user(inp, mex->inputdata, mod_len)) - return -EFAULT; - return 0; -} - -/** - * Convert a ICACRT message to a type50 CRT message. - * - * @zdev: crypto device pointer - * @zreq: crypto request pointer - * @crt: pointer to user input data - * - * Returns 0 on success or -EFAULT. - */ -static int ICACRT_msg_to_type50CRT_msg(struct zcrypt_device *zdev, - struct ap_message *ap_msg, - struct ica_rsa_modexpo_crt *crt) -{ - int mod_len, short_len, long_len, long_offset, limit; - unsigned char *p, *q, *dp, *dq, *u, *inp; - - mod_len = crt->inputdatalength; - short_len = mod_len / 2; - long_len = mod_len / 2 + 8; - - /* - * CEX2A cannot handle p, dp, or U > 128 bytes. - * If we have one of these, we need to do extra checking. - * For CEX3A the limit is 256 bytes. - */ - if (zdev->max_mod_size == CEX3A_MAX_MOD_SIZE) - limit = 256; - else - limit = 128; - - if (long_len > limit) { - /* - * zcrypt_rsa_crt already checked for the leading - * zeroes of np_prime, bp_key and u_mult_inc. - */ - long_offset = long_len - limit; - long_len = limit; - } else - long_offset = 0; - - /* - * Instead of doing extra work for p, dp, U > 64 bytes, we'll just use - * the larger message structure. - */ - if (long_len <= 64) { - struct type50_crb1_msg *crb1 = ap_msg->message; - memset(crb1, 0, sizeof(*crb1)); - ap_msg->length = sizeof(*crb1); - crb1->header.msg_type_code = TYPE50_TYPE_CODE; - crb1->header.msg_len = sizeof(*crb1); - crb1->keyblock_type = TYPE50_CRB1_FMT; - p = crb1->p + sizeof(crb1->p) - long_len; - q = crb1->q + sizeof(crb1->q) - short_len; - dp = crb1->dp + sizeof(crb1->dp) - long_len; - dq = crb1->dq + sizeof(crb1->dq) - short_len; - u = crb1->u + sizeof(crb1->u) - long_len; - inp = crb1->message + sizeof(crb1->message) - mod_len; - } else if (long_len <= 128) { - struct type50_crb2_msg *crb2 = ap_msg->message; - memset(crb2, 0, sizeof(*crb2)); - ap_msg->length = sizeof(*crb2); - crb2->header.msg_type_code = TYPE50_TYPE_CODE; - crb2->header.msg_len = sizeof(*crb2); - crb2->keyblock_type = TYPE50_CRB2_FMT; - p = crb2->p + sizeof(crb2->p) - long_len; - q = crb2->q + sizeof(crb2->q) - short_len; - dp = crb2->dp + sizeof(crb2->dp) - long_len; - dq = crb2->dq + sizeof(crb2->dq) - short_len; - u = crb2->u + sizeof(crb2->u) - long_len; - inp = crb2->message + sizeof(crb2->message) - mod_len; - } else { - /* long_len >= 256 */ - struct type50_crb3_msg *crb3 = ap_msg->message; - memset(crb3, 0, sizeof(*crb3)); - ap_msg->length = sizeof(*crb3); - crb3->header.msg_type_code = TYPE50_TYPE_CODE; - crb3->header.msg_len = sizeof(*crb3); - crb3->keyblock_type = TYPE50_CRB3_FMT; - p = crb3->p + sizeof(crb3->p) - long_len; - q = crb3->q + sizeof(crb3->q) - short_len; - dp = crb3->dp + sizeof(crb3->dp) - long_len; - dq = crb3->dq + sizeof(crb3->dq) - short_len; - u = crb3->u + sizeof(crb3->u) - long_len; - inp = crb3->message + sizeof(crb3->message) - mod_len; - } - - if (copy_from_user(p, crt->np_prime + long_offset, long_len) || - copy_from_user(q, crt->nq_prime, short_len) || - copy_from_user(dp, crt->bp_key + long_offset, long_len) || - copy_from_user(dq, crt->bq_key, short_len) || - copy_from_user(u, crt->u_mult_inv + long_offset, long_len) || - copy_from_user(inp, crt->inputdata, mod_len)) - return -EFAULT; - - return 0; -} - -/** - * Copy results from a type 80 reply message back to user space. - * - * @zdev: crypto device pointer - * @reply: reply AP message. - * @data: pointer to user output data - * @length: size of user output data - * - * Returns 0 on success or -EFAULT. - */ -static int convert_type80(struct zcrypt_device *zdev, - struct ap_message *reply, - char __user *outputdata, - unsigned int outputdatalength) -{ - struct type80_hdr *t80h = reply->message; - unsigned char *data; - - if (t80h->len < sizeof(*t80h) + outputdatalength) { - /* The result is too short, the CEX2A card may not do that.. */ - zdev->online = 0; - return -EAGAIN; /* repeat the request on a different device. */ - } - if (zdev->user_space_type == ZCRYPT_CEX2A) - BUG_ON(t80h->len > CEX2A_MAX_RESPONSE_SIZE); - else - BUG_ON(t80h->len > CEX3A_MAX_RESPONSE_SIZE); - data = reply->message + t80h->len - outputdatalength; - if (copy_to_user(outputdata, data, outputdatalength)) - return -EFAULT; - return 0; -} - -static int convert_response(struct zcrypt_device *zdev, - struct ap_message *reply, - char __user *outputdata, - unsigned int outputdatalength) -{ - /* Response type byte is the second byte in the response. */ - switch (((unsigned char *) reply->message)[1]) { - case TYPE82_RSP_CODE: - case TYPE88_RSP_CODE: - return convert_error(zdev, reply); - case TYPE80_RSP_CODE: - return convert_type80(zdev, reply, - outputdata, outputdatalength); - default: /* Unknown response type, this should NEVER EVER happen */ - zdev->online = 0; - return -EAGAIN; /* repeat the request on a different device. */ - } -} - -/** - * This function is called from the AP bus code after a crypto request - * "msg" has finished with the reply message "reply". - * It is called from tasklet context. - * @ap_dev: pointer to the AP device - * @msg: pointer to the AP message - * @reply: pointer to the AP reply message - */ -static void zcrypt_cex2a_receive(struct ap_device *ap_dev, - struct ap_message *msg, - struct ap_message *reply) -{ - static struct error_hdr error_reply = { - .type = TYPE82_RSP_CODE, - .reply_code = REP82_ERROR_MACHINE_FAILURE, - }; - struct type80_hdr *t80h; - int length; - - /* Copy the reply message to the request message buffer. */ - if (IS_ERR(reply)) { - memcpy(msg->message, &error_reply, sizeof(error_reply)); - goto out; - } - t80h = reply->message; - if (t80h->type == TYPE80_RSP_CODE) { - if (ap_dev->device_type == AP_DEVICE_TYPE_CEX2A) - length = min_t(int, - CEX2A_MAX_RESPONSE_SIZE, t80h->len); - else - length = min_t(int, - CEX3A_MAX_RESPONSE_SIZE, t80h->len); - memcpy(msg->message, reply->message, length); - } else - memcpy(msg->message, reply->message, sizeof(error_reply)); -out: - complete((struct completion *) msg->private); -} - -static atomic_t zcrypt_step = ATOMIC_INIT(0); - -/** - * The request distributor calls this function if it picked the CEX2A - * device to handle a modexpo request. - * @zdev: pointer to zcrypt_device structure that identifies the - * CEX2A device to the request distributor - * @mex: pointer to the modexpo request buffer - */ -static long zcrypt_cex2a_modexpo(struct zcrypt_device *zdev, - struct ica_rsa_modexpo *mex) -{ - struct ap_message ap_msg; - struct completion work; - int rc; - - ap_init_message(&ap_msg); - if (zdev->user_space_type == ZCRYPT_CEX2A) - ap_msg.message = kmalloc(MSGTYPE50_CRB2_MAX_MSG_SIZE, - GFP_KERNEL); - else - ap_msg.message = kmalloc(MSGTYPE50_CRB3_MAX_MSG_SIZE, - GFP_KERNEL); - if (!ap_msg.message) - return -ENOMEM; - ap_msg.receive = zcrypt_cex2a_receive; - ap_msg.psmid = (((unsigned long long) current->pid) << 32) + - atomic_inc_return(&zcrypt_step); - ap_msg.private = &work; - rc = ICAMEX_msg_to_type50MEX_msg(zdev, &ap_msg, mex); - if (rc) - goto out_free; - init_completion(&work); - ap_queue_message(zdev->ap_dev, &ap_msg); - rc = wait_for_completion_interruptible(&work); - if (rc == 0) - rc = convert_response(zdev, &ap_msg, mex->outputdata, - mex->outputdatalength); - else - /* Signal pending. */ - ap_cancel_message(zdev->ap_dev, &ap_msg); -out_free: - kfree(ap_msg.message); - return rc; -} - -/** - * The request distributor calls this function if it picked the CEX2A - * device to handle a modexpo_crt request. - * @zdev: pointer to zcrypt_device structure that identifies the - * CEX2A device to the request distributor - * @crt: pointer to the modexpoc_crt request buffer - */ -static long zcrypt_cex2a_modexpo_crt(struct zcrypt_device *zdev, - struct ica_rsa_modexpo_crt *crt) -{ - struct ap_message ap_msg; - struct completion work; - int rc; - - ap_init_message(&ap_msg); - if (zdev->user_space_type == ZCRYPT_CEX2A) - ap_msg.message = kmalloc(MSGTYPE50_CRB2_MAX_MSG_SIZE, - GFP_KERNEL); - else - ap_msg.message = kmalloc(MSGTYPE50_CRB3_MAX_MSG_SIZE, - GFP_KERNEL); - if (!ap_msg.message) - return -ENOMEM; - ap_msg.receive = zcrypt_cex2a_receive; - ap_msg.psmid = (((unsigned long long) current->pid) << 32) + - atomic_inc_return(&zcrypt_step); - ap_msg.private = &work; - rc = ICACRT_msg_to_type50CRT_msg(zdev, &ap_msg, crt); - if (rc) - goto out_free; - init_completion(&work); - ap_queue_message(zdev->ap_dev, &ap_msg); - rc = wait_for_completion_interruptible(&work); - if (rc == 0) - rc = convert_response(zdev, &ap_msg, crt->outputdata, - crt->outputdatalength); - else - /* Signal pending. */ - ap_cancel_message(zdev->ap_dev, &ap_msg); -out_free: - kfree(ap_msg.message); - return rc; -} - -/** - * The crypto operations for message type 50. - */ -static struct zcrypt_ops zcrypt_msgtype50_ops = { - .rsa_modexpo = zcrypt_cex2a_modexpo, - .rsa_modexpo_crt = zcrypt_cex2a_modexpo_crt, - .owner = THIS_MODULE, - .variant = MSGTYPE50_VARIANT_DEFAULT, -}; - -int __init zcrypt_msgtype50_init(void) -{ - zcrypt_msgtype_register(&zcrypt_msgtype50_ops); - return 0; -} - -void __exit zcrypt_msgtype50_exit(void) -{ - zcrypt_msgtype_unregister(&zcrypt_msgtype50_ops); -} - -module_init(zcrypt_msgtype50_init); -module_exit(zcrypt_msgtype50_exit); diff --git a/trunk/drivers/s390/crypto/zcrypt_msgtype50.h b/trunk/drivers/s390/crypto/zcrypt_msgtype50.h deleted file mode 100644 index e56dc72c7733..000000000000 --- a/trunk/drivers/s390/crypto/zcrypt_msgtype50.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * zcrypt 2.1.0 - * - * Copyright IBM Corp. 2001, 2012 - * Author(s): Robert Burroughs - * Eric Rossman (edrossma@us.ibm.com) - * - * Hotplug & misc device support: Jochen Roehrig (roehrig@de.ibm.com) - * Major cleanup & driver split: Martin Schwidefsky - * MSGTYPE restruct: Holger Dengler - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifndef _ZCRYPT_MSGTYPE50_H_ -#define _ZCRYPT_MSGTYPE50_H_ - -#define MSGTYPE50_NAME "zcrypt_msgtype50" -#define MSGTYPE50_VARIANT_DEFAULT 0 - -#define MSGTYPE50_CRB2_MAX_MSG_SIZE 0x390 /*sizeof(struct type50_crb2_msg)*/ -#define MSGTYPE50_CRB3_MAX_MSG_SIZE 0x710 /*sizeof(struct type50_crb3_msg)*/ - -int zcrypt_msgtype50_init(void); -void zcrypt_msgtype50_exit(void); - -#endif /* _ZCRYPT_MSGTYPE50_H_ */ diff --git a/trunk/drivers/s390/crypto/zcrypt_msgtype6.c b/trunk/drivers/s390/crypto/zcrypt_msgtype6.c deleted file mode 100644 index 7d97fa5a26d0..000000000000 --- a/trunk/drivers/s390/crypto/zcrypt_msgtype6.c +++ /dev/null @@ -1,856 +0,0 @@ -/* - * zcrypt 2.1.0 - * - * Copyright IBM Corp. 2001, 2012 - * Author(s): Robert Burroughs - * Eric Rossman (edrossma@us.ibm.com) - * - * Hotplug & misc device support: Jochen Roehrig (roehrig@de.ibm.com) - * Major cleanup & driver split: Martin Schwidefsky - * Ralph Wuerthner - * MSGTYPE restruct: Holger Dengler - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include -#include -#include -#include -#include - -#include "ap_bus.h" -#include "zcrypt_api.h" -#include "zcrypt_error.h" -#include "zcrypt_msgtype6.h" -#include "zcrypt_cca_key.h" - -#define PCIXCC_MIN_MOD_SIZE_OLD 64 /* 512 bits */ -#define PCIXCC_MAX_ICA_RESPONSE_SIZE 0x77c /* max size type86 v2 reply */ - -#define CEIL4(x) ((((x)+3)/4)*4) - -struct response_type { - struct completion work; - int type; -}; -#define PCIXCC_RESPONSE_TYPE_ICA 0 -#define PCIXCC_RESPONSE_TYPE_XCRB 1 - -MODULE_AUTHOR("IBM Corporation"); -MODULE_DESCRIPTION("Cryptographic Coprocessor (message type 6), " \ - "Copyright IBM Corp. 2001, 2012"); -MODULE_LICENSE("GPL"); - -static void zcrypt_msgtype6_receive(struct ap_device *, struct ap_message *, - struct ap_message *); - -/** - * CPRB - * Note that all shorts, ints and longs are little-endian. - * All pointer fields are 32-bits long, and mean nothing - * - * A request CPRB is followed by a request_parameter_block. - * - * The request (or reply) parameter block is organized thus: - * function code - * VUD block - * key block - */ -struct CPRB { - unsigned short cprb_len; /* CPRB length */ - unsigned char cprb_ver_id; /* CPRB version id. */ - unsigned char pad_000; /* Alignment pad byte. */ - unsigned char srpi_rtcode[4]; /* SRPI return code LELONG */ - unsigned char srpi_verb; /* SRPI verb type */ - unsigned char flags; /* flags */ - unsigned char func_id[2]; /* function id */ - unsigned char checkpoint_flag; /* */ - unsigned char resv2; /* reserved */ - unsigned short req_parml; /* request parameter buffer */ - /* length 16-bit little endian */ - unsigned char req_parmp[4]; /* request parameter buffer * - * pointer (means nothing: the * - * parameter buffer follows * - * the CPRB). */ - unsigned char req_datal[4]; /* request data buffer */ - /* length ULELONG */ - unsigned char req_datap[4]; /* request data buffer */ - /* pointer */ - unsigned short rpl_parml; /* reply parameter buffer */ - /* length 16-bit little endian */ - unsigned char pad_001[2]; /* Alignment pad bytes. ULESHORT */ - unsigned char rpl_parmp[4]; /* reply parameter buffer * - * pointer (means nothing: the * - * parameter buffer follows * - * the CPRB). */ - unsigned char rpl_datal[4]; /* reply data buffer len ULELONG */ - unsigned char rpl_datap[4]; /* reply data buffer */ - /* pointer */ - unsigned short ccp_rscode; /* server reason code ULESHORT */ - unsigned short ccp_rtcode; /* server return code ULESHORT */ - unsigned char repd_parml[2]; /* replied parameter len ULESHORT*/ - unsigned char mac_data_len[2]; /* Mac Data Length ULESHORT */ - unsigned char repd_datal[4]; /* replied data length ULELONG */ - unsigned char req_pc[2]; /* PC identifier */ - unsigned char res_origin[8]; /* resource origin */ - unsigned char mac_value[8]; /* Mac Value */ - unsigned char logon_id[8]; /* Logon Identifier */ - unsigned char usage_domain[2]; /* cdx */ - unsigned char resv3[18]; /* reserved for requestor */ - unsigned short svr_namel; /* server name length ULESHORT */ - unsigned char svr_name[8]; /* server name */ -} __packed; - -struct function_and_rules_block { - unsigned char function_code[2]; - unsigned short ulen; - unsigned char only_rule[8]; -} __packed; - -/** - * The following is used to initialize the CPRBX passed to the PCIXCC/CEX2C - * card in a type6 message. The 3 fields that must be filled in at execution - * time are req_parml, rpl_parml and usage_domain. - * Everything about this interface is ascii/big-endian, since the - * device does *not* have 'Intel inside'. - * - * The CPRBX is followed immediately by the parm block. - * The parm block contains: - * - function code ('PD' 0x5044 or 'PK' 0x504B) - * - rule block (one of:) - * + 0x000A 'PKCS-1.2' (MCL2 'PD') - * + 0x000A 'ZERO-PAD' (MCL2 'PK') - * + 0x000A 'ZERO-PAD' (MCL3 'PD' or CEX2C 'PD') - * + 0x000A 'MRP ' (MCL3 'PK' or CEX2C 'PK') - * - VUD block - */ -static struct CPRBX static_cprbx = { - .cprb_len = 0x00DC, - .cprb_ver_id = 0x02, - .func_id = {0x54, 0x32}, -}; - -/** - * Convert a ICAMEX message to a type6 MEX message. - * - * @zdev: crypto device pointer - * @ap_msg: pointer to AP message - * @mex: pointer to user input data - * - * Returns 0 on success or -EFAULT. - */ -static int ICAMEX_msg_to_type6MEX_msgX(struct zcrypt_device *zdev, - struct ap_message *ap_msg, - struct ica_rsa_modexpo *mex) -{ - static struct type6_hdr static_type6_hdrX = { - .type = 0x06, - .offset1 = 0x00000058, - .agent_id = {'C', 'A',}, - .function_code = {'P', 'K'}, - }; - static struct function_and_rules_block static_pke_fnr = { - .function_code = {'P', 'K'}, - .ulen = 10, - .only_rule = {'M', 'R', 'P', ' ', ' ', ' ', ' ', ' '} - }; - static struct function_and_rules_block static_pke_fnr_MCL2 = { - .function_code = {'P', 'K'}, - .ulen = 10, - .only_rule = {'Z', 'E', 'R', 'O', '-', 'P', 'A', 'D'} - }; - struct { - struct type6_hdr hdr; - struct CPRBX cprbx; - struct function_and_rules_block fr; - unsigned short length; - char text[0]; - } __packed * msg = ap_msg->message; - int size; - - /* VUD.ciphertext */ - msg->length = mex->inputdatalength + 2; - if (copy_from_user(msg->text, mex->inputdata, mex->inputdatalength)) - return -EFAULT; - - /* Set up key which is located after the variable length text. */ - size = zcrypt_type6_mex_key_en(mex, msg->text+mex->inputdatalength, 1); - if (size < 0) - return size; - size += sizeof(*msg) + mex->inputdatalength; - - /* message header, cprbx and f&r */ - msg->hdr = static_type6_hdrX; - msg->hdr.ToCardLen1 = size - sizeof(msg->hdr); - msg->hdr.FromCardLen1 = PCIXCC_MAX_ICA_RESPONSE_SIZE - sizeof(msg->hdr); - - msg->cprbx = static_cprbx; - msg->cprbx.domain = AP_QID_QUEUE(zdev->ap_dev->qid); - msg->cprbx.rpl_msgbl = msg->hdr.FromCardLen1; - - msg->fr = (zdev->user_space_type == ZCRYPT_PCIXCC_MCL2) ? - static_pke_fnr_MCL2 : static_pke_fnr; - - msg->cprbx.req_parml = size - sizeof(msg->hdr) - sizeof(msg->cprbx); - - ap_msg->length = size; - return 0; -} - -/** - * Convert a ICACRT message to a type6 CRT message. - * - * @zdev: crypto device pointer - * @ap_msg: pointer to AP message - * @crt: pointer to user input data - * - * Returns 0 on success or -EFAULT. - */ -static int ICACRT_msg_to_type6CRT_msgX(struct zcrypt_device *zdev, - struct ap_message *ap_msg, - struct ica_rsa_modexpo_crt *crt) -{ - static struct type6_hdr static_type6_hdrX = { - .type = 0x06, - .offset1 = 0x00000058, - .agent_id = {'C', 'A',}, - .function_code = {'P', 'D'}, - }; - static struct function_and_rules_block static_pkd_fnr = { - .function_code = {'P', 'D'}, - .ulen = 10, - .only_rule = {'Z', 'E', 'R', 'O', '-', 'P', 'A', 'D'} - }; - - static struct function_and_rules_block static_pkd_fnr_MCL2 = { - .function_code = {'P', 'D'}, - .ulen = 10, - .only_rule = {'P', 'K', 'C', 'S', '-', '1', '.', '2'} - }; - struct { - struct type6_hdr hdr; - struct CPRBX cprbx; - struct function_and_rules_block fr; - unsigned short length; - char text[0]; - } __packed * msg = ap_msg->message; - int size; - - /* VUD.ciphertext */ - msg->length = crt->inputdatalength + 2; - if (copy_from_user(msg->text, crt->inputdata, crt->inputdatalength)) - return -EFAULT; - - /* Set up key which is located after the variable length text. */ - size = zcrypt_type6_crt_key(crt, msg->text + crt->inputdatalength, 1); - if (size < 0) - return size; - size += sizeof(*msg) + crt->inputdatalength; /* total size of msg */ - - /* message header, cprbx and f&r */ - msg->hdr = static_type6_hdrX; - msg->hdr.ToCardLen1 = size - sizeof(msg->hdr); - msg->hdr.FromCardLen1 = PCIXCC_MAX_ICA_RESPONSE_SIZE - sizeof(msg->hdr); - - msg->cprbx = static_cprbx; - msg->cprbx.domain = AP_QID_QUEUE(zdev->ap_dev->qid); - msg->cprbx.req_parml = msg->cprbx.rpl_msgbl = - size - sizeof(msg->hdr) - sizeof(msg->cprbx); - - msg->fr = (zdev->user_space_type == ZCRYPT_PCIXCC_MCL2) ? - static_pkd_fnr_MCL2 : static_pkd_fnr; - - ap_msg->length = size; - return 0; -} - -/** - * Convert a XCRB message to a type6 CPRB message. - * - * @zdev: crypto device pointer - * @ap_msg: pointer to AP message - * @xcRB: pointer to user input data - * - * Returns 0 on success or -EFAULT, -EINVAL. - */ -struct type86_fmt2_msg { - struct type86_hdr hdr; - struct type86_fmt2_ext fmt2; -} __packed; - -static int XCRB_msg_to_type6CPRB_msgX(struct zcrypt_device *zdev, - struct ap_message *ap_msg, - struct ica_xcRB *xcRB) -{ - static struct type6_hdr static_type6_hdrX = { - .type = 0x06, - .offset1 = 0x00000058, - }; - struct { - struct type6_hdr hdr; - struct CPRBX cprbx; - } __packed * msg = ap_msg->message; - - int rcblen = CEIL4(xcRB->request_control_blk_length); - int replylen; - char *req_data = ap_msg->message + sizeof(struct type6_hdr) + rcblen; - char *function_code; - - /* length checks */ - ap_msg->length = sizeof(struct type6_hdr) + - CEIL4(xcRB->request_control_blk_length) + - xcRB->request_data_length; - if (ap_msg->length > MSGTYPE06_MAX_MSG_SIZE) - return -EINVAL; - replylen = sizeof(struct type86_fmt2_msg) + - CEIL4(xcRB->reply_control_blk_length) + - xcRB->reply_data_length; - if (replylen > MSGTYPE06_MAX_MSG_SIZE) - return -EINVAL; - - /* prepare type6 header */ - msg->hdr = static_type6_hdrX; - memcpy(msg->hdr.agent_id , &(xcRB->agent_ID), sizeof(xcRB->agent_ID)); - msg->hdr.ToCardLen1 = xcRB->request_control_blk_length; - if (xcRB->request_data_length) { - msg->hdr.offset2 = msg->hdr.offset1 + rcblen; - msg->hdr.ToCardLen2 = xcRB->request_data_length; - } - msg->hdr.FromCardLen1 = xcRB->reply_control_blk_length; - msg->hdr.FromCardLen2 = xcRB->reply_data_length; - - /* prepare CPRB */ - if (copy_from_user(&(msg->cprbx), xcRB->request_control_blk_addr, - xcRB->request_control_blk_length)) - return -EFAULT; - if (msg->cprbx.cprb_len + sizeof(msg->hdr.function_code) > - xcRB->request_control_blk_length) - return -EINVAL; - function_code = ((unsigned char *)&msg->cprbx) + msg->cprbx.cprb_len; - memcpy(msg->hdr.function_code, function_code, - sizeof(msg->hdr.function_code)); - - if (memcmp(function_code, "US", 2) == 0) - ap_msg->special = 1; - else - ap_msg->special = 0; - - /* copy data block */ - if (xcRB->request_data_length && - copy_from_user(req_data, xcRB->request_data_address, - xcRB->request_data_length)) - return -EFAULT; - return 0; -} - -/** - * Copy results from a type 86 ICA reply message back to user space. - * - * @zdev: crypto device pointer - * @reply: reply AP message. - * @data: pointer to user output data - * @length: size of user output data - * - * Returns 0 on success or -EINVAL, -EFAULT, -EAGAIN in case of an error. - */ -struct type86x_reply { - struct type86_hdr hdr; - struct type86_fmt2_ext fmt2; - struct CPRBX cprbx; - unsigned char pad[4]; /* 4 byte function code/rules block ? */ - unsigned short length; - char text[0]; -} __packed; - -static int convert_type86_ica(struct zcrypt_device *zdev, - struct ap_message *reply, - char __user *outputdata, - unsigned int outputdatalength) -{ - static unsigned char static_pad[] = { - 0x00, 0x02, - 0x1B, 0x7B, 0x5D, 0xB5, 0x75, 0x01, 0x3D, 0xFD, - 0x8D, 0xD1, 0xC7, 0x03, 0x2D, 0x09, 0x23, 0x57, - 0x89, 0x49, 0xB9, 0x3F, 0xBB, 0x99, 0x41, 0x5B, - 0x75, 0x21, 0x7B, 0x9D, 0x3B, 0x6B, 0x51, 0x39, - 0xBB, 0x0D, 0x35, 0xB9, 0x89, 0x0F, 0x93, 0xA5, - 0x0B, 0x47, 0xF1, 0xD3, 0xBB, 0xCB, 0xF1, 0x9D, - 0x23, 0x73, 0x71, 0xFF, 0xF3, 0xF5, 0x45, 0xFB, - 0x61, 0x29, 0x23, 0xFD, 0xF1, 0x29, 0x3F, 0x7F, - 0x17, 0xB7, 0x1B, 0xA9, 0x19, 0xBD, 0x57, 0xA9, - 0xD7, 0x95, 0xA3, 0xCB, 0xED, 0x1D, 0xDB, 0x45, - 0x7D, 0x11, 0xD1, 0x51, 0x1B, 0xED, 0x71, 0xE9, - 0xB1, 0xD1, 0xAB, 0xAB, 0x21, 0x2B, 0x1B, 0x9F, - 0x3B, 0x9F, 0xF7, 0xF7, 0xBD, 0x63, 0xEB, 0xAD, - 0xDF, 0xB3, 0x6F, 0x5B, 0xDB, 0x8D, 0xA9, 0x5D, - 0xE3, 0x7D, 0x77, 0x49, 0x47, 0xF5, 0xA7, 0xFD, - 0xAB, 0x2F, 0x27, 0x35, 0x77, 0xD3, 0x49, 0xC9, - 0x09, 0xEB, 0xB1, 0xF9, 0xBF, 0x4B, 0xCB, 0x2B, - 0xEB, 0xEB, 0x05, 0xFF, 0x7D, 0xC7, 0x91, 0x8B, - 0x09, 0x83, 0xB9, 0xB9, 0x69, 0x33, 0x39, 0x6B, - 0x79, 0x75, 0x19, 0xBF, 0xBB, 0x07, 0x1D, 0xBD, - 0x29, 0xBF, 0x39, 0x95, 0x93, 0x1D, 0x35, 0xC7, - 0xC9, 0x4D, 0xE5, 0x97, 0x0B, 0x43, 0x9B, 0xF1, - 0x16, 0x93, 0x03, 0x1F, 0xA5, 0xFB, 0xDB, 0xF3, - 0x27, 0x4F, 0x27, 0x61, 0x05, 0x1F, 0xB9, 0x23, - 0x2F, 0xC3, 0x81, 0xA9, 0x23, 0x71, 0x55, 0x55, - 0xEB, 0xED, 0x41, 0xE5, 0xF3, 0x11, 0xF1, 0x43, - 0x69, 0x03, 0xBD, 0x0B, 0x37, 0x0F, 0x51, 0x8F, - 0x0B, 0xB5, 0x89, 0x5B, 0x67, 0xA9, 0xD9, 0x4F, - 0x01, 0xF9, 0x21, 0x77, 0x37, 0x73, 0x79, 0xC5, - 0x7F, 0x51, 0xC1, 0xCF, 0x97, 0xA1, 0x75, 0xAD, - 0x35, 0x9D, 0xD3, 0xD3, 0xA7, 0x9D, 0x5D, 0x41, - 0x6F, 0x65, 0x1B, 0xCF, 0xA9, 0x87, 0x91, 0x09 - }; - struct type86x_reply *msg = reply->message; - unsigned short service_rc, service_rs; - unsigned int reply_len, pad_len; - char *data; - - service_rc = msg->cprbx.ccp_rtcode; - if (unlikely(service_rc != 0)) { - service_rs = msg->cprbx.ccp_rscode; - if (service_rc == 8 && service_rs == 66) - return -EINVAL; - if (service_rc == 8 && service_rs == 65) - return -EINVAL; - if (service_rc == 8 && service_rs == 770) - return -EINVAL; - if (service_rc == 8 && service_rs == 783) { - zdev->min_mod_size = PCIXCC_MIN_MOD_SIZE_OLD; - return -EAGAIN; - } - if (service_rc == 12 && service_rs == 769) - return -EINVAL; - if (service_rc == 8 && service_rs == 72) - return -EINVAL; - zdev->online = 0; - return -EAGAIN; /* repeat the request on a different device. */ - } - data = msg->text; - reply_len = msg->length - 2; - if (reply_len > outputdatalength) - return -EINVAL; - /* - * For all encipher requests, the length of the ciphertext (reply_len) - * will always equal the modulus length. For MEX decipher requests - * the output needs to get padded. Minimum pad size is 10. - * - * Currently, the cases where padding will be added is for: - * - PCIXCC_MCL2 using a CRT form token (since PKD didn't support - * ZERO-PAD and CRT is only supported for PKD requests) - * - PCICC, always - */ - pad_len = outputdatalength - reply_len; - if (pad_len > 0) { - if (pad_len < 10) - return -EINVAL; - /* 'restore' padding left in the PCICC/PCIXCC card. */ - if (copy_to_user(outputdata, static_pad, pad_len - 1)) - return -EFAULT; - if (put_user(0, outputdata + pad_len - 1)) - return -EFAULT; - } - /* Copy the crypto response to user space. */ - if (copy_to_user(outputdata + pad_len, data, reply_len)) - return -EFAULT; - return 0; -} - -/** - * Copy results from a type 86 XCRB reply message back to user space. - * - * @zdev: crypto device pointer - * @reply: reply AP message. - * @xcRB: pointer to XCRB - * - * Returns 0 on success or -EINVAL, -EFAULT, -EAGAIN in case of an error. - */ -static int convert_type86_xcrb(struct zcrypt_device *zdev, - struct ap_message *reply, - struct ica_xcRB *xcRB) -{ - struct type86_fmt2_msg *msg = reply->message; - char *data = reply->message; - - /* Copy CPRB to user */ - if (copy_to_user(xcRB->reply_control_blk_addr, - data + msg->fmt2.offset1, msg->fmt2.count1)) - return -EFAULT; - xcRB->reply_control_blk_length = msg->fmt2.count1; - - /* Copy data buffer to user */ - if (msg->fmt2.count2) - if (copy_to_user(xcRB->reply_data_addr, - data + msg->fmt2.offset2, msg->fmt2.count2)) - return -EFAULT; - xcRB->reply_data_length = msg->fmt2.count2; - return 0; -} - -static int convert_type86_rng(struct zcrypt_device *zdev, - struct ap_message *reply, - char *buffer) -{ - struct { - struct type86_hdr hdr; - struct type86_fmt2_ext fmt2; - struct CPRBX cprbx; - } __packed * msg = reply->message; - char *data = reply->message; - - if (msg->cprbx.ccp_rtcode != 0 || msg->cprbx.ccp_rscode != 0) - return -EINVAL; - memcpy(buffer, data + msg->fmt2.offset2, msg->fmt2.count2); - return msg->fmt2.count2; -} - -static int convert_response_ica(struct zcrypt_device *zdev, - struct ap_message *reply, - char __user *outputdata, - unsigned int outputdatalength) -{ - struct type86x_reply *msg = reply->message; - - /* Response type byte is the second byte in the response. */ - switch (((unsigned char *) reply->message)[1]) { - case TYPE82_RSP_CODE: - case TYPE88_RSP_CODE: - return convert_error(zdev, reply); - case TYPE86_RSP_CODE: - if (msg->cprbx.ccp_rtcode && - (msg->cprbx.ccp_rscode == 0x14f) && - (outputdatalength > 256)) { - if (zdev->max_exp_bit_length <= 17) { - zdev->max_exp_bit_length = 17; - return -EAGAIN; - } else - return -EINVAL; - } - if (msg->hdr.reply_code) - return convert_error(zdev, reply); - if (msg->cprbx.cprb_ver_id == 0x02) - return convert_type86_ica(zdev, reply, - outputdata, outputdatalength); - /* Fall through, no break, incorrect cprb version is an unknown - * response */ - default: /* Unknown response type, this should NEVER EVER happen */ - zdev->online = 0; - return -EAGAIN; /* repeat the request on a different device. */ - } -} - -static int convert_response_xcrb(struct zcrypt_device *zdev, - struct ap_message *reply, - struct ica_xcRB *xcRB) -{ - struct type86x_reply *msg = reply->message; - - /* Response type byte is the second byte in the response. */ - switch (((unsigned char *) reply->message)[1]) { - case TYPE82_RSP_CODE: - case TYPE88_RSP_CODE: - xcRB->status = 0x0008044DL; /* HDD_InvalidParm */ - return convert_error(zdev, reply); - case TYPE86_RSP_CODE: - if (msg->hdr.reply_code) { - memcpy(&(xcRB->status), msg->fmt2.apfs, sizeof(u32)); - return convert_error(zdev, reply); - } - if (msg->cprbx.cprb_ver_id == 0x02) - return convert_type86_xcrb(zdev, reply, xcRB); - /* Fall through, no break, incorrect cprb version is an unknown - * response */ - default: /* Unknown response type, this should NEVER EVER happen */ - xcRB->status = 0x0008044DL; /* HDD_InvalidParm */ - zdev->online = 0; - return -EAGAIN; /* repeat the request on a different device. */ - } -} - -static int convert_response_rng(struct zcrypt_device *zdev, - struct ap_message *reply, - char *data) -{ - struct type86x_reply *msg = reply->message; - - switch (msg->hdr.type) { - case TYPE82_RSP_CODE: - case TYPE88_RSP_CODE: - return -EINVAL; - case TYPE86_RSP_CODE: - if (msg->hdr.reply_code) - return -EINVAL; - if (msg->cprbx.cprb_ver_id == 0x02) - return convert_type86_rng(zdev, reply, data); - /* Fall through, no break, incorrect cprb version is an unknown - * response */ - default: /* Unknown response type, this should NEVER EVER happen */ - zdev->online = 0; - return -EAGAIN; /* repeat the request on a different device. */ - } -} - -/** - * This function is called from the AP bus code after a crypto request - * "msg" has finished with the reply message "reply". - * It is called from tasklet context. - * @ap_dev: pointer to the AP device - * @msg: pointer to the AP message - * @reply: pointer to the AP reply message - */ -static void zcrypt_msgtype6_receive(struct ap_device *ap_dev, - struct ap_message *msg, - struct ap_message *reply) -{ - static struct error_hdr error_reply = { - .type = TYPE82_RSP_CODE, - .reply_code = REP82_ERROR_MACHINE_FAILURE, - }; - struct response_type *resp_type = - (struct response_type *) msg->private; - struct type86x_reply *t86r; - int length; - - /* Copy the reply message to the request message buffer. */ - if (IS_ERR(reply)) { - memcpy(msg->message, &error_reply, sizeof(error_reply)); - goto out; - } - t86r = reply->message; - if (t86r->hdr.type == TYPE86_RSP_CODE && - t86r->cprbx.cprb_ver_id == 0x02) { - switch (resp_type->type) { - case PCIXCC_RESPONSE_TYPE_ICA: - length = sizeof(struct type86x_reply) - + t86r->length - 2; - length = min(PCIXCC_MAX_ICA_RESPONSE_SIZE, length); - memcpy(msg->message, reply->message, length); - break; - case PCIXCC_RESPONSE_TYPE_XCRB: - length = t86r->fmt2.offset2 + t86r->fmt2.count2; - length = min(MSGTYPE06_MAX_MSG_SIZE, length); - memcpy(msg->message, reply->message, length); - break; - default: - memcpy(msg->message, &error_reply, - sizeof(error_reply)); - } - } else - memcpy(msg->message, reply->message, sizeof(error_reply)); -out: - complete(&(resp_type->work)); -} - -static atomic_t zcrypt_step = ATOMIC_INIT(0); - -/** - * The request distributor calls this function if it picked the PCIXCC/CEX2C - * device to handle a modexpo request. - * @zdev: pointer to zcrypt_device structure that identifies the - * PCIXCC/CEX2C device to the request distributor - * @mex: pointer to the modexpo request buffer - */ -static long zcrypt_msgtype6_modexpo(struct zcrypt_device *zdev, - struct ica_rsa_modexpo *mex) -{ - struct ap_message ap_msg; - struct response_type resp_type = { - .type = PCIXCC_RESPONSE_TYPE_ICA, - }; - int rc; - - ap_init_message(&ap_msg); - ap_msg.message = (void *) get_zeroed_page(GFP_KERNEL); - if (!ap_msg.message) - return -ENOMEM; - ap_msg.receive = zcrypt_msgtype6_receive; - ap_msg.psmid = (((unsigned long long) current->pid) << 32) + - atomic_inc_return(&zcrypt_step); - ap_msg.private = &resp_type; - rc = ICAMEX_msg_to_type6MEX_msgX(zdev, &ap_msg, mex); - if (rc) - goto out_free; - init_completion(&resp_type.work); - ap_queue_message(zdev->ap_dev, &ap_msg); - rc = wait_for_completion_interruptible(&resp_type.work); - if (rc == 0) - rc = convert_response_ica(zdev, &ap_msg, mex->outputdata, - mex->outputdatalength); - else - /* Signal pending. */ - ap_cancel_message(zdev->ap_dev, &ap_msg); -out_free: - free_page((unsigned long) ap_msg.message); - return rc; -} - -/** - * The request distributor calls this function if it picked the PCIXCC/CEX2C - * device to handle a modexpo_crt request. - * @zdev: pointer to zcrypt_device structure that identifies the - * PCIXCC/CEX2C device to the request distributor - * @crt: pointer to the modexpoc_crt request buffer - */ -static long zcrypt_msgtype6_modexpo_crt(struct zcrypt_device *zdev, - struct ica_rsa_modexpo_crt *crt) -{ - struct ap_message ap_msg; - struct response_type resp_type = { - .type = PCIXCC_RESPONSE_TYPE_ICA, - }; - int rc; - - ap_init_message(&ap_msg); - ap_msg.message = (void *) get_zeroed_page(GFP_KERNEL); - if (!ap_msg.message) - return -ENOMEM; - ap_msg.receive = zcrypt_msgtype6_receive; - ap_msg.psmid = (((unsigned long long) current->pid) << 32) + - atomic_inc_return(&zcrypt_step); - ap_msg.private = &resp_type; - rc = ICACRT_msg_to_type6CRT_msgX(zdev, &ap_msg, crt); - if (rc) - goto out_free; - init_completion(&resp_type.work); - ap_queue_message(zdev->ap_dev, &ap_msg); - rc = wait_for_completion_interruptible(&resp_type.work); - if (rc == 0) - rc = convert_response_ica(zdev, &ap_msg, crt->outputdata, - crt->outputdatalength); - else - /* Signal pending. */ - ap_cancel_message(zdev->ap_dev, &ap_msg); -out_free: - free_page((unsigned long) ap_msg.message); - return rc; -} - -/** - * The request distributor calls this function if it picked the PCIXCC/CEX2C - * device to handle a send_cprb request. - * @zdev: pointer to zcrypt_device structure that identifies the - * PCIXCC/CEX2C device to the request distributor - * @xcRB: pointer to the send_cprb request buffer - */ -static long zcrypt_msgtype6_send_cprb(struct zcrypt_device *zdev, - struct ica_xcRB *xcRB) -{ - struct ap_message ap_msg; - struct response_type resp_type = { - .type = PCIXCC_RESPONSE_TYPE_XCRB, - }; - int rc; - - ap_init_message(&ap_msg); - ap_msg.message = kmalloc(MSGTYPE06_MAX_MSG_SIZE, GFP_KERNEL); - if (!ap_msg.message) - return -ENOMEM; - ap_msg.receive = zcrypt_msgtype6_receive; - ap_msg.psmid = (((unsigned long long) current->pid) << 32) + - atomic_inc_return(&zcrypt_step); - ap_msg.private = &resp_type; - rc = XCRB_msg_to_type6CPRB_msgX(zdev, &ap_msg, xcRB); - if (rc) - goto out_free; - init_completion(&resp_type.work); - ap_queue_message(zdev->ap_dev, &ap_msg); - rc = wait_for_completion_interruptible(&resp_type.work); - if (rc == 0) - rc = convert_response_xcrb(zdev, &ap_msg, xcRB); - else - /* Signal pending. */ - ap_cancel_message(zdev->ap_dev, &ap_msg); -out_free: - kzfree(ap_msg.message); - return rc; -} - -/** - * The request distributor calls this function if it picked the PCIXCC/CEX2C - * device to generate random data. - * @zdev: pointer to zcrypt_device structure that identifies the - * PCIXCC/CEX2C device to the request distributor - * @buffer: pointer to a memory page to return random data - */ - -static long zcrypt_msgtype6_rng(struct zcrypt_device *zdev, - char *buffer) -{ - struct ap_message ap_msg; - struct response_type resp_type = { - .type = PCIXCC_RESPONSE_TYPE_XCRB, - }; - int rc; - - ap_init_message(&ap_msg); - ap_msg.message = kmalloc(MSGTYPE06_MAX_MSG_SIZE, GFP_KERNEL); - if (!ap_msg.message) - return -ENOMEM; - ap_msg.receive = zcrypt_msgtype6_receive; - ap_msg.psmid = (((unsigned long long) current->pid) << 32) + - atomic_inc_return(&zcrypt_step); - ap_msg.private = &resp_type; - rng_type6CPRB_msgX(zdev->ap_dev, &ap_msg, ZCRYPT_RNG_BUFFER_SIZE); - init_completion(&resp_type.work); - ap_queue_message(zdev->ap_dev, &ap_msg); - rc = wait_for_completion_interruptible(&resp_type.work); - if (rc == 0) - rc = convert_response_rng(zdev, &ap_msg, buffer); - else - /* Signal pending. */ - ap_cancel_message(zdev->ap_dev, &ap_msg); - kfree(ap_msg.message); - return rc; -} - -/** - * The crypto operations for a PCIXCC/CEX2C card. - */ -static struct zcrypt_ops zcrypt_msgtype6_norng_ops = { - .owner = THIS_MODULE, - .variant = MSGTYPE06_VARIANT_NORNG, - .rsa_modexpo = zcrypt_msgtype6_modexpo, - .rsa_modexpo_crt = zcrypt_msgtype6_modexpo_crt, - .send_cprb = zcrypt_msgtype6_send_cprb, -}; - -static struct zcrypt_ops zcrypt_msgtype6_ops = { - .owner = THIS_MODULE, - .variant = MSGTYPE06_VARIANT_DEFAULT, - .rsa_modexpo = zcrypt_msgtype6_modexpo, - .rsa_modexpo_crt = zcrypt_msgtype6_modexpo_crt, - .send_cprb = zcrypt_msgtype6_send_cprb, - .rng = zcrypt_msgtype6_rng, -}; - -int __init zcrypt_msgtype6_init(void) -{ - zcrypt_msgtype_register(&zcrypt_msgtype6_norng_ops); - zcrypt_msgtype_register(&zcrypt_msgtype6_ops); - return 0; -} - -void __exit zcrypt_msgtype6_exit(void) -{ - zcrypt_msgtype_unregister(&zcrypt_msgtype6_norng_ops); - zcrypt_msgtype_unregister(&zcrypt_msgtype6_ops); -} - -module_init(zcrypt_msgtype6_init); -module_exit(zcrypt_msgtype6_exit); diff --git a/trunk/drivers/s390/crypto/zcrypt_msgtype6.h b/trunk/drivers/s390/crypto/zcrypt_msgtype6.h deleted file mode 100644 index 1e500d3c0735..000000000000 --- a/trunk/drivers/s390/crypto/zcrypt_msgtype6.h +++ /dev/null @@ -1,169 +0,0 @@ -/* - * zcrypt 2.1.0 - * - * Copyright IBM Corp. 2001, 2012 - * Author(s): Robert Burroughs - * Eric Rossman (edrossma@us.ibm.com) - * - * Hotplug & misc device support: Jochen Roehrig (roehrig@de.ibm.com) - * Major cleanup & driver split: Martin Schwidefsky - * MSGTYPE restruct: Holger Dengler - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifndef _ZCRYPT_MSGTYPE6_H_ -#define _ZCRYPT_MSGTYPE6_H_ - -#include - -#define MSGTYPE06_NAME "zcrypt_msgtype6" -#define MSGTYPE06_VARIANT_DEFAULT 0 -#define MSGTYPE06_VARIANT_NORNG 1 - -#define MSGTYPE06_MAX_MSG_SIZE (12*1024) - -/** - * The type 6 message family is associated with PCICC or PCIXCC cards. - * - * It contains a message header followed by a CPRB, both of which - * are described below. - * - * Note that all reserved fields must be zeroes. - */ -struct type6_hdr { - unsigned char reserved1; /* 0x00 */ - unsigned char type; /* 0x06 */ - unsigned char reserved2[2]; /* 0x0000 */ - unsigned char right[4]; /* 0x00000000 */ - unsigned char reserved3[2]; /* 0x0000 */ - unsigned char reserved4[2]; /* 0x0000 */ - unsigned char apfs[4]; /* 0x00000000 */ - unsigned int offset1; /* 0x00000058 (offset to CPRB) */ - unsigned int offset2; /* 0x00000000 */ - unsigned int offset3; /* 0x00000000 */ - unsigned int offset4; /* 0x00000000 */ - unsigned char agent_id[16]; /* PCICC: */ - /* 0x0100 */ - /* 0x4343412d4150504c202020 */ - /* 0x010101 */ - /* PCIXCC: */ - /* 0x4341000000000000 */ - /* 0x0000000000000000 */ - unsigned char rqid[2]; /* rqid. internal to 603 */ - unsigned char reserved5[2]; /* 0x0000 */ - unsigned char function_code[2]; /* for PKD, 0x5044 (ascii 'PD') */ - unsigned char reserved6[2]; /* 0x0000 */ - unsigned int ToCardLen1; /* (request CPRB len + 3) & -4 */ - unsigned int ToCardLen2; /* db len 0x00000000 for PKD */ - unsigned int ToCardLen3; /* 0x00000000 */ - unsigned int ToCardLen4; /* 0x00000000 */ - unsigned int FromCardLen1; /* response buffer length */ - unsigned int FromCardLen2; /* db len 0x00000000 for PKD */ - unsigned int FromCardLen3; /* 0x00000000 */ - unsigned int FromCardLen4; /* 0x00000000 */ -} __packed; - -/** - * The type 86 message family is associated with PCICC and PCIXCC cards. - * - * It contains a message header followed by a CPRB. The CPRB is - * the same as the request CPRB, which is described above. - * - * If format is 1, an error condition exists and no data beyond - * the 8-byte message header is of interest. - * - * The non-error message is shown below. - * - * Note that all reserved fields must be zeroes. - */ -struct type86_hdr { - unsigned char reserved1; /* 0x00 */ - unsigned char type; /* 0x86 */ - unsigned char format; /* 0x01 (error) or 0x02 (ok) */ - unsigned char reserved2; /* 0x00 */ - unsigned char reply_code; /* reply code (see above) */ - unsigned char reserved3[3]; /* 0x000000 */ -} __packed; - -#define TYPE86_RSP_CODE 0x86 -#define TYPE86_FMT2 0x02 - -struct type86_fmt2_ext { - unsigned char reserved[4]; /* 0x00000000 */ - unsigned char apfs[4]; /* final status */ - unsigned int count1; /* length of CPRB + parameters */ - unsigned int offset1; /* offset to CPRB */ - unsigned int count2; /* 0x00000000 */ - unsigned int offset2; /* db offset 0x00000000 for PKD */ - unsigned int count3; /* 0x00000000 */ - unsigned int offset3; /* 0x00000000 */ - unsigned int count4; /* 0x00000000 */ - unsigned int offset4; /* 0x00000000 */ -} __packed; - -/** - * Prepare a type6 CPRB message for random number generation - * - * @ap_dev: AP device pointer - * @ap_msg: pointer to AP message - */ -static inline void rng_type6CPRB_msgX(struct ap_device *ap_dev, - struct ap_message *ap_msg, - unsigned random_number_length) -{ - struct { - struct type6_hdr hdr; - struct CPRBX cprbx; - char function_code[2]; - short int rule_length; - char rule[8]; - short int verb_length; - short int key_length; - } __packed * msg = ap_msg->message; - static struct type6_hdr static_type6_hdrX = { - .type = 0x06, - .offset1 = 0x00000058, - .agent_id = {'C', 'A'}, - .function_code = {'R', 'L'}, - .ToCardLen1 = sizeof(*msg) - sizeof(msg->hdr), - .FromCardLen1 = sizeof(*msg) - sizeof(msg->hdr), - }; - static struct CPRBX local_cprbx = { - .cprb_len = 0x00dc, - .cprb_ver_id = 0x02, - .func_id = {0x54, 0x32}, - .req_parml = sizeof(*msg) - sizeof(msg->hdr) - - sizeof(msg->cprbx), - .rpl_msgbl = sizeof(*msg) - sizeof(msg->hdr), - }; - - msg->hdr = static_type6_hdrX; - msg->hdr.FromCardLen2 = random_number_length, - msg->cprbx = local_cprbx; - msg->cprbx.rpl_datal = random_number_length, - msg->cprbx.domain = AP_QID_QUEUE(ap_dev->qid); - memcpy(msg->function_code, msg->hdr.function_code, 0x02); - msg->rule_length = 0x0a; - memcpy(msg->rule, "RANDOM ", 8); - msg->verb_length = 0x02; - msg->key_length = 0x02; - ap_msg->length = sizeof(*msg); -} - -int zcrypt_msgtype6_init(void); -void zcrypt_msgtype6_exit(void); - -#endif /* _ZCRYPT_MSGTYPE6_H_ */ diff --git a/trunk/drivers/s390/crypto/zcrypt_pcixcc.c b/trunk/drivers/s390/crypto/zcrypt_pcixcc.c index c7275e303a0d..ccb4f8b60c75 100644 --- a/trunk/drivers/s390/crypto/zcrypt_pcixcc.c +++ b/trunk/drivers/s390/crypto/zcrypt_pcixcc.c @@ -1,14 +1,13 @@ /* * zcrypt 2.1.0 * - * Copyright IBM Corp. 2001, 2012 + * Copyright IBM Corp. 2001, 2006 * Author(s): Robert Burroughs * Eric Rossman (edrossma@us.ibm.com) * * Hotplug & misc device support: Jochen Roehrig (roehrig@de.ibm.com) * Major cleanup & driver split: Martin Schwidefsky * Ralph Wuerthner - * MSGTYPE restruct: Holger Dengler * * 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 @@ -36,10 +35,9 @@ #include "ap_bus.h" #include "zcrypt_api.h" #include "zcrypt_error.h" -#include "zcrypt_msgtype6.h" +#include "zcrypt_pcicc.h" #include "zcrypt_pcixcc.h" #include "zcrypt_cca_key.h" -#include "zcrypt_msgtype6.h" #define PCIXCC_MIN_MOD_SIZE 16 /* 128 bits */ #define PCIXCC_MIN_MOD_SIZE_OLD 64 /* 512 bits */ @@ -77,12 +75,14 @@ static struct ap_device_id zcrypt_pcixcc_ids[] = { MODULE_DEVICE_TABLE(ap, zcrypt_pcixcc_ids); MODULE_AUTHOR("IBM Corporation"); -MODULE_DESCRIPTION("PCIXCC Cryptographic Coprocessor device driver, " \ - "Copyright IBM Corp. 2001, 2012"); +MODULE_DESCRIPTION("PCIXCC Cryptographic Coprocessor device driver, " + "Copyright IBM Corp. 2001, 2006"); MODULE_LICENSE("GPL"); static int zcrypt_pcixcc_probe(struct ap_device *ap_dev); static void zcrypt_pcixcc_remove(struct ap_device *ap_dev); +static void zcrypt_pcixcc_receive(struct ap_device *, struct ap_message *, + struct ap_message *); static struct ap_driver zcrypt_pcixcc_driver = { .probe = zcrypt_pcixcc_probe, @@ -91,6 +91,766 @@ static struct ap_driver zcrypt_pcixcc_driver = { .request_timeout = PCIXCC_CLEANUP_TIME, }; +/** + * The following is used to initialize the CPRBX passed to the PCIXCC/CEX2C + * card in a type6 message. The 3 fields that must be filled in at execution + * time are req_parml, rpl_parml and usage_domain. + * Everything about this interface is ascii/big-endian, since the + * device does *not* have 'Intel inside'. + * + * The CPRBX is followed immediately by the parm block. + * The parm block contains: + * - function code ('PD' 0x5044 or 'PK' 0x504B) + * - rule block (one of:) + * + 0x000A 'PKCS-1.2' (MCL2 'PD') + * + 0x000A 'ZERO-PAD' (MCL2 'PK') + * + 0x000A 'ZERO-PAD' (MCL3 'PD' or CEX2C 'PD') + * + 0x000A 'MRP ' (MCL3 'PK' or CEX2C 'PK') + * - VUD block + */ +static struct CPRBX static_cprbx = { + .cprb_len = 0x00DC, + .cprb_ver_id = 0x02, + .func_id = {0x54,0x32}, +}; + +/** + * Convert a ICAMEX message to a type6 MEX message. + * + * @zdev: crypto device pointer + * @ap_msg: pointer to AP message + * @mex: pointer to user input data + * + * Returns 0 on success or -EFAULT. + */ +static int ICAMEX_msg_to_type6MEX_msgX(struct zcrypt_device *zdev, + struct ap_message *ap_msg, + struct ica_rsa_modexpo *mex) +{ + static struct type6_hdr static_type6_hdrX = { + .type = 0x06, + .offset1 = 0x00000058, + .agent_id = {'C','A',}, + .function_code = {'P','K'}, + }; + static struct function_and_rules_block static_pke_fnr = { + .function_code = {'P','K'}, + .ulen = 10, + .only_rule = {'M','R','P',' ',' ',' ',' ',' '} + }; + static struct function_and_rules_block static_pke_fnr_MCL2 = { + .function_code = {'P','K'}, + .ulen = 10, + .only_rule = {'Z','E','R','O','-','P','A','D'} + }; + struct { + struct type6_hdr hdr; + struct CPRBX cprbx; + struct function_and_rules_block fr; + unsigned short length; + char text[0]; + } __attribute__((packed)) *msg = ap_msg->message; + int size; + + /* VUD.ciphertext */ + msg->length = mex->inputdatalength + 2; + if (copy_from_user(msg->text, mex->inputdata, mex->inputdatalength)) + return -EFAULT; + + /* Set up key which is located after the variable length text. */ + size = zcrypt_type6_mex_key_en(mex, msg->text+mex->inputdatalength, 1); + if (size < 0) + return size; + size += sizeof(*msg) + mex->inputdatalength; + + /* message header, cprbx and f&r */ + msg->hdr = static_type6_hdrX; + msg->hdr.ToCardLen1 = size - sizeof(msg->hdr); + msg->hdr.FromCardLen1 = PCIXCC_MAX_ICA_RESPONSE_SIZE - sizeof(msg->hdr); + + msg->cprbx = static_cprbx; + msg->cprbx.domain = AP_QID_QUEUE(zdev->ap_dev->qid); + msg->cprbx.rpl_msgbl = msg->hdr.FromCardLen1; + + msg->fr = (zdev->user_space_type == ZCRYPT_PCIXCC_MCL2) ? + static_pke_fnr_MCL2 : static_pke_fnr; + + msg->cprbx.req_parml = size - sizeof(msg->hdr) - sizeof(msg->cprbx); + + ap_msg->length = size; + return 0; +} + +/** + * Convert a ICACRT message to a type6 CRT message. + * + * @zdev: crypto device pointer + * @ap_msg: pointer to AP message + * @crt: pointer to user input data + * + * Returns 0 on success or -EFAULT. + */ +static int ICACRT_msg_to_type6CRT_msgX(struct zcrypt_device *zdev, + struct ap_message *ap_msg, + struct ica_rsa_modexpo_crt *crt) +{ + static struct type6_hdr static_type6_hdrX = { + .type = 0x06, + .offset1 = 0x00000058, + .agent_id = {'C','A',}, + .function_code = {'P','D'}, + }; + static struct function_and_rules_block static_pkd_fnr = { + .function_code = {'P','D'}, + .ulen = 10, + .only_rule = {'Z','E','R','O','-','P','A','D'} + }; + + static struct function_and_rules_block static_pkd_fnr_MCL2 = { + .function_code = {'P','D'}, + .ulen = 10, + .only_rule = {'P','K','C','S','-','1','.','2'} + }; + struct { + struct type6_hdr hdr; + struct CPRBX cprbx; + struct function_and_rules_block fr; + unsigned short length; + char text[0]; + } __attribute__((packed)) *msg = ap_msg->message; + int size; + + /* VUD.ciphertext */ + msg->length = crt->inputdatalength + 2; + if (copy_from_user(msg->text, crt->inputdata, crt->inputdatalength)) + return -EFAULT; + + /* Set up key which is located after the variable length text. */ + size = zcrypt_type6_crt_key(crt, msg->text + crt->inputdatalength, 1); + if (size < 0) + return size; + size += sizeof(*msg) + crt->inputdatalength; /* total size of msg */ + + /* message header, cprbx and f&r */ + msg->hdr = static_type6_hdrX; + msg->hdr.ToCardLen1 = size - sizeof(msg->hdr); + msg->hdr.FromCardLen1 = PCIXCC_MAX_ICA_RESPONSE_SIZE - sizeof(msg->hdr); + + msg->cprbx = static_cprbx; + msg->cprbx.domain = AP_QID_QUEUE(zdev->ap_dev->qid); + msg->cprbx.req_parml = msg->cprbx.rpl_msgbl = + size - sizeof(msg->hdr) - sizeof(msg->cprbx); + + msg->fr = (zdev->user_space_type == ZCRYPT_PCIXCC_MCL2) ? + static_pkd_fnr_MCL2 : static_pkd_fnr; + + ap_msg->length = size; + return 0; +} + +/** + * Convert a XCRB message to a type6 CPRB message. + * + * @zdev: crypto device pointer + * @ap_msg: pointer to AP message + * @xcRB: pointer to user input data + * + * Returns 0 on success or -EFAULT, -EINVAL. + */ +struct type86_fmt2_msg { + struct type86_hdr hdr; + struct type86_fmt2_ext fmt2; +} __attribute__((packed)); + +static int XCRB_msg_to_type6CPRB_msgX(struct zcrypt_device *zdev, + struct ap_message *ap_msg, + struct ica_xcRB *xcRB) +{ + static struct type6_hdr static_type6_hdrX = { + .type = 0x06, + .offset1 = 0x00000058, + }; + struct { + struct type6_hdr hdr; + struct CPRBX cprbx; + } __attribute__((packed)) *msg = ap_msg->message; + + int rcblen = CEIL4(xcRB->request_control_blk_length); + int replylen; + char *req_data = ap_msg->message + sizeof(struct type6_hdr) + rcblen; + char *function_code; + + /* length checks */ + ap_msg->length = sizeof(struct type6_hdr) + + CEIL4(xcRB->request_control_blk_length) + + xcRB->request_data_length; + if (ap_msg->length > PCIXCC_MAX_XCRB_MESSAGE_SIZE) + return -EINVAL; + replylen = sizeof(struct type86_fmt2_msg) + + CEIL4(xcRB->reply_control_blk_length) + + xcRB->reply_data_length; + if (replylen > PCIXCC_MAX_XCRB_MESSAGE_SIZE) + return -EINVAL; + + /* prepare type6 header */ + msg->hdr = static_type6_hdrX; + memcpy(msg->hdr.agent_id , &(xcRB->agent_ID), sizeof(xcRB->agent_ID)); + msg->hdr.ToCardLen1 = xcRB->request_control_blk_length; + if (xcRB->request_data_length) { + msg->hdr.offset2 = msg->hdr.offset1 + rcblen; + msg->hdr.ToCardLen2 = xcRB->request_data_length; + } + msg->hdr.FromCardLen1 = xcRB->reply_control_blk_length; + msg->hdr.FromCardLen2 = xcRB->reply_data_length; + + /* prepare CPRB */ + if (copy_from_user(&(msg->cprbx), xcRB->request_control_blk_addr, + xcRB->request_control_blk_length)) + return -EFAULT; + if (msg->cprbx.cprb_len + sizeof(msg->hdr.function_code) > + xcRB->request_control_blk_length) + return -EINVAL; + function_code = ((unsigned char *)&msg->cprbx) + msg->cprbx.cprb_len; + memcpy(msg->hdr.function_code, function_code, sizeof(msg->hdr.function_code)); + + if (memcmp(function_code, "US", 2) == 0) + ap_msg->special = 1; + else + ap_msg->special = 0; + + /* copy data block */ + if (xcRB->request_data_length && + copy_from_user(req_data, xcRB->request_data_address, + xcRB->request_data_length)) + return -EFAULT; + return 0; +} + +/** + * Prepare a type6 CPRB message for random number generation + * + * @ap_dev: AP device pointer + * @ap_msg: pointer to AP message + */ +static void rng_type6CPRB_msgX(struct ap_device *ap_dev, + struct ap_message *ap_msg, + unsigned random_number_length) +{ + struct { + struct type6_hdr hdr; + struct CPRBX cprbx; + char function_code[2]; + short int rule_length; + char rule[8]; + short int verb_length; + short int key_length; + } __attribute__((packed)) *msg = ap_msg->message; + static struct type6_hdr static_type6_hdrX = { + .type = 0x06, + .offset1 = 0x00000058, + .agent_id = {'C', 'A'}, + .function_code = {'R', 'L'}, + .ToCardLen1 = sizeof *msg - sizeof(msg->hdr), + .FromCardLen1 = sizeof *msg - sizeof(msg->hdr), + }; + static struct CPRBX local_cprbx = { + .cprb_len = 0x00dc, + .cprb_ver_id = 0x02, + .func_id = {0x54, 0x32}, + .req_parml = sizeof *msg - sizeof(msg->hdr) - + sizeof(msg->cprbx), + .rpl_msgbl = sizeof *msg - sizeof(msg->hdr), + }; + + msg->hdr = static_type6_hdrX; + msg->hdr.FromCardLen2 = random_number_length, + msg->cprbx = local_cprbx; + msg->cprbx.rpl_datal = random_number_length, + msg->cprbx.domain = AP_QID_QUEUE(ap_dev->qid); + memcpy(msg->function_code, msg->hdr.function_code, 0x02); + msg->rule_length = 0x0a; + memcpy(msg->rule, "RANDOM ", 8); + msg->verb_length = 0x02; + msg->key_length = 0x02; + ap_msg->length = sizeof *msg; +} + +/** + * Copy results from a type 86 ICA reply message back to user space. + * + * @zdev: crypto device pointer + * @reply: reply AP message. + * @data: pointer to user output data + * @length: size of user output data + * + * Returns 0 on success or -EINVAL, -EFAULT, -EAGAIN in case of an error. + */ +struct type86x_reply { + struct type86_hdr hdr; + struct type86_fmt2_ext fmt2; + struct CPRBX cprbx; + unsigned char pad[4]; /* 4 byte function code/rules block ? */ + unsigned short length; + char text[0]; +} __attribute__((packed)); + +static int convert_type86_ica(struct zcrypt_device *zdev, + struct ap_message *reply, + char __user *outputdata, + unsigned int outputdatalength) +{ + static unsigned char static_pad[] = { + 0x00,0x02, + 0x1B,0x7B,0x5D,0xB5,0x75,0x01,0x3D,0xFD, + 0x8D,0xD1,0xC7,0x03,0x2D,0x09,0x23,0x57, + 0x89,0x49,0xB9,0x3F,0xBB,0x99,0x41,0x5B, + 0x75,0x21,0x7B,0x9D,0x3B,0x6B,0x51,0x39, + 0xBB,0x0D,0x35,0xB9,0x89,0x0F,0x93,0xA5, + 0x0B,0x47,0xF1,0xD3,0xBB,0xCB,0xF1,0x9D, + 0x23,0x73,0x71,0xFF,0xF3,0xF5,0x45,0xFB, + 0x61,0x29,0x23,0xFD,0xF1,0x29,0x3F,0x7F, + 0x17,0xB7,0x1B,0xA9,0x19,0xBD,0x57,0xA9, + 0xD7,0x95,0xA3,0xCB,0xED,0x1D,0xDB,0x45, + 0x7D,0x11,0xD1,0x51,0x1B,0xED,0x71,0xE9, + 0xB1,0xD1,0xAB,0xAB,0x21,0x2B,0x1B,0x9F, + 0x3B,0x9F,0xF7,0xF7,0xBD,0x63,0xEB,0xAD, + 0xDF,0xB3,0x6F,0x5B,0xDB,0x8D,0xA9,0x5D, + 0xE3,0x7D,0x77,0x49,0x47,0xF5,0xA7,0xFD, + 0xAB,0x2F,0x27,0x35,0x77,0xD3,0x49,0xC9, + 0x09,0xEB,0xB1,0xF9,0xBF,0x4B,0xCB,0x2B, + 0xEB,0xEB,0x05,0xFF,0x7D,0xC7,0x91,0x8B, + 0x09,0x83,0xB9,0xB9,0x69,0x33,0x39,0x6B, + 0x79,0x75,0x19,0xBF,0xBB,0x07,0x1D,0xBD, + 0x29,0xBF,0x39,0x95,0x93,0x1D,0x35,0xC7, + 0xC9,0x4D,0xE5,0x97,0x0B,0x43,0x9B,0xF1, + 0x16,0x93,0x03,0x1F,0xA5,0xFB,0xDB,0xF3, + 0x27,0x4F,0x27,0x61,0x05,0x1F,0xB9,0x23, + 0x2F,0xC3,0x81,0xA9,0x23,0x71,0x55,0x55, + 0xEB,0xED,0x41,0xE5,0xF3,0x11,0xF1,0x43, + 0x69,0x03,0xBD,0x0B,0x37,0x0F,0x51,0x8F, + 0x0B,0xB5,0x89,0x5B,0x67,0xA9,0xD9,0x4F, + 0x01,0xF9,0x21,0x77,0x37,0x73,0x79,0xC5, + 0x7F,0x51,0xC1,0xCF,0x97,0xA1,0x75,0xAD, + 0x35,0x9D,0xD3,0xD3,0xA7,0x9D,0x5D,0x41, + 0x6F,0x65,0x1B,0xCF,0xA9,0x87,0x91,0x09 + }; + struct type86x_reply *msg = reply->message; + unsigned short service_rc, service_rs; + unsigned int reply_len, pad_len; + char *data; + + service_rc = msg->cprbx.ccp_rtcode; + if (unlikely(service_rc != 0)) { + service_rs = msg->cprbx.ccp_rscode; + if (service_rc == 8 && service_rs == 66) + return -EINVAL; + if (service_rc == 8 && service_rs == 65) + return -EINVAL; + if (service_rc == 8 && service_rs == 770) + return -EINVAL; + if (service_rc == 8 && service_rs == 783) { + zdev->min_mod_size = PCIXCC_MIN_MOD_SIZE_OLD; + return -EAGAIN; + } + if (service_rc == 12 && service_rs == 769) + return -EINVAL; + if (service_rc == 8 && service_rs == 72) + return -EINVAL; + zdev->online = 0; + return -EAGAIN; /* repeat the request on a different device. */ + } + data = msg->text; + reply_len = msg->length - 2; + if (reply_len > outputdatalength) + return -EINVAL; + /* + * For all encipher requests, the length of the ciphertext (reply_len) + * will always equal the modulus length. For MEX decipher requests + * the output needs to get padded. Minimum pad size is 10. + * + * Currently, the cases where padding will be added is for: + * - PCIXCC_MCL2 using a CRT form token (since PKD didn't support + * ZERO-PAD and CRT is only supported for PKD requests) + * - PCICC, always + */ + pad_len = outputdatalength - reply_len; + if (pad_len > 0) { + if (pad_len < 10) + return -EINVAL; + /* 'restore' padding left in the PCICC/PCIXCC card. */ + if (copy_to_user(outputdata, static_pad, pad_len - 1)) + return -EFAULT; + if (put_user(0, outputdata + pad_len - 1)) + return -EFAULT; + } + /* Copy the crypto response to user space. */ + if (copy_to_user(outputdata + pad_len, data, reply_len)) + return -EFAULT; + return 0; +} + +/** + * Copy results from a type 86 XCRB reply message back to user space. + * + * @zdev: crypto device pointer + * @reply: reply AP message. + * @xcRB: pointer to XCRB + * + * Returns 0 on success or -EINVAL, -EFAULT, -EAGAIN in case of an error. + */ +static int convert_type86_xcrb(struct zcrypt_device *zdev, + struct ap_message *reply, + struct ica_xcRB *xcRB) +{ + struct type86_fmt2_msg *msg = reply->message; + char *data = reply->message; + + /* Copy CPRB to user */ + if (copy_to_user(xcRB->reply_control_blk_addr, + data + msg->fmt2.offset1, msg->fmt2.count1)) + return -EFAULT; + xcRB->reply_control_blk_length = msg->fmt2.count1; + + /* Copy data buffer to user */ + if (msg->fmt2.count2) + if (copy_to_user(xcRB->reply_data_addr, + data + msg->fmt2.offset2, msg->fmt2.count2)) + return -EFAULT; + xcRB->reply_data_length = msg->fmt2.count2; + return 0; +} + +static int convert_type86_rng(struct zcrypt_device *zdev, + struct ap_message *reply, + char *buffer) +{ + struct { + struct type86_hdr hdr; + struct type86_fmt2_ext fmt2; + struct CPRBX cprbx; + } __attribute__((packed)) *msg = reply->message; + char *data = reply->message; + + if (msg->cprbx.ccp_rtcode != 0 || msg->cprbx.ccp_rscode != 0) + return -EINVAL; + memcpy(buffer, data + msg->fmt2.offset2, msg->fmt2.count2); + return msg->fmt2.count2; +} + +static int convert_response_ica(struct zcrypt_device *zdev, + struct ap_message *reply, + char __user *outputdata, + unsigned int outputdatalength) +{ + struct type86x_reply *msg = reply->message; + + /* Response type byte is the second byte in the response. */ + switch (((unsigned char *) reply->message)[1]) { + case TYPE82_RSP_CODE: + case TYPE88_RSP_CODE: + return convert_error(zdev, reply); + case TYPE86_RSP_CODE: + if (msg->cprbx.ccp_rtcode && + (msg->cprbx.ccp_rscode == 0x14f) && + (outputdatalength > 256)) { + if (zdev->max_exp_bit_length <= 17) { + zdev->max_exp_bit_length = 17; + return -EAGAIN; + } else + return -EINVAL; + } + if (msg->hdr.reply_code) + return convert_error(zdev, reply); + if (msg->cprbx.cprb_ver_id == 0x02) + return convert_type86_ica(zdev, reply, + outputdata, outputdatalength); + /* Fall through, no break, incorrect cprb version is an unknown + * response */ + default: /* Unknown response type, this should NEVER EVER happen */ + zdev->online = 0; + return -EAGAIN; /* repeat the request on a different device. */ + } +} + +static int convert_response_xcrb(struct zcrypt_device *zdev, + struct ap_message *reply, + struct ica_xcRB *xcRB) +{ + struct type86x_reply *msg = reply->message; + + /* Response type byte is the second byte in the response. */ + switch (((unsigned char *) reply->message)[1]) { + case TYPE82_RSP_CODE: + case TYPE88_RSP_CODE: + xcRB->status = 0x0008044DL; /* HDD_InvalidParm */ + return convert_error(zdev, reply); + case TYPE86_RSP_CODE: + if (msg->hdr.reply_code) { + memcpy(&(xcRB->status), msg->fmt2.apfs, sizeof(u32)); + return convert_error(zdev, reply); + } + if (msg->cprbx.cprb_ver_id == 0x02) + return convert_type86_xcrb(zdev, reply, xcRB); + /* Fall through, no break, incorrect cprb version is an unknown + * response */ + default: /* Unknown response type, this should NEVER EVER happen */ + xcRB->status = 0x0008044DL; /* HDD_InvalidParm */ + zdev->online = 0; + return -EAGAIN; /* repeat the request on a different device. */ + } +} + +static int convert_response_rng(struct zcrypt_device *zdev, + struct ap_message *reply, + char *data) +{ + struct type86x_reply *msg = reply->message; + + switch (msg->hdr.type) { + case TYPE82_RSP_CODE: + case TYPE88_RSP_CODE: + return -EINVAL; + case TYPE86_RSP_CODE: + if (msg->hdr.reply_code) + return -EINVAL; + if (msg->cprbx.cprb_ver_id == 0x02) + return convert_type86_rng(zdev, reply, data); + /* Fall through, no break, incorrect cprb version is an unknown + * response */ + default: /* Unknown response type, this should NEVER EVER happen */ + zdev->online = 0; + return -EAGAIN; /* repeat the request on a different device. */ + } +} + +/** + * This function is called from the AP bus code after a crypto request + * "msg" has finished with the reply message "reply". + * It is called from tasklet context. + * @ap_dev: pointer to the AP device + * @msg: pointer to the AP message + * @reply: pointer to the AP reply message + */ +static void zcrypt_pcixcc_receive(struct ap_device *ap_dev, + struct ap_message *msg, + struct ap_message *reply) +{ + static struct error_hdr error_reply = { + .type = TYPE82_RSP_CODE, + .reply_code = REP82_ERROR_MACHINE_FAILURE, + }; + struct response_type *resp_type = + (struct response_type *) msg->private; + struct type86x_reply *t86r; + int length; + + /* Copy the reply message to the request message buffer. */ + if (IS_ERR(reply)) { + memcpy(msg->message, &error_reply, sizeof(error_reply)); + goto out; + } + t86r = reply->message; + if (t86r->hdr.type == TYPE86_RSP_CODE && + t86r->cprbx.cprb_ver_id == 0x02) { + switch (resp_type->type) { + case PCIXCC_RESPONSE_TYPE_ICA: + length = sizeof(struct type86x_reply) + + t86r->length - 2; + length = min(PCIXCC_MAX_ICA_RESPONSE_SIZE, length); + memcpy(msg->message, reply->message, length); + break; + case PCIXCC_RESPONSE_TYPE_XCRB: + length = t86r->fmt2.offset2 + t86r->fmt2.count2; + length = min(PCIXCC_MAX_XCRB_MESSAGE_SIZE, length); + memcpy(msg->message, reply->message, length); + break; + default: + memcpy(msg->message, &error_reply, sizeof error_reply); + } + } else + memcpy(msg->message, reply->message, sizeof error_reply); +out: + complete(&(resp_type->work)); +} + +static atomic_t zcrypt_step = ATOMIC_INIT(0); + +/** + * The request distributor calls this function if it picked the PCIXCC/CEX2C + * device to handle a modexpo request. + * @zdev: pointer to zcrypt_device structure that identifies the + * PCIXCC/CEX2C device to the request distributor + * @mex: pointer to the modexpo request buffer + */ +static long zcrypt_pcixcc_modexpo(struct zcrypt_device *zdev, + struct ica_rsa_modexpo *mex) +{ + struct ap_message ap_msg; + struct response_type resp_type = { + .type = PCIXCC_RESPONSE_TYPE_ICA, + }; + int rc; + + ap_init_message(&ap_msg); + ap_msg.message = (void *) get_zeroed_page(GFP_KERNEL); + if (!ap_msg.message) + return -ENOMEM; + ap_msg.receive = zcrypt_pcixcc_receive; + ap_msg.psmid = (((unsigned long long) current->pid) << 32) + + atomic_inc_return(&zcrypt_step); + ap_msg.private = &resp_type; + rc = ICAMEX_msg_to_type6MEX_msgX(zdev, &ap_msg, mex); + if (rc) + goto out_free; + init_completion(&resp_type.work); + ap_queue_message(zdev->ap_dev, &ap_msg); + rc = wait_for_completion_interruptible(&resp_type.work); + if (rc == 0) + rc = convert_response_ica(zdev, &ap_msg, mex->outputdata, + mex->outputdatalength); + else + /* Signal pending. */ + ap_cancel_message(zdev->ap_dev, &ap_msg); +out_free: + free_page((unsigned long) ap_msg.message); + return rc; +} + +/** + * The request distributor calls this function if it picked the PCIXCC/CEX2C + * device to handle a modexpo_crt request. + * @zdev: pointer to zcrypt_device structure that identifies the + * PCIXCC/CEX2C device to the request distributor + * @crt: pointer to the modexpoc_crt request buffer + */ +static long zcrypt_pcixcc_modexpo_crt(struct zcrypt_device *zdev, + struct ica_rsa_modexpo_crt *crt) +{ + struct ap_message ap_msg; + struct response_type resp_type = { + .type = PCIXCC_RESPONSE_TYPE_ICA, + }; + int rc; + + ap_init_message(&ap_msg); + ap_msg.message = (void *) get_zeroed_page(GFP_KERNEL); + if (!ap_msg.message) + return -ENOMEM; + ap_msg.receive = zcrypt_pcixcc_receive; + ap_msg.psmid = (((unsigned long long) current->pid) << 32) + + atomic_inc_return(&zcrypt_step); + ap_msg.private = &resp_type; + rc = ICACRT_msg_to_type6CRT_msgX(zdev, &ap_msg, crt); + if (rc) + goto out_free; + init_completion(&resp_type.work); + ap_queue_message(zdev->ap_dev, &ap_msg); + rc = wait_for_completion_interruptible(&resp_type.work); + if (rc == 0) + rc = convert_response_ica(zdev, &ap_msg, crt->outputdata, + crt->outputdatalength); + else + /* Signal pending. */ + ap_cancel_message(zdev->ap_dev, &ap_msg); +out_free: + free_page((unsigned long) ap_msg.message); + return rc; +} + +/** + * The request distributor calls this function if it picked the PCIXCC/CEX2C + * device to handle a send_cprb request. + * @zdev: pointer to zcrypt_device structure that identifies the + * PCIXCC/CEX2C device to the request distributor + * @xcRB: pointer to the send_cprb request buffer + */ +static long zcrypt_pcixcc_send_cprb(struct zcrypt_device *zdev, + struct ica_xcRB *xcRB) +{ + struct ap_message ap_msg; + struct response_type resp_type = { + .type = PCIXCC_RESPONSE_TYPE_XCRB, + }; + int rc; + + ap_init_message(&ap_msg); + ap_msg.message = kmalloc(PCIXCC_MAX_XCRB_MESSAGE_SIZE, GFP_KERNEL); + if (!ap_msg.message) + return -ENOMEM; + ap_msg.receive = zcrypt_pcixcc_receive; + ap_msg.psmid = (((unsigned long long) current->pid) << 32) + + atomic_inc_return(&zcrypt_step); + ap_msg.private = &resp_type; + rc = XCRB_msg_to_type6CPRB_msgX(zdev, &ap_msg, xcRB); + if (rc) + goto out_free; + init_completion(&resp_type.work); + ap_queue_message(zdev->ap_dev, &ap_msg); + rc = wait_for_completion_interruptible(&resp_type.work); + if (rc == 0) + rc = convert_response_xcrb(zdev, &ap_msg, xcRB); + else + /* Signal pending. */ + ap_cancel_message(zdev->ap_dev, &ap_msg); +out_free: + kzfree(ap_msg.message); + return rc; +} + +/** + * The request distributor calls this function if it picked the PCIXCC/CEX2C + * device to generate random data. + * @zdev: pointer to zcrypt_device structure that identifies the + * PCIXCC/CEX2C device to the request distributor + * @buffer: pointer to a memory page to return random data + */ + +static long zcrypt_pcixcc_rng(struct zcrypt_device *zdev, + char *buffer) +{ + struct ap_message ap_msg; + struct response_type resp_type = { + .type = PCIXCC_RESPONSE_TYPE_XCRB, + }; + int rc; + + ap_init_message(&ap_msg); + ap_msg.message = kmalloc(PCIXCC_MAX_XCRB_MESSAGE_SIZE, GFP_KERNEL); + if (!ap_msg.message) + return -ENOMEM; + ap_msg.receive = zcrypt_pcixcc_receive; + ap_msg.psmid = (((unsigned long long) current->pid) << 32) + + atomic_inc_return(&zcrypt_step); + ap_msg.private = &resp_type; + rng_type6CPRB_msgX(zdev->ap_dev, &ap_msg, ZCRYPT_RNG_BUFFER_SIZE); + init_completion(&resp_type.work); + ap_queue_message(zdev->ap_dev, &ap_msg); + rc = wait_for_completion_interruptible(&resp_type.work); + if (rc == 0) + rc = convert_response_rng(zdev, &ap_msg, buffer); + else + /* Signal pending. */ + ap_cancel_message(zdev->ap_dev, &ap_msg); + kfree(ap_msg.message); + return rc; +} + +/** + * The crypto operations for a PCIXCC/CEX2C card. + */ +static struct zcrypt_ops zcrypt_pcixcc_ops = { + .rsa_modexpo = zcrypt_pcixcc_modexpo, + .rsa_modexpo_crt = zcrypt_pcixcc_modexpo_crt, + .send_cprb = zcrypt_pcixcc_send_cprb, +}; + +static struct zcrypt_ops zcrypt_pcixcc_with_rng_ops = { + .rsa_modexpo = zcrypt_pcixcc_modexpo, + .rsa_modexpo_crt = zcrypt_pcixcc_modexpo_crt, + .send_cprb = zcrypt_pcixcc_send_cprb, + .rng = zcrypt_pcixcc_rng, +}; + /** * Micro-code detection function. Its sends a message to a pcixcc card * to find out the microcode level. @@ -323,11 +1083,9 @@ static int zcrypt_pcixcc_probe(struct ap_device *ap_dev) return rc; } if (rc) - zdev->ops = zcrypt_msgtype_request(MSGTYPE06_NAME, - MSGTYPE06_VARIANT_DEFAULT); + zdev->ops = &zcrypt_pcixcc_with_rng_ops; else - zdev->ops = zcrypt_msgtype_request(MSGTYPE06_NAME, - MSGTYPE06_VARIANT_NORNG); + zdev->ops = &zcrypt_pcixcc_ops; ap_dev->reply = &zdev->reply; ap_dev->private = zdev; rc = zcrypt_device_register(zdev); @@ -337,7 +1095,6 @@ static int zcrypt_pcixcc_probe(struct ap_device *ap_dev) out_free: ap_dev->private = NULL; - zcrypt_msgtype_release(zdev->ops); zcrypt_device_free(zdev); return rc; } @@ -349,10 +1106,8 @@ static int zcrypt_pcixcc_probe(struct ap_device *ap_dev) static void zcrypt_pcixcc_remove(struct ap_device *ap_dev) { struct zcrypt_device *zdev = ap_dev->private; - struct zcrypt_ops *zops = zdev->ops; zcrypt_device_unregister(zdev); - zcrypt_msgtype_release(zops); } int __init zcrypt_pcixcc_init(void) diff --git a/trunk/drivers/s390/crypto/zcrypt_pcixcc.h b/trunk/drivers/s390/crypto/zcrypt_pcixcc.h index eacafc8962f2..c7cdf599e46b 100644 --- a/trunk/drivers/s390/crypto/zcrypt_pcixcc.h +++ b/trunk/drivers/s390/crypto/zcrypt_pcixcc.h @@ -1,13 +1,12 @@ /* * zcrypt 2.1.0 * - * Copyright IBM Corp. 2001, 2012 + * Copyright IBM Corp. 2001, 2006 * Author(s): Robert Burroughs * Eric Rossman (edrossma@us.ibm.com) * * Hotplug & misc device support: Jochen Roehrig (roehrig@de.ibm.com) * Major cleanup & driver split: Martin Schwidefsky - * MSGTYPE restruct: Holger Dengler * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/trunk/drivers/s390/net/qeth_core_main.c b/trunk/drivers/s390/net/qeth_core_main.c index cf6da7fafe54..7a8b09612c41 100644 --- a/trunk/drivers/s390/net/qeth_core_main.c +++ b/trunk/drivers/s390/net/qeth_core_main.c @@ -2993,7 +2993,7 @@ static void qeth_get_trap_id(struct qeth_card *card, struct qeth_trap_id *tid) struct sysinfo_2_2_2 *info222 = (struct sysinfo_2_2_2 *)info; struct sysinfo_3_2_2 *info322 = (struct sysinfo_3_2_2 *)info; struct ccw_dev_id ccwid; - int level; + int level, rc; tid->chpid = card->info.chpid; ccw_device_get_id(CARD_RDEV(card), &ccwid); @@ -3001,10 +3001,17 @@ static void qeth_get_trap_id(struct qeth_card *card, struct qeth_trap_id *tid) tid->devno = ccwid.devno; if (!info) return; - level = stsi(NULL, 0, 0, 0); - if ((level >= 2) && (stsi(info222, 2, 2, 2) == 0)) + + rc = stsi(NULL, 0, 0, 0); + if (rc == -ENOSYS) + level = rc; + else + level = (((unsigned int) rc) >> 28); + + if ((level >= 2) && (stsi(info222, 2, 2, 2) != -ENOSYS)) tid->lparnr = info222->lpar_number; - if ((level >= 3) && (stsi(info322, 3, 2, 2) == 0)) { + + if ((level >= 3) && (stsi(info322, 3, 2, 2) != -ENOSYS)) { EBCASC(info322->vm[0].name, sizeof(info322->vm[0].name)); memcpy(tid->vmname, info322->vm[0].name, sizeof(tid->vmname)); } diff --git a/trunk/drivers/scsi/aic7xxx/aic79xx_core.c b/trunk/drivers/scsi/aic7xxx/aic79xx_core.c index 0bcacf71aef8..25417d0e7acb 100644 --- a/trunk/drivers/scsi/aic7xxx/aic79xx_core.c +++ b/trunk/drivers/scsi/aic7xxx/aic79xx_core.c @@ -2888,7 +2888,7 @@ ahd_handle_lqiphase_error(struct ahd_softc *ahd, u_int lqistat1) ahd_outb(ahd, CLRINT, CLRSCSIINT); ahd_unpause(ahd); } else { - printk("Resetting Channel for LQI Phase error\n"); + printk("Reseting Channel for LQI Phase error\n"); ahd_dump_card_state(ahd); ahd_reset_channel(ahd, 'A', /*Initiate Reset*/TRUE); } diff --git a/trunk/drivers/scsi/bfa/bfa_ioc.c b/trunk/drivers/scsi/bfa/bfa_ioc.c index 21ad2902e5ce..8cdb79c2fcdf 100644 --- a/trunk/drivers/scsi/bfa/bfa_ioc.c +++ b/trunk/drivers/scsi/bfa/bfa_ioc.c @@ -5587,7 +5587,7 @@ static bfa_status_t bfa_dconf_flash_write(struct bfa_dconf_mod_s *dconf); static void bfa_dconf_init_cb(void *arg, bfa_status_t status); /* - * Beginning state of dconf module. Waiting for an event to start. + * Begining state of dconf module. Waiting for an event to start. */ static void bfa_dconf_sm_uninit(struct bfa_dconf_mod_s *dconf, enum bfa_dconf_event event) diff --git a/trunk/drivers/scsi/bfa/bfa_ioc.h b/trunk/drivers/scsi/bfa/bfa_ioc.h index 7b916e04ca56..1a99d4b5b50f 100644 --- a/trunk/drivers/scsi/bfa/bfa_ioc.h +++ b/trunk/drivers/scsi/bfa/bfa_ioc.h @@ -530,7 +530,7 @@ struct bfa_diag_results_fwping { struct bfa_diag_qtest_result_s { u32 status; - u16 count; /* successful queue test count */ + u16 count; /* sucessful queue test count */ u8 queue; u8 rsvd; /* 64-bit align */ }; diff --git a/trunk/drivers/scsi/bnx2fc/bnx2fc_fcoe.c b/trunk/drivers/scsi/bnx2fc/bnx2fc_fcoe.c index e0558656c646..ae1cb7639d99 100644 --- a/trunk/drivers/scsi/bnx2fc/bnx2fc_fcoe.c +++ b/trunk/drivers/scsi/bnx2fc/bnx2fc_fcoe.c @@ -908,7 +908,7 @@ static void bnx2fc_indicate_netevent(void *context, unsigned long event, return; default: - printk(KERN_ERR PFX "Unknown netevent %ld", event); + printk(KERN_ERR PFX "Unkonwn netevent %ld", event); return; } @@ -1738,7 +1738,7 @@ static int bnx2fc_ulp_get_stats(void *handle) /** * bnx2fc_ulp_start - cnic callback to initialize & start adapter instance * - * @handle: transport handle pointing to adapter structure + * @handle: transport handle pointing to adapter struture * * This function maps adapter structure to pcidev structure and initiates * firmware handshake to enable/initialize on-chip FCoE components. diff --git a/trunk/drivers/scsi/bnx2i/bnx2i_hwi.c b/trunk/drivers/scsi/bnx2i/bnx2i_hwi.c index 91eec60252ee..33d6630529de 100644 --- a/trunk/drivers/scsi/bnx2i/bnx2i_hwi.c +++ b/trunk/drivers/scsi/bnx2i/bnx2i_hwi.c @@ -1264,9 +1264,6 @@ int bnx2i_send_fw_iscsi_init_msg(struct bnx2i_hba *hba) int rc = 0; u64 mask64; - memset(&iscsi_init, 0x00, sizeof(struct iscsi_kwqe_init1)); - memset(&iscsi_init2, 0x00, sizeof(struct iscsi_kwqe_init2)); - bnx2i_adjust_qp_size(hba); iscsi_init.flags = diff --git a/trunk/drivers/scsi/gdth.h b/trunk/drivers/scsi/gdth.h index fbf6f0f4b0dd..d3e4d7c6f577 100644 --- a/trunk/drivers/scsi/gdth.h +++ b/trunk/drivers/scsi/gdth.h @@ -49,6 +49,15 @@ /* GDT_ISA */ #define GDT2_ID 0x0120941c /* GDT2000/2020 */ +/* vendor ID, device IDs (PCI) */ +/* these defines should already exist in */ +#ifndef PCI_VENDOR_ID_VORTEX +#define PCI_VENDOR_ID_VORTEX 0x1119 /* PCI controller vendor ID */ +#endif +#ifndef PCI_VENDOR_ID_INTEL +#define PCI_VENDOR_ID_INTEL 0x8086 +#endif + #ifndef PCI_DEVICE_ID_VORTEX_GDT60x0 /* GDT_PCI */ #define PCI_DEVICE_ID_VORTEX_GDT60x0 0 /* GDT6000/6020/6050 */ diff --git a/trunk/drivers/scsi/hpsa.c b/trunk/drivers/scsi/hpsa.c index 2b4261cb7742..796482badf13 100644 --- a/trunk/drivers/scsi/hpsa.c +++ b/trunk/drivers/scsi/hpsa.c @@ -1315,9 +1315,8 @@ static void complete_scsi_command(struct CommandList *cp) } break; case CMD_PROTOCOL_ERR: - cmd->result = DID_ERROR << 16; dev_warn(&h->pdev->dev, "cp %p has " - "protocol error\n", cp); + "protocol error \n", cp); break; case CMD_HARDWARE_ERR: cmd->result = DID_ERROR << 16; diff --git a/trunk/drivers/scsi/ipr.c b/trunk/drivers/scsi/ipr.c index 0a2c5a8ebb82..467dc38246f9 100644 --- a/trunk/drivers/scsi/ipr.c +++ b/trunk/drivers/scsi/ipr.c @@ -192,7 +192,7 @@ static const struct ipr_chip_t ipr_chip[] = { { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CROCODILE, IPR_USE_MSI, IPR_SIS64, IPR_MMIO, &ipr_chip_cfg[2] } }; -static int ipr_max_bus_speeds[] = { +static int ipr_max_bus_speeds [] = { IPR_80MBs_SCSI_RATE, IPR_U160_SCSI_RATE, IPR_U320_SCSI_RATE }; @@ -562,7 +562,7 @@ static void ipr_trc_hook(struct ipr_cmnd *ipr_cmd, trace_entry->u.add_data = add_data; } #else -#define ipr_trc_hook(ipr_cmd, type, add_data) do { } while (0) +#define ipr_trc_hook(ipr_cmd, type, add_data) do { } while(0) #endif /** @@ -1002,7 +1002,7 @@ static void ipr_send_hcam(struct ipr_ioa_cfg *ioa_cfg, u8 type, **/ static void ipr_update_ata_class(struct ipr_resource_entry *res, unsigned int proto) { - switch (proto) { + switch(proto) { case IPR_PROTO_SATA: case IPR_PROTO_SAS_STP: res->ata_class = ATA_DEV_ATA; @@ -3043,7 +3043,7 @@ static void ipr_get_ioa_dump(struct ipr_ioa_cfg *ioa_cfg, struct ipr_dump *dump) } #else -#define ipr_get_ioa_dump(ioa_cfg, dump) do { } while (0) +#define ipr_get_ioa_dump(ioa_cfg, dump) do { } while(0) #endif /** @@ -3055,7 +3055,7 @@ static void ipr_get_ioa_dump(struct ipr_ioa_cfg *ioa_cfg, struct ipr_dump *dump) **/ static void ipr_release_dump(struct kref *kref) { - struct ipr_dump *dump = container_of(kref, struct ipr_dump, kref); + struct ipr_dump *dump = container_of(kref,struct ipr_dump,kref); struct ipr_ioa_cfg *ioa_cfg = dump->ioa_cfg; unsigned long lock_flags = 0; int i; @@ -3142,7 +3142,7 @@ static void ipr_worker_thread(struct work_struct *work) break; } } - } while (did_work); + } while(did_work); list_for_each_entry(res, &ioa_cfg->used_res_q, queue) { if (res->add_to_ml) { @@ -3268,7 +3268,7 @@ static ssize_t ipr_show_log_level(struct device *dev, * number of bytes printed to buffer **/ static ssize_t ipr_store_log_level(struct device *dev, - struct device_attribute *attr, + struct device_attribute *attr, const char *buf, size_t count) { struct Scsi_Host *shost = class_to_shost(dev); @@ -3315,7 +3315,7 @@ static ssize_t ipr_store_diagnostics(struct device *dev, return -EACCES; spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags); - while (ioa_cfg->in_reset_reload) { + while(ioa_cfg->in_reset_reload) { spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); wait_event(ioa_cfg->reset_wait_q, !ioa_cfg->in_reset_reload); spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags); @@ -3682,7 +3682,7 @@ static int ipr_update_ioa_ucode(struct ipr_ioa_cfg *ioa_cfg, unsigned long lock_flags; spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags); - while (ioa_cfg->in_reset_reload) { + while(ioa_cfg->in_reset_reload) { spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); wait_event(ioa_cfg->reset_wait_q, !ioa_cfg->in_reset_reload); spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags); @@ -3746,7 +3746,7 @@ static ssize_t ipr_store_update_fw(struct device *dev, len = snprintf(fname, 99, "%s", buf); fname[len-1] = '\0'; - if (request_firmware(&fw_entry, fname, &ioa_cfg->pdev->dev)) { + if(request_firmware(&fw_entry, fname, &ioa_cfg->pdev->dev)) { dev_err(&ioa_cfg->pdev->dev, "Firmware file %s not found\n", fname); return -EIO; } @@ -4612,7 +4612,7 @@ static int ipr_slave_alloc(struct scsi_device *sdev) * Return value: * SUCCESS / FAILED **/ -static int __ipr_eh_host_reset(struct scsi_cmnd *scsi_cmd) +static int __ipr_eh_host_reset(struct scsi_cmnd * scsi_cmd) { struct ipr_ioa_cfg *ioa_cfg; int rc; @@ -4634,7 +4634,7 @@ static int __ipr_eh_host_reset(struct scsi_cmnd *scsi_cmd) return rc; } -static int ipr_eh_host_reset(struct scsi_cmnd *cmd) +static int ipr_eh_host_reset(struct scsi_cmnd * cmd) { int rc; @@ -4701,7 +4701,7 @@ static int ipr_device_reset(struct ipr_ioa_cfg *ioa_cfg, } LEAVE; - return IPR_IOASC_SENSE_KEY(ioasc) ? -EIO : 0; + return (IPR_IOASC_SENSE_KEY(ioasc) ? -EIO : 0); } /** @@ -4725,7 +4725,7 @@ static int ipr_sata_reset(struct ata_link *link, unsigned int *classes, ENTER; spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags); - while (ioa_cfg->in_reset_reload) { + while(ioa_cfg->in_reset_reload) { spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); wait_event(ioa_cfg->reset_wait_q, !ioa_cfg->in_reset_reload); spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags); @@ -4753,7 +4753,7 @@ static int ipr_sata_reset(struct ata_link *link, unsigned int *classes, * Return value: * SUCCESS / FAILED **/ -static int __ipr_eh_dev_reset(struct scsi_cmnd *scsi_cmd) +static int __ipr_eh_dev_reset(struct scsi_cmnd * scsi_cmd) { struct ipr_cmnd *ipr_cmd; struct ipr_ioa_cfg *ioa_cfg; @@ -4811,10 +4811,10 @@ static int __ipr_eh_dev_reset(struct scsi_cmnd *scsi_cmd) res->resetting_device = 0; LEAVE; - return rc ? FAILED : SUCCESS; + return (rc ? FAILED : SUCCESS); } -static int ipr_eh_dev_reset(struct scsi_cmnd *cmd) +static int ipr_eh_dev_reset(struct scsi_cmnd * cmd) { int rc; @@ -4910,7 +4910,7 @@ static void ipr_abort_timeout(struct ipr_cmnd *ipr_cmd) * Return value: * SUCCESS / FAILED **/ -static int ipr_cancel_op(struct scsi_cmnd *scsi_cmd) +static int ipr_cancel_op(struct scsi_cmnd * scsi_cmd) { struct ipr_cmnd *ipr_cmd; struct ipr_ioa_cfg *ioa_cfg; @@ -4979,7 +4979,7 @@ static int ipr_cancel_op(struct scsi_cmnd *scsi_cmd) res->needs_sync_complete = 1; LEAVE; - return IPR_IOASC_SENSE_KEY(ioasc) ? FAILED : SUCCESS; + return (IPR_IOASC_SENSE_KEY(ioasc) ? FAILED : SUCCESS); } /** @@ -4989,7 +4989,7 @@ static int ipr_cancel_op(struct scsi_cmnd *scsi_cmd) * Return value: * SUCCESS / FAILED **/ -static int ipr_eh_abort(struct scsi_cmnd *scsi_cmd) +static int ipr_eh_abort(struct scsi_cmnd * scsi_cmd) { unsigned long flags; int rc; @@ -5907,7 +5907,7 @@ static int ipr_ioctl(struct scsi_device *sdev, int cmd, void __user *arg) * Return value: * pointer to buffer with description string **/ -static const char *ipr_ioa_info(struct Scsi_Host *host) +static const char * ipr_ioa_info(struct Scsi_Host *host) { static char buffer[512]; struct ipr_ioa_cfg *ioa_cfg; @@ -5965,7 +5965,7 @@ static void ipr_ata_phy_reset(struct ata_port *ap) ENTER; spin_lock_irqsave(ioa_cfg->host->host_lock, flags); - while (ioa_cfg->in_reset_reload) { + while(ioa_cfg->in_reset_reload) { spin_unlock_irqrestore(ioa_cfg->host->host_lock, flags); wait_event(ioa_cfg->reset_wait_q, !ioa_cfg->in_reset_reload); spin_lock_irqsave(ioa_cfg->host->host_lock, flags); @@ -6005,7 +6005,7 @@ static void ipr_ata_post_internal(struct ata_queued_cmd *qc) unsigned long flags; spin_lock_irqsave(ioa_cfg->host->host_lock, flags); - while (ioa_cfg->in_reset_reload) { + while(ioa_cfg->in_reset_reload) { spin_unlock_irqrestore(ioa_cfg->host->host_lock, flags); wait_event(ioa_cfg->reset_wait_q, !ioa_cfg->in_reset_reload); spin_lock_irqsave(ioa_cfg->host->host_lock, flags); @@ -6330,7 +6330,7 @@ static int ipr_invalid_adapter(struct ipr_ioa_cfg *ioa_cfg) int i; if ((ioa_cfg->type == 0x5702) && (ioa_cfg->pdev->revision < 4)) { - for (i = 0; i < ARRAY_SIZE(ipr_blocked_processors); i++) { + for (i = 0; i < ARRAY_SIZE(ipr_blocked_processors); i++){ if (__is_processor(ipr_blocked_processors[i])) return 1; } @@ -6608,7 +6608,7 @@ static void ipr_scsi_bus_speed_limit(struct ipr_ioa_cfg *ioa_cfg) * none **/ static void ipr_modify_ioafp_mode_page_28(struct ipr_ioa_cfg *ioa_cfg, - struct ipr_mode_pages *mode_pages) + struct ipr_mode_pages *mode_pages) { int i, entry_length; struct ipr_dev_bus_entry *bus; @@ -8022,7 +8022,7 @@ static void ipr_reset_ioa_job(struct ipr_cmnd *ipr_cmd) ipr_reinit_ipr_cmnd(ipr_cmd); ipr_cmd->job_step_failed = ipr_reset_cmd_failed; rc = ipr_cmd->job_step(ipr_cmd); - } while (rc == IPR_RC_JOB_CONTINUE); + } while(rc == IPR_RC_JOB_CONTINUE); } /** @@ -8283,7 +8283,7 @@ static void ipr_free_cmd_blks(struct ipr_ioa_cfg *ioa_cfg) } if (ioa_cfg->ipr_cmd_pool) - pci_pool_destroy(ioa_cfg->ipr_cmd_pool); + pci_pool_destroy (ioa_cfg->ipr_cmd_pool); kfree(ioa_cfg->ipr_cmnd_list); kfree(ioa_cfg->ipr_cmnd_list_dma); @@ -8363,8 +8363,8 @@ static int __devinit ipr_alloc_cmd_blks(struct ipr_ioa_cfg *ioa_cfg) dma_addr_t dma_addr; int i; - ioa_cfg->ipr_cmd_pool = pci_pool_create(IPR_NAME, ioa_cfg->pdev, - sizeof(struct ipr_cmnd), 512, 0); + ioa_cfg->ipr_cmd_pool = pci_pool_create (IPR_NAME, ioa_cfg->pdev, + sizeof(struct ipr_cmnd), 512, 0); if (!ioa_cfg->ipr_cmd_pool) return -ENOMEM; @@ -8378,7 +8378,7 @@ static int __devinit ipr_alloc_cmd_blks(struct ipr_ioa_cfg *ioa_cfg) } for (i = 0; i < IPR_NUM_CMD_BLKS; i++) { - ipr_cmd = pci_pool_alloc(ioa_cfg->ipr_cmd_pool, GFP_KERNEL, &dma_addr); + ipr_cmd = pci_pool_alloc (ioa_cfg->ipr_cmd_pool, GFP_KERNEL, &dma_addr); if (!ipr_cmd) { ipr_free_cmd_blks(ioa_cfg); @@ -8964,7 +8964,7 @@ static void ipr_scan_vsets(struct ipr_ioa_cfg *ioa_cfg) int target, lun; for (target = 0; target < IPR_MAX_NUM_TARGETS_PER_BUS; target++) - for (lun = 0; lun < IPR_MAX_NUM_VSET_LUNS_PER_TARGET; lun++) + for (lun = 0; lun < IPR_MAX_NUM_VSET_LUNS_PER_TARGET; lun++ ) scsi_add_device(ioa_cfg->host, IPR_VSET_BUS, target, lun); } @@ -9010,7 +9010,7 @@ static void __ipr_remove(struct pci_dev *pdev) ENTER; spin_lock_irqsave(ioa_cfg->host->host_lock, host_lock_flags); - while (ioa_cfg->in_reset_reload) { + while(ioa_cfg->in_reset_reload) { spin_unlock_irqrestore(ioa_cfg->host->host_lock, host_lock_flags); wait_event(ioa_cfg->reset_wait_q, !ioa_cfg->in_reset_reload); spin_lock_irqsave(ioa_cfg->host->host_lock, host_lock_flags); @@ -9139,7 +9139,7 @@ static void ipr_shutdown(struct pci_dev *pdev) unsigned long lock_flags = 0; spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags); - while (ioa_cfg->in_reset_reload) { + while(ioa_cfg->in_reset_reload) { spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); wait_event(ioa_cfg->reset_wait_q, !ioa_cfg->in_reset_reload); spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags); @@ -9228,7 +9228,7 @@ static struct pci_device_id ipr_pci_table[] __devinitdata = { }; MODULE_DEVICE_TABLE(pci, ipr_pci_table); -static const struct pci_error_handlers ipr_err_handler = { +static struct pci_error_handlers ipr_err_handler = { .error_detected = ipr_pci_error_detected, .slot_reset = ipr_pci_slot_reset, }; diff --git a/trunk/drivers/scsi/isci/host.c b/trunk/drivers/scsi/isci/host.c index b334fdc1726a..45385f531649 100644 --- a/trunk/drivers/scsi/isci/host.c +++ b/trunk/drivers/scsi/isci/host.c @@ -492,7 +492,7 @@ static void sci_controller_process_completions(struct isci_host *ihost) u32 event_cycle; dev_dbg(&ihost->pdev->dev, - "%s: completion queue beginning get:0x%08x\n", + "%s: completion queue begining get:0x%08x\n", __func__, ihost->completion_queue_get); diff --git a/trunk/drivers/scsi/isci/init.c b/trunk/drivers/scsi/isci/init.c index 9be45a2b2232..92c1d86d1fc6 100644 --- a/trunk/drivers/scsi/isci/init.c +++ b/trunk/drivers/scsi/isci/init.c @@ -222,7 +222,7 @@ static struct sas_domain_function_template isci_transport_ops = { * @isci_host: This parameter specifies the lldd specific wrapper for the * libsas sas_ha struct. * - * This method returns an error code indicating success or failure. The user + * This method returns an error code indicating sucess or failure. The user * should check for possible memory allocation error return otherwise, a zero * indicates success. */ diff --git a/trunk/drivers/scsi/isci/port.c b/trunk/drivers/scsi/isci/port.c index 13098b09a824..2fb85bf75449 100644 --- a/trunk/drivers/scsi/isci/port.c +++ b/trunk/drivers/scsi/isci/port.c @@ -212,7 +212,7 @@ static void isci_port_link_up(struct isci_host *isci_host, memcpy(iphy->sas_phy.attached_sas_addr, iphy->frame_rcvd.iaf.sas_addr, SAS_ADDR_SIZE); } else { - dev_err(&isci_host->pdev->dev, "%s: unknown target\n", __func__); + dev_err(&isci_host->pdev->dev, "%s: unkown target\n", __func__); success = false; } diff --git a/trunk/drivers/scsi/isci/request.c b/trunk/drivers/scsi/isci/request.c index c1bafc3f3fb1..7a0431c73493 100644 --- a/trunk/drivers/scsi/isci/request.c +++ b/trunk/drivers/scsi/isci/request.c @@ -2240,7 +2240,7 @@ static enum sci_status atapi_data_tc_completion_handler(struct isci_request *ire status = ireq->sci_status; sci_change_state(&idev->sm, SCI_STP_DEV_ATAPI_ERROR); } else { - /* If receiving any non-success TC status, no UF + /* If receiving any non-sucess TC status, no UF * received yet, then an UF for the status fis * is coming after (XXX: suspect this is * actually a protocol error or a bug like the diff --git a/trunk/drivers/scsi/isci/task.c b/trunk/drivers/scsi/isci/task.c index b6f19a1db780..6bc74eb012c9 100644 --- a/trunk/drivers/scsi/isci/task.c +++ b/trunk/drivers/scsi/isci/task.c @@ -532,7 +532,7 @@ int isci_task_abort_task(struct sas_task *task) /* The request has already completed and there * is nothing to do here other than to set the task * done bit, and indicate that the task abort function - * was successful. + * was sucessful. */ spin_lock_irqsave(&task->task_state_lock, flags); task->task_state_flags |= SAS_TASK_STATE_DONE; diff --git a/trunk/drivers/scsi/lpfc/lpfc_init.c b/trunk/drivers/scsi/lpfc/lpfc_init.c index 628a703abddb..45c15208be9f 100644 --- a/trunk/drivers/scsi/lpfc/lpfc_init.c +++ b/trunk/drivers/scsi/lpfc/lpfc_init.c @@ -6607,7 +6607,7 @@ lpfc_sli4_queue_verify(struct lpfc_hba *phba) * we just use some constant number as place holder. * * Return codes - * 0 - successful + * 0 - sucessful * -ENOMEM - No availble memory * -EIO - The mailbox failed to complete successfully. **/ @@ -10425,7 +10425,7 @@ static struct pci_device_id lpfc_id_table[] = { MODULE_DEVICE_TABLE(pci, lpfc_id_table); -static const struct pci_error_handlers lpfc_err_handler = { +static struct pci_error_handlers lpfc_err_handler = { .error_detected = lpfc_io_error_detected, .slot_reset = lpfc_io_slot_reset, .resume = lpfc_io_resume, diff --git a/trunk/drivers/scsi/lpfc/lpfc_sli.c b/trunk/drivers/scsi/lpfc/lpfc_sli.c index 0e7e144507b2..9cbd20b1328b 100644 --- a/trunk/drivers/scsi/lpfc/lpfc_sli.c +++ b/trunk/drivers/scsi/lpfc/lpfc_sli.c @@ -4739,7 +4739,7 @@ lpfc_sli4_read_rev(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq, * is attached to. * * Return codes - * 0 - successful + * 0 - sucessful * otherwise - failed to retrieve physical port name **/ static int @@ -15209,7 +15209,7 @@ lpfc_check_next_fcf_pri_level(struct lpfc_hba *phba) /* * if next_fcf_pri was not set above and the list is not empty then * we have failed flogis on all of them. So reset flogi failed - * and start at the beginning. + * and start at the begining. */ if (!next_fcf_pri && !list_empty(&phba->fcf.fcf_pri_list)) { list_for_each_entry(fcf_pri, &phba->fcf.fcf_pri_list, list) { diff --git a/trunk/drivers/scsi/megaraid.c b/trunk/drivers/scsi/megaraid.c index 76ad72d32c3f..97825f116954 100644 --- a/trunk/drivers/scsi/megaraid.c +++ b/trunk/drivers/scsi/megaraid.c @@ -305,11 +305,12 @@ mega_query_adapter(adapter_t *adapter) adapter->host->sg_tablesize = adapter->sglen; + /* use HP firmware and bios version encoding Note: fw_version[0|1] and bios_version[0|1] were originally shifted right 8 bits making them zero. This 0 value was hardcoded to fix sparse warnings. */ - if (adapter->product_info.subsysvid == PCI_VENDOR_ID_HP) { + if (adapter->product_info.subsysvid == HP_SUBSYS_VID) { sprintf (adapter->fw_version, "%c%d%d.%d%d", adapter->product_info.fw_version[2], 0, @@ -4715,7 +4716,7 @@ megaraid_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) * support, since this firmware cannot handle 64 bit * addressing */ - if ((subsysvid == PCI_VENDOR_ID_HP) && + if ((subsysvid == HP_SUBSYS_VID) && ((subsysid == 0x60E7) || (subsysid == 0x60E8))) { /* * which firmware diff --git a/trunk/drivers/scsi/megaraid.h b/trunk/drivers/scsi/megaraid.h index 4fb2adf6b80d..9a7897f8ca43 100644 --- a/trunk/drivers/scsi/megaraid.h +++ b/trunk/drivers/scsi/megaraid.h @@ -45,10 +45,45 @@ #define MAX_DEV_TYPE 32 +#ifndef PCI_VENDOR_ID_LSI_LOGIC +#define PCI_VENDOR_ID_LSI_LOGIC 0x1000 +#endif + +#ifndef PCI_VENDOR_ID_AMI +#define PCI_VENDOR_ID_AMI 0x101E +#endif + +#ifndef PCI_VENDOR_ID_DELL +#define PCI_VENDOR_ID_DELL 0x1028 +#endif + +#ifndef PCI_VENDOR_ID_INTEL +#define PCI_VENDOR_ID_INTEL 0x8086 +#endif + +#ifndef PCI_DEVICE_ID_AMI_MEGARAID +#define PCI_DEVICE_ID_AMI_MEGARAID 0x9010 +#endif + +#ifndef PCI_DEVICE_ID_AMI_MEGARAID2 +#define PCI_DEVICE_ID_AMI_MEGARAID2 0x9060 +#endif + +#ifndef PCI_DEVICE_ID_AMI_MEGARAID3 +#define PCI_DEVICE_ID_AMI_MEGARAID3 0x1960 +#endif + #define PCI_DEVICE_ID_DISCOVERY 0x000E #define PCI_DEVICE_ID_PERC4_DI 0x000F #define PCI_DEVICE_ID_PERC4_QC_VERDE 0x0407 +/* Sub-System Vendor IDs */ +#define AMI_SUBSYS_VID 0x101E +#define DELL_SUBSYS_VID 0x1028 +#define HP_SUBSYS_VID 0x103C +#define LSI_SUBSYS_VID 0x1000 +#define INTEL_SUBSYS_VID 0x8086 + #define HBA_SIGNATURE 0x3344 #define HBA_SIGNATURE_471 0xCCCC #define HBA_SIGNATURE_64BIT 0x0299 diff --git a/trunk/drivers/scsi/megaraid/megaraid_sas_base.c b/trunk/drivers/scsi/megaraid/megaraid_sas_base.c index ed38454228c6..dc27598785e5 100644 --- a/trunk/drivers/scsi/megaraid/megaraid_sas_base.c +++ b/trunk/drivers/scsi/megaraid/megaraid_sas_base.c @@ -4066,6 +4066,7 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) spin_lock_init(&instance->cmd_pool_lock); spin_lock_init(&instance->hba_lock); spin_lock_init(&instance->completion_lock); + spin_lock_init(&poll_aen_lock); mutex_init(&instance->aen_mutex); mutex_init(&instance->reset_mutex); @@ -5391,8 +5392,6 @@ static int __init megasas_init(void) printk(KERN_INFO "megasas: %s %s\n", MEGASAS_VERSION, MEGASAS_EXT_VERSION); - spin_lock_init(&poll_aen_lock); - support_poll_for_event = 2; support_device_change = 1; diff --git a/trunk/drivers/scsi/mpt2sas/mpt2sas_base.c b/trunk/drivers/scsi/mpt2sas/mpt2sas_base.c index 9d5a56c4b332..9d46fcbe7755 100644 --- a/trunk/drivers/scsi/mpt2sas/mpt2sas_base.c +++ b/trunk/drivers/scsi/mpt2sas/mpt2sas_base.c @@ -1209,13 +1209,6 @@ _base_check_enable_msix(struct MPT2SAS_ADAPTER *ioc) u16 message_control; - /* Check whether controller SAS2008 B0 controller, - if it is SAS2008 B0 controller use IO-APIC instead of MSIX */ - if (ioc->pdev->device == MPI2_MFGPAGE_DEVID_SAS2008 && - ioc->pdev->revision == 0x01) { - return -EINVAL; - } - base = pci_find_capability(ioc->pdev, PCI_CAP_ID_MSIX); if (!base) { dfailprintk(ioc, printk(MPT2SAS_INFO_FMT "msix not " @@ -2431,13 +2424,10 @@ _base_allocate_memory_pools(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) } /* command line tunables for max controller queue depth */ - if (max_queue_depth != -1 && max_queue_depth != 0) { - max_request_credit = min_t(u16, max_queue_depth + - ioc->hi_priority_depth + ioc->internal_depth, - facts->RequestCredit); - if (max_request_credit > MAX_HBA_QUEUE_DEPTH) - max_request_credit = MAX_HBA_QUEUE_DEPTH; - } else + if (max_queue_depth != -1) + max_request_credit = (max_queue_depth < facts->RequestCredit) + ? max_queue_depth : facts->RequestCredit; + else max_request_credit = min_t(u16, facts->RequestCredit, MAX_HBA_QUEUE_DEPTH); @@ -2512,7 +2502,7 @@ _base_allocate_memory_pools(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) /* set the scsi host can_queue depth * with some internal commands that could be outstanding */ - ioc->shost->can_queue = ioc->scsiio_depth; + ioc->shost->can_queue = ioc->scsiio_depth - (2); dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "scsi host: " "can_queue depth (%d)\n", ioc->name, ioc->shost->can_queue)); diff --git a/trunk/drivers/scsi/mpt2sas/mpt2sas_scsih.c b/trunk/drivers/scsi/mpt2sas/mpt2sas_scsih.c index 1ccae45c5270..b1ebd6f8dab3 100644 --- a/trunk/drivers/scsi/mpt2sas/mpt2sas_scsih.c +++ b/trunk/drivers/scsi/mpt2sas/mpt2sas_scsih.c @@ -8306,7 +8306,7 @@ _scsih_pci_mmio_enabled(struct pci_dev *pdev) return PCI_ERS_RESULT_NEED_RESET; } -static const struct pci_error_handlers _scsih_err_handler = { +static struct pci_error_handlers _scsih_err_handler = { .error_detected = _scsih_pci_error_detected, .mmio_enabled = _scsih_pci_mmio_enabled, .slot_reset = _scsih_pci_slot_reset, diff --git a/trunk/drivers/scsi/mvumi.c b/trunk/drivers/scsi/mvumi.c index 783edc7c6b98..88cf1db21a79 100644 --- a/trunk/drivers/scsi/mvumi.c +++ b/trunk/drivers/scsi/mvumi.c @@ -122,7 +122,7 @@ static struct mvumi_res *mvumi_alloc_mem_resource(struct mvumi_hba *mhba, if (!res) { dev_err(&mhba->pdev->dev, - "Failed to allocate memory for resource manager.\n"); + "Failed to allocate memory for resouce manager.\n"); return NULL; } @@ -1007,13 +1007,13 @@ static int mvumi_handshake(struct mvumi_hba *mhba) tmp |= INT_MAP_COMAOUT | INT_MAP_COMAERR; iowrite32(tmp, regs + CPU_ENPOINTA_MASK_REG); iowrite32(mhba->list_num_io, mhba->ib_shadow); - /* Set InBound List Available count shadow */ + /* Set InBound List Avaliable count shadow */ iowrite32(lower_32_bits(mhba->ib_shadow_phys), regs + CLA_INB_AVAL_COUNT_BASEL); iowrite32(upper_32_bits(mhba->ib_shadow_phys), regs + CLA_INB_AVAL_COUNT_BASEH); - /* Set OutBound List Available count shadow */ + /* Set OutBound List Avaliable count shadow */ iowrite32((mhba->list_num_io-1) | CL_POINTER_TOGGLE, mhba->ob_shadow); iowrite32(lower_32_bits(mhba->ob_shadow_phys), regs + 0x5B0); diff --git a/trunk/drivers/scsi/qla2xxx/qla_nx.c b/trunk/drivers/scsi/qla2xxx/qla_nx.c index 7cfdf2bd8edb..9ce3a8f8754f 100644 --- a/trunk/drivers/scsi/qla2xxx/qla_nx.c +++ b/trunk/drivers/scsi/qla2xxx/qla_nx.c @@ -1615,11 +1615,13 @@ qla82xx_get_fw_offs(struct qla_hw_data *ha) char * qla82xx_pci_info_str(struct scsi_qla_host *vha, char *str) { + int pcie_reg; struct qla_hw_data *ha = vha->hw; char lwstr[6]; uint16_t lnk; - pcie_capability_read_word(ha->pdev, PCI_EXP_LNKSTA, &lnk); + pcie_reg = pci_pcie_cap(ha->pdev); + pci_read_config_word(ha->pdev, pcie_reg + PCI_EXP_LNKSTA, &lnk); ha->link_width = (lnk >> 4) & 0x3f; strcpy(str, "PCIe ("); @@ -2495,6 +2497,7 @@ qla82xx_load_fw(scsi_qla_host_t *vha) int qla82xx_start_firmware(scsi_qla_host_t *vha) { + int pcie_cap; uint16_t lnk; struct qla_hw_data *ha = vha->hw; @@ -2525,7 +2528,8 @@ qla82xx_start_firmware(scsi_qla_host_t *vha) } /* Negotiated Link width */ - pcie_capability_read_word(ha->pdev, PCI_EXP_LNKSTA, &lnk); + pcie_cap = pci_pcie_cap(ha->pdev); + pci_read_config_word(ha->pdev, pcie_cap + PCI_EXP_LNKSTA, &lnk); ha->link_width = (lnk >> 4) & 0x3f; /* Synchronize with Receive peg */ diff --git a/trunk/drivers/scsi/qla2xxx/qla_os.c b/trunk/drivers/scsi/qla2xxx/qla_os.c index d3052622e77a..fb8cd3847d4b 100644 --- a/trunk/drivers/scsi/qla2xxx/qla_os.c +++ b/trunk/drivers/scsi/qla2xxx/qla_os.c @@ -4471,7 +4471,7 @@ qla2xxx_pci_resume(struct pci_dev *pdev) ha->flags.eeh_busy = 0; } -static const struct pci_error_handlers qla2xxx_err_handler = { +static struct pci_error_handlers qla2xxx_err_handler = { .error_detected = qla2xxx_pci_error_detected, .mmio_enabled = qla2xxx_pci_mmio_enabled, .slot_reset = qla2xxx_pci_slot_reset, diff --git a/trunk/drivers/scsi/qla4xxx/ql4_nx.c b/trunk/drivers/scsi/qla4xxx/ql4_nx.c index 807bf76f1b6a..939d7261c37a 100644 --- a/trunk/drivers/scsi/qla4xxx/ql4_nx.c +++ b/trunk/drivers/scsi/qla4xxx/ql4_nx.c @@ -1566,6 +1566,7 @@ qla4_8xxx_set_qsnt_ready(struct scsi_qla_host *ha) static int qla4_8xxx_start_firmware(struct scsi_qla_host *ha, uint32_t image_start) { + int pcie_cap; uint16_t lnk; /* scrub dma mask expansion register */ @@ -1589,7 +1590,8 @@ qla4_8xxx_start_firmware(struct scsi_qla_host *ha, uint32_t image_start) } /* Negotiated Link width */ - pcie_capability_read_word(ha->pdev, PCI_EXP_LNKSTA, &lnk); + pcie_cap = pci_pcie_cap(ha->pdev); + pci_read_config_word(ha->pdev, pcie_cap + PCI_EXP_LNKSTA, &lnk); ha->link_width = (lnk >> 4) & 0x3f; /* Synchronize with Receive peg */ diff --git a/trunk/drivers/scsi/qla4xxx/ql4_os.c b/trunk/drivers/scsi/qla4xxx/ql4_os.c index 79243b76d17e..9da426628b97 100644 --- a/trunk/drivers/scsi/qla4xxx/ql4_os.c +++ b/trunk/drivers/scsi/qla4xxx/ql4_os.c @@ -803,7 +803,7 @@ static void qla4xxx_conn_get_stats(struct iscsi_cls_conn *cls_conn, iscsi_stats_dma); if (ret != QLA_SUCCESS) { ql4_printk(KERN_ERR, ha, - "Unable to retrieve iscsi stats\n"); + "Unable to retreive iscsi stats\n"); goto free_stats; } @@ -4338,7 +4338,7 @@ static int qla4xxx_compare_tuple_ddb(struct scsi_qla_host *ha, return QLA_ERROR; /* For multi sessions, driver generates the ISID, so do not compare - * ISID in reset path since it would be a comparison between the + * ISID in reset path since it would be a comparision between the * driver generated ISID and firmware generated ISID. This could * lead to adding duplicated DDBs in the list as driver generated * ISID would not match firmware generated ISID. @@ -5326,7 +5326,7 @@ static void qla4xxx_destroy_fw_ddb_session(struct scsi_qla_host *ha) } } /** - * qla4xxx_remove_adapter - callback function to remove adapter. + * qla4xxx_remove_adapter - calback function to remove adapter. * @pci_dev: PCI device pointer **/ static void __devexit qla4xxx_remove_adapter(struct pci_dev *pdev) @@ -6148,7 +6148,7 @@ qla4xxx_pci_resume(struct pci_dev *pdev) clear_bit(AF_EEH_BUSY, &ha->flags); } -static const struct pci_error_handlers qla4xxx_err_handler = { +static struct pci_error_handlers qla4xxx_err_handler = { .error_detected = qla4xxx_pci_error_detected, .mmio_enabled = qla4xxx_pci_mmio_enabled, .slot_reset = qla4xxx_pci_slot_reset, diff --git a/trunk/drivers/scsi/scsi_error.c b/trunk/drivers/scsi/scsi_error.c index de2337f255a7..4a6381c87253 100644 --- a/trunk/drivers/scsi/scsi_error.c +++ b/trunk/drivers/scsi/scsi_error.c @@ -42,8 +42,6 @@ #include -static void scsi_eh_done(struct scsi_cmnd *scmd); - #define SENSE_TIMEOUT (10*HZ) /* @@ -243,14 +241,6 @@ static int scsi_check_sense(struct scsi_cmnd *scmd) if (! scsi_command_normalize_sense(scmd, &sshdr)) return FAILED; /* no valid sense data */ - if (scmd->cmnd[0] == TEST_UNIT_READY && scmd->scsi_done != scsi_eh_done) - /* - * nasty: for mid-layer issued TURs, we need to return the - * actual sense data without any recovery attempt. For eh - * issued ones, we need to try to recover and interpret - */ - return SUCCESS; - if (scsi_sense_is_deferred(&sshdr)) return NEEDS_RETRY; diff --git a/trunk/drivers/scsi/scsi_lib.c b/trunk/drivers/scsi/scsi_lib.c index faa790fba134..ffd77739ae3e 100644 --- a/trunk/drivers/scsi/scsi_lib.c +++ b/trunk/drivers/scsi/scsi_lib.c @@ -776,6 +776,7 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes) } if (req->cmd_type == REQ_TYPE_BLOCK_PC) { /* SG_IO ioctl from block level */ + req->errors = result; if (result) { if (sense_valid && req->sense) { /* @@ -791,10 +792,6 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes) if (!sense_deferred) error = __scsi_error_from_host_byte(cmd, result); } - /* - * __scsi_error_from_host_byte may have reset the host_byte - */ - req->errors = cmd->result; req->resid_len = scsi_get_resid(cmd); diff --git a/trunk/drivers/scsi/scsi_scan.c b/trunk/drivers/scsi/scsi_scan.c index d947ffc20ceb..56a93794c470 100644 --- a/trunk/drivers/scsi/scsi_scan.c +++ b/trunk/drivers/scsi/scsi_scan.c @@ -764,16 +764,6 @@ static int scsi_add_lun(struct scsi_device *sdev, unsigned char *inq_result, sdev->model = (char *) (sdev->inquiry + 16); sdev->rev = (char *) (sdev->inquiry + 32); - if (strncmp(sdev->vendor, "ATA ", 8) == 0) { - /* - * sata emulation layer device. This is a hack to work around - * the SATL power management specifications which state that - * when the SATL detects the device has gone into standby - * mode, it shall respond with NOT READY. - */ - sdev->allow_restart = 1; - } - if (*bflags & BLIST_ISROM) { sdev->type = TYPE_ROM; sdev->removable = 1; diff --git a/trunk/drivers/scsi/sym53c8xx_2/sym_glue.c b/trunk/drivers/scsi/sym53c8xx_2/sym_glue.c index e2b8e68b57e7..36d1ed7817eb 100644 --- a/trunk/drivers/scsi/sym53c8xx_2/sym_glue.c +++ b/trunk/drivers/scsi/sym53c8xx_2/sym_glue.c @@ -2117,7 +2117,7 @@ static struct pci_device_id sym2_id_table[] __devinitdata = { MODULE_DEVICE_TABLE(pci, sym2_id_table); -static const struct pci_error_handlers sym2_err_handler = { +static struct pci_error_handlers sym2_err_handler = { .error_detected = sym2_io_error_detected, .mmio_enabled = sym2_io_slot_dump, .slot_reset = sym2_io_slot_reset, diff --git a/trunk/drivers/scsi/virtio_scsi.c b/trunk/drivers/scsi/virtio_scsi.c index 3e79a2f00042..c7030fbee79c 100644 --- a/trunk/drivers/scsi/virtio_scsi.c +++ b/trunk/drivers/scsi/virtio_scsi.c @@ -331,7 +331,7 @@ static void virtscsi_map_sgl(struct scatterlist *sg, unsigned int *p_idx, int i; for_each_sg(table->sgl, sg_elem, table->nents, i) - sg[idx++] = *sg_elem; + sg_set_buf(&sg[idx++], sg_virt(sg_elem), sg_elem->length); *p_idx = idx; } diff --git a/trunk/drivers/scsi/vmw_pvscsi.c b/trunk/drivers/scsi/vmw_pvscsi.c index 20b3a483c2cc..4411d4224401 100644 --- a/trunk/drivers/scsi/vmw_pvscsi.c +++ b/trunk/drivers/scsi/vmw_pvscsi.c @@ -295,7 +295,7 @@ static void ll_adapter_reset(const struct pvscsi_adapter *adapter) static void ll_bus_reset(const struct pvscsi_adapter *adapter) { - dev_dbg(pvscsi_dev(adapter), "Resetting bus on %p\n", adapter); + dev_dbg(pvscsi_dev(adapter), "Reseting bus on %p\n", adapter); pvscsi_write_cmd_desc(adapter, PVSCSI_CMD_RESET_BUS, NULL, 0); } @@ -304,7 +304,7 @@ static void ll_device_reset(const struct pvscsi_adapter *adapter, u32 target) { struct PVSCSICmdDescResetDevice cmd = { 0 }; - dev_dbg(pvscsi_dev(adapter), "Resetting device: target=%u\n", target); + dev_dbg(pvscsi_dev(adapter), "Reseting device: target=%u\n", target); cmd.target = target; diff --git a/trunk/drivers/sh/intc/core.c b/trunk/drivers/sh/intc/core.c index 8f32a1323a79..2374468615ed 100644 --- a/trunk/drivers/sh/intc/core.c +++ b/trunk/drivers/sh/intc/core.c @@ -324,16 +324,8 @@ int __init register_intc_controller(struct intc_desc *desc) res = irq_create_identity_mapping(d->domain, irq); if (unlikely(res)) { - if (res == -EEXIST) { - res = irq_domain_associate(d->domain, irq, irq); - if (unlikely(res)) { - pr_err("domain association failure\n"); - continue; - } - } else { - pr_err("can't identity map IRQ %d\n", irq); - continue; - } + pr_err("can't get irq_desc for %d\n", irq); + continue; } intc_irq_xlate_set(irq, vect->enum_id, d); @@ -353,19 +345,8 @@ int __init register_intc_controller(struct intc_desc *desc) */ res = irq_create_identity_mapping(d->domain, irq2); if (unlikely(res)) { - if (res == -EEXIST) { - res = irq_domain_associate(d->domain, - irq2, irq2); - if (unlikely(res)) { - pr_err("domain association " - "failure\n"); - continue; - } - } else { - pr_err("can't identity map IRQ %d\n", - irq); - continue; - } + pr_err("can't get irq_desc for %d\n", irq2); + continue; } vect2->enum_id = 0; diff --git a/trunk/drivers/sh/pfc/pinctrl.c b/trunk/drivers/sh/pfc/pinctrl.c index 0646bf6e7889..2804eaae804e 100644 --- a/trunk/drivers/sh/pfc/pinctrl.c +++ b/trunk/drivers/sh/pfc/pinctrl.c @@ -208,13 +208,10 @@ static int sh_pfc_gpio_request_enable(struct pinctrl_dev *pctldev, break; case PINMUX_TYPE_GPIO: - case PINMUX_TYPE_INPUT: - case PINMUX_TYPE_OUTPUT: break; default: pr_err("Unsupported mux type (%d), bailing...\n", pinmux_type); - ret = -ENOTSUPP; - goto err; + return -ENOTSUPP; } ret = 0; diff --git a/trunk/drivers/spi/spi-au1550.c b/trunk/drivers/spi/spi-au1550.c index 4de66d1cfe51..5784c8799616 100644 --- a/trunk/drivers/spi/spi-au1550.c +++ b/trunk/drivers/spi/spi-au1550.c @@ -475,7 +475,7 @@ static irqreturn_t au1550_spi_dma_irq_callback(struct au1550_spi *hw) /* * due to an spi error we consider transfer as done, * so mask all events until before next transfer start - * and stop the possibly running dma immediately + * and stop the possibly running dma immediatelly */ au1550_spi_mask_ack_all(hw); au1xxx_dbdma_stop(hw->dma_rx_ch); diff --git a/trunk/drivers/spi/spi-bcm63xx.c b/trunk/drivers/spi/spi-bcm63xx.c index a9f4049c6769..6e25ef1bce91 100644 --- a/trunk/drivers/spi/spi-bcm63xx.c +++ b/trunk/drivers/spi/spi-bcm63xx.c @@ -47,8 +47,6 @@ struct bcm63xx_spi { /* Platform data */ u32 speed_hz; unsigned fifo_size; - unsigned int msg_type_shift; - unsigned int msg_ctl_width; /* Data buffers */ const unsigned char *tx_ptr; @@ -223,20 +221,13 @@ static unsigned int bcm63xx_txrx_bufs(struct spi_device *spi, msg_ctl = (t->len << SPI_BYTE_CNT_SHIFT); if (t->rx_buf && t->tx_buf) - msg_ctl |= (SPI_FD_RW << bs->msg_type_shift); + msg_ctl |= (SPI_FD_RW << SPI_MSG_TYPE_SHIFT); else if (t->rx_buf) - msg_ctl |= (SPI_HD_R << bs->msg_type_shift); + msg_ctl |= (SPI_HD_R << SPI_MSG_TYPE_SHIFT); else if (t->tx_buf) - msg_ctl |= (SPI_HD_W << bs->msg_type_shift); - - switch (bs->msg_ctl_width) { - case 8: - bcm_spi_writeb(bs, msg_ctl, SPI_MSG_CTL); - break; - case 16: - bcm_spi_writew(bs, msg_ctl, SPI_MSG_CTL); - break; - } + msg_ctl |= (SPI_HD_W << SPI_MSG_TYPE_SHIFT); + + bcm_spi_writew(bs, msg_ctl, SPI_MSG_CTL); /* Issue the transfer */ cmd = SPI_CMD_START_IMMEDIATE; @@ -415,21 +406,9 @@ static int __devinit bcm63xx_spi_probe(struct platform_device *pdev) master->transfer_one_message = bcm63xx_spi_transfer_one; master->mode_bits = MODEBITS; bs->speed_hz = pdata->speed_hz; - bs->msg_type_shift = pdata->msg_type_shift; - bs->msg_ctl_width = pdata->msg_ctl_width; bs->tx_io = (u8 *)(bs->regs + bcm63xx_spireg(SPI_MSG_DATA)); bs->rx_io = (const u8 *)(bs->regs + bcm63xx_spireg(SPI_RX_DATA)); - switch (bs->msg_ctl_width) { - case 8: - case 16: - break; - default: - dev_err(dev, "unsupported MSG_CTL width: %d\n", - bs->msg_ctl_width); - goto out_clk_disable; - } - /* Initialize hardware */ clk_enable(bs->clk); bcm_spi_writeb(bs, SPI_INTR_CLEAR_ALL, SPI_INT_STATUS); @@ -459,7 +438,7 @@ static int __devinit bcm63xx_spi_probe(struct platform_device *pdev) static int __devexit bcm63xx_spi_remove(struct platform_device *pdev) { - struct spi_master *master = spi_master_get(platform_get_drvdata(pdev)); + struct spi_master *master = platform_get_drvdata(pdev); struct bcm63xx_spi *bs = spi_master_get_devdata(master); spi_unregister_master(master); @@ -473,8 +452,6 @@ static int __devexit bcm63xx_spi_remove(struct platform_device *pdev) platform_set_drvdata(pdev, 0); - spi_master_put(master); - return 0; } diff --git a/trunk/drivers/spi/spi-bfin-sport.c b/trunk/drivers/spi/spi-bfin-sport.c index 6555ecd07302..1fe51198a622 100644 --- a/trunk/drivers/spi/spi-bfin-sport.c +++ b/trunk/drivers/spi/spi-bfin-sport.c @@ -467,7 +467,7 @@ bfin_sport_spi_pump_transfers(unsigned long data) dev_dbg(drv_data->dev, "IO write error!\n"); drv_data->state = ERROR_STATE; } else { - /* Update total byte transferred */ + /* Update total byte transfered */ message->actual_length += transfer->len; /* Move to next transfer of this msg */ drv_data->state = bfin_sport_spi_next_transfer(drv_data); diff --git a/trunk/drivers/spi/spi-coldfire-qspi.c b/trunk/drivers/spi/spi-coldfire-qspi.c index 764bfee75920..b2d4b9e4e010 100644 --- a/trunk/drivers/spi/spi-coldfire-qspi.c +++ b/trunk/drivers/spi/spi-coldfire-qspi.c @@ -533,6 +533,7 @@ static int __devexit mcfqspi_remove(struct platform_device *pdev) iounmap(mcfqspi->iobase); release_mem_region(res->start, resource_size(res)); spi_unregister_master(master); + spi_master_put(master); return 0; } @@ -540,7 +541,7 @@ static int __devexit mcfqspi_remove(struct platform_device *pdev) #ifdef CONFIG_PM_SLEEP static int mcfqspi_suspend(struct device *dev) { - struct spi_master *master = dev_get_drvdata(dev); + struct spi_master *master = spi_master_get(dev_get_drvdata(dev)); struct mcfqspi *mcfqspi = spi_master_get_devdata(master); spi_master_suspend(master); @@ -552,7 +553,7 @@ static int mcfqspi_suspend(struct device *dev) static int mcfqspi_resume(struct device *dev) { - struct spi_master *master = dev_get_drvdata(dev); + struct spi_master *master = spi_master_get(dev_get_drvdata(dev)); struct mcfqspi *mcfqspi = spi_master_get_devdata(master); spi_master_resume(master); diff --git a/trunk/drivers/spi/spi-oc-tiny.c b/trunk/drivers/spi/spi-oc-tiny.c index 9d9071b730be..698018fd992b 100644 --- a/trunk/drivers/spi/spi-oc-tiny.c +++ b/trunk/drivers/spi/spi-oc-tiny.c @@ -129,7 +129,7 @@ static int tiny_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t) unsigned int i; if (hw->irq >= 0) { - /* use interrupt driven data transfer */ + /* use intrrupt driven data transfer */ hw->len = t->len; hw->txp = t->tx_buf; hw->rxp = t->rx_buf; diff --git a/trunk/drivers/spi/spi-omap2-mcspi.c b/trunk/drivers/spi/spi-omap2-mcspi.c index b2fb141da375..bc4778175e34 100644 --- a/trunk/drivers/spi/spi-omap2-mcspi.c +++ b/trunk/drivers/spi/spi-omap2-mcspi.c @@ -1228,16 +1228,18 @@ static int __devinit omap2_mcspi_probe(struct platform_device *pdev) status = spi_register_master(master); if (status < 0) - goto disable_pm; + goto err_spi_register; return status; +err_spi_register: + spi_master_put(master); disable_pm: pm_runtime_disable(&pdev->dev); dma_chnl_free: kfree(mcspi->dma_channels); free_master: - spi_master_put(master); + kfree(master); platform_set_drvdata(pdev, NULL); return status; } diff --git a/trunk/drivers/spi/spi-pl022.c b/trunk/drivers/spi/spi-pl022.c index 6abbe23c39b4..aab518ec2bbc 100644 --- a/trunk/drivers/spi/spi-pl022.c +++ b/trunk/drivers/spi/spi-pl022.c @@ -2053,6 +2053,7 @@ pl022_probe(struct amba_device *adev, const struct amba_id *id) printk(KERN_INFO "pl022: mapped registers from 0x%08x to %p\n", adev->res.start, pl022->virtbase); + pm_runtime_enable(dev); pm_runtime_resume(dev); pl022->clk = clk_get(&adev->dev, NULL); diff --git a/trunk/drivers/spi/spi-ppc4xx.c b/trunk/drivers/spi/spi-ppc4xx.c index 7a85f22b6474..75ac9d48ef46 100644 --- a/trunk/drivers/spi/spi-ppc4xx.c +++ b/trunk/drivers/spi/spi-ppc4xx.c @@ -101,7 +101,7 @@ struct spi_ppc4xx_regs { u8 dummy; /* * Clock divisor modulus register - * This uses the following formula: + * This uses the follwing formula: * SCPClkOut = OPBCLK/(4(CDM + 1)) * or * CDM = (OPBCLK/4*SCPClkOut) - 1 @@ -201,7 +201,7 @@ static int spi_ppc4xx_setupxfer(struct spi_device *spi, struct spi_transfer *t) return -EINVAL; } - /* Write new configuration */ + /* Write new configration */ out_8(&hw->regs->mode, cs->mode); /* Set the clock */ diff --git a/trunk/drivers/spi/spi-s3c64xx.c b/trunk/drivers/spi/spi-s3c64xx.c index d1c8441f638c..646a7657fe62 100644 --- a/trunk/drivers/spi/spi-s3c64xx.c +++ b/trunk/drivers/spi/spi-s3c64xx.c @@ -826,7 +826,7 @@ static struct s3c64xx_spi_csinfo *s3c64xx_get_slave_ctrldata( struct spi_device *spi) { struct s3c64xx_spi_csinfo *cs; - struct device_node *slave_np, *data_np = NULL; + struct device_node *slave_np, *data_np; u32 fb_delay = 0; slave_np = spi->dev.of_node; @@ -1479,40 +1479,40 @@ static const struct dev_pm_ops s3c64xx_spi_pm = { s3c64xx_spi_runtime_resume, NULL) }; -static struct s3c64xx_spi_port_config s3c2443_spi_port_config = { +struct s3c64xx_spi_port_config s3c2443_spi_port_config = { .fifo_lvl_mask = { 0x7f }, .rx_lvl_offset = 13, .tx_st_done = 21, .high_speed = true, }; -static struct s3c64xx_spi_port_config s3c6410_spi_port_config = { +struct s3c64xx_spi_port_config s3c6410_spi_port_config = { .fifo_lvl_mask = { 0x7f, 0x7F }, .rx_lvl_offset = 13, .tx_st_done = 21, }; -static struct s3c64xx_spi_port_config s5p64x0_spi_port_config = { +struct s3c64xx_spi_port_config s5p64x0_spi_port_config = { .fifo_lvl_mask = { 0x1ff, 0x7F }, .rx_lvl_offset = 15, .tx_st_done = 25, }; -static struct s3c64xx_spi_port_config s5pc100_spi_port_config = { +struct s3c64xx_spi_port_config s5pc100_spi_port_config = { .fifo_lvl_mask = { 0x7f, 0x7F }, .rx_lvl_offset = 13, .tx_st_done = 21, .high_speed = true, }; -static struct s3c64xx_spi_port_config s5pv210_spi_port_config = { +struct s3c64xx_spi_port_config s5pv210_spi_port_config = { .fifo_lvl_mask = { 0x1ff, 0x7F }, .rx_lvl_offset = 15, .tx_st_done = 25, .high_speed = true, }; -static struct s3c64xx_spi_port_config exynos4_spi_port_config = { +struct s3c64xx_spi_port_config exynos4_spi_port_config = { .fifo_lvl_mask = { 0x1ff, 0x7F, 0x7F }, .rx_lvl_offset = 15, .tx_st_done = 25, diff --git a/trunk/drivers/spi/spi-topcliff-pch.c b/trunk/drivers/spi/spi-topcliff-pch.c index 1284c9b74653..cd56dcf46320 100644 --- a/trunk/drivers/spi/spi-topcliff-pch.c +++ b/trunk/drivers/spi/spi-topcliff-pch.c @@ -505,7 +505,7 @@ static int pch_spi_transfer(struct spi_device *pspi, struct spi_message *pmsg) } if (unlikely(pspi->max_speed_hz == 0)) { - dev_err(&pspi->dev, "%s pch_spi_transfer maxspeed=%d\n", + dev_err(&pspi->dev, "%s pch_spi_tranfer maxspeed=%d\n", __func__, pspi->max_speed_hz); retval = -EINVAL; goto err_out; diff --git a/trunk/drivers/staging/Kconfig b/trunk/drivers/staging/Kconfig index d805eef11915..e3402d5644dd 100644 --- a/trunk/drivers/staging/Kconfig +++ b/trunk/drivers/staging/Kconfig @@ -122,6 +122,8 @@ source "drivers/staging/android/Kconfig" source "drivers/staging/telephony/Kconfig" +source "drivers/staging/ramster/Kconfig" + source "drivers/staging/ozwpan/Kconfig" source "drivers/staging/ccg/Kconfig" @@ -134,14 +136,4 @@ source "drivers/staging/csr/Kconfig" source "drivers/staging/omap-thermal/Kconfig" -source "drivers/staging/ramster/Kconfig" - -source "drivers/staging/silicom/Kconfig" - -source "drivers/staging/ced1401/Kconfig" - -source "drivers/staging/imx-drm/Kconfig" - -source "drivers/staging/dgrp/Kconfig" - endif # STAGING diff --git a/trunk/drivers/staging/Makefile b/trunk/drivers/staging/Makefile index 76e2ebd596ff..3be59d02cae4 100644 --- a/trunk/drivers/staging/Makefile +++ b/trunk/drivers/staging/Makefile @@ -54,13 +54,9 @@ obj-$(CONFIG_MFD_NVEC) += nvec/ obj-$(CONFIG_DRM_OMAP) += omapdrm/ obj-$(CONFIG_ANDROID) += android/ obj-$(CONFIG_PHONE) += telephony/ +obj-$(CONFIG_RAMSTER) += ramster/ obj-$(CONFIG_USB_WPAN_HCD) += ozwpan/ obj-$(CONFIG_USB_G_CCG) += ccg/ obj-$(CONFIG_WIMAX_GDM72XX) += gdm72xx/ obj-$(CONFIG_CSR_WIFI) += csr/ obj-$(CONFIG_OMAP_BANDGAP) += omap-thermal/ -obj-$(CONFIG_ZCACHE2) += ramster/ -obj-$(CONFIG_NET_VENDOR_SILICOM) += silicom/ -obj-$(CONFIG_CED1401) += ced1401/ -obj-$(CONFIG_DRM_IMX) += imx-drm/ -obj-$(CONFIG_DGRP) += dgrp/ diff --git a/trunk/drivers/staging/android/alarm-dev.c b/trunk/drivers/staging/android/alarm-dev.c index a9b293ff3cc8..5b7064005188 100644 --- a/trunk/drivers/staging/android/alarm-dev.c +++ b/trunk/drivers/staging/android/alarm-dev.c @@ -67,8 +67,10 @@ static struct devalarm alarms[ANDROID_ALARM_TYPE_COUNT]; static int is_wakeup(enum android_alarm_type type) { - return (type == ANDROID_ALARM_RTC_WAKEUP || - type == ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP); + if (type == ANDROID_ALARM_RTC_WAKEUP || + type == ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP) + return 1; + return 0; } @@ -83,9 +85,12 @@ static void devalarm_start(struct devalarm *alrm, ktime_t exp) static int devalarm_try_to_cancel(struct devalarm *alrm) { + int ret; if (is_wakeup(alrm->type)) - return alarm_try_to_cancel(&alrm->u.alrm); - return hrtimer_try_to_cancel(&alrm->u.hrt); + ret = alarm_try_to_cancel(&alrm->u.alrm); + else + ret = hrtimer_try_to_cancel(&alrm->u.hrt); + return ret; } static void devalarm_cancel(struct devalarm *alrm) @@ -218,12 +223,10 @@ static long alarm_ioctl(struct file *file, unsigned int cmd, unsigned long arg) case ANDROID_ALARM_ELAPSED_REALTIME: get_monotonic_boottime(&tmp_time); break; + case ANDROID_ALARM_TYPE_COUNT: case ANDROID_ALARM_SYSTEMTIME: ktime_get_ts(&tmp_time); break; - default: - rv = -EINVAL; - goto err1; } if (copy_to_user((void __user *)arg, &tmp_time, sizeof(tmp_time))) { diff --git a/trunk/drivers/staging/android/android_alarm.h b/trunk/drivers/staging/android/android_alarm.h index f2ffd963f1c3..d0cafd637199 100644 --- a/trunk/drivers/staging/android/android_alarm.h +++ b/trunk/drivers/staging/android/android_alarm.h @@ -51,12 +51,10 @@ enum android_alarm_return_flags { #define ANDROID_ALARM_WAIT _IO('a', 1) #define ALARM_IOW(c, type, size) _IOW('a', (c) | ((type) << 4), size) -#define ALARM_IOR(c, type, size) _IOR('a', (c) | ((type) << 4), size) - /* Set alarm */ #define ANDROID_ALARM_SET(type) ALARM_IOW(2, type, struct timespec) #define ANDROID_ALARM_SET_AND_WAIT(type) ALARM_IOW(3, type, struct timespec) -#define ANDROID_ALARM_GET_TIME(type) ALARM_IOR(4, type, struct timespec) +#define ANDROID_ALARM_GET_TIME(type) ALARM_IOW(4, type, struct timespec) #define ANDROID_ALARM_SET_RTC _IOW('a', 5, struct timespec) #define ANDROID_ALARM_BASE_CMD(cmd) (cmd & ~(_IOC(0, 0, 0xf0, 0))) #define ANDROID_ALARM_IOCTL_TO_TYPE(cmd) (_IOC_NR(cmd) >> 4) diff --git a/trunk/drivers/staging/android/ashmem.c b/trunk/drivers/staging/android/ashmem.c index 94a740d2883d..69cf2db1d69c 100644 --- a/trunk/drivers/staging/android/ashmem.c +++ b/trunk/drivers/staging/android/ashmem.c @@ -1,20 +1,20 @@ /* mm/ashmem.c - * - * Anonymous Shared Memory Subsystem, ashmem - * - * Copyright (C) 2008 Google, Inc. - * - * Robert Love - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * 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. - */ +** +** Anonymous Shared Memory Subsystem, ashmem +** +** Copyright (C) 2008 Google, Inc. +** +** Robert Love +** +** This software is licensed under the terms of the GNU General Public +** License version 2, as published by the Free Software Foundation, and +** may be copied, distributed, and modified under those terms. +** +** 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. +*/ #define pr_fmt(fmt) "ashmem: " fmt diff --git a/trunk/drivers/staging/android/binder.c b/trunk/drivers/staging/android/binder.c index a807129c7b5a..574e99210c36 100644 --- a/trunk/drivers/staging/android/binder.c +++ b/trunk/drivers/staging/android/binder.c @@ -365,7 +365,7 @@ binder_defer_work(struct binder_proc *proc, enum binder_deferred_state defer); /* * copied from get_unused_fd_flags */ -static int task_get_unused_fd_flags(struct binder_proc *proc, int flags) +int task_get_unused_fd_flags(struct binder_proc *proc, int flags) { struct files_struct *files = proc->files; int fd, error; @@ -415,13 +415,13 @@ static int task_get_unused_fd_flags(struct binder_proc *proc, int flags) else __clear_close_on_exec(fd, fdt); files->next_fd = fd + 1; - +#if 1 /* Sanity check */ if (fdt->fd[fd] != NULL) { pr_warn("get_unused_fd: slot %d not NULL!\n", fd); fdt->fd[fd] = NULL; } - +#endif error = fd; out: diff --git a/trunk/drivers/staging/android/logger.c b/trunk/drivers/staging/android/logger.c index 1d5ed475364b..f7b8237d5be7 100644 --- a/trunk/drivers/staging/android/logger.c +++ b/trunk/drivers/staging/android/logger.c @@ -32,50 +32,38 @@ #include -/** +/* * struct logger_log - represents a specific log, such as 'main' or 'radio' - * @buffer: The actual ring buffer - * @misc: The "misc" device representing the log - * @wq: The wait queue for @readers - * @readers: This log's readers - * @mutex: The mutex that protects the @buffer - * @w_off: The current write head offset - * @head: The head, or location that readers start reading at. - * @size: The size of the log - * @logs: The list of log channels * * This structure lives from module insertion until module removal, so it does * not need additional reference counting. The structure is protected by the * mutex 'mutex'. */ struct logger_log { - unsigned char *buffer; - struct miscdevice misc; - wait_queue_head_t wq; - struct list_head readers; - struct mutex mutex; - size_t w_off; - size_t head; - size_t size; - struct list_head logs; + unsigned char *buffer;/* the ring buffer itself */ + struct miscdevice misc; /* misc device representing the log */ + wait_queue_head_t wq; /* wait queue for readers */ + struct list_head readers; /* this log's readers */ + struct mutex mutex; /* mutex protecting buffer */ + size_t w_off; /* current write head offset */ + size_t head; /* new readers start here */ + size_t size; /* size of the log */ + struct list_head logs; /* list of log channels (myself)*/ }; static LIST_HEAD(log_list); -/** +/* * struct logger_reader - a logging device open for reading - * @log: The associated log - * @list: The associated entry in @logger_log's list - * @r_off: The current read head offset. * * This object lives from open to release, so we don't need additional * reference counting. The structure is protected by log->mutex. */ struct logger_reader { - struct logger_log *log; - struct list_head list; - size_t r_off; + struct logger_log *log; /* associated log */ + struct list_head list; /* entry in logger_log's list */ + size_t r_off; /* current read head offset */ }; /* logger_offset - returns index 'n' into the log via (optimized) modulus */ diff --git a/trunk/drivers/staging/android/logger.h b/trunk/drivers/staging/android/logger.h index 9b929a8c7468..2cb06e9d8f98 100644 --- a/trunk/drivers/staging/android/logger.h +++ b/trunk/drivers/staging/android/logger.h @@ -20,24 +20,14 @@ #include #include -/** - * struct logger_entry - defines a single entry that is given to a logger - * @len: The length of the payload - * @__pad: Two bytes of padding that appear to be required - * @pid: The generating process' process ID - * @tid: The generating process' thread ID - * @sec: The number of seconds that have elapsed since the Epoch - * @nsec: The number of nanoseconds that have elapsed since @sec - * @msg: The message that is to be logged - */ struct logger_entry { - __u16 len; - __u16 __pad; - __s32 pid; - __s32 tid; - __s32 sec; - __s32 nsec; - char msg[0]; + __u16 len; /* length of the payload */ + __u16 __pad; /* no matter what, we get 2 bytes of padding */ + __s32 pid; /* generating process's pid */ + __s32 tid; /* generating process's tid */ + __s32 sec; /* seconds since Epoch */ + __s32 nsec; /* nanoseconds */ + char msg[0]; /* the entry's payload */ }; #define LOGGER_LOG_RADIO "log_radio" /* radio-related messages */ diff --git a/trunk/drivers/staging/android/timed_gpio.c b/trunk/drivers/staging/android/timed_gpio.c index e81451425c01..45c522cbe784 100644 --- a/trunk/drivers/staging/android/timed_gpio.c +++ b/trunk/drivers/staging/android/timed_gpio.c @@ -161,7 +161,18 @@ static struct platform_driver timed_gpio_driver = { }, }; -module_platform_driver(timed_gpio_driver); +static int __init timed_gpio_init(void) +{ + return platform_driver_register(&timed_gpio_driver); +} + +static void __exit timed_gpio_exit(void) +{ + platform_driver_unregister(&timed_gpio_driver); +} + +module_init(timed_gpio_init); +module_exit(timed_gpio_exit); MODULE_AUTHOR("Mike Lockwood "); MODULE_DESCRIPTION("timed gpio driver"); diff --git a/trunk/drivers/staging/asus_oled/asus_oled.c b/trunk/drivers/staging/asus_oled/asus_oled.c index 00185478647a..f63c1d3aeb64 100644 --- a/trunk/drivers/staging/asus_oled/asus_oled.c +++ b/trunk/drivers/staging/asus_oled/asus_oled.c @@ -42,6 +42,8 @@ #define ASUS_OLED_NAME "asus-oled" #define ASUS_OLED_UNDERSCORE_NAME "asus_oled" +#define ASUS_OLED_ERROR "Asus OLED Display Error: " + #define ASUS_OLED_STATIC 's' #define ASUS_OLED_ROLL 'r' #define ASUS_OLED_FLASH 'f' @@ -55,9 +57,8 @@ #define USB_DEVICE_ID_ASUS_LCM2 0x175b MODULE_AUTHOR("Jakub Schmidtke, sjakub@gmail.com"); -MODULE_DESCRIPTION("Asus OLED Driver"); +MODULE_DESCRIPTION("Asus OLED Driver v" ASUS_OLED_VERSION); MODULE_LICENSE("GPL"); -MODULE_VERSION(ASUS_OLED_VERSION); static struct class *oled_class; static int oled_num; @@ -137,7 +138,6 @@ struct asus_oled_dev { size_t buf_size; char *buf; uint8_t enabled; - uint8_t enabled_post_resume; struct device *dev; }; @@ -383,13 +383,13 @@ static int append_values(struct asus_oled_dev *odev, uint8_t val, size_t count) default: i = 0; - dev_err(odev->dev, "Unknown OLED Pack Mode: %d!\n", + printk(ASUS_OLED_ERROR "Unknown OLED Pack Mode: %d!\n", odev->pack_mode); break; } if (i >= odev->buf_size) { - dev_err(odev->dev, "Buffer overflow! Report a bug:" + printk(ASUS_OLED_ERROR "Buffer overflow! Report a bug:" "offs: %d >= %d i: %d (x: %d y: %d)\n", (int) odev->buf_offs, (int) odev->buf_size, (int) i, (int) x, (int) y); @@ -435,7 +435,7 @@ static ssize_t odev_set_picture(struct asus_oled_dev *odev, odev->buf = kmalloc(odev->buf_size, GFP_KERNEL); if (odev->buf == NULL) { odev->buf_size = 0; - dev_err(odev->dev, "Out of memory!\n"); + printk(ASUS_OLED_ERROR "Out of memory!\n"); return -ENOMEM; } @@ -473,7 +473,7 @@ static ssize_t odev_set_picture(struct asus_oled_dev *odev, odev->pic_mode = buf[1]; break; default: - dev_err(odev->dev, "Wrong picture mode: '%c'.\n", + printk(ASUS_OLED_ERROR "Wrong picture mode: '%c'.\n", buf[1]); return -EIO; break; @@ -533,7 +533,7 @@ static ssize_t odev_set_picture(struct asus_oled_dev *odev, if (odev->buf == NULL) { odev->buf_size = 0; - dev_err(odev->dev, "Out of memory!\n"); + printk(ASUS_OLED_ERROR "Out of memory!\n"); return -ENOMEM; } @@ -593,15 +593,15 @@ static ssize_t odev_set_picture(struct asus_oled_dev *odev, return count; error_width: - dev_err(odev->dev, "Wrong picture width specified.\n"); + printk(ASUS_OLED_ERROR "Wrong picture width specified.\n"); return -EIO; error_height: - dev_err(odev->dev, "Wrong picture height specified.\n"); + printk(ASUS_OLED_ERROR "Wrong picture height specified.\n"); return -EIO; error_header: - dev_err(odev->dev, "Wrong picture header.\n"); + printk(ASUS_OLED_ERROR "Wrong picture header.\n"); return -EIO; } @@ -766,45 +766,11 @@ static void asus_oled_disconnect(struct usb_interface *interface) dev_info(&interface->dev, "Disconnected Asus OLED device\n"); } -#ifdef CONFIG_PM -static int asus_oled_suspend(struct usb_interface *intf, pm_message_t message) -{ - struct asus_oled_dev *odev; - - odev = usb_get_intfdata(intf); - if (!odev) - return -ENODEV; - - odev->enabled_post_resume = odev->enabled; - enable_oled(odev, 0); - - return 0; -} - -static int asus_oled_resume(struct usb_interface *intf) -{ - struct asus_oled_dev *odev; - - odev = usb_get_intfdata(intf); - if (!odev) - return -ENODEV; - - enable_oled(odev, odev->enabled_post_resume); - - return 0; -} -#else -#define asus_oled_suspend NULL -#define asus_oled_resume NULL -#endif - static struct usb_driver oled_driver = { .name = ASUS_OLED_NAME, .probe = asus_oled_probe, .disconnect = asus_oled_disconnect, .id_table = id_table, - .suspend = asus_oled_suspend, - .resume = asus_oled_resume, }; static CLASS_ATTR_STRING(version, S_IRUGO, diff --git a/trunk/drivers/staging/bcm/Bcmchar.c b/trunk/drivers/staging/bcm/Bcmchar.c index 3d02c2ebfb8d..cf411d1706b1 100644 --- a/trunk/drivers/staging/bcm/Bcmchar.c +++ b/trunk/drivers/staging/bcm/Bcmchar.c @@ -820,7 +820,6 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) if (copy_from_user(psFwInfo, IoBuffer.InputBuffer, IoBuffer.InputLength)) { up(&Adapter->fw_download_sema); - kfree(psFwInfo); return -EFAULT; } @@ -830,7 +829,6 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Something else is wrong %lu\n", psFwInfo->u32FirmwareLength); up(&Adapter->fw_download_sema); - kfree(psFwInfo); Status = -EINVAL; return Status; } diff --git a/trunk/drivers/staging/bcm/CmHost.c b/trunk/drivers/staging/bcm/CmHost.c index 325b592fd41f..b54ec974477f 100644 --- a/trunk/drivers/staging/bcm/CmHost.c +++ b/trunk/drivers/staging/bcm/CmHost.c @@ -235,7 +235,7 @@ void ClearTargetDSXBuffer(struct bcm_mini_adapter *Adapter, B_UINT16 TID, BOOLEA * @ingroup ctrl_pkt_functions * copy classifier rule into the specified SF index */ -static inline VOID CopyClassifierRuleToSF(struct bcm_mini_adapter *Adapter, struct bcm_convergence_types *psfCSType, UINT uiSearchRuleIndex, UINT nClassifierIndex) +static inline VOID CopyClassifierRuleToSF(struct bcm_mini_adapter *Adapter, stConvergenceSLTypes *psfCSType, UINT uiSearchRuleIndex, UINT nClassifierIndex) { struct bcm_classifier_rule *pstClassifierEntry = NULL; /* VOID *pvPhsContext = NULL; */ @@ -428,7 +428,7 @@ VOID DeleteAllClassifiersForSF(struct bcm_mini_adapter *Adapter, UINT uiSearchRu * @ingroup ctrl_pkt_functions */ static VOID CopyToAdapter(register struct bcm_mini_adapter *Adapter, /* PackInfo[uiSearchRuleIndex].usVCID_Value; UINT UGIValue = 0; @@ -915,7 +915,7 @@ static VOID DumpCmControlPacket(PVOID pvBuffer) if (!pstAddIndication->sfAuthorizedSet.bValid) pstAddIndication->sfAuthorizedSet.bValid = 1; for (nIndex = 0; nIndex < nCurClassifierCnt; nIndex++) { - struct bcm_convergence_types *psfCSType = NULL; + stConvergenceSLTypes *psfCSType = NULL; psfCSType = &pstAddIndication->sfAuthorizedSet.cConvergenceSLTypes[nIndex]; BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "psfCSType = %p", psfCSType); @@ -999,10 +999,13 @@ static VOID DumpCmControlPacket(PVOID pvBuffer) #ifdef VERSION_D5 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8IPv6FlowLableLength: 0x%X ", psfCSType->cCPacketClassificationRule.u8IPv6FlowLableLength); - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, - DBG_LVL_ALL, "u8IPv6FlowLable[6]: 0x%*ph ", - 6, psfCSType->cCPacketClassificationRule. - u8IPv6FlowLable); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8IPv6FlowLable[6]: 0x %02X %02X %02X %02X %02X %02X ", + psfCSType->cCPacketClassificationRule.u8IPv6FlowLable[0], + psfCSType->cCPacketClassificationRule.u8IPv6FlowLable[1], + psfCSType->cCPacketClassificationRule.u8IPv6FlowLable[2], + psfCSType->cCPacketClassificationRule.u8IPv6FlowLable[3], + psfCSType->cCPacketClassificationRule.u8IPv6FlowLable[4], + psfCSType->cCPacketClassificationRule.u8IPv6FlowLable[5]); #endif } @@ -1012,9 +1015,13 @@ static VOID DumpCmControlPacket(PVOID pvBuffer) BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16CID: 0x%X", pstAddIndication->sfAdmittedSet.u16CID); BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8ServiceClassNameLength: 0x%X", pstAddIndication->sfAdmittedSet.u8ServiceClassNameLength); - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, - "u8ServiceClassName: 0x%*ph", - 6, pstAddIndication->sfAdmittedSet.u8ServiceClassName); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8ServiceClassName: 0x %02X %02X %02X %02X %02X %02X", + pstAddIndication->sfAdmittedSet.u8ServiceClassName[0], + pstAddIndication->sfAdmittedSet.u8ServiceClassName[1], + pstAddIndication->sfAdmittedSet.u8ServiceClassName[2], + pstAddIndication->sfAdmittedSet.u8ServiceClassName[3], + pstAddIndication->sfAdmittedSet.u8ServiceClassName[4], + pstAddIndication->sfAdmittedSet.u8ServiceClassName[5]); BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8MBSService: 0x%02X", pstAddIndication->sfAdmittedSet.u8MBSService); BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8QosParamSet: 0x%02X", pstAddIndication->sfAdmittedSet.u8QosParamSet); @@ -1059,7 +1066,7 @@ static VOID DumpCmControlPacket(PVOID pvBuffer) nCurClassifierCnt = MAX_CLASSIFIERS_IN_SF; for (nIndex = 0; nIndex < nCurClassifierCnt; nIndex++) { - struct bcm_convergence_types *psfCSType = NULL; + stConvergenceSLTypes *psfCSType = NULL; psfCSType = &pstAddIndication->sfAdmittedSet.cConvergenceSLTypes[nIndex]; BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " CCPacketClassificationRuleSI====>"); @@ -1067,10 +1074,10 @@ static VOID DumpCmControlPacket(PVOID pvBuffer) psfCSType->cCPacketClassificationRule.u8ClassifierRulePriority); BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8IPTypeOfServiceLength: 0x%02X", psfCSType->cCPacketClassificationRule.u8IPTypeOfServiceLength); - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, - DBG_LVL_ALL, "u8IPTypeOfService[3]: 0x%*ph", - 3, psfCSType->cCPacketClassificationRule. - u8IPTypeOfService); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8IPTypeOfService[3]: 0x%02X %02X %02X", + psfCSType->cCPacketClassificationRule.u8IPTypeOfService[0], + psfCSType->cCPacketClassificationRule.u8IPTypeOfService[1], + psfCSType->cCPacketClassificationRule.u8IPTypeOfService[2]); for (uiLoopIndex = 0; uiLoopIndex < 1; uiLoopIndex++) BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8Protocol: 0x%02X ", psfCSType->cCPacketClassificationRule.u8Protocol); @@ -1091,20 +1098,20 @@ static VOID DumpCmControlPacket(PVOID pvBuffer) BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8ProtocolSourcePortRangeLength: 0x%02X ", psfCSType->cCPacketClassificationRule.u8ProtocolSourcePortRangeLength); - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, - DBG_LVL_ALL, "u8ProtocolSourcePortRange[4]: " - "0x%*ph ", 4, psfCSType-> - cCPacketClassificationRule. - u8ProtocolSourcePortRange); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8ProtocolSourcePortRange[4]: 0x %02X %02X %02X %02X ", + psfCSType->cCPacketClassificationRule.u8ProtocolSourcePortRange[0], + psfCSType->cCPacketClassificationRule.u8ProtocolSourcePortRange[1], + psfCSType->cCPacketClassificationRule.u8ProtocolSourcePortRange[2], + psfCSType->cCPacketClassificationRule.u8ProtocolSourcePortRange[3]); BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8ProtocolDestPortRangeLength: 0x%02X ", psfCSType->cCPacketClassificationRule.u8ProtocolDestPortRangeLength); - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, - DBG_LVL_ALL, "u8ProtocolDestPortRange[4]: " - "0x%*ph ", 4, psfCSType-> - cCPacketClassificationRule. - u8ProtocolDestPortRange); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8ProtocolDestPortRange[4]: 0x %02X %02X %02X %02X ", + psfCSType->cCPacketClassificationRule.u8ProtocolDestPortRange[0], + psfCSType->cCPacketClassificationRule.u8ProtocolDestPortRange[1], + psfCSType->cCPacketClassificationRule.u8ProtocolDestPortRange[2], + psfCSType->cCPacketClassificationRule.u8ProtocolDestPortRange[3]); BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8EthernetDestMacAddressLength: 0x%02X ", psfCSType->cCPacketClassificationRule.u8EthernetDestMacAddressLength); @@ -1123,10 +1130,10 @@ static VOID DumpCmControlPacket(PVOID pvBuffer) u8EthernetSourceMACAddress); BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8EthertypeLength: 0x%02X ", psfCSType->cCPacketClassificationRule.u8EthertypeLength); - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, - DBG_LVL_ALL, "u8Ethertype[3]: 0x%*ph", - 3, psfCSType->cCPacketClassificationRule. - u8Ethertype); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8Ethertype[3]: 0x%02X %02X %02X", + psfCSType->cCPacketClassificationRule.u8Ethertype[0], + psfCSType->cCPacketClassificationRule.u8Ethertype[1], + psfCSType->cCPacketClassificationRule.u8Ethertype[2]); BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16UserPriority: 0x%X ", psfCSType->cCPacketClassificationRule.u16UserPriority); BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16VLANID: 0x%X ", psfCSType->cCPacketClassificationRule.u16VLANID); @@ -1140,10 +1147,13 @@ static VOID DumpCmControlPacket(PVOID pvBuffer) #ifdef VERSION_D5 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8IPv6FlowLableLength: 0x%X ", psfCSType->cCPacketClassificationRule.u8IPv6FlowLableLength); - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, - DBG_LVL_ALL, "u8IPv6FlowLable[6]: 0x%*ph ", - 6, psfCSType->cCPacketClassificationRule. - u8IPv6FlowLable); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8IPv6FlowLable[6]: 0x %02X %02X %02X %02X %02X %02X ", + psfCSType->cCPacketClassificationRule.u8IPv6FlowLable[0], + psfCSType->cCPacketClassificationRule.u8IPv6FlowLable[1], + psfCSType->cCPacketClassificationRule.u8IPv6FlowLable[2], + psfCSType->cCPacketClassificationRule.u8IPv6FlowLable[3], + psfCSType->cCPacketClassificationRule.u8IPv6FlowLable[4], + psfCSType->cCPacketClassificationRule.u8IPv6FlowLable[5]); #endif } @@ -1152,9 +1162,13 @@ static VOID DumpCmControlPacket(PVOID pvBuffer) BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u32SFID: 0x%X", pstAddIndication->sfActiveSet.u32SFID); BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16CID: 0x%X", pstAddIndication->sfActiveSet.u16CID); BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8ServiceClassNameLength: 0x%X", pstAddIndication->sfActiveSet.u8ServiceClassNameLength); - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, - "u8ServiceClassName: 0x%*ph", - 6, pstAddIndication->sfActiveSet.u8ServiceClassName); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8ServiceClassName: 0x %02X %02X %02X %02X %02X %02X", + pstAddIndication->sfActiveSet.u8ServiceClassName[0], + pstAddIndication->sfActiveSet.u8ServiceClassName[1], + pstAddIndication->sfActiveSet.u8ServiceClassName[2], + pstAddIndication->sfActiveSet.u8ServiceClassName[3], + pstAddIndication->sfActiveSet.u8ServiceClassName[4], + pstAddIndication->sfActiveSet.u8ServiceClassName[5]); BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8MBSService: 0x%02X", pstAddIndication->sfActiveSet.u8MBSService); BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8QosParamSet: 0x%02X", pstAddIndication->sfActiveSet.u8QosParamSet); @@ -1198,7 +1212,7 @@ static VOID DumpCmControlPacket(PVOID pvBuffer) nCurClassifierCnt = MAX_CLASSIFIERS_IN_SF; for (nIndex = 0; nIndex < nCurClassifierCnt; nIndex++) { - struct bcm_convergence_types *psfCSType = NULL; + stConvergenceSLTypes *psfCSType = NULL; psfCSType = &pstAddIndication->sfActiveSet.cConvergenceSLTypes[nIndex]; BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " CCPacketClassificationRuleSI====>"); @@ -1300,7 +1314,7 @@ static VOID DumpCmControlPacket(PVOID pvBuffer) static inline ULONG RestoreSFParam(struct bcm_mini_adapter *Adapter, ULONG ulAddrSFParamSet, PUCHAR pucDestBuffer) { - UINT nBytesToRead = sizeof(struct bcm_connect_mgr_params); + UINT nBytesToRead = sizeof(stServiceFlowParamSI); if (ulAddrSFParamSet == 0 || NULL == pucDestBuffer) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "Got Param address as 0!!"); @@ -1317,7 +1331,7 @@ static inline ULONG RestoreSFParam(struct bcm_mini_adapter *Adapter, ULONG ulAdd static ULONG StoreSFParam(struct bcm_mini_adapter *Adapter, PUCHAR pucSrcBuffer, ULONG ulAddrSFParamSet) { - UINT nBytesToWrite = sizeof(struct bcm_connect_mgr_params); + UINT nBytesToWrite = sizeof(stServiceFlowParamSI); int ret = 0; if (ulAddrSFParamSet == 0 || NULL == pucSrcBuffer) @@ -1334,8 +1348,8 @@ static ULONG StoreSFParam(struct bcm_mini_adapter *Adapter, PUCHAR pucSrcBuffer, ULONG StoreCmControlResponseMessage(struct bcm_mini_adapter *Adapter, PVOID pvBuffer, UINT *puBufferLength) { stLocalSFAddIndicationAlt *pstAddIndicationAlt = NULL; - struct bcm_add_indication *pstAddIndication = NULL; - struct bcm_del_request *pstDeletionRequest; + stLocalSFAddIndication *pstAddIndication = NULL; + stLocalSFDeleteRequest *pstDeletionRequest; UINT uiSearchRuleIndex; ULONG ulSFID; @@ -1346,7 +1360,7 @@ ULONG StoreCmControlResponseMessage(struct bcm_mini_adapter *Adapter, PVOID pvBu * we can stop the further classifying the pkt for this SF. */ if (pstAddIndicationAlt->u8Type == DSD_REQ) { - pstDeletionRequest = (struct bcm_del_request *)pvBuffer; + pstDeletionRequest = (stLocalSFDeleteRequest *)pvBuffer; ulSFID = ntohl(pstDeletionRequest->u32SFID); uiSearchRuleIndex = SearchSfid(Adapter, ulSFID); @@ -1365,12 +1379,12 @@ ULONG StoreCmControlResponseMessage(struct bcm_mini_adapter *Adapter, PVOID pvBu } /* For DSA_REQ, only up to "psfAuthorizedSet" parameter should be accessed by driver! */ - pstAddIndication = kmalloc(sizeof(struct bcm_add_indication), GFP_KERNEL); + pstAddIndication = kmalloc(sizeof(*pstAddIndication), GFP_KERNEL); if (pstAddIndication == NULL) return 0; /* AUTHORIZED SET */ - pstAddIndication->psfAuthorizedSet = (struct bcm_connect_mgr_params *) + pstAddIndication->psfAuthorizedSet = (stServiceFlowParamSI *) GetNextTargetBufferLocation(Adapter, pstAddIndicationAlt->u16TID); if (!pstAddIndication->psfAuthorizedSet) { kfree(pstAddIndication); @@ -1384,10 +1398,10 @@ ULONG StoreCmControlResponseMessage(struct bcm_mini_adapter *Adapter, PVOID pvBu } /* this can't possibly be right */ - pstAddIndication->psfAuthorizedSet = (struct bcm_connect_mgr_params *)ntohl((ULONG)pstAddIndication->psfAuthorizedSet); + pstAddIndication->psfAuthorizedSet = (stServiceFlowParamSI *)ntohl((ULONG)pstAddIndication->psfAuthorizedSet); if (pstAddIndicationAlt->u8Type == DSA_REQ) { - struct bcm_add_request AddRequest; + stLocalSFAddRequest AddRequest; AddRequest.u8Type = pstAddIndicationAlt->u8Type; AddRequest.eConnectionDir = pstAddIndicationAlt->u8Direction; @@ -1395,8 +1409,8 @@ ULONG StoreCmControlResponseMessage(struct bcm_mini_adapter *Adapter, PVOID pvBu AddRequest.u16CID = pstAddIndicationAlt->u16CID; AddRequest.u16VCID = pstAddIndicationAlt->u16VCID; AddRequest.psfParameterSet = pstAddIndication->psfAuthorizedSet; - (*puBufferLength) = sizeof(struct bcm_add_request); - memcpy(pvBuffer, &AddRequest, sizeof(struct bcm_add_request)); + (*puBufferLength) = sizeof(stLocalSFAddRequest); + memcpy(pvBuffer, &AddRequest, sizeof(stLocalSFAddRequest)); kfree(pstAddIndication); return 1; } @@ -1412,7 +1426,7 @@ ULONG StoreCmControlResponseMessage(struct bcm_mini_adapter *Adapter, PVOID pvBu pstAddIndication->u8CC = pstAddIndicationAlt->u8CC; /* ADMITTED SET */ - pstAddIndication->psfAdmittedSet = (struct bcm_connect_mgr_params *) + pstAddIndication->psfAdmittedSet = (stServiceFlowParamSI *) GetNextTargetBufferLocation(Adapter, pstAddIndicationAlt->u16TID); if (!pstAddIndication->psfAdmittedSet) { kfree(pstAddIndication); @@ -1423,10 +1437,10 @@ ULONG StoreCmControlResponseMessage(struct bcm_mini_adapter *Adapter, PVOID pvBu return 0; } - pstAddIndication->psfAdmittedSet = (struct bcm_connect_mgr_params *)ntohl((ULONG)pstAddIndication->psfAdmittedSet); + pstAddIndication->psfAdmittedSet = (stServiceFlowParamSI *)ntohl((ULONG)pstAddIndication->psfAdmittedSet); /* ACTIVE SET */ - pstAddIndication->psfActiveSet = (struct bcm_connect_mgr_params *) + pstAddIndication->psfActiveSet = (stServiceFlowParamSI *) GetNextTargetBufferLocation(Adapter, pstAddIndicationAlt->u16TID); if (!pstAddIndication->psfActiveSet) { kfree(pstAddIndication); @@ -1437,10 +1451,10 @@ ULONG StoreCmControlResponseMessage(struct bcm_mini_adapter *Adapter, PVOID pvBu return 0; } - pstAddIndication->psfActiveSet = (struct bcm_connect_mgr_params *)ntohl((ULONG)pstAddIndication->psfActiveSet); + pstAddIndication->psfActiveSet = (stServiceFlowParamSI *)ntohl((ULONG)pstAddIndication->psfActiveSet); - (*puBufferLength) = sizeof(struct bcm_add_indication); - *(struct bcm_add_indication *)pvBuffer = *pstAddIndication; + (*puBufferLength) = sizeof(stLocalSFAddIndication); + *(stLocalSFAddIndication *)pvBuffer = *pstAddIndication; kfree(pstAddIndication); return 1; } @@ -1449,10 +1463,10 @@ static inline stLocalSFAddIndicationAlt *RestoreCmControlResponseMessage(register struct bcm_mini_adapter *Adapter, register PVOID pvBuffer) { ULONG ulStatus = 0; - struct bcm_add_indication *pstAddIndication = NULL; + stLocalSFAddIndication *pstAddIndication = NULL; stLocalSFAddIndicationAlt *pstAddIndicationDest = NULL; - pstAddIndication = (struct bcm_add_indication *)(pvBuffer); + pstAddIndication = (stLocalSFAddIndication *)(pvBuffer); BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "=====>"); if ((pstAddIndication->u8Type == DSD_REQ) || (pstAddIndication->u8Type == DSD_RSP) || @@ -1539,7 +1553,7 @@ ULONG SetUpTargetDsxBuffers(struct bcm_mini_adapter *Adapter) if (Adapter->astTargetDsxBuffer[0].ulTargetDsxBuffer) return 1; - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "Size of Each DSX Buffer(Also size of connection manager parameters): %zx ", sizeof(struct bcm_connect_mgr_params)); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "Size of Each DSX Buffer(Also size of ServiceFlowParamSI): %zx ", sizeof(stServiceFlowParamSI)); BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "Reading DSX buffer From Target location %x ", DSX_MESSAGE_EXCHANGE_BUFFER); Status = rdmalt(Adapter, DSX_MESSAGE_EXCHANGE_BUFFER, (PUINT)&ulTargetDsxBuffersBase, sizeof(UINT)); @@ -1550,7 +1564,7 @@ ULONG SetUpTargetDsxBuffers(struct bcm_mini_adapter *Adapter) BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "Base Address Of DSX Target Buffer : 0x%lx", ulTargetDsxBuffersBase); BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "Tgt Buffer is Now %lx :", ulTargetDsxBuffersBase); - ulCntTargetBuffers = DSX_MESSAGE_EXCHANGE_BUFFER_SIZE / sizeof(struct bcm_connect_mgr_params); + ulCntTargetBuffers = DSX_MESSAGE_EXCHANGE_BUFFER_SIZE / sizeof(stServiceFlowParamSI); Adapter->ulTotalTargetBuffersAvailable = ulCntTargetBuffers > MAX_TARGET_DSX_BUFFERS ? @@ -1562,7 +1576,7 @@ ULONG SetUpTargetDsxBuffers(struct bcm_mini_adapter *Adapter) Adapter->astTargetDsxBuffer[i].ulTargetDsxBuffer = ulTargetDsxBuffersBase; Adapter->astTargetDsxBuffer[i].valid = 1; Adapter->astTargetDsxBuffer[i].tid = 0; - ulTargetDsxBuffersBase += sizeof(struct bcm_connect_mgr_params); + ulTargetDsxBuffersBase += sizeof(stServiceFlowParamSI); BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, " Target DSX Buffer %lx setup at 0x%lx", i, Adapter->astTargetDsxBuffer[i].ulTargetDsxBuffer); } @@ -1633,7 +1647,7 @@ int FreeAdapterDsxBuffer(struct bcm_mini_adapter *Adapter) BOOLEAN CmControlResponseMessage(struct bcm_mini_adapter *Adapter, /* u16TID, FALSE); + ClearTargetDSXBuffer(Adapter, ((stLocalSFAddIndication *)pvBuffer)->u16TID, FALSE); BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Error in restoring Service Flow param structure from DSx message"); return FALSE; } @@ -1856,10 +1870,10 @@ BOOLEAN CmControlResponseMessage(struct bcm_mini_adapter *Adapter, /* PLength = sizeof(struct bcm_del_indication); - *((struct bcm_del_indication *)&(Adapter->caDsxReqResp[LEADER_SIZE])) = *((struct bcm_del_indication *)pstAddIndication); + pLeader->PLength = sizeof(stLocalSFDeleteIndication); + *((stLocalSFDeleteIndication *)&(Adapter->caDsxReqResp[LEADER_SIZE])) = *((stLocalSFDeleteIndication *)pstAddIndication); - ulSFID = ntohl(((struct bcm_del_indication *)pstAddIndication)->u32SFID); + ulSFID = ntohl(((stLocalSFDeleteIndication *)pstAddIndication)->u32SFID); uiSearchRuleIndex = SearchSfid(Adapter, ulSFID); BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "DSD - Removing connection %x", uiSearchRuleIndex); @@ -1870,7 +1884,7 @@ BOOLEAN CmControlResponseMessage(struct bcm_mini_adapter *Adapter, /* caDsxReqResp[LEADER_SIZE]))->u8Type = DSD_RSP; + ((stLocalSFDeleteIndication *)&(Adapter->caDsxReqResp[LEADER_SIZE]))->u8Type = DSD_RSP; CopyBufferToControlPacket(Adapter, (PVOID)Adapter->caDsxReqResp); } case DSD_RSP: @@ -1913,7 +1927,7 @@ int get_dsx_sf_data_to_application(struct bcm_mini_adapter *Adapter, UINT uiSFId VOID OverrideServiceFlowParams(struct bcm_mini_adapter *Adapter, PUINT puiBuffer) { B_UINT32 u32NumofSFsinMsg = ntohl(*(puiBuffer + 1)); - struct bcm_stim_sfhostnotify *pHostInfo = NULL; + stIM_SFHostNotify *pHostInfo = NULL; UINT uiSearchRuleIndex = 0; ULONG ulSFID = 0; @@ -1922,7 +1936,7 @@ VOID OverrideServiceFlowParams(struct bcm_mini_adapter *Adapter, PUINT puiBuffer while (u32NumofSFsinMsg != 0 && u32NumofSFsinMsg < NO_OF_QUEUES) { u32NumofSFsinMsg--; - pHostInfo = (struct bcm_stim_sfhostnotify *)puiBuffer; + pHostInfo = (stIM_SFHostNotify *)puiBuffer; puiBuffer = (PUINT)(pHostInfo + 1); ulSFID = ntohl(pHostInfo->SFID); diff --git a/trunk/drivers/staging/bcm/CmHost.h b/trunk/drivers/staging/bcm/CmHost.h index 1c5a07c7bbe2..4cc6f93f2321 100644 --- a/trunk/drivers/staging/bcm/CmHost.h +++ b/trunk/drivers/staging/bcm/CmHost.h @@ -35,7 +35,8 @@ typedef struct stLocalSFAddRequestAlt{ B_UINT16 u16VCID; - struct bcm_connect_mgr_params sfParameterSet; + /// \brief structure ParameterSet + stServiceFlowParamSI sfParameterSet; //USE_MEMORY_MANAGER(); }stLocalSFAddRequestAlt; @@ -49,9 +50,12 @@ typedef struct stLocalSFAddIndicationAlt{ B_UINT16 u16CID; /// \brief 16bitVCID B_UINT16 u16VCID; - struct bcm_connect_mgr_params sfAuthorizedSet; - struct bcm_connect_mgr_params sfAdmittedSet; - struct bcm_connect_mgr_params sfActiveSet; + /// \brief structure AuthorizedSet + stServiceFlowParamSI sfAuthorizedSet; + /// \brief structure AdmittedSet + stServiceFlowParamSI sfAdmittedSet; + /// \brief structure ActiveSet + stServiceFlowParamSI sfActiveSet; B_UINT8 u8CC; /**< Confirmation Code*/ B_UINT8 u8Padd; /**< 8-bit Padding */ @@ -68,9 +72,12 @@ typedef struct stLocalSFAddConfirmationAlt{ B_UINT16 u16CID; /// \brief 16bitVCID B_UINT16 u16VCID; - struct bcm_connect_mgr_params sfAuthorizedSet; - struct bcm_connect_mgr_params sfAdmittedSet; - struct bcm_connect_mgr_params sfActiveSet; + /// \brief structure AuthorizedSet + stServiceFlowParamSI sfAuthorizedSet; + /// \brief structure AdmittedSet + stServiceFlowParamSI sfAdmittedSet; + /// \brief structure ActiveSet + stServiceFlowParamSI sfActiveSet; }stLocalSFAddConfirmationAlt; @@ -84,13 +91,16 @@ typedef struct stLocalSFChangeRequestAlt{ /// \brief 16bitVCID B_UINT16 u16VCID; /* - //Pointer location at which following connection manager param Structure can be read - //from the target. We only get the address location and we need to read out the - //entire connection manager param structure at the given location on target + //Pointer location at which following Service Flow param Structure can be read + //from the target. We get only the address location and we need to read out the + //entire SF param structure at the given location on target */ - struct bcm_connect_mgr_params sfAuthorizedSet; - struct bcm_connect_mgr_params sfAdmittedSet; - struct bcm_connect_mgr_params sfActiveSet; + /// \brief structure AuthorizedSet + stServiceFlowParamSI sfAuthorizedSet; + /// \brief structure AdmittedSet + stServiceFlowParamSI sfAdmittedSet; + /// \brief structure ParameterSet + stServiceFlowParamSI sfActiveSet; B_UINT8 u8CC; /**< Confirmation Code*/ B_UINT8 u8Padd; /**< 8-bit Padding */ @@ -107,9 +117,12 @@ typedef struct stLocalSFChangeConfirmationAlt{ B_UINT16 u16CID; /// \brief 16bitVCID B_UINT16 u16VCID; - struct bcm_connect_mgr_params sfAuthorizedSet; - struct bcm_connect_mgr_params sfAdmittedSet; - struct bcm_connect_mgr_params sfActiveSet; + /// \brief structure AuthorizedSet + stServiceFlowParamSI sfAuthorizedSet; + /// \brief structure AdmittedSet + stServiceFlowParamSI sfAdmittedSet; + /// \brief structure ActiveSet + stServiceFlowParamSI sfActiveSet; }stLocalSFChangeConfirmationAlt; @@ -122,9 +135,12 @@ typedef struct stLocalSFChangeIndicationAlt{ B_UINT16 u16CID; /// \brief 16bitVCID B_UINT16 u16VCID; - struct bcm_connect_mgr_params sfAuthorizedSet; - struct bcm_connect_mgr_params sfAdmittedSet; - struct bcm_connect_mgr_params sfActiveSet; + /// \brief structure AuthorizedSet + stServiceFlowParamSI sfAuthorizedSet; + /// \brief structure AdmittedSet + stServiceFlowParamSI sfAdmittedSet; + /// \brief structure ActiveSet + stServiceFlowParamSI sfActiveSet; B_UINT8 u8CC; /**< Confirmation Code*/ B_UINT8 u8Padd; /**< 8-bit Padding */ diff --git a/trunk/drivers/staging/bcm/InterfaceInit.c b/trunk/drivers/staging/bcm/InterfaceInit.c index b05f5f73548c..8f85de6a57ba 100644 --- a/trunk/drivers/staging/bcm/InterfaceInit.c +++ b/trunk/drivers/staging/bcm/InterfaceInit.c @@ -8,7 +8,6 @@ static struct usb_device_id InterfaceUsbtable[] = { { USB_DEVICE(BCM_USB_VENDOR_ID_ZTE, BCM_USB_PRODUCT_ID_226) }, { USB_DEVICE(BCM_USB_VENDOR_ID_FOXCONN, BCM_USB_PRODUCT_ID_1901) }, { USB_DEVICE(BCM_USB_VENDOR_ID_ZTE, BCM_USB_PRODUCT_ID_ZTE_TU25) }, - { USB_DEVICE(BCM_USB_VENDOR_ID_ZTE, BCM_USB_PRODUCT_ID_ZTE_226) }, { } }; MODULE_DEVICE_TABLE(usb, InterfaceUsbtable); @@ -670,24 +669,16 @@ struct class *bcm_class; static __init int bcm_init(void) { - int retval; - - pr_info("%s: %s, %s\n", DRV_NAME, DRV_DESCRIPTION, DRV_VERSION); - pr_info("%s\n", DRV_COPYRIGHT); + printk(KERN_INFO "%s: %s, %s\n", DRV_NAME, DRV_DESCRIPTION, DRV_VERSION); + printk(KERN_INFO "%s\n", DRV_COPYRIGHT); bcm_class = class_create(THIS_MODULE, DRV_NAME); if (IS_ERR(bcm_class)) { - pr_err(DRV_NAME ": could not create class\n"); + printk(KERN_ERR DRV_NAME ": could not create class\n"); return PTR_ERR(bcm_class); } - retval = usb_register(&usbbcm_driver); - if (retval < 0) { - pr_err(DRV_NAME ": could not register usb driver\n"); - class_destroy(bcm_class); - return retval; - } - return 0; + return usb_register(&usbbcm_driver); } static __exit void bcm_exit(void) diff --git a/trunk/drivers/staging/bcm/InterfaceInit.h b/trunk/drivers/staging/bcm/InterfaceInit.h index 866924e35f9c..058315a64c05 100644 --- a/trunk/drivers/staging/bcm/InterfaceInit.h +++ b/trunk/drivers/staging/bcm/InterfaceInit.h @@ -1,26 +1,27 @@ #ifndef _INTERFACE_INIT_H #define _INTERFACE_INIT_H -#define BCM_USB_VENDOR_ID_T3 0x198f -#define BCM_USB_VENDOR_ID_FOXCONN 0x0489 -#define BCM_USB_VENDOR_ID_ZTE 0x19d2 +#define BCM_USB_VENDOR_ID_T3 0x198f +#define BCM_USB_VENDOR_ID_FOXCONN 0x0489 +#define BCM_USB_VENDOR_ID_ZTE 0x19d2 -#define BCM_USB_PRODUCT_ID_T3 0x0300 -#define BCM_USB_PRODUCT_ID_T3B 0x0210 -#define BCM_USB_PRODUCT_ID_T3L 0x0220 -#define BCM_USB_PRODUCT_ID_SM250 0xbccd -#define BCM_USB_PRODUCT_ID_SYM 0x15E -#define BCM_USB_PRODUCT_ID_1901 0xe017 -#define BCM_USB_PRODUCT_ID_226 0x0132 /* not sure if this is valid */ -#define BCM_USB_PRODUCT_ID_ZTE_226 0x172 -#define BCM_USB_PRODUCT_ID_ZTE_TU25 0x0007 +#define BCM_USB_PRODUCT_ID_T3 0x0300 +#define BCM_USB_PRODUCT_ID_T3B 0x0210 +#define BCM_USB_PRODUCT_ID_T3L 0x0220 +#define BCM_USB_PRODUCT_ID_SM250 0xbccd +#define BCM_USB_PRODUCT_ID_SYM 0x15E +#define BCM_USB_PRODUCT_ID_1901 0xe017 +#define BCM_USB_PRODUCT_ID_226 0x0132 +#define BCM_USB_PRODUCT_ID_ZTE_TU25 0x0007 -#define BCM_USB_MINOR_BASE 192 +#define BCM_USB_MINOR_BASE 192 -int InterfaceInitialize(void); -int InterfaceExit(void); +INT InterfaceInitialize(void); -int usbbcm_worker_thread(PS_INTERFACE_ADAPTER psIntfAdapter); +INT InterfaceExit(void); + +INT usbbcm_worker_thread(PS_INTERFACE_ADAPTER psIntfAdapter); #endif + diff --git a/trunk/drivers/staging/bcm/Kconfig b/trunk/drivers/staging/bcm/Kconfig index 83c9752504d4..96adb1026c4f 100644 --- a/trunk/drivers/staging/bcm/Kconfig +++ b/trunk/drivers/staging/bcm/Kconfig @@ -1,6 +1,6 @@ config BCM_WIMAX tristate "Beceem BCS200/BCS220-3 and BCSM250 wimax support" - depends on USB && NET + depends on USB && NET && EXPERIMENTAL default N help This is an experimental driver for the Beceem WIMAX chipset used diff --git a/trunk/drivers/staging/bcm/Misc.c b/trunk/drivers/staging/bcm/Misc.c index f13a9582a82f..f545716c666d 100644 --- a/trunk/drivers/staging/bcm/Misc.c +++ b/trunk/drivers/staging/bcm/Misc.c @@ -752,10 +752,7 @@ VOID DumpPackInfo(struct bcm_mini_adapter *Adapter) BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "AuthzSet: %x\n", Adapter->PackInfo[uiLoopIndex].bAuthorizedSet); BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "ClassifyPrority: %x\n", Adapter->PackInfo[uiLoopIndex].bClassifierPriority); BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "uiMaxLatency: %x\n", Adapter->PackInfo[uiLoopIndex].uiMaxLatency); - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, - DBG_LVL_ALL, "ServiceClassName: %*ph\n", - 4, Adapter->PackInfo[uiLoopIndex]. - ucServiceClassName); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "ServiceClassName: %x %x %x %x\n", Adapter->PackInfo[uiLoopIndex].ucServiceClassName[0], Adapter->PackInfo[uiLoopIndex].ucServiceClassName[1], Adapter->PackInfo[uiLoopIndex].ucServiceClassName[2], Adapter->PackInfo[uiLoopIndex].ucServiceClassName[3]); /* BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "bHeaderSuppressionEnabled :%X\n", Adapter->PackInfo[uiLoopIndex].bHeaderSuppressionEnabled); * BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "uiTotalTxBytes:%X\n", Adapter->PackInfo[uiLoopIndex].uiTotalTxBytes); * BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "uiTotalRxBytes:%X\n", Adapter->PackInfo[uiLoopIndex].uiTotalRxBytes); diff --git a/trunk/drivers/staging/bcm/PHSModule.c b/trunk/drivers/staging/bcm/PHSModule.c index 6dc0bbcfeab0..479574234e4c 100644 --- a/trunk/drivers/staging/bcm/PHSModule.c +++ b/trunk/drivers/staging/bcm/PHSModule.c @@ -66,7 +66,7 @@ Input parameters: IN struct bcm_mini_adapter *Adapter - Miniport Adapte BOOLEAN bHeaderSuppressionEnabled - indicates if header suprression is enabled for SF. Return: STATUS_SUCCESS - If the send was successful. - Other - If an error occurred. + Other - If an error occured. */ int PHSTransmit(struct bcm_mini_adapter *Adapter, @@ -346,7 +346,7 @@ int phs_init(PPHS_DEVICE_EXTENSION pPhsdeviceExtension, struct bcm_mini_adapter - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "\n phs_init Successful"); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "\n phs_init Successfull"); return STATUS_SUCCESS; } diff --git a/trunk/drivers/staging/bcm/Prototypes.h b/trunk/drivers/staging/bcm/Prototypes.h index 3ec8f800a5b0..3c8cc5ba2e2e 100644 --- a/trunk/drivers/staging/bcm/Prototypes.h +++ b/trunk/drivers/staging/bcm/Prototypes.h @@ -95,7 +95,7 @@ void beceem_parse_target_struct(struct bcm_mini_adapter *Adapter); int bcm_ioctl_fw_download(struct bcm_mini_adapter *Adapter, struct bcm_firmware_info *psFwInfo); void CopyMIBSExtendedSFParameters(struct bcm_mini_adapter *Adapter, - struct bcm_connect_mgr_params *psfLocalSet, UINT uiSearchRuleIndex); + CServiceFlowParamSI *psfLocalSet, UINT uiSearchRuleIndex); VOID ResetCounters(struct bcm_mini_adapter *Adapter); diff --git a/trunk/drivers/staging/bcm/Transmit.c b/trunk/drivers/staging/bcm/Transmit.c index 27e8c890777b..5e603ce76fea 100644 --- a/trunk/drivers/staging/bcm/Transmit.c +++ b/trunk/drivers/staging/bcm/Transmit.c @@ -1,149 +1,162 @@ /** - * @file Transmit.c - * @defgroup tx_functions Transmission - * @section Queueing - * @dot - * digraph transmit1 { - * node[shape=box] - * edge[weight=5;color=red] - * - * bcm_transmit->GetPacketQueueIndex[label="IP Packet"] - * GetPacketQueueIndex->IpVersion4[label="IPV4"] - * GetPacketQueueIndex->IpVersion6[label="IPV6"] - * } - * - * @enddot - * - * @section De-Queueing - * @dot - * digraph transmit2 { - * node[shape=box] - * edge[weight=5;color=red] - * interrupt_service_thread->transmit_packets - * tx_pkt_hdler->transmit_packets - * transmit_packets->CheckAndSendPacketFromIndex - * transmit_packets->UpdateTokenCount - * CheckAndSendPacketFromIndex->PruneQueue - * CheckAndSendPacketFromIndex->IsPacketAllowedForFlow - * CheckAndSendPacketFromIndex->SendControlPacket[label="control pkt"] - * SendControlPacket->bcm_cmd53 - * CheckAndSendPacketFromIndex->SendPacketFromQueue[label="data pkt"] - * SendPacketFromQueue->SetupNextSend->bcm_cmd53 - * } - * @enddot - */ +@file Transmit.c +@defgroup tx_functions Transmission +@section Queueing +@dot +digraph transmit1 { +node[shape=box] +edge[weight=5;color=red] + +bcm_transmit->GetPacketQueueIndex[label="IP Packet"] +GetPacketQueueIndex->IpVersion4[label="IPV4"] +GetPacketQueueIndex->IpVersion6[label="IPV6"] +} + +@enddot + +@section De-Queueing +@dot +digraph transmit2 { +node[shape=box] +edge[weight=5;color=red] +interrupt_service_thread->transmit_packets +tx_pkt_hdler->transmit_packets +transmit_packets->CheckAndSendPacketFromIndex +transmit_packets->UpdateTokenCount +CheckAndSendPacketFromIndex->PruneQueue +CheckAndSendPacketFromIndex->IsPacketAllowedForFlow +CheckAndSendPacketFromIndex->SendControlPacket[label="control pkt"] +SendControlPacket->bcm_cmd53 +CheckAndSendPacketFromIndex->SendPacketFromQueue[label="data pkt"] +SendPacketFromQueue->SetupNextSend->bcm_cmd53 +} +@enddot +*/ #include "headers.h" + /** - * @ingroup ctrl_pkt_functions - * This function dispatches control packet to the h/w interface - * @return zero(success) or -ve value(failure) - */ -int SendControlPacket(struct bcm_mini_adapter *Adapter, char *pControlPacket) +@ingroup ctrl_pkt_functions +This function dispatches control packet to the h/w interface +@return zero(success) or -ve value(failure) +*/ +INT SendControlPacket(struct bcm_mini_adapter *Adapter, char *pControlPacket) { struct bcm_leader *PLeader = (struct bcm_leader *)pControlPacket; - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Tx"); - if (!pControlPacket || !Adapter) { - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Got NULL Control Packet or Adapter"); - return STATUS_FAILURE; - } - if ((atomic_read(&Adapter->CurrNumFreeTxDesc) < - ((PLeader->PLength-1)/MAX_DEVICE_DESC_SIZE)+1)) { - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "NO FREE DESCRIPTORS TO SEND CONTROL PACKET"); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Tx"); + if(!pControlPacket || !Adapter) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Got NULL Control Packet or Adapter"); return STATUS_FAILURE; } + if((atomic_read( &Adapter->CurrNumFreeTxDesc ) < + ((PLeader->PLength-1)/MAX_DEVICE_DESC_SIZE)+1)) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "NO FREE DESCRIPTORS TO SEND CONTROL PACKET"); + return STATUS_FAILURE; + } /* Update the netdevice statistics */ /* Dump Packet */ - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Leader Status: %x", PLeader->Status); - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Leader VCID: %x", PLeader->Vcid); - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Leader Length: %x", PLeader->PLength); - if (Adapter->device_removed) + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Leader Status: %x", PLeader->Status); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Leader VCID: %x",PLeader->Vcid); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Leader Length: %x",PLeader->PLength); + if(Adapter->device_removed) return 0; if (netif_msg_pktdata(Adapter)) print_hex_dump(KERN_DEBUG, PFX "tx control: ", DUMP_PREFIX_NONE, - 16, 1, pControlPacket, PLeader->PLength + LEADER_SIZE, 0); + 16, 1, pControlPacket, PLeader->PLength + LEADER_SIZE, 0); Adapter->interface_transmit(Adapter->pvInterfaceAdapter, - pControlPacket, (PLeader->PLength + LEADER_SIZE)); + pControlPacket, (PLeader->PLength + LEADER_SIZE)); atomic_dec(&Adapter->CurrNumFreeTxDesc); - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "<========="); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "<========="); return STATUS_SUCCESS; } /** - * @ingroup tx_functions - * This function despatches the IP packets with the given vcid - * to the target via the host h/w interface. - * @return zero(success) or -ve value(failure) - */ -int SetupNextSend(struct bcm_mini_adapter *Adapter, struct sk_buff *Packet, USHORT Vcid) +@ingroup tx_functions +This function despatches the IP packets with the given vcid +to the target via the host h/w interface. +@return zero(success) or -ve value(failure) +*/ +INT SetupNextSend(struct bcm_mini_adapter *Adapter, struct sk_buff *Packet, USHORT Vcid) { - int status = 0; - BOOLEAN bHeaderSupressionEnabled = FALSE; - B_UINT16 uiClassifierRuleID; + int status=0; + BOOLEAN bHeaderSupressionEnabled = FALSE; + B_UINT16 uiClassifierRuleID; u16 QueueIndex = skb_get_queue_mapping(Packet); - struct bcm_leader Leader = {0}; + struct bcm_leader Leader={0}; - if (Packet->len > MAX_DEVICE_DESC_SIZE) { + if(Packet->len > MAX_DEVICE_DESC_SIZE) + { status = STATUS_FAILURE; goto errExit; } /* Get the Classifier Rule ID */ - uiClassifierRuleID = *((UINT32 *) (Packet->cb) + SKB_CB_CLASSIFICATION_OFFSET); + uiClassifierRuleID = *((UINT32*) (Packet->cb)+SKB_CB_CLASSIFICATION_OFFSET); bHeaderSupressionEnabled = Adapter->PackInfo[QueueIndex].bHeaderSuppressionEnabled & Adapter->bPHSEnabled; - if (Adapter->device_removed) { + if(Adapter->device_removed) + { status = STATUS_FAILURE; goto errExit; - } + } status = PHSTransmit(Adapter, &Packet, Vcid, uiClassifierRuleID, bHeaderSupressionEnabled, - (UINT *)&Packet->len, Adapter->PackInfo[QueueIndex].bEthCSSupport); + (UINT *)&Packet->len, Adapter->PackInfo[QueueIndex].bEthCSSupport); - if (status != STATUS_SUCCESS) { - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "PHS Transmit failed..\n"); + if(status != STATUS_SUCCESS) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "PHS Transmit failed..\n"); goto errExit; } - Leader.Vcid = Vcid; + Leader.Vcid = Vcid; - if (TCP_ACK == *((UINT32 *) (Packet->cb) + SKB_CB_TCPACK_OFFSET)) + if(TCP_ACK == *((UINT32*) (Packet->cb) + SKB_CB_TCPACK_OFFSET )) Leader.Status = LEADER_STATUS_TCP_ACK; else Leader.Status = LEADER_STATUS; - if (Adapter->PackInfo[QueueIndex].bEthCSSupport) { + if(Adapter->PackInfo[QueueIndex].bEthCSSupport) + { Leader.PLength = Packet->len; - if (skb_headroom(Packet) < LEADER_SIZE) { - status = skb_cow(Packet, LEADER_SIZE); - if (status) { - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "bcm_transmit : Failed To Increase headRoom\n"); + if(skb_headroom(Packet) < LEADER_SIZE) + { + if((status = skb_cow(Packet,LEADER_SIZE))) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL,"bcm_transmit : Failed To Increase headRoom\n"); goto errExit; } } skb_push(Packet, LEADER_SIZE); memcpy(Packet->data, &Leader, LEADER_SIZE); - } else { + } + else + { Leader.PLength = Packet->len - ETH_HLEN; memcpy((struct bcm_leader *)skb_pull(Packet, (ETH_HLEN - LEADER_SIZE)), &Leader, LEADER_SIZE); } status = Adapter->interface_transmit(Adapter->pvInterfaceAdapter, - Packet->data, (Leader.PLength + LEADER_SIZE)); - if (status) { + Packet->data, (Leader.PLength + LEADER_SIZE)); + if(status) + { ++Adapter->dev->stats.tx_errors; if (netif_msg_tx_err(Adapter)) pr_info(PFX "%s: transmit error %d\n", Adapter->dev->name, status); - } else { + } + else + { struct net_device_stats *netstats = &Adapter->dev->stats; Adapter->PackInfo[QueueIndex].uiTotalTxBytes += Leader.PLength; @@ -162,6 +175,7 @@ int SetupNextSend(struct bcm_mini_adapter *Adapter, struct sk_buff *Packet, USH atomic_dec(&Adapter->CurrNumFreeTxDesc); errExit: + dev_kfree_skb(Packet); return status; } @@ -174,65 +188,73 @@ static int tx_pending(struct bcm_mini_adapter *Adapter) } /** - * @ingroup tx_functions - * Transmit thread - */ -int tx_pkt_handler(struct bcm_mini_adapter *Adapter /**< pointer to adapter object*/) +@ingroup tx_functions +Transmit thread +*/ +int tx_pkt_handler(struct bcm_mini_adapter *Adapter /**< pointer to adapter object*/ + ) { int status = 0; - while (!kthread_should_stop()) { + while(! kthread_should_stop()) { /* FIXME - the timeout looks like workaround for racey usage of TxPktAvail */ - if (Adapter->LinkUpStatus) + if(Adapter->LinkUpStatus) wait_event_timeout(Adapter->tx_packet_wait_queue, - tx_pending(Adapter), msecs_to_jiffies(10)); + tx_pending(Adapter), msecs_to_jiffies(10)); else wait_event_interruptible(Adapter->tx_packet_wait_queue, - tx_pending(Adapter)); + tx_pending(Adapter)); if (Adapter->device_removed) break; - if (Adapter->downloadDDR == 1) { - Adapter->downloadDDR += 1; + if(Adapter->downloadDDR == 1) + { + Adapter->downloadDDR +=1; status = download_ddr_settings(Adapter); - if (status) + if(status) pr_err(PFX "DDR DOWNLOAD FAILED! %d\n", status); continue; } - /* Check end point for halt/stall. */ - if (Adapter->bEndPointHalted == TRUE) { + //Check end point for halt/stall. + if(Adapter->bEndPointHalted == TRUE) + { Bcm_clear_halt_of_endpoints(Adapter); Adapter->bEndPointHalted = FALSE; StartInterruptUrb((PS_INTERFACE_ADAPTER)(Adapter->pvInterfaceAdapter)); } - if (Adapter->LinkUpStatus && !Adapter->IdleMode) { - if (atomic_read(&Adapter->TotalPacketCount)) + if(Adapter->LinkUpStatus && !Adapter->IdleMode) + { + if(atomic_read(&Adapter->TotalPacketCount)) + { update_per_sf_desc_cnts(Adapter); + } } - if (atomic_read(&Adapter->CurrNumFreeTxDesc) && + if( atomic_read(&Adapter->CurrNumFreeTxDesc) && Adapter->LinkStatus == SYNC_UP_REQUEST && - !Adapter->bSyncUpRequestSent) { - - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Calling LinkMessage"); + !Adapter->bSyncUpRequestSent) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Calling LinkMessage"); LinkMessage(Adapter); } - if ((Adapter->IdleMode || Adapter->bShutStatus) && atomic_read(&Adapter->TotalPacketCount)) { - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Device in Low Power mode...waking up"); - Adapter->usIdleModePattern = ABORT_IDLE_MODE; - Adapter->bWakeUpDevice = TRUE; - wake_up(&Adapter->process_rx_cntrlpkt); + if((Adapter->IdleMode || Adapter->bShutStatus) && atomic_read(&Adapter->TotalPacketCount)) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Device in Low Power mode...waking up"); + Adapter->usIdleModePattern = ABORT_IDLE_MODE; + Adapter->bWakeUpDevice = TRUE; + wake_up(&Adapter->process_rx_cntrlpkt); } transmit_packets(Adapter); + atomic_set(&Adapter->TxPktAvail, 0); } - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Exiting the tx thread..\n"); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Exiting the tx thread..\n"); Adapter->transmit_packet_thread = NULL; return 0; } diff --git a/trunk/drivers/staging/bcm/cntrl_SignalingInterface.h b/trunk/drivers/staging/bcm/cntrl_SignalingInterface.h index 990e809e9680..7619e4b819bd 100644 --- a/trunk/drivers/staging/bcm/cntrl_SignalingInterface.h +++ b/trunk/drivers/staging/bcm/cntrl_SignalingInterface.h @@ -1,311 +1,423 @@ #ifndef CNTRL_SIGNALING_INTERFACE_ #define CNTRL_SIGNALING_INTERFACE_ -#define DSA_REQ 11 -#define DSA_RSP 12 -#define DSA_ACK 13 -#define DSC_REQ 14 -#define DSC_RSP 15 -#define DSC_ACK 16 -#define DSD_REQ 17 -#define DSD_RSP 18 -#define DSD_ACK 19 -#define MAX_CLASSIFIERS_IN_SF 4 - -#define MAX_STRING_LEN 20 -#define MAX_PHS_LENGTHS 255 -#define VENDOR_PHS_PARAM_LENGTH 10 -#define MAX_NUM_ACTIVE_BS 10 -#define AUTH_TOKEN_LENGTH 10 -#define NUM_HARQ_CHANNELS 16 /* Changed from 10 to 16 to accommodate all HARQ channels */ -#define VENDOR_CLASSIFIER_PARAM_LENGTH 1 /* Changed the size to 1 byte since we dnt use it */ -#define VENDOR_SPECIF_QOS_PARAM 1 -#define VENDOR_PHS_PARAM_LENGTH 10 -#define MBS_CONTENTS_ID_LENGTH 10 -#define GLOBAL_SF_CLASSNAME_LENGTH 6 - -#define TYPE_OF_SERVICE_LENGTH 3 -#define IP_MASKED_SRC_ADDRESS_LENGTH 32 -#define IP_MASKED_DEST_ADDRESS_LENGTH 32 -#define PROTOCOL_SRC_PORT_RANGE_LENGTH 4 -#define PROTOCOL_DEST_PORT_RANGE_LENGTH 4 -#define ETHERNET_DEST_MAC_ADDR_LENGTH 12 -#define ETHERNET_SRC_MAC_ADDR_LENGTH 12 -#define NUM_ETHERTYPE_BYTES 3 -#define NUM_IPV6_FLOWLABLE_BYTES 3 - -struct bcm_packet_class_rules { - /* 16bit UserPriority Of The Service Flow */ - B_UINT16 u16UserPriority; - /* 16bit VLANID Of The Service Flow */ - B_UINT16 u16VLANID; - /* 16bit Packet Classification RuleIndex Of The Service Flow */ - B_UINT16 u16PacketClassificationRuleIndex; - /* 8bit Classifier Rule Priority Of The Service Flow */ - B_UINT8 u8ClassifierRulePriority; - /* Length of IP TypeOfService field */ - B_UINT8 u8IPTypeOfServiceLength; - /* 3bytes IP TypeOfService */ - B_UINT8 u8IPTypeOfService[TYPE_OF_SERVICE_LENGTH]; - /* Protocol used in classification of Service Flow */ - B_UINT8 u8Protocol; - /* Length of IP Masked Source Address */ - B_UINT8 u8IPMaskedSourceAddressLength; - /* IP Masked Source Address used in classification for the Service Flow */ - B_UINT8 u8IPMaskedSourceAddress[IP_MASKED_SRC_ADDRESS_LENGTH]; - /* Length of IP Destination Address */ - B_UINT8 u8IPDestinationAddressLength; - /* IP Destination Address used in classification for the Service Flow */ - B_UINT8 u8IPDestinationAddress[IP_MASKED_DEST_ADDRESS_LENGTH]; - /* Length of Protocol Source Port Range */ - B_UINT8 u8ProtocolSourcePortRangeLength; - /* Protocol Source Port Range used in the Service Flow */ - B_UINT8 u8ProtocolSourcePortRange[PROTOCOL_SRC_PORT_RANGE_LENGTH]; - /* Length of Protocol Dest Port Range */ - B_UINT8 u8ProtocolDestPortRangeLength; - /* Protocol Dest Port Range used in the Service Flow */ - B_UINT8 u8ProtocolDestPortRange[PROTOCOL_DEST_PORT_RANGE_LENGTH]; - /* Length of Ethernet Destination MAC Address */ - B_UINT8 u8EthernetDestMacAddressLength; - /* Ethernet Destination MAC Address used in classification of the Service Flow */ - B_UINT8 u8EthernetDestMacAddress[ETHERNET_DEST_MAC_ADDR_LENGTH]; - /* Length of Ethernet Source MAC Address */ - B_UINT8 u8EthernetSourceMACAddressLength; - /* Ethernet Source MAC Address used in classification of the Service Flow */ - B_UINT8 u8EthernetSourceMACAddress[ETHERNET_SRC_MAC_ADDR_LENGTH]; - /* Length of Ethertype */ - B_UINT8 u8EthertypeLength; - /* 3bytes Ethertype Of The Service Flow */ - B_UINT8 u8Ethertype[NUM_ETHERTYPE_BYTES]; - /* 8bit Associated PHSI Of The Service Flow */ - B_UINT8 u8AssociatedPHSI; - /* Length of Vendor Specific Classifier Param length Of The Service Flow */ - B_UINT8 u8VendorSpecificClassifierParamLength; - /* Vendor Specific Classifier Param Of The Service Flow */ - B_UINT8 u8VendorSpecificClassifierParam[VENDOR_CLASSIFIER_PARAM_LENGTH]; - /* Length Of IPv6 Flow Lable of the Service Flow */ - B_UINT8 u8IPv6FlowLableLength; - /* IPv6 Flow Lable Of The Service Flow */ - B_UINT8 u8IPv6FlowLable[NUM_IPV6_FLOWLABLE_BYTES]; - /* Action associated with the classifier rule */ - B_UINT8 u8ClassifierActionRule; - B_UINT16 u16ValidityBitMap; -}; -struct bcm_phs_rules { - /* 8bit PHS Index Of The Service Flow */ - B_UINT8 u8PHSI; - /* PHSF Length Of The Service Flow */ - B_UINT8 u8PHSFLength; - /* String of bytes containing header information to be suppressed by the sending CS and reconstructed by the receiving CS */ - B_UINT8 u8PHSF[MAX_PHS_LENGTHS]; - /* PHSM Length Of The Service Flow */ - B_UINT8 u8PHSMLength; - /* PHS Mask for the SF */ - B_UINT8 u8PHSM[MAX_PHS_LENGTHS]; - /* 8bit Total number of bytes to be suppressed for the Service Flow */ - B_UINT8 u8PHSS; - /* 8bit Indicates whether or not Packet Header contents need to be verified prior to suppression */ - B_UINT8 u8PHSV; - /* Vendor Specific PHS param Length Of The Service Flow */ - B_UINT8 u8VendorSpecificPHSParamsLength; - /* Vendor Specific PHS param Of The Service Flow */ - B_UINT8 u8VendorSpecificPHSParams[VENDOR_PHS_PARAM_LENGTH]; - B_UINT8 u8Padding[2]; -}; -struct bcm_convergence_types { - /* 8bit Phs Classfier Action Of The Service Flow */ - B_UINT8 u8ClassfierDSCAction; - /* 8bit Phs DSC Action Of The Service Flow */ - B_UINT8 u8PhsDSCAction; - /* 16bit Padding */ - B_UINT8 u8Padding[2]; - /* Packet classification rules structure */ - struct bcm_packet_class_rules cCPacketClassificationRule; - /* Payload header suppression rules structure */ - struct bcm_phs_rules cPhsRule; -}; -struct bcm_connect_mgr_params { - /* 32bitSFID Of The Service Flow */ - B_UINT32 u32SFID; - /* 32bit Maximum Sustained Traffic Rate of the Service Flow */ - B_UINT32 u32MaxSustainedTrafficRate; - /* 32bit Maximum Traffic Burst allowed for the Service Flow */ - B_UINT32 u32MaxTrafficBurst; - /* 32bit Minimum Reserved Traffic Rate of the Service Flow */ - B_UINT32 u32MinReservedTrafficRate; - /* 32bit Tolerated Jitter of the Service Flow */ - B_UINT32 u32ToleratedJitter; - /* 32bit Maximum Latency of the Service Flow */ - B_UINT32 u32MaximumLatency; - /* 16bitCID Of The Service Flow */ - B_UINT16 u16CID; - /* 16bit SAID on which the service flow being set up shall be mapped */ - B_UINT16 u16TargetSAID; - /* 16bit ARQ window size negotiated */ - B_UINT16 u16ARQWindowSize; - /* 16bit Total Tx delay incl sending, receiving & processing delays */ - B_UINT16 u16ARQRetryTxTimeOut; - /* 16bit Total Rx delay incl sending, receiving & processing delays */ - B_UINT16 u16ARQRetryRxTimeOut; - /* 16bit ARQ block lifetime */ - B_UINT16 u16ARQBlockLifeTime; - /* 16bit ARQ Sync loss timeout */ - B_UINT16 u16ARQSyncLossTimeOut; - /* 16bit ARQ Purge timeout */ - B_UINT16 u16ARQRxPurgeTimeOut; - /* TODO::Remove this once we move to a new CORR2 driver - * brief Size of an ARQ block - */ - B_UINT16 u16ARQBlockSize; - /* #endif */ - /* 16bit Nominal interval b/w consecutive SDU arrivals at MAC SAP */ - B_UINT16 u16SDUInterArrivalTime; - /* 16bit Specifies the time base for rate measurement */ - B_UINT16 u16TimeBase; - /* 16bit Interval b/w Successive Grant oppurtunities */ - B_UINT16 u16UnsolicitedGrantInterval; - /* 16bit Interval b/w Successive Polling grant oppurtunities */ - B_UINT16 u16UnsolicitedPollingInterval; - /* internal var to get the overhead */ - B_UINT16 u16MacOverhead; - /* MBS contents Identifier */ - B_UINT16 u16MBSContentsID[MBS_CONTENTS_ID_LENGTH]; - /* MBS contents Identifier length */ - B_UINT8 u8MBSContentsIDLength; - /* ServiceClassName Length Of The Service Flow */ - B_UINT8 u8ServiceClassNameLength; - /* 32bytes ServiceClassName Of The Service Flow */ - B_UINT8 u8ServiceClassName[32]; - /* 8bit Indicates whether or not MBS service is requested for this Serivce Flow */ - B_UINT8 u8MBSService; - /* 8bit QOS Parameter Set specifies proper application of QoS parameters to Provisioned, Admitted and Active sets */ - B_UINT8 u8QosParamSet; - /* 8bit Traffic Priority Of the Service Flow */ - B_UINT8 u8TrafficPriority; - /* 8bit Uplink Grant Scheduling Type of The Service Flow */ - B_UINT8 u8ServiceFlowSchedulingType; - /* 8bit Request transmission Policy of the Service Flow */ - B_UINT8 u8RequesttransmissionPolicy; - /* 8bit Specifies whether SDUs for this Service flow are of FixedLength or Variable length */ - B_UINT8 u8FixedLengthVSVariableLengthSDUIndicator; - /* 8bit Length of the SDU for a fixed length SDU service flow */ - B_UINT8 u8SDUSize; - /* 8bit Indicates whether or not ARQ is requested for this connection */ - B_UINT8 u8ARQEnable; - /* < 8bit Indicates whether or not data has tobe delivered in order to higher layer */ - B_UINT8 u8ARQDeliverInOrder; - /* 8bit Receiver ARQ ACK processing time */ - B_UINT8 u8RxARQAckProcessingTime; - /* 8bit Convergence Sublayer Specification Of The Service Flow */ - B_UINT8 u8CSSpecification; - /* 8 bit Type of data delivery service */ - B_UINT8 u8TypeOfDataDeliveryService; - /* 8bit Specifies whether a service flow may generate Paging */ - B_UINT8 u8PagingPreference; - /* 8bit Indicates the MBS Zone through which the connection or virtual connection is valid */ - B_UINT8 u8MBSZoneIdentifierassignment; - /* 8bit Specifies whether traffic on SF should generate MOB_TRF_IND to MS in sleep mode */ - B_UINT8 u8TrafficIndicationPreference; - /* 8bit Speciifes the length of predefined Global QoS parameter set encoding for this SF */ - B_UINT8 u8GlobalServicesClassNameLength; - /* 6 byte Speciifes the predefined Global QoS parameter set encoding for this SF */ - B_UINT8 u8GlobalServicesClassName[GLOBAL_SF_CLASSNAME_LENGTH]; - /* 8bit Indicates whether or not SN feedback is enabled for the conn */ - B_UINT8 u8SNFeedbackEnabled; - /* Indicates the size of the Fragment Sequence Number for the connection */ - B_UINT8 u8FSNSize; - /* 8bit Number of CIDs in active BS list */ - B_UINT8 u8CIDAllocation4activeBSsLength; - /* CIDs of BS in the active list */ - B_UINT8 u8CIDAllocation4activeBSs[MAX_NUM_ACTIVE_BS]; - /* Specifies if PDU extended subheader should be applied on every PDU on this conn */ - B_UINT8 u8PDUSNExtendedSubheader4HarqReordering; - /* 8bit Specifies whether the connection uses HARQ or not */ - B_UINT8 u8HARQServiceFlows; - /* Specifies the length of Authorization token */ - B_UINT8 u8AuthTokenLength; - /* Specifies the Authorization token */ - B_UINT8 u8AuthToken[AUTH_TOKEN_LENGTH]; - /* specifes Number of HARQ channels used to carry data length */ - B_UINT8 u8HarqChannelMappingLength; - /* specifes HARQ channels used to carry data */ - B_UINT8 u8HARQChannelMapping[NUM_HARQ_CHANNELS]; - /* 8bit Length of Vendor Specific QoS Params */ - B_UINT8 u8VendorSpecificQoSParamLength; - /* 1byte Vendor Specific QoS Param Of The Service Flow */ - B_UINT8 u8VendorSpecificQoSParam[VENDOR_SPECIF_QOS_PARAM]; - /* indicates total classifiers in the SF */ - B_UINT8 u8TotalClassifiers; /* < Total number of valid classifiers */ - B_UINT8 bValid; /* < Validity flag */ - B_UINT8 u8Padding; /* < Padding byte */ - /* - * Structure for Convergence SubLayer Types with a maximum of 4 classifiers - */ - struct bcm_convergence_types cConvergenceSLTypes[MAX_CLASSIFIERS_IN_SF]; -}; +#define DSA_REQ 11 +#define DSA_RSP 12 +#define DSA_ACK 13 +#define DSC_REQ 14 +#define DSC_RSP 15 +#define DSC_ACK 16 +#define DSD_REQ 17 +#define DSD_RSP 18 +#define DSD_ACK 19 +#define MAX_CLASSIFIERS_IN_SF 4 -struct bcm_add_request { - B_UINT8 u8Type; /* < Type */ - B_UINT8 eConnectionDir; /* < Connection direction */ - /* brief 16 bit TID */ - B_UINT16 u16TID; /* < 16bit TID */ - /* brief 16bitCID */ - B_UINT16 u16CID; /* < 16bit CID */ - /* brief 16bitVCID */ - B_UINT16 u16VCID; /* < 16bit VCID */ - struct bcm_connect_mgr_params *psfParameterSet; /* < connection manager parameters */ -}; -struct bcm_add_indication { - B_UINT8 u8Type; /* < Type */ - B_UINT8 eConnectionDir; /* < Connection Direction */ - /* brief 16 bit TID */ - B_UINT16 u16TID; /* < TID */ - /* brief 16bitCID */ - B_UINT16 u16CID; /* < 16bitCID */ - /* brief 16bitVCID */ - B_UINT16 u16VCID; /* < 16bitVCID */ - struct bcm_connect_mgr_params *psfAuthorizedSet; /* Authorized set of connection manager parameters */ - struct bcm_connect_mgr_params *psfAdmittedSet; /* Admitted set of connection manager parameters */ - struct bcm_connect_mgr_params *psfActiveSet; /* Activeset of connection manager parameters */ - B_UINT8 u8CC; /* PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable; diff --git a/trunk/drivers/staging/bcm/nvm.c b/trunk/drivers/staging/bcm/nvm.c index b034eb5fa6b1..b179dbab93b5 100644 --- a/trunk/drivers/staging/bcm/nvm.c +++ b/trunk/drivers/staging/bcm/nvm.c @@ -577,7 +577,7 @@ static int FlashSectorErase(struct bcm_mini_adapter *Adapter, * the sector erase cycle is 500 ms to 40000 msec. hence sleeping 10 ms * won't hamper performance in any case. */ - mdelay(10); + udelay(10000); } while ((uiStatus & 0x1) && (iRetries < 400)); if (uiStatus & 0x1) { @@ -3932,7 +3932,7 @@ int validateFlash2xReadWrite(struct bcm_mini_adapter *Adapter, PFLASH2X_READWRIT BcmGetSectionValStartOffset(Adapter, ISO_IMAGE2_PART3); } - /* since this uiSectEndoffset is the size of iso Image. hence for calculating the virtual endoffset + /* since this uiSectEndoffset is the size of iso Image. hence for calculating the vitual endoffset * it should be added in startoffset. so that check done in last of this function can be valued. */ uiSectEndOffset = uiSectStartOffset + uiSectEndOffset; diff --git a/trunk/drivers/staging/bcm/target_params.h b/trunk/drivers/staging/bcm/target_params.h index ad7ec0054938..14876388b879 100644 --- a/trunk/drivers/staging/bcm/target_params.h +++ b/trunk/drivers/staging/bcm/target_params.h @@ -32,7 +32,7 @@ typedef struct _TARGET_PARAMS B_UINT32 m_u32PowerSavingModesEnable; //bit 1: 1 Idlemode enable; bit2: 1 Sleepmode Enable /* PowerSaving Mode Options: bit 0 = 1: CPE mode - to keep pcmcia if alive; - bit 1 = 1: CINR reporting in Idlemode Msg + bit 1 = 1: CINR reporing in Idlemode Msg bit 2 = 1: Default PSC Enable in sleepmode*/ B_UINT32 m_u32PowerSavingModeOptions; diff --git a/trunk/drivers/staging/ccg/Kconfig b/trunk/drivers/staging/ccg/Kconfig index 8598111eb0b1..1f00d701da25 100644 --- a/trunk/drivers/staging/ccg/Kconfig +++ b/trunk/drivers/staging/ccg/Kconfig @@ -2,7 +2,7 @@ if USB_GADGET config USB_G_CCG tristate "Configurable Composite Gadget (STAGING)" - depends on STAGING && BLOCK && NET && !USB_ZERO && !USB_ZERO_HNPTEST && !USB_AUDIO && !GADGET_UAC1 && !USB_ETH && !USB_ETH_RNDIS && !USB_ETH_EEM && !USB_G_NCM && !USB_GADGETFS && !USB_FUNCTIONFS && !USB_FUNCTIONFS_ETH && !USB_FUNCTIONFS_RNDIS && !USB_FUNCTIONFS_GENERIC && !USB_FILE_STORAGE && !USB_FILE_STORAGE_TEST && !USB_MASS_STORAGE && !USB_G_SERIAL && !USB_MIDI_GADGET && !USB_G_PRINTER && !USB_CDC_COMPOSITE && !USB_G_NOKIA && !USB_G_ACM_MS && !USB_G_MULTI && !USB_G_MULTI_RNDIS && !USB_G_MULTI_CDC && !USB_G_HID && !USB_G_DBGP && !USB_G_WEBCAM + depends on STAGING && BLOCK && !USB_ZERO && !USB_ZERO_HNPTEST && !USB_AUDIO && !GADGET_UAC1 && !USB_ETH && !USB_ETH_RNDIS && !USB_ETH_EEM && !USB_G_NCM && !USB_GADGETFS && !USB_FUNCTIONFS && !USB_FUNCTIONFS_ETH && !USB_FUNCTIONFS_RNDIS && !USB_FUNCTIONFS_GENERIC && !USB_FILE_STORAGE && !USB_FILE_STORAGE_TEST && !USB_MASS_STORAGE && !USB_G_SERIAL && !USB_MIDI_GADGET && !USB_G_PRINTER && !USB_CDC_COMPOSITE && !USB_G_NOKIA && !USB_G_ACM_MS && !USB_G_MULTI && !USB_G_MULTI_RNDIS && !USB_G_MULTI_CDC && !USB_G_HID && !USB_G_DBGP && !USB_G_WEBCAM help The Configurable Composite Gadget supports multiple USB functions: acm, mass storage, rndis and FunctionFS. diff --git a/trunk/drivers/staging/ccg/ccg.c b/trunk/drivers/staging/ccg/ccg.c index 3fbb300cbe30..6a7aab8d9bf5 100644 --- a/trunk/drivers/staging/ccg/ccg.c +++ b/trunk/drivers/staging/ccg/ccg.c @@ -728,7 +728,7 @@ static int mass_storage_function_init(struct ccg_usb_function *f, struct fsg_common *common; int err; - memset(&fsg, 0, sizeof(fsg)); + memset(&fsg, 0, sizeof fsg); fsg.nluns = 1; fsg.luns[0].removable = 1; fsg.vendor_name = iManufacturer; @@ -1101,7 +1101,13 @@ static struct device_attribute *ccg_usb_attributes[] = { static int ccg_bind_config(struct usb_configuration *c) { struct ccg_dev *dev = _ccg_dev; - return ccg_bind_enabled_functions(dev, c); + int ret = 0; + + ret = ccg_bind_enabled_functions(dev, c); + if (ret) + return ret; + + return 0; } static void ccg_unbind_config(struct usb_configuration *c) @@ -1248,10 +1254,8 @@ static int __init init(void) return PTR_ERR(ccg_class); dev = kzalloc(sizeof(*dev), GFP_KERNEL); - if (!dev) { - class_destroy(ccg_class); + if (!dev) return -ENOMEM; - } dev->functions = supported_functions; INIT_LIST_HEAD(&dev->enabled_functions); diff --git a/trunk/drivers/staging/ced1401/Kconfig b/trunk/drivers/staging/ced1401/Kconfig deleted file mode 100644 index ae36d1b2ba99..000000000000 --- a/trunk/drivers/staging/ced1401/Kconfig +++ /dev/null @@ -1,6 +0,0 @@ -config CED1401 - tristate "Cambridge Electronic Design 1401 USB support" - depends on USB - help - This driver supports the Cambridge Electronic Design 1401 USB device - (whatever that is.) diff --git a/trunk/drivers/staging/ced1401/Makefile b/trunk/drivers/staging/ced1401/Makefile deleted file mode 100644 index f0c114b2b4b9..000000000000 --- a/trunk/drivers/staging/ced1401/Makefile +++ /dev/null @@ -1,3 +0,0 @@ - -obj-$(CONFIG_CED1401) := cedusb.o -cedusb-objs := usb1401.o ced_ioc.o diff --git a/trunk/drivers/staging/ced1401/TODO b/trunk/drivers/staging/ced1401/TODO deleted file mode 100644 index 9fd5630bdf4d..000000000000 --- a/trunk/drivers/staging/ced1401/TODO +++ /dev/null @@ -1,10 +0,0 @@ -TODO: - - coding syle fixes - - build warning fixups - - ioctl auditing - - usb api auditing - - proper USB minor number (it's stomping on an existing one right now.) - -Please send patches to Greg Kroah-Hartman and Cc: -Alois Schlögl - diff --git a/trunk/drivers/staging/ced1401/ced_ioc.c b/trunk/drivers/staging/ced1401/ced_ioc.c deleted file mode 100644 index c9492edaaddb..000000000000 --- a/trunk/drivers/staging/ced1401/ced_ioc.c +++ /dev/null @@ -1,1515 +0,0 @@ -/* ced_ioc.c - ioctl part of the 1401 usb device driver for linux. - Copyright (C) 2010 Cambridge Electronic Design Ltd - Author Greg P Smith (greg@ced.co.uk) - - 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "usb1401.h" - -/**************************************************************************** -** FlushOutBuff -** -** Empties the Output buffer and sets int lines. Used from user level only -****************************************************************************/ -void FlushOutBuff(DEVICE_EXTENSION * pdx) -{ - dev_dbg(&pdx->interface->dev, "%s currentState=%d", __func__, - pdx->sCurrentState); - if (pdx->sCurrentState == U14ERR_TIME) /* Do nothing if hardware in trouble */ - return; -// CharSend_Cancel(pdx); /* Kill off any pending I/O */ - spin_lock_irq(&pdx->charOutLock); - pdx->dwNumOutput = 0; - pdx->dwOutBuffGet = 0; - pdx->dwOutBuffPut = 0; - spin_unlock_irq(&pdx->charOutLock); -} - -/**************************************************************************** -** -** FlushInBuff -** -** Empties the input buffer and sets int lines -****************************************************************************/ -void FlushInBuff(DEVICE_EXTENSION * pdx) -{ - dev_dbg(&pdx->interface->dev, "%s currentState=%d", __func__, - pdx->sCurrentState); - if (pdx->sCurrentState == U14ERR_TIME) /* Do nothing if hardware in trouble */ - return; -// CharRead_Cancel(pDevObject); /* Kill off any pending I/O */ - spin_lock_irq(&pdx->charInLock); - pdx->dwNumInput = 0; - pdx->dwInBuffGet = 0; - pdx->dwInBuffPut = 0; - spin_unlock_irq(&pdx->charInLock); -} - -/**************************************************************************** -** PutChars -** -** Utility routine to copy chars into the output buffer and fire them off. -** called from user mode, holds charOutLock. -****************************************************************************/ -static int PutChars(DEVICE_EXTENSION * pdx, const char *pCh, - unsigned int uCount) -{ - int iReturn; - spin_lock_irq(&pdx->charOutLock); // get the output spin lock - if ((OUTBUF_SZ - pdx->dwNumOutput) >= uCount) { - unsigned int u; - for (u = 0; u < uCount; u++) { - pdx->outputBuffer[pdx->dwOutBuffPut++] = pCh[u]; - if (pdx->dwOutBuffPut >= OUTBUF_SZ) - pdx->dwOutBuffPut = 0; - } - pdx->dwNumOutput += uCount; - spin_unlock_irq(&pdx->charOutLock); - iReturn = SendChars(pdx); // ...give a chance to transmit data - } else { - iReturn = U14ERR_NOOUT; // no room at the out (ha-ha) - spin_unlock_irq(&pdx->charOutLock); - } - return iReturn; -} - -/***************************************************************************** -** Add the data in pData (local pointer) of length n to the output buffer, and -** trigger an output transfer if this is appropriate. User mode. -** Holds the io_mutex -*****************************************************************************/ -int SendString(DEVICE_EXTENSION * pdx, const char __user * pData, - unsigned int n) -{ - int iReturn = U14ERR_NOERROR; // assume all will be well - char buffer[OUTBUF_SZ + 1]; // space in our address space for characters - if (n > OUTBUF_SZ) // check space in local buffer... - return U14ERR_NOOUT; // ...too many characters - if (copy_from_user(buffer, pData, n)) - return -EFAULT; - buffer[n] = 0; // terminate for debug purposes - - mutex_lock(&pdx->io_mutex); // Protect disconnect from new i/o - if (n > 0) // do nothing if nowt to do! - { - dev_dbg(&pdx->interface->dev, "%s n=%d>%s<", __func__, n, - buffer); - iReturn = PutChars(pdx, buffer, n); - } - - Allowi(pdx, false); // make sure we have input int - mutex_unlock(&pdx->io_mutex); - - return iReturn; -} - -/**************************************************************************** -** SendChar -** -** Sends a single character to the 1401. User mode, holds io_mutex. -****************************************************************************/ -int SendChar(DEVICE_EXTENSION * pdx, char c) -{ - int iReturn; - mutex_lock(&pdx->io_mutex); // Protect disconnect from new i/o - iReturn = PutChars(pdx, &c, 1); - dev_dbg(&pdx->interface->dev, "SendChar >%c< (0x%02x)", c, c); - Allowi(pdx, false); // Make sure char reads are running - mutex_unlock(&pdx->io_mutex); - return iReturn; -} - -/*************************************************************************** -** -** Get1401State -** -** Retrieves state information from the 1401, adjusts the 1401 state held -** in the device extension to indicate the current 1401 type. -** -** *state is updated with information about the 1401 state as returned by the -** 1401. The low byte is a code for what 1401 is doing: -** -** 0 normal 1401 operation -** 1 sending chars to host -** 2 sending block data to host -** 3 reading block data from host -** 4 sending an escape sequence to the host -** 0x80 1401 is executing self-test, in which case the upper word -** is the last error code seen (or zero for no new error). -** -** *error is updated with error information if a self-test error code -** is returned in the upper word of state. -** -** both state and error are set to -1 if there are comms problems, and -** to zero if there is a simple failure. -** -** return error code (U14ERR_NOERROR for OK) -*/ -int Get1401State(DEVICE_EXTENSION * pdx, __u32 * state, __u32 * error) -{ - int nGot; - dev_dbg(&pdx->interface->dev, "Get1401State() entry"); - - *state = 0xFFFFFFFF; // Start off with invalid state - nGot = usb_control_msg(pdx->udev, usb_rcvctrlpipe(pdx->udev, 0), - GET_STATUS, (D_TO_H | VENDOR | DEVREQ), 0, 0, - pdx->statBuf, sizeof(pdx->statBuf), HZ); - if (nGot != sizeof(pdx->statBuf)) { - dev_err(&pdx->interface->dev, - "Get1401State() FAILED, return code %d", nGot); - pdx->sCurrentState = U14ERR_TIME; // Indicate that things are very wrong indeed - *state = 0; // Force status values to a known state - *error = 0; - } else { - int nDevice; - dev_dbg(&pdx->interface->dev, - "Get1401State() Success, state: 0x%x, 0x%x", - pdx->statBuf[0], pdx->statBuf[1]); - - *state = pdx->statBuf[0]; // Return the state values to the calling code - *error = pdx->statBuf[1]; - - nDevice = pdx->udev->descriptor.bcdDevice >> 8; // 1401 type code value - switch (nDevice) // so we can clean up current state - { - case 0: - pdx->sCurrentState = U14ERR_U1401; - break; - - default: // allow lots of device codes for future 1401s - if ((nDevice >= 1) && (nDevice <= 23)) - pdx->sCurrentState = (short)(nDevice + 6); - else - pdx->sCurrentState = U14ERR_ILL; - break; - } - } - - return pdx->sCurrentState >= 0 ? U14ERR_NOERROR : pdx->sCurrentState; -} - -/**************************************************************************** -** ReadWrite_Cancel -** -** Kills off staged read\write request from the USB if one is pending. -****************************************************************************/ -int ReadWrite_Cancel(DEVICE_EXTENSION * pdx) -{ - dev_dbg(&pdx->interface->dev, "ReadWrite_Cancel entry %d", - pdx->bStagedUrbPending); -#ifdef NOT_WRITTEN_YET - int ntStatus = STATUS_SUCCESS; - bool bResult = false; - unsigned int i; - // We can fill this in when we know how we will implement the staged transfer stuff - spin_lock_irq(&pdx->stagedLock); - - if (pdx->bStagedUrbPending) // anything to be cancelled? May need more... - { - dev_info(&pdx->interface - dev, - "ReadWrite_Cancel about to cancel Urb"); - - // KeClearEvent(&pdx->StagingDoneEvent); // Clear the staging done flag - USB_ASSERT(pdx->pStagedIrp != NULL); - - // Release the spinlock first otherwise the completion routine may hang - // on the spinlock while this function hands waiting for the event. - spin_unlock_irq(&pdx->stagedLock); - bResult = IoCancelIrp(pdx->pStagedIrp); // Actually do the cancel - if (bResult) { - LARGE_INTEGER timeout; - timeout.QuadPart = -10000000; // Use a timeout of 1 second - dev_info(&pdx->interface - dev, - "ReadWrite_Cancel about to wait till done"); - ntStatus = - KeWaitForSingleObject(&pdx->StagingDoneEvent, - Executive, KernelMode, FALSE, - &timeout); - } else { - dev_info(&pdx->interface - dev, - "ReadWrite_Cancel, cancellation failed"); - ntStatus = U14ERR_FAIL; - } - USB_KdPrint(DBGLVL_DEFAULT, - ("ReadWrite_Cancel ntStatus = 0x%x decimal %d\n", - ntStatus, ntStatus)); - } else - spin_unlock_irq(&pdx->stagedLock); - - dev_info(&pdx->interface - dev, "ReadWrite_Cancel done"); - return ntStatus; -#else - return U14ERR_NOERROR; -#endif - -} - -/*************************************************************************** -** InSelfTest - utility to check in self test. Return 1 for ST, 0 for not or -** a -ve error code if we failed for some reason. -***************************************************************************/ -static int InSelfTest(DEVICE_EXTENSION * pdx, unsigned int *pState) -{ - unsigned int state, error; - int iReturn = Get1401State(pdx, &state, &error); // see if in self-test - if (iReturn == U14ERR_NOERROR) // if all still OK - iReturn = (state == (unsigned int)-1) || // TX problem or... - ((state & 0xff) == 0x80); // ...self test - *pState = state; // return actual state - return iReturn; -} - -/*************************************************************************** -** Is1401 - ALWAYS CALLED HOLDING THE io_mutex -** -** Tests for the current state of the 1401. Sets sCurrentState: -** -** U14ERR_NOIF 1401 i/f card not installed (not done here) -** U14ERR_OFF 1401 apparently not switched on -** U14ERR_NC 1401 appears to be not connected -** U14ERR_ILL 1401 if it is there its not very well at all -** U14ERR_TIME 1401 appears OK, but doesn't communicate - very bad -** U14ERR_STD 1401 OK and ready for use -** U14ERR_PLUS 1401+ OK and ready for use -** U14ERR_U1401 Micro1401 OK and ready for use -** U14ERR_POWER Power1401 OK and ready for use -** U14ERR_U14012 Micro1401 mkII OK and ready for use -** -** Returns TRUE if a 1401 detected and OK, else FALSE -****************************************************************************/ -bool Is1401(DEVICE_EXTENSION * pdx) -{ - int iReturn; - dev_dbg(&pdx->interface->dev, "%s", __func__); - - ced_draw_down(pdx); // wait for, then kill outstanding Urbs - FlushInBuff(pdx); // Clear out input buffer & pipe - FlushOutBuff(pdx); // Clear output buffer & pipe - - // The next call returns 0 if OK, but has returned 1 in the past, meaning that - // usb_unlock_device() is needed... now it always is - iReturn = usb_lock_device_for_reset(pdx->udev, pdx->interface); - - // release the io_mutex because if we don't, we will deadlock due to system - // calls back into the driver. - mutex_unlock(&pdx->io_mutex); // locked, so we will not get system calls - if (iReturn >= 0) // if we failed - { - iReturn = usb_reset_device(pdx->udev); // try to do the reset - usb_unlock_device(pdx->udev); // undo the lock - } - - mutex_lock(&pdx->io_mutex); // hold stuff off while we wait - pdx->dwDMAFlag = MODE_CHAR; // Clear DMA mode flag regardless! - if (iReturn == 0) // if all is OK still - { - unsigned int state; - iReturn = InSelfTest(pdx, &state); // see if likely in self test - if (iReturn > 0) // do we need to wait for self-test? - { - unsigned long ulTimeOut = jiffies + 30 * HZ; // when to give up - while ((iReturn > 0) && time_before(jiffies, ulTimeOut)) { - schedule(); // let other stuff run - iReturn = InSelfTest(pdx, &state); // see if done yet - } - } - - if (iReturn == 0) // if all is OK... - iReturn = state == 0; // then sucess is that the state is 0 - } else - iReturn = 0; // we failed - pdx->bForceReset = false; // Clear forced reset flag now - - return iReturn > 0; -} - -/**************************************************************************** -** QuickCheck - ALWAYS CALLED HOLDING THE io_mutex -** This is used to test for a 1401. It will try to do a quick check if all is -** OK, that is the 1401 was OK the last time it was asked, and there is no DMA -** in progress, and if the bTestBuff flag is set, the character buffers must be -** empty too. If the quick check shows that the state is still the same, then -** all is OK. -** -** If any of the above conditions are not met, or if the state or type of the -** 1401 has changed since the previous test, the full Is1401 test is done, but -** only if bCanReset is also TRUE. -** -** The return value is TRUE if a useable 1401 is found, FALSE if not -*/ -bool QuickCheck(DEVICE_EXTENSION * pdx, bool bTestBuff, bool bCanReset) -{ - bool bRet = false; // assume it will fail and we will reset - bool bShortTest; - - bShortTest = ((pdx->dwDMAFlag == MODE_CHAR) && // no DMA running - (!pdx->bForceReset) && // Not had a real reset forced - (pdx->sCurrentState >= U14ERR_STD)); // No 1401 errors stored - - dev_dbg(&pdx->interface->dev, - "%s DMAFlag:%d, state:%d, force:%d, testBuff:%d, short:%d", - __func__, pdx->dwDMAFlag, pdx->sCurrentState, pdx->bForceReset, - bTestBuff, bShortTest); - - if ((bTestBuff) && // Buffer check requested, and... - (pdx->dwNumInput || pdx->dwNumOutput)) // ...characters were in the buffer? - { - bShortTest = false; // Then do the full test - dev_dbg(&pdx->interface->dev, - "%s will reset as buffers not empty", __func__); - } - - if (bShortTest || !bCanReset) // Still OK to try the short test? - { // Always test if no reset - we want state update - unsigned int state, error; - dev_dbg(&pdx->interface->dev, "%s->Get1401State", __func__); - if (Get1401State(pdx, &state, &error) == U14ERR_NOERROR) // Check on the 1401 state - { - if ((state & 0xFF) == 0) // If call worked, check the status value - bRet = true; // If that was zero, all is OK, no reset needed - } - } - - if (!bRet && bCanReset) // If all not OK, then - { - dev_info(&pdx->interface->dev, "%s->Is1401 %d %d %d %d", - __func__, bShortTest, pdx->sCurrentState, bTestBuff, - pdx->bForceReset); - bRet = Is1401(pdx); // do full test - } - - return bRet; -} - -/**************************************************************************** -** Reset1401 -** -** Resets the 1401 and empties the i/o buffers -*****************************************************************************/ -int Reset1401(DEVICE_EXTENSION * pdx) -{ - mutex_lock(&pdx->io_mutex); // Protect disconnect from new i/o - dev_dbg(&pdx->interface->dev, "ABout to call QuickCheck"); - QuickCheck(pdx, true, true); // Check 1401, reset if not OK - mutex_unlock(&pdx->io_mutex); - return U14ERR_NOERROR; -} - -/**************************************************************************** -** GetChar -** -** Gets a single character from the 1401 -****************************************************************************/ -int GetChar(DEVICE_EXTENSION * pdx) -{ - int iReturn = U14ERR_NOIN; // assume we will get nothing - mutex_lock(&pdx->io_mutex); // Protect disconnect from new i/o - - dev_dbg(&pdx->interface->dev, "GetChar"); - - Allowi(pdx, false); // Make sure char reads are running - SendChars(pdx); // and send any buffered chars - - spin_lock_irq(&pdx->charInLock); - if (pdx->dwNumInput > 0) // worth looking - { - iReturn = pdx->inputBuffer[pdx->dwInBuffGet++]; - if (pdx->dwInBuffGet >= INBUF_SZ) - pdx->dwInBuffGet = 0; - pdx->dwNumInput--; - } else - iReturn = U14ERR_NOIN; // no input data to read - spin_unlock_irq(&pdx->charInLock); - - Allowi(pdx, false); // Make sure char reads are running - - mutex_unlock(&pdx->io_mutex); // Protect disconnect from new i/o - return iReturn; -} - -/**************************************************************************** -** GetString -** -** Gets a string from the 1401. Returns chars up to the next CR or when -** there are no more to read or nowhere to put them. CR is translated to -** 0 and counted as a character. If the string does not end in a 0, we will -** add one, if there is room, but it is not counted as a character. -** -** returns the count of characters (including the terminator, or 0 if none -** or a negative error code. -****************************************************************************/ -int GetString(DEVICE_EXTENSION * pdx, char __user * pUser, int n) -{ - int nAvailable; // character in the buffer - int iReturn = U14ERR_NOIN; - if (n <= 0) - return -ENOMEM; - - mutex_lock(&pdx->io_mutex); // Protect disconnect from new i/o - Allowi(pdx, false); // Make sure char reads are running - SendChars(pdx); // and send any buffered chars - - spin_lock_irq(&pdx->charInLock); - nAvailable = pdx->dwNumInput; // characters available now - if (nAvailable > n) // read max of space in pUser... - nAvailable = n; // ...or input characters - - if (nAvailable > 0) // worth looking? - { - char buffer[INBUF_SZ + 1]; // space for a linear copy of data - int nGot = 0; - int nCopyToUser; // number to copy to user - char cData; - do { - cData = pdx->inputBuffer[pdx->dwInBuffGet++]; - if (cData == CR_CHAR) // replace CR with zero - cData = (char)0; - - if (pdx->dwInBuffGet >= INBUF_SZ) - pdx->dwInBuffGet = 0; // wrap buffer pointer - - buffer[nGot++] = cData; // save the output - } - while ((nGot < nAvailable) && cData); - - nCopyToUser = nGot; // what to copy... - if (cData) // do we need null - { - buffer[nGot] = (char)0; // make it tidy - if (nGot < n) // if space in user buffer... - ++nCopyToUser; // ...copy the 0 as well. - } - - pdx->dwNumInput -= nGot; - spin_unlock_irq(&pdx->charInLock); - - dev_dbg(&pdx->interface->dev, - "GetString read %d characters >%s<", nGot, buffer); - if (copy_to_user(pUser, buffer, nCopyToUser)) - iReturn = -EFAULT; - else - iReturn = nGot; // report characters read - } else - spin_unlock_irq(&pdx->charInLock); - - Allowi(pdx, false); // Make sure char reads are running - mutex_unlock(&pdx->io_mutex); // Protect disconnect from new i/o - - return iReturn; -} - -/******************************************************************************* -** Get count of characters in the inout buffer. -*******************************************************************************/ -int Stat1401(DEVICE_EXTENSION * pdx) -{ - int iReturn; - mutex_lock(&pdx->io_mutex); // Protect disconnect from new i/o - Allowi(pdx, false); // make sure we allow pending chars - SendChars(pdx); // in both directions - iReturn = pdx->dwNumInput; // no lock as single read - mutex_unlock(&pdx->io_mutex); // Protect disconnect from new i/o - return iReturn; -} - -/**************************************************************************** -** LineCount -** -** Returns the number of newline chars in the buffer. There is no need for -** any fancy interlocks as we only read the interrupt routine data, and the -** system is arranged so nothing can be destroyed. -****************************************************************************/ -int LineCount(DEVICE_EXTENSION * pdx) -{ - int iReturn = 0; // will be count of line ends - - mutex_lock(&pdx->io_mutex); // Protect disconnect from new i/o - Allowi(pdx, false); // Make sure char reads are running - SendChars(pdx); // and send any buffered chars - spin_lock_irq(&pdx->charInLock); // Get protection - - if (pdx->dwNumInput > 0) // worth looking? - { - unsigned int dwIndex = pdx->dwInBuffGet; // start at first available - unsigned int dwEnd = pdx->dwInBuffPut; // Position for search end - do { - if (pdx->inputBuffer[dwIndex++] == CR_CHAR) - ++iReturn; // inc count if CR - - if (dwIndex >= INBUF_SZ) // see if we fall off buff - dwIndex = 0; - } - while (dwIndex != dwEnd); // go to last avaliable - } - - spin_unlock_irq(&pdx->charInLock); - dev_dbg(&pdx->interface->dev, "LineCount returned %d", iReturn); - mutex_unlock(&pdx->io_mutex); // Protect disconnect from new i/o - return iReturn; -} - -/**************************************************************************** -** GetOutBufSpace -** -** Gets the space in the output buffer. Called from user code. -*****************************************************************************/ -int GetOutBufSpace(DEVICE_EXTENSION * pdx) -{ - int iReturn; - mutex_lock(&pdx->io_mutex); // Protect disconnect from new i/o - SendChars(pdx); // send any buffered chars - iReturn = (int)(OUTBUF_SZ - pdx->dwNumOutput); // no lock needed for single read - dev_dbg(&pdx->interface->dev, "OutBufSpace %d", iReturn); - mutex_unlock(&pdx->io_mutex); // Protect disconnect from new i/o - return iReturn; -} - -/**************************************************************************** -** -** ClearArea -** -** Clears up a transfer area. This is always called in the context of a user -** request, never from a call-back. -****************************************************************************/ -int ClearArea(DEVICE_EXTENSION * pdx, int nArea) -{ - int iReturn = U14ERR_NOERROR; - - if ((nArea < 0) || (nArea >= MAX_TRANSAREAS)) { - iReturn = U14ERR_BADAREA; - dev_err(&pdx->interface->dev, "%s Attempt to clear area %d", - __func__, nArea); - } else { - TRANSAREA *pTA = &pdx->rTransDef[nArea]; // to save typing - if (!pTA->bUsed) // if not used... - iReturn = U14ERR_NOTSET; // ...nothing to be done - else { - // We must save the memory we return as we shouldn't mess with memory while - // holding a spin lock. - struct page **pPages = 0; // save page address list - int nPages = 0; // and number of pages - int np; - - dev_dbg(&pdx->interface->dev, "%s area %d", __func__, - nArea); - spin_lock_irq(&pdx->stagedLock); - if ((pdx->StagedId == nArea) - && (pdx->dwDMAFlag > MODE_CHAR)) { - iReturn = U14ERR_UNLOCKFAIL; // cannot delete as in use - dev_err(&pdx->interface->dev, - "%s call on area %d while active", - __func__, nArea); - } else { - pPages = pTA->pPages; // save page address list - nPages = pTA->nPages; // and page count - if (pTA->dwEventSz) // if events flagging in use - wake_up_interruptible(&pTA->wqEvent); // release anything that was waiting - - if (pdx->bXFerWaiting - && (pdx->rDMAInfo.wIdent == nArea)) - pdx->bXFerWaiting = false; // Cannot have pending xfer if area cleared - - // Clean out the TRANSAREA except for the wait queue, which is at the end - // This sets bUsed to false and dwEventSz to 0 to say area not used and no events. - memset(pTA, 0, - sizeof(TRANSAREA) - - sizeof(wait_queue_head_t)); - } - spin_unlock_irq(&pdx->stagedLock); - - if (pPages) // if we decided to release the memory - { - // Now we must undo the pinning down of the pages. We will assume the worst and mark - // all the pages as dirty. Don't be tempted to move this up above as you must not be - // holding a spin lock to do this stuff as it is not atomic. - dev_dbg(&pdx->interface->dev, "%s nPages=%d", - __func__, nPages); - - for (np = 0; np < nPages; ++np) { - if (pPages[np]) { - SetPageDirty(pPages[np]); - page_cache_release(pPages[np]); - } - } - - kfree(pPages); - dev_dbg(&pdx->interface->dev, - "%s kfree(pPages) done", __func__); - } - } - } - - return iReturn; -} - -/**************************************************************************** -** SetArea -** -** Sets up a transfer area - the functional part. Called by both -** SetTransfer and SetCircular. -****************************************************************************/ -static int SetArea(DEVICE_EXTENSION * pdx, int nArea, char __user * puBuf, - unsigned int dwLength, bool bCircular, bool bCircToHost) -{ - // Start by working out the page aligned start of the area and the size - // of the area in pages, allowing for the start not being aligned and the - // end needing to be rounded up to a page boundary. - unsigned long ulStart = ((unsigned long)puBuf) & PAGE_MASK; - unsigned int ulOffset = ((unsigned long)puBuf) & (PAGE_SIZE - 1); - int len = (dwLength + ulOffset + PAGE_SIZE - 1) >> PAGE_SHIFT; - - TRANSAREA *pTA = &pdx->rTransDef[nArea]; // to save typing - struct page **pPages = 0; // space for page tables - int nPages = 0; // and number of pages - - int iReturn = ClearArea(pdx, nArea); // see if OK to use this area - if ((iReturn != U14ERR_NOTSET) && // if not area unused and... - (iReturn != U14ERR_NOERROR)) // ...not all OK, then... - return iReturn; // ...we cannot use this area - - if (!access_ok(VERIFY_WRITE, puBuf, dwLength)) // if we cannot access the memory... - return -EFAULT; // ...then we are done - - // Now allocate space to hold the page pointer and virtual address pointer tables - pPages = - (struct page **)kmalloc(len * sizeof(struct page *), GFP_KERNEL); - if (!pPages) { - iReturn = U14ERR_NOMEMORY; - goto error; - } - dev_dbg(&pdx->interface->dev, "%s %p, length=%06x, circular %d", - __func__, puBuf, dwLength, bCircular); - - // To pin down user pages we must first acquire the mapping semaphore. - down_read(¤t->mm->mmap_sem); // get memory map semaphore - nPages = - get_user_pages(current, current->mm, ulStart, len, 1, 0, pPages, 0); - up_read(¤t->mm->mmap_sem); // release the semaphore - dev_dbg(&pdx->interface->dev, "%s nPages = %d", __func__, nPages); - - if (nPages > 0) // if we succeeded - { - // If you are tempted to use page_address (form LDD3), forget it. You MUST use - // kmap() or kmap_atomic() to get a virtual address. page_address will give you - // (null) or at least it does in this context with an x86 machine. - spin_lock_irq(&pdx->stagedLock); - pTA->lpvBuff = puBuf; // keep start of region (user address) - pTA->dwBaseOffset = ulOffset; // save offset in first page to start of xfer - pTA->dwLength = dwLength; // Size if the region in bytes - pTA->pPages = pPages; // list of pages that are used by buffer - pTA->nPages = nPages; // number of pages - - pTA->bCircular = bCircular; - pTA->bCircToHost = bCircToHost; - - pTA->aBlocks[0].dwOffset = 0; - pTA->aBlocks[0].dwSize = 0; - pTA->aBlocks[1].dwOffset = 0; - pTA->aBlocks[1].dwSize = 0; - pTA->bUsed = true; // This is now a used block - - spin_unlock_irq(&pdx->stagedLock); - iReturn = U14ERR_NOERROR; // say all was well - } else { - iReturn = U14ERR_LOCKFAIL; - goto error; - } - - return iReturn; - -error: - kfree(pPages); - return iReturn; -} - -/**************************************************************************** -** SetTransfer -** -** Sets up a transfer area record. If the area is already set, we attempt to -** unset it. Unsetting will fail if the area is booked, and a transfer to that -** area is in progress. Otherwise, we will release the area and re-assign it. -****************************************************************************/ -int SetTransfer(DEVICE_EXTENSION * pdx, TRANSFERDESC __user * pTD) -{ - int iReturn; - TRANSFERDESC td; - - if (copy_from_user(&td, pTD, sizeof(td))) - return -EFAULT; - - mutex_lock(&pdx->io_mutex); - dev_dbg(&pdx->interface->dev, "%s area:%d, size:%08x", __func__, - td.wAreaNum, td.dwLength); - // The strange cast is done so that we don't get warnings in 32-bit linux about the size of the - // pointer. The pointer is always passed as a 64-bit object so that we don't have problems using - // a 32-bit program on a 64-bit system. unsigned long is 64-bits on a 64-bit system. - iReturn = - SetArea(pdx, td.wAreaNum, - (char __user *)((unsigned long)td.lpvBuff), td.dwLength, - false, false); - mutex_unlock(&pdx->io_mutex); - return iReturn; -} - -/**************************************************************************** -** UnSetTransfer -** Erases a transfer area record -****************************************************************************/ -int UnsetTransfer(DEVICE_EXTENSION * pdx, int nArea) -{ - int iReturn; - mutex_lock(&pdx->io_mutex); - iReturn = ClearArea(pdx, nArea); - mutex_unlock(&pdx->io_mutex); - return iReturn; -} - -/**************************************************************************** -** SetEvent -** Creates an event that we can test for based on a transfer to/from an area. -** The area must be setup for a transfer. We attempt to simulate the Windows -** driver behavior for events (as we don't actually use them), which is to -** pretend that whatever the user asked for was achieved, so we return 1 if -** try to create one, and 0 if they ask to remove (assuming all else was OK). -****************************************************************************/ -int SetEvent(DEVICE_EXTENSION * pdx, TRANSFEREVENT __user * pTE) -{ - int iReturn = U14ERR_NOERROR; - TRANSFEREVENT te; - - // get a local copy of the data - if (copy_from_user(&te, pTE, sizeof(te))) - return -EFAULT; - - if (te.wAreaNum >= MAX_TRANSAREAS) // the area must exist - return U14ERR_BADAREA; - else { - TRANSAREA *pTA = &pdx->rTransDef[te.wAreaNum]; - mutex_lock(&pdx->io_mutex); // make sure we have no competitor - spin_lock_irq(&pdx->stagedLock); - if (pTA->bUsed) // area must be in use - { - pTA->dwEventSt = te.dwStart; // set area regions - pTA->dwEventSz = te.dwLength; // set size (0 cancels it) - pTA->bEventToHost = te.wFlags & 1; // set the direction - pTA->iWakeUp = 0; // zero the wake up count - } else - iReturn = U14ERR_NOTSET; - spin_unlock_irq(&pdx->stagedLock); - mutex_unlock(&pdx->io_mutex); - } - return iReturn == - U14ERR_NOERROR ? (te.iSetEvent ? 1 : U14ERR_NOERROR) : iReturn; -} - -/**************************************************************************** -** WaitEvent -** Sleep the process with a timeout waiting for an event. Returns the number -** of times that a block met the event condition since we last cleared it or -** 0 if timed out, or -ve error (bad area or not set, or signal). -****************************************************************************/ -int WaitEvent(DEVICE_EXTENSION * pdx, int nArea, int msTimeOut) -{ - int iReturn; - if ((unsigned)nArea >= MAX_TRANSAREAS) - return U14ERR_BADAREA; - else { - int iWait; - TRANSAREA *pTA = &pdx->rTransDef[nArea]; - msTimeOut = (msTimeOut * HZ + 999) / 1000; // convert timeout to jiffies - - // We cannot wait holding the mutex, but we check the flags while holding - // it. This may well be pointless as another thread could get in between - // releasing it and the wait call. However, this would have to clear the - // iWakeUp flag. However, the !pTA-bUsed may help us in this case. - mutex_lock(&pdx->io_mutex); // make sure we have no competitor - if (!pTA->bUsed || !pTA->dwEventSz) // check something to wait for... - return U14ERR_NOTSET; // ...else we do nothing - mutex_unlock(&pdx->io_mutex); - - if (msTimeOut) - iWait = - wait_event_interruptible_timeout(pTA->wqEvent, - pTA->iWakeUp - || !pTA->bUsed, - msTimeOut); - else - iWait = - wait_event_interruptible(pTA->wqEvent, pTA->iWakeUp - || !pTA->bUsed); - if (iWait) - iReturn = -ERESTARTSYS; // oops - we have had a SIGNAL - else - iReturn = pTA->iWakeUp; // else the wakeup count - - spin_lock_irq(&pdx->stagedLock); - pTA->iWakeUp = 0; // clear the flag - spin_unlock_irq(&pdx->stagedLock); - } - return iReturn; -} - -/**************************************************************************** -** TestEvent -** Test the event to see if a WaitEvent would return immediately. Returns the -** number of times a block completed since the last call, or 0 if none or a -** negative error. -****************************************************************************/ -int TestEvent(DEVICE_EXTENSION * pdx, int nArea) -{ - int iReturn; - if ((unsigned)nArea >= MAX_TRANSAREAS) - iReturn = U14ERR_BADAREA; - else { - TRANSAREA *pTA = &pdx->rTransDef[nArea]; - mutex_lock(&pdx->io_mutex); // make sure we have no competitor - spin_lock_irq(&pdx->stagedLock); - iReturn = pTA->iWakeUp; // get wakeup count since last call - pTA->iWakeUp = 0; // clear the count - spin_unlock_irq(&pdx->stagedLock); - mutex_unlock(&pdx->io_mutex); - } - return iReturn; -} - -/**************************************************************************** -** GetTransferInfo -** Puts the current state of the 1401 in a TGET_TX_BLOCK. -*****************************************************************************/ -int GetTransfer(DEVICE_EXTENSION * pdx, TGET_TX_BLOCK __user * pTX) -{ - int iReturn = U14ERR_NOERROR; - unsigned int dwIdent; - - mutex_lock(&pdx->io_mutex); - dwIdent = pdx->StagedId; // area ident for last xfer - if (dwIdent >= MAX_TRANSAREAS) - iReturn = U14ERR_BADAREA; - else { - // Return the best information we have - we don't have physical addresses - TGET_TX_BLOCK tx; - memset(&tx, 0, sizeof(tx)); // clean out local work structure - tx.size = pdx->rTransDef[dwIdent].dwLength; - tx.linear = (long long)((long)pdx->rTransDef[dwIdent].lpvBuff); - tx.avail = GET_TX_MAXENTRIES; // how many blocks we could return - tx.used = 1; // number we actually return - tx.entries[0].physical = - (long long)(tx.linear + pdx->StagedOffset); - tx.entries[0].size = tx.size; - - if (copy_to_user(pTX, &tx, sizeof(tx))) - iReturn = -EFAULT; - } - mutex_unlock(&pdx->io_mutex); - return iReturn; -} - -/**************************************************************************** -** KillIO1401 -** -** Empties the host i/o buffers -****************************************************************************/ -int KillIO1401(DEVICE_EXTENSION * pdx) -{ - dev_dbg(&pdx->interface->dev, "%s", __func__); - mutex_lock(&pdx->io_mutex); - FlushOutBuff(pdx); - FlushInBuff(pdx); - mutex_unlock(&pdx->io_mutex); - return U14ERR_NOERROR; -} - -/**************************************************************************** -** BlkTransState -** Returns a 0 or a 1 for whether DMA is happening. No point holding a mutex -** for this as it only does one read. -*****************************************************************************/ -int BlkTransState(DEVICE_EXTENSION * pdx) -{ - int iReturn = pdx->dwDMAFlag != MODE_CHAR; - dev_dbg(&pdx->interface->dev, "%s = %d", __func__, iReturn); - return iReturn; -} - -/**************************************************************************** -** StateOf1401 -** -** Puts the current state of the 1401 in the Irp return buffer. -*****************************************************************************/ -int StateOf1401(DEVICE_EXTENSION * pdx) -{ - int iReturn; - mutex_lock(&pdx->io_mutex); - - QuickCheck(pdx, false, false); // get state up to date, no reset - iReturn = pdx->sCurrentState; - - mutex_unlock(&pdx->io_mutex); - dev_dbg(&pdx->interface->dev, "%s = %d", __func__, iReturn); - - return iReturn; -} - -/**************************************************************************** -** StartSelfTest -** -** Initiates a self-test cycle. The assumption is that we have no interrupts -** active, so we should make sure that this is the case. -*****************************************************************************/ -int StartSelfTest(DEVICE_EXTENSION * pdx) -{ - int nGot; - mutex_lock(&pdx->io_mutex); - dev_dbg(&pdx->interface->dev, "%s", __func__); - - ced_draw_down(pdx); // wait for, then kill outstanding Urbs - FlushInBuff(pdx); // Clear out input buffer & pipe - FlushOutBuff(pdx); // Clear output buffer & pipe -// ReadWrite_Cancel(pDeviceObject); /* so things stay tidy */ - pdx->dwDMAFlag = MODE_CHAR; /* Clear DMA mode flags here */ - - nGot = usb_control_msg(pdx->udev, usb_rcvctrlpipe(pdx->udev, 0), DB_SELFTEST, (H_TO_D | VENDOR | DEVREQ), 0, 0, 0, 0, HZ); // allow 1 second timeout - pdx->ulSelfTestTime = jiffies + HZ * 30; // 30 seconds into the future - - mutex_unlock(&pdx->io_mutex); - if (nGot < 0) - dev_err(&pdx->interface->dev, "%s err=%d", __func__, nGot); - return nGot < 0 ? U14ERR_FAIL : U14ERR_NOERROR; -} - -/**************************************************************************** -** CheckSelfTest -** -** Check progress of a self-test cycle -****************************************************************************/ -int CheckSelfTest(DEVICE_EXTENSION * pdx, TGET_SELFTEST __user * pGST) -{ - unsigned int state, error; - int iReturn; - TGET_SELFTEST gst; // local work space - memset(&gst, 0, sizeof(gst)); // clear out the space (sets code 0) - - mutex_lock(&pdx->io_mutex); - - dev_dbg(&pdx->interface->dev, "%s", __func__); - iReturn = Get1401State(pdx, &state, &error); - if (iReturn == U14ERR_NOERROR) // Only accept zero if it happens twice - iReturn = Get1401State(pdx, &state, &error); - - if (iReturn != U14ERR_NOERROR) // Self-test can cause comms errors - { // so we assume still testing - dev_err(&pdx->interface->dev, - "%s Get1401State=%d, assuming still testing", __func__, - iReturn); - state = 0x80; // Force still-testing, no error - error = 0; - iReturn = U14ERR_NOERROR; - } - - if ((state == -1) && (error == -1)) // If Get1401State had problems - { - dev_err(&pdx->interface->dev, - "%s Get1401State failed, assuming still testing", - __func__); - state = 0x80; // Force still-testing, no error - error = 0; - } - - if ((state & 0xFF) == 0x80) // If we are still in self-test - { - if (state & 0x00FF0000) // Have we got an error? - { - gst.code = (state & 0x00FF0000) >> 16; // read the error code - gst.x = error & 0x0000FFFF; // Error data X - gst.y = (error & 0xFFFF0000) >> 16; // and data Y - dev_dbg(&pdx->interface->dev, "Self-test error code %d", - gst.code); - } else // No error, check for timeout - { - unsigned long ulNow = jiffies; // get current time - if (time_after(ulNow, pdx->ulSelfTestTime)) { - gst.code = -2; // Flag the timeout - dev_dbg(&pdx->interface->dev, - "Self-test timed-out"); - } else - dev_dbg(&pdx->interface->dev, - "Self-test on-going"); - } - } else { - gst.code = -1; // Flag the test is done - dev_dbg(&pdx->interface->dev, "Self-test done"); - } - - if (gst.code < 0) // If we have a problem or finished - { // If using the 2890 we should reset properly - if ((pdx->nPipes == 4) && (pdx->s1401Type <= TYPEPOWER)) - Is1401(pdx); // Get 1401 reset and OK - else - QuickCheck(pdx, true, true); // Otherwise check without reset unless problems - } - mutex_unlock(&pdx->io_mutex); - - if (copy_to_user(pGST, &gst, sizeof(gst))) - return -EFAULT; - - return iReturn; -} - -/**************************************************************************** -** TypeOf1401 -** -** Returns code for standard, plus, micro1401, power1401 or none -****************************************************************************/ -int TypeOf1401(DEVICE_EXTENSION * pdx) -{ - int iReturn = TYPEUNKNOWN; - mutex_lock(&pdx->io_mutex); - dev_dbg(&pdx->interface->dev, "%s", __func__); - - switch (pdx->s1401Type) { - case TYPE1401: - iReturn = U14ERR_STD; - break; // Handle these types directly - case TYPEPLUS: - iReturn = U14ERR_PLUS; - break; - case TYPEU1401: - iReturn = U14ERR_U1401; - break; - default: - if ((pdx->s1401Type >= TYPEPOWER) && (pdx->s1401Type <= 25)) - iReturn = pdx->s1401Type + 4; // We can calculate types - else // for up-coming 1401 designs - iReturn = TYPEUNKNOWN; // Don't know or not there - } - dev_dbg(&pdx->interface->dev, "%s %d", __func__, iReturn); - mutex_unlock(&pdx->io_mutex); - - return iReturn; -} - -/**************************************************************************** -** TransferFlags -** -** Returns flags on block transfer abilities -****************************************************************************/ -int TransferFlags(DEVICE_EXTENSION * pdx) -{ - int iReturn = U14TF_MULTIA | U14TF_DIAG | // we always have multiple DMA area - U14TF_NOTIFY | U14TF_CIRCTH; // diagnostics, notify and circular - dev_dbg(&pdx->interface->dev, "%s", __func__); - mutex_lock(&pdx->io_mutex); - if (pdx->bIsUSB2) // Set flag for USB2 if appropriate - iReturn |= U14TF_USB2; - mutex_unlock(&pdx->io_mutex); - - return iReturn; -} - -/*************************************************************************** -** DbgCmd1401 -** Issues a debug\diagnostic command to the 1401 along with a 32-bit datum -** This is a utility command used for dbg operations. -*/ -static int DbgCmd1401(DEVICE_EXTENSION * pdx, unsigned char cmd, - unsigned int data) -{ - int iReturn; - dev_dbg(&pdx->interface->dev, "%s entry", __func__); - iReturn = usb_control_msg(pdx->udev, usb_sndctrlpipe(pdx->udev, 0), cmd, (H_TO_D | VENDOR | DEVREQ), (unsigned short)data, (unsigned short)(data >> 16), 0, 0, HZ); // allow 1 second timeout - if (iReturn < 0) - dev_err(&pdx->interface->dev, "%s fail code=%d", __func__, - iReturn); - - return iReturn; -} - -/**************************************************************************** -** DbgPeek -** -** Execute the diagnostic peek operation. Uses address, width and repeats. -****************************************************************************/ -int DbgPeek(DEVICE_EXTENSION * pdx, TDBGBLOCK __user * pDB) -{ - int iReturn; - TDBGBLOCK db; - - if (copy_from_user(&db, pDB, sizeof(db))) - return -EFAULT; - - mutex_lock(&pdx->io_mutex); - dev_dbg(&pdx->interface->dev, "%s @ %08x", __func__, db.iAddr); - - iReturn = DbgCmd1401(pdx, DB_SETADD, db.iAddr); - if (iReturn == U14ERR_NOERROR) - iReturn = DbgCmd1401(pdx, DB_WIDTH, db.iWidth); - if (iReturn == U14ERR_NOERROR) - iReturn = DbgCmd1401(pdx, DB_REPEATS, db.iRepeats); - if (iReturn == U14ERR_NOERROR) - iReturn = DbgCmd1401(pdx, DB_PEEK, 0); - mutex_unlock(&pdx->io_mutex); - - return iReturn; -} - -/**************************************************************************** -** DbgPoke -** -** Execute the diagnostic poke operation. Parameters are in the CSBLOCK struct -** in order address, size, repeats and value to poke. -****************************************************************************/ -int DbgPoke(DEVICE_EXTENSION * pdx, TDBGBLOCK __user * pDB) -{ - int iReturn; - TDBGBLOCK db; - - if (copy_from_user(&db, pDB, sizeof(db))) - return -EFAULT; - - mutex_lock(&pdx->io_mutex); - dev_dbg(&pdx->interface->dev, "%s @ %08x", __func__, db.iAddr); - - iReturn = DbgCmd1401(pdx, DB_SETADD, db.iAddr); - if (iReturn == U14ERR_NOERROR) - iReturn = DbgCmd1401(pdx, DB_WIDTH, db.iWidth); - if (iReturn == U14ERR_NOERROR) - iReturn = DbgCmd1401(pdx, DB_REPEATS, db.iRepeats); - if (iReturn == U14ERR_NOERROR) - iReturn = DbgCmd1401(pdx, DB_POKE, db.iData); - mutex_unlock(&pdx->io_mutex); - - return iReturn; -} - -/**************************************************************************** -** DbgRampData -** -** Execute the diagnostic ramp data operation. Parameters are in the CSBLOCK struct -** in order address, default, enable mask, size and repeats. -****************************************************************************/ -int DbgRampData(DEVICE_EXTENSION * pdx, TDBGBLOCK __user * pDB) -{ - int iReturn; - TDBGBLOCK db; - - if (copy_from_user(&db, pDB, sizeof(db))) - return -EFAULT; - - mutex_lock(&pdx->io_mutex); - dev_dbg(&pdx->interface->dev, "%s @ %08x", __func__, db.iAddr); - - iReturn = DbgCmd1401(pdx, DB_SETADD, db.iAddr); - if (iReturn == U14ERR_NOERROR) - iReturn = DbgCmd1401(pdx, DB_SETDEF, db.iDefault); - if (iReturn == U14ERR_NOERROR) - iReturn = DbgCmd1401(pdx, DB_SETMASK, db.iMask); - if (iReturn == U14ERR_NOERROR) - iReturn = DbgCmd1401(pdx, DB_WIDTH, db.iWidth); - if (iReturn == U14ERR_NOERROR) - iReturn = DbgCmd1401(pdx, DB_REPEATS, db.iRepeats); - if (iReturn == U14ERR_NOERROR) - iReturn = DbgCmd1401(pdx, DB_RAMPD, 0); - mutex_unlock(&pdx->io_mutex); - - return iReturn; -} - -/**************************************************************************** -** DbgRampAddr -** -** Execute the diagnostic ramp address operation -****************************************************************************/ -int DbgRampAddr(DEVICE_EXTENSION * pdx, TDBGBLOCK __user * pDB) -{ - int iReturn; - TDBGBLOCK db; - - if (copy_from_user(&db, pDB, sizeof(db))) - return -EFAULT; - - mutex_lock(&pdx->io_mutex); - dev_dbg(&pdx->interface->dev, "%s", __func__); - - iReturn = DbgCmd1401(pdx, DB_SETDEF, db.iDefault); - if (iReturn == U14ERR_NOERROR) - iReturn = DbgCmd1401(pdx, DB_SETMASK, db.iMask); - if (iReturn == U14ERR_NOERROR) - iReturn = DbgCmd1401(pdx, DB_WIDTH, db.iWidth); - if (iReturn == U14ERR_NOERROR) - iReturn = DbgCmd1401(pdx, DB_REPEATS, db.iRepeats); - if (iReturn == U14ERR_NOERROR) - iReturn = DbgCmd1401(pdx, DB_RAMPA, 0); - mutex_unlock(&pdx->io_mutex); - - return iReturn; -} - -/**************************************************************************** -** DbgGetData -** -** Retrieve the data resulting from the last debug Peek operation -****************************************************************************/ -int DbgGetData(DEVICE_EXTENSION * pdx, TDBGBLOCK __user * pDB) -{ - int iReturn; - TDBGBLOCK db; - memset(&db, 0, sizeof(db)); // fill returned block with 0s - - mutex_lock(&pdx->io_mutex); - dev_dbg(&pdx->interface->dev, "%s", __func__); - - // Read back the last peeked value from the 1401. - iReturn = usb_control_msg(pdx->udev, usb_rcvctrlpipe(pdx->udev, 0), - DB_DATA, (D_TO_H | VENDOR | DEVREQ), 0, 0, - &db.iData, sizeof(db.iData), HZ); - if (iReturn == sizeof(db.iData)) { - if (copy_to_user(pDB, &db, sizeof(db))) - iReturn = -EFAULT; - else - iReturn = U14ERR_NOERROR; - } else - dev_err(&pdx->interface->dev, "%s failed, code %d", __func__, - iReturn); - - mutex_unlock(&pdx->io_mutex); - - return iReturn; -} - -/**************************************************************************** -** DbgStopLoop -** -** Stop any never-ending debug loop, we just call Get1401State for USB -** -****************************************************************************/ -int DbgStopLoop(DEVICE_EXTENSION * pdx) -{ - int iReturn; - unsigned int uState, uErr; - - mutex_lock(&pdx->io_mutex); - dev_dbg(&pdx->interface->dev, "%s", __func__); - iReturn = Get1401State(pdx, &uState, &uErr); - mutex_unlock(&pdx->io_mutex); - - return iReturn; -} - -/**************************************************************************** -** SetCircular -** -** Sets up a transfer area record for circular transfers. If the area is -** already set, we attempt to unset it. Unsetting will fail if the area is -** booked and a transfer to that area is in progress. Otherwise, we will -** release the area and re-assign it. -****************************************************************************/ -int SetCircular(DEVICE_EXTENSION * pdx, TRANSFERDESC __user * pTD) -{ - int iReturn; - bool bToHost; - TRANSFERDESC td; - - if (copy_from_user(&td, pTD, sizeof(td))) - return -EFAULT; - - mutex_lock(&pdx->io_mutex); - dev_dbg(&pdx->interface->dev, "%s area:%d, size:%08x", __func__, - td.wAreaNum, td.dwLength); - bToHost = td.eSize != 0; // this is used as the tohost flag - - // The strange cast is done so that we don't get warnings in 32-bit linux about the size of the - // pointer. The pointer is always passed as a 64-bit object so that we don't have problems using - // a 32-bit program on a 64-bit system. unsigned long is 64-bits on a 64-bit system. - iReturn = - SetArea(pdx, td.wAreaNum, - (char __user *)((unsigned long)td.lpvBuff), td.dwLength, - true, bToHost); - mutex_unlock(&pdx->io_mutex); - return iReturn; -} - -/**************************************************************************** -** GetCircBlock -** -** Return the next available block of circularly-transferred data. -****************************************************************************/ -int GetCircBlock(DEVICE_EXTENSION * pdx, TCIRCBLOCK __user * pCB) -{ - int iReturn = U14ERR_NOERROR; - unsigned int nArea; - TCIRCBLOCK cb; - - dev_dbg(&pdx->interface->dev, "%s", __func__); - - if (copy_from_user(&cb, pCB, sizeof(cb))) - return -EFAULT; - - mutex_lock(&pdx->io_mutex); - - nArea = cb.nArea; // Retrieve parameters first - cb.dwOffset = 0; // set default result (nothing) - cb.dwSize = 0; - - if (nArea < MAX_TRANSAREAS) // The area number must be OK - { - TRANSAREA *pArea = &pdx->rTransDef[nArea]; // Pointer to relevant info - spin_lock_irq(&pdx->stagedLock); // Lock others out - - if ((pArea->bUsed) && (pArea->bCircular) && // Must be circular area - (pArea->bCircToHost)) // For now at least must be to host - { - if (pArea->aBlocks[0].dwSize > 0) // Got anything? - { - cb.dwOffset = pArea->aBlocks[0].dwOffset; - cb.dwSize = pArea->aBlocks[0].dwSize; - dev_dbg(&pdx->interface->dev, - "%s return block 0: %d bytes at %d", - __func__, cb.dwSize, cb.dwOffset); - } - } else - iReturn = U14ERR_NOTSET; - - spin_unlock_irq(&pdx->stagedLock); - } else - iReturn = U14ERR_BADAREA; - - if (copy_to_user(pCB, &cb, sizeof(cb))) - iReturn = -EFAULT; - - mutex_unlock(&pdx->io_mutex); - return iReturn; -} - -/**************************************************************************** -** FreeCircBlock -** -** Frees a block of circularly-transferred data and returns the next one. -****************************************************************************/ -int FreeCircBlock(DEVICE_EXTENSION * pdx, TCIRCBLOCK __user * pCB) -{ - int iReturn = U14ERR_NOERROR; - unsigned int nArea, uStart, uSize; - TCIRCBLOCK cb; - - dev_dbg(&pdx->interface->dev, "%s", __func__); - - if (copy_from_user(&cb, pCB, sizeof(cb))) - return -EFAULT; - - mutex_lock(&pdx->io_mutex); - - nArea = cb.nArea; // Retrieve parameters first - uStart = cb.dwOffset; - uSize = cb.dwSize; - cb.dwOffset = 0; // then set default result (nothing) - cb.dwSize = 0; - - if (nArea < MAX_TRANSAREAS) // The area number must be OK - { - TRANSAREA *pArea = &pdx->rTransDef[nArea]; // Pointer to relevant info - spin_lock_irq(&pdx->stagedLock); // Lock others out - - if ((pArea->bUsed) && (pArea->bCircular) && // Must be circular area - (pArea->bCircToHost)) // For now at least must be to host - { - bool bWaiting = false; - - if ((pArea->aBlocks[0].dwSize >= uSize) && // Got anything? - (pArea->aBlocks[0].dwOffset == uStart)) // Must be legal data - { - pArea->aBlocks[0].dwSize -= uSize; - pArea->aBlocks[0].dwOffset += uSize; - if (pArea->aBlocks[0].dwSize == 0) // Have we emptied this block? - { - if (pArea->aBlocks[1].dwSize) // Is there a second block? - { - pArea->aBlocks[0] = pArea->aBlocks[1]; // Copy down block 2 data - pArea->aBlocks[1].dwSize = 0; // and mark the second block as unused - pArea->aBlocks[1].dwOffset = 0; - } else - pArea->aBlocks[0].dwOffset = 0; - } - - dev_dbg(&pdx->interface->dev, - "%s free %d bytes at %d, return %d bytes at %d, wait=%d", - __func__, uSize, uStart, - pArea->aBlocks[0].dwSize, - pArea->aBlocks[0].dwOffset, - pdx->bXFerWaiting); - - // Return the next available block of memory as well - if (pArea->aBlocks[0].dwSize > 0) // Got anything? - { - cb.dwOffset = - pArea->aBlocks[0].dwOffset; - cb.dwSize = pArea->aBlocks[0].dwSize; - } - - bWaiting = pdx->bXFerWaiting; - if (bWaiting && pdx->bStagedUrbPending) { - dev_err(&pdx->interface->dev, - "%s ERROR: waiting xfer and staged Urb pending!", - __func__); - bWaiting = false; - } - } else { - dev_err(&pdx->interface->dev, - "%s ERROR: freeing %d bytes at %d, block 0 is %d bytes at %d", - __func__, uSize, uStart, - pArea->aBlocks[0].dwSize, - pArea->aBlocks[0].dwOffset); - iReturn = U14ERR_NOMEMORY; - } - - // If we have one, kick off pending transfer - if (bWaiting) // Got a block xfer waiting? - { - int RWMStat = - ReadWriteMem(pdx, !pdx->rDMAInfo.bOutWard, - pdx->rDMAInfo.wIdent, - pdx->rDMAInfo.dwOffset, - pdx->rDMAInfo.dwSize); - if (RWMStat != U14ERR_NOERROR) - dev_err(&pdx->interface->dev, - "%s rw setup failed %d", - __func__, RWMStat); - } - } else - iReturn = U14ERR_NOTSET; - - spin_unlock_irq(&pdx->stagedLock); - } else - iReturn = U14ERR_BADAREA; - - if (copy_to_user(pCB, &cb, sizeof(cb))) - return -EFAULT; - - mutex_unlock(&pdx->io_mutex); - return iReturn; -} diff --git a/trunk/drivers/staging/ced1401/ced_ioctl.h b/trunk/drivers/staging/ced1401/ced_ioctl.h deleted file mode 100644 index 0895c9414b4f..000000000000 --- a/trunk/drivers/staging/ced1401/ced_ioctl.h +++ /dev/null @@ -1,345 +0,0 @@ -/* - * IOCTL calls for the CED1401 driver - * Copyright (C) 2010 Cambridge Electronic Design Ltd - * Author Greg P Smith (greg@ced.co.uk) - * - * 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. - */ -#ifndef __CED_IOCTL_H__ -#define __CED_IOCTL_H__ - -#include - -/* dma modes, only MODE_CHAR and MODE_LINEAR are used in this driver */ -#define MODE_CHAR 0 -#define MODE_LINEAR 1 - -/**************************************************************************** -** TypeDefs -*****************************************************************************/ - -typedef unsigned short TBLOCKENTRY; /* index the blk transfer table 0-7 */ - -typedef struct TransferDesc { - long long lpvBuff; /* address of transfer area (for 64 or 32 bit) */ - unsigned int dwLength; /* length of the area */ - TBLOCKENTRY wAreaNum; /* number of transfer area to set up */ - short eSize; /* element size - is tohost flag for circular */ -} TRANSFERDESC; - -typedef TRANSFERDESC * LPTRANSFERDESC; - -typedef struct TransferEvent { - unsigned int dwStart; /* offset into the area */ - unsigned int dwLength; /* length of the region */ - unsigned short wAreaNum; /* the area number */ - unsigned short wFlags; /* bit 0 set for toHost */ - int iSetEvent; /* could be dummy in LINUX */ -} TRANSFEREVENT; - -#define MAX_TRANSFER_SIZE 0x4000 /* Maximum data bytes per IRP */ -#define MAX_AREA_LENGTH 0x100000 /* Maximum size of transfer area */ -#define MAX_TRANSAREAS 8 /* definitions for dma set up */ - -typedef struct TGetSelfTest { - int code; /* self-test error code */ - int x, y; /* additional information */ -} TGET_SELFTEST; - -/* Debug block used for several commands. Not all fields are used for all commands. */ -typedef struct TDbgBlock { - int iAddr; /* the address in the 1401 */ - int iRepeats; /* number of repeats */ - int iWidth; /* width in bytes 1, 2, 4 */ - int iDefault; /* default value */ - int iMask; /* mask to apply */ - int iData; /* data for poke, result for peek */ -} TDBGBLOCK; - -/* Used to collect information about a circular block from the device driver */ -typedef struct TCircBlock { - unsigned int nArea; /* the area to collect information from */ - unsigned int dwOffset; /* offset into the area to the available block */ - unsigned int dwSize; /* size of the area */ -} TCIRCBLOCK; - -/* Used to clollect the 1401 status */ -typedef struct TCSBlock { - unsigned int uiState; - unsigned int uiError; -} TCSBLOCK; - -/* - * As seen by the user, an ioctl call looks like: int ioctl(int fd, unsigned - * long cmd, char* argp); We will then have all sorts of variants on this that - * can be used to pass stuff to our driver. We will generate macros for each - * type of call so as to provide some sort of type safety in the calling: - */ -#define CED_MAGIC_IOC 0xce - -/* NBNB: READ and WRITE are from the point of view of the device, not user. */ -typedef struct ced_ioc_string { - int nChars; - char buffer[256]; -} CED_IOC_STRING; - -#define IOCTL_CED_SENDSTRING(n) _IOC(_IOC_WRITE, CED_MAGIC_IOC, 2, n) - -#define IOCTL_CED_RESET1401 _IO(CED_MAGIC_IOC, 3) -#define IOCTL_CED_GETCHAR _IO(CED_MAGIC_IOC, 4) -#define IOCTL_CED_SENDCHAR _IO(CED_MAGIC_IOC, 5) -#define IOCTL_CED_STAT1401 _IO(CED_MAGIC_IOC, 6) -#define IOCTL_CED_LINECOUNT _IO(CED_MAGIC_IOC, 7) -#define IOCTL_CED_GETSTRING(nMax) _IOC(_IOC_READ, CED_MAGIC_IOC, 8, nMax) - -#define IOCTL_CED_SETTRANSFER _IOW(CED_MAGIC_IOC, 11, TRANSFERDESC) -#define IOCTL_CED_UNSETTRANSFER _IO(CED_MAGIC_IOC, 12) -#define IOCTL_CED_SETEVENT _IOW(CED_MAGIC_IOC, 13, TRANSFEREVENT) -#define IOCTL_CED_GETOUTBUFSPACE _IO(CED_MAGIC_IOC, 14) -#define IOCTL_CED_GETBASEADDRESS _IO(CED_MAGIC_IOC, 15) -#define IOCTL_CED_GETDRIVERREVISION _IO(CED_MAGIC_IOC, 16) - -#define IOCTL_CED_GETTRANSFER _IOR(CED_MAGIC_IOC, 17, TGET_TX_BLOCK) -#define IOCTL_CED_KILLIO1401 _IO(CED_MAGIC_IOC, 18) -#define IOCTL_CED_BLKTRANSSTATE _IO(CED_MAGIC_IOC, 19) - -#define IOCTL_CED_STATEOF1401 _IO(CED_MAGIC_IOC, 23) -#define IOCTL_CED_GRAB1401 _IO(CED_MAGIC_IOC, 25) -#define IOCTL_CED_FREE1401 _IO(CED_MAGIC_IOC, 26) -#define IOCTL_CED_STARTSELFTEST _IO(CED_MAGIC_IOC, 31) -#define IOCTL_CED_CHECKSELFTEST _IOR(CED_MAGIC_IOC, 32, TGET_SELFTEST) -#define IOCTL_CED_TYPEOF1401 _IO(CED_MAGIC_IOC, 33) -#define IOCTL_CED_TRANSFERFLAGS _IO(CED_MAGIC_IOC, 34) - -#define IOCTL_CED_DBGPEEK _IOW(CED_MAGIC_IOC, 35, TDBGBLOCK) -#define IOCTL_CED_DBGPOKE _IOW(CED_MAGIC_IOC, 36, TDBGBLOCK) -#define IOCTL_CED_DBGRAMPDATA _IOW(CED_MAGIC_IOC, 37, TDBGBLOCK) -#define IOCTL_CED_DBGRAMPADDR _IOW(CED_MAGIC_IOC, 38, TDBGBLOCK) -#define IOCTL_CED_DBGGETDATA _IOR(CED_MAGIC_IOC, 39, TDBGBLOCK) -#define IOCTL_CED_DBGSTOPLOOP _IO(CED_MAGIC_IOC, 40) -#define IOCTL_CED_FULLRESET _IO(CED_MAGIC_IOC, 41) -#define IOCTL_CED_SETCIRCULAR _IOW(CED_MAGIC_IOC, 42, TRANSFERDESC) -#define IOCTL_CED_GETCIRCBLOCK _IOWR(CED_MAGIC_IOC, 43, TCIRCBLOCK) -#define IOCTL_CED_FREECIRCBLOCK _IOWR(CED_MAGIC_IOC, 44, TCIRCBLOCK) -#define IOCTL_CED_WAITEVENT _IO(CED_MAGIC_IOC, 45) -#define IOCTL_CED_TESTEVENT _IO(CED_MAGIC_IOC, 46) - -#ifndef __KERNEL__ -/* - * If nothing said about return value, it is a U14ERR_... error code - * (U14ERR_NOERROR for none) - */ -inline int CED_SendString(int fh, const char *szText, int n) -{ - return ioctl(fh, IOCTL_CED_SENDSTRING(n), szText); -} - -inline int CED_Reset1401(int fh) -{ - return ioctl(fh, IOCTL_CED_RESET1401); -} - -/* Return the singe character or a -ve error code. */ -inline int CED_GetChar(int fh) -{ - return ioctl(fh, IOCTL_CED_GETCHAR); -} - -/* Return character count in input buffer */ -inline int CED_Stat1401(int fh) -{ - return ioctl(fh, IOCTL_CED_STAT1401); -} - -inline int CED_SendChar(int fh, char c) -{ - return ioctl(fh, IOCTL_CED_SENDCHAR, c); -} - -inline int CED_LineCount(int fh) -{ - return ioctl(fh, IOCTL_CED_LINECOUNT); -} - -/* - * return the count of characters returned. If the string was terminated by CR - * or 0, then the 0 is part of the count. Otherwise, we will add a zero if - * there is room, but it is not included in the count. The return value is 0 - * if there was nothing to read. - */ -inline int CED_GetString(int fh, char *szText, int nMax) -{ - return ioctl(fh, IOCTL_CED_GETSTRING(nMax), szText); -} - -/* returns space in the output buffer. */ -inline int CED_GetOutBufSpace(int fh) -{ - return ioctl(fh, IOCTL_CED_GETOUTBUFSPACE); -} - -/* This always returns -1 as not implemented. */ -inline int CED_GetBaseAddress(int fh) -{ - return ioctl(fh, IOCTL_CED_GETBASEADDRESS); -} - -/* returns the major revision <<16 | minor revision. */ -inline int CED_GetDriverRevision(int fh) -{ - return ioctl(fh, IOCTL_CED_GETDRIVERREVISION); -} - -inline int CED_SetTransfer(int fh, TRANSFERDESC *pTD) -{ - return ioctl(fh, IOCTL_CED_SETTRANSFER, pTD); -} - -inline int CED_UnsetTransfer(int fh, int nArea) -{ - return ioctl(fh, IOCTL_CED_UNSETTRANSFER, nArea); -} - -inline int CED_SetEvent(int fh, TRANSFEREVENT *pTE) -{ - return ioctl(fh, IOCTL_CED_SETEVENT, pTE); -} - -inline int CED_GetTransfer(int fh, TGET_TX_BLOCK *pTX) -{ - return ioctl(fh, IOCTL_CED_GETTRANSFER, pTX); -} - -inline int CED_KillIO1401(int fh) -{ - return ioctl(fh, IOCTL_CED_KILLIO1401); -} - -/* returns 0 if no active DMA, 1 if active */ -inline int CED_BlkTransState(int fh) -{ - return ioctl(fh, IOCTL_CED_BLKTRANSSTATE); -} - -inline int CED_StateOf1401(int fh) -{ - return ioctl(fh, IOCTL_CED_STATEOF1401); -} - -inline int CED_Grab1401(int fh) -{ - return ioctl(fh, IOCTL_CED_GRAB1401); -} - -inline int CED_Free1401(int fh) -{ - return ioctl(fh, IOCTL_CED_FREE1401); -} - -inline int CED_StartSelfTest(int fh) -{ - return ioctl(fh, IOCTL_CED_STARTSELFTEST); -} - -inline int CED_CheckSelfTest(int fh, TGET_SELFTEST *pGST) -{ - return ioctl(fh, IOCTL_CED_CHECKSELFTEST, pGST); -} - -inline int CED_TypeOf1401(int fh) -{ - return ioctl(fh, IOCTL_CED_TYPEOF1401); -} - -inline int CED_TransferFlags(int fh) -{ - return ioctl(fh, IOCTL_CED_TRANSFERFLAGS); -} - -inline int CED_DbgPeek(int fh, TDBGBLOCK *pDB) -{ - return ioctl(fh, IOCTL_CED_DBGPEEK, pDB); -} - -inline int CED_DbgPoke(int fh, TDBGBLOCK *pDB) -{ - return ioctl(fh, IOCTL_CED_DBGPOKE, pDB); -} - -inline int CED_DbgRampData(int fh, TDBGBLOCK *pDB) -{ - return ioctl(fh, IOCTL_CED_DBGRAMPDATA, pDB); -} - -inline int CED_DbgRampAddr(int fh, TDBGBLOCK *pDB) -{ - return ioctl(fh, IOCTL_CED_DBGRAMPADDR, pDB); -} - -inline int CED_DbgGetData(int fh, TDBGBLOCK *pDB) -{ - return ioctl(fh, IOCTL_CED_DBGGETDATA, pDB); -} - -inline int CED_DbgStopLoop(int fh) -{ - return ioctl(fh, IOCTL_CED_DBGSTOPLOOP); -} - -inline int CED_FullReset(int fh) -{ - return ioctl(fh, IOCTL_CED_FULLRESET); -} - -inline int CED_SetCircular(int fh, TRANSFERDESC *pTD) -{ - return ioctl(fh, IOCTL_CED_SETCIRCULAR, pTD); -} - -inline int CED_GetCircBlock(int fh, TCIRCBLOCK *pCB) -{ - return ioctl(fh, IOCTL_CED_GETCIRCBLOCK, pCB); -} - -inline int CED_FreeCircBlock(int fh, TCIRCBLOCK *pCB) -{ - return ioctl(fh, IOCTL_CED_FREECIRCBLOCK, pCB); -} - -inline int CED_WaitEvent(int fh, int nArea, int msTimeOut) -{ - return ioctl(fh, IOCTL_CED_WAITEVENT, (nArea & 0xff)|(msTimeOut << 8)); -} - -inline int CED_TestEvent(int fh, int nArea) -{ - return ioctl(fh, IOCTL_CED_TESTEVENT, nArea); -} -#endif - -#ifdef NOTWANTEDYET -#define IOCTL_CED_REGCALLBACK _IO(CED_MAGIC_IOC, 9) /* Not used */ -#define IOCTL_CED_GETMONITORBUF _IO(CED_MAGIC_IOC, 10) /* Not used */ - -#define IOCTL_CED_BYTECOUNT _IO(CED_MAGIC_IOC, 20) /* Not used */ -#define IOCTL_CED_ZEROBLOCKCOUNT _IO(CED_MAGIC_IOC, 21) /* Not used */ -#define IOCTL_CED_STOPCIRCULAR _IO(CED_MAGIC_IOC, 22) /* Not used */ - -#define IOCTL_CED_REGISTERS1401 _IO(CED_MAGIC_IOC, 24) /* Not used */ -#define IOCTL_CED_STEP1401 _IO(CED_MAGIC_IOC, 27) /* Not used */ -#define IOCTL_CED_SET1401REGISTERS _IO(CED_MAGIC_IOC, 28) /* Not used */ -#define IOCTL_CED_STEPTILL1401 _IO(CED_MAGIC_IOC, 29) /* Not used */ -#define IOCTL_CED_SETORIN _IO(CED_MAGIC_IOC, 30) /* Not used */ - -#endif - -/* __CED_IOCTL_H__ */ -#endif diff --git a/trunk/drivers/staging/ced1401/machine.h b/trunk/drivers/staging/ced1401/machine.h deleted file mode 100644 index af073790b942..000000000000 --- a/trunk/drivers/staging/ced1401/machine.h +++ /dev/null @@ -1,127 +0,0 @@ -/***************************************************************************** -** -** machine.h -** -** Copyright (c) Cambridge Electronic Design Limited 1991,1992,2010 -** -** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -** -** Contact CED: Cambridge Electronic Design Limited, Science Park, Milton Road -** Cambridge, CB6 0FE. -** www.ced.co.uk -** greg@ced.co.uk -** -** This file is included at the start of 'C' or 'C++' source file to define -** things for cross-platform/compiler interoperability. This used to deal with -** MSDOS/16-bit stuff, but this was all removed in Decemeber 2010. There are -** three things to consider: Windows, LINUX, mac OSX (BSD Unix) and 32 vs 64 -** bit. At the time of writing (DEC 2010) there is a consensus on the following -** and their unsigned equivalents: -** -** type bits -** char 8 -** short 16 -** int 32 -** long long 64 -** -** long is a problem as it is always 64 bits on linux/unix and is always 32 bits -** on windows. -** On windows, we define _IS_WINDOWS_ and one of WIN32 or WIN64. -** On linux we define LINUX -** On Max OSX we define MACOSX -** -*/ - -#ifndef __MACHINE_H__ -#define __MACHINE_H__ -#ifndef __KERNEL__ -#include -#include -#endif - -/* -** The initial section is to identify the operating system -*/ -#if (defined(__linux__) || defined(_linux) || defined(__linux)) && !defined(LINUX) -#define LINUX 1 -#endif - -#if (defined(__WIN32__) || defined(_WIN32)) && !defined(WIN32) -#define WIN32 1 -#endif - -#if defined(__APPLE__) -#define MACOSX -#endif - -#if defined(_WIN64) -#undef WIN32 -#undef WIN64 -#define WIN64 1 -#endif - -#if defined(WIN32) || defined(WIN64) -#define _IS_WINDOWS_ 1 -#endif - -#if defined(LINUX) || defined(MAXOSX) - #define FAR - - typedef int BOOL; // To match Windows - typedef char * LPSTR; - typedef const char * LPCSTR; - typedef unsigned short WORD; - typedef unsigned int DWORD; - typedef unsigned char BYTE; - typedef BYTE BOOLEAN; - typedef unsigned char UCHAR; - #define __packed __attribute__((packed)) - typedef BYTE * LPBYTE; - #define HIWORD(x) (WORD)(((x)>>16) & 0xffff) - #define LOWORD(x) (WORD)((x) & 0xffff) -#endif - -#ifdef _IS_WINDOWS_ -#include -#define __packed -#endif - -/* -** Sort out the DllExport and DllImport macros. The GCC compiler has its own -** syntax for this, though it also supports the MS specific __declspec() as -** a synonym. -*/ -#ifdef GNUC - #define DllExport __attribute__((dllexport)) - #define DllImport __attribute__((dllimport)) -#endif - -#ifndef DllExport -#ifdef _IS_WINDOWS_ - #define DllExport __declspec(dllexport) - #define DllImport __declspec(dllimport) -#else - #define DllExport - #define DllImport -#endif -#endif /* _IS_WINDOWS_ */ - - -#ifndef TRUE - #define TRUE 1 - #define FALSE 0 -#endif - -#endif diff --git a/trunk/drivers/staging/ced1401/usb1401.c b/trunk/drivers/staging/ced1401/usb1401.c deleted file mode 100644 index 6ba0ef652561..000000000000 --- a/trunk/drivers/staging/ced1401/usb1401.c +++ /dev/null @@ -1,1637 +0,0 @@ -/*********************************************************************************** - CED1401 usb driver. This basic loading is based on the usb-skeleton.c code that is: - Copyright (C) 2001-2004 Greg Kroah-Hartman (greg@kroah.com) - Copyright (C) 2012 Alois Schloegl - There is not a great deal of the skeleton left. - - All the remainder dealing specifically with the CED1401 is based on drivers written - by CED for other systems (mainly Windows) and is: - Copyright (C) 2010 Cambridge Electronic Design Ltd - Author Greg P Smith (greg@ced.co.uk) - - 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - -Endpoints -********* -There are 4 endpoints plus the control endpoint in the standard interface -provided by most 1401s. The control endpoint is used for standard USB requests, -plus various CED-specific transactions such as start self test, debug and get -the 1401 status. The other endpoints are: - - 1 Characters to the 1401 - 2 Characters from the 1401 - 3 Block data to the 1401 - 4 Block data to the host. - -inside the driver these are indexed as an array from 0 to 3, transactions -over the control endpoint are carried out using a separate mechanism. The -use of the endpoints is mostly straightforward, with the driver issuing -IO request packets (IRPs) as required to transfer data to and from the 1401. -The handling of endpoint 2 is different because it is used for characters -from the 1401, which can appear spontaneously and without any other driver -activity - for example to repeatedly request DMA transfers in Spike2. The -desired effect is achieved by using an interrupt endpoint which can be -polled to see if it has data available, and writing the driver so that it -always maintains a pending read IRP from that endpoint which will read the -character data and terminate as soon as the 1401 makes data available. This -works very well, some care is taken with when you kick off this character -read IRP to avoid it being active when it is not wanted but generally it -is running all the time. - -In the 2270, there are only three endpoints plus the control endpoint. In -addition to the transactions mentioned above, the control endpoint is used -to transfer character data to the 1401. The other endpoints are used as: - - 1 Characters from the 1401 - 2 Block data to the 1401 - 3 Block data to the host. - -The type of interface available is specified by the interface subclass field -in the interface descriptor provided by the 1401. See the USB_INT_ constants -for the values that this field can hold. - -**************************************************************************** -Linux implementation - -Although Linux Device Drivers (3rd Edition) was a major source of information, -it is very out of date. A lot of information was gleaned from the latest -usb_skeleton.c code (you need to download the kernel sources to get this). - -To match the Windows version, everything is done using ioctl calls. All the -device state is held in the DEVICE_EXTENSION (named to match Windows use). -Block transfers are done by using get_user_pages() to pin down a list of -pages that we hold a pointer to in the device driver. We also allocate a -coherent transfer buffer of size STAGED_SZ (this must be a multiple of the -bulk endpoint size so that the 1401 does not realise that we break large -transfers down into smaller pieces). We use kmap_atomic() to get a kernel -va for each page, as it is required, for copying; see CopyUserSpace(). - -All character and data transfers are done using asynchronous IO. All Urbs are -tracked by anchoring them. Status and debug ioctls are implemented with the -synchronous non-Urb based transfers. -*/ - -#include -#include -#include -#include -#include -#include -#include -#if ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,35) ) -#include -#include -#include -#include -#include -#endif - -#include "usb1401.h" - -/* Define these values to match your devices */ -#define USB_CED_VENDOR_ID 0x0525 -#define USB_CED_PRODUCT_ID 0xa0f0 - -/* table of devices that work with this driver */ -static const struct usb_device_id ced_table[] = { - {USB_DEVICE(USB_CED_VENDOR_ID, USB_CED_PRODUCT_ID)}, - {} /* Terminating entry */ -}; - -MODULE_DEVICE_TABLE(usb, ced_table); - -/* Get a minor range for your devices from the usb maintainer */ -#define USB_CED_MINOR_BASE 192 - -/* our private defines. if this grows any larger, use your own .h file */ -#define MAX_TRANSFER (PAGE_SIZE - 512) -/* MAX_TRANSFER is chosen so that the VM is not stressed by - allocations > PAGE_SIZE and the number of packets in a page - is an integer 512 is the largest possible packet on EHCI */ -#define WRITES_IN_FLIGHT 8 -/* arbitrarily chosen */ - -/* -The cause for these errors is that the driver makes use of the functions usb_buffer_alloc() and usb_buffer_free() which got renamed in kernel 2.6.35. This is stated in the Changelog: USB: rename usb_buffer_alloc() and usb_buffer_free() users - For more clearance what the functions actually do, - usb_buffer_alloc() is renamed to usb_alloc_coherent() - usb_buffer_free() is renamed to usb_free_coherent() - This is needed on Debian 2.6.32-5-amd64 -*/ -#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35) ) -#define usb_alloc_coherent usb_buffer_alloc -#define usb_free_coherent usb_buffer_free -#define noop_llseek NULL -#endif - -static struct usb_driver ced_driver; - -static void ced_delete(struct kref *kref) -{ - DEVICE_EXTENSION *pdx = to_DEVICE_EXTENSION(kref); - - // Free up the output buffer, then free the output urb. Note that the interface member - // of pdx will probably be NULL, so cannot be used to get to dev. - usb_free_coherent(pdx->udev, OUTBUF_SZ, pdx->pCoherCharOut, - pdx->pUrbCharOut->transfer_dma); - usb_free_urb(pdx->pUrbCharOut); - - // Do the same for chan input - usb_free_coherent(pdx->udev, INBUF_SZ, pdx->pCoherCharIn, - pdx->pUrbCharIn->transfer_dma); - usb_free_urb(pdx->pUrbCharIn); - - // Do the same for the block transfers - usb_free_coherent(pdx->udev, STAGED_SZ, pdx->pCoherStagedIO, - pdx->pStagedUrb->transfer_dma); - usb_free_urb(pdx->pStagedUrb); - - usb_put_dev(pdx->udev); - kfree(pdx); -} - -// This is the driver end of the open() call from user space. -static int ced_open(struct inode *inode, struct file *file) -{ - DEVICE_EXTENSION *pdx; - int retval = 0; - int subminor = iminor(inode); - struct usb_interface *interface = - usb_find_interface(&ced_driver, subminor); - if (!interface) { - pr_err("%s - error, can't find device for minor %d", __func__, - subminor); - retval = -ENODEV; - goto exit; - } - - pdx = usb_get_intfdata(interface); - if (!pdx) { - retval = -ENODEV; - goto exit; - } - - dev_dbg(&interface->dev, "%s got pdx", __func__); - - /* increment our usage count for the device */ - kref_get(&pdx->kref); - - /* lock the device to allow correctly handling errors - * in resumption */ - mutex_lock(&pdx->io_mutex); - - if (!pdx->open_count++) { - retval = usb_autopm_get_interface(interface); - if (retval) { - pdx->open_count--; - mutex_unlock(&pdx->io_mutex); - kref_put(&pdx->kref, ced_delete); - goto exit; - } - } else { //uncomment this block if you want exclusive open - dev_err(&interface->dev, "%s fail: already open", __func__); - retval = -EBUSY; - pdx->open_count--; - mutex_unlock(&pdx->io_mutex); - kref_put(&pdx->kref, ced_delete); - goto exit; - } - /* prevent the device from being autosuspended */ - - /* save our object in the file's private structure */ - file->private_data = pdx; - mutex_unlock(&pdx->io_mutex); - -exit: - return retval; -} - -static int ced_release(struct inode *inode, struct file *file) -{ - DEVICE_EXTENSION *pdx = file->private_data; - if (pdx == NULL) - return -ENODEV; - - dev_dbg(&pdx->interface->dev, "%s called", __func__); - mutex_lock(&pdx->io_mutex); - if (!--pdx->open_count && pdx->interface) // Allow autosuspend - usb_autopm_put_interface(pdx->interface); - mutex_unlock(&pdx->io_mutex); - - kref_put(&pdx->kref, ced_delete); // decrement the count on our device - return 0; -} - -static int ced_flush(struct file *file, fl_owner_t id) -{ - int res; - DEVICE_EXTENSION *pdx = file->private_data; - if (pdx == NULL) - return -ENODEV; - - dev_dbg(&pdx->interface->dev, "%s char in pend=%d", __func__, - pdx->bReadCharsPending); - - /* wait for io to stop */ - mutex_lock(&pdx->io_mutex); - dev_dbg(&pdx->interface->dev, "%s got io_mutex", __func__); - ced_draw_down(pdx); - - /* read out errors, leave subsequent opens a clean slate */ - spin_lock_irq(&pdx->err_lock); - res = pdx->errors ? (pdx->errors == -EPIPE ? -EPIPE : -EIO) : 0; - pdx->errors = 0; - spin_unlock_irq(&pdx->err_lock); - - mutex_unlock(&pdx->io_mutex); - dev_dbg(&pdx->interface->dev, "%s exit reached", __func__); - - return res; -} - -/*************************************************************************** -** CanAcceptIoRequests -** If the device is removed, interface is set NULL. We also clear our pointer -** from the interface, so we should make sure that pdx is not NULL. This will -** not help with a device extension held by a file. -** return true if can accept new io requests, else false -*/ -static bool CanAcceptIoRequests(DEVICE_EXTENSION * pdx) -{ - return pdx && pdx->interface; // Can we accept IO requests -} - -/**************************************************************************** -** Callback routine to complete writes. This may need to fire off another -** urb to complete the transfer. -****************************************************************************/ -static void ced_writechar_callback(struct urb *pUrb) -{ - DEVICE_EXTENSION *pdx = pUrb->context; - int nGot = pUrb->actual_length; // what we transferred - - if (pUrb->status) { // sync/async unlink faults aren't errors - if (! - (pUrb->status == -ENOENT || pUrb->status == -ECONNRESET - || pUrb->status == -ESHUTDOWN)) { - dev_err(&pdx->interface->dev, - "%s - nonzero write bulk status received: %d", - __func__, pUrb->status); - } - - spin_lock(&pdx->err_lock); - pdx->errors = pUrb->status; - spin_unlock(&pdx->err_lock); - nGot = 0; // and tidy up again if so - - spin_lock(&pdx->charOutLock); // already at irq level - pdx->dwOutBuffGet = 0; // Reset the output buffer - pdx->dwOutBuffPut = 0; - pdx->dwNumOutput = 0; // Clear the char count - pdx->bPipeError[0] = 1; // Flag an error for later - pdx->bSendCharsPending = false; // Allow other threads again - spin_unlock(&pdx->charOutLock); // already at irq level - dev_dbg(&pdx->interface->dev, - "%s - char out done, 0 chars sent", __func__); - } else { - dev_dbg(&pdx->interface->dev, - "%s - char out done, %d chars sent", __func__, nGot); - spin_lock(&pdx->charOutLock); // already at irq level - pdx->dwNumOutput -= nGot; // Now adjust the char send buffer - pdx->dwOutBuffGet += nGot; // to match what we did - if (pdx->dwOutBuffGet >= OUTBUF_SZ) // Can't do this any earlier as data could be overwritten - pdx->dwOutBuffGet = 0; - - if (pdx->dwNumOutput > 0) // if more to be done... - { - int nPipe = 0; // The pipe number to use - int iReturn; - char *pDat = &pdx->outputBuffer[pdx->dwOutBuffGet]; - unsigned int dwCount = pdx->dwNumOutput; // maximum to send - if ((pdx->dwOutBuffGet + dwCount) > OUTBUF_SZ) // does it cross buffer end? - dwCount = OUTBUF_SZ - pdx->dwOutBuffGet; - spin_unlock(&pdx->charOutLock); // we are done with stuff that changes - memcpy(pdx->pCoherCharOut, pDat, dwCount); // copy output data to the buffer - usb_fill_bulk_urb(pdx->pUrbCharOut, pdx->udev, - usb_sndbulkpipe(pdx->udev, - pdx->epAddr[0]), - pdx->pCoherCharOut, dwCount, - ced_writechar_callback, pdx); - pdx->pUrbCharOut->transfer_flags |= - URB_NO_TRANSFER_DMA_MAP; - usb_anchor_urb(pdx->pUrbCharOut, &pdx->submitted); // in case we need to kill it - iReturn = usb_submit_urb(pdx->pUrbCharOut, GFP_ATOMIC); - dev_dbg(&pdx->interface->dev, "%s n=%d>%s<", __func__, - dwCount, pDat); - spin_lock(&pdx->charOutLock); // grab lock for errors - if (iReturn) { - pdx->bPipeError[nPipe] = 1; // Flag an error to be handled later - pdx->bSendCharsPending = false; // Allow other threads again - usb_unanchor_urb(pdx->pUrbCharOut); - dev_err(&pdx->interface->dev, - "%s usb_submit_urb() returned %d", - __func__, iReturn); - } - } else - pdx->bSendCharsPending = false; // Allow other threads again - spin_unlock(&pdx->charOutLock); // already at irq level - } -} - -/**************************************************************************** -** SendChars -** Transmit the characters in the output buffer to the 1401. This may need -** breaking down into multiple transfers. -****************************************************************************/ -int SendChars(DEVICE_EXTENSION * pdx) -{ - int iReturn = U14ERR_NOERROR; - - spin_lock_irq(&pdx->charOutLock); // Protect ourselves - - if ((!pdx->bSendCharsPending) && // Not currently sending - (pdx->dwNumOutput > 0) && // has characters to output - (CanAcceptIoRequests(pdx))) // and current activity is OK - { - unsigned int dwCount = pdx->dwNumOutput; // Get a copy of the character count - pdx->bSendCharsPending = true; // Set flag to lock out other threads - - dev_dbg(&pdx->interface->dev, - "Send %d chars to 1401, EP0 flag %d\n", dwCount, - pdx->nPipes == 3); - // If we have only 3 end points we must send the characters to the 1401 using EP0. - if (pdx->nPipes == 3) { - // For EP0 character transmissions to the 1401, we have to hang about until they - // are gone, as otherwise without more character IO activity they will never go. - unsigned int count = dwCount; // Local char counter - unsigned int index = 0; // The index into the char buffer - - spin_unlock_irq(&pdx->charOutLock); // Free spinlock as we call USBD - - while ((count > 0) && (iReturn == U14ERR_NOERROR)) { - // We have to break the transfer up into 64-byte chunks because of a 2270 problem - int n = count > 64 ? 64 : count; // Chars for this xfer, max of 64 - int nSent = usb_control_msg(pdx->udev, - usb_sndctrlpipe(pdx->udev, 0), // use end point 0 - DB_CHARS, // bRequest - (H_TO_D | VENDOR | DEVREQ), // to the device, vendor request to the device - 0, 0, // value and index are both 0 - &pdx->outputBuffer[index], // where to send from - n, // how much to send - 1000); // timeout in jiffies - if (nSent <= 0) { - iReturn = nSent ? nSent : -ETIMEDOUT; // if 0 chars says we timed out - dev_err(&pdx->interface->dev, - "Send %d chars by EP0 failed: %d", - n, iReturn); - } else { - dev_dbg(&pdx->interface->dev, - "Sent %d chars by EP0", n); - count -= nSent; - index += nSent; - } - } - - spin_lock_irq(&pdx->charOutLock); // Protect pdx changes, released by general code - pdx->dwOutBuffGet = 0; // so reset the output buffer - pdx->dwOutBuffPut = 0; - pdx->dwNumOutput = 0; // and clear the buffer count - pdx->bSendCharsPending = false; // Allow other threads again - } else { // Here for sending chars normally - we hold the spin lock - int nPipe = 0; // The pipe number to use - char *pDat = &pdx->outputBuffer[pdx->dwOutBuffGet]; - - if ((pdx->dwOutBuffGet + dwCount) > OUTBUF_SZ) // does it cross buffer end? - dwCount = OUTBUF_SZ - pdx->dwOutBuffGet; - spin_unlock_irq(&pdx->charOutLock); // we are done with stuff that changes - memcpy(pdx->pCoherCharOut, pDat, dwCount); // copy output data to the buffer - usb_fill_bulk_urb(pdx->pUrbCharOut, pdx->udev, - usb_sndbulkpipe(pdx->udev, - pdx->epAddr[0]), - pdx->pCoherCharOut, dwCount, - ced_writechar_callback, pdx); - pdx->pUrbCharOut->transfer_flags |= - URB_NO_TRANSFER_DMA_MAP; - usb_anchor_urb(pdx->pUrbCharOut, &pdx->submitted); - iReturn = usb_submit_urb(pdx->pUrbCharOut, GFP_KERNEL); - spin_lock_irq(&pdx->charOutLock); // grab lock for errors - if (iReturn) { - pdx->bPipeError[nPipe] = 1; // Flag an error to be handled later - pdx->bSendCharsPending = false; // Allow other threads again - usb_unanchor_urb(pdx->pUrbCharOut); // remove from list of active urbs - } - } - } else if (pdx->bSendCharsPending && (pdx->dwNumOutput > 0)) - dev_dbg(&pdx->interface->dev, - "SendChars bSendCharsPending:true"); - - dev_dbg(&pdx->interface->dev, "SendChars exit code: %d", iReturn); - spin_unlock_irq(&pdx->charOutLock); // Now let go of the spinlock - return iReturn; -} - -/*************************************************************************** -** CopyUserSpace -** This moves memory between pinned down user space and the pCoherStagedIO -** memory buffer we use for transfers. Copy n bytes in the directions that -** is defined by pdx->StagedRead. The user space is determined by the area -** in pdx->StagedId and the offset in pdx->StagedDone. The user -** area may well not start on a page boundary, so allow for that. -** -** We have a table of physical pages that describe the area, so we can use -** this to get a virtual address that the kernel can use. -** -** pdx Is our device extension which holds all we know about the transfer. -** n The number of bytes to move one way or the other. -***************************************************************************/ -static void CopyUserSpace(DEVICE_EXTENSION * pdx, int n) -{ - unsigned int nArea = pdx->StagedId; - if (nArea < MAX_TRANSAREAS) { - TRANSAREA *pArea = &pdx->rTransDef[nArea]; // area to be used - unsigned int dwOffset = - pdx->StagedDone + pdx->StagedOffset + pArea->dwBaseOffset; - char *pCoherBuf = pdx->pCoherStagedIO; // coherent buffer - if (!pArea->bUsed) { - dev_err(&pdx->interface->dev, "%s area %d unused", - __func__, nArea); - return; - } - - while (n) { - int nPage = dwOffset >> PAGE_SHIFT; // page number in table - if (nPage < pArea->nPages) { - char *pvAddress = - (char *)kmap_atomic(pArea->pPages[nPage]); - if (pvAddress) { - unsigned int uiPageOff = dwOffset & (PAGE_SIZE - 1); // offset into the page - size_t uiXfer = PAGE_SIZE - uiPageOff; // max to transfer on this page - if (uiXfer > n) // limit byte count if too much - uiXfer = n; // for the page - if (pdx->StagedRead) - memcpy(pvAddress + uiPageOff, - pCoherBuf, uiXfer); - else - memcpy(pCoherBuf, - pvAddress + uiPageOff, - uiXfer); - kunmap_atomic(pvAddress); - dwOffset += uiXfer; - pCoherBuf += uiXfer; - n -= uiXfer; - } else { - dev_err(&pdx->interface->dev, - "%s did not map page %d", - __func__, nPage); - return; - } - - } else { - dev_err(&pdx->interface->dev, - "%s exceeded pages %d", __func__, - nPage); - return; - } - } - } else - dev_err(&pdx->interface->dev, "%s bad area %d", __func__, - nArea); -} - -// Forward declarations for stuff used circularly -static int StageChunk(DEVICE_EXTENSION * pdx); -/*************************************************************************** -** ReadWrite_Complete -** -** Completion routine for our staged read/write Irps -*/ -static void staged_callback(struct urb *pUrb) -{ - DEVICE_EXTENSION *pdx = pUrb->context; - unsigned int nGot = pUrb->actual_length; // what we transferred - bool bCancel = false; - bool bRestartCharInput; // used at the end - - spin_lock(&pdx->stagedLock); // stop ReadWriteMem() action while this routine is running - pdx->bStagedUrbPending = false; // clear the flag for staged IRP pending - - if (pUrb->status) { // sync/async unlink faults aren't errors - if (! - (pUrb->status == -ENOENT || pUrb->status == -ECONNRESET - || pUrb->status == -ESHUTDOWN)) { - dev_err(&pdx->interface->dev, - "%s - nonzero write bulk status received: %d", - __func__, pUrb->status); - } else - dev_info(&pdx->interface->dev, - "%s - staged xfer cancelled", __func__); - - spin_lock(&pdx->err_lock); - pdx->errors = pUrb->status; - spin_unlock(&pdx->err_lock); - nGot = 0; // and tidy up again if so - bCancel = true; - } else { - dev_dbg(&pdx->interface->dev, "%s %d chars xferred", __func__, - nGot); - if (pdx->StagedRead) // if reading, save to user space - CopyUserSpace(pdx, nGot); // copy from buffer to user - if (nGot == 0) - dev_dbg(&pdx->interface->dev, "%s ZLP", __func__); - } - - // Update the transfer length based on the TransferBufferLength value in the URB - pdx->StagedDone += nGot; - - dev_dbg(&pdx->interface->dev, "%s, done %d bytes of %d", __func__, - pdx->StagedDone, pdx->StagedLength); - - if ((pdx->StagedDone == pdx->StagedLength) || // If no more to do - (bCancel)) // or this IRP was cancelled - { - TRANSAREA *pArea = &pdx->rTransDef[pdx->StagedId]; // Transfer area info - dev_dbg(&pdx->interface->dev, - "%s transfer done, bytes %d, cancel %d", __func__, - pdx->StagedDone, bCancel); - - // Here is where we sort out what to do with this transfer if using a circular buffer. We have - // a completed transfer that can be assumed to fit into the transfer area. We should be able to - // add this to the end of a growing block or to use it to start a new block unless the code - // that calculates the offset to use (in ReadWriteMem) is totally duff. - if ((pArea->bCircular) && (pArea->bCircToHost) && (!bCancel) && // Time to sort out circular buffer info? - (pdx->StagedRead)) // Only for tohost transfers for now - { - if (pArea->aBlocks[1].dwSize > 0) // If block 1 is in use we must append to it - { - if (pdx->StagedOffset == - (pArea->aBlocks[1].dwOffset + - pArea->aBlocks[1].dwSize)) { - pArea->aBlocks[1].dwSize += - pdx->StagedLength; - dev_dbg(&pdx->interface->dev, - "RWM_Complete, circ block 1 now %d bytes at %d", - pArea->aBlocks[1].dwSize, - pArea->aBlocks[1].dwOffset); - } else { - // Here things have gone very, very, wrong, but I cannot see how this can actually be achieved - pArea->aBlocks[1].dwOffset = - pdx->StagedOffset; - pArea->aBlocks[1].dwSize = - pdx->StagedLength; - dev_err(&pdx->interface->dev, - "%s ERROR, circ block 1 re-started %d bytes at %d", - __func__, - pArea->aBlocks[1].dwSize, - pArea->aBlocks[1].dwOffset); - } - } else // If block 1 is not used, we try to add to block 0 - { - if (pArea->aBlocks[0].dwSize > 0) // Got stored block 0 information? - { // Must append onto the existing block 0 - if (pdx->StagedOffset == - (pArea->aBlocks[0].dwOffset + - pArea->aBlocks[0].dwSize)) { - pArea->aBlocks[0].dwSize += pdx->StagedLength; // Just add this transfer in - dev_dbg(&pdx->interface->dev, - "RWM_Complete, circ block 0 now %d bytes at %d", - pArea->aBlocks[0]. - dwSize, - pArea->aBlocks[0]. - dwOffset); - } else // If it doesn't append, put into new block 1 - { - pArea->aBlocks[1].dwOffset = - pdx->StagedOffset; - pArea->aBlocks[1].dwSize = - pdx->StagedLength; - dev_dbg(&pdx->interface->dev, - "RWM_Complete, circ block 1 started %d bytes at %d", - pArea->aBlocks[1]. - dwSize, - pArea->aBlocks[1]. - dwOffset); - } - } else // No info stored yet, just save in block 0 - { - pArea->aBlocks[0].dwOffset = - pdx->StagedOffset; - pArea->aBlocks[0].dwSize = - pdx->StagedLength; - dev_dbg(&pdx->interface->dev, - "RWM_Complete, circ block 0 started %d bytes at %d", - pArea->aBlocks[0].dwSize, - pArea->aBlocks[0].dwOffset); - } - } - } - - if (!bCancel) // Don't generate an event if cancelled - { - dev_dbg(&pdx->interface->dev, - "RWM_Complete, bCircular %d, bToHost %d, eStart %d, eSize %d", - pArea->bCircular, pArea->bEventToHost, - pArea->dwEventSt, pArea->dwEventSz); - if ((pArea->dwEventSz) && // Set a user-mode event... - (pdx->StagedRead == pArea->bEventToHost)) // ...on transfers in this direction? - { - int iWakeUp = 0; // assume - // If we have completed the right sort of DMA transfer then set the event to notify - // the user code to wake up anyone that is waiting. - if ((pArea->bCircular) && // Circular areas use a simpler test - (pArea->bCircToHost)) // only in supported direction - { // Is total data waiting up to size limit? - unsigned int dwTotal = - pArea->aBlocks[0].dwSize + - pArea->aBlocks[1].dwSize; - iWakeUp = (dwTotal >= pArea->dwEventSz); - } else { - unsigned int transEnd = - pdx->StagedOffset + - pdx->StagedLength; - unsigned int eventEnd = - pArea->dwEventSt + pArea->dwEventSz; - iWakeUp = (pdx->StagedOffset < eventEnd) - && (transEnd > pArea->dwEventSt); - } - - if (iWakeUp) { - dev_dbg(&pdx->interface->dev, - "About to set event to notify app"); - wake_up_interruptible(&pArea->wqEvent); // wake up waiting processes - ++pArea->iWakeUp; // increment wakeup count - } - } - } - - pdx->dwDMAFlag = MODE_CHAR; // Switch back to char mode before ReadWriteMem call - - if (!bCancel) // Don't look for waiting transfer if cancelled - { - // If we have a transfer waiting, kick it off - if (pdx->bXFerWaiting) // Got a block xfer waiting? - { - int iReturn; - dev_info(&pdx->interface->dev, - "*** RWM_Complete *** pending transfer will now be set up!!!"); - iReturn = - ReadWriteMem(pdx, !pdx->rDMAInfo.bOutWard, - pdx->rDMAInfo.wIdent, - pdx->rDMAInfo.dwOffset, - pdx->rDMAInfo.dwSize); - - if (iReturn) - dev_err(&pdx->interface->dev, - "RWM_Complete rw setup failed %d", - iReturn); - } - } - - } else // Here for more to do - StageChunk(pdx); // fire off the next bit - - // While we hold the stagedLock, see if we should reallow character input ints - // Don't allow if cancelled, or if a new block has started or if there is a waiting block. - // This feels wrong as we should ask which spin lock protects dwDMAFlag. - bRestartCharInput = !bCancel && (pdx->dwDMAFlag == MODE_CHAR) - && !pdx->bXFerWaiting; - - spin_unlock(&pdx->stagedLock); // Finally release the lock again - - // This is not correct as dwDMAFlag is protected by the staged lock, but it is treated - // in Allowi as if it were protected by the char lock. In any case, most systems will - // not be upset by char input during DMA... sigh. Needs sorting out. - if (bRestartCharInput) // may be out of date, but... - Allowi(pdx, true); // ...Allowi tests a lock too. - dev_dbg(&pdx->interface->dev, "%s done", __func__); -} - -/**************************************************************************** -** StageChunk -** -** Generates the next chunk of data making up a staged transfer. -** -** The calling code must have acquired the staging spinlock before calling -** this function, and is responsible for releasing it. We are at callback level. -****************************************************************************/ -static int StageChunk(DEVICE_EXTENSION * pdx) -{ - int iReturn = U14ERR_NOERROR; - unsigned int ChunkSize; - int nPipe = pdx->StagedRead ? 3 : 2; // The pipe number to use for reads or writes - if (pdx->nPipes == 3) - nPipe--; // Adjust for the 3-pipe case - if (nPipe < 0) // and trap case that should never happen - return U14ERR_FAIL; - - if (!CanAcceptIoRequests(pdx)) // got sudden remove? - { - dev_info(&pdx->interface->dev, "%s sudden remove, giving up", - __func__); - return U14ERR_FAIL; // could do with a better error - } - - ChunkSize = (pdx->StagedLength - pdx->StagedDone); // transfer length remaining - if (ChunkSize > STAGED_SZ) // make sure to keep legal - ChunkSize = STAGED_SZ; // limit to max allowed - - if (!pdx->StagedRead) // if writing... - CopyUserSpace(pdx, ChunkSize); // ...copy data into the buffer - - usb_fill_bulk_urb(pdx->pStagedUrb, pdx->udev, - pdx->StagedRead ? usb_rcvbulkpipe(pdx->udev, - pdx-> - epAddr[nPipe]) : - usb_sndbulkpipe(pdx->udev, pdx->epAddr[nPipe]), - pdx->pCoherStagedIO, ChunkSize, staged_callback, pdx); - pdx->pStagedUrb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; - usb_anchor_urb(pdx->pStagedUrb, &pdx->submitted); // in case we need to kill it - iReturn = usb_submit_urb(pdx->pStagedUrb, GFP_ATOMIC); - if (iReturn) { - usb_unanchor_urb(pdx->pStagedUrb); // kill it - pdx->bPipeError[nPipe] = 1; // Flag an error to be handled later - dev_err(&pdx->interface->dev, "%s submit urb failed, code %d", - __func__, iReturn); - } else - pdx->bStagedUrbPending = true; // Set the flag for staged URB pending - dev_dbg(&pdx->interface->dev, "%s done so far:%d, this size:%d", - __func__, pdx->StagedDone, ChunkSize); - - return iReturn; -} - -/*************************************************************************** -** ReadWriteMem -** -** This routine is used generally for block read and write operations. -** Breaks up a read or write in to specified sized chunks, as specified by pipe -** information on maximum transfer size. -** -** Any code that calls this must be holding the stagedLock -** -** Arguments: -** DeviceObject - pointer to our FDO (Functional Device Object) -** Read - TRUE for read, FALSE for write. This is from POV of the driver -** wIdent - the transfer area number - defines memory area and more. -** dwOffs - the start offset within the transfer area of the start of this -** transfer. -** dwLen - the number of bytes to transfer. -*/ -int ReadWriteMem(DEVICE_EXTENSION * pdx, bool Read, unsigned short wIdent, - unsigned int dwOffs, unsigned int dwLen) -{ - TRANSAREA *pArea = &pdx->rTransDef[wIdent]; // Transfer area info - - if (!CanAcceptIoRequests(pdx)) // Are we in a state to accept new requests? - { - dev_err(&pdx->interface->dev, "%s can't accept requests", - __func__); - return U14ERR_FAIL; - } - - dev_dbg(&pdx->interface->dev, - "%s xfer %d bytes to %s, offset %d, area %d", __func__, dwLen, - Read ? "host" : "1401", dwOffs, wIdent); - - // Amazingly, we can get an escape sequence back before the current staged Urb is done, so we - // have to check for this situation and, if so, wait until all is OK. - if (pdx->bStagedUrbPending) { - pdx->bXFerWaiting = true; // Flag we are waiting - dev_info(&pdx->interface->dev, - "%s xfer is waiting, as previous staged pending", - __func__); - return U14ERR_NOERROR; - } - - if (dwLen == 0) // allow 0-len read or write; just return success - { - dev_dbg(&pdx->interface->dev, - "%s OK; zero-len read/write request", __func__); - return U14ERR_NOERROR; - } - - if ((pArea->bCircular) && // Circular transfer? - (pArea->bCircToHost) && (Read)) // In a supported direction - { // If so, we sort out offset ourself - bool bWait = false; // Flag for transfer having to wait - - dev_dbg(&pdx->interface->dev, - "Circular buffers are %d at %d and %d at %d", - pArea->aBlocks[0].dwSize, pArea->aBlocks[0].dwOffset, - pArea->aBlocks[1].dwSize, pArea->aBlocks[1].dwOffset); - if (pArea->aBlocks[1].dwSize > 0) // Using the second block already? - { - dwOffs = pArea->aBlocks[1].dwOffset + pArea->aBlocks[1].dwSize; // take offset from that - bWait = (dwOffs + dwLen) > pArea->aBlocks[0].dwOffset; // Wait if will overwrite block 0? - bWait |= (dwOffs + dwLen) > pArea->dwLength; // or if it overflows the buffer - } else // Area 1 not in use, try to use area 0 - { - if (pArea->aBlocks[0].dwSize == 0) // Reset block 0 if not in use - pArea->aBlocks[0].dwOffset = 0; - dwOffs = - pArea->aBlocks[0].dwOffset + - pArea->aBlocks[0].dwSize; - if ((dwOffs + dwLen) > pArea->dwLength) // Off the end of the buffer? - { - pArea->aBlocks[1].dwOffset = 0; // Set up to use second block - dwOffs = 0; - bWait = (dwOffs + dwLen) > pArea->aBlocks[0].dwOffset; // Wait if will overwrite block 0? - bWait |= (dwOffs + dwLen) > pArea->dwLength; // or if it overflows the buffer - } - } - - if (bWait) // This transfer will have to wait? - { - pdx->bXFerWaiting = true; // Flag we are waiting - dev_dbg(&pdx->interface->dev, - "%s xfer waiting for circular buffer space", - __func__); - return U14ERR_NOERROR; - } - - dev_dbg(&pdx->interface->dev, - "%s circular xfer, %d bytes starting at %d", __func__, - dwLen, dwOffs); - } - // Save the parameters for the read\write transfer - pdx->StagedRead = Read; // Save the parameters for this read - pdx->StagedId = wIdent; // ID allows us to get transfer area info - pdx->StagedOffset = dwOffs; // The area within the transfer area - pdx->StagedLength = dwLen; - pdx->StagedDone = 0; // Initialise the byte count - pdx->dwDMAFlag = MODE_LINEAR; // Set DMA mode flag at this point - pdx->bXFerWaiting = false; // Clearly not a transfer waiting now - -// KeClearEvent(&pdx->StagingDoneEvent); // Clear the transfer done event - StageChunk(pdx); // fire off the first chunk - - return U14ERR_NOERROR; -} - -/**************************************************************************** -** -** ReadChar -** -** Reads a character a buffer. If there is no more -** data we return FALSE. Used as part of decoding a DMA request. -** -****************************************************************************/ -static bool ReadChar(unsigned char *pChar, char *pBuf, unsigned int *pdDone, - unsigned int dGot) -{ - bool bRead = false; - unsigned int dDone = *pdDone; - - if (dDone < dGot) // If there is more data - { - *pChar = (unsigned char)pBuf[dDone]; // Extract the next char - dDone++; // Increment the done count - *pdDone = dDone; - bRead = true; // and flag success - } - - return bRead; -} - -#ifdef NOTUSED -/**************************************************************************** -** -** ReadWord -** -** Reads a word from the 1401, just uses ReadChar twice; passes on any error -** -*****************************************************************************/ -static bool ReadWord(unsigned short *pWord, char *pBuf, unsigned int *pdDone, - unsigned int dGot) -{ - if (ReadChar((unsigned char *)pWord, pBuf, pdDone, dGot)) - return ReadChar(((unsigned char *)pWord) + 1, pBuf, pdDone, - dGot); - else - return false; -} -#endif - -/**************************************************************************** -** ReadHuff -** -** Reads a coded number in and returns it, Code is: -** If data is in range 0..127 we recieve 1 byte. If data in range 128-16383 -** we recieve two bytes, top bit of first indicates another on its way. If -** data in range 16383-4194303 we get three bytes, top two bits of first set -** to indicate three byte total. -** -*****************************************************************************/ -static bool ReadHuff(volatile unsigned int *pDWord, char *pBuf, - unsigned int *pdDone, unsigned int dGot) -{ - unsigned char ucData; /* for each read to ReadChar */ - bool bReturn = true; /* assume we will succeed */ - unsigned int dwData = 0; /* Accumulator for the data */ - - if (ReadChar(&ucData, pBuf, pdDone, dGot)) { - dwData = ucData; /* copy the data */ - if ((dwData & 0x00000080) != 0) { /* Bit set for more data ? */ - dwData &= 0x0000007F; /* Clear the relevant bit */ - if (ReadChar(&ucData, pBuf, pdDone, dGot)) { - dwData = (dwData << 8) | ucData; - if ((dwData & 0x00004000) != 0) { /* three byte sequence ? */ - dwData &= 0x00003FFF; /* Clear the relevant bit */ - if (ReadChar - (&ucData, pBuf, pdDone, dGot)) - dwData = (dwData << 8) | ucData; - else - bReturn = false; - } - } else - bReturn = false; /* couldn't read data */ - } - } else - bReturn = false; - - *pDWord = dwData; /* return the data */ - return bReturn; -} - -/*************************************************************************** -** -** ReadDMAInfo -** -** Tries to read info about the dma request from the 1401 and decode it into -** the dma descriptor block. We have at this point had the escape character -** from the 1401 and now we must read in the rest of the information about -** the transfer request. Returns FALSE if 1401 fails to respond or obselete -** code from 1401 or bad parameters. -** -** The pBuf char pointer does not include the initial escape character, so -** we start handling the data at offset zero. -** -*****************************************************************************/ -static bool ReadDMAInfo(volatile DMADESC * pDmaDesc, DEVICE_EXTENSION * pdx, - char *pBuf, unsigned int dwCount) -{ - bool bResult = false; // assume we won't succeed - unsigned char ucData; - unsigned int dDone = 0; // We haven't parsed anything so far - - dev_dbg(&pdx->interface->dev, "%s", __func__); - - if (ReadChar(&ucData, pBuf, &dDone, dwCount)) { - unsigned char ucTransCode = (ucData & 0x0F); // get code for transfer type - unsigned short wIdent = ((ucData >> 4) & 0x07); // and area identifier - - // fill in the structure we were given - pDmaDesc->wTransType = ucTransCode; // type of transfer - pDmaDesc->wIdent = wIdent; // area to use - pDmaDesc->dwSize = 0; // initialise other bits - pDmaDesc->dwOffset = 0; - - dev_dbg(&pdx->interface->dev, "%s type: %d ident: %d", __func__, - pDmaDesc->wTransType, pDmaDesc->wIdent); - - pDmaDesc->bOutWard = (ucTransCode != TM_EXTTOHOST); // set transfer direction - - switch (ucTransCode) { - case TM_EXTTOHOST: // Extended linear transfer modes (the only ones!) - case TM_EXTTO1401: - { - bResult = - ReadHuff(&(pDmaDesc->dwOffset), pBuf, - &dDone, dwCount) - && ReadHuff(&(pDmaDesc->dwSize), pBuf, - &dDone, dwCount); - if (bResult) { - dev_dbg(&pdx->interface->dev, - "%s xfer offset & size %d %d", - __func__, pDmaDesc->dwOffset, - pDmaDesc->dwSize); - - if ((wIdent >= MAX_TRANSAREAS) || // Illegal area number, or... - (!pdx->rTransDef[wIdent].bUsed) || // area not set up, or... - (pDmaDesc->dwOffset > pdx->rTransDef[wIdent].dwLength) || // range/size - ((pDmaDesc->dwOffset + - pDmaDesc->dwSize) > - (pdx->rTransDef[wIdent]. - dwLength))) { - bResult = false; // bad parameter(s) - dev_dbg(&pdx->interface->dev, - "%s bad param - id %d, bUsed %d, offset %d, size %d, area length %d", - __func__, wIdent, - pdx->rTransDef[wIdent]. - bUsed, - pDmaDesc->dwOffset, - pDmaDesc->dwSize, - pdx->rTransDef[wIdent]. - dwLength); - } - } - break; - } - default: - break; - } - } else - bResult = false; - - if (!bResult) // now check parameters for validity - dev_err(&pdx->interface->dev, "%s error reading Esc sequence", - __func__); - - return bResult; -} - -/**************************************************************************** -** -** Handle1401Esc -** -** Deals with an escape sequence coming from the 1401. This can either be -** a DMA transfer request of various types or a response to an escape sequence -** sent to the 1401. This is called from a callback. -** -** Parameters are -** -** dwCount - the number of characters in the device extension char in buffer, -** this is known to be at least 2 or we will not be called. -** -****************************************************************************/ -static int Handle1401Esc(DEVICE_EXTENSION * pdx, char *pCh, - unsigned int dwCount) -{ - int iReturn = U14ERR_FAIL; - - // I have no idea what this next test is about. '?' is 0x3f, which is area 3, code - // 15. At the moment, this is not used, so it does no harm, but unless someone can - // tell me what this is for, it should be removed from this and the Windows driver. - if (pCh[0] == '?') // Is this an information response - { // Parse and save the information - } else { - spin_lock(&pdx->stagedLock); // Lock others out - - if (ReadDMAInfo(&pdx->rDMAInfo, pdx, pCh, dwCount)) // Get DMA parameters - { - unsigned short wTransType = pdx->rDMAInfo.wTransType; // check transfer type - - dev_dbg(&pdx->interface->dev, - "%s xfer to %s, offset %d, length %d", __func__, - pdx->rDMAInfo.bOutWard ? "1401" : "host", - pdx->rDMAInfo.dwOffset, pdx->rDMAInfo.dwSize); - - if (pdx->bXFerWaiting) // Check here for badly out of kilter... - { // This can never happen, really - dev_err(&pdx->interface->dev, - "ERROR: DMA setup while transfer still waiting"); - spin_unlock(&pdx->stagedLock); - } else { - if ((wTransType == TM_EXTTOHOST) - || (wTransType == TM_EXTTO1401)) { - iReturn = - ReadWriteMem(pdx, - !pdx->rDMAInfo. - bOutWard, - pdx->rDMAInfo.wIdent, - pdx->rDMAInfo.dwOffset, - pdx->rDMAInfo.dwSize); - if (iReturn != U14ERR_NOERROR) - dev_err(&pdx->interface->dev, - "%s ReadWriteMem() failed %d", - __func__, iReturn); - } else // This covers non-linear transfer setup - dev_err(&pdx->interface->dev, - "%s Unknown block xfer type %d", - __func__, wTransType); - } - } else // Failed to read parameters - dev_err(&pdx->interface->dev, "%s ReadDMAInfo() fail", - __func__); - - spin_unlock(&pdx->stagedLock); // OK here - } - - dev_dbg(&pdx->interface->dev, "%s returns %d", __func__, iReturn); - - return iReturn; -} - -/**************************************************************************** -** Callback for the character read complete or error -****************************************************************************/ -static void ced_readchar_callback(struct urb *pUrb) -{ - DEVICE_EXTENSION *pdx = pUrb->context; - int nGot = pUrb->actual_length; // what we transferred - - if (pUrb->status) // Do we have a problem to handle? - { - int nPipe = pdx->nPipes == 4 ? 1 : 0; // The pipe number to use for error - // sync/async unlink faults aren't errors... just saying device removed or stopped - if (! - (pUrb->status == -ENOENT || pUrb->status == -ECONNRESET - || pUrb->status == -ESHUTDOWN)) { - dev_err(&pdx->interface->dev, - "%s - nonzero write bulk status received: %d", - __func__, pUrb->status); - } else - dev_dbg(&pdx->interface->dev, - "%s - 0 chars pUrb->status=%d (shutdown?)", - __func__, pUrb->status); - - spin_lock(&pdx->err_lock); - pdx->errors = pUrb->status; - spin_unlock(&pdx->err_lock); - nGot = 0; // and tidy up again if so - - spin_lock(&pdx->charInLock); // already at irq level - pdx->bPipeError[nPipe] = 1; // Flag an error for later - } else { - if ((nGot > 1) && ((pdx->pCoherCharIn[0] & 0x7f) == 0x1b)) // Esc sequence? - { - Handle1401Esc(pdx, &pdx->pCoherCharIn[1], nGot - 1); // handle it - spin_lock(&pdx->charInLock); // already at irq level - } else { - spin_lock(&pdx->charInLock); // already at irq level - if (nGot > 0) { - unsigned int i; - if (nGot < INBUF_SZ) { - pdx->pCoherCharIn[nGot] = 0; // tidy the string - dev_dbg(&pdx->interface->dev, - "%s got %d chars >%s<", - __func__, nGot, - pdx->pCoherCharIn); - } - // We know that whatever we read must fit in the input buffer - for (i = 0; i < nGot; i++) { - pdx->inputBuffer[pdx->dwInBuffPut++] = - pdx->pCoherCharIn[i] & 0x7F; - if (pdx->dwInBuffPut >= INBUF_SZ) - pdx->dwInBuffPut = 0; - } - - if ((pdx->dwNumInput + nGot) <= INBUF_SZ) - pdx->dwNumInput += nGot; // Adjust the buffer count accordingly - } else - dev_dbg(&pdx->interface->dev, "%s read ZLP", - __func__); - } - } - - pdx->bReadCharsPending = false; // No longer have a pending read - spin_unlock(&pdx->charInLock); // already at irq level - - Allowi(pdx, true); // see if we can do the next one -} - -/**************************************************************************** -** Allowi -** -** This is used to make sure that there is always a pending input transfer so -** we can pick up any inward transfers. This can be called in multiple contexts -** so we use the irqsave version of the spinlock. -****************************************************************************/ -int Allowi(DEVICE_EXTENSION * pdx, bool bInCallback) -{ - int iReturn = U14ERR_NOERROR; - unsigned long flags; - spin_lock_irqsave(&pdx->charInLock, flags); // can be called in multiple contexts - - // We don't want char input running while DMA is in progress as we know that this - // can cause sequencing problems for the 2270. So don't. It will also allow the - // ERR response to get back to the host code too early on some PCs, even if there - // is no actual driver failure, so we don't allow this at all. - if (!pdx->bInDrawDown && // stop input if - !pdx->bReadCharsPending && // If no read request outstanding - (pdx->dwNumInput < (INBUF_SZ / 2)) && // and there is some space - (pdx->dwDMAFlag == MODE_CHAR) && // not doing any DMA - (!pdx->bXFerWaiting) && // no xfer waiting to start - (CanAcceptIoRequests(pdx))) // and activity is generally OK - { // then off we go - unsigned int nMax = INBUF_SZ - pdx->dwNumInput; // max we could read - int nPipe = pdx->nPipes == 4 ? 1 : 0; // The pipe number to use - - dev_dbg(&pdx->interface->dev, "%s %d chars in input buffer", - __func__, pdx->dwNumInput); - - usb_fill_int_urb(pdx->pUrbCharIn, pdx->udev, - usb_rcvintpipe(pdx->udev, pdx->epAddr[nPipe]), - pdx->pCoherCharIn, nMax, ced_readchar_callback, - pdx, pdx->bInterval); - pdx->pUrbCharIn->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; // short xfers are OK by default - usb_anchor_urb(pdx->pUrbCharIn, &pdx->submitted); // in case we need to kill it - iReturn = - usb_submit_urb(pdx->pUrbCharIn, - bInCallback ? GFP_ATOMIC : GFP_KERNEL); - if (iReturn) { - usb_unanchor_urb(pdx->pUrbCharIn); // remove from list of active Urbs - pdx->bPipeError[nPipe] = 1; // Flag an error to be handled later - dev_err(&pdx->interface->dev, - "%s submit urb failed: %d", __func__, iReturn); - } else - pdx->bReadCharsPending = true; // Flag that we are active here - } - - spin_unlock_irqrestore(&pdx->charInLock, flags); - - return iReturn; - -} - -/***************************************************************************** -** The ioctl entry point to the driver that is used by us to talk to it. -** inode The device node (no longer in 3.0.0 kernels) -** file The file that is open, which holds our pdx pointer -** ulArg The argument passed in. Note that long is 64-bits in 64-bit system, i.e. it is big -** enough for a 64-bit pointer. -*****************************************************************************/ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36) -static long ced_ioctl(struct file *file, unsigned int cmd, unsigned long ulArg) -#else -static int ced_ioctl(struct inode *node, struct file *file, unsigned int cmd, - unsigned long ulArg) -#endif -{ - int err = 0; - DEVICE_EXTENSION *pdx = file->private_data; - if (!CanAcceptIoRequests(pdx)) // check we still exist - return -ENODEV; - - // Check that access is allowed, where is is needed. Anything that would have an indeterminate - // size will be checked by the specific command. - if (_IOC_DIR(cmd) & _IOC_READ) // read from point of view of user... - err = !access_ok(VERIFY_WRITE, (void __user *)ulArg, _IOC_SIZE(cmd)); // is kernel write - else if (_IOC_DIR(cmd) & _IOC_WRITE) // and write from point of view of user... - err = !access_ok(VERIFY_READ, (void __user *)ulArg, _IOC_SIZE(cmd)); // is kernel read - if (err) - return -EFAULT; - - switch (_IOC_NR(cmd)) { - case _IOC_NR(IOCTL_CED_SENDSTRING(0)): - return SendString(pdx, (const char __user *)ulArg, - _IOC_SIZE(cmd)); - - case _IOC_NR(IOCTL_CED_RESET1401): - return Reset1401(pdx); - - case _IOC_NR(IOCTL_CED_GETCHAR): - return GetChar(pdx); - - case _IOC_NR(IOCTL_CED_SENDCHAR): - return SendChar(pdx, (char)ulArg); - - case _IOC_NR(IOCTL_CED_STAT1401): - return Stat1401(pdx); - - case _IOC_NR(IOCTL_CED_LINECOUNT): - return LineCount(pdx); - - case _IOC_NR(IOCTL_CED_GETSTRING(0)): - return GetString(pdx, (char __user *)ulArg, _IOC_SIZE(cmd)); - - case _IOC_NR(IOCTL_CED_SETTRANSFER): - return SetTransfer(pdx, (TRANSFERDESC __user *) ulArg); - - case _IOC_NR(IOCTL_CED_UNSETTRANSFER): - return UnsetTransfer(pdx, (int)ulArg); - - case _IOC_NR(IOCTL_CED_SETEVENT): - return SetEvent(pdx, (TRANSFEREVENT __user *) ulArg); - - case _IOC_NR(IOCTL_CED_GETOUTBUFSPACE): - return GetOutBufSpace(pdx); - - case _IOC_NR(IOCTL_CED_GETBASEADDRESS): - return -1; - - case _IOC_NR(IOCTL_CED_GETDRIVERREVISION): - return (2 << 24) | (DRIVERMAJREV << 16) | DRIVERMINREV; // USB | MAJOR | MINOR - - case _IOC_NR(IOCTL_CED_GETTRANSFER): - return GetTransfer(pdx, (TGET_TX_BLOCK __user *) ulArg); - - case _IOC_NR(IOCTL_CED_KILLIO1401): - return KillIO1401(pdx); - - case _IOC_NR(IOCTL_CED_STATEOF1401): - return StateOf1401(pdx); - - case _IOC_NR(IOCTL_CED_GRAB1401): - case _IOC_NR(IOCTL_CED_FREE1401): - return U14ERR_NOERROR; - - case _IOC_NR(IOCTL_CED_STARTSELFTEST): - return StartSelfTest(pdx); - - case _IOC_NR(IOCTL_CED_CHECKSELFTEST): - return CheckSelfTest(pdx, (TGET_SELFTEST __user *) ulArg); - - case _IOC_NR(IOCTL_CED_TYPEOF1401): - return TypeOf1401(pdx); - - case _IOC_NR(IOCTL_CED_TRANSFERFLAGS): - return TransferFlags(pdx); - - case _IOC_NR(IOCTL_CED_DBGPEEK): - return DbgPeek(pdx, (TDBGBLOCK __user *) ulArg); - - case _IOC_NR(IOCTL_CED_DBGPOKE): - return DbgPoke(pdx, (TDBGBLOCK __user *) ulArg); - - case _IOC_NR(IOCTL_CED_DBGRAMPDATA): - return DbgRampData(pdx, (TDBGBLOCK __user *) ulArg); - - case _IOC_NR(IOCTL_CED_DBGRAMPADDR): - return DbgRampAddr(pdx, (TDBGBLOCK __user *) ulArg); - - case _IOC_NR(IOCTL_CED_DBGGETDATA): - return DbgGetData(pdx, (TDBGBLOCK __user *) ulArg); - - case _IOC_NR(IOCTL_CED_DBGSTOPLOOP): - return DbgStopLoop(pdx); - - case _IOC_NR(IOCTL_CED_FULLRESET): - pdx->bForceReset = true; // Set a flag for a full reset - break; - - case _IOC_NR(IOCTL_CED_SETCIRCULAR): - return SetCircular(pdx, (TRANSFERDESC __user *) ulArg); - - case _IOC_NR(IOCTL_CED_GETCIRCBLOCK): - return GetCircBlock(pdx, (TCIRCBLOCK __user *) ulArg); - - case _IOC_NR(IOCTL_CED_FREECIRCBLOCK): - return FreeCircBlock(pdx, (TCIRCBLOCK __user *) ulArg); - - case _IOC_NR(IOCTL_CED_WAITEVENT): - return WaitEvent(pdx, (int)(ulArg & 0xff), (int)(ulArg >> 8)); - - case _IOC_NR(IOCTL_CED_TESTEVENT): - return TestEvent(pdx, (int)ulArg); - - default: - return U14ERR_NO_SUCH_FN; - } - return U14ERR_NOERROR; -} - -static const struct file_operations ced_fops = { - .owner = THIS_MODULE, - .open = ced_open, - .release = ced_release, - .flush = ced_flush, - .llseek = noop_llseek, -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36) - .unlocked_ioctl = ced_ioctl, -#else - .ioctl = ced_ioctl, -#endif -}; - -/* - * usb class driver info in order to get a minor number from the usb core, - * and to have the device registered with the driver core - */ -static struct usb_class_driver ced_class = { - .name = "cedusb%d", - .fops = &ced_fops, - .minor_base = USB_CED_MINOR_BASE, -}; - -// Check that the device that matches a 1401 vendor and product ID is OK to use and -// initialise our DEVICE_EXTENSION. -static int ced_probe(struct usb_interface *interface, - const struct usb_device_id *id) -{ - DEVICE_EXTENSION *pdx; - struct usb_host_interface *iface_desc; - struct usb_endpoint_descriptor *endpoint; - int i, bcdDevice; - int retval = -ENOMEM; - - // allocate memory for our device extension and initialize it - pdx = kzalloc(sizeof(*pdx), GFP_KERNEL); - if (!pdx) { - dev_err(&interface->dev, "Out of memory\n"); - goto error; - } - - for (i = 0; i < MAX_TRANSAREAS; ++i) // Initialise the wait queues - { - init_waitqueue_head(&pdx->rTransDef[i].wqEvent); - } - - // Put initialises for our stuff here. Note that all of *pdx is zero, so - // no need to explicitly zero it. - spin_lock_init(&pdx->charOutLock); - spin_lock_init(&pdx->charInLock); - spin_lock_init(&pdx->stagedLock); - - // Initialises from the skeleton stuff - kref_init(&pdx->kref); - mutex_init(&pdx->io_mutex); - spin_lock_init(&pdx->err_lock); - init_usb_anchor(&pdx->submitted); - - pdx->udev = usb_get_dev(interface_to_usbdev(interface)); - pdx->interface = interface; - - // Attempt to identify the device - bcdDevice = pdx->udev->descriptor.bcdDevice; - i = (bcdDevice >> 8); - if (i == 0) - pdx->s1401Type = TYPEU1401; - else if ((i >= 1) && (i <= 23)) - pdx->s1401Type = i + 2; - else { - dev_err(&interface->dev, "%s Unknown device. bcdDevice = %d", - __func__, bcdDevice); - goto error; - } - // set up the endpoint information. We only care about the number of EP as - // we know that we are dealing with a 1401 device. - iface_desc = interface->cur_altsetting; - pdx->nPipes = iface_desc->desc.bNumEndpoints; - dev_info(&interface->dev, "1401Type=%d with %d End Points", - pdx->s1401Type, pdx->nPipes); - if ((pdx->nPipes < 3) || (pdx->nPipes > 4)) - goto error; - - // Allocate the URBs we hold for performing transfers - pdx->pUrbCharOut = usb_alloc_urb(0, GFP_KERNEL); // character output URB - pdx->pUrbCharIn = usb_alloc_urb(0, GFP_KERNEL); // character input URB - pdx->pStagedUrb = usb_alloc_urb(0, GFP_KERNEL); // block transfer URB - if (!pdx->pUrbCharOut || !pdx->pUrbCharIn || !pdx->pStagedUrb) { - dev_err(&interface->dev, "%s URB alloc failed", __func__); - goto error; - } - - pdx->pCoherStagedIO = - usb_alloc_coherent(pdx->udev, STAGED_SZ, GFP_KERNEL, - &pdx->pStagedUrb->transfer_dma); - pdx->pCoherCharOut = - usb_alloc_coherent(pdx->udev, OUTBUF_SZ, GFP_KERNEL, - &pdx->pUrbCharOut->transfer_dma); - pdx->pCoherCharIn = - usb_alloc_coherent(pdx->udev, INBUF_SZ, GFP_KERNEL, - &pdx->pUrbCharIn->transfer_dma); - if (!pdx->pCoherCharOut || !pdx->pCoherCharIn || !pdx->pCoherStagedIO) { - dev_err(&interface->dev, "%s Coherent buffer alloc failed", - __func__); - goto error; - } - - for (i = 0; i < pdx->nPipes; ++i) { - endpoint = &iface_desc->endpoint[i].desc; - pdx->epAddr[i] = endpoint->bEndpointAddress; - dev_info(&interface->dev, "Pipe %d, ep address %02x", i, - pdx->epAddr[i]); - if (((pdx->nPipes == 3) && (i == 0)) || // if char input end point - ((pdx->nPipes == 4) && (i == 1))) { - pdx->bInterval = endpoint->bInterval; // save the endpoint interrupt interval - dev_info(&interface->dev, "Pipe %d, bInterval = %d", i, - pdx->bInterval); - } - // Detect USB2 by checking last ep size (64 if USB1) - if (i == pdx->nPipes - 1) // if this is the last ep (bulk) - { - pdx->bIsUSB2 = - le16_to_cpu(endpoint->wMaxPacketSize) > 64; - dev_info(&pdx->interface->dev, "USB%d", - pdx->bIsUSB2 + 1); - } - } - - /* save our data pointer in this interface device */ - usb_set_intfdata(interface, pdx); - - /* we can register the device now, as it is ready */ - retval = usb_register_dev(interface, &ced_class); - if (retval) { - /* something prevented us from registering this driver */ - dev_err(&interface->dev, - "Not able to get a minor for this device.\n"); - usb_set_intfdata(interface, NULL); - goto error; - } - - /* let the user know what node this device is now attached to */ - dev_info(&interface->dev, - "USB CEDUSB device now attached to cedusb #%d", - interface->minor); - return 0; - -error: - if (pdx) - kref_put(&pdx->kref, ced_delete); // frees allocated memory - return retval; -} - -static void ced_disconnect(struct usb_interface *interface) -{ - DEVICE_EXTENSION *pdx = usb_get_intfdata(interface); - int minor = interface->minor; // save for message at the end - int i; - - usb_set_intfdata(interface, NULL); // remove the pdx from the interface - usb_deregister_dev(interface, &ced_class); // give back our minor device number - - mutex_lock(&pdx->io_mutex); // stop more I/O starting while... - ced_draw_down(pdx); // ...wait for then kill any io - for (i = 0; i < MAX_TRANSAREAS; ++i) { - int iErr = ClearArea(pdx, i); // ...release any used memory - if (iErr == U14ERR_UNLOCKFAIL) - dev_err(&pdx->interface->dev, "%s Area %d was in used", - __func__, i); - } - pdx->interface = NULL; // ...we kill off link to interface - mutex_unlock(&pdx->io_mutex); - - usb_kill_anchored_urbs(&pdx->submitted); - - kref_put(&pdx->kref, ced_delete); // decrement our usage count - - dev_info(&interface->dev, "USB cedusb #%d now disconnected", minor); -} - -// Wait for all the urbs we know of to be done with, then kill off any that -// are left. NBNB we will need to have a mechanism to stop circular xfers -// from trying to fire off more urbs. We will wait up to 3 seconds for Urbs -// to be done. -void ced_draw_down(DEVICE_EXTENSION * pdx) -{ - int time; - dev_dbg(&pdx->interface->dev, "%s called", __func__); - - pdx->bInDrawDown = true; - time = usb_wait_anchor_empty_timeout(&pdx->submitted, 3000); - if (!time) // if we timed out we kill the urbs - { - usb_kill_anchored_urbs(&pdx->submitted); - dev_err(&pdx->interface->dev, "%s timed out", __func__); - } - pdx->bInDrawDown = false; -} - -static int ced_suspend(struct usb_interface *intf, pm_message_t message) -{ - DEVICE_EXTENSION *pdx = usb_get_intfdata(intf); - if (!pdx) - return 0; - ced_draw_down(pdx); - - dev_dbg(&pdx->interface->dev, "%s called", __func__); - return 0; -} - -static int ced_resume(struct usb_interface *intf) -{ - DEVICE_EXTENSION *pdx = usb_get_intfdata(intf); - if (!pdx) - return 0; - dev_dbg(&pdx->interface->dev, "%s called", __func__); - return 0; -} - -static int ced_pre_reset(struct usb_interface *intf) -{ - DEVICE_EXTENSION *pdx = usb_get_intfdata(intf); - dev_dbg(&pdx->interface->dev, "%s", __func__); - mutex_lock(&pdx->io_mutex); - ced_draw_down(pdx); - return 0; -} - -static int ced_post_reset(struct usb_interface *intf) -{ - DEVICE_EXTENSION *pdx = usb_get_intfdata(intf); - dev_dbg(&pdx->interface->dev, "%s", __func__); - - /* we are sure no URBs are active - no locking needed */ - pdx->errors = -EPIPE; - mutex_unlock(&pdx->io_mutex); - - return 0; -} - -static struct usb_driver ced_driver = { - .name = "cedusb", - .probe = ced_probe, - .disconnect = ced_disconnect, - .suspend = ced_suspend, - .resume = ced_resume, - .pre_reset = ced_pre_reset, - .post_reset = ced_post_reset, - .id_table = ced_table, - .supports_autosuspend = 1, -}; - -module_usb_driver(ced_driver); -MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/staging/ced1401/usb1401.h b/trunk/drivers/staging/ced1401/usb1401.h deleted file mode 100644 index 331ca9859829..000000000000 --- a/trunk/drivers/staging/ced1401/usb1401.h +++ /dev/null @@ -1,249 +0,0 @@ -/* usb1401.h - Header file for the CED 1401 USB device driver for Linux - Copyright (C) 2010 Cambridge Electronic Design Ltd - Author Greg P Smith (greg@ced.co.uk) - - 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ -#ifndef __USB1401_H__ -#define __USB1401_H__ -#include "use1401.h" -#include "ced_ioctl.h" - -#ifndef UINT -#define UINT unsigned int -#endif - -/// Device type codes, but these don't need to be extended - a succession is assumed -/// These are set for usb from the bcdDevice field (suitably mangled). Future devices -/// will be added in order of device creation to the list, so the names here are just -/// to help use remember which device is which. The U14ERR_... values follow the same -/// pattern for modern devices. -#define TYPEUNKNOWN -1 // dont know -#define TYPE1401 0 // standard 1401 -#define TYPEPLUS 1 // 1401 plus -#define TYPEU1401 2 // u1401 -#define TYPEPOWER 3 // Power1401 -#define TYPEU14012 4 // u1401 mkII -#define TYPEPOWER2 5 // Power1401 mk II -#define TYPEMICRO3 6 // Micro1401-3 -#define TYPEPOWER3 7 // Power1401-3 - -/// Some useful defines of constants. DONT FORGET to change the version in the -/// resources whenever you change it here!. -#define DRIVERMAJREV 2 // driver revision level major (match windows) -#define DRIVERMINREV 0 // driver revision level minor - -/// Definitions of the various block transfer command codes -#define TM_EXTTOHOST 8 // extended tohost -#define TM_EXTTO1401 9 // extended to1401 - -/// Definitions of values in usbReqtype. Used in sorting out setup actions -#define H_TO_D 0x00 -#define D_TO_H 0x80 -#define VENDOR 0x40 -#define DEVREQ 0x00 -#define INTREQ 0x01 -#define ENDREQ 0x02 - -/// Definition of values in usbRequest, again used to sort out setup -#define GET_STATUS 0x00 -#define CLEAR_FEATURE 0x01 -#define SET_FEATURE 0x03 -#define SET_ADDRESS 0x05 -#define GET_DESC 0x06 -#define SET_DESC 0x07 -#define GET_CONF 0x08 -#define SET_CONF 0x09 -#define GET_INTERFACE 0x0a -#define SET_INTERFACE 0x0b -#define SYNCH_FRAME 0x0c - -/// Definitions of the various debug command codes understood by the 1401. These -/// are used in various vendor-specific commands to achieve the desired effect -#define DB_GRAB 0x50 /* Grab is a NOP for USB */ -#define DB_FREE 0x51 /* Free is a NOP for the USB */ -#define DB_SETADD 0x52 /* Set debug address (double) */ -#define DB_SELFTEST 0x53 /* Start self test */ -#define DB_SETMASK 0x54 /* Set enable mask (double) */ -#define DB_SETDEF 0x55 /* Set default mask (double) */ -#define DB_PEEK 0x56 /* Peek address, save result */ -#define DB_POKE 0x57 /* Poke address with data (double) */ -#define DB_RAMPD 0x58 /* Ramp data at debug address */ -#define DB_RAMPA 0x59 /* Ramp address bus */ -#define DB_REPEATS 0x5A /* Set repeats for operations (double) */ -#define DB_WIDTH 0x5B /* Set width for operations (byte) */ -#define DB_DATA 0x5C /* Get 4-byte data read by PEEK */ -#define DB_CHARS 0x5D /* Send chars via EP0 control write */ - -#define CR_CHAR 0x0D /* The carriage return character */ -#define CR_CHAR_80 0x8d /* and with bit 7 set */ - -/// A structure holding information about a block of memory for use in circular transfers -typedef struct circBlk -{ - volatile UINT dwOffset; /* Offset within area of block start */ - volatile UINT dwSize; /* Size of the block, in bytes (0 = unused) */ -} CIRCBLK; - -/// A structure holding all of the information about a transfer area - an area of -/// memory set up for use either as a source or destination in DMA transfers. -typedef struct transarea -{ - void* lpvBuff; // User address of xfer area saved for completeness - UINT dwBaseOffset; // offset to start of xfer area in first page - UINT dwLength; // Length of xfer area, in bytes - struct page **pPages; // Points at array of locked down pages - int nPages; // number of pages that are locked down - bool bUsed; // Is this structure in use? - bool bCircular; // Is this area for circular transfers? - bool bCircToHost; // Flag for direction of circular transfer - bool bEventToHost; // Set event on transfer to host? - int iWakeUp; // Set 1 on event, cleared by TestEvent() - UINT dwEventSt; // Defines section within xfer area for... - UINT dwEventSz; // ...notification by the event SZ is 0 if unset - CIRCBLK aBlocks[2]; // Info on a pair of circular blocks - wait_queue_head_t wqEvent; // The wait queue for events in this area MUST BE LAST -} TRANSAREA; - -/// The DMADESC structure is used to hold information on the transfer in progress. It -/// is set up by ReadDMAInfo, using information sent by the 1401 in an escape sequence. -typedef struct dmadesc -{ - unsigned short wTransType; /* transfer type as TM_xxx above */ - unsigned short wIdent; /* identifier word */ - unsigned int dwSize; /* bytes to transfer */ - unsigned int dwOffset; /* offset into transfer area for trans */ - bool bOutWard; /* true when data is going TO 1401 */ -} DMADESC; - -#define INBUF_SZ 256 /* input buffer size */ -#define OUTBUF_SZ 256 /* output buffer size */ -#define STAGED_SZ 0x10000 // size of coherent buffer for staged transfers - -/// Structure to hold all of our device specific stuff. We are making this as similar as we -/// can to the Windows driver to help in our understanding of what is going on. -typedef struct _DEVICE_EXTENSION -{ - char inputBuffer[INBUF_SZ]; /* The two buffers */ - char outputBuffer[OUTBUF_SZ]; /* accessed by the host functions */ - volatile unsigned int dwNumInput; /* num of chars in input buffer */ - volatile unsigned int dwInBuffGet; /* where to get from input buffer */ - volatile unsigned int dwInBuffPut; /* where to put into input buffer */ - volatile unsigned int dwNumOutput; /* num of chars in output buffer */ - volatile unsigned int dwOutBuffGet; /* where to get from output buffer*/ - volatile unsigned int dwOutBuffPut; /* where to put into output buffer*/ - - volatile bool bSendCharsPending; /* Flag to indicate sendchar active */ - volatile bool bReadCharsPending; /* Flag to indicate a read is primed */ - char* pCoherCharOut; /* special aligned buffer for chars to 1401 */ - struct urb* pUrbCharOut; /* urb used for chars to 1401 */ - char* pCoherCharIn; /* special aligned buffer for chars to host */ - struct urb* pUrbCharIn; /* urb used for chars to host */ - - spinlock_t charOutLock; /* to protect the outputBuffer and outputting */ - spinlock_t charInLock; /* to protect the inputBuffer and char reads */ - __u8 bInterval; /* Interrupt end point interval */ - - volatile unsigned int dwDMAFlag; /* state of DMA */ - TRANSAREA rTransDef[MAX_TRANSAREAS];/* transfer area info */ - volatile DMADESC rDMAInfo; // info on current DMA transfer - volatile bool bXFerWaiting; // Flag set if DMA transfer stalled - volatile bool bInDrawDown; // Flag that we want to halt transfers - - // Parameters relating to a block read\write that is in progress. Some of these values - // are equivalent to values in rDMAInfo. The values here are those in use, while those - // in rDMAInfo are those recieved from the 1401 via an escape sequence. If another - // escape sequence arrives before the previous xfer ends, rDMAInfo values are updated while these - // are used to finish off the current transfer. - volatile short StagedId; // The transfer area id for this transfer - volatile bool StagedRead; // Flag TRUE for read from 1401, FALSE for write - volatile unsigned int StagedLength; // Total length of this transfer - volatile unsigned int StagedOffset; // Offset within memory area for transfer start - volatile unsigned int StagedDone; // Bytes transferred so far - volatile bool bStagedUrbPending; // Flag to indicate active - char* pCoherStagedIO; // buffer used for block transfers - struct urb* pStagedUrb; // The URB to use - spinlock_t stagedLock; // protects ReadWriteMem() and circular buffer stuff - - short s1401Type; // type of 1401 attached - short sCurrentState; // current error state - bool bIsUSB2; // type of the interface we connect to - bool bForceReset; // Flag to make sure we get a real reset - __u32 statBuf[2]; // buffer for 1401 state info - - unsigned long ulSelfTestTime; // used to timeout self test - - int nPipes; // Should be 3 or 4 depending on 1401 usb chip - int bPipeError[4]; // set non-zero if an error on one of the pipe - __u8 epAddr[4]; // addresses of the 3/4 end points - - struct usb_device *udev; // the usb device for this device - struct usb_interface *interface; // the interface for this device, NULL if removed - struct usb_anchor submitted; // in case we need to retract our submissions - struct mutex io_mutex; // synchronize I/O with disconnect, one user-mode caller at a time - - int errors; // the last request tanked - int open_count; // count the number of openers - spinlock_t err_lock; // lock for errors - struct kref kref; -}DEVICE_EXTENSION, *PDEVICE_EXTENSION; -#define to_DEVICE_EXTENSION(d) container_of(d, DEVICE_EXTENSION, kref) - -/// Definitions of routimes used between compilation object files -// in usb1401.c -extern int Allowi(DEVICE_EXTENSION* pdx, bool bInCallback); -extern int SendChars(DEVICE_EXTENSION* pdx); -extern void ced_draw_down(DEVICE_EXTENSION *pdx); -extern int ReadWriteMem(DEVICE_EXTENSION *pdx, bool Read, unsigned short wIdent, - unsigned int dwOffs, unsigned int dwLen); - -// in ced_ioc.c -extern int ClearArea(DEVICE_EXTENSION *pdx, int nArea); -extern int SendString(DEVICE_EXTENSION* pdx, const char __user* pData, unsigned int n); -extern int SendChar(DEVICE_EXTENSION *pdx, char c); -extern int Get1401State(DEVICE_EXTENSION* pdx, __u32* state, __u32* error); -extern int ReadWrite_Cancel(DEVICE_EXTENSION *pdx); -extern bool Is1401(DEVICE_EXTENSION* pdx); -extern bool QuickCheck(DEVICE_EXTENSION* pdx, bool bTestBuff, bool bCanReset); -extern int Reset1401(DEVICE_EXTENSION *pdx); -extern int GetChar(DEVICE_EXTENSION *pdx); -extern int GetString(DEVICE_EXTENSION *pdx, char __user* pUser, int n); -extern int SetTransfer(DEVICE_EXTENSION *pdx, TRANSFERDESC __user *pTD); -extern int UnsetTransfer(DEVICE_EXTENSION *pdx, int nArea); -extern int SetEvent(DEVICE_EXTENSION *pdx, TRANSFEREVENT __user*pTE); -extern int Stat1401(DEVICE_EXTENSION *pdx); -extern int LineCount(DEVICE_EXTENSION *pdx); -extern int GetOutBufSpace(DEVICE_EXTENSION *pdx); -extern int GetTransfer(DEVICE_EXTENSION *pdx, TGET_TX_BLOCK __user *pGTB); -extern int KillIO1401(DEVICE_EXTENSION *pdx); -extern int BlkTransState(DEVICE_EXTENSION *pdx); -extern int StateOf1401(DEVICE_EXTENSION *pdx); -extern int StartSelfTest(DEVICE_EXTENSION *pdx); -extern int CheckSelfTest(DEVICE_EXTENSION *pdx, TGET_SELFTEST __user *pGST); -extern int TypeOf1401(DEVICE_EXTENSION *pdx); -extern int TransferFlags(DEVICE_EXTENSION *pdx); -extern int DbgPeek(DEVICE_EXTENSION *pdx, TDBGBLOCK __user* pDB); -extern int DbgPoke(DEVICE_EXTENSION *pdx, TDBGBLOCK __user *pDB); -extern int DbgRampData(DEVICE_EXTENSION *pdx, TDBGBLOCK __user *pDB); -extern int DbgRampAddr(DEVICE_EXTENSION *pdx, TDBGBLOCK __user *pDB); -extern int DbgGetData(DEVICE_EXTENSION *pdx, TDBGBLOCK __user *pDB); -extern int DbgStopLoop(DEVICE_EXTENSION *pdx); -extern int SetCircular(DEVICE_EXTENSION *pdx, TRANSFERDESC __user *pTD); -extern int GetCircBlock(DEVICE_EXTENSION *pdx, TCIRCBLOCK __user* pCB); -extern int FreeCircBlock(DEVICE_EXTENSION *pdx, TCIRCBLOCK __user* pCB); -extern int WaitEvent(DEVICE_EXTENSION *pdx, int nArea, int msTimeOut); -extern int TestEvent(DEVICE_EXTENSION *pdx, int nArea); -#endif diff --git a/trunk/drivers/staging/ced1401/use1401.h b/trunk/drivers/staging/ced1401/use1401.h deleted file mode 100644 index 86294e21db0c..000000000000 --- a/trunk/drivers/staging/ced1401/use1401.h +++ /dev/null @@ -1,287 +0,0 @@ -/**************************************************************************** -** use1401.h -** Copyright (C) Cambridge Electronic Design Ltd, 1992-2010 -** Authors: Paul Cox, Tim Bergel, Greg Smith -** See CVS for revisions. -** -** Because the size of a long is different between 32-bit and 64-bit on some -** systems, we avoid this in this interface. -****************************************************************************/ -#ifndef __USE1401_H__ -#define __USE1401_H__ -#include "machine.h" - -// Some definitions to make things compatible. If you want to use Use1401 directly -// from a Windows program you should define U14_NOT_DLL, in which case you also -// MUST make sure that your application startup code calls U14InitLib(). -// DLL_USE1401 is defined when you are building the Use1401 dll, not otherwise. -#ifdef _IS_WINDOWS_ -#ifndef U14_NOT_DLL -#ifdef DLL_USE1401 -#define U14API(retType) retType DllExport __stdcall -#else -#define U14API(retType) retType DllImport __stdcall -#endif -#endif - -#define U14ERRBASE -500 -#define U14LONG long -#endif - -#ifdef LINUX -#define U14ERRBASE -1000 -#define U14LONG int -#endif - -#ifdef _QT -#ifndef U14_NOT_DLL -#undef U14API -#define U14API(retType) retType __declspec(dllimport) __stdcall -#endif -#undef U14LONG -#define U14LONG int -#endif - -#ifndef U14API -#define U14API(retType) retType -#endif - -#ifndef U14LONG -#define U14LONG long -#endif - -/// Error codes: We need them here as user space can see them. -#define U14ERR_NOERROR 0 // no problems - -/// Device error codes, but these don't need to be extended - a succession is assumed -#define U14ERR_STD 4 // standard 1401 connected -#define U14ERR_U1401 5 // u1401 connected -#define U14ERR_PLUS 6 // 1401 plus connected -#define U14ERR_POWER 7 // Power1401 connected -#define U14ERR_U14012 8 // u1401 mkII connected -#define U14ERR_POWER2 9 -#define U14ERR_U14013 10 -#define U14ERR_POWER3 11 - -/// NBNB Error numbers need shifting as some linux error codes start at 512 -#define U14ERR(n) (n+U14ERRBASE) -#define U14ERR_OFF U14ERR(0) /* 1401 there but switched off */ -#define U14ERR_NC U14ERR(-1) /* 1401 not connected */ -#define U14ERR_ILL U14ERR(-2) /* if present it is ill */ -#define U14ERR_NOIF U14ERR(-3) /* I/F card missing */ -#define U14ERR_TIME U14ERR(-4) /* 1401 failed to come ready */ -#define U14ERR_BADSW U14ERR(-5) /* I/F card bad switches */ -#define U14ERR_PTIME U14ERR(-6) /* 1401plus failed to come ready */ -#define U14ERR_NOINT U14ERR(-7) /* couldn't grab the int vector */ -#define U14ERR_INUSE U14ERR(-8) /* 1401 is already in use */ -#define U14ERR_NODMA U14ERR(-9) /* couldn't get DMA channel */ -#define U14ERR_BADHAND U14ERR(-10) /* handle provided was bad */ -#define U14ERR_BAD1401NUM U14ERR(-11) /* 1401 number provided was bad */ - -#define U14ERR_NO_SUCH_FN U14ERR(-20) /* no such function */ -#define U14ERR_NO_SUCH_SUBFN U14ERR(-21) /* no such sub function */ -#define U14ERR_NOOUT U14ERR(-22) /* no room in output buffer */ -#define U14ERR_NOIN U14ERR(-23) /* no input in buffer */ -#define U14ERR_STRLEN U14ERR(-24) /* string longer than buffer */ -#define U14ERR_ERR_STRLEN U14ERR(-24) /* string longer than buffer */ -#define U14ERR_LOCKFAIL U14ERR(-25) /* failed to lock memory */ -#define U14ERR_UNLOCKFAIL U14ERR(-26) /* failed to unlock memory */ -#define U14ERR_ALREADYSET U14ERR(-27) /* area already set up */ -#define U14ERR_NOTSET U14ERR(-28) /* area not set up */ -#define U14ERR_BADAREA U14ERR(-29) /* illegal area number */ -#define U14ERR_FAIL U14ERR(-30) /* we failed for some other reason*/ - -#define U14ERR_NOFILE U14ERR(-40) /* command file not found */ -#define U14ERR_READERR U14ERR(-41) /* error reading command file */ -#define U14ERR_UNKNOWN U14ERR(-42) /* unknown command */ -#define U14ERR_HOSTSPACE U14ERR(-43) /* not enough host space to load */ -#define U14ERR_LOCKERR U14ERR(-44) /* could not lock resource/command*/ -#define U14ERR_CLOADERR U14ERR(-45) /* CLOAD command failed */ - -#define U14ERR_TOXXXERR U14ERR(-60) /* tohost/1401 failed */ -#define U14ERR_NO386ENH U14ERR(-80) /* not 386 enhanced mode */ -#define U14ERR_NO1401DRIV U14ERR(-81) /* no device driver */ -#define U14ERR_DRIVTOOOLD U14ERR(-82) /* device driver too old */ - -#define U14ERR_TIMEOUT U14ERR(-90) /* timeout occurred */ - -#define U14ERR_BUFF_SMALL U14ERR(-100) /* buffer for getstring too small */ -#define U14ERR_CBALREADY U14ERR(-101) /* there is already a callback */ -#define U14ERR_BADDEREG U14ERR(-102) /* bad parameter to deregcallback */ -#define U14ERR_NOMEMORY U14ERR(-103) /* no memory for allocation */ - -#define U14ERR_DRIVCOMMS U14ERR(-110) /* failed talking to driver */ -#define U14ERR_OUTOFMEMORY U14ERR(-111) /* needed memory and couldnt get it*/ - -/// 1401 type codes. -#define U14TYPE1401 0 /* standard 1401 */ -#define U14TYPEPLUS 1 /* 1401 plus */ -#define U14TYPEU1401 2 /* u1401 */ -#define U14TYPEPOWER 3 /* power1401 */ -#define U14TYPEU14012 4 /* u1401 mk II */ -#define U14TYPEPOWER2 5 /* power1401 mk II */ -#define U14TYPEU14013 6 /* u1401-3 */ -#define U14TYPEPOWER3 7 /* power1401-3 */ -#define U14TYPEUNKNOWN -1 /* dont know */ - -/// Transfer flags to allow driver capabilities to be interrogated - -/// Constants for transfer flags -#define U14TF_USEDMA 1 /* Transfer flag for use DMA */ -#define U14TF_MULTIA 2 /* Transfer flag for multi areas */ -#define U14TF_FIFO 4 /* for FIFO interface card */ -#define U14TF_USB2 8 /* for USB2 interface and 1401 */ -#define U14TF_NOTIFY 16 /* for event notifications */ -#define U14TF_SHORT 32 /* for PCI can short cycle */ -#define U14TF_PCI2 64 /* for new PCI card 1401-70 */ -#define U14TF_CIRCTH 128 /* Circular-mode to host */ -#define U14TF_DIAG 256 /* Diagnostics/debug functions */ -#define U14TF_CIRC14 512 /* Circular-mode to 1401 */ - -/// Definitions of element sizes for DMA transfers - to allow byte-swapping -#define ESZBYTES 0 /* BYTE element size value */ -#define ESZWORDS 1 /* WORD element size value */ -#define ESZLONGS 2 /* long element size value */ -#define ESZUNKNOWN 0 /* unknown element size value */ - -/// These define required access types for the debug/diagnostics function -#define BYTE_SIZE 1 /* 8-bit access */ -#define WORD_SIZE 2 /* 16-bit access */ -#define LONG_SIZE 3 /* 32-bit access */ - -/// Stuff used by U14_GetTransfer -#define GET_TX_MAXENTRIES 257 /* (max length / page size + 1) */ - -#ifdef _IS_WINDOWS_ -#pragma pack(1) - -typedef struct /* used for U14_GetTransfer results */ -{ /* Info on a single mapped block */ - U14LONG physical; - U14LONG size; -} TXENTRY; - -typedef struct TGetTxBlock /* used for U14_GetTransfer results */ -{ /* matches structure in VXD */ - U14LONG size; - U14LONG linear; - short seg; - short reserved; - short avail; /* number of available entries */ - short used; /* number of used entries */ - TXENTRY entries[GET_TX_MAXENTRIES]; /* Array of mapped block info */ -} TGET_TX_BLOCK; - -typedef TGET_TX_BLOCK *LPGET_TX_BLOCK; - -#pragma pack() -#endif - -#ifdef LINUX -typedef struct /* used for U14_GetTransfer results */ -{ /* Info on a single mapped block */ - long long physical; - long size; -} TXENTRY; - -typedef struct TGetTxBlock /* used for U14_GetTransfer results */ -{ /* matches structure in VXD */ - long long linear; /* linear address */ - long size; /* total size of the mapped area, holds id when called */ - short seg; /* segment of the address for Win16 */ - short reserved; - short avail; /* number of available entries */ - short used; /* number of used entries */ - TXENTRY entries[GET_TX_MAXENTRIES]; /* Array of mapped block info */ -} TGET_TX_BLOCK; -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -U14API(int) U14WhenToTimeOut(short hand); // when to timeout in ms -U14API(short) U14PassedTime(int iTime); // non-zero if iTime passed - -U14API(short) U14LastErrCode(short hand); - -U14API(short) U14Open1401(short n1401); -U14API(short) U14Close1401(short hand); -U14API(short) U14Reset1401(short hand); -U14API(short) U14ForceReset(short hand); -U14API(short) U14TypeOf1401(short hand); -U14API(short) U14NameOf1401(short hand, char* pBuf, WORD wMax); - -U14API(short) U14Stat1401(short hand); -U14API(short) U14CharCount(short hand); -U14API(short) U14LineCount(short hand); - -U14API(short) U14SendString(short hand, const char* pString); -U14API(short) U14GetString(short hand, char* pBuffer, WORD wMaxLen); -U14API(short) U14SendChar(short hand, char cChar); -U14API(short) U14GetChar(short hand, char* pcChar); - -U14API(short) U14LdCmd(short hand, const char* command); -U14API(DWORD) U14Ld(short hand, const char* vl, const char* str); - -U14API(short) U14SetTransArea(short hand, WORD wArea, void *pvBuff, - DWORD dwLength, short eSz); -U14API(short) U14UnSetTransfer(short hand, WORD wArea); -U14API(short) U14SetTransferEvent(short hand, WORD wArea, BOOL bEvent, - BOOL bToHost, DWORD dwStart, DWORD dwLength); -U14API(int) U14TestTransferEvent(short hand, WORD wArea); -U14API(int) U14WaitTransferEvent(short hand, WORD wArea, int msTimeOut); -U14API(short) U14GetTransfer(short hand, TGET_TX_BLOCK *pTransBlock); - -U14API(short) U14ToHost(short hand, char* pAddrHost,DWORD dwSize,DWORD dw1401, - short eSz); -U14API(short) U14To1401(short hand, const char* pAddrHost,DWORD dwSize,DWORD dw1401, - short eSz); - -U14API(short) U14SetCircular(short hand, WORD wArea, BOOL bToHost, void *pvBuff, - DWORD dwLength); - -U14API(int) U14GetCircBlk(short hand, WORD wArea, DWORD *pdwOffs); -U14API(int) U14FreeCircBlk(short hand, WORD wArea, DWORD dwOffs, DWORD dwSize, - DWORD *pdwOffs); - -U14API(short) U14StrToLongs(const char* pszBuff, U14LONG *palNums, short sMaxLongs); -U14API(short) U14LongsFrom1401(short hand, U14LONG *palBuff, short sMaxLongs); - -U14API(void) U14SetTimeout(short hand, int lTimeout); -U14API(int) U14GetTimeout(short hand); -U14API(short) U14OutBufSpace(short hand); -U14API(int) U14BaseAddr1401(short hand); -U14API(int) U14DriverVersion(short hand); -U14API(int) U14DriverType(short hand); -U14API(short) U14DriverName(short hand, char* pBuf, WORD wMax); -U14API(short) U14GetUserMemorySize(short hand, DWORD *pMemorySize); -U14API(short) U14KillIO1401(short hand); - -U14API(short) U14BlkTransState(short hand); -U14API(short) U14StateOf1401(short hand); - -U14API(short) U14Grab1401(short hand); -U14API(short) U14Free1401(short hand); -U14API(short) U14Peek1401(short hand, DWORD dwAddr, int nSize, int nRepeats); -U14API(short) U14Poke1401(short hand, DWORD dwAddr, DWORD dwValue, int nSize, int nRepeats); -U14API(short) U14Ramp1401(short hand, DWORD dwAddr, DWORD dwDef, DWORD dwEnable, int nSize, int nRepeats); -U14API(short) U14RampAddr(short hand, DWORD dwDef, DWORD dwEnable, int nSize, int nRepeats); -U14API(short) U14StopDebugLoop(short hand); -U14API(short) U14GetDebugData(short hand, U14LONG *plValue); - -U14API(short) U14StartSelfTest(short hand); -U14API(short) U14CheckSelfTest(short hand, U14LONG *pData); -U14API(short) U14TransferFlags(short hand); -U14API(void) U14GetErrorString(short nErr, char* pStr, WORD wMax); -U14API(int) U14MonitorRev(short hand); -U14API(void) U14CloseAll(void); - -U14API(short) U14WorkingSet(DWORD dwMinKb, DWORD dwMaxKb); -U14API(int) U14InitLib(void); - -#ifdef __cplusplus -} -#endif - -#endif /* End of ifndef __USE1401_H__ */ diff --git a/trunk/drivers/staging/ced1401/use14_ioc.h b/trunk/drivers/staging/ced1401/use14_ioc.h deleted file mode 100644 index 15ca63888380..000000000000 --- a/trunk/drivers/staging/ced1401/use14_ioc.h +++ /dev/null @@ -1,301 +0,0 @@ -/* use14_ioc.h -** definitions of use1401 module stuff that is shared between use1401 and the driver. -** Copyright (C) Cambridge Electronic Design Limited 2010 -** Author Greg P Smith -************************************************************************************/ -#ifndef __USE14_IOC_H__ -#define __USE14_IOC_H__ - -#define MAX_TRANSAREAS 8 /* The number of transfer areas supported by driver */ - -#define i386 -#include "winioctl.h" /* needed so we can access driver */ - -/* -** Defines for IOCTL functions to ask driver to perform. These must be matched -** in both use1401 and in the driver. The IOCTL code contains a command -** identifier, plus other information about the device, the type of access -** with which the file must have been opened, and the type of buffering. -** The IOCTL function codes from 0x80 to 0xFF are for developer use. -*/ -#define FILE_DEVICE_CED1401 0x8001 -#define FNNUMBASE 0x800 - -#define U14_OPEN1401 CTL_CODE( FILE_DEVICE_CED1401, \ - FNNUMBASE, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - -#define U14_CLOSE1401 CTL_CODE( FILE_DEVICE_CED1401, \ - FNNUMBASE+1, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - -#define U14_SENDSTRING CTL_CODE( FILE_DEVICE_CED1401, \ - FNNUMBASE+2, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - -#define U14_RESET1401 CTL_CODE( FILE_DEVICE_CED1401, \ - FNNUMBASE+3, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - -#define U14_GETCHAR CTL_CODE( FILE_DEVICE_CED1401, \ - FNNUMBASE+4, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - -#define U14_SENDCHAR CTL_CODE( FILE_DEVICE_CED1401, \ - FNNUMBASE+5, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - -#define U14_STAT1401 CTL_CODE( FILE_DEVICE_CED1401, \ - FNNUMBASE+6, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - -#define U14_LINECOUNT CTL_CODE( FILE_DEVICE_CED1401, \ - FNNUMBASE+7, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - -#define U14_GETSTRING CTL_CODE( FILE_DEVICE_CED1401, \ - FNNUMBASE+8, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - -#define U14_REGCALLBACK CTL_CODE( FILE_DEVICE_CED1401, \ - FNNUMBASE+9, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - -#define U14_GETMONITORBUF CTL_CODE( FILE_DEVICE_CED1401, \ - FNNUMBASE+10, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - -#define U14_SETTRANSFER CTL_CODE( FILE_DEVICE_CED1401, \ - FNNUMBASE+11, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - -#define U14_UNSETTRANSFER CTL_CODE( FILE_DEVICE_CED1401, \ - FNNUMBASE+12, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - -#define U14_SETTRANSEVENT CTL_CODE( FILE_DEVICE_CED1401, \ - FNNUMBASE+13, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - -#define U14_GETOUTBUFSPACE CTL_CODE( FILE_DEVICE_CED1401, \ - FNNUMBASE+14, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - -#define U14_GETBASEADDRESS CTL_CODE( FILE_DEVICE_CED1401, \ - FNNUMBASE+15, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - -#define U14_GETDRIVERREVISION CTL_CODE( FILE_DEVICE_CED1401, \ - FNNUMBASE+16, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - -#define U14_GETTRANSFER CTL_CODE( FILE_DEVICE_CED1401, \ - FNNUMBASE+17, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - -#define U14_KILLIO1401 CTL_CODE( FILE_DEVICE_CED1401, \ - FNNUMBASE+18, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - -#define U14_BLKTRANSSTATE CTL_CODE( FILE_DEVICE_CED1401, \ - FNNUMBASE+19, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - -#define U14_BYTECOUNT CTL_CODE( FILE_DEVICE_CED1401, \ - FNNUMBASE+20, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - -#define U14_ZEROBLOCKCOUNT CTL_CODE( FILE_DEVICE_CED1401, \ - FNNUMBASE+21, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - -#define U14_STOPCIRCULAR CTL_CODE( FILE_DEVICE_CED1401, \ - FNNUMBASE+22, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - -#define U14_STATEOF1401 CTL_CODE( FILE_DEVICE_CED1401, \ - FNNUMBASE+23, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - -#define U14_REGISTERS1401 CTL_CODE( FILE_DEVICE_CED1401, \ - FNNUMBASE+24, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - -#define U14_GRAB1401 CTL_CODE( FILE_DEVICE_CED1401, \ - FNNUMBASE+25, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - -#define U14_FREE1401 CTL_CODE( FILE_DEVICE_CED1401, \ - FNNUMBASE+26, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - -#define U14_STEP1401 CTL_CODE( FILE_DEVICE_CED1401, \ - FNNUMBASE+27, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - -#define U14_SET1401REGISTERS CTL_CODE( FILE_DEVICE_CED1401, \ - FNNUMBASE+28, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - -#define U14_STEPTILL1401 CTL_CODE( FILE_DEVICE_CED1401, \ - FNNUMBASE+29, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - -#define U14_SETORIN CTL_CODE( FILE_DEVICE_CED1401, \ - FNNUMBASE+30, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - -#define U14_STARTSELFTEST CTL_CODE( FILE_DEVICE_CED1401, \ - FNNUMBASE+31, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - -#define U14_CHECKSELFTEST CTL_CODE( FILE_DEVICE_CED1401, \ - FNNUMBASE+32, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - -#define U14_TYPEOF1401 CTL_CODE( FILE_DEVICE_CED1401, \ - FNNUMBASE+33, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - -#define U14_TRANSFERFLAGS CTL_CODE( FILE_DEVICE_CED1401, \ - FNNUMBASE+34, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - -#define U14_DBGPEEK CTL_CODE( FILE_DEVICE_CED1401, \ - FNNUMBASE+35, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - -#define U14_DBGPOKE CTL_CODE( FILE_DEVICE_CED1401, \ - FNNUMBASE+36, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - -#define U14_DBGRAMPDATA CTL_CODE( FILE_DEVICE_CED1401, \ - FNNUMBASE+37, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - -#define U14_DBGRAMPADDR CTL_CODE( FILE_DEVICE_CED1401, \ - FNNUMBASE+38, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - -#define U14_DBGGETDATA CTL_CODE( FILE_DEVICE_CED1401, \ - FNNUMBASE+39, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - -#define U14_DBGSTOPLOOP CTL_CODE( FILE_DEVICE_CED1401, \ - FNNUMBASE+40, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - -#define U14_FULLRESET CTL_CODE( FILE_DEVICE_CED1401, \ - FNNUMBASE+41, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - -#define U14_SETCIRCULAR CTL_CODE( FILE_DEVICE_CED1401, \ - FNNUMBASE+42, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - -#define U14_GETCIRCBLK CTL_CODE( FILE_DEVICE_CED1401, \ - FNNUMBASE+43, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - -#define U14_FREECIRCBLK CTL_CODE( FILE_DEVICE_CED1401, \ - FNNUMBASE+44, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - -//--------------- Structures that are shared with the driver ------------- -#pragma pack(1) - -typedef struct /* used for get/set standard 1401 registers */ -{ - short sPC; - char A; - char X; - char Y; - char stat; - char rubbish; -} T1401REGISTERS; - -typedef union /* to communicate with 1401 driver status & control funcs */ -{ - char chrs[22]; - short ints[11]; - long longs[5]; - T1401REGISTERS registers; -} TCSBLOCK; - -typedef TCSBLOCK* LPTCSBLOCK; - -typedef struct paramBlk -{ - short sState; - TCSBLOCK csBlock; -} PARAMBLK; - -typedef PARAMBLK* PPARAMBLK; - -typedef struct TransferDesc /* Structure and type for SetTransArea */ -{ - WORD wArea; /* number of transfer area to set up */ - void FAR * lpvBuff; /* address of transfer area */ - DWORD dwLength; /* length of area to set up */ - short eSize; /* size to move (for swapping on MAC) */ -} TRANSFERDESC; - -typedef TRANSFERDESC FAR * LPTRANSFERDESC; - -/* This is the structure used to set up a transfer area */ -typedef struct VXTransferDesc /* use1401.c and use1432x.x use only */ -{ - WORD wArea; /* number of transfer area to set up */ - WORD wAddrSel; /* 16 bit selector for area */ - DWORD dwAddrOfs; /* 32 bit offset for area start */ - DWORD dwLength; /* length of area to set up */ -} VXTRANSFERDESC; - -#pragma pack() - -#endif \ No newline at end of file diff --git a/trunk/drivers/staging/ced1401/userspace/use1401.c b/trunk/drivers/staging/ced1401/userspace/use1401.c deleted file mode 100644 index d4c63168ea27..000000000000 --- a/trunk/drivers/staging/ced1401/userspace/use1401.c +++ /dev/null @@ -1,3035 +0,0 @@ -/**************************************************************************** -** use1401.c -** Copyright (C) Cambridge Electronic Design Ltd, 1992-2010 -** -** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -** -** Contact CED: Cambridge Electronic Design Limited, Science Park, Milton Road -** Cambridge, CB6 0FE. -** www.ced.co.uk -** greg@ced.co.uk -** -** Title: USE1401.C -** Version: 4.00 -** Author: Paul Cox, Tim Bergel, Greg Smith -** -** The code was vigorously pruned in DEC 2010 to remove the macintosh options -** and to get rid of the 16-bit support. It has also been aligned with the -** Linux version. See CVS for revisions. This will work for Win 9x onwards. -**************************************************************************** -** -** Notes on Windows interface to driver -** ************************************ -** -** Under Windows 9x and NT, Use1401 uses DeviceIoControl to get access to -** the 1401 driver. This has parameters for the device handle, the function -** code, an input pointer and byte count, an output pointer and byte count -** and a pointer to a DWORD to hold the output byte count. Note that input -** and output are from the point-of-view of the driver, so the output stuff -** is used to read values from the 1401, not send to the 1401. The use of -** these parameters varies with the function in use and the operating -** system; there are five separate DIOC calls SendString, GetString and -** SetTransferArea all have their own specialised calls, the rest use the -** Status1401 or Control1401 functions. -** -** There are two basic styles of DIOC call used, one for Win9x VxD drivers -** and one for NT Kernel-mode and WDM drivers (see below for tables showing -** the different parameters used. The array bUseNTDIOC[] selects between -** these two calling styles. -** -** Function codes -** In Win3.x, simple function codes from 0 to 40 were used, shifted left 8 -** bits with a sub-function code in the lower 8 bits. These were also used -** in the Windows 95 driver, though we had to add 1 to the code value to -** avoid problems (Open from CreateFile is zero), and the sub-function code -** is now unused. We found that this gave some problems with Windows 98 -** as the function code values are reserved by microsoft, so we switched to -** using the NT function codes instead. The NT codes are generated using the -** CTL_CODE macro, essentially this gives 0x80012000 | (func << 2), where -** func is the original 0 to 34 value. The driver will handle both types of -** code and Use1432 only uses the NT codes if it knows the driver is new -** enough. The array bUseNTCodes[] holds flags on the type of codes required. -** GPS/TDB Dec 2010: we removed the bUseNTCodes array as this is always true -** as we no longer support ancient versions. -** -** The CreateFile and CloseFile function calls are also handled -** by DIOC, using the special function codes 0 and -1 respectively. -** -** Input pointer and buffer size -** These are intended for data sent to the device driver. In nearly all cases -** they are unused in calls to the Win95 driver, the NT driver uses them -** for all information sent to the driver. The table below shows the pointer -** and byte count used for the various calls: -** -** Win 95 Win NT -** SendString NULL, 0 pStr, nStr -** GetString NULL, 0 NULL, 0 -** SetTransferArea pBuf, nBuf (unused?) pDesc, nDesc -** GetTransfer NULL, 0 NULL, 0 -** Status1401 NULL, 0 NULL, 0 -** Control1401 NULL, 0 pBlk, nBlk -** -** pStr and nStr are pointers to a char buffer and the buffer length for -** string I/O, note that these are temporary buffers owned by the DLL, not -** application memory, pBuf and nBuf are the transfer area buffer (I think -** these are unused), pDesc and nDesc are the TRANSFERDESC structure, pBlk -** and nBlk are the TCSBLOCK structure. -** -** -** Output pointer and buffer size -** These are intended for data read from the device driver. These are used -** for almost all information sent to the Win95 driver, the NT driver uses -** them for information read from the driver, chiefly the error code. The -** table below shows the pointer and byte count used for the various calls: -** -** Win 95 Win NT -** SendString pStr, nStr pPar, nPar -** GetString pStr, nStr+2 pStr, nStr+2 -** SetTransferArea pDesc, nDesc pPar, nPar -** GetTransfer pGet, nGet pGet, nGet -** Status1401 pBlk, nBlk pPar, nPar -** Control1401 pBlk, nBlk pPar, nPar -** -** pStr and nStr are pointers to a char buffer and the buffer length for -** string I/O, the +2 for GetString refers to two spare bytes at the start -** used to hold the string length and returning an error code for NT. Note -** again that these are (and must be) DLL-owned temporary buffers. pPar -** and nPar are a PARAM structure used in NT (it holds an error code and a -** TCSBLOCK structure). pDesc and nDesc are the VXTRANSFERDESC structure, -** pBlk and nBlk are the TCSBLOCK structure. pGet and nGet indicate the -** TGET_TX_BLOCK structure used for GetTransfer. -** -** -** The output byte count -** Both drivers return the output buffer size here, regardless of the actual -** bytes output. This is used to check that we did get through to the driver. -** -** Multiple 1401s -** ************** -** -** We have code that tries to support the use of multiple 1401s, but there -** are problems: The lDriverVersion and lDriverType variables are global, not -** per-1401 (a particular problem as the U14 functions that use them don't -** have a hand parameter). In addition, the mechansim for finding a free -** 1401 depends upon the 1401 device driver open operation failing if it's -** already in use, which doesn't always happen, particularly with the VxDs. -** The code in TryToOpen tries to fix this by relying on TYPEOF1401 to detect -** the 1401-in-use state - the VxDs contain special code to help this. This is -** working OK but multiple 1401 support works better with the Win2000 drivers. -** -** USB driver -** ********** -** -** The USB driver, which runs on both Win98 and NT2000, uses the NT-style -** calling convention, both for the DIOC codes and the DIOC parameters. The -** TryToOpen function has been altered to look for an NT driver first in -** the appropriate circumstances, and to set the driver DIOC flags up in -** the correct state. -** -** Adding a new 1401 type - now almost nothing to do -** ************************************************* -** -** The 1401 types are defined by a set of U14TYPExxxx codes in USE1401.H. -** You should add a new one of these to keep things tidy for applications. -** -** DRIVERET_MAX (below) specifies the maximum allowed type code from the -** 1401 driver; I have set this high to accomodate as yet undesigned 1401 -** types. Similarly, as long as the command file names follow the ARM, -** ARN, ARO sequence, these are calculated by the ExtForType function, so -** you don't need to do anything here either. -** -** Version number -** ************** -** The new U14InitLib() function returns 0 if the OS is incapable of use, -** otherwise is returns the version of the USE1401 library. This is done -** in three parts: Major(31-24).Minor(23-16).Revision.(15-0) (brackets are -** the bits used). The Major number starts at 2 for the first revision with -** the U14InitLib() function. Changes to the Major version means that we -** have broken backwards compatibility. Minor number changes mean that we -** have added new functionality that does not break backwards compatibility. -** we starts at 0. Revision changes mean we have fixed something. Each index -** returns to 0 when a higer one changes. -*/ -#define U14LIB_MAJOR 4 -#define U14LIB_MINOR 0 -#define U14LIB_REVISION 0 -#define U14LIB_VERSION ((U14LIB_MAJOR<<24) | (U14LIB_MINOR<<16) | U14LIB_REVISION) - -#include -#include -#include - -#include "USE1401.H" - -#ifdef _IS_WINDOWS_ -#include -#include -#pragma warning(disable: 4100) /* Disable "Unused formal parameter" warning */ -#include -#include "process.h" - - -#define sprintf wsprintf -#define PATHSEP '\\' -#define PATHSEPSTR "\\" -#define DEFCMDPATH "\\1401\\" // default command path if all else fails -#define MINDRIVERMAJREV 1 // minimum driver revision level we need -#define __packed // does nothing in Windows - -#include "use14_ioc.h" // links to device driver stuff -#endif - -#ifdef LINUX -#include -#include -#include -#include -#include -#include -#include -#define PATHSEP '/' -#define PATHSEPSTR "/" -#define DEFCMDPATH "/var/1401/" // default command path if all else fails -#define MINDRIVERMAJREV 2 // minimum driver revision level we need - -#include "ced_ioctl.h" // links to device driver stuff -#endif - -#define MAX1401 8 // The number of 1401s that can be supported - -/* -** These are the 1401 type codes returned by the driver, they are a slightly -** odd sequence & start for reasons of compatability with the DOS driver. -** The maximum code value is the upper limit of 1401 device types. -*/ -#define DRIVRET_STD 4 // Codes for 1401 types matching driver values -#define DRIVRET_U1401 5 // This table does not need extending, as -#define DRIVRET_PLUS 6 // we can calculate values now. -#define DRIVRET_POWER 7 // but we need all of these values still -#define DRIVRET_MAX 26 // Maximum tolerated code - future designs - -/* -** These variables store data that will be used to generate the last -** error string. For now, a string will hold the 1401 command file name. -*/ -static char szLastName[20]; // additional text information - -/* -** Information stored per handle. NBNB, driverType and DriverVersion used to be -** only stored once for all handles... i.e. nonsensical. This change means that -** three U14...() calls now include handles that were previously void. We have -** set a constructor and a destructor call for the library (see the end) to -** initialise important structures, or call use1401_load(). -*/ -static short asDriverType[MAX1401] = {0}; -static int lLastDriverVersion = U14ERR_NO1401DRIV; -static int lLastDriverType = U14TYPEUNKNOWN; -static int alDriverVersion[MAX1401]; // version/type of each driver -static int alTimeOutPeriod[MAX1401]; // timeout time in milliseconds -static short asLastRetCode[MAX1401]; // last code from a fn call -static short asType1401[MAX1401] = {0}; // The type of the 1401 -static BOOL abGrabbed[MAX1401] = {0}; // Flag for grabbed, set true by grab1401 -static int iAttached = 0; // counts process attaches so can let go - -#ifdef _IS_WINDOWS_ -/**************************************************************************** -** Windows NT Specific Variables and internal types -****************************************************************************/ -static HANDLE aHand1401[MAX1401] = {0}; // handles for 1401s -static HANDLE aXferEvent[MAX1401] = {0}; // transfer events for the 1401s -static LPVOID apAreas[MAX1401][MAX_TRANSAREAS]; // Locked areas -static DWORD auAreas[MAX1401][MAX_TRANSAREAS]; // Size of locked areas -static BOOL bWindows9x = FALSE; // if we are Windows 95 or better -#ifdef _WIN64 -#define USE_NT_DIOC(ind) TRUE -#else -static BOOL abUseNTDIOC[MAX1401]; // Use NT-style DIOC parameters */ -#define USE_NT_DIOC(ind) abUseNTDIOC[ind] -#endif - -#endif - -#ifdef LINUX -static int aHand1401[MAX1401] = {0}; // handles for 1401s -#define INVALID_HANDLE_VALUE 0 // to avoid code differences -#endif - - -/* -** The CmdHead relates to backwards compatibility with ancient Microsoft (and Sperry!) -** versions of BASIC, where this header was needed so we could load a command into -** memory. -*/ -#pragma pack(1) // pack our structure -typedef struct CmdHead // defines header block on command -{ // for PC commands - char acBasic[5]; // BASIC information - needed to align things - WORD wBasicSz; // size as seen by BASIC - WORD wCmdSize; // size of the following info -} __packed CMDHEAD; -#pragma pack() // back to normal - -/* -** The rest of the header looks like this... -** int iRelPnt; relocation pointer... actual start -** char acName[8]; string holding the command name -** BYTE bMonRev; monitor revision level -** BYTE bCmdRev; command revision level -*/ - -typedef CMDHEAD *LPCMDHEAD; // pointer to a command header - -#define MAXSTRLEN 255 // maximum string length we use -#define TOHOST FALSE -#define TO1401 TRUE - -static short CheckHandle(short h) -{ - if ((h < 0) || (h >= MAX1401)) // must be legal range... - return U14ERR_BADHAND; - if (aHand1401[h] <= 0) // must be open - return U14ERR_BADHAND; - return U14ERR_NOERROR; -} - -#ifdef _IS_WINDOWS_ -/**************************************************************************** -** U14Status1401 Used for functions which do not pass any data in but -** get data back -****************************************************************************/ -static short U14Status1401(short sHand, LONG lCode, TCSBLOCK* pBlk) -{ - DWORD dwBytes = 0; - - if ((sHand < 0) || (sHand >= MAX1401)) /* Check parameters */ - return U14ERR_BADHAND; -#ifndef _WIN64 - if (!USE_NT_DIOC(sHand)) - { /* Windows 9x DIOC methods? */ - if (DeviceIoControl(aHand1401[sHand], lCode, NULL, 0, pBlk,sizeof(TCSBLOCK),&dwBytes,NULL)) - return (short)((dwBytes>=sizeof(TCSBLOCK)) ? U14ERR_NOERROR : U14ERR_DRIVCOMMS); - else - return (short)GetLastError(); - } - else -#endif - { /* Windows NT or USB driver */ - PARAMBLK rWork; - rWork.sState = U14ERR_DRIVCOMMS; - if (DeviceIoControl(aHand1401[sHand], lCode, NULL, 0, &rWork,sizeof(PARAMBLK),&dwBytes,NULL) && - (dwBytes >= sizeof(PARAMBLK))) - { - *pBlk = rWork.csBlock; - return rWork.sState; - } - } - - return U14ERR_DRIVCOMMS; -} - -/**************************************************************************** -** U14Control1401 Used for functions which pass data in and only expect -** an error code back -****************************************************************************/ -static short U14Control1401(short sHand, LONG lCode, TCSBLOCK* pBlk) -{ - DWORD dwBytes = 0; - - if ((sHand < 0) || (sHand >= MAX1401)) /* Check parameters */ - return U14ERR_BADHAND; - -#ifndef _WIN64 - if (!USE_NT_DIOC(sHand)) - { /* Windows 9x DIOC methods */ - if (DeviceIoControl(aHand1401[sHand], lCode, NULL, 0, pBlk, sizeof(TCSBLOCK), &dwBytes, NULL)) - return (short)(dwBytes >= sizeof(TCSBLOCK) ? U14ERR_NOERROR : U14ERR_DRIVCOMMS); - else - return (short)GetLastError(); - } - else -#endif - { /* Windows NT or later */ - PARAMBLK rWork; - rWork.sState = U14ERR_DRIVCOMMS; - if (DeviceIoControl(aHand1401[sHand], lCode, pBlk, sizeof(TCSBLOCK), &rWork, sizeof(PARAMBLK), &dwBytes, NULL) && - (dwBytes >= sizeof(PARAMBLK))) - return rWork.sState; - } - - return U14ERR_DRIVCOMMS; -} -#endif - -/**************************************************************************** -** SafeTickCount -** Gets time in approximately units of a millisecond. -*****************************************************************************/ -static long SafeTickCount() -{ -#ifdef _IS_WINDOWS_ - return GetTickCount(); -#endif -#ifdef LINUX - struct timeval tv; - gettimeofday(&tv, NULL); - return (tv.tv_sec*1000 + tv.tv_usec/1000); -#endif -} - -/**************************************************************************** -** A utility routine to get the command file extension for a given type -** of 1401. We assume the type code is vaguely legal. -****************************************************************************/ -static int ExtForType(short sType, char* szExt) -{ - szExt[0] = 0; /* Default return is a blank string */ - switch (sType) - { - case U14TYPE1401: strcpy(szExt, ".CMD"); break; // Standard 1401 - case U14TYPEPLUS: strcpy(szExt, ".GXC"); break; // 1401 plus - default: // All others are in a predictable sequence - strcpy(szExt, ".ARM"); - szExt[3] = (char)('M' + sType - U14TYPEU1401); - if (szExt[3] > 'Z') // Wrap round to ARA after ARZ - szExt[3] = (char)(szExt[3] - 26); - } - return 0; -} - -/**************************************************************************** -** U14WhenToTimeOut -** Returns the time to time out in time units suitable for the machine -** we are running on ie millsecs for pc/linux, or Mac/ -****************************************************************************/ -U14API(int) U14WhenToTimeOut(short hand) -{ - int iNow = SafeTickCount(); - if ((hand >= 0) && (hand < MAX1401)) - iNow += alTimeOutPeriod[hand]; - return iNow; -} - -/**************************************************************************** -** U14PassedTime -** Returns non zero if the timed passed in has been passed 0 if not -****************************************************************************/ -U14API(short) U14PassedTime(int lCheckTime) -{ - return (short)((SafeTickCount()-lCheckTime) > 0); -} - -/**************************************************************************** -** TranslateString -** Tidies up string that U14GetString returns. Converts all the commas in a -** string to spaces. Removes terminating CR character. May do more in future. -****************************************************************************/ -static void TranslateString(char* pStr) -{ - int i = 0; - while (pStr[i]) - { - if (pStr[i] == ',') - pStr[i] = ' '; /* convert comma to space */ - ++i; - } - - if ((i > 0) && (pStr[i-1] == '\n')) /* kill terminating LF */ - pStr[i-1] = (char)0; -} - -/**************************************************************************** -** U14StrToLongs -** Converts a string to an array of longs and returns the number of values -****************************************************************************/ -U14API(short) U14StrToLongs(const char* pszBuff, U14LONG *palNums, short sMaxLongs) -{ - WORD wChInd = 0; // index into source - short sLgInd = 0; // index into result longs - - while (pszBuff[wChInd] && // until we get to end of string... - (sLgInd < sMaxLongs)) // ...or filled the buffer - { - // Why not use a C Library converter? - switch (pszBuff[wChInd]) - { - case '-': - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - { - BOOL bDone = FALSE; // true at end of number - int iSign = 1; // sign of number - long lValue = 0; - - while ((!bDone) && pszBuff[wChInd]) - { - switch (pszBuff[wChInd]) - { - case '-': - iSign = -1; // swap sign - break; - - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - lValue *= 10; // move to next digit base 10 - lValue += ((int)pszBuff[wChInd]-(int)'0'); - break; - - default: // end of number - bDone = TRUE; - break; - } - wChInd++; // move onto next character - } - palNums[sLgInd] = lValue * iSign; - sLgInd++; - } - break; - - default: - wChInd++; // look at next char - break; - } - } - return (sLgInd); -} - - -/**************************************************************************** -** U14LongsFrom1401 -** Gets the next waiting line from the 1401 and converts it longs -** Returns the number of numbers read or an error. -****************************************************************************/ -U14API(short) U14LongsFrom1401(short hand, U14LONG *palBuff, short sMaxLongs) -{ - char szWork[MAXSTRLEN]; - short sResult = U14GetString(hand, szWork, MAXSTRLEN);/* get reply from 1401 */ - if (sResult == U14ERR_NOERROR) /* if no error convert */ - sResult = U14StrToLongs(szWork, palBuff, sMaxLongs); - return sResult; -} - -/**************************************************************************** -** U14CheckErr -** Sends the ERR command to the 1401 and gets the result. Returns 0, a -** negative error code, or the first error value. -****************************************************************************/ -U14API(short) U14CheckErr(short hand) -{ - short sResult = U14SendString(hand, ";ERR;"); - if (sResult == U14ERR_NOERROR) - { - U14LONG er[3]; - sResult = U14LongsFrom1401(hand, er, 3); - if (sResult > 0) - { - sResult = (short)er[0]; /* Either zero or an error value */ -#ifdef _DEBUG - if (er[0] != 0) - { - char szMsg[50]; - sprintf(szMsg, "U14CheckErr returned %d,%d\n", er[0], er[1]); - OutputDebugString(szMsg); - } -#endif - } - else - { - if (sResult == 0) - sResult = U14ERR_TIMEOUT; /* No numbers equals timeout */ - } - } - - return sResult; -} - -/**************************************************************************** -** U14LastErrCode -** Returns the last code from the driver. This is for Windows where all calls -** go through the Control and Status routines, so we can save any error. -****************************************************************************/ -U14API(short) U14LastErrCode(short hand) -{ - if ((hand < 0) || (hand >= MAX1401)) - return U14ERR_BADHAND; - return asLastRetCode[hand]; -} - -/**************************************************************************** -** U14SetTimeout -** Set the timeout period for 1401 comms in milliseconds -****************************************************************************/ -U14API(void) U14SetTimeout(short hand, int lTimeOut) -{ - if ((hand < 0) || (hand >= MAX1401)) - return; - alTimeOutPeriod[hand] = lTimeOut; -} - -/**************************************************************************** -** U14GetTimeout -** Get the timeout period for 1401 comms in milliseconds -****************************************************************************/ -U14API(int) U14GetTimeout(short hand) -{ - if ((hand < 0) || (hand >= MAX1401)) - return U14ERR_BADHAND; - return alTimeOutPeriod[hand]; -} - -/**************************************************************************** -** U14OutBufSpace -** Return the space in the output buffer, or an error. -****************************************************************************/ -U14API(short) U14OutBufSpace(short hand) -{ -#ifdef _IS_WINDOWS_ - TCSBLOCK csBlock; - short sErr = U14Status1401(hand, U14_GETOUTBUFSPACE,&csBlock); - if (sErr == U14ERR_NOERROR) - sErr = csBlock.ints[0]; - return sErr; -#endif -#ifdef LINUX - short sErr = CheckHandle(hand); - return (sErr == U14ERR_NOERROR) ? CED_GetOutBufSpace(aHand1401[hand]) : sErr; -#endif -} - - -/**************************************************************************** -** U14BaseAddr1401 -** Returns the 1401 base address or an error code. Meaningless nowadays -****************************************************************************/ -U14API(int) U14BaseAddr1401(short hand) -{ -#ifdef _IS_WINDOWS_ - TCSBLOCK csBlock; - int iError = U14Status1401(hand, U14_GETBASEADDRESS,&csBlock); - if (iError == U14ERR_NOERROR) - iError = csBlock.longs[0]; - return iError; -#endif -#ifdef LINUX - short sErr = CheckHandle(hand); - return (sErr == U14ERR_NOERROR) ? CED_GetBaseAddress(aHand1401[hand]) : sErr; -#endif -} - -/**************************************************************************** -** U14StateOf1401 -** Return error state, either NOERROR or a negative code. -****************************************************************************/ -U14API(short) U14StateOf1401(short hand) -{ -#ifdef _IS_WINDOWS_ - TCSBLOCK csBlock; - short sErr = U14Status1401(hand, U14_STATEOF1401, &csBlock); - if (sErr == U14ERR_NOERROR) - { - sErr = csBlock.ints[0]; // returned 1401 state - if ((sErr >= DRIVRET_STD) && (sErr <= DRIVRET_MAX)) - sErr = U14ERR_NOERROR; - } -#endif -#ifdef LINUX - short sErr = CheckHandle(hand); - if (sErr == U14ERR_NOERROR) - { - sErr = (short)CED_StateOf1401(aHand1401[hand]); - if ((sErr >= DRIVRET_STD) && (sErr <= DRIVRET_MAX)) - sErr = U14ERR_NOERROR; - } -#endif - return sErr; -} - -/**************************************************************************** -** U14DriverVersion -** Returns the driver version. Hi word is major revision, low word is minor. -** If you pass in a silly handle (like -1), we return the version of the last -** driver we know of (to cope with PCI and no 1401 attached). -****************************************************************************/ -U14API(int) U14DriverVersion(short hand) -{ - return CheckHandle(hand) != U14ERR_NOERROR ? lLastDriverVersion : alDriverVersion[hand]; -} - -/**************************************************************************** -** U14DriverType -** Returns the driver type. The type, 0=ISA/NU-Bus, 1=PCI, 2=USB, 3=HSS -** If you pass in a silly handle (like -1), we return the type of the last -** driver we know of (to cope with PCI and no 1401 attached). -****************************************************************************/ -U14API(int) U14DriverType(short hand) -{ - return CheckHandle(hand) != U14ERR_NOERROR ? lLastDriverType : asDriverType[hand]; -} - -/**************************************************************************** -** U14DriverName -** Returns the driver type as 3 character (ISA, PCI, USB or HSS)) -****************************************************************************/ -U14API(short) U14DriverName(short hand, char* pBuf, WORD wMax) -{ - char* pName; - *pBuf = 0; // Start off with a blank string - switch (U14DriverType(hand)) // Results according to type - { - case 0: pName = "ISA"; break; - case 1: pName = "PCI"; break; - case 2: pName = "USB"; break; - case 3: pName = "HSS"; break; - default: pName = "???"; break; - } - strncpy(pBuf, pName, wMax); // Copy the correct name to return - - return U14ERR_NOERROR; -} - -/**************************************************************************** -** U14BlkTransState -** Returns 0 no transfer in progress, 1 transfer in progress or an error code -****************************************************************************/ -U14API(short) U14BlkTransState(short hand) -{ -#ifdef _IS_WINDOWS_ - TCSBLOCK csBlock; - short sErr = U14Status1401(hand, U14_BLKTRANSSTATE, &csBlock); - if (sErr == U14ERR_NOERROR) - sErr = csBlock.ints[0]; - return sErr; -#endif -#ifdef LINUX - short sErr = CheckHandle(hand); - return (sErr == U14ERR_NOERROR) ? CED_BlkTransState(aHand1401[hand]) : sErr; -#endif -} - -/**************************************************************************** -** U14Grab1401 -** Take control of the 1401 for diagnostics purposes. USB does nothing. -****************************************************************************/ -U14API(short) U14Grab1401(short hand) -{ - short sErr = CheckHandle(hand); - if (sErr == U14ERR_NOERROR) - { -#ifdef _IS_WINDOWS_ - if (abGrabbed[hand]) // 1401 should not have been grabbed - sErr = U14ERR_ALREADYSET; // Error code defined for this - else - { - TCSBLOCK csBlock; - sErr = U14Control1401(hand, U14_GRAB1401, &csBlock); - } -#endif -#ifdef LINUX - // 1401 should not have been grabbed - sErr = abGrabbed[hand] ? U14ERR_ALREADYSET : CED_Grab1401(aHand1401[hand]); -#endif - if (sErr == U14ERR_NOERROR) - abGrabbed[hand] = TRUE; - } - return sErr; -} - -/**************************************************************************** -** U14Free1401 -****************************************************************************/ -U14API(short) U14Free1401(short hand) -{ - short sErr = CheckHandle(hand); - if (sErr == U14ERR_NOERROR) - { -#ifdef _IS_WINDOWS_ - if (abGrabbed[hand]) // 1401 should have been grabbed - { - TCSBLOCK csBlock; - sErr = U14Control1401(hand, U14_FREE1401, &csBlock); - } - else - sErr = U14ERR_NOTSET; -#endif -#ifdef LINUX - // 1401 should not have been grabbed - sErr = abGrabbed[hand] ? CED_Free1401(aHand1401[hand]) : U14ERR_NOTSET; -#endif - if (sErr == U14ERR_NOERROR) - abGrabbed[hand] = FALSE; - } - return sErr; -} - -/**************************************************************************** -** U14Peek1401 -** DESCRIPTION Cause the 1401 to do one or more peek operations. -** If lRepeats is zero, the loop will continue until U14StopDebugLoop -** is called. After the peek is done, use U14GetDebugData to retrieve -** the results of the peek. -****************************************************************************/ -U14API(short) U14Peek1401(short hand, DWORD dwAddr, int nSize, int nRepeats) -{ - short sErr = CheckHandle(hand); - if (sErr == U14ERR_NOERROR) - { - if (abGrabbed[hand]) // 1401 should have been grabbed - { -#ifdef _IS_WINDOWS_ - TCSBLOCK csBlock; - csBlock.longs[0] = (long)dwAddr; - csBlock.longs[1] = nSize; - csBlock.longs[2] = nRepeats; - sErr = U14Control1401(hand, U14_DBGPEEK, &csBlock); -#endif -#ifdef LINUX - TDBGBLOCK dbb; - dbb.iAddr = (int)dwAddr; - dbb.iWidth = nSize; - dbb.iRepeats = nRepeats; - sErr = CED_DbgPeek(aHand1401[hand], &dbb); -#endif - } - else - sErr = U14ERR_NOTSET; - } - return sErr; -} - -/**************************************************************************** -** U14Poke1401 -** DESCRIPTION Cause the 1401 to do one or more poke operations. -** If lRepeats is zero, the loop will continue until U14StopDebugLoop -** is called. -****************************************************************************/ -U14API(short) U14Poke1401(short hand, DWORD dwAddr, DWORD dwValue, - int nSize, int nRepeats) -{ - short sErr = CheckHandle(hand); - if (sErr == U14ERR_NOERROR) - { - if (abGrabbed[hand]) // 1401 should have been grabbed - { -#ifdef _IS_WINDOWS_ - TCSBLOCK csBlock; - csBlock.longs[0] = (long)dwAddr; - csBlock.longs[1] = nSize; - csBlock.longs[2] = nRepeats; - csBlock.longs[3] = (long)dwValue; - sErr = U14Control1401(hand, U14_DBGPOKE, &csBlock); -#endif -#ifdef LINUX - TDBGBLOCK dbb; - dbb.iAddr = (int)dwAddr; - dbb.iWidth = nSize; - dbb.iRepeats= nRepeats; - dbb.iData = (int)dwValue; - sErr = CED_DbgPoke(aHand1401[hand], &dbb); -#endif - } - else - sErr = U14ERR_NOTSET; - } - return sErr; -} - -/**************************************************************************** -** U14Ramp1401 -** DESCRIPTION Cause the 1401 to loop, writing a ramp to a location. -** If lRepeats is zero, the loop will continue until U14StopDebugLoop. -****************************************************************************/ -U14API(short) U14Ramp1401(short hand, DWORD dwAddr, DWORD dwDef, DWORD dwEnable, - int nSize, int nRepeats) -{ - short sErr = CheckHandle(hand); - if (sErr == U14ERR_NOERROR) - { - if (abGrabbed[hand]) // 1401 should have been grabbed - { -#ifdef _IS_WINDOWS_ - TCSBLOCK csBlock; - csBlock.longs[0] = (long)dwAddr; - csBlock.longs[1] = (long)dwDef; - csBlock.longs[2] = (long)dwEnable; - csBlock.longs[3] = nSize; - csBlock.longs[4] = nRepeats; - sErr = U14Control1401(hand, U14_DBGRAMPDATA, &csBlock); -#endif -#ifdef LINUX - TDBGBLOCK dbb; - dbb.iAddr = (int)dwAddr; - dbb.iDefault = (int)dwDef; - dbb.iMask = (int)dwEnable; - dbb.iWidth = nSize; - dbb.iRepeats = nRepeats; - sErr = CED_DbgRampAddr(aHand1401[hand], &dbb); -#endif - } - else - sErr = U14ERR_NOTSET; - } - return sErr; -} - -/**************************************************************************** -** U14RampAddr -** DESCRIPTION Cause the 1401 to loop, reading from a ramping location. -** If lRepeats is zero, the loop will continue until U14StopDebugLoop -****************************************************************************/ -U14API(short) U14RampAddr(short hand, DWORD dwDef, DWORD dwEnable, - int nSize, int nRepeats) -{ - short sErr = CheckHandle(hand); - if (sErr == U14ERR_NOERROR) - { - if (abGrabbed[hand]) // 1401 should have been grabbed - { -#ifdef _IS_WINDOWS_ - TCSBLOCK csBlock; - csBlock.longs[0] = (long)dwDef; - csBlock.longs[1] = (long)dwEnable; - csBlock.longs[2] = nSize; - csBlock.longs[3] = nRepeats; - sErr = U14Control1401(hand, U14_DBGRAMPADDR, &csBlock); -#endif -#ifdef LINUX - TDBGBLOCK dbb; - dbb.iDefault = (int)dwDef; - dbb.iMask = (int)dwEnable; - dbb.iWidth = nSize; - dbb.iRepeats = nRepeats; - sErr = CED_DbgRampAddr(aHand1401[hand], &dbb); -#endif - } - else - sErr = U14ERR_NOTSET; - } - return sErr; -} - -/**************************************************************************** -** U14StopDebugLoop -** DESCRIPTION Stops a peek\poke\ramp that, with repeats set to zero, -** will otherwise continue forever. -****************************************************************************/ -U14API(short) U14StopDebugLoop(short hand) -{ - short sErr = CheckHandle(hand); - if (sErr == U14ERR_NOERROR) -#ifdef _IS_WINDOWS_ - { - if (abGrabbed[hand]) // 1401 should have been grabbed - { - TCSBLOCK csBlock; - sErr = U14Control1401(hand, U14_DBGSTOPLOOP, &csBlock); - } - else - sErr = U14ERR_NOTSET; - } -#endif -#ifdef LINUX - sErr = abGrabbed[hand] ? CED_DbgStopLoop(aHand1401[hand]) : U14ERR_NOTSET; -#endif - return sErr; -} - -/**************************************************************************** -** U14GetDebugData -** DESCRIPTION Returns the result from a previous peek operation. -****************************************************************************/ -U14API(short) U14GetDebugData(short hand, U14LONG* plValue) -{ - short sErr = CheckHandle(hand); - if (sErr == U14ERR_NOERROR) - { - if (abGrabbed[hand]) // 1401 should have been grabbed - { -#ifdef _IS_WINDOWS_ - TCSBLOCK csBlock; - sErr = U14Status1401(hand, U14_DBGGETDATA, &csBlock); - if (sErr == U14ERR_NOERROR) - *plValue = csBlock.longs[0]; // Return the data -#endif -#ifdef LINUX - TDBGBLOCK dbb; - sErr = CED_DbgGetData(aHand1401[hand], &dbb); - if (sErr == U14ERR_NOERROR) - *plValue = dbb.iData; /* Return the data */ -#endif - } - else - sErr = U14ERR_NOTSET; - } - return sErr; -} - -/**************************************************************************** -** U14StartSelfTest -****************************************************************************/ -U14API(short) U14StartSelfTest(short hand) -{ -#ifdef _IS_WINDOWS_ - TCSBLOCK csBlock; - return U14Control1401(hand, U14_STARTSELFTEST, &csBlock); -#endif -#ifdef LINUX - short sErr = CheckHandle(hand); - return (sErr == U14ERR_NOERROR) ? CED_StartSelfTest(aHand1401[hand]) : sErr; -#endif -} - -/**************************************************************************** -** U14CheckSelfTest -****************************************************************************/ -U14API(short) U14CheckSelfTest(short hand, U14LONG *pData) -{ -#ifdef _IS_WINDOWS_ - TCSBLOCK csBlock; - short sErr = U14Status1401(hand, U14_CHECKSELFTEST, &csBlock); - if (sErr == U14ERR_NOERROR) - { - pData[0] = csBlock.longs[0]; /* Return the results to user */ - pData[1] = csBlock.longs[1]; - pData[2] = csBlock.longs[2]; - } -#endif -#ifdef LINUX - short sErr = CheckHandle(hand); - if (sErr == U14ERR_NOERROR) /* Check parameters */ - { - TGET_SELFTEST gst; - sErr = CED_CheckSelfTest(aHand1401[hand], &gst); - if (sErr == U14ERR_NOERROR) - { - pData[0] = gst.code; /* Return the results to user */ - pData[1] = gst.x; - pData[2] = gst.y; - } - } -#endif - return sErr; -} - -/**************************************************************************** -** U14GetUserMemorySize -****************************************************************************/ -U14API(short) U14GetUserMemorySize(short hand, DWORD *pMemorySize) -{ - // The original 1401 used a different command for getting the size - short sErr = U14SendString(hand, (asType1401[hand] == U14TYPE1401) ? "MEMTOP;" : "MEMTOP,?;"); - *pMemorySize = 0; /* if we get error then leave size set at 0 */ - if (sErr == U14ERR_NOERROR) - { - U14LONG alLimits[4]; - sErr = U14LongsFrom1401(hand, alLimits, 4); - if (sErr > 0) /* +ve sErr is the number of values read */ - { - sErr = U14ERR_NOERROR; /* All OK, flag success */ - if (asType1401[hand] == U14TYPE1401) /* result for standard */ - *pMemorySize = alLimits[0] - alLimits[1]; /* memtop-membot */ - else - *pMemorySize = alLimits[0]; /* result for plus or u1401 */ - } - } - return sErr; -} - -/**************************************************************************** -** U14TypeOf1401 -** Returns the type of the 1401, maybe unknown -****************************************************************************/ -U14API(short) U14TypeOf1401(short hand) -{ - if ((hand < 0) || (hand >= MAX1401)) /* Check parameters */ - return U14ERR_BADHAND; - else - return asType1401[hand]; -} - -/**************************************************************************** -** U14NameOf1401 -** Returns the type of the 1401 as a string, blank if unknown -****************************************************************************/ -U14API(short) U14NameOf1401(short hand, char* pBuf, WORD wMax) -{ - short sErr = CheckHandle(hand); - if (sErr == U14ERR_NOERROR) - { - char* pName; - switch (asType1401[hand]) // Results according to type - { - case U14TYPE1401: pName = "Std 1401"; break; - case U14TYPEPLUS: pName = "1401plus"; break; - case U14TYPEU1401: pName = "micro1401"; break; - case U14TYPEPOWER: pName = "Power1401"; break; - case U14TYPEU14012:pName = "Micro1401 mk II"; break; - case U14TYPEPOWER2:pName = "Power1401 mk II"; break; - case U14TYPEU14013:pName = "Micro1401-3"; break; - case U14TYPEPOWER3:pName = "Power1401-3"; break; - default: pName = "Unknown"; - } - strncpy(pBuf, pName, wMax); - } - return sErr; -} - -/**************************************************************************** -** U14TransferFlags -** Returns the driver block transfer flags. -** Bits can be set - see U14TF_ constants in use1401.h -*****************************************************************************/ -U14API(short) U14TransferFlags(short hand) -{ -#ifdef _IS_WINDOWS_ - TCSBLOCK csBlock; - short sErr = U14Status1401(hand, U14_TRANSFERFLAGS, &csBlock); - return (sErr == U14ERR_NOERROR) ? (short)csBlock.ints[0] : sErr; -#endif -#ifdef LINUX - short sErr = CheckHandle(hand); - return (sErr == U14ERR_NOERROR) ? CED_TransferFlags(aHand1401[hand]) : sErr; -#endif -} - -/**************************************************************************** -** GetDriverVersion -** Actually reads driver version from the device driver. -** Hi word is major revision, low word is minor revision. -** Assumes that hand has been checked. Also codes driver type in bits 24 up. -*****************************************************************************/ -static int GetDriverVersion(short hand) -{ -#ifdef _IS_WINDOWS_ - TCSBLOCK csBlock; - int iErr = U14Status1401(hand, U14_GETDRIVERREVISION, &csBlock); - if (iErr == U14ERR_NOERROR) - iErr = csBlock.longs[0]; - return iErr; -#endif -#ifdef LINUX - return CED_GetDriverRevision(aHand1401[hand]); -#endif -} - -/**************************************************************************** -** U14MonitorRev -** Returns the 1401 monitor revision number. -** The number returned is the minor revision - the part after the -** decimal point - plus the major revision times 1000. -*****************************************************************************/ -U14API(int) U14MonitorRev(short hand) -{ - int iRev = 0; - int iErr = CheckHandle(hand); - if (iErr != U14ERR_NOERROR) // Check open and in use - return iErr; - - if (asType1401[hand] >= U14TYPEPOWER2) // The Power2 onwards can give us the monitor - { // revision directly for all versions - iErr = U14SendString(hand, "INFO,S,28;"); - if (iErr == U14ERR_NOERROR) - { - U14LONG lVals[2]; // Read a single number being the revision - iErr = U14LongsFrom1401(hand, lVals, 1); - if (iErr > 0) - { - iErr = U14ERR_NOERROR; - iRev = lVals[0]; // This is the minor part of the revision - iRev += asType1401[hand] * 10000; - } - } - } - else - { /* Do it the hard way for older hardware */ - iErr = U14SendString(hand, ";CLIST;"); /* ask for command levels */ - if (iErr == U14ERR_NOERROR) - { - while (iErr == U14ERR_NOERROR) - { - char wstr[50]; - iErr = U14GetString(hand, wstr, 45); - if (iErr == U14ERR_NOERROR) - { - char *pstr = strstr(wstr,"RESET"); /* Is this the RESET command? */ - if ((pstr == wstr) && (wstr[5] == ' ')) - { - char *pstr2; - size_t l; - pstr += 6; /* Move past RESET and followinmg char */ - l = strlen(pstr); /* The length of text remaining */ - while (((pstr[l-1] == ' ') || (pstr[l-1] == 13)) && (l > 0)) - { - pstr[l-1] = 0; /* Tidy up string at the end */ - l--; /* by removing spaces and CRs */ - } - pstr2 = strchr(pstr, '.'); /* Find the decimal point */ - if (pstr2 != NULL) /* If we found the DP */ - { - *pstr2 = 0; /* End pstr string at DP */ - pstr2++; /* Now past the decimal point */ - iRev = atoi(pstr2); /* Get the number after point */ - } - iRev += (atoi(pstr) * 1000); /* Add first bit * 1000 */ - } - if ((strlen(wstr) < 3) && (wstr[0] == ' ')) - break; /* Spot the last line of results */ - } - } - } - } - if (iErr == U14ERR_NOERROR) /* Return revision if no error */ - iErr = iRev; - - return iErr; -} - -/**************************************************************************** -** U14TryToOpen Tries to open the 1401 number passed -** Note : This will succeed with NT driver even if no I/F card or -** 1401 switched off, so we check state and close the driver -** if the state is unsatisfactory in U14Open1401. -****************************************************************************/ -#ifdef _IS_WINDOWS_ -#define U14NAMEOLD "\\\\.\\CED_140%d" -#define U14NAMENEW "\\\\.\\CED%d" -static short U14TryToOpen(int n1401, long* plRetVal, short* psHandle) -{ - short sErr = U14ERR_NOERROR; - HANDLE hDevice = INVALID_HANDLE_VALUE; - DWORD dwErr = 0; - int nFirst, nLast, nDev = 0; /* Used for the search for a 1401 */ - BOOL bOldName = FALSE; /* start by looking for a modern driver */ - - if (n1401 == 0) /* If we need to look for a 1401 */ - { - nFirst = 1; /* Set the search range */ - nLast = MAX1401; /* through all the possible 1401s */ - } - else - nFirst = nLast = n1401; /* Otherwise just one 1401 */ - - while (hDevice == INVALID_HANDLE_VALUE) /* Loop to try for a 1401 */ - { - for (nDev = nFirst; nDev <= nLast; nDev++) - { - char szDevName[40]; /* name of the device to open */ - sprintf(szDevName, bOldName ? U14NAMEOLD : U14NAMENEW, nDev); - hDevice = CreateFile(szDevName, GENERIC_WRITE | GENERIC_READ, - 0, 0, /* Unshared mode does nothing as this is a device */ - OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); - - if (hDevice != INVALID_HANDLE_VALUE)/* Check 1401 if opened */ - { - TCSBLOCK csBlock; - assert(aHand1401[nDev-1] == INVALID_HANDLE_VALUE); // assert if already open - aHand1401[nDev-1] = hDevice; /* Save handle for now */ - -#ifndef _WIN64 - // Use DIOC method if not windows 9x or if using new device name - abUseNTDIOC[nDev-1] = (BOOL)(!bWindows9x || !bOldName); -#endif - sErr = U14Status1401((short)(nDev-1), U14_TYPEOF1401, &csBlock); - if (sErr == U14ERR_NOERROR) - { - *plRetVal = csBlock.ints[0]; - if (csBlock.ints[0] == U14ERR_INUSE)/* Prevent multi opens */ - { - CloseHandle(hDevice); /* treat as open failure */ - hDevice = INVALID_HANDLE_VALUE; - aHand1401[nDev-1] = INVALID_HANDLE_VALUE; - sErr = U14ERR_INUSE; - } - else - break; /* Exit from for loop on success */ - } - else - { - CloseHandle(hDevice); /* Give up if func fails */ - hDevice = INVALID_HANDLE_VALUE; - aHand1401[nDev-1] = INVALID_HANDLE_VALUE; - } - } - else - { - DWORD dwe = GetLastError(); /* Get error code otherwise */ - if ((dwe != ERROR_FILE_NOT_FOUND) || (dwErr == 0)) - dwErr = dwe; /* Ignore repeats of 'not found' */ - } - } - - if ((hDevice == INVALID_HANDLE_VALUE) &&/* No device found, and... */ - (bWindows9x) && /* ...old names are allowed, and... */ - (bOldName == FALSE)) /* ...not tried old names yet */ - bOldName = TRUE; /* Set flag and go round again */ - else - break; /* otherwise that's all folks */ - } - - if (hDevice != INVALID_HANDLE_VALUE) /* If we got our device open */ - *psHandle = (short)(nDev-1); /* return 1401 number opened */ - else - { - if (dwErr == ERROR_FILE_NOT_FOUND) /* Sort out the error codes */ - sErr = U14ERR_NO1401DRIV; /* if file not found */ - else if (dwErr == ERROR_NOT_SUPPORTED) - sErr = U14ERR_DRIVTOOOLD; /* if DIOC not supported */ - else if (dwErr == ERROR_ACCESS_DENIED) - sErr = U14ERR_INUSE; - else - sErr = U14ERR_DRIVCOMMS; /* otherwise assume comms problem */ - } - return sErr; -} -#endif -#ifdef LINUX -static short U14TryToOpen(int n1401, long* plRetVal, short* psHandle) -{ - short sErr = U14ERR_NOERROR; - int fh = 0; // will be 1401 handle - int iErr = 0; - int nFirst, nLast, nDev = 0; // Used for the search for a 1401 - - if (n1401 == 0) // If we need to look for a 1401 - { - nFirst = 1; /* Set the search range */ - nLast = MAX1401; /* through all the possible 1401s */ - } - else - nFirst = nLast = n1401; /* Otherwise just one 1401 */ - - for (nDev = nFirst; nDev <= nLast; nDev++) - { - char szDevName[40]; // name of the device to open - sprintf(szDevName,"/dev/cedusb/%d", nDev-1); - fh = open(szDevName, O_RDWR); // can only be opened once at a time - if (fh > 0) // Check 1401 if opened - { - int iType1401 = CED_TypeOf1401(fh); // get 1401 type - aHand1401[nDev-1] = fh; // Save handle for now - if (iType1401 >= 0) - { - *plRetVal = iType1401; - break; // Exit from for loop on success - } - else - { - close(fh); // Give up if func fails - fh = 0; - aHand1401[nDev-1] = 0; - } - } - else - { - if (((errno != ENODEV) && (errno != ENOENT)) || (iErr == 0)) - iErr = errno; // Ignore repeats of 'not found' - } - } - - - if (fh) // If we got our device open - *psHandle = (short)(nDev-1); // return 1401 number opened - else - { - if ((iErr == ENODEV) || (iErr == ENOENT)) // Sort out the error codes - sErr = U14ERR_NO1401DRIV; // if file not found - else if (iErr == EBUSY) - sErr = U14ERR_INUSE; - else - sErr = U14ERR_DRIVCOMMS; // otherwise assume comms problem - } - - return sErr; -} -#endif -/**************************************************************************** -** U14Open1401 -** Tries to get the 1401 for use by this application -*****************************************************************************/ -U14API(short) U14Open1401(short n1401) -{ - long lRetVal = -1; - short sErr; - short hand = 0; - - if ((n1401 < 0) || (n1401 > MAX1401)) // must check the 1401 number - return U14ERR_BAD1401NUM; - - szLastName[0] = 0; /* initialise the error info string */ - - sErr = U14TryToOpen(n1401, &lRetVal, &hand); - if (sErr == U14ERR_NOERROR) - { - long lDriverVersion = GetDriverVersion(hand); /* get driver revision */ - long lDriverRev = -1; - if (lDriverVersion >= 0) /* can use it if all OK */ - { - lLastDriverType = (lDriverVersion >> 24) & 0x000000FF; - asDriverType[hand] = (short)lLastDriverType; /* Drv type */ - lLastDriverVersion = lDriverVersion & 0x00FFFFFF; - alDriverVersion[hand] = lLastDriverVersion; /* Actual version */ - lDriverRev = ((lDriverVersion>>16) & 0x00FF); /* use hi word */ - } - else - { - U14Close1401(hand); /* If there is a problem we should close */ - return (short)lDriverVersion; /* and return the error code */ - } - - if (lDriverRev < MINDRIVERMAJREV) /* late enough version? */ - { - U14Close1401(hand); /* If there is a problem we should close */ - return U14ERR_DRIVTOOOLD; /* too old */ - } - - asLastRetCode[hand] = U14ERR_NOERROR; /* Initialise this 1401s info */ - abGrabbed[hand] = FALSE; /* we are not in single step mode */ - U14SetTimeout(hand, 3000); /* set 3 seconds as default timeout */ - - switch (lRetVal) - { - case DRIVRET_STD: asType1401[hand] = U14TYPE1401; break; /* Some we do by hand */ - case DRIVRET_U1401:asType1401[hand] = U14TYPEU1401; break; - case DRIVRET_PLUS: asType1401[hand] = U14TYPEPLUS; break; - default: // For the power upwards, we can calculate the codes - if ((lRetVal >= DRIVRET_POWER) && (lRetVal <= DRIVRET_MAX)) - asType1401[hand] = (short)(lRetVal - (DRIVRET_POWER - U14TYPEPOWER)); - else - asType1401[hand] = U14TYPEUNKNOWN; - break; - } - U14KillIO1401(hand); /* resets the 1401 buffers */ - - if (asType1401[hand] != U14TYPEUNKNOWN) /* If all seems OK so far */ - { - sErr = U14CheckErr(hand); /* we can check 1401 comms now */ - if (sErr != 0) /* If this failed to go OK */ - U14Reset1401(hand); /* Reset the 1401 to try to sort it out */ - } - - sErr = U14StateOf1401(hand);/* Get the state of the 1401 for return */ - if (sErr == U14ERR_NOERROR) - sErr = hand; /* return the handle if no problem */ - else - U14Close1401(hand); /* If there is a problem we should close */ - } - - return sErr; -} - - -/**************************************************************************** -** U14Close1401 -** Closes the 1401 so someone else can use it. -****************************************************************************/ -U14API(short) U14Close1401(short hand) -{ - int j; - int iAreaMask = 0; // Mask for active areas - short sErr = CheckHandle(hand); - if (sErr != U14ERR_NOERROR) // Check open and in use - return sErr; - - for (j = 0; j MAXSTRLEN) - return U14ERR_STRLEN; // String too long - -#ifdef _IS_WINDOWS_ - // To get here we must wait for the buffer to have some space - lTimeOutTicks = U14WhenToTimeOut(hand); - do - { - bSpaceToSend = (BOOL)((long)U14OutBufSpace(hand) >= nChars); - } - while (!bSpaceToSend && !U14PassedTime(lTimeOutTicks)); - - if (!bSpaceToSend) /* Last-ditch attempt to avoid timeout */ - { /* This can happen with anti-virus or network activity! */ - int i; - for (i = 0; (i < 4) && (!bSpaceToSend); ++i) - { - Sleep(25); /* Give other threads a chance for a while */ - bSpaceToSend = (BOOL)((long)U14OutBufSpace(hand) >= nChars); - } - } - - if (asLastRetCode[hand] == U14ERR_NOERROR) /* no errors? */ - { - if (bSpaceToSend) - { - PARAMBLK rData; - DWORD dwBytes; - char tstr[MAXSTRLEN+5]; /* Buffer for chars */ - - if ((hand < 0) || (hand >= MAX1401)) - sErr = U14ERR_BADHAND; - else - { - strcpy(tstr, pString); /* Into local buf */ -#ifndef _WIN64 - if (!USE_NT_DIOC(hand)) /* Using WIN 95 driver access? */ - { - int iOK = DeviceIoControl(aHand1401[hand], (DWORD)U14_SENDSTRING, - NULL, 0, tstr, nChars, - &dwBytes, NULL); - if (iOK) - sErr = (dwBytes >= (DWORD)nChars) ? U14ERR_NOERROR : U14ERR_DRIVCOMMS; - else - sErr = (short)GetLastError(); - } - else -#endif - { - int iOK = DeviceIoControl(aHand1401[hand],(DWORD)U14_SENDSTRING, - tstr, nChars, - &rData,sizeof(PARAMBLK),&dwBytes,NULL); - if (iOK && (dwBytes >= sizeof(PARAMBLK))) - sErr = rData.sState; - else - sErr = U14ERR_DRIVCOMMS; - } - - if (sErr != U14ERR_NOERROR) // If we have had a comms error - U14ForceReset(hand); // make sure we get real reset - } - - return sErr; - - } - else - { - U14ForceReset(hand); // make sure we get real reset - return U14ERR_TIMEOUT; - } - } - else - return asLastRetCode[hand]; -#endif -#ifdef LINUX - // Just try to send it and see what happens! - sErr = CED_SendString(aHand1401[hand], pString, nChars); - if (sErr != U14ERR_NOOUT) // if any result except "no room in output"... - { - if (sErr != U14ERR_NOERROR) // if a problem... - U14ForceReset(hand); // ...make sure we get real reset next time - return sErr; // ... we are done as nothing we can do - } - - // To get here we must wait for the buffer to have some space - lTimeOutTicks = U14WhenToTimeOut(hand); - do - { - bSpaceToSend = (BOOL)((long)U14OutBufSpace(hand) >= nChars); - if (!bSpaceToSend) - sched_yield(); // let others have fun while we wait - } - while (!bSpaceToSend && !U14PassedTime(lTimeOutTicks)); - - if (asLastRetCode[hand] == U14ERR_NOERROR) /* no errors? */ - { - if (bSpaceToSend) - { - sErr = CED_SendString(aHand1401[hand], pString, nChars); - if (sErr != U14ERR_NOERROR) // If we have had a comms error - U14ForceReset(hand); // make sure we get real reset - return sErr; - } - else - { - U14ForceReset(hand); // make sure we get real reset - return U14ERR_TIMEOUT; - } - } - else - return asLastRetCode[hand]; -#endif -} - -/**************************************************************************** -** U14SendChar -** Send character to the 1401 -*****************************************************************************/ -U14API(short) U14SendChar(short hand, char cChar) -{ -#ifdef _IS_WINDOWS_ - char sz[2]=" "; // convert to a string and send - sz[0] = cChar; - sz[1] = 0; - return(U14SendString(hand, sz)); // String routines are better -#endif -#ifdef LINUX - short sErr = CheckHandle(hand); - return (sErr == U14ERR_NOERROR) ? CED_SendChar(aHand1401[hand], cChar) : sErr; -#endif -} - -/**************************************************************************** -** U14GetString -** Get a string from the 1401. Returns a null terminated string. -** The string is all the characters up to the next CR in the buffer -** or the end of the buffer if that comes first. This only returns text -** if there is a CR in the buffer. The terminating CR character is removed. -** wMaxLen Is the size of the buffer and must be at least 2 or an error. -** Returns U14ERR_NOERR if OK with the result in the string or a negative -** error code. Any error from the device causes us to set up for -** a full reset. -****************************************************************************/ -U14API(short) U14GetString(short hand, char* pBuffer, WORD wMaxLen) -{ - short sErr = CheckHandle(hand); - if (sErr != U14ERR_NOERROR) // If an error... - return sErr; // ...bail out! - -#ifdef _IS_WINDOWS_ - if (wMaxLen>1) // we need space for terminating 0 - { - BOOL bLineToGet; // true when a line to get - long lTimeOutTicks = U14WhenToTimeOut(hand); - do - bLineToGet = (BOOL)(U14LineCount(hand) != 0); - while (!bLineToGet && !U14PassedTime(lTimeOutTicks)); - - if (!bLineToGet) /* Last-ditch attempt to avoid timeout */ - { /* This can happen with anti-virus or network activity! */ - int i; - for (i = 0; (i < 4) && (!bLineToGet); ++i) - { - Sleep(25); /* Give other threads a chance for a while */ - bLineToGet = (BOOL)(U14LineCount(hand) != 0); - } - } - - if (bLineToGet) - { - if (asLastRetCode[hand] == U14ERR_NOERROR) /* all ok so far */ - { - DWORD dwBytes = 0; - *((WORD *)pBuffer) = wMaxLen; /* set up length */ -#ifndef _WIN64 - if (!USE_NT_DIOC(hand)) /* Win 95 DIOC here ? */ - { - char tstr[MAXSTRLEN+5]; /* Buffer for Win95 chars */ - int iOK; - - if (wMaxLen > MAXSTRLEN) /* Truncate length */ - wMaxLen = MAXSTRLEN; - - *((WORD *)tstr) = wMaxLen; /* set len */ - - iOK = DeviceIoControl(aHand1401[hand],(DWORD)U14_GETSTRING, - NULL, 0, tstr, wMaxLen+sizeof(short), - &dwBytes, NULL); - if (iOK) /* Device IO control OK ? */ - { - if (dwBytes >= 0) /* If driver OK */ - { - strcpy(pBuffer, tstr); - sErr = U14ERR_NOERROR; - } - else - sErr = U14ERR_DRIVCOMMS; - } - else - { - sErr = (short)GetLastError(); - if (sErr > 0) /* Errors are -ve */ - sErr = (short)-sErr; - } - } - else -#endif - { /* Here for NT, the DLL must own the buffer */ - HANDLE hMem = GlobalAlloc(GMEM_MOVEABLE,wMaxLen+sizeof(short)); - if (hMem) - { - char* pMem = (char*)GlobalLock(hMem); - if (pMem) - { - int iOK = DeviceIoControl(aHand1401[hand],(DWORD)U14_GETSTRING, - NULL, 0, pMem, wMaxLen+sizeof(short), - &dwBytes, NULL); - if (iOK) /* Device IO control OK ? */ - { - if (dwBytes >= wMaxLen) - { - strcpy(pBuffer, pMem+sizeof(short)); - sErr = *((SHORT*)pMem); - } - else - sErr = U14ERR_DRIVCOMMS; - } - else - sErr = U14ERR_DRIVCOMMS; - - GlobalUnlock(hMem); - } - else - sErr = U14ERR_OUTOFMEMORY; - - GlobalFree(hMem); - } - else - sErr = U14ERR_OUTOFMEMORY; - } - - if (sErr == U14ERR_NOERROR) // If all OK... - TranslateString(pBuffer); // ...convert any commas to spaces - else // If we have had a comms error... - U14ForceReset(hand); // ...make sure we get real reset - - } - else - sErr = asLastRetCode[hand]; - } - else - { - sErr = U14ERR_TIMEOUT; - U14ForceReset(hand); // make sure we get real reset - } - } - else - sErr = U14ERR_BUFF_SMALL; - return sErr; -#endif -#ifdef LINUX - if (wMaxLen>1) // we need space for terminating 0 - { - BOOL bLineToGet; // true when a line to get - long lTimeOutTicks = U14WhenToTimeOut(hand); - do - { - bLineToGet = (BOOL)(U14LineCount(hand) != 0); - if (!bLineToGet) - sched_yield(); - - } - while (!bLineToGet && !U14PassedTime(lTimeOutTicks)); - - if (bLineToGet) - { - sErr = CED_GetString(aHand1401[hand], pBuffer, wMaxLen-1); // space for terminator - if (sErr >=0) // if we were OK... - { - if (sErr >= wMaxLen) // this should NOT happen unless - sErr = U14ERR_DRIVCOMMS; // ...driver Comms are very bad - else - { - pBuffer[sErr] = 0; // OK, so terminate the string... - TranslateString(pBuffer); // ...and convert commas to spaces. - } - } - - if (sErr < U14ERR_NOERROR) // If we have had a comms error - U14ForceReset(hand); // make sure we get real reset - } - else - { - sErr = U14ERR_TIMEOUT; - U14ForceReset(hand); // make sure we get real reset - } - } - else - sErr = U14ERR_BUFF_SMALL; - - return sErr >= U14ERR_NOERROR ? U14ERR_NOERROR : sErr; -#endif -} - -/**************************************************************************** -** U14GetChar -** Get a character from the 1401. CR returned as CR. -*****************************************************************************/ -U14API(short) U14GetChar(short hand, char* pcChar) -{ -#ifdef _IS_WINDOWS_ - char sz[2]; // read a very short string - short sErr = U14GetString(hand, sz, 2); // read one char and nul terminate it - *pcChar = sz[0]; // copy to result, NB char translate done by GetString - if (sErr == U14ERR_NOERROR) - { // undo translate of CR to zero - if (*pcChar == '\0') // by converting back - *pcChar = '\n'; // What a nasty thing to have to do - } - return sErr; -#endif -#ifdef LINUX - short sErr = CheckHandle(hand); - if (sErr != U14ERR_NOERROR) // Check parameters - return sErr; - sErr = CED_GetChar(aHand1401[hand]); // get one char, if available - if (sErr >= 0) - { - *pcChar = (char)sErr; // return if it we have one - return U14ERR_NOERROR; // say all OK - } - else - return sErr; -#endif -} - -/**************************************************************************** -** U14Stat1401 -** Returns 0 for no lines or error or non zero for something waiting -****************************************************************************/ -U14API(short) U14Stat1401(short hand) -{ - return ((short)(U14LineCount(hand) > 0)); -} - -/**************************************************************************** -** U14CharCount -** Returns the number of characters in the input buffer -*****************************************************************************/ -U14API(short) U14CharCount(short hand) -{ -#ifdef _IS_WINDOWS_ - TCSBLOCK csBlock; - short sErr = U14Status1401(hand, U14_STAT1401, &csBlock); - if (sErr == U14ERR_NOERROR) - sErr = csBlock.ints[0]; - return sErr; -#endif -#ifdef LINUX - short sErr = CheckHandle(hand); - return (sErr == U14ERR_NOERROR) ? CED_Stat1401(aHand1401[hand]) : sErr; -#endif -} - -/**************************************************************************** -** U14LineCount -** Returns the number of CR characters in the input buffer -*****************************************************************************/ -U14API(short) U14LineCount(short hand) -{ -#ifdef _IS_WINDOWS_ - TCSBLOCK csBlock; - short sErr = U14Status1401(hand, U14_LINECOUNT, &csBlock); - if (sErr == U14ERR_NOERROR) - sErr = csBlock.ints[0]; - return sErr; -#endif -#ifdef LINUX - short sErr = CheckHandle(hand); - return (sErr == U14ERR_NOERROR) ? CED_LineCount(aHand1401[hand]) : sErr; -#endif -} - -/**************************************************************************** -** U14GetErrorString -** Converts error code supplied to a decent descriptive string. -** NOTE: This function may use some extra information stored -** internally in the DLL. This information is stored on a -** per-process basis, but it might be altered if you call -** other functions after getting an error and before using -** this function. -****************************************************************************/ -U14API(void) U14GetErrorString(short nErr, char* pStr, WORD wMax) -{ - char wstr[150]; - - switch (nErr) /* Basically, we do this with a switch block */ - { - case U14ERR_OFF: - sprintf(wstr, "The 1401 is apparently switched off (code %d)", nErr); - break; - - case U14ERR_NC: - sprintf(wstr, "The 1401 is not connected to the interface card (code %d)", nErr); - break; - - case U14ERR_ILL: - sprintf(wstr, "The 1401 is not working correctly (code %d)", nErr); - break; - - case U14ERR_NOIF: - sprintf(wstr, "The 1401 interface card was not detected (code %d)", nErr); - break; - - case U14ERR_TIME: - sprintf(wstr, "The 1401 fails to become ready for use (code %d)", nErr); - break; - - case U14ERR_BADSW: - sprintf(wstr, "The 1401 interface card jumpers are incorrect (code %d)", nErr); - break; - - case U14ERR_NOINT: - sprintf(wstr, "The 1401 interrupt is not available for use (code %d)", nErr); - break; - - case U14ERR_INUSE: - sprintf(wstr, "The 1401 is already in use by another program (code %d)", nErr); - break; - - case U14ERR_NODMA: - sprintf(wstr, "The 1401 DMA channel is not available for use (code %d)", nErr); - break; - - case U14ERR_BADHAND: - sprintf(wstr, "The application supplied an incorrect 1401 handle (code %d)", nErr); - break; - - case U14ERR_BAD1401NUM: - sprintf(wstr, "The application used an incorrect 1401 number (code %d)", nErr); - break; - - case U14ERR_NO_SUCH_FN: - sprintf(wstr, "The code passed to the 1401 driver is invalid (code %d)", nErr); - break; - - case U14ERR_NO_SUCH_SUBFN: - sprintf(wstr, "The sub-code passed to the 1401 driver is invalid (code %d)", nErr); - break; - - case U14ERR_NOOUT: - sprintf(wstr, "No room in buffer for characters for the 1401 (code %d)", nErr); - break; - - case U14ERR_NOIN: - sprintf(wstr, "No characters from the 1401 are available (code %d)", nErr); - break; - - case U14ERR_STRLEN: - sprintf(wstr, "A string sent to or read from the 1401 was too long (code %d)", nErr); - break; - - case U14ERR_LOCKFAIL: - sprintf(wstr, "Failed to lock host memory for data transfer (code %d)", nErr); - break; - - case U14ERR_UNLOCKFAIL: - sprintf(wstr, "Failed to unlock host memory after data transfer (code %d)", nErr); - break; - - case U14ERR_ALREADYSET: - sprintf(wstr, "The transfer area used is already set up (code %d)", nErr); - break; - - case U14ERR_NOTSET: - sprintf(wstr, "The transfer area used has not been set up (code %d)", nErr); - break; - - case U14ERR_BADAREA: - sprintf(wstr, "The transfer area number is incorrect (code %d)", nErr); - break; - - case U14ERR_NOFILE: - sprintf(wstr, "The command file %s could not be opened (code %d)", szLastName, nErr); - break; - - case U14ERR_READERR: - sprintf(wstr, "The command file %s could not be read (code %d)", szLastName, nErr); - break; - - case U14ERR_UNKNOWN: - sprintf(wstr, "The %s command resource could not be found (code %d)", szLastName, nErr); - break; - - case U14ERR_HOSTSPACE: - sprintf(wstr, "Unable to allocate memory for loading command %s (code %d)", szLastName, nErr); - break; - - case U14ERR_LOCKERR: - sprintf(wstr, "Unable to lock memory for loading command %s (code %d)", szLastName, nErr); - break; - - case U14ERR_CLOADERR: - sprintf(wstr, "Error in loading command %s, bad command format (code %d)", szLastName, nErr); - break; - - case U14ERR_TOXXXERR: - sprintf(wstr, "Error detected after data transfer to or from the 1401 (code %d)", nErr); - break; - - case U14ERR_NO386ENH: - sprintf(wstr, "Windows 3.1 is not running in 386 enhanced mode (code %d)", nErr); - break; - - case U14ERR_NO1401DRIV: - sprintf(wstr, "The 1401 device driver cannot be found (code %d)\nUSB: check plugged in and powered\nOther: not installed?", nErr); - break; - - case U14ERR_DRIVTOOOLD: - sprintf(wstr, "The 1401 device driver is too old for use (code %d)", nErr); - break; - - case U14ERR_TIMEOUT: - sprintf(wstr, "Character transmissions to the 1401 timed-out (code %d)", nErr); - break; - - case U14ERR_BUFF_SMALL: - sprintf(wstr, "Buffer for text from the 1401 was too small (code %d)", nErr); - break; - - case U14ERR_CBALREADY: - sprintf(wstr, "1401 monitor callback already set up (code %d)", nErr); - break; - - case U14ERR_BADDEREG: - sprintf(wstr, "1401 monitor callback deregister invalid (code %d)", nErr); - break; - - case U14ERR_DRIVCOMMS: - sprintf(wstr, "1401 device driver communications failed (code %d)", nErr); - break; - - case U14ERR_OUTOFMEMORY: - sprintf(wstr, "Failed to allocate or lock memory for text from the 1401 (code %d)", nErr); - break; - - default: - sprintf(wstr, "1401 error code %d returned; this code is unknown", nErr); - break; - - } - if ((WORD)strlen(wstr) >= wMax-1) /* Check for string being too long */ - wstr[wMax-1] = 0; /* and truncate it if so */ - strcpy(pStr, wstr); /* Return the error string */ -} - -/*************************************************************************** -** U14GetTransfer -** Get a TGET_TX_BLOCK describing a transfer area (held in the block) -***************************************************************************/ -U14API(short) U14GetTransfer(short hand, TGET_TX_BLOCK *pTransBlock) -{ - short sErr = CheckHandle(hand); -#ifdef _IS_WINDOWS_ - if (sErr == U14ERR_NOERROR) - { - DWORD dwBytes = 0; - BOOL bOK = DeviceIoControl(aHand1401[hand], (DWORD)U14_GETTRANSFER, NULL, 0, pTransBlock, - sizeof(TGET_TX_BLOCK), &dwBytes, NULL); - - if (bOK && (dwBytes >= sizeof(TGET_TX_BLOCK))) - sErr = U14ERR_NOERROR; - else - sErr = U14ERR_DRIVCOMMS; - } - return sErr; -#endif -#ifdef LINUX - return (sErr == U14ERR_NOERROR) ? CED_GetTransfer(aHand1401[hand], pTransBlock) : sErr; -#endif -} -///////////////////////////////////////////////////////////////////////////// -// U14WorkingSet -// For Win32 only, adjusts process working set so that minimum is at least -// dwMinKb and maximum is at least dwMaxKb. -// Return value is zero if all went OK, or a code from 1 to 3 indicating the -// cause of the failure: -// -// 1 unable to access process (insufficient rights?) -// 2 unable to read process working set -// 3 unable to set process working set - bad parameters? -U14API(short) U14WorkingSet(DWORD dwMinKb, DWORD dwMaxKb) -{ -#ifdef _IS_WINDOWS_ - short sRetVal = 0; // 0 means all is OK - HANDLE hProcess; - DWORD dwVer = GetVersion(); - if (dwVer & 0x80000000) // is this not NT? - return 0; // then give up right now - - // Now attempt to get information on working set size - hProcess = OpenProcess(STANDARD_RIGHTS_REQUIRED | - PROCESS_QUERY_INFORMATION | - PROCESS_SET_QUOTA, - FALSE, _getpid()); - if (hProcess) - { - SIZE_T dwMinSize,dwMaxSize; - if (GetProcessWorkingSetSize(hProcess, &dwMinSize, &dwMaxSize)) - { - DWORD dwMin = dwMinKb << 10; // convert from kb to bytes - DWORD dwMax = dwMaxKb << 10; - - // if we get here, we have managed to read the current size - if (dwMin > dwMinSize) // need to change sizes? - dwMinSize = dwMin; - - if (dwMax > dwMaxSize) - dwMaxSize = dwMax; - - if (!SetProcessWorkingSetSize(hProcess, dwMinSize, dwMaxSize)) - sRetVal = 3; // failed to change size - } - else - sRetVal = 2; // failed to read original size - - CloseHandle(hProcess); - } - else - sRetVal = 1; // failed to get handle - - return sRetVal; -#endif -#ifdef LINUX - if (dwMinKb | dwMaxKb) - { - // to stop compiler moaning - } - return U14ERR_NOERROR; -#endif -} - -/**************************************************************************** -** U14UnSetTransfer Cancels a transfer area -** wArea The index of a block previously used in by SetTransfer -*****************************************************************************/ -U14API(short) U14UnSetTransfer(short hand, WORD wArea) -{ - short sErr = CheckHandle(hand); -#ifdef _IS_WINDOWS_ - if (sErr == U14ERR_NOERROR) - { - TCSBLOCK csBlock; - csBlock.ints[0] = (short)wArea; /* Area number into control block */ - sErr = U14Control1401(hand, U14_UNSETTRANSFER, &csBlock); /* Free area */ - - VirtualUnlock(apAreas[hand][wArea], auAreas[hand][wArea]);/* Unlock */ - apAreas[hand][wArea] = NULL; /* Clear locations */ - auAreas[hand][wArea] = 0; - } - return sErr; -#endif -#ifdef LINUX - return (sErr == U14ERR_NOERROR) ? CED_UnsetTransfer(aHand1401[hand], wArea) : sErr; -#endif -} - -/**************************************************************************** -** U14SetTransArea Sets an area up to be used for transfers -** WORD wArea The area number to set up -** void *pvBuff The address of the buffer for the data. -** DWORD dwLength The length of the buffer for the data -** short eSz The element size (used for byte swapping on the Mac) -****************************************************************************/ -U14API(short) U14SetTransArea(short hand, WORD wArea, void *pvBuff, - DWORD dwLength, short eSz) -{ - TRANSFERDESC td; - short sErr = CheckHandle(hand); - if (sErr != U14ERR_NOERROR) - return sErr; - if (wArea >= MAX_TRANSAREAS) // Is this a valid area number - return U14ERR_BADAREA; - -#ifdef _IS_WINDOWS_ - assert(apAreas[hand][wArea] == NULL); - assert(auAreas[hand][wArea] == 0); - - apAreas[hand][wArea] = pvBuff; /* Save data for later */ - auAreas[hand][wArea] = dwLength; - - if (!VirtualLock(pvBuff, dwLength)) /* Lock using WIN32 calls */ - { - apAreas[hand][wArea] = NULL; /* Clear locations */ - auAreas[hand][wArea] = 0; - return U14ERR_LOCKERR; /* VirtualLock failed */ - } -#ifndef _WIN64 - if (!USE_NT_DIOC(hand)) /* Use Win 9x DIOC? */ - { - DWORD dwBytes; - VXTRANSFERDESC vxDesc; /* Structure to pass to VXD */ - vxDesc.wArea = wArea; /* Copy across simple params */ - vxDesc.dwLength = dwLength; - - // Check we are not asking an old driver for more than area 0 - if ((wArea != 0) && (U14DriverVersion(hand) < 0x00010002L)) - sErr = U14ERR_DRIVTOOOLD; - else - { - vxDesc.dwAddrOfs = (DWORD)pvBuff; /* 32 bit offset */ - vxDesc.wAddrSel = 0; - - if (DeviceIoControl(aHand1401[hand], (DWORD)U14_SETTRANSFER, - pvBuff,dwLength, /* Will translate pointer */ - &vxDesc,sizeof(VXTRANSFERDESC), - &dwBytes,NULL)) - { - if (dwBytes >= sizeof(VXTRANSFERDESC)) /* Driver OK ? */ - sErr = U14ERR_NOERROR; - else - sErr = U14ERR_DRIVCOMMS; /* Else never got there */ - } - else - sErr = (short)GetLastError(); - } - } - else -#endif - { - PARAMBLK rWork; - DWORD dwBytes; - td.wArea = wArea; /* Pure NT - put data into struct */ - td.lpvBuff = pvBuff; - td.dwLength = dwLength; - td.eSize = 0; // Dummy element size - - if (DeviceIoControl(aHand1401[hand],(DWORD)U14_SETTRANSFER, - &td,sizeof(TRANSFERDESC), - &rWork,sizeof(PARAMBLK),&dwBytes,NULL)) - { - if (dwBytes >= sizeof(PARAMBLK)) // maybe error from driver? - sErr = rWork.sState; // will report any error - else - sErr = U14ERR_DRIVCOMMS; // Else never got there - } - else - sErr = U14ERR_DRIVCOMMS; - } - - if (sErr != U14ERR_NOERROR) - { - if (sErr != U14ERR_LOCKERR) // unless lock failed... - VirtualUnlock(pvBuff, dwLength); // ...release the lock - apAreas[hand][wArea] = NULL; // Clear locations - auAreas[hand][wArea] = 0; - } - - return sErr; -#endif -#ifdef LINUX - // The strange cast is so that it works in 64 and 32-bit linux as long is 64-bits - // in the 64 bit version. - td.lpvBuff = (long long)((unsigned long)pvBuff); - td.wAreaNum = wArea; - td.dwLength = dwLength; - td.eSize = eSz; // Dummy element size - return CED_SetTransfer(aHand1401[hand], &td); -#endif -} - -/**************************************************************************** -** U14SetTransferEvent Sets an event for notification of application -** wArea The tranfer area index, from 0 to MAXAREAS-1 -** bEvent True to create an event, false to remove it -** bToHost Set 0 for notification on to1401 tranfers, 1 for -** notification of transfers to the host PC -** dwStart The offset of the sub-area of interest -** dwLength The size of the sub-area of interest -** -** The device driver will set the event supplied to the signalled state -** whenever a DMA transfer to/from the specified area is completed. The -** transfer has to be in the direction specified by bToHost, and overlap -** that part of the whole transfer area specified by dwStart and dwLength. -** It is important that this function is called with bEvent false to release -** the event once 1401 activity is finished. -** -** Returns 1 if an event handle exists, 0 if all OK and no event handle or -** a negative code for an error. -****************************************************************************/ -U14API(short) U14SetTransferEvent(short hand, WORD wArea, BOOL bEvent, - BOOL bToHost, DWORD dwStart, DWORD dwLength) -{ -#ifdef _IS_WINDOWS_ - TCSBLOCK csBlock; - short sErr = U14TransferFlags(hand); // see if we can handle events - if (sErr >= U14ERR_NOERROR) // check handle is OK - { - bEvent = bEvent && ((sErr & U14TF_NOTIFY) != 0); // remove request if we cannot do events - if (wArea >= MAX_TRANSAREAS) // Check a valid area... - return U14ERR_BADAREA; // ...and bail of not - - // We can hold an event for each area, so see if we need to change the - // state of the event. - if ((bEvent != 0) != (aXferEvent[hand] != 0)) // change of event state? - { - if (bEvent) // want one and none present - aXferEvent[hand] = CreateEvent(NULL, FALSE, FALSE, NULL); - else - { - CloseHandle(aXferEvent[hand]); // clear the existing event - aXferEvent[hand] = NULL; // and clear handle - } - } - - // We have to store the parameters differently for 64-bit operations - // because a handle is 64 bits long. The drivers know of this and - // handle the information appropriately. -#ifdef _WIN64 - csBlock.longs[0] = wArea; // Pass paramaters into the driver... - if (bToHost != 0) // The direction flag is held in the - csBlock.longs[0] |= 0x10000; // upper word of the transfer area value - *((HANDLE*)&csBlock.longs[1]) = aXferEvent[hand]; // The event handle is 64-bits - csBlock.longs[3] = dwStart; // Thankfully these two remain - csBlock.longs[4] = dwLength; // as unsigned 32-bit values -#else - csBlock.longs[0] = wArea; // pass paramaters into the driver... - csBlock.longs[1] = (long)aXferEvent[hand]; // ...especially the event handle - csBlock.longs[2] = bToHost; - csBlock.longs[3] = dwStart; - csBlock.longs[4] = dwLength; -#endif - sErr = U14Control1401(hand, U14_SETTRANSEVENT, &csBlock); - if (sErr == U14ERR_NOERROR) - sErr = (short)(aXferEvent[hand] != NULL); // report if we have a flag - } - - return sErr; -#endif -#ifdef LINUX - TRANSFEREVENT te; - short sErr = CheckHandle(hand); - if (sErr != U14ERR_NOERROR) - return sErr; - - if (wArea >= MAX_TRANSAREAS) // Is this a valid area number - return U14ERR_BADAREA; - - te.wAreaNum = wArea; // copy parameters to the control block - te.wFlags = bToHost ? 1 : 0; // bit 0 sets the direction - te.dwStart = dwStart; // start offset of the event area - te.dwLength = dwLength; // size of the event area - te.iSetEvent = bEvent; // in Windows, this creates/destroys the event - return CED_SetEvent(aHand1401[hand], &te); -#endif -} - -/**************************************************************************** -** U14TestTransferEvent -** Would a U14WaitTransferEvent() call return immediately? return 1 if so, -** 0 if not or a negative code if a problem. -****************************************************************************/ -U14API(int) U14TestTransferEvent(short hand, WORD wArea) -{ -#ifdef _IS_WINDOWS_ - int iErr = CheckHandle(hand); - if (iErr == U14ERR_NOERROR) - { - if (aXferEvent[hand]) // if a handle is set... - iErr = WaitForSingleObject(aXferEvent[hand], 0) == WAIT_OBJECT_0; - } - return iErr; -#endif -#ifdef LINUX - short sErr = CheckHandle(hand); - return (sErr == U14ERR_NOERROR) ? CED_TestEvent(aHand1401[hand], wArea) : sErr; -#endif -} - -/**************************************************************************** -** U14WaitTransferEvent -** Wait for a transfer event with a timeout. -** msTimeOut is 0 for an infinite wait, else it is the maximum time to wait -** in milliseconds in range 0-0x00ffffff. -** Returns If no event handle then return immediately. Else return 1 if -** timed out or 0=event, and a negative code if a problem. -****************************************************************************/ -U14API(int) U14WaitTransferEvent(short hand, WORD wArea, int msTimeOut) -{ -#ifdef _IS_WINDOWS_ - int iErr = CheckHandle(hand); - if (iErr == U14ERR_NOERROR) - { - if (aXferEvent[hand]) - { - if (msTimeOut == 0) - msTimeOut = INFINITE; - iErr = WaitForSingleObject(aXferEvent[hand], msTimeOut) != WAIT_OBJECT_0; - } - else - iErr = TRUE; // say we timed out if no event - } - return iErr; -#endif -#ifdef LINUX - short sErr = CheckHandle(hand); - return (sErr == U14ERR_NOERROR) ? CED_WaitEvent(aHand1401[hand], wArea, msTimeOut) : sErr; -#endif -} - -/**************************************************************************** -** U14SetCircular Sets an area up for circular DMA transfers -** WORD wArea The area number to set up -** BOOL bToHost Sets the direction of data transfer -** void *pvBuff The address of the buffer for the data -** DWORD dwLength The length of the buffer for the data -****************************************************************************/ -U14API(short) U14SetCircular(short hand, WORD wArea, BOOL bToHost, - void *pvBuff, DWORD dwLength) -{ - short sErr = CheckHandle(hand); - if (sErr != U14ERR_NOERROR) - return sErr; - - if (wArea >= MAX_TRANSAREAS) /* Is this a valid area number */ - return U14ERR_BADAREA; - - if (!bToHost) /* For now, support tohost transfers only */ - return U14ERR_BADAREA; /* best error code I can find */ -#ifdef _IS_WINDOWS_ - assert(apAreas[hand][wArea] == NULL); - assert(auAreas[hand][wArea] == 0); - - apAreas[hand][wArea] = pvBuff; /* Save data for later */ - auAreas[hand][wArea] = dwLength; - - if (!VirtualLock(pvBuff, dwLength)) /* Lock using WIN32 calls */ - sErr = U14ERR_LOCKERR; /* VirtualLock failed */ - else - { - PARAMBLK rWork; - DWORD dwBytes; - TRANSFERDESC txDesc; - txDesc.wArea = wArea; /* Pure NT - put data into struct */ - txDesc.lpvBuff = pvBuff; - txDesc.dwLength = dwLength; - txDesc.eSize = (short)bToHost; /* Use this for direction flag */ - - if (DeviceIoControl(aHand1401[hand],(DWORD)U14_SETCIRCULAR, - &txDesc, sizeof(TRANSFERDESC), - &rWork, sizeof(PARAMBLK),&dwBytes,NULL)) - { - if (dwBytes >= sizeof(PARAMBLK)) /* error from driver? */ - sErr = rWork.sState; /* No, just return driver data */ - else - sErr = U14ERR_DRIVCOMMS; /* Else never got there */ - } - else - sErr = U14ERR_DRIVCOMMS; - } - - if (sErr != U14ERR_NOERROR) - { - if (sErr != U14ERR_LOCKERR) - VirtualUnlock(pvBuff, dwLength); /* Release NT lock */ - apAreas[hand][wArea] = NULL; /* Clear locations */ - auAreas[hand][wArea] = 0; - } - - return sErr; -#endif -#ifdef LINUX - else - { - TRANSFERDESC td; - td.lpvBuff = (long long)((unsigned long)pvBuff); - td.wAreaNum = wArea; - td.dwLength = dwLength; - td.eSize = (short)bToHost; /* Use this for direction flag */ - return CED_SetCircular(aHand1401[hand], &td); - } -#endif -} - -/**************************************************************************** -** Function GetCircBlk returns the size (& start offset) of the next -** available block of circular data. -****************************************************************************/ -U14API(int) U14GetCircBlk(short hand, WORD wArea, DWORD *pdwOffs) -{ - int lErr = CheckHandle(hand); - if (lErr != U14ERR_NOERROR) - return lErr; - - if (wArea >= MAX_TRANSAREAS) // Is this a valid area number? - return U14ERR_BADAREA; - else - { -#ifdef _IS_WINDOWS_ - PARAMBLK rWork; - TCSBLOCK csBlock; - DWORD dwBytes; - csBlock.longs[0] = wArea; // Area number into control block - rWork.sState = U14ERR_DRIVCOMMS; - if (DeviceIoControl(aHand1401[hand], (DWORD)U14_GETCIRCBLK, &csBlock, sizeof(TCSBLOCK), &rWork, sizeof(PARAMBLK), &dwBytes, NULL) && - (dwBytes >= sizeof(PARAMBLK))) - lErr = rWork.sState; - else - lErr = U14ERR_DRIVCOMMS; - - if (lErr == U14ERR_NOERROR) // Did everything go OK? - { // Yes, we can pass the results back - lErr = rWork.csBlock.longs[1]; // Return the block information - *pdwOffs = rWork.csBlock.longs[0]; // Offset is first in array - } -#endif -#ifdef LINUX - TCIRCBLOCK cb; - cb.nArea = wArea; // Area number into control block - cb.dwOffset = 0; - cb.dwSize = 0; - lErr = CED_GetCircBlock(aHand1401[hand], &cb); - if (lErr == U14ERR_NOERROR) // Did everything go OK? - { // Yes, we can pass the results back - lErr = cb.dwSize; // return the size - *pdwOffs = cb.dwOffset; // and the offset - } -#endif - } - return lErr; -} - -/**************************************************************************** -** Function FreeCircBlk marks the specified area of memory as free for -** resuse for circular transfers and returns the size (& start -** offset) of the next available block of circular data. -****************************************************************************/ -U14API(int) U14FreeCircBlk(short hand, WORD wArea, DWORD dwOffs, DWORD dwSize, - DWORD *pdwOffs) -{ - int lErr = CheckHandle(hand); - if (lErr != U14ERR_NOERROR) - return lErr; - - if (wArea < MAX_TRANSAREAS) // Is this a valid area number - { -#ifdef _IS_WINDOWS_ - PARAMBLK rWork; - TCSBLOCK csBlock; - DWORD dwBytes; - csBlock.longs[0] = wArea; // Area number into control block - csBlock.longs[1] = dwOffs; - csBlock.longs[2] = dwSize; - rWork.sState = U14ERR_DRIVCOMMS; - if (DeviceIoControl(aHand1401[hand], (DWORD)U14_FREECIRCBLK, &csBlock, sizeof(TCSBLOCK), - &rWork, sizeof(PARAMBLK), &dwBytes, NULL) && - (dwBytes >= sizeof(PARAMBLK))) - lErr = rWork.sState; - else - lErr = U14ERR_DRIVCOMMS; - if (lErr == U14ERR_NOERROR) // Did everything work OK? - { // Yes, we can pass the results back - lErr = rWork.csBlock.longs[1]; // Return the block information - *pdwOffs = rWork.csBlock.longs[0]; // Offset is first in array - } -#endif -#ifdef LINUX - TCIRCBLOCK cb; - cb.nArea = wArea; // Area number into control block - cb.dwOffset = dwOffs; - cb.dwSize = dwSize; - - lErr = CED_FreeCircBlock(aHand1401[hand], &cb); - if (lErr == U14ERR_NOERROR) // Did everything work OK? - { // Yes, we can pass the results back - lErr = cb.dwSize; // Return the block information - *pdwOffs = cb.dwOffset; // Offset is first in array - } -#endif - } - else - lErr = U14ERR_BADAREA; - - return lErr; -} - -/**************************************************************************** -** Transfer -** Transfer moves data to 1401 or to host -** Assumes memory is allocated and locked, -** which it should be to get a pointer -*****************************************************************************/ -static short Transfer(short hand, BOOL bTo1401, char* pData, - DWORD dwSize, DWORD dw1401, short eSz) -{ - char strcopy[MAXSTRLEN+1]; // to hold copy of work string - short sResult = U14SetTransArea(hand, 0, (void *)pData, dwSize, eSz); - if (sResult == U14ERR_NOERROR) // no error - { - sprintf(strcopy, // data offset is always 0 - "TO%s,$%X,$%X,0;", bTo1401 ? "1401" : "HOST", dw1401, dwSize); - - U14SendString(hand, strcopy); // send transfer string - - sResult = U14CheckErr(hand); // Use ERR command to check for done - if (sResult > 0) - sResult = U14ERR_TOXXXERR; // If a 1401 error, use this code - - U14UnSetTransfer(hand, 0); - } - return sResult; -} - -/**************************************************************************** -** Function ToHost transfers data into the host from the 1401 -****************************************************************************/ -U14API(short) U14ToHost(short hand, char* pAddrHost, DWORD dwSize, - DWORD dw1401, short eSz) -{ - short sErr = CheckHandle(hand); - if ((sErr == U14ERR_NOERROR) && dwSize) // TOHOST is a constant - sErr = Transfer(hand, TOHOST, pAddrHost, dwSize, dw1401, eSz); - return sErr; -} - -/**************************************************************************** -** Function To1401 transfers data into the 1401 from the host -****************************************************************************/ -U14API(short) U14To1401(short hand, const char* pAddrHost,DWORD dwSize, - DWORD dw1401, short eSz) -{ - short sErr = CheckHandle(hand); - if ((sErr == U14ERR_NOERROR) && dwSize) // TO1401 is a constant - sErr = Transfer(hand, TO1401, (char*)pAddrHost, dwSize, dw1401, eSz); - return sErr; -} - -/**************************************************************************** -** Function LdCmd Loads a command from a full path or just a file -*****************************************************************************/ -#ifdef _IS_WINDOWS_ -#define file_exist(name) (_access(name, 0) != -1) -#define file_open(name) _lopen(name, OF_READ) -#define file_close(h) _lclose(h) -#define file_seek(h, pos) _llseek(h, pos, FILE_BEGIN) -#define file_read(h, buffer, size) (_lread(h, buffer, size) == size) -#endif -#ifdef LINUX -#define file_exist(name) (access(name, F_OK) != -1) -#define file_open(name) open(name, O_RDONLY) -#define file_close(h) close(h) -#define file_seek(h, pos) lseek(h, pos, SEEK_SET) -#define file_read(h, buffer, size) (read(h, buffer, size) == (ssize_t)size) -static DWORD GetModuleFileName(void* dummy, char* buffer, int max) -{ - // The following works for Linux systems with a /proc file system. - char szProcPath[32]; - sprintf(szProcPath, "/proc/%d/exe", getpid()); // attempt to read link - if (readlink(szProcPath, buffer, max) != -1) - { - dirname (buffer); - strcat (buffer, "/"); - return strlen(buffer); - } - return 0; -} -#endif - -U14API(short) U14LdCmd(short hand, const char* command) -{ - char strcopy[MAXSTRLEN+1]; // to hold copy of work string - BOOL bGotIt = FALSE; // have we found the command file? - int iFHandle; // file handle of command -#define FNSZ 260 - char filnam[FNSZ]; // space to build name in - char szCmd[25]; // just the command name with extension - - short sErr = CheckHandle(hand); - if (sErr != U14ERR_NOERROR) - return sErr; - - if (strchr(command, '.') != NULL) // see if we have full name - { - if (file_exist(command)) // If the file exists - { - strcpy(filnam, command); // use name as is - bGotIt = TRUE; // Flag no more searching - } - else // not found, get file name for search - { - char* pStr = strrchr(command, PATHSEP); // Point to last separator - if (pStr != NULL) // Check we got it - { - pStr++; // move past the backslash - strcpy(szCmd, pStr); // copy file name as is - } - else - strcpy(szCmd, command); // use as is - } - } - else // File extension not supplied, so build the command file name - { - char szExt[8]; - strcpy(szCmd, command); // Build command file name - ExtForType(asType1401[hand], szExt);// File extension string - strcat(szCmd, szExt); // add it to the end - } - - // Next place to look is in the 1401 folder in the same place as the - // application was run from. - if (!bGotIt) // Still not got it? - { - DWORD dwLen = GetModuleFileName(NULL, filnam, FNSZ); // Get app path - if (dwLen > 0) // and use it as path if found - { - char* pStr = strrchr(filnam, PATHSEP); // Point to last separator - if (pStr != NULL) - { - *(++pStr) = 0; // Terminate string there - if (strlen(filnam) < FNSZ-6) // make sure we have space - { - strcat(filnam, "1401" PATHSEPSTR); // add in 1401 subdir - strcat(filnam,szCmd); - bGotIt = (BOOL)file_exist(filnam); // See if file exists - } - } - } - } - - // Next place to look is in whatever path is set by the 1401DIR environment - // variable, if it exists. - if (!bGotIt) // Need to do more searches?/ - { - char* pStr = getenv("1401DIR"); // Try to find environment var - if (pStr != NULL) // and use it as path if found - { - strcpy(filnam, pStr); // Use path in environment - if (filnam[strlen(filnam)-1] != PATHSEP)// We need separator - strcat(filnam, PATHSEPSTR); - strcat(filnam, szCmd); - bGotIt = (BOOL)file_exist(filnam); // Got this one? - } - } - - // Last place to look is the default location. - if (!bGotIt) // Need to do more searches? - { - strcpy(filnam, DEFCMDPATH); // Use default path - strcat(filnam, szCmd); - bGotIt = file_exist(filnam); // Got this one? - } - - iFHandle = file_open(filnam); - if (iFHandle == -1) - sErr = U14ERR_NOFILE; - else - { // first read in the header block - CMDHEAD rCmdHead; // to hold the command header - if (file_read(iFHandle, &rCmdHead, sizeof(CMDHEAD))) - { - size_t nComSize = rCmdHead.wCmdSize; - char* pMem = malloc(nComSize); - if (pMem != NULL) - { - file_seek(iFHandle, sizeof(CMDHEAD)); - if (file_read(iFHandle, pMem, (UINT)nComSize)) - { - sErr = U14SetTransArea(hand, 0, (void *)pMem, (DWORD)nComSize, ESZBYTES); - if (sErr == U14ERR_NOERROR) - { - sprintf(strcopy, "CLOAD,0,$%X;", (int)nComSize); - sErr = U14SendString(hand, strcopy); - if (sErr == U14ERR_NOERROR) - { - sErr = U14CheckErr(hand); // Use ERR to check for done - if (sErr > 0) - sErr = U14ERR_CLOADERR; // If an error, this code - } - U14UnSetTransfer(hand, 0); // release transfer area - } - } - else - sErr = U14ERR_READERR; - free(pMem); - } - else - sErr = U14ERR_HOSTSPACE; // memory allocate failed - } - else - sErr = U14ERR_READERR; - - file_close(iFHandle); // close the file - } - - return sErr; -} - - -/**************************************************************************** -** Ld -** Loads a command into the 1401 -** Returns NOERROR code or a long with error in lo word and index of -** command that failed in high word -****************************************************************************/ -U14API(DWORD) U14Ld(short hand, const char* vl, const char* str) -{ - DWORD dwIndex = 0; // index to current command - long lErr = U14ERR_NOERROR; // what the error was that went wrong - char strcopy[MAXSTRLEN+1]; // stores unmodified str parameter - char szFExt[8]; // The command file extension - short sErr = CheckHandle(hand); - if (sErr != U14ERR_NOERROR) - return sErr; - - ExtForType(asType1401[hand], szFExt); // File extension string - strcpy(strcopy, str); // to avoid changing original - - // now break out one command at a time and see if loaded - if (*str) // if anything there - { - BOOL bDone = FALSE; // true when finished all commands - int iLoop1 = 0; // Point at start of string for command name - int iLoop2 = 0; // and at start of str parameter - do // repeat until end of str - { - char filnam[MAXSTRLEN+1]; // filename to use - char szFName[MAXSTRLEN+1]; // filename work string - - if (!strcopy[iLoop1]) // at the end of the string? - bDone = TRUE; // set the finish flag - - if (bDone || (strcopy[iLoop1] == ',')) // end of cmd? - { - U14LONG er[5]; // Used to read back error results - ++dwIndex; // Keep count of command number, first is 1 - szFName[iLoop2]=(char)0; // null terminate name of command - - strncpy(szLastName, szFName, sizeof(szLastName)); // Save for error info - szLastName[sizeof(szLastName)-1] = 0; - strncat(szLastName, szFExt, sizeof(szLastName)); // with extension included - szLastName[sizeof(szLastName)-1] = 0; - - U14SendString(hand, szFName); // ask if loaded - U14SendString(hand, ";ERR;"); // add err return - - lErr = U14LongsFrom1401(hand, er, 5); - if (lErr > 0) - { - lErr = U14ERR_NOERROR; - if (er[0] == 255) // if command not loaded at all - { - if (vl && *vl) // if we have a path name - { - strcpy(filnam, vl); - if (strchr("\\/:", filnam[strlen(filnam)-1]) == NULL) - strcat(filnam, PATHSEPSTR); // add separator if none found - strcat(filnam, szFName); // add the file name - strcat(filnam, szFExt); // and extension - } - else - strcpy(filnam, szFName); // simple name - - lErr = U14LdCmd(hand, filnam); // load cmd - if (lErr != U14ERR_NOERROR) // spot any errors - bDone = TRUE; // give up if an error - } - } - else - bDone = TRUE; // give up if an error - - iLoop2 = 0; // Reset pointer to command name string - ++iLoop1; // and move on through str parameter - } - else - szFName[iLoop2++] = strcopy[iLoop1++]; // no command end, so copy 1 char - } - while (!bDone); - } - - if (lErr == U14ERR_NOERROR) - { - szLastName[0] = 0; // No error, so clean out command name here - return lErr; - } - else - return ((dwIndex<<16) | ((DWORD)lErr & 0x0000FFFF)); -} - -// Initialise the library (if not initialised) and return the library version -U14API(int) U14InitLib(void) -{ - int iRetVal = U14LIB_VERSION; - if (iAttached == 0) // only do this the first time please - { - int i; -#ifdef _IS_WINDOWS_ - int j; - DWORD dwVersion = GetVersion(); - bWindows9x = FALSE; // Assume not Win9x - - if (dwVersion & 0x80000000) // if not windows NT - { - if ((LOBYTE(LOWORD(dwVersion)) < 4) && // if Win32s or... - (HIBYTE(LOWORD(dwVersion)) < 95)) // ...below Windows 95 - iRetVal = 0; // We do not support this - else - bWindows9x = TRUE; // Flag we have Win9x - } -#endif - - for (i = 0; i < MAX1401; i++) // initialise the device area - { - aHand1401[i] = INVALID_HANDLE_VALUE; // Clear handle values - asType1401[i] = U14TYPEUNKNOWN; // and 1401 type codes - alTimeOutPeriod[i] = 3000; // 3 second timeouts -#ifdef _IS_WINDOWS_ -#ifndef _WIN64 - abUseNTDIOC[i] = (BOOL)!bWindows9x; -#endif - aXferEvent[i] = NULL; // there are no Xfer events - for (j = 0; j < MAX_TRANSAREAS; j++) // Clear out locked area info - { - apAreas[i][j] = NULL; - auAreas[i][j] = 0; - } -#endif - } - } - return iRetVal; -} - -///-------------------------------------------------------------------------------- -/// Functions called when the library is loaded and unloaded to give us a chance to -/// setup the library. - - -#ifdef _IS_WINDOWS_ -#ifndef U14_NOT_DLL -/**************************************************************************** -** FUNCTION: DllMain(HANDLE, DWORD, LPVOID) -** LibMain is called by Windows when the DLL is initialized, Thread Attached, -** and other times. Refer to SDK documentation, as to the different ways this -** may be called. -****************************************************************************/ -INT APIENTRY DllMain(HANDLE hInst, DWORD ul_reason_being_called, LPVOID lpReserved) -{ - int iRetVal = 1; - - switch (ul_reason_being_called) - { - case DLL_PROCESS_ATTACH: - iRetVal = U14InitLib() > 0; // does nothing if iAttached != 0 - ++iAttached; // count times attached - break; - - case DLL_PROCESS_DETACH: - if (--iAttached == 0) // last man out? - U14CloseAll(); // release all open handles - break; - } - return iRetVal; - - UNREFERENCED_PARAMETER(lpReserved); -} -#endif -#endif -#ifdef LINUX -void __attribute__((constructor)) use1401_load(void) -{ - U14InitLib(); - ++iAttached; -} - -void __attribute__((destructor)) use1401_unload(void) -{ - if (--iAttached == 0) // last man out? - U14CloseAll(); // release all open handles -} -#endif diff --git a/trunk/drivers/staging/comedi/Kconfig b/trunk/drivers/staging/comedi/Kconfig index 2093403af253..6cee7855b019 100644 --- a/trunk/drivers/staging/comedi/Kconfig +++ b/trunk/drivers/staging/comedi/Kconfig @@ -549,23 +549,6 @@ menuconfig COMEDI_PCI_DRIVERS if COMEDI_PCI_DRIVERS -config COMEDI_8255_PCI - tristate "Generic PCI based 8255 digital i/o board support" - select COMEDI_8255 - ---help--- - Enable support for PCI based 8255 digital i/o boards. This driver - provides a PCI wrapper around the generic 8255 driver. - - Supported boards: - ADlink - PCI-7224, PCI-7248, and PCI-7296 - Measurement Computing - PCI-DIO24, PCI-DIO24H, PCI-DIO48H and - PCI-DIO96H - National Instruments - PCI-DIO-96, PCI-DIO-96B, PXI-6508, PCI-6503, - PCI-6503B, PCI-6503X, and PXI-6503 - - To compile this driver as a module, choose M here: the module will - be called 8255_pci. - config COMEDI_ADDI_APCI_035 tristate "ADDI-DATA APCI_035 support" depends on VIRT_TO_BUS @@ -693,16 +676,30 @@ config COMEDI_ADL_PCI6208 To compile this driver as a module, choose M here: the module will be called adl_pci6208. -config COMEDI_ADL_PCI7X3X - tristate "ADLink PCI-723X/743X isolated digital i/o board support" +config COMEDI_ADL_PCI7230 + tristate "ADLink PCI-7230 digital io board support" + ---help--- + Enable support for ADlink PCI-7230 digital io board support + + To compile this driver as a module, choose M here: the module will be + called adl_pci7230. + +config COMEDI_ADL_PCI7296 + tristate "ADLink PCI-7296 96 ch. digital io board support" + select COMEDI_8255 ---help--- - Enable support for ADlink PCI-723X/743X isolated digital i/o boards. - Supported boards include the 32-channel PCI-7230 (16 in/16 out), - PCI-7233 (32 in), and PCI-7234 (32 out) as well as the 64-channel - PCI-7432 (32 in/32 out), PCI-7433 (64 in), and PCI-7434 (64 out). + Enable support for ADlink PCI-7296 96 ch. digital io board support To compile this driver as a module, choose M here: the module will be - called adl_pci7x3x. + called adl_pci7296. + +config COMEDI_ADL_PCI7432 + tristate "ADLink PCI-7432 64 ch. isolated digital io board support" + ---help--- + Enable support for ADlink PCI-7432 64 ch. isolated digital io board + + To compile this driver as a module, choose M here: the module will be + called adl_pci7432. config COMEDI_ADL_PCI8164 tristate "ADLink PCI-8164 4 Axes Motion Control board support" @@ -938,6 +935,16 @@ config COMEDI_CB_PCIDDA To compile this driver as a module, choose M here: the module will be called cb_pcidda. +config COMEDI_CB_PCIDIO + tristate "MeasurementComputing PCI-DIO series support" + select COMEDI_8255 + ---help--- + Enable support for ComputerBoards/MeasurementComputing PCI-DIO series + PCI-DIO24, PCI-DIO24H and PCI-DIO48H + + To compile this driver as a module, choose M here: the module will be + called cb_pcidio. + config COMEDI_CB_PCIMDAS tristate "MeasurementComputing PCIM-DAS1602/16 support" select COMEDI_8255 @@ -1032,12 +1039,15 @@ config COMEDI_NI_LABPC called ni_labpc. config COMEDI_NI_PCIDIO - tristate "NI PCI-DIO32HS, PCI-6533, PCI-6534 support" + tristate "NI PCI-DIO32HS, PCI-DIO96, PCI-6533, PCI-6503 support" select COMEDI_MITE select COMEDI_8255 ---help--- Enable support for National Instruments PCI-DIO-32HS, PXI-6533, - PCI-6533 and PCI-6534 + PCI-DIO-96, PCI-DIO-96B, PXI-6508, PCI-6503, PCI-6503B, PCI-6503X, + PXI-6503, PCI-6533 and PCI-6534 + The DIO-96 appears as four 8255 subdevices. See the 8255 + driver notes for details. To compile this driver as a module, choose M here: the module will be called ni_pcidio. @@ -1252,8 +1262,8 @@ config COMEDI_8255 that has an 8255 chip. For multifunction boards, the main driver will configure the 8255 subdevice automatically. - Note that most PCI based 8255 boards use the 8255_pci driver as a - wrapper around this driver. + Note that most PCI 8255 boards do NOT work with this driver, and + need a separate driver as a wrapper. To compile this driver as a module, choose M here: the module will be called 8255. diff --git a/trunk/drivers/staging/comedi/comedi.h b/trunk/drivers/staging/comedi/comedi.h index 133f013e0f6d..8ea55aef10a7 100644 --- a/trunk/drivers/staging/comedi/comedi.h +++ b/trunk/drivers/staging/comedi/comedi.h @@ -208,92 +208,92 @@ /* subdevice types */ -enum comedi_subdevice_type { - COMEDI_SUBD_UNUSED, /* unused by driver */ - COMEDI_SUBD_AI, /* analog input */ - COMEDI_SUBD_AO, /* analog output */ - COMEDI_SUBD_DI, /* digital input */ - COMEDI_SUBD_DO, /* digital output */ - COMEDI_SUBD_DIO, /* digital input/output */ - COMEDI_SUBD_COUNTER, /* counter */ - COMEDI_SUBD_TIMER, /* timer */ - COMEDI_SUBD_MEMORY, /* memory, EEPROM, DPRAM */ - COMEDI_SUBD_CALIB, /* calibration DACs */ - COMEDI_SUBD_PROC, /* processor, DSP */ - COMEDI_SUBD_SERIAL, /* serial IO */ - COMEDI_SUBD_PWM /* PWM */ -}; + enum comedi_subdevice_type { + COMEDI_SUBD_UNUSED, /* unused by driver */ + COMEDI_SUBD_AI, /* analog input */ + COMEDI_SUBD_AO, /* analog output */ + COMEDI_SUBD_DI, /* digital input */ + COMEDI_SUBD_DO, /* digital output */ + COMEDI_SUBD_DIO, /* digital input/output */ + COMEDI_SUBD_COUNTER, /* counter */ + COMEDI_SUBD_TIMER, /* timer */ + COMEDI_SUBD_MEMORY, /* memory, EEPROM, DPRAM */ + COMEDI_SUBD_CALIB, /* calibration DACs */ + COMEDI_SUBD_PROC, /* processor, DSP */ + COMEDI_SUBD_SERIAL, /* serial IO */ + COMEDI_SUBD_PWM /* PWM */ + }; /* configuration instructions */ -enum configuration_ids { - INSN_CONFIG_DIO_INPUT = 0, - INSN_CONFIG_DIO_OUTPUT = 1, - INSN_CONFIG_DIO_OPENDRAIN = 2, - INSN_CONFIG_ANALOG_TRIG = 16, + enum configuration_ids { + INSN_CONFIG_DIO_INPUT = 0, + INSN_CONFIG_DIO_OUTPUT = 1, + INSN_CONFIG_DIO_OPENDRAIN = 2, + INSN_CONFIG_ANALOG_TRIG = 16, /* INSN_CONFIG_WAVEFORM = 17, */ /* INSN_CONFIG_TRIG = 18, */ /* INSN_CONFIG_COUNTER = 19, */ - INSN_CONFIG_ALT_SOURCE = 20, - INSN_CONFIG_DIGITAL_TRIG = 21, - INSN_CONFIG_BLOCK_SIZE = 22, - INSN_CONFIG_TIMER_1 = 23, - INSN_CONFIG_FILTER = 24, - INSN_CONFIG_CHANGE_NOTIFY = 25, - - INSN_CONFIG_SERIAL_CLOCK = 26, /*ALPHA*/ - INSN_CONFIG_BIDIRECTIONAL_DATA = 27, - INSN_CONFIG_DIO_QUERY = 28, - INSN_CONFIG_PWM_OUTPUT = 29, - INSN_CONFIG_GET_PWM_OUTPUT = 30, - INSN_CONFIG_ARM = 31, - INSN_CONFIG_DISARM = 32, - INSN_CONFIG_GET_COUNTER_STATUS = 33, - INSN_CONFIG_RESET = 34, - /* Use CTR as single pulsegenerator */ - INSN_CONFIG_GPCT_SINGLE_PULSE_GENERATOR = 1001, - /* Use CTR as pulsetraingenerator */ - INSN_CONFIG_GPCT_PULSE_TRAIN_GENERATOR = 1002, - /* Use the counter as encoder */ - INSN_CONFIG_GPCT_QUADRATURE_ENCODER = 1003, - INSN_CONFIG_SET_GATE_SRC = 2001, /* Set gate source */ - INSN_CONFIG_GET_GATE_SRC = 2002, /* Get gate source */ - /* Set master clock source */ - INSN_CONFIG_SET_CLOCK_SRC = 2003, - INSN_CONFIG_GET_CLOCK_SRC = 2004, /* Get master clock source */ - INSN_CONFIG_SET_OTHER_SRC = 2005, /* Set other source */ - /* INSN_CONFIG_GET_OTHER_SRC = 2006,*//* Get other source */ - /* Get size in bytes of subdevice's on-board fifos used during - * streaming input/output */ - INSN_CONFIG_GET_HARDWARE_BUFFER_SIZE = 2006, - INSN_CONFIG_SET_COUNTER_MODE = 4097, - /* INSN_CONFIG_8254_SET_MODE is deprecated */ - INSN_CONFIG_8254_SET_MODE = INSN_CONFIG_SET_COUNTER_MODE, - INSN_CONFIG_8254_READ_STATUS = 4098, - INSN_CONFIG_SET_ROUTING = 4099, - INSN_CONFIG_GET_ROUTING = 4109, - /* PWM */ - INSN_CONFIG_PWM_SET_PERIOD = 5000, /* sets frequency */ - INSN_CONFIG_PWM_GET_PERIOD = 5001, /* gets frequency */ - INSN_CONFIG_GET_PWM_STATUS = 5002, /* is it running? */ - /* sets H bridge: duty cycle and sign bit for a relay at the - * same time */ - INSN_CONFIG_PWM_SET_H_BRIDGE = 5003, - /* gets H bridge data: duty cycle and the sign bit */ - INSN_CONFIG_PWM_GET_H_BRIDGE = 5004 -}; - -enum comedi_io_direction { - COMEDI_INPUT = 0, - COMEDI_OUTPUT = 1, - COMEDI_OPENDRAIN = 2 -}; - -enum comedi_support_level { - COMEDI_UNKNOWN_SUPPORT = 0, - COMEDI_SUPPORTED, - COMEDI_UNSUPPORTED -}; + INSN_CONFIG_ALT_SOURCE = 20, + INSN_CONFIG_DIGITAL_TRIG = 21, + INSN_CONFIG_BLOCK_SIZE = 22, + INSN_CONFIG_TIMER_1 = 23, + INSN_CONFIG_FILTER = 24, + INSN_CONFIG_CHANGE_NOTIFY = 25, + + /*ALPHA*/ INSN_CONFIG_SERIAL_CLOCK = 26, + INSN_CONFIG_BIDIRECTIONAL_DATA = 27, + INSN_CONFIG_DIO_QUERY = 28, + INSN_CONFIG_PWM_OUTPUT = 29, + INSN_CONFIG_GET_PWM_OUTPUT = 30, + INSN_CONFIG_ARM = 31, + INSN_CONFIG_DISARM = 32, + INSN_CONFIG_GET_COUNTER_STATUS = 33, + INSN_CONFIG_RESET = 34, + /* Use CTR as single pulsegenerator */ + INSN_CONFIG_GPCT_SINGLE_PULSE_GENERATOR = 1001, + /* Use CTR as pulsetraingenerator */ + INSN_CONFIG_GPCT_PULSE_TRAIN_GENERATOR = 1002, + /* Use the counter as encoder */ + INSN_CONFIG_GPCT_QUADRATURE_ENCODER = 1003, + INSN_CONFIG_SET_GATE_SRC = 2001, /* Set gate source */ + INSN_CONFIG_GET_GATE_SRC = 2002, /* Get gate source */ + /* Set master clock source */ + INSN_CONFIG_SET_CLOCK_SRC = 2003, + INSN_CONFIG_GET_CLOCK_SRC = 2004, /* Get master clock source */ + INSN_CONFIG_SET_OTHER_SRC = 2005, /* Set other source */ + /* INSN_CONFIG_GET_OTHER_SRC = 2006,*//* Get other source */ + /* Get size in bytes of subdevice's on-board fifos used during + * streaming input/output */ + INSN_CONFIG_GET_HARDWARE_BUFFER_SIZE = 2006, + INSN_CONFIG_SET_COUNTER_MODE = 4097, + /* INSN_CONFIG_8254_SET_MODE is deprecated */ + INSN_CONFIG_8254_SET_MODE = INSN_CONFIG_SET_COUNTER_MODE, + INSN_CONFIG_8254_READ_STATUS = 4098, + INSN_CONFIG_SET_ROUTING = 4099, + INSN_CONFIG_GET_ROUTING = 4109, +/* PWM */ + INSN_CONFIG_PWM_SET_PERIOD = 5000, /* sets frequency */ + INSN_CONFIG_PWM_GET_PERIOD = 5001, /* gets frequency */ + INSN_CONFIG_GET_PWM_STATUS = 5002, /* is it running? */ + /* sets H bridge: duty cycle and sign bit for a relay at the + * same time */ + INSN_CONFIG_PWM_SET_H_BRIDGE = 5003, + /* gets H bridge data: duty cycle and the sign bit */ + INSN_CONFIG_PWM_GET_H_BRIDGE = 5004 + }; + + enum comedi_io_direction { + COMEDI_INPUT = 0, + COMEDI_OUTPUT = 1, + COMEDI_OPENDRAIN = 2 + }; + + enum comedi_support_level { + COMEDI_UNKNOWN_SUPPORT = 0, + COMEDI_SUPPORTED, + COMEDI_UNSUPPORTED + }; /* ioctls */ @@ -317,133 +317,133 @@ enum comedi_support_level { /* structures */ -struct comedi_trig { - unsigned int subdev; /* subdevice */ - unsigned int mode; /* mode */ - unsigned int flags; - unsigned int n_chan; /* number of channels */ - unsigned int *chanlist; /* channel/range list */ - short *data; /* data list, size depends on subd flags */ - unsigned int n; /* number of scans */ - unsigned int trigsrc; - unsigned int trigvar; - unsigned int trigvar1; - unsigned int data_len; - unsigned int unused[3]; -}; - -struct comedi_insn { - unsigned int insn; - unsigned int n; - unsigned int __user *data; - unsigned int subdev; - unsigned int chanspec; - unsigned int unused[3]; -}; - -struct comedi_insnlist { - unsigned int n_insns; - struct comedi_insn __user *insns; -}; - -struct comedi_cmd { - unsigned int subdev; - unsigned int flags; - - unsigned int start_src; - unsigned int start_arg; - - unsigned int scan_begin_src; - unsigned int scan_begin_arg; - - unsigned int convert_src; - unsigned int convert_arg; - - unsigned int scan_end_src; - unsigned int scan_end_arg; - - unsigned int stop_src; - unsigned int stop_arg; - - unsigned int *chanlist; /* channel/range list */ - unsigned int chanlist_len; - - short __user *data; /* data list, size depends on subd flags */ - unsigned int data_len; -}; - -struct comedi_chaninfo { - unsigned int subdev; - unsigned int __user *maxdata_list; - unsigned int __user *flaglist; - unsigned int __user *rangelist; - unsigned int unused[4]; -}; - -struct comedi_rangeinfo { - unsigned int range_type; - void __user *range_ptr; -}; - -struct comedi_krange { - int min; /* fixed point, multiply by 1e-6 */ - int max; /* fixed point, multiply by 1e-6 */ - unsigned int flags; -}; - -struct comedi_subdinfo { - unsigned int type; - unsigned int n_chan; - unsigned int subd_flags; - unsigned int timer_type; - unsigned int len_chanlist; - unsigned int maxdata; - unsigned int flags; /* channel flags */ - unsigned int range_type; /* lookup in kernel */ - unsigned int settling_time_0; - /* see support_level enum for values */ - unsigned insn_bits_support; - unsigned int unused[8]; -}; - -struct comedi_devinfo { - unsigned int version_code; - unsigned int n_subdevs; - char driver_name[COMEDI_NAMELEN]; - char board_name[COMEDI_NAMELEN]; - int read_subdevice; - int write_subdevice; - int unused[30]; -}; - -struct comedi_devconfig { - char board_name[COMEDI_NAMELEN]; - int options[COMEDI_NDEVCONFOPTS]; -}; - -struct comedi_bufconfig { - unsigned int subdevice; - unsigned int flags; - - unsigned int maximum_size; - unsigned int size; - - unsigned int unused[4]; -}; - -struct comedi_bufinfo { - unsigned int subdevice; - unsigned int bytes_read; - - unsigned int buf_write_ptr; - unsigned int buf_read_ptr; - unsigned int buf_write_count; - unsigned int buf_read_count; - - unsigned int bytes_written; - - unsigned int unused[4]; -}; + struct comedi_trig { + unsigned int subdev; /* subdevice */ + unsigned int mode; /* mode */ + unsigned int flags; + unsigned int n_chan; /* number of channels */ + unsigned int *chanlist; /* channel/range list */ + short *data; /* data list, size depends on subd flags */ + unsigned int n; /* number of scans */ + unsigned int trigsrc; + unsigned int trigvar; + unsigned int trigvar1; + unsigned int data_len; + unsigned int unused[3]; + }; + + struct comedi_insn { + unsigned int insn; + unsigned int n; + unsigned int __user *data; + unsigned int subdev; + unsigned int chanspec; + unsigned int unused[3]; + }; + + struct comedi_insnlist { + unsigned int n_insns; + struct comedi_insn __user *insns; + }; + + struct comedi_cmd { + unsigned int subdev; + unsigned int flags; + + unsigned int start_src; + unsigned int start_arg; + + unsigned int scan_begin_src; + unsigned int scan_begin_arg; + + unsigned int convert_src; + unsigned int convert_arg; + + unsigned int scan_end_src; + unsigned int scan_end_arg; + + unsigned int stop_src; + unsigned int stop_arg; + + unsigned int __user *chanlist; /* channel/range list */ + unsigned int chanlist_len; + + short __user *data; /* data list, size depends on subd flags */ + unsigned int data_len; + }; + + struct comedi_chaninfo { + unsigned int subdev; + unsigned int __user *maxdata_list; + unsigned int __user *flaglist; + unsigned int __user *rangelist; + unsigned int unused[4]; + }; + + struct comedi_rangeinfo { + unsigned int range_type; + void __user *range_ptr; + }; + + struct comedi_krange { + int min; /* fixed point, multiply by 1e-6 */ + int max; /* fixed point, multiply by 1e-6 */ + unsigned int flags; + }; + + struct comedi_subdinfo { + unsigned int type; + unsigned int n_chan; + unsigned int subd_flags; + unsigned int timer_type; + unsigned int len_chanlist; + unsigned int maxdata; + unsigned int flags; /* channel flags */ + unsigned int range_type; /* lookup in kernel */ + unsigned int settling_time_0; + /* see support_level enum for values */ + unsigned insn_bits_support; + unsigned int unused[8]; + }; + + struct comedi_devinfo { + unsigned int version_code; + unsigned int n_subdevs; + char driver_name[COMEDI_NAMELEN]; + char board_name[COMEDI_NAMELEN]; + int read_subdevice; + int write_subdevice; + int unused[30]; + }; + + struct comedi_devconfig { + char board_name[COMEDI_NAMELEN]; + int options[COMEDI_NDEVCONFOPTS]; + }; + + struct comedi_bufconfig { + unsigned int subdevice; + unsigned int flags; + + unsigned int maximum_size; + unsigned int size; + + unsigned int unused[4]; + }; + + struct comedi_bufinfo { + unsigned int subdevice; + unsigned int bytes_read; + + unsigned int buf_write_ptr; + unsigned int buf_read_ptr; + unsigned int buf_write_count; + unsigned int buf_read_count; + + unsigned int bytes_written; + + unsigned int unused[4]; + }; /* range stuff */ @@ -495,306 +495,306 @@ struct comedi_bufinfo { */ -enum i8254_mode { - I8254_MODE0 = (0 << 1), /* Interrupt on terminal count */ - I8254_MODE1 = (1 << 1), /* Hardware retriggerable one-shot */ - I8254_MODE2 = (2 << 1), /* Rate generator */ - I8254_MODE3 = (3 << 1), /* Square wave mode */ - I8254_MODE4 = (4 << 1), /* Software triggered strobe */ - I8254_MODE5 = (5 << 1), /* Hardware triggered strobe - * (retriggerable) */ - I8254_BCD = 1, /* use binary-coded decimal instead of binary + enum i8254_mode { + I8254_MODE0 = (0 << 1), /* Interrupt on terminal count */ + I8254_MODE1 = (1 << 1), /* Hardware retriggerable one-shot */ + I8254_MODE2 = (2 << 1), /* Rate generator */ + I8254_MODE3 = (3 << 1), /* Square wave mode */ + I8254_MODE4 = (4 << 1), /* Software triggered strobe */ + I8254_MODE5 = (5 << 1), /* Hardware triggered strobe + * (retriggerable) */ + I8254_BCD = 1, /* use binary-coded decimal instead of binary * (pretty useless) */ - I8254_BINARY = 0 -}; - -static inline unsigned NI_USUAL_PFI_SELECT(unsigned pfi_channel) -{ - if (pfi_channel < 10) - return 0x1 + pfi_channel; - else - return 0xb + pfi_channel; -} - -static inline unsigned NI_USUAL_RTSI_SELECT(unsigned rtsi_channel) -{ - if (rtsi_channel < 7) - return 0xb + rtsi_channel; - else - return 0x1b; -} + I8254_BINARY = 0 + }; + + static inline unsigned NI_USUAL_PFI_SELECT(unsigned pfi_channel) + { + if (pfi_channel < 10) + return 0x1 + pfi_channel; + else + return 0xb + pfi_channel; + } + + static inline unsigned NI_USUAL_RTSI_SELECT(unsigned rtsi_channel) + { + if (rtsi_channel < 7) + return 0xb + rtsi_channel; + else + return 0x1b; + } /* mode bits for NI general-purpose counters, set with * INSN_CONFIG_SET_COUNTER_MODE */ #define NI_GPCT_COUNTING_MODE_SHIFT 16 #define NI_GPCT_INDEX_PHASE_BITSHIFT 20 #define NI_GPCT_COUNTING_DIRECTION_SHIFT 24 -enum ni_gpct_mode_bits { - NI_GPCT_GATE_ON_BOTH_EDGES_BIT = 0x4, - NI_GPCT_EDGE_GATE_MODE_MASK = 0x18, - NI_GPCT_EDGE_GATE_STARTS_STOPS_BITS = 0x0, - NI_GPCT_EDGE_GATE_STOPS_STARTS_BITS = 0x8, - NI_GPCT_EDGE_GATE_STARTS_BITS = 0x10, - NI_GPCT_EDGE_GATE_NO_STARTS_NO_STOPS_BITS = 0x18, - NI_GPCT_STOP_MODE_MASK = 0x60, - NI_GPCT_STOP_ON_GATE_BITS = 0x00, - NI_GPCT_STOP_ON_GATE_OR_TC_BITS = 0x20, - NI_GPCT_STOP_ON_GATE_OR_SECOND_TC_BITS = 0x40, - NI_GPCT_LOAD_B_SELECT_BIT = 0x80, - NI_GPCT_OUTPUT_MODE_MASK = 0x300, - NI_GPCT_OUTPUT_TC_PULSE_BITS = 0x100, - NI_GPCT_OUTPUT_TC_TOGGLE_BITS = 0x200, - NI_GPCT_OUTPUT_TC_OR_GATE_TOGGLE_BITS = 0x300, - NI_GPCT_HARDWARE_DISARM_MASK = 0xc00, - NI_GPCT_NO_HARDWARE_DISARM_BITS = 0x000, - NI_GPCT_DISARM_AT_TC_BITS = 0x400, - NI_GPCT_DISARM_AT_GATE_BITS = 0x800, - NI_GPCT_DISARM_AT_TC_OR_GATE_BITS = 0xc00, - NI_GPCT_LOADING_ON_TC_BIT = 0x1000, - NI_GPCT_LOADING_ON_GATE_BIT = 0x4000, - NI_GPCT_COUNTING_MODE_MASK = 0x7 << NI_GPCT_COUNTING_MODE_SHIFT, - NI_GPCT_COUNTING_MODE_NORMAL_BITS = - 0x0 << NI_GPCT_COUNTING_MODE_SHIFT, - NI_GPCT_COUNTING_MODE_QUADRATURE_X1_BITS = - 0x1 << NI_GPCT_COUNTING_MODE_SHIFT, - NI_GPCT_COUNTING_MODE_QUADRATURE_X2_BITS = - 0x2 << NI_GPCT_COUNTING_MODE_SHIFT, - NI_GPCT_COUNTING_MODE_QUADRATURE_X4_BITS = - 0x3 << NI_GPCT_COUNTING_MODE_SHIFT, - NI_GPCT_COUNTING_MODE_TWO_PULSE_BITS = - 0x4 << NI_GPCT_COUNTING_MODE_SHIFT, - NI_GPCT_COUNTING_MODE_SYNC_SOURCE_BITS = - 0x6 << NI_GPCT_COUNTING_MODE_SHIFT, - NI_GPCT_INDEX_PHASE_MASK = 0x3 << NI_GPCT_INDEX_PHASE_BITSHIFT, - NI_GPCT_INDEX_PHASE_LOW_A_LOW_B_BITS = - 0x0 << NI_GPCT_INDEX_PHASE_BITSHIFT, - NI_GPCT_INDEX_PHASE_LOW_A_HIGH_B_BITS = - 0x1 << NI_GPCT_INDEX_PHASE_BITSHIFT, - NI_GPCT_INDEX_PHASE_HIGH_A_LOW_B_BITS = - 0x2 << NI_GPCT_INDEX_PHASE_BITSHIFT, - NI_GPCT_INDEX_PHASE_HIGH_A_HIGH_B_BITS = - 0x3 << NI_GPCT_INDEX_PHASE_BITSHIFT, - NI_GPCT_INDEX_ENABLE_BIT = 0x400000, - NI_GPCT_COUNTING_DIRECTION_MASK = - 0x3 << NI_GPCT_COUNTING_DIRECTION_SHIFT, - NI_GPCT_COUNTING_DIRECTION_DOWN_BITS = - 0x00 << NI_GPCT_COUNTING_DIRECTION_SHIFT, - NI_GPCT_COUNTING_DIRECTION_UP_BITS = - 0x1 << NI_GPCT_COUNTING_DIRECTION_SHIFT, - NI_GPCT_COUNTING_DIRECTION_HW_UP_DOWN_BITS = - 0x2 << NI_GPCT_COUNTING_DIRECTION_SHIFT, - NI_GPCT_COUNTING_DIRECTION_HW_GATE_BITS = - 0x3 << NI_GPCT_COUNTING_DIRECTION_SHIFT, - NI_GPCT_RELOAD_SOURCE_MASK = 0xc000000, - NI_GPCT_RELOAD_SOURCE_FIXED_BITS = 0x0, - NI_GPCT_RELOAD_SOURCE_SWITCHING_BITS = 0x4000000, - NI_GPCT_RELOAD_SOURCE_GATE_SELECT_BITS = 0x8000000, - NI_GPCT_OR_GATE_BIT = 0x10000000, - NI_GPCT_INVERT_OUTPUT_BIT = 0x20000000 -}; + enum ni_gpct_mode_bits { + NI_GPCT_GATE_ON_BOTH_EDGES_BIT = 0x4, + NI_GPCT_EDGE_GATE_MODE_MASK = 0x18, + NI_GPCT_EDGE_GATE_STARTS_STOPS_BITS = 0x0, + NI_GPCT_EDGE_GATE_STOPS_STARTS_BITS = 0x8, + NI_GPCT_EDGE_GATE_STARTS_BITS = 0x10, + NI_GPCT_EDGE_GATE_NO_STARTS_NO_STOPS_BITS = 0x18, + NI_GPCT_STOP_MODE_MASK = 0x60, + NI_GPCT_STOP_ON_GATE_BITS = 0x00, + NI_GPCT_STOP_ON_GATE_OR_TC_BITS = 0x20, + NI_GPCT_STOP_ON_GATE_OR_SECOND_TC_BITS = 0x40, + NI_GPCT_LOAD_B_SELECT_BIT = 0x80, + NI_GPCT_OUTPUT_MODE_MASK = 0x300, + NI_GPCT_OUTPUT_TC_PULSE_BITS = 0x100, + NI_GPCT_OUTPUT_TC_TOGGLE_BITS = 0x200, + NI_GPCT_OUTPUT_TC_OR_GATE_TOGGLE_BITS = 0x300, + NI_GPCT_HARDWARE_DISARM_MASK = 0xc00, + NI_GPCT_NO_HARDWARE_DISARM_BITS = 0x000, + NI_GPCT_DISARM_AT_TC_BITS = 0x400, + NI_GPCT_DISARM_AT_GATE_BITS = 0x800, + NI_GPCT_DISARM_AT_TC_OR_GATE_BITS = 0xc00, + NI_GPCT_LOADING_ON_TC_BIT = 0x1000, + NI_GPCT_LOADING_ON_GATE_BIT = 0x4000, + NI_GPCT_COUNTING_MODE_MASK = 0x7 << NI_GPCT_COUNTING_MODE_SHIFT, + NI_GPCT_COUNTING_MODE_NORMAL_BITS = + 0x0 << NI_GPCT_COUNTING_MODE_SHIFT, + NI_GPCT_COUNTING_MODE_QUADRATURE_X1_BITS = + 0x1 << NI_GPCT_COUNTING_MODE_SHIFT, + NI_GPCT_COUNTING_MODE_QUADRATURE_X2_BITS = + 0x2 << NI_GPCT_COUNTING_MODE_SHIFT, + NI_GPCT_COUNTING_MODE_QUADRATURE_X4_BITS = + 0x3 << NI_GPCT_COUNTING_MODE_SHIFT, + NI_GPCT_COUNTING_MODE_TWO_PULSE_BITS = + 0x4 << NI_GPCT_COUNTING_MODE_SHIFT, + NI_GPCT_COUNTING_MODE_SYNC_SOURCE_BITS = + 0x6 << NI_GPCT_COUNTING_MODE_SHIFT, + NI_GPCT_INDEX_PHASE_MASK = 0x3 << NI_GPCT_INDEX_PHASE_BITSHIFT, + NI_GPCT_INDEX_PHASE_LOW_A_LOW_B_BITS = + 0x0 << NI_GPCT_INDEX_PHASE_BITSHIFT, + NI_GPCT_INDEX_PHASE_LOW_A_HIGH_B_BITS = + 0x1 << NI_GPCT_INDEX_PHASE_BITSHIFT, + NI_GPCT_INDEX_PHASE_HIGH_A_LOW_B_BITS = + 0x2 << NI_GPCT_INDEX_PHASE_BITSHIFT, + NI_GPCT_INDEX_PHASE_HIGH_A_HIGH_B_BITS = + 0x3 << NI_GPCT_INDEX_PHASE_BITSHIFT, + NI_GPCT_INDEX_ENABLE_BIT = 0x400000, + NI_GPCT_COUNTING_DIRECTION_MASK = + 0x3 << NI_GPCT_COUNTING_DIRECTION_SHIFT, + NI_GPCT_COUNTING_DIRECTION_DOWN_BITS = + 0x00 << NI_GPCT_COUNTING_DIRECTION_SHIFT, + NI_GPCT_COUNTING_DIRECTION_UP_BITS = + 0x1 << NI_GPCT_COUNTING_DIRECTION_SHIFT, + NI_GPCT_COUNTING_DIRECTION_HW_UP_DOWN_BITS = + 0x2 << NI_GPCT_COUNTING_DIRECTION_SHIFT, + NI_GPCT_COUNTING_DIRECTION_HW_GATE_BITS = + 0x3 << NI_GPCT_COUNTING_DIRECTION_SHIFT, + NI_GPCT_RELOAD_SOURCE_MASK = 0xc000000, + NI_GPCT_RELOAD_SOURCE_FIXED_BITS = 0x0, + NI_GPCT_RELOAD_SOURCE_SWITCHING_BITS = 0x4000000, + NI_GPCT_RELOAD_SOURCE_GATE_SELECT_BITS = 0x8000000, + NI_GPCT_OR_GATE_BIT = 0x10000000, + NI_GPCT_INVERT_OUTPUT_BIT = 0x20000000 + }; /* Bits for setting a clock source with * INSN_CONFIG_SET_CLOCK_SRC when using NI general-purpose counters. */ -enum ni_gpct_clock_source_bits { - NI_GPCT_CLOCK_SRC_SELECT_MASK = 0x3f, - NI_GPCT_TIMEBASE_1_CLOCK_SRC_BITS = 0x0, - NI_GPCT_TIMEBASE_2_CLOCK_SRC_BITS = 0x1, - NI_GPCT_TIMEBASE_3_CLOCK_SRC_BITS = 0x2, - NI_GPCT_LOGIC_LOW_CLOCK_SRC_BITS = 0x3, - NI_GPCT_NEXT_GATE_CLOCK_SRC_BITS = 0x4, - NI_GPCT_NEXT_TC_CLOCK_SRC_BITS = 0x5, - /* NI 660x-specific */ - NI_GPCT_SOURCE_PIN_i_CLOCK_SRC_BITS = 0x6, - NI_GPCT_PXI10_CLOCK_SRC_BITS = 0x7, - NI_GPCT_PXI_STAR_TRIGGER_CLOCK_SRC_BITS = 0x8, - NI_GPCT_ANALOG_TRIGGER_OUT_CLOCK_SRC_BITS = 0x9, - NI_GPCT_PRESCALE_MODE_CLOCK_SRC_MASK = 0x30000000, - NI_GPCT_NO_PRESCALE_CLOCK_SRC_BITS = 0x0, - /* divide source by 2 */ - NI_GPCT_PRESCALE_X2_CLOCK_SRC_BITS = 0x10000000, - /* divide source by 8 */ - NI_GPCT_PRESCALE_X8_CLOCK_SRC_BITS = 0x20000000, - NI_GPCT_INVERT_CLOCK_SRC_BIT = 0x80000000 -}; -static inline unsigned NI_GPCT_SOURCE_PIN_CLOCK_SRC_BITS(unsigned n) -{ - /* NI 660x-specific */ - return 0x10 + n; -} -static inline unsigned NI_GPCT_RTSI_CLOCK_SRC_BITS(unsigned n) -{ - return 0x18 + n; -} -static inline unsigned NI_GPCT_PFI_CLOCK_SRC_BITS(unsigned n) -{ - /* no pfi on NI 660x */ - return 0x20 + n; -} + enum ni_gpct_clock_source_bits { + NI_GPCT_CLOCK_SRC_SELECT_MASK = 0x3f, + NI_GPCT_TIMEBASE_1_CLOCK_SRC_BITS = 0x0, + NI_GPCT_TIMEBASE_2_CLOCK_SRC_BITS = 0x1, + NI_GPCT_TIMEBASE_3_CLOCK_SRC_BITS = 0x2, + NI_GPCT_LOGIC_LOW_CLOCK_SRC_BITS = 0x3, + NI_GPCT_NEXT_GATE_CLOCK_SRC_BITS = 0x4, + NI_GPCT_NEXT_TC_CLOCK_SRC_BITS = 0x5, + /* NI 660x-specific */ + NI_GPCT_SOURCE_PIN_i_CLOCK_SRC_BITS = 0x6, + NI_GPCT_PXI10_CLOCK_SRC_BITS = 0x7, + NI_GPCT_PXI_STAR_TRIGGER_CLOCK_SRC_BITS = 0x8, + NI_GPCT_ANALOG_TRIGGER_OUT_CLOCK_SRC_BITS = 0x9, + NI_GPCT_PRESCALE_MODE_CLOCK_SRC_MASK = 0x30000000, + NI_GPCT_NO_PRESCALE_CLOCK_SRC_BITS = 0x0, + /* divide source by 2 */ + NI_GPCT_PRESCALE_X2_CLOCK_SRC_BITS = 0x10000000, + /* divide source by 8 */ + NI_GPCT_PRESCALE_X8_CLOCK_SRC_BITS = 0x20000000, + NI_GPCT_INVERT_CLOCK_SRC_BIT = 0x80000000 + }; + static inline unsigned NI_GPCT_SOURCE_PIN_CLOCK_SRC_BITS(unsigned n) + { + /* NI 660x-specific */ + return 0x10 + n; + } + static inline unsigned NI_GPCT_RTSI_CLOCK_SRC_BITS(unsigned n) + { + return 0x18 + n; + } + static inline unsigned NI_GPCT_PFI_CLOCK_SRC_BITS(unsigned n) + { + /* no pfi on NI 660x */ + return 0x20 + n; + } /* Possibilities for setting a gate source with INSN_CONFIG_SET_GATE_SRC when using NI general-purpose counters. May be bitwise-or'd with CR_EDGE or CR_INVERT. */ -enum ni_gpct_gate_select { - /* m-series gates */ - NI_GPCT_TIMESTAMP_MUX_GATE_SELECT = 0x0, - NI_GPCT_AI_START2_GATE_SELECT = 0x12, - NI_GPCT_PXI_STAR_TRIGGER_GATE_SELECT = 0x13, - NI_GPCT_NEXT_OUT_GATE_SELECT = 0x14, - NI_GPCT_AI_START1_GATE_SELECT = 0x1c, - NI_GPCT_NEXT_SOURCE_GATE_SELECT = 0x1d, - NI_GPCT_ANALOG_TRIGGER_OUT_GATE_SELECT = 0x1e, - NI_GPCT_LOGIC_LOW_GATE_SELECT = 0x1f, - /* more gates for 660x */ - NI_GPCT_SOURCE_PIN_i_GATE_SELECT = 0x100, - NI_GPCT_GATE_PIN_i_GATE_SELECT = 0x101, - /* more gates for 660x "second gate" */ - NI_GPCT_UP_DOWN_PIN_i_GATE_SELECT = 0x201, - NI_GPCT_SELECTED_GATE_GATE_SELECT = 0x21e, - /* m-series "second gate" sources are unknown, - * we should add them here with an offset of 0x300 when - * known. */ - NI_GPCT_DISABLED_GATE_SELECT = 0x8000, -}; -static inline unsigned NI_GPCT_GATE_PIN_GATE_SELECT(unsigned n) -{ - return 0x102 + n; -} -static inline unsigned NI_GPCT_RTSI_GATE_SELECT(unsigned n) -{ - return NI_USUAL_RTSI_SELECT(n); -} -static inline unsigned NI_GPCT_PFI_GATE_SELECT(unsigned n) -{ - return NI_USUAL_PFI_SELECT(n); -} -static inline unsigned NI_GPCT_UP_DOWN_PIN_GATE_SELECT(unsigned n) -{ - return 0x202 + n; -} + enum ni_gpct_gate_select { + /* m-series gates */ + NI_GPCT_TIMESTAMP_MUX_GATE_SELECT = 0x0, + NI_GPCT_AI_START2_GATE_SELECT = 0x12, + NI_GPCT_PXI_STAR_TRIGGER_GATE_SELECT = 0x13, + NI_GPCT_NEXT_OUT_GATE_SELECT = 0x14, + NI_GPCT_AI_START1_GATE_SELECT = 0x1c, + NI_GPCT_NEXT_SOURCE_GATE_SELECT = 0x1d, + NI_GPCT_ANALOG_TRIGGER_OUT_GATE_SELECT = 0x1e, + NI_GPCT_LOGIC_LOW_GATE_SELECT = 0x1f, + /* more gates for 660x */ + NI_GPCT_SOURCE_PIN_i_GATE_SELECT = 0x100, + NI_GPCT_GATE_PIN_i_GATE_SELECT = 0x101, + /* more gates for 660x "second gate" */ + NI_GPCT_UP_DOWN_PIN_i_GATE_SELECT = 0x201, + NI_GPCT_SELECTED_GATE_GATE_SELECT = 0x21e, + /* m-series "second gate" sources are unknown, + * we should add them here with an offset of 0x300 when + * known. */ + NI_GPCT_DISABLED_GATE_SELECT = 0x8000, + }; + static inline unsigned NI_GPCT_GATE_PIN_GATE_SELECT(unsigned n) + { + return 0x102 + n; + } + static inline unsigned NI_GPCT_RTSI_GATE_SELECT(unsigned n) + { + return NI_USUAL_RTSI_SELECT(n); + } + static inline unsigned NI_GPCT_PFI_GATE_SELECT(unsigned n) + { + return NI_USUAL_PFI_SELECT(n); + } + static inline unsigned NI_GPCT_UP_DOWN_PIN_GATE_SELECT(unsigned n) + { + return 0x202 + n; + } /* Possibilities for setting a source with INSN_CONFIG_SET_OTHER_SRC when using NI general-purpose counters. */ -enum ni_gpct_other_index { - NI_GPCT_SOURCE_ENCODER_A, - NI_GPCT_SOURCE_ENCODER_B, - NI_GPCT_SOURCE_ENCODER_Z -}; -enum ni_gpct_other_select { - /* m-series gates */ - /* Still unknown, probably only need NI_GPCT_PFI_OTHER_SELECT */ - NI_GPCT_DISABLED_OTHER_SELECT = 0x8000, -}; -static inline unsigned NI_GPCT_PFI_OTHER_SELECT(unsigned n) -{ - return NI_USUAL_PFI_SELECT(n); -} + enum ni_gpct_other_index { + NI_GPCT_SOURCE_ENCODER_A, + NI_GPCT_SOURCE_ENCODER_B, + NI_GPCT_SOURCE_ENCODER_Z + }; + enum ni_gpct_other_select { + /* m-series gates */ + /* Still unknown, probably only need NI_GPCT_PFI_OTHER_SELECT */ + NI_GPCT_DISABLED_OTHER_SELECT = 0x8000, + }; + static inline unsigned NI_GPCT_PFI_OTHER_SELECT(unsigned n) + { + return NI_USUAL_PFI_SELECT(n); + } /* start sources for ni general-purpose counters for use with INSN_CONFIG_ARM */ -enum ni_gpct_arm_source { - NI_GPCT_ARM_IMMEDIATE = 0x0, - NI_GPCT_ARM_PAIRED_IMMEDIATE = 0x1, /* Start both the counter - * and the adjacent paired - * counter simultaneously */ - /* NI doesn't document bits for selecting hardware arm triggers. - * If the NI_GPCT_ARM_UNKNOWN bit is set, we will pass the least - * significant bits (3 bits for 660x or 5 bits for m-series) - * through to the hardware. This will at least allow someone to - * figure out what the bits do later. */ - NI_GPCT_ARM_UNKNOWN = 0x1000, -}; + enum ni_gpct_arm_source { + NI_GPCT_ARM_IMMEDIATE = 0x0, + NI_GPCT_ARM_PAIRED_IMMEDIATE = 0x1, /* Start both the counter + * and the adjacent paired + * counter simultaneously */ + /* NI doesn't document bits for selecting hardware arm triggers. + * If the NI_GPCT_ARM_UNKNOWN bit is set, we will pass the least + * significant bits (3 bits for 660x or 5 bits for m-series) + * through to the hardware. This will at least allow someone to + * figure out what the bits do later. */ + NI_GPCT_ARM_UNKNOWN = 0x1000, + }; /* digital filtering options for ni 660x for use with INSN_CONFIG_FILTER. */ -enum ni_gpct_filter_select { - NI_GPCT_FILTER_OFF = 0x0, - NI_GPCT_FILTER_TIMEBASE_3_SYNC = 0x1, - NI_GPCT_FILTER_100x_TIMEBASE_1 = 0x2, - NI_GPCT_FILTER_20x_TIMEBASE_1 = 0x3, - NI_GPCT_FILTER_10x_TIMEBASE_1 = 0x4, - NI_GPCT_FILTER_2x_TIMEBASE_1 = 0x5, - NI_GPCT_FILTER_2x_TIMEBASE_3 = 0x6 -}; + enum ni_gpct_filter_select { + NI_GPCT_FILTER_OFF = 0x0, + NI_GPCT_FILTER_TIMEBASE_3_SYNC = 0x1, + NI_GPCT_FILTER_100x_TIMEBASE_1 = 0x2, + NI_GPCT_FILTER_20x_TIMEBASE_1 = 0x3, + NI_GPCT_FILTER_10x_TIMEBASE_1 = 0x4, + NI_GPCT_FILTER_2x_TIMEBASE_1 = 0x5, + NI_GPCT_FILTER_2x_TIMEBASE_3 = 0x6 + }; /* PFI digital filtering options for ni m-series for use with * INSN_CONFIG_FILTER. */ -enum ni_pfi_filter_select { - NI_PFI_FILTER_OFF = 0x0, - NI_PFI_FILTER_125ns = 0x1, - NI_PFI_FILTER_6425ns = 0x2, - NI_PFI_FILTER_2550us = 0x3 -}; + enum ni_pfi_filter_select { + NI_PFI_FILTER_OFF = 0x0, + NI_PFI_FILTER_125ns = 0x1, + NI_PFI_FILTER_6425ns = 0x2, + NI_PFI_FILTER_2550us = 0x3 + }; /* master clock sources for ni mio boards and INSN_CONFIG_SET_CLOCK_SRC */ -enum ni_mio_clock_source { - NI_MIO_INTERNAL_CLOCK = 0, - NI_MIO_RTSI_CLOCK = 1, /* doesn't work for m-series, use - NI_MIO_PLL_RTSI_CLOCK() */ - /* the NI_MIO_PLL_* sources are m-series only */ - NI_MIO_PLL_PXI_STAR_TRIGGER_CLOCK = 2, - NI_MIO_PLL_PXI10_CLOCK = 3, - NI_MIO_PLL_RTSI0_CLOCK = 4 -}; -static inline unsigned NI_MIO_PLL_RTSI_CLOCK(unsigned rtsi_channel) -{ - return NI_MIO_PLL_RTSI0_CLOCK + rtsi_channel; -} + enum ni_mio_clock_source { + NI_MIO_INTERNAL_CLOCK = 0, + NI_MIO_RTSI_CLOCK = 1, /* doesn't work for m-series, use + NI_MIO_PLL_RTSI_CLOCK() */ + /* the NI_MIO_PLL_* sources are m-series only */ + NI_MIO_PLL_PXI_STAR_TRIGGER_CLOCK = 2, + NI_MIO_PLL_PXI10_CLOCK = 3, + NI_MIO_PLL_RTSI0_CLOCK = 4 + }; + static inline unsigned NI_MIO_PLL_RTSI_CLOCK(unsigned rtsi_channel) + { + return NI_MIO_PLL_RTSI0_CLOCK + rtsi_channel; + } /* Signals which can be routed to an NI RTSI pin with INSN_CONFIG_SET_ROUTING. The numbers assigned are not arbitrary, they correspond to the bits required to program the board. */ -enum ni_rtsi_routing { - NI_RTSI_OUTPUT_ADR_START1 = 0, - NI_RTSI_OUTPUT_ADR_START2 = 1, - NI_RTSI_OUTPUT_SCLKG = 2, - NI_RTSI_OUTPUT_DACUPDN = 3, - NI_RTSI_OUTPUT_DA_START1 = 4, - NI_RTSI_OUTPUT_G_SRC0 = 5, - NI_RTSI_OUTPUT_G_GATE0 = 6, - NI_RTSI_OUTPUT_RGOUT0 = 7, - NI_RTSI_OUTPUT_RTSI_BRD_0 = 8, - NI_RTSI_OUTPUT_RTSI_OSC = 12 /* pre-m-series always have RTSI - * clock on line 7 */ -}; -static inline unsigned NI_RTSI_OUTPUT_RTSI_BRD(unsigned n) -{ - return NI_RTSI_OUTPUT_RTSI_BRD_0 + n; -} + enum ni_rtsi_routing { + NI_RTSI_OUTPUT_ADR_START1 = 0, + NI_RTSI_OUTPUT_ADR_START2 = 1, + NI_RTSI_OUTPUT_SCLKG = 2, + NI_RTSI_OUTPUT_DACUPDN = 3, + NI_RTSI_OUTPUT_DA_START1 = 4, + NI_RTSI_OUTPUT_G_SRC0 = 5, + NI_RTSI_OUTPUT_G_GATE0 = 6, + NI_RTSI_OUTPUT_RGOUT0 = 7, + NI_RTSI_OUTPUT_RTSI_BRD_0 = 8, + NI_RTSI_OUTPUT_RTSI_OSC = 12 /* pre-m-series always have RTSI + * clock on line 7 */ + }; + static inline unsigned NI_RTSI_OUTPUT_RTSI_BRD(unsigned n) + { + return NI_RTSI_OUTPUT_RTSI_BRD_0 + n; + } /* Signals which can be routed to an NI PFI pin on an m-series board with * INSN_CONFIG_SET_ROUTING. These numbers are also returned by * INSN_CONFIG_GET_ROUTING on pre-m-series boards, even though their routing * cannot be changed. The numbers assigned are not arbitrary, they correspond * to the bits required to program the board. */ -enum ni_pfi_routing { - NI_PFI_OUTPUT_PFI_DEFAULT = 0, - NI_PFI_OUTPUT_AI_START1 = 1, - NI_PFI_OUTPUT_AI_START2 = 2, - NI_PFI_OUTPUT_AI_CONVERT = 3, - NI_PFI_OUTPUT_G_SRC1 = 4, - NI_PFI_OUTPUT_G_GATE1 = 5, - NI_PFI_OUTPUT_AO_UPDATE_N = 6, - NI_PFI_OUTPUT_AO_START1 = 7, - NI_PFI_OUTPUT_AI_START_PULSE = 8, - NI_PFI_OUTPUT_G_SRC0 = 9, - NI_PFI_OUTPUT_G_GATE0 = 10, - NI_PFI_OUTPUT_EXT_STROBE = 11, - NI_PFI_OUTPUT_AI_EXT_MUX_CLK = 12, - NI_PFI_OUTPUT_GOUT0 = 13, - NI_PFI_OUTPUT_GOUT1 = 14, - NI_PFI_OUTPUT_FREQ_OUT = 15, - NI_PFI_OUTPUT_PFI_DO = 16, - NI_PFI_OUTPUT_I_ATRIG = 17, - NI_PFI_OUTPUT_RTSI0 = 18, - NI_PFI_OUTPUT_PXI_STAR_TRIGGER_IN = 26, - NI_PFI_OUTPUT_SCXI_TRIG1 = 27, - NI_PFI_OUTPUT_DIO_CHANGE_DETECT_RTSI = 28, - NI_PFI_OUTPUT_CDI_SAMPLE = 29, - NI_PFI_OUTPUT_CDO_UPDATE = 30 -}; -static inline unsigned NI_PFI_OUTPUT_RTSI(unsigned rtsi_channel) -{ - return NI_PFI_OUTPUT_RTSI0 + rtsi_channel; -} + enum ni_pfi_routing { + NI_PFI_OUTPUT_PFI_DEFAULT = 0, + NI_PFI_OUTPUT_AI_START1 = 1, + NI_PFI_OUTPUT_AI_START2 = 2, + NI_PFI_OUTPUT_AI_CONVERT = 3, + NI_PFI_OUTPUT_G_SRC1 = 4, + NI_PFI_OUTPUT_G_GATE1 = 5, + NI_PFI_OUTPUT_AO_UPDATE_N = 6, + NI_PFI_OUTPUT_AO_START1 = 7, + NI_PFI_OUTPUT_AI_START_PULSE = 8, + NI_PFI_OUTPUT_G_SRC0 = 9, + NI_PFI_OUTPUT_G_GATE0 = 10, + NI_PFI_OUTPUT_EXT_STROBE = 11, + NI_PFI_OUTPUT_AI_EXT_MUX_CLK = 12, + NI_PFI_OUTPUT_GOUT0 = 13, + NI_PFI_OUTPUT_GOUT1 = 14, + NI_PFI_OUTPUT_FREQ_OUT = 15, + NI_PFI_OUTPUT_PFI_DO = 16, + NI_PFI_OUTPUT_I_ATRIG = 17, + NI_PFI_OUTPUT_RTSI0 = 18, + NI_PFI_OUTPUT_PXI_STAR_TRIGGER_IN = 26, + NI_PFI_OUTPUT_SCXI_TRIG1 = 27, + NI_PFI_OUTPUT_DIO_CHANGE_DETECT_RTSI = 28, + NI_PFI_OUTPUT_CDI_SAMPLE = 29, + NI_PFI_OUTPUT_CDO_UPDATE = 30 + }; + static inline unsigned NI_PFI_OUTPUT_RTSI(unsigned rtsi_channel) + { + return NI_PFI_OUTPUT_RTSI0 + rtsi_channel; + } /* Signals which can be routed to output on a NI PFI pin on a 660x board with INSN_CONFIG_SET_ROUTING. The numbers assigned are @@ -802,112 +802,113 @@ static inline unsigned NI_PFI_OUTPUT_RTSI(unsigned rtsi_channel) to program the board. Lines 0 to 7 can only be set to NI_660X_PFI_OUTPUT_DIO. Lines 32 to 39 can only be set to NI_660X_PFI_OUTPUT_COUNTER. */ -enum ni_660x_pfi_routing { - NI_660X_PFI_OUTPUT_COUNTER = 1, /* counter */ - NI_660X_PFI_OUTPUT_DIO = 2, /* static digital output */ -}; + enum ni_660x_pfi_routing { + NI_660X_PFI_OUTPUT_COUNTER = 1, /* counter */ + NI_660X_PFI_OUTPUT_DIO = 2, /* static digital output */ + }; /* NI External Trigger lines. These values are not arbitrary, but are related * to the bits required to program the board (offset by 1 for historical * reasons). */ -static inline unsigned NI_EXT_PFI(unsigned pfi_channel) -{ - return NI_USUAL_PFI_SELECT(pfi_channel) - 1; -} -static inline unsigned NI_EXT_RTSI(unsigned rtsi_channel) -{ - return NI_USUAL_RTSI_SELECT(rtsi_channel) - 1; -} + static inline unsigned NI_EXT_PFI(unsigned pfi_channel) + { + return NI_USUAL_PFI_SELECT(pfi_channel) - 1; + } + static inline unsigned NI_EXT_RTSI(unsigned rtsi_channel) + { + return NI_USUAL_RTSI_SELECT(rtsi_channel) - 1; + } /* status bits for INSN_CONFIG_GET_COUNTER_STATUS */ -enum comedi_counter_status_flags { - COMEDI_COUNTER_ARMED = 0x1, - COMEDI_COUNTER_COUNTING = 0x2, - COMEDI_COUNTER_TERMINAL_COUNT = 0x4, -}; + enum comedi_counter_status_flags { + COMEDI_COUNTER_ARMED = 0x1, + COMEDI_COUNTER_COUNTING = 0x2, + COMEDI_COUNTER_TERMINAL_COUNT = 0x4, + }; /* Clock sources for CDIO subdevice on NI m-series boards. Used as the * scan_begin_arg for a comedi_command. These sources may also be bitwise-or'd * with CR_INVERT to change polarity. */ -enum ni_m_series_cdio_scan_begin_src { - NI_CDIO_SCAN_BEGIN_SRC_GROUND = 0, - NI_CDIO_SCAN_BEGIN_SRC_AI_START = 18, - NI_CDIO_SCAN_BEGIN_SRC_AI_CONVERT = 19, - NI_CDIO_SCAN_BEGIN_SRC_PXI_STAR_TRIGGER = 20, - NI_CDIO_SCAN_BEGIN_SRC_G0_OUT = 28, - NI_CDIO_SCAN_BEGIN_SRC_G1_OUT = 29, - NI_CDIO_SCAN_BEGIN_SRC_ANALOG_TRIGGER = 30, - NI_CDIO_SCAN_BEGIN_SRC_AO_UPDATE = 31, - NI_CDIO_SCAN_BEGIN_SRC_FREQ_OUT = 32, - NI_CDIO_SCAN_BEGIN_SRC_DIO_CHANGE_DETECT_IRQ = 33 -}; -static inline unsigned NI_CDIO_SCAN_BEGIN_SRC_PFI(unsigned pfi_channel) -{ - return NI_USUAL_PFI_SELECT(pfi_channel); -} -static inline unsigned NI_CDIO_SCAN_BEGIN_SRC_RTSI(unsigned rtsi_channel) -{ - return NI_USUAL_RTSI_SELECT(rtsi_channel); -} + enum ni_m_series_cdio_scan_begin_src { + NI_CDIO_SCAN_BEGIN_SRC_GROUND = 0, + NI_CDIO_SCAN_BEGIN_SRC_AI_START = 18, + NI_CDIO_SCAN_BEGIN_SRC_AI_CONVERT = 19, + NI_CDIO_SCAN_BEGIN_SRC_PXI_STAR_TRIGGER = 20, + NI_CDIO_SCAN_BEGIN_SRC_G0_OUT = 28, + NI_CDIO_SCAN_BEGIN_SRC_G1_OUT = 29, + NI_CDIO_SCAN_BEGIN_SRC_ANALOG_TRIGGER = 30, + NI_CDIO_SCAN_BEGIN_SRC_AO_UPDATE = 31, + NI_CDIO_SCAN_BEGIN_SRC_FREQ_OUT = 32, + NI_CDIO_SCAN_BEGIN_SRC_DIO_CHANGE_DETECT_IRQ = 33 + }; + static inline unsigned NI_CDIO_SCAN_BEGIN_SRC_PFI(unsigned pfi_channel) + { + return NI_USUAL_PFI_SELECT(pfi_channel); + } + static inline unsigned + NI_CDIO_SCAN_BEGIN_SRC_RTSI(unsigned rtsi_channel) + { + return NI_USUAL_RTSI_SELECT(rtsi_channel); + } /* scan_begin_src for scan_begin_arg==TRIG_EXT with analog output command on NI * boards. These scan begin sources can also be bitwise-or'd with CR_INVERT to * change polarity. */ -static inline unsigned NI_AO_SCAN_BEGIN_SRC_PFI(unsigned pfi_channel) -{ - return NI_USUAL_PFI_SELECT(pfi_channel); -} -static inline unsigned NI_AO_SCAN_BEGIN_SRC_RTSI(unsigned rtsi_channel) -{ - return NI_USUAL_RTSI_SELECT(rtsi_channel); -} + static inline unsigned NI_AO_SCAN_BEGIN_SRC_PFI(unsigned pfi_channel) + { + return NI_USUAL_PFI_SELECT(pfi_channel); + } + static inline unsigned NI_AO_SCAN_BEGIN_SRC_RTSI(unsigned rtsi_channel) + { + return NI_USUAL_RTSI_SELECT(rtsi_channel); + } /* Bits for setting a clock source with * INSN_CONFIG_SET_CLOCK_SRC when using NI frequency output subdevice. */ -enum ni_freq_out_clock_source_bits { - NI_FREQ_OUT_TIMEBASE_1_DIV_2_CLOCK_SRC, /* 10 MHz */ - NI_FREQ_OUT_TIMEBASE_2_CLOCK_SRC /* 100 KHz */ -}; + enum ni_freq_out_clock_source_bits { + NI_FREQ_OUT_TIMEBASE_1_DIV_2_CLOCK_SRC, /* 10 MHz */ + NI_FREQ_OUT_TIMEBASE_2_CLOCK_SRC /* 100 KHz */ + }; /* Values for setting a clock source with INSN_CONFIG_SET_CLOCK_SRC for * 8254 counter subdevices on Amplicon DIO boards (amplc_dio200 driver). */ -enum amplc_dio_clock_source { - AMPLC_DIO_CLK_CLKN, /* per channel external clock - input/output pin (pin is only an - input when clock source set to this - value, otherwise it is an output) */ - AMPLC_DIO_CLK_10MHZ, /* 10 MHz internal clock */ - AMPLC_DIO_CLK_1MHZ, /* 1 MHz internal clock */ - AMPLC_DIO_CLK_100KHZ, /* 100 kHz internal clock */ - AMPLC_DIO_CLK_10KHZ, /* 10 kHz internal clock */ - AMPLC_DIO_CLK_1KHZ, /* 1 kHz internal clock */ - AMPLC_DIO_CLK_OUTNM1, /* output of preceding counter channel - (for channel 0, preceding counter - channel is channel 2 on preceding - counter subdevice, for first counter - subdevice, preceding counter - subdevice is the last counter - subdevice) */ - AMPLC_DIO_CLK_EXT /* per chip external input pin */ -}; + enum amplc_dio_clock_source { + AMPLC_DIO_CLK_CLKN, /* per channel external clock + input/output pin (pin is only an + input when clock source set to this + value, otherwise it is an output) */ + AMPLC_DIO_CLK_10MHZ, /* 10 MHz internal clock */ + AMPLC_DIO_CLK_1MHZ, /* 1 MHz internal clock */ + AMPLC_DIO_CLK_100KHZ, /* 100 kHz internal clock */ + AMPLC_DIO_CLK_10KHZ, /* 10 kHz internal clock */ + AMPLC_DIO_CLK_1KHZ, /* 1 kHz internal clock */ + AMPLC_DIO_CLK_OUTNM1, /* output of preceding counter channel + (for channel 0, preceding counter + channel is channel 2 on preceding + counter subdevice, for first counter + subdevice, preceding counter + subdevice is the last counter + subdevice) */ + AMPLC_DIO_CLK_EXT /* per chip external input pin */ + }; /* Values for setting a gate source with INSN_CONFIG_SET_GATE_SRC for * 8254 counter subdevices on Amplicon DIO boards (amplc_dio200 driver). */ -enum amplc_dio_gate_source { - AMPLC_DIO_GAT_VCC, /* internal high logic level */ - AMPLC_DIO_GAT_GND, /* internal low logic level */ - AMPLC_DIO_GAT_GATN, /* per channel external gate input */ - AMPLC_DIO_GAT_NOUTNM2, /* negated output of counter channel - minus 2 (for channels 0 or 1, - channel minus 2 is channel 1 or 2 on - the preceding counter subdevice, for - the first counter subdevice the - preceding counter subdevice is the - last counter subdevice) */ - AMPLC_DIO_GAT_RESERVED4, - AMPLC_DIO_GAT_RESERVED5, - AMPLC_DIO_GAT_RESERVED6, - AMPLC_DIO_GAT_RESERVED7 -}; + enum amplc_dio_gate_source { + AMPLC_DIO_GAT_VCC, /* internal high logic level */ + AMPLC_DIO_GAT_GND, /* internal low logic level */ + AMPLC_DIO_GAT_GATN, /* per channel external gate input */ + AMPLC_DIO_GAT_NOUTNM2, /* negated output of counter channel + minus 2 (for channels 0 or 1, + channel minus 2 is channel 1 or 2 on + the preceding counter subdevice, for + the first counter subdevice the + preceding counter subdevice is the + last counter subdevice) */ + AMPLC_DIO_GAT_RESERVED4, + AMPLC_DIO_GAT_RESERVED5, + AMPLC_DIO_GAT_RESERVED6, + AMPLC_DIO_GAT_RESERVED7 + }; #endif /* _COMEDI_H */ diff --git a/trunk/drivers/staging/comedi/comedi_fops.c b/trunk/drivers/staging/comedi/comedi_fops.c index c2a32cf95a82..e82126407e95 100644 --- a/trunk/drivers/staging/comedi/comedi_fops.c +++ b/trunk/drivers/staging/comedi/comedi_fops.c @@ -370,8 +370,7 @@ static int do_devconfig_ioctl(struct comedi_device *dev, return -ENOMEM; if (copy_from_user(aux_data, - (unsigned char __user * - )comedi_aux_data(it.options, 0), aux_len)) { + comedi_aux_data(it.options, 0), aux_len)) { vfree(aux_data); return -EFAULT; } @@ -427,7 +426,7 @@ static int do_bufconfig_ioctl(struct comedi_device *dev, if (bc.subdevice >= dev->n_subdevices || bc.subdevice < 0) return -EINVAL; - s = &dev->subdevices[bc.subdevice]; + s = dev->subdevices + bc.subdevice; async = s->async; if (!async) { @@ -540,7 +539,7 @@ static int do_subdinfo_ioctl(struct comedi_device *dev, /* fill subdinfo structs */ for (i = 0; i < dev->n_subdevices; i++) { - s = &dev->subdevices[i]; + s = dev->subdevices + i; us = tmp + i; us->type = s->type; @@ -618,7 +617,7 @@ static int do_chaninfo_ioctl(struct comedi_device *dev, if (it.subdev >= dev->n_subdevices) return -EINVAL; - s = &dev->subdevices[it.subdev]; + s = dev->subdevices + it.subdev; if (it.maxdata_list) { if (s->maxdata || !s->maxdata_list) @@ -686,7 +685,7 @@ static int do_bufinfo_ioctl(struct comedi_device *dev, if (bi.subdevice >= dev->n_subdevices || bi.subdevice < 0) return -EINVAL; - s = &dev->subdevices[bi.subdevice]; + s = dev->subdevices + bi.subdevice; if (s->lock && s->lock != file) return -EACCES; @@ -883,12 +882,14 @@ static int check_insn_config_length(struct comedi_insn *insn, /* by default we allow the insn since we don't have checks for * all possible cases yet */ default: - pr_warn("comedi: No check for data length of config insn id %i is implemented.\n", - data[0]); - pr_warn("comedi: Add a check to %s in %s.\n", - __func__, __FILE__); - pr_warn("comedi: Assuming n=%i is correct.\n", insn->n); + printk(KERN_WARNING + "comedi: no check for data length of config insn id " + "%i is implemented.\n" + " Add a check to %s in %s.\n" + " Assuming n=%i is correct.\n", data[0], __func__, + __FILE__, insn->n); return 0; + break; } return -EINVAL; } @@ -939,7 +940,7 @@ static int parse_insn(struct comedi_device *dev, struct comedi_insn *insn, ret = -EINVAL; break; } - s = &dev->subdevices[insn->subdev]; + s = dev->subdevices + insn->subdev; if (!s->async) { DPRINTK("no async\n"); ret = -EINVAL; @@ -950,7 +951,7 @@ static int parse_insn(struct comedi_device *dev, struct comedi_insn *insn, ret = -EAGAIN; break; } - ret = s->async->inttrig(dev, s, data[0]); + ret = s->async->inttrig(dev, s, insn->data[0]); if (ret >= 0) ret = 1; break; @@ -968,7 +969,7 @@ static int parse_insn(struct comedi_device *dev, struct comedi_insn *insn, ret = -EINVAL; goto out; } - s = &dev->subdevices[insn->subdev]; + s = dev->subdevices + insn->subdev; if (s->type == COMEDI_SUBD_UNUSED) { DPRINTK("%d not usable subdevice\n", insn->subdev); @@ -1132,37 +1133,37 @@ static void comedi_set_subdevice_runflags(struct comedi_subdevice *s, } static int do_cmd_ioctl(struct comedi_device *dev, - struct comedi_cmd __user *arg, void *file) + struct comedi_cmd __user *cmd, void *file) { - struct comedi_cmd cmd; + struct comedi_cmd user_cmd; struct comedi_subdevice *s; struct comedi_async *async; int ret = 0; - unsigned int __user *user_chanlist; + unsigned int __user *chanlist_saver = NULL; - if (copy_from_user(&cmd, arg, sizeof(struct comedi_cmd))) { + if (copy_from_user(&user_cmd, cmd, sizeof(struct comedi_cmd))) { DPRINTK("bad cmd address\n"); return -EFAULT; } /* save user's chanlist pointer so it can be restored later */ - user_chanlist = (unsigned int __user *)cmd.chanlist; + chanlist_saver = user_cmd.chanlist; - if (cmd.subdev >= dev->n_subdevices) { - DPRINTK("%d no such subdevice\n", cmd.subdev); + if (user_cmd.subdev >= dev->n_subdevices) { + DPRINTK("%d no such subdevice\n", user_cmd.subdev); return -ENODEV; } - s = &dev->subdevices[cmd.subdev]; + s = dev->subdevices + user_cmd.subdev; async = s->async; if (s->type == COMEDI_SUBD_UNUSED) { - DPRINTK("%d not valid subdevice\n", cmd.subdev); + DPRINTK("%d not valid subdevice\n", user_cmd.subdev); return -EIO; } if (!s->do_cmd || !s->do_cmdtest || !s->async) { DPRINTK("subdevice %i does not support commands\n", - cmd.subdev); + user_cmd.subdev); return -EIO; } @@ -1180,22 +1181,23 @@ static int do_cmd_ioctl(struct comedi_device *dev, s->busy = file; /* make sure channel/gain list isn't too long */ - if (cmd.chanlist_len > s->len_chanlist) { + if (user_cmd.chanlist_len > s->len_chanlist) { DPRINTK("channel/gain list too long %u > %d\n", - cmd.chanlist_len, s->len_chanlist); + user_cmd.chanlist_len, s->len_chanlist); ret = -EINVAL; goto cleanup; } /* make sure channel/gain list isn't too short */ - if (cmd.chanlist_len < 1) { + if (user_cmd.chanlist_len < 1) { DPRINTK("channel/gain list too short %u < 1\n", - cmd.chanlist_len); + user_cmd.chanlist_len); ret = -EINVAL; goto cleanup; } - async->cmd = cmd; + kfree(async->cmd.chanlist); + async->cmd = user_cmd; async->cmd.data = NULL; /* load channel/gain list */ async->cmd.chanlist = @@ -1206,7 +1208,7 @@ static int do_cmd_ioctl(struct comedi_device *dev, goto cleanup; } - if (copy_from_user(async->cmd.chanlist, user_chanlist, + if (copy_from_user(async->cmd.chanlist, user_cmd.chanlist, async->cmd.chanlist_len * sizeof(int))) { DPRINTK("fault reading chanlist\n"); ret = -EFAULT; @@ -1226,11 +1228,11 @@ static int do_cmd_ioctl(struct comedi_device *dev, if (async->cmd.flags & TRIG_BOGUS || ret) { DPRINTK("test returned %d\n", ret); - cmd = async->cmd; + user_cmd = async->cmd; /* restore chanlist pointer before copying back */ - cmd.chanlist = (unsigned int __force *)user_chanlist; - cmd.data = NULL; - if (copy_to_user(arg, &cmd, sizeof(struct comedi_cmd))) { + user_cmd.chanlist = chanlist_saver; + user_cmd.data = NULL; + if (copy_to_user(cmd, &user_cmd, sizeof(struct comedi_cmd))) { DPRINTK("fault writing cmd\n"); ret = -EFAULT; goto cleanup; @@ -1283,77 +1285,77 @@ static int do_cmd_ioctl(struct comedi_device *dev, static int do_cmdtest_ioctl(struct comedi_device *dev, struct comedi_cmd __user *arg, void *file) { - struct comedi_cmd cmd; + struct comedi_cmd user_cmd; struct comedi_subdevice *s; int ret = 0; unsigned int *chanlist = NULL; - unsigned int __user *user_chanlist; + unsigned int __user *chanlist_saver = NULL; - if (copy_from_user(&cmd, arg, sizeof(struct comedi_cmd))) { + if (copy_from_user(&user_cmd, arg, sizeof(struct comedi_cmd))) { DPRINTK("bad cmd address\n"); return -EFAULT; } /* save user's chanlist pointer so it can be restored later */ - user_chanlist = (unsigned int __user *)cmd.chanlist; + chanlist_saver = user_cmd.chanlist; - if (cmd.subdev >= dev->n_subdevices) { - DPRINTK("%d no such subdevice\n", cmd.subdev); + if (user_cmd.subdev >= dev->n_subdevices) { + DPRINTK("%d no such subdevice\n", user_cmd.subdev); return -ENODEV; } - s = &dev->subdevices[cmd.subdev]; + s = dev->subdevices + user_cmd.subdev; if (s->type == COMEDI_SUBD_UNUSED) { - DPRINTK("%d not valid subdevice\n", cmd.subdev); + DPRINTK("%d not valid subdevice\n", user_cmd.subdev); return -EIO; } if (!s->do_cmd || !s->do_cmdtest) { DPRINTK("subdevice %i does not support commands\n", - cmd.subdev); + user_cmd.subdev); return -EIO; } /* make sure channel/gain list isn't too long */ - if (cmd.chanlist_len > s->len_chanlist) { + if (user_cmd.chanlist_len > s->len_chanlist) { DPRINTK("channel/gain list too long %d > %d\n", - cmd.chanlist_len, s->len_chanlist); + user_cmd.chanlist_len, s->len_chanlist); ret = -EINVAL; goto cleanup; } /* load channel/gain list */ - if (cmd.chanlist) { + if (user_cmd.chanlist) { chanlist = - kmalloc(cmd.chanlist_len * sizeof(int), GFP_KERNEL); + kmalloc(user_cmd.chanlist_len * sizeof(int), GFP_KERNEL); if (!chanlist) { DPRINTK("allocation failed\n"); ret = -ENOMEM; goto cleanup; } - if (copy_from_user(chanlist, user_chanlist, - cmd.chanlist_len * sizeof(int))) { + if (copy_from_user(chanlist, user_cmd.chanlist, + user_cmd.chanlist_len * sizeof(int))) { DPRINTK("fault reading chanlist\n"); ret = -EFAULT; goto cleanup; } /* make sure each element in channel/gain list is valid */ - ret = comedi_check_chanlist(s, cmd.chanlist_len, chanlist); + ret = comedi_check_chanlist(s, user_cmd.chanlist_len, chanlist); if (ret < 0) { DPRINTK("bad chanlist\n"); goto cleanup; } - cmd.chanlist = chanlist; + user_cmd.chanlist = chanlist; } - ret = s->do_cmdtest(dev, s, &cmd); + ret = s->do_cmdtest(dev, s, &user_cmd); /* restore chanlist pointer before copying back */ - cmd.chanlist = (unsigned int __force *)user_chanlist; + user_cmd.chanlist = chanlist_saver; - if (copy_to_user(arg, &cmd, sizeof(struct comedi_cmd))) { + if (copy_to_user(arg, &user_cmd, sizeof(struct comedi_cmd))) { DPRINTK("bad cmd address\n"); ret = -EFAULT; goto cleanup; @@ -1388,7 +1390,7 @@ static int do_lock_ioctl(struct comedi_device *dev, unsigned int arg, if (arg >= dev->n_subdevices) return -EINVAL; - s = &dev->subdevices[arg]; + s = dev->subdevices + arg; spin_lock_irqsave(&s->spin_lock, flags); if (s->busy || s->lock) @@ -1431,7 +1433,7 @@ static int do_unlock_ioctl(struct comedi_device *dev, unsigned int arg, if (arg >= dev->n_subdevices) return -EINVAL; - s = &dev->subdevices[arg]; + s = dev->subdevices + arg; if (s->busy) return -EBUSY; @@ -1472,7 +1474,7 @@ static int do_cancel_ioctl(struct comedi_device *dev, unsigned int arg, if (arg >= dev->n_subdevices) return -EINVAL; - s = &dev->subdevices[arg]; + s = dev->subdevices + arg; if (s->async == NULL) return -EINVAL; @@ -1509,7 +1511,7 @@ static int do_poll_ioctl(struct comedi_device *dev, unsigned int arg, if (arg >= dev->n_subdevices) return -EINVAL; - s = &dev->subdevices[arg]; + s = dev->subdevices + arg; if (s->lock && s->lock != file) return -EACCES; @@ -2023,8 +2025,7 @@ static ssize_t comedi_read(struct file *file, char __user *buf, size_t nbytes, /* This function restores a subdevice to an idle state. */ -static void do_become_nonbusy(struct comedi_device *dev, - struct comedi_subdevice *s) +void do_become_nonbusy(struct comedi_device *dev, struct comedi_subdevice *s) { struct comedi_async *async = s->async; @@ -2032,11 +2033,9 @@ static void do_become_nonbusy(struct comedi_device *dev, if (async) { comedi_reset_async_buf(async); async->inttrig = NULL; - kfree(async->cmd.chanlist); - async->cmd.chanlist = NULL; } else { - dev_err(dev->class_dev, - "BUG: (?) do_become_nonbusy called with async=NULL\n"); + printk(KERN_ERR + "BUG: (?) do_become_nonbusy called with async=0\n"); } s->busy = NULL; @@ -2141,7 +2140,7 @@ static int comedi_close(struct inode *inode, struct file *file) if (dev->subdevices) { for (i = 0; i < dev->n_subdevices; i++) { - s = &dev->subdevices[i]; + s = dev->subdevices + i; if (s->busy == file) do_cancel(dev, s); @@ -2212,12 +2211,14 @@ static int __init comedi_init(void) int i; int retval; - pr_info("comedi: version " COMEDI_RELEASE " - http://www.comedi.org\n"); + printk(KERN_INFO "comedi: version " COMEDI_RELEASE + " - http://www.comedi.org\n"); if (comedi_num_legacy_minors < 0 || comedi_num_legacy_minors > COMEDI_NUM_BOARD_MINORS) { - pr_err("comedi: error: invalid value for module parameter \"comedi_num_legacy_minors\". Valid values are 0 through %i.\n", - COMEDI_NUM_BOARD_MINORS); + printk(KERN_ERR "comedi: error: invalid value for module " + "parameter \"comedi_num_legacy_minors\". Valid values " + "are 0 through %i.\n", COMEDI_NUM_BOARD_MINORS); return -EINVAL; } @@ -2246,7 +2247,7 @@ static int __init comedi_init(void) } comedi_class = class_create(THIS_MODULE, "comedi"); if (IS_ERR(comedi_class)) { - pr_err("comedi: failed to create class\n"); + printk(KERN_ERR "comedi: failed to create class"); cdev_del(&comedi_cdev); unregister_chrdev_region(MKDEV(COMEDI_MAJOR, 0), COMEDI_NUM_MINORS); @@ -2294,7 +2295,8 @@ module_exit(comedi_cleanup); void comedi_error(const struct comedi_device *dev, const char *s) { - dev_err(dev->class_dev, "%s: %s\n", dev->driver->driver_name, s); + printk(KERN_ERR "comedi%d: %s: %s\n", dev->minor, + dev->driver->driver_name, s); } EXPORT_SYMBOL(comedi_error); @@ -2362,7 +2364,7 @@ static int is_device_busy(struct comedi_device *dev) return 0; for (i = 0; i < dev->n_subdevices; i++) { - s = &dev->subdevices[i]; + s = dev->subdevices + i; if (s->busy) return 1; if (s->async && s->async->mmap_count) @@ -2418,7 +2420,9 @@ int comedi_alloc_board_minor(struct device *hardware_device) comedi_device_cleanup(info->device); kfree(info->device); kfree(info); - pr_err("comedi: error: ran out of minor numbers for board device files.\n"); + printk(KERN_ERR + "comedi: error: " + "ran out of minor numbers for board device files.\n"); return -EBUSY; } info->device->minor = i; @@ -2495,7 +2499,9 @@ int comedi_alloc_subdevice_minor(struct comedi_device *dev, spin_unlock(&comedi_file_info_table_lock); if (i == COMEDI_NUM_MINORS) { kfree(info); - pr_err("comedi: error: ran out of minor numbers for board device files.\n"); + printk(KERN_ERR + "comedi: error: " + "ran out of minor numbers for board device files.\n"); return -EBUSY; } s->minor = i; diff --git a/trunk/drivers/staging/comedi/comedidev.h b/trunk/drivers/staging/comedi/comedidev.h index cb67a5cb9c82..f713783ef624 100644 --- a/trunk/drivers/staging/comedi/comedidev.h +++ b/trunk/drivers/staging/comedi/comedidev.h @@ -46,7 +46,7 @@ #define DPRINTK(format, args...) do { \ if (comedi_debug) \ - pr_debug("comedi: " format, ## args); \ + printk(KERN_DEBUG "comedi: " format , ## args); \ } while (0) #define COMEDI_VERSION(a, b, c) (((a) << 16) + ((b) << 8) + (c)) diff --git a/trunk/drivers/staging/comedi/drivers.c b/trunk/drivers/staging/comedi/drivers.c index 1db6bfdbf13b..c0fdb00783ed 100644 --- a/trunk/drivers/staging/comedi/drivers.c +++ b/trunk/drivers/staging/comedi/drivers.c @@ -71,7 +71,7 @@ int comedi_alloc_subdevices(struct comedi_device *dev, int num_subdevices) dev->n_subdevices = num_subdevices; for (i = 0; i < num_subdevices; ++i) { - s = &dev->subdevices[i]; + s = dev->subdevices + i; s->device = dev; s->async_dma_dir = DMA_NONE; spin_lock_init(&s->spin_lock); @@ -88,7 +88,7 @@ static void cleanup_device(struct comedi_device *dev) if (dev->subdevices) { for (i = 0; i < dev->n_subdevices; i++) { - s = &dev->subdevices[i]; + s = dev->subdevices + i; comedi_free_subdevice_minor(s); if (s->async) { comedi_buf_alloc(dev, s, 0); @@ -119,8 +119,8 @@ static void __comedi_device_detach(struct comedi_device *dev) if (dev->driver) dev->driver->detach(dev); else - dev_warn(dev->class_dev, - "BUG: dev->driver=NULL in comedi_device_detach()\n"); + printk(KERN_WARNING + "BUG: dev->driver=NULL in comedi_device_detach()\n"); cleanup_device(dev); } @@ -142,7 +142,8 @@ static int comedi_device_postconfig(struct comedi_device *dev) return ret; } if (!dev->board_name) { - dev_warn(dev->class_dev, "BUG: dev->board_name=NULL\n"); + printk(KERN_WARNING "BUG: dev->board_name=<%p>\n", + dev->board_name); dev->board_name = "BUG"; } smp_wmb(); @@ -159,13 +160,15 @@ int comedi_device_attach(struct comedi_device *dev, struct comedi_devconfig *it) return -EBUSY; for (driv = comedi_drivers; driv; driv = driv->next) { - if (!try_module_get(driv->module)) + if (!try_module_get(driv->module)) { + printk(KERN_INFO "comedi: failed to increment module count, skipping\n"); continue; + } if (driv->num_names) { dev->board_ptr = comedi_recognize(driv, it->board_name); if (dev->board_ptr) break; - } else if (strcmp(driv->driver_name, it->board_name) == 0) + } else if (strcmp(driv->driver_name, it->board_name)) break; module_put(driv->module); } @@ -173,21 +176,16 @@ int comedi_device_attach(struct comedi_device *dev, struct comedi_devconfig *it) /* recognize has failed if we get here */ /* report valid board names before returning error */ for (driv = comedi_drivers; driv; driv = driv->next) { - if (!try_module_get(driv->module)) + if (!try_module_get(driv->module)) { + printk(KERN_INFO + "comedi: failed to increment module count\n"); continue; + } comedi_report_boards(driv); module_put(driv->module); } return -EIO; } - if (driv->attach == NULL) { - /* driver does not support manual configuration */ - dev_warn(dev->class_dev, - "driver '%s' does not support attach using comedi_config\n", - driv->driver_name); - module_put(driv->module); - return -ENOSYS; - } /* initialize dev->driver here so * comedi_error() can be called from attach */ dev->driver = driv; @@ -227,9 +225,8 @@ int comedi_driver_unregister(struct comedi_driver *driver) mutex_lock(&dev->mutex); if (dev->attached && dev->driver == driver) { if (dev->use_count) - dev_warn(dev->class_dev, - "BUG! detaching device with use_count=%d\n", - dev->use_count); + printk(KERN_WARNING "BUG! detaching device with use_count=%d\n", + dev->use_count); comedi_device_detach(dev); } mutex_unlock(&dev->mutex); @@ -258,7 +255,7 @@ static int postconfig(struct comedi_device *dev) int ret; for (i = 0; i < dev->n_subdevices; i++) { - s = &dev->subdevices[i]; + s = dev->subdevices + i; if (s->type == COMEDI_SUBD_UNUSED) continue; @@ -276,8 +273,8 @@ static int postconfig(struct comedi_device *dev) async = kzalloc(sizeof(struct comedi_async), GFP_KERNEL); if (async == NULL) { - dev_warn(dev->class_dev, - "failed to allocate async struct\n"); + printk(KERN_INFO + "failed to allocate async struct\n"); return -ENOMEM; } init_waitqueue_head(&async->wait_head); @@ -293,8 +290,7 @@ static int postconfig(struct comedi_device *dev) async->prealloc_buf = NULL; async->prealloc_bufsz = 0; if (comedi_buf_alloc(dev, s, buf_size) < 0) { - dev_warn(dev->class_dev, - "Buffer allocation failed\n"); + printk(KERN_INFO "Buffer allocation failed\n"); return -ENOMEM; } if (s->buf_change) { @@ -374,17 +370,17 @@ static void comedi_report_boards(struct comedi_driver *driv) unsigned int i; const char *const *name_ptr; - pr_info("comedi: valid board names for %s driver are:\n", - driv->driver_name); + printk(KERN_INFO "comedi: valid board names for %s driver are:\n", + driv->driver_name); name_ptr = driv->board_name; for (i = 0; i < driv->num_names; i++) { - pr_info(" %s\n", *name_ptr); + printk(KERN_INFO " %s\n", *name_ptr); name_ptr = (const char **)((char *)name_ptr + driv->offset); } if (driv->num_names == 0) - pr_info(" %s\n", driv->driver_name); + printk(KERN_INFO " %s\n", driv->driver_name); } static int poll_invalid(struct comedi_device *dev, struct comedi_subdevice *s) @@ -415,6 +411,7 @@ static int insn_rw_emulate_bits(struct comedi_device *dev, new_insn.insn = INSN_BITS; new_insn.chanspec = base_bitfield_channel; new_insn.n = 2; + new_insn.data = new_data; new_insn.subdev = insn->subdev; if (insn->insn == INSN_WRITE) { @@ -587,9 +584,9 @@ static unsigned int comedi_buf_munge(struct comedi_async *async, block_size = num_bytes - count; if (block_size < 0) { - dev_warn(s->device->class_dev, - "%s: %s: bug! block_size is negative\n", - __FILE__, __func__); + printk(KERN_WARNING + "%s: %s: bug! block_size is negative\n", + __FILE__, __func__); break; } if ((int)(async->munge_ptr + block_size - @@ -670,8 +667,7 @@ unsigned comedi_buf_write_free(struct comedi_async *async, unsigned int nbytes) { if ((int)(async->buf_write_count + nbytes - async->buf_write_alloc_count) > 0) { - dev_info(async->subdevice->device->class_dev, - "attempted to write-free more bytes than have been write-allocated.\n"); + printk(KERN_INFO "comedi: attempted to write-free more bytes than have been write-allocated.\n"); nbytes = async->buf_write_alloc_count - async->buf_write_count; } async->buf_write_count += nbytes; @@ -707,8 +703,8 @@ unsigned comedi_buf_read_free(struct comedi_async *async, unsigned int nbytes) smp_mb(); if ((int)(async->buf_read_count + nbytes - async->buf_read_alloc_count) > 0) { - dev_info(async->subdevice->device->class_dev, - "attempted to read-free more bytes than have been read-allocated.\n"); + printk(KERN_INFO + "comedi: attempted to read-free more bytes than have been read-allocated.\n"); nbytes = async->buf_read_alloc_count - async->buf_read_count; } async->buf_read_count += nbytes; @@ -857,9 +853,10 @@ comedi_auto_config_helper(struct device *hardware_device, mutex_lock(&comedi_dev->mutex); if (comedi_dev->attached) ret = -EBUSY; - else if (!try_module_get(driver->module)) + else if (!try_module_get(driver->module)) { + printk(KERN_INFO "comedi: failed to increment module count\n"); ret = -EIO; - else { + } else { /* set comedi_dev->driver here for attach wrapper */ comedi_dev->driver = driver; ret = (*attach_wrapper)(comedi_dev, context); @@ -887,19 +884,14 @@ static int comedi_auto_config_wrapper(struct comedi_device *dev, void *context) * has already been copied to it->board_name */ dev->board_ptr = comedi_recognize(driv, it->board_name); if (dev->board_ptr == NULL) { - dev_warn(dev->class_dev, - "auto config failed to find board entry '%s' for driver '%s'\n", - it->board_name, driv->driver_name); + printk(KERN_WARNING + "comedi: auto config failed to find board entry" + " '%s' for driver '%s'\n", it->board_name, + driv->driver_name); comedi_report_boards(driv); return -EINVAL; } } - if (!driv->attach) { - dev_warn(dev->class_dev, - "BUG! driver '%s' using old-style auto config but has no attach handler\n", - driv->driver_name); - return -EINVAL; - } return driv->attach(dev, it); } diff --git a/trunk/drivers/staging/comedi/drivers/8253.h b/trunk/drivers/staging/comedi/drivers/8253.h index 429e0d60c0a3..3eb45d46e05b 100644 --- a/trunk/drivers/staging/comedi/drivers/8253.h +++ b/trunk/drivers/staging/comedi/drivers/8253.h @@ -262,10 +262,8 @@ static inline int i8254_load(unsigned long base_address, unsigned int regshift, return 0; } -static inline int i8254_mm_load(void __iomem *base_address, - unsigned int regshift, - unsigned int counter_number, - unsigned int count, +static inline int i8254_mm_load(void *base_address, unsigned int regshift, + unsigned int counter_number, unsigned int count, unsigned int mode) { unsigned int byte; @@ -313,8 +311,7 @@ static inline int i8254_read(unsigned long base_address, unsigned int regshift, return ret; } -static inline int i8254_mm_read(void __iomem *base_address, - unsigned int regshift, +static inline int i8254_mm_read(void *base_address, unsigned int regshift, unsigned int counter_number) { unsigned int byte; @@ -351,7 +348,7 @@ static inline void i8254_write(unsigned long base_address, outb(byte, base_address + (counter_number << regshift)); } -static inline void i8254_mm_write(void __iomem *base_address, +static inline void i8254_mm_write(void *base_address, unsigned int regshift, unsigned int counter_number, unsigned int count) @@ -393,7 +390,7 @@ static inline int i8254_set_mode(unsigned long base_address, return 0; } -static inline int i8254_mm_set_mode(void __iomem *base_address, +static inline int i8254_mm_set_mode(void *base_address, unsigned int regshift, unsigned int counter_number, unsigned int mode) @@ -422,7 +419,7 @@ static inline int i8254_status(unsigned long base_address, return inb(base_address + (counter_number << regshift)); } -static inline int i8254_mm_status(void __iomem *base_address, +static inline int i8254_mm_status(void *base_address, unsigned int regshift, unsigned int counter_number) { diff --git a/trunk/drivers/staging/comedi/drivers/8255.c b/trunk/drivers/staging/comedi/drivers/8255.c index a256622e2dd7..4c9977b8a5ae 100644 --- a/trunk/drivers/staging/comedi/drivers/8255.c +++ b/trunk/drivers/staging/comedi/drivers/8255.c @@ -82,8 +82,6 @@ I/O port base address can be found in the output of 'lspci -v'. #include #include - -#include "comedi_fc.h" #include "8255.h" #define _8255_SIZE 4 @@ -231,20 +229,39 @@ static int subdev_8255_cmdtest(struct comedi_device *dev, struct comedi_cmd *cmd) { int err = 0; + unsigned int tmp; + + /* step 1 */ + + tmp = cmd->start_src; + cmd->start_src &= TRIG_NOW; + if (!cmd->start_src || tmp != cmd->start_src) + err++; + + tmp = cmd->scan_begin_src; + cmd->scan_begin_src &= TRIG_EXT; + if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) + err++; - /* Step 1 : check if triggers are trivially valid */ + tmp = cmd->convert_src; + cmd->convert_src &= TRIG_FOLLOW; + if (!cmd->convert_src || tmp != cmd->convert_src) + err++; - err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW); - err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_EXT); - err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_FOLLOW); - err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT); - err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_NONE); + tmp = cmd->scan_end_src; + cmd->scan_end_src &= TRIG_COUNT; + if (!cmd->scan_end_src || tmp != cmd->scan_end_src) + err++; + + tmp = cmd->stop_src; + cmd->stop_src &= TRIG_NONE; + if (!cmd->stop_src || tmp != cmd->stop_src) + err++; if (err) return 1; - /* Step 2a : make sure trigger sources are unique */ - /* Step 2b : and mutually compatible */ + /* step 2 */ if (err) return 2; @@ -386,7 +403,7 @@ static int dev_8255_attach(struct comedi_device *dev, return ret; for (i = 0; i < dev->n_subdevices; i++) { - s = &dev->subdevices[i]; + s = dev->subdevices + i; iobase = it->options[i]; if (!request_region(iobase, _8255_SIZE, "8255")) { @@ -412,7 +429,7 @@ static void dev_8255_detach(struct comedi_device *dev) int i; for (i = 0; i < dev->n_subdevices; i++) { - s = &dev->subdevices[i]; + s = dev->subdevices + i; if (s->type != COMEDI_SUBD_UNUSED) { spriv = s->private; release_region(spriv->iobase, _8255_SIZE); diff --git a/trunk/drivers/staging/comedi/drivers/8255_pci.c b/trunk/drivers/staging/comedi/drivers/8255_pci.c deleted file mode 100644 index 7dff3c01dc29..000000000000 --- a/trunk/drivers/staging/comedi/drivers/8255_pci.c +++ /dev/null @@ -1,353 +0,0 @@ -/* - * COMEDI driver for generic PCI based 8255 digital i/o boards - * Copyright (C) 2012 H Hartley Sweeten - * - * Based on the tested adl_pci7296 driver written by: - * Jon Grierson - * and the experimental cb_pcidio driver written by: - * Yoshiya Matsuzaka - * - * COMEDI - Linux Control and Measurement Device Interface - * Copyright (C) 2000 David A. Schleef - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/* -Driver: 8255_pci -Description: Generic PCI based 8255 Digital I/O boards -Devices: (ADLink) PCI-7224 [adl_pci-7224] - 24 channels - (ADLink) PCI-7248 [adl_pci-7248] - 48 channels - (ADLink) PCI-7296 [adl_pci-7296] - 96 channels - (Measurement Computing) PCI-DIO24 [cb_pci-dio24] - 24 channels - (Measurement Computing) PCI-DIO24H [cb_pci-dio24h] - 24 channels - (Measurement Computing) PCI-DIO48H [cb_pci-dio48h] - 48 channels - (Measurement Computing) PCI-DIO96H [cb_pci-dio96h] - 96 channels - (National Instruments) PCI-DIO-96 [ni_pci-dio-96] - 96 channels - (National Instruments) PCI-DIO-96B [ni_pci-dio-96b] - 96 channels - (National Instruments) PXI-6508 [ni_pxi-6508] - 96 channels - (National Instruments) PCI-6503 [ni_pci-6503] - 24 channels - (National Instruments) PCI-6503B [ni_pci-6503b] - 24 channels - (National Instruments) PCI-6503X [ni_pci-6503x] - 24 channels - (National Instruments) PXI-6503 [ni_pxi-6503] - 24 channels -Author: H Hartley Sweeten -Updated: Wed, 12 Sep 2012 11:52:01 -0700 -Status: untested - -Some of these boards also have an 8254 programmable timer/counter -chip. This chip is not currently supported by this driver. - -Interrupt support for these boards is also not currently supported. - -Configuration Options: not applicable, uses PCI auto config -*/ - -#include "../comedidev.h" - -#include "8255.h" - -/* - * PCI Device ID's supported by this driver - */ -#define PCI_DEVICE_ID_ADLINK_PCI7224 0x7224 -#define PCI_DEVICE_ID_ADLINK_PCI7248 0x7248 -#define PCI_DEVICE_ID_ADLINK_PCI7296 0x7296 - -/* ComputerBoards is now known as Measurement Computing */ -#define PCI_VENDOR_ID_CB 0x1307 - -#define PCI_DEVICE_ID_CB_PCIDIO48H 0x000b -#define PCI_DEVICE_ID_CB_PCIDIO24H 0x0014 -#define PCI_DEVICE_ID_CB_PCIDIO96H 0x0017 -#define PCI_DEVICE_ID_CB_PCIDIO24 0x0028 - -#define PCI_DEVICE_ID_NI_PCIDIO96 0x0160 -#define PCI_DEVICE_ID_NI_PCI6503 0x0400 -#define PCI_DEVICE_ID_NI_PCI6503B 0x1250 -#define PCI_DEVICE_ID_NI_PXI6508 0x13c0 -#define PCI_DEVICE_ID_NI_PCIDIO96B 0x1630 -#define PCI_DEVICE_ID_NI_PCI6503X 0x17d0 -#define PCI_DEVICE_ID_NI_PXI_6503 0x1800 - -struct pci_8255_boardinfo { - const char *name; - unsigned short vendor; - unsigned short device; - int dio_badr; - int is_mmio; - int n_8255; -}; - -static const struct pci_8255_boardinfo pci_8255_boards[] = { - { - .name = "adl_pci-7224", - .vendor = PCI_VENDOR_ID_ADLINK, - .device = PCI_DEVICE_ID_ADLINK_PCI7224, - .dio_badr = 2, - .n_8255 = 1, - }, { - .name = "adl_pci-7248", - .vendor = PCI_VENDOR_ID_ADLINK, - .device = PCI_DEVICE_ID_ADLINK_PCI7248, - .dio_badr = 2, - .n_8255 = 2, - }, { - .name = "adl_pci-7296", - .vendor = PCI_VENDOR_ID_ADLINK, - .device = PCI_DEVICE_ID_ADLINK_PCI7296, - .dio_badr = 2, - .n_8255 = 4, - }, { - .name = "cb_pci-dio24", - .vendor = PCI_VENDOR_ID_CB, - .device = PCI_DEVICE_ID_CB_PCIDIO24, - .dio_badr = 2, - .n_8255 = 1, - }, { - .name = "cb_pci-dio24h", - .vendor = PCI_VENDOR_ID_CB, - .device = PCI_DEVICE_ID_CB_PCIDIO24H, - .dio_badr = 2, - .n_8255 = 1, - }, { - .name = "cb_pci-dio48h", - .vendor = PCI_VENDOR_ID_CB, - .device = PCI_DEVICE_ID_CB_PCIDIO48H, - .dio_badr = 1, - .n_8255 = 2, - }, { - .name = "cb_pci-dio96h", - .vendor = PCI_VENDOR_ID_CB, - .device = PCI_DEVICE_ID_CB_PCIDIO96H, - .dio_badr = 2, - .n_8255 = 4, - }, { - .name = "ni_pci-dio-96", - .vendor = PCI_VENDOR_ID_NI, - .device = PCI_DEVICE_ID_NI_PCIDIO96, - .dio_badr = 1, - .is_mmio = 1, - .n_8255 = 4, - }, { - .name = "ni_pci-dio-96b", - .vendor = PCI_VENDOR_ID_NI, - .device = PCI_DEVICE_ID_NI_PCIDIO96B, - .dio_badr = 1, - .is_mmio = 1, - .n_8255 = 4, - }, { - .name = "ni_pxi-6508", - .vendor = PCI_VENDOR_ID_NI, - .device = PCI_DEVICE_ID_NI_PXI6508, - .dio_badr = 1, - .is_mmio = 1, - .n_8255 = 4, - }, { - .name = "ni_pci-6503", - .vendor = PCI_VENDOR_ID_NI, - .device = PCI_DEVICE_ID_NI_PCI6503, - .dio_badr = 1, - .is_mmio = 1, - .n_8255 = 1, - }, { - .name = "ni_pci-6503b", - .vendor = PCI_VENDOR_ID_NI, - .device = PCI_DEVICE_ID_NI_PCI6503B, - .dio_badr = 1, - .is_mmio = 1, - .n_8255 = 1, - }, { - .name = "ni_pci-6503x", - .vendor = PCI_VENDOR_ID_NI, - .device = PCI_DEVICE_ID_NI_PCI6503X, - .dio_badr = 1, - .is_mmio = 1, - .n_8255 = 1, - }, { - .name = "ni_pxi-6503", - .vendor = PCI_VENDOR_ID_NI, - .device = PCI_DEVICE_ID_NI_PXI_6503, - .dio_badr = 1, - .is_mmio = 1, - .n_8255 = 1, - }, -}; - -struct pci_8255_private { - void __iomem *mmio_base; -}; - -static int pci_8255_mmio(int dir, int port, int data, unsigned long iobase) -{ - void __iomem *mmio_base = (void __iomem *)iobase; - - if (dir) { - writeb(data, mmio_base + port); - return 0; - } else { - return readb(mmio_base + port); - } -} - -static const void *pci_8255_find_boardinfo(struct comedi_device *dev, - struct pci_dev *pcidev) -{ - const struct pci_8255_boardinfo *board; - int i; - - for (i = 0; i < ARRAY_SIZE(pci_8255_boards); i++) { - board = &pci_8255_boards[i]; - if (pcidev->vendor == board->vendor && - pcidev->device == board->device) - return board; - } - return NULL; -} - -static int pci_8255_attach_pci(struct comedi_device *dev, - struct pci_dev *pcidev) -{ - const struct pci_8255_boardinfo *board; - struct pci_8255_private *devpriv; - struct comedi_subdevice *s; - resource_size_t iobase; - unsigned long len; - int ret; - int i; - - comedi_set_hw_dev(dev, &pcidev->dev); - - board = pci_8255_find_boardinfo(dev, pcidev); - if (!board) - return -ENODEV; - dev->board_ptr = board; - dev->board_name = board->name; - - ret = alloc_private(dev, sizeof(*devpriv)); - if (ret < 0) - return ret; - devpriv = dev->private; - - ret = comedi_pci_enable(pcidev, dev->board_name); - if (ret) - return ret; - iobase = pci_resource_start(pcidev, board->dio_badr); - len = pci_resource_len(pcidev, board->dio_badr); - - if (board->is_mmio) { - devpriv->mmio_base = ioremap(iobase, len); - if (!devpriv->mmio_base) - return -ENOMEM; - } - dev->iobase = iobase; - - /* - * One, two, or four subdevices are setup by this driver depending - * on the number of channels provided by the board. Each subdevice - * has 24 channels supported by the 8255 module. - */ - ret = comedi_alloc_subdevices(dev, board->n_8255); - if (ret) - return ret; - - for (i = 0; i < board->n_8255; i++) { - s = &dev->subdevices[i]; - if (board->is_mmio) { - iobase = (unsigned long)(devpriv->mmio_base + (i * 4)); - ret = subdev_8255_init(dev, s, pci_8255_mmio, iobase); - } else { - iobase = dev->iobase + (i * 4); - ret = subdev_8255_init(dev, s, NULL, iobase); - } - if (ret) - return ret; - } - - dev_info(dev->class_dev, "%s attached (%d digital i/o channels)\n", - dev->board_name, board->n_8255 * 24); - - return 0; -} - -static void pci_8255_detach(struct comedi_device *dev) -{ - struct pci_dev *pcidev = comedi_to_pci_dev(dev); - const struct pci_8255_boardinfo *board = comedi_board(dev); - struct pci_8255_private *devpriv = dev->private; - struct comedi_subdevice *s; - int i; - - if (dev->subdevices) { - for (i = 0; i < board->n_8255; i++) { - s = &dev->subdevices[i]; - subdev_8255_cleanup(dev, s); - } - } - if (pcidev) { - if (devpriv->mmio_base) - iounmap(devpriv->mmio_base); - if (dev->iobase) - comedi_pci_disable(pcidev); - } -} - -static struct comedi_driver pci_8255_driver = { - .driver_name = "8255_pci", - .module = THIS_MODULE, - .attach_pci = pci_8255_attach_pci, - .detach = pci_8255_detach, -}; - -static int __devinit pci_8255_pci_probe(struct pci_dev *dev, - const struct pci_device_id *ent) -{ - return comedi_pci_auto_config(dev, &pci_8255_driver); -} - -static void __devexit pci_8255_pci_remove(struct pci_dev *dev) -{ - comedi_pci_auto_unconfig(dev); -} - -static DEFINE_PCI_DEVICE_TABLE(pci_8255_pci_table) = { - { PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI_DEVICE_ID_ADLINK_PCI7224) }, - { PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI_DEVICE_ID_ADLINK_PCI7248) }, - { PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI_DEVICE_ID_ADLINK_PCI7296) }, - { PCI_DEVICE(PCI_VENDOR_ID_CB, PCI_DEVICE_ID_CB_PCIDIO24) }, - { PCI_DEVICE(PCI_VENDOR_ID_CB, PCI_DEVICE_ID_CB_PCIDIO24H) }, - { PCI_DEVICE(PCI_VENDOR_ID_CB, PCI_DEVICE_ID_CB_PCIDIO48H) }, - { PCI_DEVICE(PCI_VENDOR_ID_CB, PCI_DEVICE_ID_CB_PCIDIO96H) }, - { PCI_DEVICE(PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PCIDIO96) }, - { PCI_DEVICE(PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PCIDIO96B) }, - { PCI_DEVICE(PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PXI6508) }, - { PCI_DEVICE(PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PCI6503) }, - { PCI_DEVICE(PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PCI6503B) }, - { PCI_DEVICE(PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PCI6503X) }, - { PCI_DEVICE(PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PXI_6503) }, - { 0 } -}; -MODULE_DEVICE_TABLE(pci, pci_8255_pci_table); - -static struct pci_driver pci_8255_pci_driver = { - .name = "8255_pci", - .id_table = pci_8255_pci_table, - .probe = pci_8255_pci_probe, - .remove = __devexit_p(pci_8255_pci_remove), -}; -module_comedi_pci_driver(pci_8255_driver, pci_8255_pci_driver); - -MODULE_DESCRIPTION("COMEDI - Generic PCI based 8255 Digital I/O boards"); -MODULE_AUTHOR("Comedi http://www.comedi.org"); -MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/staging/comedi/drivers/Makefile b/trunk/drivers/staging/comedi/drivers/Makefile index a2787c0ca327..57b19e44d867 100644 --- a/trunk/drivers/staging/comedi/drivers/Makefile +++ b/trunk/drivers/staging/comedi/drivers/Makefile @@ -55,7 +55,6 @@ obj-$(CONFIG_COMEDI_MULTIQ3) += multiq3.o obj-$(CONFIG_COMEDI_POC) += poc.o # Comedi PCI drivers -obj-$(CONFIG_COMEDI_8255_PCI) += 8255_pci.o obj-$(CONFIG_COMEDI_ADDI_APCI_035) += addi_apci_035.o obj-$(CONFIG_COMEDI_ADDI_APCI_1032) += addi_apci_1032.o obj-$(CONFIG_COMEDI_ADDI_APCI_1500) += addi_apci_1500.o @@ -70,7 +69,9 @@ obj-$(CONFIG_COMEDI_ADDI_APCI_3120) += addi_apci_3120.o obj-$(CONFIG_COMEDI_ADDI_APCI_3501) += addi_apci_3501.o obj-$(CONFIG_COMEDI_ADDI_APCI_3XXX) += addi_apci_3xxx.o obj-$(CONFIG_COMEDI_ADL_PCI6208) += adl_pci6208.o -obj-$(CONFIG_COMEDI_ADL_PCI7X3X) += adl_pci7x3x.o +obj-$(CONFIG_COMEDI_ADL_PCI7230) += adl_pci7230.o +obj-$(CONFIG_COMEDI_ADL_PCI7296) += adl_pci7296.o +obj-$(CONFIG_COMEDI_ADL_PCI7432) += adl_pci7432.o obj-$(CONFIG_COMEDI_ADL_PCI8164) += adl_pci8164.o obj-$(CONFIG_COMEDI_ADL_PCI9111) += adl_pci9111.o obj-$(CONFIG_COMEDI_ADL_PCI9118) += adl_pci9118.o @@ -95,6 +96,7 @@ obj-$(CONFIG_COMEDI_KE_COUNTER) += ke_counter.o obj-$(CONFIG_COMEDI_CB_PCIDAS64) += cb_pcidas64.o obj-$(CONFIG_COMEDI_CB_PCIDAS) += cb_pcidas.o obj-$(CONFIG_COMEDI_CB_PCIDDA) += cb_pcidda.o +obj-$(CONFIG_COMEDI_CB_PCIDIO) += cb_pcidio.o obj-$(CONFIG_COMEDI_CB_PCIMDAS) += cb_pcimdas.o obj-$(CONFIG_COMEDI_CB_PCIMDDA) += cb_pcimdda.o obj-$(CONFIG_COMEDI_ME4000) += me4000.o diff --git a/trunk/drivers/staging/comedi/drivers/acl7225b.c b/trunk/drivers/staging/comedi/drivers/acl7225b.c index 28c7fd3a96b6..ddba5db1e2e1 100644 --- a/trunk/drivers/staging/comedi/drivers/acl7225b.c +++ b/trunk/drivers/staging/comedi/drivers/acl7225b.c @@ -81,7 +81,7 @@ static int acl7225b_attach(struct comedi_device *dev, if (ret) return ret; - s = &dev->subdevices[0]; + s = dev->subdevices + 0; /* Relays outputs */ s->type = COMEDI_SUBD_DO; s->subdev_flags = SDF_WRITABLE; @@ -91,7 +91,7 @@ static int acl7225b_attach(struct comedi_device *dev, s->range_table = &range_digital; s->private = (void *)ACL7225_RIO_LO; - s = &dev->subdevices[1]; + s = dev->subdevices + 1; /* Relays status */ s->type = COMEDI_SUBD_DI; s->subdev_flags = SDF_READABLE; @@ -101,7 +101,7 @@ static int acl7225b_attach(struct comedi_device *dev, s->range_table = &range_digital; s->private = (void *)ACL7225_RIO_LO; - s = &dev->subdevices[2]; + s = dev->subdevices + 2; /* Isolated digital inputs */ s->type = COMEDI_SUBD_DI; s->subdev_flags = SDF_READABLE; diff --git a/trunk/drivers/staging/comedi/drivers/addi-data/addi_amcc_S5920.c b/trunk/drivers/staging/comedi/drivers/addi-data/addi_amcc_S5920.c new file mode 100644 index 000000000000..b973095146f9 --- /dev/null +++ b/trunk/drivers/staging/comedi/drivers/addi-data/addi_amcc_S5920.c @@ -0,0 +1,195 @@ +/** +@verbatim + +Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module. + + ADDI-DATA GmbH + Dieselstrasse 3 + D-77833 Ottersweier + Tel: +19(0)7223/9493-0 + Fax: +49(0)7223/9493-92 + http://www.addi-data.com + info@addi-data.com + +This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. + +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 + +You should also find the complete GPL in the COPYING file accompanying this source code. + +@endverbatim +*/ +/* + +-----------------------------------------------------------------------+ + | (C) ADDI-DATA GmbH Dieselstraße 3 D-77833 Ottersweier | + +-----------------------------------------------------------------------+ + | Tel : +49 (0) 7223/9493-0 | email : info@addi-data.com | + | Fax : +49 (0) 7223/9493-92 | Internet : http://www.addi-data.com | + +-------------------------------+---------------------------------------+ + | Project : ADDI HEADER READ WRITER | Compiler : Visual C++ | + | Module name : S5920.cpp | Version : 6.0 | + +-------------------------------+---------------------------------------+ + | Author : E. LIBS Date : 02/05/2002 | + +-----------------------------------------------------------------------+ + | Description : DLL with the S5920 PCI Controller functions | + +-----------------------------------------------------------------------+ + | UPDATE'S | + +-----------------------------------------------------------------------+ + | Date | Author | Description of updates | + +----------+-----------+------------------------------------------------+ + | 28/08/02 | LIBS Eric | Add return codes each time a function of the | + | | | Addi Library is called | + +-----------------------------------------------------------------------+ + | 31/07/03 | KRAUTH J. | Changes for the MSX-Box | + +-----------------------------------------------------------------------+ +*/ + +#include "addi_amcc_S5920.h" + +/*+----------------------------------------------------------------------------+*/ +/*| Function Name : int i_AddiHeaderRW_ReadEeprom |*/ +/*| (int i_NbOfWordsToRead, |*/ +/*| unsigned int dw_PCIBoardEepromAddress, |*/ +/*| unsigned short w_EepromStartAddress, |*/ +/*| unsigned short * pw_DataRead) |*/ +/*+----------------------------------------------------------------------------+*/ +/*| Task : Read word from the 5920 eeprom. |*/ +/*+----------------------------------------------------------------------------+*/ +/*| Input Parameters : int i_NbOfWordsToRead : Nbr. of word to read |*/ +/*| unsigned int dw_PCIBoardEepromAddress : Address of the eeprom |*/ +/*| unsigned short w_EepromStartAddress : Eeprom start address |*/ +/*+----------------------------------------------------------------------------+*/ +/*| Output Parameters : unsigned short * pw_DataRead : Read data |*/ +/*+----------------------------------------------------------------------------+*/ +/*| Return Value : - |*/ +/*+----------------------------------------------------------------------------+*/ + +int i_AddiHeaderRW_ReadEeprom(int i_NbOfWordsToRead, + unsigned int dw_PCIBoardEepromAddress, + unsigned short w_EepromStartAddress, unsigned short *pw_DataRead) +{ + unsigned int dw_eeprom_busy = 0; + int i_Counter = 0; + int i_WordCounter; + int i; + unsigned char pb_ReadByte[1]; + unsigned char b_ReadLowByte = 0; + unsigned char b_ReadHighByte = 0; + unsigned char b_SelectedAddressLow = 0; + unsigned char b_SelectedAddressHigh = 0; + unsigned short w_ReadWord = 0; + + for (i_WordCounter = 0; i_WordCounter < i_NbOfWordsToRead; + i_WordCounter++) { + do { + dw_eeprom_busy = + inl(dw_PCIBoardEepromAddress + + AMCC_OP_REG_MCSR); + dw_eeprom_busy = dw_eeprom_busy & EEPROM_BUSY; + } while (dw_eeprom_busy == EEPROM_BUSY); + + for (i_Counter = 0; i_Counter < 2; i_Counter++) { + b_SelectedAddressLow = (w_EepromStartAddress + i_Counter) % 256; /* Read the low 8 bit part */ + b_SelectedAddressHigh = (w_EepromStartAddress + i_Counter) / 256; /* Read the high 8 bit part */ + + /* Select the load low address mode */ + outb(NVCMD_LOAD_LOW, + dw_PCIBoardEepromAddress + AMCC_OP_REG_MCSR + + 3); + + /* Wait on busy */ + do { + dw_eeprom_busy = + inl(dw_PCIBoardEepromAddress + + AMCC_OP_REG_MCSR); + dw_eeprom_busy = dw_eeprom_busy & EEPROM_BUSY; + } while (dw_eeprom_busy == EEPROM_BUSY); + + /* Load the low address */ + outb(b_SelectedAddressLow, + dw_PCIBoardEepromAddress + AMCC_OP_REG_MCSR + + 2); + + /* Wait on busy */ + do { + dw_eeprom_busy = + inl(dw_PCIBoardEepromAddress + + AMCC_OP_REG_MCSR); + dw_eeprom_busy = dw_eeprom_busy & EEPROM_BUSY; + } while (dw_eeprom_busy == EEPROM_BUSY); + + /* Select the load high address mode */ + outb(NVCMD_LOAD_HIGH, + dw_PCIBoardEepromAddress + AMCC_OP_REG_MCSR + + 3); + + /* Wait on busy */ + do { + dw_eeprom_busy = + inl(dw_PCIBoardEepromAddress + + AMCC_OP_REG_MCSR); + dw_eeprom_busy = dw_eeprom_busy & EEPROM_BUSY; + } while (dw_eeprom_busy == EEPROM_BUSY); + + /* Load the high address */ + outb(b_SelectedAddressHigh, + dw_PCIBoardEepromAddress + AMCC_OP_REG_MCSR + + 2); + + /* Wait on busy */ + do { + dw_eeprom_busy = + inl(dw_PCIBoardEepromAddress + + AMCC_OP_REG_MCSR); + dw_eeprom_busy = dw_eeprom_busy & EEPROM_BUSY; + } while (dw_eeprom_busy == EEPROM_BUSY); + + /* Select the READ mode */ + outb(NVCMD_BEGIN_READ, + dw_PCIBoardEepromAddress + AMCC_OP_REG_MCSR + + 3); + + /* Wait on busy */ + do { + dw_eeprom_busy = + inl(dw_PCIBoardEepromAddress + + AMCC_OP_REG_MCSR); + dw_eeprom_busy = dw_eeprom_busy & EEPROM_BUSY; + } while (dw_eeprom_busy == EEPROM_BUSY); + + /* Read data into the EEPROM */ + *pb_ReadByte = + inb(dw_PCIBoardEepromAddress + + AMCC_OP_REG_MCSR + 2); + + /* Wait on busy */ + do { + dw_eeprom_busy = + inl(dw_PCIBoardEepromAddress + + AMCC_OP_REG_MCSR); + dw_eeprom_busy = dw_eeprom_busy & EEPROM_BUSY; + } while (dw_eeprom_busy == EEPROM_BUSY); + + /* Select the upper address part */ + if (i_Counter == 0) + b_ReadLowByte = pb_ReadByte[0]; + else + b_ReadHighByte = pb_ReadByte[0]; + + /* Sleep */ + msleep(1); + + } + w_ReadWord = + (b_ReadLowByte | (((unsigned short)b_ReadHighByte) * + 256)); + + pw_DataRead[i_WordCounter] = w_ReadWord; + + w_EepromStartAddress += 2; /* to read the next word */ + + } /* for (...) i_NbOfWordsToRead */ + return 0; +} diff --git a/trunk/drivers/staging/comedi/drivers/addi-data/addi_amcc_S5920.h b/trunk/drivers/staging/comedi/drivers/addi-data/addi_amcc_S5920.h new file mode 100644 index 000000000000..9afdb1357aa9 --- /dev/null +++ b/trunk/drivers/staging/comedi/drivers/addi-data/addi_amcc_S5920.h @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module. + * + * ADDI-DATA GmbH + * Dieselstrasse 3 + * D-77833 Ottersweier + * Tel: +19(0)7223/9493-0 + * Fax: +49(0)7223/9493-92 + * http://www.addi-data.com + * info@addi-data.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + */ + +#define AMCC_OP_REG_MCSR 0x3c +#define EEPROM_BUSY 0x80000000 +#define NVCMD_LOAD_LOW (0x4 << 5) /* nvRam load low command */ +#define NVCMD_LOAD_HIGH (0x5 << 5) /* nvRam load high command */ +#define NVCMD_BEGIN_READ (0x7 << 5) /* nvRam begin read command */ +#define NVCMD_BEGIN_WRITE (0x6 << 5) /* EEPROM begin write command */ + +int i_AddiHeaderRW_ReadEeprom(int i_NbOfWordsToRead, + unsigned int dw_PCIBoardEepromAddress, + unsigned short w_EepromStartAddress, unsigned short *pw_DataRead); diff --git a/trunk/drivers/staging/comedi/drivers/addi-data/addi_common.c b/trunk/drivers/staging/comedi/drivers/addi-data/addi_common.c index 99a96bd96716..a3d4ed25fb0d 100644 --- a/trunk/drivers/staging/comedi/drivers/addi-data/addi_common.c +++ b/trunk/drivers/staging/comedi/drivers/addi-data/addi_common.c @@ -1669,7 +1669,7 @@ static int i_ADDI_Attach(struct comedi_device *dev, struct comedi_devconfig *it) return ret; /* Allocate and Initialise AI Subdevice Structures */ - s = &dev->subdevices[0]; + s = dev->subdevices + 0; if ((devpriv->s_EeParameters.i_NbrAiChannel) || (this_board->i_NbrAiChannelDiff)) { dev->read_subdev = s; @@ -1705,7 +1705,7 @@ static int i_ADDI_Attach(struct comedi_device *dev, struct comedi_devconfig *it) } /* Allocate and Initialise AO Subdevice Structures */ - s = &dev->subdevices[1]; + s = dev->subdevices + 1; if (devpriv->s_EeParameters.i_NbrAoChannel) { s->type = COMEDI_SUBD_AO; s->subdev_flags = SDF_WRITEABLE | SDF_GROUND | SDF_COMMON; @@ -1720,7 +1720,7 @@ static int i_ADDI_Attach(struct comedi_device *dev, struct comedi_devconfig *it) s->type = COMEDI_SUBD_UNUSED; } /* Allocate and Initialise DI Subdevice Structures */ - s = &dev->subdevices[2]; + s = dev->subdevices + 2; if (devpriv->s_EeParameters.i_NbrDiChannel) { s->type = COMEDI_SUBD_DI; s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_COMMON; @@ -1738,7 +1738,7 @@ static int i_ADDI_Attach(struct comedi_device *dev, struct comedi_devconfig *it) s->type = COMEDI_SUBD_UNUSED; } /* Allocate and Initialise DO Subdevice Structures */ - s = &dev->subdevices[3]; + s = dev->subdevices + 3; if (devpriv->s_EeParameters.i_NbrDoChannel) { s->type = COMEDI_SUBD_DO; s->subdev_flags = @@ -1760,7 +1760,7 @@ static int i_ADDI_Attach(struct comedi_device *dev, struct comedi_devconfig *it) } /* Allocate and Initialise Timer Subdevice Structures */ - s = &dev->subdevices[4]; + s = dev->subdevices + 4; if (devpriv->s_EeParameters.i_Timer) { s->type = COMEDI_SUBD_TIMER; s->subdev_flags = SDF_WRITEABLE | SDF_GROUND | SDF_COMMON; @@ -1778,7 +1778,7 @@ static int i_ADDI_Attach(struct comedi_device *dev, struct comedi_devconfig *it) } /* Allocate and Initialise TTL */ - s = &dev->subdevices[5]; + s = dev->subdevices + 5; if (this_board->i_NbrTTLChannel) { s->type = COMEDI_SUBD_TTLIO; s->subdev_flags = @@ -1797,7 +1797,7 @@ static int i_ADDI_Attach(struct comedi_device *dev, struct comedi_devconfig *it) } /* EEPROM */ - s = &dev->subdevices[6]; + s = dev->subdevices + 6; if (this_board->i_PCIEeprom) { s->type = COMEDI_SUBD_MEMORY; s->subdev_flags = SDF_READABLE | SDF_INTERNAL; diff --git a/trunk/drivers/staging/comedi/drivers/addi-data/amcc_s5933_58.h b/trunk/drivers/staging/comedi/drivers/addi-data/amcc_s5933_58.h new file mode 100644 index 000000000000..c26c28c31b97 --- /dev/null +++ b/trunk/drivers/staging/comedi/drivers/addi-data/amcc_s5933_58.h @@ -0,0 +1,453 @@ +/* + Modified by umesh on 16th may 2001 + Modified by sarath on 22nd may 2001 +*/ + +/* + comedi/drivers/amcc_s5933_v_58.h + + Stuff for AMCC S5933 PCI Controller + + Author: Michal Dobes + + Inspirated from general-purpose AMCC S5933 PCI Matchmaker driver + made by Andrea Cisternino + and as result of espionage from MITE code made by David A. Schleef. + Thanks to AMCC for their on-line documentation and bus master DMA + example. +*/ + +#ifndef _AMCC_S5933_H_ +#define _AMCC_S5933_H_ + +#include +#include "../../comedidev.h" + +/***********Added by sarath for compatibility with APCI3120 + +*************************/ + +#define FIFO_ADVANCE_ON_BYTE_2 0x20000000 /* written on base0 */ + +#define AMWEN_ENABLE 0x02 /* added for step 6 dma written on base2 */ +#define A2P_FIFO_WRITE_ENABLE 0x01 + +#define AGCSTS_TC_ENABLE 0x10000000 /* Added for transfer count enable bit */ + +/* ADDON RELATED ADDITIONS */ +/* Constant */ +#define APCI3120_ENABLE_TRANSFER_ADD_ON_LOW 0x00 +#define APCI3120_ENABLE_TRANSFER_ADD_ON_HIGH 0x1200 +#define APCI3120_A2P_FIFO_MANAGEMENT 0x04000400L +#define APCI3120_AMWEN_ENABLE 0x02 +#define APCI3120_A2P_FIFO_WRITE_ENABLE 0x01 +#define APCI3120_FIFO_ADVANCE_ON_BYTE_2 0x20000000L +#define APCI3120_ENABLE_WRITE_TC_INT 0x00004000L +#define APCI3120_CLEAR_WRITE_TC_INT 0x00040000L +#define APCI3120_DISABLE_AMWEN_AND_A2P_FIFO_WRITE 0x0 +#define APCI3120_DISABLE_BUS_MASTER_ADD_ON 0x0 +#define APCI3120_DISABLE_BUS_MASTER_PCI 0x0 + + /* ADD_ON ::: this needed since apci supports 16 bit interface to add on */ +#define APCI3120_ADD_ON_AGCSTS_LOW 0x3C +#define APCI3120_ADD_ON_AGCSTS_HIGH APCI3120_ADD_ON_AGCSTS_LOW + 2 +#define APCI3120_ADD_ON_MWAR_LOW 0x24 +#define APCI3120_ADD_ON_MWAR_HIGH APCI3120_ADD_ON_MWAR_LOW + 2 +#define APCI3120_ADD_ON_MWTC_LOW 0x058 +#define APCI3120_ADD_ON_MWTC_HIGH APCI3120_ADD_ON_MWTC_LOW + 2 + +/* AMCC */ +#define APCI3120_AMCC_OP_MCSR 0x3C +#define APCI3120_AMCC_OP_REG_INTCSR 0x38 + +/*******from here all upward definitions are added by sarath */ + +/****************************************************************************/ +/* AMCC Operation Register Offsets - PCI */ +/****************************************************************************/ + +#define AMCC_OP_REG_OMB1 0x00 +#define AMCC_OP_REG_OMB2 0x04 +#define AMCC_OP_REG_OMB3 0x08 +#define AMCC_OP_REG_OMB4 0x0c +#define AMCC_OP_REG_IMB1 0x10 +#define AMCC_OP_REG_IMB2 0x14 +#define AMCC_OP_REG_IMB3 0x18 +#define AMCC_OP_REG_IMB4 0x1c +#define AMCC_OP_REG_FIFO 0x20 +#define AMCC_OP_REG_MWAR 0x24 +#define AMCC_OP_REG_MWTC 0x28 +#define AMCC_OP_REG_MRAR 0x2c +#define AMCC_OP_REG_MRTC 0x30 +#define AMCC_OP_REG_MBEF 0x34 +#define AMCC_OP_REG_INTCSR 0x38 +#define AMCC_OP_REG_INTCSR_SRC (AMCC_OP_REG_INTCSR + 2) /* int source */ +#define AMCC_OP_REG_INTCSR_FEC (AMCC_OP_REG_INTCSR + 3) /* FIFO ctrl */ +#define AMCC_OP_REG_MCSR 0x3c +#define AMCC_OP_REG_MCSR_NVDATA (AMCC_OP_REG_MCSR + 2) /* Data in byte 2 */ +#define AMCC_OP_REG_MCSR_NVCMD (AMCC_OP_REG_MCSR + 3) /* Command in byte 3 */ + +#define AMCC_FIFO_DEPTH_DWORD 8 +#define AMCC_FIFO_DEPTH_BYTES (8 * sizeof (u32)) + +/****************************************************************************/ +/* AMCC Operation Registers Size - PCI */ +/****************************************************************************/ + +#define AMCC_OP_REG_SIZE 64 /* in bytes */ + +/****************************************************************************/ +/* AMCC Operation Register Offsets - Add-on */ +/****************************************************************************/ + +#define AMCC_OP_REG_AIMB1 0x00 +#define AMCC_OP_REG_AIMB2 0x04 +#define AMCC_OP_REG_AIMB3 0x08 +#define AMCC_OP_REG_AIMB4 0x0c +#define AMCC_OP_REG_AOMB1 0x10 +#define AMCC_OP_REG_AOMB2 0x14 +#define AMCC_OP_REG_AOMB3 0x18 +#define AMCC_OP_REG_AOMB4 0x1c +#define AMCC_OP_REG_AFIFO 0x20 +#define AMCC_OP_REG_AMWAR 0x24 +#define AMCC_OP_REG_APTA 0x28 +#define AMCC_OP_REG_APTD 0x2c +#define AMCC_OP_REG_AMRAR 0x30 +#define AMCC_OP_REG_AMBEF 0x34 +#define AMCC_OP_REG_AINT 0x38 +#define AMCC_OP_REG_AGCSTS 0x3c +#define AMCC_OP_REG_AMWTC 0x58 +#define AMCC_OP_REG_AMRTC 0x5c + +/****************************************************************************/ +/* AMCC - Add-on General Control/Status Register */ +/****************************************************************************/ + +#define AGCSTS_CONTROL_MASK 0xfffff000 +#define AGCSTS_NV_ACC_MASK 0xe0000000 +#define AGCSTS_RESET_MASK 0x0e000000 +#define AGCSTS_NV_DA_MASK 0x00ff0000 +#define AGCSTS_BIST_MASK 0x0000f000 +#define AGCSTS_STATUS_MASK 0x000000ff +#define AGCSTS_TCZERO_MASK 0x000000c0 +#define AGCSTS_FIFO_ST_MASK 0x0000003f + +#define AGCSTS_RESET_MBFLAGS 0x08000000 +#define AGCSTS_RESET_P2A_FIFO 0x04000000 +#define AGCSTS_RESET_A2P_FIFO 0x02000000 +#define AGCSTS_RESET_FIFOS (AGCSTS_RESET_A2P_FIFO | AGCSTS_RESET_P2A_FIFO) + +#define AGCSTS_A2P_TCOUNT 0x00000080 +#define AGCSTS_P2A_TCOUNT 0x00000040 + +#define AGCSTS_FS_P2A_EMPTY 0x00000020 +#define AGCSTS_FS_P2A_HALF 0x00000010 +#define AGCSTS_FS_P2A_FULL 0x00000008 + +#define AGCSTS_FS_A2P_EMPTY 0x00000004 +#define AGCSTS_FS_A2P_HALF 0x00000002 +#define AGCSTS_FS_A2P_FULL 0x00000001 + +/****************************************************************************/ +/* AMCC - Add-on Interrupt Control/Status Register */ +/****************************************************************************/ + +#define AINT_INT_MASK 0x00ff0000 +#define AINT_SEL_MASK 0x0000ffff +#define AINT_IS_ENSEL_MASK 0x00001f1f + +#define AINT_INT_ASSERTED 0x00800000 +#define AINT_BM_ERROR 0x00200000 +#define AINT_BIST_INT 0x00100000 + +#define AINT_RT_COMPLETE 0x00080000 +#define AINT_WT_COMPLETE 0x00040000 + +#define AINT_OUT_MB_INT 0x00020000 +#define AINT_IN_MB_INT 0x00010000 + +#define AINT_READ_COMPL 0x00008000 +#define AINT_WRITE_COMPL 0x00004000 + +#define AINT_OMB_ENABLE 0x00001000 +#define AINT_OMB_SELECT 0x00000c00 +#define AINT_OMB_BYTE 0x00000300 + +#define AINT_IMB_ENABLE 0x00000010 +#define AINT_IMB_SELECT 0x0000000c +#define AINT_IMB_BYTE 0x00000003 + +/* Enable Bus Mastering */ +#define EN_A2P_TRANSFERS 0x00000400 +/* FIFO Flag Reset */ +#define RESET_A2P_FLAGS 0x04000000L +/* FIFO Relative Priority */ +#define A2P_HI_PRIORITY 0x00000100L +/* Identify Interrupt Sources */ +#define ANY_S593X_INT 0x00800000L +#define READ_TC_INT 0x00080000L +#define WRITE_TC_INT 0x00040000L +#define IN_MB_INT 0x00020000L +#define MASTER_ABORT_INT 0x00100000L +#define TARGET_ABORT_INT 0x00200000L +#define BUS_MASTER_INT 0x00200000L + +/****************************************************************************/ + +struct pcilst_struct { + struct pcilst_struct *next; + int used; + struct pci_dev *pcidev; + unsigned short vendor; + unsigned short device; + unsigned int master; + unsigned char pci_bus; + unsigned char pci_slot; + unsigned char pci_func; + unsigned int io_addr[5]; + unsigned int irq; +}; + +struct pcilst_struct *amcc_devices; /* ptr to root list of all amcc devices */ + +/****************************************************************************/ + +void v_pci_card_list_init(unsigned short pci_vendor, char display); +void v_pci_card_list_cleanup(unsigned short pci_vendor); +struct pcilst_struct *ptr_find_free_pci_card_by_device(unsigned short vendor_id, + unsigned short + device_id); +int i_find_free_pci_card_by_position(unsigned short vendor_id, + unsigned short device_id, + unsigned short pci_bus, + unsigned short pci_slot, + struct pcilst_struct **card); +struct pcilst_struct *ptr_select_and_alloc_pci_card(unsigned short vendor_id, + unsigned short device_id, + unsigned short pci_bus, + unsigned short pci_slot); + +int i_pci_card_alloc(struct pcilst_struct *amcc); +int i_pci_card_free(struct pcilst_struct *amcc); +void v_pci_card_list_display(void); +int i_pci_card_data(struct pcilst_struct *amcc, + unsigned char *pci_bus, unsigned char *pci_slot, + unsigned char *pci_func, unsigned short *io_addr, + unsigned short *irq, unsigned short *master); + +/****************************************************************************/ + +/* build list of amcc cards in this system */ +void v_pci_card_list_init(unsigned short pci_vendor, char display) +{ + struct pci_dev *pcidev; + struct pcilst_struct *amcc, *last; + int i; + + amcc_devices = NULL; + last = NULL; + + pci_for_each_dev(pcidev) { + if (pcidev->vendor == pci_vendor) { + amcc = kzalloc(sizeof(*amcc), GFP_KERNEL); + if (amcc == NULL) + continue; + + amcc->pcidev = pcidev; + if (last) { + last->next = amcc; + } else { + amcc_devices = amcc; + } + last = amcc; + + amcc->vendor = pcidev->vendor; + amcc->device = pcidev->device; +#if 0 + amcc->master = pcidev->master; /* how get this information under 2.4 kernels? */ +#endif + amcc->pci_bus = pcidev->bus->number; + amcc->pci_slot = PCI_SLOT(pcidev->devfn); + amcc->pci_func = PCI_FUNC(pcidev->devfn); + for (i = 0; i < 5; i++) + amcc->io_addr[i] = + pcidev->resource[i].start & ~3UL; + amcc->irq = pcidev->irq; + } + } + + if (display) + v_pci_card_list_display(); +} + +/****************************************************************************/ +/* free up list of amcc cards in this system */ +void v_pci_card_list_cleanup(unsigned short pci_vendor) +{ + struct pcilst_struct *amcc, *next; + + for (amcc = amcc_devices; amcc; amcc = next) { + next = amcc->next; + kfree(amcc); + } + + amcc_devices = NULL; +} + +/****************************************************************************/ +/* find first unused card with this device_id */ +struct pcilst_struct *ptr_find_free_pci_card_by_device(unsigned short vendor_id, + unsigned short device_id) +{ + struct pcilst_struct *amcc, *next; + + for (amcc = amcc_devices; amcc; amcc = next) { + next = amcc->next; + if ((!amcc->used) && (amcc->device == device_id) + && (amcc->vendor == vendor_id)) + return amcc; + + } + + return NULL; +} + +/****************************************************************************/ +/* find card on requested position */ +int i_find_free_pci_card_by_position(unsigned short vendor_id, + unsigned short device_id, + unsigned short pci_bus, + unsigned short pci_slot, + struct pcilst_struct **card) +{ + struct pcilst_struct *amcc, *next; + + *card = NULL; + for (amcc = amcc_devices; amcc; amcc = next) { + next = amcc->next; + if ((amcc->vendor == vendor_id) && (amcc->device == device_id) + && (amcc->pci_bus == pci_bus) + && (amcc->pci_slot == pci_slot)) { + if (!(amcc->used)) { + *card = amcc; + return 0; /* ok, card is found */ + } else { + printk + (" - \nCard on requested position is used b:s %d:%d!\n", + pci_bus, pci_slot); + return 2; /* card exist but is used */ + } + } + } + + return 1; /* no card found */ +} + +/****************************************************************************/ +/* mark card as used */ +int i_pci_card_alloc(struct pcilst_struct *amcc) +{ + if (!amcc) + return -1; + + if (amcc->used) + return 1; + amcc->used = 1; + return 0; +} + +/****************************************************************************/ +/* mark card as free */ +int i_pci_card_free(struct pcilst_struct *amcc) +{ + if (!amcc) + return -1; + + if (!amcc->used) + return 1; + amcc->used = 0; + return 0; +} + +/****************************************************************************/ +/* display list of found cards */ +void v_pci_card_list_display(void) +{ + struct pcilst_struct *amcc, *next; + + printk("List of pci cards\n"); + printk("bus:slot:func vendor device master io_amcc io_daq irq used\n"); + + for (amcc = amcc_devices; amcc; amcc = next) { + next = amcc->next; + printk + ("%2d %2d %2d 0x%4x 0x%4x %3s 0x%4x 0x%4x %2d %2d\n", + amcc->pci_bus, amcc->pci_slot, amcc->pci_func, + amcc->vendor, amcc->device, amcc->master ? "yes" : "no", + amcc->io_addr[0], amcc->io_addr[2], amcc->irq, amcc->used); + + } +} + +/****************************************************************************/ +/* return all card information for driver */ +int i_pci_card_data(struct pcilst_struct *amcc, + unsigned char *pci_bus, unsigned char *pci_slot, + unsigned char *pci_func, unsigned short *io_addr, + unsigned short *irq, unsigned short *master) +{ + int i; + + if (!amcc) + return -1; + *pci_bus = amcc->pci_bus; + *pci_slot = amcc->pci_slot; + *pci_func = amcc->pci_func; + for (i = 0; i < 5; i++) + io_addr[i] = amcc->io_addr[i]; + *irq = amcc->irq; + *master = amcc->master; + return 0; +} + +/****************************************************************************/ +/* select and alloc card */ +struct pcilst_struct *ptr_select_and_alloc_pci_card(unsigned short vendor_id, + unsigned short device_id, + unsigned short pci_bus, + unsigned short pci_slot) +{ + struct pcilst_struct *card; + + if ((pci_bus < 1) & (pci_slot < 1)) { /* use autodetection */ + card = ptr_find_free_pci_card_by_device(vendor_id, device_id); + if (card == NULL) { + printk(" - Unused card not found in system!\n"); + return NULL; + } + } else { + switch (i_find_free_pci_card_by_position(vendor_id, device_id, + pci_bus, pci_slot, + &card)) { + case 1: + printk + (" - Card not found on requested position b:s %d:%d!\n", + pci_bus, pci_slot); + return NULL; + case 2: + printk + (" - Card on requested position is used b:s %d:%d!\n", + pci_bus, pci_slot); + return NULL; + } + } + + if (i_pci_card_alloc(card) != 0) { + printk(" - Can't allocate card!\n"); + return NULL; + } + + return card; +} + +#endif diff --git a/trunk/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.c b/trunk/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.c index f9a8937be8ed..595238feaf42 100644 --- a/trunk/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.c +++ b/trunk/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.c @@ -67,7 +67,7 @@ void i_ADDI_AttachPCI1710(struct comedi_device *dev) return; /* Allocate and Initialise Timer Subdevice Structures */ - s = &dev->subdevices[0]; + s = dev->subdevices + 0; s->type = COMEDI_SUBD_TIMER; s->subdev_flags = SDF_WRITEABLE | SDF_GROUND | SDF_COMMON; @@ -81,7 +81,7 @@ void i_ADDI_AttachPCI1710(struct comedi_device *dev) s->insn_bits = i_APCI1710_InsnBitsTimer; /* Allocate and Initialise DIO Subdevice Structures */ - s = &dev->subdevices[1]; + s = dev->subdevices + 1; s->type = COMEDI_SUBD_DIO; s->subdev_flags = @@ -96,7 +96,7 @@ void i_ADDI_AttachPCI1710(struct comedi_device *dev) s->insn_write = i_APCI1710_InsnWriteDigitalIOChlOnOff; /* Allocate and Initialise Chrono Subdevice Structures */ - s = &dev->subdevices[2]; + s = dev->subdevices + 2; s->type = COMEDI_SUBD_CHRONO; s->subdev_flags = SDF_WRITEABLE | SDF_GROUND | SDF_COMMON; @@ -110,7 +110,7 @@ void i_ADDI_AttachPCI1710(struct comedi_device *dev) s->insn_bits = i_APCI1710_InsnBitsChronoDigitalIO; /* Allocate and Initialise PWM Subdevice Structures */ - s = &dev->subdevices[3]; + s = dev->subdevices + 3; s->type = COMEDI_SUBD_PWM; s->subdev_flags = SDF_WRITEABLE | SDF_READABLE | SDF_GROUND | SDF_COMMON; @@ -125,7 +125,7 @@ void i_ADDI_AttachPCI1710(struct comedi_device *dev) s->insn_bits = i_APCI1710_InsnBitsReadPWMInterrupt; /* Allocate and Initialise TTLIO Subdevice Structures */ - s = &dev->subdevices[4]; + s = dev->subdevices + 4; s->type = COMEDI_SUBD_TTLIO; s->subdev_flags = SDF_WRITEABLE | SDF_READABLE | SDF_GROUND | SDF_COMMON; @@ -139,7 +139,7 @@ void i_ADDI_AttachPCI1710(struct comedi_device *dev) s->insn_read = i_APCI1710_InsnReadTTLIOAllPortValue; /* Allocate and Initialise TOR Subdevice Structures */ - s = &dev->subdevices[5]; + s = dev->subdevices + 5; s->type = COMEDI_SUBD_TOR; s->subdev_flags = SDF_WRITEABLE | SDF_READABLE | SDF_GROUND | SDF_COMMON; @@ -154,7 +154,7 @@ void i_ADDI_AttachPCI1710(struct comedi_device *dev) s->insn_bits = i_APCI1710_InsnBitsGetTorCounterProgressStatusAndValue; /* Allocate and Initialise SSI Subdevice Structures */ - s = &dev->subdevices[6]; + s = dev->subdevices + 6; s->type = COMEDI_SUBD_SSI; s->subdev_flags = SDF_WRITEABLE | SDF_READABLE | SDF_GROUND | SDF_COMMON; @@ -167,7 +167,7 @@ void i_ADDI_AttachPCI1710(struct comedi_device *dev) s->insn_bits = i_APCI1710_InsnBitsSSIDigitalIO; /* Allocate and Initialise PULSEENCODER Subdevice Structures */ - s = &dev->subdevices[7]; + s = dev->subdevices + 7; s->type = COMEDI_SUBD_PULSEENCODER; s->subdev_flags = SDF_WRITEABLE | SDF_READABLE | SDF_GROUND | SDF_COMMON; @@ -181,7 +181,7 @@ void i_ADDI_AttachPCI1710(struct comedi_device *dev) s->insn_read = i_APCI1710_InsnReadInterruptPulseEncoder; /* Allocate and Initialise INCREMENTALCOUNTER Subdevice Structures */ - s = &dev->subdevices[8]; + s = dev->subdevices + 8; s->type = COMEDI_SUBD_INCREMENTALCOUNTER; s->subdev_flags = SDF_WRITEABLE | SDF_READABLE | SDF_GROUND | SDF_COMMON; diff --git a/trunk/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c b/trunk/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c index f406dfb2a677..ffe390c6da83 100644 --- a/trunk/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c +++ b/trunk/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c @@ -479,26 +479,57 @@ int i_APCI3120_CommandTestAnalogInput(struct comedi_device *dev, struct comedi_s struct comedi_cmd *cmd) { int err = 0; + int tmp; /* divisor1,divisor2; */ - /* Step 1 : check if triggers are trivially valid */ + /* step 1: make sure trigger sources are trivially valid */ - err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_EXT); - err |= cfc_check_trigger_src(&cmd->scan_begin_src, - TRIG_TIMER | TRIG_FOLLOW); - err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_TIMER); - err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT); - err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE); + tmp = cmd->start_src; + cmd->start_src &= TRIG_NOW | TRIG_EXT; + if (!cmd->start_src || tmp != cmd->start_src) + err++; + + tmp = cmd->scan_begin_src; + cmd->scan_begin_src &= TRIG_TIMER | TRIG_FOLLOW; + if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) + err++; + + tmp = cmd->convert_src; + cmd->convert_src &= TRIG_TIMER; + if (!cmd->convert_src || tmp != cmd->convert_src) + err++; + + tmp = cmd->scan_end_src; + cmd->scan_end_src &= TRIG_COUNT; + if (!cmd->scan_end_src || tmp != cmd->scan_end_src) + err++; + + tmp = cmd->stop_src; + cmd->stop_src &= TRIG_COUNT | TRIG_NONE; + if (!cmd->stop_src || tmp != cmd->stop_src) + err++; if (err) return 1; - /* Step 2a : make sure trigger sources are unique */ + /* step 2: make sure trigger sources are unique and mutually compatible */ - err |= cfc_check_trigger_is_unique(cmd->start_src); - err |= cfc_check_trigger_is_unique(cmd->scan_begin_src); - err |= cfc_check_trigger_is_unique(cmd->stop_src); + if (cmd->start_src != TRIG_NOW && cmd->start_src != TRIG_EXT) + err++; + + if (cmd->scan_begin_src != TRIG_TIMER && + cmd->scan_begin_src != TRIG_FOLLOW) + err++; + + if (cmd->convert_src != TRIG_TIMER) + err++; - /* Step 2b : and mutually compatible */ + if (cmd->scan_end_src != TRIG_COUNT) { + cmd->scan_end_src = TRIG_COUNT; + err++; + } + + if (cmd->stop_src != TRIG_NONE && cmd->stop_src != TRIG_COUNT) + err++; if (err) return 2; @@ -1420,7 +1451,7 @@ void v_APCI3120_Interrupt(int irq, void *d) unsigned short us_TmpValue; unsigned char b_DummyRead; - struct comedi_subdevice *s = &dev->subdevices[0]; + struct comedi_subdevice *s = dev->subdevices + 0; ui_Check = 1; int_daq = inw(dev->iobase + APCI3120_RD_STATUS) & 0xf000; /* get IRQ reasons */ @@ -1625,7 +1656,7 @@ void v_APCI3120_Interrupt(int irq, void *d) int i_APCI3120_InterruptHandleEos(struct comedi_device *dev) { int n_chan, i; - struct comedi_subdevice *s = &dev->subdevices[0]; + struct comedi_subdevice *s = dev->subdevices + 0; int err = 1; n_chan = devpriv->ui_AiNbrofChannels; @@ -1667,7 +1698,7 @@ int i_APCI3120_InterruptHandleEos(struct comedi_device *dev) void v_APCI3120_InterruptDma(int irq, void *d) { struct comedi_device *dev = d; - struct comedi_subdevice *s = &dev->subdevices[0]; + struct comedi_subdevice *s = dev->subdevices + 0; unsigned int next_dma_buf, samplesinbuf; unsigned long low_word, high_word, var; diff --git a/trunk/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c b/trunk/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c index 38ab49917d7e..f9545b064eaf 100644 --- a/trunk/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c +++ b/trunk/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c @@ -57,9 +57,12 @@ You should also find the complete GPL in the COPYING file accompanying this sour +----------------------------------------------------------------------------+ */ #include "hwdrv_apci3200.h" - +/* Begin JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values */ +#include "addi_amcc_S5920.h" /* #define PRINT_INFO */ +/* End JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values */ + /* BEGIN JK 06.07.04: Management of sevrals boards */ /* int i_CJCAvailable=1; @@ -87,12 +90,7 @@ You should also find the complete GPL in the COPYING file accompanying this sour struct str_BoardInfos s_BoardInfos[100]; /* 100 will be the max number of boards to be used */ /* END JK 06.07.04: Management of sevrals boards */ -#define AMCC_OP_REG_MCSR 0x3c -#define EEPROM_BUSY 0x80000000 -#define NVCMD_LOAD_LOW (0x4 << 5) /* nvRam load low command */ -#define NVCMD_LOAD_HIGH (0x5 << 5) /* nvRam load high command */ -#define NVCMD_BEGIN_READ (0x7 << 5) /* nvRam begin read command */ -#define NVCMD_BEGIN_WRITE (0x6 << 5) /* EEPROM begin write command */ +/* Begin JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values */ /*+----------------------------------------------------------------------------+*/ /*| Function Name : int i_AddiHeaderRW_ReadEeprom |*/ @@ -2560,6 +2558,7 @@ int i_APCI3200_CommandTestAnalogInput(struct comedi_device *dev, struct comedi_s { int err = 0; + int tmp; /* divisor1,divisor2; */ unsigned int ui_ConvertTime = 0; unsigned int ui_ConvertTimeBase = 0; unsigned int ui_DelayTime = 0; @@ -2570,32 +2569,41 @@ int i_APCI3200_CommandTestAnalogInput(struct comedi_device *dev, struct comedi_s int i_Cpt = 0; double d_ConversionTimeForAllChannels = 0.0; double d_SCANTimeNewUnit = 0.0; - - /* Step 1 : check if triggers are trivially valid */ - - err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_EXT); - err |= cfc_check_trigger_src(&cmd->scan_begin_src, - TRIG_TIMER | TRIG_FOLLOW); - err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_TIMER); - err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT); - err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE); - - if (s_BoardInfos[dev->minor].i_InterruptFlag == 0) - err |= -EINVAL; - + /* step 1: make sure trigger sources are trivially valid */ + + tmp = cmd->start_src; + cmd->start_src &= TRIG_NOW | TRIG_EXT; + if (!cmd->start_src || tmp != cmd->start_src) + err++; + tmp = cmd->scan_begin_src; + cmd->scan_begin_src &= TRIG_TIMER | TRIG_FOLLOW; + if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) + err++; + tmp = cmd->convert_src; + cmd->convert_src &= TRIG_TIMER; + if (!cmd->convert_src || tmp != cmd->convert_src) + err++; + tmp = cmd->scan_end_src; + cmd->scan_end_src &= TRIG_COUNT; + if (!cmd->scan_end_src || tmp != cmd->scan_end_src) + err++; + tmp = cmd->stop_src; + cmd->stop_src &= TRIG_COUNT | TRIG_NONE; + if (!cmd->stop_src || tmp != cmd->stop_src) + err++; + /* if(i_InterruptFlag==0) */ + if (s_BoardInfos[dev->minor].i_InterruptFlag == 0) { + err++; + /* printk("\nThe interrupt should be enabled\n"); */ + } if (err) { i_APCI3200_Reset(dev); return 1; } - /* Step 2a : make sure trigger sources are unique */ - - err |= cfc_check_trigger_is_unique(&cmd->start_src); - err |= cfc_check_trigger_is_unique(&cmd->scan_begin_src); - err |= cfc_check_trigger_is_unique(&cmd->stop_src); - - /* Step 2b : and mutually compatible */ - + if (cmd->start_src != TRIG_NOW && cmd->start_src != TRIG_EXT) { + err++; + } if (cmd->start_src == TRIG_EXT) { i_TriggerEdge = cmd->start_arg & 0xFFFF; i_Triggermode = cmd->start_arg >> 16; @@ -2609,6 +2617,21 @@ int i_APCI3200_CommandTestAnalogInput(struct comedi_device *dev, struct comedi_s } } + if (cmd->scan_begin_src != TRIG_TIMER && + cmd->scan_begin_src != TRIG_FOLLOW) + err++; + + if (cmd->convert_src != TRIG_TIMER) + err++; + + if (cmd->scan_end_src != TRIG_COUNT) { + cmd->scan_end_src = TRIG_COUNT; + err++; + } + + if (cmd->stop_src != TRIG_NONE && cmd->stop_src != TRIG_COUNT) + err++; + if (err) { i_APCI3200_Reset(dev); return 2; @@ -3472,7 +3495,7 @@ void v_APCI3200_Interrupt(int irq, void *d) int i_APCI3200_InterruptHandleEos(struct comedi_device *dev) { unsigned int ui_StatusRegister = 0; - struct comedi_subdevice *s = &dev->subdevices[0]; + struct comedi_subdevice *s = dev->subdevices + 0; /* BEGIN JK 18.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68 */ /* comedi_async *async = s->async; */ diff --git a/trunk/drivers/staging/comedi/drivers/addi_apci_all.c b/trunk/drivers/staging/comedi/drivers/addi_apci_all.c new file mode 100644 index 000000000000..aeb1b2688f3d --- /dev/null +++ b/trunk/drivers/staging/comedi/drivers/addi_apci_all.c @@ -0,0 +1,18 @@ +#define CONFIG_APCI_035 1 +#define CONFIG_APCI_1032 1 +#define CONFIG_APCI_1500 1 +#define CONFIG_APCI_1516 1 +#define CONFIG_APCI_1564 1 +#define CONFIG_APCI_16XX 1 +#define CONFIG_APCI_1710 1 +#define CONFIG_APCI_2016 1 +#define CONFIG_APCI_2032 1 +#define CONFIG_APCI_2200 1 +#define CONFIG_APCI_3001 1 +#define CONFIG_APCI_3120 1 +#define CONFIG_APCI_3200 1 +#define CONFIG_APCI_3300 1 +#define CONFIG_APCI_3501 1 +#define CONFIG_APCI_3XXX 1 + +#include "addi-data/addi_common.c" diff --git a/trunk/drivers/staging/comedi/drivers/adl_pci6208.c b/trunk/drivers/staging/comedi/drivers/adl_pci6208.c index 3492ce1156e0..3bec0f6e4a8c 100644 --- a/trunk/drivers/staging/comedi/drivers/adl_pci6208.c +++ b/trunk/drivers/staging/comedi/drivers/adl_pci6208.c @@ -27,14 +27,14 @@ */ /* Driver: adl_pci6208 -Description: ADLink PCI-6208/6216 Series Multi-channel Analog Output Cards -Devices: (ADLink) PCI-6208 [adl_pci6208] - (ADLink) PCI-6216 [adl_pci6216] +Description: ADLink PCI-6208A +Devices: [ADLink] PCI-6208A (adl_pci6208) Author: nsyeow Updated: Fri, 30 Jan 2004 14:44:27 +0800 Status: untested -Configuration Options: not applicable, uses PCI auto config +Configuration Options: + none References: - ni_660x.c @@ -44,12 +44,6 @@ Configuration Options: not applicable, uses PCI auto config #include "../comedidev.h" -/* - * ADLINK PCI Device ID's supported by this driver - */ -#define PCI_DEVICE_ID_PCI6208 0x6208 -#define PCI_DEVICE_ID_PCI6216 0x6216 - /* * PCI-6208/6216-GL register map */ @@ -62,7 +56,7 @@ Configuration Options: not applicable, uses PCI auto config #define PCI6208_DIO_DI_MASK (0xf0) #define PCI6208_DIO_DI_SHIFT (4) -#define PCI6208_MAX_AO_CHANNELS 16 +#define PCI6208_MAX_AO_CHANNELS 8 struct pci6208_board { const char *name; @@ -72,13 +66,9 @@ struct pci6208_board { static const struct pci6208_board pci6208_boards[] = { { - .name = "adl_pci6208", - .dev_id = PCI_DEVICE_ID_PCI6208, + .name = "pci6208a", + .dev_id = 0x6208, .ao_chans = 8, - }, { - .name = "adl_pci6216", - .dev_id = PCI_DEVICE_ID_PCI6216, - .ao_chans = 16, }, }; @@ -125,122 +115,141 @@ static int pci6208_ao_rinsn(struct comedi_device *dev, return insn->n; } -static int pci6208_di_insn_bits(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) -{ - unsigned int val; - - val = inw(dev->iobase + PCI6208_DIO); - val = (val & PCI6208_DIO_DI_MASK) >> PCI6208_DIO_DI_SHIFT; - - data[1] = val; - - return insn->n; -} - -static int pci6208_do_insn_bits(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) +static int pci6208_dio_insn_bits(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) { - unsigned int mask = data[0]; + unsigned int mask = data[0] & PCI6208_DIO_DO_MASK; unsigned int bits = data[1]; if (mask) { s->state &= ~mask; - s->state |= (bits & mask); + s->state |= bits & mask; outw(s->state, dev->iobase + PCI6208_DIO); } + s->state = inw(dev->iobase + PCI6208_DIO); data[1] = s->state; return insn->n; } -static const void *pci6208_find_boardinfo(struct comedi_device *dev, - struct pci_dev *pcidev) +static int pci6208_dio_insn_config(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) +{ + int chan = CR_CHAN(insn->chanspec); + unsigned int mask = 1 << chan; + + switch (data[0]) { + case INSN_CONFIG_DIO_QUERY: + data[1] = (s->io_bits & mask) ? COMEDI_OUTPUT : COMEDI_INPUT; + break; + default: + return -EINVAL; + } + + return insn->n; +} + +static struct pci_dev *pci6208_find_device(struct comedi_device *dev, + struct comedi_devconfig *it) { - const struct pci6208_board *boardinfo; + const struct pci6208_board *thisboard; + struct pci_dev *pci_dev = NULL; + int bus = it->options[0]; + int slot = it->options[1]; int i; - for (i = 0; i < ARRAY_SIZE(pci6208_boards); i++) { - boardinfo = &pci6208_boards[i]; - if (boardinfo->dev_id == pcidev->device) - return boardinfo; + for_each_pci_dev(pci_dev) { + if (pci_dev->vendor != PCI_VENDOR_ID_ADLINK) + continue; + for (i = 0; i < ARRAY_SIZE(pci6208_boards); i++) { + thisboard = &pci6208_boards[i]; + if (thisboard->dev_id != pci_dev->device) + continue; + /* was a particular bus/slot requested? */ + if (bus || slot) { + /* are we on the wrong bus/slot? */ + if (pci_dev->bus->number != bus || + PCI_SLOT(pci_dev->devfn) != slot) + continue; + } + dev_dbg(dev->class_dev, + "Found %s on bus %d, slot, %d, irq=%d\n", + thisboard->name, + pci_dev->bus->number, + PCI_SLOT(pci_dev->devfn), + pci_dev->irq); + dev->board_ptr = thisboard; + return pci_dev; + } } + dev_err(dev->class_dev, + "No supported board found! (req. bus %d, slot %d)\n", + bus, slot); return NULL; } -static int pci6208_attach_pci(struct comedi_device *dev, - struct pci_dev *pcidev) +static int pci6208_attach(struct comedi_device *dev, + struct comedi_devconfig *it) { - const struct pci6208_board *boardinfo; + const struct pci6208_board *thisboard; struct pci6208_private *devpriv; + struct pci_dev *pcidev; struct comedi_subdevice *s; - unsigned int val; int ret; - comedi_set_hw_dev(dev, &pcidev->dev); - - boardinfo = pci6208_find_boardinfo(dev, pcidev); - if (!boardinfo) - return -ENODEV; - dev->board_ptr = boardinfo; - dev->board_name = boardinfo->name; - ret = alloc_private(dev, sizeof(*devpriv)); if (ret < 0) return ret; devpriv = dev->private; - ret = comedi_pci_enable(pcidev, dev->board_name); - if (ret) + pcidev = pci6208_find_device(dev, it); + if (!pcidev) + return -EIO; + comedi_set_hw_dev(dev, &pcidev->dev); + thisboard = comedi_board(dev); + + dev->board_name = thisboard->name; + + ret = comedi_pci_enable(pcidev, dev->driver->driver_name); + if (ret) { + dev_err(dev->class_dev, + "Failed to enable PCI device and request regions\n"); return ret; + } dev->iobase = pci_resource_start(pcidev, 2); - ret = comedi_alloc_subdevices(dev, 3); + ret = comedi_alloc_subdevices(dev, 2); if (ret) return ret; - s = &dev->subdevices[0]; + s = dev->subdevices + 0; /* analog output subdevice */ s->type = COMEDI_SUBD_AO; s->subdev_flags = SDF_WRITABLE; - s->n_chan = boardinfo->ao_chans; + s->n_chan = thisboard->ao_chans; s->maxdata = 0xffff; s->range_table = &range_bipolar10; s->insn_write = pci6208_ao_winsn; s->insn_read = pci6208_ao_rinsn; - s = &dev->subdevices[1]; - /* digital input subdevice */ - s->type = COMEDI_SUBD_DI; - s->subdev_flags = SDF_READABLE; - s->n_chan = 4; + s = dev->subdevices + 1; + /* digital i/o subdevice */ + s->type = COMEDI_SUBD_DIO; + s->subdev_flags = SDF_READABLE | SDF_WRITABLE; + s->n_chan = 8; s->maxdata = 1; s->range_table = &range_digital; - s->insn_bits = pci6208_di_insn_bits; + s->insn_bits = pci6208_dio_insn_bits; + s->insn_config = pci6208_dio_insn_config; - s = &dev->subdevices[2]; - /* digital output subdevice */ - s->type = COMEDI_SUBD_DO; - s->subdev_flags = SDF_WRITABLE; - s->n_chan = 4; - s->maxdata = 1; - s->range_table = &range_digital; - s->insn_bits = pci6208_do_insn_bits; - - /* - * Get the read back signals from the digital outputs - * and save it as the initial state for the subdevice. - */ - val = inw(dev->iobase + PCI6208_DIO); - val = (val & PCI6208_DIO_DO_MASK) >> PCI6208_DIO_DO_SHIFT; - s->state = val; s->io_bits = 0x0f; + s->state = inw(dev->iobase + PCI6208_DIO); dev_info(dev->class_dev, "%s: %s, I/O base=0x%04lx\n", dev->driver->driver_name, dev->board_name, dev->iobase); @@ -255,13 +264,14 @@ static void pci6208_detach(struct comedi_device *dev) if (pcidev) { if (dev->iobase) comedi_pci_disable(pcidev); + pci_dev_put(pcidev); } } static struct comedi_driver adl_pci6208_driver = { .driver_name = "adl_pci6208", .module = THIS_MODULE, - .attach_pci = pci6208_attach_pci, + .attach = pci6208_attach, .detach = pci6208_detach, }; @@ -277,8 +287,7 @@ static void __devexit adl_pci6208_pci_remove(struct pci_dev *dev) } static DEFINE_PCI_DEVICE_TABLE(adl_pci6208_pci_table) = { - { PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI_DEVICE_ID_PCI6208) }, - { PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI_DEVICE_ID_PCI6216) }, + { PCI_DEVICE(PCI_VENDOR_ID_ADLINK, 0x6208) }, { 0 } }; MODULE_DEVICE_TABLE(pci, adl_pci6208_pci_table); diff --git a/trunk/drivers/staging/comedi/drivers/adl_pci7230.c b/trunk/drivers/staging/comedi/drivers/adl_pci7230.c new file mode 100644 index 000000000000..7df4c960d5e4 --- /dev/null +++ b/trunk/drivers/staging/comedi/drivers/adl_pci7230.c @@ -0,0 +1,190 @@ +/* + comedi/drivers/adl_pci7230.c + + Hardware comedi driver fot PCI7230 Adlink card + Copyright (C) 2010 David Fernandez + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ +/* +Driver: adl_pci7230 +Description: Driver for the Adlink PCI-7230 32 ch. isolated digital io board +Devices: [ADLink] PCI-7230 (adl_pci7230) +Author: David Fernandez +Status: experimental +Updated: Mon, 14 Apr 2008 15:08:14 +0100 + +Configuration Options: + [0] - PCI bus of device (optional) + [1] - PCI slot of device (optional) + If bus/slot is not specified, the first supported + PCI device found will be used. +*/ + +#include "../comedidev.h" +#include + +#define PCI7230_DI 0x00 +#define PCI7230_DO 0x00 + +#define PCI_DEVICE_ID_PCI7230 0x7230 + +static int adl_pci7230_do_insn_bits(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) +{ + if (data[0]) { + s->state &= ~data[0]; + s->state |= (data[0] & data[1]); + + outl((s->state << 16) & 0xffffffff, dev->iobase + PCI7230_DO); + } + + return insn->n; +} + +static int adl_pci7230_di_insn_bits(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) +{ + data[1] = inl(dev->iobase + PCI7230_DI) & 0xffffffff; + + return insn->n; +} + +static struct pci_dev *adl_pci7230_find_pci(struct comedi_device *dev, + struct comedi_devconfig *it) +{ + struct pci_dev *pcidev = NULL; + int bus = it->options[0]; + int slot = it->options[1]; + + for_each_pci_dev(pcidev) { + if (pcidev->vendor != PCI_VENDOR_ID_ADLINK || + pcidev->device != PCI_DEVICE_ID_PCI7230) + continue; + if (bus || slot) { + /* requested particular bus/slot */ + if (pcidev->bus->number != bus || + PCI_SLOT(pcidev->devfn) != slot) + continue; + } + return pcidev; + } + printk(KERN_ERR "comedi%d: no supported board found! (req. bus/slot : %d/%d)\n", + dev->minor, bus, slot); + return NULL; +} + +static int adl_pci7230_attach(struct comedi_device *dev, + struct comedi_devconfig *it) +{ + struct comedi_subdevice *s; + struct pci_dev *pcidev; + int ret; + + printk(KERN_INFO "comedi%d: adl_pci7230\n", dev->minor); + + dev->board_name = "pci7230"; + + ret = comedi_alloc_subdevices(dev, 2); + if (ret) + return ret; + + pcidev = adl_pci7230_find_pci(dev, it); + if (!pcidev) + return -EIO; + comedi_set_hw_dev(dev, &pcidev->dev); + + if (comedi_pci_enable(pcidev, "adl_pci7230") < 0) { + printk(KERN_ERR "comedi%d: Failed to enable PCI device and request regions\n", + dev->minor); + return -EIO; + } + dev->iobase = pci_resource_start(pcidev, 2); + printk(KERN_DEBUG "comedi: base addr %4lx\n", dev->iobase); + + s = dev->subdevices + 0; + /* Isolated do */ + s->type = COMEDI_SUBD_DO; + s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_COMMON; + s->n_chan = 16; + s->maxdata = 1; + s->range_table = &range_digital; + s->insn_bits = adl_pci7230_do_insn_bits; + + s = dev->subdevices + 1; + /* Isolated di */ + s->type = COMEDI_SUBD_DI; + s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_COMMON; + s->n_chan = 16; + s->maxdata = 1; + s->range_table = &range_digital; + s->insn_bits = adl_pci7230_di_insn_bits; + + printk(KERN_DEBUG "comedi: attached\n"); + + return 1; +} + +static void adl_pci7230_detach(struct comedi_device *dev) +{ + struct pci_dev *pcidev = comedi_to_pci_dev(dev); + + if (pcidev) { + if (dev->iobase) + comedi_pci_disable(pcidev); + pci_dev_put(pcidev); + } +} + +static struct comedi_driver adl_pci7230_driver = { + .driver_name = "adl_pci7230", + .module = THIS_MODULE, + .attach = adl_pci7230_attach, + .detach = adl_pci7230_detach, +}; + +static int __devinit adl_pci7230_pci_probe(struct pci_dev *dev, + const struct pci_device_id *ent) +{ + return comedi_pci_auto_config(dev, &adl_pci7230_driver); +} + +static void __devexit adl_pci7230_pci_remove(struct pci_dev *dev) +{ + comedi_pci_auto_unconfig(dev); +} + +static DEFINE_PCI_DEVICE_TABLE(adl_pci7230_pci_table) = { + { PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI_DEVICE_ID_PCI7230) }, + { 0 } +}; +MODULE_DEVICE_TABLE(pci, adl_pci7230_pci_table); + +static struct pci_driver adl_pci7230_pci_driver = { + .name = "adl_pci7230", + .id_table = adl_pci7230_pci_table, + .probe = adl_pci7230_pci_probe, + .remove = __devexit_p(adl_pci7230_pci_remove), +}; +module_comedi_pci_driver(adl_pci7230_driver, adl_pci7230_pci_driver); + +MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/staging/comedi/drivers/adl_pci7296.c b/trunk/drivers/staging/comedi/drivers/adl_pci7296.c new file mode 100644 index 000000000000..19b47af9c10e --- /dev/null +++ b/trunk/drivers/staging/comedi/drivers/adl_pci7296.c @@ -0,0 +1,183 @@ +/* + comedi/drivers/adl_pci7296.c + + COMEDI - Linux Control and Measurement Device Interface + Copyright (C) 2000 David A. Schleef + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ +/* +Driver: adl_pci7296 +Description: Driver for the Adlink PCI-7296 96 ch. digital io board +Devices: [ADLink] PCI-7296 (adl_pci7296) +Author: Jon Grierson +Updated: Mon, 14 Apr 2008 15:05:56 +0100 +Status: testing + +Configuration Options: + [0] - PCI bus of device (optional) + [1] - PCI slot of device (optional) + If bus/slot is not specified, the first supported + PCI device found will be used. +*/ + +#include "../comedidev.h" +#include + +#include "8255.h" +/* #include "8253.h" */ + +#define PORT1A 0 +#define PORT2A 4 +#define PORT3A 8 +#define PORT4A 12 + +#define PCI_DEVICE_ID_PCI7296 0x7296 + +static struct pci_dev *adl_pci7296_find_pci(struct comedi_device *dev, + struct comedi_devconfig *it) +{ + struct pci_dev *pcidev = NULL; + int bus = it->options[0]; + int slot = it->options[1]; + + for_each_pci_dev(pcidev) { + if (pcidev->vendor != PCI_VENDOR_ID_ADLINK || + pcidev->device != PCI_DEVICE_ID_PCI7296) + continue; + if (bus || slot) { + /* requested particular bus/slot */ + if (pcidev->bus->number != bus || + PCI_SLOT(pcidev->devfn) != slot) + continue; + } + return pcidev; + } + printk(KERN_ERR + "comedi%d: no supported board found! (req. bus/slot : %d/%d)\n", + dev->minor, bus, slot); + return NULL; +} + +static int adl_pci7296_attach(struct comedi_device *dev, + struct comedi_devconfig *it) +{ + struct pci_dev *pcidev; + struct comedi_subdevice *s; + int ret; + + printk(KERN_INFO "comedi%d: attach adl_pci7432\n", dev->minor); + + dev->board_name = "pci7432"; + + ret = comedi_alloc_subdevices(dev, 4); + if (ret) + return ret; + + pcidev = adl_pci7296_find_pci(dev, it); + if (!pcidev) + return -EIO; + comedi_set_hw_dev(dev, &pcidev->dev); + + if (comedi_pci_enable(pcidev, "adl_pci7296") < 0) { + printk(KERN_ERR + "comedi%d: Failed to enable PCI device and request regions\n", + dev->minor); + return -EIO; + } + + dev->iobase = pci_resource_start(pcidev, 2); + printk(KERN_INFO "comedi: base addr %4lx\n", dev->iobase); + + /* four 8255 digital io subdevices */ + s = dev->subdevices + 0; + subdev_8255_init(dev, s, NULL, (unsigned long)(dev->iobase)); + + s = dev->subdevices + 1; + ret = subdev_8255_init(dev, s, NULL, + (unsigned long)(dev->iobase + PORT2A)); + if (ret < 0) + return ret; + + s = dev->subdevices + 2; + ret = subdev_8255_init(dev, s, NULL, + (unsigned long)(dev->iobase + PORT3A)); + if (ret < 0) + return ret; + + s = dev->subdevices + 3; + ret = subdev_8255_init(dev, s, NULL, + (unsigned long)(dev->iobase + PORT4A)); + if (ret < 0) + return ret; + + printk(KERN_DEBUG "comedi%d: adl_pci7432 attached\n", dev->minor); + + return 0; +} + +static void adl_pci7296_detach(struct comedi_device *dev) +{ + struct pci_dev *pcidev = comedi_to_pci_dev(dev); + + if (pcidev) { + if (dev->iobase) + comedi_pci_disable(pcidev); + pci_dev_put(pcidev); + } + if (dev->subdevices) { + subdev_8255_cleanup(dev, dev->subdevices + 0); + subdev_8255_cleanup(dev, dev->subdevices + 1); + subdev_8255_cleanup(dev, dev->subdevices + 2); + subdev_8255_cleanup(dev, dev->subdevices + 3); + } +} + +static struct comedi_driver adl_pci7296_driver = { + .driver_name = "adl_pci7296", + .module = THIS_MODULE, + .attach = adl_pci7296_attach, + .detach = adl_pci7296_detach, +}; + +static int __devinit adl_pci7296_pci_probe(struct pci_dev *dev, + const struct pci_device_id *ent) +{ + return comedi_pci_auto_config(dev, &adl_pci7296_driver); +} + +static void __devexit adl_pci7296_pci_remove(struct pci_dev *dev) +{ + comedi_pci_auto_unconfig(dev); +} + +static DEFINE_PCI_DEVICE_TABLE(adl_pci7296_pci_table) = { + { PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI_DEVICE_ID_PCI7296) }, + { 0 } +}; +MODULE_DEVICE_TABLE(pci, adl_pci7296_pci_table); + +static struct pci_driver adl_pci7296_pci_driver = { + .name = "adl_pci7296", + .id_table = adl_pci7296_pci_table, + .probe = adl_pci7296_pci_probe, + .remove = __devexit_p(adl_pci7296_pci_remove), +}; +module_comedi_pci_driver(adl_pci7296_driver, adl_pci7296_pci_driver); + +MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/staging/comedi/drivers/adl_pci7432.c b/trunk/drivers/staging/comedi/drivers/adl_pci7432.c new file mode 100644 index 000000000000..6b8d9408e3bc --- /dev/null +++ b/trunk/drivers/staging/comedi/drivers/adl_pci7432.c @@ -0,0 +1,200 @@ +/* + comedi/drivers/adl_pci7432.c + + Hardware comedi driver fot PCI7432 Adlink card + Copyright (C) 2004 Michel Lachine + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ +/* +Driver: adl_pci7432 +Description: Driver for the Adlink PCI-7432 64 ch. isolated digital io board +Devices: [ADLink] PCI-7432 (adl_pci7432) +Author: Michel Lachaine +Status: experimental +Updated: Mon, 14 Apr 2008 15:08:14 +0100 + +Configuration Options: + [0] - PCI bus of device (optional) + [1] - PCI slot of device (optional) + If bus/slot is not specified, the first supported + PCI device found will be used. +*/ + +#include "../comedidev.h" +#include + +#define PCI7432_DI 0x00 +#define PCI7432_DO 0x00 + +#define PCI_DEVICE_ID_PCI7432 0x7432 + +static int adl_pci7432_do_insn_bits(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) +{ + printk(KERN_DEBUG "comedi: pci7432_do_insn_bits called\n"); + printk(KERN_DEBUG "comedi: data0: %8x data1: %8x\n", data[0], data[1]); + + if (data[0]) { + s->state &= ~data[0]; + s->state |= (data[0] & data[1]); + + printk(KERN_DEBUG "comedi: out: %8x on iobase %4lx\n", s->state, + dev->iobase + PCI7432_DO); + outl(s->state & 0xffffffff, dev->iobase + PCI7432_DO); + } + return insn->n; +} + +static int adl_pci7432_di_insn_bits(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) +{ + printk(KERN_DEBUG "comedi: pci7432_di_insn_bits called\n"); + printk(KERN_DEBUG "comedi: data0: %8x data1: %8x\n", data[0], data[1]); + + data[1] = inl(dev->iobase + PCI7432_DI) & 0xffffffff; + printk(KERN_DEBUG "comedi: data1 %8x\n", data[1]); + + return insn->n; +} + +static struct pci_dev *adl_pci7432_find_pci(struct comedi_device *dev, + struct comedi_devconfig *it) +{ + struct pci_dev *pcidev = NULL; + int bus = it->options[0]; + int slot = it->options[1]; + + for_each_pci_dev(pcidev) { + if (pcidev->vendor != PCI_VENDOR_ID_ADLINK || + pcidev->device != PCI_DEVICE_ID_PCI7432) + continue; + if (bus || slot) { + /* requested particular bus/slot */ + if (pcidev->bus->number != bus || + PCI_SLOT(pcidev->devfn) != slot) + continue; + } + return pcidev; + } + printk(KERN_ERR + "comedi%d: no supported board found! (req. bus/slot : %d/%d)\n", + dev->minor, bus, slot); + return NULL; +} + +static int adl_pci7432_attach(struct comedi_device *dev, + struct comedi_devconfig *it) +{ + struct pci_dev *pcidev; + struct comedi_subdevice *s; + int ret; + + printk(KERN_INFO "comedi%d: attach adl_pci7432\n", dev->minor); + + dev->board_name = "pci7432"; + + ret = comedi_alloc_subdevices(dev, 2); + if (ret) + return ret; + + pcidev = adl_pci7432_find_pci(dev, it); + if (!pcidev) + return -EIO; + comedi_set_hw_dev(dev, &pcidev->dev); + + if (comedi_pci_enable(pcidev, "adl_pci7432") < 0) { + printk(KERN_ERR "comedi%d: Failed to enable PCI device and request regions\n", + dev->minor); + return -EIO; + } + dev->iobase = pci_resource_start(pcidev, 2); + printk(KERN_INFO "comedi: base addr %4lx\n", dev->iobase); + + s = dev->subdevices + 0; + s->type = COMEDI_SUBD_DI; + s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_COMMON; + s->n_chan = 32; + s->maxdata = 1; + s->len_chanlist = 32; + s->io_bits = 0x00000000; + s->range_table = &range_digital; + s->insn_bits = adl_pci7432_di_insn_bits; + + s = dev->subdevices + 1; + s->type = COMEDI_SUBD_DO; + s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_COMMON; + s->n_chan = 32; + s->maxdata = 1; + s->len_chanlist = 32; + s->io_bits = 0xffffffff; + s->range_table = &range_digital; + s->insn_bits = adl_pci7432_do_insn_bits; + + printk(KERN_DEBUG "comedi%d: adl_pci7432 attached\n", dev->minor); + return 0; +} + +static void adl_pci7432_detach(struct comedi_device *dev) +{ + struct pci_dev *pcidev = comedi_to_pci_dev(dev); + + if (pcidev) { + if (dev->iobase) + comedi_pci_disable(pcidev); + pci_dev_put(pcidev); + } +} + +static struct comedi_driver adl_pci7432_driver = { + .driver_name = "adl_pci7432", + .module = THIS_MODULE, + .attach = adl_pci7432_attach, + .detach = adl_pci7432_detach, +}; + +static int __devinit adl_pci7432_pci_probe(struct pci_dev *dev, + const struct pci_device_id *ent) +{ + return comedi_pci_auto_config(dev, &adl_pci7432_driver); +} + +static void __devexit adl_pci7432_pci_remove(struct pci_dev *dev) +{ + comedi_pci_auto_unconfig(dev); +} + +static DEFINE_PCI_DEVICE_TABLE(adl_pci7432_pci_table) = { + { PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI_DEVICE_ID_PCI7432) }, + { 0 } +}; +MODULE_DEVICE_TABLE(pci, adl_pci7432_pci_table); + +static struct pci_driver adl_pci7432_pci_driver = { + .name = "adl_pci7432", + .id_table = adl_pci7432_pci_table, + .probe = adl_pci7432_pci_probe, + .remove = __devexit_p(adl_pci7432_pci_remove), +}; +module_comedi_pci_driver(adl_pci7432_driver, adl_pci7432_pci_driver); + +MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/staging/comedi/drivers/adl_pci7x3x.c b/trunk/drivers/staging/comedi/drivers/adl_pci7x3x.c deleted file mode 100644 index 599714e978b5..000000000000 --- a/trunk/drivers/staging/comedi/drivers/adl_pci7x3x.c +++ /dev/null @@ -1,332 +0,0 @@ -/* - * COMEDI driver for the ADLINK PCI-723x/743x series boards. - * Copyright (C) 2012 H Hartley Sweeten - * - * Based on the adl_pci7230 driver written by: - * David Fernandez - * and the adl_pci7432 driver written by: - * Michel Lachaine - * - * COMEDI - Linux Control and Measurement Device Interface - * Copyright (C) 2000 David A. Schleef - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/* -Driver: adl_pci7x3x -Description: 32/64-Channel Isolated Digital I/O Boards -Devices: (ADLink) PCI-7230 [adl_pci7230] - 16 input / 16 output - (ADLink) PCI-7233 [adl_pci7233] - 32 input - (ADLink) PCI-7234 [adl_pci7234] - 32 output - (ADLink) PCI-7432 [adl_pci7432] - 32 input / 32 output - (ADLink) PCI-7433 [adl_pci7433] - 64 input - (ADLink) PCI-7434 [adl_pci7434] - 64 output -Author: H Hartley Sweeten -Updated: Thu, 02 Aug 2012 14:27:46 -0700 -Status: untested - -This driver only attaches using the PCI PnP auto config support -in the comedi core. The module parameter 'comedi_autoconfig' -must be 1 (default) to enable this feature. The COMEDI_DEVCONFIG -ioctl, used by the comedi_config utility, is not supported by -this driver. - -The PCI-7230, PCI-7432 and PCI-7433 boards also support external -interrupt signals on digital input channels 0 and 1. The PCI-7233 -has dual-interrupt sources for change-of-state (COS) on any 16 -digital input channels of LSB and for COS on any 16 digital input -lines of MSB. Interrupts are not currently supported by this -driver. - -Configuration Options: not applicable -*/ - -#include "../comedidev.h" - -/* - * PCI Device ID's supported by this driver - */ -#define PCI_DEVICE_ID_PCI7230 0x7230 -#define PCI_DEVICE_ID_PCI7233 0x7233 -#define PCI_DEVICE_ID_PCI7234 0x7234 -#define PCI_DEVICE_ID_PCI7432 0x7432 -#define PCI_DEVICE_ID_PCI7433 0x7433 -#define PCI_DEVICE_ID_PCI7434 0x7434 - -/* - * Register I/O map (32-bit access only) - */ -#define PCI7X3X_DIO_REG 0x00 -#define PCI743X_DIO_REG 0x04 - -struct adl_pci7x3x_boardinfo { - const char *name; - unsigned short device; - int nsubdevs; - int di_nchan; - int do_nchan; -}; - -static const struct adl_pci7x3x_boardinfo adl_pci7x3x_boards[] = { - { - .name = "adl_pci7230", - .device = PCI_DEVICE_ID_PCI7230, - .nsubdevs = 2, - .di_nchan = 16, - .do_nchan = 16, - }, { - .name = "adl_pci7233", - .device = PCI_DEVICE_ID_PCI7233, - .nsubdevs = 1, - .di_nchan = 32, - }, { - .name = "adl_pci7234", - .device = PCI_DEVICE_ID_PCI7234, - .nsubdevs = 1, - .do_nchan = 32, - }, { - .name = "adl_pci7432", - .device = PCI_DEVICE_ID_PCI7432, - .nsubdevs = 2, - .di_nchan = 32, - .do_nchan = 32, - }, { - .name = "adl_pci7433", - .device = PCI_DEVICE_ID_PCI7433, - .nsubdevs = 2, - .di_nchan = 64, - }, { - .name = "adl_pci7434", - .device = PCI_DEVICE_ID_PCI7434, - .nsubdevs = 2, - .do_nchan = 64, - } -}; - -static int adl_pci7x3x_do_insn_bits(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) -{ - unsigned long reg = (unsigned long)s->private; - unsigned int mask = data[0]; - unsigned int bits = data[1]; - - if (mask) { - s->state &= ~mask; - s->state |= (bits & mask); - - outl(s->state, dev->iobase + reg); - } - - /* - * NOTE: The output register is not readable. - * This returned state will not be correct until all the - * outputs have been updated. - */ - data[1] = s->state; - - return insn->n; -} - -static int adl_pci7x3x_di_insn_bits(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) -{ - unsigned long reg = (unsigned long)s->private; - - data[1] = inl(dev->iobase + reg); - - return insn->n; -} - -static const void *adl_pci7x3x_find_boardinfo(struct comedi_device *dev, - struct pci_dev *pcidev) -{ - const struct adl_pci7x3x_boardinfo *board; - int i; - - for (i = 0; i < ARRAY_SIZE(adl_pci7x3x_boards); i++) { - board = &adl_pci7x3x_boards[i]; - if (pcidev->device == board->device) - return board; - } - return NULL; -} - -static int adl_pci7x3x_attach_pci(struct comedi_device *dev, - struct pci_dev *pcidev) -{ - const struct adl_pci7x3x_boardinfo *board; - struct comedi_subdevice *s; - int subdev; - int nchan; - int ret; - - comedi_set_hw_dev(dev, &pcidev->dev); - - board = adl_pci7x3x_find_boardinfo(dev, pcidev); - if (!board) - return -ENODEV; - dev->board_ptr = board; - dev->board_name = board->name; - - ret = comedi_pci_enable(pcidev, dev->board_name); - if (ret) - return ret; - dev->iobase = pci_resource_start(pcidev, 2); - - /* - * One or two subdevices are setup by this driver depending on - * the number of digital inputs and/or outputs provided by the - * board. Each subdevice has a maximum of 32 channels. - * - * PCI-7230 - 2 subdevices: 0 - 16 input, 1 - 16 output - * PCI-7233 - 1 subdevice: 0 - 32 input - * PCI-7234 - 1 subdevice: 0 - 32 output - * PCI-7432 - 2 subdevices: 0 - 32 input, 1 - 32 output - * PCI-7433 - 2 subdevices: 0 - 32 input, 1 - 32 input - * PCI-7434 - 2 subdevices: 0 - 32 output, 1 - 32 output - */ - ret = comedi_alloc_subdevices(dev, board->nsubdevs); - if (ret) - return ret; - - subdev = 0; - - if (board->di_nchan) { - nchan = min(board->di_nchan, 32); - - s = &dev->subdevices[subdev]; - /* Isolated digital inputs 0 to 15/31 */ - s->type = COMEDI_SUBD_DI; - s->subdev_flags = SDF_READABLE; - s->n_chan = nchan; - s->maxdata = 1; - s->insn_bits = adl_pci7x3x_di_insn_bits; - s->range_table = &range_digital; - - s->private = (void *)PCI7X3X_DIO_REG; - - subdev++; - - nchan = board->di_nchan - nchan; - if (nchan) { - s = &dev->subdevices[subdev]; - /* Isolated digital inputs 32 to 63 */ - s->type = COMEDI_SUBD_DI; - s->subdev_flags = SDF_READABLE; - s->n_chan = nchan; - s->maxdata = 1; - s->insn_bits = adl_pci7x3x_di_insn_bits; - s->range_table = &range_digital; - - s->private = (void *)PCI743X_DIO_REG; - - subdev++; - } - } - - if (board->do_nchan) { - nchan = min(board->do_nchan, 32); - - s = &dev->subdevices[subdev]; - /* Isolated digital outputs 0 to 15/31 */ - s->type = COMEDI_SUBD_DO; - s->subdev_flags = SDF_WRITABLE; - s->n_chan = nchan; - s->maxdata = 1; - s->insn_bits = adl_pci7x3x_do_insn_bits; - s->range_table = &range_digital; - - s->private = (void *)PCI7X3X_DIO_REG; - - subdev++; - - nchan = board->do_nchan - nchan; - if (nchan) { - s = &dev->subdevices[subdev]; - /* Isolated digital outputs 32 to 63 */ - s->type = COMEDI_SUBD_DO; - s->subdev_flags = SDF_WRITABLE; - s->n_chan = nchan; - s->maxdata = 1; - s->insn_bits = adl_pci7x3x_do_insn_bits; - s->range_table = &range_digital; - - s->private = (void *)PCI743X_DIO_REG; - - subdev++; - } - } - - dev_info(dev->class_dev, "%s attached (%d inputs/%d outputs)\n", - dev->board_name, board->di_nchan, board->do_nchan); - - return 0; -} - -static void adl_pci7x3x_detach(struct comedi_device *dev) -{ - struct pci_dev *pcidev = comedi_to_pci_dev(dev); - - if (pcidev) { - if (dev->iobase) - comedi_pci_disable(pcidev); - } -} - -static struct comedi_driver adl_pci7x3x_driver = { - .driver_name = "adl_pci7x3x", - .module = THIS_MODULE, - .attach_pci = adl_pci7x3x_attach_pci, - .detach = adl_pci7x3x_detach, -}; - -static int __devinit adl_pci7x3x_pci_probe(struct pci_dev *dev, - const struct pci_device_id *ent) -{ - return comedi_pci_auto_config(dev, &adl_pci7x3x_driver); -} - -static void __devexit adl_pci7x3x_pci_remove(struct pci_dev *dev) -{ - comedi_pci_auto_unconfig(dev); -} - -static DEFINE_PCI_DEVICE_TABLE(adl_pci7x3x_pci_table) = { - { PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI_DEVICE_ID_PCI7230) }, - { PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI_DEVICE_ID_PCI7233) }, - { PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI_DEVICE_ID_PCI7234) }, - { PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI_DEVICE_ID_PCI7432) }, - { PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI_DEVICE_ID_PCI7433) }, - { PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI_DEVICE_ID_PCI7434) }, - { 0 } -}; -MODULE_DEVICE_TABLE(pci, adl_pci7x3x_pci_table); - -static struct pci_driver adl_pci7x3x_pci_driver = { - .name = "adl_pci7x3x", - .id_table = adl_pci7x3x_pci_table, - .probe = adl_pci7x3x_pci_probe, - .remove = __devexit_p(adl_pci7x3x_pci_remove), -}; -module_comedi_pci_driver(adl_pci7x3x_driver, adl_pci7x3x_pci_driver); - -MODULE_DESCRIPTION("ADLINK PCI-723x/743x Isolated Digital I/O boards"); -MODULE_AUTHOR("H Hartley Sweeten "); -MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/staging/comedi/drivers/adl_pci8164.c b/trunk/drivers/staging/comedi/drivers/adl_pci8164.c index 05e06e7ba9f7..247ef00a7c6c 100644 --- a/trunk/drivers/staging/comedi/drivers/adl_pci8164.c +++ b/trunk/drivers/staging/comedi/drivers/adl_pci8164.c @@ -27,7 +27,11 @@ Author: Michel Lachaine Status: experimental Updated: Mon, 14 Apr 2008 15:10:32 +0100 -Configuration Options: not applicable, uses PCI auto config +Configuration Options: + [0] - PCI bus of device (optional) + [1] - PCI slot of device (optional) + If bus/slot is not specified, the first supported + PCI device found will be used. */ #include "../comedidev.h" @@ -212,26 +216,61 @@ static int adl_pci8164_insn_write_buf1(struct comedi_device *dev, return 2; } -static int adl_pci8164_attach_pci(struct comedi_device *dev, - struct pci_dev *pcidev) +static struct pci_dev *adl_pci8164_find_pci(struct comedi_device *dev, + struct comedi_devconfig *it) { + struct pci_dev *pcidev = NULL; + int bus = it->options[0]; + int slot = it->options[1]; + + for_each_pci_dev(pcidev) { + if (pcidev->vendor != PCI_VENDOR_ID_ADLINK || + pcidev->device != PCI_DEVICE_ID_PCI8164) + continue; + if (bus || slot) { + /* requested particular bus/slot */ + if (pcidev->bus->number != bus || + PCI_SLOT(pcidev->devfn) != slot) + continue; + } + return pcidev; + } + printk(KERN_ERR + "comedi%d: no supported board found! (req. bus/slot : %d/%d)\n", + dev->minor, bus, slot); + return NULL; +} + +static int adl_pci8164_attach(struct comedi_device *dev, + struct comedi_devconfig *it) +{ + struct pci_dev *pcidev; struct comedi_subdevice *s; int ret; - comedi_set_hw_dev(dev, &pcidev->dev); + printk(KERN_INFO "comedi: attempt to attach...\n"); + printk(KERN_INFO "comedi%d: adl_pci8164\n", dev->minor); - dev->board_name = dev->driver->driver_name; - - ret = comedi_pci_enable(pcidev, dev->board_name); - if (ret) - return ret; - dev->iobase = pci_resource_start(pcidev, 2); + dev->board_name = "pci8164"; ret = comedi_alloc_subdevices(dev, 4); if (ret) return ret; - s = &dev->subdevices[0]; + pcidev = adl_pci8164_find_pci(dev, it); + if (!pcidev) + return -EIO; + comedi_set_hw_dev(dev, &pcidev->dev); + + if (comedi_pci_enable(pcidev, "adl_pci8164") < 0) { + printk(KERN_ERR "comedi%d: Failed to enable " + "PCI device and request regions\n", dev->minor); + return -EIO; + } + dev->iobase = pci_resource_start(pcidev, 2); + printk(KERN_DEBUG "comedi: base addr %4lx\n", dev->iobase); + + s = dev->subdevices + 0; s->type = COMEDI_SUBD_PROC; s->subdev_flags = SDF_READABLE | SDF_WRITABLE; s->n_chan = 4; @@ -241,7 +280,7 @@ static int adl_pci8164_attach_pci(struct comedi_device *dev, s->insn_read = adl_pci8164_insn_read_msts; s->insn_write = adl_pci8164_insn_write_cmd; - s = &dev->subdevices[1]; + s = dev->subdevices + 1; s->type = COMEDI_SUBD_PROC; s->subdev_flags = SDF_READABLE | SDF_WRITABLE; s->n_chan = 4; @@ -251,7 +290,7 @@ static int adl_pci8164_attach_pci(struct comedi_device *dev, s->insn_read = adl_pci8164_insn_read_ssts; s->insn_write = adl_pci8164_insn_write_otp; - s = &dev->subdevices[2]; + s = dev->subdevices + 2; s->type = COMEDI_SUBD_PROC; s->subdev_flags = SDF_READABLE | SDF_WRITABLE; s->n_chan = 4; @@ -261,7 +300,7 @@ static int adl_pci8164_attach_pci(struct comedi_device *dev, s->insn_read = adl_pci8164_insn_read_buf0; s->insn_write = adl_pci8164_insn_write_buf0; - s = &dev->subdevices[3]; + s = dev->subdevices + 3; s->type = COMEDI_SUBD_PROC; s->subdev_flags = SDF_READABLE | SDF_WRITABLE; s->n_chan = 4; @@ -271,8 +310,7 @@ static int adl_pci8164_attach_pci(struct comedi_device *dev, s->insn_read = adl_pci8164_insn_read_buf1; s->insn_write = adl_pci8164_insn_write_buf1; - dev_info(dev->class_dev, "%s attached\n", dev->board_name); - + printk(KERN_INFO "comedi: attached\n"); return 0; } @@ -283,13 +321,14 @@ static void adl_pci8164_detach(struct comedi_device *dev) if (pcidev) { if (dev->iobase) comedi_pci_disable(pcidev); + pci_dev_put(pcidev); } } static struct comedi_driver adl_pci8164_driver = { .driver_name = "adl_pci8164", .module = THIS_MODULE, - .attach_pci = adl_pci8164_attach_pci, + .attach = adl_pci8164_attach, .detach = adl_pci8164_detach, }; diff --git a/trunk/drivers/staging/comedi/drivers/adl_pci9111.c b/trunk/drivers/staging/comedi/drivers/adl_pci9111.c index a87192ac2846..a31dae6e07df 100644 --- a/trunk/drivers/staging/comedi/drivers/adl_pci9111.c +++ b/trunk/drivers/staging/comedi/drivers/adl_pci9111.c @@ -47,7 +47,14 @@ Status: experimental The scanned channels must be consecutive and start from 0. They must all have the same range and aref. -Configuration options: not applicable, uses PCI auto config +Configuration options: + + [0] - PCI bus number (optional) + [1] - PCI slot number (optional) + +If bus/slot is not specified, the first available PCI +device will be used. + */ /* @@ -79,9 +86,29 @@ a multiple of chanlist_len*convert_arg. #define PCI9111_DRIVER_NAME "adl_pci9111" #define PCI9111_HR_DEVICE_ID 0x9111 +/* TODO: Add other pci9111 board id */ + +#define PCI9111_IO_RANGE 0x0100 + #define PCI9111_FIFO_HALF_SIZE 512 +#define PCI9111_AI_CHANNEL_NBR 16 + +#define PCI9111_AI_RESOLUTION 12 +#define PCI9111_AI_RESOLUTION_MASK 0x0FFF +#define PCI9111_AI_RESOLUTION_2_CMP_BIT 0x0800 + +#define PCI9111_HR_AI_RESOLUTION 16 +#define PCI9111_HR_AI_RESOLUTION_MASK 0xFFFF +#define PCI9111_HR_AI_RESOLUTION_2_CMP_BIT 0x8000 + #define PCI9111_AI_ACQUISITION_PERIOD_MIN_NS 10000 +#define PCI9111_AO_CHANNEL_NBR 1 +#define PCI9111_AO_RESOLUTION 12 +#define PCI9111_AO_RESOLUTION_MASK 0x0FFF +#define PCI9111_DI_CHANNEL_NBR 16 +#define PCI9111_DO_CHANNEL_NBR 16 +#define PCI9111_DO_MASK 0xFFFF #define PCI9111_RANGE_SETTING_DELAY 10 #define PCI9111_AI_INSTANT_READ_UDELAY_US 2 @@ -89,49 +116,233 @@ a multiple of chanlist_len*convert_arg. #define PCI9111_8254_CLOCK_PERIOD_NS 500 +#define PCI9111_8254_COUNTER_0 0x00 +#define PCI9111_8254_COUNTER_1 0x40 +#define PCI9111_8254_COUNTER_2 0x80 +#define PCI9111_8254_COUNTER_LATCH 0x00 +#define PCI9111_8254_READ_LOAD_LSB_ONLY 0x10 +#define PCI9111_8254_READ_LOAD_MSB_ONLY 0x20 +#define PCI9111_8254_READ_LOAD_LSB_MSB 0x30 +#define PCI9111_8254_MODE_0 0x00 +#define PCI9111_8254_MODE_1 0x02 +#define PCI9111_8254_MODE_2 0x04 +#define PCI9111_8254_MODE_3 0x06 +#define PCI9111_8254_MODE_4 0x08 +#define PCI9111_8254_MODE_5 0x0A +#define PCI9111_8254_BINARY_COUNTER 0x00 +#define PCI9111_8254_BCD_COUNTER 0x01 + +/* IO address map */ + +#define PCI9111_REGISTER_AD_FIFO_VALUE 0x00 /* AD Data stored + in FIFO */ +#define PCI9111_REGISTER_DA_OUTPUT 0x00 +#define PCI9111_REGISTER_DIGITAL_IO 0x02 +#define PCI9111_REGISTER_EXTENDED_IO_PORTS 0x04 +#define PCI9111_REGISTER_AD_CHANNEL_CONTROL 0x06 /* Channel + selection */ +#define PCI9111_REGISTER_AD_CHANNEL_READBACK 0x06 +#define PCI9111_REGISTER_INPUT_SIGNAL_RANGE 0x08 +#define PCI9111_REGISTER_RANGE_STATUS_READBACK 0x08 +#define PCI9111_REGISTER_TRIGGER_MODE_CONTROL 0x0A +#define PCI9111_REGISTER_AD_MODE_INTERRUPT_READBACK 0x0A +#define PCI9111_REGISTER_SOFTWARE_TRIGGER 0x0E +#define PCI9111_REGISTER_INTERRUPT_CONTROL 0x0C +#define PCI9111_REGISTER_8254_COUNTER_0 0x40 +#define PCI9111_REGISTER_8254_COUNTER_1 0x42 +#define PCI9111_REGISTER_8254_COUNTER_2 0X44 +#define PCI9111_REGISTER_8254_CONTROL 0x46 +#define PCI9111_REGISTER_INTERRUPT_CLEAR 0x48 + +#define PCI9111_TRIGGER_MASK 0x0F +#define PCI9111_PTRG_OFF (0 << 3) +#define PCI9111_PTRG_ON (1 << 3) +#define PCI9111_EITS_EXTERNAL (1 << 2) +#define PCI9111_EITS_INTERNAL (0 << 2) +#define PCI9111_TPST_SOFTWARE_TRIGGER (0 << 1) +#define PCI9111_TPST_TIMER_PACER (1 << 1) +#define PCI9111_ASCAN_ON (1 << 0) +#define PCI9111_ASCAN_OFF (0 << 0) + +#define PCI9111_ISC0_SET_IRQ_ON_ENDING_OF_AD_CONVERSION (0 << 0) +#define PCI9111_ISC0_SET_IRQ_ON_FIFO_HALF_FULL (1 << 0) +#define PCI9111_ISC1_SET_IRQ_ON_TIMER_TICK (0 << 1) +#define PCI9111_ISC1_SET_IRQ_ON_EXT_TRG (1 << 1) +#define PCI9111_FFEN_SET_FIFO_ENABLE (0 << 2) +#define PCI9111_FFEN_SET_FIFO_DISABLE (1 << 2) + +#define PCI9111_CHANNEL_MASK 0x0F + +#define PCI9111_RANGE_MASK 0x07 +#define PCI9111_FIFO_EMPTY_MASK 0x10 +#define PCI9111_FIFO_HALF_FULL_MASK 0x20 +#define PCI9111_FIFO_FULL_MASK 0x40 +#define PCI9111_AD_BUSY_MASK 0x80 + +#define PCI9111_IO_BASE (dev->iobase) + /* - * IO address map and bit defines + * Define inlined function */ -#define PCI9111_AI_FIFO_REG 0x00 -#define PCI9111_AO_REG 0x00 -#define PCI9111_DIO_REG 0x02 -#define PCI9111_EDIO_REG 0x04 -#define PCI9111_AI_CHANNEL_REG 0x06 -#define PCI9111_AI_RANGE_STAT_REG 0x08 -#define PCI9111_AI_STAT_AD_BUSY (1 << 7) -#define PCI9111_AI_STAT_FF_FF (1 << 6) -#define PCI9111_AI_STAT_FF_HF (1 << 5) -#define PCI9111_AI_STAT_FF_EF (1 << 4) -#define PCI9111_AI_RANGE_MASK (7 << 0) -#define PCI9111_AI_TRIG_CTRL_REG 0x0a -#define PCI9111_AI_TRIG_CTRL_TRGEVENT (1 << 5) -#define PCI9111_AI_TRIG_CTRL_POTRG (1 << 4) -#define PCI9111_AI_TRIG_CTRL_PTRG (1 << 3) -#define PCI9111_AI_TRIG_CTRL_ETIS (1 << 2) -#define PCI9111_AI_TRIG_CTRL_TPST (1 << 1) -#define PCI9111_AI_TRIG_CTRL_ASCAN (1 << 0) -#define PCI9111_INT_CTRL_REG 0x0c -#define PCI9111_INT_CTRL_ISC2 (1 << 3) -#define PCI9111_INT_CTRL_FFEN (1 << 2) -#define PCI9111_INT_CTRL_ISC1 (1 << 1) -#define PCI9111_INT_CTRL_ISC0 (1 << 0) -#define PCI9111_SOFT_TRIG_REG 0x0e -#define PCI9111_8254_BASE_REG 0x40 -#define PCI9111_INT_CLR_REG 0x48 - -static const struct comedi_lrange pci9111_ai_range = { + +#define pci9111_trigger_and_autoscan_get() \ + (inb(PCI9111_IO_BASE+PCI9111_REGISTER_AD_MODE_INTERRUPT_READBACK)&0x0F) + +#define pci9111_trigger_and_autoscan_set(flags) \ + outb(flags, PCI9111_IO_BASE+PCI9111_REGISTER_TRIGGER_MODE_CONTROL) + +#define pci9111_interrupt_and_fifo_get() \ + ((inb(PCI9111_IO_BASE+PCI9111_REGISTER_AD_MODE_INTERRUPT_READBACK) \ + >> 4) & 0x03) + +#define pci9111_interrupt_and_fifo_set(flags) \ + outb(flags, PCI9111_IO_BASE+PCI9111_REGISTER_INTERRUPT_CONTROL) + +#define pci9111_interrupt_clear() \ + outb(0, PCI9111_IO_BASE+PCI9111_REGISTER_INTERRUPT_CLEAR) + +#define pci9111_software_trigger() \ + outb(0, PCI9111_IO_BASE+PCI9111_REGISTER_SOFTWARE_TRIGGER) + +#define pci9111_fifo_reset() do { \ + outb(PCI9111_FFEN_SET_FIFO_ENABLE, \ + PCI9111_IO_BASE+PCI9111_REGISTER_INTERRUPT_CONTROL); \ + outb(PCI9111_FFEN_SET_FIFO_DISABLE, \ + PCI9111_IO_BASE+PCI9111_REGISTER_INTERRUPT_CONTROL); \ + outb(PCI9111_FFEN_SET_FIFO_ENABLE, \ + PCI9111_IO_BASE+PCI9111_REGISTER_INTERRUPT_CONTROL); \ + } while (0) + +#define pci9111_is_fifo_full() \ + ((inb(PCI9111_IO_BASE+PCI9111_REGISTER_RANGE_STATUS_READBACK)& \ + PCI9111_FIFO_FULL_MASK) == 0) + +#define pci9111_is_fifo_half_full() \ + ((inb(PCI9111_IO_BASE+PCI9111_REGISTER_RANGE_STATUS_READBACK)& \ + PCI9111_FIFO_HALF_FULL_MASK) == 0) + +#define pci9111_is_fifo_empty() \ + ((inb(PCI9111_IO_BASE+PCI9111_REGISTER_RANGE_STATUS_READBACK)& \ + PCI9111_FIFO_EMPTY_MASK) == 0) + +#define pci9111_ai_channel_set(channel) \ + outb((channel)&PCI9111_CHANNEL_MASK, \ + PCI9111_IO_BASE+PCI9111_REGISTER_AD_CHANNEL_CONTROL) + +#define pci9111_ai_channel_get() \ + (inb(PCI9111_IO_BASE+PCI9111_REGISTER_AD_CHANNEL_READBACK) \ + &PCI9111_CHANNEL_MASK) + +#define pci9111_ai_range_set(range) \ + outb((range)&PCI9111_RANGE_MASK, \ + PCI9111_IO_BASE+PCI9111_REGISTER_INPUT_SIGNAL_RANGE) + +#define pci9111_ai_range_get() \ + (inb(PCI9111_IO_BASE+PCI9111_REGISTER_RANGE_STATUS_READBACK) \ + &PCI9111_RANGE_MASK) + +#define pci9111_ai_get_data() \ + (((inw(PCI9111_IO_BASE+PCI9111_REGISTER_AD_FIFO_VALUE)>>4) \ + &PCI9111_AI_RESOLUTION_MASK) \ + ^ PCI9111_AI_RESOLUTION_2_CMP_BIT) + +#define pci9111_hr_ai_get_data() \ + ((inw(PCI9111_IO_BASE+PCI9111_REGISTER_AD_FIFO_VALUE) \ + &PCI9111_HR_AI_RESOLUTION_MASK) \ + ^ PCI9111_HR_AI_RESOLUTION_2_CMP_BIT) + +#define pci9111_ao_set_data(data) \ + outw(data&PCI9111_AO_RESOLUTION_MASK, \ + PCI9111_IO_BASE+PCI9111_REGISTER_DA_OUTPUT) + +#define pci9111_di_get_bits() \ + inw(PCI9111_IO_BASE+PCI9111_REGISTER_DIGITAL_IO) + +#define pci9111_do_set_bits(bits) \ + outw(bits, PCI9111_IO_BASE+PCI9111_REGISTER_DIGITAL_IO) + +#define pci9111_8254_control_set(flags) \ + outb(flags, PCI9111_IO_BASE+PCI9111_REGISTER_8254_CONTROL) + +#define pci9111_8254_counter_0_set(data) \ + do { \ + outb(data & 0xFF, \ + PCI9111_IO_BASE+PCI9111_REGISTER_8254_COUNTER_0); \ + outb((data >> 8) & 0xFF, \ + PCI9111_IO_BASE+PCI9111_REGISTER_8254_COUNTER_0); \ + } while (0) + +#define pci9111_8254_counter_1_set(data) \ + do { \ + outb(data & 0xFF, \ + PCI9111_IO_BASE+PCI9111_REGISTER_8254_COUNTER_1); \ + outb((data >> 8) & 0xFF, \ + PCI9111_IO_BASE+PCI9111_REGISTER_8254_COUNTER_1); \ + } while (0) + +#define pci9111_8254_counter_2_set(data) \ + do { \ + outb(data & 0xFF, \ + PCI9111_IO_BASE+PCI9111_REGISTER_8254_COUNTER_2); \ + outb((data >> 8) & 0xFF, \ + PCI9111_IO_BASE+PCI9111_REGISTER_8254_COUNTER_2); \ + } while (0) + +static const struct comedi_lrange pci9111_hr_ai_range = { 5, { - BIP_RANGE(10), - BIP_RANGE(5), - BIP_RANGE(2.5), - BIP_RANGE(1.25), - BIP_RANGE(0.625) - } + BIP_RANGE(10), + BIP_RANGE(5), + BIP_RANGE(2.5), + BIP_RANGE(1.25), + BIP_RANGE(0.625) + } }; +/* */ +/* Board specification structure */ +/* */ + +struct pci9111_board { + const char *name; /* driver name */ + int device_id; + int ai_channel_nbr; /* num of A/D chans */ + int ao_channel_nbr; /* num of D/A chans */ + int ai_resolution; /* resolution of A/D */ + int ai_resolution_mask; + int ao_resolution; /* resolution of D/A */ + int ao_resolution_mask; + const struct comedi_lrange *ai_range_list; /* rangelist for A/D */ + const struct comedi_lrange *ao_range_list; /* rangelist for D/A */ + unsigned int ai_acquisition_period_min_ns; +}; + +static const struct pci9111_board pci9111_boards[] = { + { + .name = "pci9111_hr", + .device_id = PCI9111_HR_DEVICE_ID, + .ai_channel_nbr = PCI9111_AI_CHANNEL_NBR, + .ao_channel_nbr = PCI9111_AO_CHANNEL_NBR, + .ai_resolution = PCI9111_HR_AI_RESOLUTION, + .ai_resolution_mask = PCI9111_HR_AI_RESOLUTION_MASK, + .ao_resolution = PCI9111_AO_RESOLUTION, + .ao_resolution_mask = PCI9111_AO_RESOLUTION_MASK, + .ai_range_list = &pci9111_hr_ai_range, + .ao_range_list = &range_bipolar10, + .ai_acquisition_period_min_ns = PCI9111_AI_ACQUISITION_PERIOD_MIN_NS} +}; + +#define pci9111_board_nbr \ + (sizeof(pci9111_boards)/sizeof(struct pci9111_board)) + +/* Private data structure */ + struct pci9111_private_data { - unsigned long lcr_io_base; + unsigned long io_range; /* PCI6503 io range */ + + unsigned long lcr_io_base; /* Local configuration register base + * address */ + unsigned long lcr_io_range; int stop_counter; int stop_is_none; @@ -141,14 +352,23 @@ struct pci9111_private_data { unsigned int chunk_counter; unsigned int chunk_num_samples; - int ao_readback; + int ao_readback; /* Last written analog output data */ - unsigned int div1; - unsigned int div2; + unsigned int timer_divisor_1; /* Divisor values for the 8254 timer + * pacer */ + unsigned int timer_divisor_2; + + int is_valid; /* Is device valid */ short ai_bounce_buffer[2 * PCI9111_FIFO_HALF_SIZE]; }; +#define dev_private ((struct pci9111_private_data *)dev->private) + +/* ------------------------------------------------------------------ */ +/* PLX9050 SECTION */ +/* ------------------------------------------------------------------ */ + #define PLX9050_REGISTER_INTERRUPT_CONTROL 0x4c #define PLX9050_LINTI1_ENABLE (1 << 0) @@ -184,19 +404,33 @@ static void plx9050_interrupt_control(unsigned long io_base, outb(flags, io_base + PLX9050_REGISTER_INTERRUPT_CONTROL); } +/* ------------------------------------------------------------------ */ +/* MISCELLANEOUS SECTION */ +/* ------------------------------------------------------------------ */ + +/* 8254 timer */ + static void pci9111_timer_set(struct comedi_device *dev) { - struct pci9111_private_data *dev_private = dev->private; - unsigned long timer_base = dev->iobase + PCI9111_8254_BASE_REG; + pci9111_8254_control_set(PCI9111_8254_COUNTER_0 | + PCI9111_8254_READ_LOAD_LSB_MSB | + PCI9111_8254_MODE_0 | + PCI9111_8254_BINARY_COUNTER); - i8254_set_mode(timer_base, 1, 0, I8254_MODE0 | I8254_BINARY); - i8254_set_mode(timer_base, 1, 1, I8254_MODE2 | I8254_BINARY); - i8254_set_mode(timer_base, 1, 2, I8254_MODE2 | I8254_BINARY); + pci9111_8254_control_set(PCI9111_8254_COUNTER_1 | + PCI9111_8254_READ_LOAD_LSB_MSB | + PCI9111_8254_MODE_2 | + PCI9111_8254_BINARY_COUNTER); + + pci9111_8254_control_set(PCI9111_8254_COUNTER_2 | + PCI9111_8254_READ_LOAD_LSB_MSB | + PCI9111_8254_MODE_2 | + PCI9111_8254_BINARY_COUNTER); udelay(1); - i8254_write(timer_base, 1, 2, dev_private->div2); - i8254_write(timer_base, 1, 1, dev_private->div1); + pci9111_8254_counter_2_set(dev_private->timer_divisor_2); + pci9111_8254_counter_1_set(dev_private->timer_divisor_1); } enum pci9111_trigger_sources { @@ -210,55 +444,47 @@ static void pci9111_trigger_source_set(struct comedi_device *dev, { int flags; - /* Read the current trigger mode control bits */ - flags = inb(dev->iobase + PCI9111_AI_TRIG_CTRL_REG); - /* Mask off the EITS and TPST bits */ - flags &= 0x9; + flags = pci9111_trigger_and_autoscan_get() & 0x09; switch (source) { case software: + flags |= PCI9111_EITS_INTERNAL | PCI9111_TPST_SOFTWARE_TRIGGER; break; case timer_pacer: - flags |= PCI9111_AI_TRIG_CTRL_TPST; + flags |= PCI9111_EITS_INTERNAL | PCI9111_TPST_TIMER_PACER; break; case external: - flags |= PCI9111_AI_TRIG_CTRL_ETIS; + flags |= PCI9111_EITS_EXTERNAL; break; } - outb(flags, dev->iobase + PCI9111_AI_TRIG_CTRL_REG); + pci9111_trigger_and_autoscan_set(flags); } static void pci9111_pretrigger_set(struct comedi_device *dev, bool pretrigger) { int flags; - /* Read the current trigger mode control bits */ - flags = inb(dev->iobase + PCI9111_AI_TRIG_CTRL_REG); - /* Mask off the PTRG bit */ - flags &= 0x7; + flags = pci9111_trigger_and_autoscan_get() & 0x07; if (pretrigger) - flags |= PCI9111_AI_TRIG_CTRL_PTRG; + flags |= PCI9111_PTRG_ON; - outb(flags, dev->iobase + PCI9111_AI_TRIG_CTRL_REG); + pci9111_trigger_and_autoscan_set(flags); } static void pci9111_autoscan_set(struct comedi_device *dev, bool autoscan) { int flags; - /* Read the current trigger mode control bits */ - flags = inb(dev->iobase + PCI9111_AI_TRIG_CTRL_REG); - /* Mask off the ASCAN bit */ - flags &= 0xe; + flags = pci9111_trigger_and_autoscan_get() & 0x0e; if (autoscan) - flags |= PCI9111_AI_TRIG_CTRL_ASCAN; + flags |= PCI9111_ASCAN_ON; - outb(flags, dev->iobase + PCI9111_AI_TRIG_CTRL_REG); + pci9111_trigger_and_autoscan_set(flags); } enum pci9111_ISC0_sources { @@ -277,39 +503,30 @@ static void pci9111_interrupt_source_set(struct comedi_device *dev, { int flags; - /* Read the current interrupt control bits */ - flags = inb(dev->iobase + PCI9111_AI_TRIG_CTRL_REG); - /* Shift the bits so they are compatible with the write register */ - flags >>= 4; - /* Mask off the ISCx bits */ - flags &= 0xc0; + flags = pci9111_interrupt_and_fifo_get() & 0x04; - /* Now set the new ISCx bits */ if (irq_0_source == irq_on_fifo_half_full) - flags |= PCI9111_INT_CTRL_ISC0; + flags |= PCI9111_ISC0_SET_IRQ_ON_FIFO_HALF_FULL; if (irq_1_source == irq_on_external_trigger) - flags |= PCI9111_INT_CTRL_ISC1; + flags |= PCI9111_ISC1_SET_IRQ_ON_EXT_TRG; - outb(flags, dev->iobase + PCI9111_INT_CTRL_REG); + pci9111_interrupt_and_fifo_set(flags); } -static void pci9111_fifo_reset(struct comedi_device *dev) -{ - unsigned long int_ctrl_reg = dev->iobase + PCI9111_INT_CTRL_REG; +/* ------------------------------------------------------------------ */ +/* HARDWARE TRIGGERED ANALOG INPUT SECTION */ +/* ------------------------------------------------------------------ */ - /* To reset the FIFO, set FFEN sequence as 0 -> 1 -> 0 */ - outb(0, int_ctrl_reg); - outb(PCI9111_INT_CTRL_FFEN, int_ctrl_reg); - outb(0, int_ctrl_reg); -} +/* Cancel analog input autoscan */ + +#undef AI_DO_CMD_DEBUG static int pci9111_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s) { - struct pci9111_private_data *dev_private = dev->private; - /* Disable interrupts */ + plx9050_interrupt_control(dev_private->lcr_io_base, true, true, true, true, false); @@ -317,65 +534,97 @@ static int pci9111_ai_cancel(struct comedi_device *dev, pci9111_autoscan_set(dev, false); - pci9111_fifo_reset(dev); + pci9111_fifo_reset(); + +#ifdef AI_DO_CMD_DEBUG + printk(PCI9111_DRIVER_NAME ": ai_cancel\n"); +#endif return 0; } -static int pci9111_ai_do_cmd_test(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_cmd *cmd) +/* Test analog input command */ + +#define pci9111_check_trigger_src(src, flags) do { \ + tmp = src; \ + src &= flags; \ + if (!src || tmp != src) \ + error++; \ + } while (false); + +static int +pci9111_ai_do_cmd_test(struct comedi_device *dev, + struct comedi_subdevice *s, struct comedi_cmd *cmd) { - struct pci9111_private_data *dev_private = dev->private; int tmp; int error = 0; int range, reference; int i; + struct pci9111_board *board = (struct pci9111_board *)dev->board_ptr; - /* Step 1 : check if triggers are trivially valid */ + /* Step 1 : check if trigger are trivialy valid */ - error |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW); - error |= cfc_check_trigger_src(&cmd->scan_begin_src, - TRIG_TIMER | TRIG_FOLLOW | TRIG_EXT); - error |= cfc_check_trigger_src(&cmd->convert_src, - TRIG_TIMER | TRIG_EXT); - error |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT); - error |= cfc_check_trigger_src(&cmd->stop_src, - TRIG_COUNT | TRIG_NONE); + pci9111_check_trigger_src(cmd->start_src, TRIG_NOW); + pci9111_check_trigger_src(cmd->scan_begin_src, + TRIG_TIMER | TRIG_FOLLOW | TRIG_EXT); + pci9111_check_trigger_src(cmd->convert_src, TRIG_TIMER | TRIG_EXT); + pci9111_check_trigger_src(cmd->scan_end_src, TRIG_COUNT); + pci9111_check_trigger_src(cmd->stop_src, TRIG_COUNT | TRIG_NONE); if (error) return 1; - /* Step 2a : make sure trigger sources are unique */ + /* step 2 : make sure trigger sources are unique and mutually + * compatible */ - error |= cfc_check_trigger_is_unique(cmd->scan_begin_src); - error |= cfc_check_trigger_is_unique(cmd->convert_src); - error |= cfc_check_trigger_is_unique(cmd->stop_src); + if (cmd->start_src != TRIG_NOW) + error++; - /* Step 2b : and mutually compatible */ + if ((cmd->scan_begin_src != TRIG_TIMER) && + (cmd->scan_begin_src != TRIG_FOLLOW) && + (cmd->scan_begin_src != TRIG_EXT)) + error++; + if ((cmd->convert_src != TRIG_TIMER) && (cmd->convert_src != TRIG_EXT)) + error++; if ((cmd->convert_src == TRIG_TIMER) && !((cmd->scan_begin_src == TRIG_TIMER) || (cmd->scan_begin_src == TRIG_FOLLOW))) - error |= -EINVAL; + error++; if ((cmd->convert_src == TRIG_EXT) && !((cmd->scan_begin_src == TRIG_EXT) || (cmd->scan_begin_src == TRIG_FOLLOW))) - error |= -EINVAL; + error++; + + + if (cmd->scan_end_src != TRIG_COUNT) + error++; + if ((cmd->stop_src != TRIG_COUNT) && (cmd->stop_src != TRIG_NONE)) + error++; if (error) return 2; /* Step 3 : make sure arguments are trivialy compatible */ + if (cmd->chanlist_len < 1) { + cmd->chanlist_len = 1; + error++; + } + + if (cmd->chanlist_len > board->ai_channel_nbr) { + cmd->chanlist_len = board->ai_channel_nbr; + error++; + } + if ((cmd->start_src == TRIG_NOW) && (cmd->start_arg != 0)) { cmd->start_arg = 0; error++; } if ((cmd->convert_src == TRIG_TIMER) && - (cmd->convert_arg < PCI9111_AI_ACQUISITION_PERIOD_MIN_NS)) { - cmd->convert_arg = PCI9111_AI_ACQUISITION_PERIOD_MIN_NS; + (cmd->convert_arg < board->ai_acquisition_period_min_ns)) { + cmd->convert_arg = board->ai_acquisition_period_min_ns; error++; } if ((cmd->convert_src == TRIG_EXT) && (cmd->convert_arg != 0)) { @@ -384,8 +633,8 @@ static int pci9111_ai_do_cmd_test(struct comedi_device *dev, } if ((cmd->scan_begin_src == TRIG_TIMER) && - (cmd->scan_begin_arg < PCI9111_AI_ACQUISITION_PERIOD_MIN_NS)) { - cmd->scan_begin_arg = PCI9111_AI_ACQUISITION_PERIOD_MIN_NS; + (cmd->scan_begin_arg < board->ai_acquisition_period_min_ns)) { + cmd->scan_begin_arg = board->ai_acquisition_period_min_ns; error++; } if ((cmd->scan_begin_src == TRIG_FOLLOW) @@ -421,9 +670,9 @@ static int pci9111_ai_do_cmd_test(struct comedi_device *dev, if (cmd->convert_src == TRIG_TIMER) { tmp = cmd->convert_arg; i8253_cascade_ns_to_timer_2div(PCI9111_8254_CLOCK_PERIOD_NS, - &dev_private->div1, - &dev_private->div2, - &cmd->convert_arg, + &(dev_private->timer_divisor_1), + &(dev_private->timer_divisor_2), + &(cmd->convert_arg), cmd->flags & TRIG_ROUND_MASK); if (tmp != cmd->convert_arg) error++; @@ -484,6 +733,14 @@ static int pci9111_ai_do_cmd_test(struct comedi_device *dev, error++; } } + } else { + if ((CR_CHAN(cmd->chanlist[0]) > + (board->ai_channel_nbr - 1)) + || (CR_CHAN(cmd->chanlist[0]) < 0)) { + comedi_error(dev, + "channel number is out of limits\n"); + error++; + } } } @@ -494,11 +751,12 @@ static int pci9111_ai_do_cmd_test(struct comedi_device *dev, } +/* Analog input command */ + static int pci9111_ai_do_cmd(struct comedi_device *dev, - struct comedi_subdevice *s) + struct comedi_subdevice *subdevice) { - struct pci9111_private_data *dev_private = dev->private; - struct comedi_cmd *async_cmd = &s->async->cmd; + struct comedi_cmd *async_cmd = &subdevice->async->cmd; if (!dev->irq) { comedi_error(dev, @@ -510,20 +768,17 @@ static int pci9111_ai_do_cmd(struct comedi_device *dev, /* TODO: handle the case of an external multiplexer */ if (async_cmd->chanlist_len > 1) { - outb(async_cmd->chanlist_len - 1, - dev->iobase + PCI9111_AI_CHANNEL_REG); + pci9111_ai_channel_set((async_cmd->chanlist_len) - 1); pci9111_autoscan_set(dev, true); } else { - outb(CR_CHAN(async_cmd->chanlist[0]), - dev->iobase + PCI9111_AI_CHANNEL_REG); + pci9111_ai_channel_set(CR_CHAN(async_cmd->chanlist[0])); pci9111_autoscan_set(dev, false); } /* Set gain */ /* This is the same gain on every channel */ - outb(CR_RANGE(async_cmd->chanlist[0]) & PCI9111_AI_RANGE_MASK, - dev->iobase + PCI9111_AI_RANGE_STAT_REG); + pci9111_ai_range_set(CR_RANGE(async_cmd->chanlist[0])); /* Set counter */ @@ -549,9 +804,21 @@ static int pci9111_ai_do_cmd(struct comedi_device *dev, dev_private->scan_delay = 0; switch (async_cmd->convert_src) { case TRIG_TIMER: + i8253_cascade_ns_to_timer_2div(PCI9111_8254_CLOCK_PERIOD_NS, + &(dev_private->timer_divisor_1), + &(dev_private->timer_divisor_2), + &(async_cmd->convert_arg), + async_cmd-> + flags & TRIG_ROUND_MASK); +#ifdef AI_DO_CMD_DEBUG + printk(PCI9111_DRIVER_NAME ": divisors = %d, %d\n", + dev_private->timer_divisor_1, + dev_private->timer_divisor_2); +#endif + pci9111_trigger_source_set(dev, software); pci9111_timer_set(dev); - pci9111_fifo_reset(dev); + pci9111_fifo_reset(); pci9111_interrupt_source_set(dev, irq_on_fifo_half_full, irq_on_timer_tick); pci9111_trigger_source_set(dev, timer_pacer); @@ -570,7 +837,7 @@ static int pci9111_ai_do_cmd(struct comedi_device *dev, case TRIG_EXT: pci9111_trigger_source_set(dev, external); - pci9111_fifo_reset(dev); + pci9111_fifo_reset(); pci9111_interrupt_source_set(dev, irq_on_fifo_half_full, irq_on_timer_tick); plx9050_interrupt_control(dev_private->lcr_io_base, true, true, @@ -589,6 +856,23 @@ static int pci9111_ai_do_cmd(struct comedi_device *dev, dev_private->chunk_num_samples = dev_private->chanlist_len * (1 + dev_private->scan_delay); +#ifdef AI_DO_CMD_DEBUG + printk(PCI9111_DRIVER_NAME ": start interruptions!\n"); + printk(PCI9111_DRIVER_NAME ": trigger source = %2x\n", + pci9111_trigger_and_autoscan_get()); + printk(PCI9111_DRIVER_NAME ": irq source = %2x\n", + pci9111_interrupt_and_fifo_get()); + printk(PCI9111_DRIVER_NAME ": ai_do_cmd\n"); + printk(PCI9111_DRIVER_NAME ": stop counter = %d\n", + dev_private->stop_counter); + printk(PCI9111_DRIVER_NAME ": scan delay = %d\n", + dev_private->scan_delay); + printk(PCI9111_DRIVER_NAME ": chanlist_len = %d\n", + dev_private->chanlist_len); + printk(PCI9111_DRIVER_NAME ": chunk num samples = %d\n", + dev_private->chunk_num_samples); +#endif + return 0; } @@ -597,24 +881,34 @@ static void pci9111_ai_munge(struct comedi_device *dev, unsigned int num_bytes, unsigned int start_chan_index) { + unsigned int i, num_samples = num_bytes / sizeof(short); short *array = data; - unsigned int maxdata = s->maxdata; - unsigned int invert = (maxdata + 1) >> 1; - unsigned int shift = (maxdata == 0xffff) ? 0 : 4; - unsigned int num_samples = num_bytes / sizeof(short); - unsigned int i; - - for (i = 0; i < num_samples; i++) - array[i] = ((array[i] >> shift) & maxdata) ^ invert; + int resolution = + ((struct pci9111_board *)dev->board_ptr)->ai_resolution; + + for (i = 0; i < num_samples; i++) { + if (resolution == PCI9111_HR_AI_RESOLUTION) + array[i] = + (array[i] & PCI9111_HR_AI_RESOLUTION_MASK) ^ + PCI9111_HR_AI_RESOLUTION_2_CMP_BIT; + else + array[i] = + ((array[i] >> 4) & PCI9111_AI_RESOLUTION_MASK) ^ + PCI9111_AI_RESOLUTION_2_CMP_BIT; + } } +/* ------------------------------------------------------------------ */ +/* INTERRUPT SECTION */ +/* ------------------------------------------------------------------ */ + +#undef INTERRUPT_DEBUG + static irqreturn_t pci9111_interrupt(int irq, void *p_device) { struct comedi_device *dev = p_device; - struct pci9111_private_data *dev_private = dev->private; - struct comedi_subdevice *s = dev->read_subdev; + struct comedi_subdevice *subdevice = dev->read_subdev; struct comedi_async *async; - unsigned int status; unsigned long irq_flags; unsigned char intcsr; @@ -624,7 +918,7 @@ static irqreturn_t pci9111_interrupt(int irq, void *p_device) return IRQ_NONE; } - async = s->async; + async = subdevice->async; spin_lock_irqsave(&dev->spinlock, irq_flags); @@ -646,37 +940,37 @@ static irqreturn_t pci9111_interrupt(int irq, void *p_device) (PLX9050_LINTI1_ENABLE | PLX9050_LINTI1_STATUS)) { /* Interrupt comes from fifo_half-full signal */ - status = inb(dev->iobase + PCI9111_AI_RANGE_STAT_REG); - - /* '0' means FIFO is full, data may have been lost */ - if (!(status & PCI9111_AI_STAT_FF_FF)) { + if (pci9111_is_fifo_full()) { spin_unlock_irqrestore(&dev->spinlock, irq_flags); comedi_error(dev, PCI9111_DRIVER_NAME " fifo overflow"); - outb(0, dev->iobase + PCI9111_INT_CLR_REG); - pci9111_ai_cancel(dev, s); + pci9111_interrupt_clear(); + pci9111_ai_cancel(dev, subdevice); async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA; - comedi_event(dev, s); + comedi_event(dev, subdevice); return IRQ_HANDLED; } - /* '0' means FIFO is half-full */ - if (!(status & PCI9111_AI_STAT_FF_HF)) { + if (pci9111_is_fifo_half_full()) { unsigned int num_samples; unsigned int bytes_written = 0; +#ifdef INTERRUPT_DEBUG + printk(PCI9111_DRIVER_NAME ": fifo is half full\n"); +#endif + num_samples = PCI9111_FIFO_HALF_SIZE > dev_private->stop_counter && !dev_private-> stop_is_none ? dev_private->stop_counter : PCI9111_FIFO_HALF_SIZE; - insw(dev->iobase + PCI9111_AI_FIFO_REG, + insw(PCI9111_IO_BASE + PCI9111_REGISTER_AD_FIFO_VALUE, dev_private->ai_bounce_buffer, num_samples); if (dev_private->scan_delay < 1) { bytes_written = - cfc_write_array_to_buffer(s, + cfc_write_array_to_buffer(subdevice, dev_private-> ai_bounce_buffer, num_samples * @@ -700,7 +994,7 @@ static irqreturn_t pci9111_interrupt(int irq, void *p_device) bytes_written += cfc_write_array_to_buffer - (s, + (subdevice, dev_private->ai_bounce_buffer + position, to_read * sizeof(short)); @@ -735,135 +1029,168 @@ static irqreturn_t pci9111_interrupt(int irq, void *p_device) if ((dev_private->stop_counter == 0) && (!dev_private->stop_is_none)) { async->events |= COMEDI_CB_EOA; - pci9111_ai_cancel(dev, s); + pci9111_ai_cancel(dev, subdevice); } - outb(0, dev->iobase + PCI9111_INT_CLR_REG); + /* Very important, otherwise another interrupt request will be inserted + * and will cause driver hangs on processing interrupt event. */ + + pci9111_interrupt_clear(); spin_unlock_irqrestore(&dev->spinlock, irq_flags); - comedi_event(dev, s); + comedi_event(dev, subdevice); return IRQ_HANDLED; } +/* ------------------------------------------------------------------ */ +/* INSTANT ANALOG INPUT OUTPUT SECTION */ +/* ------------------------------------------------------------------ */ + +/* analog instant input */ + +#undef AI_INSN_DEBUG + static int pci9111_ai_insn_read(struct comedi_device *dev, - struct comedi_subdevice *s, + struct comedi_subdevice *subdevice, struct comedi_insn *insn, unsigned int *data) { - unsigned int chan = CR_CHAN(insn->chanspec); - unsigned int range = CR_RANGE(insn->chanspec); - unsigned int maxdata = s->maxdata; - unsigned int invert = (maxdata + 1) >> 1; - unsigned int shift = (maxdata == 0xffff) ? 0 : 4; - unsigned int status; - int timeout; - int i; + int resolution = + ((struct pci9111_board *)dev->board_ptr)->ai_resolution; - outb(chan, dev->iobase + PCI9111_AI_CHANNEL_REG); + int timeout, i; - status = inb(dev->iobase + PCI9111_AI_RANGE_STAT_REG); - if ((status & PCI9111_AI_RANGE_MASK) != range) { - outb(range & PCI9111_AI_RANGE_MASK, - dev->iobase + PCI9111_AI_RANGE_STAT_REG); - } +#ifdef AI_INSN_DEBUG + printk(PCI9111_DRIVER_NAME ": ai_insn set c/r/n = %2x/%2x/%2x\n", + CR_CHAN((&insn->chanspec)[0]), + CR_RANGE((&insn->chanspec)[0]), insn->n); +#endif + + pci9111_ai_channel_set(CR_CHAN((&insn->chanspec)[0])); + + if ((pci9111_ai_range_get()) != CR_RANGE((&insn->chanspec)[0])) + pci9111_ai_range_set(CR_RANGE((&insn->chanspec)[0])); - pci9111_fifo_reset(dev); + pci9111_fifo_reset(); for (i = 0; i < insn->n; i++) { - /* Generate a software trigger */ - outb(0, dev->iobase + PCI9111_SOFT_TRIG_REG); + pci9111_software_trigger(); timeout = PCI9111_AI_INSTANT_READ_TIMEOUT; while (timeout--) { - status = inb(dev->iobase + PCI9111_AI_RANGE_STAT_REG); - /* '1' means FIFO is not empty */ - if (status & PCI9111_AI_STAT_FF_EF) + if (!pci9111_is_fifo_empty()) goto conversion_done; } comedi_error(dev, "A/D read timeout"); data[i] = 0; - pci9111_fifo_reset(dev); + pci9111_fifo_reset(); return -ETIME; conversion_done: - data[i] = inw(dev->iobase + PCI9111_AI_FIFO_REG); - data[i] = ((data[i] >> shift) & maxdata) ^ invert; + if (resolution == PCI9111_HR_AI_RESOLUTION) + data[i] = pci9111_hr_ai_get_data(); + else + data[i] = pci9111_ai_get_data(); } +#ifdef AI_INSN_DEBUG + printk(PCI9111_DRIVER_NAME ": ai_insn get c/r/t = %2x/%2x/%2x\n", + pci9111_ai_channel_get(), + pci9111_ai_range_get(), pci9111_trigger_and_autoscan_get()); +#endif + return i; } -static int pci9111_ao_insn_write(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) +/* Analog instant output */ + +static int +pci9111_ao_insn_write(struct comedi_device *dev, + struct comedi_subdevice *s, struct comedi_insn *insn, + unsigned int *data) { - struct pci9111_private_data *dev_private = dev->private; - unsigned int val = 0; int i; for (i = 0; i < insn->n; i++) { - val = data[i]; - outw(val, dev->iobase + PCI9111_AO_REG); + pci9111_ao_set_data(data[i]); + dev_private->ao_readback = data[i]; } - dev_private->ao_readback = val; - return insn->n; + return i; } +/* Analog output readback */ + static int pci9111_ao_insn_read(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) + struct comedi_insn *insn, unsigned int *data) { - struct pci9111_private_data *dev_private = dev->private; int i; for (i = 0; i < insn->n; i++) - data[i] = dev_private->ao_readback; + data[i] = dev_private->ao_readback & PCI9111_AO_RESOLUTION_MASK; - return insn->n; + return i; } +/* ------------------------------------------------------------------ */ +/* DIGITAL INPUT OUTPUT SECTION */ +/* ------------------------------------------------------------------ */ + +/* Digital inputs */ + static int pci9111_di_insn_bits(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) + struct comedi_subdevice *subdevice, + struct comedi_insn *insn, unsigned int *data) { - data[1] = inw(dev->iobase + PCI9111_DIO_REG); + unsigned int bits; + + bits = pci9111_di_get_bits(); + data[1] = bits; return insn->n; } +/* Digital outputs */ + static int pci9111_do_insn_bits(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) + struct comedi_subdevice *subdevice, + struct comedi_insn *insn, unsigned int *data) { - unsigned int mask = data[0]; - unsigned int bits = data[1]; + unsigned int bits; - if (mask) { - s->state &= ~mask; - s->state |= (bits & mask); + /* Only set bits that have been masked */ + /* data[0] = mask */ + /* data[1] = bit state */ - outw(s->state, dev->iobase + PCI9111_DIO_REG); - } + data[0] &= PCI9111_DO_MASK; - data[1] = s->state; + bits = subdevice->state; + bits &= ~data[0]; + bits |= data[0] & data[1]; + subdevice->state = bits; + + pci9111_do_set_bits(bits); + + data[1] = bits; return insn->n; } +/* ------------------------------------------------------------------ */ +/* INITIALISATION SECTION */ +/* ------------------------------------------------------------------ */ + +/* Reset device */ + static int pci9111_reset(struct comedi_device *dev) { - struct pci9111_private_data *dev_private = dev->private; - /* Set trigger source to software */ + plx9050_interrupt_control(dev_private->lcr_io_base, true, true, true, true, false); @@ -871,90 +1198,177 @@ static int pci9111_reset(struct comedi_device *dev) pci9111_pretrigger_set(dev, false); pci9111_autoscan_set(dev, false); - /* Reset 8254 chip */ - dev_private->div1 = 0; - dev_private->div2 = 0; + /* Reset 8254 chip */ + + dev_private->timer_divisor_1 = 0; + dev_private->timer_divisor_2 = 0; + pci9111_timer_set(dev); return 0; } -static int pci9111_attach_pci(struct comedi_device *dev, - struct pci_dev *pcidev) +static struct pci_dev *pci9111_find_pci(struct comedi_device *dev, + struct comedi_devconfig *it) { - struct pci9111_private_data *dev_private; - struct comedi_subdevice *s; - int ret; + struct pci_dev *pcidev = NULL; + int bus = it->options[0]; + int slot = it->options[1]; + int i; + + for_each_pci_dev(pcidev) { + if (pcidev->vendor != PCI_VENDOR_ID_ADLINK) + continue; + for (i = 0; i < pci9111_board_nbr; i++) { + if (pcidev->device != pci9111_boards[i].device_id) + continue; + if (bus || slot) { + /* requested particular bus/slot */ + if (pcidev->bus->number != bus || + PCI_SLOT(pcidev->devfn) != slot) + continue; + } + dev->board_ptr = pci9111_boards + i; + printk(KERN_ERR + "comedi%d: found %s (b:s:f=%d:%d:%d), irq=%d\n", + dev->minor, pci9111_boards[i].name, + pcidev->bus->number, PCI_SLOT(pcidev->devfn), + PCI_FUNC(pcidev->devfn), pcidev->irq); + return pcidev; + } + } + printk(KERN_ERR + "comedi%d: no supported board found! (req. bus/slot : %d/%d)\n", + dev->minor, bus, slot); + return NULL; +} +static int pci9111_attach(struct comedi_device *dev, + struct comedi_devconfig *it) +{ + struct pci_dev *pcidev; + struct comedi_subdevice *subdevice; + unsigned long io_base, io_range, lcr_io_base, lcr_io_range; + int error; + const struct pci9111_board *board; + + if (alloc_private(dev, sizeof(struct pci9111_private_data)) < 0) + return -ENOMEM; + /* Probe the device to determine what device in the series it is. */ + + printk(KERN_ERR "comedi%d: " PCI9111_DRIVER_NAME " driver\n", + dev->minor); + + pcidev = pci9111_find_pci(dev, it); + if (!pcidev) + return -EIO; comedi_set_hw_dev(dev, &pcidev->dev); - dev->board_name = dev->driver->driver_name; + board = (struct pci9111_board *)dev->board_ptr; + + /* TODO: Warn about non-tested boards. */ + + /* Read local configuration register base address + * [PCI_BASE_ADDRESS #1]. */ + + lcr_io_base = pci_resource_start(pcidev, 1); + lcr_io_range = pci_resource_len(pcidev, 1); + + printk + ("comedi%d: local configuration registers at address 0x%4lx [0x%4lx]\n", + dev->minor, lcr_io_base, lcr_io_range); + + /* Enable PCI device and request regions */ + if (comedi_pci_enable(pcidev, PCI9111_DRIVER_NAME) < 0) { + printk + ("comedi%d: Failed to enable PCI device and request regions\n", + dev->minor); + return -EIO; + } + /* Read PCI6308 register base address [PCI_BASE_ADDRESS #2]. */ - ret = alloc_private(dev, sizeof(*dev_private)); - if (ret) - return ret; - dev_private = dev->private; + io_base = pci_resource_start(pcidev, 2); + io_range = pci_resource_len(pcidev, 2); - ret = comedi_pci_enable(pcidev, dev->board_name); - if (ret) - return ret; - dev_private->lcr_io_base = pci_resource_start(pcidev, 1); - dev->iobase = pci_resource_start(pcidev, 2); + printk(KERN_ERR "comedi%d: 6503 registers at address 0x%4lx [0x%4lx]\n", + dev->minor, io_base, io_range); + + dev->iobase = io_base; + dev->board_name = board->name; + dev_private->io_range = io_range; + dev_private->is_valid = 0; + dev_private->lcr_io_base = lcr_io_base; + dev_private->lcr_io_range = lcr_io_range; pci9111_reset(dev); + /* Irq setup */ + + dev->irq = 0; if (pcidev->irq > 0) { - ret = request_irq(dev->irq, pci9111_interrupt, - IRQF_SHARED, dev->board_name, dev); - if (ret) - return ret; dev->irq = pcidev->irq; + + if (request_irq(dev->irq, pci9111_interrupt, + IRQF_SHARED, PCI9111_DRIVER_NAME, dev) != 0) { + printk(KERN_ERR + "comedi%d: unable to allocate irq %u\n", + dev->minor, dev->irq); + return -EINVAL; + } } - ret = comedi_alloc_subdevices(dev, 4); - if (ret) - return ret; - - s = &dev->subdevices[0]; - dev->read_subdev = s; - s->type = COMEDI_SUBD_AI; - s->subdev_flags = SDF_READABLE | SDF_COMMON | SDF_CMD_READ; - s->n_chan = 16; - s->maxdata = 0xffff; - s->len_chanlist = 16; - s->range_table = &pci9111_ai_range; - s->cancel = pci9111_ai_cancel; - s->insn_read = pci9111_ai_insn_read; - s->do_cmdtest = pci9111_ai_do_cmd_test; - s->do_cmd = pci9111_ai_do_cmd; - s->munge = pci9111_ai_munge; - - s = &dev->subdevices[1]; - s->type = COMEDI_SUBD_AO; - s->subdev_flags = SDF_WRITABLE | SDF_COMMON; - s->n_chan = 1; - s->maxdata = 0x0fff; - s->len_chanlist = 1; - s->range_table = &range_bipolar10; - s->insn_write = pci9111_ao_insn_write; - s->insn_read = pci9111_ao_insn_read; - - s = &dev->subdevices[2]; - s->type = COMEDI_SUBD_DI; - s->subdev_flags = SDF_READABLE; - s->n_chan = 16; - s->maxdata = 1; - s->range_table = &range_digital; - s->insn_bits = pci9111_di_insn_bits; - - s = &dev->subdevices[3]; - s->type = COMEDI_SUBD_DO; - s->subdev_flags = SDF_READABLE | SDF_WRITABLE; - s->n_chan = 16; - s->maxdata = 1; - s->range_table = &range_digital; - s->insn_bits = pci9111_do_insn_bits; - - dev_info(dev->class_dev, "%s attached\n", dev->board_name); + /* TODO: Add external multiplexer setup (according to option[2]). */ + + error = comedi_alloc_subdevices(dev, 4); + if (error) + return error; + + subdevice = dev->subdevices + 0; + dev->read_subdev = subdevice; + + subdevice->type = COMEDI_SUBD_AI; + subdevice->subdev_flags = SDF_READABLE | SDF_COMMON | SDF_CMD_READ; + + /* TODO: Add external multiplexer data */ + /* if (devpriv->usemux) { subdevice->n_chan = devpriv->usemux; } */ + /* else { subdevice->n_chan = this_board->n_aichan; } */ + + subdevice->n_chan = board->ai_channel_nbr; + subdevice->maxdata = board->ai_resolution_mask; + subdevice->len_chanlist = board->ai_channel_nbr; + subdevice->range_table = board->ai_range_list; + subdevice->cancel = pci9111_ai_cancel; + subdevice->insn_read = pci9111_ai_insn_read; + subdevice->do_cmdtest = pci9111_ai_do_cmd_test; + subdevice->do_cmd = pci9111_ai_do_cmd; + subdevice->munge = pci9111_ai_munge; + + subdevice = dev->subdevices + 1; + subdevice->type = COMEDI_SUBD_AO; + subdevice->subdev_flags = SDF_WRITABLE | SDF_COMMON; + subdevice->n_chan = board->ao_channel_nbr; + subdevice->maxdata = board->ao_resolution_mask; + subdevice->len_chanlist = board->ao_channel_nbr; + subdevice->range_table = board->ao_range_list; + subdevice->insn_write = pci9111_ao_insn_write; + subdevice->insn_read = pci9111_ao_insn_read; + + subdevice = dev->subdevices + 2; + subdevice->type = COMEDI_SUBD_DI; + subdevice->subdev_flags = SDF_READABLE; + subdevice->n_chan = PCI9111_DI_CHANNEL_NBR; + subdevice->maxdata = 1; + subdevice->range_table = &range_digital; + subdevice->insn_bits = pci9111_di_insn_bits; + + subdevice = dev->subdevices + 3; + subdevice->type = COMEDI_SUBD_DO; + subdevice->subdev_flags = SDF_READABLE | SDF_WRITABLE; + subdevice->n_chan = PCI9111_DO_CHANNEL_NBR; + subdevice->maxdata = 1; + subdevice->range_table = &range_digital; + subdevice->insn_bits = pci9111_do_insn_bits; + + dev_private->is_valid = 1; return 0; } @@ -963,20 +1377,23 @@ static void pci9111_detach(struct comedi_device *dev) { struct pci_dev *pcidev = comedi_to_pci_dev(dev); - if (dev->iobase) - pci9111_reset(dev); + if (dev->private != NULL) { + if (dev_private->is_valid) + pci9111_reset(dev); + } if (dev->irq != 0) free_irq(dev->irq, dev); if (pcidev) { if (dev->iobase) comedi_pci_disable(pcidev); + pci_dev_put(pcidev); } } static struct comedi_driver adl_pci9111_driver = { .driver_name = "adl_pci9111", .module = THIS_MODULE, - .attach_pci = pci9111_attach_pci, + .attach = pci9111_attach, .detach = pci9111_detach, }; diff --git a/trunk/drivers/staging/comedi/drivers/adl_pci9118.c b/trunk/drivers/staging/comedi/drivers/adl_pci9118.c index 06ff65c85c9f..a1f74c2590e8 100644 --- a/trunk/drivers/staging/comedi/drivers/adl_pci9118.c +++ b/trunk/drivers/staging/comedi/drivers/adl_pci9118.c @@ -81,6 +81,18 @@ Configuration options: * correct channel number on every 12 bit sample */ +#undef PCI9118_EXTDEBUG /* + * if defined then driver prints + * a lot of messages + */ + +#undef DPRINTK +#ifdef PCI9118_EXTDEBUG +#define DPRINTK(fmt, args...) printk(fmt, ## args) +#else +#define DPRINTK(fmt, args...) +#endif + #define IORANGE_9118 64 /* I hope */ #define PCI9118_CHANLEN 255 /* * len of chanlist, some source say 256, @@ -344,170 +356,43 @@ struct pci9118_private { unsigned int ai_inttrig_start; /* TRIG_INT for start */ }; -static int check_channel_list(struct comedi_device *dev, - struct comedi_subdevice *s, int n_chan, - unsigned int *chanlist, int frontadd, int backadd) -{ - const struct boardtype *this_board = comedi_board(dev); - struct pci9118_private *devpriv = dev->private; - unsigned int i, differencial = 0, bipolar = 0; - - /* correct channel and range number check itself comedi/range.c */ - if (n_chan < 1) { - comedi_error(dev, "range/channel list is empty!"); - return 0; - } - if ((frontadd + n_chan + backadd) > s->len_chanlist) { - printk - ("comedi%d: range/channel list is too long for " - "actual configuration (%d>%d)!", - dev->minor, n_chan, s->len_chanlist - frontadd - backadd); - return 0; - } - - if (CR_AREF(chanlist[0]) == AREF_DIFF) - differencial = 1; /* all input must be diff */ - if (CR_RANGE(chanlist[0]) < PCI9118_BIPOLAR_RANGES) - bipolar = 1; /* all input must be bipolar */ - if (n_chan > 1) - for (i = 1; i < n_chan; i++) { /* check S.E/diff */ - if ((CR_AREF(chanlist[i]) == AREF_DIFF) != - (differencial)) { - comedi_error(dev, - "Differencial and single ended " - "inputs can't be mixtured!"); - return 0; - } - if ((CR_RANGE(chanlist[i]) < PCI9118_BIPOLAR_RANGES) != - (bipolar)) { - comedi_error(dev, - "Bipolar and unipolar ranges " - "can't be mixtured!"); - return 0; - } - if (!devpriv->usemux && differencial && - (CR_CHAN(chanlist[i]) >= this_board->n_aichand)) { - comedi_error(dev, - "If AREF_DIFF is used then is " - "available only first 8 channels!"); - return 0; - } - } +#define devpriv ((struct pci9118_private *)dev->private) +#define this_board ((struct boardtype *)dev->board_ptr) - return 1; -} +/* +============================================================================== +*/ +static int check_channel_list(struct comedi_device *dev, + struct comedi_subdevice *s, int n_chan, + unsigned int *chanlist, int frontadd, + int backadd); static int setup_channel_list(struct comedi_device *dev, struct comedi_subdevice *s, int n_chan, unsigned int *chanlist, int rot, int frontadd, - int backadd, int usedma, char useeos) -{ - struct pci9118_private *devpriv = dev->private; - unsigned int i, differencial = 0, bipolar = 0; - unsigned int scanquad, gain, ssh = 0x00; - - if (usedma == 1) { - rot = 8; - usedma = 0; - } - - if (CR_AREF(chanlist[0]) == AREF_DIFF) - differencial = 1; /* all input must be diff */ - if (CR_RANGE(chanlist[0]) < PCI9118_BIPOLAR_RANGES) - bipolar = 1; /* all input must be bipolar */ - - /* All is ok, so we can setup channel/range list */ - - if (!bipolar) { - devpriv->AdControlReg |= AdControl_UniP; - /* set unibipolar */ - } else { - devpriv->AdControlReg &= ((~AdControl_UniP) & 0xff); - /* enable bipolar */ - } - - if (differencial) { - devpriv->AdControlReg |= AdControl_Diff; - /* enable diff inputs */ - } else { - devpriv->AdControlReg &= ((~AdControl_Diff) & 0xff); - /* set single ended inputs */ - } - - outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL); - /* setup mode */ - - outl(2, dev->iobase + PCI9118_SCANMOD); - /* gods know why this sequence! */ - outl(0, dev->iobase + PCI9118_SCANMOD); - outl(1, dev->iobase + PCI9118_SCANMOD); - -#ifdef PCI9118_PARANOIDCHECK - devpriv->chanlistlen = n_chan; - for (i = 0; i < (PCI9118_CHANLEN + 1); i++) - devpriv->chanlist[i] = 0x55aa; -#endif - - if (frontadd) { /* insert channels for S&H */ - ssh = devpriv->softsshsample; - for (i = 0; i < frontadd; i++) { - /* store range list to card */ - scanquad = CR_CHAN(chanlist[0]); - /* get channel number; */ - gain = CR_RANGE(chanlist[0]); - /* get gain number */ - scanquad |= ((gain & 0x03) << 8); - outl(scanquad | ssh, dev->iobase + PCI9118_GAIN); - ssh = devpriv->softsshhold; - } - } - - for (i = 0; i < n_chan; i++) { /* store range list to card */ - scanquad = CR_CHAN(chanlist[i]); /* get channel number */ -#ifdef PCI9118_PARANOIDCHECK - devpriv->chanlist[i ^ usedma] = (scanquad & 0xf) << rot; -#endif - gain = CR_RANGE(chanlist[i]); /* get gain number */ - scanquad |= ((gain & 0x03) << 8); - outl(scanquad | ssh, dev->iobase + PCI9118_GAIN); - } - - if (backadd) { /* insert channels for fit onto 32bit DMA */ - for (i = 0; i < backadd; i++) { /* store range list to card */ - scanquad = CR_CHAN(chanlist[0]); - /* get channel number */ - gain = CR_RANGE(chanlist[0]); /* get gain number */ - scanquad |= ((gain & 0x03) << 8); - outl(scanquad | ssh, dev->iobase + PCI9118_GAIN); - } - } -#ifdef PCI9118_PARANOIDCHECK - devpriv->chanlist[n_chan ^ usedma] = devpriv->chanlist[0 ^ usedma]; - /* for 32bit operations */ - if (useeos) { - for (i = 1; i < n_chan; i++) { /* store range list to card */ - devpriv->chanlist[(n_chan + i) ^ usedma] = - (CR_CHAN(chanlist[i]) & 0xf) << rot; - } - devpriv->chanlist[(2 * n_chan) ^ usedma] = - devpriv->chanlist[0 ^ usedma]; - /* for 32bit operations */ - useeos = 2; - } else { - useeos = 1; - } -#endif - outl(0, dev->iobase + PCI9118_SCANMOD); /* close scan queue */ - /* udelay(100); important delay, or first sample will be crippled */ - - return 1; /* we can serve this with scan logic */ -} + int backadd, int usedma, char eoshandle); +static void start_pacer(struct comedi_device *dev, int mode, + unsigned int divisor1, unsigned int divisor2); +static int pci9118_reset(struct comedi_device *dev); +static int pci9118_exttrg_add(struct comedi_device *dev, unsigned char source); +static int pci9118_exttrg_del(struct comedi_device *dev, unsigned char source); +static int pci9118_ai_cancel(struct comedi_device *dev, + struct comedi_subdevice *s); +static void pci9118_calc_divisors(char mode, struct comedi_device *dev, + struct comedi_subdevice *s, + unsigned int *tim1, unsigned int *tim2, + unsigned int flags, int chans, + unsigned int *div1, unsigned int *div2, + char usessh, unsigned int chnsshfront); +/* +============================================================================== +*/ static int pci9118_insn_read_ai(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - struct pci9118_private *devpriv = dev->private; + int n, timeout; devpriv->AdControlReg = AdControl_Int & 0xff; @@ -557,11 +442,13 @@ static int pci9118_insn_read_ai(struct comedi_device *dev, } +/* +============================================================================== +*/ static int pci9118_insn_write_ao(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - struct pci9118_private *devpriv = dev->private; int n, chanreg, ch; ch = CR_CHAN(insn->chanspec); @@ -579,11 +466,13 @@ static int pci9118_insn_write_ao(struct comedi_device *dev, return n; } +/* +============================================================================== +*/ static int pci9118_insn_read_ao(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - struct pci9118_private *devpriv = dev->private; int n, chan; chan = CR_CHAN(insn->chanspec); @@ -593,6 +482,9 @@ static int pci9118_insn_read_ao(struct comedi_device *dev, return n; } +/* +============================================================================== +*/ static int pci9118_insn_bits_di(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) @@ -602,6 +494,9 @@ static int pci9118_insn_bits_di(struct comedi_device *dev, return insn->n; } +/* +============================================================================== +*/ static int pci9118_insn_bits_do(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) @@ -616,10 +511,11 @@ static int pci9118_insn_bits_do(struct comedi_device *dev, return insn->n; } +/* +============================================================================== +*/ static void interrupt_pci9118_ai_mode4_switch(struct comedi_device *dev) { - struct pci9118_private *devpriv = dev->private; - devpriv->AdFunctionReg = AdFunction_PDTrg | AdFunction_PETrg | AdFunction_AM; outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC); @@ -637,7 +533,6 @@ static unsigned int defragment_dma_buffer(struct comedi_device *dev, short *dma_buffer, unsigned int num_samples) { - struct pci9118_private *devpriv = dev->private; unsigned int i = 0, j = 0; unsigned int start_pos = devpriv->ai_add_front, stop_pos = devpriv->ai_add_front + devpriv->ai_n_chan; @@ -656,12 +551,14 @@ static unsigned int defragment_dma_buffer(struct comedi_device *dev, return j; } +/* +============================================================================== +*/ static int move_block_from_dma(struct comedi_device *dev, struct comedi_subdevice *s, short *dma_buffer, unsigned int num_samples) { - struct pci9118_private *devpriv = dev->private; unsigned int num_bytes; num_samples = defragment_dma_buffer(dev, s, dma_buffer, num_samples); @@ -677,207 +574,68 @@ static int move_block_from_dma(struct comedi_device *dev, return 0; } -static int pci9118_exttrg_add(struct comedi_device *dev, unsigned char source) +/* +============================================================================== +*/ +static char pci9118_decode_error_status(struct comedi_device *dev, + struct comedi_subdevice *s, + unsigned char m) { - struct pci9118_private *devpriv = dev->private; + if (m & 0x100) { + comedi_error(dev, "A/D FIFO Full status (Fatal Error!)"); + devpriv->ai_maskerr &= ~0x100L; + } + if (m & 0x008) { + comedi_error(dev, + "A/D Burst Mode Overrun Status (Fatal Error!)"); + devpriv->ai_maskerr &= ~0x008L; + } + if (m & 0x004) { + comedi_error(dev, "A/D Over Speed Status (Warning!)"); + devpriv->ai_maskerr &= ~0x004L; + } + if (m & 0x002) { + comedi_error(dev, "A/D Overrun Status (Fatal Error!)"); + devpriv->ai_maskerr &= ~0x002L; + } + if (m & devpriv->ai_maskharderr) { + s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA; + pci9118_ai_cancel(dev, s); + comedi_event(dev, s); + return 1; + } - if (source > 3) - return -1; /* incorrect source */ - devpriv->exttrg_users |= (1 << source); - devpriv->IntControlReg |= Int_DTrg; - outl(devpriv->IntControlReg, dev->iobase + PCI9118_INTCTRL); - outl(inl(devpriv->iobase_a + AMCC_OP_REG_INTCSR) | 0x1f00, - devpriv->iobase_a + AMCC_OP_REG_INTCSR); - /* allow INT in AMCC */ return 0; } -static int pci9118_exttrg_del(struct comedi_device *dev, unsigned char source) +static void pci9118_ai_munge(struct comedi_device *dev, + struct comedi_subdevice *s, void *data, + unsigned int num_bytes, + unsigned int start_chan_index) { - struct pci9118_private *devpriv = dev->private; - - if (source > 3) - return -1; /* incorrect source */ - devpriv->exttrg_users &= ~(1 << source); - if (!devpriv->exttrg_users) { /* shutdown ext trg intterrupts */ - devpriv->IntControlReg &= ~Int_DTrg; - if (!devpriv->IntControlReg) /* all IRQ disabled */ - outl(inl(devpriv->iobase_a + AMCC_OP_REG_INTCSR) & - (~0x00001f00), - devpriv->iobase_a + AMCC_OP_REG_INTCSR); - /* disable int in AMCC */ - outl(devpriv->IntControlReg, dev->iobase + PCI9118_INTCTRL); - } - return 0; -} - -static void pci9118_calc_divisors(char mode, struct comedi_device *dev, - struct comedi_subdevice *s, - unsigned int *tim1, unsigned int *tim2, - unsigned int flags, int chans, - unsigned int *div1, unsigned int *div2, - char usessh, unsigned int chnsshfront) -{ - const struct boardtype *this_board = comedi_board(dev); - struct pci9118_private *devpriv = dev->private; - - switch (mode) { - case 1: - case 4: - if (*tim2 < this_board->ai_ns_min) - *tim2 = this_board->ai_ns_min; - i8253_cascade_ns_to_timer(devpriv->i8254_osc_base, div1, div2, - tim2, flags & TRIG_ROUND_NEAREST); - break; - case 2: - if (*tim2 < this_board->ai_ns_min) - *tim2 = this_board->ai_ns_min; - *div1 = *tim2 / devpriv->i8254_osc_base; - /* convert timer (burst) */ - if (*div1 < this_board->ai_pacer_min) - *div1 = this_board->ai_pacer_min; - *div2 = *tim1 / devpriv->i8254_osc_base; /* scan timer */ - *div2 = *div2 / *div1; /* major timer is c1*c2 */ - if (*div2 < chans) - *div2 = chans; - - *tim2 = *div1 * devpriv->i8254_osc_base; - /* real convert timer */ - - if (usessh & (chnsshfront == 0)) /* use BSSH signal */ - if (*div2 < (chans + 2)) - *div2 = chans + 2; - - *tim1 = *div1 * *div2 * devpriv->i8254_osc_base; - break; - } -} - -static void start_pacer(struct comedi_device *dev, int mode, - unsigned int divisor1, unsigned int divisor2) -{ - outl(0x74, dev->iobase + PCI9118_CNTCTRL); - outl(0xb4, dev->iobase + PCI9118_CNTCTRL); -/* outl(0x30, dev->iobase + PCI9118_CNTCTRL); */ - udelay(1); - - if ((mode == 1) || (mode == 2) || (mode == 4)) { - outl(divisor2 & 0xff, dev->iobase + PCI9118_CNT2); - outl((divisor2 >> 8) & 0xff, dev->iobase + PCI9118_CNT2); - outl(divisor1 & 0xff, dev->iobase + PCI9118_CNT1); - outl((divisor1 >> 8) & 0xff, dev->iobase + PCI9118_CNT1); - } -} - -static int pci9118_ai_cancel(struct comedi_device *dev, - struct comedi_subdevice *s) -{ - struct pci9118_private *devpriv = dev->private; - - if (devpriv->usedma) - outl(inl(devpriv->iobase_a + AMCC_OP_REG_MCSR) & - (~EN_A2P_TRANSFERS), - devpriv->iobase_a + AMCC_OP_REG_MCSR); /* stop DMA */ - pci9118_exttrg_del(dev, EXTTRG_AI); - start_pacer(dev, 0, 0, 0); /* stop 8254 counters */ - devpriv->AdFunctionReg = AdFunction_PDTrg | AdFunction_PETrg; - outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC); - /* - * positive triggers, no S&H, no burst, - * burst stop, no post trigger, - * no about trigger, trigger stop - */ - devpriv->AdControlReg = 0x00; - outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL); - /* - * bipolar, S.E., use 8254, stop 8354, - * internal trigger, soft trigger, - * disable INT and DMA - */ - outl(0, dev->iobase + PCI9118_BURST); - outl(1, dev->iobase + PCI9118_SCANMOD); - outl(2, dev->iobase + PCI9118_SCANMOD); /* reset scan queue */ - outl(0, dev->iobase + PCI9118_DELFIFO); /* flush FIFO */ - - devpriv->ai_do = 0; - devpriv->usedma = 0; - - devpriv->ai_act_scan = 0; - devpriv->ai_act_dmapos = 0; - s->async->cur_chan = 0; - s->async->inttrig = NULL; - devpriv->ai_buf_ptr = 0; - devpriv->ai_neverending = 0; - devpriv->dma_actbuf = 0; - - if (!devpriv->IntControlReg) - outl(inl(devpriv->iobase_a + AMCC_OP_REG_INTCSR) | 0x1f00, - devpriv->iobase_a + AMCC_OP_REG_INTCSR); - /* allow INT in AMCC */ - - return 0; -} - -static char pci9118_decode_error_status(struct comedi_device *dev, - struct comedi_subdevice *s, - unsigned char m) -{ - struct pci9118_private *devpriv = dev->private; - - if (m & 0x100) { - comedi_error(dev, "A/D FIFO Full status (Fatal Error!)"); - devpriv->ai_maskerr &= ~0x100L; - } - if (m & 0x008) { - comedi_error(dev, - "A/D Burst Mode Overrun Status (Fatal Error!)"); - devpriv->ai_maskerr &= ~0x008L; - } - if (m & 0x004) { - comedi_error(dev, "A/D Over Speed Status (Warning!)"); - devpriv->ai_maskerr &= ~0x004L; - } - if (m & 0x002) { - comedi_error(dev, "A/D Overrun Status (Fatal Error!)"); - devpriv->ai_maskerr &= ~0x002L; - } - if (m & devpriv->ai_maskharderr) { - s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA; - pci9118_ai_cancel(dev, s); - comedi_event(dev, s); - return 1; - } - - return 0; -} - -static void pci9118_ai_munge(struct comedi_device *dev, - struct comedi_subdevice *s, void *data, - unsigned int num_bytes, - unsigned int start_chan_index) -{ - struct pci9118_private *devpriv = dev->private; - unsigned int i, num_samples = num_bytes / sizeof(short); - short *array = data; - - for (i = 0; i < num_samples; i++) { - if (devpriv->usedma) - array[i] = be16_to_cpu(array[i]); - if (devpriv->ai16bits) - array[i] ^= 0x8000; - else - array[i] = (array[i] >> 4) & 0x0fff; + unsigned int i, num_samples = num_bytes / sizeof(short); + short *array = data; + + for (i = 0; i < num_samples; i++) { + if (devpriv->usedma) + array[i] = be16_to_cpu(array[i]); + if (devpriv->ai16bits) + array[i] ^= 0x8000; + else + array[i] = (array[i] >> 4) & 0x0fff; } } +/* +============================================================================== +*/ static void interrupt_pci9118_ai_onesample(struct comedi_device *dev, struct comedi_subdevice *s, unsigned short int_adstat, unsigned int int_amcc, unsigned short int_daq) { - struct pci9118_private *devpriv = dev->private; register short sampl; s->async->events = 0; @@ -922,13 +680,15 @@ static void interrupt_pci9118_ai_onesample(struct comedi_device *dev, comedi_event(dev, s); } +/* +============================================================================== +*/ static void interrupt_pci9118_ai_dma(struct comedi_device *dev, struct comedi_subdevice *s, unsigned short int_adstat, unsigned int int_amcc, unsigned short int_daq) { - struct pci9118_private *devpriv = dev->private; unsigned int next_dma_buf, samplesinbuf, sampls, m; if (int_amcc & MASTER_ABORT_INT) { @@ -953,6 +713,7 @@ static void interrupt_pci9118_ai_dma(struct comedi_device *dev, samplesinbuf = devpriv->dmabuf_use_size[devpriv->dma_actbuf] >> 1; /* number of received real samples */ +/* DPRINTK("dma_actbuf=%d\n",devpriv->dma_actbuf); */ if (devpriv->dma_doublebuf) { /* * switch DMA buffers if is used @@ -974,12 +735,17 @@ static void interrupt_pci9118_ai_dma(struct comedi_device *dev, * how many samples is to * end of buffer */ +/* + * DPRINTK("samps=%d m=%d %d %d\n", + * samplesinbuf,m,s->async->buf_int_count,s->async->buf_int_ptr); + */ sampls = m; move_block_from_dma(dev, s, devpriv->dmabuf_virt[devpriv->dma_actbuf], samplesinbuf); m = m - sampls; /* m= how many samples was transferred */ } +/* DPRINTK("YYY\n"); */ if (!devpriv->ai_neverending) if (devpriv->ai_act_scan >= devpriv->ai_scans) { @@ -1002,10 +768,12 @@ static void interrupt_pci9118_ai_dma(struct comedi_device *dev, comedi_event(dev, s); } +/* +============================================================================== +*/ static irqreturn_t interrupt_pci9118(int irq, void *d) { struct comedi_device *dev = d; - struct pci9118_private *devpriv = dev->private; unsigned int int_daq = 0, int_amcc, int_adstat; if (!dev->attached) @@ -1016,6 +784,14 @@ static irqreturn_t interrupt_pci9118(int irq, void *d) int_amcc = inl(devpriv->iobase_a + AMCC_OP_REG_INTCSR); /* get INT register from AMCC chip */ +/* + * DPRINTK("INT daq=0x%01x amcc=0x%08x MWAR=0x%08x + * MWTC=0x%08x ADSTAT=0x%02x ai_do=%d\n", + * int_daq, int_amcc, inl(devpriv->iobase_a+AMCC_OP_REG_MWAR), + * inl(devpriv->iobase_a+AMCC_OP_REG_MWTC), + * inw(dev->iobase+PCI9118_ADSTAT)&0x1ff,devpriv->ai_do); + */ + if ((!int_daq) && (!(int_amcc & ANY_S593X_INT))) return IRQ_NONE; /* interrupt from other source */ @@ -1061,18 +837,19 @@ static irqreturn_t interrupt_pci9118(int irq, void *d) } } - (devpriv->int_ai_func) (dev, &dev->subdevices[0], int_adstat, + (devpriv->int_ai_func) (dev, dev->subdevices + 0, int_adstat, int_amcc, int_daq); } return IRQ_HANDLED; } +/* +============================================================================== +*/ static int pci9118_ai_inttrig(struct comedi_device *dev, struct comedi_subdevice *s, unsigned int trignum) { - struct pci9118_private *devpriv = dev->private; - if (trignum != devpriv->ai_inttrig_start) return -EINVAL; @@ -1091,64 +868,119 @@ static int pci9118_ai_inttrig(struct comedi_device *dev, return 1; } +/* +============================================================================== +*/ static int pci9118_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd) { - const struct boardtype *this_board = comedi_board(dev); - struct pci9118_private *devpriv = dev->private; int err = 0; - unsigned int flags; int tmp; unsigned int divisor1 = 0, divisor2 = 0; - /* Step 1 : check if triggers are trivially valid */ + /* step 1: make sure trigger sources are trivially valid */ - err |= cfc_check_trigger_src(&cmd->start_src, - TRIG_NOW | TRIG_EXT | TRIG_INT); + tmp = cmd->start_src; + cmd->start_src &= TRIG_NOW | TRIG_EXT | TRIG_INT; + if (!cmd->start_src || tmp != cmd->start_src) + err++; - flags = TRIG_FOLLOW; + tmp = cmd->scan_begin_src; if (devpriv->master) - flags |= TRIG_TIMER | TRIG_EXT; - err |= cfc_check_trigger_src(&cmd->scan_begin_src, flags); + cmd->scan_begin_src &= TRIG_TIMER | TRIG_EXT | TRIG_FOLLOW; + else + cmd->scan_begin_src &= TRIG_FOLLOW; - flags = TRIG_TIMER | TRIG_EXT; + if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) + err++; + + tmp = cmd->convert_src; if (devpriv->master) - flags |= TRIG_NOW; - err |= cfc_check_trigger_src(&cmd->convert_src, flags); + cmd->convert_src &= TRIG_TIMER | TRIG_EXT | TRIG_NOW; + else + cmd->convert_src &= TRIG_TIMER | TRIG_EXT; + + if (!cmd->convert_src || tmp != cmd->convert_src) + err++; + + tmp = cmd->scan_end_src; + cmd->scan_end_src &= TRIG_COUNT; + if (!cmd->scan_end_src || tmp != cmd->scan_end_src) + err++; - err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT); - err |= cfc_check_trigger_src(&cmd->stop_src, - TRIG_COUNT | TRIG_NONE | TRIG_EXT); + tmp = cmd->stop_src; + cmd->stop_src &= TRIG_COUNT | TRIG_NONE | TRIG_EXT; + if (!cmd->stop_src || tmp != cmd->stop_src) + err++; if (err) return 1; - /* Step 2a : make sure trigger sources are unique */ + /* + * step 2: + * make sure trigger sources are + * unique and mutually compatible + */ + + if (cmd->start_src != TRIG_NOW && + cmd->start_src != TRIG_INT && cmd->start_src != TRIG_EXT) { + cmd->start_src = TRIG_NOW; + err++; + } + + if (cmd->scan_begin_src != TRIG_TIMER && + cmd->scan_begin_src != TRIG_EXT && + cmd->scan_begin_src != TRIG_INT && + cmd->scan_begin_src != TRIG_FOLLOW) { + cmd->scan_begin_src = TRIG_FOLLOW; + err++; + } + + if (cmd->convert_src != TRIG_TIMER && + cmd->convert_src != TRIG_EXT && cmd->convert_src != TRIG_NOW) { + cmd->convert_src = TRIG_TIMER; + err++; + } - err |= cfc_check_trigger_is_unique(cmd->start_src); - err |= cfc_check_trigger_is_unique(cmd->scan_begin_src); - err |= cfc_check_trigger_is_unique(cmd->convert_src); - err |= cfc_check_trigger_is_unique(cmd->stop_src); + if (cmd->scan_end_src != TRIG_COUNT) { + cmd->scan_end_src = TRIG_COUNT; + err++; + } - /* Step 2b : and mutually compatible */ + if (cmd->stop_src != TRIG_NONE && + cmd->stop_src != TRIG_COUNT && + cmd->stop_src != TRIG_INT && cmd->stop_src != TRIG_EXT) { + cmd->stop_src = TRIG_COUNT; + err++; + } - if (cmd->start_src == TRIG_EXT && cmd->scan_begin_src == TRIG_EXT) - err |= -EINVAL; + if (cmd->start_src == TRIG_EXT && cmd->scan_begin_src == TRIG_EXT) { + cmd->start_src = TRIG_NOW; + err++; + } - if (cmd->start_src == TRIG_INT && cmd->scan_begin_src == TRIG_INT) - err |= -EINVAL; + if (cmd->start_src == TRIG_INT && cmd->scan_begin_src == TRIG_INT) { + cmd->start_src = TRIG_NOW; + err++; + } if ((cmd->scan_begin_src & (TRIG_TIMER | TRIG_EXT)) && - (!(cmd->convert_src & (TRIG_TIMER | TRIG_NOW)))) - err |= -EINVAL; + (!(cmd->convert_src & (TRIG_TIMER | TRIG_NOW)))) { + cmd->convert_src = TRIG_TIMER; + err++; + } if ((cmd->scan_begin_src == TRIG_FOLLOW) && - (!(cmd->convert_src & (TRIG_TIMER | TRIG_EXT)))) - err |= -EINVAL; + (!(cmd->convert_src & (TRIG_TIMER | TRIG_EXT)))) { + cmd->convert_src = TRIG_TIMER; + err++; + } - if (cmd->stop_src == TRIG_EXT && cmd->scan_begin_src == TRIG_EXT) - err |= -EINVAL; + if (cmd->stop_src == TRIG_EXT && cmd->scan_begin_src == TRIG_EXT) { + cmd->stop_src = TRIG_COUNT; + err++; + } if (err) return 2; @@ -1242,9 +1074,11 @@ static int pci9118_ai_cmdtest(struct comedi_device *dev, if (cmd->scan_begin_src == TRIG_TIMER) { tmp = cmd->scan_begin_arg; +/* printk("S1 timer1=%u timer2=%u\n",cmd->scan_begin_arg,cmd->convert_arg); */ i8253_cascade_ns_to_timer(devpriv->i8254_osc_base, &divisor1, &divisor2, &cmd->scan_begin_arg, cmd->flags & TRIG_ROUND_MASK); +/* printk("S2 timer1=%u timer2=%u\n",cmd->scan_begin_arg,cmd->convert_arg); */ if (cmd->scan_begin_arg < this_board->ai_ns_min) cmd->scan_begin_arg = this_board->ai_ns_min; if (tmp != cmd->scan_begin_arg) @@ -1256,6 +1090,7 @@ static int pci9118_ai_cmdtest(struct comedi_device *dev, i8253_cascade_ns_to_timer(devpriv->i8254_osc_base, &divisor1, &divisor2, &cmd->convert_arg, cmd->flags & TRIG_ROUND_MASK); +/* printk("s1 timer1=%u timer2=%u\n",cmd->scan_begin_arg,cmd->convert_arg); */ if (cmd->convert_arg < this_board->ai_ns_min) cmd->convert_arg = this_board->ai_ns_min; if (tmp != cmd->convert_arg) @@ -1269,6 +1104,7 @@ static int pci9118_ai_cmdtest(struct comedi_device *dev, cmd->scan_begin_arg = this_board->ai_ns_min * (cmd->scan_end_arg + 2); +/* printk("s2 timer1=%u timer2=%u\n",cmd->scan_begin_arg,cmd->convert_arg); */ err++; } } else { @@ -1277,6 +1113,7 @@ static int pci9118_ai_cmdtest(struct comedi_device *dev, cmd->scan_begin_arg = cmd->convert_arg * cmd->chanlist_len; +/* printk("s3 timer1=%u timer2=%u\n",cmd->scan_begin_arg,cmd->convert_arg); */ err++; } } @@ -1294,13 +1131,18 @@ static int pci9118_ai_cmdtest(struct comedi_device *dev, return 0; } +/* +============================================================================== +*/ static int Compute_and_setup_dma(struct comedi_device *dev) { - struct pci9118_private *devpriv = dev->private; unsigned int dmalen0, dmalen1, i; + DPRINTK("adl_pci9118 EDBG: BGN: Compute_and_setup_dma()\n"); dmalen0 = devpriv->dmabuf_size[0]; dmalen1 = devpriv->dmabuf_size[1]; + DPRINTK("1 dmalen0=%d dmalen1=%d ai_data_len=%d\n", dmalen0, dmalen1, + devpriv->ai_data_len); /* isn't output buff smaller that our DMA buff? */ if (dmalen0 > (devpriv->ai_data_len)) { dmalen0 = devpriv->ai_data_len & ~3L; /* @@ -1312,6 +1154,7 @@ static int Compute_and_setup_dma(struct comedi_device *dev) * align to 32bit down */ } + DPRINTK("2 dmalen0=%d dmalen1=%d\n", dmalen0, dmalen1); /* we want wake up every scan? */ if (devpriv->ai_flags & TRIG_WAKE_EOS) { @@ -1326,6 +1169,11 @@ static int Compute_and_setup_dma(struct comedi_device *dev) } else { /* short first DMA buffer to one scan */ dmalen0 = devpriv->ai_n_realscanlen << 1; + DPRINTK + ("21 dmalen0=%d ai_n_realscanlen=%d " + "useeoshandle=%d\n", + dmalen0, devpriv->ai_n_realscanlen, + devpriv->useeoshandle); if (devpriv->useeoshandle) dmalen0 += 2; if (dmalen0 < 4) { @@ -1349,6 +1197,11 @@ static int Compute_and_setup_dma(struct comedi_device *dev) } else { /* short second DMA buffer to one scan */ dmalen1 = devpriv->ai_n_realscanlen << 1; + DPRINTK + ("22 dmalen1=%d ai_n_realscanlen=%d " + "useeoshandle=%d\n", + dmalen1, devpriv->ai_n_realscanlen, + devpriv->useeoshandle); if (devpriv->useeoshandle) dmalen1 -= 2; if (dmalen1 < 4) { @@ -1361,6 +1214,7 @@ static int Compute_and_setup_dma(struct comedi_device *dev) } } + DPRINTK("3 dmalen0=%d dmalen1=%d\n", dmalen0, dmalen1); /* transfer without TRIG_WAKE_EOS */ if (!(devpriv->ai_flags & TRIG_WAKE_EOS)) { /* if it's possible then align DMA buffers to length of scan */ @@ -1387,9 +1241,15 @@ static int Compute_and_setup_dma(struct comedi_device *dev) if (dmalen0 > ((devpriv->ai_n_realscanlen << 1) * devpriv->ai_scans)) { + DPRINTK + ("3.0 ai_n_realscanlen=%d ai_scans=%d\n", + devpriv->ai_n_realscanlen, + devpriv->ai_scans); dmalen0 = (devpriv->ai_n_realscanlen << 1) * devpriv->ai_scans; + DPRINTK("3.1 dmalen0=%d dmalen1=%d\n", dmalen0, + dmalen1); dmalen0 &= ~3L; } else { /* * fits whole measure into @@ -1401,16 +1261,21 @@ static int Compute_and_setup_dma(struct comedi_device *dev) dmalen1 = (devpriv->ai_n_realscanlen << 1) * devpriv->ai_scans - dmalen0; + DPRINTK("3.2 dmalen0=%d dmalen1=%d\n", dmalen0, + dmalen1); dmalen1 &= ~3L; } } } + DPRINTK("4 dmalen0=%d dmalen1=%d\n", dmalen0, dmalen1); + /* these DMA buffer size will be used */ devpriv->dma_actbuf = 0; devpriv->dmabuf_use_size[0] = dmalen0; devpriv->dmabuf_use_size[1] = dmalen1; + DPRINTK("5 dmalen0=%d dmalen1=%d\n", dmalen0, dmalen1); #if 0 if (devpriv->ai_n_scanlen < this_board->half_fifo_size) { devpriv->dmabuf_panic_size[0] = @@ -1443,14 +1308,18 @@ static int Compute_and_setup_dma(struct comedi_device *dev) devpriv->iobase_a + AMCC_OP_REG_INTCSR); /* allow bus mastering */ + DPRINTK("adl_pci9118 EDBG: END: Compute_and_setup_dma()\n"); return 0; } +/* +============================================================================== +*/ static int pci9118_ai_docmd_sampl(struct comedi_device *dev, struct comedi_subdevice *s) { - struct pci9118_private *devpriv = dev->private; - + DPRINTK("adl_pci9118 EDBG: BGN: pci9118_ai_docmd_sampl(%d,) [%d]\n", + dev->minor, devpriv->ai_do); switch (devpriv->ai_do) { case 1: devpriv->AdControlReg |= AdControl_TmrTr; @@ -1497,14 +1366,18 @@ static int pci9118_ai_docmd_sampl(struct comedi_device *dev, outl(devpriv->IntControlReg, dev->iobase + PCI9118_INTCTRL); } + DPRINTK("adl_pci9118 EDBG: END: pci9118_ai_docmd_sampl()\n"); return 0; } +/* +============================================================================== +*/ static int pci9118_ai_docmd_dma(struct comedi_device *dev, struct comedi_subdevice *s) { - struct pci9118_private *devpriv = dev->private; - + DPRINTK("adl_pci9118 EDBG: BGN: pci9118_ai_docmd_dma(%d,) [%d,%d]\n", + dev->minor, devpriv->ai_do, devpriv->usedma); Compute_and_setup_dma(dev); switch (devpriv->ai_do) { @@ -1567,17 +1440,20 @@ static int pci9118_ai_docmd_dma(struct comedi_device *dev, outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL); } + DPRINTK("adl_pci9118 EDBG: BGN: pci9118_ai_docmd_dma()\n"); return 0; } +/* +============================================================================== +*/ static int pci9118_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) { - const struct boardtype *this_board = comedi_board(dev); - struct pci9118_private *devpriv = dev->private; struct comedi_cmd *cmd = &s->async->cmd; unsigned int addchans = 0; int ret = 0; + DPRINTK("adl_pci9118 EDBG: BGN: pci9118_ai_cmd(%d,)\n", dev->minor); devpriv->ai12_startstop = 0; devpriv->ai_flags = cmd->flags; devpriv->ai_n_chan = cmd->chanlist_len; @@ -1626,6 +1502,10 @@ static int pci9118_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) devpriv->usessh = 0; /* no */ + DPRINTK("1 neverending=%d scans=%u usessh=%d ai_startstop=0x%2x\n", + devpriv->ai_neverending, devpriv->ai_scans, devpriv->usessh, + devpriv->ai12_startstop); + /* * use additional sample at end of every scan * to satisty DMA 32 bit transfer? @@ -1706,6 +1586,12 @@ static int pci9118_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) devpriv->ai_add_back) * (devpriv->ai_n_scanlen / devpriv->ai_n_chan); + DPRINTK("2 usedma=%d realscan=%d af=%u n_chan=%d ab=%d n_scanlen=%d\n", + devpriv->usedma, + devpriv->ai_n_realscanlen, devpriv->ai_add_front, + devpriv->ai_n_chan, devpriv->ai_add_back, + devpriv->ai_n_scanlen); + /* check and setup channel list */ if (!check_channel_list(dev, s, devpriv->ai_n_chan, devpriv->ai_chanlist, devpriv->ai_add_front, @@ -1802,13 +1688,371 @@ static int pci9118_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) else ret = pci9118_ai_docmd_sampl(dev, s); + DPRINTK("adl_pci9118 EDBG: END: pci9118_ai_cmd()\n"); return ret; } -static int pci9118_reset(struct comedi_device *dev) +/* +============================================================================== +*/ +static int check_channel_list(struct comedi_device *dev, + struct comedi_subdevice *s, int n_chan, + unsigned int *chanlist, int frontadd, int backadd) { - struct pci9118_private *devpriv = dev->private; + unsigned int i, differencial = 0, bipolar = 0; + + /* correct channel and range number check itself comedi/range.c */ + if (n_chan < 1) { + comedi_error(dev, "range/channel list is empty!"); + return 0; + } + if ((frontadd + n_chan + backadd) > s->len_chanlist) { + printk + ("comedi%d: range/channel list is too long for " + "actual configuration (%d>%d)!", + dev->minor, n_chan, s->len_chanlist - frontadd - backadd); + return 0; + } + + if (CR_AREF(chanlist[0]) == AREF_DIFF) + differencial = 1; /* all input must be diff */ + if (CR_RANGE(chanlist[0]) < PCI9118_BIPOLAR_RANGES) + bipolar = 1; /* all input must be bipolar */ + if (n_chan > 1) + for (i = 1; i < n_chan; i++) { /* check S.E/diff */ + if ((CR_AREF(chanlist[i]) == AREF_DIFF) != + (differencial)) { + comedi_error(dev, + "Differencial and single ended " + "inputs can't be mixtured!"); + return 0; + } + if ((CR_RANGE(chanlist[i]) < PCI9118_BIPOLAR_RANGES) != + (bipolar)) { + comedi_error(dev, + "Bipolar and unipolar ranges " + "can't be mixtured!"); + return 0; + } + if (!devpriv->usemux && differencial && + (CR_CHAN(chanlist[i]) >= this_board->n_aichand)) { + comedi_error(dev, + "If AREF_DIFF is used then is " + "available only first 8 channels!"); + return 0; + } + } + return 1; +} + +/* +============================================================================== +*/ +static int setup_channel_list(struct comedi_device *dev, + struct comedi_subdevice *s, int n_chan, + unsigned int *chanlist, int rot, int frontadd, + int backadd, int usedma, char useeos) +{ + unsigned int i, differencial = 0, bipolar = 0; + unsigned int scanquad, gain, ssh = 0x00; + + DPRINTK + ("adl_pci9118 EDBG: BGN: setup_channel_list" + "(%d,.,%d,.,%d,%d,%d,%d)\n", + dev->minor, n_chan, rot, frontadd, backadd, usedma); + + if (usedma == 1) { + rot = 8; + usedma = 0; + } + + if (CR_AREF(chanlist[0]) == AREF_DIFF) + differencial = 1; /* all input must be diff */ + if (CR_RANGE(chanlist[0]) < PCI9118_BIPOLAR_RANGES) + bipolar = 1; /* all input must be bipolar */ + + /* All is ok, so we can setup channel/range list */ + + if (!bipolar) { + devpriv->AdControlReg |= AdControl_UniP; + /* set unibipolar */ + } else { + devpriv->AdControlReg &= ((~AdControl_UniP) & 0xff); + /* enable bipolar */ + } + + if (differencial) { + devpriv->AdControlReg |= AdControl_Diff; + /* enable diff inputs */ + } else { + devpriv->AdControlReg &= ((~AdControl_Diff) & 0xff); + /* set single ended inputs */ + } + + outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL); + /* setup mode */ + + outl(2, dev->iobase + PCI9118_SCANMOD); + /* gods know why this sequence! */ + outl(0, dev->iobase + PCI9118_SCANMOD); + outl(1, dev->iobase + PCI9118_SCANMOD); + +#ifdef PCI9118_PARANOIDCHECK + devpriv->chanlistlen = n_chan; + for (i = 0; i < (PCI9118_CHANLEN + 1); i++) + devpriv->chanlist[i] = 0x55aa; +#endif + + if (frontadd) { /* insert channels for S&H */ + ssh = devpriv->softsshsample; + DPRINTK("FA: %04x: ", ssh); + for (i = 0; i < frontadd; i++) { + /* store range list to card */ + scanquad = CR_CHAN(chanlist[0]); + /* get channel number; */ + gain = CR_RANGE(chanlist[0]); + /* get gain number */ + scanquad |= ((gain & 0x03) << 8); + outl(scanquad | ssh, dev->iobase + PCI9118_GAIN); + DPRINTK("%02x ", scanquad | ssh); + ssh = devpriv->softsshhold; + } + DPRINTK("\n "); + } + + DPRINTK("SL: ", ssh); + for (i = 0; i < n_chan; i++) { /* store range list to card */ + scanquad = CR_CHAN(chanlist[i]); /* get channel number */ +#ifdef PCI9118_PARANOIDCHECK + devpriv->chanlist[i ^ usedma] = (scanquad & 0xf) << rot; +#endif + gain = CR_RANGE(chanlist[i]); /* get gain number */ + scanquad |= ((gain & 0x03) << 8); + outl(scanquad | ssh, dev->iobase + PCI9118_GAIN); + DPRINTK("%02x ", scanquad | ssh); + } + DPRINTK("\n "); + + if (backadd) { /* insert channels for fit onto 32bit DMA */ + DPRINTK("BA: %04x: ", ssh); + for (i = 0; i < backadd; i++) { /* store range list to card */ + scanquad = CR_CHAN(chanlist[0]); + /* get channel number */ + gain = CR_RANGE(chanlist[0]); /* get gain number */ + scanquad |= ((gain & 0x03) << 8); + outl(scanquad | ssh, dev->iobase + PCI9118_GAIN); + DPRINTK("%02x ", scanquad | ssh); + } + DPRINTK("\n "); + } +#ifdef PCI9118_PARANOIDCHECK + devpriv->chanlist[n_chan ^ usedma] = devpriv->chanlist[0 ^ usedma]; + /* for 32bit operations */ + if (useeos) { + for (i = 1; i < n_chan; i++) { /* store range list to card */ + devpriv->chanlist[(n_chan + i) ^ usedma] = + (CR_CHAN(chanlist[i]) & 0xf) << rot; + } + devpriv->chanlist[(2 * n_chan) ^ usedma] = + devpriv->chanlist[0 ^ usedma]; + /* for 32bit operations */ + useeos = 2; + } else { + useeos = 1; + } +#ifdef PCI9118_EXTDEBUG + DPRINTK("CHL: "); + for (i = 0; i <= (useeos * n_chan); i++) + DPRINTK("%04x ", devpriv->chanlist[i]); + + DPRINTK("\n "); +#endif +#endif + outl(0, dev->iobase + PCI9118_SCANMOD); /* close scan queue */ + /* udelay(100); important delay, or first sample will be crippled */ + + DPRINTK("adl_pci9118 EDBG: END: setup_channel_list()\n"); + return 1; /* we can serve this with scan logic */ +} + +/* +============================================================================== + calculate 8254 divisors if they are used for dual timing +*/ +static void pci9118_calc_divisors(char mode, struct comedi_device *dev, + struct comedi_subdevice *s, + unsigned int *tim1, unsigned int *tim2, + unsigned int flags, int chans, + unsigned int *div1, unsigned int *div2, + char usessh, unsigned int chnsshfront) +{ + DPRINTK + ("adl_pci9118 EDBG: BGN: pci9118_calc_divisors" + "(%d,%d,.,%u,%u,%u,%d,.,.,,%u,%u)\n", + mode, dev->minor, *tim1, *tim2, flags, chans, usessh, chnsshfront); + switch (mode) { + case 1: + case 4: + if (*tim2 < this_board->ai_ns_min) + *tim2 = this_board->ai_ns_min; + i8253_cascade_ns_to_timer(devpriv->i8254_osc_base, div1, div2, + tim2, flags & TRIG_ROUND_NEAREST); + DPRINTK("OSC base=%u div1=%u div2=%u timer1=%u\n", + devpriv->i8254_osc_base, *div1, *div2, *tim1); + break; + case 2: + if (*tim2 < this_board->ai_ns_min) + *tim2 = this_board->ai_ns_min; + DPRINTK("1 div1=%u div2=%u timer1=%u timer2=%u\n", *div1, *div2, + *tim1, *tim2); + *div1 = *tim2 / devpriv->i8254_osc_base; + /* convert timer (burst) */ + DPRINTK("2 div1=%u div2=%u timer1=%u timer2=%u\n", *div1, *div2, + *tim1, *tim2); + if (*div1 < this_board->ai_pacer_min) + *div1 = this_board->ai_pacer_min; + DPRINTK("3 div1=%u div2=%u timer1=%u timer2=%u\n", *div1, *div2, + *tim1, *tim2); + *div2 = *tim1 / devpriv->i8254_osc_base; /* scan timer */ + DPRINTK("4 div1=%u div2=%u timer1=%u timer2=%u\n", *div1, *div2, + *tim1, *tim2); + *div2 = *div2 / *div1; /* major timer is c1*c2 */ + DPRINTK("5 div1=%u div2=%u timer1=%u timer2=%u\n", *div1, *div2, + *tim1, *tim2); + if (*div2 < chans) + *div2 = chans; + DPRINTK("6 div1=%u div2=%u timer1=%u timer2=%u\n", *div1, *div2, + *tim1, *tim2); + + *tim2 = *div1 * devpriv->i8254_osc_base; + /* real convert timer */ + + if (usessh & (chnsshfront == 0)) /* use BSSH signal */ + if (*div2 < (chans + 2)) + *div2 = chans + 2; + + DPRINTK("7 div1=%u div2=%u timer1=%u timer2=%u\n", *div1, *div2, + *tim1, *tim2); + *tim1 = *div1 * *div2 * devpriv->i8254_osc_base; + DPRINTK("OSC base=%u div1=%u div2=%u timer1=%u timer2=%u\n", + devpriv->i8254_osc_base, *div1, *div2, *tim1, *tim2); + break; + } + DPRINTK("adl_pci9118 EDBG: END: pci9118_calc_divisors(%u,%u)\n", + *div1, *div2); +} + +/* +============================================================================== +*/ +static void start_pacer(struct comedi_device *dev, int mode, + unsigned int divisor1, unsigned int divisor2) +{ + outl(0x74, dev->iobase + PCI9118_CNTCTRL); + outl(0xb4, dev->iobase + PCI9118_CNTCTRL); +/* outl(0x30, dev->iobase + PCI9118_CNTCTRL); */ + udelay(1); + + if ((mode == 1) || (mode == 2) || (mode == 4)) { + outl(divisor2 & 0xff, dev->iobase + PCI9118_CNT2); + outl((divisor2 >> 8) & 0xff, dev->iobase + PCI9118_CNT2); + outl(divisor1 & 0xff, dev->iobase + PCI9118_CNT1); + outl((divisor1 >> 8) & 0xff, dev->iobase + PCI9118_CNT1); + } +} + +/* +============================================================================== +*/ +static int pci9118_exttrg_add(struct comedi_device *dev, unsigned char source) +{ + if (source > 3) + return -1; /* incorrect source */ + devpriv->exttrg_users |= (1 << source); + devpriv->IntControlReg |= Int_DTrg; + outl(devpriv->IntControlReg, dev->iobase + PCI9118_INTCTRL); + outl(inl(devpriv->iobase_a + AMCC_OP_REG_INTCSR) | 0x1f00, + devpriv->iobase_a + AMCC_OP_REG_INTCSR); + /* allow INT in AMCC */ + return 0; +} + +/* +============================================================================== +*/ +static int pci9118_exttrg_del(struct comedi_device *dev, unsigned char source) +{ + if (source > 3) + return -1; /* incorrect source */ + devpriv->exttrg_users &= ~(1 << source); + if (!devpriv->exttrg_users) { /* shutdown ext trg intterrupts */ + devpriv->IntControlReg &= ~Int_DTrg; + if (!devpriv->IntControlReg) /* all IRQ disabled */ + outl(inl(devpriv->iobase_a + AMCC_OP_REG_INTCSR) & + (~0x00001f00), + devpriv->iobase_a + AMCC_OP_REG_INTCSR); + /* disable int in AMCC */ + outl(devpriv->IntControlReg, dev->iobase + PCI9118_INTCTRL); + } + return 0; +} + +/* +============================================================================== +*/ +static int pci9118_ai_cancel(struct comedi_device *dev, + struct comedi_subdevice *s) +{ + if (devpriv->usedma) + outl(inl(devpriv->iobase_a + AMCC_OP_REG_MCSR) & + (~EN_A2P_TRANSFERS), + devpriv->iobase_a + AMCC_OP_REG_MCSR); /* stop DMA */ + pci9118_exttrg_del(dev, EXTTRG_AI); + start_pacer(dev, 0, 0, 0); /* stop 8254 counters */ + devpriv->AdFunctionReg = AdFunction_PDTrg | AdFunction_PETrg; + outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC); + /* + * positive triggers, no S&H, no burst, + * burst stop, no post trigger, + * no about trigger, trigger stop + */ + devpriv->AdControlReg = 0x00; + outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL); + /* + * bipolar, S.E., use 8254, stop 8354, + * internal trigger, soft trigger, + * disable INT and DMA + */ + outl(0, dev->iobase + PCI9118_BURST); + outl(1, dev->iobase + PCI9118_SCANMOD); + outl(2, dev->iobase + PCI9118_SCANMOD); /* reset scan queue */ + outl(0, dev->iobase + PCI9118_DELFIFO); /* flush FIFO */ + + devpriv->ai_do = 0; + devpriv->usedma = 0; + + devpriv->ai_act_scan = 0; + devpriv->ai_act_dmapos = 0; + s->async->cur_chan = 0; + s->async->inttrig = NULL; + devpriv->ai_buf_ptr = 0; + devpriv->ai_neverending = 0; + devpriv->dma_actbuf = 0; + + if (!devpriv->IntControlReg) + outl(inl(devpriv->iobase_a + AMCC_OP_REG_INTCSR) | 0x1f00, + devpriv->iobase_a + AMCC_OP_REG_INTCSR); + /* allow INT in AMCC */ + + return 0; +} + +/* +============================================================================== +*/ +static int pci9118_reset(struct comedi_device *dev) +{ devpriv->IntControlReg = 0; devpriv->exttrg_users = 0; inl(dev->iobase + PCI9118_INTCTRL); @@ -1868,7 +2112,6 @@ static int pci9118_reset(struct comedi_device *dev) static struct pci_dev *pci9118_find_pci(struct comedi_device *dev, struct comedi_devconfig *it) { - const struct boardtype *this_board = comedi_board(dev); struct pci_dev *pcidev = NULL; int bus = it->options[0]; int slot = it->options[1]; @@ -1907,8 +2150,6 @@ static struct pci_dev *pci9118_find_pci(struct comedi_device *dev, static int pci9118_attach(struct comedi_device *dev, struct comedi_devconfig *it) { - const struct boardtype *this_board = comedi_board(dev); - struct pci9118_private *devpriv; struct pci_dev *pcidev; struct comedi_subdevice *s; int ret, pages, i; @@ -1923,12 +2164,11 @@ static int pci9118_attach(struct comedi_device *dev, else master = 1; - ret = alloc_private(dev, sizeof(*devpriv)); + ret = alloc_private(dev, sizeof(struct pci9118_private)); if (ret < 0) { printk(" - Allocation failed!\n"); return -ENOMEM; } - devpriv = dev->private; pcidev = pci9118_find_pci(dev, it); if (!pcidev) @@ -2033,7 +2273,7 @@ static int pci9118_attach(struct comedi_device *dev, if (ret) return ret; - s = &dev->subdevices[0]; + s = dev->subdevices + 0; dev->read_subdev = s; s->type = COMEDI_SUBD_AI; s->subdev_flags = SDF_READABLE | SDF_COMMON | SDF_GROUND | SDF_DIFF; @@ -2054,7 +2294,7 @@ static int pci9118_attach(struct comedi_device *dev, s->munge = pci9118_ai_munge; } - s = &dev->subdevices[1]; + s = dev->subdevices + 1; s->type = COMEDI_SUBD_AO; s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_COMMON; s->n_chan = this_board->n_aochan; @@ -2064,7 +2304,7 @@ static int pci9118_attach(struct comedi_device *dev, s->insn_write = pci9118_insn_write_ao; s->insn_read = pci9118_insn_read_ao; - s = &dev->subdevices[2]; + s = dev->subdevices + 2; s->type = COMEDI_SUBD_DI; s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_COMMON; s->n_chan = 4; @@ -2074,7 +2314,7 @@ static int pci9118_attach(struct comedi_device *dev, s->io_bits = 0; /* all bits input */ s->insn_bits = pci9118_insn_bits_di; - s = &dev->subdevices[3]; + s = dev->subdevices + 3; s->type = COMEDI_SUBD_DO; s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_COMMON; s->n_chan = 4; @@ -2105,9 +2345,8 @@ static int pci9118_attach(struct comedi_device *dev, static void pci9118_detach(struct comedi_device *dev) { struct pci_dev *pcidev = comedi_to_pci_dev(dev); - struct pci9118_private *devpriv = dev->private; - if (devpriv) { + if (dev->private) { if (devpriv->valid) pci9118_reset(dev); if (dev->irq) diff --git a/trunk/drivers/staging/comedi/drivers/adq12b.c b/trunk/drivers/staging/comedi/drivers/adq12b.c index 3a2aa5628be3..6df51c8a602a 100644 --- a/trunk/drivers/staging/comedi/drivers/adq12b.c +++ b/trunk/drivers/staging/comedi/drivers/adq12b.c @@ -133,6 +133,8 @@ struct adq12b_private { unsigned int digital_state; }; +#define devpriv ((struct adq12b_private *)dev->private) + /* * "instructions" read/write data in "one-shot" or "software-triggered" * mode. @@ -142,7 +144,6 @@ static int adq12b_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - struct adq12b_private *devpriv = dev->private; int n, i; int range, channel; unsigned char hi, lo, status; @@ -199,7 +200,6 @@ static int adq12b_do_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - struct adq12b_private *devpriv = dev->private; int channel; for (channel = 0; channel < 8; channel++) @@ -221,7 +221,6 @@ static int adq12b_do_insn_bits(struct comedi_device *dev, static int adq12b_attach(struct comedi_device *dev, struct comedi_devconfig *it) { const struct adq12b_board *board = comedi_board(dev); - struct adq12b_private *devpriv; struct comedi_subdevice *s; unsigned long iobase; int unipolar, differential; @@ -253,18 +252,19 @@ static int adq12b_attach(struct comedi_device *dev, struct comedi_devconfig *it) dev->board_name = board->name; - ret = alloc_private(dev, sizeof(*devpriv)); - if (ret) - return ret; - devpriv = dev->private; +/* + * Allocate the private structure area. alloc_private() is a + * convenient macro defined in comedidev.h. + */ + if (alloc_private(dev, sizeof(struct adq12b_private)) < 0) + return -ENOMEM; +/* fill in devpriv structure */ devpriv->unipolar = unipolar; devpriv->differential = differential; devpriv->digital_state = 0; - /* - * initialize channel and range to -1 so we make sure we - * always write at least once to the CTREG in the instruction - */ +/* initialize channel and range to -1 so we make sure we always write + at least once to the CTREG in the instruction */ devpriv->last_channel = -1; devpriv->last_range = -1; @@ -272,7 +272,7 @@ static int adq12b_attach(struct comedi_device *dev, struct comedi_devconfig *it) if (ret) return ret; - s = &dev->subdevices[0]; + s = dev->subdevices + 0; /* analog input subdevice */ s->type = COMEDI_SUBD_AI; if (differential) { @@ -294,7 +294,7 @@ static int adq12b_attach(struct comedi_device *dev, struct comedi_devconfig *it) the board can handle */ s->insn_read = adq12b_ai_rinsn; - s = &dev->subdevices[1]; + s = dev->subdevices + 1; /* digital input subdevice */ s->type = COMEDI_SUBD_DI; s->subdev_flags = SDF_READABLE; @@ -303,7 +303,7 @@ static int adq12b_attach(struct comedi_device *dev, struct comedi_devconfig *it) s->range_table = &range_digital; s->insn_bits = adq12b_di_insn_bits; - s = &dev->subdevices[2]; + s = dev->subdevices + 2; /* digital output subdevice */ s->type = COMEDI_SUBD_DO; s->subdev_flags = SDF_WRITABLE; @@ -321,6 +321,7 @@ static void adq12b_detach(struct comedi_device *dev) { if (dev->iobase) release_region(dev->iobase, ADQ12B_SIZE); + kfree(devpriv); } static const struct adq12b_board adq12b_boards[] = { diff --git a/trunk/drivers/staging/comedi/drivers/adv_pci1710.c b/trunk/drivers/staging/comedi/drivers/adv_pci1710.c index def37bcc2a66..31986608eaf1 100644 --- a/trunk/drivers/staging/comedi/drivers/adv_pci1710.c +++ b/trunk/drivers/staging/comedi/drivers/adv_pci1710.c @@ -45,7 +45,6 @@ Configuration options: #include "../comedidev.h" -#include "comedi_fc.h" #include "8253.h" #include "amcc_s5933.h" @@ -53,6 +52,17 @@ Configuration options: * correct channel number on every 12 bit * sample */ +#undef PCI171X_EXTDEBUG + +#define DRV_NAME "adv_pci1710" + +#undef DPRINTK +#ifdef PCI171X_EXTDEBUG +#define DPRINTK(fmt, args...) printk(fmt, ## args) +#else +#define DPRINTK(fmt, args...) +#endif + #define PCI_VENDOR_ID_ADVANTECH 0x13fe /* hardware types of the cards */ @@ -201,101 +211,44 @@ struct boardtype { }; static const struct boardtype boardtypes[] = { - { - .name = "pci1710", - .device_id = 0x1710, - .iorange = IORANGE_171x, - .have_irq = 1, - .cardtype = TYPE_PCI171X, - .n_aichan = 16, - .n_aichand = 8, - .n_aochan = 2, - .n_dichan = 16, - .n_dochan = 16, - .n_counter = 1, - .ai_maxdata = 0x0fff, - .ao_maxdata = 0x0fff, - .rangelist_ai = &range_pci1710_3, - .rangecode_ai = range_codes_pci1710_3, - .rangelist_ao = &range_pci171x_da, - .ai_ns_min = 10000, - .fifo_half_size = 2048, - }, { - .name = "pci1710hg", - .device_id = 0x1710, - .iorange = IORANGE_171x, - .have_irq = 1, - .cardtype = TYPE_PCI171X, - .n_aichan = 16, - .n_aichand = 8, - .n_aochan = 2, - .n_dichan = 16, - .n_dochan = 16, - .n_counter = 1, - .ai_maxdata = 0x0fff, - .ao_maxdata = 0x0fff, - .rangelist_ai = &range_pci1710hg, - .rangecode_ai = range_codes_pci1710hg, - .rangelist_ao = &range_pci171x_da, - .ai_ns_min = 10000, - .fifo_half_size = 2048, - }, { - .name = "pci1711", - .device_id = 0x1711, - .iorange = IORANGE_171x, - .have_irq = 1, - .cardtype = TYPE_PCI171X, - .n_aichan = 16, - .n_aochan = 2, - .n_dichan = 16, - .n_dochan = 16, - .n_counter = 1, - .ai_maxdata = 0x0fff, - .ao_maxdata = 0x0fff, - .rangelist_ai = &range_pci17x1, - .rangecode_ai = range_codes_pci17x1, - .rangelist_ao = &range_pci171x_da, - .ai_ns_min = 10000, - .fifo_half_size = 512, - }, { - .name = "pci1713", - .device_id = 0x1713, - .iorange = IORANGE_171x, - .have_irq = 1, - .cardtype = TYPE_PCI1713, - .n_aichan = 32, - .n_aichand = 16, - .ai_maxdata = 0x0fff, - .rangelist_ai = &range_pci1710_3, - .rangecode_ai = range_codes_pci1710_3, - .ai_ns_min = 10000, - .fifo_half_size = 2048, - }, { - .name = "pci1720", - .device_id = 0x1720, - .iorange = IORANGE_1720, - .cardtype = TYPE_PCI1720, - .n_aochan = 4, - .ao_maxdata = 0x0fff, - .rangelist_ao = &range_pci1720, - }, { - .name = "pci1731", - .device_id = 0x1731, - .iorange = IORANGE_171x, - .have_irq = 1, - .cardtype = TYPE_PCI171X, - .n_aichan = 16, - .n_dichan = 16, - .n_dochan = 16, - .ai_maxdata = 0x0fff, - .rangelist_ai = &range_pci17x1, - .rangecode_ai = range_codes_pci17x1, - .ai_ns_min = 10000, - .fifo_half_size = 512, - }, + {"pci1710", 0x1710, + IORANGE_171x, 1, TYPE_PCI171X, + 16, 8, 2, 16, 16, 1, 0x0fff, 0x0fff, + &range_pci1710_3, range_codes_pci1710_3, + &range_pci171x_da, + 10000, 2048}, + {"pci1710hg", 0x1710, + IORANGE_171x, 1, TYPE_PCI171X, + 16, 8, 2, 16, 16, 1, 0x0fff, 0x0fff, + &range_pci1710hg, range_codes_pci1710hg, + &range_pci171x_da, + 10000, 2048}, + {"pci1711", 0x1711, + IORANGE_171x, 1, TYPE_PCI171X, + 16, 0, 2, 16, 16, 1, 0x0fff, 0x0fff, + &range_pci17x1, range_codes_pci17x1, &range_pci171x_da, + 10000, 512}, + {"pci1713", 0x1713, + IORANGE_171x, 1, TYPE_PCI1713, + 32, 16, 0, 0, 0, 0, 0x0fff, 0x0000, + &range_pci1710_3, range_codes_pci1710_3, NULL, + 10000, 2048}, + {"pci1720", 0x1720, + IORANGE_1720, 0, TYPE_PCI1720, + 0, 0, 4, 0, 0, 0, 0x0000, 0x0fff, + NULL, NULL, &range_pci1720, + 0, 0}, + {"pci1731", 0x1731, + IORANGE_171x, 1, TYPE_PCI171X, + 16, 0, 0, 16, 16, 0, 0x0fff, 0x0000, + &range_pci17x1, range_codes_pci17x1, NULL, + 10000, 512}, + /* dummy entry corresponding to driver name */ + {.name = DRV_NAME}, }; struct pci1710_private { + char valid; /* card is usable */ char neverending_ai; /* we do unlimited AI */ unsigned int CntrlReg; /* Control register */ unsigned int i8254_osc_base; /* frequence of onboard oscilator */ @@ -325,108 +278,33 @@ struct pci1710_private { * internal state */ }; -/* used for gain list programming */ -static const unsigned int muxonechan[] = { - 0x0000, 0x0101, 0x0202, 0x0303, 0x0404, 0x0505, 0x0606, 0x0707, - 0x0808, 0x0909, 0x0a0a, 0x0b0b, 0x0c0c, 0x0d0d, 0x0e0e, 0x0f0f, - 0x1010, 0x1111, 0x1212, 0x1313, 0x1414, 0x1515, 0x1616, 0x1717, - 0x1818, 0x1919, 0x1a1a, 0x1b1b, 0x1c1c, 0x1d1d, 0x1e1e, 0x1f1f -}; +#define devpriv ((struct pci1710_private *)dev->private) +#define this_board ((const struct boardtype *)dev->board_ptr) /* ============================================================================== - Check if channel list from user is builded correctly - If it's ok, then program scan/gain logic. - This works for all cards. */ + static int check_channel_list(struct comedi_device *dev, struct comedi_subdevice *s, - unsigned int *chanlist, unsigned int n_chan) -{ - unsigned int chansegment[32]; - unsigned int i, nowmustbechan, seglen, segpos; - - /* correct channel and range number check itself comedi/range.c */ - if (n_chan < 1) { - comedi_error(dev, "range/channel list is empty!"); - return 0; - } - - if (n_chan == 1) - return 1; /* seglen=1 */ - - chansegment[0] = chanlist[0]; /* first channel is every time ok */ - for (i = 1, seglen = 1; i < n_chan; i++, seglen++) { - if (chanlist[0] == chanlist[i]) - break; /* we detected a loop, stop */ - if ((CR_CHAN(chanlist[i]) & 1) && - (CR_AREF(chanlist[i]) == AREF_DIFF)) { - comedi_error(dev, "Odd channel cannot be differential input!\n"); - return 0; - } - nowmustbechan = (CR_CHAN(chansegment[i - 1]) + 1) % s->n_chan; - if (CR_AREF(chansegment[i - 1]) == AREF_DIFF) - nowmustbechan = (nowmustbechan + 1) % s->n_chan; - if (nowmustbechan != CR_CHAN(chanlist[i])) { - printk("channel list must be continuous! chanlist[%i]=%d but must be %d or %d!\n", - i, CR_CHAN(chanlist[i]), nowmustbechan, - CR_CHAN(chanlist[0])); - return 0; - } - chansegment[i] = chanlist[i]; /* next correct channel in list */ - } - - for (i = 0, segpos = 0; i < n_chan; i++) { - if (chanlist[i] != chansegment[i % seglen]) { - printk("bad channel, reference or range number! chanlist[%i]=%d,%d,%d and not %d,%d,%d!\n", - i, CR_CHAN(chansegment[i]), - CR_RANGE(chansegment[i]), - CR_AREF(chansegment[i]), - CR_CHAN(chanlist[i % seglen]), - CR_RANGE(chanlist[i % seglen]), - CR_AREF(chansegment[i % seglen])); - return 0; - } - } - return seglen; -} - + unsigned int *chanlist, unsigned int n_chan); static void setup_channel_list(struct comedi_device *dev, struct comedi_subdevice *s, unsigned int *chanlist, unsigned int n_chan, - unsigned int seglen) -{ - const struct boardtype *this_board = comedi_board(dev); - struct pci1710_private *devpriv = dev->private; - unsigned int i, range, chanprog; - - devpriv->act_chanlist_len = seglen; - devpriv->act_chanlist_pos = 0; - - for (i = 0; i < seglen; i++) { /* store range list to card */ - chanprog = muxonechan[CR_CHAN(chanlist[i])]; - outw(chanprog, dev->iobase + PCI171x_MUX); /* select channel */ - range = this_board->rangecode_ai[CR_RANGE(chanlist[i])]; - if (CR_AREF(chanlist[i]) == AREF_DIFF) - range |= 0x0020; - outw(range, dev->iobase + PCI171x_RANGE); /* select gain */ -#ifdef PCI171x_PARANOIDCHECK - devpriv->act_chanlist[i] = - (CR_CHAN(chanlist[i]) << 12) & 0xf000; -#endif - } -#ifdef PCI171x_PARANOIDCHECK - for ( ; i < n_chan; i++) { /* store remainder of channel list */ - devpriv->act_chanlist[i] = - (CR_CHAN(chanlist[i]) << 12) & 0xf000; - } -#endif + unsigned int seglen); +static void start_pacer(struct comedi_device *dev, int mode, + unsigned int divisor1, unsigned int divisor2); +static int pci1710_reset(struct comedi_device *dev); +static int pci171x_ai_cancel(struct comedi_device *dev, + struct comedi_subdevice *s); - devpriv->ai_et_MuxVal = - CR_CHAN(chanlist[0]) | (CR_CHAN(chanlist[seglen - 1]) << 8); - /* select channel interval to scan */ - outw(devpriv->ai_et_MuxVal, dev->iobase + PCI171x_MUX); -} +/* used for gain list programming */ +static const unsigned int muxonechan[] = { + 0x0000, 0x0101, 0x0202, 0x0303, 0x0404, 0x0505, 0x0606, 0x0707, + 0x0808, 0x0909, 0x0a0a, 0x0b0b, 0x0c0c, 0x0d0d, 0x0e0e, 0x0f0f, + 0x1010, 0x1111, 0x1212, 0x1313, 0x1414, 0x1515, 0x1616, 0x1717, + 0x1818, 0x1919, 0x1a1a, 0x1b1b, 0x1c1c, 0x1d1d, 0x1e1e, 0x1f1f +}; /* ============================================================================== @@ -435,13 +313,12 @@ static int pci171x_insn_read_ai(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - struct pci1710_private *devpriv = dev->private; int n, timeout; #ifdef PCI171x_PARANOIDCHECK - const struct boardtype *this_board = comedi_board(dev); unsigned int idata; #endif + DPRINTK("adv_pci1710 EDBG: BGN: pci171x_insn_read_ai(...)\n"); devpriv->CntrlReg &= Control_CNT0; devpriv->CntrlReg |= Control_SW; /* set software trigger */ outw(devpriv->CntrlReg, dev->iobase + PCI171x_CONTROL); @@ -450,18 +327,32 @@ static int pci171x_insn_read_ai(struct comedi_device *dev, setup_channel_list(dev, s, &insn->chanspec, 1, 1); + DPRINTK("adv_pci1710 A ST=%4x IO=%x\n", + inw(dev->iobase + PCI171x_STATUS), + dev->iobase + PCI171x_STATUS); for (n = 0; n < insn->n; n++) { outw(0, dev->iobase + PCI171x_SOFTTRG); /* start conversion */ + DPRINTK("adv_pci1710 B n=%d ST=%4x\n", n, + inw(dev->iobase + PCI171x_STATUS)); /* udelay(1); */ + DPRINTK("adv_pci1710 C n=%d ST=%4x\n", n, + inw(dev->iobase + PCI171x_STATUS)); timeout = 100; while (timeout--) { if (!(inw(dev->iobase + PCI171x_STATUS) & Status_FE)) goto conv_finish; + if (!(timeout % 10)) + DPRINTK("adv_pci1710 D n=%d tm=%d ST=%4x\n", n, + timeout, + inw(dev->iobase + PCI171x_STATUS)); } comedi_error(dev, "A/D insn timeout"); outb(0, dev->iobase + PCI171x_CLRFIFO); outb(0, dev->iobase + PCI171x_CLRINT); data[n] = 0; + DPRINTK + ("adv_pci1710 EDBG: END: pci171x_insn_read_ai(...) n=%d\n", + n); return -ETIME; conv_finish: @@ -482,6 +373,7 @@ static int pci171x_insn_read_ai(struct comedi_device *dev, outb(0, dev->iobase + PCI171x_CLRFIFO); outb(0, dev->iobase + PCI171x_CLRINT); + DPRINTK("adv_pci1710 EDBG: END: pci171x_insn_read_ai(...) n=%d\n", n); return n; } @@ -492,7 +384,6 @@ static int pci171x_insn_write_ao(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - struct pci1710_private *devpriv = dev->private; int n, chan, range, ofs; chan = CR_CHAN(insn->chanspec); @@ -525,7 +416,6 @@ static int pci171x_insn_read_ao(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - struct pci1710_private *devpriv = dev->private; int n, chan; chan = CR_CHAN(insn->chanspec); @@ -564,23 +454,6 @@ static int pci171x_insn_bits_do(struct comedi_device *dev, return insn->n; } -/* -============================================================================== -*/ -static void start_pacer(struct comedi_device *dev, int mode, - unsigned int divisor1, unsigned int divisor2) -{ - outw(0xb4, dev->iobase + PCI171x_CNTCTRL); - outw(0x74, dev->iobase + PCI171x_CNTCTRL); - - if (mode == 1) { - outw(divisor2 & 0xff, dev->iobase + PCI171x_CNT2); - outw((divisor2 >> 8) & 0xff, dev->iobase + PCI171x_CNT2); - outw(divisor1 & 0xff, dev->iobase + PCI171x_CNT1); - outw((divisor1 >> 8) & 0xff, dev->iobase + PCI171x_CNT1); - } -} - /* ============================================================================== */ @@ -613,7 +486,6 @@ static int pci171x_insn_counter_write(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data) { - struct pci1710_private *devpriv = dev->private; uint msb, lsb, ccntrl, status; lsb = data[0] & 0x00FF; @@ -645,7 +517,6 @@ static int pci171x_insn_counter_config(struct comedi_device *dev, { #ifdef unused /* This doesn't work like a normal Comedi counter config */ - struct pci1710_private *devpriv = dev->private; uint ccntrl = 0; devpriv->cnt0_write_wait = data[0] & 0x20; @@ -681,7 +552,6 @@ static int pci1720_insn_write_ao(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - struct pci1710_private *devpriv = dev->private; int n, rangereg, chan; chan = CR_CHAN(insn->chanspec); @@ -702,50 +572,19 @@ static int pci1720_insn_write_ao(struct comedi_device *dev, return n; } -/* -============================================================================== -*/ -static int pci171x_ai_cancel(struct comedi_device *dev, - struct comedi_subdevice *s) -{ - const struct boardtype *this_board = comedi_board(dev); - struct pci1710_private *devpriv = dev->private; - - switch (this_board->cardtype) { - default: - devpriv->CntrlReg &= Control_CNT0; - devpriv->CntrlReg |= Control_SW; - - outw(devpriv->CntrlReg, dev->iobase + PCI171x_CONTROL); /* reset any operations */ - start_pacer(dev, -1, 0, 0); - outb(0, dev->iobase + PCI171x_CLRFIFO); - outb(0, dev->iobase + PCI171x_CLRINT); - break; - } - - devpriv->ai_do = 0; - devpriv->ai_act_scan = 0; - s->async->cur_chan = 0; - devpriv->ai_buf_ptr = 0; - devpriv->neverending_ai = 0; - - return 0; -} - /* ============================================================================== */ static void interrupt_pci1710_every_sample(void *d) { struct comedi_device *dev = d; - struct pci1710_private *devpriv = dev->private; - struct comedi_subdevice *s = &dev->subdevices[0]; + struct comedi_subdevice *s = dev->subdevices + 0; int m; #ifdef PCI171x_PARANOIDCHECK - const struct boardtype *this_board = comedi_board(dev); short sampl; #endif + DPRINTK("adv_pci1710 EDBG: BGN: interrupt_pci1710_every_sample(...)\n"); m = inw(dev->iobase + PCI171x_STATUS); if (m & Status_FE) { printk("comedi%d: A/D FIFO empty (%4x)\n", dev->minor, m); @@ -766,9 +605,11 @@ static void interrupt_pci1710_every_sample(void *d) outb(0, dev->iobase + PCI171x_CLRINT); /* clear our INT request */ + DPRINTK("FOR "); for (; !(inw(dev->iobase + PCI171x_STATUS) & Status_FE);) { #ifdef PCI171x_PARANOIDCHECK sampl = inw(dev->iobase + PCI171x_AD_DATA); + DPRINTK("%04x:", sampl); if (this_board->cardtype != TYPE_PCI1713) if ((sampl & 0xf000) != devpriv->act_chanlist[s->async->cur_chan]) { @@ -785,6 +626,8 @@ static void interrupt_pci1710_every_sample(void *d) comedi_event(dev, s); return; } + DPRINTK("%8d %2d %8d~", s->async->buf_int_ptr, + s->async->cur_chan, s->async->buf_int_count); comedi_buf_put(s->async, sampl & 0x0fff); #else comedi_buf_put(s->async, @@ -798,6 +641,11 @@ static void interrupt_pci1710_every_sample(void *d) if (s->async->cur_chan == 0) { /* one scan done */ devpriv->ai_act_scan++; + DPRINTK + ("adv_pci1710 EDBG: EOS1 bic %d bip %d buc %d bup %d\n", + s->async->buf_int_count, s->async->buf_int_ptr, + s->async->buf_user_count, s->async->buf_user_ptr); + DPRINTK("adv_pci1710 EDBG: EOS2\n"); if ((!devpriv->neverending_ai) && (devpriv->ai_act_scan >= devpriv->ai_scans)) { /* all data sampled */ @@ -810,6 +658,7 @@ static void interrupt_pci1710_every_sample(void *d) } outb(0, dev->iobase + PCI171x_CLRINT); /* clear our INT request */ + DPRINTK("adv_pci1710 EDBG: END: interrupt_pci1710_every_sample(...)\n"); comedi_event(dev, s); } @@ -820,13 +669,12 @@ static void interrupt_pci1710_every_sample(void *d) static int move_block_from_fifo(struct comedi_device *dev, struct comedi_subdevice *s, int n, int turn) { - struct pci1710_private *devpriv = dev->private; int i, j; #ifdef PCI171x_PARANOIDCHECK - const struct boardtype *this_board = comedi_board(dev); int sampl; #endif - + DPRINTK("adv_pci1710 EDBG: BGN: move_block_from_fifo(...,%d,%d)\n", n, + turn); j = s->async->cur_chan; for (i = 0; i < n; i++) { #ifdef PCI171x_PARANOIDCHECK @@ -857,6 +705,7 @@ static int move_block_from_fifo(struct comedi_device *dev, } } s->async->cur_chan = j; + DPRINTK("adv_pci1710 EDBG: END: move_block_from_fifo(...)\n"); return 0; } @@ -866,11 +715,10 @@ static int move_block_from_fifo(struct comedi_device *dev, static void interrupt_pci1710_half_fifo(void *d) { struct comedi_device *dev = d; - const struct boardtype *this_board = comedi_board(dev); - struct pci1710_private *devpriv = dev->private; - struct comedi_subdevice *s = &dev->subdevices[0]; + struct comedi_subdevice *s = dev->subdevices + 0; int m, samplesinbuf; + DPRINTK("adv_pci1710 EDBG: BGN: interrupt_pci1710_half_fifo(...)\n"); m = inw(dev->iobase + PCI171x_STATUS); if (!(m & Status_FH)) { printk("comedi%d: A/D FIFO not half full! (%4x)\n", @@ -912,6 +760,7 @@ static void interrupt_pci1710_half_fifo(void *d) return; } outb(0, dev->iobase + PCI171x_CLRINT); /* clear our INT request */ + DPRINTK("adv_pci1710 EDBG: END: interrupt_pci1710_half_fifo(...)\n"); comedi_event(dev, s); } @@ -922,14 +771,18 @@ static void interrupt_pci1710_half_fifo(void *d) static irqreturn_t interrupt_service_pci1710(int irq, void *d) { struct comedi_device *dev = d; - struct pci1710_private *devpriv = dev->private; + DPRINTK("adv_pci1710 EDBG: BGN: interrupt_service_pci1710(%d,...)\n", + irq); if (!dev->attached) /* is device attached? */ return IRQ_NONE; /* no, exit */ /* is this interrupt from our board? */ if (!(inw(dev->iobase + PCI171x_STATUS) & Status_IRQ)) return IRQ_NONE; /* no, exit */ + DPRINTK("adv_pci1710 EDBG: interrupt_service_pci1710() ST: %4x\n", + inw(dev->iobase + PCI171x_STATUS)); + if (devpriv->ai_et) { /* Switch from initial TRIG_EXT to TRIG_xxx. */ devpriv->ai_et = 0; devpriv->CntrlReg &= Control_CNT0; @@ -949,6 +802,7 @@ static irqreturn_t interrupt_service_pci1710(int irq, void *d) } else { interrupt_pci1710_half_fifo(d); } + DPRINTK("adv_pci1710 EDBG: END: interrupt_service_pci1710(...)\n"); return IRQ_HANDLED; } @@ -958,11 +812,11 @@ static irqreturn_t interrupt_service_pci1710(int irq, void *d) static int pci171x_ai_docmd_and_mode(int mode, struct comedi_device *dev, struct comedi_subdevice *s) { - const struct boardtype *this_board = comedi_board(dev); - struct pci1710_private *devpriv = dev->private; unsigned int divisor1 = 0, divisor2 = 0; unsigned int seglen; + DPRINTK("adv_pci1710 EDBG: BGN: pci171x_ai_docmd_and_mode(%d,...)\n", + mode); start_pacer(dev, -1, 0, 0); /* stop pacer */ seglen = check_channel_list(dev, s, devpriv->ai_chanlist, @@ -1015,6 +869,10 @@ static int pci171x_ai_docmd_and_mode(int mode, struct comedi_device *dev, i8253_cascade_ns_to_timer(devpriv->i8254_osc_base, &divisor1, &divisor2, &devpriv->ai_timer1, devpriv->ai_flags & TRIG_ROUND_MASK); + DPRINTK + ("adv_pci1710 EDBG: OSC base=%u div1=%u div2=%u timer=%u\n", + devpriv->i8254_osc_base, divisor1, divisor2, + devpriv->ai_timer1); outw(devpriv->CntrlReg, dev->iobase + PCI171x_CONTROL); if (mode != 2) { /* start pacer */ @@ -1030,9 +888,27 @@ static int pci171x_ai_docmd_and_mode(int mode, struct comedi_device *dev, break; } + DPRINTK("adv_pci1710 EDBG: END: pci171x_ai_docmd_and_mode(...)\n"); return 0; } +#ifdef PCI171X_EXTDEBUG +/* +============================================================================== +*/ +static void pci171x_cmdtest_out(int e, struct comedi_cmd *cmd) +{ + printk("adv_pci1710 e=%d startsrc=%x scansrc=%x convsrc=%x\n", e, + cmd->start_src, cmd->scan_begin_src, cmd->convert_src); + printk("adv_pci1710 e=%d startarg=%d scanarg=%d convarg=%d\n", e, + cmd->start_arg, cmd->scan_begin_arg, cmd->convert_arg); + printk("adv_pci1710 e=%d stopsrc=%x scanend=%x\n", e, cmd->stop_src, + cmd->scan_end_src); + printk("adv_pci1710 e=%d stoparg=%d scanendarg=%d chanlistlen=%d\n", + e, cmd->stop_arg, cmd->scan_end_arg, cmd->chanlist_len); +} +#endif + /* ============================================================================== */ @@ -1040,33 +916,83 @@ static int pci171x_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd) { - const struct boardtype *this_board = comedi_board(dev); - struct pci1710_private *devpriv = dev->private; int err = 0; int tmp; unsigned int divisor1 = 0, divisor2 = 0; - /* Step 1 : check if triggers are trivially valid */ + DPRINTK("adv_pci1710 EDBG: BGN: pci171x_ai_cmdtest(...)\n"); +#ifdef PCI171X_EXTDEBUG + pci171x_cmdtest_out(-1, cmd); +#endif + /* step 1: make sure trigger sources are trivially valid */ - err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_EXT); - err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_FOLLOW); - err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_TIMER | TRIG_EXT); - err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT); - err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE); + tmp = cmd->start_src; + cmd->start_src &= TRIG_NOW | TRIG_EXT; + if (!cmd->start_src || tmp != cmd->start_src) + err++; + + tmp = cmd->scan_begin_src; + cmd->scan_begin_src &= TRIG_FOLLOW; + if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) + err++; - if (err) + tmp = cmd->convert_src; + cmd->convert_src &= TRIG_TIMER | TRIG_EXT; + if (!cmd->convert_src || tmp != cmd->convert_src) + err++; + + tmp = cmd->scan_end_src; + cmd->scan_end_src &= TRIG_COUNT; + if (!cmd->scan_end_src || tmp != cmd->scan_end_src) + err++; + + tmp = cmd->stop_src; + cmd->stop_src &= TRIG_COUNT | TRIG_NONE; + if (!cmd->stop_src || tmp != cmd->stop_src) + err++; + + if (err) { +#ifdef PCI171X_EXTDEBUG + pci171x_cmdtest_out(1, cmd); +#endif + DPRINTK( + "adv_pci1710 EDBG: BGN: pci171x_ai_cmdtest(...) err=%d ret=1\n", + err); return 1; + } + + /* step2: make sure trigger srcs are unique and mutually compatible */ + + if (cmd->start_src != TRIG_NOW && cmd->start_src != TRIG_EXT) { + cmd->start_src = TRIG_NOW; + err++; + } - /* step 2a: make sure trigger sources are unique */ + if (cmd->scan_begin_src != TRIG_FOLLOW) { + cmd->scan_begin_src = TRIG_FOLLOW; + err++; + } - err |= cfc_check_trigger_is_unique(cmd->start_src); - err |= cfc_check_trigger_is_unique(cmd->convert_src); - err |= cfc_check_trigger_is_unique(cmd->stop_src); + if (cmd->convert_src != TRIG_TIMER && cmd->convert_src != TRIG_EXT) + err++; - /* step 2b: and mutually compatible */ + if (cmd->scan_end_src != TRIG_COUNT) { + cmd->scan_end_src = TRIG_COUNT; + err++; + } + + if (cmd->stop_src != TRIG_NONE && cmd->stop_src != TRIG_COUNT) + err++; - if (err) + if (err) { +#ifdef PCI171X_EXTDEBUG + pci171x_cmdtest_out(2, cmd); +#endif + DPRINTK( + "adv_pci1710 EDBG: BGN: pci171x_ai_cmdtest(...) err=%d ret=2\n", + err); return 2; + } /* step 3: make sure arguments are trivially compatible */ @@ -1108,8 +1034,15 @@ static int pci171x_ai_cmdtest(struct comedi_device *dev, } } - if (err) + if (err) { +#ifdef PCI171X_EXTDEBUG + pci171x_cmdtest_out(3, cmd); +#endif + DPRINTK( + "adv_pci1710 EDBG: BGN: pci171x_ai_cmdtest(...) err=%d ret=3\n", + err); return 3; + } /* step 4: fix up any arguments */ @@ -1124,8 +1057,12 @@ static int pci171x_ai_cmdtest(struct comedi_device *dev, err++; } - if (err) + if (err) { + DPRINTK + ("adv_pci1710 EDBG: BGN: pci171x_ai_cmdtest(...) err=%d ret=4\n", + err); return 4; + } /* step 5: complain about special chanlist considerations */ @@ -1135,6 +1072,7 @@ static int pci171x_ai_cmdtest(struct comedi_device *dev, return 5; /* incorrect channels list */ } + DPRINTK("adv_pci1710 EDBG: BGN: pci171x_ai_cmdtest(...) ret=0\n"); return 0; } @@ -1143,9 +1081,9 @@ static int pci171x_ai_cmdtest(struct comedi_device *dev, */ static int pci171x_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) { - struct pci1710_private *devpriv = dev->private; struct comedi_cmd *cmd = &s->async->cmd; + DPRINTK("adv_pci1710 EDBG: BGN: pci171x_ai_cmd(...)\n"); devpriv->ai_n_chan = cmd->chanlist_len; devpriv->ai_chanlist = cmd->chanlist; devpriv->ai_flags = cmd->flags; @@ -1177,12 +1115,162 @@ static int pci171x_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) /* ============================================================================== + Check if channel list from user is builded correctly + If it's ok, then program scan/gain logic. + This works for all cards. */ -static int pci171x_reset(struct comedi_device *dev) +static int check_channel_list(struct comedi_device *dev, + struct comedi_subdevice *s, + unsigned int *chanlist, unsigned int n_chan) { - const struct boardtype *this_board = comedi_board(dev); - struct pci1710_private *devpriv = dev->private; + unsigned int chansegment[32]; + unsigned int i, nowmustbechan, seglen, segpos; + DPRINTK("adv_pci1710 EDBG: check_channel_list(...,%d)\n", n_chan); + /* correct channel and range number check itself comedi/range.c */ + if (n_chan < 1) { + comedi_error(dev, "range/channel list is empty!"); + return 0; + } + + if (n_chan == 1) + return 1; /* seglen=1 */ + + chansegment[0] = chanlist[0]; /* first channel is every time ok */ + for (i = 1, seglen = 1; i < n_chan; i++, seglen++) { + if (chanlist[0] == chanlist[i]) + break; /* we detected a loop, stop */ + if ((CR_CHAN(chanlist[i]) & 1) && + (CR_AREF(chanlist[i]) == AREF_DIFF)) { + comedi_error(dev, "Odd channel cannot be differential input!\n"); + return 0; + } + nowmustbechan = (CR_CHAN(chansegment[i - 1]) + 1) % s->n_chan; + if (CR_AREF(chansegment[i - 1]) == AREF_DIFF) + nowmustbechan = (nowmustbechan + 1) % s->n_chan; + if (nowmustbechan != CR_CHAN(chanlist[i])) { + printk("channel list must be continuous! chanlist[%i]=%d but must be %d or %d!\n", + i, CR_CHAN(chanlist[i]), nowmustbechan, + CR_CHAN(chanlist[0])); + return 0; + } + chansegment[i] = chanlist[i]; /* next correct channel in list */ + } + + for (i = 0, segpos = 0; i < n_chan; i++) { + if (chanlist[i] != chansegment[i % seglen]) { + printk("bad channel, reference or range number! chanlist[%i]=%d,%d,%d and not %d,%d,%d!\n", + i, CR_CHAN(chansegment[i]), + CR_RANGE(chansegment[i]), + CR_AREF(chansegment[i]), + CR_CHAN(chanlist[i % seglen]), + CR_RANGE(chanlist[i % seglen]), + CR_AREF(chansegment[i % seglen])); + return 0; + } + } + return seglen; +} + +static void setup_channel_list(struct comedi_device *dev, + struct comedi_subdevice *s, + unsigned int *chanlist, unsigned int n_chan, + unsigned int seglen) +{ + unsigned int i, range, chanprog; + + DPRINTK("adv_pci1710 EDBG: setup_channel_list(...,%d,%d)\n", n_chan, + seglen); + devpriv->act_chanlist_len = seglen; + devpriv->act_chanlist_pos = 0; + + DPRINTK("SegLen: %d\n", seglen); + for (i = 0; i < seglen; i++) { /* store range list to card */ + chanprog = muxonechan[CR_CHAN(chanlist[i])]; + outw(chanprog, dev->iobase + PCI171x_MUX); /* select channel */ + range = this_board->rangecode_ai[CR_RANGE(chanlist[i])]; + if (CR_AREF(chanlist[i]) == AREF_DIFF) + range |= 0x0020; + outw(range, dev->iobase + PCI171x_RANGE); /* select gain */ +#ifdef PCI171x_PARANOIDCHECK + devpriv->act_chanlist[i] = + (CR_CHAN(chanlist[i]) << 12) & 0xf000; +#endif + DPRINTK("GS: %2d. [%4x]=%4x %4x\n", i, chanprog, range, + devpriv->act_chanlist[i]); + } +#ifdef PCI171x_PARANOIDCHECK + for ( ; i < n_chan; i++) { /* store remainder of channel list */ + devpriv->act_chanlist[i] = + (CR_CHAN(chanlist[i]) << 12) & 0xf000; + } +#endif + + devpriv->ai_et_MuxVal = + CR_CHAN(chanlist[0]) | (CR_CHAN(chanlist[seglen - 1]) << 8); + /* select channel interval to scan */ + outw(devpriv->ai_et_MuxVal, dev->iobase + PCI171x_MUX); + DPRINTK("MUX: %4x L%4x.H%4x\n", + CR_CHAN(chanlist[0]) | (CR_CHAN(chanlist[seglen - 1]) << 8), + CR_CHAN(chanlist[0]), CR_CHAN(chanlist[seglen - 1])); +} + +/* +============================================================================== +*/ +static void start_pacer(struct comedi_device *dev, int mode, + unsigned int divisor1, unsigned int divisor2) +{ + DPRINTK("adv_pci1710 EDBG: BGN: start_pacer(%d,%u,%u)\n", mode, + divisor1, divisor2); + outw(0xb4, dev->iobase + PCI171x_CNTCTRL); + outw(0x74, dev->iobase + PCI171x_CNTCTRL); + + if (mode == 1) { + outw(divisor2 & 0xff, dev->iobase + PCI171x_CNT2); + outw((divisor2 >> 8) & 0xff, dev->iobase + PCI171x_CNT2); + outw(divisor1 & 0xff, dev->iobase + PCI171x_CNT1); + outw((divisor1 >> 8) & 0xff, dev->iobase + PCI171x_CNT1); + } + DPRINTK("adv_pci1710 EDBG: END: start_pacer(...)\n"); +} + +/* +============================================================================== +*/ +static int pci171x_ai_cancel(struct comedi_device *dev, + struct comedi_subdevice *s) +{ + DPRINTK("adv_pci1710 EDBG: BGN: pci171x_ai_cancel(...)\n"); + + switch (this_board->cardtype) { + default: + devpriv->CntrlReg &= Control_CNT0; + devpriv->CntrlReg |= Control_SW; + + outw(devpriv->CntrlReg, dev->iobase + PCI171x_CONTROL); /* reset any operations */ + start_pacer(dev, -1, 0, 0); + outb(0, dev->iobase + PCI171x_CLRFIFO); + outb(0, dev->iobase + PCI171x_CLRINT); + break; + } + + devpriv->ai_do = 0; + devpriv->ai_act_scan = 0; + s->async->cur_chan = 0; + devpriv->ai_buf_ptr = 0; + devpriv->neverending_ai = 0; + + DPRINTK("adv_pci1710 EDBG: END: pci171x_ai_cancel(...)\n"); + return 0; +} + +/* +============================================================================== +*/ +static int pci171x_reset(struct comedi_device *dev) +{ + DPRINTK("adv_pci1710 EDBG: BGN: pci171x_reset(...)\n"); outw(0x30, dev->iobase + PCI171x_CNTCTRL); devpriv->CntrlReg = Control_SW | Control_CNT0; /* Software trigger, CNT0=external */ outw(devpriv->CntrlReg, dev->iobase + PCI171x_CONTROL); /* reset any operations */ @@ -1203,6 +1291,7 @@ static int pci171x_reset(struct comedi_device *dev) outb(0, dev->iobase + PCI171x_CLRFIFO); /* clear FIFO */ outb(0, dev->iobase + PCI171x_CLRINT); /* clear INT request */ + DPRINTK("adv_pci1710 EDBG: END: pci171x_reset(...)\n"); return 0; } @@ -1211,8 +1300,7 @@ static int pci171x_reset(struct comedi_device *dev) */ static int pci1720_reset(struct comedi_device *dev) { - struct pci1710_private *devpriv = dev->private; - + DPRINTK("adv_pci1710 EDBG: BGN: pci1720_reset(...)\n"); outb(Syncont_SC0, dev->iobase + PCI1720_SYNCONT); /* set synchronous output mode */ devpriv->da_ranges = 0xAA; outb(devpriv->da_ranges, dev->iobase + PCI1720_RANGE); /* set all ranges to +/-5V */ @@ -1225,6 +1313,7 @@ static int pci1720_reset(struct comedi_device *dev) devpriv->ao_data[1] = 0x0800; devpriv->ao_data[2] = 0x0800; devpriv->ao_data[3] = 0x0800; + DPRINTK("adv_pci1710 EDBG: END: pci1720_reset(...)\n"); return 0; } @@ -1233,55 +1322,85 @@ static int pci1720_reset(struct comedi_device *dev) */ static int pci1710_reset(struct comedi_device *dev) { - const struct boardtype *this_board = comedi_board(dev); - + DPRINTK("adv_pci1710 EDBG: BGN: pci1710_reset(...)\n"); switch (this_board->cardtype) { case TYPE_PCI1720: return pci1720_reset(dev); default: return pci171x_reset(dev); } + DPRINTK("adv_pci1710 EDBG: END: pci1710_reset(...)\n"); } -static const void *pci1710_find_boardinfo(struct comedi_device *dev, - struct pci_dev *pcidev) +static struct pci_dev *pci1710_find_pci_dev(struct comedi_device *dev, + struct comedi_devconfig *it) { - const struct boardtype *this_board; + struct pci_dev *pcidev = NULL; + int bus = it->options[0]; + int slot = it->options[1]; + int board_index = this_board - boardtypes; int i; - for (i = 0; i < ARRAY_SIZE(boardtypes); i++) { - this_board = &boardtypes[i]; - if (pcidev->device == this_board->device_id) - return this_board; + for_each_pci_dev(pcidev) { + if (bus || slot) { + if (bus != pcidev->bus->number || + slot != PCI_SLOT(pcidev->devfn)) + continue; + } + if (pcidev->vendor != PCI_VENDOR_ID_ADVANTECH) + continue; + if (pci_is_enabled(pcidev)) + continue; + + if (strcmp(this_board->name, DRV_NAME) == 0) { + for (i = 0; i < ARRAY_SIZE(boardtypes); ++i) { + if (pcidev->device == boardtypes[i].device_id) { + board_index = i; + break; + } + } + if (i == ARRAY_SIZE(boardtypes)) + continue; + } else { + if (pcidev->device != boardtypes[board_index].device_id) + continue; + } + dev->board_ptr = &boardtypes[board_index]; + return pcidev; } + dev_err(dev->class_dev, + "No supported board found! (req. bus %d, slot %d)\n", + bus, slot); return NULL; } -static int pci1710_attach_pci(struct comedi_device *dev, - struct pci_dev *pcidev) +static int pci1710_attach(struct comedi_device *dev, + struct comedi_devconfig *it) { - const struct boardtype *this_board; - struct pci1710_private *devpriv; + struct pci_dev *pcidev; struct comedi_subdevice *s; int ret, subdev, n_subdevices; + unsigned int irq; - comedi_set_hw_dev(dev, &pcidev->dev); + dev_info(dev->class_dev, DRV_NAME ": attach\n"); - this_board = pci1710_find_boardinfo(dev, pcidev); - if (!this_board) - return -ENODEV; - dev->board_ptr = this_board; - dev->board_name = this_board->name; - - ret = alloc_private(dev, sizeof(*devpriv)); + ret = alloc_private(dev, sizeof(struct pci1710_private)); if (ret < 0) - return ret; - devpriv = dev->private; + return -ENOMEM; - ret = comedi_pci_enable(pcidev, dev->board_name); + pcidev = pci1710_find_pci_dev(dev, it); + if (!pcidev) + return -EIO; + comedi_set_hw_dev(dev, &pcidev->dev); + + ret = comedi_pci_enable(pcidev, DRV_NAME); if (ret) return ret; + dev->iobase = pci_resource_start(pcidev, 2); + irq = pcidev->irq; + + dev->board_name = this_board->name; n_subdevices = 0; if (this_board->n_aichan) @@ -1301,17 +1420,30 @@ static int pci1710_attach_pci(struct comedi_device *dev, pci1710_reset(dev); - if (this_board->have_irq && pcidev->irq) { - ret = request_irq(pcidev->irq, interrupt_service_pci1710, - IRQF_SHARED, dev->board_name, dev); - if (ret == 0) - dev->irq = pcidev->irq; + if (this_board->have_irq) { + if (irq) { + if (request_irq(irq, interrupt_service_pci1710, + IRQF_SHARED, "Advantech PCI-1710", + dev)) { + dev_dbg(dev->class_dev, + "unable to allocate IRQ %d, DISABLING IT", + irq); + irq = 0; /* Can't use IRQ */ + } else { + dev_dbg(dev->class_dev, "irq=%u", irq); + } + } else { + dev_dbg(dev->class_dev, "IRQ disabled"); + } + } else { + irq = 0; } + dev->irq = irq; subdev = 0; if (this_board->n_aichan) { - s = &dev->subdevices[subdev]; + s = dev->subdevices + subdev; dev->read_subdev = s; s->type = COMEDI_SUBD_AI; s->subdev_flags = SDF_READABLE | SDF_COMMON | SDF_GROUND; @@ -1323,7 +1455,7 @@ static int pci1710_attach_pci(struct comedi_device *dev, s->range_table = this_board->rangelist_ai; s->cancel = pci171x_ai_cancel; s->insn_read = pci171x_insn_read_ai; - if (dev->irq) { + if (irq) { s->subdev_flags |= SDF_CMD_READ; s->do_cmdtest = pci171x_ai_cmdtest; s->do_cmd = pci171x_ai_cmd; @@ -1333,7 +1465,7 @@ static int pci1710_attach_pci(struct comedi_device *dev, } if (this_board->n_aochan) { - s = &dev->subdevices[subdev]; + s = dev->subdevices + subdev; s->type = COMEDI_SUBD_AO; s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_COMMON; s->n_chan = this_board->n_aochan; @@ -1353,7 +1485,7 @@ static int pci1710_attach_pci(struct comedi_device *dev, } if (this_board->n_dichan) { - s = &dev->subdevices[subdev]; + s = dev->subdevices + subdev; s->type = COMEDI_SUBD_DI; s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_COMMON; s->n_chan = this_board->n_dichan; @@ -1366,7 +1498,7 @@ static int pci1710_attach_pci(struct comedi_device *dev, } if (this_board->n_dochan) { - s = &dev->subdevices[subdev]; + s = dev->subdevices + subdev; s->type = COMEDI_SUBD_DO; s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_COMMON; s->n_chan = this_board->n_dochan; @@ -1381,7 +1513,7 @@ static int pci1710_attach_pci(struct comedi_device *dev, } if (this_board->n_counter) { - s = &dev->subdevices[subdev]; + s = dev->subdevices + subdev; s->type = COMEDI_SUBD_COUNTER; s->subdev_flags = SDF_READABLE | SDF_WRITABLE; s->n_chan = this_board->n_counter; @@ -1394,8 +1526,7 @@ static int pci1710_attach_pci(struct comedi_device *dev, subdev++; } - dev_info(dev->class_dev, "%s attached, irq %sabled\n", - dev->board_name, dev->irq ? "en" : "dis"); + devpriv->valid = 1; return 0; } @@ -1404,21 +1535,27 @@ static void pci1710_detach(struct comedi_device *dev) { struct pci_dev *pcidev = comedi_to_pci_dev(dev); - if (dev->iobase) - pci1710_reset(dev); - if (dev->irq) - free_irq(dev->irq, dev); + if (dev->private) { + if (devpriv->valid) + pci1710_reset(dev); + if (dev->irq) + free_irq(dev->irq, dev); + } if (pcidev) { if (dev->iobase) comedi_pci_disable(pcidev); + pci_dev_put(pcidev); } } static struct comedi_driver adv_pci1710_driver = { .driver_name = "adv_pci1710", .module = THIS_MODULE, - .attach_pci = pci1710_attach_pci, + .attach = pci1710_attach, .detach = pci1710_detach, + .num_names = ARRAY_SIZE(boardtypes), + .board_name = &boardtypes[0].name, + .offset = sizeof(struct boardtype), }; static int __devinit adv_pci1710_pci_probe(struct pci_dev *dev, diff --git a/trunk/drivers/staging/comedi/drivers/adv_pci1723.c b/trunk/drivers/staging/comedi/drivers/adv_pci1723.c index df4efc0606de..da5ee69d2c9d 100644 --- a/trunk/drivers/staging/comedi/drivers/adv_pci1723.c +++ b/trunk/drivers/staging/comedi/drivers/adv_pci1723.c @@ -52,6 +52,11 @@ configures all channels in the same group. #define PCI_VENDOR_ID_ADVANTECH 0x13fe /* Advantech PCI vendor ID */ +/* hardware types of the cards */ +#define TYPE_PCI1723 0 + +#define IORANGE_1723 0x2A + /* all the registers for the pci1723 board */ #define PCI1723_DA(N) ((N)<<1) /* W: D/A register N (0 to 7) */ @@ -107,18 +112,63 @@ configures all channels in the same group. #define PCI1723_SELECT_CALIBRATION 0x28 /* Select the calibration Ref_V */ +/* static unsigned short pci_list_builded=0; =1 list of card is know */ + +static const struct comedi_lrange range_pci1723 = { 1, { + BIP_RANGE(10) + } +}; + +/* + * Board descriptions for pci1723 boards. + */ +struct pci1723_board { + const char *name; + int vendor_id; /* PCI vendor a device ID of card */ + int device_id; + int iorange; + char cardtype; + int n_aochan; /* num of D/A chans */ + int n_diochan; /* num of DIO chans */ + int ao_maxdata; /* resolution of D/A */ + const struct comedi_lrange *rangelist_ao; /* rangelist for D/A */ +}; + +static const struct pci1723_board boardtypes[] = { + { + .name = "pci1723", + .vendor_id = PCI_VENDOR_ID_ADVANTECH, + .device_id = 0x1723, + .iorange = IORANGE_1723, + .cardtype = TYPE_PCI1723, + .n_aochan = 8, + .n_diochan = 16, + .ao_maxdata = 0xffff, + .rangelist_ao = &range_pci1723, + }, +}; + +/* This structure is for data unique to this hardware driver. */ struct pci1723_private { + int valid; /* card is usable; */ + unsigned char da_range[8]; /* D/A output range for each channel */ + short ao_data[8]; /* data output buffer */ }; +/* The following macro to make it easy to access the private structure. */ +#define devpriv ((struct pci1723_private *)dev->private) + +#define this_board boardtypes + /* * The pci1723 card reset; */ static int pci1723_reset(struct comedi_device *dev) { - struct pci1723_private *devpriv = dev->private; int i; + DPRINTK("adv_pci1723 EDBG: BGN: pci1723_reset(...)\n"); outw(0x01, dev->iobase + PCI1723_SYN_SET); /* set synchronous output mode */ @@ -140,6 +190,7 @@ static int pci1723_reset(struct comedi_device *dev) /* set asynchronous output mode */ outw(0, dev->iobase + PCI1723_SYN_SET); + DPRINTK("adv_pci1723 EDBG: END: pci1723_reset(...)\n"); return 0; } @@ -147,10 +198,10 @@ static int pci1723_insn_read_ao(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - struct pci1723_private *devpriv = dev->private; int n, chan; chan = CR_CHAN(insn->chanspec); + DPRINTK(" adv_PCI1723 DEBUG: pci1723_insn_read_ao() -----\n"); for (n = 0; n < insn->n; n++) data[n] = devpriv->ao_data[chan]; @@ -164,10 +215,11 @@ static int pci1723_ao_write_winsn(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - struct pci1723_private *devpriv = dev->private; int n, chan; chan = CR_CHAN(insn->chanspec); + DPRINTK("PCI1723: the pci1723_ao_write_winsn() ------\n"); + for (n = 0; n < insn->n; n++) { devpriv->ao_data[chan] = data[n]; @@ -234,72 +286,125 @@ static int pci1723_dio_insn_bits(struct comedi_device *dev, return insn->n; } -static int pci1723_attach_pci(struct comedi_device *dev, - struct pci_dev *pcidev) +static struct pci_dev *pci1723_find_pci_dev(struct comedi_device *dev, + struct comedi_devconfig *it) { - struct pci1723_private *devpriv; + struct pci_dev *pcidev = NULL; + int bus = it->options[0]; + int slot = it->options[1]; + + for_each_pci_dev(pcidev) { + if (bus || slot) { + if (bus != pcidev->bus->number || + slot != PCI_SLOT(pcidev->devfn)) + continue; + } + if (pcidev->vendor != PCI_VENDOR_ID_ADVANTECH) + continue; + if (pci_is_enabled(pcidev)) + continue; + return pcidev; + } + dev_err(dev->class_dev, + "No supported board found! (req. bus %d, slot %d)\n", + bus, slot); + return NULL; +} + +static int pci1723_attach(struct comedi_device *dev, + struct comedi_devconfig *it) +{ + struct pci_dev *pcidev; struct comedi_subdevice *s; - int ret; + int ret, subdev, n_subdevices; - comedi_set_hw_dev(dev, &pcidev->dev); - dev->board_name = dev->driver->driver_name; + printk(KERN_ERR "comedi%d: adv_pci1723: board=%s", + dev->minor, this_board->name); - ret = alloc_private(dev, sizeof(*devpriv)); - if (ret < 0) - return ret; - devpriv = dev->private; + ret = alloc_private(dev, sizeof(struct pci1723_private)); + if (ret < 0) { + printk(" - Allocation failed!\n"); + return -ENOMEM; + } + + pcidev = pci1723_find_pci_dev(dev, it); + if (!pcidev) + return -EIO; + comedi_set_hw_dev(dev, &pcidev->dev); - ret = comedi_pci_enable(pcidev, dev->board_name); + ret = comedi_pci_enable(pcidev, "adv_pci1723"); if (ret) return ret; + dev->iobase = pci_resource_start(pcidev, 2); - ret = comedi_alloc_subdevices(dev, 2); + dev->board_name = this_board->name; + + n_subdevices = 0; + + if (this_board->n_aochan) + n_subdevices++; + if (this_board->n_diochan) + n_subdevices++; + + ret = comedi_alloc_subdevices(dev, n_subdevices); if (ret) return ret; - s = &dev->subdevices[0]; - dev->write_subdev = s; - s->type = COMEDI_SUBD_AO; - s->subdev_flags = SDF_WRITEABLE | SDF_GROUND | SDF_COMMON; - s->n_chan = 8; - s->maxdata = 0xffff; - s->len_chanlist = 8; - s->range_table = &range_bipolar10; - s->insn_write = pci1723_ao_write_winsn; - s->insn_read = pci1723_insn_read_ao; - - s = &dev->subdevices[1]; - s->type = COMEDI_SUBD_DIO; - s->subdev_flags = SDF_READABLE | SDF_WRITABLE; - s->n_chan = 16; - s->maxdata = 1; - s->len_chanlist = 16; - s->range_table = &range_digital; - s->insn_config = pci1723_dio_insn_config; - s->insn_bits = pci1723_dio_insn_bits; - - /* read DIO config */ - switch (inw(dev->iobase + PCI1723_DIGITAL_IO_PORT_MODE) & 0x03) { - case 0x00: /* low byte output, high byte output */ - s->io_bits = 0xFFFF; - break; - case 0x01: /* low byte input, high byte output */ - s->io_bits = 0xFF00; - break; - case 0x02: /* low byte output, high byte input */ - s->io_bits = 0x00FF; - break; - case 0x03: /* low byte input, high byte input */ - s->io_bits = 0x0000; - break; + pci1723_reset(dev); + subdev = 0; + if (this_board->n_aochan) { + s = dev->subdevices + subdev; + dev->write_subdev = s; + s->type = COMEDI_SUBD_AO; + s->subdev_flags = SDF_WRITEABLE | SDF_GROUND | SDF_COMMON; + s->n_chan = this_board->n_aochan; + s->maxdata = this_board->ao_maxdata; + s->len_chanlist = this_board->n_aochan; + s->range_table = this_board->rangelist_ao; + + s->insn_write = pci1723_ao_write_winsn; + s->insn_read = pci1723_insn_read_ao; + + /* read DIO config */ + switch (inw(dev->iobase + PCI1723_DIGITAL_IO_PORT_MODE) + & 0x03) { + case 0x00: /* low byte output, high byte output */ + s->io_bits = 0xFFFF; + break; + case 0x01: /* low byte input, high byte output */ + s->io_bits = 0xFF00; + break; + case 0x02: /* low byte output, high byte input */ + s->io_bits = 0x00FF; + break; + case 0x03: /* low byte input, high byte input */ + s->io_bits = 0x0000; + break; + } + /* read DIO port state */ + s->state = inw(dev->iobase + PCI1723_READ_DIGITAL_INPUT_DATA); + + subdev++; } - /* read DIO port state */ - s->state = inw(dev->iobase + PCI1723_READ_DIGITAL_INPUT_DATA); - pci1723_reset(dev); + if (this_board->n_diochan) { + s = dev->subdevices + subdev; + s->type = COMEDI_SUBD_DIO; + s->subdev_flags = + SDF_READABLE | SDF_WRITABLE | SDF_GROUND | SDF_COMMON; + s->n_chan = this_board->n_diochan; + s->maxdata = 1; + s->len_chanlist = this_board->n_diochan; + s->range_table = &range_digital; + s->insn_config = pci1723_dio_insn_config; + s->insn_bits = pci1723_dio_insn_bits; + subdev++; + } - dev_info(dev->class_dev, "%s attached\n", dev->board_name); + devpriv->valid = 1; + + pci1723_reset(dev); return 0; } @@ -308,18 +413,21 @@ static void pci1723_detach(struct comedi_device *dev) { struct pci_dev *pcidev = comedi_to_pci_dev(dev); - if (pcidev) { - if (dev->iobase) { + if (dev->private) { + if (devpriv->valid) pci1723_reset(dev); + } + if (pcidev) { + if (dev->iobase) comedi_pci_disable(pcidev); - } + pci_dev_put(pcidev); } } static struct comedi_driver adv_pci1723_driver = { .driver_name = "adv_pci1723", .module = THIS_MODULE, - .attach_pci = pci1723_attach_pci, + .attach = pci1723_attach, .detach = pci1723_detach, }; diff --git a/trunk/drivers/staging/comedi/drivers/adv_pci_dio.c b/trunk/drivers/staging/comedi/drivers/adv_pci_dio.c index a3c22419cd5f..97f06dc8e48d 100644 --- a/trunk/drivers/staging/comedi/drivers/adv_pci_dio.c +++ b/trunk/drivers/staging/comedi/drivers/adv_pci_dio.c @@ -36,6 +36,15 @@ Configuration options: #include "8255.h" #include "8253.h" +#undef PCI_DIO_EXTDEBUG /* if defined, enable extensive debug logging */ + +#undef DPRINTK +#ifdef PCI_DIO_EXTDEBUG +#define DPRINTK(fmt, args...) printk(fmt, ## args) +#else +#define DPRINTK(fmt, args...) +#endif + #define PCI_VENDOR_ID_ADVANTECH 0x13fe /* hardware types of the cards */ @@ -241,7 +250,6 @@ struct dio_boardtype { int device_id; int main_pci_region; /* main I/O PCI region */ enum hw_cards_id cardtype; - int nsubdevs; struct diosubd_data sdi[MAX_DI_SUBDEVS]; /* DI chans */ struct diosubd_data sdo[MAX_DO_SUBDEVS]; /* DO chans */ struct diosubd_data sdio[MAX_DIO_SUBDEVG]; /* DIO 8255 chans */ @@ -251,164 +259,126 @@ struct dio_boardtype { }; static const struct dio_boardtype boardtypes[] = { - { - .name = "pci1730", - .vendor_id = PCI_VENDOR_ID_ADVANTECH, - .device_id = 0x1730, - .main_pci_region = PCIDIO_MAINREG, - .cardtype = TYPE_PCI1730, - .nsubdevs = 5, - .sdi[0] = { 16, PCI1730_DI, 2, 0, }, - .sdi[1] = { 16, PCI1730_IDI, 2, 0, }, - .sdo[0] = { 16, PCI1730_DO, 2, 0, }, - .sdo[1] = { 16, PCI1730_IDO, 2, 0, }, - .boardid = { 4, PCI173x_BOARDID, 1, SDF_INTERNAL, }, - .io_access = IO_8b, - }, { - .name = "pci1733", - .vendor_id = PCI_VENDOR_ID_ADVANTECH, - .device_id = 0x1733, - .main_pci_region = PCIDIO_MAINREG, - .cardtype = TYPE_PCI1733, - .nsubdevs = 2, - .sdi[1] = { 32, PCI1733_IDI, 4, 0, }, - .boardid = { 4, PCI173x_BOARDID, 1, SDF_INTERNAL, }, - .io_access = IO_8b, - }, { - .name = "pci1734", - .vendor_id = PCI_VENDOR_ID_ADVANTECH, - .device_id = 0x1734, - .main_pci_region = PCIDIO_MAINREG, - .cardtype = TYPE_PCI1734, - .nsubdevs = 2, - .sdo[1] = { 32, PCI1734_IDO, 4, 0, }, - .boardid = { 4, PCI173x_BOARDID, 1, SDF_INTERNAL, }, - .io_access = IO_8b, - }, { - .name = "pci1735", - .vendor_id = PCI_VENDOR_ID_ADVANTECH, - .device_id = 0x1735, - .main_pci_region = PCIDIO_MAINREG, - .cardtype = TYPE_PCI1735, - .nsubdevs = 4, - .sdi[0] = { 32, PCI1735_DI, 4, 0, }, - .sdo[0] = { 32, PCI1735_DO, 4, 0, }, - .boardid = { 4, PCI1735_BOARDID, 1, SDF_INTERNAL, }, - .s8254[0] = { 3, PCI1735_C8254, 1, 0, }, - .io_access = IO_8b, - }, { - .name = "pci1736", - .vendor_id = PCI_VENDOR_ID_ADVANTECH, - .device_id = 0x1736, - .main_pci_region = PCI1736_MAINREG, - .cardtype = TYPE_PCI1736, - .nsubdevs = 3, - .sdi[1] = { 16, PCI1736_IDI, 2, 0, }, - .sdo[1] = { 16, PCI1736_IDO, 2, 0, }, - .boardid = { 4, PCI1736_BOARDID, 1, SDF_INTERNAL, }, - .io_access = IO_8b, - }, { - .name = "pci1739", - .vendor_id = PCI_VENDOR_ID_ADVANTECH, - .device_id = 0x1739, - .main_pci_region = PCIDIO_MAINREG, - .cardtype = TYPE_PCI1739, - .nsubdevs = 2, - .sdio[0] = { 48, PCI1739_DIO, 2, 0, }, - .io_access = IO_8b, - }, { - .name = "pci1750", - .vendor_id = PCI_VENDOR_ID_ADVANTECH, - .device_id = 0x1750, - .main_pci_region = PCIDIO_MAINREG, - .cardtype = TYPE_PCI1750, - .nsubdevs = 2, - .sdi[1] = { 16, PCI1750_IDI, 2, 0, }, - .sdo[1] = { 16, PCI1750_IDO, 2, 0, }, - .io_access = IO_8b, - }, { - .name = "pci1751", - .vendor_id = PCI_VENDOR_ID_ADVANTECH, - .device_id = 0x1751, - .main_pci_region = PCIDIO_MAINREG, - .cardtype = TYPE_PCI1751, - .nsubdevs = 3, - .sdio[0] = { 48, PCI1751_DIO, 2, 0, }, - .s8254[0] = { 3, PCI1751_CNT, 1, 0, }, - .io_access = IO_8b, - }, { - .name = "pci1752", - .vendor_id = PCI_VENDOR_ID_ADVANTECH, - .device_id = 0x1752, - .main_pci_region = PCIDIO_MAINREG, - .cardtype = TYPE_PCI1752, - .nsubdevs = 3, - .sdo[0] = { 32, PCI1752_IDO, 2, 0, }, - .sdo[1] = { 32, PCI1752_IDO2, 2, 0, }, - .boardid = { 4, PCI175x_BOARDID, 1, SDF_INTERNAL, }, - .io_access = IO_16b, - }, { - .name = "pci1753", - .vendor_id = PCI_VENDOR_ID_ADVANTECH, - .device_id = 0x1753, - .main_pci_region = PCIDIO_MAINREG, - .cardtype = TYPE_PCI1753, - .nsubdevs = 4, - .sdio[0] = { 96, PCI1753_DIO, 4, 0, }, - .io_access = IO_8b, - }, { - .name = "pci1753e", - .vendor_id = PCI_VENDOR_ID_ADVANTECH, - .device_id = 0x1753, - .main_pci_region = PCIDIO_MAINREG, - .cardtype = TYPE_PCI1753E, - .nsubdevs = 8, - .sdio[0] = { 96, PCI1753_DIO, 4, 0, }, - .sdio[1] = { 96, PCI1753E_DIO, 4, 0, }, - .io_access = IO_8b, - }, { - .name = "pci1754", - .vendor_id = PCI_VENDOR_ID_ADVANTECH, - .device_id = 0x1754, - .main_pci_region = PCIDIO_MAINREG, - .cardtype = TYPE_PCI1754, - .nsubdevs = 3, - .sdi[0] = { 32, PCI1754_IDI, 2, 0, }, - .sdi[1] = { 32, PCI1754_IDI2, 2, 0, }, - .boardid = { 4, PCI175x_BOARDID, 1, SDF_INTERNAL, }, - .io_access = IO_16b, - }, { - .name = "pci1756", - .vendor_id = PCI_VENDOR_ID_ADVANTECH, - .device_id = 0x1756, - .main_pci_region = PCIDIO_MAINREG, - .cardtype = TYPE_PCI1756, - .nsubdevs = 3, - .sdi[1] = { 32, PCI1756_IDI, 2, 0, }, - .sdo[1] = { 32, PCI1756_IDO, 2, 0, }, - .boardid = { 4, PCI175x_BOARDID, 1, SDF_INTERNAL, }, - .io_access = IO_16b, - }, { - /* This card has its own 'attach' */ - .name = "pci1760", - .vendor_id = PCI_VENDOR_ID_ADVANTECH, - .device_id = 0x1760, - .main_pci_region = 0, - .cardtype = TYPE_PCI1760, - .nsubdevs = 4, - .io_access = IO_8b, - }, { - .name = "pci1762", - .vendor_id = PCI_VENDOR_ID_ADVANTECH, - .device_id = 0x1762, - .main_pci_region = PCIDIO_MAINREG, - .cardtype = TYPE_PCI1762, - .nsubdevs = 3, - .sdi[1] = { 16, PCI1762_IDI, 1, 0, }, - .sdo[1] = { 16, PCI1762_RO, 1, 0, }, - .boardid = { 4, PCI1762_BOARDID, 1, SDF_INTERNAL, }, - .io_access = IO_16b, - }, + {"pci1730", PCI_VENDOR_ID_ADVANTECH, 0x1730, PCIDIO_MAINREG, + TYPE_PCI1730, + { {16, PCI1730_DI, 2, 0}, {16, PCI1730_IDI, 2, 0} }, + { {16, PCI1730_DO, 2, 0}, {16, PCI1730_IDO, 2, 0} }, + { {0, 0, 0, 0}, {0, 0, 0, 0} }, + {4, PCI173x_BOARDID, 1, SDF_INTERNAL}, + { {0, 0, 0, 0} }, + IO_8b}, + {"pci1733", PCI_VENDOR_ID_ADVANTECH, 0x1733, PCIDIO_MAINREG, + TYPE_PCI1733, + { {0, 0, 0, 0}, {32, PCI1733_IDI, 4, 0} }, + { {0, 0, 0, 0}, {0, 0, 0, 0} }, + { {0, 0, 0, 0}, {0, 0, 0, 0} }, + {4, PCI173x_BOARDID, 1, SDF_INTERNAL}, + { {0, 0, 0, 0} }, + IO_8b}, + {"pci1734", PCI_VENDOR_ID_ADVANTECH, 0x1734, PCIDIO_MAINREG, + TYPE_PCI1734, + { {0, 0, 0, 0}, {0, 0, 0, 0} }, + { {0, 0, 0, 0}, {32, PCI1734_IDO, 4, 0} }, + { {0, 0, 0, 0}, {0, 0, 0, 0} }, + {4, PCI173x_BOARDID, 1, SDF_INTERNAL}, + { {0, 0, 0, 0} }, + IO_8b}, + {"pci1735", PCI_VENDOR_ID_ADVANTECH, 0x1735, PCIDIO_MAINREG, + TYPE_PCI1735, + { {32, PCI1735_DI, 4, 0}, {0, 0, 0, 0} }, + { {32, PCI1735_DO, 4, 0}, {0, 0, 0, 0} }, + { {0, 0, 0, 0}, {0, 0, 0, 0} }, + { 4, PCI1735_BOARDID, 1, SDF_INTERNAL}, + { {3, PCI1735_C8254, 1, 0} }, + IO_8b}, + {"pci1736", PCI_VENDOR_ID_ADVANTECH, 0x1736, PCI1736_MAINREG, + TYPE_PCI1736, + { {0, 0, 0, 0}, {16, PCI1736_IDI, 2, 0} }, + { {0, 0, 0, 0}, {16, PCI1736_IDO, 2, 0} }, + { {0, 0, 0, 0}, {0, 0, 0, 0} }, + {4, PCI1736_BOARDID, 1, SDF_INTERNAL}, + { {0, 0, 0, 0} }, + IO_8b}, + {"pci1739", PCI_VENDOR_ID_ADVANTECH, 0x1739, PCIDIO_MAINREG, + TYPE_PCI1739, + { {0, 0, 0, 0}, {0, 0, 0, 0} }, + { {0, 0, 0, 0}, {0, 0, 0, 0} }, + { {48, PCI1739_DIO, 2, 0}, {0, 0, 0, 0} }, + {0, 0, 0, 0}, + { {0, 0, 0, 0} }, + IO_8b}, + {"pci1750", PCI_VENDOR_ID_ADVANTECH, 0x1750, PCIDIO_MAINREG, + TYPE_PCI1750, + { {0, 0, 0, 0}, {16, PCI1750_IDI, 2, 0} }, + { {0, 0, 0, 0}, {16, PCI1750_IDO, 2, 0} }, + { {0, 0, 0, 0}, {0, 0, 0, 0} }, + {0, 0, 0, 0}, + { {0, 0, 0, 0} }, + IO_8b}, + {"pci1751", PCI_VENDOR_ID_ADVANTECH, 0x1751, PCIDIO_MAINREG, + TYPE_PCI1751, + { {0, 0, 0, 0}, {0, 0, 0, 0} }, + { {0, 0, 0, 0}, {0, 0, 0, 0} }, + { {48, PCI1751_DIO, 2, 0}, {0, 0, 0, 0} }, + {0, 0, 0, 0}, + { {3, PCI1751_CNT, 1, 0} }, + IO_8b}, + {"pci1752", PCI_VENDOR_ID_ADVANTECH, 0x1752, PCIDIO_MAINREG, + TYPE_PCI1752, + { {0, 0, 0, 0}, {0, 0, 0, 0} }, + { {32, PCI1752_IDO, 2, 0}, {32, PCI1752_IDO2, 2, 0} }, + { {0, 0, 0, 0}, {0, 0, 0, 0} }, + {4, PCI175x_BOARDID, 1, SDF_INTERNAL}, + { {0, 0, 0, 0} }, + IO_16b}, + {"pci1753", PCI_VENDOR_ID_ADVANTECH, 0x1753, PCIDIO_MAINREG, + TYPE_PCI1753, + { {0, 0, 0, 0}, {0, 0, 0, 0} }, + { {0, 0, 0, 0}, {0, 0, 0, 0} }, + { {96, PCI1753_DIO, 4, 0}, {0, 0, 0, 0} }, + {0, 0, 0, 0}, + { {0, 0, 0, 0} }, + IO_8b}, + {"pci1753e", PCI_VENDOR_ID_ADVANTECH, 0x1753, PCIDIO_MAINREG, + TYPE_PCI1753E, + { {0, 0, 0, 0}, {0, 0, 0, 0} }, + { {0, 0, 0, 0}, {0, 0, 0, 0} }, + { {96, PCI1753_DIO, 4, 0}, {96, PCI1753E_DIO, 4, 0} }, + {0, 0, 0, 0}, + { {0, 0, 0, 0} }, + IO_8b}, + {"pci1754", PCI_VENDOR_ID_ADVANTECH, 0x1754, PCIDIO_MAINREG, + TYPE_PCI1754, + { {32, PCI1754_IDI, 2, 0}, {32, PCI1754_IDI2, 2, 0} }, + { {0, 0, 0, 0}, {0, 0, 0, 0} }, + { {0, 0, 0, 0}, {0, 0, 0, 0} }, + {4, PCI175x_BOARDID, 1, SDF_INTERNAL}, + { {0, 0, 0, 0} }, + IO_16b}, + {"pci1756", PCI_VENDOR_ID_ADVANTECH, 0x1756, PCIDIO_MAINREG, + TYPE_PCI1756, + { {0, 0, 0, 0}, {32, PCI1756_IDI, 2, 0} }, + { {0, 0, 0, 0}, {32, PCI1756_IDO, 2, 0} }, + { {0, 0, 0, 0}, {0, 0, 0, 0} }, + {4, PCI175x_BOARDID, 1, SDF_INTERNAL}, + { {0, 0, 0, 0} }, + IO_16b}, + {"pci1760", PCI_VENDOR_ID_ADVANTECH, 0x1760, 0, + TYPE_PCI1760, + { {0, 0, 0, 0}, {0, 0, 0, 0} }, /* This card have own setup work */ + { {0, 0, 0, 0}, {0, 0, 0, 0} }, + { {0, 0, 0, 0}, {0, 0, 0, 0} }, + {0, 0, 0, 0}, + { {0, 0, 0, 0} }, + IO_8b}, + {"pci1762", PCI_VENDOR_ID_ADVANTECH, 0x1762, PCIDIO_MAINREG, + TYPE_PCI1762, + { {0, 0, 0, 0}, {16, PCI1762_IDI, 1, 0} }, + { {0, 0, 0, 0}, {16, PCI1762_RO, 1, 0} }, + { {0, 0, 0, 0}, {0, 0, 0, 0} }, + {4, PCI1762_BOARDID, 1, SDF_INTERNAL}, + { {0, 0, 0, 0} }, + IO_16b} }; struct pci_dio_private { @@ -431,6 +401,9 @@ struct pci_dio_private { unsigned short IDIFiltrHigh[8]; /* IDI's filter value high signal */ }; +#define devpriv ((struct pci_dio_private *)dev->private) +#define this_board ((const struct dio_boardtype *)dev->board_ptr) + /* ============================================================================== */ @@ -721,7 +694,6 @@ static int pci1760_insn_cnt_write(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - struct pci_dio_private *devpriv = dev->private; int ret; unsigned char chan = CR_CHAN(insn->chanspec) & 0x07; unsigned char bitmask = 1 << chan; @@ -764,7 +736,6 @@ static int pci1760_insn_cnt_write(struct comedi_device *dev, */ static int pci1760_reset(struct comedi_device *dev) { - struct pci_dio_private *devpriv = dev->private; int i; unsigned char omb[4] = { 0x00, 0x00, 0x00, 0x00 }; unsigned char imb[4]; @@ -845,7 +816,7 @@ static int pci1760_reset(struct comedi_device *dev) */ static int pci_dio_reset(struct comedi_device *dev) { - const struct dio_boardtype *this_board = comedi_board(dev); + DPRINTK("adv_pci_dio EDBG: BGN: pci171x_reset(...)\n"); switch (this_board->cardtype) { case TYPE_PCI1730: @@ -946,17 +917,21 @@ static int pci_dio_reset(struct comedi_device *dev) break; } + DPRINTK("adv_pci_dio EDBG: END: pci171x_reset(...)\n"); + return 0; } /* ============================================================================== */ -static int pci1760_attach(struct comedi_device *dev) +static int pci1760_attach(struct comedi_device *dev, + struct comedi_devconfig *it) { struct comedi_subdevice *s; + int subdev = 0; - s = &dev->subdevices[0]; + s = dev->subdevices + subdev; s->type = COMEDI_SUBD_DI; s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_COMMON; s->n_chan = 8; @@ -964,8 +939,9 @@ static int pci1760_attach(struct comedi_device *dev) s->len_chanlist = 8; s->range_table = &range_digital; s->insn_bits = pci1760_insn_bits_di; + subdev++; - s = &dev->subdevices[1]; + s = dev->subdevices + subdev; s->type = COMEDI_SUBD_DO; s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_COMMON; s->n_chan = 8; @@ -974,16 +950,18 @@ static int pci1760_attach(struct comedi_device *dev) s->range_table = &range_digital; s->state = 0; s->insn_bits = pci1760_insn_bits_do; + subdev++; - s = &dev->subdevices[2]; + s = dev->subdevices + subdev; s->type = COMEDI_SUBD_TIMER; s->subdev_flags = SDF_WRITABLE | SDF_LSAMPL; s->n_chan = 2; s->maxdata = 0xffffffff; s->len_chanlist = 2; /* s->insn_config=pci1760_insn_pwm_cfg; */ + subdev++; - s = &dev->subdevices[3]; + s = dev->subdevices + subdev; s->type = COMEDI_SUBD_COUNTER; s->subdev_flags = SDF_READABLE | SDF_WRITABLE; s->n_chan = 8; @@ -992,6 +970,7 @@ static int pci1760_attach(struct comedi_device *dev) s->insn_read = pci1760_insn_cnt_read; s->insn_write = pci1760_insn_cnt_write; /* s->insn_config=pci1760_insn_cnt_cfg; */ + subdev++; return 0; } @@ -999,12 +978,9 @@ static int pci1760_attach(struct comedi_device *dev) /* ============================================================================== */ -static int pci_dio_add_di(struct comedi_device *dev, - struct comedi_subdevice *s, - const struct diosubd_data *d) +static int pci_dio_add_di(struct comedi_device *dev, struct comedi_subdevice *s, + const struct diosubd_data *d, int subdev) { - const struct dio_boardtype *this_board = comedi_board(dev); - s->type = COMEDI_SUBD_DI; s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_COMMON | d->specflags; if (d->chans > 16) @@ -1029,12 +1005,9 @@ static int pci_dio_add_di(struct comedi_device *dev, /* ============================================================================== */ -static int pci_dio_add_do(struct comedi_device *dev, - struct comedi_subdevice *s, - const struct diosubd_data *d) +static int pci_dio_add_do(struct comedi_device *dev, struct comedi_subdevice *s, + const struct diosubd_data *d, int subdev) { - const struct dio_boardtype *this_board = comedi_board(dev); - s->type = COMEDI_SUBD_DO; s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_COMMON; if (d->chans > 16) @@ -1062,7 +1035,7 @@ static int pci_dio_add_do(struct comedi_device *dev, */ static int pci_dio_add_8254(struct comedi_device *dev, struct comedi_subdevice *s, - const struct diosubd_data *d) + const struct diosubd_data *d, int subdev) { s->type = COMEDI_SUBD_COUNTER; s->subdev_flags = SDF_WRITABLE | SDF_READABLE; @@ -1077,69 +1050,103 @@ static int pci_dio_add_8254(struct comedi_device *dev, return 0; } -static const void *pci_dio_find_boardinfo(struct comedi_device *dev, - struct pci_dev *pcidev) +static struct pci_dev *pci_dio_find_pci_dev(struct comedi_device *dev, + struct comedi_devconfig *it) { - const struct dio_boardtype *this_board; + struct pci_dev *pcidev = NULL; + int bus = it->options[0]; + int slot = it->options[1]; int i; - for (i = 0; i < ARRAY_SIZE(boardtypes); ++i) { - this_board = &boardtypes[i]; - if (this_board->vendor_id == pcidev->vendor && - this_board->device_id == pcidev->device) - return this_board; + for_each_pci_dev(pcidev) { + if (bus || slot) { + if (bus != pcidev->bus->number || + slot != PCI_SLOT(pcidev->devfn)) + continue; + } + if (pci_is_enabled(pcidev)) + continue; + for (i = 0; i < ARRAY_SIZE(boardtypes); ++i) { + if (boardtypes[i].vendor_id != pcidev->vendor) + continue; + if (boardtypes[i].device_id != pcidev->device) + continue; + dev->board_ptr = boardtypes + i; + return pcidev; + } } + dev_err(dev->class_dev, + "No supported board found! (req. bus %d, slot %d)\n", + bus, slot); return NULL; } -static int pci_dio_attach_pci(struct comedi_device *dev, - struct pci_dev *pcidev) +static int pci_dio_attach(struct comedi_device *dev, + struct comedi_devconfig *it) { - const struct dio_boardtype *this_board; - struct pci_dio_private *devpriv; + struct pci_dev *pcidev; struct comedi_subdevice *s; - int ret, subdev, i, j; + int ret, subdev, n_subdevices, i, j; - comedi_set_hw_dev(dev, &pcidev->dev); + ret = alloc_private(dev, sizeof(struct pci_dio_private)); + if (ret < 0) + return -ENOMEM; - this_board = pci_dio_find_boardinfo(dev, pcidev); - if (!this_board) - return -ENODEV; - dev->board_ptr = this_board; - dev->board_name = this_board->name; + pcidev = pci_dio_find_pci_dev(dev, it); + if (!pcidev) + return -EIO; + comedi_set_hw_dev(dev, &pcidev->dev); - ret = alloc_private(dev, sizeof(*devpriv)); - if (ret < 0) - return ret; - devpriv = dev->private; + if (comedi_pci_enable(pcidev, dev->driver->driver_name)) { + dev_err(dev->class_dev, + "Error: Can't enable PCI device and request regions!\n"); + return -EIO; + } - ret = comedi_pci_enable(pcidev, dev->board_name); - if (ret) - return ret; dev->iobase = pci_resource_start(pcidev, this_board->main_pci_region); + dev->board_name = this_board->name; - ret = comedi_alloc_subdevices(dev, this_board->nsubdevs); + if (this_board->cardtype == TYPE_PCI1760) { + n_subdevices = 4; /* 8 IDI, 8 IDO, 2 PWM, 8 CNT */ + } else { + n_subdevices = 0; + for (i = 0; i < MAX_DI_SUBDEVS; i++) + if (this_board->sdi[i].chans) + n_subdevices++; + for (i = 0; i < MAX_DO_SUBDEVS; i++) + if (this_board->sdo[i].chans) + n_subdevices++; + for (i = 0; i < MAX_DIO_SUBDEVG; i++) + n_subdevices += this_board->sdio[i].regs; + if (this_board->boardid.chans) + n_subdevices++; + for (i = 0; i < MAX_8254_SUBDEVS; i++) + if (this_board->s8254[i].chans) + n_subdevices++; + } + + ret = comedi_alloc_subdevices(dev, n_subdevices); if (ret) return ret; subdev = 0; for (i = 0; i < MAX_DI_SUBDEVS; i++) if (this_board->sdi[i].chans) { - s = &dev->subdevices[subdev]; - pci_dio_add_di(dev, s, &this_board->sdi[i]); + s = dev->subdevices + subdev; + pci_dio_add_di(dev, s, &this_board->sdi[i], subdev); subdev++; } for (i = 0; i < MAX_DO_SUBDEVS; i++) if (this_board->sdo[i].chans) { - s = &dev->subdevices[subdev]; - pci_dio_add_do(dev, s, &this_board->sdo[i]); + s = dev->subdevices + subdev; + pci_dio_add_do(dev, s, &this_board->sdo[i], subdev); subdev++; } for (i = 0; i < MAX_DIO_SUBDEVG; i++) for (j = 0; j < this_board->sdio[i].regs; j++) { - s = &dev->subdevices[subdev]; + s = dev->subdevices + subdev; subdev_8255_init(dev, s, NULL, dev->iobase + this_board->sdio[i].addr + @@ -1148,21 +1155,21 @@ static int pci_dio_attach_pci(struct comedi_device *dev, } if (this_board->boardid.chans) { - s = &dev->subdevices[subdev]; + s = dev->subdevices + subdev; s->type = COMEDI_SUBD_DI; - pci_dio_add_di(dev, s, &this_board->boardid); + pci_dio_add_di(dev, s, &this_board->boardid, subdev); subdev++; } for (i = 0; i < MAX_8254_SUBDEVS; i++) if (this_board->s8254[i].chans) { - s = &dev->subdevices[subdev]; - pci_dio_add_8254(dev, s, &this_board->s8254[i]); + s = dev->subdevices + subdev; + pci_dio_add_8254(dev, s, &this_board->s8254[i], subdev); subdev++; } if (this_board->cardtype == TYPE_PCI1760) - pci1760_attach(dev); + pci1760_attach(dev, it); devpriv->valid = 1; @@ -1173,34 +1180,52 @@ static int pci_dio_attach_pci(struct comedi_device *dev, static void pci_dio_detach(struct comedi_device *dev) { - struct pci_dio_private *devpriv = dev->private; struct pci_dev *pcidev = comedi_to_pci_dev(dev); + int i, j; struct comedi_subdevice *s; - int i; + int subdev; - if (devpriv) { + if (dev->private) { if (devpriv->valid) pci_dio_reset(dev); - } - if (dev->subdevices) { - for (i = 0; i < dev->n_subdevices; i++) { - s = &dev->subdevices[i]; - if (s->type == COMEDI_SUBD_DIO) + subdev = 0; + for (i = 0; i < MAX_DI_SUBDEVS; i++) { + if (this_board->sdi[i].chans) + subdev++; + } + for (i = 0; i < MAX_DO_SUBDEVS; i++) { + if (this_board->sdo[i].chans) + subdev++; + } + for (i = 0; i < MAX_DIO_SUBDEVG; i++) { + for (j = 0; j < this_board->sdio[i].regs; j++) { + s = dev->subdevices + subdev; subdev_8255_cleanup(dev, s); + subdev++; + } + } + if (this_board->boardid.chans) + subdev++; + for (i = 0; i < MAX_8254_SUBDEVS; i++) + if (this_board->s8254[i].chans) + subdev++; + for (i = 0; i < dev->n_subdevices; i++) { + s = dev->subdevices + i; s->private = NULL; } } if (pcidev) { if (dev->iobase) comedi_pci_disable(pcidev); + pci_dev_put(pcidev); } } static struct comedi_driver adv_pci_dio_driver = { .driver_name = "adv_pci_dio", .module = THIS_MODULE, - .attach_pci = pci_dio_attach_pci, - .detach = pci_dio_detach, + .attach = pci_dio_attach, + .detach = pci_dio_detach }; static int __devinit adv_pci_dio_pci_probe(struct pci_dev *dev, diff --git a/trunk/drivers/staging/comedi/drivers/aio_aio12_8.c b/trunk/drivers/staging/comedi/drivers/aio_aio12_8.c index 8acf60d0f20d..f7d453f8fe33 100644 --- a/trunk/drivers/staging/comedi/drivers/aio_aio12_8.c +++ b/trunk/drivers/staging/comedi/drivers/aio_aio12_8.c @@ -25,9 +25,8 @@ Driver: aio_aio12_8 Description: Access I/O Products PC-104 AIO12-8 Analog I/O Board Author: Pablo Mejia -Devices: [Access I/O] PC-104 AIO12-8 (aio_aio12_8) - [Access I/O] PC-104 AI12-8 (aio_ai12_8) - [Access I/O] PC-104 AO12-8 (aio_ao12_8) +Devices: + [Access I/O] PC-104 AIO12-8 Status: experimental Configuration Options: @@ -43,118 +42,91 @@ Configuration Options: #include #include "8255.h" -/* - * Register map - */ -#define AIO12_8_STATUS_REG 0x00 -#define AIO12_8_STATUS_ADC_EOC (1 << 7) -#define AIO12_8_STATUS_PORT_C_COS (1 << 6) -#define AIO12_8_STATUS_IRQ_ENA (1 << 2) -#define AIO12_8_INTERRUPT_REG 0x01 -#define AIO12_8_INTERRUPT_ADC (1 << 7) -#define AIO12_8_INTERRUPT_COS (1 << 6) -#define AIO12_8_INTERRUPT_COUNTER1 (1 << 5) -#define AIO12_8_INTERRUPT_PORT_C3 (1 << 4) -#define AIO12_8_INTERRUPT_PORT_C0 (1 << 3) -#define AIO12_8_INTERRUPT_ENA (1 << 2) -#define AIO12_8_ADC_REG 0x02 -#define AIO12_8_ADC_MODE_NORMAL (0 << 6) -#define AIO12_8_ADC_MODE_INT_CLK (1 << 6) -#define AIO12_8_ADC_MODE_STANDBY (2 << 6) -#define AIO12_8_ADC_MODE_POWERDOWN (3 << 6) -#define AIO12_8_ADC_ACQ_3USEC (0 << 5) -#define AIO12_8_ADC_ACQ_PROGRAM (1 << 5) -#define AIO12_8_ADC_RANGE(x) ((x) << 3) -#define AIO12_8_ADC_CHAN(x) ((x) << 0) -#define AIO12_8_DAC_REG(x) (0x04 + (x) * 2) -#define AIO12_8_8254_BASE_REG 0x0c -#define AIO12_8_8255_BASE_REG 0x10 -#define AIO12_8_DIO_CONTROL_REG 0x14 -#define AIO12_8_DIO_CONTROL_TST (1 << 0) -#define AIO12_8_ADC_TRIGGER_REG 0x15 -#define AIO12_8_ADC_TRIGGER_RANGE(x) ((x) << 3) -#define AIO12_8_ADC_TRIGGER_CHAN(x) ((x) << 0) -#define AIO12_8_TRIGGER_REG 0x16 -#define AIO12_8_TRIGGER_ADTRIG (1 << 1) -#define AIO12_8_TRIGGER_DACTRIG (1 << 0) -#define AIO12_8_COS_REG 0x17 -#define AIO12_8_DAC_ENABLE_REG 0x18 -#define AIO12_8_DAC_ENABLE_REF_ENA (1 << 0) +#define AIO12_8_STATUS 0x00 +#define AIO12_8_INTERRUPT 0x01 +#define AIO12_8_ADC 0x02 +#define AIO12_8_DAC_0 0x04 +#define AIO12_8_DAC_1 0x06 +#define AIO12_8_DAC_2 0x08 +#define AIO12_8_DAC_3 0x0A +#define AIO12_8_COUNTER_0 0x0C +#define AIO12_8_COUNTER_1 0x0D +#define AIO12_8_COUNTER_2 0x0E +#define AIO12_8_COUNTER_CONTROL 0x0F +#define AIO12_8_DIO_0 0x10 +#define AIO12_8_DIO_1 0x11 +#define AIO12_8_DIO_2 0x12 +#define AIO12_8_DIO_STATUS 0x13 +#define AIO12_8_DIO_CONTROL 0x14 +#define AIO12_8_ADC_TRIGGER_CONTROL 0x15 +#define AIO12_8_TRIGGER 0x16 +#define AIO12_8_POWER 0x17 + +#define STATUS_ADC_EOC 0x80 + +#define ADC_MODE_NORMAL 0x00 +#define ADC_MODE_INTERNAL_CLOCK 0x40 +#define ADC_MODE_STANDBY 0x80 +#define ADC_MODE_POWERDOWN 0xC0 + +#define DAC_ENABLE 0x18 struct aio12_8_boardtype { const char *name; - int ai_nchan; - int ao_nchan; }; static const struct aio12_8_boardtype board_types[] = { { - .name = "aio_aio12_8", - .ai_nchan = 8, - .ao_nchan = 4, - }, { - .name = "aio_ai12_8", - .ai_nchan = 8, - }, { - .name = "aio_ao12_8", - .ao_nchan = 4, - }, + .name = "aio_aio12_8"}, }; struct aio12_8_private { unsigned int ao_readback[4]; }; +#define devpriv ((struct aio12_8_private *) dev->private) + static int aio_aio12_8_ai_read(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - unsigned int chan = CR_CHAN(insn->chanspec); - unsigned int range = CR_RANGE(insn->chanspec); - unsigned int val; - unsigned char control; int n; + unsigned char control = + ADC_MODE_NORMAL | + (CR_RANGE(insn->chanspec) << 3) | CR_CHAN(insn->chanspec); - /* - * Setup the control byte for internal 2MHz clock, 3uS conversion, - * at the desired range of the requested channel. - */ - control = AIO12_8_ADC_MODE_NORMAL | AIO12_8_ADC_ACQ_3USEC | - AIO12_8_ADC_RANGE(range) | AIO12_8_ADC_CHAN(chan); - - /* Read status to clear EOC latch */ - inb(dev->iobase + AIO12_8_STATUS_REG); + /* read status to clear EOC latch */ + inb(dev->iobase + AIO12_8_STATUS); for (n = 0; n < insn->n; n++) { int timeout = 5; /* Setup and start conversion */ - outb(control, dev->iobase + AIO12_8_ADC_REG); + outb(control, dev->iobase + AIO12_8_ADC); /* Wait for conversion to complete */ - do { - val = inb(dev->iobase + AIO12_8_STATUS_REG); + while (timeout && + !(inb(dev->iobase + AIO12_8_STATUS) & STATUS_ADC_EOC)) { timeout--; - if (timeout == 0) { - dev_err(dev->class_dev, "ADC timeout\n"); - return -ETIMEDOUT; - } - } while (!(val & AIO12_8_STATUS_ADC_EOC)); - - data[n] = inw(dev->iobase + AIO12_8_ADC_REG) & s->maxdata; + printk(KERN_ERR "timeout %d\n", timeout); + udelay(1); + } + if (timeout == 0) { + comedi_error(dev, "ADC timeout"); + return -EIO; + } + + data[n] = inw(dev->iobase + AIO12_8_ADC) & 0x0FFF; } - - return insn->n; + return n; } static int aio_aio12_8_ao_read(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - struct aio12_8_private *devpriv = dev->private; - unsigned int chan = CR_CHAN(insn->chanspec); - int val = devpriv->ao_readback[chan]; int i; + int val = devpriv->ao_readback[CR_CHAN(insn->chanspec)]; for (i = 0; i < insn->n; i++) data[i] = val; @@ -165,22 +137,18 @@ static int aio_aio12_8_ao_write(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - struct aio12_8_private *devpriv = dev->private; - unsigned int chan = CR_CHAN(insn->chanspec); - unsigned long port = dev->iobase + AIO12_8_DAC_REG(chan); - unsigned int val = 0; int i; + int chan = CR_CHAN(insn->chanspec); + unsigned long port = dev->iobase + AIO12_8_DAC_0 + (2 * chan); /* enable DACs */ - outb(AIO12_8_DAC_ENABLE_REF_ENA, dev->iobase + AIO12_8_DAC_ENABLE_REG); + outb(0x01, dev->iobase + DAC_ENABLE); for (i = 0; i < insn->n; i++) { - val = data[i]; - outw(val, port); + outb(data[i] & 0xFF, port); /* LSB */ + outb((data[i] >> 8) & 0x0F, port + 1); /* MSB */ + devpriv->ao_readback[chan] = data[i]; } - - devpriv->ao_readback[chan] = val; - return insn->n; } @@ -198,77 +166,53 @@ static int aio_aio12_8_attach(struct comedi_device *dev, struct comedi_devconfig *it) { const struct aio12_8_boardtype *board = comedi_board(dev); - struct aio12_8_private *devpriv; - struct comedi_subdevice *s; int iobase; + struct comedi_subdevice *s; int ret; - dev->board_name = board->name; - iobase = it->options[0]; - if (!request_region(iobase, 32, dev->board_name)) { + if (!request_region(iobase, 24, "aio_aio12_8")) { printk(KERN_ERR "I/O port conflict"); return -EIO; } + + dev->board_name = board->name; + dev->iobase = iobase; - ret = alloc_private(dev, sizeof(*devpriv)); - if (ret) - return ret; - devpriv = dev->private; + if (alloc_private(dev, sizeof(struct aio12_8_private)) < 0) + return -ENOMEM; - ret = comedi_alloc_subdevices(dev, 4); + ret = comedi_alloc_subdevices(dev, 3); if (ret) return ret; s = &dev->subdevices[0]; - if (board->ai_nchan) { - /* Analog input subdevice */ - s->type = COMEDI_SUBD_AI; - s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DIFF; - s->n_chan = board->ai_nchan; - s->maxdata = 0x0fff; - s->range_table = &range_aio_aio12_8; - s->insn_read = aio_aio12_8_ai_read; - } else { - s->type = COMEDI_SUBD_UNUSED; - } + s->type = COMEDI_SUBD_AI; + s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DIFF; + s->n_chan = 8; + s->maxdata = (1 << 12) - 1; + s->range_table = &range_aio_aio12_8; + s->insn_read = aio_aio12_8_ai_read; s = &dev->subdevices[1]; - if (board->ao_nchan) { - /* Analog output subdevice */ - s->type = COMEDI_SUBD_AO; - s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_DIFF; - s->n_chan = 4; - s->maxdata = 0x0fff; - s->range_table = &range_aio_aio12_8; - s->insn_read = aio_aio12_8_ao_read; - s->insn_write = aio_aio12_8_ao_write; - } else { - s->type = COMEDI_SUBD_UNUSED; - } + s->type = COMEDI_SUBD_AO; + s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_DIFF; + s->n_chan = 4; + s->maxdata = (1 << 12) - 1; + s->range_table = &range_aio_aio12_8; + s->insn_read = aio_aio12_8_ao_read; + s->insn_write = aio_aio12_8_ao_write; s = &dev->subdevices[2]; - /* 8255 Digital i/o subdevice */ - iobase = dev->iobase + AIO12_8_8255_BASE_REG; - ret = subdev_8255_init(dev, s, NULL, iobase); - if (ret) - return ret; - - s = &dev->subdevices[3]; - /* 8254 counter/timer subdevice */ - s->type = COMEDI_SUBD_UNUSED; - - dev_info(dev->class_dev, "%s: %s attached\n", - dev->driver->driver_name, dev->board_name); + subdev_8255_init(dev, s, NULL, dev->iobase + AIO12_8_DIO_0); return 0; } static void aio_aio12_8_detach(struct comedi_device *dev) { - if (dev->subdevices) - subdev_8255_cleanup(dev, &dev->subdevices[2]); + subdev_8255_cleanup(dev, &dev->subdevices[2]); if (dev->iobase) release_region(dev->iobase, 24); } diff --git a/trunk/drivers/staging/comedi/drivers/aio_iiro_16.c b/trunk/drivers/staging/comedi/drivers/aio_iiro_16.c index b2cb8b02b2a1..ba1e3bbf2df8 100644 --- a/trunk/drivers/staging/comedi/drivers/aio_iiro_16.c +++ b/trunk/drivers/staging/comedi/drivers/aio_iiro_16.c @@ -112,7 +112,7 @@ static int aio_iiro_16_attach(struct comedi_device *dev, if (ret) return ret; - s = &dev->subdevices[0]; + s = dev->subdevices + 0; s->type = COMEDI_SUBD_DIO; s->subdev_flags = SDF_WRITABLE; s->n_chan = 16; @@ -120,7 +120,7 @@ static int aio_iiro_16_attach(struct comedi_device *dev, s->range_table = &range_digital; s->insn_bits = aio_iiro_16_dio_insn_bits_write; - s = &dev->subdevices[1]; + s = dev->subdevices + 1; s->type = COMEDI_SUBD_DIO; s->subdev_flags = SDF_READABLE; s->n_chan = 16; diff --git a/trunk/drivers/staging/comedi/drivers/amplc_dio200.c b/trunk/drivers/staging/comedi/drivers/amplc_dio200.c index 08f305210a69..6c81e377262c 100644 --- a/trunk/drivers/staging/comedi/drivers/amplc_dio200.c +++ b/trunk/drivers/staging/comedi/drivers/amplc_dio200.c @@ -210,15 +210,11 @@ order they appear in the channel list. #include "../comedidev.h" -#include "comedi_fc.h" #include "8255.h" #include "8253.h" #define DIO200_DRIVER_NAME "amplc_dio200" -#define DO_ISA IS_ENABLED(CONFIG_COMEDI_AMPLC_DIO200_ISA) -#define DO_PCI IS_ENABLED(CONFIG_COMEDI_AMPLC_DIO200_PCI) - /* PCI IDs */ #define PCI_VENDOR_ID_AMPLICON 0x14dc #define PCI_DEVICE_ID_AMPLICON_PCI272 0x000a @@ -276,12 +272,12 @@ enum dio200_model { }; enum dio200_layout { -#if DO_ISA +#if IS_ENABLED(CONFIG_COMEDI_AMPLC_DIO200_ISA) pc212_layout, pc214_layout, #endif pc215_layout, -#if DO_ISA +#if IS_ENABLED(CONFIG_COMEDI_AMPLC_DIO200_ISA) pc218_layout, #endif pc272_layout @@ -296,7 +292,7 @@ struct dio200_board { }; static const struct dio200_board dio200_boards[] = { -#if DO_ISA +#if IS_ENABLED(CONFIG_COMEDI_AMPLC_DIO200_ISA) { .name = "pc212e", .bustype = isa_bustype, @@ -328,7 +324,7 @@ static const struct dio200_board dio200_boards[] = { .layout = pc272_layout, }, #endif -#if DO_PCI +#if IS_ENABLED(CONFIG_COMEDI_AMPLC_DIO200_PCI) { .name = "pci215", .devid = PCI_DEVICE_ID_AMPLICON_PCI215, @@ -371,7 +367,7 @@ struct dio200_layout_struct { }; static const struct dio200_layout_struct dio200_layouts[] = { -#if DO_ISA +#if IS_ENABLED(CONFIG_COMEDI_AMPLC_DIO200_ISA) [pc212_layout] = { .n_subdevs = 6, .sdtype = {sd_8255, sd_8254, sd_8254, sd_8254, @@ -400,7 +396,7 @@ static const struct dio200_layout_struct dio200_layouts[] = { .has_int_sce = 1, .has_clk_gat_sce = 1, }, -#if DO_ISA +#if IS_ENABLED(CONFIG_COMEDI_AMPLC_DIO200_ISA) [pc218_layout] = { .n_subdevs = 7, .sdtype = {sd_8254, sd_8254, sd_8255, sd_8254, @@ -453,16 +449,6 @@ struct dio200_subdev_intr { int continuous; }; -static inline bool is_pci_board(const struct dio200_board *board) -{ - return DO_PCI && board->bustype == pci_bustype; -} - -static inline bool is_isa_board(const struct dio200_board *board) -{ - return DO_ISA && board->bustype == isa_bustype; -} - /* * This function looks for a board matching the supplied PCI device. */ @@ -472,7 +458,7 @@ dio200_find_pci_board(struct pci_dev *pci_dev) unsigned int i; for (i = 0; i < ARRAY_SIZE(dio200_boards); i++) - if (is_pci_board(&dio200_boards[i]) && + if (dio200_boards[i].bustype == pci_bustype && pci_dev->device == dio200_boards[i].devid) return &dio200_boards[i]; return NULL; @@ -772,24 +758,52 @@ dio200_subdev_intr_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd) { int err = 0; + unsigned int tmp; - /* Step 1 : check if triggers are trivially valid */ + /* step 1: make sure trigger sources are trivially valid */ - err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_INT); - err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_EXT); - err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_NOW); - err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT); - err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE); + tmp = cmd->start_src; + cmd->start_src &= (TRIG_NOW | TRIG_INT); + if (!cmd->start_src || tmp != cmd->start_src) + err++; + + tmp = cmd->scan_begin_src; + cmd->scan_begin_src &= TRIG_EXT; + if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) + err++; + + tmp = cmd->convert_src; + cmd->convert_src &= TRIG_NOW; + if (!cmd->convert_src || tmp != cmd->convert_src) + err++; + + tmp = cmd->scan_end_src; + cmd->scan_end_src &= TRIG_COUNT; + if (!cmd->scan_end_src || tmp != cmd->scan_end_src) + err++; + + tmp = cmd->stop_src; + cmd->stop_src &= (TRIG_COUNT | TRIG_NONE); + if (!cmd->stop_src || tmp != cmd->stop_src) + err++; if (err) return 1; - /* Step 2a : make sure trigger sources are unique */ + /* step 2: make sure trigger sources are unique and mutually + compatible */ - err |= cfc_check_trigger_is_unique(cmd->start_src); - err |= cfc_check_trigger_is_unique(cmd->stop_src); - - /* Step 2b : and mutually compatible */ + /* these tests are true if more than one _src bit is set */ + if ((cmd->start_src & (cmd->start_src - 1)) != 0) + err++; + if ((cmd->scan_begin_src & (cmd->scan_begin_src - 1)) != 0) + err++; + if ((cmd->convert_src & (cmd->convert_src - 1)) != 0) + err++; + if ((cmd->scan_end_src & (cmd->scan_end_src - 1)) != 0) + err++; + if ((cmd->stop_src & (cmd->stop_src - 1)) != 0) + err++; if (err) return 2; @@ -951,15 +965,15 @@ static irqreturn_t dio200_interrupt(int irq, void *d) { struct comedi_device *dev = d; struct dio200_private *devpriv = dev->private; - struct comedi_subdevice *s; int handled; if (!dev->attached) return IRQ_NONE; if (devpriv->intr_sd >= 0) { - s = &dev->subdevices[devpriv->intr_sd]; - handled = dio200_handle_read_intr(dev, s); + handled = dio200_handle_read_intr(dev, + dev->subdevices + + devpriv->intr_sd); } else { handled = 0; } @@ -1214,10 +1228,12 @@ static void dio200_report_attach(struct comedi_device *dev, unsigned int irq) char tmpbuf[60]; int tmplen; - if (is_isa_board(thisboard)) + if (IS_ENABLED(CONFIG_COMEDI_AMPLC_DIO200_ISA) && + thisboard->bustype == isa_bustype) tmplen = scnprintf(tmpbuf, sizeof(tmpbuf), "(base %#lx) ", dev->iobase); - else if (is_pci_board(thisboard)) + else if (IS_ENABLED(CONFIG_COMEDI_AMPLC_DIO200_PCI) && + thisboard->bustype == pci_bustype) tmplen = scnprintf(tmpbuf, sizeof(tmpbuf), "(pci %s) ", pci_name(pcidev)); else @@ -1345,7 +1361,8 @@ static int dio200_attach(struct comedi_device *dev, struct comedi_devconfig *it) } /* Process options and reserve resources according to bus type. */ - if (is_isa_board(thisboard)) { + if (IS_ENABLED(CONFIG_COMEDI_AMPLC_DIO200_ISA) && + thisboard->bustype == isa_bustype) { unsigned long iobase; unsigned int irq; @@ -1355,7 +1372,8 @@ static int dio200_attach(struct comedi_device *dev, struct comedi_devconfig *it) if (ret < 0) return ret; return dio200_common_attach(dev, iobase, irq, 0); - } else if (is_pci_board(thisboard)) { + } else if (IS_ENABLED(CONFIG_COMEDI_AMPLC_DIO200_PCI) && + thisboard->bustype == pci_bustype) { struct pci_dev *pci_dev; pci_dev = dio200_find_pci_dev(dev, it); @@ -1379,7 +1397,7 @@ static int __devinit dio200_attach_pci(struct comedi_device *dev, { int ret; - if (!DO_PCI) + if (!IS_ENABLED(CONFIG_COMEDI_AMPLC_DIO200_PCI)) return -EINVAL; dev_info(dev->class_dev, DIO200_DRIVER_NAME ": attach pci %s\n", @@ -1394,19 +1412,13 @@ static int __devinit dio200_attach_pci(struct comedi_device *dev, dev_err(dev->class_dev, "BUG! cannot determine board type!\n"); return -EINVAL; } - /* - * Need to 'get' the PCI device to match the 'put' in dio200_detach(). - * TODO: Remove the pci_dev_get() and matching pci_dev_put() once - * support for manual attachment of PCI devices via dio200_attach() - * has been removed. - */ - pci_dev_get(pci_dev); return dio200_pci_common_attach(dev, pci_dev); } static void dio200_detach(struct comedi_device *dev) { const struct dio200_board *thisboard = comedi_board(dev); + struct pci_dev *pcidev = comedi_to_pci_dev(dev); const struct dio200_layout_struct *layout; unsigned n; @@ -1431,16 +1443,13 @@ static void dio200_detach(struct comedi_device *dev) } } } - if (is_isa_board(thisboard)) { + if (pcidev) { + if (dev->iobase) + comedi_pci_disable(pcidev); + pci_dev_put(pcidev); + } else { if (dev->iobase) release_region(dev->iobase, DIO200_IO_SIZE); - } else if (is_pci_board(thisboard)) { - struct pci_dev *pcidev = comedi_to_pci_dev(dev); - if (pcidev) { - if (dev->iobase) - comedi_pci_disable(pcidev); - pci_dev_put(pcidev); - } } } @@ -1461,7 +1470,7 @@ static struct comedi_driver amplc_dio200_driver = { .num_names = ARRAY_SIZE(dio200_boards), }; -#if DO_PCI +#if IS_ENABLED(CONFIG_COMEDI_AMPLC_DIO200_PCI) static DEFINE_PCI_DEVICE_TABLE(dio200_pci_table) = { { PCI_DEVICE(PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCI215) }, { PCI_DEVICE(PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCI272) }, diff --git a/trunk/drivers/staging/comedi/drivers/amplc_pc236.c b/trunk/drivers/staging/comedi/drivers/amplc_pc236.c index eacb5e4735d7..aabba9886b7d 100644 --- a/trunk/drivers/staging/comedi/drivers/amplc_pc236.c +++ b/trunk/drivers/staging/comedi/drivers/amplc_pc236.c @@ -56,15 +56,11 @@ unused. #include "../comedidev.h" -#include "comedi_fc.h" #include "8255.h" #include "plx9052.h" #define PC236_DRIVER_NAME "amplc_pc236" -#define DO_ISA IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_ISA) -#define DO_PCI IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_PCI) - /* PCI236 PCI configuration register information */ #define PCI_VENDOR_ID_AMPLICON 0x14dc #define PCI_DEVICE_ID_AMPLICON_PCI236 0x0009 @@ -107,14 +103,14 @@ struct pc236_board { enum pc236_model model; }; static const struct pc236_board pc236_boards[] = { -#if DO_ISA +#if IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_ISA) { .name = "pc36at", .bustype = isa_bustype, .model = pc36at_model, }, #endif -#if DO_PCI +#if IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_PCI) { .name = "pci236", .devid = PCI_DEVICE_ID_AMPLICON_PCI236, @@ -139,18 +135,6 @@ struct pc236_private { int enable_irq; }; -/* test if ISA supported and this is an ISA board */ -static inline bool is_isa_board(const struct pc236_board *board) -{ - return DO_ISA && board->bustype == isa_bustype; -} - -/* test if PCI supported and this is a PCI board */ -static inline bool is_pci_board(const struct pc236_board *board) -{ - return DO_PCI && board->bustype == pci_bustype; -} - /* * This function looks for a board matching the supplied PCI device. */ @@ -159,7 +143,7 @@ static const struct pc236_board *pc236_find_pci_board(struct pci_dev *pci_dev) unsigned int i; for (i = 0; i < ARRAY_SIZE(pc236_boards); i++) - if (is_pci_board(&pc236_boards[i]) && + if (pc236_boards[i].bustype == pci_bustype && pci_dev->device == pc236_boards[i].devid) return &pc236_boards[i]; return NULL; @@ -230,13 +214,12 @@ static int pc236_request_region(struct comedi_device *dev, unsigned long from, */ static void pc236_intr_disable(struct comedi_device *dev) { - const struct pc236_board *thisboard = comedi_board(dev); struct pc236_private *devpriv = dev->private; unsigned long flags; spin_lock_irqsave(&dev->spinlock, flags); devpriv->enable_irq = 0; - if (is_pci_board(thisboard)) + if (IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_PCI) && devpriv->lcr_iobase) outl(PCI236_INTR_DISABLE, devpriv->lcr_iobase + PLX9052_INTCSR); spin_unlock_irqrestore(&dev->spinlock, flags); } @@ -248,13 +231,12 @@ static void pc236_intr_disable(struct comedi_device *dev) */ static void pc236_intr_enable(struct comedi_device *dev) { - const struct pc236_board *thisboard = comedi_board(dev); struct pc236_private *devpriv = dev->private; unsigned long flags; spin_lock_irqsave(&dev->spinlock, flags); devpriv->enable_irq = 1; - if (is_pci_board(thisboard)) + if (IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_PCI) && devpriv->lcr_iobase) outl(PCI236_INTR_ENABLE, devpriv->lcr_iobase + PLX9052_INTCSR); spin_unlock_irqrestore(&dev->spinlock, flags); } @@ -268,7 +250,6 @@ static void pc236_intr_enable(struct comedi_device *dev) */ static int pc236_intr_check(struct comedi_device *dev) { - const struct pc236_board *thisboard = comedi_board(dev); struct pc236_private *devpriv = dev->private; int retval = 0; unsigned long flags; @@ -276,7 +257,8 @@ static int pc236_intr_check(struct comedi_device *dev) spin_lock_irqsave(&dev->spinlock, flags); if (devpriv->enable_irq) { retval = 1; - if (is_pci_board(thisboard)) { + if (IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_PCI) && + devpriv->lcr_iobase) { if ((inl(devpriv->lcr_iobase + PLX9052_INTCSR) & PLX9052_INTCSR_LI1STAT_MASK) == PLX9052_INTCSR_LI1STAT_INACTIVE) { @@ -314,20 +296,39 @@ static int pc236_intr_cmdtest(struct comedi_device *dev, struct comedi_cmd *cmd) { int err = 0; + int tmp; - /* Step 1 : check if triggers are trivially valid */ + /* step 1 */ - err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW); - err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_EXT); - err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_FOLLOW); - err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT); - err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_NONE); + tmp = cmd->start_src; + cmd->start_src &= TRIG_NOW; + if (!cmd->start_src || tmp != cmd->start_src) + err++; + + tmp = cmd->scan_begin_src; + cmd->scan_begin_src &= TRIG_EXT; + if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) + err++; + + tmp = cmd->convert_src; + cmd->convert_src &= TRIG_FOLLOW; + if (!cmd->convert_src || tmp != cmd->convert_src) + err++; + + tmp = cmd->scan_end_src; + cmd->scan_end_src &= TRIG_COUNT; + if (!cmd->scan_end_src || tmp != cmd->scan_end_src) + err++; + + tmp = cmd->stop_src; + cmd->stop_src &= TRIG_NONE; + if (!cmd->stop_src || tmp != cmd->stop_src) + err++; if (err) return 1; - /* Step 2a : make sure trigger sources are unique */ - /* Step 2b : and mutually compatible */ + /* step 2: ignored */ if (err) return 2; @@ -394,7 +395,7 @@ static int pc236_intr_cancel(struct comedi_device *dev, static irqreturn_t pc236_interrupt(int irq, void *d) { struct comedi_device *dev = d; - struct comedi_subdevice *s = &dev->subdevices[1]; + struct comedi_subdevice *s = dev->subdevices + 1; int handled; handled = pc236_intr_check(dev); @@ -413,13 +414,15 @@ static void pc236_report_attach(struct comedi_device *dev, unsigned int irq) char tmpbuf[60]; int tmplen; - if (is_isa_board(thisboard)) + if (IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_ISA) && + thisboard->bustype == isa_bustype) tmplen = scnprintf(tmpbuf, sizeof(tmpbuf), "(base %#lx) ", dev->iobase); - else if (is_pci_board(thisboard)) + else if (IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_PCI) && + thisboard->bustype == pci_bustype) { tmplen = scnprintf(tmpbuf, sizeof(tmpbuf), "(pci %s) ", pci_name(pcidev)); - else + } else tmplen = 0; if (irq) tmplen += scnprintf(&tmpbuf[tmplen], sizeof(tmpbuf) - tmplen, @@ -446,14 +449,14 @@ static int pc236_common_attach(struct comedi_device *dev, unsigned long iobase, if (ret) return ret; - s = &dev->subdevices[0]; + s = dev->subdevices + 0; /* digital i/o subdevice (8255) */ ret = subdev_8255_init(dev, s, NULL, iobase); if (ret < 0) { dev_err(dev->class_dev, "error! out of memory!\n"); return ret; } - s = &dev->subdevices[1]; + s = dev->subdevices + 1; dev->read_subdev = s; s->type = COMEDI_SUBD_UNUSED; pc236_intr_disable(dev); @@ -514,14 +517,16 @@ static int pc236_attach(struct comedi_device *dev, struct comedi_devconfig *it) return ret; } /* Process options according to bus type. */ - if (is_isa_board(thisboard)) { + if (IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_ISA) && + thisboard->bustype == isa_bustype) { unsigned long iobase = it->options[0]; unsigned int irq = it->options[1]; ret = pc236_request_region(dev, iobase, PC236_IO_SIZE); if (ret < 0) return ret; return pc236_common_attach(dev, iobase, irq, 0); - } else if (is_pci_board(thisboard)) { + } else if (IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_PCI) && + thisboard->bustype == pci_bustype) { struct pci_dev *pci_dev; pci_dev = pc236_find_pci_dev(dev, it); @@ -545,7 +550,7 @@ static int __devinit pc236_attach_pci(struct comedi_device *dev, { int ret; - if (!DO_PCI) + if (!IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_PCI)) return -EINVAL; dev_info(dev->class_dev, PC236_DRIVER_NAME ": attach pci %s\n", @@ -560,37 +565,27 @@ static int __devinit pc236_attach_pci(struct comedi_device *dev, dev_err(dev->class_dev, "BUG! cannot determine board type!\n"); return -EINVAL; } - /* - * Need to 'get' the PCI device to match the 'put' in pc236_detach(). - * TODO: Remove the pci_dev_get() and matching pci_dev_put() once - * support for manual attachment of PCI devices via pc236_attach() - * has been removed. - */ - pci_dev_get(pci_dev); return pc236_pci_common_attach(dev, pci_dev); } static void pc236_detach(struct comedi_device *dev) { - const struct pc236_board *thisboard = comedi_board(dev); struct pc236_private *devpriv = dev->private; + struct pci_dev *pcidev = comedi_to_pci_dev(dev); if (devpriv) pc236_intr_disable(dev); if (dev->irq) free_irq(dev->irq, dev); if (dev->subdevices) - subdev_8255_cleanup(dev, &dev->subdevices[0]); - if (is_isa_board(thisboard)) { + subdev_8255_cleanup(dev, dev->subdevices + 0); + if (pcidev) { + if (dev->iobase) + comedi_pci_disable(pcidev); + pci_dev_put(pcidev); + } else { if (dev->iobase) release_region(dev->iobase, PC236_IO_SIZE); - } else if (is_pci_board(thisboard)) { - struct pci_dev *pcidev = comedi_to_pci_dev(dev); - if (pcidev) { - if (dev->iobase) - comedi_pci_disable(pcidev); - pci_dev_put(pcidev); - } } } @@ -611,7 +606,7 @@ static struct comedi_driver amplc_pc236_driver = { .num_names = ARRAY_SIZE(pc236_boards), }; -#if DO_PCI +#if IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_PCI) static DEFINE_PCI_DEVICE_TABLE(pc236_pci_table) = { { PCI_DEVICE(PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCI236) }, {0} diff --git a/trunk/drivers/staging/comedi/drivers/amplc_pc263.c b/trunk/drivers/staging/comedi/drivers/amplc_pc263.c index 60830ccfb903..40ec1ffebba6 100644 --- a/trunk/drivers/staging/comedi/drivers/amplc_pc263.c +++ b/trunk/drivers/staging/comedi/drivers/amplc_pc263.c @@ -48,9 +48,6 @@ The state of the outputs can be read. #define PC263_DRIVER_NAME "amplc_pc263" -#define DO_ISA IS_ENABLED(CONFIG_COMEDI_AMPLC_PC263_ISA) -#define DO_PCI IS_ENABLED(CONFIG_COMEDI_AMPLC_PC263_PCI) - /* PCI263 PCI configuration register information */ #define PCI_VENDOR_ID_AMPLICON 0x14dc #define PCI_DEVICE_ID_AMPLICON_PCI263 0x000c @@ -73,14 +70,14 @@ struct pc263_board { enum pc263_model model; }; static const struct pc263_board pc263_boards[] = { -#if DO_ISA +#if IS_ENABLED(CONFIG_COMEDI_AMPLC_PC263_ISA) { .name = "pc263", .bustype = isa_bustype, .model = pc263_model, }, #endif -#if DO_PCI +#if IS_ENABLED(CONFIG_COMEDI_AMPLC_PC263_PCI) { .name = "pci263", .devid = PCI_DEVICE_ID_AMPLICON_PCI263, @@ -96,18 +93,6 @@ static const struct pc263_board pc263_boards[] = { #endif }; -/* test if ISA supported and this is an ISA board */ -static inline bool is_isa_board(const struct pc263_board *board) -{ - return DO_ISA && board->bustype == isa_bustype; -} - -/* test if PCI supported and this is a PCI board */ -static inline bool is_pci_board(const struct pc263_board *board) -{ - return DO_PCI && board->bustype == pci_bustype; -} - /* * This function looks for a board matching the supplied PCI device. */ @@ -116,7 +101,7 @@ static const struct pc263_board *pc263_find_pci_board(struct pci_dev *pci_dev) unsigned int i; for (i = 0; i < ARRAY_SIZE(pc263_boards); i++) - if (is_pci_board(&pc263_boards[i]) && + if (pc263_boards[i].bustype == pci_bustype && pci_dev->device == pc263_boards[i].devid) return &pc263_boards[i]; return NULL; @@ -202,9 +187,11 @@ static void pc263_report_attach(struct comedi_device *dev) struct pci_dev *pcidev = comedi_to_pci_dev(dev); char tmpbuf[40]; - if (is_isa_board(thisboard)) + if (IS_ENABLED(CONFIG_COMEDI_AMPLC_PC263_ISA) && + thisboard->bustype == isa_bustype) snprintf(tmpbuf, sizeof(tmpbuf), "(base %#lx) ", dev->iobase); - else if (is_pci_board(thisboard)) + else if (IS_ENABLED(CONFIG_COMEDI_AMPLC_PC263_PCI) && + thisboard->bustype == pci_bustype) snprintf(tmpbuf, sizeof(tmpbuf), "(pci %s) ", pci_name(pcidev)); else @@ -225,7 +212,7 @@ static int pc263_common_attach(struct comedi_device *dev, unsigned long iobase) if (ret) return ret; - s = &dev->subdevices[0]; + s = dev->subdevices + 0; /* digital output subdevice */ s->type = COMEDI_SUBD_DO; s->subdev_flags = SDF_READABLE | SDF_WRITABLE; @@ -272,13 +259,15 @@ static int pc263_attach(struct comedi_device *dev, struct comedi_devconfig *it) dev_info(dev->class_dev, PC263_DRIVER_NAME ": attach\n"); /* Process options and reserve resources according to bus type. */ - if (is_isa_board(thisboard)) { + if (IS_ENABLED(CONFIG_COMEDI_AMPLC_PC263_ISA) && + thisboard->bustype == isa_bustype) { unsigned long iobase = it->options[0]; ret = pc263_request_region(dev, iobase, PC263_IO_SIZE); if (ret < 0) return ret; return pc263_common_attach(dev, iobase); - } else if (is_pci_board(thisboard)) { + } else if (IS_ENABLED(CONFIG_COMEDI_AMPLC_PC263_PCI) && + thisboard->bustype == pci_bustype) { struct pci_dev *pci_dev; pci_dev = pc263_find_pci_dev(dev, it); @@ -299,7 +288,7 @@ static int pc263_attach(struct comedi_device *dev, struct comedi_devconfig *it) static int __devinit pc263_attach_pci(struct comedi_device *dev, struct pci_dev *pci_dev) { - if (!DO_PCI) + if (!IS_ENABLED(CONFIG_COMEDI_AMPLC_PC263_PCI)) return -EINVAL; dev_info(dev->class_dev, PC263_DRIVER_NAME ": attach pci %s\n", @@ -309,30 +298,20 @@ static int __devinit pc263_attach_pci(struct comedi_device *dev, dev_err(dev->class_dev, "BUG! cannot determine board type!\n"); return -EINVAL; } - /* - * Need to 'get' the PCI device to match the 'put' in pc263_detach(). - * TODO: Remove the pci_dev_get() and matching pci_dev_put() once - * support for manual attachment of PCI devices via pc263_attach() - * has been removed. - */ - pci_dev_get(pci_dev); return pc263_pci_common_attach(dev, pci_dev); } static void pc263_detach(struct comedi_device *dev) { - const struct pc263_board *thisboard = comedi_board(dev); + struct pci_dev *pcidev = comedi_to_pci_dev(dev); - if (is_isa_board(thisboard)) { + if (pcidev) { + if (dev->iobase) + comedi_pci_disable(pcidev); + pci_dev_put(pcidev); + } else { if (dev->iobase) release_region(dev->iobase, PC263_IO_SIZE); - } else if (is_pci_board(thisboard)) { - struct pci_dev *pcidev = comedi_to_pci_dev(dev); - if (pcidev) { - if (dev->iobase) - comedi_pci_disable(pcidev); - pci_dev_put(pcidev); - } } } @@ -353,7 +332,7 @@ static struct comedi_driver amplc_pc263_driver = { .num_names = ARRAY_SIZE(pc263_boards), }; -#if DO_PCI +#if IS_ENABLED(CONFIG_COMEDI_AMPLC_PC263_PCI) static DEFINE_PCI_DEVICE_TABLE(pc263_pci_table) = { { PCI_DEVICE(PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCI263) }, {0} diff --git a/trunk/drivers/staging/comedi/drivers/amplc_pci224.c b/trunk/drivers/staging/comedi/drivers/amplc_pci224.c index 1f65ec4d261e..4e17f13e57f6 100644 --- a/trunk/drivers/staging/comedi/drivers/amplc_pci224.c +++ b/trunk/drivers/staging/comedi/drivers/amplc_pci224.c @@ -720,31 +720,53 @@ pci224_ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, int err = 0; unsigned int tmp; - /* Step 1 : check if triggers are trivially valid */ + /* Step 1: make sure trigger sources are trivially valid. */ - err |= cfc_check_trigger_src(&cmd->start_src, TRIG_INT | TRIG_EXT); - err |= cfc_check_trigger_src(&cmd->scan_begin_src, - TRIG_EXT | TRIG_TIMER); - err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_NOW); - err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT); - err |= cfc_check_trigger_src(&cmd->stop_src, - TRIG_COUNT | TRIG_EXT | TRIG_NONE); + tmp = cmd->start_src; + cmd->start_src &= TRIG_INT | TRIG_EXT; + if (!cmd->start_src || tmp != cmd->start_src) + err++; + + tmp = cmd->scan_begin_src; + cmd->scan_begin_src &= TRIG_EXT | TRIG_TIMER; + if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) + err++; + + tmp = cmd->convert_src; + cmd->convert_src &= TRIG_NOW; + if (!cmd->convert_src || tmp != cmd->convert_src) + err++; + + tmp = cmd->scan_end_src; + cmd->scan_end_src &= TRIG_COUNT; + if (!cmd->scan_end_src || tmp != cmd->scan_end_src) + err++; + + tmp = cmd->stop_src; + cmd->stop_src &= TRIG_COUNT | TRIG_EXT | TRIG_NONE; + if (!cmd->stop_src || tmp != cmd->stop_src) + err++; if (err) return 1; - /* Step 2a : make sure trigger sources are unique */ - - err |= cfc_check_trigger_is_unique(cmd->start_src); - err |= cfc_check_trigger_is_unique(cmd->scan_begin_src); - err |= cfc_check_trigger_is_unique(cmd->stop_src); + /* Step 2: make sure trigger sources are unique and mutually + * compatible. */ - /* Step 2b : and mutually compatible */ + /* these tests are true if more than one _src bit is set */ + if ((cmd->start_src & (cmd->start_src - 1)) != 0) + err++; + if ((cmd->scan_begin_src & (cmd->scan_begin_src - 1)) != 0) + err++; + if ((cmd->convert_src & (cmd->convert_src - 1)) != 0) + err++; + if ((cmd->scan_end_src & (cmd->scan_end_src - 1)) != 0) + err++; + if ((cmd->stop_src & (cmd->stop_src - 1)) != 0) + err++; - /* - * There's only one external trigger signal (which makes these - * tests easier). Only one thing can use it. - */ + /* There's only one external trigger signal (which makes these + * tests easier). Only one thing can use it. */ tmp = 0; if (cmd->start_src & TRIG_EXT) tmp++; @@ -753,7 +775,7 @@ pci224_ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, if (cmd->stop_src & TRIG_EXT) tmp++; if (tmp > 1) - err |= -EINVAL; + err++; if (err) return 2; @@ -1353,7 +1375,7 @@ static int pci224_attach_common(struct comedi_device *dev, if (ret) return ret; - s = &dev->subdevices[0]; + s = dev->subdevices + 0; /* Analog output subdevice. */ s->type = COMEDI_SUBD_AO; s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_CMD_WRITE; @@ -1481,13 +1503,6 @@ pci224_attach_pci(struct comedi_device *dev, struct pci_dev *pci_dev) DRIVER_NAME ": BUG! cannot determine board type!\n"); return -EINVAL; } - /* - * Need to 'get' the PCI device to match the 'put' in pci224_detach(). - * TODO: Remove the pci_dev_get() and matching pci_dev_put() once - * support for manual attachment of PCI devices via pci224_attach() - * has been removed. - */ - pci_dev_get(pci_dev); return pci224_attach_common(dev, pci_dev, NULL); } @@ -1501,7 +1516,7 @@ static void pci224_detach(struct comedi_device *dev) if (dev->subdevices) { struct comedi_subdevice *s; - s = &dev->subdevices[0]; + s = dev->subdevices + 0; /* AO subdevice */ kfree(s->range_table_list); } diff --git a/trunk/drivers/staging/comedi/drivers/amplc_pci230.c b/trunk/drivers/staging/comedi/drivers/amplc_pci230.c index bd8fb876ce2e..1b67d0c61fa7 100644 --- a/trunk/drivers/staging/comedi/drivers/amplc_pci230.c +++ b/trunk/drivers/staging/comedi/drivers/amplc_pci230.c @@ -193,7 +193,6 @@ for (or detection of) various hardware problems added by Ian Abbott. #include #include -#include "comedi_fc.h" #include "8253.h" #include "8255.h" @@ -959,11 +958,23 @@ static int pci230_ao_cmdtest(struct comedi_device *dev, int err = 0; unsigned int tmp; - /* Step 1 : check if triggers are trivially valid */ + /* cmdtest tests a particular command to see if it is valid. + * Using the cmdtest ioctl, a user can create a valid cmd + * and then have it executes by the cmd ioctl. + * + * cmdtest returns 1,2,3,4 or 0, depending on which tests + * the command passes. */ - err |= cfc_check_trigger_src(&cmd->start_src, TRIG_INT); + /* Step 1: make sure trigger sources are trivially valid. + * "invalid source" returned by comedilib to user mode process + * if this fails. */ + + tmp = cmd->start_src; + cmd->start_src &= TRIG_INT; + if (!cmd->start_src || tmp != cmd->start_src) + err++; - tmp = TRIG_TIMER | TRIG_INT; + tmp = cmd->scan_begin_src; if ((thisboard->min_hwver > 0) && (devpriv->hwver >= 2)) { /* * For PCI230+ hardware version 2 onwards, allow external @@ -979,23 +990,46 @@ static int pci230_ao_cmdtest(struct comedi_device *dev, * scan_begin_src==TRIG_EXT support to be a bonus rather than a * guarantee! */ - tmp |= TRIG_EXT; + cmd->scan_begin_src &= TRIG_TIMER | TRIG_INT | TRIG_EXT; + } else { + cmd->scan_begin_src &= TRIG_TIMER | TRIG_INT; } - err |= cfc_check_trigger_src(&cmd->scan_begin_src, tmp); + if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) + err++; - err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_NOW); - err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT); - err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE); + tmp = cmd->convert_src; + cmd->convert_src &= TRIG_NOW; + if (!cmd->convert_src || tmp != cmd->convert_src) + err++; + + tmp = cmd->scan_end_src; + cmd->scan_end_src &= TRIG_COUNT; + if (!cmd->scan_end_src || tmp != cmd->scan_end_src) + err++; + + tmp = cmd->stop_src; + cmd->stop_src &= TRIG_COUNT | TRIG_NONE; + if (!cmd->stop_src || tmp != cmd->stop_src) + err++; if (err) return 1; - /* Step 2a : make sure trigger sources are unique */ - - err |= cfc_check_trigger_is_unique(cmd->scan_begin_src); - err |= cfc_check_trigger_is_unique(cmd->stop_src); + /* Step 2: make sure trigger sources are unique and mutually compatible + * "source conflict" returned by comedilib to user mode process + * if this fails. */ - /* Step 2b : and mutually compatible */ + /* these tests are true if more than one _src bit is set */ + if ((cmd->start_src & (cmd->start_src - 1)) != 0) + err++; + if ((cmd->scan_begin_src & (cmd->scan_begin_src - 1)) != 0) + err++; + if ((cmd->convert_src & (cmd->convert_src - 1)) != 0) + err++; + if ((cmd->scan_end_src & (cmd->scan_end_src - 1)) != 0) + err++; + if ((cmd->stop_src & (cmd->stop_src - 1)) != 0) + err++; if (err) return 2; @@ -1576,45 +1610,75 @@ static int pci230_ai_cmdtest(struct comedi_device *dev, int err = 0; unsigned int tmp; - /* Step 1 : check if triggers are trivially valid */ + /* cmdtest tests a particular command to see if it is valid. + * Using the cmdtest ioctl, a user can create a valid cmd + * and then have it executes by the cmd ioctl. + * + * cmdtest returns 1,2,3,4,5 or 0, depending on which tests + * the command passes. */ - err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_INT); + /* Step 1: make sure trigger sources are trivially valid. + * "invalid source" returned by comedilib to user mode process + * if this fails. */ - tmp = TRIG_FOLLOW | TRIG_TIMER | TRIG_INT; + tmp = cmd->start_src; + cmd->start_src &= TRIG_NOW | TRIG_INT; + if (!cmd->start_src || tmp != cmd->start_src) + err++; + + tmp = cmd->scan_begin_src; + /* Unfortunately, we cannot trigger a scan off an external source + * on the PCI260 board, since it uses the PPIC0 (DIO) input, which + * isn't present on the PCI260. For PCI260+ we can use the + * EXTTRIG/EXTCONVCLK input on pin 17 instead. */ if ((thisboard->have_dio) || (thisboard->min_hwver > 0)) { - /* - * Unfortunately, we cannot trigger a scan off an external - * source on the PCI260 board, since it uses the PPIC0 (DIO) - * input, which isn't present on the PCI260. For PCI260+ - * we can use the EXTTRIG/EXTCONVCLK input on pin 17 instead. - */ - tmp |= TRIG_EXT; + cmd->scan_begin_src &= TRIG_FOLLOW | TRIG_TIMER | TRIG_INT + | TRIG_EXT; + } else { + cmd->scan_begin_src &= TRIG_FOLLOW | TRIG_TIMER | TRIG_INT; } - err |= cfc_check_trigger_src(&cmd->scan_begin_src, tmp); - err |= cfc_check_trigger_src(&cmd->convert_src, - TRIG_TIMER | TRIG_INT | TRIG_EXT); - err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT); - err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE); + if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) + err++; + + tmp = cmd->convert_src; + cmd->convert_src &= TRIG_TIMER | TRIG_INT | TRIG_EXT; + if (!cmd->convert_src || tmp != cmd->convert_src) + err++; + + tmp = cmd->scan_end_src; + cmd->scan_end_src &= TRIG_COUNT; + if (!cmd->scan_end_src || tmp != cmd->scan_end_src) + err++; + + tmp = cmd->stop_src; + cmd->stop_src &= TRIG_COUNT | TRIG_NONE; + if (!cmd->stop_src || tmp != cmd->stop_src) + err++; if (err) return 1; - /* Step 2a : make sure trigger sources are unique */ - - err |= cfc_check_trigger_is_unique(cmd->start_src); - err |= cfc_check_trigger_is_unique(cmd->scan_begin_src); - err |= cfc_check_trigger_is_unique(cmd->convert_src); - err |= cfc_check_trigger_is_unique(cmd->stop_src); + /* Step 2: make sure trigger sources are unique and mutually compatible + * "source conflict" returned by comedilib to user mode process + * if this fails. */ - /* Step 2b : and mutually compatible */ + /* these tests are true if more than one _src bit is set */ + if ((cmd->start_src & (cmd->start_src - 1)) != 0) + err++; + if ((cmd->scan_begin_src & (cmd->scan_begin_src - 1)) != 0) + err++; + if ((cmd->convert_src & (cmd->convert_src - 1)) != 0) + err++; + if ((cmd->scan_end_src & (cmd->scan_end_src - 1)) != 0) + err++; + if ((cmd->stop_src & (cmd->stop_src - 1)) != 0) + err++; - /* - * If scan_begin_src is not TRIG_FOLLOW, then a monostable will be - * set up to generate a fixed number of timed conversion pulses. - */ + /* If scan_begin_src is not TRIG_FOLLOW, then a monostable will be + * set up to generate a fixed number of timed conversion pulses. */ if ((cmd->scan_begin_src != TRIG_FOLLOW) && (cmd->convert_src != TRIG_TIMER)) - err |= -EINVAL; + err++; if (err) return 2; @@ -2774,7 +2838,7 @@ static int pci230_attach_common(struct comedi_device *dev, if (rc) return rc; - s = &dev->subdevices[0]; + s = dev->subdevices + 0; /* analog input subdevice */ s->type = COMEDI_SUBD_AI; s->subdev_flags = SDF_READABLE | SDF_DIFF | SDF_GROUND; @@ -2791,7 +2855,7 @@ static int pci230_attach_common(struct comedi_device *dev, s->do_cmdtest = &pci230_ai_cmdtest; s->cancel = pci230_ai_cancel; } - s = &dev->subdevices[1]; + s = dev->subdevices + 1; /* analog output subdevice */ if (thisboard->ao_chans > 0) { s->type = COMEDI_SUBD_AO; @@ -2814,7 +2878,7 @@ static int pci230_attach_common(struct comedi_device *dev, } else { s->type = COMEDI_SUBD_UNUSED; } - s = &dev->subdevices[2]; + s = dev->subdevices + 2; /* digital i/o subdevice */ if (thisboard->have_dio) { rc = subdev_8255_init(dev, s, NULL, @@ -2861,13 +2925,6 @@ static int __devinit pci230_attach_pci(struct comedi_device *dev, "amplc_pci230: BUG! cannot determine board type!\n"); return -EINVAL; } - /* - * Need to 'get' the PCI device to match the 'put' in pci230_detach(). - * TODO: Remove the pci_dev_get() and matching pci_dev_put() once - * support for manual attachment of PCI devices via pci230_attach() - * has been removed. - */ - pci_dev_get(pci_dev); return pci230_attach_common(dev, pci_dev); } @@ -2877,7 +2934,7 @@ static void pci230_detach(struct comedi_device *dev) struct pci_dev *pcidev = comedi_to_pci_dev(dev); if (dev->subdevices && thisboard->have_dio) - subdev_8255_cleanup(dev, &dev->subdevices[2]); + subdev_8255_cleanup(dev, dev->subdevices + 2); if (dev->irq) free_irq(dev->irq, dev); if (pcidev) { diff --git a/trunk/drivers/staging/comedi/drivers/c6xdigio.c b/trunk/drivers/staging/comedi/drivers/c6xdigio.c index 070037c22db7..41ed8576f301 100644 --- a/trunk/drivers/staging/comedi/drivers/c6xdigio.c +++ b/trunk/drivers/staging/comedi/drivers/c6xdigio.c @@ -447,7 +447,7 @@ static int c6xdigio_attach(struct comedi_device *dev, else if (irq == 0) printk(KERN_DEBUG "comedi%d: no irq\n", dev->minor); - s = &dev->subdevices[0]; + s = dev->subdevices + 0; /* pwm output subdevice */ s->type = COMEDI_SUBD_AO; /* Not sure what to put here */ s->subdev_flags = SDF_WRITEABLE; @@ -458,7 +458,7 @@ static int c6xdigio_attach(struct comedi_device *dev, s->maxdata = 500; s->range_table = &range_bipolar10; /* A suitable lie */ - s = &dev->subdevices[1]; + s = dev->subdevices + 1; /* encoder (counter) subdevice */ s->type = COMEDI_SUBD_COUNTER; s->subdev_flags = SDF_READABLE | SDF_LSAMPL; @@ -468,7 +468,7 @@ static int c6xdigio_attach(struct comedi_device *dev, s->maxdata = 0xffffff; s->range_table = &range_unknown; - /* s = &dev->subdevices[2]; */ + /* s = dev->subdevices + 2; */ /* pwm output subdevice */ /* s->type = COMEDI_SUBD_COUNTER; // Not sure what to put here */ /* s->subdev_flags = SDF_WRITEABLE; */ diff --git a/trunk/drivers/staging/comedi/drivers/cb_das16_cs.c b/trunk/drivers/staging/comedi/drivers/cb_das16_cs.c index 6d81d8b40ccc..58d45299bf85 100644 --- a/trunk/drivers/staging/comedi/drivers/cb_das16_cs.c +++ b/trunk/drivers/staging/comedi/drivers/cb_das16_cs.c @@ -46,7 +46,6 @@ Status: experimental #include #include -#include "comedi_fc.h" #include "8253.h" #define DAS16CS_SIZE 18 @@ -170,26 +169,47 @@ static int das16cs_ai_cmdtest(struct comedi_device *dev, int err = 0; int tmp; - /* Step 1 : check if triggers are trivially valid */ + /* step 1: make sure trigger sources are trivially valid */ - err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW); - err |= cfc_check_trigger_src(&cmd->scan_begin_src, - TRIG_TIMER | TRIG_EXT); - err |= cfc_check_trigger_src(&cmd->convert_src, - TRIG_TIMER | TRIG_EXT); - err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT); - err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE); + tmp = cmd->start_src; + cmd->start_src &= TRIG_NOW; + if (!cmd->start_src || tmp != cmd->start_src) + err++; + + tmp = cmd->scan_begin_src; + cmd->scan_begin_src &= TRIG_TIMER | TRIG_EXT; + if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) + err++; + + tmp = cmd->convert_src; + cmd->convert_src &= TRIG_TIMER | TRIG_EXT; + if (!cmd->convert_src || tmp != cmd->convert_src) + err++; + + tmp = cmd->scan_end_src; + cmd->scan_end_src &= TRIG_COUNT; + if (!cmd->scan_end_src || tmp != cmd->scan_end_src) + err++; + + tmp = cmd->stop_src; + cmd->stop_src &= TRIG_COUNT | TRIG_NONE; + if (!cmd->stop_src || tmp != cmd->stop_src) + err++; if (err) return 1; - /* Step 2a : make sure trigger sources are unique */ - - err |= cfc_check_trigger_is_unique(cmd->scan_begin_src); - err |= cfc_check_trigger_is_unique(cmd->convert_src); - err |= cfc_check_trigger_is_unique(cmd->stop_src); + /* step 2: make sure trigger sources are unique and + * mutually compatible */ - /* Step 2b : and mutually compatible */ + /* note that mutual compatibility is not an issue here */ + if (cmd->scan_begin_src != TRIG_TIMER && + cmd->scan_begin_src != TRIG_EXT) + err++; + if (cmd->convert_src != TRIG_TIMER && cmd->convert_src != TRIG_EXT) + err++; + if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE) + err++; if (err) return 2; @@ -458,7 +478,7 @@ static int das16cs_attach(struct comedi_device *dev, if (ret) return ret; - s = &dev->subdevices[0]; + s = dev->subdevices + 0; dev->read_subdev = s; /* analog input subdevice */ s->type = COMEDI_SUBD_AI; @@ -471,7 +491,7 @@ static int das16cs_attach(struct comedi_device *dev, s->do_cmd = das16cs_ai_cmd; s->do_cmdtest = das16cs_ai_cmdtest; - s = &dev->subdevices[1]; + s = dev->subdevices + 1; /* analog output subdevice */ if (thisboard->n_ao_chans) { s->type = COMEDI_SUBD_AO; @@ -485,7 +505,7 @@ static int das16cs_attach(struct comedi_device *dev, s->type = COMEDI_SUBD_UNUSED; } - s = &dev->subdevices[2]; + s = dev->subdevices + 2; /* digital i/o subdevice */ s->type = COMEDI_SUBD_DIO; s->subdev_flags = SDF_READABLE | SDF_WRITABLE; diff --git a/trunk/drivers/staging/comedi/drivers/cb_pcidas.c b/trunk/drivers/staging/comedi/drivers/cb_pcidas.c index de21a261ff45..2b6a637c3499 100644 --- a/trunk/drivers/staging/comedi/drivers/cb_pcidas.c +++ b/trunk/drivers/staging/comedi/drivers/cb_pcidas.c @@ -45,7 +45,11 @@ Devices: [Measurement Computing] PCI-DAS1602/16 (cb_pcidas), The boards may be autocalibrated using the comedi_calibrate utility. -Configuration options: not applicable, uses PCI auto config +Configuration options: + [0] - PCI bus of device (optional) + [1] - PCI slot of device (optional) + If bus/slot is not specified, the first supported + PCI device found will be used. For commands, the scanned channels must be consecutive (i.e. 4-5-6-7, 2-3-4,...), and must all have the same @@ -803,35 +807,58 @@ static int cb_pcidas_ai_cmdtest(struct comedi_device *dev, int tmp; int i, gain, start_chan; - /* Step 1 : check if triggers are trivially valid */ + /* step 1: trigger sources are trivially valid */ - err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_EXT); - err |= cfc_check_trigger_src(&cmd->scan_begin_src, - TRIG_FOLLOW | TRIG_TIMER | TRIG_EXT); - err |= cfc_check_trigger_src(&cmd->convert_src, - TRIG_TIMER | TRIG_NOW | TRIG_EXT); - err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT); - err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE); + tmp = cmd->start_src; + cmd->start_src &= TRIG_NOW | TRIG_EXT; + if (!cmd->start_src || tmp != cmd->start_src) + err++; + + tmp = cmd->scan_begin_src; + cmd->scan_begin_src &= TRIG_FOLLOW | TRIG_TIMER | TRIG_EXT; + if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) + err++; + + tmp = cmd->convert_src; + cmd->convert_src &= TRIG_TIMER | TRIG_NOW | TRIG_EXT; + if (!cmd->convert_src || tmp != cmd->convert_src) + err++; + + tmp = cmd->scan_end_src; + cmd->scan_end_src &= TRIG_COUNT; + if (!cmd->scan_end_src || tmp != cmd->scan_end_src) + err++; + + tmp = cmd->stop_src; + cmd->stop_src &= TRIG_COUNT | TRIG_NONE; + if (!cmd->stop_src || tmp != cmd->stop_src) + err++; if (err) return 1; - /* Step 2a : make sure trigger sources are unique */ + /* step 2: trigger sources are unique and mutually compatible */ - err |= cfc_check_trigger_is_unique(cmd->start_src); - err |= cfc_check_trigger_is_unique(cmd->scan_begin_src); - err |= cfc_check_trigger_is_unique(cmd->convert_src); - err |= cfc_check_trigger_is_unique(cmd->stop_src); - - /* Step 2b : and mutually compatible */ + if (cmd->start_src != TRIG_NOW && cmd->start_src != TRIG_EXT) + err++; + if (cmd->scan_begin_src != TRIG_FOLLOW && + cmd->scan_begin_src != TRIG_TIMER && + cmd->scan_begin_src != TRIG_EXT) + err++; + if (cmd->convert_src != TRIG_TIMER && + cmd->convert_src != TRIG_EXT && cmd->convert_src != TRIG_NOW) + err++; + if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE) + err++; + /* make sure trigger sources are compatible with each other */ if (cmd->scan_begin_src == TRIG_FOLLOW && cmd->convert_src == TRIG_NOW) - err |= -EINVAL; + err++; if (cmd->scan_begin_src != TRIG_FOLLOW && cmd->convert_src != TRIG_NOW) - err |= -EINVAL; + err++; if (cmd->start_src == TRIG_EXT && (cmd->convert_src == TRIG_EXT || cmd->scan_begin_src == TRIG_EXT)) - err |= -EINVAL; + err++; if (err) return 2; @@ -1056,24 +1083,43 @@ static int cb_pcidas_ao_cmdtest(struct comedi_device *dev, int err = 0; int tmp; - /* Step 1 : check if triggers are trivially valid */ + /* step 1: trigger sources are trivially valid */ + + tmp = cmd->start_src; + cmd->start_src &= TRIG_INT; + if (!cmd->start_src || tmp != cmd->start_src) + err++; + + tmp = cmd->scan_begin_src; + cmd->scan_begin_src &= TRIG_TIMER | TRIG_EXT; + if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) + err++; - err |= cfc_check_trigger_src(&cmd->start_src, TRIG_INT); - err |= cfc_check_trigger_src(&cmd->scan_begin_src, - TRIG_TIMER | TRIG_EXT); - err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_NOW); - err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT); - err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE); + tmp = cmd->convert_src; + cmd->convert_src &= TRIG_NOW; + if (!cmd->convert_src || tmp != cmd->convert_src) + err++; + + tmp = cmd->scan_end_src; + cmd->scan_end_src &= TRIG_COUNT; + if (!cmd->scan_end_src || tmp != cmd->scan_end_src) + err++; + + tmp = cmd->stop_src; + cmd->stop_src &= TRIG_COUNT | TRIG_NONE; + if (!cmd->stop_src || tmp != cmd->stop_src) + err++; if (err) return 1; - /* Step 2a : make sure trigger sources are unique */ - - err |= cfc_check_trigger_is_unique(cmd->scan_begin_src); - err |= cfc_check_trigger_is_unique(cmd->stop_src); + /* step 2: trigger sources are unique and mutually compatible */ - /* Step 2b : and mutually compatible */ + if (cmd->scan_begin_src != TRIG_TIMER && + cmd->scan_begin_src != TRIG_EXT) + err++; + if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE) + err++; if (err) return 2; @@ -1455,45 +1501,69 @@ static irqreturn_t cb_pcidas_interrupt(int irq, void *d) return IRQ_HANDLED; } -static const void *cb_pcidas_find_boardinfo(struct comedi_device *dev, - struct pci_dev *pcidev) +static struct pci_dev *cb_pcidas_find_pci_device(struct comedi_device *dev, + struct comedi_devconfig *it) { const struct cb_pcidas_board *thisboard; + struct pci_dev *pcidev = NULL; + int bus = it->options[0]; + int slot = it->options[1]; int i; - for (i = 0; i < ARRAY_SIZE(cb_pcidas_boards); i++) { - thisboard = &cb_pcidas_boards[i]; - if (thisboard->device_id == pcidev->device) - return thisboard; + for_each_pci_dev(pcidev) { + /* is it not a computer boards card? */ + if (pcidev->vendor != PCI_VENDOR_ID_CB) + continue; + /* loop through cards supported by this driver */ + for (i = 0; i < ARRAY_SIZE(cb_pcidas_boards); i++) { + thisboard = &cb_pcidas_boards[i]; + if (thisboard->device_id != pcidev->device) + continue; + /* was a particular bus/slot requested? */ + if (bus || slot) { + /* are we on the wrong bus/slot? */ + if (pcidev->bus->number != bus || + PCI_SLOT(pcidev->devfn) != slot) { + continue; + } + } + dev_dbg(dev->class_dev, + "Found %s on bus %i, slot %i\n", + thisboard->name, + pcidev->bus->number, PCI_SLOT(pcidev->devfn)); + dev->board_ptr = thisboard; + return pcidev; + } } + dev_err(dev->class_dev, "No supported card found\n"); return NULL; } -static int cb_pcidas_attach_pci(struct comedi_device *dev, - struct pci_dev *pcidev) +static int cb_pcidas_attach(struct comedi_device *dev, + struct comedi_devconfig *it) { const struct cb_pcidas_board *thisboard; struct cb_pcidas_private *devpriv; + struct pci_dev *pcidev; struct comedi_subdevice *s; int i; int ret; - comedi_set_hw_dev(dev, &pcidev->dev); - - thisboard = cb_pcidas_find_boardinfo(dev, pcidev); - if (!thisboard) - return -ENODEV; - dev->board_ptr = thisboard; - dev->board_name = thisboard->name; - - ret = alloc_private(dev, sizeof(*devpriv)); - if (ret) - return ret; + if (alloc_private(dev, sizeof(struct cb_pcidas_private)) < 0) + return -ENOMEM; devpriv = dev->private; - ret = comedi_pci_enable(pcidev, dev->board_name); - if (ret) - return ret; + pcidev = cb_pcidas_find_pci_device(dev, it); + if (!pcidev) + return -EIO; + comedi_set_hw_dev(dev, &pcidev->dev); + thisboard = comedi_board(dev); + + if (comedi_pci_enable(pcidev, dev->driver->driver_name)) { + dev_err(dev->class_dev, + "Failed to enable PCI device and request regions\n"); + return -EIO; + } devpriv->s5933_config = pci_resource_start(pcidev, 0); devpriv->control_status = pci_resource_start(pcidev, 1); @@ -1514,11 +1584,13 @@ static int cb_pcidas_attach_pci(struct comedi_device *dev, } dev->irq = pcidev->irq; + dev->board_name = thisboard->name; + ret = comedi_alloc_subdevices(dev, 7); if (ret) return ret; - s = &dev->subdevices[0]; + s = dev->subdevices + 0; /* analog input subdevice */ dev->read_subdev = s; s->type = COMEDI_SUBD_AI; @@ -1535,7 +1607,7 @@ static int cb_pcidas_attach_pci(struct comedi_device *dev, s->cancel = cb_pcidas_cancel; /* analog output subdevice */ - s = &dev->subdevices[1]; + s = dev->subdevices + 1; if (thisboard->ao_nchan) { s->type = COMEDI_SUBD_AO; s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_GROUND; @@ -1562,14 +1634,14 @@ static int cb_pcidas_attach_pci(struct comedi_device *dev, } /* 8255 */ - s = &dev->subdevices[2]; + s = dev->subdevices + 2; ret = subdev_8255_init(dev, s, NULL, devpriv->pacer_counter_dio + DIO_8255); if (ret) return ret; /* serial EEPROM, */ - s = &dev->subdevices[3]; + s = dev->subdevices + 3; s->type = COMEDI_SUBD_MEMORY; s->subdev_flags = SDF_READABLE | SDF_INTERNAL; s->n_chan = 256; @@ -1577,7 +1649,7 @@ static int cb_pcidas_attach_pci(struct comedi_device *dev, s->insn_read = eeprom_read_insn; /* 8800 caldac */ - s = &dev->subdevices[4]; + s = dev->subdevices + 4; s->type = COMEDI_SUBD_CALIB; s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL; s->n_chan = NUM_CHANNELS_8800; @@ -1588,7 +1660,7 @@ static int cb_pcidas_attach_pci(struct comedi_device *dev, caldac_8800_write(dev, i, s->maxdata / 2); /* trim potentiometer */ - s = &dev->subdevices[5]; + s = dev->subdevices + 5; s->type = COMEDI_SUBD_CALIB; s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL; if (thisboard->trimpot == AD7376) { @@ -1604,7 +1676,7 @@ static int cb_pcidas_attach_pci(struct comedi_device *dev, cb_pcidas_trimpot_write(dev, i, s->maxdata / 2); /* dac08 caldac */ - s = &dev->subdevices[6]; + s = dev->subdevices + 6; if (thisboard->has_dac08) { s->type = COMEDI_SUBD_CALIB; s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL; @@ -1626,10 +1698,7 @@ static int cb_pcidas_attach_pci(struct comedi_device *dev, outl(devpriv->s5933_intcsr_bits | INTCSR_INBOX_INTR_STATUS, devpriv->s5933_config + AMCC_OP_REG_INTCSR); - dev_info(dev->class_dev, "%s: %s attached\n", - dev->driver->driver_name, dev->board_name); - - return 0; + return 1; } static void cb_pcidas_detach(struct comedi_device *dev) @@ -1646,17 +1715,18 @@ static void cb_pcidas_detach(struct comedi_device *dev) if (dev->irq) free_irq(dev->irq, dev); if (dev->subdevices) - subdev_8255_cleanup(dev, &dev->subdevices[2]); + subdev_8255_cleanup(dev, dev->subdevices + 2); if (pcidev) { if (devpriv->s5933_config) comedi_pci_disable(pcidev); + pci_dev_put(pcidev); } } static struct comedi_driver cb_pcidas_driver = { .driver_name = "cb_pcidas", .module = THIS_MODULE, - .attach_pci = cb_pcidas_attach_pci, + .attach = cb_pcidas_attach, .detach = cb_pcidas_detach, }; diff --git a/trunk/drivers/staging/comedi/drivers/cb_pcidas64.c b/trunk/drivers/staging/comedi/drivers/cb_pcidas64.c index 0472a9088abe..65cbaabf6456 100644 --- a/trunk/drivers/staging/comedi/drivers/cb_pcidas64.c +++ b/trunk/drivers/staging/comedi/drivers/cb_pcidas64.c @@ -1348,7 +1348,7 @@ static int setup_subdevices(struct comedi_device *dev) if (ret) return ret; - s = &dev->subdevices[0]; + s = dev->subdevices + 0; /* analog input subdevice */ dev->read_subdev = s; s->type = COMEDI_SUBD_AI; @@ -1379,7 +1379,7 @@ static int setup_subdevices(struct comedi_device *dev) } /* analog output subdevice */ - s = &dev->subdevices[1]; + s = dev->subdevices + 1; if (board(dev)->ao_nchan) { s->type = COMEDI_SUBD_AO; s->subdev_flags = @@ -1401,7 +1401,7 @@ static int setup_subdevices(struct comedi_device *dev) } /* digital input */ - s = &dev->subdevices[2]; + s = dev->subdevices + 2; if (board(dev)->layout == LAYOUT_64XX) { s->type = COMEDI_SUBD_DI; s->subdev_flags = SDF_READABLE; @@ -1414,7 +1414,7 @@ static int setup_subdevices(struct comedi_device *dev) /* digital output */ if (board(dev)->layout == LAYOUT_64XX) { - s = &dev->subdevices[3]; + s = dev->subdevices + 3; s->type = COMEDI_SUBD_DO; s->subdev_flags = SDF_WRITABLE | SDF_READABLE; s->n_chan = 4; @@ -1425,7 +1425,7 @@ static int setup_subdevices(struct comedi_device *dev) s->type = COMEDI_SUBD_UNUSED; /* 8255 */ - s = &dev->subdevices[4]; + s = dev->subdevices + 4; if (board(dev)->has_8255) { if (board(dev)->layout == LAYOUT_4020) { dio_8255_iobase = @@ -1442,7 +1442,7 @@ static int setup_subdevices(struct comedi_device *dev) s->type = COMEDI_SUBD_UNUSED; /* 8 channel dio for 60xx */ - s = &dev->subdevices[5]; + s = dev->subdevices + 5; if (board(dev)->layout == LAYOUT_60XX) { s->type = COMEDI_SUBD_DIO; s->subdev_flags = SDF_WRITABLE | SDF_READABLE; @@ -1455,7 +1455,7 @@ static int setup_subdevices(struct comedi_device *dev) s->type = COMEDI_SUBD_UNUSED; /* caldac */ - s = &dev->subdevices[6]; + s = dev->subdevices + 6; s->type = COMEDI_SUBD_CALIB; s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL; s->n_chan = 8; @@ -1469,7 +1469,7 @@ static int setup_subdevices(struct comedi_device *dev) caldac_write(dev, i, s->maxdata / 2); /* 2 channel ad8402 potentiometer */ - s = &dev->subdevices[7]; + s = dev->subdevices + 7; if (board(dev)->layout == LAYOUT_64XX) { s->type = COMEDI_SUBD_CALIB; s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL; @@ -1483,7 +1483,7 @@ static int setup_subdevices(struct comedi_device *dev) s->type = COMEDI_SUBD_UNUSED; /* serial EEPROM, if present */ - s = &dev->subdevices[8]; + s = dev->subdevices + 8; if (readl(priv(dev)->plx9080_iobase + PLX_CONTROL_REG) & CTL_EECHK) { s->type = COMEDI_SUBD_MEMORY; s->subdev_flags = SDF_READABLE | SDF_INTERNAL; @@ -1494,7 +1494,7 @@ static int setup_subdevices(struct comedi_device *dev) s->type = COMEDI_SUBD_UNUSED; /* user counter subd XXX */ - s = &dev->subdevices[9]; + s = dev->subdevices + 9; s->type = COMEDI_SUBD_UNUSED; return 0; @@ -1847,7 +1847,7 @@ static void detach(struct comedi_device *dev) } } if (dev->subdevices) - subdev_8255_cleanup(dev, &dev->subdevices[4]); + subdev_8255_cleanup(dev, dev->subdevices + 4); if (pcidev) { if (dev->iobase) comedi_pci_disable(pcidev); @@ -2108,50 +2108,74 @@ static int ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd) { int err = 0; + int tmp; unsigned int tmp_arg, tmp_arg2; int i; int aref; unsigned int triggers; - /* Step 1 : check if triggers are trivially valid */ + /* step 1: make sure trigger sources are trivially valid */ - err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_EXT); + tmp = cmd->start_src; + cmd->start_src &= TRIG_NOW | TRIG_EXT; + if (!cmd->start_src || tmp != cmd->start_src) + err++; + tmp = cmd->scan_begin_src; triggers = TRIG_TIMER; if (board(dev)->layout == LAYOUT_4020) triggers |= TRIG_OTHER; else triggers |= TRIG_FOLLOW; - err |= cfc_check_trigger_src(&cmd->scan_begin_src, triggers); + cmd->scan_begin_src &= triggers; + if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) + err++; + tmp = cmd->convert_src; triggers = TRIG_TIMER; if (board(dev)->layout == LAYOUT_4020) triggers |= TRIG_NOW; else triggers |= TRIG_EXT; - err |= cfc_check_trigger_src(&cmd->convert_src, triggers); + cmd->convert_src &= triggers; + if (!cmd->convert_src || tmp != cmd->convert_src) + err++; + + tmp = cmd->scan_end_src; + cmd->scan_end_src &= TRIG_COUNT; + if (!cmd->scan_end_src || tmp != cmd->scan_end_src) + err++; - err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT); - err |= cfc_check_trigger_src(&cmd->stop_src, - TRIG_COUNT | TRIG_EXT | TRIG_NONE); + tmp = cmd->stop_src; + cmd->stop_src &= TRIG_COUNT | TRIG_EXT | TRIG_NONE; + if (!cmd->stop_src || tmp != cmd->stop_src) + err++; if (err) return 1; - /* Step 2a : make sure trigger sources are unique */ + /* step 2: make sure trigger sources are unique and mutually compatible */ - err |= cfc_check_trigger_is_unique(cmd->start_src); - err |= cfc_check_trigger_is_unique(cmd->scan_begin_src); - err |= cfc_check_trigger_is_unique(cmd->convert_src); - err |= cfc_check_trigger_is_unique(cmd->stop_src); - - /* Step 2b : and mutually compatible */ + /* uniqueness check */ + if (cmd->start_src != TRIG_NOW && cmd->start_src != TRIG_EXT) + err++; + if (cmd->scan_begin_src != TRIG_TIMER && + cmd->scan_begin_src != TRIG_OTHER && + cmd->scan_begin_src != TRIG_FOLLOW) + err++; + if (cmd->convert_src != TRIG_TIMER && + cmd->convert_src != TRIG_EXT && cmd->convert_src != TRIG_NOW) + err++; + if (cmd->stop_src != TRIG_COUNT && + cmd->stop_src != TRIG_NONE && cmd->stop_src != TRIG_EXT) + err++; + /* compatibility check */ if (cmd->convert_src == TRIG_EXT && cmd->scan_begin_src == TRIG_TIMER) - err |= -EINVAL; + err++; if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE && cmd->stop_src != TRIG_EXT) - err |= -EINVAL; + err++; if (err) return 2; @@ -3442,33 +3466,55 @@ static int ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd) { int err = 0; + int tmp; unsigned int tmp_arg; int i; - /* Step 1 : check if triggers are trivially valid */ + /* step 1: make sure trigger sources are trivially valid */ - err |= cfc_check_trigger_src(&cmd->start_src, TRIG_INT | TRIG_EXT); - err |= cfc_check_trigger_src(&cmd->scan_begin_src, - TRIG_TIMER | TRIG_EXT); - err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_NOW); - err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT); - err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_NONE); + tmp = cmd->start_src; + cmd->start_src &= TRIG_INT | TRIG_EXT; + if (!cmd->start_src || tmp != cmd->start_src) + err++; + + tmp = cmd->scan_begin_src; + cmd->scan_begin_src &= TRIG_TIMER | TRIG_EXT; + if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) + err++; + + tmp = cmd->convert_src; + cmd->convert_src &= TRIG_NOW; + if (!cmd->convert_src || tmp != cmd->convert_src) + err++; + + tmp = cmd->scan_end_src; + cmd->scan_end_src &= TRIG_COUNT; + if (!cmd->scan_end_src || tmp != cmd->scan_end_src) + err++; + + tmp = cmd->stop_src; + cmd->stop_src &= TRIG_NONE; + if (!cmd->stop_src || tmp != cmd->stop_src) + err++; if (err) return 1; - /* Step 2a : make sure trigger sources are unique */ + /* step 2: make sure trigger sources are unique and mutually compatible */ - err |= cfc_check_trigger_is_unique(cmd->start_src); - err |= cfc_check_trigger_is_unique(cmd->scan_begin_src); - - /* Step 2b : and mutually compatible */ + /* uniqueness check */ + if (cmd->start_src != TRIG_INT && cmd->start_src != TRIG_EXT) + err++; + if (cmd->scan_begin_src != TRIG_TIMER && + cmd->scan_begin_src != TRIG_EXT) + err++; + /* compatibility check */ if (cmd->convert_src == TRIG_EXT && cmd->scan_begin_src == TRIG_TIMER) - err |= -EINVAL; + err++; if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE && cmd->stop_src != TRIG_EXT) - err |= -EINVAL; + err++; if (err) return 2; diff --git a/trunk/drivers/staging/comedi/drivers/cb_pcidda.c b/trunk/drivers/staging/comedi/drivers/cb_pcidda.c index aef946df27e2..12660a384e59 100644 --- a/trunk/drivers/staging/comedi/drivers/cb_pcidda.c +++ b/trunk/drivers/staging/comedi/drivers/cb_pcidda.c @@ -48,7 +48,6 @@ Please report success/failure with other different cards to #include "../comedidev.h" -#include "comedi_fc.h" #include "8255.h" /* PCI vendor number of ComputerBoards */ @@ -57,6 +56,14 @@ Please report success/failure with other different cards to /* maximum number of ao channels for supported boards */ #define MAX_AO_CHANNELS 8 +/* PCI-DDA base addresses */ +#define DIGITALIO_BADRINDEX 2 + /* DIGITAL I/O is pci_dev->resource[2] */ +#define DIGITALIO_SIZE 8 + /* DIGITAL I/O uses 8 I/O port addresses */ +#define DAC_BADRINDEX 3 + /* DAC is pci_dev->resource[3] */ + /* Digital I/O registers */ #define PORT1A 0 /* PORT 1A DATA */ @@ -195,6 +202,11 @@ static const struct cb_pcidda_board cb_pcidda_boards[] = { }, }; +/* + * Useful for shorthand access to the particular board structure + */ +#define thisboard ((const struct cb_pcidda_board *)dev->board_ptr) + /* * this structure is for data unique to this hardware driver. If * several hardware drivers keep similar information in this structure, @@ -217,6 +229,164 @@ struct cb_pcidda_private { u16 eeprom_data[EEPROM_SIZE]; /* software copy of board's eeprom */ }; +/* + * most drivers define the following macro to make it easy to + * access the private structure. + */ +#define devpriv ((struct cb_pcidda_private *)dev->private) + +/* static int cb_pcidda_ai_rinsn(struct comedi_device *dev,struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data); */ +static int cb_pcidda_ao_winsn(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); + +/* static int cb_pcidda_ai_cmd(struct comedi_device *dev, struct *comedi_subdevice *s);*/ +/* static int cb_pcidda_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd); */ +/* static int cb_pcidda_ns_to_timer(unsigned int *ns,int *round); */ + +static unsigned int cb_pcidda_serial_in(struct comedi_device *dev); +static void cb_pcidda_serial_out(struct comedi_device *dev, unsigned int value, + unsigned int num_bits); +static unsigned int cb_pcidda_read_eeprom(struct comedi_device *dev, + unsigned int address); +static void cb_pcidda_calibrate(struct comedi_device *dev, unsigned int channel, + unsigned int range); + +static struct pci_dev *cb_pcidda_find_pci_dev(struct comedi_device *dev, + struct comedi_devconfig *it) +{ + struct pci_dev *pcidev = NULL; + int bus = it->options[0]; + int slot = it->options[1]; + int i; + + for_each_pci_dev(pcidev) { + if (bus || slot) { + if (bus != pcidev->bus->number || + slot != PCI_SLOT(pcidev->devfn)) + continue; + } + if (pcidev->vendor != PCI_VENDOR_ID_CB) + continue; + + for (i = 0; i < ARRAY_SIZE(cb_pcidda_boards); i++) { + if (cb_pcidda_boards[i].device_id != pcidev->device) + continue; + dev->board_ptr = cb_pcidda_boards + i; + return pcidev; + } + } + dev_err(dev->class_dev, + "No supported board found! (req. bus %d, slot %d)\n", + bus, slot); + return NULL; +} + +/* + * Attach is called by the Comedi core to configure the driver + * for a particular board. + */ +static int cb_pcidda_attach(struct comedi_device *dev, + struct comedi_devconfig *it) +{ + struct pci_dev *pcidev; + struct comedi_subdevice *s; + int index; + int ret; + +/* + * Allocate the private structure area. + */ + if (alloc_private(dev, sizeof(struct cb_pcidda_private)) < 0) + return -ENOMEM; + + pcidev = cb_pcidda_find_pci_dev(dev, it); + if (!pcidev) + return -EIO; + comedi_set_hw_dev(dev, &pcidev->dev); + + /* + * Enable PCI device and request regions. + */ + if (comedi_pci_enable(pcidev, thisboard->name)) { + dev_err(dev->class_dev, + "cb_pcidda: failed to enable PCI device and request regions\n"); + return -EIO; + } + +/* + * Allocate the I/O ports. + */ + devpriv->digitalio = pci_resource_start(pcidev, DIGITALIO_BADRINDEX); + devpriv->dac = pci_resource_start(pcidev, DAC_BADRINDEX); + dev->iobase = devpriv->dac; + +/* + * Warn about the status of the driver. + */ + if (thisboard->status == 2) + printk + ("WARNING: DRIVER FOR THIS BOARD NOT CHECKED WITH MANUAL. " + "WORKS ASSUMING FULL COMPATIBILITY WITH PCI-DDA08/12. " + "PLEASE REPORT USAGE TO .\n"); + +/* + * Initialize dev->board_name. + */ + dev->board_name = thisboard->name; + + ret = comedi_alloc_subdevices(dev, 3); + if (ret) + return ret; + + s = dev->subdevices + 0; + /* analog output subdevice */ + s->type = COMEDI_SUBD_AO; + s->subdev_flags = SDF_WRITABLE; + s->n_chan = thisboard->ao_chans; + s->maxdata = (1 << thisboard->ao_bits) - 1; + s->range_table = thisboard->ranges; + s->insn_write = cb_pcidda_ao_winsn; + + /* s->subdev_flags |= SDF_CMD_READ; */ + /* s->do_cmd = cb_pcidda_ai_cmd; */ + /* s->do_cmdtest = cb_pcidda_ai_cmdtest; */ + + /* two 8255 digital io subdevices */ + s = dev->subdevices + 1; + subdev_8255_init(dev, s, NULL, devpriv->digitalio); + s = dev->subdevices + 2; + subdev_8255_init(dev, s, NULL, devpriv->digitalio + PORT2A); + + dev_dbg(dev->class_dev, "eeprom:\n"); + for (index = 0; index < EEPROM_SIZE; index++) { + devpriv->eeprom_data[index] = cb_pcidda_read_eeprom(dev, index); + dev_dbg(dev->class_dev, "%i:0x%x\n", index, + devpriv->eeprom_data[index]); + } + + /* set calibrations dacs */ + for (index = 0; index < thisboard->ao_chans; index++) + cb_pcidda_calibrate(dev, index, devpriv->ao_range[index]); + + return 1; +} + +static void cb_pcidda_detach(struct comedi_device *dev) +{ + struct pci_dev *pcidev = comedi_to_pci_dev(dev); + + if (pcidev) { + if (dev->iobase) + comedi_pci_disable(pcidev); + pci_dev_put(pcidev); + } + if (dev->subdevices) { + subdev_8255_cleanup(dev, dev->subdevices + 1); + subdev_8255_cleanup(dev, dev->subdevices + 2); + } +} + /* * I will program this later... ;-) */ @@ -248,26 +418,56 @@ static int cb_pcidda_ai_cmdtest(struct comedi_device *dev, int err = 0; int tmp; - /* Step 1 : check if triggers are trivially valid */ + /* cmdtest tests a particular command to see if it is valid. + * Using the cmdtest ioctl, a user can create a valid cmd + * and then have it executes by the cmd ioctl. + * + * cmdtest returns 1,2,3,4 or 0, depending on which tests + * the command passes. */ + + /* step 1: make sure trigger sources are trivially valid */ + + tmp = cmd->start_src; + cmd->start_src &= TRIG_NOW; + if (!cmd->start_src || tmp != cmd->start_src) + err++; + + tmp = cmd->scan_begin_src; + cmd->scan_begin_src &= TRIG_TIMER | TRIG_EXT; + if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) + err++; + + tmp = cmd->convert_src; + cmd->convert_src &= TRIG_TIMER | TRIG_EXT; + if (!cmd->convert_src || tmp != cmd->convert_src) + err++; + + tmp = cmd->scan_end_src; + cmd->scan_end_src &= TRIG_COUNT; + if (!cmd->scan_end_src || tmp != cmd->scan_end_src) + err++; - err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW); - err |= cfc_check_trigger_src(&cmd->scan_begin_src, - TRIG_TIMER | TRIG_EXT); - err |= cfc_check_trigger_src(&cmd->convert_src, - TRIG_TIMER | TRIG_EXT); - err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT); - err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE); + tmp = cmd->stop_src; + cmd->stop_src &= TRIG_COUNT | TRIG_NONE; + if (!cmd->stop_src || tmp != cmd->stop_src) + err++; if (err) return 1; - /* Step 2a : make sure trigger sources are unique */ - - err |= cfc_check_trigger_is_unique(cmd->scan_begin_src); - err |= cfc_check_trigger_is_unique(cmd->convert_src); - err |= cfc_check_trigger_is_unique(cmd->stop_src); + /* + * step 2: make sure trigger sources are unique and mutually + * compatible + */ - /* Step 2b : and mutually compatible */ + /* note that mutual compatibility is not an issue here */ + if (cmd->scan_begin_src != TRIG_TIMER + && cmd->scan_begin_src != TRIG_EXT) + err++; + if (cmd->convert_src != TRIG_TIMER && cmd->convert_src != TRIG_EXT) + err++; + if (cmd->stop_src != TRIG_TIMER && cmd->stop_src != TRIG_EXT) + err++; if (err) return 2; @@ -381,10 +581,59 @@ static int cb_pcidda_ns_to_timer(unsigned int *ns, int round) } #endif +static int cb_pcidda_ao_winsn(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data) +{ + unsigned int command; + unsigned int channel, range; + + channel = CR_CHAN(insn->chanspec); + range = CR_RANGE(insn->chanspec); + + /* adjust calibration dacs if range has changed */ + if (range != devpriv->ao_range[channel]) + cb_pcidda_calibrate(dev, channel, range); + + /* output channel configuration */ + command = NOSU | ENABLEDAC; + + /* output channel range */ + switch (range) { + case 0: + command |= BIP | RANGE10V; + break; + case 1: + command |= BIP | RANGE5V; + break; + case 2: + command |= BIP | RANGE2V5; + break; + case 3: + command |= UNIP | RANGE10V; + break; + case 4: + command |= UNIP | RANGE5V; + break; + case 5: + command |= UNIP | RANGE2V5; + break; + } + + /* output channel specification */ + command |= channel << 2; + outw(command, devpriv->dac + DACONTROL); + + /* write data */ + outw(data[0], devpriv->dac + DADATA + channel * 2); + + /* return the number of samples read/written */ + return 1; +} + /* lowlevel read from eeprom */ static unsigned int cb_pcidda_serial_in(struct comedi_device *dev) { - struct cb_pcidda_private *devpriv = dev->private; unsigned int value = 0; int i; const int value_width = 16; /* number of bits wide values are */ @@ -402,7 +651,6 @@ static unsigned int cb_pcidda_serial_in(struct comedi_device *dev) static void cb_pcidda_serial_out(struct comedi_device *dev, unsigned int value, unsigned int num_bits) { - struct cb_pcidda_private *devpriv = dev->private; int i; for (i = 1; i <= num_bits; i++) { @@ -419,7 +667,6 @@ static void cb_pcidda_serial_out(struct comedi_device *dev, unsigned int value, static unsigned int cb_pcidda_read_eeprom(struct comedi_device *dev, unsigned int address) { - struct cb_pcidda_private *devpriv = dev->private; unsigned int i; unsigned int cal2_bits; unsigned int value; @@ -456,7 +703,6 @@ static void cb_pcidda_write_caldac(struct comedi_device *dev, unsigned int caldac, unsigned int channel, unsigned int value) { - struct cb_pcidda_private *devpriv = dev->private; unsigned int cal2_bits; unsigned int i; /* caldacs use 3 bit channel specification */ @@ -551,7 +797,6 @@ static unsigned int eeprom_fine_byte(unsigned int word) static void cb_pcidda_calibrate(struct comedi_device *dev, unsigned int channel, unsigned int range) { - struct cb_pcidda_private *devpriv = dev->private; unsigned int coarse_offset, fine_offset, coarse_gain, fine_gain; /* remember range so we can tell when we need to readjust calibration */ @@ -582,164 +827,10 @@ static void cb_pcidda_calibrate(struct comedi_device *dev, unsigned int channel, fine_gain_channel(channel), fine_gain); } -static int cb_pcidda_ao_winsn(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) -{ - struct cb_pcidda_private *devpriv = dev->private; - unsigned int command; - unsigned int channel, range; - - channel = CR_CHAN(insn->chanspec); - range = CR_RANGE(insn->chanspec); - - /* adjust calibration dacs if range has changed */ - if (range != devpriv->ao_range[channel]) - cb_pcidda_calibrate(dev, channel, range); - - /* output channel configuration */ - command = NOSU | ENABLEDAC; - - /* output channel range */ - switch (range) { - case 0: - command |= BIP | RANGE10V; - break; - case 1: - command |= BIP | RANGE5V; - break; - case 2: - command |= BIP | RANGE2V5; - break; - case 3: - command |= UNIP | RANGE10V; - break; - case 4: - command |= UNIP | RANGE5V; - break; - case 5: - command |= UNIP | RANGE2V5; - break; - } - - /* output channel specification */ - command |= channel << 2; - outw(command, devpriv->dac + DACONTROL); - - /* write data */ - outw(data[0], devpriv->dac + DADATA + channel * 2); - - /* return the number of samples read/written */ - return 1; -} - -static const void *cb_pcidda_find_boardinfo(struct comedi_device *dev, - struct pci_dev *pcidev) -{ - const struct cb_pcidda_board *thisboard; - int i; - - for (i = 0; i < ARRAY_SIZE(cb_pcidda_boards); i++) { - thisboard = &cb_pcidda_boards[i]; - if (thisboard->device_id != pcidev->device) - return thisboard; - } - return NULL; -} - -static int cb_pcidda_attach_pci(struct comedi_device *dev, - struct pci_dev *pcidev) -{ - const struct cb_pcidda_board *thisboard; - struct cb_pcidda_private *devpriv; - struct comedi_subdevice *s; - int index; - int ret; - - comedi_set_hw_dev(dev, &pcidev->dev); - - thisboard = cb_pcidda_find_boardinfo(dev, pcidev); - if (!pcidev) - return -ENODEV; - dev->board_ptr = thisboard; - dev->board_name = thisboard->name; - - ret = alloc_private(dev, sizeof(*devpriv)); - if (ret) - return ret; - devpriv = dev->private; - - ret = comedi_pci_enable(pcidev, dev->board_name); - if (ret) - return ret; - - devpriv->digitalio = pci_resource_start(pcidev, 2); - devpriv->dac = pci_resource_start(pcidev, 3); - dev->iobase = devpriv->dac; - - if (thisboard->status == 2) - printk - ("WARNING: DRIVER FOR THIS BOARD NOT CHECKED WITH MANUAL. " - "WORKS ASSUMING FULL COMPATIBILITY WITH PCI-DDA08/12. " - "PLEASE REPORT USAGE TO .\n"); - - ret = comedi_alloc_subdevices(dev, 3); - if (ret) - return ret; - - s = &dev->subdevices[0]; - /* analog output subdevice */ - s->type = COMEDI_SUBD_AO; - s->subdev_flags = SDF_WRITABLE; - s->n_chan = thisboard->ao_chans; - s->maxdata = (1 << thisboard->ao_bits) - 1; - s->range_table = thisboard->ranges; - s->insn_write = cb_pcidda_ao_winsn; - - /* s->subdev_flags |= SDF_CMD_READ; */ - /* s->do_cmd = cb_pcidda_ai_cmd; */ - /* s->do_cmdtest = cb_pcidda_ai_cmdtest; */ - - /* two 8255 digital io subdevices */ - s = &dev->subdevices[1]; - subdev_8255_init(dev, s, NULL, devpriv->digitalio); - s = &dev->subdevices[2]; - subdev_8255_init(dev, s, NULL, devpriv->digitalio + PORT2A); - - dev_dbg(dev->class_dev, "eeprom:\n"); - for (index = 0; index < EEPROM_SIZE; index++) { - devpriv->eeprom_data[index] = cb_pcidda_read_eeprom(dev, index); - dev_dbg(dev->class_dev, "%i:0x%x\n", index, - devpriv->eeprom_data[index]); - } - - /* set calibrations dacs */ - for (index = 0; index < thisboard->ao_chans; index++) - cb_pcidda_calibrate(dev, index, devpriv->ao_range[index]); - - dev_info(dev->class_dev, "%s attached\n", dev->board_name); - - return 0; -} - -static void cb_pcidda_detach(struct comedi_device *dev) -{ - struct pci_dev *pcidev = comedi_to_pci_dev(dev); - - if (dev->subdevices) { - subdev_8255_cleanup(dev, &dev->subdevices[1]); - subdev_8255_cleanup(dev, &dev->subdevices[2]); - } - if (pcidev) { - if (dev->iobase) - comedi_pci_disable(pcidev); - } -} - static struct comedi_driver cb_pcidda_driver = { .driver_name = "cb_pcidda", .module = THIS_MODULE, - .attach_pci = cb_pcidda_attach_pci, + .attach = cb_pcidda_attach, .detach = cb_pcidda_detach, }; diff --git a/trunk/drivers/staging/comedi/drivers/cb_pcidio.c b/trunk/drivers/staging/comedi/drivers/cb_pcidio.c new file mode 100644 index 000000000000..e370d0d81bbd --- /dev/null +++ b/trunk/drivers/staging/comedi/drivers/cb_pcidio.c @@ -0,0 +1,211 @@ +/* + comedi/drivers/cb_pcidio.c + A Comedi driver for PCI-DIO24H & PCI-DIO48H of ComputerBoards (currently MeasurementComputing) + + COMEDI - Linux Control and Measurement Device Interface + Copyright (C) 2000 David A. Schleef + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ +/* +Driver: cb_pcidio +Description: ComputerBoards' DIO boards with PCI interface +Devices: [Measurement Computing] PCI-DIO24 (cb_pcidio), PCI-DIO24H, PCI-DIO48H +Author: Yoshiya Matsuzaka +Updated: Mon, 29 Oct 2007 15:40:47 +0000 +Status: experimental + +This driver has been modified from skel.c of comedi-0.7.70. + +Configuration Options: + [0] - PCI bus of device (optional) + [1] - PCI slot of device (optional) + If bus/slot is not specified, the first available PCI device will + be used. + +Passing a zero for an option is the same as leaving it unspecified. +*/ + +/*------------------------------ HEADER FILES ---------------------------------*/ +#include "../comedidev.h" +#include "8255.h" + +/*-------------------------- MACROS and DATATYPES -----------------------------*/ +#define PCI_VENDOR_ID_CB 0x1307 + +/* + * Board descriptions for two imaginary boards. Describing the + * boards in this way is optional, and completely driver-dependent. + * Some drivers use arrays such as this, other do not. + */ +struct pcidio_board { + const char *name; /* name of the board */ + int dev_id; + int n_8255; /* number of 8255 chips on board */ + + /* indices of base address regions */ + int pcicontroler_badrindex; + int dioregs_badrindex; +}; + +static const struct pcidio_board pcidio_boards[] = { + { + .name = "pci-dio24", + .dev_id = 0x0028, + .n_8255 = 1, + .pcicontroler_badrindex = 1, + .dioregs_badrindex = 2, + }, + { + .name = "pci-dio24h", + .dev_id = 0x0014, + .n_8255 = 1, + .pcicontroler_badrindex = 1, + .dioregs_badrindex = 2, + }, + { + .name = "pci-dio48h", + .dev_id = 0x000b, + .n_8255 = 2, + .pcicontroler_badrindex = 0, + .dioregs_badrindex = 1, + }, +}; + +/* + * Useful for shorthand access to the particular board structure + */ +#define thisboard ((const struct pcidio_board *)dev->board_ptr) + +static struct pci_dev *pcidio_find_pci_dev(struct comedi_device *dev, + struct comedi_devconfig *it) +{ + struct pci_dev *pcidev = NULL; + int bus = it->options[0]; + int slot = it->options[1]; + int i; + + for_each_pci_dev(pcidev) { + if (bus || slot) { + if (bus != pcidev->bus->number || + slot != PCI_SLOT(pcidev->devfn)) + continue; + } + if (pcidev->vendor != PCI_VENDOR_ID_CB) + continue; + for (i = 0; i < ARRAY_SIZE(pcidio_boards); i++) { + if (pcidio_boards[i].dev_id != pcidev->device) + continue; + + dev->board_ptr = pcidio_boards + i; + return pcidev; + } + } + dev_err(dev->class_dev, + "No supported board found! (req. bus %d, slot %d)\n", + bus, slot); + return NULL; +} + +static int pcidio_attach(struct comedi_device *dev, struct comedi_devconfig *it) +{ + struct pci_dev *pcidev; + int i; + int ret; + + pcidev = pcidio_find_pci_dev(dev, it); + if (!pcidev) + return -EIO; + comedi_set_hw_dev(dev, &pcidev->dev); + +/* + * Initialize dev->board_name. Note that we can use the "thisboard" + * macro now, since we just initialized it in the last line. + */ + dev->board_name = thisboard->name; + + if (comedi_pci_enable(pcidev, thisboard->name)) + return -EIO; + + dev->iobase = pci_resource_start(pcidev, thisboard->dioregs_badrindex); + + ret = comedi_alloc_subdevices(dev, thisboard->n_8255); + if (ret) + return ret; + + for (i = 0; i < thisboard->n_8255; i++) { + subdev_8255_init(dev, dev->subdevices + i, + NULL, dev->iobase + i * 4); + dev_dbg(dev->class_dev, "subdev %d: base = 0x%lx\n", i, + dev->iobase + i * 4); + } + + return 1; +} + +static void pcidio_detach(struct comedi_device *dev) +{ + struct pci_dev *pcidev = comedi_to_pci_dev(dev); + + if (pcidev) { + if (dev->iobase) + comedi_pci_disable(pcidev); + pci_dev_put(pcidev); + } + if (dev->subdevices) { + int i; + for (i = 0; i < thisboard->n_8255; i++) + subdev_8255_cleanup(dev, dev->subdevices + i); + } +} + +static struct comedi_driver cb_pcidio_driver = { + .driver_name = "cb_pcidio", + .module = THIS_MODULE, + .attach = pcidio_attach, + .detach = pcidio_detach, +}; + +static int __devinit cb_pcidio_pci_probe(struct pci_dev *dev, + const struct pci_device_id *ent) +{ + return comedi_pci_auto_config(dev, &cb_pcidio_driver); +} + +static void __devexit cb_pcidio_pci_remove(struct pci_dev *dev) +{ + comedi_pci_auto_unconfig(dev); +} + +static DEFINE_PCI_DEVICE_TABLE(cb_pcidio_pci_table) = { + { PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0028) }, + { PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0014) }, + { PCI_DEVICE(PCI_VENDOR_ID_CB, 0x000b) }, + { 0 } +}; +MODULE_DEVICE_TABLE(pci, cb_pcidio_pci_table); + +static struct pci_driver cb_pcidio_pci_driver = { + .name = "cb_pcidio", + .id_table = cb_pcidio_pci_table, + .probe = cb_pcidio_pci_probe, + .remove = __devexit_p(cb_pcidio_pci_remove), +}; +module_comedi_pci_driver(cb_pcidio_driver, cb_pcidio_pci_driver); + +MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/staging/comedi/drivers/cb_pcimdas.c b/trunk/drivers/staging/comedi/drivers/cb_pcimdas.c index 9515b6926662..c632a89f3ae9 100644 --- a/trunk/drivers/staging/comedi/drivers/cb_pcimdas.c +++ b/trunk/drivers/staging/comedi/drivers/cb_pcimdas.c @@ -118,6 +118,11 @@ static const struct cb_pcimdas_board cb_pcimdas_boards[] = { }, }; +/* + * Useful for shorthand access to the particular board structure + */ +#define thisboard ((const struct cb_pcimdas_board *)dev->board_ptr) + /* * this structure is for data unique to this hardware driver. If * several hardware drivers keep similar information in this structure, @@ -132,6 +137,160 @@ struct cb_pcimdas_private { unsigned int ao_readback[2]; }; +/* + * most drivers define the following macro to make it easy to + * access the private structure. + */ +#define devpriv ((struct cb_pcimdas_private *)dev->private) + +static int cb_pcimdas_ai_rinsn(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); +static int cb_pcimdas_ao_winsn(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); +static int cb_pcimdas_ao_rinsn(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); + +static struct pci_dev *cb_pcimdas_find_pci_dev(struct comedi_device *dev, + struct comedi_devconfig *it) +{ + struct pci_dev *pcidev = NULL; + int bus = it->options[0]; + int slot = it->options[1]; + int i; + + for_each_pci_dev(pcidev) { + if (bus || slot) { + if (bus != pcidev->bus->number || + slot != PCI_SLOT(pcidev->devfn)) + continue; + } + if (pcidev->vendor != PCI_VENDOR_ID_COMPUTERBOARDS) + continue; + + for (i = 0; i < ARRAY_SIZE(cb_pcimdas_boards); i++) { + if (cb_pcimdas_boards[i].device_id != pcidev->device) + continue; + + dev->board_ptr = cb_pcimdas_boards + i; + return pcidev; + } + } + dev_err(dev->class_dev, + "No supported board found! (req. bus %d, slot %d)\n", + bus, slot); + return NULL; +} + +/* + * Attach is called by the Comedi core to configure the driver + * for a particular board. If you specified a board_name array + * in the driver structure, dev->board_ptr contains that + * address. + */ +static int cb_pcimdas_attach(struct comedi_device *dev, + struct comedi_devconfig *it) +{ + struct pci_dev *pcidev; + struct comedi_subdevice *s; + unsigned long iobase_8255; + int ret; + +/* + * Allocate the private structure area. + */ + if (alloc_private(dev, sizeof(struct cb_pcimdas_private)) < 0) + return -ENOMEM; + + pcidev = cb_pcimdas_find_pci_dev(dev, it); + if (!pcidev) + return -EIO; + comedi_set_hw_dev(dev, &pcidev->dev); + + /* Warn about non-tested features */ + switch (thisboard->device_id) { + case 0x56: + break; + default: + dev_dbg(dev->class_dev, "THIS CARD IS UNSUPPORTED.\n"); + dev_dbg(dev->class_dev, + "PLEASE REPORT USAGE TO \n"); + } + + if (comedi_pci_enable(pcidev, "cb_pcimdas")) { + dev_err(dev->class_dev, + "Failed to enable PCI device and request regions\n"); + return -EIO; + } + + dev->iobase = pci_resource_start(pcidev, 2); + devpriv->BADR3 = pci_resource_start(pcidev, 3); + iobase_8255 = pci_resource_start(pcidev, 4); + +/* Dont support IRQ yet */ +/* get irq */ +/* if(request_irq(pcidev->irq, cb_pcimdas_interrupt, IRQF_SHARED, "cb_pcimdas", dev )) */ +/* { */ +/* printk(" unable to allocate irq %u\n", pcidev->irq); */ +/* return -EINVAL; */ +/* } */ +/* dev->irq = pcidev->irq; */ + + /* Initialize dev->board_name */ + dev->board_name = thisboard->name; + + ret = comedi_alloc_subdevices(dev, 3); + if (ret) + return ret; + + s = dev->subdevices + 0; + /* dev->read_subdev=s; */ + /* analog input subdevice */ + s->type = COMEDI_SUBD_AI; + s->subdev_flags = SDF_READABLE | SDF_GROUND; + s->n_chan = thisboard->ai_se_chans; + s->maxdata = (1 << thisboard->ai_bits) - 1; + s->range_table = &range_unknown; + s->len_chanlist = 1; /* This is the maximum chanlist length that */ + /* the board can handle */ + s->insn_read = cb_pcimdas_ai_rinsn; + + s = dev->subdevices + 1; + /* analog output subdevice */ + s->type = COMEDI_SUBD_AO; + s->subdev_flags = SDF_WRITABLE; + s->n_chan = thisboard->ao_nchan; + s->maxdata = 1 << thisboard->ao_bits; + /* ranges are hardware settable, but not software readable. */ + s->range_table = &range_unknown; + s->insn_write = &cb_pcimdas_ao_winsn; + s->insn_read = &cb_pcimdas_ao_rinsn; + + s = dev->subdevices + 2; + /* digital i/o subdevice */ + if (thisboard->has_dio) + subdev_8255_init(dev, s, NULL, iobase_8255); + else + s->type = COMEDI_SUBD_UNUSED; + + return 1; +} + +static void cb_pcimdas_detach(struct comedi_device *dev) +{ + struct pci_dev *pcidev = comedi_to_pci_dev(dev); + + if (dev->irq) + free_irq(dev->irq, dev); + if (pcidev) { + if (dev->iobase) + comedi_pci_disable(pcidev); + pci_dev_put(pcidev); + } +} + /* * "instructions" read/write data in "one-shot" or "software-triggered" * mode. @@ -140,8 +299,6 @@ static int cb_pcimdas_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - const struct cb_pcimdas_board *thisboard = comedi_board(dev); - struct cb_pcimdas_private *devpriv = dev->private; int n, i; unsigned int d; unsigned int busy; @@ -211,7 +368,6 @@ static int cb_pcimdas_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - struct cb_pcimdas_private *devpriv = dev->private; int i; int chan = CR_CHAN(insn->chanspec); @@ -241,7 +397,6 @@ static int cb_pcimdas_ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - struct cb_pcimdas_private *devpriv = dev->private; int i; int chan = CR_CHAN(insn->chanspec); @@ -251,124 +406,10 @@ static int cb_pcimdas_ao_rinsn(struct comedi_device *dev, return i; } -static const void *cb_pcimdas_find_boardinfo(struct comedi_device *dev, - struct pci_dev *pcidev) -{ - const struct cb_pcimdas_board *thisboard; - int i; - - for (i = 0; i < ARRAY_SIZE(cb_pcimdas_boards); i++) { - thisboard = &cb_pcimdas_boards[i]; - if (thisboard->device_id == pcidev->device) - return thisboard; - } - return NULL; -} - -static int cb_pcimdas_attach_pci(struct comedi_device *dev, - struct pci_dev *pcidev) -{ - const struct cb_pcimdas_board *thisboard; - struct cb_pcimdas_private *devpriv; - struct comedi_subdevice *s; - unsigned long iobase_8255; - int ret; - - comedi_set_hw_dev(dev, &pcidev->dev); - - thisboard = cb_pcimdas_find_boardinfo(dev, pcidev); - if (!thisboard) - return -ENODEV; - dev->board_ptr = thisboard; - dev->board_name = thisboard->name; - - ret = alloc_private(dev, sizeof(*devpriv)); - if (ret) - return ret; - devpriv = dev->private; - - /* Warn about non-tested features */ - switch (thisboard->device_id) { - case 0x56: - break; - default: - dev_dbg(dev->class_dev, "THIS CARD IS UNSUPPORTED.\n"); - dev_dbg(dev->class_dev, - "PLEASE REPORT USAGE TO \n"); - } - - ret = comedi_pci_enable(pcidev, dev->board_name); - if (ret) - return ret; - - dev->iobase = pci_resource_start(pcidev, 2); - devpriv->BADR3 = pci_resource_start(pcidev, 3); - iobase_8255 = pci_resource_start(pcidev, 4); - -/* Dont support IRQ yet */ -/* get irq */ -/* if(request_irq(pcidev->irq, cb_pcimdas_interrupt, IRQF_SHARED, "cb_pcimdas", dev )) */ -/* { */ -/* printk(" unable to allocate irq %u\n", pcidev->irq); */ -/* return -EINVAL; */ -/* } */ -/* dev->irq = pcidev->irq; */ - - ret = comedi_alloc_subdevices(dev, 3); - if (ret) - return ret; - - s = &dev->subdevices[0]; - /* dev->read_subdev=s; */ - /* analog input subdevice */ - s->type = COMEDI_SUBD_AI; - s->subdev_flags = SDF_READABLE | SDF_GROUND; - s->n_chan = thisboard->ai_se_chans; - s->maxdata = (1 << thisboard->ai_bits) - 1; - s->range_table = &range_unknown; - s->len_chanlist = 1; /* This is the maximum chanlist length that */ - /* the board can handle */ - s->insn_read = cb_pcimdas_ai_rinsn; - - s = &dev->subdevices[1]; - /* analog output subdevice */ - s->type = COMEDI_SUBD_AO; - s->subdev_flags = SDF_WRITABLE; - s->n_chan = thisboard->ao_nchan; - s->maxdata = 1 << thisboard->ao_bits; - /* ranges are hardware settable, but not software readable. */ - s->range_table = &range_unknown; - s->insn_write = &cb_pcimdas_ao_winsn; - s->insn_read = &cb_pcimdas_ao_rinsn; - - s = &dev->subdevices[2]; - /* digital i/o subdevice */ - if (thisboard->has_dio) - subdev_8255_init(dev, s, NULL, iobase_8255); - else - s->type = COMEDI_SUBD_UNUSED; - - dev_info(dev->class_dev, "%s attached\n", dev->board_name); - - return 0; -} - -static void cb_pcimdas_detach(struct comedi_device *dev) -{ - struct pci_dev *pcidev = comedi_to_pci_dev(dev); - - if (dev->irq) - free_irq(dev->irq, dev); - if (pcidev) { - if (dev->iobase) - comedi_pci_disable(pcidev); - } -} - static struct comedi_driver cb_pcimdas_driver = { .driver_name = "cb_pcimdas", .module = THIS_MODULE, - .attach_pci = cb_pcimdas_attach_pci, + .attach = cb_pcimdas_attach, .detach = cb_pcimdas_detach, }; diff --git a/trunk/drivers/staging/comedi/drivers/cb_pcimdda.c b/trunk/drivers/staging/comedi/drivers/cb_pcimdda.c index ba9f0599be28..a80146133c04 100644 --- a/trunk/drivers/staging/comedi/drivers/cb_pcimdda.c +++ b/trunk/drivers/staging/comedi/drivers/cb_pcimdda.c @@ -57,7 +57,12 @@ output modes on the board: then issue one comedi_data_read() on any channel on the AO subdevice to initiate the simultaneous XFER. -Configuration Options: not applicable, uses PCI auto config +Configuration Options: + [0] PCI bus (optional) + [1] PCI slot (optional) + [2] analog output range jumper setting + 0 == +/- 5 V + 1 == +/- 10 V */ /* @@ -88,133 +93,337 @@ Configuration Options: not applicable, uses PCI auto config #define PCI_ID_PCIM_DDA06_16 0x0053 /* - * Register map, 8-bit access only + * This is straight from skel.c -- I did this in case this source file + * will someday support more than 1 board... */ -#define PCIMDDA_DA_CHAN(x) (0x00 + (x) * 2) -#define PCIMDDA_8255_BASE_REG 0x0c - -#define MAX_AO_READBACK_CHANNELS 6 +struct board_struct { + const char *name; + unsigned short device_id; + int ao_chans; + int ao_bits; + int dio_chans; + int dio_method; + /* how many bytes into the BADR are the DIO ports */ + int dio_offset; + int regs_badrindex; /* IO Region for the control, analog output, + and DIO registers */ + int reg_sz; /* number of bytes of registers in io region */ +}; -struct cb_pcimdda_private { - unsigned int ao_readback[MAX_AO_READBACK_CHANNELS]; +enum DIO_METHODS { + DIO_NONE = 0, + DIO_8255, + DIO_INTERNAL /* unimplemented */ }; -static int cb_pcimdda_ao_winsn(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) -{ - struct cb_pcimdda_private *devpriv = dev->private; - unsigned int chan = CR_CHAN(insn->chanspec); - unsigned long offset = dev->iobase + PCIMDDA_DA_CHAN(chan); - unsigned int val = 0; - int i; +static const struct board_struct boards[] = { + { + .name = "cb_pcimdda06-16", + .device_id = PCI_ID_PCIM_DDA06_16, + .ao_chans = 6, + .ao_bits = 16, + .dio_chans = 24, + .dio_method = DIO_8255, + .dio_offset = 12, + .regs_badrindex = 3, + .reg_sz = 16, + } +}; - for (i = 0; i < insn->n; i++) { - val = data[i]; +/* + * Useful for shorthand access to the particular board structure + */ +#define thisboard ((const struct board_struct *)dev->board_ptr) - /* - * Write the LSB then MSB. - * - * If the simultaneous xfer mode is selected by the - * jumper on the card, a read instruction is needed - * in order to initiate the simultaneous transfer. - * Otherwise, the DAC will be updated when the MSB - * is written. - */ - outb(val & 0x00ff, offset); - outb((val >> 8) & 0x00ff, offset + 1); - } +#define REG_SZ (thisboard->reg_sz) +#define REGS_BADRINDEX (thisboard->regs_badrindex) - /* Cache the last value for readback */ - devpriv->ao_readback[chan] = val; +/* + * this structure is for data unique to this hardware driver. If + * several hardware drivers keep similar information in this structure, + * feel free to suggest moving the variable to the struct comedi_device + * struct. + */ +struct board_private_struct { + unsigned long registers; /* set by probe */ + unsigned long dio_registers; + char attached_to_8255; /* boolean */ + /* would be useful for a PCI device */ + struct pci_dev *pci_dev; + +#define MAX_AO_READBACK_CHANNELS 6 + /* Used for AO readback */ + unsigned int ao_readback[MAX_AO_READBACK_CHANNELS]; - return insn->n; -} +}; -static int cb_pcimdda_ao_rinsn(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) -{ - struct cb_pcimdda_private *devpriv = dev->private; - int chan = CR_CHAN(insn->chanspec); - unsigned long offset = dev->iobase + PCIMDDA_DA_CHAN(chan); - int i; +/* + * most drivers define the following macro to make it easy to + * access the private structure. + */ +#define devpriv ((struct board_private_struct *)dev->private) - for (i = 0; i < insn->n; i++) { - /* Initiate the simultaneous transfer */ - inw(offset); +static int ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); +static int ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); - data[i] = devpriv->ao_readback[chan]; - } +/*--------------------------------------------------------------------------- + HELPER FUNCTION DECLARATIONS +-----------------------------------------------------------------------------*/ - return insn->n; +/* returns a maxdata value for a given n_bits */ +static inline unsigned int figure_out_maxdata(int bits) +{ + return ((unsigned int)1 << bits) - 1; } -static int cb_pcimdda_attach_pci(struct comedi_device *dev, - struct pci_dev *pcidev) +/* + * Probes for a supported device. + * + * Prerequisite: private be allocated already inside dev + * + * If the device is found, it returns 0 and has the following side effects: + * + * o assigns a struct pci_dev * to dev->private->pci_dev + * o assigns a struct board * to dev->board_ptr + * o sets dev->private->registers + * o sets dev->private->dio_registers + * + * Otherwise, returns a -errno on error + */ +static int probe(struct comedi_device *dev, const struct comedi_devconfig *it); + +/*--------------------------------------------------------------------------- + FUNCTION DEFINITIONS +-----------------------------------------------------------------------------*/ + +/* + * Attach is called by the Comedi core to configure the driver + * for a particular board. If you specified a board_name array + * in the driver structure, dev->board_ptr contains that + * address. + */ +static int attach(struct comedi_device *dev, struct comedi_devconfig *it) { - struct cb_pcimdda_private *devpriv; struct comedi_subdevice *s; - int ret; + int err; - comedi_set_hw_dev(dev, &pcidev->dev); - dev->board_name = dev->driver->driver_name; +/* + * Allocate the private structure area. alloc_private() is a + * convenient macro defined in comedidev.h. + * if this function fails (returns negative) then the private area is + * kfree'd by comedi + */ + if (alloc_private(dev, sizeof(struct board_private_struct)) < 0) + return -ENOMEM; - ret = alloc_private(dev, sizeof(*devpriv)); - if (ret) - return ret; - devpriv = dev->private; +/* + * If you can probe the device to determine what device in a series + * it is, this is the place to do it. Otherwise, dev->board_ptr + * should already be initialized. + */ + err = probe(dev, it); + if (err) + return err; - ret = comedi_pci_enable(pcidev, dev->board_name); - if (ret) - return ret; - dev->iobase = pci_resource_start(pcidev, 3); +/* Output some info */ + printk("comedi%d: %s: ", dev->minor, thisboard->name); - ret = comedi_alloc_subdevices(dev, 2); - if (ret) - return ret; +/* + * Initialize dev->board_name. Note that we can use the "thisboard" + * macro now, since we just initialized it in the last line. + */ + dev->board_name = thisboard->name; + + err = comedi_alloc_subdevices(dev, 2); + if (err) + return err; + + s = dev->subdevices + 0; - s = &dev->subdevices[0]; /* analog output subdevice */ - s->type = COMEDI_SUBD_AO; - s->subdev_flags = SDF_WRITABLE | SDF_READABLE; - s->n_chan = 6; - s->maxdata = 0xffff; - s->range_table = &range_bipolar5; - s->insn_write = cb_pcimdda_ao_winsn; - s->insn_read = cb_pcimdda_ao_rinsn; - - s = &dev->subdevices[1]; + s->type = COMEDI_SUBD_AO; + s->subdev_flags = SDF_WRITABLE | SDF_READABLE; + s->n_chan = thisboard->ao_chans; + s->maxdata = figure_out_maxdata(thisboard->ao_bits); + /* this is hard-coded here */ + if (it->options[2]) + s->range_table = &range_bipolar10; + else + s->range_table = &range_bipolar5; + s->insn_write = &ao_winsn; + s->insn_read = &ao_rinsn; + + s = dev->subdevices + 1; /* digital i/o subdevice */ - ret = subdev_8255_init(dev, s, NULL, - dev->iobase + PCIMDDA_8255_BASE_REG); - if (ret) - return ret; + if (thisboard->dio_chans) { + switch (thisboard->dio_method) { + case DIO_8255: + /* + * this is a straight 8255, so register us with + * the 8255 driver + */ + subdev_8255_init(dev, s, NULL, devpriv->dio_registers); + devpriv->attached_to_8255 = 1; + break; + case DIO_INTERNAL: + default: + printk("DIO_INTERNAL not implemented yet!\n"); + return -ENXIO; + break; + } + } else { + s->type = COMEDI_SUBD_UNUSED; + } - dev_info(dev->class_dev, "%s attached\n", dev->board_name); + printk("attached\n"); return 1; } -static void cb_pcimdda_detach(struct comedi_device *dev) +static void detach(struct comedi_device *dev) +{ + if (devpriv) { + if (dev->subdevices && devpriv->attached_to_8255) { + subdev_8255_cleanup(dev, dev->subdevices + 2); + devpriv->attached_to_8255 = 0; + } + if (devpriv->pci_dev) { + if (devpriv->registers) + comedi_pci_disable(devpriv->pci_dev); + pci_dev_put(devpriv->pci_dev); + } + } +} + +static int ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data) { - struct pci_dev *pcidev = comedi_to_pci_dev(dev); + int i; + int chan = CR_CHAN(insn->chanspec); + unsigned long offset = devpriv->registers + chan * 2; - if (dev->subdevices) - subdev_8255_cleanup(dev, &dev->subdevices[1]); - if (pcidev) { - if (dev->iobase) - comedi_pci_disable(pcidev); + /* Writing a list of values to an AO channel is probably not + * very useful, but that's how the interface is defined. */ + for (i = 0; i < insn->n; i++) { + /* first, load the low byte */ + outb((char)(data[i] & 0x00ff), offset); + /* next, write the high byte -- only after this is written is + the channel voltage updated in the DAC, unless + we're in simultaneous xfer mode (jumper on card) + then a rinsn is necessary to actually update the DAC -- + see ao_rinsn() below... */ + outb((char)(data[i] >> 8 & 0x00ff), offset + 1); + + /* for testing only.. the actual rinsn SHOULD do an inw! + (see the stuff about simultaneous XFER mode on this board) */ + devpriv->ao_readback[chan] = data[i]; } + + /* return the number of samples read/written */ + return i; +} + +/* AO subdevices should have a read insn as well as a write insn. + + Usually this means copying a value stored in devpriv->ao_readback. + However, since this board has this jumper setting called "Simultaneous + Xfer mode" (off by default), we will support it. Simultaneaous xfer + mode is accomplished by loading ALL the values you want for AO in all the + channels, then READing off one of the AO registers to initiate the + instantaneous simultaneous update of all DAC outputs, which makes + all AO channels update simultaneously. This is useful for some control + applications, I would imagine. +*/ +static int ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data) +{ + int i; + int chan = CR_CHAN(insn->chanspec); + + for (i = 0; i < insn->n; i++) { + inw(devpriv->registers + chan * 2); + /* + * should I set data[i] to the result of the actual read + * on the register or the cached unsigned int in + * devpriv->ao_readback[]? + */ + data[i] = devpriv->ao_readback[chan]; + } + + return i; +} + +/*--------------------------------------------------------------------------- + HELPER FUNCTION DEFINITIONS +-----------------------------------------------------------------------------*/ + +/* + * Probes for a supported device. + * + * Prerequisite: private be allocated already inside dev + * + * If the device is found, it returns 0 and has the following side effects: + * + * o assigns a struct pci_dev * to dev->private->pci_dev + * o assigns a struct board * to dev->board_ptr + * o sets dev->private->registers + * o sets dev->private->dio_registers + * + * Otherwise, returns a -errno on error + */ +static int probe(struct comedi_device *dev, const struct comedi_devconfig *it) +{ + struct pci_dev *pcidev = NULL; + int index; + unsigned long registers; + + for_each_pci_dev(pcidev) { + /* is it not a computer boards card? */ + if (pcidev->vendor != PCI_VENDOR_ID_COMPUTERBOARDS) + continue; + /* loop through cards supported by this driver */ + for (index = 0; index < ARRAY_SIZE(boards); index++) { + if (boards[index].device_id != pcidev->device) + continue; + /* was a particular bus/slot requested? */ + if (it->options[0] || it->options[1]) { + /* are we on the wrong bus/slot? */ + if (pcidev->bus->number != it->options[0] || + PCI_SLOT(pcidev->devfn) != it->options[1]) { + continue; + } + } + /* found ! */ + + devpriv->pci_dev = pcidev; + dev->board_ptr = boards + index; + if (comedi_pci_enable(pcidev, thisboard->name)) { + printk + ("cb_pcimdda: Failed to enable PCI device and request regions\n"); + return -EIO; + } + registers = + pci_resource_start(devpriv->pci_dev, + REGS_BADRINDEX); + devpriv->registers = registers; + devpriv->dio_registers + = devpriv->registers + thisboard->dio_offset; + return 0; + } + } + + printk("cb_pcimdda: No supported ComputerBoards/MeasurementComputing " + "card found at the requested position\n"); + return -ENODEV; } static struct comedi_driver cb_pcimdda_driver = { .driver_name = "cb_pcimdda", .module = THIS_MODULE, - .attach_pci = cb_pcimdda_attach_pci, - .detach = cb_pcimdda_detach, + .attach = attach, + .detach = detach, }; static int __devinit cb_pcimdda_pci_probe(struct pci_dev *dev, diff --git a/trunk/drivers/staging/comedi/drivers/comedi_bond.c b/trunk/drivers/staging/comedi/drivers/comedi_bond.c index 5c768bc76eb1..5ed324c4f620 100644 --- a/trunk/drivers/staging/comedi/drivers/comedi_bond.c +++ b/trunk/drivers/staging/comedi/drivers/comedi_bond.c @@ -59,6 +59,40 @@ Configuration Options: /* The maxiumum number of channels per subdevice. */ #define MAX_CHANS 256 +#define MODULE_NAME "comedi_bond" +#ifndef STR +# define STR1(x) #x +# define STR(x) STR1(x) +#endif + +static int debug; +module_param(debug, int, 0644); +MODULE_PARM_DESC(debug, "If true, print extra cryptic debugging output useful" + "only to developers."); + +#define LOG_MSG(x...) printk(KERN_INFO MODULE_NAME": "x) +#define DEBUG(x...) \ + do { \ + if (debug) \ + printk(KERN_DEBUG MODULE_NAME": DEBUG: "x); \ + } while (0) +#define WARNING(x...) printk(KERN_WARNING MODULE_NAME ": WARNING: "x) +#define ERROR(x...) printk(KERN_ERR MODULE_NAME ": INTERNAL ERROR: "x) + +/* + * Board descriptions for two imaginary boards. Describing the + * boards in this way is optional, and completely driver-dependent. + * Some drivers use arrays such as this, other do not. + */ +struct BondingBoard { + const char *name; +}; + +/* + * Useful for shorthand access to the particular board structure + */ +#define thisboard ((const struct BondingBoard *)dev->board_ptr) + struct BondedDevice { struct comedi_device *dev; unsigned minor; @@ -73,7 +107,7 @@ struct BondedDevice { /* this structure is for data unique to this hardware driver. If several hardware drivers keep similar information in this structure, feel free to suggest moving the variable to the struct comedi_device struct. */ -struct comedi_bond_private { +struct Private { # define MAX_BOARD_NAME 256 char name[MAX_BOARD_NAME]; struct BondedDevice **devs; @@ -82,6 +116,12 @@ struct comedi_bond_private { unsigned nchans; }; +/* + * most drivers define the following macro to make it easy to + * access the private structure. + */ +#define devpriv ((struct Private *)dev->private) + /* DIO devices are slightly special. Although it is possible to * implement the insn_read/insn_write interface, it is much more * useful to applications if you implement the insn_bits interface. @@ -91,7 +131,6 @@ static int bonding_dio_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - struct comedi_bond_private *devpriv = dev->private; #define LSAMPL_BITS (sizeof(unsigned int)*8) unsigned nchans = LSAMPL_BITS, num_done = 0, i; @@ -138,7 +177,6 @@ static int bonding_dio_insn_config(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - struct comedi_bond_private *devpriv = dev->private; int chan = CR_CHAN(insn->chanspec), ret, io_bits = s->io_bits; unsigned int io; struct BondedDevice *bdev; @@ -192,7 +230,6 @@ static void *Realloc(const void *oldmem, size_t newlen, size_t oldlen) static int doDevConfig(struct comedi_device *dev, struct comedi_devconfig *it) { - struct comedi_bond_private *devpriv = dev->private; int i; struct comedi_device *devs_opened[COMEDI_NUM_BOARD_MINORS]; @@ -208,18 +245,15 @@ static int doDevConfig(struct comedi_device *dev, struct comedi_devconfig *it) struct BondedDevice *bdev = NULL; if (minor < 0 || minor >= COMEDI_NUM_BOARD_MINORS) { - dev_err(dev->class_dev, - "Minor %d is invalid!\n", minor); + ERROR("Minor %d is invalid!\n", minor); return 0; } if (minor == dev->minor) { - dev_err(dev->class_dev, - "Cannot bond this driver to itself!\n"); + ERROR("Cannot bond this driver to itself!\n"); return 0; } if (devs_opened[minor]) { - dev_err(dev->class_dev, - "Minor %d specified more than once!\n", minor); + ERROR("Minor %d specified more than once!\n", minor); return 0; } @@ -229,8 +263,7 @@ static int doDevConfig(struct comedi_device *dev, struct comedi_devconfig *it) d = devs_opened[minor] = comedi_open(file); if (!d) { - dev_err(dev->class_dev, - "Minor %u could not be opened\n", minor); + ERROR("Minor %u could not be opened\n", minor); return 0; } @@ -239,14 +272,14 @@ static int doDevConfig(struct comedi_device *dev, struct comedi_devconfig *it) sdev + 1)) > -1) { nchans = comedi_get_n_channels(d, sdev); if (nchans <= 0) { - dev_err(dev->class_dev, - "comedi_get_n_channels() returned %d on minor %u subdev %d!\n", - nchans, minor, sdev); + ERROR("comedi_get_n_channels() returned %d " + "on minor %u subdev %d!\n", + nchans, minor, sdev); return 0; } bdev = kmalloc(sizeof(*bdev), GFP_KERNEL); if (!bdev) { - dev_err(dev->class_dev, "Out of memory\n"); + ERROR("Out of memory.\n"); return 0; } bdev->dev = d; @@ -269,8 +302,8 @@ static int doDevConfig(struct comedi_device *dev, struct comedi_devconfig *it) Realloc(devpriv->devs, ++devpriv->ndevs * sizeof(bdev), tmp); if (!devpriv->devs) { - dev_err(dev->class_dev, - "Could not allocate memory. Out of memory?\n"); + ERROR("Could not allocate memory. " + "Out of memory?"); return 0; } @@ -290,7 +323,7 @@ static int doDevConfig(struct comedi_device *dev, struct comedi_devconfig *it) } if (!devpriv->nchans) { - dev_err(dev->class_dev, "No channels found!\n"); + ERROR("No channels found!\n"); return 0; } @@ -300,28 +333,35 @@ static int doDevConfig(struct comedi_device *dev, struct comedi_devconfig *it) static int bonding_attach(struct comedi_device *dev, struct comedi_devconfig *it) { - struct comedi_bond_private *devpriv; struct comedi_subdevice *s; int ret; - ret = alloc_private(dev, sizeof(*devpriv)); - if (ret) - return ret; - devpriv = dev->private; + LOG_MSG("comedi%d\n", dev->minor); + + /* + * Allocate the private structure area. alloc_private() is a + * convenient macro defined in comedidev.h. + */ + if (alloc_private(dev, sizeof(struct Private)) < 0) + return -ENOMEM; /* - * Setup our bonding from config params.. sets up our private struct.. + * Setup our bonding from config params.. sets up our Private struct.. */ if (!doDevConfig(dev, it)) return -EINVAL; + /* + * Initialize dev->board_name. Note that we can use the "thisboard" + * macro now, since we just initialized it in the last line. + */ dev->board_name = devpriv->name; ret = comedi_alloc_subdevices(dev, 1); if (ret) return ret; - s = &dev->subdevices[0]; + s = dev->subdevices + 0; s->type = COMEDI_SUBD_DIO; s->subdev_flags = SDF_READABLE | SDF_WRITABLE; s->n_chan = devpriv->nchans; @@ -330,9 +370,9 @@ static int bonding_attach(struct comedi_device *dev, s->insn_bits = bonding_dio_insn_bits; s->insn_config = bonding_dio_insn_config; - dev_info(dev->class_dev, - "%s: %s attached, %u channels from %u devices\n", - dev->driver->driver_name, dev->board_name, + LOG_MSG("attached with %u DIO channels coming from %u different " + "subdevices all bonded together. " + "John Lennon would be proud!\n", devpriv->nchans, devpriv->ndevs); return 1; @@ -340,7 +380,6 @@ static int bonding_attach(struct comedi_device *dev, static void bonding_detach(struct comedi_device *dev) { - struct comedi_bond_private *devpriv = dev->private; unsigned long devs_closed = 0; if (devpriv) { @@ -363,16 +402,25 @@ static void bonding_detach(struct comedi_device *dev) } } +static const struct BondingBoard bondingBoards[] = { + { + .name = "comedi_bond", + }, +}; + static struct comedi_driver bonding_driver = { .driver_name = "comedi_bond", .module = THIS_MODULE, .attach = bonding_attach, .detach = bonding_detach, + .board_name = &bondingBoards[0].name, + .offset = sizeof(struct BondingBoard), + .num_names = ARRAY_SIZE(bondingBoards), }; module_comedi_driver(bonding_driver); MODULE_AUTHOR("Calin A. Culianu"); -MODULE_DESCRIPTION("comedi_bond: A driver for COMEDI to bond multiple COMEDI " +MODULE_DESCRIPTION(MODULE_NAME "A driver for COMEDI to bond multiple COMEDI " "devices together as one. In the words of John Lennon: " "'And the world will live as one...'"); MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/staging/comedi/drivers/comedi_fc.h b/trunk/drivers/staging/comedi/drivers/comedi_fc.h index 94481c637a0a..4b2cfd327995 100644 --- a/trunk/drivers/staging/comedi/drivers/comedi_fc.h +++ b/trunk/drivers/staging/comedi/drivers/comedi_fc.h @@ -73,36 +73,4 @@ static inline unsigned int cfc_bytes_per_scan(struct comedi_subdevice *subd) return num_samples * bytes_per_sample(subd); } -/** - * cfc_check_trigger_src() - trivially validate a comedi_cmd trigger source - * @src: pointer to the trigger source to validate - * @flags: bitmask of valid TRIG_* for the trigger - * - * This is used in "step 1" of the do_cmdtest functions of comedi drivers - * to vaildate the comedi_cmd triggers. The mask of the @src against the - * @flags allows the userspace comedilib to pass all the comedi_cmd - * triggers as TRIG_ANY and get back a bitmask of the valid trigger sources. - */ -static inline int cfc_check_trigger_src(unsigned int *src, unsigned int flags) -{ - unsigned int orig_src = *src; - - *src = orig_src & flags; - if (*src == TRIG_INVALID || *src != orig_src) - return -EINVAL; - return 0; -} - -/** - * cfc_check_trigger_is_unique() - make sure a trigger source is unique - * @src: the trigger source to check - */ -static inline int cfc_check_trigger_is_unique(unsigned int src) -{ - /* this test is true if more than one _src bit is set */ - if ((src & (src - 1)) != 0) - return -EINVAL; - return 0; -} - #endif /* _COMEDI_FC_H */ diff --git a/trunk/drivers/staging/comedi/drivers/comedi_parport.c b/trunk/drivers/staging/comedi/drivers/comedi_parport.c index 22ef94242590..9a63cac2434a 100644 --- a/trunk/drivers/staging/comedi/drivers/comedi_parport.c +++ b/trunk/drivers/staging/comedi/drivers/comedi_parport.c @@ -85,8 +85,6 @@ pin, which can be used to wake up tasks. #include #include -#include "comedi_fc.h" - #define PARPORT_SIZE 3 #define PARPORT_A 0 @@ -98,12 +96,11 @@ struct parport_private { unsigned int c_data; int enable_irq; }; +#define devpriv ((struct parport_private *)(dev->private)) static int parport_insn_a(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - struct parport_private *devpriv = dev->private; - if (data[0]) { devpriv->a_data &= ~data[0]; devpriv->a_data |= (data[0] & data[1]); @@ -120,8 +117,6 @@ static int parport_insn_config_a(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - struct parport_private *devpriv = dev->private; - if (data[0]) { s->io_bits = 0xff; devpriv->c_data &= ~(1 << 5); @@ -150,8 +145,6 @@ static int parport_insn_b(struct comedi_device *dev, struct comedi_subdevice *s, static int parport_insn_c(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - struct parport_private *devpriv = dev->private; - data[0] &= 0x0f; if (data[0]) { devpriv->c_data &= ~data[0]; @@ -178,20 +171,39 @@ static int parport_intr_cmdtest(struct comedi_device *dev, struct comedi_cmd *cmd) { int err = 0; + int tmp; + + /* step 1 */ - /* Step 1 : check if triggers are trivially valid */ + tmp = cmd->start_src; + cmd->start_src &= TRIG_NOW; + if (!cmd->start_src || tmp != cmd->start_src) + err++; - err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW); - err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_EXT); - err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_FOLLOW); - err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT); - err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_NONE); + tmp = cmd->scan_begin_src; + cmd->scan_begin_src &= TRIG_EXT; + if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) + err++; + + tmp = cmd->convert_src; + cmd->convert_src &= TRIG_FOLLOW; + if (!cmd->convert_src || tmp != cmd->convert_src) + err++; + + tmp = cmd->scan_end_src; + cmd->scan_end_src &= TRIG_COUNT; + if (!cmd->scan_end_src || tmp != cmd->scan_end_src) + err++; + + tmp = cmd->stop_src; + cmd->stop_src &= TRIG_NONE; + if (!cmd->stop_src || tmp != cmd->stop_src) + err++; if (err) return 1; - /* Step 2a : make sure trigger sources are unique */ - /* Step 2b : and mutually compatible */ + /* step 2: ignored */ if (err) return 2; @@ -233,8 +245,6 @@ static int parport_intr_cmdtest(struct comedi_device *dev, static int parport_intr_cmd(struct comedi_device *dev, struct comedi_subdevice *s) { - struct parport_private *devpriv = dev->private; - devpriv->c_data |= 0x10; outb(devpriv->c_data, dev->iobase + PARPORT_C); @@ -246,7 +256,7 @@ static int parport_intr_cmd(struct comedi_device *dev, static int parport_intr_cancel(struct comedi_device *dev, struct comedi_subdevice *s) { - struct parport_private *devpriv = dev->private; + printk(KERN_DEBUG "parport_intr_cancel()\n"); devpriv->c_data &= ~0x10; outb(devpriv->c_data, dev->iobase + PARPORT_C); @@ -259,11 +269,12 @@ static int parport_intr_cancel(struct comedi_device *dev, static irqreturn_t parport_interrupt(int irq, void *d) { struct comedi_device *dev = d; - struct parport_private *devpriv = dev->private; - struct comedi_subdevice *s = &dev->subdevices[3]; + struct comedi_subdevice *s = dev->subdevices + 3; - if (!devpriv->enable_irq) + if (!devpriv->enable_irq) { + printk(KERN_ERR "comedi_parport: bogus irq, ignored\n"); return IRQ_NONE; + } comedi_buf_put(s->async, 0); s->async->events |= COMEDI_CB_BLOCK | COMEDI_CB_EOS; @@ -275,42 +286,41 @@ static irqreturn_t parport_interrupt(int irq, void *d) static int parport_attach(struct comedi_device *dev, struct comedi_devconfig *it) { - struct parport_private *devpriv; int ret; unsigned int irq; unsigned long iobase; struct comedi_subdevice *s; - dev->board_name = dev->driver->driver_name; - iobase = it->options[0]; - if (!request_region(iobase, PARPORT_SIZE, dev->board_name)) { - dev_err(dev->class_dev, "I/O port conflict\n"); + printk(KERN_INFO "comedi%d: parport: 0x%04lx ", dev->minor, iobase); + if (!request_region(iobase, PARPORT_SIZE, "parport (comedi)")) { + printk(KERN_ERR "I/O port conflict\n"); return -EIO; } dev->iobase = iobase; irq = it->options[1]; if (irq) { - ret = request_irq(irq, parport_interrupt, 0, dev->board_name, + printk(KERN_INFO " irq=%u", irq); + ret = request_irq(irq, parport_interrupt, 0, "comedi_parport", dev); if (ret < 0) { - dev_err(dev->class_dev, "irq not available\n"); + printk(KERN_ERR " irq not available\n"); return -EINVAL; } dev->irq = irq; } + dev->board_name = "parport"; ret = comedi_alloc_subdevices(dev, 4); if (ret) return ret; - ret = alloc_private(dev, sizeof(*devpriv)); + ret = alloc_private(dev, sizeof(struct parport_private)); if (ret < 0) return ret; - devpriv = dev->private; - s = &dev->subdevices[0]; + s = dev->subdevices + 0; s->type = COMEDI_SUBD_DIO; s->subdev_flags = SDF_READABLE | SDF_WRITABLE; s->n_chan = 8; @@ -319,7 +329,7 @@ static int parport_attach(struct comedi_device *dev, s->insn_bits = parport_insn_a; s->insn_config = parport_insn_config_a; - s = &dev->subdevices[1]; + s = dev->subdevices + 1; s->type = COMEDI_SUBD_DI; s->subdev_flags = SDF_READABLE; s->n_chan = 5; @@ -327,7 +337,7 @@ static int parport_attach(struct comedi_device *dev, s->range_table = &range_digital; s->insn_bits = parport_insn_b; - s = &dev->subdevices[2]; + s = dev->subdevices + 2; s->type = COMEDI_SUBD_DO; s->subdev_flags = SDF_WRITABLE; s->n_chan = 4; @@ -335,7 +345,7 @@ static int parport_attach(struct comedi_device *dev, s->range_table = &range_digital; s->insn_bits = parport_insn_c; - s = &dev->subdevices[3]; + s = dev->subdevices + 3; if (irq) { dev->read_subdev = s; s->type = COMEDI_SUBD_DI; @@ -356,10 +366,8 @@ static int parport_attach(struct comedi_device *dev, devpriv->c_data = 0; outb(devpriv->c_data, dev->iobase + PARPORT_C); - dev_info(dev->class_dev, "%s: iobase=0x%04lx, irq %sabled", - dev->board_name, dev->iobase, dev->irq ? "en" : "dis"); - - return 0; + printk(KERN_INFO "\n"); + return 1; } static void parport_detach(struct comedi_device *dev) diff --git a/trunk/drivers/staging/comedi/drivers/comedi_test.c b/trunk/drivers/staging/comedi/drivers/comedi_test.c index 7817def1556c..523a809708b7 100644 --- a/trunk/drivers/staging/comedi/drivers/comedi_test.c +++ b/trunk/drivers/staging/comedi/drivers/comedi_test.c @@ -57,6 +57,14 @@ zero volts). #include "comedi_fc.h" #include +/* Board descriptions */ +struct waveform_board { + const char *name; + int ai_chans; + int ai_bits; + int have_dio; +}; + #define N_CHANS 8 /* Data unique to this driver */ @@ -73,6 +81,7 @@ struct waveform_private { unsigned timer_running:1; unsigned int ao_loopbacks[N_CHANS]; }; +#define devpriv ((struct waveform_private *)dev->private) /* 1000 nanosec in a microsec */ static const int nano_per_micro = 1000; @@ -89,7 +98,6 @@ static const struct comedi_lrange waveform_ai_ranges = { static short fake_sawtooth(struct comedi_device *dev, unsigned int range_index, unsigned long current_time) { - struct waveform_private *devpriv = dev->private; struct comedi_subdevice *s = dev->read_subdev; unsigned int offset = s->maxdata / 2; u64 value; @@ -114,7 +122,6 @@ static short fake_squarewave(struct comedi_device *dev, unsigned int range_index, unsigned long current_time) { - struct waveform_private *devpriv = dev->private; struct comedi_subdevice *s = dev->read_subdev; unsigned int offset = s->maxdata / 2; u64 value; @@ -168,7 +175,6 @@ static short fake_waveform(struct comedi_device *dev, unsigned int channel, static void waveform_ai_interrupt(unsigned long arg) { struct comedi_device *dev = (struct comedi_device *)arg; - struct waveform_private *devpriv = dev->private; struct comedi_async *async = dev->read_subdev->async; struct comedi_cmd *cmd = &async->cmd; unsigned int i, j; @@ -231,23 +237,44 @@ static int waveform_ai_cmdtest(struct comedi_device *dev, int err = 0; int tmp; - /* Step 1 : check if triggers are trivially valid */ + /* step 1: make sure trigger sources are trivially valid */ + + tmp = cmd->start_src; + cmd->start_src &= TRIG_NOW; + if (!cmd->start_src || tmp != cmd->start_src) + err++; + + tmp = cmd->scan_begin_src; + cmd->scan_begin_src &= TRIG_TIMER; + if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) + err++; + + tmp = cmd->convert_src; + cmd->convert_src &= TRIG_NOW | TRIG_TIMER; + if (!cmd->convert_src || tmp != cmd->convert_src) + err++; + + tmp = cmd->scan_end_src; + cmd->scan_end_src &= TRIG_COUNT; + if (!cmd->scan_end_src || tmp != cmd->scan_end_src) + err++; - err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW); - err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_TIMER); - err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_NOW | TRIG_TIMER); - err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT); - err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE); + tmp = cmd->stop_src; + cmd->stop_src &= TRIG_COUNT | TRIG_NONE; + if (!cmd->stop_src || tmp != cmd->stop_src) + err++; if (err) return 1; - /* Step 2a : make sure trigger sources are unique */ - - err |= cfc_check_trigger_is_unique(cmd->convert_src); - err |= cfc_check_trigger_is_unique(cmd->stop_src); + /* + * step 2: make sure trigger sources are unique and mutually compatible + */ - /* Step 2b : and mutually compatible */ + if (cmd->convert_src != TRIG_NOW && cmd->convert_src != TRIG_TIMER) + err++; + if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE) + err++; if (err) return 2; @@ -335,7 +362,6 @@ static int waveform_ai_cmdtest(struct comedi_device *dev, static int waveform_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) { - struct waveform_private *devpriv = dev->private; struct comedi_cmd *cmd = &s->async->cmd; if (cmd->flags & TRIG_RT) { @@ -369,8 +395,6 @@ static int waveform_ai_cmd(struct comedi_device *dev, static int waveform_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s) { - struct waveform_private *devpriv = dev->private; - devpriv->timer_running = 0; del_timer(&devpriv->timer); return 0; @@ -380,7 +404,6 @@ static int waveform_ai_insn_read(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - struct waveform_private *devpriv = dev->private; int i, chan = CR_CHAN(insn->chanspec); for (i = 0; i < insn->n; i++) @@ -393,7 +416,6 @@ static int waveform_ao_insn_write(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - struct waveform_private *devpriv = dev->private; int i, chan = CR_CHAN(insn->chanspec); for (i = 0; i < insn->n; i++) @@ -405,19 +427,17 @@ static int waveform_ao_insn_write(struct comedi_device *dev, static int waveform_attach(struct comedi_device *dev, struct comedi_devconfig *it) { - struct waveform_private *devpriv; + const struct waveform_board *board = comedi_board(dev); struct comedi_subdevice *s; int amplitude = it->options[0]; int period = it->options[1]; int i; int ret; - dev->board_name = dev->driver->driver_name; + dev->board_name = board->name; - ret = alloc_private(dev, sizeof(*devpriv)); - if (ret < 0) - return ret; - devpriv = dev->private; + if (alloc_private(dev, sizeof(struct waveform_private)) < 0) + return -ENOMEM; /* set default amplitude and period */ if (amplitude <= 0) @@ -432,13 +452,13 @@ static int waveform_attach(struct comedi_device *dev, if (ret) return ret; - s = &dev->subdevices[0]; + s = dev->subdevices + 0; dev->read_subdev = s; /* analog input subdevice */ s->type = COMEDI_SUBD_AI; s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_CMD_READ; - s->n_chan = N_CHANS; - s->maxdata = 0xffff; + s->n_chan = board->ai_chans; + s->maxdata = (1 << board->ai_bits) - 1; s->range_table = &waveform_ai_ranges; s->len_chanlist = s->n_chan * 2; s->insn_read = waveform_ai_insn_read; @@ -446,13 +466,13 @@ static int waveform_attach(struct comedi_device *dev, s->do_cmdtest = waveform_ai_cmdtest; s->cancel = waveform_ai_cancel; - s = &dev->subdevices[1]; + s = dev->subdevices + 1; dev->write_subdev = s; /* analog output subdevice (loopback) */ s->type = COMEDI_SUBD_AO; s->subdev_flags = SDF_WRITEABLE | SDF_GROUND; - s->n_chan = N_CHANS; - s->maxdata = 0xffff; + s->n_chan = board->ai_chans; + s->maxdata = (1 << board->ai_bits) - 1; s->range_table = &waveform_ai_ranges; s->len_chanlist = s->n_chan * 2; s->insn_write = waveform_ao_insn_write; @@ -468,27 +488,35 @@ static int waveform_attach(struct comedi_device *dev, devpriv->timer.function = waveform_ai_interrupt; devpriv->timer.data = (unsigned long)dev; - dev_info(dev->class_dev, - "%s: %i microvolt, %li microsecond waveform attached\n", - dev->board_name, - devpriv->uvolt_amplitude, devpriv->usec_period); - - return 0; + printk(KERN_INFO "comedi%d: comedi_test: " + "%i microvolt, %li microsecond waveform attached\n", dev->minor, + devpriv->uvolt_amplitude, devpriv->usec_period); + return 1; } static void waveform_detach(struct comedi_device *dev) { - struct waveform_private *devpriv = dev->private; - - if (devpriv) + if (dev->private) waveform_ai_cancel(dev, dev->read_subdev); } +static const struct waveform_board waveform_boards[] = { + { + .name = "comedi_test", + .ai_chans = N_CHANS, + .ai_bits = 16, + .have_dio = 0, + }, +}; + static struct comedi_driver waveform_driver = { .driver_name = "comedi_test", .module = THIS_MODULE, .attach = waveform_attach, .detach = waveform_detach, + .board_name = &waveform_boards[0].name, + .offset = sizeof(struct waveform_board), + .num_names = ARRAY_SIZE(waveform_boards), }; module_comedi_driver(waveform_driver); diff --git a/trunk/drivers/staging/comedi/drivers/contec_pci_dio.c b/trunk/drivers/staging/comedi/drivers/contec_pci_dio.c index 178a6a4bb7d5..944cfeeb2b2d 100644 --- a/trunk/drivers/staging/comedi/drivers/contec_pci_dio.c +++ b/trunk/drivers/staging/comedi/drivers/contec_pci_dio.c @@ -27,35 +27,51 @@ Author: Stefano Rivoir Updated: Wed, 27 Jun 2007 13:00:06 +0100 Status: works -Configuration Options: not applicable, uses comedi PCI auto config +Configuration Options: + [0] - PCI bus of device (optional) + [1] - PCI slot of device (optional) + If bus/slot is not specified, the first supported + PCI device found will be used. */ #include "../comedidev.h" +enum contec_model { + PIO1616L = 0, +}; + +struct contec_board { + const char *name; + int model; + int in_ports; + int out_ports; + int in_offs; + int out_offs; + int out_boffs; +}; +static const struct contec_board contec_boards[] = { + {"PIO1616L", PIO1616L, 16, 16, 0, 2, 10}, +}; + #define PCI_DEVICE_ID_PIO1616L 0x8172 -/* - * Register map - */ -#define PIO1616L_DI_REG 0x00 -#define PIO1616L_DO_REG 0x02 +#define thisboard ((const struct contec_board *)dev->board_ptr) static int contec_do_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - unsigned int mask = data[0]; - unsigned int bits = data[1]; - if (mask) { - s->state &= ~mask; - s->state |= (bits & mask); + dev_dbg(dev->class_dev, "contec_do_insn_bits called\n"); + dev_dbg(dev->class_dev, "data: %d %d\n", data[0], data[1]); - outw(s->state, dev->iobase + PIO1616L_DO_REG); + if (data[0]) { + s->state &= ~data[0]; + s->state |= data[0] & data[1]; + dev_dbg(dev->class_dev, "out: %d on %lx\n", s->state, + dev->iobase + thisboard->out_offs); + outw(s->state, dev->iobase + thisboard->out_offs); } - - data[1] = s->state; - return insn->n; } @@ -63,49 +79,87 @@ static int contec_di_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - data[1] = inw(dev->iobase + PIO1616L_DI_REG); + + dev_dbg(dev->class_dev, "contec_di_insn_bits called\n"); + dev_dbg(dev->class_dev, "data: %d %d\n", data[0], data[1]); + + data[1] = inw(dev->iobase + thisboard->in_offs); return insn->n; } -static int contec_attach_pci(struct comedi_device *dev, - struct pci_dev *pcidev) +static struct pci_dev *contec_find_pci_dev(struct comedi_device *dev, + struct comedi_devconfig *it) +{ + struct pci_dev *pcidev = NULL; + int bus = it->options[0]; + int slot = it->options[1]; + + for_each_pci_dev(pcidev) { + if (bus || slot) { + if (bus != pcidev->bus->number || + slot != PCI_SLOT(pcidev->devfn)) + continue; + } + if (pcidev->vendor != PCI_VENDOR_ID_CONTEC || + pcidev->device != PCI_DEVICE_ID_PIO1616L) + continue; + + dev->board_ptr = contec_boards + 0; + return pcidev; + } + dev_err(dev->class_dev, + "No supported board found! (req. bus %d, slot %d)\n", + bus, slot); + return NULL; +} + +static int contec_attach(struct comedi_device *dev, struct comedi_devconfig *it) { + struct pci_dev *pcidev; struct comedi_subdevice *s; int ret; - comedi_set_hw_dev(dev, &pcidev->dev); + printk("comedi%d: contec: ", dev->minor); - dev->board_name = dev->driver->driver_name; + dev->board_name = thisboard->name; - ret = comedi_pci_enable(pcidev, dev->board_name); + ret = comedi_alloc_subdevices(dev, 2); if (ret) return ret; + + pcidev = contec_find_pci_dev(dev, it); + if (!pcidev) + return -EIO; + comedi_set_hw_dev(dev, &pcidev->dev); + + if (comedi_pci_enable(pcidev, "contec_pci_dio")) { + printk("error enabling PCI device and request regions!\n"); + return -EIO; + } dev->iobase = pci_resource_start(pcidev, 0); + printk(" base addr %lx ", dev->iobase); - ret = comedi_alloc_subdevices(dev, 2); - if (ret) - return ret; + s = dev->subdevices + 0; + + s->type = COMEDI_SUBD_DI; + s->subdev_flags = SDF_READABLE; + s->n_chan = 16; + s->maxdata = 1; + s->range_table = &range_digital; + s->insn_bits = contec_di_insn_bits; + + s = dev->subdevices + 1; + s->type = COMEDI_SUBD_DO; + s->subdev_flags = SDF_WRITABLE; + s->n_chan = 16; + s->maxdata = 1; + s->range_table = &range_digital; + s->insn_bits = contec_do_insn_bits; + + printk("attached\n"); - s = &dev->subdevices[0]; - s->type = COMEDI_SUBD_DI; - s->subdev_flags = SDF_READABLE; - s->n_chan = 16; - s->maxdata = 1; - s->range_table = &range_digital; - s->insn_bits = contec_di_insn_bits; - - s = &dev->subdevices[1]; - s->type = COMEDI_SUBD_DO; - s->subdev_flags = SDF_WRITABLE; - s->n_chan = 16; - s->maxdata = 1; - s->range_table = &range_digital; - s->insn_bits = contec_do_insn_bits; - - dev_info(dev->class_dev, "%s attached\n", dev->board_name); - - return 0; + return 1; } static void contec_detach(struct comedi_device *dev) @@ -115,13 +169,14 @@ static void contec_detach(struct comedi_device *dev) if (pcidev) { if (dev->iobase) comedi_pci_disable(pcidev); + pci_dev_put(pcidev); } } static struct comedi_driver contec_pci_dio_driver = { .driver_name = "contec_pci_dio", .module = THIS_MODULE, - .attach_pci = contec_attach_pci, + .attach = contec_attach, .detach = contec_detach, }; @@ -137,7 +192,8 @@ static void __devexit contec_pci_dio_pci_remove(struct pci_dev *dev) } static DEFINE_PCI_DEVICE_TABLE(contec_pci_dio_pci_table) = { - { PCI_DEVICE(PCI_VENDOR_ID_CONTEC, PCI_DEVICE_ID_PIO1616L) }, + { PCI_DEVICE(PCI_VENDOR_ID_CONTEC, PCI_DEVICE_ID_PIO1616L), + .driver_data = PIO1616L }, { 0 } }; MODULE_DEVICE_TABLE(pci, contec_pci_dio_pci_table); diff --git a/trunk/drivers/staging/comedi/drivers/daqboard2000.c b/trunk/drivers/staging/comedi/drivers/daqboard2000.c index d13c8c5822bf..ef28385c1482 100644 --- a/trunk/drivers/staging/comedi/drivers/daqboard2000.c +++ b/trunk/drivers/staging/comedi/drivers/daqboard2000.c @@ -31,10 +31,16 @@ Devices: [IOTech] DAQBoard/2000 (daqboard2000) Much of the functionality of this driver was determined from reading the source code for the Windows driver. -The FPGA on the board requires fimware, which is available from -http://www.comedi.org in the comedi_nonfree_firmware tarball. - -Configuration options: not applicable, uses PCI auto config +The FPGA on the board requires initialization code, which can +be loaded by comedi_config using the -i +option. The initialization code is available from http://www.comedi.org +in the comedi_nonfree_firmware tarball. + +Configuration options: + [0] - PCI bus of device (optional) + [1] - PCI slot of device (optional) + If bus/slot is not specified, the first supported + PCI device found will be used. */ /* This card was obviously never intended to leave the Windows world, @@ -111,17 +117,17 @@ Configuration options: not applicable, uses PCI auto config #include #include -#include #include "8255.h" -#define DAQBOARD2000_FIRMWARE "daqboard2000_firmware.bin" - #define PCI_VENDOR_ID_IOTECH 0x1616 #define DAQBOARD2000_SUBSYSTEM_IDS2 0x0002 /* Daqboard/2000 - 2 Dacs */ #define DAQBOARD2000_SUBSYSTEM_IDS4 0x0004 /* Daqboard/2000 - 4 Dacs */ +#define DAQBOARD2000_DAQ_SIZE 0x1002 +#define DAQBOARD2000_PLX_SIZE 0x100 + /* Initialization bits for the Serial EEPROM Control Register */ #define DAQBOARD2000_SECRProgPinHi 0x8001767e #define DAQBOARD2000_SECRProgPinLo 0x8000767e @@ -137,56 +143,85 @@ Configuration options: not applicable, uses PCI auto config #define DAQBOARD2000_CPLD_INIT 0x0002 #define DAQBOARD2000_CPLD_DONE 0x0004 -static const struct comedi_lrange range_daqboard2000_ai = { - 13, { - BIP_RANGE(10), - BIP_RANGE(5), - BIP_RANGE(2.5), - BIP_RANGE(1.25), - BIP_RANGE(0.625), - BIP_RANGE(0.3125), - BIP_RANGE(0.156), - UNI_RANGE(10), - UNI_RANGE(5), - UNI_RANGE(2.5), - UNI_RANGE(1.25), - UNI_RANGE(0.625), - UNI_RANGE(0.3125) - } +/* Available ranges */ +static const struct comedi_lrange range_daqboard2000_ai = { 13, { + RANGE(-10, 10), + RANGE(-5, 5), + RANGE(-2.5, + 2.5), + RANGE(-1.25, + 1.25), + RANGE(-0.625, + 0.625), + RANGE(-0.3125, + 0.3125), + RANGE(-0.156, + 0.156), + RANGE(0, 10), + RANGE(0, 5), + RANGE(0, 2.5), + RANGE(0, 1.25), + RANGE(0, + 0.625), + RANGE(0, + 0.3125) + } }; -/* - * Register Memory Map - */ -#define acqControl 0x00 /* u16 */ -#define acqScanListFIFO 0x02 /* u16 */ -#define acqPacerClockDivLow 0x04 /* u32 */ -#define acqScanCounter 0x08 /* u16 */ -#define acqPacerClockDivHigh 0x0a /* u16 */ -#define acqTriggerCount 0x0c /* u16 */ -#define acqResultsFIFO 0x10 /* u16 */ -#define acqResultsShadow 0x14 /* u16 */ -#define acqAdcResult 0x18 /* u16 */ -#define dacScanCounter 0x1c /* u16 */ -#define dacControl 0x20 /* u16 */ -#define dacFIFO 0x24 /* s16 */ -#define dacPacerClockDiv 0x2a /* u16 */ -#define refDacs 0x2c /* u16 */ -#define dioControl 0x30 /* u16 */ -#define dioP3hsioData 0x32 /* s16 */ -#define dioP3Control 0x34 /* u16 */ -#define calEepromControl 0x36 /* u16 */ -#define dacSetting(x) (0x38 + (x)*2) /* s16 */ -#define dioP2ExpansionIO8Bit 0x40 /* s16 */ -#define ctrTmrControl 0x80 /* u16 */ -#define ctrInput(x) (0x88 + (x)*2) /* s16 */ -#define timerDivisor(x) (0xa0 + (x)*2) /* u16 */ -#define dmaControl 0xb0 /* u16 */ -#define trigControl 0xb2 /* u16 */ -#define calEeprom 0xb8 /* u16 */ -#define acqDigitalMark 0xba /* u16 */ -#define trigDacs 0xbc /* u16 */ -#define dioP2ExpansionIO16Bit(x) (0xc0 + (x)*2) /* s16 */ +static const struct comedi_lrange range_daqboard2000_ao = { 1, { + RANGE(-10, 10) + } +}; + +struct daqboard2000_hw { + volatile u16 acqControl; /* 0x00 */ + volatile u16 acqScanListFIFO; /* 0x02 */ + volatile u32 acqPacerClockDivLow; /* 0x04 */ + + volatile u16 acqScanCounter; /* 0x08 */ + volatile u16 acqPacerClockDivHigh; /* 0x0a */ + volatile u16 acqTriggerCount; /* 0x0c */ + volatile u16 fill2; /* 0x0e */ + volatile u16 acqResultsFIFO; /* 0x10 */ + volatile u16 fill3; /* 0x12 */ + volatile u16 acqResultsShadow; /* 0x14 */ + volatile u16 fill4; /* 0x16 */ + volatile u16 acqAdcResult; /* 0x18 */ + volatile u16 fill5; /* 0x1a */ + volatile u16 dacScanCounter; /* 0x1c */ + volatile u16 fill6; /* 0x1e */ + + volatile u16 dacControl; /* 0x20 */ + volatile u16 fill7; /* 0x22 */ + volatile s16 dacFIFO; /* 0x24 */ + volatile u16 fill8[2]; /* 0x26 */ + volatile u16 dacPacerClockDiv; /* 0x2a */ + volatile u16 refDacs; /* 0x2c */ + volatile u16 fill9; /* 0x2e */ + + volatile u16 dioControl; /* 0x30 */ + volatile s16 dioP3hsioData; /* 0x32 */ + volatile u16 dioP3Control; /* 0x34 */ + volatile u16 calEepromControl; /* 0x36 */ + volatile s16 dacSetting[4]; /* 0x38 */ + volatile s16 dioP2ExpansionIO8Bit[32]; /* 0x40 */ + + volatile u16 ctrTmrControl; /* 0x80 */ + volatile u16 fill10[3]; /* 0x82 */ + volatile s16 ctrInput[4]; /* 0x88 */ + volatile u16 fill11[8]; /* 0x90 */ + volatile u16 timerDivisor[2]; /* 0xa0 */ + volatile u16 fill12[6]; /* 0xa4 */ + + volatile u16 dmaControl; /* 0xb0 */ + volatile u16 trigControl; /* 0xb2 */ + volatile u16 fill13[2]; /* 0xb4 */ + volatile u16 calEeprom; /* 0xb8 */ + volatile u16 acqDigitalMark; /* 0xba */ + volatile u16 trigDacs; /* 0xbc */ + volatile u16 fill14; /* 0xbe */ + volatile s16 dioP2ExpansionIO16Bit[32]; /* 0xc0 */ +}; /* Scan Sequencer programming */ #define DAQBOARD2000_SeqStartScanList 0x0011 @@ -276,23 +311,27 @@ static const struct daq200_boardtype boardtypes[] = { {"ids4", DAQBOARD2000_SUBSYSTEM_IDS4}, }; +#define this_board ((const struct daq200_boardtype *)dev->board_ptr) + struct daqboard2000_private { enum { card_daqboard_2000 } card; - void __iomem *daq; + void *daq; void __iomem *plx; unsigned int ao_readback[2]; }; +#define devpriv ((struct daqboard2000_private *)dev->private) + static void writeAcqScanListEntry(struct comedi_device *dev, u16 entry) { - struct daqboard2000_private *devpriv = dev->private; + struct daqboard2000_hw *fpga = devpriv->daq; - /* udelay(4); */ - writew(entry & 0x00ff, devpriv->daq + acqScanListFIFO); - /* udelay(4); */ - writew((entry >> 8) & 0x00ff, devpriv->daq + acqScanListFIFO); +/* udelay(4); */ + fpga->acqScanListFIFO = entry & 0x00ff; +/* udelay(4); */ + fpga->acqScanListFIFO = (entry >> 8) & 0x00ff; } static void setup_sampling(struct comedi_device *dev, int chan, int gain) @@ -333,6 +372,7 @@ static void setup_sampling(struct comedi_device *dev, int chan, int gain) /* These should be read from EEPROM */ word2 |= 0x0800; word3 |= 0xc000; +/* printk("%d %4.4x %4.4x %4.4x %4.4x\n", chan, word0, word1, word2, word3);*/ writeAcqScanListEntry(dev, word0); writeAcqScanListEntry(dev, word1); writeAcqScanListEntry(dev, word2); @@ -344,22 +384,21 @@ static int daqboard2000_ai_insn_read(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data) { - struct daqboard2000_private *devpriv = dev->private; - unsigned int val; - int gain, chan, timeout; int i; + struct daqboard2000_hw *fpga = devpriv->daq; + int gain, chan, timeout; - writew(DAQBOARD2000_AcqResetScanListFifo | - DAQBOARD2000_AcqResetResultsFifo | - DAQBOARD2000_AcqResetConfigPipe, devpriv->daq + acqControl); + fpga->acqControl = + DAQBOARD2000_AcqResetScanListFifo | + DAQBOARD2000_AcqResetResultsFifo | DAQBOARD2000_AcqResetConfigPipe; /* * If pacer clock is not set to some high value (> 10 us), we * risk multiple samples to be put into the result FIFO. */ /* 1 second, should be long enough */ - writel(1000000, devpriv->daq + acqPacerClockDivLow); - writew(0, devpriv->daq + acqPacerClockDivHigh); + fpga->acqPacerClockDivLow = 1000000; + fpga->acqPacerClockDivHigh = 0; gain = CR_RANGE(insn->chanspec); chan = CR_CHAN(insn->chanspec); @@ -371,30 +410,28 @@ static int daqboard2000_ai_insn_read(struct comedi_device *dev, for (i = 0; i < insn->n; i++) { setup_sampling(dev, chan, gain); /* Enable reading from the scanlist FIFO */ - writew(DAQBOARD2000_SeqStartScanList, - devpriv->daq + acqControl); + fpga->acqControl = DAQBOARD2000_SeqStartScanList; for (timeout = 0; timeout < 20; timeout++) { - val = readw(devpriv->daq + acqControl); - if (val & DAQBOARD2000_AcqConfigPipeFull) + if (fpga->acqControl & DAQBOARD2000_AcqConfigPipeFull) break; /* udelay(2); */ } - writew(DAQBOARD2000_AdcPacerEnable, devpriv->daq + acqControl); + fpga->acqControl = DAQBOARD2000_AdcPacerEnable; for (timeout = 0; timeout < 20; timeout++) { - val = readw(devpriv->daq + acqControl); - if (val & DAQBOARD2000_AcqLogicScanning) + if (fpga->acqControl & DAQBOARD2000_AcqLogicScanning) break; /* udelay(2); */ } for (timeout = 0; timeout < 20; timeout++) { - val = readw(devpriv->daq + acqControl); - if (val & DAQBOARD2000_AcqResultsFIFOHasValidData) + if (fpga->acqControl & + DAQBOARD2000_AcqResultsFIFOHasValidData) { break; + } /* udelay(2); */ } - data[i] = readw(devpriv->daq + acqResultsFIFO); - writew(DAQBOARD2000_AdcPacerDisable, devpriv->daq + acqControl); - writew(DAQBOARD2000_SeqStopScanList, devpriv->daq + acqControl); + data[i] = fpga->acqResultsFIFO; + fpga->acqControl = DAQBOARD2000_AdcPacerDisable; + fpga->acqControl = DAQBOARD2000_SeqStopScanList; } return i; @@ -405,9 +442,8 @@ static int daqboard2000_ao_insn_read(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data) { - struct daqboard2000_private *devpriv = dev->private; - int chan = CR_CHAN(insn->chanspec); int i; + int chan = CR_CHAN(insn->chanspec); for (i = 0; i < insn->n; i++) data[i] = devpriv->ao_readback[chan]; @@ -420,39 +456,28 @@ static int daqboard2000_ao_insn_write(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data) { - struct daqboard2000_private *devpriv = dev->private; + int i; int chan = CR_CHAN(insn->chanspec); - unsigned int val; + struct daqboard2000_hw *fpga = devpriv->daq; int timeout; - int i; for (i = 0; i < insn->n; i++) { -#if 0 /* - * OK, since it works OK without enabling the DAC's, - * let's keep it as simple as possible... + * OK, since it works OK without enabling the DAC's, let's keep + * it as simple as possible... */ - writew((chan + 2) * 0x0010 | 0x0001, - devpriv->daq + dacControl); - udelay(1000); -#endif - writew(data[i], devpriv->daq + dacSetting(chan)); + /* fpga->dacControl = (chan + 2) * 0x0010 | 0x0001; udelay(1000); */ + fpga->dacSetting[chan] = data[i]; for (timeout = 0; timeout < 20; timeout++) { - val = readw(devpriv->daq + dacControl); - if ((val & ((chan + 1) * 0x0010)) == 0) + if ((fpga->dacControl & ((chan + 1) * 0x0010)) == 0) break; /* udelay(2); */ } devpriv->ao_readback[chan] = data[i]; -#if 0 /* - * Since we never enabled the DAC's, we don't need - * to disable it... + * Since we never enabled the DAC's, we don't need to disable it... + * fpga->dacControl = (chan + 2) * 0x0010 | 0x0000; udelay(1000); */ - writew((chan + 2) * 0x0010 | 0x0000, - devpriv->daq + dacControl); - udelay(1000); -#endif } return i; @@ -460,8 +485,7 @@ static int daqboard2000_ao_insn_write(struct comedi_device *dev, static void daqboard2000_resetLocalBus(struct comedi_device *dev) { - struct daqboard2000_private *devpriv = dev->private; - + dev_dbg(dev->class_dev, "daqboard2000_resetLocalBus\n"); writel(DAQBOARD2000_SECRLocalBusHi, devpriv->plx + 0x6c); udelay(10000); writel(DAQBOARD2000_SECRLocalBusLo, devpriv->plx + 0x6c); @@ -470,8 +494,7 @@ static void daqboard2000_resetLocalBus(struct comedi_device *dev) static void daqboard2000_reloadPLX(struct comedi_device *dev) { - struct daqboard2000_private *devpriv = dev->private; - + dev_dbg(dev->class_dev, "daqboard2000_reloadPLX\n"); writel(DAQBOARD2000_SECRReloadLo, devpriv->plx + 0x6c); udelay(10000); writel(DAQBOARD2000_SECRReloadHi, devpriv->plx + 0x6c); @@ -482,8 +505,7 @@ static void daqboard2000_reloadPLX(struct comedi_device *dev) static void daqboard2000_pulseProgPin(struct comedi_device *dev) { - struct daqboard2000_private *devpriv = dev->private; - + dev_dbg(dev->class_dev, "daqboard2000_pulseProgPin 1\n"); writel(DAQBOARD2000_SECRProgPinHi, devpriv->plx + 0x6c); udelay(10000); writel(DAQBOARD2000_SECRProgPinLo, devpriv->plx + 0x6c); @@ -492,7 +514,6 @@ static void daqboard2000_pulseProgPin(struct comedi_device *dev) static int daqboard2000_pollCPLD(struct comedi_device *dev, int mask) { - struct daqboard2000_private *devpriv = dev->private; int result = 0; int i; int cpld; @@ -512,7 +533,6 @@ static int daqboard2000_pollCPLD(struct comedi_device *dev, int mask) static int daqboard2000_writeCPLD(struct comedi_device *dev, int data) { - struct daqboard2000_private *devpriv = dev->private; int result = 0; udelay(10); @@ -525,29 +545,41 @@ static int daqboard2000_writeCPLD(struct comedi_device *dev, int data) } static int initialize_daqboard2000(struct comedi_device *dev, - const u8 *cpld_array, size_t len) + unsigned char *cpld_array, int len) { - struct daqboard2000_private *devpriv = dev->private; int result = -EIO; /* Read the serial EEPROM control register */ int secr; int retry; - size_t i; + int i; /* Check to make sure the serial eeprom is present on the board */ secr = readl(devpriv->plx + 0x6c); - if (!(secr & DAQBOARD2000_EEPROM_PRESENT)) + if (!(secr & DAQBOARD2000_EEPROM_PRESENT)) { +#ifdef DEBUG_EEPROM + dev_dbg(dev->class_dev, "no serial eeprom\n"); +#endif return -EIO; + } for (retry = 0; retry < 3; retry++) { +#ifdef DEBUG_EEPROM + dev_dbg(dev->class_dev, "Programming EEPROM try %x\n", retry); +#endif + daqboard2000_resetLocalBus(dev); daqboard2000_reloadPLX(dev); daqboard2000_pulseProgPin(dev); if (daqboard2000_pollCPLD(dev, DAQBOARD2000_CPLD_INIT)) { for (i = 0; i < len; i++) { - if (cpld_array[i] == 0xff && - cpld_array[i + 1] == 0x20) + if (cpld_array[i] == 0xff + && cpld_array[i + 1] == 0x20) { +#ifdef DEBUG_EEPROM + dev_dbg(dev->class_dev, + "Preamble found at %d\n", i); +#endif break; + } } for (; i < len; i += 2) { int data = @@ -556,6 +588,9 @@ static int initialize_daqboard2000(struct comedi_device *dev, break; } if (i >= len) { +#ifdef DEBUG_EEPROM + dev_dbg(dev->class_dev, "Programmed\n"); +#endif daqboard2000_resetLocalBus(dev); daqboard2000_reloadPLX(dev); result = 0; @@ -566,45 +601,28 @@ static int initialize_daqboard2000(struct comedi_device *dev, return result; } -static int daqboard2000_upload_firmware(struct comedi_device *dev) -{ - struct pci_dev *pcidev = comedi_to_pci_dev(dev); - const struct firmware *fw; - int ret; - - ret = request_firmware(&fw, DAQBOARD2000_FIRMWARE, &pcidev->dev); - if (ret) - return ret; - - ret = initialize_daqboard2000(dev, fw->data, fw->size); - release_firmware(fw); - - return ret; -} - static void daqboard2000_adcStopDmaTransfer(struct comedi_device *dev) { +/* printk("Implement: daqboard2000_adcStopDmaTransfer\n");*/ } static void daqboard2000_adcDisarm(struct comedi_device *dev) { - struct daqboard2000_private *devpriv = dev->private; + struct daqboard2000_hw *fpga = devpriv->daq; /* Disable hardware triggers */ udelay(2); - writew(DAQBOARD2000_TrigAnalog | DAQBOARD2000_TrigDisable, - devpriv->daq + trigControl); + fpga->trigControl = DAQBOARD2000_TrigAnalog | DAQBOARD2000_TrigDisable; udelay(2); - writew(DAQBOARD2000_TrigTTL | DAQBOARD2000_TrigDisable, - devpriv->daq + trigControl); + fpga->trigControl = DAQBOARD2000_TrigTTL | DAQBOARD2000_TrigDisable; /* Stop the scan list FIFO from loading the configuration pipe */ udelay(2); - writew(DAQBOARD2000_SeqStopScanList, devpriv->daq + acqControl); + fpga->acqControl = DAQBOARD2000_SeqStopScanList; /* Stop the pacer clock */ udelay(2); - writew(DAQBOARD2000_AdcPacerDisable, devpriv->daq + acqControl); + fpga->acqControl = DAQBOARD2000_AdcPacerDisable; /* Stop the input dma (abort channel 1) */ daqboard2000_adcStopDmaTransfer(dev); @@ -612,39 +630,41 @@ static void daqboard2000_adcDisarm(struct comedi_device *dev) static void daqboard2000_activateReferenceDacs(struct comedi_device *dev) { - struct daqboard2000_private *devpriv = dev->private; - unsigned int val; + struct daqboard2000_hw *fpga = devpriv->daq; int timeout; /* Set the + reference dac value in the FPGA */ - writew(0x80 | DAQBOARD2000_PosRefDacSelect, devpriv->daq + refDacs); + fpga->refDacs = 0x80 | DAQBOARD2000_PosRefDacSelect; for (timeout = 0; timeout < 20; timeout++) { - val = readw(devpriv->daq + dacControl); - if ((val & DAQBOARD2000_RefBusy) == 0) + if ((fpga->dacControl & DAQBOARD2000_RefBusy) == 0) break; udelay(2); } +/* printk("DAQBOARD2000_PosRefDacSelect %d\n", timeout);*/ /* Set the - reference dac value in the FPGA */ - writew(0x80 | DAQBOARD2000_NegRefDacSelect, devpriv->daq + refDacs); + fpga->refDacs = 0x80 | DAQBOARD2000_NegRefDacSelect; for (timeout = 0; timeout < 20; timeout++) { - val = readw(devpriv->daq + dacControl); - if ((val & DAQBOARD2000_RefBusy) == 0) + if ((fpga->dacControl & DAQBOARD2000_RefBusy) == 0) break; udelay(2); } +/* printk("DAQBOARD2000_NegRefDacSelect %d\n", timeout);*/ } static void daqboard2000_initializeCtrs(struct comedi_device *dev) { +/* printk("Implement: daqboard2000_initializeCtrs\n");*/ } static void daqboard2000_initializeTmrs(struct comedi_device *dev) { +/* printk("Implement: daqboard2000_initializeTmrs\n");*/ } static void daqboard2000_dacDisarm(struct comedi_device *dev) { +/* printk("Implement: daqboard2000_dacDisarm\n");*/ } static void daqboard2000_initializeAdc(struct comedi_device *dev) @@ -660,66 +680,89 @@ static void daqboard2000_initializeDac(struct comedi_device *dev) daqboard2000_dacDisarm(dev); } +/* +The test command, REMOVE!!: + +rmmod daqboard2000 ; rmmod comedi; make install ; modprobe daqboard2000; /usr/sbin/comedi_config /dev/comedi0 daqboard/2000 ; tail -40 /var/log/messages +*/ + static int daqboard2000_8255_cb(int dir, int port, int data, unsigned long ioaddr) { - void __iomem *mmio_base = (void __iomem *)ioaddr; - + int result = 0; if (dir) { - writew(data, mmio_base + port * 2); - return 0; + writew(data, ((void *)ioaddr) + port * 2); + result = 0; } else { - return readw(mmio_base + port * 2); + result = readw(((void *)ioaddr) + port * 2); } +/* + printk("daqboard2000_8255_cb %x %d %d %2.2x -> %2.2x\n", + arg, dir, port, data, result); +*/ + return result; } -static const void *daqboard2000_find_boardinfo(struct comedi_device *dev, - struct pci_dev *pcidev) +static struct pci_dev *daqboard2000_find_pci_dev(struct comedi_device *dev, + struct comedi_devconfig *it) { - const struct daq200_boardtype *board; + struct pci_dev *pcidev = NULL; + int bus = it->options[0]; + int slot = it->options[1]; int i; - if (pcidev->subsystem_device != PCI_VENDOR_ID_IOTECH) - return NULL; - - for (i = 0; i < ARRAY_SIZE(boardtypes); i++) { - board = &boardtypes[i]; - if (pcidev->subsystem_device == board->id) - return board; + for_each_pci_dev(pcidev) { + if (bus || slot) { + if (bus != pcidev->bus->number || + slot != PCI_SLOT(pcidev->devfn)) + continue; + } + if (pcidev->vendor != PCI_VENDOR_ID_IOTECH || + pcidev->device != 0x0409) + continue; + + for (i = 0; i < ARRAY_SIZE(boardtypes); i++) { + if (boardtypes[i].id != pcidev->subsystem_device) + continue; + dev->board_ptr = boardtypes + i; + return pcidev; + } } + dev_err(dev->class_dev, + "No supported board found! (req. bus %d, slot %d)\n", + bus, slot); return NULL; } -static int daqboard2000_attach_pci(struct comedi_device *dev, - struct pci_dev *pcidev) +static int daqboard2000_attach(struct comedi_device *dev, + struct comedi_devconfig *it) { - const struct daq200_boardtype *board; - struct daqboard2000_private *devpriv; + struct pci_dev *pcidev; struct comedi_subdevice *s; + void *aux_data; + unsigned int aux_len; int result; - comedi_set_hw_dev(dev, &pcidev->dev); - - board = daqboard2000_find_boardinfo(dev, pcidev); - if (!board) - return -ENODEV; - dev->board_ptr = board; - dev->board_name = board->name; - - result = alloc_private(dev, sizeof(*devpriv)); + result = alloc_private(dev, sizeof(struct daqboard2000_private)); if (result < 0) return -ENOMEM; - devpriv = dev->private; - result = comedi_pci_enable(pcidev, dev->driver->driver_name); - if (result < 0) - return result; - dev->iobase = 1; /* the "detach" needs this */ + pcidev = daqboard2000_find_pci_dev(dev, it); + if (!pcidev) + return -EIO; + comedi_set_hw_dev(dev, &pcidev->dev); - devpriv->plx = ioremap(pci_resource_start(pcidev, 0), - pci_resource_len(pcidev, 0)); - devpriv->daq = ioremap(pci_resource_start(pcidev, 2), - pci_resource_len(pcidev, 2)); + result = comedi_pci_enable(pcidev, "daqboard2000"); + if (result < 0) { + dev_err(dev->class_dev, + "failed to enable PCI device and request regions\n"); + return -EIO; + } + dev->iobase = pci_resource_start(pcidev, 2); + + devpriv->plx = + ioremap(pci_resource_start(pcidev, 0), DAQBOARD2000_PLX_SIZE); + devpriv->daq = ioremap(dev->iobase, DAQBOARD2000_DAQ_SIZE); if (!devpriv->plx || !devpriv->daq) return -ENOMEM; @@ -729,14 +772,38 @@ static int daqboard2000_attach_pci(struct comedi_device *dev, readl(devpriv->plx + 0x6c); - result = daqboard2000_upload_firmware(dev); - if (result < 0) - return result; + /* + u8 interrupt; + Windows code does restore interrupts, but since we don't use them... + pci_read_config_byte(pcidev, PCI_INTERRUPT_LINE, &interrupt); + printk("Interrupt before is: %x\n", interrupt); + */ + + aux_data = comedi_aux_data(it->options, 0); + aux_len = it->options[COMEDI_DEVCONF_AUX_DATA_LENGTH]; + if (aux_data && aux_len) { + result = initialize_daqboard2000(dev, aux_data, aux_len); + } else { + dev_dbg(dev->class_dev, + "no FPGA initialization code, aborting\n"); + result = -EIO; + } + if (result < 0) + goto out; daqboard2000_initializeAdc(dev); daqboard2000_initializeDac(dev); + /* + Windows code does restore interrupts, but since we don't use them... + pci_read_config_byte(pcidev, PCI_INTERRUPT_LINE, &interrupt); + printk("Interrupt after is: %x\n", interrupt); + */ + + dev->iobase = (unsigned long)devpriv->daq; + + dev->board_name = this_board->name; - s = &dev->subdevices[0]; + s = dev->subdevices + 0; /* ai subdevice */ s->type = COMEDI_SUBD_AI; s->subdev_flags = SDF_READABLE | SDF_GROUND; @@ -745,7 +812,7 @@ static int daqboard2000_attach_pci(struct comedi_device *dev, s->insn_read = daqboard2000_ai_insn_read; s->range_table = &range_daqboard2000_ai; - s = &dev->subdevices[1]; + s = dev->subdevices + 1; /* ao subdevice */ s->type = COMEDI_SUBD_AO; s->subdev_flags = SDF_WRITABLE; @@ -753,27 +820,22 @@ static int daqboard2000_attach_pci(struct comedi_device *dev, s->maxdata = 0xffff; s->insn_read = daqboard2000_ao_insn_read; s->insn_write = daqboard2000_ao_insn_write; - s->range_table = &range_bipolar10; + s->range_table = &range_daqboard2000_ao; - s = &dev->subdevices[2]; + s = dev->subdevices + 2; result = subdev_8255_init(dev, s, daqboard2000_8255_cb, - (unsigned long)(devpriv->daq + dioP2ExpansionIO8Bit)); - if (result) - return result; + (unsigned long)(dev->iobase + 0x40)); - dev_info(dev->class_dev, "%s: %s attached\n", - dev->driver->driver_name, dev->board_name); - - return 0; +out: + return result; } static void daqboard2000_detach(struct comedi_device *dev) { struct pci_dev *pcidev = comedi_to_pci_dev(dev); - struct daqboard2000_private *devpriv = dev->private; if (dev->subdevices) - subdev_8255_cleanup(dev, &dev->subdevices[2]); + subdev_8255_cleanup(dev, dev->subdevices + 2); if (dev->irq) free_irq(dev->irq, dev); if (devpriv) { @@ -792,7 +854,7 @@ static void daqboard2000_detach(struct comedi_device *dev) static struct comedi_driver daqboard2000_driver = { .driver_name = "daqboard2000", .module = THIS_MODULE, - .attach_pci = daqboard2000_attach_pci, + .attach = daqboard2000_attach, .detach = daqboard2000_detach, }; @@ -824,4 +886,3 @@ module_comedi_pci_driver(daqboard2000_driver, daqboard2000_pci_driver); MODULE_AUTHOR("Comedi http://www.comedi.org"); MODULE_DESCRIPTION("Comedi low-level driver"); MODULE_LICENSE("GPL"); -MODULE_FIRMWARE(DAQBOARD2000_FIRMWARE); diff --git a/trunk/drivers/staging/comedi/drivers/das08.c b/trunk/drivers/staging/comedi/drivers/das08.c index 5fd21fa6c1c7..874e02e47668 100644 --- a/trunk/drivers/staging/comedi/drivers/das08.c +++ b/trunk/drivers/staging/comedi/drivers/das08.c @@ -32,9 +32,8 @@ * [ComputerBoards] DAS08 (isa-das08), DAS08-PGM (das08-pgm), * DAS08-PGH (das08-pgh), DAS08-PGL (das08-pgl), DAS08-AOH (das08-aoh), * DAS08-AOL (das08-aol), DAS08-AOM (das08-aom), DAS08/JR-AO (das08/jr-ao), - * DAS08/JR-16-AO (das08jr-16-ao), PCI-DAS08 (pci-das08), + * DAS08/JR-16-AO (das08jr-16-ao), PCI-DAS08 (pci-das08 or das08), * PC104-DAS08 (pc104-das08), DAS08/JR/16 (das08jr/16) - * Updated: Fri, 31 Aug 2012 19:19:06 +0100 * Status: works * * This is a rewrite of the das08 and das08jr drivers. @@ -42,8 +41,9 @@ * Options (for ISA cards): * [0] - base io address * - * Manual configuration of PCI cards is not supported; they are - * configured automatically. + * Options (for pci-das08): + * [0] - bus (optional) + * [1] = slot (optional) * * The das08 driver doesn't support asynchronous commands, since * the cheap das08 hardware doesn't really support them. The @@ -61,9 +61,9 @@ #define DRV_NAME "das08" -#define DO_ISA IS_ENABLED(CONFIG_COMEDI_DAS08_ISA) -#define DO_PCI IS_ENABLED(CONFIG_COMEDI_DAS08_PCI) -#define DO_COMEDI_DRIVER_REGISTER (DO_ISA || DO_PCI) +#define DO_COMEDI_DRIVER_REGISTER \ + (IS_ENABLED(CONFIG_COMEDI_DAS08_ISA) || \ + IS_ENABLED(CONFIG_COMEDI_DAS08_PCI)) #define PCI_VENDOR_ID_COMPUTERBOARDS 0x1307 #define PCI_DEVICE_ID_PCIDAS08 0x29 @@ -236,16 +236,6 @@ static const int *const das08_gainlists[] = { das08_pgm_gainlist, }; -static inline bool is_isa_board(const struct das08_board_struct *board) -{ - return DO_ISA && board->bustype == isa; -} - -static inline bool is_pci_board(const struct das08_board_struct *board) -{ - return DO_PCI && board->bustype == pci; -} - #define TIMEOUT 100000 static int das08_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, @@ -352,9 +342,9 @@ static int das08_do_wbits(struct comedi_device *dev, struct comedi_subdevice *s, return insn->n; } -static int das08jr_di_rbits(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) +static int __maybe_unused +das08jr_di_rbits(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data) { data[0] = 0; data[1] = inb(dev->iobase + DAS08JR_DIO); @@ -362,9 +352,9 @@ static int das08jr_di_rbits(struct comedi_device *dev, return insn->n; } -static int das08jr_do_wbits(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) +static int __maybe_unused +das08jr_do_wbits(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data) { struct das08_private_struct *devpriv = dev->private; @@ -379,92 +369,88 @@ static int das08jr_do_wbits(struct comedi_device *dev, return insn->n; } -static void das08_ao_set_data(struct comedi_device *dev, - unsigned int chan, unsigned int data) +static int __maybe_unused +das08jr_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data) { - const struct das08_board_struct *thisboard = comedi_board(dev); - struct das08_private_struct *devpriv = dev->private; - unsigned char lsb; - unsigned char msb; + int n; + int lsb, msb; + int chan; + + lsb = data[0] & 0xff; + msb = (data[0] >> 8) & 0xf; - lsb = data & 0xff; - msb = (data >> 8) & 0xff; - if (thisboard->is_jr) { + chan = CR_CHAN(insn->chanspec); + + for (n = 0; n < insn->n; n++) { +#if 0 + outb(lsb, dev->iobase + devpriv->ao_offset_lsb[chan]); + outb(msb, dev->iobase + devpriv->ao_offset_msb[chan]); +#else outb(lsb, dev->iobase + DAS08JR_AO_LSB(chan)); outb(msb, dev->iobase + DAS08JR_AO_MSB(chan)); +#endif + /* load DACs */ inb(dev->iobase + DAS08JR_DIO); - } else { - outb(lsb, dev->iobase + DAS08AO_AO_LSB(chan)); - outb(msb, dev->iobase + DAS08AO_AO_MSB(chan)); - /* load DACs */ - inb(dev->iobase + DAS08AO_AO_UPDATE); } - devpriv->ao_readback[chan] = data; + + return n; } -static void das08_ao_initialize(struct comedi_device *dev, - struct comedi_subdevice *s) +/* + * + * The -aox boards have the DACs at a different offset and use + * a different method to force an update. + * + */ +static int __maybe_unused +das08ao_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data) { int n; - unsigned int data; + int lsb, msb; + int chan; - data = s->maxdata / 2; /* should be about 0 volts */ - for (n = 0; n < s->n_chan; n++) - das08_ao_set_data(dev, n, data); -} - -static int das08_ao_winsn(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) -{ - unsigned int n; - unsigned int chan; + lsb = data[0] & 0xff; + msb = (data[0] >> 8) & 0xf; chan = CR_CHAN(insn->chanspec); - for (n = 0; n < insn->n; n++) - das08_ao_set_data(dev, chan, *data); - - return n; -} - -static int das08_ao_rinsn(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) -{ - struct das08_private_struct *devpriv = dev->private; - unsigned int n; - unsigned int chan; - - chan = CR_CHAN(insn->chanspec); + for (n = 0; n < insn->n; n++) { +#if 0 + outb(lsb, dev->iobase + devpriv->ao_offset_lsb[chan]); + outb(msb, dev->iobase + devpriv->ao_offset_msb[chan]); +#else + outb(lsb, dev->iobase + DAS08AO_AO_LSB(chan)); + outb(msb, dev->iobase + DAS08AO_AO_MSB(chan)); +#endif - for (n = 0; n < insn->n; n++) - data[n] = devpriv->ao_readback[chan]; + /* load DACs */ + inb(dev->iobase + DAS08AO_AO_UPDATE); + } return n; } static void i8254_initialize(struct comedi_device *dev) { - const struct das08_board_struct *thisboard = comedi_board(dev); - unsigned long i8254_iobase = dev->iobase + thisboard->i8254_offset; + struct das08_private_struct *devpriv = dev->private; unsigned int mode = I8254_MODE0 | I8254_BINARY; int i; for (i = 0; i < 3; ++i) - i8254_set_mode(i8254_iobase, 0, i, mode); + i8254_set_mode(devpriv->i8254_iobase, 0, i, mode); } static int das08_counter_read(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - const struct das08_board_struct *thisboard = comedi_board(dev); - unsigned long i8254_iobase = dev->iobase + thisboard->i8254_offset; + struct das08_private_struct *devpriv = dev->private; int chan = insn->chanspec; - data[0] = i8254_read(i8254_iobase, 0, chan); + data[0] = i8254_read(devpriv->i8254_iobase, 0, chan); return 1; } @@ -472,11 +458,10 @@ static int das08_counter_write(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - const struct das08_board_struct *thisboard = comedi_board(dev); - unsigned long i8254_iobase = dev->iobase + thisboard->i8254_offset; + struct das08_private_struct *devpriv = dev->private; int chan = insn->chanspec; - i8254_write(i8254_iobase, 0, chan, data[0]); + i8254_write(devpriv->i8254_iobase, 0, chan, data[0]); return 1; } @@ -484,16 +469,18 @@ static int das08_counter_config(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - const struct das08_board_struct *thisboard = comedi_board(dev); - unsigned long i8254_iobase = dev->iobase + thisboard->i8254_offset; + struct das08_private_struct *devpriv = dev->private; int chan = insn->chanspec; + if (insn->n != 2) + return -EINVAL; + switch (data[0]) { case INSN_CONFIG_SET_COUNTER_MODE: - i8254_set_mode(i8254_iobase, 0, chan, data[1]); + i8254_set_mode(devpriv->i8254_iobase, 0, chan, data[1]); break; case INSN_CONFIG_8254_READ_STATUS: - data[1] = i8254_status(i8254_iobase, 0, chan); + data[1] = i8254_status(devpriv->i8254_iobase, 0, chan); break; default: return -EINVAL; @@ -504,14 +491,18 @@ static int das08_counter_config(struct comedi_device *dev, #if DO_COMEDI_DRIVER_REGISTER static const struct das08_board_struct das08_boards[] = { -#if DO_ISA +#if IS_ENABLED(CONFIG_COMEDI_DAS08_ISA) { .name = "isa-das08", /* cio-das08.pdf */ .bustype = isa, + .ai = das08_ai_rinsn, .ai_nbits = 12, .ai_pg = das08_pg_none, .ai_encoding = das08_encode12, - .di_nchan = 3, + .ao = NULL, + .ao_nbits = 12, + .di = das08_di_rbits, + .do_ = das08_do_wbits, .do_nchan = 4, .i8255_offset = 8, .i8254_offset = 4, @@ -520,10 +511,13 @@ static const struct das08_board_struct das08_boards[] = { { .name = "das08-pgm", /* cio-das08pgx.pdf */ .bustype = isa, + .ai = das08_ai_rinsn, .ai_nbits = 12, .ai_pg = das08_pgm, .ai_encoding = das08_encode12, - .di_nchan = 3, + .ao = NULL, + .di = das08_di_rbits, + .do_ = das08_do_wbits, .do_nchan = 4, .i8255_offset = 0, .i8254_offset = 0x04, @@ -532,33 +526,44 @@ static const struct das08_board_struct das08_boards[] = { { .name = "das08-pgh", /* cio-das08pgx.pdf */ .bustype = isa, + .ai = das08_ai_rinsn, .ai_nbits = 12, .ai_pg = das08_pgh, .ai_encoding = das08_encode12, - .di_nchan = 3, + .ao = NULL, + .di = das08_di_rbits, + .do_ = das08_do_wbits, .do_nchan = 4, + .i8255_offset = 0, .i8254_offset = 0x04, .iosize = 16, /* unchecked */ }, { .name = "das08-pgl", /* cio-das08pgx.pdf */ .bustype = isa, + .ai = das08_ai_rinsn, .ai_nbits = 12, .ai_pg = das08_pgl, .ai_encoding = das08_encode12, - .di_nchan = 3, + .ao = NULL, + .di = das08_di_rbits, + .do_ = das08_do_wbits, .do_nchan = 4, + .i8255_offset = 0, .i8254_offset = 0x04, .iosize = 16, /* unchecked */ }, { .name = "das08-aoh", /* cio-das08_aox.pdf */ .bustype = isa, + .ai = das08_ai_rinsn, .ai_nbits = 12, .ai_pg = das08_pgh, .ai_encoding = das08_encode12, + .ao = das08ao_ao_winsn, /* 8 */ .ao_nbits = 12, - .di_nchan = 3, + .di = das08_di_rbits, + .do_ = das08_do_wbits, .do_nchan = 4, .i8255_offset = 0x0c, .i8254_offset = 0x04, @@ -567,11 +572,14 @@ static const struct das08_board_struct das08_boards[] = { { .name = "das08-aol", /* cio-das08_aox.pdf */ .bustype = isa, + .ai = das08_ai_rinsn, .ai_nbits = 12, .ai_pg = das08_pgl, .ai_encoding = das08_encode12, + .ao = das08ao_ao_winsn, /* 8 */ .ao_nbits = 12, - .di_nchan = 3, + .di = das08_di_rbits, + .do_ = das08_do_wbits, .do_nchan = 4, .i8255_offset = 0x0c, .i8254_offset = 0x04, @@ -580,11 +588,14 @@ static const struct das08_board_struct das08_boards[] = { { .name = "das08-aom", /* cio-das08_aox.pdf */ .bustype = isa, + .ai = das08_ai_rinsn, .ai_nbits = 12, .ai_pg = das08_pgm, .ai_encoding = das08_encode12, + .ao = das08ao_ao_winsn, /* 8 */ .ao_nbits = 12, - .di_nchan = 3, + .di = das08_di_rbits, + .do_ = das08_do_wbits, .do_nchan = 4, .i8255_offset = 0x0c, .i8254_offset = 0x04, @@ -593,68 +604,152 @@ static const struct das08_board_struct das08_boards[] = { { .name = "das08/jr-ao", /* cio-das08-jr-ao.pdf */ .bustype = isa, - .is_jr = true, + .ai = das08_ai_rinsn, .ai_nbits = 12, .ai_pg = das08_pg_none, .ai_encoding = das08_encode12, + .ao = das08jr_ao_winsn, .ao_nbits = 12, - .di_nchan = 8, + .di = das08jr_di_rbits, + .do_ = das08jr_do_wbits, .do_nchan = 8, + .i8255_offset = 0, + .i8254_offset = 0, .iosize = 16, /* unchecked */ }, { .name = "das08jr-16-ao", /* cio-das08jr-16-ao.pdf */ .bustype = isa, - .is_jr = true, + .ai = das08_ai_rinsn, .ai_nbits = 16, .ai_pg = das08_pg_none, - .ai_encoding = das08_encode16, + .ai_encoding = das08_encode12, + .ao = das08jr_ao_winsn, .ao_nbits = 16, - .di_nchan = 8, + .di = das08jr_di_rbits, + .do_ = das08jr_do_wbits, .do_nchan = 8, + .i8255_offset = 0, .i8254_offset = 0x04, .iosize = 16, /* unchecked */ }, { .name = "pc104-das08", - .bustype = isa, + .bustype = pc104, + .ai = das08_ai_rinsn, .ai_nbits = 12, .ai_pg = das08_pg_none, .ai_encoding = das08_encode12, - .di_nchan = 3, + .ao = NULL, + .ao_nbits = 0, + .di = das08_di_rbits, + .do_ = das08_do_wbits, .do_nchan = 4, + .i8255_offset = 0, .i8254_offset = 4, .iosize = 16, /* unchecked */ }, +#if 0 + { + .name = "das08/f", + }, + { + .name = "das08jr", + }, +#endif { .name = "das08jr/16", .bustype = isa, - .is_jr = true, + .ai = das08_ai_rinsn, .ai_nbits = 16, .ai_pg = das08_pg_none, .ai_encoding = das08_encode16, - .di_nchan = 8, + .ao = NULL, + .ao_nbits = 0, + .di = das08jr_di_rbits, + .do_ = das08jr_do_wbits, .do_nchan = 8, + .i8255_offset = 0, + .i8254_offset = 0, .iosize = 16, /* unchecked */ }, -#endif /* DO_ISA */ -#if DO_PCI +#if 0 + { + .name = "das48-pga", /* cio-das48-pga.pdf */ + }, + { + .name = "das08-pga-g2", /* a KM board */ + }, +#endif +#endif /* IS_ENABLED(CONFIG_COMEDI_DAS08_ISA) */ +#if IS_ENABLED(CONFIG_COMEDI_DAS08_PCI) { .name = "pci-das08", /* pci-das08 */ .id = PCI_DEVICE_ID_PCIDAS08, .bustype = pci, + .ai = das08_ai_rinsn, .ai_nbits = 12, .ai_pg = das08_bipolar5, .ai_encoding = das08_encode12, - .di_nchan = 3, + .ao = NULL, + .ao_nbits = 0, + .di = das08_di_rbits, + .do_ = das08_do_wbits, .do_nchan = 4, + .i8255_offset = 0, .i8254_offset = 4, .iosize = 8, }, -#endif /* DO_PCI */ + { /* wildcard entry matches any supported PCI device */ + .name = DRV_NAME, + .id = PCI_ANY_ID, + .bustype = pci, + }, +#endif /* IS_ENABLED(CONFIG_COMEDI_DAS08_PCI) */ }; #endif /* DO_COMEDI_DRIVER_REGISTER */ +#if IS_ENABLED(CONFIG_COMEDI_DAS08_CS) +struct das08_board_struct das08_cs_boards[NUM_DAS08_CS_BOARDS] = { + { + .name = "pcm-das08", + .id = 0x0, /* XXX */ + .bustype = pcmcia, + .ai = das08_ai_rinsn, + .ai_nbits = 12, + .ai_pg = das08_bipolar5, + .ai_encoding = das08_pcm_encode12, + .ao = NULL, + .ao_nbits = 0, + .di = das08_di_rbits, + .do_ = das08_do_wbits, + .do_nchan = 3, + .i8255_offset = 0, + .i8254_offset = 0, + .iosize = 16, + }, + /* duplicate so driver name can be used also */ + { + .name = "das08_cs", + .id = 0x0, /* XXX */ + .bustype = pcmcia, + .ai = das08_ai_rinsn, + .ai_nbits = 12, + .ai_pg = das08_bipolar5, + .ai_encoding = das08_pcm_encode12, + .ao = NULL, + .ao_nbits = 0, + .di = das08_di_rbits, + .do_ = das08_do_wbits, + .do_nchan = 3, + .i8255_offset = 0, + .i8254_offset = 0, + .iosize = 16, + }, +}; +EXPORT_SYMBOL_GPL(das08_cs_boards); +#endif + int das08_common_attach(struct comedi_device *dev, unsigned long iobase) { const struct das08_board_struct *thisboard = comedi_board(dev); @@ -670,9 +765,9 @@ int das08_common_attach(struct comedi_device *dev, unsigned long iobase) if (ret) return ret; - s = &dev->subdevices[0]; + s = dev->subdevices + 0; /* ai */ - if (thisboard->ai_nbits) { + if (thisboard->ai) { s->type = COMEDI_SUBD_AI; /* XXX some boards actually have differential * inputs instead of single ended. @@ -683,56 +778,53 @@ int das08_common_attach(struct comedi_device *dev, unsigned long iobase) s->n_chan = 8; s->maxdata = (1 << thisboard->ai_nbits) - 1; s->range_table = das08_ai_lranges[thisboard->ai_pg]; - s->insn_read = das08_ai_rinsn; + s->insn_read = thisboard->ai; devpriv->pg_gainlist = das08_gainlists[thisboard->ai_pg]; } else { s->type = COMEDI_SUBD_UNUSED; } - s = &dev->subdevices[1]; + s = dev->subdevices + 1; /* ao */ - if (thisboard->ao_nbits) { + if (thisboard->ao) { s->type = COMEDI_SUBD_AO; +/* XXX lacks read-back insn */ s->subdev_flags = SDF_WRITABLE; s->n_chan = 2; s->maxdata = (1 << thisboard->ao_nbits) - 1; s->range_table = &range_bipolar5; - s->insn_write = das08_ao_winsn; - s->insn_read = das08_ao_rinsn; - das08_ao_initialize(dev, s); + s->insn_write = thisboard->ao; } else { s->type = COMEDI_SUBD_UNUSED; } - s = &dev->subdevices[2]; + s = dev->subdevices + 2; /* di */ - if (thisboard->di_nchan) { + if (thisboard->di) { s->type = COMEDI_SUBD_DI; s->subdev_flags = SDF_READABLE; - s->n_chan = thisboard->di_nchan; + s->n_chan = (thisboard->di == das08_di_rbits) ? 3 : 8; s->maxdata = 1; s->range_table = &range_digital; - s->insn_bits = - thisboard->is_jr ? das08jr_di_rbits : das08_di_rbits; + s->insn_bits = thisboard->di; } else { s->type = COMEDI_SUBD_UNUSED; } - s = &dev->subdevices[3]; + s = dev->subdevices + 3; /* do */ - if (thisboard->do_nchan) { + if (thisboard->do_) { s->type = COMEDI_SUBD_DO; s->subdev_flags = SDF_WRITABLE | SDF_READABLE; s->n_chan = thisboard->do_nchan; s->maxdata = 1; s->range_table = &range_digital; - s->insn_bits = - thisboard->is_jr ? das08jr_do_wbits : das08_do_wbits; + s->insn_bits = thisboard->do_; } else { s->type = COMEDI_SUBD_UNUSED; } - s = &dev->subdevices[4]; + s = dev->subdevices + 4; /* 8255 */ if (thisboard->i8255_offset != 0) { subdev_8255_init(dev, s, NULL, (unsigned long)(dev->iobase + @@ -742,7 +834,7 @@ int das08_common_attach(struct comedi_device *dev, unsigned long iobase) s->type = COMEDI_SUBD_UNUSED; } - s = &dev->subdevices[5]; + s = dev->subdevices + 5; /* 8254 */ if (thisboard->i8254_offset != 0) { s->type = COMEDI_SUBD_COUNTER; @@ -752,6 +844,8 @@ int das08_common_attach(struct comedi_device *dev, unsigned long iobase) s->insn_read = das08_counter_read; s->insn_write = das08_counter_write; s->insn_config = das08_counter_config; + + devpriv->i8254_iobase = iobase + thisboard->i8254_offset; i8254_initialize(dev); } else { s->type = COMEDI_SUBD_UNUSED; @@ -761,13 +855,50 @@ int das08_common_attach(struct comedi_device *dev, unsigned long iobase) } EXPORT_SYMBOL_GPL(das08_common_attach); +static int das08_pci_attach_common(struct comedi_device *dev, + struct pci_dev *pdev) +{ + unsigned long iobase; + unsigned long pci_iobase; + struct das08_private_struct *devpriv = dev->private; + + if (!IS_ENABLED(CONFIG_COMEDI_DAS08_PCI)) + return -EINVAL; + + devpriv->pdev = pdev; + /* enable PCI device and reserve I/O spaces */ + if (comedi_pci_enable(pdev, dev->driver->driver_name)) { + dev_err(dev->class_dev, + "Error enabling PCI device and requesting regions\n"); + return -EIO; + } + /* read base addresses */ + pci_iobase = pci_resource_start(pdev, 1); + iobase = pci_resource_start(pdev, 2); + dev_info(dev->class_dev, "pcibase 0x%lx iobase 0x%lx\n", + pci_iobase, iobase); + devpriv->pci_iobase = pci_iobase; +#if 0 + /* We could enable pci-das08's interrupt here to make it possible + * to do timed input in this driver, but there is little point since + * conversions would have to be started by the interrupt handler + * so you might as well use comedi_rt_timer to emulate commands + */ + /* set source of interrupt trigger to counter2 output */ + outb(CNTRL_INTR | CNTRL_DIR, pci_iobase + CNTRL); + /* Enable local interrupt 1 and pci interrupt */ + outw(INTR1_ENABLE | PCI_INTR_ENABLE, pci_iobase + INTCSR); +#endif + return das08_common_attach(dev, iobase); +} + static const struct das08_board_struct * das08_find_pci_board(struct pci_dev *pdev) { #if DO_COMEDI_DRIVER_REGISTER unsigned int i; for (i = 0; i < ARRAY_SIZE(das08_boards); i++) - if (is_pci_board(&das08_boards[i]) && + if (das08_boards[i].bustype == pci && pdev->device == das08_boards[i].id) return &das08_boards[i]; #endif @@ -778,10 +909,9 @@ das08_find_pci_board(struct pci_dev *pdev) static int __devinit __maybe_unused das08_attach_pci(struct comedi_device *dev, struct pci_dev *pdev) { - unsigned long iobase; int ret; - if (!DO_PCI) + if (!IS_ENABLED(CONFIG_COMEDI_DAS08_PCI)) return -EINVAL; ret = alloc_private(dev, sizeof(struct das08_private_struct)); if (ret < 0) @@ -792,16 +922,58 @@ das08_attach_pci(struct comedi_device *dev, struct pci_dev *pdev) dev_err(dev->class_dev, "BUG! cannot determine board type!\n"); return -EINVAL; } - comedi_set_hw_dev(dev, &pdev->dev); - /* enable PCI device and reserve I/O spaces */ - if (comedi_pci_enable(pdev, dev->driver->driver_name)) { - dev_err(dev->class_dev, - "Error enabling PCI device and requesting regions\n"); - return -EIO; + return das08_pci_attach_common(dev, pdev); +} + +static struct pci_dev *das08_find_pci(struct comedi_device *dev, + int bus, int slot) +{ + const struct das08_board_struct *thisboard = comedi_board(dev); + struct pci_dev *pdev; + unsigned int matchid; + + if (bus || slot) + dev_dbg(dev->class_dev, "Looking for %s at PCI %02X:%02X\n", + thisboard->name, bus, slot); + else + dev_dbg(dev->class_dev, "Looking for %s on PCI buses\n", + thisboard->name); + + matchid = thisboard->id; + pdev = NULL; + for_each_pci_dev(pdev) { + if ((bus || slot) && + (bus != pdev->bus->number || slot != PCI_SLOT(pdev->devfn))) + continue; + if (pdev->vendor != PCI_VENDOR_ID_COMPUTERBOARDS) + continue; + if (matchid == PCI_ANY_ID) { + /* wildcard board matches any supported PCI board */ + const struct das08_board_struct *foundboard; + foundboard = das08_find_pci_board(pdev); + if (foundboard == NULL) + continue; + /* replace wildcard board_ptr */ + dev->board_ptr = thisboard = foundboard; + } else { + /* match specific PCI board */ + if (pdev->device != matchid) + continue; + } + /* found a match */ + dev_info(dev->class_dev, "Found %s at PCI %s\n", + thisboard->name, pci_name(pdev)); + return pdev; } - /* read base addresses */ - iobase = pci_resource_start(pdev, 2); - return das08_common_attach(dev, iobase); + /* no match found */ + if (bus || slot) + dev_err(dev->class_dev, + "No %s cards found at PCI %02X:%02X\n", + thisboard->name, bus, slot); + else + dev_err(dev->class_dev, "No %s cards found on PCI buses\n", + thisboard->name); + return NULL; } static int __maybe_unused @@ -818,12 +990,14 @@ das08_attach(struct comedi_device *dev, struct comedi_devconfig *it) devpriv = dev->private; dev_info(dev->class_dev, "attach\n"); - if (is_pci_board(thisboard)) { - dev_err(dev->class_dev, - "Manual configuration of PCI board '%s' is not supported\n", - thisboard->name); - return -EIO; - } else if (is_isa_board(thisboard)) { + if (IS_ENABLED(CONFIG_COMEDI_DAS08_PCI) && thisboard->bustype == pci) { + struct pci_dev *pdev; + pdev = das08_find_pci(dev, it->options[0], it->options[1]); + if (pdev == NULL) + return -EIO; + return das08_pci_attach_common(dev, pdev); + } else if (IS_ENABLED(CONFIG_COMEDI_DAS08_ISA) && + (thisboard->bustype == isa || thisboard->bustype == pc104)) { iobase = it->options[0]; dev_info(dev->class_dev, "iobase 0x%lx\n", iobase); if (!request_region(iobase, thisboard->iosize, DRV_NAME)) { @@ -838,23 +1012,26 @@ das08_attach(struct comedi_device *dev, struct comedi_devconfig *it) void das08_common_detach(struct comedi_device *dev) { if (dev->subdevices) - subdev_8255_cleanup(dev, &dev->subdevices[4]); + subdev_8255_cleanup(dev, dev->subdevices + 4); } EXPORT_SYMBOL_GPL(das08_common_detach); static void __maybe_unused das08_detach(struct comedi_device *dev) { const struct das08_board_struct *thisboard = comedi_board(dev); + struct das08_private_struct *devpriv = dev->private; das08_common_detach(dev); - if (is_isa_board(thisboard)) { + if (IS_ENABLED(CONFIG_COMEDI_DAS08_ISA) && + (thisboard->bustype == isa || thisboard->bustype == pc104)) { if (dev->iobase) release_region(dev->iobase, thisboard->iosize); - } else if (is_pci_board(thisboard)) { - struct pci_dev *pdev = comedi_to_pci_dev(dev); - if (pdev) { - if (dev->iobase) - comedi_pci_disable(pdev); + } else if (IS_ENABLED(CONFIG_COMEDI_DAS08_PCI) && + thisboard->bustype == pci) { + if (devpriv && devpriv->pdev) { + if (devpriv->pci_iobase) + comedi_pci_disable(devpriv->pdev); + pci_dev_put(devpriv->pdev); } } } @@ -872,7 +1049,7 @@ static struct comedi_driver das08_driver = { }; #endif -#if DO_PCI +#if IS_ENABLED(CONFIG_COMEDI_DAS08_PCI) static DEFINE_PCI_DEVICE_TABLE(das08_pci_table) = { { PCI_DEVICE(PCI_VENDOR_ID_COMPUTERBOARDS, PCI_DEVICE_ID_PCIDAS08) }, {0} @@ -897,10 +1074,10 @@ static struct pci_driver das08_pci_driver = { .probe = &das08_pci_probe, .remove = __devexit_p(&das08_pci_remove) }; -#endif /* DO_PCI */ +#endif /* CONFIG_COMEDI_DAS08_PCI */ #if DO_COMEDI_DRIVER_REGISTER -#if DO_PCI +#if IS_ENABLED(CONFIG_COMEDI_DAS08_PCI) module_comedi_pci_driver(das08_driver, das08_pci_driver); #else module_comedi_driver(das08_driver); diff --git a/trunk/drivers/staging/comedi/drivers/das08.h b/trunk/drivers/staging/comedi/drivers/das08.h index 0314baebae39..27b6d4ec9032 100644 --- a/trunk/drivers/staging/comedi/drivers/das08.h +++ b/trunk/drivers/staging/comedi/drivers/das08.h @@ -24,7 +24,7 @@ #ifndef _DAS08_H #define _DAS08_H -enum das08_bustype { isa, pci, pcmcia }; +enum das08_bustype { isa, pci, pcmcia, pc104 }; /* different ways ai data is encoded in first two registers */ enum das08_ai_encoding { das08_encode12, das08_encode16, das08_pcm_encode12 }; enum das08_lrange { das08_pg_none, das08_bipolar5, das08_pgh, das08_pgl, @@ -35,12 +35,14 @@ struct das08_board_struct { const char *name; unsigned int id; /* id for pci/pcmcia boards */ enum das08_bustype bustype; - bool is_jr; /* true for 'JR' boards */ + void *ai; unsigned int ai_nbits; enum das08_lrange ai_pg; enum das08_ai_encoding ai_encoding; + void *ao; unsigned int ao_nbits; - unsigned int di_nchan; + void *di; + void *do_; unsigned int do_nchan; unsigned int i8255_offset; unsigned int i8254_offset; @@ -51,9 +53,14 @@ struct das08_private_struct { unsigned int do_mux_bits; /* bits for do/mux register on boards without separate do register */ unsigned int do_bits; /* bits for do register on boards with register dedicated to digital out only */ const unsigned int *pg_gainlist; - unsigned int ao_readback[2]; /* assume 2 AO channels */ + struct pci_dev *pdev; /* struct for pci-das08 */ + unsigned int pci_iobase; /* additional base address for pci-das08 */ + unsigned int i8254_iobase; }; +#define NUM_DAS08_CS_BOARDS 2 +extern struct das08_board_struct das08_cs_boards[NUM_DAS08_CS_BOARDS]; + int das08_common_attach(struct comedi_device *dev, unsigned long iobase); void das08_common_detach(struct comedi_device *dev); diff --git a/trunk/drivers/staging/comedi/drivers/das08_cs.c b/trunk/drivers/staging/comedi/drivers/das08_cs.c index e4c91e675379..f5700de7b6c0 100644 --- a/trunk/drivers/staging/comedi/drivers/das08_cs.c +++ b/trunk/drivers/staging/comedi/drivers/das08_cs.c @@ -58,32 +58,6 @@ Command support does not exist, but could be added for this board. #include #include -static const struct das08_board_struct das08_cs_boards[] = { - { - .name = "pcm-das08", - .id = 0x0, /* XXX */ - .bustype = pcmcia, - .ai_nbits = 12, - .ai_pg = das08_bipolar5, - .ai_encoding = das08_pcm_encode12, - .di_nchan = 3, - .do_nchan = 3, - .iosize = 16, - }, - /* duplicate so driver name can be used also */ - { - .name = "das08_cs", - .id = 0x0, /* XXX */ - .bustype = pcmcia, - .ai_nbits = 12, - .ai_pg = das08_bipolar5, - .ai_encoding = das08_pcm_encode12, - .di_nchan = 3, - .do_nchan = 3, - .iosize = 16, - }, -}; - static struct pcmcia_device *cur_dev; static int das08_cs_attach(struct comedi_device *dev, diff --git a/trunk/drivers/staging/comedi/drivers/das16.c b/trunk/drivers/staging/comedi/drivers/das16.c index fcb8a32adb2f..895cc7783c9c 100644 --- a/trunk/drivers/staging/comedi/drivers/das16.c +++ b/trunk/drivers/staging/comedi/drivers/das16.c @@ -402,42 +402,62 @@ static int das16_cmd_test(struct comedi_device *dev, struct comedi_subdevice *s, int gain, start_chan, i; int mask; - /* Step 1 : check if triggers are trivially valid */ - - err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW); + /* make sure triggers are valid */ + tmp = cmd->start_src; + cmd->start_src &= TRIG_NOW; + if (!cmd->start_src || tmp != cmd->start_src) + err++; + tmp = cmd->scan_begin_src; mask = TRIG_FOLLOW; /* if board supports burst mode */ if (board->size > 0x400) mask |= TRIG_TIMER | TRIG_EXT; - err |= cfc_check_trigger_src(&cmd->scan_begin_src, mask); + cmd->scan_begin_src &= mask; + if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) + err++; tmp = cmd->convert_src; mask = TRIG_TIMER | TRIG_EXT; /* if board supports burst mode */ if (board->size > 0x400) mask |= TRIG_NOW; - err |= cfc_check_trigger_src(&cmd->convert_src, mask); + cmd->convert_src &= mask; + if (!cmd->convert_src || tmp != cmd->convert_src) + err++; - err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT); - err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE); + tmp = cmd->scan_end_src; + cmd->scan_end_src &= TRIG_COUNT; + if (!cmd->scan_end_src || tmp != cmd->scan_end_src) + err++; + + tmp = cmd->stop_src; + cmd->stop_src &= TRIG_COUNT | TRIG_NONE; + if (!cmd->stop_src || tmp != cmd->stop_src) + err++; if (err) return 1; - /* Step 2a : make sure trigger sources are unique */ - - err |= cfc_check_trigger_is_unique(cmd->scan_begin_src); - err |= cfc_check_trigger_is_unique(cmd->convert_src); - err |= cfc_check_trigger_is_unique(cmd->stop_src); - - /* Step 2b : and mutually compatible */ + /** + * step 2: make sure trigger sources are unique and + * mutually compatible + */ + if (cmd->scan_begin_src != TRIG_TIMER && + cmd->scan_begin_src != TRIG_EXT && + cmd->scan_begin_src != TRIG_FOLLOW) + err++; + if (cmd->convert_src != TRIG_TIMER && + cmd->convert_src != TRIG_EXT && cmd->convert_src != TRIG_NOW) + err++; + if (cmd->stop_src != TRIG_NONE && cmd->stop_src != TRIG_COUNT) + err++; /* make sure scan_begin_src and convert_src dont conflict */ if (cmd->scan_begin_src == TRIG_FOLLOW && cmd->convert_src == TRIG_NOW) - err |= -EINVAL; + err++; if (cmd->scan_begin_src != TRIG_FOLLOW && cmd->convert_src != TRIG_NOW) - err |= -EINVAL; + err++; if (err) return 2; @@ -538,7 +558,7 @@ static int das16_cmd_test(struct comedi_device *dev, struct comedi_subdevice *s, /* utility function that suggests a dma transfer size in bytes */ static unsigned int das16_suggest_transfer_size(struct comedi_device *dev, - const struct comedi_cmd *cmd) + struct comedi_cmd cmd) { unsigned int size; unsigned int freq; @@ -551,16 +571,16 @@ static unsigned int das16_suggest_transfer_size(struct comedi_device *dev, /* otherwise, we are relying on dma terminal count interrupt, * so pick a reasonable size */ - if (cmd->convert_src == TRIG_TIMER) - freq = 1000000000 / cmd->convert_arg; - else if (cmd->scan_begin_src == TRIG_TIMER) - freq = (1000000000 / cmd->scan_begin_arg) * cmd->chanlist_len; + if (cmd.convert_src == TRIG_TIMER) + freq = 1000000000 / cmd.convert_arg; + else if (cmd.scan_begin_src == TRIG_TIMER) + freq = (1000000000 / cmd.scan_begin_arg) * cmd.chanlist_len; /* return some default value */ else freq = 0xffffffff; - if (cmd->flags & TRIG_WAKE_EOS) { - size = sample_size * cmd->chanlist_len; + if (cmd.flags & TRIG_WAKE_EOS) { + size = sample_size * cmd.chanlist_len; } else { /* make buffer fill in no more than 1/3 second */ size = (freq / 3) * sample_size; @@ -572,7 +592,7 @@ static unsigned int das16_suggest_transfer_size(struct comedi_device *dev, else if (size < sample_size) size = sample_size; - if (cmd->stop_src == TRIG_COUNT && size > devpriv->adc_byte_count) + if (cmd.stop_src == TRIG_COUNT && size > devpriv->adc_byte_count) size = devpriv->adc_byte_count; return size; @@ -665,7 +685,7 @@ static int das16_cmd_exec(struct comedi_device *dev, struct comedi_subdevice *s) set_dma_addr(devpriv->dma_chan, devpriv->dma_buffer_addr[devpriv->current_buffer]); /* set appropriate size of transfer */ - devpriv->dma_transfer_size = das16_suggest_transfer_size(dev, cmd); + devpriv->dma_transfer_size = das16_suggest_transfer_size(dev, *cmd); set_dma_count(devpriv->dma_chan, devpriv->dma_transfer_size); enable_dma(devpriv->dma_chan); release_dma_lock(flags); @@ -1248,7 +1268,7 @@ static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it) if (ret) return ret; - s = &dev->subdevices[0]; + s = dev->subdevices + 0; dev->read_subdev = s; /* ai */ if (board->ai) { @@ -1280,7 +1300,7 @@ static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it) s->type = COMEDI_SUBD_UNUSED; } - s = &dev->subdevices[1]; + s = dev->subdevices + 1; /* ao */ if (board->ao) { s->type = COMEDI_SUBD_AO; @@ -1298,7 +1318,7 @@ static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it) s->type = COMEDI_SUBD_UNUSED; } - s = &dev->subdevices[2]; + s = dev->subdevices + 2; /* di */ if (board->di) { s->type = COMEDI_SUBD_DI; @@ -1311,7 +1331,7 @@ static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it) s->type = COMEDI_SUBD_UNUSED; } - s = &dev->subdevices[3]; + s = dev->subdevices + 3; /* do */ if (board->do_) { s->type = COMEDI_SUBD_DO; @@ -1326,7 +1346,7 @@ static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it) s->type = COMEDI_SUBD_UNUSED; } - s = &dev->subdevices[4]; + s = dev->subdevices + 4; /* 8255 */ if (board->i8255_offset != 0) { subdev_8255_init(dev, s, NULL, (dev->iobase + @@ -1356,7 +1376,7 @@ static void das16_detach(struct comedi_device *dev) das16_reset(dev); if (dev->subdevices) - subdev_8255_cleanup(dev, &dev->subdevices[4]); + subdev_8255_cleanup(dev, dev->subdevices + 4); if (devpriv) { int i; for (i = 0; i < 2; i++) { diff --git a/trunk/drivers/staging/comedi/drivers/das16m1.c b/trunk/drivers/staging/comedi/drivers/das16m1.c index 3f87d7598e5b..200926347861 100644 --- a/trunk/drivers/staging/comedi/drivers/das16m1.c +++ b/trunk/drivers/staging/comedi/drivers/das16m1.c @@ -170,24 +170,42 @@ static int das16m1_cmd_test(struct comedi_device *dev, const struct das16m1_board *board = comedi_board(dev); unsigned int err = 0, tmp, i; - /* Step 1 : check if triggers are trivially valid */ + /* make sure triggers are valid */ + tmp = cmd->start_src; + cmd->start_src &= TRIG_NOW | TRIG_EXT; + if (!cmd->start_src || tmp != cmd->start_src) + err++; - err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_EXT); - err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_FOLLOW); - err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_TIMER | TRIG_EXT); - err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT); - err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE); + tmp = cmd->scan_begin_src; + cmd->scan_begin_src &= TRIG_FOLLOW; + if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) + err++; - if (err) - return 1; + tmp = cmd->convert_src; + cmd->convert_src &= TRIG_TIMER | TRIG_EXT; + if (!cmd->convert_src || tmp != cmd->convert_src) + err++; - /* Step 2a : make sure trigger sources are unique */ + tmp = cmd->scan_end_src; + cmd->scan_end_src &= TRIG_COUNT; + if (!cmd->scan_end_src || tmp != cmd->scan_end_src) + err++; - err |= cfc_check_trigger_is_unique(cmd->start_src); - err |= cfc_check_trigger_is_unique(cmd->convert_src); - err |= cfc_check_trigger_is_unique(cmd->stop_src); + tmp = cmd->stop_src; + cmd->stop_src &= TRIG_COUNT | TRIG_NONE; + if (!cmd->stop_src || tmp != cmd->stop_src) + err++; - /* Step 2b : and mutually compatible */ + if (err) + return 1; + + /* step 2: make sure trigger sources are unique and mutually compatible */ + if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE) + err++; + if (cmd->start_src != TRIG_NOW && cmd->start_src != TRIG_EXT) + err++; + if (cmd->convert_src != TRIG_TIMER && cmd->convert_src != TRIG_EXT) + err++; if (err) return 2; @@ -632,7 +650,7 @@ static int das16m1_attach(struct comedi_device *dev, if (ret) return ret; - s = &dev->subdevices[0]; + s = dev->subdevices + 0; dev->read_subdev = s; /* ai */ s->type = COMEDI_SUBD_AI; @@ -648,7 +666,7 @@ static int das16m1_attach(struct comedi_device *dev, s->cancel = das16m1_cancel; s->poll = das16m1_poll; - s = &dev->subdevices[1]; + s = dev->subdevices + 1; /* di */ s->type = COMEDI_SUBD_DI; s->subdev_flags = SDF_READABLE; @@ -657,7 +675,7 @@ static int das16m1_attach(struct comedi_device *dev, s->range_table = &range_digital; s->insn_bits = das16m1_di_rbits; - s = &dev->subdevices[2]; + s = dev->subdevices + 2; /* do */ s->type = COMEDI_SUBD_DO; s->subdev_flags = SDF_WRITABLE | SDF_READABLE; @@ -666,7 +684,7 @@ static int das16m1_attach(struct comedi_device *dev, s->range_table = &range_digital; s->insn_bits = das16m1_do_wbits; - s = &dev->subdevices[3]; + s = dev->subdevices + 3; /* 8255 */ subdev_8255_init(dev, s, NULL, dev->iobase + DAS16M1_82C55); @@ -689,7 +707,7 @@ static int das16m1_attach(struct comedi_device *dev, static void das16m1_detach(struct comedi_device *dev) { if (dev->subdevices) - subdev_8255_cleanup(dev, &dev->subdevices[3]); + subdev_8255_cleanup(dev, dev->subdevices + 3); if (dev->irq) free_irq(dev->irq, dev); if (dev->iobase) { diff --git a/trunk/drivers/staging/comedi/drivers/das1800.c b/trunk/drivers/staging/comedi/drivers/das1800.c index 2555f3297d7b..25e7e56a376f 100644 --- a/trunk/drivers/staging/comedi/drivers/das1800.c +++ b/trunk/drivers/staging/comedi/drivers/das1800.c @@ -656,7 +656,7 @@ static int das1800_cancel(struct comedi_device *dev, struct comedi_subdevice *s) /* the guts of the interrupt handler, that is shared with das1800_ai_poll */ static void das1800_ai_handler(struct comedi_device *dev) { - struct comedi_subdevice *s = &dev->subdevices[0]; + struct comedi_subdevice *s = dev->subdevices + 0; /* analog input subdevice */ struct comedi_async *async = s->async; struct comedi_cmd *cmd = &async->cmd; unsigned int status = inb(dev->iobase + DAS1800_STATUS); @@ -784,35 +784,59 @@ static int das1800_ai_do_cmdtest(struct comedi_device *dev, struct comedi_cmd *cmd) { int err = 0; + int tmp; unsigned int tmp_arg; int i; int unipolar; - /* Step 1 : check if triggers are trivially valid */ + /* step 1: make sure trigger sources are trivially valid */ - err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_EXT); - err |= cfc_check_trigger_src(&cmd->scan_begin_src, - TRIG_FOLLOW | TRIG_TIMER | TRIG_EXT); - err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_TIMER | TRIG_EXT); - err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT); - err |= cfc_check_trigger_src(&cmd->stop_src, - TRIG_COUNT | TRIG_EXT | TRIG_NONE); + tmp = cmd->start_src; + cmd->start_src &= TRIG_NOW | TRIG_EXT; + if (!cmd->start_src || tmp != cmd->start_src) + err++; - if (err) - return 1; + tmp = cmd->scan_begin_src; + cmd->scan_begin_src &= TRIG_FOLLOW | TRIG_TIMER | TRIG_EXT; + if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) + err++; + + tmp = cmd->convert_src; + cmd->convert_src &= TRIG_TIMER | TRIG_EXT; + if (!cmd->convert_src || tmp != cmd->convert_src) + err++; - /* Step 2a : make sure trigger sources are unique */ + tmp = cmd->scan_end_src; + cmd->scan_end_src &= TRIG_COUNT; + if (!cmd->scan_end_src || tmp != cmd->scan_end_src) + err++; + + tmp = cmd->stop_src; + cmd->stop_src &= TRIG_COUNT | TRIG_EXT | TRIG_NONE; + if (!cmd->stop_src || tmp != cmd->stop_src) + err++; - err |= cfc_check_trigger_is_unique(cmd->start_src); - err |= cfc_check_trigger_is_unique(cmd->scan_begin_src); - err |= cfc_check_trigger_is_unique(cmd->convert_src); - err |= cfc_check_trigger_is_unique(cmd->stop_src); + if (err) + return 1; - /* Step 2b : and mutually compatible */ + /* step 2: make sure trigger sources are unique and mutually compatible */ + /* uniqueness check */ + if (cmd->start_src != TRIG_NOW && cmd->start_src != TRIG_EXT) + err++; + if (cmd->scan_begin_src != TRIG_FOLLOW && + cmd->scan_begin_src != TRIG_TIMER && + cmd->scan_begin_src != TRIG_EXT) + err++; + if (cmd->convert_src != TRIG_TIMER && cmd->convert_src != TRIG_EXT) + err++; + if (cmd->stop_src != TRIG_COUNT && + cmd->stop_src != TRIG_NONE && cmd->stop_src != TRIG_EXT) + err++; + /* compatibility check */ if (cmd->scan_begin_src != TRIG_FOLLOW && cmd->convert_src != TRIG_TIMER) - err |= -EINVAL; + err++; if (err) return 2; @@ -934,14 +958,14 @@ static int das1800_ai_do_cmdtest(struct comedi_device *dev, } /* returns appropriate bits for control register a, depending on command */ -static int control_a_bits(const struct comedi_cmd *cmd) +static int control_a_bits(struct comedi_cmd cmd) { int control_a; control_a = FFEN; /* enable fifo */ - if (cmd->stop_src == TRIG_EXT) + if (cmd.stop_src == TRIG_EXT) control_a |= ATEN; - switch (cmd->start_src) { + switch (cmd.start_src) { case TRIG_EXT: control_a |= TGEN | CGSL; break; @@ -956,7 +980,7 @@ static int control_a_bits(const struct comedi_cmd *cmd) } /* returns appropriate bits for control register c, depending on command */ -static int control_c_bits(const struct comedi_cmd *cmd) +static int control_c_bits(struct comedi_cmd cmd) { int control_c; int aref; @@ -964,18 +988,18 @@ static int control_c_bits(const struct comedi_cmd *cmd) /* set clock source to internal or external, select analog reference, * select unipolar / bipolar */ - aref = CR_AREF(cmd->chanlist[0]); + aref = CR_AREF(cmd.chanlist[0]); control_c = UQEN; /* enable upper qram addresses */ if (aref != AREF_DIFF) control_c |= SD; if (aref == AREF_COMMON) control_c |= CMEN; /* if a unipolar range was selected */ - if (CR_RANGE(cmd->chanlist[0]) & UNIPOLAR) + if (CR_RANGE(cmd.chanlist[0]) & UNIPOLAR) control_c |= UB; - switch (cmd->scan_begin_src) { + switch (cmd.scan_begin_src) { case TRIG_FOLLOW: /* not in burst mode */ - switch (cmd->convert_src) { + switch (cmd.convert_src) { case TRIG_TIMER: /* trig on cascaded counters */ control_c |= IPCLK; @@ -1023,33 +1047,29 @@ static int das1800_set_frequency(struct comedi_device *dev) } /* sets up counters */ -static int setup_counters(struct comedi_device *dev, - const struct comedi_cmd *cmd) +static int setup_counters(struct comedi_device *dev, struct comedi_cmd cmd) { - unsigned int period; - /* setup cascaded counters for conversion/scan frequency */ - switch (cmd->scan_begin_src) { + switch (cmd.scan_begin_src) { case TRIG_FOLLOW: /* not in burst mode */ - if (cmd->convert_src == TRIG_TIMER) { + if (cmd.convert_src == TRIG_TIMER) { /* set conversion frequency */ - period = cmd->convert_arg; i8253_cascade_ns_to_timer_2div(TIMER_BASE, - &devpriv->divisor1, - &devpriv->divisor2, - &period, - cmd->flags & - TRIG_ROUND_MASK); + &(devpriv->divisor1), + &(devpriv->divisor2), + &(cmd.convert_arg), + cmd. + flags & TRIG_ROUND_MASK); if (das1800_set_frequency(dev) < 0) return -1; } break; case TRIG_TIMER: /* in burst mode */ /* set scan frequency */ - period = cmd->scan_begin_arg; - i8253_cascade_ns_to_timer_2div(TIMER_BASE, &devpriv->divisor1, - &devpriv->divisor2, &period, - cmd->flags & TRIG_ROUND_MASK); + i8253_cascade_ns_to_timer_2div(TIMER_BASE, &(devpriv->divisor1), + &(devpriv->divisor2), + &(cmd.scan_begin_arg), + cmd.flags & TRIG_ROUND_MASK); if (das1800_set_frequency(dev) < 0) return -1; break; @@ -1058,7 +1078,7 @@ static int setup_counters(struct comedi_device *dev, } /* setup counter 0 for 'about triggering' */ - if (cmd->stop_src == TRIG_EXT) { + if (cmd.stop_src == TRIG_EXT) { /* load counter 0 in mode 0 */ i8254_load(dev->iobase + DAS1800_COUNTER, 0, 0, 1, 0); } @@ -1067,7 +1087,7 @@ static int setup_counters(struct comedi_device *dev, } /* utility function that suggests a dma transfer size based on the conversion period 'ns' */ -static unsigned int suggest_transfer_size(const struct comedi_cmd *cmd) +static unsigned int suggest_transfer_size(struct comedi_cmd *cmd) { unsigned int size = DMA_BUF_SIZE; static const int sample_size = 2; /* size in bytes of one sample from board */ @@ -1105,7 +1125,7 @@ static unsigned int suggest_transfer_size(const struct comedi_cmd *cmd) } /* sets up dma */ -static void setup_dma(struct comedi_device *dev, const struct comedi_cmd *cmd) +static void setup_dma(struct comedi_device *dev, struct comedi_cmd cmd) { unsigned long lock_flags; const int dual_dma = devpriv->irq_dma_bits & DMA_DUAL; @@ -1114,7 +1134,7 @@ static void setup_dma(struct comedi_device *dev, const struct comedi_cmd *cmd) return; /* determine a reasonable dma transfer size */ - devpriv->dma_transfer_size = suggest_transfer_size(cmd); + devpriv->dma_transfer_size = suggest_transfer_size(&cmd); lock_flags = claim_dma_lock(); disable_dma(devpriv->dma0); /* clear flip-flop to make sure 2-byte registers for @@ -1143,15 +1163,14 @@ static void setup_dma(struct comedi_device *dev, const struct comedi_cmd *cmd) } /* programs channel/gain list into card */ -static void program_chanlist(struct comedi_device *dev, - const struct comedi_cmd *cmd) +static void program_chanlist(struct comedi_device *dev, struct comedi_cmd cmd) { int i, n, chan_range; unsigned long irq_flags; const int range_mask = 0x3; /* masks unipolar/bipolar bit off range */ const int range_bitshift = 8; - n = cmd->chanlist_len; + n = cmd.chanlist_len; /* spinlock protects indirect addressing */ spin_lock_irqsave(&dev->spinlock, irq_flags); outb(QRAM, dev->iobase + DAS1800_SELECT); /* select QRAM for baseAddress + 0x0 */ @@ -1159,9 +1178,9 @@ static void program_chanlist(struct comedi_device *dev, /* make channel / gain list */ for (i = 0; i < n; i++) { chan_range = - CR_CHAN(cmd->chanlist[i]) | - ((CR_RANGE(cmd->chanlist[i]) & range_mask) << - range_bitshift); + CR_CHAN(cmd. + chanlist[i]) | ((CR_RANGE(cmd.chanlist[i]) & + range_mask) << range_bitshift); outw(chan_range, dev->iobase + DAS1800_QRAM); } outb(n - 1, dev->iobase + DAS1800_QRAM_ADDRESS); /*finish write to QRAM */ @@ -1177,7 +1196,7 @@ static int das1800_ai_do_cmd(struct comedi_device *dev, int ret; int control_a, control_c; struct comedi_async *async = s->async; - const struct comedi_cmd *cmd = &async->cmd; + struct comedi_cmd cmd = async->cmd; if (!dev->irq) { comedi_error(dev, @@ -1187,12 +1206,12 @@ static int das1800_ai_do_cmd(struct comedi_device *dev, /* disable dma on TRIG_WAKE_EOS, or TRIG_RT * (because dma in handler is unsafe at hard real-time priority) */ - if (cmd->flags & (TRIG_WAKE_EOS | TRIG_RT)) + if (cmd.flags & (TRIG_WAKE_EOS | TRIG_RT)) devpriv->irq_dma_bits &= ~DMA_ENABLED; else devpriv->irq_dma_bits |= devpriv->dma_bits; /* interrupt on end of conversion for TRIG_WAKE_EOS */ - if (cmd->flags & TRIG_WAKE_EOS) { + if (cmd.flags & TRIG_WAKE_EOS) { /* interrupt fifo not empty */ devpriv->irq_dma_bits &= ~FIMD; } else { @@ -1200,8 +1219,8 @@ static int das1800_ai_do_cmd(struct comedi_device *dev, devpriv->irq_dma_bits |= FIMD; } /* determine how many conversions we need */ - if (cmd->stop_src == TRIG_COUNT) - devpriv->count = cmd->stop_arg * cmd->chanlist_len; + if (cmd.stop_src == TRIG_COUNT) + devpriv->count = cmd.stop_arg * cmd.chanlist_len; das1800_cancel(dev, s); @@ -1221,9 +1240,9 @@ static int das1800_ai_do_cmd(struct comedi_device *dev, /* set conversion rate and length for burst mode */ if (control_c & BMDE) { /* program conversion period with number of microseconds minus 1 */ - outb(cmd->convert_arg / 1000 - 1, + outb(cmd.convert_arg / 1000 - 1, dev->iobase + DAS1800_BURST_RATE); - outb(cmd->chanlist_len - 1, dev->iobase + DAS1800_BURST_LENGTH); + outb(cmd.chanlist_len - 1, dev->iobase + DAS1800_BURST_LENGTH); } outb(devpriv->irq_dma_bits, dev->iobase + DAS1800_CONTROL_B); /* enable irq/dma */ outb(control_a, dev->iobase + DAS1800_CONTROL_A); /* enable fifo and triggering */ @@ -1634,7 +1653,7 @@ static int das1800_attach(struct comedi_device *dev, return retval; /* analog input subdevice */ - s = &dev->subdevices[0]; + s = dev->subdevices + 0; dev->read_subdev = s; s->type = COMEDI_SUBD_AI; s->subdev_flags = SDF_READABLE | SDF_DIFF | SDF_GROUND | SDF_CMD_READ; @@ -1651,7 +1670,7 @@ static int das1800_attach(struct comedi_device *dev, s->cancel = das1800_cancel; /* analog out */ - s = &dev->subdevices[1]; + s = dev->subdevices + 1; if (thisboard->ao_ability == 1) { s->type = COMEDI_SUBD_AO; s->subdev_flags = SDF_WRITABLE; @@ -1664,7 +1683,7 @@ static int das1800_attach(struct comedi_device *dev, } /* di */ - s = &dev->subdevices[2]; + s = dev->subdevices + 2; s->type = COMEDI_SUBD_DI; s->subdev_flags = SDF_READABLE; s->n_chan = 4; @@ -1673,7 +1692,7 @@ static int das1800_attach(struct comedi_device *dev, s->insn_bits = das1800_di_rbits; /* do */ - s = &dev->subdevices[3]; + s = dev->subdevices + 3; s->type = COMEDI_SUBD_DO; s->subdev_flags = SDF_WRITABLE | SDF_READABLE; s->n_chan = thisboard->do_n_chan; diff --git a/trunk/drivers/staging/comedi/drivers/das6402.c b/trunk/drivers/staging/comedi/drivers/das6402.c index e134c46dedff..e3afcfa9efc8 100644 --- a/trunk/drivers/staging/comedi/drivers/das6402.c +++ b/trunk/drivers/staging/comedi/drivers/das6402.c @@ -152,7 +152,7 @@ static void das6402_setcounter(struct comedi_device *dev) static irqreturn_t intr_handler(int irq, void *d) { struct comedi_device *dev = d; - struct comedi_subdevice *s = &dev->subdevices[0]; + struct comedi_subdevice *s = dev->subdevices; if (!dev->attached || devpriv->das6402_ignoreirq) { dev_warn(dev->class_dev, "BUG: spurious interrupt\n"); @@ -312,7 +312,7 @@ static int das6402_attach(struct comedi_device *dev, return ret; /* ai subdevice */ - s = &dev->subdevices[0]; + s = dev->subdevices + 0; s->type = COMEDI_SUBD_AI; s->subdev_flags = SDF_READABLE | SDF_GROUND; s->n_chan = 8; diff --git a/trunk/drivers/staging/comedi/drivers/das800.c b/trunk/drivers/staging/comedi/drivers/das800.c index 215deac0a396..a0959a5e8747 100644 --- a/trunk/drivers/staging/comedi/drivers/das800.c +++ b/trunk/drivers/staging/comedi/drivers/das800.c @@ -435,7 +435,7 @@ static irqreturn_t das800_interrupt(int irq, void *d) if (fifo_overflow) { spin_unlock_irqrestore(&dev->spinlock, irq_flags); comedi_error(dev, "DAS800 FIFO overflow"); - das800_cancel(dev, s); + das800_cancel(dev, dev->subdevices + 0); async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA; comedi_event(dev, s); async->events = 0; @@ -517,7 +517,7 @@ static int das800_attach(struct comedi_device *dev, struct comedi_devconfig *it) return ret; /* analog input subdevice */ - s = &dev->subdevices[0]; + s = dev->subdevices + 0; dev->read_subdev = s; s->type = COMEDI_SUBD_AI; s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_CMD_READ; @@ -531,7 +531,7 @@ static int das800_attach(struct comedi_device *dev, struct comedi_devconfig *it) s->cancel = das800_cancel; /* di */ - s = &dev->subdevices[1]; + s = dev->subdevices + 1; s->type = COMEDI_SUBD_DI; s->subdev_flags = SDF_READABLE; s->n_chan = 3; @@ -540,7 +540,7 @@ static int das800_attach(struct comedi_device *dev, struct comedi_devconfig *it) s->insn_bits = das800_di_rbits; /* do */ - s = &dev->subdevices[2]; + s = dev->subdevices + 2; s->type = COMEDI_SUBD_DO; s->subdev_flags = SDF_WRITABLE | SDF_READABLE; s->n_chan = 4; @@ -609,24 +609,44 @@ static int das800_ai_do_cmdtest(struct comedi_device *dev, int gain, startChan; int i; - /* Step 1 : check if triggers are trivially valid */ + /* step 1: make sure trigger sources are trivially valid */ - err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_EXT); - err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_FOLLOW); - err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_TIMER | TRIG_EXT); - err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT); - err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE); + tmp = cmd->start_src; + cmd->start_src &= TRIG_NOW | TRIG_EXT; + if (!cmd->start_src || tmp != cmd->start_src) + err++; + + tmp = cmd->scan_begin_src; + cmd->scan_begin_src &= TRIG_FOLLOW; + if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) + err++; + + tmp = cmd->convert_src; + cmd->convert_src &= TRIG_TIMER | TRIG_EXT; + if (!cmd->convert_src || tmp != cmd->convert_src) + err++; + + tmp = cmd->scan_end_src; + cmd->scan_end_src &= TRIG_COUNT; + if (!cmd->scan_end_src || tmp != cmd->scan_end_src) + err++; + + tmp = cmd->stop_src; + cmd->stop_src &= TRIG_COUNT | TRIG_NONE; + if (!cmd->stop_src || tmp != cmd->stop_src) + err++; if (err) return 1; - /* Step 2a : make sure trigger sources are unique */ - - err |= cfc_check_trigger_is_unique(cmd->start_src); - err |= cfc_check_trigger_is_unique(cmd->convert_src); - err |= cfc_check_trigger_is_unique(cmd->stop_src); + /* step 2: make sure trigger sources are unique and mutually compatible */ - /* Step 2b : and mutually compatible */ + if (cmd->start_src != TRIG_NOW && cmd->start_src != TRIG_EXT) + err++; + if (cmd->convert_src != TRIG_TIMER && cmd->convert_src != TRIG_EXT) + err++; + if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE) + err++; if (err) return 2; diff --git a/trunk/drivers/staging/comedi/drivers/dmm32at.c b/trunk/drivers/staging/comedi/drivers/dmm32at.c index 4d5c33c4750f..7107f590b1fe 100644 --- a/trunk/drivers/staging/comedi/drivers/dmm32at.c +++ b/trunk/drivers/staging/comedi/drivers/dmm32at.c @@ -41,8 +41,6 @@ Configuration Options: #include "../comedidev.h" #include -#include "comedi_fc.h" - /* Board register addresses */ #define DMM32AT_MEMSIZE 0x10 @@ -260,26 +258,47 @@ static int dmm32at_ai_cmdtest(struct comedi_device *dev, int tmp; int start_chan, gain, i; - /* Step 1 : check if triggers are trivially valid */ + /* step 1: make sure trigger sources are trivially valid */ + + tmp = cmd->start_src; + cmd->start_src &= TRIG_NOW; + if (!cmd->start_src || tmp != cmd->start_src) + err++; + + tmp = cmd->scan_begin_src; + cmd->scan_begin_src &= TRIG_TIMER /*| TRIG_EXT */ ; + if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) + err++; + + tmp = cmd->convert_src; + cmd->convert_src &= TRIG_TIMER /*| TRIG_EXT */ ; + if (!cmd->convert_src || tmp != cmd->convert_src) + err++; + + tmp = cmd->scan_end_src; + cmd->scan_end_src &= TRIG_COUNT; + if (!cmd->scan_end_src || tmp != cmd->scan_end_src) + err++; - err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW); - err |= cfc_check_trigger_src(&cmd->scan_begin_src, - TRIG_TIMER /*| TRIG_EXT */); - err |= cfc_check_trigger_src(&cmd->convert_src, - TRIG_TIMER /*| TRIG_EXT */); - err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT); - err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE); + tmp = cmd->stop_src; + cmd->stop_src &= TRIG_COUNT | TRIG_NONE; + if (!cmd->stop_src || tmp != cmd->stop_src) + err++; if (err) return 1; - /* Step 2a : make sure trigger sources are unique */ - - err |= cfc_check_trigger_is_unique(cmd->scan_begin_src); - err |= cfc_check_trigger_is_unique(cmd->convert_src); - err |= cfc_check_trigger_is_unique(cmd->stop_src); + /* step 2: make sure trigger sources are unique and mutually + * compatible */ - /* Step 2b : and mutually compatible */ + /* note that mutual compatibility is not an issue here */ + if (cmd->scan_begin_src != TRIG_TIMER && + cmd->scan_begin_src != TRIG_EXT) + err++; + if (cmd->convert_src != TRIG_TIMER && cmd->convert_src != TRIG_EXT) + err++; + if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE) + err++; if (err) return 2; @@ -806,7 +825,7 @@ static int dmm32at_attach(struct comedi_device *dev, if (ret) return ret; - s = &dev->subdevices[0]; + s = dev->subdevices + 0; dev->read_subdev = s; /* analog input subdevice */ s->type = COMEDI_SUBD_AI; @@ -822,7 +841,7 @@ static int dmm32at_attach(struct comedi_device *dev, s->do_cmdtest = dmm32at_ai_cmdtest; s->cancel = dmm32at_ai_cancel; - s = &dev->subdevices[1]; + s = dev->subdevices + 1; /* analog output subdevice */ s->type = COMEDI_SUBD_AO; s->subdev_flags = SDF_WRITABLE; @@ -832,7 +851,7 @@ static int dmm32at_attach(struct comedi_device *dev, s->insn_write = dmm32at_ao_winsn; s->insn_read = dmm32at_ao_rinsn; - s = &dev->subdevices[2]; + s = dev->subdevices + 2; /* digital i/o subdevice */ /* get access to the DIO regs */ diff --git a/trunk/drivers/staging/comedi/drivers/dt2801.c b/trunk/drivers/staging/comedi/drivers/dt2801.c index c59a652a1194..d332269375ab 100644 --- a/trunk/drivers/staging/comedi/drivers/dt2801.c +++ b/trunk/drivers/staging/comedi/drivers/dt2801.c @@ -532,7 +532,7 @@ static int dt2801_dio_insn_bits(struct comedi_device *dev, { int which = 0; - if (s == &dev->subdevices[3]) + if (s == dev->subdevices + 4) which = 1; if (data[0]) { @@ -555,7 +555,7 @@ static int dt2801_dio_insn_config(struct comedi_device *dev, { int which = 0; - if (s == &dev->subdevices[3]) + if (s == dev->subdevices + 4) which = 1; /* configure */ @@ -636,7 +636,7 @@ static int dt2801_attach(struct comedi_device *dev, struct comedi_devconfig *it) dev->board_name = boardtype.name; - s = &dev->subdevices[0]; + s = dev->subdevices + 0; /* ai subdevice */ s->type = COMEDI_SUBD_AI; s->subdev_flags = SDF_READABLE | SDF_GROUND; @@ -652,7 +652,7 @@ static int dt2801_attach(struct comedi_device *dev, struct comedi_devconfig *it) s->range_table = ai_range_lkup(boardtype.adrangetype, it->options[3]); s->insn_read = dt2801_ai_insn_read; - s = &dev->subdevices[1]; + s++; /* ao subdevice */ s->type = COMEDI_SUBD_AO; s->subdev_flags = SDF_WRITABLE; @@ -664,7 +664,7 @@ static int dt2801_attach(struct comedi_device *dev, struct comedi_devconfig *it) s->insn_read = dt2801_ao_insn_read; s->insn_write = dt2801_ao_insn_write; - s = &dev->subdevices[2]; + s++; /* 1st digital subdevice */ s->type = COMEDI_SUBD_DIO; s->subdev_flags = SDF_READABLE | SDF_WRITABLE; @@ -674,7 +674,7 @@ static int dt2801_attach(struct comedi_device *dev, struct comedi_devconfig *it) s->insn_bits = dt2801_dio_insn_bits; s->insn_config = dt2801_dio_insn_config; - s = &dev->subdevices[3]; + s++; /* 2nd digital subdevice */ s->type = COMEDI_SUBD_DIO; s->subdev_flags = SDF_READABLE | SDF_WRITABLE; diff --git a/trunk/drivers/staging/comedi/drivers/dt2811.c b/trunk/drivers/staging/comedi/drivers/dt2811.c index d3a8c1aec9d6..290b933c5f96 100644 --- a/trunk/drivers/staging/comedi/drivers/dt2811.c +++ b/trunk/drivers/staging/comedi/drivers/dt2811.c @@ -510,7 +510,7 @@ static int dt2811_attach(struct comedi_device *dev, struct comedi_devconfig *it) break; } - s = &dev->subdevices[0]; + s = dev->subdevices + 0; /* initialize the ADC subdevice */ s->type = COMEDI_SUBD_AI; s->subdev_flags = SDF_READABLE | SDF_GROUND; @@ -530,7 +530,7 @@ static int dt2811_attach(struct comedi_device *dev, struct comedi_devconfig *it) break; } - s = &dev->subdevices[1]; + s = dev->subdevices + 1; /* ao subdevice */ s->type = COMEDI_SUBD_AO; s->subdev_flags = SDF_WRITABLE; @@ -542,7 +542,7 @@ static int dt2811_attach(struct comedi_device *dev, struct comedi_devconfig *it) devpriv->range_type_list[0] = dac_range_types[devpriv->dac_range[0]]; devpriv->range_type_list[1] = dac_range_types[devpriv->dac_range[1]]; - s = &dev->subdevices[2]; + s = dev->subdevices + 2; /* di subdevice */ s->type = COMEDI_SUBD_DI; s->subdev_flags = SDF_READABLE; @@ -551,7 +551,7 @@ static int dt2811_attach(struct comedi_device *dev, struct comedi_devconfig *it) s->maxdata = 1; s->range_table = &range_digital; - s = &dev->subdevices[3]; + s = dev->subdevices + 3; /* do subdevice */ s->type = COMEDI_SUBD_DO; s->subdev_flags = SDF_WRITABLE; diff --git a/trunk/drivers/staging/comedi/drivers/dt2814.c b/trunk/drivers/staging/comedi/drivers/dt2814.c index 064a8f215e4d..2e39ebe36fb5 100644 --- a/trunk/drivers/staging/comedi/drivers/dt2814.c +++ b/trunk/drivers/staging/comedi/drivers/dt2814.c @@ -45,8 +45,6 @@ addition, the clock does not seem to be very accurate. #include #include -#include "comedi_fc.h" - #define DT2814_SIZE 2 #define DT2814_CSR 0 @@ -131,22 +129,42 @@ static int dt2814_ai_cmdtest(struct comedi_device *dev, int err = 0; int tmp; - /* Step 1 : check if triggers are trivially valid */ + /* step 1: make sure trigger sources are trivially valid */ + + tmp = cmd->start_src; + cmd->start_src &= TRIG_NOW; + if (!cmd->start_src || tmp != cmd->start_src) + err++; + + tmp = cmd->scan_begin_src; + cmd->scan_begin_src &= TRIG_TIMER; + if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) + err++; + + tmp = cmd->convert_src; + cmd->convert_src &= TRIG_NOW; + if (!cmd->convert_src || tmp != cmd->convert_src) + err++; + + tmp = cmd->scan_end_src; + cmd->scan_end_src &= TRIG_COUNT; + if (!cmd->scan_end_src || tmp != cmd->scan_end_src) + err++; - err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW); - err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_TIMER); - err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_NOW); - err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT); - err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE); + tmp = cmd->stop_src; + cmd->stop_src &= TRIG_COUNT | TRIG_NONE; + if (!cmd->stop_src || tmp != cmd->stop_src) + err++; if (err) return 1; - /* Step 2a : make sure trigger sources are unique */ - - err |= cfc_check_trigger_is_unique(cmd->stop_src); + /* step 2: make sure trigger sources are + * unique and mutually compatible */ - /* Step 2b : and mutually compatible */ + /* note that mutual compatibility is not an issue here */ + if (cmd->stop_src != TRIG_TIMER && cmd->stop_src != TRIG_EXT) + err++; if (err) return 2; @@ -229,7 +247,7 @@ static irqreturn_t dt2814_interrupt(int irq, void *d) return IRQ_HANDLED; } - s = &dev->subdevices[0]; + s = dev->subdevices + 0; hi = inb(dev->iobase + DT2814_DATA); lo = inb(dev->iobase + DT2814_DATA); @@ -328,7 +346,7 @@ static int dt2814_attach(struct comedi_device *dev, struct comedi_devconfig *it) if (ret < 0) return ret; - s = &dev->subdevices[0]; + s = dev->subdevices + 0; dev->read_subdev = s; s->type = COMEDI_SUBD_AI; s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_CMD_READ; diff --git a/trunk/drivers/staging/comedi/drivers/dt2815.c b/trunk/drivers/staging/comedi/drivers/dt2815.c index b9692ef64c41..45b20bee4369 100644 --- a/trunk/drivers/staging/comedi/drivers/dt2815.c +++ b/trunk/drivers/staging/comedi/drivers/dt2815.c @@ -185,7 +185,7 @@ static int dt2815_attach(struct comedi_device *dev, struct comedi_devconfig *it) if (alloc_private(dev, sizeof(struct dt2815_private)) < 0) return -ENOMEM; - s = &dev->subdevices[0]; + s = dev->subdevices; /* ao subdevice */ s->type = COMEDI_SUBD_AO; s->subdev_flags = SDF_WRITABLE; diff --git a/trunk/drivers/staging/comedi/drivers/dt2817.c b/trunk/drivers/staging/comedi/drivers/dt2817.c index 502e42e0753e..beba0447b3ee 100644 --- a/trunk/drivers/staging/comedi/drivers/dt2817.c +++ b/trunk/drivers/staging/comedi/drivers/dt2817.c @@ -141,7 +141,7 @@ static int dt2817_attach(struct comedi_device *dev, struct comedi_devconfig *it) if (ret) return ret; - s = &dev->subdevices[0]; + s = dev->subdevices + 0; s->n_chan = 32; s->type = COMEDI_SUBD_DIO; diff --git a/trunk/drivers/staging/comedi/drivers/dt282x.c b/trunk/drivers/staging/comedi/drivers/dt282x.c index 78d340716d1e..1f0b40e4bddd 100644 --- a/trunk/drivers/staging/comedi/drivers/dt282x.c +++ b/trunk/drivers/staging/comedi/drivers/dt282x.c @@ -312,7 +312,7 @@ static void dt282x_ao_dma_interrupt(struct comedi_device *dev) void *ptr; int size; int i; - struct comedi_subdevice *s = &dev->subdevices[1]; + struct comedi_subdevice *s = dev->subdevices + 1; outw(devpriv->supcsr | DT2821_CLRDMADNE, dev->iobase + DT2821_SUPCSR); @@ -345,7 +345,7 @@ static void dt282x_ai_dma_interrupt(struct comedi_device *dev) int size; int i; int ret; - struct comedi_subdevice *s = &dev->subdevices[0]; + struct comedi_subdevice *s = dev->subdevices; outw(devpriv->supcsr | DT2821_CLRDMADNE, dev->iobase + DT2821_SUPCSR); @@ -457,8 +457,8 @@ static irqreturn_t dt282x_interrupt(int irq, void *d) return IRQ_HANDLED; } - s = &dev->subdevices[0]; - s_ao = &dev->subdevices[1]; + s = dev->subdevices + 0; + s_ao = dev->subdevices + 1; adcsr = inw(dev->iobase + DT2821_ADCSR); dacsr = inw(dev->iobase + DT2821_DACSR); supcsr = inw(dev->iobase + DT2821_SUPCSR); @@ -582,24 +582,47 @@ static int dt282x_ai_cmdtest(struct comedi_device *dev, int err = 0; int tmp; - /* Step 1 : check if triggers are trivially valid */ + /* step 1: make sure trigger sources are trivially valid */ - err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW); - err |= cfc_check_trigger_src(&cmd->scan_begin_src, - TRIG_FOLLOW | TRIG_EXT); - err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_TIMER); - err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT); - err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE); + tmp = cmd->start_src; + cmd->start_src &= TRIG_NOW; + if (!cmd->start_src || tmp != cmd->start_src) + err++; + + tmp = cmd->scan_begin_src; + cmd->scan_begin_src &= TRIG_FOLLOW | TRIG_EXT; + if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) + err++; + + tmp = cmd->convert_src; + cmd->convert_src &= TRIG_TIMER; + if (!cmd->convert_src || tmp != cmd->convert_src) + err++; + + tmp = cmd->scan_end_src; + cmd->scan_end_src &= TRIG_COUNT; + if (!cmd->scan_end_src || tmp != cmd->scan_end_src) + err++; + + tmp = cmd->stop_src; + cmd->stop_src &= TRIG_COUNT | TRIG_NONE; + if (!cmd->stop_src || tmp != cmd->stop_src) + err++; if (err) return 1; - /* Step 2a : make sure trigger sources are unique */ + /* + * step 2: make sure trigger sources are unique + * and mutually compatible + */ - err |= cfc_check_trigger_is_unique(cmd->scan_begin_src); - err |= cfc_check_trigger_is_unique(cmd->stop_src); - - /* Step 2b : and mutually compatible */ + /* note that mutual compatibility is not an issue here */ + if (cmd->scan_begin_src != TRIG_FOLLOW && + cmd->scan_begin_src != TRIG_EXT) + err++; + if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE) + err++; if (err) return 2; @@ -839,22 +862,44 @@ static int dt282x_ao_cmdtest(struct comedi_device *dev, int err = 0; int tmp; - /* Step 1 : check if triggers are trivially valid */ + /* step 1: make sure trigger sources are trivially valid */ - err |= cfc_check_trigger_src(&cmd->start_src, TRIG_INT); - err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_TIMER); - err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_NOW); - err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT); - err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE); + tmp = cmd->start_src; + cmd->start_src &= TRIG_INT; + if (!cmd->start_src || tmp != cmd->start_src) + err++; + + tmp = cmd->scan_begin_src; + cmd->scan_begin_src &= TRIG_TIMER; + if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) + err++; + + tmp = cmd->convert_src; + cmd->convert_src &= TRIG_NOW; + if (!cmd->convert_src || tmp != cmd->convert_src) + err++; + + tmp = cmd->scan_end_src; + cmd->scan_end_src &= TRIG_COUNT; + if (!cmd->scan_end_src || tmp != cmd->scan_end_src) + err++; + + tmp = cmd->stop_src; + cmd->stop_src &= TRIG_NONE; + if (!cmd->stop_src || tmp != cmd->stop_src) + err++; if (err) return 1; - /* Step 2a : make sure trigger sources are unique */ + /* + * step 2: make sure trigger sources are unique + * and mutually compatible + */ - err |= cfc_check_trigger_is_unique(cmd->stop_src); - - /* Step 2b : and mutually compatible */ + /* note that mutual compatibility is not an issue here */ + if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE) + err++; if (err) return 2; @@ -1230,7 +1275,7 @@ static int dt282x_attach(struct comedi_device *dev, struct comedi_devconfig *it) if (ret) return ret; - s = &dev->subdevices[0]; + s = dev->subdevices + 0; dev->read_subdev = s; /* ai subdevice */ @@ -1249,7 +1294,7 @@ static int dt282x_attach(struct comedi_device *dev, struct comedi_devconfig *it) opt_ai_range_lkup(boardtype.ispgl, it->options[opt_ai_range]); devpriv->ad_2scomp = it->options[opt_ai_twos]; - s = &dev->subdevices[1]; + s++; s->n_chan = boardtype.dachan; if (s->n_chan) { @@ -1275,7 +1320,7 @@ static int dt282x_attach(struct comedi_device *dev, struct comedi_devconfig *it) s->type = COMEDI_SUBD_UNUSED; } - s = &dev->subdevices[2]; + s++; /* dio subsystem */ s->type = COMEDI_SUBD_DIO; s->subdev_flags = SDF_READABLE | SDF_WRITABLE; diff --git a/trunk/drivers/staging/comedi/drivers/dt3000.c b/trunk/drivers/staging/comedi/drivers/dt3000.c index 43d05ef97157..a6fe6c9be87e 100644 --- a/trunk/drivers/staging/comedi/drivers/dt3000.c +++ b/trunk/drivers/staging/comedi/drivers/dt3000.c @@ -63,8 +63,6 @@ AO commands are not supported. #include "../comedidev.h" #include -#include "comedi_fc.h" - #define PCI_VENDOR_ID_DT 0x1116 static const struct comedi_lrange range_dt3000_ai = { 4, { @@ -332,7 +330,7 @@ static irqreturn_t dt3k_interrupt(int irq, void *d) if (!dev->attached) return IRQ_NONE; - s = &dev->subdevices[0]; + s = dev->subdevices + 0; status = readw(devpriv->io_addr + DPR_Intr_Flag); #ifdef DEBUG debug_intr_flags(status); @@ -410,19 +408,37 @@ static int dt3k_ai_cmdtest(struct comedi_device *dev, int err = 0; int tmp; - /* Step 1 : check if triggers are trivially valid */ + /* step 1: make sure trigger sources are trivially valid */ + + tmp = cmd->start_src; + cmd->start_src &= TRIG_NOW; + if (!cmd->start_src || tmp != cmd->start_src) + err++; + + tmp = cmd->scan_begin_src; + cmd->scan_begin_src &= TRIG_TIMER; + if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) + err++; + + tmp = cmd->convert_src; + cmd->convert_src &= TRIG_TIMER; + if (!cmd->convert_src || tmp != cmd->convert_src) + err++; - err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW); - err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_TIMER); - err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_TIMER); - err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT); - err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT); + tmp = cmd->scan_end_src; + cmd->scan_end_src &= TRIG_COUNT; + if (!cmd->scan_end_src || tmp != cmd->scan_end_src) + err++; + + tmp = cmd->stop_src; + cmd->stop_src &= TRIG_COUNT; + if (!cmd->stop_src || tmp != cmd->stop_src) + err++; if (err) return 1; - /* Step 2a : make sure trigger sources are unique */ - /* Step 2b : and mutually compatible */ + /* step 2: make sure trigger sources are unique and mutually compatible */ if (err) return 2; @@ -788,7 +804,6 @@ static int dt3000_attach(struct comedi_device *dev, struct comedi_devconfig *it) { struct pci_dev *pcidev; struct comedi_subdevice *s; - resource_size_t pci_base; int ret = 0; dev_dbg(dev->class_dev, "dt3000:\n"); @@ -805,10 +820,9 @@ static int dt3000_attach(struct comedi_device *dev, struct comedi_devconfig *it) ret = comedi_pci_enable(pcidev, "dt3000"); if (ret < 0) return ret; - dev->iobase = 1; /* the "detach" needs this */ - pci_base = pci_resource_start(pcidev, 0); - devpriv->io_addr = ioremap(pci_base, DT3000_SIZE); + dev->iobase = pci_resource_start(pcidev, 0); + devpriv->io_addr = ioremap(dev->iobase, DT3000_SIZE); if (!devpriv->io_addr) return -ENOMEM; @@ -826,7 +840,7 @@ static int dt3000_attach(struct comedi_device *dev, struct comedi_devconfig *it) if (ret) return ret; - s = &dev->subdevices[0]; + s = dev->subdevices; dev->read_subdev = s; /* ai subdevice */ @@ -841,7 +855,7 @@ static int dt3000_attach(struct comedi_device *dev, struct comedi_devconfig *it) s->do_cmdtest = dt3k_ai_cmdtest; s->cancel = dt3k_ai_cancel; - s = &dev->subdevices[1]; + s++; /* ao subsystem */ s->type = COMEDI_SUBD_AO; s->subdev_flags = SDF_WRITABLE; @@ -852,7 +866,7 @@ static int dt3000_attach(struct comedi_device *dev, struct comedi_devconfig *it) s->len_chanlist = 1; s->range_table = &range_bipolar10; - s = &dev->subdevices[2]; + s++; /* dio subsystem */ s->type = COMEDI_SUBD_DIO; s->subdev_flags = SDF_READABLE | SDF_WRITABLE; @@ -863,7 +877,7 @@ static int dt3000_attach(struct comedi_device *dev, struct comedi_devconfig *it) s->len_chanlist = 8; s->range_table = &range_digital; - s = &dev->subdevices[3]; + s++; /* mem subsystem */ s->type = COMEDI_SUBD_MEMORY; s->subdev_flags = SDF_READABLE; @@ -874,7 +888,7 @@ static int dt3000_attach(struct comedi_device *dev, struct comedi_devconfig *it) s->range_table = &range_unknown; #if 0 - s = &dev->subdevices[4]; + s++; /* proc subsystem */ s->type = COMEDI_SUBD_PROC; #endif diff --git a/trunk/drivers/staging/comedi/drivers/dt9812.c b/trunk/drivers/staging/comedi/drivers/dt9812.c index bc6f409b7e19..40821c7303ea 100644 --- a/trunk/drivers/staging/comedi/drivers/dt9812.c +++ b/trunk/drivers/staging/comedi/drivers/dt9812.c @@ -1041,7 +1041,7 @@ static int dt9812_attach(struct comedi_device *dev, struct comedi_devconfig *it) return ret; /* digital input subdevice */ - s = &dev->subdevices[0]; + s = dev->subdevices + 0; s->type = COMEDI_SUBD_DI; s->subdev_flags = SDF_READABLE; s->n_chan = 0; @@ -1050,7 +1050,7 @@ static int dt9812_attach(struct comedi_device *dev, struct comedi_devconfig *it) s->insn_read = &dt9812_di_rinsn; /* digital output subdevice */ - s = &dev->subdevices[1]; + s = dev->subdevices + 1; s->type = COMEDI_SUBD_DO; s->subdev_flags = SDF_WRITEABLE; s->n_chan = 0; @@ -1059,7 +1059,7 @@ static int dt9812_attach(struct comedi_device *dev, struct comedi_devconfig *it) s->insn_write = &dt9812_do_winsn; /* analog input subdevice */ - s = &dev->subdevices[2]; + s = dev->subdevices + 2; s->type = COMEDI_SUBD_AI; s->subdev_flags = SDF_READABLE | SDF_GROUND; s->n_chan = 0; @@ -1068,7 +1068,7 @@ static int dt9812_attach(struct comedi_device *dev, struct comedi_devconfig *it) s->insn_read = &dt9812_ai_rinsn; /* analog output subdevice */ - s = &dev->subdevices[3]; + s = dev->subdevices + 3; s->type = COMEDI_SUBD_AO; s->subdev_flags = SDF_WRITEABLE; s->n_chan = 0; diff --git a/trunk/drivers/staging/comedi/drivers/dyna_pci10xx.c b/trunk/drivers/staging/comedi/drivers/dyna_pci10xx.c index 6f612be1b0a5..064be9aae3aa 100644 --- a/trunk/drivers/staging/comedi/drivers/dyna_pci10xx.c +++ b/trunk/drivers/staging/comedi/drivers/dyna_pci10xx.c @@ -41,6 +41,7 @@ #include #define PCI_VENDOR_ID_DYNALOG 0x10b5 +#define DRV_NAME "dyna_pci10xx" #define READ_TIMEOUT 50 @@ -53,11 +54,59 @@ static const struct comedi_lrange range_pci1050_ai = { 3, { static const char range_codes_pci1050_ai[] = { 0x00, 0x10, 0x30 }; +static const struct comedi_lrange range_pci1050_ao = { 1, { + UNI_RANGE(10) + } +}; + +static const char range_codes_pci1050_ao[] = { 0x00 }; + +struct boardtype { + const char *name; + int device_id; + int ai_chans; + int ai_bits; + int ao_chans; + int ao_bits; + int di_chans; + int di_bits; + int do_chans; + int do_bits; + const struct comedi_lrange *range_ai; + const char *range_codes_ai; + const struct comedi_lrange *range_ao; + const char *range_codes_ao; +}; + +static const struct boardtype boardtypes[] = { + { + .name = "dyna_pci1050", + .device_id = 0x1050, + .ai_chans = 16, + .ai_bits = 12, + .ao_chans = 16, + .ao_bits = 12, + .di_chans = 16, + .di_bits = 16, + .do_chans = 16, + .do_bits = 16, + .range_ai = &range_pci1050_ai, + .range_codes_ai = range_codes_pci1050_ai, + .range_ao = &range_pci1050_ao, + .range_codes_ao = range_codes_pci1050_ao, + }, + /* dummy entry corresponding to driver name */ + {.name = DRV_NAME}, +}; + struct dyna_pci10xx_private { struct mutex mutex; unsigned long BADR3; }; +#define thisboard ((const struct boardtype *)dev->board_ptr) +#define devpriv ((struct dyna_pci10xx_private *)dev->private) + /******************************************************************************/ /************************** READ WRITE FUNCTIONS ******************************/ /******************************************************************************/ @@ -67,14 +116,13 @@ static int dyna_pci10xx_insn_read_ai(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - struct dyna_pci10xx_private *devpriv = dev->private; int n, counter; u16 d = 0; unsigned int chan, range; /* get the channel number and range */ chan = CR_CHAN(insn->chanspec); - range = range_codes_pci1050_ai[CR_RANGE((insn->chanspec))]; + range = thisboard->range_codes_ai[CR_RANGE((insn->chanspec))]; mutex_lock(&devpriv->mutex); /* convert n samples */ @@ -111,12 +159,11 @@ static int dyna_pci10xx_insn_write_ao(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - struct dyna_pci10xx_private *devpriv = dev->private; int n; unsigned int chan, range; chan = CR_CHAN(insn->chanspec); - range = range_codes_pci1050_ai[CR_RANGE((insn->chanspec))]; + range = thisboard->range_codes_ai[CR_RANGE((insn->chanspec))]; mutex_lock(&devpriv->mutex); for (n = 0; n < insn->n; n++) { @@ -134,7 +181,6 @@ static int dyna_pci10xx_di_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - struct dyna_pci10xx_private *devpriv = dev->private; u16 d = 0; mutex_lock(&devpriv->mutex); @@ -154,8 +200,6 @@ static int dyna_pci10xx_do_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - struct dyna_pci10xx_private *devpriv = dev->private; - /* The insn data is a mask in data[0] and the new data * in data[1], each channel cooresponding to a bit. * s->state contains the previous write data @@ -179,98 +223,143 @@ static int dyna_pci10xx_do_insn_bits(struct comedi_device *dev, return insn->n; } -static int dyna_pci10xx_attach_pci(struct comedi_device *dev, - struct pci_dev *pcidev) +static struct pci_dev *dyna_pci10xx_find_pci_dev(struct comedi_device *dev, + struct comedi_devconfig *it) +{ + struct pci_dev *pcidev = NULL; + int bus = it->options[0]; + int slot = it->options[1]; + int i; + + for_each_pci_dev(pcidev) { + if (bus || slot) { + if (bus != pcidev->bus->number || + slot != PCI_SLOT(pcidev->devfn)) + continue; + } + if (pcidev->vendor != PCI_VENDOR_ID_DYNALOG) + continue; + + for (i = 0; i < ARRAY_SIZE(boardtypes); ++i) { + if (pcidev->device != boardtypes[i].device_id) + continue; + + dev->board_ptr = &boardtypes[i]; + return pcidev; + } + } + dev_err(dev->class_dev, + "No supported board found! (req. bus %d, slot %d)\n", + bus, slot); + return NULL; +} + +static int dyna_pci10xx_attach(struct comedi_device *dev, + struct comedi_devconfig *it) { - struct dyna_pci10xx_private *devpriv; + struct pci_dev *pcidev; struct comedi_subdevice *s; int ret; + if (alloc_private(dev, sizeof(struct dyna_pci10xx_private)) < 0) { + printk(KERN_ERR "comedi: dyna_pci10xx: " + "failed to allocate memory!\n"); + return -ENOMEM; + } + + pcidev = dyna_pci10xx_find_pci_dev(dev, it); + if (!pcidev) + return -EIO; comedi_set_hw_dev(dev, &pcidev->dev); - dev->board_name = dev->driver->driver_name; + dev->board_name = thisboard->name; + dev->irq = 0; - ret = alloc_private(dev, sizeof(*devpriv)); - if (ret) - return ret; - devpriv = dev->private; + if (comedi_pci_enable(pcidev, DRV_NAME)) { + printk(KERN_ERR "comedi: dyna_pci10xx: " + "failed to enable PCI device and request regions!"); + return -EIO; + } + + mutex_init(&devpriv->mutex); + + printk(KERN_INFO "comedi: dyna_pci10xx: device found!\n"); - ret = comedi_pci_enable(pcidev, dev->board_name); - if (ret) - return ret; dev->iobase = pci_resource_start(pcidev, 2); devpriv->BADR3 = pci_resource_start(pcidev, 3); - mutex_init(&devpriv->mutex); - ret = comedi_alloc_subdevices(dev, 4); if (ret) return ret; /* analog input */ - s = &dev->subdevices[0]; + s = dev->subdevices + 0; s->type = COMEDI_SUBD_AI; s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DIFF; - s->n_chan = 16; + s->n_chan = thisboard->ai_chans; s->maxdata = 0x0FFF; - s->range_table = &range_pci1050_ai; + s->range_table = thisboard->range_ai; s->len_chanlist = 16; s->insn_read = dyna_pci10xx_insn_read_ai; /* analog output */ - s = &dev->subdevices[1]; + s = dev->subdevices + 1; s->type = COMEDI_SUBD_AO; s->subdev_flags = SDF_WRITABLE; - s->n_chan = 16; + s->n_chan = thisboard->ao_chans; s->maxdata = 0x0FFF; - s->range_table = &range_unipolar10; + s->range_table = thisboard->range_ao; s->len_chanlist = 16; s->insn_write = dyna_pci10xx_insn_write_ao; /* digital input */ - s = &dev->subdevices[2]; + s = dev->subdevices + 2; s->type = COMEDI_SUBD_DI; s->subdev_flags = SDF_READABLE | SDF_GROUND; - s->n_chan = 16; + s->n_chan = thisboard->di_chans; s->maxdata = 1; s->range_table = &range_digital; - s->len_chanlist = 16; + s->len_chanlist = thisboard->di_chans; s->insn_bits = dyna_pci10xx_di_insn_bits; /* digital output */ - s = &dev->subdevices[3]; + s = dev->subdevices + 3; s->type = COMEDI_SUBD_DO; s->subdev_flags = SDF_WRITABLE | SDF_GROUND; - s->n_chan = 16; + s->n_chan = thisboard->do_chans; s->maxdata = 1; s->range_table = &range_digital; - s->len_chanlist = 16; + s->len_chanlist = thisboard->do_chans; s->state = 0; s->insn_bits = dyna_pci10xx_do_insn_bits; - dev_info(dev->class_dev, "%s attached\n", dev->board_name); + printk(KERN_INFO "comedi: dyna_pci10xx: %s - device setup completed!\n", + thisboard->name); - return 0; + return 1; } static void dyna_pci10xx_detach(struct comedi_device *dev) { struct pci_dev *pcidev = comedi_to_pci_dev(dev); - struct dyna_pci10xx_private *devpriv = dev->private; if (devpriv) mutex_destroy(&devpriv->mutex); if (pcidev) { if (dev->iobase) comedi_pci_disable(pcidev); + pci_dev_put(pcidev); } } static struct comedi_driver dyna_pci10xx_driver = { .driver_name = "dyna_pci10xx", .module = THIS_MODULE, - .attach_pci = dyna_pci10xx_attach_pci, + .attach = dyna_pci10xx_attach, .detach = dyna_pci10xx_detach, + .board_name = &boardtypes[0].name, + .offset = sizeof(struct boardtype), + .num_names = ARRAY_SIZE(boardtypes), }; static int __devinit dyna_pci10xx_pci_probe(struct pci_dev *dev, diff --git a/trunk/drivers/staging/comedi/drivers/fl512.c b/trunk/drivers/staging/comedi/drivers/fl512.c index ae8e8f460295..d1da80976f84 100644 --- a/trunk/drivers/staging/comedi/drivers/fl512.c +++ b/trunk/drivers/staging/comedi/drivers/fl512.c @@ -140,7 +140,7 @@ static int fl512_attach(struct comedi_device *dev, struct comedi_devconfig *it) * this if the definitions of the supdevices, 2 have been defined */ /* Analog indput */ - s = &dev->subdevices[0]; + s = dev->subdevices + 0; /* define subdevice as Analog In */ s->type = COMEDI_SUBD_AI; /* you can read it from userspace */ @@ -156,7 +156,7 @@ static int fl512_attach(struct comedi_device *dev, struct comedi_devconfig *it) printk(KERN_INFO "comedi: fl512: subdevice 0 initialized\n"); /* Analog output */ - s = &dev->subdevices[1]; + s = dev->subdevices + 1; /* define subdevice as Analog OUT */ s->type = COMEDI_SUBD_AO; /* you can write it from userspace */ diff --git a/trunk/drivers/staging/comedi/drivers/gsc_hpdi.c b/trunk/drivers/staging/comedi/drivers/gsc_hpdi.c index abff6603952a..79f580841dee 100644 --- a/trunk/drivers/staging/comedi/drivers/gsc_hpdi.c +++ b/trunk/drivers/staging/comedi/drivers/gsc_hpdi.c @@ -436,7 +436,7 @@ static int setup_subdevices(struct comedi_device *dev) if (ret) return ret; - s = &dev->subdevices[0]; + s = dev->subdevices + 0; /* analog input subdevice */ dev->read_subdev = s; /* dev->write_subdev = s; */ @@ -723,24 +723,45 @@ static int di_cmd_test(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd) { int err = 0; + int tmp; int i; - /* Step 1 : check if triggers are trivially valid */ + /* step 1: make sure trigger sources are trivially valid */ - err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW); - err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_EXT); - err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_NOW); - err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT); - err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE); + tmp = cmd->start_src; + cmd->start_src &= TRIG_NOW; + if (!cmd->start_src || tmp != cmd->start_src) + err++; + + tmp = cmd->scan_begin_src; + cmd->scan_begin_src &= TRIG_EXT; + if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) + err++; + + tmp = cmd->convert_src; + cmd->convert_src &= TRIG_NOW; + if (!cmd->convert_src || tmp != cmd->convert_src) + err++; + + tmp = cmd->scan_end_src; + cmd->scan_end_src &= TRIG_COUNT; + if (!cmd->scan_end_src || tmp != cmd->scan_end_src) + err++; + + tmp = cmd->stop_src; + cmd->stop_src &= TRIG_COUNT | TRIG_NONE; + if (!cmd->stop_src || tmp != cmd->stop_src) + err++; if (err) return 1; - /* Step 2a : make sure trigger sources are unique */ + /* step 2: make sure trigger sources are unique and mutually + * compatible */ - err |= cfc_check_trigger_is_unique(cmd->stop_src); - - /* Step 2b : and mutually compatible */ + /* uniqueness check */ + if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE) + err++; if (err) return 2; diff --git a/trunk/drivers/staging/comedi/drivers/icp_multi.c b/trunk/drivers/staging/comedi/drivers/icp_multi.c index d696d4d51e28..b10ebdbc1f7e 100644 --- a/trunk/drivers/staging/comedi/drivers/icp_multi.c +++ b/trunk/drivers/staging/comedi/drivers/icp_multi.c @@ -44,7 +44,10 @@ There are 4 x 12-bit Analogue Outputs. Ranges : 5V, 10V, +/-5V, +/-10V 4 x 16-bit counters -Configuration options: not applicable, uses PCI auto config +Options: + [0] - PCI bus number - if bus number and slot number are 0, + then driver search for first unused card + [1] - PCI slot number */ #include @@ -53,7 +56,16 @@ Configuration options: not applicable, uses PCI auto config #include #include -#define PCI_DEVICE_ID_ICP_MULTI 0x8000 +#include "icp_multi.h" + +#define DEVICE_ID 0x8000 /* Device ID */ + +#define ICP_MULTI_EXTDEBUG + +/* Hardware types of the cards */ +#define TYPE_ICP_MULTI 0 + +#define IORANGE_ICP_MULTI 32 #define ICP_MULTI_ADC_CSR 0 /* R/W: ADC command/status register */ #define ICP_MULTI_AI 2 /* R: Analogue input data */ @@ -112,10 +124,32 @@ static const char range_codes_analog[] = { 0x00, 0x20, 0x10, 0x30 }; Data & Structure declarations ============================================================================== */ +static unsigned short pci_list_builded; /*>0 list of card is known */ + +struct boardtype { + const char *name; /* driver name */ + int device_id; + int iorange; /* I/O range len */ + char have_irq; /* 1=card support IRQ */ + char cardtype; /* 0=ICP Multi */ + int n_aichan; /* num of A/D chans */ + int n_aichand; /* num of A/D chans in diff mode */ + int n_aochan; /* num of D/A chans */ + int n_dichan; /* num of DI chans */ + int n_dochan; /* num of DO chans */ + int n_ctrs; /* num of counters */ + int ai_maxdata; /* resolution of A/D */ + int ao_maxdata; /* resolution of D/A */ + const struct comedi_lrange *rangelist_ai; /* rangelist for A/D */ + const char *rangecode; /* range codes for programming */ + const struct comedi_lrange *rangelist_ao; /* rangelist for D/A */ +}; struct icp_multi_private { + struct pcilst_struct *card; /* pointer to card */ char valid; /* card is usable */ void __iomem *io_addr; /* Pointer to mapped io address */ + resource_size_t phys_iobase; /* Physical io address */ unsigned int AdcCmdStatus; /* ADC Command/Status register */ unsigned int DacCmdStatus; /* DAC Command/Status register */ unsigned int IntEnable; /* Interrupt Enable register */ @@ -130,14 +164,40 @@ struct icp_multi_private { unsigned int do_data; /* Remember digital output data */ }; +#define devpriv ((struct icp_multi_private *)dev->private) +#define this_board ((const struct boardtype *)dev->board_ptr) + +/* +============================================================================== + +Name: setup_channel_list + +Description: + This function sets the appropriate channel selection, + differential input mode and range bits in the ADC Command/ + Status register. + +Parameters: + struct comedi_device *dev Pointer to current service structure + struct comedi_subdevice *s Pointer to current subdevice structure + unsigned int *chanlist Pointer to packed channel list + unsigned int n_chan Number of channels to scan + +Returns:Void + +============================================================================== +*/ static void setup_channel_list(struct comedi_device *dev, struct comedi_subdevice *s, unsigned int *chanlist, unsigned int n_chan) { - struct icp_multi_private *devpriv = dev->private; unsigned int i, range, chanprog; unsigned int diff; +#ifdef ICP_MULTI_EXTDEBUG + printk(KERN_DEBUG + "icp multi EDBG: setup_channel_list(...,%d)\n", n_chan); +#endif devpriv->act_chanlist_len = n_chan; devpriv->act_chanlist_pos = 0; @@ -168,23 +228,50 @@ static void setup_channel_list(struct comedi_device *dev, devpriv->AdcCmdStatus |= (chanprog << 8); /* Get range for current channel */ - range = range_codes_analog[CR_RANGE(chanlist[i])]; + range = this_board->rangecode[CR_RANGE(chanlist[i])]; /* Set range. bits 4-5 */ devpriv->AdcCmdStatus |= range; /* Output channel, range, mode to ICP Multi */ writew(devpriv->AdcCmdStatus, devpriv->io_addr + ICP_MULTI_ADC_CSR); + +#ifdef ICP_MULTI_EXTDEBUG + printk(KERN_DEBUG + "GS: %2d. [%4x]=%4x %4x\n", i, chanprog, range, + devpriv->act_chanlist[i]); +#endif } + } +/* +============================================================================== + +Name: icp_multi_insn_read_ai + +Description: + This function reads a single analogue input. + +Parameters: + struct comedi_device *dev Pointer to current device structure + struct comedi_subdevice *s Pointer to current subdevice structure + struct comedi_insn *insn Pointer to current comedi instruction + unsigned int *data Pointer to analogue input data + +Returns:int Nmuber of instructions executed + +============================================================================== +*/ static int icp_multi_insn_read_ai(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - struct icp_multi_private *devpriv = dev->private; int n, timeout; +#ifdef ICP_MULTI_EXTDEBUG + printk(KERN_DEBUG "icp multi EDBG: BGN: icp_multi_insn_read_ai(...)\n"); +#endif /* Disable A/D conversion ready interrupt */ devpriv->IntEnable &= ~ADC_READY; writew(devpriv->IntEnable, devpriv->io_addr + ICP_MULTI_INT_EN); @@ -196,6 +283,12 @@ static int icp_multi_insn_read_ai(struct comedi_device *dev, /* Set up appropriate channel, mode and range data, for specified ch */ setup_channel_list(dev, s, &insn->chanspec, 1); +#ifdef ICP_MULTI_EXTDEBUG + printk(KERN_DEBUG "icp_multi A ST=%4x IO=%p\n", + readw(devpriv->io_addr + ICP_MULTI_ADC_CSR), + devpriv->io_addr + ICP_MULTI_ADC_CSR); +#endif + for (n = 0; n < insn->n; n++) { /* Set start ADC bit */ devpriv->AdcCmdStatus |= ADC_ST; @@ -203,8 +296,18 @@ static int icp_multi_insn_read_ai(struct comedi_device *dev, devpriv->io_addr + ICP_MULTI_ADC_CSR); devpriv->AdcCmdStatus &= ~ADC_ST; +#ifdef ICP_MULTI_EXTDEBUG + printk(KERN_DEBUG "icp multi B n=%d ST=%4x\n", n, + readw(devpriv->io_addr + ICP_MULTI_ADC_CSR)); +#endif + udelay(1); +#ifdef ICP_MULTI_EXTDEBUG + printk(KERN_DEBUG "icp multi C n=%d ST=%4x\n", n, + readw(devpriv->io_addr + ICP_MULTI_ADC_CSR)); +#endif + /* Wait for conversion to complete, or get fed up waiting */ timeout = 100; while (timeout--) { @@ -212,6 +315,15 @@ static int icp_multi_insn_read_ai(struct comedi_device *dev, ICP_MULTI_ADC_CSR) & ADC_BSY)) goto conv_finish; +#ifdef ICP_MULTI_EXTDEBUG + if (!(timeout % 10)) + printk(KERN_DEBUG + "icp multi D n=%d tm=%d ST=%4x\n", n, + timeout, + readw(devpriv->io_addr + + ICP_MULTI_ADC_CSR)); +#endif + udelay(1); } @@ -230,6 +342,11 @@ static int icp_multi_insn_read_ai(struct comedi_device *dev, /* Clear data received */ data[n] = 0; +#ifdef ICP_MULTI_EXTDEBUG + printk(KERN_DEBUG + "icp multi EDBG: END: icp_multi_insn_read_ai(...) n=%d\n", + n); +#endif return -ETIME; conv_finish: @@ -245,16 +362,41 @@ static int icp_multi_insn_read_ai(struct comedi_device *dev, devpriv->IntStatus |= ADC_READY; writew(devpriv->IntStatus, devpriv->io_addr + ICP_MULTI_INT_STAT); +#ifdef ICP_MULTI_EXTDEBUG + printk(KERN_DEBUG + "icp multi EDBG: END: icp_multi_insn_read_ai(...) n=%d\n", n); +#endif return n; } +/* +============================================================================== + +Name: icp_multi_insn_write_ao + +Description: + This function writes a single analogue output. + +Parameters: + struct comedi_device *dev Pointer to current device structure + struct comedi_subdevice *s Pointer to current subdevice structure + struct comedi_insn *insn Pointer to current comedi instruction + unsigned int *data Pointer to analogue output data + +Returns:int Nmuber of instructions executed + +============================================================================== +*/ static int icp_multi_insn_write_ao(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - struct icp_multi_private *devpriv = dev->private; int n, chan, range, timeout; +#ifdef ICP_MULTI_EXTDEBUG + printk(KERN_DEBUG + "icp multi EDBG: BGN: icp_multi_insn_write_ao(...)\n"); +#endif /* Disable D/A conversion ready interrupt */ devpriv->IntEnable &= ~DAC_READY; writew(devpriv->IntEnable, devpriv->io_addr + ICP_MULTI_INT_EN); @@ -273,7 +415,7 @@ static int icp_multi_insn_write_ao(struct comedi_device *dev, /* Bit 5 = 1 : 10V */ /* Bits 8-9 : Channel number */ devpriv->DacCmdStatus &= 0xfccf; - devpriv->DacCmdStatus |= range_codes_analog[range]; + devpriv->DacCmdStatus |= this_board->rangecode[range]; devpriv->DacCmdStatus |= (chan << 8); writew(devpriv->DacCmdStatus, devpriv->io_addr + ICP_MULTI_DAC_CSR); @@ -287,6 +429,15 @@ static int icp_multi_insn_write_ao(struct comedi_device *dev, ICP_MULTI_DAC_CSR) & DAC_BSY)) goto dac_ready; +#ifdef ICP_MULTI_EXTDEBUG + if (!(timeout % 10)) + printk(KERN_DEBUG + "icp multi A n=%d tm=%d ST=%4x\n", n, + timeout, + readw(devpriv->io_addr + + ICP_MULTI_DAC_CSR)); +#endif + udelay(1); } @@ -305,6 +456,11 @@ static int icp_multi_insn_write_ao(struct comedi_device *dev, /* Clear data received */ devpriv->ao_data[chan] = 0; +#ifdef ICP_MULTI_EXTDEBUG + printk(KERN_DEBUG + "icp multi EDBG: END: icp_multi_insn_write_ao(...) n=%d\n", + n); +#endif return -ETIME; dac_ready: @@ -321,14 +477,35 @@ static int icp_multi_insn_write_ao(struct comedi_device *dev, devpriv->ao_data[chan] = data[n]; } +#ifdef ICP_MULTI_EXTDEBUG + printk(KERN_DEBUG + "icp multi EDBG: END: icp_multi_insn_write_ao(...) n=%d\n", n); +#endif return n; } +/* +============================================================================== + +Name: icp_multi_insn_read_ao + +Description: + This function reads a single analogue output. + +Parameters: + struct comedi_device *dev Pointer to current device structure + struct comedi_subdevice *s Pointer to current subdevice structure + struct comedi_insn *insn Pointer to current comedi instruction + unsigned int *data Pointer to analogue output data + +Returns:int Nmuber of instructions executed + +============================================================================== +*/ static int icp_multi_insn_read_ao(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - struct icp_multi_private *devpriv = dev->private; int n, chan; /* Get channel number */ @@ -341,22 +518,58 @@ static int icp_multi_insn_read_ao(struct comedi_device *dev, return n; } +/* +============================================================================== + +Name: icp_multi_insn_bits_di + +Description: + This function reads the digital inputs. + +Parameters: + struct comedi_device *dev Pointer to current device structure + struct comedi_subdevice *s Pointer to current subdevice structure + struct comedi_insn *insn Pointer to current comedi instruction + unsigned int *data Pointer to analogue output data + +Returns:int Nmuber of instructions executed + +============================================================================== +*/ static int icp_multi_insn_bits_di(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - struct icp_multi_private *devpriv = dev->private; - data[1] = readw(devpriv->io_addr + ICP_MULTI_DI); return insn->n; } +/* +============================================================================== + +Name: icp_multi_insn_bits_do + +Description: + This function writes the appropriate digital outputs. + +Parameters: + struct comedi_device *dev Pointer to current device structure + struct comedi_subdevice *s Pointer to current subdevice structure + struct comedi_insn *insn Pointer to current comedi instruction + unsigned int *data Pointer to analogue output data + +Returns:int Nmuber of instructions executed + +============================================================================== +*/ static int icp_multi_insn_bits_do(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - struct icp_multi_private *devpriv = dev->private; +#ifdef ICP_MULTI_EXTDEBUG + printk(KERN_DEBUG "icp multi EDBG: BGN: icp_multi_insn_bits_do(...)\n"); +#endif if (data[0]) { s->state &= ~data[0]; @@ -369,9 +582,30 @@ static int icp_multi_insn_bits_do(struct comedi_device *dev, data[1] = readw(devpriv->io_addr + ICP_MULTI_DI); +#ifdef ICP_MULTI_EXTDEBUG + printk(KERN_DEBUG "icp multi EDBG: END: icp_multi_insn_bits_do(...)\n"); +#endif return insn->n; } +/* +============================================================================== + +Name: icp_multi_insn_read_ctr + +Description: + This function reads the specified counter. + +Parameters: + struct comedi_device *dev Pointer to current device structure + struct comedi_subdevice *s Pointer to current subdevice structure + struct comedi_insn *insn Pointer to current comedi instruction + unsigned int *data Pointer to counter data + +Returns:int Nmuber of instructions executed + +============================================================================== +*/ static int icp_multi_insn_read_ctr(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) @@ -379,6 +613,24 @@ static int icp_multi_insn_read_ctr(struct comedi_device *dev, return 0; } +/* +============================================================================== + +Name: icp_multi_insn_write_ctr + +Description: + This function write to the specified counter. + +Parameters: + struct comedi_device *dev Pointer to current device structure + struct comedi_subdevice *s Pointer to current subdevice structure + struct comedi_insn *insn Pointer to current comedi instruction + unsigned int *data Pointer to counter data + +Returns:int Nmuber of instructions executed + +============================================================================== +*/ static int icp_multi_insn_write_ctr(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, @@ -387,18 +639,44 @@ static int icp_multi_insn_write_ctr(struct comedi_device *dev, return 0; } +/* +============================================================================== + +Name: interrupt_service_icp_multi + +Description: + This function is the interrupt service routine for all + interrupts generated by the icp multi board. + +Parameters: + int irq + void *d Pointer to current device + +============================================================================== +*/ static irqreturn_t interrupt_service_icp_multi(int irq, void *d) { struct comedi_device *dev = d; - struct icp_multi_private *devpriv = dev->private; int int_no; +#ifdef ICP_MULTI_EXTDEBUG + printk(KERN_DEBUG + "icp multi EDBG: BGN: interrupt_service_icp_multi(%d,...)\n", + irq); +#endif + /* Is this interrupt from our board? */ int_no = readw(devpriv->io_addr + ICP_MULTI_INT_STAT) & Status_IRQ; if (!int_no) /* No, exit */ return IRQ_NONE; +#ifdef ICP_MULTI_EXTDEBUG + printk(KERN_DEBUG + "icp multi EDBG: interrupt_service_icp_multi() ST: %4x\n", + readw(devpriv->io_addr + ICP_MULTI_INT_STAT)); +#endif + /* Determine which interrupt is active & handle it */ switch (int_no) { case ADC_READY: @@ -422,16 +700,44 @@ static irqreturn_t interrupt_service_icp_multi(int irq, void *d) } +#ifdef ICP_MULTI_EXTDEBUG + printk(KERN_DEBUG + "icp multi EDBG: END: interrupt_service_icp_multi(...)\n"); +#endif return IRQ_HANDLED; } #if 0 +/* +============================================================================== + +Name: check_channel_list + +Description: + This function checks if the channel list, provided by user + is built correctly + +Parameters: + struct comedi_device *dev Pointer to current service structure + struct comedi_subdevice *s Pointer to current subdevice structure + unsigned int *chanlist Pointer to packed channel list + unsigned int n_chan Number of channels to scan + +Returns:int 0 = failure + 1 = success + +============================================================================== +*/ static int check_channel_list(struct comedi_device *dev, struct comedi_subdevice *s, unsigned int *chanlist, unsigned int n_chan) { unsigned int i; +#ifdef ICP_MULTI_EXTDEBUG + printk(KERN_DEBUG + "icp multi EDBG: check_channel_list(...,%d)\n", n_chan); +#endif /* Check that we at least have one channel to check */ if (n_chan < 1) { comedi_error(dev, "range/channel list is empty!"); @@ -441,13 +747,13 @@ static int check_channel_list(struct comedi_device *dev, for (i = 0; i < n_chan; i++) { /* Check that channel number is < maximum */ if (CR_AREF(chanlist[i]) == AREF_DIFF) { - if (CR_CHAN(chanlist[i]) > (s->nchan / 2)) { + if (CR_CHAN(chanlist[i]) > this_board->n_aichand) { comedi_error(dev, "Incorrect differential ai ch-nr"); return 0; } } else { - if (CR_CHAN(chanlist[i]) > s->n_chan) { + if (CR_CHAN(chanlist[i]) > this_board->n_aichan) { comedi_error(dev, "Incorrect ai channel number"); return 0; @@ -458,189 +764,295 @@ static int check_channel_list(struct comedi_device *dev, } #endif +/* +============================================================================== + +Name: icp_multi_reset + +Description: + This function resets the icp multi device to a 'safe' state + +Parameters: + struct comedi_device *dev Pointer to current service structure + +Returns:int 0 = success + +============================================================================== +*/ static int icp_multi_reset(struct comedi_device *dev) { - struct icp_multi_private *devpriv = dev->private; unsigned int i; +#ifdef ICP_MULTI_EXTDEBUG + printk(KERN_DEBUG + "icp_multi EDBG: BGN: icp_multi_reset(...)\n"); +#endif /* Clear INT enables and requests */ writew(0, devpriv->io_addr + ICP_MULTI_INT_EN); writew(0x00ff, devpriv->io_addr + ICP_MULTI_INT_STAT); - /* Set DACs to 0..5V range and 0V output */ - for (i = 0; i < 4; i++) { - devpriv->DacCmdStatus &= 0xfcce; - - /* Set channel number */ - devpriv->DacCmdStatus |= (i << 8); + if (this_board->n_aochan) + /* Set DACs to 0..5V range and 0V output */ + for (i = 0; i < this_board->n_aochan; i++) { + devpriv->DacCmdStatus &= 0xfcce; - /* Output 0V */ - writew(0, devpriv->io_addr + ICP_MULTI_AO); + /* Set channel number */ + devpriv->DacCmdStatus |= (i << 8); - /* Set start conversion bit */ - devpriv->DacCmdStatus |= DAC_ST; + /* Output 0V */ + writew(0, devpriv->io_addr + ICP_MULTI_AO); - /* Output to command / status register */ - writew(devpriv->DacCmdStatus, - devpriv->io_addr + ICP_MULTI_DAC_CSR); + /* Set start conversion bit */ + devpriv->DacCmdStatus |= DAC_ST; - /* Delay to allow DAC time to recover */ - udelay(1); - } + /* Output to command / status register */ + writew(devpriv->DacCmdStatus, + devpriv->io_addr + ICP_MULTI_DAC_CSR); - /* Digital outputs to 0 */ + /* Delay to allow DAC time to recover */ + udelay(1); + } + /* Digital outputs to 0 */ writew(0, devpriv->io_addr + ICP_MULTI_DO); +#ifdef ICP_MULTI_EXTDEBUG + printk(KERN_DEBUG + "icp multi EDBG: END: icp_multi_reset(...)\n"); +#endif return 0; } -static int icp_multi_attach_pci(struct comedi_device *dev, - struct pci_dev *pcidev) +static int icp_multi_attach(struct comedi_device *dev, + struct comedi_devconfig *it) { - struct icp_multi_private *devpriv; struct comedi_subdevice *s; - resource_size_t iobase; - int ret; + int ret, subdev, n_subdevices; + unsigned int irq; + struct pcilst_struct *card = NULL; + resource_size_t io_addr[5], iobase; + unsigned char pci_bus, pci_slot, pci_func; - comedi_set_hw_dev(dev, &pcidev->dev); - dev->board_name = dev->driver->driver_name; + printk(KERN_WARNING + "icp_multi EDBG: BGN: icp_multi_attach(...)\n"); - ret = alloc_private(dev, sizeof(*devpriv)); + /* Allocate private data storage space */ + ret = alloc_private(dev, sizeof(struct icp_multi_private)); if (ret < 0) return ret; - devpriv = dev->private; - ret = comedi_pci_enable(pcidev, dev->board_name); - if (ret) - return ret; - iobase = pci_resource_start(pcidev, 2); - dev->iobase = iobase; + /* Initialise list of PCI cards in system, if not already done so */ + if (pci_list_builded++ == 0) { + pci_card_list_init(PCI_VENDOR_ID_ICP, +#ifdef ICP_MULTI_EXTDEBUG + 1 +#else + 0 +#endif + ); + } + + printk(KERN_WARNING + "Anne's comedi%d: icp_multi: board=%s", dev->minor, + this_board->name); + + card = select_and_alloc_pci_card(PCI_VENDOR_ID_ICP, + this_board->device_id, it->options[0], + it->options[1]); + + if (card == NULL) + return -EIO; + + devpriv->card = card; + + if ((pci_card_data(card, &pci_bus, &pci_slot, &pci_func, &io_addr[0], + &irq)) < 0) { + printk(KERN_WARNING " - Can't get configuration data!\n"); + return -EIO; + } + + iobase = io_addr[2]; + devpriv->phys_iobase = iobase; + + printk(KERN_WARNING + ", b:s:f=%d:%d:%d, io=0x%8llx \n", pci_bus, pci_slot, pci_func, + (unsigned long long)iobase); devpriv->io_addr = ioremap(iobase, ICP_MULTI_SIZE); - if (!devpriv->io_addr) + + if (devpriv->io_addr == NULL) { + printk(KERN_WARNING "ioremap failed.\n"); return -ENOMEM; + } +#ifdef ICP_MULTI_EXTDEBUG + printk(KERN_DEBUG + "0x%08llx mapped to %p, ", (unsigned long long)iobase, + devpriv->io_addr); +#endif - ret = comedi_alloc_subdevices(dev, 5); + dev->board_name = this_board->name; + + n_subdevices = 0; + if (this_board->n_aichan) + n_subdevices++; + if (this_board->n_aochan) + n_subdevices++; + if (this_board->n_dichan) + n_subdevices++; + if (this_board->n_dochan) + n_subdevices++; + if (this_board->n_ctrs) + n_subdevices++; + + ret = comedi_alloc_subdevices(dev, n_subdevices); if (ret) return ret; icp_multi_reset(dev); - if (pcidev->irq) { - ret = request_irq(pcidev->irq, interrupt_service_icp_multi, - IRQF_SHARED, dev->board_name, dev); - if (ret == 0) - dev->irq = pcidev->irq; + if (this_board->have_irq) { + if (irq) { + if (request_irq(irq, interrupt_service_icp_multi, + IRQF_SHARED, "Inova Icp Multi", dev)) { + printk(KERN_WARNING + "unable to allocate IRQ %u, DISABLING IT", + irq); + irq = 0; /* Can't use IRQ */ + } else + printk(KERN_WARNING ", irq=%u", irq); + } else + printk(KERN_WARNING ", IRQ disabled"); + } else + irq = 0; + + dev->irq = irq; + + printk(KERN_WARNING ".\n"); + + subdev = 0; + + if (this_board->n_aichan) { + s = dev->subdevices + subdev; + dev->read_subdev = s; + s->type = COMEDI_SUBD_AI; + s->subdev_flags = SDF_READABLE | SDF_COMMON | SDF_GROUND; + if (this_board->n_aichand) + s->subdev_flags |= SDF_DIFF; + s->n_chan = this_board->n_aichan; + s->maxdata = this_board->ai_maxdata; + s->len_chanlist = this_board->n_aichan; + s->range_table = this_board->rangelist_ai; + s->insn_read = icp_multi_insn_read_ai; + subdev++; } - s = &dev->subdevices[0]; - dev->read_subdev = s; - s->type = COMEDI_SUBD_AI; - s->subdev_flags = SDF_READABLE | SDF_COMMON | SDF_GROUND | SDF_DIFF; - s->n_chan = 16; - s->maxdata = 0x0fff; - s->len_chanlist = 16; - s->range_table = &range_analog; - s->insn_read = icp_multi_insn_read_ai; - - s = &dev->subdevices[1]; - s->type = COMEDI_SUBD_AO; - s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_COMMON; - s->n_chan = 4; - s->maxdata = 0x0fff; - s->len_chanlist = 4; - s->range_table = &range_analog; - s->insn_write = icp_multi_insn_write_ao; - s->insn_read = icp_multi_insn_read_ao; - - s = &dev->subdevices[2]; - s->type = COMEDI_SUBD_DI; - s->subdev_flags = SDF_READABLE; - s->n_chan = 16; - s->maxdata = 1; - s->len_chanlist = 16; - s->range_table = &range_digital; - s->io_bits = 0; - s->insn_bits = icp_multi_insn_bits_di; - - s = &dev->subdevices[3]; - s->type = COMEDI_SUBD_DO; - s->subdev_flags = SDF_WRITABLE | SDF_READABLE; - s->n_chan = 8; - s->maxdata = 1; - s->len_chanlist = 8; - s->range_table = &range_digital; - s->io_bits = 0xff; - s->state = 0; - s->insn_bits = icp_multi_insn_bits_do; - - s = &dev->subdevices[4]; - s->type = COMEDI_SUBD_COUNTER; - s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_COMMON; - s->n_chan = 4; - s->maxdata = 0xffff; - s->len_chanlist = 4; - s->state = 0; - s->insn_read = icp_multi_insn_read_ctr; - s->insn_write = icp_multi_insn_write_ctr; + if (this_board->n_aochan) { + s = dev->subdevices + subdev; + s->type = COMEDI_SUBD_AO; + s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_COMMON; + s->n_chan = this_board->n_aochan; + s->maxdata = this_board->ao_maxdata; + s->len_chanlist = this_board->n_aochan; + s->range_table = this_board->rangelist_ao; + s->insn_write = icp_multi_insn_write_ao; + s->insn_read = icp_multi_insn_read_ao; + subdev++; + } + + if (this_board->n_dichan) { + s = dev->subdevices + subdev; + s->type = COMEDI_SUBD_DI; + s->subdev_flags = SDF_READABLE; + s->n_chan = this_board->n_dichan; + s->maxdata = 1; + s->len_chanlist = this_board->n_dichan; + s->range_table = &range_digital; + s->io_bits = 0; + s->insn_bits = icp_multi_insn_bits_di; + subdev++; + } + + if (this_board->n_dochan) { + s = dev->subdevices + subdev; + s->type = COMEDI_SUBD_DO; + s->subdev_flags = SDF_WRITABLE | SDF_READABLE; + s->n_chan = this_board->n_dochan; + s->maxdata = 1; + s->len_chanlist = this_board->n_dochan; + s->range_table = &range_digital; + s->io_bits = (1 << this_board->n_dochan) - 1; + s->state = 0; + s->insn_bits = icp_multi_insn_bits_do; + subdev++; + } + + if (this_board->n_ctrs) { + s = dev->subdevices + subdev; + s->type = COMEDI_SUBD_COUNTER; + s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_COMMON; + s->n_chan = this_board->n_ctrs; + s->maxdata = 0xffff; + s->len_chanlist = this_board->n_ctrs; + s->state = 0; + s->insn_read = icp_multi_insn_read_ctr; + s->insn_write = icp_multi_insn_write_ctr; + subdev++; + } devpriv->valid = 1; - dev_info(dev->class_dev, "%s attached, irq %sabled\n", - dev->board_name, dev->irq ? "en" : "dis"); +#ifdef ICP_MULTI_EXTDEBUG + printk(KERN_DEBUG "icp multi EDBG: END: icp_multi_attach(...)\n"); +#endif return 0; } static void icp_multi_detach(struct comedi_device *dev) { - struct pci_dev *pcidev = comedi_to_pci_dev(dev); - struct icp_multi_private *devpriv = dev->private; - - if (devpriv) + if (dev->private) if (devpriv->valid) icp_multi_reset(dev); if (dev->irq) free_irq(dev->irq, dev); - if (devpriv && devpriv->io_addr) + if (dev->private && devpriv->io_addr) iounmap(devpriv->io_addr); - if (pcidev) { - if (dev->iobase) - comedi_pci_disable(pcidev); - } + if (dev->private && devpriv->card) + pci_card_free(devpriv->card); + if (--pci_list_builded == 0) + pci_card_list_cleanup(PCI_VENDOR_ID_ICP); } +static const struct boardtype boardtypes[] = { + { + .name = "icp_multi", + .device_id = DEVICE_ID, + .iorange = IORANGE_ICP_MULTI, + .have_irq = 1, + .cardtype = TYPE_ICP_MULTI, + .n_aichan = 16, + .n_aichand = 8, + .n_aochan = 4, + .n_dichan = 16, + .n_dochan = 8, + .n_ctrs = 4, + .ai_maxdata = 0x0fff, + .ao_maxdata = 0x0fff, + .rangelist_ai = &range_analog, + .rangecode = range_codes_analog, + .rangelist_ao = &range_analog, + }, +}; + static struct comedi_driver icp_multi_driver = { .driver_name = "icp_multi", .module = THIS_MODULE, - .attach_pci = icp_multi_attach_pci, + .attach = icp_multi_attach, .detach = icp_multi_detach, + .num_names = ARRAY_SIZE(boardtypes), + .board_name = &boardtypes[0].name, + .offset = sizeof(struct boardtype), }; - -static int __devinit icp_multi_pci_probe(struct pci_dev *dev, - const struct pci_device_id *ent) -{ - return comedi_pci_auto_config(dev, &icp_multi_driver); -} - -static void __devexit icp_multi_pci_remove(struct pci_dev *dev) -{ - comedi_pci_auto_unconfig(dev); -} - -static DEFINE_PCI_DEVICE_TABLE(icp_multi_pci_table) = { - { PCI_DEVICE(PCI_VENDOR_ID_ICP, PCI_DEVICE_ID_ICP_MULTI) }, - { 0 } -}; -MODULE_DEVICE_TABLE(pci, icp_multi_pci_table); - -static struct pci_driver icp_multi_pci_driver = { - .name = "icp_multi", - .id_table = icp_multi_pci_table, - .probe = icp_multi_pci_probe, - .remove = __devexit_p(icp_multi_pci_remove), -}; -module_comedi_pci_driver(icp_multi_driver, icp_multi_pci_driver); +module_comedi_driver(icp_multi_driver); MODULE_AUTHOR("Comedi http://www.comedi.org"); MODULE_DESCRIPTION("Comedi low-level driver"); diff --git a/trunk/drivers/staging/comedi/drivers/icp_multi.h b/trunk/drivers/staging/comedi/drivers/icp_multi.h new file mode 100644 index 000000000000..dbf9908cfde6 --- /dev/null +++ b/trunk/drivers/staging/comedi/drivers/icp_multi.h @@ -0,0 +1,297 @@ +/* + comedi/drivers/icp_multi.h + + Stuff for ICP Multi + + Author: Anne Smorthit + +*/ + +#ifndef _ICP_MULTI_H_ +#define _ICP_MULTI_H_ + +#include "../comedidev.h" + +/****************************************************************************/ + +struct pcilst_struct { + struct pcilst_struct *next; + int used; + struct pci_dev *pcidev; + unsigned short vendor; + unsigned short device; + unsigned char pci_bus; + unsigned char pci_slot; + unsigned char pci_func; + resource_size_t io_addr[5]; + unsigned int irq; +}; + +struct pcilst_struct *inova_devices; +/* ptr to root list of all Inova devices */ + +/****************************************************************************/ + +static void pci_card_list_init(unsigned short pci_vendor, char display); +static void pci_card_list_cleanup(unsigned short pci_vendor); +static struct pcilst_struct *find_free_pci_card_by_device(unsigned short + vendor_id, + unsigned short + device_id); +static int find_free_pci_card_by_position(unsigned short vendor_id, + unsigned short device_id, + unsigned short pci_bus, + unsigned short pci_slot, + struct pcilst_struct **card); +static struct pcilst_struct *select_and_alloc_pci_card(unsigned short vendor_id, + unsigned short device_id, + unsigned short pci_bus, + unsigned short pci_slot); + +static int pci_card_alloc(struct pcilst_struct *amcc); +static int pci_card_free(struct pcilst_struct *amcc); +static void pci_card_list_display(void); +static int pci_card_data(struct pcilst_struct *amcc, + unsigned char *pci_bus, unsigned char *pci_slot, + unsigned char *pci_func, resource_size_t * io_addr, + unsigned int *irq); + +/****************************************************************************/ + +/* build list of Inova cards in this system */ +static void pci_card_list_init(unsigned short pci_vendor, char display) +{ + struct pci_dev *pcidev = NULL; + struct pcilst_struct *inova, *last; + int i; + + inova_devices = NULL; + last = NULL; + + for_each_pci_dev(pcidev) { + if (pcidev->vendor == pci_vendor) { + inova = kzalloc(sizeof(*inova), GFP_KERNEL); + if (!inova) { + printk + ("icp_multi: pci_card_list_init: allocation failed\n"); + pci_dev_put(pcidev); + break; + } + + inova->pcidev = pci_dev_get(pcidev); + if (last) { + last->next = inova; + } else { + inova_devices = inova; + } + last = inova; + + inova->vendor = pcidev->vendor; + inova->device = pcidev->device; + inova->pci_bus = pcidev->bus->number; + inova->pci_slot = PCI_SLOT(pcidev->devfn); + inova->pci_func = PCI_FUNC(pcidev->devfn); + /* Note: resources may be invalid if PCI device + * not enabled, but they are corrected in + * pci_card_alloc. */ + for (i = 0; i < 5; i++) + inova->io_addr[i] = + pci_resource_start(pcidev, i); + inova->irq = pcidev->irq; + } + } + + if (display) + pci_card_list_display(); +} + +/****************************************************************************/ +/* free up list of amcc cards in this system */ +static void pci_card_list_cleanup(unsigned short pci_vendor) +{ + struct pcilst_struct *inova, *next; + + for (inova = inova_devices; inova; inova = next) { + next = inova->next; + pci_dev_put(inova->pcidev); + kfree(inova); + } + + inova_devices = NULL; +} + +/****************************************************************************/ +/* find first unused card with this device_id */ +static struct pcilst_struct *find_free_pci_card_by_device(unsigned short + vendor_id, + unsigned short + device_id) +{ + struct pcilst_struct *inova, *next; + + for (inova = inova_devices; inova; inova = next) { + next = inova->next; + if ((!inova->used) && (inova->device == device_id) + && (inova->vendor == vendor_id)) + return inova; + + } + + return NULL; +} + +/****************************************************************************/ +/* find card on requested position */ +static int find_free_pci_card_by_position(unsigned short vendor_id, + unsigned short device_id, + unsigned short pci_bus, + unsigned short pci_slot, + struct pcilst_struct **card) +{ + struct pcilst_struct *inova, *next; + + *card = NULL; + for (inova = inova_devices; inova; inova = next) { + next = inova->next; + if ((inova->vendor == vendor_id) && (inova->device == device_id) + && (inova->pci_bus == pci_bus) + && (inova->pci_slot == pci_slot)) { + if (!(inova->used)) { + *card = inova; + return 0; /* ok, card is found */ + } else { + return 2; /* card exist but is used */ + } + } + } + + return 1; /* no card found */ +} + +/****************************************************************************/ +/* mark card as used */ +static int pci_card_alloc(struct pcilst_struct *inova) +{ + int i; + + if (!inova) { + printk(" - BUG!! inova is NULL!\n"); + return -1; + } + + if (inova->used) + return 1; + if (comedi_pci_enable(inova->pcidev, "icp_multi")) { + printk(" - Can't enable PCI device and request regions!\n"); + return -1; + } + /* Resources will be accurate now. */ + for (i = 0; i < 5; i++) + inova->io_addr[i] = pci_resource_start(inova->pcidev, i); + inova->irq = inova->pcidev->irq; + inova->used = 1; + return 0; +} + +/****************************************************************************/ +/* mark card as free */ +static int pci_card_free(struct pcilst_struct *inova) +{ + if (!inova) + return -1; + + if (!inova->used) + return 1; + inova->used = 0; + comedi_pci_disable(inova->pcidev); + return 0; +} + +/****************************************************************************/ +/* display list of found cards */ +static void pci_card_list_display(void) +{ + struct pcilst_struct *inova, *next; + + printk("Anne's List of pci cards\n"); + printk("bus:slot:func vendor device io_inova io_daq irq used\n"); + + for (inova = inova_devices; inova; inova = next) { + next = inova->next; + printk + ("%2d %2d %2d 0x%4x 0x%4x 0x%8llx 0x%8llx %2u %2d\n", + inova->pci_bus, inova->pci_slot, inova->pci_func, + inova->vendor, inova->device, + (unsigned long long)inova->io_addr[0], + (unsigned long long)inova->io_addr[2], inova->irq, + inova->used); + + } +} + +/****************************************************************************/ +/* return all card information for driver */ +static int pci_card_data(struct pcilst_struct *inova, + unsigned char *pci_bus, unsigned char *pci_slot, + unsigned char *pci_func, resource_size_t * io_addr, + unsigned int *irq) +{ + int i; + + if (!inova) + return -1; + *pci_bus = inova->pci_bus; + *pci_slot = inova->pci_slot; + *pci_func = inova->pci_func; + for (i = 0; i < 5; i++) + io_addr[i] = inova->io_addr[i]; + *irq = inova->irq; + return 0; +} + +/****************************************************************************/ +/* select and alloc card */ +static struct pcilst_struct *select_and_alloc_pci_card(unsigned short vendor_id, + unsigned short device_id, + unsigned short pci_bus, + unsigned short pci_slot) +{ + struct pcilst_struct *card; + int err; + + if ((pci_bus < 1) & (pci_slot < 1)) { /* use autodetection */ + + card = find_free_pci_card_by_device(vendor_id, device_id); + if (card == NULL) { + printk(" - Unused card not found in system!\n"); + return NULL; + } + } else { + switch (find_free_pci_card_by_position(vendor_id, device_id, + pci_bus, pci_slot, + &card)) { + case 1: + printk + (" - Card not found on requested position b:s %d:%d!\n", + pci_bus, pci_slot); + return NULL; + case 2: + printk + (" - Card on requested position is used b:s %d:%d!\n", + pci_bus, pci_slot); + return NULL; + } + } + + err = pci_card_alloc(card); + if (err != 0) { + if (err > 0) + printk(" - Can't allocate card!\n"); + /* else: error already printed. */ + return NULL; + } + + return card; +} + +#endif diff --git a/trunk/drivers/staging/comedi/drivers/ii_pci20kc.c b/trunk/drivers/staging/comedi/drivers/ii_pci20kc.c index 65ff1c9b973c..0f9cfe662b9a 100644 --- a/trunk/drivers/staging/comedi/drivers/ii_pci20kc.c +++ b/trunk/drivers/staging/comedi/drivers/ii_pci20kc.c @@ -224,7 +224,7 @@ static int pci20xxx_attach(struct comedi_device *dev, dev->minor, devpriv->ioaddr); for (i = 0; i < PCI20000_MODULES; i++) { - s = &dev->subdevices[i]; + s = dev->subdevices + i; id = readb(devpriv->ioaddr + (i + 1) * PCI20000_OFFSET); s->private = devpriv->subdev_private + i; sdp = s->private; @@ -259,7 +259,7 @@ static int pci20xxx_attach(struct comedi_device *dev, } /* initialize struct pci20xxx_private */ - pci20xxx_dio_init(dev, &dev->subdevices[PCI20000_MODULES]); + pci20xxx_dio_init(dev, dev->subdevices + PCI20000_MODULES); return 1; } diff --git a/trunk/drivers/staging/comedi/drivers/jr3_pci.c b/trunk/drivers/staging/comedi/drivers/jr3_pci.c index 4a108ea8a9aa..93f94cd7bae2 100644 --- a/trunk/drivers/staging/comedi/drivers/jr3_pci.c +++ b/trunk/drivers/staging/comedi/drivers/jr3_pci.c @@ -362,11 +362,10 @@ static int jr3_pci_open(struct comedi_device *dev) return 0; } -static int read_idm_word(const u8 *data, size_t size, int *pos, - unsigned int *val) +int read_idm_word(const u8 * data, size_t size, int *pos, unsigned int *val) { int result = 0; - if (pos && val) { + if (pos != 0 && val != 0) { /* Skip over non hex */ for (; *pos < size && !isxdigit(data[*pos]); (*pos)++) { } @@ -876,7 +875,7 @@ static int jr3_pci_attach(struct comedi_device *dev, p->maxdata_list[56] = 0xffff; p->maxdata_list[57] = 0xffff; /* Channel specific range and maxdata */ - dev->subdevices[i].range_table = NULL; + dev->subdevices[i].range_table = 0; dev->subdevices[i].range_table_list = p->range_table_list; dev->subdevices[i].maxdata = 0; @@ -885,7 +884,7 @@ static int jr3_pci_attach(struct comedi_device *dev, } /* Reset DSP card */ - writel(0, &devpriv->iobase->channel[0].reset); + devpriv->iobase->channel[0].reset = 0; result = comedi_load_firmware(dev, "jr3pci.idm", jr3_download_firmware); dev_dbg(dev->class_dev, "Firmare load %d\n", result); diff --git a/trunk/drivers/staging/comedi/drivers/jr3_pci.h b/trunk/drivers/staging/comedi/drivers/jr3_pci.h index 9c42653d8f18..a1469611d84e 100644 --- a/trunk/drivers/staging/comedi/drivers/jr3_pci.h +++ b/trunk/drivers/staging/comedi/drivers/jr3_pci.h @@ -97,7 +97,7 @@ enum { mz = 0x0020, changeV2 = 0x0040, changeV1 = 0x0080 -}; +} vect_bits_t; /* WARNING_BITS */ /* The warning_bits structure shows the bit pattern for the warning @@ -116,7 +116,7 @@ enum { mx_near_sat = 0x0008, my_near_sat = 0x0010, mz_near_sat = 0x0020 -}; +} warning_bits_t; /* ERROR_BITS */ /* XX_SAT */ diff --git a/trunk/drivers/staging/comedi/drivers/ke_counter.c b/trunk/drivers/staging/comedi/drivers/ke_counter.c index e867b720f666..d4e9292483a0 100644 --- a/trunk/drivers/staging/comedi/drivers/ke_counter.c +++ b/trunk/drivers/staging/comedi/drivers/ke_counter.c @@ -28,7 +28,11 @@ Author: Michael Hillmann Updated: Mon, 14 Apr 2008 15:42:42 +0100 Status: tested -Configuration Options: not applicable, uses PCI auto config +Configuration Options: + [0] - PCI bus of device (optional) + [1] - PCI slot of device (optional) + If bus/slot is not specified, the first supported + PCI device found will be used. This driver is a simple driver to read the counter values from Kolter Electronic PCI Counter Card. @@ -107,53 +111,82 @@ static int cnt_rinsn(struct comedi_device *dev, return 1; } -static const void *cnt_find_boardinfo(struct comedi_device *dev, - struct pci_dev *pcidev) +static struct pci_dev *cnt_find_pci_dev(struct comedi_device *dev, + struct comedi_devconfig *it) { const struct cnt_board_struct *board; + struct pci_dev *pcidev = NULL; + int bus = it->options[0]; + int slot = it->options[1]; int i; - for (i = 0; i < ARRAY_SIZE(cnt_boards); i++) { - board = &cnt_boards[i]; - if (board->device_id == pcidev->device) - return board; + /* Probe the device to determine what device in the series it is. */ + for_each_pci_dev(pcidev) { + if (bus || slot) { + if (pcidev->bus->number != bus || + PCI_SLOT(pcidev->devfn) != slot) + continue; + } + if (pcidev->vendor != PCI_VENDOR_ID_KOLTER) + continue; + + for (i = 0; i < ARRAY_SIZE(cnt_boards); i++) { + board = &cnt_boards[i]; + if (board->device_id != pcidev->device) + continue; + + dev->board_ptr = board; + return pcidev; + } } + dev_err(dev->class_dev, + "No supported board found! (req. bus %d, slot %d)\n", + bus, slot); return NULL; } -static int cnt_attach_pci(struct comedi_device *dev, - struct pci_dev *pcidev) +static int cnt_attach(struct comedi_device *dev, struct comedi_devconfig *it) { const struct cnt_board_struct *board; - struct comedi_subdevice *s; - int ret; - + struct pci_dev *pcidev; + struct comedi_subdevice *subdevice; + unsigned long io_base; + int error; + + pcidev = cnt_find_pci_dev(dev, it); + if (!pcidev) + return -EIO; comedi_set_hw_dev(dev, &pcidev->dev); + board = comedi_board(dev); - board = cnt_find_boardinfo(dev, pcidev); - if (!board) - return -ENODEV; - dev->board_ptr = board; dev->board_name = board->name; - ret = comedi_pci_enable(pcidev, dev->board_name); - if (ret) - return ret; - dev->iobase = pci_resource_start(pcidev, 0); + /* enable PCI device and request regions */ + error = comedi_pci_enable(pcidev, CNT_DRIVER_NAME); + if (error < 0) { + printk(KERN_WARNING "comedi%d: " + "failed to enable PCI device and request regions!\n", + dev->minor); + return error; + } + + /* read register base address [PCI_BASE_ADDRESS #0] */ + io_base = pci_resource_start(pcidev, 0); + dev->iobase = io_base; - ret = comedi_alloc_subdevices(dev, 1); - if (ret) - return ret; + error = comedi_alloc_subdevices(dev, 1); + if (error) + return error; - s = &dev->subdevices[0]; - dev->read_subdev = s; + subdevice = dev->subdevices + 0; + dev->read_subdev = subdevice; - s->type = COMEDI_SUBD_COUNTER; - s->subdev_flags = SDF_READABLE /* | SDF_COMMON */ ; - s->n_chan = board->cnt_channel_nbr; - s->maxdata = (1 << board->cnt_bits) - 1; - s->insn_read = cnt_rinsn; - s->insn_write = cnt_winsn; + subdevice->type = COMEDI_SUBD_COUNTER; + subdevice->subdev_flags = SDF_READABLE /* | SDF_COMMON */ ; + subdevice->n_chan = board->cnt_channel_nbr; + subdevice->maxdata = (1 << board->cnt_bits) - 1; + subdevice->insn_read = cnt_rinsn; + subdevice->insn_write = cnt_winsn; /* select 20MHz clock */ outb(3, dev->iobase + 248); @@ -163,9 +196,8 @@ static int cnt_attach_pci(struct comedi_device *dev, outb(0, dev->iobase + 0x20); outb(0, dev->iobase + 0x40); - dev_info(dev->class_dev, "%s: %s attached\n", - dev->driver->driver_name, dev->board_name); - + printk(KERN_INFO "comedi%d: " CNT_DRIVER_NAME " attached.\n", + dev->minor); return 0; } @@ -176,13 +208,14 @@ static void cnt_detach(struct comedi_device *dev) if (pcidev) { if (dev->iobase) comedi_pci_disable(pcidev); + pci_dev_put(pcidev); } } static struct comedi_driver ke_counter_driver = { .driver_name = "ke_counter", .module = THIS_MODULE, - .attach_pci = cnt_attach_pci, + .attach = cnt_attach, .detach = cnt_detach, }; diff --git a/trunk/drivers/staging/comedi/drivers/me4000.c b/trunk/drivers/staging/comedi/drivers/me4000.c index 22db35d091f8..9a8258e6fa45 100644 --- a/trunk/drivers/staging/comedi/drivers/me4000.c +++ b/trunk/drivers/staging/comedi/drivers/me4000.c @@ -35,7 +35,13 @@ Status: broken (no support for loading firmware) - Digital I/O - Counter -Configuration Options: not applicable, uses PCI auto config +Configuration Options: + + [0] - PCI bus number (optional) + [1] - PCI slot number (optional) + + If bus/slot is not specified, the first available PCI + device will be used. The firmware required by these boards is available in the comedi_nonfree_firmware tarball available from @@ -52,307 +58,52 @@ broken. #include #include -#include "comedi_fc.h" -#include "8253.h" - +#include "me4000.h" #if 0 /* file removed due to GPL incompatibility */ #include "me4000_fw.h" #endif -#define PCI_VENDOR_ID_MEILHAUS 0x1402 - -#define PCI_DEVICE_ID_MEILHAUS_ME4650 0x4650 -#define PCI_DEVICE_ID_MEILHAUS_ME4660 0x4660 -#define PCI_DEVICE_ID_MEILHAUS_ME4660I 0x4661 -#define PCI_DEVICE_ID_MEILHAUS_ME4660S 0x4662 -#define PCI_DEVICE_ID_MEILHAUS_ME4660IS 0x4663 -#define PCI_DEVICE_ID_MEILHAUS_ME4670 0x4670 -#define PCI_DEVICE_ID_MEILHAUS_ME4670I 0x4671 -#define PCI_DEVICE_ID_MEILHAUS_ME4670S 0x4672 -#define PCI_DEVICE_ID_MEILHAUS_ME4670IS 0x4673 -#define PCI_DEVICE_ID_MEILHAUS_ME4680 0x4680 -#define PCI_DEVICE_ID_MEILHAUS_ME4680I 0x4681 -#define PCI_DEVICE_ID_MEILHAUS_ME4680S 0x4682 -#define PCI_DEVICE_ID_MEILHAUS_ME4680IS 0x4683 +static const struct me4000_board me4000_boards[] = { + {"ME-4650", 0x4650, {0, 0}, {16, 0, 0, 0}, {4}, {0} }, -/* - * ME4000 Register map and bit defines - */ -#define ME4000_AO_CHAN(x) ((x) * 0x18) - -#define ME4000_AO_CTRL_REG(x) (0x00 + ME4000_AO_CHAN(x)) -#define ME4000_AO_CTRL_BIT_MODE_0 (1 << 0) -#define ME4000_AO_CTRL_BIT_MODE_1 (1 << 1) -#define ME4000_AO_CTRL_MASK_MODE (3 << 0) -#define ME4000_AO_CTRL_BIT_STOP (1 << 2) -#define ME4000_AO_CTRL_BIT_ENABLE_FIFO (1 << 3) -#define ME4000_AO_CTRL_BIT_ENABLE_EX_TRIG (1 << 4) -#define ME4000_AO_CTRL_BIT_EX_TRIG_EDGE (1 << 5) -#define ME4000_AO_CTRL_BIT_IMMEDIATE_STOP (1 << 7) -#define ME4000_AO_CTRL_BIT_ENABLE_DO (1 << 8) -#define ME4000_AO_CTRL_BIT_ENABLE_IRQ (1 << 9) -#define ME4000_AO_CTRL_BIT_RESET_IRQ (1 << 10) -#define ME4000_AO_STATUS_REG(x) (0x04 + ME4000_AO_CHAN(x)) -#define ME4000_AO_STATUS_BIT_FSM (1 << 0) -#define ME4000_AO_STATUS_BIT_FF (1 << 1) -#define ME4000_AO_STATUS_BIT_HF (1 << 2) -#define ME4000_AO_STATUS_BIT_EF (1 << 3) -#define ME4000_AO_FIFO_REG(x) (0x08 + ME4000_AO_CHAN(x)) -#define ME4000_AO_SINGLE_REG(x) (0x0c + ME4000_AO_CHAN(x)) -#define ME4000_AO_TIMER_REG(x) (0x10 + ME4000_AO_CHAN(x)) -#define ME4000_AI_CTRL_REG 0x74 -#define ME4000_AI_STATUS_REG 0x74 -#define ME4000_AI_CTRL_BIT_MODE_0 (1 << 0) -#define ME4000_AI_CTRL_BIT_MODE_1 (1 << 1) -#define ME4000_AI_CTRL_BIT_MODE_2 (1 << 2) -#define ME4000_AI_CTRL_BIT_SAMPLE_HOLD (1 << 3) -#define ME4000_AI_CTRL_BIT_IMMEDIATE_STOP (1 << 4) -#define ME4000_AI_CTRL_BIT_STOP (1 << 5) -#define ME4000_AI_CTRL_BIT_CHANNEL_FIFO (1 << 6) -#define ME4000_AI_CTRL_BIT_DATA_FIFO (1 << 7) -#define ME4000_AI_CTRL_BIT_FULLSCALE (1 << 8) -#define ME4000_AI_CTRL_BIT_OFFSET (1 << 9) -#define ME4000_AI_CTRL_BIT_EX_TRIG_ANALOG (1 << 10) -#define ME4000_AI_CTRL_BIT_EX_TRIG (1 << 11) -#define ME4000_AI_CTRL_BIT_EX_TRIG_FALLING (1 << 12) -#define ME4000_AI_CTRL_BIT_EX_IRQ (1 << 13) -#define ME4000_AI_CTRL_BIT_EX_IRQ_RESET (1 << 14) -#define ME4000_AI_CTRL_BIT_LE_IRQ (1 << 15) -#define ME4000_AI_CTRL_BIT_LE_IRQ_RESET (1 << 16) -#define ME4000_AI_CTRL_BIT_HF_IRQ (1 << 17) -#define ME4000_AI_CTRL_BIT_HF_IRQ_RESET (1 << 18) -#define ME4000_AI_CTRL_BIT_SC_IRQ (1 << 19) -#define ME4000_AI_CTRL_BIT_SC_IRQ_RESET (1 << 20) -#define ME4000_AI_CTRL_BIT_SC_RELOAD (1 << 21) -#define ME4000_AI_STATUS_BIT_EF_CHANNEL (1 << 22) -#define ME4000_AI_STATUS_BIT_HF_CHANNEL (1 << 23) -#define ME4000_AI_STATUS_BIT_FF_CHANNEL (1 << 24) -#define ME4000_AI_STATUS_BIT_EF_DATA (1 << 25) -#define ME4000_AI_STATUS_BIT_HF_DATA (1 << 26) -#define ME4000_AI_STATUS_BIT_FF_DATA (1 << 27) -#define ME4000_AI_STATUS_BIT_LE (1 << 28) -#define ME4000_AI_STATUS_BIT_FSM (1 << 29) -#define ME4000_AI_CTRL_BIT_EX_TRIG_BOTH (1 << 31) -#define ME4000_AI_CHANNEL_LIST_REG 0x78 -#define ME4000_AI_LIST_INPUT_SINGLE_ENDED (0 << 5) -#define ME4000_AI_LIST_INPUT_DIFFERENTIAL (1 << 5) -#define ME4000_AI_LIST_RANGE_BIPOLAR_10 (0 << 6) -#define ME4000_AI_LIST_RANGE_BIPOLAR_2_5 (1 << 6) -#define ME4000_AI_LIST_RANGE_UNIPOLAR_10 (2 << 6) -#define ME4000_AI_LIST_RANGE_UNIPOLAR_2_5 (3 << 6) -#define ME4000_AI_LIST_LAST_ENTRY (1 << 8) -#define ME4000_AI_DATA_REG 0x7c -#define ME4000_AI_CHAN_TIMER_REG 0x80 -#define ME4000_AI_CHAN_PRE_TIMER_REG 0x84 -#define ME4000_AI_SCAN_TIMER_LOW_REG 0x88 -#define ME4000_AI_SCAN_TIMER_HIGH_REG 0x8c -#define ME4000_AI_SCAN_PRE_TIMER_LOW_REG 0x90 -#define ME4000_AI_SCAN_PRE_TIMER_HIGH_REG 0x94 -#define ME4000_AI_START_REG 0x98 -#define ME4000_IRQ_STATUS_REG 0x9c -#define ME4000_IRQ_STATUS_BIT_EX (1 << 0) -#define ME4000_IRQ_STATUS_BIT_LE (1 << 1) -#define ME4000_IRQ_STATUS_BIT_AI_HF (1 << 2) -#define ME4000_IRQ_STATUS_BIT_AO_0_HF (1 << 3) -#define ME4000_IRQ_STATUS_BIT_AO_1_HF (1 << 4) -#define ME4000_IRQ_STATUS_BIT_AO_2_HF (1 << 5) -#define ME4000_IRQ_STATUS_BIT_AO_3_HF (1 << 6) -#define ME4000_IRQ_STATUS_BIT_SC (1 << 7) -#define ME4000_DIO_PORT_0_REG 0xa0 -#define ME4000_DIO_PORT_1_REG 0xa4 -#define ME4000_DIO_PORT_2_REG 0xa8 -#define ME4000_DIO_PORT_3_REG 0xac -#define ME4000_DIO_DIR_REG 0xb0 -#define ME4000_AO_LOADSETREG_XX 0xb4 -#define ME4000_DIO_CTRL_REG 0xb8 -#define ME4000_DIO_CTRL_BIT_MODE_0 (1 << 0) -#define ME4000_DIO_CTRL_BIT_MODE_1 (1 << 1) -#define ME4000_DIO_CTRL_BIT_MODE_2 (1 << 2) -#define ME4000_DIO_CTRL_BIT_MODE_3 (1 << 3) -#define ME4000_DIO_CTRL_BIT_MODE_4 (1 << 4) -#define ME4000_DIO_CTRL_BIT_MODE_5 (1 << 5) -#define ME4000_DIO_CTRL_BIT_MODE_6 (1 << 6) -#define ME4000_DIO_CTRL_BIT_MODE_7 (1 << 7) -#define ME4000_DIO_CTRL_BIT_FUNCTION_0 (1 << 8) -#define ME4000_DIO_CTRL_BIT_FUNCTION_1 (1 << 9) -#define ME4000_DIO_CTRL_BIT_FIFO_HIGH_0 (1 << 10) -#define ME4000_DIO_CTRL_BIT_FIFO_HIGH_1 (1 << 11) -#define ME4000_DIO_CTRL_BIT_FIFO_HIGH_2 (1 << 12) -#define ME4000_DIO_CTRL_BIT_FIFO_HIGH_3 (1 << 13) -#define ME4000_AO_DEMUX_ADJUST_REG 0xbc -#define ME4000_AO_DEMUX_ADJUST_VALUE 0x4c -#define ME4000_AI_SAMPLE_COUNTER_REG 0xc0 + {"ME-4660", 0x4660, {0, 0}, {32, 0, 16, 0}, {4}, {3} }, + {"ME-4660i", 0x4661, {0, 0}, {32, 0, 16, 0}, {4}, {3} }, + {"ME-4660s", 0x4662, {0, 0}, {32, 8, 16, 0}, {4}, {3} }, + {"ME-4660is", 0x4663, {0, 0}, {32, 8, 16, 0}, {4}, {3} }, -/* - * PLX Register map and bit defines - */ -#define PLX_INTCSR 0x4c -#define PLX_INTCSR_LOCAL_INT1_EN (1 << 0) -#define PLX_INTCSR_LOCAL_INT1_POL (1 << 1) -#define PLX_INTCSR_LOCAL_INT1_STATE (1 << 2) -#define PLX_INTCSR_LOCAL_INT2_EN (1 << 3) -#define PLX_INTCSR_LOCAL_INT2_POL (1 << 4) -#define PLX_INTCSR_LOCAL_INT2_STATE (1 << 5) -#define PLX_INTCSR_PCI_INT_EN (1 << 6) -#define PLX_INTCSR_SOFT_INT (1 << 7) -#define PLX_ICR 0x50 -#define PLX_ICR_BIT_EEPROM_CLOCK_SET (1 << 24) -#define PLX_ICR_BIT_EEPROM_CHIP_SELECT (1 << 25) -#define PLX_ICR_BIT_EEPROM_WRITE (1 << 26) -#define PLX_ICR_BIT_EEPROM_READ (1 << 27) -#define PLX_ICR_BIT_EEPROM_VALID (1 << 28) -#define PLX_ICR_MASK_EEPROM (0x1f << 24) - -#define EEPROM_DELAY 1 - -#define ME4000_AI_FIFO_COUNT 2048 - -#define ME4000_AI_MIN_TICKS 66 -#define ME4000_AI_MIN_SAMPLE_TIME 2000 -#define ME4000_AI_BASE_FREQUENCY (unsigned int) 33E6 - -#define ME4000_AI_CHANNEL_LIST_COUNT 1024 - -struct me4000_info { - unsigned long plx_regbase; - unsigned long timer_regbase; - - unsigned int ao_readback[4]; -}; + {"ME-4670", 0x4670, {4, 0}, {32, 0, 16, 1}, {4}, {3} }, + {"ME-4670i", 0x4671, {4, 0}, {32, 0, 16, 1}, {4}, {3} }, + {"ME-4670s", 0x4672, {4, 0}, {32, 8, 16, 1}, {4}, {3} }, + {"ME-4670is", 0x4673, {4, 0}, {32, 8, 16, 1}, {4}, {3} }, -struct me4000_board { - const char *name; - unsigned short device_id; - int ao_nchan; - int ao_fifo; - int ai_nchan; - int ai_diff_nchan; - int ai_sh_nchan; - int ex_trig_analog; - int dio_nchan; - int has_counter; -}; + {"ME-4680", 0x4680, {4, 4}, {32, 0, 16, 1}, {4}, {3} }, + {"ME-4680i", 0x4681, {4, 4}, {32, 0, 16, 1}, {4}, {3} }, + {"ME-4680s", 0x4682, {4, 4}, {32, 8, 16, 1}, {4}, {3} }, + {"ME-4680is", 0x4683, {4, 4}, {32, 8, 16, 1}, {4}, {3} }, -static const struct me4000_board me4000_boards[] = { - { - .name = "ME-4650", - .device_id = PCI_DEVICE_ID_MEILHAUS_ME4650, - .ai_nchan = 16, - .dio_nchan = 32, - }, { - .name = "ME-4660", - .device_id = PCI_DEVICE_ID_MEILHAUS_ME4660, - .ai_nchan = 32, - .ai_diff_nchan = 16, - .dio_nchan = 32, - .has_counter = 1, - }, { - .name = "ME-4660i", - .device_id = PCI_DEVICE_ID_MEILHAUS_ME4660I, - .ai_nchan = 32, - .ai_diff_nchan = 16, - .dio_nchan = 32, - .has_counter = 1, - }, { - .name = "ME-4660s", - .device_id = PCI_DEVICE_ID_MEILHAUS_ME4660S, - .ai_nchan = 32, - .ai_diff_nchan = 16, - .ai_sh_nchan = 8, - .dio_nchan = 32, - .has_counter = 1, - }, { - .name = "ME-4660is", - .device_id = PCI_DEVICE_ID_MEILHAUS_ME4660IS, - .ai_nchan = 32, - .ai_diff_nchan = 16, - .ai_sh_nchan = 8, - .dio_nchan = 32, - .has_counter = 1, - }, { - .name = "ME-4670", - .device_id = PCI_DEVICE_ID_MEILHAUS_ME4670, - .ao_nchan = 4, - .ai_nchan = 32, - .ai_diff_nchan = 16, - .ex_trig_analog = 1, - .dio_nchan = 32, - .has_counter = 1, - }, { - .name = "ME-4670i", - .device_id = PCI_DEVICE_ID_MEILHAUS_ME4670I, - .ao_nchan = 4, - .ai_nchan = 32, - .ai_diff_nchan = 16, - .ex_trig_analog = 1, - .dio_nchan = 32, - .has_counter = 1, - }, { - .name = "ME-4670s", - .device_id = PCI_DEVICE_ID_MEILHAUS_ME4670S, - .ao_nchan = 4, - .ai_nchan = 32, - .ai_diff_nchan = 16, - .ai_sh_nchan = 8, - .ex_trig_analog = 1, - .dio_nchan = 32, - .has_counter = 1, - }, { - .name = "ME-4670is", - .device_id = PCI_DEVICE_ID_MEILHAUS_ME4670IS, - .ao_nchan = 4, - .ai_nchan = 32, - .ai_diff_nchan = 16, - .ai_sh_nchan = 8, - .ex_trig_analog = 1, - .dio_nchan = 32, - .has_counter = 1, - }, { - .name = "ME-4680", - .device_id = PCI_DEVICE_ID_MEILHAUS_ME4680, - .ao_nchan = 4, - .ao_fifo = 4, - .ai_nchan = 32, - .ai_diff_nchan = 16, - .ex_trig_analog = 1, - .dio_nchan = 32, - .has_counter = 1, - }, { - .name = "ME-4680i", - .device_id = PCI_DEVICE_ID_MEILHAUS_ME4680I, - .ao_nchan = 4, - .ao_fifo = 4, - .ai_nchan = 32, - .ai_diff_nchan = 16, - .ex_trig_analog = 1, - .dio_nchan = 32, - .has_counter = 1, - }, { - .name = "ME-4680s", - .device_id = PCI_DEVICE_ID_MEILHAUS_ME4680S, - .ao_nchan = 4, - .ao_fifo = 4, - .ai_nchan = 32, - .ai_diff_nchan = 16, - .ai_sh_nchan = 8, - .ex_trig_analog = 1, - .dio_nchan = 32, - .has_counter = 1, - }, { - .name = "ME-4680is", - .device_id = PCI_DEVICE_ID_MEILHAUS_ME4680IS, - .ao_nchan = 4, - .ao_fifo = 4, - .ai_nchan = 32, - .ai_diff_nchan = 16, - .ai_sh_nchan = 8, - .ex_trig_analog = 1, - .dio_nchan = 32, - .has_counter = 1, - }, + {0}, }; +#define ME4000_BOARD_VERSIONS (ARRAY_SIZE(me4000_boards) - 1) + +/*----------------------------------------------------------------------------- + Meilhaus function prototypes + ---------------------------------------------------------------------------*/ +static int get_registers(struct comedi_device *dev, struct pci_dev *pci_dev_p); +static int init_board_info(struct comedi_device *dev, + struct pci_dev *pci_dev_p); +static int init_ao_context(struct comedi_device *dev); +static int init_ai_context(struct comedi_device *dev); +static int init_dio_context(struct comedi_device *dev); +static int init_cnt_context(struct comedi_device *dev); +static int xilinx_download(struct comedi_device *dev); +static int reset_board(struct comedi_device *dev); + +static int ai_write_chanlist(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_cmd *cmd); + static const struct comedi_lrange me4000_ai_range = { 4, { @@ -363,6 +114,380 @@ static const struct comedi_lrange me4000_ai_range = { } }; +static const struct comedi_lrange me4000_ao_range = { + 1, + { + BIP_RANGE(10), + } +}; + +static int me4000_probe(struct comedi_device *dev, struct comedi_devconfig *it) +{ + struct pci_dev *pci_device = NULL; + int result, i; + struct me4000_board *board; + + /* Allocate private memory */ + if (alloc_private(dev, sizeof(struct me4000_info)) < 0) + return -ENOMEM; + + /* + * Probe the device to determine what device in the series it is. + */ + for_each_pci_dev(pci_device) { + if (pci_device->vendor == PCI_VENDOR_ID_MEILHAUS) { + for (i = 0; i < ME4000_BOARD_VERSIONS; i++) { + if (me4000_boards[i].device_id == + pci_device->device) { + /* + * Was a particular + * bus/slot requested? + */ + if ((it->options[0] != 0) + || (it->options[1] != 0)) { + /* + * Are we on the wrong + * bus/slot? + */ + if (pci_device->bus->number != + it->options[0] + || + PCI_SLOT(pci_device->devfn) + != it->options[1]) { + continue; + } + } + dev->board_ptr = me4000_boards + i; + board = + (struct me4000_board *) + dev->board_ptr; + info->pci_dev_p = pci_device; + goto found; + } + } + } + } + + printk(KERN_ERR + "comedi%d: me4000: me4000_probe(): " + "No supported board found (req. bus/slot : %d/%d)\n", + dev->minor, it->options[0], it->options[1]); + return -ENODEV; + +found: + + printk(KERN_INFO + "comedi%d: me4000: me4000_probe(): " + "Found %s at PCI bus %d, slot %d\n", + dev->minor, me4000_boards[i].name, pci_device->bus->number, + PCI_SLOT(pci_device->devfn)); + + /* Set data in device structure */ + dev->board_name = board->name; + + /* Enable PCI device and request regions */ + result = comedi_pci_enable(pci_device, dev->board_name); + if (result) { + printk(KERN_ERR + "comedi%d: me4000: me4000_probe(): Cannot enable PCI " + "device and request I/O regions\n", dev->minor); + return result; + } + + /* Get the PCI base registers */ + result = get_registers(dev, pci_device); + if (result) { + printk(KERN_ERR + "comedi%d: me4000: me4000_probe(): " + "Cannot get registers\n", dev->minor); + return result; + } + /* Initialize board info */ + result = init_board_info(dev, pci_device); + if (result) { + printk(KERN_ERR + "comedi%d: me4000: me4000_probe(): " + "Cannot init baord info\n", dev->minor); + return result; + } + + /* Init analog output context */ + result = init_ao_context(dev); + if (result) { + printk(KERN_ERR + "comedi%d: me4000: me4000_probe(): " + "Cannot init ao context\n", dev->minor); + return result; + } + + /* Init analog input context */ + result = init_ai_context(dev); + if (result) { + printk(KERN_ERR + "comedi%d: me4000: me4000_probe(): " + "Cannot init ai context\n", dev->minor); + return result; + } + + /* Init digital I/O context */ + result = init_dio_context(dev); + if (result) { + printk(KERN_ERR + "comedi%d: me4000: me4000_probe(): " + "Cannot init dio context\n", dev->minor); + return result; + } + + /* Init counter context */ + result = init_cnt_context(dev); + if (result) { + printk(KERN_ERR + "comedi%d: me4000: me4000_probe(): " + "Cannot init cnt context\n", dev->minor); + return result; + } + + /* Download the xilinx firmware */ + result = xilinx_download(dev); + if (result) { + printk(KERN_ERR + "comedi%d: me4000: me4000_probe(): " + "Can't download firmware\n", dev->minor); + return result; + } + + /* Make a hardware reset */ + result = reset_board(dev); + if (result) { + printk(KERN_ERR + "comedi%d: me4000: me4000_probe(): Can't reset board\n", + dev->minor); + return result; + } + + return 0; +} + +static int get_registers(struct comedi_device *dev, struct pci_dev *pci_dev_p) +{ + /*--------------------------- plx regbase -------------------------------*/ + + info->plx_regbase = pci_resource_start(pci_dev_p, 1); + if (info->plx_regbase == 0) { + printk(KERN_ERR + "comedi%d: me4000: get_registers(): " + "PCI base address 1 is not available\n", dev->minor); + return -ENODEV; + } + info->plx_regbase_size = pci_resource_len(pci_dev_p, 1); + + /*--------------------------- me4000 regbase ----------------------------*/ + + info->me4000_regbase = pci_resource_start(pci_dev_p, 2); + if (info->me4000_regbase == 0) { + printk(KERN_ERR + "comedi%d: me4000: get_registers(): " + "PCI base address 2 is not available\n", dev->minor); + return -ENODEV; + } + info->me4000_regbase_size = pci_resource_len(pci_dev_p, 2); + + /*--------------------------- timer regbase ------------------------------*/ + + info->timer_regbase = pci_resource_start(pci_dev_p, 3); + if (info->timer_regbase == 0) { + printk(KERN_ERR + "comedi%d: me4000: get_registers(): " + "PCI base address 3 is not available\n", dev->minor); + return -ENODEV; + } + info->timer_regbase_size = pci_resource_len(pci_dev_p, 3); + + /*--------------------------- program regbase ----------------------------*/ + + info->program_regbase = pci_resource_start(pci_dev_p, 5); + if (info->program_regbase == 0) { + printk(KERN_ERR + "comedi%d: me4000: get_registers(): " + "PCI base address 5 is not available\n", dev->minor); + return -ENODEV; + } + info->program_regbase_size = pci_resource_len(pci_dev_p, 5); + + return 0; +} + +static int init_board_info(struct comedi_device *dev, struct pci_dev *pci_dev_p) +{ + int result; + + /* Init spin locks */ + /* spin_lock_init(&info->preload_lock); */ + /* spin_lock_init(&info->ai_ctrl_lock); */ + + /* Get the serial number */ + result = pci_read_config_dword(pci_dev_p, 0x2C, &info->serial_no); + if (result != PCIBIOS_SUCCESSFUL) + return result; + + /* Get the hardware revision */ + result = pci_read_config_byte(pci_dev_p, 0x08, &info->hw_revision); + if (result != PCIBIOS_SUCCESSFUL) + return result; + + /* Get the vendor id */ + info->vendor_id = pci_dev_p->vendor; + + /* Get the device id */ + info->device_id = pci_dev_p->device; + + /* Get the irq assigned to the board */ + info->irq = pci_dev_p->irq; + + return 0; +} + +static int init_ao_context(struct comedi_device *dev) +{ + int i; + + for (i = 0; i < thisboard->ao.count; i++) { + /* spin_lock_init(&info->ao_context[i].use_lock); */ + info->ao_context[i].irq = info->irq; + + switch (i) { + case 0: + info->ao_context[i].ctrl_reg = + info->me4000_regbase + ME4000_AO_00_CTRL_REG; + info->ao_context[i].status_reg = + info->me4000_regbase + ME4000_AO_00_STATUS_REG; + info->ao_context[i].fifo_reg = + info->me4000_regbase + ME4000_AO_00_FIFO_REG; + info->ao_context[i].single_reg = + info->me4000_regbase + ME4000_AO_00_SINGLE_REG; + info->ao_context[i].timer_reg = + info->me4000_regbase + ME4000_AO_00_TIMER_REG; + info->ao_context[i].irq_status_reg = + info->me4000_regbase + ME4000_IRQ_STATUS_REG; + info->ao_context[i].preload_reg = + info->me4000_regbase + ME4000_AO_LOADSETREG_XX; + break; + case 1: + info->ao_context[i].ctrl_reg = + info->me4000_regbase + ME4000_AO_01_CTRL_REG; + info->ao_context[i].status_reg = + info->me4000_regbase + ME4000_AO_01_STATUS_REG; + info->ao_context[i].fifo_reg = + info->me4000_regbase + ME4000_AO_01_FIFO_REG; + info->ao_context[i].single_reg = + info->me4000_regbase + ME4000_AO_01_SINGLE_REG; + info->ao_context[i].timer_reg = + info->me4000_regbase + ME4000_AO_01_TIMER_REG; + info->ao_context[i].irq_status_reg = + info->me4000_regbase + ME4000_IRQ_STATUS_REG; + info->ao_context[i].preload_reg = + info->me4000_regbase + ME4000_AO_LOADSETREG_XX; + break; + case 2: + info->ao_context[i].ctrl_reg = + info->me4000_regbase + ME4000_AO_02_CTRL_REG; + info->ao_context[i].status_reg = + info->me4000_regbase + ME4000_AO_02_STATUS_REG; + info->ao_context[i].fifo_reg = + info->me4000_regbase + ME4000_AO_02_FIFO_REG; + info->ao_context[i].single_reg = + info->me4000_regbase + ME4000_AO_02_SINGLE_REG; + info->ao_context[i].timer_reg = + info->me4000_regbase + ME4000_AO_02_TIMER_REG; + info->ao_context[i].irq_status_reg = + info->me4000_regbase + ME4000_IRQ_STATUS_REG; + info->ao_context[i].preload_reg = + info->me4000_regbase + ME4000_AO_LOADSETREG_XX; + break; + case 3: + info->ao_context[i].ctrl_reg = + info->me4000_regbase + ME4000_AO_03_CTRL_REG; + info->ao_context[i].status_reg = + info->me4000_regbase + ME4000_AO_03_STATUS_REG; + info->ao_context[i].fifo_reg = + info->me4000_regbase + ME4000_AO_03_FIFO_REG; + info->ao_context[i].single_reg = + info->me4000_regbase + ME4000_AO_03_SINGLE_REG; + info->ao_context[i].timer_reg = + info->me4000_regbase + ME4000_AO_03_TIMER_REG; + info->ao_context[i].irq_status_reg = + info->me4000_regbase + ME4000_IRQ_STATUS_REG; + info->ao_context[i].preload_reg = + info->me4000_regbase + ME4000_AO_LOADSETREG_XX; + break; + default: + break; + } + } + + return 0; +} + +static int init_ai_context(struct comedi_device *dev) +{ + info->ai_context.irq = info->irq; + + info->ai_context.ctrl_reg = info->me4000_regbase + ME4000_AI_CTRL_REG; + info->ai_context.status_reg = + info->me4000_regbase + ME4000_AI_STATUS_REG; + info->ai_context.channel_list_reg = + info->me4000_regbase + ME4000_AI_CHANNEL_LIST_REG; + info->ai_context.data_reg = info->me4000_regbase + ME4000_AI_DATA_REG; + info->ai_context.chan_timer_reg = + info->me4000_regbase + ME4000_AI_CHAN_TIMER_REG; + info->ai_context.chan_pre_timer_reg = + info->me4000_regbase + ME4000_AI_CHAN_PRE_TIMER_REG; + info->ai_context.scan_timer_low_reg = + info->me4000_regbase + ME4000_AI_SCAN_TIMER_LOW_REG; + info->ai_context.scan_timer_high_reg = + info->me4000_regbase + ME4000_AI_SCAN_TIMER_HIGH_REG; + info->ai_context.scan_pre_timer_low_reg = + info->me4000_regbase + ME4000_AI_SCAN_PRE_TIMER_LOW_REG; + info->ai_context.scan_pre_timer_high_reg = + info->me4000_regbase + ME4000_AI_SCAN_PRE_TIMER_HIGH_REG; + info->ai_context.start_reg = info->me4000_regbase + ME4000_AI_START_REG; + info->ai_context.irq_status_reg = + info->me4000_regbase + ME4000_IRQ_STATUS_REG; + info->ai_context.sample_counter_reg = + info->me4000_regbase + ME4000_AI_SAMPLE_COUNTER_REG; + + return 0; +} + +static int init_dio_context(struct comedi_device *dev) +{ + info->dio_context.dir_reg = info->me4000_regbase + ME4000_DIO_DIR_REG; + info->dio_context.ctrl_reg = info->me4000_regbase + ME4000_DIO_CTRL_REG; + info->dio_context.port_0_reg = + info->me4000_regbase + ME4000_DIO_PORT_0_REG; + info->dio_context.port_1_reg = + info->me4000_regbase + ME4000_DIO_PORT_1_REG; + info->dio_context.port_2_reg = + info->me4000_regbase + ME4000_DIO_PORT_2_REG; + info->dio_context.port_3_reg = + info->me4000_regbase + ME4000_DIO_PORT_3_REG; + + return 0; +} + +static int init_cnt_context(struct comedi_device *dev) +{ + info->cnt_context.ctrl_reg = info->timer_regbase + ME4000_CNT_CTRL_REG; + info->cnt_context.counter_0_reg = + info->timer_regbase + ME4000_CNT_COUNTER_0_REG; + info->cnt_context.counter_1_reg = + info->timer_regbase + ME4000_CNT_COUNTER_1_REG; + info->cnt_context.counter_2_reg = + info->timer_regbase + ME4000_CNT_COUNTER_2_REG; + + return 0; +} + #define FIRMWARE_NOT_AVAILABLE 1 #if FIRMWARE_NOT_AVAILABLE extern unsigned char *xilinx_firm; @@ -370,17 +495,11 @@ extern unsigned char *xilinx_firm; static int xilinx_download(struct comedi_device *dev) { - struct pci_dev *pcidev = comedi_to_pci_dev(dev); - struct me4000_info *info = dev->private; - unsigned long xilinx_iobase = pci_resource_start(pcidev, 5); u32 value = 0; wait_queue_head_t queue; int idx = 0; int size = 0; - if (!xilinx_iobase) - return -ENODEV; - init_waitqueue_head(&queue); /* @@ -395,12 +514,14 @@ static int xilinx_download(struct comedi_device *dev) outl(value, info->plx_regbase + PLX_ICR); /* Init Xilinx with CS1 */ - inb(xilinx_iobase + 0xC8); + inb(info->program_regbase + 0xC8); /* Wait until /INIT pin is set */ udelay(20); if (!(inl(info->plx_regbase + PLX_INTCSR) & 0x20)) { - dev_err(dev->class_dev, "Can't init Xilinx\n"); + printk(KERN_ERR + "comedi%d: me4000: xilinx_download(): " + "Can't init Xilinx\n", dev->minor); return -EIO; } @@ -409,8 +530,8 @@ static int xilinx_download(struct comedi_device *dev) value &= ~0x100; outl(value, info->plx_regbase + PLX_ICR); if (FIRMWARE_NOT_AVAILABLE) { - dev_err(dev->class_dev, - "xilinx firmware unavailable due to licensing, aborting"); + comedi_error(dev, "xilinx firmware unavailable " + "due to licensing, aborting"); return -EIO; } else { /* Download Xilinx firmware */ @@ -419,14 +540,15 @@ static int xilinx_download(struct comedi_device *dev) udelay(10); for (idx = 0; idx < size; idx++) { - outb(xilinx_firm[16 + idx], xilinx_iobase); + outb(xilinx_firm[16 + idx], info->program_regbase); udelay(10); /* Check if BUSY flag is low */ if (inl(info->plx_regbase + PLX_ICR) & 0x20) { - dev_err(dev->class_dev, - "Xilinx is still busy (idx = %d)\n", - idx); + printk(KERN_ERR + "comedi%d: me4000: xilinx_download(): " + "Xilinx is still busy (idx = %d)\n", + dev->minor, idx); return -EIO; } } @@ -435,8 +557,12 @@ static int xilinx_download(struct comedi_device *dev) /* If done flag is high download was successful */ if (inl(info->plx_regbase + PLX_ICR) & 0x4) { } else { - dev_err(dev->class_dev, "DONE flag is not set\n"); - dev_err(dev->class_dev, "Download not successful\n"); + printk(KERN_ERR + "comedi%d: me4000: xilinx_download(): " + "DONE flag is not set\n", dev->minor); + printk(KERN_ERR + "comedi%d: me4000: xilinx_download(): " + "Download not successful\n", dev->minor); return -EIO; } @@ -448,45 +574,52 @@ static int xilinx_download(struct comedi_device *dev) return 0; } -static void me4000_reset(struct comedi_device *dev) +static int reset_board(struct comedi_device *dev) { - struct me4000_info *info = dev->private; - unsigned long val; - int chan; + unsigned long icr; /* Make a hardware reset */ - val = inl(info->plx_regbase + PLX_ICR); - val |= 0x40000000; - outl(val, info->plx_regbase + PLX_ICR); - val &= ~0x40000000; - outl(val , info->plx_regbase + PLX_ICR); + icr = inl(info->plx_regbase + PLX_ICR); + icr |= 0x40000000; + outl(icr, info->plx_regbase + PLX_ICR); + icr &= ~0x40000000; + outl(icr, info->plx_regbase + PLX_ICR); /* 0x8000 to the DACs means an output voltage of 0V */ - for (chan = 0; chan < 4; chan++) - outl(0x8000, dev->iobase + ME4000_AO_SINGLE_REG(chan)); + outl(0x8000, info->me4000_regbase + ME4000_AO_00_SINGLE_REG); + outl(0x8000, info->me4000_regbase + ME4000_AO_01_SINGLE_REG); + outl(0x8000, info->me4000_regbase + ME4000_AO_02_SINGLE_REG); + outl(0x8000, info->me4000_regbase + ME4000_AO_03_SINGLE_REG); /* Set both stop bits in the analog input control register */ outl(ME4000_AI_CTRL_BIT_IMMEDIATE_STOP | ME4000_AI_CTRL_BIT_STOP, - dev->iobase + ME4000_AI_CTRL_REG); + info->me4000_regbase + ME4000_AI_CTRL_REG); /* Set both stop bits in the analog output control register */ - val = ME4000_AO_CTRL_BIT_IMMEDIATE_STOP | ME4000_AO_CTRL_BIT_STOP; - for (chan = 0; chan < 4; chan++) - outl(val, dev->iobase + ME4000_AO_CTRL_REG(chan)); + outl(ME4000_AO_CTRL_BIT_IMMEDIATE_STOP | ME4000_AO_CTRL_BIT_STOP, + info->me4000_regbase + ME4000_AO_00_CTRL_REG); + outl(ME4000_AO_CTRL_BIT_IMMEDIATE_STOP | ME4000_AO_CTRL_BIT_STOP, + info->me4000_regbase + ME4000_AO_01_CTRL_REG); + outl(ME4000_AO_CTRL_BIT_IMMEDIATE_STOP | ME4000_AO_CTRL_BIT_STOP, + info->me4000_regbase + ME4000_AO_02_CTRL_REG); + outl(ME4000_AO_CTRL_BIT_IMMEDIATE_STOP | ME4000_AO_CTRL_BIT_STOP, + info->me4000_regbase + ME4000_AO_03_CTRL_REG); /* Enable interrupts on the PLX */ outl(0x43, info->plx_regbase + PLX_INTCSR); /* Set the adustment register for AO demux */ outl(ME4000_AO_DEMUX_ADJUST_VALUE, - dev->iobase + ME4000_AO_DEMUX_ADJUST_REG); + info->me4000_regbase + ME4000_AO_DEMUX_ADJUST_REG); /* * Set digital I/O direction for port 0 * to output on isolated versions */ - if (!(inl(dev->iobase + ME4000_DIO_DIR_REG) & 0x1)) - outl(0x1, dev->iobase + ME4000_DIO_CTRL_REG); + if (!(inl(info->me4000_regbase + ME4000_DIO_DIR_REG) & 0x1)) + outl(0x1, info->me4000_regbase + ME4000_DIO_CTRL_REG); + + return 0; } /*============================================================================= @@ -497,7 +630,7 @@ static int me4000_ai_insn_read(struct comedi_device *dev, struct comedi_subdevice *subdevice, struct comedi_insn *insn, unsigned int *data) { - const struct me4000_board *thisboard = comedi_board(dev); + int chan = CR_CHAN(insn->chanspec); int rang = CR_RANGE(insn->chanspec); int aref = CR_AREF(insn->chanspec); @@ -509,8 +642,9 @@ static int me4000_ai_insn_read(struct comedi_device *dev, if (insn->n == 0) { return 0; } else if (insn->n > 1) { - dev_err(dev->class_dev, "Invalid instruction length %d\n", - insn->n); + printk(KERN_ERR + "comedi%d: me4000: me4000_ai_insn_read(): " + "Invalid instruction length %d\n", dev->minor, insn->n); return -EINVAL; } @@ -528,16 +662,19 @@ static int me4000_ai_insn_read(struct comedi_device *dev, entry |= ME4000_AI_LIST_RANGE_BIPOLAR_10; break; default: - dev_err(dev->class_dev, "Invalid range specified\n"); + printk(KERN_ERR + "comedi%d: me4000: me4000_ai_insn_read(): " + "Invalid range specified\n", dev->minor); return -EINVAL; } switch (aref) { case AREF_GROUND: case AREF_COMMON: - if (chan >= thisboard->ai_nchan) { - dev_err(dev->class_dev, - "Analog input is not available\n"); + if (chan >= thisboard->ai.count) { + printk(KERN_ERR + "comedi%d: me4000: me4000_ai_insn_read(): " + "Analog input is not available\n", dev->minor); return -EINVAL; } entry |= ME4000_AI_LIST_INPUT_SINGLE_ENDED | chan; @@ -545,61 +682,68 @@ static int me4000_ai_insn_read(struct comedi_device *dev, case AREF_DIFF: if (rang == 0 || rang == 1) { - dev_err(dev->class_dev, - "Range must be bipolar when aref = diff\n"); + printk(KERN_ERR + "comedi%d: me4000: me4000_ai_insn_read(): " + "Range must be bipolar when aref = diff\n", + dev->minor); return -EINVAL; } - if (chan >= thisboard->ai_diff_nchan) { - dev_err(dev->class_dev, - "Analog input is not available\n"); + if (chan >= thisboard->ai.diff_count) { + printk(KERN_ERR + "comedi%d: me4000: me4000_ai_insn_read(): " + "Analog input is not available\n", dev->minor); return -EINVAL; } entry |= ME4000_AI_LIST_INPUT_DIFFERENTIAL | chan; break; default: - dev_err(dev->class_dev, "Invalid aref specified\n"); + printk(KERN_ERR + "comedi%d: me4000: me4000_ai_insn_read(): " + "Invalid aref specified\n", dev->minor); return -EINVAL; } entry |= ME4000_AI_LIST_LAST_ENTRY; /* Clear channel list, data fifo and both stop bits */ - tmp = inl(dev->iobase + ME4000_AI_CTRL_REG); + tmp = inl(info->ai_context.ctrl_reg); tmp &= ~(ME4000_AI_CTRL_BIT_CHANNEL_FIFO | ME4000_AI_CTRL_BIT_DATA_FIFO | ME4000_AI_CTRL_BIT_STOP | ME4000_AI_CTRL_BIT_IMMEDIATE_STOP); - outl(tmp, dev->iobase + ME4000_AI_CTRL_REG); + outl(tmp, info->ai_context.ctrl_reg); /* Set the acquisition mode to single */ tmp &= ~(ME4000_AI_CTRL_BIT_MODE_0 | ME4000_AI_CTRL_BIT_MODE_1 | ME4000_AI_CTRL_BIT_MODE_2); - outl(tmp, dev->iobase + ME4000_AI_CTRL_REG); + outl(tmp, info->ai_context.ctrl_reg); /* Enable channel list and data fifo */ tmp |= ME4000_AI_CTRL_BIT_CHANNEL_FIFO | ME4000_AI_CTRL_BIT_DATA_FIFO; - outl(tmp, dev->iobase + ME4000_AI_CTRL_REG); + outl(tmp, info->ai_context.ctrl_reg); /* Generate channel list entry */ - outl(entry, dev->iobase + ME4000_AI_CHANNEL_LIST_REG); + outl(entry, info->ai_context.channel_list_reg); /* Set the timer to maximum sample rate */ - outl(ME4000_AI_MIN_TICKS, dev->iobase + ME4000_AI_CHAN_TIMER_REG); - outl(ME4000_AI_MIN_TICKS, dev->iobase + ME4000_AI_CHAN_PRE_TIMER_REG); + outl(ME4000_AI_MIN_TICKS, info->ai_context.chan_timer_reg); + outl(ME4000_AI_MIN_TICKS, info->ai_context.chan_pre_timer_reg); /* Start conversion by dummy read */ - inl(dev->iobase + ME4000_AI_START_REG); + inl(info->ai_context.start_reg); /* Wait until ready */ udelay(10); - if (!(inl(dev->iobase + ME4000_AI_STATUS_REG) & + if (!(inl(info->ai_context.status_reg) & ME4000_AI_STATUS_BIT_EF_DATA)) { - dev_err(dev->class_dev, "Value not available after wait\n"); + printk(KERN_ERR + "comedi%d: me4000: me4000_ai_insn_read(): " + "Value not available after wait\n", dev->minor); return -EIO; } /* Read value from data fifo */ - lval = inl(dev->iobase + ME4000_AI_DATA_REG) & 0xFFFF; + lval = inl(info->ai_context.data_reg) & 0xFFFF; data[0] = lval ^ 0x8000; return 1; @@ -611,12 +755,12 @@ static int me4000_ai_cancel(struct comedi_device *dev, unsigned long tmp; /* Stop any running conversion */ - tmp = inl(dev->iobase + ME4000_AI_CTRL_REG); + tmp = inl(info->ai_context.ctrl_reg); tmp &= ~(ME4000_AI_CTRL_BIT_STOP | ME4000_AI_CTRL_BIT_IMMEDIATE_STOP); - outl(tmp, dev->iobase + ME4000_AI_CTRL_REG); + outl(tmp, info->ai_context.ctrl_reg); /* Clear the control register */ - outl(0x0, dev->iobase + ME4000_AI_CTRL_REG); + outl(0x0, info->ai_context.ctrl_reg); return 0; } @@ -624,25 +768,30 @@ static int me4000_ai_cancel(struct comedi_device *dev, static int ai_check_chanlist(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd) { - const struct me4000_board *thisboard = comedi_board(dev); int aref; int i; /* Check whether a channel list is available */ if (!cmd->chanlist_len) { - dev_err(dev->class_dev, "No channel list available\n"); + printk(KERN_ERR + "comedi%d: me4000: ai_check_chanlist(): " + "No channel list available\n", dev->minor); return -EINVAL; } /* Check the channel list size */ if (cmd->chanlist_len > ME4000_AI_CHANNEL_LIST_COUNT) { - dev_err(dev->class_dev, "Channel list is to large\n"); + printk(KERN_ERR + "comedi%d: me4000: ai_check_chanlist(): " + "Channel list is to large\n", dev->minor); return -EINVAL; } /* Check the pointer */ if (!cmd->chanlist) { - dev_err(dev->class_dev, "NULL pointer to channel list\n"); + printk(KERN_ERR + "comedi%d: me4000: ai_check_chanlist(): " + "NULL pointer to channel list\n", dev->minor); return -EFAULT; } @@ -650,8 +799,10 @@ static int ai_check_chanlist(struct comedi_device *dev, aref = CR_AREF(cmd->chanlist[0]); for (i = 0; i < cmd->chanlist_len; i++) { if (CR_AREF(cmd->chanlist[i]) != aref) { - dev_err(dev->class_dev, - "Mode is not equal for all entries\n"); + printk(KERN_ERR + "comedi%d: me4000: ai_check_chanlist(): " + "Mode is not equal for all entries\n", + dev->minor); return -EINVAL; } } @@ -660,17 +811,19 @@ static int ai_check_chanlist(struct comedi_device *dev, if (aref == SDF_DIFF) { for (i = 0; i < cmd->chanlist_len; i++) { if (CR_CHAN(cmd->chanlist[i]) >= - thisboard->ai_diff_nchan) { - dev_err(dev->class_dev, - "Channel number to high\n"); + thisboard->ai.diff_count) { + printk(KERN_ERR + "comedi%d: me4000: ai_check_chanlist():" + " Channel number to high\n", dev->minor); return -EINVAL; } } } else { for (i = 0; i < cmd->chanlist_len; i++) { - if (CR_CHAN(cmd->chanlist[i]) >= thisboard->ai_nchan) { - dev_err(dev->class_dev, - "Channel number to high\n"); + if (CR_CHAN(cmd->chanlist[i]) >= thisboard->ai.count) { + printk(KERN_ERR + "comedi%d: me4000: ai_check_chanlist(): " + "Channel number to high\n", dev->minor); return -EINVAL; } } @@ -681,8 +834,11 @@ static int ai_check_chanlist(struct comedi_device *dev, for (i = 0; i < cmd->chanlist_len; i++) { if (CR_RANGE(cmd->chanlist[i]) != 1 && CR_RANGE(cmd->chanlist[i]) != 2) { - dev_err(dev->class_dev, - "Bipolar is not selected in differential mode\n"); + printk(KERN_ERR + "comedi%d: me4000: ai_check_chanlist(): " + "Bipolar is not selected in " + "differential mode\n", + dev->minor); return -EINVAL; } } @@ -750,52 +906,16 @@ static void ai_write_timer(struct comedi_device *dev, unsigned int init_ticks, unsigned int scan_ticks, unsigned int chan_ticks) { - outl(init_ticks - 1, dev->iobase + ME4000_AI_SCAN_PRE_TIMER_LOW_REG); - outl(0x0, dev->iobase + ME4000_AI_SCAN_PRE_TIMER_HIGH_REG); + outl(init_ticks - 1, info->ai_context.scan_pre_timer_low_reg); + outl(0x0, info->ai_context.scan_pre_timer_high_reg); if (scan_ticks) { - outl(scan_ticks - 1, dev->iobase + ME4000_AI_SCAN_TIMER_LOW_REG); - outl(0x0, dev->iobase + ME4000_AI_SCAN_TIMER_HIGH_REG); + outl(scan_ticks - 1, info->ai_context.scan_timer_low_reg); + outl(0x0, info->ai_context.scan_timer_high_reg); } - outl(chan_ticks - 1, dev->iobase + ME4000_AI_CHAN_PRE_TIMER_REG); - outl(chan_ticks - 1, dev->iobase + ME4000_AI_CHAN_TIMER_REG); -} - -static int ai_write_chanlist(struct comedi_device *dev, - struct comedi_subdevice *s, struct comedi_cmd *cmd) -{ - unsigned int entry; - unsigned int chan; - unsigned int rang; - unsigned int aref; - int i; - - for (i = 0; i < cmd->chanlist_len; i++) { - chan = CR_CHAN(cmd->chanlist[i]); - rang = CR_RANGE(cmd->chanlist[i]); - aref = CR_AREF(cmd->chanlist[i]); - - entry = chan; - - if (rang == 0) - entry |= ME4000_AI_LIST_RANGE_UNIPOLAR_2_5; - else if (rang == 1) - entry |= ME4000_AI_LIST_RANGE_UNIPOLAR_10; - else if (rang == 2) - entry |= ME4000_AI_LIST_RANGE_BIPOLAR_2_5; - else - entry |= ME4000_AI_LIST_RANGE_BIPOLAR_10; - - if (aref == SDF_DIFF) - entry |= ME4000_AI_LIST_INPUT_DIFFERENTIAL; - else - entry |= ME4000_AI_LIST_INPUT_SINGLE_ENDED; - - outl(entry, dev->iobase + ME4000_AI_CHANNEL_LIST_REG); - } - - return 0; + outl(chan_ticks - 1, info->ai_context.chan_pre_timer_reg); + outl(chan_ticks - 1, info->ai_context.chan_timer_reg); } static int ai_prepare(struct comedi_device *dev, @@ -811,7 +931,7 @@ static int ai_prepare(struct comedi_device *dev, ai_write_timer(dev, init_ticks, scan_ticks, chan_ticks); /* Reset control register */ - outl(tmp, dev->iobase + ME4000_AI_CTRL_REG); + outl(tmp, info->ai_context.ctrl_reg); /* Start sources */ if ((cmd->start_src == TRIG_EXT && @@ -845,19 +965,19 @@ static int ai_prepare(struct comedi_device *dev, /* Stop triggers */ if (cmd->stop_src == TRIG_COUNT) { outl(cmd->chanlist_len * cmd->stop_arg, - dev->iobase + ME4000_AI_SAMPLE_COUNTER_REG); + info->ai_context.sample_counter_reg); tmp |= ME4000_AI_CTRL_BIT_HF_IRQ | ME4000_AI_CTRL_BIT_SC_IRQ; } else if (cmd->stop_src == TRIG_NONE && cmd->scan_end_src == TRIG_COUNT) { outl(cmd->scan_end_arg, - dev->iobase + ME4000_AI_SAMPLE_COUNTER_REG); + info->ai_context.sample_counter_reg); tmp |= ME4000_AI_CTRL_BIT_HF_IRQ | ME4000_AI_CTRL_BIT_SC_IRQ; } else { tmp |= ME4000_AI_CTRL_BIT_HF_IRQ; } /* Write the setup to the control register */ - outl(tmp, dev->iobase + ME4000_AI_CTRL_REG); + outl(tmp, info->ai_context.ctrl_reg); /* Write the channel list */ ai_write_chanlist(dev, s, cmd); @@ -865,6 +985,42 @@ static int ai_prepare(struct comedi_device *dev, return 0; } +static int ai_write_chanlist(struct comedi_device *dev, + struct comedi_subdevice *s, struct comedi_cmd *cmd) +{ + unsigned int entry; + unsigned int chan; + unsigned int rang; + unsigned int aref; + int i; + + for (i = 0; i < cmd->chanlist_len; i++) { + chan = CR_CHAN(cmd->chanlist[i]); + rang = CR_RANGE(cmd->chanlist[i]); + aref = CR_AREF(cmd->chanlist[i]); + + entry = chan; + + if (rang == 0) + entry |= ME4000_AI_LIST_RANGE_UNIPOLAR_2_5; + else if (rang == 1) + entry |= ME4000_AI_LIST_RANGE_UNIPOLAR_10; + else if (rang == 2) + entry |= ME4000_AI_LIST_RANGE_BIPOLAR_2_5; + else + entry |= ME4000_AI_LIST_RANGE_BIPOLAR_10; + + if (aref == SDF_DIFF) + entry |= ME4000_AI_LIST_INPUT_DIFFERENTIAL; + else + entry |= ME4000_AI_LIST_INPUT_SINGLE_ENDED; + + outl(entry, info->ai_context.channel_list_reg); + } + + return 0; +} + static int me4000_ai_do_cmd(struct comedi_device *dev, struct comedi_subdevice *s) { @@ -891,11 +1047,23 @@ static int me4000_ai_do_cmd(struct comedi_device *dev, return err; /* Start acquistion by dummy read */ - inl(dev->iobase + ME4000_AI_START_REG); + inl(info->ai_context.start_reg); return 0; } +/* + * me4000_ai_do_cmd_test(): + * + * The demo cmd.c in ./comedilib/demo specifies 6 return values: + * - success + * - invalid source + * - source conflict + * - invalid argument + * - argument conflict + * - invalid chanlist + * So I tried to adopt this scheme. + */ static int me4000_ai_do_cmd_test(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd) @@ -912,29 +1080,91 @@ static int me4000_ai_do_cmd_test(struct comedi_device *dev, /* Round the timer arguments */ ai_round_cmd_args(dev, s, cmd, &init_ticks, &scan_ticks, &chan_ticks); - /* Step 1 : check if triggers are trivially valid */ - - err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_EXT); - err |= cfc_check_trigger_src(&cmd->scan_begin_src, - TRIG_FOLLOW | TRIG_TIMER | TRIG_EXT); - err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_TIMER | TRIG_EXT); - err |= cfc_check_trigger_src(&cmd->scan_end_src, - TRIG_NONE | TRIG_COUNT); - err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_NONE | TRIG_COUNT); - + /* + * Stage 1. Check if the trigger sources are generally valid. + */ + switch (cmd->start_src) { + case TRIG_NOW: + case TRIG_EXT: + break; + case TRIG_ANY: + cmd->start_src &= TRIG_NOW | TRIG_EXT; + err++; + break; + default: + printk(KERN_ERR + "comedi%d: me4000: me4000_ai_do_cmd_test(): " + "Invalid start source\n", dev->minor); + cmd->start_src = TRIG_NOW; + err++; + } + switch (cmd->scan_begin_src) { + case TRIG_FOLLOW: + case TRIG_TIMER: + case TRIG_EXT: + break; + case TRIG_ANY: + cmd->scan_begin_src &= TRIG_FOLLOW | TRIG_TIMER | TRIG_EXT; + err++; + break; + default: + printk(KERN_ERR + "comedi%d: me4000: me4000_ai_do_cmd_test(): " + "Invalid scan begin source\n", dev->minor); + cmd->scan_begin_src = TRIG_FOLLOW; + err++; + } + switch (cmd->convert_src) { + case TRIG_TIMER: + case TRIG_EXT: + break; + case TRIG_ANY: + cmd->convert_src &= TRIG_TIMER | TRIG_EXT; + err++; + break; + default: + printk(KERN_ERR + "comedi%d: me4000: me4000_ai_do_cmd_test(): " + "Invalid convert source\n", dev->minor); + cmd->convert_src = TRIG_TIMER; + err++; + } + switch (cmd->scan_end_src) { + case TRIG_NONE: + case TRIG_COUNT: + break; + case TRIG_ANY: + cmd->scan_end_src &= TRIG_NONE | TRIG_COUNT; + err++; + break; + default: + printk(KERN_ERR + "comedi%d: me4000: me4000_ai_do_cmd_test(): " + "Invalid scan end source\n", dev->minor); + cmd->scan_end_src = TRIG_NONE; + err++; + } + switch (cmd->stop_src) { + case TRIG_NONE: + case TRIG_COUNT: + break; + case TRIG_ANY: + cmd->stop_src &= TRIG_NONE | TRIG_COUNT; + err++; + break; + default: + printk(KERN_ERR + "comedi%d: me4000: me4000_ai_do_cmd_test(): " + "Invalid stop source\n", dev->minor); + cmd->stop_src = TRIG_NONE; + err++; + } if (err) return 1; - /* Step 2a : make sure trigger sources are unique */ - - err |= cfc_check_trigger_is_unique(cmd->start_src); - err |= cfc_check_trigger_is_unique(cmd->scan_begin_src); - err |= cfc_check_trigger_is_unique(cmd->convert_src); - err |= cfc_check_trigger_is_unique(cmd->scan_end_src); - err |= cfc_check_trigger_is_unique(cmd->stop_src); - - /* Step 2b : and mutually compatible */ - + /* + * Stage 2. Check for trigger source conflicts. + */ if (cmd->start_src == TRIG_NOW && cmd->scan_begin_src == TRIG_TIMER && cmd->convert_src == TRIG_TIMER) { @@ -954,7 +1184,13 @@ static int me4000_ai_do_cmd_test(struct comedi_device *dev, cmd->scan_begin_src == TRIG_EXT && cmd->convert_src == TRIG_EXT) { } else { - err |= -EINVAL; + printk(KERN_ERR + "comedi%d: me4000: me4000_ai_do_cmd_test(): " + "Invalid start trigger combination\n", dev->minor); + cmd->start_src = TRIG_NOW; + cmd->scan_begin_src = TRIG_FOLLOW; + cmd->convert_src = TRIG_TIMER; + err++; } if (cmd->stop_src == TRIG_NONE && cmd->scan_end_src == TRIG_NONE) { @@ -965,9 +1201,13 @@ static int me4000_ai_do_cmd_test(struct comedi_device *dev, } else if (cmd->stop_src == TRIG_COUNT && cmd->scan_end_src == TRIG_COUNT) { } else { - err |= -EINVAL; + printk(KERN_ERR + "comedi%d: me4000: me4000_ai_do_cmd_test(): " + "Invalid stop trigger combination\n", dev->minor); + cmd->stop_src = TRIG_NONE; + cmd->scan_end_src = TRIG_NONE; + err++; } - if (err) return 2; @@ -975,22 +1215,30 @@ static int me4000_ai_do_cmd_test(struct comedi_device *dev, * Stage 3. Check if arguments are generally valid. */ if (cmd->chanlist_len < 1) { - dev_err(dev->class_dev, "No channel list\n"); + printk(KERN_ERR + "comedi%d: me4000: me4000_ai_do_cmd_test(): " + "No channel list\n", dev->minor); cmd->chanlist_len = 1; err++; } if (init_ticks < 66) { - dev_err(dev->class_dev, "Start arg to low\n"); + printk(KERN_ERR + "comedi%d: me4000: me4000_ai_do_cmd_test(): " + "Start arg to low\n", dev->minor); cmd->start_arg = 2000; err++; } if (scan_ticks && scan_ticks < 67) { - dev_err(dev->class_dev, "Scan begin arg to low\n"); + printk(KERN_ERR + "comedi%d: me4000: me4000_ai_do_cmd_test(): " + "Scan begin arg to low\n", dev->minor); cmd->scan_begin_arg = 2031; err++; } if (chan_ticks < 66) { - dev_err(dev->class_dev, "Convert arg to low\n"); + printk(KERN_ERR + "comedi%d: me4000: me4000_ai_do_cmd_test(): " + "Convert arg to low\n", dev->minor); cmd->convert_arg = 2000; err++; } @@ -1007,17 +1255,23 @@ static int me4000_ai_do_cmd_test(struct comedi_device *dev, /* Check timer arguments */ if (init_ticks < ME4000_AI_MIN_TICKS) { - dev_err(dev->class_dev, "Invalid start arg\n"); + printk(KERN_ERR + "comedi%d: me4000: me4000_ai_do_cmd_test(): " + "Invalid start arg\n", dev->minor); cmd->start_arg = 2000; /* 66 ticks at least */ err++; } if (chan_ticks < ME4000_AI_MIN_TICKS) { - dev_err(dev->class_dev, "Invalid convert arg\n"); + printk(KERN_ERR + "comedi%d: me4000: me4000_ai_do_cmd_test(): " + "Invalid convert arg\n", dev->minor); cmd->convert_arg = 2000; /* 66 ticks at least */ err++; } if (scan_ticks <= cmd->chanlist_len * chan_ticks) { - dev_err(dev->class_dev, "Invalid scan end arg\n"); + printk(KERN_ERR + "comedi%d: me4000: me4000_ai_do_cmd_test(): " + "Invalid scan end arg\n", dev->minor); /* At least one tick more */ cmd->scan_end_arg = 2000 * cmd->chanlist_len + 31; @@ -1029,12 +1283,16 @@ static int me4000_ai_do_cmd_test(struct comedi_device *dev, /* Check timer arguments */ if (init_ticks < ME4000_AI_MIN_TICKS) { - dev_err(dev->class_dev, "Invalid start arg\n"); + printk(KERN_ERR + "comedi%d: me4000: me4000_ai_do_cmd_test(): " + "Invalid start arg\n", dev->minor); cmd->start_arg = 2000; /* 66 ticks at least */ err++; } if (chan_ticks < ME4000_AI_MIN_TICKS) { - dev_err(dev->class_dev, "Invalid convert arg\n"); + printk(KERN_ERR + "comedi%d: me4000: me4000_ai_do_cmd_test(): " + "Invalid convert arg\n", dev->minor); cmd->convert_arg = 2000; /* 66 ticks at least */ err++; } @@ -1044,17 +1302,23 @@ static int me4000_ai_do_cmd_test(struct comedi_device *dev, /* Check timer arguments */ if (init_ticks < ME4000_AI_MIN_TICKS) { - dev_err(dev->class_dev, "Invalid start arg\n"); + printk(KERN_ERR + "comedi%d: me4000: me4000_ai_do_cmd_test(): " + "Invalid start arg\n", dev->minor); cmd->start_arg = 2000; /* 66 ticks at least */ err++; } if (chan_ticks < ME4000_AI_MIN_TICKS) { - dev_err(dev->class_dev, "Invalid convert arg\n"); + printk(KERN_ERR + "comedi%d: me4000: me4000_ai_do_cmd_test(): " + "Invalid convert arg\n", dev->minor); cmd->convert_arg = 2000; /* 66 ticks at least */ err++; } if (scan_ticks <= cmd->chanlist_len * chan_ticks) { - dev_err(dev->class_dev, "Invalid scan end arg\n"); + printk(KERN_ERR + "comedi%d: me4000: me4000_ai_do_cmd_test(): " + "Invalid scan end arg\n", dev->minor); /* At least one tick more */ cmd->scan_end_arg = 2000 * cmd->chanlist_len + 31; @@ -1066,12 +1330,16 @@ static int me4000_ai_do_cmd_test(struct comedi_device *dev, /* Check timer arguments */ if (init_ticks < ME4000_AI_MIN_TICKS) { - dev_err(dev->class_dev, "Invalid start arg\n"); + printk(KERN_ERR + "comedi%d: me4000: me4000_ai_do_cmd_test(): " + "Invalid start arg\n", dev->minor); cmd->start_arg = 2000; /* 66 ticks at least */ err++; } if (chan_ticks < ME4000_AI_MIN_TICKS) { - dev_err(dev->class_dev, "Invalid convert arg\n"); + printk(KERN_ERR + "comedi%d: me4000: me4000_ai_do_cmd_test(): " + "Invalid convert arg\n", dev->minor); cmd->convert_arg = 2000; /* 66 ticks at least */ err++; } @@ -1081,12 +1349,16 @@ static int me4000_ai_do_cmd_test(struct comedi_device *dev, /* Check timer arguments */ if (init_ticks < ME4000_AI_MIN_TICKS) { - dev_err(dev->class_dev, "Invalid start arg\n"); + printk(KERN_ERR + "comedi%d: me4000: me4000_ai_do_cmd_test(): " + "Invalid start arg\n", dev->minor); cmd->start_arg = 2000; /* 66 ticks at least */ err++; } if (chan_ticks < ME4000_AI_MIN_TICKS) { - dev_err(dev->class_dev, "Invalid convert arg\n"); + printk(KERN_ERR + "comedi%d: me4000: me4000_ai_do_cmd_test(): " + "Invalid convert arg\n", dev->minor); cmd->convert_arg = 2000; /* 66 ticks at least */ err++; } @@ -1096,21 +1368,27 @@ static int me4000_ai_do_cmd_test(struct comedi_device *dev, /* Check timer arguments */ if (init_ticks < ME4000_AI_MIN_TICKS) { - dev_err(dev->class_dev, "Invalid start arg\n"); + printk(KERN_ERR + "comedi%d: me4000: me4000_ai_do_cmd_test(): " + "Invalid start arg\n", dev->minor); cmd->start_arg = 2000; /* 66 ticks at least */ err++; } } if (cmd->stop_src == TRIG_COUNT) { if (cmd->stop_arg == 0) { - dev_err(dev->class_dev, "Invalid stop arg\n"); + printk(KERN_ERR + "comedi%d: me4000: me4000_ai_do_cmd_test(): " + "Invalid stop arg\n", dev->minor); cmd->stop_arg = 1; err++; } } if (cmd->scan_end_src == TRIG_COUNT) { if (cmd->scan_end_arg == 0) { - dev_err(dev->class_dev, "Invalid scan end arg\n"); + printk(KERN_ERR + "comedi%d: me4000: me4000_ai_do_cmd_test(): " + "Invalid scan end arg\n", dev->minor); cmd->scan_end_arg = 1; err++; } @@ -1132,7 +1410,8 @@ static irqreturn_t me4000_ai_isr(int irq, void *dev_id) { unsigned int tmp; struct comedi_device *dev = dev_id; - struct comedi_subdevice *s = &dev->subdevices[0]; + struct comedi_subdevice *s = dev->subdevices; + struct me4000_ai_context *ai_context = &info->ai_context; int i; int c = 0; long lval; @@ -1144,15 +1423,17 @@ static irqreturn_t me4000_ai_isr(int irq, void *dev_id) s->async->events = 0; /* Check if irq number is right */ - if (irq != dev->irq) { - dev_err(dev->class_dev, "Incorrect interrupt num: %d\n", irq); + if (irq != ai_context->irq) { + printk(KERN_ERR + "comedi%d: me4000: me4000_ai_isr(): " + "Incorrect interrupt num: %d\n", dev->minor, irq); return IRQ_HANDLED; } - if (inl(dev->iobase + ME4000_IRQ_STATUS_REG) & + if (inl(ai_context->irq_status_reg) & ME4000_IRQ_STATUS_BIT_AI_HF) { /* Read status register to find out what happened */ - tmp = inl(dev->iobase + ME4000_AI_CTRL_REG); + tmp = inl(ai_context->ctrl_reg); if (!(tmp & ME4000_AI_STATUS_BIT_FF_DATA) && !(tmp & ME4000_AI_STATUS_BIT_HF_DATA) && @@ -1166,11 +1447,13 @@ static irqreturn_t me4000_ai_isr(int irq, void *dev_id) tmp |= ME4000_AI_CTRL_BIT_IMMEDIATE_STOP; tmp &= ~(ME4000_AI_CTRL_BIT_HF_IRQ | ME4000_AI_CTRL_BIT_SC_IRQ); - outl(tmp, dev->iobase + ME4000_AI_CTRL_REG); + outl(tmp, ai_context->ctrl_reg); s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA; - dev_err(dev->class_dev, "FIFO overflow\n"); + printk(KERN_ERR + "comedi%d: me4000: me4000_ai_isr(): " + "FIFO overflow\n", dev->minor); } else if ((tmp & ME4000_AI_STATUS_BIT_FF_DATA) && !(tmp & ME4000_AI_STATUS_BIT_HF_DATA) && (tmp & ME4000_AI_STATUS_BIT_EF_DATA)) { @@ -1178,8 +1461,9 @@ static irqreturn_t me4000_ai_isr(int irq, void *dev_id) c = ME4000_AI_FIFO_COUNT / 2; } else { - dev_err(dev->class_dev, - "Can't determine state of fifo\n"); + printk(KERN_ERR + "comedi%d: me4000: me4000_ai_isr(): " + "Can't determine state of fifo\n", dev->minor); c = 0; /* @@ -1189,16 +1473,18 @@ static irqreturn_t me4000_ai_isr(int irq, void *dev_id) tmp |= ME4000_AI_CTRL_BIT_IMMEDIATE_STOP; tmp &= ~(ME4000_AI_CTRL_BIT_HF_IRQ | ME4000_AI_CTRL_BIT_SC_IRQ); - outl(tmp, dev->iobase + ME4000_AI_CTRL_REG); + outl(tmp, ai_context->ctrl_reg); s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA; - dev_err(dev->class_dev, "Undefined FIFO state\n"); + printk(KERN_ERR + "comedi%d: me4000: me4000_ai_isr(): " + "Undefined FIFO state\n", dev->minor); } for (i = 0; i < c; i++) { /* Read value from data fifo */ - lval = inl(dev->iobase + ME4000_AI_DATA_REG) & 0xFFFF; + lval = inl(ai_context->data_reg) & 0xFFFF; lval ^= 0x8000; if (!comedi_buf_put(s->async, lval)) { @@ -1209,11 +1495,13 @@ static irqreturn_t me4000_ai_isr(int irq, void *dev_id) tmp |= ME4000_AI_CTRL_BIT_IMMEDIATE_STOP; tmp &= ~(ME4000_AI_CTRL_BIT_HF_IRQ | ME4000_AI_CTRL_BIT_SC_IRQ); - outl(tmp, dev->iobase + ME4000_AI_CTRL_REG); + outl(tmp, ai_context->ctrl_reg); s->async->events |= COMEDI_CB_OVERFLOW; - dev_err(dev->class_dev, "Buffer overflow\n"); + printk(KERN_ERR + "comedi%d: me4000: me4000_ai_isr(): " + "Buffer overflow\n", dev->minor); break; } @@ -1221,33 +1509,33 @@ static irqreturn_t me4000_ai_isr(int irq, void *dev_id) /* Work is done, so reset the interrupt */ tmp |= ME4000_AI_CTRL_BIT_HF_IRQ_RESET; - outl(tmp, dev->iobase + ME4000_AI_CTRL_REG); + outl(tmp, ai_context->ctrl_reg); tmp &= ~ME4000_AI_CTRL_BIT_HF_IRQ_RESET; - outl(tmp, dev->iobase + ME4000_AI_CTRL_REG); + outl(tmp, ai_context->ctrl_reg); } - if (inl(dev->iobase + ME4000_IRQ_STATUS_REG) & - ME4000_IRQ_STATUS_BIT_SC) { + if (inl(ai_context->irq_status_reg) & ME4000_IRQ_STATUS_BIT_SC) { s->async->events |= COMEDI_CB_BLOCK | COMEDI_CB_EOA; /* * Acquisition is complete, so stop * conversion and disable all interrupts */ - tmp = inl(dev->iobase + ME4000_AI_CTRL_REG); + tmp = inl(ai_context->ctrl_reg); tmp |= ME4000_AI_CTRL_BIT_IMMEDIATE_STOP; tmp &= ~(ME4000_AI_CTRL_BIT_HF_IRQ | ME4000_AI_CTRL_BIT_SC_IRQ); - outl(tmp, dev->iobase + ME4000_AI_CTRL_REG); + outl(tmp, ai_context->ctrl_reg); /* Poll data until fifo empty */ - while (inl(dev->iobase + ME4000_AI_CTRL_REG) & - ME4000_AI_STATUS_BIT_EF_DATA) { + while (inl(ai_context->ctrl_reg) & ME4000_AI_STATUS_BIT_EF_DATA) { /* Read value from data fifo */ - lval = inl(dev->iobase + ME4000_AI_DATA_REG) & 0xFFFF; + lval = inl(ai_context->data_reg) & 0xFFFF; lval ^= 0x8000; if (!comedi_buf_put(s->async, lval)) { - dev_err(dev->class_dev, "Buffer overflow\n"); + printk(KERN_ERR + "comedi%d: me4000: me4000_ai_isr(): " + "Buffer overflow\n", dev->minor); s->async->events |= COMEDI_CB_OVERFLOW; break; } @@ -1255,9 +1543,9 @@ static irqreturn_t me4000_ai_isr(int irq, void *dev_id) /* Work is done, so reset the interrupt */ tmp |= ME4000_AI_CTRL_BIT_SC_IRQ_RESET; - outl(tmp, dev->iobase + ME4000_AI_CTRL_REG); + outl(tmp, ai_context->ctrl_reg); tmp &= ~ME4000_AI_CTRL_BIT_SC_IRQ_RESET; - outl(tmp, dev->iobase + ME4000_AI_CTRL_REG); + outl(tmp, ai_context->ctrl_reg); } if (s->async->events) @@ -1274,8 +1562,7 @@ static int me4000_ao_insn_write(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - const struct me4000_board *thisboard = comedi_board(dev); - struct me4000_info *info = dev->private; + int chan = CR_CHAN(insn->chanspec); int rang = CR_RANGE(insn->chanspec); int aref = CR_AREF(insn->chanspec); @@ -1284,39 +1571,46 @@ static int me4000_ao_insn_write(struct comedi_device *dev, if (insn->n == 0) { return 0; } else if (insn->n > 1) { - dev_err(dev->class_dev, "Invalid instruction length %d\n", - insn->n); + printk(KERN_ERR + "comedi%d: me4000: me4000_ao_insn_write(): " + "Invalid instruction length %d\n", dev->minor, insn->n); return -EINVAL; } - if (chan >= thisboard->ao_nchan) { - dev_err(dev->class_dev, "Invalid channel %d\n", insn->n); + if (chan >= thisboard->ao.count) { + printk(KERN_ERR + "comedi%d: me4000: me4000_ao_insn_write(): " + "Invalid channel %d\n", dev->minor, insn->n); return -EINVAL; } if (rang != 0) { - dev_err(dev->class_dev, "Invalid range %d\n", insn->n); + printk(KERN_ERR + "comedi%d: me4000: me4000_ao_insn_write(): " + "Invalid range %d\n", dev->minor, insn->n); return -EINVAL; } if (aref != AREF_GROUND && aref != AREF_COMMON) { - dev_err(dev->class_dev, "Invalid aref %d\n", insn->n); + printk(KERN_ERR + "comedi%d: me4000: me4000_ao_insn_write(): " + "Invalid aref %d\n", dev->minor, insn->n); return -EINVAL; } /* Stop any running conversion */ - tmp = inl(dev->iobase + ME4000_AO_CTRL_REG(chan)); + tmp = inl(info->ao_context[chan].ctrl_reg); tmp |= ME4000_AO_CTRL_BIT_IMMEDIATE_STOP; - outl(tmp, dev->iobase + ME4000_AO_CTRL_REG(chan)); + outl(tmp, info->ao_context[chan].ctrl_reg); /* Clear control register and set to single mode */ - outl(0x0, dev->iobase + ME4000_AO_CTRL_REG(chan)); + outl(0x0, info->ao_context[chan].ctrl_reg); /* Write data value */ - outl(data[0], dev->iobase + ME4000_AO_SINGLE_REG(chan)); + outl(data[0], info->ao_context[chan].single_reg); /* Store in the mirror */ - info->ao_readback[chan] = data[0]; + info->ao_context[chan].mirror = data[0]; return 1; } @@ -1325,17 +1619,18 @@ static int me4000_ao_insn_read(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - struct me4000_info *info = dev->private; int chan = CR_CHAN(insn->chanspec); if (insn->n == 0) { return 0; } else if (insn->n > 1) { - dev_err(dev->class_dev, "Invalid instruction length\n"); + printk + ("comedi%d: me4000: me4000_ao_insn_read(): " + "Invalid instruction length\n", dev->minor); return -EINVAL; } - data[0] = info->ao_readback[chan]; + data[0] = info->ao_context[chan].mirror; return 1; } @@ -1364,21 +1659,21 @@ static int me4000_dio_insn_bits(struct comedi_device *dev, /* Write out the new digital output lines */ outl((s->state >> 0) & 0xFF, - dev->iobase + ME4000_DIO_PORT_0_REG); + info->dio_context.port_0_reg); outl((s->state >> 8) & 0xFF, - dev->iobase + ME4000_DIO_PORT_1_REG); + info->dio_context.port_1_reg); outl((s->state >> 16) & 0xFF, - dev->iobase + ME4000_DIO_PORT_2_REG); + info->dio_context.port_2_reg); outl((s->state >> 24) & 0xFF, - dev->iobase + ME4000_DIO_PORT_3_REG); + info->dio_context.port_3_reg); } /* On return, data[1] contains the value of the digital input and output lines. */ - data[1] = ((inl(dev->iobase + ME4000_DIO_PORT_0_REG) & 0xFF) << 0) | - ((inl(dev->iobase + ME4000_DIO_PORT_1_REG) & 0xFF) << 8) | - ((inl(dev->iobase + ME4000_DIO_PORT_2_REG) & 0xFF) << 16) | - ((inl(dev->iobase + ME4000_DIO_PORT_3_REG) & 0xFF) << 24); + data[1] = ((inl(info->dio_context.port_0_reg) & 0xFF) << 0) | + ((inl(info->dio_context.port_1_reg) & 0xFF) << 8) | + ((inl(info->dio_context.port_2_reg) & 0xFF) << 16) | + ((inl(info->dio_context.port_3_reg) & 0xFF) << 24); return insn->n; } @@ -1410,7 +1705,7 @@ static int me4000_dio_insn_config(struct comedi_device *dev, * On the ME-4000 it is only possible to switch port wise (8 bit) */ - tmp = inl(dev->iobase + ME4000_DIO_CTRL_REG); + tmp = inl(info->dio_context.ctrl_reg); if (data[0] == INSN_CONFIG_DIO_OUTPUT) { if (chan < 8) { @@ -1424,7 +1719,7 @@ static int me4000_dio_insn_config(struct comedi_device *dev, * If one the first port is a fixed output * port and the second is a fixed input port. */ - if (!inl(dev->iobase + ME4000_DIO_DIR_REG)) + if (!inl(info->dio_context.dir_reg)) return -ENODEV; s->io_bits |= 0xFF00; @@ -1451,7 +1746,7 @@ static int me4000_dio_insn_config(struct comedi_device *dev, * If one the first port is a fixed output * port and the second is a fixed input port. */ - if (!inl(dev->iobase + ME4000_DIO_DIR_REG)) + if (!inl(info->dio_context.dir_reg)) return -ENODEV; s->io_bits &= ~0xFF; @@ -1474,7 +1769,7 @@ static int me4000_dio_insn_config(struct comedi_device *dev, } } - outl(tmp, dev->iobase + ME4000_DIO_CTRL_REG); + outl(tmp, info->dio_context.ctrl_reg); return 1; } @@ -1483,56 +1778,177 @@ static int me4000_dio_insn_config(struct comedi_device *dev, Counter section ===========================================================================*/ +static int cnt_reset(struct comedi_device *dev, unsigned int channel) +{ + switch (channel) { + case 0: + outb(0x30, info->cnt_context.ctrl_reg); + outb(0x00, info->cnt_context.counter_0_reg); + outb(0x00, info->cnt_context.counter_0_reg); + break; + case 1: + outb(0x70, info->cnt_context.ctrl_reg); + outb(0x00, info->cnt_context.counter_1_reg); + outb(0x00, info->cnt_context.counter_1_reg); + break; + case 2: + outb(0xB0, info->cnt_context.ctrl_reg); + outb(0x00, info->cnt_context.counter_2_reg); + outb(0x00, info->cnt_context.counter_2_reg); + break; + default: + printk(KERN_ERR + "comedi%d: me4000: cnt_reset(): Invalid channel\n", + dev->minor); + return -EINVAL; + } + + return 0; +} + +static int cnt_config(struct comedi_device *dev, unsigned int channel, + unsigned int mode) +{ + int tmp = 0; + + switch (channel) { + case 0: + tmp |= ME4000_CNT_COUNTER_0; + break; + case 1: + tmp |= ME4000_CNT_COUNTER_1; + break; + case 2: + tmp |= ME4000_CNT_COUNTER_2; + break; + default: + printk(KERN_ERR + "comedi%d: me4000: cnt_config(): Invalid channel\n", + dev->minor); + return -EINVAL; + } + + switch (mode) { + case 0: + tmp |= ME4000_CNT_MODE_0; + break; + case 1: + tmp |= ME4000_CNT_MODE_1; + break; + case 2: + tmp |= ME4000_CNT_MODE_2; + break; + case 3: + tmp |= ME4000_CNT_MODE_3; + break; + case 4: + tmp |= ME4000_CNT_MODE_4; + break; + case 5: + tmp |= ME4000_CNT_MODE_5; + break; + default: + printk(KERN_ERR + "comedi%d: me4000: cnt_config(): Invalid counter mode\n", + dev->minor); + return -EINVAL; + } + + /* Write the control word */ + tmp |= 0x30; + outb(tmp, info->cnt_context.ctrl_reg); + + return 0; +} + static int me4000_cnt_insn_config(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) + struct comedi_insn *insn, unsigned int *data) { - struct me4000_info *info = dev->private; + int err; switch (data[0]) { case GPCT_RESET: - if (insn->n != 1) + if (insn->n != 1) { + printk(KERN_ERR + "comedi%d: me4000: me4000_cnt_insn_config(): " + "Invalid instruction length%d\n", + dev->minor, insn->n); return -EINVAL; + } - err = i8254_load(info->timer_regbase, 0, insn->chanspec, 0, - I8254_MODE0 | I8254_BINARY); + err = cnt_reset(dev, insn->chanspec); if (err) return err; break; case GPCT_SET_OPERATION: - if (insn->n != 2) + if (insn->n != 2) { + printk(KERN_ERR + "comedi%d: me4000: me4000_cnt_insn_config(): " + "Invalid instruction length%d\n", + dev->minor, insn->n); return -EINVAL; + } - err = i8254_set_mode(info->timer_regbase, 0, insn->chanspec, - (data[1] << 1) | I8254_BINARY); + err = cnt_config(dev, insn->chanspec, data[1]); if (err) return err; break; default: + printk(KERN_ERR + "comedi%d: me4000: me4000_cnt_insn_config(): " + "Invalid instruction\n", dev->minor); return -EINVAL; } - return insn->n; + return 2; } static int me4000_cnt_insn_read(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - struct me4000_info *info = dev->private; + + unsigned short tmp; if (insn->n == 0) return 0; if (insn->n > 1) { - dev_err(dev->class_dev, "Invalid instruction length %d\n", - insn->n); + printk(KERN_ERR + "comedi%d: me4000: me4000_cnt_insn_read(): " + "Invalid instruction length %d\n", + dev->minor, insn->n); return -EINVAL; } - data[0] = i8254_read(info->timer_regbase, 0, insn->chanspec); + switch (insn->chanspec) { + case 0: + tmp = inb(info->cnt_context.counter_0_reg); + data[0] = tmp; + tmp = inb(info->cnt_context.counter_0_reg); + data[0] |= tmp << 8; + break; + case 1: + tmp = inb(info->cnt_context.counter_1_reg); + data[0] = tmp; + tmp = inb(info->cnt_context.counter_1_reg); + data[0] |= tmp << 8; + break; + case 2: + tmp = inb(info->cnt_context.counter_2_reg); + data[0] = tmp; + tmp = inb(info->cnt_context.counter_2_reg); + data[0] |= tmp << 8; + break; + default: + printk(KERN_ERR + "comedi%d: me4000: me4000_cnt_insn_read(): " + "Invalid channel %d\n", + dev->minor, insn->chanspec); + return -EINVAL; + } return 1; } @@ -1541,72 +1957,58 @@ static int me4000_cnt_insn_write(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - struct me4000_info *info = dev->private; + + unsigned short tmp; if (insn->n == 0) { return 0; } else if (insn->n > 1) { - dev_err(dev->class_dev, "Invalid instruction length %d\n", - insn->n); + printk(KERN_ERR + "comedi%d: me4000: me4000_cnt_insn_write(): " + "Invalid instruction length %d\n", + dev->minor, insn->n); return -EINVAL; } - i8254_write(info->timer_regbase, 0, insn->chanspec, data[0]); + switch (insn->chanspec) { + case 0: + tmp = data[0] & 0xFF; + outb(tmp, info->cnt_context.counter_0_reg); + tmp = (data[0] >> 8) & 0xFF; + outb(tmp, info->cnt_context.counter_0_reg); + break; + case 1: + tmp = data[0] & 0xFF; + outb(tmp, info->cnt_context.counter_1_reg); + tmp = (data[0] >> 8) & 0xFF; + outb(tmp, info->cnt_context.counter_1_reg); + break; + case 2: + tmp = data[0] & 0xFF; + outb(tmp, info->cnt_context.counter_2_reg); + tmp = (data[0] >> 8) & 0xFF; + outb(tmp, info->cnt_context.counter_2_reg); + break; + default: + printk(KERN_ERR + "comedi%d: me4000: me4000_cnt_insn_write(): " + "Invalid channel %d\n", + dev->minor, insn->chanspec); + return -EINVAL; + } return 1; } -static const void *me4000_find_boardinfo(struct comedi_device *dev, - struct pci_dev *pcidev) +static int me4000_attach(struct comedi_device *dev, struct comedi_devconfig *it) { - const struct me4000_board *thisboard; - int i; - - for (i = 0; i < ARRAY_SIZE(me4000_boards); i++) { - thisboard = &me4000_boards[i]; - if (thisboard->device_id == pcidev->device) - return thisboard; - } - return NULL; -} - -static int me4000_attach_pci(struct comedi_device *dev, - struct pci_dev *pcidev) -{ - const struct me4000_board *thisboard; - struct me4000_info *info; struct comedi_subdevice *s; int result; - comedi_set_hw_dev(dev, &pcidev->dev); - - thisboard = me4000_find_boardinfo(dev, pcidev); - if (!thisboard) - return -ENODEV; - dev->board_ptr = thisboard; - dev->board_name = thisboard->name; - - result = alloc_private(dev, sizeof(*info)); - if (result) - return result; - info = dev->private; - - result = comedi_pci_enable(pcidev, dev->board_name); - if (result) - return result; - - info->plx_regbase = pci_resource_start(pcidev, 1); - dev->iobase = pci_resource_start(pcidev, 2); - info->timer_regbase = pci_resource_start(pcidev, 3); - if (!info->plx_regbase || !dev->iobase || !info->timer_regbase) - return -ENODEV; - - result = xilinx_download(dev); + result = me4000_probe(dev, it); if (result) return result; - me4000_reset(dev); - result = comedi_alloc_subdevices(dev, 4); if (result) return result; @@ -1615,34 +2017,35 @@ static int me4000_attach_pci(struct comedi_device *dev, Analog input subdevice ========================================================================*/ - s = &dev->subdevices[0]; + s = dev->subdevices + 0; - if (thisboard->ai_nchan) { + if (thisboard->ai.count) { s->type = COMEDI_SUBD_AI; s->subdev_flags = SDF_READABLE | SDF_COMMON | SDF_GROUND | SDF_DIFF; - s->n_chan = thisboard->ai_nchan; + s->n_chan = thisboard->ai.count; s->maxdata = 0xFFFF; /* 16 bit ADC */ s->len_chanlist = ME4000_AI_CHANNEL_LIST_COUNT; s->range_table = &me4000_ai_range; s->insn_read = me4000_ai_insn_read; - if (pcidev->irq > 0) { - if (request_irq(pcidev->irq, me4000_ai_isr, - IRQF_SHARED, dev->board_name, dev)) { - dev_warn(dev->class_dev, - "request_irq failed\n"); + if (info->irq > 0) { + if (request_irq(info->irq, me4000_ai_isr, + IRQF_SHARED, "ME-4000", dev)) { + printk + ("comedi%d: me4000: me4000_attach(): " + "Unable to allocate irq\n", dev->minor); } else { dev->read_subdev = s; s->subdev_flags |= SDF_CMD_READ; s->cancel = me4000_ai_cancel; s->do_cmdtest = me4000_ai_do_cmd_test; s->do_cmd = me4000_ai_do_cmd; - - dev->irq = pcidev->irq; } } else { - dev_warn(dev->class_dev, "No interrupt available\n"); + printk(KERN_WARNING + "comedi%d: me4000: me4000_attach(): " + "No interrupt available\n", dev->minor); } } else { s->type = COMEDI_SUBD_UNUSED; @@ -1652,14 +2055,14 @@ static int me4000_attach_pci(struct comedi_device *dev, Analog output subdevice ========================================================================*/ - s = &dev->subdevices[1]; + s = dev->subdevices + 1; - if (thisboard->ao_nchan) { + if (thisboard->ao.count) { s->type = COMEDI_SUBD_AO; s->subdev_flags = SDF_WRITEABLE | SDF_COMMON | SDF_GROUND; - s->n_chan = thisboard->ao_nchan; + s->n_chan = thisboard->ao.count; s->maxdata = 0xFFFF; /* 16 bit DAC */ - s->range_table = &range_bipolar10; + s->range_table = &me4000_ao_range; s->insn_write = me4000_ao_insn_write; s->insn_read = me4000_ao_insn_read; } else { @@ -1670,12 +2073,12 @@ static int me4000_attach_pci(struct comedi_device *dev, Digital I/O subdevice ========================================================================*/ - s = &dev->subdevices[2]; + s = dev->subdevices + 2; - if (thisboard->dio_nchan) { + if (thisboard->dio.count) { s->type = COMEDI_SUBD_DIO; s->subdev_flags = SDF_READABLE | SDF_WRITABLE; - s->n_chan = thisboard->dio_nchan; + s->n_chan = thisboard->dio.count * 8; s->maxdata = 1; s->range_table = &range_digital; s->insn_bits = me4000_dio_insn_bits; @@ -1688,22 +2091,21 @@ static int me4000_attach_pci(struct comedi_device *dev, * Check for optoisolated ME-4000 version. If one the first * port is a fixed output port and the second is a fixed input port. */ - if (!inl(dev->iobase + ME4000_DIO_DIR_REG)) { + if (!inl(info->dio_context.dir_reg)) { s->io_bits |= 0xFF; - outl(ME4000_DIO_CTRL_BIT_MODE_0, - dev->iobase + ME4000_DIO_DIR_REG); + outl(ME4000_DIO_CTRL_BIT_MODE_0, info->dio_context.dir_reg); } /*========================================================================= Counter subdevice ========================================================================*/ - s = &dev->subdevices[3]; + s = dev->subdevices + 3; - if (thisboard->has_counter) { + if (thisboard->cnt.count) { s->type = COMEDI_SUBD_COUNTER; s->subdev_flags = SDF_READABLE | SDF_WRITABLE; - s->n_chan = 3; + s->n_chan = thisboard->cnt.count; s->maxdata = 0xFFFF; /* 16 bit counters */ s->insn_read = me4000_cnt_insn_read; s->insn_write = me4000_cnt_insn_write; @@ -1717,14 +2119,12 @@ static int me4000_attach_pci(struct comedi_device *dev, static void me4000_detach(struct comedi_device *dev) { - struct pci_dev *pcidev = comedi_to_pci_dev(dev); - - if (dev->irq) - free_irq(dev->irq, dev); - if (pcidev) { - if (dev->iobase) { - me4000_reset(dev); - comedi_pci_disable(pcidev); + if (info) { + if (info->pci_dev_p) { + reset_board(dev); + if (info->plx_regbase) + comedi_pci_disable(info->pci_dev_p); + pci_dev_put(info->pci_dev_p); } } } @@ -1732,7 +2132,7 @@ static void me4000_detach(struct comedi_device *dev) static struct comedi_driver me4000_driver = { .driver_name = "me4000", .module = THIS_MODULE, - .attach_pci = me4000_attach_pci, + .attach = me4000_attach, .detach = me4000_detach, }; @@ -1748,20 +2148,20 @@ static void __devexit me4000_pci_remove(struct pci_dev *dev) } static DEFINE_PCI_DEVICE_TABLE(me4000_pci_table) = { - {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4650)}, - {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4660)}, - {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4660I)}, - {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4660S)}, - {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4660IS)}, - {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4670)}, - {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4670I)}, - {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4670S)}, - {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4670IS)}, - {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4680)}, - {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4680I)}, - {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4680S)}, - {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4680IS)}, - {0} + { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, 0x4650) }, + { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, 0x4660) }, + { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, 0x4661) }, + { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, 0x4662) }, + { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, 0x4663) }, + { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, 0x4670) }, + { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, 0x4671) }, + { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, 0x4672) }, + { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, 0x4673) }, + { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, 0x4680) }, + { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, 0x4681) }, + { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, 0x4682) }, + { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, 0x4683) }, + { 0 } }; MODULE_DEVICE_TABLE(pci, me4000_pci_table); diff --git a/trunk/drivers/staging/comedi/drivers/me4000.h b/trunk/drivers/staging/comedi/drivers/me4000.h new file mode 100644 index 000000000000..5a4df4e4b236 --- /dev/null +++ b/trunk/drivers/staging/comedi/drivers/me4000.h @@ -0,0 +1,409 @@ +/* + me4000.h + Register descriptions and defines for the ME-4000 board family + + COMEDI - Linux Control and Measurement Device Interface + Copyright (C) 1998-9 David A. Schleef + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#ifndef _ME4000_H_ +#define _ME4000_H_ + +/*============================================================================= + PCI vendor and device IDs + ===========================================================================*/ + +#define PCI_VENDOR_ID_MEILHAUS 0x1402 + +#define PCI_DEVICE_ID_MEILHAUS_ME4650 0x4650 /* Low Cost version */ + +#define PCI_DEVICE_ID_MEILHAUS_ME4660 0x4660 /* Standard version */ +#define PCI_DEVICE_ID_MEILHAUS_ME4660I 0x4661 /* Isolated version */ +#define PCI_DEVICE_ID_MEILHAUS_ME4660S 0x4662 /* Standard version with Sample and Hold */ +#define PCI_DEVICE_ID_MEILHAUS_ME4660IS 0x4663 /* Isolated version with Sample and Hold */ + +#define PCI_DEVICE_ID_MEILHAUS_ME4670 0x4670 /* Standard version */ +#define PCI_DEVICE_ID_MEILHAUS_ME4670I 0x4671 /* Isolated version */ +#define PCI_DEVICE_ID_MEILHAUS_ME4670S 0x4672 /* Standard version with Sample and Hold */ +#define PCI_DEVICE_ID_MEILHAUS_ME4670IS 0x4673 /* Isolated version with Sample and Hold */ + +#define PCI_DEVICE_ID_MEILHAUS_ME4680 0x4680 /* Standard version */ +#define PCI_DEVICE_ID_MEILHAUS_ME4680I 0x4681 /* Isolated version */ +#define PCI_DEVICE_ID_MEILHAUS_ME4680S 0x4682 /* Standard version with Sample and Hold */ +#define PCI_DEVICE_ID_MEILHAUS_ME4680IS 0x4683 /* Isolated version with Sample and Hold */ + +/*============================================================================= + ME-4000 base register offsets + ===========================================================================*/ + +#define ME4000_AO_00_CTRL_REG 0x00 /* R/W */ +#define ME4000_AO_00_STATUS_REG 0x04 /* R/_ */ +#define ME4000_AO_00_FIFO_REG 0x08 /* _/W */ +#define ME4000_AO_00_SINGLE_REG 0x0C /* R/W */ +#define ME4000_AO_00_TIMER_REG 0x10 /* _/W */ + +#define ME4000_AO_01_CTRL_REG 0x18 /* R/W */ +#define ME4000_AO_01_STATUS_REG 0x1C /* R/_ */ +#define ME4000_AO_01_FIFO_REG 0x20 /* _/W */ +#define ME4000_AO_01_SINGLE_REG 0x24 /* R/W */ +#define ME4000_AO_01_TIMER_REG 0x28 /* _/W */ + +#define ME4000_AO_02_CTRL_REG 0x30 /* R/W */ +#define ME4000_AO_02_STATUS_REG 0x34 /* R/_ */ +#define ME4000_AO_02_FIFO_REG 0x38 /* _/W */ +#define ME4000_AO_02_SINGLE_REG 0x3C /* R/W */ +#define ME4000_AO_02_TIMER_REG 0x40 /* _/W */ + +#define ME4000_AO_03_CTRL_REG 0x48 /* R/W */ +#define ME4000_AO_03_STATUS_REG 0x4C /* R/_ */ +#define ME4000_AO_03_FIFO_REG 0x50 /* _/W */ +#define ME4000_AO_03_SINGLE_REG 0x54 /* R/W */ +#define ME4000_AO_03_TIMER_REG 0x58 /* _/W */ + +#define ME4000_AI_CTRL_REG 0x74 /* _/W */ +#define ME4000_AI_STATUS_REG 0x74 /* R/_ */ +#define ME4000_AI_CHANNEL_LIST_REG 0x78 /* _/W */ +#define ME4000_AI_DATA_REG 0x7C /* R/_ */ +#define ME4000_AI_CHAN_TIMER_REG 0x80 /* _/W */ +#define ME4000_AI_CHAN_PRE_TIMER_REG 0x84 /* _/W */ +#define ME4000_AI_SCAN_TIMER_LOW_REG 0x88 /* _/W */ +#define ME4000_AI_SCAN_TIMER_HIGH_REG 0x8C /* _/W */ +#define ME4000_AI_SCAN_PRE_TIMER_LOW_REG 0x90 /* _/W */ +#define ME4000_AI_SCAN_PRE_TIMER_HIGH_REG 0x94 /* _/W */ +#define ME4000_AI_START_REG 0x98 /* R/_ */ + +#define ME4000_IRQ_STATUS_REG 0x9C /* R/_ */ + +#define ME4000_DIO_PORT_0_REG 0xA0 /* R/W */ +#define ME4000_DIO_PORT_1_REG 0xA4 /* R/W */ +#define ME4000_DIO_PORT_2_REG 0xA8 /* R/W */ +#define ME4000_DIO_PORT_3_REG 0xAC /* R/W */ +#define ME4000_DIO_DIR_REG 0xB0 /* R/W */ + +#define ME4000_AO_LOADSETREG_XX 0xB4 /* R/W */ + +#define ME4000_DIO_CTRL_REG 0xB8 /* R/W */ + +#define ME4000_AO_DEMUX_ADJUST_REG 0xBC /* -/W */ + +#define ME4000_AI_SAMPLE_COUNTER_REG 0xC0 /* _/W */ + +/*============================================================================= + Value to adjust Demux + ===========================================================================*/ + +#define ME4000_AO_DEMUX_ADJUST_VALUE 0x4C + +/*============================================================================= + Counter base register offsets + ===========================================================================*/ + +#define ME4000_CNT_COUNTER_0_REG 0x00 +#define ME4000_CNT_COUNTER_1_REG 0x01 +#define ME4000_CNT_COUNTER_2_REG 0x02 +#define ME4000_CNT_CTRL_REG 0x03 + +/*============================================================================= + PLX base register offsets + ===========================================================================*/ + +#define PLX_INTCSR 0x4C /* Interrupt control and status register */ +#define PLX_ICR 0x50 /* Initialization control register */ + +/*============================================================================= + Bits for the PLX_ICSR register + ===========================================================================*/ + +#define PLX_INTCSR_LOCAL_INT1_EN 0x01 /* If set, local interrupt 1 is enabled (r/w) */ +#define PLX_INTCSR_LOCAL_INT1_POL 0x02 /* If set, local interrupt 1 polarity is active high (r/w) */ +#define PLX_INTCSR_LOCAL_INT1_STATE 0x04 /* If set, local interrupt 1 is active (r/_) */ +#define PLX_INTCSR_LOCAL_INT2_EN 0x08 /* If set, local interrupt 2 is enabled (r/w) */ +#define PLX_INTCSR_LOCAL_INT2_POL 0x10 /* If set, local interrupt 2 polarity is active high (r/w) */ +#define PLX_INTCSR_LOCAL_INT2_STATE 0x20 /* If set, local interrupt 2 is active (r/_) */ +#define PLX_INTCSR_PCI_INT_EN 0x40 /* If set, PCI interrupt is enabled (r/w) */ +#define PLX_INTCSR_SOFT_INT 0x80 /* If set, a software interrupt is generated (r/w) */ + +/*============================================================================= + Bits for the PLX_ICR register + ===========================================================================*/ + +#define PLX_ICR_BIT_EEPROM_CLOCK_SET 0x01000000 +#define PLX_ICR_BIT_EEPROM_CHIP_SELECT 0x02000000 +#define PLX_ICR_BIT_EEPROM_WRITE 0x04000000 +#define PLX_ICR_BIT_EEPROM_READ 0x08000000 +#define PLX_ICR_BIT_EEPROM_VALID 0x10000000 + +#define PLX_ICR_MASK_EEPROM 0x1F000000 + +#define EEPROM_DELAY 1 + +/*============================================================================= + Bits for the ME4000_AO_CTRL_REG register + ===========================================================================*/ + +#define ME4000_AO_CTRL_BIT_MODE_0 0x001 +#define ME4000_AO_CTRL_BIT_MODE_1 0x002 +#define ME4000_AO_CTRL_MASK_MODE 0x003 +#define ME4000_AO_CTRL_BIT_STOP 0x004 +#define ME4000_AO_CTRL_BIT_ENABLE_FIFO 0x008 +#define ME4000_AO_CTRL_BIT_ENABLE_EX_TRIG 0x010 +#define ME4000_AO_CTRL_BIT_EX_TRIG_EDGE 0x020 +#define ME4000_AO_CTRL_BIT_IMMEDIATE_STOP 0x080 +#define ME4000_AO_CTRL_BIT_ENABLE_DO 0x100 +#define ME4000_AO_CTRL_BIT_ENABLE_IRQ 0x200 +#define ME4000_AO_CTRL_BIT_RESET_IRQ 0x400 + +/*============================================================================= + Bits for the ME4000_AO_STATUS_REG register + ===========================================================================*/ + +#define ME4000_AO_STATUS_BIT_FSM 0x01 +#define ME4000_AO_STATUS_BIT_FF 0x02 +#define ME4000_AO_STATUS_BIT_HF 0x04 +#define ME4000_AO_STATUS_BIT_EF 0x08 + +/*============================================================================= + Bits for the ME4000_AI_CTRL_REG register + ===========================================================================*/ + +#define ME4000_AI_CTRL_BIT_MODE_0 0x00000001 +#define ME4000_AI_CTRL_BIT_MODE_1 0x00000002 +#define ME4000_AI_CTRL_BIT_MODE_2 0x00000004 +#define ME4000_AI_CTRL_BIT_SAMPLE_HOLD 0x00000008 +#define ME4000_AI_CTRL_BIT_IMMEDIATE_STOP 0x00000010 +#define ME4000_AI_CTRL_BIT_STOP 0x00000020 +#define ME4000_AI_CTRL_BIT_CHANNEL_FIFO 0x00000040 +#define ME4000_AI_CTRL_BIT_DATA_FIFO 0x00000080 +#define ME4000_AI_CTRL_BIT_FULLSCALE 0x00000100 +#define ME4000_AI_CTRL_BIT_OFFSET 0x00000200 +#define ME4000_AI_CTRL_BIT_EX_TRIG_ANALOG 0x00000400 +#define ME4000_AI_CTRL_BIT_EX_TRIG 0x00000800 +#define ME4000_AI_CTRL_BIT_EX_TRIG_FALLING 0x00001000 +#define ME4000_AI_CTRL_BIT_EX_IRQ 0x00002000 +#define ME4000_AI_CTRL_BIT_EX_IRQ_RESET 0x00004000 +#define ME4000_AI_CTRL_BIT_LE_IRQ 0x00008000 +#define ME4000_AI_CTRL_BIT_LE_IRQ_RESET 0x00010000 +#define ME4000_AI_CTRL_BIT_HF_IRQ 0x00020000 +#define ME4000_AI_CTRL_BIT_HF_IRQ_RESET 0x00040000 +#define ME4000_AI_CTRL_BIT_SC_IRQ 0x00080000 +#define ME4000_AI_CTRL_BIT_SC_IRQ_RESET 0x00100000 +#define ME4000_AI_CTRL_BIT_SC_RELOAD 0x00200000 +#define ME4000_AI_CTRL_BIT_EX_TRIG_BOTH 0x80000000 + +/*============================================================================= + Bits for the ME4000_AI_STATUS_REG register + ===========================================================================*/ + +#define ME4000_AI_STATUS_BIT_EF_CHANNEL 0x00400000 +#define ME4000_AI_STATUS_BIT_HF_CHANNEL 0x00800000 +#define ME4000_AI_STATUS_BIT_FF_CHANNEL 0x01000000 +#define ME4000_AI_STATUS_BIT_EF_DATA 0x02000000 +#define ME4000_AI_STATUS_BIT_HF_DATA 0x04000000 +#define ME4000_AI_STATUS_BIT_FF_DATA 0x08000000 +#define ME4000_AI_STATUS_BIT_LE 0x10000000 +#define ME4000_AI_STATUS_BIT_FSM 0x20000000 + +/*============================================================================= + Bits for the ME4000_IRQ_STATUS_REG register + ===========================================================================*/ + +#define ME4000_IRQ_STATUS_BIT_EX 0x01 +#define ME4000_IRQ_STATUS_BIT_LE 0x02 +#define ME4000_IRQ_STATUS_BIT_AI_HF 0x04 +#define ME4000_IRQ_STATUS_BIT_AO_0_HF 0x08 +#define ME4000_IRQ_STATUS_BIT_AO_1_HF 0x10 +#define ME4000_IRQ_STATUS_BIT_AO_2_HF 0x20 +#define ME4000_IRQ_STATUS_BIT_AO_3_HF 0x40 +#define ME4000_IRQ_STATUS_BIT_SC 0x80 + +/*============================================================================= + Bits for the ME4000_DIO_CTRL_REG register + ===========================================================================*/ + +#define ME4000_DIO_CTRL_BIT_MODE_0 0x0001 +#define ME4000_DIO_CTRL_BIT_MODE_1 0x0002 +#define ME4000_DIO_CTRL_BIT_MODE_2 0x0004 +#define ME4000_DIO_CTRL_BIT_MODE_3 0x0008 +#define ME4000_DIO_CTRL_BIT_MODE_4 0x0010 +#define ME4000_DIO_CTRL_BIT_MODE_5 0x0020 +#define ME4000_DIO_CTRL_BIT_MODE_6 0x0040 +#define ME4000_DIO_CTRL_BIT_MODE_7 0x0080 + +#define ME4000_DIO_CTRL_BIT_FUNCTION_0 0x0100 +#define ME4000_DIO_CTRL_BIT_FUNCTION_1 0x0200 + +#define ME4000_DIO_CTRL_BIT_FIFO_HIGH_0 0x0400 +#define ME4000_DIO_CTRL_BIT_FIFO_HIGH_1 0x0800 +#define ME4000_DIO_CTRL_BIT_FIFO_HIGH_2 0x1000 +#define ME4000_DIO_CTRL_BIT_FIFO_HIGH_3 0x2000 + +/*============================================================================= + Information about the hardware capabilities + ===========================================================================*/ + +struct me4000_ao_info { + int count; + int fifo_count; +}; + +struct me4000_ai_info { + int count; + int sh_count; + int diff_count; + int ex_trig_analog; +}; + +struct me4000_dio_info { + int count; +}; + +struct me4000_cnt_info { + int count; +}; + +struct me4000_board { + const char *name; + unsigned short device_id; + struct me4000_ao_info ao; + struct me4000_ai_info ai; + struct me4000_dio_info dio; + struct me4000_cnt_info cnt; +}; + +#define thisboard ((const struct me4000_board *)dev->board_ptr) + +/*============================================================================= + Global board and subdevice information structures + ===========================================================================*/ + +struct me4000_ao_context { + int irq; + + unsigned long mirror; /* Store the last written value */ + + unsigned long ctrl_reg; + unsigned long status_reg; + unsigned long fifo_reg; + unsigned long single_reg; + unsigned long timer_reg; + unsigned long irq_status_reg; + unsigned long preload_reg; +}; + +struct me4000_ai_context { + int irq; + + unsigned long ctrl_reg; + unsigned long status_reg; + unsigned long channel_list_reg; + unsigned long data_reg; + unsigned long chan_timer_reg; + unsigned long chan_pre_timer_reg; + unsigned long scan_timer_low_reg; + unsigned long scan_timer_high_reg; + unsigned long scan_pre_timer_low_reg; + unsigned long scan_pre_timer_high_reg; + unsigned long start_reg; + unsigned long irq_status_reg; + unsigned long sample_counter_reg; +}; + +struct me4000_dio_context { + unsigned long dir_reg; + unsigned long ctrl_reg; + unsigned long port_0_reg; + unsigned long port_1_reg; + unsigned long port_2_reg; + unsigned long port_3_reg; +}; + +struct me4000_cnt_context { + unsigned long ctrl_reg; + unsigned long counter_0_reg; + unsigned long counter_1_reg; + unsigned long counter_2_reg; +}; + +struct me4000_info { + unsigned long plx_regbase; /* PLX configuration space base address */ + unsigned long me4000_regbase; /* Base address of the ME4000 */ + unsigned long timer_regbase; /* Base address of the timer circuit */ + unsigned long program_regbase; /* Base address to set the program pin for the xilinx */ + + unsigned long plx_regbase_size; /* PLX register set space */ + unsigned long me4000_regbase_size; /* ME4000 register set space */ + unsigned long timer_regbase_size; /* Timer circuit register set space */ + unsigned long program_regbase_size; /* Size of program base address of the ME4000 */ + + unsigned int serial_no; /* Serial number of the board */ + unsigned char hw_revision; /* Hardware revision of the board */ + unsigned short vendor_id; /* Meilhaus vendor id */ + unsigned short device_id; /* Device id */ + + struct pci_dev *pci_dev_p; /* General PCI information */ + + unsigned int irq; /* IRQ assigned from the PCI BIOS */ + + struct me4000_ai_context ai_context; /* Analog input specific context */ + struct me4000_ao_context ao_context[4]; /* Vector with analog output specific context */ + struct me4000_dio_context dio_context; /* Digital I/O specific context */ + struct me4000_cnt_context cnt_context; /* Counter specific context */ +}; + +#define info ((struct me4000_info *)dev->private) + +/*----------------------------------------------------------------------------- + Defines for analog input + ----------------------------------------------------------------------------*/ + +/* General stuff */ +#define ME4000_AI_FIFO_COUNT 2048 + +#define ME4000_AI_MIN_TICKS 66 +#define ME4000_AI_MIN_SAMPLE_TIME 2000 /* Minimum sample time [ns] */ +#define ME4000_AI_BASE_FREQUENCY (unsigned int) 33E6 + +/* Channel list defines and masks */ +#define ME4000_AI_CHANNEL_LIST_COUNT 1024 + +#define ME4000_AI_LIST_INPUT_SINGLE_ENDED 0x000 +#define ME4000_AI_LIST_INPUT_DIFFERENTIAL 0x020 + +#define ME4000_AI_LIST_RANGE_BIPOLAR_10 0x000 +#define ME4000_AI_LIST_RANGE_BIPOLAR_2_5 0x040 +#define ME4000_AI_LIST_RANGE_UNIPOLAR_10 0x080 +#define ME4000_AI_LIST_RANGE_UNIPOLAR_2_5 0x0C0 + +#define ME4000_AI_LIST_LAST_ENTRY 0x100 + +/*----------------------------------------------------------------------------- + Defines for counters + ----------------------------------------------------------------------------*/ + +#define ME4000_CNT_COUNTER_0 0x00 +#define ME4000_CNT_COUNTER_1 0x40 +#define ME4000_CNT_COUNTER_2 0x80 + +#define ME4000_CNT_MODE_0 0x00 /* Change state if zero crossing */ +#define ME4000_CNT_MODE_1 0x02 /* Retriggerable One-Shot */ +#define ME4000_CNT_MODE_2 0x04 /* Asymmetrical divider */ +#define ME4000_CNT_MODE_3 0x06 /* Symmetrical divider */ +#define ME4000_CNT_MODE_4 0x08 /* Counter start by software trigger */ +#define ME4000_CNT_MODE_5 0x0A /* Counter start by hardware trigger */ + +#endif diff --git a/trunk/drivers/staging/comedi/drivers/me_daq.c b/trunk/drivers/staging/comedi/drivers/me_daq.c index 2ce0b14af589..8c6f8b93b277 100644 --- a/trunk/drivers/staging/comedi/drivers/me_daq.c +++ b/trunk/drivers/staging/comedi/drivers/me_daq.c @@ -41,14 +41,22 @@ Configuration options: If bus/slot is not specified, the first available PCI device will be used. + +The 2600 requires a firmware upload, which can be accomplished +using the -i or --init-data option of comedi_config. +The firmware can be +found in the comedi_nonfree_firmware tarball available +from http://www.comedi.org + */ #include #include -#include #include "../comedidev.h" -#define ME2600_FIRMWARE "me2600_firmware.bin" +/*#include "me2600_fw.h" */ + +#define ME_DRIVER_NAME "me_daq" #define PCI_VENDOR_ID_MEILHAUS 0x1402 #define ME2000_DEVICE_ID 0x2000 @@ -190,7 +198,8 @@ struct me_board { static const struct me_board me_boards[] = { { - .name = "me-2600i", + /* -- ME-2600i -- */ + .name = ME_DRIVER_NAME, .device_id = ME2600_DEVICE_ID, /* Analog Output */ .ao_channel_nbr = 4, @@ -205,7 +214,8 @@ static const struct me_board me_boards[] = { .dio_channel_nbr = 32, }, { - .name = "me-2000i", + /* -- ME-2000i -- */ + .name = ME_DRIVER_NAME, .device_id = ME2000_DEVICE_ID, /* Analog Output */ .ao_channel_nbr = 0, @@ -331,7 +341,7 @@ static int me_dio_insn_bits(struct comedi_device *dev, /* Analog instant input */ static int me_ai_insn_read(struct comedi_device *dev, - struct comedi_subdevice *s, + struct comedi_subdevice *subdevice, struct comedi_insn *insn, unsigned int *data) { unsigned short value; @@ -425,7 +435,7 @@ static int me_ai_do_cmd_test(struct comedi_device *dev, /* Analog input command */ static int me_ai_do_cmd(struct comedi_device *dev, - struct comedi_subdevice *s) + struct comedi_subdevice *subdevice) { return 0; } @@ -514,7 +524,8 @@ static int me_ao_insn_read(struct comedi_device *dev, /* Xilinx firmware download for card: ME-2600i */ static int me2600_xilinx_download(struct comedi_device *dev, - const u8 *data, size_t size) + unsigned char *me2600_firmware, + unsigned int length) { unsigned int value; unsigned int file_length; @@ -541,20 +552,19 @@ static int me2600_xilinx_download(struct comedi_device *dev, * Byte 8-11: date * Byte 12-15: reserved */ - if (size < 16) + if (length < 16) return -EINVAL; - - file_length = (((unsigned int)data[0] & 0xff) << 24) + - (((unsigned int)data[1] & 0xff) << 16) + - (((unsigned int)data[2] & 0xff) << 8) + - ((unsigned int)data[3] & 0xff); + file_length = (((unsigned int)me2600_firmware[0] & 0xff) << 24) + + (((unsigned int)me2600_firmware[1] & 0xff) << 16) + + (((unsigned int)me2600_firmware[2] & 0xff) << 8) + + ((unsigned int)me2600_firmware[3] & 0xff); /* * Loop for writing firmware byte by byte to xilinx * Firmware data start at offfset 16 */ for (i = 0; i < file_length; i++) - writeb((data[16 + i] & 0xff), + writeb((me2600_firmware[16 + i] & 0xff), dev_private->me_regbase + 0x0); /* Write 5 dummy values to xilinx */ @@ -580,22 +590,6 @@ static int me2600_xilinx_download(struct comedi_device *dev, return 0; } -static int me2600_upload_firmware(struct comedi_device *dev) -{ - struct pci_dev *pcidev = comedi_to_pci_dev(dev); - const struct firmware *fw; - int ret; - - ret = request_firmware(&fw, ME2600_FIRMWARE, &pcidev->dev); - if (ret) - return ret; - - ret = me2600_xilinx_download(dev, fw->data, fw->size); - release_firmware(fw); - - return ret; -} - /* Reset device */ static int me_reset(struct comedi_device *dev) { @@ -613,24 +607,44 @@ static int me_reset(struct comedi_device *dev) return 0; } -static const void *me_find_boardinfo(struct comedi_device *dev, - struct pci_dev *pcidev) +static struct pci_dev *me_find_pci_dev(struct comedi_device *dev, + struct comedi_devconfig *it) { const struct me_board *board; + struct pci_dev *pcidev = NULL; + int bus = it->options[0]; + int slot = it->options[1]; int i; - for (i = 0; i < ARRAY_SIZE(me_boards); i++) { - board = &me_boards[i]; - if (board->device_id == pcidev->device) - return board; + for_each_pci_dev(pcidev) { + if (bus || slot) { + if (pcidev->bus->number != bus || + PCI_SLOT(pcidev->devfn) != slot) + continue; + } + if (pcidev->vendor != PCI_VENDOR_ID_MEILHAUS) + continue; + + for (i = 0; i < ARRAY_SIZE(me_boards); i++) { + board = &me_boards[i]; + if (board->device_id != pcidev->device) + continue; + + dev->board_ptr = board; + return pcidev; + } } + dev_err(dev->class_dev, + "No supported board found! (req. bus %d, slot %d)\n", + bus, slot); return NULL; } -static int me_attach_pci(struct comedi_device *dev, struct pci_dev *pcidev) +static int me_attach(struct comedi_device *dev, struct comedi_devconfig *it) { - const struct me_board *board; - struct comedi_subdevice *s; + struct pci_dev *pci_device; + struct comedi_subdevice *subdevice; + struct me_board *board; resource_size_t plx_regbase_tmp; unsigned long plx_regbase_size_tmp; resource_size_t me_regbase_tmp; @@ -640,28 +654,29 @@ static int me_attach_pci(struct comedi_device *dev, struct pci_dev *pcidev) resource_size_t regbase_tmp; int result, error; - comedi_set_hw_dev(dev, &pcidev->dev); - - board = me_find_boardinfo(dev, pcidev); - if (!board) - return -ENODEV; - dev->board_ptr = board; - dev->board_name = board->name; - /* Allocate private memory */ if (alloc_private(dev, sizeof(struct me_private_data)) < 0) return -ENOMEM; + pci_device = me_find_pci_dev(dev, it); + if (!pci_device) + return -EIO; + comedi_set_hw_dev(dev, &pci_device->dev); + board = (struct me_board *)dev->board_ptr; + /* Enable PCI device and request PCI regions */ - if (comedi_pci_enable(pcidev, dev->board_name) < 0) { + if (comedi_pci_enable(pci_device, ME_DRIVER_NAME) < 0) { printk(KERN_ERR "comedi%d: Failed to enable PCI device and " "request regions\n", dev->minor); return -EIO; } + /* Set data in device structure */ + dev->board_name = board->name; + /* Read PLX register base address [PCI_BASE_ADDRESS #0]. */ - plx_regbase_tmp = pci_resource_start(pcidev, 0); - plx_regbase_size_tmp = pci_resource_len(pcidev, 0); + plx_regbase_tmp = pci_resource_start(pci_device, 0); + plx_regbase_size_tmp = pci_resource_len(pci_device, 0); dev_private->plx_regbase = ioremap(plx_regbase_tmp, plx_regbase_size_tmp); dev_private->plx_regbase_size = plx_regbase_size_tmp; @@ -672,8 +687,8 @@ static int me_attach_pci(struct comedi_device *dev, struct pci_dev *pcidev) /* Read Swap base address [PCI_BASE_ADDRESS #5]. */ - swap_regbase_tmp = pci_resource_start(pcidev, 5); - swap_regbase_size_tmp = pci_resource_len(pcidev, 5); + swap_regbase_tmp = pci_resource_start(pci_device, 5); + swap_regbase_size_tmp = pci_resource_len(pci_device, 5); if (!swap_regbase_tmp) printk(KERN_ERR "comedi%d: Swap not present\n", dev->minor); @@ -687,20 +702,20 @@ static int me_attach_pci(struct comedi_device *dev, struct pci_dev *pcidev) plx_regbase_tmp = swap_regbase_tmp; swap_regbase_tmp = regbase_tmp; - result = pci_write_config_dword(pcidev, + result = pci_write_config_dword(pci_device, PCI_BASE_ADDRESS_0, plx_regbase_tmp); if (result != PCIBIOS_SUCCESSFUL) return -EIO; - result = pci_write_config_dword(pcidev, + result = pci_write_config_dword(pci_device, PCI_BASE_ADDRESS_5, swap_regbase_tmp); if (result != PCIBIOS_SUCCESSFUL) return -EIO; } else { plx_regbase_tmp -= 0x80; - result = pci_write_config_dword(pcidev, + result = pci_write_config_dword(pci_device, PCI_BASE_ADDRESS_0, plx_regbase_tmp); if (result != PCIBIOS_SUCCESSFUL) @@ -711,8 +726,8 @@ static int me_attach_pci(struct comedi_device *dev, struct pci_dev *pcidev) /* Read Meilhaus register base address [PCI_BASE_ADDRESS #2]. */ - me_regbase_tmp = pci_resource_start(pcidev, 2); - me_regbase_size_tmp = pci_resource_len(pcidev, 2); + me_regbase_tmp = pci_resource_start(pci_device, 2); + me_regbase_size_tmp = pci_resource_len(pci_device, 2); dev_private->me_regbase_size = me_regbase_size_tmp; dev_private->me_regbase = ioremap(me_regbase_tmp, me_regbase_size_tmp); if (!dev_private->me_regbase) { @@ -720,55 +735,64 @@ static int me_attach_pci(struct comedi_device *dev, struct pci_dev *pcidev) dev->minor); return -ENOMEM; } - /* Download firmware and reset card */ if (board->device_id == ME2600_DEVICE_ID) { - result = me2600_upload_firmware(dev); - if (result < 0) - return result; + unsigned char *aux_data; + int aux_len; + + aux_data = comedi_aux_data(it->options, 0); + aux_len = it->options[COMEDI_DEVCONF_AUX_DATA_LENGTH]; + + if (!aux_data || aux_len < 1) { + comedi_error(dev, "You must provide me2600 firmware " + "using the --init-data option of " + "comedi_config"); + return -EINVAL; + } + me2600_xilinx_download(dev, aux_data, aux_len); } + me_reset(dev); error = comedi_alloc_subdevices(dev, 3); if (error) return error; - s = &dev->subdevices[0]; - s->type = COMEDI_SUBD_AI; - s->subdev_flags = SDF_READABLE | SDF_COMMON | SDF_CMD_READ; - s->n_chan = board->ai_channel_nbr; - s->maxdata = board->ai_resolution_mask; - s->len_chanlist = board->ai_channel_nbr; - s->range_table = board->ai_range_list; - s->cancel = me_ai_cancel; - s->insn_read = me_ai_insn_read; - s->do_cmdtest = me_ai_do_cmd_test; - s->do_cmd = me_ai_do_cmd; - - s = &dev->subdevices[1]; - s->type = COMEDI_SUBD_AO; - s->subdev_flags = SDF_WRITEABLE | SDF_COMMON; - s->n_chan = board->ao_channel_nbr; - s->maxdata = board->ao_resolution_mask; - s->len_chanlist = board->ao_channel_nbr; - s->range_table = board->ao_range_list; - s->insn_read = me_ao_insn_read; - s->insn_write = me_ao_insn_write; - - s = &dev->subdevices[2]; - s->type = COMEDI_SUBD_DIO; - s->subdev_flags = SDF_READABLE | SDF_WRITEABLE; - s->n_chan = board->dio_channel_nbr; - s->maxdata = 1; - s->len_chanlist = board->dio_channel_nbr; - s->range_table = &range_digital; - s->insn_bits = me_dio_insn_bits; - s->insn_config = me_dio_insn_config; - s->io_bits = 0; - - dev_info(dev->class_dev, "%s: %s attached\n", - dev->driver->driver_name, dev->board_name); - + subdevice = dev->subdevices + 0; + subdevice->type = COMEDI_SUBD_AI; + subdevice->subdev_flags = SDF_READABLE | SDF_COMMON | SDF_CMD_READ; + subdevice->n_chan = board->ai_channel_nbr; + subdevice->maxdata = board->ai_resolution_mask; + subdevice->len_chanlist = board->ai_channel_nbr; + subdevice->range_table = board->ai_range_list; + subdevice->cancel = me_ai_cancel; + subdevice->insn_read = me_ai_insn_read; + subdevice->do_cmdtest = me_ai_do_cmd_test; + subdevice->do_cmd = me_ai_do_cmd; + + subdevice = dev->subdevices + 1; + subdevice->type = COMEDI_SUBD_AO; + subdevice->subdev_flags = SDF_WRITEABLE | SDF_COMMON; + subdevice->n_chan = board->ao_channel_nbr; + subdevice->maxdata = board->ao_resolution_mask; + subdevice->len_chanlist = board->ao_channel_nbr; + subdevice->range_table = board->ao_range_list; + subdevice->insn_read = me_ao_insn_read; + subdevice->insn_write = me_ao_insn_write; + + subdevice = dev->subdevices + 2; + subdevice->type = COMEDI_SUBD_DIO; + subdevice->subdev_flags = SDF_READABLE | SDF_WRITEABLE; + subdevice->n_chan = board->dio_channel_nbr; + subdevice->maxdata = 1; + subdevice->len_chanlist = board->dio_channel_nbr; + subdevice->range_table = &range_digital; + subdevice->insn_bits = me_dio_insn_bits; + subdevice->insn_config = me_dio_insn_config; + subdevice->io_bits = 0; + + printk(KERN_INFO "comedi%d: " ME_DRIVER_NAME " attached.\n", + dev->minor); return 0; } @@ -794,7 +818,7 @@ static void me_detach(struct comedi_device *dev) static struct comedi_driver me_daq_driver = { .driver_name = "me_daq", .module = THIS_MODULE, - .attach_pci = me_attach_pci, + .attach = me_attach, .detach = me_detach, }; @@ -827,4 +851,3 @@ module_comedi_pci_driver(me_daq_driver, me_daq_pci_driver); MODULE_AUTHOR("Comedi http://www.comedi.org"); MODULE_DESCRIPTION("Comedi low-level driver"); MODULE_LICENSE("GPL"); -MODULE_FIRMWARE(ME2600_FIRMWARE); diff --git a/trunk/drivers/staging/comedi/drivers/mite.c b/trunk/drivers/staging/comedi/drivers/mite.c index e27850f628ce..a93166d6a8f8 100644 --- a/trunk/drivers/staging/comedi/drivers/mite.c +++ b/trunk/drivers/staging/comedi/drivers/mite.c @@ -49,8 +49,6 @@ /* #define USE_KMALLOC */ -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - #include "mite.h" #include "comedi_fc.h" @@ -61,38 +59,52 @@ #define PCI_DAQ_SIZE 4096 #define PCI_DAQ_SIZE_660X 8192 +struct mite_struct *mite_devices; +EXPORT_SYMBOL(mite_devices); + #define TOP_OF_PAGE(x) ((x)|(~(PAGE_MASK))) -struct mite_struct *mite_alloc(struct pci_dev *pcidev) +void mite_init(void) { + struct pci_dev *pcidev = NULL; struct mite_struct *mite; - unsigned int i; - - mite = kzalloc(sizeof(*mite), GFP_KERNEL); - if (mite) { - spin_lock_init(&mite->lock); - mite->pcidev = pcidev; - for (i = 0; i < MAX_MITE_DMA_CHANNELS; ++i) { - mite->channels[i].mite = mite; - mite->channels[i].channel = i; - mite->channels[i].done = 1; + + for_each_pci_dev(pcidev) { + if (pcidev->vendor == PCI_VENDOR_ID_NI) { + unsigned i; + + mite = kzalloc(sizeof(*mite), GFP_KERNEL); + if (!mite) { + printk(KERN_ERR "mite: allocation failed\n"); + pci_dev_put(pcidev); + return; + } + spin_lock_init(&mite->lock); + mite->pcidev = pci_dev_get(pcidev); + for (i = 0; i < MAX_MITE_DMA_CHANNELS; ++i) { + mite->channels[i].mite = mite; + mite->channels[i].channel = i; + mite->channels[i].done = 1; + } + mite->next = mite_devices; + mite_devices = mite; } } - return mite; } -EXPORT_SYMBOL(mite_alloc); static void dump_chip_signature(u32 csigr_bits) { - pr_info("version = %i, type = %i, mite mode = %i, interface mode = %i\n", - mite_csigr_version(csigr_bits), mite_csigr_type(csigr_bits), - mite_csigr_mmode(csigr_bits), mite_csigr_imode(csigr_bits)); - pr_info("num channels = %i, write post fifo depth = %i, wins = %i, iowins = %i\n", - mite_csigr_dmac(csigr_bits), mite_csigr_wpdep(csigr_bits), - mite_csigr_wins(csigr_bits), mite_csigr_iowins(csigr_bits)); + printk(KERN_INFO "mite: version = %i, type = %i, mite mode = %i," + "interface mode = %i\n", + mite_csigr_version(csigr_bits), mite_csigr_type(csigr_bits), + mite_csigr_mmode(csigr_bits), mite_csigr_imode(csigr_bits)); + printk(KERN_INFO "mite: num channels = %i, write post fifo depth = %i," + "wins = %i, iowins = %i\n", + mite_csigr_dmac(csigr_bits), mite_csigr_wpdep(csigr_bits), + mite_csigr_wins(csigr_bits), mite_csigr_iowins(csigr_bits)); } -static unsigned mite_fifo_size(struct mite_struct *mite, unsigned channel) +unsigned mite_fifo_size(struct mite_struct *mite, unsigned channel) { unsigned fcr_bits = readl(mite->mite_io_addr + MITE_FCR(channel)); unsigned empty_count = (fcr_bits >> 16) & 0xff; @@ -109,8 +121,7 @@ int mite_setup2(struct mite_struct *mite, unsigned use_iodwbsr_1) unsigned unknown_dma_burst_bits; if (comedi_pci_enable(mite->pcidev, "mite")) { - dev_err(&mite->pcidev->dev, - "error enabling mite and requesting io regions\n"); + printk(KERN_ERR "error enabling mite and requesting io regions\n"); return -EIO; } pci_set_master(mite->pcidev); @@ -119,10 +130,11 @@ int mite_setup2(struct mite_struct *mite, unsigned use_iodwbsr_1) mite->mite_phys_addr = addr; mite->mite_io_addr = ioremap(addr, PCI_MITE_SIZE); if (!mite->mite_io_addr) { - dev_err(&mite->pcidev->dev, - "Failed to remap mite io memory address\n"); + printk(KERN_ERR "Failed to remap mite io memory address\n"); return -ENOMEM; } + printk(KERN_INFO "MITE:0x%08llx mapped to %p ", + (unsigned long long)mite->mite_phys_addr, mite->mite_io_addr); addr = pci_resource_start(mite->pcidev, 1); mite->daq_phys_addr = addr; @@ -133,15 +145,15 @@ int mite_setup2(struct mite_struct *mite, unsigned use_iodwbsr_1) */ mite->daq_io_addr = ioremap(mite->daq_phys_addr, length); if (!mite->daq_io_addr) { - dev_err(&mite->pcidev->dev, - "Failed to remap daq io memory address\n"); + printk(KERN_ERR "Failed to remap daq io memory address\n"); return -ENOMEM; } + printk(KERN_INFO "DAQ:0x%08llx mapped to %p\n", + (unsigned long long)mite->daq_phys_addr, mite->daq_io_addr); if (use_iodwbsr_1) { writel(0, mite->mite_io_addr + MITE_IODWBSR); - dev_info(&mite->pcidev->dev, - "using I/O Window Base Size register 1\n"); + printk(KERN_INFO "mite: using I/O Window Base Size register 1\n"); writel(mite->daq_phys_addr | WENAB | MITE_IODWBSR_1_WSIZE_bits(length), mite->mite_io_addr + MITE_IODWBSR_1); @@ -166,9 +178,9 @@ int mite_setup2(struct mite_struct *mite, unsigned use_iodwbsr_1) csigr_bits = readl(mite->mite_io_addr + MITE_CSIGR); mite->num_channels = mite_csigr_dmac(csigr_bits); if (mite->num_channels > MAX_MITE_DMA_CHANNELS) { - dev_warn(&mite->pcidev->dev, - "mite: bug? chip claims to have %i dma channels. Setting to %i.\n", - mite->num_channels, MAX_MITE_DMA_CHANNELS); + printk(KERN_WARNING "mite: bug? chip claims to have %i dma " + "channels. Setting to %i.\n", + mite->num_channels, MAX_MITE_DMA_CHANNELS); mite->num_channels = MAX_MITE_DMA_CHANNELS; } dump_chip_signature(csigr_bits); @@ -181,7 +193,9 @@ int mite_setup2(struct mite_struct *mite, unsigned use_iodwbsr_1) mite->mite_io_addr + MITE_CHCR(i)); } mite->fifo_size = mite_fifo_size(mite, 0); - dev_info(&mite->pcidev->dev, "fifo size is %i.\n", mite->fifo_size); + printk(KERN_INFO "mite: fifo size is %i.\n", mite->fifo_size); + mite->used = 1; + return 0; } EXPORT_SYMBOL(mite_setup2); @@ -192,6 +206,17 @@ int mite_setup(struct mite_struct *mite) } EXPORT_SYMBOL(mite_setup); +void mite_cleanup(void) +{ + struct mite_struct *mite, *next; + + for (mite = mite_devices; mite; mite = next) { + pci_dev_put(mite->pcidev); + next = mite->next; + kfree(mite); + } +} + void mite_unsetup(struct mite_struct *mite) { /* unsigned long offset, start, length; */ @@ -211,43 +236,26 @@ void mite_unsetup(struct mite_struct *mite) comedi_pci_disable(mite->pcidev); mite->mite_phys_addr = 0; } + + mite->used = 0; } EXPORT_SYMBOL(mite_unsetup); -struct mite_dma_descriptor_ring *mite_alloc_ring(struct mite_struct *mite) -{ - struct mite_dma_descriptor_ring *ring = - kmalloc(sizeof(struct mite_dma_descriptor_ring), GFP_KERNEL); - - if (ring == NULL) - return ring; - ring->hw_dev = get_device(&mite->pcidev->dev); - if (ring->hw_dev == NULL) { - kfree(ring); - return NULL; - } - ring->n_links = 0; - ring->descriptors = NULL; - ring->descriptors_dma_addr = 0; - return ring; -}; -EXPORT_SYMBOL(mite_alloc_ring); - -void mite_free_ring(struct mite_dma_descriptor_ring *ring) +void mite_list_devices(void) { - if (ring) { - if (ring->descriptors) { - dma_free_coherent(ring->hw_dev, - ring->n_links * - sizeof(struct mite_dma_descriptor), - ring->descriptors, - ring->descriptors_dma_addr); + struct mite_struct *mite, *next; + + printk(KERN_INFO "Available NI device IDs:"); + if (mite_devices) + for (mite = mite_devices; mite; mite = next) { + next = mite->next; + printk(KERN_INFO " 0x%04x", mite_device_id(mite)); + if (mite->used) + printk(KERN_INFO "(used)"); } - put_device(ring->hw_dev); - kfree(ring); - } -}; -EXPORT_SYMBOL(mite_free_ring); + printk(KERN_INFO "\n"); +} +EXPORT_SYMBOL(mite_list_devices); struct mite_channel *mite_request_channel_in_range(struct mite_struct *mite, struct @@ -309,7 +317,7 @@ void mite_dma_arm(struct mite_channel *mite_chan) int chor; unsigned long flags; - MDPRINTK("mite_dma_arm ch%i\n", mite_chan->channel); + MDPRINTK("mite_dma_arm ch%i\n", channel); /* * memory barrier is intended to insure any twiddling with the buffer * is done before writing to the mite to arm dma transfer @@ -357,8 +365,7 @@ int mite_buf_change(struct mite_dma_descriptor_ring *ring, n_links * sizeof(struct mite_dma_descriptor), &ring->descriptors_dma_addr, GFP_KERNEL); if (!ring->descriptors) { - dev_err(async->subdevice->device->class_dev, - "mite: ring buffer allocation failed\n"); + printk(KERN_ERR "mite: ring buffer allocation failed\n"); return -ENOMEM; } ring->n_links = n_links; @@ -435,7 +442,8 @@ void mite_prep_dma(struct mite_channel *mite_chan, mcr |= CR_PSIZE32; break; default: - pr_warn("bug! invalid mem bit width for dma transfer\n"); + printk(KERN_WARNING "mite: bug! invalid mem bit width for dma " + "transfer\n"); break; } writel(mcr, mite->mite_io_addr + MITE_MCR(mite_chan->channel)); @@ -454,7 +462,8 @@ void mite_prep_dma(struct mite_channel *mite_chan, dcr |= CR_PSIZE32; break; default: - pr_warn("bug! invalid dev bit width for dma transfer\n"); + printk(KERN_WARNING "mite: bug! invalid dev bit width for dma " + "transfer\n"); break; } writel(dcr, mite->mite_io_addr + MITE_DCR(mite_chan->channel)); @@ -474,7 +483,7 @@ void mite_prep_dma(struct mite_channel *mite_chan, } EXPORT_SYMBOL(mite_prep_dma); -static u32 mite_device_bytes_transferred(struct mite_channel *mite_chan) +u32 mite_device_bytes_transferred(struct mite_channel *mite_chan) { struct mite_struct *mite = mite_chan->mite; return readl(mite->mite_io_addr + MITE_DAR(mite_chan->channel)); @@ -568,8 +577,7 @@ int mite_sync_input_dma(struct mite_channel *mite_chan, nbytes = mite_bytes_written_to_memory_lb(mite_chan); if ((int)(mite_bytes_written_to_memory_ub(mite_chan) - old_alloc_count) > 0) { - dev_warn(async->subdevice->device->class_dev, - "mite: DMA overwrite of free area\n"); + printk("mite: DMA overwrite of free area\n"); async->events |= COMEDI_CB_OVERFLOW; return -1; } @@ -613,8 +621,7 @@ int mite_sync_output_dma(struct mite_channel *mite_chan, (int)(nbytes_ub - stop_count) > 0) nbytes_ub = stop_count; if ((int)(nbytes_ub - old_alloc_count) > 0) { - dev_warn(async->subdevice->device->class_dev, - "mite: DMA underrun\n"); + printk(KERN_ERR "mite: DMA underrun\n"); async->events |= COMEDI_CB_OVERFLOW; return -1; } @@ -665,6 +672,8 @@ EXPORT_SYMBOL(mite_done); #ifdef DEBUG_MITE +static void mite_decode(char **bit_str, unsigned int bits); + /* names of bits in mite registers */ static const char *const mite_CHOR_strings[] = { @@ -734,80 +743,86 @@ static const char *const mite_CHSR_strings[] = { "28", "lpauses", "30", "int", }; -static void mite_decode(const char *const *bit_str, unsigned int bits) +void mite_dump_regs(struct mite_channel *mite_chan) +{ + unsigned long mite_io_addr = + (unsigned long)mite_chan->mite->mite_io_addr; + unsigned long addr = 0; + unsigned long temp = 0; + + printk(KERN_DEBUG "mite_dump_regs ch%i\n", mite_chan->channel); + printk(KERN_DEBUG "mite address is =0x%08lx\n", mite_io_addr); + + addr = mite_io_addr + MITE_CHOR(channel); + printk(KERN_DEBUG "mite status[CHOR]at 0x%08lx =0x%08lx\n", addr, + temp = readl(addr)); + mite_decode(mite_CHOR_strings, temp); + addr = mite_io_addr + MITE_CHCR(channel); + printk(KERN_DEBUG "mite status[CHCR]at 0x%08lx =0x%08lx\n", addr, + temp = readl(addr)); + mite_decode(mite_CHCR_strings, temp); + addr = mite_io_addr + MITE_TCR(channel); + printk(KERN_DEBUG "mite status[TCR] at 0x%08lx =0x%08x\n", addr, + readl(addr)); + addr = mite_io_addr + MITE_MCR(channel); + printk(KERN_DEBUG "mite status[MCR] at 0x%08lx =0x%08lx\n", addr, + temp = readl(addr)); + mite_decode(mite_MCR_strings, temp); + + addr = mite_io_addr + MITE_MAR(channel); + printk(KERN_DEBUG "mite status[MAR] at 0x%08lx =0x%08x\n", addr, + readl(addr)); + addr = mite_io_addr + MITE_DCR(channel); + printk(KERN_DEBUG "mite status[DCR] at 0x%08lx =0x%08lx\n", addr, + temp = readl(addr)); + mite_decode(mite_DCR_strings, temp); + addr = mite_io_addr + MITE_DAR(channel); + printk(KERN_DEBUG "mite status[DAR] at 0x%08lx =0x%08x\n", addr, + readl(addr)); + addr = mite_io_addr + MITE_LKCR(channel); + printk(KERN_DEBUG "mite status[LKCR]at 0x%08lx =0x%08lx\n", addr, + temp = readl(addr)); + mite_decode(mite_LKCR_strings, temp); + addr = mite_io_addr + MITE_LKAR(channel); + printk(KERN_DEBUG "mite status[LKAR]at 0x%08lx =0x%08x\n", addr, + readl(addr)); + addr = mite_io_addr + MITE_CHSR(channel); + printk(KERN_DEBUG "mite status[CHSR]at 0x%08lx =0x%08lx\n", addr, + temp = readl(addr)); + mite_decode(mite_CHSR_strings, temp); + addr = mite_io_addr + MITE_FCR(channel); + printk(KERN_DEBUG "mite status[FCR] at 0x%08lx =0x%08x\n\n", addr, + readl(addr)); +} +EXPORT_SYMBOL(mite_dump_regs); + +static void mite_decode(char **bit_str, unsigned int bits) { int i; for (i = 31; i >= 0; i--) { if (bits & (1 << i)) - pr_debug(" %s\n", bit_str[i]); + printk(KERN_DEBUG " %s", bit_str[i]); } + printk(KERN_DEBUG "\n"); } - -void mite_dump_regs(struct mite_channel *mite_chan) -{ - void __iomem *mite_io_addr = mite_chan->mite->mite_io_addr; - unsigned int offset; - unsigned int value; - int channel = mite_chan->channel; - - pr_debug("mite_dump_regs ch%i\n", channel); - pr_debug("mite address is =%p\n", mite_io_addr); - - offset = MITE_CHOR(channel); - value = readl(mite_io_addr + offset); - pr_debug("mite status[CHOR] at 0x%08x =0x%08x\n", offset, value); - mite_decode(mite_CHOR_strings, value); - offset = MITE_CHCR(channel); - value = readl(mite_io_addr + offset); - pr_debug("mite status[CHCR] at 0x%08x =0x%08x\n", offset, value); - mite_decode(mite_CHCR_strings, value); - offset = MITE_TCR(channel); - value = readl(mite_io_addr + offset); - pr_debug("mite status[TCR] at 0x%08x =0x%08x\n", offset, value); - offset = MITE_MCR(channel); - value = readl(mite_io_addr + offset); - pr_debug("mite status[MCR] at 0x%08x =0x%08x\n", offset, value); - mite_decode(mite_MCR_strings, value); - offset = MITE_MAR(channel); - value = readl(mite_io_addr + offset); - pr_debug("mite status[MAR] at 0x%08x =0x%08x\n", offset, value); - offset = MITE_DCR(channel); - value = readl(mite_io_addr + offset); - pr_debug("mite status[DCR] at 0x%08x =0x%08x\n", offset, value); - mite_decode(mite_DCR_strings, value); - offset = MITE_DAR(channel); - value = readl(mite_io_addr + offset); - pr_debug("mite status[DAR] at 0x%08x =0x%08x\n", offset, value); - offset = MITE_LKCR(channel); - value = readl(mite_io_addr + offset); - pr_debug("mite status[LKCR] at 0x%08x =0x%08x\n", offset, value); - mite_decode(mite_LKCR_strings, value); - offset = MITE_LKAR(channel); - value = readl(mite_io_addr + offset); - pr_debug("mite status[LKAR] at 0x%08x =0x%08x\n", offset, value); - offset = MITE_CHSR(channel); - value = readl(mite_io_addr + offset); - pr_debug("mite status[CHSR] at 0x%08x =0x%08x\n", offset, value); - mite_decode(mite_CHSR_strings, value); - offset = MITE_FCR(channel); - value = readl(mite_io_addr + offset); - pr_debug("mite status[FCR] at 0x%08x =0x%08x\n", offset, value); -} -EXPORT_SYMBOL(mite_dump_regs); +EXPORT_SYMBOL(mite_decode); #endif -static int __init mite_module_init(void) +#ifdef MODULE +int __init init_module(void) { + mite_init(); + mite_list_devices(); + return 0; } -static void __exit mite_module_exit(void) +void __exit cleanup_module(void) { + mite_cleanup(); } - -module_init(mite_module_init); -module_exit(mite_module_exit); +#endif MODULE_AUTHOR("Comedi http://www.comedi.org"); MODULE_DESCRIPTION("Comedi low-level driver"); diff --git a/trunk/drivers/staging/comedi/drivers/mite.h b/trunk/drivers/staging/comedi/drivers/mite.h index 255b8ba9c917..83f1b27a4720 100644 --- a/trunk/drivers/staging/comedi/drivers/mite.h +++ b/trunk/drivers/staging/comedi/drivers/mite.h @@ -25,16 +25,15 @@ #define _MITE_H_ #include -#include #include "../comedidev.h" /* #define DEBUG_MITE */ #define PCIMIO_COMPAT #ifdef DEBUG_MITE -#define MDPRINTK(format, args...) pr_debug(format , ## args) +#define MDPRINTK(format, args...) printk(format , ## args) #else -#define MDPRINTK(format, args...) do { } while (0) +#define MDPRINTK(format, args...) #endif #define MAX_MITE_DMA_CHANNELS 8 @@ -62,11 +61,15 @@ struct mite_channel { }; struct mite_struct { + struct mite_struct *next; + int used; + struct pci_dev *pcidev; resource_size_t mite_phys_addr; void __iomem *mite_io_addr; resource_size_t daq_phys_addr; void __iomem *daq_io_addr; + struct mite_channel channels[MAX_MITE_DMA_CHANNELS]; short channel_allocated[MAX_MITE_DMA_CHANNELS]; int num_channels; @@ -74,12 +77,41 @@ struct mite_struct { spinlock_t lock; }; -struct mite_struct *mite_alloc(struct pci_dev *pcidev); - -static inline void mite_free(struct mite_struct *mite) +static inline struct mite_dma_descriptor_ring *mite_alloc_ring(struct + mite_struct + *mite) { - kfree(mite); -} + struct mite_dma_descriptor_ring *ring = + kmalloc(sizeof(struct mite_dma_descriptor_ring), GFP_KERNEL); + if (ring == NULL) + return ring; + ring->hw_dev = get_device(&mite->pcidev->dev); + if (ring->hw_dev == NULL) { + kfree(ring); + return NULL; + } + ring->n_links = 0; + ring->descriptors = NULL; + ring->descriptors_dma_addr = 0; + return ring; +}; + +static inline void mite_free_ring(struct mite_dma_descriptor_ring *ring) +{ + if (ring) { + if (ring->descriptors) { + dma_free_coherent(ring->hw_dev, + ring->n_links * + sizeof(struct mite_dma_descriptor), + ring->descriptors, + ring->descriptors_dma_addr); + } + put_device(ring->hw_dev); + kfree(ring); + } +}; + +extern struct mite_struct *mite_devices; static inline unsigned int mite_irq(struct mite_struct *mite) { @@ -91,11 +123,12 @@ static inline unsigned int mite_device_id(struct mite_struct *mite) return mite->pcidev->device; }; +void mite_init(void); +void mite_cleanup(void); int mite_setup(struct mite_struct *mite); int mite_setup2(struct mite_struct *mite, unsigned use_iodwbsr_1); void mite_unsetup(struct mite_struct *mite); -struct mite_dma_descriptor_ring *mite_alloc_ring(struct mite_struct *mite); -void mite_free_ring(struct mite_dma_descriptor_ring *ring); +void mite_list_devices(void); struct mite_channel *mite_request_channel_in_range(struct mite_struct *mite, struct mite_dma_descriptor_ring @@ -246,9 +279,8 @@ enum MITE_IODWBSR_bits { static inline unsigned MITE_IODWBSR_1_WSIZE_bits(unsigned size) { unsigned order = 0; - - BUG_ON(size == 0); - order = ilog2(size); + while (size >>= 1) + ++order; BUG_ON(order < 1); return (order - 1) & 0x1f; } @@ -395,10 +427,12 @@ static inline int CR_RL(unsigned int retry_limit) { int value = 0; - if (retry_limit) - value = 1 + ilog2(retry_limit); + while (retry_limit) { + retry_limit >>= 1; + value++; + } if (value > 0x7) - value = 0x7; + printk("comedi: bug! retry_limit too large\n"); return (value & 0x7) << 21; } diff --git a/trunk/drivers/staging/comedi/drivers/mpc624.c b/trunk/drivers/staging/comedi/drivers/mpc624.c index f8b7faefc961..b928b6763cd5 100644 --- a/trunk/drivers/staging/comedi/drivers/mpc624.c +++ b/trunk/drivers/staging/comedi/drivers/mpc624.c @@ -353,7 +353,7 @@ static int mpc624_attach(struct comedi_device *dev, struct comedi_devconfig *it) if (ret) return ret; - s = &dev->subdevices[0]; + s = dev->subdevices + 0; s->type = COMEDI_SUBD_AI; s->subdev_flags = SDF_READABLE | SDF_DIFF; s->n_chan = 8; diff --git a/trunk/drivers/staging/comedi/drivers/mpc8260cpm.c b/trunk/drivers/staging/comedi/drivers/mpc8260cpm.c index c0c33299b7f1..a7fda8f01e8c 100644 --- a/trunk/drivers/staging/comedi/drivers/mpc8260cpm.c +++ b/trunk/drivers/staging/comedi/drivers/mpc8260cpm.c @@ -137,7 +137,7 @@ static int mpc8260cpm_attach(struct comedi_device *dev, return ret; for (i = 0; i < 4; i++) { - s = &dev->subdevices[i]; + s = dev->subdevices + i; s->type = COMEDI_SUBD_DIO; s->subdev_flags = SDF_READABLE | SDF_WRITABLE; s->n_chan = 32; diff --git a/trunk/drivers/staging/comedi/drivers/multiq3.c b/trunk/drivers/staging/comedi/drivers/multiq3.c index 4625cb4d07c6..eccbe1fb4f2c 100644 --- a/trunk/drivers/staging/comedi/drivers/multiq3.c +++ b/trunk/drivers/staging/comedi/drivers/multiq3.c @@ -204,10 +204,8 @@ static int multiq3_encoder_insn_read(struct comedi_device *dev, static void encoder_reset(struct comedi_device *dev) { - struct comedi_subdevice *s = &dev->subdevices[4]; int chan; - - for (chan = 0; chan < s->n_chan; chan++) { + for (chan = 0; chan < dev->subdevices[4].n_chan; chan++) { int control = MULTIQ3_CONTROL_MUST | MULTIQ3_AD_MUX_EN | (chan << 3); outw(control, dev->iobase + MULTIQ3_CONTROL); @@ -260,7 +258,7 @@ static int multiq3_attach(struct comedi_device *dev, if (result < 0) return result; - s = &dev->subdevices[0]; + s = dev->subdevices + 0; /* ai subdevice */ s->type = COMEDI_SUBD_AI; s->subdev_flags = SDF_READABLE | SDF_GROUND; @@ -269,7 +267,7 @@ static int multiq3_attach(struct comedi_device *dev, s->maxdata = 0x1fff; s->range_table = &range_bipolar5; - s = &dev->subdevices[1]; + s = dev->subdevices + 1; /* ao subdevice */ s->type = COMEDI_SUBD_AO; s->subdev_flags = SDF_WRITABLE; @@ -279,7 +277,7 @@ static int multiq3_attach(struct comedi_device *dev, s->maxdata = 0xfff; s->range_table = &range_bipolar5; - s = &dev->subdevices[2]; + s = dev->subdevices + 2; /* di subdevice */ s->type = COMEDI_SUBD_DI; s->subdev_flags = SDF_READABLE; @@ -288,7 +286,7 @@ static int multiq3_attach(struct comedi_device *dev, s->maxdata = 1; s->range_table = &range_digital; - s = &dev->subdevices[3]; + s = dev->subdevices + 3; /* do subdevice */ s->type = COMEDI_SUBD_DO; s->subdev_flags = SDF_WRITABLE; @@ -298,7 +296,7 @@ static int multiq3_attach(struct comedi_device *dev, s->range_table = &range_digital; s->state = 0; - s = &dev->subdevices[4]; + s = dev->subdevices + 4; /* encoder (counter) subdevice */ s->type = COMEDI_SUBD_COUNTER; s->subdev_flags = SDF_READABLE | SDF_LSAMPL; diff --git a/trunk/drivers/staging/comedi/drivers/ni_6527.c b/trunk/drivers/staging/comedi/drivers/ni_6527.c index 51295f32ee89..a80c52fb2731 100644 --- a/trunk/drivers/staging/comedi/drivers/ni_6527.c +++ b/trunk/drivers/staging/comedi/drivers/ni_6527.c @@ -44,11 +44,8 @@ Updated: Sat, 25 Jan 2003 13:24:40 -0800 #include #include "../comedidev.h" -#include "comedi_fc.h" #include "mite.h" -#define DRIVER_NAME "ni_6527" - #define NI6527_DIO_SIZE 4096 #define NI6527_MITE_SIZE 4096 @@ -79,6 +76,16 @@ Updated: Sat, 25 Jan 2003 13:24:40 -0800 #define Rising_Edge_Detection_Enable(x) (0x018+(x)) #define Falling_Edge_Detection_Enable(x) (0x020+(x)) +static int ni6527_attach(struct comedi_device *dev, + struct comedi_devconfig *it); +static void ni6527_detach(struct comedi_device *dev); +static struct comedi_driver driver_ni6527 = { + .driver_name = "ni6527", + .module = THIS_MODULE, + .attach = ni6527_attach, + .detach = ni6527_detach, +}; + struct ni6527_board { int dev_id; @@ -96,6 +103,7 @@ static const struct ni6527_board ni6527_boards[] = { }, }; +#define n_ni6527_boards ARRAY_SIZE(ni6527_boards) #define this_board ((const struct ni6527_board *)dev->board_ptr) static DEFINE_PCI_DEVICE_TABLE(ni6527_pci_table) = { @@ -114,6 +122,8 @@ struct ni6527_private { #define devpriv ((struct ni6527_private *)dev->private) +static int ni6527_find_device(struct comedi_device *dev, int bus, int slot); + static int ni6527_di_insn_config(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) @@ -202,7 +212,7 @@ static int ni6527_do_insn_bits(struct comedi_device *dev, static irqreturn_t ni6527_interrupt(int irq, void *d) { struct comedi_device *dev = d; - struct comedi_subdevice *s = &dev->subdevices[2]; + struct comedi_subdevice *s = dev->subdevices + 2; unsigned int status; status = readb(devpriv->mite->daq_io_addr + Change_Status); @@ -225,20 +235,40 @@ static int ni6527_intr_cmdtest(struct comedi_device *dev, struct comedi_cmd *cmd) { int err = 0; + int tmp; + + /* step 1: make sure trigger sources are trivially valid */ + + tmp = cmd->start_src; + cmd->start_src &= TRIG_NOW; + if (!cmd->start_src || tmp != cmd->start_src) + err++; + + tmp = cmd->scan_begin_src; + cmd->scan_begin_src &= TRIG_OTHER; + if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) + err++; - /* Step 1 : check if triggers are trivially valid */ + tmp = cmd->convert_src; + cmd->convert_src &= TRIG_FOLLOW; + if (!cmd->convert_src || tmp != cmd->convert_src) + err++; + + tmp = cmd->scan_end_src; + cmd->scan_end_src &= TRIG_COUNT; + if (!cmd->scan_end_src || tmp != cmd->scan_end_src) + err++; - err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW); - err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_OTHER); - err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_FOLLOW); - err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT); - err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT); + tmp = cmd->stop_src; + cmd->stop_src &= TRIG_COUNT; + if (!cmd->stop_src || tmp != cmd->stop_src) + err++; if (err) return 1; - /* Step 2a : make sure trigger sources are unique */ - /* Step 2b : and mutually compatible */ + /* step 2: make sure trigger sources are unique and */ + /* are mutually compatible */ if (err) return 2; @@ -334,53 +364,36 @@ static int ni6527_intr_insn_config(struct comedi_device *dev, return 2; } -static const struct ni6527_board * -ni6527_find_boardinfo(struct pci_dev *pcidev) -{ - unsigned int dev_id = pcidev->device; - unsigned int n; - - for (n = 0; n < ARRAY_SIZE(ni6527_boards); n++) { - const struct ni6527_board *board = &ni6527_boards[n]; - if (board->dev_id == dev_id) - return board; - } - return NULL; -} - -static int __devinit ni6527_attach_pci(struct comedi_device *dev, - struct pci_dev *pcidev) +static int ni6527_attach(struct comedi_device *dev, struct comedi_devconfig *it) { struct comedi_subdevice *s; int ret; + printk(KERN_INFO "comedi%d: ni6527\n", dev->minor); + ret = alloc_private(dev, sizeof(struct ni6527_private)); if (ret < 0) return ret; - dev->board_ptr = ni6527_find_boardinfo(pcidev); - if (!dev->board_ptr) - return -ENODEV; - - devpriv->mite = mite_alloc(pcidev); - if (!devpriv->mite) - return -ENOMEM; + ret = ni6527_find_device(dev, it->options[0], it->options[1]); + if (ret < 0) + return ret; ret = mite_setup(devpriv->mite); if (ret < 0) { - dev_err(dev->class_dev, "error setting up mite\n"); + printk(KERN_ERR "comedi: error setting up mite\n"); return ret; } dev->board_name = this_board->name; - dev_info(dev->class_dev, "board: %s, ID=0x%02x\n", dev->board_name, - readb(devpriv->mite->daq_io_addr + ID_Register)); + printk(KERN_INFO "comedi board: %s, ID=0x%02x\n", dev->board_name, + readb(devpriv->mite->daq_io_addr + ID_Register)); ret = comedi_alloc_subdevices(dev, 3); if (ret) return ret; - s = &dev->subdevices[0]; + s = dev->subdevices + 0; s->type = COMEDI_SUBD_DI; s->subdev_flags = SDF_READABLE; s->n_chan = 24; @@ -389,7 +402,7 @@ static int __devinit ni6527_attach_pci(struct comedi_device *dev, s->insn_config = ni6527_di_insn_config; s->insn_bits = ni6527_di_insn_bits; - s = &dev->subdevices[1]; + s = dev->subdevices + 1; s->type = COMEDI_SUBD_DO; s->subdev_flags = SDF_READABLE | SDF_WRITABLE; s->n_chan = 24; @@ -397,7 +410,7 @@ static int __devinit ni6527_attach_pci(struct comedi_device *dev, s->maxdata = 1; s->insn_bits = ni6527_do_insn_bits; - s = &dev->subdevices[2]; + s = dev->subdevices + 2; dev->read_subdev = s; s->type = COMEDI_SUBD_DI; s->subdev_flags = SDF_READABLE | SDF_CMD_READ; @@ -419,9 +432,9 @@ static int __devinit ni6527_attach_pci(struct comedi_device *dev, writeb(0x00, devpriv->mite->daq_io_addr + Master_Interrupt_Control); ret = request_irq(mite_irq(devpriv->mite), ni6527_interrupt, - IRQF_SHARED, DRIVER_NAME, dev); + IRQF_SHARED, "ni6527", dev); if (ret < 0) - dev_warn(dev->class_dev, "irq not available\n"); + printk(KERN_WARNING "comedi i6527 irq not available\n"); else dev->irq = mite_irq(devpriv->mite); @@ -435,37 +448,73 @@ static void ni6527_detach(struct comedi_device *dev) devpriv->mite->daq_io_addr + Master_Interrupt_Control); if (dev->irq) free_irq(dev->irq, dev); - if (devpriv && devpriv->mite) { + if (devpriv && devpriv->mite) mite_unsetup(devpriv->mite); - mite_free(devpriv->mite); - } } -static struct comedi_driver ni6527_driver = { - .driver_name = DRIVER_NAME, - .module = THIS_MODULE, - .attach_pci = ni6527_attach_pci, - .detach = ni6527_detach, -}; +static int ni6527_find_device(struct comedi_device *dev, int bus, int slot) +{ + struct mite_struct *mite; + int i; + + for (mite = mite_devices; mite; mite = mite->next) { + if (mite->used) + continue; + if (bus || slot) { + if (bus != mite->pcidev->bus->number || + slot != PCI_SLOT(mite->pcidev->devfn)) + continue; + } + for (i = 0; i < n_ni6527_boards; i++) { + if (mite_device_id(mite) == ni6527_boards[i].dev_id) { + dev->board_ptr = ni6527_boards + i; + devpriv->mite = mite; + return 0; + } + } + } + printk(KERN_ERR "comedi 6527: no device found\n"); + mite_list_devices(); + return -EIO; +} -static int __devinit ni6527_pci_probe(struct pci_dev *dev, - const struct pci_device_id *ent) +static int __devinit driver_ni6527_pci_probe(struct pci_dev *dev, + const struct pci_device_id *ent) { - return comedi_pci_auto_config(dev, &ni6527_driver); + return comedi_pci_auto_config(dev, &driver_ni6527); } -static void __devexit ni6527_pci_remove(struct pci_dev *dev) +static void __devexit driver_ni6527_pci_remove(struct pci_dev *dev) { comedi_pci_auto_unconfig(dev); } -static struct pci_driver ni6527_pci_driver = { - .name = DRIVER_NAME, +static struct pci_driver driver_ni6527_pci_driver = { .id_table = ni6527_pci_table, - .probe = ni6527_pci_probe, - .remove = __devexit_p(ni6527_pci_remove) + .probe = &driver_ni6527_pci_probe, + .remove = __devexit_p(&driver_ni6527_pci_remove) }; -module_comedi_pci_driver(ni6527_driver, ni6527_pci_driver); + +static int __init driver_ni6527_init_module(void) +{ + int retval; + + retval = comedi_driver_register(&driver_ni6527); + if (retval < 0) + return retval; + + driver_ni6527_pci_driver.name = (char *)driver_ni6527.driver_name; + return pci_register_driver(&driver_ni6527_pci_driver); +} + +static void __exit driver_ni6527_cleanup_module(void) +{ + pci_unregister_driver(&driver_ni6527_pci_driver); + comedi_driver_unregister(&driver_ni6527); +} + +module_init(driver_ni6527_init_module); +module_exit(driver_ni6527_cleanup_module); MODULE_AUTHOR("Comedi http://www.comedi.org"); MODULE_DESCRIPTION("Comedi low-level driver"); diff --git a/trunk/drivers/staging/comedi/drivers/ni_65xx.c b/trunk/drivers/staging/comedi/drivers/ni_65xx.c index 2a73ff57a2fb..bce39f1ea36d 100644 --- a/trunk/drivers/staging/comedi/drivers/ni_65xx.c +++ b/trunk/drivers/staging/comedi/drivers/ni_65xx.c @@ -55,7 +55,6 @@ except maybe the 6514. #include #include "../comedidev.h" -#include "comedi_fc.h" #include "mite.h" #define NI6514_DIO_SIZE 4096 @@ -110,7 +109,18 @@ static inline unsigned Filter_Enable(unsigned port) #define OverflowIntEnable 0x02 #define EdgeIntEnable 0x01 +static int ni_65xx_attach(struct comedi_device *dev, + struct comedi_devconfig *it); +static void ni_65xx_detach(struct comedi_device *dev); +static struct comedi_driver driver_ni_65xx = { + .driver_name = "ni_65xx", + .module = THIS_MODULE, + .attach = ni_65xx_attach, + .detach = ni_65xx_detach, +}; + struct ni_65xx_board { + int dev_id; const char *name; unsigned num_dio_ports; @@ -315,6 +325,8 @@ static struct ni_65xx_subdevice_private *ni_65xx_alloc_subdevice_private(void) return subdev_private; } +static int ni_65xx_find_device(struct comedi_device *dev, int bus, int slot); + static int ni_65xx_config_filter(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) @@ -441,9 +453,11 @@ static int ni_65xx_dio_insn_bits(struct comedi_device *dev, writeb(bits, private(dev)->mite->daq_io_addr + Port_Data(port)); +/* printk("wrote 0x%x to port %i\n", bits, port); */ } port_read_bits = readb(private(dev)->mite->daq_io_addr + Port_Data(port)); +/* printk("read 0x%x from port %i\n", port_read_bits, port); */ if (s->type == COMEDI_SUBD_DO && board(dev)->invert_outputs) { /* Outputs inverted, so invert value read back from * DO subdevice. (Does not apply to boards with DIO @@ -464,7 +478,7 @@ static int ni_65xx_dio_insn_bits(struct comedi_device *dev, static irqreturn_t ni_65xx_interrupt(int irq, void *d) { struct comedi_device *dev = d; - struct comedi_subdevice *s = &dev->subdevices[2]; + struct comedi_subdevice *s = dev->subdevices + 2; unsigned int status; status = readb(private(dev)->mite->daq_io_addr + Change_Status); @@ -487,20 +501,40 @@ static int ni_65xx_intr_cmdtest(struct comedi_device *dev, struct comedi_cmd *cmd) { int err = 0; + int tmp; + + /* step 1: make sure trigger sources are trivially valid */ + + tmp = cmd->start_src; + cmd->start_src &= TRIG_NOW; + if (!cmd->start_src || tmp != cmd->start_src) + err++; + + tmp = cmd->scan_begin_src; + cmd->scan_begin_src &= TRIG_OTHER; + if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) + err++; - /* Step 1 : check if triggers are trivially valid */ + tmp = cmd->convert_src; + cmd->convert_src &= TRIG_FOLLOW; + if (!cmd->convert_src || tmp != cmd->convert_src) + err++; + + tmp = cmd->scan_end_src; + cmd->scan_end_src &= TRIG_COUNT; + if (!cmd->scan_end_src || tmp != cmd->scan_end_src) + err++; - err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW); - err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_OTHER); - err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_FOLLOW); - err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT); - err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT); + tmp = cmd->stop_src; + cmd->stop_src &= TRIG_COUNT; + if (!cmd->stop_src || tmp != cmd->stop_src) + err++; if (err) return 1; - /* Step 2a : make sure trigger sources are unique */ - /* Step 2b : and mutually compatible */ + /* step 2: make sure trigger sources are unique and mutually + compatible */ if (err) return 2; @@ -610,55 +644,41 @@ static int ni_65xx_intr_insn_config(struct comedi_device *dev, return 2; } -static const struct ni_65xx_board * -ni_65xx_find_boardinfo(struct pci_dev *pcidev) -{ - unsigned int dev_id = pcidev->device; - unsigned int n; - - for (n = 0; n < ARRAY_SIZE(ni_65xx_boards); n++) { - const struct ni_65xx_board *board = &ni_65xx_boards[n]; - if (board->dev_id == dev_id) - return board; - } - return NULL; -} - -static int __devinit ni_65xx_attach_pci(struct comedi_device *dev, - struct pci_dev *pcidev) +static int ni_65xx_attach(struct comedi_device *dev, + struct comedi_devconfig *it) { struct comedi_subdevice *s; unsigned i; int ret; + printk(KERN_INFO "comedi%d: ni_65xx:", dev->minor); + ret = alloc_private(dev, sizeof(struct ni_65xx_private)); if (ret < 0) return ret; - dev->board_ptr = ni_65xx_find_boardinfo(pcidev); - if (!dev->board_ptr) - return -ENODEV; - - private(dev)->mite = mite_alloc(pcidev); - if (!private(dev)->mite) - return -ENOMEM; + ret = ni_65xx_find_device(dev, it->options[0], it->options[1]); + if (ret < 0) + return ret; ret = mite_setup(private(dev)->mite); if (ret < 0) { - dev_warn(dev->class_dev, "error setting up mite\n"); + printk(KERN_WARNING "error setting up mite\n"); return ret; } dev->board_name = board(dev)->name; dev->irq = mite_irq(private(dev)->mite); - dev_info(dev->class_dev, "board: %s, ID=0x%02x", dev->board_name, + printk(KERN_INFO " %s", dev->board_name); + + printk(KERN_INFO " ID=0x%02x", readb(private(dev)->mite->daq_io_addr + ID_Register)); ret = comedi_alloc_subdevices(dev, 4); if (ret) return ret; - s = &dev->subdevices[0]; + s = dev->subdevices + 0; if (board(dev)->num_di_ports) { s->type = COMEDI_SUBD_DI; s->subdev_flags = SDF_READABLE; @@ -676,7 +696,7 @@ static int __devinit ni_65xx_attach_pci(struct comedi_device *dev, s->type = COMEDI_SUBD_UNUSED; } - s = &dev->subdevices[1]; + s = dev->subdevices + 1; if (board(dev)->num_do_ports) { s->type = COMEDI_SUBD_DO; s->subdev_flags = SDF_READABLE | SDF_WRITABLE; @@ -693,7 +713,7 @@ static int __devinit ni_65xx_attach_pci(struct comedi_device *dev, s->type = COMEDI_SUBD_UNUSED; } - s = &dev->subdevices[2]; + s = dev->subdevices + 2; if (board(dev)->num_dio_ports) { s->type = COMEDI_SUBD_DIO; s->subdev_flags = SDF_READABLE | SDF_WRITABLE; @@ -717,7 +737,7 @@ static int __devinit ni_65xx_attach_pci(struct comedi_device *dev, s->type = COMEDI_SUBD_UNUSED; } - s = &dev->subdevices[3]; + s = dev->subdevices + 3; dev->read_subdev = s; s->type = COMEDI_SUBD_DI; s->subdev_flags = SDF_READABLE | SDF_CMD_READ; @@ -752,9 +772,11 @@ static int __devinit ni_65xx_attach_pci(struct comedi_device *dev, "ni_65xx", dev); if (ret < 0) { dev->irq = 0; - dev_warn(dev->class_dev, "irq not available\n"); + printk(KERN_WARNING " irq not available"); } + printk("\n"); + return 0; } @@ -769,46 +791,79 @@ static void ni_65xx_detach(struct comedi_device *dev) if (dev->irq) free_irq(dev->irq, dev); if (private(dev)) { - struct comedi_subdevice *s; unsigned i; - for (i = 0; i < dev->n_subdevices; ++i) { - s = &dev->subdevices[i]; - kfree(s->private); - s->private = NULL; + kfree(dev->subdevices[i].private); + dev->subdevices[i].private = NULL; } - if (private(dev)->mite) { + if (private(dev)->mite) mite_unsetup(private(dev)->mite); - mite_free(private(dev)->mite); - } } } -static struct comedi_driver ni_65xx_driver = { - .driver_name = "ni_65xx", - .module = THIS_MODULE, - .attach_pci = ni_65xx_attach_pci, - .detach = ni_65xx_detach, -}; +static int ni_65xx_find_device(struct comedi_device *dev, int bus, int slot) +{ + struct mite_struct *mite; + int i; + + for (mite = mite_devices; mite; mite = mite->next) { + if (mite->used) + continue; + if (bus || slot) { + if (bus != mite->pcidev->bus->number || + slot != PCI_SLOT(mite->pcidev->devfn)) + continue; + } + for (i = 0; i < n_ni_65xx_boards; i++) { + if (mite_device_id(mite) == ni_65xx_boards[i].dev_id) { + dev->board_ptr = ni_65xx_boards + i; + private(dev)->mite = mite; + return 0; + } + } + } + printk(KERN_WARNING "no device found\n"); + mite_list_devices(); + return -EIO; +} -static int __devinit ni_65xx_pci_probe(struct pci_dev *dev, - const struct pci_device_id *ent) +static int __devinit driver_ni_65xx_pci_probe(struct pci_dev *dev, + const struct pci_device_id *ent) { - return comedi_pci_auto_config(dev, &ni_65xx_driver); + return comedi_pci_auto_config(dev, &driver_ni_65xx); } -static void __devexit ni_65xx_pci_remove(struct pci_dev *dev) +static void __devexit driver_ni_65xx_pci_remove(struct pci_dev *dev) { comedi_pci_auto_unconfig(dev); } -static struct pci_driver ni_65xx_pci_driver = { - .name = "ni_65xx", +static struct pci_driver driver_ni_65xx_pci_driver = { .id_table = ni_65xx_pci_table, - .probe = ni_65xx_pci_probe, - .remove = __devexit_p(ni_65xx_pci_remove) + .probe = &driver_ni_65xx_pci_probe, + .remove = __devexit_p(&driver_ni_65xx_pci_remove) }; -module_comedi_pci_driver(ni_65xx_driver, ni_65xx_pci_driver); + +static int __init driver_ni_65xx_init_module(void) +{ + int retval; + + retval = comedi_driver_register(&driver_ni_65xx); + if (retval < 0) + return retval; + + driver_ni_65xx_pci_driver.name = (char *)driver_ni_65xx.driver_name; + return pci_register_driver(&driver_ni_65xx_pci_driver); +} + +static void __exit driver_ni_65xx_cleanup_module(void) +{ + pci_unregister_driver(&driver_ni_65xx_pci_driver); + comedi_driver_unregister(&driver_ni_65xx); +} + +module_init(driver_ni_65xx_init_module); +module_exit(driver_ni_65xx_cleanup_module); MODULE_AUTHOR("Comedi http://www.comedi.org"); MODULE_DESCRIPTION("Comedi low-level driver"); diff --git a/trunk/drivers/staging/comedi/drivers/ni_660x.c b/trunk/drivers/staging/comedi/drivers/ni_660x.c index df2f3b0bab48..5e863ff343dd 100644 --- a/trunk/drivers/staging/comedi/drivers/ni_660x.c +++ b/trunk/drivers/staging/comedi/drivers/ni_660x.c @@ -448,46 +448,68 @@ static inline struct ni_660x_private *private(struct comedi_device *dev) return dev->private; } -/* initialized in ni_660x_attach_pci() */ +/* initialized in ni_660x_find_device() */ static inline const struct ni_660x_board *board(struct comedi_device *dev) { return dev->board_ptr; } -static int ni_660x_attach_pci(struct comedi_device *dev, - struct pci_dev *pcidev); +#define n_ni_660x_boards ARRAY_SIZE(ni_660x_boards) + +static int ni_660x_attach(struct comedi_device *dev, + struct comedi_devconfig *it); static void ni_660x_detach(struct comedi_device *dev); static void init_tio_chip(struct comedi_device *dev, int chipset); static void ni_660x_select_pfi_output(struct comedi_device *dev, unsigned pfi_channel, unsigned output_select); -static struct comedi_driver ni_660x_driver = { +static struct comedi_driver driver_ni_660x = { .driver_name = "ni_660x", .module = THIS_MODULE, - .attach_pci = ni_660x_attach_pci, + .attach = ni_660x_attach, .detach = ni_660x_detach, }; -static int __devinit ni_660x_pci_probe(struct pci_dev *dev, - const struct pci_device_id *ent) +static int __devinit driver_ni_660x_pci_probe(struct pci_dev *dev, + const struct pci_device_id *ent) { - return comedi_pci_auto_config(dev, &ni_660x_driver); + return comedi_pci_auto_config(dev, &driver_ni_660x); } -static void __devexit ni_660x_pci_remove(struct pci_dev *dev) +static void __devexit driver_ni_660x_pci_remove(struct pci_dev *dev) { comedi_pci_auto_unconfig(dev); } -static struct pci_driver ni_660x_pci_driver = { - .name = "ni_660x", +static struct pci_driver driver_ni_660x_pci_driver = { .id_table = ni_660x_pci_table, - .probe = ni_660x_pci_probe, - .remove = __devexit_p(ni_660x_pci_remove) + .probe = &driver_ni_660x_pci_probe, + .remove = __devexit_p(&driver_ni_660x_pci_remove) }; -module_comedi_pci_driver(ni_660x_driver, ni_660x_pci_driver); +static int __init driver_ni_660x_init_module(void) +{ + int retval; + + retval = comedi_driver_register(&driver_ni_660x); + if (retval < 0) + return retval; + + driver_ni_660x_pci_driver.name = (char *)driver_ni_660x.driver_name; + return pci_register_driver(&driver_ni_660x_pci_driver); +} + +static void __exit driver_ni_660x_cleanup_module(void) +{ + pci_unregister_driver(&driver_ni_660x_pci_driver); + comedi_driver_unregister(&driver_ni_660x); +} + +module_init(driver_ni_660x_init_module); +module_exit(driver_ni_660x_cleanup_module); + +static int ni_660x_find_device(struct comedi_device *dev, int bus, int slot); static int ni_660x_set_pfi_routing(struct comedi_device *dev, unsigned chan, unsigned source); @@ -726,6 +748,8 @@ static enum NI_660x_Register ni_gpct_to_660x_register(enum ni_gpct_register reg) ni_660x_register = G3InterruptEnable; break; default: + printk(KERN_WARNING "%s: unhandled register 0x%x in switch.\n", + __func__, reg); BUG(); return 0; break; @@ -749,6 +773,8 @@ static inline void ni_660x_write_register(struct comedi_device *dev, writel(bits, write_address); break; default: + printk(KERN_WARNING "%s: %s: bug! unhandled case (reg=0x%x) in switch.\n", + __FILE__, __func__, reg); BUG(); break; } @@ -770,6 +796,8 @@ static inline unsigned ni_660x_read_register(struct comedi_device *dev, return readl(read_address); break; default: + printk(KERN_WARNING "%s: %s: bug! unhandled case (reg=0x%x) in switch.\n", + __FILE__, __func__, reg); BUG(); break; } @@ -865,8 +893,8 @@ static int ni_660x_request_mite_channel(struct comedi_device *dev, return 0; } -static void ni_660x_release_mite_channel(struct comedi_device *dev, - struct ni_gpct *counter) +void ni_660x_release_mite_channel(struct comedi_device *dev, + struct ni_gpct *counter) { unsigned long flags; @@ -957,7 +985,7 @@ static irqreturn_t ni_660x_interrupt(int irq, void *d) spin_lock_irqsave(&private(dev)->interrupt_lock, flags); smp_mb(); for (i = 0; i < ni_660x_num_counters(dev); ++i) { - s = &dev->subdevices[NI_660X_GPCT_SUBDEV(i)]; + s = dev->subdevices + NI_660X_GPCT_SUBDEV(i); ni_660x_handle_gpct_interrupt(dev, s); } spin_unlock_irqrestore(&private(dev)->interrupt_lock, flags); @@ -1034,43 +1062,28 @@ static void ni_660x_free_mite_rings(struct comedi_device *dev) } } -static const struct ni_660x_board * -ni_660x_find_boardinfo(struct pci_dev *pcidev) -{ - unsigned int dev_id = pcidev->device; - unsigned int n; - - for (n = 0; n < ARRAY_SIZE(ni_660x_boards); n++) { - const struct ni_660x_board *board = &ni_660x_boards[n]; - if (board->dev_id == dev_id) - return board; - } - return NULL; -} - -static int __devinit ni_660x_attach_pci(struct comedi_device *dev, - struct pci_dev *pcidev) +static int ni_660x_attach(struct comedi_device *dev, + struct comedi_devconfig *it) { struct comedi_subdevice *s; int ret; unsigned i; unsigned global_interrupt_config_bits; + printk(KERN_INFO "comedi%d: ni_660x: ", dev->minor); + ret = ni_660x_allocate_private(dev); if (ret < 0) return ret; - dev->board_ptr = ni_660x_find_boardinfo(pcidev); - if (!dev->board_ptr) - return -ENODEV; - private(dev)->mite = mite_alloc(pcidev); - if (!private(dev)->mite) - return -ENOMEM; + ret = ni_660x_find_device(dev, it->options[0], it->options[1]); + if (ret < 0) + return ret; dev->board_name = board(dev)->name; ret = mite_setup2(private(dev)->mite, 1); if (ret < 0) { - dev_warn(dev->class_dev, "error setting up mite\n"); + printk(KERN_WARNING "error setting up mite\n"); return ret; } comedi_set_hw_dev(dev, &private(dev)->mite->pcidev->dev); @@ -1078,15 +1091,17 @@ static int __devinit ni_660x_attach_pci(struct comedi_device *dev, if (ret < 0) return ret; + printk(KERN_INFO " %s ", dev->board_name); + ret = comedi_alloc_subdevices(dev, 2 + NI_660X_MAX_NUM_COUNTERS); if (ret) return ret; - s = &dev->subdevices[0]; + s = dev->subdevices + 0; /* Old GENERAL-PURPOSE COUNTER/TIME (GPCT) subdevice, no longer used */ s->type = COMEDI_SUBD_UNUSED; - s = &dev->subdevices[NI_660X_DIO_SUBDEV]; + s = dev->subdevices + NI_660X_DIO_SUBDEV; /* DIGITAL I/O SUBDEVICE */ s->type = COMEDI_SUBD_DIO; s->subdev_flags = SDF_READABLE | SDF_WRITABLE; @@ -1109,7 +1124,7 @@ static int __devinit ni_660x_attach_pci(struct comedi_device *dev, if (private(dev)->counter_dev == NULL) return -ENOMEM; for (i = 0; i < NI_660X_MAX_NUM_COUNTERS; ++i) { - s = &dev->subdevices[NI_660X_GPCT_SUBDEV(i)]; + s = dev->subdevices + NI_660X_GPCT_SUBDEV(i); if (i < ni_660x_num_counters(dev)) { s->type = COMEDI_SUBD_COUNTER; s->subdev_flags = @@ -1159,7 +1174,7 @@ static int __devinit ni_660x_attach_pci(struct comedi_device *dev, ret = request_irq(mite_irq(private(dev)->mite), ni_660x_interrupt, IRQF_SHARED, "ni_660x", dev); if (ret < 0) { - dev_warn(dev->class_dev, " irq not available\n"); + printk(KERN_WARNING " irq not available\n"); return ret; } dev->irq = mite_irq(private(dev)->mite); @@ -1168,7 +1183,7 @@ static int __devinit ni_660x_attach_pci(struct comedi_device *dev, global_interrupt_config_bits |= Cascade_Int_Enable_Bit; ni_660x_write_register(dev, 0, global_interrupt_config_bits, GlobalInterruptConfigRegister); - dev_info(dev->class_dev, "ni_660x: %s attached\n", dev->board_name); + printk(KERN_INFO "attached\n"); return 0; } @@ -1182,7 +1197,6 @@ static void ni_660x_detach(struct comedi_device *dev) if (private(dev)->mite) { ni_660x_free_mite_rings(dev); mite_unsetup(private(dev)->mite); - mite_free(private(dev)->mite); } } } @@ -1226,6 +1240,33 @@ static int ni_660x_GPCT_winsn(struct comedi_device *dev, return ni_tio_winsn(subdev_to_counter(s), insn, data); } +static int ni_660x_find_device(struct comedi_device *dev, int bus, int slot) +{ + struct mite_struct *mite; + int i; + + for (mite = mite_devices; mite; mite = mite->next) { + if (mite->used) + continue; + if (bus || slot) { + if (bus != mite->pcidev->bus->number || + slot != PCI_SLOT(mite->pcidev->devfn)) + continue; + } + + for (i = 0; i < n_ni_660x_boards; i++) { + if (mite_device_id(mite) == ni_660x_boards[i].dev_id) { + dev->board_ptr = ni_660x_boards + i; + private(dev)->mite = mite; + return 0; + } + } + } + printk(KERN_WARNING "no device found\n"); + mite_list_devices(); + return -EIO; +} + static int ni_660x_dio_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) diff --git a/trunk/drivers/staging/comedi/drivers/ni_670x.c b/trunk/drivers/staging/comedi/drivers/ni_670x.c index eac6dc047bb0..9c57618f2c5b 100644 --- a/trunk/drivers/staging/comedi/drivers/ni_670x.c +++ b/trunk/drivers/staging/comedi/drivers/ni_670x.c @@ -187,22 +187,37 @@ static int ni_670x_dio_insn_config(struct comedi_device *dev, return insn->n; } -static const struct ni_670x_board * -ni_670x_find_boardinfo(struct pci_dev *pcidev) +static int ni_670x_find_device(struct comedi_device *dev, int bus, int slot) { - unsigned int dev_id = pcidev->device; - unsigned int n; + struct ni_670x_private *devpriv = dev->private; + struct mite_struct *mite; + int i; + + for (mite = mite_devices; mite; mite = mite->next) { + if (mite->used) + continue; + if (bus || slot) { + if (bus != mite->pcidev->bus->number + || slot != PCI_SLOT(mite->pcidev->devfn)) + continue; + } + + for (i = 0; i < ARRAY_SIZE(ni_670x_boards); i++) { + if (mite_device_id(mite) == ni_670x_boards[i].dev_id) { + dev->board_ptr = ni_670x_boards + i; + devpriv->mite = mite; - for (n = 0; n < ARRAY_SIZE(ni_670x_boards); n++) { - const struct ni_670x_board *board = &ni_670x_boards[n]; - if (board->dev_id == dev_id) - return board; + return 0; + } + } } - return NULL; + dev_warn(dev->class_dev, "no device found\n"); + mite_list_devices(); + return -EIO; } -static int __devinit ni_670x_attach_pci(struct comedi_device *dev, - struct pci_dev *pcidev) +static int ni_670x_attach(struct comedi_device *dev, + struct comedi_devconfig *it) { const struct ni_670x_board *thisboard; struct ni_670x_private *devpriv; @@ -214,12 +229,10 @@ static int __devinit ni_670x_attach_pci(struct comedi_device *dev, if (ret < 0) return ret; devpriv = dev->private; - dev->board_ptr = ni_670x_find_boardinfo(pcidev); - if (!dev->board_ptr) - return -ENODEV; - devpriv->mite = mite_alloc(pcidev); - if (!devpriv->mite) - return -ENOMEM; + + ret = ni_670x_find_device(dev, it->options[0], it->options[1]); + if (ret < 0) + return ret; thisboard = comedi_board(dev); ret = mite_setup(devpriv->mite); @@ -228,12 +241,13 @@ static int __devinit ni_670x_attach_pci(struct comedi_device *dev, return ret; } dev->board_name = thisboard->name; + dev->irq = mite_irq(devpriv->mite); ret = comedi_alloc_subdevices(dev, 2); if (ret) return ret; - s = &dev->subdevices[0]; + s = dev->subdevices + 0; /* analog output subdevice */ s->type = COMEDI_SUBD_AO; s->subdev_flags = SDF_WRITABLE; @@ -257,7 +271,7 @@ static int __devinit ni_670x_attach_pci(struct comedi_device *dev, s->insn_write = &ni_670x_ao_winsn; s->insn_read = &ni_670x_ao_rinsn; - s = &dev->subdevices[1]; + s = dev->subdevices + 1; /* digital i/o subdevice */ s->type = COMEDI_SUBD_DIO; s->subdev_flags = SDF_READABLE | SDF_WRITABLE; @@ -284,20 +298,20 @@ static void ni_670x_detach(struct comedi_device *dev) struct comedi_subdevice *s; if (dev->n_subdevices) { - s = &dev->subdevices[0]; + s = dev->subdevices + 0; if (s) kfree(s->range_table_list); } - if (devpriv && devpriv->mite) { + if (devpriv && devpriv->mite) mite_unsetup(devpriv->mite); - mite_free(devpriv->mite); - } + if (dev->irq) + free_irq(dev->irq, dev); } static struct comedi_driver ni_670x_driver = { .driver_name = "ni_670x", .module = THIS_MODULE, - .attach_pci = ni_670x_attach_pci, + .attach = ni_670x_attach, .detach = ni_670x_detach, }; diff --git a/trunk/drivers/staging/comedi/drivers/ni_at_a2150.c b/trunk/drivers/staging/comedi/drivers/ni_at_a2150.c index 83950807b672..b53a4286f8cb 100644 --- a/trunk/drivers/staging/comedi/drivers/ni_at_a2150.c +++ b/trunk/drivers/staging/comedi/drivers/ni_at_a2150.c @@ -321,23 +321,45 @@ static int a2150_ai_cmdtest(struct comedi_device *dev, int startChan; int i; - /* Step 1 : check if triggers are trivially valid */ + /* step 1: make sure trigger sources are trivially valid */ - err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_EXT); - err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_TIMER); - err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_NOW); - err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT); - err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE); + tmp = cmd->start_src; + cmd->start_src &= TRIG_NOW | TRIG_EXT; + if (!cmd->start_src || tmp != cmd->start_src) + err++; + + tmp = cmd->scan_begin_src; + cmd->scan_begin_src &= TRIG_TIMER; + if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) + err++; + + tmp = cmd->convert_src; + cmd->convert_src &= TRIG_NOW; + if (!cmd->convert_src || tmp != cmd->convert_src) + err++; + + tmp = cmd->scan_end_src; + cmd->scan_end_src &= TRIG_COUNT; + if (!cmd->scan_end_src || tmp != cmd->scan_end_src) + err++; + + tmp = cmd->stop_src; + cmd->stop_src &= TRIG_COUNT | TRIG_NONE; + if (!cmd->stop_src || tmp != cmd->stop_src) + err++; if (err) return 1; - /* Step 2a : make sure trigger sources are unique */ - - err |= cfc_check_trigger_is_unique(cmd->start_src); - err |= cfc_check_trigger_is_unique(cmd->stop_src); + /* + * step 2: make sure trigger sources are unique and mutually + * compatible + */ - /* Step 2b : and mutually compatible */ + if (cmd->start_src != TRIG_NOW && cmd->start_src != TRIG_EXT) + err++; + if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE) + err++; if (err) return 2; @@ -810,7 +832,7 @@ static int a2150_attach(struct comedi_device *dev, struct comedi_devconfig *it) return ret; /* analog input subdevice */ - s = &dev->subdevices[0]; + s = dev->subdevices + 0; dev->read_subdev = s; s->type = COMEDI_SUBD_AI; s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_OTHER | SDF_CMD_READ; diff --git a/trunk/drivers/staging/comedi/drivers/ni_at_ao.c b/trunk/drivers/staging/comedi/drivers/ni_at_ao.c index 93938cec93e7..62c8c44a8d28 100644 --- a/trunk/drivers/staging/comedi/drivers/ni_at_ao.c +++ b/trunk/drivers/staging/comedi/drivers/ni_at_ao.c @@ -358,7 +358,7 @@ static int atao_attach(struct comedi_device *dev, struct comedi_devconfig *it) if (ret) return ret; - s = &dev->subdevices[0]; + s = dev->subdevices + 0; /* analog output subdevice */ s->type = COMEDI_SUBD_AO; s->subdev_flags = SDF_WRITABLE; @@ -371,7 +371,7 @@ static int atao_attach(struct comedi_device *dev, struct comedi_devconfig *it) s->insn_write = &atao_ao_winsn; s->insn_read = &atao_ao_rinsn; - s = &dev->subdevices[1]; + s = dev->subdevices + 1; /* digital i/o subdevice */ s->type = COMEDI_SUBD_DIO; s->subdev_flags = SDF_READABLE | SDF_WRITABLE; @@ -381,7 +381,7 @@ static int atao_attach(struct comedi_device *dev, struct comedi_devconfig *it) s->insn_bits = atao_dio_insn_bits; s->insn_config = atao_dio_insn_config; - s = &dev->subdevices[2]; + s = dev->subdevices + 2; /* caldac subdevice */ s->type = COMEDI_SUBD_CALIB; s->subdev_flags = SDF_WRITABLE | SDF_INTERNAL; @@ -390,7 +390,7 @@ static int atao_attach(struct comedi_device *dev, struct comedi_devconfig *it) s->insn_read = atao_calib_insn_read; s->insn_write = atao_calib_insn_write; - s = &dev->subdevices[3]; + s = dev->subdevices + 3; /* eeprom subdevice */ /* s->type=COMEDI_SUBD_EEPROM; */ s->type = COMEDI_SUBD_UNUSED; diff --git a/trunk/drivers/staging/comedi/drivers/ni_atmio.c b/trunk/drivers/staging/comedi/drivers/ni_atmio.c index cac25572f6bb..6448373878ed 100644 --- a/trunk/drivers/staging/comedi/drivers/ni_atmio.c +++ b/trunk/drivers/staging/comedi/drivers/ni_atmio.c @@ -489,7 +489,7 @@ static int ni_atmio_attach(struct comedi_device *dev, /* generic E series stuff in ni_mio_common.c */ - ret = ni_E_init(dev); + ret = ni_E_init(dev, it); if (ret < 0) return ret; diff --git a/trunk/drivers/staging/comedi/drivers/ni_atmio16d.c b/trunk/drivers/staging/comedi/drivers/ni_atmio16d.c index e91a620f9db3..2c78d3dd242a 100644 --- a/trunk/drivers/staging/comedi/drivers/ni_atmio16d.c +++ b/trunk/drivers/staging/comedi/drivers/ni_atmio16d.c @@ -40,7 +40,6 @@ Devices: [National Instruments] AT-MIO-16 (atmio16), AT-MIO-16D (atmio16d) #include -#include "comedi_fc.h" #include "8255.h" /* Configuration and Status Registers */ @@ -235,7 +234,7 @@ static void reset_atmio16d(struct comedi_device *dev) static irqreturn_t atmio16d_interrupt(int irq, void *d) { struct comedi_device *dev = d; - struct comedi_subdevice *s = &dev->subdevices[0]; + struct comedi_subdevice *s = dev->subdevices + 0; comedi_buf_put(s->async, inw(dev->iobase + AD_FIFO_REG)); @@ -247,26 +246,45 @@ static int atmio16d_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd) { - int err = 0; + int err = 0, tmp; - /* Step 1 : check if triggers are trivially valid */ + /* make sure triggers are valid */ + tmp = cmd->start_src; + cmd->start_src &= TRIG_NOW; + if (!cmd->start_src || tmp != cmd->start_src) + err++; - err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW); - err |= cfc_check_trigger_src(&cmd->scan_begin_src, - TRIG_FOLLOW | TRIG_TIMER); - err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_TIMER); - err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT); - err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE); + tmp = cmd->scan_begin_src; + cmd->scan_begin_src &= TRIG_FOLLOW | TRIG_TIMER; + if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) + err++; - if (err) - return 1; + tmp = cmd->convert_src; + cmd->convert_src &= TRIG_TIMER; + if (!cmd->convert_src || tmp != cmd->convert_src) + err++; + + tmp = cmd->scan_end_src; + cmd->scan_end_src &= TRIG_COUNT; + if (!cmd->scan_end_src || tmp != cmd->scan_end_src) + err++; - /* Step 2a : make sure trigger sources are unique */ + tmp = cmd->stop_src; + cmd->stop_src &= TRIG_COUNT | TRIG_NONE; + if (!cmd->stop_src || tmp != cmd->stop_src) + err++; - err |= cfc_check_trigger_is_unique(cmd->scan_begin_src); - err |= cfc_check_trigger_is_unique(cmd->stop_src); + if (err) + return 1; - /* Step 2b : and mutually compatible */ + /* step 2: make sure trigger sources are unique & mutually compatible */ + /* note that mutual compatibility is not an issue here */ + if (cmd->scan_begin_src != TRIG_FOLLOW && + cmd->scan_begin_src != TRIG_EXT && + cmd->scan_begin_src != TRIG_TIMER) + err++; + if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE) + err++; if (err) return 2; @@ -706,7 +724,7 @@ static int atmio16d_attach(struct comedi_device *dev, devpriv->dac1_coding = it->options[12]; /* setup sub-devices */ - s = &dev->subdevices[0]; + s = dev->subdevices + 0; dev->read_subdev = s; /* ai subdevice */ s->type = COMEDI_SUBD_AI; @@ -731,7 +749,7 @@ static int atmio16d_attach(struct comedi_device *dev, } /* ao subdevice */ - s = &dev->subdevices[1]; + s++; s->type = COMEDI_SUBD_AO; s->subdev_flags = SDF_WRITABLE; s->n_chan = 2; @@ -757,7 +775,7 @@ static int atmio16d_attach(struct comedi_device *dev, } /* Digital I/O */ - s = &dev->subdevices[2]; + s++; s->type = COMEDI_SUBD_DIO; s->subdev_flags = SDF_WRITABLE | SDF_READABLE; s->n_chan = 8; @@ -767,7 +785,7 @@ static int atmio16d_attach(struct comedi_device *dev, s->range_table = &range_digital; /* 8255 subdevice */ - s = &dev->subdevices[3]; + s++; if (board->has_8255) subdev_8255_init(dev, s, NULL, dev->iobase); else @@ -775,7 +793,7 @@ static int atmio16d_attach(struct comedi_device *dev, /* don't yet know how to deal with counter/timers */ #if 0 - s = &dev->subdevices[4]; + s++; /* do */ s->type = COMEDI_SUBD_TIMER; s->n_chan = 0; @@ -789,12 +807,9 @@ static int atmio16d_attach(struct comedi_device *dev, static void atmio16d_detach(struct comedi_device *dev) { const struct atmio16_board_t *board = comedi_board(dev); - struct comedi_subdevice *s; - if (dev->subdevices && board->has_8255) { - s = &dev->subdevices[3]; - subdev_8255_cleanup(dev, s); - } + if (dev->subdevices && board->has_8255) + subdev_8255_cleanup(dev, dev->subdevices + 3); if (dev->irq) free_irq(dev->irq, dev); reset_atmio16d(dev); diff --git a/trunk/drivers/staging/comedi/drivers/ni_daq_700.c b/trunk/drivers/staging/comedi/drivers/ni_daq_700.c index 2ba0ade45c64..83016b411851 100644 --- a/trunk/drivers/staging/comedi/drivers/ni_daq_700.c +++ b/trunk/drivers/staging/comedi/drivers/ni_daq_700.c @@ -1,6 +1,6 @@ /* * comedi/drivers/ni_daq_700.c - * Driver for DAQCard-700 DIO/AI + * Driver for DAQCard-700 DIO only * copied from 8255 * * COMEDI - Linux Control and Measurement Device Interface @@ -29,25 +29,14 @@ Author: Fred Brooks , based on ni_daq_dio24 by Daniel Vecino Castel Devices: [National Instruments] PCMCIA DAQ-Card-700 (ni_daq_700) Status: works -Updated: Wed, 19 Sep 2012 12:07:20 +0000 +Updated: Thu, 21 Feb 2008 12:07:20 +0000 -The daqcard-700 appears in Comedi as a digital I/O subdevice (0) with -16 channels and a analog input subdevice (1) with 16 single-ended channels. - -Digital: The channel 0 corresponds to the daqcard-700's output +The daqcard-700 appears in Comedi as a single digital I/O subdevice with +16 channels. The channel 0 corresponds to the daqcard-700's output port, bit 0; channel 8 corresponds to the input port, bit 0. -Digital direction configuration: channels 0-7 output, 8-15 input (8225 device +Direction configuration: channels 0-7 output, 8-15 input (8225 device emu as port A output, port B input, port C N/A). - -Analog: The input range is 0 to 4095 for -10 to +10 volts -IRQ is assigned but not used. - -Version 0.1 Original DIO only driver -Version 0.2 DIO and basic AI analog input support on 16 se channels - -Manuals: Register level: http://www.ni.com/pdf/manuals/340698.pdf - User Manual: http://www.ni.com/pdf/manuals/320676d.pdf */ #include @@ -62,29 +51,16 @@ Manuals: Register level: http://www.ni.com/pdf/manuals/340698.pdf static struct pcmcia_device *pcmcia_cur_dev; -struct daq700_board { +struct dio700_board { const char *name; }; -/* daqcard700 registers */ -#define DIO_W 0x04 /* WO 8bit */ -#define DIO_R 0x05 /* RO 8bit */ -#define CMD_R1 0x00 /* WO 8bit */ -#define CMD_R2 0x07 /* RW 8bit */ -#define CMD_R3 0x05 /* W0 8bit */ -#define STA_R1 0x00 /* RO 8bit */ -#define STA_R2 0x01 /* RO 8bit */ -#define ADFIFO_R 0x02 /* RO 16bit */ -#define ADCLEAR_R 0x01 /* WO 8bit */ -#define CDA_R0 0x08 /* RW 8bit */ -#define CDA_R1 0x09 /* RW 8bit */ -#define CDA_R2 0x0A /* RW 8bit */ -#define CMO_R 0x0B /* RO 8bit */ -#define TIC_R 0x06 /* WO 8bit */ - -static int daq700_dio_insn_bits(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) +#define DIO_W 0x04 +#define DIO_R 0x05 + +static int subdev_700_insn(struct comedi_device *dev, + struct comedi_subdevice *s, struct comedi_insn *insn, + unsigned int *data) { if (data[0]) { s->state &= ~data[0]; @@ -100,7 +76,7 @@ static int daq700_dio_insn_bits(struct comedi_device *dev, return insn->n; } -static int daq700_dio_insn_config(struct comedi_device *dev, +static int subdev_700_insn_config(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { @@ -121,90 +97,9 @@ static int daq700_dio_insn_config(struct comedi_device *dev, return insn->n; } -static int daq700_ai_rinsn(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) +static int dio700_attach(struct comedi_device *dev, struct comedi_devconfig *it) { - int n, i, chan; - int d; - unsigned int status; - enum { TIMEOUT = 100 }; - - chan = CR_CHAN(insn->chanspec); - /* write channel to multiplexer */ - /* set mask scan bit high to disable scanning */ - outb(chan | 0x80, dev->iobase + CMD_R1); - - /* convert n samples */ - for (n = 0; n < insn->n; n++) { - /* trigger conversion with out0 L to H */ - outb(0x00, dev->iobase + CMD_R2); /* enable ADC conversions */ - outb(0x30, dev->iobase + CMO_R); /* mode 0 out0 L, from H */ - /* mode 1 out0 H, L to H, start conversion */ - outb(0x32, dev->iobase + CMO_R); - /* wait for conversion to end */ - for (i = 0; i < TIMEOUT; i++) { - status = inb(dev->iobase + STA_R2); - if ((status & 0x03) != 0) { - dev_info(dev->class_dev, - "Overflow/run Error\n"); - return -EOVERFLOW; - } - status = inb(dev->iobase + STA_R1); - if ((status & 0x02) != 0) { - dev_info(dev->class_dev, "Data Error\n"); - return -ENODATA; - } - if ((status & 0x11) == 0x01) { - /* ADC conversion complete */ - break; - } - udelay(1); - } - if (i == TIMEOUT) { - dev_info(dev->class_dev, - "timeout during ADC conversion\n"); - return -ETIMEDOUT; - } - /* read data */ - d = inw(dev->iobase + ADFIFO_R); - /* mangle the data as necessary */ - /* Bipolar Offset Binary: 0 to 4095 for -10 to +10 */ - d &= 0x0fff; - d ^= 0x0800; - data[n] = d; - } - return n; -} - -/* - * Data acquisition is enabled. - * The counter 0 output is high. - * The I/O connector pin CLK1 drives counter 1 source. - * Multiple-channel scanning is disabled. - * All interrupts are disabled. - * The analog input range is set to +-10 V - * The analog input mode is single-ended. - * The analog input circuitry is initialized to channel 0. - * The A/D FIFO is cleared. - */ -static void daq700_ai_config(struct comedi_device *dev, - struct comedi_subdevice *s) -{ - unsigned long iobase = dev->iobase; - - outb(0x80, iobase + CMD_R1); /* disable scanning, ADC to chan 0 */ - outb(0x00, iobase + CMD_R2); /* clear all bits */ - outb(0x00, iobase + CMD_R3); /* set +-10 range */ - outb(0x32, iobase + CMO_R); /* config counter mode1, out0 to H */ - outb(0x00, iobase + TIC_R); /* clear counter interrupt */ - outb(0x00, iobase + ADCLEAR_R); /* clear the ADC FIFO */ - inw(iobase + ADFIFO_R); /* read 16bit junk from FIFO to clear */ -} - -static int daq700_attach(struct comedi_device *dev, struct comedi_devconfig *it) -{ - const struct daq700_board *thisboard = comedi_board(dev); + const struct dio700_board *thisboard = comedi_board(dev); struct comedi_subdevice *s; struct pcmcia_device *link; int ret; @@ -221,33 +116,23 @@ static int daq700_attach(struct comedi_device *dev, struct comedi_devconfig *it) dev->board_name = thisboard->name; - ret = comedi_alloc_subdevices(dev, 2); + ret = comedi_alloc_subdevices(dev, 1); if (ret) return ret; /* DAQCard-700 dio */ - s = &dev->subdevices[0]; + s = dev->subdevices + 0; s->type = COMEDI_SUBD_DIO; s->subdev_flags = SDF_READABLE | SDF_WRITABLE; s->n_chan = 16; s->range_table = &range_digital; s->maxdata = 1; - s->insn_bits = daq700_dio_insn_bits; - s->insn_config = daq700_dio_insn_config; + s->insn_bits = subdev_700_insn; + s->insn_config = subdev_700_insn_config; + s->state = 0; s->io_bits = 0x00ff; - /* DAQCard-700 ai */ - s = &dev->subdevices[1]; - s->type = COMEDI_SUBD_AI; - /* we support single-ended (ground) */ - s->subdev_flags = SDF_READABLE | SDF_GROUND; - s->n_chan = 16; - s->maxdata = (1 << 12) - 1; - s->range_table = &range_bipolar10; - s->insn_read = daq700_ai_rinsn; - daq700_ai_config(dev, s); - dev_info(dev->class_dev, "%s: %s, io 0x%lx\n", dev->driver->driver_name, dev->board_name, @@ -256,12 +141,12 @@ static int daq700_attach(struct comedi_device *dev, struct comedi_devconfig *it) return 0; } -static void daq700_detach(struct comedi_device *dev) +static void dio700_detach(struct comedi_device *dev) { /* nothing to cleanup */ } -static const struct daq700_board daq700_boards[] = { +static const struct dio700_board dio700_boards[] = { { .name = "daqcard-700", }, { @@ -269,17 +154,17 @@ static const struct daq700_board daq700_boards[] = { }, }; -static struct comedi_driver daq700_driver = { +static struct comedi_driver driver_dio700 = { .driver_name = "ni_daq_700", .module = THIS_MODULE, - .attach = daq700_attach, - .detach = daq700_detach, - .board_name = &daq700_boards[0].name, - .num_names = ARRAY_SIZE(daq700_boards), - .offset = sizeof(struct daq700_board), + .attach = dio700_attach, + .detach = dio700_detach, + .board_name = &dio700_boards[0].name, + .num_names = ARRAY_SIZE(dio700_boards), + .offset = sizeof(struct dio700_board), }; -static int daq700_pcmcia_config_loop(struct pcmcia_device *p_dev, +static int dio700_pcmcia_config_loop(struct pcmcia_device *p_dev, void *priv_data) { if (p_dev->config_index == 0) @@ -288,14 +173,14 @@ static int daq700_pcmcia_config_loop(struct pcmcia_device *p_dev, return pcmcia_request_io(p_dev); } -static int daq700_cs_attach(struct pcmcia_device *link) +static int dio700_cs_attach(struct pcmcia_device *link) { int ret; link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_AUDIO | CONF_AUTO_SET_IO; - ret = pcmcia_loop_config(link, daq700_pcmcia_config_loop, NULL); + ret = pcmcia_loop_config(link, dio700_pcmcia_config_loop, NULL); if (ret) goto failed; @@ -314,53 +199,52 @@ static int daq700_cs_attach(struct pcmcia_device *link) return ret; } -static void daq700_cs_detach(struct pcmcia_device *link) +static void dio700_cs_detach(struct pcmcia_device *link) { pcmcia_disable_device(link); pcmcia_cur_dev = NULL; } -static const struct pcmcia_device_id daq700_cs_ids[] = { +static const struct pcmcia_device_id dio700_cs_ids[] = { PCMCIA_DEVICE_MANF_CARD(0x010b, 0x4743), PCMCIA_DEVICE_NULL }; -MODULE_DEVICE_TABLE(pcmcia, daq700_cs_ids); +MODULE_DEVICE_TABLE(pcmcia, dio700_cs_ids); -static struct pcmcia_driver daq700_cs_driver = { +static struct pcmcia_driver dio700_cs_driver = { .name = "ni_daq_700", .owner = THIS_MODULE, - .probe = daq700_cs_attach, - .remove = daq700_cs_detach, - .id_table = daq700_cs_ids, + .probe = dio700_cs_attach, + .remove = dio700_cs_detach, + .id_table = dio700_cs_ids, }; -static int __init daq700_cs_init(void) +static int __init dio700_cs_init(void) { int ret; - ret = comedi_driver_register(&daq700_driver); + ret = comedi_driver_register(&driver_dio700); if (ret < 0) return ret; - ret = pcmcia_register_driver(&daq700_cs_driver); + ret = pcmcia_register_driver(&dio700_cs_driver); if (ret < 0) { - comedi_driver_unregister(&daq700_driver); + comedi_driver_unregister(&driver_dio700); return ret; } return 0; } -module_init(daq700_cs_init); +module_init(dio700_cs_init); -static void __exit daq700_cs_exit(void) +static void __exit dio700_cs_exit(void) { - pcmcia_unregister_driver(&daq700_cs_driver); - comedi_driver_unregister(&daq700_driver); + pcmcia_unregister_driver(&dio700_cs_driver); + comedi_driver_unregister(&driver_dio700); } -module_exit(daq700_cs_exit); +module_exit(dio700_cs_exit); MODULE_AUTHOR("Fred Brooks "); MODULE_DESCRIPTION( - "Comedi driver for National Instruments PCMCIA DAQCard-700 DIO/AI"); -MODULE_VERSION("0.2.00"); + "Comedi driver for National Instruments PCMCIA DAQCard-700 DIO"); MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/staging/comedi/drivers/ni_daq_dio24.c b/trunk/drivers/staging/comedi/drivers/ni_daq_dio24.c index 0ca222bbcbe6..e27cae0eb8a2 100644 --- a/trunk/drivers/staging/comedi/drivers/ni_daq_dio24.c +++ b/trunk/drivers/staging/comedi/drivers/ni_daq_dio24.c @@ -164,7 +164,7 @@ static int dio24_attach(struct comedi_device *dev, struct comedi_devconfig *it) return ret; /* 8255 dio */ - s = &dev->subdevices[0]; + s = dev->subdevices + 0; subdev_8255_init(dev, s, NULL, dev->iobase); return 0; @@ -172,12 +172,8 @@ static int dio24_attach(struct comedi_device *dev, struct comedi_devconfig *it) static void dio24_detach(struct comedi_device *dev) { - struct comedi_subdevice *s; - - if (dev->subdevices) { - s = &dev->subdevices[0]; - subdev_8255_cleanup(dev, s); - } + if (dev->subdevices) + subdev_8255_cleanup(dev, dev->subdevices + 0); if (thisboard->bustype != pcmcia_bustype && dev->iobase) release_region(dev->iobase, DIO24_SIZE); if (dev->irq) @@ -308,7 +304,7 @@ MODULE_DESCRIPTION("Comedi driver for National Instruments " "PCMCIA DAQ-Card DIO-24"); MODULE_LICENSE("GPL"); -static struct pcmcia_driver dio24_cs_driver = { +struct pcmcia_driver dio24_cs_driver = { .probe = dio24_cs_attach, .remove = dio24_cs_detach, .suspend = dio24_cs_suspend, diff --git a/trunk/drivers/staging/comedi/drivers/ni_labpc.c b/trunk/drivers/staging/comedi/drivers/ni_labpc.c index 28b91a6c3789..ab8b787c78bb 100644 --- a/trunk/drivers/staging/comedi/drivers/ni_labpc.c +++ b/trunk/drivers/staging/comedi/drivers/ni_labpc.c @@ -73,6 +73,9 @@ NI manuals: */ +#undef LABPC_DEBUG +/* #define LABPC_DEBUG enable debugging messages */ + #include #include #include @@ -206,13 +209,7 @@ NI manuals: #define INIT_A1_BITS 0x70 #define COUNTER_B_BASE_REG 0x18 -enum scan_mode { - MODE_SINGLE_CHAN, - MODE_SINGLE_CHAN_INTERVAL, - MODE_MULT_CHAN_UP, - MODE_MULT_CHAN_DOWN, -}; - +static int labpc_attach(struct comedi_device *dev, struct comedi_devconfig *it); static int labpc_cancel(struct comedi_device *dev, struct comedi_subdevice *s); static irqreturn_t labpc_interrupt(int irq, void *d); static int labpc_drain_fifo(struct comedi_device *dev); @@ -243,10 +240,12 @@ static int labpc_eeprom_write_insn(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data); -static void labpc_adc_timing(struct comedi_device *dev, struct comedi_cmd *cmd, - enum scan_mode scan_mode); +static void labpc_adc_timing(struct comedi_device *dev, struct comedi_cmd *cmd); #ifdef CONFIG_ISA_DMA_API -static unsigned int labpc_suggest_transfer_size(const struct comedi_cmd *cmd); +static unsigned int labpc_suggest_transfer_size(struct comedi_cmd cmd); +#endif +#ifdef CONFIG_COMEDI_PCI_DRIVERS +static int labpc_find_device(struct comedi_device *dev, int bus, int slot); #endif static int labpc_dio_mem_callback(int dir, int port, int data, unsigned long arg); @@ -262,6 +261,13 @@ static int labpc_eeprom_write(struct comedi_device *dev, static void write_caldac(struct comedi_device *dev, unsigned int channel, unsigned int value); +enum scan_mode { + MODE_SINGLE_CHAN, + MODE_SINGLE_CHAN_INTERVAL, + MODE_MULT_CHAN_UP, + MODE_MULT_CHAN_DOWN, +}; + /* analog input ranges */ #define NUM_LABPC_PLUS_AI_RANGES 16 /* indicates unipolar ranges */ @@ -410,12 +416,12 @@ static inline void labpc_outb(unsigned int byte, unsigned long address) static inline unsigned int labpc_readb(unsigned long address) { - return readb((void __iomem *)address); + return readb((void *)address); } static inline void labpc_writeb(unsigned int byte, unsigned long address) { - writeb(byte, (void __iomem *)address); + writeb(byte, (void *)address); } static const struct labpc_board_struct labpc_boards[] = { @@ -489,14 +495,33 @@ static const int sample_size = 2; #define devpriv ((struct labpc_private *)dev->private) +static struct comedi_driver driver_labpc = { + .driver_name = DRV_NAME, + .module = THIS_MODULE, + .attach = labpc_attach, + .detach = labpc_common_detach, + .num_names = ARRAY_SIZE(labpc_boards), + .board_name = &labpc_boards[0].name, + .offset = sizeof(struct labpc_board_struct), +}; + +#ifdef CONFIG_COMEDI_PCI_DRIVERS +static DEFINE_PCI_DEVICE_TABLE(labpc_pci_table) = { + {PCI_DEVICE(PCI_VENDOR_ID_NI, 0x161)}, + {0} +}; + +MODULE_DEVICE_TABLE(pci, labpc_pci_table); +#endif /* CONFIG_COMEDI_PCI_DRIVERS */ + static inline int labpc_counter_load(struct comedi_device *dev, unsigned long base_address, unsigned int counter_number, unsigned int count, unsigned int mode) { if (thisboard->memory_mapped_io) - return i8254_mm_load((void __iomem *)base_address, 0, - counter_number, count, mode); + return i8254_mm_load((void *)base_address, 0, counter_number, + count, mode); else return i8254_load(base_address, 0, counter_number, count, mode); } @@ -513,16 +538,25 @@ int labpc_common_attach(struct comedi_device *dev, unsigned long iobase, short lsb, msb; int ret; - dev_info(dev->class_dev, "ni_labpc: %s\n", thisboard->name); + printk(KERN_ERR "comedi%d: ni_labpc: %s, io 0x%lx", dev->minor, + thisboard->name, + iobase); + if (irq) + printk(", irq %u", irq); + if (dma_chan) + printk(", dma %u", dma_chan); + printk("\n"); + if (iobase == 0) { - dev_err(dev->class_dev, "io base address is zero!\n"); + printk(KERN_ERR "io base address is zero!\n"); return -EINVAL; } /* request io regions for isa boards */ if (thisboard->bustype == isa_bustype) { /* check if io addresses are available */ - if (!request_region(iobase, LABPC_SIZE, DRV_NAME)) { - dev_err(dev->class_dev, "I/O port conflict\n"); + if (!request_region(iobase, LABPC_SIZE, + driver_labpc.driver_name)) { + printk(KERN_ERR "I/O port conflict\n"); return -EIO; } } @@ -554,9 +588,8 @@ int labpc_common_attach(struct comedi_device *dev, unsigned long iobase, || thisboard->bustype == pcmcia_bustype) isr_flags |= IRQF_SHARED; if (request_irq(irq, labpc_interrupt, isr_flags, - DRV_NAME, dev)) { - dev_err(dev->class_dev, "unable to allocate irq %u\n", - irq); + driver_labpc.driver_name, dev)) { + printk(KERN_ERR "unable to allocate irq %u\n", irq); return -EINVAL; } } @@ -565,21 +598,19 @@ int labpc_common_attach(struct comedi_device *dev, unsigned long iobase, #ifdef CONFIG_ISA_DMA_API /* grab dma channel */ if (dma_chan > 3) { - dev_err(dev->class_dev, "invalid dma channel %u\n", dma_chan); + printk(KERN_ERR " invalid dma channel %u\n", dma_chan); return -EINVAL; } else if (dma_chan) { /* allocate dma buffer */ devpriv->dma_buffer = kmalloc(dma_buffer_size, GFP_KERNEL | GFP_DMA); if (devpriv->dma_buffer == NULL) { - dev_err(dev->class_dev, - "failed to allocate dma buffer\n"); + printk(KERN_ERR " failed to allocate dma buffer\n"); return -ENOMEM; } - if (request_dma(dma_chan, DRV_NAME)) { - dev_err(dev->class_dev, - "failed to allocate dma channel %u\n", - dma_chan); + if (request_dma(dma_chan, driver_labpc.driver_name)) { + printk(KERN_ERR " failed to allocate dma channel %u\n", + dma_chan); return -EINVAL; } devpriv->dma_chan = dma_chan; @@ -597,7 +628,7 @@ int labpc_common_attach(struct comedi_device *dev, unsigned long iobase, return ret; /* analog input subdevice */ - s = &dev->subdevices[0]; + s = dev->subdevices + 0; dev->read_subdev = s; s->type = COMEDI_SUBD_AI; s->subdev_flags = @@ -612,7 +643,7 @@ int labpc_common_attach(struct comedi_device *dev, unsigned long iobase, s->cancel = labpc_cancel; /* analog output */ - s = &dev->subdevices[1]; + s = dev->subdevices + 1; if (thisboard->has_ao) { /* * Could provide command support, except it only has a @@ -639,7 +670,7 @@ int labpc_common_attach(struct comedi_device *dev, unsigned long iobase, } /* 8255 dio */ - s = &dev->subdevices[2]; + s = dev->subdevices + 2; /* if board uses io memory we have to give a custom callback * function to the 8255 driver */ if (thisboard->memory_mapped_io) @@ -649,7 +680,7 @@ int labpc_common_attach(struct comedi_device *dev, unsigned long iobase, subdev_8255_init(dev, s, NULL, dev->iobase + DIO_BASE_REG); /* calibration subdevices for boards that have one */ - s = &dev->subdevices[3]; + s = dev->subdevices + 3; if (thisboard->register_layout == labpc_1200_layout) { s->type = COMEDI_SUBD_CALIB; s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL; @@ -664,7 +695,7 @@ int labpc_common_attach(struct comedi_device *dev, unsigned long iobase, s->type = COMEDI_SUBD_UNUSED; /* EEPROM */ - s = &dev->subdevices[4]; + s = dev->subdevices + 4; if (thisboard->register_layout == labpc_1200_layout) { s->type = COMEDI_SUBD_MEMORY; s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL; @@ -675,6 +706,12 @@ int labpc_common_attach(struct comedi_device *dev, unsigned long iobase, for (i = 0; i < EEPROM_SIZE; i++) devpriv->eeprom_data[i] = labpc_eeprom_read(dev, i); +#ifdef LABPC_DEBUG + printk(KERN_ERR " eeprom:"); + for (i = 0; i < EEPROM_SIZE; i++) + printk(" %i:0x%x ", i, devpriv->eeprom_data[i]); + printk("\n"); +#endif } else s->type = COMEDI_SUBD_UNUSED; @@ -682,52 +719,14 @@ int labpc_common_attach(struct comedi_device *dev, unsigned long iobase, } EXPORT_SYMBOL_GPL(labpc_common_attach); -static const struct labpc_board_struct * -labpc_pci_find_boardinfo(struct pci_dev *pcidev) -{ - unsigned int device_id = pcidev->device; - unsigned int n; - - for (n = 0; n < ARRAY_SIZE(labpc_boards); n++) { - const struct labpc_board_struct *board = &labpc_boards[n]; - if (board->bustype == pci_bustype && - board->device_id == device_id) - return board; - } - return NULL; -} - -static int __devinit labpc_attach_pci(struct comedi_device *dev, - struct pci_dev *pcidev) -{ - unsigned long iobase; - unsigned int irq; - int ret; - - if (!IS_ENABLED(CONFIG_COMEDI_PCI_DRIVERS)) - return -ENODEV; - ret = alloc_private(dev, sizeof(struct labpc_private)); - if (ret < 0) - return ret; - dev->board_ptr = labpc_pci_find_boardinfo(pcidev); - if (!dev->board_ptr) - return -ENODEV; - devpriv->mite = mite_alloc(pcidev); - if (!devpriv->mite) - return -ENOMEM; - ret = mite_setup(devpriv->mite); - if (ret < 0) - return ret; - iobase = (unsigned long)devpriv->mite->daq_io_addr; - irq = mite_irq(devpriv->mite); - return labpc_common_attach(dev, iobase, irq, 0); -} - static int labpc_attach(struct comedi_device *dev, struct comedi_devconfig *it) { unsigned long iobase = 0; unsigned int irq = 0; unsigned int dma_chan = 0; +#ifdef CONFIG_COMEDI_PCI_DRIVERS + int retval; +#endif /* allocate and initialize dev->private */ if (alloc_private(dev, sizeof(struct labpc_private)) < 0) @@ -741,26 +740,34 @@ static int labpc_attach(struct comedi_device *dev, struct comedi_devconfig *it) irq = it->options[1]; dma_chan = it->options[2]; #else - dev_err(dev->class_dev, - "ni_labpc driver has not been built with ISA DMA support.\n"); + printk(KERN_ERR " this driver has not been built with ISA DMA " + "support.\n"); return -EINVAL; #endif break; case pci_bustype: #ifdef CONFIG_COMEDI_PCI_DRIVERS - dev_err(dev->class_dev, - "manual configuration of PCI board '%s' is not supported\n", - thisboard->name); - return -EINVAL; + retval = labpc_find_device(dev, it->options[0], it->options[1]); + if (retval < 0) + return retval; + retval = mite_setup(devpriv->mite); + if (retval < 0) + return retval; + iobase = (unsigned long)devpriv->mite->daq_io_addr; + irq = mite_irq(devpriv->mite); #else - dev_err(dev->class_dev, - "ni_labpc driver has not been built with PCI support.\n"); + printk(KERN_ERR " this driver has not been built with PCI " + "support.\n"); return -EINVAL; #endif break; + case pcmcia_bustype: + printk + (" this driver does not support pcmcia cards, use ni_labpc_cs.o\n"); + return -EINVAL; + break; default: - dev_err(dev->class_dev, - "ni_labpc: bug! couldn't determine board type\n"); + printk(KERN_ERR "bug! couldn't determine board type\n"); return -EINVAL; break; } @@ -768,14 +775,42 @@ static int labpc_attach(struct comedi_device *dev, struct comedi_devconfig *it) return labpc_common_attach(dev, iobase, irq, dma_chan); } -void labpc_common_detach(struct comedi_device *dev) +/* adapted from ni_pcimio for finding mite based boards (pc-1200) */ +#ifdef CONFIG_COMEDI_PCI_DRIVERS +static int labpc_find_device(struct comedi_device *dev, int bus, int slot) { - struct comedi_subdevice *s; - - if (dev->subdevices) { - s = &dev->subdevices[2]; - subdev_8255_cleanup(dev, s); + struct mite_struct *mite; + int i; + for (mite = mite_devices; mite; mite = mite->next) { + if (mite->used) + continue; +/* if bus/slot are specified then make sure we have the right bus/slot */ + if (bus || slot) { + if (bus != mite->pcidev->bus->number + || slot != PCI_SLOT(mite->pcidev->devfn)) + continue; + } + for (i = 0; i < driver_labpc.num_names; i++) { + if (labpc_boards[i].bustype != pci_bustype) + continue; + if (mite_device_id(mite) == labpc_boards[i].device_id) { + devpriv->mite = mite; +/* fixup board pointer, in case we were using the dummy "ni_labpc" entry */ + dev->board_ptr = &labpc_boards[i]; + return 0; + } + } } + printk(KERN_ERR "no device found\n"); + mite_list_devices(); + return -EIO; +} +#endif + +void labpc_common_detach(struct comedi_device *dev) +{ + if (dev->subdevices) + subdev_8255_cleanup(dev, dev->subdevices + 2); #ifdef CONFIG_ISA_DMA_API /* only free stuff if it has been allocated by _attach */ kfree(devpriv->dma_buffer); @@ -787,10 +822,8 @@ void labpc_common_detach(struct comedi_device *dev) if (thisboard->bustype == isa_bustype && dev->iobase) release_region(dev->iobase, LABPC_SIZE); #ifdef CONFIG_COMEDI_PCI_DRIVERS - if (devpriv->mite) { + if (devpriv->mite) mite_unsetup(devpriv->mite); - mite_free(devpriv->mite); - } #endif }; EXPORT_SYMBOL_GPL(labpc_common_detach); @@ -835,19 +868,21 @@ static enum scan_mode labpc_ai_scan_mode(const struct comedi_cmd *cmd) if (CR_CHAN(cmd->chanlist[0]) > CR_CHAN(cmd->chanlist[1])) return MODE_MULT_CHAN_DOWN; - pr_err("ni_labpc: bug! cannot determine AI scan mode\n"); + printk(KERN_ERR "ni_labpc: bug! this should never happen\n"); + return 0; } static int labpc_ai_chanlist_invalid(const struct comedi_device *dev, - const struct comedi_cmd *cmd, - enum scan_mode mode) + const struct comedi_cmd *cmd) { - int channel, range, aref, i; + int mode, channel, range, aref, i; if (cmd->chanlist == NULL) return 0; + mode = labpc_ai_scan_mode(cmd); + if (mode == MODE_SINGLE_CHAN) return 0; @@ -889,8 +924,7 @@ static int labpc_ai_chanlist_invalid(const struct comedi_device *dev, } break; default: - dev_err(dev->class_dev, - "ni_labpc: bug! in chanlist check\n"); + printk(KERN_ERR "ni_labpc: bug! in chanlist check\n"); return 1; break; } @@ -911,10 +945,9 @@ static int labpc_ai_chanlist_invalid(const struct comedi_device *dev, return 0; } -static int labpc_use_continuous_mode(const struct comedi_cmd *cmd, - enum scan_mode mode) +static int labpc_use_continuous_mode(const struct comedi_cmd *cmd) { - if (mode == MODE_SINGLE_CHAN) + if (labpc_ai_scan_mode(cmd) == MODE_SINGLE_CHAN) return 1; if (cmd->scan_begin_src == TRIG_FOLLOW) @@ -923,25 +956,24 @@ static int labpc_use_continuous_mode(const struct comedi_cmd *cmd, return 0; } -static unsigned int labpc_ai_convert_period(const struct comedi_cmd *cmd, - enum scan_mode mode) +static unsigned int labpc_ai_convert_period(const struct comedi_cmd *cmd) { if (cmd->convert_src != TRIG_TIMER) return 0; - if (mode == MODE_SINGLE_CHAN && cmd->scan_begin_src == TRIG_TIMER) + if (labpc_ai_scan_mode(cmd) == MODE_SINGLE_CHAN && + cmd->scan_begin_src == TRIG_TIMER) return cmd->scan_begin_arg; return cmd->convert_arg; } -static void labpc_set_ai_convert_period(struct comedi_cmd *cmd, - enum scan_mode mode, unsigned int ns) +static void labpc_set_ai_convert_period(struct comedi_cmd *cmd, unsigned int ns) { if (cmd->convert_src != TRIG_TIMER) return; - if (mode == MODE_SINGLE_CHAN && + if (labpc_ai_scan_mode(cmd) == MODE_SINGLE_CHAN && cmd->scan_begin_src == TRIG_TIMER) { cmd->scan_begin_arg = ns; if (cmd->convert_arg > cmd->scan_begin_arg) @@ -950,25 +982,25 @@ static void labpc_set_ai_convert_period(struct comedi_cmd *cmd, cmd->convert_arg = ns; } -static unsigned int labpc_ai_scan_period(const struct comedi_cmd *cmd, - enum scan_mode mode) +static unsigned int labpc_ai_scan_period(const struct comedi_cmd *cmd) { if (cmd->scan_begin_src != TRIG_TIMER) return 0; - if (mode == MODE_SINGLE_CHAN && cmd->convert_src == TRIG_TIMER) + if (labpc_ai_scan_mode(cmd) == MODE_SINGLE_CHAN && + cmd->convert_src == TRIG_TIMER) return 0; return cmd->scan_begin_arg; } -static void labpc_set_ai_scan_period(struct comedi_cmd *cmd, - enum scan_mode mode, unsigned int ns) +static void labpc_set_ai_scan_period(struct comedi_cmd *cmd, unsigned int ns) { if (cmd->scan_begin_src != TRIG_TIMER) return; - if (mode == MODE_SINGLE_CHAN && cmd->convert_src == TRIG_TIMER) + if (labpc_ai_scan_mode(cmd) == MODE_SINGLE_CHAN && + cmd->convert_src == TRIG_TIMER) return; cmd->scan_begin_arg = ns; @@ -979,33 +1011,54 @@ static int labpc_ai_cmdtest(struct comedi_device *dev, { int err = 0; int tmp, tmp2; - unsigned int stop_mask; - enum scan_mode mode; + int stop_mask; - /* Step 1 : check if triggers are trivially valid */ + /* step 1: make sure trigger sources are trivially valid */ - err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_EXT); - err |= cfc_check_trigger_src(&cmd->scan_begin_src, - TRIG_TIMER | TRIG_FOLLOW | TRIG_EXT); - err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_TIMER | TRIG_EXT); - err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT); + tmp = cmd->start_src; + cmd->start_src &= TRIG_NOW | TRIG_EXT; + if (!cmd->start_src || tmp != cmd->start_src) + err++; + + tmp = cmd->scan_begin_src; + cmd->scan_begin_src &= TRIG_TIMER | TRIG_FOLLOW | TRIG_EXT; + if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) + err++; + tmp = cmd->convert_src; + cmd->convert_src &= TRIG_TIMER | TRIG_EXT; + if (!cmd->convert_src || tmp != cmd->convert_src) + err++; + + tmp = cmd->scan_end_src; + cmd->scan_end_src &= TRIG_COUNT; + if (!cmd->scan_end_src || tmp != cmd->scan_end_src) + err++; + + tmp = cmd->stop_src; stop_mask = TRIG_COUNT | TRIG_NONE; if (thisboard->register_layout == labpc_1200_layout) stop_mask |= TRIG_EXT; - err |= cfc_check_trigger_src(&cmd->stop_src, stop_mask); + cmd->stop_src &= stop_mask; + if (!cmd->stop_src || tmp != cmd->stop_src) + err++; if (err) return 1; - /* Step 2a : make sure trigger sources are unique */ + /* step 2: make sure trigger sources are unique and mutually compatible */ - err |= cfc_check_trigger_is_unique(cmd->start_src); - err |= cfc_check_trigger_is_unique(cmd->scan_begin_src); - err |= cfc_check_trigger_is_unique(cmd->convert_src); - err |= cfc_check_trigger_is_unique(cmd->stop_src); - - /* Step 2b : and mutually compatible */ + if (cmd->start_src != TRIG_NOW && cmd->start_src != TRIG_EXT) + err++; + if (cmd->scan_begin_src != TRIG_TIMER && + cmd->scan_begin_src != TRIG_FOLLOW && + cmd->scan_begin_src != TRIG_EXT) + err++; + if (cmd->convert_src != TRIG_TIMER && cmd->convert_src != TRIG_EXT) + err++; + if (cmd->stop_src != TRIG_COUNT && + cmd->stop_src != TRIG_EXT && cmd->stop_src != TRIG_NONE) + err++; /* can't have external stop and start triggers at once */ if (cmd->start_src == TRIG_EXT && cmd->stop_src == TRIG_EXT) @@ -1080,15 +1133,14 @@ static int labpc_ai_cmdtest(struct comedi_device *dev, tmp = cmd->convert_arg; tmp2 = cmd->scan_begin_arg; - mode = labpc_ai_scan_mode(cmd); - labpc_adc_timing(dev, cmd, mode); + labpc_adc_timing(dev, cmd); if (tmp != cmd->convert_arg || tmp2 != cmd->scan_begin_arg) err++; if (err) return 4; - if (labpc_ai_chanlist_invalid(dev, cmd, mode)) + if (labpc_ai_chanlist_invalid(dev, cmd)) return 5; return 0; @@ -1104,7 +1156,6 @@ static int labpc_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) struct comedi_async *async = s->async; struct comedi_cmd *cmd = &async->cmd; enum transfer_type xfer; - enum scan_mode mode; unsigned long flags; if (!dev->irq) { @@ -1170,7 +1221,6 @@ static int labpc_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) } else xfer = fifo_not_empty_transfer; devpriv->current_transfer = xfer; - mode = labpc_ai_scan_mode(cmd); /* setup command6 register for 1200 boards */ if (thisboard->register_layout == labpc_1200_layout) { @@ -1195,7 +1245,7 @@ static int labpc_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) else devpriv->command6_bits &= ~A1_INTR_EN_BIT; /* are we scanning up or down through channels? */ - if (mode == MODE_MULT_CHAN_UP) + if (labpc_ai_scan_mode(cmd) == MODE_MULT_CHAN_UP) devpriv->command6_bits |= ADC_SCAN_UP_BIT; else devpriv->command6_bits &= ~ADC_SCAN_UP_BIT; @@ -1206,18 +1256,19 @@ static int labpc_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) /* setup channel list, etc (command1 register) */ devpriv->command1_bits = 0; - if (mode == MODE_MULT_CHAN_UP) + if (labpc_ai_scan_mode(cmd) == MODE_MULT_CHAN_UP) channel = CR_CHAN(cmd->chanlist[cmd->chanlist_len - 1]); else channel = CR_CHAN(cmd->chanlist[0]); /* munge channel bits for differential / scan disabled mode */ - if (mode != MODE_SINGLE_CHAN && aref == AREF_DIFF) + if (labpc_ai_scan_mode(cmd) != MODE_SINGLE_CHAN && aref == AREF_DIFF) channel *= 2; devpriv->command1_bits |= ADC_CHAN_BITS(channel); devpriv->command1_bits |= thisboard->ai_range_code[range]; devpriv->write_byte(devpriv->command1_bits, dev->iobase + COMMAND1_REG); /* manual says to set scan enable bit on second pass */ - if (mode == MODE_MULT_CHAN_UP || mode == MODE_MULT_CHAN_DOWN) { + if (labpc_ai_scan_mode(cmd) == MODE_MULT_CHAN_UP || + labpc_ai_scan_mode(cmd) == MODE_MULT_CHAN_DOWN) { devpriv->command1_bits |= ADC_SCAN_EN_BIT; /* need a brief delay before enabling scan, or scan * list will get screwed when you switch @@ -1232,7 +1283,7 @@ static int labpc_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) devpriv->command4_bits |= EXT_CONVERT_DISABLE_BIT; /* XXX should discard first scan when using interval scanning * since manual says it is not synced with scan clock */ - if (labpc_use_continuous_mode(cmd, mode) == 0) { + if (labpc_use_continuous_mode(cmd) == 0) { devpriv->command4_bits |= INTERVAL_SCAN_EN_BIT; if (cmd->scan_begin_src == TRIG_EXT) devpriv->command4_bits |= EXT_SCAN_EN_BIT; @@ -1250,7 +1301,7 @@ static int labpc_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) if (cmd->convert_src == TRIG_TIMER || cmd->scan_begin_src == TRIG_TIMER) { /* set up pacing */ - labpc_adc_timing(dev, cmd, mode); + labpc_adc_timing(dev, cmd); /* load counter b0 in mode 3 */ ret = labpc_counter_load(dev, dev->iobase + COUNTER_B_BASE_REG, 0, devpriv->divisor_b0, 3); @@ -1260,7 +1311,7 @@ static int labpc_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) } } /* set up conversion pacing */ - if (labpc_ai_convert_period(cmd, mode)) { + if (labpc_ai_convert_period(cmd)) { /* load counter a0 in mode 2 */ ret = labpc_counter_load(dev, dev->iobase + COUNTER_A_BASE_REG, 0, devpriv->divisor_a0, 2); @@ -1273,7 +1324,7 @@ static int labpc_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) dev->iobase + COUNTER_A_CONTROL_REG); /* set up scan pacing */ - if (labpc_ai_scan_period(cmd, mode)) { + if (labpc_ai_scan_period(cmd)) { /* load counter b1 in mode 2 */ ret = labpc_counter_load(dev, dev->iobase + COUNTER_B_BASE_REG, 1, devpriv->divisor_b1, 2); @@ -1296,7 +1347,7 @@ static int labpc_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) set_dma_addr(devpriv->dma_chan, virt_to_bus(devpriv->dma_buffer)); /* set appropriate size of transfer */ - devpriv->dma_transfer_size = labpc_suggest_transfer_size(cmd); + devpriv->dma_transfer_size = labpc_suggest_transfer_size(*cmd); if (cmd->stop_src == TRIG_COUNT && devpriv->count * sample_size < devpriv->dma_transfer_size) { devpriv->dma_transfer_size = @@ -1735,8 +1786,8 @@ static int labpc_eeprom_write_insn(struct comedi_device *dev, /* only allow writes to user area of eeprom */ if (channel < 16 || channel > 127) { - dev_dbg(dev->class_dev, - "eeprom writes are only allowed to channels 16 through 127 (the pointer and user areas)\n"); + printk + ("eeprom writes are only allowed to channels 16 through 127 (the pointer and user areas)"); return -EINVAL; } @@ -1749,13 +1800,13 @@ static int labpc_eeprom_write_insn(struct comedi_device *dev, #ifdef CONFIG_ISA_DMA_API /* utility function that suggests a dma transfer size in bytes */ -static unsigned int labpc_suggest_transfer_size(const struct comedi_cmd *cmd) +static unsigned int labpc_suggest_transfer_size(struct comedi_cmd cmd) { unsigned int size; unsigned int freq; - if (cmd->convert_src == TRIG_TIMER) - freq = 1000000000 / cmd->convert_arg; + if (cmd.convert_src == TRIG_TIMER) + freq = 1000000000 / cmd.convert_arg; /* return some default value */ else freq = 0xffffffff; @@ -1774,29 +1825,24 @@ static unsigned int labpc_suggest_transfer_size(const struct comedi_cmd *cmd) #endif /* figures out what counter values to use based on command */ -static void labpc_adc_timing(struct comedi_device *dev, struct comedi_cmd *cmd, - enum scan_mode mode) +static void labpc_adc_timing(struct comedi_device *dev, struct comedi_cmd *cmd) { /* max value for 16 bit counter in mode 2 */ const int max_counter_value = 0x10000; /* min value for 16 bit counter in mode 2 */ const int min_counter_value = 2; unsigned int base_period; - unsigned int scan_period; - unsigned int convert_period; /* * if both convert and scan triggers are TRIG_TIMER, then they * both rely on counter b0 */ - convert_period = labpc_ai_convert_period(cmd, mode); - scan_period = labpc_ai_scan_period(cmd, mode); - if (convert_period && scan_period) { + if (labpc_ai_convert_period(cmd) && labpc_ai_scan_period(cmd)) { /* * pick the lowest b0 divisor value we can (for maximum input * clock speed on convert and scan counters) */ - devpriv->divisor_b0 = (scan_period - 1) / + devpriv->divisor_b0 = (labpc_ai_scan_period(cmd) - 1) / (LABPC_TIMER_BASE * max_counter_value) + 1; if (devpriv->divisor_b0 < min_counter_value) devpriv->divisor_b0 = min_counter_value; @@ -1810,19 +1856,25 @@ static void labpc_adc_timing(struct comedi_device *dev, struct comedi_cmd *cmd, default: case TRIG_ROUND_NEAREST: devpriv->divisor_a0 = - (convert_period + (base_period / 2)) / base_period; + (labpc_ai_convert_period(cmd) + + (base_period / 2)) / base_period; devpriv->divisor_b1 = - (scan_period + (base_period / 2)) / base_period; + (labpc_ai_scan_period(cmd) + + (base_period / 2)) / base_period; break; case TRIG_ROUND_UP: devpriv->divisor_a0 = - (convert_period + (base_period - 1)) / base_period; + (labpc_ai_convert_period(cmd) + (base_period - + 1)) / base_period; devpriv->divisor_b1 = - (scan_period + (base_period - 1)) / base_period; + (labpc_ai_scan_period(cmd) + (base_period - + 1)) / base_period; break; case TRIG_ROUND_DOWN: - devpriv->divisor_a0 = convert_period / base_period; - devpriv->divisor_b1 = scan_period / base_period; + devpriv->divisor_a0 = + labpc_ai_convert_period(cmd) / base_period; + devpriv->divisor_b1 = + labpc_ai_scan_period(cmd) / base_period; break; } /* make sure a0 and b1 values are acceptable */ @@ -1835,15 +1887,18 @@ static void labpc_adc_timing(struct comedi_device *dev, struct comedi_cmd *cmd, if (devpriv->divisor_b1 > max_counter_value) devpriv->divisor_b1 = max_counter_value; /* write corrected timings to command */ - labpc_set_ai_convert_period(cmd, mode, + labpc_set_ai_convert_period(cmd, base_period * devpriv->divisor_a0); - labpc_set_ai_scan_period(cmd, mode, + labpc_set_ai_scan_period(cmd, base_period * devpriv->divisor_b1); /* * if only one TRIG_TIMER is used, we can employ the generic * cascaded timing functions */ - } else if (scan_period) { + } else if (labpc_ai_scan_period(cmd)) { + unsigned int scan_period; + + scan_period = labpc_ai_scan_period(cmd); /* * calculate cascaded counter values * that give desired scan timing @@ -1853,8 +1908,11 @@ static void labpc_adc_timing(struct comedi_device *dev, struct comedi_cmd *cmd, &(devpriv->divisor_b0), &scan_period, cmd->flags & TRIG_ROUND_MASK); - labpc_set_ai_scan_period(cmd, mode, scan_period); - } else if (convert_period) { + labpc_set_ai_scan_period(cmd, scan_period); + } else if (labpc_ai_convert_period(cmd)) { + unsigned int convert_period; + + convert_period = labpc_ai_convert_period(cmd); /* * calculate cascaded counter values * that give desired conversion timing @@ -1864,7 +1922,7 @@ static void labpc_adc_timing(struct comedi_device *dev, struct comedi_cmd *cmd, &(devpriv->divisor_b0), &convert_period, cmd->flags & TRIG_ROUND_MASK); - labpc_set_ai_convert_period(cmd, mode, convert_period); + labpc_set_ai_convert_period(cmd, convert_period); } } @@ -1872,10 +1930,10 @@ static int labpc_dio_mem_callback(int dir, int port, int data, unsigned long iobase) { if (dir) { - writeb(data, (void __iomem *)(iobase + port)); + writeb(data, (void *)(iobase + port)); return 0; } else { - return readb((void __iomem *)(iobase + port)); + return readb((void *)(iobase + port)); } } @@ -2078,44 +2136,57 @@ static void write_caldac(struct comedi_device *dev, unsigned int channel, devpriv->write_byte(devpriv->command5_bits, dev->iobase + COMMAND5_REG); } -static struct comedi_driver labpc_driver = { - .driver_name = DRV_NAME, - .module = THIS_MODULE, - .attach = labpc_attach, - .attach_pci = labpc_attach_pci, - .detach = labpc_common_detach, - .num_names = ARRAY_SIZE(labpc_boards), - .board_name = &labpc_boards[0].name, - .offset = sizeof(struct labpc_board_struct), -}; - #ifdef CONFIG_COMEDI_PCI_DRIVERS -static DEFINE_PCI_DEVICE_TABLE(labpc_pci_table) = { - {PCI_DEVICE(PCI_VENDOR_ID_NI, 0x161)}, - {0} -}; -MODULE_DEVICE_TABLE(pci, labpc_pci_table); - -static int __devinit labpc_pci_probe(struct pci_dev *dev, - const struct pci_device_id *ent) +static int __devinit driver_labpc_pci_probe(struct pci_dev *dev, + const struct pci_device_id *ent) { - return comedi_pci_auto_config(dev, &labpc_driver); + return comedi_pci_auto_config(dev, &driver_labpc); } -static void __devexit labpc_pci_remove(struct pci_dev *dev) +static void __devexit driver_labpc_pci_remove(struct pci_dev *dev) { comedi_pci_auto_unconfig(dev); } -static struct pci_driver labpc_pci_driver = { - .name = DRV_NAME, +static struct pci_driver driver_labpc_pci_driver = { .id_table = labpc_pci_table, - .probe = labpc_pci_probe, - .remove = __devexit_p(labpc_pci_remove) + .probe = &driver_labpc_pci_probe, + .remove = __devexit_p(&driver_labpc_pci_remove) }; -module_comedi_pci_driver(labpc_driver, labpc_pci_driver); + +static int __init driver_labpc_init_module(void) +{ + int retval; + + retval = comedi_driver_register(&driver_labpc); + if (retval < 0) + return retval; + + driver_labpc_pci_driver.name = (char *)driver_labpc.driver_name; + return pci_register_driver(&driver_labpc_pci_driver); +} + +static void __exit driver_labpc_cleanup_module(void) +{ + pci_unregister_driver(&driver_labpc_pci_driver); + comedi_driver_unregister(&driver_labpc); +} + +module_init(driver_labpc_init_module); +module_exit(driver_labpc_cleanup_module); #else -module_comedi_driver(labpc_driver); +static int __init driver_labpc_init_module(void) +{ + return comedi_driver_register(&driver_labpc); +} + +static void __exit driver_labpc_cleanup_module(void) +{ + comedi_driver_unregister(&driver_labpc); +} + +module_init(driver_labpc_init_module); +module_exit(driver_labpc_cleanup_module); #endif diff --git a/trunk/drivers/staging/comedi/drivers/ni_labpc_cs.c b/trunk/drivers/staging/comedi/drivers/ni_labpc_cs.c index eb0417eb6d7d..dbb61b6b3ed1 100644 --- a/trunk/drivers/staging/comedi/drivers/ni_labpc_cs.c +++ b/trunk/drivers/staging/comedi/drivers/ni_labpc_cs.c @@ -270,7 +270,7 @@ MODULE_AUTHOR("Frank Mori Hess "); MODULE_DESCRIPTION("Comedi driver for National Instruments Lab-PC"); MODULE_LICENSE("GPL"); -static struct pcmcia_driver labpc_cs_driver = { +struct pcmcia_driver labpc_cs_driver = { .probe = labpc_cs_attach, .remove = labpc_cs_detach, .suspend = labpc_cs_suspend, @@ -291,7 +291,7 @@ static void __exit exit_labpc_cs(void) pcmcia_unregister_driver(&labpc_cs_driver); } -static int __init labpc_init_module(void) +int __init labpc_init_module(void) { int ret; @@ -302,7 +302,7 @@ static int __init labpc_init_module(void) return comedi_driver_register(&driver_labpc_cs); } -static void __exit labpc_exit_module(void) +void __exit labpc_exit_module(void) { exit_labpc_cs(); comedi_driver_unregister(&driver_labpc_cs); diff --git a/trunk/drivers/staging/comedi/drivers/ni_mio_common.c b/trunk/drivers/staging/comedi/drivers/ni_mio_common.c index 3e5fdae93163..cf0e0d147f8c 100644 --- a/trunk/drivers/staging/comedi/drivers/ni_mio_common.c +++ b/trunk/drivers/staging/comedi/drivers/ni_mio_common.c @@ -644,10 +644,10 @@ static void ni_release_ao_mite_channel(struct comedi_device *dev) #endif /* PCIDMA */ } -#ifdef PCIDMA -static void ni_release_gpct_mite_channel(struct comedi_device *dev, - unsigned gpct_index) +void ni_release_gpct_mite_channel(struct comedi_device *dev, + unsigned gpct_index) { +#ifdef PCIDMA unsigned long flags; BUG_ON(gpct_index >= NUM_GPCT); @@ -663,8 +663,8 @@ static void ni_release_gpct_mite_channel(struct comedi_device *dev, mite_release_channel(mite_chan); } spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags); -} #endif /* PCIDMA */ +} static void ni_release_cdo_mite_channel(struct comedi_device *dev) { @@ -872,7 +872,7 @@ static irqreturn_t ni_E_interrupt(int irq, void *d) #ifdef PCIDMA static void ni_sync_ai_dma(struct comedi_device *dev) { - struct comedi_subdevice *s = &dev->subdevices[NI_AI_SUBDEV]; + struct comedi_subdevice *s = dev->subdevices + NI_AI_SUBDEV; unsigned long flags; spin_lock_irqsave(&devpriv->mite_channel_lock, flags); @@ -884,7 +884,7 @@ static void ni_sync_ai_dma(struct comedi_device *dev) static void mite_handle_b_linkc(struct mite_struct *mite, struct comedi_device *dev) { - struct comedi_subdevice *s = &dev->subdevices[NI_AO_SUBDEV]; + struct comedi_subdevice *s = dev->subdevices + NI_AO_SUBDEV; unsigned long flags; spin_lock_irqsave(&devpriv->mite_channel_lock, flags); @@ -942,7 +942,7 @@ static void ni_handle_eos(struct comedi_device *dev, struct comedi_subdevice *s) static void shutdown_ai_command(struct comedi_device *dev) { - struct comedi_subdevice *s = &dev->subdevices[NI_AI_SUBDEV]; + struct comedi_subdevice *s = dev->subdevices + NI_AI_SUBDEV; #ifdef PCIDMA ni_ai_drain_dma(dev); @@ -984,9 +984,8 @@ static void handle_gpct_interrupt(struct comedi_device *dev, unsigned short counter_index) { #ifdef PCIDMA - struct comedi_subdevice *s; - - s = &dev->subdevices[NI_GPCT_SUBDEV(counter_index)]; + struct comedi_subdevice *s = + dev->subdevices + NI_GPCT_SUBDEV(counter_index); ni_tio_handle_interrupt(&devpriv->counter_dev->counters[counter_index], s); @@ -1019,7 +1018,7 @@ static void ack_a_interrupt(struct comedi_device *dev, unsigned short a_status) static void handle_a_interrupt(struct comedi_device *dev, unsigned short status, unsigned ai_mite_status) { - struct comedi_subdevice *s = &dev->subdevices[NI_AI_SUBDEV]; + struct comedi_subdevice *s = dev->subdevices + NI_AI_SUBDEV; /* 67xx boards don't have ai subdevice, but their gpct0 might generate an a interrupt */ if (s->type == COMEDI_SUBD_UNUSED) @@ -1151,7 +1150,7 @@ static void ack_b_interrupt(struct comedi_device *dev, unsigned short b_status) static void handle_b_interrupt(struct comedi_device *dev, unsigned short b_status, unsigned ao_mite_status) { - struct comedi_subdevice *s = &dev->subdevices[NI_AO_SUBDEV]; + struct comedi_subdevice *s = dev->subdevices + NI_AO_SUBDEV; /* unsigned short ack=0; */ #ifdef DEBUG_INTERRUPT printk("ni_mio_common: interrupt: b_status=%04x m1_status=%08x\n", @@ -1423,7 +1422,7 @@ static void ni_ai_fifo_read(struct comedi_device *dev, static void ni_handle_fifo_half_full(struct comedi_device *dev) { int n; - struct comedi_subdevice *s = &dev->subdevices[NI_AI_SUBDEV]; + struct comedi_subdevice *s = dev->subdevices + NI_AI_SUBDEV; n = boardtype.ai_fifo_depth / 2; @@ -1471,7 +1470,7 @@ static int ni_ai_drain_dma(struct comedi_device *dev) */ static void ni_handle_fifo_dregs(struct comedi_device *dev) { - struct comedi_subdevice *s = &dev->subdevices[NI_AI_SUBDEV]; + struct comedi_subdevice *s = dev->subdevices + NI_AI_SUBDEV; short data[2]; u32 dl; short fifo_empty; @@ -1535,7 +1534,7 @@ static void ni_handle_fifo_dregs(struct comedi_device *dev) static void get_last_sample_611x(struct comedi_device *dev) { - struct comedi_subdevice *s = &dev->subdevices[NI_AI_SUBDEV]; + struct comedi_subdevice *s = dev->subdevices + NI_AI_SUBDEV; short data; u32 dl; @@ -1552,7 +1551,7 @@ static void get_last_sample_611x(struct comedi_device *dev) static void get_last_sample_6143(struct comedi_device *dev) { - struct comedi_subdevice *s = &dev->subdevices[NI_AI_SUBDEV]; + struct comedi_subdevice *s = dev->subdevices + NI_AI_SUBDEV; short data; u32 dl; @@ -1599,7 +1598,7 @@ static void ni_ai_munge(struct comedi_device *dev, struct comedi_subdevice *s, static int ni_ai_setup_MITE_dma(struct comedi_device *dev) { - struct comedi_subdevice *s = &dev->subdevices[NI_AI_SUBDEV]; + struct comedi_subdevice *s = dev->subdevices + NI_AI_SUBDEV; int retval; unsigned long flags; @@ -1638,7 +1637,7 @@ static int ni_ai_setup_MITE_dma(struct comedi_device *dev) static int ni_ao_setup_MITE_dma(struct comedi_device *dev) { - struct comedi_subdevice *s = &dev->subdevices[NI_AO_SUBDEV]; + struct comedi_subdevice *s = dev->subdevices + NI_AO_SUBDEV; int retval; unsigned long flags; @@ -1766,18 +1765,20 @@ static int ni_ai_reset(struct comedi_device *dev, struct comedi_subdevice *s) static int ni_ai_poll(struct comedi_device *dev, struct comedi_subdevice *s) { - unsigned long flags; + unsigned long flags = 0; int count; /* lock to avoid race with interrupt handler */ - spin_lock_irqsave(&dev->spinlock, flags); + if (in_interrupt() == 0) + spin_lock_irqsave(&dev->spinlock, flags); #ifndef PCIDMA ni_handle_fifo_dregs(dev); #else ni_sync_ai_dma(dev); #endif count = s->async->buf_write_count - s->async->buf_read_count; - spin_unlock_irqrestore(&dev->spinlock, flags); + if (in_interrupt() == 0) + spin_unlock_irqrestore(&dev->spinlock, flags); return count; } @@ -1879,7 +1880,7 @@ static int ni_ai_insn_read(struct comedi_device *dev, return insn->n; } -static void ni_prime_channelgain_list(struct comedi_device *dev) +void ni_prime_channelgain_list(struct comedi_device *dev) { int i; devpriv->stc_writew(dev, AI_CONVERT_Pulse, AI_Command_1_Register); @@ -2164,38 +2165,61 @@ static int ni_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, { int err = 0; int tmp; - unsigned int sources; + int sources; - /* Step 1 : check if triggers are trivially valid */ + /* step 1: make sure trigger sources are trivially valid */ - if ((cmd->flags & CMDF_WRITE)) + if ((cmd->flags & CMDF_WRITE)) { cmd->flags &= ~CMDF_WRITE; + } - err |= cfc_check_trigger_src(&cmd->start_src, - TRIG_NOW | TRIG_INT | TRIG_EXT); - err |= cfc_check_trigger_src(&cmd->scan_begin_src, - TRIG_TIMER | TRIG_EXT); + tmp = cmd->start_src; + cmd->start_src &= TRIG_NOW | TRIG_INT | TRIG_EXT; + if (!cmd->start_src || tmp != cmd->start_src) + err++; + + tmp = cmd->scan_begin_src; + cmd->scan_begin_src &= TRIG_TIMER | TRIG_EXT; + if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) + err++; + tmp = cmd->convert_src; sources = TRIG_TIMER | TRIG_EXT; - if (boardtype.reg_type == ni_reg_611x || - boardtype.reg_type == ni_reg_6143) + if ((boardtype.reg_type == ni_reg_611x) + || (boardtype.reg_type == ni_reg_6143)) sources |= TRIG_NOW; - err |= cfc_check_trigger_src(&cmd->convert_src, sources); + cmd->convert_src &= sources; + if (!cmd->convert_src || tmp != cmd->convert_src) + err++; + + tmp = cmd->scan_end_src; + cmd->scan_end_src &= TRIG_COUNT; + if (!cmd->scan_end_src || tmp != cmd->scan_end_src) + err++; - err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT); - err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE); + tmp = cmd->stop_src; + cmd->stop_src &= TRIG_COUNT | TRIG_NONE; + if (!cmd->stop_src || tmp != cmd->stop_src) + err++; if (err) return 1; - /* Step 2a : make sure trigger sources are unique */ + /* step 2: make sure trigger sources are unique and mutually compatible */ - err |= cfc_check_trigger_is_unique(cmd->start_src); - err |= cfc_check_trigger_is_unique(cmd->scan_begin_src); - err |= cfc_check_trigger_is_unique(cmd->convert_src); - err |= cfc_check_trigger_is_unique(cmd->stop_src); - - /* Step 2b : and mutually compatible */ + /* note that mutual compatibility is not an issue here */ + if (cmd->start_src != TRIG_NOW && + cmd->start_src != TRIG_INT && cmd->start_src != TRIG_EXT) + err++; + if (cmd->scan_begin_src != TRIG_TIMER && + cmd->scan_begin_src != TRIG_EXT && + cmd->scan_begin_src != TRIG_OTHER) + err++; + if (cmd->convert_src != TRIG_TIMER && + cmd->convert_src != TRIG_EXT && cmd->convert_src != TRIG_NOW) + err++; + if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE) + err++; if (err) return 2; @@ -3333,28 +3357,44 @@ static int ni_ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, int err = 0; int tmp; - /* Step 1 : check if triggers are trivially valid */ + /* step 1: make sure trigger sources are trivially valid */ - if ((cmd->flags & CMDF_WRITE) == 0) + if ((cmd->flags & CMDF_WRITE) == 0) { cmd->flags |= CMDF_WRITE; + } - err |= cfc_check_trigger_src(&cmd->start_src, TRIG_INT | TRIG_EXT); - err |= cfc_check_trigger_src(&cmd->scan_begin_src, - TRIG_TIMER | TRIG_EXT); - err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_NOW); - err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT); - err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE); + tmp = cmd->start_src; + cmd->start_src &= TRIG_INT | TRIG_EXT; + if (!cmd->start_src || tmp != cmd->start_src) + err++; + + tmp = cmd->scan_begin_src; + cmd->scan_begin_src &= TRIG_TIMER | TRIG_EXT; + if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) + err++; + + tmp = cmd->convert_src; + cmd->convert_src &= TRIG_NOW; + if (!cmd->convert_src || tmp != cmd->convert_src) + err++; + + tmp = cmd->scan_end_src; + cmd->scan_end_src &= TRIG_COUNT; + if (!cmd->scan_end_src || tmp != cmd->scan_end_src) + err++; + + tmp = cmd->stop_src; + cmd->stop_src &= TRIG_COUNT | TRIG_NONE; + if (!cmd->stop_src || tmp != cmd->stop_src) + err++; if (err) return 1; - /* Step 2a : make sure trigger sources are unique */ - - err |= cfc_check_trigger_is_unique(cmd->start_src); - err |= cfc_check_trigger_is_unique(cmd->scan_begin_src); - err |= cfc_check_trigger_is_unique(cmd->stop_src); + /* step 2: make sure trigger sources are unique and mutually compatible */ - /* Step 2b : and mutually compatible */ + if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE) + err++; if (err) return 2; @@ -3604,21 +3644,51 @@ static int ni_cdio_cmdtest(struct comedi_device *dev, { int err = 0; int tmp; + int sources; unsigned i; - /* Step 1 : check if triggers are trivially valid */ + /* step 1: make sure trigger sources are trivially valid */ + + tmp = cmd->start_src; + sources = TRIG_INT; + cmd->start_src &= sources; + if (!cmd->start_src || tmp != cmd->start_src) + err++; + + tmp = cmd->scan_begin_src; + cmd->scan_begin_src &= TRIG_EXT; + if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) + err++; - err |= cfc_check_trigger_src(&cmd->start_src, TRIG_INT); - err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_EXT); - err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_NOW); - err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT); - err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_NONE); + tmp = cmd->convert_src; + cmd->convert_src &= TRIG_NOW; + if (!cmd->convert_src || tmp != cmd->convert_src) + err++; + + tmp = cmd->scan_end_src; + cmd->scan_end_src &= TRIG_COUNT; + if (!cmd->scan_end_src || tmp != cmd->scan_end_src) + err++; + + tmp = cmd->stop_src; + cmd->stop_src &= TRIG_NONE; + if (!cmd->stop_src || tmp != cmd->stop_src) + err++; if (err) return 1; - /* Step 2a : make sure trigger sources are unique */ - /* Step 2b : and mutually compatible */ + /* step 2: make sure trigger sources are unique... */ + + if (cmd->start_src != TRIG_INT) + err++; + if (cmd->scan_begin_src != TRIG_EXT) + err++; + if (cmd->convert_src != TRIG_NOW) + err++; + if (cmd->stop_src != TRIG_NONE) + err++; + /* ... and mutually compatible */ if (err) return 2; @@ -3782,7 +3852,7 @@ static int ni_cdio_cancel(struct comedi_device *dev, struct comedi_subdevice *s) static void handle_cdio_interrupt(struct comedi_device *dev) { unsigned cdio_status; - struct comedi_subdevice *s = &dev->subdevices[NI_DIO_SUBDEV]; + struct comedi_subdevice *s = dev->subdevices + NI_DIO_SUBDEV; #ifdef PCIDMA unsigned long flags; #endif @@ -4031,17 +4101,13 @@ static int ni_serial_sw_readwrite8(struct comedi_device *dev, static void mio_common_detach(struct comedi_device *dev) { - struct comedi_subdevice *s; - if (dev->private) { if (devpriv->counter_dev) { ni_gpct_device_destroy(devpriv->counter_dev); } } - if (dev->subdevices && boardtype.has_8255) { - s = &dev->subdevices[NI_8255_DIO_SUBDEV]; - subdev_8255_cleanup(dev, s); - } + if (dev->subdevices && boardtype.has_8255) + subdev_8255_cleanup(dev, dev->subdevices + NI_8255_DIO_SUBDEV); } static void init_ao_67xx(struct comedi_device *dev, struct comedi_subdevice *s) @@ -4333,7 +4399,7 @@ static int ni_alloc_private(struct comedi_device *dev) return 0; }; -static int ni_E_init(struct comedi_device *dev) +static int ni_E_init(struct comedi_device *dev, struct comedi_devconfig *it) { struct comedi_subdevice *s; unsigned j; @@ -4351,7 +4417,7 @@ static int ni_E_init(struct comedi_device *dev) /* analog input subdevice */ - s = &dev->subdevices[NI_AI_SUBDEV]; + s = dev->subdevices + NI_AI_SUBDEV; dev->read_subdev = s; if (boardtype.n_adchan) { s->type = COMEDI_SUBD_AI; @@ -4383,7 +4449,7 @@ static int ni_E_init(struct comedi_device *dev) /* analog output subdevice */ - s = &dev->subdevices[NI_AO_SUBDEV]; + s = dev->subdevices + NI_AO_SUBDEV; if (boardtype.n_aochan) { s->type = COMEDI_SUBD_AO; s->subdev_flags = SDF_WRITABLE | SDF_DEGLITCH | SDF_GROUND; @@ -4422,7 +4488,7 @@ static int ni_E_init(struct comedi_device *dev) /* digital i/o subdevice */ - s = &dev->subdevices[NI_DIO_SUBDEV]; + s = dev->subdevices + NI_DIO_SUBDEV; s->type = COMEDI_SUBD_DIO; s->subdev_flags = SDF_WRITABLE | SDF_READABLE; s->maxdata = 1; @@ -4450,7 +4516,7 @@ static int ni_E_init(struct comedi_device *dev) } /* 8255 device */ - s = &dev->subdevices[NI_8255_DIO_SUBDEV]; + s = dev->subdevices + NI_8255_DIO_SUBDEV; if (boardtype.has_8255) { subdev_8255_init(dev, s, ni_8255_callback, (unsigned long)dev); } else { @@ -4458,11 +4524,11 @@ static int ni_E_init(struct comedi_device *dev) } /* formerly general purpose counter/timer device, but no longer used */ - s = &dev->subdevices[NI_UNUSED_SUBDEV]; + s = dev->subdevices + NI_UNUSED_SUBDEV; s->type = COMEDI_SUBD_UNUSED; /* calibration subdevice -- ai and ao */ - s = &dev->subdevices[NI_CALIBRATION_SUBDEV]; + s = dev->subdevices + NI_CALIBRATION_SUBDEV; s->type = COMEDI_SUBD_CALIB; if (boardtype.reg_type & ni_reg_m_series_mask) { /* internal PWM analog output used for AI nonlinearity calibration */ @@ -4485,7 +4551,7 @@ static int ni_E_init(struct comedi_device *dev) } /* EEPROM */ - s = &dev->subdevices[NI_EEPROM_SUBDEV]; + s = dev->subdevices + NI_EEPROM_SUBDEV; s->type = COMEDI_SUBD_MEMORY; s->subdev_flags = SDF_READABLE | SDF_INTERNAL; s->maxdata = 0xff; @@ -4498,7 +4564,7 @@ static int ni_E_init(struct comedi_device *dev) } /* PFI */ - s = &dev->subdevices[NI_PFI_DIO_SUBDEV]; + s = dev->subdevices + NI_PFI_DIO_SUBDEV; s->type = COMEDI_SUBD_DIO; s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL; if (boardtype.reg_type & ni_reg_m_series_mask) { @@ -4520,7 +4586,7 @@ static int ni_E_init(struct comedi_device *dev) ni_set_bits(dev, IO_Bidirection_Pin_Register, ~0, 0); /* cs5529 calibration adc */ - s = &dev->subdevices[NI_CS5529_CALIBRATION_SUBDEV]; + s = dev->subdevices + NI_CS5529_CALIBRATION_SUBDEV; if (boardtype.reg_type & ni_reg_67xx_mask) { s->type = COMEDI_SUBD_AI; s->subdev_flags = SDF_READABLE | SDF_DIFF | SDF_INTERNAL; @@ -4536,7 +4602,7 @@ static int ni_E_init(struct comedi_device *dev) } /* Serial */ - s = &dev->subdevices[NI_SERIAL_SUBDEV]; + s = dev->subdevices + NI_SERIAL_SUBDEV; s->type = COMEDI_SUBD_SERIAL; s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL; s->n_chan = 1; @@ -4546,7 +4612,7 @@ static int ni_E_init(struct comedi_device *dev) devpriv->serial_hw_mode = 0; /* RTSI */ - s = &dev->subdevices[NI_RTSI_SUBDEV]; + s = dev->subdevices + NI_RTSI_SUBDEV; s->type = COMEDI_SUBD_DIO; s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL; s->n_chan = 8; @@ -4567,7 +4633,7 @@ static int ni_E_init(struct comedi_device *dev) NUM_GPCT); /* General purpose counters */ for (j = 0; j < NUM_GPCT; ++j) { - s = &dev->subdevices[NI_GPCT_SUBDEV(j)]; + s = dev->subdevices + NI_GPCT_SUBDEV(j); s->type = COMEDI_SUBD_COUNTER; s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_LSAMPL | SDF_CMD_READ @@ -4593,7 +4659,7 @@ static int ni_E_init(struct comedi_device *dev) } /* Frequency output */ - s = &dev->subdevices[NI_FREQ_OUT_SUBDEV]; + s = dev->subdevices + NI_FREQ_OUT_SUBDEV; s->type = COMEDI_SUBD_COUNTER; s->subdev_flags = SDF_READABLE | SDF_WRITABLE; s->n_chan = 1; @@ -4603,8 +4669,7 @@ static int ni_E_init(struct comedi_device *dev) s->insn_config = &ni_freq_out_insn_config; /* ai configuration */ - s = &dev->subdevices[NI_AI_SUBDEV]; - ni_ai_reset(dev, s); + ni_ai_reset(dev, dev->subdevices + NI_AI_SUBDEV); if ((boardtype.reg_type & ni_reg_6xxx_mask) == 0) { /* BEAM is this needed for PCI-6143 ?? */ devpriv->clock_and_fout = @@ -4623,8 +4688,7 @@ static int ni_E_init(struct comedi_device *dev) Clock_and_FOUT_Register); /* analog output configuration */ - s = &dev->subdevices[NI_AO_SUBDEV]; - ni_ao_reset(dev, s); + ni_ao_reset(dev, dev->subdevices + NI_AO_SUBDEV); if (dev->irq) { devpriv->stc_writew(dev, diff --git a/trunk/drivers/staging/comedi/drivers/ni_mio_cs.c b/trunk/drivers/staging/comedi/drivers/ni_mio_cs.c index ca4f8e06e75b..b85765d266c2 100644 --- a/trunk/drivers/staging/comedi/drivers/ni_mio_cs.c +++ b/trunk/drivers/staging/comedi/drivers/ni_mio_cs.c @@ -382,7 +382,7 @@ static int mio_cs_attach(struct comedi_device *dev, struct comedi_devconfig *it) devpriv->stc_writel = &win_out2; devpriv->stc_readl = &win_in2; - ret = ni_E_init(dev); + ret = ni_E_init(dev, it); if (ret < 0) return ret; @@ -421,7 +421,7 @@ MODULE_AUTHOR("David A. Schleef "); MODULE_DESCRIPTION("Comedi driver for National Instruments DAQCard E series"); MODULE_LICENSE("GPL"); -static struct pcmcia_driver ni_mio_cs_driver = { +struct pcmcia_driver ni_mio_cs_driver = { .probe = &cs_attach, .remove = &cs_detach, .suspend = &mio_cs_suspend, diff --git a/trunk/drivers/staging/comedi/drivers/ni_pcidio.c b/trunk/drivers/staging/comedi/drivers/ni_pcidio.c index bc9313ec985c..0a55de968039 100644 --- a/trunk/drivers/staging/comedi/drivers/ni_pcidio.c +++ b/trunk/drivers/staging/comedi/drivers/ni_pcidio.c @@ -1,6 +1,8 @@ /* comedi/drivers/ni_pcidio.c - driver for National Instruments PCI-DIO-32HS + driver for National Instruments PCI-DIO-96/PCI-6508 + National Instruments PCI-DIO-32HS + National Instruments PCI-6503 COMEDI - Linux Control and Measurement Device Interface Copyright (C) 1999,2002 David A. Schleef @@ -22,14 +24,17 @@ */ /* Driver: ni_pcidio -Description: National Instruments PCI-DIO32HS, PCI-6533 +Description: National Instruments PCI-DIO32HS, PCI-DIO96, PCI-6533, PCI-6503 Author: ds Status: works -Devices: [National Instruments] PCI-DIO-32HS (ni_pcidio) - [National Instruments] PXI-6533, PCI-6533 (pxi-6533) - [National Instruments] PCI-6534 (pci-6534) +Devices: [National Instruments] PCI-DIO-32HS (ni_pcidio), PXI-6533, + PCI-DIO-96, PCI-DIO-96B, PXI-6508, PCI-6503, PCI-6503B, PCI-6503X, + PXI-6503, PCI-6533, PCI-6534 Updated: Mon, 09 Jan 2012 14:27:23 +0000 +The DIO-96 appears as four 8255 subdevices. See the 8255 +driver notes for details. + The DIO32HS board appears as one subdevice, with 32 channels. Each channel is individually I/O configurable. The channel order is 0=A0, 1=A1, 2=A2, ... 8=B0, 16=C0, 24=D0. The driver only @@ -51,28 +56,49 @@ it are contained in the comedi_nonfree_firmware tarball available from http://www.comedi.org */ +/* + This driver is for both the NI PCI-DIO-32HS and the PCI-DIO-96, + which have very different architectures. But, since the '96 is + so simple, it is included here. + + Manuals (available from ftp://ftp.natinst.com/support/manuals) + + 320938c.pdf PCI-DIO-96/PXI-6508/PCI-6503 User Manual + 321464b.pdf AT/PCI-DIO-32HS User Manual + 341329A.pdf PCI-6533 Register-Level Programmer Manual + 341330A.pdf DAQ-DIO Technical Reference Manual + + */ + #define USE_DMA /* #define DEBUG 1 */ /* #define DEBUG_FLAGS */ #include #include -#include #include "../comedidev.h" -#include "comedi_fc.h" #include "mite.h" +#include "8255.h" #undef DPRINTK #ifdef DEBUG -#define DPRINTK(format, args...) pr_debug(format, ## args) +#define DPRINTK(format, args...) printk(format, ## args) #else -#define DPRINTK(format, args...) do { } while (0) +#define DPRINTK(format, args...) #endif #define PCI_DIO_SIZE 4096 #define PCI_MITE_SIZE 4096 +/* defines for the PCI-DIO-96 */ + +#define NIDIO_8255_BASE(x) ((x)*4) +#define NIDIO_A 0 +#define NIDIO_B 4 +#define NIDIO_C 8 +#define NIDIO_D 12 + /* defines for the PCI-DIO-32HS */ #define Window_Address 4 /* W */ @@ -232,14 +258,6 @@ static inline unsigned secondary_DMAChannel_bits(unsigned channel) #define Protocol_Register_8 88 /* 32 bit */ #define StartDelay Protocol_Register_8 -/* Firmware files for PCI-6524 */ -#define FW_PCI_6534_MAIN "ni6534a.bin" -#define FW_PCI_6534_SCARAB_DI "niscrb01.bin" -#define FW_PCI_6534_SCARAB_DO "niscrb02.bin" -MODULE_FIRMWARE(FW_PCI_6534_MAIN); -MODULE_FIRMWARE(FW_PCI_6534_SCARAB_DI); -MODULE_FIRMWARE(FW_PCI_6534_SCARAB_DO); - enum pci_6534_firmware_registers { /* 16 bit */ Firmware_Control_Register = 0x100, Firmware_Status_Register = 0x104, @@ -279,23 +297,76 @@ static int ni_pcidio_cancel(struct comedi_device *dev, struct comedi_subdevice *s); struct nidio_board { + int dev_id; const char *name; + int n_8255; + unsigned int is_diodaq:1; unsigned int uses_firmware:1; }; static const struct nidio_board nidio_boards[] = { { - .dev_id = 0x1150, - .name = "pci-dio-32hs", - }, { - .dev_id = 0x1320, - .name = "pxi-6533", - }, { - .dev_id = 0x12b0, - .name = "pci-6534", - .uses_firmware = 1, - }, + .dev_id = 0x1150, + .name = "pci-dio-32hs", + .n_8255 = 0, + .is_diodaq = 1, + }, + { + .dev_id = 0x1320, + .name = "pxi-6533", + .n_8255 = 0, + .is_diodaq = 1, + }, + { + .dev_id = 0x12b0, + .name = "pci-6534", + .n_8255 = 0, + .is_diodaq = 1, + .uses_firmware = 1, + }, + { + .dev_id = 0x0160, + .name = "pci-dio-96", + .n_8255 = 4, + .is_diodaq = 0, + }, + { + .dev_id = 0x1630, + .name = "pci-dio-96b", + .n_8255 = 4, + .is_diodaq = 0, + }, + { + .dev_id = 0x13c0, + .name = "pxi-6508", + .n_8255 = 4, + .is_diodaq = 0, + }, + { + .dev_id = 0x0400, + .name = "pci-6503", + .n_8255 = 1, + .is_diodaq = 0, + }, + { + .dev_id = 0x1250, + .name = "pci-6503b", + .n_8255 = 1, + .is_diodaq = 0, + }, + { + .dev_id = 0x17d0, + .name = "pci-6503x", + .n_8255 = 1, + .is_diodaq = 0, + }, + { + .dev_id = 0x1800, + .name = "pxi-6503", + .n_8255 = 1, + .is_diodaq = 0, + }, }; #define n_nidio_boards ARRAY_SIZE(nidio_boards) @@ -371,8 +442,17 @@ static void ni_pcidio_release_di_mite_channel(struct comedi_device *dev) spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags); } -static void ni_pcidio_event(struct comedi_device *dev, - struct comedi_subdevice *s) +static int nidio96_8255_cb(int dir, int port, int data, unsigned long iobase) +{ + if (dir) { + writeb(data, (void *)(iobase + port)); + return 0; + } else { + return readb((void *)(iobase + port)); + } +} + +void ni_pcidio_event(struct comedi_device *dev, struct comedi_subdevice *s) { if (s-> async->events & (COMEDI_CB_EOA | COMEDI_CB_ERROR | @@ -400,7 +480,7 @@ static int ni_pcidio_poll(struct comedi_device *dev, struct comedi_subdevice *s) static irqreturn_t nidio_interrupt(int irq, void *d) { struct comedi_device *dev = d; - struct comedi_subdevice *s = &dev->subdevices[0]; + struct comedi_subdevice *s = dev->subdevices; struct comedi_async *async = s->async; struct mite_struct *mite = devpriv->mite; @@ -431,12 +511,18 @@ static irqreturn_t nidio_interrupt(int irq, void *d) ni_pcidio_print_flags(flags); ni_pcidio_print_status(status); + /* printk("buf[0]=%08x\n",*(unsigned int *)async->prealloc_buf); */ + /* printk("buf[4096]=%08x\n", + *(unsigned int *)(async->prealloc_buf+4096)); */ + spin_lock(&devpriv->mite_channel_lock); if (devpriv->di_mite_chan) m_status = mite_get_status(devpriv->di_mite_chan); #ifdef MITE_DEBUG mite_print_chsr(m_status); #endif + /* printk("mite_bytes_transferred: %d\n", + mite_bytes_transferred(mite,DI_DMA_CHAN)); */ /* mite_dump_regs(mite); */ if (m_status & CHSR_INT) { @@ -531,7 +617,7 @@ static irqreturn_t nidio_interrupt(int irq, void *d) } #if 0 else { - DPRINTK("ni_pcidio: unknown interrupt\n"); + printk("ni_pcidio: unknown interrupt\n"); async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA; writeb(0x00, devpriv->mite->daq_io_addr + @@ -562,47 +648,38 @@ static irqreturn_t nidio_interrupt(int irq, void *d) } #ifdef DEBUG_FLAGS -static const char *bit_set_string(unsigned int bits, unsigned int bit, - const char *const strings[]) -{ - return (bits & (1U << bit)) ? strings[bit] : ""; -} - static const char *const flags_strings[] = { - " TransferReady", " CountExpired", " 2", " 3", - " 4", " Waited", " PrimaryTC", " SecondaryTC", + "TransferReady", "CountExpired", "2", "3", + "4", "Waited", "PrimaryTC", "SecondaryTC", }; - static void ni_pcidio_print_flags(unsigned int flags) { - pr_debug("group_1_flags:%s%s%s%s%s%s%s%s\n", - bit_set_string(flags, 7, flags_strings), - bit_set_string(flags, 6, flags_strings), - bit_set_string(flags, 5, flags_strings), - bit_set_string(flags, 4, flags_strings), - bit_set_string(flags, 3, flags_strings), - bit_set_string(flags, 2, flags_strings), - bit_set_string(flags, 1, flags_strings), - bit_set_string(flags, 0, flags_strings)); + int i; + + printk(KERN_INFO "group_1_flags:"); + for (i = 7; i >= 0; i--) { + if (flags & (1 << i)) + printk(" %s", flags_strings[i]); + } + printk("\n"); } -static const char *const status_strings[] = { - " DataLeft1", " Reserved1", " Req1", " StopTrig1", - " DataLeft2", " Reserved2", " Req2", " StopTrig2", +static char *status_strings[] = { + "DataLeft1", "Reserved1", "Req1", "StopTrig1", + "DataLeft2", "Reserved2", "Req2", "StopTrig2", }; static void ni_pcidio_print_status(unsigned int flags) { - pr_debug("group_status:%s%s%s%s%s%s%s%s\n", - bit_set_string(flags, 7, status_strings), - bit_set_string(flags, 6, status_strings), - bit_set_string(flags, 5, status_strings), - bit_set_string(flags, 4, status_strings), - bit_set_string(flags, 3, status_strings), - bit_set_string(flags, 2, status_strings), - bit_set_string(flags, 1, status_strings), - bit_set_string(flags, 0, status_strings)); + int i; + + printk(KERN_INFO "group_status:"); + for (i = 7; i >= 0; i--) { + if (flags & (1 << i)) + printk(" %s", status_strings[i]); + } + printk("\n"); } #endif @@ -684,25 +761,45 @@ static int ni_pcidio_cmdtest(struct comedi_device *dev, int err = 0; int tmp; - /* Step 1 : check if triggers are trivially valid */ + /* step 1: make sure trigger sources are trivially valid */ - err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_INT); - err |= cfc_check_trigger_src(&cmd->scan_begin_src, - TRIG_TIMER | TRIG_EXT); - err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_NOW); - err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT); - err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE); + tmp = cmd->start_src; + cmd->start_src &= TRIG_NOW | TRIG_INT; + if (!cmd->start_src || tmp != cmd->start_src) + err++; + + tmp = cmd->scan_begin_src; + cmd->scan_begin_src &= TRIG_TIMER | TRIG_EXT; + if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) + err++; + + tmp = cmd->convert_src; + cmd->convert_src &= TRIG_NOW; + if (!cmd->convert_src || tmp != cmd->convert_src) + err++; + + tmp = cmd->scan_end_src; + cmd->scan_end_src &= TRIG_COUNT; + if (!cmd->scan_end_src || tmp != cmd->scan_end_src) + err++; + + tmp = cmd->stop_src; + cmd->stop_src &= TRIG_COUNT | TRIG_NONE; + if (!cmd->stop_src || tmp != cmd->stop_src) + err++; if (err) return 1; - /* Step 2a : make sure trigger sources are unique */ - - err |= cfc_check_trigger_is_unique(cmd->start_src); - err |= cfc_check_trigger_is_unique(cmd->scan_begin_src); - err |= cfc_check_trigger_is_unique(cmd->stop_src); + /* step 2: make sure trigger sources are unique and mutually + compatible */ - /* Step 2b : and mutually compatible */ + /* note that mutual compatibility is not an issue here */ + if (cmd->start_src != TRIG_NOW && cmd->start_src != TRIG_INT) + err++; + if (cmd->scan_begin_src != TRIG_TIMER && + cmd->scan_begin_src != TRIG_EXT) + err++; if (err) return 2; @@ -968,12 +1065,10 @@ static int ni_pcidio_change(struct comedi_device *dev, } static int pci_6534_load_fpga(struct comedi_device *dev, int fpga_index, - const u8 *data, size_t data_len) + u8 *data, int data_len) { static const int timeout = 1000; - int i; - size_t j; - + int i, j; writew(0x80 | fpga_index, devpriv->mite->daq_io_addr + Firmware_Control_Register); writew(0xc0 | fpga_index, @@ -984,9 +1079,8 @@ static int pci_6534_load_fpga(struct comedi_device *dev, int fpga_index, udelay(1); } if (i == timeout) { - dev_warn(dev->class_dev, - "ni_pcidio: failed to load fpga %i, waiting for status 0x2\n", - fpga_index); + printk(KERN_WARNING "ni_pcidio: failed to load fpga %i, " + "waiting for status 0x2\n", fpga_index); return -EIO; } writew(0x80 | fpga_index, @@ -997,9 +1091,8 @@ static int pci_6534_load_fpga(struct comedi_device *dev, int fpga_index, udelay(1); } if (i == timeout) { - dev_warn(dev->class_dev, - "ni_pcidio: failed to load fpga %i, waiting for status 0x3\n", - fpga_index); + printk(KERN_WARNING "ni_pcidio: failed to load fpga %i, " + "waiting for status 0x3\n", fpga_index); return -EIO; } for (j = 0; j + 1 < data_len;) { @@ -1014,9 +1107,8 @@ static int pci_6534_load_fpga(struct comedi_device *dev, int fpga_index, udelay(1); } if (i == timeout) { - dev_warn(dev->class_dev, - "ni_pcidio: failed to load word into fpga %i\n", - fpga_index); + printk("ni_pcidio: failed to load word into fpga %i\n", + fpga_index); return -EIO; } if (need_resched()) @@ -1055,72 +1147,85 @@ static void pci_6534_init_main_fpga(struct comedi_device *dev) writel(0, devpriv->mite->daq_io_addr + FPGA_SCBMS_Counter_Register); } -static int pci_6534_upload_firmware(struct comedi_device *dev) +static int pci_6534_upload_firmware(struct comedi_device *dev, int options[]) { int ret; - const struct firmware *fw; - static const char *const fw_file[3] = { - FW_PCI_6534_SCARAB_DI, /* loaded into scarab A for DI */ - FW_PCI_6534_SCARAB_DO, /* loaded into scarab B for DO */ - FW_PCI_6534_MAIN, /* loaded into main FPGA */ - }; - int n; + void *main_fpga_data, *scarab_a_data, *scarab_b_data; + int main_fpga_data_len, scarab_a_data_len, scarab_b_data_len; + if (options[COMEDI_DEVCONF_AUX_DATA_LENGTH] == 0) + return 0; ret = pci_6534_reset_fpgas(dev); if (ret < 0) return ret; - /* load main FPGA first, then the two scarabs */ - for (n = 2; n >= 0; n--) { - ret = request_firmware(&fw, fw_file[n], - &devpriv->mite->pcidev->dev); - if (ret == 0) { - ret = pci_6534_load_fpga(dev, n, fw->data, fw->size); - if (ret == 0 && n == 2) - pci_6534_init_main_fpga(dev); - release_firmware(fw); - } - if (ret < 0) - break; - } - return ret; + main_fpga_data = comedi_aux_data(options, 0); + main_fpga_data_len = options[COMEDI_DEVCONF_AUX_DATA0_LENGTH]; + ret = pci_6534_load_fpga(dev, 2, main_fpga_data, main_fpga_data_len); + if (ret < 0) + return ret; + pci_6534_init_main_fpga(dev); + scarab_a_data = comedi_aux_data(options, 1); + scarab_a_data_len = options[COMEDI_DEVCONF_AUX_DATA1_LENGTH]; + ret = pci_6534_load_fpga(dev, 0, scarab_a_data, scarab_a_data_len); + if (ret < 0) + return ret; + scarab_b_data = comedi_aux_data(options, 2); + scarab_b_data_len = options[COMEDI_DEVCONF_AUX_DATA2_LENGTH]; + ret = pci_6534_load_fpga(dev, 1, scarab_b_data, scarab_b_data_len); + if (ret < 0) + return ret; + return 0; } -static const struct nidio_board * -nidio_find_boardinfo(struct pci_dev *pcidev) +static int nidio_find_device(struct comedi_device *dev, int bus, int slot) { - unsigned int dev_id = pcidev->device; - unsigned int n; + struct mite_struct *mite; + int i; + + for (mite = mite_devices; mite; mite = mite->next) { + if (mite->used) + continue; + if (bus || slot) { + if (bus != mite->pcidev->bus->number || + slot != PCI_SLOT(mite->pcidev->devfn)) + continue; + } + for (i = 0; i < n_nidio_boards; i++) { + if (mite_device_id(mite) == nidio_boards[i].dev_id) { + dev->board_ptr = nidio_boards + i; + devpriv->mite = mite; - for (n = 0; n < ARRAY_SIZE(nidio_boards); n++) { - const struct nidio_board *board = &nidio_boards[n]; - if (board->dev_id == dev_id) - return board; + return 0; + } + } } - return NULL; + printk(KERN_WARNING "no device found\n"); + mite_list_devices(); + return -EIO; } -static int __devinit nidio_attach_pci(struct comedi_device *dev, - struct pci_dev *pcidev) +static int nidio_attach(struct comedi_device *dev, struct comedi_devconfig *it) { struct comedi_subdevice *s; + int i; int ret; + int n_subdevices; unsigned int irq; + printk(KERN_INFO "comedi%d: nidio:", dev->minor); + ret = alloc_private(dev, sizeof(struct nidio96_private)); if (ret < 0) return ret; spin_lock_init(&devpriv->mite_channel_lock); - dev->board_ptr = nidio_find_boardinfo(pcidev); - if (!dev->board_ptr) - return -ENODEV; - devpriv->mite = mite_alloc(pcidev); - if (!devpriv->mite) - return -ENOMEM; + ret = nidio_find_device(dev, it->options[0], it->options[1]); + if (ret < 0) + return ret; ret = mite_setup(devpriv->mite); if (ret < 0) { - dev_warn(dev->class_dev, "error setting up mite\n"); + printk(KERN_WARNING "error setting up mite\n"); return ret; } comedi_set_hw_dev(dev, &devpriv->mite->pcidev->dev); @@ -1130,60 +1235,84 @@ static int __devinit nidio_attach_pci(struct comedi_device *dev, dev->board_name = this_board->name; irq = mite_irq(devpriv->mite); + printk(KERN_INFO " %s", dev->board_name); if (this_board->uses_firmware) { - ret = pci_6534_upload_firmware(dev); + ret = pci_6534_upload_firmware(dev, it->options); if (ret < 0) return ret; } + if (!this_board->is_diodaq) + n_subdevices = this_board->n_8255; + else + n_subdevices = 1; - ret = comedi_alloc_subdevices(dev, 1); + ret = comedi_alloc_subdevices(dev, n_subdevices); if (ret) return ret; - dev_info(dev->class_dev, "%s rev=%d\n", dev->board_name, - readb(devpriv->mite->daq_io_addr + Chip_Version)); - - s = &dev->subdevices[0]; - - dev->read_subdev = s; - s->type = COMEDI_SUBD_DIO; - s->subdev_flags = - SDF_READABLE | SDF_WRITABLE | SDF_LSAMPL | SDF_PACKED | - SDF_CMD_READ; - s->n_chan = 32; - s->range_table = &range_digital; - s->maxdata = 1; - s->insn_config = &ni_pcidio_insn_config; - s->insn_bits = &ni_pcidio_insn_bits; - s->do_cmd = &ni_pcidio_cmd; - s->do_cmdtest = &ni_pcidio_cmdtest; - s->cancel = &ni_pcidio_cancel; - s->len_chanlist = 32; /* XXX */ - s->buf_change = &ni_pcidio_change; - s->async_dma_dir = DMA_BIDIRECTIONAL; - s->poll = &ni_pcidio_poll; - - writel(0, devpriv->mite->daq_io_addr + Port_IO(0)); - writel(0, devpriv->mite->daq_io_addr + Port_Pin_Directions(0)); - writel(0, devpriv->mite->daq_io_addr + Port_Pin_Mask(0)); - - /* disable interrupts on board */ - writeb(0x00, - devpriv->mite->daq_io_addr + - Master_DMA_And_Interrupt_Control); + if (!this_board->is_diodaq) { + for (i = 0; i < this_board->n_8255; i++) { + subdev_8255_init(dev, dev->subdevices + i, + nidio96_8255_cb, + (unsigned long)(devpriv->mite-> + daq_io_addr + + NIDIO_8255_BASE(i))); + } + } else { - ret = request_irq(irq, nidio_interrupt, IRQF_SHARED, - "ni_pcidio", dev); - if (ret < 0) - dev_warn(dev->class_dev, "irq not available\n"); + printk(KERN_INFO " rev=%d", + readb(devpriv->mite->daq_io_addr + Chip_Version)); + + s = dev->subdevices + 0; + + dev->read_subdev = s; + s->type = COMEDI_SUBD_DIO; + s->subdev_flags = + SDF_READABLE | SDF_WRITABLE | SDF_LSAMPL | SDF_PACKED | + SDF_CMD_READ; + s->n_chan = 32; + s->range_table = &range_digital; + s->maxdata = 1; + s->insn_config = &ni_pcidio_insn_config; + s->insn_bits = &ni_pcidio_insn_bits; + s->do_cmd = &ni_pcidio_cmd; + s->do_cmdtest = &ni_pcidio_cmdtest; + s->cancel = &ni_pcidio_cancel; + s->len_chanlist = 32; /* XXX */ + s->buf_change = &ni_pcidio_change; + s->async_dma_dir = DMA_BIDIRECTIONAL; + s->poll = &ni_pcidio_poll; + + writel(0, devpriv->mite->daq_io_addr + Port_IO(0)); + writel(0, devpriv->mite->daq_io_addr + Port_Pin_Directions(0)); + writel(0, devpriv->mite->daq_io_addr + Port_Pin_Mask(0)); + + /* disable interrupts on board */ + writeb(0x00, + devpriv->mite->daq_io_addr + + Master_DMA_And_Interrupt_Control); + + ret = request_irq(irq, nidio_interrupt, IRQF_SHARED, + "ni_pcidio", dev); + if (ret < 0) + printk(KERN_WARNING " irq not available"); + + dev->irq = irq; + } - dev->irq = irq; + printk("\n"); return 0; } static void nidio_detach(struct comedi_device *dev) { + int i; + + if (this_board && !this_board->is_diodaq) { + for (i = 0; i < this_board->n_8255; i++) + subdev_8255_cleanup(dev, dev->subdevices + i); + } if (dev->irq) free_irq(dev->irq, dev); if (devpriv) { @@ -1191,17 +1320,15 @@ static void nidio_detach(struct comedi_device *dev) mite_free_ring(devpriv->di_mite_ring); devpriv->di_mite_ring = NULL; } - if (devpriv->mite) { + if (devpriv->mite) mite_unsetup(devpriv->mite); - mite_free(devpriv->mite); - } } } static struct comedi_driver ni_pcidio_driver = { .driver_name = "ni_pcidio", .module = THIS_MODULE, - .attach_pci = nidio_attach_pci, + .attach = nidio_attach, .detach = nidio_detach, }; @@ -1220,6 +1347,13 @@ static DEFINE_PCI_DEVICE_TABLE(ni_pcidio_pci_table) = { { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x1150) }, { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x1320) }, { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x12b0) }, + { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x0160) }, + { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x1630) }, + { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x13c0) }, + { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x0400) }, + { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x1250) }, + { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x17d0) }, + { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x1800) }, { 0 } }; MODULE_DEVICE_TABLE(pci, ni_pcidio_pci_table); diff --git a/trunk/drivers/staging/comedi/drivers/ni_pcimio.c b/trunk/drivers/staging/comedi/drivers/ni_pcimio.c index f284a90720ec..89f4d43c6d08 100644 --- a/trunk/drivers/staging/comedi/drivers/ni_pcimio.c +++ b/trunk/drivers/staging/comedi/drivers/ni_pcimio.c @@ -1188,6 +1188,8 @@ static const struct ni_board_struct ni_boards[] = { }, }; +#define n_pcimio_boards ARRAY_SIZE(ni_boards) + struct ni_private { NI_PRIVATE_COMMON}; #define devpriv ((struct ni_private *)dev->private) @@ -1500,6 +1502,7 @@ static uint32_t m_series_stc_readl(struct comedi_device *dev, int reg) #include "ni_mio_common.c" +static int pcimio_find_device(struct comedi_device *dev, int bus, int slot); static int pcimio_ai_change(struct comedi_device *dev, struct comedi_subdevice *s, unsigned long new_size); static int pcimio_ao_change(struct comedi_device *dev, @@ -1581,45 +1584,24 @@ static void pcimio_detach(struct comedi_device *dev) mite_free_ring(devpriv->cdo_mite_ring); mite_free_ring(devpriv->gpct_mite_ring[0]); mite_free_ring(devpriv->gpct_mite_ring[1]); - if (devpriv->mite) { + if (devpriv->mite) mite_unsetup(devpriv->mite); - mite_free(devpriv->mite); - } } } -static const struct ni_board_struct * -pcimio_find_boardinfo(struct pci_dev *pcidev) -{ - unsigned int device_id = pcidev->device; - unsigned int n; - - for (n = 0; n < ARRAY_SIZE(ni_boards); n++) { - const struct ni_board_struct *board = &ni_boards[n]; - if (board->device_id == device_id) - return board; - } - return NULL; -} - -static int __devinit pcimio_attach_pci(struct comedi_device *dev, - struct pci_dev *pcidev) +static int pcimio_attach(struct comedi_device *dev, struct comedi_devconfig *it) { int ret; - dev_info(dev->class_dev, "ni_pcimio: attach %s\n", pci_name(pcidev)); + dev_info(dev->class_dev, "ni_pcimio: attach\n"); ret = ni_alloc_private(dev); if (ret < 0) return ret; - dev->board_ptr = pcimio_find_boardinfo(pcidev); - if (!dev->board_ptr) - return -ENODEV; - - devpriv->mite = mite_alloc(pcidev); - if (!devpriv->mite) - return -ENOMEM; + ret = pcimio_find_device(dev, it->options[0], it->options[1]); + if (ret < 0) + return ret; dev_dbg(dev->class_dev, "%s\n", boardtype.name); dev->board_name = boardtype.name; @@ -1677,7 +1659,7 @@ static int __devinit pcimio_attach_pci(struct comedi_device *dev, } } - ret = ni_E_init(dev); + ret = ni_E_init(dev, it); if (ret < 0) return ret; @@ -1690,6 +1672,34 @@ static int __devinit pcimio_attach_pci(struct comedi_device *dev, return ret; } +static int pcimio_find_device(struct comedi_device *dev, int bus, int slot) +{ + struct mite_struct *mite; + int i; + + for (mite = mite_devices; mite; mite = mite->next) { + if (mite->used) + continue; + if (bus || slot) { + if (bus != mite->pcidev->bus->number || + slot != PCI_SLOT(mite->pcidev->devfn)) + continue; + } + + for (i = 0; i < n_pcimio_boards; i++) { + if (mite_device_id(mite) == ni_boards[i].device_id) { + dev->board_ptr = ni_boards + i; + devpriv->mite = mite; + + return 0; + } + } + } + pr_warn("no device found\n"); + mite_list_devices(); + return -EIO; +} + static int pcimio_ai_change(struct comedi_device *dev, struct comedi_subdevice *s, unsigned long new_size) { @@ -1755,7 +1765,7 @@ static int pcimio_dio_change(struct comedi_device *dev, static struct comedi_driver ni_pcimio_driver = { .driver_name = "ni_pcimio", .module = THIS_MODULE, - .attach_pci = pcimio_attach_pci, + .attach = pcimio_attach, .detach = pcimio_detach, }; @@ -1834,7 +1844,7 @@ static struct pci_driver ni_pcimio_pci_driver = { .probe = ni_pcimio_pci_probe, .remove = __devexit_p(ni_pcimio_pci_remove) }; -module_comedi_pci_driver(ni_pcimio_driver, ni_pcimio_pci_driver); +module_comedi_pci_driver(ni_pcimio_driver, ni_pcimio_pci_driver) MODULE_AUTHOR("Comedi http://www.comedi.org"); MODULE_DESCRIPTION("Comedi low-level driver"); diff --git a/trunk/drivers/staging/comedi/drivers/ni_tiocmd.c b/trunk/drivers/staging/comedi/drivers/ni_tiocmd.c index 8ee93d359bed..a9611587460a 100644 --- a/trunk/drivers/staging/comedi/drivers/ni_tiocmd.c +++ b/trunk/drivers/staging/comedi/drivers/ni_tiocmd.c @@ -48,7 +48,6 @@ DAQ 6601/6602 User Manual (NI 322137B-01) Support use of both banks X and Y */ -#include "comedi_fc.h" #include "ni_tio_internal.h" #include "mite.h" @@ -238,35 +237,61 @@ EXPORT_SYMBOL_GPL(ni_tio_cmd); int ni_tio_cmdtest(struct ni_gpct *counter, struct comedi_cmd *cmd) { int err = 0; - unsigned int sources; + int tmp; + int sources; - /* Step 1 : check if triggers are trivially valid */ + /* step 1: make sure trigger sources are trivially valid */ + tmp = cmd->start_src; sources = TRIG_NOW | TRIG_INT | TRIG_OTHER; if (ni_tio_counting_mode_registers_present(counter->counter_dev)) sources |= TRIG_EXT; - err |= cfc_check_trigger_src(&cmd->start_src, sources); + cmd->start_src &= sources; + if (!cmd->start_src || tmp != cmd->start_src) + err++; - err |= cfc_check_trigger_src(&cmd->scan_begin_src, - TRIG_FOLLOW | TRIG_EXT | TRIG_OTHER); - err |= cfc_check_trigger_src(&cmd->convert_src, - TRIG_NOW | TRIG_EXT | TRIG_OTHER); - err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT); - err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_NONE); + tmp = cmd->scan_begin_src; + cmd->scan_begin_src &= TRIG_FOLLOW | TRIG_EXT | TRIG_OTHER; + if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) + err++; - if (err) - return 1; + tmp = cmd->convert_src; + sources = TRIG_NOW | TRIG_EXT | TRIG_OTHER; + cmd->convert_src &= sources; + if (!cmd->convert_src || tmp != cmd->convert_src) + err++; - /* Step 2a : make sure trigger sources are unique */ + tmp = cmd->scan_end_src; + cmd->scan_end_src &= TRIG_COUNT; + if (!cmd->scan_end_src || tmp != cmd->scan_end_src) + err++; - err |= cfc_check_trigger_is_unique(cmd->start_src); - err |= cfc_check_trigger_is_unique(cmd->scan_begin_src); - err |= cfc_check_trigger_is_unique(cmd->convert_src); + tmp = cmd->stop_src; + cmd->stop_src &= TRIG_NONE; + if (!cmd->stop_src || tmp != cmd->stop_src) + err++; - /* Step 2b : and mutually compatible */ + if (err) + return 1; + + /* step 2: make sure trigger sources are unique... */ + if (cmd->start_src != TRIG_NOW && + cmd->start_src != TRIG_INT && + cmd->start_src != TRIG_EXT && cmd->start_src != TRIG_OTHER) + err++; + if (cmd->scan_begin_src != TRIG_FOLLOW && + cmd->scan_begin_src != TRIG_EXT && + cmd->scan_begin_src != TRIG_OTHER) + err++; + if (cmd->convert_src != TRIG_OTHER && + cmd->convert_src != TRIG_EXT && cmd->convert_src != TRIG_NOW) + err++; + if (cmd->stop_src != TRIG_NONE) + err++; + /* ... and mutually compatible */ if (cmd->convert_src != TRIG_NOW && cmd->scan_begin_src != TRIG_FOLLOW) - err |= -EINVAL; + err++; if (err) return 2; diff --git a/trunk/drivers/staging/comedi/drivers/pcl711.c b/trunk/drivers/staging/comedi/drivers/pcl711.c index 89305a14eb5c..bb72d0bc2975 100644 --- a/trunk/drivers/staging/comedi/drivers/pcl711.c +++ b/trunk/drivers/staging/comedi/drivers/pcl711.c @@ -64,7 +64,6 @@ supported. #include #include -#include "comedi_fc.h" #include "8253.h" #define PCL711_SIZE 16 @@ -169,7 +168,7 @@ static irqreturn_t pcl711_interrupt(int irq, void *d) int data; struct comedi_device *dev = d; const struct pcl711_board *board = comedi_board(dev); - struct comedi_subdevice *s = &dev->subdevices[0]; + struct comedi_subdevice *s = dev->subdevices + 0; if (!dev->attached) { comedi_error(dev, "spurious interrupt"); @@ -267,24 +266,42 @@ static int pcl711_ai_cmdtest(struct comedi_device *dev, int tmp; int err = 0; - /* Step 1 : check if triggers are trivially valid */ + /* step 1 */ + tmp = cmd->start_src; + cmd->start_src &= TRIG_NOW; + if (!cmd->start_src || tmp != cmd->start_src) + err++; + + tmp = cmd->scan_begin_src; + cmd->scan_begin_src &= TRIG_TIMER | TRIG_EXT; + if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) + err++; - err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW); - err |= cfc_check_trigger_src(&cmd->scan_begin_src, - TRIG_TIMER | TRIG_EXT); - err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_NOW); - err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT); - err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE); + tmp = cmd->convert_src; + cmd->convert_src &= TRIG_NOW; + if (!cmd->convert_src || tmp != cmd->convert_src) + err++; + + tmp = cmd->scan_end_src; + cmd->scan_end_src &= TRIG_COUNT; + if (!cmd->scan_end_src || tmp != cmd->scan_end_src) + err++; + + tmp = cmd->stop_src; + cmd->stop_src &= TRIG_COUNT | TRIG_NONE; + if (!cmd->stop_src || tmp != cmd->stop_src) + err++; if (err) return 1; - /* Step 2a : make sure trigger sources are unique */ - - err |= cfc_check_trigger_is_unique(cmd->scan_begin_src); - err |= cfc_check_trigger_is_unique(cmd->stop_src); + /* step 2 */ - /* Step 2b : and mutually compatible */ + if (cmd->scan_begin_src != TRIG_TIMER && + cmd->scan_begin_src != TRIG_EXT) + err++; + if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE) + err++; if (err) return 2; @@ -503,7 +520,7 @@ static int pcl711_attach(struct comedi_device *dev, struct comedi_devconfig *it) if (ret < 0) return ret; - s = &dev->subdevices[0]; + s = dev->subdevices + 0; /* AI subdevice */ s->type = COMEDI_SUBD_AI; s->subdev_flags = SDF_READABLE | SDF_GROUND; @@ -519,7 +536,7 @@ static int pcl711_attach(struct comedi_device *dev, struct comedi_devconfig *it) s->do_cmd = pcl711_ai_cmd; } - s = &dev->subdevices[1]; + s++; /* AO subdevice */ s->type = COMEDI_SUBD_AO; s->subdev_flags = SDF_WRITABLE; @@ -530,7 +547,7 @@ static int pcl711_attach(struct comedi_device *dev, struct comedi_devconfig *it) s->insn_write = pcl711_ao_insn; s->insn_read = pcl711_ao_insn_read; - s = &dev->subdevices[2]; + s++; /* 16-bit digital input */ s->type = COMEDI_SUBD_DI; s->subdev_flags = SDF_READABLE; @@ -540,7 +557,7 @@ static int pcl711_attach(struct comedi_device *dev, struct comedi_devconfig *it) s->range_table = &range_digital; s->insn_bits = pcl711_di_insn_bits; - s = &dev->subdevices[3]; + s++; /* 16-bit digital out */ s->type = COMEDI_SUBD_DO; s->subdev_flags = SDF_WRITABLE; diff --git a/trunk/drivers/staging/comedi/drivers/pcl724.c b/trunk/drivers/staging/comedi/drivers/pcl724.c index 7b3c4293c01b..c8fe23ca899d 100644 --- a/trunk/drivers/staging/comedi/drivers/pcl724.c +++ b/trunk/drivers/staging/comedi/drivers/pcl724.c @@ -99,7 +99,6 @@ static int subdev_8255mapped_cb(int dir, int port, int data, static int pcl724_attach(struct comedi_device *dev, struct comedi_devconfig *it) { const struct pcl724_board *board = comedi_board(dev); - struct comedi_subdevice *s; unsigned long iobase; unsigned int iorange; int ret, i, n_subdevices; @@ -162,13 +161,14 @@ static int pcl724_attach(struct comedi_device *dev, struct comedi_devconfig *it) return ret; for (i = 0; i < dev->n_subdevices; i++) { - s = &dev->subdevices[i]; if (board->is_pet48) { - subdev_8255_init(dev, s, subdev_8255mapped_cb, + subdev_8255_init(dev, dev->subdevices + i, + subdev_8255mapped_cb, (unsigned long)(dev->iobase + i * 0x1000)); } else - subdev_8255_init(dev, s, subdev_8255_cb, + subdev_8255_init(dev, dev->subdevices + i, + subdev_8255_cb, (unsigned long)(dev->iobase + SIZE_8255 * i)); } @@ -179,13 +179,10 @@ static int pcl724_attach(struct comedi_device *dev, struct comedi_devconfig *it) static void pcl724_detach(struct comedi_device *dev) { const struct pcl724_board *board = comedi_board(dev); - struct comedi_subdevice *s; int i; - for (i = 0; i < dev->n_subdevices; i++) { - s = &dev->subdevices[i]; - subdev_8255_cleanup(dev, s); - } + for (i = 0; i < dev->n_subdevices; i++) + subdev_8255_cleanup(dev, dev->subdevices + i); #ifdef PCL724_IRQ if (dev->irq) free_irq(dev->irq, dev); diff --git a/trunk/drivers/staging/comedi/drivers/pcl725.c b/trunk/drivers/staging/comedi/drivers/pcl725.c index 21fbc1ae1e73..d5b60cf7c93f 100644 --- a/trunk/drivers/staging/comedi/drivers/pcl725.c +++ b/trunk/drivers/staging/comedi/drivers/pcl725.c @@ -62,7 +62,7 @@ static int pcl725_attach(struct comedi_device *dev, struct comedi_devconfig *it) if (ret) return ret; - s = &dev->subdevices[0]; + s = dev->subdevices + 0; /* do */ s->type = COMEDI_SUBD_DO; s->subdev_flags = SDF_WRITABLE; @@ -71,7 +71,7 @@ static int pcl725_attach(struct comedi_device *dev, struct comedi_devconfig *it) s->insn_bits = pcl725_do_insn; s->range_table = &range_digital; - s = &dev->subdevices[1]; + s = dev->subdevices + 1; /* di */ s->type = COMEDI_SUBD_DI; s->subdev_flags = SDF_READABLE; diff --git a/trunk/drivers/staging/comedi/drivers/pcl726.c b/trunk/drivers/staging/comedi/drivers/pcl726.c index 07e72de982ac..2b10f1d83085 100644 --- a/trunk/drivers/staging/comedi/drivers/pcl726.c +++ b/trunk/drivers/staging/comedi/drivers/pcl726.c @@ -290,7 +290,7 @@ static int pcl726_attach(struct comedi_device *dev, struct comedi_devconfig *it) if (ret) return ret; - s = &dev->subdevices[0]; + s = dev->subdevices + 0; /* ao */ s->type = COMEDI_SUBD_AO; s->subdev_flags = SDF_WRITABLE | SDF_GROUND; @@ -316,7 +316,7 @@ static int pcl726_attach(struct comedi_device *dev, struct comedi_devconfig *it) devpriv->bipolar[i] = 1; /* bipolar range */ } - s = &dev->subdevices[1]; + s = dev->subdevices + 1; /* di */ if (!board->have_dio) { s->type = COMEDI_SUBD_UNUSED; @@ -330,7 +330,7 @@ static int pcl726_attach(struct comedi_device *dev, struct comedi_devconfig *it) s->range_table = &range_digital; } - s = &dev->subdevices[2]; + s = dev->subdevices + 2; /* do */ if (!board->have_dio) { s->type = COMEDI_SUBD_UNUSED; diff --git a/trunk/drivers/staging/comedi/drivers/pcl730.c b/trunk/drivers/staging/comedi/drivers/pcl730.c index e3de49937452..4675ec57082e 100644 --- a/trunk/drivers/staging/comedi/drivers/pcl730.c +++ b/trunk/drivers/staging/comedi/drivers/pcl730.c @@ -84,7 +84,7 @@ static int pcl730_attach(struct comedi_device *dev, struct comedi_devconfig *it) if (ret) return ret; - s = &dev->subdevices[0]; + s = dev->subdevices + 0; /* Isolated do */ s->type = COMEDI_SUBD_DO; s->subdev_flags = SDF_WRITABLE; @@ -94,7 +94,7 @@ static int pcl730_attach(struct comedi_device *dev, struct comedi_devconfig *it) s->range_table = &range_digital; s->private = (void *)PCL730_IDIO_LO; - s = &dev->subdevices[1]; + s = dev->subdevices + 1; /* Isolated di */ s->type = COMEDI_SUBD_DI; s->subdev_flags = SDF_READABLE; @@ -104,7 +104,7 @@ static int pcl730_attach(struct comedi_device *dev, struct comedi_devconfig *it) s->range_table = &range_digital; s->private = (void *)PCL730_IDIO_LO; - s = &dev->subdevices[2]; + s = dev->subdevices + 2; /* TTL do */ s->type = COMEDI_SUBD_DO; s->subdev_flags = SDF_WRITABLE; @@ -114,7 +114,7 @@ static int pcl730_attach(struct comedi_device *dev, struct comedi_devconfig *it) s->range_table = &range_digital; s->private = (void *)PCL730_DIO_LO; - s = &dev->subdevices[3]; + s = dev->subdevices + 3; /* TTL di */ s->type = COMEDI_SUBD_DI; s->subdev_flags = SDF_READABLE; diff --git a/trunk/drivers/staging/comedi/drivers/pcl812.c b/trunk/drivers/staging/comedi/drivers/pcl812.c index 3cf55ff93083..578fd8920be1 100644 --- a/trunk/drivers/staging/comedi/drivers/pcl812.c +++ b/trunk/drivers/staging/comedi/drivers/pcl812.c @@ -117,7 +117,6 @@ #include #include -#include "comedi_fc.h" #include "8253.h" /* hardware types of the cards */ @@ -534,31 +533,49 @@ static int pcl812_ai_cmdtest(struct comedi_device *dev, { const struct pcl812_board *board = comedi_board(dev); int err = 0; - unsigned int flags; int tmp, divisor1, divisor2; - /* Step 1 : check if triggers are trivially valid */ + /* step 1: make sure trigger sources are trivially valid */ - err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW); - err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_FOLLOW); + tmp = cmd->start_src; + cmd->start_src &= TRIG_NOW; + if (!cmd->start_src || tmp != cmd->start_src) + err++; + + tmp = cmd->scan_begin_src; + cmd->scan_begin_src &= TRIG_FOLLOW; + if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) + err++; + tmp = cmd->convert_src; if (devpriv->use_ext_trg) - flags = TRIG_EXT; + cmd->convert_src &= TRIG_EXT; else - flags = TRIG_TIMER; - err |= cfc_check_trigger_src(&cmd->convert_src, flags); + cmd->convert_src &= TRIG_TIMER; + + if (!cmd->convert_src || tmp != cmd->convert_src) + err++; - err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT); - err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE); + tmp = cmd->scan_end_src; + cmd->scan_end_src &= TRIG_COUNT; + if (!cmd->scan_end_src || tmp != cmd->scan_end_src) + err++; + + tmp = cmd->stop_src; + cmd->stop_src &= TRIG_COUNT | TRIG_NONE; + if (!cmd->stop_src || tmp != cmd->stop_src) + err++; if (err) return 1; - /* Step 2a : make sure trigger sources are unique */ + /* + * step 2: make sure trigger sources are + * unique and mutually compatible + */ - err |= cfc_check_trigger_is_unique(cmd->stop_src); - - /* Step 2b : and mutually compatible */ + if (cmd->stop_src != TRIG_NONE && cmd->stop_src != TRIG_COUNT) + err++; if (err) return 2; @@ -789,7 +806,7 @@ static irqreturn_t interrupt_pcl812_ai_int(int irq, void *d) char err = 1; unsigned int mask, timeout; struct comedi_device *dev = d; - struct comedi_subdevice *s = &dev->subdevices[0]; + struct comedi_subdevice *s = dev->subdevices + 0; unsigned int next_chan; s->async->events = 0; @@ -892,7 +909,7 @@ static void transfer_from_dma_buf(struct comedi_device *dev, static irqreturn_t interrupt_pcl812_ai_dma(int irq, void *d) { struct comedi_device *dev = d; - struct comedi_subdevice *s = &dev->subdevices[0]; + struct comedi_subdevice *s = dev->subdevices + 0; unsigned long dma_flags; int len, bufptr; short *ptr; @@ -1250,7 +1267,7 @@ static int pcl812_attach(struct comedi_device *dev, struct comedi_devconfig *it) /* analog input */ if (board->n_aichan > 0) { - s = &dev->subdevices[subdev]; + s = dev->subdevices + subdev; s->type = COMEDI_SUBD_AI; s->subdev_flags = SDF_READABLE; switch (board->board_type) { @@ -1392,7 +1409,7 @@ static int pcl812_attach(struct comedi_device *dev, struct comedi_devconfig *it) /* analog output */ if (board->n_aochan > 0) { - s = &dev->subdevices[subdev]; + s = dev->subdevices + subdev; s->type = COMEDI_SUBD_AO; s->subdev_flags = SDF_WRITABLE | SDF_GROUND; s->n_chan = board->n_aochan; @@ -1421,7 +1438,7 @@ static int pcl812_attach(struct comedi_device *dev, struct comedi_devconfig *it) /* digital input */ if (board->n_dichan > 0) { - s = &dev->subdevices[subdev]; + s = dev->subdevices + subdev; s->type = COMEDI_SUBD_DI; s->subdev_flags = SDF_READABLE; s->n_chan = board->n_dichan; @@ -1434,7 +1451,7 @@ static int pcl812_attach(struct comedi_device *dev, struct comedi_devconfig *it) /* digital output */ if (board->n_dochan > 0) { - s = &dev->subdevices[subdev]; + s = dev->subdevices + subdev; s->type = COMEDI_SUBD_DO; s->subdev_flags = SDF_WRITABLE; s->n_chan = board->n_dochan; diff --git a/trunk/drivers/staging/comedi/drivers/pcl816.c b/trunk/drivers/staging/comedi/drivers/pcl816.c index 0822de058e4d..ba6911f063cb 100644 --- a/trunk/drivers/staging/comedi/drivers/pcl816.c +++ b/trunk/drivers/staging/comedi/drivers/pcl816.c @@ -41,7 +41,6 @@ Configuration Options: #include #include -#include "comedi_fc.h" #include "8253.h" #define DEBUG(x) x @@ -259,7 +258,7 @@ static int pcl816_ai_insn_read(struct comedi_device *dev, static irqreturn_t interrupt_pcl816_ai_mode13_int(int irq, void *d) { struct comedi_device *dev = d; - struct comedi_subdevice *s = &dev->subdevices[0]; + struct comedi_subdevice *s = dev->subdevices + 0; int low, hi; int timeout = 50; /* wait max 50us */ @@ -350,7 +349,7 @@ static void transfer_from_dma_buf(struct comedi_device *dev, static irqreturn_t interrupt_pcl816_ai_mode13_dma(int irq, void *d) { struct comedi_device *dev = d; - struct comedi_subdevice *s = &dev->subdevices[0]; + struct comedi_subdevice *s = dev->subdevices + 0; int len, bufptr, this_dma_buf; unsigned long dma_flags; short *ptr; @@ -459,23 +458,48 @@ static int pcl816_ai_cmdtest(struct comedi_device *dev, pcl816_cmdtest_out(-1, cmd); ); - /* Step 1 : check if triggers are trivially valid */ + /* step 1: make sure trigger sources are trivially valid */ + tmp = cmd->start_src; + cmd->start_src &= TRIG_NOW; + if (!cmd->start_src || tmp != cmd->start_src) + err++; + + tmp = cmd->scan_begin_src; + cmd->scan_begin_src &= TRIG_FOLLOW; + if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) + err++; + + tmp = cmd->convert_src; + cmd->convert_src &= TRIG_EXT | TRIG_TIMER; + if (!cmd->convert_src || tmp != cmd->convert_src) + err++; + + tmp = cmd->scan_end_src; + cmd->scan_end_src &= TRIG_COUNT; + if (!cmd->scan_end_src || tmp != cmd->scan_end_src) + err++; - err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW); - err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_FOLLOW); - err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_EXT | TRIG_TIMER); - err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT); - err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE); + tmp = cmd->stop_src; + cmd->stop_src &= TRIG_COUNT | TRIG_NONE; + if (!cmd->stop_src || tmp != cmd->stop_src) + err++; if (err) return 1; - /* Step 2a : make sure trigger sources are unique */ - err |= cfc_check_trigger_is_unique(cmd->convert_src); - err |= cfc_check_trigger_is_unique(cmd->stop_src); + /* + * step 2: make sure trigger sources + * are unique and mutually compatible + */ + + if (cmd->convert_src != TRIG_EXT && cmd->convert_src != TRIG_TIMER) { + cmd->convert_src = TRIG_TIMER; + err++; + } - /* Step 2b : and mutually compatible */ + if (cmd->stop_src != TRIG_NONE && cmd->stop_src != TRIG_COUNT) + err++; if (err) return 2; @@ -1159,7 +1183,7 @@ static int pcl816_attach(struct comedi_device *dev, struct comedi_devconfig *it) if (ret) return ret; - s = &dev->subdevices[0]; + s = dev->subdevices + 0; if (board->n_aichan > 0) { s->type = COMEDI_SUBD_AI; devpriv->sub_ai = s; diff --git a/trunk/drivers/staging/comedi/drivers/pcl818.c b/trunk/drivers/staging/comedi/drivers/pcl818.c index d4b0859d81f2..34169c16fb92 100644 --- a/trunk/drivers/staging/comedi/drivers/pcl818.c +++ b/trunk/drivers/staging/comedi/drivers/pcl818.c @@ -107,7 +107,6 @@ A word or two about DMA. Driver support DMA operations at two ways: #include #include -#include "comedi_fc.h" #include "8253.h" /* #define PCL818_MODE13_AO 1 */ @@ -478,7 +477,7 @@ static int pcl818_do_insn_bits(struct comedi_device *dev, static irqreturn_t interrupt_pcl818_ai_mode13_int(int irq, void *d) { struct comedi_device *dev = d; - struct comedi_subdevice *s = &dev->subdevices[0]; + struct comedi_subdevice *s = dev->subdevices + 0; int low; int timeout = 50; /* wait max 50us */ @@ -537,7 +536,7 @@ static irqreturn_t interrupt_pcl818_ai_mode13_int(int irq, void *d) static irqreturn_t interrupt_pcl818_ai_mode13_dma(int irq, void *d) { struct comedi_device *dev = d; - struct comedi_subdevice *s = &dev->subdevices[0]; + struct comedi_subdevice *s = dev->subdevices + 0; int i, len, bufptr; unsigned long flags; short *ptr; @@ -616,7 +615,7 @@ static irqreturn_t interrupt_pcl818_ai_mode13_dma(int irq, void *d) static irqreturn_t interrupt_pcl818_ai_mode13_dma_rtc(int irq, void *d) { struct comedi_device *dev = d; - struct comedi_subdevice *s = &dev->subdevices[0]; + struct comedi_subdevice *s = dev->subdevices + 0; unsigned long tmp; unsigned int top1, top2, i, bufptr; long ofs_dats; @@ -721,7 +720,7 @@ static irqreturn_t interrupt_pcl818_ai_mode13_dma_rtc(int irq, void *d) static irqreturn_t interrupt_pcl818_ai_mode13_fifo(int irq, void *d) { struct comedi_device *dev = d; - struct comedi_subdevice *s = &dev->subdevices[0]; + struct comedi_subdevice *s = dev->subdevices + 0; int i, len, lo; outb(0, dev->iobase + PCL818_FI_INTCLR); /* clear fifo int request */ @@ -812,7 +811,7 @@ static irqreturn_t interrupt_pcl818(int irq, void *d) being reprogrammed while a DMA transfer is in progress. */ - struct comedi_subdevice *s = &dev->subdevices[0]; + struct comedi_subdevice *s = dev->subdevices + 0; devpriv->ai_act_scan = 0; devpriv->neverending_ai = 0; pcl818_ai_cancel(dev, s); @@ -1262,23 +1261,43 @@ static int ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, int err = 0; int tmp, divisor1 = 0, divisor2 = 0; - /* Step 1 : check if triggers are trivially valid */ + /* step 1: make sure trigger sources are trivially valid */ - err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW); - err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_FOLLOW); - err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_TIMER | TRIG_EXT); - err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT); - err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE); + tmp = cmd->start_src; + cmd->start_src &= TRIG_NOW; + if (!cmd->start_src || tmp != cmd->start_src) + err++; + + tmp = cmd->scan_begin_src; + cmd->scan_begin_src &= TRIG_FOLLOW; + if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) + err++; + + tmp = cmd->convert_src; + cmd->convert_src &= TRIG_TIMER | TRIG_EXT; + if (!cmd->convert_src || tmp != cmd->convert_src) + err++; + + tmp = cmd->scan_end_src; + cmd->scan_end_src &= TRIG_COUNT; + if (!cmd->scan_end_src || tmp != cmd->scan_end_src) + err++; + + tmp = cmd->stop_src; + cmd->stop_src &= TRIG_COUNT | TRIG_NONE; + if (!cmd->stop_src || tmp != cmd->stop_src) + err++; if (err) return 1; - /* Step 2a : make sure trigger sources are unique */ + /* step 2: make sure trigger sources are unique and mutually compatible */ - err |= cfc_check_trigger_is_unique(cmd->convert_src); - err |= cfc_check_trigger_is_unique(cmd->stop_src); + if (cmd->convert_src != TRIG_TIMER && cmd->convert_src != TRIG_EXT) + err++; - /* Step 2b : and mutually compatible */ + if (cmd->stop_src != TRIG_NONE && cmd->stop_src != TRIG_COUNT) + err++; if (err) return 2; @@ -1744,7 +1763,7 @@ static int pcl818_attach(struct comedi_device *dev, struct comedi_devconfig *it) if (ret) return ret; - s = &dev->subdevices[0]; + s = dev->subdevices + 0; if (!board->n_aichan_se) { s->type = COMEDI_SUBD_UNUSED; } else { @@ -1810,7 +1829,7 @@ static int pcl818_attach(struct comedi_device *dev, struct comedi_devconfig *it) } } - s = &dev->subdevices[1]; + s = dev->subdevices + 1; if (!board->n_aochan) { s->type = COMEDI_SUBD_UNUSED; } else { @@ -1843,7 +1862,7 @@ static int pcl818_attach(struct comedi_device *dev, struct comedi_devconfig *it) } } - s = &dev->subdevices[2]; + s = dev->subdevices + 2; if (!board->n_dichan) { s->type = COMEDI_SUBD_UNUSED; } else { @@ -1856,7 +1875,7 @@ static int pcl818_attach(struct comedi_device *dev, struct comedi_devconfig *it) s->insn_bits = pcl818_di_insn_bits; } - s = &dev->subdevices[3]; + s = dev->subdevices + 3; if (!board->n_dochan) { s->type = COMEDI_SUBD_UNUSED; } else { diff --git a/trunk/drivers/staging/comedi/drivers/pcm3724.c b/trunk/drivers/staging/comedi/drivers/pcm3724.c index 4102547dc6a8..62c22ccfb780 100644 --- a/trunk/drivers/staging/comedi/drivers/pcm3724.c +++ b/trunk/drivers/staging/comedi/drivers/pcm3724.c @@ -119,8 +119,6 @@ static int compute_buffer(int config, int devno, struct comedi_subdevice *s) static void do_3724_config(struct comedi_device *dev, struct comedi_subdevice *s, int chanspec) { - struct comedi_subdevice *s_dio1 = &dev->subdevices[0]; - struct comedi_subdevice *s_dio2 = &dev->subdevices[1]; int config; int buffer_config; unsigned long port_8255_cfg; @@ -138,10 +136,10 @@ static void do_3724_config(struct comedi_device *dev, if (!(s->io_bits & 0xff0000)) config |= CR_C_IO; - buffer_config = compute_buffer(0, 0, s_dio1); - buffer_config = compute_buffer(buffer_config, 1, s_dio2); + buffer_config = compute_buffer(0, 0, dev->subdevices); + buffer_config = compute_buffer(buffer_config, 1, (dev->subdevices) + 1); - if (s == s_dio1) + if (s == dev->subdevices) port_8255_cfg = dev->iobase + _8255_CR; else port_8255_cfg = dev->iobase + SIZE_8255 + _8255_CR; @@ -156,7 +154,6 @@ static void do_3724_config(struct comedi_device *dev, static void enable_chan(struct comedi_device *dev, struct comedi_subdevice *s, int chanspec) { - struct comedi_subdevice *s_dio1 = &dev->subdevices[0]; unsigned int mask; int gatecfg; struct priv_pcm3724 *priv; @@ -165,9 +162,9 @@ static void enable_chan(struct comedi_device *dev, struct comedi_subdevice *s, priv = dev->private; mask = 1 << CR_CHAN(chanspec); - if (s == s_dio1) + if (s == dev->subdevices) /* subdev 0 */ priv->dio_1 |= mask; - else + else /* subdev 1 */ priv->dio_2 |= mask; if (priv->dio_1 & 0xff0000) @@ -234,7 +231,6 @@ static int pcm3724_attach(struct comedi_device *dev, struct comedi_devconfig *it) { const struct pcm3724_board *board = comedi_board(dev); - struct comedi_subdevice *s; unsigned long iobase; unsigned int iorange; int ret, i, n_subdevices; @@ -267,10 +263,9 @@ static int pcm3724_attach(struct comedi_device *dev, return ret; for (i = 0; i < dev->n_subdevices; i++) { - s = &dev->subdevices[i]; - subdev_8255_init(dev, s, subdev_8255_cb, + subdev_8255_init(dev, dev->subdevices + i, subdev_8255_cb, (unsigned long)(dev->iobase + SIZE_8255 * i)); - s->insn_config = subdev_3724_insn_config; + ((dev->subdevices) + i)->insn_config = subdev_3724_insn_config; } return 0; } @@ -278,14 +273,11 @@ static int pcm3724_attach(struct comedi_device *dev, static void pcm3724_detach(struct comedi_device *dev) { const struct pcm3724_board *board = comedi_board(dev); - struct comedi_subdevice *s; int i; if (dev->subdevices) { - for (i = 0; i < dev->n_subdevices; i++) { - s = &dev->subdevices[i]; - subdev_8255_cleanup(dev, s); - } + for (i = 0; i < dev->n_subdevices; i++) + subdev_8255_cleanup(dev, dev->subdevices + i); } if (dev->iobase) release_region(dev->iobase, board->io_range); diff --git a/trunk/drivers/staging/comedi/drivers/pcm3730.c b/trunk/drivers/staging/comedi/drivers/pcm3730.c index 067f14d22610..d65e0bda2c44 100644 --- a/trunk/drivers/staging/comedi/drivers/pcm3730.c +++ b/trunk/drivers/staging/comedi/drivers/pcm3730.c @@ -72,7 +72,7 @@ static int pcm3730_attach(struct comedi_device *dev, if (ret) return ret; - s = &dev->subdevices[0]; + s = dev->subdevices + 0; s->type = COMEDI_SUBD_DO; s->subdev_flags = SDF_WRITABLE; s->maxdata = 1; @@ -81,7 +81,7 @@ static int pcm3730_attach(struct comedi_device *dev, s->range_table = &range_digital; s->private = (void *)PCM3730_DOA; - s = &dev->subdevices[1]; + s = dev->subdevices + 1; s->type = COMEDI_SUBD_DO; s->subdev_flags = SDF_WRITABLE; s->maxdata = 1; @@ -90,7 +90,7 @@ static int pcm3730_attach(struct comedi_device *dev, s->range_table = &range_digital; s->private = (void *)PCM3730_DOB; - s = &dev->subdevices[2]; + s = dev->subdevices + 2; s->type = COMEDI_SUBD_DO; s->subdev_flags = SDF_WRITABLE; s->maxdata = 1; @@ -99,7 +99,7 @@ static int pcm3730_attach(struct comedi_device *dev, s->range_table = &range_digital; s->private = (void *)PCM3730_DOC; - s = &dev->subdevices[3]; + s = dev->subdevices + 3; s->type = COMEDI_SUBD_DI; s->subdev_flags = SDF_READABLE; s->maxdata = 1; @@ -108,7 +108,7 @@ static int pcm3730_attach(struct comedi_device *dev, s->range_table = &range_digital; s->private = (void *)PCM3730_DIA; - s = &dev->subdevices[4]; + s = dev->subdevices + 4; s->type = COMEDI_SUBD_DI; s->subdev_flags = SDF_READABLE; s->maxdata = 1; @@ -117,7 +117,7 @@ static int pcm3730_attach(struct comedi_device *dev, s->range_table = &range_digital; s->private = (void *)PCM3730_DIB; - s = &dev->subdevices[5]; + s = dev->subdevices + 5; s->type = COMEDI_SUBD_DI; s->subdev_flags = SDF_READABLE; s->maxdata = 1; diff --git a/trunk/drivers/staging/comedi/drivers/pcm_common.c b/trunk/drivers/staging/comedi/drivers/pcm_common.c index 85ee05ece9c8..474af7bc6c8b 100644 --- a/trunk/drivers/staging/comedi/drivers/pcm_common.c +++ b/trunk/drivers/staging/comedi/drivers/pcm_common.c @@ -1,30 +1,60 @@ #include "../comedidev.h" - -#include "comedi_fc.h" #include "pcm_common.h" +/* + * 'do_cmdtest' function for an 'INTERRUPT' subdevice. This is for + * the PCM drivers. + */ int comedi_pcm_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd) { int err = 0; + unsigned int tmp; + + /* step 1: make sure trigger sources are trivially valid */ + + tmp = cmd->start_src; + cmd->start_src &= (TRIG_NOW | TRIG_INT); + if (!cmd->start_src || tmp != cmd->start_src) + err++; + + tmp = cmd->scan_begin_src; + cmd->scan_begin_src &= TRIG_EXT; + if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) + err++; + + tmp = cmd->convert_src; + cmd->convert_src &= TRIG_NOW; + if (!cmd->convert_src || tmp != cmd->convert_src) + err++; - /* Step 1 : check if triggers are trivially valid */ + tmp = cmd->scan_end_src; + cmd->scan_end_src &= TRIG_COUNT; + if (!cmd->scan_end_src || tmp != cmd->scan_end_src) + err++; - err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_INT); - err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_EXT); - err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_NOW); - err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT); - err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE); + tmp = cmd->stop_src; + cmd->stop_src &= (TRIG_COUNT | TRIG_NONE); + if (!cmd->stop_src || tmp != cmd->stop_src) + err++; if (err) return 1; - /* Step 2a : make sure trigger sources are unique */ + /* step 2: make sure trigger sources are unique and + * mutually compatible */ - err |= cfc_check_trigger_is_unique(cmd->start_src); - err |= cfc_check_trigger_is_unique(cmd->stop_src); - - /* Step 2b : and mutually compatible */ + /* these tests are true if more than one _src bit is set */ + if ((cmd->start_src & (cmd->start_src - 1)) != 0) + err++; + if ((cmd->scan_begin_src & (cmd->scan_begin_src - 1)) != 0) + err++; + if ((cmd->convert_src & (cmd->convert_src - 1)) != 0) + err++; + if ((cmd->scan_end_src & (cmd->scan_end_src - 1)) != 0) + err++; + if ((cmd->stop_src & (cmd->stop_src - 1)) != 0) + err++; if (err) return 2; diff --git a/trunk/drivers/staging/comedi/drivers/pcmad.c b/trunk/drivers/staging/comedi/drivers/pcmad.c index 5efeb9205c2e..54d19c943967 100644 --- a/trunk/drivers/staging/comedi/drivers/pcmad.c +++ b/trunk/drivers/staging/comedi/drivers/pcmad.c @@ -127,7 +127,7 @@ static int pcmad_attach(struct comedi_device *dev, struct comedi_devconfig *it) dev->board_name = board->name; - s = &dev->subdevices[0]; + s = dev->subdevices + 0; s->type = COMEDI_SUBD_AI; s->subdev_flags = SDF_READABLE | AREF_GROUND; s->n_chan = 16; /* XXX */ diff --git a/trunk/drivers/staging/comedi/drivers/pcmda12.c b/trunk/drivers/staging/comedi/drivers/pcmda12.c index 28af8f6873eb..291ce7c1bdb1 100644 --- a/trunk/drivers/staging/comedi/drivers/pcmda12.c +++ b/trunk/drivers/staging/comedi/drivers/pcmda12.c @@ -195,7 +195,7 @@ static int pcmda12_attach(struct comedi_device *dev, if (ret) return ret; - s = &dev->subdevices[0]; + s = dev->subdevices; s->private = NULL; s->maxdata = (0x1 << BITS) - 1; s->range_table = &pcmda12_ranges; diff --git a/trunk/drivers/staging/comedi/drivers/pcmmio.c b/trunk/drivers/staging/comedi/drivers/pcmmio.c index a10bf0a2987f..3d2e6f01c4b7 100644 --- a/trunk/drivers/staging/comedi/drivers/pcmmio.c +++ b/trunk/drivers/staging/comedi/drivers/pcmmio.c @@ -526,7 +526,6 @@ static irqreturn_t interrupt_pcmmio(int irq, void *d) { int asic, got1 = 0; struct comedi_device *dev = (struct comedi_device *)d; - int i; for (asic = 0; asic < MAX_ASICS; ++asic) { if (irq == devpriv->asics[asic].irq) { @@ -584,8 +583,9 @@ static irqreturn_t interrupt_pcmmio(int irq, void *d) printk (KERN_DEBUG "got edge detect interrupt %d asic %d which_chans: %06x\n", irq, asic, triggered); - for (i = 2; i < dev->n_subdevices; i++) { - s = &dev->subdevices[i]; + for (s = dev->subdevices + 2; + s < dev->subdevices + dev->n_subdevices; + ++s) { /* * this is an interrupt subdev, * and it matches this asic! @@ -1076,8 +1076,9 @@ static int pcmmio_attach(struct comedi_device *dev, struct comedi_devconfig *it) return ret; /* First, AI */ - s = &dev->subdevices[0]; - s->private = &devpriv->sprivs[0]; + sdev_no = 0; + s = dev->subdevices + sdev_no; + s->private = devpriv->sprivs + sdev_no; s->maxdata = (1 << board->ai_bits) - 1; s->range_table = board->ai_range_table; s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DIFF; @@ -1091,8 +1092,9 @@ static int pcmmio_attach(struct comedi_device *dev, struct comedi_devconfig *it) outb(0, subpriv->iobase + 4 + 3); /* Next, AO */ - s = &dev->subdevices[1]; - s->private = &devpriv->sprivs[1]; + ++sdev_no; + s = dev->subdevices + sdev_no; + s->private = devpriv->sprivs + sdev_no; s->maxdata = (1 << board->ao_bits) - 1; s->range_table = board->ao_range_table; s->subdev_flags = SDF_READABLE; @@ -1106,13 +1108,14 @@ static int pcmmio_attach(struct comedi_device *dev, struct comedi_devconfig *it) outb(0, subpriv->iobase + 3); outb(0, subpriv->iobase + 4 + 3); + ++sdev_no; port = 0; asic = 0; - for (sdev_no = 2; sdev_no < dev->n_subdevices; ++sdev_no) { + for (; sdev_no < (int)dev->n_subdevices; ++sdev_no) { int byte_no; - s = &dev->subdevices[sdev_no]; - s->private = &devpriv->sprivs[sdev_no]; + s = dev->subdevices + sdev_no; + s->private = devpriv->sprivs + sdev_no; s->maxdata = 1; s->range_table = &range_digital; s->subdev_flags = SDF_READABLE | SDF_WRITABLE; @@ -1197,6 +1200,15 @@ static int pcmmio_attach(struct comedi_device *dev, struct comedi_devconfig *it) * multiple irqs.. */ + if (irq[0]) { + printk(KERN_DEBUG "comedi%d: irq: %u\n", dev->minor, irq[0]); + if (board->dio_num_asics == 2 && irq[1]) + printk(KERN_DEBUG "comedi%d: second ASIC irq: %u\n", + dev->minor, irq[1]); + } else { + printk(KERN_INFO "comedi%d: (IRQ mode disabled)\n", dev->minor); + } + printk(KERN_INFO "comedi%d: attached\n", dev->minor); return 1; diff --git a/trunk/drivers/staging/comedi/drivers/pcmuio.c b/trunk/drivers/staging/comedi/drivers/pcmuio.c index 0e32119bc3f9..feef3d02f35a 100644 --- a/trunk/drivers/staging/comedi/drivers/pcmuio.c +++ b/trunk/drivers/staging/comedi/drivers/pcmuio.c @@ -442,7 +442,7 @@ static void pcmuio_stop_intr(struct comedi_device *dev, subpriv->intr.enabled_mask = 0; subpriv->intr.active = 0; - s->async->inttrig = NULL; + s->async->inttrig = 0; nports = subpriv->intr.num_asic_chans / CHANS_PER_PORT; firstport = subpriv->intr.asic_chan / CHANS_PER_PORT; switch_page(dev, asic, PAGE_ENAB); @@ -456,7 +456,6 @@ static irqreturn_t interrupt_pcmuio(int irq, void *d) { int asic, got1 = 0; struct comedi_device *dev = (struct comedi_device *)d; - int i; for (asic = 0; asic < MAX_ASICS; ++asic) { if (irq == devpriv->asics[asic].irq) { @@ -508,8 +507,9 @@ static irqreturn_t interrupt_pcmuio(int irq, void *d) printk ("PCMUIO DEBUG: got edge detect interrupt %d asic %d which_chans: %06x\n", irq, asic, triggered); - for (i = 0; i < dev->n_subdevices; i++) { - s = &dev->subdevices[i]; + for (s = dev->subdevices; + s < dev->subdevices + dev->n_subdevices; + ++s) { if (subpriv->intr.asic == asic) { /* this is an interrupt subdev, and it matches this asic! */ unsigned long flags; unsigned oldevents; @@ -683,7 +683,7 @@ pcmuio_inttrig_start_intr(struct comedi_device *dev, struct comedi_subdevice *s, return -EINVAL; spin_lock_irqsave(&subpriv->intr.spinlock, flags); - s->async->inttrig = NULL; + s->async->inttrig = 0; if (subpriv->intr.active) event = pcmuio_start_intr(dev, s); @@ -811,8 +811,8 @@ static int pcmuio_attach(struct comedi_device *dev, struct comedi_devconfig *it) for (sdev_no = 0; sdev_no < (int)dev->n_subdevices; ++sdev_no) { int byte_no; - s = &dev->subdevices[sdev_no]; - s->private = &devpriv->sprivs[sdev_no]; + s = dev->subdevices + sdev_no; + s->private = devpriv->sprivs + sdev_no; s->maxdata = 1; s->range_table = &range_digital; s->subdev_flags = SDF_READABLE | SDF_WRITABLE; diff --git a/trunk/drivers/staging/comedi/drivers/poc.c b/trunk/drivers/staging/comedi/drivers/poc.c index 78dfe167b147..c253bb9ef335 100644 --- a/trunk/drivers/staging/comedi/drivers/poc.c +++ b/trunk/drivers/staging/comedi/drivers/poc.c @@ -164,7 +164,7 @@ static int poc_attach(struct comedi_device *dev, struct comedi_devconfig *it) return -ENOMEM; /* analog output subdevice */ - s = &dev->subdevices[0]; + s = dev->subdevices + 0; s->type = board->type; s->n_chan = board->n_chan; s->maxdata = (1 << board->n_bits) - 1; diff --git a/trunk/drivers/staging/comedi/drivers/quatech_daqp_cs.c b/trunk/drivers/staging/comedi/drivers/quatech_daqp_cs.c index 3e276f7a3380..a029147c9b69 100644 --- a/trunk/drivers/staging/comedi/drivers/quatech_daqp_cs.c +++ b/trunk/drivers/staging/comedi/drivers/quatech_daqp_cs.c @@ -56,8 +56,6 @@ Devices: [Quatech] DAQP-208 (daqp), DAQP-308 #include -#include "comedi_fc.h" - /* Maximum number of separate DAQP devices we'll allow */ #define MAX_DEV 4 @@ -458,26 +456,51 @@ static int daqp_ai_cmdtest(struct comedi_device *dev, int err = 0; int tmp; - /* Step 1 : check if triggers are trivially valid */ + /* step 1: make sure trigger sources are trivially valid */ + + tmp = cmd->start_src; + cmd->start_src &= TRIG_NOW; + if (!cmd->start_src || tmp != cmd->start_src) + err++; + + tmp = cmd->scan_begin_src; + cmd->scan_begin_src &= TRIG_TIMER | TRIG_FOLLOW; + if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) + err++; + + tmp = cmd->convert_src; + cmd->convert_src &= TRIG_TIMER | TRIG_NOW; + if (!cmd->convert_src || tmp != cmd->convert_src) + err++; + + tmp = cmd->scan_end_src; + cmd->scan_end_src &= TRIG_COUNT; + if (!cmd->scan_end_src || tmp != cmd->scan_end_src) + err++; - err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW); - err |= cfc_check_trigger_src(&cmd->scan_begin_src, - TRIG_TIMER | TRIG_FOLLOW); - err |= cfc_check_trigger_src(&cmd->convert_src, - TRIG_TIMER | TRIG_NOW); - err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT); - err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE); + tmp = cmd->stop_src; + cmd->stop_src &= TRIG_COUNT | TRIG_NONE; + if (!cmd->stop_src || tmp != cmd->stop_src) + err++; if (err) return 1; - /* Step 2a : make sure trigger sources are unique */ - - err |= cfc_check_trigger_is_unique(cmd->scan_begin_src); - err |= cfc_check_trigger_is_unique(cmd->convert_src); - err |= cfc_check_trigger_is_unique(cmd->stop_src); + /* + * step 2: make sure trigger sources + * are unique and mutually compatible + */ - /* Step 2b : and mutually compatible */ + /* note that mutual compatibility is not an issue here */ + if (cmd->scan_begin_src != TRIG_TIMER && + cmd->scan_begin_src != TRIG_FOLLOW) + err++; + if (cmd->convert_src != TRIG_NOW && cmd->convert_src != TRIG_TIMER) + err++; + if (cmd->scan_begin_src == TRIG_FOLLOW && cmd->convert_src == TRIG_NOW) + err++; + if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE) + err++; if (err) return 2; @@ -855,7 +878,7 @@ static int daqp_attach(struct comedi_device *dev, struct comedi_devconfig *it) printk(KERN_INFO "comedi%d: attaching daqp%d (io 0x%04lx)\n", dev->minor, it->options[0], dev->iobase); - s = &dev->subdevices[0]; + s = dev->subdevices + 0; dev->read_subdev = s; s->private = local; s->type = COMEDI_SUBD_AI; @@ -869,7 +892,7 @@ static int daqp_attach(struct comedi_device *dev, struct comedi_devconfig *it) s->do_cmd = daqp_ai_cmd; s->cancel = daqp_ai_cancel; - s = &dev->subdevices[1]; + s = dev->subdevices + 1; dev->write_subdev = s; s->private = local; s->type = COMEDI_SUBD_AO; @@ -880,7 +903,7 @@ static int daqp_attach(struct comedi_device *dev, struct comedi_devconfig *it) s->range_table = &range_daqp_ao; s->insn_write = daqp_ao_insn_write; - s = &dev->subdevices[2]; + s = dev->subdevices + 2; s->private = local; s->type = COMEDI_SUBD_DI; s->subdev_flags = SDF_READABLE; @@ -888,7 +911,7 @@ static int daqp_attach(struct comedi_device *dev, struct comedi_devconfig *it) s->len_chanlist = 1; s->insn_read = daqp_di_insn_read; - s = &dev->subdevices[3]; + s = dev->subdevices + 3; s->private = local; s->type = COMEDI_SUBD_DO; s->subdev_flags = SDF_WRITEABLE; diff --git a/trunk/drivers/staging/comedi/drivers/rtd520.c b/trunk/drivers/staging/comedi/drivers/rtd520.c index 41d24b08913b..112fdc3e9c69 100644 --- a/trunk/drivers/staging/comedi/drivers/rtd520.c +++ b/trunk/drivers/staging/comedi/drivers/rtd520.c @@ -106,8 +106,6 @@ Configuration options: #include "../comedidev.h" -#include "comedi_fc.h" - #define DRV_NAME "rtd520" /*====================================================================== @@ -785,7 +783,7 @@ static irqreturn_t rtd_interrupt(int irq, /* interrupt number (ignored) */ void *d) { /* our data *//* cpu context (ignored) */ struct comedi_device *dev = d; - struct comedi_subdevice *s = &dev->subdevices[0]; + struct comedi_subdevice *s = dev->subdevices + 0; /* analog in subdevice */ struct rtdPrivate *devpriv = dev->private; u32 overrun; u16 status; @@ -966,7 +964,7 @@ static int rtd_ai_poll(struct comedi_device *dev, struct comedi_subdevice *s) /* cmdtest tests a particular command to see if it is valid. Using the cmdtest ioctl, a user can create a valid cmd - and then have it executed by the cmd ioctl (asynchronously). + and then have it executed by the cmd ioctl (asyncronously). cmdtest returns 1,2,3,4 or 0, depending on which tests the command passes. @@ -978,25 +976,52 @@ static int rtd_ai_cmdtest(struct comedi_device *dev, int err = 0; int tmp; - /* Step 1 : check if triggers are trivially valid */ + /* step 1: make sure trigger sources are trivially valid */ + + tmp = cmd->start_src; + cmd->start_src &= TRIG_NOW; + if (!cmd->start_src || tmp != cmd->start_src) + err++; + + tmp = cmd->scan_begin_src; + cmd->scan_begin_src &= TRIG_TIMER | TRIG_EXT; + if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) + err++; + + + tmp = cmd->convert_src; + cmd->convert_src &= TRIG_TIMER | TRIG_EXT; + if (!cmd->convert_src || tmp != cmd->convert_src) + err++; + + + tmp = cmd->scan_end_src; + cmd->scan_end_src &= TRIG_COUNT; + if (!cmd->scan_end_src || tmp != cmd->scan_end_src) + err++; + + + tmp = cmd->stop_src; + cmd->stop_src &= TRIG_COUNT | TRIG_NONE; + if (!cmd->stop_src || tmp != cmd->stop_src) + err++; - err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW); - err |= cfc_check_trigger_src(&cmd->scan_begin_src, - TRIG_TIMER | TRIG_EXT); - err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_TIMER | TRIG_EXT); - err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT); - err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE); if (err) return 1; - /* Step 2a : make sure trigger sources are unique */ - - err |= cfc_check_trigger_is_unique(cmd->scan_begin_src); - err |= cfc_check_trigger_is_unique(cmd->convert_src); - err |= cfc_check_trigger_is_unique(cmd->stop_src); + /* step 2: make sure trigger sources are unique + and mutually compatible */ + /* note that mutual compatibility is not an issue here */ + if (cmd->scan_begin_src != TRIG_TIMER && + cmd->scan_begin_src != TRIG_EXT) { + err++; + } + if (cmd->convert_src != TRIG_TIMER && cmd->convert_src != TRIG_EXT) + err++; - /* Step 2b : and mutually compatible */ + if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE) + err++; if (err) return 2; @@ -1594,8 +1619,9 @@ static int rtd_attach(struct comedi_device *dev, struct comedi_devconfig *it) struct rtdPrivate *devpriv; struct pci_dev *pcidev; struct comedi_subdevice *s; - resource_size_t pci_base; int ret; + resource_size_t physLas1; /* data area */ + resource_size_t physLcfg; /* PLX9080 */ #ifdef USE_DMA int index; #endif @@ -1629,15 +1655,20 @@ static int rtd_attach(struct comedi_device *dev, struct comedi_devconfig *it) printk(KERN_INFO "Failed to enable PCI device and request regions.\n"); return ret; } - dev->iobase = 1; /* the "detach" needs this */ - - /* Initialize the base addresses */ - pci_base = pci_resource_start(pcidev, LAS0_PCIINDEX); - devpriv->las0 = ioremap_nocache(pci_base, LAS0_PCISIZE); - pci_base = pci_resource_start(pcidev, LAS1_PCIINDEX); - devpriv->las1 = ioremap_nocache(pci_base, LAS1_PCISIZE); - pci_base = pci_resource_start(pcidev, LCFG_PCIINDEX); - devpriv->lcfg = ioremap_nocache(pci_base, LCFG_PCISIZE); + + /* + * Initialize base addresses + */ + /* Get the physical address from PCI config */ + dev->iobase = pci_resource_start(pcidev, LAS0_PCIINDEX); + physLas1 = pci_resource_start(pcidev, LAS1_PCIINDEX); + physLcfg = pci_resource_start(pcidev, LCFG_PCIINDEX); + /* Now have the kernel map this into memory */ + /* ASSUME page aligned */ + devpriv->las0 = ioremap_nocache(dev->iobase, LAS0_PCISIZE); + devpriv->las1 = ioremap_nocache(physLas1, LAS1_PCISIZE); + devpriv->lcfg = ioremap_nocache(physLcfg, LCFG_PCISIZE); + if (!devpriv->las0 || !devpriv->las1 || !devpriv->lcfg) return -ENOMEM; @@ -1681,7 +1712,7 @@ static int rtd_attach(struct comedi_device *dev, struct comedi_devconfig *it) if (ret) return ret; - s = &dev->subdevices[0]; + s = dev->subdevices + 0; dev->read_subdev = s; /* analog input subdevice */ s->type = COMEDI_SUBD_AI; @@ -1701,7 +1732,7 @@ static int rtd_attach(struct comedi_device *dev, struct comedi_devconfig *it) s->cancel = rtd_ai_cancel; /* s->poll = rtd_ai_poll; *//* not ready yet */ - s = &dev->subdevices[1]; + s = dev->subdevices + 1; /* analog output subdevice */ s->type = COMEDI_SUBD_AO; s->subdev_flags = SDF_WRITABLE; @@ -1711,7 +1742,7 @@ static int rtd_attach(struct comedi_device *dev, struct comedi_devconfig *it) s->insn_write = rtd_ao_winsn; s->insn_read = rtd_ao_rinsn; - s = &dev->subdevices[2]; + s = dev->subdevices + 2; /* digital i/o subdevice */ s->type = COMEDI_SUBD_DIO; s->subdev_flags = SDF_READABLE | SDF_WRITABLE; @@ -1723,7 +1754,7 @@ static int rtd_attach(struct comedi_device *dev, struct comedi_devconfig *it) s->insn_config = rtd_dio_insn_config; /* timer/counter subdevices (not currently supported) */ - s = &dev->subdevices[3]; + s = dev->subdevices + 3; s->type = COMEDI_SUBD_COUNTER; s->subdev_flags = SDF_READABLE | SDF_WRITABLE; s->n_chan = 3; diff --git a/trunk/drivers/staging/comedi/drivers/rti800.c b/trunk/drivers/staging/comedi/drivers/rti800.c index 137885b1681a..f7fa940d9783 100644 --- a/trunk/drivers/staging/comedi/drivers/rti800.c +++ b/trunk/drivers/staging/comedi/drivers/rti800.c @@ -360,7 +360,7 @@ static int rti800_attach(struct comedi_device *dev, struct comedi_devconfig *it) devpriv->dac1_coding = it->options[8]; devpriv->muxgain_bits = -1; - s = &dev->subdevices[0]; + s = dev->subdevices + 0; /* ai subdevice */ s->type = COMEDI_SUBD_AI; s->subdev_flags = SDF_READABLE | SDF_GROUND; @@ -379,7 +379,7 @@ static int rti800_attach(struct comedi_device *dev, struct comedi_devconfig *it) break; } - s = &dev->subdevices[1]; + s++; if (board->has_ao) { /* ao subdevice (only on rti815) */ s->type = COMEDI_SUBD_AO; @@ -409,7 +409,7 @@ static int rti800_attach(struct comedi_device *dev, struct comedi_devconfig *it) s->type = COMEDI_SUBD_UNUSED; } - s = &dev->subdevices[2]; + s++; /* di */ s->type = COMEDI_SUBD_DI; s->subdev_flags = SDF_READABLE; @@ -418,7 +418,7 @@ static int rti800_attach(struct comedi_device *dev, struct comedi_devconfig *it) s->maxdata = 1; s->range_table = &range_digital; - s = &dev->subdevices[3]; + s++; /* do */ s->type = COMEDI_SUBD_DO; s->subdev_flags = SDF_WRITABLE; @@ -429,7 +429,7 @@ static int rti800_attach(struct comedi_device *dev, struct comedi_devconfig *it) /* don't yet know how to deal with counter/timers */ #if 0 - s = &dev->subdevices[4]; + s++; /* do */ s->type = COMEDI_SUBD_TIMER; #endif diff --git a/trunk/drivers/staging/comedi/drivers/rti802.c b/trunk/drivers/staging/comedi/drivers/rti802.c index 3f9d0278be50..fc16508181d4 100644 --- a/trunk/drivers/staging/comedi/drivers/rti802.c +++ b/trunk/drivers/staging/comedi/drivers/rti802.c @@ -111,7 +111,7 @@ static int rti802_attach(struct comedi_device *dev, struct comedi_devconfig *it) if (ret) return ret; - s = &dev->subdevices[0]; + s = dev->subdevices; /* ao subdevice */ s->type = COMEDI_SUBD_AO; s->subdev_flags = SDF_WRITABLE; diff --git a/trunk/drivers/staging/comedi/drivers/s526.c b/trunk/drivers/staging/comedi/drivers/s526.c index a1e256293bd6..737a194dfce3 100644 --- a/trunk/drivers/staging/comedi/drivers/s526.c +++ b/trunk/drivers/staging/comedi/drivers/s526.c @@ -83,6 +83,36 @@ comedi_config /dev/comedi0 s526 0x2C0,0x3 #define REG_EED 0x32 #define REG_EEC 0x34 +static const int s526_ports[] = { + REG_TCR, + REG_WDC, + REG_DAC, + REG_ADC, + REG_ADD, + REG_DIO, + REG_IER, + REG_ISR, + REG_MSC, + REG_C0L, + REG_C0H, + REG_C0M, + REG_C0C, + REG_C1L, + REG_C1H, + REG_C1M, + REG_C1C, + REG_C2L, + REG_C2H, + REG_C2M, + REG_C2C, + REG_C3L, + REG_C3H, + REG_C3M, + REG_C3C, + REG_EED, + REG_EEC +}; + struct counter_mode_register_t { #if defined(__LITTLE_ENDIAN_BITFIELD) unsigned short coutSource:1; @@ -118,48 +148,122 @@ union cmReg { unsigned short value; }; +#define MAX_GPCT_CONFIG_DATA 6 + +/* Different Application Classes for GPCT Subdevices */ +/* The list is not exhaustive and needs discussion! */ +enum S526_GPCT_APP_CLASS { + CountingAndTimeMeasurement, + SinglePulseGeneration, + PulseTrainGeneration, + PositionMeasurement, + Miscellaneous +}; + +/* Config struct for different GPCT subdevice Application Classes and + their options +*/ +struct s526GPCTConfig { + enum S526_GPCT_APP_CLASS app; + int data[MAX_GPCT_CONFIG_DATA]; +}; + +/* + * Board descriptions for two imaginary boards. Describing the + * boards in this way is optional, and completely driver-dependent. + * Some drivers use arrays such as this, other do not. + */ +struct s526_board { + const char *name; + int gpct_chans; + int gpct_bits; + int ad_chans; + int ad_bits; + int da_chans; + int da_bits; + int have_dio; +}; + +static const struct s526_board s526_boards[] = { + { + .name = "s526", + .gpct_chans = 4, + .gpct_bits = 24, + .ad_chans = 8, + .ad_bits = 16, + .da_chans = 4, + .da_bits = 16, + .have_dio = 1, + } +}; + +#define ADDR_REG(reg) (dev->iobase + (reg)) +#define ADDR_CHAN_REG(reg, chan) (dev->iobase + (reg) + (chan) * 8) + +/* this structure is for data unique to this hardware driver. If + several hardware drivers keep similar information in this structure, + feel free to suggest moving the variable to the struct comedi_device + struct. +*/ struct s526_private { unsigned int ao_readback[2]; - unsigned int gpct_config[4]; - unsigned short ai_config; + struct s526GPCTConfig s526_gpct_config[4]; + unsigned short s526_ai_config; }; +/* + * most drivers define the following macro to make it easy to + * access the private structure. + */ +#define devpriv ((struct s526_private *)dev->private) + static int s526_gpct_rinsn(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, + struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - unsigned int chan = CR_CHAN(insn->chanspec); - unsigned long chan_iobase = dev->iobase + chan * 8; - unsigned int lo; - unsigned int hi; - int i; - + int i; /* counts the Data */ + int counter_channel = CR_CHAN(insn->chanspec); + unsigned short datalow; + unsigned short datahigh; + + /* Check if (n > 0) */ + if (insn->n <= 0) { + printk(KERN_ERR "s526: INSN_READ: n should be > 0\n"); + return -EINVAL; + } + /* Read the low word first */ for (i = 0; i < insn->n; i++) { - /* Read the low word first */ - lo = inw(chan_iobase + REG_C0L) & 0xffff; - hi = inw(chan_iobase + REG_C0H) & 0xff; - - data[i] = (hi << 16) | lo; + datalow = inw(ADDR_CHAN_REG(REG_C0L, counter_channel)); + datahigh = inw(ADDR_CHAN_REG(REG_C0H, counter_channel)); + data[i] = (int)(datahigh & 0x00FF); + data[i] = (data[i] << 16) | (datalow & 0xFFFF); + /* printk("s526 GPCT[%d]: %x(0x%04x, 0x%04x)\n", + counter_channel, data[i], datahigh, datalow); */ } - - return insn->n; + return i; } static int s526_gpct_insn_config(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) + struct comedi_insn *insn, unsigned int *data) { - struct s526_private *devpriv = dev->private; - unsigned int chan = CR_CHAN(insn->chanspec); - unsigned long chan_iobase = dev->iobase + chan * 8; - unsigned int val; + int subdev_channel = CR_CHAN(insn->chanspec); /* Unpack chanspec */ + int i; + short value; union cmReg cmReg; + /* printk("s526: GPCT_INSN_CONFIG: Configuring Channel %d\n", + subdev_channel); */ + + for (i = 0; i < MAX_GPCT_CONFIG_DATA; i++) { + devpriv->s526_gpct_config[subdev_channel].data[i] = + insn->data[i]; +/* printk("data[%d]=%x\n", i, insn->data[i]); */ + } + /* Check what type of Counter the user requested, data[0] contains */ /* the Application type */ - switch (data[0]) { + switch (insn->data[0]) { case INSN_CONFIG_GPCT_QUADRATURE_ENCODER: /* data[0]: Application Type @@ -167,7 +271,9 @@ static int s526_gpct_insn_config(struct comedi_device *dev, data[2]: Pre-load Register Value data[3]: Conter Control Register */ - devpriv->gpct_config[chan] = data[0]; + printk(KERN_INFO "s526: GPCT_INSN_CONFIG: Configuring Encoder\n"); + devpriv->s526_gpct_config[subdev_channel].app = + PositionMeasurement; #if 0 /* Example of Counter Application */ @@ -184,32 +290,34 @@ static int s526_gpct_insn_config(struct comedi_device *dev, cmReg.reg.preloadRegSel = 0; /* PR0 */ cmReg.reg.reserved = 0; - outw(cmReg.value, chan_iobase + REG_C0M); + outw(cmReg.value, ADDR_CHAN_REG(REG_C0M, subdev_channel)); - outw(0x0001, chan_iobase + REG_C0H); - outw(0x3C68, chan_iobase + REG_C0L); + outw(0x0001, ADDR_CHAN_REG(REG_C0H, subdev_channel)); + outw(0x3C68, ADDR_CHAN_REG(REG_C0L, subdev_channel)); /* Reset the counter */ - outw(0x8000, chan_iobase + REG_C0C); + outw(0x8000, ADDR_CHAN_REG(REG_C0C, subdev_channel)); /* Load the counter from PR0 */ - outw(0x4000, chan_iobase + REG_C0C); + outw(0x4000, ADDR_CHAN_REG(REG_C0C, subdev_channel)); /* Reset RCAP (fires one-shot) */ - outw(0x0008, chan_iobase + REG_C0C); + outw(0x0008, ADDR_CHAN_REG(REG_C0C, subdev_channel)); #endif #if 1 /* Set Counter Mode Register */ - cmReg.value = data[1] & 0xffff; - outw(cmReg.value, chan_iobase + REG_C0M); + cmReg.value = insn->data[1] & 0xFFFF; + +/* printk("s526: Counter Mode register=%x\n", cmReg.value); */ + outw(cmReg.value, ADDR_CHAN_REG(REG_C0M, subdev_channel)); /* Reset the counter if it is software preload */ if (cmReg.reg.autoLoadResetRcap == 0) { /* Reset the counter */ - outw(0x8000, chan_iobase + REG_C0C); + outw(0x8000, ADDR_CHAN_REG(REG_C0C, subdev_channel)); /* Load the counter from PR0 - * outw(0x4000, chan_iobase + REG_C0C); + * outw(0x4000, ADDR_CHAN_REG(REG_C0C, subdev_channel)); */ } #else @@ -217,47 +325,47 @@ static int s526_gpct_insn_config(struct comedi_device *dev, cmReg.reg.countDirCtrl = 0; /* data[1] contains GPCT_X1, GPCT_X2 or GPCT_X4 */ - if (data[1] == GPCT_X2) + if (insn->data[1] == GPCT_X2) cmReg.reg.clockSource = 1; - else if (data[1] == GPCT_X4) + else if (insn->data[1] == GPCT_X4) cmReg.reg.clockSource = 2; else cmReg.reg.clockSource = 0; /* When to take into account the indexpulse: */ - /*if (data[2] == GPCT_IndexPhaseLowLow) { - } else if (data[2] == GPCT_IndexPhaseLowHigh) { - } else if (data[2] == GPCT_IndexPhaseHighLow) { - } else if (data[2] == GPCT_IndexPhaseHighHigh) { + /*if (insn->data[2] == GPCT_IndexPhaseLowLow) { + } else if (insn->data[2] == GPCT_IndexPhaseLowHigh) { + } else if (insn->data[2] == GPCT_IndexPhaseHighLow) { + } else if (insn->data[2] == GPCT_IndexPhaseHighHigh) { }*/ /* Take into account the index pulse? */ - if (data[3] == GPCT_RESET_COUNTER_ON_INDEX) + if (insn->data[3] == GPCT_RESET_COUNTER_ON_INDEX) /* Auto load with INDEX^ */ cmReg.reg.autoLoadResetRcap = 4; /* Set Counter Mode Register */ - cmReg.value = data[1] & 0xffff; - outw(cmReg.value, chan_iobase + REG_C0M); + cmReg.value = (short)(insn->data[1] & 0xFFFF); + outw(cmReg.value, ADDR_CHAN_REG(REG_C0M, subdev_channel)); /* Load the pre-load register high word */ - val = (data[2] >> 16) & 0xffff; - outw(val, chan_iobase + REG_C0H); + value = (short)((insn->data[2] >> 16) & 0xFFFF); + outw(value, ADDR_CHAN_REG(REG_C0H, subdev_channel)); /* Load the pre-load register low word */ - val = data[2] & 0xffff; - outw(val, chan_iobase + REG_C0L); + value = (short)(insn->data[2] & 0xFFFF); + outw(value, ADDR_CHAN_REG(REG_C0L, subdev_channel)); /* Write the Counter Control Register */ - if (data[3]) { - val = data[3] & 0xffff; - outw(val, chan_iobase + REG_C0C); + if (insn->data[3] != 0) { + value = (short)(insn->data[3] & 0xFFFF); + outw(value, ADDR_CHAN_REG(REG_C0C, subdev_channel)); } /* Reset the counter if it is software preload */ if (cmReg.reg.autoLoadResetRcap == 0) { /* Reset the counter */ - outw(0x8000, chan_iobase + REG_C0C); + outw(0x8000, ADDR_CHAN_REG(REG_C0C, subdev_channel)); /* Load the counter from PR0 */ - outw(0x4000, chan_iobase + REG_C0C); + outw(0x4000, ADDR_CHAN_REG(REG_C0C, subdev_channel)); } #endif break; @@ -270,38 +378,40 @@ static int s526_gpct_insn_config(struct comedi_device *dev, data[3]: Pre-load Register 1 Value data[4]: Conter Control Register */ - devpriv->gpct_config[chan] = data[0]; + printk(KERN_INFO "s526: GPCT_INSN_CONFIG: Configuring SPG\n"); + devpriv->s526_gpct_config[subdev_channel].app = + SinglePulseGeneration; /* Set Counter Mode Register */ - cmReg.value = data[1] & 0xffff; + cmReg.value = (short)(insn->data[1] & 0xFFFF); cmReg.reg.preloadRegSel = 0; /* PR0 */ - outw(cmReg.value, chan_iobase + REG_C0M); + outw(cmReg.value, ADDR_CHAN_REG(REG_C0M, subdev_channel)); /* Load the pre-load register 0 high word */ - val = (data[2] >> 16) & 0xffff; - outw(val, chan_iobase + REG_C0H); + value = (short)((insn->data[2] >> 16) & 0xFFFF); + outw(value, ADDR_CHAN_REG(REG_C0H, subdev_channel)); /* Load the pre-load register 0 low word */ - val = data[2] & 0xffff; - outw(val, chan_iobase + REG_C0L); + value = (short)(insn->data[2] & 0xFFFF); + outw(value, ADDR_CHAN_REG(REG_C0L, subdev_channel)); /* Set Counter Mode Register */ - cmReg.value = data[1] & 0xffff; + cmReg.value = (short)(insn->data[1] & 0xFFFF); cmReg.reg.preloadRegSel = 1; /* PR1 */ - outw(cmReg.value, chan_iobase + REG_C0M); + outw(cmReg.value, ADDR_CHAN_REG(REG_C0M, subdev_channel)); /* Load the pre-load register 1 high word */ - val = (data[3] >> 16) & 0xffff; - outw(val, chan_iobase + REG_C0H); + value = (short)((insn->data[3] >> 16) & 0xFFFF); + outw(value, ADDR_CHAN_REG(REG_C0H, subdev_channel)); /* Load the pre-load register 1 low word */ - val = data[3] & 0xffff; - outw(val, chan_iobase + REG_C0L); + value = (short)(insn->data[3] & 0xFFFF); + outw(value, ADDR_CHAN_REG(REG_C0L, subdev_channel)); /* Write the Counter Control Register */ - if (data[4]) { - val = data[4] & 0xffff; - outw(val, chan_iobase + REG_C0C); + if (insn->data[4] != 0) { + value = (short)(insn->data[4] & 0xFFFF); + outw(value, ADDR_CHAN_REG(REG_C0C, subdev_channel)); } break; @@ -313,42 +423,45 @@ static int s526_gpct_insn_config(struct comedi_device *dev, data[3]: Pre-load Register 1 Value data[4]: Conter Control Register */ - devpriv->gpct_config[chan] = data[0]; + printk(KERN_INFO "s526: GPCT_INSN_CONFIG: Configuring PTG\n"); + devpriv->s526_gpct_config[subdev_channel].app = + PulseTrainGeneration; /* Set Counter Mode Register */ - cmReg.value = data[1] & 0xffff; + cmReg.value = (short)(insn->data[1] & 0xFFFF); cmReg.reg.preloadRegSel = 0; /* PR0 */ - outw(cmReg.value, chan_iobase + REG_C0M); + outw(cmReg.value, ADDR_CHAN_REG(REG_C0M, subdev_channel)); /* Load the pre-load register 0 high word */ - val = (data[2] >> 16) & 0xffff; - outw(val, chan_iobase + REG_C0H); + value = (short)((insn->data[2] >> 16) & 0xFFFF); + outw(value, ADDR_CHAN_REG(REG_C0H, subdev_channel)); /* Load the pre-load register 0 low word */ - val = data[2] & 0xffff; - outw(val, chan_iobase + REG_C0L); + value = (short)(insn->data[2] & 0xFFFF); + outw(value, ADDR_CHAN_REG(REG_C0L, subdev_channel)); /* Set Counter Mode Register */ - cmReg.value = data[1] & 0xffff; + cmReg.value = (short)(insn->data[1] & 0xFFFF); cmReg.reg.preloadRegSel = 1; /* PR1 */ - outw(cmReg.value, chan_iobase + REG_C0M); + outw(cmReg.value, ADDR_CHAN_REG(REG_C0M, subdev_channel)); /* Load the pre-load register 1 high word */ - val = (data[3] >> 16) & 0xffff; - outw(val, chan_iobase + REG_C0H); + value = (short)((insn->data[3] >> 16) & 0xFFFF); + outw(value, ADDR_CHAN_REG(REG_C0H, subdev_channel)); /* Load the pre-load register 1 low word */ - val = data[3] & 0xffff; - outw(val, chan_iobase + REG_C0L); + value = (short)(insn->data[3] & 0xFFFF); + outw(value, ADDR_CHAN_REG(REG_C0L, subdev_channel)); /* Write the Counter Control Register */ - if (data[4]) { - val = data[4] & 0xffff; - outw(val, chan_iobase + REG_C0C); + if (insn->data[4] != 0) { + value = (short)(insn->data[4] & 0xFFFF); + outw(value, ADDR_CHAN_REG(REG_C0C, subdev_channel)); } break; default: + printk(KERN_ERR "s526: unsupported GPCT_insn_config\n"); return -EINVAL; break; } @@ -357,40 +470,65 @@ static int s526_gpct_insn_config(struct comedi_device *dev, } static int s526_gpct_winsn(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, + struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - struct s526_private *devpriv = dev->private; - unsigned int chan = CR_CHAN(insn->chanspec); - unsigned long chan_iobase = dev->iobase + chan * 8; - - inw(chan_iobase + REG_C0M); /* Is this read required? */ + int subdev_channel = CR_CHAN(insn->chanspec); /* Unpack chanspec */ + short value; + union cmReg cmReg; + printk(KERN_INFO "s526: GPCT_INSN_WRITE on channel %d\n", + subdev_channel); + cmReg.value = inw(ADDR_CHAN_REG(REG_C0M, subdev_channel)); + printk(KERN_INFO "s526: Counter Mode Register: %x\n", cmReg.value); /* Check what Application of Counter this channel is configured for */ - switch (devpriv->gpct_config[chan]) { - case INSN_CONFIG_GPCT_PULSE_TRAIN_GENERATOR: + switch (devpriv->s526_gpct_config[subdev_channel].app) { + case PositionMeasurement: + printk(KERN_INFO "S526: INSN_WRITE: PM\n"); + outw(0xFFFF & ((*data) >> 16), ADDR_CHAN_REG(REG_C0H, + subdev_channel)); + outw(0xFFFF & (*data), ADDR_CHAN_REG(REG_C0L, subdev_channel)); + break; + + case SinglePulseGeneration: + printk(KERN_INFO "S526: INSN_WRITE: SPG\n"); + outw(0xFFFF & ((*data) >> 16), ADDR_CHAN_REG(REG_C0H, + subdev_channel)); + outw(0xFFFF & (*data), ADDR_CHAN_REG(REG_C0L, subdev_channel)); + break; + + case PulseTrainGeneration: /* data[0] contains the PULSE_WIDTH data[1] contains the PULSE_PERIOD @pre PULSE_PERIOD > PULSE_WIDTH > 0 The above periods must be expressed as a multiple of the pulse frequency on the selected source */ - if ((data[1] <= data[0]) || !data[0]) + printk(KERN_INFO "S526: INSN_WRITE: PTG\n"); + if ((insn->data[1] > insn->data[0]) && (insn->data[0] > 0)) { + (devpriv->s526_gpct_config[subdev_channel]).data[0] = + insn->data[0]; + (devpriv->s526_gpct_config[subdev_channel]).data[1] = + insn->data[1]; + } else { + printk(KERN_ERR "s526: INSN_WRITE: PTG: Problem with Pulse params -> %d %d\n", + insn->data[0], insn->data[1]); return -EINVAL; + } - /* Fall thru to write the PULSE_WIDTH */ - - case INSN_CONFIG_GPCT_QUADRATURE_ENCODER: - case INSN_CONFIG_GPCT_SINGLE_PULSE_GENERATOR: - outw((data[0] >> 16) & 0xffff, chan_iobase + REG_C0H); - outw(data[0] & 0xffff, chan_iobase + REG_C0L); + value = (short)((*data >> 16) & 0xFFFF); + outw(value, ADDR_CHAN_REG(REG_C0H, subdev_channel)); + value = (short)(*data & 0xFFFF); + outw(value, ADDR_CHAN_REG(REG_C0L, subdev_channel)); break; - - default: + default: /* Impossible */ + printk + ("s526: INSN_WRITE: Functionality %d not implemented yet\n", + devpriv->s526_gpct_config[subdev_channel].app); return -EINVAL; + break; } - + /* return the number of samples written */ return insn->n; } @@ -399,7 +537,6 @@ static int s526_ai_insn_config(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - struct s526_private *devpriv = dev->private; int result = -EINVAL; if (insn->n < 1) @@ -415,50 +552,62 @@ static int s526_ai_insn_config(struct comedi_device *dev, * INSN_READ handler. */ /* Enable ADC interrupt */ - outw(ISR_ADC_DONE, dev->iobase + REG_IER); - devpriv->ai_config = (data[0] & 0x3ff) << 5; + outw(ISR_ADC_DONE, ADDR_REG(REG_IER)); +/* printk("s526: ADC current value: 0x%04x\n", inw(ADDR_REG(REG_ADC))); */ + devpriv->s526_ai_config = (data[0] & 0x3FF) << 5; if (data[1] > 0) - devpriv->ai_config |= 0x8000; /* set the delay */ + devpriv->s526_ai_config |= 0x8000; /* set the delay */ - devpriv->ai_config |= 0x0001; /* ADC start bit */ + devpriv->s526_ai_config |= 0x0001; /* ADC start bit. */ return result; } +/* + * "instructions" read/write data in "one-shot" or "software-triggered" + * mode. + */ static int s526_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - struct s526_private *devpriv = dev->private; - unsigned int chan = CR_CHAN(insn->chanspec); int n, i; + int chan = CR_CHAN(insn->chanspec); unsigned short value; unsigned int d; unsigned int status; /* Set configured delay, enable channel for this channel only, * select "ADC read" channel, set "ADC start" bit. */ - value = (devpriv->ai_config & 0x8000) | - ((1 << 5) << chan) | (chan << 1) | 0x0001; + value = (devpriv->s526_ai_config & 0x8000) | + ((1 << 5) << chan) | (chan << 1) | 0x0001; /* convert n samples */ for (n = 0; n < insn->n; n++) { /* trigger conversion */ - outw(value, dev->iobase + REG_ADC); + outw(value, ADDR_REG(REG_ADC)); +/* printk("s526: Wrote 0x%04x to ADC\n", value); */ +/* printk("s526: ADC reg=0x%04x\n", inw(ADDR_REG(REG_ADC))); */ #define TIMEOUT 100 /* wait for conversion to end */ for (i = 0; i < TIMEOUT; i++) { - status = inw(dev->iobase + REG_ISR); + status = inw(ADDR_REG(REG_ISR)); if (status & ISR_ADC_DONE) { - outw(ISR_ADC_DONE, dev->iobase + REG_ISR); + outw(ISR_ADC_DONE, ADDR_REG(REG_ISR)); break; } } - if (i == TIMEOUT) + if (i == TIMEOUT) { + /* printk() should be used instead of printk() + * whenever the code can be called from real-time. */ + printk(KERN_ERR "s526: ADC(0x%04x) timeout\n", + inw(ADDR_REG(REG_ISR))); return -ETIMEDOUT; + } /* read data */ - d = inw(dev->iobase + REG_ADD); + d = inw(ADDR_REG(REG_ADD)); +/* printk("AI[%d]=0x%04x\n", n, (unsigned short)(d & 0xFFFF)); */ /* munge data */ data[n] = d ^ 0x8000; @@ -471,30 +620,40 @@ static int s526_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, static int s526_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - struct s526_private *devpriv = dev->private; - unsigned int chan = CR_CHAN(insn->chanspec); - unsigned short val; int i; + int chan = CR_CHAN(insn->chanspec); + unsigned short val; +/* printk("s526_ao_winsn\n"); */ val = chan << 1; - outw(val, dev->iobase + REG_DAC); +/* outw(val, dev->iobase + REG_DAC); */ + outw(val, ADDR_REG(REG_DAC)); + /* Writing a list of values to an AO channel is probably not + * very useful, but that's how the interface is defined. */ for (i = 0; i < insn->n; i++) { - outw(data[i], dev->iobase + REG_ADD); + /* a typical programming sequence */ + /* write the data to preload register + * outw(data[i], dev->iobase + REG_ADD); + */ + /* write the data to preload register */ + outw(data[i], ADDR_REG(REG_ADD)); devpriv->ao_readback[chan] = data[i]; - /* starts the D/A conversion */ - outw(val + 1, dev->iobase + REG_DAC); +/* outw(val + 1, dev->iobase + REG_DAC); starts the D/A conversion. */ + outw(val + 1, ADDR_REG(REG_DAC)); /*starts the D/A conversion.*/ } + /* return the number of samples read/written */ return i; } +/* AO subdevices should have a read insn as well as a write insn. + * Usually this means copying a value stored in devpriv. */ static int s526_ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - struct s526_private *devpriv = dev->private; - unsigned int chan = CR_CHAN(insn->chanspec); int i; + int chan = CR_CHAN(insn->chanspec); for (i = 0; i < insn->n; i++) data[i] = devpriv->ao_readback[chan]; @@ -502,18 +661,30 @@ static int s526_ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, return i; } +/* DIO devices are slightly special. Although it is possible to + * implement the insn_read/insn_write interface, it is much more + * useful to applications if you implement the insn_bits interface. + * This allows packed reading/writing of the DIO channels. The + * comedi core can convert between insn_bits and insn_read/write */ static int s526_dio_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { + /* The insn data is a mask in data[0] and the new data + * in data[1], each channel cooresponding to a bit. */ if (data[0]) { s->state &= ~data[0]; s->state |= data[0] & data[1]; - - outw(s->state, dev->iobase + REG_DIO); + /* Write out the new digital output lines */ + outw(s->state, ADDR_REG(REG_DIO)); } - data[1] = inw(dev->iobase + REG_DIO) & 0xff; + /* on return, data[1] contains the value of the digital + * input and output lines. */ + data[1] = inw(ADDR_REG(REG_DIO)) & 0xFF; /* low 8 bits are the data */ + /* or we could just return the software copy of the output values if + * it was a purely digital output subdevice */ + /* data[1]=s->state & 0xFF; */ return insn->n; } @@ -522,9 +693,16 @@ static int s526_dio_insn_config(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - unsigned int chan = CR_CHAN(insn->chanspec); + int chan = CR_CHAN(insn->chanspec); int group, mask; + printk(KERN_INFO "S526 DIO insn_config\n"); + + /* The input or output configuration of each digital line is + * configured by a special insn_config instruction. chanspec + * contains the channel to be changed, and data[0] contains the + * value COMEDI_INPUT or COMEDI_OUTPUT. */ + group = chan >> 2; mask = 0xF << (group << 2); switch (data[0]) { @@ -543,60 +721,88 @@ static int s526_dio_insn_config(struct comedi_device *dev, default: return -EINVAL; } - outw(s->state, dev->iobase + REG_DIO); + outw(s->state, ADDR_REG(REG_DIO)); return 1; } static int s526_attach(struct comedi_device *dev, struct comedi_devconfig *it) { - struct s526_private *devpriv; + const struct s526_board *board = comedi_board(dev); struct comedi_subdevice *s; int iobase; + int i, n; int ret; +/* short value; */ +/* int subdev_channel = 0; */ + union cmReg cmReg; - dev->board_name = dev->driver->driver_name; + printk(KERN_INFO "comedi%d: s526: ", dev->minor); iobase = it->options[0]; - if (!iobase || !request_region(iobase, S526_IOSIZE, dev->board_name)) { + if (!iobase || !request_region(iobase, S526_IOSIZE, board->name)) { comedi_error(dev, "I/O port conflict"); return -EIO; } dev->iobase = iobase; - ret = alloc_private(dev, sizeof(*devpriv)); - if (ret) - return ret; - devpriv = dev->private; + printk("iobase=0x%lx\n", dev->iobase); + + /*** make it a little quieter, exw, 8/29/06 + for (i = 0; i < S526_NUM_PORTS; i++) { + printk("0x%02x: 0x%04x\n", ADDR_REG(s526_ports[i]), + inw(ADDR_REG(s526_ports[i]))); + } + ***/ + + dev->board_name = board->name; + +/* + * Allocate the private structure area. alloc_private() is a + * convenient macro defined in comedidev.h. + */ + if (alloc_private(dev, sizeof(struct s526_private)) < 0) + return -ENOMEM; ret = comedi_alloc_subdevices(dev, 4); if (ret) return ret; - s = &dev->subdevices[0]; + s = dev->subdevices + 0; /* GENERAL-PURPOSE COUNTER/TIME (GPCT) */ s->type = COMEDI_SUBD_COUNTER; s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_LSAMPL; - s->n_chan = 4; + /* KG: What does SDF_LSAMPL (see multiq3.c) mean? */ + s->n_chan = board->gpct_chans; s->maxdata = 0x00ffffff; /* 24 bit counter */ s->insn_read = s526_gpct_rinsn; s->insn_config = s526_gpct_insn_config; s->insn_write = s526_gpct_winsn; - s = &dev->subdevices[1]; + /* Command are not implemented yet, however they are necessary to + allocate the necessary memory for the comedi_async struct (used + to trigger the GPCT in case of pulsegenerator function */ + /* s->do_cmd = s526_gpct_cmd; */ + /* s->do_cmdtest = s526_gpct_cmdtest; */ + /* s->cancel = s526_gpct_cancel; */ + + s = dev->subdevices + 1; + /* dev->read_subdev=s; */ /* analog input subdevice */ s->type = COMEDI_SUBD_AI; + /* we support differential */ s->subdev_flags = SDF_READABLE | SDF_DIFF; /* channels 0 to 7 are the regular differential inputs */ /* channel 8 is "reference 0" (+10V), channel 9 is "reference 1" (0V) */ s->n_chan = 10; s->maxdata = 0xffff; s->range_table = &range_bipolar10; - s->len_chanlist = 16; + s->len_chanlist = 16; /* This is the maximum chanlist length that + the board can handle */ s->insn_read = s526_ai_rinsn; s->insn_config = s526_ai_insn_config; - s = &dev->subdevices[2]; + s = dev->subdevices + 2; /* analog output subdevice */ s->type = COMEDI_SUBD_AO; s->subdev_flags = SDF_WRITABLE; @@ -606,18 +812,105 @@ static int s526_attach(struct comedi_device *dev, struct comedi_devconfig *it) s->insn_write = s526_ao_winsn; s->insn_read = s526_ao_rinsn; - s = &dev->subdevices[3]; + s = dev->subdevices + 3; /* digital i/o subdevice */ - s->type = COMEDI_SUBD_DIO; - s->subdev_flags = SDF_READABLE | SDF_WRITABLE; - s->n_chan = 8; - s->maxdata = 1; - s->range_table = &range_digital; - s->insn_bits = s526_dio_insn_bits; - s->insn_config = s526_dio_insn_config; + if (board->have_dio) { + s->type = COMEDI_SUBD_DIO; + s->subdev_flags = SDF_READABLE | SDF_WRITABLE; + s->n_chan = 8; + s->maxdata = 1; + s->range_table = &range_digital; + s->insn_bits = s526_dio_insn_bits; + s->insn_config = s526_dio_insn_config; + } else { + s->type = COMEDI_SUBD_UNUSED; + } + + printk(KERN_INFO "attached\n"); + + return 1; + +#if 0 + /* Example of Counter Application */ + /* One-shot (software trigger) */ + cmReg.reg.coutSource = 0; /* out RCAP */ + cmReg.reg.coutPolarity = 1; /* Polarity inverted */ + cmReg.reg.autoLoadResetRcap = 1;/* Auto load 0:disabled, 1:enabled */ + cmReg.reg.hwCtEnableSource = 3; /* NOT RCAP */ + cmReg.reg.ctEnableCtrl = 2; /* Hardware */ + cmReg.reg.clockSource = 2; /* Internal */ + cmReg.reg.countDir = 1; /* Down */ + cmReg.reg.countDirCtrl = 1; /* Software */ + cmReg.reg.outputRegLatchCtrl = 0; /* latch on read */ + cmReg.reg.preloadRegSel = 0; /* PR0 */ + cmReg.reg.reserved = 0; + + outw(cmReg.value, ADDR_CHAN_REG(REG_C0M, subdev_channel)); + + outw(0x0001, ADDR_CHAN_REG(REG_C0H, subdev_channel)); + outw(0x3C68, ADDR_CHAN_REG(REG_C0L, subdev_channel)); + + /* Reset the counter */ + outw(0x8000, ADDR_CHAN_REG(REG_C0C, subdev_channel)); + /* Load the counter from PR0 */ + outw(0x4000, ADDR_CHAN_REG(REG_C0C, subdev_channel)); + /* Reset RCAP (fires one-shot) */ + outw(0x0008, ADDR_CHAN_REG(REG_C0C, subdev_channel)); + +#else + + /* Set Counter Mode Register */ + cmReg.reg.coutSource = 0; /* out RCAP */ + cmReg.reg.coutPolarity = 0; /* Polarity inverted */ + cmReg.reg.autoLoadResetRcap = 0; /* Auto load disabled */ + cmReg.reg.hwCtEnableSource = 2; /* NOT RCAP */ + cmReg.reg.ctEnableCtrl = 1; /* 1: Software, >1 : Hardware */ + cmReg.reg.clockSource = 3; /* x4 */ + cmReg.reg.countDir = 0; /* up */ + cmReg.reg.countDirCtrl = 0; /* quadrature */ + cmReg.reg.outputRegLatchCtrl = 0; /* latch on read */ + cmReg.reg.preloadRegSel = 0; /* PR0 */ + cmReg.reg.reserved = 0; + + n = 0; + printk(KERN_INFO "Mode reg=0x%04x, 0x%04lx\n", + cmReg.value, ADDR_CHAN_REG(REG_C0M, n)); + outw(cmReg.value, ADDR_CHAN_REG(REG_C0M, n)); + udelay(1000); + printk(KERN_INFO "Read back mode reg=0x%04x\n", + inw(ADDR_CHAN_REG(REG_C0M, n))); + + /* Load the pre-load register high word */ +/* value = (short) (0x55); */ +/* outw(value, ADDR_CHAN_REG(REG_C0H, n)); */ + + /* Load the pre-load register low word */ +/* value = (short)(0xaa55); */ +/* outw(value, ADDR_CHAN_REG(REG_C0L, n)); */ + + /* Write the Counter Control Register */ +/* outw(value, ADDR_CHAN_REG(REG_C0C, 0)); */ + + /* Reset the counter if it is software preload */ + if (cmReg.reg.autoLoadResetRcap == 0) { + /* Reset the counter */ + outw(0x8000, ADDR_CHAN_REG(REG_C0C, n)); + /* Load the counter from PR0 */ + outw(0x4000, ADDR_CHAN_REG(REG_C0C, n)); + } - dev_info(dev->class_dev, "%s attached\n", dev->board_name); + outw(cmReg.value, ADDR_CHAN_REG(REG_C0M, n)); + udelay(1000); + printk(KERN_INFO "Read back mode reg=0x%04x\n", + inw(ADDR_CHAN_REG(REG_C0M, n))); +#endif + printk(KERN_INFO "Current registres:\n"); + + for (i = 0; i < S526_NUM_PORTS; i++) { + printk(KERN_INFO "0x%02lx: 0x%04x\n", + ADDR_REG(s526_ports[i]), inw(ADDR_REG(s526_ports[i]))); + } return 1; } @@ -632,6 +925,9 @@ static struct comedi_driver s526_driver = { .module = THIS_MODULE, .attach = s526_attach, .detach = s526_detach, + .board_name = &s526_boards[0].name, + .offset = sizeof(struct s526_board), + .num_names = ARRAY_SIZE(s526_boards), }; module_comedi_driver(s526_driver); diff --git a/trunk/drivers/staging/comedi/drivers/s626.c b/trunk/drivers/staging/comedi/drivers/s626.c index 551d68b7837c..f90578e5e727 100644 --- a/trunk/drivers/staging/comedi/drivers/s626.c +++ b/trunk/drivers/staging/comedi/drivers/s626.c @@ -32,7 +32,11 @@ Authors: Gianluca Palli , Updated: Fri, 15 Feb 2008 10:28:42 +0000 Status: experimental -Configuration options: not applicable, uses PCI auto config +Configuration options: + [0] - PCI bus of device (optional) + [1] - PCI slot of device (optional) + If bus/slot is not specified, the first supported + PCI device found will be used. INSN_CONFIG instructions: analog input: @@ -78,8 +82,45 @@ INSN_CONFIG instructions: #define PCI_SUBVENDOR_ID_S626 0x6000 #define PCI_SUBDEVICE_ID_S626 0x0272 +struct s626_board { + const char *name; + int vendor_id; + int device_id; + int subvendor_id; + int subdevice_id; + int ai_chans; + int ai_bits; + int ao_chans; + int ao_bits; + int dio_chans; + int dio_banks; + int enc_chans; +}; + +static const struct s626_board s626_boards[] = { + { + .name = "s626", + .vendor_id = PCI_VENDOR_ID_S626, + .device_id = PCI_DEVICE_ID_S626, + .subvendor_id = PCI_SUBVENDOR_ID_S626, + .subdevice_id = PCI_SUBDEVICE_ID_S626, + .ai_chans = S626_ADC_CHANNELS, + .ai_bits = 14, + .ao_chans = S626_DAC_CHANNELS, + .ao_bits = 13, + .dio_chans = S626_DIO_CHANNELS, + .dio_banks = S626_DIO_BANKS, + .enc_chans = S626_ENCODER_CHANNELS, + } +}; + +#define thisboard ((const struct s626_board *)dev->board_ptr) + struct s626_private { + struct pci_dev *pdev; void __iomem *base_addr; + int got_regions; + short allocatedBuf; uint8_t ai_cmd_running; /* ai_cmd is running */ uint8_t ai_continous; /* continous acquisition */ int ai_sample_count; /* number of samples to acquire */ @@ -98,7 +139,9 @@ struct s626_private { /* Pointer to logical adrs of DMA buffer used to hold DAC data. */ uint16_t Dacpol; /* Image of DAC polarity register. */ uint8_t TrimSetpoint[12]; /* Images of TrimDAC setpoints */ + uint16_t ChargeEnabled; /* Image of MISC2 Battery */ /* Charge Enabled (0 or WRMISC2_CHARGE_ENABLE). */ + uint16_t WDInterval; /* Image of MISC2 watchdog interval control bits. */ uint32_t I2CAdrs; /* I2C device address for onboard EEPROM (board rev dependent). */ /* short I2Cards; */ @@ -1505,28 +1548,56 @@ static int s626_ai_cmdtest(struct comedi_device *dev, int err = 0; int tmp; - /* Step 1 : check if triggers are trivially valid */ + /* cmdtest tests a particular command to see if it is valid. Using + * the cmdtest ioctl, a user can create a valid cmd and then have it + * executes by the cmd ioctl. + * + * cmdtest returns 1,2,3,4 or 0, depending on which tests the + * command passes. */ + + /* step 1: make sure trigger sources are trivially valid */ + + tmp = cmd->start_src; + cmd->start_src &= TRIG_NOW | TRIG_INT | TRIG_EXT; + if (!cmd->start_src || tmp != cmd->start_src) + err++; + + tmp = cmd->scan_begin_src; + cmd->scan_begin_src &= TRIG_TIMER | TRIG_EXT | TRIG_FOLLOW; + if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) + err++; + + tmp = cmd->convert_src; + cmd->convert_src &= TRIG_TIMER | TRIG_EXT | TRIG_NOW; + if (!cmd->convert_src || tmp != cmd->convert_src) + err++; + + tmp = cmd->scan_end_src; + cmd->scan_end_src &= TRIG_COUNT; + if (!cmd->scan_end_src || tmp != cmd->scan_end_src) + err++; - err |= cfc_check_trigger_src(&cmd->start_src, - TRIG_NOW | TRIG_INT | TRIG_EXT); - err |= cfc_check_trigger_src(&cmd->scan_begin_src, - TRIG_TIMER | TRIG_EXT | TRIG_FOLLOW); - err |= cfc_check_trigger_src(&cmd->convert_src, - TRIG_TIMER | TRIG_EXT | TRIG_NOW); - err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT); - err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE); + tmp = cmd->stop_src; + cmd->stop_src &= TRIG_COUNT | TRIG_NONE; + if (!cmd->stop_src || tmp != cmd->stop_src) + err++; if (err) return 1; - /* Step 2a : make sure trigger sources are unique */ - - err |= cfc_check_trigger_is_unique(cmd->start_src); - err |= cfc_check_trigger_is_unique(cmd->scan_begin_src); - err |= cfc_check_trigger_is_unique(cmd->convert_src); - err |= cfc_check_trigger_is_unique(cmd->stop_src); + /* step 2: make sure trigger sources are unique and mutually + compatible */ - /* Step 2b : and mutually compatible */ + /* note that mutual compatibility is not an issue here */ + if (cmd->scan_begin_src != TRIG_TIMER && + cmd->scan_begin_src != TRIG_EXT + && cmd->scan_begin_src != TRIG_FOLLOW) + err++; + if (cmd->convert_src != TRIG_TIMER && + cmd->convert_src != TRIG_EXT && cmd->convert_src != TRIG_NOW) + err++; + if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE) + err++; if (err) return 2; @@ -1776,9 +1847,6 @@ static int s626_dio_insn_config(struct comedi_device *dev, /* Now this function initializes the value of the counter (data[0]) and set the subdevice. To complete with trigger and interrupt configuration */ -/* FIXME: data[0] is supposed to be an INSN_CONFIG_xxx constant indicating - * what is being configured, but this function appears to be using data[0] - * as a variable. */ static int s626_enc_insn_config(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) @@ -1800,7 +1868,7 @@ static int s626_enc_insn_config(struct comedi_device *dev, /* (data==NULL) ? (Preloadvalue=0) : (Preloadvalue=data[0]); */ k->SetMode(dev, k, Setup, TRUE); - Preload(dev, k, data[0]); + Preload(dev, k, *(insn->data)); k->PulseIndex(dev, k); SetLatchSource(dev, k, valueSrclatch); k->SetEnable(dev, k, (uint16_t) (enab != 0)); @@ -1852,7 +1920,6 @@ static void WriteMISC2(struct comedi_device *dev, uint16_t NewImage) static void CloseDMAB(struct comedi_device *dev, struct bufferDMA *pdma, size_t bsize) { - struct pci_dev *pcidev = comedi_to_pci_dev(dev); void *vbptr; dma_addr_t vpptr; @@ -1863,7 +1930,7 @@ static void CloseDMAB(struct comedi_device *dev, struct bufferDMA *pdma, vbptr = pdma->LogicalBase; vpptr = pdma->PhysicalBase; if (vbptr) { - pci_free_consistent(pcidev, bsize, vbptr, vpptr); + pci_free_consistent(devpriv->pdev, bsize, vbptr, vpptr); pdma->LogicalBase = NULL; pdma->PhysicalBase = 0; } @@ -2409,317 +2476,146 @@ static void CountersInit(struct comedi_device *dev) } } -static int s626_allocate_dma_buffers(struct comedi_device *dev) +static struct pci_dev *s626_find_pci(struct comedi_device *dev, + struct comedi_devconfig *it) { - struct pci_dev *pcidev = comedi_to_pci_dev(dev); - void *addr; - dma_addr_t appdma; - - addr = pci_alloc_consistent(pcidev, DMABUF_SIZE, &appdma); - if (!addr) - return -ENOMEM; - devpriv->ANABuf.LogicalBase = addr; - devpriv->ANABuf.PhysicalBase = appdma; - - addr = pci_alloc_consistent(pcidev, DMABUF_SIZE, &appdma); - if (!addr) - return -ENOMEM; - devpriv->RPSBuf.LogicalBase = addr; - devpriv->RPSBuf.PhysicalBase = appdma; + struct pci_dev *pcidev = NULL; + int bus = it->options[0]; + int slot = it->options[1]; + int i; - return 0; + for (i = 0; i < ARRAY_SIZE(s626_boards) && !pcidev; i++) { + do { + pcidev = pci_get_subsys(s626_boards[i].vendor_id, + s626_boards[i].device_id, + s626_boards[i].subvendor_id, + s626_boards[i].subdevice_id, + pcidev); + + if ((bus || slot) && pcidev) { + /* matches requested bus/slot */ + if (pcidev->bus->number == bus && + PCI_SLOT(pcidev->devfn) == slot) + break; + } else { + break; + } + } while (1); + } + return pcidev; } -static void s626_initialize(struct comedi_device *dev) +static int s626_attach(struct comedi_device *dev, struct comedi_devconfig *it) { - dma_addr_t pPhysBuf; - uint16_t chan; +/* uint8_t PollList; */ +/* uint16_t AdcData; */ +/* uint16_t StartVal; */ +/* uint16_t index; */ +/* unsigned int data[16]; */ + int result; int i; + int ret; + resource_size_t resourceStart; + dma_addr_t appdma; + struct comedi_subdevice *s; - /* Enable DEBI and audio pins, enable I2C interface */ - MC_ENABLE(P_MC1, MC1_DEBI | MC1_AUDIO | MC1_I2C); - - /* - * Configure DEBI operating mode - * - * Local bus is 16 bits wide - * Declare DEBI transfer timeout interval - * Set up byte lane steering - * Intel-compatible local bus (DEBI never times out) - */ - WR7146(P_DEBICFG, DEBI_CFG_SLAVE16 | - (DEBI_TOUT << DEBI_CFG_TOUT_BIT) | - DEBI_SWAP | DEBI_CFG_INTEL); - - /* Disable MMU paging */ - WR7146(P_DEBIPAGE, DEBI_PAGE_DISABLE); - - /* Init GPIO so that ADC Start* is negated */ - WR7146(P_GPIO, GPIO_BASE | GPIO1_HI); - - /* I2C device address for onboard eeprom (revb) */ - devpriv->I2CAdrs = 0xA0; - - /* - * Issue an I2C ABORT command to halt any I2C - * operation in progress and reset BUSY flag. - */ - WR7146(P_I2CSTAT, I2C_CLKSEL | I2C_ABORT); - MC_ENABLE(P_MC2, MC2_UPLD_IIC); - while ((RR7146(P_MC2) & MC2_UPLD_IIC) == 0) - ; - - /* - * Per SAA7146 data sheet, write to STATUS - * reg twice to reset all I2C error flags. - */ - for (i = 0; i < 2; i++) { - WR7146(P_I2CSTAT, I2C_CLKSEL); - MC_ENABLE(P_MC2, MC2_UPLD_IIC); - while (!MC_TEST(P_MC2, MC2_UPLD_IIC)) - ; - } - - /* - * Init audio interface functional attributes: set DAC/ADC - * serial clock rates, invert DAC serial clock so that - * DAC data setup times are satisfied, enable DAC serial - * clock out. - */ - WR7146(P_ACON2, ACON2_INIT); - - /* - * Set up TSL1 slot list, which is used to control the - * accumulation of ADC data: RSD1 = shift data in on SD1. - * SIB_A1 = store data uint8_t at next available location - * in FB BUFFER1 register. - */ - WR7146(P_TSL1, RSD1 | SIB_A1); - WR7146(P_TSL1 + 4, RSD1 | SIB_A1 | EOS); - - /* Enable TSL1 slot list so that it executes all the time */ - WR7146(P_ACON1, ACON1_ADCSTART); - - /* - * Initialize RPS registers used for ADC - */ - - /* Physical start of RPS program */ - WR7146(P_RPSADDR1, (uint32_t)devpriv->RPSBuf.PhysicalBase); - /* RPS program performs no explicit mem writes */ - WR7146(P_RPSPAGE1, 0); - /* Disable RPS timeouts */ - WR7146(P_RPS1_TOUT, 0); - -#if 0 - /* - * SAA7146 BUG WORKAROUND - * - * Initialize SAA7146 ADC interface to a known state by - * invoking ADCs until FB BUFFER 1 register shows that it - * is correctly receiving ADC data. This is necessary - * because the SAA7146 ADC interface does not start up in - * a defined state after a PCI reset. - */ - - { - uint8_t PollList; - uint16_t AdcData; - uint16_t StartVal; - uint16_t index; - unsigned int data[16]; - - /* Create a simple polling list for analog input channel 0 */ - PollList = EOPL; - ResetADC(dev, &PollList); - - /* Get initial ADC value */ - s626_ai_rinsn(dev, dev->subdevices, NULL, data); - StartVal = data[0]; + if (alloc_private(dev, sizeof(struct s626_private)) < 0) + return -ENOMEM; - /* - * VERSION 2.01 CHANGE: TIMEOUT ADDED TO PREVENT HANGED EXECUTION. - * - * Invoke ADCs until the new ADC value differs from the initial - * value or a timeout occurs. The timeout protects against the - * possibility that the driver is restarting and the ADC data is a - * fixed value resulting from the applied ADC analog input being - * unusually quiet or at the rail. - */ - for (index = 0; index < 500; index++) { - s626_ai_rinsn(dev, dev->subdevices, NULL, data); - AdcData = data[0]; - if (AdcData != StartVal) - break; + devpriv->pdev = s626_find_pci(dev, it); + if (!devpriv->pdev) { + printk(KERN_ERR "s626_attach: Board not present!!!\n"); + return -ENODEV; } + result = comedi_pci_enable(devpriv->pdev, "s626"); + if (result < 0) { + printk(KERN_ERR "s626_attach: comedi_pci_enable fails\n"); + return -ENODEV; } -#endif /* SAA7146 BUG WORKAROUND */ - - /* - * Initialize the DAC interface - */ + devpriv->got_regions = 1; - /* - * Init Audio2's output DMAC attributes: - * burst length = 1 DWORD - * threshold = 1 DWORD. - */ - WR7146(P_PCI_BT_A, 0); + resourceStart = pci_resource_start(devpriv->pdev, 0); - /* - * Init Audio2's output DMA physical addresses. The protection - * address is set to 1 DWORD past the base address so that a - * single DWORD will be transferred each time a DMA transfer is - * enabled. - */ - pPhysBuf = devpriv->ANABuf.PhysicalBase + - (DAC_WDMABUF_OS * sizeof(uint32_t)); - WR7146(P_BASEA2_OUT, (uint32_t) pPhysBuf); - WR7146(P_PROTA2_OUT, (uint32_t) (pPhysBuf + sizeof(uint32_t))); - - /* - * Cache Audio2's output DMA buffer logical address. This is - * where DAC data is buffered for A2 output DMA transfers. - */ - devpriv->pDacWBuf = (uint32_t *)devpriv->ANABuf.LogicalBase + - DAC_WDMABUF_OS; - - /* - * Audio2's output channels does not use paging. The - * protection violation handling bit is set so that the - * DMAC will automatically halt and its PCI address pointer - * will be reset when the protection address is reached. - */ - WR7146(P_PAGEA2_OUT, 8); - - /* - * Initialize time slot list 2 (TSL2), which is used to control - * the clock generation for and serialization of data to be sent - * to the DAC devices. Slot 0 is a NOP that is used to trap TSL - * execution; this permits other slots to be safely modified - * without first turning off the TSL sequencer (which is - * apparently impossible to do). Also, SD3 (which is driven by a - * pull-up resistor) is shifted in and stored to the MSB of - * FB_BUFFER2 to be used as evidence that the slot sequence has - * not yet finished executing. - */ + devpriv->base_addr = ioremap(resourceStart, SIZEOF_ADDRESS_SPACE); + if (devpriv->base_addr == NULL) { + printk(KERN_ERR "s626_attach: IOREMAP failed\n"); + return -ENODEV; + } - /* Slot 0: Trap TSL execution, shift 0xFF into FB_BUFFER2 */ - SETVECT(0, XSD2 | RSD3 | SIB_A2 | EOS); + if (devpriv->base_addr) { + /* disable master interrupt */ + writel(0, devpriv->base_addr + P_IER); - /* - * Initialize slot 1, which is constant. Slot 1 causes a - * DWORD to be transferred from audio channel 2's output FIFO - * to the FIFO's output buffer so that it can be serialized - * and sent to the DAC during subsequent slots. All remaining - * slots are dynamically populated as required by the target - * DAC device. - */ + /* soft reset */ + writel(MC1_SOFT_RESET, devpriv->base_addr + P_MC1); - /* Slot 1: Fetch DWORD from Audio2's output FIFO */ - SETVECT(1, LF_A2); + /* DMA FIXME DMA// */ - /* Start DAC's audio interface (TSL2) running */ - WR7146(P_ACON1, ACON1_DACSTART); + /* adc buffer allocation */ + devpriv->allocatedBuf = 0; - /* - * Init Trim DACs to calibrated values. Do it twice because the - * SAA7146 audio channel does not always reset properly and - * sometimes causes the first few TrimDAC writes to malfunction. - */ - LoadTrimDACs(dev); - LoadTrimDACs(dev); + devpriv->ANABuf.LogicalBase = + pci_alloc_consistent(devpriv->pdev, DMABUF_SIZE, &appdma); - /* - * Manually init all gate array hardware in case this is a soft - * reset (we have no way of determining whether this is a warm - * or cold start). This is necessary because the gate array will - * reset only in response to a PCI hard reset; there is no soft - * reset function. - */ + if (devpriv->ANABuf.LogicalBase == NULL) { + printk(KERN_ERR "s626_attach: DMA Memory mapping error\n"); + return -ENOMEM; + } - /* - * Init all DAC outputs to 0V and init all DAC setpoint and - * polarity images. - */ - for (chan = 0; chan < S626_DAC_CHANNELS; chan++) - SetDAC(dev, chan, 0); + devpriv->ANABuf.PhysicalBase = appdma; - /* Init counters */ - CountersInit(dev); + devpriv->allocatedBuf++; - /* - * Without modifying the state of the Battery Backup enab, disable - * the watchdog timer, set DIO channels 0-5 to operate in the - * standard DIO (vs. counter overflow) mode, disable the battery - * charger, and reset the watchdog interval selector to zero. - */ - WriteMISC2(dev, (uint16_t)(DEBIread(dev, LP_RDMISC2) & - MISC2_BATT_ENABLE)); + devpriv->RPSBuf.LogicalBase = + pci_alloc_consistent(devpriv->pdev, DMABUF_SIZE, &appdma); - /* Initialize the digital I/O subsystem */ - s626_dio_init(dev); + if (devpriv->RPSBuf.LogicalBase == NULL) { + printk(KERN_ERR "s626_attach: DMA Memory mapping error\n"); + return -ENOMEM; + } - /* enable interrupt test */ - /* writel(IRQ_GPIO3 | IRQ_RPS1, devpriv->base_addr + P_IER); */ -} + devpriv->RPSBuf.PhysicalBase = appdma; -static int s626_attach_pci(struct comedi_device *dev, struct pci_dev *pcidev) -{ - struct comedi_subdevice *s; - int ret; + devpriv->allocatedBuf++; - comedi_set_hw_dev(dev, &pcidev->dev); - dev->board_name = dev->driver->driver_name; + } - if (alloc_private(dev, sizeof(struct s626_private)) < 0) - return -ENOMEM; + dev->board_ptr = s626_boards; + dev->board_name = thisboard->name; - ret = comedi_pci_enable(pcidev, dev->board_name); + ret = comedi_alloc_subdevices(dev, 6); if (ret) return ret; - dev->iobase = 1; /* detach needs this */ - devpriv->base_addr = ioremap(pci_resource_start(pcidev, 0), - pci_resource_len(pcidev, 0)); - if (!devpriv->base_addr) - return -ENOMEM; + dev->iobase = (unsigned long)devpriv->base_addr; + dev->irq = devpriv->pdev->irq; - /* disable master interrupt */ - writel(0, devpriv->base_addr + P_IER); - - /* soft reset */ - writel(MC1_SOFT_RESET, devpriv->base_addr + P_MC1); - - /* DMA FIXME DMA// */ - - ret = s626_allocate_dma_buffers(dev); - if (ret) - return ret; - - if (pcidev->irq) { - ret = request_irq(pcidev->irq, s626_irq_handler, IRQF_SHARED, - dev->board_name, dev); + /* set up interrupt handler */ + if (dev->irq == 0) { + printk(KERN_ERR " unknown irq (bad)\n"); + } else { + ret = request_irq(dev->irq, s626_irq_handler, IRQF_SHARED, + "s626", dev); - if (ret == 0) - dev->irq = pcidev->irq; + if (ret < 0) { + printk(KERN_ERR " irq not available\n"); + dev->irq = 0; + } } - ret = comedi_alloc_subdevices(dev, 6); - if (ret) - return ret; - s = dev->subdevices + 0; /* analog input subdevice */ dev->read_subdev = s; /* we support single-ended (ground) and differential */ s->type = COMEDI_SUBD_AI; s->subdev_flags = SDF_READABLE | SDF_DIFF | SDF_CMD_READ; - s->n_chan = S626_ADC_CHANNELS; + s->n_chan = thisboard->ai_chans; s->maxdata = (0xffff >> 2); s->range_table = &s626_range_table; - s->len_chanlist = S626_ADC_CHANNELS; + s->len_chanlist = thisboard->ai_chans; /* This is the maximum chanlist + length that the board can + handle */ s->insn_config = s626_ai_insn_config; s->insn_read = s626_ai_insn_read; s->do_cmd = s626_ai_cmd; @@ -2730,7 +2626,7 @@ static int s626_attach_pci(struct comedi_device *dev, struct pci_dev *pcidev) /* analog output subdevice */ s->type = COMEDI_SUBD_AO; s->subdev_flags = SDF_WRITABLE | SDF_READABLE; - s->n_chan = S626_DAC_CHANNELS; + s->n_chan = thisboard->ao_chans; s->maxdata = (0x3fff); s->range_table = &range_bipolar10; s->insn_write = s626_ao_winsn; @@ -2776,7 +2672,7 @@ static int s626_attach_pci(struct comedi_device *dev, struct pci_dev *pcidev) /* encoder (counter) subdevice */ s->type = COMEDI_SUBD_COUNTER; s->subdev_flags = SDF_WRITABLE | SDF_READABLE | SDF_LSAMPL; - s->n_chan = S626_ENCODER_CHANNELS; + s->n_chan = thisboard->enc_chans; s->private = enc_private_data; s->insn_config = s626_enc_insn_config; s->insn_read = s626_enc_insn_read; @@ -2784,17 +2680,269 @@ static int s626_attach_pci(struct comedi_device *dev, struct pci_dev *pcidev) s->maxdata = 0xffffff; s->range_table = &range_unknown; - s626_initialize(dev); + /* stop ai_command */ + devpriv->ai_cmd_running = 0; + + if (devpriv->base_addr && (devpriv->allocatedBuf == 2)) { + dma_addr_t pPhysBuf; + uint16_t chan; + + /* enab DEBI and audio pins, enable I2C interface. */ + MC_ENABLE(P_MC1, MC1_DEBI | MC1_AUDIO | MC1_I2C); + /* Configure DEBI operating mode. */ + WR7146(P_DEBICFG, DEBI_CFG_SLAVE16 /* Local bus is 16 */ + /* bits wide. */ + | (DEBI_TOUT << DEBI_CFG_TOUT_BIT) + + /* Declare DEBI */ + /* transfer timeout */ + /* interval. */ + |DEBI_SWAP /* Set up byte lane */ + /* steering. */ + | DEBI_CFG_INTEL); /* Intel-compatible */ + /* local bus (DEBI */ + /* never times out). */ + + /* DEBI INIT S626 WR7146( P_DEBICFG, DEBI_CFG_INTEL | DEBI_CFG_TOQ */ + /* | DEBI_CFG_INCQ| DEBI_CFG_16Q); //end */ + + /* Paging is disabled. */ + WR7146(P_DEBIPAGE, DEBI_PAGE_DISABLE); /* Disable MMU paging. */ + + /* Init GPIO so that ADC Start* is negated. */ + WR7146(P_GPIO, GPIO_BASE | GPIO1_HI); + + /* IsBoardRevA is a boolean that indicates whether the board is RevA. + * + * VERSION 2.01 CHANGE: REV A & B BOARDS NOW SUPPORTED BY DYNAMIC + * EEPROM ADDRESS SELECTION. Initialize the I2C interface, which + * is used to access the onboard serial EEPROM. The EEPROM's I2C + * DeviceAddress is hardwired to a value that is dependent on the + * 626 board revision. On all board revisions, the EEPROM stores + * TrimDAC calibration constants for analog I/O. On RevB and + * higher boards, the DeviceAddress is hardwired to 0 to enable + * the EEPROM to also store the PCI SubVendorID and SubDeviceID; + * this is the address at which the SAA7146 expects a + * configuration EEPROM to reside. On RevA boards, the EEPROM + * device address, which is hardwired to 4, prevents the SAA7146 + * from retrieving PCI sub-IDs, so the SAA7146 uses its built-in + * default values, instead. + */ - dev_info(dev->class_dev, "%s attached\n", dev->board_name); + /* devpriv->I2Cards= IsBoardRevA ? 0xA8 : 0xA0; // Set I2C EEPROM */ + /* DeviceType (0xA0) */ + /* and DeviceAddress<<1. */ - return 0; + devpriv->I2CAdrs = 0xA0; /* I2C device address for onboard */ + /* eeprom(revb) */ + + /* Issue an I2C ABORT command to halt any I2C operation in */ + /* progress and reset BUSY flag. */ + WR7146(P_I2CSTAT, I2C_CLKSEL | I2C_ABORT); + /* Write I2C control: abort any I2C activity. */ + MC_ENABLE(P_MC2, MC2_UPLD_IIC); + /* Invoke command upload */ + while ((RR7146(P_MC2) & MC2_UPLD_IIC) == 0) + ; + /* and wait for upload to complete. */ + + /* Per SAA7146 data sheet, write to STATUS reg twice to + * reset all I2C error flags. */ + for (i = 0; i < 2; i++) { + WR7146(P_I2CSTAT, I2C_CLKSEL); + /* Write I2C control: reset error flags. */ + MC_ENABLE(P_MC2, MC2_UPLD_IIC); /* Invoke command upload */ + while (!MC_TEST(P_MC2, MC2_UPLD_IIC)) + ; + /* and wait for upload to complete. */ + } + + /* Init audio interface functional attributes: set DAC/ADC + * serial clock rates, invert DAC serial clock so that + * DAC data setup times are satisfied, enable DAC serial + * clock out. + */ + + WR7146(P_ACON2, ACON2_INIT); + + /* Set up TSL1 slot list, which is used to control the + * accumulation of ADC data: RSD1 = shift data in on SD1. + * SIB_A1 = store data uint8_t at next available location in + * FB BUFFER1 register. */ + WR7146(P_TSL1, RSD1 | SIB_A1); + /* Fetch ADC high data uint8_t. */ + WR7146(P_TSL1 + 4, RSD1 | SIB_A1 | EOS); + /* Fetch ADC low data uint8_t; end of TSL1. */ + + /* enab TSL1 slot list so that it executes all the time. */ + WR7146(P_ACON1, ACON1_ADCSTART); + + /* Initialize RPS registers used for ADC. */ + + /* Physical start of RPS program. */ + WR7146(P_RPSADDR1, (uint32_t) devpriv->RPSBuf.PhysicalBase); + + WR7146(P_RPSPAGE1, 0); + /* RPS program performs no explicit mem writes. */ + WR7146(P_RPS1_TOUT, 0); /* Disable RPS timeouts. */ + + /* SAA7146 BUG WORKAROUND. Initialize SAA7146 ADC interface + * to a known state by invoking ADCs until FB BUFFER 1 + * register shows that it is correctly receiving ADC data. + * This is necessary because the SAA7146 ADC interface does + * not start up in a defined state after a PCI reset. + */ + +/* PollList = EOPL; // Create a simple polling */ +/* // list for analog input */ +/* // channel 0. */ +/* ResetADC( dev, &PollList ); */ + +/* s626_ai_rinsn(dev,dev->subdevices,NULL,data); //( &AdcData ); // */ +/* //Get initial ADC */ +/* //value. */ + +/* StartVal = data[0]; */ + +/* // VERSION 2.01 CHANGE: TIMEOUT ADDED TO PREVENT HANGED EXECUTION. */ +/* // Invoke ADCs until the new ADC value differs from the initial */ +/* // value or a timeout occurs. The timeout protects against the */ +/* // possibility that the driver is restarting and the ADC data is a */ +/* // fixed value resulting from the applied ADC analog input being */ +/* // unusually quiet or at the rail. */ + +/* for ( index = 0; index < 500; index++ ) */ +/* { */ +/* s626_ai_rinsn(dev,dev->subdevices,NULL,data); */ +/* AdcData = data[0]; //ReadADC( &AdcData ); */ +/* if ( AdcData != StartVal ) */ +/* break; */ +/* } */ + + /* end initADC */ + + /* init the DAC interface */ + + /* Init Audio2's output DMAC attributes: burst length = 1 + * DWORD, threshold = 1 DWORD. + */ + WR7146(P_PCI_BT_A, 0); + + /* Init Audio2's output DMA physical addresses. The protection + * address is set to 1 DWORD past the base address so that a + * single DWORD will be transferred each time a DMA transfer is + * enabled. */ + + pPhysBuf = + devpriv->ANABuf.PhysicalBase + + (DAC_WDMABUF_OS * sizeof(uint32_t)); + + WR7146(P_BASEA2_OUT, (uint32_t) pPhysBuf); /* Buffer base adrs. */ + WR7146(P_PROTA2_OUT, (uint32_t) (pPhysBuf + sizeof(uint32_t))); /* Protection address. */ + + /* Cache Audio2's output DMA buffer logical address. This is + * where DAC data is buffered for A2 output DMA transfers. */ + devpriv->pDacWBuf = + (uint32_t *) devpriv->ANABuf.LogicalBase + DAC_WDMABUF_OS; + + /* Audio2's output channels does not use paging. The protection + * violation handling bit is set so that the DMAC will + * automatically halt and its PCI address pointer will be reset + * when the protection address is reached. */ + + WR7146(P_PAGEA2_OUT, 8); + + /* Initialize time slot list 2 (TSL2), which is used to control + * the clock generation for and serialization of data to be sent + * to the DAC devices. Slot 0 is a NOP that is used to trap TSL + * execution; this permits other slots to be safely modified + * without first turning off the TSL sequencer (which is + * apparently impossible to do). Also, SD3 (which is driven by a + * pull-up resistor) is shifted in and stored to the MSB of + * FB_BUFFER2 to be used as evidence that the slot sequence has + * not yet finished executing. + */ + + SETVECT(0, XSD2 | RSD3 | SIB_A2 | EOS); + /* Slot 0: Trap TSL execution, shift 0xFF into FB_BUFFER2. */ + + /* Initialize slot 1, which is constant. Slot 1 causes a + * DWORD to be transferred from audio channel 2's output FIFO + * to the FIFO's output buffer so that it can be serialized + * and sent to the DAC during subsequent slots. All remaining + * slots are dynamically populated as required by the target + * DAC device. + */ + SETVECT(1, LF_A2); + /* Slot 1: Fetch DWORD from Audio2's output FIFO. */ + + /* Start DAC's audio interface (TSL2) running. */ + WR7146(P_ACON1, ACON1_DACSTART); + + /* end init DAC interface */ + + /* Init Trim DACs to calibrated values. Do it twice because the + * SAA7146 audio channel does not always reset properly and + * sometimes causes the first few TrimDAC writes to malfunction. + */ + + LoadTrimDACs(dev); + LoadTrimDACs(dev); /* Insurance. */ + + /* Manually init all gate array hardware in case this is a soft + * reset (we have no way of determining whether this is a warm + * or cold start). This is necessary because the gate array will + * reset only in response to a PCI hard reset; there is no soft + * reset function. */ + + /* Init all DAC outputs to 0V and init all DAC setpoint and + * polarity images. + */ + for (chan = 0; chan < S626_DAC_CHANNELS; chan++) + SetDAC(dev, chan, 0); + + /* Init image of WRMISC2 Battery Charger Enabled control bit. + * This image is used when the state of the charger control bit, + * which has no direct hardware readback mechanism, is queried. + */ + devpriv->ChargeEnabled = 0; + + /* Init image of watchdog timer interval in WRMISC2. This image + * maintains the value of the control bits of MISC2 are + * continuously reset to zero as long as the WD timer is disabled. + */ + devpriv->WDInterval = 0; + + /* Init Counter Interrupt enab mask for RDMISC2. This mask is + * applied against MISC2 when testing to determine which timer + * events are requesting interrupt service. + */ + devpriv->CounterIntEnabs = 0; + + /* Init counters. */ + CountersInit(dev); + + /* Without modifying the state of the Battery Backup enab, disable + * the watchdog timer, set DIO channels 0-5 to operate in the + * standard DIO (vs. counter overflow) mode, disable the battery + * charger, and reset the watchdog interval selector to zero. + */ + WriteMISC2(dev, (uint16_t) (DEBIread(dev, + LP_RDMISC2) & + MISC2_BATT_ENABLE)); + + /* Initialize the digital I/O subsystem. */ + s626_dio_init(dev); + + /* enable interrupt test */ + /* writel(IRQ_GPIO3 | IRQ_RPS1,devpriv->base_addr+P_IER); */ + } + + return 1; } static void s626_detach(struct comedi_device *dev) { - struct pci_dev *pcidev = comedi_to_pci_dev(dev); - if (devpriv) { /* stop ai_command */ devpriv->ai_cmd_running = 0; @@ -2819,17 +2967,18 @@ static void s626_detach(struct comedi_device *dev) free_irq(dev->irq, dev); if (devpriv->base_addr) iounmap(devpriv->base_addr); - } - if (pcidev) { - if (dev->iobase) - comedi_pci_disable(pcidev); + if (devpriv->pdev) { + if (devpriv->got_regions) + comedi_pci_disable(devpriv->pdev); + pci_dev_put(devpriv->pdev); + } } } static struct comedi_driver s626_driver = { .driver_name = "s626", .module = THIS_MODULE, - .attach_pci = s626_attach_pci, + .attach = s626_attach, .detach = s626_detach, }; diff --git a/trunk/drivers/staging/comedi/drivers/s626.h b/trunk/drivers/staging/comedi/drivers/s626.h index ff4b3a5e4e5f..8a8f196cf153 100644 --- a/trunk/drivers/staging/comedi/drivers/s626.h +++ b/trunk/drivers/staging/comedi/drivers/s626.h @@ -73,6 +73,7 @@ #include #define S626_SIZE 0x0200 +#define SIZEOF_ADDRESS_SPACE 0x0200 #define DMABUF_SIZE 4096 /* 4k pages */ #define S626_ADC_CHANNELS 16 diff --git a/trunk/drivers/staging/comedi/drivers/serial2002.c b/trunk/drivers/staging/comedi/drivers/serial2002.c index 5bf84cfbdceb..c18314be8c82 100644 --- a/trunk/drivers/staging/comedi/drivers/serial2002.c +++ b/trunk/drivers/staging/comedi/drivers/serial2002.c @@ -588,9 +588,7 @@ static int serial_2002_open(struct comedi_device *dev) kfree(s->range_table_list); s->range_table = NULL; s->range_table_list = NULL; - if (kind == 1 || kind == 2) { - s->range_table = &range_digital; - } else if (range) { + if (range) { s->range_table_list = range_table_list = kmalloc(sizeof (struct @@ -800,7 +798,7 @@ static int serial2002_attach(struct comedi_device *dev, return ret; /* digital input subdevice */ - s = &dev->subdevices[0]; + s = dev->subdevices + 0; s->type = COMEDI_SUBD_DI; s->subdev_flags = SDF_READABLE; s->n_chan = 0; @@ -809,7 +807,7 @@ static int serial2002_attach(struct comedi_device *dev, s->insn_read = &serial2002_di_rinsn; /* digital output subdevice */ - s = &dev->subdevices[1]; + s = dev->subdevices + 1; s->type = COMEDI_SUBD_DO; s->subdev_flags = SDF_WRITEABLE; s->n_chan = 0; @@ -818,7 +816,7 @@ static int serial2002_attach(struct comedi_device *dev, s->insn_write = &serial2002_do_winsn; /* analog input subdevice */ - s = &dev->subdevices[2]; + s = dev->subdevices + 2; s->type = COMEDI_SUBD_AI; s->subdev_flags = SDF_READABLE | SDF_GROUND; s->n_chan = 0; @@ -827,7 +825,7 @@ static int serial2002_attach(struct comedi_device *dev, s->insn_read = &serial2002_ai_rinsn; /* analog output subdevice */ - s = &dev->subdevices[3]; + s = dev->subdevices + 3; s->type = COMEDI_SUBD_AO; s->subdev_flags = SDF_WRITEABLE; s->n_chan = 0; @@ -837,7 +835,7 @@ static int serial2002_attach(struct comedi_device *dev, s->insn_read = &serial2002_ao_rinsn; /* encoder input subdevice */ - s = &dev->subdevices[4]; + s = dev->subdevices + 4; s->type = COMEDI_SUBD_COUNTER; s->subdev_flags = SDF_READABLE | SDF_LSAMPL; s->n_chan = 0; diff --git a/trunk/drivers/staging/comedi/drivers/skel.c b/trunk/drivers/staging/comedi/drivers/skel.c index b70cdf300bbd..9a68eebefca0 100644 --- a/trunk/drivers/staging/comedi/drivers/skel.c +++ b/trunk/drivers/staging/comedi/drivers/skel.c @@ -76,8 +76,6 @@ Configuration Options: #include /* for PCI devices */ -#include "comedi_fc.h" - /* Imaginary registers for the imaginary board */ #define SKEL_SIZE 0 @@ -240,7 +238,7 @@ static int skel_attach(struct comedi_device *dev, struct comedi_devconfig *it) if (ret) return ret; - s = &dev->subdevices[0]; + s = dev->subdevices + 0; /* dev->read_subdev=s; */ /* analog input subdevice */ s->type = COMEDI_SUBD_AI; @@ -258,7 +256,7 @@ static int skel_attach(struct comedi_device *dev, struct comedi_devconfig *it) */ s->do_cmdtest = skel_ai_cmdtest; - s = &dev->subdevices[1]; + s = dev->subdevices + 1; /* analog output subdevice */ s->type = COMEDI_SUBD_AO; s->subdev_flags = SDF_WRITABLE; @@ -268,7 +266,7 @@ static int skel_attach(struct comedi_device *dev, struct comedi_devconfig *it) s->insn_write = skel_ao_winsn; s->insn_read = skel_ao_rinsn; - s = &dev->subdevices[2]; + s = dev->subdevices + 2; /* digital i/o subdevice */ if (thisboard->have_dio) { s->type = COMEDI_SUBD_DIO; @@ -351,40 +349,60 @@ static int skel_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, return n; } -/* - * cmdtest tests a particular command to see if it is valid. - * Using the cmdtest ioctl, a user can create a valid cmd - * and then have it executes by the cmd ioctl. - * - * cmdtest returns 1,2,3,4 or 0, depending on which tests - * the command passes. - */ static int skel_ai_cmdtest(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_cmd *cmd) + struct comedi_subdevice *s, struct comedi_cmd *cmd) { int err = 0; int tmp; - /* Step 1 : check if triggers are trivially valid */ + /* cmdtest tests a particular command to see if it is valid. + * Using the cmdtest ioctl, a user can create a valid cmd + * and then have it executes by the cmd ioctl. + * + * cmdtest returns 1,2,3,4 or 0, depending on which tests + * the command passes. */ + + /* step 1: make sure trigger sources are trivially valid */ - err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW); - err |= cfc_check_trigger_src(&cmd->scan_begin_src, - TRIG_TIMER | TRIG_EXT); - err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_TIMER | TRIG_EXT); - err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT); - err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE); + tmp = cmd->start_src; + cmd->start_src &= TRIG_NOW; + if (!cmd->start_src || tmp != cmd->start_src) + err++; + + tmp = cmd->scan_begin_src; + cmd->scan_begin_src &= TRIG_TIMER | TRIG_EXT; + if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) + err++; + + tmp = cmd->convert_src; + cmd->convert_src &= TRIG_TIMER | TRIG_EXT; + if (!cmd->convert_src || tmp != cmd->convert_src) + err++; + + tmp = cmd->scan_end_src; + cmd->scan_end_src &= TRIG_COUNT; + if (!cmd->scan_end_src || tmp != cmd->scan_end_src) + err++; + + tmp = cmd->stop_src; + cmd->stop_src &= TRIG_COUNT | TRIG_NONE; + if (!cmd->stop_src || tmp != cmd->stop_src) + err++; if (err) return 1; - /* Step 2a : make sure trigger sources are unique */ + /* step 2: make sure trigger sources are unique and mutually compatible + */ - err |= cfc_check_trigger_is_unique(cmd->scan_begin_src); - err |= cfc_check_trigger_is_unique(cmd->convert_src); - err |= cfc_check_trigger_is_unique(cmd->stop_src); - - /* Step 2b : and mutually compatible */ + /* note that mutual compatibility is not an issue here */ + if (cmd->scan_begin_src != TRIG_TIMER && + cmd->scan_begin_src != TRIG_EXT) + err++; + if (cmd->convert_src != TRIG_TIMER && cmd->convert_src != TRIG_EXT) + err++; + if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE) + err++; if (err) return 2; diff --git a/trunk/drivers/staging/comedi/drivers/ssv_dnp.c b/trunk/drivers/staging/comedi/drivers/ssv_dnp.c index ae3aa1c5caef..84b9f2a4280b 100644 --- a/trunk/drivers/staging/comedi/drivers/ssv_dnp.c +++ b/trunk/drivers/staging/comedi/drivers/ssv_dnp.c @@ -177,13 +177,15 @@ static int dnp_attach(struct comedi_device *dev, struct comedi_devconfig *it) struct comedi_subdevice *s; int ret; + printk(KERN_INFO "comedi%d: dnp: ", dev->minor); + dev->board_name = board->name; ret = comedi_alloc_subdevices(dev, 1); if (ret) return ret; - s = &dev->subdevices[0]; + s = dev->subdevices + 0; /* digital i/o subdevice */ s->type = COMEDI_SUBD_DIO; s->subdev_flags = SDF_READABLE | SDF_WRITABLE; @@ -193,6 +195,8 @@ static int dnp_attach(struct comedi_device *dev, struct comedi_devconfig *it) s->insn_bits = dnp_dio_insn_bits; s->insn_config = dnp_dio_insn_config; + printk("attached\n"); + /* We use the I/O ports 0x22,0x23 and 0xa3-0xa9, which are always * allocated for the primary 8259, so we don't need to allocate them * ourselves. */ @@ -205,7 +209,6 @@ static int dnp_attach(struct comedi_device *dev, struct comedi_devconfig *it) outb(PCMR, CSCIR); outb((inb(CSCDR) & 0xAA), CSCDR); - dev_info(dev->class_dev, "%s: attached\n", dev->board_name); return 1; } diff --git a/trunk/drivers/staging/comedi/drivers/usbdux.c b/trunk/drivers/staging/comedi/drivers/usbdux.c index b536bba74351..848c7ec06976 100644 --- a/trunk/drivers/staging/comedi/drivers/usbdux.c +++ b/trunk/drivers/staging/comedi/drivers/usbdux.c @@ -98,13 +98,10 @@ sampling rate. If you sample two channels you get 4kHz and so on. #include "../comedidev.h" -#include "comedi_fc.h" - /* timeout for the USB-transfer in ms*/ #define BULK_TIMEOUT 1000 /* constants for "firmware" upload and download */ -#define FIRMWARE "usbdux_firmware.bin" #define USBDUXSUB_FIRMWARE 0xA0 #define VENDOR_DIR_IN 0xC0 #define VENDOR_DIR_OUT 0x40 @@ -406,7 +403,7 @@ static void usbduxsub_ai_IsocIrq(struct urb *urb) /* the private structure of the subdevice is struct usbduxsub */ this_usbduxsub = this_comedidev->private; /* subdevice which is the AD converter */ - s = &this_comedidev->subdevices[SUBDEV_AD]; + s = this_comedidev->subdevices + SUBDEV_AD; /* first we test if something unusual has just happened */ switch (urb->status) { @@ -606,7 +603,7 @@ static void usbduxsub_ao_IsocIrq(struct urb *urb) /* the private structure of the subdevice is struct usbduxsub */ this_usbduxsub = this_comedidev->private; - s = &this_comedidev->subdevices[SUBDEV_DA]; + s = this_comedidev->subdevices + SUBDEV_DA; switch (urb->status) { case 0: @@ -931,9 +928,9 @@ static int usbduxsub_submit_OutURBs(struct usbduxsub *usbduxsub) static int usbdux_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd) { - struct usbduxsub *this_usbduxsub = dev->private; - int err = 0, i; + int err = 0, tmp, i; unsigned int tmpTimer; + struct usbduxsub *this_usbduxsub = dev->private; if (!(this_usbduxsub->probed)) return -ENODEV; @@ -941,23 +938,51 @@ static int usbdux_ai_cmdtest(struct comedi_device *dev, dev_dbg(&this_usbduxsub->interface->dev, "comedi%d: usbdux_ai_cmdtest\n", dev->minor); - /* Step 1 : check if triggers are trivially valid */ + /* make sure triggers are valid */ + /* Only immediate triggers are allowed */ + tmp = cmd->start_src; + cmd->start_src &= TRIG_NOW | TRIG_INT; + if (!cmd->start_src || tmp != cmd->start_src) + err++; - err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_INT); - err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_TIMER); - err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_NOW); - err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT); - err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE); + /* trigger should happen timed */ + tmp = cmd->scan_begin_src; + /* start a new _scan_ with a timer */ + cmd->scan_begin_src &= TRIG_TIMER; + if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) + err++; - if (err) - return 1; + /* scanning is continuous */ + tmp = cmd->convert_src; + cmd->convert_src &= TRIG_NOW; + if (!cmd->convert_src || tmp != cmd->convert_src) + err++; - /* Step 2a : make sure trigger sources are unique */ + /* issue a trigger when scan is finished and start a new scan */ + tmp = cmd->scan_end_src; + cmd->scan_end_src &= TRIG_COUNT; + if (!cmd->scan_end_src || tmp != cmd->scan_end_src) + err++; - err |= cfc_check_trigger_is_unique(cmd->start_src); - err |= cfc_check_trigger_is_unique(cmd->stop_src); + /* trigger at the end of count events or not, stop condition or not */ + tmp = cmd->stop_src; + cmd->stop_src &= TRIG_COUNT | TRIG_NONE; + if (!cmd->stop_src || tmp != cmd->stop_src) + err++; - /* Step 2b : and mutually compatible */ + if (err) + return 1; + + /* + * step 2: make sure trigger sources are unique and mutually compatible + * note that mutual compatibility is not an issue here + */ + if (cmd->scan_begin_src != TRIG_FOLLOW && + cmd->scan_begin_src != TRIG_EXT && + cmd->scan_begin_src != TRIG_TIMER) + err++; + if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE) + err++; if (err) return 2; @@ -1462,9 +1487,8 @@ static int usbdux_ao_inttrig(struct comedi_device *dev, static int usbdux_ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd) { + int err = 0, tmp; struct usbduxsub *this_usbduxsub = dev->private; - int err = 0; - unsigned int flags; if (!this_usbduxsub) return -EFAULT; @@ -1475,46 +1499,69 @@ static int usbdux_ao_cmdtest(struct comedi_device *dev, dev_dbg(&this_usbduxsub->interface->dev, "comedi%d: usbdux_ao_cmdtest\n", dev->minor); - /* Step 1 : check if triggers are trivially valid */ - - err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_INT); + /* make sure triggers are valid */ + /* Only immediate triggers are allowed */ + tmp = cmd->start_src; + cmd->start_src &= TRIG_NOW | TRIG_INT; + if (!cmd->start_src || tmp != cmd->start_src) + err++; + /* trigger should happen timed */ + tmp = cmd->scan_begin_src; + /* just now we scan also in the high speed mode every frame */ + /* this is due to ehci driver limitations */ if (0) { /* (this_usbduxsub->high_speed) */ + /* start immediately a new scan */ /* the sampling rate is set by the coversion rate */ - flags = TRIG_FOLLOW; + cmd->scan_begin_src &= TRIG_FOLLOW; } else { /* start a new scan (output at once) with a timer */ - flags = TRIG_TIMER; + cmd->scan_begin_src &= TRIG_TIMER; } - err |= cfc_check_trigger_src(&cmd->scan_begin_src, flags); + if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) + err++; + /* scanning is continuous */ + tmp = cmd->convert_src; + /* we always output at 1kHz just now all channels at once */ if (0) { /* (this_usbduxsub->high_speed) */ /* - * in usb-2.0 only one conversion it transmitted - * but with 8kHz/n + * in usb-2.0 only one conversion it transmitted but with 8kHz/n */ - flags = TRIG_TIMER; + cmd->convert_src &= TRIG_TIMER; } else { - /* - * all conversion events happen simultaneously with - * a rate of 1kHz/n - */ - flags = TRIG_NOW; + /* all conversion events happen simultaneously with a rate of + * 1kHz/n */ + cmd->convert_src &= TRIG_NOW; } - err |= cfc_check_trigger_src(&cmd->convert_src, flags); + if (!cmd->convert_src || tmp != cmd->convert_src) + err++; + + /* issue a trigger when scan is finished and start a new scan */ + tmp = cmd->scan_end_src; + cmd->scan_end_src &= TRIG_COUNT; + if (!cmd->scan_end_src || tmp != cmd->scan_end_src) + err++; - err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT); - err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE); + /* trigger at the end of count events or not, stop condition or not */ + tmp = cmd->stop_src; + cmd->stop_src &= TRIG_COUNT | TRIG_NONE; + if (!cmd->stop_src || tmp != cmd->stop_src) + err++; if (err) return 1; - /* Step 2a : make sure trigger sources are unique */ - - err |= cfc_check_trigger_is_unique(cmd->start_src); - err |= cfc_check_trigger_is_unique(cmd->stop_src); - - /* Step 2b : and mutually compatible */ + /* + * step 2: make sure trigger sources are unique and mutually compatible + * note that mutual compatibility is not an issue here + */ + if (cmd->scan_begin_src != TRIG_FOLLOW && + cmd->scan_begin_src != TRIG_EXT && + cmd->scan_begin_src != TRIG_TIMER) + err++; + if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE) + err++; if (err) return 2; @@ -1899,7 +1946,7 @@ static void usbduxsub_pwm_irq(struct urb *urb) /* the private structure of the subdevice is struct usbduxsub */ this_usbduxsub = this_comedidev->private; - s = &this_comedidev->subdevices[SUBDEV_DA]; + s = this_comedidev->subdevices + SUBDEV_DA; switch (urb->status) { case 0: @@ -2245,8 +2292,10 @@ static void tidy_up(struct usbduxsub *usbduxsub_tmp) usbduxsub_tmp->pwm_cmd_running = 0; } +/* common part of attach and attach_usb */ static int usbdux_attach_common(struct comedi_device *dev, - struct usbduxsub *udev) + struct usbduxsub *udev, + void *aux_data, int aux_len) { int ret; struct comedi_subdevice *s = NULL; @@ -2256,6 +2305,10 @@ static int usbdux_attach_common(struct comedi_device *dev, /* pointer back to the corresponding comedi device */ udev->comedidev = dev; + /* trying to upload the firmware into the chip */ + if (aux_data) + firmwareUpload(udev, aux_data, aux_len); + dev->board_name = "usbdux"; /* set number of subdevices */ @@ -2277,7 +2330,7 @@ static int usbdux_attach_common(struct comedi_device *dev, dev->private = udev; /* the first subdevice is the A/D converter */ - s = &dev->subdevices[SUBDEV_AD]; + s = dev->subdevices + SUBDEV_AD; /* the URBs get the comedi subdevice */ /* which is responsible for reading */ /* this is the subdevice which reads data */ @@ -2304,7 +2357,7 @@ static int usbdux_attach_common(struct comedi_device *dev, s->range_table = (&range_usbdux_ai_range); /* analog out */ - s = &dev->subdevices[SUBDEV_DA]; + s = dev->subdevices + SUBDEV_DA; /* analog out */ s->type = COMEDI_SUBD_AO; /* backward pointer */ @@ -2330,7 +2383,7 @@ static int usbdux_attach_common(struct comedi_device *dev, s->insn_write = usbdux_ao_insn_write; /* digital I/O */ - s = &dev->subdevices[SUBDEV_DIO]; + s = dev->subdevices + SUBDEV_DIO; s->type = COMEDI_SUBD_DIO; s->subdev_flags = SDF_READABLE | SDF_WRITABLE; s->n_chan = 8; @@ -2342,7 +2395,7 @@ static int usbdux_attach_common(struct comedi_device *dev, s->private = NULL; /* counter */ - s = &dev->subdevices[SUBDEV_COUNTER]; + s = dev->subdevices + SUBDEV_COUNTER; s->type = COMEDI_SUBD_COUNTER; s->subdev_flags = SDF_WRITABLE | SDF_READABLE; s->n_chan = 4; @@ -2353,7 +2406,7 @@ static int usbdux_attach_common(struct comedi_device *dev, if (udev->high_speed) { /* timer / pwm */ - s = &dev->subdevices[SUBDEV_PWM]; + s = dev->subdevices + SUBDEV_PWM; s->type = COMEDI_SUBD_PWM; s->subdev_flags = SDF_WRITABLE | SDF_PWM_HBRIDGE; s->n_chan = 8; @@ -2375,6 +2428,48 @@ static int usbdux_attach_common(struct comedi_device *dev, return 0; } +/* is called when comedi-config is called */ +static int usbdux_attach(struct comedi_device *dev, struct comedi_devconfig *it) +{ + int ret; + int index; + int i; + void *aux_data; + int aux_len; + + dev->private = NULL; + + aux_data = comedi_aux_data(it->options, 0); + aux_len = it->options[COMEDI_DEVCONF_AUX_DATA_LENGTH]; + if (aux_data == NULL) + aux_len = 0; + else if (aux_len == 0) + aux_data = NULL; + + down(&start_stop_sem); + /* find a valid device which has been detected by the probe function of + * the usb */ + index = -1; + for (i = 0; i < NUMUSBDUX; i++) { + if ((usbduxsub[i].probed) && (!usbduxsub[i].attached)) { + index = i; + break; + } + } + + if (index < 0) { + printk(KERN_ERR + "comedi%d: usbdux: error: attach failed, no usbdux devs connected to the usb bus.\n", + dev->minor); + ret = -ENODEV; + } else + ret = usbdux_attach_common(dev, &usbduxsub[index], + aux_data, aux_len); + up(&start_stop_sem); + return ret; +} + +/* is called from comedi_usb_auto_config() */ static int usbdux_attach_usb(struct comedi_device *dev, struct usb_interface *uinterf) { @@ -2396,7 +2491,7 @@ static int usbdux_attach_usb(struct comedi_device *dev, dev->minor); ret = -ENODEV; } else - ret = usbdux_attach_common(dev, this_usbduxsub); + ret = usbdux_attach_common(dev, this_usbduxsub, NULL, 0); up(&start_stop_sem); return ret; } @@ -2417,8 +2512,9 @@ static void usbdux_detach(struct comedi_device *dev) static struct comedi_driver usbdux_driver = { .driver_name = "usbdux", .module = THIS_MODULE, - .attach_usb = usbdux_attach_usb, + .attach = usbdux_attach, .detach = usbdux_detach, + .attach_usb = usbdux_attach_usb, }; static void usbdux_firmware_request_complete_handler(const struct firmware *fw, @@ -2695,7 +2791,7 @@ static int usbdux_usb_probe(struct usb_interface *uinterf, ret = request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG, - FIRMWARE, + "usbdux_firmware.bin", &udev->dev, GFP_KERNEL, usbduxsub + index, @@ -2754,4 +2850,3 @@ module_comedi_usb_driver(usbdux_driver, usbdux_usb_driver); MODULE_AUTHOR("Bernd Porr, BerndPorr@f2s.com"); MODULE_DESCRIPTION("Stirling/ITL USB-DUX -- Bernd.Porr@f2s.com"); MODULE_LICENSE("GPL"); -MODULE_FIRMWARE(FIRMWARE); diff --git a/trunk/drivers/staging/comedi/drivers/usbduxfast.c b/trunk/drivers/staging/comedi/drivers/usbduxfast.c index 1154a7e2895d..d9911588c10a 100644 --- a/trunk/drivers/staging/comedi/drivers/usbduxfast.c +++ b/trunk/drivers/staging/comedi/drivers/usbduxfast.c @@ -57,7 +57,6 @@ /* * constants for "firmware" upload and download */ -#define FIRMWARE "usbduxfast_firmware.bin" #define USBDUXFASTSUB_FIRMWARE 0xA0 #define VENDOR_DIR_IN 0xC0 #define VENDOR_DIR_OUT 0x40 @@ -346,7 +345,7 @@ static void usbduxfastsub_ai_Irq(struct urb *urb) return; } /* subdevice which is the AD converter */ - s = &this_comedidev->subdevices[SUBDEV_AD]; + s = this_comedidev->subdevices + SUBDEV_AD; /* first we test if something unusual has just happened */ switch (urb->status) { @@ -549,10 +548,10 @@ static int usbduxfast_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd) { - struct usbduxfastsub_s *udfs = dev->private; - int err = 0; + int err = 0, stop_mask = 0; long int steps, tmp; int minSamplPer; + struct usbduxfastsub_s *udfs = dev->private; if (!udfs->probed) return -ENODEV; @@ -563,31 +562,57 @@ static int usbduxfast_ai_cmdtest(struct comedi_device *dev, "scan_begin_arg=%u\n", dev->minor, cmd->convert_arg, cmd->scan_begin_arg); #endif - /* Step 1 : check if triggers are trivially valid */ + /* step 1: make sure trigger sources are trivially valid */ + + tmp = cmd->start_src; + cmd->start_src &= TRIG_NOW | TRIG_EXT | TRIG_INT; + if (!cmd->start_src || tmp != cmd->start_src) + err++; + + tmp = cmd->scan_begin_src; + cmd->scan_begin_src &= TRIG_TIMER | TRIG_FOLLOW | TRIG_EXT; + if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) + err++; + + tmp = cmd->convert_src; + cmd->convert_src &= TRIG_TIMER | TRIG_EXT; + if (!cmd->convert_src || tmp != cmd->convert_src) + err++; - err |= cfc_check_trigger_src(&cmd->start_src, - TRIG_NOW | TRIG_EXT | TRIG_INT); - err |= cfc_check_trigger_src(&cmd->scan_begin_src, - TRIG_TIMER | TRIG_FOLLOW | TRIG_EXT); - err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_TIMER | TRIG_EXT); - err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT); - err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE); + tmp = cmd->scan_end_src; + cmd->scan_end_src &= TRIG_COUNT; + if (!cmd->scan_end_src || tmp != cmd->scan_end_src) + err++; + + tmp = cmd->stop_src; + stop_mask = TRIG_COUNT | TRIG_NONE; + cmd->stop_src &= stop_mask; + if (!cmd->stop_src || tmp != cmd->stop_src) + err++; if (err) return 1; - /* Step 2a : make sure trigger sources are unique */ - - err |= cfc_check_trigger_is_unique(cmd->start_src); - err |= cfc_check_trigger_is_unique(cmd->scan_begin_src); - err |= cfc_check_trigger_is_unique(cmd->convert_src); - err |= cfc_check_trigger_is_unique(cmd->stop_src); + /* + * step 2: make sure trigger sources are unique and mutually compatible + */ - /* Step 2b : and mutually compatible */ + if (cmd->start_src != TRIG_NOW && + cmd->start_src != TRIG_EXT && cmd->start_src != TRIG_INT) + err++; + if (cmd->scan_begin_src != TRIG_TIMER && + cmd->scan_begin_src != TRIG_FOLLOW && + cmd->scan_begin_src != TRIG_EXT) + err++; + if (cmd->convert_src != TRIG_TIMER && cmd->convert_src != TRIG_EXT) + err++; + if (cmd->stop_src != TRIG_COUNT && + cmd->stop_src != TRIG_EXT && cmd->stop_src != TRIG_NONE) + err++; /* can't have external stop and start triggers at once */ if (cmd->start_src == TRIG_EXT && cmd->stop_src == TRIG_EXT) - err |= -EINVAL; + err++; if (err) return 2; @@ -1404,8 +1429,10 @@ static void tidy_up(struct usbduxfastsub_s *udfs) udfs->ai_cmd_running = 0; } +/* common part of attach and attach_usb */ static int usbduxfast_attach_common(struct comedi_device *dev, - struct usbduxfastsub_s *udfs) + struct usbduxfastsub_s *udfs, + void *aux_data, int aux_len) { int ret; struct comedi_subdevice *s; @@ -1413,6 +1440,9 @@ static int usbduxfast_attach_common(struct comedi_device *dev, down(&udfs->sem); /* pointer back to the corresponding comedi device */ udfs->comedidev = dev; + /* trying to upload the firmware into the chip */ + if (aux_data) + firmwareUpload(udfs, aux_data, aux_len); dev->board_name = "usbduxfast"; ret = comedi_alloc_subdevices(dev, 1); if (ret) { @@ -1422,7 +1452,7 @@ static int usbduxfast_attach_common(struct comedi_device *dev, /* private structure is also simply the usb-structure */ dev->private = udfs; /* the first subdevice is the A/D converter */ - s = &dev->subdevices[SUBDEV_AD]; + s = dev->subdevices + SUBDEV_AD; /* * the URBs get the comedi subdevice which is responsible for reading * this is the subdevice which reads data @@ -1454,6 +1484,48 @@ static int usbduxfast_attach_common(struct comedi_device *dev, return 0; } +/* is called for COMEDI_DEVCONFIG ioctl (when comedi_config is run) */ +static int usbduxfast_attach(struct comedi_device *dev, + struct comedi_devconfig *it) +{ + int ret; + int index; + int i; + void *aux_data; + int aux_len; + + dev->private = NULL; + + aux_data = comedi_aux_data(it->options, 0); + aux_len = it->options[COMEDI_DEVCONF_AUX_DATA_LENGTH]; + if (aux_data == NULL) + aux_len = 0; + else if (aux_len == 0) + aux_data = NULL; + down(&start_stop_sem); + /* + * find a valid device which has been detected by the + * probe function of the usb + */ + index = -1; + for (i = 0; i < NUMUSBDUXFAST; i++) { + if (usbduxfastsub[i].probed && !usbduxfastsub[i].attached) { + index = i; + break; + } + } + if (index < 0) { + dev_err(dev->class_dev, + "usbduxfast: error: attach failed, no usbduxfast devs connected to the usb bus.\n"); + ret = -ENODEV; + } else + ret = usbduxfast_attach_common(dev, &usbduxfastsub[index], + aux_data, aux_len); + up(&start_stop_sem); + return ret; +} + +/* is called from comedi_usb_auto_config() */ static int usbduxfast_attach_usb(struct comedi_device *dev, struct usb_interface *uinterf) { @@ -1472,7 +1544,7 @@ static int usbduxfast_attach_usb(struct comedi_device *dev, "usbduxfast: error: attach_usb failed, already attached\n"); ret = -ENODEV; } else - ret = usbduxfast_attach_common(dev, udfs); + ret = usbduxfast_attach_common(dev, udfs, NULL, 0); up(&start_stop_sem); return ret; } @@ -1495,8 +1567,9 @@ static void usbduxfast_detach(struct comedi_device *dev) static struct comedi_driver usbduxfast_driver = { .driver_name = "usbduxfast", .module = THIS_MODULE, - .attach_usb = usbduxfast_attach_usb, + .attach = usbduxfast_attach, .detach = usbduxfast_detach, + .attach_usb = usbduxfast_attach_usb, }; static void usbduxfast_firmware_request_complete_handler(const struct firmware @@ -1633,7 +1706,7 @@ static int usbduxfast_usb_probe(struct usb_interface *uinterf, ret = request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG, - FIRMWARE, + "usbduxfast_firmware.bin", &udev->dev, GFP_KERNEL, usbduxfastsub + index, @@ -1701,4 +1774,3 @@ module_comedi_usb_driver(usbduxfast_driver, usbduxfast_usb_driver); MODULE_AUTHOR("Bernd Porr, BerndPorr@f2s.com"); MODULE_DESCRIPTION("USB-DUXfast, BerndPorr@f2s.com"); MODULE_LICENSE("GPL"); -MODULE_FIRMWARE(FIRMWARE); diff --git a/trunk/drivers/staging/comedi/drivers/usbduxsigma.c b/trunk/drivers/staging/comedi/drivers/usbduxsigma.c index b1694121f845..543e604791e2 100644 --- a/trunk/drivers/staging/comedi/drivers/usbduxsigma.c +++ b/trunk/drivers/staging/comedi/drivers/usbduxsigma.c @@ -63,7 +63,6 @@ Status: testing #define BULK_TIMEOUT 1000 /* constants for "firmware" upload and download */ -#define FIRMWARE "usbduxsigma_firmware.bin" #define USBDUXSUB_FIRMWARE 0xA0 #define VENDOR_DIR_IN 0xC0 #define VENDOR_DIR_OUT 0x40 @@ -356,7 +355,7 @@ static void usbduxsub_ai_IsocIrq(struct urb *urb) /* the private structure of the subdevice is struct usbduxsub */ this_usbduxsub = this_comedidev->private; /* subdevice which is the AD converter */ - s = &this_comedidev->subdevices[SUBDEV_AD]; + s = this_comedidev->subdevices + SUBDEV_AD; /* first we test if something unusual has just happened */ switch (urb->status) { @@ -558,7 +557,7 @@ static void usbduxsub_ao_IsocIrq(struct urb *urb) /* the private structure of the subdevice is struct usbduxsub */ this_usbduxsub = this_comedidev->private; - s = &this_comedidev->subdevices[SUBDEV_DA]; + s = this_comedidev->subdevices + SUBDEV_DA; switch (urb->status) { case 0: @@ -897,9 +896,9 @@ static int usbdux_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd) { - struct usbduxsub *this_usbduxsub = dev->private; - int err = 0, i; + int err = 0, tmp, i; unsigned int tmpTimer; + struct usbduxsub *this_usbduxsub = dev->private; if (!(this_usbduxsub->probed)) return -ENODEV; @@ -907,23 +906,51 @@ static int usbdux_ai_cmdtest(struct comedi_device *dev, dev_dbg(&this_usbduxsub->interface->dev, "comedi%d: usbdux_ai_cmdtest\n", dev->minor); - /* Step 1 : check if triggers are trivially valid */ + /* make sure triggers are valid */ + /* Only immediate triggers are allowed */ + tmp = cmd->start_src; + cmd->start_src &= TRIG_NOW | TRIG_INT; + if (!cmd->start_src || tmp != cmd->start_src) + err++; - err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_INT); - err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_TIMER); - err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_NOW); - err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT); - err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE); + /* trigger should happen timed */ + tmp = cmd->scan_begin_src; + /* start a new _scan_ with a timer */ + cmd->scan_begin_src &= TRIG_TIMER; + if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) + err++; - if (err) - return 1; + /* scanning is continuous */ + tmp = cmd->convert_src; + cmd->convert_src &= TRIG_NOW; + if (!cmd->convert_src || tmp != cmd->convert_src) + err++; - /* Step 2a : make sure trigger sources are unique */ + /* issue a trigger when scan is finished and start a new scan */ + tmp = cmd->scan_end_src; + cmd->scan_end_src &= TRIG_COUNT; + if (!cmd->scan_end_src || tmp != cmd->scan_end_src) + err++; - err |= cfc_check_trigger_is_unique(cmd->start_src); - err |= cfc_check_trigger_is_unique(cmd->stop_src); + /* trigger at the end of count events or not, stop condition or not */ + tmp = cmd->stop_src; + cmd->stop_src &= TRIG_COUNT | TRIG_NONE; + if (!cmd->stop_src || tmp != cmd->stop_src) + err++; + + if (err) + return 1; - /* Step 2b : and mutually compatible */ + /* + * step 2: make sure trigger sources are unique and mutually compatible + * note that mutual compatibility is not an issue here + */ + if (cmd->scan_begin_src != TRIG_FOLLOW && + cmd->scan_begin_src != TRIG_EXT && + cmd->scan_begin_src != TRIG_TIMER) + err++; + if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE) + err++; if (err) return 2; @@ -1530,9 +1557,8 @@ static int usbdux_ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd) { + int err = 0, tmp; struct usbduxsub *this_usbduxsub = dev->private; - int err = 0; - unsigned int flags; if (!this_usbduxsub) return -EFAULT; @@ -1543,35 +1569,63 @@ static int usbdux_ao_cmdtest(struct comedi_device *dev, dev_dbg(&this_usbduxsub->interface->dev, "comedi%d: usbdux_ao_cmdtest\n", dev->minor); - /* Step 1 : check if triggers are trivially valid */ - - err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_INT); + /* make sure triggers are valid */ + /* Only immediate triggers are allowed */ + tmp = cmd->start_src; + cmd->start_src &= TRIG_NOW | TRIG_INT; + if (!cmd->start_src || tmp != cmd->start_src) + err++; + /* trigger should happen timed */ + tmp = cmd->scan_begin_src; + /* just now we scan also in the high speed mode every frame */ + /* this is due to ehci driver limitations */ if (0) { /* (this_usbduxsub->high_speed) */ - /* - * start immediately a new scan - * the sampling rate is set by the coversion rate - */ - flags = TRIG_FOLLOW; + /* start immediately a new scan */ + /* the sampling rate is set by the coversion rate */ + cmd->scan_begin_src &= TRIG_FOLLOW; } else { /* start a new scan (output at once) with a timer */ - flags = TRIG_TIMER; + cmd->scan_begin_src &= TRIG_TIMER; } - err |= cfc_check_trigger_src(&cmd->scan_begin_src, flags); + if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) + err++; - err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_NOW); - err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT); - err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE); + /* scanning is continuous */ + tmp = cmd->convert_src; - if (err) - return 1; + /* all conversion events happen simultaneously */ + cmd->convert_src &= TRIG_NOW; - /* Step 2a : make sure trigger sources are unique */ + if (!cmd->convert_src || tmp != cmd->convert_src) + err++; - err |= cfc_check_trigger_is_unique(cmd->start_src); - err |= cfc_check_trigger_is_unique(cmd->stop_src); + /* issue a trigger when scan is finished and start a new scan */ + tmp = cmd->scan_end_src; + cmd->scan_end_src &= TRIG_COUNT; + if (!cmd->scan_end_src || tmp != cmd->scan_end_src) + err++; - /* Step 2b : and mutually compatible */ + /* trigger at the end of count events or not, stop condition or not */ + tmp = cmd->stop_src; + cmd->stop_src &= TRIG_COUNT | TRIG_NONE; + if (!cmd->stop_src || tmp != cmd->stop_src) + err++; + + if (err) + return 1; + + /* + * step 2: make sure trigger sources + * are unique and mutually compatible + * note that mutual compatibility is not an issue here + */ + if (cmd->scan_begin_src != TRIG_FOLLOW && + cmd->scan_begin_src != TRIG_EXT && + cmd->scan_begin_src != TRIG_TIMER) + err++; + if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE) + err++; if (err) return 2; @@ -1895,7 +1949,7 @@ static void usbduxsub_pwm_irq(struct urb *urb) /* the private structure of the subdevice is struct usbduxsub */ this_usbduxsub = this_comedidev->private; - s = &this_comedidev->subdevices[SUBDEV_DA]; + s = this_comedidev->subdevices + SUBDEV_DA; switch (urb->status) { case 0: @@ -2246,8 +2300,10 @@ static void tidy_up(struct usbduxsub *usbduxsub_tmp) usbduxsub_tmp->pwm_cmd_running = 0; } +/* common part of attach and attach_usb */ static int usbduxsigma_attach_common(struct comedi_device *dev, - struct usbduxsub *uds) + struct usbduxsub *uds, + void *aux_data, int aux_len) { int ret; struct comedi_subdevice *s; @@ -2257,6 +2313,9 @@ static int usbduxsigma_attach_common(struct comedi_device *dev, down(&uds->sem); /* pointer back to the corresponding comedi device */ uds->comedidev = dev; + /* trying to upload the firmware into the FX2 */ + if (aux_data) + firmwareUpload(uds, aux_data, aux_len); dev->board_name = "usbduxsigma"; /* set number of subdevices */ if (uds->high_speed) @@ -2271,7 +2330,7 @@ static int usbduxsigma_attach_common(struct comedi_device *dev, /* private structure is also simply the usb-structure */ dev->private = uds; /* the first subdevice is the A/D converter */ - s = &dev->subdevices[SUBDEV_AD]; + s = dev->subdevices + SUBDEV_AD; /* the URBs get the comedi subdevice */ /* which is responsible for reading */ /* this is the subdevice which reads data */ @@ -2298,7 +2357,7 @@ static int usbduxsigma_attach_common(struct comedi_device *dev, /* range table to convert to physical units */ s->range_table = (&range_usbdux_ai_range); /* analog output subdevice */ - s = &dev->subdevices[SUBDEV_DA]; + s = dev->subdevices + SUBDEV_DA; /* analog out */ s->type = COMEDI_SUBD_AO; /* backward pointer */ @@ -2323,7 +2382,7 @@ static int usbduxsigma_attach_common(struct comedi_device *dev, s->insn_read = usbdux_ao_insn_read; s->insn_write = usbdux_ao_insn_write; /* digital I/O subdevice */ - s = &dev->subdevices[SUBDEV_DIO]; + s = dev->subdevices + SUBDEV_DIO; s->type = COMEDI_SUBD_DIO; s->subdev_flags = SDF_READABLE | SDF_WRITABLE; /* 8 external and 16 internal channels */ @@ -2336,7 +2395,7 @@ static int usbduxsigma_attach_common(struct comedi_device *dev, s->private = NULL; if (uds->high_speed) { /* timer / pwm subdevice */ - s = &dev->subdevices[SUBDEV_PWM]; + s = dev->subdevices + SUBDEV_PWM; s->type = COMEDI_SUBD_PWM; s->subdev_flags = SDF_WRITABLE | SDF_PWM_HBRIDGE; s->n_chan = 8; @@ -2359,6 +2418,47 @@ static int usbduxsigma_attach_common(struct comedi_device *dev, return 0; } +/* is called for COMEDI_DEVCONFIG ioctl (when comedi_config is run) */ +static int usbduxsigma_attach(struct comedi_device *dev, + struct comedi_devconfig *it) +{ + int ret; + int index; + int i; + void *aux_data; + int aux_len; + + dev->private = NULL; + + aux_data = comedi_aux_data(it->options, 0); + aux_len = it->options[COMEDI_DEVCONF_AUX_DATA_LENGTH]; + if (aux_data == NULL) + aux_len = 0; + else if (aux_len == 0) + aux_data = NULL; + + down(&start_stop_sem); + /* find a valid device which has been detected by the probe function of + * the usb */ + index = -1; + for (i = 0; i < NUMUSBDUX; i++) { + if ((usbduxsub[i].probed) && (!usbduxsub[i].attached)) { + index = i; + break; + } + } + if (index < 0) { + dev_err(dev->class_dev, + "usbduxsigma: error: attach failed, dev not connected to the usb bus.\n"); + ret = -ENODEV; + } else + ret = usbduxsigma_attach_common(dev, &usbduxsub[index], + aux_data, aux_len); + up(&start_stop_sem); + return ret; +} + +/* is called from comedi_usb_auto_config() */ static int usbduxsigma_attach_usb(struct comedi_device *dev, struct usb_interface *uinterf) { @@ -2377,7 +2477,7 @@ static int usbduxsigma_attach_usb(struct comedi_device *dev, "usbduxsigma: error: attach_usb failed, already attached\n"); ret = -ENODEV; } else - ret = usbduxsigma_attach_common(dev, uds); + ret = usbduxsigma_attach_common(dev, uds, NULL, 0); up(&start_stop_sem); return ret; } @@ -2398,8 +2498,9 @@ static void usbduxsigma_detach(struct comedi_device *dev) static struct comedi_driver usbduxsigma_driver = { .driver_name = "usbduxsigma", .module = THIS_MODULE, - .attach_usb = usbduxsigma_attach_usb, + .attach = usbduxsigma_attach, .detach = usbduxsigma_detach, + .attach_usb = usbduxsigma_attach_usb, }; static void usbdux_firmware_request_complete_handler(const struct firmware *fw, @@ -2679,7 +2780,7 @@ static int usbduxsigma_usb_probe(struct usb_interface *uinterf, ret = request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG, - FIRMWARE, + "usbduxsigma_firmware.bin", &udev->dev, GFP_KERNEL, usbduxsub + index, @@ -2744,4 +2845,3 @@ module_comedi_usb_driver(usbduxsigma_driver, usbduxsigma_usb_driver); MODULE_AUTHOR("Bernd Porr, BerndPorr@f2s.com"); MODULE_DESCRIPTION("Stirling/ITL USB-DUX SIGMA -- Bernd.Porr@f2s.com"); MODULE_LICENSE("GPL"); -MODULE_FIRMWARE(FIRMWARE); diff --git a/trunk/drivers/staging/comedi/drivers/vmk80xx.c b/trunk/drivers/staging/comedi/drivers/vmk80xx.c index df277aa591bb..94010fc05905 100644 --- a/trunk/drivers/staging/comedi/drivers/vmk80xx.c +++ b/trunk/drivers/staging/comedi/drivers/vmk80xx.c @@ -546,7 +546,6 @@ static int vmk80xx_ai_rinsn(struct comedi_device *cdev, reg[0] = VMK8055_AI2_REG; break; case VMK8061_MODEL: - default: reg[0] = VMK8061_AI_REG1; reg[1] = VMK8061_AI_REG2; dev->usb_tx_buf[0] = VMK8061_CMD_RD_AI; @@ -905,7 +904,6 @@ static int vmk80xx_cnt_rinsn(struct comedi_device *cdev, reg[0] = VMK8055_CNT2_REG; break; case VMK8061_MODEL: - default: reg[0] = VMK8061_CNT_REG; reg[1] = VMK8061_CNT_REG; dev->usb_tx_buf[0] = VMK8061_CMD_RD_CNT; @@ -1121,7 +1119,7 @@ static int vmk80xx_attach_common(struct comedi_device *cdev, return ret; } /* Analog input subdevice */ - s = &cdev->subdevices[VMK80XX_SUBD_AI]; + s = cdev->subdevices + VMK80XX_SUBD_AI; s->type = COMEDI_SUBD_AI; s->subdev_flags = SDF_READABLE | SDF_GROUND; s->n_chan = dev->board.ai_chans; @@ -1129,7 +1127,7 @@ static int vmk80xx_attach_common(struct comedi_device *cdev, s->range_table = dev->board.range; s->insn_read = vmk80xx_ai_rinsn; /* Analog output subdevice */ - s = &cdev->subdevices[VMK80XX_SUBD_AO]; + s = cdev->subdevices + VMK80XX_SUBD_AO; s->type = COMEDI_SUBD_AO; s->subdev_flags = SDF_WRITEABLE | SDF_GROUND; s->n_chan = dev->board.ao_chans; @@ -1141,7 +1139,7 @@ static int vmk80xx_attach_common(struct comedi_device *cdev, s->insn_read = vmk80xx_ao_rinsn; } /* Digital input subdevice */ - s = &cdev->subdevices[VMK80XX_SUBD_DI]; + s = cdev->subdevices + VMK80XX_SUBD_DI; s->type = COMEDI_SUBD_DI; s->subdev_flags = SDF_READABLE | SDF_GROUND; s->n_chan = dev->board.di_chans; @@ -1149,7 +1147,7 @@ static int vmk80xx_attach_common(struct comedi_device *cdev, s->insn_read = vmk80xx_di_rinsn; s->insn_bits = vmk80xx_di_bits; /* Digital output subdevice */ - s = &cdev->subdevices[VMK80XX_SUBD_DO]; + s = cdev->subdevices + VMK80XX_SUBD_DO; s->type = COMEDI_SUBD_DO; s->subdev_flags = SDF_WRITEABLE | SDF_GROUND; s->n_chan = dev->board.do_chans; @@ -1161,7 +1159,7 @@ static int vmk80xx_attach_common(struct comedi_device *cdev, s->insn_read = vmk80xx_do_rinsn; } /* Counter subdevice */ - s = &cdev->subdevices[VMK80XX_SUBD_CNT]; + s = cdev->subdevices + VMK80XX_SUBD_CNT; s->type = COMEDI_SUBD_COUNTER; s->subdev_flags = SDF_READABLE; s->n_chan = dev->board.cnt_chans; @@ -1174,7 +1172,7 @@ static int vmk80xx_attach_common(struct comedi_device *cdev, } /* PWM subdevice */ if (dev->board.model == VMK8061_MODEL) { - s = &cdev->subdevices[VMK80XX_SUBD_PWM]; + s = cdev->subdevices + VMK80XX_SUBD_PWM; s->type = COMEDI_SUBD_PWM; s->subdev_flags = SDF_READABLE | SDF_WRITEABLE; s->n_chan = dev->board.pwm_chans; diff --git a/trunk/drivers/staging/comedi/kcomedilib/kcomedilib_main.c b/trunk/drivers/staging/comedi/kcomedilib/kcomedilib_main.c index 3f20ea55b8d0..0252b4408851 100644 --- a/trunk/drivers/staging/comedi/kcomedilib/kcomedilib_main.c +++ b/trunk/drivers/staging/comedi/kcomedilib/kcomedilib_main.c @@ -80,9 +80,7 @@ int comedi_close(struct comedi_device *d) } EXPORT_SYMBOL(comedi_close); -static int comedi_do_insn(struct comedi_device *dev, - struct comedi_insn *insn, - unsigned int *data) +static int comedi_do_insn(struct comedi_device *dev, struct comedi_insn *insn) { struct comedi_subdevice *s; int ret = 0; @@ -92,7 +90,7 @@ static int comedi_do_insn(struct comedi_device *dev, ret = -EINVAL; goto error; } - s = &dev->subdevices[insn->subdev]; + s = dev->subdevices + insn->subdev; if (s->type == COMEDI_SUBD_UNUSED) { printk(KERN_ERR "%d not useable subdevice\n", insn->subdev); @@ -117,11 +115,11 @@ static int comedi_do_insn(struct comedi_device *dev, switch (insn->insn) { case INSN_BITS: - ret = s->insn_bits(dev, s, insn, data); + ret = s->insn_bits(dev, s, insn, insn->data); break; case INSN_CONFIG: /* XXX should check instruction length */ - ret = s->insn_config(dev, s, insn, data); + ret = s->insn_config(dev, s, insn, insn->data); break; default: ret = -EINVAL; @@ -142,10 +140,11 @@ int comedi_dio_config(struct comedi_device *dev, unsigned int subdev, memset(&insn, 0, sizeof(insn)); insn.insn = INSN_CONFIG; insn.n = 1; + insn.data = &io; insn.subdev = subdev; insn.chanspec = CR_PACK(chan, 0, 0); - return comedi_do_insn(dev, &insn, &io); + return comedi_do_insn(dev, &insn); } EXPORT_SYMBOL(comedi_dio_config); @@ -159,12 +158,13 @@ int comedi_dio_bitfield(struct comedi_device *dev, unsigned int subdev, memset(&insn, 0, sizeof(insn)); insn.insn = INSN_BITS; insn.n = 2; + insn.data = data; insn.subdev = subdev; data[0] = mask; data[1] = *bits; - ret = comedi_do_insn(dev, &insn, data); + ret = comedi_do_insn(dev, &insn); *bits = data[1]; @@ -175,14 +175,11 @@ EXPORT_SYMBOL(comedi_dio_bitfield); int comedi_find_subdevice_by_type(struct comedi_device *dev, int type, unsigned int subd) { - struct comedi_subdevice *s; - if (subd > dev->n_subdevices) return -ENODEV; for (; subd < dev->n_subdevices; subd++) { - s = &dev->subdevices[subd]; - if (s->type == type) + if (dev->subdevices[subd].type == type) return subd; } return -1; @@ -191,7 +188,7 @@ EXPORT_SYMBOL(comedi_find_subdevice_by_type); int comedi_get_n_channels(struct comedi_device *dev, unsigned int subdevice) { - struct comedi_subdevice *s = &dev->subdevices[subdevice]; + struct comedi_subdevice *s = dev->subdevices + subdevice; return s->n_chan; } diff --git a/trunk/drivers/staging/comedi/range.c b/trunk/drivers/staging/comedi/range.c index 59ff0cf73381..41f95237789d 100644 --- a/trunk/drivers/staging/comedi/range.c +++ b/trunk/drivers/staging/comedi/range.c @@ -68,7 +68,7 @@ int do_rangeinfo_ioctl(struct comedi_device *dev, return -EINVAL; if (subd >= dev->n_subdevices) return -EINVAL; - s = &dev->subdevices[subd]; + s = dev->subdevices + subd; if (s->range_table) { lr = s->range_table; } else if (s->range_table_list) { @@ -131,7 +131,6 @@ static int aref_invalid(struct comedi_subdevice *s, unsigned int chanspec) int comedi_check_chanlist(struct comedi_subdevice *s, int n, unsigned int *chanlist) { - struct comedi_device *dev = s->device; int i; int chan; @@ -140,10 +139,10 @@ int comedi_check_chanlist(struct comedi_subdevice *s, int n, if (CR_CHAN(chanlist[i]) >= s->n_chan || CR_RANGE(chanlist[i]) >= s->range_table->length || aref_invalid(s, chanlist[i])) { - dev_warn(dev->class_dev, - "bad chanlist[%d]=0x%08x in_chan=%d range length=%d\n", - i, chanlist[i], s->n_chan, - s->range_table->length); + printk(KERN_ERR "bad chanlist[%d]=0x%08x " + "in_chan=%d range length=%d\n", i, + chanlist[i], s->n_chan, + s->range_table->length); return -EINVAL; } } else if (s->range_table_list) { @@ -153,14 +152,13 @@ int comedi_check_chanlist(struct comedi_subdevice *s, int n, CR_RANGE(chanlist[i]) >= s->range_table_list[chan]->length || aref_invalid(s, chanlist[i])) { - dev_warn(dev->class_dev, - "bad chanlist[%d]=0x%08x\n", - i, chanlist[i]); + printk(KERN_ERR "bad chanlist[%d]=0x%08x\n", + i, chanlist[i]); return -EINVAL; } } } else { - dev_err(dev->class_dev, "(bug) no range type list!\n"); + printk(KERN_ERR "comedi: (bug) no range type list!\n"); return -EINVAL; } return 0; diff --git a/trunk/drivers/staging/cptm1217/clearpad_tm1217.c b/trunk/drivers/staging/cptm1217/clearpad_tm1217.c index a49b0da60049..0d924d3a2ab1 100644 --- a/trunk/drivers/staging/cptm1217/clearpad_tm1217.c +++ b/trunk/drivers/staging/cptm1217/clearpad_tm1217.c @@ -658,7 +658,18 @@ static struct i2c_driver cp_tm1217_driver = { .resume = cp_tm1217_resume, }; -module_i2c_driver(cp_tm1217_driver); +static int __init clearpad_tm1217_init(void) +{ + return i2c_add_driver(&cp_tm1217_driver); +} + +static void __exit clearpad_tm1217_exit(void) +{ + i2c_del_driver(&cp_tm1217_driver); +} + +module_init(clearpad_tm1217_init); +module_exit(clearpad_tm1217_exit); MODULE_AUTHOR("Ramesh Agarwal "); MODULE_DESCRIPTION("Synaptics TM1217 TouchScreen Driver"); diff --git a/trunk/drivers/staging/crystalhd/crystalhd_lnx.c b/trunk/drivers/staging/crystalhd/crystalhd_lnx.c index 166203aeb7b4..d9e3d618f7f4 100644 --- a/trunk/drivers/staging/crystalhd/crystalhd_lnx.c +++ b/trunk/drivers/staging/crystalhd/crystalhd_lnx.c @@ -373,15 +373,13 @@ static int __devinit chd_dec_init_chdev(struct crystalhd_adp *adp) /* register crystalhd class */ crystalhd_class = class_create(THIS_MODULE, "crystalhd"); if (IS_ERR(crystalhd_class)) { - rc = PTR_ERR(crystalhd_class); BCMLOG_ERR("failed to create class\n"); - goto class_create_fail; + goto fail; } dev = device_create(crystalhd_class, NULL, MKDEV(adp->chd_dec_major, 0), NULL, "crystalhd"); if (IS_ERR(dev)) { - rc = PTR_ERR(dev); BCMLOG_ERR("failed to create device\n"); goto device_create_fail; } @@ -412,8 +410,6 @@ static int __devinit chd_dec_init_chdev(struct crystalhd_adp *adp) device_destroy(crystalhd_class, MKDEV(adp->chd_dec_major, 0)); device_create_fail: class_destroy(crystalhd_class); -class_create_fail: - unregister_chrdev(adp->chd_dec_major, CRYSTALHD_API_NAME); fail: return rc; } diff --git a/trunk/drivers/staging/csr/Kconfig b/trunk/drivers/staging/csr/Kconfig index ad2a1096e920..cee8d48d2af9 100644 --- a/trunk/drivers/staging/csr/Kconfig +++ b/trunk/drivers/staging/csr/Kconfig @@ -1,6 +1,6 @@ config CSR_WIFI tristate "CSR wireless driver" - depends on MMC && CFG80211_WEXT && INET + depends on MMC && CFG80211_WEXT select WIRELESS_EXT select WEXT_PRIV help diff --git a/trunk/drivers/staging/csr/Makefile b/trunk/drivers/staging/csr/Makefile index ab626edc5ba4..afda44b0a925 100644 --- a/trunk/drivers/staging/csr/Makefile +++ b/trunk/drivers/staging/csr/Makefile @@ -25,6 +25,7 @@ csr_wifi-y := bh.o \ unifi_event.o \ unifi_pdu_processing.o \ unifi_sme.o \ + csr_formatted_io.o \ csr_wifi_hip_card_sdio.o \ csr_wifi_hip_card_sdio_intr.o \ csr_wifi_hip_card_sdio_mem.o \ diff --git a/trunk/drivers/staging/csr/bh.c b/trunk/drivers/staging/csr/bh.c index addee05a4516..b089c28d5610 100644 --- a/trunk/drivers/staging/csr/bh.c +++ b/trunk/drivers/staging/csr/bh.c @@ -32,49 +32,45 @@ * 0 on success or else a Linux error code. * --------------------------------------------------------------------------- */ -int uf_start_thread(unifi_priv_t *priv, - struct uf_thread *thread, int (*func)(void *)) +int +uf_start_thread(unifi_priv_t *priv, struct uf_thread *thread, int (*func)(void *)) { - if (thread->thread_task != NULL) { - unifi_error(priv, "%s thread already started\n", thread->name); - return 0; - } - - /* Start the kernel thread that handles all h/w accesses. */ - thread->thread_task = kthread_run(func, priv, "%s", thread->name); - if (IS_ERR(thread->thread_task)) - return PTR_ERR(thread->thread_task); - - /* Module parameter overides the thread priority */ - if (bh_priority != -1) { - if (bh_priority >= 0 && bh_priority <= MAX_RT_PRIO) { - struct sched_param param; - priv->bh_thread.prio = bh_priority; - unifi_trace(priv, UDBG1, - "%s thread (RT) priority = %d\n", - thread->name, bh_priority); - param.sched_priority = bh_priority; - sched_setscheduler(thread->thread_task, - SCHED_FIFO, ¶m); - } else if (bh_priority > MAX_RT_PRIO && - bh_priority <= MAX_PRIO) { - priv->bh_thread.prio = bh_priority; - unifi_trace(priv, UDBG1, "%s thread priority = %d\n", - thread->name, - PRIO_TO_NICE(bh_priority)); - set_user_nice(thread->thread_task, - PRIO_TO_NICE(bh_priority)); - } else { - priv->bh_thread.prio = DEFAULT_PRIO; - unifi_warning(priv, - "%s thread unsupported (%d) priority\n", - thread->name, bh_priority); - } - } else - priv->bh_thread.prio = DEFAULT_PRIO; - unifi_trace(priv, UDBG2, "Started %s thread\n", thread->name); - - return 0; + if (thread->thread_task != NULL) { + unifi_error(priv, "%s thread already started\n", thread->name); + return 0; + } + + /* Start the kernel thread that handles all h/w accesses. */ + thread->thread_task = kthread_run(func, priv, "%s", thread->name); + if (IS_ERR(thread->thread_task)) { + return PTR_ERR(thread->thread_task); + } + + /* Module parameter overides the thread priority */ + if (bh_priority != -1) { + if (bh_priority >= 0 && bh_priority <= MAX_RT_PRIO) { + struct sched_param param; + priv->bh_thread.prio = bh_priority; + unifi_trace(priv, UDBG1, "%s thread (RT) priority = %d\n", + thread->name, bh_priority); + param.sched_priority = bh_priority; + sched_setscheduler(thread->thread_task, SCHED_FIFO, ¶m); + } else if (bh_priority > MAX_RT_PRIO && bh_priority <= MAX_PRIO) { + priv->bh_thread.prio = bh_priority; + unifi_trace(priv, UDBG1, "%s thread priority = %d\n", + thread->name, PRIO_TO_NICE(bh_priority)); + set_user_nice(thread->thread_task, PRIO_TO_NICE(bh_priority)); + } else { + priv->bh_thread.prio = DEFAULT_PRIO; + unifi_warning(priv, "%s thread unsupported (%d) priority\n", + thread->name, bh_priority); + } + } else { + priv->bh_thread.prio = DEFAULT_PRIO; + } + unifi_trace(priv, UDBG2, "Started %s thread\n", thread->name); + + return 0; } /* uf_start_thread() */ @@ -92,18 +88,18 @@ int uf_start_thread(unifi_priv_t *priv, * * --------------------------------------------------------------------------- */ -void uf_stop_thread(unifi_priv_t *priv, struct uf_thread *thread) + void +uf_stop_thread(unifi_priv_t *priv, struct uf_thread *thread) { - if (!thread->thread_task) { - unifi_notice(priv, "%s thread is already stopped\n", - thread->name); - return; - } + if (!thread->thread_task) { + unifi_notice(priv, "%s thread is already stopped\n", thread->name); + return; + } - unifi_trace(priv, UDBG2, "Stopping %s thread\n", thread->name); + unifi_trace(priv, UDBG2, "Stopping %s thread\n", thread->name); - kthread_stop(thread->thread_task); - thread->thread_task = NULL; + kthread_stop(thread->thread_task); + thread->thread_task = NULL; } /* uf_stop_thread() */ @@ -122,24 +118,23 @@ void uf_stop_thread(unifi_priv_t *priv, struct uf_thread *thread) * * --------------------------------------------------------------------------- */ -void + void uf_wait_for_thread_to_stop(unifi_priv_t *priv, struct uf_thread *thread) { - /* - * kthread_stop() cannot handle the thread exiting while - * kthread_should_stop() is false, so sleep until kthread_stop() - * wakes us up - */ - unifi_trace(priv, UDBG2, "%s waiting for the stop signal.\n", - thread->name); - set_current_state(TASK_INTERRUPTIBLE); - if (!kthread_should_stop()) { - unifi_trace(priv, UDBG2, "%s schedule....\n", thread->name); - schedule(); - } - - thread->thread_task = NULL; - unifi_trace(priv, UDBG2, "%s exiting....\n", thread->name); + /* + * kthread_stop() cannot handle the thread exiting while + * kthread_should_stop() is false, so sleep until kthread_stop() + * wakes us up. + */ + unifi_trace(priv, UDBG2, "%s waiting for the stop signal.\n", thread->name); + set_current_state(TASK_INTERRUPTIBLE); + if (!kthread_should_stop()) { + unifi_trace(priv, UDBG2, "%s schedule....\n", thread->name); + schedule(); + } + + thread->thread_task = NULL; + unifi_trace(priv, UDBG2, "%s exiting....\n", thread->name); } /* uf_wait_for_thread_to_stop() */ @@ -160,41 +155,39 @@ uf_wait_for_thread_to_stop(unifi_priv_t *priv, struct uf_thread *thread) * None. * --------------------------------------------------------------------------- */ -static void + static void handle_bh_error(unifi_priv_t *priv) { - netInterface_priv_t *interfacePriv; - u8 conf_param = CONFIG_IND_ERROR; - u8 interfaceTag; + u8 conf_param = CONFIG_IND_ERROR; + u8 interfaceTag = 0; /* used as a loop counter */ - /* Block unifi_run_bh() until the error has been handled. */ - priv->bh_thread.block_thread = 1; + /* Block unifi_run_bh() until the error has been handled. */ + priv->bh_thread.block_thread = 1; - /* Consider UniFi to be uninitialised */ - priv->init_progress = UNIFI_INIT_NONE; + /* Consider UniFi to be uninitialised */ + priv->init_progress = UNIFI_INIT_NONE; - /* Stop the network traffic */ - for (interfaceTag = 0; - interfaceTag < CSR_WIFI_NUM_INTERFACES; interfaceTag++) { - interfacePriv = priv->interfacePriv[interfaceTag]; - if (interfacePriv->netdev_registered) - netif_carrier_off(priv->netdev[interfaceTag]); - } + /* Stop the network traffic */ + for( interfaceTag =0; interfaceTag interfacePriv[interfaceTag]; + if (interfacePriv->netdev_registered == 1) { + netif_carrier_off(priv->netdev[interfaceTag]); + } + } #ifdef CSR_NATIVE_LINUX - /* Force any client waiting on an mlme_wait_for_reply() to abort. */ - uf_abort_mlme(priv); + /* Force any client waiting on an mlme_wait_for_reply() to abort. */ + uf_abort_mlme(priv); - /* Cancel any pending workqueue tasks */ - flush_workqueue(priv->unifi_workqueue); + /* Cancel any pending workqueue tasks */ + flush_workqueue(priv->unifi_workqueue); #endif /* CSR_NATIVE_LINUX */ - unifi_error(priv, - "handle_bh_error: fatal error is reported to the SME.\n"); - /* Notify the clients (SME or unifi_manager) for the error. */ - ul_log_config_ind(priv, &conf_param, sizeof(u8)); + unifi_error(priv, "handle_bh_error: fatal error is reported to the SME.\n"); + /* Notify the clients (SME or unifi_manager) for the error. */ + ul_log_config_ind(priv, &conf_param, sizeof(u8)); } /* handle_bh_error() */ diff --git a/trunk/drivers/staging/csr/csr_formatted_io.c b/trunk/drivers/staging/csr/csr_formatted_io.c new file mode 100644 index 000000000000..7213cc8fb577 --- /dev/null +++ b/trunk/drivers/staging/csr/csr_formatted_io.c @@ -0,0 +1,27 @@ +/***************************************************************************** + + (c) Cambridge Silicon Radio Limited 2010 + All rights reserved and confidential information of CSR + + Refer to LICENSE.txt included with this source for details + on the license terms. + +*****************************************************************************/ +#include +#include "csr_formatted_io.h" + +s32 CsrSnprintf(char *dest, size_t n, const char *fmt, ...) +{ + s32 r; + va_list args; + va_start(args, fmt); + r = vsnprintf(dest, n, fmt, args); + va_end(args); + + if (dest && (n > 0)) + { + dest[n - 1] = '\0'; + } + + return r; +} diff --git a/trunk/drivers/staging/csr/csr_formatted_io.h b/trunk/drivers/staging/csr/csr_formatted_io.h new file mode 100644 index 000000000000..2e238cb98d51 --- /dev/null +++ b/trunk/drivers/staging/csr/csr_formatted_io.h @@ -0,0 +1,25 @@ +#ifndef CSR_FORMATTED_IO_H__ +#define CSR_FORMATTED_IO_H__ +/***************************************************************************** + + (c) Cambridge Silicon Radio Limited 2010 + All rights reserved and confidential information of CSR + + Refer to LICENSE.txt included with this source for details + on the license terms. + +*****************************************************************************/ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +s32 CsrSnprintf(char *dest, size_t n, const char *fmt, ...); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/trunk/drivers/staging/csr/csr_framework_ext.c b/trunk/drivers/staging/csr/csr_framework_ext.c index f91a4bf4e68f..12e7ddf3220a 100644 --- a/trunk/drivers/staging/csr/csr_framework_ext.c +++ b/trunk/drivers/staging/csr/csr_framework_ext.c @@ -12,9 +12,20 @@ #include #include #include + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 34) +#include +#endif + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 19) #include +#endif +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 27) +#include +#else #include -#include +#endif + #include #include "csr_framework_ext.h" diff --git a/trunk/drivers/staging/csr/csr_panic.c b/trunk/drivers/staging/csr/csr_panic.c index 095f7fa3ae2c..353a829bb74c 100644 --- a/trunk/drivers/staging/csr/csr_panic.c +++ b/trunk/drivers/staging/csr/csr_panic.c @@ -9,6 +9,7 @@ *****************************************************************************/ #include +#include #include #include "csr_panic.h" diff --git a/trunk/drivers/staging/csr/csr_time.c b/trunk/drivers/staging/csr/csr_time.c index 7b597f7622a2..83586ca34e8c 100644 --- a/trunk/drivers/staging/csr/csr_time.c +++ b/trunk/drivers/staging/csr/csr_time.c @@ -10,6 +10,13 @@ #include #include + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 33) +#elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 16) +#include +#include +#endif + #include #include @@ -17,18 +24,20 @@ CsrTime CsrTimeGet(CsrTime *high) { - struct timespec ts; - u64 time; - CsrTime low; + struct timespec ts; + u64 time; + CsrTime low; - ts = current_kernel_time(); - time = (u64) ts.tv_sec * 1000000 + ts.tv_nsec / 1000; + ts = current_kernel_time(); + time = (u64) ts.tv_sec * 1000000 + ts.tv_nsec / 1000; - if (high != NULL) - *high = (CsrTime) ((time >> 32) & 0xFFFFFFFF); + if (high != NULL) + { + *high = (CsrTime) ((time >> 32) & 0xFFFFFFFF); + } - low = (CsrTime) (time & 0xFFFFFFFF); + low = (CsrTime) (time & 0xFFFFFFFF); - return low; + return low; } EXPORT_SYMBOL_GPL(CsrTimeGet); diff --git a/trunk/drivers/staging/csr/csr_wifi_hip_card_sdio.c b/trunk/drivers/staging/csr/csr_wifi_hip_card_sdio.c index cf148a0fec6a..44ab00c53fec 100644 --- a/trunk/drivers/staging/csr/csr_wifi_hip_card_sdio.c +++ b/trunk/drivers/staging/csr/csr_wifi_hip_card_sdio.c @@ -1612,13 +1612,13 @@ static CsrResult card_allocate_memory_resources(card_t *card) /* Reset any state carried forward from a previous life */ card->fh_command_queue.q_rd_ptr = 0; card->fh_command_queue.q_wr_ptr = 0; - (void)scnprintf(card->fh_command_queue.name, UNIFI_QUEUE_NAME_MAX_LENGTH, + (void)CsrSnprintf(card->fh_command_queue.name, UNIFI_QUEUE_NAME_MAX_LENGTH, "fh_cmd_q"); for (i = 0; i < UNIFI_NO_OF_TX_QS; i++) { card->fh_traffic_queue[i].q_rd_ptr = 0; card->fh_traffic_queue[i].q_wr_ptr = 0; - (void)scnprintf(card->fh_traffic_queue[i].name, + (void)CsrSnprintf(card->fh_traffic_queue[i].name, UNIFI_QUEUE_NAME_MAX_LENGTH, "fh_data_q%d", i); } #ifndef CSR_WIFI_HIP_TA_DISABLE @@ -1826,13 +1826,13 @@ static void card_init_soft_queues(card_t *card) /* Reset any state carried forward from a previous life */ card->fh_command_queue.q_rd_ptr = 0; card->fh_command_queue.q_wr_ptr = 0; - (void)scnprintf(card->fh_command_queue.name, UNIFI_QUEUE_NAME_MAX_LENGTH, + (void)CsrSnprintf(card->fh_command_queue.name, UNIFI_QUEUE_NAME_MAX_LENGTH, "fh_cmd_q"); for (i = 0; i < UNIFI_NO_OF_TX_QS; i++) { card->fh_traffic_queue[i].q_rd_ptr = 0; card->fh_traffic_queue[i].q_wr_ptr = 0; - (void)scnprintf(card->fh_traffic_queue[i].name, + (void)CsrSnprintf(card->fh_traffic_queue[i].name, UNIFI_QUEUE_NAME_MAX_LENGTH, "fh_data_q%d", i); } #ifndef CSR_WIFI_HIP_TA_DISABLE diff --git a/trunk/drivers/staging/csr/csr_wifi_hip_download.c b/trunk/drivers/staging/csr/csr_wifi_hip_download.c index 6db672caaa02..8e4a4608ba5c 100644 --- a/trunk/drivers/staging/csr/csr_wifi_hip_download.c +++ b/trunk/drivers/staging/csr/csr_wifi_hip_download.c @@ -250,7 +250,6 @@ static CsrResult do_patch_convert_download(card_t *card, void *dlpriv, xbv1_t *p if (r != CSR_RESULT_SUCCESS) { unifi_error(card->ospriv, "Failed to find BOOT_LOADER_CONTROL\n"); - kfree(pfw); return CSR_RESULT_FAILURE; } @@ -266,7 +265,6 @@ static CsrResult do_patch_convert_download(card_t *card, void *dlpriv, xbv1_t *p desc = unifi_fw_open_buffer(card->ospriv, pfw, psize); if (!desc) { - kfree(pfw); return CSR_WIFI_HIP_RESULT_NO_MEMORY; } diff --git a/trunk/drivers/staging/csr/csr_wifi_hip_send.c b/trunk/drivers/staging/csr/csr_wifi_hip_send.c index 86aa23cefe30..684d30459d75 100644 --- a/trunk/drivers/staging/csr/csr_wifi_hip_send.c +++ b/trunk/drivers/staging/csr/csr_wifi_hip_send.c @@ -172,8 +172,13 @@ static CsrResult send_signal(card_t *card, const u8 *sigptr, u32 siglen, { const u8 *sig = sigptr; - unifi_error(card->ospriv, "Signal(%d): %*ph\n", siglen, - 16, sig); + unifi_error(card->ospriv, "Signal(%d): %02x %02x %02x %02x %02x %02x %02x %02x" + " %02x %02x %02x %02x %02x %02x %02x %02x\n", + siglen, + sig[0], sig[1], sig[2], sig[3], + sig[4], sig[5], sig[6], sig[7], + sig[8], sig[9], sig[10], sig[11], + sig[12], sig[13], sig[14], sig[15]); unifi_error(card->ospriv, "Bulkdata pointer %p(%d), %p(%d)\n", bulkdata != NULL?bulkdata->d[0].os_data_ptr : NULL, bulkdata != NULL?bulkdata->d[0].data_length : 0, diff --git a/trunk/drivers/staging/csr/csr_wifi_hip_udi.c b/trunk/drivers/staging/csr/csr_wifi_hip_udi.c index a65b822db698..07cfd36c4971 100644 --- a/trunk/drivers/staging/csr/csr_wifi_hip_udi.c +++ b/trunk/drivers/staging/csr/csr_wifi_hip_udi.c @@ -64,104 +64,104 @@ s32 unifi_print_status(card_t *card, char *str, s32 *remain) } i = n = 0; - written = scnprintf(p, remaining, "Chip ID %u\n", + written = CsrSnprintf(p, remaining, "Chip ID %u\n", (u16)card->chip_id); UNIFI_SNPRINTF_RET(p, remaining, written); - written = scnprintf(p, remaining, "Chip Version %04X\n", + written = CsrSnprintf(p, remaining, "Chip Version %04X\n", card->chip_version); UNIFI_SNPRINTF_RET(p, remaining, written); - written = scnprintf(p, remaining, "HIP v%u.%u\n", + written = CsrSnprintf(p, remaining, "HIP v%u.%u\n", (card->config_data.version >> 8) & 0xFF, card->config_data.version & 0xFF); UNIFI_SNPRINTF_RET(p, remaining, written); - written = scnprintf(p, remaining, "Build %u: %s\n", + written = CsrSnprintf(p, remaining, "Build %lu: %s\n", card->build_id, card->build_id_string); UNIFI_SNPRINTF_RET(p, remaining, written); cfg = &card->config_data; - written = scnprintf(p, remaining, "sdio ctrl offset %u\n", + written = CsrSnprintf(p, remaining, "sdio ctrl offset %u\n", cfg->sdio_ctrl_offset); UNIFI_SNPRINTF_RET(p, remaining, written); - written = scnprintf(p, remaining, "fromhost sigbuf handle %u\n", + written = CsrSnprintf(p, remaining, "fromhost sigbuf handle %u\n", cfg->fromhost_sigbuf_handle); UNIFI_SNPRINTF_RET(p, remaining, written); - written = scnprintf(p, remaining, "tohost_sigbuf_handle %u\n", + written = CsrSnprintf(p, remaining, "tohost_sigbuf_handle %u\n", cfg->tohost_sigbuf_handle); UNIFI_SNPRINTF_RET(p, remaining, written); - written = scnprintf(p, remaining, "num_fromhost_sig_frags %u\n", + written = CsrSnprintf(p, remaining, "num_fromhost_sig_frags %u\n", cfg->num_fromhost_sig_frags); UNIFI_SNPRINTF_RET(p, remaining, written); - written = scnprintf(p, remaining, "num_tohost_sig_frags %u\n", + written = CsrSnprintf(p, remaining, "num_tohost_sig_frags %u\n", cfg->num_tohost_sig_frags); UNIFI_SNPRINTF_RET(p, remaining, written); - written = scnprintf(p, remaining, "num_fromhost_data_slots %u\n", + written = CsrSnprintf(p, remaining, "num_fromhost_data_slots %u\n", cfg->num_fromhost_data_slots); UNIFI_SNPRINTF_RET(p, remaining, written); - written = scnprintf(p, remaining, "num_tohost_data_slots %u\n", + written = CsrSnprintf(p, remaining, "num_tohost_data_slots %u\n", cfg->num_tohost_data_slots); UNIFI_SNPRINTF_RET(p, remaining, written); - written = scnprintf(p, remaining, "data_slot_size %u\n", + written = CsrSnprintf(p, remaining, "data_slot_size %u\n", cfg->data_slot_size); UNIFI_SNPRINTF_RET(p, remaining, written); /* Added by protocol version 0x0001 */ - written = scnprintf(p, remaining, "overlay_size %u\n", + written = CsrSnprintf(p, remaining, "overlay_size %u\n", (u16)cfg->overlay_size); UNIFI_SNPRINTF_RET(p, remaining, written); /* Added by protocol version 0x0300 */ - written = scnprintf(p, remaining, "data_slot_round %u\n", + written = CsrSnprintf(p, remaining, "data_slot_round %u\n", cfg->data_slot_round); UNIFI_SNPRINTF_RET(p, remaining, written); - written = scnprintf(p, remaining, "sig_frag_size %u\n", + written = CsrSnprintf(p, remaining, "sig_frag_size %u\n", cfg->sig_frag_size); UNIFI_SNPRINTF_RET(p, remaining, written); /* Added by protocol version 0x0300 */ - written = scnprintf(p, remaining, "tohost_sig_pad %u\n", + written = CsrSnprintf(p, remaining, "tohost_sig_pad %u\n", cfg->tohost_signal_padding); UNIFI_SNPRINTF_RET(p, remaining, written); - written = scnprintf(p, remaining, "\nInternal state:\n"); + written = CsrSnprintf(p, remaining, "\nInternal state:\n"); UNIFI_SNPRINTF_RET(p, remaining, written); - written = scnprintf(p, remaining, "Last PHY PANIC: %04x:%04x\n", + written = CsrSnprintf(p, remaining, "Last PHY PANIC: %04x:%04x\n", card->last_phy_panic_code, card->last_phy_panic_arg); UNIFI_SNPRINTF_RET(p, remaining, written); - written = scnprintf(p, remaining, "Last MAC PANIC: %04x:%04x\n", + written = CsrSnprintf(p, remaining, "Last MAC PANIC: %04x:%04x\n", card->last_mac_panic_code, card->last_mac_panic_arg); UNIFI_SNPRINTF_RET(p, remaining, written); - written = scnprintf(p, remaining, "fhsr: %u\n", + written = CsrSnprintf(p, remaining, "fhsr: %u\n", (u16)card->from_host_signals_r); UNIFI_SNPRINTF_RET(p, remaining, written); - written = scnprintf(p, remaining, "fhsw: %u\n", + written = CsrSnprintf(p, remaining, "fhsw: %u\n", (u16)card->from_host_signals_w); UNIFI_SNPRINTF_RET(p, remaining, written); - written = scnprintf(p, remaining, "thsr: %u\n", + written = CsrSnprintf(p, remaining, "thsr: %u\n", (u16)card->to_host_signals_r); UNIFI_SNPRINTF_RET(p, remaining, written); - written = scnprintf(p, remaining, "thsw: %u\n", + written = CsrSnprintf(p, remaining, "thsw: %u\n", (u16)card->to_host_signals_w); UNIFI_SNPRINTF_RET(p, remaining, written); - written = scnprintf(p, remaining, - "fh buffer contains: %d signals, %td bytes\n", + written = CsrSnprintf(p, remaining, + "fh buffer contains: %u signals, %u bytes\n", card->fh_buffer.count, card->fh_buffer.ptr - card->fh_buffer.buf); UNIFI_SNPRINTF_RET(p, remaining, written); - written = scnprintf(p, remaining, "paused: "); + written = CsrSnprintf(p, remaining, "paused: "); UNIFI_SNPRINTF_RET(p, remaining, written); for (i = 0; i < sizeof(card->tx_q_paused_flag) / sizeof(card->tx_q_paused_flag[0]); i++) { - written = scnprintf(p, remaining, card->tx_q_paused_flag[i]?"1" : "0"); + written = CsrSnprintf(p, remaining, card->tx_q_paused_flag[i]?"1" : "0"); UNIFI_SNPRINTF_RET(p, remaining, written); } - written = scnprintf(p, remaining, "\n"); + written = CsrSnprintf(p, remaining, "\n"); UNIFI_SNPRINTF_RET(p, remaining, written); - written = scnprintf(p, remaining, + written = CsrSnprintf(p, remaining, "fh command q: %u waiting, %u free of %u:\n", CSR_WIFI_HIP_Q_SLOTS_USED(&card->fh_command_queue), CSR_WIFI_HIP_Q_SLOTS_FREE(&card->fh_command_queue), @@ -169,7 +169,7 @@ s32 unifi_print_status(card_t *card, char *str, s32 *remain) UNIFI_SNPRINTF_RET(p, remaining, written); for (i = 0; i < UNIFI_NO_OF_TX_QS; i++) { - written = scnprintf(p, remaining, + written = CsrSnprintf(p, remaining, "fh traffic q[%u]: %u waiting, %u free of %u:\n", i, CSR_WIFI_HIP_Q_SLOTS_USED(&card->fh_traffic_queue[i]), @@ -178,58 +178,58 @@ s32 unifi_print_status(card_t *card, char *str, s32 *remain) UNIFI_SNPRINTF_RET(p, remaining, written); } - written = scnprintf(p, remaining, "fh data slots free: %u\n", + written = CsrSnprintf(p, remaining, "fh data slots free: %u\n", card->from_host_data?CardGetFreeFromHostDataSlots(card) : 0); UNIFI_SNPRINTF_RET(p, remaining, written); - written = scnprintf(p, remaining, "From host data slots:"); + written = CsrSnprintf(p, remaining, "From host data slots:"); UNIFI_SNPRINTF_RET(p, remaining, written); n = card->config_data.num_fromhost_data_slots; for (i = 0; i < n && card->from_host_data; i++) { - written = scnprintf(p, remaining, " %u", + written = CsrSnprintf(p, remaining, " %u", (u16)card->from_host_data[i].bd.data_length); UNIFI_SNPRINTF_RET(p, remaining, written); } - written = scnprintf(p, remaining, "\n"); + written = CsrSnprintf(p, remaining, "\n"); UNIFI_SNPRINTF_RET(p, remaining, written); - written = scnprintf(p, remaining, "To host data slots:"); + written = CsrSnprintf(p, remaining, "To host data slots:"); UNIFI_SNPRINTF_RET(p, remaining, written); n = card->config_data.num_tohost_data_slots; for (i = 0; i < n && card->to_host_data; i++) { - written = scnprintf(p, remaining, " %u", + written = CsrSnprintf(p, remaining, " %u", (u16)card->to_host_data[i].data_length); UNIFI_SNPRINTF_RET(p, remaining, written); } - written = scnprintf(p, remaining, "\n"); + written = CsrSnprintf(p, remaining, "\n"); UNIFI_SNPRINTF_RET(p, remaining, written); #ifdef CSR_UNSAFE_SDIO_ACCESS - written = scnprintf(p, remaining, "Host State: %s\n", states[card->host_state]); + written = CsrSnprintf(p, remaining, "Host State: %s\n", states[card->host_state]); UNIFI_SNPRINTF_RET(p, remaining, written); r = unifi_check_io_status(card, &iostate); if (iostate == 1) { - written = scnprintf(p, remaining, "I/O Check: F1 disabled\n"); + written = CsrSnprintf(p, remaining, "I/O Check: F1 disabled\n"); UNIFI_SNPRINTF_RET(p, remaining, written); } else { if (iostate == 1) { - written = scnprintf(p, remaining, "I/O Check: pending interrupt\n"); + written = CsrSnprintf(p, remaining, "I/O Check: pending interrupt\n"); UNIFI_SNPRINTF_RET(p, remaining, written); } - written = scnprintf(p, remaining, "BH reason interrupt = %d\n", + written = CsrSnprintf(p, remaining, "BH reason interrupt = %d\n", card->bh_reason_unifi); UNIFI_SNPRINTF_RET(p, remaining, written); - written = scnprintf(p, remaining, "BH reason host = %d\n", + written = CsrSnprintf(p, remaining, "BH reason host = %d\n", card->bh_reason_host); UNIFI_SNPRINTF_RET(p, remaining, written); @@ -238,26 +238,26 @@ s32 unifi_print_status(card_t *card, char *str, s32 *remain) r = unifi_read_8_or_16(card, card->sdio_ctrl_addr + 2, &b); if ((r == CSR_RESULT_SUCCESS) && (!(b & 0x80))) { - written = scnprintf(p, remaining, "fhsr: %u (driver thinks is %u)\n", + written = CsrSnprintf(p, remaining, "fhsr: %u (driver thinks is %u)\n", b, card->from_host_signals_r); UNIFI_SNPRINTF_RET(p, remaining, written); break; } } iostate = unifi_read_shared_count(card, card->sdio_ctrl_addr + 4); - written = scnprintf(p, remaining, "thsw: %u (driver thinks is %u)\n", + written = CsrSnprintf(p, remaining, "thsw: %u (driver thinks is %u)\n", iostate, card->to_host_signals_w); UNIFI_SNPRINTF_RET(p, remaining, written); } #endif - written = scnprintf(p, remaining, "\nStats:\n"); + written = CsrSnprintf(p, remaining, "\nStats:\n"); UNIFI_SNPRINTF_RET(p, remaining, written); - written = scnprintf(p, remaining, "Total SDIO bytes: R=%u W=%u\n", + written = CsrSnprintf(p, remaining, "Total SDIO bytes: R=%lu W=%lu\n", card->sdio_bytes_read, card->sdio_bytes_written); UNIFI_SNPRINTF_RET(p, remaining, written); - written = scnprintf(p, remaining, "Interrupts generated on card: %u\n", + written = CsrSnprintf(p, remaining, "Interrupts generated on card: %lu\n", card->unifi_interrupt_seq); UNIFI_SNPRINTF_RET(p, remaining, written); diff --git a/trunk/drivers/staging/csr/csr_wifi_hip_unifi.h b/trunk/drivers/staging/csr/csr_wifi_hip_unifi.h index 2923e2ef12f2..dc3c60b49702 100644 --- a/trunk/drivers/staging/csr/csr_wifi_hip_unifi.h +++ b/trunk/drivers/staging/csr/csr_wifi_hip_unifi.h @@ -98,6 +98,7 @@ extern "C" { #include "csr_framework_ext.h" /* from the synergy porting folder */ #include "csr_sdio.h" /* from the synergy porting folder */ #include "csr_macro.h" /* from the synergy porting folder */ +#include "csr_formatted_io.h" /* from the synergy gsp folder */ #include "csr_wifi_result.h" /* Utility MACROS. Note that UNIFI_MAC_ADDRESS_CMP returns TRUE on success */ diff --git a/trunk/drivers/staging/csr/drv.c b/trunk/drivers/staging/csr/drv.c index 249758076a75..b2c27f4f03d4 100644 --- a/trunk/drivers/staging/csr/drv.c +++ b/trunk/drivers/staging/csr/drv.c @@ -15,6 +15,8 @@ * --------------------------------------------------------------------------- */ + + /* * Porting Notes: * Part of this file contains an example for how to glue the OS layer @@ -35,7 +37,6 @@ #include #include #include -#include #include "csr_wifi_hip_unifiversion.h" #include "unifi_priv.h" @@ -123,7 +124,11 @@ static void udi_set_log_filter(ul_client_t *pcli, /* Mutex to protect access to priv->sme_cli */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37) DEFINE_SEMAPHORE(udi_mutex); +#else +DECLARE_MUTEX(udi_mutex); +#endif s32 CsrHipResultToStatus(CsrResult csrResult) { @@ -1975,6 +1980,18 @@ uf_sme_queue_message(unifi_priv_t *priv, u8 *buffer, int length) } /* uf_sme_queue_message() */ #endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) +#define UF_DEVICE_CREATE(_class, _parent, _devno, _priv, _fmt, _args) \ + device_create(_class, _parent, _devno, _priv, _fmt, _args) +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) +#define UF_DEVICE_CREATE(_class, _parent, _devno, _priv, _fmt, _args) \ + device_create_drvdata(_class, _parent, _devno, _priv, _fmt, _args) +#else +#define UF_DEVICE_CREATE(_class, _parent, _devno, _priv, _fmt, _args) \ + device_create(_class, _parent, _devno, _fmt, _args) +#endif + /* **************************************************************************** * @@ -1992,6 +2009,17 @@ static struct file_operations unifi_fops = { .poll = unifi_poll, }; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) +#define UF_DEVICE_CREATE(_class, _parent, _devno, _priv, _fmt, _args) \ + device_create(_class, _parent, _devno, _priv, _fmt, _args) +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) +#define UF_DEVICE_CREATE(_class, _parent, _devno, _priv, _fmt, _args) \ + device_create_drvdata(_class, _parent, _devno, _priv, _fmt, _args) +#else +#define UF_DEVICE_CREATE(_class, _parent, _devno, _priv, _fmt, _args) \ + device_create(_class, _parent, _devno, _fmt, _args) +#endif + static dev_t unifi_first_devno; static struct class *unifi_class; @@ -2014,11 +2042,11 @@ int uf_create_device_nodes(unifi_priv_t *priv, int bus_id) } #ifdef SDIO_EXPORTS_STRUCT_DEVICE - if (!device_create(unifi_class, priv->unifi_device, - devno, priv, "unifi%d", bus_id)) { + if (!UF_DEVICE_CREATE(unifi_class, priv->unifi_device, + devno, priv, "unifi%d", bus_id)) { #else - priv->unifi_device = device_create(unifi_class, NULL, - devno, priv, "unifi%d", bus_id); + priv->unifi_device = UF_DEVICE_CREATE(unifi_class, NULL, + devno, priv, "unifi%d", bus_id); if (priv->unifi_device == NULL) { #endif /* SDIO_EXPORTS_STRUCT_DEVICE */ @@ -2040,13 +2068,13 @@ int uf_create_device_nodes(unifi_priv_t *priv, int bus_id) return r; } - if (!device_create(unifi_class, + if (!UF_DEVICE_CREATE(unifi_class, #ifdef SDIO_EXPORTS_STRUCT_DEVICE - priv->unifi_device, + priv->unifi_device, #else - NULL, + NULL, #endif /* SDIO_EXPORTS_STRUCT_DEVICE */ - devno, priv, "unifiudi%d", bus_id)) { + devno, priv, "unifiudi%d", bus_id)) { device_destroy(unifi_class, priv->unifi_cdev.dev); cdev_del(&priv->unifiudi_cdev); cdev_del(&priv->unifi_cdev); diff --git a/trunk/drivers/staging/csr/firmware.c b/trunk/drivers/staging/csr/firmware.c index b6d8a6e52915..d14e11839618 100644 --- a/trunk/drivers/staging/csr/firmware.c +++ b/trunk/drivers/staging/csr/firmware.c @@ -286,7 +286,7 @@ uf_run_unifihelper(unifi_priv_t *priv) unifi_trace(priv, UDBG2, "running %s %s %s\n", argv[0], argv[1], argv[2]); - r = call_usermodehelper(argv[0], argv, envp, UMH_WAIT_EXEC); + r = call_usermodehelper(argv[0], argv, envp, 0); return r; #else @@ -402,7 +402,9 @@ int uf_release_firmware_files(unifi_priv_t *priv) int uf_release_firmware(unifi_priv_t *priv, struct dlpriv *to_free) { if (to_free != NULL) { - release_firmware((const struct firmware *)to_free->fw_desc); + if (to_free->fw_desc != NULL) { + release_firmware((const struct firmware *)to_free->fw_desc); + } to_free->fw_desc = NULL; to_free->dl_data = NULL; to_free->dl_len = 0; diff --git a/trunk/drivers/staging/csr/io.c b/trunk/drivers/staging/csr/io.c index caf48e3120ca..e6503d9620a4 100644 --- a/trunk/drivers/staging/csr/io.c +++ b/trunk/drivers/staging/csr/io.c @@ -31,7 +31,6 @@ * --------------------------------------------------------------------------- */ #include -#include #include "csr_wifi_hip_unifi.h" #include "csr_wifi_hip_unifiversion.h" @@ -39,6 +38,7 @@ #include "unifiio.h" #include "unifi_priv.h" + /* * Array of pointers to context structs for unifi devices that are present. * The index in the array corresponds to the wlan interface number @@ -70,7 +70,11 @@ static int In_use[MAX_UNIFI_DEVS]; * Mutex to prevent UDI clients to open the character device before the priv * is created and initialised. */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37) DEFINE_SEMAPHORE(Unifi_instance_mutex); +#else +DECLARE_MUTEX(Unifi_instance_mutex); +#endif /* * When the device is removed, unregister waits on Unifi_cleanup_wq * until all the UDI clients release the character device. @@ -173,6 +177,21 @@ uf_register_netdev(unifi_priv_t *priv, int interfaceTag) /* The device is registed */ interfacePriv->netdev_registered = 1; +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) +#ifdef CONFIG_NET_SCHED + /* + * IMPORTANT: + * uf_install_qdisc() holds the network device lock, we can not + * install the qdisk before the network device is registered. + */ + r = uf_install_qdisc(priv->netdev[interfaceTag]); + if (r) { + unifi_error(priv, "Failed to install qdisc\n"); + return r; + } +#endif /* CONFIG_NET_SCHED */ +#endif /* LINUX_VERSION_CODE */ + #ifdef CSR_SUPPORT_SME /* * Register the inet handler; it notifies us for changes in the IP address. @@ -328,7 +347,7 @@ register_unifi_sdio(CsrSdioFunction *sdio_dev, int bus_id, struct device *dev) /* * We use the slot number as unifi device index. */ - scnprintf(priv->proc_entry_name, 64, "driver/unifi%d", priv->instance); + snprintf(priv->proc_entry_name, 64, "driver/unifi%d", priv->instance); /* * The following complex casting is in place in order to eliminate 64-bit compilation warning * "cast to/from pointer from/to integer of different size" @@ -650,7 +669,7 @@ unregister_unifi_sdio(int bus_id) if(interfacePriv->netdev_registered) { netif_carrier_off(priv->netdev[interfaceTag]); - netif_tx_stop_all_queues(priv->netdev[interfaceTag]); + UF_NETIF_TX_STOP_ALL_QUEUES(priv->netdev[interfaceTag]); } } @@ -885,54 +904,54 @@ uf_read_proc(char *page, char **start, off_t offset, int count, orig_p = p; - written = scnprintf(p, remain, "UniFi SDIO Driver: %s %s %s\n", + written = CsrSnprintf(p, remain, "UniFi SDIO Driver: %s %s %s\n", CSR_WIFI_VERSION, __DATE__, __TIME__); UNIFI_SNPRINTF_RET(p, remain, written); #ifdef CSR_SME_USERSPACE - written = scnprintf(p, remain, "SME: CSR userspace "); + written = CsrSnprintf(p, remain, "SME: CSR userspace "); UNIFI_SNPRINTF_RET(p, remain, written); #ifdef CSR_SUPPORT_WEXT - written = scnprintf(p, remain, "with WEXT support\n"); + written = CsrSnprintf(p, remain, "with WEXT support\n"); #else - written = scnprintf(p, remain, "\n"); + written = CsrSnprintf(p, remain, "\n"); #endif /* CSR_SUPPORT_WEXT */ UNIFI_SNPRINTF_RET(p, remain, written); #endif /* CSR_SME_USERSPACE */ #ifdef CSR_NATIVE_LINUX - written = scnprintf(p, remain, "SME: native\n"); + written = CsrSnprintf(p, remain, "SME: native\n"); UNIFI_SNPRINTF_RET(p, remain, written); #endif #ifdef CSR_SUPPORT_SME - written = scnprintf(p, remain, - "Firmware (ROM) build:%u, Patch:%u\n", + written = CsrSnprintf(p, remain, + "Firmware (ROM) build:%lu, Patch:%lu\n", priv->card_info.fw_build, priv->sme_versions.firmwarePatch); UNIFI_SNPRINTF_RET(p, remain, written); #endif p += unifi_print_status(priv->card, p, &remain); - written = scnprintf(p, remain, "Last dbg str: %s\n", + written = CsrSnprintf(p, remain, "Last dbg str: %s\n", priv->last_debug_string); UNIFI_SNPRINTF_RET(p, remain, written); - written = scnprintf(p, remain, "Last dbg16:"); + written = CsrSnprintf(p, remain, "Last dbg16:"); UNIFI_SNPRINTF_RET(p, remain, written); for (i = 0; i < 8; i++) { - written = scnprintf(p, remain, " %04X", + written = CsrSnprintf(p, remain, " %04X", priv->last_debug_word16[i]); UNIFI_SNPRINTF_RET(p, remain, written); } - written = scnprintf(p, remain, "\n"); + written = CsrSnprintf(p, remain, "\n"); UNIFI_SNPRINTF_RET(p, remain, written); - written = scnprintf(p, remain, " "); + written = CsrSnprintf(p, remain, " "); UNIFI_SNPRINTF_RET(p, remain, written); for (; i < 16; i++) { - written = scnprintf(p, remain, " %04X", + written = CsrSnprintf(p, remain, " %04X", priv->last_debug_word16[i]); UNIFI_SNPRINTF_RET(p, remain, written); } - written = scnprintf(p, remain, "\n"); + written = CsrSnprintf(p, remain, "\n"); UNIFI_SNPRINTF_RET(p, remain, written); *start = page; diff --git a/trunk/drivers/staging/csr/monitor.c b/trunk/drivers/staging/csr/monitor.c index 7c524a18958e..628782ad641e 100644 --- a/trunk/drivers/staging/csr/monitor.c +++ b/trunk/drivers/staging/csr/monitor.c @@ -10,7 +10,6 @@ * --------------------------------------------------------------------------- */ -#include #include "unifi_priv.h" #ifdef UNIFI_SNIFF_ARPHRD @@ -24,6 +23,8 @@ #define ETH_P_80211_RAW ETH_P_ALL #endif + + /* * --------------------------------------------------------------------------- * uf_start_sniff @@ -191,7 +192,11 @@ netrx_radiotap(unifi_priv_t *priv, skb->dev = dev; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22) skb->mac_header = skb->data; +#else + skb->mac.raw = skb->data; +#endif skb->pkt_type = PACKET_OTHERHOST; skb->protocol = __constant_htons(ETH_P_80211_RAW); memset(skb->cb, 0, sizeof(skb->cb)); diff --git a/trunk/drivers/staging/csr/netdev.c b/trunk/drivers/staging/csr/netdev.c index 9a52ab408e1a..1e6e111a8e15 100644 --- a/trunk/drivers/staging/csr/netdev.c +++ b/trunk/drivers/staging/csr/netdev.c @@ -15,6 +15,7 @@ * --------------------------------------------------------------------------- */ + /* * Porting Notes: * This file implements the data plane of the UniFi linux driver. @@ -47,14 +48,59 @@ #include #include #include -#include + #include #include "csr_wifi_hip_unifi.h" #include "csr_wifi_hip_conversions.h" #include "unifi_priv.h" +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,13) +#include +#endif #include +/* ALLOW_Q_PAUSE: Pre 2.6.28 kernels do not support multiple driver queues (required for QoS). + * In order to support QoS in these kernels, multiple queues are implemented in the driver. But since + * there is only a single queue in the kernel (leading to multiple queues in the driver) there is no possibility + * of stopping a particular queue in the kernel. Stopping the single kernel queue leads to undesirable starvation + * of driver queues. One of the proposals is to not stop the kernel queue but to prevent dequeuing from the + * 'stopped' driver queue. Allow q pause is an experimental implementation of this scheme for pre 2.6.28 kernels. + * When NOT defined, queues are paused locally in the driver and packets are dequeued for transmission only from the + * unpaused queues. When Allow q pause is defined the kernel queue is stopped whenever any driver queue is paused. + */ +#define ALLOW_Q_PAUSE + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28) +#ifdef UNIFI_NET_NAME +#define UF_ALLOC_NETDEV(_dev, _size, _name, _setup, _num_of_queues) \ + do { \ + static char name[8]; \ + sprintf(name, "%s%s", UNIFI_NET_NAME, _name); \ + _dev = alloc_netdev_mq(_size, name, _setup, _num_of_queues); \ + } while (0); +#else +#define UF_ALLOC_NETDEV(_dev, _size, _name, _setup, _num_of_queues) \ + do { \ + _dev = alloc_etherdev_mq(_size, _num_of_queues); \ + } while (0); +#endif /* UNIFI_NET_NAME */ +#else +#ifdef UNIFI_NET_NAME +#define UF_ALLOC_NETDEV(_dev, _size, _name, _setup, _num_of_queues) \ + do { \ + static char name[8]; \ + sprintf(name, "%s%s", UNIFI_NET_NAME, _name); \ + _dev = alloc_netdev(_size, name, _setup); \ + } while (0); +#else +#define UF_ALLOC_NETDEV(_dev, _size, _name, _setup, _num_of_queues) \ + do { \ + _dev = alloc_etherdev(_size); \ + } while (0); +#endif /* UNIFI_NET_NAME */ +#endif /* LINUX_VERSION_CODE */ + + /* Wext handler is suported only if CSR_SUPPORT_WEXT is defined */ #ifdef CSR_SUPPORT_WEXT extern struct iw_handler_def unifi_iw_handler_def; @@ -73,8 +119,20 @@ static int uf_net_open(struct net_device *dev); static int uf_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); static int uf_net_stop(struct net_device *dev); static struct net_device_stats *uf_net_get_stats(struct net_device *dev); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28) static u16 uf_net_select_queue(struct net_device *dev, struct sk_buff *skb); +#endif +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32) static netdev_tx_t uf_net_xmit(struct sk_buff *skb, struct net_device *dev); +#else +static int uf_net_xmit(struct sk_buff *skb, struct net_device *dev); +#ifndef NETDEV_TX_OK +#define NETDEV_TX_OK 0 +#endif +#ifndef NETDEV_TX_BUSY +#define NETDEV_TX_BUSY 1 +#endif +#endif static void uf_set_multicast_list(struct net_device *dev); @@ -124,8 +182,62 @@ struct uf_tx_packet_data { unsigned long host_tag; }; +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) +static int uf_qdiscop_enqueue(struct sk_buff *skb, struct Qdisc* qd); +static int uf_qdiscop_requeue(struct sk_buff *skb, struct Qdisc* qd); +static struct sk_buff *uf_qdiscop_dequeue(struct Qdisc* qd); +static void uf_qdiscop_reset(struct Qdisc* qd); +static void uf_qdiscop_destroy(struct Qdisc* qd); +static int uf_qdiscop_dump(struct Qdisc *qd, struct sk_buff *skb); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,25) +static int uf_qdiscop_tune(struct Qdisc *qd, struct nlattr *opt); +static int uf_qdiscop_init(struct Qdisc *qd, struct nlattr *opt); +#else +static int uf_qdiscop_tune(struct Qdisc *qd, struct rtattr *opt); +static int uf_qdiscop_init(struct Qdisc *qd, struct rtattr *opt); +#endif +#endif + + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) +/* queueing discipline operations */ +static struct Qdisc_ops uf_qdisc_ops = +{ + .next = NULL, + .cl_ops = NULL, + .id = "UniFi Qdisc", + .priv_size = sizeof(struct uf_sched_data), + + .enqueue = uf_qdiscop_enqueue, + .dequeue = uf_qdiscop_dequeue, + .requeue = uf_qdiscop_requeue, + .drop = NULL, /* drop not needed since we are always the root qdisc */ + + .init = uf_qdiscop_init, + .reset = uf_qdiscop_reset, + .destroy = uf_qdiscop_destroy, + .change = uf_qdiscop_tune, + + .dump = uf_qdiscop_dump, +}; +#endif /* LINUX_VERSION_CODE */ + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28) +#define UF_QDISC_CREATE_DFLT(_dev, _ops, _root) +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) +#define UF_QDISC_CREATE_DFLT(_dev, _ops, _root) \ + qdisc_create_dflt(dev, netdev_get_tx_queue(_dev, 0), _ops, _root) +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20) +#define UF_QDISC_CREATE_DFLT(_dev, _ops, _root) \ + qdisc_create_dflt(dev, _ops, _root) +#else +#define UF_QDISC_CREATE_DFLT(_dev, _ops, _root) \ + qdisc_create_dflt(dev, _ops) +#endif /* LINUX_VERSION_CODE */ + #endif /* CONFIG_NET_SCHED */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29) static const struct net_device_ops uf_netdev_ops = { .ndo_open = uf_net_open, @@ -136,6 +248,7 @@ static const struct net_device_ops uf_netdev_ops = .ndo_set_rx_mode = uf_set_multicast_list, .ndo_select_queue = uf_net_select_queue, }; +#endif static u8 oui_rfc1042[P80211_OUI_LEN] = { 0x00, 0x00, 0x00 }; static u8 oui_8021h[P80211_OUI_LEN] = { 0x00, 0x00, 0xf8 }; @@ -197,7 +310,7 @@ uf_alloc_netdevice(CsrSdioFunction *sdio_dev, int bus_id) * The RedHat 9 redhat-config-network tool doesn't recognise wlan* devices, * so use "eth*" (like other wireless extns drivers). */ - dev = alloc_etherdev_mq(sizeof(unifi_priv_t) + sizeof(netInterface_priv_t), UNIFI_TRAFFIC_Q_MAX); + UF_ALLOC_NETDEV(dev, sizeof(unifi_priv_t)+sizeof(netInterface_priv_t), "%d", ether_setup, UNIFI_TRAFFIC_Q_MAX); if (dev == NULL) { return NULL; @@ -219,7 +332,22 @@ uf_alloc_netdevice(CsrSdioFunction *sdio_dev, int bus_id) priv->interfacePriv[0] = interfacePriv; /* Setup / override net_device fields */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29) dev->netdev_ops = &uf_netdev_ops; +#else + dev->open = uf_net_open; + dev->stop = uf_net_stop; + dev->hard_start_xmit = uf_net_xmit; + dev->do_ioctl = uf_net_ioctl; + + /* called by /proc/net/dev */ + dev->get_stats = uf_net_get_stats; + + dev->set_multicast_list = uf_set_multicast_list; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28) + dev->select_queue = uf_net_select_queue; +#endif +#endif #ifdef CSR_SUPPORT_WEXT dev->wireless_handlers = &unifi_iw_handler_def; @@ -312,13 +440,21 @@ uf_alloc_netdevice(CsrSdioFunction *sdio_dev, int bus_id) interfacePriv->connected = UnifiConnectedUnknown; /* -1 unknown, 0 no, 1 yes */ #ifdef USE_DRIVER_LOCK +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37) sema_init(&priv->lock, 1); +#else + init_MUTEX(&priv->lock); +#endif #endif /* USE_DRIVER_LOCK */ spin_lock_init(&priv->send_signal_lock); spin_lock_init(&priv->m4_lock); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37) sema_init(&priv->ba_mutex, 1); +#else + init_MUTEX(&priv->ba_mutex); +#endif #if (defined(CSR_WIFI_SECURITY_WAPI_ENABLE) && defined(CSR_WIFI_SECURITY_WAPI_SW_ENCRYPTION)) spin_lock_init(&priv->wapi_lock); @@ -351,8 +487,16 @@ uf_alloc_netdevice(CsrSdioFunction *sdio_dev, int bus_id) #endif #endif +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) +#ifdef CONFIG_NET_SCHED + /* Register the qdisc operations */ + register_qdisc(&uf_qdisc_ops); +#endif /* CONFIG_NET_SCHED */ +#endif /* LINUX_VERSION_CODE */ + priv->ref_count = 1; + priv->amp_client = NULL; priv->coredump_mode = 0; priv->ptest_mode = 0; @@ -422,7 +566,7 @@ uf_alloc_netdevice_for_other_interfaces(unifi_priv_t *priv, u16 interfaceTag) * The RedHat 9 redhat-config-network tool doesn't recognise wlan* devices, * so use "eth*" (like other wireless extns drivers). */ - dev = alloc_etherdev_mq(sizeof(netInterface_priv_t), 1); + UF_ALLOC_NETDEV(dev, sizeof(netInterface_priv_t), "%d", ether_setup, 1); if (dev == NULL) { return FALSE; } @@ -445,7 +589,19 @@ uf_alloc_netdevice_for_other_interfaces(unifi_priv_t *priv, u16 interfaceTag) INIT_LIST_HEAD(&interfacePriv->rx_controlled_list); /* Setup / override net_device fields */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29) dev->netdev_ops = &uf_netdev_ops; +#else + dev->open = uf_net_open; + dev->stop = uf_net_stop; + dev->hard_start_xmit = uf_net_xmit; + dev->do_ioctl = uf_net_ioctl; + + /* called by /proc/net/dev */ + dev->get_stats = uf_net_get_stats; + + dev->set_multicast_list = uf_set_multicast_list; +#endif #ifdef CSR_SUPPORT_WEXT dev->wireless_handlers = &unifi_iw_handler_def; @@ -530,6 +686,13 @@ uf_free_netdevice(unifi_priv_t *priv) spin_unlock_irqrestore(&priv->wapi_lock, flags); #endif +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) +#ifdef CONFIG_NET_SCHED + /* Unregister the qdisc operations */ + unregister_qdisc(&uf_qdisc_ops); +#endif /* CONFIG_NET_SCHED */ +#endif /* LINUX_VERSION_CODE */ + #ifdef CSR_SUPPORT_WEXT /* Unregister callback for netdevice state changes */ unregister_netdevice_notifier(&uf_netdev_notifier); @@ -537,8 +700,10 @@ uf_free_netdevice(unifi_priv_t *priv) #ifdef CSR_SUPPORT_SME /* Cancel work items and destroy the workqueue */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23) cancel_work_sync(&priv->multicast_list_task); #endif +#endif /* Destroy the workqueues. */ flush_workqueue(priv->unifi_workqueue); destroy_workqueue(priv->unifi_workqueue); @@ -613,7 +778,7 @@ uf_net_open(struct net_device *dev) } #endif - netif_tx_start_all_queues(dev); + UF_NETIF_TX_START_ALL_QUEUES(dev); func_exit(); return 0; @@ -643,7 +808,7 @@ uf_net_stop(struct net_device *dev) func_enter(); #endif - netif_tx_stop_all_queues(dev); + UF_NETIF_TX_STOP_ALL_QUEUES(dev); func_exit(); return 0; @@ -792,6 +957,7 @@ get_packet_priority(unifi_priv_t *priv, struct sk_buff *skb, const struct ethhdr return priority; } +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28) /* * --------------------------------------------------------------------------- * uf_net_select_queue @@ -839,6 +1005,7 @@ uf_net_select_queue(struct net_device *dev, struct sk_buff *skb) func_exit(); return (u16)queue; } /* uf_net_select_queue() */ +#endif int skb_add_llc_snap(struct net_device *dev, struct sk_buff *skb, int proto) @@ -1748,7 +1915,11 @@ send_ma_pkt_request(unifi_priv_t *priv, struct sk_buff *skb, const struct ethhdr * The controlled port is handled in the qdisc dequeue handler. * --------------------------------------------------------------------------- */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32) static netdev_tx_t +#else +static int +#endif uf_net_xmit(struct sk_buff *skb, struct net_device *dev) { netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev); @@ -1758,7 +1929,9 @@ uf_net_xmit(struct sk_buff *skb, struct net_device *dev) int result; static tx_signal_handler tx_handler; CSR_PRIORITY priority; +#if !defined (CONFIG_NET_SCHED) || (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28)) CsrWifiRouterCtrlPortAction port_action; +#endif /* CONFIG_NET_SCHED */ func_enter(); @@ -1783,6 +1956,11 @@ uf_net_xmit(struct sk_buff *skb, struct net_device *dev) port = UF_UNCONTROLLED_PORT_Q; } +#if defined (CONFIG_NET_SCHED) && (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)) + /* Remove the ethernet header */ + skb_pull(skb, ETH_HLEN); + result = tx_handler(priv, skb, &ehdr, priority); +#else /* Uncontrolled port rules apply */ port_action = verify_port(priv , (((CSR_WIFI_ROUTER_CTRL_MODE_STA == interfacePriv->interfaceMode)||(CSR_WIFI_ROUTER_CTRL_MODE_P2PCLI== interfacePriv->interfaceMode))? interfacePriv->bssid.a: ehdr.h_dest) @@ -1808,6 +1986,7 @@ uf_net_xmit(struct sk_buff *skb, struct net_device *dev) func_exit(); return NETDEV_TX_OK; } +#endif /* CONFIG_NET_SCHED */ if (result == NETDEV_TX_OK) { #if (defined(CSR_WIFI_SECURITY_WAPI_ENABLE) && defined(CSR_WIFI_SECURITY_WAPI_SW_ENCRYPTION)) @@ -1880,6 +2059,7 @@ unifi_pause_xmit(void *ospriv, unifi_TrafficQueue queue) func_enter(); unifi_trace(priv, UDBG2, "Stopping queue %d\n", queue); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28) for(i=0;inetdev[i])) @@ -1887,6 +2067,24 @@ unifi_pause_xmit(void *ospriv, unifi_TrafficQueue queue) netif_stop_subqueue(priv->netdev[i], (u16)queue); } } +#else +#ifdef ALLOW_Q_PAUSE + unifi_trace(priv, UDBG2, "Stopping netif\n"); + /* stop the traffic from all the interfaces. */ + for(i=0;inetdev[i])) { + UF_NETIF_TX_STOP_ALL_QUEUES(priv->netdev[i]); + } + } +#else + if (net_is_tx_q_paused(priv, queue)) { + unifi_trace(priv, UDBG2, "Queue already stopped\n"); + return; + } + net_tx_q_pause(priv, queue); +#endif +#endif #ifdef CSR_SUPPORT_SME if(queue<=3) { @@ -1910,6 +2108,7 @@ unifi_restart_xmit(void *ospriv, unifi_TrafficQueue queue) func_enter(); unifi_trace(priv, UDBG2, "Waking queue %d\n", queue); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28) for(i=0;inetdev[i])) @@ -1917,6 +2116,25 @@ unifi_restart_xmit(void *ospriv, unifi_TrafficQueue queue) netif_wake_subqueue(priv->netdev[i], (u16)queue); } } +#else +#ifdef ALLOW_Q_PAUSE + /* Need to supply queue number depending on Kernel support */ + /* Resume the traffic from all the interfaces */ + for(i=0;inetdev[i])) { + UF_NETIF_TX_WAKE_ALL_QUEUES(priv->netdev[i]); + } + } +#else + if (!(net_is_tx_q_paused(priv, queue))) { + unifi_trace(priv, UDBG2, "Queue already running\n"); + func_exit(); + return; + } + net_tx_q_unpause(priv, queue); +#endif +#endif #ifdef CSR_SUPPORT_SME if(queue <=3) { @@ -2131,7 +2349,13 @@ uf_resume_data_plane(unifi_priv_t *priv, int queue, { #ifdef CONFIG_NET_SCHED if (netif_running(priv->netdev[interfaceTag])) { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28) netif_tx_schedule_all(priv->netdev[interfaceTag]); +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) + netif_schedule_queue(netdev_get_tx_queue(priv->netdev[interfaceTag], 0)); +#else + netif_schedule(priv->netdev[interfaceTag]); +#endif /* LINUX_VERSION_CODE */ } #endif uf_process_rx_pending_queue(priv, queue, peer_address, 1,interfaceTag); @@ -2774,13 +2998,19 @@ uf_set_multicast_list(struct net_device *dev) #else u8 *mc_list = interfacePriv->mc_list; +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,34) struct netdev_hw_addr *mc_addr; int mc_addr_count; +#else + struct dev_mc_list *p; /* Pointer to the addresses structure. */ + int i; +#endif if (priv->init_progress != UNIFI_INIT_COMPLETED) { return; } +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,34) mc_addr_count = netdev_mc_count(dev); unifi_trace(priv, UDBG3, @@ -2799,6 +3029,25 @@ uf_set_multicast_list(struct net_device *dev) mc_list += ETH_ALEN; } +#else + unifi_trace(priv, UDBG3, + "uf_set_multicast_list (count=%d)\n", dev->mc_count); + + /* Not enough space? */ + if (dev->mc_count > UNIFI_MAX_MULTICAST_ADDRESSES) { + return; + } + + /* Store the list to be processed by the work item. */ + interfacePriv->mc_list_count = dev->mc_count; + p = dev->mc_list; + for (i = 0; i < dev->mc_count; i++) { + memcpy(mc_list, p->dmi_addr, ETH_ALEN); + p = p->next; + mc_list += ETH_ALEN; + } +#endif + /* Send a message to the workqueue */ queue_work(priv->unifi_workqueue, &priv->multicast_list_task); #endif @@ -2932,6 +3181,375 @@ void uf_net_get_name(struct net_device *dev, char *name, int len) } /* uf_net_get_name */ + + + + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) +#ifdef CONFIG_NET_SCHED + +/* + * --------------------------------------------------------------------------- + * uf_install_qdisc + * + * Creates a root qdisc, registers our qdisc handlers and + * overrides the device's qdisc_sleeping to prevent the system + * from creating a new one for our network device. + * + * Arguments: + * dev Pointer to the network device. + * + * Returns: + * 0 on success, Linux error code otherwise. + * + * Notes: + * This function holds the qdisk lock so it needs to be called + * after registering the network device in uf_register_netdev(). + * Also, the qdisc_create_dflt() API has changed in 2.6.20 to + * include the parentid. + * --------------------------------------------------------------------------- + */ +int uf_install_qdisc(struct net_device *dev) +{ + struct Qdisc *qdisc; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) + struct netdev_queue *queue0; +#endif /* LINUX_VERSION_CODE */ + + + func_enter(); + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27) + /* + * check that there is no qdisc currently attached to device + * this ensures that we will be the root qdisc. (I can't find a better + * way to test this explicitly) + */ + if (dev->qdisc_sleeping != &noop_qdisc) { + func_exit_r(-EFAULT); + return -EINVAL; + } +#endif /* LINUX_VERSION_CODE */ + + qdisc = UF_QDISC_CREATE_DFLT(dev, &uf_qdisc_ops, TC_H_ROOT); + if (!qdisc) { + unifi_error(NULL, "%s: qdisc installation failed\n", dev->name); + func_exit_r(-EFAULT); + return -EFAULT; + } + unifi_trace(NULL, UDBG5, "%s: parent qdisc=0x%p\n", + dev->name, qdisc); + + qdisc->handle = 0x80020000; + qdisc->flags = 0x0; + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) + queue0 = netdev_get_tx_queue(dev, 0); + if (queue0 == NULL) { + unifi_error(NULL, "%s: netdev_get_tx_queue returned no queue\n", + dev->name); + func_exit_r(-EFAULT); + return -EFAULT; + } + queue0->qdisc = qdisc; + queue0->qdisc_sleeping = qdisc; +#else + qdisc_lock_tree(dev); + list_add_tail(&qdisc->list, &dev->qdisc_list); + dev->qdisc_sleeping = qdisc; + qdisc_unlock_tree(dev); +#endif /* LINUX_VERSION_CODE */ + + func_exit_r(0); + return 0; + +} /* uf_install_qdisc() */ + +static int uf_qdiscop_enqueue(struct sk_buff *skb, struct Qdisc* qd) +{ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) + netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(qd->dev_queue->dev); +#else + netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(qd->dev); +#endif /* LINUX_VERSION_CODE */ + unifi_priv_t *priv = interfacePriv->privPtr; + struct uf_sched_data *q = qdisc_priv(qd); + struct uf_tx_packet_data *pkt_data = (struct uf_tx_packet_data *) skb->cb; + struct ethhdr ehdr; + struct Qdisc *qdisc; + int r, proto; + + func_enter(); + + memcpy(&ehdr, skb->data, ETH_HLEN); + proto = ntohs(ehdr.h_proto); + + /* 802.1x - apply controlled/uncontrolled port rules */ + if ((proto != ETH_P_PAE) +#ifdef CSR_WIFI_SECURITY_WAPI_ENABLE + && (proto != ETH_P_WAI) +#endif + ) { + /* queues 0 - 3 */ + pkt_data->priority = get_packet_priority(priv, skb, &ehdr, interfacePriv); + pkt_data->queue = unifi_frame_priority_to_queue(pkt_data->priority); + } else { + pkt_data->queue = UNIFI_TRAFFIC_Q_EAPOL; + } + + qdisc = q->queues[pkt_data->queue]; + r = qdisc->enqueue(skb, qdisc); + if (r == NET_XMIT_SUCCESS) { + qd->q.qlen++; + qd->bstats.bytes += skb->len; + qd->bstats.packets++; + func_exit_r(NET_XMIT_SUCCESS); + return NET_XMIT_SUCCESS; + } + + unifi_error(priv, "uf_qdiscop_enqueue: dropped\n"); + qd->qstats.drops++; + + func_exit_r(r); + return r; + +} /* uf_qdiscop_enqueue() */ + + +static int uf_qdiscop_requeue(struct sk_buff *skb, struct Qdisc* qd) +{ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) + netInterface_priv_t *interfacePriv = (netInterface_priv_t*)netdev_priv(qd->dev_queue->dev); +#else + netInterface_priv_t *interfacePriv = (netInterface_priv_t*)netdev_priv(qd->dev); +#endif /* LINUX_VERSION_CODE */ + unifi_priv_t *priv = interfacePriv->privPtr; + struct uf_sched_data *q = qdisc_priv(qd); + struct uf_tx_packet_data *pkt_data = (struct uf_tx_packet_data *) skb->cb; + struct Qdisc *qdisc; + int r; + + func_enter(); + + unifi_trace(priv, UDBG5, "uf_qdiscop_requeue: (q=%d), tag=%u\n", + pkt_data->queue, pkt_data->host_tag); + + /* we recorded which queue to use earlier! */ + qdisc = q->queues[pkt_data->queue]; + + if ((r = qdisc->ops->requeue(skb, qdisc)) == 0) { + qd->q.qlen++; + func_exit_r(0); + return 0; + } + + unifi_error(priv, "uf_qdiscop_requeue: dropped\n"); + qd->qstats.drops++; + + func_exit_r(r); + return r; +} /* uf_qdiscop_requeue() */ + +static struct sk_buff *uf_qdiscop_dequeue(struct Qdisc* qd) +{ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) + netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(qd->dev_queue->dev); +#else + netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(qd->dev); +#endif /* LINUX_VERSION_CODE */ + unifi_priv_t *priv = interfacePriv->privPtr; + struct uf_sched_data *q = qdisc_priv(qd); + struct sk_buff *skb; + struct Qdisc *qdisc; + int queue, i; + struct ethhdr ehdr; + struct uf_tx_packet_data *pkt_data; + CsrWifiRouterCtrlPortAction port_action; + + func_enter(); + + /* check all the queues */ + for (i = UNIFI_TRAFFIC_Q_MAX - 1; i >= 0; i--) { + + if (i != UNIFI_TRAFFIC_Q_EAPOL) { + queue = priv->prev_queue; + if (++priv->prev_queue >= UNIFI_TRAFFIC_Q_EAPOL) { + priv->prev_queue = 0; + } + } else { + queue = i; + } + +#ifndef ALLOW_Q_PAUSE + /* If queue is paused, do not dequeue */ + if (net_is_tx_q_paused(priv, queue)) { + unifi_trace(priv, UDBG5, + "uf_qdiscop_dequeue: tx queue paused (q=%d)\n", queue); + continue; + } +#endif + + qdisc = q->queues[queue]; + skb = qdisc->dequeue(qdisc); + if (skb) { + /* A packet has been dequeued, decrease the queued packets count */ + qd->q.qlen--; + + pkt_data = (struct uf_tx_packet_data *) skb->cb; + + /* Check the (un)controlled port status */ + memcpy(&ehdr, skb->data, ETH_HLEN); + + port_action = verify_port(priv + , (((CSR_WIFI_ROUTER_CTRL_MODE_STA == interfacePriv->interfaceMode) ||(CSR_WIFI_ROUTER_CTRL_MODE_P2PCLI == interfacePriv->interfaceMode))? interfacePriv->bssid.a: ehdr.h_dest) + , (UNIFI_TRAFFIC_Q_EAPOL == queue? UF_UNCONTROLLED_PORT_Q: UF_CONTROLLED_PORT_Q) + , interfacePriv->InterfaceTag); + + /* Dequeue packet if port is open */ + if (port_action == CSR_WIFI_ROUTER_CTRL_PORT_ACTION_8021X_PORT_OPEN) { + unifi_trace(priv, UDBG5, + "uf_qdiscop_dequeue: new (q=%d), tag=%u\n", + queue, pkt_data->host_tag); + + func_exit(); + return skb; + } + + /* Discard or block the packet if necessary */ + if (port_action == CSR_WIFI_ROUTER_CTRL_PORT_ACTION_8021X_PORT_CLOSED_DISCARD) { + unifi_trace(priv, UDBG5, + "uf_qdiscop_dequeue: drop (q=%d), tag=%u\n", + queue, pkt_data->host_tag); + kfree_skb(skb); + break; + } + + /* We can not send the packet now, put it back to the queue */ + if (qdisc->ops->requeue(skb, qdisc) != 0) { + unifi_error(priv, + "uf_qdiscop_dequeue: requeue (q=%d) failed, tag=%u, drop it\n", + queue, pkt_data->host_tag); + + /* Requeue failed, drop the packet */ + kfree_skb(skb); + break; + } + /* We requeued the packet, increase the queued packets count */ + qd->q.qlen++; + + unifi_trace(priv, UDBG5, + "uf_qdiscop_dequeue: skip (q=%d), tag=%u\n", + queue, pkt_data->host_tag); + } + } + + func_exit(); + return NULL; +} /* uf_qdiscop_dequeue() */ + + +static void uf_qdiscop_reset(struct Qdisc* qd) +{ + struct uf_sched_data *q = qdisc_priv(qd); + int queue; + func_enter(); + + for (queue = 0; queue < UNIFI_TRAFFIC_Q_MAX; queue++) { + qdisc_reset(q->queues[queue]); + } + qd->q.qlen = 0; + + func_exit(); +} /* uf_qdiscop_reset() */ + + +static void uf_qdiscop_destroy(struct Qdisc* qd) +{ + struct uf_sched_data *q = qdisc_priv(qd); + int queue; + + func_enter(); + + for (queue=0; queue < UNIFI_TRAFFIC_Q_MAX; queue++) { + qdisc_destroy(q->queues[queue]); + q->queues[queue] = &noop_qdisc; + } + + func_exit(); +} /* uf_qdiscop_destroy() */ + + +/* called whenever parameters are updated on existing qdisc */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,25) +static int uf_qdiscop_tune(struct Qdisc *qd, struct nlattr *opt) +#else +static int uf_qdiscop_tune(struct Qdisc *qd, struct rtattr *opt) +#endif +{ + func_enter(); + func_exit(); + return 0; +} /* uf_qdiscop_tune() */ + + +/* called during initial creation of qdisc on device */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,25) +static int uf_qdiscop_init(struct Qdisc *qd, struct nlattr *opt) +#else +static int uf_qdiscop_init(struct Qdisc *qd, struct rtattr *opt) +#endif +{ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) + struct net_device *dev = qd->dev_queue->dev; +#else + struct net_device *dev = qd->dev; +#endif /* LINUX_VERSION_CODE */ + netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev); + unifi_priv_t *priv = interfacePriv->privPtr; + struct uf_sched_data *q = qdisc_priv(qd); + int err = 0, i; + + func_enter(); + + /* make sure we do not mess with the ingress qdisc */ + if (qd->flags & TCQ_F_INGRESS) { + func_exit(); + return -EINVAL; + } + + /* if options were passed in, set them */ + if (opt) { + err = uf_qdiscop_tune(qd, opt); + } + + /* create child queues */ + for (i = 0; i < UNIFI_TRAFFIC_Q_MAX; i++) { + q->queues[i] = UF_QDISC_CREATE_DFLT(dev, &pfifo_qdisc_ops, + qd->handle); + if (!q->queues[i]) { + q->queues[i] = &noop_qdisc; + unifi_error(priv, "%s child qdisc %i creation failed\n"); + } + + unifi_trace(priv, UDBG5, "%s: child qdisc=0x%p\n", + dev->name, q->queues[i]); + } + + func_exit_r(err); + return err; +} /* uf_qdiscop_init() */ + + +static int uf_qdiscop_dump(struct Qdisc *qd, struct sk_buff *skb) +{ + func_enter(); + func_exit_r(skb->len); + return skb->len; +} /* uf_qdiscop_dump() */ + +#endif /* CONFIG_NET_SCHED */ +#endif /* LINUX_VERSION_CODE */ + #ifdef CSR_SUPPORT_WEXT /* @@ -2977,7 +3595,7 @@ uf_netdev_event(struct notifier_block *notif, unsigned long event, void* ptr) { interfacePriv->wait_netdev_change ? "" : "not"); if (interfacePriv->wait_netdev_change) { - netif_tx_wake_all_queues(priv->netdev[interfacePriv->InterfaceTag]); + UF_NETIF_TX_WAKE_ALL_QUEUES(priv->netdev[interfacePriv->InterfaceTag]); interfacePriv->connected = UnifiConnected; interfacePriv->wait_netdev_change = FALSE; /* Note: passing the broadcast address here will allow anyone to attempt to join our adhoc network */ diff --git a/trunk/drivers/staging/csr/sdio_events.c b/trunk/drivers/staging/csr/sdio_events.c index 2a80b9eb0200..6892c2e281bc 100644 --- a/trunk/drivers/staging/csr/sdio_events.c +++ b/trunk/drivers/staging/csr/sdio_events.c @@ -66,7 +66,7 @@ void unifi_suspend(void *ospriv) unifi_trace(priv, UDBG1, "unifi_suspend: netif_carrier_off"); netif_carrier_off(priv->netdev[interfaceTag]); } - netif_tx_stop_all_queues(priv->netdev[interfaceTag]); + UF_NETIF_TX_STOP_ALL_QUEUES(priv->netdev[interfaceTag]); } } @@ -119,7 +119,7 @@ void unifi_resume(void *ospriv) if (interfacePriv->netdev_registered == 1) { netif_carrier_on(priv->netdev[interfaceTag]); - netif_tx_start_all_queues(priv->netdev[interfaceTag]); + UF_NETIF_TX_START_ALL_QUEUES(priv->netdev[interfaceTag]); } } diff --git a/trunk/drivers/staging/csr/sdio_mmc.c b/trunk/drivers/staging/csr/sdio_mmc.c index af3e40bb5010..d3fd57cdde0b 100644 --- a/trunk/drivers/staging/csr/sdio_mmc.c +++ b/trunk/drivers/staging/csr/sdio_mmc.c @@ -14,7 +14,7 @@ #include #include #include -#include + #include #include #include @@ -31,6 +31,7 @@ struct wake_lock unifi_sdio_wake_lock; /* wakelock to prevent suspend while resu static CsrSdioFunctionDriver *sdio_func_drv; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32) #ifdef CONFIG_PM static int uf_sdio_mmc_power_event(struct notifier_block *this, unsigned long event, void *ptr); #endif @@ -44,6 +45,7 @@ static int uf_sdio_mmc_power_event(struct notifier_block *this, unsigned long ev * returning immediately (at least on x86). */ static int card_is_powered = 1; +#endif /* 2.6.32 */ /* MMC uses ENOMEDIUM to indicate card gone away */ @@ -635,6 +637,7 @@ CsrSdioFunctionIdle(CsrSdioFunction *function) CsrResult CsrSdioPowerOn(CsrSdioFunction *function) { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32) struct sdio_func *func = (struct sdio_func *)function->priv; struct mmc_host *host = func->card->host; @@ -646,6 +649,7 @@ CsrSdioPowerOn(CsrSdioFunction *function) printk(KERN_INFO "SDIO: Skip power on; card is already powered.\n"); } _sdio_release_host(func); +#endif /* 2.6.32 */ return CSR_RESULT_SUCCESS; } /* CsrSdioPowerOn() */ @@ -663,6 +667,7 @@ CsrSdioPowerOn(CsrSdioFunction *function) void CsrSdioPowerOff(CsrSdioFunction *function) { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32) struct sdio_func *func = (struct sdio_func *)function->priv; struct mmc_host *host = func->card->host; @@ -674,6 +679,7 @@ CsrSdioPowerOff(CsrSdioFunction *function) printk(KERN_INFO "SDIO: Skip power off; card is already powered off.\n"); } _sdio_release_host(func); +#endif /* 2.6.32 */ } /* CsrSdioPowerOff() */ @@ -839,18 +845,19 @@ uf_glue_sdio_int_handler(struct sdio_func *func) * Status of the removal. * --------------------------------------------------------------------------- */ -int csr_sdio_linux_remove_irq(CsrSdioFunction *function) +int +csr_sdio_linux_remove_irq(CsrSdioFunction *function) { - struct sdio_func *func = (struct sdio_func *)function->priv; - int r; + struct sdio_func *func = (struct sdio_func *)function->priv; + int r; - unifi_trace(NULL, UDBG1, "csr_sdio_linux_remove_irq\n"); + unifi_trace(NULL, UDBG1, "csr_sdio_linux_remove_irq\n"); - sdio_claim_host(func); - r = sdio_release_irq(func); - sdio_release_host(func); + sdio_claim_host(func); + r = sdio_release_irq(func); + sdio_release_host(func); - return r; + return r; } /* csr_sdio_linux_remove_irq() */ @@ -869,25 +876,28 @@ int csr_sdio_linux_remove_irq(CsrSdioFunction *function) * Status of the removal. * --------------------------------------------------------------------------- */ -int csr_sdio_linux_install_irq(CsrSdioFunction *function) +int +csr_sdio_linux_install_irq(CsrSdioFunction *function) { - struct sdio_func *func = (struct sdio_func *)function->priv; - int r; + struct sdio_func *func = (struct sdio_func *)function->priv; + int r; - unifi_trace(NULL, UDBG1, "csr_sdio_linux_install_irq\n"); + unifi_trace(NULL, UDBG1, "csr_sdio_linux_install_irq\n"); - /* Register our interrupt handle */ - sdio_claim_host(func); - r = sdio_claim_irq(func, uf_glue_sdio_int_handler); - sdio_release_host(func); + /* Register our interrupt handle */ + sdio_claim_host(func); + r = sdio_claim_irq(func, uf_glue_sdio_int_handler); + sdio_release_host(func); - /* If the interrupt was installed earlier, is fine */ - if (r == -EBUSY) - r = 0; + /* If the interrupt was installed earlier, is fine */ + if (r == -EBUSY) { + r = 0; + } - return r; + return r; } /* csr_sdio_linux_install_irq() */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32) #ifdef CONFIG_PM /* @@ -1013,6 +1023,7 @@ uf_sdio_mmc_power_event(struct notifier_block *this, unsigned long event, void * } #endif /* CONFIG_PM */ +#endif /* 2.6.32 */ /* * --------------------------------------------------------------------------- @@ -1039,8 +1050,10 @@ uf_glue_sdio_probe(struct sdio_func *func, /* First of all claim the SDIO driver */ sdio_claim_host(func); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32) /* Assume that the card is already powered */ card_is_powered = 1; +#endif /* Assumes one card per host, which is true for SDIO */ instance = func->card->host->index; @@ -1080,11 +1093,13 @@ uf_glue_sdio_probe(struct sdio_func *func, /* Pass context to the SDIO driver */ sdio_set_drvdata(func, sdio_ctx); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32) #ifdef CONFIG_PM /* Register to get PM events */ if (uf_sdio_mmc_register_pm_notifier(sdio_ctx) == NULL) { unifi_error(NULL, "%s: Failed to register for PM events\n", __FUNCTION__); } +#endif #endif /* Register this device with the SDIO function driver */ @@ -1141,9 +1156,11 @@ uf_glue_sdio_remove(struct sdio_func *func) sdio_func_drv->removed(sdio_ctx); } +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32) #ifdef CONFIG_PM /* Unregister for PM events */ uf_sdio_mmc_unregister_pm_notifier(sdio_ctx); +#endif #endif kfree(sdio_ctx); @@ -1165,6 +1182,7 @@ static const struct sdio_device_id unifi_ids[] = { MODULE_DEVICE_TABLE(sdio, unifi_ids); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32) #ifdef CONFIG_PM /* @@ -1234,13 +1252,16 @@ static struct dev_pm_ops unifi_pm_ops = { #define UNIFI_PM_OPS NULL #endif /* CONFIG_PM */ +#endif /* 2.6.32 */ static struct sdio_driver unifi_driver = { .probe = uf_glue_sdio_probe, .remove = uf_glue_sdio_remove, .name = "unifi", .id_table = unifi_ids, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32) .drv.pm = UNIFI_PM_OPS, +#endif /* 2.6.32 */ }; @@ -1284,9 +1305,11 @@ CsrSdioFunctionDriverRegister(CsrSdioFunctionDriver *sdio_drv) */ sdio_func_drv = sdio_drv; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32) #ifdef CONFIG_PM /* Initialise PM notifier list */ INIT_LIST_HEAD(&uf_sdio_mmc_pm_notifiers.list); +#endif #endif /* Register ourself with mmc_core */ diff --git a/trunk/drivers/staging/csr/sme_blocking.c b/trunk/drivers/staging/csr/sme_blocking.c index 543e8f2c407a..acf0f0fe3b37 100644 --- a/trunk/drivers/staging/csr/sme_blocking.c +++ b/trunk/drivers/staging/csr/sme_blocking.c @@ -18,10 +18,10 @@ /* - * This file also contains the implementation of the asynchronous + * This file also contains the implementation of the asyncronous * requests to the SME. * - * Before calling an asynchronous SME function, we call sme_init_request() + * Before calling an asyncronous SME function, we call sme_init_request() * which gets hold of the SME semaphore and updates the request status. * The semaphore makes sure that there is only one pending request to * the SME at a time. diff --git a/trunk/drivers/staging/csr/sme_native.c b/trunk/drivers/staging/csr/sme_native.c index d7a5125d9a8e..229268fd746c 100644 --- a/trunk/drivers/staging/csr/sme_native.c +++ b/trunk/drivers/staging/csr/sme_native.c @@ -12,7 +12,7 @@ */ #include -#include + #include "unifi_priv.h" #include "csr_wifi_hip_unifi.h" #include "csr_wifi_hip_conversions.h" @@ -24,7 +24,11 @@ uf_sme_init(unifi_priv_t *priv) { func_enter(); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37) sema_init(&priv->mlme_blocking_mutex, 1); +#else + init_MUTEX(&priv->mlme_blocking_mutex); +#endif #ifdef CSR_SUPPORT_WEXT { diff --git a/trunk/drivers/staging/csr/sme_sys.c b/trunk/drivers/staging/csr/sme_sys.c index 5b26c41c01f6..99de27e678d2 100644 --- a/trunk/drivers/staging/csr/sme_sys.c +++ b/trunk/drivers/staging/csr/sme_sys.c @@ -14,7 +14,6 @@ * --------------------------------------------------------------------------- */ -#include #include "csr_wifi_hip_unifiversion.h" #include "unifi_priv.h" #include "csr_wifi_hip_conversions.h" @@ -22,6 +21,7 @@ #include "csr_wifi_sme_sef.h" #endif + /* * This file implements the SME SYS API and contains the following functions: * CsrWifiRouterCtrlMediaStatusReqHandler() @@ -192,7 +192,7 @@ void CsrWifiRouterCtrlMediaStatusReqHandler(void* drvpriv, CsrWifiFsmEvent* msg) #endif unifi_trace(priv, UDBG1, "CsrWifiRouterCtrlMediaStatusReqHandler: AP/P2PGO setting netif_carrier_on\n"); - netif_tx_wake_all_queues(priv->netdev[req->interfaceTag]); + UF_NETIF_TX_WAKE_ALL_QUEUES(priv->netdev[req->interfaceTag]); break; default: @@ -226,7 +226,7 @@ void CsrWifiRouterCtrlMediaStatusReqHandler(void* drvpriv, CsrWifiFsmEvent* msg) unifi_trace(priv, UDBG1, "CsrWifiRouterMediaStatusReqHandler: UnifiConnected && netif_carrier_on\n"); netif_carrier_on(priv->netdev[req->interfaceTag]); - netif_tx_wake_all_queues(priv->netdev[req->interfaceTag]); + UF_NETIF_TX_WAKE_ALL_QUEUES(priv->netdev[req->interfaceTag]); uf_process_rx_pending_queue(priv, UF_UNCONTROLLED_PORT_Q, broadcast_address, 1, interfacePriv->InterfaceTag); uf_process_rx_pending_queue(priv, UF_CONTROLLED_PORT_Q, broadcast_address, 1, interfacePriv->InterfaceTag); } @@ -869,6 +869,7 @@ wifi_off(unifi_priv_t *priv) unifi_trace(priv, UDBG1, "wifi_off\n"); /* Destroy the Traffic Analysis Module */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23) cancel_work_sync(&priv->ta_ind_work.task); cancel_work_sync(&priv->ta_sample_ind_work.task); #ifdef CSR_SUPPORT_WEXT @@ -883,6 +884,7 @@ wifi_off(unifi_priv_t *priv) cancel_work_sync(&netpriv->send_m4_ready_task); } } +#endif flush_workqueue(priv->unifi_workqueue); /* fw_init parameter can prevent power off UniFi, for debugging */ @@ -953,7 +955,7 @@ void CsrWifiRouterCtrlWifiOffReqHandler(void* drvpriv, CsrWifiFsmEvent* msg) netInterface_priv_t *interfacePriv = priv->interfacePriv[i]; if (interfacePriv->netdev_registered == 1) { netif_carrier_off(priv->netdev[i]); - netif_tx_stop_all_queues(priv->netdev[i]); + UF_NETIF_TX_STOP_ALL_QUEUES(priv->netdev[i]); interfacePriv->connected = UnifiConnectedUnknown; } interfacePriv->interfaceMode = 0; @@ -2121,7 +2123,7 @@ static int peer_add_new_record(unifi_priv_t *priv,CsrWifiRouterCtrlPeerAddReq *r /* Allocate for the new station record , to avoid race condition would happen between ADD_PEER & * DEL_PEER the allocation made atomic memory rather than kernel memory */ - newRecord = kmalloc(sizeof(CsrWifiRouterCtrlStaInfo_t), GFP_ATOMIC); + newRecord = (CsrWifiRouterCtrlStaInfo_t *) kmalloc(sizeof(CsrWifiRouterCtrlStaInfo_t), GFP_ATOMIC); if (!newRecord) { unifi_error(priv, "failed to allocate the %d bytes of mem for station record\n", sizeof(CsrWifiRouterCtrlStaInfo_t)); @@ -2813,11 +2815,12 @@ u8 blockack_session_start(unifi_priv_t *priv, } /* create and populate the new BA session structure */ - ba_session_tx = kzalloc(sizeof(ba_session_tx_struct), GFP_KERNEL); + ba_session_tx = kmalloc(sizeof(ba_session_tx_struct), GFP_KERNEL); if (!ba_session_tx) { unifi_error(priv, "%s: kmalloc failed for ba_session_tx\n", __FUNCTION__); return FALSE; } + memset(ba_session_tx, 0, sizeof(ba_session_tx_struct)); ba_session_tx->interfacePriv = interfacePriv; ba_session_tx->tID = tID; @@ -2902,23 +2905,26 @@ u8 blockack_session_start(unifi_priv_t *priv, return FALSE; } - ba_session_rx = kzalloc(sizeof(ba_session_rx_struct), GFP_KERNEL); + ba_session_rx = kmalloc(sizeof(ba_session_rx_struct), GFP_KERNEL); if (!ba_session_rx) { unifi_error(priv, "%s: kmalloc failed for ba_session_rx\n", __FUNCTION__); return FALSE; } + memset(ba_session_rx, 0, sizeof(ba_session_rx_struct)); ba_session_rx->wind_size = wind_size; ba_session_rx->start_sn = ba_session_rx->expected_sn = start_sn; ba_session_rx->trigger_ba_after_ssn = FALSE; - ba_session_rx->buffer = kzalloc(ba_session_rx->wind_size*sizeof(frame_desc_struct), GFP_KERNEL); + ba_session_rx->buffer = kmalloc(ba_session_rx->wind_size*sizeof(frame_desc_struct), GFP_KERNEL); if (!ba_session_rx->buffer) { kfree(ba_session_rx); unifi_error(priv, "%s: kmalloc failed for buffer\n", __FUNCTION__); return FALSE; } + memset(ba_session_rx->buffer, 0, ba_session_rx->wind_size*sizeof(frame_desc_struct)); + INIT_WORK(&ba_session_rx->send_ba_err_task, uf_send_ba_err_wq); if (timeout) { ba_session_rx->timeout = timeout; diff --git a/trunk/drivers/staging/csr/sme_wext.c b/trunk/drivers/staging/csr/sme_wext.c index b58c0c6b171c..7e85907e29a3 100644 --- a/trunk/drivers/staging/csr/sme_wext.c +++ b/trunk/drivers/staging/csr/sme_wext.c @@ -1191,6 +1191,8 @@ unifi_siwap(struct net_device *dev, struct iw_request_info *info, netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev); unifi_priv_t *priv = interfacePriv->privPtr; int err = 0; + const unsigned char zero_bssid[ETH_ALEN] = {0x00, 0x00, 0x00, + 0x00, 0x00, 0x00}; func_enter(); @@ -1211,7 +1213,7 @@ unifi_siwap(struct net_device *dev, struct iw_request_info *info, unifi_trace(priv, UDBG1, "unifi_siwap: asked for %pM\n", wrqu->ap_addr.sa_data); - if (is_zero_ether_addr(wrqu->ap_addr.sa_data)) { + if (!memcmp(wrqu->ap_addr.sa_data, zero_bssid, ETH_ALEN)) { priv->ignore_bssid_join = FALSE; err = sme_mgt_disconnect(priv); if (err) { @@ -3041,8 +3043,8 @@ _unifi_siwencodeext(struct net_device *dev, struct iw_request_info *info, memcpy(sme_key.address.a, ext->addr.sa_data, ETH_ALEN); if (ext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID) { - unifi_trace(priv, UDBG5, "RSC first 6 bytes = %*phC\n", - 6, ext->rx_seq); + unifi_trace(priv, UDBG5, "RSC first 6 bytes = %02X:%02X:%02X:%02X:%02X:%02X\n", + ext->rx_seq[0], ext->rx_seq[1], ext->rx_seq[2], ext->rx_seq[3], ext->rx_seq[4], ext->rx_seq[5]); /* memcpy((u8*)(&sme_key.keyRsc), ext->rx_seq, 8); */ sme_key.keyRsc[0] = ext->rx_seq[1] << 8 | ext->rx_seq[0]; diff --git a/trunk/drivers/staging/csr/ul_int.c b/trunk/drivers/staging/csr/ul_int.c index 4013d021ebbf..46d3507fd8f1 100644 --- a/trunk/drivers/staging/csr/ul_int.c +++ b/trunk/drivers/staging/csr/ul_int.c @@ -12,7 +12,6 @@ * * *************************************************************************** */ -#include #include "csr_wifi_hip_unifi.h" #include "csr_wifi_hip_conversions.h" #include "unifi_priv.h" @@ -45,7 +44,11 @@ ul_init_clients(unifi_priv_t *priv) int id; ul_client_t *ul_clients; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37) sema_init(&priv->udi_logging_mutex, 1); +#else + init_MUTEX(&priv->udi_logging_mutex); +#endif priv->logging_client = NULL; ul_clients = priv->ul_clients; diff --git a/trunk/drivers/staging/csr/unifi_pdu_processing.c b/trunk/drivers/staging/csr/unifi_pdu_processing.c index ae7c8fc94092..7c7e8d49ae42 100644 --- a/trunk/drivers/staging/csr/unifi_pdu_processing.c +++ b/trunk/drivers/staging/csr/unifi_pdu_processing.c @@ -14,7 +14,7 @@ * --------------------------------------------------------------------------- */ -#include + #include #include #include @@ -23,6 +23,9 @@ #include "csr_wifi_hip_conversions.h" #include "csr_time.h" #include "unifi_priv.h" +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,13) +#include +#endif #include #ifdef CSR_SUPPORT_SME diff --git a/trunk/drivers/staging/csr/unifi_priv.h b/trunk/drivers/staging/csr/unifi_priv.h index aec8e28fb60d..6d6b46191a1a 100644 --- a/trunk/drivers/staging/csr/unifi_priv.h +++ b/trunk/drivers/staging/csr/unifi_priv.h @@ -29,7 +29,9 @@ #include #include #include +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,19) #include +#endif #ifdef CSR_WIFI_SUPPORT_MMC_DRIVER #include @@ -71,6 +73,33 @@ extern struct wake_lock unifi_sdio_wake_lock; #include "unifi_clients.h" + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) +#include + +#undef INIT_WORK +#define INIT_WORK(_work, _func) \ + do { \ + INIT_LIST_HEAD(&(_work)->entry); \ + (_work)->pending = 0; \ + PREPARE_WORK((_work), (_func), (_work)); \ + init_timer(&(_work)->timer); \ + } while(0) + +#endif /* Linux kernel < 2.6.20 */ + + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) +#define UF_NETIF_TX_WAKE_ALL_QUEUES(_netdev) netif_tx_wake_all_queues(_netdev) +#define UF_NETIF_TX_START_ALL_QUEUES(_netdev) netif_tx_start_all_queues(_netdev) +#define UF_NETIF_TX_STOP_ALL_QUEUES(_netdev) netif_tx_stop_all_queues(_netdev) +#else +#define UF_NETIF_TX_WAKE_ALL_QUEUES(_netdev) netif_wake_queue(_netdev) +#define UF_NETIF_TX_START_ALL_QUEUES(_netdev) netif_start_queue(_netdev) +#define UF_NETIF_TX_STOP_ALL_QUEUES(_netdev) netif_stop_queue(_netdev) +#endif /* Linux kernel >= 2.6.27 */ + + #ifdef CSR_NATIVE_LINUX #include "sme_native/unifi_native.h" #else @@ -605,10 +634,12 @@ struct unifi_priv { spinlock_t wapi_lock; #endif +#ifndef ALLOW_Q_PAUSE /* Array to indicate if a particular Tx queue is paused, this may not be * required in a multiqueue implementation since we can directly stop kernel * queues */ u8 tx_q_paused_flag[UNIFI_TRAFFIC_Q_MAX]; +#endif #ifdef CSR_WIFI_RX_PATH_SPLIT struct workqueue_struct *rx_workqueue; @@ -767,6 +798,12 @@ typedef struct netInterface_priv u8 bcTimSetReqQueued; } netInterface_priv_t; +#ifndef ALLOW_Q_PAUSE +#define net_is_tx_q_paused(priv, q) (priv->tx_q_paused_flag[q]) +#define net_tx_q_unpause(priv, q) (priv->tx_q_paused_flag[q] = 0) +#define net_tx_q_pause(priv, q) (priv->tx_q_paused_flag[q] = 1) +#endif + #ifdef CSR_SUPPORT_SME #define routerStartBuffering(priv,queue) priv->routerBufferEnable[(queue)] = TRUE; #define routerStopBuffering(priv,queue) priv->routerBufferEnable[(queue)] = FALSE; @@ -1051,6 +1088,9 @@ CsrWifiRouterCtrlStaInfo_t * CsrWifiRouterCtrlGetStationRecordFromHandle(unifi_p void uf_update_sta_activity(unifi_priv_t *priv, u16 interfaceTag, const u8 *peerMacAddress); void uf_process_ma_pkt_cfm_for_ap(unifi_priv_t *priv,u16 interfaceTag, const CSR_MA_PACKET_CONFIRM *pkt_cfm); #endif +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) +int uf_install_qdisc(struct net_device *dev); +#endif void uf_resume_data_plane(unifi_priv_t *priv, int queue, CsrWifiMacAddress peer_address, diff --git a/trunk/drivers/staging/csr/unifi_wext.h b/trunk/drivers/staging/csr/unifi_wext.h index 6834c43abfbb..6d7a99595083 100644 --- a/trunk/drivers/staging/csr/unifi_wext.h +++ b/trunk/drivers/staging/csr/unifi_wext.h @@ -16,7 +16,6 @@ #define __LINUX_UNIFI_WEXT_H__ 1 #include -#include #include #include "csr_wifi_sme_prim.h" @@ -71,9 +70,15 @@ uf_iwe_stream_add_point(struct iw_request_info *info, char *start, char *stop, { char *new_start; - new_start = iwe_stream_add_point(info, start, stop, piwe, extra); + new_start = iwe_stream_add_point( +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27) || defined (IW_REQUEST_FLAG_COMPAT) + info, +#endif + start, stop, piwe, extra); if (unlikely(new_start == start)) + { return -E2BIG; + } return (new_start - start); } @@ -85,9 +90,14 @@ uf_iwe_stream_add_event(struct iw_request_info *info, char *start, char *stop, { char *new_start; - new_start = iwe_stream_add_event(info, start, stop, piwe, len); - if (unlikely(new_start == start)) + new_start = iwe_stream_add_event( +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27) || defined(IW_REQUEST_FLAG_COMPAT) + info, +#endif + start, stop, piwe, len); + if (unlikely(new_start == start)) { return -E2BIG; + } return (new_start - start); } @@ -98,9 +108,14 @@ uf_iwe_stream_add_value(struct iw_request_info *info, char *stream, char *start, { char *new_start; - new_start = iwe_stream_add_value(info, stream, start, stop, piwe, len); - if (unlikely(new_start == start)) + new_start = iwe_stream_add_value( +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27) || defined(IW_REQUEST_FLAG_COMPAT) + info, +#endif + stream, start, stop, piwe, len); + if (unlikely(new_start == start)) { return -E2BIG; + } return (new_start - start); } diff --git a/trunk/drivers/staging/csr/wext_events.c b/trunk/drivers/staging/csr/wext_events.c index 9860ea30da25..d356887ac4c6 100644 --- a/trunk/drivers/staging/csr/wext_events.c +++ b/trunk/drivers/staging/csr/wext_events.c @@ -194,9 +194,11 @@ _send_michaelmicfailure_event(struct net_device *dev, union iwreq_data wrqu; char buf[128]; - sprintf(buf, - "MLME-MICHAELMICFAILURE.indication(keyid=%d %scast addr=%pM)", - key_idx, (key_type == CSR_GROUP) ? "broad" : "uni", macaddr); + sprintf(buf, + "MLME-MICHAELMICFAILURE.indication(keyid=%d %scast addr=%02x:%02x:%02x:%02x:%02x:%02x)", + key_idx, (key_type == CSR_GROUP) ? "broad" : "uni", + macaddr[0], macaddr[1], macaddr[2], + macaddr[3], macaddr[4], macaddr[5]); memset(&wrqu, 0, sizeof(wrqu)); wrqu.data.length = strlen(buf); wireless_send_event(dev, IWEVCUSTOM, &wrqu, buf); diff --git a/trunk/drivers/staging/cxt1e1/linux.c b/trunk/drivers/staging/cxt1e1/linux.c index 0ff2865edec8..911c0e4375fd 100644 --- a/trunk/drivers/staging/cxt1e1/linux.c +++ b/trunk/drivers/staging/cxt1e1/linux.c @@ -405,7 +405,7 @@ c4_linux_xmit (struct sk_buff * skb, struct net_device * ndev) priv = hdlc->priv; rval = musycc_start_xmit (priv->ci, priv->channum, skb); - return rval; + return -rval; } static const struct net_device_ops chan_ops = { @@ -1169,11 +1169,11 @@ cleanup_hdlc (void) STATIC void __exit c4_mod_remove (void) { - cleanup_hdlc(); /* delete any missed channels */ - cleanup_devs(); - c4_cleanup(); - cleanup_ioremap(); - pr_info("SBE - driver removed.\n"); + cleanup_hdlc (); /* delete any missed channels */ + cleanup_devs (); + c4_cleanup (); + cleanup_ioremap (); + pr_info("SBE - driver removed.\n"); } module_init (c4_mod_init); diff --git a/trunk/drivers/staging/cxt1e1/musycc.c b/trunk/drivers/staging/cxt1e1/musycc.c index ba721c604061..90c0f1e30f65 100644 --- a/trunk/drivers/staging/cxt1e1/musycc.c +++ b/trunk/drivers/staging/cxt1e1/musycc.c @@ -1761,15 +1761,15 @@ musycc_start_xmit (ci_t * ci, int channum, void *mem_token) u_int32_t len; if (!(ch = sd_find_chan (ci, channum))) - return -ENOENT; + return ENOENT; if (ci->state != C_RUNNING) /* full interrupt processing available */ - return -EINVAL; + return EINVAL; if (ch->state != UP) - return -EINVAL; + return EINVAL; if (!(ch->status & TX_ENABLED)) - return -EROFS; /* how else to flag unwritable state ? */ + return EROFS; /* how else to flag unwritable state ? */ #ifdef RLD_TRANS_DEBUGx if (1 || cxt1e1_log_level >= LOG_MONITOR2) @@ -1836,7 +1836,7 @@ musycc_start_xmit (ci_t * ci, int channum, void *mem_token) #if 0 spin_unlock_irqrestore (&ch->ch_txlock, flags); #endif - return -EBUSY; /* tell user to try again later */ + return EBUSY; /* tell user to try again later */ } /**************************************************/ /** Put the user data into MUSYCC data buffer(s) **/ diff --git a/trunk/drivers/staging/dgrp/Kconfig b/trunk/drivers/staging/dgrp/Kconfig deleted file mode 100644 index 39f4bb65ec83..000000000000 --- a/trunk/drivers/staging/dgrp/Kconfig +++ /dev/null @@ -1,9 +0,0 @@ -config DGRP - tristate "Digi Realport driver" - default n - depends on SYSFS - ---help--- - Support for Digi Realport devices. These devices allow you to - access remote serial ports as if they are local tty devices. This - will build the kernel driver, you will still need the userspace - component to make your Realport device work. diff --git a/trunk/drivers/staging/dgrp/Makefile b/trunk/drivers/staging/dgrp/Makefile deleted file mode 100644 index d9c3b88d7162..000000000000 --- a/trunk/drivers/staging/dgrp/Makefile +++ /dev/null @@ -1,12 +0,0 @@ -obj-$(CONFIG_DGRP) += dgrp.o - -dgrp-y := \ - dgrp_common.o \ - dgrp_dpa_ops.o \ - dgrp_driver.o \ - dgrp_mon_ops.o \ - dgrp_net_ops.o \ - dgrp_ports_ops.o \ - dgrp_specproc.o \ - dgrp_tty.o \ - dgrp_sysfs.o diff --git a/trunk/drivers/staging/dgrp/README b/trunk/drivers/staging/dgrp/README deleted file mode 100644 index 1d8aaee270e8..000000000000 --- a/trunk/drivers/staging/dgrp/README +++ /dev/null @@ -1,2 +0,0 @@ -The user space code to work with this driver is located at -https://github.com/wfp5p/dgrp-utils diff --git a/trunk/drivers/staging/dgrp/TODO b/trunk/drivers/staging/dgrp/TODO deleted file mode 100644 index 3ef2611bc6d7..000000000000 --- a/trunk/drivers/staging/dgrp/TODO +++ /dev/null @@ -1,13 +0,0 @@ -- Use configfs for config stuff. This will require changes to the - user space code. - -- dgrp_send() and dgrp_receive() could use some refactoring - -- Don't automatically create CHAN_MAX (64) channel array entries for - every device as many devices are going to have much less than 64 - channels. - -- The locking needs to be checked. It seems haphazardly done in most - places. - -- Check Kconfig dependencies diff --git a/trunk/drivers/staging/dgrp/dgrp_common.c b/trunk/drivers/staging/dgrp/dgrp_common.c deleted file mode 100644 index fce74e7fb834..000000000000 --- a/trunk/drivers/staging/dgrp/dgrp_common.c +++ /dev/null @@ -1,200 +0,0 @@ -/* - * - * Copyright 1999 Digi International (www.digi.com) - * James Puzzo - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the - * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR - * PURPOSE. See the GNU General Public License for more details. - * - */ - -/* - * - * Filename: - * - * dgrp_common.c - * - * Description: - * - * Definitions of global variables and functions which are either - * shared by the tty, mon, and net drivers; or which cross them - * functionally (like the poller). - * - * Author: - * - * James A. Puzzo - * - */ - -#include -#include -#include -#include - -#include "dgrp_common.h" - -/** - * dgrp_carrier -- check for carrier change state and act - * @ch: struct ch_struct * - */ -void dgrp_carrier(struct ch_struct *ch) -{ - struct nd_struct *nd; - - int virt_carrier = 0; - int phys_carrier = 0; - - /* fix case when the tty has already closed. */ - - if (!ch) - return; - nd = ch->ch_nd; - if (!nd) - return; - - /* - * If we are currently waiting to determine the status of the port, - * we don't yet know the state of the modem lines. As a result, - * we ignore state changes when we are waiting for the modem lines - * to be established. We know, as a result of code in dgrp_net_ops, - * that we will be called again immediately following the reception - * of the status message with the true modem status flags in it. - */ - if (ch->ch_expect & RR_STATUS) - return; - - /* - * If CH_HANGUP is set, we gotta keep trying to get all the processes - * that have the port open to close the port. - * So lets just keep sending a hangup every time we get here. - */ - if ((ch->ch_flag & CH_HANGUP) && - (ch->ch_tun.un_open_count > 0)) - tty_hangup(ch->ch_tun.un_tty); - - /* - * Compute the effective state of both the physical and virtual - * senses of carrier. - */ - - if (ch->ch_s_mlast & DM_CD) - phys_carrier = 1; - - if ((ch->ch_s_mlast & DM_CD) || - (ch->ch_digi.digi_flags & DIGI_FORCEDCD) || - (ch->ch_flag & CH_CLOCAL)) - virt_carrier = 1; - - /* - * Test for a VIRTUAL carrier transition to HIGH. - * - * The CH_HANGUP condition is intended to prevent any action - * except for close. As a result, we ignore positive carrier - * transitions during CH_HANGUP. - */ - if (((ch->ch_flag & CH_HANGUP) == 0) && - ((ch->ch_flag & CH_VIRT_CD) == 0) && - (virt_carrier == 1)) { - /* - * When carrier rises, wake any threads waiting - * for carrier in the open routine. - */ - nd->nd_tx_work = 1; - - if (waitqueue_active(&ch->ch_flag_wait)) - wake_up_interruptible(&ch->ch_flag_wait); - } - - /* - * Test for a PHYSICAL transition to low, so long as we aren't - * currently ignoring physical transitions (which is what "virtual - * carrier" indicates). - * - * The transition of the virtual carrier to low really doesn't - * matter... it really only means "ignore carrier state", not - * "make pretend that carrier is there". - */ - if ((virt_carrier == 0) && - ((ch->ch_flag & CH_PHYS_CD) != 0) && - (phys_carrier == 0)) { - /* - * When carrier drops: - * - * Do a Hard Hangup if that is called for. - * - * Drop carrier on all open units. - * - * Flush queues, waking up any task waiting in the - * line discipline. - * - * Send a hangup to the control terminal. - * - * Enable all select calls. - */ - - nd->nd_tx_work = 1; - - ch->ch_flag &= ~(CH_LOW | CH_EMPTY | CH_DRAIN | CH_INPUT); - - if (waitqueue_active(&ch->ch_flag_wait)) - wake_up_interruptible(&ch->ch_flag_wait); - - if (ch->ch_tun.un_open_count > 0) - tty_hangup(ch->ch_tun.un_tty); - - if (ch->ch_pun.un_open_count > 0) - tty_hangup(ch->ch_pun.un_tty); - } - - /* - * Make sure that our cached values reflect the current reality. - */ - if (virt_carrier == 1) - ch->ch_flag |= CH_VIRT_CD; - else - ch->ch_flag &= ~CH_VIRT_CD; - - if (phys_carrier == 1) - ch->ch_flag |= CH_PHYS_CD; - else - ch->ch_flag &= ~CH_PHYS_CD; - -} - -/** - * dgrp_chk_perm() -- check permissions for net device - * @inode: pointer to inode structure for the net communication device - * @op: operation to be tested - * - * The file permissions and ownerships are tested to determine whether - * the operation "op" is permitted on the file pointed to by the inode. - * Returns 0 if the operation is permitted, -EACCESS otherwise - */ -int dgrp_chk_perm(int mode, int op) -{ - if (!current_euid()) - mode >>= 6; - else if (in_egroup_p(0)) - mode >>= 3; - - if ((mode & op & 0007) == op) - return 0; - - if (capable(CAP_SYS_ADMIN)) - return 0; - - return -EACCES; -} - -/* dgrp_chk_perm wrapper for permission call in struct inode_operations */ -int dgrp_inode_permission(struct inode *inode, int op) -{ - return dgrp_chk_perm(inode->i_mode, op); -} diff --git a/trunk/drivers/staging/dgrp/dgrp_common.h b/trunk/drivers/staging/dgrp/dgrp_common.h deleted file mode 100644 index 05ff338471ac..000000000000 --- a/trunk/drivers/staging/dgrp/dgrp_common.h +++ /dev/null @@ -1,208 +0,0 @@ -/* - * - * Copyright 1999 Digi International (www.digi.com) - * James Puzzo - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the - * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR - * PURPOSE. See the GNU General Public License for more details. - * - */ - -#ifndef __DGRP_COMMON_H -#define __DGRP_COMMON_H - -#define DIGI_VERSION "1.9-29" - -#include -#include -#include "drp.h" - -#define DGRP_TTIME 100 -#define DGRP_RTIME 100 - -/************************************************************************ - * All global storage allocation. - ************************************************************************/ - -extern int dgrp_rawreadok; /* Allow raw writing of input */ -extern int dgrp_register_cudevices; /* enable legacy cu devices */ -extern int dgrp_register_prdevices; /* enable transparent print devices */ -extern int dgrp_poll_tick; /* Poll interval - in ms */ - -extern struct list_head nd_struct_list; - -struct dgrp_poll_data { - spinlock_t poll_lock; - struct timer_list timer; - int poll_tick; - ulong poll_round; /* Timer rouding factor */ - long node_active_count; -}; - -extern struct dgrp_poll_data dgrp_poll_data; -extern void dgrp_poll_handler(unsigned long arg); - -/* from dgrp_mon_ops.c */ -extern void dgrp_register_mon_hook(struct proc_dir_entry *de); - -/* from dgrp_tty.c */ -extern int dgrp_tty_init(struct nd_struct *nd); -extern void dgrp_tty_uninit(struct nd_struct *nd); - -/* from dgrp_ports_ops.c */ -extern void dgrp_register_ports_hook(struct proc_dir_entry *de); - -/* from dgrp_net_ops.c */ -extern void dgrp_register_net_hook(struct proc_dir_entry *de); - -/* from dgrp_dpa_ops.c */ -extern void dgrp_register_dpa_hook(struct proc_dir_entry *de); -extern void dgrp_dpa_data(struct nd_struct *, int, u8 *, int); - -/* from dgrp_sysfs.c */ -extern void dgrp_create_class_sysfs_files(void); -extern void dgrp_remove_class_sysfs_files(void); - -extern void dgrp_create_node_class_sysfs_files(struct nd_struct *nd); -extern void dgrp_remove_node_class_sysfs_files(struct nd_struct *nd); - -extern void dgrp_create_tty_sysfs(struct un_struct *un, struct device *c); -extern void dgrp_remove_tty_sysfs(struct device *c); - -/* from dgrp_specproc.c */ -/* - * The list of DGRP entries with r/w capabilities. These - * magic numbers are used for identification purposes. - */ -enum { - DGRP_CONFIG = 1, /* Configure portservers */ - DGRP_NETDIR = 2, /* Directory for "net" devices */ - DGRP_MONDIR = 3, /* Directory for "mon" devices */ - DGRP_PORTSDIR = 4, /* Directory for "ports" devices */ - DGRP_INFO = 5, /* Get info. about the running module */ - DGRP_NODEINFO = 6, /* Get info. about the configured nodes */ - DGRP_DPADIR = 7, /* Directory for the "dpa" devices */ -}; - -/* - * Directions for proc handlers - */ -enum { - INBOUND = 1, /* Data being written to kernel */ - OUTBOUND = 2, /* Data being read from the kernel */ -}; - -/** - * dgrp_proc_entry: structure for dgrp proc dirs - * @id: ID number associated with this particular entry. Should be - * unique across all of DGRP. - * @name: text name associated with the /proc entry - * @mode: file access permisssions for the /proc entry - * @child: pointer to table describing a subdirectory for this entry - * @de: pointer to directory entry for this object once registered. Used - * to grab the handle of the object for unregistration - * @excl_sem: semaphore to provide exclusive to struct - * @excl_cnt: counter of current accesses - * - * Each entry in a DGRP proc directory is described with a - * dgrp_proc_entry structure. A collection of these - * entries (in an array) represents the members associated - * with a particular /proc directory, and is referred to - * as a table. All tables are terminated by an entry with - * zeros for every member. - */ -struct dgrp_proc_entry { - int id; /* Integer identifier */ - const char *name; /* ASCII identifier */ - mode_t mode; /* File access permissions */ - struct dgrp_proc_entry *child; /* Child pointer */ - - /* file ops to use, pass NULL to use default */ - struct file_operations *proc_file_ops; - - struct proc_dir_entry *de; /* proc entry pointer */ - struct semaphore excl_sem; /* Protects exclusive access var */ - int excl_cnt; /* Counts number of curr accesses */ -}; - -extern void dgrp_unregister_proc(void); -extern void dgrp_register_proc(void); - -/*-----------------------------------------------------------------------* - * - * Declarations for common operations: - * - * (either used by more than one of net, mon, or tty, - * or in interrupt context (i.e. the poller)) - * - *-----------------------------------------------------------------------*/ - -void dgrp_carrier(struct ch_struct *ch); -extern int dgrp_inode_permission(struct inode *inode, int op); -extern int dgrp_chk_perm(int mode, int op); - - -/* - * ID manipulation macros (where c1 & c2 are characters, i is - * a long integer, and s is a character array of at least three members - */ - -static inline void ID_TO_CHAR(long i, char *s) -{ - s[0] = ((i & 0xff00)>>8); - s[1] = (i & 0xff); - s[2] = 0; -} - -static inline long CHAR_TO_ID(char *s) -{ - return ((s[0] & 0xff) << 8) | (s[1] & 0xff); -} - -static inline struct nd_struct *nd_struct_get(long major) -{ - struct nd_struct *nd; - - list_for_each_entry(nd, &nd_struct_list, list) { - if (major == nd->nd_major) - return nd; - } - - return NULL; -} - -static inline int nd_struct_add(struct nd_struct *entry) -{ - struct nd_struct *ptr; - - ptr = nd_struct_get(entry->nd_major); - - if (ptr) - return -EBUSY; - - list_add_tail(&entry->list, &nd_struct_list); - - return 0; -} - -static inline int nd_struct_del(struct nd_struct *entry) -{ - struct nd_struct *nd; - - nd = nd_struct_get(entry->nd_major); - - if (!nd) - return -ENODEV; - - list_del(&nd->list); - return 0; -} - -#endif /* __DGRP_COMMON_H */ diff --git a/trunk/drivers/staging/dgrp/dgrp_dpa_ops.c b/trunk/drivers/staging/dgrp/dgrp_dpa_ops.c deleted file mode 100644 index 49e670915e5c..000000000000 --- a/trunk/drivers/staging/dgrp/dgrp_dpa_ops.c +++ /dev/null @@ -1,556 +0,0 @@ -/* - * - * Copyright 1999 Digi International (www.digi.com) - * James Puzzo - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the - * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR - * PURPOSE. See the GNU General Public License for more details. - * - */ - -/* - * - * Filename: - * - * dgrp_dpa_ops.c - * - * Description: - * - * Handle the file operations required for the "dpa" devices. - * Includes those functions required to register the "dpa" devices - * in "/proc". - * - * Author: - * - * James A. Puzzo - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "dgrp_common.h" - -/* File operation declarations */ -static int dgrp_dpa_open(struct inode *, struct file *); -static int dgrp_dpa_release(struct inode *, struct file *); -static ssize_t dgrp_dpa_read(struct file *, char __user *, size_t, loff_t *); -static long dgrp_dpa_ioctl(struct file *file, unsigned int cmd, - unsigned long arg); -static unsigned int dgrp_dpa_select(struct file *, struct poll_table_struct *); - -static const struct file_operations dpa_ops = { - .owner = THIS_MODULE, - .read = dgrp_dpa_read, - .poll = dgrp_dpa_select, - .unlocked_ioctl = dgrp_dpa_ioctl, - .open = dgrp_dpa_open, - .release = dgrp_dpa_release, -}; - -static struct inode_operations dpa_inode_ops = { - .permission = dgrp_inode_permission -}; - - - -struct digi_node { - uint nd_state; /* Node state: 1 = up, 0 = down. */ - uint nd_chan_count; /* Number of channels found */ - uint nd_tx_byte; /* Tx data count */ - uint nd_rx_byte; /* RX data count */ - u8 nd_ps_desc[MAX_DESC_LEN]; /* Description from PS */ -}; - -#define DIGI_GETNODE (('d'<<8) | 249) /* get board info */ - - -struct digi_chan { - uint ch_port; /* Port number to get info on */ - uint ch_open; /* 1 if open, 0 if not */ - uint ch_txcount; /* TX data count */ - uint ch_rxcount; /* RX data count */ - uint ch_s_brate; /* Realport BRATE */ - uint ch_s_estat; /* Realport ELAST */ - uint ch_s_cflag; /* Realport CFLAG */ - uint ch_s_iflag; /* Realport IFLAG */ - uint ch_s_oflag; /* Realport OFLAG */ - uint ch_s_xflag; /* Realport XFLAG */ - uint ch_s_mstat; /* Realport MLAST */ -}; - -#define DIGI_GETCHAN (('d'<<8) | 248) /* get channel info */ - - -struct digi_vpd { - int vpd_len; - char vpd_data[VPDSIZE]; -}; - -#define DIGI_GETVPD (('d'<<8) | 246) /* get VPD info */ - - -struct digi_debug { - int onoff; - int port; -}; - -#define DIGI_SETDEBUG (('d'<<8) | 247) /* set debug info */ - - -void dgrp_register_dpa_hook(struct proc_dir_entry *de) -{ - struct nd_struct *node = de->data; - - de->proc_iops = &dpa_inode_ops; - de->proc_fops = &dpa_ops; - - node->nd_dpa_de = de; - spin_lock_init(&node->nd_dpa_lock); -} - -/* - * dgrp_dpa_open -- open the DPA device for a particular PortServer - */ -static int dgrp_dpa_open(struct inode *inode, struct file *file) -{ - struct nd_struct *nd; - int rtn = 0; - - struct proc_dir_entry *de; - - rtn = try_module_get(THIS_MODULE); - if (!rtn) - return -ENXIO; - - rtn = 0; - - if (!capable(CAP_SYS_ADMIN)) { - rtn = -EPERM; - goto done; - } - - /* - * Make sure that the "private_data" field hasn't already been used. - */ - if (file->private_data) { - rtn = -EINVAL; - goto done; - } - - /* - * Get the node pointer, and fail if it doesn't exist. - */ - de = PDE(inode); - if (!de) { - rtn = -ENXIO; - goto done; - } - nd = (struct nd_struct *)de->data; - if (!nd) { - rtn = -ENXIO; - goto done; - } - - file->private_data = (void *) nd; - - /* - * Allocate the DPA buffer. - */ - - if (nd->nd_dpa_buf) { - rtn = -EBUSY; - } else { - nd->nd_dpa_buf = kmalloc(DPA_MAX, GFP_KERNEL); - - if (!nd->nd_dpa_buf) { - rtn = -ENOMEM; - } else { - nd->nd_dpa_out = 0; - nd->nd_dpa_in = 0; - nd->nd_dpa_lbolt = jiffies; - } - } - -done: - - if (rtn) - module_put(THIS_MODULE); - return rtn; -} - -/* - * dgrp_dpa_release -- close the DPA device for a particular PortServer - */ -static int dgrp_dpa_release(struct inode *inode, struct file *file) -{ - struct nd_struct *nd; - u8 *buf; - unsigned long lock_flags; - - /* - * Get the node pointer, and quit if it doesn't exist. - */ - nd = (struct nd_struct *)(file->private_data); - if (!nd) - goto done; - - /* - * Free the dpa buffer. - */ - - spin_lock_irqsave(&nd->nd_dpa_lock, lock_flags); - - buf = nd->nd_dpa_buf; - - nd->nd_dpa_buf = NULL; - nd->nd_dpa_out = nd->nd_dpa_in; - - /* - * Wakeup any thread waiting for buffer space. - */ - - if (nd->nd_dpa_flag & DPA_WAIT_SPACE) { - nd->nd_dpa_flag &= ~DPA_WAIT_SPACE; - wake_up_interruptible(&nd->nd_dpa_wqueue); - } - - spin_unlock_irqrestore(&nd->nd_dpa_lock, lock_flags); - - kfree(buf); - -done: - module_put(THIS_MODULE); - file->private_data = NULL; - return 0; -} - -/* - * dgrp_dpa_read - * - * Copy data from the monitoring buffer to the user, freeing space - * in the monitoring buffer for more messages - */ -static ssize_t dgrp_dpa_read(struct file *file, char __user *buf, size_t count, - loff_t *ppos) -{ - struct nd_struct *nd; - int n; - int r; - int offset = 0; - int res = 0; - ssize_t rtn; - unsigned long lock_flags; - - /* - * Get the node pointer, and quit if it doesn't exist. - */ - nd = (struct nd_struct *)(file->private_data); - if (!nd) - return -ENXIO; - - /* - * Wait for some data to appear in the buffer. - */ - - spin_lock_irqsave(&nd->nd_dpa_lock, lock_flags); - - for (;;) { - n = (nd->nd_dpa_in - nd->nd_dpa_out) & DPA_MASK; - - if (n != 0) - break; - - nd->nd_dpa_flag |= DPA_WAIT_DATA; - - spin_unlock_irqrestore(&nd->nd_dpa_lock, lock_flags); - - /* - * Go to sleep waiting until the condition becomes true. - */ - rtn = wait_event_interruptible(nd->nd_dpa_wqueue, - ((nd->nd_dpa_flag & DPA_WAIT_DATA) == 0)); - - if (rtn) - return rtn; - - spin_lock_irqsave(&nd->nd_dpa_lock, lock_flags); - } - - /* - * Read whatever is there. - */ - - if (n > count) - n = count; - - res = n; - - r = DPA_MAX - nd->nd_dpa_out; - - if (r <= n) { - - spin_unlock_irqrestore(&nd->nd_dpa_lock, lock_flags); - rtn = copy_to_user((void __user *)buf, - nd->nd_dpa_buf + nd->nd_dpa_out, r); - spin_lock_irqsave(&nd->nd_dpa_lock, lock_flags); - - if (rtn) { - rtn = -EFAULT; - goto done; - } - - nd->nd_dpa_out = 0; - n -= r; - offset = r; - } - - spin_unlock_irqrestore(&nd->nd_dpa_lock, lock_flags); - rtn = copy_to_user((void __user *)buf + offset, - nd->nd_dpa_buf + nd->nd_dpa_out, n); - spin_lock_irqsave(&nd->nd_dpa_lock, lock_flags); - - if (rtn) { - rtn = -EFAULT; - goto done; - } - - nd->nd_dpa_out += n; - - *ppos += res; - - rtn = res; - - /* - * Wakeup any thread waiting for buffer space. - */ - - n = (nd->nd_dpa_in - nd->nd_dpa_out) & DPA_MASK; - - if (nd->nd_dpa_flag & DPA_WAIT_SPACE && - (DPA_MAX - n) > DPA_HIGH_WATER) { - nd->nd_dpa_flag &= ~DPA_WAIT_SPACE; - wake_up_interruptible(&nd->nd_dpa_wqueue); - } - - done: - spin_unlock_irqrestore(&nd->nd_dpa_lock, lock_flags); - return rtn; -} - -static unsigned int dgrp_dpa_select(struct file *file, - struct poll_table_struct *table) -{ - unsigned int retval = 0; - struct nd_struct *nd = file->private_data; - - if (nd->nd_dpa_out != nd->nd_dpa_in) - retval |= POLLIN | POLLRDNORM; /* Conditionally readable */ - - retval |= POLLOUT | POLLWRNORM; /* Always writeable */ - - return retval; -} - -static long dgrp_dpa_ioctl(struct file *file, unsigned int cmd, - unsigned long arg) -{ - - struct nd_struct *nd; - struct digi_chan getchan; - struct digi_node getnode; - struct ch_struct *ch; - struct digi_debug setdebug; - struct digi_vpd vpd; - unsigned int port; - void __user *uarg = (void __user *) arg; - - nd = file->private_data; - - switch (cmd) { - case DIGI_GETCHAN: - if (copy_from_user(&getchan, uarg, sizeof(struct digi_chan))) - return -EFAULT; - - port = getchan.ch_port; - - if (port < 0 || port > nd->nd_chan_count) - return -EINVAL; - - ch = nd->nd_chan + port; - - getchan.ch_open = (ch->ch_open_count > 0) ? 1 : 0; - getchan.ch_txcount = ch->ch_txcount; - getchan.ch_rxcount = ch->ch_rxcount; - getchan.ch_s_brate = ch->ch_s_brate; - getchan.ch_s_estat = ch->ch_s_elast; - getchan.ch_s_cflag = ch->ch_s_cflag; - getchan.ch_s_iflag = ch->ch_s_iflag; - getchan.ch_s_oflag = ch->ch_s_oflag; - getchan.ch_s_xflag = ch->ch_s_xflag; - getchan.ch_s_mstat = ch->ch_s_mlast; - - if (copy_to_user(uarg, &getchan, sizeof(struct digi_chan))) - return -EFAULT; - break; - - - case DIGI_GETNODE: - getnode.nd_state = (nd->nd_state & NS_READY) ? 1 : 0; - getnode.nd_chan_count = nd->nd_chan_count; - getnode.nd_tx_byte = nd->nd_tx_byte; - getnode.nd_rx_byte = nd->nd_rx_byte; - - memset(&getnode.nd_ps_desc, 0, MAX_DESC_LEN); - strncpy(getnode.nd_ps_desc, nd->nd_ps_desc, MAX_DESC_LEN); - - if (copy_to_user(uarg, &getnode, sizeof(struct digi_node))) - return -EFAULT; - break; - - - case DIGI_SETDEBUG: - if (copy_from_user(&setdebug, uarg, sizeof(struct digi_debug))) - return -EFAULT; - - nd->nd_dpa_debug = setdebug.onoff; - nd->nd_dpa_port = setdebug.port; - break; - - - case DIGI_GETVPD: - if (nd->nd_vpd_len > 0) { - vpd.vpd_len = nd->nd_vpd_len; - memcpy(&vpd.vpd_data, &nd->nd_vpd, nd->nd_vpd_len); - } else { - vpd.vpd_len = 0; - } - - if (copy_to_user(uarg, &vpd, sizeof(struct digi_vpd))) - return -EFAULT; - break; - } - - return 0; -} - -/** - * dgrp_dpa() -- send data to the device monitor queue - * @nd: pointer to a node structure - * @buf: buffer of data to copy to the monitoring buffer - * @len: number of bytes to transfer to the buffer - * - * Called by the net device routines to send data to the device - * monitor queue. If the device monitor buffer is too full to - * accept the data, it waits until the buffer is ready. - */ -static void dgrp_dpa(struct nd_struct *nd, u8 *buf, int nbuf) -{ - int n; - int r; - unsigned long lock_flags; - - /* - * Grab DPA lock. - */ - spin_lock_irqsave(&nd->nd_dpa_lock, lock_flags); - - /* - * Loop while data remains. - */ - while (nbuf > 0 && nd->nd_dpa_buf != NULL) { - - n = (nd->nd_dpa_out - nd->nd_dpa_in - 1) & DPA_MASK; - - /* - * Enforce flow control on the DPA device. - */ - if (n < (DPA_MAX - DPA_HIGH_WATER)) - nd->nd_dpa_flag |= DPA_WAIT_SPACE; - - /* - * This should never happen, as the flow control above - * should have stopped things before they got to this point. - */ - if (n == 0) { - spin_unlock_irqrestore(&nd->nd_dpa_lock, lock_flags); - return; - } - - /* - * Copy as much data as will fit. - */ - - if (n > nbuf) - n = nbuf; - - r = DPA_MAX - nd->nd_dpa_in; - - if (r <= n) { - memcpy(nd->nd_dpa_buf + nd->nd_dpa_in, buf, r); - - n -= r; - - nd->nd_dpa_in = 0; - - buf += r; - nbuf -= r; - } - - memcpy(nd->nd_dpa_buf + nd->nd_dpa_in, buf, n); - - nd->nd_dpa_in += n; - - buf += n; - nbuf -= n; - - if (nd->nd_dpa_in >= DPA_MAX) - pr_info_ratelimited("%s - nd->nd_dpa_in (%i) >= DPA_MAX\n", - __func__, nd->nd_dpa_in); - - /* - * Wakeup any thread waiting for data - */ - if (nd->nd_dpa_flag & DPA_WAIT_DATA) { - nd->nd_dpa_flag &= ~DPA_WAIT_DATA; - wake_up_interruptible(&nd->nd_dpa_wqueue); - } - } - - /* - * Release the DPA lock. - */ - spin_unlock_irqrestore(&nd->nd_dpa_lock, lock_flags); -} - -/** - * dgrp_monitor_data() -- builds a DPA data packet - * @nd: pointer to a node structure - * @type: type of message to be logged in the DPA buffer - * @buf: buffer of data to be logged in the DPA buffer - * @size -- number of bytes in the "buf" buffer - */ -void dgrp_dpa_data(struct nd_struct *nd, int type, u8 *buf, int size) -{ - u8 header[5]; - - header[0] = type; - - put_unaligned_be32(size, header + 1); - - dgrp_dpa(nd, header, sizeof(header)); - dgrp_dpa(nd, buf, size); -} diff --git a/trunk/drivers/staging/dgrp/dgrp_driver.c b/trunk/drivers/staging/dgrp/dgrp_driver.c deleted file mode 100644 index 6e4a0ebc0749..000000000000 --- a/trunk/drivers/staging/dgrp/dgrp_driver.c +++ /dev/null @@ -1,110 +0,0 @@ -/* - * - * Copyright 1999-2003 Digi International (www.digi.com) - * Jeff Randall - * James Puzzo - * Scott Kilau - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the - * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR - * PURPOSE. See the GNU General Public License for more details. - * - */ - -/* - * Driver specific includes - */ -#include -#include -#include -#include - -/* - * PortServer includes - */ -#include "dgrp_common.h" - - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Digi International, http://www.digi.com"); -MODULE_DESCRIPTION("RealPort driver for Digi's ethernet-based serial connectivity product line"); -MODULE_VERSION(DIGI_VERSION); - -struct list_head nd_struct_list; -struct dgrp_poll_data dgrp_poll_data; - -int dgrp_rawreadok = 1; /* Bypass flipbuf on input */ -int dgrp_register_cudevices = 1;/* Turn on/off registering legacy cu devices */ -int dgrp_register_prdevices = 1;/* Turn on/off registering transparent print */ -int dgrp_poll_tick = 20; /* Poll interval - in ms */ - -module_param_named(rawreadok, dgrp_rawreadok, int, 0644); -MODULE_PARM_DESC(rawreadok, "Bypass flip buffers on input"); - -module_param_named(register_cudevices, dgrp_register_cudevices, int, 0644); -MODULE_PARM_DESC(register_cudevices, "Turn on/off registering legacy cu devices"); - -module_param_named(register_prdevices, dgrp_register_prdevices, int, 0644); -MODULE_PARM_DESC(register_prdevices, "Turn on/off registering transparent print devices"); - -module_param_named(pollrate, dgrp_poll_tick, int, 0644); -MODULE_PARM_DESC(pollrate, "Poll interval in ms"); - -/* Driver load/unload functions */ -static int dgrp_init_module(void); -static void dgrp_cleanup_module(void); - -module_init(dgrp_init_module); -module_exit(dgrp_cleanup_module); - -/* - * init_module() - * - * Module load. This is where it all starts. - */ -static int dgrp_init_module(void) -{ - INIT_LIST_HEAD(&nd_struct_list); - - spin_lock_init(&dgrp_poll_data.poll_lock); - init_timer(&dgrp_poll_data.timer); - dgrp_poll_data.poll_tick = dgrp_poll_tick; - dgrp_poll_data.timer.function = dgrp_poll_handler; - dgrp_poll_data.timer.data = (unsigned long) &dgrp_poll_data; - - dgrp_create_class_sysfs_files(); - - dgrp_register_proc(); - - return 0; -} - - -/* - * Module unload. This is where it all ends. - */ -static void dgrp_cleanup_module(void) -{ - struct nd_struct *nd, *next; - - /* - * Attempting to free resources in backwards - * order of allocation, in case that helps - * memory pool fragmentation. - */ - dgrp_unregister_proc(); - - dgrp_remove_class_sysfs_files(); - - - list_for_each_entry_safe(nd, next, &nd_struct_list, list) { - dgrp_tty_uninit(nd); - kfree(nd); - } -} diff --git a/trunk/drivers/staging/dgrp/dgrp_mon_ops.c b/trunk/drivers/staging/dgrp/dgrp_mon_ops.c deleted file mode 100644 index 268dcb95204b..000000000000 --- a/trunk/drivers/staging/dgrp/dgrp_mon_ops.c +++ /dev/null @@ -1,346 +0,0 @@ -/***************************************************************************** - * - * Copyright 1999 Digi International (www.digi.com) - * James Puzzo - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the - * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR - * PURPOSE. See the GNU General Public License for more details. - * - */ - -/* - * - * Filename: - * - * dgrp_mon_ops.c - * - * Description: - * - * Handle the file operations required for the "monitor" devices. - * Includes those functions required to register the "mon" devices - * in "/proc". - * - * Author: - * - * James A. Puzzo - * - */ - -#include -#include -#include -#include -#include - -#include "dgrp_common.h" - -/* File operation declarations */ -static int dgrp_mon_open(struct inode *, struct file *); -static int dgrp_mon_release(struct inode *, struct file *); -static ssize_t dgrp_mon_read(struct file *, char __user *, size_t, loff_t *); -static long dgrp_mon_ioctl(struct file *file, unsigned int cmd, - unsigned long arg); - -static const struct file_operations mon_ops = { - .owner = THIS_MODULE, - .read = dgrp_mon_read, - .unlocked_ioctl = dgrp_mon_ioctl, - .open = dgrp_mon_open, - .release = dgrp_mon_release, -}; - -static struct inode_operations mon_inode_ops = { - .permission = dgrp_inode_permission -}; - -void dgrp_register_mon_hook(struct proc_dir_entry *de) -{ - struct nd_struct *node = de->data; - - de->proc_iops = &mon_inode_ops; - de->proc_fops = &mon_ops; - node->nd_mon_de = de; - sema_init(&node->nd_mon_semaphore, 1); -} - -/** - * dgrp_mon_open() -- open /proc/dgrp/ports device for a PortServer - * @inode: struct inode * - * @file: struct file * - * - * Open function to open the /proc/dgrp/ports device for a PortServer. - */ -static int dgrp_mon_open(struct inode *inode, struct file *file) -{ - struct nd_struct *nd; - struct proc_dir_entry *de; - struct timeval tv; - uint32_t time; - u8 *buf; - int rtn; - - rtn = try_module_get(THIS_MODULE); - if (!rtn) - return -ENXIO; - - rtn = 0; - - if (!capable(CAP_SYS_ADMIN)) { - rtn = -EPERM; - goto done; - } - - /* - * Make sure that the "private_data" field hasn't already been used. - */ - if (file->private_data) { - rtn = -EINVAL; - goto done; - } - - /* - * Get the node pointer, and fail if it doesn't exist. - */ - de = PDE(inode); - if (!de) { - rtn = -ENXIO; - goto done; - } - - nd = (struct nd_struct *)de->data; - if (!nd) { - rtn = -ENXIO; - goto done; - } - - file->private_data = (void *) nd; - - /* - * Allocate the monitor buffer. - */ - - /* - * Grab the MON lock. - */ - down(&nd->nd_mon_semaphore); - - if (nd->nd_mon_buf) { - rtn = -EBUSY; - goto done_up; - } - - nd->nd_mon_buf = kmalloc(MON_MAX, GFP_KERNEL); - - if (!nd->nd_mon_buf) { - rtn = -ENOMEM; - goto done_up; - } - - /* - * Enter an RPDUMP file header into the buffer. - */ - - buf = nd->nd_mon_buf; - - strcpy(buf, RPDUMP_MAGIC); - buf += strlen(buf) + 1; - - do_gettimeofday(&tv); - - /* - * tv.tv_sec might be a 64 bit quantity. Pare - * it down to 32 bits before attempting to encode - * it. - */ - time = (uint32_t) (tv.tv_sec & 0xffffffff); - - put_unaligned_be32(time, buf); - put_unaligned_be16(0, buf + 4); - buf += 6; - - if (nd->nd_tx_module) { - buf[0] = RPDUMP_CLIENT; - put_unaligned_be32(0, buf + 1); - put_unaligned_be16(1, buf + 5); - buf[7] = 0xf0 + nd->nd_tx_module; - buf += 8; - } - - if (nd->nd_rx_module) { - buf[0] = RPDUMP_SERVER; - put_unaligned_be32(0, buf + 1); - put_unaligned_be16(1, buf + 5); - buf[7] = 0xf0 + nd->nd_rx_module; - buf += 8; - } - - nd->nd_mon_out = 0; - nd->nd_mon_in = buf - nd->nd_mon_buf; - nd->nd_mon_lbolt = jiffies; - -done_up: - up(&nd->nd_mon_semaphore); - -done: - if (rtn) - module_put(THIS_MODULE); - return rtn; -} - - -/** - * dgrp_mon_release() - Close the MON device for a particular PortServer - * @inode: struct inode * - * @file: struct file * - */ -static int dgrp_mon_release(struct inode *inode, struct file *file) -{ - struct nd_struct *nd; - - /* - * Get the node pointer, and quit if it doesn't exist. - */ - nd = (struct nd_struct *)(file->private_data); - if (!nd) - goto done; - - /* - * Free the monitor buffer. - */ - - down(&nd->nd_mon_semaphore); - - kfree(nd->nd_mon_buf); - nd->nd_mon_buf = NULL; - nd->nd_mon_out = nd->nd_mon_in; - - /* - * Wakeup any thread waiting for buffer space. - */ - - if (nd->nd_mon_flag & MON_WAIT_SPACE) { - nd->nd_mon_flag &= ~MON_WAIT_SPACE; - wake_up_interruptible(&nd->nd_mon_wqueue); - } - - up(&nd->nd_mon_semaphore); - - /* - * Make sure there is no thread in the middle of writing a packet. - */ - down(&nd->nd_net_semaphore); - up(&nd->nd_net_semaphore); - -done: - module_put(THIS_MODULE); - file->private_data = NULL; - return 0; -} - -/** - * dgrp_mon_read() -- Copy data from the monitoring buffer to the user - */ -static ssize_t dgrp_mon_read(struct file *file, char __user *buf, size_t count, - loff_t *ppos) -{ - struct nd_struct *nd; - int r; - int offset = 0; - int res = 0; - ssize_t rtn; - - /* - * Get the node pointer, and quit if it doesn't exist. - */ - nd = (struct nd_struct *)(file->private_data); - if (!nd) - return -ENXIO; - - /* - * Wait for some data to appear in the buffer. - */ - - down(&nd->nd_mon_semaphore); - - for (;;) { - res = (nd->nd_mon_in - nd->nd_mon_out) & MON_MASK; - - if (res) - break; - - nd->nd_mon_flag |= MON_WAIT_DATA; - - up(&nd->nd_mon_semaphore); - - /* - * Go to sleep waiting until the condition becomes true. - */ - rtn = wait_event_interruptible(nd->nd_mon_wqueue, - ((nd->nd_mon_flag & MON_WAIT_DATA) == 0)); - - if (rtn) - return rtn; - - down(&nd->nd_mon_semaphore); - } - - /* - * Read whatever is there. - */ - - if (res > count) - res = count; - - r = MON_MAX - nd->nd_mon_out; - - if (r <= res) { - rtn = copy_to_user((void __user *)buf, - nd->nd_mon_buf + nd->nd_mon_out, r); - if (rtn) { - up(&nd->nd_mon_semaphore); - return -EFAULT; - } - - nd->nd_mon_out = 0; - res -= r; - offset = r; - } - - rtn = copy_to_user((void __user *) buf + offset, - nd->nd_mon_buf + nd->nd_mon_out, res); - if (rtn) { - up(&nd->nd_mon_semaphore); - return -EFAULT; - } - - nd->nd_mon_out += res; - - *ppos += res; - - up(&nd->nd_mon_semaphore); - - /* - * Wakeup any thread waiting for buffer space. - */ - - if (nd->nd_mon_flag & MON_WAIT_SPACE) { - nd->nd_mon_flag &= ~MON_WAIT_SPACE; - wake_up_interruptible(&nd->nd_mon_wqueue); - } - - return res; -} - -/* ioctl is not valid on monitor device */ -static long dgrp_mon_ioctl(struct file *file, unsigned int cmd, - unsigned long arg) -{ - return -EINVAL; -} diff --git a/trunk/drivers/staging/dgrp/dgrp_net_ops.c b/trunk/drivers/staging/dgrp/dgrp_net_ops.c deleted file mode 100644 index ab839ea3b44c..000000000000 --- a/trunk/drivers/staging/dgrp/dgrp_net_ops.c +++ /dev/null @@ -1,3737 +0,0 @@ -/* - * - * Copyright 1999 Digi International (www.digi.com) - * James Puzzo - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the - * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR - * PURPOSE. See the GNU General Public License for more details. - * - */ - -/* - * - * Filename: - * - * dgrp_net_ops.c - * - * Description: - * - * Handle the file operations required for the "network" devices. - * Includes those functions required to register the "net" devices - * in "/proc". - * - * Author: - * - * James A. Puzzo - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define MYFLIPLEN TBUF_MAX - -#include "dgrp_common.h" - -#define TTY_FLIPBUF_SIZE 512 -#define DEVICE_NAME_SIZE 50 - -/* - * Generic helper function declarations - */ -static void parity_scan(struct ch_struct *ch, unsigned char *cbuf, - unsigned char *fbuf, int *len); - -/* - * File operation declarations - */ -static int dgrp_net_open(struct inode *, struct file *); -static int dgrp_net_release(struct inode *, struct file *); -static ssize_t dgrp_net_read(struct file *, char __user *, size_t, loff_t *); -static ssize_t dgrp_net_write(struct file *, const char __user *, size_t, - loff_t *); -static long dgrp_net_ioctl(struct file *file, unsigned int cmd, - unsigned long arg); -static unsigned int dgrp_net_select(struct file *file, - struct poll_table_struct *table); - -static const struct file_operations net_ops = { - .owner = THIS_MODULE, - .read = dgrp_net_read, - .write = dgrp_net_write, - .poll = dgrp_net_select, - .unlocked_ioctl = dgrp_net_ioctl, - .open = dgrp_net_open, - .release = dgrp_net_release, -}; - -static struct inode_operations net_inode_ops = { - .permission = dgrp_inode_permission -}; - -void dgrp_register_net_hook(struct proc_dir_entry *de) -{ - struct nd_struct *node = de->data; - - de->proc_iops = &net_inode_ops; - de->proc_fops = &net_ops; - node->nd_net_de = de; - sema_init(&node->nd_net_semaphore, 1); - node->nd_state = NS_CLOSED; - dgrp_create_node_class_sysfs_files(node); -} - - -/** - * dgrp_dump() -- prints memory for debugging purposes. - * @mem: Memory location which should be printed to the console - * @len: Number of bytes to be dumped - */ -static void dgrp_dump(u8 *mem, int len) -{ - int i; - - pr_debug("dgrp dump length = %d, data = ", len); - for (i = 0; i < len; ++i) - pr_debug("%.2x ", mem[i]); - pr_debug("\n"); -} - -/** - * dgrp_read_data_block() -- Read a data block - * @ch: struct ch_struct * - * @flipbuf: u8 * - * @flipbuf_size: size of flipbuf - */ -static void dgrp_read_data_block(struct ch_struct *ch, u8 *flipbuf, - int flipbuf_size) -{ - int t; - int n; - - if (flipbuf_size <= 0) - return; - - t = RBUF_MAX - ch->ch_rout; - n = flipbuf_size; - - if (n >= t) { - memcpy(flipbuf, ch->ch_rbuf + ch->ch_rout, t); - flipbuf += t; - n -= t; - ch->ch_rout = 0; - } - - memcpy(flipbuf, ch->ch_rbuf + ch->ch_rout, n); - flipbuf += n; - ch->ch_rout += n; -} - - -/** - * dgrp_input() -- send data to the line disipline - * @ch: pointer to channel struct - * - * Copys the rbuf to the flipbuf and sends to line discipline. - * Sends input buffer data to the line discipline. - * - * There are several modes to consider here: - * rawreadok, tty->real_raw, and IF_PARMRK - */ -static void dgrp_input(struct ch_struct *ch) -{ - struct nd_struct *nd; - struct tty_struct *tty; - int remain; - int data_len; - int len; - int flip_len; - int tty_count; - ulong lock_flags; - struct tty_ldisc *ld; - u8 *myflipbuf; - u8 *myflipflagbuf; - - if (!ch) - return; - - nd = ch->ch_nd; - - if (!nd) - return; - - spin_lock_irqsave(&nd->nd_lock, lock_flags); - - myflipbuf = nd->nd_inputbuf; - myflipflagbuf = nd->nd_inputflagbuf; - - if (!ch->ch_open_count) { - ch->ch_rout = ch->ch_rin; - goto out; - } - - if (ch->ch_tun.un_flag & UN_CLOSING) { - ch->ch_rout = ch->ch_rin; - goto out; - } - - tty = (ch->ch_tun).un_tty; - - - if (!tty || tty->magic != TTY_MAGIC) { - ch->ch_rout = ch->ch_rin; - goto out; - } - - tty_count = tty->count; - if (!tty_count) { - ch->ch_rout = ch->ch_rin; - goto out; - } - - if (tty->closing || test_bit(TTY_CLOSING, &tty->flags)) { - ch->ch_rout = ch->ch_rin; - goto out; - } - - spin_unlock_irqrestore(&nd->nd_lock, lock_flags); - - /* Decide how much data we can send into the tty layer */ - if (dgrp_rawreadok && tty->real_raw) - flip_len = MYFLIPLEN; - else - flip_len = TTY_FLIPBUF_SIZE; - - /* data_len should be the number of chars that we read in */ - data_len = (ch->ch_rin - ch->ch_rout) & RBUF_MASK; - remain = data_len; - - /* len is the amount of data we are going to transfer here */ - len = min(data_len, flip_len); - - /* take into consideration length of ldisc */ - len = min(len, (N_TTY_BUF_SIZE - 1) - tty->read_cnt); - - ld = tty_ldisc_ref(tty); - - /* - * If we were unable to get a reference to the ld, - * don't flush our buffer, and act like the ld doesn't - * have any space to put the data right now. - */ - if (!ld) { - len = 0; - } else if (!ld->ops->receive_buf) { - spin_lock_irqsave(&nd->nd_lock, lock_flags); - ch->ch_rout = ch->ch_rin; - spin_unlock_irqrestore(&nd->nd_lock, lock_flags); - len = 0; - } - - /* Check DPA flow control */ - if ((nd->nd_dpa_debug) && - (nd->nd_dpa_flag & DPA_WAIT_SPACE) && - (nd->nd_dpa_port == MINOR(tty_devnum(ch->ch_tun.un_tty)))) - len = 0; - - if ((len) && !(ch->ch_flag & CH_RXSTOP)) { - - dgrp_read_data_block(ch, myflipbuf, len); - - /* - * In high performance mode, we don't have to update - * flag_buf or any of the counts or pointers into flip buf. - */ - if (!dgrp_rawreadok || !tty->real_raw) { - if (I_PARMRK(tty) || I_BRKINT(tty) || I_INPCK(tty)) - parity_scan(ch, myflipbuf, myflipflagbuf, &len); - else - memset(myflipflagbuf, TTY_NORMAL, len); - } - - if ((nd->nd_dpa_debug) && - (nd->nd_dpa_port == PORT_NUM(MINOR(tty_devnum(tty))))) - dgrp_dpa_data(nd, 1, myflipbuf, len); - - /* - * If we're doing raw reads, jam it right into the - * line disc bypassing the flip buffers. - */ - if (dgrp_rawreadok && tty->real_raw) - ld->ops->receive_buf(tty, myflipbuf, NULL, len); - else { - len = tty_buffer_request_room(tty, len); - tty_insert_flip_string_flags(tty, myflipbuf, - myflipflagbuf, len); - - /* Tell the tty layer its okay to "eat" the data now */ - tty_flip_buffer_push(tty); - } - - ch->ch_rxcount += len; - } - - if (ld) - tty_ldisc_deref(ld); - - /* - * Wake up any sleepers (maybe dgrp close) that might be waiting - * for a channel flag state change. - */ - wake_up_interruptible(&ch->ch_flag_wait); - return; - -out: - spin_unlock_irqrestore(&nd->nd_lock, lock_flags); -} - - -/* - * parity_scan - * - * Loop to inspect each single character or 0xFF escape. - * - * if PARMRK & ~DOSMODE: - * 0xFF 0xFF Normal 0xFF character, escaped - * to eliminate confusion. - * 0xFF 0x00 0x00 Break - * 0xFF 0x00 CC Error character CC. - * CC Normal character CC. - * - * if PARMRK & DOSMODE: - * 0xFF 0x18 0x00 Break - * 0xFF 0x08 0x00 Framing Error - * 0xFF 0x04 0x00 Parity error - * 0xFF 0x0C 0x00 Both Framing and Parity error - * - * TODO: do we need to do the XMODEM, XOFF, XON, XANY processing?? - * as per protocol - */ -static void parity_scan(struct ch_struct *ch, unsigned char *cbuf, - unsigned char *fbuf, int *len) -{ - int l = *len; - int count = 0; - int DOS = ((ch->ch_iflag & IF_DOSMODE) == 0 ? 0 : 1); - unsigned char *cout; /* character buffer */ - unsigned char *fout; /* flag buffer */ - unsigned char *in; - unsigned char c; - - in = cbuf; - cout = cbuf; - fout = fbuf; - - while (l--) { - c = *in; - in++; - - switch (ch->ch_pscan_state) { - default: - /* reset to sanity and fall through */ - ch->ch_pscan_state = 0 ; - - case 0: - /* No FF seen yet */ - if (c == 0xff) /* delete this character from stream */ - ch->ch_pscan_state = 1; - else { - *cout++ = c; - *fout++ = TTY_NORMAL; - count += 1; - } - break; - - case 1: - /* first FF seen */ - if (c == 0xff) { - /* doubled ff, transform to single ff */ - *cout++ = c; - *fout++ = TTY_NORMAL; - count += 1; - ch->ch_pscan_state = 0; - } else { - /* save value examination in next state */ - ch->ch_pscan_savechar = c; - ch->ch_pscan_state = 2; - } - break; - - case 2: - /* third character of ff sequence */ - *cout++ = c; - if (DOS) { - if (ch->ch_pscan_savechar & 0x10) - *fout++ = TTY_BREAK; - else if (ch->ch_pscan_savechar & 0x08) - *fout++ = TTY_FRAME; - else - /* - * either marked as a parity error, - * indeterminate, or not in DOSMODE - * call it a parity error - */ - *fout++ = TTY_PARITY; - } else { - /* case FF XX ?? where XX is not 00 */ - if (ch->ch_pscan_savechar & 0xff) { - /* this should not happen */ - pr_info("%s: parity_scan: error unexpected byte\n", - __func__); - *fout++ = TTY_PARITY; - } - /* case FF 00 XX where XX is not 00 */ - else if (c == 0xff) - *fout++ = TTY_PARITY; - /* case FF 00 00 */ - else - *fout++ = TTY_BREAK; - - } - count += 1; - ch->ch_pscan_state = 0; - } - } - *len = count; -} - - -/** - * dgrp_net_idle() -- Idle the network connection - * @nd: pointer to node structure to idle - */ -static void dgrp_net_idle(struct nd_struct *nd) -{ - struct ch_struct *ch; - int i; - - nd->nd_tx_work = 1; - - nd->nd_state = NS_IDLE; - nd->nd_flag = 0; - - for (i = nd->nd_seq_out; ; i = (i + 1) & SEQ_MASK) { - if (!nd->nd_seq_wait[i]) { - nd->nd_seq_wait[i] = 0; - wake_up_interruptible(&nd->nd_seq_wque[i]); - } - - if (i == nd->nd_seq_in) - break; - } - - nd->nd_seq_out = nd->nd_seq_in; - - nd->nd_unack = 0; - nd->nd_remain = 0; - - nd->nd_tx_module = 0x10; - nd->nd_rx_module = 0x00; - - for (i = 0, ch = nd->nd_chan; i < CHAN_MAX; i++, ch++) { - ch->ch_state = CS_IDLE; - - ch->ch_otype = 0; - ch->ch_otype_waiting = 0; - } -} - -/* - * Increase the number of channels, waking up any - * threads that might be waiting for the channels - * to appear. - */ -static void increase_channel_count(struct nd_struct *nd, int n) -{ - struct ch_struct *ch; - struct device *classp; - char name[DEVICE_NAME_SIZE]; - int ret; - u8 *buf; - int i; - - for (i = nd->nd_chan_count; i < n; ++i) { - ch = nd->nd_chan + i; - - /* FIXME: return a useful error instead! */ - buf = kmalloc(TBUF_MAX, GFP_KERNEL); - if (!buf) - return; - - if (ch->ch_tbuf) - pr_info_ratelimited("%s - ch_tbuf was not NULL\n", - __func__); - - ch->ch_tbuf = buf; - - buf = kmalloc(RBUF_MAX, GFP_KERNEL); - if (!buf) - return; - - if (ch->ch_rbuf) - pr_info("%s - ch_rbuf was not NULL\n", - __func__); - ch->ch_rbuf = buf; - - classp = tty_port_register_device(&ch->port, - nd->nd_serial_ttdriver, i, - NULL); - - ch->ch_tun.un_sysfs = classp; - snprintf(name, DEVICE_NAME_SIZE, "tty_%d", i); - - dgrp_create_tty_sysfs(&ch->ch_tun, classp); - ret = sysfs_create_link(&nd->nd_class_dev->kobj, - &classp->kobj, name); - - /* NOTE: We don't support "cu" devices anymore, - * so you will notice we don't register them - * here anymore. */ - if (dgrp_register_prdevices) { - classp = tty_register_device(nd->nd_xprint_ttdriver, - i, NULL); - ch->ch_pun.un_sysfs = classp; - snprintf(name, DEVICE_NAME_SIZE, "pr_%d", i); - - dgrp_create_tty_sysfs(&ch->ch_pun, classp); - ret = sysfs_create_link(&nd->nd_class_dev->kobj, - &classp->kobj, name); - } - - nd->nd_chan_count = i + 1; - wake_up_interruptible(&ch->ch_flag_wait); - } -} - -/* - * Decrease the number of channels, and wake up any threads that might - * be waiting on the channels that vanished. - */ -static void decrease_channel_count(struct nd_struct *nd, int n) -{ - struct ch_struct *ch; - char name[DEVICE_NAME_SIZE]; - int i; - - for (i = nd->nd_chan_count - 1; i >= n; --i) { - ch = nd->nd_chan + i; - - /* - * Make any open ports inoperative. - */ - ch->ch_state = CS_IDLE; - - ch->ch_otype = 0; - ch->ch_otype_waiting = 0; - - /* - * Only "HANGUP" if we care about carrier - * transitions and we are already open. - */ - if (ch->ch_open_count != 0) { - ch->ch_flag |= CH_HANGUP; - dgrp_carrier(ch); - } - - /* - * Unlike the CH_HANGUP flag above, use another - * flag to indicate to the RealPort state machine - * that this port has disappeared. - */ - if (ch->ch_open_count != 0) - ch->ch_flag |= CH_PORT_GONE; - - wake_up_interruptible(&ch->ch_flag_wait); - - nd->nd_chan_count = i; - - kfree(ch->ch_tbuf); - ch->ch_tbuf = NULL; - - kfree(ch->ch_rbuf); - ch->ch_rbuf = NULL; - - nd->nd_chan_count = i; - - dgrp_remove_tty_sysfs(ch->ch_tun.un_sysfs); - snprintf(name, DEVICE_NAME_SIZE, "tty_%d", i); - sysfs_remove_link(&nd->nd_class_dev->kobj, name); - tty_unregister_device(nd->nd_serial_ttdriver, i); - - /* - * NOTE: We don't support "cu" devices anymore, so don't - * unregister them here anymore. - */ - - if (dgrp_register_prdevices) { - dgrp_remove_tty_sysfs(ch->ch_pun.un_sysfs); - snprintf(name, DEVICE_NAME_SIZE, "pr_%d", i); - sysfs_remove_link(&nd->nd_class_dev->kobj, name); - tty_unregister_device(nd->nd_xprint_ttdriver, i); - } - } -} - -/** - * dgrp_chan_count() -- Adjust the node channel count. - * @nd: pointer to a node structure - * @n: new value for channel count - * - * Adjusts the node channel count. If new ports have appeared, it tries - * to signal those processes that might have been waiting for ports to - * appear. If ports have disappeared it tries to signal those processes - * that might be hung waiting for a response for the now non-existant port. - */ -static void dgrp_chan_count(struct nd_struct *nd, int n) -{ - if (n == nd->nd_chan_count) - return; - - if (n > nd->nd_chan_count) - increase_channel_count(nd, n); - - if (n < nd->nd_chan_count) - decrease_channel_count(nd, n); -} - -/** - * dgrp_monitor() -- send data to the device monitor queue - * @nd: pointer to a node structure - * @buf: data to copy to the monitoring buffer - * @len: number of bytes to transfer to the buffer - * - * Called by the net device routines to send data to the device - * monitor queue. If the device monitor buffer is too full to - * accept the data, it waits until the buffer is ready. - */ -static void dgrp_monitor(struct nd_struct *nd, u8 *buf, int len) -{ - int n; - int r; - int rtn; - - /* - * Grab monitor lock. - */ - down(&nd->nd_mon_semaphore); - - /* - * Loop while data remains. - */ - while ((len > 0) && (nd->nd_mon_buf)) { - /* - * Determine the amount of available space left in the - * buffer. If there's none, wait until some appears. - */ - - n = (nd->nd_mon_out - nd->nd_mon_in - 1) & MON_MASK; - - if (!n) { - nd->nd_mon_flag |= MON_WAIT_SPACE; - - up(&nd->nd_mon_semaphore); - - /* - * Go to sleep waiting until the condition becomes true. - */ - rtn = wait_event_interruptible(nd->nd_mon_wqueue, - ((nd->nd_mon_flag & MON_WAIT_SPACE) == 0)); - -/* FIXME: really ignore rtn? */ - - /* - * We can't exit here if we receive a signal, since - * to do so would trash the debug stream. - */ - - down(&nd->nd_mon_semaphore); - - continue; - } - - /* - * Copy as much data as will fit. - */ - - if (n > len) - n = len; - - r = MON_MAX - nd->nd_mon_in; - - if (r <= n) { - memcpy(nd->nd_mon_buf + nd->nd_mon_in, buf, r); - - n -= r; - - nd->nd_mon_in = 0; - - buf += r; - len -= r; - } - - memcpy(nd->nd_mon_buf + nd->nd_mon_in, buf, n); - - nd->nd_mon_in += n; - - buf += n; - len -= n; - - if (nd->nd_mon_in >= MON_MAX) - pr_info_ratelimited("%s - nd_mon_in (%i) >= MON_MAX\n", - __func__, nd->nd_mon_in); - - /* - * Wakeup any thread waiting for data - */ - - if (nd->nd_mon_flag & MON_WAIT_DATA) { - nd->nd_mon_flag &= ~MON_WAIT_DATA; - wake_up_interruptible(&nd->nd_mon_wqueue); - } - } - - /* - * Release the monitor lock. - */ - up(&nd->nd_mon_semaphore); -} - -/** - * dgrp_encode_time() -- Encodes rpdump time into a 4-byte quantity. - * @nd: pointer to a node structure - * @buf: destination buffer - * - * Encodes "rpdump" time into a 4-byte quantity. Time is measured since - * open. - */ -static void dgrp_encode_time(struct nd_struct *nd, u8 *buf) -{ - ulong t; - - /* - * Convert time in HZ since open to time in milliseconds - * since open. - */ - t = jiffies - nd->nd_mon_lbolt; - t = 1000 * (t / HZ) + 1000 * (t % HZ) / HZ; - - put_unaligned_be32((uint)(t & 0xffffffff), buf); -} - - - -/** - * dgrp_monitor_message() -- Builds a rpdump style message. - * @nd: pointer to a node structure - * @message: destination buffer - */ -static void dgrp_monitor_message(struct nd_struct *nd, char *message) -{ - u8 header[7]; - int n; - - header[0] = RPDUMP_MESSAGE; - - dgrp_encode_time(nd, header + 1); - - n = strlen(message); - - put_unaligned_be16(n, header + 5); - - dgrp_monitor(nd, header, sizeof(header)); - dgrp_monitor(nd, (u8 *) message, n); -} - - - -/** - * dgrp_monitor_reset() -- Note a reset in the monitoring buffer. - * @nd: pointer to a node structure - */ -static void dgrp_monitor_reset(struct nd_struct *nd) -{ - u8 header[5]; - - header[0] = RPDUMP_RESET; - - dgrp_encode_time(nd, header + 1); - - dgrp_monitor(nd, header, sizeof(header)); -} - -/** - * dgrp_monitor_data() -- builds a monitor data packet - * @nd: pointer to a node structure - * @type: type of message to be logged - * @buf: data to be logged - * @size: number of bytes in the buffer - */ -static void dgrp_monitor_data(struct nd_struct *nd, u8 type, u8 *buf, int size) -{ - u8 header[7]; - - header[0] = type; - - dgrp_encode_time(nd, header + 1); - - put_unaligned_be16(size, header + 5); - - dgrp_monitor(nd, header, sizeof(header)); - dgrp_monitor(nd, buf, size); -} - -static int alloc_nd_buffers(struct nd_struct *nd) -{ - - nd->nd_iobuf = NULL; - nd->nd_writebuf = NULL; - nd->nd_inputbuf = NULL; - nd->nd_inputflagbuf = NULL; - - /* - * Allocate the network read/write buffer. - */ - nd->nd_iobuf = kzalloc(UIO_MAX + 10, GFP_KERNEL); - if (!nd->nd_iobuf) - goto out_err; - - /* - * Allocate a buffer for doing the copy from user space to - * kernel space in the write routines. - */ - nd->nd_writebuf = kzalloc(WRITEBUFLEN, GFP_KERNEL); - if (!nd->nd_writebuf) - goto out_err; - - /* - * Allocate a buffer for doing the copy from kernel space to - * tty buffer space in the read routines. - */ - nd->nd_inputbuf = kzalloc(MYFLIPLEN, GFP_KERNEL); - if (!nd->nd_inputbuf) - goto out_err; - - /* - * Allocate a buffer for doing the copy from kernel space to - * tty buffer space in the read routines. - */ - nd->nd_inputflagbuf = kzalloc(MYFLIPLEN, GFP_KERNEL); - if (!nd->nd_inputflagbuf) - goto out_err; - - return 0; - -out_err: - kfree(nd->nd_iobuf); - kfree(nd->nd_writebuf); - kfree(nd->nd_inputbuf); - kfree(nd->nd_inputflagbuf); - return -ENOMEM; -} - -/* - * dgrp_net_open() -- Open the NET device for a particular PortServer - */ -static int dgrp_net_open(struct inode *inode, struct file *file) -{ - struct nd_struct *nd; - struct proc_dir_entry *de; - ulong lock_flags; - int rtn; - - rtn = try_module_get(THIS_MODULE); - if (!rtn) - return -EAGAIN; - - if (!capable(CAP_SYS_ADMIN)) { - rtn = -EPERM; - goto done; - } - - /* - * Make sure that the "private_data" field hasn't already been used. - */ - if (file->private_data) { - rtn = -EINVAL; - goto done; - } - - /* - * Get the node pointer, and fail if it doesn't exist. - */ - de = PDE(inode); - if (!de) { - rtn = -ENXIO; - goto done; - } - - nd = (struct nd_struct *) de->data; - if (!nd) { - rtn = -ENXIO; - goto done; - } - - file->private_data = (void *) nd; - - /* - * Grab the NET lock. - */ - down(&nd->nd_net_semaphore); - - if (nd->nd_state != NS_CLOSED) { - rtn = -EBUSY; - goto unlock; - } - - /* - * Initialize the link speed parameters. - */ - - nd->nd_link.lk_fast_rate = UIO_MAX; - nd->nd_link.lk_slow_rate = UIO_MAX; - - nd->nd_link.lk_fast_delay = 1000; - nd->nd_link.lk_slow_delay = 1000; - - nd->nd_link.lk_header_size = 46; - - - rtn = alloc_nd_buffers(nd); - if (rtn) - goto unlock; - - /* - * The port is now open, so move it to the IDLE state - */ - dgrp_net_idle(nd); - - nd->nd_tx_time = jiffies; - - /* - * If the polling routing is not running, start it running here - */ - spin_lock_irqsave(&dgrp_poll_data.poll_lock, lock_flags); - - if (!dgrp_poll_data.node_active_count) { - dgrp_poll_data.node_active_count = 2; - dgrp_poll_data.timer.expires = jiffies + - dgrp_poll_tick * HZ / 1000; - add_timer(&dgrp_poll_data.timer); - } - - spin_unlock_irqrestore(&dgrp_poll_data.poll_lock, lock_flags); - - dgrp_monitor_message(nd, "Net Open"); - -unlock: - /* - * Release the NET lock. - */ - up(&nd->nd_net_semaphore); - -done: - if (rtn) - module_put(THIS_MODULE); - - return rtn; -} - -/* dgrp_net_release() -- close the NET device for a particular PortServer */ -static int dgrp_net_release(struct inode *inode, struct file *file) -{ - struct nd_struct *nd; - ulong lock_flags; - - nd = (struct nd_struct *)(file->private_data); - if (!nd) - goto done; - -/* TODO : historical locking placeholder */ -/* - * In the HPUX version of the RealPort driver (which served as a basis - * for this driver) this locking code was used. Saved if ever we need - * to review the locking under Linux. - */ -/* spinlock(&nd->nd_lock); */ - - - /* - * Grab the NET lock. - */ - down(&nd->nd_net_semaphore); - - /* - * Before "closing" the internal connection, make sure all - * ports are "idle". - */ - dgrp_net_idle(nd); - - nd->nd_state = NS_CLOSED; - nd->nd_flag = 0; - - /* - * TODO ... must the wait queue be reset on close? - * should any pending waiters be reset? - * Let's decide to assert that the waitq is empty... and see - * how soon we break. - */ - if (waitqueue_active(&nd->nd_tx_waitq)) - pr_info("%s - expected waitqueue_active to be false\n", - __func__); - - nd->nd_send = 0; - - kfree(nd->nd_iobuf); - nd->nd_iobuf = NULL; - -/* TODO : historical locking placeholder */ -/* - * In the HPUX version of the RealPort driver (which served as a basis - * for this driver) this locking code was used. Saved if ever we need - * to review the locking under Linux. - */ -/* spinunlock( &nd->nd_lock ); */ - - - kfree(nd->nd_writebuf); - nd->nd_writebuf = NULL; - - kfree(nd->nd_inputbuf); - nd->nd_inputbuf = NULL; - - kfree(nd->nd_inputflagbuf); - nd->nd_inputflagbuf = NULL; - -/* TODO : historical locking placeholder */ -/* - * In the HPUX version of the RealPort driver (which served as a basis - * for this driver) this locking code was used. Saved if ever we need - * to review the locking under Linux. - */ -/* spinlock(&nd->nd_lock); */ - - /* - * Set the active port count to zero. - */ - dgrp_chan_count(nd, 0); - -/* TODO : historical locking placeholder */ -/* - * In the HPUX version of the RealPort driver (which served as a basis - * for this driver) this locking code was used. Saved if ever we need - * to review the locking under Linux. - */ -/* spinunlock(&nd->nd_lock); */ - - /* - * Release the NET lock. - */ - up(&nd->nd_net_semaphore); - - /* - * Cause the poller to stop scheduling itself if this is - * the last active node. - */ - spin_lock_irqsave(&dgrp_poll_data.poll_lock, lock_flags); - - if (dgrp_poll_data.node_active_count == 2) { - del_timer(&dgrp_poll_data.timer); - dgrp_poll_data.node_active_count = 0; - } - - spin_unlock_irqrestore(&dgrp_poll_data.poll_lock, lock_flags); - -done: - down(&nd->nd_net_semaphore); - - dgrp_monitor_message(nd, "Net Close"); - - up(&nd->nd_net_semaphore); - - module_put(THIS_MODULE); - file->private_data = NULL; - return 0; -} - -/* used in dgrp_send to setup command header */ -static inline u8 *set_cmd_header(u8 *b, u8 port, u8 cmd) -{ - *b++ = 0xb0 + (port & 0x0f); - *b++ = cmd; - return b; -} - -/** - * dgrp_send() -- build a packet for transmission to the server - * @nd: pointer to a node structure - * @tmax: maximum bytes to transmit - * - * returns number of bytes sent - */ -static int dgrp_send(struct nd_struct *nd, long tmax) -{ - struct ch_struct *ch = nd->nd_chan; - u8 *b; - u8 *buf; - u8 *mbuf; - u8 port; - int mod; - long send; - int maxport; - long lastport = -1; - ushort rwin; - long in; - ushort n; - long t; - long ttotal; - long tchan; - long tsend; - ushort tsafe; - long work; - long send_sync; - long wanted_sync_port = -1; - ushort tdata[CHAN_MAX]; - long used_buffer; - - mbuf = nd->nd_iobuf + UIO_BASE; - buf = b = mbuf; - - send_sync = nd->nd_link.lk_slow_rate < UIO_MAX; - - ttotal = 0; - tchan = 0; - - memset(tdata, 0, sizeof(tdata)); - - - /* - * If there are any outstanding requests to be serviced, - * service them here. - */ - if (nd->nd_send & NR_PASSWORD) { - - /* - * Send Password response. - */ - - b[0] = 0xfc; - b[1] = 0x20; - put_unaligned_be16(strlen(nd->password), b + 2); - b += 4; - b += strlen(nd->password); - nd->nd_send &= ~(NR_PASSWORD); - } - - - /* - * Loop over all modules to generate commands, and determine - * the amount of data queued for transmit. - */ - - for (mod = 0, port = 0; port < nd->nd_chan_count; mod++) { - /* - * If this is not the current module, enter a module select - * code in the buffer. - */ - - if (mod != nd->nd_tx_module) - mbuf = ++b; - - /* - * Loop to process one module. - */ - - maxport = port + 16; - - if (maxport > nd->nd_chan_count) - maxport = nd->nd_chan_count; - - for (; port < maxport; port++, ch++) { - /* - * Switch based on channel state. - */ - - switch (ch->ch_state) { - /* - * Send requests when the port is closed, and there - * are no Open, Close or Cancel requests expected. - */ - - case CS_IDLE: - /* - * Wait until any open error code - * has been delivered to all - * associated ports. - */ - - if (ch->ch_open_error) { - if (ch->ch_wait_count[ch->ch_otype]) { - work = 1; - break; - } - - ch->ch_open_error = 0; - } - - /* - * Wait until the channel HANGUP flag is reset - * before sending the first open. We can only - * get to this state after a server disconnect. - */ - - if ((ch->ch_flag & CH_HANGUP) != 0) - break; - - /* - * If recovering from a TCP disconnect, or if - * there is an immediate open pending, send an - * Immediate Open request. - */ - if ((ch->ch_flag & CH_PORT_GONE) || - ch->ch_wait_count[OTYPE_IMMEDIATE] != 0) { - b = set_cmd_header(b, port, 10); - *b++ = 0; - - ch->ch_state = CS_WAIT_OPEN; - ch->ch_otype = OTYPE_IMMEDIATE; - break; - } - - /* - * If there is no Persistent or Incoming Open on the wait - * list in the server, and a thread is waiting for a - * Persistent or Incoming Open, send a Persistent or Incoming - * Open Request. - */ - if (ch->ch_otype_waiting == 0) { - if (ch->ch_wait_count[OTYPE_PERSISTENT] != 0) { - b = set_cmd_header(b, port, 10); - *b++ = 1; - - ch->ch_state = CS_WAIT_OPEN; - ch->ch_otype = OTYPE_PERSISTENT; - } else if (ch->ch_wait_count[OTYPE_INCOMING] != 0) { - b = set_cmd_header(b, port, 10); - *b++ = 2; - - ch->ch_state = CS_WAIT_OPEN; - ch->ch_otype = OTYPE_INCOMING; - } - break; - } - - /* - * If a Persistent or Incoming Open is pending in - * the server, but there is no longer an open - * thread waiting for it, cancel the request. - */ - - if (ch->ch_wait_count[ch->ch_otype_waiting] == 0) { - b = set_cmd_header(b, port, 10); - *b++ = 4; - - ch->ch_state = CS_WAIT_CANCEL; - ch->ch_otype = ch->ch_otype_waiting; - } - break; - - /* - * Send port parameter queries. - */ - case CS_SEND_QUERY: - /* - * Clear out all FEP state that might remain - * from the last connection. - */ - - ch->ch_flag |= CH_PARAM; - - ch->ch_flag &= ~CH_RX_FLUSH; - - ch->ch_expect = 0; - - ch->ch_s_tin = 0; - ch->ch_s_tpos = 0; - ch->ch_s_tsize = 0; - ch->ch_s_treq = 0; - ch->ch_s_elast = 0; - - ch->ch_s_rin = 0; - ch->ch_s_rwin = 0; - ch->ch_s_rsize = 0; - - ch->ch_s_tmax = 0; - ch->ch_s_ttime = 0; - ch->ch_s_rmax = 0; - ch->ch_s_rtime = 0; - ch->ch_s_rlow = 0; - ch->ch_s_rhigh = 0; - - ch->ch_s_brate = 0; - ch->ch_s_iflag = 0; - ch->ch_s_cflag = 0; - ch->ch_s_oflag = 0; - ch->ch_s_xflag = 0; - - ch->ch_s_mout = 0; - ch->ch_s_mflow = 0; - ch->ch_s_mctrl = 0; - ch->ch_s_xon = 0; - ch->ch_s_xoff = 0; - ch->ch_s_lnext = 0; - ch->ch_s_xxon = 0; - ch->ch_s_xxoff = 0; - - /* Send Sequence Request */ - b = set_cmd_header(b, port, 14); - - /* Configure Event Conditions Packet */ - b = set_cmd_header(b, port, 42); - put_unaligned_be16(0x02c0, b); - b += 2; - *b++ = (DM_DTR | DM_RTS | DM_CTS | - DM_DSR | DM_RI | DM_CD); - - /* Send Status Request */ - b = set_cmd_header(b, port, 16); - - /* Send Buffer Request */ - b = set_cmd_header(b, port, 20); - - /* Send Port Capability Request */ - b = set_cmd_header(b, port, 22); - - ch->ch_expect = (RR_SEQUENCE | - RR_STATUS | - RR_BUFFER | - RR_CAPABILITY); - - ch->ch_state = CS_WAIT_QUERY; - - /* Raise modem signals */ - b = set_cmd_header(b, port, 44); - - if (ch->ch_flag & CH_PORT_GONE) - ch->ch_s_mout = ch->ch_mout; - else - ch->ch_s_mout = ch->ch_mout = DM_DTR | DM_RTS; - - *b++ = ch->ch_mout; - *b++ = ch->ch_s_mflow = 0; - *b++ = ch->ch_s_mctrl = ch->ch_mctrl = 0; - - if (ch->ch_flag & CH_PORT_GONE) - ch->ch_flag &= ~CH_PORT_GONE; - - break; - - /* - * Handle normal open and ready mode. - */ - - case CS_READY: - - /* - * If the port is not open, and there are no - * no longer any ports requesting an open, - * then close the port. - */ - - if (ch->ch_open_count == 0 && - ch->ch_wait_count[ch->ch_otype] == 0) { - goto send_close; - } - - /* - * Process waiting input. - * - * If there is no one to read it, discard the data. - * - * Otherwise if we are not in fastcook mode, or if there is a - * fastcook thread waiting for data, send the data to the - * line discipline. - */ - if (ch->ch_rin != ch->ch_rout) { - if (ch->ch_tun.un_open_count == 0 || - (ch->ch_tun.un_flag & UN_CLOSING) || - (ch->ch_cflag & CF_CREAD) == 0) { - ch->ch_rout = ch->ch_rin; - } else if ((ch->ch_flag & CH_FAST_READ) == 0 || - ch->ch_inwait != 0) { - dgrp_input(ch); - - if (ch->ch_rin != ch->ch_rout) - work = 1; - } - } - - /* - * Handle receive flush, and changes to - * server port parameters. - */ - - if (ch->ch_flag & (CH_RX_FLUSH | CH_PARAM)) { - /* - * If we are in receive flush mode, - * and enough data has gone by, reset - * receive flush mode. - */ - if (ch->ch_flag & CH_RX_FLUSH) { - if (((ch->ch_flush_seq - nd->nd_seq_out) & SEQ_MASK) > - ((nd->nd_seq_in - nd->nd_seq_out) & SEQ_MASK)) - ch->ch_flag &= ~CH_RX_FLUSH; - else - work = 1; - } - - /* - * Send TMAX, TTIME. - */ - - if (ch->ch_s_tmax != ch->ch_tmax || - ch->ch_s_ttime != ch->ch_ttime) { - b = set_cmd_header(b, port, 48); - - ch->ch_s_tmax = ch->ch_tmax; - ch->ch_s_ttime = ch->ch_ttime; - - put_unaligned_be16(ch->ch_s_tmax, - b); - b += 2; - - put_unaligned_be16(ch->ch_s_ttime, - b); - b += 2; - } - - /* - * Send RLOW, RHIGH. - */ - - if (ch->ch_s_rlow != ch->ch_rlow || - ch->ch_s_rhigh != ch->ch_rhigh) { - b = set_cmd_header(b, port, 45); - - ch->ch_s_rlow = ch->ch_rlow; - ch->ch_s_rhigh = ch->ch_rhigh; - - put_unaligned_be16(ch->ch_s_rlow, - b); - b += 2; - - put_unaligned_be16(ch->ch_s_rhigh, - b); - b += 2; - } - - /* - * Send BRATE, CFLAG, IFLAG, - * OFLAG, XFLAG. - */ - - if (ch->ch_s_brate != ch->ch_brate || - ch->ch_s_cflag != ch->ch_cflag || - ch->ch_s_iflag != ch->ch_iflag || - ch->ch_s_oflag != ch->ch_oflag || - ch->ch_s_xflag != ch->ch_xflag) { - b = set_cmd_header(b, port, 40); - - ch->ch_s_brate = ch->ch_brate; - ch->ch_s_cflag = ch->ch_cflag; - ch->ch_s_iflag = ch->ch_iflag; - ch->ch_s_oflag = ch->ch_oflag; - ch->ch_s_xflag = ch->ch_xflag; - - put_unaligned_be16(ch->ch_s_brate, - b); - b += 2; - - put_unaligned_be16(ch->ch_s_cflag, - b); - b += 2; - - put_unaligned_be16(ch->ch_s_iflag, - b); - b += 2; - - put_unaligned_be16(ch->ch_s_oflag, - b); - b += 2; - - put_unaligned_be16(ch->ch_s_xflag, - b); - b += 2; - } - - /* - * Send MOUT, MFLOW, MCTRL. - */ - - if (ch->ch_s_mout != ch->ch_mout || - ch->ch_s_mflow != ch->ch_mflow || - ch->ch_s_mctrl != ch->ch_mctrl) { - b = set_cmd_header(b, port, 44); - - *b++ = ch->ch_s_mout = ch->ch_mout; - *b++ = ch->ch_s_mflow = ch->ch_mflow; - *b++ = ch->ch_s_mctrl = ch->ch_mctrl; - } - - /* - * Send Flow control characters. - */ - - if (ch->ch_s_xon != ch->ch_xon || - ch->ch_s_xoff != ch->ch_xoff || - ch->ch_s_lnext != ch->ch_lnext || - ch->ch_s_xxon != ch->ch_xxon || - ch->ch_s_xxoff != ch->ch_xxoff) { - b = set_cmd_header(b, port, 46); - - *b++ = ch->ch_s_xon = ch->ch_xon; - *b++ = ch->ch_s_xoff = ch->ch_xoff; - *b++ = ch->ch_s_lnext = ch->ch_lnext; - *b++ = ch->ch_s_xxon = ch->ch_xxon; - *b++ = ch->ch_s_xxoff = ch->ch_xxoff; - } - - /* - * Send RMAX, RTIME. - */ - - if (ch->ch_s_rmax != ch->ch_rmax || - ch->ch_s_rtime != ch->ch_rtime) { - b = set_cmd_header(b, port, 47); - - ch->ch_s_rmax = ch->ch_rmax; - ch->ch_s_rtime = ch->ch_rtime; - - put_unaligned_be16(ch->ch_s_rmax, - b); - b += 2; - - put_unaligned_be16(ch->ch_s_rtime, - b); - b += 2; - } - - ch->ch_flag &= ~CH_PARAM; - wake_up_interruptible(&ch->ch_flag_wait); - } - - - /* - * Handle action commands. - */ - - if (ch->ch_send != 0) { - /* int send = ch->ch_send & ~ch->ch_expect; */ - send = ch->ch_send & ~ch->ch_expect; - - /* Send character immediate */ - if ((send & RR_TX_ICHAR) != 0) { - b = set_cmd_header(b, port, 60); - - *b++ = ch->ch_xon; - ch->ch_expect |= RR_TX_ICHAR; - } - - /* BREAK request */ - if ((send & RR_TX_BREAK) != 0) { - if (ch->ch_break_time != 0) { - b = set_cmd_header(b, port, 61); - put_unaligned_be16(ch->ch_break_time, - b); - b += 2; - - ch->ch_expect |= RR_TX_BREAK; - ch->ch_break_time = 0; - } else { - ch->ch_send &= ~RR_TX_BREAK; - ch->ch_flag &= ~CH_TX_BREAK; - wake_up_interruptible(&ch->ch_flag_wait); - } - } - - /* - * Flush input/output buffers. - */ - - if ((send & (RR_RX_FLUSH | RR_TX_FLUSH)) != 0) { - b = set_cmd_header(b, port, 62); - - *b++ = ((send & RR_TX_FLUSH) == 0 ? 1 : - (send & RR_RX_FLUSH) == 0 ? 2 : 3); - - if (send & RR_RX_FLUSH) { - ch->ch_flush_seq = nd->nd_seq_in; - ch->ch_flag |= CH_RX_FLUSH; - work = 1; - send_sync = 1; - wanted_sync_port = port; - } - - ch->ch_send &= ~(RR_RX_FLUSH | RR_TX_FLUSH); - } - - /* Pause input/output */ - if ((send & (RR_RX_STOP | RR_TX_STOP)) != 0) { - b = set_cmd_header(b, port, 63); - *b = 0; - - if ((send & RR_TX_STOP) != 0) - *b |= EV_OPU; - - if ((send & RR_RX_STOP) != 0) - *b |= EV_IPU; - - b++; - - ch->ch_send &= ~(RR_RX_STOP | RR_TX_STOP); - } - - /* Start input/output */ - if ((send & (RR_RX_START | RR_TX_START)) != 0) { - b = set_cmd_header(b, port, 64); - *b = 0; - - if ((send & RR_TX_START) != 0) - *b |= EV_OPU | EV_OPS | EV_OPX; - - if ((send & RR_RX_START) != 0) - *b |= EV_IPU | EV_IPS; - - b++; - - ch->ch_send &= ~(RR_RX_START | RR_TX_START); - } - } - - - /* - * Send a window sequence to acknowledge received data. - */ - - rwin = (ch->ch_s_rin + - ((ch->ch_rout - ch->ch_rin - 1) & RBUF_MASK)); - - n = (rwin - ch->ch_s_rwin) & 0xffff; - - if (n >= RBUF_MAX / 4) { - b[0] = 0xa0 + (port & 0xf); - ch->ch_s_rwin = rwin; - put_unaligned_be16(rwin, b + 1); - b += 3; - } - - /* - * If the terminal is waiting on LOW - * water or EMPTY, and the condition - * is now satisfied, call the line - * discipline to put more data in the - * buffer. - */ - - n = (ch->ch_tin - ch->ch_tout) & TBUF_MASK; - - if ((ch->ch_tun.un_flag & (UN_EMPTY|UN_LOW)) != 0) { - if ((ch->ch_tun.un_flag & UN_LOW) != 0 ? - (n <= TBUF_LOW) : - (n == 0 && ch->ch_s_tpos == ch->ch_s_tin)) { - ch->ch_tun.un_flag &= ~(UN_EMPTY|UN_LOW); - - if (waitqueue_active(&((ch->ch_tun.un_tty)->write_wait))) - wake_up_interruptible(&((ch->ch_tun.un_tty)->write_wait)); - tty_wakeup(ch->ch_tun.un_tty); - n = (ch->ch_tin - ch->ch_tout) & TBUF_MASK; - } - } - - /* - * If the printer is waiting on LOW - * water, TIME, EMPTY or PWAIT, and is - * now ready to put more data in the - * buffer, call the line discipline to - * do the job. - */ - - if (ch->ch_pun.un_open_count && - (ch->ch_pun.un_flag & - (UN_EMPTY|UN_TIME|UN_LOW|UN_PWAIT)) != 0) { - - if ((ch->ch_pun.un_flag & UN_LOW) != 0 ? - (n <= TBUF_LOW) : - (ch->ch_pun.un_flag & UN_TIME) != 0 ? - ((jiffies - ch->ch_waketime) >= 0) : - (n == 0 && ch->ch_s_tpos == ch->ch_s_tin) && - ((ch->ch_pun.un_flag & UN_EMPTY) != 0 || - ((ch->ch_tun.un_open_count && - ch->ch_tun.un_tty->ops->chars_in_buffer) ? - (ch->ch_tun.un_tty->ops->chars_in_buffer)(ch->ch_tun.un_tty) == 0 - : 1 - ) - )) { - ch->ch_pun.un_flag &= ~(UN_EMPTY | UN_TIME | UN_LOW | UN_PWAIT); - - if (waitqueue_active(&((ch->ch_pun.un_tty)->write_wait))) - wake_up_interruptible(&((ch->ch_pun.un_tty)->write_wait)); - tty_wakeup(ch->ch_pun.un_tty); - n = (ch->ch_tin - ch->ch_tout) & TBUF_MASK; - - } else if ((ch->ch_pun.un_flag & UN_TIME) != 0) { - work = 1; - } - } - - - /* - * Determine the max number of bytes - * this port can send, including - * packet header overhead. - */ - - t = ((ch->ch_s_tsize + ch->ch_s_tpos - ch->ch_s_tin) & 0xffff); - - if (n > t) - n = t; - - if (n != 0) { - n += (n <= 8 ? 1 : n <= 255 ? 2 : 3); - - tdata[tchan++] = n; - ttotal += n; - } - break; - - /* - * Close the port. - */ - -send_close: - case CS_SEND_CLOSE: - b = set_cmd_header(b, port, 10); - if (ch->ch_otype == OTYPE_IMMEDIATE) - *b++ = 3; - else - *b++ = 4; - - ch->ch_state = CS_WAIT_CLOSE; - break; - - /* - * Wait for a previous server request. - */ - - case CS_WAIT_OPEN: - case CS_WAIT_CANCEL: - case CS_WAIT_FAIL: - case CS_WAIT_QUERY: - case CS_WAIT_CLOSE: - break; - - default: - pr_info("%s - unexpected channel state (%i)\n", - __func__, ch->ch_state); - } - } - - /* - * If a module select code is needed, drop one in. If space - * was reserved for one, but none is needed, recover the space. - */ - - if (mod != nd->nd_tx_module) { - if (b != mbuf) { - mbuf[-1] = 0xf0 | mod; - nd->nd_tx_module = mod; - } else { - b--; - } - } - } - - /* - * Adjust "tmax" so that under worst case conditions we do - * not overflow either the daemon buffer or the internal - * buffer in the loop that follows. Leave a safe area - * of 64 bytes so we start getting asserts before we start - * losing data or clobbering memory. - */ - - n = UIO_MAX - UIO_BASE; - - if (tmax > n) - tmax = n; - - tmax -= 64; - - tsafe = tmax; - - /* - * Allocate space for 5 Module Selects, 1 Sequence Request, - * and 1 Set TREQ for each active channel. - */ - - tmax -= 5 + 3 + 4 * nd->nd_chan_count; - - /* - * Further reduce "tmax" to the available transmit credit. - * Note that this is a soft constraint; The transmit credit - * can go negative for a time and then recover. - */ - - n = nd->nd_tx_deposit - nd->nd_tx_charge - nd->nd_link.lk_header_size; - - if (tmax > n) - tmax = n; - - /* - * Finally reduce tmax by the number of bytes already in - * the buffer. - */ - - tmax -= b - buf; - - /* - * Suspend data transmit unless every ready channel can send - * at least 1 character. - */ - if (tmax < 2 * nd->nd_chan_count) { - tsend = 1; - - } else if (tchan > 1 && ttotal > tmax) { - - /* - * If transmit is limited by the credit budget, find the - * largest number of characters we can send without driving - * the credit negative. - */ - - long tm = tmax; - int tc = tchan; - int try; - - tsend = tm / tc; - - for (try = 0; try < 3; try++) { - int i; - int c = 0; - - for (i = 0; i < tc; i++) { - if (tsend < tdata[i]) - tdata[c++] = tdata[i]; - else - tm -= tdata[i]; - } - - if (c == tc) - break; - - tsend = tm / c; - - if (c == 1) - break; - - tc = c; - } - - tsend = tm / nd->nd_chan_count; - - if (tsend < 2) - tsend = 1; - - } else { - /* - * If no budgetary constraints, or only one channel ready - * to send, set the character limit to the remaining - * buffer size. - */ - - tsend = tmax; - } - - tsend -= (tsend <= 9) ? 1 : (tsend <= 257) ? 2 : 3; - - /* - * Loop over all channels, sending queued data. - */ - - port = 0; - ch = nd->nd_chan; - used_buffer = tmax; - - for (mod = 0; port < nd->nd_chan_count; mod++) { - /* - * If this is not the current module, enter a module select - * code in the buffer. - */ - - if (mod != nd->nd_tx_module) - mbuf = ++b; - - /* - * Loop to process one module. - */ - - maxport = port + 16; - - if (maxport > nd->nd_chan_count) - maxport = nd->nd_chan_count; - - for (; port < maxport; port++, ch++) { - if (ch->ch_state != CS_READY) - continue; - - lastport = port; - - n = (ch->ch_tin - ch->ch_tout) & TBUF_MASK; - - /* - * If there is data that can be sent, send it. - */ - - if (n != 0 && used_buffer > 0) { - t = (ch->ch_s_tsize + ch->ch_s_tpos - ch->ch_s_tin) & 0xffff; - - if (n > t) - n = t; - - if (n > tsend) { - work = 1; - n = tsend; - } - - if (n > used_buffer) { - work = 1; - n = used_buffer; - } - - if (n <= 0) - continue; - - /* - * Create the correct size transmit header, - * depending on the amount of data to transmit. - */ - - if (n <= 8) { - - b[0] = ((n - 1) << 4) + (port & 0xf); - b += 1; - - } else if (n <= 255) { - - b[0] = 0x80 + (port & 0xf); - b[1] = n; - b += 2; - - } else { - - b[0] = 0x90 + (port & 0xf); - put_unaligned_be16(n, b + 1); - b += 3; - } - - ch->ch_s_tin = (ch->ch_s_tin + n) & 0xffff; - - /* - * Copy transmit data to the packet. - */ - - t = TBUF_MAX - ch->ch_tout; - - if (n >= t) { - memcpy(b, ch->ch_tbuf + ch->ch_tout, t); - b += t; - n -= t; - used_buffer -= t; - ch->ch_tout = 0; - } - - memcpy(b, ch->ch_tbuf + ch->ch_tout, n); - b += n; - used_buffer -= n; - ch->ch_tout += n; - n = (ch->ch_tin - ch->ch_tout) & TBUF_MASK; - } - - /* - * Wake any terminal unit process waiting in the - * dgrp_write routine for low water. - */ - - if (n > TBUF_LOW) - continue; - - if ((ch->ch_flag & CH_LOW) != 0) { - ch->ch_flag &= ~CH_LOW; - wake_up_interruptible(&ch->ch_flag_wait); - } - - /* selwakeup tty_sel */ - if (ch->ch_tun.un_open_count) { - struct tty_struct *tty = (ch->ch_tun.un_tty); - - if (waitqueue_active(&tty->write_wait)) - wake_up_interruptible(&tty->write_wait); - - tty_wakeup(tty); - } - - if (ch->ch_pun.un_open_count) { - struct tty_struct *tty = (ch->ch_pun.un_tty); - - if (waitqueue_active(&tty->write_wait)) - wake_up_interruptible(&tty->write_wait); - - tty_wakeup(tty); - } - - /* - * Do EMPTY processing. - */ - - if (n != 0) - continue; - - if ((ch->ch_flag & (CH_EMPTY | CH_DRAIN)) != 0 || - (ch->ch_pun.un_flag & UN_EMPTY) != 0) { - /* - * If there is still data in the server, ask the server - * to notify us when its all gone. - */ - - if (ch->ch_s_treq != ch->ch_s_tin) { - b = set_cmd_header(b, port, 43); - - ch->ch_s_treq = ch->ch_s_tin; - put_unaligned_be16(ch->ch_s_treq, - b); - b += 2; - } - - /* - * If there is a thread waiting for buffer empty, - * and we are truly empty, wake the thread. - */ - - else if ((ch->ch_flag & CH_EMPTY) != 0 && - (ch->ch_send & RR_TX_BREAK) == 0) { - ch->ch_flag &= ~CH_EMPTY; - - wake_up_interruptible(&ch->ch_flag_wait); - } - } - } - - /* - * If a module select code is needed, drop one in. If space - * was reserved for one, but none is needed, recover the space. - */ - - if (mod != nd->nd_tx_module) { - if (b != mbuf) { - mbuf[-1] = 0xf0 | mod; - nd->nd_tx_module = mod; - } else { - b--; - } - } - } - - /* - * Send a synchronization sequence associated with the last open - * channel that sent data, and remember the time when the data was - * sent. - */ - - in = nd->nd_seq_in; - - if ((send_sync || nd->nd_seq_wait[in] != 0) && lastport >= 0) { - u8 *bb = b; - - /* - * Attempt the use the port that really wanted the sync. - * This gets around a race condition where the "lastport" is in - * the middle of the close() routine, and by the time we - * send this command, it will have already acked the close, and - * thus not send the sync response. - */ - if (wanted_sync_port >= 0) - lastport = wanted_sync_port; - /* - * Set a flag just in case the port is in the middle of a close, - * it will not be permitted to actually close until we get an - * sync response, and clear the flag there. - */ - ch = nd->nd_chan + lastport; - ch->ch_flag |= CH_WAITING_SYNC; - - mod = lastport >> 4; - - if (mod != nd->nd_tx_module) { - bb[0] = 0xf0 + mod; - bb += 1; - - nd->nd_tx_module = mod; - } - - bb = set_cmd_header(bb, lastport, 12); - *bb++ = in; - - nd->nd_seq_size[in] = bb - buf; - nd->nd_seq_time[in] = jiffies; - - if (++in >= SEQ_MAX) - in = 0; - - if (in != nd->nd_seq_out) { - b = bb; - nd->nd_seq_in = in; - nd->nd_unack += b - buf; - } - } - - /* - * If there are no open ports, a sync cannot be sent. - * There is nothing left to wait for anyway, so wake any - * thread waiting for an acknowledgement. - */ - - else if (nd->nd_seq_wait[in] != 0) { - nd->nd_seq_wait[in] = 0; - - wake_up_interruptible(&nd->nd_seq_wque[in]); - } - - /* - * If there is no traffic for an interval of IDLE_MAX, then - * send a single byte packet. - */ - - if (b != buf) { - nd->nd_tx_time = jiffies; - } else if ((ulong)(jiffies - nd->nd_tx_time) >= IDLE_MAX) { - *b++ = 0xf0 | nd->nd_tx_module; - nd->nd_tx_time = jiffies; - } - - n = b - buf; - - if (n >= tsafe) - pr_info("%s - n(%i) >= tsafe(%i)\n", - __func__, n, tsafe); - - if (tsend < 0) - dgrp_dump(buf, n); - - nd->nd_tx_work = work; - - return n; -} - -/* - * dgrp_net_read() - * Data to be sent TO the PortServer from the "async." half of the driver. - */ -static ssize_t dgrp_net_read(struct file *file, char __user *buf, size_t count, - loff_t *ppos) -{ - struct nd_struct *nd; - long n; - u8 *local_buf; - u8 *b; - ssize_t rtn; - - /* - * Get the node pointer, and quit if it doesn't exist. - */ - nd = (struct nd_struct *)(file->private_data); - if (!nd) - return -ENXIO; - - if (count < UIO_MIN) - return -EINVAL; - - /* - * Only one read/write operation may be in progress at - * any given time. - */ - - /* - * Grab the NET lock. - */ - down(&nd->nd_net_semaphore); - - nd->nd_read_count++; - - nd->nd_tx_ready = 0; - - /* - * Determine the effective size of the buffer. - */ - - if (nd->nd_remain > UIO_BASE) - pr_info_ratelimited("%s - nd_remain(%i) > UIO_BASE\n", - __func__, nd->nd_remain); - - b = local_buf = nd->nd_iobuf + UIO_BASE; - - /* - * Generate data according to the node state. - */ - - switch (nd->nd_state) { - /* - * Initialize the connection. - */ - - case NS_IDLE: - if (nd->nd_mon_buf) - dgrp_monitor_reset(nd); - - /* - * Request a Product ID Packet. - */ - - b[0] = 0xfb; - b[1] = 0x01; - b += 2; - - nd->nd_expect |= NR_IDENT; - - /* - * Request a Server Capability ID Response. - */ - - b[0] = 0xfb; - b[1] = 0x02; - b += 2; - - nd->nd_expect |= NR_CAPABILITY; - - /* - * Request a Server VPD Response. - */ - - b[0] = 0xfb; - b[1] = 0x18; - b += 2; - - nd->nd_expect |= NR_VPD; - - nd->nd_state = NS_WAIT_QUERY; - break; - - /* - * We do serious communication with the server only in - * the READY state. - */ - - case NS_READY: - b = dgrp_send(nd, count) + local_buf; - break; - - /* - * Send off an error after receiving a bogus message - * from the server. - */ - - case NS_SEND_ERROR: - n = strlen(nd->nd_error); - - b[0] = 0xff; - b[1] = n; - memcpy(b + 2, nd->nd_error, n); - b += 2 + n; - - dgrp_net_idle(nd); - /* - * Set the active port count to zero. - */ - dgrp_chan_count(nd, 0); - break; - - default: - break; - } - - n = b - local_buf; - - if (n != 0) { - nd->nd_send_count++; - - nd->nd_tx_byte += n + nd->nd_link.lk_header_size; - nd->nd_tx_charge += n + nd->nd_link.lk_header_size; - } - - rtn = copy_to_user((void __user *)buf, local_buf, n); - if (rtn) { - rtn = -EFAULT; - goto done; - } - - *ppos += n; - - rtn = n; - - if (nd->nd_mon_buf) - dgrp_monitor_data(nd, RPDUMP_CLIENT, local_buf, n); - - /* - * Release the NET lock. - */ -done: - up(&nd->nd_net_semaphore); - - return rtn; -} - -/** - * dgrp_receive() -- decode data packets received from the remote PortServer. - * @nd: pointer to a node structure - */ -static void dgrp_receive(struct nd_struct *nd) -{ - struct ch_struct *ch; - u8 *buf; - u8 *b; - u8 *dbuf; - char *error; - long port; - long dlen; - long plen; - long remain; - long n; - long mlast; - long elast; - long mstat; - long estat; - - char ID[3]; - - nd->nd_tx_time = jiffies; - - ID_TO_CHAR(nd->nd_ID, ID); - - b = buf = nd->nd_iobuf; - remain = nd->nd_remain; - - /* - * Loop to process Realport protocol packets. - */ - - while (remain > 0) { - int n0 = b[0] >> 4; - int n1 = b[0] & 0x0f; - - if (n0 <= 12) { - port = (nd->nd_rx_module << 4) + n1; - - if (port >= nd->nd_chan_count) { - error = "Improper Port Number"; - goto prot_error; - } - - ch = nd->nd_chan + port; - } else { - port = -1; - ch = NULL; - } - - /* - * Process by major packet type. - */ - - switch (n0) { - - /* - * Process 1-byte header data packet. - */ - - case 0: - case 1: - case 2: - case 3: - case 4: - case 5: - case 6: - case 7: - dlen = n0 + 1; - plen = dlen + 1; - - dbuf = b + 1; - goto data; - - /* - * Process 2-byte header data packet. - */ - - case 8: - if (remain < 3) - goto done; - - dlen = b[1]; - plen = dlen + 2; - - dbuf = b + 2; - goto data; - - /* - * Process 3-byte header data packet. - */ - - case 9: - if (remain < 4) - goto done; - - dlen = get_unaligned_be16(b + 1); - plen = dlen + 3; - - dbuf = b + 3; - - /* - * Common packet handling code. - */ - -data: - nd->nd_tx_work = 1; - - /* - * Otherwise data should appear only when we are - * in the CS_READY state. - */ - - if (ch->ch_state < CS_READY) { - error = "Data received before RWIN established"; - goto prot_error; - } - - /* - * Assure that the data received is within the - * allowable window. - */ - - n = (ch->ch_s_rwin - ch->ch_s_rin) & 0xffff; - - if (dlen > n) { - error = "Receive data overrun"; - goto prot_error; - } - - /* - * If we received 3 or less characters, - * assume it is a human typing, and set RTIME - * to 10 milliseconds. - * - * If we receive 10 or more characters, - * assume its not a human typing, and set RTIME - * to 100 milliseconds. - */ - - if (ch->ch_edelay != DGRP_RTIME) { - if (ch->ch_rtime != ch->ch_edelay) { - ch->ch_rtime = ch->ch_edelay; - ch->ch_flag |= CH_PARAM; - } - } else if (dlen <= 3) { - if (ch->ch_rtime != 10) { - ch->ch_rtime = 10; - ch->ch_flag |= CH_PARAM; - } - } else { - if (ch->ch_rtime != DGRP_RTIME) { - ch->ch_rtime = DGRP_RTIME; - ch->ch_flag |= CH_PARAM; - } - } - - /* - * If a portion of the packet is outside the - * buffer, shorten the effective length of the - * data packet to be the amount of data received. - */ - - if (remain < plen) - dlen -= plen - remain; - - /* - * Detect if receive flush is now complete. - */ - - if ((ch->ch_flag & CH_RX_FLUSH) != 0 && - ((ch->ch_flush_seq - nd->nd_seq_out) & SEQ_MASK) >= - ((nd->nd_seq_in - nd->nd_seq_out) & SEQ_MASK)) { - ch->ch_flag &= ~CH_RX_FLUSH; - } - - /* - * If we are ready to receive, move the data into - * the receive buffer. - */ - - ch->ch_s_rin = (ch->ch_s_rin + dlen) & 0xffff; - - if (ch->ch_state == CS_READY && - (ch->ch_tun.un_open_count != 0) && - (ch->ch_tun.un_flag & UN_CLOSING) == 0 && - (ch->ch_cflag & CF_CREAD) != 0 && - (ch->ch_flag & (CH_BAUD0 | CH_RX_FLUSH)) == 0 && - (ch->ch_send & RR_RX_FLUSH) == 0) { - - if (ch->ch_rin + dlen >= RBUF_MAX) { - n = RBUF_MAX - ch->ch_rin; - - memcpy(ch->ch_rbuf + ch->ch_rin, dbuf, n); - - ch->ch_rin = 0; - dbuf += n; - dlen -= n; - } - - memcpy(ch->ch_rbuf + ch->ch_rin, dbuf, dlen); - - ch->ch_rin += dlen; - - - /* - * If we are not in fastcook mode, or - * if there is a fastcook thread - * waiting for data, send the data to - * the line discipline. - */ - - if ((ch->ch_flag & CH_FAST_READ) == 0 || - ch->ch_inwait != 0) { - dgrp_input(ch); - } - - /* - * If there is a read thread waiting - * in select, and we are in fastcook - * mode, wake him up. - */ - - if (waitqueue_active(&ch->ch_tun.un_tty->read_wait) && - (ch->ch_flag & CH_FAST_READ) != 0) - wake_up_interruptible(&ch->ch_tun.un_tty->read_wait); - - /* - * Wake any thread waiting in the - * fastcook loop. - */ - - if ((ch->ch_flag & CH_INPUT) != 0) { - ch->ch_flag &= ~CH_INPUT; - - wake_up_interruptible(&ch->ch_flag_wait); - } - } - - /* - * Fabricate and insert a data packet header to - * preceed the remaining data when it comes in. - */ - - if (remain < plen) { - dlen = plen - remain; - b = buf; - - b[0] = 0x90 + n1; - put_unaligned_be16(dlen, b + 1); - - remain = 3; - goto done; - } - break; - - /* - * Handle Window Sequence packets. - */ - - case 10: - plen = 3; - if (remain < plen) - goto done; - - nd->nd_tx_work = 1; - - { - ushort tpos = get_unaligned_be16(b + 1); - - ushort ack = (tpos - ch->ch_s_tpos) & 0xffff; - ushort unack = (ch->ch_s_tin - ch->ch_s_tpos) & 0xffff; - ushort notify = (ch->ch_s_treq - ch->ch_s_tpos) & 0xffff; - - if (ch->ch_state < CS_READY || ack > unack) { - error = "Improper Window Sequence"; - goto prot_error; - } - - ch->ch_s_tpos = tpos; - - if (notify <= ack) - ch->ch_s_treq = tpos; - } - break; - - /* - * Handle Command response packets. - */ - - case 11: - - /* - * RealPort engine fix - 03/11/2004 - * - * This check did not used to be here. - * - * We were using b[1] without verifying that the data - * is actually there and valid. On a split packet, it - * might not be yet. - * - * NOTE: I have never actually seen the failure happen - * under Linux, but since I have seen it occur - * under both Solaris and HP-UX, the assumption - * is that it *could* happen here as well... - */ - if (remain < 2) - goto done; - - - switch (b[1]) { - - /* - * Handle Open Response. - */ - - case 11: - plen = 6; - if (remain < plen) - goto done; - - nd->nd_tx_work = 1; - - { - int req = b[2]; - int resp = b[3]; - port = get_unaligned_be16(b + 4); - - if (port >= nd->nd_chan_count) { - error = "Open channel number out of range"; - goto prot_error; - } - - ch = nd->nd_chan + port; - - /* - * How we handle an open response depends primarily - * on our current channel state. - */ - - switch (ch->ch_state) { - case CS_IDLE: - - /* - * Handle a delayed open. - */ - - if (ch->ch_otype_waiting != 0 && - req == ch->ch_otype_waiting && - resp == 0) { - ch->ch_otype = req; - ch->ch_otype_waiting = 0; - ch->ch_state = CS_SEND_QUERY; - break; - } - goto open_error; - - case CS_WAIT_OPEN: - - /* - * Handle the open response. - */ - - if (req == ch->ch_otype) { - switch (resp) { - - /* - * On successful response, open the - * port and proceed normally. - */ - - case 0: - ch->ch_state = CS_SEND_QUERY; - break; - - /* - * On a busy response to a persistent open, - * remember that the open is pending. - */ - - case 1: - case 2: - if (req != OTYPE_IMMEDIATE) { - ch->ch_otype_waiting = req; - ch->ch_state = CS_IDLE; - break; - } - - /* - * Otherwise the server open failed. If - * the Unix port is open, hang it up. - */ - - default: - if (ch->ch_open_count != 0) { - ch->ch_flag |= CH_HANGUP; - dgrp_carrier(ch); - ch->ch_state = CS_IDLE; - break; - } - - ch->ch_open_error = resp; - ch->ch_state = CS_IDLE; - - wake_up_interruptible(&ch->ch_flag_wait); - } - break; - } - - /* - * Handle delayed response arrival preceeding - * the open response we are waiting for. - */ - - if (ch->ch_otype_waiting != 0 && - req == ch->ch_otype_waiting && - resp == 0) { - ch->ch_otype = ch->ch_otype_waiting; - ch->ch_otype_waiting = 0; - ch->ch_state = CS_WAIT_FAIL; - break; - } - goto open_error; - - - case CS_WAIT_FAIL: - - /* - * Handle response to immediate open arriving - * after a delayed open success. - */ - - if (req == OTYPE_IMMEDIATE) { - ch->ch_state = CS_SEND_QUERY; - break; - } - goto open_error; - - - case CS_WAIT_CANCEL: - /* - * Handle delayed open response arriving before - * the cancel response. - */ - - if (req == ch->ch_otype_waiting && - resp == 0) { - ch->ch_otype_waiting = 0; - break; - } - - /* - * Handle cancel response. - */ - - if (req == 4 && resp == 0) { - ch->ch_otype_waiting = 0; - ch->ch_state = CS_IDLE; - break; - } - goto open_error; - - - case CS_WAIT_CLOSE: - /* - * Handle a successful response to a port - * close. - */ - - if (req >= 3) { - ch->ch_state = CS_IDLE; - break; - } - goto open_error; - -open_error: - default: - { - error = "Improper Open Response"; - goto prot_error; - } - } - } - break; - - /* - * Handle Synchronize Response. - */ - - case 13: - plen = 3; - if (remain < plen) - goto done; - { - int seq = b[2]; - int s; - - /* - * If channel was waiting for this sync response, - * unset the flag, and wake up anyone waiting - * on the event. - */ - if (ch->ch_flag & CH_WAITING_SYNC) { - ch->ch_flag &= ~(CH_WAITING_SYNC); - wake_up_interruptible(&ch->ch_flag_wait); - } - - if (((seq - nd->nd_seq_out) & SEQ_MASK) >= - ((nd->nd_seq_in - nd->nd_seq_out) & SEQ_MASK)) { - break; - } - - for (s = nd->nd_seq_out;; s = (s + 1) & SEQ_MASK) { - if (nd->nd_seq_wait[s] != 0) { - nd->nd_seq_wait[s] = 0; - - wake_up_interruptible(&nd->nd_seq_wque[s]); - } - - nd->nd_unack -= nd->nd_seq_size[s]; - - if (s == seq) - break; - } - - nd->nd_seq_out = (seq + 1) & SEQ_MASK; - } - break; - - /* - * Handle Sequence Response. - */ - - case 15: - plen = 6; - if (remain < plen) - goto done; - - { - /* Record that we have received the Sequence - * Response, but we aren't interested in the - * sequence numbers. We were using RIN like it - * was ROUT and that was causing problems, - * fixed 7-13-2001 David Fries. See comment in - * drp.h for ch_s_rin variable. - int rin = get_unaligned_be16(b + 2); - int tpos = get_unaligned_be16(b + 4); - */ - - ch->ch_send &= ~RR_SEQUENCE; - ch->ch_expect &= ~RR_SEQUENCE; - } - goto check_query; - - /* - * Handle Status Response. - */ - - case 17: - plen = 5; - if (remain < plen) - goto done; - - { - ch->ch_s_elast = get_unaligned_be16(b + 2); - ch->ch_s_mlast = b[4]; - - ch->ch_expect &= ~RR_STATUS; - ch->ch_send &= ~RR_STATUS; - - /* - * CH_PHYS_CD is cleared because something _could_ be - * waiting for the initial sense of carrier... and if - * carrier is high immediately, we want to be sure to - * wake them as soon as possible. - */ - ch->ch_flag &= ~CH_PHYS_CD; - - dgrp_carrier(ch); - } - goto check_query; - - /* - * Handle Line Error Response. - */ - - case 19: - plen = 14; - if (remain < plen) - goto done; - - break; - - /* - * Handle Buffer Response. - */ - - case 21: - plen = 6; - if (remain < plen) - goto done; - - { - ch->ch_s_rsize = get_unaligned_be16(b + 2); - ch->ch_s_tsize = get_unaligned_be16(b + 4); - - ch->ch_send &= ~RR_BUFFER; - ch->ch_expect &= ~RR_BUFFER; - } - goto check_query; - - /* - * Handle Port Capability Response. - */ - - case 23: - plen = 32; - if (remain < plen) - goto done; - - { - ch->ch_send &= ~RR_CAPABILITY; - ch->ch_expect &= ~RR_CAPABILITY; - } - - /* - * When all queries are complete, set those parameters - * derived from the query results, then transition - * to the READY state. - */ - -check_query: - if (ch->ch_state == CS_WAIT_QUERY && - (ch->ch_expect & (RR_SEQUENCE | - RR_STATUS | - RR_BUFFER | - RR_CAPABILITY)) == 0) { - ch->ch_tmax = ch->ch_s_tsize / 4; - - if (ch->ch_edelay == DGRP_TTIME) - ch->ch_ttime = DGRP_TTIME; - else - ch->ch_ttime = ch->ch_edelay; - - ch->ch_rmax = ch->ch_s_rsize / 4; - - if (ch->ch_edelay == DGRP_RTIME) - ch->ch_rtime = DGRP_RTIME; - else - ch->ch_rtime = ch->ch_edelay; - - ch->ch_rlow = 2 * ch->ch_s_rsize / 8; - ch->ch_rhigh = 6 * ch->ch_s_rsize / 8; - - ch->ch_state = CS_READY; - - nd->nd_tx_work = 1; - wake_up_interruptible(&ch->ch_flag_wait); - - } - break; - - default: - goto decode_error; - } - break; - - /* - * Handle Events. - */ - - case 12: - plen = 4; - if (remain < plen) - goto done; - - mlast = ch->ch_s_mlast; - elast = ch->ch_s_elast; - - mstat = ch->ch_s_mlast = b[1]; - estat = ch->ch_s_elast = get_unaligned_be16(b + 2); - - /* - * Handle modem changes. - */ - - if (((mstat ^ mlast) & DM_CD) != 0) - dgrp_carrier(ch); - - - /* - * Handle received break. - */ - - if ((estat & ~elast & EV_RXB) != 0 && - (ch->ch_tun.un_open_count != 0) && - I_BRKINT(ch->ch_tun.un_tty) && - !(I_IGNBRK(ch->ch_tun.un_tty))) { - - tty_buffer_request_room(ch->ch_tun.un_tty, 1); - tty_insert_flip_char(ch->ch_tun.un_tty, 0, TTY_BREAK); - tty_flip_buffer_push(ch->ch_tun.un_tty); - - } - - /* - * On transmit break complete, if more break traffic - * is waiting then send it. Otherwise wake any threads - * waiting for transmitter empty. - */ - - if ((~estat & elast & EV_TXB) != 0 && - (ch->ch_expect & RR_TX_BREAK) != 0) { - - nd->nd_tx_work = 1; - - ch->ch_expect &= ~RR_TX_BREAK; - - if (ch->ch_break_time != 0) { - ch->ch_send |= RR_TX_BREAK; - } else { - ch->ch_send &= ~RR_TX_BREAK; - ch->ch_flag &= ~CH_TX_BREAK; - wake_up_interruptible(&ch->ch_flag_wait); - } - } - break; - - case 13: - case 14: - error = "Unrecognized command"; - goto prot_error; - - /* - * Decode Special Codes. - */ - - case 15: - switch (n1) { - /* - * One byte module select. - */ - - case 0: - case 1: - case 2: - case 3: - case 4: - case 5: - case 6: - case 7: - plen = 1; - nd->nd_rx_module = n1; - break; - - /* - * Two byte module select. - */ - - case 8: - plen = 2; - if (remain < plen) - goto done; - - nd->nd_rx_module = b[1]; - break; - - /* - * ID Request packet. - */ - - case 11: - if (remain < 4) - goto done; - - plen = get_unaligned_be16(b + 2); - - if (plen < 12 || plen > 1000) { - error = "Response Packet length error"; - goto prot_error; - } - - nd->nd_tx_work = 1; - - switch (b[1]) { - /* - * Echo packet. - */ - - case 0: - nd->nd_send |= NR_ECHO; - break; - - /* - * ID Response packet. - */ - - case 1: - nd->nd_send |= NR_IDENT; - break; - - /* - * ID Response packet. - */ - - case 32: - nd->nd_send |= NR_PASSWORD; - break; - - } - break; - - /* - * Various node-level response packets. - */ - - case 12: - if (remain < 4) - goto done; - - plen = get_unaligned_be16(b + 2); - - if (plen < 4 || plen > 1000) { - error = "Response Packet length error"; - goto prot_error; - } - - nd->nd_tx_work = 1; - - switch (b[1]) { - /* - * Echo packet. - */ - - case 0: - nd->nd_expect &= ~NR_ECHO; - break; - - /* - * Product Response Packet. - */ - - case 1: - { - int desclen; - - nd->nd_hw_ver = (b[8] << 8) | b[9]; - nd->nd_sw_ver = (b[10] << 8) | b[11]; - nd->nd_hw_id = b[6]; - desclen = ((plen - 12) > MAX_DESC_LEN) ? MAX_DESC_LEN : - plen - 12; - - if (desclen <= 0) { - error = "Response Packet desclen error"; - goto prot_error; - } - - strncpy(nd->nd_ps_desc, b + 12, desclen); - nd->nd_ps_desc[desclen] = 0; - } - - nd->nd_expect &= ~NR_IDENT; - break; - - /* - * Capability Response Packet. - */ - - case 2: - { - int nn = get_unaligned_be16(b + 4); - - if (nn > CHAN_MAX) - nn = CHAN_MAX; - - dgrp_chan_count(nd, nn); - } - - nd->nd_expect &= ~NR_CAPABILITY; - break; - - /* - * VPD Response Packet. - */ - - case 15: - /* - * NOTE: case 15 is here ONLY because the EtherLite - * is broken, and sends a response to 24 back as 15. - * To resolve this, the EtherLite firmware is now - * fixed to send back 24 correctly, but, for backwards - * compatibility, we now have reserved 15 for the - * bad EtherLite response to 24 as well. - */ - - /* Fallthru! */ - - case 24: - - /* - * If the product doesn't support VPD, - * it will send back a null IDRESP, - * which is a length of 4 bytes. - */ - if (plen > 4) { - memcpy(nd->nd_vpd, b + 4, min(plen - 4, (long) VPDSIZE)); - nd->nd_vpd_len = min(plen - 4, (long) VPDSIZE); - } - - nd->nd_expect &= ~NR_VPD; - break; - - default: - goto decode_error; - } - - if (nd->nd_expect == 0 && - nd->nd_state == NS_WAIT_QUERY) { - nd->nd_state = NS_READY; - } - break; - - /* - * Debug packet. - */ - - case 14: - if (remain < 4) - goto done; - - plen = get_unaligned_be16(b + 2) + 4; - - if (plen > 1000) { - error = "Debug Packet too large"; - goto prot_error; - } - - if (remain < plen) - goto done; - break; - - /* - * Handle reset packet. - */ - - case 15: - if (remain < 2) - goto done; - - plen = 2 + b[1]; - - if (remain < plen) - goto done; - - nd->nd_tx_work = 1; - - n = b[plen]; - b[plen] = 0; - - b[plen] = n; - - error = "Client Reset Acknowledge"; - goto prot_error; - - default: - goto decode_error; - } - break; - - default: - goto decode_error; - } - - b += plen; - remain -= plen; - } - - /* - * When the buffer is exhausted, copy any data left at the - * top of the buffer back down to the bottom for the next - * read request. - */ - -done: - if (remain > 0 && b != buf) - memcpy(buf, b, remain); - - nd->nd_remain = remain; - return; - -/* - * Handle a decode error. - */ - -decode_error: - error = "Protocol decode error"; - -/* - * Handle a general protocol error. - */ - -prot_error: - nd->nd_remain = 0; - nd->nd_state = NS_SEND_ERROR; - nd->nd_error = error; -} - -/* - * dgrp_net_write() -- write data to the network device. - * - * A zero byte write indicates that the connection to the RealPort - * device has been broken. - * - * A non-zero write indicates data from the RealPort device. - */ -static ssize_t dgrp_net_write(struct file *file, const char __user *buf, - size_t count, loff_t *ppos) -{ - struct nd_struct *nd; - ssize_t rtn = 0; - long n; - long total = 0; - - /* - * Get the node pointer, and quit if it doesn't exist. - */ - nd = (struct nd_struct *)(file->private_data); - if (!nd) - return -ENXIO; - - /* - * Grab the NET lock. - */ - down(&nd->nd_net_semaphore); - - nd->nd_write_count++; - - /* - * Handle disconnect. - */ - - if (count == 0) { - dgrp_net_idle(nd); - /* - * Set the active port count to zero. - */ - dgrp_chan_count(nd, 0); - goto unlock; - } - - /* - * Loop to process entire receive packet. - */ - - while (count > 0) { - n = UIO_MAX - nd->nd_remain; - - if (n > count) - n = count; - - nd->nd_rx_byte += n + nd->nd_link.lk_header_size; - - rtn = copy_from_user(nd->nd_iobuf + nd->nd_remain, - (void __user *) buf + total, n); - if (rtn) { - rtn = -EFAULT; - goto unlock; - } - - *ppos += n; - - total += n; - - count -= n; - - if (nd->nd_mon_buf) - dgrp_monitor_data(nd, RPDUMP_SERVER, - nd->nd_iobuf + nd->nd_remain, n); - - nd->nd_remain += n; - - dgrp_receive(nd); - } - - rtn = total; - -unlock: - /* - * Release the NET lock. - */ - up(&nd->nd_net_semaphore); - - return rtn; -} - - -/* - * dgrp_net_select() - * Determine whether a device is ready to be read or written to, and - * sleep if not. - */ -static unsigned int dgrp_net_select(struct file *file, - struct poll_table_struct *table) -{ - unsigned int retval = 0; - struct nd_struct *nd = file->private_data; - - poll_wait(file, &nd->nd_tx_waitq, table); - - if (nd->nd_tx_ready) - retval |= POLLIN | POLLRDNORM; /* Conditionally readable */ - - retval |= POLLOUT | POLLWRNORM; /* Always writeable */ - - return retval; -} - -/* - * dgrp_net_ioctl - * - * Implement those functions which allow the network daemon to control - * the network parameters in the driver. The ioctls include ones to - * get and set the link speed parameters for the PortServer. - */ -static long dgrp_net_ioctl(struct file *file, unsigned int cmd, - unsigned long arg) -{ - struct nd_struct *nd; - int rtn = 0; - long size = _IOC_SIZE(cmd); - struct link_struct link; - - nd = file->private_data; - - if (_IOC_DIR(cmd) & _IOC_READ) - rtn = access_ok(VERIFY_WRITE, (void __user *) arg, size); - else if (_IOC_DIR(cmd) & _IOC_WRITE) - rtn = access_ok(VERIFY_READ, (void __user *) arg, size); - - if (!rtn) - return rtn; - - switch (cmd) { - case DIGI_SETLINK: - if (size != sizeof(struct link_struct)) - return -EINVAL; - - if (copy_from_user((void *)(&link), (void __user *) arg, size)) - return -EFAULT; - - if (link.lk_fast_rate < 9600) - link.lk_fast_rate = 9600; - - if (link.lk_slow_rate < 2400) - link.lk_slow_rate = 2400; - - if (link.lk_fast_rate > 10000000) - link.lk_fast_rate = 10000000; - - if (link.lk_slow_rate > link.lk_fast_rate) - link.lk_slow_rate = link.lk_fast_rate; - - if (link.lk_fast_delay > 2000) - link.lk_fast_delay = 2000; - - if (link.lk_slow_delay > 10000) - link.lk_slow_delay = 10000; - - if (link.lk_fast_delay < 60) - link.lk_fast_delay = 60; - - if (link.lk_slow_delay < link.lk_fast_delay) - link.lk_slow_delay = link.lk_fast_delay; - - if (link.lk_header_size < 2) - link.lk_header_size = 2; - - if (link.lk_header_size > 128) - link.lk_header_size = 128; - - link.lk_fast_rate /= 8 * 1000 / dgrp_poll_tick; - link.lk_slow_rate /= 8 * 1000 / dgrp_poll_tick; - - link.lk_fast_delay /= dgrp_poll_tick; - link.lk_slow_delay /= dgrp_poll_tick; - - nd->nd_link = link; - - break; - - case DIGI_GETLINK: - if (size != sizeof(struct link_struct)) - return -EINVAL; - - if (copy_to_user((void __user *)arg, (void *)(&nd->nd_link), - size)) - return -EFAULT; - - break; - - default: - return -EINVAL; - - } - - return 0; -} - -/** - * dgrp_poll_handler() -- handler for poll timer - * - * As each timer expires, it determines (a) whether the "transmit" - * waiter needs to be woken up, and (b) whether the poller needs to - * be rescheduled. - */ -void dgrp_poll_handler(unsigned long arg) -{ - struct dgrp_poll_data *poll_data; - struct nd_struct *nd; - struct link_struct *lk; - ulong time; - ulong poll_time; - ulong freq; - ulong lock_flags; - - poll_data = (struct dgrp_poll_data *) arg; - freq = 1000 / poll_data->poll_tick; - poll_data->poll_round += 17; - - if (poll_data->poll_round >= freq) - poll_data->poll_round -= freq; - - /* - * Loop to process all open nodes. - * - * For each node, determine the rate at which it should - * be transmitting data. Then if the node should wake up - * and transmit data now, enable the net receive select - * to get the transmit going. - */ - - list_for_each_entry(nd, &nd_struct_list, list) { - - lk = &nd->nd_link; - - /* - * Decrement statistics. These are only for use with - * KME, so don't worry that the operations are done - * unlocked, and so the results are occassionally wrong. - */ - - nd->nd_read_count -= (nd->nd_read_count + - poll_data->poll_round) / freq; - nd->nd_write_count -= (nd->nd_write_count + - poll_data->poll_round) / freq; - nd->nd_send_count -= (nd->nd_send_count + - poll_data->poll_round) / freq; - nd->nd_tx_byte -= (nd->nd_tx_byte + - poll_data->poll_round) / freq; - nd->nd_rx_byte -= (nd->nd_rx_byte + - poll_data->poll_round) / freq; - - /* - * Wake the daemon to transmit data only when there is - * enough byte credit to send data. - * - * The results are approximate because the operations - * are performed unlocked, and we are inspecting - * data asynchronously updated elsewhere. The whole - * thing is just approximation anyway, so that should - * be okay. - */ - - if (lk->lk_slow_rate >= UIO_MAX) { - - nd->nd_delay = 0; - nd->nd_rate = UIO_MAX; - - nd->nd_tx_deposit = nd->nd_tx_charge + 3 * UIO_MAX; - nd->nd_tx_credit = 3 * UIO_MAX; - - } else { - - long rate; - long delay; - long deposit; - long charge; - long size; - long excess; - - long seq_in = nd->nd_seq_in; - long seq_out = nd->nd_seq_out; - - /* - * If there are no outstanding packets, run at the - * fastest rate. - */ - - if (seq_in == seq_out) { - delay = 0; - rate = lk->lk_fast_rate; - } - - /* - * Otherwise compute the transmit rate based on the - * delay since the oldest packet. - */ - - else { - /* - * The actual delay is computed as the - * time since the oldest unacknowledged - * packet was sent, minus the time it - * took to send that packet to the server. - */ - - delay = ((jiffies - nd->nd_seq_time[seq_out]) - - (nd->nd_seq_size[seq_out] / - lk->lk_fast_rate)); - - /* - * If the delay is less than the "fast" - * delay, transmit full speed. If greater - * than the "slow" delay, transmit at the - * "slow" speed. In between, interpolate - * between the fast and slow speeds. - */ - - rate = - (delay <= lk->lk_fast_delay ? - lk->lk_fast_rate : - delay >= lk->lk_slow_delay ? - lk->lk_slow_rate : - (lk->lk_slow_rate + - (lk->lk_slow_delay - delay) * - (lk->lk_fast_rate - lk->lk_slow_rate) / - (lk->lk_slow_delay - lk->lk_fast_delay) - ) - ); - } - - nd->nd_delay = delay; - nd->nd_rate = rate; - - /* - * Increase the transmit credit by depositing the - * current transmit rate. - */ - - deposit = nd->nd_tx_deposit; - charge = nd->nd_tx_charge; - - deposit += rate; - - /* - * If the available transmit credit becomes too large, - * reduce the deposit to correct the value. - * - * Too large is the max of: - * 6 times the header size - * 3 times the current transmit rate. - */ - - size = 2 * nd->nd_link.lk_header_size; - - if (size < rate) - size = rate; - - size *= 3; - - excess = deposit - charge - size; - - if (excess > 0) - deposit -= excess; - - nd->nd_tx_deposit = deposit; - nd->nd_tx_credit = deposit - charge; - - /* - * Wake the transmit task only if the transmit credit - * is at least 3 times the transmit header size. - */ - - size = 3 * lk->lk_header_size; - - if (nd->nd_tx_credit < size) - continue; - } - - - /* - * Enable the READ select to wake the daemon if there - * is useful work for the drp_read routine to perform. - */ - - if (waitqueue_active(&nd->nd_tx_waitq) && - (nd->nd_tx_work != 0 || - (ulong)(jiffies - nd->nd_tx_time) >= IDLE_MAX)) { - nd->nd_tx_ready = 1; - - wake_up_interruptible(&nd->nd_tx_waitq); - - /* not needed */ - /* nd->nd_flag &= ~ND_SELECT; */ - } - } - - - /* - * Schedule ourself back at the nominal wakeup interval. - */ - spin_lock_irqsave(&poll_data->poll_lock, lock_flags); - - poll_data->node_active_count--; - if (poll_data->node_active_count > 0) { - poll_data->node_active_count++; - poll_time = poll_data->timer.expires + - poll_data->poll_tick * HZ / 1000; - - time = poll_time - jiffies; - - if (time >= 2 * poll_data->poll_tick) - poll_time = jiffies + dgrp_poll_tick * HZ / 1000; - - poll_data->timer.expires = poll_time; - add_timer(&poll_data->timer); - } - - spin_unlock_irqrestore(&poll_data->poll_lock, lock_flags); -} diff --git a/trunk/drivers/staging/dgrp/dgrp_ports_ops.c b/trunk/drivers/staging/dgrp/dgrp_ports_ops.c deleted file mode 100644 index cd1fc2088624..000000000000 --- a/trunk/drivers/staging/dgrp/dgrp_ports_ops.c +++ /dev/null @@ -1,170 +0,0 @@ -/* - * - * Copyright 1999-2000 Digi International (www.digi.com) - * James Puzzo - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the - * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR - * PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -/* - * - * Filename: - * - * dgrp_ports_ops.c - * - * Description: - * - * Handle the file operations required for the /proc/dgrp/ports/... - * devices. Basically gathers tty status for the node and returns it. - * - * Author: - * - * James A. Puzzo - * - */ - -#include -#include -#include -#include -#include - -#include "dgrp_common.h" - -/* File operation declarations */ -static int dgrp_ports_open(struct inode *, struct file *); - -static const struct file_operations ports_ops = { - .owner = THIS_MODULE, - .open = dgrp_ports_open, - .read = seq_read, - .llseek = seq_lseek, - .release = seq_release -}; - -static struct inode_operations ports_inode_ops = { - .permission = dgrp_inode_permission -}; - - -void dgrp_register_ports_hook(struct proc_dir_entry *de) -{ - struct nd_struct *node = de->data; - - de->proc_iops = &ports_inode_ops; - de->proc_fops = &ports_ops; - node->nd_ports_de = de; -} - -static void *dgrp_ports_seq_start(struct seq_file *seq, loff_t *pos) -{ - if (*pos == 0) - seq_puts(seq, "#num tty_open pr_open tot_wait MSTAT IFLAG OFLAG CFLAG BPS DIGIFLAGS\n"); - - return pos; -} - -static void *dgrp_ports_seq_next(struct seq_file *seq, void *v, loff_t *pos) -{ - struct nd_struct *nd = seq->private; - - if (*pos >= nd->nd_chan_count) - return NULL; - - *pos += 1; - - return pos; -} - -static void dgrp_ports_seq_stop(struct seq_file *seq, void *v) -{ -} - -static int dgrp_ports_seq_show(struct seq_file *seq, void *v) -{ - loff_t *pos = v; - struct nd_struct *nd; - struct ch_struct *ch; - struct un_struct *tun, *pun; - unsigned int totcnt; - - nd = seq->private; - if (!nd) - return 0; - - if (*pos >= nd->nd_chan_count) - return 0; - - ch = &nd->nd_chan[*pos]; - tun = &ch->ch_tun; - pun = &ch->ch_pun; - - /* - * If port is not open and no one is waiting to - * open it, the modem signal values can't be - * trusted, and will be zeroed. - */ - totcnt = tun->un_open_count + - pun->un_open_count + - ch->ch_wait_count[0] + - ch->ch_wait_count[1] + - ch->ch_wait_count[2]; - - seq_printf(seq, "%02d %02d %02d %02d 0x%04X 0x%04X 0x%04X 0x%04X %-6d 0x%04X\n", - (int) *pos, - tun->un_open_count, - pun->un_open_count, - ch->ch_wait_count[0] + - ch->ch_wait_count[1] + - ch->ch_wait_count[2], - (totcnt ? ch->ch_s_mlast : 0), - ch->ch_s_iflag, - ch->ch_s_oflag, - ch->ch_s_cflag, - (ch->ch_s_brate ? (1843200 / ch->ch_s_brate) : 0), - ch->ch_digi.digi_flags); - - return 0; -} - -static const struct seq_operations ports_seq_ops = { - .start = dgrp_ports_seq_start, - .next = dgrp_ports_seq_next, - .stop = dgrp_ports_seq_stop, - .show = dgrp_ports_seq_show, -}; - -/** - * dgrp_ports_open -- open the /proc/dgrp/ports/... device - * @inode: struct inode * - * @file: struct file * - * - * Open function to open the /proc/dgrp/ports device for a PortServer. - * This is the open function for struct file_operations - */ -static int dgrp_ports_open(struct inode *inode, struct file *file) -{ - struct seq_file *seq; - int rtn; - - rtn = seq_open(file, &ports_seq_ops); - if (!rtn) { - seq = file->private_data; - seq->private = PDE(inode)->data; - } - - return rtn; -} diff --git a/trunk/drivers/staging/dgrp/dgrp_specproc.c b/trunk/drivers/staging/dgrp/dgrp_specproc.c deleted file mode 100644 index 28f5c9ab6b43..000000000000 --- a/trunk/drivers/staging/dgrp/dgrp_specproc.c +++ /dev/null @@ -1,822 +0,0 @@ -/* - * - * Copyright 1999 Digi International (www.digi.com) - * James Puzzo - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the - * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR - * PURPOSE. See the GNU General Public License for more details. - * - */ - -/* - * - * Filename: - * - * dgrp_specproc.c - * - * Description: - * - * Handle the "config" proc entry for the linux realport device driver - * and provide slots for the "net" and "mon" devices - * - * Author: - * - * James A. Puzzo - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "dgrp_common.h" - -static struct dgrp_proc_entry dgrp_table[]; -static struct proc_dir_entry *dgrp_proc_dir_entry; - -static int dgrp_add_id(long id); -static int dgrp_remove_nd(struct nd_struct *nd); -static void unregister_dgrp_device(struct proc_dir_entry *de); -static void register_dgrp_device(struct nd_struct *node, - struct proc_dir_entry *root, - void (*register_hook)(struct proc_dir_entry *de)); - -/* File operation declarations */ -static int dgrp_gen_proc_open(struct inode *, struct file *); -static int dgrp_gen_proc_close(struct inode *, struct file *); -static int parse_write_config(char *); - - -static const struct file_operations dgrp_proc_file_ops = { - .owner = THIS_MODULE, - .open = dgrp_gen_proc_open, - .release = dgrp_gen_proc_close, -}; - -static struct inode_operations proc_inode_ops = { - .permission = dgrp_inode_permission -}; - - -static void register_proc_table(struct dgrp_proc_entry *, - struct proc_dir_entry *); -static void unregister_proc_table(struct dgrp_proc_entry *, - struct proc_dir_entry *); - -static struct dgrp_proc_entry dgrp_net_table[]; -static struct dgrp_proc_entry dgrp_mon_table[]; -static struct dgrp_proc_entry dgrp_ports_table[]; -static struct dgrp_proc_entry dgrp_dpa_table[]; - -static ssize_t config_proc_write(struct file *file, const char __user *buffer, - size_t count, loff_t *pos); - -static int nodeinfo_proc_open(struct inode *inode, struct file *file); -static int info_proc_open(struct inode *inode, struct file *file); -static int config_proc_open(struct inode *inode, struct file *file); - -static struct file_operations config_proc_file_ops = { - .owner = THIS_MODULE, - .open = config_proc_open, - .read = seq_read, - .llseek = seq_lseek, - .release = seq_release, - .write = config_proc_write -}; - -static struct file_operations info_proc_file_ops = { - .owner = THIS_MODULE, - .open = info_proc_open, - .read = seq_read, - .llseek = seq_lseek, - .release = seq_release, -}; - -static struct file_operations nodeinfo_proc_file_ops = { - .owner = THIS_MODULE, - .open = nodeinfo_proc_open, - .read = seq_read, - .llseek = seq_lseek, - .release = seq_release, -}; - -static struct dgrp_proc_entry dgrp_table[] = { - { - .id = DGRP_CONFIG, - .name = "config", - .mode = 0644, - .proc_file_ops = &config_proc_file_ops, - }, - { - .id = DGRP_INFO, - .name = "info", - .mode = 0644, - .proc_file_ops = &info_proc_file_ops, - }, - { - .id = DGRP_NODEINFO, - .name = "nodeinfo", - .mode = 0644, - .proc_file_ops = &nodeinfo_proc_file_ops, - }, - { - .id = DGRP_NETDIR, - .name = "net", - .mode = 0500, - .child = dgrp_net_table - }, - { - .id = DGRP_MONDIR, - .name = "mon", - .mode = 0500, - .child = dgrp_mon_table - }, - { - .id = DGRP_PORTSDIR, - .name = "ports", - .mode = 0500, - .child = dgrp_ports_table - }, - { - .id = DGRP_DPADIR, - .name = "dpa", - .mode = 0500, - .child = dgrp_dpa_table - } -}; - -static struct proc_dir_entry *net_entry_pointer; -static struct proc_dir_entry *mon_entry_pointer; -static struct proc_dir_entry *dpa_entry_pointer; -static struct proc_dir_entry *ports_entry_pointer; - -static struct dgrp_proc_entry dgrp_net_table[] = { - {0} -}; - -static struct dgrp_proc_entry dgrp_mon_table[] = { - {0} -}; - -static struct dgrp_proc_entry dgrp_ports_table[] = { - {0} -}; - -static struct dgrp_proc_entry dgrp_dpa_table[] = { - {0} -}; - -void dgrp_unregister_proc(void) -{ - unregister_proc_table(dgrp_table, dgrp_proc_dir_entry); - net_entry_pointer = NULL; - mon_entry_pointer = NULL; - dpa_entry_pointer = NULL; - ports_entry_pointer = NULL; - - if (dgrp_proc_dir_entry) { - remove_proc_entry(dgrp_proc_dir_entry->name, - dgrp_proc_dir_entry->parent); - dgrp_proc_dir_entry = NULL; - } - -} - -void dgrp_register_proc(void) -{ - /* - * Register /proc/dgrp - */ - dgrp_proc_dir_entry = proc_create("dgrp", S_IFDIR, NULL, - &dgrp_proc_file_ops); - register_proc_table(dgrp_table, dgrp_proc_dir_entry); -} - -/* - * /proc/sys support - */ -static int dgrp_proc_match(int len, const char *name, struct proc_dir_entry *de) -{ - if (!de || !de->low_ino) - return 0; - if (de->namelen != len) - return 0; - return !memcmp(name, de->name, len); -} - - -/* - * Scan the entries in table and add them all to /proc at the position - * referred to by "root" - */ -static void register_proc_table(struct dgrp_proc_entry *table, - struct proc_dir_entry *root) -{ - struct proc_dir_entry *de; - int len; - mode_t mode; - - for (; table->id; table++) { - /* Can't do anything without a proc name. */ - if (!table->name) - continue; - - /* Maybe we can't do anything with it... */ - if (!table->proc_file_ops && - !table->child) { - pr_warn("dgrp: Can't register %s\n", - table->name); - continue; - } - - len = strlen(table->name); - mode = table->mode; - - de = NULL; - if (!table->child) - mode |= S_IFREG; - else { - mode |= S_IFDIR; - for (de = root->subdir; de; de = de->next) { - if (dgrp_proc_match(len, table->name, de)) - break; - } - /* If the subdir exists already, de is non-NULL */ - } - - if (!de) { - de = create_proc_entry(table->name, mode, root); - if (!de) - continue; - de->data = (void *) table; - if (!table->child) { - de->proc_iops = &proc_inode_ops; - if (table->proc_file_ops) - de->proc_fops = table->proc_file_ops; - else - de->proc_fops = &dgrp_proc_file_ops; - } - } - table->de = de; - if (de->mode & S_IFDIR) - register_proc_table(table->child, de); - - if (table->id == DGRP_NETDIR) - net_entry_pointer = de; - - if (table->id == DGRP_MONDIR) - mon_entry_pointer = de; - - if (table->id == DGRP_DPADIR) - dpa_entry_pointer = de; - - if (table->id == DGRP_PORTSDIR) - ports_entry_pointer = de; - } -} - -/* - * Unregister a /proc sysctl table and any subdirectories. - */ -static void unregister_proc_table(struct dgrp_proc_entry *table, - struct proc_dir_entry *root) -{ - struct proc_dir_entry *de; - struct nd_struct *tmp; - - list_for_each_entry(tmp, &nd_struct_list, list) { - if ((table == dgrp_net_table) && (tmp->nd_net_de)) { - unregister_dgrp_device(tmp->nd_net_de); - dgrp_remove_node_class_sysfs_files(tmp); - } - - if ((table == dgrp_mon_table) && (tmp->nd_mon_de)) - unregister_dgrp_device(tmp->nd_mon_de); - - if ((table == dgrp_dpa_table) && (tmp->nd_dpa_de)) - unregister_dgrp_device(tmp->nd_dpa_de); - - if ((table == dgrp_ports_table) && (tmp->nd_ports_de)) - unregister_dgrp_device(tmp->nd_ports_de); - } - - for (; table->id; table++) { - de = table->de; - - if (!de) - continue; - if (de->mode & S_IFDIR) { - if (!table->child) { - pr_alert("dgrp: malformed sysctl tree on free\n"); - continue; - } - unregister_proc_table(table->child, de); - - /* Don't unregister directories which still have entries */ - if (de->subdir) - continue; - } - - /* Don't unregister proc entries that are still being used.. */ - if ((atomic_read(&de->count)) != 1) { - pr_alert("proc entry %s in use, not removing\n", - de->name); - continue; - } - - remove_proc_entry(de->name, de->parent); - table->de = NULL; - } -} - -static int dgrp_gen_proc_open(struct inode *inode, struct file *file) -{ - struct proc_dir_entry *de; - struct dgrp_proc_entry *entry; - int ret = 0; - - de = (struct proc_dir_entry *) PDE(file->f_dentry->d_inode); - if (!de || !de->data) { - ret = -ENXIO; - goto done; - } - - entry = (struct dgrp_proc_entry *) de->data; - if (!entry) { - ret = -ENXIO; - goto done; - } - - down(&entry->excl_sem); - - if (entry->excl_cnt) - ret = -EBUSY; - else - entry->excl_cnt++; - - up(&entry->excl_sem); - -done: - return ret; -} - -static int dgrp_gen_proc_close(struct inode *inode, struct file *file) -{ - struct proc_dir_entry *de; - struct dgrp_proc_entry *entry; - - de = (struct proc_dir_entry *) PDE(file->f_dentry->d_inode); - if (!de || !de->data) - goto done; - - entry = (struct dgrp_proc_entry *) de->data; - if (!entry) - goto done; - - down(&entry->excl_sem); - - if (entry->excl_cnt) - entry->excl_cnt = 0; - - up(&entry->excl_sem); - -done: - return 0; -} - -static void *config_proc_start(struct seq_file *m, loff_t *pos) -{ - return seq_list_start_head(&nd_struct_list, *pos); -} - -static void *config_proc_next(struct seq_file *p, void *v, loff_t *pos) -{ - return seq_list_next(v, &nd_struct_list, pos); -} - -static void config_proc_stop(struct seq_file *m, void *v) -{ -} - -static int config_proc_show(struct seq_file *m, void *v) -{ - struct nd_struct *nd; - char tmp_id[4]; - - if (v == &nd_struct_list) { - seq_puts(m, "#-----------------------------------------------------------------------------\n"); - seq_puts(m, "# Avail\n"); - seq_puts(m, "# ID Major State Ports\n"); - return 0; - } - - nd = list_entry(v, struct nd_struct, list); - - ID_TO_CHAR(nd->nd_ID, tmp_id); - - seq_printf(m, " %-2.2s %-5ld %-10.10s %-5d\n", - tmp_id, - nd->nd_major, - ND_STATE_STR(nd->nd_state), - nd->nd_chan_count); - - return 0; -} - -static const struct seq_operations proc_config_ops = { - .start = config_proc_start, - .next = config_proc_next, - .stop = config_proc_stop, - .show = config_proc_show -}; - -static int config_proc_open(struct inode *inode, struct file *file) -{ - return seq_open(file, &proc_config_ops); -} - - -/* - * When writing configuration information, each "record" (i.e. each - * write) is treated as an independent request. See the "parse" - * description for more details. - */ -static ssize_t config_proc_write(struct file *file, const char __user *buffer, - size_t count, loff_t *pos) -{ - ssize_t retval; - char *inbuf, *sp; - char *line, *ldelim; - - if (count > 32768) - return -EINVAL; - - inbuf = sp = vzalloc(count + 1); - if (!inbuf) - return -ENOMEM; - - if (copy_from_user(inbuf, buffer, count)) { - retval = -EFAULT; - goto done; - } - - inbuf[count] = 0; - - ldelim = "\n"; - - line = strpbrk(sp, ldelim); - while (line) { - *line = 0; - retval = parse_write_config(sp); - if (retval) - goto done; - - sp = line + 1; - line = strpbrk(sp, ldelim); - } - - retval = count; -done: - vfree(inbuf); - return retval; -} - -/* - * ------------------------------------------------------------------------ - * - * The following are the functions to parse input - * - * ------------------------------------------------------------------------ - */ -static inline char *skip_past_ws(const char *str) -{ - while ((*str) && !isspace(*str)) - ++str; - - return skip_spaces(str); -} - -static int parse_id(char **c, char *cID) -{ - int tmp = **c; - - if (isalnum(tmp) || (tmp == '_')) - cID[0] = tmp; - else - return -EINVAL; - - (*c)++; tmp = **c; - - if (isalnum(tmp) || (tmp == '_')) { - cID[1] = tmp; - (*c)++; - } else - cID[1] = 0; - - return 0; -} - -static int parse_add_config(char *buf) -{ - char *c = buf; - int retval; - char cID[2]; - long ID; - - c = skip_past_ws(c); - - retval = parse_id(&c, cID); - if (retval < 0) - return retval; - - ID = CHAR_TO_ID(cID); - - c = skip_past_ws(c); - - return dgrp_add_id(ID); -} - -static int parse_del_config(char *buf) -{ - char *c = buf; - int retval; - struct nd_struct *nd; - char cID[2]; - long ID; - long major; - - c = skip_past_ws(c); - - retval = parse_id(&c, cID); - if (retval < 0) - return retval; - - ID = CHAR_TO_ID(cID); - - c = skip_past_ws(c); - - retval = kstrtol(c, 10, &major); - if (retval) - return retval; - - nd = nd_struct_get(major); - if (!nd) - return -EINVAL; - - if ((nd->nd_major != major) || (nd->nd_ID != ID)) - return -EINVAL; - - return dgrp_remove_nd(nd); -} - -static int parse_chg_config(char *buf) -{ - return -EINVAL; -} - -/* - * The passed character buffer represents a single configuration request. - * If the first character is a "+", it is parsed as a request to add a - * PortServer - * If the first character is a "-", it is parsed as a request to delete a - * PortServer - * If the first character is a "*", it is parsed as a request to change a - * PortServer - * Any other character (including whitespace) causes the record to be - * ignored. - */ -static int parse_write_config(char *buf) -{ - int retval; - - switch (buf[0]) { - case '+': - retval = parse_add_config(buf); - break; - case '-': - retval = parse_del_config(buf); - break; - case '*': - retval = parse_chg_config(buf); - break; - default: - retval = -EINVAL; - } - - return retval; -} - -static int info_proc_show(struct seq_file *m, void *v) -{ - seq_printf(m, "version: %s\n", DIGI_VERSION); - seq_puts(m, "register_with_sysfs: 1\n"); - seq_printf(m, "rawreadok: 0x%08x\t(%d)\n", - dgrp_rawreadok, dgrp_rawreadok); - seq_printf(m, "pollrate: 0x%08x\t(%d)\n", - dgrp_poll_tick, dgrp_poll_tick); - - return 0; -} - -static int info_proc_open(struct inode *inode, struct file *file) -{ - return single_open(file, info_proc_show, NULL); -} - - -static void *nodeinfo_start(struct seq_file *m, loff_t *pos) -{ - return seq_list_start_head(&nd_struct_list, *pos); -} - -static void *nodeinfo_next(struct seq_file *p, void *v, loff_t *pos) -{ - return seq_list_next(v, &nd_struct_list, pos); -} - -static void nodeinfo_stop(struct seq_file *m, void *v) -{ -} - -static int nodeinfo_show(struct seq_file *m, void *v) -{ - struct nd_struct *nd; - char hwver[8]; - char swver[8]; - char tmp_id[4]; - - if (v == &nd_struct_list) { - seq_puts(m, "#-----------------------------------------------------------------------------\n"); - seq_puts(m, "# HW HW SW\n"); - seq_puts(m, "# ID State Version ID Version Description\n"); - return 0; - } - - nd = list_entry(v, struct nd_struct, list); - - ID_TO_CHAR(nd->nd_ID, tmp_id); - - if (nd->nd_state == NS_READY) { - sprintf(hwver, "%d.%d", (nd->nd_hw_ver >> 8) & 0xff, - nd->nd_hw_ver & 0xff); - sprintf(swver, "%d.%d", (nd->nd_sw_ver >> 8) & 0xff, - nd->nd_sw_ver & 0xff); - seq_printf(m, " %-2.2s %-10.10s %-7.7s %-3d %-7.7s %-35.35s\n", - tmp_id, - ND_STATE_STR(nd->nd_state), - hwver, - nd->nd_hw_id, - swver, - nd->nd_ps_desc); - - } else { - seq_printf(m, " %-2.2s %-10.10s\n", - tmp_id, - ND_STATE_STR(nd->nd_state)); - } - - return 0; -} - - -static const struct seq_operations nodeinfo_ops = { - .start = nodeinfo_start, - .next = nodeinfo_next, - .stop = nodeinfo_stop, - .show = nodeinfo_show -}; - -static int nodeinfo_proc_open(struct inode *inode, struct file *file) -{ - return seq_open(file, &nodeinfo_ops); -} - -/** - * dgrp_add_id() -- creates new nd struct and adds it to list - * @id: id of device to add - */ -static int dgrp_add_id(long id) -{ - struct nd_struct *nd; - int ret; - int i; - - nd = kzalloc(sizeof(struct nd_struct), GFP_KERNEL); - if (!nd) - return -ENOMEM; - - nd->nd_major = 0; - nd->nd_ID = id; - - spin_lock_init(&nd->nd_lock); - - init_waitqueue_head(&nd->nd_tx_waitq); - init_waitqueue_head(&nd->nd_mon_wqueue); - init_waitqueue_head(&nd->nd_dpa_wqueue); - for (i = 0; i < SEQ_MAX; i++) - init_waitqueue_head(&nd->nd_seq_wque[i]); - - /* setup the structures to get the major number */ - ret = dgrp_tty_init(nd); - if (ret) - goto error_out; - - nd->nd_major = nd->nd_serial_ttdriver->major; - - ret = nd_struct_add(nd); - if (ret) - goto error_out; - - register_dgrp_device(nd, net_entry_pointer, dgrp_register_net_hook); - register_dgrp_device(nd, mon_entry_pointer, dgrp_register_mon_hook); - register_dgrp_device(nd, dpa_entry_pointer, dgrp_register_dpa_hook); - register_dgrp_device(nd, ports_entry_pointer, - dgrp_register_ports_hook); - - return 0; - -error_out: - kfree(nd); - return ret; - -} - -static int dgrp_remove_nd(struct nd_struct *nd) -{ - int ret; - - /* Check to see if the selected structure is in use */ - if (nd->nd_tty_ref_cnt) - return -EBUSY; - - if (nd->nd_net_de) { - unregister_dgrp_device(nd->nd_net_de); - dgrp_remove_node_class_sysfs_files(nd); - } - - if (nd->nd_mon_de) - unregister_dgrp_device(nd->nd_mon_de); - - if (nd->nd_ports_de) - unregister_dgrp_device(nd->nd_ports_de); - - if (nd->nd_dpa_de) - unregister_dgrp_device(nd->nd_dpa_de); - - dgrp_tty_uninit(nd); - - ret = nd_struct_del(nd); - if (ret) - return ret; - - kfree(nd); - return 0; -} - -static void register_dgrp_device(struct nd_struct *node, - struct proc_dir_entry *root, - void (*register_hook)(struct proc_dir_entry *de)) -{ - char buf[3]; - struct proc_dir_entry *de; - - ID_TO_CHAR(node->nd_ID, buf); - - de = create_proc_entry(buf, 0600 | S_IFREG, root); - if (!de) - return; - - de->data = (void *) node; - - if (register_hook) - register_hook(de); - -} - -static void unregister_dgrp_device(struct proc_dir_entry *de) -{ - if (!de) - return; - - /* Don't unregister proc entries that are still being used.. */ - if ((atomic_read(&de->count)) != 1) { - pr_alert("%s - proc entry %s in use. Not removing.\n", - __func__, de->name); - return; - } - - remove_proc_entry(de->name, de->parent); - de = NULL; -} diff --git a/trunk/drivers/staging/dgrp/dgrp_sysfs.c b/trunk/drivers/staging/dgrp/dgrp_sysfs.c deleted file mode 100644 index e5a3c88d016e..000000000000 --- a/trunk/drivers/staging/dgrp/dgrp_sysfs.c +++ /dev/null @@ -1,555 +0,0 @@ -/* - * Copyright 2004 Digi International (www.digi.com) - * Scott H Kilau - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the - * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR - * PURPOSE. See the GNU General Public License for more details. - * - */ - -#include "dgrp_common.h" - -#include -#include -#include -#include -#include -#include -#include -#include - - -#define PORTSERVER_DIVIDEND 1843200 -#define SERIAL_TYPE_NORMAL 1 -#define SERIAL_TYPE_CALLOUT 2 -#define SERIAL_TYPE_XPRINT 3 - - -static struct class *dgrp_class; -static struct device *dgrp_class_nodes_dev; -static struct device *dgrp_class_global_settings_dev; - - -static ssize_t dgrp_class_version_show(struct class *class, - struct class_attribute *attr, char *buf) -{ - return snprintf(buf, PAGE_SIZE, "%s\n", DIGI_VERSION); -} -static CLASS_ATTR(driver_version, 0400, dgrp_class_version_show, NULL); - - -static ssize_t dgrp_class_register_with_sysfs_show(struct device *c, - struct device_attribute *attr, - char *buf) -{ - return snprintf(buf, PAGE_SIZE, "1\n"); -} -static DEVICE_ATTR(register_with_sysfs, 0400, - dgrp_class_register_with_sysfs_show, NULL); - - -static ssize_t dgrp_class_rawreadok_show(struct device *c, - struct device_attribute *attr, - char *buf) -{ - return snprintf(buf, PAGE_SIZE, "%d\n", dgrp_rawreadok); -} -static ssize_t dgrp_class_rawreadok_store(struct device *c, - struct device_attribute *attr, - const char *buf, size_t count) -{ - sscanf(buf, "0x%x\n", &dgrp_rawreadok); - return count; -} -static DEVICE_ATTR(rawreadok, 0600, dgrp_class_rawreadok_show, - dgrp_class_rawreadok_store); - - -static ssize_t dgrp_class_pollrate_show(struct device *c, - struct device_attribute *attr, - char *buf) -{ - return snprintf(buf, PAGE_SIZE, "%d\n", dgrp_poll_tick); -} - -static ssize_t dgrp_class_pollrate_store(struct device *c, - struct device_attribute *attr, - const char *buf, size_t count) -{ - sscanf(buf, "0x%x\n", &dgrp_poll_tick); - return count; -} -static DEVICE_ATTR(pollrate, 0600, dgrp_class_pollrate_show, - dgrp_class_pollrate_store); - -static struct attribute *dgrp_sysfs_global_settings_entries[] = { - &dev_attr_pollrate.attr, - &dev_attr_rawreadok.attr, - &dev_attr_register_with_sysfs.attr, - NULL -}; - - -static struct attribute_group dgrp_global_settings_attribute_group = { - .name = NULL, - .attrs = dgrp_sysfs_global_settings_entries, -}; - - - -void dgrp_create_class_sysfs_files(void) -{ - int ret = 0; - int max_majors = 1U << (32 - MINORBITS); - - dgrp_class = class_create(THIS_MODULE, "digi_realport"); - ret = class_create_file(dgrp_class, &class_attr_driver_version); - - dgrp_class_global_settings_dev = device_create(dgrp_class, NULL, - MKDEV(0, max_majors + 1), NULL, "driver_settings"); - - ret = sysfs_create_group(&dgrp_class_global_settings_dev->kobj, - &dgrp_global_settings_attribute_group); - if (ret) { - pr_alert("%s: failed to create sysfs global settings device attributes.\n", - __func__); - sysfs_remove_group(&dgrp_class_global_settings_dev->kobj, - &dgrp_global_settings_attribute_group); - return; - } - - dgrp_class_nodes_dev = device_create(dgrp_class, NULL, - MKDEV(0, max_majors + 2), NULL, "nodes"); - -} - - -void dgrp_remove_class_sysfs_files(void) -{ - struct nd_struct *nd; - int max_majors = 1U << (32 - MINORBITS); - - list_for_each_entry(nd, &nd_struct_list, list) - dgrp_remove_node_class_sysfs_files(nd); - - sysfs_remove_group(&dgrp_class_global_settings_dev->kobj, - &dgrp_global_settings_attribute_group); - - class_remove_file(dgrp_class, &class_attr_driver_version); - - device_destroy(dgrp_class, MKDEV(0, max_majors + 1)); - device_destroy(dgrp_class, MKDEV(0, max_majors + 2)); - class_destroy(dgrp_class); -} - -static ssize_t dgrp_node_state_show(struct device *c, - struct device_attribute *attr, char *buf) -{ - struct nd_struct *nd; - - if (!c) - return 0; - nd = (struct nd_struct *) dev_get_drvdata(c); - if (!nd) - return 0; - - return snprintf(buf, PAGE_SIZE, "%s\n", ND_STATE_STR(nd->nd_state)); -} - -static DEVICE_ATTR(state, 0600, dgrp_node_state_show, NULL); - -static ssize_t dgrp_node_description_show(struct device *c, - struct device_attribute *attr, - char *buf) -{ - struct nd_struct *nd; - - if (!c) - return 0; - nd = (struct nd_struct *) dev_get_drvdata(c); - if (!nd) - return 0; - - if (nd->nd_state == NS_READY && nd->nd_ps_desc) - return snprintf(buf, PAGE_SIZE, "%s\n", nd->nd_ps_desc); - return 0; -} -static DEVICE_ATTR(description_info, 0600, dgrp_node_description_show, NULL); - -static ssize_t dgrp_node_hw_version_show(struct device *c, - struct device_attribute *attr, - char *buf) -{ - struct nd_struct *nd; - - if (!c) - return 0; - nd = (struct nd_struct *) dev_get_drvdata(c); - if (!nd) - return 0; - - if (nd->nd_state == NS_READY) - return snprintf(buf, PAGE_SIZE, "%d.%d\n", - (nd->nd_hw_ver >> 8) & 0xff, - nd->nd_hw_ver & 0xff); - - return 0; -} -static DEVICE_ATTR(hw_version_info, 0600, dgrp_node_hw_version_show, NULL); - -static ssize_t dgrp_node_hw_id_show(struct device *c, - struct device_attribute *attr, char *buf) -{ - struct nd_struct *nd; - - if (!c) - return 0; - nd = (struct nd_struct *) dev_get_drvdata(c); - if (!nd) - return 0; - - - if (nd->nd_state == NS_READY) - return snprintf(buf, PAGE_SIZE, "%d\n", nd->nd_hw_id); - return 0; -} -static DEVICE_ATTR(hw_id_info, 0600, dgrp_node_hw_id_show, NULL); - -static ssize_t dgrp_node_sw_version_show(struct device *c, - struct device_attribute *attr, - char *buf) -{ - struct nd_struct *nd; - - if (!c) - return 0; - - nd = (struct nd_struct *) dev_get_drvdata(c); - if (!nd) - return 0; - - if (nd->nd_state == NS_READY) - return snprintf(buf, PAGE_SIZE, "%d.%d\n", - (nd->nd_sw_ver >> 8) & 0xff, - nd->nd_sw_ver & 0xff); - - return 0; -} -static DEVICE_ATTR(sw_version_info, 0600, dgrp_node_sw_version_show, NULL); - - -static struct attribute *dgrp_sysfs_node_entries[] = { - &dev_attr_state.attr, - &dev_attr_description_info.attr, - &dev_attr_hw_version_info.attr, - &dev_attr_hw_id_info.attr, - &dev_attr_sw_version_info.attr, - NULL -}; - - -static struct attribute_group dgrp_node_attribute_group = { - .name = NULL, - .attrs = dgrp_sysfs_node_entries, -}; - - -void dgrp_create_node_class_sysfs_files(struct nd_struct *nd) -{ - int ret; - char name[10]; - - if (nd->nd_ID) - ID_TO_CHAR(nd->nd_ID, name); - else - sprintf(name, "node%ld", nd->nd_major); - - nd->nd_class_dev = device_create(dgrp_class, dgrp_class_nodes_dev, - MKDEV(0, nd->nd_major), NULL, name); - - ret = sysfs_create_group(&nd->nd_class_dev->kobj, - &dgrp_node_attribute_group); - - if (ret) { - pr_alert("%s: failed to create sysfs node device attributes.\n", - __func__); - sysfs_remove_group(&nd->nd_class_dev->kobj, - &dgrp_node_attribute_group); - return; - } - - dev_set_drvdata(nd->nd_class_dev, nd); - -} - - -void dgrp_remove_node_class_sysfs_files(struct nd_struct *nd) -{ - if (nd->nd_class_dev) { - sysfs_remove_group(&nd->nd_class_dev->kobj, - &dgrp_node_attribute_group); - - device_destroy(dgrp_class, MKDEV(0, nd->nd_major)); - nd->nd_class_dev = NULL; - } -} - - - -static ssize_t dgrp_tty_state_show(struct device *d, - struct device_attribute *attr, char *buf) -{ - struct un_struct *un; - - if (!d) - return 0; - un = (struct un_struct *) dev_get_drvdata(d); - if (!un) - return 0; - - return snprintf(buf, PAGE_SIZE, "%s\n", - un->un_open_count ? "Open" : "Closed"); -} -static DEVICE_ATTR(state_info, 0600, dgrp_tty_state_show, NULL); - -static ssize_t dgrp_tty_baud_show(struct device *d, - struct device_attribute *attr, char *buf) -{ - struct ch_struct *ch; - struct un_struct *un; - - if (!d) - return 0; - un = (struct un_struct *) dev_get_drvdata(d); - if (!un) - return 0; - ch = un->un_ch; - if (!ch) - return 0; - return snprintf(buf, PAGE_SIZE, "%d\n", - un->un_open_count ? (PORTSERVER_DIVIDEND / ch->ch_s_brate) : 0); -} -static DEVICE_ATTR(baud_info, 0400, dgrp_tty_baud_show, NULL); - - -static ssize_t dgrp_tty_msignals_show(struct device *d, - struct device_attribute *attr, char *buf) -{ - struct ch_struct *ch; - struct un_struct *un; - - if (!d) - return 0; - un = (struct un_struct *) dev_get_drvdata(d); - if (!un) - return 0; - ch = un->un_ch; - if (!ch) - return 0; - - if (ch->ch_open_count) { - return snprintf(buf, PAGE_SIZE, "%s %s %s %s %s %s\n", - (ch->ch_s_mlast & DM_RTS) ? "RTS" : "", - (ch->ch_s_mlast & DM_CTS) ? "CTS" : "", - (ch->ch_s_mlast & DM_DTR) ? "DTR" : "", - (ch->ch_s_mlast & DM_DSR) ? "DSR" : "", - (ch->ch_s_mlast & DM_CD) ? "DCD" : "", - (ch->ch_s_mlast & DM_RI) ? "RI" : ""); - } - return 0; -} -static DEVICE_ATTR(msignals_info, 0400, dgrp_tty_msignals_show, NULL); - - -static ssize_t dgrp_tty_iflag_show(struct device *d, - struct device_attribute *attr, char *buf) -{ - struct ch_struct *ch; - struct un_struct *un; - - if (!d) - return 0; - un = (struct un_struct *) dev_get_drvdata(d); - if (!un) - return 0; - ch = un->un_ch; - if (!ch) - return 0; - return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_s_iflag); -} -static DEVICE_ATTR(iflag_info, 0600, dgrp_tty_iflag_show, NULL); - - -static ssize_t dgrp_tty_cflag_show(struct device *d, - struct device_attribute *attr, char *buf) -{ - struct ch_struct *ch; - struct un_struct *un; - - if (!d) - return 0; - un = (struct un_struct *) dev_get_drvdata(d); - if (!un) - return 0; - ch = un->un_ch; - if (!ch) - return 0; - return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_s_cflag); -} -static DEVICE_ATTR(cflag_info, 0600, dgrp_tty_cflag_show, NULL); - - -static ssize_t dgrp_tty_oflag_show(struct device *d, - struct device_attribute *attr, char *buf) -{ - struct ch_struct *ch; - struct un_struct *un; - - if (!d) - return 0; - un = (struct un_struct *) dev_get_drvdata(d); - if (!un) - return 0; - ch = un->un_ch; - if (!ch) - return 0; - return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_s_oflag); -} -static DEVICE_ATTR(oflag_info, 0600, dgrp_tty_oflag_show, NULL); - - -static ssize_t dgrp_tty_digi_flag_show(struct device *d, - struct device_attribute *attr, char *buf) -{ - struct ch_struct *ch; - struct un_struct *un; - - if (!d) - return 0; - un = (struct un_struct *) dev_get_drvdata(d); - if (!un) - return 0; - ch = un->un_ch; - if (!ch) - return 0; - return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_digi.digi_flags); -} -static DEVICE_ATTR(digi_flag_info, 0600, dgrp_tty_digi_flag_show, NULL); - - -static ssize_t dgrp_tty_rxcount_show(struct device *d, - struct device_attribute *attr, char *buf) -{ - struct ch_struct *ch; - struct un_struct *un; - - if (!d) - return 0; - un = (struct un_struct *) dev_get_drvdata(d); - if (!un) - return 0; - ch = un->un_ch; - if (!ch) - return 0; - return snprintf(buf, PAGE_SIZE, "%d\n", ch->ch_rxcount); -} -static DEVICE_ATTR(rxcount_info, 0600, dgrp_tty_rxcount_show, NULL); - - -static ssize_t dgrp_tty_txcount_show(struct device *d, - struct device_attribute *attr, char *buf) -{ - struct ch_struct *ch; - struct un_struct *un; - - if (!d) - return 0; - un = (struct un_struct *) dev_get_drvdata(d); - if (!un) - return 0; - ch = un->un_ch; - if (!ch) - return 0; - return snprintf(buf, PAGE_SIZE, "%d\n", ch->ch_txcount); -} -static DEVICE_ATTR(txcount_info, 0600, dgrp_tty_txcount_show, NULL); - - -static ssize_t dgrp_tty_name_show(struct device *d, - struct device_attribute *attr, char *buf) -{ - struct nd_struct *nd; - struct ch_struct *ch; - struct un_struct *un; - char name[10]; - - if (!d) - return 0; - un = (struct un_struct *) dev_get_drvdata(d); - if (!un) - return 0; - ch = un->un_ch; - if (!ch) - return 0; - nd = ch->ch_nd; - if (!nd) - return 0; - - ID_TO_CHAR(nd->nd_ID, name); - - return snprintf(buf, PAGE_SIZE, "%s%s%02d\n", - un->un_type == SERIAL_TYPE_XPRINT ? "pr" : "tty", - name, ch->ch_portnum); -} -static DEVICE_ATTR(custom_name, 0600, dgrp_tty_name_show, NULL); - - -static struct attribute *dgrp_sysfs_tty_entries[] = { - &dev_attr_state_info.attr, - &dev_attr_baud_info.attr, - &dev_attr_msignals_info.attr, - &dev_attr_iflag_info.attr, - &dev_attr_cflag_info.attr, - &dev_attr_oflag_info.attr, - &dev_attr_digi_flag_info.attr, - &dev_attr_rxcount_info.attr, - &dev_attr_txcount_info.attr, - &dev_attr_custom_name.attr, - NULL -}; - - -static struct attribute_group dgrp_tty_attribute_group = { - .name = NULL, - .attrs = dgrp_sysfs_tty_entries, -}; - - -void dgrp_create_tty_sysfs(struct un_struct *un, struct device *c) -{ - int ret; - - ret = sysfs_create_group(&c->kobj, &dgrp_tty_attribute_group); - if (ret) { - pr_alert("%s: failed to create sysfs tty device attributes.\n", - __func__); - sysfs_remove_group(&c->kobj, &dgrp_tty_attribute_group); - return; - } - - dev_set_drvdata(c, un); - -} - - -void dgrp_remove_tty_sysfs(struct device *c) -{ - sysfs_remove_group(&c->kobj, &dgrp_tty_attribute_group); -} diff --git a/trunk/drivers/staging/dgrp/dgrp_tty.c b/trunk/drivers/staging/dgrp/dgrp_tty.c deleted file mode 100644 index 7d7de873870c..000000000000 --- a/trunk/drivers/staging/dgrp/dgrp_tty.c +++ /dev/null @@ -1,3331 +0,0 @@ -/* - * - * Copyright 1999 Digi International (www.digi.com) - * Gene Olson - * James Puzzo - * Jeff Randall - * Scott Kilau - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the - * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR - * PURPOSE. See the GNU General Public License for more details. - * - */ - -/* - * - * Filename: - * - * dgrp_tty.c - * - * Description: - * - * This file implements the tty driver functionality for the - * RealPort driver software. - * - * Author: - * - * James A. Puzzo - * Ann-Marie Westgate - * - */ - -#include -#include -#include -#include - -#include "dgrp_common.h" - -#ifndef _POSIX_VDISABLE -#define _POSIX_VDISABLE ('\0') -#endif - -/* - * forward declarations - */ - -static void drp_param(struct ch_struct *); -static void dgrp_tty_close(struct tty_struct *, struct file *); - -/* ioctl helper functions */ -static int set_modem_info(struct ch_struct *, unsigned int, unsigned int *); -static int get_modem_info(struct ch_struct *, unsigned int *); -static void dgrp_set_custom_speed(struct ch_struct *, int); -static int dgrp_tty_digigetedelay(struct tty_struct *, int *); -static int dgrp_tty_digisetedelay(struct tty_struct *, int *); -static int dgrp_send_break(struct ch_struct *, int); - -static ushort tty_to_ch_flags(struct tty_struct *, char); -static tcflag_t ch_to_tty_flags(unsigned short, char); - -static void dgrp_tty_input_start(struct tty_struct *); -static void dgrp_tty_input_stop(struct tty_struct *); - -static void drp_wmove(struct ch_struct *, int, void*, int); - -static int dgrp_tty_open(struct tty_struct *, struct file *); -static void dgrp_tty_close(struct tty_struct *, struct file *); -static int dgrp_tty_write(struct tty_struct *, const unsigned char *, int); -static int dgrp_tty_write_room(struct tty_struct *); -static void dgrp_tty_flush_buffer(struct tty_struct *); -static int dgrp_tty_chars_in_buffer(struct tty_struct *); -static int dgrp_tty_ioctl(struct tty_struct *, unsigned int, unsigned long); -static void dgrp_tty_set_termios(struct tty_struct *, struct ktermios *); -static void dgrp_tty_stop(struct tty_struct *); -static void dgrp_tty_start(struct tty_struct *); -static void dgrp_tty_throttle(struct tty_struct *); -static void dgrp_tty_unthrottle(struct tty_struct *); -static void dgrp_tty_hangup(struct tty_struct *); -static int dgrp_tty_put_char(struct tty_struct *, unsigned char); -static int dgrp_tty_tiocmget(struct tty_struct *); -static int dgrp_tty_tiocmset(struct tty_struct *, unsigned int, unsigned int); -static int dgrp_tty_send_break(struct tty_struct *, int); -static void dgrp_tty_send_xchar(struct tty_struct *, char); - -/* - * tty defines - */ -#define SERIAL_TYPE_NORMAL 1 -#define SERIAL_TYPE_CALLOUT 2 -#define SERIAL_TYPE_XPRINT 3 - - -/* - * tty globals/statics - */ - - -#define PORTSERVER_DIVIDEND 1843200 - -/* - * Default transparent print information. - */ -static struct digi_struct digi_init = { - .digi_flags = DIGI_COOK, /* Flags */ - .digi_maxcps = 100, /* Max CPS */ - .digi_maxchar = 50, /* Max chars in print queue */ - .digi_bufsize = 100, /* Printer buffer size */ - .digi_onlen = 4, /* size of printer on string */ - .digi_offlen = 4, /* size of printer off string */ - .digi_onstr = "\033[5i", /* ANSI printer on string */ - .digi_offstr = "\033[4i", /* ANSI printer off string */ - .digi_term = "ansi" /* default terminal type */ -}; - -/* - * Define a local default termios struct. All ports will be created - * with this termios initially. - * - * This defines a raw port at 9600 baud, 8 data bits, no parity, - * 1 stop bit. - */ -static struct ktermios DefaultTermios = { - .c_iflag = (ICRNL | IXON), - .c_oflag = (OPOST | ONLCR), - .c_cflag = (B9600 | CS8 | CREAD | HUPCL | CLOCAL), - .c_lflag = (ISIG | ICANON | ECHO | ECHOE | ECHOK | ECHOCTL - | ECHOKE | IEXTEN), - .c_cc = INIT_C_CC, - .c_line = 0, -}; - -/* Define our tty operations struct */ -static const struct tty_operations dgrp_tty_ops = { - .open = dgrp_tty_open, - .close = dgrp_tty_close, - .write = dgrp_tty_write, - .write_room = dgrp_tty_write_room, - .flush_buffer = dgrp_tty_flush_buffer, - .chars_in_buffer = dgrp_tty_chars_in_buffer, - .flush_chars = NULL, - .ioctl = dgrp_tty_ioctl, - .set_termios = dgrp_tty_set_termios, - .stop = dgrp_tty_stop, - .start = dgrp_tty_start, - .throttle = dgrp_tty_throttle, - .unthrottle = dgrp_tty_unthrottle, - .hangup = dgrp_tty_hangup, - .put_char = dgrp_tty_put_char, - .tiocmget = dgrp_tty_tiocmget, - .tiocmset = dgrp_tty_tiocmset, - .break_ctl = dgrp_tty_send_break, - .send_xchar = dgrp_tty_send_xchar -}; - - -static int calc_baud_rate(struct un_struct *un) -{ - int i; - int brate; - - struct baud_rates { - unsigned int rate; - unsigned int cflag; - }; - - static struct baud_rates baud_rates[] = { - { 921600, B921600 }, - { 460800, B460800 }, - { 230400, B230400 }, - { 115200, B115200 }, - { 57600, B57600 }, - { 38400, B38400 }, - { 19200, B19200 }, - { 9600, B9600 }, - { 4800, B4800 }, - { 2400, B2400 }, - { 1200, B1200 }, - { 600, B600 }, - { 300, B300 }, - { 200, B200 }, - { 150, B150 }, - { 134, B134 }, - { 110, B110 }, - { 75, B75 }, - { 50, B50 }, - { 0, B9600 } - }; - - brate = C_BAUD(un->un_tty); - - for (i = 0; baud_rates[i].rate; i++) { - if (baud_rates[i].cflag == brate) - break; - } - - return baud_rates[i].rate; -} - -static int calc_fastbaud_rate(struct un_struct *un, struct ktermios *uts) -{ - int i; - int brate; - - ulong bauds[2][16] = { - { /* fastbaud*/ - 0, 57600, 76800, 115200, - 131657, 153600, 230400, 460800, - 921600, 1200, 1800, 2400, - 4800, 9600, 19200, 38400 }, - { /* fastbaud & CBAUDEX */ - 0, 57600, 115200, 230400, - 460800, 150, 200, 921600, - 600, 1200, 1800, 2400, - 4800, 9600, 19200, 38400 } - }; - - brate = C_BAUD(un->un_tty) & 0xff; - - i = (uts->c_cflag & CBAUDEX) ? 1 : 0; - - - if ((i >= 0) && (i < 2) && (brate >= 0) && (brate < 16)) - brate = bauds[i][brate]; - else - brate = 0; - - return brate; -} - -/** - * drp_param() -- send parameter values to be sent to the node - * @ch: channel structure of port to modify - * - * Interprets the tty and modem changes made by an application - * program (by examining the termios structures) and sets up - * parameter values to be sent to the node. - */ -static void drp_param(struct ch_struct *ch) -{ - struct nd_struct *nd; - struct un_struct *un; - int brate; - int mflow; - int xflag; - int iflag; - struct ktermios *tts, *pts, *uts; - - nd = ch->ch_nd; - - /* - * If the terminal device is open, use it to set up all tty - * modes and functions. Otherwise use the printer device. - */ - - if (ch->ch_tun.un_open_count) { - - un = &ch->ch_tun; - tts = &ch->ch_tun.un_tty->termios; - - /* - * If both devices are open, copy critical line - * parameters from the tty device to the printer, - * so that if the tty is closed, the printer will - * continue without disruption. - */ - - if (ch->ch_pun.un_open_count) { - - pts = &ch->ch_pun.un_tty->termios; - - pts->c_cflag ^= - (pts->c_cflag ^ tts->c_cflag) & - (CBAUD | CSIZE | CSTOPB | CREAD | PARENB | - PARODD | HUPCL | CLOCAL); - - pts->c_iflag ^= - (pts->c_iflag ^ tts->c_iflag) & - (IGNBRK | BRKINT | IGNPAR | PARMRK | INPCK | - ISTRIP | IXON | IXANY | IXOFF); - - pts->c_cc[VSTART] = tts->c_cc[VSTART]; - pts->c_cc[VSTOP] = tts->c_cc[VSTOP]; - } - } else if (ch->ch_pun.un_open_count == 0) { - pr_warn("%s - ch_pun.un_open_count shouldn't be 0\n", - __func__); - return; - } else { - un = &ch->ch_pun; - } - - uts = &un->un_tty->termios; - - /* - * Determine if FAST writes can be performed. - */ - - if ((ch->ch_digi.digi_flags & DIGI_COOK) != 0 && - (ch->ch_tun.un_open_count != 0) && - !((un->un_tty)->ldisc->ops->flags & LDISC_FLAG_DEFINED) && - !(L_XCASE(un->un_tty))) { - ch->ch_flag |= CH_FAST_WRITE; - } else { - ch->ch_flag &= ~CH_FAST_WRITE; - } - - /* - * If FAST writes can be performed, and OPOST is on in the - * terminal device, do OPOST handling in the server. - */ - - if ((ch->ch_flag & CH_FAST_WRITE) && - O_OPOST(un->un_tty) != 0) { - int oflag = tty_to_ch_flags(un->un_tty, 'o'); - - /* add to ch_ocook any processing flags set in the termio */ - ch->ch_ocook |= oflag & (OF_OLCUC | - OF_ONLCR | - OF_OCRNL | - OF_ONLRET | - OF_TABDLY); - - /* - * the hpux driver clears any flags set in ch_ocook - * from the termios oflag. It is STILL reported though - * by a TCGETA - */ - - oflag = ch_to_tty_flags(ch->ch_ocook, 'o'); - uts->c_oflag &= ~oflag; - - } else { - /* clear the ch->ch_ocook flag */ - int oflag = ch_to_tty_flags(ch->ch_ocook, 'o'); - uts->c_oflag |= oflag; - ch->ch_ocook = 0; - } - - ch->ch_oflag = ch->ch_ocook; - - - ch->ch_flag &= ~CH_FAST_READ; - - /* - * Generate channel flags - */ - - if (C_BAUD(un->un_tty) == B0) { - if (!(ch->ch_flag & CH_BAUD0)) { - /* TODO : the HPUX driver flushes line */ - /* TODO : discipline, I assume I don't have to */ - - ch->ch_tout = ch->ch_tin; - ch->ch_rout = ch->ch_rin; - - ch->ch_break_time = 0; - - ch->ch_send |= RR_TX_FLUSH | RR_RX_FLUSH; - - ch->ch_mout &= ~(DM_DTR | DM_RTS); - - ch->ch_flag |= CH_BAUD0; - } - } else if (ch->ch_custom_speed) { - ch->ch_brate = PORTSERVER_DIVIDEND / ch->ch_custom_speed ; - - if (ch->ch_flag & CH_BAUD0) { - ch->ch_mout |= DM_DTR | DM_RTS; - - ch->ch_flag &= ~CH_BAUD0; - } - } else { - /* - * Baud rate mapping. - * - * If FASTBAUD isn't on, we can scan the new baud rate list - * as required. - * - * However, if FASTBAUD is on, we must go to the old - * baud rate mapping that existed many many moons ago, - * for compatibility reasons. - */ - - if (!(ch->ch_digi.digi_flags & DIGI_FAST)) - brate = calc_baud_rate(un); - else - brate = calc_fastbaud_rate(un, uts); - - if (brate == 0) - brate = 9600; - - ch->ch_brate = PORTSERVER_DIVIDEND / brate; - - if (ch->ch_flag & CH_BAUD0) { - ch->ch_mout |= DM_DTR | DM_RTS; - - ch->ch_flag &= ~CH_BAUD0; - } - } - - /* - * Generate channel cflags from the termio. - */ - - ch->ch_cflag = tty_to_ch_flags(un->un_tty, 'c'); - - /* - * Generate channel iflags from the termio. - */ - - iflag = (int) tty_to_ch_flags(un->un_tty, 'i'); - - if (START_CHAR(un->un_tty) == _POSIX_VDISABLE || - STOP_CHAR(un->un_tty) == _POSIX_VDISABLE) { - iflag &= ~(IF_IXON | IF_IXANY | IF_IXOFF); - } - - ch->ch_iflag = iflag; - - /* - * Generate flow control characters - */ - - /* - * From the POSIX.1 spec (7.1.2.6): "If {_POSIX_VDISABLE} - * is defined for the terminal device file, and the value - * of one of the changable special control characters (see - * 7.1.1.9) is {_POSIX_VDISABLE}, that function shall be - * disabled, that is, no input data shall be recognized as - * the disabled special character." - * - * OK, so we don't ever assign S/DXB XON or XOFF to _POSIX_VDISABLE. - */ - - if (uts->c_cc[VSTART] != _POSIX_VDISABLE) - ch->ch_xon = uts->c_cc[VSTART]; - if (uts->c_cc[VSTOP] != _POSIX_VDISABLE) - ch->ch_xoff = uts->c_cc[VSTOP]; - - ch->ch_lnext = (uts->c_cc[VLNEXT] == _POSIX_VDISABLE ? 0 : - uts->c_cc[VLNEXT]); - - /* - * Also, if either c_cc[START] or c_cc[STOP] is set to - * _POSIX_VDISABLE, we can't really do software flow - * control--in either direction--so we turn it off as - * far as S/DXB is concerned. In essence, if you disable - * one, you disable the other too. - */ - if ((uts->c_cc[VSTART] == _POSIX_VDISABLE) || - (uts->c_cc[VSTOP] == _POSIX_VDISABLE)) - ch->ch_iflag &= ~(IF_IXOFF | IF_IXON); - - /* - * Update xflags. - */ - - xflag = 0; - - if (ch->ch_digi.digi_flags & DIGI_AIXON) - xflag = XF_XIXON; - - if ((ch->ch_xxon == _POSIX_VDISABLE) || - (ch->ch_xxoff == _POSIX_VDISABLE)) - xflag &= ~XF_XIXON; - - ch->ch_xflag = xflag; - - - /* - * Figure effective DCD value. - */ - - if (C_CLOCAL(un->un_tty)) - ch->ch_flag |= CH_CLOCAL; - else - ch->ch_flag &= ~CH_CLOCAL; - - /* - * Check modem signals - */ - - dgrp_carrier(ch); - - /* - * Get hardware handshake value. - */ - - mflow = 0; - - if (C_CRTSCTS(un->un_tty)) - mflow |= (DM_RTS | DM_CTS); - - if (ch->ch_digi.digi_flags & RTSPACE) - mflow |= DM_RTS; - - if (ch->ch_digi.digi_flags & DTRPACE) - mflow |= DM_DTR; - - if (ch->ch_digi.digi_flags & CTSPACE) - mflow |= DM_CTS; - - if (ch->ch_digi.digi_flags & DSRPACE) - mflow |= DM_DSR; - - if (ch->ch_digi.digi_flags & DCDPACE) - mflow |= DM_CD; - - if (ch->ch_digi.digi_flags & DIGI_RTS_TOGGLE) - mflow |= DM_RTS_TOGGLE; - - ch->ch_mflow = mflow; - - /* - * Send the changes to the server. - */ - - ch->ch_flag |= CH_PARAM; - (ch->ch_nd)->nd_tx_work = 1; - - if (waitqueue_active(&ch->ch_flag_wait)) - wake_up_interruptible(&ch->ch_flag_wait); -} - -/* - * This function is just used as a callback for timeouts - * waiting on the ch_sleep flag. - */ -static void wake_up_drp_sleep_timer(unsigned long ptr) -{ - struct ch_struct *ch = (struct ch_struct *) ptr; - if (ch) - wake_up(&ch->ch_sleep); -} - - -/* - * Set up our own sleep that can't be cancelled - * until our timeout occurs. - */ -static void drp_my_sleep(struct ch_struct *ch) -{ - struct timer_list drp_wakeup_timer; - DECLARE_WAITQUEUE(wait, current); - - /* - * First make sure we're ready to receive the wakeup. - */ - - add_wait_queue(&ch->ch_sleep, &wait); - current->state = TASK_UNINTERRUPTIBLE; - - /* - * Since we are uninterruptible, set a timer to - * unset the uninterruptable state in 1 second. - */ - - init_timer(&drp_wakeup_timer); - drp_wakeup_timer.function = wake_up_drp_sleep_timer; - drp_wakeup_timer.data = (unsigned long) ch; - drp_wakeup_timer.expires = jiffies + (1 * HZ); - add_timer(&drp_wakeup_timer); - - schedule(); - - del_timer(&drp_wakeup_timer); - - remove_wait_queue(&ch->ch_sleep, &wait); -} - -/* - * dgrp_tty_open() - * - * returns: - * -EBUSY - this is a callout device and the normal device is active - * - there is an error in opening the tty - * -ENODEV - the channel does not exist - * -EAGAIN - we are in the middle of hanging up or closing - * - IMMEDIATE_OPEN fails - * -ENXIO or -EAGAIN - * - if the port is outside physical range - * -EINTR - the open is interrupted - * - */ -static int dgrp_tty_open(struct tty_struct *tty, struct file *file) -{ - int retval = 0; - struct nd_struct *nd; - struct ch_struct *ch; - struct un_struct *un; - int port; - int delay_error; - int otype; - int unf; - int wait_carrier; - int category; - int counts_were_incremented = 0; - ulong lock_flags; - DECLARE_WAITQUEUE(wait, current); - - /* - * Do some initial checks to see if the node and port exist - */ - - nd = nd_struct_get(MAJOR(tty_devnum(tty))); - port = PORT_NUM(MINOR(tty_devnum(tty))); - category = OPEN_CATEGORY(MINOR(tty_devnum(tty))); - - if (!nd) - return -ENODEV; - - if (port >= CHAN_MAX) - return -ENODEV; - - /* - * The channel exists. - */ - - ch = nd->nd_chan + port; - - un = IS_PRINT(MINOR(tty_devnum(tty))) ? &ch->ch_pun : &ch->ch_tun; - un->un_tty = tty; - tty->driver_data = un; - - /* - * If we are in the middle of hanging up, - * then return an error - */ - if (tty_hung_up_p(file)) { - retval = ((un->un_flag & UN_HUP_NOTIFY) ? - -EAGAIN : -ERESTARTSYS); - goto done; - } - - /* - * If the port is in the middle of closing, then block - * until it is done, then try again. - */ - retval = wait_event_interruptible(un->un_close_wait, - ((un->un_flag & UN_CLOSING) == 0)); - - if (retval) - goto done; - - /* - * If the port is in the middle of a reopen after a network disconnect, - * wait until it is done, then try again. - */ - retval = wait_event_interruptible(ch->ch_flag_wait, - ((ch->ch_flag & CH_PORT_GONE) == 0)); - - if (retval) - goto done; - - /* - * If this is a callout device, then just make sure the normal - * device isn't being used. - */ - - if (tty->driver->subtype == SERIAL_TYPE_CALLOUT) { - if (un->un_flag & UN_NORMAL_ACTIVE) { - retval = -EBUSY; - goto done; - } else { - un->un_flag |= UN_CALLOUT_ACTIVE; - } - } - - /* - * Loop waiting until the open can be successfully completed. - */ - - spin_lock_irqsave(&nd->nd_lock, lock_flags); - - nd->nd_tx_work = 1; - - for (;;) { - wait_carrier = 0; - - /* - * Determine the open type from the flags provided. - */ - - /* - * If the port is not enabled, then exit - */ - if (test_bit(TTY_IO_ERROR, &tty->flags)) { - /* there was an error in opening the tty */ - if (un->un_flag & UN_CALLOUT_ACTIVE) - retval = -EBUSY; - else - un->un_flag |= UN_NORMAL_ACTIVE; - goto unlock; - } - - if (file->f_flags & O_NONBLOCK) { - - /* - * if the O_NONBLOCK is set, errors on read and write - * must return -EAGAIN immediately and NOT sleep - * on the waitqs. - */ - otype = OTYPE_IMMEDIATE; - delay_error = -EAGAIN; - - } else if (!OPEN_WAIT_AVAIL(category) || - (file->f_flags & O_NDELAY) != 0) { - otype = OTYPE_IMMEDIATE; - delay_error = -EBUSY; - - } else if (!OPEN_WAIT_CARRIER(category) || - ((ch->ch_digi.digi_flags & DIGI_FORCEDCD) != 0) || - C_CLOCAL(tty)) { - otype = OTYPE_PERSISTENT; - delay_error = 0; - - } else { - otype = OTYPE_INCOMING; - delay_error = 0; - } - - /* - * Handle port currently outside physical port range. - */ - - if (port >= nd->nd_chan_count) { - if (otype == OTYPE_IMMEDIATE) { - retval = (nd->nd_state == NS_READY) ? - -ENXIO : -EAGAIN; - goto unlock; - } - } - - /* - * Handle port not currently open. - */ - - else if (ch->ch_open_count == 0) { - /* - * Return an error when an Incoming Open - * response indicates the port is busy. - */ - - if (ch->ch_open_error != 0 && otype == ch->ch_otype) { - retval = (ch->ch_open_error <= 2) ? - delay_error : -ENXIO ; - goto unlock; - } - - /* - * Fail any new Immediate open if we do not have - * a normal connection to the server. - */ - - if (nd->nd_state != NS_READY && - otype == OTYPE_IMMEDIATE) { - retval = -EAGAIN; - goto unlock; - } - - /* - * If a Realport open of the correct type has - * succeeded, complete the open. - */ - - if (ch->ch_state == CS_READY && ch->ch_otype == otype) - break; - } - - /* - * Handle port already open and active as a device - * of same category. - */ - - else if ((ch->ch_category == category) || - IS_PRINT(MINOR(tty_devnum(tty)))) { - /* - * Fail if opening the device now would - * violate exclusive use. - */ - unf = ch->ch_tun.un_flag | ch->ch_pun.un_flag; - - if ((file->f_flags & O_EXCL) || (unf & UN_EXCL)) { - retval = -EBUSY; - goto unlock; - } - - /* - * If the open device is in the hangup state, all - * system calls fail except close(). - */ - - /* TODO : check on hangup_p calls */ - - if (ch->ch_flag & CH_HANGUP) { - retval = -ENXIO; - goto unlock; - } - - /* - * If the port is ready, and carrier is ignored - * or present, then complete the open. - */ - - if (ch->ch_state == CS_READY && - (otype != OTYPE_INCOMING || - ch->ch_flag & CH_VIRT_CD)) - break; - - wait_carrier = 1; - } - - /* - * Handle port active with a different category device. - */ - - else { - if (otype == OTYPE_IMMEDIATE) { - retval = delay_error; - goto unlock; - } - } - - /* - * Wait until conditions change, then take another - * try at the open. - */ - - ch->ch_wait_count[otype]++; - - if (wait_carrier) - ch->ch_wait_carrier++; - - /* - * Prepare the task to accept the wakeup, then - * release our locks and release control. - */ - - add_wait_queue(&ch->ch_flag_wait, &wait); - current->state = TASK_INTERRUPTIBLE; - - spin_unlock_irqrestore(&nd->nd_lock, lock_flags); - - /* - * Give up control, we'll come back if we're - * interrupted or are woken up. - */ - schedule(); - remove_wait_queue(&ch->ch_flag_wait, &wait); - - spin_lock_irqsave(&nd->nd_lock, lock_flags); - - current->state = TASK_RUNNING; - - ch->ch_wait_count[otype]--; - - if (wait_carrier) - ch->ch_wait_carrier--; - - nd->nd_tx_work = 1; - - if (signal_pending(current)) { - retval = -EINTR; - goto unlock; - } - } /* end for(;;) */ - - /* - * The open has succeeded. No turning back. - */ - counts_were_incremented = 1; - un->un_open_count++; - ch->ch_open_count++; - - /* - * Initialize the channel, if it's not already open. - */ - - if (ch->ch_open_count == 1) { - ch->ch_flag = 0; - ch->ch_inwait = 0; - ch->ch_category = category; - ch->ch_pscan_state = 0; - - /* TODO : find out what PS-1 bug Gene was referring to */ - /* TODO : in the following comment. */ - - ch->ch_send = RR_TX_START | RR_RX_START; /* PS-1 bug */ - - if (C_CLOCAL(tty) || - ch->ch_s_mlast & DM_CD || - ch->ch_digi.digi_flags & DIGI_FORCEDCD) - ch->ch_flag |= CH_VIRT_CD; - else if (OPEN_FORCES_CARRIER(category)) - ch->ch_flag |= CH_VIRT_CD; - - } - - /* - * Initialize the unit, if it is not already open. - */ - - if (un->un_open_count == 1) { - /* - * Since all terminal options are always sticky in Linux, - * we don't need the UN_STICKY flag to be handled specially. - */ - /* clears all the digi flags, leaves serial flags */ - un->un_flag &= ~UN_DIGI_MASK; - - if (file->f_flags & O_EXCL) - un->un_flag |= UN_EXCL; - - /* TODO : include "session" and "pgrp" */ - - /* - * In Linux, all terminal parameters are intended to be sticky. - * as a result, we "remove" the code which once reset the ports - * to sane values. - */ - - drp_param(ch); - - } - - un->un_flag |= UN_INITIALIZED; - - retval = 0; - -unlock: - - spin_unlock_irqrestore(&nd->nd_lock, lock_flags); - -done: - /* - * Linux does a close for every open, even failed ones! - */ - if (!counts_were_incremented) { - un->un_open_count++; - ch->ch_open_count++; - } - - if (retval) - dev_err(tty->dev, "tty open bad return (%i)\n", retval); - - return retval; -} - - - - -/* - * dgrp_tty_close() -- close function for tty_operations - */ -static void dgrp_tty_close(struct tty_struct *tty, struct file *file) -{ - struct ch_struct *ch; - struct un_struct *un; - struct nd_struct *nd; - int tpos; - int port; - int err = 0; - int s = 0; - ulong waketime; - ulong lock_flags; - int sent_printer_offstr = 0; - - port = PORT_NUM(MINOR(tty_devnum(tty))); - - un = tty->driver_data; - - if (!un) - return; - - ch = un->un_ch; - - if (!ch) - return; - - nd = ch->ch_nd; - - if (!nd) - return; - - spin_lock_irqsave(&nd->nd_lock, lock_flags); - - - /* Used to be on channel basis, now we check on a unit basis. */ - if (un->un_open_count != 1) - goto unlock; - - /* - * OK, its the last close on the unit - */ - un->un_flag |= UN_CLOSING; - - /* - * Notify the discipline to only process XON/XOFF characters. - */ - tty->closing = 1; - - /* - * Wait for output to drain only if this is - * the last close against the channel - */ - - if (ch->ch_open_count == 1) { - /* - * If its the print device, we need to ensure at all costs that - * the offstr will fit. If it won't, flush our tbuf. - */ - if (IS_PRINT(MINOR(tty_devnum(tty))) && - (((ch->ch_tout - ch->ch_tin - 1) & TBUF_MASK) < - ch->ch_digi.digi_offlen)) - ch->ch_tin = ch->ch_tout; - - /* - * Turn off the printer. Don't bother checking to see if its - * IS_PRINT... Since this is the last close the flag is going - * to be cleared, so we MUST make sure the offstr gets inserted - * into tbuf. - */ - - if ((ch->ch_flag & CH_PRON) != 0) { - drp_wmove(ch, 0, ch->ch_digi.digi_offstr, - ch->ch_digi.digi_offlen); - ch->ch_flag &= ~CH_PRON; - sent_printer_offstr = 1; - } - } - - /* - * Wait until either the output queue has drained, or we see - * absolutely no progress for 15 seconds. - */ - - tpos = ch->ch_s_tpos; - - waketime = jiffies + 15 * HZ; - - for (;;) { - - /* - * Make sure the port still exists. - */ - - if (port >= nd->nd_chan_count) { - err = 1; - break; - } - - if (signal_pending(current)) { - err = 1; - break; - } - - /* - * If the port is idle (not opened on the server), we have - * no way of draining/flushing/closing the port on that server. - * So break out of loop. - */ - if (ch->ch_state == CS_IDLE) - break; - - nd->nd_tx_work = 1; - - /* - * Exit if the queues for this unit are empty, - * and either the other unit is still open or all - * data has drained. - */ - - if ((un->un_tty)->ops->chars_in_buffer ? - ((un->un_tty)->ops->chars_in_buffer)(un->un_tty) == 0 : 1) { - - /* - * We don't need to wait for a buffer to drain - * if the other unit is open. - */ - - if (ch->ch_open_count != un->un_open_count) - break; - - /* - * The wait is complete when all queues are - * drained, and any break in progress is complete. - */ - - if (ch->ch_tin == ch->ch_tout && - ch->ch_s_tin == ch->ch_s_tpos && - (ch->ch_send & RR_TX_BREAK) == 0) { - break; - } - } - - /* - * Flush TX data and exit the wait if NDELAY is set, - * or this is not a DIGI printer, and the close timeout - * expires. - */ - - if ((file->f_flags & (O_NDELAY | O_NONBLOCK)) || - ((long)(jiffies - waketime) >= 0 && - (ch->ch_digi.digi_flags & DIGI_PRINTER) == 0)) { - - /* - * If we sent the printer off string, we cannot - * flush our internal buffers, or we might lose - * the offstr. - */ - if (!sent_printer_offstr) - dgrp_tty_flush_buffer(tty); - - tty_ldisc_flush(tty); - break; - } - - /* - * Otherwise take a short nap. - */ - - ch->ch_flag |= CH_DRAIN; - - spin_unlock_irqrestore(&nd->nd_lock, lock_flags); - - schedule_timeout_interruptible(1); - s = signal_pending(current); - - spin_lock_irqsave(&nd->nd_lock, lock_flags); - - if (s) { - /* - * If we had sent the printer off string, we now have - * some problems. - * - * The system won't let us sleep since we got an error - * back from sleep, presumably because the user did - * a ctrl-c... - * But we need to ensure that the offstr gets sent! - * Thus, we have to do something else besides sleeping. - * The plan: - * 1) Make this task uninterruptable. - * 2) Set up a timer to go off in 1 sec. - * 3) Act as tho we just got out of the sleep above. - * - * Thankfully, in the real world, this just - * never happens. - */ - - if (sent_printer_offstr) { - spin_unlock_irqrestore(&nd->nd_lock, - lock_flags); - drp_my_sleep(ch); - spin_lock_irqsave(&nd->nd_lock, lock_flags); - } else { - err = 1; - break; - } - } - - /* - * Restart the wait if any progress is seen. - */ - - if (ch->ch_s_tpos != tpos) { - tpos = ch->ch_s_tpos; - - /* TODO: this gives us timeout problems with nist ?? */ - waketime = jiffies + 15 * HZ; - } - } - - /* - * Close the line discipline - */ - - /* this is done in tty_io.c */ - /* if ((un->un_tty)->ldisc.close) - * ((un->un_tty)->ldisc.close)(un->un_tty); - */ - - /* don't do this here */ - /* un->un_flag = 0; */ - - /* - * Flush the receive buffer on terminal unit close only. - */ - - if (!IS_PRINT(MINOR(tty_devnum(tty)))) - ch->ch_rout = ch->ch_rin; - - - /* - * Don't permit the close to happen until we get any pending - * sync request responses. - * There could be other ports depending upon the response as well. - * - * Also, don't permit the close to happen until any parameter - * changes have been sent out from the state machine as well. - * This is required because of a ditty -a race with -HUPCL - * We MUST make sure all channel parameters have been sent to the - * Portserver before sending a close. - */ - - if ((err != 1) && (ch->ch_state != CS_IDLE)) { - spin_unlock_irqrestore(&nd->nd_lock, lock_flags); - s = wait_event_interruptible(ch->ch_flag_wait, - ((ch->ch_flag & (CH_WAITING_SYNC | CH_PARAM)) == 0)); - spin_lock_irqsave(&nd->nd_lock, lock_flags); - } - - /* - * Cleanup the channel if last unit open. - */ - - if (ch->ch_open_count == 1) { - ch->ch_flag = 0; - ch->ch_category = 0; - ch->ch_send = 0; - ch->ch_expect = 0; - ch->ch_tout = ch->ch_tin; - /* (un->un_tty)->device = 0; */ - - if (ch->ch_state == CS_READY) - ch->ch_state = CS_SEND_CLOSE; - } - - /* - * Send the changes to the server - */ - if (ch->ch_state != CS_IDLE) { - ch->ch_flag |= CH_PARAM; - wake_up_interruptible(&ch->ch_flag_wait); - } - - nd->nd_tx_work = 1; - nd->nd_tx_ready = 1; - -unlock: - tty->closing = 0; - - if (ch->ch_open_count <= 0) - dev_info(tty->dev, - "%s - unexpected value for ch->ch_open_count: %i\n", - __func__, ch->ch_open_count); - else - ch->ch_open_count--; - - if (un->un_open_count <= 0) - dev_info(tty->dev, - "%s - unexpected value for un->un_open_count: %i\n", - __func__, un->un_open_count); - else - un->un_open_count--; - - un->un_flag &= ~(UN_NORMAL_ACTIVE | UN_CALLOUT_ACTIVE | UN_CLOSING); - if (waitqueue_active(&un->un_close_wait)) - wake_up_interruptible(&un->un_close_wait); - - spin_unlock_irqrestore(&nd->nd_lock, lock_flags); - - return; - -} - -static void drp_wmove(struct ch_struct *ch, int from_user, void *buf, int count) -{ - int n; - int ret = 0; - - ch->ch_nd->nd_tx_work = 1; - - n = TBUF_MAX - ch->ch_tin; - - if (count >= n) { - if (from_user) - ret = copy_from_user(ch->ch_tbuf + ch->ch_tin, - (void __user *) buf, n); - else - memcpy(ch->ch_tbuf + ch->ch_tin, buf, n); - - buf = (char *) buf + n; - count -= n; - ch->ch_tin = 0; - } - - if (from_user) - ret = copy_from_user(ch->ch_tbuf + ch->ch_tin, - (void __user *) buf, count); - else - memcpy(ch->ch_tbuf + ch->ch_tin, buf, count); - - ch->ch_tin += count; -} - - -static int dgrp_calculate_txprint_bounds(struct ch_struct *ch, int space, - int *un_flag) -{ - clock_t tt; - clock_t mt; - unsigned short tmax = 0; - - /* - * If the terminal device is busy, reschedule when - * the terminal device becomes idle. - */ - - if (ch->ch_tun.un_open_count != 0 && - ch->ch_tun.un_tty->ops->chars_in_buffer && - ((ch->ch_tun.un_tty->ops->chars_in_buffer)(ch->ch_tun.un_tty) != 0)) { - *un_flag = UN_PWAIT; - return 0; - } - - /* - * Assure that whenever there is printer data in the output - * buffer, there always remains enough space after it to - * turn the printer off. - */ - space -= ch->ch_digi.digi_offlen; - - if (space <= 0) { - *un_flag = UN_EMPTY; - return 0; - } - - /* - * We measure printer CPS speed by incrementing - * ch_cpstime by (HZ / digi_maxcps) for every - * character we output, restricting output so - * that ch_cpstime never exceeds lbolt. - * - * However if output has not been done for some - * time, lbolt will grow to very much larger than - * ch_cpstime, which would allow essentially - * unlimited amounts of output until ch_cpstime - * finally caught up. To avoid this, we adjust - * cps_time when necessary so the difference - * between lbolt and ch_cpstime never results - * in sending more than digi_bufsize characters. - * - * This nicely models a printer with an internal - * buffer of digi_bufsize characters. - * - * Get the time between lbolt and ch->ch_cpstime; - */ - - tt = jiffies - ch->ch_cpstime; - - /* - * Compute the time required to send digi_bufsize - * characters. - */ - - mt = HZ * ch->ch_digi.digi_bufsize / ch->ch_digi.digi_maxcps; - - /* - * Compute the number of characters that can be sent - * without violating the time constraint. If the - * direct calculation of this number is bigger than - * digi_bufsize, limit the number to digi_bufsize, - * and adjust cpstime to match. - */ - - if ((clock_t)(tt + HZ) > (clock_t)(mt + HZ)) { - tmax = ch->ch_digi.digi_bufsize; - ch->ch_cpstime = jiffies - mt; - } else { - tmax = ch->ch_digi.digi_maxcps * tt / HZ; - } - - /* - * If the time constraint now binds, limit the transmit - * count accordingly, and tentatively arrange to be - * rescheduled based on time. - */ - - if (tmax < space) { - *un_flag = UN_TIME; - space = tmax; - } - - /* - * Compute the total number of characters we can - * output before the total number of characters known - * to be in the output queue exceeds digi_maxchar. - */ - - tmax = (ch->ch_digi.digi_maxchar - - ((ch->ch_tin - ch->ch_tout) & TBUF_MASK) - - ((ch->ch_s_tin - ch->ch_s_tpos) & 0xffff)); - - - /* - * If the digi_maxchar constraint now holds, limit - * the transmit count accordingly, and arrange to - * be rescheduled when the queue becomes empty. - */ - - if (space > tmax) { - *un_flag = UN_EMPTY; - space = tmax; - } - - if (space <= 0) - *un_flag |= UN_EMPTY; - - return space; -} - - -static int dgrp_tty_write(struct tty_struct *tty, - const unsigned char *buf, - int count) -{ - struct nd_struct *nd; - struct un_struct *un; - struct ch_struct *ch; - int space; - int n; - int t; - int sendcount; - int un_flag; - ulong lock_flags; - - if (tty == NULL) - return 0; - - un = tty->driver_data; - if (!un) - return 0; - - ch = un->un_ch; - if (!ch) - return 0; - - nd = ch->ch_nd; - if (!nd) - return 0; - - /* - * Ignore the request if the channel is not ready. - */ - if (ch->ch_state != CS_READY) - return 0; - - spin_lock_irqsave(&dgrp_poll_data.poll_lock, lock_flags); - - /* - * Ignore the request if output is blocked. - */ - if ((un->un_flag & (UN_EMPTY | UN_LOW | UN_TIME | UN_PWAIT)) != 0) { - count = 0; - goto out; - } - - /* - * Also ignore the request if DPA has this port open, - * and is flow controlled on reading more data. - */ - if (nd->nd_dpa_debug && nd->nd_dpa_flag & DPA_WAIT_SPACE && - nd->nd_dpa_port == MINOR(tty_devnum(ch->ch_tun.un_tty))) { - count = 0; - goto out; - } - - /* - * Limit amount we will write to the amount of space - * available in the channel buffer. - */ - sendcount = 0; - - space = (ch->ch_tout - ch->ch_tin - 1) & TBUF_MASK; - - /* - * Handle the printer device. - */ - - un_flag = UN_LOW; - - if (IS_PRINT(MINOR(tty_devnum(tty)))) { - clock_t tt; - clock_t mt; - unsigned short tmax = 0; - - /* - * If the terminal device is busy, reschedule when - * the terminal device becomes idle. - */ - - if (ch->ch_tun.un_open_count != 0 && - ((ch->ch_tun.un_tty->ops->chars_in_buffer)(ch->ch_tun.un_tty) != 0)) { - un->un_flag |= UN_PWAIT; - count = 0; - goto out; - } - - /* - * Assure that whenever there is printer data in the output - * buffer, there always remains enough space after it to - * turn the printer off. - */ - space -= ch->ch_digi.digi_offlen; - - /* - * Output the printer on string. - */ - - if ((ch->ch_flag & CH_PRON) == 0) { - space -= ch->ch_digi.digi_onlen; - - if (space < 0) { - un->un_flag |= UN_EMPTY; - (ch->ch_nd)->nd_tx_work = 1; - count = 0; - goto out; - } - - drp_wmove(ch, 0, ch->ch_digi.digi_onstr, - ch->ch_digi.digi_onlen); - - ch->ch_flag |= CH_PRON; - } - - /* - * We measure printer CPS speed by incrementing - * ch_cpstime by (HZ / digi_maxcps) for every - * character we output, restricting output so - * that ch_cpstime never exceeds lbolt. - * - * However if output has not been done for some - * time, lbolt will grow to very much larger than - * ch_cpstime, which would allow essentially - * unlimited amounts of output until ch_cpstime - * finally caught up. To avoid this, we adjust - * cps_time when necessary so the difference - * between lbolt and ch_cpstime never results - * in sending more than digi_bufsize characters. - * - * This nicely models a printer with an internal - * buffer of digi_bufsize characters. - * - * Get the time between lbolt and ch->ch_cpstime; - */ - - tt = jiffies - ch->ch_cpstime; - - /* - * Compute the time required to send digi_bufsize - * characters. - */ - - mt = HZ * ch->ch_digi.digi_bufsize / ch->ch_digi.digi_maxcps; - - /* - * Compute the number of characters that can be sent - * without violating the time constraint. If the - * direct calculation of this number is bigger than - * digi_bufsize, limit the number to digi_bufsize, - * and adjust cpstime to match. - */ - - if ((clock_t)(tt + HZ) > (clock_t)(mt + HZ)) { - tmax = ch->ch_digi.digi_bufsize; - ch->ch_cpstime = jiffies - mt; - } else { - tmax = ch->ch_digi.digi_maxcps * tt / HZ; - } - - /* - * If the time constraint now binds, limit the transmit - * count accordingly, and tentatively arrange to be - * rescheduled based on time. - */ - - if (tmax < space) { - space = tmax; - un_flag = UN_TIME; - } - - /* - * Compute the total number of characters we can - * output before the total number of characters known - * to be in the output queue exceeds digi_maxchar. - */ - - tmax = (ch->ch_digi.digi_maxchar - - ((ch->ch_tin - ch->ch_tout) & TBUF_MASK) - - ((ch->ch_s_tin - ch->ch_s_tpos) & 0xffff)); - - - /* - * If the digi_maxchar constraint now holds, limit - * the transmit count accordingly, and arrange to - * be rescheduled when the queue becomes empty. - */ - - if (space > tmax) { - space = tmax; - un_flag = UN_EMPTY; - } - - } - /* - * Handle the terminal device. - */ - else { - - /* - * If the printer device is on, turn it off. - */ - - if ((ch->ch_flag & CH_PRON) != 0) { - - space -= ch->ch_digi.digi_offlen; - - drp_wmove(ch, 0, ch->ch_digi.digi_offstr, - ch->ch_digi.digi_offlen); - - ch->ch_flag &= ~CH_PRON; - } - } - - /* - * If space is 0 and its because the ch->tbuf - * is full, then Linux will handle a callback when queue - * space becomes available. - * tty_write returns count = 0 - */ - - if (space <= 0) { - /* the linux tty_io.c handles this if we return 0 */ - /* if (fp->flags & O_NONBLOCK) return -EAGAIN; */ - - un->un_flag |= UN_EMPTY; - (ch->ch_nd)->nd_tx_work = 1; - count = 0; - goto out; - } - - count = min(count, space); - - if (count > 0) { - - un->un_tbusy++; - - /* - * Copy the buffer contents to the ch_tbuf - * being careful to wrap around the circular queue - */ - - t = TBUF_MAX - ch->ch_tin; - n = count; - - if (n >= t) { - memcpy(ch->ch_tbuf + ch->ch_tin, buf, t); - if (nd->nd_dpa_debug && nd->nd_dpa_port == PORT_NUM(MINOR(tty_devnum(un->un_tty)))) - dgrp_dpa_data(nd, 0, (char *) buf, t); - buf += t; - n -= t; - ch->ch_tin = 0; - sendcount += n; - } - - memcpy(ch->ch_tbuf + ch->ch_tin, buf, n); - if (nd->nd_dpa_debug && nd->nd_dpa_port == PORT_NUM(MINOR(tty_devnum(un->un_tty)))) - dgrp_dpa_data(nd, 0, (char *) buf, n); - buf += n; - ch->ch_tin += n; - sendcount += n; - - un->un_tbusy--; - (ch->ch_nd)->nd_tx_work = 1; - if (ch->ch_edelay != DGRP_RTIME) { - (ch->ch_nd)->nd_tx_ready = 1; - wake_up_interruptible(&nd->nd_tx_waitq); - } - } - - ch->ch_txcount += count; - - if (IS_PRINT(MINOR(tty_devnum(tty)))) { - - /* - * Adjust ch_cpstime to account - * for the characters just output. - */ - - if (sendcount > 0) { - int cc = HZ * sendcount + ch->ch_cpsrem; - - ch->ch_cpstime += cc / ch->ch_digi.digi_maxcps; - ch->ch_cpsrem = cc % ch->ch_digi.digi_maxcps; - } - - /* - * If we are now waiting on time, schedule ourself - * back when we'll be able to send a block of - * digi_maxchar characters. - */ - - if ((un_flag & UN_TIME) != 0) { - ch->ch_waketime = (ch->ch_cpstime + - (ch->ch_digi.digi_maxchar * HZ / - ch->ch_digi.digi_maxcps)); - } - } - - /* - * If the printer unit is waiting for completion - * of terminal output, get him going again. - */ - - if ((ch->ch_pun.un_flag & UN_PWAIT) != 0) - (ch->ch_nd)->nd_tx_work = 1; - -out: - spin_unlock_irqrestore(&dgrp_poll_data.poll_lock, lock_flags); - - return count; -} - - -/* - * Put a character into ch->ch_buf - * - * - used by the line discipline for OPOST processing - */ - -static int dgrp_tty_put_char(struct tty_struct *tty, unsigned char new_char) -{ - struct un_struct *un; - struct ch_struct *ch; - ulong lock_flags; - int space; - int retval = 0; - - if (tty == NULL) - return 0; - - un = tty->driver_data; - if (!un) - return 0; - - ch = un->un_ch; - if (!ch) - return 0; - - if (ch->ch_state != CS_READY) - return 0; - - spin_lock_irqsave(&dgrp_poll_data.poll_lock, lock_flags); - - - /* - * If space is 0 and its because the ch->tbuf - * Warn and dump the character, there isn't anything else - * we can do about it. David_Fries@digi.com - */ - - space = (ch->ch_tout - ch->ch_tin - 1) & TBUF_MASK; - - un->un_tbusy++; - - /* - * Output the printer on string if device is TXPrint. - */ - if (IS_PRINT(MINOR(tty_devnum(tty))) && (ch->ch_flag & CH_PRON) == 0) { - if (space < ch->ch_digi.digi_onlen) { - un->un_tbusy--; - goto out; - } - space -= ch->ch_digi.digi_onlen; - drp_wmove(ch, 0, ch->ch_digi.digi_onstr, - ch->ch_digi.digi_onlen); - ch->ch_flag |= CH_PRON; - } - - /* - * Output the printer off string if device is NOT TXPrint. - */ - - if (!IS_PRINT(MINOR(tty_devnum(tty))) && - ((ch->ch_flag & CH_PRON) != 0)) { - if (space < ch->ch_digi.digi_offlen) { - un->un_tbusy--; - goto out; - } - - space -= ch->ch_digi.digi_offlen; - drp_wmove(ch, 0, ch->ch_digi.digi_offstr, - ch->ch_digi.digi_offlen); - ch->ch_flag &= ~CH_PRON; - } - - if (!space) { - un->un_tbusy--; - goto out; - } - - /* - * Copy the character to the ch_tbuf being - * careful to wrap around the circular queue - */ - ch->ch_tbuf[ch->ch_tin] = new_char; - ch->ch_tin = (1 + ch->ch_tin) & TBUF_MASK; - - if (IS_PRINT(MINOR(tty_devnum(tty)))) { - - /* - * Adjust ch_cpstime to account - * for the character just output. - */ - - int cc = HZ + ch->ch_cpsrem; - - ch->ch_cpstime += cc / ch->ch_digi.digi_maxcps; - ch->ch_cpsrem = cc % ch->ch_digi.digi_maxcps; - - /* - * If we are now waiting on time, schedule ourself - * back when we'll be able to send a block of - * digi_maxchar characters. - */ - - ch->ch_waketime = (ch->ch_cpstime + - (ch->ch_digi.digi_maxchar * HZ / - ch->ch_digi.digi_maxcps)); - } - - - un->un_tbusy--; - (ch->ch_nd)->nd_tx_work = 1; - - retval = 1; -out: - spin_unlock_irqrestore(&dgrp_poll_data.poll_lock, lock_flags); - return retval; -} - - - -/* - * Flush TX buffer (make in == out) - * - * check tty_ioctl.c -- this is called after TCOFLUSH - */ -static void dgrp_tty_flush_buffer(struct tty_struct *tty) -{ - struct un_struct *un; - struct ch_struct *ch; - - if (!tty) - return; - un = tty->driver_data; - if (!un) - return; - - ch = un->un_ch; - if (!ch) - return; - - ch->ch_tout = ch->ch_tin; - /* do NOT do this here! */ - /* ch->ch_s_tpos = ch->ch_s_tin = 0; */ - - /* send the flush output command now */ - ch->ch_send |= RR_TX_FLUSH; - (ch->ch_nd)->nd_tx_ready = 1; - (ch->ch_nd)->nd_tx_work = 1; - wake_up_interruptible(&(ch->ch_nd)->nd_tx_waitq); - - if (waitqueue_active(&tty->write_wait)) - wake_up_interruptible(&tty->write_wait); - - tty_wakeup(tty); - -} - -/* - * Return space available in Tx buffer - * count = ( ch->ch_tout - ch->ch_tin ) mod (TBUF_MAX - 1) - */ -static int dgrp_tty_write_room(struct tty_struct *tty) -{ - struct un_struct *un; - struct ch_struct *ch; - int count; - - if (!tty) - return 0; - - un = tty->driver_data; - if (!un) - return 0; - - ch = un->un_ch; - if (!ch) - return 0; - - count = (ch->ch_tout - ch->ch_tin - 1) & TBUF_MASK; - - /* We *MUST* check this, and return 0 if the Printer Unit cannot - * take any more data within its time constraints... If we don't - * return 0 and the printer has hit it time constraint, the ld will - * call us back doing a put_char, which cannot be rejected!!! - */ - if (IS_PRINT(MINOR(tty_devnum(tty)))) { - int un_flag = 0; - count = dgrp_calculate_txprint_bounds(ch, count, &un_flag); - if (count <= 0) - count = 0; - - ch->ch_pun.un_flag |= un_flag; - (ch->ch_nd)->nd_tx_work = 1; - } - - return count; -} - -/* - * Return number of characters that have not been transmitted yet. - * chars_in_buffer = ( ch->ch_tin - ch->ch_tout ) mod (TBUF_MAX - 1) - * + ( ch->ch_s_tin - ch->ch_s_tout ) mod (0xffff) - * = number of characters "in transit" - * - * Remember that sequence number math is always with a sixteen bit - * mask, not the TBUF_MASK. - */ - -static int dgrp_tty_chars_in_buffer(struct tty_struct *tty) -{ - struct un_struct *un; - struct ch_struct *ch; - int count; - int count1; - - if (!tty) - return 0; - - un = tty->driver_data; - if (!un) - return 0; - - ch = un->un_ch; - if (!ch) - return 0; - - count1 = count = (ch->ch_tin - ch->ch_tout) & TBUF_MASK; - count += (ch->ch_s_tin - ch->ch_s_tpos) & 0xffff; - /* one for tbuf, one for the PS */ - - /* - * If we are busy transmitting add 1 - */ - count += un->un_tbusy; - - return count; -} - - -/***************************************************************************** - * - * Helper applications for dgrp_tty_ioctl() - * - ***************************************************************************** - */ - - -/** - * ch_to_tty_flags() -- convert channel flags to termio flags - * @ch_flag: Digi channel flags - * @flagtype: type of ch_flag (iflag, oflag or cflag) - * - * take the channel flags of the specified type and return the - * corresponding termio flag - */ -static tcflag_t ch_to_tty_flags(ushort ch_flag, char flagtype) -{ - tcflag_t retval = 0; - - switch (flagtype) { - case 'i': - retval = ((ch_flag & IF_IGNBRK) ? IGNBRK : 0) - | ((ch_flag & IF_BRKINT) ? BRKINT : 0) - | ((ch_flag & IF_IGNPAR) ? IGNPAR : 0) - | ((ch_flag & IF_PARMRK) ? PARMRK : 0) - | ((ch_flag & IF_INPCK) ? INPCK : 0) - | ((ch_flag & IF_ISTRIP) ? ISTRIP : 0) - | ((ch_flag & IF_IXON) ? IXON : 0) - | ((ch_flag & IF_IXANY) ? IXANY : 0) - | ((ch_flag & IF_IXOFF) ? IXOFF : 0); - break; - - case 'o': - retval = ((ch_flag & OF_OLCUC) ? OLCUC : 0) - | ((ch_flag & OF_ONLCR) ? ONLCR : 0) - | ((ch_flag & OF_OCRNL) ? OCRNL : 0) - | ((ch_flag & OF_ONOCR) ? ONOCR : 0) - | ((ch_flag & OF_ONLRET) ? ONLRET : 0) - /* | ((ch_flag & OF_OTAB3) ? OFILL : 0) */ - | ((ch_flag & OF_TABDLY) ? TABDLY : 0); - break; - - case 'c': - retval = ((ch_flag & CF_CSTOPB) ? CSTOPB : 0) - | ((ch_flag & CF_CREAD) ? CREAD : 0) - | ((ch_flag & CF_PARENB) ? PARENB : 0) - | ((ch_flag & CF_PARODD) ? PARODD : 0) - | ((ch_flag & CF_HUPCL) ? HUPCL : 0); - - switch (ch_flag & CF_CSIZE) { - case CF_CS5: - retval |= CS5; - break; - case CF_CS6: - retval |= CS6; - break; - case CF_CS7: - retval |= CS7; - break; - case CF_CS8: - retval |= CS8; - break; - default: - retval |= CS8; - break; - } - break; - case 'x': - break; - case 'l': - break; - default: - return 0; - } - - return retval; -} - - -/** - * tty_to_ch_flags() -- convert termio flags to digi channel flags - * @tty: pointer to a TTY structure holding flag to be converted - * @flagtype: identifies which flag (iflags, oflags, or cflags) should - * be converted - * - * take the termio flag of the specified type and return the - * corresponding Digi version of the flags - */ -static ushort tty_to_ch_flags(struct tty_struct *tty, char flagtype) -{ - ushort retval = 0; - tcflag_t tflag = 0; - - switch (flagtype) { - case 'i': - tflag = tty->termios.c_iflag; - retval = (I_IGNBRK(tty) ? IF_IGNBRK : 0) - | (I_BRKINT(tty) ? IF_BRKINT : 0) - | (I_IGNPAR(tty) ? IF_IGNPAR : 0) - | (I_PARMRK(tty) ? IF_PARMRK : 0) - | (I_INPCK(tty) ? IF_INPCK : 0) - | (I_ISTRIP(tty) ? IF_ISTRIP : 0) - | (I_IXON(tty) ? IF_IXON : 0) - | (I_IXANY(tty) ? IF_IXANY : 0) - | (I_IXOFF(tty) ? IF_IXOFF : 0); - break; - case 'o': - tflag = tty->termios.c_oflag; - /* - * If OPOST is set, then do the post processing in the - * firmware by setting all the processing flags on. - * If ~OPOST, then make sure we are not doing any - * output processing!! - */ - if (!O_OPOST(tty)) - retval = 0; - else - retval = (O_OLCUC(tty) ? OF_OLCUC : 0) - | (O_ONLCR(tty) ? OF_ONLCR : 0) - | (O_OCRNL(tty) ? OF_OCRNL : 0) - | (O_ONOCR(tty) ? OF_ONOCR : 0) - | (O_ONLRET(tty) ? OF_ONLRET : 0) - /* | (O_OFILL(tty) ? OF_TAB3 : 0) */ - | (O_TABDLY(tty) ? OF_TABDLY : 0); - break; - case 'c': - tflag = tty->termios.c_cflag; - retval = (C_CSTOPB(tty) ? CF_CSTOPB : 0) - | (C_CREAD(tty) ? CF_CREAD : 0) - | (C_PARENB(tty) ? CF_PARENB : 0) - | (C_PARODD(tty) ? CF_PARODD : 0) - | (C_HUPCL(tty) ? CF_HUPCL : 0); - switch (C_CSIZE(tty)) { - case CS8: - retval |= CF_CS8; - break; - case CS7: - retval |= CF_CS7; - break; - case CS6: - retval |= CF_CS6; - break; - case CS5: - retval |= CF_CS5; - break; - default: - retval |= CF_CS8; - break; - } - break; - case 'x': - break; - case 'l': - break; - default: - return 0; - } - - return retval; -} - - -static int dgrp_tty_send_break(struct tty_struct *tty, int msec) -{ - struct un_struct *un; - struct ch_struct *ch; - int ret = -EIO; - - if (!tty) - return ret; - - un = tty->driver_data; - if (!un) - return ret; - - ch = un->un_ch; - if (!ch) - return ret; - - dgrp_send_break(ch, msec); - return 0; -} - - -/* - * This routine sends a break character out the serial port. - * - * duration is in 1/1000's of a second - */ -static int dgrp_send_break(struct ch_struct *ch, int msec) -{ - ulong x; - - wait_event_interruptible(ch->ch_flag_wait, - ((ch->ch_flag & CH_TX_BREAK) == 0)); - ch->ch_break_time += max(msec, 250); - ch->ch_send |= RR_TX_BREAK; - ch->ch_flag |= CH_TX_BREAK; - (ch->ch_nd)->nd_tx_work = 1; - - x = (msec * HZ) / 1000; - wake_up_interruptible(&(ch->ch_nd)->nd_tx_waitq); - - return 0; -} - - -/* - * Return modem signals to ld. - */ -static int dgrp_tty_tiocmget(struct tty_struct *tty) -{ - unsigned int mlast; - struct un_struct *un = tty->driver_data; - struct ch_struct *ch; - - if (!un) - return -ENODEV; - - ch = un->un_ch; - if (!ch) - return -ENODEV; - - mlast = ((ch->ch_s_mlast & ~(DM_RTS | DM_DTR)) | - (ch->ch_mout & (DM_RTS | DM_DTR))); - - /* defined in /usr/include/asm/termios.h */ - mlast = ((mlast & DM_RTS) ? TIOCM_RTS : 0) - | ((mlast & DM_DTR) ? TIOCM_DTR : 0) - | ((mlast & DM_CD) ? TIOCM_CAR : 0) - | ((mlast & DM_RI) ? TIOCM_RNG : 0) - | ((mlast & DM_DSR) ? TIOCM_DSR : 0) - | ((mlast & DM_CTS) ? TIOCM_CTS : 0); - - return mlast; -} - - -/* - * Set modem lines - */ -static int dgrp_tty_tiocmset(struct tty_struct *tty, - unsigned int set, unsigned int clear) -{ - ulong lock_flags; - struct un_struct *un = tty->driver_data; - struct ch_struct *ch; - - if (!un) - return -ENODEV; - - ch = un->un_ch; - if (!ch) - return -ENODEV; - - if (set & TIOCM_RTS) - ch->ch_mout |= DM_RTS; - - if (set & TIOCM_DTR) - ch->ch_mout |= DM_DTR; - - if (clear & TIOCM_RTS) - ch->ch_mout &= ~(DM_RTS); - - if (clear & TIOCM_DTR) - ch->ch_mout &= ~(DM_DTR); - - spin_lock_irqsave(&(ch->ch_nd)->nd_lock, lock_flags); - ch->ch_flag |= CH_PARAM; - (ch->ch_nd)->nd_tx_work = 1; - wake_up_interruptible(&ch->ch_flag_wait); - - spin_unlock_irqrestore(&(ch->ch_nd)->nd_lock, lock_flags); - - return 0; -} - - - -/* - * Get current modem status - */ -static int get_modem_info(struct ch_struct *ch, unsigned int *value) -{ - unsigned int mlast; - - mlast = ((ch->ch_s_mlast & ~(DM_RTS | DM_DTR)) | - (ch->ch_mout & (DM_RTS | DM_DTR))); - - /* defined in /usr/include/asm/termios.h */ - mlast = ((mlast & DM_RTS) ? TIOCM_RTS : 0) - | ((mlast & DM_DTR) ? TIOCM_DTR : 0) - | ((mlast & DM_CD) ? TIOCM_CAR : 0) - | ((mlast & DM_RI) ? TIOCM_RNG : 0) - | ((mlast & DM_DSR) ? TIOCM_DSR : 0) - | ((mlast & DM_CTS) ? TIOCM_CTS : 0); - put_user(mlast, (unsigned int __user *) value); - - return 0; -} - -/* - * Set modem lines - */ -static int set_modem_info(struct ch_struct *ch, unsigned int command, - unsigned int *value) -{ - int error; - unsigned int arg; - int mval = 0; - ulong lock_flags; - - error = access_ok(VERIFY_READ, (void __user *) value, sizeof(int)); - if (error == 0) - return -EFAULT; - - get_user(arg, (unsigned int __user *) value); - mval |= ((arg & TIOCM_RTS) ? DM_RTS : 0) - | ((arg & TIOCM_DTR) ? DM_DTR : 0); - - switch (command) { - case TIOCMBIS: /* set flags */ - ch->ch_mout |= mval; - break; - case TIOCMBIC: /* clear flags */ - ch->ch_mout &= ~mval; - break; - case TIOCMSET: - ch->ch_mout = mval; - break; - default: - return -EINVAL; - } - - spin_lock_irqsave(&(ch->ch_nd)->nd_lock, lock_flags); - - ch->ch_flag |= CH_PARAM; - (ch->ch_nd)->nd_tx_work = 1; - wake_up_interruptible(&ch->ch_flag_wait); - - spin_unlock_irqrestore(&(ch->ch_nd)->nd_lock, lock_flags); - - return 0; -} - - -/* - * Assign the custom baud rate to the channel structure - */ -static void dgrp_set_custom_speed(struct ch_struct *ch, int newrate) -{ - int testdiv; - int testrate_high; - int testrate_low; - - int deltahigh, deltalow; - - if (newrate < 0) - newrate = 0; - - /* - * Since the divisor is stored in a 16-bit integer, we make sure - * we don't allow any rates smaller than a 16-bit integer would allow. - * And of course, rates above the dividend won't fly. - */ - if (newrate && newrate < ((PORTSERVER_DIVIDEND / 0xFFFF) + 1)) - newrate = ((PORTSERVER_DIVIDEND / 0xFFFF) + 1); - if (newrate && newrate > PORTSERVER_DIVIDEND) - newrate = PORTSERVER_DIVIDEND; - - while (newrate > 0) { - testdiv = PORTSERVER_DIVIDEND / newrate; - - /* - * If we try to figure out what rate the PortServer would use - * with the test divisor, it will be either equal or higher - * than the requested baud rate. If we then determine the - * rate with a divisor one higher, we will get the next lower - * supported rate below the requested. - */ - testrate_high = PORTSERVER_DIVIDEND / testdiv; - testrate_low = PORTSERVER_DIVIDEND / (testdiv + 1); - - /* - * If the rate for the requested divisor is correct, just - * use it and be done. - */ - if (testrate_high == newrate) - break; - - /* - * Otherwise, pick the rate that is closer (i.e. whichever rate - * has a smaller delta). - */ - deltahigh = testrate_high - newrate; - deltalow = newrate - testrate_low; - - if (deltahigh < deltalow) - newrate = testrate_high; - else - newrate = testrate_low; - - break; - } - - ch->ch_custom_speed = newrate; - - drp_param(ch); - - return; -} - - -/* - # dgrp_tty_digiseta() - * - * Ioctl to set the information from ditty. - * - * NOTE: DIGI_IXON, DSRPACE, DCDPACE, and DTRPACE are unsupported. JAR 990922 - */ -static int dgrp_tty_digiseta(struct tty_struct *tty, - struct digi_struct *new_info) -{ - struct un_struct *un = tty->driver_data; - struct ch_struct *ch; - - if (!un) - return -ENODEV; - - ch = un->un_ch; - if (!ch) - return -ENODEV; - - if (copy_from_user(&ch->ch_digi, (void __user *) new_info, - sizeof(struct digi_struct))) - return -EFAULT; - - if ((ch->ch_digi.digi_flags & RTSPACE) || - (ch->ch_digi.digi_flags & CTSPACE)) - tty->termios.c_cflag |= CRTSCTS; - else - tty->termios.c_cflag &= ~CRTSCTS; - - if (ch->ch_digi.digi_maxcps < 1) - ch->ch_digi.digi_maxcps = 1; - - if (ch->ch_digi.digi_maxcps > 10000) - ch->ch_digi.digi_maxcps = 10000; - - if (ch->ch_digi.digi_bufsize < 10) - ch->ch_digi.digi_bufsize = 10; - - if (ch->ch_digi.digi_maxchar < 1) - ch->ch_digi.digi_maxchar = 1; - - if (ch->ch_digi.digi_maxchar > ch->ch_digi.digi_bufsize) - ch->ch_digi.digi_maxchar = ch->ch_digi.digi_bufsize; - - if (ch->ch_digi.digi_onlen > DIGI_PLEN) - ch->ch_digi.digi_onlen = DIGI_PLEN; - - if (ch->ch_digi.digi_offlen > DIGI_PLEN) - ch->ch_digi.digi_offlen = DIGI_PLEN; - - /* make the changes now */ - drp_param(ch); - - return 0; -} - - - -/* - * dgrp_tty_digigetedelay() - * - * Ioctl to get the current edelay setting. - * - * - * - */ -static int dgrp_tty_digigetedelay(struct tty_struct *tty, int *retinfo) -{ - struct un_struct *un; - struct ch_struct *ch; - int tmp; - - if (!retinfo) - return -EFAULT; - - if (!tty || tty->magic != TTY_MAGIC) - return -EFAULT; - - un = tty->driver_data; - - if (!un) - return -ENODEV; - - ch = un->un_ch; - if (!ch) - return -ENODEV; - - tmp = ch->ch_edelay; - - if (copy_to_user((void __user *) retinfo, &tmp, sizeof(*retinfo))) - return -EFAULT; - - return 0; -} - - -/* - * dgrp_tty_digisetedelay() - * - * Ioctl to set the EDELAY setting - * - */ -static int dgrp_tty_digisetedelay(struct tty_struct *tty, int *new_info) -{ - struct un_struct *un; - struct ch_struct *ch; - int new_digi; - - if (!tty || tty->magic != TTY_MAGIC) - return -EFAULT; - - un = tty->driver_data; - - if (!un) - return -ENODEV; - - ch = un->un_ch; - if (!ch) - return -ENODEV; - - if (copy_from_user(&new_digi, (void __user *)new_info, sizeof(int))) - return -EFAULT; - - ch->ch_edelay = new_digi; - - /* make the changes now */ - drp_param(ch); - - return 0; -} - - -/* - * The usual assortment of ioctl's - * - * note: use tty_check_change to make sure that we are not - * changing the state of a terminal when we are not a process - * in the forground. See tty_io.c - * rc = tty_check_change(tty); - * if (rc) return rc; - */ -static int dgrp_tty_ioctl(struct tty_struct *tty, unsigned int cmd, - unsigned long arg) -{ - struct un_struct *un; - struct ch_struct *ch; - int rc; - struct digiflow_struct dflow; - - if (!tty) - return -ENODEV; - - un = tty->driver_data; - if (!un) - return -ENODEV; - - ch = un->un_ch; - if (!ch) - return -ENODEV; - - switch (cmd) { - - /* - * Here are all the standard ioctl's that we MUST implement - */ - - case TCSBRK: - /* - * TCSBRK is SVID version: non-zero arg --> no break - * this behaviour is exploited by tcdrain(). - * - * According to POSIX.1 spec (7.2.2.1.2) breaks should be - * between 0.25 and 0.5 seconds - */ - - rc = tty_check_change(tty); - if (rc) - return rc; - tty_wait_until_sent(tty, 0); - - if (!arg) - rc = dgrp_send_break(ch, 250); /* 1/4 second */ - - if (dgrp_tty_chars_in_buffer(tty) != 0) - return -EINTR; - - return 0; - - case TCSBRKP: - /* support for POSIX tcsendbreak() - * - * According to POSIX.1 spec (7.2.2.1.2) breaks should be - * between 0.25 and 0.5 seconds so we'll ask for something - * in the middle: 0.375 seconds. - */ - rc = tty_check_change(tty); - if (rc) - return rc; - tty_wait_until_sent(tty, 0); - - rc = dgrp_send_break(ch, arg ? arg*250 : 250); - - if (dgrp_tty_chars_in_buffer(tty) != 0) - return -EINTR; - return 0; - - case TIOCSBRK: - rc = tty_check_change(tty); - if (rc) - return rc; - tty_wait_until_sent(tty, 0); - - /* - * RealPort doesn't support turning on a break unconditionally. - * The RealPort device will stop sending a break automatically - * after the specified time value that we send in. - */ - rc = dgrp_send_break(ch, 250); /* 1/4 second */ - - if (dgrp_tty_chars_in_buffer(tty) != 0) - return -EINTR; - return 0; - - case TIOCCBRK: - /* - * RealPort doesn't support turning off a break unconditionally. - * The RealPort device will stop sending a break automatically - * after the specified time value that was sent when turning on - * the break. - */ - return 0; - - case TIOCGSOFTCAR: - rc = access_ok(VERIFY_WRITE, (void __user *) arg, - sizeof(long)); - if (rc == 0) - return -EFAULT; - put_user(C_CLOCAL(tty) ? 1 : 0, (unsigned long __user *) arg); - return 0; - - case TIOCSSOFTCAR: - get_user(arg, (unsigned long __user *) arg); - tty->termios.c_cflag = - ((tty->termios.c_cflag & ~CLOCAL) | - (arg ? CLOCAL : 0)); - return 0; - - case TIOCMGET: - rc = access_ok(VERIFY_WRITE, (void __user *) arg, - sizeof(unsigned int)); - if (rc == 0) - return -EFAULT; - return get_modem_info(ch, (unsigned int *) arg); - - case TIOCMBIS: - case TIOCMBIC: - case TIOCMSET: - return set_modem_info(ch, cmd, (unsigned int *) arg); - - /* - * Here are any additional ioctl's that we want to implement - */ - - case TCFLSH: - /* - * The linux tty driver doesn't have a flush - * input routine for the driver, assuming all backed - * up data is in the line disc. buffers. However, - * we all know that's not the case. Here, we - * act on the ioctl, but then lie and say we didn't - * so the line discipline will process the flush - * also. - */ - rc = tty_check_change(tty); - if (rc) - return rc; - - switch (arg) { - case TCIFLUSH: - case TCIOFLUSH: - /* only flush input if this is the only open unit */ - if (!IS_PRINT(MINOR(tty_devnum(tty)))) { - ch->ch_rout = ch->ch_rin; - ch->ch_send |= RR_RX_FLUSH; - (ch->ch_nd)->nd_tx_work = 1; - (ch->ch_nd)->nd_tx_ready = 1; - wake_up_interruptible(&(ch->ch_nd)->nd_tx_waitq); - } - if (arg == TCIFLUSH) - break; - - case TCOFLUSH: /* flush output, or the receive buffer */ - /* - * This is handled in the tty_ioctl.c code - * calling tty_flush_buffer - */ - break; - - default: - /* POSIX.1 says return EINVAL if we got a bad arg */ - return -EINVAL; - } - /* pretend we didn't recognize this IOCTL */ - return -ENOIOCTLCMD; - -#ifdef TIOCGETP - case TIOCGETP: -#endif - /***************************************** - Linux HPUX Function - TCSETA TCSETA - set the termios - TCSETAF TCSETAF - wait for drain first, then set termios - TCSETAW TCSETAW - wait for drain, flush the input queue, then set termios - - looking at the tty_ioctl code, these command all call our - tty_set_termios at the driver's end, when a TCSETA* is sent, - it is expecting the tty to have a termio structure, - NOT a termios stucture. These two structures differ in size - and the tty_ioctl code does a conversion before processing them both. - - we should treat the TCSETAW TCSETAF ioctls the same, and let - the tty_ioctl code do the conversion stuff. - - TCSETS - TCSETSF (none) - TCSETSW - - the associated tty structure has a termios structure. - *****************************************/ - - case TCGETS: - case TCGETA: - return -ENOIOCTLCMD; - - case TCSETAW: - case TCSETAF: - case TCSETSF: - case TCSETSW: - /* - * The linux tty driver doesn't have a flush - * input routine for the driver, assuming all backed - * up data is in the line disc. buffers. However, - * we all know that's not the case. Here, we - * act on the ioctl, but then lie and say we didn't - * so the line discipline will process the flush - * also. - */ - - /* - * Also, now that we have TXPrint, we have to check - * if this is the TXPrint device and the terminal - * device is open. If so, do NOT run check_change, - * as the terminal device is ALWAYS the parent. - */ - if (!IS_PRINT(MINOR(tty_devnum(tty))) || - !ch->ch_tun.un_open_count) { - rc = tty_check_change(tty); - if (rc) - return rc; - } - - /* wait for all the characters in tbuf to drain */ - tty_wait_until_sent(tty, 0); - - if ((cmd == TCSETSF) || (cmd == TCSETAF)) { - /* flush the contents of the rbuf queue */ - /* TODO: check if this is print device? */ - ch->ch_send |= RR_RX_FLUSH; - (ch->ch_nd)->nd_tx_ready = 1; - (ch->ch_nd)->nd_tx_work = 1; - wake_up_interruptible(&(ch->ch_nd)->nd_tx_waitq); - /* do we need to do this? just to be safe! */ - ch->ch_rout = ch->ch_rin; - } - - /* pretend we didn't recognize this */ - return -ENOIOCTLCMD; - - case TCXONC: - /* - * The Linux Line Discipline (LD) would do this for us if we - * let it, but we have the special firmware options to do this - * the "right way" regardless of hardware or software flow - * control so we'll do it outselves instead of letting the LD - * do it. - */ - rc = tty_check_change(tty); - if (rc) - return rc; - - switch (arg) { - case TCOON: - dgrp_tty_start(tty); - return 0; - case TCOOFF: - dgrp_tty_stop(tty); - return 0; - case TCION: - dgrp_tty_input_start(tty); - return 0; - case TCIOFF: - dgrp_tty_input_stop(tty); - return 0; - default: - return -EINVAL; - } - - case DIGI_GETA: - /* get information for ditty */ - if (copy_to_user((struct digi_struct __user *) arg, - &ch->ch_digi, sizeof(struct digi_struct))) - return -EFAULT; - break; - - case DIGI_SETAW: - case DIGI_SETAF: - /* wait for all the characters in tbuf to drain */ - tty_wait_until_sent(tty, 0); - - if (cmd == DIGI_SETAF) { - /* flush the contents of the rbuf queue */ - /* send down a packet with RR_RX_FLUSH set */ - ch->ch_send |= RR_RX_FLUSH; - (ch->ch_nd)->nd_tx_ready = 1; - (ch->ch_nd)->nd_tx_work = 1; - wake_up_interruptible(&(ch->ch_nd)->nd_tx_waitq); - /* do we need to do this? just to be safe! */ - ch->ch_rout = ch->ch_rin; - } - - /* pretend we didn't recognize this */ - - case DIGI_SETA: - return dgrp_tty_digiseta(tty, (struct digi_struct *) arg); - - case DIGI_SEDELAY: - return dgrp_tty_digisetedelay(tty, (int *) arg); - - case DIGI_GEDELAY: - return dgrp_tty_digigetedelay(tty, (int *) arg); - - case DIGI_GETFLOW: - case DIGI_GETAFLOW: - if (cmd == (DIGI_GETFLOW)) { - dflow.startc = tty->termios.c_cc[VSTART]; - dflow.stopc = tty->termios.c_cc[VSTOP]; - } else { - dflow.startc = ch->ch_xxon; - dflow.stopc = ch->ch_xxoff; - } - - if (copy_to_user((char __user *)arg, &dflow, sizeof(dflow))) - return -EFAULT; - break; - - case DIGI_SETFLOW: - case DIGI_SETAFLOW: - - if (copy_from_user(&dflow, (char __user *)arg, sizeof(dflow))) - return -EFAULT; - - if (cmd == (DIGI_SETFLOW)) { - tty->termios.c_cc[VSTART] = dflow.startc; - tty->termios.c_cc[VSTOP] = dflow.stopc; - } else { - ch->ch_xxon = dflow.startc; - ch->ch_xxoff = dflow.stopc; - } - break; - - case DIGI_GETCUSTOMBAUD: - rc = access_ok(VERIFY_WRITE, (void __user *) arg, sizeof(int)); - if (rc == 0) - return -EFAULT; - put_user(ch->ch_custom_speed, (unsigned int __user *) arg); - break; - - case DIGI_SETCUSTOMBAUD: - { - int new_rate; - - get_user(new_rate, (unsigned int __user *) arg); - dgrp_set_custom_speed(ch, new_rate); - - break; - } - - default: - return -ENOIOCTLCMD; - } - - return 0; -} - -/* - * This routine allows the tty driver to be notified when - * the device's termios setting have changed. Note that we - * should be prepared to accept the case where old == NULL - * and try to do something rational. - * - * So we need to make sure that our copies of ch_oflag, - * ch_clag, and ch_iflag reflect the tty->termios flags. - */ -static void dgrp_tty_set_termios(struct tty_struct *tty, struct ktermios *old) -{ - struct ktermios *ts; - struct ch_struct *ch; - struct un_struct *un; - - /* seems silly, but we have to check all these! */ - if (!tty) - return; - - un = tty->driver_data; - if (!un) - return; - - ts = &tty->termios; - - ch = un->un_ch; - if (!ch) - return; - - drp_param(ch); - - /* the CLOCAL flag has just been set */ - if (!(old->c_cflag & CLOCAL) && C_CLOCAL(tty)) - wake_up_interruptible(&un->un_open_wait); -} - - -/* - * Throttle receiving data. We just set a bit and stop reading - * data out of the channel buffer. It will back up and the - * FEP will do whatever is necessary to stop the far end. - */ -static void dgrp_tty_throttle(struct tty_struct *tty) -{ - struct ch_struct *ch; - - if (!tty) - return; - - ch = ((struct un_struct *) tty->driver_data)->un_ch; - if (!ch) - return; - - ch->ch_flag |= CH_RXSTOP; -} - - -static void dgrp_tty_unthrottle(struct tty_struct *tty) -{ - struct ch_struct *ch; - - if (!tty) - return; - - ch = ((struct un_struct *) tty->driver_data)->un_ch; - if (!ch) - return; - - ch->ch_flag &= ~CH_RXSTOP; -} - -/* - * Stop the transmitter - */ -static void dgrp_tty_stop(struct tty_struct *tty) -{ - struct ch_struct *ch; - - if (!tty) - return; - - ch = ((struct un_struct *) tty->driver_data)->un_ch; - if (!ch) - return; - - ch->ch_send |= RR_TX_STOP; - ch->ch_send &= ~RR_TX_START; - - /* make the change NOW! */ - (ch->ch_nd)->nd_tx_ready = 1; - if (waitqueue_active(&(ch->ch_nd)->nd_tx_waitq)) - wake_up_interruptible(&(ch->ch_nd)->nd_tx_waitq); -} - -/* - * Start the transmitter - */ -static void dgrp_tty_start(struct tty_struct *tty) -{ - struct ch_struct *ch; - - if (!tty) - return; - - ch = ((struct un_struct *) tty->driver_data)->un_ch; - if (!ch) - return; - - /* TODO: don't do anything if the transmitter is not stopped */ - - ch->ch_send |= RR_TX_START; - ch->ch_send &= ~RR_TX_STOP; - - /* make the change NOW! */ - (ch->ch_nd)->nd_tx_ready = 1; - (ch->ch_nd)->nd_tx_work = 1; - if (waitqueue_active(&(ch->ch_nd)->nd_tx_waitq)) - wake_up_interruptible(&(ch->ch_nd)->nd_tx_waitq); - -} - -/* - * Stop the reciever - */ -static void dgrp_tty_input_stop(struct tty_struct *tty) -{ - struct ch_struct *ch; - - if (!tty) - return; - - ch = ((struct un_struct *) tty->driver_data)->un_ch; - if (!ch) - return; - - ch->ch_send |= RR_RX_STOP; - ch->ch_send &= ~RR_RX_START; - (ch->ch_nd)->nd_tx_ready = 1; - if (waitqueue_active(&(ch->ch_nd)->nd_tx_waitq)) - wake_up_interruptible(&(ch->ch_nd)->nd_tx_waitq); - -} - - -static void dgrp_tty_send_xchar(struct tty_struct *tty, char c) -{ - struct un_struct *un; - struct ch_struct *ch; - - if (!tty) - return; - - un = tty->driver_data; - if (!un) - return; - - ch = un->un_ch; - if (!ch) - return; - if (c == STOP_CHAR(tty)) - ch->ch_send |= RR_RX_STOP; - else if (c == START_CHAR(tty)) - ch->ch_send |= RR_RX_START; - - ch->ch_nd->nd_tx_ready = 1; - ch->ch_nd->nd_tx_work = 1; - - return; -} - - -static void dgrp_tty_input_start(struct tty_struct *tty) -{ - struct ch_struct *ch; - - if (!tty) - return; - - ch = ((struct un_struct *) tty->driver_data)->un_ch; - if (!ch) - return; - - ch->ch_send |= RR_RX_START; - ch->ch_send &= ~RR_RX_STOP; - (ch->ch_nd)->nd_tx_ready = 1; - (ch->ch_nd)->nd_tx_work = 1; - if (waitqueue_active(&(ch->ch_nd)->nd_tx_waitq)) - wake_up_interruptible(&(ch->ch_nd)->nd_tx_waitq); - -} - - -/* - * Hangup the port. Like a close, but don't wait for output - * to drain. - * - * How do we close all the channels that are open? - */ -static void dgrp_tty_hangup(struct tty_struct *tty) -{ - struct ch_struct *ch; - struct nd_struct *nd; - struct un_struct *un; - - if (!tty) - return; - - un = tty->driver_data; - if (!un) - return; - - ch = un->un_ch; - if (!ch) - return; - - nd = ch->ch_nd; - - if (C_HUPCL(tty)) { - /* LOWER DTR */ - ch->ch_mout &= ~DM_DTR; - /* Don't do this here */ - /* ch->ch_flag |= CH_HANGUP; */ - ch->ch_nd->nd_tx_ready = 1; - ch->ch_nd->nd_tx_work = 1; - if (waitqueue_active(&ch->ch_flag_wait)) - wake_up_interruptible(&ch->ch_flag_wait); - } - -} - -/************************************************************************/ -/* */ -/* TTY Initialization/Cleanup Functions */ -/* */ -/************************************************************************/ - -/* - * Uninitialize the TTY portion of the supplied node. Free all - * memory and resources associated with this node. Do it in reverse - * allocation order: this might possibly result in less fragmentation - * of memory, though I don't know this for sure. - */ -void -dgrp_tty_uninit(struct nd_struct *nd) -{ - char id[3]; - - ID_TO_CHAR(nd->nd_ID, id); - - if (nd->nd_ttdriver_flags & SERIAL_TTDRV_REG) { - tty_unregister_driver(nd->nd_serial_ttdriver); - - kfree(nd->nd_serial_ttdriver->ttys); - nd->nd_serial_ttdriver->ttys = NULL; - - put_tty_driver(nd->nd_serial_ttdriver); - nd->nd_ttdriver_flags &= ~SERIAL_TTDRV_REG; - } - - if (nd->nd_ttdriver_flags & CALLOUT_TTDRV_REG) { - tty_unregister_driver(nd->nd_callout_ttdriver); - - kfree(nd->nd_callout_ttdriver->ttys); - nd->nd_callout_ttdriver->ttys = NULL; - - put_tty_driver(nd->nd_callout_ttdriver); - nd->nd_ttdriver_flags &= ~CALLOUT_TTDRV_REG; - } - - if (nd->nd_ttdriver_flags & XPRINT_TTDRV_REG) { - tty_unregister_driver(nd->nd_xprint_ttdriver); - - kfree(nd->nd_xprint_ttdriver->ttys); - nd->nd_xprint_ttdriver->ttys = NULL; - - put_tty_driver(nd->nd_xprint_ttdriver); - nd->nd_ttdriver_flags &= ~XPRINT_TTDRV_REG; - } -} - - - -/* - * Initialize the TTY portion of the supplied node. - */ -int -dgrp_tty_init(struct nd_struct *nd) -{ - char id[3]; - int rc; - int i; - - ID_TO_CHAR(nd->nd_ID, id); - - /* - * Initialize the TTDRIVER structures. - */ - - nd->nd_serial_ttdriver = alloc_tty_driver(CHAN_MAX); - sprintf(nd->nd_serial_name, "tty_dgrp_%s_", id); - - nd->nd_serial_ttdriver->owner = THIS_MODULE; - nd->nd_serial_ttdriver->name = nd->nd_serial_name; - nd->nd_serial_ttdriver->name_base = 0; - nd->nd_serial_ttdriver->major = 0; - nd->nd_serial_ttdriver->minor_start = 0; - nd->nd_serial_ttdriver->type = TTY_DRIVER_TYPE_SERIAL; - nd->nd_serial_ttdriver->subtype = SERIAL_TYPE_NORMAL; - nd->nd_serial_ttdriver->init_termios = DefaultTermios; - nd->nd_serial_ttdriver->driver_name = "dgrp"; - nd->nd_serial_ttdriver->flags = (TTY_DRIVER_REAL_RAW | - TTY_DRIVER_DYNAMIC_DEV | - TTY_DRIVER_HARDWARE_BREAK); - - /* The kernel wants space to store pointers to tty_structs. */ - nd->nd_serial_ttdriver->ttys = - kzalloc(CHAN_MAX * sizeof(struct tty_struct *), GFP_KERNEL); - if (!nd->nd_serial_ttdriver->ttys) - return -ENOMEM; - - tty_set_operations(nd->nd_serial_ttdriver, &dgrp_tty_ops); - - if (!(nd->nd_ttdriver_flags & SERIAL_TTDRV_REG)) { - /* - * Register tty devices - */ - rc = tty_register_driver(nd->nd_serial_ttdriver); - if (rc < 0) { - /* - * If errno is EBUSY, this means there are no more - * slots available to have us auto-majored. - * (Which is currently supported up to 256) - * - * We can still request majors above 256, - * we just have to do it manually. - */ - if (rc == -EBUSY) { - int i; - int max_majors = 1U << (32 - MINORBITS); - for (i = 256; i < max_majors; i++) { - nd->nd_serial_ttdriver->major = i; - rc = tty_register_driver(nd->nd_serial_ttdriver); - if (rc >= 0) - break; - } - /* Really fail now, since we ran out - * of majors to try. */ - if (i == max_majors) - return rc; - - } else { - return rc; - } - } - nd->nd_ttdriver_flags |= SERIAL_TTDRV_REG; - } - - nd->nd_callout_ttdriver = alloc_tty_driver(CHAN_MAX); - sprintf(nd->nd_callout_name, "cu_dgrp_%s_", id); - - nd->nd_callout_ttdriver->owner = THIS_MODULE; - nd->nd_callout_ttdriver->name = nd->nd_callout_name; - nd->nd_callout_ttdriver->name_base = 0; - nd->nd_callout_ttdriver->major = nd->nd_serial_ttdriver->major; - nd->nd_callout_ttdriver->minor_start = 0x40; - nd->nd_callout_ttdriver->type = TTY_DRIVER_TYPE_SERIAL; - nd->nd_callout_ttdriver->subtype = SERIAL_TYPE_CALLOUT; - nd->nd_callout_ttdriver->init_termios = DefaultTermios; - nd->nd_callout_ttdriver->driver_name = "dgrp"; - nd->nd_callout_ttdriver->flags = (TTY_DRIVER_REAL_RAW | - TTY_DRIVER_DYNAMIC_DEV | - TTY_DRIVER_HARDWARE_BREAK); - - /* The kernel wants space to store pointers to tty_structs. */ - nd->nd_callout_ttdriver->ttys = - kzalloc(CHAN_MAX * sizeof(struct tty_struct *), GFP_KERNEL); - if (!nd->nd_callout_ttdriver->ttys) - return -ENOMEM; - - tty_set_operations(nd->nd_callout_ttdriver, &dgrp_tty_ops); - - if (dgrp_register_cudevices) { - if (!(nd->nd_ttdriver_flags & CALLOUT_TTDRV_REG)) { - /* - * Register cu devices - */ - rc = tty_register_driver(nd->nd_callout_ttdriver); - if (rc < 0) - return rc; - nd->nd_ttdriver_flags |= CALLOUT_TTDRV_REG; - } - } - - - nd->nd_xprint_ttdriver = alloc_tty_driver(CHAN_MAX); - sprintf(nd->nd_xprint_name, "pr_dgrp_%s_", id); - - nd->nd_xprint_ttdriver->owner = THIS_MODULE; - nd->nd_xprint_ttdriver->name = nd->nd_xprint_name; - nd->nd_xprint_ttdriver->name_base = 0; - nd->nd_xprint_ttdriver->major = nd->nd_serial_ttdriver->major; - nd->nd_xprint_ttdriver->minor_start = 0x80; - nd->nd_xprint_ttdriver->type = TTY_DRIVER_TYPE_SERIAL; - nd->nd_xprint_ttdriver->subtype = SERIAL_TYPE_XPRINT; - nd->nd_xprint_ttdriver->init_termios = DefaultTermios; - nd->nd_xprint_ttdriver->driver_name = "dgrp"; - nd->nd_xprint_ttdriver->flags = (TTY_DRIVER_REAL_RAW | - TTY_DRIVER_DYNAMIC_DEV | - TTY_DRIVER_HARDWARE_BREAK); - - /* The kernel wants space to store pointers to tty_structs. */ - nd->nd_xprint_ttdriver->ttys = - kzalloc(CHAN_MAX * sizeof(struct tty_struct *), GFP_KERNEL); - if (!nd->nd_xprint_ttdriver->ttys) - return -ENOMEM; - - tty_set_operations(nd->nd_xprint_ttdriver, &dgrp_tty_ops); - - if (dgrp_register_prdevices) { - if (!(nd->nd_ttdriver_flags & XPRINT_TTDRV_REG)) { - /* - * Register transparent print devices - */ - rc = tty_register_driver(nd->nd_xprint_ttdriver); - if (rc < 0) - return rc; - nd->nd_ttdriver_flags |= XPRINT_TTDRV_REG; - } - } - - for (i = 0; i < CHAN_MAX; i++) { - struct ch_struct *ch = nd->nd_chan + i; - - ch->ch_nd = nd; - ch->ch_digi = digi_init; - ch->ch_edelay = 100; - ch->ch_custom_speed = 0; - ch->ch_portnum = i; - ch->ch_tun.un_ch = ch; - ch->ch_pun.un_ch = ch; - ch->ch_tun.un_type = SERIAL_TYPE_NORMAL; - ch->ch_pun.un_type = SERIAL_TYPE_XPRINT; - - init_waitqueue_head(&(ch->ch_flag_wait)); - init_waitqueue_head(&(ch->ch_sleep)); - - init_waitqueue_head(&(ch->ch_tun.un_open_wait)); - init_waitqueue_head(&(ch->ch_tun.un_close_wait)); - - init_waitqueue_head(&(ch->ch_pun.un_open_wait)); - init_waitqueue_head(&(ch->ch_pun.un_close_wait)); - tty_port_init(&ch->port); - tty_port_init(&ch->port); - } - return 0; -} diff --git a/trunk/drivers/staging/dgrp/digirp.h b/trunk/drivers/staging/dgrp/digirp.h deleted file mode 100644 index 33c1394fade7..000000000000 --- a/trunk/drivers/staging/dgrp/digirp.h +++ /dev/null @@ -1,129 +0,0 @@ -/************************************************************************ - * HP-UX Realport Daemon interface file. - * - * Copyright (C) 1998, by Digi International. All Rights Reserved. - ************************************************************************/ - -#ifndef _DIGIDRP_H -#define _DIGIDRP_H - -/************************************************************************ - * This file contains defines for the ioctl() interface to - * the realport driver. This ioctl() interface is used by the - * daemon to set speed setup parameters honored by the driver. - ************************************************************************/ - -struct link_struct { - int lk_fast_rate; /* Fast line rate to be used - when the delay is less-equal - to lk_fast_delay */ - - int lk_fast_delay; /* Fast line rate delay in - milliseconds */ - - int lk_slow_rate; /* Slow line rate to be used when - the delay is greater-equal - to lk_slow_delay */ - - int lk_slow_delay; /* Slow line rate delay in - milliseconds */ - - int lk_header_size; /* Estimated packet header size - when sent across the slowest - link. */ -}; - -#define DIGI_GETLINK _IOW('e', 103, struct link_struct) /* Get link parameters */ -#define DIGI_SETLINK _IOW('e', 104, struct link_struct) /* Set link parameters */ - - -/************************************************************************ - * This module provides application access to special Digi - * serial line enhancements which are not standard UNIX(tm) features. - ************************************************************************/ - -struct digiflow_struct { - unsigned char startc; /* flow cntl start char */ - unsigned char stopc; /* flow cntl stop char */ -}; - -/************************************************************************ - * Values for digi_flags - ************************************************************************/ -#define DIGI_IXON 0x0001 /* Handle IXON in the FEP */ -#define DIGI_FAST 0x0002 /* Fast baud rates */ -#define RTSPACE 0x0004 /* RTS input flow control */ -#define CTSPACE 0x0008 /* CTS output flow control */ -#define DSRPACE 0x0010 /* DSR output flow control */ -#define DCDPACE 0x0020 /* DCD output flow control */ -#define DTRPACE 0x0040 /* DTR input flow control */ -#define DIGI_COOK 0x0080 /* Cooked processing done in FEP */ -#define DIGI_FORCEDCD 0x0100 /* Force carrier */ -#define DIGI_ALTPIN 0x0200 /* Alternate RJ-45 pin config */ -#define DIGI_AIXON 0x0400 /* Aux flow control in fep */ -#define DIGI_PRINTER 0x0800 /* Hold port open for flow cntrl */ -#define DIGI_PP_INPUT 0x1000 /* Change parallel port to input */ -#define DIGI_422 0x4000 /* Change parallel port to input */ -#define DIGI_RTS_TOGGLE 0x8000 /* Support RTS Toggle */ - - -/************************************************************************ - * Values associated with transparent print - ************************************************************************/ -#define DIGI_PLEN 8 /* String length */ -#define DIGI_TSIZ 10 /* Terminal string len */ - - -/************************************************************************ - * Structure used with ioctl commands for DIGI parameters. - ************************************************************************/ -struct digi_struct { - unsigned short digi_flags; /* Flags (see above) */ - unsigned short digi_maxcps; /* Max printer CPS */ - unsigned short digi_maxchar; /* Max chars in print queue */ - unsigned short digi_bufsize; /* Buffer size */ - unsigned char digi_onlen; /* Length of ON string */ - unsigned char digi_offlen; /* Length of OFF string */ - char digi_onstr[DIGI_PLEN]; /* Printer on string */ - char digi_offstr[DIGI_PLEN]; /* Printer off string */ - char digi_term[DIGI_TSIZ]; /* terminal string */ -}; - -/************************************************************************ - * Ioctl command arguments for DIGI parameters. - ************************************************************************/ -/* Read params */ -#define DIGI_GETA _IOR('e', 94, struct digi_struct) - -/* Set params */ -#define DIGI_SETA _IOW('e', 95, struct digi_struct) - -/* Drain & set params */ -#define DIGI_SETAW _IOW('e', 96, struct digi_struct) - -/* Drain, flush & set params */ -#define DIGI_SETAF _IOW('e', 97, struct digi_struct) - -/* Get startc/stopc flow control characters */ -#define DIGI_GETFLOW _IOR('e', 99, struct digiflow_struct) - -/* Set startc/stopc flow control characters */ -#define DIGI_SETFLOW _IOW('e', 100, struct digiflow_struct) - -/* Get Aux. startc/stopc flow control chars */ -#define DIGI_GETAFLOW _IOR('e', 101, struct digiflow_struct) - -/* Set Aux. startc/stopc flow control chars */ -#define DIGI_SETAFLOW _IOW('e', 102, struct digiflow_struct) - -/* Set integer baud rate */ -#define DIGI_SETCUSTOMBAUD _IOW('e', 106, int) - -/* Get integer baud rate */ -#define DIGI_GETCUSTOMBAUD _IOR('e', 107, int) - -#define DIGI_GEDELAY _IOR('d', 246, int) /* Get edelay */ -#define DIGI_SEDELAY _IOW('d', 247, int) /* Get edelay */ - - -#endif /* _DIGIDRP_H */ diff --git a/trunk/drivers/staging/dgrp/drp.h b/trunk/drivers/staging/dgrp/drp.h deleted file mode 100644 index 84a1e7be4899..000000000000 --- a/trunk/drivers/staging/dgrp/drp.h +++ /dev/null @@ -1,693 +0,0 @@ -/* - * - * Copyright 1999 Digi International (www.digi.com) - * Gene Olson - * James Puzzo - * Scott Kilau - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the - * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR - * PURPOSE. See the GNU General Public License for more details. - * - */ - -/************************************************************************ - * Master include file for Linux Realport Driver. - ************************************************************************/ - -#ifndef __DRP_H -#define __DRP_H - -#include -#include -#include -#include - - -#include "digirp.h" - -/************************************************************************ - * Tuning parameters. - ************************************************************************/ - -#define CHAN_MAX 64 /* Max # ports per server */ - -#define SEQ_MAX 128 /* Max # transmit sequences (2^n) */ -#define SEQ_MASK (SEQ_MAX-1) /* Sequence buffer modulus mask */ - -#define TBUF_MAX 4096 /* Size of transmit buffer (2^n) */ -#define RBUF_MAX 4096 /* Size of receive buffer (2^n) */ - -#define TBUF_MASK (TBUF_MAX-1) /* Transmit buffer modulus mask */ -#define RBUF_MASK (RBUF_MAX-1) /* Receive buffer modulus mask */ - -#define TBUF_LOW 1000 /* Transmit low water mark */ - -#define UIO_BASE 1000 /* Base for write operations */ -#define UIO_MIN 2000 /* Minimum size application buffer */ -#define UIO_MAX 8100 /* Unix I/O buffer size */ - -#define MON_MAX 65536 /* Monitor buffer size (2^n) */ -#define MON_MASK (MON_MAX-1) /* Monitor wrap mask */ - -#define DPA_MAX 65536 /* DPA buffer size (2^n) */ -#define DPA_MASK (DPA_MAX-1) /* DPA wrap mask */ -#define DPA_HIGH_WATER 58000 /* Enforce flow control when - * over this amount - */ - -#define IDLE_MAX (20 * HZ) /* Max TCP link idle time */ - -#define MAX_DESC_LEN 100 /* Maximum length of stored PS - * description - */ - -#define WRITEBUFLEN ((4096) + 4) /* 4 extra for alignment play space */ - -#define VPDSIZE 512 - -/************************************************************************ - * Minor device decoding conventions. - ************************************************************************ - * - * For Linux, the net and mon devices are handled via "proc", so we - * only have to mux the "tty" devices. Since every PortServer will - * have an individual major number, the PortServer number does not - * need to be encoded, and in fact, does not need to exist. - * - */ - -/* - * Port device decoding conventions: - * - * Device 00 - 3f 64 dial-in modem devices. (tty) - * Device 40 - 7f 64 dial-out tty devices. (cu) - * Device 80 - bf 64 dial-out printer devices. - * - * IS_PRINT(dev) This is a printer device. - * - * OPEN_CATEGORY(dev) Specifies the device category. No two - * devices of different categories may be open - * at the same time. - * - * The following require the category returned by OPEN_CATEGORY(). - * - * OPEN_WAIT_AVAIL(cat) Waits on open until the device becomes - * available. Fails if NDELAY specified. - * - * OPEN_WAIT_CARRIER(cat) Waits on open if carrier is not present. - * Succeeds if NDELAY is given. - * - * OPEN_FORCES_CARRIER(cat) Carrier is forced high on open. - * - */ - -#define PORT_NUM(dev) ((dev) & 0x3f) - -#define OPEN_CATEGORY(dev) ((((dev) & 0x80) & 0x40)) -#define IS_PRINT(dev) (((dev) & 0xff) >= 0x80) - -#define OPEN_WAIT_AVAIL(cat) (((cat) & 0x40) == 0x000) -#define OPEN_WAIT_CARRIER(cat) (((cat) & 0x40) == 0x000) -#define OPEN_FORCES_CARRIER(cat) (((cat) & 0x40) != 0x000) - - -/************************************************************************ - * Modem signal defines for 16450/16550 compatible FEP. - * set in ch_mout, ch_mflow, ch_mlast etc - ************************************************************************/ - -/* TODO : Re-verify that these modem signal definitions are correct */ - -#define DM_DTR 0x01 -#define DM_RTS 0x02 -#define DM_RTS_TOGGLE 0x04 - -#define DM_OUT1 0x04 -#define DM_OUT2 0x08 - -#define DM_CTS 0x10 -#define DM_DSR 0x20 -#define DM_RI 0x40 -#define DM_CD 0x80 /* This is the DCD flag */ - - -/************************************************************************ - * Realport Event Flags. - ************************************************************************/ - -#define EV_OPU 0x0001 /* Ouput paused by client */ -#define EV_OPS 0x0002 /* Output paused by XOFF */ -#define EV_OPX 0x0004 /* Output paused by XXOFF */ -#define EV_OPH 0x0008 /* Output paused by MFLOW */ -#define EV_IPU 0x0010 /* Input paused by client */ -#define EV_IPS 0x0020 /* Input paused by hi/low water */ -#define EV_TXB 0x0040 /* Transmit break pending */ -#define EV_TXI 0x0080 /* Transmit immediate pending */ -#define EV_TXF 0x0100 /* Transmit flow control pending */ -#define EV_RXB 0x0200 /* Break received */ - - -/************************************************************************ - * Realport CFLAGS. - ************************************************************************/ - -#define CF_CS5 0x0000 /* 5 bit characters */ -#define CF_CS6 0x0010 /* 6 bit characters */ -#define CF_CS7 0x0020 /* 7 bit characters */ -#define CF_CS8 0x0030 /* 8 bit characters */ -#define CF_CSIZE 0x0030 /* Character size */ -#define CF_CSTOPB 0x0040 /* Two stop bits */ -#define CF_CREAD 0x0080 /* Enable receiver */ -#define CF_PARENB 0x0100 /* Enable parity */ -#define CF_PARODD 0x0200 /* Odd parity */ -#define CF_HUPCL 0x0400 /* Drop DTR on close */ - - -/************************************************************************ - * Realport XFLAGS. - ************************************************************************/ - -#define XF_XPAR 0x0001 /* Enable Mark/Space Parity */ -#define XF_XMODEM 0x0002 /* Enable in-band modem signalling */ -#define XF_XCASE 0x0004 /* Convert special characters */ -#define XF_XEDATA 0x0008 /* Error data in stream */ -#define XF_XTOSS 0x0010 /* Toss IXANY characters */ -#define XF_XIXON 0x0020 /* xxon/xxoff enable */ - - -/************************************************************************ - * Realport IFLAGS. - ************************************************************************/ - -#define IF_IGNBRK 0x0001 /* Ignore input break */ -#define IF_BRKINT 0x0002 /* Break interrupt */ -#define IF_IGNPAR 0x0004 /* Ignore error characters */ -#define IF_PARMRK 0x0008 /* Error chars marked with 0xff */ -#define IF_INPCK 0x0010 /* Input parity checking enabled */ -#define IF_ISTRIP 0x0020 /* Input chars masked with 0x7F */ -#define IF_IXON 0x0400 /* Output software flow control */ -#define IF_IXANY 0x0800 /* Restart output on any char */ -#define IF_IXOFF 0x1000 /* Input software flow control */ -#define IF_DOSMODE 0x8000 /* 16450-compatible errors */ - - -/************************************************************************ - * Realport OFLAGS. - ************************************************************************/ - -#define OF_OLCUC 0x0002 /* Map lower to upper case */ -#define OF_ONLCR 0x0004 /* Map NL to CR-NL */ -#define OF_OCRNL 0x0008 /* Map CR to NL */ -#define OF_ONOCR 0x0010 /* No CR output at column 0 */ -#define OF_ONLRET 0x0020 /* Assume NL does NL/CR */ -#define OF_TAB3 0x1800 /* Tabs expand to 8 spaces */ -#define OF_TABDLY 0x1800 /* Tab delay */ - -/************************************************************************ - * Unit flag definitions for un_flag. - ************************************************************************/ - -/* These are the DIGI unit flags */ -#define UN_EXCL 0x00010000 /* Exclusive open */ -#define UN_STICKY 0x00020000 /* TTY Settings are now sticky */ -#define UN_BUSY 0x00040000 /* Some work this channel */ -#define UN_PWAIT 0x00080000 /* Printer waiting for terminal */ -#define UN_TIME 0x00100000 /* Waiting on time */ -#define UN_EMPTY 0x00200000 /* Waiting output queue empty */ -#define UN_LOW 0x00400000 /* Waiting output low water */ -#define UN_DIGI_MASK 0x00FF0000 /* Waiting output low water */ - -/* - * Definitions for async_struct (and serial_struct) flags field - * - * these are the ASYNC flags copied from serial.h - * - */ -#define UN_HUP_NOTIFY 0x0001 /* Notify getty on hangups and - * closes on the callout port - */ -#define UN_FOURPORT 0x0002 /* Set OU1, OUT2 per AST Fourport settings */ -#define UN_SAK 0x0004 /* Secure Attention Key (Orange book) */ -#define UN_SPLIT_TERMIOS 0x0008 /* Separate termios for dialin/callout */ - -#define UN_SPD_MASK 0x0030 -#define UN_SPD_HI 0x0010 /* Use 56000 instead of 38400 bps */ -#define UN_SPD_VHI 0x0020 /* Use 115200 instead of 38400 bps */ -#define UN_SPD_CUST 0x0030 /* Use user-specified divisor */ - -#define UN_SKIP_TEST 0x0040 /* Skip UART test during autoconfiguration */ -#define UN_AUTO_IRQ 0x0080 /* Do automatic IRQ during autoconfiguration */ - -#define UN_SESSION_LOCKOUT 0x0100 /* Lock out cua opens based on session */ -#define UN_PGRP_LOCKOUT 0x0200 /* Lock out cua opens based on pgrp */ -#define UN_CALLOUT_NOHUP 0x0400 /* Don't do hangups for cua device */ - -#define UN_FLAGS 0x0FFF /* Possible legal async flags */ -#define UN_USR_MASK 0x0430 /* Legal flags that non-privileged - * users can set or reset - */ - -#define UN_INITIALIZED 0x80000000 /* Serial port was initialized */ -#define UN_CALLOUT_ACTIVE 0x40000000 /* Call out device is active */ -#define UN_NORMAL_ACTIVE 0x20000000 /* Normal device is active */ -#define UN_BOOT_AUTOCONF 0x10000000 /* Autoconfigure port on bootup */ -#define UN_CLOSING 0x08000000 /* Serial port is closing */ -#define UN_CTS_FLOW 0x04000000 /* Do CTS flow control */ -#define UN_CHECK_CD 0x02000000 /* i.e., CLOCAL */ -#define UN_SHARE_IRQ 0x01000000 /* for multifunction cards */ - - -/************************************************************************ - * Structure for terminal or printer unit. struct un_struct - * - * Note that in some places the code assumes the "tty_t" is placed - * first in the structure. - ************************************************************************/ - -struct un_struct { - struct tty_struct *un_tty; /* System TTY struct */ - struct ch_struct *un_ch; /* Associated channel */ - - ushort un_open_count; /* Successful open count */ - int un_flag; /* Unit flags */ - ushort un_tbusy; /* Busy transmit count */ - - wait_queue_head_t un_open_wait; - wait_queue_head_t un_close_wait; - ushort un_type; - struct device *un_sysfs; -}; - - -/************************************************************************ - * Channel State Numbers for ch_state. - ************************************************************************/ - -/* - * The ordering is important. - * - * state <= CS_WAIT_CANCEL implies the channel is definitely closed. - * - * state >= CS_WAIT_FAIL implies the channel is definitely open. - * - * state >= CS_READY implies data is allowed on the channel. - */ - -enum dgrp_ch_state_t { - CS_IDLE = 0, /* Channel is idle */ - CS_WAIT_OPEN = 1, /* Waiting for Immediate Open Resp */ - CS_WAIT_CANCEL = 2, /* Waiting for Per/Incom Cancel Resp */ - CS_WAIT_FAIL = 3, /* Waiting for Immed Open Failure */ - CS_SEND_QUERY = 4, /* Ready to send Port Query */ - CS_WAIT_QUERY = 5, /* Waiting for Port Query Response */ - CS_READY = 6, /* Ready to accept commands and data */ - CS_SEND_CLOSE = 7, /* Ready to send Close Request */ - CS_WAIT_CLOSE = 8 /* Waiting for Close Response */ -}; - -/************************************************************************ - * Device flag definitions for ch_flag. - ************************************************************************/ - -/* - * Note that the state of the two carrier based flags is key. When - * we check for carrier state transitions, we look at the current - * physical state of the DCD line and compare it with PHYS_CD (which - * was the state the last time we checked), and we also determine - * a new virtual state (composite of the physical state, FORCEDCD, - * CLOCAL, etc.) and compare it with VIRT_CD. - * - * VIRTUAL transitions high will have the side effect of waking blocked - * opens. - * - * PHYSICAL transitions low will cause hangups to occur _IF_ the virtual - * state is also low. We DON'T want to hangup on a PURE virtual drop. - */ - -#define CH_HANGUP 0x00002 /* Server port ready to close */ - -#define CH_VIRT_CD 0x00004 /* Carrier was virtually present */ -#define CH_PHYS_CD 0x00008 /* Carrier was physically present */ - -#define CH_CLOCAL 0x00010 /* CLOCAL set in cflags */ -#define CH_BAUD0 0x00020 /* Baud rate zero hangup */ - -#define CH_FAST_READ 0x00040 /* Fast reads are enabled */ -#define CH_FAST_WRITE 0x00080 /* Fast writes are enabled */ - -#define CH_PRON 0x00100 /* Printer on string active */ -#define CH_RX_FLUSH 0x00200 /* Flushing receive data */ -#define CH_LOW 0x00400 /* Thread waiting for LOW water */ -#define CH_EMPTY 0x00800 /* Thread waiting for EMPTY */ -#define CH_DRAIN 0x01000 /* Close is waiting to drain */ -#define CH_INPUT 0x02000 /* Thread waiting for INPUT */ -#define CH_RXSTOP 0x04000 /* Stop output to ldisc */ -#define CH_PARAM 0x08000 /* A parameter was updated */ -#define CH_WAITING_SYNC 0x10000 /* A pending sync was assigned - * to this port. - */ -#define CH_PORT_GONE 0x20000 /* Port has disappeared */ -#define CH_TX_BREAK 0x40000 /* TX Break to be sent, - * but has not yet. - */ - -/************************************************************************ - * Types of Open Requests for ch_otype. - ************************************************************************/ - -#define OTYPE_IMMEDIATE 0 /* Immediate Open */ -#define OTYPE_PERSISTENT 1 /* Persistent Open */ -#define OTYPE_INCOMING 2 /* Incoming Open */ - - -/************************************************************************ - * Request/Response flags. - ************************************************************************/ - -#define RR_SEQUENCE 0x0001 /* Get server RLAST, TIN */ -#define RR_STATUS 0x0002 /* Get server MINT, EINT */ -#define RR_BUFFER 0x0004 /* Get server RSIZE, TSIZE */ -#define RR_CAPABILITY 0x0008 /* Get server port capabilities */ - -#define RR_TX_FLUSH 0x0040 /* Flush output buffers */ -#define RR_RX_FLUSH 0x0080 /* Flush input buffers */ - -#define RR_TX_STOP 0x0100 /* Pause output */ -#define RR_RX_STOP 0x0200 /* Pause input */ -#define RR_TX_START 0x0400 /* Start output */ -#define RR_RX_START 0x0800 /* Start input */ - -#define RR_TX_BREAK 0x1000 /* Send BREAK */ -#define RR_TX_ICHAR 0x2000 /* Send character immediate */ - - -/************************************************************************ - * Channel information structure. struct ch_struct - ************************************************************************/ - -struct ch_struct { - struct digi_struct ch_digi; /* Digi variables */ - int ch_edelay; /* Digi edelay */ - - struct tty_port port; - struct un_struct ch_tun; /* Terminal unit info */ - struct un_struct ch_pun; /* Printer unit info */ - - struct nd_struct *ch_nd; /* Node pointer */ - u8 *ch_tbuf; /* Local Transmit Buffer */ - u8 *ch_rbuf; /* Local Receive Buffer */ - ulong ch_cpstime; /* Printer CPS time */ - ulong ch_waketime; /* Printer wake time */ - - ulong ch_flag; /* CH_* flags */ - - enum dgrp_ch_state_t ch_state; /* CS_* Protocol state */ - ushort ch_send; /* Bit vector of RR_* requests */ - ushort ch_expect; /* Bit vector of RR_* responses */ - ushort ch_wait_carrier; /* Thread count waiting for carrier */ - ushort ch_wait_count[3]; /* Thread count waiting by otype */ - - ushort ch_portnum; /* Port number */ - ushort ch_open_count; /* Successful open count */ - ushort ch_category; /* Device category */ - ushort ch_open_error; /* Last open error number */ - ushort ch_break_time; /* Pending break request time */ - ushort ch_cpsrem; /* Printer CPS remainder */ - ushort ch_ocook; /* Realport fastcook oflags */ - ushort ch_inwait; /* Thread count in CLIST input */ - - ushort ch_tin; /* Local transmit buffer in ptr */ - ushort ch_tout; /* Local transmit buffer out ptr */ - ushort ch_s_tin; /* Realport TIN */ - ushort ch_s_tpos; /* Realport TPOS */ - ushort ch_s_tsize; /* Realport TSIZE */ - ushort ch_s_treq; /* Realport TREQ */ - ushort ch_s_elast; /* Realport ELAST */ - - ushort ch_rin; /* Local receive buffer in ptr */ - ushort ch_rout; /* Local receive buffer out ptr */ - ushort ch_s_rin; /* Realport RIN */ - /* David Fries 7-13-2001, ch_s_rin should be renamed ch_s_rout because - * the variable we want to represent is the PortServer's ROUT, which is - * the sequence number for the next byte the PortServer will send us. - * RIN is the sequence number for the next byte the PortServer will - * receive from the uart. The port server will send data as long as - * ROUT is less than RWIN. What would happen is the port is opened, it - * receives data, it gives the value of RIN, we set the RWIN to - * RIN+RBUF_MAX-1, it sends us RWIN-ROUT bytes which overflows. ROUT - * is set to zero when the port is opened, so we start at zero and - * count up as data is received. - */ - ushort ch_s_rwin; /* Realport RWIN */ - ushort ch_s_rsize; /* Realport RSIZE */ - - ushort ch_tmax; /* Local TMAX */ - ushort ch_ttime; /* Local TTIME */ - ushort ch_rmax; /* Local RMAX */ - ushort ch_rtime; /* Local RTIME */ - ushort ch_rlow; /* Local RLOW */ - ushort ch_rhigh; /* Local RHIGH */ - - ushort ch_s_tmax; /* Realport TMAX */ - ushort ch_s_ttime; /* Realport TTIME */ - ushort ch_s_rmax; /* Realport RMAX */ - ushort ch_s_rtime; /* Realport RTIME */ - ushort ch_s_rlow; /* Realport RLOW */ - ushort ch_s_rhigh; /* Realport RHIGH */ - - ushort ch_brate; /* Local baud rate */ - ushort ch_cflag; /* Local tty cflags */ - ushort ch_iflag; /* Local tty iflags */ - ushort ch_oflag; /* Local tty oflags */ - ushort ch_xflag; /* Local tty xflags */ - - ushort ch_s_brate; /* Realport BRATE */ - ushort ch_s_cflag; /* Realport CFLAG */ - ushort ch_s_iflag; /* Realport IFLAG */ - ushort ch_s_oflag; /* Realport OFLAG */ - ushort ch_s_xflag; /* Realport XFLAG */ - - u8 ch_otype; /* Open request type */ - u8 ch_pscan_savechar; /* Last character read by parity scan */ - u8 ch_pscan_state; /* PScan State based on last 2 chars */ - u8 ch_otype_waiting; /* Type of open pending in server */ - u8 ch_flush_seq; /* Receive flush end sequence */ - u8 ch_s_mlast; /* Realport MLAST */ - - u8 ch_mout; /* Local MOUT */ - u8 ch_mflow; /* Local MFLOW */ - u8 ch_mctrl; /* Local MCTRL */ - u8 ch_xon; /* Local XON */ - u8 ch_xoff; /* Local XOFF */ - u8 ch_lnext; /* Local LNEXT */ - u8 ch_xxon; /* Local XXON */ - u8 ch_xxoff; /* Local XXOFF */ - - u8 ch_s_mout; /* Realport MOUT */ - u8 ch_s_mflow; /* Realport MFLOW */ - u8 ch_s_mctrl; /* Realport MCTRL */ - u8 ch_s_xon; /* Realport XON */ - u8 ch_s_xoff; /* Realport XOFF */ - u8 ch_s_lnext; /* Realport LNEXT */ - u8 ch_s_xxon; /* Realport XXON */ - u8 ch_s_xxoff; /* Realport XXOFF */ - - wait_queue_head_t ch_flag_wait; /* Wait queue for ch_flag changes */ - wait_queue_head_t ch_sleep; /* Wait queue for my_sleep() */ - - int ch_custom_speed; /* Realport custom speed */ - int ch_txcount; /* Running TX count */ - int ch_rxcount; /* Running RX count */ -}; - - -/************************************************************************ - * Node State definitions. - ************************************************************************/ - -enum dgrp_nd_state_t { - NS_CLOSED = 0, /* Network device is closed */ - NS_IDLE = 1, /* Network connection inactive */ - NS_SEND_QUERY = 2, /* Send server query */ - NS_WAIT_QUERY = 3, /* Wait for query response */ - NS_READY = 4, /* Network ready */ - NS_SEND_ERROR = 5 /* Must send error hangup */ -}; - -#define ND_STATE_STR(x) \ - ((x) == NS_CLOSED ? "CLOSED" : \ - ((x) == NS_IDLE ? "IDLE" : \ - ((x) == NS_SEND_QUERY ? "SEND_QUERY" : \ - ((x) == NS_WAIT_QUERY ? "WAIT_QUERY" : \ - ((x) == NS_READY ? "READY" : \ - ((x) == NS_SEND_ERROR ? "SEND_ERROR" : "UNKNOWN")))))) - -/************************************************************************ - * Node Flag definitions. - ************************************************************************/ - -#define ND_SELECT 0x0001 /* Multiple net read selects */ -#define ND_DEB_WAIT 0x0002 /* Debug Device waiting */ - - -/************************************************************************ - * Monitoring flag definitions. - ************************************************************************/ - -#define MON_WAIT_DATA 0x0001 /* Waiting for buffer data */ -#define MON_WAIT_SPACE 0x0002 /* Waiting for buffer space */ - -/************************************************************************ - * DPA flag definitions. - ************************************************************************/ - -#define DPA_WAIT_DATA 0x0001 /* Waiting for buffer data */ -#define DPA_WAIT_SPACE 0x0002 /* Waiting for buffer space */ - - -/************************************************************************ - * Definitions taken from Realport Dump. - ************************************************************************/ - -#define RPDUMP_MAGIC "Digi-RealPort-1.0" - -#define RPDUMP_MESSAGE 0xE2 /* Descriptive message */ -#define RPDUMP_RESET 0xE7 /* Connection reset */ -#define RPDUMP_CLIENT 0xE8 /* Client data */ -#define RPDUMP_SERVER 0xE9 /* Server data */ - - -/************************************************************************ - * Node request/response definitions. - ************************************************************************/ - -#define NR_ECHO 0x0001 /* Server echo packet */ -#define NR_IDENT 0x0002 /* Server Product ID */ -#define NR_CAPABILITY 0x0004 /* Server Capabilties */ -#define NR_VPD 0x0008 /* Server VPD, if any */ -#define NR_PASSWORD 0x0010 /* Server Password */ - -/************************************************************************ - * Registration status of the node's Linux struct tty_driver structures. - ************************************************************************/ -#define SERIAL_TTDRV_REG 0x0001 /* nd_serial_ttdriver registered */ -#define CALLOUT_TTDRV_REG 0x0002 /* nd_callout_ttdriver registered */ -#define XPRINT_TTDRV_REG 0x0004 /* nd_xprint_ttdriver registered */ - - -/************************************************************************ - * Node structure. There exists one of these for each associated - * realport server. - ************************************************************************/ - -struct nd_struct { - struct list_head list; - long nd_major; /* Node's major number */ - long nd_ID; /* Node's ID code */ - - char nd_serial_name[50]; /* "tty_dgrp__" + null */ - char nd_callout_name[50]; /* "cu_dgrp__" + null */ - char nd_xprint_name[50]; /* "pr_dgrp__" + null */ - - char password[16]; /* Password for server, if needed */ - int nd_tty_ref_cnt; /* Linux tty reference count */ - - struct proc_dir_entry *nd_net_de; /* Dir entry for /proc/dgrp/net */ - struct proc_dir_entry *nd_mon_de; /* Dir entry for /proc/dgrp/mon */ - struct proc_dir_entry *nd_ports_de; /* Dir entry for /proc/dgrp/ports*/ - struct proc_dir_entry *nd_dpa_de; /* Dir entry for /proc/dgrp/dpa */ - - spinlock_t nd_lock; /* General node lock */ - - struct semaphore nd_net_semaphore; /* Net read/write lock */ - struct semaphore nd_mon_semaphore; /* Monitor buffer lock */ - spinlock_t nd_dpa_lock; /* DPA buffer lock */ - - enum dgrp_nd_state_t nd_state; /* NS_* network state */ - int nd_chan_count; /* # active channels */ - int nd_flag; /* Node flags */ - int nd_send; /* Responses to send */ - int nd_expect; /* Responses we expect */ - - u8 *nd_iobuf; /* Network R/W Buffer */ - wait_queue_head_t nd_tx_waitq; /* Network select wait queue */ - - u8 *nd_inputbuf; /* Input Buffer */ - u8 *nd_inputflagbuf; /* Input Flags Buffer */ - - int nd_tx_deposit; /* Accumulated transmit deposits */ - int nd_tx_charge; /* Accumulated transmit charges */ - int nd_tx_credit; /* Current TX credit */ - int nd_tx_ready; /* Ready to transmit */ - int nd_tx_work; /* TX work waiting */ - ulong nd_tx_time; /* Last transmit time */ - ulong nd_poll_time; /* Next scheduled poll time */ - - int nd_delay; /* Current TX delay */ - int nd_rate; /* Current TX rate */ - struct link_struct nd_link; /* Link speed params. */ - - int nd_seq_in; /* TX seq in ptr */ - int nd_seq_out; /* TX seq out ptr */ - int nd_unack; /* Unacknowledged byte count */ - int nd_remain; /* Remaining receive bytes */ - int nd_tx_module; /* Current TX module # */ - int nd_rx_module; /* Current RX module # */ - char *nd_error; /* Protocol error message */ - - int nd_write_count; /* drp_write() call count */ - int nd_read_count; /* drp_read() count */ - int nd_send_count; /* TCP message sent */ - int nd_tx_byte; /* Transmit byte count */ - int nd_rx_byte; /* Receive byte count */ - - ulong nd_mon_lbolt; /* Monitor start time */ - int nd_mon_flag; /* Monitor flags */ - int nd_mon_in; /* Monitor in pointer */ - int nd_mon_out; /* Monitor out pointer */ - wait_queue_head_t nd_mon_wqueue; /* Monitor wait queue (on flags) */ - u8 *nd_mon_buf; /* Monitor buffer */ - - ulong nd_dpa_lbolt; /* DPA start time */ - int nd_dpa_flag; /* DPA flags */ - int nd_dpa_in; /* DPA in pointer */ - int nd_dpa_out; /* DPA out pointer */ - wait_queue_head_t nd_dpa_wqueue; /* DPA wait queue (on flags) */ - u8 *nd_dpa_buf; /* DPA buffer */ - - uint nd_dpa_debug; - uint nd_dpa_port; - - wait_queue_head_t nd_seq_wque[SEQ_MAX]; /* TX thread wait queues */ - u8 nd_seq_wait[SEQ_MAX]; /* Transmit thread wait count */ - - ushort nd_seq_size[SEQ_MAX]; /* Transmit seq packet size */ - ulong nd_seq_time[SEQ_MAX]; /* Transmit seq packet time */ - - ushort nd_hw_ver; /* HW version returned from PS */ - ushort nd_sw_ver; /* SW version returned from PS */ - uint nd_hw_id; /* HW ID returned from PS */ - u8 nd_ps_desc[MAX_DESC_LEN+1]; /* Description from PS */ - uint nd_vpd_len; /* VPD len, if any */ - u8 nd_vpd[VPDSIZE]; /* VPD, if any */ - - ulong nd_ttdriver_flags; /* Registration status */ - struct tty_driver *nd_serial_ttdriver; /* Linux TTYDRIVER structure */ - struct tty_driver *nd_callout_ttdriver; /* Linux TTYDRIVER structure */ - struct tty_driver *nd_xprint_ttdriver; /* Linux TTYDRIVER structure */ - - u8 *nd_writebuf; /* Used to cache data read - * from user - */ - struct ch_struct nd_chan[CHAN_MAX]; /* Channel array */ - struct device *nd_class_dev; /* Hang our sysfs stuff off of here */ -}; - -#endif /* __DRP_H */ diff --git a/trunk/drivers/staging/et131x/et131x.c b/trunk/drivers/staging/et131x/et131x.c index 413da0d6b9f6..029725c89e58 100644 --- a/trunk/drivers/staging/et131x/et131x.c +++ b/trunk/drivers/staging/et131x/et131x.c @@ -3955,7 +3955,12 @@ static void et131x_hwaddr_init(struct et131x_adapter *adapter) * EEPROM then we need to generate the last octet and set it on the * device */ - if (is_zero_ether_addr(adapter->rom_addr)) { + if (adapter->rom_addr[0] == 0x00 && + adapter->rom_addr[1] == 0x00 && + adapter->rom_addr[2] == 0x00 && + adapter->rom_addr[3] == 0x00 && + adapter->rom_addr[4] == 0x00 && + adapter->rom_addr[5] == 0x00) { /* * We need to randomly generate the last octet so we * decrease our chances of setting the mac address to @@ -3990,14 +3995,16 @@ static void et131x_hwaddr_init(struct et131x_adapter *adapter) static int et131x_pci_init(struct et131x_adapter *adapter, struct pci_dev *pdev) { + int cap = pci_pcie_cap(pdev); u16 max_payload; + u16 ctl; int i, rc; rc = et131x_init_eeprom(adapter); if (rc < 0) goto out; - if (!pci_is_pcie(pdev)) { + if (!cap) { dev_err(&pdev->dev, "Missing PCIe capabilities\n"); goto err_out; } @@ -4005,7 +4012,7 @@ static int et131x_pci_init(struct et131x_adapter *adapter, /* Let's set up the PORT LOGIC Register. First we need to know what * the max_payload_size is */ - if (pcie_capability_read_word(pdev, PCI_EXP_DEVCAP, &max_payload)) { + if (pci_read_config_word(pdev, cap + PCI_EXP_DEVCAP, &max_payload)) { dev_err(&pdev->dev, "Could not read PCI config space for Max Payload Size\n"); goto err_out; @@ -4042,10 +4049,17 @@ static int et131x_pci_init(struct et131x_adapter *adapter, } /* Change the max read size to 2k */ - if (pcie_capability_clear_and_set_word(pdev, PCI_EXP_DEVCTL, - PCI_EXP_DEVCTL_READRQ, 0x4 << 12)) { + if (pci_read_config_word(pdev, cap + PCI_EXP_DEVCTL, &ctl)) { dev_err(&pdev->dev, - "Couldn't change PCI config space for Max read size\n"); + "Could not read PCI config space for Max read size\n"); + goto err_out; + } + + ctl = (ctl & ~PCI_EXP_DEVCTL_READRQ) | (0x04 << 12); + + if (pci_write_config_word(pdev, cap + PCI_EXP_DEVCTL, ctl)) { + dev_err(&pdev->dev, + "Could not write PCI config space for Max read size\n"); goto err_out; } diff --git a/trunk/drivers/staging/ft1000/ft1000-pcmcia/ft1000_dnld.c b/trunk/drivers/staging/ft1000/ft1000-pcmcia/ft1000_dnld.c index 47cc365c630b..f8b8e71284d9 100644 --- a/trunk/drivers/staging/ft1000/ft1000-pcmcia/ft1000_dnld.c +++ b/trunk/drivers/staging/ft1000/ft1000-pcmcia/ft1000_dnld.c @@ -94,27 +94,27 @@ void put_request_value(struct net_device *dev, long lvalue); u16 hdr_checksum(struct pseudo_hdr *pHdr); struct dsp_file_hdr { - u32 version_id; /* Version ID of this image format. */ - u32 package_id; /* Package ID of code release. */ - u32 build_date; /* Date/time stamp when file was built. */ - u32 commands_offset; /* Offset to attached commands in Pseudo Hdr format. */ - u32 loader_offset; /* Offset to bootloader code. */ - u32 loader_code_address; /* Start address of bootloader. */ - u32 loader_code_end; /* Where bootloader code ends. */ + u32 version_id; // Version ID of this image format. + u32 package_id; // Package ID of code release. + u32 build_date; // Date/time stamp when file was built. + u32 commands_offset; // Offset to attached commands in Pseudo Hdr format. + u32 loader_offset; // Offset to bootloader code. + u32 loader_code_address; // Start address of bootloader. + u32 loader_code_end; // Where bootloader code ends. u32 loader_code_size; - u32 version_data_offset; /* Offset were scrambled version data begins. */ - u32 version_data_size; /* Size, in words, of scrambled version data. */ - u32 nDspImages; /* Number of DSP images in file. */ + u32 version_data_offset; // Offset were scrambled version data begins. + u32 version_data_size; // Size, in words, of scrambled version data. + u32 nDspImages; // Number of DSP images in file. } __attribute__ ((packed)); struct dsp_image_info { - u32 coff_date; /* Date/time when DSP Coff image was built. */ - u32 begin_offset; /* Offset in file where image begins. */ - u32 end_offset; /* Offset in file where image begins. */ - u32 run_address; /* On chip Start address of DSP code. */ - u32 image_size; /* Size of image. */ - u32 version; /* Embedded version # of DSP code. */ - unsigned short checksum; /* Dsp File checksum */ + u32 coff_date; // Date/time when DSP Coff image was built. + u32 begin_offset; // Offset in file where image begins. + u32 end_offset; // Offset in file where image begins. + u32 run_address; // On chip Start address of DSP code. + u32 image_size; // Size of image. + u32 version; // Embedded version # of DSP code. + unsigned short checksum; // Dsp File checksum unsigned short pad1; } __attribute__ ((packed)); diff --git a/trunk/drivers/staging/ft1000/ft1000-usb/ft1000_hw.c b/trunk/drivers/staging/ft1000/ft1000-usb/ft1000_hw.c index 809fa4886961..31929ef5332d 100644 --- a/trunk/drivers/staging/ft1000/ft1000-usb/ft1000_hw.c +++ b/trunk/drivers/staging/ft1000/ft1000-usb/ft1000_hw.c @@ -73,7 +73,7 @@ static int ft1000_control(struct ft1000_device *ft1000dev, unsigned int pipe, } ret = usb_control_msg(ft1000dev->dev, pipe, request, requesttype, - value, index, data, size, timeout); + value, index, data, size, LARGE_TIMEOUT); if (ret > 0) ret = 0; @@ -110,7 +110,7 @@ int ft1000_read_register(struct ft1000_device *ft1000dev, u16* Data, nRegIndx, Data, 2, - USB_CTRL_GET_TIMEOUT); + LARGE_TIMEOUT); return ret; } @@ -143,7 +143,7 @@ int ft1000_write_register(struct ft1000_device *ft1000dev, u16 value, nRegIndx, NULL, 0, - USB_CTRL_SET_TIMEOUT); + LARGE_TIMEOUT); return ret; } @@ -178,7 +178,7 @@ int ft1000_read_dpram32(struct ft1000_device *ft1000dev, u16 indx, u8 *buffer, indx, buffer, cnt, - USB_CTRL_GET_TIMEOUT); + LARGE_TIMEOUT); return ret; } @@ -215,7 +215,7 @@ int ft1000_write_dpram32(struct ft1000_device *ft1000dev, u16 indx, u8 *buffer, indx, buffer, cnt, - USB_CTRL_SET_TIMEOUT); + LARGE_TIMEOUT); return ret; } @@ -255,7 +255,7 @@ int ft1000_read_dpram16(struct ft1000_device *ft1000dev, u16 indx, u8 *buffer, indx, buffer, 2, - USB_CTRL_GET_TIMEOUT); + LARGE_TIMEOUT); return ret; } @@ -294,7 +294,7 @@ int ft1000_write_dpram16(struct ft1000_device *ft1000dev, u16 indx, u16 value, u indx, NULL, 0, - USB_CTRL_SET_TIMEOUT); + LARGE_TIMEOUT); return ret; } diff --git a/trunk/drivers/staging/ft1000/ft1000-usb/ft1000_usb.h b/trunk/drivers/staging/ft1000/ft1000-usb/ft1000_usb.h index 2aa6a1c7fd38..642bb89942f5 100644 --- a/trunk/drivers/staging/ft1000/ft1000-usb/ft1000_usb.h +++ b/trunk/drivers/staging/ft1000/ft1000-usb/ft1000_usb.h @@ -36,6 +36,8 @@ struct app_info_block { #define FT1000_STATUS_CLOSING 0x01 +#define LARGE_TIMEOUT 5000 + #define DSPBCMSGID 0x10 /* Electrabuzz specific DPRAM mapping */ diff --git a/trunk/drivers/staging/gdm72xx/gdm_qos.c b/trunk/drivers/staging/gdm72xx/gdm_qos.c index e26c6a8b2627..80bde053fbc2 100644 --- a/trunk/drivers/staging/gdm72xx/gdm_qos.c +++ b/trunk/drivers/staging/gdm72xx/gdm_qos.c @@ -106,8 +106,8 @@ void gdm_qos_init(void *nic_ptr) for (i = 0 ; i < QOS_MAX; i++) { INIT_LIST_HEAD(&qcb->qos_list[i]); - qcb->csr[i].qos_buf_count = 0; - qcb->csr[i].enabled = 0; + qcb->csr[i].QoSBufCount = 0; + qcb->csr[i].Enabled = 0; } qcb->qos_list_cnt = 0; @@ -133,8 +133,8 @@ void gdm_qos_release_list(void *nic_ptr) spin_lock_irqsave(&qcb->qos_lock, flags); for (i = 0; i < QOS_MAX; i++) { - qcb->csr[i].qos_buf_count = 0; - qcb->csr[i].enabled = 0; + qcb->csr[i].QoSBufCount = 0; + qcb->csr[i].Enabled = 0; } qcb->qos_list_cnt = 0; @@ -153,42 +153,42 @@ static u32 chk_ipv4_rule(struct gdm_wimax_csr_s *csr, u8 *Stream, u8 *port) { int i; - if (csr->classifier_rule_en&IPTYPEOFSERVICE) { - if (((Stream[1] & csr->ip2s_mask) < csr->ip2s_lo) || - ((Stream[1] & csr->ip2s_mask) > csr->ip2s_hi)) + if (csr->ClassifierRuleEnable&IPTYPEOFSERVICE) { + if (((Stream[1] & csr->IPToSMask) < csr->IPToSLow) || + ((Stream[1] & csr->IPToSMask) > csr->IPToSHigh)) return 1; } - if (csr->classifier_rule_en&PROTOCOL) { - if (Stream[9] != csr->protocol) + if (csr->ClassifierRuleEnable&PROTOCOL) { + if (Stream[9] != csr->Protocol) return 1; } - if (csr->classifier_rule_en&IPMASKEDSRCADDRESS) { + if (csr->ClassifierRuleEnable&IPMASKEDSRCADDRESS) { for (i = 0; i < 4; i++) { - if ((Stream[12 + i] & csr->ipsrc_addrmask[i]) != - (csr->ipsrc_addr[i] & csr->ipsrc_addrmask[i])) + if ((Stream[12 + i] & csr->IPSrcAddrMask[i]) != + (csr->IPSrcAddr[i] & csr->IPSrcAddrMask[i])) return 1; } } - if (csr->classifier_rule_en&IPMASKEDDSTADDRESS) { + if (csr->ClassifierRuleEnable&IPMASKEDDSTADDRESS) { for (i = 0; i < 4; i++) { - if ((Stream[16 + i] & csr->ipdst_addrmask[i]) != - (csr->ipdst_addr[i] & csr->ipdst_addrmask[i])) + if ((Stream[16 + i] & csr->IPDstAddrMask[i]) != + (csr->IPDstAddr[i] & csr->IPDstAddrMask[i])) return 1; } } - if (csr->classifier_rule_en&PROTOCOLSRCPORTRANGE) { + if (csr->ClassifierRuleEnable&PROTOCOLSRCPORTRANGE) { i = ((port[0]<<8)&0xff00)+port[1]; - if ((i < csr->srcport_lo) || (i > csr->srcport_hi)) + if ((i < csr->SrcPortLow) || (i > csr->SrcPortHigh)) return 1; } - if (csr->classifier_rule_en&PROTOCOLDSTPORTRANGE) { + if (csr->ClassifierRuleEnable&PROTOCOLDSTPORTRANGE) { i = ((port[2]<<8)&0xff00)+port[3]; - if ((i < csr->dstport_lo) || (i > csr->dstport_hi)) + if ((i < csr->DstPortLow) || (i > csr->DstPortHigh)) return 1; } @@ -208,8 +208,8 @@ static u32 get_qos_index(struct nic *nic, u8 *iph, u8 *tcpudph) if (IP_Ver == 4) { for (i = 0; i < QOS_MAX; i++) { - if (qcb->csr[i].enabled) { - if (qcb->csr[i].classifier_rule_en) { + if (qcb->csr[i].Enabled) { + if (qcb->csr[i].ClassifierRuleEnable) { if (chk_ipv4_rule(&qcb->csr[i], iph, tcpudph) == 0) return i; @@ -230,14 +230,14 @@ static u32 extract_qos_list(struct nic *nic, struct list_head *head) INIT_LIST_HEAD(head); for (i = 0; i < QOS_MAX; i++) { - if (qcb->csr[i].enabled) { - if (qcb->csr[i].qos_buf_count < qcb->qos_limit_size) { + if (qcb->csr[i].Enabled) { + if (qcb->csr[i].QoSBufCount < qcb->qos_limit_size) { if (!list_empty(&qcb->qos_list[i])) { entry = list_entry( qcb->qos_list[i].prev, struct qos_entry_s, list); list_move_tail(&entry->list, head); - qcb->csr[i].qos_buf_count++; + qcb->csr[i].QoSBufCount++; if (!list_empty(&qcb->qos_list[i])) wprintk("QoS Index(%d) is piled!!\n", i); @@ -322,8 +322,8 @@ static u32 get_csr(struct qos_cb_s *qcb, u32 SFID, int mode) if (mode) { for (i = 0; i < QOS_MAX; i++) { - if (qcb->csr[i].enabled == 0) { - qcb->csr[i].enabled = 1; + if (qcb->csr[i].Enabled == 0) { + qcb->csr[i].Enabled = 1; qcb->qos_list_cnt++; return i; } @@ -365,7 +365,7 @@ void gdm_recv_qos_hci_packet(void *nic_ptr, u8 *buf, int size) eprintk("QoS ERROR: No SF\n"); return; } - qcb->csr[index].qos_buf_count = buf[(i*5)+10]; + qcb->csr[index].QoSBufCount = buf[(i*5)+10]; } extract_qos_list(nic, &send_list); @@ -391,38 +391,38 @@ void gdm_recv_qos_hci_packet(void *nic_ptr, u8 *buf, int size) spin_lock_irqsave(&qcb->qos_lock, flags); qcb->csr[index].SFID = SFID; - qcb->csr[index].classifier_rule_en = ((buf[pos++]<<8)&0xff00); - qcb->csr[index].classifier_rule_en += buf[pos++]; - if (qcb->csr[index].classifier_rule_en == 0) + qcb->csr[index].ClassifierRuleEnable = ((buf[pos++]<<8)&0xff00); + qcb->csr[index].ClassifierRuleEnable += buf[pos++]; + if (qcb->csr[index].ClassifierRuleEnable == 0) qcb->qos_null_idx = index; - qcb->csr[index].ip2s_mask = buf[pos++]; - qcb->csr[index].ip2s_lo = buf[pos++]; - qcb->csr[index].ip2s_hi = buf[pos++]; - qcb->csr[index].protocol = buf[pos++]; - qcb->csr[index].ipsrc_addrmask[0] = buf[pos++]; - qcb->csr[index].ipsrc_addrmask[1] = buf[pos++]; - qcb->csr[index].ipsrc_addrmask[2] = buf[pos++]; - qcb->csr[index].ipsrc_addrmask[3] = buf[pos++]; - qcb->csr[index].ipsrc_addr[0] = buf[pos++]; - qcb->csr[index].ipsrc_addr[1] = buf[pos++]; - qcb->csr[index].ipsrc_addr[2] = buf[pos++]; - qcb->csr[index].ipsrc_addr[3] = buf[pos++]; - qcb->csr[index].ipdst_addrmask[0] = buf[pos++]; - qcb->csr[index].ipdst_addrmask[1] = buf[pos++]; - qcb->csr[index].ipdst_addrmask[2] = buf[pos++]; - qcb->csr[index].ipdst_addrmask[3] = buf[pos++]; - qcb->csr[index].ipdst_addr[0] = buf[pos++]; - qcb->csr[index].ipdst_addr[1] = buf[pos++]; - qcb->csr[index].ipdst_addr[2] = buf[pos++]; - qcb->csr[index].ipdst_addr[3] = buf[pos++]; - qcb->csr[index].srcport_lo = ((buf[pos++]<<8)&0xff00); - qcb->csr[index].srcport_lo += buf[pos++]; - qcb->csr[index].srcport_hi = ((buf[pos++]<<8)&0xff00); - qcb->csr[index].srcport_hi += buf[pos++]; - qcb->csr[index].dstport_lo = ((buf[pos++]<<8)&0xff00); - qcb->csr[index].dstport_lo += buf[pos++]; - qcb->csr[index].dstport_hi = ((buf[pos++]<<8)&0xff00); - qcb->csr[index].dstport_hi += buf[pos++]; + qcb->csr[index].IPToSMask = buf[pos++]; + qcb->csr[index].IPToSLow = buf[pos++]; + qcb->csr[index].IPToSHigh = buf[pos++]; + qcb->csr[index].Protocol = buf[pos++]; + qcb->csr[index].IPSrcAddrMask[0] = buf[pos++]; + qcb->csr[index].IPSrcAddrMask[1] = buf[pos++]; + qcb->csr[index].IPSrcAddrMask[2] = buf[pos++]; + qcb->csr[index].IPSrcAddrMask[3] = buf[pos++]; + qcb->csr[index].IPSrcAddr[0] = buf[pos++]; + qcb->csr[index].IPSrcAddr[1] = buf[pos++]; + qcb->csr[index].IPSrcAddr[2] = buf[pos++]; + qcb->csr[index].IPSrcAddr[3] = buf[pos++]; + qcb->csr[index].IPDstAddrMask[0] = buf[pos++]; + qcb->csr[index].IPDstAddrMask[1] = buf[pos++]; + qcb->csr[index].IPDstAddrMask[2] = buf[pos++]; + qcb->csr[index].IPDstAddrMask[3] = buf[pos++]; + qcb->csr[index].IPDstAddr[0] = buf[pos++]; + qcb->csr[index].IPDstAddr[1] = buf[pos++]; + qcb->csr[index].IPDstAddr[2] = buf[pos++]; + qcb->csr[index].IPDstAddr[3] = buf[pos++]; + qcb->csr[index].SrcPortLow = ((buf[pos++]<<8)&0xff00); + qcb->csr[index].SrcPortLow += buf[pos++]; + qcb->csr[index].SrcPortHigh = ((buf[pos++]<<8)&0xff00); + qcb->csr[index].SrcPortHigh += buf[pos++]; + qcb->csr[index].DstPortLow = ((buf[pos++]<<8)&0xff00); + qcb->csr[index].DstPortLow += buf[pos++]; + qcb->csr[index].DstPortHigh = ((buf[pos++]<<8)&0xff00); + qcb->csr[index].DstPortHigh += buf[pos++]; qcb->qos_limit_size = 254/qcb->qos_list_cnt; spin_unlock_irqrestore(&qcb->qos_lock, flags); @@ -444,7 +444,7 @@ void gdm_recv_qos_hci_packet(void *nic_ptr, u8 *buf, int size) INIT_LIST_HEAD(&free_list); spin_lock_irqsave(&qcb->qos_lock, flags); - qcb->csr[index].enabled = 0; + qcb->csr[index].Enabled = 0; qcb->qos_list_cnt--; qcb->qos_limit_size = 254/qcb->qos_list_cnt; diff --git a/trunk/drivers/staging/gdm72xx/gdm_qos.h b/trunk/drivers/staging/gdm72xx/gdm_qos.h index 8f18119d22a9..33f2bd4cee32 100644 --- a/trunk/drivers/staging/gdm72xx/gdm_qos.h +++ b/trunk/drivers/staging/gdm72xx/gdm_qos.h @@ -20,18 +20,18 @@ #define BOOLEAN u8 -#define QOS_MAX 16 -#define IPTYPEOFSERVICE 0x8000 -#define PROTOCOL 0x4000 -#define IPMASKEDSRCADDRESS 0x2000 -#define IPMASKEDDSTADDRESS 0x1000 +#define QOS_MAX 16 +#define IPTYPEOFSERVICE 0x8000 +#define PROTOCOL 0x4000 +#define IPMASKEDSRCADDRESS 0x2000 +#define IPMASKEDDSTADDRESS 0x1000 #define PROTOCOLSRCPORTRANGE 0x800 #define PROTOCOLDSTPORTRANGE 0x400 -#define DSTMACADDR 0x200 -#define SRCMACADDR 0x100 -#define ETHERTYPE 0x80 +#define DSTMACADDR 0x200 +#define SRCMACADDR 0x100 +#define ETHERTYPE 0x80 #define IEEE802_1DUSERPRIORITY 0x40 -#define IEEE802_1QVLANID 0x10 +#define IEEE802_1QVLANID 0x10 struct gdm_wimax_csr_s { /* union{ @@ -51,28 +51,28 @@ struct gdm_wimax_csr_s { Reserved:5; } fields; } */ - BOOLEAN enabled; - u32 SFID; - u8 qos_buf_count; - u16 classifier_rule_en; - u8 ip2s_lo; - u8 ip2s_hi; - u8 ip2s_mask; - u8 protocol; - u8 ipsrc_addr[16]; - u8 ipsrc_addrmask[16]; - u8 ipdst_addr[16]; - u8 ipdst_addrmask[16]; - u16 srcport_lo; - u16 srcport_hi; - u16 dstport_lo; - u16 dstport_hi; + BOOLEAN Enabled; + u32 SFID; + u8 QoSBufCount; + u16 ClassifierRuleEnable; + u8 IPToSLow; + u8 IPToSHigh; + u8 IPToSMask; + u8 Protocol; + u8 IPSrcAddr[16]; + u8 IPSrcAddrMask[16]; + u8 IPDstAddr[16]; + u8 IPDstAddrMask[16]; + u16 SrcPortLow; + u16 SrcPortHigh; + u16 DstPortLow; + u16 DstPortHigh; }; struct qos_entry_s { - struct list_head list; - struct sk_buff *skb; - struct net_device *dev; + struct list_head list; + struct sk_buff *skb; + struct net_device *dev; }; @@ -81,7 +81,7 @@ struct qos_cb_s { u32 qos_list_cnt; u32 qos_null_idx; struct gdm_wimax_csr_s csr[QOS_MAX]; - spinlock_t qos_lock; + spinlock_t qos_lock; u32 qos_limit_size; }; diff --git a/trunk/drivers/staging/gdm72xx/gdm_sdio.c b/trunk/drivers/staging/gdm72xx/gdm_sdio.c index ca38d719a1f8..3e43c012ef27 100644 --- a/trunk/drivers/staging/gdm72xx/gdm_sdio.c +++ b/trunk/drivers/staging/gdm72xx/gdm_sdio.c @@ -60,20 +60,27 @@ static void hexdump(char *title, u8 *data, int len) static struct sdio_tx *alloc_tx_struct(struct tx_cxt *tx) { - struct sdio_tx *t = kzalloc(sizeof(*t), GFP_ATOMIC); + struct sdio_tx *t = NULL; - if (!t) - return NULL; + t = kmalloc(sizeof(*t), GFP_ATOMIC); + if (t == NULL) + goto out; + + memset(t, 0, sizeof(*t)); t->buf = kmalloc(TX_BUF_SIZE, GFP_ATOMIC); - if (!t->buf) { - kfree(t); - return NULL; - } + if (t->buf == NULL) + goto out; t->tx_cxt = tx; return t; +out: + if (t) { + kfree(t->buf); + kfree(t); + } + return NULL; } static void free_tx_struct(struct sdio_tx *t) @@ -86,12 +93,20 @@ static void free_tx_struct(struct sdio_tx *t) static struct sdio_rx *alloc_rx_struct(struct rx_cxt *rx) { - struct sdio_rx *r = kzalloc(sizeof(*r), GFP_ATOMIC); + struct sdio_rx *r = NULL; - if (r) - r->rx_cxt = rx; + r = kmalloc(sizeof(*r), GFP_ATOMIC); + if (r == NULL) + goto out; + + memset(r, 0, sizeof(*r)); + + r->rx_cxt = rx; return r; +out: + kfree(r); + return NULL; } static void free_rx_struct(struct sdio_rx *r) @@ -665,7 +680,7 @@ static int sdio_wimax_probe(struct sdio_func *func, phy_dev->rcv_func = gdm_sdio_receive; ret = init_sdio(sdev); - if (ret < 0) + if (sdev < 0) goto out; sdev->func = func; diff --git a/trunk/drivers/staging/gdm72xx/gdm_usb.c b/trunk/drivers/staging/gdm72xx/gdm_usb.c index 0c9e8958009b..d48d49c145ee 100644 --- a/trunk/drivers/staging/gdm72xx/gdm_usb.c +++ b/trunk/drivers/staging/gdm72xx/gdm_usb.c @@ -26,11 +26,11 @@ MODULE_DEVICE_TABLE(usb, id_table); -#define TX_BUF_SIZE 2048 +#define TX_BUF_SIZE 2048 #if defined(CONFIG_WIMAX_GDM72XX_WIMAX2) -#define RX_BUF_SIZE (128*1024) /* For packet aggregation */ +#define RX_BUF_SIZE (128*1024) /* For packet aggregation */ #else -#define RX_BUF_SIZE 2048 +#define RX_BUF_SIZE 2048 #endif #define GDM7205_PADDING 256 @@ -39,7 +39,7 @@ MODULE_DEVICE_TABLE(usb, id_table); #define B2H(x) __be16_to_cpu(x) #define DB2H(x) __be32_to_cpu(x) -#define DOWNLOAD_CONF_VALUE 0x21 +#define DOWNLOAD_CONF_VALUE 0x21 #ifdef CONFIG_WIMAX_GDM72XX_K_MODE @@ -48,7 +48,7 @@ static LIST_HEAD(k_list); static DEFINE_SPINLOCK(k_lock); static int k_mode_stop; -#define K_WAIT_TIME (2 * HZ / 100) +#define K_WAIT_TIME (2 * HZ / 100) #endif /* CONFIG_WIMAX_GDM72XX_K_MODE */ @@ -73,23 +73,29 @@ static void hexdump(char *title, u8 *data, int len) static struct usb_tx *alloc_tx_struct(struct tx_cxt *tx) { - struct usb_tx *t = kzalloc(sizeof(*t), GFP_ATOMIC); + struct usb_tx *t = NULL; - if (!t) - return NULL; + t = kmalloc(sizeof(*t), GFP_ATOMIC); + if (t == NULL) + goto out; + + memset(t, 0, sizeof(*t)); t->urb = usb_alloc_urb(0, GFP_ATOMIC); t->buf = kmalloc(TX_BUF_SIZE, GFP_ATOMIC); - if (!t->urb || !t->buf) { - usb_free_urb(t->urb); - kfree(t->buf); - kfree(t); - return NULL; - } + if (t->urb == NULL || t->buf == NULL) + goto out; t->tx_cxt = tx; return t; +out: + if (t) { + usb_free_urb(t->urb); + kfree(t->buf); + kfree(t); + } + return NULL; } static void free_tx_struct(struct usb_tx *t) @@ -103,22 +109,28 @@ static void free_tx_struct(struct usb_tx *t) static struct usb_rx *alloc_rx_struct(struct rx_cxt *rx) { - struct usb_rx *r = kzalloc(sizeof(*r), GFP_ATOMIC); + struct usb_rx *r = NULL; - if (!r) - return NULL; + r = kmalloc(sizeof(*r), GFP_ATOMIC); + if (r == NULL) + goto out; + + memset(r, 0, sizeof(*r)); r->urb = usb_alloc_urb(0, GFP_ATOMIC); r->buf = kmalloc(RX_BUF_SIZE, GFP_ATOMIC); - if (!r->urb || !r->buf) { + if (r->urb == NULL || r->buf == NULL) + goto out; + + r->rx_cxt = rx; + return r; +out: + if (r) { usb_free_urb(r->urb); kfree(r->buf); kfree(r); - return NULL; } - - r->rx_cxt = rx; - return r; + return NULL; } static void free_rx_struct(struct usb_rx *r) @@ -168,7 +180,8 @@ static struct usb_rx *get_rx_struct(struct rx_cxt *rx) } r = list_entry(rx->free_list.next, struct usb_rx, list); - list_move_tail(&r->list, &rx->used_list); + list_del(&r->list); + list_add_tail(&r->list, &rx->used_list); return r; } @@ -176,7 +189,8 @@ static struct usb_rx *get_rx_struct(struct rx_cxt *rx) /* Before this function is called, spin lock should be locked. */ static void put_rx_struct(struct rx_cxt *rx, struct usb_rx *r) { - list_move(&r->list, &rx->free_list); + list_del(&r->list); + list_add(&r->list, &rx->free_list); } static int init_usb(struct usbwm_dev *udev) diff --git a/trunk/drivers/staging/gdm72xx/gdm_usb.h b/trunk/drivers/staging/gdm72xx/gdm_usb.h index f2c54511bb96..ecb891f6a599 100644 --- a/trunk/drivers/staging/gdm72xx/gdm_usb.h +++ b/trunk/drivers/staging/gdm72xx/gdm_usb.h @@ -18,8 +18,8 @@ #include #include -#define B_DIFF_DL_DRV (1 << 4) -#define B_DOWNLOAD (1 << 5) +#define B_DIFF_DL_DRV (1<<4) +#define B_DOWNLOAD (1 << 5) #define MAX_NR_SDU_BUF 64 struct usb_tx { @@ -29,7 +29,7 @@ struct usb_tx { #endif struct tx_cxt *tx_cxt; - struct urb *urb; + struct urb *urb; u8 *buf; void (*callback)(void *cb_data); @@ -44,14 +44,14 @@ struct tx_cxt { struct list_head pending_list; #endif - spinlock_t lock; + spinlock_t lock; }; struct usb_rx { struct list_head list; struct rx_cxt *rx_cxt; - struct urb *urb; + struct urb *urb; u8 *buf; void (*callback)(void *cb_data, void *data, int len); @@ -61,7 +61,7 @@ struct usb_rx { struct rx_cxt { struct list_head free_list; struct list_head used_list; - spinlock_t lock; + spinlock_t lock; }; struct usbwm_dev { @@ -76,8 +76,8 @@ struct usbwm_dev { struct list_head list; #endif - struct tx_cxt tx; - struct rx_cxt rx; + struct tx_cxt tx; + struct rx_cxt rx; int padding; }; diff --git a/trunk/drivers/staging/gdm72xx/gdm_wimax.c b/trunk/drivers/staging/gdm72xx/gdm_wimax.c index 6cb810701a3e..0716efc1817d 100644 --- a/trunk/drivers/staging/gdm72xx/gdm_wimax.c +++ b/trunk/drivers/staging/gdm72xx/gdm_wimax.c @@ -258,16 +258,12 @@ static int gdm_wimax_event_init(void) if (!wm_event.ref_cnt) { wm_event.sock = netlink_init(NETLINK_WIMAX, gdm_wimax_event_rcv); - if (wm_event.sock) { - INIT_LIST_HEAD(&wm_event.evtq); - INIT_LIST_HEAD(&wm_event.freeq); - INIT_WORK(&wm_event.ws, __gdm_wimax_event_send); - spin_lock_init(&wm_event.evt_lock); - } - } - - if (wm_event.sock) { - wm_event.ref_cnt++; + if (wm_event.sock) + wm_event.ref_cnt++; + INIT_LIST_HEAD(&wm_event.evtq); + INIT_LIST_HEAD(&wm_event.freeq); + INIT_WORK(&wm_event.ws, __gdm_wimax_event_send); + spin_lock_init(&wm_event.evt_lock); return 0; } diff --git a/trunk/drivers/staging/gdm72xx/usb_boot.c b/trunk/drivers/staging/gdm72xx/usb_boot.c index 0787188728aa..e3dbd5a552ca 100644 --- a/trunk/drivers/staging/gdm72xx/usb_boot.c +++ b/trunk/drivers/staging/gdm72xx/usb_boot.c @@ -18,22 +18,25 @@ #include #include #include -#include #include #include "gdm_usb.h" #include "usb_boot.h" -#define DN_KERNEL_MAGIC_NUMBER 0x10760001 -#define DN_ROOTFS_MAGIC_NUMBER 0x10760002 +#define DN_KERNEL_MAGIC_NUMBER 0x10760001 +#define DN_ROOTFS_MAGIC_NUMBER 0x10760002 -#define DOWNLOAD_SIZE 1024 +#define DOWNLOAD_SIZE 1024 + +#define DH2B(x) __cpu_to_be32(x) +#define DL2H(x) __le32_to_cpu(x) + +#define MIN(a, b) ((a) > (b) ? (b) : (a)) #define MAX_IMG_CNT 16 -#define FW_DIR "gdm72xx/" -#define FW_UIMG "gdmuimg.bin" -#define FW_KERN "zImage" -#define FW_FS "ramdisk.jffs2" +#define UIMG_PATH "/lib/firmware/gdm72xx/gdmuimg.bin" +#define KERN_PATH "/lib/firmware/gdm72xx/zImage" +#define FS_PATH "/lib/firmware/gdm72xx/ramdisk.jffs2" struct dn_header { u32 magic_num; @@ -41,23 +44,23 @@ struct dn_header { }; struct img_header { - u32 magic_code; - u32 count; - u32 len; - u32 offset[MAX_IMG_CNT]; + u32 magic_code; + u32 count; + u32 len; + u32 offset[MAX_IMG_CNT]; char hostname[32]; char date[32]; }; struct fw_info { - u32 id; - u32 len; - u32 kernel_len; - u32 rootfs_len; - u32 kernel_offset; - u32 rootfs_offset; - u32 fw_ver; - u32 mac_ver; + u32 id; + u32 len; + u32 kernel_len; + u32 rootfs_len; + u32 kernel_offset; + u32 rootfs_offset; + u32 fw_ver; + u32 mac_ver; char hostname[32]; char userid[16]; char date[32]; @@ -68,7 +71,7 @@ static void array_le32_to_cpu(u32 *arr, int num) { int i; for (i = 0; i < num; i++, arr++) - *arr = __le32_to_cpu(*arr); + *arr = DL2H(*arr); } static u8 *tx_buf; @@ -104,37 +107,44 @@ static int gdm_wibro_recv(struct usb_device *usbdev, void *data, int len) return 0; } -static int download_image(struct usb_device *usbdev, - const struct firmware *firm, - loff_t pos, u32 img_len, u32 magic_num) +static int download_image(struct usb_device *usbdev, struct file *filp, + loff_t *pos, u32 img_len, u32 magic_num) { struct dn_header h; int ret = 0; u32 size; + int len, readn; - size = ALIGN(img_len, DOWNLOAD_SIZE); - h.magic_num = __cpu_to_be32(magic_num); - h.file_size = __cpu_to_be32(size); + size = (img_len + DOWNLOAD_SIZE - 1) & ~(DOWNLOAD_SIZE - 1); + h.magic_num = DH2B(magic_num); + h.file_size = DH2B(size); ret = gdm_wibro_send(usbdev, &h, sizeof(h)); if (ret < 0) - return ret; + goto out; - while (img_len > 0) { - if (img_len > DOWNLOAD_SIZE) - size = DOWNLOAD_SIZE; - else - size = img_len; /* the last chunk of data */ + readn = 0; + while ((len = filp->f_op->read(filp, tx_buf, DOWNLOAD_SIZE, pos))) { - memcpy(tx_buf, firm->data + pos, size); - ret = gdm_wibro_send(usbdev, tx_buf, size); + if (len < 0) { + ret = -1; + goto out; + } + readn += len; + ret = gdm_wibro_send(usbdev, tx_buf, DOWNLOAD_SIZE); if (ret < 0) - return ret; + goto out; + if (readn >= img_len) + break; + } - img_len -= size; - pos += size; + if (readn < img_len) { + printk(KERN_ERR "gdmwm: Cannot read to the requested size. " + "Read = %d Requested = %d\n", readn, img_len); + ret = -EIO; } +out: return ret; } @@ -142,19 +152,14 @@ static int download_image(struct usb_device *usbdev, int usb_boot(struct usb_device *usbdev, u16 pid) { int i, ret = 0; + struct file *filp = NULL; + struct inode *inode = NULL; + static mm_segment_t fs; struct img_header hdr; struct fw_info fw_info; loff_t pos = 0; - char *img_name = FW_DIR FW_UIMG; - const struct firmware *firm; - - ret = request_firmware(&firm, img_name, &usbdev->dev); - if (ret < 0) { - printk(KERN_ERR - "requesting firmware %s failed with error %d\n", - img_name, ret); - return ret; - } + char *img_name = UIMG_PATH; + int len; tx_buf = kmalloc(DOWNLOAD_SIZE, GFP_KERNEL); if (tx_buf == NULL) { @@ -162,12 +167,29 @@ int usb_boot(struct usb_device *usbdev, u16 pid) return -ENOMEM; } - if (firm->size < sizeof(hdr)) { + fs = get_fs(); + set_fs(get_ds()); + + filp = filp_open(img_name, O_RDONLY | O_LARGEFILE, 0); + if (IS_ERR(filp)) { + printk(KERN_ERR "Can't find %s.\n", img_name); + ret = PTR_ERR(filp); + goto restore_fs; + } + + inode = filp->f_dentry->d_inode; + if (!S_ISREG(inode->i_mode)) { + printk(KERN_ERR "Invalid file type: %s\n", img_name); + ret = -EINVAL; + goto out; + } + + len = filp->f_op->read(filp, (u8 *)&hdr, sizeof(hdr), &pos); + if (len != sizeof(hdr)) { printk(KERN_ERR "gdmwm: Cannot read the image info.\n"); ret = -EIO; goto out; } - memcpy(&hdr, firm->data, sizeof(hdr)); array_le32_to_cpu((u32 *)&hdr, 19); #if 0 @@ -195,12 +217,13 @@ int usb_boot(struct usb_device *usbdev, u16 pid) } pos = hdr.offset[i]; - if (firm->size < sizeof(fw_info) + pos) { + len = filp->f_op->read(filp, (u8 *)&fw_info, sizeof(fw_info), + &pos); + if (len != sizeof(fw_info)) { printk(KERN_ERR "gdmwm: Cannot read the FW info.\n"); ret = -EIO; goto out; } - memcpy(&fw_info, firm->data + pos, sizeof(fw_info)); array_le32_to_cpu((u32 *)&fw_info, 8); #if 0 @@ -216,23 +239,14 @@ int usb_boot(struct usb_device *usbdev, u16 pid) continue; pos = hdr.offset[i] + fw_info.kernel_offset; - if (firm->size < fw_info.kernel_len + pos) { - printk(KERN_ERR "gdmwm: Kernel FW is too small.\n"); - goto out; - } - - ret = download_image(usbdev, firm, pos, - fw_info.kernel_len, DN_KERNEL_MAGIC_NUMBER); + ret = download_image(usbdev, filp, &pos, fw_info.kernel_len, + DN_KERNEL_MAGIC_NUMBER); if (ret < 0) goto out; printk(KERN_INFO "GCT: Kernel download success.\n"); pos = hdr.offset[i] + fw_info.rootfs_offset; - if (firm->size < fw_info.rootfs_len + pos) { - printk(KERN_ERR "gdmwm: Filesystem FW is too small.\n"); - goto out; - } - ret = download_image(usbdev, firm, pos, fw_info.rootfs_len, + ret = download_image(usbdev, filp, &pos, fw_info.rootfs_len, DN_ROOTFS_MAGIC_NUMBER); if (ret < 0) goto out; @@ -246,7 +260,10 @@ int usb_boot(struct usb_device *usbdev, u16 pid) ret = -EINVAL; } out: - release_firmware(firm); + filp_close(filp, NULL); + +restore_fs: + set_fs(fs); kfree(tx_buf); return ret; } @@ -276,27 +293,38 @@ static int em_wait_ack(struct usb_device *usbdev, int send_zlp) return ret; } -static int em_download_image(struct usb_device *usbdev, const char *img_name, +static int em_download_image(struct usb_device *usbdev, char *path, char *type_string) { + struct file *filp; + struct inode *inode; + static mm_segment_t fs; char *buf = NULL; loff_t pos = 0; int ret = 0; - int len; - int img_len; - const struct firmware *firm; + int len, readn = 0; #if defined(GDM7205_PADDING) const int pad_size = GDM7205_PADDING; #else const int pad_size = 0; #endif - ret = request_firmware(&firm, img_name, &usbdev->dev); - if (ret < 0) { - printk(KERN_ERR - "requesting firmware %s failed with error %d\n", - img_name, ret); - return ret; + fs = get_fs(); + set_fs(get_ds()); + + filp = filp_open(path, O_RDONLY | O_LARGEFILE, 0); + if (IS_ERR(filp)) { + printk(KERN_ERR "Can't find %s.\n", path); + set_fs(fs); + ret = -ENOENT; + goto restore_fs; + } + + inode = filp->f_dentry->d_inode; + if (!S_ISREG(inode->i_mode)) { + printk(KERN_ERR "Invalid file type: %s\n", path); + ret = -EINVAL; + goto out; } buf = kmalloc(DOWNLOAD_CHUCK + pad_size, GFP_KERNEL); @@ -310,28 +338,18 @@ static int em_download_image(struct usb_device *usbdev, const char *img_name, if (ret < 0) goto out; - img_len = firm->size; - - if (img_len <= 0) { - ret = -1; - goto out; - } - - while (img_len > 0) { - if (img_len > DOWNLOAD_CHUCK) - len = DOWNLOAD_CHUCK; - else - len = img_len; /* the last chunk of data */ + while ((len = filp->f_op->read(filp, buf+pad_size, DOWNLOAD_CHUCK, + &pos))) { + if (len < 0) { + ret = -1; + goto out; + } + readn += len; - memcpy(buf+pad_size, firm->data + pos, len); ret = gdm_wibro_send(usbdev, buf, len+pad_size); - if (ret < 0) goto out; - img_len -= DOWNLOAD_CHUCK; - pos += DOWNLOAD_CHUCK; - ret = em_wait_ack(usbdev, ((len+pad_size) % 512 == 0)); if (ret < 0) goto out; @@ -342,7 +360,11 @@ static int em_download_image(struct usb_device *usbdev, const char *img_name, goto out; out: - release_firmware(firm); + filp_close(filp, NULL); + +restore_fs: + set_fs(fs); + kfree(buf); return ret; @@ -360,20 +382,18 @@ static int em_fw_reset(struct usb_device *usbdev) int usb_emergency(struct usb_device *usbdev) { int ret; - const char *kern_name = FW_DIR FW_KERN; - const char *fs_name = FW_DIR FW_FS; - ret = em_download_image(usbdev, kern_name, KERNEL_TYPE_STRING); + ret = em_download_image(usbdev, KERN_PATH, KERNEL_TYPE_STRING); if (ret < 0) - return ret; + goto out; printk(KERN_INFO "GCT Emergency: Kernel download success.\n"); - ret = em_download_image(usbdev, fs_name, FS_TYPE_STRING); + ret = em_download_image(usbdev, FS_PATH, FS_TYPE_STRING); if (ret < 0) - return ret; + goto out; printk(KERN_INFO "GCT Emergency: Filesystem download success.\n"); ret = em_fw_reset(usbdev); - +out: return ret; } diff --git a/trunk/drivers/staging/iio/Documentation/generic_buffer.c b/trunk/drivers/staging/iio/Documentation/generic_buffer.c index 40d0ecac047f..827e92de8e30 100644 --- a/trunk/drivers/staging/iio/Documentation/generic_buffer.c +++ b/trunk/drivers/staging/iio/Documentation/generic_buffer.c @@ -104,16 +104,6 @@ void process_scan(char *data, print2byte(*(uint16_t *)(data + channels[k].location), &channels[k]); break; - case 4: - if (!channels[k].is_signed) { - uint32_t val = *(uint32_t *) - (data + channels[k].location); - printf("%05f ", ((float)val + - channels[k].offset)* - channels[k].scale); - - } - break; case 8: if (channels[k].is_signed) { int64_t val = *(int64_t *) diff --git a/trunk/drivers/staging/iio/Documentation/inkernel.txt b/trunk/drivers/staging/iio/Documentation/inkernel.txt index ab528409bba6..a05823e955d2 100644 --- a/trunk/drivers/staging/iio/Documentation/inkernel.txt +++ b/trunk/drivers/staging/iio/Documentation/inkernel.txt @@ -48,11 +48,11 @@ There are then a number of functions that can be used to get information about this channel such as it's current reading. e.g. -iio_read_channel_raw() - get a reading -iio_get_channel_type() - get the type of channel +iio_st_read_channel_raw() - get a reading +iio_st_read_channel_type() - get the type of channel There is also provision for retrieving all of the channels associated with a given consumer. This is useful for generic drivers such as iio_hwmon where the number and naming of channels is not known by the -consumer driver. To do this, use iio_channel_get_all. +consumer driver. To do this, use iio_st_channel_get_all. diff --git a/trunk/drivers/staging/iio/Kconfig b/trunk/drivers/staging/iio/Kconfig index ca56c75a35fc..04cd6ec1f70f 100644 --- a/trunk/drivers/staging/iio/Kconfig +++ b/trunk/drivers/staging/iio/Kconfig @@ -1,5 +1,5 @@ # -# Industrial I/O subsystem configuration +# Industrial I/O subsytem configuration # menu "IIO staging drivers" depends on IIO diff --git a/trunk/drivers/staging/iio/TODO b/trunk/drivers/staging/iio/TODO index 04c23262f8e2..cf3f9489b9da 100644 --- a/trunk/drivers/staging/iio/TODO +++ b/trunk/drivers/staging/iio/TODO @@ -69,5 +69,5 @@ Documentation 1) Lots of cleanup and expansion. 2) Some device require individual docs. -Contact: Jonathan Cameron . +Contact: Jonathan Cameron . Mailing list: linux-iio@vger.kernel.org diff --git a/trunk/drivers/staging/iio/accel/adis16201_core.c b/trunk/drivers/staging/iio/accel/adis16201_core.c index 8e37d6e04277..204106b72d24 100644 --- a/trunk/drivers/staging/iio/accel/adis16201_core.c +++ b/trunk/drivers/staging/iio/accel/adis16201_core.c @@ -390,7 +390,7 @@ static int adis16201_write_raw(struct iio_dev *indio_dev, return -EINVAL; } -static const struct iio_chan_spec adis16201_channels[] = { +static struct iio_chan_spec adis16201_channels[] = { { .type = IIO_VOLTAGE, .indexed = 1, @@ -565,7 +565,7 @@ static int __devinit adis16201_probe(struct spi_device *spi) return ret; } -static int __devexit adis16201_remove(struct spi_device *spi) +static int adis16201_remove(struct spi_device *spi) { struct iio_dev *indio_dev = spi_get_drvdata(spi); diff --git a/trunk/drivers/staging/iio/accel/adis16201_ring.c b/trunk/drivers/staging/iio/accel/adis16201_ring.c index 97c09f0c26ae..03fcf6e319db 100644 --- a/trunk/drivers/staging/iio/accel/adis16201_ring.c +++ b/trunk/drivers/staging/iio/accel/adis16201_ring.c @@ -62,6 +62,7 @@ static irqreturn_t adis16201_trigger_handler(int irq, void *p) struct iio_poll_func *pf = p; struct iio_dev *indio_dev = pf->indio_dev; struct adis16201_state *st = iio_priv(indio_dev); + struct iio_buffer *ring = indio_dev->buffer; int i = 0; s16 *data; @@ -82,7 +83,7 @@ static irqreturn_t adis16201_trigger_handler(int irq, void *p) if (indio_dev->scan_timestamp) *((s64 *)(data + ((i + 3)/4)*4)) = pf->timestamp; - iio_push_to_buffer(indio_dev->buffer, (u8 *)data); + ring->access->store_to(ring, (u8 *)data, pf->timestamp); kfree(data); done: diff --git a/trunk/drivers/staging/iio/accel/adis16203_core.c b/trunk/drivers/staging/iio/accel/adis16203_core.c index 002fa9dfc375..22085e9dfd16 100644 --- a/trunk/drivers/staging/iio/accel/adis16203_core.c +++ b/trunk/drivers/staging/iio/accel/adis16203_core.c @@ -355,7 +355,7 @@ static int adis16203_read_raw(struct iio_dev *indio_dev, } } -static const struct iio_chan_spec adis16203_channels[] = { +static struct iio_chan_spec adis16203_channels[] = { { .type = IIO_VOLTAGE, .indexed = 1, @@ -500,7 +500,7 @@ static int __devinit adis16203_probe(struct spi_device *spi) return ret; } -static int __devexit adis16203_remove(struct spi_device *spi) +static int adis16203_remove(struct spi_device *spi) { struct iio_dev *indio_dev = spi_get_drvdata(spi); diff --git a/trunk/drivers/staging/iio/accel/adis16203_ring.c b/trunk/drivers/staging/iio/accel/adis16203_ring.c index 7507e1a04591..c16b2b7323ac 100644 --- a/trunk/drivers/staging/iio/accel/adis16203_ring.c +++ b/trunk/drivers/staging/iio/accel/adis16203_ring.c @@ -61,6 +61,7 @@ static irqreturn_t adis16203_trigger_handler(int irq, void *p) struct iio_poll_func *pf = p; struct iio_dev *indio_dev = pf->indio_dev; struct adis16203_state *st = iio_priv(indio_dev); + struct iio_buffer *ring = indio_dev->buffer; int i = 0; s16 *data; @@ -81,7 +82,9 @@ static irqreturn_t adis16203_trigger_handler(int irq, void *p) if (indio_dev->scan_timestamp) *((s64 *)(data + ((i + 3)/4)*4)) = pf->timestamp; - iio_push_to_buffer(indio_dev->buffer, (u8 *)data); + ring->access->store_to(ring, + (u8 *)data, + pf->timestamp); kfree(data); done: diff --git a/trunk/drivers/staging/iio/accel/adis16204_core.c b/trunk/drivers/staging/iio/accel/adis16204_core.c index 05bdb7c2c8e3..5f2e5f11c543 100644 --- a/trunk/drivers/staging/iio/accel/adis16204_core.c +++ b/trunk/drivers/staging/iio/accel/adis16204_core.c @@ -397,7 +397,7 @@ static int adis16204_write_raw(struct iio_dev *indio_dev, return -EINVAL; } -static const struct iio_chan_spec adis16204_channels[] = { +static struct iio_chan_spec adis16204_channels[] = { { .type = IIO_VOLTAGE, .indexed = 1, /* Note was not previously indexed */ @@ -558,7 +558,7 @@ static int __devinit adis16204_probe(struct spi_device *spi) return ret; } -static int __devexit adis16204_remove(struct spi_device *spi) +static int adis16204_remove(struct spi_device *spi) { struct iio_dev *indio_dev = spi_get_drvdata(spi); diff --git a/trunk/drivers/staging/iio/accel/adis16204_ring.c b/trunk/drivers/staging/iio/accel/adis16204_ring.c index 4c976bec986b..1d2b31cc849e 100644 --- a/trunk/drivers/staging/iio/accel/adis16204_ring.c +++ b/trunk/drivers/staging/iio/accel/adis16204_ring.c @@ -59,6 +59,7 @@ static irqreturn_t adis16204_trigger_handler(int irq, void *p) struct iio_poll_func *pf = p; struct iio_dev *indio_dev = pf->indio_dev; struct adis16204_state *st = iio_priv(indio_dev); + struct iio_buffer *ring = indio_dev->buffer; int i = 0; s16 *data; @@ -78,7 +79,7 @@ static irqreturn_t adis16204_trigger_handler(int irq, void *p) if (indio_dev->scan_timestamp) *((s64 *)(data + ((i + 3)/4)*4)) = pf->timestamp; - iio_push_to_buffer(indio_dev->buffer, (u8 *)data); + ring->access->store_to(ring, (u8 *)data, pf->timestamp); kfree(data); done: diff --git a/trunk/drivers/staging/iio/accel/adis16209_core.c b/trunk/drivers/staging/iio/accel/adis16209_core.c index b7333bfe0b2f..494570508c36 100644 --- a/trunk/drivers/staging/iio/accel/adis16209_core.c +++ b/trunk/drivers/staging/iio/accel/adis16209_core.c @@ -390,7 +390,7 @@ static int adis16209_read_raw(struct iio_dev *indio_dev, return -EINVAL; } -static const struct iio_chan_spec adis16209_channels[] = { +static struct iio_chan_spec adis16209_channels[] = { { .type = IIO_VOLTAGE, .indexed = 1, @@ -573,7 +573,7 @@ static int __devinit adis16209_probe(struct spi_device *spi) return ret; } -static int __devexit adis16209_remove(struct spi_device *spi) +static int adis16209_remove(struct spi_device *spi) { struct iio_dev *indio_dev = spi_get_drvdata(spi); diff --git a/trunk/drivers/staging/iio/accel/adis16209_ring.c b/trunk/drivers/staging/iio/accel/adis16209_ring.c index f939e29d6c82..1a4a55c27c7c 100644 --- a/trunk/drivers/staging/iio/accel/adis16209_ring.c +++ b/trunk/drivers/staging/iio/accel/adis16209_ring.c @@ -59,6 +59,7 @@ static irqreturn_t adis16209_trigger_handler(int irq, void *p) struct iio_poll_func *pf = p; struct iio_dev *indio_dev = pf->indio_dev; struct adis16209_state *st = iio_priv(indio_dev); + struct iio_buffer *ring = indio_dev->buffer; int i = 0; s16 *data; @@ -78,7 +79,7 @@ static irqreturn_t adis16209_trigger_handler(int irq, void *p) if (indio_dev->scan_timestamp) *((s64 *)(data + ((i + 3)/4)*4)) = pf->timestamp; - iio_push_to_buffer(indio_dev->buffer, (u8 *)data); + ring->access->store_to(ring, (u8 *)data, pf->timestamp); kfree(data); done: diff --git a/trunk/drivers/staging/iio/accel/adis16220_core.c b/trunk/drivers/staging/iio/accel/adis16220_core.c index c755089c7117..575f1af25d5d 100644 --- a/trunk/drivers/staging/iio/accel/adis16220_core.c +++ b/trunk/drivers/staging/iio/accel/adis16220_core.c @@ -372,7 +372,8 @@ static ssize_t adis16220_accel_bin_read(struct file *filp, struct kobject *kobj, loff_t off, size_t count) { - struct iio_dev *indio_dev = dev_to_iio_dev(kobj_to_dev(kobj)); + struct device *dev = container_of(kobj, struct device, kobj); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); return adis16220_capture_buffer_read(indio_dev, buf, off, count, @@ -393,7 +394,8 @@ static ssize_t adis16220_adc1_bin_read(struct file *filp, struct kobject *kobj, char *buf, loff_t off, size_t count) { - struct iio_dev *indio_dev = dev_to_iio_dev(kobj_to_dev(kobj)); + struct device *dev = container_of(kobj, struct device, kobj); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); return adis16220_capture_buffer_read(indio_dev, buf, off, count, @@ -414,7 +416,8 @@ static ssize_t adis16220_adc2_bin_read(struct file *filp, struct kobject *kobj, char *buf, loff_t off, size_t count) { - struct iio_dev *indio_dev = dev_to_iio_dev(kobj_to_dev(kobj)); + struct device *dev = container_of(kobj, struct device, kobj); + struct iio_dev *indio_dev = dev_to_iio_dev(dev); return adis16220_capture_buffer_read(indio_dev, buf, off, count, @@ -663,7 +666,7 @@ static int __devinit adis16220_probe(struct spi_device *spi) return ret; } -static int __devexit adis16220_remove(struct spi_device *spi) +static int adis16220_remove(struct spi_device *spi) { struct iio_dev *indio_dev = spi_get_drvdata(spi); diff --git a/trunk/drivers/staging/iio/accel/adis16240_core.c b/trunk/drivers/staging/iio/accel/adis16240_core.c index 0fc26a49d681..b30b7874ffb0 100644 --- a/trunk/drivers/staging/iio/accel/adis16240_core.c +++ b/trunk/drivers/staging/iio/accel/adis16240_core.c @@ -448,7 +448,7 @@ static int adis16240_write_raw(struct iio_dev *indio_dev, return -EINVAL; } -static const struct iio_chan_spec adis16240_channels[] = { +static struct iio_chan_spec adis16240_channels[] = { { .type = IIO_VOLTAGE, .indexed = 1, @@ -619,7 +619,7 @@ static int __devinit adis16240_probe(struct spi_device *spi) return ret; } -static int __devexit adis16240_remove(struct spi_device *spi) +static int adis16240_remove(struct spi_device *spi) { struct iio_dev *indio_dev = spi_get_drvdata(spi); diff --git a/trunk/drivers/staging/iio/accel/adis16240_ring.c b/trunk/drivers/staging/iio/accel/adis16240_ring.c index caff8e25e0a2..360dfed6d4d1 100644 --- a/trunk/drivers/staging/iio/accel/adis16240_ring.c +++ b/trunk/drivers/staging/iio/accel/adis16240_ring.c @@ -56,6 +56,7 @@ static irqreturn_t adis16240_trigger_handler(int irq, void *p) struct iio_poll_func *pf = p; struct iio_dev *indio_dev = pf->indio_dev; struct adis16240_state *st = iio_priv(indio_dev); + struct iio_buffer *ring = indio_dev->buffer; int i = 0; s16 *data; @@ -76,7 +77,7 @@ static irqreturn_t adis16240_trigger_handler(int irq, void *p) if (indio_dev->scan_timestamp) *((s64 *)(data + ((i + 3)/4)*4)) = pf->timestamp; - iio_push_to_buffer(indio_dev->buffer, (u8 *)data); + ring->access->store_to(ring, (u8 *)data, pf->timestamp); kfree(data); done: diff --git a/trunk/drivers/staging/iio/accel/kxsd9.c b/trunk/drivers/staging/iio/accel/kxsd9.c index fdd5fbded660..8cf7cd943c90 100644 --- a/trunk/drivers/staging/iio/accel/kxsd9.c +++ b/trunk/drivers/staging/iio/accel/kxsd9.c @@ -2,7 +2,7 @@ * kxsd9.c simple support for the Kionix KXSD9 3D * accelerometer. * - * Copyright (c) 2008-2009 Jonathan Cameron + * Copyright (c) 2008-2009 Jonathan Cameron * * 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 @@ -186,7 +186,7 @@ static int kxsd9_read_raw(struct iio_dev *indio_dev, .address = KXSD9_REG_##axis, \ } -static const struct iio_chan_spec kxsd9_channels[] = { +static struct iio_chan_spec kxsd9_channels[] = { KXSD9_ACCEL_CHAN(X), KXSD9_ACCEL_CHAN(Y), KXSD9_ACCEL_CHAN(Z), { .type = IIO_VOLTAGE, @@ -286,6 +286,6 @@ static struct spi_driver kxsd9_driver = { }; module_spi_driver(kxsd9_driver); -MODULE_AUTHOR("Jonathan Cameron "); +MODULE_AUTHOR("Jonathan Cameron "); MODULE_DESCRIPTION("Kionix KXSD9 SPI driver"); MODULE_LICENSE("GPL v2"); diff --git a/trunk/drivers/staging/iio/accel/lis3l02dq.h b/trunk/drivers/staging/iio/accel/lis3l02dq.h index f9bcd41f7188..ae5f225b4bb2 100644 --- a/trunk/drivers/staging/iio/accel/lis3l02dq.h +++ b/trunk/drivers/staging/iio/accel/lis3l02dq.h @@ -2,7 +2,7 @@ * LISL02DQ.h -- support STMicroelectronics LISD02DQ * 3d 2g Linear Accelerometers via SPI * - * Copyright (c) 2007 Jonathan Cameron + * Copyright (c) 2007 Jonathan Cameron * * Loosely based upon tle62x0.c * @@ -28,7 +28,7 @@ /* Control Register (1 of 2) */ #define LIS3L02DQ_REG_CTRL_1_ADDR 0x20 /* Power ctrl - either bit set corresponds to on*/ -#define LIS3L02DQ_REG_CTRL_1_PD_ON 0xC0 +#define LIS3L02DQ_REG_CTRL_1_PD_ON 0xC0 /* Decimation Factor */ #define LIS3L02DQ_DEC_MASK 0x30 @@ -73,14 +73,14 @@ /* Interrupt related stuff */ #define LIS3L02DQ_REG_WAKE_UP_CFG_ADDR 0x23 -/* Switch from or combination of conditions to and */ +/* Switch from or combination fo conditions to and */ #define LIS3L02DQ_REG_WAKE_UP_CFG_BOOLEAN_AND 0x80 /* Latch interrupt request, * if on ack must be given by reading the ack register */ #define LIS3L02DQ_REG_WAKE_UP_CFG_LATCH_SRC 0x40 -/* Z Interrupt on High (above threshold) */ +/* Z Interrupt on High (above threshold)*/ #define LIS3L02DQ_REG_WAKE_UP_CFG_INTERRUPT_Z_HIGH 0x20 /* Z Interrupt on Low */ #define LIS3L02DQ_REG_WAKE_UP_CFG_INTERRUPT_Z_LOW 0x10 @@ -117,13 +117,13 @@ #define LIS3L02DQ_REG_STATUS_Y_OVERRUN 0x20 #define LIS3L02DQ_REG_STATUS_X_OVERRUN 0x10 /* XYZ new data available - first is all 3 available? */ -#define LIS3L02DQ_REG_STATUS_XYZ_NEW_DATA 0x08 +#define LIS3L02DQ_REG_STATUS_XYZ_NEW_DATA 0x08 #define LIS3L02DQ_REG_STATUS_Z_NEW_DATA 0x04 #define LIS3L02DQ_REG_STATUS_Y_NEW_DATA 0x02 #define LIS3L02DQ_REG_STATUS_X_NEW_DATA 0x01 /* The accelerometer readings - low and high bytes. - * Form of high byte dependent on justification set in ctrl reg */ +Form of high byte dependent on justification set in ctrl reg */ #define LIS3L02DQ_REG_OUT_X_L_ADDR 0x28 #define LIS3L02DQ_REG_OUT_X_H_ADDR 0x29 #define LIS3L02DQ_REG_OUT_Y_L_ADDR 0x2A @@ -150,9 +150,9 @@ * struct lis3l02dq_state - device instance specific data * @us: actual spi_device * @trig: data ready trigger registered with iio - * @buf_lock: mutex to protect tx and rx * @tx: transmit buffer * @rx: receive buffer + * @buf_lock: mutex to protect tx and rx **/ struct lis3l02dq_state { struct spi_device *us; diff --git a/trunk/drivers/staging/iio/accel/lis3l02dq_core.c b/trunk/drivers/staging/iio/accel/lis3l02dq_core.c index 21b0469f8bc2..9d263484fb86 100644 --- a/trunk/drivers/staging/iio/accel/lis3l02dq_core.c +++ b/trunk/drivers/staging/iio/accel/lis3l02dq_core.c @@ -2,7 +2,7 @@ * lis3l02dq.c support STMicroelectronics LISD02DQ * 3d 2g Linear Accelerometers via SPI * - * Copyright (c) 2007 Jonathan Cameron + * Copyright (c) 2007 Jonathan Cameron * * 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 @@ -392,7 +392,7 @@ static int lis3l02dq_initial_setup(struct iio_dev *indio_dev) dev_err(&st->us->dev, "problem with setup control register 1"); goto err_ret; } - /* Repeat as sometimes doesn't work first time? */ + /* Repeat as sometimes doesn't work first time?*/ ret = lis3l02dq_spi_write_reg_8(indio_dev, LIS3L02DQ_REG_CTRL_1_ADDR, val); @@ -538,7 +538,7 @@ static irqreturn_t lis3l02dq_event_handler(int irq, void *private) .event_mask = LIS3L02DQ_EVENT_MASK, \ } -static const struct iio_chan_spec lis3l02dq_channels[] = { +static struct iio_chan_spec lis3l02dq_channels[] = { LIS3L02DQ_CHAN(0, IIO_MOD_X), LIS3L02DQ_CHAN(1, IIO_MOD_Y), LIS3L02DQ_CHAN(2, IIO_MOD_Z), @@ -686,7 +686,7 @@ static int __devinit lis3l02dq_probe(struct spi_device *spi) goto error_ret; } st = iio_priv(indio_dev); - /* this is only used for removal purposes */ + /* this is only used tor removal purposes */ spi_set_drvdata(spi, indio_dev); st->us = spi; @@ -780,15 +780,21 @@ static int lis3l02dq_stop_device(struct iio_dev *indio_dev) } /* fixme, confirm ordering in this function */ -static int __devexit lis3l02dq_remove(struct spi_device *spi) +static int lis3l02dq_remove(struct spi_device *spi) { + int ret; struct iio_dev *indio_dev = spi_get_drvdata(spi); struct lis3l02dq_state *st = iio_priv(indio_dev); iio_device_unregister(indio_dev); - lis3l02dq_disable_all_events(indio_dev); - lis3l02dq_stop_device(indio_dev); + ret = lis3l02dq_disable_all_events(indio_dev); + if (ret) + goto err_ret; + + ret = lis3l02dq_stop_device(indio_dev); + if (ret) + goto err_ret; if (spi->irq && gpio_is_valid(irq_to_gpio(spi->irq)) > 0) free_irq(st->us->irq, indio_dev); @@ -798,8 +804,8 @@ static int __devexit lis3l02dq_remove(struct spi_device *spi) lis3l02dq_unconfigure_buffer(indio_dev); iio_device_free(indio_dev); - - return 0; +err_ret: + return ret; } static struct spi_driver lis3l02dq_driver = { @@ -812,7 +818,7 @@ static struct spi_driver lis3l02dq_driver = { }; module_spi_driver(lis3l02dq_driver); -MODULE_AUTHOR("Jonathan Cameron "); +MODULE_AUTHOR("Jonathan Cameron "); MODULE_DESCRIPTION("ST LIS3L02DQ Accelerometer SPI driver"); MODULE_LICENSE("GPL v2"); MODULE_ALIAS("spi:lis3l02dq"); diff --git a/trunk/drivers/staging/iio/accel/lis3l02dq_ring.c b/trunk/drivers/staging/iio/accel/lis3l02dq_ring.c index fa4190d96247..18d108fd967a 100644 --- a/trunk/drivers/staging/iio/accel/lis3l02dq_ring.c +++ b/trunk/drivers/staging/iio/accel/lis3l02dq_ring.c @@ -14,7 +14,7 @@ #include "lis3l02dq.h" /** - * combine_8_to_16() utility function to munge two u8s into u16 + * combine_8_to_16() utility function to munge to u8s into u16 **/ static inline u16 combine_8_to_16(u8 lower, u8 upper) { @@ -49,7 +49,7 @@ static const u8 read_all_tx_array[] = { /** * lis3l02dq_read_all() Reads all channels currently selected - * @indio_dev: IIO device state + * @st: device specific state * @rx_array: (dma capable) receive array, must be at least * 4*number of channels **/ @@ -121,10 +121,8 @@ static int lis3l02dq_get_buffer_element(struct iio_dev *indio_dev, if (rx_array == NULL) return -ENOMEM; ret = lis3l02dq_read_all(indio_dev, rx_array); - if (ret < 0) { - kfree(rx_array); + if (ret < 0) return ret; - } for (i = 0; i < scan_count; i++) data[i] = combine_8_to_16(rx_array[i*4+1], rx_array[i*4+3]); @@ -137,6 +135,7 @@ static irqreturn_t lis3l02dq_trigger_handler(int irq, void *p) { struct iio_poll_func *pf = p; struct iio_dev *indio_dev = pf->indio_dev; + struct iio_buffer *buffer = indio_dev->buffer; int len = 0; char *data; @@ -154,7 +153,7 @@ static irqreturn_t lis3l02dq_trigger_handler(int irq, void *p) if (indio_dev->scan_timestamp) *(s64 *)((u8 *)data + ALIGN(len, sizeof(s64))) = pf->timestamp; - iio_push_to_buffer(indio_dev->buffer, (u8 *)data); + buffer->access->store_to(buffer, (u8 *)data, pf->timestamp); kfree(data); done: @@ -171,22 +170,22 @@ __lis3l02dq_write_data_ready_config(struct iio_dev *indio_dev, bool state) bool currentlyset; struct lis3l02dq_state *st = iio_priv(indio_dev); - /* Get the current event mask register */ +/* Get the current event mask register */ ret = lis3l02dq_spi_read_reg_8(indio_dev, LIS3L02DQ_REG_CTRL_2_ADDR, &valold); if (ret) goto error_ret; - /* Find out if data ready is already on */ +/* Find out if data ready is already on */ currentlyset = valold & LIS3L02DQ_REG_CTRL_2_ENABLE_DATA_READY_GENERATION; - /* Disable requested */ +/* Disable requested */ if (!state && currentlyset) { - /* Disable the data ready signal */ + /* disable the data ready signal */ valold &= ~LIS3L02DQ_REG_CTRL_2_ENABLE_DATA_READY_GENERATION; - /* The double write is to overcome a hardware bug? */ + /* The double write is to overcome a hardware bug?*/ ret = lis3l02dq_spi_write_reg_8(indio_dev, LIS3L02DQ_REG_CTRL_2_ADDR, valold); @@ -198,10 +197,10 @@ __lis3l02dq_write_data_ready_config(struct iio_dev *indio_dev, bool state) if (ret) goto error_ret; st->trigger_on = false; - /* Enable requested */ +/* Enable requested */ } else if (state && !currentlyset) { - /* If not set, enable requested - * first disable all events */ + /* if not set, enable requested */ + /* first disable all events */ ret = lis3l02dq_disable_all_events(indio_dev); if (ret < 0) goto error_ret; @@ -240,7 +239,7 @@ static int lis3l02dq_data_rdy_trigger_set_state(struct iio_trigger *trig, if (state == false) { /* * A possible quirk with the handler is currently worked around - * by ensuring outstanding read events are cleared. + * by ensuring outstanding read events are cleared. */ ret = lis3l02dq_read_all(indio_dev, NULL); } @@ -251,7 +250,7 @@ static int lis3l02dq_data_rdy_trigger_set_state(struct iio_trigger *trig, } /** - * lis3l02dq_trig_try_reen() try reenabling irq for data rdy trigger + * lis3l02dq_trig_try_reen() try renabling irq for data rdy trigger * @trig: the datardy trigger */ static int lis3l02dq_trig_try_reen(struct iio_trigger *trig) @@ -260,8 +259,8 @@ static int lis3l02dq_trig_try_reen(struct iio_trigger *trig) struct lis3l02dq_state *st = iio_priv(indio_dev); int i; - /* If gpio still high (or high again) - * In theory possible we will need to do this several times */ + /* If gpio still high (or high again) */ + /* In theory possible we will need to do this several times */ for (i = 0; i < 5; i++) if (gpio_get_value(irq_to_gpio(st->us->irq))) lis3l02dq_read_all(indio_dev, NULL); diff --git a/trunk/drivers/staging/iio/accel/sca3000.h b/trunk/drivers/staging/iio/accel/sca3000.h index c1016c510dae..131daac90012 100644 --- a/trunk/drivers/staging/iio/accel/sca3000.h +++ b/trunk/drivers/staging/iio/accel/sca3000.h @@ -2,7 +2,7 @@ * sca3000.c -- support VTI sca3000 series accelerometers * via SPI * - * Copyright (c) 2007 Jonathan Cameron + * Copyright (c) 2007 Jonathan Cameron * * Partly based upon tle62x0.c * diff --git a/trunk/drivers/staging/iio/accel/sca3000_core.c b/trunk/drivers/staging/iio/accel/sca3000_core.c index ffd1697a9db0..c218d71abf1f 100644 --- a/trunk/drivers/staging/iio/accel/sca3000_core.c +++ b/trunk/drivers/staging/iio/accel/sca3000_core.c @@ -5,7 +5,7 @@ * under the terms of the GNU General Public License version 2 as published by * the Free Software Foundation. * - * Copyright (c) 2009 Jonathan Cameron + * Copyright (c) 2009 Jonathan Cameron * * See industrialio/accels/sca3000.h for comments. */ @@ -450,7 +450,7 @@ static IIO_DEVICE_ATTR(revision, S_IRUGO, sca3000_show_rev, NULL, 0); .event_mask = SCA3000_EVENT_MASK, \ } -static const struct iio_chan_spec sca3000_channels[] = { +static struct iio_chan_spec sca3000_channels[] = { SCA3000_CHAN(0, IIO_MOD_X), SCA3000_CHAN(1, IIO_MOD_Y), SCA3000_CHAN(2, IIO_MOD_Z), @@ -1233,13 +1233,15 @@ static int sca3000_stop_all_interrupts(struct sca3000_state *st) return ret; } -static int __devexit sca3000_remove(struct spi_device *spi) +static int sca3000_remove(struct spi_device *spi) { struct iio_dev *indio_dev = spi_get_drvdata(spi); struct sca3000_state *st = iio_priv(indio_dev); - + int ret; /* Must ensure no interrupts can be generated after this!*/ - sca3000_stop_all_interrupts(st); + ret = sca3000_stop_all_interrupts(st); + if (ret) + return ret; if (spi->irq) free_irq(spi->irq, indio_dev); iio_device_unregister(indio_dev); @@ -1270,6 +1272,6 @@ static struct spi_driver sca3000_driver = { }; module_spi_driver(sca3000_driver); -MODULE_AUTHOR("Jonathan Cameron "); +MODULE_AUTHOR("Jonathan Cameron "); MODULE_DESCRIPTION("VTI SCA3000 Series Accelerometers SPI driver"); MODULE_LICENSE("GPL v2"); diff --git a/trunk/drivers/staging/iio/accel/sca3000_ring.c b/trunk/drivers/staging/iio/accel/sca3000_ring.c index cbec2f1665e5..b7e1a002630a 100644 --- a/trunk/drivers/staging/iio/accel/sca3000_ring.c +++ b/trunk/drivers/staging/iio/accel/sca3000_ring.c @@ -5,7 +5,7 @@ * under the terms of the GNU General Public License version 2 as published by * the Free Software Foundation. * - * Copyright (c) 2009 Jonathan Cameron + * Copyright (c) 2009 Jonathan Cameron * */ diff --git a/trunk/drivers/staging/iio/adc/Kconfig b/trunk/drivers/staging/iio/adc/Kconfig index a525143ecbea..67711b7d718a 100644 --- a/trunk/drivers/staging/iio/adc/Kconfig +++ b/trunk/drivers/staging/iio/adc/Kconfig @@ -68,6 +68,20 @@ config AD799X_RING_BUFFER Say yes here to include ring buffer support in the AD799X ADC driver. +config AD7476 + tristate "Analog Devices AD7475/6/7/8 AD7466/7/8 and AD7495 ADC driver" + depends on SPI + select IIO_BUFFER + select IIO_TRIGGERED_BUFFER + help + Say yes here to build support for Analog Devices + AD7475, AD7476, AD7477, AD7478, AD7466, AD7467, AD7468, AD7495 + SPI analog to digital converters (ADC). + If unsure, say N (but it's safe to say "Y"). + + To compile this driver as a module, choose M here: the + module will be called ad7476. + config AD7887 tristate "Analog Devices AD7887 ADC driver" depends on SPI @@ -82,12 +96,11 @@ config AD7887 module will be called ad7887. config AD7780 - tristate "Analog Devices AD7780 and similar ADCs driver" + tristate "Analog Devices AD7780 AD7781 ADC driver" depends on SPI depends on GPIOLIB - select AD_SIGMA_DELTA help - Say yes here to build support for Analog Devices AD7170, AD7171, + Say yes here to build support for Analog Devices AD7780 and AD7781 SPI analog to digital converters (ADC). If unsure, say N (but it's safe to say "Y"). @@ -95,12 +108,13 @@ config AD7780 module will be called ad7780. config AD7793 - tristate "Analog Devices AD7793 and similar ADCs driver" + tristate "Analog Devices AD7792 AD7793 ADC driver" depends on SPI - select AD_SIGMA_DELTA + select IIO_BUFFER + select IIO_TRIGGERED_BUFFER help - Say yes here to build support for Analog Devices AD7785, AD7792, AD7793, - AD7794 and AD7795 SPI analog to digital converters (ADC). + Say yes here to build support for Analog Devices + AD7792 and AD7793 SPI analog to digital converters (ADC). If unsure, say N (but it's safe to say "Y"). To compile this driver as a module, choose M here: the @@ -117,7 +131,8 @@ config AD7816 config AD7192 tristate "Analog Devices AD7190 AD7192 AD7195 ADC driver" depends on SPI - select AD_SIGMA_DELTA + select IIO_BUFFER + select IIO_TRIGGERED_BUFFER help Say yes here to build support for Analog Devices AD7190, AD7192 or AD7195 SPI analog to digital converters (ADC). @@ -185,18 +200,6 @@ config LPC32XX_ADC activate only one via device tree selection. Provides direct access via sysfs. -config MXS_LRADC - tristate "Freescale i.MX28 LRADC" - depends on ARCH_MXS - select IIO_BUFFER - select IIO_TRIGGERED_BUFFER - help - Say yes here to build support for i.MX28 LRADC convertor - built into these chips. - - To compile this driver as a module, choose M here: the - module will be called mxs-lradc. - config SPEAR_ADC tristate "ST SPEAr ADC" depends on PLAT_SPEAR diff --git a/trunk/drivers/staging/iio/adc/Makefile b/trunk/drivers/staging/iio/adc/Makefile index 62ee02e80cf9..14e98b62b70a 100644 --- a/trunk/drivers/staging/iio/adc/Makefile +++ b/trunk/drivers/staging/iio/adc/Makefile @@ -17,6 +17,10 @@ ad799x-y := ad799x_core.o ad799x-$(CONFIG_AD799X_RING_BUFFER) += ad799x_ring.o obj-$(CONFIG_AD799X) += ad799x.o +ad7476-y := ad7476_core.o +ad7476-$(CONFIG_IIO_BUFFER) += ad7476_ring.o +obj-$(CONFIG_AD7476) += ad7476.o + ad7887-y := ad7887_core.o ad7887-$(CONFIG_IIO_BUFFER) += ad7887_ring.o obj-$(CONFIG_AD7887) += ad7887.o @@ -34,5 +38,4 @@ obj-$(CONFIG_ADT7310) += adt7310.o obj-$(CONFIG_ADT7410) += adt7410.o obj-$(CONFIG_AD7280) += ad7280a.o obj-$(CONFIG_LPC32XX_ADC) += lpc32xx_adc.o -obj-$(CONFIG_MXS_LRADC) += mxs-lradc.o obj-$(CONFIG_SPEAR_ADC) += spear_adc.o diff --git a/trunk/drivers/staging/iio/adc/ad7192.c b/trunk/drivers/staging/iio/adc/ad7192.c index aeaa61d49f51..22c3923d55eb 100644 --- a/trunk/drivers/staging/iio/adc/ad7192.c +++ b/trunk/drivers/staging/iio/adc/ad7192.c @@ -23,7 +23,6 @@ #include #include #include -#include #include "ad7192.h" @@ -58,7 +57,6 @@ /* Mode Register Bit Designations (AD7192_REG_MODE) */ #define AD7192_MODE_SEL(x) (((x) & 0x7) << 21) /* Operation Mode Select */ -#define AD7192_MODE_SEL_MASK (0x7 << 21) /* Operation Mode Select Mask */ #define AD7192_MODE_DAT_STA (1 << 20) /* Status Register transmission */ #define AD7192_MODE_CLKSRC(x) (((x) & 0x3) << 18) /* Clock Source Select */ #define AD7192_MODE_SINC3 (1 << 15) /* SINC3 Filter Select */ @@ -93,8 +91,7 @@ #define AD7192_CONF_CHOP (1 << 23) /* CHOP enable */ #define AD7192_CONF_REFSEL (1 << 20) /* REFIN1/REFIN2 Reference Select */ -#define AD7192_CONF_CHAN(x) (((1 << (x)) & 0xFF) << 8) /* Channel select */ -#define AD7192_CONF_CHAN_MASK (0xFF << 8) /* Channel select mask */ +#define AD7192_CONF_CHAN(x) (((x) & 0xFF) << 8) /* Channel select */ #define AD7192_CONF_BURN (1 << 7) /* Burnout current enable */ #define AD7192_CONF_REFDET (1 << 6) /* Reference detect enable */ #define AD7192_CONF_BUF (1 << 4) /* Buffered Mode Enable */ @@ -136,7 +133,13 @@ */ struct ad7192_state { + struct spi_device *spi; + struct iio_trigger *trig; struct regulator *reg; + struct ad7192_platform_data *pdata; + wait_queue_head_t wq_data_avail; + bool done; + bool irq_dis; u16 int_vref_mv; u32 mclk; u32 f_order; @@ -145,45 +148,178 @@ struct ad7192_state { u32 scale_avail[8][2]; u8 gpocon; u8 devid; - - struct ad_sigma_delta sd; + /* + * DMA (thus cache coherency maintenance) requires the + * transfer buffers to live in their own cache lines. + */ + u8 data[4] ____cacheline_aligned; }; -static struct ad7192_state *ad_sigma_delta_to_ad7192(struct ad_sigma_delta *sd) +static int __ad7192_write_reg(struct ad7192_state *st, bool locked, + bool cs_change, unsigned char reg, + unsigned size, unsigned val) { - return container_of(sd, struct ad7192_state, sd); + u8 *data = st->data; + struct spi_transfer t = { + .tx_buf = data, + .len = size + 1, + .cs_change = cs_change, + }; + struct spi_message m; + + data[0] = AD7192_COMM_WRITE | AD7192_COMM_ADDR(reg); + + switch (size) { + case 3: + data[1] = val >> 16; + data[2] = val >> 8; + data[3] = val; + break; + case 2: + data[1] = val >> 8; + data[2] = val; + break; + case 1: + data[1] = val; + break; + default: + return -EINVAL; + } + + spi_message_init(&m); + spi_message_add_tail(&t, &m); + + if (locked) + return spi_sync_locked(st->spi, &m); + else + return spi_sync(st->spi, &m); } -static int ad7192_set_channel(struct ad_sigma_delta *sd, unsigned int channel) +static int ad7192_write_reg(struct ad7192_state *st, + unsigned reg, unsigned size, unsigned val) { - struct ad7192_state *st = ad_sigma_delta_to_ad7192(sd); + return __ad7192_write_reg(st, false, false, reg, size, val); +} + +static int __ad7192_read_reg(struct ad7192_state *st, bool locked, + bool cs_change, unsigned char reg, + int *val, unsigned size) +{ + u8 *data = st->data; + int ret; + struct spi_transfer t[] = { + { + .tx_buf = data, + .len = 1, + }, { + .rx_buf = data, + .len = size, + .cs_change = cs_change, + }, + }; + struct spi_message m; + + data[0] = AD7192_COMM_READ | AD7192_COMM_ADDR(reg); + + spi_message_init(&m); + spi_message_add_tail(&t[0], &m); + spi_message_add_tail(&t[1], &m); + + if (locked) + ret = spi_sync_locked(st->spi, &m); + else + ret = spi_sync(st->spi, &m); + + if (ret < 0) + return ret; + + switch (size) { + case 3: + *val = data[0] << 16 | data[1] << 8 | data[2]; + break; + case 2: + *val = data[0] << 8 | data[1]; + break; + case 1: + *val = data[0]; + break; + default: + return -EINVAL; + } - st->conf &= ~AD7192_CONF_CHAN_MASK; - st->conf |= AD7192_CONF_CHAN(channel); + return 0; +} - return ad_sd_write_reg(&st->sd, AD7192_REG_CONF, 3, st->conf); +static int ad7192_read_reg(struct ad7192_state *st, + unsigned reg, int *val, unsigned size) +{ + return __ad7192_read_reg(st, 0, 0, reg, val, size); } -static int ad7192_set_mode(struct ad_sigma_delta *sd, - enum ad_sigma_delta_mode mode) +static int ad7192_read(struct ad7192_state *st, unsigned ch, + unsigned len, int *val) { - struct ad7192_state *st = ad_sigma_delta_to_ad7192(sd); + int ret; + st->conf = (st->conf & ~AD7192_CONF_CHAN(-1)) | + AD7192_CONF_CHAN(1 << ch); + st->mode = (st->mode & ~AD7192_MODE_SEL(-1)) | + AD7192_MODE_SEL(AD7192_MODE_SINGLE); + + ad7192_write_reg(st, AD7192_REG_CONF, 3, st->conf); - st->mode &= ~AD7192_MODE_SEL_MASK; - st->mode |= AD7192_MODE_SEL(mode); + spi_bus_lock(st->spi->master); + st->done = false; - return ad_sd_write_reg(&st->sd, AD7192_REG_MODE, 3, st->mode); + ret = __ad7192_write_reg(st, 1, 1, AD7192_REG_MODE, 3, st->mode); + if (ret < 0) + goto out; + + st->irq_dis = false; + enable_irq(st->spi->irq); + wait_event_interruptible(st->wq_data_avail, st->done); + + ret = __ad7192_read_reg(st, 1, 0, AD7192_REG_DATA, val, len); +out: + spi_bus_unlock(st->spi->master); + + return ret; } -static const struct ad_sigma_delta_info ad7192_sigma_delta_info = { - .set_channel = ad7192_set_channel, - .set_mode = ad7192_set_mode, - .has_registers = true, - .addr_shift = 3, - .read_mask = BIT(6), -}; +static int ad7192_calibrate(struct ad7192_state *st, unsigned mode, unsigned ch) +{ + int ret; + + st->conf = (st->conf & ~AD7192_CONF_CHAN(-1)) | + AD7192_CONF_CHAN(1 << ch); + st->mode = (st->mode & ~AD7192_MODE_SEL(-1)) | AD7192_MODE_SEL(mode); + + ad7192_write_reg(st, AD7192_REG_CONF, 3, st->conf); -static const struct ad_sd_calib_data ad7192_calib_arr[8] = { + spi_bus_lock(st->spi->master); + st->done = false; + + ret = __ad7192_write_reg(st, 1, 1, AD7192_REG_MODE, 3, + (st->devid != ID_AD7195) ? + st->mode | AD7192_MODE_CLKDIV : + st->mode); + if (ret < 0) + goto out; + + st->irq_dis = false; + enable_irq(st->spi->irq); + wait_event_interruptible(st->wq_data_avail, st->done); + + st->mode = (st->mode & ~AD7192_MODE_SEL(-1)) | + AD7192_MODE_SEL(AD7192_MODE_IDLE); + + ret = __ad7192_write_reg(st, 1, 0, AD7192_REG_MODE, 3, st->mode); +out: + spi_bus_unlock(st->spi->master); + + return ret; +} + +static const u8 ad7192_calib_arr[8][2] = { {AD7192_MODE_CAL_INT_ZERO, AD7192_CH_AIN1}, {AD7192_MODE_CAL_INT_FULL, AD7192_CH_AIN1}, {AD7192_MODE_CAL_INT_ZERO, AD7192_CH_AIN2}, @@ -196,34 +332,45 @@ static const struct ad_sd_calib_data ad7192_calib_arr[8] = { static int ad7192_calibrate_all(struct ad7192_state *st) { - return ad_sd_calibrate_all(&st->sd, ad7192_calib_arr, - ARRAY_SIZE(ad7192_calib_arr)); + int i, ret; + + for (i = 0; i < ARRAY_SIZE(ad7192_calib_arr); i++) { + ret = ad7192_calibrate(st, ad7192_calib_arr[i][0], + ad7192_calib_arr[i][1]); + if (ret) + goto out; + } + + return 0; +out: + dev_err(&st->spi->dev, "Calibration failed\n"); + return ret; } -static int ad7192_setup(struct ad7192_state *st, - const struct ad7192_platform_data *pdata) +static int ad7192_setup(struct ad7192_state *st) { - struct iio_dev *indio_dev = spi_get_drvdata(st->sd.spi); + struct iio_dev *indio_dev = spi_get_drvdata(st->spi); + struct ad7192_platform_data *pdata = st->pdata; unsigned long long scale_uv; int i, ret, id; u8 ones[6]; /* reset the serial interface */ memset(&ones, 0xFF, 6); - ret = spi_write(st->sd.spi, &ones, 6); + ret = spi_write(st->spi, &ones, 6); if (ret < 0) goto out; msleep(1); /* Wait for at least 500us */ /* write/read test for device presence */ - ret = ad_sd_read_reg(&st->sd, AD7192_REG_ID, 1, &id); + ret = ad7192_read_reg(st, AD7192_REG_ID, &id, 1); if (ret) goto out; id &= AD7192_ID_MASK; if (id != st->devid) - dev_warn(&st->sd.spi->dev, "device ID query failed (0x%X)\n", id); + dev_warn(&st->spi->dev, "device ID query failed (0x%X)\n", id); switch (pdata->clock_source_sel) { case AD7192_CLK_EXT_MCLK1_2: @@ -276,11 +423,11 @@ static int ad7192_setup(struct ad7192_state *st, if (pdata->burnout_curr_en) st->conf |= AD7192_CONF_BURN; - ret = ad_sd_write_reg(&st->sd, AD7192_REG_MODE, 3, st->mode); + ret = ad7192_write_reg(st, AD7192_REG_MODE, 3, st->mode); if (ret) goto out; - ret = ad_sd_write_reg(&st->sd, AD7192_REG_CONF, 3, st->conf); + ret = ad7192_write_reg(st, AD7192_REG_CONF, 3, st->conf); if (ret) goto out; @@ -301,10 +448,181 @@ static int ad7192_setup(struct ad7192_state *st, return 0; out: - dev_err(&st->sd.spi->dev, "setup failed\n"); + dev_err(&st->spi->dev, "setup failed\n"); + return ret; +} + +static int ad7192_ring_preenable(struct iio_dev *indio_dev) +{ + struct ad7192_state *st = iio_priv(indio_dev); + unsigned channel; + int ret; + + if (bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength)) + return -EINVAL; + + ret = iio_sw_buffer_preenable(indio_dev); + if (ret < 0) + return ret; + + channel = find_first_bit(indio_dev->active_scan_mask, + indio_dev->masklength); + + st->mode = (st->mode & ~AD7192_MODE_SEL(-1)) | + AD7192_MODE_SEL(AD7192_MODE_CONT); + st->conf = (st->conf & ~AD7192_CONF_CHAN(-1)) | + AD7192_CONF_CHAN(1 << indio_dev->channels[channel].address); + + ad7192_write_reg(st, AD7192_REG_CONF, 3, st->conf); + + spi_bus_lock(st->spi->master); + __ad7192_write_reg(st, 1, 1, AD7192_REG_MODE, 3, st->mode); + + st->irq_dis = false; + enable_irq(st->spi->irq); + + return 0; +} + +static int ad7192_ring_postdisable(struct iio_dev *indio_dev) +{ + struct ad7192_state *st = iio_priv(indio_dev); + + st->mode = (st->mode & ~AD7192_MODE_SEL(-1)) | + AD7192_MODE_SEL(AD7192_MODE_IDLE); + + st->done = false; + wait_event_interruptible(st->wq_data_avail, st->done); + + if (!st->irq_dis) + disable_irq_nosync(st->spi->irq); + + __ad7192_write_reg(st, 1, 0, AD7192_REG_MODE, 3, st->mode); + + return spi_bus_unlock(st->spi->master); +} + +/** + * ad7192_trigger_handler() bh of trigger launched polling to ring buffer + **/ +static irqreturn_t ad7192_trigger_handler(int irq, void *p) +{ + struct iio_poll_func *pf = p; + struct iio_dev *indio_dev = pf->indio_dev; + struct iio_buffer *ring = indio_dev->buffer; + struct ad7192_state *st = iio_priv(indio_dev); + s64 dat64[2]; + s32 *dat32 = (s32 *)dat64; + + if (!bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength)) + __ad7192_read_reg(st, 1, 1, AD7192_REG_DATA, + dat32, + indio_dev->channels[0].scan_type.realbits/8); + + /* Guaranteed to be aligned with 8 byte boundary */ + if (indio_dev->scan_timestamp) + dat64[1] = pf->timestamp; + + ring->access->store_to(ring, (u8 *)dat64, pf->timestamp); + + iio_trigger_notify_done(indio_dev->trig); + st->irq_dis = false; + enable_irq(st->spi->irq); + + return IRQ_HANDLED; +} + +static const struct iio_buffer_setup_ops ad7192_ring_setup_ops = { + .preenable = &ad7192_ring_preenable, + .postenable = &iio_triggered_buffer_postenable, + .predisable = &iio_triggered_buffer_predisable, + .postdisable = &ad7192_ring_postdisable, + .validate_scan_mask = &iio_validate_scan_mask_onehot, +}; + +static int ad7192_register_ring_funcs_and_init(struct iio_dev *indio_dev) +{ + return iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time, + &ad7192_trigger_handler, &ad7192_ring_setup_ops); +} + +static void ad7192_ring_cleanup(struct iio_dev *indio_dev) +{ + iio_triggered_buffer_cleanup(indio_dev); +} + +/** + * ad7192_data_rdy_trig_poll() the event handler for the data rdy trig + **/ +static irqreturn_t ad7192_data_rdy_trig_poll(int irq, void *private) +{ + struct ad7192_state *st = iio_priv(private); + + st->done = true; + wake_up_interruptible(&st->wq_data_avail); + disable_irq_nosync(irq); + st->irq_dis = true; + iio_trigger_poll(st->trig, iio_get_time_ns()); + + return IRQ_HANDLED; +} + +static struct iio_trigger_ops ad7192_trigger_ops = { + .owner = THIS_MODULE, +}; + +static int ad7192_probe_trigger(struct iio_dev *indio_dev) +{ + struct ad7192_state *st = iio_priv(indio_dev); + int ret; + + st->trig = iio_trigger_alloc("%s-dev%d", + spi_get_device_id(st->spi)->name, + indio_dev->id); + if (st->trig == NULL) { + ret = -ENOMEM; + goto error_ret; + } + st->trig->ops = &ad7192_trigger_ops; + ret = request_irq(st->spi->irq, + ad7192_data_rdy_trig_poll, + IRQF_TRIGGER_LOW, + spi_get_device_id(st->spi)->name, + indio_dev); + if (ret) + goto error_free_trig; + + disable_irq_nosync(st->spi->irq); + st->irq_dis = true; + st->trig->dev.parent = &st->spi->dev; + st->trig->private_data = indio_dev; + + ret = iio_trigger_register(st->trig); + + /* select default trigger */ + indio_dev->trig = st->trig; + if (ret) + goto error_free_irq; + + return 0; + +error_free_irq: + free_irq(st->spi->irq, indio_dev); +error_free_trig: + iio_trigger_free(st->trig); +error_ret: return ret; } +static void ad7192_remove_trigger(struct iio_dev *indio_dev) +{ + struct ad7192_state *st = iio_priv(indio_dev); + + iio_trigger_unregister(st->trig); + free_irq(st->spi->irq, indio_dev); + iio_trigger_free(st->trig); +} + static ssize_t ad7192_read_frequency(struct device *dev, struct device_attribute *attr, char *buf) @@ -329,8 +647,6 @@ static ssize_t ad7192_write_frequency(struct device *dev, ret = strict_strtoul(buf, 10, &lval); if (ret) return ret; - if (lval == 0) - return -EINVAL; mutex_lock(&indio_dev->mlock); if (iio_buffer_enabled(indio_dev)) { @@ -346,7 +662,7 @@ static ssize_t ad7192_write_frequency(struct device *dev, st->mode &= ~AD7192_MODE_RATE(-1); st->mode |= AD7192_MODE_RATE(div); - ad_sd_write_reg(&st->sd, AD7192_REG_MODE, 3, st->mode); + ad7192_write_reg(st, AD7192_REG_MODE, 3, st->mode); out: mutex_unlock(&indio_dev->mlock); @@ -358,6 +674,7 @@ static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO, ad7192_read_frequency, ad7192_write_frequency); + static ssize_t ad7192_show_scale_available(struct device *dev, struct device_attribute *attr, char *buf) { @@ -429,7 +746,7 @@ static ssize_t ad7192_set(struct device *dev, else st->gpocon &= ~AD7192_GPOCON_BPDSW; - ad_sd_write_reg(&st->sd, AD7192_REG_GPOCON, 1, st->gpocon); + ad7192_write_reg(st, AD7192_REG_GPOCON, 1, st->gpocon); break; case AD7192_REG_MODE: if (val) @@ -437,7 +754,7 @@ static ssize_t ad7192_set(struct device *dev, else st->mode &= ~AD7192_MODE_ACX; - ad_sd_write_reg(&st->sd, AD7192_REG_MODE, 3, st->mode); + ad7192_write_reg(st, AD7192_REG_GPOCON, 3, st->mode); break; default: ret = -EINVAL; @@ -481,11 +798,6 @@ static const struct attribute_group ad7195_attribute_group = { .attrs = ad7195_attributes, }; -static unsigned int ad7192_get_temp_scale(bool unipolar) -{ - return unipolar ? 2815 * 2 : 2815; -} - static int ad7192_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val, @@ -493,11 +805,40 @@ static int ad7192_read_raw(struct iio_dev *indio_dev, long m) { struct ad7192_state *st = iio_priv(indio_dev); + int ret, smpl = 0; bool unipolar = !!(st->conf & AD7192_CONF_UNIPOLAR); switch (m) { case IIO_CHAN_INFO_RAW: - return ad_sigma_delta_single_conversion(indio_dev, chan, val); + mutex_lock(&indio_dev->mlock); + if (iio_buffer_enabled(indio_dev)) + ret = -EBUSY; + else + ret = ad7192_read(st, chan->address, + chan->scan_type.realbits / 8, &smpl); + mutex_unlock(&indio_dev->mlock); + + if (ret < 0) + return ret; + + *val = (smpl >> chan->scan_type.shift) & + ((1 << (chan->scan_type.realbits)) - 1); + + switch (chan->type) { + case IIO_VOLTAGE: + if (!unipolar) + *val -= (1 << (chan->scan_type.realbits - 1)); + break; + case IIO_TEMP: + *val -= 0x800000; + *val /= 2815; /* temp Kelvin */ + *val -= 273; /* temp Celsius */ + break; + default: + return -EINVAL; + } + return IIO_VAL_INT; + case IIO_CHAN_INFO_SCALE: switch (chan->type) { case IIO_VOLTAGE: @@ -507,21 +848,11 @@ static int ad7192_read_raw(struct iio_dev *indio_dev, mutex_unlock(&indio_dev->mlock); return IIO_VAL_INT_PLUS_NANO; case IIO_TEMP: - *val = 0; - *val2 = 1000000000 / ad7192_get_temp_scale(unipolar); - return IIO_VAL_INT_PLUS_NANO; + *val = 1000; + return IIO_VAL_INT; default: return -EINVAL; } - case IIO_CHAN_INFO_OFFSET: - if (!unipolar) - *val = -(1 << (chan->scan_type.realbits - 1)); - else - *val = 0; - /* Kelvin to Celsius */ - if (chan->type == IIO_TEMP) - *val -= 273 * ad7192_get_temp_scale(unipolar); - return IIO_VAL_INT; } return -EINVAL; @@ -548,18 +879,18 @@ static int ad7192_write_raw(struct iio_dev *indio_dev, ret = -EINVAL; for (i = 0; i < ARRAY_SIZE(st->scale_avail); i++) if (val2 == st->scale_avail[i][1]) { - ret = 0; tmp = st->conf; st->conf &= ~AD7192_CONF_GAIN(-1); st->conf |= AD7192_CONF_GAIN(i); - if (tmp == st->conf) - break; - ad_sd_write_reg(&st->sd, AD7192_REG_CONF, - 3, st->conf); - ad7192_calibrate_all(st); - break; + + if (tmp != st->conf) { + ad7192_write_reg(st, AD7192_REG_CONF, + 3, st->conf); + ad7192_calibrate_all(st); + } + ret = 0; } - break; + default: ret = -EINVAL; } @@ -569,6 +900,15 @@ static int ad7192_write_raw(struct iio_dev *indio_dev, return ret; } +static int ad7192_validate_trigger(struct iio_dev *indio_dev, + struct iio_trigger *trig) +{ + if (indio_dev->trig != trig) + return -EINVAL; + + return 0; +} + static int ad7192_write_raw_get_fmt(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, long mask) @@ -581,7 +921,7 @@ static const struct iio_info ad7192_info = { .write_raw = &ad7192_write_raw, .write_raw_get_fmt = &ad7192_write_raw_get_fmt, .attrs = &ad7192_attribute_group, - .validate_trigger = ad_sd_validate_trigger, + .validate_trigger = ad7192_validate_trigger, .driver_module = THIS_MODULE, }; @@ -590,25 +930,58 @@ static const struct iio_info ad7195_info = { .write_raw = &ad7192_write_raw, .write_raw_get_fmt = &ad7192_write_raw_get_fmt, .attrs = &ad7195_attribute_group, - .validate_trigger = ad_sd_validate_trigger, + .validate_trigger = ad7192_validate_trigger, .driver_module = THIS_MODULE, }; -static const struct iio_chan_spec ad7192_channels[] = { - AD_SD_DIFF_CHANNEL(0, 1, 2, AD7192_CH_AIN1P_AIN2M, 24, 32, 0), - AD_SD_DIFF_CHANNEL(1, 3, 4, AD7192_CH_AIN3P_AIN4M, 24, 32, 0), - AD_SD_TEMP_CHANNEL(2, AD7192_CH_TEMP, 24, 32, 0), - AD_SD_SHORTED_CHANNEL(3, 2, AD7192_CH_AIN2P_AIN2M, 24, 32, 0), - AD_SD_CHANNEL(4, 1, AD7192_CH_AIN1, 24, 32, 0), - AD_SD_CHANNEL(5, 2, AD7192_CH_AIN2, 24, 32, 0), - AD_SD_CHANNEL(6, 3, AD7192_CH_AIN3, 24, 32, 0), - AD_SD_CHANNEL(7, 4, AD7192_CH_AIN4, 24, 32, 0), +#define AD7192_CHAN_DIFF(_chan, _chan2, _name, _address, _si) \ + { .type = IIO_VOLTAGE, \ + .differential = 1, \ + .indexed = 1, \ + .extend_name = _name, \ + .channel = _chan, \ + .channel2 = _chan2, \ + .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \ + IIO_CHAN_INFO_SCALE_SHARED_BIT, \ + .address = _address, \ + .scan_index = _si, \ + .scan_type = IIO_ST('s', 24, 32, 0)} + +#define AD7192_CHAN(_chan, _address, _si) \ + { .type = IIO_VOLTAGE, \ + .indexed = 1, \ + .channel = _chan, \ + .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \ + IIO_CHAN_INFO_SCALE_SHARED_BIT, \ + .address = _address, \ + .scan_index = _si, \ + .scan_type = IIO_ST('s', 24, 32, 0)} + +#define AD7192_CHAN_TEMP(_chan, _address, _si) \ + { .type = IIO_TEMP, \ + .indexed = 1, \ + .channel = _chan, \ + .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \ + IIO_CHAN_INFO_SCALE_SEPARATE_BIT, \ + .address = _address, \ + .scan_index = _si, \ + .scan_type = IIO_ST('s', 24, 32, 0)} + +static struct iio_chan_spec ad7192_channels[] = { + AD7192_CHAN_DIFF(1, 2, NULL, AD7192_CH_AIN1P_AIN2M, 0), + AD7192_CHAN_DIFF(3, 4, NULL, AD7192_CH_AIN3P_AIN4M, 1), + AD7192_CHAN_TEMP(0, AD7192_CH_TEMP, 2), + AD7192_CHAN_DIFF(2, 2, "shorted", AD7192_CH_AIN2P_AIN2M, 3), + AD7192_CHAN(1, AD7192_CH_AIN1, 4), + AD7192_CHAN(2, AD7192_CH_AIN2, 5), + AD7192_CHAN(3, AD7192_CH_AIN3, 6), + AD7192_CHAN(4, AD7192_CH_AIN4, 7), IIO_CHAN_SOFT_TIMESTAMP(8), }; static int __devinit ad7192_probe(struct spi_device *spi) { - const struct ad7192_platform_data *pdata = spi->dev.platform_data; + struct ad7192_platform_data *pdata = spi->dev.platform_data; struct ad7192_state *st; struct iio_dev *indio_dev; int ret , voltage_uv = 0; @@ -638,6 +1011,8 @@ static int __devinit ad7192_probe(struct spi_device *spi) voltage_uv = regulator_get_voltage(st->reg); } + st->pdata = pdata; + if (pdata && pdata->vref_mv) st->int_vref_mv = pdata->vref_mv; else if (voltage_uv) @@ -646,6 +1021,7 @@ static int __devinit ad7192_probe(struct spi_device *spi) dev_warn(&spi->dev, "reference voltage undefined\n"); spi_set_drvdata(spi, indio_dev); + st->spi = spi; st->devid = spi_get_device_id(spi)->driver_data; indio_dev->dev.parent = &spi->dev; indio_dev->name = spi_get_device_id(spi)->name; @@ -657,13 +1033,17 @@ static int __devinit ad7192_probe(struct spi_device *spi) else indio_dev->info = &ad7192_info; - ad_sd_init(&st->sd, indio_dev, spi, &ad7192_sigma_delta_info); + init_waitqueue_head(&st->wq_data_avail); - ret = ad_sd_setup_buffer_and_trigger(indio_dev); + ret = ad7192_register_ring_funcs_and_init(indio_dev); if (ret) goto error_disable_reg; - ret = ad7192_setup(st, pdata); + ret = ad7192_probe_trigger(indio_dev); + if (ret) + goto error_ring_cleanup; + + ret = ad7192_setup(st); if (ret) goto error_remove_trigger; @@ -673,7 +1053,9 @@ static int __devinit ad7192_probe(struct spi_device *spi) return 0; error_remove_trigger: - ad_sd_cleanup_buffer_and_trigger(indio_dev); + ad7192_remove_trigger(indio_dev); +error_ring_cleanup: + ad7192_ring_cleanup(indio_dev); error_disable_reg: if (!IS_ERR(st->reg)) regulator_disable(st->reg); @@ -686,13 +1068,14 @@ static int __devinit ad7192_probe(struct spi_device *spi) return ret; } -static int __devexit ad7192_remove(struct spi_device *spi) +static int ad7192_remove(struct spi_device *spi) { struct iio_dev *indio_dev = spi_get_drvdata(spi); struct ad7192_state *st = iio_priv(indio_dev); iio_device_unregister(indio_dev); - ad_sd_cleanup_buffer_and_trigger(indio_dev); + ad7192_remove_trigger(indio_dev); + ad7192_ring_cleanup(indio_dev); if (!IS_ERR(st->reg)) { regulator_disable(st->reg); diff --git a/trunk/drivers/staging/iio/adc/ad7298_core.c b/trunk/drivers/staging/iio/adc/ad7298_core.c index 4c75114e7d7c..6141f4a70cfa 100644 --- a/trunk/drivers/staging/iio/adc/ad7298_core.c +++ b/trunk/drivers/staging/iio/adc/ad7298_core.c @@ -38,7 +38,7 @@ }, \ } -static const struct iio_chan_spec ad7298_channels[] = { +static struct iio_chan_spec ad7298_channels[] = { { .type = IIO_TEMP, .indexed = 1, diff --git a/trunk/drivers/staging/iio/adc/ad7298_ring.c b/trunk/drivers/staging/iio/adc/ad7298_ring.c index c2906a85fedb..fd1d855ff57a 100644 --- a/trunk/drivers/staging/iio/adc/ad7298_ring.c +++ b/trunk/drivers/staging/iio/adc/ad7298_ring.c @@ -75,7 +75,8 @@ static irqreturn_t ad7298_trigger_handler(int irq, void *p) struct iio_poll_func *pf = p; struct iio_dev *indio_dev = pf->indio_dev; struct ad7298_state *st = iio_priv(indio_dev); - s64 time_ns = 0; + struct iio_buffer *ring = indio_dev->buffer; + s64 time_ns; __u16 buf[16]; int b_sent, i; @@ -93,7 +94,7 @@ static irqreturn_t ad7298_trigger_handler(int irq, void *p) indio_dev->masklength); i++) buf[i] = be16_to_cpu(st->rx_buf[i]); - iio_push_to_buffer(indio_dev->buffer, (u8 *)buf); + indio_dev->buffer->access->store_to(ring, (u8 *)buf, time_ns); done: iio_trigger_notify_done(indio_dev->trig); diff --git a/trunk/drivers/staging/iio/adc/ad7476.h b/trunk/drivers/staging/iio/adc/ad7476.h new file mode 100644 index 000000000000..b1dd9317fe1f --- /dev/null +++ b/trunk/drivers/staging/iio/adc/ad7476.h @@ -0,0 +1,66 @@ +/* + * AD7476/5/7/8 (A) SPI ADC driver + * + * Copyright 2010 Analog Devices Inc. + * + * Licensed under the GPL-2 or later. + */ +#ifndef IIO_ADC_AD7476_H_ +#define IIO_ADC_AD7476_H_ + +#define RES_MASK(bits) ((1 << (bits)) - 1) + +/* + * TODO: struct ad7476_platform_data needs to go into include/linux/iio + */ + +struct ad7476_platform_data { + u16 vref_mv; +}; + +struct ad7476_chip_info { + u16 int_vref_mv; + struct iio_chan_spec channel[2]; +}; + +struct ad7476_state { + struct spi_device *spi; + const struct ad7476_chip_info *chip_info; + struct regulator *reg; + u16 int_vref_mv; + struct spi_transfer xfer; + struct spi_message msg; + /* + * DMA (thus cache coherency maintenance) requires the + * transfer buffers to live in their own cache lines. + */ + unsigned char data[2] ____cacheline_aligned; +}; + +enum ad7476_supported_device_ids { + ID_AD7466, + ID_AD7467, + ID_AD7468, + ID_AD7475, + ID_AD7476, + ID_AD7477, + ID_AD7478, + ID_AD7495 +}; + +#ifdef CONFIG_IIO_BUFFER +int ad7476_register_ring_funcs_and_init(struct iio_dev *indio_dev); +void ad7476_ring_cleanup(struct iio_dev *indio_dev); +#else /* CONFIG_IIO_BUFFER */ + +static inline int +ad7476_register_ring_funcs_and_init(struct iio_dev *indio_dev) +{ + return 0; +} + +static inline void ad7476_ring_cleanup(struct iio_dev *indio_dev) +{ +} +#endif /* CONFIG_IIO_BUFFER */ +#endif /* IIO_ADC_AD7476_H_ */ diff --git a/trunk/drivers/iio/adc/ad7476.c b/trunk/drivers/staging/iio/adc/ad7476_core.c similarity index 52% rename from trunk/drivers/iio/adc/ad7476.c rename to trunk/drivers/staging/iio/adc/ad7476_core.c index 7f2f45a0a48d..4d30a798ba0d 100644 --- a/trunk/drivers/iio/adc/ad7476.c +++ b/trunk/drivers/staging/iio/adc/ad7476_core.c @@ -18,76 +18,8 @@ #include #include #include -#include -#include -#define RES_MASK(bits) ((1 << (bits)) - 1) - -struct ad7476_state; - -struct ad7476_chip_info { - unsigned int int_vref_uv; - struct iio_chan_spec channel[2]; - void (*reset)(struct ad7476_state *); -}; - -struct ad7476_state { - struct spi_device *spi; - const struct ad7476_chip_info *chip_info; - struct regulator *reg; - struct spi_transfer xfer; - struct spi_message msg; - /* - * DMA (thus cache coherency maintenance) requires the - * transfer buffers to live in their own cache lines. - * Make the buffer large enough for one 16 bit sample and one 64 bit - * aligned 64 bit timestamp. - */ - unsigned char data[ALIGN(2, sizeof(s64)) + sizeof(s64)] - ____cacheline_aligned; -}; - -enum ad7476_supported_device_ids { - ID_AD7091R, - ID_AD7276, - ID_AD7277, - ID_AD7278, - ID_AD7466, - ID_AD7467, - ID_AD7468, - ID_AD7495, - ID_AD7940, -}; - -static irqreturn_t ad7476_trigger_handler(int irq, void *p) -{ - struct iio_poll_func *pf = p; - struct iio_dev *indio_dev = pf->indio_dev; - struct ad7476_state *st = iio_priv(indio_dev); - s64 time_ns; - int b_sent; - - b_sent = spi_sync(st->spi, &st->msg); - if (b_sent < 0) - goto done; - - time_ns = iio_get_time_ns(); - - if (indio_dev->scan_timestamp) - ((s64 *)st->data)[1] = time_ns; - - iio_push_to_buffer(indio_dev->buffer, st->data); -done: - iio_trigger_notify_done(indio_dev->trig); - - return IRQ_HANDLED; -} - -static void ad7091_reset(struct ad7476_state *st) -{ - /* Any transfers with 8 scl cycles will reset the device */ - spi_read(st->spi, st->data, 1); -} +#include "ad7476.h" static int ad7476_scan_direct(struct ad7476_state *st) { @@ -97,7 +29,7 @@ static int ad7476_scan_direct(struct ad7476_state *st) if (ret) return ret; - return be16_to_cpup((__be16 *)st->data); + return (st->data[0] << 8) | st->data[1]; } static int ad7476_read_raw(struct iio_dev *indio_dev, @@ -108,7 +40,7 @@ static int ad7476_read_raw(struct iio_dev *indio_dev, { int ret; struct ad7476_state *st = iio_priv(indio_dev); - int scale_uv; + unsigned int scale_uv; switch (m) { case IIO_CHAN_INFO_RAW: @@ -125,80 +57,62 @@ static int ad7476_read_raw(struct iio_dev *indio_dev, RES_MASK(st->chip_info->channel[0].scan_type.realbits); return IIO_VAL_INT; case IIO_CHAN_INFO_SCALE: - if (!st->chip_info->int_vref_uv) { - scale_uv = regulator_get_voltage(st->reg); - if (scale_uv < 0) - return scale_uv; - } else { - scale_uv = st->chip_info->int_vref_uv; - } - scale_uv >>= chan->scan_type.realbits; - *val = scale_uv / 1000; - *val2 = (scale_uv % 1000) * 1000; + scale_uv = (st->int_vref_mv * 1000) + >> st->chip_info->channel[0].scan_type.realbits; + *val = scale_uv/1000; + *val2 = (scale_uv%1000)*1000; return IIO_VAL_INT_PLUS_MICRO; } return -EINVAL; } -#define _AD7476_CHAN(bits, _shift, _info_mask) \ +#define AD7476_CHAN(bits) \ { \ .type = IIO_VOLTAGE, \ .indexed = 1, \ - .info_mask = _info_mask | \ + .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \ IIO_CHAN_INFO_SCALE_SHARED_BIT, \ .scan_type = { \ .sign = 'u', \ - .realbits = (bits), \ + .realbits = bits, \ .storagebits = 16, \ - .shift = (_shift), \ - .endianness = IIO_BE, \ + .shift = 12 - bits, \ }, \ } -#define AD7476_CHAN(bits) _AD7476_CHAN((bits), 13 - (bits), \ - IIO_CHAN_INFO_RAW_SEPARATE_BIT) -#define AD7940_CHAN(bits) _AD7476_CHAN((bits), 15 - (bits), \ - IIO_CHAN_INFO_RAW_SEPARATE_BIT) -#define AD7091R_CHAN(bits) _AD7476_CHAN((bits), 16 - (bits), 0) - static const struct ad7476_chip_info ad7476_chip_info_tbl[] = { - [ID_AD7091R] = { - .channel[0] = AD7091R_CHAN(12), + [ID_AD7466] = { + .channel[0] = AD7476_CHAN(12), .channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1), - .reset = ad7091_reset, }, - [ID_AD7276] = { - .channel[0] = AD7940_CHAN(12), + [ID_AD7467] = { + .channel[0] = AD7476_CHAN(10), .channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1), }, - [ID_AD7277] = { - .channel[0] = AD7940_CHAN(10), + [ID_AD7468] = { + .channel[0] = AD7476_CHAN(8), .channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1), }, - [ID_AD7278] = { - .channel[0] = AD7940_CHAN(8), + [ID_AD7475] = { + .channel[0] = AD7476_CHAN(12), .channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1), }, - [ID_AD7466] = { + [ID_AD7476] = { .channel[0] = AD7476_CHAN(12), .channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1), }, - [ID_AD7467] = { + [ID_AD7477] = { .channel[0] = AD7476_CHAN(10), .channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1), }, - [ID_AD7468] = { + [ID_AD7478] = { .channel[0] = AD7476_CHAN(8), .channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1), }, [ID_AD7495] = { .channel[0] = AD7476_CHAN(12), .channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1), - .int_vref_uv = 2500000, - }, - [ID_AD7940] = { - .channel[0] = AD7940_CHAN(14), - .channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1), + .int_vref_mv = 2500, }, }; @@ -209,9 +123,10 @@ static const struct iio_info ad7476_info = { static int __devinit ad7476_probe(struct spi_device *spi) { + struct ad7476_platform_data *pdata = spi->dev.platform_data; struct ad7476_state *st; struct iio_dev *indio_dev; - int ret; + int ret, voltage_uv = 0; indio_dev = iio_device_alloc(sizeof(*st)); if (indio_dev == NULL) { @@ -219,18 +134,25 @@ static int __devinit ad7476_probe(struct spi_device *spi) goto error_ret; } st = iio_priv(indio_dev); - st->chip_info = - &ad7476_chip_info_tbl[spi_get_device_id(spi)->driver_data]; - st->reg = regulator_get(&spi->dev, "vcc"); - if (IS_ERR(st->reg)) { - ret = PTR_ERR(st->reg); - goto error_free_dev; + if (!IS_ERR(st->reg)) { + ret = regulator_enable(st->reg); + if (ret) + goto error_put_reg; + + voltage_uv = regulator_get_voltage(st->reg); } + st->chip_info = + &ad7476_chip_info_tbl[spi_get_device_id(spi)->driver_data]; - ret = regulator_enable(st->reg); - if (ret) - goto error_put_reg; + if (st->chip_info->int_vref_mv) + st->int_vref_mv = st->chip_info->int_vref_mv; + else if (pdata && pdata->vref_mv) + st->int_vref_mv = pdata->vref_mv; + else if (voltage_uv) + st->int_vref_mv = voltage_uv / 1000; + else + dev_warn(&spi->dev, "reference voltage unspecified\n"); spi_set_drvdata(spi, indio_dev); @@ -251,67 +173,57 @@ static int __devinit ad7476_probe(struct spi_device *spi) spi_message_init(&st->msg); spi_message_add_tail(&st->xfer, &st->msg); - ret = iio_triggered_buffer_setup(indio_dev, NULL, - &ad7476_trigger_handler, NULL); + ret = ad7476_register_ring_funcs_and_init(indio_dev); if (ret) goto error_disable_reg; - if (st->chip_info->reset) - st->chip_info->reset(st); - ret = iio_device_register(indio_dev); if (ret) goto error_ring_unregister; return 0; error_ring_unregister: - iio_triggered_buffer_cleanup(indio_dev); + ad7476_ring_cleanup(indio_dev); error_disable_reg: - regulator_disable(st->reg); + if (!IS_ERR(st->reg)) + regulator_disable(st->reg); error_put_reg: - regulator_put(st->reg); -error_free_dev: + if (!IS_ERR(st->reg)) + regulator_put(st->reg); iio_device_free(indio_dev); error_ret: return ret; } -static int __devexit ad7476_remove(struct spi_device *spi) +static int ad7476_remove(struct spi_device *spi) { struct iio_dev *indio_dev = spi_get_drvdata(spi); struct ad7476_state *st = iio_priv(indio_dev); iio_device_unregister(indio_dev); - iio_triggered_buffer_cleanup(indio_dev); - regulator_disable(st->reg); - regulator_put(st->reg); + ad7476_ring_cleanup(indio_dev); + if (!IS_ERR(st->reg)) { + regulator_disable(st->reg); + regulator_put(st->reg); + } iio_device_free(indio_dev); return 0; } static const struct spi_device_id ad7476_id[] = { - {"ad7091r", ID_AD7091R}, - {"ad7273", ID_AD7277}, - {"ad7274", ID_AD7276}, - {"ad7276", ID_AD7276}, - {"ad7277", ID_AD7277}, - {"ad7278", ID_AD7278}, {"ad7466", ID_AD7466}, {"ad7467", ID_AD7467}, {"ad7468", ID_AD7468}, - {"ad7475", ID_AD7466}, - {"ad7476", ID_AD7466}, - {"ad7476a", ID_AD7466}, - {"ad7477", ID_AD7467}, - {"ad7477a", ID_AD7467}, - {"ad7478", ID_AD7468}, - {"ad7478a", ID_AD7468}, + {"ad7475", ID_AD7475}, + {"ad7476", ID_AD7476}, + {"ad7476a", ID_AD7476}, + {"ad7477", ID_AD7477}, + {"ad7477a", ID_AD7477}, + {"ad7478", ID_AD7478}, + {"ad7478a", ID_AD7478}, {"ad7495", ID_AD7495}, - {"ad7910", ID_AD7467}, - {"ad7920", ID_AD7466}, - {"ad7940", ID_AD7940}, {} }; MODULE_DEVICE_TABLE(spi, ad7476_id); @@ -328,5 +240,5 @@ static struct spi_driver ad7476_driver = { module_spi_driver(ad7476_driver); MODULE_AUTHOR("Michael Hennerich "); -MODULE_DESCRIPTION("Analog Devices AD7476 and similar 1-channel ADCs"); +MODULE_DESCRIPTION("Analog Devices AD7475/6/7/8(A) AD7466/7/8 ADC"); MODULE_LICENSE("GPL v2"); diff --git a/trunk/drivers/staging/iio/adc/ad7476_ring.c b/trunk/drivers/staging/iio/adc/ad7476_ring.c new file mode 100644 index 000000000000..d087b21c51f6 --- /dev/null +++ b/trunk/drivers/staging/iio/adc/ad7476_ring.c @@ -0,0 +1,64 @@ +/* + * Copyright 2010-2012 Analog Devices Inc. + * Copyright (C) 2008 Jonathan Cameron + * + * Licensed under the GPL-2 or later. + * + * ad7476_ring.c + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "ad7476.h" + +static irqreturn_t ad7476_trigger_handler(int irq, void *p) +{ + struct iio_poll_func *pf = p; + struct iio_dev *indio_dev = pf->indio_dev; + struct ad7476_state *st = iio_priv(indio_dev); + s64 time_ns; + __u8 *rxbuf; + int b_sent; + + rxbuf = kzalloc(indio_dev->scan_bytes, GFP_KERNEL); + if (rxbuf == NULL) + goto done; + + b_sent = spi_read(st->spi, rxbuf, + st->chip_info->channel[0].scan_type.storagebits / 8); + if (b_sent < 0) + goto done; + + time_ns = iio_get_time_ns(); + + if (indio_dev->scan_timestamp) + memcpy(rxbuf + indio_dev->scan_bytes - sizeof(s64), + &time_ns, sizeof(time_ns)); + + indio_dev->buffer->access->store_to(indio_dev->buffer, rxbuf, time_ns); +done: + iio_trigger_notify_done(indio_dev->trig); + kfree(rxbuf); + + return IRQ_HANDLED; +} + +int ad7476_register_ring_funcs_and_init(struct iio_dev *indio_dev) +{ + return iio_triggered_buffer_setup(indio_dev, NULL, + &ad7476_trigger_handler, NULL); +} + +void ad7476_ring_cleanup(struct iio_dev *indio_dev) +{ + iio_triggered_buffer_cleanup(indio_dev); +} diff --git a/trunk/drivers/staging/iio/adc/ad7606.h b/trunk/drivers/staging/iio/adc/ad7606.h index 9221a74efd18..10f59896597f 100644 --- a/trunk/drivers/staging/iio/adc/ad7606.h +++ b/trunk/drivers/staging/iio/adc/ad7606.h @@ -51,7 +51,7 @@ struct ad7606_platform_data { struct ad7606_chip_info { const char *name; u16 int_vref_mv; - const struct iio_chan_spec *channels; + struct iio_chan_spec *channels; unsigned num_channels; }; diff --git a/trunk/drivers/staging/iio/adc/ad7606_core.c b/trunk/drivers/staging/iio/adc/ad7606_core.c index bae61cbe9212..ccb97fecdea7 100644 --- a/trunk/drivers/staging/iio/adc/ad7606_core.c +++ b/trunk/drivers/staging/iio/adc/ad7606_core.c @@ -241,7 +241,7 @@ static const struct attribute_group ad7606_attribute_group_range = { .scan_type = IIO_ST('s', 16, 16, 0), \ } -static const struct iio_chan_spec ad7606_8_channels[] = { +static struct iio_chan_spec ad7606_8_channels[] = { AD7606_CHANNEL(0), AD7606_CHANNEL(1), AD7606_CHANNEL(2), @@ -253,7 +253,7 @@ static const struct iio_chan_spec ad7606_8_channels[] = { IIO_CHAN_SOFT_TIMESTAMP(8), }; -static const struct iio_chan_spec ad7606_6_channels[] = { +static struct iio_chan_spec ad7606_6_channels[] = { AD7606_CHANNEL(0), AD7606_CHANNEL(1), AD7606_CHANNEL(2), @@ -263,7 +263,7 @@ static const struct iio_chan_spec ad7606_6_channels[] = { IIO_CHAN_SOFT_TIMESTAMP(6), }; -static const struct iio_chan_spec ad7606_4_channels[] = { +static struct iio_chan_spec ad7606_4_channels[] = { AD7606_CHANNEL(0), AD7606_CHANNEL(1), AD7606_CHANNEL(2), diff --git a/trunk/drivers/staging/iio/adc/ad7606_ring.c b/trunk/drivers/staging/iio/adc/ad7606_ring.c index ba04d0ffd4f4..f15afe47c20d 100644 --- a/trunk/drivers/staging/iio/adc/ad7606_ring.c +++ b/trunk/drivers/staging/iio/adc/ad7606_ring.c @@ -46,6 +46,7 @@ static void ad7606_poll_bh_to_ring(struct work_struct *work_s) struct ad7606_state *st = container_of(work_s, struct ad7606_state, poll_work); struct iio_dev *indio_dev = iio_priv_to_dev(st); + struct iio_buffer *ring = indio_dev->buffer; s64 time_ns; __u8 *buf; int ret; @@ -83,7 +84,7 @@ static void ad7606_poll_bh_to_ring(struct work_struct *work_s) if (indio_dev->scan_timestamp) *((s64 *)(buf + indio_dev->scan_bytes - sizeof(s64))) = time_ns; - iio_push_to_buffer(indio_dev->buffer, buf); + ring->access->store_to(indio_dev->buffer, buf, time_ns); done: gpio_set_value(st->pdata->gpio_convst, 0); iio_trigger_notify_done(indio_dev->trig); diff --git a/trunk/drivers/staging/iio/adc/ad7780.c b/trunk/drivers/staging/iio/adc/ad7780.c index 0a1328b8657f..1ece2ac8de56 100644 --- a/trunk/drivers/staging/iio/adc/ad7780.c +++ b/trunk/drivers/staging/iio/adc/ad7780.c @@ -1,5 +1,5 @@ /* - * AD7170/AD7171 and AD7780/AD7781 SPI ADC driver + * AD7780/AD7781 SPI ADC driver * * Copyright 2011 Analog Devices Inc. * @@ -20,7 +20,6 @@ #include #include -#include #include "ad7780.h" @@ -34,53 +33,53 @@ #define AD7780_PAT0 (1 << 0) struct ad7780_chip_info { - struct iio_chan_spec channel; - unsigned int pattern_mask; - unsigned int pattern; + struct iio_chan_spec channel; }; struct ad7780_state { + struct spi_device *spi; const struct ad7780_chip_info *chip_info; struct regulator *reg; - int powerdown_gpio; - unsigned int gain; + struct ad7780_platform_data *pdata; + wait_queue_head_t wq_data_avail; + bool done; u16 int_vref_mv; - - struct ad_sigma_delta sd; + struct spi_transfer xfer; + struct spi_message msg; + /* + * DMA (thus cache coherency maintenance) requires the + * transfer buffers to live in their own cache lines. + */ + unsigned int data ____cacheline_aligned; }; enum ad7780_supported_device_ids { - ID_AD7170, - ID_AD7171, ID_AD7780, ID_AD7781, }; -static struct ad7780_state *ad_sigma_delta_to_ad7780(struct ad_sigma_delta *sd) +static int ad7780_read(struct ad7780_state *st, int *val) { - return container_of(sd, struct ad7780_state, sd); -} + int ret; -static int ad7780_set_mode(struct ad_sigma_delta *sigma_delta, - enum ad_sigma_delta_mode mode) -{ - struct ad7780_state *st = ad_sigma_delta_to_ad7780(sigma_delta); - unsigned val; - - switch (mode) { - case AD_SD_MODE_SINGLE: - case AD_SD_MODE_CONTINUOUS: - val = 1; - break; - default: - val = 0; - break; - } + spi_bus_lock(st->spi->master); - if (gpio_is_valid(st->powerdown_gpio)) - gpio_set_value(st->powerdown_gpio, val); + enable_irq(st->spi->irq); + st->done = false; + gpio_set_value(st->pdata->gpio_pdrst, 1); - return 0; + ret = wait_event_interruptible(st->wq_data_avail, st->done); + disable_irq_nosync(st->spi->irq); + if (ret) + goto out; + + ret = spi_sync_locked(st->spi, &st->msg); + *val = be32_to_cpu(st->data); +out: + gpio_set_value(st->pdata->gpio_pdrst, 0); + spi_bus_unlock(st->spi->master); + + return ret; } static int ad7780_read_raw(struct iio_dev *indio_dev, @@ -90,75 +89,87 @@ static int ad7780_read_raw(struct iio_dev *indio_dev, long m) { struct ad7780_state *st = iio_priv(indio_dev); + struct iio_chan_spec channel = st->chip_info->channel; + int ret, smpl = 0; unsigned long scale_uv; switch (m) { case IIO_CHAN_INFO_RAW: - return ad_sigma_delta_single_conversion(indio_dev, chan, val); + mutex_lock(&indio_dev->mlock); + ret = ad7780_read(st, &smpl); + mutex_unlock(&indio_dev->mlock); + + if (ret < 0) + return ret; + + if ((smpl & AD7780_ERR) || + !((smpl & AD7780_PAT0) && !(smpl & AD7780_PAT1))) + return -EIO; + + *val = (smpl >> channel.scan_type.shift) & + ((1 << (channel.scan_type.realbits)) - 1); + *val -= (1 << (channel.scan_type.realbits - 1)); + + if (!(smpl & AD7780_GAIN)) + *val *= 128; + + return IIO_VAL_INT; case IIO_CHAN_INFO_SCALE: - scale_uv = (st->int_vref_mv * 100000 * st->gain) - >> (chan->scan_type.realbits - 1); + scale_uv = (st->int_vref_mv * 100000) + >> (channel.scan_type.realbits - 1); *val = scale_uv / 100000; *val2 = (scale_uv % 100000) * 10; return IIO_VAL_INT_PLUS_MICRO; - case IIO_CHAN_INFO_OFFSET: - *val -= (1 << (chan->scan_type.realbits - 1)); - return IIO_VAL_INT; } - return -EINVAL; } -static int ad7780_postprocess_sample(struct ad_sigma_delta *sigma_delta, - unsigned int raw_sample) -{ - struct ad7780_state *st = ad_sigma_delta_to_ad7780(sigma_delta); - const struct ad7780_chip_info *chip_info = st->chip_info; - - if ((raw_sample & AD7780_ERR) || - ((raw_sample & chip_info->pattern_mask) != chip_info->pattern)) - return -EIO; - - if (raw_sample & AD7780_GAIN) - st->gain = 1; - else - st->gain = 128; - - return 0; -} - -static const struct ad_sigma_delta_info ad7780_sigma_delta_info = { - .set_mode = ad7780_set_mode, - .postprocess_sample = ad7780_postprocess_sample, - .has_registers = false, -}; - -#define AD7780_CHANNEL(bits, wordsize) \ - AD_SD_CHANNEL(1, 0, 0, bits, 32, wordsize - bits) - static const struct ad7780_chip_info ad7780_chip_info_tbl[] = { - [ID_AD7170] = { - .channel = AD7780_CHANNEL(12, 24), - .pattern = 0x5, - .pattern_mask = 0x7, - }, - [ID_AD7171] = { - .channel = AD7780_CHANNEL(16, 24), - .pattern = 0x5, - .pattern_mask = 0x7, - }, [ID_AD7780] = { - .channel = AD7780_CHANNEL(24, 32), - .pattern = 0x1, - .pattern_mask = 0x3, + .channel = { + .type = IIO_VOLTAGE, + .indexed = 1, + .channel = 0, + .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | + IIO_CHAN_INFO_SCALE_SHARED_BIT, + .scan_type = { + .sign = 's', + .realbits = 24, + .storagebits = 32, + .shift = 8, + }, + }, }, [ID_AD7781] = { - .channel = AD7780_CHANNEL(20, 32), - .pattern = 0x1, - .pattern_mask = 0x3, + .channel = { + .type = IIO_VOLTAGE, + .indexed = 1, + .channel = 0, + .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | + IIO_CHAN_INFO_SCALE_SHARED_BIT, + .scan_type = { + .sign = 's', + .realbits = 20, + .storagebits = 32, + .shift = 12, + }, + }, }, }; +/** + * Interrupt handler + */ +static irqreturn_t ad7780_interrupt(int irq, void *dev_id) +{ + struct ad7780_state *st = dev_id; + + st->done = true; + wake_up_interruptible(&st->wq_data_avail); + + return IRQ_HANDLED; +}; + static const struct iio_info ad7780_info = { .read_raw = &ad7780_read_raw, .driver_module = THIS_MODULE, @@ -171,14 +182,16 @@ static int __devinit ad7780_probe(struct spi_device *spi) struct iio_dev *indio_dev; int ret, voltage_uv = 0; + if (!pdata) { + dev_dbg(&spi->dev, "no platform data?\n"); + return -ENODEV; + } + indio_dev = iio_device_alloc(sizeof(*st)); if (indio_dev == NULL) return -ENOMEM; st = iio_priv(indio_dev); - st->gain = 1; - - ad_sd_init(&st->sd, indio_dev, spi, &ad7780_sigma_delta_info); st->reg = regulator_get(&spi->dev, "vcc"); if (!IS_ERR(st->reg)) { @@ -192,6 +205,8 @@ static int __devinit ad7780_probe(struct spi_device *spi) st->chip_info = &ad7780_chip_info_tbl[spi_get_device_id(spi)->driver_data]; + st->pdata = pdata; + if (pdata && pdata->vref_mv) st->int_vref_mv = pdata->vref_mv; else if (voltage_uv) @@ -200,6 +215,7 @@ static int __devinit ad7780_probe(struct spi_device *spi) dev_warn(&spi->dev, "reference voltage unspecified\n"); spi_set_drvdata(spi, indio_dev); + st->spi = spi; indio_dev->dev.parent = &spi->dev; indio_dev->name = spi_get_device_id(spi)->name; @@ -208,34 +224,40 @@ static int __devinit ad7780_probe(struct spi_device *spi) indio_dev->num_channels = 1; indio_dev->info = &ad7780_info; - if (pdata && gpio_is_valid(pdata->gpio_pdrst)) { + init_waitqueue_head(&st->wq_data_avail); + + /* Setup default message */ - ret = gpio_request_one(pdata->gpio_pdrst, GPIOF_OUT_INIT_LOW, + st->xfer.rx_buf = &st->data; + st->xfer.len = st->chip_info->channel.scan_type.storagebits / 8; + + spi_message_init(&st->msg); + spi_message_add_tail(&st->xfer, &st->msg); + + ret = gpio_request_one(st->pdata->gpio_pdrst, GPIOF_OUT_INIT_LOW, "AD7780 /PDRST"); - if (ret) { - dev_err(&spi->dev, "failed to request GPIO PDRST\n"); - goto error_disable_reg; - } - st->powerdown_gpio = pdata->gpio_pdrst; - } else { - st->powerdown_gpio = -1; + if (ret) { + dev_err(&spi->dev, "failed to request GPIO PDRST\n"); + goto error_disable_reg; } - ret = ad_sd_setup_buffer_and_trigger(indio_dev); + ret = request_irq(spi->irq, ad7780_interrupt, + IRQF_TRIGGER_FALLING, spi_get_device_id(spi)->name, st); if (ret) goto error_free_gpio; + disable_irq(spi->irq); + ret = iio_device_register(indio_dev); if (ret) - goto error_cleanup_buffer_and_trigger; + goto error_free_irq; return 0; -error_cleanup_buffer_and_trigger: - ad_sd_cleanup_buffer_and_trigger(indio_dev); +error_free_irq: + free_irq(spi->irq, st); error_free_gpio: - if (pdata && gpio_is_valid(pdata->gpio_pdrst)) - gpio_free(pdata->gpio_pdrst); + gpio_free(st->pdata->gpio_pdrst); error_disable_reg: if (!IS_ERR(st->reg)) regulator_disable(st->reg); @@ -248,17 +270,14 @@ static int __devinit ad7780_probe(struct spi_device *spi) return ret; } -static int __devexit ad7780_remove(struct spi_device *spi) +static int ad7780_remove(struct spi_device *spi) { struct iio_dev *indio_dev = spi_get_drvdata(spi); struct ad7780_state *st = iio_priv(indio_dev); iio_device_unregister(indio_dev); - ad_sd_cleanup_buffer_and_trigger(indio_dev); - - if (gpio_is_valid(st->powerdown_gpio)) - gpio_free(st->powerdown_gpio); - + free_irq(spi->irq, st); + gpio_free(st->pdata->gpio_pdrst); if (!IS_ERR(st->reg)) { regulator_disable(st->reg); regulator_put(st->reg); @@ -269,8 +288,6 @@ static int __devexit ad7780_remove(struct spi_device *spi) } static const struct spi_device_id ad7780_id[] = { - {"ad7170", ID_AD7170}, - {"ad7171", ID_AD7171}, {"ad7780", ID_AD7780}, {"ad7781", ID_AD7781}, {} @@ -289,5 +306,5 @@ static struct spi_driver ad7780_driver = { module_spi_driver(ad7780_driver); MODULE_AUTHOR("Michael Hennerich "); -MODULE_DESCRIPTION("Analog Devices AD7780 and similar ADCs"); +MODULE_DESCRIPTION("Analog Devices AD7780/1 ADC"); MODULE_LICENSE("GPL v2"); diff --git a/trunk/drivers/staging/iio/adc/ad7793.c b/trunk/drivers/staging/iio/adc/ad7793.c index 691a7be6f5cb..76fdd7145fc5 100644 --- a/trunk/drivers/staging/iio/adc/ad7793.c +++ b/trunk/drivers/staging/iio/adc/ad7793.c @@ -1,5 +1,5 @@ /* - * AD7785/AD7792/AD7793/AD7794/AD7795 SPI ADC driver + * AD7792/AD7793 SPI ADC driver * * Copyright 2011-2012 Analog Devices Inc. * @@ -24,7 +24,6 @@ #include #include #include -#include #include "ad7793.h" @@ -37,65 +36,198 @@ */ struct ad7793_chip_info { - const struct iio_chan_spec *channels; - unsigned int num_channels; + struct iio_chan_spec channel[7]; }; struct ad7793_state { + struct spi_device *spi; + struct iio_trigger *trig; const struct ad7793_chip_info *chip_info; struct regulator *reg; + struct ad7793_platform_data *pdata; + wait_queue_head_t wq_data_avail; + bool done; + bool irq_dis; u16 int_vref_mv; u16 mode; u16 conf; u32 scale_avail[8][2]; - struct ad_sigma_delta sd; - + /* + * DMA (thus cache coherency maintenance) requires the + * transfer buffers to live in their own cache lines. + */ + u8 data[4] ____cacheline_aligned; }; enum ad7793_supported_device_ids { - ID_AD7785, ID_AD7792, ID_AD7793, - ID_AD7794, - ID_AD7795, }; -static struct ad7793_state *ad_sigma_delta_to_ad7793(struct ad_sigma_delta *sd) +static int __ad7793_write_reg(struct ad7793_state *st, bool locked, + bool cs_change, unsigned char reg, + unsigned size, unsigned val) +{ + u8 *data = st->data; + struct spi_transfer t = { + .tx_buf = data, + .len = size + 1, + .cs_change = cs_change, + }; + struct spi_message m; + + data[0] = AD7793_COMM_WRITE | AD7793_COMM_ADDR(reg); + + switch (size) { + case 3: + data[1] = val >> 16; + data[2] = val >> 8; + data[3] = val; + break; + case 2: + data[1] = val >> 8; + data[2] = val; + break; + case 1: + data[1] = val; + break; + default: + return -EINVAL; + } + + spi_message_init(&m); + spi_message_add_tail(&t, &m); + + if (locked) + return spi_sync_locked(st->spi, &m); + else + return spi_sync(st->spi, &m); +} + +static int ad7793_write_reg(struct ad7793_state *st, + unsigned reg, unsigned size, unsigned val) { - return container_of(sd, struct ad7793_state, sd); + return __ad7793_write_reg(st, false, false, reg, size, val); } -static int ad7793_set_channel(struct ad_sigma_delta *sd, unsigned int channel) +static int __ad7793_read_reg(struct ad7793_state *st, bool locked, + bool cs_change, unsigned char reg, + int *val, unsigned size) { - struct ad7793_state *st = ad_sigma_delta_to_ad7793(sd); + u8 *data = st->data; + int ret; + struct spi_transfer t[] = { + { + .tx_buf = data, + .len = 1, + }, { + .rx_buf = data, + .len = size, + .cs_change = cs_change, + }, + }; + struct spi_message m; + + data[0] = AD7793_COMM_READ | AD7793_COMM_ADDR(reg); + + spi_message_init(&m); + spi_message_add_tail(&t[0], &m); + spi_message_add_tail(&t[1], &m); + + if (locked) + ret = spi_sync_locked(st->spi, &m); + else + ret = spi_sync(st->spi, &m); + + if (ret < 0) + return ret; - st->conf &= ~AD7793_CONF_CHAN_MASK; - st->conf |= AD7793_CONF_CHAN(channel); + switch (size) { + case 3: + *val = data[0] << 16 | data[1] << 8 | data[2]; + break; + case 2: + *val = data[0] << 8 | data[1]; + break; + case 1: + *val = data[0]; + break; + default: + return -EINVAL; + } - return ad_sd_write_reg(&st->sd, AD7793_REG_CONF, 2, st->conf); + return 0; +} + +static int ad7793_read_reg(struct ad7793_state *st, + unsigned reg, int *val, unsigned size) +{ + return __ad7793_read_reg(st, 0, 0, reg, val, size); } -static int ad7793_set_mode(struct ad_sigma_delta *sd, - enum ad_sigma_delta_mode mode) +static int ad7793_read(struct ad7793_state *st, unsigned ch, + unsigned len, int *val) { - struct ad7793_state *st = ad_sigma_delta_to_ad7793(sd); + int ret; + st->conf = (st->conf & ~AD7793_CONF_CHAN(-1)) | AD7793_CONF_CHAN(ch); + st->mode = (st->mode & ~AD7793_MODE_SEL(-1)) | + AD7793_MODE_SEL(AD7793_MODE_SINGLE); + + ad7793_write_reg(st, AD7793_REG_CONF, sizeof(st->conf), st->conf); - st->mode &= ~AD7793_MODE_SEL_MASK; - st->mode |= AD7793_MODE_SEL(mode); + spi_bus_lock(st->spi->master); + st->done = false; - return ad_sd_write_reg(&st->sd, AD7793_REG_MODE, 2, st->mode); + ret = __ad7793_write_reg(st, 1, 1, AD7793_REG_MODE, + sizeof(st->mode), st->mode); + if (ret < 0) + goto out; + + st->irq_dis = false; + enable_irq(st->spi->irq); + wait_event_interruptible(st->wq_data_avail, st->done); + + ret = __ad7793_read_reg(st, 1, 0, AD7793_REG_DATA, val, len); +out: + spi_bus_unlock(st->spi->master); + + return ret; } -static const struct ad_sigma_delta_info ad7793_sigma_delta_info = { - .set_channel = ad7793_set_channel, - .set_mode = ad7793_set_mode, - .has_registers = true, - .addr_shift = 3, - .read_mask = BIT(6), -}; +static int ad7793_calibrate(struct ad7793_state *st, unsigned mode, unsigned ch) +{ + int ret; -static const struct ad_sd_calib_data ad7793_calib_arr[6] = { + st->conf = (st->conf & ~AD7793_CONF_CHAN(-1)) | AD7793_CONF_CHAN(ch); + st->mode = (st->mode & ~AD7793_MODE_SEL(-1)) | AD7793_MODE_SEL(mode); + + ad7793_write_reg(st, AD7793_REG_CONF, sizeof(st->conf), st->conf); + + spi_bus_lock(st->spi->master); + st->done = false; + + ret = __ad7793_write_reg(st, 1, 1, AD7793_REG_MODE, + sizeof(st->mode), st->mode); + if (ret < 0) + goto out; + + st->irq_dis = false; + enable_irq(st->spi->irq); + wait_event_interruptible(st->wq_data_avail, st->done); + + st->mode = (st->mode & ~AD7793_MODE_SEL(-1)) | + AD7793_MODE_SEL(AD7793_MODE_IDLE); + + ret = __ad7793_write_reg(st, 1, 0, AD7793_REG_MODE, + sizeof(st->mode), st->mode); +out: + spi_bus_unlock(st->spi->master); + + return ret; +} + +static const u8 ad7793_calib_arr[6][2] = { {AD7793_MODE_CAL_INT_ZERO, AD7793_CH_AIN1P_AIN1M}, {AD7793_MODE_CAL_INT_FULL, AD7793_CH_AIN1P_AIN1M}, {AD7793_MODE_CAL_INT_ZERO, AD7793_CH_AIN2P_AIN2M}, @@ -106,49 +238,59 @@ static const struct ad_sd_calib_data ad7793_calib_arr[6] = { static int ad7793_calibrate_all(struct ad7793_state *st) { - return ad_sd_calibrate_all(&st->sd, ad7793_calib_arr, - ARRAY_SIZE(ad7793_calib_arr)); + int i, ret; + + for (i = 0; i < ARRAY_SIZE(ad7793_calib_arr); i++) { + ret = ad7793_calibrate(st, ad7793_calib_arr[i][0], + ad7793_calib_arr[i][1]); + if (ret) + goto out; + } + + return 0; +out: + dev_err(&st->spi->dev, "Calibration failed\n"); + return ret; } -static int ad7793_setup(struct iio_dev *indio_dev, - const struct ad7793_platform_data *pdata) +static int ad7793_setup(struct ad7793_state *st) { - struct ad7793_state *st = iio_priv(indio_dev); int i, ret = -1; unsigned long long scale_uv; u32 id; /* reset the serial interface */ - ret = spi_write(st->sd.spi, (u8 *)&ret, sizeof(ret)); + ret = spi_write(st->spi, (u8 *)&ret, sizeof(ret)); if (ret < 0) goto out; msleep(1); /* Wait for at least 500us */ /* write/read test for device presence */ - ret = ad_sd_read_reg(&st->sd, AD7793_REG_ID, 1, &id); + ret = ad7793_read_reg(st, AD7793_REG_ID, &id, 1); if (ret) goto out; id &= AD7793_ID_MASK; - if (!((id == AD7792_ID) || (id == AD7793_ID) || (id == AD7795_ID))) { - dev_err(&st->sd.spi->dev, "device ID query failed\n"); + if (!((id == AD7792_ID) || (id == AD7793_ID))) { + dev_err(&st->spi->dev, "device ID query failed\n"); goto out; } - st->mode = pdata->mode; - st->conf = pdata->conf; + st->mode = (st->pdata->mode & ~AD7793_MODE_SEL(-1)) | + AD7793_MODE_SEL(AD7793_MODE_IDLE); + st->conf = st->pdata->conf & ~AD7793_CONF_CHAN(-1); - ret = ad7793_set_mode(&st->sd, AD_SD_MODE_IDLE); + ret = ad7793_write_reg(st, AD7793_REG_MODE, sizeof(st->mode), st->mode); if (ret) goto out; - ret = ad7793_set_channel(&st->sd, 0); + ret = ad7793_write_reg(st, AD7793_REG_CONF, sizeof(st->conf), st->conf); if (ret) goto out; - ret = ad_sd_write_reg(&st->sd, AD7793_REG_IO, - sizeof(pdata->io), pdata->io); + ret = ad7793_write_reg(st, AD7793_REG_IO, + sizeof(st->pdata->io), st->pdata->io); if (ret) goto out; @@ -159,7 +301,7 @@ static int ad7793_setup(struct iio_dev *indio_dev, /* Populate available ADC input ranges */ for (i = 0; i < ARRAY_SIZE(st->scale_avail); i++) { scale_uv = ((u64)st->int_vref_mv * 100000000) - >> (st->chip_info->channels[0].scan_type.realbits - + >> (st->chip_info->channel[0].scan_type.realbits - (!!(st->conf & AD7793_CONF_UNIPOLAR) ? 0 : 1)); scale_uv >>= i; @@ -169,10 +311,184 @@ static int ad7793_setup(struct iio_dev *indio_dev, return 0; out: - dev_err(&st->sd.spi->dev, "setup failed\n"); + dev_err(&st->spi->dev, "setup failed\n"); + return ret; +} + +static int ad7793_ring_preenable(struct iio_dev *indio_dev) +{ + struct ad7793_state *st = iio_priv(indio_dev); + unsigned channel; + int ret; + + if (bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength)) + return -EINVAL; + ret = iio_sw_buffer_preenable(indio_dev); + if (ret < 0) + return ret; + + channel = find_first_bit(indio_dev->active_scan_mask, + indio_dev->masklength); + + st->mode = (st->mode & ~AD7793_MODE_SEL(-1)) | + AD7793_MODE_SEL(AD7793_MODE_CONT); + st->conf = (st->conf & ~AD7793_CONF_CHAN(-1)) | + AD7793_CONF_CHAN(indio_dev->channels[channel].address); + + ad7793_write_reg(st, AD7793_REG_CONF, sizeof(st->conf), st->conf); + + spi_bus_lock(st->spi->master); + __ad7793_write_reg(st, 1, 1, AD7793_REG_MODE, + sizeof(st->mode), st->mode); + + st->irq_dis = false; + enable_irq(st->spi->irq); + + return 0; +} + +static int ad7793_ring_postdisable(struct iio_dev *indio_dev) +{ + struct ad7793_state *st = iio_priv(indio_dev); + + st->mode = (st->mode & ~AD7793_MODE_SEL(-1)) | + AD7793_MODE_SEL(AD7793_MODE_IDLE); + + st->done = false; + wait_event_interruptible(st->wq_data_avail, st->done); + + if (!st->irq_dis) + disable_irq_nosync(st->spi->irq); + + __ad7793_write_reg(st, 1, 0, AD7793_REG_MODE, + sizeof(st->mode), st->mode); + + return spi_bus_unlock(st->spi->master); +} + +/** + * ad7793_trigger_handler() bh of trigger launched polling to ring buffer + **/ + +static irqreturn_t ad7793_trigger_handler(int irq, void *p) +{ + struct iio_poll_func *pf = p; + struct iio_dev *indio_dev = pf->indio_dev; + struct iio_buffer *ring = indio_dev->buffer; + struct ad7793_state *st = iio_priv(indio_dev); + s64 dat64[2]; + s32 *dat32 = (s32 *)dat64; + + if (!bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength)) + __ad7793_read_reg(st, 1, 1, AD7793_REG_DATA, + dat32, + indio_dev->channels[0].scan_type.realbits/8); + + /* Guaranteed to be aligned with 8 byte boundary */ + if (indio_dev->scan_timestamp) + dat64[1] = pf->timestamp; + + ring->access->store_to(ring, (u8 *)dat64, pf->timestamp); + + iio_trigger_notify_done(indio_dev->trig); + st->irq_dis = false; + enable_irq(st->spi->irq); + + return IRQ_HANDLED; +} + +static const struct iio_buffer_setup_ops ad7793_ring_setup_ops = { + .preenable = &ad7793_ring_preenable, + .postenable = &iio_triggered_buffer_postenable, + .predisable = &iio_triggered_buffer_predisable, + .postdisable = &ad7793_ring_postdisable, + .validate_scan_mask = &iio_validate_scan_mask_onehot, +}; + +static int ad7793_register_ring_funcs_and_init(struct iio_dev *indio_dev) +{ + return iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time, + &ad7793_trigger_handler, &ad7793_ring_setup_ops); +} + +static void ad7793_ring_cleanup(struct iio_dev *indio_dev) +{ + iio_triggered_buffer_cleanup(indio_dev); +} + +/** + * ad7793_data_rdy_trig_poll() the event handler for the data rdy trig + **/ +static irqreturn_t ad7793_data_rdy_trig_poll(int irq, void *private) +{ + struct ad7793_state *st = iio_priv(private); + + st->done = true; + wake_up_interruptible(&st->wq_data_avail); + disable_irq_nosync(irq); + st->irq_dis = true; + iio_trigger_poll(st->trig, iio_get_time_ns()); + + return IRQ_HANDLED; +} + +static struct iio_trigger_ops ad7793_trigger_ops = { + .owner = THIS_MODULE, +}; + +static int ad7793_probe_trigger(struct iio_dev *indio_dev) +{ + struct ad7793_state *st = iio_priv(indio_dev); + int ret; + + st->trig = iio_trigger_alloc("%s-dev%d", + spi_get_device_id(st->spi)->name, + indio_dev->id); + if (st->trig == NULL) { + ret = -ENOMEM; + goto error_ret; + } + st->trig->ops = &ad7793_trigger_ops; + + ret = request_irq(st->spi->irq, + ad7793_data_rdy_trig_poll, + IRQF_TRIGGER_LOW, + spi_get_device_id(st->spi)->name, + indio_dev); + if (ret) + goto error_free_trig; + + disable_irq_nosync(st->spi->irq); + st->irq_dis = true; + st->trig->dev.parent = &st->spi->dev; + st->trig->private_data = indio_dev; + + ret = iio_trigger_register(st->trig); + + /* select default trigger */ + indio_dev->trig = st->trig; + if (ret) + goto error_free_irq; + + return 0; + +error_free_irq: + free_irq(st->spi->irq, indio_dev); +error_free_trig: + iio_trigger_free(st->trig); +error_ret: return ret; } +static void ad7793_remove_trigger(struct iio_dev *indio_dev) +{ + struct ad7793_state *st = iio_priv(indio_dev); + + iio_trigger_unregister(st->trig); + free_irq(st->spi->irq, indio_dev); + iio_trigger_free(st->trig); +} + static const u16 sample_freq_avail[16] = {0, 470, 242, 123, 62, 50, 39, 33, 19, 17, 16, 12, 10, 8, 6, 4}; @@ -215,7 +531,7 @@ static ssize_t ad7793_write_frequency(struct device *dev, mutex_lock(&indio_dev->mlock); st->mode &= ~AD7793_MODE_RATE(-1); st->mode |= AD7793_MODE_RATE(i); - ad_sd_write_reg(&st->sd, AD7793_REG_MODE, + ad7793_write_reg(st, AD7793_REG_MODE, sizeof(st->mode), st->mode); mutex_unlock(&indio_dev->mlock); ret = 0; @@ -247,9 +563,8 @@ static ssize_t ad7793_show_scale_available(struct device *dev, return len; } -static IIO_DEVICE_ATTR_NAMED(in_m_in_scale_available, - in_voltage-voltage_scale_available, S_IRUGO, - ad7793_show_scale_available, NULL, 0); +static IIO_DEVICE_ATTR_NAMED(in_m_in_scale_available, in-in_scale_available, + S_IRUGO, ad7793_show_scale_available, NULL, 0); static struct attribute *ad7793_attributes[] = { &iio_dev_attr_sampling_frequency.dev_attr.attr, @@ -269,16 +584,29 @@ static int ad7793_read_raw(struct iio_dev *indio_dev, long m) { struct ad7793_state *st = iio_priv(indio_dev); - int ret; + int ret, smpl = 0; unsigned long long scale_uv; bool unipolar = !!(st->conf & AD7793_CONF_UNIPOLAR); switch (m) { case IIO_CHAN_INFO_RAW: - ret = ad_sigma_delta_single_conversion(indio_dev, chan, val); + mutex_lock(&indio_dev->mlock); + if (iio_buffer_enabled(indio_dev)) + ret = -EBUSY; + else + ret = ad7793_read(st, chan->address, + chan->scan_type.realbits / 8, &smpl); + mutex_unlock(&indio_dev->mlock); + if (ret < 0) return ret; + *val = (smpl >> chan->scan_type.shift) & + ((1 << (chan->scan_type.realbits)) - 1); + + if (!unipolar) + *val -= (1 << (chan->scan_type.realbits - 1)); + return IIO_VAL_INT; case IIO_CHAN_INFO_SCALE: @@ -292,38 +620,25 @@ static int ad7793_read_raw(struct iio_dev *indio_dev, return IIO_VAL_INT_PLUS_NANO; } else { /* 1170mV / 2^23 * 6 */ - scale_uv = (1170ULL * 100000000ULL * 6ULL); + scale_uv = (1170ULL * 100000000ULL * 6ULL) + >> (chan->scan_type.realbits - + (unipolar ? 0 : 1)); } break; case IIO_TEMP: - /* 1170mV / 0.81 mV/C / 2^23 */ - scale_uv = 1444444444444ULL; + /* Always uses unity gain and internal ref */ + scale_uv = (2500ULL * 100000000ULL) + >> (chan->scan_type.realbits - + (unipolar ? 0 : 1)); break; default: return -EINVAL; } - scale_uv >>= (chan->scan_type.realbits - (unipolar ? 0 : 1)); - *val = 0; - *val2 = scale_uv; - return IIO_VAL_INT_PLUS_NANO; - case IIO_CHAN_INFO_OFFSET: - if (!unipolar) - *val = -(1 << (chan->scan_type.realbits - 1)); - else - *val = 0; - - /* Kelvin to Celsius */ - if (chan->type == IIO_TEMP) { - unsigned long long offset; - unsigned int shift; + *val2 = do_div(scale_uv, 100000000) * 10; + *val = scale_uv; - shift = chan->scan_type.realbits - (unipolar ? 0 : 1); - offset = 273ULL << shift; - do_div(offset, 1444); - *val -= offset; - } - return IIO_VAL_INT; + return IIO_VAL_INT_PLUS_NANO; } return -EINVAL; } @@ -349,20 +664,19 @@ static int ad7793_write_raw(struct iio_dev *indio_dev, ret = -EINVAL; for (i = 0; i < ARRAY_SIZE(st->scale_avail); i++) if (val2 == st->scale_avail[i][1]) { - ret = 0; tmp = st->conf; st->conf &= ~AD7793_CONF_GAIN(-1); st->conf |= AD7793_CONF_GAIN(i); - if (tmp == st->conf) - break; - - ad_sd_write_reg(&st->sd, AD7793_REG_CONF, - sizeof(st->conf), st->conf); - ad7793_calibrate_all(st); - break; + if (tmp != st->conf) { + ad7793_write_reg(st, AD7793_REG_CONF, + sizeof(st->conf), + st->conf); + ad7793_calibrate_all(st); + } + ret = 0; } - break; + default: ret = -EINVAL; } @@ -371,6 +685,15 @@ static int ad7793_write_raw(struct iio_dev *indio_dev, return ret; } +static int ad7793_validate_trigger(struct iio_dev *indio_dev, + struct iio_trigger *trig) +{ + if (indio_dev->trig != trig) + return -EINVAL; + + return 0; +} + static int ad7793_write_raw_get_fmt(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, long mask) @@ -383,67 +706,162 @@ static const struct iio_info ad7793_info = { .write_raw = &ad7793_write_raw, .write_raw_get_fmt = &ad7793_write_raw_get_fmt, .attrs = &ad7793_attribute_group, - .validate_trigger = ad_sd_validate_trigger, + .validate_trigger = ad7793_validate_trigger, .driver_module = THIS_MODULE, }; -#define DECLARE_AD7793_CHANNELS(_name, _b, _sb, _s) \ -const struct iio_chan_spec _name##_channels[] = { \ - AD_SD_DIFF_CHANNEL(0, 0, 0, AD7793_CH_AIN1P_AIN1M, (_b), (_sb), (_s)), \ - AD_SD_DIFF_CHANNEL(1, 1, 1, AD7793_CH_AIN2P_AIN2M, (_b), (_sb), (_s)), \ - AD_SD_DIFF_CHANNEL(2, 2, 2, AD7793_CH_AIN3P_AIN3M, (_b), (_sb), (_s)), \ - AD_SD_SHORTED_CHANNEL(3, 0, AD7793_CH_AIN1M_AIN1M, (_b), (_sb), (_s)), \ - AD_SD_TEMP_CHANNEL(4, AD7793_CH_TEMP, (_b), (_sb), (_s)), \ - AD_SD_SUPPLY_CHANNEL(5, 3, AD7793_CH_AVDD_MONITOR, (_b), (_sb), (_s)), \ - IIO_CHAN_SOFT_TIMESTAMP(6), \ -} - -#define DECLARE_AD7795_CHANNELS(_name, _b, _sb) \ -const struct iio_chan_spec _name##_channels[] = { \ - AD_SD_DIFF_CHANNEL(0, 0, 0, AD7793_CH_AIN1P_AIN1M, (_b), (_sb), 0), \ - AD_SD_DIFF_CHANNEL(1, 1, 1, AD7793_CH_AIN2P_AIN2M, (_b), (_sb), 0), \ - AD_SD_DIFF_CHANNEL(2, 2, 2, AD7793_CH_AIN3P_AIN3M, (_b), (_sb), 0), \ - AD_SD_DIFF_CHANNEL(3, 3, 3, AD7795_CH_AIN4P_AIN4M, (_b), (_sb), 0), \ - AD_SD_DIFF_CHANNEL(4, 4, 4, AD7795_CH_AIN5P_AIN5M, (_b), (_sb), 0), \ - AD_SD_DIFF_CHANNEL(5, 5, 5, AD7795_CH_AIN6P_AIN6M, (_b), (_sb), 0), \ - AD_SD_SHORTED_CHANNEL(6, 0, AD7795_CH_AIN1M_AIN1M, (_b), (_sb), 0), \ - AD_SD_TEMP_CHANNEL(7, AD7793_CH_TEMP, (_b), (_sb), 0), \ - AD_SD_SUPPLY_CHANNEL(8, 3, AD7793_CH_AVDD_MONITOR, (_b), (_sb), 0), \ - IIO_CHAN_SOFT_TIMESTAMP(9), \ -} - -static DECLARE_AD7793_CHANNELS(ad7785, 20, 32, 4); -static DECLARE_AD7793_CHANNELS(ad7792, 16, 32, 0); -static DECLARE_AD7793_CHANNELS(ad7793, 24, 32, 0); -static DECLARE_AD7795_CHANNELS(ad7794, 16, 32); -static DECLARE_AD7795_CHANNELS(ad7795, 24, 32); - static const struct ad7793_chip_info ad7793_chip_info_tbl[] = { - [ID_AD7785] = { - .channels = ad7785_channels, - .num_channels = ARRAY_SIZE(ad7785_channels), - }, - [ID_AD7792] = { - .channels = ad7792_channels, - .num_channels = ARRAY_SIZE(ad7792_channels), - }, [ID_AD7793] = { - .channels = ad7793_channels, - .num_channels = ARRAY_SIZE(ad7793_channels), + .channel[0] = { + .type = IIO_VOLTAGE, + .differential = 1, + .indexed = 1, + .channel = 0, + .channel2 = 0, + .address = AD7793_CH_AIN1P_AIN1M, + .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | + IIO_CHAN_INFO_SCALE_SHARED_BIT, + .scan_index = 0, + .scan_type = IIO_ST('s', 24, 32, 0) + }, + .channel[1] = { + .type = IIO_VOLTAGE, + .differential = 1, + .indexed = 1, + .channel = 1, + .channel2 = 1, + .address = AD7793_CH_AIN2P_AIN2M, + .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | + IIO_CHAN_INFO_SCALE_SHARED_BIT, + .scan_index = 1, + .scan_type = IIO_ST('s', 24, 32, 0) + }, + .channel[2] = { + .type = IIO_VOLTAGE, + .differential = 1, + .indexed = 1, + .channel = 2, + .channel2 = 2, + .address = AD7793_CH_AIN3P_AIN3M, + .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | + IIO_CHAN_INFO_SCALE_SHARED_BIT, + .scan_index = 2, + .scan_type = IIO_ST('s', 24, 32, 0) + }, + .channel[3] = { + .type = IIO_VOLTAGE, + .differential = 1, + .extend_name = "shorted", + .indexed = 1, + .channel = 2, + .channel2 = 2, + .address = AD7793_CH_AIN1M_AIN1M, + .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | + IIO_CHAN_INFO_SCALE_SHARED_BIT, + .scan_index = 3, + .scan_type = IIO_ST('s', 24, 32, 0) + }, + .channel[4] = { + .type = IIO_TEMP, + .indexed = 1, + .channel = 0, + .address = AD7793_CH_TEMP, + .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | + IIO_CHAN_INFO_SCALE_SEPARATE_BIT, + .scan_index = 4, + .scan_type = IIO_ST('s', 24, 32, 0), + }, + .channel[5] = { + .type = IIO_VOLTAGE, + .extend_name = "supply", + .indexed = 1, + .channel = 4, + .address = AD7793_CH_AVDD_MONITOR, + .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | + IIO_CHAN_INFO_SCALE_SEPARATE_BIT, + .scan_index = 5, + .scan_type = IIO_ST('s', 24, 32, 0), + }, + .channel[6] = IIO_CHAN_SOFT_TIMESTAMP(6), }, - [ID_AD7794] = { - .channels = ad7794_channels, - .num_channels = ARRAY_SIZE(ad7794_channels), - }, - [ID_AD7795] = { - .channels = ad7795_channels, - .num_channels = ARRAY_SIZE(ad7795_channels), + [ID_AD7792] = { + .channel[0] = { + .type = IIO_VOLTAGE, + .differential = 1, + .indexed = 1, + .channel = 0, + .channel2 = 0, + .address = AD7793_CH_AIN1P_AIN1M, + .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | + IIO_CHAN_INFO_SCALE_SHARED_BIT, + .scan_index = 0, + .scan_type = IIO_ST('s', 16, 32, 0) + }, + .channel[1] = { + .type = IIO_VOLTAGE, + .differential = 1, + .indexed = 1, + .channel = 1, + .channel2 = 1, + .address = AD7793_CH_AIN2P_AIN2M, + .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | + IIO_CHAN_INFO_SCALE_SHARED_BIT, + .scan_index = 1, + .scan_type = IIO_ST('s', 16, 32, 0) + }, + .channel[2] = { + .type = IIO_VOLTAGE, + .differential = 1, + .indexed = 1, + .channel = 2, + .channel2 = 2, + .address = AD7793_CH_AIN3P_AIN3M, + .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | + IIO_CHAN_INFO_SCALE_SHARED_BIT, + .scan_index = 2, + .scan_type = IIO_ST('s', 16, 32, 0) + }, + .channel[3] = { + .type = IIO_VOLTAGE, + .differential = 1, + .extend_name = "shorted", + .indexed = 1, + .channel = 2, + .channel2 = 2, + .address = AD7793_CH_AIN1M_AIN1M, + .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | + IIO_CHAN_INFO_SCALE_SHARED_BIT, + .scan_index = 3, + .scan_type = IIO_ST('s', 16, 32, 0) + }, + .channel[4] = { + .type = IIO_TEMP, + .indexed = 1, + .channel = 0, + .address = AD7793_CH_TEMP, + .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | + IIO_CHAN_INFO_SCALE_SEPARATE_BIT, + .scan_index = 4, + .scan_type = IIO_ST('s', 16, 32, 0), + }, + .channel[5] = { + .type = IIO_VOLTAGE, + .extend_name = "supply", + .indexed = 1, + .channel = 4, + .address = AD7793_CH_AVDD_MONITOR, + .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | + IIO_CHAN_INFO_SCALE_SEPARATE_BIT, + .scan_index = 5, + .scan_type = IIO_ST('s', 16, 32, 0), + }, + .channel[6] = IIO_CHAN_SOFT_TIMESTAMP(6), }, }; static int __devinit ad7793_probe(struct spi_device *spi) { - const struct ad7793_platform_data *pdata = spi->dev.platform_data; + struct ad7793_platform_data *pdata = spi->dev.platform_data; struct ad7793_state *st; struct iio_dev *indio_dev; int ret, voltage_uv = 0; @@ -464,8 +882,6 @@ static int __devinit ad7793_probe(struct spi_device *spi) st = iio_priv(indio_dev); - ad_sd_init(&st->sd, indio_dev, spi, &ad7793_sigma_delta_info); - st->reg = regulator_get(&spi->dev, "vcc"); if (!IS_ERR(st->reg)) { ret = regulator_enable(st->reg); @@ -478,27 +894,36 @@ static int __devinit ad7793_probe(struct spi_device *spi) st->chip_info = &ad7793_chip_info_tbl[spi_get_device_id(spi)->driver_data]; + st->pdata = pdata; + if (pdata && pdata->vref_mv) st->int_vref_mv = pdata->vref_mv; else if (voltage_uv) st->int_vref_mv = voltage_uv / 1000; else - st->int_vref_mv = 1170; /* Build-in ref */ + st->int_vref_mv = 2500; /* Build-in ref */ spi_set_drvdata(spi, indio_dev); + st->spi = spi; indio_dev->dev.parent = &spi->dev; indio_dev->name = spi_get_device_id(spi)->name; indio_dev->modes = INDIO_DIRECT_MODE; - indio_dev->channels = st->chip_info->channels; - indio_dev->num_channels = st->chip_info->num_channels; + indio_dev->channels = st->chip_info->channel; + indio_dev->num_channels = 7; indio_dev->info = &ad7793_info; - ret = ad_sd_setup_buffer_and_trigger(indio_dev); + init_waitqueue_head(&st->wq_data_avail); + + ret = ad7793_register_ring_funcs_and_init(indio_dev); if (ret) goto error_disable_reg; - ret = ad7793_setup(indio_dev, pdata); + ret = ad7793_probe_trigger(indio_dev); + if (ret) + goto error_unreg_ring; + + ret = ad7793_setup(st); if (ret) goto error_remove_trigger; @@ -509,7 +934,9 @@ static int __devinit ad7793_probe(struct spi_device *spi) return 0; error_remove_trigger: - ad_sd_cleanup_buffer_and_trigger(indio_dev); + ad7793_remove_trigger(indio_dev); +error_unreg_ring: + ad7793_ring_cleanup(indio_dev); error_disable_reg: if (!IS_ERR(st->reg)) regulator_disable(st->reg); @@ -522,13 +949,14 @@ static int __devinit ad7793_probe(struct spi_device *spi) return ret; } -static int __devexit ad7793_remove(struct spi_device *spi) +static int ad7793_remove(struct spi_device *spi) { struct iio_dev *indio_dev = spi_get_drvdata(spi); struct ad7793_state *st = iio_priv(indio_dev); iio_device_unregister(indio_dev); - ad_sd_cleanup_buffer_and_trigger(indio_dev); + ad7793_remove_trigger(indio_dev); + ad7793_ring_cleanup(indio_dev); if (!IS_ERR(st->reg)) { regulator_disable(st->reg); @@ -541,11 +969,8 @@ static int __devexit ad7793_remove(struct spi_device *spi) } static const struct spi_device_id ad7793_id[] = { - {"ad7785", ID_AD7785}, {"ad7792", ID_AD7792}, {"ad7793", ID_AD7793}, - {"ad7794", ID_AD7794}, - {"ad7795", ID_AD7795}, {} }; MODULE_DEVICE_TABLE(spi, ad7793_id); @@ -562,5 +987,5 @@ static struct spi_driver ad7793_driver = { module_spi_driver(ad7793_driver); MODULE_AUTHOR("Michael Hennerich "); -MODULE_DESCRIPTION("Analog Devices AD7793 and simialr ADCs"); +MODULE_DESCRIPTION("Analog Devices AD7792/3 ADC"); MODULE_LICENSE("GPL v2"); diff --git a/trunk/drivers/staging/iio/adc/ad7793.h b/trunk/drivers/staging/iio/adc/ad7793.h index 8fdd450a2cd9..64f7d41dc453 100644 --- a/trunk/drivers/staging/iio/adc/ad7793.h +++ b/trunk/drivers/staging/iio/adc/ad7793.h @@ -41,7 +41,6 @@ /* Mode Register Bit Designations (AD7793_REG_MODE) */ #define AD7793_MODE_SEL(x) (((x) & 0x7) << 13) /* Operation Mode Select */ -#define AD7793_MODE_SEL_MASK (0x7 << 13) /* Operation Mode Select mask */ #define AD7793_MODE_CLKSRC(x) (((x) & 0x3) << 6) /* ADC Clock Source Select */ #define AD7793_MODE_RATE(x) ((x) & 0xF) /* Filter Update Rate Select */ @@ -70,8 +69,7 @@ #define AD7793_CONF_GAIN(x) (((x) & 0x7) << 8) /* Gain Select */ #define AD7793_CONF_REFSEL (1 << 7) /* INT/EXT Reference Select */ #define AD7793_CONF_BUF (1 << 4) /* Buffered Mode Enable */ -#define AD7793_CONF_CHAN(x) ((x) & 0xf) /* Channel select */ -#define AD7793_CONF_CHAN_MASK 0xf /* Channel select mask */ +#define AD7793_CONF_CHAN(x) ((x) & 0x7) /* Channel select */ #define AD7793_CH_AIN1P_AIN1M 0 /* AIN1(+) - AIN1(-) */ #define AD7793_CH_AIN2P_AIN2M 1 /* AIN2(+) - AIN2(-) */ @@ -80,15 +78,9 @@ #define AD7793_CH_TEMP 6 /* Temp Sensor */ #define AD7793_CH_AVDD_MONITOR 7 /* AVDD Monitor */ -#define AD7795_CH_AIN4P_AIN4M 4 /* AIN4(+) - AIN4(-) */ -#define AD7795_CH_AIN5P_AIN5M 5 /* AIN5(+) - AIN5(-) */ -#define AD7795_CH_AIN6P_AIN6M 6 /* AIN6(+) - AIN6(-) */ -#define AD7795_CH_AIN1M_AIN1M 8 /* AIN1(-) - AIN1(-) */ - /* ID Register Bit Designations (AD7793_REG_ID) */ #define AD7792_ID 0xA #define AD7793_ID 0xB -#define AD7795_ID 0xF #define AD7793_ID_MASK 0xF /* IO (Excitation Current Sources) Register Bit Designations (AD7793_REG_IO) */ diff --git a/trunk/drivers/staging/iio/adc/ad7887_core.c b/trunk/drivers/staging/iio/adc/ad7887_core.c index 551790584a12..397b84947155 100644 --- a/trunk/drivers/staging/iio/adc/ad7887_core.c +++ b/trunk/drivers/staging/iio/adc/ad7887_core.c @@ -219,7 +219,7 @@ static int __devinit ad7887_probe(struct spi_device *spi) return ret; } -static int __devexit ad7887_remove(struct spi_device *spi) +static int ad7887_remove(struct spi_device *spi) { struct iio_dev *indio_dev = spi_get_drvdata(spi); struct ad7887_state *st = iio_priv(indio_dev); diff --git a/trunk/drivers/staging/iio/adc/ad7887_ring.c b/trunk/drivers/staging/iio/adc/ad7887_ring.c index b39923bbeedc..c76fdb5081c2 100644 --- a/trunk/drivers/staging/iio/adc/ad7887_ring.c +++ b/trunk/drivers/staging/iio/adc/ad7887_ring.c @@ -95,7 +95,7 @@ static irqreturn_t ad7887_trigger_handler(int irq, void *p) memcpy(buf + indio_dev->scan_bytes - sizeof(s64), &time_ns, sizeof(time_ns)); - iio_push_to_buffer(indio_dev->buffer, buf); + indio_dev->buffer->access->store_to(indio_dev->buffer, buf, time_ns); done: kfree(buf); iio_trigger_notify_done(indio_dev->trig); diff --git a/trunk/drivers/staging/iio/adc/ad799x_ring.c b/trunk/drivers/staging/iio/adc/ad799x_ring.c index 86026d9b20bc..858a685e3889 100644 --- a/trunk/drivers/staging/iio/adc/ad799x_ring.c +++ b/trunk/drivers/staging/iio/adc/ad799x_ring.c @@ -35,6 +35,7 @@ static irqreturn_t ad799x_trigger_handler(int irq, void *p) struct iio_poll_func *pf = p; struct iio_dev *indio_dev = pf->indio_dev; struct ad799x_state *st = iio_priv(indio_dev); + struct iio_buffer *ring = indio_dev->buffer; s64 time_ns; __u8 *rxbuf; int b_sent; @@ -77,7 +78,7 @@ static irqreturn_t ad799x_trigger_handler(int irq, void *p) memcpy(rxbuf + indio_dev->scan_bytes - sizeof(s64), &time_ns, sizeof(time_ns)); - iio_push_to_buffer(indio_dev->buffer, rxbuf); + ring->access->store_to(indio_dev->buffer, rxbuf, time_ns); done: kfree(rxbuf); out: diff --git a/trunk/drivers/staging/iio/adc/lpc32xx_adc.c b/trunk/drivers/staging/iio/adc/lpc32xx_adc.c index 7e9bd0001cc7..348d051fc2f8 100644 --- a/trunk/drivers/staging/iio/adc/lpc32xx_adc.c +++ b/trunk/drivers/staging/iio/adc/lpc32xx_adc.c @@ -108,7 +108,7 @@ static const struct iio_info lpc32xx_adc_iio_info = { .scan_index = _index, \ } -static const struct iio_chan_spec lpc32xx_adc_iio_channels[] = { +static struct iio_chan_spec lpc32xx_adc_iio_channels[] = { LPC32XX_ADC_CHANNEL(0), LPC32XX_ADC_CHANNEL(1), LPC32XX_ADC_CHANNEL(2), diff --git a/trunk/drivers/staging/iio/adc/max1363.h b/trunk/drivers/staging/iio/adc/max1363.h index c746918683f1..2cd0112067b2 100644 --- a/trunk/drivers/staging/iio/adc/max1363.h +++ b/trunk/drivers/staging/iio/adc/max1363.h @@ -100,7 +100,7 @@ enum max1363_modes { */ struct max1363_chip_info { const struct iio_info *info; - const struct iio_chan_spec *channels; + struct iio_chan_spec *channels; int num_channels; const enum max1363_modes *mode_list; enum max1363_modes default_mode; diff --git a/trunk/drivers/staging/iio/adc/max1363_core.c b/trunk/drivers/staging/iio/adc/max1363_core.c index d7b4ffcfa052..6799ce23a395 100644 --- a/trunk/drivers/staging/iio/adc/max1363_core.c +++ b/trunk/drivers/staging/iio/adc/max1363_core.c @@ -335,12 +335,12 @@ static const enum max1363_modes max1363_mode_list[] = { IIO_CHAN_SOFT_TIMESTAMP(8) \ } -static const struct iio_chan_spec max1036_channels[] = MAX1363_4X_CHANS(8, 0); -static const struct iio_chan_spec max1136_channels[] = MAX1363_4X_CHANS(10, 0); -static const struct iio_chan_spec max1236_channels[] = MAX1363_4X_CHANS(12, 0); -static const struct iio_chan_spec max1361_channels[] = +static struct iio_chan_spec max1036_channels[] = MAX1363_4X_CHANS(8, 0); +static struct iio_chan_spec max1136_channels[] = MAX1363_4X_CHANS(10, 0); +static struct iio_chan_spec max1236_channels[] = MAX1363_4X_CHANS(12, 0); +static struct iio_chan_spec max1361_channels[] = MAX1363_4X_CHANS(10, MAX1363_EV_M); -static const struct iio_chan_spec max1363_channels[] = +static struct iio_chan_spec max1363_channels[] = MAX1363_4X_CHANS(12, MAX1363_EV_M); /* Applies to max1236, max1237 */ @@ -392,9 +392,9 @@ static const enum max1363_modes max1238_mode_list[] = { MAX1363_CHAN_B(11, 10, d11m10, 23, bits, 0), \ IIO_CHAN_SOFT_TIMESTAMP(24) \ } -static const struct iio_chan_spec max1038_channels[] = MAX1363_12X_CHANS(8); -static const struct iio_chan_spec max1138_channels[] = MAX1363_12X_CHANS(10); -static const struct iio_chan_spec max1238_channels[] = MAX1363_12X_CHANS(12); +static struct iio_chan_spec max1038_channels[] = MAX1363_12X_CHANS(8); +static struct iio_chan_spec max1138_channels[] = MAX1363_12X_CHANS(10); +static struct iio_chan_spec max1238_channels[] = MAX1363_12X_CHANS(12); static const enum max1363_modes max11607_mode_list[] = { _s0, _s1, _s2, _s3, @@ -433,9 +433,9 @@ static const enum max1363_modes max11608_mode_list[] = { MAX1363_CHAN_B(7, 6, d7m6, 15, bits, 0), \ IIO_CHAN_SOFT_TIMESTAMP(16) \ } -static const struct iio_chan_spec max11602_channels[] = MAX1363_8X_CHANS(8); -static const struct iio_chan_spec max11608_channels[] = MAX1363_8X_CHANS(10); -static const struct iio_chan_spec max11614_channels[] = MAX1363_8X_CHANS(12); +static struct iio_chan_spec max11602_channels[] = MAX1363_8X_CHANS(8); +static struct iio_chan_spec max11608_channels[] = MAX1363_8X_CHANS(10); +static struct iio_chan_spec max11614_channels[] = MAX1363_8X_CHANS(12); static const enum max1363_modes max11644_mode_list[] = { _s0, _s1, s0to1, d0m1, d1m0, @@ -449,8 +449,8 @@ static const enum max1363_modes max11644_mode_list[] = { IIO_CHAN_SOFT_TIMESTAMP(4) \ } -static const struct iio_chan_spec max11646_channels[] = MAX1363_2X_CHANS(10); -static const struct iio_chan_spec max11644_channels[] = MAX1363_2X_CHANS(12); +static struct iio_chan_spec max11646_channels[] = MAX1363_2X_CHANS(10); +static struct iio_chan_spec max11644_channels[] = MAX1363_2X_CHANS(12); enum { max1361, max1362, @@ -1367,7 +1367,7 @@ static int __devinit max1363_probe(struct i2c_client *client, return ret; } -static int __devexit max1363_remove(struct i2c_client *client) +static int max1363_remove(struct i2c_client *client) { struct iio_dev *indio_dev = i2c_get_clientdata(client); struct max1363_state *st = iio_priv(indio_dev); @@ -1434,11 +1434,11 @@ static struct i2c_driver max1363_driver = { .name = "max1363", }, .probe = max1363_probe, - .remove = __devexit_p(max1363_remove), + .remove = max1363_remove, .id_table = max1363_id, }; module_i2c_driver(max1363_driver); -MODULE_AUTHOR("Jonathan Cameron "); +MODULE_AUTHOR("Jonathan Cameron "); MODULE_DESCRIPTION("Maxim 1363 ADC"); MODULE_LICENSE("GPL v2"); diff --git a/trunk/drivers/staging/iio/adc/max1363_ring.c b/trunk/drivers/staging/iio/adc/max1363_ring.c index 5f74f3b7671a..774ae1b63550 100644 --- a/trunk/drivers/staging/iio/adc/max1363_ring.c +++ b/trunk/drivers/staging/iio/adc/max1363_ring.c @@ -80,7 +80,7 @@ static irqreturn_t max1363_trigger_handler(int irq, void *p) if (indio_dev->scan_timestamp) memcpy(rxbuf + d_size - sizeof(s64), &time_ns, sizeof(time_ns)); - iio_push_to_buffer(indio_dev->buffer, rxbuf); + iio_push_to_buffer(indio_dev->buffer, rxbuf, time_ns); done_free: kfree(rxbuf); diff --git a/trunk/drivers/staging/iio/adc/mxs-lradc.c b/trunk/drivers/staging/iio/adc/mxs-lradc.c deleted file mode 100644 index ca7c1fa88e71..000000000000 --- a/trunk/drivers/staging/iio/adc/mxs-lradc.c +++ /dev/null @@ -1,590 +0,0 @@ -/* - * Freescale i.MX28 LRADC driver - * - * Copyright (c) 2012 DENX Software Engineering, GmbH. - * Marek Vasut - * - * 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. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include -#include - -#define DRIVER_NAME "mxs-lradc" - -#define LRADC_MAX_DELAY_CHANS 4 -#define LRADC_MAX_MAPPED_CHANS 8 -#define LRADC_MAX_TOTAL_CHANS 16 - -#define LRADC_DELAY_TIMER_HZ 2000 - -/* - * Make this runtime configurable if necessary. Currently, if the buffered mode - * is enabled, the LRADC takes LRADC_DELAY_TIMER_LOOP samples of data before - * triggering IRQ. The sampling happens every (LRADC_DELAY_TIMER_PER / 2000) - * seconds. The result is that the samples arrive every 500mS. - */ -#define LRADC_DELAY_TIMER_PER 200 -#define LRADC_DELAY_TIMER_LOOP 5 - -static const char * const mxs_lradc_irq_name[] = { - "mxs-lradc-touchscreen", - "mxs-lradc-thresh0", - "mxs-lradc-thresh1", - "mxs-lradc-channel0", - "mxs-lradc-channel1", - "mxs-lradc-channel2", - "mxs-lradc-channel3", - "mxs-lradc-channel4", - "mxs-lradc-channel5", - "mxs-lradc-channel6", - "mxs-lradc-channel7", - "mxs-lradc-button0", - "mxs-lradc-button1", -}; - -struct mxs_lradc_chan { - uint8_t slot; - uint8_t flags; -}; - -struct mxs_lradc { - struct device *dev; - void __iomem *base; - int irq[13]; - - uint32_t *buffer; - struct iio_trigger *trig; - - struct mutex lock; - - uint8_t enable; - - struct completion completion; -}; - -#define LRADC_CTRL0 0x00 -#define LRADC_CTRL0_TOUCH_DETECT_ENABLE (1 << 23) -#define LRADC_CTRL0_TOUCH_SCREEN_TYPE (1 << 22) - -#define LRADC_CTRL1 0x10 -#define LRADC_CTRL1_LRADC_IRQ(n) (1 << (n)) -#define LRADC_CTRL1_LRADC_IRQ_MASK 0x1fff -#define LRADC_CTRL1_LRADC_IRQ_EN(n) (1 << ((n) + 16)) -#define LRADC_CTRL1_LRADC_IRQ_EN_MASK (0x1fff << 16) - -#define LRADC_CTRL2 0x20 -#define LRADC_CTRL2_TEMPSENSE_PWD (1 << 15) - -#define LRADC_CH(n) (0x50 + (0x10 * (n))) -#define LRADC_CH_ACCUMULATE (1 << 29) -#define LRADC_CH_NUM_SAMPLES_MASK (0x1f << 24) -#define LRADC_CH_NUM_SAMPLES_OFFSET 24 -#define LRADC_CH_VALUE_MASK 0x3ffff -#define LRADC_CH_VALUE_OFFSET 0 - -#define LRADC_DELAY(n) (0xd0 + (0x10 * (n))) -#define LRADC_DELAY_TRIGGER_LRADCS_MASK (0xff << 24) -#define LRADC_DELAY_TRIGGER_LRADCS_OFFSET 24 -#define LRADC_DELAY_KICK (1 << 20) -#define LRADC_DELAY_TRIGGER_DELAYS_MASK (0xf << 16) -#define LRADC_DELAY_TRIGGER_DELAYS_OFFSET 16 -#define LRADC_DELAY_LOOP_COUNT_MASK (0x1f << 11) -#define LRADC_DELAY_LOOP_COUNT_OFFSET 11 -#define LRADC_DELAY_DELAY_MASK 0x7ff -#define LRADC_DELAY_DELAY_OFFSET 0 - -#define LRADC_CTRL4 0x140 -#define LRADC_CTRL4_LRADCSELECT_MASK(n) (0xf << ((n) * 4)) -#define LRADC_CTRL4_LRADCSELECT_OFFSET(n) ((n) * 4) - -/* - * Raw I/O operations - */ -static int mxs_lradc_read_raw(struct iio_dev *iio_dev, - const struct iio_chan_spec *chan, - int *val, int *val2, long m) -{ - struct mxs_lradc *lradc = iio_priv(iio_dev); - int ret; - - if (m != IIO_CHAN_INFO_RAW) - return -EINVAL; - - /* Check for invalid channel */ - if (chan->channel > LRADC_MAX_TOTAL_CHANS) - return -EINVAL; - - /* - * See if there is no buffered operation in progess. If there is, simply - * bail out. This can be improved to support both buffered and raw IO at - * the same time, yet the code becomes horribly complicated. Therefore I - * applied KISS principle here. - */ - ret = mutex_trylock(&lradc->lock); - if (!ret) - return -EBUSY; - - INIT_COMPLETION(lradc->completion); - - /* - * No buffered operation in progress, map the channel and trigger it. - * Virtual channel 0 is always used here as the others are always not - * used if doing raw sampling. - */ - writel(LRADC_CTRL1_LRADC_IRQ_EN_MASK, - lradc->base + LRADC_CTRL1 + STMP_OFFSET_REG_CLR); - writel(0xff, lradc->base + LRADC_CTRL0 + STMP_OFFSET_REG_CLR); - - writel(chan->channel, lradc->base + LRADC_CTRL4); - writel(0, lradc->base + LRADC_CH(0)); - - /* Enable the IRQ and start sampling the channel. */ - writel(LRADC_CTRL1_LRADC_IRQ_EN(0), - lradc->base + LRADC_CTRL1 + STMP_OFFSET_REG_SET); - writel(1 << 0, lradc->base + LRADC_CTRL0 + STMP_OFFSET_REG_SET); - - /* Wait for completion on the channel, 1 second max. */ - ret = wait_for_completion_killable_timeout(&lradc->completion, HZ); - if (!ret) - ret = -ETIMEDOUT; - if (ret < 0) - goto err; - - /* Read the data. */ - *val = readl(lradc->base + LRADC_CH(0)) & LRADC_CH_VALUE_MASK; - ret = IIO_VAL_INT; - -err: - writel(LRADC_CTRL1_LRADC_IRQ_EN(0), - lradc->base + LRADC_CTRL1 + STMP_OFFSET_REG_CLR); - - mutex_unlock(&lradc->lock); - - return ret; -} - -static const struct iio_info mxs_lradc_iio_info = { - .driver_module = THIS_MODULE, - .read_raw = mxs_lradc_read_raw, -}; - -/* - * IRQ Handling - */ -static irqreturn_t mxs_lradc_handle_irq(int irq, void *data) -{ - struct iio_dev *iio = data; - struct mxs_lradc *lradc = iio_priv(iio); - unsigned long reg = readl(lradc->base + LRADC_CTRL1); - - if (!(reg & LRADC_CTRL1_LRADC_IRQ_MASK)) - return IRQ_NONE; - - /* - * Touchscreen IRQ handling code shall probably have priority - * and therefore shall be placed here. - */ - - if (iio_buffer_enabled(iio)) - iio_trigger_poll(iio->trig, iio_get_time_ns()); - else if (reg & LRADC_CTRL1_LRADC_IRQ(0)) - complete(&lradc->completion); - - writel(reg & LRADC_CTRL1_LRADC_IRQ_MASK, - lradc->base + LRADC_CTRL1 + STMP_OFFSET_REG_CLR); - - return IRQ_HANDLED; -} - -/* - * Trigger handling - */ -static irqreturn_t mxs_lradc_trigger_handler(int irq, void *p) -{ - struct iio_poll_func *pf = p; - struct iio_dev *iio = pf->indio_dev; - struct mxs_lradc *lradc = iio_priv(iio); - struct iio_buffer *buffer = iio->buffer; - const uint32_t chan_value = LRADC_CH_ACCUMULATE | - ((LRADC_DELAY_TIMER_LOOP - 1) << LRADC_CH_NUM_SAMPLES_OFFSET); - int i, j = 0; - - for_each_set_bit(i, iio->active_scan_mask, iio->masklength) { - lradc->buffer[j] = readl(lradc->base + LRADC_CH(j)); - writel(chan_value, lradc->base + LRADC_CH(j)); - lradc->buffer[j] &= LRADC_CH_VALUE_MASK; - lradc->buffer[j] /= LRADC_DELAY_TIMER_LOOP; - j++; - } - - if (iio->scan_timestamp) { - s64 *timestamp = (s64 *)((u8 *)lradc->buffer + - ALIGN(j, sizeof(s64))); - *timestamp = pf->timestamp; - } - - iio_push_to_buffer(buffer, (u8 *)lradc->buffer); - - iio_trigger_notify_done(iio->trig); - - return IRQ_HANDLED; -} - -static int mxs_lradc_configure_trigger(struct iio_trigger *trig, bool state) -{ - struct iio_dev *iio = trig->private_data; - struct mxs_lradc *lradc = iio_priv(iio); - const uint32_t st = state ? STMP_OFFSET_REG_SET : STMP_OFFSET_REG_CLR; - - writel(LRADC_DELAY_KICK, lradc->base + LRADC_DELAY(0) + st); - - return 0; -} - -static const struct iio_trigger_ops mxs_lradc_trigger_ops = { - .owner = THIS_MODULE, - .set_trigger_state = &mxs_lradc_configure_trigger, -}; - -static int mxs_lradc_trigger_init(struct iio_dev *iio) -{ - int ret; - struct iio_trigger *trig; - - trig = iio_trigger_alloc("%s-dev%i", iio->name, iio->id); - if (trig == NULL) - return -ENOMEM; - - trig->dev.parent = iio->dev.parent; - trig->private_data = iio; - trig->ops = &mxs_lradc_trigger_ops; - - ret = iio_trigger_register(trig); - if (ret) { - iio_trigger_free(trig); - return ret; - } - - iio->trig = trig; - - return 0; -} - -static void mxs_lradc_trigger_remove(struct iio_dev *iio) -{ - iio_trigger_unregister(iio->trig); - iio_trigger_free(iio->trig); -} - -static int mxs_lradc_buffer_preenable(struct iio_dev *iio) -{ - struct mxs_lradc *lradc = iio_priv(iio); - struct iio_buffer *buffer = iio->buffer; - int ret = 0, chan, ofs = 0, enable = 0; - uint32_t ctrl4 = 0; - uint32_t ctrl1_irq = 0; - const uint32_t chan_value = LRADC_CH_ACCUMULATE | - ((LRADC_DELAY_TIMER_LOOP - 1) << LRADC_CH_NUM_SAMPLES_OFFSET); - const int len = bitmap_weight(buffer->scan_mask, LRADC_MAX_TOTAL_CHANS); - - if (!len) - return -EINVAL; - - /* - * Lock the driver so raw access can not be done during buffered - * operation. This simplifies the code a lot. - */ - ret = mutex_trylock(&lradc->lock); - if (!ret) - return -EBUSY; - - lradc->buffer = kmalloc(len * sizeof(*lradc->buffer), GFP_KERNEL); - if (!lradc->buffer) { - ret = -ENOMEM; - goto err_mem; - } - - ret = iio_sw_buffer_preenable(iio); - if (ret < 0) - goto err_buf; - - writel(LRADC_CTRL1_LRADC_IRQ_EN_MASK, - lradc->base + LRADC_CTRL1 + STMP_OFFSET_REG_CLR); - writel(0xff, lradc->base + LRADC_CTRL0 + STMP_OFFSET_REG_CLR); - - for_each_set_bit(chan, buffer->scan_mask, LRADC_MAX_TOTAL_CHANS) { - ctrl4 |= chan << LRADC_CTRL4_LRADCSELECT_OFFSET(ofs); - ctrl1_irq |= LRADC_CTRL1_LRADC_IRQ_EN(ofs); - writel(chan_value, lradc->base + LRADC_CH(ofs)); - enable |= 1 << ofs; - ofs++; - }; - - writel(LRADC_DELAY_TRIGGER_LRADCS_MASK | LRADC_DELAY_KICK, - lradc->base + LRADC_DELAY(0) + STMP_OFFSET_REG_CLR); - - writel(ctrl4, lradc->base + LRADC_CTRL4); - writel(ctrl1_irq, lradc->base + LRADC_CTRL1 + STMP_OFFSET_REG_SET); - - writel(enable << LRADC_DELAY_TRIGGER_LRADCS_OFFSET, - lradc->base + LRADC_DELAY(0) + STMP_OFFSET_REG_SET); - - return 0; - -err_buf: - kfree(lradc->buffer); -err_mem: - mutex_unlock(&lradc->lock); - return ret; -} - -static int mxs_lradc_buffer_postdisable(struct iio_dev *iio) -{ - struct mxs_lradc *lradc = iio_priv(iio); - - writel(LRADC_DELAY_TRIGGER_LRADCS_MASK | LRADC_DELAY_KICK, - lradc->base + LRADC_DELAY(0) + STMP_OFFSET_REG_CLR); - - writel(0xff, lradc->base + LRADC_CTRL0 + STMP_OFFSET_REG_CLR); - writel(LRADC_CTRL1_LRADC_IRQ_EN_MASK, - lradc->base + LRADC_CTRL1 + STMP_OFFSET_REG_CLR); - - kfree(lradc->buffer); - mutex_unlock(&lradc->lock); - - return 0; -} - -static bool mxs_lradc_validate_scan_mask(struct iio_dev *iio, - const unsigned long *mask) -{ - const int mw = bitmap_weight(mask, iio->masklength); - - return mw <= LRADC_MAX_MAPPED_CHANS; -} - -static const struct iio_buffer_setup_ops mxs_lradc_buffer_ops = { - .preenable = &mxs_lradc_buffer_preenable, - .postenable = &iio_triggered_buffer_postenable, - .predisable = &iio_triggered_buffer_predisable, - .postdisable = &mxs_lradc_buffer_postdisable, - .validate_scan_mask = &mxs_lradc_validate_scan_mask, -}; - -/* - * Driver initialization - */ - -#define MXS_ADC_CHAN(idx, chan_type) { \ - .type = (chan_type), \ - .indexed = 1, \ - .scan_index = (idx), \ - .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT, \ - .channel = (idx), \ - .scan_type = { \ - .sign = 'u', \ - .realbits = 18, \ - .storagebits = 32, \ - }, \ -} - -static const struct iio_chan_spec mxs_lradc_chan_spec[] = { - MXS_ADC_CHAN(0, IIO_VOLTAGE), - MXS_ADC_CHAN(1, IIO_VOLTAGE), - MXS_ADC_CHAN(2, IIO_VOLTAGE), - MXS_ADC_CHAN(3, IIO_VOLTAGE), - MXS_ADC_CHAN(4, IIO_VOLTAGE), - MXS_ADC_CHAN(5, IIO_VOLTAGE), - MXS_ADC_CHAN(6, IIO_VOLTAGE), - MXS_ADC_CHAN(7, IIO_VOLTAGE), /* VBATT */ - MXS_ADC_CHAN(8, IIO_TEMP), /* Temp sense 0 */ - MXS_ADC_CHAN(9, IIO_TEMP), /* Temp sense 1 */ - MXS_ADC_CHAN(10, IIO_VOLTAGE), /* VDDIO */ - MXS_ADC_CHAN(11, IIO_VOLTAGE), /* VTH */ - MXS_ADC_CHAN(12, IIO_VOLTAGE), /* VDDA */ - MXS_ADC_CHAN(13, IIO_VOLTAGE), /* VDDD */ - MXS_ADC_CHAN(14, IIO_VOLTAGE), /* VBG */ - MXS_ADC_CHAN(15, IIO_VOLTAGE), /* VDD5V */ -}; - -static void mxs_lradc_hw_init(struct mxs_lradc *lradc) -{ - int i; - const uint32_t cfg = - (LRADC_DELAY_TIMER_PER << LRADC_DELAY_DELAY_OFFSET); - - stmp_reset_block(lradc->base); - - for (i = 0; i < LRADC_MAX_DELAY_CHANS; i++) - writel(cfg | (1 << (LRADC_DELAY_TRIGGER_DELAYS_OFFSET + i)), - lradc->base + LRADC_DELAY(i)); - - /* Start internal temperature sensing. */ - writel(0, lradc->base + LRADC_CTRL2); -} - -static void mxs_lradc_hw_stop(struct mxs_lradc *lradc) -{ - int i; - - writel(LRADC_CTRL1_LRADC_IRQ_EN_MASK, - lradc->base + LRADC_CTRL1 + STMP_OFFSET_REG_CLR); - - for (i = 0; i < LRADC_MAX_DELAY_CHANS; i++) - writel(0, lradc->base + LRADC_DELAY(i)); -} - -static int __devinit mxs_lradc_probe(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct mxs_lradc *lradc; - struct iio_dev *iio; - struct resource *iores; - int ret = 0; - int i; - - /* Allocate the IIO device. */ - iio = iio_device_alloc(sizeof(*lradc)); - if (!iio) { - dev_err(dev, "Failed to allocate IIO device\n"); - return -ENOMEM; - } - - lradc = iio_priv(iio); - - /* Grab the memory area */ - iores = platform_get_resource(pdev, IORESOURCE_MEM, 0); - lradc->dev = &pdev->dev; - lradc->base = devm_request_and_ioremap(dev, iores); - if (!lradc->base) { - ret = -EADDRNOTAVAIL; - goto err_addr; - } - - /* Grab all IRQ sources */ - for (i = 0; i < 13; i++) { - lradc->irq[i] = platform_get_irq(pdev, i); - if (lradc->irq[i] < 0) { - ret = -EINVAL; - goto err_addr; - } - - ret = devm_request_irq(dev, lradc->irq[i], - mxs_lradc_handle_irq, 0, - mxs_lradc_irq_name[i], iio); - if (ret) - goto err_addr; - } - - platform_set_drvdata(pdev, iio); - - init_completion(&lradc->completion); - mutex_init(&lradc->lock); - - iio->name = pdev->name; - iio->dev.parent = &pdev->dev; - iio->info = &mxs_lradc_iio_info; - iio->modes = INDIO_DIRECT_MODE; - iio->channels = mxs_lradc_chan_spec; - iio->num_channels = ARRAY_SIZE(mxs_lradc_chan_spec); - - ret = iio_triggered_buffer_setup(iio, &iio_pollfunc_store_time, - &mxs_lradc_trigger_handler, - &mxs_lradc_buffer_ops); - if (ret) - goto err_addr; - - ret = mxs_lradc_trigger_init(iio); - if (ret) - goto err_trig; - - /* Register IIO device. */ - ret = iio_device_register(iio); - if (ret) { - dev_err(dev, "Failed to register IIO device\n"); - goto err_dev; - } - - /* Configure the hardware. */ - mxs_lradc_hw_init(lradc); - - return 0; - -err_dev: - mxs_lradc_trigger_remove(iio); -err_trig: - iio_triggered_buffer_cleanup(iio); -err_addr: - iio_device_free(iio); - return ret; -} - -static int __devexit mxs_lradc_remove(struct platform_device *pdev) -{ - struct iio_dev *iio = platform_get_drvdata(pdev); - struct mxs_lradc *lradc = iio_priv(iio); - - mxs_lradc_hw_stop(lradc); - - iio_device_unregister(iio); - iio_triggered_buffer_cleanup(iio); - mxs_lradc_trigger_remove(iio); - iio_device_free(iio); - - return 0; -} - -static const struct of_device_id mxs_lradc_dt_ids[] = { - { .compatible = "fsl,imx28-lradc", }, - { /* sentinel */ } -}; -MODULE_DEVICE_TABLE(of, mxs_lradc_dt_ids); - -static struct platform_driver mxs_lradc_driver = { - .driver = { - .name = DRIVER_NAME, - .owner = THIS_MODULE, - .of_match_table = mxs_lradc_dt_ids, - }, - .probe = mxs_lradc_probe, - .remove = __devexit_p(mxs_lradc_remove), -}; - -module_platform_driver(mxs_lradc_driver); - -MODULE_AUTHOR("Marek Vasut "); -MODULE_DESCRIPTION("Freescale i.MX28 LRADC driver"); -MODULE_LICENSE("GPL v2"); diff --git a/trunk/drivers/staging/iio/adc/spear_adc.c b/trunk/drivers/staging/iio/adc/spear_adc.c index 0b83e2e1f410..64d630e6fe29 100644 --- a/trunk/drivers/staging/iio/adc/spear_adc.c +++ b/trunk/drivers/staging/iio/adc/spear_adc.c @@ -189,7 +189,7 @@ static int spear_read_raw(struct iio_dev *indio_dev, }, \ } -static const struct iio_chan_spec spear_adc_iio_channels[] = { +static struct iio_chan_spec spear_adc_iio_channels[] = { SPEAR_ADC_CHAN(0), SPEAR_ADC_CHAN(1), SPEAR_ADC_CHAN(2), @@ -330,30 +330,36 @@ static int __devinit spear_adc_probe(struct platform_device *pdev) goto errout3; } - ret = clk_prepare_enable(info->clk); + ret = clk_prepare(info->clk); if (ret) { - dev_err(dev, "failed enabling clock\n"); + dev_err(dev, "failed preparing clock\n"); goto errout4; } + ret = clk_enable(info->clk); + if (ret) { + dev_err(dev, "failed enabling clock\n"); + goto errout5; + } + irq = platform_get_irq(pdev, 0); if ((irq < 0) || (irq >= NR_IRQS)) { dev_err(dev, "failed getting interrupt resource\n"); ret = -EINVAL; - goto errout5; + goto errout6; } ret = devm_request_irq(dev, irq, spear_adc_isr, 0, MOD_NAME, info); if (ret < 0) { dev_err(dev, "failed requesting interrupt\n"); - goto errout5; + goto errout6; } if (of_property_read_u32(np, "sampling-frequency", &info->sampling_freq)) { dev_err(dev, "sampling-frequency missing in DT\n"); ret = -EINVAL; - goto errout5; + goto errout6; } /* @@ -383,14 +389,16 @@ static int __devinit spear_adc_probe(struct platform_device *pdev) ret = iio_device_register(iodev); if (ret) - goto errout5; + goto errout6; dev_info(dev, "SPEAR ADC driver loaded, IRQ %d\n", irq); return 0; +errout6: + clk_disable(info->clk); errout5: - clk_disable_unprepare(info->clk); + clk_unprepare(info->clk); errout4: clk_put(info->clk); errout3: @@ -408,7 +416,8 @@ static int __devexit spear_adc_remove(struct platform_device *pdev) iio_device_unregister(iodev); platform_set_drvdata(pdev, NULL); - clk_disable_unprepare(info->clk); + clk_disable(info->clk); + clk_unprepare(info->clk); clk_put(info->clk); iounmap(info->adc_base_spear6xx); iio_device_free(iodev); diff --git a/trunk/drivers/staging/iio/gyro/adis16060_core.c b/trunk/drivers/staging/iio/gyro/adis16060_core.c index 87151a7cff04..9931e2060e1f 100644 --- a/trunk/drivers/staging/iio/gyro/adis16060_core.c +++ b/trunk/drivers/staging/iio/gyro/adis16060_core.c @@ -184,7 +184,7 @@ static int __devinit adis16060_r_probe(struct spi_device *spi) } /* fixme, confirm ordering in this function */ -static int __devexit adis16060_r_remove(struct spi_device *spi) +static int adis16060_r_remove(struct spi_device *spi) { iio_device_unregister(spi_get_drvdata(spi)); iio_device_free(spi_get_drvdata(spi)); @@ -210,7 +210,7 @@ static int __devinit adis16060_w_probe(struct spi_device *spi) return ret; } -static int __devexit adis16060_w_remove(struct spi_device *spi) +static int adis16060_w_remove(struct spi_device *spi) { return 0; } diff --git a/trunk/drivers/staging/iio/gyro/adis16080_core.c b/trunk/drivers/staging/iio/gyro/adis16080_core.c index a73902573f79..345e4fa778ba 100644 --- a/trunk/drivers/staging/iio/gyro/adis16080_core.c +++ b/trunk/drivers/staging/iio/gyro/adis16080_core.c @@ -177,7 +177,7 @@ static int __devinit adis16080_probe(struct spi_device *spi) } /* fixme, confirm ordering in this function */ -static int __devexit adis16080_remove(struct spi_device *spi) +static int adis16080_remove(struct spi_device *spi) { iio_device_unregister(spi_get_drvdata(spi)); iio_device_free(spi_get_drvdata(spi)); diff --git a/trunk/drivers/staging/iio/gyro/adis16130_core.c b/trunk/drivers/staging/iio/gyro/adis16130_core.c index fbf96b0b6ee8..bf61cd0b5bbc 100644 --- a/trunk/drivers/staging/iio/gyro/adis16130_core.c +++ b/trunk/drivers/staging/iio/gyro/adis16130_core.c @@ -154,7 +154,7 @@ static int __devinit adis16130_probe(struct spi_device *spi) } /* fixme, confirm ordering in this function */ -static int __devexit adis16130_remove(struct spi_device *spi) +static int adis16130_remove(struct spi_device *spi) { iio_device_unregister(spi_get_drvdata(spi)); iio_device_free(spi_get_drvdata(spi)); diff --git a/trunk/drivers/staging/iio/gyro/adis16260_core.c b/trunk/drivers/staging/iio/gyro/adis16260_core.c index 9571c03aa4cc..93aa431287ac 100644 --- a/trunk/drivers/staging/iio/gyro/adis16260_core.c +++ b/trunk/drivers/staging/iio/gyro/adis16260_core.c @@ -195,8 +195,6 @@ static ssize_t adis16260_write_frequency(struct device *dev, ret = strict_strtol(buf, 10, &val); if (ret) return ret; - if (val == 0) - return -EINVAL; mutex_lock(&indio_dev->mlock); if (spi_get_device_id(st->us)) { @@ -700,18 +698,24 @@ static int __devinit adis16260_probe(struct spi_device *spi) return ret; } -static int __devexit adis16260_remove(struct spi_device *spi) +static int adis16260_remove(struct spi_device *spi) { + int ret; struct iio_dev *indio_dev = spi_get_drvdata(spi); iio_device_unregister(indio_dev); - adis16260_stop_device(indio_dev); + + ret = adis16260_stop_device(indio_dev); + if (ret) + goto err_ret; + adis16260_remove_trigger(indio_dev); iio_buffer_unregister(indio_dev); adis16260_unconfigure_ring(indio_dev); iio_device_free(indio_dev); - return 0; +err_ret: + return ret; } /* diff --git a/trunk/drivers/staging/iio/gyro/adis16260_ring.c b/trunk/drivers/staging/iio/gyro/adis16260_ring.c index e294cb49736d..eeee8e760e6c 100644 --- a/trunk/drivers/staging/iio/gyro/adis16260_ring.c +++ b/trunk/drivers/staging/iio/gyro/adis16260_ring.c @@ -62,6 +62,7 @@ static irqreturn_t adis16260_trigger_handler(int irq, void *p) struct iio_poll_func *pf = p; struct iio_dev *indio_dev = pf->indio_dev; struct adis16260_state *st = iio_priv(indio_dev); + struct iio_buffer *ring = indio_dev->buffer; int i = 0; s16 *data; @@ -81,7 +82,7 @@ static irqreturn_t adis16260_trigger_handler(int irq, void *p) if (indio_dev->scan_timestamp) *((s64 *)(data + ((i + 3)/4)*4)) = pf->timestamp; - iio_push_to_buffer(indio_dev->buffer, (u8 *)data); + ring->access->store_to(ring, (u8 *)data, pf->timestamp); kfree(data); done: diff --git a/trunk/drivers/staging/iio/gyro/adxrs450_core.c b/trunk/drivers/staging/iio/gyro/adxrs450_core.c index d93527d15917..6513119b1e90 100644 --- a/trunk/drivers/staging/iio/gyro/adxrs450_core.c +++ b/trunk/drivers/staging/iio/gyro/adxrs450_core.c @@ -409,7 +409,7 @@ static int __devinit adxrs450_probe(struct spi_device *spi) return ret; } -static int __devexit adxrs450_remove(struct spi_device *spi) +static int adxrs450_remove(struct spi_device *spi) { iio_device_unregister(spi_get_drvdata(spi)); iio_device_free(spi_get_drvdata(spi)); diff --git a/trunk/drivers/staging/iio/iio_dummy_evgen.c b/trunk/drivers/staging/iio/iio_dummy_evgen.c index 74e24e8aa876..0cd4fe916bf9 100644 --- a/trunk/drivers/staging/iio/iio_dummy_evgen.c +++ b/trunk/drivers/staging/iio/iio_dummy_evgen.c @@ -216,6 +216,6 @@ static __exit void iio_dummy_evgen_exit(void) } module_exit(iio_dummy_evgen_exit); -MODULE_AUTHOR("Jonathan Cameron "); +MODULE_AUTHOR("Jonathan Cameron "); MODULE_DESCRIPTION("IIO dummy driver"); MODULE_LICENSE("GPL v2"); diff --git a/trunk/drivers/staging/iio/iio_hwmon.c b/trunk/drivers/staging/iio/iio_hwmon.c index 5d491227e01b..27d27ec9521f 100644 --- a/trunk/drivers/staging/iio/iio_hwmon.c +++ b/trunk/drivers/staging/iio/iio_hwmon.c @@ -42,17 +42,40 @@ static ssize_t iio_hwmon_read_val(struct device *dev, struct device_attribute *attr, char *buf) { - int result; - int ret; + long result; + int val, ret, scaleint, scalepart; struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr); struct iio_hwmon_state *state = dev_get_drvdata(dev); - ret = iio_read_channel_processed(&state->channels[sattr->index], - &result); + /* + * No locking between this pair, so theoretically possible + * the scale has changed. + */ + ret = iio_read_channel_raw(&state->channels[sattr->index], + &val); if (ret < 0) return ret; - return sprintf(buf, "%d\n", result); + ret = iio_read_channel_scale(&state->channels[sattr->index], + &scaleint, &scalepart); + if (ret < 0) + return ret; + switch (ret) { + case IIO_VAL_INT: + result = val * scaleint; + break; + case IIO_VAL_INT_PLUS_MICRO: + result = (s64)val * (s64)scaleint + + div_s64((s64)val * (s64)scalepart, 1000000LL); + break; + case IIO_VAL_INT_PLUS_NANO: + result = (s64)val * (s64)scaleint + + div_s64((s64)val * (s64)scalepart, 1000000000LL); + break; + default: + return -EINVAL; + } + return sprintf(buf, "%ld\n", result); } static void iio_hwmon_free_attrs(struct iio_hwmon_state *st) @@ -192,8 +215,18 @@ static struct platform_driver __refdata iio_hwmon_driver = { .remove = __devexit_p(iio_hwmon_remove), }; -module_platform_driver(iio_hwmon_driver); +static int iio_inkern_init(void) +{ + return platform_driver_register(&iio_hwmon_driver); +} +module_init(iio_inkern_init); + +static void iio_inkern_exit(void) +{ + platform_driver_unregister(&iio_hwmon_driver); +} +module_exit(iio_inkern_exit); -MODULE_AUTHOR("Jonathan Cameron "); +MODULE_AUTHOR("Jonathan Cameron "); MODULE_DESCRIPTION("IIO to hwmon driver"); MODULE_LICENSE("GPL v2"); diff --git a/trunk/drivers/staging/iio/iio_simple_dummy.c b/trunk/drivers/staging/iio/iio_simple_dummy.c index dc6c728ea47a..155a49a9da7e 100644 --- a/trunk/drivers/staging/iio/iio_simple_dummy.c +++ b/trunk/drivers/staging/iio/iio_simple_dummy.c @@ -63,7 +63,7 @@ static const struct iio_dummy_accel_calibscale dummy_scales[] = { * This array of structures tells the IIO core about what the device * actually provides for a given channel. */ -static const struct iio_chan_spec iio_dummy_channels[] = { +static struct iio_chan_spec iio_dummy_channels[] = { /* indexed ADC channel in_voltage0_raw etc */ { .type = IIO_VOLTAGE, @@ -445,20 +445,26 @@ static int __devinit iio_dummy_probe(int index) if (ret < 0) goto error_free_device; + /* Configure buffered capture support. */ + ret = iio_simple_dummy_configure_buffer(indio_dev); + if (ret < 0) + goto error_unregister_events; + /* - * Configure buffered capture support and register the channels with the - * buffer, but avoid the output channel being registered by reducing the - * number of channels by 1. + * Register the channels with the buffer, but avoid the output + * channel being registered by reducing the number of channels by 1. */ - ret = iio_simple_dummy_configure_buffer(indio_dev, iio_dummy_channels, 5); + ret = iio_buffer_register(indio_dev, iio_dummy_channels, 5); if (ret < 0) - goto error_unregister_events; + goto error_unconfigure_buffer; ret = iio_device_register(indio_dev); if (ret < 0) - goto error_unconfigure_buffer; + goto error_unregister_buffer; return 0; +error_unregister_buffer: + iio_buffer_unregister(indio_dev); error_unconfigure_buffer: iio_simple_dummy_unconfigure_buffer(indio_dev); error_unregister_events: @@ -493,6 +499,7 @@ static int iio_dummy_remove(int index) /* Device specific code to power down etc */ /* Buffered capture related cleanup */ + iio_buffer_unregister(indio_dev); iio_simple_dummy_unconfigure_buffer(indio_dev); ret = iio_simple_dummy_events_unregister(indio_dev); @@ -523,7 +530,6 @@ static __init int iio_dummy_init(void) instances = 1; return -EINVAL; } - /* Fake a bus */ iio_dummy_devs = kcalloc(instances, sizeof(*iio_dummy_devs), GFP_KERNEL); @@ -552,6 +558,6 @@ static __exit void iio_dummy_exit(void) } module_exit(iio_dummy_exit); -MODULE_AUTHOR("Jonathan Cameron "); +MODULE_AUTHOR("Jonathan Cameron "); MODULE_DESCRIPTION("IIO dummy driver"); MODULE_LICENSE("GPL v2"); diff --git a/trunk/drivers/staging/iio/iio_simple_dummy.h b/trunk/drivers/staging/iio/iio_simple_dummy.h index c9e8702caca4..53975d916fc9 100644 --- a/trunk/drivers/staging/iio/iio_simple_dummy.h +++ b/trunk/drivers/staging/iio/iio_simple_dummy.h @@ -95,12 +95,10 @@ enum iio_simple_dummy_scan_elements { }; #ifdef CONFIG_IIO_SIMPLE_DUMMY_BUFFER -int iio_simple_dummy_configure_buffer(struct iio_dev *indio_dev, - const struct iio_chan_spec *channels, unsigned int num_channels); +int iio_simple_dummy_configure_buffer(struct iio_dev *indio_dev); void iio_simple_dummy_unconfigure_buffer(struct iio_dev *indio_dev); #else -static inline int iio_simple_dummy_configure_buffer(struct iio_dev *indio_dev, - const struct iio_chan_spec *channels, unsigned int num_channels) +static inline int iio_simple_dummy_configure_buffer(struct iio_dev *indio_dev) { return 0; }; diff --git a/trunk/drivers/staging/iio/iio_simple_dummy_buffer.c b/trunk/drivers/staging/iio/iio_simple_dummy_buffer.c index 697d9700db2f..bd628de472a9 100644 --- a/trunk/drivers/staging/iio/iio_simple_dummy_buffer.c +++ b/trunk/drivers/staging/iio/iio_simple_dummy_buffer.c @@ -87,7 +87,7 @@ static irqreturn_t iio_simple_dummy_trigger_h(int irq, void *p) if (indio_dev->scan_timestamp) *(s64 *)((u8 *)data + ALIGN(len, sizeof(s64))) = iio_get_time_ns(); - iio_push_to_buffer(buffer, (u8 *)data); + buffer->access->store_to(buffer, (u8 *)data, pf->timestamp); kfree(data); @@ -126,8 +126,7 @@ static const struct iio_buffer_setup_ops iio_simple_dummy_buffer_setup_ops = { .predisable = &iio_triggered_buffer_predisable, }; -int iio_simple_dummy_configure_buffer(struct iio_dev *indio_dev, - const struct iio_chan_spec *channels, unsigned int num_channels) +int iio_simple_dummy_configure_buffer(struct iio_dev *indio_dev) { int ret; struct iio_buffer *buffer; @@ -183,15 +182,8 @@ int iio_simple_dummy_configure_buffer(struct iio_dev *indio_dev, * driven by a trigger. */ indio_dev->modes |= INDIO_BUFFER_TRIGGERED; - - ret = iio_buffer_register(indio_dev, channels, num_channels); - if (ret) - goto error_dealloc_pollfunc; - return 0; -error_dealloc_pollfunc: - iio_dealloc_pollfunc(indio_dev->pollfunc); error_free_buffer: iio_kfifo_free(indio_dev->buffer); error_ret: @@ -205,7 +197,6 @@ int iio_simple_dummy_configure_buffer(struct iio_dev *indio_dev, */ void iio_simple_dummy_unconfigure_buffer(struct iio_dev *indio_dev) { - iio_buffer_unregister(indio_dev); iio_dealloc_pollfunc(indio_dev->pollfunc); iio_kfifo_free(indio_dev->buffer); } diff --git a/trunk/drivers/staging/iio/impedance-analyzer/ad5933.c b/trunk/drivers/staging/iio/impedance-analyzer/ad5933.c index de21d47f33e9..a8e51bc04439 100644 --- a/trunk/drivers/staging/iio/impedance-analyzer/ad5933.c +++ b/trunk/drivers/staging/iio/impedance-analyzer/ad5933.c @@ -108,7 +108,7 @@ static struct ad5933_platform_data ad5933_default_pdata = { .vref_mv = 3300, }; -static const struct iio_chan_spec ad5933_channels[] = { +static struct iio_chan_spec ad5933_channels[] = { { .type = IIO_TEMP, .indexed = 1, @@ -678,7 +678,7 @@ static void ad5933_work(struct work_struct *work) buf[0] = be16_to_cpu(buf[0]); } /* save datum to the ring */ - iio_push_to_buffer(ring, (u8 *)buf); + ring->access->store_to(ring, (u8 *)buf, iio_get_time_ns()); } else { /* no data available - try again later */ schedule_delayed_work(&st->work, st->poll_time_jiffies); diff --git a/trunk/drivers/staging/iio/imu/adis16400.h b/trunk/drivers/staging/iio/imu/adis16400.h index d59d7ac856a9..9dd9f1459a4d 100644 --- a/trunk/drivers/staging/iio/imu/adis16400.h +++ b/trunk/drivers/staging/iio/imu/adis16400.h @@ -5,7 +5,7 @@ * 3d 2.5gauss magnetometers via SPI * * Copyright (c) 2009 Manuel Stahl - * Copyright (c) 2007 Jonathan Cameron + * Copyright (c) 2007 Jonathan Cameron * * Loosely based upon lis3l02dq.h * diff --git a/trunk/drivers/staging/iio/imu/adis16400_core.c b/trunk/drivers/staging/iio/imu/adis16400_core.c index b302c9ba2712..1f4c17779b5a 100644 --- a/trunk/drivers/staging/iio/imu/adis16400_core.c +++ b/trunk/drivers/staging/iio/imu/adis16400_core.c @@ -5,7 +5,7 @@ * 3d Magnetometers via SPI * * Copyright (c) 2009 Manuel Stahl - * Copyright (c) 2007 Jonathan Cameron + * Copyright (c) 2007 Jonathan Cameron * Copyright (c) 2011 Analog Devices Inc. * * This program is free software; you can redistribute it and/or modify @@ -234,8 +234,6 @@ static ssize_t adis16400_write_frequency(struct device *dev, ret = strict_strtol(buf, 10, &val); if (ret) return ret; - if (val == 0) - return -EINVAL; mutex_lock(&indio_dev->mlock); @@ -612,7 +610,7 @@ static int adis16400_read_raw(struct iio_dev *indio_dev, } } -static const struct iio_chan_spec adis16400_channels[] = { +static struct iio_chan_spec adis16400_channels[] = { { .type = IIO_VOLTAGE, .indexed = 1, @@ -742,7 +740,7 @@ static const struct iio_chan_spec adis16400_channels[] = { IIO_CHAN_SOFT_TIMESTAMP(12) }; -static const struct iio_chan_spec adis16350_channels[] = { +static struct iio_chan_spec adis16350_channels[] = { { .type = IIO_VOLTAGE, .indexed = 1, @@ -867,7 +865,7 @@ static const struct iio_chan_spec adis16350_channels[] = { IIO_CHAN_SOFT_TIMESTAMP(11) }; -static const struct iio_chan_spec adis16300_channels[] = { +static struct iio_chan_spec adis16300_channels[] = { { .type = IIO_VOLTAGE, .indexed = 1, @@ -1206,12 +1204,15 @@ static int __devinit adis16400_probe(struct spi_device *spi) } /* fixme, confirm ordering in this function */ -static int __devexit adis16400_remove(struct spi_device *spi) +static int adis16400_remove(struct spi_device *spi) { + int ret; struct iio_dev *indio_dev = spi_get_drvdata(spi); iio_device_unregister(indio_dev); - adis16400_stop_device(indio_dev); + ret = adis16400_stop_device(indio_dev); + if (ret) + goto err_ret; adis16400_remove_trigger(indio_dev); iio_buffer_unregister(indio_dev); @@ -1219,6 +1220,9 @@ static int __devexit adis16400_remove(struct spi_device *spi) iio_device_free(indio_dev); return 0; + +err_ret: + return ret; } static const struct spi_device_id adis16400_id[] = { diff --git a/trunk/drivers/staging/iio/imu/adis16400_ring.c b/trunk/drivers/staging/iio/imu/adis16400_ring.c index 260bdd1a4681..beec650ddbdb 100644 --- a/trunk/drivers/staging/iio/imu/adis16400_ring.c +++ b/trunk/drivers/staging/iio/imu/adis16400_ring.c @@ -150,7 +150,7 @@ static irqreturn_t adis16400_trigger_handler(int irq, void *p) /* Guaranteed to be aligned with 8 byte boundary */ if (ring->scan_timestamp) *((s64 *)(data + ((i + 3)/4)*4)) = pf->timestamp; - iio_push_to_buffer(ring, (u8 *) data); + ring->access->store_to(indio_dev->buffer, (u8 *) data, pf->timestamp); done: kfree(data); diff --git a/trunk/drivers/staging/iio/light/isl29018.c b/trunk/drivers/staging/iio/light/isl29018.c index 6ee5567d9813..31d22f5591ca 100644 --- a/trunk/drivers/staging/iio/light/isl29018.c +++ b/trunk/drivers/staging/iio/light/isl29018.c @@ -63,7 +63,6 @@ struct isl29018_chip { struct regmap *regmap; struct mutex lock; unsigned int lux_scale; - unsigned int lux_uscale; unsigned int range; unsigned int adc_bit; int prox_scheme; @@ -146,22 +145,13 @@ static int isl29018_read_sensor_input(struct isl29018_chip *chip, int mode) static int isl29018_read_lux(struct isl29018_chip *chip, int *lux) { int lux_data; - unsigned int data_x_range, lux_unshifted; lux_data = isl29018_read_sensor_input(chip, COMMMAND1_OPMODE_ALS_ONCE); if (lux_data < 0) return lux_data; - /* To support fractional scaling, separate the unshifted lux - * into two calculations: int scaling and micro-scaling. - * lux_uscale ranges from 0-999999, so about 20 bits. Split - * the /1,000,000 in two to reduce the risk of over/underflow. - */ - data_x_range = lux_data * chip->range; - lux_unshifted = data_x_range * chip->lux_scale; - lux_unshifted += data_x_range / 1000 * chip->lux_uscale / 1000; - *lux = lux_unshifted >> chip->adc_bit; + *lux = (lux_data * chip->range * chip->lux_scale) >> chip->adc_bit; return 0; } @@ -349,8 +339,6 @@ static int isl29018_write_raw(struct iio_dev *indio_dev, mutex_lock(&chip->lock); if (mask == IIO_CHAN_INFO_CALIBSCALE && chan->type == IIO_LIGHT) { chip->lux_scale = val; - /* With no write_raw_get_fmt(), val2 is a MICRO fraction. */ - chip->lux_uscale = val2; ret = 0; } mutex_unlock(&chip->lock); @@ -391,8 +379,7 @@ static int isl29018_read_raw(struct iio_dev *indio_dev, case IIO_CHAN_INFO_CALIBSCALE: if (chan->type == IIO_LIGHT) { *val = chip->lux_scale; - *val2 = chip->lux_uscale; - ret = IIO_VAL_INT_PLUS_MICRO; + ret = IIO_VAL_INT; } break; default: diff --git a/trunk/drivers/staging/iio/light/tsl2563.c b/trunk/drivers/staging/iio/light/tsl2563.c index 954ca2c172c6..9d740be43a82 100644 --- a/trunk/drivers/staging/iio/light/tsl2563.c +++ b/trunk/drivers/staging/iio/light/tsl2563.c @@ -805,7 +805,7 @@ static int __devinit tsl2563_probe(struct i2c_client *client, return err; } -static int __devexit tsl2563_remove(struct i2c_client *client) +static int tsl2563_remove(struct i2c_client *client) { struct tsl2563_chip *chip = i2c_get_clientdata(client); struct iio_dev *indio_dev = iio_priv_to_dev(chip); diff --git a/trunk/drivers/staging/iio/magnetometer/hmc5843.c b/trunk/drivers/staging/iio/magnetometer/hmc5843.c index 10e095486e54..6c3e50f7c0d8 100644 --- a/trunk/drivers/staging/iio/magnetometer/hmc5843.c +++ b/trunk/drivers/staging/iio/magnetometer/hmc5843.c @@ -1,6 +1,6 @@ /* Copyright (C) 2010 Texas Instruments Author: Shubhrajyoti Datta - Acknowledgement: Jonathan Cameron for valuable inputs. + Acknowledgement: Jonathan Cameron for valuable inputs. Support for HMC5883 and HMC5883L by Peter Meerwald . diff --git a/trunk/drivers/staging/iio/meter/ade7753.c b/trunk/drivers/staging/iio/meter/ade7753.c index 8b9eceb66b37..f04ece7fbc2f 100644 --- a/trunk/drivers/staging/iio/meter/ade7753.c +++ b/trunk/drivers/staging/iio/meter/ade7753.c @@ -425,8 +425,6 @@ static ssize_t ade7753_write_frequency(struct device *dev, ret = strict_strtol(buf, 10, &val); if (ret) return ret; - if (val == 0) - return -EINVAL; mutex_lock(&indio_dev->mlock); @@ -555,15 +553,20 @@ static int __devinit ade7753_probe(struct spi_device *spi) } /* fixme, confirm ordering in this function */ -static int __devexit ade7753_remove(struct spi_device *spi) +static int ade7753_remove(struct spi_device *spi) { + int ret; struct iio_dev *indio_dev = spi_get_drvdata(spi); iio_device_unregister(indio_dev); - ade7753_stop_device(&indio_dev->dev); - iio_device_free(indio_dev); - return 0; + ret = ade7753_stop_device(&(indio_dev->dev)); + if (ret) + goto err_ret; + + iio_device_free(indio_dev); +err_ret: + return ret; } static struct spi_driver ade7753_driver = { diff --git a/trunk/drivers/staging/iio/meter/ade7754.c b/trunk/drivers/staging/iio/meter/ade7754.c index 76e0adee96ea..6cee28a5e877 100644 --- a/trunk/drivers/staging/iio/meter/ade7754.c +++ b/trunk/drivers/staging/iio/meter/ade7754.c @@ -445,8 +445,6 @@ static ssize_t ade7754_write_frequency(struct device *dev, ret = strict_strtol(buf, 10, &val); if (ret) return ret; - if (val == 0) - return -EINVAL; mutex_lock(&indio_dev->mlock); @@ -577,15 +575,21 @@ static int __devinit ade7754_probe(struct spi_device *spi) } /* fixme, confirm ordering in this function */ -static int __devexit ade7754_remove(struct spi_device *spi) +static int ade7754_remove(struct spi_device *spi) { + int ret; struct iio_dev *indio_dev = spi_get_drvdata(spi); iio_device_unregister(indio_dev); - ade7754_stop_device(&indio_dev->dev); + ret = ade7754_stop_device(&(indio_dev->dev)); + if (ret) + goto err_ret; + iio_device_free(indio_dev); - return 0; +err_ret: + return ret; + } static struct spi_driver ade7754_driver = { diff --git a/trunk/drivers/staging/iio/meter/ade7758.h b/trunk/drivers/staging/iio/meter/ade7758.h index 1e11ad5ae5a4..ec202b4ecfb2 100644 --- a/trunk/drivers/staging/iio/meter/ade7758.h +++ b/trunk/drivers/staging/iio/meter/ade7758.h @@ -122,7 +122,7 @@ struct ade7758_state { u8 *tx; u8 *rx; struct mutex buf_lock; - const struct iio_chan_spec *ade7758_ring_channels; + struct iio_chan_spec *ade7758_ring_channels; struct spi_transfer ring_xfer[4]; struct spi_message ring_msg; /* diff --git a/trunk/drivers/staging/iio/meter/ade7758_core.c b/trunk/drivers/staging/iio/meter/ade7758_core.c index a0fef77d8e5e..7014a0078446 100644 --- a/trunk/drivers/staging/iio/meter/ade7758_core.c +++ b/trunk/drivers/staging/iio/meter/ade7758_core.c @@ -661,7 +661,7 @@ static const struct attribute_group ade7758_attribute_group = { .attrs = ade7758_attributes, }; -static const struct iio_chan_spec ade7758_channels[] = { +static struct iio_chan_spec ade7758_channels[] = { { .type = IIO_VOLTAGE, .indexed = 1, @@ -962,13 +962,17 @@ static int __devinit ade7758_probe(struct spi_device *spi) return ret; } -static int __devexit ade7758_remove(struct spi_device *spi) +static int ade7758_remove(struct spi_device *spi) { struct iio_dev *indio_dev = spi_get_drvdata(spi); struct ade7758_state *st = iio_priv(indio_dev); + int ret; iio_device_unregister(indio_dev); - ade7758_stop_device(&indio_dev->dev); + ret = ade7758_stop_device(&indio_dev->dev); + if (ret) + goto err_ret; + ade7758_remove_trigger(indio_dev); ade7758_uninitialize_ring(indio_dev); ade7758_unconfigure_ring(indio_dev); @@ -977,7 +981,8 @@ static int __devexit ade7758_remove(struct spi_device *spi) iio_device_free(indio_dev); - return 0; +err_ret: + return ret; } static const struct spi_device_id ade7758_id[] = { diff --git a/trunk/drivers/staging/iio/meter/ade7758_ring.c b/trunk/drivers/staging/iio/meter/ade7758_ring.c index 9e49baccf660..1ce10b21f4d6 100644 --- a/trunk/drivers/staging/iio/meter/ade7758_ring.c +++ b/trunk/drivers/staging/iio/meter/ade7758_ring.c @@ -61,6 +61,7 @@ static irqreturn_t ade7758_trigger_handler(int irq, void *p) { struct iio_poll_func *pf = p; struct iio_dev *indio_dev = pf->indio_dev; + struct iio_buffer *ring = indio_dev->buffer; struct ade7758_state *st = iio_priv(indio_dev); s64 dat64[2]; u32 *dat32 = (u32 *)dat64; @@ -73,7 +74,7 @@ static irqreturn_t ade7758_trigger_handler(int irq, void *p) if (indio_dev->scan_timestamp) dat64[1] = pf->timestamp; - iio_push_to_buffer(indio_dev->buffer, (u8 *)dat64); + ring->access->store_to(ring, (u8 *)dat64, pf->timestamp); iio_trigger_notify_done(indio_dev->trig); diff --git a/trunk/drivers/staging/iio/meter/ade7759.c b/trunk/drivers/staging/iio/meter/ade7759.c index cb0707cbc347..b3f7e0fa9612 100644 --- a/trunk/drivers/staging/iio/meter/ade7759.c +++ b/trunk/drivers/staging/iio/meter/ade7759.c @@ -385,8 +385,6 @@ static ssize_t ade7759_write_frequency(struct device *dev, ret = strict_strtol(buf, 10, &val); if (ret) return ret; - if (val == 0) - return -EINVAL; mutex_lock(&indio_dev->mlock); @@ -499,15 +497,20 @@ static int __devinit ade7759_probe(struct spi_device *spi) } /* fixme, confirm ordering in this function */ -static int __devexit ade7759_remove(struct spi_device *spi) +static int ade7759_remove(struct spi_device *spi) { + int ret; struct iio_dev *indio_dev = spi_get_drvdata(spi); iio_device_unregister(indio_dev); - ade7759_stop_device(&indio_dev->dev); + ret = ade7759_stop_device(&(indio_dev->dev)); + if (ret) + goto err_ret; + iio_device_free(indio_dev); - return 0; +err_ret: + return ret; } static struct spi_driver ade7759_driver = { diff --git a/trunk/drivers/staging/iio/meter/ade7854-spi.c b/trunk/drivers/staging/iio/meter/ade7854-spi.c index 7dae03573428..9fb2f8bfca81 100644 --- a/trunk/drivers/staging/iio/meter/ade7854-spi.c +++ b/trunk/drivers/staging/iio/meter/ade7854-spi.c @@ -330,7 +330,7 @@ static int __devinit ade7854_spi_probe(struct spi_device *spi) return 0; } -static int __devexit ade7854_spi_remove(struct spi_device *spi) +static int ade7854_spi_remove(struct spi_device *spi) { ade7854_remove(spi_get_drvdata(spi)); diff --git a/trunk/drivers/staging/iio/resolver/ad2s1210.c b/trunk/drivers/staging/iio/resolver/ad2s1210.c index 4ba4d05ed423..f313859476c1 100644 --- a/trunk/drivers/staging/iio/resolver/ad2s1210.c +++ b/trunk/drivers/staging/iio/resolver/ad2s1210.c @@ -575,7 +575,7 @@ static IIO_DEVICE_ATTR(lot_low_thrd, S_IRUGO | S_IWUSR, AD2S1210_REG_LOT_LOW_THRD); -static const struct iio_chan_spec ad2s1210_channels[] = { +static struct iio_chan_spec ad2s1210_channels[] = { { .type = IIO_ANGL, .indexed = 1, diff --git a/trunk/drivers/staging/iio/ring_hw.h b/trunk/drivers/staging/iio/ring_hw.h index 39c14a715868..cad8a2ed9b68 100644 --- a/trunk/drivers/staging/iio/ring_hw.h +++ b/trunk/drivers/staging/iio/ring_hw.h @@ -5,7 +5,7 @@ * under the terms of the GNU General Public License version 2 as published by * the Free Software Foundation. * - * Copyright (c) 2009 Jonathan Cameron + * Copyright (c) 2009 Jonathan Cameron * */ diff --git a/trunk/drivers/staging/iio/ring_sw.c b/trunk/drivers/staging/iio/ring_sw.c index 3a45f9a52de8..f61c8fdaab06 100644 --- a/trunk/drivers/staging/iio/ring_sw.c +++ b/trunk/drivers/staging/iio/ring_sw.c @@ -65,7 +65,7 @@ static inline void __iio_free_sw_ring_buffer(struct iio_sw_ring_buffer *ring) /* Lock always held if their is a chance this may be called */ /* Only one of these per ring may run concurrently - enforced by drivers */ static int iio_store_to_sw_ring(struct iio_sw_ring_buffer *ring, - unsigned char *data) + unsigned char *data, s64 timestamp) { int ret = 0; unsigned char *temp_ptr, *change_test_ptr; @@ -256,10 +256,11 @@ static int iio_read_first_n_sw_rb(struct iio_buffer *r, } static int iio_store_to_sw_rb(struct iio_buffer *r, - u8 *data) + u8 *data, + s64 timestamp) { struct iio_sw_ring_buffer *ring = iio_to_sw_ring(r); - return iio_store_to_sw_ring(ring, data); + return iio_store_to_sw_ring(ring, data, timestamp); } static int iio_request_update_sw_rb(struct iio_buffer *r) diff --git a/trunk/drivers/staging/iio/trigger/Kconfig b/trunk/drivers/staging/iio/trigger/Kconfig index 7d3207559265..b8abf5473ddc 100644 --- a/trunk/drivers/staging/iio/trigger/Kconfig +++ b/trunk/drivers/staging/iio/trigger/Kconfig @@ -21,8 +21,6 @@ config IIO_GPIO_TRIGGER config IIO_SYSFS_TRIGGER tristate "SYSFS trigger" depends on SYSFS - depends on HAVE_IRQ_WORK - select IRQ_WORK help Provides support for using SYSFS entry as IIO triggers. If unsure, say N (but it's safe to say "Y"). diff --git a/trunk/drivers/staging/iio/trigger/iio-trig-bfin-timer.c b/trunk/drivers/staging/iio/trigger/iio-trig-bfin-timer.c index 52062d786f84..ce6a7b1b8860 100644 --- a/trunk/drivers/staging/iio/trigger/iio-trig-bfin-timer.c +++ b/trunk/drivers/staging/iio/trigger/iio-trig-bfin-timer.c @@ -14,18 +14,14 @@ #include #include -#include #include #include -#include "iio-trig-bfin-timer.h" - struct bfin_timer { unsigned short id, bit; unsigned long irqbit; int irq; - int pin; }; /* @@ -34,22 +30,22 @@ struct bfin_timer { */ static struct bfin_timer iio_bfin_timer_code[MAX_BLACKFIN_GPTIMERS] = { - {TIMER0_id, TIMER0bit, TIMER_STATUS_TIMIL0, IRQ_TIMER0, P_TMR0}, - {TIMER1_id, TIMER1bit, TIMER_STATUS_TIMIL1, IRQ_TIMER1, P_TMR1}, - {TIMER2_id, TIMER2bit, TIMER_STATUS_TIMIL2, IRQ_TIMER2, P_TMR2}, + {TIMER0_id, TIMER0bit, TIMER_STATUS_TIMIL0, IRQ_TIMER0}, + {TIMER1_id, TIMER1bit, TIMER_STATUS_TIMIL1, IRQ_TIMER1}, + {TIMER2_id, TIMER2bit, TIMER_STATUS_TIMIL2, IRQ_TIMER2}, #if (MAX_BLACKFIN_GPTIMERS > 3) - {TIMER3_id, TIMER3bit, TIMER_STATUS_TIMIL3, IRQ_TIMER3, P_TMR3}, - {TIMER4_id, TIMER4bit, TIMER_STATUS_TIMIL4, IRQ_TIMER4, P_TMR4}, - {TIMER5_id, TIMER5bit, TIMER_STATUS_TIMIL5, IRQ_TIMER5, P_TMR5}, - {TIMER6_id, TIMER6bit, TIMER_STATUS_TIMIL6, IRQ_TIMER6, P_TMR6}, - {TIMER7_id, TIMER7bit, TIMER_STATUS_TIMIL7, IRQ_TIMER7, P_TMR7}, + {TIMER3_id, TIMER3bit, TIMER_STATUS_TIMIL3, IRQ_TIMER3}, + {TIMER4_id, TIMER4bit, TIMER_STATUS_TIMIL4, IRQ_TIMER4}, + {TIMER5_id, TIMER5bit, TIMER_STATUS_TIMIL5, IRQ_TIMER5}, + {TIMER6_id, TIMER6bit, TIMER_STATUS_TIMIL6, IRQ_TIMER6}, + {TIMER7_id, TIMER7bit, TIMER_STATUS_TIMIL7, IRQ_TIMER7}, #endif #if (MAX_BLACKFIN_GPTIMERS > 8) - {TIMER8_id, TIMER8bit, TIMER_STATUS_TIMIL8, IRQ_TIMER8, P_TMR8}, - {TIMER9_id, TIMER9bit, TIMER_STATUS_TIMIL9, IRQ_TIMER9, P_TMR9}, - {TIMER10_id, TIMER10bit, TIMER_STATUS_TIMIL10, IRQ_TIMER10, P_TMR10}, + {TIMER8_id, TIMER8bit, TIMER_STATUS_TIMIL8, IRQ_TIMER8}, + {TIMER9_id, TIMER9bit, TIMER_STATUS_TIMIL9, IRQ_TIMER9}, + {TIMER10_id, TIMER10bit, TIMER_STATUS_TIMIL10, IRQ_TIMER10}, #if (MAX_BLACKFIN_GPTIMERS > 11) - {TIMER11_id, TIMER11bit, TIMER_STATUS_TIMIL11, IRQ_TIMER11, P_TMR11}, + {TIMER11_id, TIMER11bit, TIMER_STATUS_TIMIL11, IRQ_TIMER11}, #endif #endif }; @@ -58,33 +54,15 @@ struct bfin_tmr_state { struct iio_trigger *trig; struct bfin_timer *t; unsigned timer_num; - bool output_enable; - unsigned int duty; int irq; }; -static int iio_bfin_tmr_set_state(struct iio_trigger *trig, bool state) -{ - struct bfin_tmr_state *st = trig->private_data; - - if (get_gptimer_period(st->t->id) == 0) - return -EINVAL; - - if (state) - enable_gptimers(st->t->bit); - else - disable_gptimers(st->t->bit); - - return 0; -} - static ssize_t iio_bfin_tmr_frequency_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct iio_trigger *trig = to_iio_trigger(dev); struct bfin_tmr_state *st = trig->private_data; - unsigned long val; - bool enabled; + long val; int ret; ret = strict_strtoul(buf, 10, &val); @@ -96,25 +74,20 @@ static ssize_t iio_bfin_tmr_frequency_store(struct device *dev, goto error_ret; } - enabled = get_enabled_gptimers() & st->t->bit; - - if (enabled) - disable_gptimers(st->t->bit); + disable_gptimers(st->t->bit); if (!val) goto error_ret; val = get_sclk() / val; - if (val <= 4 || val <= st->duty) { + if (val <= 4) { ret = -EINVAL; goto error_ret; } set_gptimer_period(st->t->id, val); - set_gptimer_pwidth(st->t->id, val - st->duty); - - if (enabled) - enable_gptimers(st->t->bit); + set_gptimer_pwidth(st->t->id, 1); + enable_gptimers(st->t->bit); error_ret: return ret ? ret : count; @@ -126,15 +99,9 @@ static ssize_t iio_bfin_tmr_frequency_show(struct device *dev, { struct iio_trigger *trig = to_iio_trigger(dev); struct bfin_tmr_state *st = trig->private_data; - unsigned int period = get_gptimer_period(st->t->id); - unsigned long val; - - if (period == 0) - val = 0; - else - val = get_sclk() / get_gptimer_period(st->t->id); - return sprintf(buf, "%lu\n", val); + return sprintf(buf, "%lu\n", + get_sclk() / get_gptimer_period(st->t->id)); } static DEVICE_ATTR(frequency, S_IRUGO | S_IWUSR, iio_bfin_tmr_frequency_show, @@ -154,6 +121,7 @@ static const struct attribute_group *iio_bfin_tmr_trigger_attr_groups[] = { NULL }; + static irqreturn_t iio_bfin_tmr_trigger_isr(int irq, void *devid) { struct bfin_tmr_state *st = devid; @@ -177,14 +145,11 @@ static int iio_bfin_tmr_get_number(int irq) static const struct iio_trigger_ops iio_bfin_tmr_trigger_ops = { .owner = THIS_MODULE, - .set_trigger_state = iio_bfin_tmr_set_state, }; static int __devinit iio_bfin_tmr_trigger_probe(struct platform_device *pdev) { - struct iio_bfin_timer_trigger_pdata *pdata = pdev->dev.platform_data; struct bfin_tmr_state *st; - unsigned int config; int ret; st = kzalloc(sizeof(*st), GFP_KERNEL); @@ -228,43 +193,13 @@ static int __devinit iio_bfin_tmr_trigger_probe(struct platform_device *pdev) goto out4; } - config = PWM_OUT | PERIOD_CNT | IRQ_ENA; - - if (pdata && pdata->output_enable) { - unsigned long long val; - - st->output_enable = true; - - ret = peripheral_request(st->t->pin, st->trig->name); - if (ret) - goto out_free_irq; - - val = (unsigned long long)get_sclk() * pdata->duty_ns; - do_div(val, NSEC_PER_SEC); - st->duty = val; - - /** - * The interrupt will be generated at the end of the period, - * since we want the interrupt to be generated at end of the - * pulse we invert both polarity and duty cycle, so that the - * pulse will be generated directly before the interrupt. - */ - if (pdata->active_low) - config |= PULSE_HI; - } else { - st->duty = 1; - config |= OUT_DIS; - } - - set_gptimer_config(st->t->id, config); + set_gptimer_config(st->t->id, OUT_DIS | PWM_OUT | PERIOD_CNT | IRQ_ENA); dev_info(&pdev->dev, "iio trigger Blackfin TMR%d, IRQ-%d", st->timer_num, st->irq); platform_set_drvdata(pdev, st); return 0; -out_free_irq: - free_irq(st->irq, st); out4: iio_trigger_unregister(st->trig); out2: @@ -280,8 +215,6 @@ static int __devexit iio_bfin_tmr_trigger_remove(struct platform_device *pdev) struct bfin_tmr_state *st = platform_get_drvdata(pdev); disable_gptimers(st->t->bit); - if (st->output_enable) - peripheral_free(st->t->pin); free_irq(st->irq, st); iio_trigger_unregister(st->trig); iio_trigger_put(st->trig); diff --git a/trunk/drivers/staging/iio/trigger/iio-trig-bfin-timer.h b/trunk/drivers/staging/iio/trigger/iio-trig-bfin-timer.h deleted file mode 100644 index c07321f8d94c..000000000000 --- a/trunk/drivers/staging/iio/trigger/iio-trig-bfin-timer.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef __IIO_BFIN_TIMER_TRIGGER_H__ -#define __IIO_BFIN_TIMER_TRIGGER_H__ - -/** - * struct iio_bfin_timer_trigger_pdata - timer trigger platform data - * @output_enable: Enable external trigger pulse generation. - * @active_low: Whether the trigger pulse is active low. - * @duty_ns: Length of the trigger pulse in nanoseconds. - * - * This struct is used to configure the output pulse generation of the blackfin - * timer trigger. If output_enable is set to true an external trigger signal - * will generated on the pin corresponding to the timer. This is useful for - * converters which needs an external signal to start conversion. active_low and - * duty_ns are used to configure the type of the trigger pulse. If output_enable - * is set to false no external trigger pulse will be generated and active_low - * and duty_ns are ignored. - **/ -struct iio_bfin_timer_trigger_pdata { - bool output_enable; - bool active_low; - unsigned int duty_ns; -}; - -#endif diff --git a/trunk/drivers/staging/iio/trigger/iio-trig-gpio.c b/trunk/drivers/staging/iio/trigger/iio-trig-gpio.c index 5ff4d7fa20fa..90b26846fc6b 100644 --- a/trunk/drivers/staging/iio/trigger/iio-trig-gpio.c +++ b/trunk/drivers/staging/iio/trigger/iio-trig-gpio.c @@ -51,7 +51,7 @@ static const struct iio_trigger_ops iio_gpio_trigger_ops = { .owner = THIS_MODULE, }; -static int __devinit iio_gpio_trigger_probe(struct platform_device *pdev) +static int iio_gpio_trigger_probe(struct platform_device *pdev) { struct iio_gpio_trigger_info *trig_info; struct iio_trigger *trig, *trig2; @@ -130,7 +130,7 @@ static int __devinit iio_gpio_trigger_probe(struct platform_device *pdev) return ret; } -static int __devexit iio_gpio_trigger_remove(struct platform_device *pdev) +static int iio_gpio_trigger_remove(struct platform_device *pdev) { struct iio_trigger *trig, *trig2; struct iio_gpio_trigger_info *trig_info; @@ -153,7 +153,7 @@ static int __devexit iio_gpio_trigger_remove(struct platform_device *pdev) static struct platform_driver iio_gpio_trigger_driver = { .probe = iio_gpio_trigger_probe, - .remove = __devexit_p(iio_gpio_trigger_remove), + .remove = iio_gpio_trigger_remove, .driver = { .name = "iio_gpio_trigger", .owner = THIS_MODULE, @@ -162,6 +162,6 @@ static struct platform_driver iio_gpio_trigger_driver = { module_platform_driver(iio_gpio_trigger_driver); -MODULE_AUTHOR("Jonathan Cameron "); +MODULE_AUTHOR("Jonathan Cameron "); MODULE_DESCRIPTION("Example gpio trigger for the iio subsystem"); MODULE_LICENSE("GPL v2"); diff --git a/trunk/drivers/staging/iio/trigger/iio-trig-periodic-rtc.c b/trunk/drivers/staging/iio/trigger/iio-trig-periodic-rtc.c index a3de76d70cdc..4ceaa18ef9f4 100644 --- a/trunk/drivers/staging/iio/trigger/iio-trig-periodic-rtc.c +++ b/trunk/drivers/staging/iio/trigger/iio-trig-periodic-rtc.c @@ -101,7 +101,7 @@ static const struct iio_trigger_ops iio_prtc_trigger_ops = { .set_trigger_state = &iio_trig_periodic_rtc_set_state, }; -static int __devinit iio_trig_periodic_rtc_probe(struct platform_device *dev) +static int iio_trig_periodic_rtc_probe(struct platform_device *dev) { char **pdata = dev->dev.platform_data; struct iio_prtc_trigger_info *trig_info; @@ -167,7 +167,7 @@ static int __devinit iio_trig_periodic_rtc_probe(struct platform_device *dev) return ret; } -static int __devexit iio_trig_periodic_rtc_remove(struct platform_device *dev) +static int iio_trig_periodic_rtc_remove(struct platform_device *dev) { struct iio_trigger *trig, *trig2; struct iio_prtc_trigger_info *trig_info; @@ -188,7 +188,7 @@ static int __devexit iio_trig_periodic_rtc_remove(struct platform_device *dev) static struct platform_driver iio_trig_periodic_rtc_driver = { .probe = iio_trig_periodic_rtc_probe, - .remove = __devexit_p(iio_trig_periodic_rtc_remove), + .remove = iio_trig_periodic_rtc_remove, .driver = { .name = "iio_prtc_trigger", .owner = THIS_MODULE, @@ -197,6 +197,6 @@ static struct platform_driver iio_trig_periodic_rtc_driver = { module_platform_driver(iio_trig_periodic_rtc_driver); -MODULE_AUTHOR("Jonathan Cameron "); +MODULE_AUTHOR("Jonathan Cameron "); MODULE_DESCRIPTION("Periodic realtime clock trigger for the iio subsystem"); MODULE_LICENSE("GPL v2"); diff --git a/trunk/drivers/staging/iio/trigger/iio-trig-sysfs.c b/trunk/drivers/staging/iio/trigger/iio-trig-sysfs.c index 3bac97224bf4..fee474648108 100644 --- a/trunk/drivers/staging/iio/trigger/iio-trig-sysfs.c +++ b/trunk/drivers/staging/iio/trigger/iio-trig-sysfs.c @@ -10,14 +10,12 @@ #include #include #include -#include #include #include struct iio_sysfs_trig { struct iio_trigger *trig; - struct irq_work work; int id; struct list_head l; }; @@ -91,21 +89,11 @@ static struct device iio_sysfs_trig_dev = { .release = &iio_trigger_sysfs_release, }; -static void iio_sysfs_trigger_work(struct irq_work *work) -{ - struct iio_sysfs_trig *trig = container_of(work, struct iio_sysfs_trig, - work); - - iio_trigger_poll(trig->trig, 0); -} - static ssize_t iio_sysfs_trigger_poll(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct iio_trigger *trig = to_iio_trigger(dev); - struct iio_sysfs_trig *sysfs_trig = trig->private_data; - - irq_work_queue(&sysfs_trig->work); + iio_trigger_poll_chained(trig, 0); return count; } @@ -160,9 +148,6 @@ static int iio_sysfs_trigger_probe(int id) t->trig->dev.groups = iio_sysfs_trigger_attr_groups; t->trig->ops = &iio_sysfs_trigger_ops; t->trig->dev.parent = &iio_sysfs_trig_dev; - t->trig->private_data = t; - - init_irq_work(&t->work, iio_sysfs_trigger_work); ret = iio_trigger_register(t->trig); if (ret) diff --git a/trunk/drivers/staging/imx-drm/Kconfig b/trunk/drivers/staging/imx-drm/Kconfig deleted file mode 100644 index 14b4449df234..000000000000 --- a/trunk/drivers/staging/imx-drm/Kconfig +++ /dev/null @@ -1,35 +0,0 @@ -config DRM_IMX - tristate "DRM Support for Freescale i.MX" - select DRM_KMS_HELPER - select DRM_GEM_CMA_HELPER - select DRM_KMS_CMA_HELPER - depends on DRM && ARCH_MXC - help - enable i.MX graphics support - -config DRM_IMX_FB_HELPER - tristate "provide legacy framebuffer /dev/fb0" - select DRM_KMS_CMA_HELPER - depends on DRM_IMX - help - The DRM framework can provide a legacy /dev/fb0 framebuffer - for your device. This is necessary to get a framebuffer console - and also for appplications using the legacy framebuffer API - -config DRM_IMX_PARALLEL_DISPLAY - tristate "Support for parallel displays" - depends on DRM_IMX - -config DRM_IMX_IPUV3_CORE - tristate "IPUv3 core support" - depends on DRM_IMX - help - Choose this if you have a i.MX5/6 system and want - to use the IPU. This option only enables IPU base - support. - -config DRM_IMX_IPUV3 - tristate "DRM Support for i.MX IPUv3" - depends on DRM_IMX - help - Choose this if you have a i.MX5 or i.MX6 processor. diff --git a/trunk/drivers/staging/imx-drm/Makefile b/trunk/drivers/staging/imx-drm/Makefile deleted file mode 100644 index 83a9056546e6..000000000000 --- a/trunk/drivers/staging/imx-drm/Makefile +++ /dev/null @@ -1,9 +0,0 @@ - -imxdrm-objs := imx-drm-core.o imx-fb.o - -obj-$(CONFIG_DRM_IMX) += imxdrm.o - -obj-$(CONFIG_DRM_IMX_PARALLEL_DISPLAY) += parallel-display.o -obj-$(CONFIG_DRM_IMX_FB_HELPER) += imx-fbdev.o -obj-$(CONFIG_DRM_IMX_IPUV3_CORE) += ipu-v3/ -obj-$(CONFIG_DRM_IMX_IPUV3) += ipuv3-crtc.o diff --git a/trunk/drivers/staging/imx-drm/TODO b/trunk/drivers/staging/imx-drm/TODO deleted file mode 100644 index e52adc44e607..000000000000 --- a/trunk/drivers/staging/imx-drm/TODO +++ /dev/null @@ -1,22 +0,0 @@ -TODO: -- get DRM Maintainer review for this code -- Factor out more code to common helper functions -- decide where to put the base driver. It is not specific to a subsystem - and would be used by DRM/KMS and media/V4L2 -- convert irq driver to irq_domain_add_linear - -Missing features (not necessarily for moving out of staging): - -- Add KMS plane support for CRTC driver -- Add LDB (LVDS Display Bridge) support -- Add i.MX6 HDMI support -- Add support for IC (Image converter) -- Add support for CSI (CMOS Sensor interface) -- Add support for VDIC (Video Deinterlacer) - -Many work-in-progress patches for the above features exist. Contact -Sascha Hauer if you are interested in working -on a specific feature. - -Please send any patches to Greg Kroah-Hartman and -Sascha Hauer diff --git a/trunk/drivers/staging/imx-drm/imx-drm-core.c b/trunk/drivers/staging/imx-drm/imx-drm-core.c deleted file mode 100644 index 1913199ba16e..000000000000 --- a/trunk/drivers/staging/imx-drm/imx-drm-core.c +++ /dev/null @@ -1,884 +0,0 @@ -/* - * Freescale i.MX drm driver - * - * Copyright (C) 2011 Sascha Hauer, Pengutronix - * - * 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. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "imx-drm.h" - -#define MAX_CRTC 4 - -struct crtc_cookie { - void *cookie; - int id; - struct list_head list; -}; - -struct imx_drm_device { - struct drm_device *drm; - struct device *dev; - struct list_head crtc_list; - struct list_head encoder_list; - struct list_head connector_list; - struct mutex mutex; - int references; - int pipes; - struct drm_fbdev_cma *fbhelper; -}; - -struct imx_drm_crtc { - struct drm_crtc *crtc; - struct list_head list; - struct imx_drm_device *imxdrm; - int pipe; - struct imx_drm_crtc_helper_funcs imx_drm_helper_funcs; - struct module *owner; - struct crtc_cookie cookie; -}; - -struct imx_drm_encoder { - struct drm_encoder *encoder; - struct list_head list; - struct module *owner; - struct list_head possible_crtcs; -}; - -struct imx_drm_connector { - struct drm_connector *connector; - struct list_head list; - struct module *owner; -}; - -static int imx_drm_driver_firstopen(struct drm_device *drm) -{ - if (!imx_drm_device_get()) - return -EINVAL; - - return 0; -} - -static void imx_drm_driver_lastclose(struct drm_device *drm) -{ - struct imx_drm_device *imxdrm = drm->dev_private; - - if (imxdrm->fbhelper) - drm_fbdev_cma_restore_mode(imxdrm->fbhelper); - - imx_drm_device_put(); -} - -static int imx_drm_driver_unload(struct drm_device *drm) -{ - struct imx_drm_device *imxdrm = drm->dev_private; - - drm_mode_config_cleanup(imxdrm->drm); - drm_kms_helper_poll_fini(imxdrm->drm); - - return 0; -} - -/* - * We don't care at all for crtc numbers, but the core expects the - * crtcs to be numbered - */ -static struct imx_drm_crtc *imx_drm_crtc_by_num(struct imx_drm_device *imxdrm, - int num) -{ - struct imx_drm_crtc *imx_drm_crtc; - - list_for_each_entry(imx_drm_crtc, &imxdrm->crtc_list, list) - if (imx_drm_crtc->pipe == num) - return imx_drm_crtc; - return NULL; -} - -int imx_drm_crtc_panel_format(struct drm_crtc *crtc, u32 encoder_type, - u32 interface_pix_fmt) -{ - struct imx_drm_device *imxdrm = crtc->dev->dev_private; - struct imx_drm_crtc *imx_crtc; - struct imx_drm_crtc_helper_funcs *helper; - - mutex_lock(&imxdrm->mutex); - - list_for_each_entry(imx_crtc, &imxdrm->crtc_list, list) - if (imx_crtc->crtc == crtc) - goto found; - - mutex_unlock(&imxdrm->mutex); - - return -EINVAL; -found: - mutex_unlock(&imxdrm->mutex); - - helper = &imx_crtc->imx_drm_helper_funcs; - if (helper->set_interface_pix_fmt) - return helper->set_interface_pix_fmt(crtc, - encoder_type, interface_pix_fmt); - return 0; -} -EXPORT_SYMBOL_GPL(imx_drm_crtc_panel_format); - -int imx_drm_crtc_vblank_get(struct imx_drm_crtc *imx_drm_crtc) -{ - return drm_vblank_get(imx_drm_crtc->imxdrm->drm, imx_drm_crtc->pipe); -} -EXPORT_SYMBOL_GPL(imx_drm_crtc_vblank_get); - -void imx_drm_crtc_vblank_put(struct imx_drm_crtc *imx_drm_crtc) -{ - drm_vblank_put(imx_drm_crtc->imxdrm->drm, imx_drm_crtc->pipe); -} -EXPORT_SYMBOL_GPL(imx_drm_crtc_vblank_put); - -void imx_drm_handle_vblank(struct imx_drm_crtc *imx_drm_crtc) -{ - drm_handle_vblank(imx_drm_crtc->imxdrm->drm, imx_drm_crtc->pipe); -} -EXPORT_SYMBOL_GPL(imx_drm_handle_vblank); - -static int imx_drm_enable_vblank(struct drm_device *drm, int crtc) -{ - struct imx_drm_device *imxdrm = drm->dev_private; - struct imx_drm_crtc *imx_drm_crtc; - int ret; - - imx_drm_crtc = imx_drm_crtc_by_num(imxdrm, crtc); - if (!imx_drm_crtc) - return -EINVAL; - - if (!imx_drm_crtc->imx_drm_helper_funcs.enable_vblank) - return -ENOSYS; - - ret = imx_drm_crtc->imx_drm_helper_funcs.enable_vblank( - imx_drm_crtc->crtc); - - return ret; -} - -static void imx_drm_disable_vblank(struct drm_device *drm, int crtc) -{ - struct imx_drm_device *imxdrm = drm->dev_private; - struct imx_drm_crtc *imx_drm_crtc; - - imx_drm_crtc = imx_drm_crtc_by_num(imxdrm, crtc); - if (!imx_drm_crtc) - return; - - if (!imx_drm_crtc->imx_drm_helper_funcs.disable_vblank) - return; - - imx_drm_crtc->imx_drm_helper_funcs.disable_vblank(imx_drm_crtc->crtc); -} - -static const struct file_operations imx_drm_driver_fops = { - .owner = THIS_MODULE, - .open = drm_open, - .release = drm_release, - .unlocked_ioctl = drm_ioctl, - .mmap = drm_gem_cma_mmap, - .poll = drm_poll, - .fasync = drm_fasync, - .read = drm_read, - .llseek = noop_llseek, -}; - -static struct imx_drm_device *imx_drm_device; - -static struct imx_drm_device *__imx_drm_device(void) -{ - return imx_drm_device; -} - -struct drm_device *imx_drm_device_get(void) -{ - struct imx_drm_device *imxdrm = __imx_drm_device(); - struct imx_drm_encoder *enc; - struct imx_drm_connector *con; - struct imx_drm_crtc *crtc; - - mutex_lock(&imxdrm->mutex); - - list_for_each_entry(enc, &imxdrm->encoder_list, list) { - if (!try_module_get(enc->owner)) { - dev_err(imxdrm->dev, "could not get module %s\n", - module_name(enc->owner)); - goto unwind_enc; - } - } - - list_for_each_entry(con, &imxdrm->connector_list, list) { - if (!try_module_get(con->owner)) { - dev_err(imxdrm->dev, "could not get module %s\n", - module_name(con->owner)); - goto unwind_con; - } - } - - list_for_each_entry(crtc, &imxdrm->crtc_list, list) { - if (!try_module_get(crtc->owner)) { - dev_err(imxdrm->dev, "could not get module %s\n", - module_name(crtc->owner)); - goto unwind_crtc; - } - } - - imxdrm->references++; - - mutex_unlock(&imxdrm->mutex); - - return imxdrm->drm; - -unwind_crtc: - list_for_each_entry_continue_reverse(crtc, &imxdrm->crtc_list, list) - module_put(crtc->owner); -unwind_con: - list_for_each_entry_continue_reverse(con, &imxdrm->connector_list, list) - module_put(con->owner); -unwind_enc: - list_for_each_entry_continue_reverse(enc, &imxdrm->encoder_list, list) - module_put(enc->owner); - - mutex_unlock(&imxdrm->mutex); - - return NULL; - -} -EXPORT_SYMBOL_GPL(imx_drm_device_get); - -void imx_drm_device_put(void) -{ - struct imx_drm_device *imxdrm = __imx_drm_device(); - struct imx_drm_encoder *enc; - struct imx_drm_connector *con; - struct imx_drm_crtc *crtc; - - mutex_lock(&imxdrm->mutex); - - list_for_each_entry(crtc, &imxdrm->crtc_list, list) - module_put(crtc->owner); - - list_for_each_entry(con, &imxdrm->connector_list, list) - module_put(con->owner); - - list_for_each_entry(enc, &imxdrm->encoder_list, list) - module_put(enc->owner); - - imxdrm->references--; - - mutex_unlock(&imxdrm->mutex); -} -EXPORT_SYMBOL_GPL(imx_drm_device_put); - -static int drm_mode_group_reinit(struct drm_device *dev) -{ - struct drm_mode_group *group = &dev->primary->mode_group; - uint32_t *id_list = group->id_list; - int ret; - - ret = drm_mode_group_init_legacy_group(dev, group); - if (ret < 0) - return ret; - - kfree(id_list); - return 0; -} - -/* - * register an encoder to the drm core - */ -static int imx_drm_encoder_register(struct imx_drm_encoder *imx_drm_encoder) -{ - struct imx_drm_device *imxdrm = __imx_drm_device(); - - INIT_LIST_HEAD(&imx_drm_encoder->possible_crtcs); - - drm_encoder_init(imxdrm->drm, imx_drm_encoder->encoder, - imx_drm_encoder->encoder->funcs, - imx_drm_encoder->encoder->encoder_type); - - drm_mode_group_reinit(imxdrm->drm); - - return 0; -} - -/* - * unregister an encoder from the drm core - */ -static void imx_drm_encoder_unregister(struct imx_drm_encoder - *imx_drm_encoder) -{ - struct imx_drm_device *imxdrm = __imx_drm_device(); - - drm_encoder_cleanup(imx_drm_encoder->encoder); - - drm_mode_group_reinit(imxdrm->drm); -} - -/* - * register a connector to the drm core - */ -static int imx_drm_connector_register( - struct imx_drm_connector *imx_drm_connector) -{ - struct imx_drm_device *imxdrm = __imx_drm_device(); - - drm_connector_init(imxdrm->drm, imx_drm_connector->connector, - imx_drm_connector->connector->funcs, - imx_drm_connector->connector->connector_type); - drm_mode_group_reinit(imxdrm->drm); - - return drm_sysfs_connector_add(imx_drm_connector->connector); -} - -/* - * unregister a connector from the drm core - */ -static void imx_drm_connector_unregister( - struct imx_drm_connector *imx_drm_connector) -{ - struct imx_drm_device *imxdrm = __imx_drm_device(); - - drm_sysfs_connector_remove(imx_drm_connector->connector); - drm_connector_cleanup(imx_drm_connector->connector); - - drm_mode_group_reinit(imxdrm->drm); -} - -/* - * register a crtc to the drm core - */ -static int imx_drm_crtc_register(struct imx_drm_crtc *imx_drm_crtc) -{ - struct imx_drm_device *imxdrm = __imx_drm_device(); - int ret; - - drm_crtc_init(imxdrm->drm, imx_drm_crtc->crtc, - imx_drm_crtc->imx_drm_helper_funcs.crtc_funcs); - ret = drm_mode_crtc_set_gamma_size(imx_drm_crtc->crtc, 256); - if (ret) - return ret; - - drm_crtc_helper_add(imx_drm_crtc->crtc, - imx_drm_crtc->imx_drm_helper_funcs.crtc_helper_funcs); - - drm_mode_group_reinit(imxdrm->drm); - - return 0; -} - -/* - * Called by the CRTC driver when all CRTCs are registered. This - * puts all the pieces together and initializes the driver. - * Once this is called no more CRTCs can be registered since - * the drm core has hardcoded the number of crtcs in several - * places. - */ -static int imx_drm_driver_load(struct drm_device *drm, unsigned long flags) -{ - struct imx_drm_device *imxdrm = __imx_drm_device(); - int ret; - - imxdrm->drm = drm; - - drm->dev_private = imxdrm; - - /* - * enable drm irq mode. - * - with irq_enabled = 1, we can use the vblank feature. - * - * P.S. note that we wouldn't use drm irq handler but - * just specific driver own one instead because - * drm framework supports only one irq handler and - * drivers can well take care of their interrupts - */ - drm->irq_enabled = 1; - - drm_mode_config_init(drm); - imx_drm_mode_config_init(drm); - - mutex_lock(&imxdrm->mutex); - - drm_kms_helper_poll_init(imxdrm->drm); - - /* setup the grouping for the legacy output */ - ret = drm_mode_group_init_legacy_group(imxdrm->drm, - &imxdrm->drm->primary->mode_group); - if (ret) - goto err_init; - - ret = drm_vblank_init(imxdrm->drm, MAX_CRTC); - if (ret) - goto err_init; - - /* - * with vblank_disable_allowed = 1, vblank interrupt will be disabled - * by drm timer once a current process gives up ownership of - * vblank event.(after drm_vblank_put function is called) - */ - imxdrm->drm->vblank_disable_allowed = 1; - - ret = 0; - -err_init: - mutex_unlock(&imxdrm->mutex); - - return ret; -} - -static void imx_drm_update_possible_crtcs(void) -{ - struct imx_drm_device *imxdrm = __imx_drm_device(); - struct imx_drm_crtc *imx_drm_crtc; - struct imx_drm_encoder *enc; - struct crtc_cookie *cookie; - - list_for_each_entry(enc, &imxdrm->encoder_list, list) { - u32 possible_crtcs = 0; - - list_for_each_entry(cookie, &enc->possible_crtcs, list) { - list_for_each_entry(imx_drm_crtc, &imxdrm->crtc_list, list) { - if (imx_drm_crtc->cookie.cookie == cookie->cookie && - imx_drm_crtc->cookie.id == cookie->id) { - possible_crtcs |= 1 << imx_drm_crtc->pipe; - } - } - } - enc->encoder->possible_crtcs = possible_crtcs; - enc->encoder->possible_clones = possible_crtcs; - } -} - -/* - * imx_drm_add_crtc - add a new crtc - * - * The return value if !NULL is a cookie for the caller to pass to - * imx_drm_remove_crtc later. - */ -int imx_drm_add_crtc(struct drm_crtc *crtc, - struct imx_drm_crtc **new_crtc, - const struct imx_drm_crtc_helper_funcs *imx_drm_helper_funcs, - struct module *owner, void *cookie, int id) -{ - struct imx_drm_device *imxdrm = __imx_drm_device(); - struct imx_drm_crtc *imx_drm_crtc; - const struct drm_crtc_funcs *crtc_funcs; - int ret; - - mutex_lock(&imxdrm->mutex); - - if (imxdrm->references) { - ret = -EBUSY; - goto err_busy; - } - - imx_drm_crtc = kzalloc(sizeof(*imx_drm_crtc), GFP_KERNEL); - if (!imx_drm_crtc) { - ret = -ENOMEM; - goto err_alloc; - } - - imx_drm_crtc->imx_drm_helper_funcs = *imx_drm_helper_funcs; - imx_drm_crtc->pipe = imxdrm->pipes++; - imx_drm_crtc->cookie.cookie = cookie; - imx_drm_crtc->cookie.id = id; - - crtc_funcs = imx_drm_helper_funcs->crtc_funcs; - - imx_drm_crtc->crtc = crtc; - imx_drm_crtc->imxdrm = imxdrm; - - imx_drm_crtc->owner = owner; - - list_add_tail(&imx_drm_crtc->list, &imxdrm->crtc_list); - - *new_crtc = imx_drm_crtc; - - ret = imx_drm_crtc_register(imx_drm_crtc); - if (ret) - goto err_register; - - imx_drm_update_possible_crtcs(); - - mutex_unlock(&imxdrm->mutex); - - return 0; - -err_register: - kfree(imx_drm_crtc); -err_alloc: -err_busy: - mutex_unlock(&imxdrm->mutex); - return ret; -} -EXPORT_SYMBOL_GPL(imx_drm_add_crtc); - -/* - * imx_drm_remove_crtc - remove a crtc - */ -int imx_drm_remove_crtc(struct imx_drm_crtc *imx_drm_crtc) -{ - struct imx_drm_device *imxdrm = imx_drm_crtc->imxdrm; - - mutex_lock(&imxdrm->mutex); - - drm_crtc_cleanup(imx_drm_crtc->crtc); - - list_del(&imx_drm_crtc->list); - - drm_mode_group_reinit(imxdrm->drm); - - mutex_unlock(&imxdrm->mutex); - - kfree(imx_drm_crtc); - - return 0; -} -EXPORT_SYMBOL_GPL(imx_drm_remove_crtc); - -/* - * imx_drm_add_encoder - add a new encoder - */ -int imx_drm_add_encoder(struct drm_encoder *encoder, - struct imx_drm_encoder **newenc, struct module *owner) -{ - struct imx_drm_device *imxdrm = __imx_drm_device(); - struct imx_drm_encoder *imx_drm_encoder; - int ret; - - mutex_lock(&imxdrm->mutex); - - if (imxdrm->references) { - ret = -EBUSY; - goto err_busy; - } - - imx_drm_encoder = kzalloc(sizeof(*imx_drm_encoder), GFP_KERNEL); - if (!imx_drm_encoder) { - ret = -ENOMEM; - goto err_alloc; - } - - imx_drm_encoder->encoder = encoder; - imx_drm_encoder->owner = owner; - - ret = imx_drm_encoder_register(imx_drm_encoder); - if (ret) { - kfree(imx_drm_encoder); - ret = -ENOMEM; - goto err_register; - } - - list_add_tail(&imx_drm_encoder->list, &imxdrm->encoder_list); - - *newenc = imx_drm_encoder; - - mutex_unlock(&imxdrm->mutex); - - return 0; - -err_register: - kfree(imx_drm_encoder); -err_alloc: -err_busy: - mutex_unlock(&imxdrm->mutex); - - return ret; -} -EXPORT_SYMBOL_GPL(imx_drm_add_encoder); - -int imx_drm_encoder_add_possible_crtcs( - struct imx_drm_encoder *imx_drm_encoder, - struct device_node *np) -{ - struct imx_drm_device *imxdrm = __imx_drm_device(); - struct of_phandle_args args; - struct crtc_cookie *c; - int ret = 0; - int i; - - if (!list_empty(&imx_drm_encoder->possible_crtcs)) - return -EBUSY; - - for (i = 0; !ret; i++) { - ret = of_parse_phandle_with_args(np, "crtcs", - "#crtc-cells", i, &args); - if (ret < 0) - break; - - c = kzalloc(sizeof(*c), GFP_KERNEL); - if (!c) { - of_node_put(args.np); - return -ENOMEM; - } - - c->cookie = args.np; - c->id = args.args_count > 0 ? args.args[0] : 0; - - of_node_put(args.np); - - mutex_lock(&imxdrm->mutex); - - list_add_tail(&c->list, &imx_drm_encoder->possible_crtcs); - - mutex_unlock(&imxdrm->mutex); - } - - imx_drm_update_possible_crtcs(); - - return 0; -} -EXPORT_SYMBOL_GPL(imx_drm_encoder_add_possible_crtcs); - -int imx_drm_encoder_get_mux_id(struct imx_drm_encoder *imx_drm_encoder, - struct drm_crtc *crtc) -{ - struct imx_drm_device *imxdrm = __imx_drm_device(); - struct imx_drm_crtc *imx_crtc; - int i = 0; - - mutex_lock(&imxdrm->mutex); - - list_for_each_entry(imx_crtc, &imxdrm->crtc_list, list) { - if (imx_crtc->crtc == crtc) - goto found; - i++; - } - - mutex_unlock(&imxdrm->mutex); - - return -EINVAL; -found: - mutex_unlock(&imxdrm->mutex); - - return i; -} - -/* - * imx_drm_remove_encoder - remove an encoder - */ -int imx_drm_remove_encoder(struct imx_drm_encoder *imx_drm_encoder) -{ - struct imx_drm_device *imxdrm = __imx_drm_device(); - struct crtc_cookie *c, *tmp; - - mutex_lock(&imxdrm->mutex); - - imx_drm_encoder_unregister(imx_drm_encoder); - - list_del(&imx_drm_encoder->list); - - list_for_each_entry_safe(c, tmp, &imx_drm_encoder->possible_crtcs, - list) - kfree(c); - - mutex_unlock(&imxdrm->mutex); - - kfree(imx_drm_encoder); - - return 0; -} -EXPORT_SYMBOL_GPL(imx_drm_remove_encoder); - -/* - * imx_drm_add_connector - add a connector - */ -int imx_drm_add_connector(struct drm_connector *connector, - struct imx_drm_connector **new_con, - struct module *owner) -{ - struct imx_drm_device *imxdrm = __imx_drm_device(); - struct imx_drm_connector *imx_drm_connector; - int ret; - - mutex_lock(&imxdrm->mutex); - - if (imxdrm->references) { - ret = -EBUSY; - goto err_busy; - } - - imx_drm_connector = kzalloc(sizeof(*imx_drm_connector), GFP_KERNEL); - if (!imx_drm_connector) { - ret = -ENOMEM; - goto err_alloc; - } - - imx_drm_connector->connector = connector; - imx_drm_connector->owner = owner; - - ret = imx_drm_connector_register(imx_drm_connector); - if (ret) - goto err_register; - - list_add_tail(&imx_drm_connector->list, &imxdrm->connector_list); - - *new_con = imx_drm_connector; - - mutex_unlock(&imxdrm->mutex); - - return 0; - -err_register: - kfree(imx_drm_connector); -err_alloc: -err_busy: - mutex_unlock(&imxdrm->mutex); - - return ret; -} -EXPORT_SYMBOL_GPL(imx_drm_add_connector); - -void imx_drm_fb_helper_set(struct drm_fbdev_cma *fbdev_helper) -{ - struct imx_drm_device *imxdrm = __imx_drm_device(); - - imxdrm->fbhelper = fbdev_helper; -} -EXPORT_SYMBOL_GPL(imx_drm_fb_helper_set); - -/* - * imx_drm_remove_connector - remove a connector - */ -int imx_drm_remove_connector(struct imx_drm_connector *imx_drm_connector) -{ - struct imx_drm_device *imxdrm = __imx_drm_device(); - - mutex_lock(&imxdrm->mutex); - - imx_drm_connector_unregister(imx_drm_connector); - - list_del(&imx_drm_connector->list); - - mutex_unlock(&imxdrm->mutex); - - kfree(imx_drm_connector); - - return 0; -} -EXPORT_SYMBOL_GPL(imx_drm_remove_connector); - -static struct drm_ioctl_desc imx_drm_ioctls[] = { - /* none so far */ -}; - -static struct drm_driver imx_drm_driver = { - .driver_features = DRIVER_MODESET | DRIVER_GEM, - .load = imx_drm_driver_load, - .unload = imx_drm_driver_unload, - .firstopen = imx_drm_driver_firstopen, - .lastclose = imx_drm_driver_lastclose, - .gem_free_object = drm_gem_cma_free_object, - .gem_vm_ops = &drm_gem_cma_vm_ops, - .dumb_create = drm_gem_cma_dumb_create, - .dumb_map_offset = drm_gem_cma_dumb_map_offset, - .dumb_destroy = drm_gem_cma_dumb_destroy, - - .get_vblank_counter = drm_vblank_count, - .enable_vblank = imx_drm_enable_vblank, - .disable_vblank = imx_drm_disable_vblank, - .ioctls = imx_drm_ioctls, - .num_ioctls = ARRAY_SIZE(imx_drm_ioctls), - .fops = &imx_drm_driver_fops, - .name = "imx-drm", - .desc = "i.MX DRM graphics", - .date = "20120507", - .major = 1, - .minor = 0, - .patchlevel = 0, -}; - -static int imx_drm_platform_probe(struct platform_device *pdev) -{ - imx_drm_device->dev = &pdev->dev; - - return drm_platform_init(&imx_drm_driver, pdev); -} - -static int imx_drm_platform_remove(struct platform_device *pdev) -{ - drm_platform_exit(&imx_drm_driver, pdev); - - return 0; -} - -static struct platform_driver imx_drm_pdrv = { - .probe = imx_drm_platform_probe, - .remove = __devexit_p(imx_drm_platform_remove), - .driver = { - .owner = THIS_MODULE, - .name = "imx-drm", - }, -}; - -static struct platform_device *imx_drm_pdev; - -static int __init imx_drm_init(void) -{ - int ret; - - imx_drm_device = kzalloc(sizeof(*imx_drm_device), GFP_KERNEL); - if (!imx_drm_device) - return -ENOMEM; - - mutex_init(&imx_drm_device->mutex); - INIT_LIST_HEAD(&imx_drm_device->crtc_list); - INIT_LIST_HEAD(&imx_drm_device->connector_list); - INIT_LIST_HEAD(&imx_drm_device->encoder_list); - - imx_drm_pdev = platform_device_register_simple("imx-drm", -1, NULL, 0); - if (!imx_drm_pdev) { - ret = -EINVAL; - goto err_pdev; - } - - imx_drm_pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32), - - ret = platform_driver_register(&imx_drm_pdrv); - if (ret) - goto err_pdrv; - - return 0; - -err_pdrv: - platform_device_unregister(imx_drm_pdev); -err_pdev: - kfree(imx_drm_device); - - return ret; -} - -static void __exit imx_drm_exit(void) -{ - platform_device_unregister(imx_drm_pdev); - platform_driver_unregister(&imx_drm_pdrv); - - kfree(imx_drm_device); -} - -module_init(imx_drm_init); -module_exit(imx_drm_exit); - -MODULE_AUTHOR("Sascha Hauer "); -MODULE_DESCRIPTION("i.MX drm driver core"); -MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/staging/imx-drm/imx-drm.h b/trunk/drivers/staging/imx-drm/imx-drm.h deleted file mode 100644 index ae28a490c445..000000000000 --- a/trunk/drivers/staging/imx-drm/imx-drm.h +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef _IMX_DRM_H_ -#define _IMX_DRM_H_ - -struct imx_drm_crtc; -struct drm_fbdev_cma; - -struct imx_drm_crtc_helper_funcs { - int (*enable_vblank)(struct drm_crtc *crtc); - void (*disable_vblank)(struct drm_crtc *crtc); - int (*set_interface_pix_fmt)(struct drm_crtc *crtc, u32 encoder_type, - u32 pix_fmt); - const struct drm_crtc_helper_funcs *crtc_helper_funcs; - const struct drm_crtc_funcs *crtc_funcs; -}; - -int imx_drm_add_crtc(struct drm_crtc *crtc, - struct imx_drm_crtc **new_crtc, - const struct imx_drm_crtc_helper_funcs *imx_helper_funcs, - struct module *owner, void *cookie, int id); -int imx_drm_remove_crtc(struct imx_drm_crtc *); -int imx_drm_init_drm(struct platform_device *pdev, - int preferred_bpp); -int imx_drm_exit_drm(void); - -int imx_drm_crtc_vblank_get(struct imx_drm_crtc *imx_drm_crtc); -void imx_drm_crtc_vblank_put(struct imx_drm_crtc *imx_drm_crtc); -void imx_drm_handle_vblank(struct imx_drm_crtc *imx_drm_crtc); - -struct imx_drm_encoder; -int imx_drm_add_encoder(struct drm_encoder *encoder, - struct imx_drm_encoder **new_enc, - struct module *owner); -int imx_drm_remove_encoder(struct imx_drm_encoder *); - -struct imx_drm_connector; -int imx_drm_add_connector(struct drm_connector *connector, - struct imx_drm_connector **new_con, - struct module *owner); -int imx_drm_remove_connector(struct imx_drm_connector *); - -void imx_drm_mode_config_init(struct drm_device *drm); - -struct drm_gem_cma_object *imx_drm_fb_get_obj(struct drm_framebuffer *fb); - -struct drm_device *imx_drm_device_get(void); -void imx_drm_device_put(void); -int imx_drm_crtc_panel_format(struct drm_crtc *crtc, u32 encoder_type, - u32 interface_pix_fmt); -void imx_drm_fb_helper_set(struct drm_fbdev_cma *fbdev_helper); - -struct device_node; - -int imx_drm_encoder_get_mux_id(struct imx_drm_encoder *imx_drm_encoder, - struct drm_crtc *crtc); -int imx_drm_encoder_add_possible_crtcs(struct imx_drm_encoder *imx_drm_encoder, - struct device_node *np); - -#endif /* _IMX_DRM_H_ */ diff --git a/trunk/drivers/staging/imx-drm/imx-fb.c b/trunk/drivers/staging/imx-drm/imx-fb.c deleted file mode 100644 index 03a7b4e14f67..000000000000 --- a/trunk/drivers/staging/imx-drm/imx-fb.c +++ /dev/null @@ -1,47 +0,0 @@ -/* - * i.MX drm driver - * - * Copyright (C) 2012 Sascha Hauer, Pengutronix - * - * Based on Samsung Exynos code - * - * Copyright (c) 2011 Samsung Electronics Co., Ltd. - * - * 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. - * - */ -#include -#include -#include -#include -#include -#include - -#include "imx-drm.h" - -static struct drm_mode_config_funcs imx_drm_mode_config_funcs = { - .fb_create = drm_fb_cma_create, -}; - -void imx_drm_mode_config_init(struct drm_device *dev) -{ - dev->mode_config.min_width = 64; - dev->mode_config.min_height = 64; - - /* - * set max width and height as default value(4096x4096). - * this value would be used to check framebuffer size limitation - * at drm_mode_addfb(). - */ - dev->mode_config.max_width = 4096; - dev->mode_config.max_height = 4096; - - dev->mode_config.funcs = &imx_drm_mode_config_funcs; -} diff --git a/trunk/drivers/staging/imx-drm/imx-fbdev.c b/trunk/drivers/staging/imx-drm/imx-fbdev.c deleted file mode 100644 index 8331739c3d08..000000000000 --- a/trunk/drivers/staging/imx-drm/imx-fbdev.c +++ /dev/null @@ -1,74 +0,0 @@ -/* - * i.MX drm driver - * - * Copyright (C) 2012 Sascha Hauer, Pengutronix - * - * Based on Samsung Exynos code - * - * Copyright (c) 2011 Samsung Electronics Co., Ltd. - * - * 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. - * - */ -#include -#include -#include -#include -#include - -#include "imx-drm.h" - -#define MAX_CONNECTOR 4 -#define PREFERRED_BPP 16 - -static struct drm_fbdev_cma *fbdev_cma; - -static int legacyfb_depth = 16; - -module_param(legacyfb_depth, int, 0444); - -static int __init imx_fb_helper_init(void) -{ - struct drm_device *drm = imx_drm_device_get(); - - if (!drm) - return -EINVAL; - - if (legacyfb_depth != 16 && legacyfb_depth != 32) { - pr_warn("i.MX legacyfb: invalid legacyfb_depth setting. defaulting to 16bpp\n"); - legacyfb_depth = 16; - } - - fbdev_cma = drm_fbdev_cma_init(drm, legacyfb_depth, - drm->mode_config.num_crtc, MAX_CONNECTOR); - - if (IS_ERR(fbdev_cma)) { - imx_drm_device_put(); - return PTR_ERR(fbdev_cma); - } - - imx_drm_fb_helper_set(fbdev_cma); - - return 0; -} - -static void __exit imx_fb_helper_exit(void) -{ - imx_drm_fb_helper_set(NULL); - drm_fbdev_cma_fini(fbdev_cma); - imx_drm_device_put(); -} - -late_initcall(imx_fb_helper_init); -module_exit(imx_fb_helper_exit); - -MODULE_DESCRIPTION("Freescale i.MX legacy fb driver"); -MODULE_AUTHOR("Sascha Hauer, Pengutronix"); -MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/staging/imx-drm/ipu-v3/Makefile b/trunk/drivers/staging/imx-drm/ipu-v3/Makefile deleted file mode 100644 index 28ed72e98a96..000000000000 --- a/trunk/drivers/staging/imx-drm/ipu-v3/Makefile +++ /dev/null @@ -1,3 +0,0 @@ -obj-$(CONFIG_DRM_IMX_IPUV3_CORE) += imx-ipu-v3.o - -imx-ipu-v3-objs := ipu-common.o ipu-dc.o ipu-di.o ipu-dp.o ipu-dmfc.o diff --git a/trunk/drivers/staging/imx-drm/ipu-v3/imx-ipu-v3.h b/trunk/drivers/staging/imx-drm/ipu-v3/imx-ipu-v3.h deleted file mode 100644 index 74158dd73758..000000000000 --- a/trunk/drivers/staging/imx-drm/ipu-v3/imx-ipu-v3.h +++ /dev/null @@ -1,318 +0,0 @@ -/* - * Copyright 2005-2009 Freescale Semiconductor, Inc. - * - * The code contained herein is licensed under the GNU Lesser General - * Public License. You may obtain a copy of the GNU Lesser General - * Public License Version 2.1 or later at the following locations: - * - * http://www.opensource.org/licenses/lgpl-license.html - * http://www.gnu.org/copyleft/lgpl.html - */ - -#ifndef __DRM_IPU_H__ -#define __DRM_IPU_H__ - -#include -#include -#include -#include -#include - -struct ipu_soc; - -enum ipuv3_type { - IPUV3EX, - IPUV3M, - IPUV3H, -}; - -/* - * Bitfield of Display Interface signal polarities. - */ -struct ipu_di_signal_cfg { - unsigned datamask_en:1; - unsigned interlaced:1; - unsigned odd_field_first:1; - unsigned clksel_en:1; - unsigned clkidle_en:1; - unsigned data_pol:1; /* true = inverted */ - unsigned clk_pol:1; /* true = rising edge */ - unsigned enable_pol:1; - unsigned Hsync_pol:1; /* true = active high */ - unsigned Vsync_pol:1; - - u16 width; - u16 height; - u32 pixel_fmt; - u16 h_start_width; - u16 h_sync_width; - u16 h_end_width; - u16 v_start_width; - u16 v_sync_width; - u16 v_end_width; - u32 v_to_h_sync; - unsigned long pixelclock; -#define IPU_DI_CLKMODE_SYNC (1 << 0) -#define IPU_DI_CLKMODE_EXT (1 << 1) - unsigned long clkflags; -}; - -enum ipu_color_space { - IPUV3_COLORSPACE_RGB, - IPUV3_COLORSPACE_YUV, - IPUV3_COLORSPACE_UNKNOWN, -}; - -struct ipuv3_channel; - -enum ipu_channel_irq { - IPU_IRQ_EOF = 0, - IPU_IRQ_NFACK = 64, - IPU_IRQ_NFB4EOF = 128, - IPU_IRQ_EOS = 192, -}; - -int ipu_idmac_channel_irq(struct ipu_soc *ipu, struct ipuv3_channel *channel, - enum ipu_channel_irq irq); - -#define IPU_IRQ_DP_SF_START (448 + 2) -#define IPU_IRQ_DP_SF_END (448 + 3) -#define IPU_IRQ_BG_SF_END IPU_IRQ_DP_SF_END, -#define IPU_IRQ_DC_FC_0 (448 + 8) -#define IPU_IRQ_DC_FC_1 (448 + 9) -#define IPU_IRQ_DC_FC_2 (448 + 10) -#define IPU_IRQ_DC_FC_3 (448 + 11) -#define IPU_IRQ_DC_FC_4 (448 + 12) -#define IPU_IRQ_DC_FC_6 (448 + 13) -#define IPU_IRQ_VSYNC_PRE_0 (448 + 14) -#define IPU_IRQ_VSYNC_PRE_1 (448 + 15) - -/* - * IPU Image DMA Controller (idmac) functions - */ -struct ipuv3_channel *ipu_idmac_get(struct ipu_soc *ipu, unsigned channel); -void ipu_idmac_put(struct ipuv3_channel *); - -int ipu_idmac_enable_channel(struct ipuv3_channel *channel); -int ipu_idmac_disable_channel(struct ipuv3_channel *channel); - -void ipu_idmac_set_double_buffer(struct ipuv3_channel *channel, - bool doublebuffer); -void ipu_idmac_select_buffer(struct ipuv3_channel *channel, u32 buf_num); - -/* - * IPU Display Controller (dc) functions - */ -struct ipu_dc; -struct ipu_di; -struct ipu_dc *ipu_dc_get(struct ipu_soc *ipu, int channel); -void ipu_dc_put(struct ipu_dc *dc); -int ipu_dc_init_sync(struct ipu_dc *dc, struct ipu_di *di, bool interlaced, - u32 pixel_fmt, u32 width); -void ipu_dc_enable_channel(struct ipu_dc *dc); -void ipu_dc_disable_channel(struct ipu_dc *dc); - -/* - * IPU Display Interface (di) functions - */ -struct ipu_di *ipu_di_get(struct ipu_soc *ipu, int disp); -void ipu_di_put(struct ipu_di *); -int ipu_di_disable(struct ipu_di *); -int ipu_di_enable(struct ipu_di *); -int ipu_di_get_num(struct ipu_di *); -int ipu_di_init_sync_panel(struct ipu_di *, struct ipu_di_signal_cfg *sig); - -/* - * IPU Display Multi FIFO Controller (dmfc) functions - */ -struct dmfc_channel; -int ipu_dmfc_enable_channel(struct dmfc_channel *dmfc); -void ipu_dmfc_disable_channel(struct dmfc_channel *dmfc); -int ipu_dmfc_alloc_bandwidth(struct dmfc_channel *dmfc, - unsigned long bandwidth_mbs, int burstsize); -void ipu_dmfc_free_bandwidth(struct dmfc_channel *dmfc); -int ipu_dmfc_init_channel(struct dmfc_channel *dmfc, int width); -struct dmfc_channel *ipu_dmfc_get(struct ipu_soc *ipu, int ipuv3_channel); -void ipu_dmfc_put(struct dmfc_channel *dmfc); - -/* - * IPU Display Processor (dp) functions - */ -#define IPU_DP_FLOW_SYNC_BG 0 -#define IPU_DP_FLOW_SYNC_FG 1 -#define IPU_DP_FLOW_ASYNC0_BG 2 -#define IPU_DP_FLOW_ASYNC0_FG 3 -#define IPU_DP_FLOW_ASYNC1_BG 4 -#define IPU_DP_FLOW_ASYNC1_FG 5 - -struct ipu_dp *ipu_dp_get(struct ipu_soc *ipu, unsigned int flow); -void ipu_dp_put(struct ipu_dp *); -int ipu_dp_enable_channel(struct ipu_dp *dp); -void ipu_dp_disable_channel(struct ipu_dp *dp); -int ipu_dp_setup_channel(struct ipu_dp *dp, - enum ipu_color_space in, enum ipu_color_space out); -int ipu_dp_set_window_pos(struct ipu_dp *, u16 x_pos, u16 y_pos); -int ipu_dp_set_global_alpha(struct ipu_dp *dp, bool enable, u8 alpha, - bool bg_chan); - -#define IPU_CPMEM_WORD(word, ofs, size) ((((word) * 160 + (ofs)) << 8) | (size)) - -#define IPU_FIELD_UBO IPU_CPMEM_WORD(0, 46, 22) -#define IPU_FIELD_VBO IPU_CPMEM_WORD(0, 68, 22) -#define IPU_FIELD_IOX IPU_CPMEM_WORD(0, 90, 4) -#define IPU_FIELD_RDRW IPU_CPMEM_WORD(0, 94, 1) -#define IPU_FIELD_SO IPU_CPMEM_WORD(0, 113, 1) -#define IPU_FIELD_SLY IPU_CPMEM_WORD(1, 102, 14) -#define IPU_FIELD_SLUV IPU_CPMEM_WORD(1, 128, 14) - -#define IPU_FIELD_XV IPU_CPMEM_WORD(0, 0, 10) -#define IPU_FIELD_YV IPU_CPMEM_WORD(0, 10, 9) -#define IPU_FIELD_XB IPU_CPMEM_WORD(0, 19, 13) -#define IPU_FIELD_YB IPU_CPMEM_WORD(0, 32, 12) -#define IPU_FIELD_NSB_B IPU_CPMEM_WORD(0, 44, 1) -#define IPU_FIELD_CF IPU_CPMEM_WORD(0, 45, 1) -#define IPU_FIELD_SX IPU_CPMEM_WORD(0, 46, 12) -#define IPU_FIELD_SY IPU_CPMEM_WORD(0, 58, 11) -#define IPU_FIELD_NS IPU_CPMEM_WORD(0, 69, 10) -#define IPU_FIELD_SDX IPU_CPMEM_WORD(0, 79, 7) -#define IPU_FIELD_SM IPU_CPMEM_WORD(0, 86, 10) -#define IPU_FIELD_SCC IPU_CPMEM_WORD(0, 96, 1) -#define IPU_FIELD_SCE IPU_CPMEM_WORD(0, 97, 1) -#define IPU_FIELD_SDY IPU_CPMEM_WORD(0, 98, 7) -#define IPU_FIELD_SDRX IPU_CPMEM_WORD(0, 105, 1) -#define IPU_FIELD_SDRY IPU_CPMEM_WORD(0, 106, 1) -#define IPU_FIELD_BPP IPU_CPMEM_WORD(0, 107, 3) -#define IPU_FIELD_DEC_SEL IPU_CPMEM_WORD(0, 110, 2) -#define IPU_FIELD_DIM IPU_CPMEM_WORD(0, 112, 1) -#define IPU_FIELD_BNDM IPU_CPMEM_WORD(0, 114, 3) -#define IPU_FIELD_BM IPU_CPMEM_WORD(0, 117, 2) -#define IPU_FIELD_ROT IPU_CPMEM_WORD(0, 119, 1) -#define IPU_FIELD_HF IPU_CPMEM_WORD(0, 120, 1) -#define IPU_FIELD_VF IPU_CPMEM_WORD(0, 121, 1) -#define IPU_FIELD_THE IPU_CPMEM_WORD(0, 122, 1) -#define IPU_FIELD_CAP IPU_CPMEM_WORD(0, 123, 1) -#define IPU_FIELD_CAE IPU_CPMEM_WORD(0, 124, 1) -#define IPU_FIELD_FW IPU_CPMEM_WORD(0, 125, 13) -#define IPU_FIELD_FH IPU_CPMEM_WORD(0, 138, 12) -#define IPU_FIELD_EBA0 IPU_CPMEM_WORD(1, 0, 29) -#define IPU_FIELD_EBA1 IPU_CPMEM_WORD(1, 29, 29) -#define IPU_FIELD_ILO IPU_CPMEM_WORD(1, 58, 20) -#define IPU_FIELD_NPB IPU_CPMEM_WORD(1, 78, 7) -#define IPU_FIELD_PFS IPU_CPMEM_WORD(1, 85, 4) -#define IPU_FIELD_ALU IPU_CPMEM_WORD(1, 89, 1) -#define IPU_FIELD_ALBM IPU_CPMEM_WORD(1, 90, 3) -#define IPU_FIELD_ID IPU_CPMEM_WORD(1, 93, 2) -#define IPU_FIELD_TH IPU_CPMEM_WORD(1, 95, 7) -#define IPU_FIELD_SL IPU_CPMEM_WORD(1, 102, 14) -#define IPU_FIELD_WID0 IPU_CPMEM_WORD(1, 116, 3) -#define IPU_FIELD_WID1 IPU_CPMEM_WORD(1, 119, 3) -#define IPU_FIELD_WID2 IPU_CPMEM_WORD(1, 122, 3) -#define IPU_FIELD_WID3 IPU_CPMEM_WORD(1, 125, 3) -#define IPU_FIELD_OFS0 IPU_CPMEM_WORD(1, 128, 5) -#define IPU_FIELD_OFS1 IPU_CPMEM_WORD(1, 133, 5) -#define IPU_FIELD_OFS2 IPU_CPMEM_WORD(1, 138, 5) -#define IPU_FIELD_OFS3 IPU_CPMEM_WORD(1, 143, 5) -#define IPU_FIELD_SXYS IPU_CPMEM_WORD(1, 148, 1) -#define IPU_FIELD_CRE IPU_CPMEM_WORD(1, 149, 1) -#define IPU_FIELD_DEC_SEL2 IPU_CPMEM_WORD(1, 150, 1) - -struct ipu_cpmem_word { - u32 data[5]; - u32 res[3]; -}; - -struct ipu_ch_param { - struct ipu_cpmem_word word[2]; -}; - -void ipu_ch_param_write_field(struct ipu_ch_param __iomem *base, u32 wbs, u32 v); -u32 ipu_ch_param_read_field(struct ipu_ch_param __iomem *base, u32 wbs); -struct ipu_ch_param __iomem *ipu_get_cpmem(struct ipuv3_channel *channel); -void ipu_ch_param_dump(struct ipu_ch_param __iomem *p); - -static inline void ipu_ch_param_zero(struct ipu_ch_param __iomem *p) -{ - int i; - void __iomem *base = p; - - for (i = 0; i < sizeof(*p) / sizeof(u32); i++) - writel(0, base + i * sizeof(u32)); -} - -static inline void ipu_cpmem_set_buffer(struct ipu_ch_param __iomem *p, - int bufnum, dma_addr_t buf) -{ - if (bufnum) - ipu_ch_param_write_field(p, IPU_FIELD_EBA1, buf >> 3); - else - ipu_ch_param_write_field(p, IPU_FIELD_EBA0, buf >> 3); -} - -static inline void ipu_cpmem_set_resolution(struct ipu_ch_param __iomem *p, - int xres, int yres) -{ - ipu_ch_param_write_field(p, IPU_FIELD_FW, xres - 1); - ipu_ch_param_write_field(p, IPU_FIELD_FH, yres - 1); -} - -static inline void ipu_cpmem_set_stride(struct ipu_ch_param __iomem *p, - int stride) -{ - ipu_ch_param_write_field(p, IPU_FIELD_SLY, stride - 1); -} - -void ipu_cpmem_set_high_priority(struct ipuv3_channel *channel); - -struct ipu_rgb { - struct fb_bitfield red; - struct fb_bitfield green; - struct fb_bitfield blue; - struct fb_bitfield transp; - int bits_per_pixel; -}; - -struct ipu_image { - struct v4l2_pix_format pix; - struct v4l2_rect rect; - dma_addr_t phys; -}; - -int ipu_cpmem_set_format_passthrough(struct ipu_ch_param __iomem *p, - int width); - -int ipu_cpmem_set_format_rgb(struct ipu_ch_param __iomem *, - struct ipu_rgb *rgb); - -static inline void ipu_cpmem_interlaced_scan(struct ipu_ch_param *p, - int stride) -{ - ipu_ch_param_write_field(p, IPU_FIELD_SO, 1); - ipu_ch_param_write_field(p, IPU_FIELD_ILO, stride / 8); - ipu_ch_param_write_field(p, IPU_FIELD_SLY, (stride * 2) - 1); -}; - -void ipu_cpmem_set_yuv_planar(struct ipu_ch_param __iomem *p, u32 pixel_format, - int stride, int height); -void ipu_cpmem_set_yuv_planar_full(struct ipu_ch_param __iomem *p, - u32 pixel_format, int stride, int u_offset, int v_offset); -int ipu_cpmem_set_fmt(struct ipu_ch_param __iomem *cpmem, u32 pixelformat); -int ipu_cpmem_set_image(struct ipu_ch_param __iomem *cpmem, - struct ipu_image *image); - -enum ipu_color_space ipu_pixelformat_to_colorspace(u32 pixelformat); - -static inline void ipu_cpmem_set_burstsize(struct ipu_ch_param __iomem *p, - int burstsize) -{ - ipu_ch_param_write_field(p, IPU_FIELD_NPB, burstsize - 1); -}; - -struct ipu_client_platformdata { - int di; - int dc; - int dp; - int dmfc; - int dma[2]; -}; - -#endif /* __DRM_IPU_H__ */ diff --git a/trunk/drivers/staging/imx-drm/ipu-v3/ipu-common.c b/trunk/drivers/staging/imx-drm/ipu-v3/ipu-common.c deleted file mode 100644 index f381960f42b0..000000000000 --- a/trunk/drivers/staging/imx-drm/ipu-v3/ipu-common.c +++ /dev/null @@ -1,1143 +0,0 @@ -/* - * Copyright (c) 2010 Sascha Hauer - * Copyright (C) 2005-2009 Freescale Semiconductor, Inc. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * 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. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "imx-ipu-v3.h" -#include "ipu-prv.h" - -static inline u32 ipu_cm_read(struct ipu_soc *ipu, unsigned offset) -{ - return readl(ipu->cm_reg + offset); -} - -static inline void ipu_cm_write(struct ipu_soc *ipu, u32 value, unsigned offset) -{ - writel(value, ipu->cm_reg + offset); -} - -static inline u32 ipu_idmac_read(struct ipu_soc *ipu, unsigned offset) -{ - return readl(ipu->idmac_reg + offset); -} - -static inline void ipu_idmac_write(struct ipu_soc *ipu, u32 value, - unsigned offset) -{ - writel(value, ipu->idmac_reg + offset); -} - -void ipu_srm_dp_sync_update(struct ipu_soc *ipu) -{ - u32 val; - - val = ipu_cm_read(ipu, IPU_SRM_PRI2); - val |= 0x8; - ipu_cm_write(ipu, val, IPU_SRM_PRI2); -} -EXPORT_SYMBOL_GPL(ipu_srm_dp_sync_update); - -struct ipu_ch_param __iomem *ipu_get_cpmem(struct ipuv3_channel *channel) -{ - struct ipu_soc *ipu = channel->ipu; - - return ipu->cpmem_base + channel->num; -} -EXPORT_SYMBOL_GPL(ipu_get_cpmem); - -void ipu_cpmem_set_high_priority(struct ipuv3_channel *channel) -{ - struct ipu_soc *ipu = channel->ipu; - struct ipu_ch_param __iomem *p = ipu_get_cpmem(channel); - u32 val; - - if (ipu->ipu_type == IPUV3EX) - ipu_ch_param_write_field(p, IPU_FIELD_ID, 1); - - val = ipu_idmac_read(ipu, IDMAC_CHA_PRI(channel->num)); - val |= 1 << (channel->num % 32); - ipu_idmac_write(ipu, val, IDMAC_CHA_PRI(channel->num)); -}; -EXPORT_SYMBOL_GPL(ipu_cpmem_set_high_priority); - -void ipu_ch_param_write_field(struct ipu_ch_param __iomem *base, u32 wbs, u32 v) -{ - u32 bit = (wbs >> 8) % 160; - u32 size = wbs & 0xff; - u32 word = (wbs >> 8) / 160; - u32 i = bit / 32; - u32 ofs = bit % 32; - u32 mask = (1 << size) - 1; - u32 val; - - pr_debug("%s %d %d %d\n", __func__, word, bit , size); - - val = readl(&base->word[word].data[i]); - val &= ~(mask << ofs); - val |= v << ofs; - writel(val, &base->word[word].data[i]); - - if ((bit + size - 1) / 32 > i) { - val = readl(&base->word[word].data[i + 1]); - val &= ~(mask >> (ofs ? (32 - ofs) : 0)); - val |= v >> (ofs ? (32 - ofs) : 0); - writel(val, &base->word[word].data[i + 1]); - } -} -EXPORT_SYMBOL_GPL(ipu_ch_param_write_field); - -u32 ipu_ch_param_read_field(struct ipu_ch_param __iomem *base, u32 wbs) -{ - u32 bit = (wbs >> 8) % 160; - u32 size = wbs & 0xff; - u32 word = (wbs >> 8) / 160; - u32 i = bit / 32; - u32 ofs = bit % 32; - u32 mask = (1 << size) - 1; - u32 val = 0; - - pr_debug("%s %d %d %d\n", __func__, word, bit , size); - - val = (readl(&base->word[word].data[i]) >> ofs) & mask; - - if ((bit + size - 1) / 32 > i) { - u32 tmp; - tmp = readl(&base->word[word].data[i + 1]); - tmp &= mask >> (ofs ? (32 - ofs) : 0); - val |= tmp << (ofs ? (32 - ofs) : 0); - } - - return val; -} -EXPORT_SYMBOL_GPL(ipu_ch_param_read_field); - -int ipu_cpmem_set_format_rgb(struct ipu_ch_param __iomem *p, - struct ipu_rgb *rgb) -{ - int bpp = 0, npb = 0, ro, go, bo, to; - - ro = rgb->bits_per_pixel - rgb->red.length - rgb->red.offset; - go = rgb->bits_per_pixel - rgb->green.length - rgb->green.offset; - bo = rgb->bits_per_pixel - rgb->blue.length - rgb->blue.offset; - to = rgb->bits_per_pixel - rgb->transp.length - rgb->transp.offset; - - ipu_ch_param_write_field(p, IPU_FIELD_WID0, rgb->red.length - 1); - ipu_ch_param_write_field(p, IPU_FIELD_OFS0, ro); - ipu_ch_param_write_field(p, IPU_FIELD_WID1, rgb->green.length - 1); - ipu_ch_param_write_field(p, IPU_FIELD_OFS1, go); - ipu_ch_param_write_field(p, IPU_FIELD_WID2, rgb->blue.length - 1); - ipu_ch_param_write_field(p, IPU_FIELD_OFS2, bo); - - if (rgb->transp.length) { - ipu_ch_param_write_field(p, IPU_FIELD_WID3, - rgb->transp.length - 1); - ipu_ch_param_write_field(p, IPU_FIELD_OFS3, to); - } else { - ipu_ch_param_write_field(p, IPU_FIELD_WID3, 7); - ipu_ch_param_write_field(p, IPU_FIELD_OFS3, - rgb->bits_per_pixel); - } - - switch (rgb->bits_per_pixel) { - case 32: - bpp = 0; - npb = 15; - break; - case 24: - bpp = 1; - npb = 19; - break; - case 16: - bpp = 3; - npb = 31; - break; - case 8: - bpp = 5; - npb = 63; - break; - default: - return -EINVAL; - } - ipu_ch_param_write_field(p, IPU_FIELD_BPP, bpp); - ipu_ch_param_write_field(p, IPU_FIELD_NPB, npb); - ipu_ch_param_write_field(p, IPU_FIELD_PFS, 7); /* rgb mode */ - - return 0; -} -EXPORT_SYMBOL_GPL(ipu_cpmem_set_format_rgb); - -int ipu_cpmem_set_format_passthrough(struct ipu_ch_param __iomem *p, - int width) -{ - int bpp = 0, npb = 0; - - switch (width) { - case 32: - bpp = 0; - npb = 15; - break; - case 24: - bpp = 1; - npb = 19; - break; - case 16: - bpp = 3; - npb = 31; - break; - case 8: - bpp = 5; - npb = 63; - break; - default: - return -EINVAL; - } - - ipu_ch_param_write_field(p, IPU_FIELD_BPP, bpp); - ipu_ch_param_write_field(p, IPU_FIELD_NPB, npb); - ipu_ch_param_write_field(p, IPU_FIELD_PFS, 6); /* raw mode */ - - return 0; -} -EXPORT_SYMBOL_GPL(ipu_cpmem_set_format_passthrough); - -void ipu_cpmem_set_yuv_planar_full(struct ipu_ch_param __iomem *p, - u32 pixel_format, int stride, int u_offset, int v_offset) -{ - switch (pixel_format) { - case V4L2_PIX_FMT_YUV420: - ipu_ch_param_write_field(p, IPU_FIELD_SLUV, (stride / 2) - 1); - ipu_ch_param_write_field(p, IPU_FIELD_UBO, u_offset / 8); - ipu_ch_param_write_field(p, IPU_FIELD_VBO, v_offset / 8); - break; - } -} -EXPORT_SYMBOL_GPL(ipu_cpmem_set_yuv_planar_full); - -void ipu_cpmem_set_yuv_planar(struct ipu_ch_param __iomem *p, u32 pixel_format, - int stride, int height) -{ - int u_offset, v_offset; - int uv_stride = 0; - - switch (pixel_format) { - case V4L2_PIX_FMT_YUV420: - uv_stride = stride / 2; - u_offset = stride * height; - v_offset = u_offset + (uv_stride * height / 2); - ipu_cpmem_set_yuv_planar_full(p, V4L2_PIX_FMT_YUV420, stride, - u_offset, v_offset); - break; - } -} -EXPORT_SYMBOL_GPL(ipu_cpmem_set_yuv_planar); - -static struct ipu_rgb def_rgb_32 = { - .red = { .offset = 16, .length = 8, }, - .green = { .offset = 8, .length = 8, }, - .blue = { .offset = 0, .length = 8, }, - .transp = { .offset = 24, .length = 8, }, - .bits_per_pixel = 32, -}; - -static struct ipu_rgb def_bgr_32 = { - .red = { .offset = 16, .length = 8, }, - .green = { .offset = 8, .length = 8, }, - .blue = { .offset = 0, .length = 8, }, - .transp = { .offset = 24, .length = 8, }, - .bits_per_pixel = 32, -}; - -static struct ipu_rgb def_rgb_24 = { - .red = { .offset = 0, .length = 8, }, - .green = { .offset = 8, .length = 8, }, - .blue = { .offset = 16, .length = 8, }, - .transp = { .offset = 0, .length = 0, }, - .bits_per_pixel = 24, -}; - -static struct ipu_rgb def_bgr_24 = { - .red = { .offset = 16, .length = 8, }, - .green = { .offset = 8, .length = 8, }, - .blue = { .offset = 0, .length = 8, }, - .transp = { .offset = 0, .length = 0, }, - .bits_per_pixel = 24, -}; - -static struct ipu_rgb def_rgb_16 = { - .red = { .offset = 11, .length = 5, }, - .green = { .offset = 5, .length = 6, }, - .blue = { .offset = 0, .length = 5, }, - .transp = { .offset = 0, .length = 0, }, - .bits_per_pixel = 16, -}; - -#define Y_OFFSET(pix, x, y) ((x) + pix->width * (y)) -#define U_OFFSET(pix, x, y) ((pix->width * pix->height) + \ - (pix->width * (y) / 4) + (x) / 2) -#define V_OFFSET(pix, x, y) ((pix->width * pix->height) + \ - (pix->width * pix->height / 4) + \ - (pix->width * (y) / 4) + (x) / 2) - -int ipu_cpmem_set_fmt(struct ipu_ch_param __iomem *cpmem, u32 pixelformat) -{ - switch (pixelformat) { - case V4L2_PIX_FMT_YUV420: - /* pix format */ - ipu_ch_param_write_field(cpmem, IPU_FIELD_PFS, 2); - /* burst size */ - ipu_ch_param_write_field(cpmem, IPU_FIELD_NPB, 63); - break; - case V4L2_PIX_FMT_UYVY: - /* bits/pixel */ - ipu_ch_param_write_field(cpmem, IPU_FIELD_BPP, 3); - /* pix format */ - ipu_ch_param_write_field(cpmem, IPU_FIELD_PFS, 0xA); - /* burst size */ - ipu_ch_param_write_field(cpmem, IPU_FIELD_NPB, 31); - break; - case V4L2_PIX_FMT_YUYV: - /* bits/pixel */ - ipu_ch_param_write_field(cpmem, IPU_FIELD_BPP, 3); - /* pix format */ - ipu_ch_param_write_field(cpmem, IPU_FIELD_PFS, 0x8); - /* burst size */ - ipu_ch_param_write_field(cpmem, IPU_FIELD_NPB, 31); - break; - case V4L2_PIX_FMT_RGB32: - ipu_cpmem_set_format_rgb(cpmem, &def_rgb_32); - break; - case V4L2_PIX_FMT_RGB565: - ipu_cpmem_set_format_rgb(cpmem, &def_rgb_16); - break; - case V4L2_PIX_FMT_BGR32: - ipu_cpmem_set_format_rgb(cpmem, &def_bgr_32); - break; - case V4L2_PIX_FMT_RGB24: - ipu_cpmem_set_format_rgb(cpmem, &def_rgb_24); - break; - case V4L2_PIX_FMT_BGR24: - ipu_cpmem_set_format_rgb(cpmem, &def_bgr_24); - break; - default: - return -EINVAL; - } - - return 0; -} -EXPORT_SYMBOL_GPL(ipu_cpmem_set_fmt); - -int ipu_cpmem_set_image(struct ipu_ch_param __iomem *cpmem, - struct ipu_image *image) -{ - struct v4l2_pix_format *pix = &image->pix; - int y_offset, u_offset, v_offset; - - pr_debug("%s: resolution: %dx%d stride: %d\n", - __func__, pix->width, pix->height, - pix->bytesperline); - - ipu_cpmem_set_resolution(cpmem, image->rect.width, - image->rect.height); - ipu_cpmem_set_stride(cpmem, pix->bytesperline); - - ipu_cpmem_set_fmt(cpmem, pix->pixelformat); - - switch (pix->pixelformat) { - case V4L2_PIX_FMT_YUV420: - y_offset = Y_OFFSET(pix, image->rect.left, image->rect.top); - u_offset = U_OFFSET(pix, image->rect.left, - image->rect.top) - y_offset; - v_offset = V_OFFSET(pix, image->rect.left, - image->rect.top) - y_offset; - - ipu_cpmem_set_yuv_planar_full(cpmem, pix->pixelformat, - pix->bytesperline, u_offset, v_offset); - ipu_cpmem_set_buffer(cpmem, 0, image->phys + y_offset); - break; - case V4L2_PIX_FMT_UYVY: - ipu_cpmem_set_buffer(cpmem, 0, image->phys + - image->rect.left * 2 + - image->rect.top * image->pix.bytesperline); - break; - case V4L2_PIX_FMT_RGB32: - case V4L2_PIX_FMT_BGR32: - ipu_cpmem_set_buffer(cpmem, 0, image->phys + - image->rect.left * 4 + - image->rect.top * image->pix.bytesperline); - break; - case V4L2_PIX_FMT_RGB565: - ipu_cpmem_set_buffer(cpmem, 0, image->phys + - image->rect.left * 2 + - image->rect.top * image->pix.bytesperline); - break; - case V4L2_PIX_FMT_RGB24: - case V4L2_PIX_FMT_BGR24: - ipu_cpmem_set_buffer(cpmem, 0, image->phys + - image->rect.left * 3 + - image->rect.top * image->pix.bytesperline); - break; - default: - return -EINVAL; - } - - return 0; -} -EXPORT_SYMBOL_GPL(ipu_cpmem_set_image); - -enum ipu_color_space ipu_pixelformat_to_colorspace(u32 pixelformat) -{ - switch (pixelformat) { - case V4L2_PIX_FMT_YUV420: - case V4L2_PIX_FMT_UYVY: - case V4L2_PIX_FMT_YVYU: - return IPUV3_COLORSPACE_YUV; - case V4L2_PIX_FMT_RGB32: - case V4L2_PIX_FMT_BGR32: - case V4L2_PIX_FMT_RGB24: - case V4L2_PIX_FMT_BGR24: - case V4L2_PIX_FMT_RGB565: - return IPUV3_COLORSPACE_RGB; - default: - return IPUV3_COLORSPACE_UNKNOWN; - } -} -EXPORT_SYMBOL_GPL(ipu_pixelformat_to_colorspace); - -struct ipuv3_channel *ipu_idmac_get(struct ipu_soc *ipu, unsigned num) -{ - struct ipuv3_channel *channel; - - dev_dbg(ipu->dev, "%s %d\n", __func__, num); - - if (num > 63) - return ERR_PTR(-ENODEV); - - mutex_lock(&ipu->channel_lock); - - channel = &ipu->channel[num]; - - if (channel->busy) { - channel = ERR_PTR(-EBUSY); - goto out; - } - - channel->busy = 1; - channel->num = num; - -out: - mutex_unlock(&ipu->channel_lock); - - return channel; -} -EXPORT_SYMBOL_GPL(ipu_idmac_get); - -void ipu_idmac_put(struct ipuv3_channel *channel) -{ - struct ipu_soc *ipu = channel->ipu; - - dev_dbg(ipu->dev, "%s %d\n", __func__, channel->num); - - mutex_lock(&ipu->channel_lock); - - channel->busy = 0; - - mutex_unlock(&ipu->channel_lock); -} -EXPORT_SYMBOL_GPL(ipu_idmac_put); - -#define idma_mask(ch) (1 << (ch & 0x1f)) - -void ipu_idmac_set_double_buffer(struct ipuv3_channel *channel, - bool doublebuffer) -{ - struct ipu_soc *ipu = channel->ipu; - unsigned long flags; - u32 reg; - - spin_lock_irqsave(&ipu->lock, flags); - - reg = ipu_cm_read(ipu, IPU_CHA_DB_MODE_SEL(channel->num)); - if (doublebuffer) - reg |= idma_mask(channel->num); - else - reg &= ~idma_mask(channel->num); - ipu_cm_write(ipu, reg, IPU_CHA_DB_MODE_SEL(channel->num)); - - spin_unlock_irqrestore(&ipu->lock, flags); -} -EXPORT_SYMBOL_GPL(ipu_idmac_set_double_buffer); - -int ipu_module_enable(struct ipu_soc *ipu, u32 mask) -{ - unsigned long lock_flags; - u32 val; - - spin_lock_irqsave(&ipu->lock, lock_flags); - - val = ipu_cm_read(ipu, IPU_DISP_GEN); - - if (mask & IPU_CONF_DI0_EN) - val |= IPU_DI0_COUNTER_RELEASE; - if (mask & IPU_CONF_DI1_EN) - val |= IPU_DI1_COUNTER_RELEASE; - - ipu_cm_write(ipu, val, IPU_DISP_GEN); - - val = ipu_cm_read(ipu, IPU_CONF); - val |= mask; - ipu_cm_write(ipu, val, IPU_CONF); - - spin_unlock_irqrestore(&ipu->lock, lock_flags); - - return 0; -} -EXPORT_SYMBOL_GPL(ipu_module_enable); - -int ipu_module_disable(struct ipu_soc *ipu, u32 mask) -{ - unsigned long lock_flags; - u32 val; - - spin_lock_irqsave(&ipu->lock, lock_flags); - - val = ipu_cm_read(ipu, IPU_CONF); - val &= ~mask; - ipu_cm_write(ipu, val, IPU_CONF); - - val = ipu_cm_read(ipu, IPU_DISP_GEN); - - if (mask & IPU_CONF_DI0_EN) - val &= ~IPU_DI0_COUNTER_RELEASE; - if (mask & IPU_CONF_DI1_EN) - val &= ~IPU_DI1_COUNTER_RELEASE; - - ipu_cm_write(ipu, val, IPU_DISP_GEN); - - spin_unlock_irqrestore(&ipu->lock, lock_flags); - - return 0; -} -EXPORT_SYMBOL_GPL(ipu_module_disable); - -void ipu_idmac_select_buffer(struct ipuv3_channel *channel, u32 buf_num) -{ - struct ipu_soc *ipu = channel->ipu; - unsigned int chno = channel->num; - unsigned long flags; - - spin_lock_irqsave(&ipu->lock, flags); - - /* Mark buffer as ready. */ - if (buf_num == 0) - ipu_cm_write(ipu, idma_mask(chno), IPU_CHA_BUF0_RDY(chno)); - else - ipu_cm_write(ipu, idma_mask(chno), IPU_CHA_BUF1_RDY(chno)); - - spin_unlock_irqrestore(&ipu->lock, flags); -} -EXPORT_SYMBOL_GPL(ipu_idmac_select_buffer); - -int ipu_idmac_enable_channel(struct ipuv3_channel *channel) -{ - struct ipu_soc *ipu = channel->ipu; - u32 val; - unsigned long flags; - - spin_lock_irqsave(&ipu->lock, flags); - - val = ipu_idmac_read(ipu, IDMAC_CHA_EN(channel->num)); - val |= idma_mask(channel->num); - ipu_idmac_write(ipu, val, IDMAC_CHA_EN(channel->num)); - - spin_unlock_irqrestore(&ipu->lock, flags); - - return 0; -} -EXPORT_SYMBOL_GPL(ipu_idmac_enable_channel); - -int ipu_idmac_disable_channel(struct ipuv3_channel *channel) -{ - struct ipu_soc *ipu = channel->ipu; - u32 val; - unsigned long flags; - unsigned long timeout; - - timeout = jiffies + msecs_to_jiffies(50); - while (ipu_idmac_read(ipu, IDMAC_CHA_BUSY(channel->num)) & - idma_mask(channel->num)) { - if (time_after(jiffies, timeout)) { - dev_warn(ipu->dev, "disabling busy idmac channel %d\n", - channel->num); - break; - } - cpu_relax(); - } - - spin_lock_irqsave(&ipu->lock, flags); - - /* Disable DMA channel(s) */ - val = ipu_idmac_read(ipu, IDMAC_CHA_EN(channel->num)); - val &= ~idma_mask(channel->num); - ipu_idmac_write(ipu, val, IDMAC_CHA_EN(channel->num)); - - /* Set channel buffers NOT to be ready */ - ipu_cm_write(ipu, 0xf0000000, IPU_GPR); /* write one to clear */ - - if (ipu_cm_read(ipu, IPU_CHA_BUF0_RDY(channel->num)) & - idma_mask(channel->num)) { - ipu_cm_write(ipu, idma_mask(channel->num), - IPU_CHA_BUF0_RDY(channel->num)); - } - - if (ipu_cm_read(ipu, IPU_CHA_BUF1_RDY(channel->num)) & - idma_mask(channel->num)) { - ipu_cm_write(ipu, idma_mask(channel->num), - IPU_CHA_BUF1_RDY(channel->num)); - } - - ipu_cm_write(ipu, 0x0, IPU_GPR); /* write one to set */ - - /* Reset the double buffer */ - val = ipu_cm_read(ipu, IPU_CHA_DB_MODE_SEL(channel->num)); - val &= ~idma_mask(channel->num); - ipu_cm_write(ipu, val, IPU_CHA_DB_MODE_SEL(channel->num)); - - spin_unlock_irqrestore(&ipu->lock, flags); - - return 0; -} -EXPORT_SYMBOL_GPL(ipu_idmac_disable_channel); - -static int ipu_reset(struct ipu_soc *ipu) -{ - unsigned long timeout; - - ipu_cm_write(ipu, 0x807FFFFF, IPU_MEM_RST); - - timeout = jiffies + msecs_to_jiffies(1000); - while (ipu_cm_read(ipu, IPU_MEM_RST) & 0x80000000) { - if (time_after(jiffies, timeout)) - return -ETIME; - cpu_relax(); - } - - mdelay(300); - - return 0; -} - -struct ipu_devtype { - const char *name; - unsigned long cm_ofs; - unsigned long cpmem_ofs; - unsigned long srm_ofs; - unsigned long tpm_ofs; - unsigned long disp0_ofs; - unsigned long disp1_ofs; - unsigned long dc_tmpl_ofs; - unsigned long vdi_ofs; - enum ipuv3_type type; -}; - -static struct ipu_devtype ipu_type_imx51 = { - .name = "IPUv3EX", - .cm_ofs = 0x1e000000, - .cpmem_ofs = 0x1f000000, - .srm_ofs = 0x1f040000, - .tpm_ofs = 0x1f060000, - .disp0_ofs = 0x1e040000, - .disp1_ofs = 0x1e048000, - .dc_tmpl_ofs = 0x1f080000, - .vdi_ofs = 0x1e068000, - .type = IPUV3EX, -}; - -static struct ipu_devtype ipu_type_imx53 = { - .name = "IPUv3M", - .cm_ofs = 0x06000000, - .cpmem_ofs = 0x07000000, - .srm_ofs = 0x07040000, - .tpm_ofs = 0x07060000, - .disp0_ofs = 0x06040000, - .disp1_ofs = 0x06048000, - .dc_tmpl_ofs = 0x07080000, - .vdi_ofs = 0x06068000, - .type = IPUV3M, -}; - -static struct ipu_devtype ipu_type_imx6q = { - .name = "IPUv3H", - .cm_ofs = 0x00200000, - .cpmem_ofs = 0x00300000, - .srm_ofs = 0x00340000, - .tpm_ofs = 0x00360000, - .disp0_ofs = 0x00240000, - .disp1_ofs = 0x00248000, - .dc_tmpl_ofs = 0x00380000, - .vdi_ofs = 0x00268000, - .type = IPUV3H, -}; - -static const struct of_device_id imx_ipu_dt_ids[] = { - { .compatible = "fsl,imx51-ipu", .data = &ipu_type_imx51, }, - { .compatible = "fsl,imx53-ipu", .data = &ipu_type_imx53, }, - { .compatible = "fsl,imx6q-ipu", .data = &ipu_type_imx6q, }, - { /* sentinel */ } -}; -MODULE_DEVICE_TABLE(of, imx_ipu_dt_ids); - -static int ipu_submodules_init(struct ipu_soc *ipu, - struct platform_device *pdev, unsigned long ipu_base, - struct clk *ipu_clk) -{ - char *unit; - int ret; - struct device *dev = &pdev->dev; - const struct ipu_devtype *devtype = ipu->devtype; - - ret = ipu_di_init(ipu, dev, 0, ipu_base + devtype->disp0_ofs, - IPU_CONF_DI0_EN, ipu_clk); - if (ret) { - unit = "di0"; - goto err_di_0; - } - - ret = ipu_di_init(ipu, dev, 1, ipu_base + devtype->disp1_ofs, - IPU_CONF_DI1_EN, ipu_clk); - if (ret) { - unit = "di1"; - goto err_di_1; - } - - ret = ipu_dc_init(ipu, dev, ipu_base + devtype->cm_ofs + - IPU_CM_DC_REG_OFS, ipu_base + devtype->dc_tmpl_ofs); - if (ret) { - unit = "dc_template"; - goto err_dc; - } - - ret = ipu_dmfc_init(ipu, dev, ipu_base + - devtype->cm_ofs + IPU_CM_DMFC_REG_OFS, ipu_clk); - if (ret) { - unit = "dmfc"; - goto err_dmfc; - } - - ret = ipu_dp_init(ipu, dev, ipu_base + devtype->srm_ofs); - if (ret) { - unit = "dp"; - goto err_dp; - } - - return 0; - -err_dp: - ipu_dmfc_exit(ipu); -err_dmfc: - ipu_dc_exit(ipu); -err_dc: - ipu_di_exit(ipu, 1); -err_di_1: - ipu_di_exit(ipu, 0); -err_di_0: - dev_err(&pdev->dev, "init %s failed with %d\n", unit, ret); - return ret; -} - -static void ipu_irq_handle(struct ipu_soc *ipu, const int *regs, int num_regs) -{ - unsigned long status; - int i, bit, irq_base; - - for (i = 0; i < num_regs; i++) { - - status = ipu_cm_read(ipu, IPU_INT_STAT(regs[i])); - status &= ipu_cm_read(ipu, IPU_INT_CTRL(regs[i])); - - irq_base = ipu->irq_start + regs[i] * 32; - for_each_set_bit(bit, &status, 32) - generic_handle_irq(irq_base + bit); - } -} - -static void ipu_irq_handler(unsigned int irq, struct irq_desc *desc) -{ - struct ipu_soc *ipu = irq_desc_get_handler_data(desc); - const int int_reg[] = { 0, 1, 2, 3, 10, 11, 12, 13, 14}; - struct irq_chip *chip = irq_get_chip(irq); - - chained_irq_enter(chip, desc); - - ipu_irq_handle(ipu, int_reg, ARRAY_SIZE(int_reg)); - - chained_irq_exit(chip, desc); -} - -static void ipu_err_irq_handler(unsigned int irq, struct irq_desc *desc) -{ - struct ipu_soc *ipu = irq_desc_get_handler_data(desc); - const int int_reg[] = { 4, 5, 8, 9}; - struct irq_chip *chip = irq_get_chip(irq); - - chained_irq_enter(chip, desc); - - ipu_irq_handle(ipu, int_reg, ARRAY_SIZE(int_reg)); - - chained_irq_exit(chip, desc); -} - -static void ipu_ack_irq(struct irq_data *d) -{ - struct ipu_soc *ipu = irq_data_get_irq_chip_data(d); - unsigned int irq = d->irq - ipu->irq_start; - - ipu_cm_write(ipu, 1 << (irq % 32), IPU_INT_STAT(irq / 32)); -} - -static void ipu_unmask_irq(struct irq_data *d) -{ - struct ipu_soc *ipu = irq_data_get_irq_chip_data(d); - unsigned int irq = d->irq - ipu->irq_start; - unsigned long flags; - u32 reg; - - spin_lock_irqsave(&ipu->lock, flags); - - reg = ipu_cm_read(ipu, IPU_INT_CTRL(irq / 32)); - reg |= 1 << (irq % 32); - ipu_cm_write(ipu, reg, IPU_INT_CTRL(irq / 32)); - - spin_unlock_irqrestore(&ipu->lock, flags); -} - -static void ipu_mask_irq(struct irq_data *d) -{ - struct ipu_soc *ipu = irq_data_get_irq_chip_data(d); - unsigned int irq = d->irq - ipu->irq_start; - unsigned long flags; - u32 reg; - - spin_lock_irqsave(&ipu->lock, flags); - - reg = ipu_cm_read(ipu, IPU_INT_CTRL(irq / 32)); - reg &= ~(1 << (irq % 32)); - ipu_cm_write(ipu, reg, IPU_INT_CTRL(irq / 32)); - - spin_unlock_irqrestore(&ipu->lock, flags); -} - -static struct irq_chip ipu_irq_chip = { - .name = "IPU", - .irq_ack = ipu_ack_irq, - .irq_mask = ipu_mask_irq, - .irq_unmask = ipu_unmask_irq, -}; - -int ipu_idmac_channel_irq(struct ipu_soc *ipu, struct ipuv3_channel *channel, - enum ipu_channel_irq irq_type) -{ - return ipu->irq_start + irq_type + channel->num; -} -EXPORT_SYMBOL_GPL(ipu_idmac_channel_irq); - -static void ipu_submodules_exit(struct ipu_soc *ipu) -{ - ipu_dp_exit(ipu); - ipu_dmfc_exit(ipu); - ipu_dc_exit(ipu); - ipu_di_exit(ipu, 1); - ipu_di_exit(ipu, 0); -} - -static int platform_remove_devices_fn(struct device *dev, void *unused) -{ - struct platform_device *pdev = to_platform_device(dev); - - platform_device_unregister(pdev); - - return 0; -} - -static void platform_device_unregister_children(struct platform_device *pdev) -{ - device_for_each_child(&pdev->dev, NULL, platform_remove_devices_fn); -} - -struct ipu_platform_reg { - struct ipu_client_platformdata pdata; - const char *name; -}; - -static const struct ipu_platform_reg client_reg[] = { - { - .pdata = { - .di = 0, - .dc = 5, - .dp = IPU_DP_FLOW_SYNC_BG, - .dma[0] = IPUV3_CHANNEL_MEM_BG_SYNC, - .dma[1] = -EINVAL, - }, - .name = "imx-ipuv3-crtc", - }, { - .pdata = { - .di = 1, - .dc = 1, - .dp = -EINVAL, - .dma[0] = IPUV3_CHANNEL_MEM_DC_SYNC, - .dma[1] = -EINVAL, - }, - .name = "imx-ipuv3-crtc", - }, -}; - -static int ipu_client_id; - -static int ipu_add_subdevice_pdata(struct device *dev, - const struct ipu_platform_reg *reg) -{ - struct platform_device *pdev; - - pdev = platform_device_register_data(dev, reg->name, ipu_client_id++, - ®->pdata, sizeof(struct ipu_platform_reg)); - - return pdev ? 0 : -EINVAL; -} - -static int ipu_add_client_devices(struct ipu_soc *ipu) -{ - int ret; - int i; - - for (i = 0; i < ARRAY_SIZE(client_reg); i++) { - const struct ipu_platform_reg *reg = &client_reg[i]; - ret = ipu_add_subdevice_pdata(ipu->dev, reg); - if (ret) - goto err_register; - } - - return 0; - -err_register: - platform_device_unregister_children(to_platform_device(ipu->dev)); - - return ret; -} - -static int ipu_irq_init(struct ipu_soc *ipu) -{ - int i; - - ipu->irq_start = irq_alloc_descs(-1, 0, IPU_NUM_IRQS, 0); - if (ipu->irq_start < 0) - return ipu->irq_start; - - for (i = ipu->irq_start; i < ipu->irq_start + IPU_NUM_IRQS; i++) { - irq_set_chip_and_handler(i, &ipu_irq_chip, handle_level_irq); - set_irq_flags(i, IRQF_VALID); - irq_set_chip_data(i, ipu); - } - - irq_set_chained_handler(ipu->irq_sync, ipu_irq_handler); - irq_set_handler_data(ipu->irq_sync, ipu); - irq_set_chained_handler(ipu->irq_err, ipu_err_irq_handler); - irq_set_handler_data(ipu->irq_err, ipu); - - return 0; -} - -static void ipu_irq_exit(struct ipu_soc *ipu) -{ - int i; - - irq_set_chained_handler(ipu->irq_err, NULL); - irq_set_handler_data(ipu->irq_err, NULL); - irq_set_chained_handler(ipu->irq_sync, NULL); - irq_set_handler_data(ipu->irq_sync, NULL); - - for (i = ipu->irq_start; i < ipu->irq_start + IPU_NUM_IRQS; i++) { - set_irq_flags(i, 0); - irq_set_chip(i, NULL); - irq_set_chip_data(i, NULL); - } - - irq_free_descs(ipu->irq_start, IPU_NUM_IRQS); -} - -static int __devinit ipu_probe(struct platform_device *pdev) -{ - const struct of_device_id *of_id = - of_match_device(imx_ipu_dt_ids, &pdev->dev); - struct ipu_soc *ipu; - struct resource *res; - unsigned long ipu_base; - int i, ret, irq_sync, irq_err; - const struct ipu_devtype *devtype; - - devtype = of_id->data; - - dev_info(&pdev->dev, "Initializing %s\n", devtype->name); - - irq_sync = platform_get_irq(pdev, 0); - irq_err = platform_get_irq(pdev, 1); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - - dev_info(&pdev->dev, "irq_sync: %d irq_err: %d\n", - irq_sync, irq_err); - - if (!res || irq_sync < 0 || irq_err < 0) - return -ENODEV; - - ipu_base = res->start; - - ipu = devm_kzalloc(&pdev->dev, sizeof(*ipu), GFP_KERNEL); - if (!ipu) - return -ENODEV; - - for (i = 0; i < 64; i++) - ipu->channel[i].ipu = ipu; - ipu->devtype = devtype; - ipu->ipu_type = devtype->type; - - spin_lock_init(&ipu->lock); - mutex_init(&ipu->channel_lock); - - dev_info(&pdev->dev, "cm_reg: 0x%08lx\n", - ipu_base + devtype->cm_ofs); - dev_info(&pdev->dev, "idmac: 0x%08lx\n", - ipu_base + devtype->cm_ofs + IPU_CM_IDMAC_REG_OFS); - dev_info(&pdev->dev, "cpmem: 0x%08lx\n", - ipu_base + devtype->cpmem_ofs); - dev_info(&pdev->dev, "disp0: 0x%08lx\n", - ipu_base + devtype->disp0_ofs); - dev_info(&pdev->dev, "disp1: 0x%08lx\n", - ipu_base + devtype->disp1_ofs); - dev_info(&pdev->dev, "srm: 0x%08lx\n", - ipu_base + devtype->srm_ofs); - dev_info(&pdev->dev, "tpm: 0x%08lx\n", - ipu_base + devtype->tpm_ofs); - dev_info(&pdev->dev, "dc: 0x%08lx\n", - ipu_base + devtype->cm_ofs + IPU_CM_DC_REG_OFS); - dev_info(&pdev->dev, "ic: 0x%08lx\n", - ipu_base + devtype->cm_ofs + IPU_CM_IC_REG_OFS); - dev_info(&pdev->dev, "dmfc: 0x%08lx\n", - ipu_base + devtype->cm_ofs + IPU_CM_DMFC_REG_OFS); - dev_info(&pdev->dev, "vdi: 0x%08lx\n", - ipu_base + devtype->vdi_ofs); - - ipu->cm_reg = devm_ioremap(&pdev->dev, - ipu_base + devtype->cm_ofs, PAGE_SIZE); - ipu->idmac_reg = devm_ioremap(&pdev->dev, - ipu_base + devtype->cm_ofs + IPU_CM_IDMAC_REG_OFS, - PAGE_SIZE); - ipu->cpmem_base = devm_ioremap(&pdev->dev, - ipu_base + devtype->cpmem_ofs, PAGE_SIZE); - - if (!ipu->cm_reg || !ipu->idmac_reg || !ipu->cpmem_base) { - ret = -ENOMEM; - goto failed_ioremap; - } - - ipu->clk = devm_clk_get(&pdev->dev, "bus"); - if (IS_ERR(ipu->clk)) { - ret = PTR_ERR(ipu->clk); - dev_err(&pdev->dev, "clk_get failed with %d", ret); - goto failed_clk_get; - } - - platform_set_drvdata(pdev, ipu); - - clk_prepare_enable(ipu->clk); - - ipu->dev = &pdev->dev; - ipu->irq_sync = irq_sync; - ipu->irq_err = irq_err; - - ret = ipu_irq_init(ipu); - if (ret) - goto out_failed_irq; - - ipu_reset(ipu); - - /* Set MCU_T to divide MCU access window into 2 */ - ipu_cm_write(ipu, 0x00400000L | (IPU_MCU_T_DEFAULT << 18), - IPU_DISP_GEN); - - ret = ipu_submodules_init(ipu, pdev, ipu_base, ipu->clk); - if (ret) - goto failed_submodules_init; - - ret = ipu_add_client_devices(ipu); - if (ret) { - dev_err(&pdev->dev, "adding client devices failed with %d\n", - ret); - goto failed_add_clients; - } - - return 0; - -failed_add_clients: - ipu_submodules_exit(ipu); -failed_submodules_init: - ipu_irq_exit(ipu); -out_failed_irq: - clk_disable_unprepare(ipu->clk); -failed_clk_get: -failed_ioremap: - return ret; -} - -static int __devexit ipu_remove(struct platform_device *pdev) -{ - struct ipu_soc *ipu = platform_get_drvdata(pdev); - struct resource *res; - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - - platform_device_unregister_children(pdev); - ipu_submodules_exit(ipu); - ipu_irq_exit(ipu); - - clk_disable_unprepare(ipu->clk); - - return 0; -} - -static struct platform_driver imx_ipu_driver = { - .driver = { - .name = "imx-ipuv3", - .of_match_table = imx_ipu_dt_ids, - }, - .probe = ipu_probe, - .remove = __devexit_p(ipu_remove), -}; - -module_platform_driver(imx_ipu_driver); - -MODULE_DESCRIPTION("i.MX IPU v3 driver"); -MODULE_AUTHOR("Sascha Hauer "); -MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/staging/imx-drm/ipu-v3/ipu-dc.c b/trunk/drivers/staging/imx-drm/ipu-v3/ipu-dc.c deleted file mode 100644 index 93c7579417be..000000000000 --- a/trunk/drivers/staging/imx-drm/ipu-v3/ipu-dc.c +++ /dev/null @@ -1,372 +0,0 @@ -/* - * Copyright (c) 2010 Sascha Hauer - * Copyright (C) 2005-2009 Freescale Semiconductor, Inc. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * 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. - */ - -#include -#include -#include -#include -#include -#include - -#include "imx-ipu-v3.h" -#include "ipu-prv.h" - -#define DC_MAP_CONF_PTR(n) (0x108 + ((n) & ~0x1) * 2) -#define DC_MAP_CONF_VAL(n) (0x144 + ((n) & ~0x1) * 2) - -#define DC_EVT_NF 0 -#define DC_EVT_NL 1 -#define DC_EVT_EOF 2 -#define DC_EVT_NFIELD 3 -#define DC_EVT_EOL 4 -#define DC_EVT_EOFIELD 5 -#define DC_EVT_NEW_ADDR 6 -#define DC_EVT_NEW_CHAN 7 -#define DC_EVT_NEW_DATA 8 - -#define DC_EVT_NEW_ADDR_W_0 0 -#define DC_EVT_NEW_ADDR_W_1 1 -#define DC_EVT_NEW_CHAN_W_0 2 -#define DC_EVT_NEW_CHAN_W_1 3 -#define DC_EVT_NEW_DATA_W_0 4 -#define DC_EVT_NEW_DATA_W_1 5 -#define DC_EVT_NEW_ADDR_R_0 6 -#define DC_EVT_NEW_ADDR_R_1 7 -#define DC_EVT_NEW_CHAN_R_0 8 -#define DC_EVT_NEW_CHAN_R_1 9 -#define DC_EVT_NEW_DATA_R_0 10 -#define DC_EVT_NEW_DATA_R_1 11 - -#define DC_WR_CH_CONF 0x0 -#define DC_WR_CH_ADDR 0x4 -#define DC_RL_CH(evt) (8 + ((evt) & ~0x1) * 2) - -#define DC_GEN 0xd4 -#define DC_DISP_CONF1(disp) (0xd8 + (disp) * 4) -#define DC_DISP_CONF2(disp) (0xe8 + (disp) * 4) -#define DC_STAT 0x1c8 - -#define WROD(lf) (0x18 | ((lf) << 1)) -#define WRG 0x01 - -#define SYNC_WAVE 0 - -#define DC_GEN_SYNC_1_6_SYNC (2 << 1) -#define DC_GEN_SYNC_PRIORITY_1 (1 << 7) - -#define DC_WR_CH_CONF_WORD_SIZE_8 (0 << 0) -#define DC_WR_CH_CONF_WORD_SIZE_16 (1 << 0) -#define DC_WR_CH_CONF_WORD_SIZE_24 (2 << 0) -#define DC_WR_CH_CONF_WORD_SIZE_32 (3 << 0) -#define DC_WR_CH_CONF_DISP_ID_PARALLEL(i) (((i) & 0x1) << 3) -#define DC_WR_CH_CONF_DISP_ID_SERIAL (2 << 3) -#define DC_WR_CH_CONF_DISP_ID_ASYNC (3 << 4) -#define DC_WR_CH_CONF_FIELD_MODE (1 << 9) -#define DC_WR_CH_CONF_PROG_TYPE_NORMAL (4 << 5) -#define DC_WR_CH_CONF_PROG_TYPE_MASK (7 << 5) -#define DC_WR_CH_CONF_PROG_DI_ID (1 << 2) -#define DC_WR_CH_CONF_PROG_DISP_ID(i) (((i) & 0x1) << 3) - -#define IPU_DC_NUM_CHANNELS 10 - -struct ipu_dc_priv; - -enum ipu_dc_map { - IPU_DC_MAP_RGB24, - IPU_DC_MAP_RGB565, -}; - -struct ipu_dc { - /* The display interface number assigned to this dc channel */ - unsigned int di; - void __iomem *base; - struct ipu_dc_priv *priv; - int chno; - bool in_use; -}; - -struct ipu_dc_priv { - void __iomem *dc_reg; - void __iomem *dc_tmpl_reg; - struct ipu_soc *ipu; - struct device *dev; - struct ipu_dc channels[IPU_DC_NUM_CHANNELS]; - struct mutex mutex; -}; - -static void dc_link_event(struct ipu_dc *dc, int event, int addr, int priority) -{ - u32 reg; - - reg = readl(dc->base + DC_RL_CH(event)); - reg &= ~(0xffff << (16 * (event & 0x1))); - reg |= ((addr << 8) | priority) << (16 * (event & 0x1)); - writel(reg, dc->base + DC_RL_CH(event)); -} - -static void dc_write_tmpl(struct ipu_dc *dc, int word, u32 opcode, u32 operand, - int map, int wave, int glue, int sync) -{ - struct ipu_dc_priv *priv = dc->priv; - u32 reg; - int stop = 1; - - reg = sync | glue << 4 | ++wave << 11 | ++map << 15 | ((operand << 20) & 0xfff00000); - writel(reg, priv->dc_tmpl_reg + word * 8); - reg = operand >> 12 | opcode << 4 | stop << 9; - writel(reg, priv->dc_tmpl_reg + word * 8 + 4); -} - -static int ipu_pixfmt_to_map(u32 fmt) -{ - switch (fmt) { - case V4L2_PIX_FMT_RGB24: - return IPU_DC_MAP_RGB24; - case V4L2_PIX_FMT_RGB565: - return IPU_DC_MAP_RGB565; - default: - return -EINVAL; - } -} - -int ipu_dc_init_sync(struct ipu_dc *dc, struct ipu_di *di, bool interlaced, - u32 pixel_fmt, u32 width) -{ - struct ipu_dc_priv *priv = dc->priv; - u32 reg = 0, map; - - dc->di = ipu_di_get_num(di); - - map = ipu_pixfmt_to_map(pixel_fmt); - if (map < 0) { - dev_dbg(priv->dev, "IPU_DISP: No MAP\n"); - return -EINVAL; - } - - if (interlaced) { - dc_link_event(dc, DC_EVT_NL, 0, 3); - dc_link_event(dc, DC_EVT_EOL, 0, 2); - dc_link_event(dc, DC_EVT_NEW_DATA, 0, 1); - - /* Init template microcode */ - dc_write_tmpl(dc, 0, WROD(0), 0, map, SYNC_WAVE, 0, 8); - } else { - if (dc->di) { - dc_link_event(dc, DC_EVT_NL, 2, 3); - dc_link_event(dc, DC_EVT_EOL, 3, 2); - dc_link_event(dc, DC_EVT_NEW_DATA, 4, 1); - /* Init template microcode */ - dc_write_tmpl(dc, 2, WROD(0), 0, map, SYNC_WAVE, 8, 5); - dc_write_tmpl(dc, 3, WROD(0), 0, map, SYNC_WAVE, 4, 5); - dc_write_tmpl(dc, 4, WROD(0), 0, map, SYNC_WAVE, 0, 5); - } else { - dc_link_event(dc, DC_EVT_NL, 5, 3); - dc_link_event(dc, DC_EVT_EOL, 6, 2); - dc_link_event(dc, DC_EVT_NEW_DATA, 7, 1); - /* Init template microcode */ - dc_write_tmpl(dc, 5, WROD(0), 0, map, SYNC_WAVE, 8, 5); - dc_write_tmpl(dc, 6, WROD(0), 0, map, SYNC_WAVE, 4, 5); - dc_write_tmpl(dc, 7, WROD(0), 0, map, SYNC_WAVE, 0, 5); - } - } - dc_link_event(dc, DC_EVT_NF, 0, 0); - dc_link_event(dc, DC_EVT_NFIELD, 0, 0); - dc_link_event(dc, DC_EVT_EOF, 0, 0); - dc_link_event(dc, DC_EVT_EOFIELD, 0, 0); - dc_link_event(dc, DC_EVT_NEW_CHAN, 0, 0); - dc_link_event(dc, DC_EVT_NEW_ADDR, 0, 0); - - reg = readl(dc->base + DC_WR_CH_CONF); - if (interlaced) - reg |= DC_WR_CH_CONF_FIELD_MODE; - else - reg &= ~DC_WR_CH_CONF_FIELD_MODE; - writel(reg, dc->base + DC_WR_CH_CONF); - - writel(0x0, dc->base + DC_WR_CH_ADDR); - writel(width, priv->dc_reg + DC_DISP_CONF2(dc->di)); - - ipu_module_enable(priv->ipu, IPU_CONF_DC_EN); - - return 0; -} -EXPORT_SYMBOL_GPL(ipu_dc_init_sync); - -void ipu_dc_enable_channel(struct ipu_dc *dc) -{ - int di; - u32 reg; - - di = dc->di; - - reg = readl(dc->base + DC_WR_CH_CONF); - reg |= DC_WR_CH_CONF_PROG_TYPE_NORMAL; - writel(reg, dc->base + DC_WR_CH_CONF); -} -EXPORT_SYMBOL_GPL(ipu_dc_enable_channel); - -void ipu_dc_disable_channel(struct ipu_dc *dc) -{ - struct ipu_dc_priv *priv = dc->priv; - u32 val; - int irq = 0, timeout = 50; - - if (dc->chno == 1) - irq = IPU_IRQ_DC_FC_1; - else if (dc->chno == 5) - irq = IPU_IRQ_DP_SF_END; - else - return; - - /* should wait for the interrupt here */ - mdelay(50); - - if (dc->di == 0) - val = 0x00000002; - else - val = 0x00000020; - - /* Wait for DC triple buffer to empty */ - while ((readl(priv->dc_reg + DC_STAT) & val) != val) { - msleep(2); - timeout -= 2; - if (timeout <= 0) - break; - } - - val = readl(dc->base + DC_WR_CH_CONF); - val &= ~DC_WR_CH_CONF_PROG_TYPE_MASK; - writel(val, dc->base + DC_WR_CH_CONF); -} -EXPORT_SYMBOL_GPL(ipu_dc_disable_channel); - -static void ipu_dc_map_config(struct ipu_dc_priv *priv, enum ipu_dc_map map, - int byte_num, int offset, int mask) -{ - int ptr = map * 3 + byte_num; - u32 reg; - - reg = readl(priv->dc_reg + DC_MAP_CONF_VAL(ptr)); - reg &= ~(0xffff << (16 * (ptr & 0x1))); - reg |= ((offset << 8) | mask) << (16 * (ptr & 0x1)); - writel(reg, priv->dc_reg + DC_MAP_CONF_VAL(ptr)); - - reg = readl(priv->dc_reg + DC_MAP_CONF_PTR(map)); - reg &= ~(0x1f << ((16 * (map & 0x1)) + (5 * byte_num))); - reg |= ptr << ((16 * (map & 0x1)) + (5 * byte_num)); - writel(reg, priv->dc_reg + DC_MAP_CONF_PTR(map)); -} - -static void ipu_dc_map_clear(struct ipu_dc_priv *priv, int map) -{ - u32 reg = readl(priv->dc_reg + DC_MAP_CONF_PTR(map)); - - writel(reg & ~(0xffff << (16 * (map & 0x1))), - priv->dc_reg + DC_MAP_CONF_PTR(map)); -} - -struct ipu_dc *ipu_dc_get(struct ipu_soc *ipu, int channel) -{ - struct ipu_dc_priv *priv = ipu->dc_priv; - struct ipu_dc *dc; - - if (channel >= IPU_DC_NUM_CHANNELS) - return ERR_PTR(-ENODEV); - - dc = &priv->channels[channel]; - - mutex_lock(&priv->mutex); - - if (dc->in_use) { - mutex_unlock(&priv->mutex); - return ERR_PTR(-EBUSY); - } - - dc->in_use = 1; - - mutex_unlock(&priv->mutex); - - return dc; -} -EXPORT_SYMBOL_GPL(ipu_dc_get); - -void ipu_dc_put(struct ipu_dc *dc) -{ - struct ipu_dc_priv *priv = dc->priv; - - mutex_lock(&priv->mutex); - dc->in_use = 0; - mutex_unlock(&priv->mutex); -} -EXPORT_SYMBOL_GPL(ipu_dc_put); - -int ipu_dc_init(struct ipu_soc *ipu, struct device *dev, - unsigned long base, unsigned long template_base) -{ - struct ipu_dc_priv *priv; - static int channel_offsets[] = { 0, 0x1c, 0x38, 0x54, 0x58, 0x5c, - 0x78, 0, 0x94, 0xb4}; - int i; - - priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); - if (!priv) - return -ENOMEM; - - mutex_init(&priv->mutex); - - priv->dev = dev; - priv->ipu = ipu; - priv->dc_reg = devm_ioremap(dev, base, PAGE_SIZE); - priv->dc_tmpl_reg = devm_ioremap(dev, template_base, PAGE_SIZE); - if (!priv->dc_reg || !priv->dc_tmpl_reg) - return -ENOMEM; - - for (i = 0; i < IPU_DC_NUM_CHANNELS; i++) { - priv->channels[i].chno = i; - priv->channels[i].priv = priv; - priv->channels[i].base = priv->dc_reg + channel_offsets[i]; - } - - writel(DC_WR_CH_CONF_WORD_SIZE_24 | DC_WR_CH_CONF_DISP_ID_PARALLEL(1) | - DC_WR_CH_CONF_PROG_DI_ID, - priv->channels[1].base + DC_WR_CH_CONF); - writel(DC_WR_CH_CONF_WORD_SIZE_24 | DC_WR_CH_CONF_DISP_ID_PARALLEL(0), - priv->channels[5].base + DC_WR_CH_CONF); - - writel(DC_GEN_SYNC_1_6_SYNC | DC_GEN_SYNC_PRIORITY_1, priv->dc_reg + DC_GEN); - - ipu->dc_priv = priv; - - dev_dbg(dev, "DC base: 0x%08lx template base: 0x%08lx\n", - base, template_base); - - /* rgb24 */ - ipu_dc_map_clear(priv, IPU_DC_MAP_RGB24); - ipu_dc_map_config(priv, IPU_DC_MAP_RGB24, 0, 7, 0xff); /* blue */ - ipu_dc_map_config(priv, IPU_DC_MAP_RGB24, 1, 15, 0xff); /* green */ - ipu_dc_map_config(priv, IPU_DC_MAP_RGB24, 2, 23, 0xff); /* red */ - - /* rgb565 */ - ipu_dc_map_clear(priv, IPU_DC_MAP_RGB565); - ipu_dc_map_config(priv, IPU_DC_MAP_RGB565, 0, 4, 0xf8); /* blue */ - ipu_dc_map_config(priv, IPU_DC_MAP_RGB565, 1, 10, 0xfc); /* green */ - ipu_dc_map_config(priv, IPU_DC_MAP_RGB565, 2, 15, 0xf8); /* red */ - - return 0; -} - -void ipu_dc_exit(struct ipu_soc *ipu) -{ -} diff --git a/trunk/drivers/staging/imx-drm/ipu-v3/ipu-di.c b/trunk/drivers/staging/imx-drm/ipu-v3/ipu-di.c deleted file mode 100644 index 67d974f7be36..000000000000 --- a/trunk/drivers/staging/imx-drm/ipu-v3/ipu-di.c +++ /dev/null @@ -1,700 +0,0 @@ -/* - * Copyright (c) 2010 Sascha Hauer - * Copyright (C) 2005-2009 Freescale Semiconductor, Inc. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * 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. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "imx-ipu-v3.h" -#include "ipu-prv.h" - -struct ipu_di { - void __iomem *base; - int id; - u32 module; - struct clk *clk_di; /* display input clock */ - struct clk *clk_ipu; /* IPU bus clock */ - struct clk *clk_di_pixel; /* resulting pixel clock */ - struct clk_hw clk_hw_out; - char *clk_name; - bool inuse; - unsigned long clkflags; - struct ipu_soc *ipu; -}; - -static DEFINE_MUTEX(di_mutex); - -struct di_sync_config { - int run_count; - int run_src; - int offset_count; - int offset_src; - int repeat_count; - int cnt_clr_src; - int cnt_polarity_gen_en; - int cnt_polarity_clr_src; - int cnt_polarity_trigger_src; - int cnt_up; - int cnt_down; -}; - -enum di_pins { - DI_PIN11 = 0, - DI_PIN12 = 1, - DI_PIN13 = 2, - DI_PIN14 = 3, - DI_PIN15 = 4, - DI_PIN16 = 5, - DI_PIN17 = 6, - DI_PIN_CS = 7, - - DI_PIN_SER_CLK = 0, - DI_PIN_SER_RS = 1, -}; - -enum di_sync_wave { - DI_SYNC_NONE = 0, - DI_SYNC_CLK = 1, - DI_SYNC_INT_HSYNC = 2, - DI_SYNC_HSYNC = 3, - DI_SYNC_VSYNC = 4, - DI_SYNC_DE = 6, -}; - -#define SYNC_WAVE 0 - -#define DI_GENERAL 0x0000 -#define DI_BS_CLKGEN0 0x0004 -#define DI_BS_CLKGEN1 0x0008 -#define DI_SW_GEN0(gen) (0x000c + 4 * ((gen) - 1)) -#define DI_SW_GEN1(gen) (0x0030 + 4 * ((gen) - 1)) -#define DI_STP_REP(gen) (0x0148 + 4 * (((gen) - 1)/2)) -#define DI_SYNC_AS_GEN 0x0054 -#define DI_DW_GEN(gen) (0x0058 + 4 * (gen)) -#define DI_DW_SET(gen, set) (0x0088 + 4 * ((gen) + 0xc * (set))) -#define DI_SER_CONF 0x015c -#define DI_SSC 0x0160 -#define DI_POL 0x0164 -#define DI_AW0 0x0168 -#define DI_AW1 0x016c -#define DI_SCR_CONF 0x0170 -#define DI_STAT 0x0174 - -#define DI_SW_GEN0_RUN_COUNT(x) ((x) << 19) -#define DI_SW_GEN0_RUN_SRC(x) ((x) << 16) -#define DI_SW_GEN0_OFFSET_COUNT(x) ((x) << 3) -#define DI_SW_GEN0_OFFSET_SRC(x) ((x) << 0) - -#define DI_SW_GEN1_CNT_POL_GEN_EN(x) ((x) << 29) -#define DI_SW_GEN1_CNT_CLR_SRC(x) ((x) << 25) -#define DI_SW_GEN1_CNT_POL_TRIGGER_SRC(x) ((x) << 12) -#define DI_SW_GEN1_CNT_POL_CLR_SRC(x) ((x) << 9) -#define DI_SW_GEN1_CNT_DOWN(x) ((x) << 16) -#define DI_SW_GEN1_CNT_UP(x) (x) -#define DI_SW_GEN1_AUTO_RELOAD (0x10000000) - -#define DI_DW_GEN_ACCESS_SIZE_OFFSET 24 -#define DI_DW_GEN_COMPONENT_SIZE_OFFSET 16 - -#define DI_GEN_POLARITY_1 (1 << 0) -#define DI_GEN_POLARITY_2 (1 << 1) -#define DI_GEN_POLARITY_3 (1 << 2) -#define DI_GEN_POLARITY_4 (1 << 3) -#define DI_GEN_POLARITY_5 (1 << 4) -#define DI_GEN_POLARITY_6 (1 << 5) -#define DI_GEN_POLARITY_7 (1 << 6) -#define DI_GEN_POLARITY_8 (1 << 7) -#define DI_GEN_POLARITY_DISP_CLK (1 << 17) -#define DI_GEN_DI_CLK_EXT (1 << 20) -#define DI_GEN_DI_VSYNC_EXT (1 << 21) - -#define DI_POL_DRDY_DATA_POLARITY (1 << 7) -#define DI_POL_DRDY_POLARITY_15 (1 << 4) - -#define DI_VSYNC_SEL_OFFSET 13 - -static inline u32 ipu_di_read(struct ipu_di *di, unsigned offset) -{ - return readl(di->base + offset); -} - -static inline void ipu_di_write(struct ipu_di *di, u32 value, unsigned offset) -{ - writel(value, di->base + offset); -} - -static int ipu_di_clk_calc_div(unsigned long inrate, unsigned long outrate) -{ - u64 tmp = inrate; - int div; - - tmp *= 16; - - do_div(tmp, outrate); - - div = tmp; - - if (div < 0x10) - div = 0x10; - -#ifdef WTF_IS_THIS - /* - * Freescale has this in their Kernel. It is neither clear what - * it does nor why it does it - */ - if (div & 0x10) - div &= ~0x7; - else { - /* Round up divider if it gets us closer to desired pix clk */ - if ((div & 0xC) == 0xC) { - div += 0x10; - div &= ~0xF; - } - } -#endif - return div; -} - -static unsigned long clk_di_recalc_rate(struct clk_hw *hw, - unsigned long parent_rate) -{ - struct ipu_di *di = container_of(hw, struct ipu_di, clk_hw_out); - unsigned long outrate; - u32 div = ipu_di_read(di, DI_BS_CLKGEN0); - - if (div < 0x10) - div = 0x10; - - outrate = (parent_rate / div) * 16; - - return outrate; -} - -static long clk_di_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *prate) -{ - struct ipu_di *di = container_of(hw, struct ipu_di, clk_hw_out); - unsigned long outrate; - int div; - u32 val; - - div = ipu_di_clk_calc_div(*prate, rate); - - outrate = (*prate / div) * 16; - - val = ipu_di_read(di, DI_GENERAL); - - if (!(val & DI_GEN_DI_CLK_EXT) && outrate > *prate / 2) - outrate = *prate / 2; - - dev_dbg(di->ipu->dev, - "%s: inrate: %ld div: 0x%08x outrate: %ld wanted: %ld\n", - __func__, *prate, div, outrate, rate); - - return outrate; -} - -static int clk_di_set_rate(struct clk_hw *hw, unsigned long rate, - unsigned long parent_rate) -{ - struct ipu_di *di = container_of(hw, struct ipu_di, clk_hw_out); - int div; - u32 clkgen0; - - clkgen0 = ipu_di_read(di, DI_BS_CLKGEN0) & ~0xfff; - - div = ipu_di_clk_calc_div(parent_rate, rate); - - ipu_di_write(di, clkgen0 | div, DI_BS_CLKGEN0); - - dev_dbg(di->ipu->dev, "%s: inrate: %ld desired: %ld div: 0x%08x\n", - __func__, parent_rate, rate, div); - return 0; -} - -static u8 clk_di_get_parent(struct clk_hw *hw) -{ - struct ipu_di *di = container_of(hw, struct ipu_di, clk_hw_out); - u32 val; - - val = ipu_di_read(di, DI_GENERAL); - - return val & DI_GEN_DI_CLK_EXT ? 1 : 0; -} - -static int clk_di_set_parent(struct clk_hw *hw, u8 index) -{ - struct ipu_di *di = container_of(hw, struct ipu_di, clk_hw_out); - u32 val; - - val = ipu_di_read(di, DI_GENERAL); - - if (index) - val |= DI_GEN_DI_CLK_EXT; - else - val &= ~DI_GEN_DI_CLK_EXT; - - ipu_di_write(di, val, DI_GENERAL); - - return 0; -} - -static struct clk_ops clk_di_ops = { - .round_rate = clk_di_round_rate, - .set_rate = clk_di_set_rate, - .recalc_rate = clk_di_recalc_rate, - .set_parent = clk_di_set_parent, - .get_parent = clk_di_get_parent, -}; - -static void ipu_di_data_wave_config(struct ipu_di *di, - int wave_gen, - int access_size, int component_size) -{ - u32 reg; - reg = (access_size << DI_DW_GEN_ACCESS_SIZE_OFFSET) | - (component_size << DI_DW_GEN_COMPONENT_SIZE_OFFSET); - ipu_di_write(di, reg, DI_DW_GEN(wave_gen)); -} - -static void ipu_di_data_pin_config(struct ipu_di *di, int wave_gen, int di_pin, - int set, int up, int down) -{ - u32 reg; - - reg = ipu_di_read(di, DI_DW_GEN(wave_gen)); - reg &= ~(0x3 << (di_pin * 2)); - reg |= set << (di_pin * 2); - ipu_di_write(di, reg, DI_DW_GEN(wave_gen)); - - ipu_di_write(di, (down << 16) | up, DI_DW_SET(wave_gen, set)); -} - -static void ipu_di_sync_config(struct ipu_di *di, struct di_sync_config *config, - int start, int count) -{ - u32 reg; - int i; - - for (i = 0; i < count; i++) { - struct di_sync_config *c = &config[i]; - int wave_gen = start + i + 1; - - if ((c->run_count >= 0x1000) || (c->offset_count >= 0x1000) || - (c->repeat_count >= 0x1000) || - (c->cnt_up >= 0x400) || - (c->cnt_down >= 0x400)) { - dev_err(di->ipu->dev, "DI%d counters out of range.\n", - di->id); - return; - } - - reg = DI_SW_GEN0_RUN_COUNT(c->run_count) | - DI_SW_GEN0_RUN_SRC(c->run_src) | - DI_SW_GEN0_OFFSET_COUNT(c->offset_count) | - DI_SW_GEN0_OFFSET_SRC(c->offset_src); - ipu_di_write(di, reg, DI_SW_GEN0(wave_gen)); - - reg = DI_SW_GEN1_CNT_POL_GEN_EN(c->cnt_polarity_gen_en) | - DI_SW_GEN1_CNT_CLR_SRC(c->cnt_clr_src) | - DI_SW_GEN1_CNT_POL_TRIGGER_SRC( - c->cnt_polarity_trigger_src) | - DI_SW_GEN1_CNT_POL_CLR_SRC(c->cnt_polarity_clr_src) | - DI_SW_GEN1_CNT_DOWN(c->cnt_down) | - DI_SW_GEN1_CNT_UP(c->cnt_up); - - /* Enable auto reload */ - if (c->repeat_count == 0) - reg |= DI_SW_GEN1_AUTO_RELOAD; - - ipu_di_write(di, reg, DI_SW_GEN1(wave_gen)); - - reg = ipu_di_read(di, DI_STP_REP(wave_gen)); - reg &= ~(0xffff << (16 * ((wave_gen - 1) & 0x1))); - reg |= c->repeat_count << (16 * ((wave_gen - 1) & 0x1)); - ipu_di_write(di, reg, DI_STP_REP(wave_gen)); - } -} - -static void ipu_di_sync_config_interlaced(struct ipu_di *di, - struct ipu_di_signal_cfg *sig) -{ - u32 h_total = sig->width + sig->h_sync_width + - sig->h_start_width + sig->h_end_width; - u32 v_total = sig->height + sig->v_sync_width + - sig->v_start_width + sig->v_end_width; - u32 reg; - struct di_sync_config cfg[] = { - { - .run_count = h_total / 2 - 1, - .run_src = DI_SYNC_CLK, - }, { - .run_count = h_total - 11, - .run_src = DI_SYNC_CLK, - .cnt_down = 4, - }, { - .run_count = v_total * 2 - 1, - .run_src = DI_SYNC_INT_HSYNC, - .offset_count = 1, - .offset_src = DI_SYNC_INT_HSYNC, - .cnt_down = 4, - }, { - .run_count = v_total / 2 - 1, - .run_src = DI_SYNC_HSYNC, - .offset_count = sig->v_start_width, - .offset_src = DI_SYNC_HSYNC, - .repeat_count = 2, - .cnt_clr_src = DI_SYNC_VSYNC, - }, { - .run_src = DI_SYNC_HSYNC, - .repeat_count = sig->height / 2, - .cnt_clr_src = 4, - }, { - .run_count = v_total - 1, - .run_src = DI_SYNC_HSYNC, - }, { - .run_count = v_total / 2 - 1, - .run_src = DI_SYNC_HSYNC, - .offset_count = 9, - .offset_src = DI_SYNC_HSYNC, - .repeat_count = 2, - .cnt_clr_src = DI_SYNC_VSYNC, - }, { - .run_src = DI_SYNC_CLK, - .offset_count = sig->h_start_width, - .offset_src = DI_SYNC_CLK, - .repeat_count = sig->width, - .cnt_clr_src = 5, - }, { - .run_count = v_total - 1, - .run_src = DI_SYNC_INT_HSYNC, - .offset_count = v_total / 2, - .offset_src = DI_SYNC_INT_HSYNC, - .cnt_clr_src = DI_SYNC_HSYNC, - .cnt_down = 4, - } - }; - - ipu_di_sync_config(di, cfg, 0, ARRAY_SIZE(cfg)); - - /* set gentime select and tag sel */ - reg = ipu_di_read(di, DI_SW_GEN1(9)); - reg &= 0x1FFFFFFF; - reg |= (3 - 1) << 29 | 0x00008000; - ipu_di_write(di, reg, DI_SW_GEN1(9)); - - ipu_di_write(di, v_total / 2 - 1, DI_SCR_CONF); -} - -static void ipu_di_sync_config_noninterlaced(struct ipu_di *di, - struct ipu_di_signal_cfg *sig, int div) -{ - u32 h_total = sig->width + sig->h_sync_width + sig->h_start_width + - sig->h_end_width; - u32 v_total = sig->height + sig->v_sync_width + sig->v_start_width + - sig->v_end_width; - struct di_sync_config cfg[] = { - { - .run_count = h_total - 1, - .run_src = DI_SYNC_CLK, - } , { - .run_count = h_total - 1, - .run_src = DI_SYNC_CLK, - .offset_count = div * sig->v_to_h_sync, - .offset_src = DI_SYNC_CLK, - .cnt_polarity_gen_en = 1, - .cnt_polarity_trigger_src = DI_SYNC_CLK, - .cnt_down = sig->h_sync_width * 2, - } , { - .run_count = v_total - 1, - .run_src = DI_SYNC_INT_HSYNC, - .cnt_polarity_gen_en = 1, - .cnt_polarity_trigger_src = DI_SYNC_INT_HSYNC, - .cnt_down = sig->v_sync_width * 2, - } , { - .run_src = DI_SYNC_HSYNC, - .offset_count = sig->v_sync_width + sig->v_start_width, - .offset_src = DI_SYNC_HSYNC, - .repeat_count = sig->height, - .cnt_clr_src = DI_SYNC_VSYNC, - } , { - .run_src = DI_SYNC_CLK, - .offset_count = sig->h_sync_width + sig->h_start_width, - .offset_src = DI_SYNC_CLK, - .repeat_count = sig->width, - .cnt_clr_src = 5, - } , { - /* unused */ - } , { - /* unused */ - } , { - /* unused */ - } , { - /* unused */ - }, - }; - - ipu_di_write(di, v_total - 1, DI_SCR_CONF); - ipu_di_sync_config(di, cfg, 0, ARRAY_SIZE(cfg)); -} - -int ipu_di_init_sync_panel(struct ipu_di *di, struct ipu_di_signal_cfg *sig) -{ - u32 reg; - u32 di_gen, vsync_cnt; - u32 div; - u32 h_total, v_total; - int ret; - unsigned long round; - struct clk *parent; - - dev_dbg(di->ipu->dev, "disp %d: panel size = %d x %d\n", - di->id, sig->width, sig->height); - - if ((sig->v_sync_width == 0) || (sig->h_sync_width == 0)) - return -EINVAL; - - if (sig->clkflags & IPU_DI_CLKMODE_EXT) - parent = di->clk_di; - else - parent = di->clk_ipu; - - ret = clk_set_parent(di->clk_di_pixel, parent); - if (ret) { - dev_err(di->ipu->dev, - "setting pixel clock to parent %s failed with %d\n", - __clk_get_name(parent), ret); - return ret; - } - - if (sig->clkflags & IPU_DI_CLKMODE_SYNC) - round = clk_get_rate(parent); - else - round = clk_round_rate(di->clk_di_pixel, sig->pixelclock); - - ret = clk_set_rate(di->clk_di_pixel, round); - - h_total = sig->width + sig->h_sync_width + sig->h_start_width + - sig->h_end_width; - v_total = sig->height + sig->v_sync_width + sig->v_start_width + - sig->v_end_width; - - mutex_lock(&di_mutex); - - div = ipu_di_read(di, DI_BS_CLKGEN0) & 0xfff; - div = div / 16; /* Now divider is integer portion */ - - /* Setup pixel clock timing */ - /* Down time is half of period */ - ipu_di_write(di, (div << 16), DI_BS_CLKGEN1); - - ipu_di_data_wave_config(di, SYNC_WAVE, div - 1, div - 1); - ipu_di_data_pin_config(di, SYNC_WAVE, DI_PIN15, 3, 0, div * 2); - - di_gen = ipu_di_read(di, DI_GENERAL) & DI_GEN_DI_CLK_EXT; - di_gen |= DI_GEN_DI_VSYNC_EXT; - - if (sig->interlaced) { - ipu_di_sync_config_interlaced(di, sig); - - /* set y_sel = 1 */ - di_gen |= 0x10000000; - di_gen |= DI_GEN_POLARITY_5; - di_gen |= DI_GEN_POLARITY_8; - - vsync_cnt = 7; - - if (sig->Hsync_pol) - di_gen |= DI_GEN_POLARITY_3; - if (sig->Vsync_pol) - di_gen |= DI_GEN_POLARITY_2; - } else { - ipu_di_sync_config_noninterlaced(di, sig, div); - - vsync_cnt = 3; - - if (sig->Hsync_pol) - di_gen |= DI_GEN_POLARITY_2; - if (sig->Vsync_pol) - di_gen |= DI_GEN_POLARITY_3; - } - - if (!sig->clk_pol) - di_gen |= DI_GEN_POLARITY_DISP_CLK; - - ipu_di_write(di, di_gen, DI_GENERAL); - - ipu_di_write(di, (--vsync_cnt << DI_VSYNC_SEL_OFFSET) | 0x00000002, - DI_SYNC_AS_GEN); - - reg = ipu_di_read(di, DI_POL); - reg &= ~(DI_POL_DRDY_DATA_POLARITY | DI_POL_DRDY_POLARITY_15); - - if (sig->enable_pol) - reg |= DI_POL_DRDY_POLARITY_15; - if (sig->data_pol) - reg |= DI_POL_DRDY_DATA_POLARITY; - - ipu_di_write(di, reg, DI_POL); - - mutex_unlock(&di_mutex); - - return 0; -} -EXPORT_SYMBOL_GPL(ipu_di_init_sync_panel); - -int ipu_di_enable(struct ipu_di *di) -{ - clk_prepare_enable(di->clk_di_pixel); - - ipu_module_enable(di->ipu, di->module); - - return 0; -} -EXPORT_SYMBOL_GPL(ipu_di_enable); - -int ipu_di_disable(struct ipu_di *di) -{ - ipu_module_disable(di->ipu, di->module); - - clk_disable_unprepare(di->clk_di_pixel); - - return 0; -} -EXPORT_SYMBOL_GPL(ipu_di_disable); - -int ipu_di_get_num(struct ipu_di *di) -{ - return di->id; -} -EXPORT_SYMBOL_GPL(ipu_di_get_num); - -static DEFINE_MUTEX(ipu_di_lock); - -struct ipu_di *ipu_di_get(struct ipu_soc *ipu, int disp) -{ - struct ipu_di *di; - - if (disp > 1) - return ERR_PTR(-EINVAL); - - di = ipu->di_priv[disp]; - - mutex_lock(&ipu_di_lock); - - if (di->inuse) { - di = ERR_PTR(-EBUSY); - goto out; - } - - di->inuse = true; -out: - mutex_unlock(&ipu_di_lock); - - return di; -} -EXPORT_SYMBOL_GPL(ipu_di_get); - -void ipu_di_put(struct ipu_di *di) -{ - mutex_lock(&ipu_di_lock); - - di->inuse = false; - - mutex_unlock(&ipu_di_lock); -} -EXPORT_SYMBOL_GPL(ipu_di_put); - -int ipu_di_init(struct ipu_soc *ipu, struct device *dev, int id, - unsigned long base, - u32 module, struct clk *clk_ipu) -{ - struct ipu_di *di; - int ret; - const char *di_parent[2]; - struct clk_init_data init = { - .ops = &clk_di_ops, - .num_parents = 2, - .flags = 0, - }; - - if (id > 1) - return -ENODEV; - - di = devm_kzalloc(dev, sizeof(*di), GFP_KERNEL); - if (!di) - return -ENOMEM; - - ipu->di_priv[id] = di; - - di->clk_di = devm_clk_get(dev, id ? "di1" : "di0"); - if (IS_ERR(di->clk_di)) - return PTR_ERR(di->clk_di); - - di->module = module; - di->id = id; - di->clk_ipu = clk_ipu; - di->base = devm_ioremap(dev, base, PAGE_SIZE); - if (!di->base) - return -ENOMEM; - - di_parent[0] = __clk_get_name(di->clk_ipu); - di_parent[1] = __clk_get_name(di->clk_di); - - ipu_di_write(di, 0x10, DI_BS_CLKGEN0); - - init.parent_names = (const char **)&di_parent; - di->clk_name = kasprintf(GFP_KERNEL, "%s_di%d_pixel", - dev_name(dev), id); - if (!di->clk_name) - return -ENOMEM; - - init.name = di->clk_name; - - di->clk_hw_out.init = &init; - di->clk_di_pixel = clk_register(dev, &di->clk_hw_out); - - if (IS_ERR(di->clk_di_pixel)) { - ret = PTR_ERR(di->clk_di_pixel); - goto failed_clk_register; - } - - dev_info(dev, "DI%d base: 0x%08lx remapped to %p\n", - id, base, di->base); - di->inuse = false; - di->ipu = ipu; - - return 0; - -failed_clk_register: - - kfree(di->clk_name); - - return ret; -} - -void ipu_di_exit(struct ipu_soc *ipu, int id) -{ - struct ipu_di *di = ipu->di_priv[id]; - - clk_unregister(di->clk_di_pixel); - kfree(di->clk_name); -} diff --git a/trunk/drivers/staging/imx-drm/ipu-v3/ipu-dmfc.c b/trunk/drivers/staging/imx-drm/ipu-v3/ipu-dmfc.c deleted file mode 100644 index 91821bc30f41..000000000000 --- a/trunk/drivers/staging/imx-drm/ipu-v3/ipu-dmfc.c +++ /dev/null @@ -1,408 +0,0 @@ -/* - * Copyright (c) 2010 Sascha Hauer - * Copyright (C) 2005-2009 Freescale Semiconductor, Inc. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * 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. - */ -#include -#include -#include -#include - -#include "imx-ipu-v3.h" -#include "ipu-prv.h" - -#define DMFC_RD_CHAN 0x0000 -#define DMFC_WR_CHAN 0x0004 -#define DMFC_WR_CHAN_DEF 0x0008 -#define DMFC_DP_CHAN 0x000c -#define DMFC_DP_CHAN_DEF 0x0010 -#define DMFC_GENERAL1 0x0014 -#define DMFC_GENERAL2 0x0018 -#define DMFC_IC_CTRL 0x001c -#define DMFC_STAT 0x0020 - -#define DMFC_WR_CHAN_1_28 0 -#define DMFC_WR_CHAN_2_41 8 -#define DMFC_WR_CHAN_1C_42 16 -#define DMFC_WR_CHAN_2C_43 24 - -#define DMFC_DP_CHAN_5B_23 0 -#define DMFC_DP_CHAN_5F_27 8 -#define DMFC_DP_CHAN_6B_24 16 -#define DMFC_DP_CHAN_6F_29 24 - -#define DMFC_FIFO_SIZE_64 (3 << 3) -#define DMFC_FIFO_SIZE_128 (2 << 3) -#define DMFC_FIFO_SIZE_256 (1 << 3) -#define DMFC_FIFO_SIZE_512 (0 << 3) - -#define DMFC_SEGMENT(x) ((x & 0x7) << 0) -#define DMFC_BURSTSIZE_128 (0 << 6) -#define DMFC_BURSTSIZE_64 (1 << 6) -#define DMFC_BURSTSIZE_32 (2 << 6) -#define DMFC_BURSTSIZE_16 (3 << 6) - -struct dmfc_channel_data { - int ipu_channel; - unsigned long channel_reg; - unsigned long shift; - unsigned eot_shift; - unsigned max_fifo_lines; -}; - -static const struct dmfc_channel_data dmfcdata[] = { - { - .ipu_channel = 23, - .channel_reg = DMFC_DP_CHAN, - .shift = DMFC_DP_CHAN_5B_23, - .eot_shift = 20, - .max_fifo_lines = 3, - }, { - .ipu_channel = 24, - .channel_reg = DMFC_DP_CHAN, - .shift = DMFC_DP_CHAN_6B_24, - .eot_shift = 22, - .max_fifo_lines = 1, - }, { - .ipu_channel = 27, - .channel_reg = DMFC_DP_CHAN, - .shift = DMFC_DP_CHAN_5F_27, - .eot_shift = 21, - .max_fifo_lines = 2, - }, { - .ipu_channel = 28, - .channel_reg = DMFC_WR_CHAN, - .shift = DMFC_WR_CHAN_1_28, - .eot_shift = 16, - .max_fifo_lines = 2, - }, { - .ipu_channel = 29, - .channel_reg = DMFC_DP_CHAN, - .shift = DMFC_DP_CHAN_6F_29, - .eot_shift = 23, - .max_fifo_lines = 1, - }, -}; - -#define DMFC_NUM_CHANNELS ARRAY_SIZE(dmfcdata) - -struct ipu_dmfc_priv; - -struct dmfc_channel { - unsigned slots; - unsigned slotmask; - unsigned segment; - int burstsize; - struct ipu_soc *ipu; - struct ipu_dmfc_priv *priv; - const struct dmfc_channel_data *data; -}; - -struct ipu_dmfc_priv { - struct ipu_soc *ipu; - struct device *dev; - struct dmfc_channel channels[DMFC_NUM_CHANNELS]; - struct mutex mutex; - unsigned long bandwidth_per_slot; - void __iomem *base; - int use_count; -}; - -int ipu_dmfc_enable_channel(struct dmfc_channel *dmfc) -{ - struct ipu_dmfc_priv *priv = dmfc->priv; - mutex_lock(&priv->mutex); - - if (!priv->use_count) - ipu_module_enable(priv->ipu, IPU_CONF_DMFC_EN); - - priv->use_count++; - - mutex_unlock(&priv->mutex); - - return 0; -} -EXPORT_SYMBOL_GPL(ipu_dmfc_enable_channel); - -void ipu_dmfc_disable_channel(struct dmfc_channel *dmfc) -{ - struct ipu_dmfc_priv *priv = dmfc->priv; - - mutex_lock(&priv->mutex); - - priv->use_count--; - - if (!priv->use_count) - ipu_module_disable(priv->ipu, IPU_CONF_DMFC_EN); - - if (priv->use_count < 0) - priv->use_count = 0; - - mutex_unlock(&priv->mutex); -} -EXPORT_SYMBOL_GPL(ipu_dmfc_disable_channel); - -static int ipu_dmfc_setup_channel(struct dmfc_channel *dmfc, int slots, - int segment, int burstsize) -{ - struct ipu_dmfc_priv *priv = dmfc->priv; - u32 val, field; - - dev_dbg(priv->dev, - "dmfc: using %d slots starting from segment %d for IPU channel %d\n", - slots, segment, dmfc->data->ipu_channel); - - if (!dmfc) - return -EINVAL; - - switch (slots) { - case 1: - field = DMFC_FIFO_SIZE_64; - break; - case 2: - field = DMFC_FIFO_SIZE_128; - break; - case 4: - field = DMFC_FIFO_SIZE_256; - break; - case 8: - field = DMFC_FIFO_SIZE_512; - break; - default: - return -EINVAL; - } - - switch (burstsize) { - case 16: - field |= DMFC_BURSTSIZE_16; - break; - case 32: - field |= DMFC_BURSTSIZE_32; - break; - case 64: - field |= DMFC_BURSTSIZE_64; - break; - case 128: - field |= DMFC_BURSTSIZE_128; - break; - } - - field |= DMFC_SEGMENT(segment); - - val = readl(priv->base + dmfc->data->channel_reg); - - val &= ~(0xff << dmfc->data->shift); - val |= field << dmfc->data->shift; - - writel(val, priv->base + dmfc->data->channel_reg); - - dmfc->slots = slots; - dmfc->segment = segment; - dmfc->burstsize = burstsize; - dmfc->slotmask = ((1 << slots) - 1) << segment; - - return 0; -} - -static int dmfc_bandwidth_to_slots(struct ipu_dmfc_priv *priv, - unsigned long bandwidth) -{ - int slots = 1; - - while (slots * priv->bandwidth_per_slot < bandwidth) - slots *= 2; - - return slots; -} - -static int dmfc_find_slots(struct ipu_dmfc_priv *priv, int slots) -{ - unsigned slotmask_need, slotmask_used = 0; - int i, segment = 0; - - slotmask_need = (1 << slots) - 1; - - for (i = 0; i < DMFC_NUM_CHANNELS; i++) - slotmask_used |= priv->channels[i].slotmask; - - while (slotmask_need <= 0xff) { - if (!(slotmask_used & slotmask_need)) - return segment; - - slotmask_need <<= 1; - segment++; - } - - return -EBUSY; -} - -void ipu_dmfc_free_bandwidth(struct dmfc_channel *dmfc) -{ - struct ipu_dmfc_priv *priv = dmfc->priv; - int i; - - dev_dbg(priv->dev, "dmfc: freeing %d slots starting from segment %d\n", - dmfc->slots, dmfc->segment); - - mutex_lock(&priv->mutex); - - if (!dmfc->slots) - goto out; - - dmfc->slotmask = 0; - dmfc->slots = 0; - dmfc->segment = 0; - - for (i = 0; i < DMFC_NUM_CHANNELS; i++) - priv->channels[i].slotmask = 0; - - for (i = 0; i < DMFC_NUM_CHANNELS; i++) { - if (priv->channels[i].slots > 0) { - priv->channels[i].segment = - dmfc_find_slots(priv, priv->channels[i].slots); - priv->channels[i].slotmask = - ((1 << priv->channels[i].slots) - 1) << - priv->channels[i].segment; - } - } - - for (i = 0; i < DMFC_NUM_CHANNELS; i++) { - if (priv->channels[i].slots > 0) - ipu_dmfc_setup_channel(&priv->channels[i], - priv->channels[i].slots, - priv->channels[i].segment, - priv->channels[i].burstsize); - } -out: - mutex_unlock(&priv->mutex); -} -EXPORT_SYMBOL_GPL(ipu_dmfc_free_bandwidth); - -int ipu_dmfc_alloc_bandwidth(struct dmfc_channel *dmfc, - unsigned long bandwidth_pixel_per_second, int burstsize) -{ - struct ipu_dmfc_priv *priv = dmfc->priv; - int slots = dmfc_bandwidth_to_slots(priv, bandwidth_pixel_per_second); - int segment = 0, ret = 0; - - dev_dbg(priv->dev, "dmfc: trying to allocate %ldMpixel/s for IPU channel %d\n", - bandwidth_pixel_per_second / 1000000, - dmfc->data->ipu_channel); - - ipu_dmfc_free_bandwidth(dmfc); - - mutex_lock(&priv->mutex); - - if (slots > 8) { - ret = -EBUSY; - goto out; - } - - segment = dmfc_find_slots(priv, slots); - if (segment < 0) { - ret = -EBUSY; - goto out; - } - - ipu_dmfc_setup_channel(dmfc, slots, segment, burstsize); - -out: - mutex_unlock(&priv->mutex); - - return ret; -} -EXPORT_SYMBOL_GPL(ipu_dmfc_alloc_bandwidth); - -int ipu_dmfc_init_channel(struct dmfc_channel *dmfc, int width) -{ - struct ipu_dmfc_priv *priv = dmfc->priv; - u32 dmfc_gen1; - - dmfc_gen1 = readl(priv->base + DMFC_GENERAL1); - - if ((dmfc->slots * 64 * 4) / width > dmfc->data->max_fifo_lines) - dmfc_gen1 |= 1 << dmfc->data->eot_shift; - else - dmfc_gen1 &= ~(1 << dmfc->data->eot_shift); - - writel(dmfc_gen1, priv->base + DMFC_GENERAL1); - - return 0; -} -EXPORT_SYMBOL_GPL(ipu_dmfc_init_channel); - -struct dmfc_channel *ipu_dmfc_get(struct ipu_soc *ipu, int ipu_channel) -{ - struct ipu_dmfc_priv *priv = ipu->dmfc_priv; - int i; - - for (i = 0; i < DMFC_NUM_CHANNELS; i++) - if (dmfcdata[i].ipu_channel == ipu_channel) - return &priv->channels[i]; - return ERR_PTR(-ENODEV); -} -EXPORT_SYMBOL_GPL(ipu_dmfc_get); - -void ipu_dmfc_put(struct dmfc_channel *dmfc) -{ - ipu_dmfc_free_bandwidth(dmfc); -} -EXPORT_SYMBOL_GPL(ipu_dmfc_put); - -int ipu_dmfc_init(struct ipu_soc *ipu, struct device *dev, unsigned long base, - struct clk *ipu_clk) -{ - struct ipu_dmfc_priv *priv; - int i; - - priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); - if (!priv) - return -ENOMEM; - - priv->base = devm_ioremap(dev, base, PAGE_SIZE); - if (!priv->base) - return -ENOMEM; - - priv->dev = dev; - priv->ipu = ipu; - mutex_init(&priv->mutex); - - ipu->dmfc_priv = priv; - - for (i = 0; i < DMFC_NUM_CHANNELS; i++) { - priv->channels[i].priv = priv; - priv->channels[i].ipu = ipu; - priv->channels[i].data = &dmfcdata[i]; - } - - writel(0x0, priv->base + DMFC_WR_CHAN); - writel(0x0, priv->base + DMFC_DP_CHAN); - - /* - * We have a total bandwidth of clkrate * 4pixel divided - * into 8 slots. - */ - priv->bandwidth_per_slot = clk_get_rate(ipu_clk) / 8; - - dev_dbg(dev, "dmfc: 8 slots with %ldMpixel/s bandwidth each\n", - priv->bandwidth_per_slot / 1000000); - - writel(0x202020f6, priv->base + DMFC_WR_CHAN_DEF); - writel(0x2020f6f6, priv->base + DMFC_DP_CHAN_DEF); - writel(0x00000003, priv->base + DMFC_GENERAL1); - - return 0; -} - -void ipu_dmfc_exit(struct ipu_soc *ipu) -{ -} diff --git a/trunk/drivers/staging/imx-drm/ipu-v3/ipu-dp.c b/trunk/drivers/staging/imx-drm/ipu-v3/ipu-dp.c deleted file mode 100644 index 26aecaf9677f..000000000000 --- a/trunk/drivers/staging/imx-drm/ipu-v3/ipu-dp.c +++ /dev/null @@ -1,336 +0,0 @@ -/* - * Copyright (c) 2010 Sascha Hauer - * Copyright (C) 2005-2009 Freescale Semiconductor, Inc. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * 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. - */ -#include -#include -#include -#include -#include -#include - -#include "imx-ipu-v3.h" -#include "ipu-prv.h" - -#define DP_SYNC 0 -#define DP_ASYNC0 0x60 -#define DP_ASYNC1 0xBC - -#define DP_COM_CONF 0x0 -#define DP_GRAPH_WIND_CTRL 0x0004 -#define DP_FG_POS 0x0008 -#define DP_CSC_A_0 0x0044 -#define DP_CSC_A_1 0x0048 -#define DP_CSC_A_2 0x004C -#define DP_CSC_A_3 0x0050 -#define DP_CSC_0 0x0054 -#define DP_CSC_1 0x0058 - -#define DP_COM_CONF_FG_EN (1 << 0) -#define DP_COM_CONF_GWSEL (1 << 1) -#define DP_COM_CONF_GWAM (1 << 2) -#define DP_COM_CONF_GWCKE (1 << 3) -#define DP_COM_CONF_CSC_DEF_MASK (3 << 8) -#define DP_COM_CONF_CSC_DEF_OFFSET 8 -#define DP_COM_CONF_CSC_DEF_FG (3 << 8) -#define DP_COM_CONF_CSC_DEF_BG (2 << 8) -#define DP_COM_CONF_CSC_DEF_BOTH (1 << 8) - -struct ipu_dp_priv; - -struct ipu_dp { - u32 flow; - bool in_use; - bool foreground; - enum ipu_color_space in_cs; -}; - -struct ipu_flow { - struct ipu_dp foreground; - struct ipu_dp background; - enum ipu_color_space out_cs; - void __iomem *base; - struct ipu_dp_priv *priv; -}; - -struct ipu_dp_priv { - struct ipu_soc *ipu; - struct device *dev; - void __iomem *base; - struct ipu_flow flow[3]; - struct mutex mutex; - int use_count; -}; - -static u32 ipu_dp_flow_base[] = {DP_SYNC, DP_ASYNC0, DP_ASYNC1}; - -static inline struct ipu_flow *to_flow(struct ipu_dp *dp) -{ - if (dp->foreground) - return container_of(dp, struct ipu_flow, foreground); - else - return container_of(dp, struct ipu_flow, background); -} - -int ipu_dp_set_global_alpha(struct ipu_dp *dp, bool enable, - u8 alpha, bool bg_chan) -{ - struct ipu_flow *flow = to_flow(dp); - struct ipu_dp_priv *priv = flow->priv; - u32 reg; - - mutex_lock(&priv->mutex); - - reg = readl(flow->base + DP_COM_CONF); - if (bg_chan) - reg &= ~DP_COM_CONF_GWSEL; - else - reg |= DP_COM_CONF_GWSEL; - writel(reg, flow->base + DP_COM_CONF); - - if (enable) { - reg = readl(flow->base + DP_GRAPH_WIND_CTRL) & 0x00FFFFFFL; - writel(reg | ((u32) alpha << 24), - flow->base + DP_GRAPH_WIND_CTRL); - - reg = readl(flow->base + DP_COM_CONF); - writel(reg | DP_COM_CONF_GWAM, flow->base + DP_COM_CONF); - } else { - reg = readl(flow->base + DP_COM_CONF); - writel(reg & ~DP_COM_CONF_GWAM, flow->base + DP_COM_CONF); - } - - ipu_srm_dp_sync_update(priv->ipu); - - mutex_unlock(&priv->mutex); - - return 0; -} -EXPORT_SYMBOL_GPL(ipu_dp_set_global_alpha); - -int ipu_dp_set_window_pos(struct ipu_dp *dp, u16 x_pos, u16 y_pos) -{ - struct ipu_flow *flow = to_flow(dp); - struct ipu_dp_priv *priv = flow->priv; - - writel((x_pos << 16) | y_pos, flow->base + DP_FG_POS); - - ipu_srm_dp_sync_update(priv->ipu); - - return 0; -} -EXPORT_SYMBOL_GPL(ipu_dp_set_window_pos); - -static void ipu_dp_csc_init(struct ipu_flow *flow, - enum ipu_color_space in, - enum ipu_color_space out, - u32 place) -{ - u32 reg; - - reg = readl(flow->base + DP_COM_CONF); - reg &= ~DP_COM_CONF_CSC_DEF_MASK; - - if (in == out) { - writel(reg, flow->base + DP_COM_CONF); - return; - } - - if (in == IPUV3_COLORSPACE_RGB && out == IPUV3_COLORSPACE_YUV) { - writel(0x099 | (0x12d << 16), flow->base + DP_CSC_A_0); - writel(0x03a | (0x3a9 << 16), flow->base + DP_CSC_A_1); - writel(0x356 | (0x100 << 16), flow->base + DP_CSC_A_2); - writel(0x100 | (0x329 << 16), flow->base + DP_CSC_A_3); - writel(0x3d6 | (0x0000 << 16) | (2 << 30), - flow->base + DP_CSC_0); - writel(0x200 | (2 << 14) | (0x200 << 16) | (2 << 30), - flow->base + DP_CSC_1); - } else { - writel(0x095 | (0x000 << 16), flow->base + DP_CSC_A_0); - writel(0x0cc | (0x095 << 16), flow->base + DP_CSC_A_1); - writel(0x3ce | (0x398 << 16), flow->base + DP_CSC_A_2); - writel(0x095 | (0x0ff << 16), flow->base + DP_CSC_A_3); - writel(0x000 | (0x3e42 << 16) | (1 << 30), - flow->base + DP_CSC_0); - writel(0x10a | (1 << 14) | (0x3dd6 << 16) | (1 << 30), - flow->base + DP_CSC_1); - } - - reg |= place; - - writel(reg, flow->base + DP_COM_CONF); -} - -int ipu_dp_setup_channel(struct ipu_dp *dp, - enum ipu_color_space in, - enum ipu_color_space out) -{ - struct ipu_flow *flow = to_flow(dp); - struct ipu_dp_priv *priv = flow->priv; - - mutex_lock(&priv->mutex); - - dp->in_cs = in; - - if (!dp->foreground) - flow->out_cs = out; - - if (flow->foreground.in_cs == flow->background.in_cs) { - /* - * foreground and background are of same colorspace, put - * colorspace converter after combining unit. - */ - ipu_dp_csc_init(flow, flow->foreground.in_cs, flow->out_cs, - DP_COM_CONF_CSC_DEF_BOTH); - } else { - if (flow->foreground.in_cs == flow->out_cs) - /* - * foreground identical to output, apply color - * conversion on background - */ - ipu_dp_csc_init(flow, flow->background.in_cs, - flow->out_cs, DP_COM_CONF_CSC_DEF_BG); - else - ipu_dp_csc_init(flow, flow->foreground.in_cs, - flow->out_cs, DP_COM_CONF_CSC_DEF_FG); - } - - ipu_srm_dp_sync_update(priv->ipu); - - mutex_unlock(&priv->mutex); - - return 0; -} -EXPORT_SYMBOL_GPL(ipu_dp_setup_channel); - -int ipu_dp_enable_channel(struct ipu_dp *dp) -{ - struct ipu_flow *flow = to_flow(dp); - struct ipu_dp_priv *priv = flow->priv; - - mutex_lock(&priv->mutex); - - if (!priv->use_count) - ipu_module_enable(priv->ipu, IPU_CONF_DP_EN); - - priv->use_count++; - - if (dp->foreground) { - u32 reg; - - reg = readl(flow->base + DP_COM_CONF); - reg |= DP_COM_CONF_FG_EN; - writel(reg, flow->base + DP_COM_CONF); - - ipu_srm_dp_sync_update(priv->ipu); - } - - mutex_unlock(&priv->mutex); - - return 0; -} -EXPORT_SYMBOL_GPL(ipu_dp_enable_channel); - -void ipu_dp_disable_channel(struct ipu_dp *dp) -{ - struct ipu_flow *flow = to_flow(dp); - struct ipu_dp_priv *priv = flow->priv; - - mutex_lock(&priv->mutex); - - priv->use_count--; - - if (dp->foreground) { - u32 reg, csc; - - reg = readl(flow->base + DP_COM_CONF); - csc = reg & DP_COM_CONF_CSC_DEF_MASK; - if (csc == DP_COM_CONF_CSC_DEF_FG) - reg &= ~DP_COM_CONF_CSC_DEF_MASK; - - reg &= ~DP_COM_CONF_FG_EN; - writel(reg, flow->base + DP_COM_CONF); - - writel(0, flow->base + DP_FG_POS); - ipu_srm_dp_sync_update(priv->ipu); - } - - if (!priv->use_count) - ipu_module_disable(priv->ipu, IPU_CONF_DP_EN); - - if (priv->use_count < 0) - priv->use_count = 0; - - mutex_unlock(&priv->mutex); -} -EXPORT_SYMBOL_GPL(ipu_dp_disable_channel); - -struct ipu_dp *ipu_dp_get(struct ipu_soc *ipu, unsigned int flow) -{ - struct ipu_dp_priv *priv = ipu->dp_priv; - struct ipu_dp *dp; - - if (flow > 5) - return ERR_PTR(-EINVAL); - - if (flow & 1) - dp = &priv->flow[flow >> 1].foreground; - else - dp = &priv->flow[flow >> 1].background; - - if (dp->in_use) - return ERR_PTR(-EBUSY); - - dp->in_use = true; - - return dp; -} -EXPORT_SYMBOL_GPL(ipu_dp_get); - -void ipu_dp_put(struct ipu_dp *dp) -{ - dp->in_use = false; -} -EXPORT_SYMBOL_GPL(ipu_dp_put); - -int ipu_dp_init(struct ipu_soc *ipu, struct device *dev, unsigned long base) -{ - struct ipu_dp_priv *priv; - int i; - - priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); - priv->dev = dev; - priv->ipu = ipu; - - ipu->dp_priv = priv; - - priv->base = devm_ioremap(dev, base, PAGE_SIZE); - if (!priv->base) { - kfree(priv); - return -ENOMEM; - } - - mutex_init(&priv->mutex); - - for (i = 0; i < 3; i++) { - priv->flow[i].foreground.foreground = 1; - priv->flow[i].base = priv->base + ipu_dp_flow_base[i]; - priv->flow[i].priv = priv; - } - - return 0; -} - -void ipu_dp_exit(struct ipu_soc *ipu) -{ -} diff --git a/trunk/drivers/staging/imx-drm/ipu-v3/ipu-prv.h b/trunk/drivers/staging/imx-drm/ipu-v3/ipu-prv.h deleted file mode 100644 index 551802863fd5..000000000000 --- a/trunk/drivers/staging/imx-drm/ipu-v3/ipu-prv.h +++ /dev/null @@ -1,206 +0,0 @@ -/* - * Copyright (c) 2010 Sascha Hauer - * Copyright (C) 2005-2009 Freescale Semiconductor, Inc. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * 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. - */ -#ifndef __IPU_PRV_H__ -#define __IPU_PRV_H__ - -struct ipu_soc; - -#include -#include -#include -#include - -#include "imx-ipu-v3.h" - -#define IPUV3_CHANNEL_CSI0 0 -#define IPUV3_CHANNEL_CSI1 1 -#define IPUV3_CHANNEL_CSI2 2 -#define IPUV3_CHANNEL_CSI3 3 -#define IPUV3_CHANNEL_MEM_BG_SYNC 23 -#define IPUV3_CHANNEL_MEM_FG_SYNC 27 -#define IPUV3_CHANNEL_MEM_DC_SYNC 28 -#define IPUV3_CHANNEL_MEM_FG_SYNC_ALPHA 31 -#define IPUV3_CHANNEL_MEM_DC_ASYNC 41 -#define IPUV3_CHANNEL_ROT_ENC_MEM 45 -#define IPUV3_CHANNEL_ROT_VF_MEM 46 -#define IPUV3_CHANNEL_ROT_PP_MEM 47 -#define IPUV3_CHANNEL_ROT_ENC_MEM_OUT 48 -#define IPUV3_CHANNEL_ROT_VF_MEM_OUT 49 -#define IPUV3_CHANNEL_ROT_PP_MEM_OUT 50 -#define IPUV3_CHANNEL_MEM_BG_SYNC_ALPHA 51 - -#define IPU_MCU_T_DEFAULT 8 -#define IPU_CM_IDMAC_REG_OFS 0x00008000 -#define IPU_CM_IC_REG_OFS 0x00020000 -#define IPU_CM_IRT_REG_OFS 0x00028000 -#define IPU_CM_CSI0_REG_OFS 0x00030000 -#define IPU_CM_CSI1_REG_OFS 0x00038000 -#define IPU_CM_SMFC_REG_OFS 0x00050000 -#define IPU_CM_DC_REG_OFS 0x00058000 -#define IPU_CM_DMFC_REG_OFS 0x00060000 - -/* Register addresses */ -/* IPU Common registers */ -#define IPU_CM_REG(offset) (offset) - -#define IPU_CONF IPU_CM_REG(0) - -#define IPU_SRM_PRI1 IPU_CM_REG(0x00a0) -#define IPU_SRM_PRI2 IPU_CM_REG(0x00a4) -#define IPU_FS_PROC_FLOW1 IPU_CM_REG(0x00a8) -#define IPU_FS_PROC_FLOW2 IPU_CM_REG(0x00ac) -#define IPU_FS_PROC_FLOW3 IPU_CM_REG(0x00b0) -#define IPU_FS_DISP_FLOW1 IPU_CM_REG(0x00b4) -#define IPU_FS_DISP_FLOW2 IPU_CM_REG(0x00b8) -#define IPU_SKIP IPU_CM_REG(0x00bc) -#define IPU_DISP_ALT_CONF IPU_CM_REG(0x00c0) -#define IPU_DISP_GEN IPU_CM_REG(0x00c4) -#define IPU_DISP_ALT1 IPU_CM_REG(0x00c8) -#define IPU_DISP_ALT2 IPU_CM_REG(0x00cc) -#define IPU_DISP_ALT3 IPU_CM_REG(0x00d0) -#define IPU_DISP_ALT4 IPU_CM_REG(0x00d4) -#define IPU_SNOOP IPU_CM_REG(0x00d8) -#define IPU_MEM_RST IPU_CM_REG(0x00dc) -#define IPU_PM IPU_CM_REG(0x00e0) -#define IPU_GPR IPU_CM_REG(0x00e4) -#define IPU_CHA_DB_MODE_SEL(ch) IPU_CM_REG(0x0150 + 4 * ((ch) / 32)) -#define IPU_ALT_CHA_DB_MODE_SEL(ch) IPU_CM_REG(0x0168 + 4 * ((ch) / 32)) -#define IPU_CHA_CUR_BUF(ch) IPU_CM_REG(0x023C + 4 * ((ch) / 32)) -#define IPU_ALT_CUR_BUF0 IPU_CM_REG(0x0244) -#define IPU_ALT_CUR_BUF1 IPU_CM_REG(0x0248) -#define IPU_SRM_STAT IPU_CM_REG(0x024C) -#define IPU_PROC_TASK_STAT IPU_CM_REG(0x0250) -#define IPU_DISP_TASK_STAT IPU_CM_REG(0x0254) -#define IPU_CHA_BUF0_RDY(ch) IPU_CM_REG(0x0268 + 4 * ((ch) / 32)) -#define IPU_CHA_BUF1_RDY(ch) IPU_CM_REG(0x0270 + 4 * ((ch) / 32)) -#define IPU_ALT_CHA_BUF0_RDY(ch) IPU_CM_REG(0x0278 + 4 * ((ch) / 32)) -#define IPU_ALT_CHA_BUF1_RDY(ch) IPU_CM_REG(0x0280 + 4 * ((ch) / 32)) - -#define IPU_INT_CTRL(n) IPU_CM_REG(0x003C + 4 * (n)) -#define IPU_INT_STAT(n) IPU_CM_REG(0x0200 + 4 * (n)) - -#define IPU_DI0_COUNTER_RELEASE (1 << 24) -#define IPU_DI1_COUNTER_RELEASE (1 << 25) - -#define IPU_IDMAC_REG(offset) (offset) - -#define IDMAC_CONF IPU_IDMAC_REG(0x0000) -#define IDMAC_CHA_EN(ch) IPU_IDMAC_REG(0x0004 + 4 * ((ch) / 32)) -#define IDMAC_SEP_ALPHA IPU_IDMAC_REG(0x000c) -#define IDMAC_ALT_SEP_ALPHA IPU_IDMAC_REG(0x0010) -#define IDMAC_CHA_PRI(ch) IPU_IDMAC_REG(0x0014 + 4 * ((ch) / 32)) -#define IDMAC_WM_EN(ch) IPU_IDMAC_REG(0x001c + 4 * ((ch) / 32)) -#define IDMAC_CH_LOCK_EN_1 IPU_IDMAC_REG(0x0024) -#define IDMAC_CH_LOCK_EN_2 IPU_IDMAC_REG(0x0028) -#define IDMAC_SUB_ADDR_0 IPU_IDMAC_REG(0x002c) -#define IDMAC_SUB_ADDR_1 IPU_IDMAC_REG(0x0030) -#define IDMAC_SUB_ADDR_2 IPU_IDMAC_REG(0x0034) -#define IDMAC_BAND_EN(ch) IPU_IDMAC_REG(0x0040 + 4 * ((ch) / 32)) -#define IDMAC_CHA_BUSY(ch) IPU_IDMAC_REG(0x0100 + 4 * ((ch) / 32)) - -#define IPU_NUM_IRQS (32 * 5) - -enum ipu_modules { - IPU_CONF_CSI0_EN = (1 << 0), - IPU_CONF_CSI1_EN = (1 << 1), - IPU_CONF_IC_EN = (1 << 2), - IPU_CONF_ROT_EN = (1 << 3), - IPU_CONF_ISP_EN = (1 << 4), - IPU_CONF_DP_EN = (1 << 5), - IPU_CONF_DI0_EN = (1 << 6), - IPU_CONF_DI1_EN = (1 << 7), - IPU_CONF_SMFC_EN = (1 << 8), - IPU_CONF_DC_EN = (1 << 9), - IPU_CONF_DMFC_EN = (1 << 10), - - IPU_CONF_VDI_EN = (1 << 12), - - IPU_CONF_IDMAC_DIS = (1 << 22), - - IPU_CONF_IC_DMFC_SEL = (1 << 25), - IPU_CONF_IC_DMFC_SYNC = (1 << 26), - IPU_CONF_VDI_DMFC_SYNC = (1 << 27), - - IPU_CONF_CSI0_DATA_SOURCE = (1 << 28), - IPU_CONF_CSI1_DATA_SOURCE = (1 << 29), - IPU_CONF_IC_INPUT = (1 << 30), - IPU_CONF_CSI_SEL = (1 << 31), -}; - -struct ipuv3_channel { - unsigned int num; - - bool enabled; - bool busy; - - struct ipu_soc *ipu; -}; - -struct ipu_dc_priv; -struct ipu_dmfc_priv; -struct ipu_di; -struct ipu_devtype; - -struct ipu_soc { - struct device *dev; - const struct ipu_devtype *devtype; - enum ipuv3_type ipu_type; - spinlock_t lock; - struct mutex channel_lock; - - void __iomem *cm_reg; - void __iomem *idmac_reg; - struct ipu_ch_param __iomem *cpmem_base; - - int usecount; - - struct clk *clk; - - struct ipuv3_channel channel[64]; - - int irq_start; - int irq_sync; - int irq_err; - - struct ipu_dc_priv *dc_priv; - struct ipu_dp_priv *dp_priv; - struct ipu_dmfc_priv *dmfc_priv; - struct ipu_di *di_priv[2]; -}; - -void ipu_srm_dp_sync_update(struct ipu_soc *ipu); - -int ipu_module_enable(struct ipu_soc *ipu, u32 mask); -int ipu_module_disable(struct ipu_soc *ipu, u32 mask); - -int ipu_di_init(struct ipu_soc *ipu, struct device *dev, int id, - unsigned long base, u32 module, struct clk *ipu_clk); -void ipu_di_exit(struct ipu_soc *ipu, int id); - -int ipu_dmfc_init(struct ipu_soc *ipu, struct device *dev, unsigned long base, - struct clk *ipu_clk); -void ipu_dmfc_exit(struct ipu_soc *ipu); - -int ipu_dp_init(struct ipu_soc *ipu, struct device *dev, unsigned long base); -void ipu_dp_exit(struct ipu_soc *ipu); - -int ipu_dc_init(struct ipu_soc *ipu, struct device *dev, unsigned long base, - unsigned long template_base); -void ipu_dc_exit(struct ipu_soc *ipu); - -int ipu_cpmem_init(struct ipu_soc *ipu, struct device *dev, unsigned long base); -void ipu_cpmem_exit(struct ipu_soc *ipu); - -#endif /* __IPU_PRV_H__ */ diff --git a/trunk/drivers/staging/imx-drm/ipuv3-crtc.c b/trunk/drivers/staging/imx-drm/ipuv3-crtc.c deleted file mode 100644 index 78d3edac75c1..000000000000 --- a/trunk/drivers/staging/imx-drm/ipuv3-crtc.c +++ /dev/null @@ -1,579 +0,0 @@ -/* - * i.MX IPUv3 Graphics driver - * - * Copyright (C) 2011 Sascha Hauer, Pengutronix - * - * 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., 51 Franklin Street, Fifth Floor, Boston, - * MA 02110-1301, USA. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "ipu-v3/imx-ipu-v3.h" -#include "imx-drm.h" - -#define DRIVER_DESC "i.MX IPUv3 Graphics" - -struct ipu_framebuffer { - struct drm_framebuffer base; - void *virt; - dma_addr_t phys; - size_t len; -}; - -struct ipu_crtc { - struct drm_fb_helper fb_helper; - struct ipu_framebuffer ifb; - int num_crtcs; - struct device *dev; - struct drm_crtc base; - struct imx_drm_crtc *imx_crtc; - struct ipuv3_channel *ipu_ch; - struct ipu_dc *dc; - struct ipu_dp *dp; - struct dmfc_channel *dmfc; - struct ipu_di *di; - int enabled; - struct ipu_priv *ipu_priv; - struct drm_pending_vblank_event *page_flip_event; - struct drm_framebuffer *newfb; - int irq; - u32 interface_pix_fmt; - unsigned long di_clkflags; -}; - -#define to_ipu_crtc(x) container_of(x, struct ipu_crtc, base) - -static int calc_vref(struct drm_display_mode *mode) -{ - unsigned long htotal, vtotal; - - htotal = mode->htotal; - vtotal = mode->vtotal; - - if (!htotal || !vtotal) - return 60; - - return mode->clock * 1000 / vtotal / htotal; -} - -static int calc_bandwidth(struct drm_display_mode *mode, unsigned int vref) -{ - return mode->hdisplay * mode->vdisplay * vref; -} - -static void ipu_fb_enable(struct ipu_crtc *ipu_crtc) -{ - if (ipu_crtc->enabled) - return; - - ipu_di_enable(ipu_crtc->di); - ipu_dmfc_enable_channel(ipu_crtc->dmfc); - ipu_idmac_enable_channel(ipu_crtc->ipu_ch); - ipu_dc_enable_channel(ipu_crtc->dc); - if (ipu_crtc->dp) - ipu_dp_enable_channel(ipu_crtc->dp); - - ipu_crtc->enabled = 1; -} - -static void ipu_fb_disable(struct ipu_crtc *ipu_crtc) -{ - if (!ipu_crtc->enabled) - return; - - if (ipu_crtc->dp) - ipu_dp_disable_channel(ipu_crtc->dp); - ipu_dc_disable_channel(ipu_crtc->dc); - ipu_idmac_disable_channel(ipu_crtc->ipu_ch); - ipu_dmfc_disable_channel(ipu_crtc->dmfc); - ipu_di_disable(ipu_crtc->di); - - ipu_crtc->enabled = 0; -} - -static void ipu_crtc_dpms(struct drm_crtc *crtc, int mode) -{ - struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc); - - dev_info(ipu_crtc->dev, "%s mode: %d\n", __func__, mode); - - switch (mode) { - case DRM_MODE_DPMS_ON: - ipu_fb_enable(ipu_crtc); - break; - case DRM_MODE_DPMS_STANDBY: - case DRM_MODE_DPMS_SUSPEND: - case DRM_MODE_DPMS_OFF: - ipu_fb_disable(ipu_crtc); - break; - } -} - -static int ipu_page_flip(struct drm_crtc *crtc, - struct drm_framebuffer *fb, - struct drm_pending_vblank_event *event) -{ - struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc); - int ret; - - if (ipu_crtc->newfb) - return -EBUSY; - - ret = imx_drm_crtc_vblank_get(ipu_crtc->imx_crtc); - if (ret) { - dev_dbg(ipu_crtc->dev, "failed to acquire vblank counter\n"); - list_del(&event->base.link); - - return ret; - } - - ipu_crtc->newfb = fb; - ipu_crtc->page_flip_event = event; - - return 0; -} - -static const struct drm_crtc_funcs ipu_crtc_funcs = { - .set_config = drm_crtc_helper_set_config, - .destroy = drm_crtc_cleanup, - .page_flip = ipu_page_flip, -}; - -static int ipu_drm_set_base(struct drm_crtc *crtc, int x, int y) -{ - struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc); - struct drm_gem_cma_object *cma_obj; - struct drm_framebuffer *fb = crtc->fb; - unsigned long phys; - - cma_obj = drm_fb_cma_get_gem_obj(fb, 0); - if (!cma_obj) { - DRM_LOG_KMS("entry is null.\n"); - return -EFAULT; - } - - phys = cma_obj->paddr; - phys += x * (fb->bits_per_pixel >> 3); - phys += y * fb->pitches[0]; - - dev_dbg(ipu_crtc->dev, "%s: phys: 0x%lx\n", __func__, phys); - dev_dbg(ipu_crtc->dev, "%s: xy: %dx%d\n", __func__, x, y); - - ipu_cpmem_set_stride(ipu_get_cpmem(ipu_crtc->ipu_ch), fb->pitches[0]); - ipu_cpmem_set_buffer(ipu_get_cpmem(ipu_crtc->ipu_ch), - 0, phys); - - return 0; -} - -static int ipu_crtc_mode_set(struct drm_crtc *crtc, - struct drm_display_mode *orig_mode, - struct drm_display_mode *mode, - int x, int y, - struct drm_framebuffer *old_fb) -{ - struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc); - struct drm_framebuffer *fb = ipu_crtc->base.fb; - int ret; - struct ipu_di_signal_cfg sig_cfg = {}; - u32 out_pixel_fmt; - struct ipu_ch_param __iomem *cpmem = ipu_get_cpmem(ipu_crtc->ipu_ch); - int bpp; - u32 v4l2_fmt; - - dev_dbg(ipu_crtc->dev, "%s: mode->hdisplay: %d\n", __func__, - mode->hdisplay); - dev_dbg(ipu_crtc->dev, "%s: mode->vdisplay: %d\n", __func__, - mode->vdisplay); - - ipu_ch_param_zero(cpmem); - - switch (fb->pixel_format) { - case DRM_FORMAT_XRGB8888: - case DRM_FORMAT_ARGB8888: - v4l2_fmt = V4L2_PIX_FMT_RGB32; - bpp = 32; - break; - case DRM_FORMAT_RGB565: - v4l2_fmt = V4L2_PIX_FMT_RGB565; - bpp = 16; - break; - case DRM_FORMAT_RGB888: - v4l2_fmt = V4L2_PIX_FMT_RGB24; - bpp = 24; - break; - default: - dev_err(ipu_crtc->dev, "unsupported pixel format 0x%08x\n", - fb->pixel_format); - return -EINVAL; - } - - out_pixel_fmt = ipu_crtc->interface_pix_fmt; - - if (mode->flags & DRM_MODE_FLAG_INTERLACE) - sig_cfg.interlaced = 1; - if (mode->flags & DRM_MODE_FLAG_PHSYNC) - sig_cfg.Hsync_pol = 1; - if (mode->flags & DRM_MODE_FLAG_PVSYNC) - sig_cfg.Vsync_pol = 1; - - sig_cfg.enable_pol = 1; - sig_cfg.clk_pol = 0; - sig_cfg.width = mode->hdisplay; - sig_cfg.height = mode->vdisplay; - sig_cfg.pixel_fmt = out_pixel_fmt; - sig_cfg.h_start_width = mode->htotal - mode->hsync_end; - sig_cfg.h_sync_width = mode->hsync_end - mode->hsync_start; - sig_cfg.h_end_width = mode->hsync_start - mode->hdisplay; - - sig_cfg.v_start_width = mode->vtotal - mode->vsync_end; - sig_cfg.v_sync_width = mode->vsync_end - mode->vsync_start; - sig_cfg.v_end_width = mode->vsync_start - mode->vdisplay; - sig_cfg.pixelclock = mode->clock * 1000; - sig_cfg.clkflags = ipu_crtc->di_clkflags; - - sig_cfg.v_to_h_sync = 0; - - if (ipu_crtc->dp) { - ret = ipu_dp_setup_channel(ipu_crtc->dp, IPUV3_COLORSPACE_RGB, - IPUV3_COLORSPACE_RGB); - if (ret) { - dev_err(ipu_crtc->dev, - "initializing display processor failed with %d\n", - ret); - return ret; - } - ipu_dp_set_global_alpha(ipu_crtc->dp, 1, 0, 1); - } - - ret = ipu_dc_init_sync(ipu_crtc->dc, ipu_crtc->di, sig_cfg.interlaced, - out_pixel_fmt, mode->hdisplay); - if (ret) { - dev_err(ipu_crtc->dev, - "initializing display controller failed with %d\n", - ret); - return ret; - } - - ret = ipu_di_init_sync_panel(ipu_crtc->di, &sig_cfg); - if (ret) { - dev_err(ipu_crtc->dev, - "initializing panel failed with %d\n", ret); - return ret; - } - - ipu_cpmem_set_resolution(cpmem, mode->hdisplay, mode->vdisplay); - ipu_cpmem_set_fmt(cpmem, v4l2_fmt); - ipu_cpmem_set_high_priority(ipu_crtc->ipu_ch); - - ret = ipu_dmfc_init_channel(ipu_crtc->dmfc, mode->hdisplay); - if (ret) { - dev_err(ipu_crtc->dev, - "initializing dmfc channel failed with %d\n", - ret); - return ret; - } - - ret = ipu_dmfc_alloc_bandwidth(ipu_crtc->dmfc, - calc_bandwidth(mode, calc_vref(mode)), 64); - if (ret) { - dev_err(ipu_crtc->dev, - "allocating dmfc bandwidth failed with %d\n", - ret); - return ret; - } - - ipu_drm_set_base(crtc, x, y); - - return 0; -} - -static void ipu_crtc_handle_pageflip(struct ipu_crtc *ipu_crtc) -{ - struct drm_pending_vblank_event *e; - struct timeval now; - unsigned long flags; - struct drm_device *drm = ipu_crtc->base.dev; - - spin_lock_irqsave(&drm->event_lock, flags); - - e = ipu_crtc->page_flip_event; - if (!e) { - spin_unlock_irqrestore(&drm->event_lock, flags); - return; - } - - do_gettimeofday(&now); - e->event.sequence = 0; - e->event.tv_sec = now.tv_sec; - e->event.tv_usec = now.tv_usec; - ipu_crtc->page_flip_event = NULL; - - imx_drm_crtc_vblank_put(ipu_crtc->imx_crtc); - - list_add_tail(&e->base.link, &e->base.file_priv->event_list); - - wake_up_interruptible(&e->base.file_priv->event_wait); - - spin_unlock_irqrestore(&drm->event_lock, flags); -} - -static irqreturn_t ipu_irq_handler(int irq, void *dev_id) -{ - struct ipu_crtc *ipu_crtc = dev_id; - - imx_drm_handle_vblank(ipu_crtc->imx_crtc); - - if (ipu_crtc->newfb) { - ipu_crtc->base.fb = ipu_crtc->newfb; - ipu_crtc->newfb = NULL; - ipu_drm_set_base(&ipu_crtc->base, 0, 0); - ipu_crtc_handle_pageflip(ipu_crtc); - } - - return IRQ_HANDLED; -} - -static bool ipu_crtc_mode_fixup(struct drm_crtc *crtc, - const struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) -{ - return true; -} - -static void ipu_crtc_prepare(struct drm_crtc *crtc) -{ - struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc); - - ipu_fb_disable(ipu_crtc); -} - -static void ipu_crtc_commit(struct drm_crtc *crtc) -{ - struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc); - - ipu_fb_enable(ipu_crtc); -} - -static void ipu_crtc_load_lut(struct drm_crtc *crtc) -{ -} - -static struct drm_crtc_helper_funcs ipu_helper_funcs = { - .dpms = ipu_crtc_dpms, - .mode_fixup = ipu_crtc_mode_fixup, - .mode_set = ipu_crtc_mode_set, - .prepare = ipu_crtc_prepare, - .commit = ipu_crtc_commit, - .load_lut = ipu_crtc_load_lut, -}; - -static int ipu_enable_vblank(struct drm_crtc *crtc) -{ - struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc); - - enable_irq(ipu_crtc->irq); - - return 0; -} - -static void ipu_disable_vblank(struct drm_crtc *crtc) -{ - struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc); - - disable_irq(ipu_crtc->irq); -} - -static int ipu_set_interface_pix_fmt(struct drm_crtc *crtc, u32 encoder_type, - u32 pixfmt) -{ - struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc); - - ipu_crtc->interface_pix_fmt = pixfmt; - - switch (encoder_type) { - case DRM_MODE_ENCODER_LVDS: - ipu_crtc->di_clkflags = IPU_DI_CLKMODE_SYNC | - IPU_DI_CLKMODE_EXT; - break; - case DRM_MODE_ENCODER_NONE: - ipu_crtc->di_clkflags = 0; - break; - } - - return 0; -} - -static const struct imx_drm_crtc_helper_funcs ipu_crtc_helper_funcs = { - .enable_vblank = ipu_enable_vblank, - .disable_vblank = ipu_disable_vblank, - .set_interface_pix_fmt = ipu_set_interface_pix_fmt, - .crtc_funcs = &ipu_crtc_funcs, - .crtc_helper_funcs = &ipu_helper_funcs, -}; - -static void ipu_put_resources(struct ipu_crtc *ipu_crtc) -{ - if (!IS_ERR_OR_NULL(ipu_crtc->ipu_ch)) - ipu_idmac_put(ipu_crtc->ipu_ch); - if (!IS_ERR_OR_NULL(ipu_crtc->dmfc)) - ipu_dmfc_put(ipu_crtc->dmfc); - if (!IS_ERR_OR_NULL(ipu_crtc->dp)) - ipu_dp_put(ipu_crtc->dp); - if (!IS_ERR_OR_NULL(ipu_crtc->di)) - ipu_di_put(ipu_crtc->di); -} - -static int ipu_get_resources(struct ipu_crtc *ipu_crtc, - struct ipu_client_platformdata *pdata) -{ - struct ipu_soc *ipu = dev_get_drvdata(ipu_crtc->dev->parent); - int ret; - - ipu_crtc->ipu_ch = ipu_idmac_get(ipu, pdata->dma[0]); - if (IS_ERR_OR_NULL(ipu_crtc->ipu_ch)) { - ret = PTR_ERR(ipu_crtc->ipu_ch); - goto err_out; - } - - ipu_crtc->dc = ipu_dc_get(ipu, pdata->dc); - if (IS_ERR(ipu_crtc->dc)) { - ret = PTR_ERR(ipu_crtc->dc); - goto err_out; - } - - ipu_crtc->dmfc = ipu_dmfc_get(ipu, pdata->dma[0]); - if (IS_ERR(ipu_crtc->dmfc)) { - ret = PTR_ERR(ipu_crtc->dmfc); - goto err_out; - } - - if (pdata->dp >= 0) { - ipu_crtc->dp = ipu_dp_get(ipu, pdata->dp); - if (IS_ERR(ipu_crtc->dp)) { - ret = PTR_ERR(ipu_crtc->ipu_ch); - goto err_out; - } - } - - ipu_crtc->di = ipu_di_get(ipu, pdata->di); - if (IS_ERR(ipu_crtc->di)) { - ret = PTR_ERR(ipu_crtc->di); - goto err_out; - } - - ipu_crtc->irq = ipu_idmac_channel_irq(ipu, ipu_crtc->ipu_ch, - IPU_IRQ_EOF); - ret = devm_request_irq(ipu_crtc->dev, ipu_crtc->irq, ipu_irq_handler, 0, - "imx_drm", ipu_crtc); - if (ret < 0) { - dev_err(ipu_crtc->dev, "irq request failed with %d.\n", ret); - goto err_out; - } - - disable_irq(ipu_crtc->irq); - - return 0; -err_out: - ipu_put_resources(ipu_crtc); - - return ret; -} - -static int ipu_crtc_init(struct ipu_crtc *ipu_crtc, - struct ipu_client_platformdata *pdata) -{ - int ret; - - ret = ipu_get_resources(ipu_crtc, pdata); - if (ret) { - dev_err(ipu_crtc->dev, "getting resources failed with %d.\n", - ret); - return ret; - } - - ret = imx_drm_add_crtc(&ipu_crtc->base, - &ipu_crtc->imx_crtc, - &ipu_crtc_helper_funcs, THIS_MODULE, - ipu_crtc->dev->parent->of_node, pdata->di); - if (ret) { - dev_err(ipu_crtc->dev, "adding crtc failed with %d.\n", ret); - goto err_put_resources; - } - - return 0; - -err_put_resources: - ipu_put_resources(ipu_crtc); - - return ret; -} - -static int __devinit ipu_drm_probe(struct platform_device *pdev) -{ - struct ipu_client_platformdata *pdata = pdev->dev.platform_data; - struct ipu_crtc *ipu_crtc; - int ret; - - if (!pdata) - return -EINVAL; - - pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32); - - ipu_crtc = devm_kzalloc(&pdev->dev, sizeof(*ipu_crtc), GFP_KERNEL); - if (!ipu_crtc) - return -ENOMEM; - - ipu_crtc->dev = &pdev->dev; - - ret = ipu_crtc_init(ipu_crtc, pdata); - - platform_set_drvdata(pdev, ipu_crtc); - - return 0; -} - -static int __devexit ipu_drm_remove(struct platform_device *pdev) -{ - struct ipu_crtc *ipu_crtc = platform_get_drvdata(pdev); - - imx_drm_remove_crtc(ipu_crtc->imx_crtc); - - ipu_put_resources(ipu_crtc); - - return 0; -} - -static struct platform_driver ipu_drm_driver = { - .driver = { - .name = "imx-ipuv3-crtc", - }, - .probe = ipu_drm_probe, - .remove = __devexit_p(ipu_drm_remove), -}; -module_platform_driver(ipu_drm_driver); - -MODULE_AUTHOR("Sascha Hauer "); -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/staging/imx-drm/parallel-display.c b/trunk/drivers/staging/imx-drm/parallel-display.c deleted file mode 100644 index 9b51d732eefa..000000000000 --- a/trunk/drivers/staging/imx-drm/parallel-display.c +++ /dev/null @@ -1,261 +0,0 @@ -/* - * i.MX drm driver - parallel display implementation - * - * Copyright (C) 2012 Sascha Hauer, Pengutronix - * - * 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., 51 Franklin Street, Fifth Floor, Boston, - * MA 02110-1301, USA. - */ - -#include -#include -#include -#include -#include - -#include "imx-drm.h" - -#define con_to_imxpd(x) container_of(x, struct imx_parallel_display, connector) -#define enc_to_imxpd(x) container_of(x, struct imx_parallel_display, encoder) - -struct imx_parallel_display { - struct drm_connector connector; - struct imx_drm_connector *imx_drm_connector; - struct drm_encoder encoder; - struct imx_drm_encoder *imx_drm_encoder; - struct device *dev; - void *edid; - int edid_len; - u32 interface_pix_fmt; - int mode_valid; - struct drm_display_mode mode; -}; - -static enum drm_connector_status imx_pd_connector_detect( - struct drm_connector *connector, bool force) -{ - return connector_status_connected; -} - -static void imx_pd_connector_destroy(struct drm_connector *connector) -{ - /* do not free here */ -} - -static int imx_pd_connector_get_modes(struct drm_connector *connector) -{ - struct imx_parallel_display *imxpd = con_to_imxpd(connector); - int num_modes = 0; - - if (imxpd->edid) { - drm_mode_connector_update_edid_property(connector, imxpd->edid); - num_modes = drm_add_edid_modes(connector, imxpd->edid); - } - - if (imxpd->mode_valid) { - struct drm_display_mode *mode = drm_mode_create(connector->dev); - drm_mode_copy(mode, &imxpd->mode); - mode->type |= DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED, - drm_mode_probed_add(connector, mode); - num_modes++; - } - - return num_modes; -} - -static int imx_pd_connector_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) -{ - return 0; -} - -static struct drm_encoder *imx_pd_connector_best_encoder( - struct drm_connector *connector) -{ - struct imx_parallel_display *imxpd = con_to_imxpd(connector); - - return &imxpd->encoder; -} - -static void imx_pd_encoder_dpms(struct drm_encoder *encoder, int mode) -{ -} - -static bool imx_pd_encoder_mode_fixup(struct drm_encoder *encoder, - const struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) -{ - return true; -} - -static void imx_pd_encoder_prepare(struct drm_encoder *encoder) -{ - struct imx_parallel_display *imxpd = enc_to_imxpd(encoder); - - imx_drm_crtc_panel_format(encoder->crtc, DRM_MODE_ENCODER_NONE, - imxpd->interface_pix_fmt); -} - -static void imx_pd_encoder_commit(struct drm_encoder *encoder) -{ -} - -static void imx_pd_encoder_mode_set(struct drm_encoder *encoder, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) -{ -} - -static void imx_pd_encoder_disable(struct drm_encoder *encoder) -{ -} - -static void imx_pd_encoder_destroy(struct drm_encoder *encoder) -{ - /* do not free here */ -} - -static struct drm_connector_funcs imx_pd_connector_funcs = { - .dpms = drm_helper_connector_dpms, - .fill_modes = drm_helper_probe_single_connector_modes, - .detect = imx_pd_connector_detect, - .destroy = imx_pd_connector_destroy, -}; - -static struct drm_connector_helper_funcs imx_pd_connector_helper_funcs = { - .get_modes = imx_pd_connector_get_modes, - .best_encoder = imx_pd_connector_best_encoder, - .mode_valid = imx_pd_connector_mode_valid, -}; - -static struct drm_encoder_funcs imx_pd_encoder_funcs = { - .destroy = imx_pd_encoder_destroy, -}; - -static struct drm_encoder_helper_funcs imx_pd_encoder_helper_funcs = { - .dpms = imx_pd_encoder_dpms, - .mode_fixup = imx_pd_encoder_mode_fixup, - .prepare = imx_pd_encoder_prepare, - .commit = imx_pd_encoder_commit, - .mode_set = imx_pd_encoder_mode_set, - .disable = imx_pd_encoder_disable, -}; - -static int imx_pd_register(struct imx_parallel_display *imxpd) -{ - int ret; - - drm_mode_connector_attach_encoder(&imxpd->connector, &imxpd->encoder); - - imxpd->connector.funcs = &imx_pd_connector_funcs; - imxpd->encoder.funcs = &imx_pd_encoder_funcs; - - imxpd->encoder.encoder_type = DRM_MODE_ENCODER_NONE; - imxpd->connector.connector_type = DRM_MODE_CONNECTOR_VGA; - - drm_encoder_helper_add(&imxpd->encoder, &imx_pd_encoder_helper_funcs); - ret = imx_drm_add_encoder(&imxpd->encoder, &imxpd->imx_drm_encoder, - THIS_MODULE); - if (ret) { - dev_err(imxpd->dev, "adding encoder failed with %d\n", ret); - return ret; - } - - drm_connector_helper_add(&imxpd->connector, - &imx_pd_connector_helper_funcs); - - ret = imx_drm_add_connector(&imxpd->connector, - &imxpd->imx_drm_connector, THIS_MODULE); - if (ret) { - imx_drm_remove_encoder(imxpd->imx_drm_encoder); - dev_err(imxpd->dev, "adding connector failed with %d\n", ret); - return ret; - } - - imxpd->connector.encoder = &imxpd->encoder; - - return 0; -} - -static int __devinit imx_pd_probe(struct platform_device *pdev) -{ - struct device_node *np = pdev->dev.of_node; - const u8 *edidp; - struct imx_parallel_display *imxpd; - int ret; - const char *fmt; - - imxpd = devm_kzalloc(&pdev->dev, sizeof(*imxpd), GFP_KERNEL); - if (!imxpd) - return -ENOMEM; - - edidp = of_get_property(np, "edid", &imxpd->edid_len); - if (edidp) - imxpd->edid = kmemdup(edidp, imxpd->edid_len, GFP_KERNEL); - - ret = of_property_read_string(np, "interface-pix-fmt", &fmt); - if (!ret) { - if (!strcmp(fmt, "rgb24")) - imxpd->interface_pix_fmt = V4L2_PIX_FMT_RGB24; - else if (!strcmp(fmt, "rgb565")) - imxpd->interface_pix_fmt = V4L2_PIX_FMT_RGB565; - } - - imxpd->dev = &pdev->dev; - - ret = imx_pd_register(imxpd); - if (ret) - return ret; - - ret = imx_drm_encoder_add_possible_crtcs(imxpd->imx_drm_encoder, np); - - platform_set_drvdata(pdev, imxpd); - - return 0; -} - -static int __devexit imx_pd_remove(struct platform_device *pdev) -{ - struct imx_parallel_display *imxpd = platform_get_drvdata(pdev); - struct drm_connector *connector = &imxpd->connector; - struct drm_encoder *encoder = &imxpd->encoder; - - drm_mode_connector_detach_encoder(connector, encoder); - - imx_drm_remove_connector(imxpd->imx_drm_connector); - imx_drm_remove_encoder(imxpd->imx_drm_encoder); - - return 0; -} - -static const struct of_device_id imx_pd_dt_ids[] = { - { .compatible = "fsl,imx-parallel-display", }, - { /* sentinel */ } -}; - -static struct platform_driver imx_pd_driver = { - .probe = imx_pd_probe, - .remove = __devexit_p(imx_pd_remove), - .driver = { - .of_match_table = imx_pd_dt_ids, - .name = "imx-parallel-display", - .owner = THIS_MODULE, - }, -}; - -module_platform_driver(imx_pd_driver); - -MODULE_DESCRIPTION("i.MX parallel display driver"); -MODULE_AUTHOR("Sascha Hauer, Pengutronix"); -MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/staging/ipack/Kconfig b/trunk/drivers/staging/ipack/Kconfig index 4cf47066140c..af321789dddb 100644 --- a/trunk/drivers/staging/ipack/Kconfig +++ b/trunk/drivers/staging/ipack/Kconfig @@ -4,7 +4,6 @@ menuconfig IPACK_BUS tristate "IndustryPack bus support" - depends on HAS_IOMEM ---help--- If you say Y here you get support for the IndustryPack Framework for drivers for many types of boards that support this industrial diff --git a/trunk/drivers/staging/ipack/TODO b/trunk/drivers/staging/ipack/TODO index ffafe6911a77..b21d33ab144a 100644 --- a/trunk/drivers/staging/ipack/TODO +++ b/trunk/drivers/staging/ipack/TODO @@ -12,8 +12,29 @@ operations between the two kind of boards. TODO ==== -checkpatch.pl warnings -cleanup +TPCI-200 +-------- + +* It has a linked list with the tpci200 devices it is managing. Get rid of it + and use driver_for_each_device() instead. + +IP-OCTAL +-------- + +* It has a linked list which saves the devices it is currently + managing. It should use the driver_for_each_device() function. It is not there + due to the impossibility of using container_of macro to recover the + corresponding "struct ipoctal" because the attribute "struct ipack_device" is + a pointer. This code should be refactored. + +Ipack +----- + +* The structures and API exported can be improved a lot. For example, the + way to unregistering IP module devices, doing the IP module driver a call to + remove_device() to notify the carrier driver, or the opposite with the call to + the ipack_driver_ops' remove() function could be improved. + Contact ======= diff --git a/trunk/drivers/staging/ipack/bridges/tpci200.c b/trunk/drivers/staging/ipack/bridges/tpci200.c index bb8aa70281cd..2b83fa8e550a 100644 --- a/trunk/drivers/staging/ipack/bridges/tpci200.c +++ b/trunk/drivers/staging/ipack/bridges/tpci200.c @@ -14,32 +14,38 @@ #include #include "tpci200.h" -static u16 tpci200_status_timeout[] = { - TPCI200_A_TIMEOUT, - TPCI200_B_TIMEOUT, - TPCI200_C_TIMEOUT, - TPCI200_D_TIMEOUT, +static struct ipack_bus_ops tpci200_bus_ops; + +/* TPCI200 controls registers */ +static int control_reg[] = { + TPCI200_CONTROL_A_REG, + TPCI200_CONTROL_B_REG, + TPCI200_CONTROL_C_REG, + TPCI200_CONTROL_D_REG }; -static u16 tpci200_status_error[] = { - TPCI200_A_ERROR, - TPCI200_B_ERROR, - TPCI200_C_ERROR, - TPCI200_D_ERROR, -}; +/* Linked list to save the registered devices */ +static LIST_HEAD(tpci200_list); + +static int tpci200_slot_unregister(struct ipack_device *dev); static struct tpci200_board *check_slot(struct ipack_device *dev) { struct tpci200_board *tpci200; + int found = 0; if (dev == NULL) return NULL; + list_for_each_entry(tpci200, &tpci200_list, list) { + if (tpci200->number == dev->bus_nr) { + found = 1; + break; + } + } - tpci200 = dev_get_drvdata(dev->bus->parent); - - if (tpci200 == NULL) { - dev_info(&dev->dev, "carrier board not found\n"); + if (!found) { + dev_err(&dev->dev, "Carrier not found\n"); return NULL; } @@ -53,190 +59,296 @@ static struct tpci200_board *check_slot(struct ipack_device *dev) return tpci200; } -static void tpci200_clear_mask(struct tpci200_board *tpci200, - __le16 __iomem *addr, u16 mask) +static inline unsigned char __tpci200_read8(void __iomem *address, + unsigned long offset) { - unsigned long flags; - spin_lock_irqsave(&tpci200->regs_lock, flags); - iowrite16(ioread16(addr) & (~mask), addr); - spin_unlock_irqrestore(&tpci200->regs_lock, flags); + return ioread8(address + (offset^1)); } -static void tpci200_set_mask(struct tpci200_board *tpci200, - __le16 __iomem *addr, u16 mask) +static inline unsigned short __tpci200_read16(void __iomem *address, + unsigned long offset) { - unsigned long flags; - spin_lock_irqsave(&tpci200->regs_lock, flags); - iowrite16(ioread16(addr) | mask, addr); - spin_unlock_irqrestore(&tpci200->regs_lock, flags); + return ioread16(address + offset); } -static void tpci200_unregister(struct tpci200_board *tpci200) +static inline unsigned int __tpci200_read32(void __iomem *address, + unsigned long offset) { - int i; + return swahw32(ioread32(address + offset)); +} - free_irq(tpci200->info->pdev->irq, (void *) tpci200); +static inline void __tpci200_write8(unsigned char value, + void __iomem *address, unsigned long offset) +{ + iowrite8(value, address+(offset^1)); +} - pci_iounmap(tpci200->info->pdev, tpci200->info->interface_regs); - pci_iounmap(tpci200->info->pdev, tpci200->info->ioidint_space); - pci_iounmap(tpci200->info->pdev, tpci200->info->mem8_space); - pci_iounmap(tpci200->info->pdev, tpci200->info->cfg_regs); +static inline void __tpci200_write16(unsigned short value, + void __iomem *address, + unsigned long offset) +{ + iowrite16(value, address+offset); +} - pci_release_region(tpci200->info->pdev, TPCI200_IP_INTERFACE_BAR); - pci_release_region(tpci200->info->pdev, TPCI200_IO_ID_INT_SPACES_BAR); - pci_release_region(tpci200->info->pdev, TPCI200_MEM8_SPACE_BAR); - pci_release_region(tpci200->info->pdev, TPCI200_CFG_MEM_BAR); +static inline void __tpci200_write32(unsigned int value, + void __iomem *address, + unsigned long offset) +{ + iowrite32(swahw32(value), address+offset); +} - pci_disable_device(tpci200->info->pdev); - pci_dev_put(tpci200->info->pdev); +static struct ipack_addr_space *get_slot_address_space(struct ipack_device *dev, + int space) +{ + struct ipack_addr_space *addr; - for (i = 0; i < TPCI200_NB_SLOT; i++) { - tpci200->slots[i].io_phys.address = NULL; - tpci200->slots[i].io_phys.size = 0; - tpci200->slots[i].id_phys.address = NULL; - tpci200->slots[i].id_phys.size = 0; - tpci200->slots[i].int_phys.address = NULL; - tpci200->slots[i].int_phys.size = 0; - tpci200->slots[i].mem_phys.address = NULL; - tpci200->slots[i].mem_phys.size = 0; + switch (space) { + case IPACK_IO_SPACE: + addr = &dev->io_space; + break; + case IPACK_ID_SPACE: + addr = &dev->id_space; + break; + case IPACK_MEM_SPACE: + addr = &dev->mem_space; + break; + default: + dev_err(&dev->dev, + "Slot [%d:%d] space number %d doesn't exist !\n", + dev->bus_nr, dev->slot, space); + return NULL; + break; } + + if ((addr->size == 0) || (addr->address == NULL)) { + dev_err(&dev->dev, "Error, slot space not mapped !\n"); + return NULL; + } + + return addr; } -static void tpci200_enable_irq(struct tpci200_board *tpci200, - int islot) +static int tpci200_read8(struct ipack_device *dev, int space, + unsigned long offset, unsigned char *value) { - tpci200_set_mask(tpci200, - &tpci200->info->interface_regs->control[islot], - TPCI200_INT0_EN | TPCI200_INT1_EN); + struct ipack_addr_space *addr; + struct tpci200_board *tpci200; + + tpci200 = check_slot(dev); + if (tpci200 == NULL) + return -EINVAL; + + addr = get_slot_address_space(dev, space); + if (addr == NULL) + return -EINVAL; + + if (offset >= addr->size) { + dev_err(&dev->dev, "Error, slot space offset error !\n"); + return -EFAULT; + } + + *value = __tpci200_read8(addr->address, offset); + + return 0; } -static void tpci200_disable_irq(struct tpci200_board *tpci200, - int islot) +static int tpci200_read16(struct ipack_device *dev, int space, + unsigned long offset, unsigned short *value) { - tpci200_clear_mask(tpci200, - &tpci200->info->interface_regs->control[islot], - TPCI200_INT0_EN | TPCI200_INT1_EN); + struct ipack_addr_space *addr; + struct tpci200_board *tpci200; + + tpci200 = check_slot(dev); + if (tpci200 == NULL) + return -EINVAL; + + addr = get_slot_address_space(dev, space); + if (addr == NULL) + return -EINVAL; + + if ((offset+2) >= addr->size) { + dev_err(&dev->dev, "Error, slot space offset error !\n"); + return -EFAULT; + } + *value = __tpci200_read16(addr->address, offset); + + return 0; } -static irqreturn_t tpci200_slot_irq(struct slot_irq *slot_irq) +static int tpci200_read32(struct ipack_device *dev, int space, + unsigned long offset, unsigned int *value) { - irqreturn_t ret; + struct ipack_addr_space *addr; + struct tpci200_board *tpci200; - if (!slot_irq) - return -ENODEV; - ret = slot_irq->handler(slot_irq->arg); + tpci200 = check_slot(dev); + if (tpci200 == NULL) + return -EINVAL; - return ret; + addr = get_slot_address_space(dev, space); + if (addr == NULL) + return -EINVAL; + + if ((offset+4) >= addr->size) { + dev_err(&dev->dev, "Error, slot space offset error !\n"); + return -EFAULT; + } + + *value = __tpci200_read32(addr->address, offset); + + return 0; } -static irqreturn_t tpci200_interrupt(int irq, void *dev_id) +static int tpci200_write8(struct ipack_device *dev, int space, + unsigned long offset, unsigned char value) { - struct tpci200_board *tpci200 = (struct tpci200_board *) dev_id; - struct slot_irq *slot_irq; - irqreturn_t ret; - u16 status_reg; - int i; + struct ipack_addr_space *addr; + struct tpci200_board *tpci200; - /* Read status register */ - status_reg = ioread16(&tpci200->info->interface_regs->status); + tpci200 = check_slot(dev); + if (tpci200 == NULL) + return -EINVAL; - /* Did we cause the interrupt? */ - if (!(status_reg & TPCI200_SLOT_INT_MASK)) - return IRQ_NONE; + addr = get_slot_address_space(dev, space); + if (addr == NULL) + return -EINVAL; - /* callback to the IRQ handler for the corresponding slot */ - rcu_read_lock(); - for (i = 0; i < TPCI200_NB_SLOT; i++) { - if (!(status_reg & ((TPCI200_A_INT0 | TPCI200_A_INT1) << (2 * i)))) - continue; - slot_irq = rcu_dereference(tpci200->slots[i].irq); - ret = tpci200_slot_irq(slot_irq); - if (ret == -ENODEV) { - dev_info(&tpci200->info->pdev->dev, - "No registered ISR for slot [%d:%d]!. IRQ will be disabled.\n", - tpci200->number, i); - tpci200_disable_irq(tpci200, i); - } + if (offset >= addr->size) { + dev_err(&dev->dev, "Error, slot space offset error !\n"); + return -EFAULT; } - rcu_read_unlock(); - return IRQ_HANDLED; + __tpci200_write8(value, addr->address, offset); + + return 0; } -static int tpci200_free_irq(struct ipack_device *dev) +static int tpci200_write16(struct ipack_device *dev, int space, + unsigned long offset, unsigned short value) { - struct slot_irq *slot_irq; + struct ipack_addr_space *addr; struct tpci200_board *tpci200; tpci200 = check_slot(dev); if (tpci200 == NULL) return -EINVAL; - if (mutex_lock_interruptible(&tpci200->mutex)) - return -ERESTARTSYS; - - if (tpci200->slots[dev->slot].irq == NULL) { - mutex_unlock(&tpci200->mutex); + addr = get_slot_address_space(dev, space); + if (addr == NULL) return -EINVAL; + + if ((offset+2) >= addr->size) { + dev_err(&dev->dev, "Error, slot space offset error !\n"); + return -EFAULT; } - tpci200_disable_irq(tpci200, dev->slot); - slot_irq = tpci200->slots[dev->slot].irq; - /* uninstall handler */ - RCU_INIT_POINTER(tpci200->slots[dev->slot].irq, NULL); - synchronize_rcu(); - kfree(slot_irq); - mutex_unlock(&tpci200->mutex); + __tpci200_write16(value, addr->address, offset); + return 0; } -static int tpci200_request_irq(struct ipack_device *dev, - irqreturn_t (*handler)(void *), void *arg) +static int tpci200_write32(struct ipack_device *dev, int space, + unsigned long offset, unsigned int value) { - int res = 0; - struct slot_irq *slot_irq; + struct ipack_addr_space *addr; struct tpci200_board *tpci200; tpci200 = check_slot(dev); if (tpci200 == NULL) return -EINVAL; - if (mutex_lock_interruptible(&tpci200->mutex)) - return -ERESTARTSYS; + addr = get_slot_address_space(dev, space); + if (addr == NULL) + return -EINVAL; - if (tpci200->slots[dev->slot].irq != NULL) { - dev_err(&dev->dev, - "Slot [%d:%d] IRQ already registered !\n", dev->bus_nr, - dev->slot); - res = -EINVAL; - goto out_unlock; + if ((offset+4) >= addr->size) { + dev_err(&dev->dev, "Error, slot space offset error !\n"); + return -EFAULT; } - slot_irq = kzalloc(sizeof(struct slot_irq), GFP_KERNEL); - if (slot_irq == NULL) { - dev_err(&dev->dev, - "Slot [%d:%d] unable to allocate memory for IRQ !\n", - dev->bus_nr, dev->slot); - res = -ENOMEM; - goto out_unlock; + __tpci200_write32(value, addr->address, offset); + + return 0; +} + +static void tpci200_unregister(struct tpci200_board *tpci200) +{ + int i; + + free_irq(tpci200->info->pdev->irq, (void *) tpci200); + + pci_iounmap(tpci200->info->pdev, tpci200->info->interface_regs); + pci_iounmap(tpci200->info->pdev, tpci200->info->ioidint_space); + pci_iounmap(tpci200->info->pdev, tpci200->info->mem8_space); + + pci_release_region(tpci200->info->pdev, TPCI200_IP_INTERFACE_BAR); + pci_release_region(tpci200->info->pdev, TPCI200_IO_ID_INT_SPACES_BAR); + pci_release_region(tpci200->info->pdev, TPCI200_MEM8_SPACE_BAR); + + pci_disable_device(tpci200->info->pdev); + pci_dev_put(tpci200->info->pdev); + + for (i = 0; i < TPCI200_NB_SLOT; i++) { + tpci200->slots[i].io_phys.address = NULL; + tpci200->slots[i].io_phys.size = 0; + tpci200->slots[i].id_phys.address = NULL; + tpci200->slots[i].id_phys.size = 0; + tpci200->slots[i].mem_phys.address = NULL; + tpci200->slots[i].mem_phys.size = 0; } +} - /* - * WARNING: Setup Interrupt Vector in the IndustryPack device - * before an IRQ request. - * Read the User Manual of your IndustryPack device to know - * where to write the vector in memory. - */ - slot_irq->handler = handler; - slot_irq->arg = arg; - slot_irq->holder = dev; +static irqreturn_t tpci200_interrupt(int irq, void *dev_id) +{ + struct tpci200_board *tpci200 = (struct tpci200_board *) dev_id; + int i; + unsigned short status_reg, reg_value; + unsigned short unhandled_ints = 0; + irqreturn_t ret = IRQ_NONE; - rcu_assign_pointer(tpci200->slots[dev->slot].irq, slot_irq); - tpci200_enable_irq(tpci200, dev->slot); + /* Read status register */ + status_reg = readw(tpci200->info->interface_regs + + TPCI200_STATUS_REG); + + if (status_reg & TPCI200_SLOT_INT_MASK) { + unhandled_ints = status_reg & TPCI200_SLOT_INT_MASK; + /* callback to the IRQ handler for the corresponding slot */ + for (i = 0; i < TPCI200_NB_SLOT; i++) { + if ((tpci200->slots[i].irq != NULL) && + (status_reg & ((TPCI200_A_INT0 | TPCI200_A_INT1) << (2*i)))) { + + ret = tpci200->slots[i].irq->handler(tpci200->slots[i].irq->arg); + + /* Dummy reads */ + readw(tpci200->slots[i].dev->io_space.address + + 0xC0); + readw(tpci200->slots[i].dev->io_space.address + + 0xC2); + + unhandled_ints &= ~(((TPCI200_A_INT0 | TPCI200_A_INT1) << (2*i))); + } + } + } + /* Interrupt not handled are disabled */ + if (unhandled_ints) { + for (i = 0; i < TPCI200_NB_SLOT; i++) { + if (unhandled_ints & ((TPCI200_INT0_EN | TPCI200_INT1_EN) << (2*i))) { + dev_info(&tpci200->slots[i].dev->dev, + "No registered ISR for slot [%d:%d]!. IRQ will be disabled.\n", + tpci200->number, i); + reg_value = readw( + tpci200->info->interface_regs + + control_reg[i]); + reg_value &= + ~(TPCI200_INT0_EN | TPCI200_INT1_EN); + writew(reg_value, + (tpci200->info->interface_regs + + control_reg[i])); + } + } + } -out_unlock: - mutex_unlock(&tpci200->mutex); - return res; + return ret; } static int tpci200_register(struct tpci200_board *tpci200) @@ -286,21 +398,18 @@ static int tpci200_register(struct tpci200_board *tpci200) /* Map internal tpci200 driver user space */ tpci200->info->interface_regs = - ioremap_nocache(pci_resource_start(tpci200->info->pdev, + ioremap(pci_resource_start(tpci200->info->pdev, TPCI200_IP_INTERFACE_BAR), TPCI200_IFACE_SIZE); tpci200->info->ioidint_space = - ioremap_nocache(pci_resource_start(tpci200->info->pdev, + ioremap(pci_resource_start(tpci200->info->pdev, TPCI200_IO_ID_INT_SPACES_BAR), TPCI200_IOIDINT_SIZE); tpci200->info->mem8_space = - ioremap_nocache(pci_resource_start(tpci200->info->pdev, + ioremap(pci_resource_start(tpci200->info->pdev, TPCI200_MEM8_SPACE_BAR), TPCI200_MEM8_SIZE); - /* Initialize lock that protects interface_regs */ - spin_lock_init(&tpci200->regs_lock); - ioidint_base = pci_resource_start(tpci200->info->pdev, TPCI200_IO_ID_INT_SPACES_BAR); mem_base = pci_resource_start(tpci200->info->pdev, @@ -328,16 +437,12 @@ static int tpci200_register(struct tpci200_board *tpci200) TPCI200_ID_SPACE_OFF + TPCI200_ID_SPACE_GAP*i; tpci200->slots[i].id_phys.size = TPCI200_ID_SPACE_SIZE; - tpci200->slots[i].int_phys.address = - (void __iomem *)ioidint_base + - TPCI200_INT_SPACE_OFF + TPCI200_INT_SPACE_GAP * i; - tpci200->slots[i].int_phys.size = TPCI200_INT_SPACE_SIZE; - tpci200->slots[i].mem_phys.address = (void __iomem *)mem_base + TPCI200_MEM8_GAP*i; tpci200->slots[i].mem_phys.size = TPCI200_MEM8_SIZE; - writew(slot_ctrl, &tpci200->info->interface_regs->control[i]); + writew(slot_ctrl, (tpci200->info->interface_regs + + control_reg[i])); } res = request_irq(tpci200->info->pdev->irq, @@ -362,6 +467,70 @@ static int tpci200_register(struct tpci200_board *tpci200) return res; } +static int __tpci200_request_irq(struct tpci200_board *tpci200, + struct ipack_device *dev) +{ + unsigned short slot_ctrl; + + /* Set the default parameters of the slot + * INT0 enabled, level sensitive + * INT1 enabled, level sensitive + * error interrupt disabled + * timeout interrupt disabled + * recover time disabled + * clock rate 8 MHz + */ + slot_ctrl = TPCI200_INT0_EN | TPCI200_INT1_EN; + writew(slot_ctrl, (tpci200->info->interface_regs + + control_reg[dev->slot])); + + return 0; +} + +static void __tpci200_free_irq(struct tpci200_board *tpci200, + struct ipack_device *dev) +{ + unsigned short slot_ctrl; + + /* Set the default parameters of the slot + * INT0 disabled, level sensitive + * INT1 disabled, level sensitive + * error interrupt disabled + * timeout interrupt disabled + * recover time disabled + * clock rate 8 MHz + */ + slot_ctrl = 0; + writew(slot_ctrl, (tpci200->info->interface_regs + + control_reg[dev->slot])); +} + +static int tpci200_free_irq(struct ipack_device *dev) +{ + struct slot_irq *slot_irq; + struct tpci200_board *tpci200; + + tpci200 = check_slot(dev); + if (tpci200 == NULL) + return -EINVAL; + + if (mutex_lock_interruptible(&tpci200->mutex)) + return -ERESTARTSYS; + + if (tpci200->slots[dev->slot].irq == NULL) { + mutex_unlock(&tpci200->mutex); + return -EINVAL; + } + + __tpci200_free_irq(tpci200, dev); + slot_irq = tpci200->slots[dev->slot].irq; + tpci200->slots[dev->slot].irq = NULL; + kfree(slot_irq); + + mutex_unlock(&tpci200->mutex); + return 0; +} + static int tpci200_slot_unmap_space(struct ipack_device *dev, int space) { struct ipack_addr_space *virt_addr_space; @@ -393,15 +562,6 @@ static int tpci200_slot_unmap_space(struct ipack_device *dev, int space) } virt_addr_space = &dev->id_space; break; - case IPACK_INT_SPACE: - if (dev->int_space.address == NULL) { - dev_info(&dev->dev, - "Slot [%d:%d] INT space not mapped !\n", - dev->bus_nr, dev->slot); - goto out_unlock; - } - virt_addr_space = &dev->int_space; - break; case IPACK_MEM_SPACE: if (dev->mem_space.address == NULL) { dev_info(&dev->dev, @@ -428,6 +588,29 @@ static int tpci200_slot_unmap_space(struct ipack_device *dev, int space) return 0; } +static int tpci200_slot_unregister(struct ipack_device *dev) +{ + struct tpci200_board *tpci200; + + if (dev == NULL) + return -ENODEV; + + tpci200 = check_slot(dev); + if (tpci200 == NULL) + return -EINVAL; + + tpci200_free_irq(dev); + + if (mutex_lock_interruptible(&tpci200->mutex)) + return -ERESTARTSYS; + + ipack_device_unregister(dev); + tpci200->slots[dev->slot].dev = NULL; + mutex_unlock(&tpci200->mutex); + + return 0; +} + static int tpci200_slot_map_space(struct ipack_device *dev, unsigned int memory_size, int space) { @@ -471,19 +654,6 @@ static int tpci200_slot_map_space(struct ipack_device *dev, phys_address = tpci200->slots[dev->slot].id_phys.address; size_to_map = tpci200->slots[dev->slot].id_phys.size; break; - case IPACK_INT_SPACE: - if (dev->int_space.address != NULL) { - dev_err(&dev->dev, - "Slot [%d:%d] INT space already mapped !\n", - tpci200->number, dev->slot); - res = -EINVAL; - goto out_unlock; - } - virt_addr_space = &dev->int_space; - - phys_address = tpci200->slots[dev->slot].int_phys.address; - size_to_map = tpci200->slots[dev->slot].int_phys.size; - break; case IPACK_MEM_SPACE: if (dev->mem_space.address != NULL) { dev_err(&dev->dev, @@ -515,109 +685,85 @@ static int tpci200_slot_map_space(struct ipack_device *dev, virt_addr_space->size = size_to_map; virt_addr_space->address = - ioremap_nocache((unsigned long)phys_address, size_to_map); + ioremap((unsigned long)phys_address, size_to_map); out_unlock: mutex_unlock(&tpci200->mutex); return res; } -static int tpci200_get_clockrate(struct ipack_device *dev) +static int tpci200_request_irq(struct ipack_device *dev, int vector, + int (*handler)(void *), void *arg) { - struct tpci200_board *tpci200 = check_slot(dev); - __le16 __iomem *addr; - - if (!tpci200) - return -ENODEV; - - addr = &tpci200->info->interface_regs->control[dev->slot]; - return (ioread16(addr) & TPCI200_CLK32) ? 32 : 8; -} - -static int tpci200_set_clockrate(struct ipack_device *dev, int mherz) -{ - struct tpci200_board *tpci200 = check_slot(dev); - __le16 __iomem *addr; - - if (!tpci200) - return -ENODEV; - - addr = &tpci200->info->interface_regs->control[dev->slot]; + int res; + struct slot_irq *slot_irq; + struct tpci200_board *tpci200; - switch (mherz) { - case 8: - tpci200_clear_mask(tpci200, addr, TPCI200_CLK32); - break; - case 32: - tpci200_set_mask(tpci200, addr, TPCI200_CLK32); - break; - default: + tpci200 = check_slot(dev); + if (tpci200 == NULL) return -EINVAL; - } - return 0; -} - -static int tpci200_get_error(struct ipack_device *dev) -{ - struct tpci200_board *tpci200 = check_slot(dev); - __le16 __iomem *addr; - u16 mask; - if (!tpci200) - return -ENODEV; + if (mutex_lock_interruptible(&tpci200->mutex)) + return -ERESTARTSYS; - addr = &tpci200->info->interface_regs->status; - mask = tpci200_status_error[dev->slot]; - return (ioread16(addr) & mask) ? 1 : 0; -} + if (tpci200->slots[dev->slot].irq != NULL) { + dev_err(&dev->dev, + "Slot [%d:%d] IRQ already registered !\n", dev->bus_nr, + dev->slot); + res = -EINVAL; + goto out_unlock; + } -static int tpci200_get_timeout(struct ipack_device *dev) -{ - struct tpci200_board *tpci200 = check_slot(dev); - __le16 __iomem *addr; - u16 mask; + slot_irq = kzalloc(sizeof(struct slot_irq), GFP_KERNEL); + if (slot_irq == NULL) { + dev_err(&dev->dev, + "Slot [%d:%d] unable to allocate memory for IRQ !\n", + dev->bus_nr, dev->slot); + res = -ENOMEM; + goto out_unlock; + } - if (!tpci200) - return -ENODEV; + /* + * WARNING: Setup Interrupt Vector in the IndustryPack device + * before an IRQ request. + * Read the User Manual of your IndustryPack device to know + * where to write the vector in memory. + */ + slot_irq->vector = vector; + slot_irq->handler = handler; + slot_irq->arg = arg; - addr = &tpci200->info->interface_regs->status; - mask = tpci200_status_timeout[dev->slot]; + tpci200->slots[dev->slot].irq = slot_irq; + res = __tpci200_request_irq(tpci200, dev); - return (ioread16(addr) & mask) ? 1 : 0; +out_unlock: + mutex_unlock(&tpci200->mutex); + return res; } -static int tpci200_reset_timeout(struct ipack_device *dev) +static void tpci200_uninstall(struct tpci200_board *tpci200) { - struct tpci200_board *tpci200 = check_slot(dev); - __le16 __iomem *addr; - u16 mask; - - if (!tpci200) - return -ENODEV; - - addr = &tpci200->info->interface_regs->status; - mask = tpci200_status_timeout[dev->slot]; + int i; - iowrite16(mask, addr); - return 0; -} + for (i = 0; i < TPCI200_NB_SLOT; i++) + tpci200_slot_unregister(tpci200->slots[i].dev); -static void tpci200_uninstall(struct tpci200_board *tpci200) -{ tpci200_unregister(tpci200); kfree(tpci200->slots); } -static const struct ipack_bus_ops tpci200_bus_ops = { +static struct ipack_bus_ops tpci200_bus_ops = { .map_space = tpci200_slot_map_space, .unmap_space = tpci200_slot_unmap_space, .request_irq = tpci200_request_irq, .free_irq = tpci200_free_irq, - .get_clockrate = tpci200_get_clockrate, - .set_clockrate = tpci200_set_clockrate, - .get_error = tpci200_get_error, - .get_timeout = tpci200_get_timeout, - .reset_timeout = tpci200_reset_timeout, + .read8 = tpci200_read8, + .read16 = tpci200_read16, + .read32 = tpci200_read32, + .write8 = tpci200_write8, + .write16 = tpci200_write16, + .write32 = tpci200_write32, + .remove_device = tpci200_slot_unregister, }; static int tpci200_install(struct tpci200_board *tpci200) @@ -640,12 +786,11 @@ static int tpci200_install(struct tpci200_board *tpci200) return 0; } -static int tpci200_pci_probe(struct pci_dev *pdev, - const struct pci_device_id *id) +static int tpci200_pciprobe(struct pci_dev *pdev, + const struct pci_device_id *id) { int ret, i; struct tpci200_board *tpci200; - u32 reg32; tpci200 = kzalloc(sizeof(struct tpci200_board), GFP_KERNEL); if (!tpci200) @@ -653,40 +798,10 @@ static int tpci200_pci_probe(struct pci_dev *pdev, tpci200->info = kzalloc(sizeof(struct tpci200_infos), GFP_KERNEL); if (!tpci200->info) { - ret = -ENOMEM; - goto out_err_info; - } - - pci_dev_get(pdev); - - /* Obtain a mapping of the carrier's PCI configuration registers */ - ret = pci_request_region(pdev, TPCI200_CFG_MEM_BAR, - KBUILD_MODNAME " Configuration Memory"); - if (ret) { - dev_err(&pdev->dev, "Failed to allocate PCI Configuration Memory"); - ret = -EBUSY; - goto out_err_pci_request; - } - tpci200->info->cfg_regs = ioremap_nocache( - pci_resource_start(pdev, TPCI200_CFG_MEM_BAR), - pci_resource_len(pdev, TPCI200_CFG_MEM_BAR)); - if (!tpci200->info->cfg_regs) { - dev_err(&pdev->dev, "Failed to map PCI Configuration Memory"); - ret = -EFAULT; - goto out_err_ioremap; + kfree(tpci200); + return -ENOMEM; } - /* Disable byte swapping for 16 bit IP module access. This will ensure - * that the Industrypack big endian byte order is preserved by the - * carrier. */ - reg32 = ioread32(tpci200->info->cfg_regs + LAS1_DESC); - reg32 |= 1 << LAS_BIT_BIGENDIAN; - iowrite32(reg32, tpci200->info->cfg_regs + LAS1_DESC); - - reg32 = ioread32(tpci200->info->cfg_regs + LAS2_DESC); - reg32 |= 1 << LAS_BIT_BIGENDIAN; - iowrite32(reg32, tpci200->info->cfg_regs + LAS2_DESC); - /* Save struct pci_dev pointer */ tpci200->info->pdev = pdev; tpci200->info->id_table = (struct pci_device_id *)id; @@ -694,9 +809,10 @@ static int tpci200_pci_probe(struct pci_dev *pdev, /* register the device and initialize it */ ret = tpci200_install(tpci200); if (ret) { - dev_err(&pdev->dev, "error during tpci200 install\n"); - ret = -ENODEV; - goto out_err_install; + dev_err(&pdev->dev, "Error during tpci200 install !\n"); + kfree(tpci200->info); + kfree(tpci200); + return -ENODEV; } /* Register the carrier in the industry pack bus driver */ @@ -706,46 +822,48 @@ static int tpci200_pci_probe(struct pci_dev *pdev, if (!tpci200->info->ipack_bus) { dev_err(&pdev->dev, "error registering the carrier on ipack driver\n"); - ret = -EFAULT; - goto out_err_bus_register; + tpci200_uninstall(tpci200); + kfree(tpci200->info); + kfree(tpci200); + return -EFAULT; } /* save the bus number given by ipack to logging purpose */ tpci200->number = tpci200->info->ipack_bus->bus_nr; dev_set_drvdata(&pdev->dev, tpci200); + /* add the registered device in an internal linked list */ + list_add_tail(&tpci200->list, &tpci200_list); + /* + * Give the same IRQ number as the slot number. + * The TPCI200 has assigned his own two IRQ by PCI bus driver + */ for (i = 0; i < TPCI200_NB_SLOT; i++) - ipack_device_register(tpci200->info->ipack_bus, i); - return 0; - -out_err_bus_register: - tpci200_uninstall(tpci200); -out_err_install: - iounmap(tpci200->info->cfg_regs); -out_err_ioremap: - pci_release_region(pdev, TPCI200_CFG_MEM_BAR); -out_err_pci_request: - pci_dev_put(pdev); - kfree(tpci200->info); -out_err_info: - kfree(tpci200); + tpci200->slots[i].dev = + ipack_device_register(tpci200->info->ipack_bus, i, i); return ret; } static void __tpci200_pci_remove(struct tpci200_board *tpci200) { - ipack_bus_unregister(tpci200->info->ipack_bus); tpci200_uninstall(tpci200); - + list_del(&tpci200->list); + ipack_bus_unregister(tpci200->info->ipack_bus); kfree(tpci200->info); kfree(tpci200); } static void __devexit tpci200_pci_remove(struct pci_dev *dev) { - struct tpci200_board *tpci200 = pci_get_drvdata(dev); + struct tpci200_board *tpci200, *next; - __tpci200_pci_remove(tpci200); + /* Search the registered device to uninstall it */ + list_for_each_entry_safe(tpci200, next, &tpci200_list, list) { + if (tpci200->info->pdev == dev) { + __tpci200_pci_remove(tpci200); + break; + } + } } static DEFINE_PCI_DEVICE_TABLE(tpci200_idtable) = { @@ -759,7 +877,7 @@ MODULE_DEVICE_TABLE(pci, tpci200_idtable); static struct pci_driver tpci200_pci_drv = { .name = "tpci200", .id_table = tpci200_idtable, - .probe = tpci200_pci_probe, + .probe = tpci200_pciprobe, .remove = __devexit_p(tpci200_pci_remove), }; @@ -770,6 +888,11 @@ static int __init tpci200_drvr_init_module(void) static void __exit tpci200_drvr_exit_module(void) { + struct tpci200_board *tpci200, *next; + + list_for_each_entry_safe(tpci200, next, &tpci200_list, list) + __tpci200_pci_remove(tpci200); + pci_unregister_driver(&tpci200_pci_drv); } diff --git a/trunk/drivers/staging/ipack/bridges/tpci200.h b/trunk/drivers/staging/ipack/bridges/tpci200.h index 235d1fe4f48c..d04510a89be4 100644 --- a/trunk/drivers/staging/ipack/bridges/tpci200.h +++ b/trunk/drivers/staging/ipack/bridges/tpci200.h @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -30,21 +31,18 @@ #define TPCI200_SUBVENDOR_ID 0x1498 #define TPCI200_SUBDEVICE_ID 0x300A -#define TPCI200_CFG_MEM_BAR 0 #define TPCI200_IP_INTERFACE_BAR 2 #define TPCI200_IO_ID_INT_SPACES_BAR 3 #define TPCI200_MEM16_SPACE_BAR 4 #define TPCI200_MEM8_SPACE_BAR 5 -struct tpci200_regs { - __le16 revision; - /* writes to control should occur with the mutex held to protect - * read-modify-write operations */ - __le16 control[4]; - __le16 reset; - __le16 status; - u8 reserved[242]; -} __packed; +#define TPCI200_REVISION_REG 0x00 +#define TPCI200_CONTROL_A_REG 0x02 +#define TPCI200_CONTROL_B_REG 0x04 +#define TPCI200_CONTROL_C_REG 0x06 +#define TPCI200_CONTROL_D_REG 0x08 +#define TPCI200_RESET_REG 0x0A +#define TPCI200_STATUS_REG 0x0C #define TPCI200_IFACE_SIZE 0x100 @@ -64,7 +62,6 @@ struct tpci200_regs { #define TPCI200_MEM16_GAP 0x00800000 #define TPCI200_MEM16_SIZE 0x00800000 -/* control field in tpci200_regs */ #define TPCI200_INT0_EN 0x0040 #define TPCI200_INT1_EN 0x0080 #define TPCI200_INT0_EDGE 0x0010 @@ -74,13 +71,11 @@ struct tpci200_regs { #define TPCI200_RECOVER_EN 0x0002 #define TPCI200_CLK32 0x0001 -/* reset field in tpci200_regs */ #define TPCI200_A_RESET 0x0001 #define TPCI200_B_RESET 0x0002 #define TPCI200_C_RESET 0x0004 #define TPCI200_D_RESET 0x0008 -/* status field in tpci200_regs */ #define TPCI200_A_TIMEOUT 0x1000 #define TPCI200_B_TIMEOUT 0x2000 #define TPCI200_C_TIMEOUT 0x4000 @@ -102,13 +97,6 @@ struct tpci200_regs { #define TPCI200_SLOT_INT_MASK 0x00FF -/* PCI Configuration registers. The PCI bridge is a PLX Technology PCI9030. */ -#define LAS1_DESC 0x2C -#define LAS2_DESC 0x30 - -/* Bits in the LAS?_DESC registers */ -#define LAS_BIT_BIGENDIAN 24 - #define VME_IOID_SPACE "IOID" #define VME_MEM_SPACE "MEM" @@ -120,9 +108,8 @@ struct tpci200_regs { * */ struct slot_irq { - struct ipack_device *holder; int vector; - irqreturn_t (*handler)(void *); + int (*handler)(void *); void *arg; }; @@ -132,15 +119,14 @@ struct slot_irq { * @irq Slot IRQ infos * @io_phys IO physical base address register of the slot * @id_phys ID physical base address register of the slot - * @int_phys INT physical base address register of the slot * @mem_phys MEM physical base address register of the slot * */ struct tpci200_slot { + struct ipack_device *dev; struct slot_irq *irq; struct ipack_addr_space io_phys; struct ipack_addr_space id_phys; - struct ipack_addr_space int_phys; struct ipack_addr_space mem_phys; }; @@ -155,16 +141,15 @@ struct tpci200_slot { struct tpci200_infos { struct pci_dev *pdev; struct pci_device_id *id_table; - struct tpci200_regs __iomem *interface_regs; + void __iomem *interface_regs; void __iomem *ioidint_space; void __iomem *mem8_space; - void __iomem *cfg_regs; struct ipack_bus_device *ipack_bus; }; struct tpci200_board { + struct list_head list; unsigned int number; struct mutex mutex; - spinlock_t regs_lock; struct tpci200_slot *slots; struct tpci200_infos *info; }; diff --git a/trunk/drivers/staging/ipack/devices/ipoctal.c b/trunk/drivers/staging/ipack/devices/ipoctal.c index d751edfda839..fd0e30132ca2 100644 --- a/trunk/drivers/staging/ipack/devices/ipoctal.c +++ b/trunk/drivers/staging/ipack/devices/ipoctal.c @@ -20,68 +20,127 @@ #include #include #include -#include #include "../ipack.h" #include "ipoctal.h" #include "scc2698.h" +#define IP_OCTAL_MANUFACTURER_ID 0xF0 +#define IP_OCTAL_232_ID 0x22 +#define IP_OCTAL_422_ID 0x2A +#define IP_OCTAL_485_ID 0x48 + #define IP_OCTAL_ID_SPACE_VECTOR 0x41 #define IP_OCTAL_NB_BLOCKS 4 +static struct ipack_driver driver; static const struct tty_operations ipoctal_fops; -struct ipoctal_channel { - struct ipoctal_stats stats; - unsigned int nb_bytes; - wait_queue_head_t queue; - spinlock_t lock; - unsigned int pointer_read; - unsigned int pointer_write; - atomic_t open; - struct tty_port tty_port; - union scc2698_channel __iomem *regs; - union scc2698_block __iomem *block_regs; - unsigned int board_id; - unsigned char *board_write; - u8 isr_rx_rdy_mask; - u8 isr_tx_rdy_mask; -}; - struct ipoctal { + struct list_head list; struct ipack_device *dev; unsigned int board_id; - struct ipoctal_channel channel[NR_CHANNELS]; + struct scc2698_channel *chan_regs; + struct scc2698_block *block_regs; + struct ipoctal_stats chan_stats[NR_CHANNELS]; + unsigned int nb_bytes[NR_CHANNELS]; + unsigned int count_wr[NR_CHANNELS]; + wait_queue_head_t queue[NR_CHANNELS]; + spinlock_t lock[NR_CHANNELS]; + unsigned int pointer_read[NR_CHANNELS]; + unsigned int pointer_write[NR_CHANNELS]; + atomic_t open[NR_CHANNELS]; unsigned char write; + struct tty_port tty_port[NR_CHANNELS]; struct tty_driver *tty_drv; }; +/* Linked list to save the registered devices */ +static LIST_HEAD(ipoctal_list); + +static inline void ipoctal_write_io_reg(struct ipoctal *ipoctal, + unsigned char *dest, + unsigned char value) +{ + unsigned long offset; + + offset = ((void __iomem *) dest) - ipoctal->dev->io_space.address; + ipoctal->dev->bus->ops->write8(ipoctal->dev, IPACK_IO_SPACE, offset, + value); +} + +static inline void ipoctal_write_cr_cmd(struct ipoctal *ipoctal, + unsigned char *dest, + unsigned char value) +{ + ipoctal_write_io_reg(ipoctal, dest, value); +} + +static inline unsigned char ipoctal_read_io_reg(struct ipoctal *ipoctal, + unsigned char *src) +{ + unsigned long offset; + unsigned char value; + + offset = ((void __iomem *) src) - ipoctal->dev->io_space.address; + ipoctal->dev->bus->ops->read8(ipoctal->dev, IPACK_IO_SPACE, offset, + &value); + return value; +} + +static struct ipoctal *ipoctal_find_board(struct tty_struct *tty) +{ + struct ipoctal *p; + + list_for_each_entry(p, &ipoctal_list, list) { + if (tty->driver->major == p->tty_drv->major) + return p; + } + + return NULL; +} + static int ipoctal_port_activate(struct tty_port *port, struct tty_struct *tty) { - struct ipoctal_channel *channel; + struct ipoctal *ipoctal; + int channel = tty->index; - channel = dev_get_drvdata(tty->dev); + ipoctal = ipoctal_find_board(tty); - iowrite8(CR_ENABLE_RX, &channel->regs->w.cr); + if (ipoctal == NULL) { + dev_err(tty->dev, "Device not found. Major %d\n", + tty->driver->major); + return -ENODEV; + } + + ipoctal_write_io_reg(ipoctal, &ipoctal->chan_regs[channel].u.w.cr, + CR_ENABLE_RX); return 0; } static int ipoctal_open(struct tty_struct *tty, struct file *file) { + int channel = tty->index; int res; - struct ipoctal_channel *channel; + struct ipoctal *ipoctal; - channel = dev_get_drvdata(tty->dev); + ipoctal = ipoctal_find_board(tty); + + if (ipoctal == NULL) { + dev_err(tty->dev, "Device not found. Major %d\n", + tty->driver->major); + return -ENODEV; + } - if (atomic_read(&channel->open)) + if (atomic_read(&ipoctal->open[channel])) return -EBUSY; - tty->driver_data = channel; + tty->driver_data = ipoctal; - res = tty_port_open(&channel->tty_port, tty, file); + res = tty_port_open(&ipoctal->tty_port[channel], tty, file); if (res) return res; - atomic_inc(&channel->open); + atomic_inc(&ipoctal->open[channel]); return 0; } @@ -95,166 +154,175 @@ static void ipoctal_reset_stats(struct ipoctal_stats *stats) stats->parity_err = 0; } -static void ipoctal_free_channel(struct ipoctal_channel *channel) +static void ipoctal_free_channel(struct tty_struct *tty) { - ipoctal_reset_stats(&channel->stats); - channel->pointer_read = 0; - channel->pointer_write = 0; - channel->nb_bytes = 0; + int channel = tty->index; + struct ipoctal *ipoctal = tty->driver_data; + + if (ipoctal == NULL) + return; + + ipoctal_reset_stats(&ipoctal->chan_stats[channel]); + ipoctal->pointer_read[channel] = 0; + ipoctal->pointer_write[channel] = 0; + ipoctal->nb_bytes[channel] = 0; } static void ipoctal_close(struct tty_struct *tty, struct file *filp) { - struct ipoctal_channel *channel = tty->driver_data; + int channel = tty->index; + struct ipoctal *ipoctal = tty->driver_data; - tty_port_close(&channel->tty_port, tty, filp); + tty_port_close(&ipoctal->tty_port[channel], tty, filp); - if (atomic_dec_and_test(&channel->open)) - ipoctal_free_channel(channel); + if (atomic_dec_and_test(&ipoctal->open[channel])) + ipoctal_free_channel(tty); } static int ipoctal_get_icount(struct tty_struct *tty, struct serial_icounter_struct *icount) { - struct ipoctal_channel *channel = tty->driver_data; + struct ipoctal *ipoctal = tty->driver_data; + int channel = tty->index; icount->cts = 0; icount->dsr = 0; icount->rng = 0; icount->dcd = 0; - icount->rx = channel->stats.rx; - icount->tx = channel->stats.tx; - icount->frame = channel->stats.framing_err; - icount->parity = channel->stats.parity_err; - icount->brk = channel->stats.rcv_break; + icount->rx = ipoctal->chan_stats[channel].rx; + icount->tx = ipoctal->chan_stats[channel].tx; + icount->frame = ipoctal->chan_stats[channel].framing_err; + icount->parity = ipoctal->chan_stats[channel].parity_err; + icount->brk = ipoctal->chan_stats[channel].rcv_break; return 0; } -static void ipoctal_irq_rx(struct ipoctal_channel *channel, - struct tty_struct *tty, u8 sr) +static int ipoctal_irq_handler(void *arg) { + unsigned int channel; + unsigned int block; + unsigned char isr; + unsigned char sr; + unsigned char isr_tx_rdy, isr_rx_rdy; unsigned char value; - unsigned char flag = TTY_NORMAL; - u8 isr; - - do { - value = ioread8(&channel->regs->r.rhr); - /* Error: count statistics */ - if (sr & SR_ERROR) { - iowrite8(CR_CMD_RESET_ERR_STATUS, &channel->regs->w.cr); - - if (sr & SR_OVERRUN_ERROR) { - channel->stats.overrun_err++; - /* Overrun doesn't affect the current character*/ - tty_insert_flip_char(tty, 0, TTY_OVERRUN); - } - if (sr & SR_PARITY_ERROR) { - channel->stats.parity_err++; - flag = TTY_PARITY; - } - if (sr & SR_FRAMING_ERROR) { - channel->stats.framing_err++; - flag = TTY_FRAME; - } - if (sr & SR_RECEIVED_BREAK) { - iowrite8(CR_CMD_RESET_BREAK_CHANGE, &channel->regs->w.cr); - channel->stats.rcv_break++; - flag = TTY_BREAK; - } - } - tty_insert_flip_char(tty, value, flag); - - /* Check if there are more characters in RX FIFO - * If there are more, the isr register for this channel - * has enabled the RxRDY|FFULL bit. - */ - isr = ioread8(&channel->block_regs->r.isr); - sr = ioread8(&channel->regs->r.sr); - } while (isr & channel->isr_rx_rdy_mask); - - tty_flip_buffer_push(tty); -} - -static void ipoctal_irq_tx(struct ipoctal_channel *channel) -{ - unsigned char value; - unsigned int *pointer_write = &channel->pointer_write; - - if (channel->nb_bytes <= 0) { - channel->nb_bytes = 0; - return; - } + unsigned char flag; + struct tty_struct *tty; + struct ipoctal *ipoctal = (struct ipoctal *) arg; - value = channel->tty_port.xmit_buf[*pointer_write]; - iowrite8(value, &channel->regs->w.thr); - channel->stats.tx++; - (*pointer_write)++; - *pointer_write = *pointer_write % PAGE_SIZE; - channel->nb_bytes--; + /* Check all channels */ + for (channel = 0; channel < NR_CHANNELS; channel++) { + /* If there is no client, skip the check */ + if (!atomic_read(&ipoctal->open[channel])) + continue; - if ((channel->nb_bytes == 0) && - (waitqueue_active(&channel->queue))) { + tty = tty_port_tty_get(&ipoctal->tty_port[channel]); + if (!tty) + continue; - if (channel->board_id != IPACK1_DEVICE_ID_SBS_OCTAL_485) { - *channel->board_write = 1; - wake_up_interruptible(&channel->queue); + /* + * The HW is organized in pair of channels. + * See which register we need to read from + */ + block = channel / 2; + isr = ipoctal_read_io_reg(ipoctal, + &ipoctal->block_regs[block].u.r.isr); + sr = ipoctal_read_io_reg(ipoctal, + &ipoctal->chan_regs[channel].u.r.sr); + + if ((channel % 2) == 1) { + isr_tx_rdy = isr & ISR_TxRDY_B; + isr_rx_rdy = isr & ISR_RxRDY_FFULL_B; + } else { + isr_tx_rdy = isr & ISR_TxRDY_A; + isr_rx_rdy = isr & ISR_RxRDY_FFULL_A; } - } -} - -static void ipoctal_irq_channel(struct ipoctal_channel *channel) -{ - u8 isr, sr; - struct tty_struct *tty; - /* If there is no client, skip the check */ - if (!atomic_read(&channel->open)) - return; - - tty = tty_port_tty_get(&channel->tty_port); - if (!tty) - return; - /* The HW is organized in pair of channels. See which register we need - * to read from */ - isr = ioread8(&channel->block_regs->r.isr); - sr = ioread8(&channel->regs->r.sr); - - /* In case of RS-485, change from TX to RX when finishing TX. - * Half-duplex. */ - if ((channel->board_id == IPACK1_DEVICE_ID_SBS_OCTAL_485) && - (sr & SR_TX_EMPTY) && (channel->nb_bytes == 0)) { - iowrite8(CR_DISABLE_TX, &channel->regs->w.cr); - iowrite8(CR_CMD_NEGATE_RTSN, &channel->regs->w.cr); - iowrite8(CR_ENABLE_RX, &channel->regs->w.cr); - *channel->board_write = 1; - wake_up_interruptible(&channel->queue); - } - - /* RX data */ - if ((isr & channel->isr_rx_rdy_mask) && (sr & SR_RX_READY)) - ipoctal_irq_rx(channel, tty, sr); + /* In case of RS-485, change from TX to RX when finishing TX. + * Half-duplex. + */ + if ((ipoctal->board_id == IP_OCTAL_485_ID) && + (sr & SR_TX_EMPTY) && + (ipoctal->nb_bytes[channel] == 0)) { + ipoctal_write_io_reg(ipoctal, + &ipoctal->chan_regs[channel].u.w.cr, + CR_DISABLE_TX); + ipoctal_write_cr_cmd(ipoctal, + &ipoctal->chan_regs[channel].u.w.cr, + CR_CMD_NEGATE_RTSN); + ipoctal_write_io_reg(ipoctal, + &ipoctal->chan_regs[channel].u.w.cr, + CR_ENABLE_RX); + ipoctal->write = 1; + wake_up_interruptible(&ipoctal->queue[channel]); + } - /* TX of each character */ - if ((isr & channel->isr_tx_rdy_mask) && (sr & SR_TX_READY)) - ipoctal_irq_tx(channel); + /* RX data */ + if (isr_rx_rdy && (sr & SR_RX_READY)) { + value = ipoctal_read_io_reg(ipoctal, + &ipoctal->chan_regs[channel].u.r.rhr); + flag = TTY_NORMAL; + + /* Error: count statistics */ + if (sr & SR_ERROR) { + ipoctal_write_cr_cmd(ipoctal, + &ipoctal->chan_regs[channel].u.w.cr, + CR_CMD_RESET_ERR_STATUS); + + if (sr & SR_OVERRUN_ERROR) { + ipoctal->chan_stats[channel].overrun_err++; + /* Overrun doesn't affect the current character*/ + tty_insert_flip_char(tty, 0, TTY_OVERRUN); + } + if (sr & SR_PARITY_ERROR) { + ipoctal->chan_stats[channel].parity_err++; + flag = TTY_PARITY; + } + if (sr & SR_FRAMING_ERROR) { + ipoctal->chan_stats[channel].framing_err++; + flag = TTY_FRAME; + } + if (sr & SR_RECEIVED_BREAK) { + ipoctal->chan_stats[channel].rcv_break++; + flag = TTY_BREAK; + } + } - tty_flip_buffer_push(tty); - tty_kref_put(tty); -} + tty_insert_flip_char(tty, value, flag); + } -static irqreturn_t ipoctal_irq_handler(void *arg) -{ - unsigned int i; - struct ipoctal *ipoctal = (struct ipoctal *) arg; + /* TX of each character */ + if (isr_tx_rdy && (sr & SR_TX_READY)) { + unsigned int *pointer_write = + &ipoctal->pointer_write[channel]; - /* Check all channels */ - for (i = 0; i < NR_CHANNELS; i++) - ipoctal_irq_channel(&ipoctal->channel[i]); + if (ipoctal->nb_bytes[channel] <= 0) { + ipoctal->nb_bytes[channel] = 0; + continue; + } - /* Clear the IPack device interrupt */ - readw(ipoctal->dev->int_space.address + ACK_INT_REQ0); - readw(ipoctal->dev->int_space.address + ACK_INT_REQ1); + value = ipoctal->tty_port[channel].xmit_buf[*pointer_write]; + ipoctal_write_io_reg(ipoctal, + &ipoctal->chan_regs[channel].u.w.thr, + value); + ipoctal->chan_stats[channel].tx++; + ipoctal->count_wr[channel]++; + (*pointer_write)++; + *pointer_write = *pointer_write % PAGE_SIZE; + ipoctal->nb_bytes[channel]--; + + if ((ipoctal->nb_bytes[channel] == 0) && + (waitqueue_active(&ipoctal->queue[channel]))) { + + if (ipoctal->board_id != IP_OCTAL_485_ID) { + ipoctal->write = 1; + wake_up_interruptible(&ipoctal->queue[channel]); + } + } + } + tty_flip_buffer_push(tty); + tty_kref_put(tty); + } return IRQ_HANDLED; } @@ -263,15 +331,18 @@ static int ipoctal_check_model(struct ipack_device *dev, unsigned char *id) unsigned char manufacturerID; unsigned char board_id; - - manufacturerID = ioread8(dev->id_space.address + IPACK_IDPROM_OFFSET_MANUFACTURER_ID); - if (manufacturerID != IPACK1_VENDOR_ID_SBS) + dev->bus->ops->read8(dev, IPACK_ID_SPACE, + IPACK_IDPROM_OFFSET_MANUFACTURER_ID, &manufacturerID); + if (manufacturerID != IP_OCTAL_MANUFACTURER_ID) return -ENODEV; - board_id = ioread8(dev->id_space.address + IPACK_IDPROM_OFFSET_MODEL); + + dev->bus->ops->read8(dev, IPACK_ID_SPACE, + IPACK_IDPROM_OFFSET_MODEL, (unsigned char *)&board_id); + switch (board_id) { - case IPACK1_DEVICE_ID_SBS_OCTAL_232: - case IPACK1_DEVICE_ID_SBS_OCTAL_422: - case IPACK1_DEVICE_ID_SBS_OCTAL_485: + case IP_OCTAL_232_ID: + case IP_OCTAL_422_ID: + case IP_OCTAL_485_ID: *id = board_id; break; default: @@ -287,16 +358,13 @@ static const struct tty_port_operations ipoctal_tty_port_ops = { }; static int ipoctal_inst_slot(struct ipoctal *ipoctal, unsigned int bus_nr, - unsigned int slot) + unsigned int slot, unsigned int vector) { int res = 0; int i; struct tty_driver *tty; char name[20]; unsigned char board_id; - struct ipoctal_channel *channel; - union scc2698_channel __iomem *chan_regs; - union scc2698_block __iomem *block_regs; res = ipoctal->dev->bus->ops->map_space(ipoctal->dev, 0, IPACK_ID_SPACE); @@ -324,61 +392,54 @@ static int ipoctal_inst_slot(struct ipoctal *ipoctal, unsigned int bus_nr, goto out_unregister_id_space; } - res = ipoctal->dev->bus->ops->map_space(ipoctal->dev, 0, - IPACK_INT_SPACE); - if (res) { - dev_err(&ipoctal->dev->dev, - "Unable to map slot [%d:%d] INT space!\n", - bus_nr, slot); - goto out_unregister_io_space; - } - res = ipoctal->dev->bus->ops->map_space(ipoctal->dev, 0x8000, IPACK_MEM_SPACE); if (res) { dev_err(&ipoctal->dev->dev, "Unable to map slot [%d:%d] MEM space!\n", bus_nr, slot); - goto out_unregister_int_space; + goto out_unregister_io_space; } /* Save the virtual address to access the registers easily */ - chan_regs = - (union scc2698_channel __iomem *) ipoctal->dev->io_space.address; - block_regs = - (union scc2698_block __iomem *) ipoctal->dev->io_space.address; + ipoctal->chan_regs = + (struct scc2698_channel *) ipoctal->dev->io_space.address; + ipoctal->block_regs = + (struct scc2698_block *) ipoctal->dev->io_space.address; /* Disable RX and TX before touching anything */ for (i = 0; i < NR_CHANNELS ; i++) { - struct ipoctal_channel *channel = &ipoctal->channel[i]; - channel->regs = chan_regs + i; - channel->block_regs = block_regs + (i >> 1); - channel->board_write = &ipoctal->write; - channel->board_id = ipoctal->board_id; - if (i & 1) { - channel->isr_tx_rdy_mask = ISR_TxRDY_B; - channel->isr_rx_rdy_mask = ISR_RxRDY_FFULL_B; - } else { - channel->isr_tx_rdy_mask = ISR_TxRDY_A; - channel->isr_rx_rdy_mask = ISR_RxRDY_FFULL_A; - } - - iowrite8(CR_DISABLE_RX | CR_DISABLE_TX, &channel->regs->w.cr); - iowrite8(CR_CMD_RESET_RX, &channel->regs->w.cr); - iowrite8(CR_CMD_RESET_TX, &channel->regs->w.cr); - iowrite8(MR1_CHRL_8_BITS | MR1_ERROR_CHAR | MR1_RxINT_RxRDY, - &channel->regs->w.mr); /* mr1 */ - iowrite8(0, &channel->regs->w.mr); /* mr2 */ - iowrite8(TX_CLK_9600 | RX_CLK_9600, &channel->regs->w.csr); + ipoctal_write_io_reg(ipoctal, &ipoctal->chan_regs[i].u.w.cr, + CR_DISABLE_RX | CR_DISABLE_TX); + ipoctal_write_cr_cmd(ipoctal, &ipoctal->chan_regs[i].u.w.cr, + CR_CMD_RESET_RX); + ipoctal_write_cr_cmd(ipoctal, &ipoctal->chan_regs[i].u.w.cr, + CR_CMD_RESET_TX); + ipoctal_write_io_reg(ipoctal, + &ipoctal->chan_regs[i].u.w.mr, + MR1_CHRL_8_BITS | MR1_ERROR_CHAR | + MR1_RxINT_RxRDY); /* mr1 */ + ipoctal_write_io_reg(ipoctal, + &ipoctal->chan_regs[i].u.w.mr, + 0); /* mr2 */ + ipoctal_write_io_reg(ipoctal, + &ipoctal->chan_regs[i].u.w.csr, + TX_CLK_9600 | RX_CLK_9600); } for (i = 0; i < IP_OCTAL_NB_BLOCKS; i++) { - iowrite8(ACR_BRG_SET2, &block_regs[i].w.acr); - iowrite8(OPCR_MPP_OUTPUT | OPCR_MPOa_RTSN | OPCR_MPOb_RTSN, - &block_regs[i].w.opcr); - iowrite8(IMR_TxRDY_A | IMR_RxRDY_FFULL_A | IMR_DELTA_BREAK_A | - IMR_TxRDY_B | IMR_RxRDY_FFULL_B | IMR_DELTA_BREAK_B, - &block_regs[i].w.imr); + ipoctal_write_io_reg(ipoctal, + &ipoctal->block_regs[i].u.w.acr, + ACR_BRG_SET2); + ipoctal_write_io_reg(ipoctal, + &ipoctal->block_regs[i].u.w.opcr, + OPCR_MPP_OUTPUT | OPCR_MPOa_RTSN | + OPCR_MPOb_RTSN); + ipoctal_write_io_reg(ipoctal, + &ipoctal->block_regs[i].u.w.imr, + IMR_TxRDY_A | IMR_RxRDY_FFULL_A | + IMR_DELTA_BREAK_A | IMR_TxRDY_B | + IMR_RxRDY_FFULL_B | IMR_DELTA_BREAK_B); } /* @@ -386,10 +447,10 @@ static int ipoctal_inst_slot(struct ipoctal *ipoctal, unsigned int bus_nr, * Depending of the carrier these addresses are accesible or not. * More info in the datasheet. */ - ipoctal->dev->bus->ops->request_irq(ipoctal->dev, + ipoctal->dev->bus->ops->request_irq(ipoctal->dev, vector, ipoctal_irq_handler, ipoctal); - /* Dummy write */ - iowrite8(1, ipoctal->dev->mem_space.address + 1); + ipoctal->dev->bus->ops->write8(ipoctal->dev, IPACK_MEM_SPACE, 0, + vector); /* Register the TTY device */ @@ -403,8 +464,8 @@ static int ipoctal_inst_slot(struct ipoctal *ipoctal, unsigned int bus_nr, /* Fill struct tty_driver with ipoctal data */ tty->owner = THIS_MODULE; - tty->driver_name = KBUILD_MODNAME; - sprintf(name, KBUILD_MODNAME ".%d.%d.", bus_nr, slot); + tty->driver_name = "ipoctal"; + sprintf(name, "ipoctal.%d.%d.", bus_nr, slot); tty->name = name; tty->major = 0; @@ -429,40 +490,32 @@ static int ipoctal_inst_slot(struct ipoctal *ipoctal, unsigned int bus_nr, ipoctal->tty_drv = tty; for (i = 0; i < NR_CHANNELS; i++) { - struct device *tty_dev; - - channel = &ipoctal->channel[i]; - tty_port_init(&channel->tty_port); - tty_port_alloc_xmit_buf(&channel->tty_port); - channel->tty_port.ops = &ipoctal_tty_port_ops; - - ipoctal_reset_stats(&channel->stats); - channel->nb_bytes = 0; - init_waitqueue_head(&channel->queue); - - spin_lock_init(&channel->lock); - channel->pointer_read = 0; - channel->pointer_write = 0; - tty_dev = tty_port_register_device(&channel->tty_port, tty, i, NULL); - if (IS_ERR(tty_dev)) { - dev_err(&ipoctal->dev->dev, "Failed to register tty device.\n"); - continue; - } - dev_set_drvdata(tty_dev, channel); + tty_port_init(&ipoctal->tty_port[i]); + tty_port_alloc_xmit_buf(&ipoctal->tty_port[i]); + ipoctal->tty_port[i].ops = &ipoctal_tty_port_ops; + + ipoctal_reset_stats(&ipoctal->chan_stats[i]); + ipoctal->nb_bytes[i] = 0; + init_waitqueue_head(&ipoctal->queue[i]); + + spin_lock_init(&ipoctal->lock[i]); + ipoctal->pointer_read[i] = 0; + ipoctal->pointer_write[i] = 0; + ipoctal->nb_bytes[i] = 0; + tty_register_device(tty, i, NULL); /* * Enable again the RX. TX will be enabled when * there is something to send */ - iowrite8(CR_ENABLE_RX, &channel->regs->w.cr); + ipoctal_write_io_reg(ipoctal, &ipoctal->chan_regs[i].u.w.cr, + CR_ENABLE_RX); } return 0; out_unregister_slot_unmap: ipoctal->dev->bus->ops->unmap_space(ipoctal->dev, IPACK_ID_SPACE); -out_unregister_int_space: - ipoctal->dev->bus->ops->unmap_space(ipoctal->dev, IPACK_INT_SPACE); out_unregister_io_space: ipoctal->dev->bus->ops->unmap_space(ipoctal->dev, IPACK_IO_SPACE); out_unregister_id_space: @@ -470,22 +523,23 @@ static int ipoctal_inst_slot(struct ipoctal *ipoctal, unsigned int bus_nr, return res; } -static inline int ipoctal_copy_write_buffer(struct ipoctal_channel *channel, +static inline int ipoctal_copy_write_buffer(struct ipoctal *ipoctal, + unsigned int channel, const unsigned char *buf, int count) { unsigned long flags; int i; - unsigned int *pointer_read = &channel->pointer_read; + unsigned int *pointer_read = &ipoctal->pointer_read[channel]; /* Copy the bytes from the user buffer to the internal one */ for (i = 0; i < count; i++) { - if (i <= (PAGE_SIZE - channel->nb_bytes)) { - spin_lock_irqsave(&channel->lock, flags); - channel->tty_port.xmit_buf[*pointer_read] = buf[i]; + if (i <= (PAGE_SIZE - ipoctal->nb_bytes[channel])) { + spin_lock_irqsave(&ipoctal->lock[channel], flags); + ipoctal->tty_port[channel].xmit_buf[*pointer_read] = buf[i]; *pointer_read = (*pointer_read + 1) % PAGE_SIZE; - channel->nb_bytes++; - spin_unlock_irqrestore(&channel->lock, flags); + ipoctal->nb_bytes[channel]++; + spin_unlock_irqrestore(&ipoctal->lock[channel], flags); } else { break; } @@ -493,44 +547,63 @@ static inline int ipoctal_copy_write_buffer(struct ipoctal_channel *channel, return i; } -static int ipoctal_write_tty(struct tty_struct *tty, - const unsigned char *buf, int count) +static int ipoctal_write(struct ipoctal *ipoctal, unsigned int channel, + const unsigned char *buf, int count) { - struct ipoctal_channel *channel = tty->driver_data; - unsigned int char_copied; + ipoctal->nb_bytes[channel] = 0; + ipoctal->count_wr[channel] = 0; - char_copied = ipoctal_copy_write_buffer(channel, buf, count); + ipoctal_copy_write_buffer(ipoctal, channel, buf, count); /* As the IP-OCTAL 485 only supports half duplex, do it manually */ - if (channel->board_id == IPACK1_DEVICE_ID_SBS_OCTAL_485) { - iowrite8(CR_DISABLE_RX, &channel->regs->w.cr); - iowrite8(CR_CMD_ASSERT_RTSN, &channel->regs->w.cr); + if (ipoctal->board_id == IP_OCTAL_485_ID) { + ipoctal_write_io_reg(ipoctal, + &ipoctal->chan_regs[channel].u.w.cr, + CR_DISABLE_RX); + ipoctal_write_cr_cmd(ipoctal, + &ipoctal->chan_regs[channel].u.w.cr, + CR_CMD_ASSERT_RTSN); } /* * Send a packet and then disable TX to avoid failure after several send * operations */ - iowrite8(CR_ENABLE_TX, &channel->regs->w.cr); - wait_event_interruptible(channel->queue, *channel->board_write); - iowrite8(CR_DISABLE_TX, &channel->regs->w.cr); + ipoctal_write_io_reg(ipoctal, + &ipoctal->chan_regs[channel].u.w.cr, + CR_ENABLE_TX); + wait_event_interruptible(ipoctal->queue[channel], ipoctal->write); + ipoctal_write_io_reg(ipoctal, + &ipoctal->chan_regs[channel].u.w.cr, + CR_DISABLE_TX); + + ipoctal->write = 0; + return ipoctal->count_wr[channel]; +} + +static int ipoctal_write_tty(struct tty_struct *tty, + const unsigned char *buf, int count) +{ + unsigned int channel = tty->index; + struct ipoctal *ipoctal = tty->driver_data; - *channel->board_write = 0; - return char_copied; + return ipoctal_write(ipoctal, channel, buf, count); } static int ipoctal_write_room(struct tty_struct *tty) { - struct ipoctal_channel *channel = tty->driver_data; + int channel = tty->index; + struct ipoctal *ipoctal = tty->driver_data; - return PAGE_SIZE - channel->nb_bytes; + return PAGE_SIZE - ipoctal->nb_bytes[channel]; } static int ipoctal_chars_in_buffer(struct tty_struct *tty) { - struct ipoctal_channel *channel = tty->driver_data; + int channel = tty->index; + struct ipoctal *ipoctal = tty->driver_data; - return channel->nb_bytes; + return ipoctal->nb_bytes[channel]; } static void ipoctal_set_termios(struct tty_struct *tty, @@ -540,17 +613,23 @@ static void ipoctal_set_termios(struct tty_struct *tty, unsigned char mr1 = 0; unsigned char mr2 = 0; unsigned char csr = 0; - struct ipoctal_channel *channel = tty->driver_data; + unsigned int channel = tty->index; + struct ipoctal *ipoctal = tty->driver_data; speed_t baud; - cflag = tty->termios.c_cflag; + cflag = tty->termios->c_cflag; /* Disable and reset everything before change the setup */ - iowrite8(CR_DISABLE_RX | CR_DISABLE_TX, &channel->regs->w.cr); - iowrite8(CR_CMD_RESET_RX, &channel->regs->w.cr); - iowrite8(CR_CMD_RESET_TX, &channel->regs->w.cr); - iowrite8(CR_CMD_RESET_ERR_STATUS, &channel->regs->w.cr); - iowrite8(CR_CMD_RESET_MR, &channel->regs->w.cr); + ipoctal_write_io_reg(ipoctal, &ipoctal->chan_regs[channel].u.w.cr, + CR_DISABLE_RX | CR_DISABLE_TX); + ipoctal_write_cr_cmd(ipoctal, &ipoctal->chan_regs[channel].u.w.cr, + CR_CMD_RESET_RX); + ipoctal_write_cr_cmd(ipoctal, &ipoctal->chan_regs[channel].u.w.cr, + CR_CMD_RESET_TX); + ipoctal_write_cr_cmd(ipoctal, &ipoctal->chan_regs[channel].u.w.cr, + CR_CMD_RESET_ERR_STATUS); + ipoctal_write_cr_cmd(ipoctal, &ipoctal->chan_regs[channel].u.w.cr, + CR_CMD_RESET_MR); /* Set Bits per chars */ switch (cflag & CSIZE) { @@ -564,7 +643,7 @@ static void ipoctal_set_termios(struct tty_struct *tty, default: mr1 |= MR1_CHRL_8_BITS; /* By default, select CS8 */ - tty->termios.c_cflag = (cflag & ~CSIZE) | CS8; + tty->termios->c_cflag = (cflag & ~CSIZE) | CS8; break; } @@ -578,7 +657,7 @@ static void ipoctal_set_termios(struct tty_struct *tty, mr1 |= MR1_PARITY_OFF; /* Mark or space parity is not supported */ - tty->termios.c_cflag &= ~CMSPAR; + tty->termios->c_cflag &= ~CMSPAR; /* Set stop bits */ if (cflag & CSTOPB) @@ -587,8 +666,8 @@ static void ipoctal_set_termios(struct tty_struct *tty, mr2 |= MR2_STOP_BITS_LENGTH_1; /* Set the flow control */ - switch (channel->board_id) { - case IPACK1_DEVICE_ID_SBS_OCTAL_232: + switch (ipoctal->board_id) { + case IP_OCTAL_232_ID: if (cflag & CRTSCTS) { mr1 |= MR1_RxRTS_CONTROL_ON; mr2 |= MR2_TxRTS_CONTROL_OFF | MR2_CTS_ENABLE_TX_ON; @@ -597,11 +676,11 @@ static void ipoctal_set_termios(struct tty_struct *tty, mr2 |= MR2_TxRTS_CONTROL_OFF | MR2_CTS_ENABLE_TX_OFF; } break; - case IPACK1_DEVICE_ID_SBS_OCTAL_422: + case IP_OCTAL_422_ID: mr1 |= MR1_RxRTS_CONTROL_OFF; mr2 |= MR2_TxRTS_CONTROL_OFF | MR2_CTS_ENABLE_TX_OFF; break; - case IPACK1_DEVICE_ID_SBS_OCTAL_485: + case IP_OCTAL_485_ID: mr1 |= MR1_RxRTS_CONTROL_OFF; mr2 |= MR2_TxRTS_CONTROL_ON | MR2_CTS_ENABLE_TX_OFF; break; @@ -611,10 +690,10 @@ static void ipoctal_set_termios(struct tty_struct *tty, } baud = tty_get_baud_rate(tty); - tty_termios_encode_baud_rate(&tty->termios, baud, baud); + tty_termios_encode_baud_rate(tty->termios, baud, baud); /* Set baud rate */ - switch (baud) { + switch (tty->termios->c_ospeed) { case 75: csr |= TX_CLK_75 | RX_CLK_75; break; @@ -655,7 +734,7 @@ static void ipoctal_set_termios(struct tty_struct *tty, default: csr |= TX_CLK_38400 | RX_CLK_38400; /* In case of default, we establish 38400 bps */ - tty_termios_encode_baud_rate(&tty->termios, 38400, 38400); + tty_termios_encode_baud_rate(tty->termios, 38400, 38400); break; } @@ -663,38 +742,45 @@ static void ipoctal_set_termios(struct tty_struct *tty, mr1 |= MR1_RxINT_RxRDY; /* Write the control registers */ - iowrite8(mr1, &channel->regs->w.mr); - iowrite8(mr2, &channel->regs->w.mr); - iowrite8(csr, &channel->regs->w.csr); + ipoctal_write_io_reg(ipoctal, &ipoctal->chan_regs[channel].u.w.mr, mr1); + ipoctal_write_io_reg(ipoctal, &ipoctal->chan_regs[channel].u.w.mr, mr2); + ipoctal_write_io_reg(ipoctal, &ipoctal->chan_regs[channel].u.w.csr, csr); /* Enable again the RX */ - iowrite8(CR_ENABLE_RX, &channel->regs->w.cr); + ipoctal_write_io_reg(ipoctal, &ipoctal->chan_regs[channel].u.w.cr, + CR_ENABLE_RX); } static void ipoctal_hangup(struct tty_struct *tty) { unsigned long flags; - struct ipoctal_channel *channel = tty->driver_data; + int channel = tty->index; + struct ipoctal *ipoctal = tty->driver_data; - if (channel == NULL) + if (ipoctal == NULL) return; - spin_lock_irqsave(&channel->lock, flags); - channel->nb_bytes = 0; - channel->pointer_read = 0; - channel->pointer_write = 0; - spin_unlock_irqrestore(&channel->lock, flags); - - tty_port_hangup(&channel->tty_port); - - iowrite8(CR_DISABLE_RX | CR_DISABLE_TX, &channel->regs->w.cr); - iowrite8(CR_CMD_RESET_RX, &channel->regs->w.cr); - iowrite8(CR_CMD_RESET_TX, &channel->regs->w.cr); - iowrite8(CR_CMD_RESET_ERR_STATUS, &channel->regs->w.cr); - iowrite8(CR_CMD_RESET_MR, &channel->regs->w.cr); - - clear_bit(ASYNCB_INITIALIZED, &channel->tty_port.flags); - wake_up_interruptible(&channel->tty_port.open_wait); + spin_lock_irqsave(&ipoctal->lock[channel], flags); + ipoctal->nb_bytes[channel] = 0; + ipoctal->pointer_read[channel] = 0; + ipoctal->pointer_write[channel] = 0; + spin_unlock_irqrestore(&ipoctal->lock[channel], flags); + + tty_port_hangup(&ipoctal->tty_port[channel]); + + ipoctal_write_io_reg(ipoctal, &ipoctal->chan_regs[channel].u.w.cr, + CR_DISABLE_RX | CR_DISABLE_TX); + ipoctal_write_cr_cmd(ipoctal, &ipoctal->chan_regs[channel].u.w.cr, + CR_CMD_RESET_RX); + ipoctal_write_cr_cmd(ipoctal, &ipoctal->chan_regs[channel].u.w.cr, + CR_CMD_RESET_TX); + ipoctal_write_cr_cmd(ipoctal, &ipoctal->chan_regs[channel].u.w.cr, + CR_CMD_RESET_ERR_STATUS); + ipoctal_write_cr_cmd(ipoctal, &ipoctal->chan_regs[channel].u.w.cr, + CR_CMD_RESET_MR); + + clear_bit(ASYNCB_INITIALIZED, &ipoctal->tty_port[channel].flags); + wake_up_interruptible(&ipoctal->tty_port[channel].open_wait); } static const struct tty_operations ipoctal_fops = { @@ -709,6 +795,27 @@ static const struct tty_operations ipoctal_fops = { .hangup = ipoctal_hangup, }; +static int ipoctal_match(struct ipack_device *dev) +{ + int res; + unsigned char board_id; + + if ((!dev->bus->ops) || (!dev->bus->ops->map_space) || + (!dev->bus->ops->unmap_space)) + return 0; + + res = dev->bus->ops->map_space(dev, 0, IPACK_ID_SPACE); + if (res) + return 0; + + res = ipoctal_check_model(dev, &board_id); + dev->bus->ops->unmap_space(dev, IPACK_ID_SPACE); + if (!res) + return 1; + + return 0; +} + static int ipoctal_probe(struct ipack_device *dev) { int res; @@ -719,11 +826,11 @@ static int ipoctal_probe(struct ipack_device *dev) return -ENOMEM; ipoctal->dev = dev; - res = ipoctal_inst_slot(ipoctal, dev->bus_nr, dev->slot); + res = ipoctal_inst_slot(ipoctal, dev->bus_nr, dev->slot, dev->irq); if (res) goto out_uninst; - dev_set_drvdata(&dev->dev, ipoctal); + list_add_tail(&ipoctal->list, &ipoctal_list); return 0; out_uninst: @@ -735,57 +842,46 @@ static void __ipoctal_remove(struct ipoctal *ipoctal) { int i; - ipoctal->dev->bus->ops->free_irq(ipoctal->dev); - for (i = 0; i < NR_CHANNELS; i++) { - struct ipoctal_channel *channel = &ipoctal->channel[i]; tty_unregister_device(ipoctal->tty_drv, i); - tty_port_free_xmit_buf(&channel->tty_port); + tty_port_free_xmit_buf(&ipoctal->tty_port[i]); } tty_unregister_driver(ipoctal->tty_drv); put_tty_driver(ipoctal->tty_drv); - ipoctal->dev->bus->ops->unmap_space(ipoctal->dev, IPACK_MEM_SPACE); - ipoctal->dev->bus->ops->unmap_space(ipoctal->dev, IPACK_INT_SPACE); - ipoctal->dev->bus->ops->unmap_space(ipoctal->dev, IPACK_IO_SPACE); - ipoctal->dev->bus->ops->unmap_space(ipoctal->dev, IPACK_ID_SPACE); + list_del(&ipoctal->list); kfree(ipoctal); } -static void ipoctal_remove(struct ipack_device *idev) +static void ipoctal_remove(struct ipack_device *device) { - __ipoctal_remove(dev_get_drvdata(&idev->dev)); -} + struct ipoctal *ipoctal, *next; -static DEFINE_IPACK_DEVICE_TABLE(ipoctal_ids) = { - { IPACK_DEVICE(IPACK_ID_VERSION_1, IPACK1_VENDOR_ID_SBS, - IPACK1_DEVICE_ID_SBS_OCTAL_232) }, - { IPACK_DEVICE(IPACK_ID_VERSION_1, IPACK1_VENDOR_ID_SBS, - IPACK1_DEVICE_ID_SBS_OCTAL_422) }, - { IPACK_DEVICE(IPACK_ID_VERSION_1, IPACK1_VENDOR_ID_SBS, - IPACK1_DEVICE_ID_SBS_OCTAL_485) }, - { 0, }, -}; - -MODULE_DEVICE_TABLE(ipack, ipoctal_ids); + list_for_each_entry_safe(ipoctal, next, &ipoctal_list, list) { + if (ipoctal->dev == device) + __ipoctal_remove(ipoctal); + } +} -static const struct ipack_driver_ops ipoctal_drv_ops = { - .probe = ipoctal_probe, +static struct ipack_driver_ops ipoctal_drv_ops = { + .match = ipoctal_match, + .probe = ipoctal_probe, .remove = ipoctal_remove, }; -static struct ipack_driver driver = { - .ops = &ipoctal_drv_ops, - .id_table = ipoctal_ids, -}; - static int __init ipoctal_init(void) { + driver.ops = &ipoctal_drv_ops; return ipack_driver_register(&driver, THIS_MODULE, KBUILD_MODNAME); } static void __exit ipoctal_exit(void) { + struct ipoctal *p, *next; + + list_for_each_entry_safe(p, next, &ipoctal_list, list) + p->dev->bus->ops->remove_device(p->dev); + ipack_driver_unregister(&driver); } diff --git a/trunk/drivers/staging/ipack/devices/scc2698.h b/trunk/drivers/staging/ipack/devices/scc2698.h index 96e8d8c30e14..47f6269985fd 100644 --- a/trunk/drivers/staging/ipack/devices/scc2698.h +++ b/trunk/drivers/staging/ipack/devices/scc2698.h @@ -15,74 +15,78 @@ #define SCC2698_H_ /* - * union scc2698_channel - Channel access to scc2698 IO + * struct scc2698_channel - Channel access to scc2698 IO * * dn value are only spacer. * */ -union scc2698_channel { - struct { - u8 d0, mr; /* Mode register 1/2*/ - u8 d1, sr; /* Status register */ - u8 d2, r1; /* reserved */ - u8 d3, rhr; /* Receive holding register (R) */ - u8 junk[8]; /* other crap for block control */ - } __packed r; /* Read access */ - struct { - u8 d0, mr; /* Mode register 1/2 */ - u8 d1, csr; /* Clock select register */ - u8 d2, cr; /* Command register */ - u8 d3, thr; /* Transmit holding register */ - u8 junk[8]; /* other crap for block control */ - } __packed w; /* Write access */ +struct scc2698_channel { + union { + struct { + unsigned char d0, mr; /* Mode register 1/2*/ + unsigned char d1, sr; /* Status register */ + unsigned char d2, r1; /* reserved */ + unsigned char d3, rhr; /* Receive holding register (R) */ + unsigned char junk[8]; /* other crap for block control */ + } r; /* Read access */ + struct { + unsigned char d0, mr; /* Mode register 1/2 */ + unsigned char d1, csr; /* Clock select register */ + unsigned char d2, cr; /* Command register */ + unsigned char d3, thr; /* Transmit holding register */ + unsigned char junk[8]; /* other crap for block control */ + } w; /* Write access */ + } u; }; /* - * union scc2698_block - Block access to scc2698 IO + * struct scc2698_block - Block access to scc2698 IO * * The scc2698 contain 4 block. * Each block containt two channel a and b. * dn value are only spacer. * */ -union scc2698_block { - struct { - u8 d0, mra; /* Mode register 1/2 (a) */ - u8 d1, sra; /* Status register (a) */ - u8 d2, r1; /* reserved */ - u8 d3, rhra; /* Receive holding register (a) */ - u8 d4, ipcr; /* Input port change register of block */ - u8 d5, isr; /* Interrupt status register of block */ - u8 d6, ctur; /* Counter timer upper register of block */ - u8 d7, ctlr; /* Counter timer lower register of block */ - u8 d8, mrb; /* Mode register 1/2 (b) */ - u8 d9, srb; /* Status register (b) */ - u8 da, r2; /* reserved */ - u8 db, rhrb; /* Receive holding register (b) */ - u8 dc, r3; /* reserved */ - u8 dd, ip; /* Input port register of block */ - u8 de, ctg; /* Start counter timer of block */ - u8 df, cts; /* Stop counter timer of block */ - } __packed r; /* Read access */ - struct { - u8 d0, mra; /* Mode register 1/2 (a) */ - u8 d1, csra; /* Clock select register (a) */ - u8 d2, cra; /* Command register (a) */ - u8 d3, thra; /* Transmit holding register (a) */ - u8 d4, acr; /* Auxiliary control register of block */ - u8 d5, imr; /* Interrupt mask register of block */ - u8 d6, ctu; /* Counter timer upper register of block */ - u8 d7, ctl; /* Counter timer lower register of block */ - u8 d8, mrb; /* Mode register 1/2 (b) */ - u8 d9, csrb; /* Clock select register (a) */ - u8 da, crb; /* Command register (b) */ - u8 db, thrb; /* Transmit holding register (b) */ - u8 dc, r1; /* reserved */ - u8 dd, opcr; /* Output port configuration register of block */ - u8 de, r2; /* reserved */ - u8 df, r3; /* reserved */ - } __packed w; /* Write access */ -}; +struct scc2698_block { + union { + struct { + unsigned char d0, mra; /* Mode register 1/2 (a) */ + unsigned char d1, sra; /* Status register (a) */ + unsigned char d2, r1; /* reserved */ + unsigned char d3, rhra; /* Receive holding register (a) */ + unsigned char d4, ipcr; /* Input port change register of block */ + unsigned char d5, isr; /* Interrupt status register of block */ + unsigned char d6, ctur; /* Counter timer upper register of block */ + unsigned char d7, ctlr; /* Counter timer lower register of block */ + unsigned char d8, mrb; /* Mode register 1/2 (b) */ + unsigned char d9, srb; /* Status register (b) */ + unsigned char da, r2; /* reserved */ + unsigned char db, rhrb; /* Receive holding register (b) */ + unsigned char dc, r3; /* reserved */ + unsigned char dd, ip; /* Input port register of block */ + unsigned char de, ctg; /* Start counter timer of block */ + unsigned char df, cts; /* Stop counter timer of block */ + } r; /* Read access */ + struct { + unsigned char d0, mra; /* Mode register 1/2 (a) */ + unsigned char d1, csra; /* Clock select register (a) */ + unsigned char d2, cra; /* Command register (a) */ + unsigned char d3, thra; /* Transmit holding register (a) */ + unsigned char d4, acr; /* Auxiliary control register of block */ + unsigned char d5, imr; /* Interrupt mask register of block */ + unsigned char d6, ctu; /* Counter timer upper register of block */ + unsigned char d7, ctl; /* Counter timer lower register of block */ + unsigned char d8, mrb; /* Mode register 1/2 (b) */ + unsigned char d9, csrb; /* Clock select register (a) */ + unsigned char da, crb; /* Command register (b) */ + unsigned char db, thrb; /* Transmit holding register (b) */ + unsigned char dc, r1; /* reserved */ + unsigned char dd, opcr; /* Output port configuration register of block */ + unsigned char de, r2; /* reserved */ + unsigned char df, r3; /* reserved */ + } w; /* Write access */ + } u; +} ; #define MR1_CHRL_5_BITS (0x0 << 0) #define MR1_CHRL_6_BITS (0x1 << 0) @@ -221,7 +225,4 @@ union scc2698_block { #define ISR_DELTA_BREAK_B (0x1 << 6) #define ISR_INPUT_PORT_CHANGE (0x1 << 7) -#define ACK_INT_REQ0 0 -#define ACK_INT_REQ1 2 - #endif /* SCC2698_H_ */ diff --git a/trunk/drivers/staging/ipack/ipack.c b/trunk/drivers/staging/ipack/ipack.c index d1e0651592a2..c1cd97a4d9ce 100644 --- a/trunk/drivers/staging/ipack/ipack.c +++ b/trunk/drivers/staging/ipack/ipack.c @@ -12,7 +12,6 @@ #include #include #include -#include #include "ipack.h" #define to_ipack_dev(device) container_of(device, struct ipack_device, dev) @@ -23,190 +22,55 @@ static DEFINE_IDA(ipack_ida); static void ipack_device_release(struct device *dev) { struct ipack_device *device = to_ipack_dev(dev); - kfree(device->id); kfree(device); } -static inline const struct ipack_device_id * -ipack_match_one_device(const struct ipack_device_id *id, - const struct ipack_device *device) +static int ipack_bus_match(struct device *device, struct device_driver *driver) { - if ((id->format == IPACK_ANY_FORMAT || - id->format == device->id_format) && - (id->vendor == IPACK_ANY_ID || id->vendor == device->id_vendor) && - (id->device == IPACK_ANY_ID || id->device == device->id_device)) - return id; - return NULL; -} + int ret; + struct ipack_device *dev = to_ipack_dev(device); + struct ipack_driver *drv = to_ipack_driver(driver); -static const struct ipack_device_id * -ipack_match_id(const struct ipack_device_id *ids, struct ipack_device *idev) -{ - if (ids) { - while (ids->vendor || ids->device) { - if (ipack_match_one_device(ids, idev)) - return ids; - ids++; - } - } - return NULL; -} + if ((!drv->ops) || (!drv->ops->match)) + return -EINVAL; -static int ipack_bus_match(struct device *dev, struct device_driver *drv) -{ - struct ipack_device *idev = to_ipack_dev(dev); - struct ipack_driver *idrv = to_ipack_driver(drv); - const struct ipack_device_id *found_id; + ret = drv->ops->match(dev); + if (ret) + dev->driver = drv; - found_id = ipack_match_id(idrv->id_table, idev); - return found_id ? 1 : 0; + return ret; } static int ipack_bus_probe(struct device *device) { struct ipack_device *dev = to_ipack_dev(device); - struct ipack_driver *drv = to_ipack_driver(device->driver); - if (!drv->ops->probe) + if (!dev->driver->ops->probe) return -EINVAL; - return drv->ops->probe(dev); + return dev->driver->ops->probe(dev); } static int ipack_bus_remove(struct device *device) { struct ipack_device *dev = to_ipack_dev(device); - struct ipack_driver *drv = to_ipack_driver(device->driver); - if (!drv->ops->remove) + if (!dev->driver->ops->remove) return -EINVAL; - drv->ops->remove(dev); - return 0; -} - -#ifdef CONFIG_HOTPLUG - -static int ipack_uevent(struct device *dev, struct kobj_uevent_env *env) -{ - struct ipack_device *idev; - - if (!dev) - return -ENODEV; - - idev = to_ipack_dev(dev); - - if (add_uevent_var(env, - "MODALIAS=ipack:f%02Xv%08Xd%08X", idev->id_format, - idev->id_vendor, idev->id_device)) - return -ENOMEM; - + dev->driver->ops->remove(dev); return 0; } -#else /* !CONFIG_HOTPLUG */ - -#define ipack_uevent NULL - -#endif /* !CONFIG_HOTPLUG */ - -#define ipack_device_attr(field, format_string) \ -static ssize_t \ -field##_show(struct device *dev, struct device_attribute *attr, \ - char *buf) \ -{ \ - struct ipack_device *idev = to_ipack_dev(dev); \ - return sprintf(buf, format_string, idev->field); \ -} - -static ssize_t id_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - unsigned int i, c, l, s; - struct ipack_device *idev = to_ipack_dev(dev); - - - switch (idev->id_format) { - case IPACK_ID_VERSION_1: - l = 0x7; s = 1; break; - case IPACK_ID_VERSION_2: - l = 0xf; s = 2; break; - default: - return -EIO; - } - c = 0; - for (i = 0; i < idev->id_avail; i++) { - if (i > 0) { - if ((i & l) == 0) - buf[c++] = '\n'; - else if ((i & s) == 0) - buf[c++] = ' '; - } - sprintf(&buf[c], "%02x", idev->id[i]); - c += 2; - } - buf[c++] = '\n'; - return c; -} - -static ssize_t -id_vendor_show(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct ipack_device *idev = to_ipack_dev(dev); - switch (idev->id_format) { - case IPACK_ID_VERSION_1: - return sprintf(buf, "0x%02x\n", idev->id_vendor); - case IPACK_ID_VERSION_2: - return sprintf(buf, "0x%06x\n", idev->id_vendor); - default: - return -EIO; - } -} - -static ssize_t -id_device_show(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct ipack_device *idev = to_ipack_dev(dev); - switch (idev->id_format) { - case IPACK_ID_VERSION_1: - return sprintf(buf, "0x%02x\n", idev->id_device); - case IPACK_ID_VERSION_2: - return sprintf(buf, "0x%04x\n", idev->id_device); - default: - return -EIO; - } -} - -static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct ipack_device *idev = to_ipack_dev(dev); - - return sprintf(buf, "ipac:f%02Xv%08Xd%08X", idev->id_format, - idev->id_vendor, idev->id_device); -} - -ipack_device_attr(id_format, "0x%hhu\n"); - -static struct device_attribute ipack_dev_attrs[] = { - __ATTR_RO(id), - __ATTR_RO(id_device), - __ATTR_RO(id_format), - __ATTR_RO(id_vendor), - __ATTR_RO(modalias), -}; - static struct bus_type ipack_bus_type = { - .name = "ipack", - .probe = ipack_bus_probe, - .match = ipack_bus_match, - .remove = ipack_bus_remove, - .dev_attrs = ipack_dev_attrs, - .uevent = ipack_uevent, + .name = "ipack", + .probe = ipack_bus_probe, + .match = ipack_bus_match, + .remove = ipack_bus_remove, }; struct ipack_bus_device *ipack_bus_register(struct device *parent, int slots, - const struct ipack_bus_ops *ops) + struct ipack_bus_ops *ops) { int bus_nr; struct ipack_bus_device *bus; @@ -229,20 +93,8 @@ struct ipack_bus_device *ipack_bus_register(struct device *parent, int slots, } EXPORT_SYMBOL_GPL(ipack_bus_register); -static int ipack_unregister_bus_member(struct device *dev, void *data) -{ - struct ipack_device *idev = to_ipack_dev(dev); - struct ipack_bus_device *bus = data; - - if (idev->bus_nr == bus->bus_nr) - ipack_device_unregister(idev); - - return 1; -} - int ipack_bus_unregister(struct ipack_bus_device *bus) { - bus_for_each_dev(&ipack_bus_type, NULL, bus, ipack_unregister_bus_member); ida_simple_remove(&ipack_ida, bus->bus_nr); kfree(bus); return 0; @@ -250,7 +102,7 @@ int ipack_bus_unregister(struct ipack_bus_device *bus) EXPORT_SYMBOL_GPL(ipack_bus_unregister); int ipack_driver_register(struct ipack_driver *edrv, struct module *owner, - const char *name) + char *name) { edrv->driver.owner = owner; edrv->driver.name = name; @@ -265,169 +117,8 @@ void ipack_driver_unregister(struct ipack_driver *edrv) } EXPORT_SYMBOL_GPL(ipack_driver_unregister); -static u16 ipack_crc_byte(u16 crc, u8 c) -{ - int i; - - crc ^= c << 8; - for (i = 0; i < 8; i++) - crc = (crc << 1) ^ ((crc & 0x8000) ? 0x1021 : 0); - return crc; -} - -/* - * The algorithm in lib/crc-ccitt.c does not seem to apply since it uses the - * opposite bit ordering. - */ -static u8 ipack_calc_crc1(struct ipack_device *dev) -{ - u8 c; - u16 crc; - unsigned int i; - - crc = 0xffff; - for (i = 0; i < dev->id_avail; i++) { - c = (i != 11) ? dev->id[i] : 0; - crc = ipack_crc_byte(crc, c); - } - crc = ~crc; - return crc & 0xff; -} - -static u16 ipack_calc_crc2(struct ipack_device *dev) -{ - u8 c; - u16 crc; - unsigned int i; - - crc = 0xffff; - for (i = 0; i < dev->id_avail; i++) { - c = ((i != 0x18) && (i != 0x19)) ? dev->id[i] : 0; - crc = ipack_crc_byte(crc, c); - } - crc = ~crc; - return crc; -} - -static void ipack_parse_id1(struct ipack_device *dev) -{ - u8 *id = dev->id; - u8 crc; - - dev->id_vendor = id[4]; - dev->id_device = id[5]; - dev->speed_8mhz = 1; - dev->speed_32mhz = (id[7] == 'H'); - crc = ipack_calc_crc1(dev); - dev->id_crc_correct = (crc == id[11]); - if (!dev->id_crc_correct) { - dev_warn(&dev->dev, "ID CRC invalid found 0x%x, expected 0x%x.\n", - id[11], crc); - } -} - -static void ipack_parse_id2(struct ipack_device *dev) -{ - __be16 *id = (__be16 *) dev->id; - u16 flags, crc; - - dev->id_vendor = ((be16_to_cpu(id[3]) & 0xff) << 16) - + be16_to_cpu(id[4]); - dev->id_device = be16_to_cpu(id[5]); - flags = be16_to_cpu(id[10]); - dev->speed_8mhz = !!(flags & 2); - dev->speed_32mhz = !!(flags & 4); - crc = ipack_calc_crc2(dev); - dev->id_crc_correct = (crc == be16_to_cpu(id[12])); - if (!dev->id_crc_correct) { - dev_warn(&dev->dev, "ID CRC invalid found 0x%x, expected 0x%x.\n", - id[11], crc); - } -} - -static int ipack_device_read_id(struct ipack_device *dev) -{ - u8 __iomem *idmem; - int i; - int ret = 0; - - ret = dev->bus->ops->map_space(dev, 0, IPACK_ID_SPACE); - if (ret) { - dev_err(&dev->dev, "error mapping memory\n"); - return ret; - } - idmem = dev->id_space.address; - - /* Determine ID PROM Data Format. If we find the ids "IPAC" or "IPAH" - * we are dealing with a IndustryPack format 1 device. If we detect - * "VITA4 " (16 bit big endian formatted) we are dealing with a - * IndustryPack format 2 device */ - if ((ioread8(idmem + 1) == 'I') && - (ioread8(idmem + 3) == 'P') && - (ioread8(idmem + 5) == 'A') && - ((ioread8(idmem + 7) == 'C') || - (ioread8(idmem + 7) == 'H'))) { - dev->id_format = IPACK_ID_VERSION_1; - dev->id_avail = ioread8(idmem + 0x15); - if ((dev->id_avail < 0x0c) || (dev->id_avail > 0x40)) { - dev_warn(&dev->dev, "invalid id size"); - dev->id_avail = 0x0c; - } - } else if ((ioread8(idmem + 0) == 'I') && - (ioread8(idmem + 1) == 'V') && - (ioread8(idmem + 2) == 'A') && - (ioread8(idmem + 3) == 'T') && - (ioread8(idmem + 4) == ' ') && - (ioread8(idmem + 5) == '4')) { - dev->id_format = IPACK_ID_VERSION_2; - dev->id_avail = ioread16be(idmem + 0x16); - if ((dev->id_avail < 0x1a) || (dev->id_avail > 0x40)) { - dev_warn(&dev->dev, "invalid id size"); - dev->id_avail = 0x1a; - } - } else { - dev->id_format = IPACK_ID_VERSION_INVALID; - dev->id_avail = 0; - } - - if (!dev->id_avail) { - ret = -ENODEV; - goto out; - } - - /* Obtain the amount of memory required to store a copy of the complete - * ID ROM contents */ - dev->id = kmalloc(dev->id_avail, GFP_KERNEL); - if (!dev->id) { - dev_err(&dev->dev, "dev->id alloc failed.\n"); - ret = -ENOMEM; - goto out; - } - for (i = 0; i < dev->id_avail; i++) { - if (dev->id_format == IPACK_ID_VERSION_1) - dev->id[i] = ioread8(idmem + (i << 1) + 1); - else - dev->id[i] = ioread8(idmem + i); - } - - /* now we can finally work with the copy */ - switch (dev->id_format) { - case IPACK_ID_VERSION_1: - ipack_parse_id1(dev); - break; - case IPACK_ID_VERSION_2: - ipack_parse_id2(dev); - break; - } - -out: - dev->bus->ops->unmap_space(dev, IPACK_ID_SPACE); - - return ret; -} - struct ipack_device *ipack_device_register(struct ipack_bus_device *bus, - int slot) + int slot, int irqv) { int ret; struct ipack_device *dev; @@ -441,32 +132,13 @@ struct ipack_device *ipack_device_register(struct ipack_bus_device *bus, dev->dev.parent = bus->parent; dev->slot = slot; dev->bus_nr = bus->bus_nr; + dev->irq = irqv; dev->bus = bus; dev_set_name(&dev->dev, "ipack-dev.%u.%u", dev->bus_nr, dev->slot); - if (bus->ops->set_clockrate(dev, 8)) - dev_warn(&dev->dev, "failed to switch to 8 MHz operation for reading of device ID.\n"); - if (bus->ops->reset_timeout(dev)) - dev_warn(&dev->dev, "failed to reset potential timeout."); - - ret = ipack_device_read_id(dev); - if (ret < 0) { - dev_err(&dev->dev, "error reading device id section.\n"); - kfree(dev); - return NULL; - } - - /* if the device supports 32 MHz operation, use it. */ - if (dev->speed_32mhz) { - ret = bus->ops->set_clockrate(dev, 32); - if (ret < 0) - dev_err(&dev->dev, "failed to switch to 32 MHz operation.\n"); - } - ret = device_register(&dev->dev); if (ret < 0) { - kfree(dev->id); kfree(dev); return NULL; } diff --git a/trunk/drivers/staging/ipack/ipack.h b/trunk/drivers/staging/ipack/ipack.h index d8e3bb6feac8..8bc001e3ca4e 100644 --- a/trunk/drivers/staging/ipack/ipack.h +++ b/trunk/drivers/staging/ipack/ipack.h @@ -9,11 +9,7 @@ * Software Foundation; version 2 of the License. */ -#include #include -#include - -#include "ipack_ids.h" #define IPACK_IDPROM_OFFSET_I 0x01 #define IPACK_IDPROM_OFFSET_P 0x03 @@ -35,7 +31,6 @@ enum ipack_space { IPACK_IO_SPACE = 0, IPACK_ID_SPACE = 1, IPACK_MEM_SPACE = 2, - IPACK_INT_SPACE, }; /** @@ -54,6 +49,8 @@ struct ipack_addr_space { * * @bus_nr: IP bus number where the device is plugged * @slot: Slot where the device is plugged in the carrier board + * @irq: IRQ vector + * @driver: Pointer to the ipack_driver that manages the device * @bus: ipack_bus_device where the device is plugged to. * @id_space: Virtual address to ID space. * @io_space: Virtual address to IO space. @@ -67,30 +64,25 @@ struct ipack_addr_space { struct ipack_device { unsigned int bus_nr; unsigned int slot; + unsigned int irq; + struct ipack_driver *driver; struct ipack_bus_device *bus; struct ipack_addr_space id_space; struct ipack_addr_space io_space; - struct ipack_addr_space int_space; struct ipack_addr_space mem_space; struct device dev; - u8 *id; - size_t id_avail; - u32 id_vendor; - u32 id_device; - u8 id_format; - unsigned int id_crc_correct:1; - unsigned int speed_8mhz:1; - unsigned int speed_32mhz:1; }; /** * struct ipack_driver_ops -- callbacks to mezzanine driver for installing/removing one device * + * @match: Match function * @probe: Probe function * @remove: tell the driver that the carrier board wants to remove one device */ struct ipack_driver_ops { + int (*match) (struct ipack_device *dev); int (*probe) (struct ipack_device *dev); void (*remove) (struct ipack_device *dev); }; @@ -103,8 +95,7 @@ struct ipack_driver_ops { */ struct ipack_driver { struct device_driver driver; - const struct ipack_device_id *id_table; - const struct ipack_driver_ops *ops; + struct ipack_driver_ops *ops; }; /** @@ -114,27 +105,26 @@ struct ipack_driver { * @unmap_space: unmap IP address space * @request_irq: request IRQ * @free_irq: free IRQ - * @get_clockrate: Returns the clockrate the carrier is currently - * communicating with the device at. - * @set_clockrate: Sets the clock-rate for carrier / module communication. - * Should return -EINVAL if the requested speed is not supported. - * @get_error: Returns the error state for the slot the device is attached - * to. - * @get_timeout: Returns 1 if the communication with the device has - * previously timed out. - * @reset_timeout: Resets the state returned by get_timeout. + * @read8: read unsigned char + * @read16: read unsigned short + * @read32: read unsigned int + * @write8: read unsigned char + * @write16: read unsigned short + * @write32: read unsigned int + * @remove_device: tell the bridge module that the device has been removed */ struct ipack_bus_ops { int (*map_space) (struct ipack_device *dev, unsigned int memory_size, int space); int (*unmap_space) (struct ipack_device *dev, int space); - int (*request_irq) (struct ipack_device *dev, - irqreturn_t (*handler)(void *), void *arg); + int (*request_irq) (struct ipack_device *dev, int vector, int (*handler)(void *), void *arg); int (*free_irq) (struct ipack_device *dev); - int (*get_clockrate) (struct ipack_device *dev); - int (*set_clockrate) (struct ipack_device *dev, int mherz); - int (*get_error) (struct ipack_device *dev); - int (*get_timeout) (struct ipack_device *dev); - int (*reset_timeout) (struct ipack_device *dev); + int (*read8) (struct ipack_device *dev, int space, unsigned long offset, unsigned char *value); + int (*read16) (struct ipack_device *dev, int space, unsigned long offset, unsigned short *value); + int (*read32) (struct ipack_device *dev, int space, unsigned long offset, unsigned int *value); + int (*write8) (struct ipack_device *dev, int space, unsigned long offset, unsigned char value); + int (*write16) (struct ipack_device *dev, int space, unsigned long offset, unsigned short value); + int (*write32) (struct ipack_device *dev, int space, unsigned long offset, unsigned int value); + int (*remove_device) (struct ipack_device *dev); }; /** @@ -149,7 +139,7 @@ struct ipack_bus_device { struct device *parent; int slots; int bus_nr; - const struct ipack_bus_ops *ops; + struct ipack_bus_ops *ops; }; /** @@ -163,7 +153,7 @@ struct ipack_bus_device { * available bus device in ipack. */ struct ipack_bus_device *ipack_bus_register(struct device *parent, int slots, - const struct ipack_bus_ops *ops); + struct ipack_bus_ops *ops); /** * ipack_bus_unregister -- unregister an ipack bus @@ -176,8 +166,7 @@ int ipack_bus_unregister(struct ipack_bus_device *bus); * Called by a ipack driver to register itself as a driver * that can manage ipack devices. */ -int ipack_driver_register(struct ipack_driver *edrv, struct module *owner, - const char *name); +int ipack_driver_register(struct ipack_driver *edrv, struct module *owner, char *name); void ipack_driver_unregister(struct ipack_driver *edrv); /** @@ -185,33 +174,10 @@ void ipack_driver_unregister(struct ipack_driver *edrv); * * @bus: ipack bus device it is plugged to. * @slot: slot position in the bus device. + * @irqv: IRQ vector for the mezzanine. * * Register a new ipack device (mezzanine device). The call is done by * the carrier device driver. */ -struct ipack_device *ipack_device_register(struct ipack_bus_device *bus, int slot); +struct ipack_device *ipack_device_register(struct ipack_bus_device *bus, int slot, int irqv); void ipack_device_unregister(struct ipack_device *dev); - -/** - * DEFINE_IPACK_DEVICE_TABLE - macro used to describe a IndustryPack table - * @_table: device table name - * - * This macro is used to create a struct ipack_device_id array (a device table) - * in a generic manner. - */ -#define DEFINE_IPACK_DEVICE_TABLE(_table) \ - const struct ipack_device_id _table[] __devinitconst - -/** - * IPACK_DEVICE - macro used to describe a specific IndustryPack device - * @_format: the format version (currently either 1 or 2, 8 bit value) - * @vend: the 8 or 24 bit IndustryPack Vendor ID - * @dev: the 8 or 16 bit IndustryPack Device ID - * - * This macro is used to create a struct ipack_device_id that matches a specific - * device. - */ -#define IPACK_DEVICE(_format, vend, dev) \ - .format = (_format), \ - .vendor = (vend), \ - .device = (dev) diff --git a/trunk/drivers/staging/ipack/ipack_ids.h b/trunk/drivers/staging/ipack/ipack_ids.h deleted file mode 100644 index 8153fee3f2f7..000000000000 --- a/trunk/drivers/staging/ipack/ipack_ids.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * IndustryPack Fromat, Vendor and Device IDs. - */ - -/* ID section format versions */ -#define IPACK_ID_VERSION_INVALID 0x00 -#define IPACK_ID_VERSION_1 0x01 -#define IPACK_ID_VERSION_2 0x02 - -/* Vendors and devices. Sort key: vendor first, device next. */ -#define IPACK1_VENDOR_ID_RESERVED1 0x00 -#define IPACK1_VENDOR_ID_RESERVED2 0xFF -#define IPACK1_VENDOR_ID_UNREGISTRED01 0x01 -#define IPACK1_VENDOR_ID_UNREGISTRED02 0x02 -#define IPACK1_VENDOR_ID_UNREGISTRED03 0x03 -#define IPACK1_VENDOR_ID_UNREGISTRED04 0x04 -#define IPACK1_VENDOR_ID_UNREGISTRED05 0x05 -#define IPACK1_VENDOR_ID_UNREGISTRED06 0x06 -#define IPACK1_VENDOR_ID_UNREGISTRED07 0x07 -#define IPACK1_VENDOR_ID_UNREGISTRED08 0x08 -#define IPACK1_VENDOR_ID_UNREGISTRED09 0x09 -#define IPACK1_VENDOR_ID_UNREGISTRED10 0x0A -#define IPACK1_VENDOR_ID_UNREGISTRED11 0x0B -#define IPACK1_VENDOR_ID_UNREGISTRED12 0x0C -#define IPACK1_VENDOR_ID_UNREGISTRED13 0x0D -#define IPACK1_VENDOR_ID_UNREGISTRED14 0x0E -#define IPACK1_VENDOR_ID_UNREGISTRED15 0x0F - -#define IPACK1_VENDOR_ID_SBS 0xF0 -#define IPACK1_DEVICE_ID_SBS_OCTAL_232 0x22 -#define IPACK1_DEVICE_ID_SBS_OCTAL_422 0x2A -#define IPACK1_DEVICE_ID_SBS_OCTAL_485 0x48 diff --git a/trunk/drivers/staging/keucr/smcommon.h b/trunk/drivers/staging/keucr/smcommon.h index 4d57203b64d8..278bdb871129 100644 --- a/trunk/drivers/staging/keucr/smcommon.h +++ b/trunk/drivers/staging/keucr/smcommon.h @@ -25,5 +25,7 @@ Define Difinetion #define ERR_NoSmartMedia 0x003A /* Medium Not Present */ /***************************************************************************/ +void StringCopy(char *, char *, int); +int StringCmp(char *, char *, int); #endif diff --git a/trunk/drivers/staging/line6/pcm.c b/trunk/drivers/staging/line6/pcm.c index 7fe44a6fd0ed..5e319e3ce685 100644 --- a/trunk/drivers/staging/line6/pcm.c +++ b/trunk/drivers/staging/line6/pcm.c @@ -48,13 +48,7 @@ static ssize_t pcm_set_impulse_volume(struct device *dev, const char *buf, size_t count) { struct snd_line6_pcm *line6pcm = dev2pcm(dev); - int value; - int rv; - - rv = kstrtoint(buf, 10, &value); - if (rv < 0) - return rv; - + int value = simple_strtoul(buf, NULL, 10); line6pcm->impulse_volume = value; if (value > 0) diff --git a/trunk/drivers/staging/line6/variax.c b/trunk/drivers/staging/line6/variax.c index f97416b1de54..bb99ee4919e7 100644 --- a/trunk/drivers/staging/line6/variax.c +++ b/trunk/drivers/staging/line6/variax.c @@ -353,10 +353,10 @@ static ssize_t variax_set_model(struct device *dev, { struct usb_line6_variax *variax = usb_get_intfdata(to_usb_interface(dev)); - u8 value; + unsigned long value; int ret; - ret = kstrtou8(buf, 10, &value); + ret = strict_strtoul(buf, 10, &value); if (ret) return ret; @@ -387,10 +387,10 @@ static ssize_t variax_set_active(struct device *dev, { struct usb_line6_variax *variax = usb_get_intfdata(to_usb_interface(dev)); - u8 value; + unsigned long value; int ret; - ret = kstrtou8(buf, 10, &value); + ret = strict_strtoul(buf, 10, &value); if (ret) return ret; diff --git a/trunk/drivers/staging/nvec/Kconfig b/trunk/drivers/staging/nvec/Kconfig index 1235a7897d04..43048e9ba0d4 100644 --- a/trunk/drivers/staging/nvec/Kconfig +++ b/trunk/drivers/staging/nvec/Kconfig @@ -28,7 +28,7 @@ config NVEC_POWER config NVEC_PAZ00 bool "Support for OEM specific functions on Compal PAZ00 based devices" - depends on MFD_NVEC && LEDS_CLASS + depends on MFD_NVEC && LEDS_CLASS && MACH_PAZ00 help Say Y to enable control of the yellow side leds on Compal PAZ00 based devices, e.g. Toshbia AC100 and Dynabooks AZ netbooks. diff --git a/trunk/drivers/staging/nvec/nvec.c b/trunk/drivers/staging/nvec/nvec.c index 24d8eebc1d10..695ea35f75b0 100644 --- a/trunk/drivers/staging/nvec/nvec.c +++ b/trunk/drivers/staging/nvec/nvec.c @@ -264,7 +264,7 @@ int nvec_write_async(struct nvec_chip *nvec, const unsigned char *data, list_add_tail(&msg->node, &nvec->tx_data); spin_unlock_irqrestore(&nvec->tx_lock, flags); - queue_work(system_nrt_wq, &nvec->tx_work); + queue_work(nvec->wq, &nvec->tx_work); return 0; } @@ -294,10 +294,8 @@ struct nvec_msg *nvec_write_sync(struct nvec_chip *nvec, nvec->sync_write_pending = (data[1] << 8) + data[0]; - if (nvec_write_async(nvec, data, size) < 0) { - mutex_unlock(&nvec->sync_write_mutex); + if (nvec_write_async(nvec, data, size) < 0) return NULL; - } dev_dbg(nvec->dev, "nvec_sync_write: 0x%04x\n", nvec->sync_write_pending); @@ -368,7 +366,8 @@ static void nvec_request_master(struct work_struct *work) static int parse_msg(struct nvec_chip *nvec, struct nvec_msg *msg) { if ((msg->data[0] & 1 << 7) == 0 && msg->data[3]) { - dev_err(nvec->dev, "ec responded %*ph\n", 4, msg->data); + dev_err(nvec->dev, "ec responded %02x %02x %02x %02x\n", + msg->data[0], msg->data[1], msg->data[2], msg->data[3]); return -EINVAL; } @@ -471,7 +470,7 @@ static void nvec_rx_completed(struct nvec_chip *nvec) if (!nvec_msg_is_event(nvec->rx)) complete(&nvec->ec_transfer); - queue_work(system_nrt_wq, &nvec->rx_work); + queue_work(nvec->wq, &nvec->rx_work); } /** @@ -738,14 +737,12 @@ static int __devinit tegra_nvec_probe(struct platform_device *pdev) nvec->gpio = pdata->gpio; nvec->i2c_addr = pdata->i2c_addr; } else if (nvec->dev->of_node) { - nvec->gpio = of_get_named_gpio(nvec->dev->of_node, - "request-gpios", 0); + nvec->gpio = of_get_named_gpio(nvec->dev->of_node, "request-gpios", 0); if (nvec->gpio < 0) { dev_err(&pdev->dev, "no gpio specified"); return -ENODEV; } - if (of_property_read_u32(nvec->dev->of_node, - "slave-addr", &nvec->i2c_addr)) { + if (of_property_read_u32(nvec->dev->of_node, "slave-addr", &nvec->i2c_addr)) { dev_err(&pdev->dev, "no i2c address specified"); return -ENODEV; } @@ -772,7 +769,7 @@ static int __devinit tegra_nvec_probe(struct platform_device *pdev) return -ENODEV; } - i2c_clk = clk_get_sys("tegra-i2c.2", "div-clk"); + i2c_clk = clk_get_sys("tegra-i2c.2", NULL); if (IS_ERR(i2c_clk)) { dev_err(nvec->dev, "failed to get controller clock\n"); return -ENODEV; @@ -794,11 +791,13 @@ static int __devinit tegra_nvec_probe(struct platform_device *pdev) INIT_LIST_HEAD(&nvec->tx_data); INIT_WORK(&nvec->rx_work, nvec_dispatch); INIT_WORK(&nvec->tx_work, nvec_request_master); + nvec->wq = alloc_workqueue("nvec", WQ_NON_REENTRANT, 2); err = devm_gpio_request_one(&pdev->dev, nvec->gpio, GPIOF_OUT_INIT_HIGH, "nvec gpio"); if (err < 0) { dev_err(nvec->dev, "couldn't request gpio\n"); + destroy_workqueue(nvec->wq); return -ENODEV; } @@ -806,6 +805,7 @@ static int __devinit tegra_nvec_probe(struct platform_device *pdev) "nvec", nvec); if (err) { dev_err(nvec->dev, "couldn't request irq\n"); + destroy_workqueue(nvec->wq); return -ENODEV; } disable_irq(nvec->irq); @@ -837,7 +837,7 @@ static int __devinit tegra_nvec_probe(struct platform_device *pdev) } ret = mfd_add_devices(nvec->dev, -1, nvec_devices, - ARRAY_SIZE(nvec_devices), base, 0, NULL); + ARRAY_SIZE(nvec_devices), base, 0); if (ret) dev_err(nvec->dev, "error adding subdevices\n"); @@ -859,8 +859,7 @@ static int __devexit tegra_nvec_remove(struct platform_device *pdev) nvec_write_async(nvec, EC_DISABLE_EVENT_REPORTING, 3); mfd_remove_devices(nvec->dev); - cancel_work_sync(&nvec->rx_work); - cancel_work_sync(&nvec->tx_work); + destroy_workqueue(nvec->wq); return 0; } diff --git a/trunk/drivers/staging/olpc_dcon/olpc_dcon.c b/trunk/drivers/staging/olpc_dcon/olpc_dcon.c index d49c32a95690..2c4bd746715a 100644 --- a/trunk/drivers/staging/olpc_dcon/olpc_dcon.c +++ b/trunk/drivers/staging/olpc_dcon/olpc_dcon.c @@ -11,7 +11,6 @@ * License as published by the Free Software Foundation. */ -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include #include @@ -73,16 +72,18 @@ static int dcon_hw_init(struct dcon_priv *dcon, int is_init) ver = dcon_read(dcon, DCON_REG_ID); if ((ver >> 8) != 0xDC) { - pr_err("DCON ID not 0xDCxx: 0x%04x instead.\n", ver); + printk(KERN_ERR "olpc-dcon: DCON ID not 0xDCxx: 0x%04x instead.\n", + ver); rc = -ENXIO; goto err; } if (is_init) { - pr_info("Discovered DCON version %x\n", ver & 0xFF); + printk(KERN_INFO "olpc-dcon: Discovered DCON version %x\n", + ver & 0xFF); rc = pdata->init(dcon); if (rc != 0) { - pr_err("Unable to init.\n"); + printk(KERN_ERR "olpc-dcon: Unable to init.\n"); goto err; } } @@ -136,7 +137,8 @@ static int dcon_bus_stabilize(struct dcon_priv *dcon, int is_powered_down) x = 1; x = olpc_ec_cmd(0x26, (unsigned char *)&x, 1, NULL, 0); if (x) { - pr_warn("unable to force dcon to power up: %d!\n", x); + printk(KERN_WARNING "olpc-dcon: unable to force dcon to power up: %d!\n", + x); return x; } msleep(10); /* we'll be conservative */ @@ -149,7 +151,7 @@ static int dcon_bus_stabilize(struct dcon_priv *dcon, int is_powered_down) x = dcon_read(dcon, DCON_REG_ID); } if (x < 0) { - pr_err("unable to stabilize dcon's smbus, reasserting power and praying.\n"); + printk(KERN_ERR "olpc-dcon: unable to stabilize dcon's smbus, reasserting power and praying.\n"); BUG_ON(olpc_board_at_least(olpc_board(0xc2))); x = 0; olpc_ec_cmd(0x26, (unsigned char *)&x, 1, NULL, 0); @@ -220,7 +222,8 @@ static void dcon_sleep(struct dcon_priv *dcon, bool sleep) x = 0; x = olpc_ec_cmd(0x26, (unsigned char *)&x, 1, NULL, 0); if (x) - pr_warn("unable to force dcon to power down: %d!\n", x); + printk(KERN_WARNING "olpc-dcon: unable to force dcon to power down: %d!\n", + x); else dcon->asleep = sleep; } else { @@ -229,7 +232,8 @@ static void dcon_sleep(struct dcon_priv *dcon, bool sleep) dcon->disp_mode |= MODE_BL_ENABLE; x = dcon_bus_stabilize(dcon, 1); if (x) - pr_warn("unable to reinit dcon hardware: %d!\n", x); + printk(KERN_WARNING "olpc-dcon: unable to reinit dcon hardware: %d!\n", + x); else dcon->asleep = sleep; @@ -300,11 +304,12 @@ static void dcon_source_switch(struct work_struct *work) switch (source) { case DCON_SOURCE_CPU: - pr_info("dcon_source_switch to CPU\n"); + printk(KERN_INFO "dcon_source_switch to CPU\n"); /* Enable the scanline interrupt bit */ if (dcon_write(dcon, DCON_REG_MODE, dcon->disp_mode | MODE_SCAN_INT)) - pr_err("couldn't enable scanline interrupt!\n"); + printk(KERN_ERR + "olpc-dcon: couldn't enable scanline interrupt!\n"); else { /* Wait up to one second for the scanline interrupt */ wait_event_timeout(dcon_wait_queue, @@ -312,11 +317,11 @@ static void dcon_source_switch(struct work_struct *work) } if (!dcon->switched) - pr_err("Timeout entering CPU mode; expect a screen glitch.\n"); + printk(KERN_ERR "olpc-dcon: Timeout entering CPU mode; expect a screen glitch.\n"); /* Turn off the scanline interrupt */ if (dcon_write(dcon, DCON_REG_MODE, dcon->disp_mode)) - pr_err("couldn't disable scanline interrupt!\n"); + printk(KERN_ERR "olpc-dcon: couldn't disable scanline interrupt!\n"); /* * Ideally we'd like to disable interrupts here so that the @@ -327,7 +332,7 @@ static void dcon_source_switch(struct work_struct *work) * For now, we just hope.. */ if (!dcon_blank_fb(dcon, false)) { - pr_err("Failed to enter CPU mode\n"); + printk(KERN_ERR "olpc-dcon: Failed to enter CPU mode\n"); dcon->pending_src = DCON_SOURCE_DCON; return; } @@ -336,14 +341,14 @@ static void dcon_source_switch(struct work_struct *work) pdata->set_dconload(1); getnstimeofday(&dcon->load_time); - pr_info("The CPU has control\n"); + printk(KERN_INFO "olpc-dcon: The CPU has control\n"); break; case DCON_SOURCE_DCON: { int t; struct timespec delta_t; - pr_info("dcon_source_switch to DCON\n"); + printk(KERN_INFO "dcon_source_switch to DCON\n"); add_wait_queue(&dcon_wait_queue, &wait); set_current_state(TASK_UNINTERRUPTIBLE); @@ -357,7 +362,7 @@ static void dcon_source_switch(struct work_struct *work) set_current_state(TASK_RUNNING); if (!dcon->switched) { - pr_err("Timeout entering DCON mode; expect a screen glitch.\n"); + printk(KERN_ERR "olpc-dcon: Timeout entering DCON mode; expect a screen glitch.\n"); } else { /* sometimes the DCON doesn't follow its own rules, * and doesn't wait for two vsync pulses before @@ -373,7 +378,7 @@ static void dcon_source_switch(struct work_struct *work) delta_t = timespec_sub(dcon->irq_time, dcon->load_time); if (dcon->switched && delta_t.tv_sec == 0 && delta_t.tv_nsec < NSEC_PER_MSEC * 20) { - pr_err("missed loading, retrying\n"); + printk(KERN_ERR "olpc-dcon: missed loading, retrying\n"); pdata->set_dconload(1); mdelay(41); pdata->set_dconload(0); @@ -383,7 +388,7 @@ static void dcon_source_switch(struct work_struct *work) } dcon_blank_fb(dcon, true); - pr_info("The DCON has control\n"); + printk(KERN_INFO "olpc-dcon: The DCON has control\n"); break; } default: @@ -471,7 +476,7 @@ static ssize_t dcon_freeze_store(struct device *dev, if (ret) return ret; - pr_info("dcon_freeze_store: %lu\n", output); + printk(KERN_INFO "dcon_freeze_store: %lu\n", output); switch (output) { case 0: @@ -645,7 +650,7 @@ static int dcon_probe(struct i2c_client *client, const struct i2c_device_id *id) dcon_device = platform_device_alloc("dcon", -1); if (dcon_device == NULL) { - pr_err("Unable to create the DCON device\n"); + printk(KERN_ERR "dcon: Unable to create the DCON device\n"); rc = -ENOMEM; goto eirq; } @@ -653,7 +658,7 @@ static int dcon_probe(struct i2c_client *client, const struct i2c_device_id *id) platform_set_drvdata(dcon_device, dcon); if (rc) { - pr_err("Unable to add the DCON device\n"); + printk(KERN_ERR "dcon: Unable to add the DCON device\n"); goto edev; } @@ -757,7 +762,7 @@ irqreturn_t dcon_interrupt(int irq, void *id) switch (status & 3) { case 3: - pr_debug("DCONLOAD_MISSED interrupt\n"); + printk(KERN_DEBUG "olpc-dcon: DCONLOAD_MISSED interrupt\n"); break; case 2: /* switch to DCON mode */ @@ -779,9 +784,9 @@ irqreturn_t dcon_interrupt(int irq, void *id) dcon->switched = true; getnstimeofday(&dcon->irq_time); wake_up(&dcon_wait_queue); - pr_debug("switching w/ status 0/0\n"); + printk(KERN_DEBUG "olpc-dcon: switching w/ status 0/0\n"); } else { - pr_debug("scanline interrupt w/CPU\n"); + printk(KERN_DEBUG "olpc-dcon: scanline interrupt w/CPU\n"); } } diff --git a/trunk/drivers/staging/olpc_dcon/olpc_dcon_xo_1.c b/trunk/drivers/staging/olpc_dcon/olpc_dcon_xo_1.c index 77e8eb5a5abd..c87fdfac4855 100644 --- a/trunk/drivers/staging/olpc_dcon/olpc_dcon_xo_1.c +++ b/trunk/drivers/staging/olpc_dcon/olpc_dcon_xo_1.c @@ -10,9 +10,6 @@ * modify it under the terms of version 2 of the GNU General Public * License as published by the Free Software Foundation. */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - #include #include #include @@ -25,23 +22,23 @@ static int dcon_init_xo_1(struct dcon_priv *dcon) unsigned char lob; if (gpio_request(OLPC_GPIO_DCON_STAT0, "OLPC-DCON")) { - pr_err("failed to request STAT0 GPIO\n"); + printk(KERN_ERR "olpc-dcon: failed to request STAT0 GPIO\n"); return -EIO; } if (gpio_request(OLPC_GPIO_DCON_STAT1, "OLPC-DCON")) { - pr_err("failed to request STAT1 GPIO\n"); + printk(KERN_ERR "olpc-dcon: failed to request STAT1 GPIO\n"); goto err_gp_stat1; } if (gpio_request(OLPC_GPIO_DCON_IRQ, "OLPC-DCON")) { - pr_err("failed to request IRQ GPIO\n"); + printk(KERN_ERR "olpc-dcon: failed to request IRQ GPIO\n"); goto err_gp_irq; } if (gpio_request(OLPC_GPIO_DCON_LOAD, "OLPC-DCON")) { - pr_err("failed to request LOAD GPIO\n"); + printk(KERN_ERR "olpc-dcon: failed to request LOAD GPIO\n"); goto err_gp_load; } if (gpio_request(OLPC_GPIO_DCON_BLANK, "OLPC-DCON")) { - pr_err("failed to request BLANK GPIO\n"); + printk(KERN_ERR "olpc-dcon: failed to request BLANK GPIO\n"); goto err_gp_blank; } @@ -86,7 +83,7 @@ static int dcon_init_xo_1(struct dcon_priv *dcon) /* Register the interrupt handler */ if (request_irq(DCON_IRQ, &dcon_interrupt, 0, "DCON", dcon)) { - pr_err("failed to request DCON's irq\n"); + printk(KERN_ERR "olpc-dcon: failed to request DCON's irq\n"); goto err_req_irq; } diff --git a/trunk/drivers/staging/olpc_dcon/olpc_dcon_xo_1_5.c b/trunk/drivers/staging/olpc_dcon/olpc_dcon_xo_1_5.c index 352dd3db0132..69415eec425c 100644 --- a/trunk/drivers/staging/olpc_dcon/olpc_dcon_xo_1_5.c +++ b/trunk/drivers/staging/olpc_dcon/olpc_dcon_xo_1_5.c @@ -6,8 +6,6 @@ * License as published by the Free Software Foundation. */ -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - #include #include #include @@ -68,7 +66,7 @@ static int dcon_init_xo_1_5(struct dcon_priv *dcon) pdev = pci_get_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VX855, NULL); if (!pdev) { - pr_err("cannot find VX855 PCI ID\n"); + printk(KERN_ERR "cannot find VX855 PCI ID\n"); return 1; } @@ -106,7 +104,7 @@ static int dcon_init_xo_1_5(struct dcon_priv *dcon) /* we're sharing the IRQ with ACPI */ irq = acpi_gbl_FADT.sci_interrupt; if (request_irq(irq, &dcon_interrupt, IRQF_SHARED, "DCON", dcon)) { - pr_err("DCON (IRQ%d) allocation failed\n", irq); + printk(KERN_ERR PREFIX "DCON (IRQ%d) allocation failed\n", irq); return 1; } diff --git a/trunk/drivers/staging/omap-thermal/omap-bandgap.c b/trunk/drivers/staging/omap-thermal/omap-bandgap.c index 368a2e19b2d4..c556abb63a17 100644 --- a/trunk/drivers/staging/omap-thermal/omap-bandgap.c +++ b/trunk/drivers/staging/omap-thermal/omap-bandgap.c @@ -157,7 +157,7 @@ static int temp_to_adc_conversion(long temp, struct omap_bandgap *bg_ptr, int i, high = ts_data->adc_end_val - ts_data->adc_start_val; mid = (high + low) / 2; - if (temp < bg_ptr->conv_table[low] || temp > bg_ptr->conv_table[high]) + if (temp < bg_ptr->conv_table[high] || temp > bg_ptr->conv_table[high]) return -EINVAL; while (low < high) { @@ -953,12 +953,12 @@ int __devinit omap_bandgap_probe(struct platform_device *pdev) for (i = 0; i < bg_ptr->conf->sensor_count; i++) { char *domain; - if (bg_ptr->conf->sensors[i].register_cooling) - bg_ptr->conf->sensors[i].register_cooling(bg_ptr, i); - domain = bg_ptr->conf->sensors[i].domain; if (bg_ptr->conf->expose_sensor) bg_ptr->conf->expose_sensor(bg_ptr, i, domain); + + if (bg_ptr->conf->sensors[i].register_cooling) + bg_ptr->conf->sensors[i].register_cooling(bg_ptr, i); } /* @@ -1037,20 +1037,20 @@ static int omap_bandgap_save_ctxt(struct omap_bandgap *bg_ptr) if (OMAP_BANDGAP_HAS(bg_ptr, MODE_CONFIG)) rval->bg_mode_ctrl = omap_bandgap_readl(bg_ptr, - tsr->bgap_mode_ctrl); + tsr->bgap_mode_ctrl); if (OMAP_BANDGAP_HAS(bg_ptr, COUNTER)) rval->bg_counter = omap_bandgap_readl(bg_ptr, - tsr->bgap_counter); + tsr->bgap_counter); if (OMAP_BANDGAP_HAS(bg_ptr, TALERT)) { rval->bg_threshold = omap_bandgap_readl(bg_ptr, - tsr->bgap_threshold); + tsr->bgap_threshold); rval->bg_ctrl = omap_bandgap_readl(bg_ptr, - tsr->bgap_mask_ctrl); + tsr->bgap_mask_ctrl); } if (OMAP_BANDGAP_HAS(bg_ptr, TSHUT_CONFIG)) rval->tshut_threshold = omap_bandgap_readl(bg_ptr, - tsr->tshut_threshold); + tsr->tshut_threshold); } return 0; @@ -1074,9 +1074,8 @@ static int omap_bandgap_restore_ctxt(struct omap_bandgap *bg_ptr) if (val == 0) { if (OMAP_BANDGAP_HAS(bg_ptr, TSHUT_CONFIG)) - omap_bandgap_writel(bg_ptr, - rval->tshut_threshold, - tsr->tshut_threshold); + omap_bandgap_writel(bg_ptr, rval->tshut_threshold, + tsr->tshut_threshold); /* Force immediate temperature measurement and update * of the DTEMP field */ diff --git a/trunk/drivers/staging/omap-thermal/omap-thermal-common.c b/trunk/drivers/staging/omap-thermal/omap-thermal-common.c index 46ee0a9f49d9..0675a5e2f7c8 100644 --- a/trunk/drivers/staging/omap-thermal/omap-thermal-common.c +++ b/trunk/drivers/staging/omap-thermal/omap-thermal-common.c @@ -77,16 +77,10 @@ static inline int omap_thermal_get_temp(struct thermal_zone_device *thermal, unsigned long *temp) { struct omap_thermal_data *data = thermal->devdata; - struct omap_bandgap *bg_ptr; - struct omap_temp_sensor *s; + struct omap_bandgap *bg_ptr = data->bg_ptr; + struct omap_temp_sensor *s = &bg_ptr->conf->sensors[data->sensor_id]; int ret, tmp, pcb_temp, slope, constant; - if (!data) - return 0; - - bg_ptr = data->bg_ptr; - s = &bg_ptr->conf->sensors[data->sensor_id]; - ret = omap_bandgap_read_temperature(bg_ptr, data->sensor_id, &tmp); if (ret) return ret; @@ -233,44 +227,26 @@ static struct thermal_zone_device_ops omap_thermal_ops = { .get_crit_temp = omap_thermal_get_crit_temp, }; -static struct omap_thermal_data -*omap_thermal_build_data(struct omap_bandgap *bg_ptr, int id) +int omap_thermal_expose_sensor(struct omap_bandgap *bg_ptr, int id, + char *domain) { struct omap_thermal_data *data; data = devm_kzalloc(bg_ptr->dev, sizeof(*data), GFP_KERNEL); if (!data) { dev_err(bg_ptr->dev, "kzalloc fail\n"); - return NULL; + return -ENOMEM; } data->sensor_id = id; data->bg_ptr = bg_ptr; data->mode = THERMAL_DEVICE_ENABLED; INIT_WORK(&data->thermal_wq, omap_thermal_work); - return data; -} - -int omap_thermal_expose_sensor(struct omap_bandgap *bg_ptr, int id, - char *domain) -{ - struct omap_thermal_pdata pdata; - - data = omap_bandgap_get_sensor_data(bg_ptr, id); - - if (!data) - data = omap_thermal_build_pdata(bg_ptr, id); - - if (!data) - return -EINVAL; - /* TODO: remove TC1 TC2 */ /* Create thermal zone */ data->omap_thermal = thermal_zone_device_register(domain, OMAP_TRIP_NUMBER, 0, data, &omap_thermal_ops, - 1, 2, /*TODO: remove this when FW allows */ - FAST_TEMP_MONITORING_RATE, - FAST_TEMP_MONITORING_RATE); + 0, FAST_TEMP_MONITORING_RATE, 0, 0); if (IS_ERR_OR_NULL(data->omap_thermal)) { dev_err(bg_ptr->dev, "thermal zone device is NULL\n"); return PTR_ERR(data->omap_thermal); @@ -357,11 +333,6 @@ int omap_thermal_register_cpu_cooling(struct omap_bandgap *bg_ptr, int id) int tab_size, ret; data = omap_bandgap_get_sensor_data(bg_ptr, id); - if (!data) - data = omap_thermal_build_pdata(bg_ptr, id); - - if (!data) - return -EINVAL; ret = omap_thermal_build_cpufreq_clip(bg_ptr, &tab_ptr, &tab_size); if (ret < 0) { @@ -378,7 +349,6 @@ int omap_thermal_register_cpu_cooling(struct omap_bandgap *bg_ptr, int id) return PTR_ERR(data->cool_dev); } bg_ptr->conf->sensors[id].cooling_data.freq_clip_count = tab_size; - omap_bandgap_set_sensor_data(bg_ptr, id, data); return 0; } diff --git a/trunk/drivers/staging/omap-thermal/omap4-thermal.c b/trunk/drivers/staging/omap-thermal/omap4-thermal.c index 04c02b6c0077..fa9dbcd71830 100644 --- a/trunk/drivers/staging/omap-thermal/omap4-thermal.c +++ b/trunk/drivers/staging/omap-thermal/omap4-thermal.c @@ -77,15 +77,15 @@ const struct omap_bandgap_data omap4430_data = { .remove_sensor = omap_thermal_remove_sensor, .sensors = { { - .registers = &omap4430_mpu_temp_sensor_registers, - .ts_data = &omap4430_mpu_temp_sensor_data, - .domain = "cpu", - .slope = 0, - .constant = 20000, - .slope_pcb = 0, - .constant_pcb = 20000, - .register_cooling = omap_thermal_register_cpu_cooling, - .unregister_cooling = omap_thermal_unregister_cpu_cooling, + .registers = &omap4430_mpu_temp_sensor_registers, + .ts_data = &omap4430_mpu_temp_sensor_data, + .domain = "cpu", + .slope = 0, + .constant = 20000, + .slope_pcb = 0, + .constant_pcb = 20000, + .register_cooling = omap_thermal_register_cpu_cooling, + .unregister_cooling = omap_thermal_unregister_cpu_cooling, }, }, .sensor_count = 1, @@ -215,15 +215,15 @@ const struct omap_bandgap_data omap4460_data = { .remove_sensor = omap_thermal_remove_sensor, .sensors = { { - .registers = &omap4460_mpu_temp_sensor_registers, - .ts_data = &omap4460_mpu_temp_sensor_data, - .domain = "cpu", - .slope = OMAP_GRADIENT_SLOPE_4460, - .constant = OMAP_GRADIENT_CONST_4460, - .slope_pcb = OMAP_GRADIENT_SLOPE_W_PCB_4460, - .constant_pcb = OMAP_GRADIENT_CONST_W_PCB_4460, - .register_cooling = omap_thermal_register_cpu_cooling, - .unregister_cooling = omap_thermal_unregister_cpu_cooling, + .registers = &omap4460_mpu_temp_sensor_registers, + .ts_data = &omap4460_mpu_temp_sensor_data, + .domain = "cpu", + .slope = OMAP_GRADIENT_SLOPE_4460, + .constant = OMAP_GRADIENT_CONST_4460, + .slope_pcb = OMAP_GRADIENT_SLOPE_W_PCB_4460, + .constant_pcb = OMAP_GRADIENT_CONST_W_PCB_4460, + .register_cooling = omap_thermal_register_cpu_cooling, + .unregister_cooling = omap_thermal_unregister_cpu_cooling, }, }, .sensor_count = 1, @@ -244,15 +244,15 @@ const struct omap_bandgap_data omap4470_data = { .remove_sensor = omap_thermal_remove_sensor, .sensors = { { - .registers = &omap4460_mpu_temp_sensor_registers, - .ts_data = &omap4460_mpu_temp_sensor_data, - .domain = "cpu", - .slope = OMAP_GRADIENT_SLOPE_4470, - .constant = OMAP_GRADIENT_CONST_4470, - .slope_pcb = OMAP_GRADIENT_SLOPE_W_PCB_4470, - .constant_pcb = OMAP_GRADIENT_CONST_W_PCB_4470, - .register_cooling = omap_thermal_register_cpu_cooling, - .unregister_cooling = omap_thermal_unregister_cpu_cooling, + .registers = &omap4460_mpu_temp_sensor_registers, + .ts_data = &omap4460_mpu_temp_sensor_data, + .domain = "cpu", + .slope = OMAP_GRADIENT_SLOPE_4470, + .constant = OMAP_GRADIENT_CONST_4470, + .slope_pcb = OMAP_GRADIENT_SLOPE_W_PCB_4470, + .constant_pcb = OMAP_GRADIENT_CONST_W_PCB_4470, + .register_cooling = omap_thermal_register_cpu_cooling, + .unregister_cooling = omap_thermal_unregister_cpu_cooling, }, }, .sensor_count = 1, diff --git a/trunk/drivers/staging/omap-thermal/omap5-thermal.c b/trunk/drivers/staging/omap-thermal/omap5-thermal.c index 2f3a498dacd1..0658af24a5c7 100644 --- a/trunk/drivers/staging/omap-thermal/omap5-thermal.c +++ b/trunk/drivers/staging/omap-thermal/omap5-thermal.c @@ -268,29 +268,29 @@ const struct omap_bandgap_data omap5430_data = { .remove_sensor = omap_thermal_remove_sensor, .sensors = { { - .registers = &omap5430_mpu_temp_sensor_registers, - .ts_data = &omap5430_mpu_temp_sensor_data, - .domain = "cpu", - .register_cooling = omap_thermal_register_cpu_cooling, - .unregister_cooling = omap_thermal_unregister_cpu_cooling, - .slope = OMAP_GRADIENT_SLOPE_5430_CPU, - .constant = OMAP_GRADIENT_CONST_5430_CPU, - .slope_pcb = OMAP_GRADIENT_SLOPE_W_PCB_5430_CPU, - .constant_pcb = OMAP_GRADIENT_CONST_W_PCB_5430_CPU, + .registers = &omap5430_mpu_temp_sensor_registers, + .ts_data = &omap5430_mpu_temp_sensor_data, + .domain = "cpu", + .register_cooling = omap_thermal_register_cpu_cooling, + .unregister_cooling = omap_thermal_unregister_cpu_cooling, + .slope = OMAP_GRADIENT_SLOPE_5430_CPU, + .constant = OMAP_GRADIENT_CONST_5430_CPU, + .slope_pcb = OMAP_GRADIENT_SLOPE_W_PCB_5430_CPU, + .constant_pcb = OMAP_GRADIENT_CONST_W_PCB_5430_CPU, }, { - .registers = &omap5430_gpu_temp_sensor_registers, - .ts_data = &omap5430_gpu_temp_sensor_data, - .domain = "gpu", - .slope = OMAP_GRADIENT_SLOPE_5430_GPU, - .constant = OMAP_GRADIENT_CONST_5430_GPU, - .slope_pcb = OMAP_GRADIENT_SLOPE_W_PCB_5430_GPU, - .constant_pcb = OMAP_GRADIENT_CONST_W_PCB_5430_GPU, + .registers = &omap5430_gpu_temp_sensor_registers, + .ts_data = &omap5430_gpu_temp_sensor_data, + .domain = "gpu", + .slope = OMAP_GRADIENT_SLOPE_5430_GPU, + .constant = OMAP_GRADIENT_CONST_5430_GPU, + .slope_pcb = OMAP_GRADIENT_SLOPE_W_PCB_5430_GPU, + .constant_pcb = OMAP_GRADIENT_CONST_W_PCB_5430_GPU, }, { - .registers = &omap5430_core_temp_sensor_registers, - .ts_data = &omap5430_core_temp_sensor_data, - .domain = "core", + .registers = &omap5430_core_temp_sensor_registers, + .ts_data = &omap5430_core_temp_sensor_data, + .domain = "core", }, }, .sensor_count = 3, diff --git a/trunk/drivers/staging/omapdrm/omap_connector.c b/trunk/drivers/staging/omapdrm/omap_connector.c index 55e9c8655850..5e2856c0e0bb 100644 --- a/trunk/drivers/staging/omapdrm/omap_connector.c +++ b/trunk/drivers/staging/omapdrm/omap_connector.c @@ -48,20 +48,13 @@ static inline void copy_timings_omap_to_drm(struct drm_display_mode *mode, mode->vsync_end = mode->vsync_start + timings->vsw; mode->vtotal = mode->vsync_end + timings->vbp; - mode->flags = 0; - - if (timings->interlace) - mode->flags |= DRM_MODE_FLAG_INTERLACE; - - if (timings->hsync_level == OMAPDSS_SIG_ACTIVE_HIGH) - mode->flags |= DRM_MODE_FLAG_PHSYNC; - else - mode->flags |= DRM_MODE_FLAG_NHSYNC; - - if (timings->vsync_level == OMAPDSS_SIG_ACTIVE_HIGH) - mode->flags |= DRM_MODE_FLAG_PVSYNC; - else - mode->flags |= DRM_MODE_FLAG_NVSYNC; + /* note: whether or not it is interlaced, +/- h/vsync, etc, + * which should be set in the mode flags, is not exposed in + * the omap_video_timings struct.. but hdmi driver tracks + * those separately so all we have to have to set the mode + * is the way to recover these timings values, and the + * omap_dss_driver would do the rest. + */ } static inline void copy_timings_drm_to_omap(struct omap_video_timings *timings, @@ -78,22 +71,6 @@ static inline void copy_timings_drm_to_omap(struct omap_video_timings *timings, timings->vfp = mode->vsync_start - mode->vdisplay; timings->vsw = mode->vsync_end - mode->vsync_start; timings->vbp = mode->vtotal - mode->vsync_end; - - timings->interlace = !!(mode->flags & DRM_MODE_FLAG_INTERLACE); - - if (mode->flags & DRM_MODE_FLAG_PHSYNC) - timings->hsync_level = OMAPDSS_SIG_ACTIVE_HIGH; - else - timings->hsync_level = OMAPDSS_SIG_ACTIVE_LOW; - - if (mode->flags & DRM_MODE_FLAG_PVSYNC) - timings->vsync_level = OMAPDSS_SIG_ACTIVE_HIGH; - else - timings->vsync_level = OMAPDSS_SIG_ACTIVE_LOW; - - timings->data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE; - timings->de_level = OMAPDSS_SIG_ACTIVE_HIGH; - timings->sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES; } static void omap_connector_dpms(struct drm_connector *connector, int mode) @@ -210,7 +187,7 @@ static int omap_connector_get_modes(struct drm_connector *connector) } } else { struct drm_display_mode *mode = drm_mode_create(dev); - struct omap_video_timings timings = {0}; + struct omap_video_timings timings; dssdrv->get_timings(dssdev, &timings); @@ -314,7 +291,7 @@ void omap_connector_mode_set(struct drm_connector *connector, struct omap_connector *omap_connector = to_omap_connector(connector); struct omap_dss_device *dssdev = omap_connector->dssdev; struct omap_dss_driver *dssdrv = dssdev->driver; - struct omap_video_timings timings = {0}; + struct omap_video_timings timings; copy_timings_drm_to_omap(&timings, mode); diff --git a/trunk/drivers/staging/omapdrm/omap_crtc.c b/trunk/drivers/staging/omapdrm/omap_crtc.c index 732f2ad34036..62e0022561bc 100644 --- a/trunk/drivers/staging/omapdrm/omap_crtc.c +++ b/trunk/drivers/staging/omapdrm/omap_crtc.c @@ -155,7 +155,6 @@ static void page_flip_cb(void *arg) struct drm_crtc *crtc = arg; struct omap_crtc *omap_crtc = to_omap_crtc(crtc); struct drm_framebuffer *old_fb = omap_crtc->old_fb; - struct drm_gem_object *bo; omap_crtc->old_fb = NULL; @@ -166,9 +165,6 @@ static void page_flip_cb(void *arg) * cycle.. for now go for correctness and later figure out speed.. */ omap_plane_on_endwin(omap_crtc->plane, vblank_cb, crtc); - - bo = omap_framebuffer_bo(crtc->fb, 0); - drm_gem_object_unreference_unlocked(bo); } static int omap_crtc_page_flip_locked(struct drm_crtc *crtc, @@ -177,7 +173,6 @@ static int omap_crtc_page_flip_locked(struct drm_crtc *crtc, { struct drm_device *dev = crtc->dev; struct omap_crtc *omap_crtc = to_omap_crtc(crtc); - struct drm_gem_object *bo; DBG("%d -> %d", crtc->fb ? crtc->fb->base.id : -1, fb->base.id); @@ -190,38 +185,16 @@ static int omap_crtc_page_flip_locked(struct drm_crtc *crtc, omap_crtc->event = event; crtc->fb = fb; - /* - * Hold a reference temporarily until the crtc is updated - * and takes the reference to the bo. This avoids it - * getting freed from under us: - */ - bo = omap_framebuffer_bo(fb, 0); - drm_gem_object_reference(bo); - - omap_gem_op_async(bo, OMAP_GEM_READ, page_flip_cb, crtc); + omap_gem_op_async(omap_framebuffer_bo(fb, 0), OMAP_GEM_READ, + page_flip_cb, crtc); return 0; } -static int omap_crtc_set_property(struct drm_crtc *crtc, - struct drm_property *property, uint64_t val) -{ - struct omap_crtc *omap_crtc = to_omap_crtc(crtc); - struct omap_drm_private *priv = crtc->dev->dev_private; - - if (property == priv->rotation_prop) { - crtc->invert_dimensions = - !!(val & ((1LL << DRM_ROTATE_90) | (1LL << DRM_ROTATE_270))); - } - - return omap_plane_set_property(omap_crtc->plane, property, val); -} - static const struct drm_crtc_funcs omap_crtc_funcs = { .set_config = drm_crtc_helper_set_config, .destroy = omap_crtc_destroy, .page_flip = omap_crtc_page_flip_locked, - .set_property = omap_crtc_set_property, }; static const struct drm_crtc_helper_funcs omap_crtc_helper_funcs = { @@ -258,8 +231,6 @@ struct drm_crtc *omap_crtc_init(struct drm_device *dev, drm_crtc_init(dev, crtc, &omap_crtc_funcs); drm_crtc_helper_add(crtc, &omap_crtc_helper_funcs); - omap_plane_install_properties(omap_crtc->plane, &crtc->base); - return crtc; fail: diff --git a/trunk/drivers/staging/omapdrm/omap_dmm_tiler.c b/trunk/drivers/staging/omapdrm/omap_dmm_tiler.c index 3ae39554df18..86197831f63e 100644 --- a/trunk/drivers/staging/omapdrm/omap_dmm_tiler.c +++ b/trunk/drivers/staging/omapdrm/omap_dmm_tiler.c @@ -120,7 +120,7 @@ static int wait_status(struct refill_engine *engine, uint32_t wait_mask) return 0; } -static irqreturn_t omap_dmm_irq_handler(int irq, void *arg) +irqreturn_t omap_dmm_irq_handler(int irq, void *arg) { struct dmm *dmm = arg; uint32_t status = readl(dmm->base + DMM_PAT_IRQSTATUS); @@ -367,7 +367,7 @@ struct tiler_block *tiler_reserve_1d(size_t size) int num_pages = (size + PAGE_SIZE - 1) >> PAGE_SHIFT; if (!block) - return ERR_PTR(-ENOMEM); + return 0; block->fmt = TILFMT_PAGE; @@ -404,26 +404,8 @@ int tiler_release(struct tiler_block *block) * Utils */ -/* calculate the tiler space address of a pixel in a view orientation... - * below description copied from the display subsystem section of TRM: - * - * When the TILER is addressed, the bits: - * [28:27] = 0x0 for 8-bit tiled - * 0x1 for 16-bit tiled - * 0x2 for 32-bit tiled - * 0x3 for page mode - * [31:29] = 0x0 for 0-degree view - * 0x1 for 180-degree view + mirroring - * 0x2 for 0-degree view + mirroring - * 0x3 for 180-degree view - * 0x4 for 270-degree view + mirroring - * 0x5 for 270-degree view - * 0x6 for 90-degree view - * 0x7 for 90-degree view + mirroring - * Otherwise the bits indicated the corresponding bit address to access - * the SDRAM. - */ -static u32 tiler_get_address(enum tiler_fmt fmt, u32 orient, u32 x, u32 y) +/* calculate the tiler space address of a pixel in a view orientation */ +static u32 tiler_get_address(u32 orient, enum tiler_fmt fmt, u32 x, u32 y) { u32 x_bits, y_bits, tmp, x_mask, y_mask, alignment; @@ -435,11 +417,8 @@ static u32 tiler_get_address(enum tiler_fmt fmt, u32 orient, u32 x, u32 y) x_mask = MASK(x_bits); y_mask = MASK(y_bits); - if (x < 0 || x > x_mask || y < 0 || y > y_mask) { - DBG("invalid coords: %u < 0 || %u > %u || %u < 0 || %u > %u", - x, x, x_mask, y, y, y_mask); + if (x < 0 || x > x_mask || y < 0 || y > y_mask) return 0; - } /* account for mirroring */ if (orient & MASK_X_INVERT) @@ -460,22 +439,11 @@ dma_addr_t tiler_ssptr(struct tiler_block *block) { BUG_ON(!validfmt(block->fmt)); - return TILVIEW_8BIT + tiler_get_address(block->fmt, 0, + return TILVIEW_8BIT + tiler_get_address(0, block->fmt, block->area.p0.x * geom[block->fmt].slot_w, block->area.p0.y * geom[block->fmt].slot_h); } -dma_addr_t tiler_tsptr(struct tiler_block *block, uint32_t orient, - uint32_t x, uint32_t y) -{ - struct tcm_pt *p = &block->area.p0; - BUG_ON(!validfmt(block->fmt)); - - return tiler_get_address(block->fmt, orient, - (p->x * geom[block->fmt].slot_w) + x, - (p->y * geom[block->fmt].slot_h) + y); -} - void tiler_align(enum tiler_fmt fmt, uint16_t *w, uint16_t *h) { BUG_ON(!validfmt(fmt)); @@ -483,14 +451,11 @@ void tiler_align(enum tiler_fmt fmt, uint16_t *w, uint16_t *h) *h = round_up(*h, geom[fmt].slot_h); } -uint32_t tiler_stride(enum tiler_fmt fmt, uint32_t orient) +uint32_t tiler_stride(enum tiler_fmt fmt) { BUG_ON(!validfmt(fmt)); - if (orient & MASK_XY_FLIP) - return 1 << (CONT_HEIGHT_BITS + geom[fmt].x_shft); - else - return 1 << (CONT_WIDTH_BITS + geom[fmt].y_shft); + return 1 << (CONT_WIDTH_BITS + geom[fmt].y_shft); } size_t tiler_size(enum tiler_fmt fmt, uint16_t w, uint16_t h) diff --git a/trunk/drivers/staging/omapdrm/omap_dmm_tiler.h b/trunk/drivers/staging/omapdrm/omap_dmm_tiler.h index 740911df5fc3..7b1052a329e4 100644 --- a/trunk/drivers/staging/omapdrm/omap_dmm_tiler.h +++ b/trunk/drivers/staging/omapdrm/omap_dmm_tiler.h @@ -54,18 +54,7 @@ struct tiler_block { #define TILER_WIDTH (1 << (CONT_WIDTH_BITS - SLOT_WIDTH_BITS)) #define TILER_HEIGHT (1 << (CONT_HEIGHT_BITS - SLOT_HEIGHT_BITS)) -/* -Table 15-11. Coding and Description of TILER Orientations -S Y X Description Alternate description -0 0 0 0-degree view Natural view -0 0 1 0-degree view with vertical mirror 180-degree view with horizontal mirror -0 1 0 0-degree view with horizontal mirror 180-degree view with vertical mirror -0 1 1 180-degree view -1 0 0 90-degree view with vertical mirror 270-degree view with horizontal mirror -1 0 1 270-degree view -1 1 0 90-degree view -1 1 1 90-degree view with horizontal mirror 270-degree view with vertical mirror - */ +/* tiler space addressing bitfields */ #define MASK_XY_FLIP (1 << 31) #define MASK_Y_INVERT (1 << 30) #define MASK_X_INVERT (1 << 29) @@ -101,9 +90,7 @@ int tiler_release(struct tiler_block *block); /* utilities */ dma_addr_t tiler_ssptr(struct tiler_block *block); -dma_addr_t tiler_tsptr(struct tiler_block *block, uint32_t orient, - uint32_t x, uint32_t y); -uint32_t tiler_stride(enum tiler_fmt fmt, uint32_t orient); +uint32_t tiler_stride(enum tiler_fmt fmt); size_t tiler_size(enum tiler_fmt fmt, uint16_t w, uint16_t h); size_t tiler_vsize(enum tiler_fmt fmt, uint16_t w, uint16_t h); void tiler_align(enum tiler_fmt fmt, uint16_t *w, uint16_t *h); diff --git a/trunk/drivers/staging/omapdrm/omap_drv.c b/trunk/drivers/staging/omapdrm/omap_drv.c index 2ec5264dd002..4beab9447ceb 100644 --- a/trunk/drivers/staging/omapdrm/omap_drv.c +++ b/trunk/drivers/staging/omapdrm/omap_drv.c @@ -571,7 +571,8 @@ static int dev_load(struct drm_device *dev, unsigned long flags) dev->dev_private = priv; - priv->wq = alloc_ordered_workqueue("omapdrm", 0); + priv->wq = alloc_workqueue("omapdrm", + WQ_UNBOUND | WQ_NON_REENTRANT, 1); INIT_LIST_HEAD(&priv->obj_list); @@ -648,8 +649,6 @@ static int dev_firstopen(struct drm_device *dev) */ static void dev_lastclose(struct drm_device *dev) { - int i; - /* we don't support vga-switcheroo.. so just make sure the fbdev * mode is active */ @@ -658,21 +657,6 @@ static void dev_lastclose(struct drm_device *dev) DBG("lastclose: dev=%p", dev); - /* need to restore default rotation state.. not sure if there is - * a cleaner way to restore properties to default state? Maybe - * a flag that properties should automatically be restored to - * default state on lastclose? - */ - for (i = 0; i < priv->num_crtcs; i++) { - drm_object_property_set_value(&priv->crtcs[i]->base, - priv->rotation_prop, 0); - } - - for (i = 0; i < priv->num_planes; i++) { - drm_object_property_set_value(&priv->planes[i]->base, - priv->rotation_prop, 0); - } - ret = drm_fb_helper_restore_fbdev_mode(priv->fbdev); if (ret) DBG("failed to restore crtc mode"); @@ -777,6 +761,7 @@ static struct drm_driver omap_drm_driver = { .irq_postinstall = dev_irq_postinstall, .irq_uninstall = dev_irq_uninstall, .irq_handler = dev_irq_handler, + .reclaim_buffers = drm_core_reclaim_buffers, #ifdef CONFIG_DEBUG_FS .debugfs_init = omap_debugfs_init, .debugfs_cleanup = omap_debugfs_cleanup, diff --git a/trunk/drivers/staging/omapdrm/omap_drv.h b/trunk/drivers/staging/omapdrm/omap_drv.h index 9dc72d143ff3..2092a9167d29 100644 --- a/trunk/drivers/staging/omapdrm/omap_drv.h +++ b/trunk/drivers/staging/omapdrm/omap_drv.h @@ -59,27 +59,6 @@ struct omap_drm_private { struct list_head obj_list; bool has_dmm; - - /* properties: */ - struct drm_property *rotation_prop; - struct drm_property *zorder_prop; -}; - -/* this should probably be in drm-core to standardize amongst drivers */ -#define DRM_ROTATE_0 0 -#define DRM_ROTATE_90 1 -#define DRM_ROTATE_180 2 -#define DRM_ROTATE_270 3 -#define DRM_REFLECT_X 4 -#define DRM_REFLECT_Y 5 - -/* parameters which describe (unrotated) coordinates of scanout within a fb: */ -struct omap_drm_window { - uint32_t rotation; - int32_t crtc_x, crtc_y; /* signed because can be offscreen */ - uint32_t crtc_w, crtc_h; - uint32_t src_x, src_y; - uint32_t src_w, src_h; }; #ifdef CONFIG_DEBUG_FS @@ -108,10 +87,6 @@ int omap_plane_mode_set(struct drm_plane *plane, uint32_t src_w, uint32_t src_h); void omap_plane_on_endwin(struct drm_plane *plane, void (*fxn)(void *), void *arg); -void omap_plane_install_properties(struct drm_plane *plane, - struct drm_mode_object *obj); -int omap_plane_set_property(struct drm_plane *plane, - struct drm_property *property, uint64_t val); struct drm_encoder *omap_encoder_init(struct drm_device *dev, struct omap_overlay_manager *mgr); @@ -139,8 +114,8 @@ struct drm_gem_object *omap_framebuffer_bo(struct drm_framebuffer *fb, int p); int omap_framebuffer_replace(struct drm_framebuffer *a, struct drm_framebuffer *b, void *arg, void (*unpin)(void *arg, struct drm_gem_object *bo)); -void omap_framebuffer_update_scanout(struct drm_framebuffer *fb, - struct omap_drm_window *win, struct omap_overlay_info *info); +void omap_framebuffer_update_scanout(struct drm_framebuffer *fb, int x, int y, + struct omap_overlay_info *info); struct drm_connector *omap_framebuffer_get_next_connector( struct drm_framebuffer *fb, struct drm_connector *from); void omap_framebuffer_flush(struct drm_framebuffer *fb, @@ -182,12 +157,8 @@ int omap_gem_get_pages(struct drm_gem_object *obj, struct page ***pages, bool remap); int omap_gem_put_pages(struct drm_gem_object *obj); uint32_t omap_gem_flags(struct drm_gem_object *obj); -int omap_gem_rotated_paddr(struct drm_gem_object *obj, uint32_t orient, - int x, int y, dma_addr_t *paddr); uint64_t omap_gem_mmap_offset(struct drm_gem_object *obj); size_t omap_gem_mmap_size(struct drm_gem_object *obj); -int omap_gem_tiled_size(struct drm_gem_object *obj, uint16_t *w, uint16_t *h); -int omap_gem_tiled_stride(struct drm_gem_object *obj, uint32_t orient); struct dma_buf * omap_gem_prime_export(struct drm_device *dev, struct drm_gem_object *obj, int flags); diff --git a/trunk/drivers/staging/omapdrm/omap_fb.c b/trunk/drivers/staging/omapdrm/omap_fb.c index 446801d63007..74260f043ab1 100644 --- a/trunk/drivers/staging/omapdrm/omap_fb.c +++ b/trunk/drivers/staging/omapdrm/omap_fb.c @@ -18,7 +18,6 @@ */ #include "omap_drv.h" -#include "omap_dmm_tiler.h" #include "drm_crtc.h" #include "drm_crtc_helper.h" @@ -138,100 +137,30 @@ static const struct drm_framebuffer_funcs omap_framebuffer_funcs = { .dirty = omap_framebuffer_dirty, }; -static uint32_t get_linear_addr(struct plane *plane, - const struct format *format, int n, int x, int y) -{ - uint32_t offset; - - offset = plane->offset + - (x * format->planes[n].stride_bpp) + - (y * plane->pitch / format->planes[n].sub_y); - - return plane->paddr + offset; -} - /* update ovl info for scanout, handles cases of multi-planar fb's, etc. */ -void omap_framebuffer_update_scanout(struct drm_framebuffer *fb, - struct omap_drm_window *win, struct omap_overlay_info *info) +void omap_framebuffer_update_scanout(struct drm_framebuffer *fb, int x, int y, + struct omap_overlay_info *info) { struct omap_framebuffer *omap_fb = to_omap_framebuffer(fb); const struct format *format = omap_fb->format; struct plane *plane = &omap_fb->planes[0]; - uint32_t x, y, orient = 0; - - info->color_mode = format->dss_format; - - info->pos_x = win->crtc_x; - info->pos_y = win->crtc_y; - info->out_width = win->crtc_w; - info->out_height = win->crtc_h; - info->width = win->src_w; - info->height = win->src_h; - - x = win->src_x; - y = win->src_y; - - if (omap_gem_flags(plane->bo) & OMAP_BO_TILED) { - uint32_t w = win->src_w; - uint32_t h = win->src_h; - - switch (win->rotation & 0xf) { - default: - dev_err(fb->dev->dev, "invalid rotation: %02x", - (uint32_t)win->rotation); - /* fallthru to default to no rotation */ - case 0: - case BIT(DRM_ROTATE_0): - orient = 0; - break; - case BIT(DRM_ROTATE_90): - orient = MASK_XY_FLIP | MASK_X_INVERT; - break; - case BIT(DRM_ROTATE_180): - orient = MASK_X_INVERT | MASK_Y_INVERT; - break; - case BIT(DRM_ROTATE_270): - orient = MASK_XY_FLIP | MASK_Y_INVERT; - break; - } - - if (win->rotation & BIT(DRM_REFLECT_X)) - orient ^= MASK_X_INVERT; - - if (win->rotation & BIT(DRM_REFLECT_Y)) - orient ^= MASK_Y_INVERT; - - /* adjust x,y offset for flip/invert: */ - if (orient & MASK_XY_FLIP) - swap(w, h); - if (orient & MASK_Y_INVERT) - y += h - 1; - if (orient & MASK_X_INVERT) - x += w - 1; + unsigned int offset; - omap_gem_rotated_paddr(plane->bo, orient, x, y, &info->paddr); - info->rotation_type = OMAP_DSS_ROT_TILER; - info->screen_width = omap_gem_tiled_stride(plane->bo, orient); - } else { - info->paddr = get_linear_addr(plane, format, 0, x, y); - info->rotation_type = OMAP_DSS_ROT_DMA; - info->screen_width = plane->pitch; - } + offset = plane->offset + + (x * format->planes[0].stride_bpp) + + (y * plane->pitch / format->planes[0].sub_y); - /* convert to pixels: */ - info->screen_width /= format->planes[0].stride_bpp; + info->color_mode = format->dss_format; + info->paddr = plane->paddr + offset; + info->screen_width = plane->pitch / format->planes[0].stride_bpp; if (format->dss_format == OMAP_DSS_COLOR_NV12) { plane = &omap_fb->planes[1]; - - if (info->rotation_type == OMAP_DSS_ROT_TILER) { - WARN_ON(!(omap_gem_flags(plane->bo) & OMAP_BO_TILED)); - omap_gem_rotated_paddr(plane->bo, orient, - x/2, y/2, &info->p_uv_addr); - } else { - info->p_uv_addr = get_linear_addr(plane, format, 1, x, y); - } + offset = plane->offset + + (x * format->planes[1].stride_bpp) + + (y * plane->pitch / format->planes[1].sub_y); + info->p_uv_addr = plane->paddr + offset; } else { info->p_uv_addr = 0; } @@ -448,7 +377,7 @@ struct drm_framebuffer *omap_framebuffer_init(struct drm_device *dev, size = pitch * mode_cmd->height / format->planes[i].sub_y; - if (size > (omap_gem_mmap_size(bos[i]) - mode_cmd->offsets[i])) { + if (size > (bos[i]->size - mode_cmd->offsets[i])) { dev_err(dev->dev, "provided buffer object is too small! %d < %d\n", bos[i]->size - mode_cmd->offsets[i], size); ret = -EINVAL; diff --git a/trunk/drivers/staging/omapdrm/omap_gem.c b/trunk/drivers/staging/omapdrm/omap_gem.c index c8287438e0dc..3a0d035a9e03 100644 --- a/trunk/drivers/staging/omapdrm/omap_gem.c +++ b/trunk/drivers/staging/omapdrm/omap_gem.c @@ -226,8 +226,7 @@ static int omap_gem_attach_pages(struct drm_gem_object *obj) struct drm_device *dev = obj->dev; struct omap_gem_object *omap_obj = to_omap_bo(obj); struct page **pages; - int npages = obj->size >> PAGE_SHIFT; - int i, ret; + int i, npages = obj->size >> PAGE_SHIFT; dma_addr_t *addrs; WARN_ON(omap_obj->pages); @@ -247,32 +246,18 @@ static int omap_gem_attach_pages(struct drm_gem_object *obj) */ if (omap_obj->flags & (OMAP_BO_WC|OMAP_BO_UNCACHED)) { addrs = kmalloc(npages * sizeof(addrs), GFP_KERNEL); - if (!addrs) { - ret = -ENOMEM; - goto free_pages; - } - for (i = 0; i < npages; i++) { addrs[i] = dma_map_page(dev->dev, pages[i], 0, PAGE_SIZE, DMA_BIDIRECTIONAL); } } else { addrs = kzalloc(npages * sizeof(addrs), GFP_KERNEL); - if (!addrs) { - ret = -ENOMEM; - goto free_pages; - } } omap_obj->addrs = addrs; omap_obj->pages = pages; return 0; - -free_pages: - _drm_gem_put_pages(obj, pages, true, false); - - return ret; } /** release backing pages */ @@ -354,17 +339,6 @@ size_t omap_gem_mmap_size(struct drm_gem_object *obj) return size; } -/* get tiled size, returns -EINVAL if not tiled buffer */ -int omap_gem_tiled_size(struct drm_gem_object *obj, uint16_t *w, uint16_t *h) -{ - struct omap_gem_object *omap_obj = to_omap_bo(obj); - if (omap_obj->flags & OMAP_BO_TILED) { - *w = omap_obj->width; - *h = omap_obj->height; - return 0; - } - return -EINVAL; -} /* Normal handling for the case of faulting in non-tiled buffers */ static int fault_1d(struct drm_gem_object *obj, @@ -858,36 +832,6 @@ int omap_gem_put_paddr(struct drm_gem_object *obj) return ret; } -/* Get rotated scanout address (only valid if already pinned), at the - * specified orientation and x,y offset from top-left corner of buffer - * (only valid for tiled 2d buffers) - */ -int omap_gem_rotated_paddr(struct drm_gem_object *obj, uint32_t orient, - int x, int y, dma_addr_t *paddr) -{ - struct omap_gem_object *omap_obj = to_omap_bo(obj); - int ret = -EINVAL; - - mutex_lock(&obj->dev->struct_mutex); - if ((omap_obj->paddr_cnt > 0) && omap_obj->block && - (omap_obj->flags & OMAP_BO_TILED)) { - *paddr = tiler_tsptr(omap_obj->block, orient, x, y); - ret = 0; - } - mutex_unlock(&obj->dev->struct_mutex); - return ret; -} - -/* Get tiler stride for the buffer (only valid for 2d tiled buffers) */ -int omap_gem_tiled_stride(struct drm_gem_object *obj, uint32_t orient) -{ - struct omap_gem_object *omap_obj = to_omap_bo(obj); - int ret = -EINVAL; - if (omap_obj->flags & OMAP_BO_TILED) - ret = tiler_stride(gem2fmt(omap_obj->flags), orient); - return ret; -} - /* acquire pages when needed (for example, for DMA where physically * contiguous buffer is not required */ @@ -1458,7 +1402,7 @@ void omap_gem_init(struct drm_device *dev) */ usergart[i].height = h; usergart[i].height_shift = ilog2(h); - usergart[i].stride_pfn = tiler_stride(fmts[i], 0) >> PAGE_SHIFT; + usergart[i].stride_pfn = tiler_stride(fmts[i]) >> PAGE_SHIFT; usergart[i].slot_shift = ilog2((PAGE_SIZE / h) >> i); for (j = 0; j < NUM_USERGART_ENTRIES; j++) { struct usergart_entry *entry = &usergart[i].entry[j]; diff --git a/trunk/drivers/staging/omapdrm/omap_plane.c b/trunk/drivers/staging/omapdrm/omap_plane.c index 4bde639dd02c..7997be74010d 100644 --- a/trunk/drivers/staging/omapdrm/omap_plane.c +++ b/trunk/drivers/staging/omapdrm/omap_plane.c @@ -20,7 +20,6 @@ #include #include "omap_drv.h" -#include "omap_dmm_tiler.h" /* some hackery because omapdss has an 'enum omap_plane' (which would be * better named omap_plane_id).. and compiler seems unhappy about having @@ -44,9 +43,10 @@ struct omap_plane { struct omap_overlay *ovl; struct omap_overlay_info info; - /* position/orientation of scanout within the fb: */ - struct omap_drm_window win; - + /* Source values, converted to integers because we don't support + * fractional positions: + */ + unsigned int src_x, src_y; /* last fb that we pinned: */ struct drm_framebuffer *pinned_fb; @@ -289,7 +289,6 @@ static void update_scanout(struct drm_plane *plane) { struct omap_plane *omap_plane = to_omap_plane(plane); struct omap_overlay_info *info = &omap_plane->info; - struct omap_drm_window *win = &omap_plane->win; int ret; ret = update_pin(plane, plane->fb); @@ -300,10 +299,11 @@ static void update_scanout(struct drm_plane *plane) return; } - omap_framebuffer_update_scanout(plane->fb, win, info); + omap_framebuffer_update_scanout(plane->fb, + omap_plane->src_x, omap_plane->src_y, info); DBG("%s: %d,%d: %08x %08x (%d)", omap_plane->ovl->name, - win->src_x, win->src_y, + omap_plane->src_x, omap_plane->src_y, (u32)info->paddr, (u32)info->p_uv_addr, info->screen_width); } @@ -316,18 +316,21 @@ int omap_plane_mode_set(struct drm_plane *plane, uint32_t src_w, uint32_t src_h) { struct omap_plane *omap_plane = to_omap_plane(plane); - struct omap_drm_window *win = &omap_plane->win; - - win->crtc_x = crtc_x; - win->crtc_y = crtc_y; - win->crtc_w = crtc_w; - win->crtc_h = crtc_h; /* src values are in Q16 fixed point, convert to integer: */ - win->src_x = src_x >> 16; - win->src_y = src_y >> 16; - win->src_w = src_w >> 16; - win->src_h = src_h >> 16; + src_x = src_x >> 16; + src_y = src_y >> 16; + src_w = src_w >> 16; + src_h = src_h >> 16; + + omap_plane->info.pos_x = crtc_x; + omap_plane->info.pos_y = crtc_y; + omap_plane->info.out_width = crtc_w; + omap_plane->info.out_height = crtc_h; + omap_plane->info.width = src_w; + omap_plane->info.height = src_h; + omap_plane->src_x = src_x; + omap_plane->src_y = src_y; /* note: this is done after this fxn returns.. but if we need * to do a commit/update_scanout, etc before this returns we @@ -356,8 +359,6 @@ static int omap_plane_update(struct drm_plane *plane, static int omap_plane_disable(struct drm_plane *plane) { - struct omap_plane *omap_plane = to_omap_plane(plane); - omap_plane->win.rotation = BIT(DRM_ROTATE_0); return omap_plane_dpms(plane, DRM_MODE_DPMS_OFF); } @@ -408,79 +409,10 @@ void omap_plane_on_endwin(struct drm_plane *plane, install_irq(plane); } -/* helper to install properties which are common to planes and crtcs */ -void omap_plane_install_properties(struct drm_plane *plane, - struct drm_mode_object *obj) -{ - struct drm_device *dev = plane->dev; - struct omap_drm_private *priv = dev->dev_private; - struct drm_property *prop; - - prop = priv->rotation_prop; - if (!prop) { - const struct drm_prop_enum_list props[] = { - { DRM_ROTATE_0, "rotate-0" }, - { DRM_ROTATE_90, "rotate-90" }, - { DRM_ROTATE_180, "rotate-180" }, - { DRM_ROTATE_270, "rotate-270" }, - { DRM_REFLECT_X, "reflect-x" }, - { DRM_REFLECT_Y, "reflect-y" }, - }; - prop = drm_property_create_bitmask(dev, 0, "rotation", - props, ARRAY_SIZE(props)); - if (prop == NULL) - return; - priv->rotation_prop = prop; - } - drm_object_attach_property(obj, prop, 0); - - prop = priv->zorder_prop; - if (!prop) { - prop = drm_property_create_range(dev, 0, "zorder", 0, 3); - if (prop == NULL) - return; - priv->zorder_prop = prop; - } - drm_object_attach_property(obj, prop, 0); -} - -int omap_plane_set_property(struct drm_plane *plane, - struct drm_property *property, uint64_t val) -{ - struct omap_plane *omap_plane = to_omap_plane(plane); - struct omap_drm_private *priv = plane->dev->dev_private; - int ret = -EINVAL; - - if (property == priv->rotation_prop) { - struct omap_overlay *ovl = omap_plane->ovl; - - DBG("%s: rotation: %02x", ovl->name, (uint32_t)val); - omap_plane->win.rotation = val; - - if (ovl->is_enabled(ovl)) - ret = omap_plane_dpms(plane, DRM_MODE_DPMS_ON); - else - ret = 0; - } else if (property == priv->zorder_prop) { - struct omap_overlay *ovl = omap_plane->ovl; - - DBG("%s: zorder: %d", ovl->name, (uint32_t)val); - omap_plane->info.zorder = val; - - if (ovl->is_enabled(ovl)) - ret = omap_plane_dpms(plane, DRM_MODE_DPMS_ON); - else - ret = 0; - } - - return ret; -} - static const struct drm_plane_funcs omap_plane_funcs = { .update_plane = omap_plane_update, .disable_plane = omap_plane_disable, .destroy = omap_plane_destroy, - .set_property = omap_plane_set_property, }; /* initialize plane */ @@ -523,8 +455,6 @@ struct drm_plane *omap_plane_init(struct drm_device *dev, drm_plane_init(dev, plane, possible_crtcs, &omap_plane_funcs, omap_plane->formats, omap_plane->nformats, priv); - omap_plane_install_properties(plane, &plane->base); - /* get our starting configuration, set defaults for parameters * we don't currently use, etc: */ @@ -533,6 +463,7 @@ struct drm_plane *omap_plane_init(struct drm_device *dev, omap_plane->info.rotation = OMAP_DSS_ROT_0; omap_plane->info.global_alpha = 0xff; omap_plane->info.mirror = 0; + omap_plane->info.mirror = 0; /* Set defaults depending on whether we are a CRTC or overlay * layer. diff --git a/trunk/drivers/staging/ozwpan/ozcdev.c b/trunk/drivers/staging/ozwpan/ozcdev.c index 64913aeb0bac..d98321945802 100644 --- a/trunk/drivers/staging/ozwpan/ozcdev.c +++ b/trunk/drivers/staging/ozwpan/ozcdev.c @@ -8,7 +8,6 @@ #include #include #include -#include #include #include #include "ozconfig.h" @@ -104,10 +103,10 @@ ssize_t oz_cdev_read(struct file *filp, char __user *buf, size_t count, if (pd) oz_pd_get(pd); spin_unlock_bh(&g_cdev.lock); - if (pd == NULL) + if (pd == 0) return -1; ctx = oz_cdev_claim_ctx(pd); - if (ctx == NULL) + if (ctx == 0) goto out2; n = ctx->rd_in - ctx->rd_out; if (n < 0) @@ -157,11 +156,11 @@ ssize_t oz_cdev_write(struct file *filp, const char __user *buf, size_t count, if (pd) oz_pd_get(pd); spin_unlock_bh(&g_cdev.lock); - if (pd == NULL) + if (pd == 0) return -1; eb = &pd->elt_buff; ei = oz_elt_info_alloc(eb); - if (ei == NULL) { + if (ei == 0) { count = 0; goto out; } @@ -214,7 +213,7 @@ static int oz_set_active_pd(u8 *addr) if (old_pd) oz_pd_put(old_pd); } else { - if (is_zero_ether_addr(addr)) { + if (!memcmp(addr, "\0\0\0\0\0\0", sizeof(addr))) { spin_lock_bh(&g_cdev.lock); pd = g_cdev.active_pd; g_cdev.active_pd = 0; @@ -410,7 +409,7 @@ int oz_cdev_start(struct oz_pd *pd, int resume) return 0; } ctx = kzalloc(sizeof(struct oz_serial_ctx), GFP_ATOMIC); - if (ctx == NULL) + if (ctx == 0) return -ENOMEM; atomic_set(&ctx->ref_count, 1); ctx->tx_seq_num = 1; @@ -424,7 +423,7 @@ int oz_cdev_start(struct oz_pd *pd, int resume) spin_unlock_bh(&pd->app_lock[OZ_APPID_SERIAL-1]); } spin_lock(&g_cdev.lock); - if ((g_cdev.active_pd == NULL) && + if ((g_cdev.active_pd == 0) && (memcmp(pd->mac_addr, g_cdev.active_addr, ETH_ALEN) == 0)) { oz_pd_get(pd); g_cdev.active_pd = pd; @@ -477,7 +476,7 @@ void oz_cdev_rx(struct oz_pd *pd, struct oz_elt *elt) int ix; ctx = oz_cdev_claim_ctx(pd); - if (ctx == NULL) { + if (ctx == 0) { oz_trace("Cannot claim serial context.\n"); return; } diff --git a/trunk/drivers/staging/ozwpan/ozevent.c b/trunk/drivers/staging/ozwpan/ozevent.c index a48498bd9b5f..7f66b4f19b01 100644 --- a/trunk/drivers/staging/ozwpan/ozevent.c +++ b/trunk/drivers/staging/ozwpan/ozevent.c @@ -14,7 +14,7 @@ #include "ozappif.h" /*------------------------------------------------------------------------------ * Although the event mask is logically part of the oz_evtdev structure, it is - * needed outside of this file so define it separately to avoid the need to + * needed outside of this file so define it seperately to avoid the need to * export definition of struct oz_evtdev. */ u32 g_evt_mask; @@ -39,8 +39,8 @@ static struct oz_evtdev g_evtdev; */ void oz_event_init(void) { - /* Because g_evtdev is static external all fields initially zero so no - * need to reinitialized those. + /* Because g_evtdev is static external all fields initally zero so no + * need to reinitialised those. */ oz_trace("Event tracing initialized\n"); spin_lock_init(&g_evtdev.lock); diff --git a/trunk/drivers/staging/ozwpan/ozhcd.c b/trunk/drivers/staging/ozwpan/ozhcd.c index 2e087acf1578..251f07c39a6b 100644 --- a/trunk/drivers/staging/ozwpan/ozhcd.c +++ b/trunk/drivers/staging/ozwpan/ozhcd.c @@ -414,44 +414,6 @@ static void oz_ep_free(struct oz_port *port, struct oz_endpoint *ep) oz_trace("Freeing endpoint memory\n"); kfree(ep); } -/*------------------------------------------------------------------------------ - * Context: softirq - */ -void oz_complete_buffered_urb(struct oz_port *port, struct oz_endpoint *ep, - struct urb *urb) -{ - u8 data_len, available_space, copy_len; - - memcpy(&data_len, &ep->buffer[ep->out_ix], sizeof(u8)); - if (data_len <= urb->transfer_buffer_length) - available_space = data_len; - else - available_space = urb->transfer_buffer_length; - - if (++ep->out_ix == ep->buffer_size) - ep->out_ix = 0; - copy_len = ep->buffer_size - ep->out_ix; - if (copy_len >= available_space) - copy_len = available_space; - memcpy(urb->transfer_buffer, &ep->buffer[ep->out_ix], copy_len); - - if (copy_len < available_space) { - memcpy((urb->transfer_buffer + copy_len), ep->buffer, - (available_space - copy_len)); - ep->out_ix = available_space - copy_len; - } else { - ep->out_ix += copy_len; - } - urb->actual_length = available_space; - if (ep->out_ix == ep->buffer_size) - ep->out_ix = 0; - - ep->buffered_units--; - oz_trace("Trying to give back buffered frame of size=%d\n", - available_space); - oz_complete_urb(port->ozhcd->hcd, urb, 0, 0); -} - /*------------------------------------------------------------------------------ * Context: softirq */ @@ -490,18 +452,6 @@ static int oz_enqueue_ep_urb(struct oz_port *port, u8 ep_addr, int in_dir, ep = port->in_ep[ep_addr]; else ep = port->out_ep[ep_addr]; - - /*For interrupt endpoint check for buffered data - * & complete urb - */ - if (((ep->attrib & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT) - && ep->buffered_units > 0) { - oz_free_urb_link(urbl); - spin_unlock_bh(&port->ozhcd->hcd_lock); - oz_complete_buffered_urb(port, ep, urb); - return 0; - } - if (ep && port->hpd) { list_add_tail(&urbl->link, &ep->urb_list); if (!in_dir && ep_addr && (ep->credit < 0)) { @@ -933,14 +883,13 @@ void oz_hcd_control_cnf(void *hport, u8 req_id, u8 rcode, u8 *data, } else { int copy_len; oz_trace("VENDOR-CLASS - cnf\n"); - if (data_len) { - if (data_len <= urb->transfer_buffer_length) - copy_len = data_len; - else - copy_len = urb->transfer_buffer_length; + if (data_len <= urb->transfer_buffer_length) + copy_len = data_len; + else + copy_len = urb->transfer_buffer_length; + if (copy_len) memcpy(urb->transfer_buffer, data, copy_len); - urb->actual_length = copy_len; - } + urb->actual_length = copy_len; oz_complete_urb(hcd, urb, 0, 0); } } @@ -1012,9 +961,6 @@ void oz_hcd_data_ind(void *hport, u8 endpoint, u8 *data, int data_len) urb->actual_length = copy_len; oz_complete_urb(port->ozhcd->hcd, urb, 0, 0); return; - } else { - oz_trace("buffering frame as URB is not available\n"); - oz_hcd_buffer_data(ep, data, data_len); } break; case USB_ENDPOINT_XFER_ISOC: @@ -1054,7 +1000,7 @@ int oz_hcd_heartbeat(void *hport) ep = ep_from_link(e); if (ep->credit < 0) continue; - ep->credit += jiffies_to_msecs(now - ep->last_jiffies); + ep->credit += (now - ep->last_jiffies); if (ep->credit > ep->credit_ceiling) ep->credit = ep->credit_ceiling; oz_event_log(OZ_EVT_EP_CREDIT, ep->ep_num, 0, 0, ep->credit); @@ -1063,12 +1009,13 @@ int oz_hcd_heartbeat(void *hport) urbl = list_first_entry(&ep->urb_list, struct oz_urb_link, link); urb = urbl->urb; - if ((ep->credit + 1) < urb->number_of_packets) + if (ep->credit < urb->number_of_packets) break; ep->credit -= urb->number_of_packets; oz_event_log(OZ_EVT_EP_CREDIT, ep->ep_num, 0, 0, ep->credit); - list_move_tail(&urbl->link, &xfr_list); + list_del(&urbl->link); + list_add_tail(&urbl->link, &xfr_list); } } spin_unlock_bh(&ozhcd->hcd_lock); @@ -1105,7 +1052,7 @@ int oz_hcd_heartbeat(void *hport) } continue; } - ep->credit += jiffies_to_msecs(now - ep->last_jiffies); + ep->credit += (now - ep->last_jiffies); oz_event_log(OZ_EVT_EP_CREDIT, ep->ep_num | USB_DIR_IN, 0, 0, ep->credit); ep->last_jiffies = now; @@ -1117,7 +1064,7 @@ int oz_hcd_heartbeat(void *hport) int len = 0; int copy_len; int i; - if ((ep->credit + 1) < urb->number_of_packets) + if (ep->credit < urb->number_of_packets) break; if (ep->buffered_units < urb->number_of_packets) break; @@ -1149,7 +1096,8 @@ int oz_hcd_heartbeat(void *hport) urb->error_count = 0; urb->start_frame = ep->start_frame; ep->start_frame += urb->number_of_packets; - list_move_tail(&urbl->link, &xfr_list); + list_del(&urbl->link); + list_add_tail(&urbl->link, &xfr_list); ep->credit -= urb->number_of_packets; oz_event_log(OZ_EVT_EP_CREDIT, ep->ep_num | USB_DIR_IN, 0, 0, ep->credit); @@ -1181,7 +1129,8 @@ int oz_hcd_heartbeat(void *hport) oz_trace("%ld: Request 0x%p timeout\n", now, urbl->urb); urbl->submit_jiffies = now; - list_move_tail(e, &xfr_list); + list_del(e); + list_add_tail(e, &xfr_list); } } if (!list_empty(&ep->urb_list)) @@ -1218,16 +1167,10 @@ static int oz_build_endpoints_for_interface(struct usb_hcd *hcd, int buffer_size = 0; oz_trace("%d bEndpointAddress = %x\n", i, ep_addr); - if (ep_addr & USB_ENDPOINT_DIR_MASK) { - switch (hep->desc.bmAttributes & - USB_ENDPOINT_XFERTYPE_MASK) { - case USB_ENDPOINT_XFER_ISOC: - buffer_size = 24*1024; - break; - case USB_ENDPOINT_XFER_INT: - buffer_size = 128; - break; - } + if ((ep_addr & USB_ENDPOINT_DIR_MASK) && + ((hep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) + == USB_ENDPOINT_XFER_ISOC)) { + buffer_size = 24*1024; } ep = oz_ep_alloc(mem_flags, buffer_size); @@ -1304,14 +1247,16 @@ static void oz_clean_endpoints_for_interface(struct usb_hcd *hcd, port->out_ep[i] = 0; /* Remove from isoc list if present. */ - list_move_tail(e, &ep_list); + list_del(e); + list_add_tail(e, &ep_list); } /* Gather IN endpoints. */ if ((mask & (1<<(i+OZ_NB_ENDPOINTS))) && port->in_ep[i]) { e = &port->in_ep[i]->link; port->in_ep[i] = 0; - list_move_tail(e, &ep_list); + list_del(e); + list_add_tail(e, &ep_list); } } spin_unlock_bh(&ozhcd->hcd_lock); @@ -1513,7 +1458,6 @@ static void oz_process_ep0_urb(struct oz_hcd *ozhcd, struct urb *urb, int data_len = 0; if ((setup->bRequestType & USB_DIR_IN) == 0) data_len = wlength; - urb->actual_length = data_len; if (oz_usb_control_req(port->hpd, req_id, setup, urb->transfer_buffer, data_len)) { rc = -ENOMEM; diff --git a/trunk/drivers/staging/ozwpan/ozmain.c b/trunk/drivers/staging/ozwpan/ozmain.c index ef6c5ab753ee..c1ed6b2522ec 100644 --- a/trunk/drivers/staging/ozwpan/ozmain.c +++ b/trunk/drivers/staging/ozwpan/ozmain.c @@ -59,6 +59,6 @@ module_exit(ozwpan_exit); MODULE_AUTHOR("Chris Kelly"); MODULE_DESCRIPTION("Ozmo Devices USB over WiFi hcd driver"); -MODULE_VERSION("1.0.13"); +MODULE_VERSION("1.0.10"); MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/staging/ozwpan/ozpd.c b/trunk/drivers/staging/ozwpan/ozpd.c index 0b3648ce9687..6c287ac6eaea 100644 --- a/trunk/drivers/staging/ozwpan/ozpd.c +++ b/trunk/drivers/staging/ozwpan/ozpd.c @@ -24,6 +24,12 @@ /*------------------------------------------------------------------------------ */ #define OZ_MAX_TX_POOL_SIZE 6 +/* Maximum number of uncompleted isoc frames that can be pending in network. + */ +#define OZ_MAX_SUBMITTED_ISOC 16 +/* Maximum number of uncompleted isoc frames that can be pending in Tx Queue. + */ +#define OZ_MAX_TX_QUEUE_ISOC 32 /*------------------------------------------------------------------------------ */ static struct oz_tx_frame *oz_tx_frame_alloc(struct oz_pd *pd); @@ -746,7 +752,8 @@ int oz_isoc_stream_create(struct oz_pd *pd, u8 ep_num) */ static void oz_isoc_stream_free(struct oz_isoc_stream *st) { - kfree_skb(st->skb); + if (st->skb) + kfree_skb(st->skb); kfree(st); } /*------------------------------------------------------------------------------ @@ -847,7 +854,7 @@ int oz_send_isoc_unit(struct oz_pd *pd, u8 ep_num, u8 *data, int len) if (!(pd->mode & OZ_F_ISOC_ANYTIME)) { struct oz_tx_frame *isoc_unit = NULL; int nb = pd->nb_queued_isoc_frames; - if (nb >= pd->isoc_latency) { + if (nb >= OZ_MAX_TX_QUEUE_ISOC) { oz_trace2(OZ_TRACE_TX_FRAMES, "Dropping ISOC Unit nb= %d\n", nb); diff --git a/trunk/drivers/staging/ozwpan/ozpd.h b/trunk/drivers/staging/ozwpan/ozpd.h index d35b0ea44f67..ddf1341b4e67 100644 --- a/trunk/drivers/staging/ozwpan/ozpd.h +++ b/trunk/drivers/staging/ozwpan/ozpd.h @@ -82,7 +82,6 @@ struct oz_pd { u8 heartbeat_requested; u8 mode; u8 ms_per_isoc; - unsigned isoc_latency; unsigned max_stream_buffering; int nb_queued_frames; int nb_queued_isoc_frames; diff --git a/trunk/drivers/staging/ozwpan/ozproto.c b/trunk/drivers/staging/ozwpan/ozproto.c index cfb5160d1ebe..a50ab18a5987 100644 --- a/trunk/drivers/staging/ozwpan/ozproto.c +++ b/trunk/drivers/staging/ozwpan/ozproto.c @@ -220,19 +220,6 @@ static struct oz_pd *oz_connect_req(struct oz_pd *cur_pd, struct oz_elt *elt, pd->ms_per_isoc = body->ms_per_isoc; if (!pd->ms_per_isoc) pd->ms_per_isoc = 4; - - switch (body->ms_isoc_latency & OZ_LATENCY_MASK) { - case OZ_ONE_MS_LATENCY: - pd->isoc_latency = (body->ms_isoc_latency & - ~OZ_LATENCY_MASK) / pd->ms_per_isoc; - break; - case OZ_TEN_MS_LATENCY: - pd->isoc_latency = ((body->ms_isoc_latency & - ~OZ_LATENCY_MASK) * 10) / pd->ms_per_isoc; - break; - default: - pd->isoc_latency = OZ_MAX_TX_QUEUE_ISOC; - } } if (body->max_len_div16) pd->max_tx_size = ((u16)body->max_len_div16)<<4; diff --git a/trunk/drivers/staging/ozwpan/ozproto.h b/trunk/drivers/staging/ozwpan/ozproto.h index 755a08d0e1ca..89aea28bd8d5 100644 --- a/trunk/drivers/staging/ozwpan/ozproto.h +++ b/trunk/drivers/staging/ozwpan/ozproto.h @@ -14,7 +14,7 @@ /* Converts millisecs to jiffies. */ -#define oz_ms_to_jiffies(__x) msecs_to_jiffies(__x) +#define oz_ms_to_jiffies(__x) (((__x)*1000)/HZ) /* Quantum milliseconds. */ @@ -30,12 +30,6 @@ /* Maximun sizes of tx frames. */ #define OZ_MAX_TX_SIZE 1514 -/* Maximum number of uncompleted isoc frames that can be pending in network. */ -#define OZ_MAX_SUBMITTED_ISOC 16 - -/* Maximum number of uncompleted isoc frames that can be pending in Tx Queue. */ -#define OZ_MAX_TX_QUEUE_ISOC 32 - /* Application handler functions. */ typedef int (*oz_app_init_fn_t)(void); diff --git a/trunk/drivers/staging/ozwpan/ozprotocol.h b/trunk/drivers/staging/ozwpan/ozprotocol.h index 17b09b9a5b08..1e4edbeb61cd 100644 --- a/trunk/drivers/staging/ozwpan/ozprotocol.h +++ b/trunk/drivers/staging/ozwpan/ozprotocol.h @@ -65,10 +65,6 @@ struct oz_hdr { #define OZ_LAST_PN_HALF_CYCLE 127 -#define OZ_LATENCY_MASK 0xc0 -#define OZ_ONE_MS_LATENCY 0x40 -#define OZ_TEN_MS_LATENCY 0x80 - /* Connect request data structure. */ struct oz_elt_connect_req { @@ -77,7 +73,7 @@ struct oz_elt_connect_req { u8 pd_info; u8 session_id; u8 presleep; - u8 ms_isoc_latency; + u8 resv2; u8 host_vendor; u8 keep_alive; u16 apps; diff --git a/trunk/drivers/staging/panel/panel.c b/trunk/drivers/staging/panel/panel.c index 6e9f7090c451..39f9982c2708 100644 --- a/trunk/drivers/staging/panel/panel.c +++ b/trunk/drivers/staging/panel/panel.c @@ -137,8 +137,8 @@ #define r_ctr(x) (parport_read_control((x)->port)) #define r_dtr(x) (parport_read_data((x)->port)) #define r_str(x) (parport_read_status((x)->port)) -#define w_ctr(x, y) (parport_write_control((x)->port, (y))) -#define w_dtr(x, y) (parport_write_data((x)->port, (y))) +#define w_ctr(x, y) do { parport_write_control((x)->port, (y)); } while (0) +#define w_dtr(x, y) do { parport_write_data((x)->port, (y)); } while (0) /* this defines which bits are to be used and which ones to be ignored */ /* logical or of the output bits involved in the scan matrix */ @@ -757,38 +757,38 @@ static void lcd_backlight(int on) return; /* The backlight is activated by setting the AUTOFEED line to +5V */ - spin_lock_irq(&pprt_lock); + spin_lock(&pprt_lock); bits.bl = on; panel_set_bits(); - spin_unlock_irq(&pprt_lock); + spin_unlock(&pprt_lock); } /* send a command to the LCD panel in serial mode */ static void lcd_write_cmd_s(int cmd) { - spin_lock_irq(&pprt_lock); + spin_lock(&pprt_lock); lcd_send_serial(0x1F); /* R/W=W, RS=0 */ lcd_send_serial(cmd & 0x0F); lcd_send_serial((cmd >> 4) & 0x0F); udelay(40); /* the shortest command takes at least 40 us */ - spin_unlock_irq(&pprt_lock); + spin_unlock(&pprt_lock); } /* send data to the LCD panel in serial mode */ static void lcd_write_data_s(int data) { - spin_lock_irq(&pprt_lock); + spin_lock(&pprt_lock); lcd_send_serial(0x5F); /* R/W=W, RS=1 */ lcd_send_serial(data & 0x0F); lcd_send_serial((data >> 4) & 0x0F); udelay(40); /* the shortest data takes at least 40 us */ - spin_unlock_irq(&pprt_lock); + spin_unlock(&pprt_lock); } /* send a command to the LCD panel in 8 bits parallel mode */ static void lcd_write_cmd_p8(int cmd) { - spin_lock_irq(&pprt_lock); + spin_lock(&pprt_lock); /* present the data to the data port */ w_dtr(pprt, cmd); udelay(20); /* maintain the data during 20 us before the strobe */ @@ -804,13 +804,13 @@ static void lcd_write_cmd_p8(int cmd) set_ctrl_bits(); udelay(120); /* the shortest command takes at least 120 us */ - spin_unlock_irq(&pprt_lock); + spin_unlock(&pprt_lock); } /* send data to the LCD panel in 8 bits parallel mode */ static void lcd_write_data_p8(int data) { - spin_lock_irq(&pprt_lock); + spin_lock(&pprt_lock); /* present the data to the data port */ w_dtr(pprt, data); udelay(20); /* maintain the data during 20 us before the strobe */ @@ -826,27 +826,27 @@ static void lcd_write_data_p8(int data) set_ctrl_bits(); udelay(45); /* the shortest data takes at least 45 us */ - spin_unlock_irq(&pprt_lock); + spin_unlock(&pprt_lock); } /* send a command to the TI LCD panel */ static void lcd_write_cmd_tilcd(int cmd) { - spin_lock_irq(&pprt_lock); + spin_lock(&pprt_lock); /* present the data to the control port */ w_ctr(pprt, cmd); udelay(60); - spin_unlock_irq(&pprt_lock); + spin_unlock(&pprt_lock); } /* send data to the TI LCD panel */ static void lcd_write_data_tilcd(int data) { - spin_lock_irq(&pprt_lock); + spin_lock(&pprt_lock); /* present the data to the data port */ w_dtr(pprt, data); udelay(60); - spin_unlock_irq(&pprt_lock); + spin_unlock(&pprt_lock); } static void lcd_gotoxy(void) @@ -879,14 +879,14 @@ static void lcd_clear_fast_s(void) lcd_addr_x = lcd_addr_y = 0; lcd_gotoxy(); - spin_lock_irq(&pprt_lock); + spin_lock(&pprt_lock); for (pos = 0; pos < lcd_height * lcd_hwidth; pos++) { lcd_send_serial(0x5F); /* R/W=W, RS=1 */ lcd_send_serial(' ' & 0x0F); lcd_send_serial((' ' >> 4) & 0x0F); udelay(40); /* the shortest data takes at least 40 us */ } - spin_unlock_irq(&pprt_lock); + spin_unlock(&pprt_lock); lcd_addr_x = lcd_addr_y = 0; lcd_gotoxy(); @@ -899,7 +899,7 @@ static void lcd_clear_fast_p8(void) lcd_addr_x = lcd_addr_y = 0; lcd_gotoxy(); - spin_lock_irq(&pprt_lock); + spin_lock(&pprt_lock); for (pos = 0; pos < lcd_height * lcd_hwidth; pos++) { /* present the data to the data port */ w_dtr(pprt, ' '); @@ -921,7 +921,7 @@ static void lcd_clear_fast_p8(void) /* the shortest data takes at least 45 us */ udelay(45); } - spin_unlock_irq(&pprt_lock); + spin_unlock(&pprt_lock); lcd_addr_x = lcd_addr_y = 0; lcd_gotoxy(); @@ -934,14 +934,14 @@ static void lcd_clear_fast_tilcd(void) lcd_addr_x = lcd_addr_y = 0; lcd_gotoxy(); - spin_lock_irq(&pprt_lock); + spin_lock(&pprt_lock); for (pos = 0; pos < lcd_height * lcd_hwidth; pos++) { /* present the data to the data port */ w_dtr(pprt, ' '); udelay(60); } - spin_unlock_irq(&pprt_lock); + spin_unlock(&pprt_lock); lcd_addr_x = lcd_addr_y = 0; lcd_gotoxy(); @@ -1197,7 +1197,7 @@ static inline int handle_lcd_special_code(void) break; } - /* Check whether one flag was changed */ + /* Check wether one flag was changed */ if (oldflags != lcd_flags) { /* check whether one of B,C,D flags were changed */ if ((oldflags ^ lcd_flags) & @@ -1212,7 +1212,7 @@ static inline int handle_lcd_special_code(void) lcd_write_cmd(0x30 | ((lcd_flags & LCD_FLAG_F) ? 4 : 0) | ((lcd_flags & LCD_FLAG_N) ? 8 : 0)); - /* check whether L flag was changed */ + /* check wether L flag was changed */ else if ((oldflags ^ lcd_flags) & (LCD_FLAG_L)) { if (lcd_flags & (LCD_FLAG_L)) lcd_backlight(1); @@ -1886,11 +1886,11 @@ static void panel_process_inputs(void) static void panel_scan_timer(void) { if (keypad_enabled && keypad_initialized) { - if (spin_trylock_irq(&pprt_lock)) { + if (spin_trylock(&pprt_lock)) { phys_scan_contacts(); /* no need for the parport anymore */ - spin_unlock_irq(&pprt_lock); + spin_unlock(&pprt_lock); } if (!inputs_stable || phys_curr != phys_prev) diff --git a/trunk/drivers/staging/ramster/Kconfig b/trunk/drivers/staging/ramster/Kconfig index 843c54101438..8349887827dc 100644 --- a/trunk/drivers/staging/ramster/Kconfig +++ b/trunk/drivers/staging/ramster/Kconfig @@ -1,30 +1,13 @@ -config ZCACHE2 - bool "Dynamic compression of swap pages and clean pagecache pages" - depends on CRYPTO=y && SWAP=y && CLEANCACHE && FRONTSWAP && !ZCACHE - select CRYPTO_LZO - default n - help - Zcache2 doubles RAM efficiency while providing a significant - performance boosts on many workloads. Zcache2 uses - compression and an in-kernel implementation of transcendent - memory to store clean page cache pages and swap in RAM, - providing a noticeable reduction in disk I/O. Zcache2 - is a complete rewrite of the older zcache; it was intended to - be a merge but that has been blocked due to political and - technical disagreements. It is intended that they will merge - again in the future. Until then, zcache2 is a single-node - version of ramster. - config RAMSTER bool "Cross-machine RAM capacity sharing, aka peer-to-peer tmem" - depends on CONFIGFS_FS=y && SYSFS=y && !HIGHMEM && ZCACHE2=y - # must ensure struct page is 8-byte aligned - select HAVE_ALIGNED_STRUCT_PAGE if !64_BIT + depends on (CLEANCACHE || FRONTSWAP) && CONFIGFS_FS=y && !ZCACHE && !XVMALLOC && !HIGHMEM && NET + select LZO_COMPRESS + select LZO_DECOMPRESS default n help RAMster allows RAM on other machines in a cluster to be utilized dynamically and symmetrically instead of swapping to a local swap disk, thus improving performance on memory-constrained workloads while minimizing total RAM across the cluster. RAMster, like - zcache2, compresses swap pages into local RAM, but then remotifies + zcache, compresses swap pages into local RAM, but then remotifies the compressed pages to another node in the RAMster cluster. diff --git a/trunk/drivers/staging/ramster/Makefile b/trunk/drivers/staging/ramster/Makefile index 2d8b9d0a6a8b..bcc13c87f996 100644 --- a/trunk/drivers/staging/ramster/Makefile +++ b/trunk/drivers/staging/ramster/Makefile @@ -1,6 +1 @@ -zcache-y := zcache-main.o tmem.o zbud.o -zcache-$(CONFIG_RAMSTER) += ramster/ramster.o ramster/r2net.o -zcache-$(CONFIG_RAMSTER) += ramster/nodemanager.o ramster/tcp.o -zcache-$(CONFIG_RAMSTER) += ramster/heartbeat.o ramster/masklog.o - -obj-$(CONFIG_ZCACHE2) += zcache.o +obj-$(CONFIG_RAMSTER) += zcache-main.o tmem.o r2net.o xvmalloc.o cluster/ diff --git a/trunk/drivers/staging/ramster/TODO b/trunk/drivers/staging/ramster/TODO new file mode 100644 index 000000000000..46fcf0c58acf --- /dev/null +++ b/trunk/drivers/staging/ramster/TODO @@ -0,0 +1,13 @@ +For this staging driver, RAMster duplicates code from drivers/staging/zcache +then incorporates changes to the local copy of the code. For V5, it also +directly incorporates the soon-to-be-removed drivers/staging/zram/xvmalloc.[ch] +as all testing has been done with xvmalloc rather than the new zsmalloc. +Before RAMster can be promoted from staging, the zcache and RAMster drivers +should be either merged or reorganized to separate out common code. + +Until V4, RAMster duplicated code from fs/ocfs2/cluster, but this made +RAMster incompatible with ocfs2 running in the same kernel and included +lots of code that could be removed. As of V5, the ocfs2 code has been +mined and made RAMster-specific, made to communicate with a userland +ramster-tools package rather than ocfs2-tools, and can co-exist with ocfs2 +both in the same kernel and in userland on the same machine. diff --git a/trunk/drivers/staging/ramster/cluster/Makefile b/trunk/drivers/staging/ramster/cluster/Makefile new file mode 100644 index 000000000000..9c6943652c01 --- /dev/null +++ b/trunk/drivers/staging/ramster/cluster/Makefile @@ -0,0 +1,3 @@ +obj-$(CONFIG_RAMSTER) += ramster_nodemanager.o + +ramster_nodemanager-objs := heartbeat.o masklog.o nodemanager.o tcp.o diff --git a/trunk/drivers/staging/ramster/ramster/heartbeat.c b/trunk/drivers/staging/ramster/cluster/heartbeat.c similarity index 98% rename from trunk/drivers/staging/ramster/ramster/heartbeat.c rename to trunk/drivers/staging/ramster/cluster/heartbeat.c index 75d3fe80b055..00209490756e 100644 --- a/trunk/drivers/staging/ramster/ramster/heartbeat.c +++ b/trunk/drivers/staging/ramster/cluster/heartbeat.c @@ -172,7 +172,8 @@ static void r2hb_hb_group_drop_item(struct config_group *group, struct config_item *item) { if (r2hb_global_heartbeat_active()) { - pr_notice("ramster: Heartbeat %s on region %s (%s)\n", + printk(KERN_NOTICE "ramster: Heartbeat %s " + "on region %s (%s)\n", "stopped/aborted", config_item_name(item), "no region"); } @@ -264,7 +265,8 @@ ssize_t r2hb_hb_group_mode_store(struct r2hb_hb_group *group, ret = r2hb_global_hearbeat_mode_set(i); if (!ret) - pr_notice("ramster: Heartbeat mode set to %s\n", + printk(KERN_NOTICE "ramster: Heartbeat mode " + "set to %s\n", r2hb_heartbeat_mode_desc[i]); return count; } diff --git a/trunk/drivers/staging/ramster/ramster/heartbeat.h b/trunk/drivers/staging/ramster/cluster/heartbeat.h similarity index 100% rename from trunk/drivers/staging/ramster/ramster/heartbeat.h rename to trunk/drivers/staging/ramster/cluster/heartbeat.h diff --git a/trunk/drivers/staging/ramster/ramster/masklog.c b/trunk/drivers/staging/ramster/cluster/masklog.c similarity index 100% rename from trunk/drivers/staging/ramster/ramster/masklog.c rename to trunk/drivers/staging/ramster/cluster/masklog.c diff --git a/trunk/drivers/staging/ramster/ramster/masklog.h b/trunk/drivers/staging/ramster/cluster/masklog.h similarity index 100% rename from trunk/drivers/staging/ramster/ramster/masklog.h rename to trunk/drivers/staging/ramster/cluster/masklog.h diff --git a/trunk/drivers/staging/ramster/ramster/nodemanager.c b/trunk/drivers/staging/ramster/cluster/nodemanager.c similarity index 98% rename from trunk/drivers/staging/ramster/ramster/nodemanager.c rename to trunk/drivers/staging/ramster/cluster/nodemanager.c index c0f48158735d..de0e5c8da6ea 100644 --- a/trunk/drivers/staging/ramster/ramster/nodemanager.c +++ b/trunk/drivers/staging/ramster/cluster/nodemanager.c @@ -528,8 +528,7 @@ static ssize_t r2nm_cluster_attr_idle_timeout_ms_write( r2net_num_connected_peers()); ret = -EINVAL; } else if (val <= cluster->cl_keepalive_delay_ms) { - mlog(ML_NOTICE, - "r2net: idle timeout must be larger " + mlog(ML_NOTICE, "r2net: idle timeout must be larger " "than keepalive delay\n"); ret = -EINVAL; } else { @@ -564,8 +563,7 @@ static ssize_t r2nm_cluster_attr_keepalive_delay_ms_write( r2net_num_connected_peers()); ret = -EINVAL; } else if (val >= cluster->cl_idle_timeout_ms) { - mlog(ML_NOTICE, - "r2net: keepalive delay must be " + mlog(ML_NOTICE, "r2net: keepalive delay must be " "smaller than idle timeout\n"); ret = -EINVAL; } else { @@ -614,7 +612,7 @@ static ssize_t r2nm_cluster_attr_fence_method_write( if (strncasecmp(page, r2nm_fence_method_desc[i], count - 1)) continue; if (cluster->cl_fence_method != i) { - pr_info("ramster: Changing fence method to %s\n", + printk(KERN_INFO "ramster: Changing fence method to %s\n", r2nm_fence_method_desc[i]); cluster->cl_fence_method = i; } @@ -969,7 +967,7 @@ static int __init init_r2nm(void) mutex_init(&r2nm_cluster_group.cs_subsys.su_mutex); ret = configfs_register_subsystem(&r2nm_cluster_group.cs_subsys); if (ret) { - pr_err("nodemanager: Registration returned %d\n", ret); + printk(KERN_ERR "nodemanager: Registration returned %d\n", ret); goto out_callbacks; } @@ -990,6 +988,5 @@ static int __init init_r2nm(void) MODULE_AUTHOR("Oracle"); MODULE_LICENSE("GPL"); -/* module_init(init_r2nm) */ -late_initcall(init_r2nm); -/* module_exit(exit_r2nm) */ +module_init(init_r2nm) +module_exit(exit_r2nm) diff --git a/trunk/drivers/staging/ramster/ramster/nodemanager.h b/trunk/drivers/staging/ramster/cluster/nodemanager.h similarity index 100% rename from trunk/drivers/staging/ramster/ramster/nodemanager.h rename to trunk/drivers/staging/ramster/cluster/nodemanager.h diff --git a/trunk/drivers/staging/ramster/ramster/ramster_nodemanager.h b/trunk/drivers/staging/ramster/cluster/ramster_nodemanager.h similarity index 100% rename from trunk/drivers/staging/ramster/ramster/ramster_nodemanager.h rename to trunk/drivers/staging/ramster/cluster/ramster_nodemanager.h diff --git a/trunk/drivers/staging/ramster/ramster/tcp.c b/trunk/drivers/staging/ramster/cluster/tcp.c similarity index 97% rename from trunk/drivers/staging/ramster/ramster/tcp.c rename to trunk/drivers/staging/ramster/cluster/tcp.c index aa2a1a763aa4..d0a07d722b61 100644 --- a/trunk/drivers/staging/ramster/ramster/tcp.c +++ b/trunk/drivers/staging/ramster/cluster/tcp.c @@ -541,7 +541,8 @@ static void r2net_set_nn_state(struct r2net_node *nn, } if (was_valid && !valid) { - pr_notice("ramster: No longer connected to " SC_NODEF_FMT "\n", + printk(KERN_NOTICE "ramster: No longer connected to " + SC_NODEF_FMT "\n", old_sc->sc_node->nd_name, old_sc->sc_node->nd_num, &old_sc->sc_node->nd_ipv4_address, ntohs(old_sc->sc_node->nd_ipv4_port)); @@ -550,7 +551,7 @@ static void r2net_set_nn_state(struct r2net_node *nn, if (!was_valid && valid) { cancel_delayed_work(&nn->nn_connect_expired); - pr_notice("ramster: %s " SC_NODEF_FMT "\n", + printk(KERN_NOTICE "ramster: %s " SC_NODEF_FMT "\n", r2nm_this_node() > sc->sc_node->nd_num ? "Connected to" : "Accepted connection from", sc->sc_node->nd_name, sc->sc_node->nd_num, @@ -643,7 +644,7 @@ static void r2net_state_change(struct sock *sk) r2net_sc_queue_work(sc, &sc->sc_connect_work); break; default: - pr_info("ramster: Connection to " + printk(KERN_INFO "ramster: Connection to " SC_NODEF_FMT " shutdown, state %d\n", sc->sc_node->nd_name, sc->sc_node->nd_num, &sc->sc_node->nd_ipv4_address, @@ -1159,8 +1160,7 @@ int r2net_send_message_vec(u32 msg_type, u32 key, struct kvec *caller_vec, /* wait on other node's handler */ r2net_set_nst_status_time(&nst); - wait_event(nsw.ns_wq, r2net_nsw_completed(nn, &nsw) || - nn->nn_persistent_error || !nn->nn_sc_valid); + wait_event(nsw.ns_wq, r2net_nsw_completed(nn, &nsw)); r2net_update_send_stats(&nst, sc); @@ -1325,10 +1325,8 @@ static int r2net_process_message(struct r2net_sock_container *sc, if (be16_to_cpu(hdr->data_len) > nmh->nh_max_len) syserr = R2NET_ERR_OVERFLOW; - if (syserr != R2NET_ERR_NONE) { - pr_err("ramster_r2net, message length problem\n"); + if (syserr != R2NET_ERR_NONE) goto out_respond; - } r2net_set_func_start_time(sc); sc->sc_msg_key = be32_to_cpu(hdr->key); @@ -1395,7 +1393,7 @@ static int r2net_check_handshake(struct r2net_sock_container *sc) struct r2net_node *nn = r2net_nn_from_num(sc->sc_node->nd_num); if (hand->protocol_version != cpu_to_be64(R2NET_PROTOCOL_VERSION)) { - pr_notice("ramster: " SC_NODEF_FMT " Advertised net " + printk(KERN_NOTICE "ramster: " SC_NODEF_FMT " Advertised net " "protocol version %llu but %llu is required. " "Disconnecting.\n", sc->sc_node->nd_name, sc->sc_node->nd_num, &sc->sc_node->nd_ipv4_address, @@ -1415,7 +1413,7 @@ static int r2net_check_handshake(struct r2net_sock_container *sc) */ if (be32_to_cpu(hand->r2net_idle_timeout_ms) != r2net_idle_timeout()) { - pr_notice("ramster: " SC_NODEF_FMT " uses a network " + printk(KERN_NOTICE "ramster: " SC_NODEF_FMT " uses a network " "idle timeout of %u ms, but we use %u ms locally. " "Disconnecting.\n", sc->sc_node->nd_name, sc->sc_node->nd_num, &sc->sc_node->nd_ipv4_address, @@ -1428,7 +1426,7 @@ static int r2net_check_handshake(struct r2net_sock_container *sc) if (be32_to_cpu(hand->r2net_keepalive_delay_ms) != r2net_keepalive_delay()) { - pr_notice("ramster: " SC_NODEF_FMT " uses a keepalive " + printk(KERN_NOTICE "ramster: " SC_NODEF_FMT " uses a keepalive " "delay of %u ms, but we use %u ms locally. " "Disconnecting.\n", sc->sc_node->nd_name, sc->sc_node->nd_num, &sc->sc_node->nd_ipv4_address, @@ -1441,7 +1439,7 @@ static int r2net_check_handshake(struct r2net_sock_container *sc) if (be32_to_cpu(hand->r2hb_heartbeat_timeout_ms) != R2HB_MAX_WRITE_TIMEOUT_MS) { - pr_notice("ramster: " SC_NODEF_FMT " uses a heartbeat " + printk(KERN_NOTICE "ramster: " SC_NODEF_FMT " uses a heartbeat " "timeout of %u ms, but we use %u ms locally. " "Disconnecting.\n", sc->sc_node->nd_name, sc->sc_node->nd_num, &sc->sc_node->nd_ipv4_address, @@ -1518,7 +1516,6 @@ static int r2net_advance_rx(struct r2net_sock_container *sc) if (be16_to_cpu(hdr->data_len) > R2NET_MAX_PAYLOAD_BYTES) ret = -EOVERFLOW; - WARN_ON_ONCE(ret == -EOVERFLOW); } } if (ret <= 0) @@ -1586,6 +1583,7 @@ static void r2net_rx_until_empty(struct work_struct *work) /* not permanent so read failed handshake can retry */ r2net_ensure_shutdown(nn, sc, 0); } + sc_put(sc); } @@ -1661,7 +1659,6 @@ static void r2net_sc_send_keep_req(struct work_struct *work) static void r2net_idle_timer(unsigned long data) { struct r2net_sock_container *sc = (struct r2net_sock_container *)data; - struct r2net_node *nn = r2net_nn_from_num(sc->sc_node->nd_num); #ifdef CONFIG_DEBUG_FS unsigned long msecs = ktime_to_ms(ktime_get()) - ktime_to_ms(sc->sc_tv_timer); @@ -1669,7 +1666,7 @@ static void r2net_idle_timer(unsigned long data) unsigned long msecs = r2net_idle_timeout(); #endif - pr_notice("ramster: Connection to " SC_NODEF_FMT " has been " + printk(KERN_NOTICE "ramster: Connection to " SC_NODEF_FMT " has been " "idle for %lu.%lu secs, shutting it down.\n", sc->sc_node->nd_name, sc->sc_node->nd_num, &sc->sc_node->nd_ipv4_address, ntohs(sc->sc_node->nd_ipv4_port), @@ -1679,8 +1676,13 @@ static void r2net_idle_timer(unsigned long data) * Initialize the nn_timeout so that the next connection attempt * will continue in r2net_start_connect. */ + /* Avoid spurious shutdowns... not sure if this is still necessary */ + pr_err("ramster_idle_timer, skipping shutdown work\n"); +#if 0 + /* old code used to do these two lines */ atomic_set(&nn->nn_timeout, 1); r2net_sc_queue_work(sc, &sc->sc_shutdown_work); +#endif } static void r2net_sc_reset_idle_timer(struct r2net_sock_container *sc) @@ -1805,7 +1807,7 @@ static void r2net_start_connect(struct work_struct *work) out: if (ret) { - pr_notice("ramster: Connect attempt to " SC_NODEF_FMT + printk(KERN_NOTICE "ramster: Connect attempt to " SC_NODEF_FMT " failed with errno %d\n", sc->sc_node->nd_name, sc->sc_node->nd_num, &sc->sc_node->nd_ipv4_address, ntohs(sc->sc_node->nd_ipv4_port), ret); @@ -1831,7 +1833,7 @@ static void r2net_connect_expired(struct work_struct *work) spin_lock(&nn->nn_lock); if (!nn->nn_sc_valid) { - pr_notice("ramster: No connection established with " + printk(KERN_NOTICE "ramster: No connection established with " "node %u after %u.%u seconds, giving up.\n", r2net_num_from_nn(nn), r2net_idle_timeout() / 1000, @@ -1967,7 +1969,7 @@ static int r2net_accept_one(struct socket *sock) node = r2nm_get_node_by_ip(sin.sin_addr.s_addr); if (node == NULL) { - pr_notice("ramster: Attempt to connect from unknown " + printk(KERN_NOTICE "ramster: Attempt to connect from unknown " "node at %pI4:%d\n", &sin.sin_addr.s_addr, ntohs(sin.sin_port)); ret = -EINVAL; @@ -1976,7 +1978,7 @@ static int r2net_accept_one(struct socket *sock) if (r2nm_this_node() >= node->nd_num) { local_node = r2nm_get_node_by_num(r2nm_this_node()); - pr_notice("ramster: Unexpected connect attempt seen " + printk(KERN_NOTICE "ramster: Unexpected connect attempt seen " "at node '%s' (%u, %pI4:%d) from node '%s' (%u, " "%pI4:%d)\n", local_node->nd_name, local_node->nd_num, &(local_node->nd_ipv4_address), @@ -2006,7 +2008,7 @@ static int r2net_accept_one(struct socket *sock) ret = 0; spin_unlock(&nn->nn_lock); if (ret) { - pr_notice("ramster: Attempt to connect from node '%s' " + printk(KERN_NOTICE "ramster: Attempt to connect from node '%s' " "at %pI4:%d but it already has an open connection\n", node->nd_name, &sin.sin_addr.s_addr, ntohs(sin.sin_port)); @@ -2089,7 +2091,8 @@ static int r2net_open_listening_sock(__be32 addr, __be16 port) ret = sock_create(PF_INET, SOCK_STREAM, IPPROTO_TCP, &sock); if (ret < 0) { - pr_err("ramster: Error %d while creating socket\n", ret); + printk(KERN_ERR "ramster: Error %d while creating socket\n", + ret); goto out; } @@ -2103,17 +2106,17 @@ static int r2net_open_listening_sock(__be32 addr, __be16 port) r2net_listen_sock = sock; INIT_WORK(&r2net_listen_work, r2net_accept_many); - sock->sk->sk_reuse = /* SK_CAN_REUSE FIXME FOR 3.4 */ 1; + sock->sk->sk_reuse = SK_CAN_REUSE; ret = sock->ops->bind(sock, (struct sockaddr *)&sin, sizeof(sin)); if (ret < 0) { - pr_err("ramster: Error %d while binding socket at %pI4:%u\n", - ret, &addr, ntohs(port)); + printk(KERN_ERR "ramster: Error %d while binding socket at " + "%pI4:%u\n", ret, &addr, ntohs(port)); goto out; } ret = sock->ops->listen(sock, 64); if (ret < 0) - pr_err("ramster: Error %d while listening on %pI4:%u\n", + printk(KERN_ERR "ramster: Error %d while listening on %pI4:%u\n", ret, &addr, ntohs(port)); out: diff --git a/trunk/drivers/staging/ramster/ramster/tcp.h b/trunk/drivers/staging/ramster/cluster/tcp.h similarity index 100% rename from trunk/drivers/staging/ramster/ramster/tcp.h rename to trunk/drivers/staging/ramster/cluster/tcp.h diff --git a/trunk/drivers/staging/ramster/ramster/tcp_internal.h b/trunk/drivers/staging/ramster/cluster/tcp_internal.h similarity index 100% rename from trunk/drivers/staging/ramster/ramster/tcp_internal.h rename to trunk/drivers/staging/ramster/cluster/tcp_internal.h diff --git a/trunk/drivers/staging/ramster/ramster/r2net.c b/trunk/drivers/staging/ramster/r2net.c similarity index 86% rename from trunk/drivers/staging/ramster/ramster/r2net.c rename to trunk/drivers/staging/ramster/r2net.c index 34818dc65612..fc830c3ac74b 100644 --- a/trunk/drivers/staging/ramster/ramster/r2net.c +++ b/trunk/drivers/staging/ramster/r2net.c @@ -1,7 +1,7 @@ /* * r2net.c * - * Copyright (c) 2011-2012, Dan Magenheimer, Oracle Corp. + * Copyright (c) 2011, Dan Magenheimer, Oracle Corp. * * Ramster_r2net provides an interface between zcache and r2net. * @@ -9,10 +9,10 @@ */ #include -#include "tcp.h" -#include "nodemanager.h" -#include "../tmem.h" -#include "../zcache.h" +#include "cluster/tcp.h" +#include "cluster/nodemanager.h" +#include "tmem.h" +#include "zcache.h" #include "ramster.h" #define RAMSTER_TESTING @@ -33,7 +33,7 @@ enum { #define RMSTR_R2NET_MAX_LEN \ (R2NET_MAX_PAYLOAD_BYTES - sizeof(struct tmem_xhandle)) -#include "tcp_internal.h" +#include "cluster/tcp_internal.h" static struct r2nm_node *r2net_target_node; static int r2net_target_nodenum; @@ -72,8 +72,8 @@ static int ramster_remote_async_get_request_handler(struct r2net_msg *msg, *(struct tmem_xhandle *)pdata = xh; pdata += sizeof(struct tmem_xhandle); local_irq_save(flags); - found = zcache_get_page(xh.client_id, xh.pool_id, &xh.oid, xh.index, - pdata, &size, true, get_and_free ? 1 : -1); + found = zcache_get(xh.client_id, xh.pool_id, &xh.oid, xh.index, + pdata, &size, 1, get_and_free ? 1 : -1); local_irq_restore(flags); if (found < 0) { /* a zero size indicates the get failed */ @@ -98,7 +98,7 @@ static int ramster_remote_async_get_reply_handler(struct r2net_msg *msg, in += sizeof(struct tmem_xhandle); datalen -= sizeof(struct tmem_xhandle); BUG_ON(datalen < 0 || datalen > PAGE_SIZE); - ret = ramster_localify(xh->pool_id, &xh->oid, xh->index, + ret = zcache_localify(xh->pool_id, &xh->oid, xh->index, in, datalen, xh->extra); #ifdef RAMSTER_TESTING if (ret == -EEXIST) @@ -123,8 +123,8 @@ int ramster_remote_put_handler(struct r2net_msg *msg, p += sizeof(struct tmem_xhandle); zcache_autocreate_pool(xh->client_id, xh->pool_id, ephemeral); local_irq_save(flags); - ret = zcache_put_page(xh->client_id, xh->pool_id, &xh->oid, xh->index, - p, datalen, true, ephemeral); + ret = zcache_put(xh->client_id, xh->pool_id, &xh->oid, xh->index, + p, datalen, 1, ephemeral ? 1 : -1); local_irq_restore(flags); return ret; } @@ -137,8 +137,7 @@ int ramster_remote_flush_handler(struct r2net_msg *msg, xh = (struct tmem_xhandle *)p; p += sizeof(struct tmem_xhandle); - (void)zcache_flush_page(xh->client_id, xh->pool_id, - &xh->oid, xh->index); + (void)zcache_flush(xh->client_id, xh->pool_id, &xh->oid, xh->index); return 0; } @@ -154,16 +153,15 @@ int ramster_remote_flobj_handler(struct r2net_msg *msg, return 0; } -int r2net_remote_async_get(struct tmem_xhandle *xh, bool free, int remotenode, +int ramster_remote_async_get(struct tmem_xhandle *xh, bool free, int remotenode, size_t expect_size, uint8_t expect_cksum, void *extra) { - int nodenum, ret = -1, status; + int ret = -1, status; struct r2nm_node *node = NULL; struct kvec vec[1]; size_t veclen = 1; u32 msg_type; - struct r2net_node *nn; node = r2nm_get_node_by_num(remotenode); if (node == NULL) @@ -174,21 +172,6 @@ int r2net_remote_async_get(struct tmem_xhandle *xh, bool free, int remotenode, xh->extra = extra; vec[0].iov_len = sizeof(*xh); vec[0].iov_base = xh; - - node = r2net_target_node; - if (!node) - goto out; - - nodenum = r2net_target_nodenum; - - r2nm_node_get(node); - nn = r2net_nn_from_num(nodenum); - if (nn->nn_persistent_error || !nn->nn_sc_valid) { - ret = -ENOTCONN; - r2nm_node_put(node); - goto out; - } - if (free) msg_type = RMSTR_TMEM_ASYNC_GET_AND_FREE_REQUEST; else @@ -197,13 +180,8 @@ int r2net_remote_async_get(struct tmem_xhandle *xh, bool free, int remotenode, vec, veclen, remotenode, &status); r2nm_node_put(node); if (ret < 0) { - if (ret == -ENOTCONN || ret == -EHOSTDOWN) - goto out; - if (ret == -EAGAIN) - goto out; /* FIXME handle bad message possibilities here? */ - pr_err("UNTESTED ret<0 in ramster_remote_async_get: ret=%d\n", - ret); + pr_err("UNTESTED ret<0 in ramster_remote_async_get\n"); } ret = status; out: @@ -241,7 +219,7 @@ static void ramster_check_irq_counts(void) } #endif -int r2net_remote_put(struct tmem_xhandle *xh, char *data, size_t size, +int ramster_remote_put(struct tmem_xhandle *xh, char *data, size_t size, bool ephemeral, int *remotenode) { int nodenum, ret = -1, status; @@ -249,7 +227,9 @@ int r2net_remote_put(struct tmem_xhandle *xh, char *data, size_t size, struct kvec vec[2]; size_t veclen = 2; u32 msg_type; +#ifdef RAMSTER_TESTING struct r2net_node *nn; +#endif BUG_ON(size > RMSTR_R2NET_MAX_LEN); xh->client_id = r2nm_this_node(); /* which node is putting */ @@ -257,7 +237,6 @@ int r2net_remote_put(struct tmem_xhandle *xh, char *data, size_t size, vec[0].iov_base = xh; vec[1].iov_len = size; vec[1].iov_base = data; - node = r2net_target_node; if (!node) goto out; @@ -266,12 +245,10 @@ int r2net_remote_put(struct tmem_xhandle *xh, char *data, size_t size, r2nm_node_get(node); +#ifdef RAMSTER_TESTING nn = r2net_nn_from_num(nodenum); - if (nn->nn_persistent_error || !nn->nn_sc_valid) { - ret = -ENOTCONN; - r2nm_node_put(node); - goto out; - } + WARN_ON_ONCE(nn->nn_persistent_error || !nn->nn_sc_valid); +#endif if (ephemeral) msg_type = RMSTR_TMEM_PUT_EPH; @@ -284,6 +261,16 @@ int r2net_remote_put(struct tmem_xhandle *xh, char *data, size_t size, ret = r2net_send_message_vec(msg_type, RMSTR_KEY, vec, veclen, nodenum, &status); +#ifdef RAMSTER_TESTING + if (ret != 0) { + static unsigned long cnt; + cnt++; + if (!(cnt&(cnt-1))) + pr_err("ramster_remote_put: message failed, ret=%d, cnt=%lu\n", + ret, cnt); + ret = -1; + } +#endif if (ret < 0) ret = -1; else { @@ -296,7 +283,7 @@ int r2net_remote_put(struct tmem_xhandle *xh, char *data, size_t size, return ret; } -int r2net_remote_flush(struct tmem_xhandle *xh, int remotenode) +int ramster_remote_flush(struct tmem_xhandle *xh, int remotenode) { int ret = -1, status; struct r2nm_node *node = NULL; @@ -316,7 +303,7 @@ int r2net_remote_flush(struct tmem_xhandle *xh, int remotenode) return ret; } -int r2net_remote_flush_object(struct tmem_xhandle *xh, int remotenode) +int ramster_remote_flush_object(struct tmem_xhandle *xh, int remotenode) { int ret = -1, status; struct r2nm_node *node = NULL; diff --git a/trunk/drivers/staging/ramster/ramster.h b/trunk/drivers/staging/ramster/ramster.h index 1b71aea2ff62..0c9455e8dcd8 100644 --- a/trunk/drivers/staging/ramster/ramster.h +++ b/trunk/drivers/staging/ramster/ramster.h @@ -1,59 +1,118 @@ - /* - * zcache/ramster.h + * ramster.h * - * Placeholder to resolve ramster references when !CONFIG_RAMSTER - * Real ramster.h lives in ramster subdirectory. + * Peer-to-peer transcendent memory * * Copyright (c) 2009-2012, Dan Magenheimer, Oracle Corp. */ -#ifndef _ZCACHE_RAMSTER_H_ -#define _ZCACHE_RAMSTER_H_ +#ifndef _RAMSTER_H_ +#define _RAMSTER_H_ -#ifdef CONFIG_RAMSTER -#include "ramster/ramster.h" -#else -static inline void ramster_init(bool x, bool y, bool z) -{ -} +/* + * format of remote pampd: + * bit 0 == intransit + * bit 1 == is_remote... if this bit is set, then + * bit 2-9 == remotenode + * bit 10-22 == size + * bit 23-30 == cksum + */ +#define FAKE_PAMPD_INTRANSIT_BITS 1 +#define FAKE_PAMPD_ISREMOTE_BITS 1 +#define FAKE_PAMPD_REMOTENODE_BITS 8 +#define FAKE_PAMPD_REMOTESIZE_BITS 13 +#define FAKE_PAMPD_CHECKSUM_BITS 8 -static inline void ramster_register_pamops(struct tmem_pamops *p) +#define FAKE_PAMPD_INTRANSIT_SHIFT 0 +#define FAKE_PAMPD_ISREMOTE_SHIFT (FAKE_PAMPD_INTRANSIT_SHIFT + \ + FAKE_PAMPD_INTRANSIT_BITS) +#define FAKE_PAMPD_REMOTENODE_SHIFT (FAKE_PAMPD_ISREMOTE_SHIFT + \ + FAKE_PAMPD_ISREMOTE_BITS) +#define FAKE_PAMPD_REMOTESIZE_SHIFT (FAKE_PAMPD_REMOTENODE_SHIFT + \ + FAKE_PAMPD_REMOTENODE_BITS) +#define FAKE_PAMPD_CHECKSUM_SHIFT (FAKE_PAMPD_REMOTESIZE_SHIFT + \ + FAKE_PAMPD_REMOTESIZE_BITS) + +#define FAKE_PAMPD_MASK(x) ((1UL << (x)) - 1) + +static inline void *pampd_make_remote(int remotenode, size_t size, + unsigned char cksum) { + unsigned long fake_pampd = 0; + fake_pampd |= 1UL << FAKE_PAMPD_ISREMOTE_SHIFT; + fake_pampd |= ((unsigned long)remotenode & + FAKE_PAMPD_MASK(FAKE_PAMPD_REMOTENODE_BITS)) << + FAKE_PAMPD_REMOTENODE_SHIFT; + fake_pampd |= ((unsigned long)size & + FAKE_PAMPD_MASK(FAKE_PAMPD_REMOTESIZE_BITS)) << + FAKE_PAMPD_REMOTESIZE_SHIFT; + fake_pampd |= ((unsigned long)cksum & + FAKE_PAMPD_MASK(FAKE_PAMPD_CHECKSUM_BITS)) << + FAKE_PAMPD_CHECKSUM_SHIFT; + return (void *)fake_pampd; } -static inline int ramster_remotify_pageframe(bool b) +static inline unsigned int pampd_remote_node(void *pampd) { - return 0; + unsigned long fake_pampd = (unsigned long)pampd; + return (fake_pampd >> FAKE_PAMPD_REMOTENODE_SHIFT) & + FAKE_PAMPD_MASK(FAKE_PAMPD_REMOTENODE_BITS); } -static inline void *ramster_pampd_free(void *v, struct tmem_pool *p, - struct tmem_oid *o, uint32_t u, bool b) +static inline unsigned int pampd_remote_size(void *pampd) { - return NULL; + unsigned long fake_pampd = (unsigned long)pampd; + return (fake_pampd >> FAKE_PAMPD_REMOTESIZE_SHIFT) & + FAKE_PAMPD_MASK(FAKE_PAMPD_REMOTESIZE_BITS); } -static inline int ramster_do_preload_flnode(struct tmem_pool *p) +static inline unsigned char pampd_remote_cksum(void *pampd) { - return -1; + unsigned long fake_pampd = (unsigned long)pampd; + return (fake_pampd >> FAKE_PAMPD_CHECKSUM_SHIFT) & + FAKE_PAMPD_MASK(FAKE_PAMPD_CHECKSUM_BITS); } -static inline bool pampd_is_remote(void *v) +static inline bool pampd_is_remote(void *pampd) { - return false; + unsigned long fake_pampd = (unsigned long)pampd; + return (fake_pampd >> FAKE_PAMPD_ISREMOTE_SHIFT) & + FAKE_PAMPD_MASK(FAKE_PAMPD_ISREMOTE_BITS); } -static inline void ramster_count_foreign_pages(bool b, int i) +static inline bool pampd_is_intransit(void *pampd) { + unsigned long fake_pampd = (unsigned long)pampd; + return (fake_pampd >> FAKE_PAMPD_INTRANSIT_SHIFT) & + FAKE_PAMPD_MASK(FAKE_PAMPD_INTRANSIT_BITS); } -static inline void ramster_cpu_up(int cpu) +/* note that it is a BUG for intransit to be set without isremote also set */ +static inline void *pampd_mark_intransit(void *pampd) { + unsigned long fake_pampd = (unsigned long)pampd; + + fake_pampd |= 1UL << FAKE_PAMPD_ISREMOTE_SHIFT; + fake_pampd |= 1UL << FAKE_PAMPD_INTRANSIT_SHIFT; + return (void *)fake_pampd; } -static inline void ramster_cpu_down(int cpu) +static inline void *pampd_mask_intransit_and_remote(void *marked_pampd) { + unsigned long pampd = (unsigned long)marked_pampd; + + pampd &= ~(1UL << FAKE_PAMPD_INTRANSIT_SHIFT); + pampd &= ~(1UL << FAKE_PAMPD_ISREMOTE_SHIFT); + return (void *)pampd; } -#endif -#endif /* _ZCACHE_RAMSTER_H */ +extern int ramster_remote_async_get(struct tmem_xhandle *, + bool, int, size_t, uint8_t, void *extra); +extern int ramster_remote_put(struct tmem_xhandle *, char *, size_t, + bool, int *); +extern int ramster_remote_flush(struct tmem_xhandle *, int); +extern int ramster_remote_flush_object(struct tmem_xhandle *, int); +extern int r2net_register_handlers(void); +extern int r2net_remote_target_node_set(int); + +#endif /* _TMEM_H */ diff --git a/trunk/drivers/staging/ramster/ramster/ramster.c b/trunk/drivers/staging/ramster/ramster/ramster.c deleted file mode 100644 index c06709f39682..000000000000 --- a/trunk/drivers/staging/ramster/ramster/ramster.c +++ /dev/null @@ -1,985 +0,0 @@ -/* - * ramster.c - * - * Copyright (c) 2010-2012, Dan Magenheimer, Oracle Corp. - * - * RAMster implements peer-to-peer transcendent memory, allowing a "cluster" of - * kernels to dynamically pool their RAM so that a RAM-hungry workload on one - * machine can temporarily and transparently utilize RAM on another machine - * which is presumably idle or running a non-RAM-hungry workload. - * - * RAMster combines a clustering and messaging foundation based on the ocfs2 - * cluster layer with the in-kernel compression implementation of zcache, and - * adds code to glue them together. When a page is "put" to RAMster, it is - * compressed and stored locally. Periodically, a thread will "remotify" these - * pages by sending them via messages to a remote machine. When the page is - * later needed as indicated by a page fault, a "get" is issued. If the data - * is local, it is uncompressed and the fault is resolved. If the data is - * remote, a message is sent to fetch the data and the faulting thread sleeps; - * when the data arrives, the thread awakens, the data is decompressed and - * the fault is resolved. - - * As of V5, clusters up to eight nodes are supported; each node can remotify - * pages to one specified node, so clusters can be configured as clients to - * a "memory server". Some simple policy is in place that will need to be - * refined over time. Larger clusters and fault-resistant protocols can also - * be added over time. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "../tmem.h" -#include "../zcache.h" -#include "../zbud.h" -#include "ramster.h" -#include "ramster_nodemanager.h" -#include "tcp.h" - -#define RAMSTER_TESTING - -#ifndef CONFIG_SYSFS -#error "ramster needs sysfs to define cluster nodes to use" -#endif - -static bool use_cleancache __read_mostly; -static bool use_frontswap __read_mostly; -static bool use_frontswap_exclusive_gets __read_mostly; - -/* These must be sysfs not debugfs as they are checked/used by userland!! */ -static unsigned long ramster_interface_revision __read_mostly = - R2NM_API_VERSION; /* interface revision must match userspace! */ -static unsigned long ramster_pers_remotify_enable __read_mostly; -static unsigned long ramster_eph_remotify_enable __read_mostly; -static atomic_t ramster_remote_pers_pages = ATOMIC_INIT(0); -#define MANUAL_NODES 8 -static bool ramster_nodes_manual_up[MANUAL_NODES] __read_mostly; -static int ramster_remote_target_nodenum __read_mostly = -1; - -/* these counters are made available via debugfs */ -static long ramster_flnodes; -static atomic_t ramster_flnodes_atomic = ATOMIC_INIT(0); -static unsigned long ramster_flnodes_max; -static long ramster_foreign_eph_pages; -static atomic_t ramster_foreign_eph_pages_atomic = ATOMIC_INIT(0); -static unsigned long ramster_foreign_eph_pages_max; -static long ramster_foreign_pers_pages; -static atomic_t ramster_foreign_pers_pages_atomic = ATOMIC_INIT(0); -static unsigned long ramster_foreign_pers_pages_max; -static unsigned long ramster_eph_pages_remoted; -static unsigned long ramster_pers_pages_remoted; -static unsigned long ramster_eph_pages_remote_failed; -static unsigned long ramster_pers_pages_remote_failed; -static unsigned long ramster_remote_eph_pages_succ_get; -static unsigned long ramster_remote_pers_pages_succ_get; -static unsigned long ramster_remote_eph_pages_unsucc_get; -static unsigned long ramster_remote_pers_pages_unsucc_get; -static unsigned long ramster_pers_pages_remote_nomem; -static unsigned long ramster_remote_objects_flushed; -static unsigned long ramster_remote_object_flushes_failed; -static unsigned long ramster_remote_pages_flushed; -static unsigned long ramster_remote_page_flushes_failed; -/* FIXME frontswap selfshrinking knobs in debugfs? */ - -#ifdef CONFIG_DEBUG_FS -#include -#define zdfs debugfs_create_size_t -#define zdfs64 debugfs_create_u64 -static int __init ramster_debugfs_init(void) -{ - struct dentry *root = debugfs_create_dir("ramster", NULL); - if (root == NULL) - return -ENXIO; - - zdfs("eph_pages_remoted", S_IRUGO, root, &ramster_eph_pages_remoted); - zdfs("pers_pages_remoted", S_IRUGO, root, &ramster_pers_pages_remoted); - zdfs("eph_pages_remote_failed", S_IRUGO, root, - &ramster_eph_pages_remote_failed); - zdfs("pers_pages_remote_failed", S_IRUGO, root, - &ramster_pers_pages_remote_failed); - zdfs("remote_eph_pages_succ_get", S_IRUGO, root, - &ramster_remote_eph_pages_succ_get); - zdfs("remote_pers_pages_succ_get", S_IRUGO, root, - &ramster_remote_pers_pages_succ_get); - zdfs("remote_eph_pages_unsucc_get", S_IRUGO, root, - &ramster_remote_eph_pages_unsucc_get); - zdfs("remote_pers_pages_unsucc_get", S_IRUGO, root, - &ramster_remote_pers_pages_unsucc_get); - zdfs("pers_pages_remote_nomem", S_IRUGO, root, - &ramster_pers_pages_remote_nomem); - zdfs("remote_objects_flushed", S_IRUGO, root, - &ramster_remote_objects_flushed); - zdfs("remote_pages_flushed", S_IRUGO, root, - &ramster_remote_pages_flushed); - zdfs("remote_object_flushes_failed", S_IRUGO, root, - &ramster_remote_object_flushes_failed); - zdfs("remote_page_flushes_failed", S_IRUGO, root, - &ramster_remote_page_flushes_failed); - zdfs("foreign_eph_pages", S_IRUGO, root, - &ramster_foreign_eph_pages); - zdfs("foreign_eph_pages_max", S_IRUGO, root, - &ramster_foreign_eph_pages_max); - zdfs("foreign_pers_pages", S_IRUGO, root, - &ramster_foreign_pers_pages); - zdfs("foreign_pers_pages_max", S_IRUGO, root, - &ramster_foreign_pers_pages_max); - return 0; -} -#undef zdebugfs -#undef zdfs64 -#endif - -static LIST_HEAD(ramster_rem_op_list); -static DEFINE_SPINLOCK(ramster_rem_op_list_lock); -static DEFINE_PER_CPU(struct ramster_preload, ramster_preloads); - -static DEFINE_PER_CPU(unsigned char *, ramster_remoteputmem1); -static DEFINE_PER_CPU(unsigned char *, ramster_remoteputmem2); - -static struct kmem_cache *ramster_flnode_cache __read_mostly; - -static struct flushlist_node *ramster_flnode_alloc(struct tmem_pool *pool) -{ - struct flushlist_node *flnode = NULL; - struct ramster_preload *kp; - - kp = &__get_cpu_var(ramster_preloads); - flnode = kp->flnode; - BUG_ON(flnode == NULL); - kp->flnode = NULL; - ramster_flnodes = atomic_inc_return(&ramster_flnodes_atomic); - if (ramster_flnodes > ramster_flnodes_max) - ramster_flnodes_max = ramster_flnodes; - return flnode; -} - -/* the "flush list" asynchronously collects pages to remotely flush */ -#define FLUSH_ENTIRE_OBJECT ((uint32_t)-1) -static void ramster_flnode_free(struct flushlist_node *flnode, - struct tmem_pool *pool) -{ - int flnodes; - - flnodes = atomic_dec_return(&ramster_flnodes_atomic); - BUG_ON(flnodes < 0); - kmem_cache_free(ramster_flnode_cache, flnode); -} - -int ramster_do_preload_flnode(struct tmem_pool *pool) -{ - struct ramster_preload *kp; - struct flushlist_node *flnode; - int ret = -ENOMEM; - - BUG_ON(!irqs_disabled()); - if (unlikely(ramster_flnode_cache == NULL)) - BUG(); - kp = &__get_cpu_var(ramster_preloads); - flnode = kmem_cache_alloc(ramster_flnode_cache, GFP_ATOMIC); - if (unlikely(flnode == NULL) && kp->flnode == NULL) - BUG(); /* FIXME handle more gracefully, but how??? */ - else if (kp->flnode == NULL) - kp->flnode = flnode; - else - kmem_cache_free(ramster_flnode_cache, flnode); - return ret; -} - -/* - * Called by the message handler after a (still compressed) page has been - * fetched from the remote machine in response to an "is_remote" tmem_get - * or persistent tmem_localify. For a tmem_get, "extra" is the address of - * the page that is to be filled to successfully resolve the tmem_get; for - * a (persistent) tmem_localify, "extra" is NULL (as the data is placed only - * in the local zcache). "data" points to "size" bytes of (compressed) data - * passed in the message. In the case of a persistent remote get, if - * pre-allocation was successful (see ramster_repatriate_preload), the page - * is placed into both local zcache and at "extra". - */ -int ramster_localify(int pool_id, struct tmem_oid *oidp, uint32_t index, - char *data, unsigned int size, void *extra) -{ - int ret = -ENOENT; - unsigned long flags; - struct tmem_pool *pool; - bool eph, delete = false; - void *pampd, *saved_hb; - struct tmem_obj *obj; - - pool = zcache_get_pool_by_id(LOCAL_CLIENT, pool_id); - if (unlikely(pool == NULL)) - /* pool doesn't exist anymore */ - goto out; - eph = is_ephemeral(pool); - local_irq_save(flags); /* FIXME: maybe only disable softirqs? */ - pampd = tmem_localify_get_pampd(pool, oidp, index, &obj, &saved_hb); - if (pampd == NULL) { - /* hmmm... must have been a flush while waiting */ -#ifdef RAMSTER_TESTING - pr_err("UNTESTED pampd==NULL in ramster_localify\n"); -#endif - if (eph) - ramster_remote_eph_pages_unsucc_get++; - else - ramster_remote_pers_pages_unsucc_get++; - obj = NULL; - goto finish; - } else if (unlikely(!pampd_is_remote(pampd))) { - /* hmmm... must have been a dup put while waiting */ -#ifdef RAMSTER_TESTING - pr_err("UNTESTED dup while waiting in ramster_localify\n"); -#endif - if (eph) - ramster_remote_eph_pages_unsucc_get++; - else - ramster_remote_pers_pages_unsucc_get++; - obj = NULL; - pampd = NULL; - ret = -EEXIST; - goto finish; - } else if (size == 0) { - /* no remote data, delete the local is_remote pampd */ - pampd = NULL; - if (eph) - ramster_remote_eph_pages_unsucc_get++; - else - BUG(); - delete = true; - goto finish; - } - if (pampd_is_intransit(pampd)) { - /* - * a pampd is marked intransit if it is remote and space has - * been allocated for it locally (note, only happens for - * persistent pages, in which case the remote copy is freed) - */ - BUG_ON(eph); - pampd = pampd_mask_intransit_and_remote(pampd); - zbud_copy_to_zbud(pampd, data, size); - } else { - /* - * setting pampd to NULL tells tmem_localify_finish to leave - * pampd alone... meaning it is left pointing to the - * remote copy - */ - pampd = NULL; - obj = NULL; - } - /* - * but in all cases, we decompress direct-to-memory to complete - * the remotify and return success - */ - BUG_ON(extra == NULL); - zcache_decompress_to_page(data, size, (struct page *)extra); - if (eph) - ramster_remote_eph_pages_succ_get++; - else - ramster_remote_pers_pages_succ_get++; - ret = 0; -finish: - tmem_localify_finish(obj, index, pampd, saved_hb, delete); - zcache_put_pool(pool); - local_irq_restore(flags); -out: - return ret; -} - -void ramster_pampd_new_obj(struct tmem_obj *obj) -{ - obj->extra = NULL; -} - -void ramster_pampd_free_obj(struct tmem_pool *pool, struct tmem_obj *obj, - bool pool_destroy) -{ - struct flushlist_node *flnode; - - BUG_ON(preemptible()); - if (obj->extra == NULL) - return; - if (pool_destroy && is_ephemeral(pool)) - /* FIXME don't bother with remote eph data for now */ - return; - BUG_ON(!pampd_is_remote(obj->extra)); - flnode = ramster_flnode_alloc(pool); - flnode->xh.client_id = pampd_remote_node(obj->extra); - flnode->xh.pool_id = pool->pool_id; - flnode->xh.oid = obj->oid; - flnode->xh.index = FLUSH_ENTIRE_OBJECT; - flnode->rem_op.op = RAMSTER_REMOTIFY_FLUSH_OBJ; - spin_lock(&ramster_rem_op_list_lock); - list_add(&flnode->rem_op.list, &ramster_rem_op_list); - spin_unlock(&ramster_rem_op_list_lock); -} - -/* - * Called on a remote persistent tmem_get to attempt to preallocate - * local storage for the data contained in the remote persistent page. - * If successfully preallocated, returns the pampd, marked as remote and - * in_transit. Else returns NULL. Note that the appropriate tmem data - * structure must be locked. - */ -void *ramster_pampd_repatriate_preload(void *pampd, struct tmem_pool *pool, - struct tmem_oid *oidp, uint32_t index, - bool *intransit) -{ - int clen = pampd_remote_size(pampd), c; - void *ret_pampd = NULL; - unsigned long flags; - struct tmem_handle th; - - BUG_ON(!pampd_is_remote(pampd)); - BUG_ON(is_ephemeral(pool)); - if (use_frontswap_exclusive_gets) - /* don't need local storage */ - goto out; - if (pampd_is_intransit(pampd)) { - /* - * to avoid multiple allocations (and maybe a memory leak) - * don't preallocate if already in the process of being - * repatriated - */ - *intransit = true; - goto out; - } - *intransit = false; - local_irq_save(flags); - th.client_id = pampd_remote_node(pampd); - th.pool_id = pool->pool_id; - th.oid = *oidp; - th.index = index; - ret_pampd = zcache_pampd_create(NULL, clen, true, false, &th); - if (ret_pampd != NULL) { - /* - * a pampd is marked intransit if it is remote and space has - * been allocated for it locally (note, only happens for - * persistent pages, in which case the remote copy is freed) - */ - ret_pampd = pampd_mark_intransit(ret_pampd); - c = atomic_dec_return(&ramster_remote_pers_pages); - WARN_ON_ONCE(c < 0); - } else { - ramster_pers_pages_remote_nomem++; - } - local_irq_restore(flags); -out: - return ret_pampd; -} - -/* - * Called on a remote tmem_get to invoke a message to fetch the page. - * Might sleep so no tmem locks can be held. "extra" is passed - * all the way through the round-trip messaging to ramster_localify. - */ -int ramster_pampd_repatriate(void *fake_pampd, void *real_pampd, - struct tmem_pool *pool, - struct tmem_oid *oid, uint32_t index, - bool free, void *extra) -{ - struct tmem_xhandle xh; - int ret; - - if (pampd_is_intransit(real_pampd)) - /* have local space pre-reserved, so free remote copy */ - free = true; - xh = tmem_xhandle_fill(LOCAL_CLIENT, pool, oid, index); - /* unreliable request/response for now */ - ret = r2net_remote_async_get(&xh, free, - pampd_remote_node(fake_pampd), - pampd_remote_size(fake_pampd), - pampd_remote_cksum(fake_pampd), - extra); - return ret; -} - -bool ramster_pampd_is_remote(void *pampd) -{ - return pampd_is_remote(pampd); -} - -int ramster_pampd_replace_in_obj(void *new_pampd, struct tmem_obj *obj) -{ - int ret = -1; - - if (new_pampd != NULL) { - if (obj->extra == NULL) - obj->extra = new_pampd; - /* enforce that all remote pages in an object reside - * in the same node! */ - else if (pampd_remote_node(new_pampd) != - pampd_remote_node((void *)(obj->extra))) - BUG(); - ret = 0; - } - return ret; -} - -void *ramster_pampd_free(void *pampd, struct tmem_pool *pool, - struct tmem_oid *oid, uint32_t index, bool acct) -{ - bool eph = is_ephemeral(pool); - void *local_pampd = NULL; - int c; - - BUG_ON(preemptible()); - BUG_ON(!pampd_is_remote(pampd)); - WARN_ON(acct == false); - if (oid == NULL) { - /* - * a NULL oid means to ignore this pampd free - * as the remote freeing will be handled elsewhere - */ - } else if (eph) { - /* FIXME remote flush optional but probably good idea */ - } else if (pampd_is_intransit(pampd)) { - /* did a pers remote get_and_free, so just free local */ - local_pampd = pampd_mask_intransit_and_remote(pampd); - } else { - struct flushlist_node *flnode = - ramster_flnode_alloc(pool); - - flnode->xh.client_id = pampd_remote_node(pampd); - flnode->xh.pool_id = pool->pool_id; - flnode->xh.oid = *oid; - flnode->xh.index = index; - flnode->rem_op.op = RAMSTER_REMOTIFY_FLUSH_PAGE; - spin_lock(&ramster_rem_op_list_lock); - list_add(&flnode->rem_op.list, &ramster_rem_op_list); - spin_unlock(&ramster_rem_op_list_lock); - c = atomic_dec_return(&ramster_remote_pers_pages); - WARN_ON_ONCE(c < 0); - } - return local_pampd; -} - -void ramster_count_foreign_pages(bool eph, int count) -{ - int c; - - BUG_ON(count != 1 && count != -1); - if (eph) { - if (count > 0) { - c = atomic_inc_return( - &ramster_foreign_eph_pages_atomic); - if (c > ramster_foreign_eph_pages_max) - ramster_foreign_eph_pages_max = c; - } else { - c = atomic_dec_return(&ramster_foreign_eph_pages_atomic); - WARN_ON_ONCE(c < 0); - } - ramster_foreign_eph_pages = c; - } else { - if (count > 0) { - c = atomic_inc_return( - &ramster_foreign_pers_pages_atomic); - if (c > ramster_foreign_pers_pages_max) - ramster_foreign_pers_pages_max = c; - } else { - c = atomic_dec_return( - &ramster_foreign_pers_pages_atomic); - WARN_ON_ONCE(c < 0); - } - ramster_foreign_pers_pages = c; - } -} - -/* - * For now, just push over a few pages every few seconds to - * ensure that it basically works - */ -static struct workqueue_struct *ramster_remotify_workqueue; -static void ramster_remotify_process(struct work_struct *work); -static DECLARE_DELAYED_WORK(ramster_remotify_worker, - ramster_remotify_process); - -static void ramster_remotify_queue_delayed_work(unsigned long delay) -{ - if (!queue_delayed_work(ramster_remotify_workqueue, - &ramster_remotify_worker, delay)) - pr_err("ramster_remotify: bad workqueue\n"); -} - -static void ramster_remote_flush_page(struct flushlist_node *flnode) -{ - struct tmem_xhandle *xh; - int remotenode, ret; - - preempt_disable(); - xh = &flnode->xh; - remotenode = flnode->xh.client_id; - ret = r2net_remote_flush(xh, remotenode); - if (ret >= 0) - ramster_remote_pages_flushed++; - else - ramster_remote_page_flushes_failed++; - preempt_enable_no_resched(); - ramster_flnode_free(flnode, NULL); -} - -static void ramster_remote_flush_object(struct flushlist_node *flnode) -{ - struct tmem_xhandle *xh; - int remotenode, ret; - - preempt_disable(); - xh = &flnode->xh; - remotenode = flnode->xh.client_id; - ret = r2net_remote_flush_object(xh, remotenode); - if (ret >= 0) - ramster_remote_objects_flushed++; - else - ramster_remote_object_flushes_failed++; - preempt_enable_no_resched(); - ramster_flnode_free(flnode, NULL); -} - -int ramster_remotify_pageframe(bool eph) -{ - struct tmem_xhandle xh; - unsigned int size; - int remotenode, ret, zbuds; - struct tmem_pool *pool; - unsigned long flags; - unsigned char cksum; - char *p; - int i, j; - unsigned char *tmpmem[2]; - struct tmem_handle th[2]; - unsigned int zsize[2]; - - tmpmem[0] = __get_cpu_var(ramster_remoteputmem1); - tmpmem[1] = __get_cpu_var(ramster_remoteputmem2); - local_bh_disable(); - zbuds = zbud_make_zombie_lru(&th[0], &tmpmem[0], &zsize[0], eph); - /* now OK to release lock set in caller */ - local_bh_enable(); - if (zbuds == 0) - goto out; - BUG_ON(zbuds > 2); - for (i = 0; i < zbuds; i++) { - xh.client_id = th[i].client_id; - xh.pool_id = th[i].pool_id; - xh.oid = th[i].oid; - xh.index = th[i].index; - size = zsize[i]; - BUG_ON(size == 0 || size > zbud_max_buddy_size()); - for (p = tmpmem[i], cksum = 0, j = 0; j < size; j++) - cksum += *p++; - ret = r2net_remote_put(&xh, tmpmem[i], size, eph, &remotenode); - if (ret != 0) { - /* - * This is some form of a memory leak... if the remote put - * fails, there will never be another attempt to remotify - * this page. But since we've dropped the zv pointer, - * the page may have been freed or the data replaced - * so we can't just "put it back" in the remote op list. - * Even if we could, not sure where to put it in the list - * because there may be flushes that must be strictly - * ordered vs the put. So leave this as a FIXME for now. - * But count them so we know if it becomes a problem. - */ - if (eph) - ramster_eph_pages_remote_failed++; - else - ramster_pers_pages_remote_failed++; - break; - } else { - if (!eph) - atomic_inc(&ramster_remote_pers_pages); - } - if (eph) - ramster_eph_pages_remoted++; - else - ramster_pers_pages_remoted++; - /* - * data was successfully remoted so change the local version to - * point to the remote node where it landed - */ - local_bh_disable(); - pool = zcache_get_pool_by_id(LOCAL_CLIENT, xh.pool_id); - local_irq_save(flags); - (void)tmem_replace(pool, &xh.oid, xh.index, - pampd_make_remote(remotenode, size, cksum)); - local_irq_restore(flags); - zcache_put_pool(pool); - local_bh_enable(); - } -out: - return zbuds; -} - -static void zcache_do_remotify_flushes(void) -{ - struct ramster_remotify_hdr *rem_op; - union remotify_list_node *u; - - while (1) { - spin_lock(&ramster_rem_op_list_lock); - if (list_empty(&ramster_rem_op_list)) { - spin_unlock(&ramster_rem_op_list_lock); - goto out; - } - rem_op = list_first_entry(&ramster_rem_op_list, - struct ramster_remotify_hdr, list); - list_del_init(&rem_op->list); - spin_unlock(&ramster_rem_op_list_lock); - u = (union remotify_list_node *)rem_op; - switch (rem_op->op) { - case RAMSTER_REMOTIFY_FLUSH_PAGE: - ramster_remote_flush_page((struct flushlist_node *)u); - break; - case RAMSTER_REMOTIFY_FLUSH_OBJ: - ramster_remote_flush_object((struct flushlist_node *)u); - break; - default: - BUG(); - } - } -out: - return; -} - -static void ramster_remotify_process(struct work_struct *work) -{ - static bool remotify_in_progress; - int i; - - BUG_ON(irqs_disabled()); - if (remotify_in_progress) - goto requeue; - if (ramster_remote_target_nodenum == -1) - goto requeue; - remotify_in_progress = true; - if (use_cleancache && ramster_eph_remotify_enable) { - for (i = 0; i < 100; i++) { - zcache_do_remotify_flushes(); - (void)ramster_remotify_pageframe(true); - } - } - if (use_frontswap && ramster_pers_remotify_enable) { - for (i = 0; i < 100; i++) { - zcache_do_remotify_flushes(); - (void)ramster_remotify_pageframe(false); - } - } - remotify_in_progress = false; -requeue: - ramster_remotify_queue_delayed_work(HZ); -} - -void __init ramster_remotify_init(void) -{ - unsigned long n = 60UL; - ramster_remotify_workqueue = - create_singlethread_workqueue("ramster_remotify"); - ramster_remotify_queue_delayed_work(n * HZ); -} - -static ssize_t ramster_manual_node_up_show(struct kobject *kobj, - struct kobj_attribute *attr, char *buf) -{ - int i; - char *p = buf; - for (i = 0; i < MANUAL_NODES; i++) - if (ramster_nodes_manual_up[i]) - p += sprintf(p, "%d ", i); - p += sprintf(p, "\n"); - return p - buf; -} - -static ssize_t ramster_manual_node_up_store(struct kobject *kobj, - struct kobj_attribute *attr, const char *buf, size_t count) -{ - int err; - unsigned long node_num; - - err = kstrtoul(buf, 10, &node_num); - if (err) { - pr_err("ramster: bad strtoul?\n"); - return -EINVAL; - } - if (node_num >= MANUAL_NODES) { - pr_err("ramster: bad node_num=%lu?\n", node_num); - return -EINVAL; - } - if (ramster_nodes_manual_up[node_num]) { - pr_err("ramster: node %d already up, ignoring\n", - (int)node_num); - } else { - ramster_nodes_manual_up[node_num] = true; - r2net_hb_node_up_manual((int)node_num); - } - return count; -} - -static struct kobj_attribute ramster_manual_node_up_attr = { - .attr = { .name = "manual_node_up", .mode = 0644 }, - .show = ramster_manual_node_up_show, - .store = ramster_manual_node_up_store, -}; - -static ssize_t ramster_remote_target_nodenum_show(struct kobject *kobj, - struct kobj_attribute *attr, char *buf) -{ - if (ramster_remote_target_nodenum == -1UL) - return sprintf(buf, "unset\n"); - else - return sprintf(buf, "%d\n", ramster_remote_target_nodenum); -} - -static ssize_t ramster_remote_target_nodenum_store(struct kobject *kobj, - struct kobj_attribute *attr, const char *buf, size_t count) -{ - int err; - unsigned long node_num; - - err = kstrtoul(buf, 10, &node_num); - if (err) { - pr_err("ramster: bad strtoul?\n"); - return -EINVAL; - } else if (node_num == -1UL) { - pr_err("ramster: disabling all remotification, " - "data may still reside on remote nodes however\n"); - return -EINVAL; - } else if (node_num >= MANUAL_NODES) { - pr_err("ramster: bad node_num=%lu?\n", node_num); - return -EINVAL; - } else if (!ramster_nodes_manual_up[node_num]) { - pr_err("ramster: node %d not up, ignoring setting " - "of remotification target\n", (int)node_num); - } else if (r2net_remote_target_node_set((int)node_num) >= 0) { - pr_info("ramster: node %d set as remotification target\n", - (int)node_num); - ramster_remote_target_nodenum = (int)node_num; - } else { - pr_err("ramster: bad num to node node_num=%d?\n", - (int)node_num); - return -EINVAL; - } - return count; -} - -static struct kobj_attribute ramster_remote_target_nodenum_attr = { - .attr = { .name = "remote_target_nodenum", .mode = 0644 }, - .show = ramster_remote_target_nodenum_show, - .store = ramster_remote_target_nodenum_store, -}; - -#define RAMSTER_SYSFS_RO(_name) \ - static ssize_t ramster_##_name##_show(struct kobject *kobj, \ - struct kobj_attribute *attr, char *buf) \ - { \ - return sprintf(buf, "%lu\n", ramster_##_name); \ - } \ - static struct kobj_attribute ramster_##_name##_attr = { \ - .attr = { .name = __stringify(_name), .mode = 0444 }, \ - .show = ramster_##_name##_show, \ - } - -#define RAMSTER_SYSFS_RW(_name) \ - static ssize_t ramster_##_name##_show(struct kobject *kobj, \ - struct kobj_attribute *attr, char *buf) \ - { \ - return sprintf(buf, "%lu\n", ramster_##_name); \ - } \ - static ssize_t ramster_##_name##_store(struct kobject *kobj, \ - struct kobj_attribute *attr, const char *buf, size_t count) \ - { \ - int err; \ - unsigned long enable; \ - err = kstrtoul(buf, 10, &enable); \ - if (err) \ - return -EINVAL; \ - ramster_##_name = enable; \ - return count; \ - } \ - static struct kobj_attribute ramster_##_name##_attr = { \ - .attr = { .name = __stringify(_name), .mode = 0644 }, \ - .show = ramster_##_name##_show, \ - .store = ramster_##_name##_store, \ - } - -#define RAMSTER_SYSFS_RO_ATOMIC(_name) \ - static ssize_t ramster_##_name##_show(struct kobject *kobj, \ - struct kobj_attribute *attr, char *buf) \ - { \ - return sprintf(buf, "%d\n", atomic_read(&ramster_##_name)); \ - } \ - static struct kobj_attribute ramster_##_name##_attr = { \ - .attr = { .name = __stringify(_name), .mode = 0444 }, \ - .show = ramster_##_name##_show, \ - } - -RAMSTER_SYSFS_RO(interface_revision); -RAMSTER_SYSFS_RO_ATOMIC(remote_pers_pages); -RAMSTER_SYSFS_RW(pers_remotify_enable); -RAMSTER_SYSFS_RW(eph_remotify_enable); - -static struct attribute *ramster_attrs[] = { - &ramster_interface_revision_attr.attr, - &ramster_remote_pers_pages_attr.attr, - &ramster_manual_node_up_attr.attr, - &ramster_remote_target_nodenum_attr.attr, - &ramster_pers_remotify_enable_attr.attr, - &ramster_eph_remotify_enable_attr.attr, - NULL, -}; - -static struct attribute_group ramster_attr_group = { - .attrs = ramster_attrs, - .name = "ramster", -}; - -/* - * frontswap selfshrinking - */ - -/* In HZ, controls frequency of worker invocation. */ -static unsigned int selfshrink_interval __read_mostly = 5; -/* Enable/disable with sysfs. */ -static bool frontswap_selfshrinking __read_mostly; - -static void selfshrink_process(struct work_struct *work); -static DECLARE_DELAYED_WORK(selfshrink_worker, selfshrink_process); - -/* Enable/disable with kernel boot option. */ -static bool use_frontswap_selfshrink __initdata = true; - -/* - * The default values for the following parameters were deemed reasonable - * by experimentation, may be workload-dependent, and can all be - * adjusted via sysfs. - */ - -/* Control rate for frontswap shrinking. Higher hysteresis is slower. */ -static unsigned int frontswap_hysteresis __read_mostly = 20; - -/* - * Number of selfshrink worker invocations to wait before observing that - * frontswap selfshrinking should commence. Note that selfshrinking does - * not use a separate worker thread. - */ -static unsigned int frontswap_inertia __read_mostly = 3; - -/* Countdown to next invocation of frontswap_shrink() */ -static unsigned long frontswap_inertia_counter; - -/* - * Invoked by the selfshrink worker thread, uses current number of pages - * in frontswap (frontswap_curr_pages()), previous status, and control - * values (hysteresis and inertia) to determine if frontswap should be - * shrunk and what the new frontswap size should be. Note that - * frontswap_shrink is essentially a partial swapoff that immediately - * transfers pages from the "swap device" (frontswap) back into kernel - * RAM; despite the name, frontswap "shrinking" is very different from - * the "shrinker" interface used by the kernel MM subsystem to reclaim - * memory. - */ -static void frontswap_selfshrink(void) -{ - static unsigned long cur_frontswap_pages; - static unsigned long last_frontswap_pages; - static unsigned long tgt_frontswap_pages; - - last_frontswap_pages = cur_frontswap_pages; - cur_frontswap_pages = frontswap_curr_pages(); - if (!cur_frontswap_pages || - (cur_frontswap_pages > last_frontswap_pages)) { - frontswap_inertia_counter = frontswap_inertia; - return; - } - if (frontswap_inertia_counter && --frontswap_inertia_counter) - return; - if (cur_frontswap_pages <= frontswap_hysteresis) - tgt_frontswap_pages = 0; - else - tgt_frontswap_pages = cur_frontswap_pages - - (cur_frontswap_pages / frontswap_hysteresis); - frontswap_shrink(tgt_frontswap_pages); -} - -static int __init ramster_nofrontswap_selfshrink_setup(char *s) -{ - use_frontswap_selfshrink = false; - return 1; -} - -__setup("noselfshrink", ramster_nofrontswap_selfshrink_setup); - -static void selfshrink_process(struct work_struct *work) -{ - if (frontswap_selfshrinking && frontswap_enabled) { - frontswap_selfshrink(); - schedule_delayed_work(&selfshrink_worker, - selfshrink_interval * HZ); - } -} - -void ramster_cpu_up(int cpu) -{ - unsigned char *p1 = kzalloc(PAGE_SIZE, GFP_KERNEL | __GFP_REPEAT); - unsigned char *p2 = kzalloc(PAGE_SIZE, GFP_KERNEL | __GFP_REPEAT); - BUG_ON(!p1 || !p2); - per_cpu(ramster_remoteputmem1, cpu) = p1; - per_cpu(ramster_remoteputmem2, cpu) = p2; -} - -void ramster_cpu_down(int cpu) -{ - struct ramster_preload *kp; - - kfree(per_cpu(ramster_remoteputmem1, cpu)); - per_cpu(ramster_remoteputmem1, cpu) = NULL; - kfree(per_cpu(ramster_remoteputmem2, cpu)); - per_cpu(ramster_remoteputmem2, cpu) = NULL; - kp = &per_cpu(ramster_preloads, cpu); - if (kp->flnode) { - kmem_cache_free(ramster_flnode_cache, kp->flnode); - kp->flnode = NULL; - } -} - -void ramster_register_pamops(struct tmem_pamops *pamops) -{ - pamops->free_obj = ramster_pampd_free_obj; - pamops->new_obj = ramster_pampd_new_obj; - pamops->replace_in_obj = ramster_pampd_replace_in_obj; - pamops->is_remote = ramster_pampd_is_remote; - pamops->repatriate = ramster_pampd_repatriate; - pamops->repatriate_preload = ramster_pampd_repatriate_preload; -} - -void __init ramster_init(bool cleancache, bool frontswap, - bool frontswap_exclusive_gets) -{ - int ret = 0; - - if (cleancache) - use_cleancache = true; - if (frontswap) - use_frontswap = true; - if (frontswap_exclusive_gets) - use_frontswap_exclusive_gets = true; - ramster_debugfs_init(); - ret = sysfs_create_group(mm_kobj, &ramster_attr_group); - if (ret) - pr_err("ramster: can't create sysfs for ramster\n"); - (void)r2net_register_handlers(); - INIT_LIST_HEAD(&ramster_rem_op_list); - ramster_flnode_cache = kmem_cache_create("ramster_flnode", - sizeof(struct flushlist_node), 0, 0, NULL); - frontswap_selfshrinking = use_frontswap_selfshrink; - if (frontswap_selfshrinking) { - pr_info("ramster: Initializing frontswap selfshrink driver.\n"); - schedule_delayed_work(&selfshrink_worker, - selfshrink_interval * HZ); - } - ramster_remotify_init(); -} diff --git a/trunk/drivers/staging/ramster/ramster/ramster.h b/trunk/drivers/staging/ramster/ramster/ramster.h deleted file mode 100644 index 12ae56f09ca4..000000000000 --- a/trunk/drivers/staging/ramster/ramster/ramster.h +++ /dev/null @@ -1,161 +0,0 @@ -/* - * ramster.h - * - * Peer-to-peer transcendent memory - * - * Copyright (c) 2009-2012, Dan Magenheimer, Oracle Corp. - */ - -#ifndef _RAMSTER_RAMSTER_H_ -#define _RAMSTER_RAMSTER_H_ - -#include "../tmem.h" - -enum ramster_remotify_op { - RAMSTER_REMOTIFY_FLUSH_PAGE, - RAMSTER_REMOTIFY_FLUSH_OBJ, -}; - -struct ramster_remotify_hdr { - enum ramster_remotify_op op; - struct list_head list; -}; - -struct flushlist_node { - struct ramster_remotify_hdr rem_op; - struct tmem_xhandle xh; -}; - -struct ramster_preload { - struct flushlist_node *flnode; -}; - -union remotify_list_node { - struct ramster_remotify_hdr rem_op; - struct { - struct ramster_remotify_hdr rem_op; - struct tmem_handle th; - } zbud_hdr; - struct flushlist_node flist; -}; - -/* - * format of remote pampd: - * bit 0 is reserved for zbud (in-page buddy selection) - * bit 1 == intransit - * bit 2 == is_remote... if this bit is set, then - * bit 3-10 == remotenode - * bit 11-23 == size - * bit 24-31 == cksum - */ -#define FAKE_PAMPD_INTRANSIT_BITS 1 -#define FAKE_PAMPD_ISREMOTE_BITS 1 -#define FAKE_PAMPD_REMOTENODE_BITS 8 -#define FAKE_PAMPD_REMOTESIZE_BITS 13 -#define FAKE_PAMPD_CHECKSUM_BITS 8 - -#define FAKE_PAMPD_INTRANSIT_SHIFT 1 -#define FAKE_PAMPD_ISREMOTE_SHIFT (FAKE_PAMPD_INTRANSIT_SHIFT + \ - FAKE_PAMPD_INTRANSIT_BITS) -#define FAKE_PAMPD_REMOTENODE_SHIFT (FAKE_PAMPD_ISREMOTE_SHIFT + \ - FAKE_PAMPD_ISREMOTE_BITS) -#define FAKE_PAMPD_REMOTESIZE_SHIFT (FAKE_PAMPD_REMOTENODE_SHIFT + \ - FAKE_PAMPD_REMOTENODE_BITS) -#define FAKE_PAMPD_CHECKSUM_SHIFT (FAKE_PAMPD_REMOTESIZE_SHIFT + \ - FAKE_PAMPD_REMOTESIZE_BITS) - -#define FAKE_PAMPD_MASK(x) ((1UL << (x)) - 1) - -static inline void *pampd_make_remote(int remotenode, size_t size, - unsigned char cksum) -{ - unsigned long fake_pampd = 0; - fake_pampd |= 1UL << FAKE_PAMPD_ISREMOTE_SHIFT; - fake_pampd |= ((unsigned long)remotenode & - FAKE_PAMPD_MASK(FAKE_PAMPD_REMOTENODE_BITS)) << - FAKE_PAMPD_REMOTENODE_SHIFT; - fake_pampd |= ((unsigned long)size & - FAKE_PAMPD_MASK(FAKE_PAMPD_REMOTESIZE_BITS)) << - FAKE_PAMPD_REMOTESIZE_SHIFT; - fake_pampd |= ((unsigned long)cksum & - FAKE_PAMPD_MASK(FAKE_PAMPD_CHECKSUM_BITS)) << - FAKE_PAMPD_CHECKSUM_SHIFT; - return (void *)fake_pampd; -} - -static inline unsigned int pampd_remote_node(void *pampd) -{ - unsigned long fake_pampd = (unsigned long)pampd; - return (fake_pampd >> FAKE_PAMPD_REMOTENODE_SHIFT) & - FAKE_PAMPD_MASK(FAKE_PAMPD_REMOTENODE_BITS); -} - -static inline unsigned int pampd_remote_size(void *pampd) -{ - unsigned long fake_pampd = (unsigned long)pampd; - return (fake_pampd >> FAKE_PAMPD_REMOTESIZE_SHIFT) & - FAKE_PAMPD_MASK(FAKE_PAMPD_REMOTESIZE_BITS); -} - -static inline unsigned char pampd_remote_cksum(void *pampd) -{ - unsigned long fake_pampd = (unsigned long)pampd; - return (fake_pampd >> FAKE_PAMPD_CHECKSUM_SHIFT) & - FAKE_PAMPD_MASK(FAKE_PAMPD_CHECKSUM_BITS); -} - -static inline bool pampd_is_remote(void *pampd) -{ - unsigned long fake_pampd = (unsigned long)pampd; - return (fake_pampd >> FAKE_PAMPD_ISREMOTE_SHIFT) & - FAKE_PAMPD_MASK(FAKE_PAMPD_ISREMOTE_BITS); -} - -static inline bool pampd_is_intransit(void *pampd) -{ - unsigned long fake_pampd = (unsigned long)pampd; - return (fake_pampd >> FAKE_PAMPD_INTRANSIT_SHIFT) & - FAKE_PAMPD_MASK(FAKE_PAMPD_INTRANSIT_BITS); -} - -/* note that it is a BUG for intransit to be set without isremote also set */ -static inline void *pampd_mark_intransit(void *pampd) -{ - unsigned long fake_pampd = (unsigned long)pampd; - - fake_pampd |= 1UL << FAKE_PAMPD_ISREMOTE_SHIFT; - fake_pampd |= 1UL << FAKE_PAMPD_INTRANSIT_SHIFT; - return (void *)fake_pampd; -} - -static inline void *pampd_mask_intransit_and_remote(void *marked_pampd) -{ - unsigned long pampd = (unsigned long)marked_pampd; - - pampd &= ~(1UL << FAKE_PAMPD_INTRANSIT_SHIFT); - pampd &= ~(1UL << FAKE_PAMPD_ISREMOTE_SHIFT); - return (void *)pampd; -} - -extern int r2net_remote_async_get(struct tmem_xhandle *, - bool, int, size_t, uint8_t, void *extra); -extern int r2net_remote_put(struct tmem_xhandle *, char *, size_t, - bool, int *); -extern int r2net_remote_flush(struct tmem_xhandle *, int); -extern int r2net_remote_flush_object(struct tmem_xhandle *, int); -extern int r2net_register_handlers(void); -extern int r2net_remote_target_node_set(int); - -extern int ramster_remotify_pageframe(bool); -extern void ramster_init(bool, bool, bool); -extern void ramster_register_pamops(struct tmem_pamops *); -extern int ramster_localify(int, struct tmem_oid *oidp, uint32_t, char *, - unsigned int, void *); -extern void *ramster_pampd_free(void *, struct tmem_pool *, struct tmem_oid *, - uint32_t, bool); -extern void ramster_count_foreign_pages(bool, int); -extern int ramster_do_preload_flnode(struct tmem_pool *); -extern void ramster_cpu_up(int); -extern void ramster_cpu_down(int); - -#endif /* _RAMSTER_RAMSTER_H */ diff --git a/trunk/drivers/staging/ramster/tmem.c b/trunk/drivers/staging/ramster/tmem.c index a2b7e03b6062..8f2f6892d8d3 100644 --- a/trunk/drivers/staging/ramster/tmem.c +++ b/trunk/drivers/staging/ramster/tmem.c @@ -1,43 +1,33 @@ /* * In-kernel transcendent memory (generic implementation) * - * Copyright (c) 2009-2012, Dan Magenheimer, Oracle Corp. + * Copyright (c) 2009-2011, Dan Magenheimer, Oracle Corp. * * The primary purpose of Transcedent Memory ("tmem") is to map object-oriented * "handles" (triples containing a pool id, and object id, and an index), to * pages in a page-accessible memory (PAM). Tmem references the PAM pages via * an abstract "pampd" (PAM page-descriptor), which can be operated on by a * set of functions (pamops). Each pampd contains some representation of - * PAGE_SIZE bytes worth of data. For those familiar with key-value stores, - * the tmem handle is a three-level hierarchical key, and the value is always - * reconstituted (but not necessarily stored) as PAGE_SIZE bytes and is - * referenced in the datastore by the pampd. The hierarchy is required - * to ensure that certain invalidation functions can be performed efficiently - * (i.e. flush all indexes associated with this object_id, or - * flush all objects associated with this pool). - * - * Tmem must support potentially millions of pages and must be able to insert, - * find, and delete these pages at a potential frequency of thousands per - * second concurrently across many CPUs, (and, if used with KVM, across many - * vcpus across many guests). Tmem is tracked with a hierarchy of data - * structures, organized by the elements in the handle-tuple: pool_id, - * object_id, and page index. One or more "clients" (e.g. guests) each - * provide one or more tmem_pools. Each pool, contains a hash table of - * rb_trees of tmem_objs. Each tmem_obj contains a radix-tree-like tree - * of pointers, with intermediate nodes called tmem_objnodes. Each leaf - * pointer in this tree points to a pampd, which is accessible only through - * a small set of callbacks registered by the PAM implementation (see - * tmem_register_pamops). Tmem only needs to memory allocation for objs - * and objnodes and this is done via a set of callbacks that must be - * registered by the tmem host implementation (e.g. see tmem_register_hostops). + * PAGE_SIZE bytes worth of data. Tmem must support potentially millions of + * pages and must be able to insert, find, and delete these pages at a + * potential frequency of thousands per second concurrently across many CPUs, + * (and, if used with KVM, across many vcpus across many guests). + * Tmem is tracked with a hierarchy of data structures, organized by + * the elements in a handle-tuple: pool_id, object_id, and page index. + * One or more "clients" (e.g. guests) each provide one or more tmem_pools. + * Each pool, contains a hash table of rb_trees of tmem_objs. Each + * tmem_obj contains a radix-tree-like tree of pointers, with intermediate + * nodes called tmem_objnodes. Each leaf pointer in this tree points to + * a pampd, which is accessible only through a small set of callbacks + * registered by the PAM implementation (see tmem_register_pamops). Tmem + * does all memory allocation via a set of callbacks registered by the tmem + * host implementation (e.g. see tmem_register_hostops). */ #include #include #include -#ifdef CONFIG_RAMSTER #include -#endif #include "tmem.h" @@ -62,7 +52,7 @@ void tmem_register_hostops(struct tmem_hostops *m) /* * A tmem host implementation must use this function to register - * callbacks for a page-accessible memory (PAM) implementation. + * callbacks for a page-accessible memory (PAM) implementation */ static struct tmem_pamops tmem_pamops; @@ -77,62 +67,42 @@ void tmem_register_pamops(struct tmem_pamops *m) * So an rb_tree is an ideal data structure to manage tmem_objs. But because * of the potentially huge number of tmem_objs, each pool manages a hashtable * of rb_trees to reduce search, insert, delete, and rebalancing time. - * Each hashbucket also has a lock to manage concurrent access and no - * searches, inserts, or deletions can be performed unless the lock is held. - * As a result, care must be taken to ensure tmem routines are not called - * recursively; the vast majority of the time, a recursive call may work - * but a deadlock will occur a small fraction of the time due to the - * hashbucket lock. + * Each hashbucket also has a lock to manage concurrent access. * - * The following routines manage tmem_objs. In all of these routines, - * the hashbucket lock is already held. + * The following routines manage tmem_objs. When any tmem_obj is accessed, + * the hashbucket lock must be held. */ -/* Search for object==oid in pool, returns object if found. */ -static struct tmem_obj *__tmem_obj_find(struct tmem_hashbucket *hb, - struct tmem_oid *oidp, - struct rb_node **parent, - struct rb_node ***link) +/* searches for object==oid in pool, returns locked object if found */ +static struct tmem_obj *tmem_obj_find(struct tmem_hashbucket *hb, + struct tmem_oid *oidp) { - struct rb_node *_parent = NULL, **rbnode; - struct tmem_obj *obj = NULL; + struct rb_node *rbnode; + struct tmem_obj *obj; - rbnode = &hb->obj_rb_root.rb_node; - while (*rbnode) { - BUG_ON(RB_EMPTY_NODE(*rbnode)); - _parent = *rbnode; - obj = rb_entry(*rbnode, struct tmem_obj, - rb_tree_node); + rbnode = hb->obj_rb_root.rb_node; + while (rbnode) { + BUG_ON(RB_EMPTY_NODE(rbnode)); + obj = rb_entry(rbnode, struct tmem_obj, rb_tree_node); switch (tmem_oid_compare(oidp, &obj->oid)) { case 0: /* equal */ goto out; case -1: - rbnode = &(*rbnode)->rb_left; + rbnode = rbnode->rb_left; break; case 1: - rbnode = &(*rbnode)->rb_right; + rbnode = rbnode->rb_right; break; } } - - if (parent) - *parent = _parent; - if (link) - *link = rbnode; obj = NULL; out: return obj; } -static struct tmem_obj *tmem_obj_find(struct tmem_hashbucket *hb, - struct tmem_oid *oidp) -{ - return __tmem_obj_find(hb, oidp, NULL, NULL); -} +static void tmem_pampd_destroy_all_in_obj(struct tmem_obj *); -static void tmem_pampd_destroy_all_in_obj(struct tmem_obj *, bool); - -/* Free an object that has no more pampds in it. */ +/* free an object that has no more pampds in it */ static void tmem_obj_free(struct tmem_obj *obj, struct tmem_hashbucket *hb) { struct tmem_pool *pool; @@ -143,7 +113,7 @@ static void tmem_obj_free(struct tmem_obj *obj, struct tmem_hashbucket *hb) pool = obj->pool; BUG_ON(pool == NULL); if (obj->objnode_tree_root != NULL) /* may be "stump" with no leaves */ - tmem_pampd_destroy_all_in_obj(obj, false); + tmem_pampd_destroy_all_in_obj(obj); BUG_ON(obj->objnode_tree_root != NULL); BUG_ON((long)obj->objnode_count != 0); atomic_dec(&pool->obj_count); @@ -155,14 +125,15 @@ static void tmem_obj_free(struct tmem_obj *obj, struct tmem_hashbucket *hb) } /* - * Initialize, and insert an tmem_object_root (called only if find failed). + * initialize, and insert an tmem_object_root (called only if find failed) */ static void tmem_obj_init(struct tmem_obj *obj, struct tmem_hashbucket *hb, struct tmem_pool *pool, struct tmem_oid *oidp) { struct rb_root *root = &hb->obj_rb_root; - struct rb_node **new = NULL, *parent = NULL; + struct rb_node **new = &(root->rb_node), *parent = NULL; + struct tmem_obj *this; BUG_ON(pool == NULL); atomic_inc(&pool->obj_count); @@ -172,15 +143,24 @@ static void tmem_obj_init(struct tmem_obj *obj, struct tmem_hashbucket *hb, obj->oid = *oidp; obj->objnode_count = 0; obj->pampd_count = 0; -#ifdef CONFIG_RAMSTER - if (tmem_pamops.new_obj != NULL) - (*tmem_pamops.new_obj)(obj); -#endif + (*tmem_pamops.new_obj)(obj); SET_SENTINEL(obj, OBJ); - - if (__tmem_obj_find(hb, oidp, &parent, &new)) - BUG(); - + while (*new) { + BUG_ON(RB_EMPTY_NODE(*new)); + this = rb_entry(*new, struct tmem_obj, rb_tree_node); + parent = *new; + switch (tmem_oid_compare(oidp, &this->oid)) { + case 0: + BUG(); /* already present; should never happen! */ + break; + case -1: + new = &(*new)->rb_left; + break; + case 1: + new = &(*new)->rb_right; + break; + } + } rb_link_node(&obj->rb_tree_node, parent, new); rb_insert_color(&obj->rb_tree_node, root); } @@ -190,7 +170,7 @@ static void tmem_obj_init(struct tmem_obj *obj, struct tmem_hashbucket *hb, * "ephemeral" vs "persistent". These attributes apply to all tmem_objs * and all pampds that belong to a tmem_pool. A tmem_pool is created * or deleted relatively rarely (for example, when a filesystem is - * mounted or unmounted). + * mounted or unmounted. */ /* flush all data from a pool and, optionally, free it */ @@ -208,7 +188,7 @@ static void tmem_pool_flush(struct tmem_pool *pool, bool destroy) while (rbnode != NULL) { obj = rb_entry(rbnode, struct tmem_obj, rb_tree_node); rbnode = rb_next(rbnode); - tmem_pampd_destroy_all_in_obj(obj, true); + tmem_pampd_destroy_all_in_obj(obj); tmem_obj_free(obj, hb); (*tmem_hostops.obj_free)(obj, pool); } @@ -294,7 +274,7 @@ static void tmem_objnode_free(struct tmem_objnode *objnode) } /* - * Lookup index in object and return associated pampd (or NULL if not found). + * lookup index in object and return associated pampd (or NULL if not found) */ static void **__tmem_pampd_lookup_in_obj(struct tmem_obj *obj, uint32_t index) { @@ -336,7 +316,6 @@ static void *tmem_pampd_lookup_in_obj(struct tmem_obj *obj, uint32_t index) return slot != NULL ? *slot : NULL; } -#ifdef CONFIG_RAMSTER static void *tmem_pampd_replace_in_obj(struct tmem_obj *obj, uint32_t index, void *new_pampd, bool no_free) { @@ -354,7 +333,6 @@ static void *tmem_pampd_replace_in_obj(struct tmem_obj *obj, uint32_t index, } return ret; } -#endif static int tmem_pampd_add_to_obj(struct tmem_obj *obj, uint32_t index, void *pampd) @@ -492,7 +470,7 @@ static void *tmem_pampd_delete_from_obj(struct tmem_obj *obj, uint32_t index) return slot; } -/* Recursively walk the objnode_tree destroying pampds and objnodes. */ +/* recursively walk the objnode_tree destroying pampds and objnodes */ static void tmem_objnode_node_destroy(struct tmem_obj *obj, struct tmem_objnode *objnode, unsigned int ht) @@ -517,8 +495,7 @@ static void tmem_objnode_node_destroy(struct tmem_obj *obj, } } -static void tmem_pampd_destroy_all_in_obj(struct tmem_obj *obj, - bool pool_destroy) +static void tmem_pampd_destroy_all_in_obj(struct tmem_obj *obj) { if (obj->objnode_tree_root == NULL) return; @@ -533,10 +510,7 @@ static void tmem_pampd_destroy_all_in_obj(struct tmem_obj *obj, obj->objnode_tree_height = 0; } obj->objnode_tree_root = NULL; -#ifdef CONFIG_RAMSTER - if (tmem_pamops.free_obj != NULL) - (*tmem_pamops.free_obj)(obj->pool, obj, pool_destroy); -#endif + (*tmem_pamops.free_obj)(obj->pool, obj); } /* @@ -549,16 +523,17 @@ static void tmem_pampd_destroy_all_in_obj(struct tmem_obj *obj, */ /* - * "Put" a page, e.g. associate the passed pampd with the passed handle. - * Tmem_put is complicated by a corner case: What if a page with matching - * handle already exists in tmem? To guarantee coherency, one of two - * actions is necessary: Either the data for the page must be overwritten, - * or the page must be "flushed" so that the data is not accessible to a - * subsequent "get". Since these "duplicate puts" are relatively rare, - * this implementation always flushes for simplicity. + * "Put" a page, e.g. copy a page from the kernel into newly allocated + * PAM space (if such space is available). Tmem_put is complicated by + * a corner case: What if a page with matching handle already exists in + * tmem? To guarantee coherency, one of two actions is necessary: Either + * the data for the page must be overwritten, or the page must be + * "flushed" so that the data is not accessible to a subsequent "get". + * Since these "duplicate puts" are relatively rare, this implementation + * always flushes for simplicity. */ int tmem_put(struct tmem_pool *pool, struct tmem_oid *oidp, uint32_t index, - bool raw, void *pampd_to_use) + char *data, size_t size, bool raw, int ephemeral) { struct tmem_obj *obj = NULL, *objfound = NULL, *objnew = NULL; void *pampd = NULL, *pampd_del = NULL; @@ -591,17 +566,19 @@ int tmem_put(struct tmem_pool *pool, struct tmem_oid *oidp, uint32_t index, } BUG_ON(obj == NULL); BUG_ON(((objnew != obj) && (objfound != obj)) || (objnew == objfound)); - pampd = pampd_to_use; - BUG_ON(pampd_to_use == NULL); + pampd = (*tmem_pamops.create)(data, size, raw, ephemeral, + obj->pool, &obj->oid, index); + if (unlikely(pampd == NULL)) + goto free; ret = tmem_pampd_add_to_obj(obj, index, pampd); if (unlikely(ret == -ENOMEM)) /* may have partially built objnode tree ("stump") */ goto delete_and_free; - (*tmem_pamops.create_finish)(pampd, is_ephemeral(pool)); goto out; delete_and_free: (void)tmem_pampd_delete_from_obj(obj, index); +free: if (pampd) (*tmem_pamops.free)(pampd, pool, NULL, 0, true); if (objnew) { @@ -613,16 +590,6 @@ int tmem_put(struct tmem_pool *pool, struct tmem_oid *oidp, uint32_t index, return ret; } -#ifdef CONFIG_RAMSTER -/* - * For ramster only: The following routines provide a two-step sequence - * to allow the caller to replace a pampd in the tmem data structures with - * another pampd. Here, we lookup the passed handle and, if found, return the - * associated pampd and object, leaving the hashbucket locked and returning - * a reference to it. The caller is expected to immediately call the - * matching tmem_localify_finish routine which will handles the replacement - * and unlocks the hashbucket. - */ void *tmem_localify_get_pampd(struct tmem_pool *pool, struct tmem_oid *oidp, uint32_t index, struct tmem_obj **ret_obj, void **saved_hb) @@ -651,7 +618,6 @@ void tmem_localify_finish(struct tmem_obj *obj, uint32_t index, if (pampd != NULL) { BUG_ON(obj == NULL); (void)tmem_pampd_replace_in_obj(obj, index, pampd, 1); - (*tmem_pamops.create_finish)(pampd, is_ephemeral(obj->pool)); } else if (delete) { BUG_ON(obj == NULL); (void)tmem_pampd_delete_from_obj(obj, index); @@ -659,9 +625,6 @@ void tmem_localify_finish(struct tmem_obj *obj, uint32_t index, spin_unlock(&hb->lock); } -/* - * For ramster only. Helper function to support asynchronous tmem_get. - */ static int tmem_repatriate(void **ppampd, struct tmem_hashbucket *hb, struct tmem_pool *pool, struct tmem_oid *oidp, uint32_t index, bool free, char *data) @@ -670,6 +633,7 @@ static int tmem_repatriate(void **ppampd, struct tmem_hashbucket *hb, bool intransit = false; int ret = 0; + if (!is_ephemeral(pool)) new_pampd = (*tmem_pamops.repatriate_preload)( old_pampd, pool, oidp, index, &intransit); @@ -682,91 +646,60 @@ static int tmem_repatriate(void **ppampd, struct tmem_hashbucket *hb, if (!intransit) ret = (*tmem_pamops.repatriate)(old_pampd, new_pampd, pool, oidp, index, free, data); - if (ret == -EAGAIN) { - /* rare I think, but should cond_resched()??? */ - usleep_range(10, 1000); - } else if (ret == -ENOTCONN || ret == -EHOSTDOWN) { - ret = -1; - } else if (ret != 0 && ret != -ENOENT) { - ret = -1; - } - /* note hb->lock has now been unlocked */ - return ret; -} - -/* - * For ramster only. If a page in tmem matches the handle, replace the - * page so that any subsequent "get" gets the new page. Returns 0 if - * there was a page to replace, else returns -1. - */ -int tmem_replace(struct tmem_pool *pool, struct tmem_oid *oidp, - uint32_t index, void *new_pampd) -{ - struct tmem_obj *obj; - int ret = -1; - struct tmem_hashbucket *hb; - - hb = &pool->hashbucket[tmem_oid_hash(oidp)]; - spin_lock(&hb->lock); - obj = tmem_obj_find(hb, oidp); - if (obj == NULL) - goto out; - new_pampd = tmem_pampd_replace_in_obj(obj, index, new_pampd, 0); - /* if we bug here, pamops wasn't properly set up for ramster */ - BUG_ON(tmem_pamops.replace_in_obj == NULL); - ret = (*tmem_pamops.replace_in_obj)(new_pampd, obj); -out: - spin_unlock(&hb->lock); return ret; } -#endif /* - * "Get" a page, e.g. if a pampd can be found matching the passed handle, - * use a pamops callback to recreated the page from the pampd with the - * matching handle. By tmem definition, when a "get" is successful on - * an ephemeral page, the page is "flushed", and when a "get" is successful - * on a persistent page, the page is retained in tmem. Note that to preserve + * "Get" a page, e.g. if one can be found, copy the tmem page with the + * matching handle from PAM space to the kernel. By tmem definition, + * when a "get" is successful on an ephemeral page, the page is "flushed", + * and when a "get" is successful on a persistent page, the page is retained + * in tmem. Note that to preserve * coherency, "get" can never be skipped if tmem contains the data. * That is, if a get is done with a certain handle and fails, any * subsequent "get" must also fail (unless of course there is a * "put" done with the same handle). + */ int tmem_get(struct tmem_pool *pool, struct tmem_oid *oidp, uint32_t index, - char *data, size_t *sizep, bool raw, int get_and_free) + char *data, size_t *size, bool raw, int get_and_free) { struct tmem_obj *obj; - void *pampd = NULL; + void *pampd; bool ephemeral = is_ephemeral(pool); int ret = -1; struct tmem_hashbucket *hb; bool free = (get_and_free == 1) || ((get_and_free == 0) && ephemeral); - bool lock_held = false; + bool lock_held = 0; void **ppampd; - do { - hb = &pool->hashbucket[tmem_oid_hash(oidp)]; - spin_lock(&hb->lock); - lock_held = true; - obj = tmem_obj_find(hb, oidp); - if (obj == NULL) - goto out; - ppampd = __tmem_pampd_lookup_in_obj(obj, index); - if (ppampd == NULL) +again: + hb = &pool->hashbucket[tmem_oid_hash(oidp)]; + spin_lock(&hb->lock); + lock_held = 1; + obj = tmem_obj_find(hb, oidp); + if (obj == NULL) + goto out; + ppampd = __tmem_pampd_lookup_in_obj(obj, index); + if (ppampd == NULL) + goto out; + if (tmem_pamops.is_remote(*ppampd)) { + ret = tmem_repatriate(ppampd, hb, pool, oidp, + index, free, data); + lock_held = 0; /* note hb->lock has been unlocked */ + if (ret == -EAGAIN) { + /* rare I think, but should cond_resched()??? */ + usleep_range(10, 1000); + goto again; + } else if (ret != 0) { + if (ret != -ENOENT) + pr_err("UNTESTED case in tmem_get, ret=%d\n", + ret); + ret = -1; goto out; -#ifdef CONFIG_RAMSTER - if ((tmem_pamops.is_remote != NULL) && - tmem_pamops.is_remote(*ppampd)) { - ret = tmem_repatriate(ppampd, hb, pool, oidp, - index, free, data); - /* tmem_repatriate releases hb->lock */ - lock_held = false; - *sizep = PAGE_SIZE; - if (ret != -EAGAIN) - goto out; } -#endif - } while (ret == -EAGAIN); + goto out; + } if (free) pampd = tmem_pampd_delete_from_obj(obj, index); else @@ -782,10 +715,10 @@ int tmem_get(struct tmem_pool *pool, struct tmem_oid *oidp, uint32_t index, } if (free) ret = (*tmem_pamops.get_data_and_free)( - data, sizep, raw, pampd, pool, oidp, index); + data, size, raw, pampd, pool, oidp, index); else ret = (*tmem_pamops.get_data)( - data, sizep, raw, pampd, pool, oidp, index); + data, size, raw, pampd, pool, oidp, index); if (ret < 0) goto out; ret = 0; @@ -828,6 +761,30 @@ int tmem_flush_page(struct tmem_pool *pool, return ret; } +/* + * If a page in tmem matches the handle, replace the page so that any + * subsequent "get" gets the new page. Returns the new page if + * there was a page to replace, else returns NULL. + */ +int tmem_replace(struct tmem_pool *pool, struct tmem_oid *oidp, + uint32_t index, void *new_pampd) +{ + struct tmem_obj *obj; + int ret = -1; + struct tmem_hashbucket *hb; + + hb = &pool->hashbucket[tmem_oid_hash(oidp)]; + spin_lock(&hb->lock); + obj = tmem_obj_find(hb, oidp); + if (obj == NULL) + goto out; + new_pampd = tmem_pampd_replace_in_obj(obj, index, new_pampd, 0); + ret = (*tmem_pamops.replace_in_obj)(new_pampd, obj); +out: + spin_unlock(&hb->lock); + return ret; +} + /* * "Flush" all pages in tmem matching this oid. */ @@ -842,7 +799,7 @@ int tmem_flush_object(struct tmem_pool *pool, struct tmem_oid *oidp) obj = tmem_obj_find(hb, oidp); if (obj == NULL) goto out; - tmem_pampd_destroy_all_in_obj(obj, false); + tmem_pampd_destroy_all_in_obj(obj); tmem_obj_free(obj, hb); (*tmem_hostops.obj_free)(obj, pool); ret = 0; diff --git a/trunk/drivers/staging/ramster/tmem.h b/trunk/drivers/staging/ramster/tmem.h index adbe5a8f28aa..47f1918c8314 100644 --- a/trunk/drivers/staging/ramster/tmem.h +++ b/trunk/drivers/staging/ramster/tmem.h @@ -3,20 +3,23 @@ * * Transcendent memory * - * Copyright (c) 2009-2012, Dan Magenheimer, Oracle Corp. + * Copyright (c) 2009-2011, Dan Magenheimer, Oracle Corp. */ #ifndef _TMEM_H_ #define _TMEM_H_ -#include #include #include #include /* - * These are defined by the Xen<->Linux ABI so should remain consistent + * These are pre-defined by the Xen<->Linux ABI */ +#define TMEM_PUT_PAGE 4 +#define TMEM_GET_PAGE 5 +#define TMEM_FLUSH_PAGE 6 +#define TMEM_FLUSH_OBJECT 7 #define TMEM_POOL_PERSIST 1 #define TMEM_POOL_SHARED 2 #define TMEM_POOL_PRECOMPRESSED 4 @@ -28,7 +31,7 @@ * sentinels have proven very useful for debugging but can be removed * or disabled before final merge. */ -#undef SENTINELS +#define SENTINELS #ifdef SENTINELS #define DECL_SENTINEL uint32_t sentinel; #define SET_SENTINEL(_x, _y) (_x->sentinel = _y##_SENTINEL) @@ -43,7 +46,7 @@ #define ASSERT_INVERTED_SENTINEL(_x, _y) do { } while (0) #endif -#define ASSERT_SPINLOCK(_l) lockdep_assert_held(_l) +#define ASSERT_SPINLOCK(_l) WARN_ON(!spin_is_locked(_l)) /* * A pool is the highest-level data structure managed by tmem and @@ -85,6 +88,31 @@ struct tmem_oid { uint64_t oid[3]; }; +struct tmem_xhandle { + uint8_t client_id; + uint8_t xh_data_cksum; + uint16_t xh_data_size; + uint16_t pool_id; + struct tmem_oid oid; + uint32_t index; + void *extra; +}; + +static inline struct tmem_xhandle tmem_xhandle_fill(uint16_t client_id, + struct tmem_pool *pool, + struct tmem_oid *oidp, + uint32_t index) +{ + struct tmem_xhandle xh; + xh.client_id = client_id; + xh.xh_data_cksum = (uint8_t)-1; + xh.xh_data_size = (uint16_t)-1; + xh.pool_id = pool->pool_id; + xh.oid = *oidp; + xh.index = index; + return xh; +} + static inline void tmem_oid_set_invalid(struct tmem_oid *oidp) { oidp->oid[0] = oidp->oid[1] = oidp->oid[2] = -1UL; @@ -126,34 +154,6 @@ static inline unsigned tmem_oid_hash(struct tmem_oid *oidp) TMEM_HASH_BUCKET_BITS); } -#ifdef CONFIG_RAMSTER -struct tmem_xhandle { - uint8_t client_id; - uint8_t xh_data_cksum; - uint16_t xh_data_size; - uint16_t pool_id; - struct tmem_oid oid; - uint32_t index; - void *extra; -}; - -static inline struct tmem_xhandle tmem_xhandle_fill(uint16_t client_id, - struct tmem_pool *pool, - struct tmem_oid *oidp, - uint32_t index) -{ - struct tmem_xhandle xh; - xh.client_id = client_id; - xh.xh_data_cksum = (uint8_t)-1; - xh.xh_data_size = (uint16_t)-1; - xh.pool_id = pool->pool_id; - xh.oid = *oidp; - xh.index = index; - return xh; -} -#endif - - /* * A tmem_obj contains an identifier (oid), pointers to the parent * pool and the rb_tree to which it belongs, counters, and an ordered @@ -171,15 +171,11 @@ struct tmem_obj { unsigned int objnode_tree_height; unsigned long objnode_count; long pampd_count; -#ifdef CONFIG_RAMSTER - /* - * for current design of ramster, all pages belonging to + /* for current design of ramster, all pages belonging to * an object reside on the same remotenode and extra is * used to record the number of the remotenode so a - * flush-object operation can specify it - */ - void *extra; /* for private use by pampd implementation */ -#endif + * flush-object operation can specify it */ + void *extra; /* for use by pampd implementation */ DECL_SENTINEL }; @@ -197,17 +193,10 @@ struct tmem_objnode { unsigned int slots_in_use; }; -struct tmem_handle { - struct tmem_oid oid; /* 24 bytes */ - uint32_t index; - uint16_t pool_id; - uint16_t client_id; -}; - - /* pampd abstract datatype methods provided by the PAM implementation */ struct tmem_pamops { - void (*create_finish)(void *, bool); + void *(*create)(char *, size_t, bool, int, + struct tmem_pool *, struct tmem_oid *, uint32_t); int (*get_data)(char *, size_t *, bool, void *, struct tmem_pool *, struct tmem_oid *, uint32_t); int (*get_data_and_free)(char *, size_t *, bool, void *, @@ -215,16 +204,14 @@ struct tmem_pamops { uint32_t); void (*free)(void *, struct tmem_pool *, struct tmem_oid *, uint32_t, bool); -#ifdef CONFIG_RAMSTER - void (*new_obj)(struct tmem_obj *); - void (*free_obj)(struct tmem_pool *, struct tmem_obj *, bool); + void (*free_obj)(struct tmem_pool *, struct tmem_obj *); + bool (*is_remote)(void *); void *(*repatriate_preload)(void *, struct tmem_pool *, struct tmem_oid *, uint32_t, bool *); int (*repatriate)(void *, void *, struct tmem_pool *, struct tmem_oid *, uint32_t, bool, void *); - bool (*is_remote)(void *); + void (*new_obj)(struct tmem_obj *); int (*replace_in_obj)(void *, struct tmem_obj *); -#endif }; extern void tmem_register_pamops(struct tmem_pamops *m); @@ -239,15 +226,9 @@ extern void tmem_register_hostops(struct tmem_hostops *m); /* core tmem accessor functions */ extern int tmem_put(struct tmem_pool *, struct tmem_oid *, uint32_t index, - bool, void *); + char *, size_t, bool, int); extern int tmem_get(struct tmem_pool *, struct tmem_oid *, uint32_t index, char *, size_t *, bool, int); -extern int tmem_flush_page(struct tmem_pool *, struct tmem_oid *, - uint32_t index); -extern int tmem_flush_object(struct tmem_pool *, struct tmem_oid *); -extern int tmem_destroy_pool(struct tmem_pool *); -extern void tmem_new_pool(struct tmem_pool *, uint32_t); -#ifdef CONFIG_RAMSTER extern int tmem_replace(struct tmem_pool *, struct tmem_oid *, uint32_t index, void *); extern void *tmem_localify_get_pampd(struct tmem_pool *, struct tmem_oid *, @@ -255,5 +236,9 @@ extern void *tmem_localify_get_pampd(struct tmem_pool *, struct tmem_oid *, void **); extern void tmem_localify_finish(struct tmem_obj *, uint32_t index, void *, void *, bool); -#endif +extern int tmem_flush_page(struct tmem_pool *, struct tmem_oid *, + uint32_t index); +extern int tmem_flush_object(struct tmem_pool *, struct tmem_oid *); +extern int tmem_destroy_pool(struct tmem_pool *); +extern void tmem_new_pool(struct tmem_pool *, uint32_t); #endif /* _TMEM_H */ diff --git a/trunk/drivers/staging/ramster/xvmalloc.c b/trunk/drivers/staging/ramster/xvmalloc.c new file mode 100644 index 000000000000..44ceb0b823a9 --- /dev/null +++ b/trunk/drivers/staging/ramster/xvmalloc.c @@ -0,0 +1,509 @@ +/* + * xvmalloc memory allocator + * + * Copyright (C) 2008, 2009, 2010 Nitin Gupta + * + * This code is released using a dual license strategy: BSD/GPL + * You can choose the licence that better fits your requirements. + * + * Released under the terms of 3-clause BSD License + * Released under the terms of GNU General Public License Version 2.0 + */ + +#ifdef CONFIG_ZRAM_DEBUG +#define DEBUG +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "xvmalloc.h" +#include "xvmalloc_int.h" + +static void stat_inc(u64 *value) +{ + *value = *value + 1; +} + +static void stat_dec(u64 *value) +{ + *value = *value - 1; +} + +static int test_flag(struct block_header *block, enum blockflags flag) +{ + return block->prev & BIT(flag); +} + +static void set_flag(struct block_header *block, enum blockflags flag) +{ + block->prev |= BIT(flag); +} + +static void clear_flag(struct block_header *block, enum blockflags flag) +{ + block->prev &= ~BIT(flag); +} + +/* + * Given pair, provide a dereferencable pointer. + * This is called from xv_malloc/xv_free path, so it + * needs to be fast. + */ +static void *get_ptr_atomic(struct page *page, u16 offset) +{ + unsigned char *base; + + base = kmap_atomic(page); + return base + offset; +} + +static void put_ptr_atomic(void *ptr) +{ + kunmap_atomic(ptr); +} + +static u32 get_blockprev(struct block_header *block) +{ + return block->prev & PREV_MASK; +} + +static void set_blockprev(struct block_header *block, u16 new_offset) +{ + block->prev = new_offset | (block->prev & FLAGS_MASK); +} + +static struct block_header *BLOCK_NEXT(struct block_header *block) +{ + return (struct block_header *) + ((char *)block + block->size + XV_ALIGN); +} + +/* + * Get index of free list containing blocks of maximum size + * which is less than or equal to given size. + */ +static u32 get_index_for_insert(u32 size) +{ + if (unlikely(size > XV_MAX_ALLOC_SIZE)) + size = XV_MAX_ALLOC_SIZE; + size &= ~FL_DELTA_MASK; + return (size - XV_MIN_ALLOC_SIZE) >> FL_DELTA_SHIFT; +} + +/* + * Get index of free list having blocks of size greater than + * or equal to requested size. + */ +static u32 get_index(u32 size) +{ + if (unlikely(size < XV_MIN_ALLOC_SIZE)) + size = XV_MIN_ALLOC_SIZE; + size = ALIGN(size, FL_DELTA); + return (size - XV_MIN_ALLOC_SIZE) >> FL_DELTA_SHIFT; +} + +/** + * find_block - find block of at least given size + * @pool: memory pool to search from + * @size: size of block required + * @page: page containing required block + * @offset: offset within the page where block is located. + * + * Searches two level bitmap to locate block of at least + * the given size. If such a block is found, it provides + * to identify this block and returns index + * in freelist where we found this block. + * Otherwise, returns 0 and params are not touched. + */ +static u32 find_block(struct xv_pool *pool, u32 size, + struct page **page, u32 *offset) +{ + ulong flbitmap, slbitmap; + u32 flindex, slindex, slbitstart; + + /* There are no free blocks in this pool */ + if (!pool->flbitmap) + return 0; + + /* Get freelist index corresponding to this size */ + slindex = get_index(size); + slbitmap = pool->slbitmap[slindex / BITS_PER_LONG]; + slbitstart = slindex % BITS_PER_LONG; + + /* + * If freelist is not empty at this index, we found the + * block - head of this list. This is approximate best-fit match. + */ + if (test_bit(slbitstart, &slbitmap)) { + *page = pool->freelist[slindex].page; + *offset = pool->freelist[slindex].offset; + return slindex; + } + + /* + * No best-fit found. Search a bit further in bitmap for a free block. + * Second level bitmap consists of series of 32-bit chunks. Search + * further in the chunk where we expected a best-fit, starting from + * index location found above. + */ + slbitstart++; + slbitmap >>= slbitstart; + + /* Skip this search if we were already at end of this bitmap chunk */ + if ((slbitstart != BITS_PER_LONG) && slbitmap) { + slindex += __ffs(slbitmap) + 1; + *page = pool->freelist[slindex].page; + *offset = pool->freelist[slindex].offset; + return slindex; + } + + /* Now do a full two-level bitmap search to find next nearest fit */ + flindex = slindex / BITS_PER_LONG; + + flbitmap = (pool->flbitmap) >> (flindex + 1); + if (!flbitmap) + return 0; + + flindex += __ffs(flbitmap) + 1; + slbitmap = pool->slbitmap[flindex]; + slindex = (flindex * BITS_PER_LONG) + __ffs(slbitmap); + *page = pool->freelist[slindex].page; + *offset = pool->freelist[slindex].offset; + + return slindex; +} + +/* + * Insert block at in freelist of given pool. + * freelist used depends on block size. + */ +static void insert_block(struct xv_pool *pool, struct page *page, u32 offset, + struct block_header *block) +{ + u32 flindex, slindex; + struct block_header *nextblock; + + slindex = get_index_for_insert(block->size); + flindex = slindex / BITS_PER_LONG; + + block->link.prev_page = NULL; + block->link.prev_offset = 0; + block->link.next_page = pool->freelist[slindex].page; + block->link.next_offset = pool->freelist[slindex].offset; + pool->freelist[slindex].page = page; + pool->freelist[slindex].offset = offset; + + if (block->link.next_page) { + nextblock = get_ptr_atomic(block->link.next_page, + block->link.next_offset); + nextblock->link.prev_page = page; + nextblock->link.prev_offset = offset; + put_ptr_atomic(nextblock); + /* If there was a next page then the free bits are set. */ + return; + } + + __set_bit(slindex % BITS_PER_LONG, &pool->slbitmap[flindex]); + __set_bit(flindex, &pool->flbitmap); +} + +/* + * Remove block from freelist. Index 'slindex' identifies the freelist. + */ +static void remove_block(struct xv_pool *pool, struct page *page, u32 offset, + struct block_header *block, u32 slindex) +{ + u32 flindex = slindex / BITS_PER_LONG; + struct block_header *tmpblock; + + if (block->link.prev_page) { + tmpblock = get_ptr_atomic(block->link.prev_page, + block->link.prev_offset); + tmpblock->link.next_page = block->link.next_page; + tmpblock->link.next_offset = block->link.next_offset; + put_ptr_atomic(tmpblock); + } + + if (block->link.next_page) { + tmpblock = get_ptr_atomic(block->link.next_page, + block->link.next_offset); + tmpblock->link.prev_page = block->link.prev_page; + tmpblock->link.prev_offset = block->link.prev_offset; + put_ptr_atomic(tmpblock); + } + + /* Is this block is at the head of the freelist? */ + if (pool->freelist[slindex].page == page + && pool->freelist[slindex].offset == offset) { + + pool->freelist[slindex].page = block->link.next_page; + pool->freelist[slindex].offset = block->link.next_offset; + + if (pool->freelist[slindex].page) { + struct block_header *tmpblock; + tmpblock = get_ptr_atomic(pool->freelist[slindex].page, + pool->freelist[slindex].offset); + tmpblock->link.prev_page = NULL; + tmpblock->link.prev_offset = 0; + put_ptr_atomic(tmpblock); + } else { + /* This freelist bucket is empty */ + __clear_bit(slindex % BITS_PER_LONG, + &pool->slbitmap[flindex]); + if (!pool->slbitmap[flindex]) + __clear_bit(flindex, &pool->flbitmap); + } + } + + block->link.prev_page = NULL; + block->link.prev_offset = 0; + block->link.next_page = NULL; + block->link.next_offset = 0; +} + +/* + * Allocate a page and add it to freelist of given pool. + */ +static int grow_pool(struct xv_pool *pool, gfp_t flags) +{ + struct page *page; + struct block_header *block; + + page = alloc_page(flags); + if (unlikely(!page)) + return -ENOMEM; + + stat_inc(&pool->total_pages); + + spin_lock(&pool->lock); + block = get_ptr_atomic(page, 0); + + block->size = PAGE_SIZE - XV_ALIGN; + set_flag(block, BLOCK_FREE); + clear_flag(block, PREV_FREE); + set_blockprev(block, 0); + + insert_block(pool, page, 0, block); + + put_ptr_atomic(block); + spin_unlock(&pool->lock); + + return 0; +} + +/* + * Create a memory pool. Allocates freelist, bitmaps and other + * per-pool metadata. + */ +struct xv_pool *xv_create_pool(void) +{ + u32 ovhd_size; + struct xv_pool *pool; + + ovhd_size = roundup(sizeof(*pool), PAGE_SIZE); + pool = kzalloc(ovhd_size, GFP_KERNEL); + if (!pool) + return NULL; + + spin_lock_init(&pool->lock); + + return pool; +} +EXPORT_SYMBOL_GPL(xv_create_pool); + +void xv_destroy_pool(struct xv_pool *pool) +{ + kfree(pool); +} +EXPORT_SYMBOL_GPL(xv_destroy_pool); + +/** + * xv_malloc - Allocate block of given size from pool. + * @pool: pool to allocate from + * @size: size of block to allocate + * @page: page no. that holds the object + * @offset: location of object within page + * + * On success, identifies block allocated + * and 0 is returned. On failure, is set to + * 0 and -ENOMEM is returned. + * + * Allocation requests with size > XV_MAX_ALLOC_SIZE will fail. + */ +int xv_malloc(struct xv_pool *pool, u32 size, struct page **page, + u32 *offset, gfp_t flags) +{ + int error; + u32 index, tmpsize, origsize, tmpoffset; + struct block_header *block, *tmpblock; + + *page = NULL; + *offset = 0; + origsize = size; + + if (unlikely(!size || size > XV_MAX_ALLOC_SIZE)) + return -ENOMEM; + + size = ALIGN(size, XV_ALIGN); + + spin_lock(&pool->lock); + + index = find_block(pool, size, page, offset); + + if (!*page) { + spin_unlock(&pool->lock); + if (flags & GFP_NOWAIT) + return -ENOMEM; + error = grow_pool(pool, flags); + if (unlikely(error)) + return error; + + spin_lock(&pool->lock); + index = find_block(pool, size, page, offset); + } + + if (!*page) { + spin_unlock(&pool->lock); + return -ENOMEM; + } + + block = get_ptr_atomic(*page, *offset); + + remove_block(pool, *page, *offset, block, index); + + /* Split the block if required */ + tmpoffset = *offset + size + XV_ALIGN; + tmpsize = block->size - size; + tmpblock = (struct block_header *)((char *)block + size + XV_ALIGN); + if (tmpsize) { + tmpblock->size = tmpsize - XV_ALIGN; + set_flag(tmpblock, BLOCK_FREE); + clear_flag(tmpblock, PREV_FREE); + + set_blockprev(tmpblock, *offset); + if (tmpblock->size >= XV_MIN_ALLOC_SIZE) + insert_block(pool, *page, tmpoffset, tmpblock); + + if (tmpoffset + XV_ALIGN + tmpblock->size != PAGE_SIZE) { + tmpblock = BLOCK_NEXT(tmpblock); + set_blockprev(tmpblock, tmpoffset); + } + } else { + /* This block is exact fit */ + if (tmpoffset != PAGE_SIZE) + clear_flag(tmpblock, PREV_FREE); + } + + block->size = origsize; + clear_flag(block, BLOCK_FREE); + + put_ptr_atomic(block); + spin_unlock(&pool->lock); + + *offset += XV_ALIGN; + + return 0; +} +EXPORT_SYMBOL_GPL(xv_malloc); + +/* + * Free block identified with + */ +void xv_free(struct xv_pool *pool, struct page *page, u32 offset) +{ + void *page_start; + struct block_header *block, *tmpblock; + + offset -= XV_ALIGN; + + spin_lock(&pool->lock); + + page_start = get_ptr_atomic(page, 0); + block = (struct block_header *)((char *)page_start + offset); + + /* Catch double free bugs */ + BUG_ON(test_flag(block, BLOCK_FREE)); + + block->size = ALIGN(block->size, XV_ALIGN); + + tmpblock = BLOCK_NEXT(block); + if (offset + block->size + XV_ALIGN == PAGE_SIZE) + tmpblock = NULL; + + /* Merge next block if its free */ + if (tmpblock && test_flag(tmpblock, BLOCK_FREE)) { + /* + * Blocks smaller than XV_MIN_ALLOC_SIZE + * are not inserted in any free list. + */ + if (tmpblock->size >= XV_MIN_ALLOC_SIZE) { + remove_block(pool, page, + offset + block->size + XV_ALIGN, tmpblock, + get_index_for_insert(tmpblock->size)); + } + block->size += tmpblock->size + XV_ALIGN; + } + + /* Merge previous block if its free */ + if (test_flag(block, PREV_FREE)) { + tmpblock = (struct block_header *)((char *)(page_start) + + get_blockprev(block)); + offset = offset - tmpblock->size - XV_ALIGN; + + if (tmpblock->size >= XV_MIN_ALLOC_SIZE) + remove_block(pool, page, offset, tmpblock, + get_index_for_insert(tmpblock->size)); + + tmpblock->size += block->size + XV_ALIGN; + block = tmpblock; + } + + /* No used objects in this page. Free it. */ + if (block->size == PAGE_SIZE - XV_ALIGN) { + put_ptr_atomic(page_start); + spin_unlock(&pool->lock); + + __free_page(page); + stat_dec(&pool->total_pages); + return; + } + + set_flag(block, BLOCK_FREE); + if (block->size >= XV_MIN_ALLOC_SIZE) + insert_block(pool, page, offset, block); + + if (offset + block->size + XV_ALIGN != PAGE_SIZE) { + tmpblock = BLOCK_NEXT(block); + set_flag(tmpblock, PREV_FREE); + set_blockprev(tmpblock, offset); + } + + put_ptr_atomic(page_start); + spin_unlock(&pool->lock); +} +EXPORT_SYMBOL_GPL(xv_free); + +u32 xv_get_object_size(void *obj) +{ + struct block_header *blk; + + blk = (struct block_header *)((char *)(obj) - XV_ALIGN); + return blk->size; +} +EXPORT_SYMBOL_GPL(xv_get_object_size); + +/* + * Returns total memory used by allocator (userdata + metadata) + */ +u64 xv_get_total_size_bytes(struct xv_pool *pool) +{ + return pool->total_pages << PAGE_SHIFT; +} +EXPORT_SYMBOL_GPL(xv_get_total_size_bytes); diff --git a/trunk/drivers/staging/ramster/xvmalloc.h b/trunk/drivers/staging/ramster/xvmalloc.h new file mode 100644 index 000000000000..5b1a81aa5faf --- /dev/null +++ b/trunk/drivers/staging/ramster/xvmalloc.h @@ -0,0 +1,30 @@ +/* + * xvmalloc memory allocator + * + * Copyright (C) 2008, 2009, 2010 Nitin Gupta + * + * This code is released using a dual license strategy: BSD/GPL + * You can choose the licence that better fits your requirements. + * + * Released under the terms of 3-clause BSD License + * Released under the terms of GNU General Public License Version 2.0 + */ + +#ifndef _XV_MALLOC_H_ +#define _XV_MALLOC_H_ + +#include + +struct xv_pool; + +struct xv_pool *xv_create_pool(void); +void xv_destroy_pool(struct xv_pool *pool); + +int xv_malloc(struct xv_pool *pool, u32 size, struct page **page, + u32 *offset, gfp_t flags); +void xv_free(struct xv_pool *pool, struct page *page, u32 offset); + +u32 xv_get_object_size(void *obj); +u64 xv_get_total_size_bytes(struct xv_pool *pool); + +#endif diff --git a/trunk/drivers/staging/ramster/xvmalloc_int.h b/trunk/drivers/staging/ramster/xvmalloc_int.h new file mode 100644 index 000000000000..b5f1f7febcf6 --- /dev/null +++ b/trunk/drivers/staging/ramster/xvmalloc_int.h @@ -0,0 +1,95 @@ +/* + * xvmalloc memory allocator + * + * Copyright (C) 2008, 2009, 2010 Nitin Gupta + * + * This code is released using a dual license strategy: BSD/GPL + * You can choose the licence that better fits your requirements. + * + * Released under the terms of 3-clause BSD License + * Released under the terms of GNU General Public License Version 2.0 + */ + +#ifndef _XV_MALLOC_INT_H_ +#define _XV_MALLOC_INT_H_ + +#include +#include + +/* User configurable params */ + +/* Must be power of two */ +#ifdef CONFIG_64BIT +#define XV_ALIGN_SHIFT 3 +#else +#define XV_ALIGN_SHIFT 2 +#endif +#define XV_ALIGN (1 << XV_ALIGN_SHIFT) +#define XV_ALIGN_MASK (XV_ALIGN - 1) + +/* This must be greater than sizeof(link_free) */ +#define XV_MIN_ALLOC_SIZE 32 +#define XV_MAX_ALLOC_SIZE (PAGE_SIZE - XV_ALIGN) + +/* + * Free lists are separated by FL_DELTA bytes + * This value is 3 for 4k pages and 4 for 64k pages, for any + * other page size, a conservative (PAGE_SHIFT - 9) is used. + */ +#if PAGE_SHIFT == 16 +#define FL_DELTA_SHIFT 4 +#else +#define FL_DELTA_SHIFT (PAGE_SHIFT - 9) +#endif +#define FL_DELTA (1 << FL_DELTA_SHIFT) +#define FL_DELTA_MASK (FL_DELTA - 1) +#define NUM_FREE_LISTS ((XV_MAX_ALLOC_SIZE - XV_MIN_ALLOC_SIZE) \ + / FL_DELTA + 1) + +#define MAX_FLI DIV_ROUND_UP(NUM_FREE_LISTS, BITS_PER_LONG) + +/* End of user params */ + +enum blockflags { + BLOCK_FREE, + PREV_FREE, + __NR_BLOCKFLAGS, +}; + +#define FLAGS_MASK XV_ALIGN_MASK +#define PREV_MASK (~FLAGS_MASK) + +struct freelist_entry { + struct page *page; + u16 offset; + u16 pad; +}; + +struct link_free { + struct page *prev_page; + struct page *next_page; + u16 prev_offset; + u16 next_offset; +}; + +struct block_header { + union { + /* This common header must be XV_ALIGN bytes */ + u8 common[XV_ALIGN]; + struct { + u16 size; + u16 prev; + }; + }; + struct link_free link; +}; + +struct xv_pool { + ulong flbitmap; + ulong slbitmap[MAX_FLI]; + u64 total_pages; /* stats */ + struct freelist_entry freelist[NUM_FREE_LISTS]; + spinlock_t lock; +}; + +#endif diff --git a/trunk/drivers/staging/ramster/zbud.c b/trunk/drivers/staging/ramster/zbud.c deleted file mode 100644 index a7c436127aa1..000000000000 --- a/trunk/drivers/staging/ramster/zbud.c +++ /dev/null @@ -1,1060 +0,0 @@ -/* - * zbud.c - Compression buddies allocator - * - * Copyright (c) 2010-2012, Dan Magenheimer, Oracle Corp. - * - * Compression buddies ("zbud") provides for efficiently packing two - * (or, possibly in the future, more) compressed pages ("zpages") into - * a single "raw" pageframe and for tracking both zpages and pageframes - * so that whole pageframes can be easily reclaimed in LRU-like order. - * It is designed to be used in conjunction with transcendent memory - * ("tmem"); for example separate LRU lists are maintained for persistent - * vs. ephemeral pages. - * - * A zbudpage is an overlay for a struct page and thus each zbudpage - * refers to a physical pageframe of RAM. When the caller passes a - * struct page from the kernel's page allocator, zbud "transforms" it - * to a zbudpage which sets/uses a different set of fields than the - * struct-page and thus must "untransform" it back by reinitializing - * certain fields before the struct-page can be freed. The fields - * of a zbudpage include a page lock for controlling access to the - * corresponding pageframe, and there is a size field for each zpage. - * Each zbudpage also lives on two linked lists: a "budlist" which is - * used to support efficient buddying of zpages; and an "lru" which - * is used for reclaiming pageframes in approximately least-recently-used - * order. - * - * A zbudpageframe is a pageframe divided up into aligned 64-byte "chunks" - * which contain the compressed data for zero, one, or two zbuds. Contained - * with the compressed data is a tmem_handle which is a key to allow - * the same data to be found via the tmem interface so the zpage can - * be invalidated (for ephemeral pages) or repatriated to the swap cache - * (for persistent pages). The contents of a zbudpageframe must never - * be accessed without holding the page lock for the corresponding - * zbudpage and, to accomodate highmem machines, the contents may - * only be examined or changes when kmapped. Thus, when in use, a - * kmapped zbudpageframe is referred to in the zbud code as "void *zbpg". - * - * Note that the term "zbud" refers to the combination of a zpage and - * a tmem_handle that is stored as one of possibly two "buddied" zpages; - * it also generically refers to this allocator... sorry for any confusion. - * - * A zbudref is a pointer to a struct zbudpage (which can be cast to a - * struct page), with the LSB either cleared or set to indicate, respectively, - * the first or second zpage in the zbudpageframe. Since a zbudref can be - * cast to a pointer, it is used as the tmem "pampd" pointer and uniquely - * references a stored tmem page and so is the only zbud data structure - * externally visible to zbud.c/zbud.h. - * - * Since we wish to reclaim entire pageframes but zpages may be randomly - * added and deleted to any given pageframe, we approximate LRU by - * promoting a pageframe to MRU when a zpage is added to it, but - * leaving it at the current place in the list when a zpage is deleted - * from it. As a side effect, zpages that are difficult to buddy (e.g. - * very large paages) will be reclaimed faster than average, which seems - * reasonable. - * - * In the current implementation, no more than two zpages may be stored in - * any pageframe and no zpage ever crosses a pageframe boundary. While - * other zpage allocation mechanisms may allow greater density, this two - * zpage-per-pageframe limit both ensures simple reclaim of pageframes - * (including garbage collection of references to the contents of those - * pageframes from tmem data structures) AND avoids the need for compaction. - * With additional complexity, zbud could be modified to support storing - * up to three zpages per pageframe or, to handle larger average zpages, - * up to three zpages per pair of pageframes, but it is not clear if the - * additional complexity would be worth it. So consider it an exercise - * for future developers. - * - * Note also that zbud does no page allocation or freeing. This is so - * that the caller has complete control over and, for accounting, visibility - * into if/when pages are allocated and freed. - * - * Finally, note that zbud limits the size of zpages it can store; the - * caller must check the zpage size with zbud_max_buddy_size before - * storing it, else BUGs will result. User beware. - */ - -#include -#include -#include -#include -#include -#include -#include -#include "tmem.h" -#include "zcache.h" -#include "zbud.h" - -/* - * We need to ensure that a struct zbudpage is never larger than a - * struct page. This is checked with a BUG_ON in zbud_init. - * - * The unevictable field indicates that a zbud is being added to the - * zbudpage. Since this is a two-phase process (due to tmem locking), - * this field locks the zbudpage against eviction when a zbud match - * or creation is in process. Since this addition process may occur - * in parallel for two zbuds in one zbudpage, the field is a counter - * that must not exceed two. - */ -struct zbudpage { - union { - struct page page; - struct { - unsigned long space_for_flags; - struct { - unsigned zbud0_size:12; - unsigned zbud1_size:12; - unsigned unevictable:2; - }; - struct list_head budlist; - struct list_head lru; - }; - }; -}; - -struct zbudref { - union { - struct zbudpage *zbudpage; - unsigned long zbudref; - }; -}; - -#define CHUNK_SHIFT 6 -#define CHUNK_SIZE (1 << CHUNK_SHIFT) -#define CHUNK_MASK (~(CHUNK_SIZE-1)) -#define NCHUNKS (PAGE_SIZE >> CHUNK_SHIFT) -#define MAX_CHUNK (NCHUNKS-1) - -/* - * The following functions deal with the difference between struct - * page and struct zbudpage. Note the hack of using the pageflags - * from struct page; this is to avoid duplicating all the complex - * pageflag macros. - */ -static inline void zbudpage_spin_lock(struct zbudpage *zbudpage) -{ - struct page *page = (struct page *)zbudpage; - - while (unlikely(test_and_set_bit_lock(PG_locked, &page->flags))) { - do { - cpu_relax(); - } while (test_bit(PG_locked, &page->flags)); - } -} - -static inline void zbudpage_spin_unlock(struct zbudpage *zbudpage) -{ - struct page *page = (struct page *)zbudpage; - - clear_bit(PG_locked, &page->flags); -} - -static inline int zbudpage_spin_trylock(struct zbudpage *zbudpage) -{ - return trylock_page((struct page *)zbudpage); -} - -static inline int zbudpage_is_locked(struct zbudpage *zbudpage) -{ - return PageLocked((struct page *)zbudpage); -} - -static inline void *kmap_zbudpage_atomic(struct zbudpage *zbudpage) -{ - return kmap_atomic((struct page *)zbudpage); -} - -/* - * A dying zbudpage is an ephemeral page in the process of being evicted. - * Any data contained in the zbudpage is invalid and we are just waiting for - * the tmem pampds to be invalidated before freeing the page - */ -static inline int zbudpage_is_dying(struct zbudpage *zbudpage) -{ - struct page *page = (struct page *)zbudpage; - - return test_bit(PG_reclaim, &page->flags); -} - -static inline void zbudpage_set_dying(struct zbudpage *zbudpage) -{ - struct page *page = (struct page *)zbudpage; - - set_bit(PG_reclaim, &page->flags); -} - -static inline void zbudpage_clear_dying(struct zbudpage *zbudpage) -{ - struct page *page = (struct page *)zbudpage; - - clear_bit(PG_reclaim, &page->flags); -} - -/* - * A zombie zbudpage is a persistent page in the process of being evicted. - * The data contained in the zbudpage is valid and we are just waiting for - * the tmem pampds to be invalidated before freeing the page - */ -static inline int zbudpage_is_zombie(struct zbudpage *zbudpage) -{ - struct page *page = (struct page *)zbudpage; - - return test_bit(PG_dirty, &page->flags); -} - -static inline void zbudpage_set_zombie(struct zbudpage *zbudpage) -{ - struct page *page = (struct page *)zbudpage; - - set_bit(PG_dirty, &page->flags); -} - -static inline void zbudpage_clear_zombie(struct zbudpage *zbudpage) -{ - struct page *page = (struct page *)zbudpage; - - clear_bit(PG_dirty, &page->flags); -} - -static inline void kunmap_zbudpage_atomic(void *zbpg) -{ - kunmap_atomic(zbpg); -} - -/* - * zbud "translation" and helper functions - */ - -static inline struct zbudpage *zbudref_to_zbudpage(struct zbudref *zref) -{ - unsigned long zbud = (unsigned long)zref; - zbud &= ~1UL; - return (struct zbudpage *)zbud; -} - -static inline struct zbudref *zbudpage_to_zbudref(struct zbudpage *zbudpage, - unsigned budnum) -{ - unsigned long zbud = (unsigned long)zbudpage; - BUG_ON(budnum > 1); - zbud |= budnum; - return (struct zbudref *)zbud; -} - -static inline int zbudref_budnum(struct zbudref *zbudref) -{ - unsigned long zbud = (unsigned long)zbudref; - return zbud & 1UL; -} - -static inline unsigned zbud_max_size(void) -{ - return MAX_CHUNK << CHUNK_SHIFT; -} - -static inline unsigned zbud_size_to_chunks(unsigned size) -{ - BUG_ON(size == 0 || size > zbud_max_size()); - return (size + CHUNK_SIZE - 1) >> CHUNK_SHIFT; -} - -/* can only be used between kmap_zbudpage_atomic/kunmap_zbudpage_atomic! */ -static inline char *zbud_data(void *zbpg, - unsigned budnum, unsigned size) -{ - char *p; - - BUG_ON(size == 0 || size > zbud_max_size()); - p = (char *)zbpg; - if (budnum == 1) - p += PAGE_SIZE - ((size + CHUNK_SIZE - 1) & CHUNK_MASK); - return p; -} - -/* - * These are all informative and exposed through debugfs... except for - * the arrays... anyone know how to do that? To avoid confusion for - * debugfs viewers, some of these should also be atomic_long_t, but - * I don't know how to expose atomics via debugfs either... - */ -static unsigned long zbud_eph_pageframes; -static unsigned long zbud_pers_pageframes; -static unsigned long zbud_eph_zpages; -static unsigned long zbud_pers_zpages; -static u64 zbud_eph_zbytes; -static u64 zbud_pers_zbytes; -static unsigned long zbud_eph_evicted_pageframes; -static unsigned long zbud_pers_evicted_pageframes; -static unsigned long zbud_eph_cumul_zpages; -static unsigned long zbud_pers_cumul_zpages; -static u64 zbud_eph_cumul_zbytes; -static u64 zbud_pers_cumul_zbytes; -static unsigned long zbud_eph_cumul_chunk_counts[NCHUNKS]; -static unsigned long zbud_pers_cumul_chunk_counts[NCHUNKS]; -static unsigned long zbud_eph_buddied_count; -static unsigned long zbud_pers_buddied_count; -static unsigned long zbud_eph_unbuddied_count; -static unsigned long zbud_pers_unbuddied_count; -static unsigned long zbud_eph_zombie_count; -static unsigned long zbud_pers_zombie_count; -static atomic_t zbud_eph_zombie_atomic; -static atomic_t zbud_pers_zombie_atomic; - -#ifdef CONFIG_DEBUG_FS -#include -#define zdfs debugfs_create_size_t -#define zdfs64 debugfs_create_u64 -static int zbud_debugfs_init(void) -{ - struct dentry *root = debugfs_create_dir("zbud", NULL); - if (root == NULL) - return -ENXIO; - - /* - * would be nice to dump the sizes of the unbuddied - * arrays, like was done with sysfs, but it doesn't - * look like debugfs is flexible enough to do that - */ - zdfs64("eph_zbytes", S_IRUGO, root, &zbud_eph_zbytes); - zdfs64("eph_cumul_zbytes", S_IRUGO, root, &zbud_eph_cumul_zbytes); - zdfs64("pers_zbytes", S_IRUGO, root, &zbud_pers_zbytes); - zdfs64("pers_cumul_zbytes", S_IRUGO, root, &zbud_pers_cumul_zbytes); - zdfs("eph_cumul_zpages", S_IRUGO, root, &zbud_eph_cumul_zpages); - zdfs("eph_evicted_pageframes", S_IRUGO, root, - &zbud_eph_evicted_pageframes); - zdfs("eph_zpages", S_IRUGO, root, &zbud_eph_zpages); - zdfs("eph_pageframes", S_IRUGO, root, &zbud_eph_pageframes); - zdfs("eph_buddied_count", S_IRUGO, root, &zbud_eph_buddied_count); - zdfs("eph_unbuddied_count", S_IRUGO, root, &zbud_eph_unbuddied_count); - zdfs("pers_cumul_zpages", S_IRUGO, root, &zbud_pers_cumul_zpages); - zdfs("pers_evicted_pageframes", S_IRUGO, root, - &zbud_pers_evicted_pageframes); - zdfs("pers_zpages", S_IRUGO, root, &zbud_pers_zpages); - zdfs("pers_pageframes", S_IRUGO, root, &zbud_pers_pageframes); - zdfs("pers_buddied_count", S_IRUGO, root, &zbud_pers_buddied_count); - zdfs("pers_unbuddied_count", S_IRUGO, root, &zbud_pers_unbuddied_count); - zdfs("pers_zombie_count", S_IRUGO, root, &zbud_pers_zombie_count); - return 0; -} -#undef zdfs -#undef zdfs64 -#endif - -/* protects the buddied list and all unbuddied lists */ -static DEFINE_SPINLOCK(zbud_eph_lists_lock); -static DEFINE_SPINLOCK(zbud_pers_lists_lock); - -struct zbud_unbuddied { - struct list_head list; - unsigned count; -}; - -/* list N contains pages with N chunks USED and NCHUNKS-N unused */ -/* element 0 is never used but optimizing that isn't worth it */ -static struct zbud_unbuddied zbud_eph_unbuddied[NCHUNKS]; -static struct zbud_unbuddied zbud_pers_unbuddied[NCHUNKS]; -static LIST_HEAD(zbud_eph_lru_list); -static LIST_HEAD(zbud_pers_lru_list); -static LIST_HEAD(zbud_eph_buddied_list); -static LIST_HEAD(zbud_pers_buddied_list); -static LIST_HEAD(zbud_eph_zombie_list); -static LIST_HEAD(zbud_pers_zombie_list); - -/* - * Given a struct page, transform it to a zbudpage so that it can be - * used by zbud and initialize fields as necessary. - */ -static inline struct zbudpage *zbud_init_zbudpage(struct page *page, bool eph) -{ - struct zbudpage *zbudpage = (struct zbudpage *)page; - - BUG_ON(page == NULL); - INIT_LIST_HEAD(&zbudpage->budlist); - INIT_LIST_HEAD(&zbudpage->lru); - zbudpage->zbud0_size = 0; - zbudpage->zbud1_size = 0; - zbudpage->unevictable = 0; - if (eph) - zbud_eph_pageframes++; - else - zbud_pers_pageframes++; - return zbudpage; -} - -/* "Transform" a zbudpage back to a struct page suitable to free. */ -static inline struct page *zbud_unuse_zbudpage(struct zbudpage *zbudpage, - bool eph) -{ - struct page *page = (struct page *)zbudpage; - - BUG_ON(!list_empty(&zbudpage->budlist)); - BUG_ON(!list_empty(&zbudpage->lru)); - BUG_ON(zbudpage->zbud0_size != 0); - BUG_ON(zbudpage->zbud1_size != 0); - BUG_ON(!PageLocked(page)); - BUG_ON(zbudpage->unevictable != 0); - BUG_ON(zbudpage_is_dying(zbudpage)); - BUG_ON(zbudpage_is_zombie(zbudpage)); - if (eph) - zbud_eph_pageframes--; - else - zbud_pers_pageframes--; - zbudpage_spin_unlock(zbudpage); - reset_page_mapcount(page); - init_page_count(page); - page->index = 0; - return page; -} - -/* Mark a zbud as unused and do accounting */ -static inline void zbud_unuse_zbud(struct zbudpage *zbudpage, - int budnum, bool eph) -{ - unsigned size; - - BUG_ON(!zbudpage_is_locked(zbudpage)); - if (budnum == 0) { - size = zbudpage->zbud0_size; - zbudpage->zbud0_size = 0; - } else { - size = zbudpage->zbud1_size; - zbudpage->zbud1_size = 0; - } - if (eph) { - zbud_eph_zbytes -= size; - zbud_eph_zpages--; - } else { - zbud_pers_zbytes -= size; - zbud_pers_zpages--; - } -} - -/* - * Given a zbudpage/budnum/size, a tmem handle, and a kmapped pointer - * to some data, set up the zbud appropriately including data copying - * and accounting. Note that if cdata is NULL, the data copying is - * skipped. (This is useful for lazy writes such as for RAMster.) - */ -static void zbud_init_zbud(struct zbudpage *zbudpage, struct tmem_handle *th, - bool eph, void *cdata, - unsigned budnum, unsigned size) -{ - char *to; - void *zbpg; - struct tmem_handle *to_th; - unsigned nchunks = zbud_size_to_chunks(size); - - BUG_ON(!zbudpage_is_locked(zbudpage)); - zbpg = kmap_zbudpage_atomic(zbudpage); - to = zbud_data(zbpg, budnum, size); - to_th = (struct tmem_handle *)to; - to_th->index = th->index; - to_th->oid = th->oid; - to_th->pool_id = th->pool_id; - to_th->client_id = th->client_id; - to += sizeof(struct tmem_handle); - if (cdata != NULL) - memcpy(to, cdata, size - sizeof(struct tmem_handle)); - kunmap_zbudpage_atomic(zbpg); - if (budnum == 0) - zbudpage->zbud0_size = size; - else - zbudpage->zbud1_size = size; - if (eph) { - zbud_eph_cumul_chunk_counts[nchunks]++; - zbud_eph_zpages++; - zbud_eph_cumul_zpages++; - zbud_eph_zbytes += size; - zbud_eph_cumul_zbytes += size; - } else { - zbud_pers_cumul_chunk_counts[nchunks]++; - zbud_pers_zpages++; - zbud_pers_cumul_zpages++; - zbud_pers_zbytes += size; - zbud_pers_cumul_zbytes += size; - } -} - -/* - * Given a locked dying zbudpage, read out the tmem handles from the data, - * unlock the page, then use the handles to tell tmem to flush out its - * references - */ -static void zbud_evict_tmem(struct zbudpage *zbudpage) -{ - int i, j; - uint32_t pool_id[2], client_id[2]; - uint32_t index[2]; - struct tmem_oid oid[2]; - struct tmem_pool *pool; - void *zbpg; - struct tmem_handle *th; - unsigned size; - - /* read out the tmem handles from the data and set aside */ - zbpg = kmap_zbudpage_atomic(zbudpage); - for (i = 0, j = 0; i < 2; i++) { - size = (i == 0) ? zbudpage->zbud0_size : zbudpage->zbud1_size; - if (size) { - th = (struct tmem_handle *)zbud_data(zbpg, i, size); - client_id[j] = th->client_id; - pool_id[j] = th->pool_id; - oid[j] = th->oid; - index[j] = th->index; - j++; - zbud_unuse_zbud(zbudpage, i, true); - } - } - kunmap_zbudpage_atomic(zbpg); - zbudpage_spin_unlock(zbudpage); - /* zbudpage is now an unlocked dying... tell tmem to flush pointers */ - for (i = 0; i < j; i++) { - pool = zcache_get_pool_by_id(client_id[i], pool_id[i]); - if (pool != NULL) { - tmem_flush_page(pool, &oid[i], index[i]); - zcache_put_pool(pool); - } - } -} - -/* - * Externally callable zbud handling routines. - */ - -/* - * Return the maximum size compressed page that can be stored (secretly - * setting aside space for the tmem handle. - */ -unsigned int zbud_max_buddy_size(void) -{ - return zbud_max_size() - sizeof(struct tmem_handle); -} - -/* - * Given a zbud reference, free the corresponding zbud from all lists, - * mark it as unused, do accounting, and if the freeing of the zbud - * frees up an entire pageframe, return it to the caller (else NULL). - */ -struct page *zbud_free_and_delist(struct zbudref *zref, bool eph, - unsigned int *zsize, unsigned int *zpages) -{ - unsigned long budnum = zbudref_budnum(zref); - struct zbudpage *zbudpage = zbudref_to_zbudpage(zref); - struct page *page = NULL; - unsigned chunks, bud_size, other_bud_size; - spinlock_t *lists_lock = - eph ? &zbud_eph_lists_lock : &zbud_pers_lists_lock; - struct zbud_unbuddied *unbud = - eph ? zbud_eph_unbuddied : zbud_pers_unbuddied; - - - spin_lock(lists_lock); - zbudpage_spin_lock(zbudpage); - if (zbudpage_is_dying(zbudpage)) { - /* ignore dying zbudpage... see zbud_evict_pageframe_lru() */ - zbudpage_spin_unlock(zbudpage); - spin_unlock(lists_lock); - *zpages = 0; - *zsize = 0; - goto out; - } - if (budnum == 0) { - bud_size = zbudpage->zbud0_size; - other_bud_size = zbudpage->zbud1_size; - } else { - bud_size = zbudpage->zbud1_size; - other_bud_size = zbudpage->zbud0_size; - } - *zsize = bud_size - sizeof(struct tmem_handle); - *zpages = 1; - zbud_unuse_zbud(zbudpage, budnum, eph); - if (other_bud_size == 0) { /* was unbuddied: unlist and free */ - chunks = zbud_size_to_chunks(bud_size) ; - if (zbudpage_is_zombie(zbudpage)) { - if (eph) - zbud_pers_zombie_count = - atomic_dec_return(&zbud_eph_zombie_atomic); - else - zbud_pers_zombie_count = - atomic_dec_return(&zbud_pers_zombie_atomic); - zbudpage_clear_zombie(zbudpage); - } else { - BUG_ON(list_empty(&unbud[chunks].list)); - list_del_init(&zbudpage->budlist); - unbud[chunks].count--; - } - list_del_init(&zbudpage->lru); - spin_unlock(lists_lock); - if (eph) - zbud_eph_unbuddied_count--; - else - zbud_pers_unbuddied_count--; - page = zbud_unuse_zbudpage(zbudpage, eph); - } else { /* was buddied: move remaining buddy to unbuddied list */ - chunks = zbud_size_to_chunks(other_bud_size) ; - if (!zbudpage_is_zombie(zbudpage)) { - list_del_init(&zbudpage->budlist); - list_add_tail(&zbudpage->budlist, &unbud[chunks].list); - unbud[chunks].count++; - } - if (eph) { - zbud_eph_buddied_count--; - zbud_eph_unbuddied_count++; - } else { - zbud_pers_unbuddied_count++; - zbud_pers_buddied_count--; - } - /* don't mess with lru, no need to move it */ - zbudpage_spin_unlock(zbudpage); - spin_unlock(lists_lock); - } -out: - return page; -} - -/* - * Given a tmem handle, and a kmapped pointer to compressed data of - * the given size, try to find an unbuddied zbudpage in which to - * create a zbud. If found, put it there, mark the zbudpage unevictable, - * and return a zbudref to it. Else return NULL. - */ -struct zbudref *zbud_match_prep(struct tmem_handle *th, bool eph, - void *cdata, unsigned size) -{ - struct zbudpage *zbudpage = NULL, *zbudpage2; - unsigned long budnum = 0UL; - unsigned nchunks; - int i, found_good_buddy = 0; - spinlock_t *lists_lock = - eph ? &zbud_eph_lists_lock : &zbud_pers_lists_lock; - struct zbud_unbuddied *unbud = - eph ? zbud_eph_unbuddied : zbud_pers_unbuddied; - - size += sizeof(struct tmem_handle); - nchunks = zbud_size_to_chunks(size); - for (i = MAX_CHUNK - nchunks + 1; i > 0; i--) { - spin_lock(lists_lock); - if (!list_empty(&unbud[i].list)) { - list_for_each_entry_safe(zbudpage, zbudpage2, - &unbud[i].list, budlist) { - if (zbudpage_spin_trylock(zbudpage)) { - found_good_buddy = i; - goto found_unbuddied; - } - } - } - spin_unlock(lists_lock); - } - zbudpage = NULL; - goto out; - -found_unbuddied: - BUG_ON(!zbudpage_is_locked(zbudpage)); - BUG_ON(!((zbudpage->zbud0_size == 0) ^ (zbudpage->zbud1_size == 0))); - if (zbudpage->zbud0_size == 0) - budnum = 0UL; - else if (zbudpage->zbud1_size == 0) - budnum = 1UL; - list_del_init(&zbudpage->budlist); - if (eph) { - list_add_tail(&zbudpage->budlist, &zbud_eph_buddied_list); - unbud[found_good_buddy].count--; - zbud_eph_unbuddied_count--; - zbud_eph_buddied_count++; - /* "promote" raw zbudpage to most-recently-used */ - list_del_init(&zbudpage->lru); - list_add_tail(&zbudpage->lru, &zbud_eph_lru_list); - } else { - list_add_tail(&zbudpage->budlist, &zbud_pers_buddied_list); - unbud[found_good_buddy].count--; - zbud_pers_unbuddied_count--; - zbud_pers_buddied_count++; - /* "promote" raw zbudpage to most-recently-used */ - list_del_init(&zbudpage->lru); - list_add_tail(&zbudpage->lru, &zbud_pers_lru_list); - } - zbud_init_zbud(zbudpage, th, eph, cdata, budnum, size); - zbudpage->unevictable++; - BUG_ON(zbudpage->unevictable == 3); - zbudpage_spin_unlock(zbudpage); - spin_unlock(lists_lock); -out: - return zbudpage_to_zbudref(zbudpage, budnum); - -} - -/* - * Given a tmem handle, and a kmapped pointer to compressed data of - * the given size, and a newly allocated struct page, create an unevictable - * zbud in that new page and return a zbudref to it. - */ -struct zbudref *zbud_create_prep(struct tmem_handle *th, bool eph, - void *cdata, unsigned size, - struct page *newpage) -{ - struct zbudpage *zbudpage; - unsigned long budnum = 0; - unsigned nchunks; - spinlock_t *lists_lock = - eph ? &zbud_eph_lists_lock : &zbud_pers_lists_lock; - struct zbud_unbuddied *unbud = - eph ? zbud_eph_unbuddied : zbud_pers_unbuddied; - -#if 0 - /* this may be worth it later to support decompress-in-place? */ - static unsigned long counter; - budnum = counter++ & 1; /* alternate using zbud0 and zbud1 */ -#endif - - if (size > zbud_max_buddy_size()) - return NULL; - if (newpage == NULL) - return NULL; - - size += sizeof(struct tmem_handle); - nchunks = zbud_size_to_chunks(size) ; - spin_lock(lists_lock); - zbudpage = zbud_init_zbudpage(newpage, eph); - zbudpage_spin_lock(zbudpage); - list_add_tail(&zbudpage->budlist, &unbud[nchunks].list); - if (eph) { - list_add_tail(&zbudpage->lru, &zbud_eph_lru_list); - zbud_eph_unbuddied_count++; - } else { - list_add_tail(&zbudpage->lru, &zbud_pers_lru_list); - zbud_pers_unbuddied_count++; - } - unbud[nchunks].count++; - zbud_init_zbud(zbudpage, th, eph, cdata, budnum, size); - zbudpage->unevictable++; - BUG_ON(zbudpage->unevictable == 3); - zbudpage_spin_unlock(zbudpage); - spin_unlock(lists_lock); - return zbudpage_to_zbudref(zbudpage, budnum); -} - -/* - * Finish creation of a zbud by, assuming another zbud isn't being created - * in parallel, marking it evictable. - */ -void zbud_create_finish(struct zbudref *zref, bool eph) -{ - struct zbudpage *zbudpage = zbudref_to_zbudpage(zref); - spinlock_t *lists_lock = - eph ? &zbud_eph_lists_lock : &zbud_pers_lists_lock; - - spin_lock(lists_lock); - zbudpage_spin_lock(zbudpage); - BUG_ON(zbudpage_is_dying(zbudpage)); - zbudpage->unevictable--; - BUG_ON((int)zbudpage->unevictable < 0); - zbudpage_spin_unlock(zbudpage); - spin_unlock(lists_lock); -} - -/* - * Given a zbudref and a struct page, decompress the data from - * the zbud into the physical page represented by the struct page - * by upcalling to zcache_decompress - */ -int zbud_decompress(struct page *data_page, struct zbudref *zref, bool eph, - void (*decompress)(char *, unsigned int, char *)) -{ - struct zbudpage *zbudpage = zbudref_to_zbudpage(zref); - unsigned long budnum = zbudref_budnum(zref); - void *zbpg; - char *to_va, *from_va; - unsigned size; - int ret = -1; - spinlock_t *lists_lock = - eph ? &zbud_eph_lists_lock : &zbud_pers_lists_lock; - - spin_lock(lists_lock); - zbudpage_spin_lock(zbudpage); - if (zbudpage_is_dying(zbudpage)) { - /* ignore dying zbudpage... see zbud_evict_pageframe_lru() */ - goto out; - } - zbpg = kmap_zbudpage_atomic(zbudpage); - to_va = kmap_atomic(data_page); - if (budnum == 0) - size = zbudpage->zbud0_size; - else - size = zbudpage->zbud1_size; - BUG_ON(size == 0 || size > zbud_max_size()); - from_va = zbud_data(zbpg, budnum, size); - from_va += sizeof(struct tmem_handle); - size -= sizeof(struct tmem_handle); - decompress(from_va, size, to_va); - kunmap_atomic(to_va); - kunmap_zbudpage_atomic(zbpg); - ret = 0; -out: - zbudpage_spin_unlock(zbudpage); - spin_unlock(lists_lock); - return ret; -} - -/* - * Given a zbudref and a kernel pointer, copy the data from - * the zbud to the kernel pointer. - */ -int zbud_copy_from_zbud(char *to_va, struct zbudref *zref, - size_t *sizep, bool eph) -{ - struct zbudpage *zbudpage = zbudref_to_zbudpage(zref); - unsigned long budnum = zbudref_budnum(zref); - void *zbpg; - char *from_va; - unsigned size; - int ret = -1; - spinlock_t *lists_lock = - eph ? &zbud_eph_lists_lock : &zbud_pers_lists_lock; - - spin_lock(lists_lock); - zbudpage_spin_lock(zbudpage); - if (zbudpage_is_dying(zbudpage)) { - /* ignore dying zbudpage... see zbud_evict_pageframe_lru() */ - goto out; - } - zbpg = kmap_zbudpage_atomic(zbudpage); - if (budnum == 0) - size = zbudpage->zbud0_size; - else - size = zbudpage->zbud1_size; - BUG_ON(size == 0 || size > zbud_max_size()); - from_va = zbud_data(zbpg, budnum, size); - from_va += sizeof(struct tmem_handle); - size -= sizeof(struct tmem_handle); - *sizep = size; - memcpy(to_va, from_va, size); - - kunmap_zbudpage_atomic(zbpg); - ret = 0; -out: - zbudpage_spin_unlock(zbudpage); - spin_unlock(lists_lock); - return ret; -} - -/* - * Given a zbudref and a kernel pointer, copy the data from - * the kernel pointer to the zbud. - */ -int zbud_copy_to_zbud(struct zbudref *zref, char *from_va, bool eph) -{ - struct zbudpage *zbudpage = zbudref_to_zbudpage(zref); - unsigned long budnum = zbudref_budnum(zref); - void *zbpg; - char *to_va; - unsigned size; - int ret = -1; - spinlock_t *lists_lock = - eph ? &zbud_eph_lists_lock : &zbud_pers_lists_lock; - - spin_lock(lists_lock); - zbudpage_spin_lock(zbudpage); - if (zbudpage_is_dying(zbudpage)) { - /* ignore dying zbudpage... see zbud_evict_pageframe_lru() */ - goto out; - } - zbpg = kmap_zbudpage_atomic(zbudpage); - if (budnum == 0) - size = zbudpage->zbud0_size; - else - size = zbudpage->zbud1_size; - BUG_ON(size == 0 || size > zbud_max_size()); - to_va = zbud_data(zbpg, budnum, size); - to_va += sizeof(struct tmem_handle); - size -= sizeof(struct tmem_handle); - memcpy(to_va, from_va, size); - - kunmap_zbudpage_atomic(zbpg); - ret = 0; -out: - zbudpage_spin_unlock(zbudpage); - spin_unlock(lists_lock); - return ret; -} - -/* - * Choose an ephemeral LRU zbudpage that is evictable (not locked), ensure - * there are no references to it remaining, and return the now unused - * (and re-init'ed) struct page and the total amount of compressed - * data that was evicted. - */ -struct page *zbud_evict_pageframe_lru(unsigned int *zsize, unsigned int *zpages) -{ - struct zbudpage *zbudpage = NULL, *zbudpage2; - struct zbud_unbuddied *unbud = zbud_eph_unbuddied; - struct page *page = NULL; - bool irqs_disabled = irqs_disabled(); - - /* - * Since this can be called indirectly from cleancache_put, which - * has interrupts disabled, as well as frontswap_put, which does not, - * we need to be able to handle both cases, even though it is ugly. - */ - if (irqs_disabled) - spin_lock(&zbud_eph_lists_lock); - else - spin_lock_bh(&zbud_eph_lists_lock); - *zsize = 0; - if (list_empty(&zbud_eph_lru_list)) - goto unlock_out; - list_for_each_entry_safe(zbudpage, zbudpage2, &zbud_eph_lru_list, lru) { - /* skip a locked zbudpage */ - if (unlikely(!zbudpage_spin_trylock(zbudpage))) - continue; - /* skip an unevictable zbudpage */ - if (unlikely(zbudpage->unevictable != 0)) { - zbudpage_spin_unlock(zbudpage); - continue; - } - /* got a locked evictable page */ - goto evict_page; - - } -unlock_out: - /* no unlocked evictable pages, give up */ - if (irqs_disabled) - spin_unlock(&zbud_eph_lists_lock); - else - spin_unlock_bh(&zbud_eph_lists_lock); - goto out; - -evict_page: - list_del_init(&zbudpage->budlist); - list_del_init(&zbudpage->lru); - zbudpage_set_dying(zbudpage); - /* - * the zbudpage is now "dying" and attempts to read, write, - * or delete data from it will be ignored - */ - if (zbudpage->zbud0_size != 0 && zbudpage->zbud1_size != 0) { - *zsize = zbudpage->zbud0_size + zbudpage->zbud1_size - - (2 * sizeof(struct tmem_handle)); - *zpages = 2; - } else if (zbudpage->zbud0_size != 0) { - unbud[zbud_size_to_chunks(zbudpage->zbud0_size)].count--; - *zsize = zbudpage->zbud0_size - sizeof(struct tmem_handle); - *zpages = 1; - } else if (zbudpage->zbud1_size != 0) { - unbud[zbud_size_to_chunks(zbudpage->zbud1_size)].count--; - *zsize = zbudpage->zbud1_size - sizeof(struct tmem_handle); - *zpages = 1; - } else { - BUG(); - } - spin_unlock(&zbud_eph_lists_lock); - zbud_eph_evicted_pageframes++; - if (*zpages == 1) - zbud_eph_unbuddied_count--; - else - zbud_eph_buddied_count--; - zbud_evict_tmem(zbudpage); - zbudpage_spin_lock(zbudpage); - zbudpage_clear_dying(zbudpage); - page = zbud_unuse_zbudpage(zbudpage, true); - if (!irqs_disabled) - local_bh_enable(); -out: - return page; -} - -/* - * Choose a persistent LRU zbudpage that is evictable (not locked), zombify it, - * read the tmem_handle(s) out of it into the passed array, and return the - * number of zbuds. Caller must perform necessary tmem functions and, - * indirectly, zbud functions to fetch any valid data and cause the - * now-zombified zbudpage to eventually be freed. We track the zombified - * zbudpage count so it is possible to observe if there is a leak. - FIXME: describe (ramster) case where data pointers are passed in for memcpy - */ -unsigned int zbud_make_zombie_lru(struct tmem_handle *th, unsigned char **data, - unsigned int *zsize, bool eph) -{ - struct zbudpage *zbudpage = NULL, *zbudpag2; - struct tmem_handle *thfrom; - char *from_va; - void *zbpg; - unsigned size; - int ret = 0, i; - spinlock_t *lists_lock = - eph ? &zbud_eph_lists_lock : &zbud_pers_lists_lock; - struct list_head *lru_list = - eph ? &zbud_eph_lru_list : &zbud_pers_lru_list; - - spin_lock_bh(lists_lock); - if (list_empty(lru_list)) - goto out; - list_for_each_entry_safe(zbudpage, zbudpag2, lru_list, lru) { - /* skip a locked zbudpage */ - if (unlikely(!zbudpage_spin_trylock(zbudpage))) - continue; - /* skip an unevictable zbudpage */ - if (unlikely(zbudpage->unevictable != 0)) { - zbudpage_spin_unlock(zbudpage); - continue; - } - /* got a locked evictable page */ - goto zombify_page; - } - /* no unlocked evictable pages, give up */ - goto out; - -zombify_page: - /* got an unlocked evictable page, zombify it */ - list_del_init(&zbudpage->budlist); - zbudpage_set_zombie(zbudpage); - /* FIXME what accounting do I need to do here? */ - list_del_init(&zbudpage->lru); - if (eph) { - list_add_tail(&zbudpage->lru, &zbud_eph_zombie_list); - zbud_eph_zombie_count = - atomic_inc_return(&zbud_eph_zombie_atomic); - } else { - list_add_tail(&zbudpage->lru, &zbud_pers_zombie_list); - zbud_pers_zombie_count = - atomic_inc_return(&zbud_pers_zombie_atomic); - } - /* FIXME what accounting do I need to do here? */ - zbpg = kmap_zbudpage_atomic(zbudpage); - for (i = 0; i < 2; i++) { - size = (i == 0) ? zbudpage->zbud0_size : zbudpage->zbud1_size; - if (size) { - from_va = zbud_data(zbpg, i, size); - thfrom = (struct tmem_handle *)from_va; - from_va += sizeof(struct tmem_handle); - size -= sizeof(struct tmem_handle); - if (th != NULL) - th[ret] = *thfrom; - if (data != NULL) - memcpy(data[ret], from_va, size); - if (zsize != NULL) - *zsize++ = size; - ret++; - } - } - kunmap_zbudpage_atomic(zbpg); - zbudpage_spin_unlock(zbudpage); -out: - spin_unlock_bh(lists_lock); - return ret; -} - -void __init zbud_init(void) -{ - int i; - -#ifdef CONFIG_DEBUG_FS - zbud_debugfs_init(); -#endif - BUG_ON((sizeof(struct tmem_handle) * 2 > CHUNK_SIZE)); - BUG_ON(sizeof(struct zbudpage) > sizeof(struct page)); - for (i = 0; i < NCHUNKS; i++) { - INIT_LIST_HEAD(&zbud_eph_unbuddied[i].list); - INIT_LIST_HEAD(&zbud_pers_unbuddied[i].list); - } -} diff --git a/trunk/drivers/staging/ramster/zbud.h b/trunk/drivers/staging/ramster/zbud.h deleted file mode 100644 index 891e8a7d5aa5..000000000000 --- a/trunk/drivers/staging/ramster/zbud.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * zbud.h - * - * Copyright (c) 2010-2012, Dan Magenheimer, Oracle Corp. - * - */ - -#ifndef _ZBUD_H_ -#define _ZBUD_H_ - -#include "tmem.h" - -struct zbudref; - -extern unsigned int zbud_max_buddy_size(void); -extern struct zbudref *zbud_match_prep(struct tmem_handle *th, bool eph, - void *cdata, unsigned size); -extern struct zbudref *zbud_create_prep(struct tmem_handle *th, bool eph, - void *cdata, unsigned size, - struct page *newpage); -extern void zbud_create_finish(struct zbudref *, bool); -extern int zbud_decompress(struct page *, struct zbudref *, bool, - void (*func)(char *, unsigned int, char *)); -extern int zbud_copy_from_zbud(char *, struct zbudref *, size_t *, bool); -extern int zbud_copy_to_zbud(struct zbudref *, char *, bool); -extern struct page *zbud_free_and_delist(struct zbudref *, bool eph, - unsigned int *, unsigned int *); -extern struct page *zbud_evict_pageframe_lru(unsigned int *, unsigned int *); -extern unsigned int zbud_make_zombie_lru(struct tmem_handle *, unsigned char **, - unsigned int *, bool); -extern void zbud_init(void); - -#endif /* _ZBUD_H_ */ diff --git a/trunk/drivers/staging/ramster/zcache-main.c b/trunk/drivers/staging/ramster/zcache-main.c index a09dd5cc1cea..d46764b5aaba 100644 --- a/trunk/drivers/staging/ramster/zcache-main.c +++ b/trunk/drivers/staging/ramster/zcache-main.c @@ -5,321 +5,1391 @@ * Copyright (c) 2010,2011, Nitin Gupta * * Zcache provides an in-kernel "host implementation" for transcendent memory - * ("tmem") and, thus indirectly, for cleancache and frontswap. Zcache uses - * lzo1x compression to improve density and an embedded allocator called - * "zbud" which "buddies" two compressed pages semi-optimally in each physical - * pageframe. Zbud is integrally tied into tmem to allow pageframes to - * be "reclaimed" efficiently. + * and, thus indirectly, for cleancache and frontswap. Zcache includes two + * page-accessible memory [1] interfaces, both utilizing lzo1x compression: + * 1) "compression buddies" ("zbud") is used for ephemeral pages + * 2) xvmalloc is used for persistent pages. + * Xvmalloc (based on the TLSF allocator) has very low fragmentation + * so maximizes space efficiency, while zbud allows pairs (and potentially, + * in the future, more than a pair of) compressed pages to be closely linked + * so that reclaiming can be done via the kernel's physical-page-oriented + * "shrinker" interface. + * + * [1] For a definition of page-accessible memory (aka PAM), see: + * http://marc.info/?l=linux-mm&m=127811271605009 + * RAMSTER TODO: + * - handle remotifying of buddied pages (see zbud_remotify_zbpg) + * - kernel boot params: nocleancache/nofrontswap don't always work?!? */ #include #include #include #include +#include #include #include #include #include #include -#include - -#include -#include #include "tmem.h" #include "zcache.h" -#include "zbud.h" #include "ramster.h" -#ifdef CONFIG_RAMSTER -static int ramster_enabled; +#include "cluster/tcp.h" + +#include "xvmalloc.h" /* temporary until change to zsmalloc */ + +#define RAMSTER_TESTING + +#if (!defined(CONFIG_CLEANCACHE) && !defined(CONFIG_FRONTSWAP)) +#error "ramster is useless without CONFIG_CLEANCACHE or CONFIG_FRONTSWAP" +#endif +#ifdef CONFIG_CLEANCACHE +#include +#endif +#ifdef CONFIG_FRONTSWAP +#include +#endif + +enum ramster_remotify_op { + RAMSTER_REMOTIFY_EPH_PUT, + RAMSTER_REMOTIFY_PERS_PUT, + RAMSTER_REMOTIFY_FLUSH_PAGE, + RAMSTER_REMOTIFY_FLUSH_OBJ, + RAMSTER_INTRANSIT_PERS +}; + +struct ramster_remotify_hdr { + enum ramster_remotify_op op; + struct list_head list; +}; + +#define ZBH_SENTINEL 0x43214321 +#define ZBPG_SENTINEL 0xdeadbeef + +#define ZBUD_MAX_BUDS 2 + +struct zbud_hdr { + struct ramster_remotify_hdr rem_op; + uint16_t client_id; + uint16_t pool_id; + struct tmem_oid oid; + uint32_t index; + uint16_t size; /* compressed size in bytes, zero means unused */ + DECL_SENTINEL +}; + +#define ZVH_SENTINEL 0x43214321 +static const int zv_max_page_size = (PAGE_SIZE / 8) * 7; + +struct zv_hdr { + struct ramster_remotify_hdr rem_op; + uint16_t client_id; + uint16_t pool_id; + struct tmem_oid oid; + uint32_t index; + DECL_SENTINEL +}; + +struct flushlist_node { + struct ramster_remotify_hdr rem_op; + struct tmem_xhandle xh; +}; + +union { + struct ramster_remotify_hdr rem_op; + struct zv_hdr zv; + struct zbud_hdr zbud; + struct flushlist_node flist; +} remotify_list_node; + +static LIST_HEAD(zcache_rem_op_list); +static DEFINE_SPINLOCK(zcache_rem_op_list_lock); + +#if 0 +/* this is more aggressive but may cause other problems? */ +#define ZCACHE_GFP_MASK (GFP_ATOMIC | __GFP_NORETRY | __GFP_NOWARN) #else -#define ramster_enabled 0 +#define ZCACHE_GFP_MASK \ + (__GFP_FS | __GFP_NORETRY | __GFP_NOWARN | __GFP_NOMEMALLOC) #endif -#ifndef __PG_WAS_ACTIVE -static inline bool PageWasActive(struct page *page) +#define MAX_POOLS_PER_CLIENT 16 + +#define MAX_CLIENTS 16 +#define LOCAL_CLIENT ((uint16_t)-1) + +MODULE_LICENSE("GPL"); + +struct zcache_client { + struct tmem_pool *tmem_pools[MAX_POOLS_PER_CLIENT]; + struct xv_pool *xvpool; + bool allocated; + atomic_t refcount; +}; + +static struct zcache_client zcache_host; +static struct zcache_client zcache_clients[MAX_CLIENTS]; + +static inline uint16_t get_client_id_from_client(struct zcache_client *cli) { - return true; + BUG_ON(cli == NULL); + if (cli == &zcache_host) + return LOCAL_CLIENT; + return cli - &zcache_clients[0]; } -static inline void SetPageWasActive(struct page *page) +static inline bool is_local_client(struct zcache_client *cli) { + return cli == &zcache_host; } -#endif -#ifdef FRONTSWAP_HAS_EXCLUSIVE_GETS -static bool frontswap_has_exclusive_gets __read_mostly = true; -#else -static bool frontswap_has_exclusive_gets __read_mostly; -static inline void frontswap_tmem_exclusive_gets(bool b) +/********** + * Compression buddies ("zbud") provides for packing two (or, possibly + * in the future, more) compressed ephemeral pages into a single "raw" + * (physical) page and tracking them with data structures so that + * the raw pages can be easily reclaimed. + * + * A zbud page ("zbpg") is an aligned page containing a list_head, + * a lock, and two "zbud headers". The remainder of the physical + * page is divided up into aligned 64-byte "chunks" which contain + * the compressed data for zero, one, or two zbuds. Each zbpg + * resides on: (1) an "unused list" if it has no zbuds; (2) a + * "buddied" list if it is fully populated with two zbuds; or + * (3) one of PAGE_SIZE/64 "unbuddied" lists indexed by how many chunks + * the one unbuddied zbud uses. The data inside a zbpg cannot be + * read or written unless the zbpg's lock is held. + */ + +struct zbud_page { + struct list_head bud_list; + spinlock_t lock; + struct zbud_hdr buddy[ZBUD_MAX_BUDS]; + DECL_SENTINEL + /* followed by NUM_CHUNK aligned CHUNK_SIZE-byte chunks */ +}; + +#define CHUNK_SHIFT 6 +#define CHUNK_SIZE (1 << CHUNK_SHIFT) +#define CHUNK_MASK (~(CHUNK_SIZE-1)) +#define NCHUNKS (((PAGE_SIZE - sizeof(struct zbud_page)) & \ + CHUNK_MASK) >> CHUNK_SHIFT) +#define MAX_CHUNK (NCHUNKS-1) + +static struct { + struct list_head list; + unsigned count; +} zbud_unbuddied[NCHUNKS]; +/* list N contains pages with N chunks USED and NCHUNKS-N unused */ +/* element 0 is never used but optimizing that isn't worth it */ +static unsigned long zbud_cumul_chunk_counts[NCHUNKS]; + +struct list_head zbud_buddied_list; +static unsigned long zcache_zbud_buddied_count; + +/* protects the buddied list and all unbuddied lists */ +static DEFINE_SPINLOCK(zbud_budlists_spinlock); + +static atomic_t zcache_zbud_curr_raw_pages; +static atomic_t zcache_zbud_curr_zpages; +static unsigned long zcache_zbud_curr_zbytes; +static unsigned long zcache_zbud_cumul_zpages; +static unsigned long zcache_zbud_cumul_zbytes; +static unsigned long zcache_compress_poor; +static unsigned long zcache_policy_percent_exceeded; +static unsigned long zcache_mean_compress_poor; + +/* + * RAMster counters + * - Remote pages are pages with a local pampd but the data is remote + * - Foreign pages are pages stored locally but belonging to another node + */ +static atomic_t ramster_remote_pers_pages = ATOMIC_INIT(0); +static unsigned long ramster_pers_remotify_enable; +static unsigned long ramster_eph_remotify_enable; +static unsigned long ramster_eph_pages_remoted; +static unsigned long ramster_eph_pages_remote_failed; +static unsigned long ramster_pers_pages_remoted; +static unsigned long ramster_pers_pages_remote_failed; +static unsigned long ramster_pers_pages_remote_nomem; +static unsigned long ramster_remote_objects_flushed; +static unsigned long ramster_remote_object_flushes_failed; +static unsigned long ramster_remote_pages_flushed; +static unsigned long ramster_remote_page_flushes_failed; +static unsigned long ramster_remote_eph_pages_succ_get; +static unsigned long ramster_remote_pers_pages_succ_get; +static unsigned long ramster_remote_eph_pages_unsucc_get; +static unsigned long ramster_remote_pers_pages_unsucc_get; +static atomic_t ramster_curr_flnode_count = ATOMIC_INIT(0); +static unsigned long ramster_curr_flnode_count_max; +static atomic_t ramster_foreign_eph_pampd_count = ATOMIC_INIT(0); +static unsigned long ramster_foreign_eph_pampd_count_max; +static atomic_t ramster_foreign_pers_pampd_count = ATOMIC_INIT(0); +static unsigned long ramster_foreign_pers_pampd_count_max; + +/* forward references */ +static void *zcache_get_free_page(void); +static void zcache_free_page(void *p); + +/* + * zbud helper functions + */ + +static inline unsigned zbud_max_buddy_size(void) { + return MAX_CHUNK << CHUNK_SHIFT; } -#endif -static int zcache_enabled __read_mostly; -static int disable_cleancache __read_mostly; -static int disable_frontswap __read_mostly; -static int disable_frontswap_ignore_nonactive __read_mostly; -static int disable_cleancache_ignore_nonactive __read_mostly; -static char *namestr __read_mostly = "zcache"; +static inline unsigned zbud_size_to_chunks(unsigned size) +{ + BUG_ON(size == 0 || size > zbud_max_buddy_size()); + return (size + CHUNK_SIZE - 1) >> CHUNK_SHIFT; +} -#define ZCACHE_GFP_MASK \ - (__GFP_FS | __GFP_NORETRY | __GFP_NOWARN | __GFP_NOMEMALLOC) +static inline int zbud_budnum(struct zbud_hdr *zh) +{ + unsigned offset = (unsigned long)zh & (PAGE_SIZE - 1); + struct zbud_page *zbpg = NULL; + unsigned budnum = -1U; + int i; -MODULE_LICENSE("GPL"); + for (i = 0; i < ZBUD_MAX_BUDS; i++) + if (offset == offsetof(typeof(*zbpg), buddy[i])) { + budnum = i; + break; + } + BUG_ON(budnum == -1U); + return budnum; +} + +static char *zbud_data(struct zbud_hdr *zh, unsigned size) +{ + struct zbud_page *zbpg; + char *p; + unsigned budnum; + + ASSERT_SENTINEL(zh, ZBH); + budnum = zbud_budnum(zh); + BUG_ON(size == 0 || size > zbud_max_buddy_size()); + zbpg = container_of(zh, struct zbud_page, buddy[budnum]); + ASSERT_SPINLOCK(&zbpg->lock); + p = (char *)zbpg; + if (budnum == 0) + p += ((sizeof(struct zbud_page) + CHUNK_SIZE - 1) & + CHUNK_MASK); + else if (budnum == 1) + p += PAGE_SIZE - ((size + CHUNK_SIZE - 1) & CHUNK_MASK); + return p; +} + +static void zbud_copy_from_pampd(char *data, size_t *size, struct zbud_hdr *zh) +{ + struct zbud_page *zbpg; + char *p; + unsigned budnum; + + ASSERT_SENTINEL(zh, ZBH); + budnum = zbud_budnum(zh); + zbpg = container_of(zh, struct zbud_page, buddy[budnum]); + spin_lock(&zbpg->lock); + BUG_ON(zh->size > *size); + p = (char *)zbpg; + if (budnum == 0) + p += ((sizeof(struct zbud_page) + CHUNK_SIZE - 1) & + CHUNK_MASK); + else if (budnum == 1) + p += PAGE_SIZE - ((zh->size + CHUNK_SIZE - 1) & CHUNK_MASK); + /* client should be filled in by caller */ + memcpy(data, p, zh->size); + *size = zh->size; + spin_unlock(&zbpg->lock); +} -/* crypto API for zcache */ -#define ZCACHE_COMP_NAME_SZ CRYPTO_MAX_ALG_NAME -static char zcache_comp_name[ZCACHE_COMP_NAME_SZ] __read_mostly; -static struct crypto_comp * __percpu *zcache_comp_pcpu_tfms __read_mostly; +/* + * zbud raw page management + */ -enum comp_op { - ZCACHE_COMPOP_COMPRESS, - ZCACHE_COMPOP_DECOMPRESS -}; +static struct zbud_page *zbud_alloc_raw_page(void) +{ + struct zbud_page *zbpg = NULL; + struct zbud_hdr *zh0, *zh1; + zbpg = zcache_get_free_page(); + if (likely(zbpg != NULL)) { + INIT_LIST_HEAD(&zbpg->bud_list); + zh0 = &zbpg->buddy[0]; zh1 = &zbpg->buddy[1]; + spin_lock_init(&zbpg->lock); + atomic_inc(&zcache_zbud_curr_raw_pages); + INIT_LIST_HEAD(&zbpg->bud_list); + SET_SENTINEL(zbpg, ZBPG); + zh0->size = 0; zh1->size = 0; + tmem_oid_set_invalid(&zh0->oid); + tmem_oid_set_invalid(&zh1->oid); + } + return zbpg; +} -static inline int zcache_comp_op(enum comp_op op, - const u8 *src, unsigned int slen, - u8 *dst, unsigned int *dlen) +static void zbud_free_raw_page(struct zbud_page *zbpg) { - struct crypto_comp *tfm; - int ret = -1; + struct zbud_hdr *zh0 = &zbpg->buddy[0], *zh1 = &zbpg->buddy[1]; - BUG_ON(!zcache_comp_pcpu_tfms); - tfm = *per_cpu_ptr(zcache_comp_pcpu_tfms, get_cpu()); - BUG_ON(!tfm); - switch (op) { - case ZCACHE_COMPOP_COMPRESS: - ret = crypto_comp_compress(tfm, src, slen, dst, dlen); - break; - case ZCACHE_COMPOP_DECOMPRESS: - ret = crypto_comp_decompress(tfm, src, slen, dst, dlen); - break; - default: + ASSERT_SENTINEL(zbpg, ZBPG); + BUG_ON(!list_empty(&zbpg->bud_list)); + ASSERT_SPINLOCK(&zbpg->lock); + BUG_ON(zh0->size != 0 || tmem_oid_valid(&zh0->oid)); + BUG_ON(zh1->size != 0 || tmem_oid_valid(&zh1->oid)); + INVERT_SENTINEL(zbpg, ZBPG); + spin_unlock(&zbpg->lock); + atomic_dec(&zcache_zbud_curr_raw_pages); + zcache_free_page(zbpg); +} + +/* + * core zbud handling routines + */ + +static unsigned zbud_free(struct zbud_hdr *zh) +{ + unsigned size; + + ASSERT_SENTINEL(zh, ZBH); + BUG_ON(!tmem_oid_valid(&zh->oid)); + size = zh->size; + BUG_ON(zh->size == 0 || zh->size > zbud_max_buddy_size()); + zh->size = 0; + tmem_oid_set_invalid(&zh->oid); + INVERT_SENTINEL(zh, ZBH); + zcache_zbud_curr_zbytes -= size; + atomic_dec(&zcache_zbud_curr_zpages); + return size; +} + +static void zbud_free_and_delist(struct zbud_hdr *zh) +{ + unsigned chunks; + struct zbud_hdr *zh_other; + unsigned budnum = zbud_budnum(zh), size; + struct zbud_page *zbpg = + container_of(zh, struct zbud_page, buddy[budnum]); + + /* FIXME, should be BUG_ON, pool destruction path doesn't disable + * interrupts tmem_destroy_pool()->tmem_pampd_destroy_all_in_obj()-> + * tmem_objnode_node_destroy()-> zcache_pampd_free() */ + WARN_ON(!irqs_disabled()); + spin_lock(&zbpg->lock); + if (list_empty(&zbpg->bud_list)) { + /* ignore zombie page... see zbud_evict_pages() */ + spin_unlock(&zbpg->lock); + return; + } + size = zbud_free(zh); + ASSERT_SPINLOCK(&zbpg->lock); + zh_other = &zbpg->buddy[(budnum == 0) ? 1 : 0]; + if (zh_other->size == 0) { /* was unbuddied: unlist and free */ + chunks = zbud_size_to_chunks(size) ; + spin_lock(&zbud_budlists_spinlock); + BUG_ON(list_empty(&zbud_unbuddied[chunks].list)); + list_del_init(&zbpg->bud_list); + zbud_unbuddied[chunks].count--; + spin_unlock(&zbud_budlists_spinlock); + zbud_free_raw_page(zbpg); + } else { /* was buddied: move remaining buddy to unbuddied list */ + chunks = zbud_size_to_chunks(zh_other->size) ; + spin_lock(&zbud_budlists_spinlock); + list_del_init(&zbpg->bud_list); + zcache_zbud_buddied_count--; + list_add_tail(&zbpg->bud_list, &zbud_unbuddied[chunks].list); + zbud_unbuddied[chunks].count++; + spin_unlock(&zbud_budlists_spinlock); + spin_unlock(&zbpg->lock); + } +} + +static struct zbud_hdr *zbud_create(uint16_t client_id, uint16_t pool_id, + struct tmem_oid *oid, + uint32_t index, struct page *page, + void *cdata, unsigned size) +{ + struct zbud_hdr *zh0, *zh1, *zh = NULL; + struct zbud_page *zbpg = NULL, *ztmp; + unsigned nchunks; + char *to; + int i, found_good_buddy = 0; + + nchunks = zbud_size_to_chunks(size) ; + for (i = MAX_CHUNK - nchunks + 1; i > 0; i--) { + spin_lock(&zbud_budlists_spinlock); + if (!list_empty(&zbud_unbuddied[i].list)) { + list_for_each_entry_safe(zbpg, ztmp, + &zbud_unbuddied[i].list, bud_list) { + if (spin_trylock(&zbpg->lock)) { + found_good_buddy = i; + goto found_unbuddied; + } + } + } + spin_unlock(&zbud_budlists_spinlock); + } + /* didn't find a good buddy, try allocating a new page */ + zbpg = zbud_alloc_raw_page(); + if (unlikely(zbpg == NULL)) + goto out; + /* ok, have a page, now compress the data before taking locks */ + spin_lock(&zbud_budlists_spinlock); + spin_lock(&zbpg->lock); + list_add_tail(&zbpg->bud_list, &zbud_unbuddied[nchunks].list); + zbud_unbuddied[nchunks].count++; + zh = &zbpg->buddy[0]; + goto init_zh; + +found_unbuddied: + ASSERT_SPINLOCK(&zbpg->lock); + zh0 = &zbpg->buddy[0]; zh1 = &zbpg->buddy[1]; + BUG_ON(!((zh0->size == 0) ^ (zh1->size == 0))); + if (zh0->size != 0) { /* buddy0 in use, buddy1 is vacant */ + ASSERT_SENTINEL(zh0, ZBH); + zh = zh1; + } else if (zh1->size != 0) { /* buddy1 in use, buddy0 is vacant */ + ASSERT_SENTINEL(zh1, ZBH); + zh = zh0; + } else + BUG(); + list_del_init(&zbpg->bud_list); + zbud_unbuddied[found_good_buddy].count--; + list_add_tail(&zbpg->bud_list, &zbud_buddied_list); + zcache_zbud_buddied_count++; + +init_zh: + SET_SENTINEL(zh, ZBH); + zh->size = size; + zh->index = index; + zh->oid = *oid; + zh->pool_id = pool_id; + zh->client_id = client_id; + to = zbud_data(zh, size); + memcpy(to, cdata, size); + spin_unlock(&zbpg->lock); + spin_unlock(&zbud_budlists_spinlock); + zbud_cumul_chunk_counts[nchunks]++; + atomic_inc(&zcache_zbud_curr_zpages); + zcache_zbud_cumul_zpages++; + zcache_zbud_curr_zbytes += size; + zcache_zbud_cumul_zbytes += size; +out: + return zh; +} + +static int zbud_decompress(struct page *page, struct zbud_hdr *zh) +{ + struct zbud_page *zbpg; + unsigned budnum = zbud_budnum(zh); + size_t out_len = PAGE_SIZE; + char *to_va, *from_va; + unsigned size; + int ret = 0; + + zbpg = container_of(zh, struct zbud_page, buddy[budnum]); + spin_lock(&zbpg->lock); + if (list_empty(&zbpg->bud_list)) { + /* ignore zombie page... see zbud_evict_pages() */ ret = -EINVAL; + goto out; + } + ASSERT_SENTINEL(zh, ZBH); + BUG_ON(zh->size == 0 || zh->size > zbud_max_buddy_size()); + to_va = kmap_atomic(page); + size = zh->size; + from_va = zbud_data(zh, size); + ret = lzo1x_decompress_safe(from_va, size, to_va, &out_len); + BUG_ON(ret != LZO_E_OK); + BUG_ON(out_len != PAGE_SIZE); + kunmap_atomic(to_va); +out: + spin_unlock(&zbpg->lock); + return ret; +} + +/* + * The following routines handle shrinking of ephemeral pages by evicting + * pages "least valuable" first. + */ + +static unsigned long zcache_evicted_raw_pages; +static unsigned long zcache_evicted_buddied_pages; +static unsigned long zcache_evicted_unbuddied_pages; + +static struct tmem_pool *zcache_get_pool_by_id(uint16_t cli_id, + uint16_t poolid); +static void zcache_put_pool(struct tmem_pool *pool); + +/* + * Flush and free all zbuds in a zbpg, then free the pageframe + */ +static void zbud_evict_zbpg(struct zbud_page *zbpg) +{ + struct zbud_hdr *zh; + int i, j; + uint32_t pool_id[ZBUD_MAX_BUDS], client_id[ZBUD_MAX_BUDS]; + uint32_t index[ZBUD_MAX_BUDS]; + struct tmem_oid oid[ZBUD_MAX_BUDS]; + struct tmem_pool *pool; + unsigned long flags; + + ASSERT_SPINLOCK(&zbpg->lock); + for (i = 0, j = 0; i < ZBUD_MAX_BUDS; i++) { + zh = &zbpg->buddy[i]; + if (zh->size) { + client_id[j] = zh->client_id; + pool_id[j] = zh->pool_id; + oid[j] = zh->oid; + index[j] = zh->index; + j++; + } + } + spin_unlock(&zbpg->lock); + for (i = 0; i < j; i++) { + pool = zcache_get_pool_by_id(client_id[i], pool_id[i]); + BUG_ON(pool == NULL); + local_irq_save(flags); + /* these flushes should dispose of any local storage */ + tmem_flush_page(pool, &oid[i], index[i]); + local_irq_restore(flags); + zcache_put_pool(pool); + } +} + +/* + * Free nr pages. This code is funky because we want to hold the locks + * protecting various lists for as short a time as possible, and in some + * circumstances the list may change asynchronously when the list lock is + * not held. In some cases we also trylock not only to avoid waiting on a + * page in use by another cpu, but also to avoid potential deadlock due to + * lock inversion. + */ +static void zbud_evict_pages(int nr) +{ + struct zbud_page *zbpg; + int i, newly_unused_pages = 0; + + + /* now try freeing unbuddied pages, starting with least space avail */ + for (i = 0; i < MAX_CHUNK; i++) { +retry_unbud_list_i: + spin_lock_bh(&zbud_budlists_spinlock); + if (list_empty(&zbud_unbuddied[i].list)) { + spin_unlock_bh(&zbud_budlists_spinlock); + continue; + } + list_for_each_entry(zbpg, &zbud_unbuddied[i].list, bud_list) { + if (unlikely(!spin_trylock(&zbpg->lock))) + continue; + zbud_unbuddied[i].count--; + spin_unlock(&zbud_budlists_spinlock); + zcache_evicted_unbuddied_pages++; + /* want budlists unlocked when doing zbpg eviction */ + zbud_evict_zbpg(zbpg); + newly_unused_pages++; + local_bh_enable(); + if (--nr <= 0) + goto evict_unused; + goto retry_unbud_list_i; + } + spin_unlock_bh(&zbud_budlists_spinlock); } - put_cpu(); + + /* as a last resort, free buddied pages */ +retry_bud_list: + spin_lock_bh(&zbud_budlists_spinlock); + if (list_empty(&zbud_buddied_list)) { + spin_unlock_bh(&zbud_budlists_spinlock); + goto evict_unused; + } + list_for_each_entry(zbpg, &zbud_buddied_list, bud_list) { + if (unlikely(!spin_trylock(&zbpg->lock))) + continue; + zcache_zbud_buddied_count--; + spin_unlock(&zbud_budlists_spinlock); + zcache_evicted_buddied_pages++; + /* want budlists unlocked when doing zbpg eviction */ + zbud_evict_zbpg(zbpg); + newly_unused_pages++; + local_bh_enable(); + if (--nr <= 0) + goto evict_unused; + goto retry_bud_list; + } + spin_unlock_bh(&zbud_budlists_spinlock); + +evict_unused: + return; +} + +static DEFINE_PER_CPU(unsigned char *, zcache_remoteputmem); + +static int zbud_remotify_zbud(struct tmem_xhandle *xh, char *data, + size_t size) +{ + struct tmem_pool *pool; + int i, remotenode, ret = -1; + unsigned char cksum, *p; + unsigned long flags; + + for (p = data, cksum = 0, i = 0; i < size; i++) + cksum += *p; + ret = ramster_remote_put(xh, data, size, true, &remotenode); + if (ret == 0) { + /* data was successfully remoted so change the local version + * to point to the remote node where it landed */ + pool = zcache_get_pool_by_id(LOCAL_CLIENT, xh->pool_id); + BUG_ON(pool == NULL); + local_irq_save(flags); + /* tmem_replace will also free up any local space */ + (void)tmem_replace(pool, &xh->oid, xh->index, + pampd_make_remote(remotenode, size, cksum)); + local_irq_restore(flags); + zcache_put_pool(pool); + ramster_eph_pages_remoted++; + ret = 0; + } else + ramster_eph_pages_remote_failed++; return ret; } +static int zbud_remotify_zbpg(struct zbud_page *zbpg) +{ + struct zbud_hdr *zh1, *zh2 = NULL; + struct tmem_xhandle xh1, xh2 = { 0 }; + char *data1 = NULL, *data2 = NULL; + size_t size1 = 0, size2 = 0; + int ret = 0; + unsigned char *tmpmem = __get_cpu_var(zcache_remoteputmem); + + ASSERT_SPINLOCK(&zbpg->lock); + if (zbpg->buddy[0].size == 0) + zh1 = &zbpg->buddy[1]; + else if (zbpg->buddy[1].size == 0) + zh1 = &zbpg->buddy[0]; + else { + zh1 = &zbpg->buddy[0]; + zh2 = &zbpg->buddy[1]; + } + /* don't remotify pages that are already remotified */ + if (zh1->client_id != LOCAL_CLIENT) + zh1 = NULL; + if ((zh2 != NULL) && (zh2->client_id != LOCAL_CLIENT)) + zh2 = NULL; + + /* copy the data and metadata so can release lock */ + if (zh1 != NULL) { + xh1.client_id = zh1->client_id; + xh1.pool_id = zh1->pool_id; + xh1.oid = zh1->oid; + xh1.index = zh1->index; + size1 = zh1->size; + data1 = zbud_data(zh1, size1); + memcpy(tmpmem, zbud_data(zh1, size1), size1); + data1 = tmpmem; + tmpmem += size1; + } + if (zh2 != NULL) { + xh2.client_id = zh2->client_id; + xh2.pool_id = zh2->pool_id; + xh2.oid = zh2->oid; + xh2.index = zh2->index; + size2 = zh2->size; + memcpy(tmpmem, zbud_data(zh2, size2), size2); + data2 = tmpmem; + } + spin_unlock(&zbpg->lock); + preempt_enable(); + + /* OK, no locks held anymore, remotify one or both zbuds */ + if (zh1 != NULL) + ret = zbud_remotify_zbud(&xh1, data1, size1); + if (zh2 != NULL) + ret |= zbud_remotify_zbud(&xh2, data2, size2); + return ret; +} + +void zbud_remotify_pages(int nr) +{ + struct zbud_page *zbpg; + int i, ret; + + /* + * for now just try remotifying unbuddied pages, starting with + * least space avail + */ + for (i = 0; i < MAX_CHUNK; i++) { +retry_unbud_list_i: + preempt_disable(); /* enable in zbud_remotify_zbpg */ + spin_lock_bh(&zbud_budlists_spinlock); + if (list_empty(&zbud_unbuddied[i].list)) { + spin_unlock_bh(&zbud_budlists_spinlock); + preempt_enable(); + continue; /* next i in for loop */ + } + list_for_each_entry(zbpg, &zbud_unbuddied[i].list, bud_list) { + if (unlikely(!spin_trylock(&zbpg->lock))) + continue; /* next list_for_each_entry */ + zbud_unbuddied[i].count--; + /* want budlists unlocked when doing zbpg remotify */ + spin_unlock_bh(&zbud_budlists_spinlock); + ret = zbud_remotify_zbpg(zbpg); + /* preemption is re-enabled in zbud_remotify_zbpg */ + if (ret == 0) { + if (--nr <= 0) + goto out; + goto retry_unbud_list_i; + } + /* if fail to remotify any page, quit */ + pr_err("TESTING zbud_remotify_pages failed on page," + " trying to re-add\n"); + spin_lock_bh(&zbud_budlists_spinlock); + spin_lock(&zbpg->lock); + list_add_tail(&zbpg->bud_list, &zbud_unbuddied[i].list); + zbud_unbuddied[i].count++; + spin_unlock(&zbpg->lock); + spin_unlock_bh(&zbud_budlists_spinlock); + pr_err("TESTING zbud_remotify_pages failed on page," + " finished re-add\n"); + goto out; + } + spin_unlock_bh(&zbud_budlists_spinlock); + preempt_enable(); + } + +next_buddied_zbpg: + preempt_disable(); /* enable in zbud_remotify_zbpg */ + spin_lock_bh(&zbud_budlists_spinlock); + if (list_empty(&zbud_buddied_list)) + goto unlock_out; + list_for_each_entry(zbpg, &zbud_buddied_list, bud_list) { + if (unlikely(!spin_trylock(&zbpg->lock))) + continue; /* next list_for_each_entry */ + zcache_zbud_buddied_count--; + /* want budlists unlocked when doing zbpg remotify */ + spin_unlock_bh(&zbud_budlists_spinlock); + ret = zbud_remotify_zbpg(zbpg); + /* preemption is re-enabled in zbud_remotify_zbpg */ + if (ret == 0) { + if (--nr <= 0) + goto out; + goto next_buddied_zbpg; + } + /* if fail to remotify any page, quit */ + pr_err("TESTING zbud_remotify_pages failed on BUDDIED page," + " trying to re-add\n"); + spin_lock_bh(&zbud_budlists_spinlock); + spin_lock(&zbpg->lock); + list_add_tail(&zbpg->bud_list, &zbud_buddied_list); + zcache_zbud_buddied_count++; + spin_unlock(&zbpg->lock); + spin_unlock_bh(&zbud_budlists_spinlock); + pr_err("TESTING zbud_remotify_pages failed on BUDDIED page," + " finished re-add\n"); + goto out; + } +unlock_out: + spin_unlock_bh(&zbud_budlists_spinlock); + preempt_enable(); +out: + return; +} + +/* the "flush list" asynchronously collects pages to remotely flush */ +#define FLUSH_ENTIRE_OBJECT ((uint32_t)-1) +static void ramster_flnode_free(struct flushlist_node *, + struct tmem_pool *); + +static void zcache_remote_flush_page(struct flushlist_node *flnode) +{ + struct tmem_xhandle *xh; + int remotenode, ret; + + preempt_disable(); + xh = &flnode->xh; + remotenode = flnode->xh.client_id; + ret = ramster_remote_flush(xh, remotenode); + if (ret >= 0) + ramster_remote_pages_flushed++; + else + ramster_remote_page_flushes_failed++; + preempt_enable_no_resched(); + ramster_flnode_free(flnode, NULL); +} + +static void zcache_remote_flush_object(struct flushlist_node *flnode) +{ + struct tmem_xhandle *xh; + int remotenode, ret; + + preempt_disable(); + xh = &flnode->xh; + remotenode = flnode->xh.client_id; + ret = ramster_remote_flush_object(xh, remotenode); + if (ret >= 0) + ramster_remote_objects_flushed++; + else + ramster_remote_object_flushes_failed++; + preempt_enable_no_resched(); + ramster_flnode_free(flnode, NULL); +} + +static void zcache_remote_eph_put(struct zbud_hdr *zbud) +{ + /* FIXME */ +} + +static void zcache_remote_pers_put(struct zv_hdr *zv) +{ + struct tmem_xhandle xh; + uint16_t size; + bool ephemeral; + int remotenode, ret = -1; + char *data; + struct tmem_pool *pool; + unsigned long flags; + unsigned char cksum; + char *p; + int i; + unsigned char *tmpmem = __get_cpu_var(zcache_remoteputmem); + + ASSERT_SENTINEL(zv, ZVH); + BUG_ON(zv->client_id != LOCAL_CLIENT); + local_bh_disable(); + xh.client_id = zv->client_id; + xh.pool_id = zv->pool_id; + xh.oid = zv->oid; + xh.index = zv->index; + size = xv_get_object_size(zv) - sizeof(*zv); + BUG_ON(size == 0 || size > zv_max_page_size); + data = (char *)zv + sizeof(*zv); + for (p = data, cksum = 0, i = 0; i < size; i++) + cksum += *p; + memcpy(tmpmem, data, size); + data = tmpmem; + pool = zcache_get_pool_by_id(zv->client_id, zv->pool_id); + ephemeral = is_ephemeral(pool); + zcache_put_pool(pool); + /* now OK to release lock set in caller */ + spin_unlock(&zcache_rem_op_list_lock); + local_bh_enable(); + preempt_disable(); + ret = ramster_remote_put(&xh, data, size, ephemeral, &remotenode); + preempt_enable_no_resched(); + if (ret != 0) { + /* + * This is some form of a memory leak... if the remote put + * fails, there will never be another attempt to remotify + * this page. But since we've dropped the zv pointer, + * the page may have been freed or the data replaced + * so we can't just "put it back" in the remote op list. + * Even if we could, not sure where to put it in the list + * because there may be flushes that must be strictly + * ordered vs the put. So leave this as a FIXME for now. + * But count them so we know if it becomes a problem. + */ + ramster_pers_pages_remote_failed++; + goto out; + } else + atomic_inc(&ramster_remote_pers_pages); + ramster_pers_pages_remoted++; + /* + * data was successfully remoted so change the local version to + * point to the remote node where it landed + */ + local_bh_disable(); + pool = zcache_get_pool_by_id(LOCAL_CLIENT, xh.pool_id); + local_irq_save(flags); + (void)tmem_replace(pool, &xh.oid, xh.index, + pampd_make_remote(remotenode, size, cksum)); + local_irq_restore(flags); + zcache_put_pool(pool); + local_bh_enable(); +out: + return; +} + +static void zcache_do_remotify_ops(int nr) +{ + struct ramster_remotify_hdr *rem_op; + union remotify_list_node *u; + + while (1) { + if (!nr) + goto out; + spin_lock(&zcache_rem_op_list_lock); + if (list_empty(&zcache_rem_op_list)) { + spin_unlock(&zcache_rem_op_list_lock); + goto out; + } + rem_op = list_first_entry(&zcache_rem_op_list, + struct ramster_remotify_hdr, list); + list_del_init(&rem_op->list); + if (rem_op->op != RAMSTER_REMOTIFY_PERS_PUT) + spin_unlock(&zcache_rem_op_list_lock); + u = (union remotify_list_node *)rem_op; + switch (rem_op->op) { + case RAMSTER_REMOTIFY_EPH_PUT: +BUG(); + zcache_remote_eph_put((struct zbud_hdr *)rem_op); + break; + case RAMSTER_REMOTIFY_PERS_PUT: + zcache_remote_pers_put((struct zv_hdr *)rem_op); + break; + case RAMSTER_REMOTIFY_FLUSH_PAGE: + zcache_remote_flush_page((struct flushlist_node *)u); + break; + case RAMSTER_REMOTIFY_FLUSH_OBJ: + zcache_remote_flush_object((struct flushlist_node *)u); + break; + default: + BUG(); + } + } +out: + return; +} + +/* + * Communicate interface revision with userspace + */ +#include "cluster/ramster_nodemanager.h" +static unsigned long ramster_interface_revision = R2NM_API_VERSION; + +/* + * For now, just push over a few pages every few seconds to + * ensure that it basically works + */ +static struct workqueue_struct *ramster_remotify_workqueue; +static void ramster_remotify_process(struct work_struct *work); +static DECLARE_DELAYED_WORK(ramster_remotify_worker, + ramster_remotify_process); + +static void ramster_remotify_queue_delayed_work(unsigned long delay) +{ + if (!queue_delayed_work(ramster_remotify_workqueue, + &ramster_remotify_worker, delay)) + pr_err("ramster_remotify: bad workqueue\n"); +} + + +static int use_frontswap; +static int use_cleancache; +static int ramster_remote_target_nodenum = -1; +static void ramster_remotify_process(struct work_struct *work) +{ + static bool remotify_in_progress; + + BUG_ON(irqs_disabled()); + if (remotify_in_progress) + ramster_remotify_queue_delayed_work(HZ); + else if (ramster_remote_target_nodenum != -1) { + remotify_in_progress = true; +#ifdef CONFIG_CLEANCACHE + if (use_cleancache && ramster_eph_remotify_enable) + zbud_remotify_pages(5000); /* FIXME is this a good number? */ +#endif +#ifdef CONFIG_FRONTSWAP + if (use_frontswap && ramster_pers_remotify_enable) + zcache_do_remotify_ops(500); /* FIXME is this a good number? */ +#endif + remotify_in_progress = false; + ramster_remotify_queue_delayed_work(HZ); + } +} + +static void ramster_remotify_init(void) +{ + unsigned long n = 60UL; + ramster_remotify_workqueue = + create_singlethread_workqueue("ramster_remotify"); + ramster_remotify_queue_delayed_work(n * HZ); +} + + +static void zbud_init(void) +{ + int i; + + INIT_LIST_HEAD(&zbud_buddied_list); + zcache_zbud_buddied_count = 0; + for (i = 0; i < NCHUNKS; i++) { + INIT_LIST_HEAD(&zbud_unbuddied[i].list); + zbud_unbuddied[i].count = 0; + } +} + +#ifdef CONFIG_SYSFS /* - * policy parameters + * These sysfs routines show a nice distribution of how many zbpg's are + * currently (and have ever been placed) in each unbuddied list. It's fun + * to watch but can probably go away before final merge. + */ +static int zbud_show_unbuddied_list_counts(char *buf) +{ + int i; + char *p = buf; + + for (i = 0; i < NCHUNKS; i++) + p += sprintf(p, "%u ", zbud_unbuddied[i].count); + return p - buf; +} + +static int zbud_show_cumul_chunk_counts(char *buf) +{ + unsigned long i, chunks = 0, total_chunks = 0, sum_total_chunks = 0; + unsigned long total_chunks_lte_21 = 0, total_chunks_lte_32 = 0; + unsigned long total_chunks_lte_42 = 0; + char *p = buf; + + for (i = 0; i < NCHUNKS; i++) { + p += sprintf(p, "%lu ", zbud_cumul_chunk_counts[i]); + chunks += zbud_cumul_chunk_counts[i]; + total_chunks += zbud_cumul_chunk_counts[i]; + sum_total_chunks += i * zbud_cumul_chunk_counts[i]; + if (i == 21) + total_chunks_lte_21 = total_chunks; + if (i == 32) + total_chunks_lte_32 = total_chunks; + if (i == 42) + total_chunks_lte_42 = total_chunks; + } + p += sprintf(p, "<=21:%lu <=32:%lu <=42:%lu, mean:%lu\n", + total_chunks_lte_21, total_chunks_lte_32, total_chunks_lte_42, + chunks == 0 ? 0 : sum_total_chunks / chunks); + return p - buf; +} +#endif + +/********** + * This "zv" PAM implementation combines the TLSF-based xvMalloc + * with lzo1x compression to maximize the amount of data that can + * be packed into a physical page. + * + * Zv represents a PAM page with the index and object (plus a "size" value + * necessary for decompression) immediately preceding the compressed data. */ +/* rudimentary policy limits */ +/* total number of persistent pages may not exceed this percentage */ +static unsigned int zv_page_count_policy_percent = 75; /* * byte count defining poor compression; pages with greater zsize will be * rejected */ -static unsigned int zbud_max_zsize __read_mostly = (PAGE_SIZE / 8) * 7; +static unsigned int zv_max_zsize = (PAGE_SIZE / 8) * 7; /* * byte count defining poor *mean* compression; pages with greater zsize * will be rejected until sufficient better-compressed pages are accepted * driving the mean below this threshold */ -static unsigned int zbud_max_mean_zsize __read_mostly = (PAGE_SIZE / 8) * 5; +static unsigned int zv_max_mean_zsize = (PAGE_SIZE / 8) * 5; + +static atomic_t zv_curr_dist_counts[NCHUNKS]; +static atomic_t zv_cumul_dist_counts[NCHUNKS]; + + +static struct zv_hdr *zv_create(struct zcache_client *cli, uint32_t pool_id, + struct tmem_oid *oid, uint32_t index, + void *cdata, unsigned clen) +{ + struct page *page; + struct zv_hdr *zv = NULL; + uint32_t offset; + int alloc_size = clen + sizeof(struct zv_hdr); + int chunks = (alloc_size + (CHUNK_SIZE - 1)) >> CHUNK_SHIFT; + int ret; + + BUG_ON(!irqs_disabled()); + BUG_ON(chunks >= NCHUNKS); + ret = xv_malloc(cli->xvpool, clen + sizeof(struct zv_hdr), + &page, &offset, ZCACHE_GFP_MASK); + if (unlikely(ret)) + goto out; + atomic_inc(&zv_curr_dist_counts[chunks]); + atomic_inc(&zv_cumul_dist_counts[chunks]); + zv = kmap_atomic(page) + offset; + zv->index = index; + zv->oid = *oid; + zv->pool_id = pool_id; + SET_SENTINEL(zv, ZVH); + INIT_LIST_HEAD(&zv->rem_op.list); + zv->client_id = get_client_id_from_client(cli); + zv->rem_op.op = RAMSTER_REMOTIFY_PERS_PUT; + if (zv->client_id == LOCAL_CLIENT) { + spin_lock(&zcache_rem_op_list_lock); + list_add_tail(&zv->rem_op.list, &zcache_rem_op_list); + spin_unlock(&zcache_rem_op_list_lock); + } + memcpy((char *)zv + sizeof(struct zv_hdr), cdata, clen); + kunmap_atomic(zv); +out: + return zv; +} + +/* similar to zv_create, but just reserve space, no data yet */ +static struct zv_hdr *zv_alloc(struct tmem_pool *pool, + struct tmem_oid *oid, uint32_t index, + unsigned clen) +{ + struct zcache_client *cli = pool->client; + struct page *page; + struct zv_hdr *zv = NULL; + uint32_t offset; + int ret; + + BUG_ON(!irqs_disabled()); + BUG_ON(!is_local_client(pool->client)); + ret = xv_malloc(cli->xvpool, clen + sizeof(struct zv_hdr), + &page, &offset, ZCACHE_GFP_MASK); + if (unlikely(ret)) + goto out; + zv = kmap_atomic(page) + offset; + SET_SENTINEL(zv, ZVH); + INIT_LIST_HEAD(&zv->rem_op.list); + zv->client_id = LOCAL_CLIENT; + zv->rem_op.op = RAMSTER_INTRANSIT_PERS; + zv->index = index; + zv->oid = *oid; + zv->pool_id = pool->pool_id; + kunmap_atomic(zv); +out: + return zv; +} + +static void zv_free(struct xv_pool *xvpool, struct zv_hdr *zv) +{ + unsigned long flags; + struct page *page; + uint32_t offset; + uint16_t size = xv_get_object_size(zv); + int chunks = (size + (CHUNK_SIZE - 1)) >> CHUNK_SHIFT; + + ASSERT_SENTINEL(zv, ZVH); + BUG_ON(chunks >= NCHUNKS); + atomic_dec(&zv_curr_dist_counts[chunks]); + size -= sizeof(*zv); + spin_lock(&zcache_rem_op_list_lock); + size = xv_get_object_size(zv) - sizeof(*zv); + BUG_ON(size == 0); + INVERT_SENTINEL(zv, ZVH); + if (!list_empty(&zv->rem_op.list)) + list_del_init(&zv->rem_op.list); + spin_unlock(&zcache_rem_op_list_lock); + page = virt_to_page(zv); + offset = (unsigned long)zv & ~PAGE_MASK; + local_irq_save(flags); + xv_free(xvpool, page, offset); + local_irq_restore(flags); +} + +static void zv_decompress(struct page *page, struct zv_hdr *zv) +{ + size_t clen = PAGE_SIZE; + char *to_va; + unsigned size; + int ret; + + ASSERT_SENTINEL(zv, ZVH); + size = xv_get_object_size(zv) - sizeof(*zv); + BUG_ON(size == 0); + to_va = kmap_atomic(page); + ret = lzo1x_decompress_safe((char *)zv + sizeof(*zv), + size, to_va, &clen); + kunmap_atomic(to_va); + BUG_ON(ret != LZO_E_OK); + BUG_ON(clen != PAGE_SIZE); +} + +static void zv_copy_from_pampd(char *data, size_t *bufsize, struct zv_hdr *zv) +{ + unsigned size; + + ASSERT_SENTINEL(zv, ZVH); + size = xv_get_object_size(zv) - sizeof(*zv); + BUG_ON(size == 0 || size > zv_max_page_size); + BUG_ON(size > *bufsize); + memcpy(data, (char *)zv + sizeof(*zv), size); + *bufsize = size; +} + +static void zv_copy_to_pampd(struct zv_hdr *zv, char *data, size_t size) +{ + unsigned zv_size; + + ASSERT_SENTINEL(zv, ZVH); + zv_size = xv_get_object_size(zv) - sizeof(*zv); + BUG_ON(zv_size != size); + BUG_ON(zv_size == 0 || zv_size > zv_max_page_size); + memcpy((char *)zv + sizeof(*zv), data, size); +} + +#ifdef CONFIG_SYSFS +/* + * show a distribution of compression stats for zv pages. + */ + +static int zv_curr_dist_counts_show(char *buf) +{ + unsigned long i, n, chunks = 0, sum_total_chunks = 0; + char *p = buf; + + for (i = 0; i < NCHUNKS; i++) { + n = atomic_read(&zv_curr_dist_counts[i]); + p += sprintf(p, "%lu ", n); + chunks += n; + sum_total_chunks += i * n; + } + p += sprintf(p, "mean:%lu\n", + chunks == 0 ? 0 : sum_total_chunks / chunks); + return p - buf; +} + +static int zv_cumul_dist_counts_show(char *buf) +{ + unsigned long i, n, chunks = 0, sum_total_chunks = 0; + char *p = buf; + + for (i = 0; i < NCHUNKS; i++) { + n = atomic_read(&zv_cumul_dist_counts[i]); + p += sprintf(p, "%lu ", n); + chunks += n; + sum_total_chunks += i * n; + } + p += sprintf(p, "mean:%lu\n", + chunks == 0 ? 0 : sum_total_chunks / chunks); + return p - buf; +} + +/* + * setting zv_max_zsize via sysfs causes all persistent (e.g. swap) + * pages that don't compress to less than this value (including metadata + * overhead) to be rejected. We don't allow the value to get too close + * to PAGE_SIZE. + */ +static ssize_t zv_max_zsize_show(struct kobject *kobj, + struct kobj_attribute *attr, + char *buf) +{ + return sprintf(buf, "%u\n", zv_max_zsize); +} + +static ssize_t zv_max_zsize_store(struct kobject *kobj, + struct kobj_attribute *attr, + const char *buf, size_t count) +{ + unsigned long val; + int err; + + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + + err = kstrtoul(buf, 10, &val); + if (err || (val == 0) || (val > (PAGE_SIZE / 8) * 7)) + return -EINVAL; + zv_max_zsize = val; + return count; +} /* - * for now, used named slabs so can easily track usage; later can - * either just use kmalloc, or perhaps add a slab-like allocator - * to more carefully manage total memory utilization + * setting zv_max_mean_zsize via sysfs causes all persistent (e.g. swap) + * pages that don't compress to less than this value (including metadata + * overhead) to be rejected UNLESS the mean compression is also smaller + * than this value. In other words, we are load-balancing-by-zsize the + * accepted pages. Again, we don't allow the value to get too close + * to PAGE_SIZE. */ -static struct kmem_cache *zcache_objnode_cache; -static struct kmem_cache *zcache_obj_cache; +static ssize_t zv_max_mean_zsize_show(struct kobject *kobj, + struct kobj_attribute *attr, + char *buf) +{ + return sprintf(buf, "%u\n", zv_max_mean_zsize); +} -static DEFINE_PER_CPU(struct zcache_preload, zcache_preloads) = { 0, }; +static ssize_t zv_max_mean_zsize_store(struct kobject *kobj, + struct kobj_attribute *attr, + const char *buf, size_t count) +{ + unsigned long val; + int err; -/* we try to keep these statistics SMP-consistent */ -static long zcache_obj_count; -static atomic_t zcache_obj_atomic = ATOMIC_INIT(0); -static long zcache_obj_count_max; -static long zcache_objnode_count; -static atomic_t zcache_objnode_atomic = ATOMIC_INIT(0); -static long zcache_objnode_count_max; -static u64 zcache_eph_zbytes; -static atomic_long_t zcache_eph_zbytes_atomic = ATOMIC_INIT(0); -static u64 zcache_eph_zbytes_max; -static u64 zcache_pers_zbytes; -static atomic_long_t zcache_pers_zbytes_atomic = ATOMIC_INIT(0); -static u64 zcache_pers_zbytes_max; -static long zcache_eph_pageframes; -static atomic_t zcache_eph_pageframes_atomic = ATOMIC_INIT(0); -static long zcache_eph_pageframes_max; -static long zcache_pers_pageframes; -static atomic_t zcache_pers_pageframes_atomic = ATOMIC_INIT(0); -static long zcache_pers_pageframes_max; -static long zcache_pageframes_alloced; -static atomic_t zcache_pageframes_alloced_atomic = ATOMIC_INIT(0); -static long zcache_pageframes_freed; -static atomic_t zcache_pageframes_freed_atomic = ATOMIC_INIT(0); -static long zcache_eph_zpages; -static atomic_t zcache_eph_zpages_atomic = ATOMIC_INIT(0); -static long zcache_eph_zpages_max; -static long zcache_pers_zpages; -static atomic_t zcache_pers_zpages_atomic = ATOMIC_INIT(0); -static long zcache_pers_zpages_max; - -/* but for the rest of these, counting races are ok */ -static unsigned long zcache_flush_total; -static unsigned long zcache_flush_found; -static unsigned long zcache_flobj_total; -static unsigned long zcache_flobj_found; -static unsigned long zcache_failed_eph_puts; -static unsigned long zcache_failed_pers_puts; -static unsigned long zcache_failed_getfreepages; -static unsigned long zcache_failed_alloc; -static unsigned long zcache_put_to_flush; -static unsigned long zcache_compress_poor; -static unsigned long zcache_mean_compress_poor; -static unsigned long zcache_eph_ate_tail; -static unsigned long zcache_eph_ate_tail_failed; -static unsigned long zcache_pers_ate_eph; -static unsigned long zcache_pers_ate_eph_failed; -static unsigned long zcache_evicted_eph_zpages; -static unsigned long zcache_evicted_eph_pageframes; -static unsigned long zcache_last_active_file_pageframes; -static unsigned long zcache_last_inactive_file_pageframes; -static unsigned long zcache_last_active_anon_pageframes; -static unsigned long zcache_last_inactive_anon_pageframes; -static unsigned long zcache_eph_nonactive_puts_ignored; -static unsigned long zcache_pers_nonactive_puts_ignored; - -#ifdef CONFIG_DEBUG_FS -#include -#define zdfs debugfs_create_size_t -#define zdfs64 debugfs_create_u64 -static int zcache_debugfs_init(void) -{ - struct dentry *root = debugfs_create_dir("zcache", NULL); - if (root == NULL) - return -ENXIO; - - zdfs("obj_count", S_IRUGO, root, &zcache_obj_count); - zdfs("obj_count_max", S_IRUGO, root, &zcache_obj_count_max); - zdfs("objnode_count", S_IRUGO, root, &zcache_objnode_count); - zdfs("objnode_count_max", S_IRUGO, root, &zcache_objnode_count_max); - zdfs("flush_total", S_IRUGO, root, &zcache_flush_total); - zdfs("flush_found", S_IRUGO, root, &zcache_flush_found); - zdfs("flobj_total", S_IRUGO, root, &zcache_flobj_total); - zdfs("flobj_found", S_IRUGO, root, &zcache_flobj_found); - zdfs("failed_eph_puts", S_IRUGO, root, &zcache_failed_eph_puts); - zdfs("failed_pers_puts", S_IRUGO, root, &zcache_failed_pers_puts); - zdfs("failed_get_free_pages", S_IRUGO, root, - &zcache_failed_getfreepages); - zdfs("failed_alloc", S_IRUGO, root, &zcache_failed_alloc); - zdfs("put_to_flush", S_IRUGO, root, &zcache_put_to_flush); - zdfs("compress_poor", S_IRUGO, root, &zcache_compress_poor); - zdfs("mean_compress_poor", S_IRUGO, root, &zcache_mean_compress_poor); - zdfs("eph_ate_tail", S_IRUGO, root, &zcache_eph_ate_tail); - zdfs("eph_ate_tail_failed", S_IRUGO, root, &zcache_eph_ate_tail_failed); - zdfs("pers_ate_eph", S_IRUGO, root, &zcache_pers_ate_eph); - zdfs("pers_ate_eph_failed", S_IRUGO, root, &zcache_pers_ate_eph_failed); - zdfs("evicted_eph_zpages", S_IRUGO, root, &zcache_evicted_eph_zpages); - zdfs("evicted_eph_pageframes", S_IRUGO, root, - &zcache_evicted_eph_pageframes); - zdfs("eph_pageframes", S_IRUGO, root, &zcache_eph_pageframes); - zdfs("eph_pageframes_max", S_IRUGO, root, &zcache_eph_pageframes_max); - zdfs("pers_pageframes", S_IRUGO, root, &zcache_pers_pageframes); - zdfs("pers_pageframes_max", S_IRUGO, root, &zcache_pers_pageframes_max); - zdfs("eph_zpages", S_IRUGO, root, &zcache_eph_zpages); - zdfs("eph_zpages_max", S_IRUGO, root, &zcache_eph_zpages_max); - zdfs("pers_zpages", S_IRUGO, root, &zcache_pers_zpages); - zdfs("pers_zpages_max", S_IRUGO, root, &zcache_pers_zpages_max); - zdfs("last_active_file_pageframes", S_IRUGO, root, - &zcache_last_active_file_pageframes); - zdfs("last_inactive_file_pageframes", S_IRUGO, root, - &zcache_last_inactive_file_pageframes); - zdfs("last_active_anon_pageframes", S_IRUGO, root, - &zcache_last_active_anon_pageframes); - zdfs("last_inactive_anon_pageframes", S_IRUGO, root, - &zcache_last_inactive_anon_pageframes); - zdfs("eph_nonactive_puts_ignored", S_IRUGO, root, - &zcache_eph_nonactive_puts_ignored); - zdfs("pers_nonactive_puts_ignored", S_IRUGO, root, - &zcache_pers_nonactive_puts_ignored); - zdfs64("eph_zbytes", S_IRUGO, root, &zcache_eph_zbytes); - zdfs64("eph_zbytes_max", S_IRUGO, root, &zcache_eph_zbytes_max); - zdfs64("pers_zbytes", S_IRUGO, root, &zcache_pers_zbytes); - zdfs64("pers_zbytes_max", S_IRUGO, root, &zcache_pers_zbytes_max); - return 0; + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + + err = kstrtoul(buf, 10, &val); + if (err || (val == 0) || (val > (PAGE_SIZE / 8) * 7)) + return -EINVAL; + zv_max_mean_zsize = val; + return count; } -#undef zdebugfs -#undef zdfs64 -#endif -#define ZCACHE_DEBUG -#ifdef ZCACHE_DEBUG -/* developers can call this in case of ooms, e.g. to find memory leaks */ -void zcache_dump(void) -{ - pr_info("zcache: obj_count=%lu\n", zcache_obj_count); - pr_info("zcache: obj_count_max=%lu\n", zcache_obj_count_max); - pr_info("zcache: objnode_count=%lu\n", zcache_objnode_count); - pr_info("zcache: objnode_count_max=%lu\n", zcache_objnode_count_max); - pr_info("zcache: flush_total=%lu\n", zcache_flush_total); - pr_info("zcache: flush_found=%lu\n", zcache_flush_found); - pr_info("zcache: flobj_total=%lu\n", zcache_flobj_total); - pr_info("zcache: flobj_found=%lu\n", zcache_flobj_found); - pr_info("zcache: failed_eph_puts=%lu\n", zcache_failed_eph_puts); - pr_info("zcache: failed_pers_puts=%lu\n", zcache_failed_pers_puts); - pr_info("zcache: failed_get_free_pages=%lu\n", - zcache_failed_getfreepages); - pr_info("zcache: failed_alloc=%lu\n", zcache_failed_alloc); - pr_info("zcache: put_to_flush=%lu\n", zcache_put_to_flush); - pr_info("zcache: compress_poor=%lu\n", zcache_compress_poor); - pr_info("zcache: mean_compress_poor=%lu\n", - zcache_mean_compress_poor); - pr_info("zcache: eph_ate_tail=%lu\n", zcache_eph_ate_tail); - pr_info("zcache: eph_ate_tail_failed=%lu\n", - zcache_eph_ate_tail_failed); - pr_info("zcache: pers_ate_eph=%lu\n", zcache_pers_ate_eph); - pr_info("zcache: pers_ate_eph_failed=%lu\n", - zcache_pers_ate_eph_failed); - pr_info("zcache: evicted_eph_zpages=%lu\n", zcache_evicted_eph_zpages); - pr_info("zcache: evicted_eph_pageframes=%lu\n", - zcache_evicted_eph_pageframes); - pr_info("zcache: eph_pageframes=%lu\n", zcache_eph_pageframes); - pr_info("zcache: eph_pageframes_max=%lu\n", zcache_eph_pageframes_max); - pr_info("zcache: pers_pageframes=%lu\n", zcache_pers_pageframes); - pr_info("zcache: pers_pageframes_max=%lu\n", - zcache_pers_pageframes_max); - pr_info("zcache: eph_zpages=%lu\n", zcache_eph_zpages); - pr_info("zcache: eph_zpages_max=%lu\n", zcache_eph_zpages_max); - pr_info("zcache: pers_zpages=%lu\n", zcache_pers_zpages); - pr_info("zcache: pers_zpages_max=%lu\n", zcache_pers_zpages_max); - pr_info("zcache: eph_zbytes=%llu\n", - (unsigned long long)zcache_eph_zbytes); - pr_info("zcache: eph_zbytes_max=%llu\n", - (unsigned long long)zcache_eph_zbytes_max); - pr_info("zcache: pers_zbytes=%llu\n", - (unsigned long long)zcache_pers_zbytes); - pr_info("zcache: pers_zbytes_max=%llu\n", - (unsigned long long)zcache_pers_zbytes_max); +/* + * setting zv_page_count_policy_percent via sysfs sets an upper bound of + * persistent (e.g. swap) pages that will be retained according to: + * (zv_page_count_policy_percent * totalram_pages) / 100) + * when that limit is reached, further puts will be rejected (until + * some pages have been flushed). Note that, due to compression, + * this number may exceed 100; it defaults to 75 and we set an + * arbitrary limit of 150. A poor choice will almost certainly result + * in OOM's, so this value should only be changed prudently. + */ +static ssize_t zv_page_count_policy_percent_show(struct kobject *kobj, + struct kobj_attribute *attr, + char *buf) +{ + return sprintf(buf, "%u\n", zv_page_count_policy_percent); +} + +static ssize_t zv_page_count_policy_percent_store(struct kobject *kobj, + struct kobj_attribute *attr, + const char *buf, size_t count) +{ + unsigned long val; + int err; + + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + + err = kstrtoul(buf, 10, &val); + if (err || (val == 0) || (val > 150)) + return -EINVAL; + zv_page_count_policy_percent = val; + return count; } + +static struct kobj_attribute zcache_zv_max_zsize_attr = { + .attr = { .name = "zv_max_zsize", .mode = 0644 }, + .show = zv_max_zsize_show, + .store = zv_max_zsize_store, +}; + +static struct kobj_attribute zcache_zv_max_mean_zsize_attr = { + .attr = { .name = "zv_max_mean_zsize", .mode = 0644 }, + .show = zv_max_mean_zsize_show, + .store = zv_max_mean_zsize_store, +}; + +static struct kobj_attribute zcache_zv_page_count_policy_percent_attr = { + .attr = { .name = "zv_page_count_policy_percent", + .mode = 0644 }, + .show = zv_page_count_policy_percent_show, + .store = zv_page_count_policy_percent_store, +}; #endif /* * zcache core code starts here */ -static struct zcache_client zcache_host; -static struct zcache_client zcache_clients[MAX_CLIENTS]; - -static inline bool is_local_client(struct zcache_client *cli) -{ - return cli == &zcache_host; -} - -static struct zcache_client *zcache_get_client_by_id(uint16_t cli_id) -{ - struct zcache_client *cli = &zcache_host; - - if (cli_id != LOCAL_CLIENT) { - if (cli_id >= MAX_CLIENTS) - goto out; - cli = &zcache_clients[cli_id]; - } -out: - return cli; -} +/* useful stats not collected by cleancache or frontswap */ +static unsigned long zcache_flush_total; +static unsigned long zcache_flush_found; +static unsigned long zcache_flobj_total; +static unsigned long zcache_flobj_found; +static unsigned long zcache_failed_eph_puts; +static unsigned long zcache_nonactive_puts; +static unsigned long zcache_failed_pers_puts; /* * Tmem operations assume the poolid implies the invoking client. @@ -328,16 +1398,21 @@ static struct zcache_client *zcache_get_client_by_id(uint16_t cli_id) * of zcache would have one client per guest and each client might * have a poolid==N. */ -struct tmem_pool *zcache_get_pool_by_id(uint16_t cli_id, uint16_t poolid) +static struct tmem_pool *zcache_get_pool_by_id(uint16_t cli_id, uint16_t poolid) { struct tmem_pool *pool = NULL; struct zcache_client *cli = NULL; - cli = zcache_get_client_by_id(cli_id); - if (cli == NULL) - goto out; - if (!is_local_client(cli)) + if (cli_id == LOCAL_CLIENT) + cli = &zcache_host; + else { + if (cli_id >= MAX_CLIENTS) + goto out; + cli = &zcache_clients[cli_id]; + if (cli == NULL) + goto out; atomic_inc(&cli->refcount); + } if (poolid < MAX_POOLS_PER_CLIENT) { pool = cli->tmem_pools[poolid]; if (pool != NULL) @@ -347,7 +1422,7 @@ struct tmem_pool *zcache_get_pool_by_id(uint16_t cli_id, uint16_t poolid) return pool; } -void zcache_put_pool(struct tmem_pool *pool) +static void zcache_put_pool(struct tmem_pool *pool) { struct zcache_client *cli = NULL; @@ -355,26 +1430,173 @@ void zcache_put_pool(struct tmem_pool *pool) BUG(); cli = pool->client; atomic_dec(&pool->refcount); - if (!is_local_client(cli)) - atomic_dec(&cli->refcount); + atomic_dec(&cli->refcount); } int zcache_new_client(uint16_t cli_id) { - struct zcache_client *cli; + struct zcache_client *cli = NULL; int ret = -1; - cli = zcache_get_client_by_id(cli_id); + if (cli_id == LOCAL_CLIENT) + cli = &zcache_host; + else if ((unsigned int)cli_id < MAX_CLIENTS) + cli = &zcache_clients[cli_id]; if (cli == NULL) goto out; if (cli->allocated) goto out; cli->allocated = 1; +#ifdef CONFIG_FRONTSWAP + cli->xvpool = xv_create_pool(); + if (cli->xvpool == NULL) + goto out; +#endif + ret = 0; +out: + return ret; +} + +/* counters for debugging */ +static unsigned long zcache_failed_get_free_pages; +static unsigned long zcache_failed_alloc; +static unsigned long zcache_put_to_flush; + +/* + * for now, used named slabs so can easily track usage; later can + * either just use kmalloc, or perhaps add a slab-like allocator + * to more carefully manage total memory utilization + */ +static struct kmem_cache *zcache_objnode_cache; +static struct kmem_cache *zcache_obj_cache; +static struct kmem_cache *ramster_flnode_cache; +static atomic_t zcache_curr_obj_count = ATOMIC_INIT(0); +static unsigned long zcache_curr_obj_count_max; +static atomic_t zcache_curr_objnode_count = ATOMIC_INIT(0); +static unsigned long zcache_curr_objnode_count_max; + +/* + * to avoid memory allocation recursion (e.g. due to direct reclaim), we + * preload all necessary data structures so the hostops callbacks never + * actually do a malloc + */ +struct zcache_preload { + void *page; + struct tmem_obj *obj; + int nr; + struct tmem_objnode *objnodes[OBJNODE_TREE_MAX_PATH]; + struct flushlist_node *flnode; +}; +static DEFINE_PER_CPU(struct zcache_preload, zcache_preloads) = { 0, }; + +static int zcache_do_preload(struct tmem_pool *pool) +{ + struct zcache_preload *kp; + struct tmem_objnode *objnode; + struct tmem_obj *obj; + struct flushlist_node *flnode; + void *page; + int ret = -ENOMEM; + + if (unlikely(zcache_objnode_cache == NULL)) + goto out; + if (unlikely(zcache_obj_cache == NULL)) + goto out; + preempt_disable(); + kp = &__get_cpu_var(zcache_preloads); + while (kp->nr < ARRAY_SIZE(kp->objnodes)) { + preempt_enable_no_resched(); + objnode = kmem_cache_alloc(zcache_objnode_cache, + ZCACHE_GFP_MASK); + if (unlikely(objnode == NULL)) { + zcache_failed_alloc++; + goto out; + } + preempt_disable(); + kp = &__get_cpu_var(zcache_preloads); + if (kp->nr < ARRAY_SIZE(kp->objnodes)) + kp->objnodes[kp->nr++] = objnode; + else + kmem_cache_free(zcache_objnode_cache, objnode); + } + preempt_enable_no_resched(); + obj = kmem_cache_alloc(zcache_obj_cache, ZCACHE_GFP_MASK); + if (unlikely(obj == NULL)) { + zcache_failed_alloc++; + goto out; + } + flnode = kmem_cache_alloc(ramster_flnode_cache, ZCACHE_GFP_MASK); + if (unlikely(flnode == NULL)) { + zcache_failed_alloc++; + goto out; + } + if (is_ephemeral(pool)) { + page = (void *)__get_free_page(ZCACHE_GFP_MASK); + if (unlikely(page == NULL)) { + zcache_failed_get_free_pages++; + kmem_cache_free(zcache_obj_cache, obj); + kmem_cache_free(ramster_flnode_cache, flnode); + goto out; + } + } + preempt_disable(); + kp = &__get_cpu_var(zcache_preloads); + if (kp->obj == NULL) + kp->obj = obj; + else + kmem_cache_free(zcache_obj_cache, obj); + if (kp->flnode == NULL) + kp->flnode = flnode; + else + kmem_cache_free(ramster_flnode_cache, flnode); + if (is_ephemeral(pool)) { + if (kp->page == NULL) + kp->page = page; + else + free_page((unsigned long)page); + } ret = 0; out: return ret; } +static int ramster_do_preload_flnode_only(struct tmem_pool *pool) +{ + struct zcache_preload *kp; + struct flushlist_node *flnode; + int ret = -ENOMEM; + + BUG_ON(!irqs_disabled()); + if (unlikely(ramster_flnode_cache == NULL)) + BUG(); + kp = &__get_cpu_var(zcache_preloads); + flnode = kmem_cache_alloc(ramster_flnode_cache, GFP_ATOMIC); + if (unlikely(flnode == NULL) && kp->flnode == NULL) + BUG(); /* FIXME handle more gracefully, but how??? */ + else if (kp->flnode == NULL) + kp->flnode = flnode; + else + kmem_cache_free(ramster_flnode_cache, flnode); + return ret; +} + +static void *zcache_get_free_page(void) +{ + struct zcache_preload *kp; + void *page; + + kp = &__get_cpu_var(zcache_preloads); + page = kp->page; + BUG_ON(page == NULL); + kp->page = NULL; + return page; +} + +static void zcache_free_page(void *p) +{ + free_page((unsigned long)p); +} + /* * zcache implementation for tmem host ops */ @@ -382,56 +1604,78 @@ int zcache_new_client(uint16_t cli_id) static struct tmem_objnode *zcache_objnode_alloc(struct tmem_pool *pool) { struct tmem_objnode *objnode = NULL; + unsigned long count; struct zcache_preload *kp; - int i; kp = &__get_cpu_var(zcache_preloads); - for (i = 0; i < ARRAY_SIZE(kp->objnodes); i++) { - objnode = kp->objnodes[i]; - if (objnode != NULL) { - kp->objnodes[i] = NULL; - break; - } - } + if (kp->nr <= 0) + goto out; + objnode = kp->objnodes[kp->nr - 1]; BUG_ON(objnode == NULL); - zcache_objnode_count = atomic_inc_return(&zcache_objnode_atomic); - if (zcache_objnode_count > zcache_objnode_count_max) - zcache_objnode_count_max = zcache_objnode_count; + kp->objnodes[kp->nr - 1] = NULL; + kp->nr--; + count = atomic_inc_return(&zcache_curr_objnode_count); + if (count > zcache_curr_objnode_count_max) + zcache_curr_objnode_count_max = count; +out: return objnode; } static void zcache_objnode_free(struct tmem_objnode *objnode, struct tmem_pool *pool) { - zcache_objnode_count = - atomic_dec_return(&zcache_objnode_atomic); - BUG_ON(zcache_objnode_count < 0); + atomic_dec(&zcache_curr_objnode_count); + BUG_ON(atomic_read(&zcache_curr_objnode_count) < 0); kmem_cache_free(zcache_objnode_cache, objnode); } static struct tmem_obj *zcache_obj_alloc(struct tmem_pool *pool) { struct tmem_obj *obj = NULL; + unsigned long count; struct zcache_preload *kp; kp = &__get_cpu_var(zcache_preloads); obj = kp->obj; BUG_ON(obj == NULL); kp->obj = NULL; - zcache_obj_count = atomic_inc_return(&zcache_obj_atomic); - if (zcache_obj_count > zcache_obj_count_max) - zcache_obj_count_max = zcache_obj_count; + count = atomic_inc_return(&zcache_curr_obj_count); + if (count > zcache_curr_obj_count_max) + zcache_curr_obj_count_max = count; return obj; } static void zcache_obj_free(struct tmem_obj *obj, struct tmem_pool *pool) { - zcache_obj_count = - atomic_dec_return(&zcache_obj_atomic); - BUG_ON(zcache_obj_count < 0); + atomic_dec(&zcache_curr_obj_count); + BUG_ON(atomic_read(&zcache_curr_obj_count) < 0); kmem_cache_free(zcache_obj_cache, obj); } +static struct flushlist_node *ramster_flnode_alloc(struct tmem_pool *pool) +{ + struct flushlist_node *flnode = NULL; + struct zcache_preload *kp; + int count; + + kp = &__get_cpu_var(zcache_preloads); + flnode = kp->flnode; + BUG_ON(flnode == NULL); + kp->flnode = NULL; + count = atomic_inc_return(&ramster_curr_flnode_count); + if (count > ramster_curr_flnode_count_max) + ramster_curr_flnode_count_max = count; + return flnode; +} + +static void ramster_flnode_free(struct flushlist_node *flnode, + struct tmem_pool *pool) +{ + atomic_dec(&ramster_curr_flnode_count); + BUG_ON(atomic_read(&ramster_curr_flnode_count) < 0); + kmem_cache_free(ramster_flnode_cache, flnode); +} + static struct tmem_hostops zcache_hostops = { .obj_alloc = zcache_obj_alloc, .obj_free = zcache_obj_free, @@ -439,498 +1683,583 @@ static struct tmem_hostops zcache_hostops = { .objnode_free = zcache_objnode_free, }; -static struct page *zcache_alloc_page(void) -{ - struct page *page = alloc_page(ZCACHE_GFP_MASK); - - if (page != NULL) - zcache_pageframes_alloced = - atomic_inc_return(&zcache_pageframes_alloced_atomic); - return page; -} +/* + * zcache implementations for PAM page descriptor ops + */ -#ifdef FRONTSWAP_HAS_UNUSE -static void zcache_unacct_page(void) -{ - zcache_pageframes_freed = - atomic_inc_return(&zcache_pageframes_freed_atomic); -} -#endif -static void zcache_free_page(struct page *page) +static inline void dec_and_check(atomic_t *pvar) { - long curr_pageframes; - static long max_pageframes, min_pageframes; - - if (page == NULL) - BUG(); - __free_page(page); - zcache_pageframes_freed = - atomic_inc_return(&zcache_pageframes_freed_atomic); - curr_pageframes = zcache_pageframes_alloced - - atomic_read(&zcache_pageframes_freed_atomic) - - atomic_read(&zcache_eph_pageframes_atomic) - - atomic_read(&zcache_pers_pageframes_atomic); - if (curr_pageframes > max_pageframes) - max_pageframes = curr_pageframes; - if (curr_pageframes < min_pageframes) - min_pageframes = curr_pageframes; -#ifdef ZCACHE_DEBUG - if (curr_pageframes > 2L || curr_pageframes < -2L) { - /* pr_info here */ - } -#endif + atomic_dec(pvar); + /* later when all accounting is fixed, make this a BUG */ + WARN_ON_ONCE(atomic_read(pvar) < 0); } -/* - * zcache implementations for PAM page descriptor ops - */ +static atomic_t zcache_curr_eph_pampd_count = ATOMIC_INIT(0); +static unsigned long zcache_curr_eph_pampd_count_max; +static atomic_t zcache_curr_pers_pampd_count = ATOMIC_INIT(0); +static unsigned long zcache_curr_pers_pampd_count_max; /* forward reference */ -static void zcache_compress(struct page *from, - void **out_va, unsigned *out_len); +static int zcache_compress(struct page *from, void **out_va, size_t *out_len); -static struct page *zcache_evict_eph_pageframe(void); - -static void *zcache_pampd_eph_create(char *data, size_t size, bool raw, - struct tmem_handle *th) +static int zcache_pampd_eph_create(char *data, size_t size, bool raw, + struct tmem_pool *pool, struct tmem_oid *oid, + uint32_t index, void **pampd) { - void *pampd = NULL, *cdata = data; - unsigned clen = size; - struct page *page = (struct page *)(data), *newpage; + int ret = -1; + void *cdata = data; + size_t clen = size; + struct zcache_client *cli = pool->client; + uint16_t client_id = get_client_id_from_client(cli); + struct page *page = NULL; + unsigned long count; if (!raw) { - zcache_compress(page, &cdata, &clen); - if (clen > zbud_max_buddy_size()) { + page = virt_to_page(data); + ret = zcache_compress(page, &cdata, &clen); + if (ret == 0) + goto out; + if (clen == 0 || clen > zbud_max_buddy_size()) { zcache_compress_poor++; goto out; } - } else { - BUG_ON(clen > zbud_max_buddy_size()); } - - /* look for space via an existing match first */ - pampd = (void *)zbud_match_prep(th, true, cdata, clen); - if (pampd != NULL) - goto got_pampd; - - /* no match, now we need to find (or free up) a full page */ - newpage = zcache_alloc_page(); - if (newpage != NULL) - goto create_in_new_page; - - zcache_failed_getfreepages++; - /* can't allocate a page, evict an ephemeral page via LRU */ - newpage = zcache_evict_eph_pageframe(); - if (newpage == NULL) { - zcache_eph_ate_tail_failed++; + *pampd = (void *)zbud_create(client_id, pool->pool_id, oid, + index, page, cdata, clen); + if (*pampd == NULL) { + ret = -ENOMEM; goto out; } - zcache_eph_ate_tail++; - -create_in_new_page: - pampd = (void *)zbud_create_prep(th, true, cdata, clen, newpage); - BUG_ON(pampd == NULL); - zcache_eph_pageframes = - atomic_inc_return(&zcache_eph_pageframes_atomic); - if (zcache_eph_pageframes > zcache_eph_pageframes_max) - zcache_eph_pageframes_max = zcache_eph_pageframes; - -got_pampd: - zcache_eph_zbytes = - atomic_long_add_return(clen, &zcache_eph_zbytes_atomic); - if (zcache_eph_zbytes > zcache_eph_zbytes_max) - zcache_eph_zbytes_max = zcache_eph_zbytes; - zcache_eph_zpages = atomic_inc_return(&zcache_eph_zpages_atomic); - if (zcache_eph_zpages > zcache_eph_zpages_max) - zcache_eph_zpages_max = zcache_eph_zpages; - if (ramster_enabled && raw) - ramster_count_foreign_pages(true, 1); + ret = 0; + count = atomic_inc_return(&zcache_curr_eph_pampd_count); + if (count > zcache_curr_eph_pampd_count_max) + zcache_curr_eph_pampd_count_max = count; + if (client_id != LOCAL_CLIENT) { + count = atomic_inc_return(&ramster_foreign_eph_pampd_count); + if (count > ramster_foreign_eph_pampd_count_max) + ramster_foreign_eph_pampd_count_max = count; + } out: - return pampd; + return ret; } -static void *zcache_pampd_pers_create(char *data, size_t size, bool raw, - struct tmem_handle *th) +static int zcache_pampd_pers_create(char *data, size_t size, bool raw, + struct tmem_pool *pool, struct tmem_oid *oid, + uint32_t index, void **pampd) { - void *pampd = NULL, *cdata = data; - unsigned clen = size; - struct page *page = (struct page *)(data), *newpage; - unsigned long zbud_mean_zsize; - unsigned long curr_pers_zpages, total_zsize; + int ret = -1; + void *cdata = data; + size_t clen = size; + struct zcache_client *cli = pool->client; + struct page *page; + unsigned long count; + unsigned long zv_mean_zsize; + struct zv_hdr *zv; + long curr_pers_pampd_count; + u64 total_zsize; +#ifdef RAMSTER_TESTING + static bool pampd_neg_warned; +#endif - if (data == NULL) { - BUG_ON(!ramster_enabled); - goto create_pampd; + curr_pers_pampd_count = atomic_read(&zcache_curr_pers_pampd_count) - + atomic_read(&ramster_remote_pers_pages); +#ifdef RAMSTER_TESTING + /* should always be positive, but warn if accounting is off */ + if (!pampd_neg_warned) { + pr_warn("ramster: bad accounting for curr_pers_pampd_count\n"); + pampd_neg_warned = true; } - curr_pers_zpages = zcache_pers_zpages; -/* FIXME CONFIG_RAMSTER... subtract atomic remote_pers_pages here? */ - if (!raw) - zcache_compress(page, &cdata, &clen); +#endif + if (curr_pers_pampd_count > + (zv_page_count_policy_percent * totalram_pages) / 100) { + zcache_policy_percent_exceeded++; + goto out; + } + if (raw) + goto ok_to_create; + page = virt_to_page(data); + if (zcache_compress(page, &cdata, &clen) == 0) + goto out; /* reject if compression is too poor */ - if (clen > zbud_max_zsize) { + if (clen > zv_max_zsize) { zcache_compress_poor++; goto out; } /* reject if mean compression is too poor */ - if ((clen > zbud_max_mean_zsize) && (curr_pers_zpages > 0)) { - total_zsize = zcache_pers_zbytes; - if ((long)total_zsize < 0) - total_zsize = 0; - zbud_mean_zsize = div_u64(total_zsize, - curr_pers_zpages); - if (zbud_mean_zsize > zbud_max_mean_zsize) { + if ((clen > zv_max_mean_zsize) && (curr_pers_pampd_count > 0)) { + total_zsize = xv_get_total_size_bytes(cli->xvpool); + zv_mean_zsize = div_u64(total_zsize, curr_pers_pampd_count); + if (zv_mean_zsize > zv_max_mean_zsize) { zcache_mean_compress_poor++; goto out; } } - -create_pampd: - /* look for space via an existing match first */ - pampd = (void *)zbud_match_prep(th, false, cdata, clen); - if (pampd != NULL) - goto got_pampd; - - /* no match, now we need to find (or free up) a full page */ - newpage = zcache_alloc_page(); - if (newpage != NULL) - goto create_in_new_page; - /* - * FIXME do the following only if eph is oversized? - * if (zcache_eph_pageframes > - * (global_page_state(NR_LRU_BASE + LRU_ACTIVE_FILE) + - * global_page_state(NR_LRU_BASE + LRU_INACTIVE_FILE))) - */ - zcache_failed_getfreepages++; - /* can't allocate a page, evict an ephemeral page via LRU */ - newpage = zcache_evict_eph_pageframe(); - if (newpage == NULL) { - zcache_pers_ate_eph_failed++; +ok_to_create: + *pampd = (void *)zv_create(cli, pool->pool_id, oid, index, cdata, clen); + if (*pampd == NULL) { + ret = -ENOMEM; goto out; } - zcache_pers_ate_eph++; - -create_in_new_page: - pampd = (void *)zbud_create_prep(th, false, cdata, clen, newpage); - BUG_ON(pampd == NULL); - zcache_pers_pageframes = - atomic_inc_return(&zcache_pers_pageframes_atomic); - if (zcache_pers_pageframes > zcache_pers_pageframes_max) - zcache_pers_pageframes_max = zcache_pers_pageframes; - -got_pampd: - zcache_pers_zpages = atomic_inc_return(&zcache_pers_zpages_atomic); - if (zcache_pers_zpages > zcache_pers_zpages_max) - zcache_pers_zpages_max = zcache_pers_zpages; - zcache_pers_zbytes = - atomic_long_add_return(clen, &zcache_pers_zbytes_atomic); - if (zcache_pers_zbytes > zcache_pers_zbytes_max) - zcache_pers_zbytes_max = zcache_pers_zbytes; - if (ramster_enabled && raw) - ramster_count_foreign_pages(false, 1); + ret = 0; + count = atomic_inc_return(&zcache_curr_pers_pampd_count); + if (count > zcache_curr_pers_pampd_count_max) + zcache_curr_pers_pampd_count_max = count; + if (is_local_client(cli)) + goto out; + zv = *(struct zv_hdr **)pampd; + count = atomic_inc_return(&ramster_foreign_pers_pampd_count); + if (count > ramster_foreign_pers_pampd_count_max) + ramster_foreign_pers_pampd_count_max = count; out: - return pampd; + return ret; } -/* - * This is called directly from zcache_put_page to pre-allocate space - * to store a zpage. - */ -void *zcache_pampd_create(char *data, unsigned int size, bool raw, - int eph, struct tmem_handle *th) +static void *zcache_pampd_create(char *data, size_t size, bool raw, int eph, + struct tmem_pool *pool, struct tmem_oid *oid, + uint32_t index) { void *pampd = NULL; - struct zcache_preload *kp; - struct tmem_objnode *objnode; - struct tmem_obj *obj; - int i; + int ret; + bool ephemeral; - BUG_ON(!irqs_disabled()); - /* pre-allocate per-cpu metadata */ - BUG_ON(zcache_objnode_cache == NULL); - BUG_ON(zcache_obj_cache == NULL); - kp = &__get_cpu_var(zcache_preloads); - for (i = 0; i < ARRAY_SIZE(kp->objnodes); i++) { - objnode = kp->objnodes[i]; - if (objnode == NULL) { - objnode = kmem_cache_alloc(zcache_objnode_cache, - ZCACHE_GFP_MASK); - if (unlikely(objnode == NULL)) { - zcache_failed_alloc++; - goto out; - } - kp->objnodes[i] = objnode; - } - } - if (kp->obj == NULL) { - obj = kmem_cache_alloc(zcache_obj_cache, ZCACHE_GFP_MASK); - kp->obj = obj; - } - if (unlikely(kp->obj == NULL)) { - zcache_failed_alloc++; - goto out; - } - /* - * ok, have all the metadata pre-allocated, now do the data - * but since how we allocate the data is dependent on ephemeral - * or persistent, we split the call here to different sub-functions - */ - if (eph) - pampd = zcache_pampd_eph_create(data, size, raw, th); + BUG_ON(preemptible()); + ephemeral = (eph == 1) || ((eph == 0) && is_ephemeral(pool)); + if (ephemeral) + ret = zcache_pampd_eph_create(data, size, raw, pool, + oid, index, &pampd); else - pampd = zcache_pampd_pers_create(data, size, raw, th); -out: + ret = zcache_pampd_pers_create(data, size, raw, pool, + oid, index, &pampd); + /* FIXME add some counters here for failed creates? */ return pampd; } /* - * This is a pamops called via tmem_put and is necessary to "finish" - * a pampd creation. + * fill the pageframe corresponding to the struct page with the data + * from the passed pampd */ -void zcache_pampd_create_finish(void *pampd, bool eph) +static int zcache_pampd_get_data(char *data, size_t *bufsize, bool raw, + void *pampd, struct tmem_pool *pool, + struct tmem_oid *oid, uint32_t index) { - zbud_create_finish((struct zbudref *)pampd, eph); + int ret = 0; + + BUG_ON(preemptible()); + BUG_ON(is_ephemeral(pool)); /* Fix later for shared pools? */ + BUG_ON(pampd_is_remote(pampd)); + if (raw) + zv_copy_from_pampd(data, bufsize, pampd); + else + zv_decompress(virt_to_page(data), pampd); + return ret; } -/* - * This is passed as a function parameter to zbud_decompress so that - * zbud need not be familiar with the details of crypto. It assumes that - * the bytes from_va and to_va through from_va+size-1 and to_va+size-1 are - * kmapped. It must be successful, else there is a logic bug somewhere. - */ -static void zcache_decompress(char *from_va, unsigned int size, char *to_va) +static int zcache_pampd_get_data_and_free(char *data, size_t *bufsize, bool raw, + void *pampd, struct tmem_pool *pool, + struct tmem_oid *oid, uint32_t index) { - int ret; - unsigned int outlen = PAGE_SIZE; + int ret = 0; + unsigned long flags; + struct zcache_client *cli = pool->client; + + BUG_ON(preemptible()); + BUG_ON(pampd_is_remote(pampd)); + if (is_ephemeral(pool)) { + local_irq_save(flags); + if (raw) + zbud_copy_from_pampd(data, bufsize, pampd); + else + ret = zbud_decompress(virt_to_page(data), pampd); + zbud_free_and_delist((struct zbud_hdr *)pampd); + local_irq_restore(flags); + if (!is_local_client(cli)) + dec_and_check(&ramster_foreign_eph_pampd_count); + dec_and_check(&zcache_curr_eph_pampd_count); + } else { + if (is_local_client(cli)) + BUG(); + if (raw) + zv_copy_from_pampd(data, bufsize, pampd); + else + zv_decompress(virt_to_page(data), pampd); + zv_free(cli->xvpool, pampd); + if (!is_local_client(cli)) + dec_and_check(&ramster_foreign_pers_pampd_count); + dec_and_check(&zcache_curr_pers_pampd_count); + ret = 0; + } + return ret; +} - ret = zcache_comp_op(ZCACHE_COMPOP_DECOMPRESS, from_va, size, - to_va, &outlen); - BUG_ON(ret); - BUG_ON(outlen != PAGE_SIZE); +static bool zcache_pampd_is_remote(void *pampd) +{ + return pampd_is_remote(pampd); } /* - * Decompress from the kernel va to a pageframe + * free the pampd and remove it from any zcache lists + * pampd must no longer be pointed to from any tmem data structures! */ -void zcache_decompress_to_page(char *from_va, unsigned int size, - struct page *to_page) +static void zcache_pampd_free(void *pampd, struct tmem_pool *pool, + struct tmem_oid *oid, uint32_t index, bool acct) { - char *to_va = kmap_atomic(to_page); - zcache_decompress(from_va, size, to_va); - kunmap_atomic(to_va); + struct zcache_client *cli = pool->client; + bool eph = is_ephemeral(pool); + struct zv_hdr *zv; + + BUG_ON(preemptible()); + if (pampd_is_remote(pampd)) { + WARN_ON(acct == false); + if (oid == NULL) { + /* + * a NULL oid means to ignore this pampd free + * as the remote freeing will be handled elsewhere + */ + } else if (eph) { + /* FIXME remote flush optional but probably good idea */ + /* FIXME get these working properly again */ + dec_and_check(&zcache_curr_eph_pampd_count); + } else if (pampd_is_intransit(pampd)) { + /* did a pers remote get_and_free, so just free local */ + pampd = pampd_mask_intransit_and_remote(pampd); + goto local_pers; + } else { + struct flushlist_node *flnode = + ramster_flnode_alloc(pool); + + flnode->xh.client_id = pampd_remote_node(pampd); + flnode->xh.pool_id = pool->pool_id; + flnode->xh.oid = *oid; + flnode->xh.index = index; + flnode->rem_op.op = RAMSTER_REMOTIFY_FLUSH_PAGE; + spin_lock(&zcache_rem_op_list_lock); + list_add(&flnode->rem_op.list, &zcache_rem_op_list); + spin_unlock(&zcache_rem_op_list_lock); + dec_and_check(&zcache_curr_pers_pampd_count); + dec_and_check(&ramster_remote_pers_pages); + } + } else if (eph) { + zbud_free_and_delist((struct zbud_hdr *)pampd); + if (!is_local_client(pool->client)) + dec_and_check(&ramster_foreign_eph_pampd_count); + if (acct) + /* FIXME get these working properly again */ + dec_and_check(&zcache_curr_eph_pampd_count); + } else { +local_pers: + zv = (struct zv_hdr *)pampd; + if (!is_local_client(pool->client)) + dec_and_check(&ramster_foreign_pers_pampd_count); + zv_free(cli->xvpool, zv); + if (acct) + /* FIXME get these working properly again */ + dec_and_check(&zcache_curr_pers_pampd_count); + } +} + +static void zcache_pampd_free_obj(struct tmem_pool *pool, + struct tmem_obj *obj) +{ + struct flushlist_node *flnode; + + BUG_ON(preemptible()); + if (obj->extra == NULL) + return; + BUG_ON(!pampd_is_remote(obj->extra)); + flnode = ramster_flnode_alloc(pool); + flnode->xh.client_id = pampd_remote_node(obj->extra); + flnode->xh.pool_id = pool->pool_id; + flnode->xh.oid = obj->oid; + flnode->xh.index = FLUSH_ENTIRE_OBJECT; + flnode->rem_op.op = RAMSTER_REMOTIFY_FLUSH_OBJ; + spin_lock(&zcache_rem_op_list_lock); + list_add(&flnode->rem_op.list, &zcache_rem_op_list); + spin_unlock(&zcache_rem_op_list_lock); +} + +void zcache_pampd_new_obj(struct tmem_obj *obj) +{ + obj->extra = NULL; +} + +int zcache_pampd_replace_in_obj(void *new_pampd, struct tmem_obj *obj) +{ + int ret = -1; + + if (new_pampd != NULL) { + if (obj->extra == NULL) + obj->extra = new_pampd; + /* enforce that all remote pages in an object reside + * in the same node! */ + else if (pampd_remote_node(new_pampd) != + pampd_remote_node((void *)(obj->extra))) + BUG(); + ret = 0; + } + return ret; } /* - * fill the pageframe corresponding to the struct page with the data - * from the passed pampd + * Called by the message handler after a (still compressed) page has been + * fetched from the remote machine in response to an "is_remote" tmem_get + * or persistent tmem_localify. For a tmem_get, "extra" is the address of + * the page that is to be filled to successfully resolve the tmem_get; for + * a (persistent) tmem_localify, "extra" is NULL (as the data is placed only + * in the local zcache). "data" points to "size" bytes of (compressed) data + * passed in the message. In the case of a persistent remote get, if + * pre-allocation was successful (see zcache_repatriate_preload), the page + * is placed into both local zcache and at "extra". */ -static int zcache_pampd_get_data(char *data, size_t *sizep, bool raw, - void *pampd, struct tmem_pool *pool, - struct tmem_oid *oid, uint32_t index) +int zcache_localify(int pool_id, struct tmem_oid *oidp, + uint32_t index, char *data, size_t size, + void *extra) { - int ret; - bool eph = !is_persistent(pool); + int ret = -ENOENT; + unsigned long flags; + struct tmem_pool *pool; + bool ephemeral, delete = false; + size_t clen = PAGE_SIZE; + void *pampd, *saved_hb; + struct tmem_obj *obj; - BUG_ON(preemptible()); - BUG_ON(eph); /* fix later if shared pools get implemented */ - BUG_ON(pampd_is_remote(pampd)); - if (raw) - ret = zbud_copy_from_zbud(data, (struct zbudref *)pampd, - sizep, eph); - else { - ret = zbud_decompress((struct page *)(data), - (struct zbudref *)pampd, false, - zcache_decompress); - *sizep = PAGE_SIZE; + pool = zcache_get_pool_by_id(LOCAL_CLIENT, pool_id); + if (unlikely(pool == NULL)) + /* pool doesn't exist anymore */ + goto out; + ephemeral = is_ephemeral(pool); + local_irq_save(flags); /* FIXME: maybe only disable softirqs? */ + pampd = tmem_localify_get_pampd(pool, oidp, index, &obj, &saved_hb); + if (pampd == NULL) { + /* hmmm... must have been a flush while waiting */ +#ifdef RAMSTER_TESTING + pr_err("UNTESTED pampd==NULL in zcache_localify\n"); +#endif + if (ephemeral) + ramster_remote_eph_pages_unsucc_get++; + else + ramster_remote_pers_pages_unsucc_get++; + obj = NULL; + goto finish; + } else if (unlikely(!pampd_is_remote(pampd))) { + /* hmmm... must have been a dup put while waiting */ +#ifdef RAMSTER_TESTING + pr_err("UNTESTED dup while waiting in zcache_localify\n"); +#endif + if (ephemeral) + ramster_remote_eph_pages_unsucc_get++; + else + ramster_remote_pers_pages_unsucc_get++; + obj = NULL; + pampd = NULL; + ret = -EEXIST; + goto finish; + } else if (size == 0) { + /* no remote data, delete the local is_remote pampd */ + pampd = NULL; + if (ephemeral) + ramster_remote_eph_pages_unsucc_get++; + else + BUG(); + delete = true; + goto finish; } + if (!ephemeral && pampd_is_intransit(pampd)) { + /* localify to zcache */ + pampd = pampd_mask_intransit_and_remote(pampd); + zv_copy_to_pampd(pampd, data, size); + } else { + pampd = NULL; + obj = NULL; + } + if (extra != NULL) { + /* decompress direct-to-memory to complete remotify */ + ret = lzo1x_decompress_safe((char *)data, size, + (char *)extra, &clen); + BUG_ON(ret != LZO_E_OK); + BUG_ON(clen != PAGE_SIZE); + } + if (ephemeral) + ramster_remote_eph_pages_succ_get++; + else + ramster_remote_pers_pages_succ_get++; + ret = 0; +finish: + tmem_localify_finish(obj, index, pampd, saved_hb, delete); + zcache_put_pool(pool); + local_irq_restore(flags); +out: return ret; } /* - * fill the pageframe corresponding to the struct page with the data - * from the passed pampd + * Called on a remote persistent tmem_get to attempt to preallocate + * local storage for the data contained in the remote persistent page. + * If successfully preallocated, returns the pampd, marked as remote and + * in_transit. Else returns NULL. Note that the appropriate tmem data + * structure must be locked. */ -static int zcache_pampd_get_data_and_free(char *data, size_t *sizep, bool raw, - void *pampd, struct tmem_pool *pool, - struct tmem_oid *oid, uint32_t index) -{ - int ret; - bool eph = !is_persistent(pool); - struct page *page = NULL; - unsigned int zsize, zpages; +static void *zcache_pampd_repatriate_preload(void *pampd, + struct tmem_pool *pool, + struct tmem_oid *oid, + uint32_t index, + bool *intransit) +{ + int clen = pampd_remote_size(pampd); + void *ret_pampd = NULL; + unsigned long flags; - BUG_ON(preemptible()); - BUG_ON(pampd_is_remote(pampd)); - if (raw) - ret = zbud_copy_from_zbud(data, (struct zbudref *)pampd, - sizep, eph); - else { - ret = zbud_decompress((struct page *)(data), - (struct zbudref *)pampd, eph, - zcache_decompress); - *sizep = PAGE_SIZE; - } - page = zbud_free_and_delist((struct zbudref *)pampd, eph, - &zsize, &zpages); - if (eph) { - if (page) - zcache_eph_pageframes = - atomic_dec_return(&zcache_eph_pageframes_atomic); - zcache_eph_zpages = - atomic_sub_return(zpages, &zcache_eph_zpages_atomic); - zcache_eph_zbytes = - atomic_long_sub_return(zsize, &zcache_eph_zbytes_atomic); - } else { - if (page) - zcache_pers_pageframes = - atomic_dec_return(&zcache_pers_pageframes_atomic); - zcache_pers_zpages = - atomic_sub_return(zpages, &zcache_pers_zpages_atomic); - zcache_pers_zbytes = - atomic_long_sub_return(zsize, &zcache_pers_zbytes_atomic); - } - if (!is_local_client(pool->client)) - ramster_count_foreign_pages(eph, -1); - if (page) - zcache_free_page(page); - return ret; + if (!pampd_is_remote(pampd)) + BUG(); + if (is_ephemeral(pool)) + BUG(); + if (pampd_is_intransit(pampd)) { + /* + * to avoid multiple allocations (and maybe a memory leak) + * don't preallocate if already in the process of being + * repatriated + */ + *intransit = true; + goto out; + } + *intransit = false; + local_irq_save(flags); + ret_pampd = (void *)zv_alloc(pool, oid, index, clen); + if (ret_pampd != NULL) { + /* + * a pampd is marked intransit if it is remote and space has + * been allocated for it locally (note, only happens for + * persistent pages, in which case the remote copy is freed) + */ + ret_pampd = pampd_mark_intransit(ret_pampd); + dec_and_check(&ramster_remote_pers_pages); + } else + ramster_pers_pages_remote_nomem++; + local_irq_restore(flags); +out: + return ret_pampd; } /* - * free the pampd and remove it from any zcache lists - * pampd must no longer be pointed to from any tmem data structures! + * Called on a remote tmem_get to invoke a message to fetch the page. + * Might sleep so no tmem locks can be held. "extra" is passed + * all the way through the round-trip messaging to zcache_localify. */ -static void zcache_pampd_free(void *pampd, struct tmem_pool *pool, - struct tmem_oid *oid, uint32_t index, bool acct) +static int zcache_pampd_repatriate(void *fake_pampd, void *real_pampd, + struct tmem_pool *pool, + struct tmem_oid *oid, uint32_t index, + bool free, void *extra) { - struct page *page = NULL; - unsigned int zsize, zpages; + struct tmem_xhandle xh; + int ret; - BUG_ON(preemptible()); - if (pampd_is_remote(pampd)) { - BUG_ON(!ramster_enabled); - pampd = ramster_pampd_free(pampd, pool, oid, index, acct); - if (pampd == NULL) - return; - } - if (is_ephemeral(pool)) { - page = zbud_free_and_delist((struct zbudref *)pampd, - true, &zsize, &zpages); - if (page) - zcache_eph_pageframes = - atomic_dec_return(&zcache_eph_pageframes_atomic); - zcache_eph_zpages = - atomic_sub_return(zpages, &zcache_eph_zpages_atomic); - zcache_eph_zbytes = - atomic_long_sub_return(zsize, &zcache_eph_zbytes_atomic); - /* FIXME CONFIG_RAMSTER... check acct parameter? */ - } else { - page = zbud_free_and_delist((struct zbudref *)pampd, - false, &zsize, &zpages); - if (page) - zcache_pers_pageframes = - atomic_dec_return(&zcache_pers_pageframes_atomic); - zcache_pers_zpages = - atomic_sub_return(zpages, &zcache_pers_zpages_atomic); - zcache_pers_zbytes = - atomic_long_sub_return(zsize, &zcache_pers_zbytes_atomic); - } - if (!is_local_client(pool->client)) - ramster_count_foreign_pages(is_ephemeral(pool), -1); - if (page) - zcache_free_page(page); + if (pampd_is_intransit(real_pampd)) + /* have local space pre-reserved, so free remote copy */ + free = true; + xh = tmem_xhandle_fill(LOCAL_CLIENT, pool, oid, index); + /* unreliable request/response for now */ + ret = ramster_remote_async_get(&xh, free, + pampd_remote_node(fake_pampd), + pampd_remote_size(fake_pampd), + pampd_remote_cksum(fake_pampd), + extra); +#ifdef RAMSTER_TESTING + if (ret != 0 && ret != -ENOENT) + pr_err("TESTING zcache_pampd_repatriate returns, ret=%d\n", + ret); +#endif + return ret; } static struct tmem_pamops zcache_pamops = { - .create_finish = zcache_pampd_create_finish, + .create = zcache_pampd_create, .get_data = zcache_pampd_get_data, - .get_data_and_free = zcache_pampd_get_data_and_free, .free = zcache_pampd_free, + .get_data_and_free = zcache_pampd_get_data_and_free, + .free_obj = zcache_pampd_free_obj, + .is_remote = zcache_pampd_is_remote, + .repatriate_preload = zcache_pampd_repatriate_preload, + .repatriate = zcache_pampd_repatriate, + .new_obj = zcache_pampd_new_obj, + .replace_in_obj = zcache_pampd_replace_in_obj, }; /* * zcache compression/decompression and related per-cpu stuff */ +#define LZO_WORKMEM_BYTES LZO1X_1_MEM_COMPRESS +#define LZO_DSTMEM_PAGE_ORDER 1 +static DEFINE_PER_CPU(unsigned char *, zcache_workmem); static DEFINE_PER_CPU(unsigned char *, zcache_dstmem); -#define ZCACHE_DSTMEM_ORDER 1 -static void zcache_compress(struct page *from, void **out_va, unsigned *out_len) +static int zcache_compress(struct page *from, void **out_va, size_t *out_len) { - int ret; + int ret = 0; unsigned char *dmem = __get_cpu_var(zcache_dstmem); + unsigned char *wmem = __get_cpu_var(zcache_workmem); char *from_va; BUG_ON(!irqs_disabled()); - /* no buffer or no compressor so can't compress */ - BUG_ON(dmem == NULL); - *out_len = PAGE_SIZE << ZCACHE_DSTMEM_ORDER; + if (unlikely(dmem == NULL || wmem == NULL)) + goto out; /* no buffer, so can't compress */ from_va = kmap_atomic(from); mb(); - ret = zcache_comp_op(ZCACHE_COMPOP_COMPRESS, from_va, PAGE_SIZE, dmem, - out_len); - BUG_ON(ret); + ret = lzo1x_1_compress(from_va, PAGE_SIZE, dmem, out_len, wmem); + BUG_ON(ret != LZO_E_OK); *out_va = dmem; kunmap_atomic(from_va); + ret = 1; +out: + return ret; } -static int zcache_comp_cpu_up(int cpu) -{ - struct crypto_comp *tfm; - - tfm = crypto_alloc_comp(zcache_comp_name, 0, 0); - if (IS_ERR(tfm)) - return NOTIFY_BAD; - *per_cpu_ptr(zcache_comp_pcpu_tfms, cpu) = tfm; - return NOTIFY_OK; -} - -static void zcache_comp_cpu_down(int cpu) -{ - struct crypto_comp *tfm; - - tfm = *per_cpu_ptr(zcache_comp_pcpu_tfms, cpu); - crypto_free_comp(tfm); - *per_cpu_ptr(zcache_comp_pcpu_tfms, cpu) = NULL; -} static int zcache_cpu_notifier(struct notifier_block *nb, unsigned long action, void *pcpu) { - int ret, i, cpu = (long)pcpu; + int cpu = (long)pcpu; struct zcache_preload *kp; switch (action) { case CPU_UP_PREPARE: - ret = zcache_comp_cpu_up(cpu); - if (ret != NOTIFY_OK) { - pr_err("%s: can't allocate compressor xform\n", - namestr); - return ret; - } per_cpu(zcache_dstmem, cpu) = (void *)__get_free_pages( - GFP_KERNEL | __GFP_REPEAT, ZCACHE_DSTMEM_ORDER); - if (ramster_enabled) - ramster_cpu_up(cpu); + GFP_KERNEL | __GFP_REPEAT, + LZO_DSTMEM_PAGE_ORDER), + per_cpu(zcache_workmem, cpu) = + kzalloc(LZO1X_MEM_COMPRESS, + GFP_KERNEL | __GFP_REPEAT); + per_cpu(zcache_remoteputmem, cpu) = + kzalloc(PAGE_SIZE, GFP_KERNEL | __GFP_REPEAT); break; case CPU_DEAD: case CPU_UP_CANCELED: - zcache_comp_cpu_down(cpu); + kfree(per_cpu(zcache_remoteputmem, cpu)); + per_cpu(zcache_remoteputmem, cpu) = NULL; free_pages((unsigned long)per_cpu(zcache_dstmem, cpu), - ZCACHE_DSTMEM_ORDER); + LZO_DSTMEM_PAGE_ORDER); per_cpu(zcache_dstmem, cpu) = NULL; + kfree(per_cpu(zcache_workmem, cpu)); + per_cpu(zcache_workmem, cpu) = NULL; kp = &per_cpu(zcache_preloads, cpu); - for (i = 0; i < ARRAY_SIZE(kp->objnodes); i++) { - if (kp->objnodes[i]) - kmem_cache_free(zcache_objnode_cache, - kp->objnodes[i]); + while (kp->nr) { + kmem_cache_free(zcache_objnode_cache, + kp->objnodes[kp->nr - 1]); + kp->objnodes[kp->nr - 1] = NULL; + kp->nr--; } if (kp->obj) { kmem_cache_free(zcache_obj_cache, kp->obj); kp->obj = NULL; } - if (ramster_enabled) - ramster_cpu_down(cpu); + if (kp->flnode) { + kmem_cache_free(ramster_flnode_cache, kp->flnode); + kp->flnode = NULL; + } + if (kp->page) { + free_page((unsigned long)kp->page); + kp->page = NULL; + } break; default: break; @@ -942,104 +2271,314 @@ static struct notifier_block zcache_cpu_notifier_block = { .notifier_call = zcache_cpu_notifier }; -/* - * The following code interacts with the zbud eviction and zbud - * zombify code to access LRU pages - */ +#ifdef CONFIG_SYSFS +#define ZCACHE_SYSFS_RO(_name) \ + static ssize_t zcache_##_name##_show(struct kobject *kobj, \ + struct kobj_attribute *attr, char *buf) \ + { \ + return sprintf(buf, "%lu\n", zcache_##_name); \ + } \ + static struct kobj_attribute zcache_##_name##_attr = { \ + .attr = { .name = __stringify(_name), .mode = 0444 }, \ + .show = zcache_##_name##_show, \ + } -static struct page *zcache_evict_eph_pageframe(void) -{ - struct page *page; - unsigned int zsize = 0, zpages = 0; +#define ZCACHE_SYSFS_RO_ATOMIC(_name) \ + static ssize_t zcache_##_name##_show(struct kobject *kobj, \ + struct kobj_attribute *attr, char *buf) \ + { \ + return sprintf(buf, "%d\n", atomic_read(&zcache_##_name)); \ + } \ + static struct kobj_attribute zcache_##_name##_attr = { \ + .attr = { .name = __stringify(_name), .mode = 0444 }, \ + .show = zcache_##_name##_show, \ + } - page = zbud_evict_pageframe_lru(&zsize, &zpages); - if (page == NULL) - goto out; - zcache_eph_zbytes = atomic_long_sub_return(zsize, - &zcache_eph_zbytes_atomic); - zcache_eph_zpages = atomic_sub_return(zpages, - &zcache_eph_zpages_atomic); - zcache_evicted_eph_zpages++; - zcache_eph_pageframes = - atomic_dec_return(&zcache_eph_pageframes_atomic); - zcache_evicted_eph_pageframes++; -out: - return page; +#define ZCACHE_SYSFS_RO_CUSTOM(_name, _func) \ + static ssize_t zcache_##_name##_show(struct kobject *kobj, \ + struct kobj_attribute *attr, char *buf) \ + { \ + return _func(buf); \ + } \ + static struct kobj_attribute zcache_##_name##_attr = { \ + .attr = { .name = __stringify(_name), .mode = 0444 }, \ + .show = zcache_##_name##_show, \ + } + +ZCACHE_SYSFS_RO(curr_obj_count_max); +ZCACHE_SYSFS_RO(curr_objnode_count_max); +ZCACHE_SYSFS_RO(flush_total); +ZCACHE_SYSFS_RO(flush_found); +ZCACHE_SYSFS_RO(flobj_total); +ZCACHE_SYSFS_RO(flobj_found); +ZCACHE_SYSFS_RO(failed_eph_puts); +ZCACHE_SYSFS_RO(nonactive_puts); +ZCACHE_SYSFS_RO(failed_pers_puts); +ZCACHE_SYSFS_RO(zbud_curr_zbytes); +ZCACHE_SYSFS_RO(zbud_cumul_zpages); +ZCACHE_SYSFS_RO(zbud_cumul_zbytes); +ZCACHE_SYSFS_RO(zbud_buddied_count); +ZCACHE_SYSFS_RO(evicted_raw_pages); +ZCACHE_SYSFS_RO(evicted_unbuddied_pages); +ZCACHE_SYSFS_RO(evicted_buddied_pages); +ZCACHE_SYSFS_RO(failed_get_free_pages); +ZCACHE_SYSFS_RO(failed_alloc); +ZCACHE_SYSFS_RO(put_to_flush); +ZCACHE_SYSFS_RO(compress_poor); +ZCACHE_SYSFS_RO(mean_compress_poor); +ZCACHE_SYSFS_RO(policy_percent_exceeded); +ZCACHE_SYSFS_RO_ATOMIC(zbud_curr_raw_pages); +ZCACHE_SYSFS_RO_ATOMIC(zbud_curr_zpages); +ZCACHE_SYSFS_RO_ATOMIC(curr_obj_count); +ZCACHE_SYSFS_RO_ATOMIC(curr_objnode_count); +ZCACHE_SYSFS_RO_CUSTOM(zbud_unbuddied_list_counts, + zbud_show_unbuddied_list_counts); +ZCACHE_SYSFS_RO_CUSTOM(zbud_cumul_chunk_counts, + zbud_show_cumul_chunk_counts); +ZCACHE_SYSFS_RO_CUSTOM(zv_curr_dist_counts, + zv_curr_dist_counts_show); +ZCACHE_SYSFS_RO_CUSTOM(zv_cumul_dist_counts, + zv_cumul_dist_counts_show); + +static struct attribute *zcache_attrs[] = { + &zcache_curr_obj_count_attr.attr, + &zcache_curr_obj_count_max_attr.attr, + &zcache_curr_objnode_count_attr.attr, + &zcache_curr_objnode_count_max_attr.attr, + &zcache_flush_total_attr.attr, + &zcache_flobj_total_attr.attr, + &zcache_flush_found_attr.attr, + &zcache_flobj_found_attr.attr, + &zcache_failed_eph_puts_attr.attr, + &zcache_nonactive_puts_attr.attr, + &zcache_failed_pers_puts_attr.attr, + &zcache_policy_percent_exceeded_attr.attr, + &zcache_compress_poor_attr.attr, + &zcache_mean_compress_poor_attr.attr, + &zcache_zbud_curr_raw_pages_attr.attr, + &zcache_zbud_curr_zpages_attr.attr, + &zcache_zbud_curr_zbytes_attr.attr, + &zcache_zbud_cumul_zpages_attr.attr, + &zcache_zbud_cumul_zbytes_attr.attr, + &zcache_zbud_buddied_count_attr.attr, + &zcache_evicted_raw_pages_attr.attr, + &zcache_evicted_unbuddied_pages_attr.attr, + &zcache_evicted_buddied_pages_attr.attr, + &zcache_failed_get_free_pages_attr.attr, + &zcache_failed_alloc_attr.attr, + &zcache_put_to_flush_attr.attr, + &zcache_zbud_unbuddied_list_counts_attr.attr, + &zcache_zbud_cumul_chunk_counts_attr.attr, + &zcache_zv_curr_dist_counts_attr.attr, + &zcache_zv_cumul_dist_counts_attr.attr, + &zcache_zv_max_zsize_attr.attr, + &zcache_zv_max_mean_zsize_attr.attr, + &zcache_zv_page_count_policy_percent_attr.attr, + NULL, +}; + +static struct attribute_group zcache_attr_group = { + .attrs = zcache_attrs, + .name = "zcache", +}; + +#define RAMSTER_SYSFS_RO(_name) \ + static ssize_t ramster_##_name##_show(struct kobject *kobj, \ + struct kobj_attribute *attr, char *buf) \ + { \ + return sprintf(buf, "%lu\n", ramster_##_name); \ + } \ + static struct kobj_attribute ramster_##_name##_attr = { \ + .attr = { .name = __stringify(_name), .mode = 0444 }, \ + .show = ramster_##_name##_show, \ + } + +#define RAMSTER_SYSFS_RW(_name) \ + static ssize_t ramster_##_name##_show(struct kobject *kobj, \ + struct kobj_attribute *attr, char *buf) \ + { \ + return sprintf(buf, "%lu\n", ramster_##_name); \ + } \ + static ssize_t ramster_##_name##_store(struct kobject *kobj, \ + struct kobj_attribute *attr, const char *buf, size_t count) \ + { \ + int err; \ + unsigned long enable; \ + err = kstrtoul(buf, 10, &enable); \ + if (err) \ + return -EINVAL; \ + ramster_##_name = enable; \ + return count; \ + } \ + static struct kobj_attribute ramster_##_name##_attr = { \ + .attr = { .name = __stringify(_name), .mode = 0644 }, \ + .show = ramster_##_name##_show, \ + .store = ramster_##_name##_store, \ + } + +#define RAMSTER_SYSFS_RO_ATOMIC(_name) \ + static ssize_t ramster_##_name##_show(struct kobject *kobj, \ + struct kobj_attribute *attr, char *buf) \ + { \ + return sprintf(buf, "%d\n", atomic_read(&ramster_##_name)); \ + } \ + static struct kobj_attribute ramster_##_name##_attr = { \ + .attr = { .name = __stringify(_name), .mode = 0444 }, \ + .show = ramster_##_name##_show, \ + } + +RAMSTER_SYSFS_RO(interface_revision); +RAMSTER_SYSFS_RO_ATOMIC(remote_pers_pages); +RAMSTER_SYSFS_RW(pers_remotify_enable); +RAMSTER_SYSFS_RW(eph_remotify_enable); +RAMSTER_SYSFS_RO(eph_pages_remoted); +RAMSTER_SYSFS_RO(eph_pages_remote_failed); +RAMSTER_SYSFS_RO(pers_pages_remoted); +RAMSTER_SYSFS_RO(pers_pages_remote_failed); +RAMSTER_SYSFS_RO(pers_pages_remote_nomem); +RAMSTER_SYSFS_RO(remote_pages_flushed); +RAMSTER_SYSFS_RO(remote_page_flushes_failed); +RAMSTER_SYSFS_RO(remote_objects_flushed); +RAMSTER_SYSFS_RO(remote_object_flushes_failed); +RAMSTER_SYSFS_RO(remote_eph_pages_succ_get); +RAMSTER_SYSFS_RO(remote_eph_pages_unsucc_get); +RAMSTER_SYSFS_RO(remote_pers_pages_succ_get); +RAMSTER_SYSFS_RO(remote_pers_pages_unsucc_get); +RAMSTER_SYSFS_RO_ATOMIC(foreign_eph_pampd_count); +RAMSTER_SYSFS_RO(foreign_eph_pampd_count_max); +RAMSTER_SYSFS_RO_ATOMIC(foreign_pers_pampd_count); +RAMSTER_SYSFS_RO(foreign_pers_pampd_count_max); +RAMSTER_SYSFS_RO_ATOMIC(curr_flnode_count); +RAMSTER_SYSFS_RO(curr_flnode_count_max); + +#define MANUAL_NODES 8 +static bool ramster_nodes_manual_up[MANUAL_NODES]; +static ssize_t ramster_manual_node_up_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) +{ + int i; + char *p = buf; + for (i = 0; i < MANUAL_NODES; i++) + if (ramster_nodes_manual_up[i]) + p += sprintf(p, "%d ", i); + p += sprintf(p, "\n"); + return p - buf; } -#ifdef FRONTSWAP_HAS_UNUSE -static void unswiz(struct tmem_oid oid, u32 index, - unsigned *type, pgoff_t *offset); +static ssize_t ramster_manual_node_up_store(struct kobject *kobj, + struct kobj_attribute *attr, const char *buf, size_t count) +{ + int err; + unsigned long node_num; -/* - * Choose an LRU persistent pageframe and attempt to "unuse" it by - * calling frontswap_unuse on both zpages. - * - * This is work-in-progress. - */ + err = kstrtoul(buf, 10, &node_num); + if (err) { + pr_err("ramster: bad strtoul?\n"); + return -EINVAL; + } + if (node_num >= MANUAL_NODES) { + pr_err("ramster: bad node_num=%lu?\n", node_num); + return -EINVAL; + } + if (ramster_nodes_manual_up[node_num]) { + pr_err("ramster: node %d already up, ignoring\n", + (int)node_num); + } else { + ramster_nodes_manual_up[node_num] = true; + r2net_hb_node_up_manual((int)node_num); + } + return count; +} + +static struct kobj_attribute ramster_manual_node_up_attr = { + .attr = { .name = "manual_node_up", .mode = 0644 }, + .show = ramster_manual_node_up_show, + .store = ramster_manual_node_up_store, +}; -static int zcache_frontswap_unuse(void) +static ssize_t ramster_remote_target_nodenum_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) { - struct tmem_handle th[2]; - int ret = -ENOMEM; - int nzbuds, unuse_ret; - unsigned type; - struct page *newpage1 = NULL, *newpage2 = NULL; - struct page *evictpage1 = NULL, *evictpage2 = NULL; - pgoff_t offset; - - newpage1 = alloc_page(ZCACHE_GFP_MASK); - newpage2 = alloc_page(ZCACHE_GFP_MASK); - if (newpage1 == NULL) - evictpage1 = zcache_evict_eph_pageframe(); - if (newpage2 == NULL) - evictpage2 = zcache_evict_eph_pageframe(); - if (evictpage1 == NULL || evictpage2 == NULL) - goto free_and_out; - /* ok, we have two pages pre-allocated */ - nzbuds = zbud_make_zombie_lru(&th[0], NULL, NULL, false); - if (nzbuds == 0) { - ret = -ENOENT; - goto free_and_out; - } - unswiz(th[0].oid, th[0].index, &type, &offset); - unuse_ret = frontswap_unuse(type, offset, - newpage1 != NULL ? newpage1 : evictpage1, - ZCACHE_GFP_MASK); - if (unuse_ret != 0) - goto free_and_out; - else if (evictpage1 != NULL) - zcache_unacct_page(); - newpage1 = NULL; - evictpage1 = NULL; - if (nzbuds == 2) { - unswiz(th[1].oid, th[1].index, &type, &offset); - unuse_ret = frontswap_unuse(type, offset, - newpage2 != NULL ? newpage2 : evictpage2, - ZCACHE_GFP_MASK); - if (unuse_ret != 0) { - goto free_and_out; - } else if (evictpage2 != NULL) { - zcache_unacct_page(); - } + if (ramster_remote_target_nodenum == -1UL) + return sprintf(buf, "unset\n"); + else + return sprintf(buf, "%d\n", ramster_remote_target_nodenum); +} + +static ssize_t ramster_remote_target_nodenum_store(struct kobject *kobj, + struct kobj_attribute *attr, const char *buf, size_t count) +{ + int err; + unsigned long node_num; + + err = kstrtoul(buf, 10, &node_num); + if (err) { + pr_err("ramster: bad strtoul?\n"); + return -EINVAL; + } else if (node_num == -1UL) { + pr_err("ramster: disabling all remotification, " + "data may still reside on remote nodes however\n"); + return -EINVAL; + } else if (node_num >= MANUAL_NODES) { + pr_err("ramster: bad node_num=%lu?\n", node_num); + return -EINVAL; + } else if (!ramster_nodes_manual_up[node_num]) { + pr_err("ramster: node %d not up, ignoring setting " + "of remotification target\n", (int)node_num); + } else if (r2net_remote_target_node_set((int)node_num) >= 0) { + pr_info("ramster: node %d set as remotification target\n", + (int)node_num); + ramster_remote_target_nodenum = (int)node_num; + } else { + pr_err("ramster: bad num to node node_num=%d?\n", + (int)node_num); + return -EINVAL; } - ret = 0; - goto out; - -free_and_out: - if (newpage1 != NULL) - __free_page(newpage1); - if (newpage2 != NULL) - __free_page(newpage2); - if (evictpage1 != NULL) - zcache_free_page(evictpage1); - if (evictpage2 != NULL) - zcache_free_page(evictpage2); -out: - return ret; + return count; } -#endif +static struct kobj_attribute ramster_remote_target_nodenum_attr = { + .attr = { .name = "remote_target_nodenum", .mode = 0644 }, + .show = ramster_remote_target_nodenum_show, + .store = ramster_remote_target_nodenum_store, +}; + + +static struct attribute *ramster_attrs[] = { + &ramster_interface_revision_attr.attr, + &ramster_pers_remotify_enable_attr.attr, + &ramster_eph_remotify_enable_attr.attr, + &ramster_remote_pers_pages_attr.attr, + &ramster_eph_pages_remoted_attr.attr, + &ramster_eph_pages_remote_failed_attr.attr, + &ramster_pers_pages_remoted_attr.attr, + &ramster_pers_pages_remote_failed_attr.attr, + &ramster_pers_pages_remote_nomem_attr.attr, + &ramster_remote_pages_flushed_attr.attr, + &ramster_remote_page_flushes_failed_attr.attr, + &ramster_remote_objects_flushed_attr.attr, + &ramster_remote_object_flushes_failed_attr.attr, + &ramster_remote_eph_pages_succ_get_attr.attr, + &ramster_remote_eph_pages_unsucc_get_attr.attr, + &ramster_remote_pers_pages_succ_get_attr.attr, + &ramster_remote_pers_pages_unsucc_get_attr.attr, + &ramster_foreign_eph_pampd_count_attr.attr, + &ramster_foreign_eph_pampd_count_max_attr.attr, + &ramster_foreign_pers_pampd_count_attr.attr, + &ramster_foreign_pers_pampd_count_max_attr.attr, + &ramster_curr_flnode_count_attr.attr, + &ramster_curr_flnode_count_max_attr.attr, + &ramster_manual_node_up_attr.attr, + &ramster_remote_target_nodenum_attr.attr, + NULL, +}; + +static struct attribute_group ramster_attr_group = { + .attrs = ramster_attrs, + .name = "ramster", +}; + +#endif /* CONFIG_SYSFS */ /* * When zcache is disabled ("frozen"), pools can be created and destroyed, * but all puts (and thus all other operations that require memory allocation) @@ -1050,74 +2589,23 @@ static int zcache_frontswap_unuse(void) static bool zcache_freeze; /* - * This zcache shrinker interface reduces the number of ephemeral pageframes - * used by zcache to approximately the same as the total number of LRU_FILE - * pageframes in use. + * zcache shrinker interface (only useful for ephemeral pages, so zbud only) */ static int shrink_zcache_memory(struct shrinker *shrink, struct shrink_control *sc) { - static bool in_progress; int ret = -1; int nr = sc->nr_to_scan; - int nr_evict = 0; - int nr_unuse = 0; - struct page *page; -#ifdef FRONTSWAP_HAS_UNUSE - int unuse_ret; -#endif + gfp_t gfp_mask = sc->gfp_mask; - if (nr <= 0) - goto skip_evict; - - /* don't allow more than one eviction thread at a time */ - if (in_progress) - goto skip_evict; - - in_progress = true; - - /* we are going to ignore nr, and target a different value */ - zcache_last_active_file_pageframes = - global_page_state(NR_LRU_BASE + LRU_ACTIVE_FILE); - zcache_last_inactive_file_pageframes = - global_page_state(NR_LRU_BASE + LRU_INACTIVE_FILE); - nr_evict = zcache_eph_pageframes - zcache_last_active_file_pageframes + - zcache_last_inactive_file_pageframes; - while (nr_evict-- > 0) { - page = zcache_evict_eph_pageframe(); - if (page == NULL) - break; - zcache_free_page(page); - } - - zcache_last_active_anon_pageframes = - global_page_state(NR_LRU_BASE + LRU_ACTIVE_ANON); - zcache_last_inactive_anon_pageframes = - global_page_state(NR_LRU_BASE + LRU_INACTIVE_ANON); - nr_unuse = zcache_pers_pageframes - zcache_last_active_anon_pageframes + - zcache_last_inactive_anon_pageframes; -#ifdef FRONTSWAP_HAS_UNUSE - /* rate limit for testing */ - if (nr_unuse > 32) - nr_unuse = 32; - while (nr_unuse-- > 0) { - unuse_ret = zcache_frontswap_unuse(); - if (unuse_ret == -ENOMEM) - break; + if (nr >= 0) { + if (!(gfp_mask & __GFP_FS)) + /* does this case really need to be skipped? */ + goto out; + zbud_evict_pages(nr); } -#endif - in_progress = false; - -skip_evict: - /* resample: has changed, but maybe not all the way yet */ - zcache_last_active_file_pageframes = - global_page_state(NR_LRU_BASE + LRU_ACTIVE_FILE); - zcache_last_inactive_file_pageframes = - global_page_state(NR_LRU_BASE + LRU_INACTIVE_FILE); - ret = zcache_eph_pageframes - zcache_last_active_file_pageframes + - zcache_last_inactive_file_pageframes; - if (ret < 0) - ret = 0; + ret = (int)atomic_read(&zcache_zbud_curr_raw_pages); +out: return ret; } @@ -1130,46 +2618,30 @@ static struct shrinker zcache_shrinker = { * zcache shims between cleancache/frontswap ops and tmem */ -/* FIXME rename these core routines to zcache_tmemput etc? */ -int zcache_put_page(int cli_id, int pool_id, struct tmem_oid *oidp, - uint32_t index, void *page, - unsigned int size, bool raw, int ephemeral) +int zcache_put(int cli_id, int pool_id, struct tmem_oid *oidp, + uint32_t index, char *data, size_t size, + bool raw, int ephemeral) { struct tmem_pool *pool; - struct tmem_handle th; int ret = -1; - void *pampd = NULL; BUG_ON(!irqs_disabled()); pool = zcache_get_pool_by_id(cli_id, pool_id); if (unlikely(pool == NULL)) goto out; - if (!zcache_freeze) { - ret = 0; - th.client_id = cli_id; - th.pool_id = pool_id; - th.oid = *oidp; - th.index = index; - pampd = zcache_pampd_create((char *)page, size, raw, - ephemeral, &th); - if (pampd == NULL) { - ret = -ENOMEM; - if (ephemeral) + if (!zcache_freeze && zcache_do_preload(pool) == 0) { + /* preload does preempt_disable on success */ + ret = tmem_put(pool, oidp, index, data, size, raw, ephemeral); + if (ret < 0) { + if (is_ephemeral(pool)) zcache_failed_eph_puts++; else zcache_failed_pers_puts++; - } else { - if (ramster_enabled) - ramster_do_preload_flnode(pool); - ret = tmem_put(pool, oidp, index, 0, pampd); - if (ret < 0) - BUG(); } zcache_put_pool(pool); + preempt_enable_no_resched(); } else { zcache_put_to_flush++; - if (ramster_enabled) - ramster_do_preload_flnode(pool); if (atomic_read(&pool->obj_count) > 0) /* the put fails whether the flush succeeds or not */ (void)tmem_flush_page(pool, oidp, index); @@ -1179,9 +2651,9 @@ int zcache_put_page(int cli_id, int pool_id, struct tmem_oid *oidp, return ret; } -int zcache_get_page(int cli_id, int pool_id, struct tmem_oid *oidp, - uint32_t index, void *page, - size_t *sizep, bool raw, int get_and_free) +int zcache_get(int cli_id, int pool_id, struct tmem_oid *oidp, + uint32_t index, char *data, size_t *sizep, + bool raw, int get_and_free) { struct tmem_pool *pool; int ret = -1; @@ -1195,21 +2667,22 @@ int zcache_get_page(int cli_id, int pool_id, struct tmem_oid *oidp, eph = is_ephemeral(pool); if (likely(pool != NULL)) { if (atomic_read(&pool->obj_count) > 0) - ret = tmem_get(pool, oidp, index, (char *)(page), - sizep, raw, get_and_free); + ret = tmem_get(pool, oidp, index, data, sizep, + raw, get_and_free); zcache_put_pool(pool); } - WARN_ONCE((!is_ephemeral(pool) && (ret != 0)), - "zcache_get fails on persistent pool, " - "bad things are very likely to happen soon\n"); + WARN_ONCE((!eph && (ret != 0)), "zcache_get fails on persistent pool, " + "bad things are very likely to happen soon\n"); #ifdef RAMSTER_TESTING if (ret != 0 && ret != -1 && !(ret == -EINVAL && is_ephemeral(pool))) pr_err("TESTING zcache_get tmem_get returns ret=%d\n", ret); #endif + if (ret == -EAGAIN) + BUG(); /* FIXME... don't need this anymore??? let's ensure */ return ret; } -int zcache_flush_page(int cli_id, int pool_id, +int zcache_flush(int cli_id, int pool_id, struct tmem_oid *oidp, uint32_t index) { struct tmem_pool *pool; @@ -1219,8 +2692,7 @@ int zcache_flush_page(int cli_id, int pool_id, local_irq_save(flags); zcache_flush_total++; pool = zcache_get_pool_by_id(cli_id, pool_id); - if (ramster_enabled) - ramster_do_preload_flnode(pool); + ramster_do_preload_flnode_only(pool); if (likely(pool != NULL)) { if (atomic_read(&pool->obj_count) > 0) ret = tmem_flush_page(pool, oidp, index); @@ -1232,8 +2704,7 @@ int zcache_flush_page(int cli_id, int pool_id, return ret; } -int zcache_flush_object(int cli_id, int pool_id, - struct tmem_oid *oidp) +int zcache_flush_object(int cli_id, int pool_id, struct tmem_oid *oidp) { struct tmem_pool *pool; int ret = -1; @@ -1242,8 +2713,7 @@ int zcache_flush_object(int cli_id, int pool_id, local_irq_save(flags); zcache_flobj_total++; pool = zcache_get_pool_by_id(cli_id, pool_id); - if (ramster_enabled) - ramster_do_preload_flnode(pool); + ramster_do_preload_flnode_only(pool); if (likely(pool != NULL)) { if (atomic_read(&pool->obj_count) > 0) ret = tmem_flush_object(pool, oidp); @@ -1255,7 +2725,7 @@ int zcache_flush_object(int cli_id, int pool_id, return ret; } -static int zcache_client_destroy_pool(int cli_id, int pool_id) +int zcache_client_destroy_pool(int cli_id, int pool_id) { struct tmem_pool *pool = NULL; struct zcache_client *cli = NULL; @@ -1282,15 +2752,16 @@ static int zcache_client_destroy_pool(int cli_id, int pool_id) ret = tmem_destroy_pool(pool); local_bh_enable(); kfree(pool); - if (cli_id == LOCAL_CLIENT) - pr_info("%s: destroyed local pool id=%d\n", namestr, pool_id); - else - pr_info("%s: destroyed pool id=%d, client=%d\n", - namestr, pool_id, cli_id); + pr_info("ramster: destroyed pool id=%d cli_id=%d\n", pool_id, cli_id); out: return ret; } +static int zcache_destroy_pool(int pool_id) +{ + return zcache_client_destroy_pool(LOCAL_CLIENT, pool_id); +} + int zcache_new_pool(uint16_t cli_id, uint32_t flags) { int poolid = -1; @@ -1306,7 +2777,7 @@ int zcache_new_pool(uint16_t cli_id, uint32_t flags) atomic_inc(&cli->refcount); pool = kmalloc(sizeof(struct tmem_pool), GFP_ATOMIC); if (pool == NULL) { - pr_info("%s: pool creation failed: out of memory\n", namestr); + pr_info("ramster: pool creation failed: out of memory\n"); goto out; } @@ -1314,7 +2785,7 @@ int zcache_new_pool(uint16_t cli_id, uint32_t flags) if (cli->tmem_pools[poolid] == NULL) break; if (poolid >= MAX_POOLS_PER_CLIENT) { - pr_info("%s: pool creation failed: max exceeded\n", namestr); + pr_info("ramster: pool creation failed: max exceeded\n"); kfree(pool); poolid = -1; goto out; @@ -1325,11 +2796,11 @@ int zcache_new_pool(uint16_t cli_id, uint32_t flags) tmem_new_pool(pool, flags); cli->tmem_pools[poolid] = pool; if (cli_id == LOCAL_CLIENT) - pr_info("%s: created %s local tmem pool, id=%d\n", namestr, + pr_info("ramster: created %s tmem pool, id=%d, local client\n", flags & TMEM_POOL_PERSIST ? "persistent" : "ephemeral", poolid); else - pr_info("%s: created %s tmem pool, id=%d, client=%d\n", namestr, + pr_info("ramster: created %s tmem pool, id=%d, client=%d\n", flags & TMEM_POOL_PERSIST ? "persistent" : "ephemeral", poolid, cli_id); out: @@ -1343,37 +2814,30 @@ static int zcache_local_new_pool(uint32_t flags) return zcache_new_pool(LOCAL_CLIENT, flags); } -int zcache_autocreate_pool(unsigned int cli_id, unsigned int pool_id, bool eph) +int zcache_autocreate_pool(int cli_id, int pool_id, bool ephemeral) { struct tmem_pool *pool; - struct zcache_client *cli; - uint32_t flags = eph ? 0 : TMEM_POOL_PERSIST; + struct zcache_client *cli = NULL; + uint32_t flags = ephemeral ? 0 : TMEM_POOL_PERSIST; int ret = -1; - BUG_ON(!ramster_enabled); if (cli_id == LOCAL_CLIENT) goto out; if (pool_id >= MAX_POOLS_PER_CLIENT) goto out; - if (cli_id >= MAX_CLIENTS) - goto out; - - cli = &zcache_clients[cli_id]; - if ((eph && disable_cleancache) || (!eph && disable_frontswap)) { - pr_err("zcache_autocreate_pool: pool type disabled\n"); - goto out; - } + else if ((unsigned int)cli_id < MAX_CLIENTS) + cli = &zcache_clients[cli_id]; + if ((ephemeral && !use_cleancache) || (!ephemeral && !use_frontswap)) + BUG(); /* FIXME, handle more gracefully later */ if (!cli->allocated) { - if (zcache_new_client(cli_id)) { - pr_err("zcache_autocreate_pool: can't create client\n"); - goto out; - } + if (zcache_new_client(cli_id)) + BUG(); /* FIXME, handle more gracefully later */ cli = &zcache_clients[cli_id]; } atomic_inc(&cli->refcount); pool = cli->tmem_pools[pool_id]; if (pool != NULL) { - if (pool->persistent && eph) { + if (pool->persistent && ephemeral) { pr_err("zcache_autocreate_pool: type mismatch\n"); goto out; } @@ -1382,7 +2846,7 @@ int zcache_autocreate_pool(unsigned int cli_id, unsigned int pool_id, bool eph) } pool = kmalloc(sizeof(struct tmem_pool), GFP_KERNEL); if (pool == NULL) { - pr_info("%s: pool creation failed: out of memory\n", namestr); + pr_info("ramster: pool creation failed: out of memory\n"); goto out; } atomic_set(&pool->refcount, 0); @@ -1390,11 +2854,14 @@ int zcache_autocreate_pool(unsigned int cli_id, unsigned int pool_id, bool eph) pool->pool_id = pool_id; tmem_new_pool(pool, flags); cli->tmem_pools[pool_id] = pool; - pr_info("%s: AUTOcreated %s tmem poolid=%d, for remote client=%d\n", - namestr, flags & TMEM_POOL_PERSIST ? "persistent" : "ephemeral", + pr_info("ramster: AUTOcreated %s tmem poolid=%d, for remote client=%d\n", + flags & TMEM_POOL_PERSIST ? "persistent" : "ephemeral", pool_id, cli_id); ret = 0; out: + if (cli == NULL) + BUG(); /* FIXME, handle more gracefully later */ + /* pr_err("zcache_autocreate_pool: failed\n"); */ if (cli != NULL) atomic_dec(&cli->refcount); return ret; @@ -1408,6 +2875,7 @@ int zcache_autocreate_pool(unsigned int cli_id, unsigned int pool_id, bool eph) * to translate in-kernel semantics to zcache semantics. */ +#ifdef CONFIG_CLEANCACHE static void zcache_cleancache_put_page(int pool_id, struct cleancache_filekey key, pgoff_t index, struct page *page) @@ -1415,13 +2883,18 @@ static void zcache_cleancache_put_page(int pool_id, u32 ind = (u32) index; struct tmem_oid oid = *(struct tmem_oid *)&key; - if (!disable_cleancache_ignore_nonactive && !PageWasActive(page)) { - zcache_eph_nonactive_puts_ignored++; +#ifdef __PG_WAS_ACTIVE + if (!PageWasActive(page)) { + zcache_nonactive_puts++; return; } - if (likely(ind == index)) - (void)zcache_put_page(LOCAL_CLIENT, pool_id, &oid, index, - page, PAGE_SIZE, false, 1); +#endif + if (likely(ind == index)) { + char *kva = page_address(page); + + (void)zcache_put(LOCAL_CLIENT, pool_id, &oid, index, + kva, PAGE_SIZE, 0, 1); + } } static int zcache_cleancache_get_page(int pool_id, @@ -1430,16 +2903,21 @@ static int zcache_cleancache_get_page(int pool_id, { u32 ind = (u32) index; struct tmem_oid oid = *(struct tmem_oid *)&key; - size_t size; int ret = -1; + preempt_disable(); if (likely(ind == index)) { - ret = zcache_get_page(LOCAL_CLIENT, pool_id, &oid, index, - page, &size, false, 0); - BUG_ON(ret >= 0 && size != PAGE_SIZE); + char *kva = page_address(page); + size_t size = PAGE_SIZE; + + ret = zcache_get(LOCAL_CLIENT, pool_id, &oid, index, + kva, &size, 0, 0); +#ifdef __PG_WAS_ACTIVE if (ret == 0) SetPageWasActive(page); +#endif } + preempt_enable(); return ret; } @@ -1451,7 +2929,7 @@ static void zcache_cleancache_flush_page(int pool_id, struct tmem_oid oid = *(struct tmem_oid *)&key; if (likely(ind == index)) - (void)zcache_flush_page(LOCAL_CLIENT, pool_id, &oid, ind); + (void)zcache_flush(LOCAL_CLIENT, pool_id, &oid, ind); } static void zcache_cleancache_flush_inode(int pool_id, @@ -1465,7 +2943,7 @@ static void zcache_cleancache_flush_inode(int pool_id, static void zcache_cleancache_flush_fs(int pool_id) { if (pool_id >= 0) - (void)zcache_client_destroy_pool(LOCAL_CLIENT, pool_id); + (void)zcache_destroy_pool(pool_id); } static int zcache_cleancache_init_fs(size_t pagesize) @@ -1502,15 +2980,15 @@ struct cleancache_ops zcache_cleancache_register_ops(void) return old_ops; } +#endif +#ifdef CONFIG_FRONTSWAP /* a single tmem poolid is used for all frontswap "types" (swapfiles) */ -static int zcache_frontswap_poolid __read_mostly = -1; +static int zcache_frontswap_poolid = -1; /* * Swizzling increases objects per swaptype, increasing tmem concurrency * for heavy swaploads. Later, larger nr_cpus -> larger SWIZ_BITS - * Setting SWIZ_BITS to 27 basically reconstructs the swap entry from - * frontswap_get_page(), but has side-effects. Hence using 8. */ #define SWIZ_BITS 8 #define SWIZ_MASK ((1 << SWIZ_BITS) - 1) @@ -1524,64 +3002,47 @@ static inline struct tmem_oid oswiz(unsigned type, u32 ind) return oid; } -#ifdef FRONTSWAP_HAS_UNUSE -static void unswiz(struct tmem_oid oid, u32 index, - unsigned *type, pgoff_t *offset) -{ - *type = (unsigned)(oid.oid[0] >> SWIZ_BITS); - *offset = (pgoff_t)((index << SWIZ_BITS) | - (oid.oid[0] & SWIZ_MASK)); -} -#endif - -static int zcache_frontswap_put_page(unsigned type, pgoff_t offset, - struct page *page) +static int zcache_frontswap_store(unsigned type, pgoff_t offset, + struct page *page) { u64 ind64 = (u64)offset; u32 ind = (u32)offset; struct tmem_oid oid = oswiz(type, ind); int ret = -1; unsigned long flags; + char *kva; BUG_ON(!PageLocked(page)); - if (!disable_frontswap_ignore_nonactive && !PageWasActive(page)) { - zcache_pers_nonactive_puts_ignored++; - ret = -ERANGE; - goto out; - } if (likely(ind64 == ind)) { local_irq_save(flags); - ret = zcache_put_page(LOCAL_CLIENT, zcache_frontswap_poolid, - &oid, iswiz(ind), - page, PAGE_SIZE, false, 0); + kva = page_address(page); + ret = zcache_put(LOCAL_CLIENT, zcache_frontswap_poolid, + &oid, iswiz(ind), kva, PAGE_SIZE, 0, 0); local_irq_restore(flags); } -out: return ret; } /* returns 0 if the page was successfully gotten from frontswap, -1 if * was not present (should never happen!) */ -static int zcache_frontswap_get_page(unsigned type, pgoff_t offset, - struct page *page) +static int zcache_frontswap_load(unsigned type, pgoff_t offset, + struct page *page) { u64 ind64 = (u64)offset; u32 ind = (u32)offset; struct tmem_oid oid = oswiz(type, ind); - size_t size; - int ret = -1, get_and_free; + int ret = -1; - if (frontswap_has_exclusive_gets) - get_and_free = 1; - else - get_and_free = -1; + preempt_disable(); /* FIXME, remove this? */ BUG_ON(!PageLocked(page)); if (likely(ind64 == ind)) { - ret = zcache_get_page(LOCAL_CLIENT, zcache_frontswap_poolid, - &oid, iswiz(ind), - page, &size, false, get_and_free); - BUG_ON(ret >= 0 && size != PAGE_SIZE); + char *kva = page_address(page); + size_t size = PAGE_SIZE; + + ret = zcache_get(LOCAL_CLIENT, zcache_frontswap_poolid, + &oid, iswiz(ind), kva, &size, 0, -1); } + preempt_enable(); /* FIXME, remove this? */ return ret; } @@ -1593,7 +3054,7 @@ static void zcache_frontswap_flush_page(unsigned type, pgoff_t offset) struct tmem_oid oid = oswiz(type, ind); if (likely(ind64 == ind)) - (void)zcache_flush_page(LOCAL_CLIENT, zcache_frontswap_poolid, + (void)zcache_flush(LOCAL_CLIENT, zcache_frontswap_poolid, &oid, iswiz(ind)); } @@ -1615,12 +3076,12 @@ static void zcache_frontswap_init(unsigned ignored) /* a single tmem poolid is used for all frontswap "types" (swapfiles) */ if (zcache_frontswap_poolid < 0) zcache_frontswap_poolid = - zcache_local_new_pool(TMEM_POOL_PERSIST); + zcache_local_new_pool(TMEM_POOL_PERSIST); } static struct frontswap_ops zcache_frontswap_ops = { - .store = zcache_frontswap_put_page, - .load = zcache_frontswap_get_page, + .store = zcache_frontswap_store, + .load = zcache_frontswap_load, .invalidate_page = zcache_frontswap_flush_page, .invalidate_area = zcache_frontswap_flush_area, .init = zcache_frontswap_init @@ -1633,135 +3094,179 @@ struct frontswap_ops zcache_frontswap_register_ops(void) return old_ops; } +#endif /* - * zcache initialization - * NOTE FOR NOW zcache or ramster MUST BE PROVIDED AS A KERNEL BOOT PARAMETER - * OR NOTHING HAPPENS! + * frontswap selfshrinking */ -static int __init enable_zcache(char *s) +#ifdef CONFIG_FRONTSWAP +/* In HZ, controls frequency of worker invocation. */ +static unsigned int selfshrink_interval __read_mostly = 5; + +static void selfshrink_process(struct work_struct *work); +static DECLARE_DELAYED_WORK(selfshrink_worker, selfshrink_process); + +/* Enable/disable with sysfs. */ +static bool frontswap_selfshrinking __read_mostly; + +/* Enable/disable with kernel boot option. */ +static bool use_frontswap_selfshrink __initdata = true; + +/* + * The default values for the following parameters were deemed reasonable + * by experimentation, may be workload-dependent, and can all be + * adjusted via sysfs. + */ + +/* Control rate for frontswap shrinking. Higher hysteresis is slower. */ +static unsigned int frontswap_hysteresis __read_mostly = 20; + +/* + * Number of selfshrink worker invocations to wait before observing that + * frontswap selfshrinking should commence. Note that selfshrinking does + * not use a separate worker thread. + */ +static unsigned int frontswap_inertia __read_mostly = 3; + +/* Countdown to next invocation of frontswap_shrink() */ +static unsigned long frontswap_inertia_counter; + +/* + * Invoked by the selfshrink worker thread, uses current number of pages + * in frontswap (frontswap_curr_pages()), previous status, and control + * values (hysteresis and inertia) to determine if frontswap should be + * shrunk and what the new frontswap size should be. Note that + * frontswap_shrink is essentially a partial swapoff that immediately + * transfers pages from the "swap device" (frontswap) back into kernel + * RAM; despite the name, frontswap "shrinking" is very different from + * the "shrinker" interface used by the kernel MM subsystem to reclaim + * memory. + */ +static void frontswap_selfshrink(void) { - zcache_enabled = 1; - return 1; + static unsigned long cur_frontswap_pages; + static unsigned long last_frontswap_pages; + static unsigned long tgt_frontswap_pages; + + last_frontswap_pages = cur_frontswap_pages; + cur_frontswap_pages = frontswap_curr_pages(); + if (!cur_frontswap_pages || + (cur_frontswap_pages > last_frontswap_pages)) { + frontswap_inertia_counter = frontswap_inertia; + return; + } + if (frontswap_inertia_counter && --frontswap_inertia_counter) + return; + if (cur_frontswap_pages <= frontswap_hysteresis) + tgt_frontswap_pages = 0; + else + tgt_frontswap_pages = cur_frontswap_pages - + (cur_frontswap_pages / frontswap_hysteresis); + frontswap_shrink(tgt_frontswap_pages); } -__setup("zcache", enable_zcache); -static int __init enable_ramster(char *s) +static int __init ramster_nofrontswap_selfshrink_setup(char *s) { - zcache_enabled = 1; -#ifdef CONFIG_RAMSTER - ramster_enabled = 1; -#endif + use_frontswap_selfshrink = false; return 1; } -__setup("ramster", enable_ramster); -/* allow independent dynamic disabling of cleancache and frontswap */ +__setup("noselfshrink", ramster_nofrontswap_selfshrink_setup); -static int __init no_cleancache(char *s) +static void selfshrink_process(struct work_struct *work) { - disable_cleancache = 1; - return 1; + if (frontswap_selfshrinking && frontswap_enabled) { + frontswap_selfshrink(); + schedule_delayed_work(&selfshrink_worker, + selfshrink_interval * HZ); + } } -__setup("nocleancache", no_cleancache); +static int ramster_enabled; -static int __init no_frontswap(char *s) +static int __init ramster_selfshrink_init(void) { - disable_frontswap = 1; - return 1; -} + frontswap_selfshrinking = ramster_enabled && use_frontswap_selfshrink; + if (frontswap_selfshrinking) + pr_info("ramster: Initializing frontswap " + "selfshrinking driver.\n"); + else + return -ENODEV; -__setup("nofrontswap", no_frontswap); + schedule_delayed_work(&selfshrink_worker, selfshrink_interval * HZ); -static int __init no_frontswap_exclusive_gets(char *s) -{ - frontswap_has_exclusive_gets = false; - return 1; + return 0; } -__setup("nofrontswapexclusivegets", no_frontswap_exclusive_gets); +subsys_initcall(ramster_selfshrink_init); +#endif + +/* + * zcache initialization + * NOTE FOR NOW ramster MUST BE PROVIDED AS A KERNEL BOOT PARAMETER OR + * NOTHING HAPPENS! + */ + +static int ramster_enabled; -static int __init no_frontswap_ignore_nonactive(char *s) +static int __init enable_ramster(char *s) { - disable_frontswap_ignore_nonactive = 1; + ramster_enabled = 1; return 1; } +__setup("ramster", enable_ramster); + +/* allow independent dynamic disabling of cleancache and frontswap */ -__setup("nofrontswapignorenonactive", no_frontswap_ignore_nonactive); +static int use_cleancache = 1; -static int __init no_cleancache_ignore_nonactive(char *s) +static int __init no_cleancache(char *s) { - disable_cleancache_ignore_nonactive = 1; + pr_info("INIT no_cleancache called\n"); + use_cleancache = 0; return 1; } -__setup("nocleancacheignorenonactive", no_cleancache_ignore_nonactive); +/* + * FIXME: need to guarantee this gets checked before zcache_init is called + * What is the correct way to achieve this? + */ +early_param("nocleancache", no_cleancache); + +static int use_frontswap = 1; -static int __init enable_zcache_compressor(char *s) +static int __init no_frontswap(char *s) { - strncpy(zcache_comp_name, s, ZCACHE_COMP_NAME_SZ); - zcache_enabled = 1; + pr_info("INIT no_frontswap called\n"); + use_frontswap = 0; return 1; } -__setup("zcache=", enable_zcache_compressor); +__setup("nofrontswap", no_frontswap); -static int __init zcache_comp_init(void) +static int __init zcache_init(void) { int ret = 0; - /* check crypto algorithm */ - if (*zcache_comp_name != '\0') { - ret = crypto_has_comp(zcache_comp_name, 0, 0); - if (!ret) - pr_info("zcache: %s not supported\n", - zcache_comp_name); - } - if (!ret) - strcpy(zcache_comp_name, "lzo"); - ret = crypto_has_comp(zcache_comp_name, 0, 0); - if (!ret) { - ret = 1; +#ifdef CONFIG_SYSFS + ret = sysfs_create_group(mm_kobj, &zcache_attr_group); + ret = sysfs_create_group(mm_kobj, &ramster_attr_group); + if (ret) { + pr_err("ramster: can't create sysfs\n"); goto out; } - pr_info("zcache: using %s compressor\n", zcache_comp_name); - - /* alloc percpu transforms */ - ret = 0; - zcache_comp_pcpu_tfms = alloc_percpu(struct crypto_comp *); - if (!zcache_comp_pcpu_tfms) - ret = 1; -out: - return ret; -} - -static int __init zcache_init(void) -{ - int ret = 0; - +#endif /* CONFIG_SYSFS */ +#if defined(CONFIG_CLEANCACHE) || defined(CONFIG_FRONTSWAP) if (ramster_enabled) { - namestr = "ramster"; - ramster_register_pamops(&zcache_pamops); - } -#ifdef CONFIG_DEBUG_FS - zcache_debugfs_init(); -#endif - if (zcache_enabled) { unsigned int cpu; + (void)r2net_register_handlers(); tmem_register_hostops(&zcache_hostops); tmem_register_pamops(&zcache_pamops); ret = register_cpu_notifier(&zcache_cpu_notifier_block); if (ret) { - pr_err("%s: can't register cpu notifier\n", namestr); - goto out; - } - ret = zcache_comp_init(); - if (ret) { - pr_err("%s: compressor initialization failed\n", - namestr); + pr_err("ramster: can't register cpu notifier\n"); goto out; } for_each_online_cpu(cpu) { @@ -1774,47 +3279,42 @@ static int __init zcache_init(void) sizeof(struct tmem_objnode), 0, 0, NULL); zcache_obj_cache = kmem_cache_create("zcache_obj", sizeof(struct tmem_obj), 0, 0, NULL); - ret = zcache_new_client(LOCAL_CLIENT); - if (ret) { - pr_err("%s: can't create client\n", namestr); - goto out; - } - zbud_init(); - if (zcache_enabled && !disable_cleancache) { + ramster_flnode_cache = kmem_cache_create("ramster_flnode", + sizeof(struct flushlist_node), 0, 0, NULL); +#endif +#ifdef CONFIG_CLEANCACHE + pr_info("INIT ramster_enabled=%d use_cleancache=%d\n", + ramster_enabled, use_cleancache); + if (ramster_enabled && use_cleancache) { struct cleancache_ops old_ops; + zbud_init(); register_shrinker(&zcache_shrinker); old_ops = zcache_cleancache_register_ops(); - pr_info("%s: cleancache enabled using kernel transcendent " - "memory and compression buddies\n", namestr); -#ifdef ZCACHE_DEBUG - pr_info("%s: cleancache: ignorenonactive = %d\n", - namestr, !disable_cleancache_ignore_nonactive); -#endif + pr_info("ramster: cleancache enabled using kernel " + "transcendent memory and compression buddies\n"); if (old_ops.init_fs != NULL) - pr_warn("%s: cleancache_ops overridden\n", namestr); + pr_warning("ramster: cleancache_ops overridden"); } - if (zcache_enabled && !disable_frontswap) { +#endif +#ifdef CONFIG_FRONTSWAP + pr_info("INIT ramster_enabled=%d use_frontswap=%d\n", + ramster_enabled, use_frontswap); + if (ramster_enabled && use_frontswap) { struct frontswap_ops old_ops; + zcache_new_client(LOCAL_CLIENT); old_ops = zcache_frontswap_register_ops(); - if (frontswap_has_exclusive_gets) - frontswap_tmem_exclusive_gets(true); - pr_info("%s: frontswap enabled using kernel transcendent " - "memory and compression buddies\n", namestr); -#ifdef ZCACHE_DEBUG - pr_info("%s: frontswap: excl gets = %d active only = %d\n", - namestr, frontswap_has_exclusive_gets, - !disable_frontswap_ignore_nonactive); -#endif + pr_info("ramster: frontswap enabled using kernel " + "transcendent memory and xvmalloc\n"); if (old_ops.init != NULL) - pr_warn("%s: frontswap_ops overridden\n", namestr); + pr_warning("ramster: frontswap_ops overridden"); } - if (ramster_enabled) - ramster_init(!disable_cleancache, !disable_frontswap, - frontswap_has_exclusive_gets); + if (ramster_enabled && (use_frontswap || use_cleancache)) + ramster_remotify_init(); +#endif out: return ret; } -late_initcall(zcache_init); +module_init(zcache_init) diff --git a/trunk/drivers/staging/ramster/zcache.h b/trunk/drivers/staging/ramster/zcache.h index 81722b33b087..250b121c22e5 100644 --- a/trunk/drivers/staging/ramster/zcache.h +++ b/trunk/drivers/staging/ramster/zcache.h @@ -1,53 +1,22 @@ - /* * zcache.h * - * Copyright (c) 2012, Dan Magenheimer, Oracle Corp. + * External zcache functions + * + * Copyright (c) 2009-2012, Dan Magenheimer, Oracle Corp. */ #ifndef _ZCACHE_H_ #define _ZCACHE_H_ -struct zcache_preload { - struct tmem_obj *obj; - struct tmem_objnode *objnodes[OBJNODE_TREE_MAX_PATH]; -}; - -struct tmem_pool; - -#define MAX_POOLS_PER_CLIENT 16 - -#define MAX_CLIENTS 16 -#define LOCAL_CLIENT ((uint16_t)-1) - -struct zcache_client { - struct tmem_pool *tmem_pools[MAX_POOLS_PER_CLIENT]; - bool allocated; - atomic_t refcount; -}; - -extern struct tmem_pool *zcache_get_pool_by_id(uint16_t cli_id, - uint16_t poolid); -extern void zcache_put_pool(struct tmem_pool *pool); - -extern int zcache_put_page(int, int, struct tmem_oid *, - uint32_t, void *, - unsigned int, bool, int); -extern int zcache_get_page(int, int, struct tmem_oid *, uint32_t, - void *, size_t *, bool, int); -extern int zcache_flush_page(int, int, struct tmem_oid *, uint32_t); +extern int zcache_put(int, int, struct tmem_oid *, uint32_t, + char *, size_t, bool, int); +extern int zcache_autocreate_pool(int, int, bool); +extern int zcache_get(int, int, struct tmem_oid *, uint32_t, + char *, size_t *, bool, int); +extern int zcache_flush(int, int, struct tmem_oid *, uint32_t); extern int zcache_flush_object(int, int, struct tmem_oid *); -extern void zcache_decompress_to_page(char *, unsigned int, struct page *); - -#ifdef CONFIG_RAMSTER -extern void *zcache_pampd_create(char *, unsigned int, bool, int, - struct tmem_handle *); -int zcache_autocreate_pool(unsigned int cli_id, unsigned int pool_id, bool eph); -#endif - -#define MAX_POOLS_PER_CLIENT 16 - -#define MAX_CLIENTS 16 -#define LOCAL_CLIENT ((uint16_t)-1) +extern int zcache_localify(int, struct tmem_oid *, uint32_t, + char *, size_t, void *); -#endif /* _ZCACHE_H_ */ +#endif /* _ZCACHE_H */ diff --git a/trunk/drivers/staging/rtl8187se/ieee80211/ieee80211.h b/trunk/drivers/staging/rtl8187se/ieee80211/ieee80211.h index 5f5a30223d56..b94c48b29302 100644 --- a/trunk/drivers/staging/rtl8187se/ieee80211/ieee80211.h +++ b/trunk/drivers/staging/rtl8187se/ieee80211/ieee80211.h @@ -1094,7 +1094,7 @@ struct ieee80211_device { int (*reset_port)(struct net_device *dev); - /* Softmac-generated frames (management) are TXed via this + /* Softmac-generated frames (mamagement) are TXed via this * callback if the flag IEEE_SOFTMAC_SINGLE_QUEUE is * not set. As some cards may have different HW queues that * one might want to use for data and management frames diff --git a/trunk/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c b/trunk/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c index 00f9af06aca5..8173240dcf7a 100644 --- a/trunk/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c +++ b/trunk/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c @@ -21,7 +21,6 @@ #include #include #include -#include #include "dot11d.h" u8 rsn_authen_cipher_suite[16][4] = { @@ -2111,7 +2110,13 @@ void ieee80211_rtl_stop_queue(struct ieee80211_device *ieee) inline void ieee80211_randomize_cell(struct ieee80211_device *ieee) { - random_ether_addr(ieee->current_network.bssid); + get_random_bytes(ieee->current_network.bssid, ETH_ALEN); + + /* an IBSS cell address must have the two less significant + * bits of the first byte = 2 + */ + ieee->current_network.bssid[0] &= ~0x01; + ieee->current_network.bssid[0] |= 0x02; } /* called in user context only */ @@ -2803,7 +2808,9 @@ static int ieee80211_wpa_set_encryption(struct ieee80211_device *ieee, param->u.crypt.key_len); return -EINVAL; } - if (is_broadcast_ether_addr(param->sta_addr)) { + if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff && + param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff && + param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) { if (param->u.crypt.idx >= WEP_KEYS) return -EINVAL; crypt = &ieee->crypt[param->u.crypt.idx]; diff --git a/trunk/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac_wx.c b/trunk/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac_wx.c index 1ef8fd612732..5d204906baf7 100644 --- a/trunk/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac_wx.c +++ b/trunk/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac_wx.c @@ -14,8 +14,6 @@ */ -#include - #include "ieee80211.h" /* FIXME: add A freqs */ @@ -133,6 +131,7 @@ int ieee80211_wx_set_wap(struct ieee80211_device *ieee, { int ret = 0; + u8 zero[] = {0,0,0,0,0,0}; unsigned long flags; short ifup = ieee->proto_started;//dev->flags & IFF_UP; @@ -162,7 +161,7 @@ int ieee80211_wx_set_wap(struct ieee80211_device *ieee, spin_lock_irqsave(&ieee->lock, flags); memcpy(ieee->current_network.bssid, temp->sa_data, ETH_ALEN); - ieee->wap_set = !is_zero_ether_addr(temp->sa_data); + ieee->wap_set = memcmp(temp->sa_data, zero,ETH_ALEN)!=0; //printk(" %x:%x:%x:%x:%x:%x\n", ieee->current_network.bssid[0],ieee->current_network.bssid[1],ieee->current_network.bssid[2],ieee->current_network.bssid[3],ieee->current_network.bssid[4],ieee->current_network.bssid[5]); spin_unlock_irqrestore(&ieee->lock, flags); diff --git a/trunk/drivers/staging/rtl8187se/r8180_core.c b/trunk/drivers/staging/rtl8187se/r8180_core.c index 20e5fb58f52f..fd22b75aea4f 100644 --- a/trunk/drivers/staging/rtl8187se/r8180_core.c +++ b/trunk/drivers/staging/rtl8187se/r8180_core.c @@ -2377,7 +2377,7 @@ void rtl8180_wmm_param_update(struct work_struct *work) u8 u1bAIFS; u32 u4bAcParam; pAcParam = (PAC_PARAM)(&AcParam); - /* Retrieve parameters to update. */ + /* Retrieve paramters to update. */ u1bAIFS = pAcParam->f.AciAifsn.f.AIFSN * (((mode&IEEE_G) == IEEE_G) ? 9 : 20) + aSifsTime; u4bAcParam = ((((u32)(pAcParam->f.TXOPLimit))<f.Ecw.f.ECWmax))<f.AciAifsn.f.ACI; /* Mode G/A: slotTimeTimer = 9; Mode B: 20 */ u1bAIFS = pAcParam->f.AciAifsn.f.AIFSN * (((mode&IEEE_G) == IEEE_G) ? 9 : 20) + aSifsTime; diff --git a/trunk/drivers/staging/rtl8187se/r8180_hw.h b/trunk/drivers/staging/rtl8187se/r8180_hw.h index 533938123a97..3fca144a56a4 100644 --- a/trunk/drivers/staging/rtl8187se/r8180_hw.h +++ b/trunk/drivers/staging/rtl8187se/r8180_hw.h @@ -554,16 +554,11 @@ /* by amy for power save */ /* by amy for antenna */ #define EEPROM_SW_REVD_OFFSET 0x3f - -/* BIT[8-9] is for SW Antenna Diversity. - * Only the value EEPROM_SW_AD_ENABLE means enable, other values are disable. - */ +/* BIT[8-9] is for SW Antenna Diversity. Only the value EEPROM_SW_AD_ENABLE means enable, other values are diable. */ #define EEPROM_SW_AD_MASK 0x0300 #define EEPROM_SW_AD_ENABLE 0x0100 -/* BIT[10-11] determine if Antenna 1 is the Default Antenna. - * Only the value EEPROM_DEF_ANT_1 means TRUE, other values are FALSE. - */ +/* BIT[10-11] determine if Antenna 1 is the Default Antenna. Only the value EEPROM_DEF_ANT_1 means TRUE, other values are FALSE. */ #define EEPROM_DEF_ANT_MASK 0x0C00 #define EEPROM_DEF_ANT_1 0x0400 /*by amy for antenna */ diff --git a/trunk/drivers/staging/rtl8187se/r8185b_init.c b/trunk/drivers/staging/rtl8187se/r8185b_init.c index bf343199bd21..914495783c06 100644 --- a/trunk/drivers/staging/rtl8187se/r8185b_init.c +++ b/trunk/drivers/staging/rtl8187se/r8185b_init.c @@ -1008,7 +1008,7 @@ void ActUpdateChannelAccessSetting(struct net_device *dev, u8 u1bAIFS; u32 u4bAcParam; - /* Retrieve parameters to update. */ + /* Retrieve paramters to update. */ eACI = pAcParam->f.AciAifsn.f.ACI; u1bAIFS = pAcParam->f.AciAifsn.f.AIFSN * ChnlAccessSetting->SlotTimeTimer + aSifsTime; u4bAcParam = ((((u32)(pAcParam->f.TXOPLimit)) << AC_PARAM_TXOP_LIMIT_OFFSET) | diff --git a/trunk/drivers/staging/rtl8192e/rtl8192e/r8192E_firmware.c b/trunk/drivers/staging/rtl8192e/rtl8192e/r8192E_firmware.c index dd2a96bfcc0c..b526fa428679 100644 --- a/trunk/drivers/staging/rtl8192e/rtl8192e/r8192E_firmware.c +++ b/trunk/drivers/staging/rtl8192e/rtl8192e/r8192E_firmware.c @@ -265,11 +265,10 @@ bool init_firmware(struct net_device *dev) case FW_SOURCE_IMG_FILE: { if (pfirmware->firmware_buf_size[init_step] == 0) { - const char *fw_name[3] = { - RTL8192E_BOOT_IMG_FW, - RTL8192E_MAIN_IMG_FW, - RTL8192E_DATA_IMG_FW - }; + const char *fw_name[3] = { "RTL8192E/boot.img", + "RTL8192E/main.img", + "RTL8192E/data.img" + }; const struct firmware *fw_entry; int rc; rc = request_firmware(&fw_entry, diff --git a/trunk/drivers/staging/rtl8192e/rtl8192e/r8192E_firmware.h b/trunk/drivers/staging/rtl8192e/rtl8192e/r8192E_firmware.h index 06d6abc8345c..caa878833106 100644 --- a/trunk/drivers/staging/rtl8192e/rtl8192e/r8192E_firmware.h +++ b/trunk/drivers/staging/rtl8192e/rtl8192e/r8192E_firmware.h @@ -23,10 +23,6 @@ #define GET_COMMAND_PACKET_FRAG_THRESHOLD(v) (4*(v/4) - 8) -#define RTL8192E_BOOT_IMG_FW "RTL8192E/boot.img" -#define RTL8192E_MAIN_IMG_FW "RTL8192E/main.img" -#define RTL8192E_DATA_IMG_FW "RTL8192E/data.img" - enum firmware_init_step { FW_INIT_STEP0_BOOT = 0, FW_INIT_STEP1_MAIN = 1, diff --git a/trunk/drivers/staging/rtl8192e/rtl8192e/rtl_core.c b/trunk/drivers/staging/rtl8192e/rtl8192e/rtl_core.c index 81134d312ee3..4f602b227b50 100644 --- a/trunk/drivers/staging/rtl8192e/rtl8192e/rtl_core.c +++ b/trunk/drivers/staging/rtl8192e/rtl8192e/rtl_core.c @@ -734,7 +734,8 @@ static void rtl8192_prepare_beacon(struct r8192_priv *priv) ring = &priv->tx_ring[BEACON_QUEUE]; pskb = __skb_dequeue(&ring->queue); - kfree_skb(pskb); + if (pskb) + kfree_skb(pskb); pnewskb = rtllib_get_beacon(priv->rtllib); if (!pnewskb) @@ -3124,9 +3125,6 @@ MODULE_DESCRIPTION("Linux driver for Realtek RTL819x WiFi cards"); MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR); MODULE_VERSION(DRV_VERSION); MODULE_LICENSE("GPL"); -MODULE_FIRMWARE(RTL8192E_BOOT_IMG_FW); -MODULE_FIRMWARE(RTL8192E_MAIN_IMG_FW); -MODULE_FIRMWARE(RTL8192E_DATA_IMG_FW); module_param(ifname, charp, S_IRUGO|S_IWUSR); module_param(hwwep, int, S_IRUGO|S_IWUSR); diff --git a/trunk/drivers/staging/rtl8192e/rtl8192e/rtl_dm.c b/trunk/drivers/staging/rtl8192e/rtl8192e/rtl_dm.c index 1853665764a0..481b1e4d4913 100644 --- a/trunk/drivers/staging/rtl8192e/rtl8192e/rtl_dm.c +++ b/trunk/drivers/staging/rtl8192e/rtl8192e/rtl_dm.c @@ -202,7 +202,7 @@ static void dm_check_ac_dc_power(struct net_device *dev) if (priv->ResetProgress == RESET_TYPE_SILENT) { RT_TRACE((COMP_INIT | COMP_POWER | COMP_RF), - "GPIOChangeRFWorkItemCallBack(): Silent Reset!!!!!!!\n"); + "GPIOChangeRFWorkItemCallBack(): Silent Reseting!!!!!!!\n"); return; } diff --git a/trunk/drivers/staging/rtl8192e/rtl8192e/rtl_pci.c b/trunk/drivers/staging/rtl8192e/rtl8192e/rtl_pci.c index 5abbee37cdca..ddadcc3e4e7c 100644 --- a/trunk/drivers/staging/rtl8192e/rtl8192e/rtl_pci.c +++ b/trunk/drivers/staging/rtl8192e/rtl8192e/rtl_pci.c @@ -31,10 +31,12 @@ static void rtl8192_parse_pci_configuration(struct pci_dev *pdev, struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev); u8 tmp; - u16 LinkCtrlReg; + int pos; + u8 LinkCtrlReg; - pcie_capability_read_word(priv->pdev, PCI_EXP_LNKCTL, &LinkCtrlReg); - priv->NdisAdapter.LinkCtrlReg = (u8)LinkCtrlReg; + pos = pci_find_capability(priv->pdev, PCI_CAP_ID_EXP); + pci_read_config_byte(priv->pdev, pos + PCI_EXP_LNKCTL, &LinkCtrlReg); + priv->NdisAdapter.LinkCtrlReg = LinkCtrlReg; RT_TRACE(COMP_INIT, "Link Control Register =%x\n", priv->NdisAdapter.LinkCtrlReg); diff --git a/trunk/drivers/staging/rtl8192e/rtllib.h b/trunk/drivers/staging/rtl8192e/rtllib.h index 9ac8d8ea4ae8..d7460ae3a765 100644 --- a/trunk/drivers/staging/rtl8192e/rtllib.h +++ b/trunk/drivers/staging/rtl8192e/rtllib.h @@ -2397,12 +2397,12 @@ struct rtllib_device { struct rtllib_network *network, u16 type); int (*is_qos_active)(struct net_device *dev, struct sk_buff *skb); - /* Softmac-generated frames (management) are TXed via this + /* Softmac-generated frames (mamagement) are TXed via this * callback if the flag IEEE_SOFTMAC_SINGLE_QUEUE is * not set. As some cards may have different HW queues that * one might want to use for data and management frames * the option to have two callbacks might be useful. - * This function can't sleep. + * This fucntion can't sleep. */ int (*softmac_hard_start_xmit)(struct sk_buff *skb, struct net_device *dev); @@ -2441,9 +2441,9 @@ struct rtllib_device { * it is called in a work_queue when switching to ad-hoc mode * or in behalf of iwlist scan when the card is associated * and root user ask for a scan. - * the function stop_scan should stop both the syncro and + * the fucntion stop_scan should stop both the syncro and * background scanning and can sleep. - * The function start_scan should initiate the background + * The fucntion start_scan should initiate the background * scanning and can't sleep. */ void (*scan_syncro)(struct net_device *dev); diff --git a/trunk/drivers/staging/rtl8192e/rtllib_softmac.c b/trunk/drivers/staging/rtl8192e/rtllib_softmac.c index 4feecec8609c..a21b4d91a596 100644 --- a/trunk/drivers/staging/rtl8192e/rtllib_softmac.c +++ b/trunk/drivers/staging/rtl8192e/rtllib_softmac.c @@ -19,7 +19,6 @@ #include #include #include -#include #include "dot11d.h" short rtllib_is_54g(struct rtllib_network *net) @@ -267,7 +266,7 @@ inline void softmac_mgmt_xmit(struct sk_buff *skb, struct rtllib_device *ieee) else ieee->seq_ctrl[0]++; - /* check whether the managed packet queued greater than 5 */ + /* check wether the managed packet queued greater than 5 */ if (!ieee->check_nic_enough_desc(ieee->dev, tcb_desc->queue_index) || (skb_queue_len(&ieee->skb_waitQ[tcb_desc->queue_index]) != 0) || (ieee->queue_stop)) { @@ -1688,7 +1687,7 @@ inline void rtllib_softmac_new_net(struct rtllib_device *ieee, * if the network does broadcast and the user did set essid * check if essid match * if the ap is not set, check that the user set the bssid - * and the network does broadcast and that those two bssid match + * and the network does bradcast and that those two bssid match */ if ((apset && apmatch && ((ssidset && ssidbroad && ssidmatch) || @@ -1844,7 +1843,7 @@ static short probe_rq_parse(struct rtllib_device *ieee, struct sk_buff *skb, bssid_match = (memcmp(header->addr3, ieee->current_network.bssid, ETH_ALEN) != 0) && - (!is_broadcast_ether_addr(header->addr3)); + (memcmp(header->addr3, "\xff\xff\xff\xff\xff\xff", ETH_ALEN) != 0); if (bssid_match) return -1; @@ -2443,7 +2442,7 @@ inline int rtllib_rx_frame_softmac(struct rtllib_device *ieee, return 0; } -/* following are for a simpler TX queue management. +/* following are for a simplier TX queue management. * Instead of using netif_[stop/wake]_queue the driver * will use these two functions (plus a reset one), that * will internally use the kernel netif_* and takes @@ -2620,7 +2619,13 @@ void rtllib_wake_all_queues(struct rtllib_device *ieee) inline void rtllib_randomize_cell(struct rtllib_device *ieee) { - random_ether_addr(ieee->current_network.bssid); + get_random_bytes(ieee->current_network.bssid, ETH_ALEN); + + /* an IBSS cell address must have the two less significant + * bits of the first byte = 2 + */ + ieee->current_network.bssid[0] &= ~0x01; + ieee->current_network.bssid[0] |= 0x02; } /* called in user context only */ @@ -3356,7 +3361,9 @@ static int rtllib_wpa_set_encryption(struct rtllib_device *ieee, param->u.crypt.key_len); return -EINVAL; } - if (is_broadcast_ether_addr(param->sta_addr)) { + if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff && + param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff && + param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) { if (param->u.crypt.idx >= NUM_WEP_KEYS) return -EINVAL; crypt = &ieee->crypt_info.crypt[param->u.crypt.idx]; @@ -3404,7 +3411,8 @@ static int rtllib_wpa_set_encryption(struct rtllib_device *ieee, lib80211_crypt_delayed_deinit(&ieee->crypt_info, crypt); - new_crypt = kmalloc(sizeof(*new_crypt), GFP_KERNEL); + new_crypt = (struct lib80211_crypt_data *) + kmalloc(sizeof(*new_crypt), GFP_KERNEL); if (new_crypt == NULL) { ret = -ENOMEM; goto done; diff --git a/trunk/drivers/staging/rtl8192e/rtllib_softmac_wx.c b/trunk/drivers/staging/rtl8192e/rtllib_softmac_wx.c index 740cf85e9d5b..1bb6b52e0f24 100644 --- a/trunk/drivers/staging/rtl8192e/rtllib_softmac_wx.c +++ b/trunk/drivers/staging/rtl8192e/rtllib_softmac_wx.c @@ -14,8 +14,6 @@ */ -#include - #include "rtllib.h" #include "dot11d.h" /* FIXME: add A freqs */ @@ -139,6 +137,7 @@ int rtllib_wx_set_wap(struct rtllib_device *ieee, { int ret = 0; + u8 zero[] = {0, 0, 0, 0, 0, 0}; unsigned long flags; short ifup = ieee->proto_started; @@ -158,7 +157,7 @@ int rtllib_wx_set_wap(struct rtllib_device *ieee, goto out; } - if (is_zero_ether_addr(temp->sa_data)) { + if (memcmp(temp->sa_data, zero, ETH_ALEN) == 0) { spin_lock_irqsave(&ieee->lock, flags); memcpy(ieee->current_network.bssid, temp->sa_data, ETH_ALEN); ieee->wap_set = 0; @@ -178,7 +177,7 @@ int rtllib_wx_set_wap(struct rtllib_device *ieee, ieee->cannot_notify = false; memcpy(ieee->current_network.bssid, temp->sa_data, ETH_ALEN); - ieee->wap_set = !is_zero_ether_addr(temp->sa_data); + ieee->wap_set = (memcmp(temp->sa_data, zero, ETH_ALEN) != 0); spin_unlock_irqrestore(&ieee->lock, flags); diff --git a/trunk/drivers/staging/rtl8192u/ieee80211/ieee80211.h b/trunk/drivers/staging/rtl8192u/ieee80211/ieee80211.h index 13f45c3125ce..1c0a1db6420f 100644 --- a/trunk/drivers/staging/rtl8192u/ieee80211/ieee80211.h +++ b/trunk/drivers/staging/rtl8192u/ieee80211/ieee80211.h @@ -2114,7 +2114,7 @@ struct ieee80211_device { struct ieee80211_network * network, u16 type); int (*is_qos_active) (struct net_device *dev, struct sk_buff *skb); - /* Softmac-generated frames (management) are TXed via this + /* Softmac-generated frames (mamagement) are TXed via this * callback if the flag IEEE_SOFTMAC_SINGLE_QUEUE is * not set. As some cards may have different HW queues that * one might want to use for data and management frames @@ -2192,7 +2192,7 @@ struct ieee80211_device { int (*handle_assoc_response) (struct net_device * dev, struct ieee80211_assoc_response_frame * resp, struct ieee80211_network * network); - /* check whether Tx hw resource available */ + /* check whether Tx hw resouce available */ short (*check_nic_enough_desc)(struct net_device *dev, int queue_index); //added by wb for HT related // void (*SwChnlByTimerHandler)(struct net_device *dev, int channel); diff --git a/trunk/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c b/trunk/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c index 7a0707810fd0..f6ff8cff313a 100644 --- a/trunk/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c +++ b/trunk/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c @@ -20,8 +20,6 @@ #include #include #include -#include - #include "dot11d.h" u8 rsn_authen_cipher_suite[16][4] = { @@ -271,7 +269,7 @@ inline void softmac_mgmt_xmit(struct sk_buff *skb, struct ieee80211_device *ieee else ieee->seq_ctrl[0]++; - /* check whether the managed packet queued greater than 5 */ + /* check wether the managed packet queued greater than 5 */ if(!ieee->check_nic_enough_desc(ieee->dev,tcb_desc->queue_index)||\ (skb_queue_len(&ieee->skb_waitQ[tcb_desc->queue_index]) != 0)||\ (ieee->queue_stop) ) { @@ -1450,7 +1448,7 @@ inline void ieee80211_softmac_new_net(struct ieee80211_device *ieee, struct ieee ( apset && apmatch && ((ssidset && ssidbroad && ssidmatch) || (ssidbroad && !ssidset) || (!ssidbroad && ssidset)) ) || /* if the ap is not set, check that the user set the bssid - * and the network does broadcast and that those two bssid matches + * and the network does bradcast and that those two bssid matches */ (!apset && ssidset && ssidbroad && ssidmatch) ){ @@ -2288,7 +2286,13 @@ void ieee80211_stop_queue(struct ieee80211_device *ieee) inline void ieee80211_randomize_cell(struct ieee80211_device *ieee) { - random_ether_addr(ieee->current_network.bssid); + get_random_bytes(ieee->current_network.bssid, ETH_ALEN); + + /* an IBSS cell address must have the two less significant + * bits of the first byte = 2 + */ + ieee->current_network.bssid[0] &= ~0x01; + ieee->current_network.bssid[0] |= 0x02; } /* called in user context only */ @@ -2516,7 +2520,7 @@ void ieee80211_associate_retry_wq(struct work_struct *work) /* until we do not set the state to IEEE80211_NOLINK * there are no possibility to have someone else trying - * to start an association procedure (we get here with + * to start an association procdure (we get here with * ieee->state = IEEE80211_ASSOCIATING). * When we set the state to IEEE80211_NOLINK it is possible * that the RX path run an attempt to associate, but @@ -2965,7 +2969,9 @@ static int ieee80211_wpa_set_encryption(struct ieee80211_device *ieee, param->u.crypt.key_len); return -EINVAL; } - if (is_broadcast_ether_addr(param->sta_addr)) { + if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff && + param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff && + param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) { if (param->u.crypt.idx >= WEP_KEYS) return -EINVAL; crypt = &ieee->crypt[param->u.crypt.idx]; diff --git a/trunk/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac_wx.c b/trunk/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac_wx.c index 421da8a07697..cb5a3c32974e 100644 --- a/trunk/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac_wx.c +++ b/trunk/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac_wx.c @@ -14,8 +14,6 @@ */ -#include - #include "ieee80211.h" #include "dot11d.h" /* FIXME: add A freqs */ @@ -138,6 +136,7 @@ int ieee80211_wx_set_wap(struct ieee80211_device *ieee, { int ret = 0; + u8 zero[] = {0,0,0,0,0,0}; unsigned long flags; short ifup = ieee->proto_started;//dev->flags & IFF_UP; @@ -166,7 +165,7 @@ int ieee80211_wx_set_wap(struct ieee80211_device *ieee, spin_lock_irqsave(&ieee->lock, flags); memcpy(ieee->current_network.bssid, temp->sa_data, ETH_ALEN); - ieee->wap_set = !is_zero_ether_addr(temp->sa_data); + ieee->wap_set = memcmp(temp->sa_data, zero,ETH_ALEN)!=0; spin_unlock_irqrestore(&ieee->lock, flags); diff --git a/trunk/drivers/staging/rtl8192u/ieee80211/rtl819x_BAProc.c b/trunk/drivers/staging/rtl8192u/ieee80211/rtl819x_BAProc.c index 1ebea3daea2d..27d083a70eb2 100644 --- a/trunk/drivers/staging/rtl8192u/ieee80211/rtl819x_BAProc.c +++ b/trunk/drivers/staging/rtl8192u/ieee80211/rtl819x_BAProc.c @@ -1,6 +1,6 @@ /******************************************************************************************************************************** * This file is created to process BA Action Frame. According to 802.11 spec, there are 3 BA action types at all. And as BA is - * related to TS, this part need some structure defined in QOS side code. Also TX RX is going to be resturctured, so how to send + * related to TS, this part need some struture defined in QOS side code. Also TX RX is going to be resturctured, so how to send * ADDBAREQ ADDBARSP and DELBA packet is still on consideration. Temporarily use MANAGE QUEUE instead of Normal Queue. * WB 2008-05-27 * *****************************************************************************************************************************/ diff --git a/trunk/drivers/staging/rtl8192u/ieee80211/rtl819x_HT.h b/trunk/drivers/staging/rtl8192u/ieee80211/rtl819x_HT.h index a60b39cdb472..0b1a1fc09391 100644 --- a/trunk/drivers/staging/rtl8192u/ieee80211/rtl819x_HT.h +++ b/trunk/drivers/staging/rtl8192u/ieee80211/rtl819x_HT.h @@ -15,7 +15,7 @@ #define HT_OPMODE_MIXED 3 // -// MIMO Power Save Settings +// MIMO Power Save Setings // #define MIMO_PS_STATIC 0 #define MIMO_PS_DYNAMIC 1 @@ -242,7 +242,7 @@ typedef struct _RT_HIGH_THROUGHPUT{ u8 bEnableHT; u8 bCurrentHTSupport; - u8 bRegBW40MHz; // Tx 40MHz channel capability + u8 bRegBW40MHz; // Tx 40MHz channel capablity u8 bCurBW40MHz; // Tx 40MHz channel capability u8 bRegShortGI40MHz; // Tx Short GI for 40Mhz diff --git a/trunk/drivers/staging/rtl8192u/ieee80211/rtl819x_HTProc.c b/trunk/drivers/staging/rtl8192u/ieee80211/rtl819x_HTProc.c index ebb523904edc..e88a839b2a91 100644 --- a/trunk/drivers/staging/rtl8192u/ieee80211/rtl819x_HTProc.c +++ b/trunk/drivers/staging/rtl8192u/ieee80211/rtl819x_HTProc.c @@ -912,7 +912,7 @@ u8 HTFilterMCSRate( struct ieee80211_device* ieee, u8* pSupportMCS, u8* pOperate u8 i=0; - // filter out operational rate set not supported by AP, the length of it is 16 + // filter out operational rate set not supported by AP, the lenth of it is 16 for(i=0;i<=15;i++){ pOperateMCS[i] = ieee->Regdot11HTOperationalRateSet[i]&pSupportMCS[i]; } diff --git a/trunk/drivers/staging/rtl8192u/r8192U_core.c b/trunk/drivers/staging/rtl8192u/r8192U_core.c index 5a2fab9fa772..5981d6658320 100644 --- a/trunk/drivers/staging/rtl8192u/r8192U_core.c +++ b/trunk/drivers/staging/rtl8192u/r8192U_core.c @@ -2232,15 +2232,24 @@ short rtl8192_usb_initendpoints(struct net_device *dev) memset(priv->rx_urb, 0, sizeof(struct urb*) * MAX_RX_URB); priv->pp_rxskb = kcalloc(MAX_RX_URB, sizeof(struct sk_buff *), GFP_KERNEL); - if (!priv->pp_rxskb) { - kfree(priv->rx_urb); + if (priv->pp_rxskb == NULL) + goto destroy; - priv->pp_rxskb = NULL; - priv->rx_urb = NULL; + goto _middle; - DMESGE("Endpoint Alloc Failure"); - return -ENOMEM; - } + +destroy: + kfree(priv->pp_rxskb); + kfree(priv->rx_urb); + + priv->pp_rxskb = NULL; + priv->rx_urb = NULL; + + DMESGE("Endpoint Alloc Failure"); + return -ENOMEM; + + +_middle: printk("End of initendpoints\n"); return 0; @@ -2799,7 +2808,9 @@ static void rtl8192_init_priv_variable(struct net_device* dev) (priv->EarlyRxThreshold == 7 ? RCR_ONLYERLPKT:0); priv->AcmControl = 0; - priv->pFirmware = kzalloc(sizeof(rt_firmware), GFP_KERNEL); + priv->pFirmware = kmalloc(sizeof(rt_firmware), GFP_KERNEL); + if (priv->pFirmware) + memset(priv->pFirmware, 0, sizeof(rt_firmware)); /* rx related queue */ skb_queue_head_init(&priv->rx_queue); diff --git a/trunk/drivers/staging/rtl8192u/r819xU_HTType.h b/trunk/drivers/staging/rtl8192u/r819xU_HTType.h index 6c1d05e1e820..e07f8b17a0d6 100644 --- a/trunk/drivers/staging/rtl8192u/r819xU_HTType.h +++ b/trunk/drivers/staging/rtl8192u/r819xU_HTType.h @@ -16,7 +16,7 @@ #define HT_OPMODE_MIXED 3 // -// MIMO Power Save Settings +// MIMO Power Save Setings // #define MIMO_PS_STATIC 0 #define MIMO_PS_DYNAMIC 1 diff --git a/trunk/drivers/staging/rtl8192u/r819xU_phyreg.h b/trunk/drivers/staging/rtl8192u/r819xU_phyreg.h index cca34c05f6a5..50f24dce8b16 100644 --- a/trunk/drivers/staging/rtl8192u/r819xU_phyreg.h +++ b/trunk/drivers/staging/rtl8192u/r819xU_phyreg.h @@ -443,7 +443,7 @@ #define bCCKRxIG 0x7f00 #define bCCKLNAPolarity 0x800000 #define bCCKRx1stGain 0x7f0000 -#define bCCKRFExtend 0x20000000 //CCK Rx initial gain polarity +#define bCCKRFExtend 0x20000000 //CCK Rx inital gain polarity #define bCCKRxAGCSatLevel 0x1f000000 #define bCCKRxAGCSatCount 0xe0 #define bCCKRxRFSettle 0x1f //AGCsamp_dly diff --git a/trunk/drivers/staging/rtl8712/drv_types.h b/trunk/drivers/staging/rtl8712/drv_types.h index a074fe810169..62b55663c63a 100644 --- a/trunk/drivers/staging/rtl8712/drv_types.h +++ b/trunk/drivers/staging/rtl8712/drv_types.h @@ -70,7 +70,9 @@ struct qos_priv { #include "rtl871x_event.h" #include "rtl871x_led.h" +#define SPEC_DEV_ID_NONE BIT(0) #define SPEC_DEV_ID_DISABLE_HT BIT(1) +#define SPEC_DEV_ID_ENABLE_PS BIT(2) struct specific_device_id { u32 flags; @@ -125,6 +127,13 @@ struct registry_priv { u8 wifi_test; }; +/* For registry parameters */ +#define RGTRY_OFT(field) ((addr_t)FIELD_OFFSET(struct registry_priv, field)) +#define RGTRY_SZ(field) sizeof(((struct registry_priv *)0)->field) +#define BSSID_OFT(field) ((addr_t)FIELD_OFFSET(struct ndis_wlan_bssid_ex, \ + field)) +#define BSSID_SZ(field) sizeof(((struct ndis_wlan_bssid_ex *)0)->field) + struct dvobj_priv { struct _adapter *padapter; u32 nr_endpoint; diff --git a/trunk/drivers/staging/rtl8712/ethernet.h b/trunk/drivers/staging/rtl8712/ethernet.h index 90954203776d..882d61b2e959 100644 --- a/trunk/drivers/staging/rtl8712/ethernet.h +++ b/trunk/drivers/staging/rtl8712/ethernet.h @@ -35,6 +35,14 @@ /*!< Is Multicast Address? */ #define RT_ETH_IS_MULTICAST(_pAddr) ((((u8 *)(_pAddr))[0]&0x01) != 0) +/*!< Is Broadcast Address? */ +#define RT_ETH_IS_BROADCAST(_pAddr) ( \ + ((u8 *)(_pAddr))[0] == 0xff && \ + ((u8 *)(_pAddr))[1] == 0xff && \ + ((u8 *)(_pAddr))[2] == 0xff && \ + ((u8 *)(_pAddr))[3] == 0xff && \ + ((u8 *)(_pAddr))[4] == 0xff && \ + ((u8 *)(_pAddr))[5] == 0xff) #endif /* #ifndef __INC_ETHERNET_H */ diff --git a/trunk/drivers/staging/rtl8712/os_intfs.c b/trunk/drivers/staging/rtl8712/os_intfs.c index e00f7918d261..448f00dd68fe 100644 --- a/trunk/drivers/staging/rtl8712/os_intfs.c +++ b/trunk/drivers/staging/rtl8712/os_intfs.c @@ -96,7 +96,7 @@ static char *initmac; /* if wifi_test = 1, driver will disable the turbo mode and pass it to * firmware private. */ -static int wifi_test; +static int wifi_test = 0; module_param_string(ifname, ifname, sizeof(ifname), S_IRUGO|S_IWUSR); module_param(wifi_test, int, 0644); diff --git a/trunk/drivers/staging/rtl8712/recv_linux.c b/trunk/drivers/staging/rtl8712/recv_linux.c index 495ee1205e02..0e26d5f6cf2d 100644 --- a/trunk/drivers/staging/rtl8712/recv_linux.c +++ b/trunk/drivers/staging/rtl8712/recv_linux.c @@ -117,8 +117,13 @@ void r8712_recv_indicatepkt(struct _adapter *padapter, if (skb == NULL) goto _recv_indicatepkt_drop; skb->data = precv_frame->u.hdr.rx_data; +#ifdef NET_SKBUFF_DATA_USES_OFFSET + skb->tail = (sk_buff_data_t)(precv_frame->u.hdr.rx_tail - + precv_frame->u.hdr.rx_head); +#else + skb->tail = (sk_buff_data_t)precv_frame->u.hdr.rx_tail; +#endif skb->len = precv_frame->u.hdr.len; - skb_set_tail_pointer(skb, skb->len); if ((pattrib->tcpchk_valid == 1) && (pattrib->tcp_chkrpt == 1)) skb->ip_summed = CHECKSUM_UNNECESSARY; else diff --git a/trunk/drivers/staging/rtl8712/rtl8712_recv.c b/trunk/drivers/staging/rtl8712/rtl8712_recv.c index c76732cdb183..8e82ce2fee38 100644 --- a/trunk/drivers/staging/rtl8712/rtl8712_recv.c +++ b/trunk/drivers/staging/rtl8712/rtl8712_recv.c @@ -374,8 +374,6 @@ static int amsdu_to_msdu(struct _adapter *padapter, union recv_frame *prframe) a_len -= ETH_HLEN; /* Allocate new skb for releasing to upper layer */ sub_skb = dev_alloc_skb(nSubframe_Length + 12); - if (!sub_skb) - break; skb_reserve(sub_skb, 12); data_ptr = (u8 *)skb_put(sub_skb, nSubframe_Length); memcpy(data_ptr, pdata, nSubframe_Length); @@ -1096,8 +1094,6 @@ static int recvbuf2recvframe(struct _adapter *padapter, struct sk_buff *pskb) precvframe->u.hdr.rx_end = pkt_copy->data + alloc_sz; } else { precvframe->u.hdr.pkt = skb_clone(pskb, GFP_ATOMIC); - if (!precvframe->u.hdr.pkt) - return _FAIL; precvframe->u.hdr.rx_head = pbuf; precvframe->u.hdr.rx_data = pbuf; precvframe->u.hdr.rx_tail = pbuf; @@ -1131,9 +1127,6 @@ static void recv_tasklet(void *priv) recvbuf2recvframe(padapter, pskb); skb_reset_tail_pointer(pskb); pskb->len = 0; - if (!skb_cloned(pskb)) - skb_queue_tail(&precvpriv->free_recv_skb_queue, pskb); - else - consume_skb(pskb); + skb_queue_tail(&precvpriv->free_recv_skb_queue, pskb); } } diff --git a/trunk/drivers/staging/rtl8712/rtl8712_recv.h b/trunk/drivers/staging/rtl8712/rtl8712_recv.h index fd9e3fc4c226..8efbd1fa035f 100644 --- a/trunk/drivers/staging/rtl8712/rtl8712_recv.h +++ b/trunk/drivers/staging/rtl8712/rtl8712_recv.h @@ -41,7 +41,7 @@ #define RECV_BLK_SZ 512 #define RECV_BLK_CNT 16 #define RECV_BLK_TH RECV_BLK_CNT -#define MAX_RECVBUF_SZ 9100 +#define MAX_RECVBUF_SZ (30720) /* 30K */ #define RECVBUFF_ALIGN_SZ 512 #define RSVD_ROOM_SZ (0) /*These definition is used for Rx packet reordering.*/ diff --git a/trunk/drivers/staging/rtl8712/rtl8712_xmit.c b/trunk/drivers/staging/rtl8712/rtl8712_xmit.c index 4e3f09420c1e..3d23514c0222 100644 --- a/trunk/drivers/staging/rtl8712/rtl8712_xmit.c +++ b/trunk/drivers/staging/rtl8712/rtl8712_xmit.c @@ -376,7 +376,7 @@ u8 r8712_dump_aggr_xframe(struct xmit_buf *pxmitbuf, { struct _adapter *padapter = pxmitframe->padapter; struct dvobj_priv *pdvobj = (struct dvobj_priv *) &padapter->dvobjpriv; - struct tx_desc *ptxdesc = (struct tx_desc *)pxmitbuf->pbuf; + struct tx_desc * ptxdesc = (struct tx_desc *)pxmitbuf->pbuf; struct cmd_hdr *pcmd_hdr = (struct cmd_hdr *) (pxmitbuf->pbuf + TXDESC_SIZE); u16 total_length = (u16) (ptxdesc->txdw0 & 0xffff); diff --git a/trunk/drivers/staging/rtl8712/rtl871x_ioctl_linux.c b/trunk/drivers/staging/rtl8712/rtl871x_ioctl_linux.c index c9a6a7fbb89c..35e781fca4a0 100644 --- a/trunk/drivers/staging/rtl8712/rtl871x_ioctl_linux.c +++ b/trunk/drivers/staging/rtl8712/rtl871x_ioctl_linux.c @@ -407,7 +407,9 @@ static int wpa_set_encryption(struct net_device *dev, struct ieee_param *param, if (param_len != (u32)((u8 *) param->u.crypt.key - (u8 *)param) + param->u.crypt.key_len) return -EINVAL; - if (is_broadcast_ether_addr(param->sta_addr)) { + if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff && + param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff && + param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) { if (param->u.crypt.idx >= WEP_KEYS) { /* for large key indices, set the default (0) */ param->u.crypt.idx = 0; diff --git a/trunk/drivers/staging/rtl8712/rtl871x_ioctl_set.c b/trunk/drivers/staging/rtl8712/rtl871x_ioctl_set.c index d3ab24e34e3d..f352b32355a0 100644 --- a/trunk/drivers/staging/rtl8712/rtl871x_ioctl_set.c +++ b/trunk/drivers/staging/rtl8712/rtl871x_ioctl_set.c @@ -131,7 +131,10 @@ u8 r8712_set_802_11_bssid(struct _adapter *padapter, u8 *bssid) u8 status = true; struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - if (is_zero_ether_addr(bssid) || is_broadcast_ether_addr(bssid)) { + if ((bssid[0] == 0x00 && bssid[1] == 0x00 && bssid[2] == 0x00 && + bssid[3] == 0x00 && bssid[4] == 0x00 && bssid[5] == 0x00) || + (bssid[0] == 0xFF && bssid[1] == 0xFF && bssid[2] == 0xFF && + bssid[3] == 0xFF && bssid[4] == 0xFF && bssid[5] == 0xFF)) { status = false; return status; } diff --git a/trunk/drivers/staging/rtl8712/rtl871x_mlme.c b/trunk/drivers/staging/rtl8712/rtl871x_mlme.c index c51ad9ed4b52..dc7adc132d12 100644 --- a/trunk/drivers/staging/rtl8712/rtl871x_mlme.c +++ b/trunk/drivers/staging/rtl8712/rtl871x_mlme.c @@ -28,8 +28,6 @@ #define _RTL871X_MLME_C_ -#include - #include "osdep_service.h" #include "drv_types.h" #include "recv_osdep.h" @@ -148,8 +146,9 @@ static struct wlan_network *_r8712_find_network(struct __queue *scanned_queue, unsigned long irqL; struct list_head *phead, *plist; struct wlan_network *pnetwork = NULL; + u8 zero_addr[ETH_ALEN] = {0, 0, 0, 0, 0, 0}; - if (is_zero_ether_addr(addr)) + if (!memcmp(zero_addr, addr, ETH_ALEN)) return NULL; spin_lock_irqsave(&scanned_queue->lock, irqL); phead = get_list_head(scanned_queue); diff --git a/trunk/drivers/staging/rtl8712/rtl871x_pwrctrl.h b/trunk/drivers/staging/rtl8712/rtl871x_pwrctrl.h index 70ff924fba04..6024c4f63d5b 100644 --- a/trunk/drivers/staging/rtl8712/rtl871x_pwrctrl.h +++ b/trunk/drivers/staging/rtl8712/rtl871x_pwrctrl.h @@ -30,7 +30,26 @@ #include "drv_types.h" +#define FW_PWR0 0 +#define FW_PWR1 1 +#define FW_PWR2 2 +#define FW_PWR3 3 + + +#define HW_PWR0 7 +#define HW_PWR1 6 +#define HW_PWR2 2 +#define HW_PWR3 0 +#define HW_PWR4 8 + +#define FW_PWRMSK 0x7 + + +#define XMIT_ALIVE BIT(0) +#define RECV_ALIVE BIT(1) #define CMD_ALIVE BIT(2) +#define EVT_ALIVE BIT(3) + enum Power_Mgnt { PS_MODE_ACTIVE = 0 , @@ -47,6 +66,7 @@ enum Power_Mgnt { PS_MODE_NUM }; + /* BIT[2:0] = HW state BIT[3] = Protocol PS state, 0: register active state, diff --git a/trunk/drivers/staging/rtl8712/rtl871x_recv.c b/trunk/drivers/staging/rtl8712/rtl871x_recv.c index 23ec684b60e1..c9d1743e5c5d 100644 --- a/trunk/drivers/staging/rtl8712/rtl871x_recv.c +++ b/trunk/drivers/staging/rtl8712/rtl871x_recv.c @@ -32,7 +32,6 @@ #include #include #include -#include #include "osdep_service.h" #include "drv_types.h" @@ -332,8 +331,8 @@ static sint sta2sta_data_frame(struct _adapter *adapter, return _FAIL; if ((memcmp(myhwaddr, pattrib->dst, ETH_ALEN)) && (!bmcast)) return _FAIL; - if (is_zero_ether_addr(pattrib->bssid) || - is_zero_ether_addr(mybssid) || + if (!memcmp(pattrib->bssid, "\x0\x0\x0\x0\x0\x0", ETH_ALEN) || + !memcmp(mybssid, "\x0\x0\x0\x0\x0\x0", ETH_ALEN) || (memcmp(pattrib->bssid, mybssid, ETH_ALEN))) return _FAIL; sta_addr = pattrib->src; @@ -410,8 +409,8 @@ static sint ap2sta_data_frame(struct _adapter *adapter, if ((memcmp(myhwaddr, pattrib->dst, ETH_ALEN)) && (!bmcast)) return _FAIL; /* check BSSID */ - if (is_zero_ether_addr(pattrib->bssid) || - is_zero_ether_addr(mybssid) || + if (!memcmp(pattrib->bssid, "\x0\x0\x0\x0\x0\x0", ETH_ALEN) || + !memcmp(mybssid, "\x0\x0\x0\x0\x0\x0", ETH_ALEN) || (memcmp(pattrib->bssid, mybssid, ETH_ALEN))) return _FAIL; if (bmcast) diff --git a/trunk/drivers/staging/rtl8712/rtl871x_security.c b/trunk/drivers/staging/rtl8712/rtl871x_security.c index e33fd6db246d..7b92927a04dc 100644 --- a/trunk/drivers/staging/rtl8712/rtl871x_security.c +++ b/trunk/drivers/staging/rtl8712/rtl871x_security.c @@ -58,7 +58,7 @@ struct arc4context { u8 state[256]; }; -static void arcfour_init(struct arc4context *parc4ctx, u8 *key, u32 key_len) +static void arcfour_init(struct arc4context *parc4ctx, u8 * key, u32 key_len) { u32 t, u; u32 keyindex; @@ -288,7 +288,7 @@ static void secmicclear(struct mic_data *pmicdata) pmicdata->M = 0; } -void r8712_secmicsetkey(struct mic_data *pmicdata, u8 *key) +void r8712_secmicsetkey(struct mic_data *pmicdata, u8 * key) { /* Set the key */ pmicdata->K0 = secmicgetuint32(key); @@ -320,7 +320,7 @@ static void secmicappendbyte(struct mic_data *pmicdata, u8 b) } } -void r8712_secmicappend(struct mic_data *pmicdata, u8 *src, u32 nbytes) +void r8712_secmicappend(struct mic_data *pmicdata, u8 * src, u32 nbytes) { /* This is simple */ while (nbytes > 0) { @@ -1368,7 +1368,7 @@ u32 r8712_aes_decrypt(struct _adapter *padapter, u8 *precvframe) precvframe)->u.hdr.attrib; struct security_priv *psecuritypriv = &padapter->securitypriv; - pframe = (unsigned char *)((union recv_frame *)precvframe)-> + pframe = (unsigned char *)((union recv_frame*)precvframe)-> u.hdr.rx_data; /* 4 start to encrypt each fragment */ if ((prxattrib->encrypt == _AES_)) { diff --git a/trunk/drivers/staging/rtl8712/usb_intf.c b/trunk/drivers/staging/rtl8712/usb_intf.c index 6b73843e580a..c758c40e0c85 100644 --- a/trunk/drivers/staging/rtl8712/usb_intf.c +++ b/trunk/drivers/staging/rtl8712/usb_intf.c @@ -37,6 +37,7 @@ #include "recv_osdep.h" #include "xmit_osdep.h" #include "rtl8712_efuse.h" +#include "usb_vendor_req.h" #include "usb_ops.h" #include "usb_osintf.h" diff --git a/trunk/drivers/staging/rtl8712/usb_osintf.h b/trunk/drivers/staging/rtl8712/usb_osintf.h index 609f9210cc46..d95797aac37a 100644 --- a/trunk/drivers/staging/rtl8712/usb_osintf.h +++ b/trunk/drivers/staging/rtl8712/usb_osintf.h @@ -28,6 +28,9 @@ #include "osdep_service.h" #include "drv_types.h" +#include "usb_vendor_req.h" + +#define USBD_HALTED(Status) ((u32)(Status) >> 30 == 3) extern char *r8712_initmac; diff --git a/trunk/drivers/staging/rtl8712/usb_vendor_req.h b/trunk/drivers/staging/rtl8712/usb_vendor_req.h new file mode 100644 index 000000000000..82335a83d0d2 --- /dev/null +++ b/trunk/drivers/staging/rtl8712/usb_vendor_req.h @@ -0,0 +1,58 @@ +/****************************************************************************** + * + * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License 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, USA + * + * Modifications for inclusion into the Linux staging tree are + * Copyright(c) 2010 Larry Finger. All rights reserved. + * + * Contact information: + * WLAN FAE + * Larry Finger + * + ******************************************************************************/ +#ifndef _USB_VENDOR_REQUEST_H_ +#define _USB_VENDOR_REQUEST_H_ + +/*4 Set/Get Register related wIndex/Data */ +#define RT_USB_RESET_MASK_OFF 0 +#define RT_USB_RESET_MASK_ON 1 +#define RT_USB_SLEEP_MASK_OFF 0 +#define RT_USB_SLEEP_MASK_ON 1 +#define RT_USB_LDO_ON 1 +#define RT_USB_LDO_OFF 0 + +/*4 Set/Get SYSCLK related wValue or Data */ +#define RT_USB_SYSCLK_32KHZ 0 +#define RT_USB_SYSCLK_40MHZ 1 +#define RT_USB_SYSCLK_60MHZ 2 + +enum RT_USB_BREQUEST { + RT_USB_SET_REGISTER = 1, + RT_USB_SET_SYSCLK = 2, + RT_USB_GET_SYSCLK = 3, + RT_USB_GET_REGISTER = 4 +}; + +enum RT_USB_WVALUE { + RT_USB_RESET_MASK = 1, + RT_USB_SLEEP_MASK = 2, + RT_USB_USB_HRCPWM = 3, + RT_USB_LDO = 4, + RT_USB_BOOT_TYPE = 5 +}; + +#endif + diff --git a/trunk/drivers/staging/rts5139/rts51x_fop.c b/trunk/drivers/staging/rts5139/rts51x_fop.c index bf1a9e64e874..e1200fe89579 100644 --- a/trunk/drivers/staging/rts5139/rts51x_fop.c +++ b/trunk/drivers/staging/rts5139/rts51x_fop.c @@ -79,7 +79,7 @@ static int rts51x_sd_direct_cmnd(struct rts51x_chip *chip, case 1: /* Read from card */ - buf = kzalloc(cmnd->buf_len, GFP_KERNEL); + buf = kmalloc(cmnd->buf_len, GFP_KERNEL); if (!buf) TRACE_RET(chip, STATUS_NOMEM); diff --git a/trunk/drivers/staging/rts5139/trace.h b/trunk/drivers/staging/rts5139/trace.h index c9dfb1ea4115..0584b8ab43ca 100644 --- a/trunk/drivers/staging/rts5139/trace.h +++ b/trunk/drivers/staging/rts5139/trace.h @@ -93,9 +93,35 @@ do { \ #endif #ifdef CONFIG_RTS5139_DEBUG -#define RTS51X_DUMP(buf, buf_len) \ - print_hex_dump(KERN_DEBUG, RTS51X_TIP, DUMP_PREFIX_NONE, \ - 16, 1, (buf), (buf_len), false) +static inline void rts51x_dump(u8 *buf, int buf_len) +{ + int i; + u8 tmp[16] = { 0 }; + u8 *_ptr = buf; + + for (i = 0; i < ((buf_len) / 16); i++) { + RTS51X_DEBUGP("%02x %02x %02x %02x %02x %02x %02x %02x " + "%02x %02x %02x %02x %02x %02x %02x %02x\n", + _ptr[0], _ptr[1], _ptr[2], _ptr[3], _ptr[4], + _ptr[5], _ptr[6], _ptr[7], _ptr[8], _ptr[9], + _ptr[10], _ptr[11], _ptr[12], _ptr[13], _ptr[14], + _ptr[15]); + _ptr += 16; + } + if ((buf_len) % 16) { + memcpy(tmp, _ptr, (buf_len) % 16); + _ptr = tmp; + RTS51X_DEBUGP("%02x %02x %02x %02x %02x %02x %02x %02x " + "%02x %02x %02x %02x %02x %02x %02x %02x\n", + _ptr[0], _ptr[1], _ptr[2], _ptr[3], _ptr[4], + _ptr[5], _ptr[6], _ptr[7], _ptr[8], _ptr[9], + _ptr[10], _ptr[11], _ptr[12], _ptr[13], _ptr[14], + _ptr[15]); + } +} + +#define RTS51X_DUMP(buf, buf_len) \ + rts51x_dump((u8 *)(buf), (buf_len)) #define CATCH_TRIGGER(chip) \ do { \ diff --git a/trunk/drivers/staging/rts_pstor/ms.c b/trunk/drivers/staging/rts_pstor/ms.c index 16a5c16fb6ab..7cc2b53f20d0 100644 --- a/trunk/drivers/staging/rts_pstor/ms.c +++ b/trunk/drivers/staging/rts_pstor/ms.c @@ -109,8 +109,9 @@ static int ms_transfer_data(struct rtsx_chip *chip, u8 trans_mode, u8 tpc, u16 s u8 val, err_code = 0; enum dma_data_direction dir; - if (!buf || !buf_len) + if (!buf || !buf_len) { TRACE_RET(chip, STATUS_FAIL); + } if (trans_mode == MS_TM_AUTO_READ) { dir = DMA_FROM_DEVICE; @@ -150,17 +151,18 @@ static int ms_transfer_data(struct rtsx_chip *chip, u8 trans_mode, u8 tpc, u16 s use_sg, dir, chip->mspro_timeout); if (retval < 0) { ms_set_err_code(chip, err_code); - if (retval == -ETIMEDOUT) + if (retval == -ETIMEDOUT) { retval = STATUS_TIMEDOUT; - else + } else { retval = STATUS_FAIL; - + } TRACE_RET(chip, retval); } RTSX_READ_REG(chip, MS_TRANS_CFG, &val); - if (val & (MS_INT_CMDNK | MS_INT_ERR | MS_CRC16_ERR | MS_RDY_TIMEOUT)) + if (val & (MS_INT_CMDNK | MS_INT_ERR | MS_CRC16_ERR | MS_RDY_TIMEOUT)) { TRACE_RET(chip, STATUS_FAIL); + } return STATUS_SUCCESS; } @@ -171,8 +173,9 @@ static int ms_write_bytes(struct rtsx_chip *chip, struct ms_info *ms_card = &(chip->ms_card); int retval, i; - if (!data || (data_len < cnt)) + if (!data || (data_len < cnt)) { TRACE_RET(chip, STATUS_ERROR); + } rtsx_init_cmd(chip); @@ -180,8 +183,9 @@ static int ms_write_bytes(struct rtsx_chip *chip, rtsx_add_cmd(chip, WRITE_REG_CMD, PPBUF_BASE2 + i, 0xFF, data[i]); } - if (cnt % 2) + if (cnt % 2) { rtsx_add_cmd(chip, WRITE_REG_CMD, PPBUF_BASE2 + i, 0xFF, 0xFF); + } rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TPC, 0xFF, tpc); rtsx_add_cmd(chip, WRITE_REG_CMD, MS_BYTE_CNT, 0xFF, cnt); @@ -234,8 +238,9 @@ static int ms_read_bytes(struct rtsx_chip *chip, u8 tpc, u8 cnt, u8 cfg, u8 *dat int retval, i; u8 *ptr; - if (!data) + if (!data) { TRACE_RET(chip, STATUS_ERROR); + } rtsx_init_cmd(chip); @@ -247,13 +252,14 @@ static int ms_read_bytes(struct rtsx_chip *chip, u8 tpc, u8 cnt, u8 cfg, u8 *dat rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TRANSFER, 0xFF, MS_TRANSFER_START | MS_TM_READ_BYTES); rtsx_add_cmd(chip, CHECK_REG_CMD, MS_TRANSFER, MS_TRANSFER_END, MS_TRANSFER_END); - for (i = 0; i < data_len - 1; i++) + for (i = 0; i < data_len - 1; i++) { rtsx_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2 + i, 0, 0); - - if (data_len % 2) + } + if (data_len % 2) { rtsx_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2 + data_len, 0, 0); - else + } else { rtsx_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2 + data_len - 1, 0, 0); + } retval = rtsx_send_cmd(chip, MS_CARD, 5000); if (retval < 0) { @@ -287,8 +293,9 @@ static int ms_read_bytes(struct rtsx_chip *chip, u8 tpc, u8 cnt, u8 cfg, u8 *dat ptr = rtsx_get_cmd_data(chip) + 1; - for (i = 0; i < data_len; i++) + for (i = 0; i < data_len; i++) { data[i] = ptr[i]; + } if ((tpc == PRO_READ_SHORT_DATA) && (data_len == 8)) { RTSX_DEBUGP("Read format progress:\n"); @@ -336,31 +343,34 @@ static int ms_set_init_para(struct rtsx_chip *chip) int retval; if (CHK_HG8BIT(ms_card)) { - if (chip->asic_code) + if (chip->asic_code) { ms_card->ms_clock = chip->asic_ms_hg_clk; - else + } else { ms_card->ms_clock = chip->fpga_ms_hg_clk; - + } } else if (CHK_MSPRO(ms_card) || CHK_MS4BIT(ms_card)) { - if (chip->asic_code) + if (chip->asic_code) { ms_card->ms_clock = chip->asic_ms_4bit_clk; - else + } else { ms_card->ms_clock = chip->fpga_ms_4bit_clk; - + } } else { - if (chip->asic_code) + if (chip->asic_code) { ms_card->ms_clock = chip->asic_ms_1bit_clk; - else + } else { ms_card->ms_clock = chip->fpga_ms_1bit_clk; + } } retval = switch_clock(chip, ms_card->ms_clock); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } retval = select_card(chip, MS_CARD); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } return STATUS_SUCCESS; } @@ -371,12 +381,14 @@ static int ms_switch_clock(struct rtsx_chip *chip) int retval; retval = select_card(chip, MS_CARD); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } retval = switch_clock(chip, ms_card->ms_clock); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } return STATUS_SUCCESS; } @@ -449,8 +461,9 @@ static int ms_pull_ctl_enable(struct rtsx_chip *chip) } retval = rtsx_send_cmd(chip, MS_CARD, 100); - if (retval < 0) + if (retval < 0) { TRACE_RET(chip, STATUS_FAIL); + } return STATUS_SUCCESS; } @@ -469,37 +482,40 @@ static int ms_prepare_reset(struct rtsx_chip *chip) ms_card->pro_under_formatting = 0; retval = ms_power_off_card3v3(chip); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } if (!chip->ft2_fast_mode) wait_timeout(250); retval = enable_card_clock(chip, MS_CARD); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } if (chip->asic_code) { retval = ms_pull_ctl_enable(chip); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } } else { RTSX_WRITE_REG(chip, FPGA_PULL_CTL, FPGA_MS_PULL_CTL_BIT | 0x20, 0); } if (!chip->ft2_fast_mode) { retval = card_power_on(chip, MS_CARD); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); - + } wait_timeout(150); #ifdef SUPPORT_OCP - if (CHECK_LUN_MODE(chip, SD_MS_2LUN)) + if (CHECK_LUN_MODE(chip, SD_MS_2LUN)) { oc_mask = MS_OC_NOW | MS_OC_EVER; - else + } else { oc_mask = SD_OC_NOW | SD_OC_EVER; - + } if (chip->ocp_stat & oc_mask) { RTSX_DEBUGP("Over current, OCPSTAT is 0x%x\n", chip->ocp_stat); @@ -523,8 +539,9 @@ static int ms_prepare_reset(struct rtsx_chip *chip) RTSX_WRITE_REG(chip, CARD_STOP, MS_STOP | MS_CLR_ERR, MS_STOP | MS_CLR_ERR); retval = ms_set_init_para(chip); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } return STATUS_SUCCESS; } @@ -536,23 +553,26 @@ static int ms_identify_media_type(struct rtsx_chip *chip, int switch_8bit_bus) u8 val; retval = ms_set_rw_reg_addr(chip, Pro_StatusReg, 6, SystemParm, 1); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } for (i = 0; i < MS_MAX_RETRY_COUNT; i++) { retval = ms_transfer_tpc(chip, MS_TM_READ_BYTES, READ_REG, 6, NO_WAIT_INT); - if (retval == STATUS_SUCCESS) + if (retval == STATUS_SUCCESS) { break; + } } - if (i == MS_MAX_RETRY_COUNT) + if (i == MS_MAX_RETRY_COUNT) { TRACE_RET(chip, STATUS_FAIL); + } RTSX_READ_REG(chip, PPBUF_BASE2 + 2, &val); RTSX_DEBUGP("Type register: 0x%x\n", val); if (val != 0x01) { - if (val != 0x02) + if (val != 0x02) { ms_card->check_ms_flow = 1; - + } TRACE_RET(chip, STATUS_FAIL); } @@ -567,11 +587,11 @@ static int ms_identify_media_type(struct rtsx_chip *chip, int switch_8bit_bus) RTSX_DEBUGP("Class register: 0x%x\n", val); if (val == 0) { RTSX_READ_REG(chip, PPBUF_BASE2, &val); - if (val & WRT_PRTCT) + if (val & WRT_PRTCT) { chip->card_wp |= MS_CARD; - else + } else { chip->card_wp &= ~MS_CARD; - + } } else if ((val == 0x01) || (val == 0x02) || (val == 0x03)) { chip->card_wp |= MS_CARD; } else { @@ -586,11 +606,11 @@ static int ms_identify_media_type(struct rtsx_chip *chip, int switch_8bit_bus) if (val == 0) { ms_card->ms_type &= 0x0F; } else if (val == 7) { - if (switch_8bit_bus) + if (switch_8bit_bus) { ms_card->ms_type |= MS_HG; - else + } else { ms_card->ms_type &= 0x0F; - + } } else { TRACE_RET(chip, STATUS_FAIL); } @@ -613,15 +633,17 @@ static int ms_confirm_cpu_startup(struct rtsx_chip *chip) for (i = 0; i < MS_MAX_RETRY_COUNT; i++) { retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, &val, 1); - if (retval == STATUS_SUCCESS) + if (retval == STATUS_SUCCESS) { break; + } } - if (i == MS_MAX_RETRY_COUNT) + if (i == MS_MAX_RETRY_COUNT) { TRACE_RET(chip, STATUS_FAIL); + } - if (k > 100) + if (k > 100) { TRACE_RET(chip, STATUS_FAIL); - + } k++; wait_timeout(100); } while (!(val & INT_REG_CED)); @@ -631,14 +653,16 @@ static int ms_confirm_cpu_startup(struct rtsx_chip *chip) if (retval == STATUS_SUCCESS) break; } - if (i == MS_MAX_RETRY_COUNT) + if (i == MS_MAX_RETRY_COUNT) { TRACE_RET(chip, STATUS_FAIL); + } if (val & INT_REG_ERR) { - if (val & INT_REG_CMDNK) + if (val & INT_REG_CMDNK) { chip->card_wp |= (MS_CARD); - else + } else { TRACE_RET(chip, STATUS_FAIL); + } } /* -- end confirm CPU startup */ @@ -657,8 +681,9 @@ static int ms_switch_parallel_bus(struct rtsx_chip *chip) if (retval == STATUS_SUCCESS) break; } - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } return STATUS_SUCCESS; } @@ -673,22 +698,26 @@ static int ms_switch_8bit_bus(struct rtsx_chip *chip) data[1] = 0; for (i = 0; i < MS_MAX_RETRY_COUNT; i++) { retval = ms_write_bytes(chip, WRITE_REG, 1, NO_WAIT_INT, data, 2); - if (retval == STATUS_SUCCESS) + if (retval == STATUS_SUCCESS) { break; + } } - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } RTSX_WRITE_REG(chip, MS_CFG, 0x98, MS_BUS_WIDTH_8 | SAMPLE_TIME_FALLING); ms_card->ms_type |= MS_8BIT; retval = ms_set_init_para(chip); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } for (i = 0; i < MS_MAX_RETRY_COUNT; i++) { retval = ms_transfer_tpc(chip, MS_TM_READ_BYTES, GET_INT, 1, NO_WAIT_INT); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } } return STATUS_SUCCESS; @@ -701,16 +730,19 @@ static int ms_pro_reset_flow(struct rtsx_chip *chip, int switch_8bit_bus) for (i = 0; i < 3; i++) { retval = ms_prepare_reset(chip); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } retval = ms_identify_media_type(chip, switch_8bit_bus); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } retval = ms_confirm_cpu_startup(chip); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } retval = ms_switch_parallel_bus(chip); if (retval != STATUS_SUCCESS) { @@ -724,16 +756,18 @@ static int ms_pro_reset_flow(struct rtsx_chip *chip, int switch_8bit_bus) } } - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } /* Switch MS-PRO into Parallel mode */ RTSX_WRITE_REG(chip, MS_CFG, 0x18, MS_BUS_WIDTH_4); RTSX_WRITE_REG(chip, MS_CFG, PUSH_TIME_ODD, PUSH_TIME_ODD); retval = ms_set_init_para(chip); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } /* If MSPro HG Card, We shall try to switch to 8-bit bus */ if (CHK_MSHG(ms_card) && chip->support_ms_8bit && switch_8bit_bus) { @@ -756,8 +790,9 @@ static int msxc_change_power(struct rtsx_chip *chip, u8 mode) ms_cleanup_work(chip); retval = ms_set_rw_reg_addr(chip, 0, 0, Pro_DataCount1, 6); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } buf[0] = 0; buf[1] = mode; @@ -767,16 +802,19 @@ static int msxc_change_power(struct rtsx_chip *chip, u8 mode) buf[5] = 0; retval = ms_write_bytes(chip, PRO_WRITE_REG , 6, NO_WAIT_INT, buf, 6); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } retval = ms_send_cmd(chip, XC_CHG_POWER, WAIT_INT); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } RTSX_READ_REG(chip, MS_TRANS_CFG, buf); - if (buf[0] & (MS_INT_CMDNK | MS_INT_ERR)) + if (buf[0] & (MS_INT_CMDNK | MS_INT_ERR)) { TRACE_RET(chip, STATUS_FAIL); + } return STATUS_SUCCESS; } @@ -798,14 +836,15 @@ static int ms_read_attribute_info(struct rtsx_chip *chip) #endif retval = ms_set_rw_reg_addr(chip, Pro_IntReg, 2, Pro_SystemParm, 7); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } - if (CHK_MS8BIT(ms_card)) + if (CHK_MS8BIT(ms_card)) { data[0] = PARALLEL_8BIT_IF; - else + } else { data[0] = PARALLEL_4BIT_IF; - + } data[1] = 0; data[2] = 0x40; @@ -817,21 +856,24 @@ static int ms_read_attribute_info(struct rtsx_chip *chip) for (i = 0; i < MS_MAX_RETRY_COUNT; i++) { retval = ms_write_bytes(chip, PRO_WRITE_REG, 7, NO_WAIT_INT, data, 8); - if (retval == STATUS_SUCCESS) + if (retval == STATUS_SUCCESS) { break; + } } - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } buf = kmalloc(64 * 512, GFP_KERNEL); - if (buf == NULL) + if (buf == NULL) { TRACE_RET(chip, STATUS_ERROR); + } for (i = 0; i < MS_MAX_RETRY_COUNT; i++) { retval = ms_send_cmd(chip, PRO_READ_ATRB, WAIT_INT); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { continue; - + } retval = rtsx_read_register(chip, MS_TRANS_CFG, &val); if (retval != STATUS_SUCCESS) { kfree(buf); @@ -843,10 +885,11 @@ static int ms_read_attribute_info(struct rtsx_chip *chip) } retval = ms_transfer_data(chip, MS_TM_AUTO_READ, PRO_READ_LONG_DATA, 0x40, WAIT_INT, 0, 0, buf, 64 * 512); - if (retval == STATUS_SUCCESS) + if (retval == STATUS_SUCCESS) { break; - else + } else { rtsx_clear_ms_error(chip); + } } if (retval != STATUS_SUCCESS) { kfree(buf); @@ -920,8 +963,9 @@ static int ms_read_attribute_info(struct rtsx_chip *chip) } #ifdef SUPPORT_MSXC - if (buf[cur_addr_off + 8] == 0x13) + if (buf[cur_addr_off + 8] == 0x13) { ms_card->ms_type |= MS_XC; + } #endif #ifdef SUPPORT_PCGL_1P18 found_sys_info = 1; @@ -1002,15 +1046,18 @@ static int ms_read_attribute_info(struct rtsx_chip *chip) #ifdef SUPPORT_MSXC if (CHK_MSXC(ms_card)) { - if (class_code != 0x03) + if (class_code != 0x03) { TRACE_RET(chip, STATUS_FAIL); + } } else { - if (class_code != 0x02) + if (class_code != 0x02) { TRACE_RET(chip, STATUS_FAIL); + } } #else - if (class_code != 0x02) + if (class_code != 0x02) { TRACE_RET(chip, STATUS_FAIL); + } #endif if (device_type != 0x00) { @@ -1022,8 +1069,9 @@ static int ms_read_attribute_info(struct rtsx_chip *chip) } } - if (sub_class & 0xC0) + if (sub_class & 0xC0) { TRACE_RET(chip, STATUS_FAIL); + } RTSX_DEBUGP("class_code: 0x%x, device_type: 0x%x, sub_class: 0x%x\n", class_code, device_type, sub_class); @@ -1069,20 +1117,23 @@ static int reset_ms_pro(struct rtsx_chip *chip) if (retval != STATUS_SUCCESS) { if (ms_card->switch_8bit_fail) { retval = ms_pro_reset_flow(chip, 0); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } } else { TRACE_RET(chip, STATUS_FAIL); } } retval = ms_read_attribute_info(chip); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } #ifdef XC_POWERCLASS - if (CHK_HG8BIT(ms_card)) + if (CHK_HG8BIT(ms_card)) { change_power_class = 0; + } if (change_power_class && CHK_MSXC(ms_card)) { u8 power_class_en = chip->ms_power_class_en; @@ -1090,10 +1141,11 @@ static int reset_ms_pro(struct rtsx_chip *chip) RTSX_DEBUGP("power_class_en = 0x%x\n", power_class_en); RTSX_DEBUGP("change_power_class = %d\n", change_power_class); - if (change_power_class) + if (change_power_class) { power_class_en &= (1 << (change_power_class - 1)); - else + } else { power_class_en = 0; + } if (power_class_en) { u8 power_class_mode = (ms_card->raw_sys_info[46] & 0x18) >> 3; @@ -1113,14 +1165,16 @@ static int reset_ms_pro(struct rtsx_chip *chip) #ifdef SUPPORT_MAGIC_GATE retval = mg_set_tpc_para_sub(chip, 0, 0); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } #endif - if (CHK_HG8BIT(ms_card)) + if (CHK_HG8BIT(ms_card)) { chip->card_bus_width[chip->card2lun[MS_CARD]] = 8; - else + } else { chip->card_bus_width[chip->card2lun[MS_CARD]] = 4; + } return STATUS_SUCCESS; } @@ -1131,12 +1185,14 @@ static int ms_read_status_reg(struct rtsx_chip *chip) u8 val[2]; retval = ms_set_rw_reg_addr(chip, StatusReg0, 2, 0, 0); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } retval = ms_read_bytes(chip, READ_REG, 2, NO_WAIT_INT, val, 2); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } if (val[1] & (STS_UCDT | STS_UCEX | STS_UCFG)) { ms_set_err_code(chip, MS_FLASH_READ_ERROR); @@ -1155,8 +1211,9 @@ static int ms_read_extra_data(struct rtsx_chip *chip, u8 val, data[10]; retval = ms_set_rw_reg_addr(chip, OverwriteFlag, MS_EXTRA_SIZE, SystemParm, 6); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } if (CHK_MS4BIT(ms_card)) { /* Parallel interface */ @@ -1176,8 +1233,9 @@ static int ms_read_extra_data(struct rtsx_chip *chip, if (retval == STATUS_SUCCESS) break; } - if (i == MS_MAX_RETRY_COUNT) + if (i == MS_MAX_RETRY_COUNT) { TRACE_RET(chip, STATUS_FAIL); + } ms_set_err_code(chip, MS_NO_ERROR); @@ -1186,14 +1244,15 @@ static int ms_read_extra_data(struct rtsx_chip *chip, if (retval == STATUS_SUCCESS) break; } - if (i == MS_MAX_RETRY_COUNT) + if (i == MS_MAX_RETRY_COUNT) { TRACE_RET(chip, STATUS_FAIL); + } ms_set_err_code(chip, MS_NO_ERROR); retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, &val, 1); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); - + } if (val & INT_REG_CMDNK) { ms_set_err_code(chip, MS_CMD_NK); TRACE_RET(chip, STATUS_FAIL); @@ -1201,18 +1260,20 @@ static int ms_read_extra_data(struct rtsx_chip *chip, if (val & INT_REG_CED) { if (val & INT_REG_ERR) { retval = ms_read_status_reg(chip); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); - + } retval = ms_set_rw_reg_addr(chip, OverwriteFlag, MS_EXTRA_SIZE, SystemParm, 6); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } } } retval = ms_read_bytes(chip, READ_REG, MS_EXTRA_SIZE, NO_WAIT_INT, data, MS_EXTRA_SIZE); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } if (buf && buf_len) { if (buf_len > MS_EXTRA_SIZE) @@ -1230,40 +1291,45 @@ static int ms_write_extra_data(struct rtsx_chip *chip, int retval, i; u8 val, data[16]; - if (!buf || (buf_len < MS_EXTRA_SIZE)) + if (!buf || (buf_len < MS_EXTRA_SIZE)) { TRACE_RET(chip, STATUS_FAIL); + } retval = ms_set_rw_reg_addr(chip, OverwriteFlag, MS_EXTRA_SIZE, SystemParm, 6 + MS_EXTRA_SIZE); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } - if (CHK_MS4BIT(ms_card)) + if (CHK_MS4BIT(ms_card)) { data[0] = 0x88; - else + } else { data[0] = 0x80; - + } data[1] = 0; data[2] = (u8)(block_addr >> 8); data[3] = (u8)block_addr; data[4] = 0x40; data[5] = page_num; - for (i = 6; i < MS_EXTRA_SIZE + 6; i++) + for (i = 6; i < MS_EXTRA_SIZE + 6; i++) { data[i] = buf[i - 6]; + } retval = ms_write_bytes(chip, WRITE_REG , (6+MS_EXTRA_SIZE), NO_WAIT_INT, data, 16); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } retval = ms_send_cmd(chip, BLOCK_WRITE, WAIT_INT); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } ms_set_err_code(chip, MS_NO_ERROR); retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, &val, 1); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); - + } if (val & INT_REG_CMDNK) { ms_set_err_code(chip, MS_CMD_NK); TRACE_RET(chip, STATUS_FAIL); @@ -1286,14 +1352,15 @@ static int ms_read_page(struct rtsx_chip *chip, u16 block_addr, u8 page_num) u8 val, data[6]; retval = ms_set_rw_reg_addr(chip, OverwriteFlag, MS_EXTRA_SIZE, SystemParm, 6); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } - if (CHK_MS4BIT(ms_card)) + if (CHK_MS4BIT(ms_card)) { data[0] = 0x88; - else + } else { data[0] = 0x80; - + } data[1] = 0; data[2] = (u8)(block_addr >> 8); data[3] = (u8)block_addr; @@ -1301,18 +1368,20 @@ static int ms_read_page(struct rtsx_chip *chip, u16 block_addr, u8 page_num) data[5] = page_num; retval = ms_write_bytes(chip, WRITE_REG , 6, NO_WAIT_INT, data, 6); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } retval = ms_send_cmd(chip, BLOCK_READ, WAIT_INT); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } ms_set_err_code(chip, MS_NO_ERROR); retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, &val, 1); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); - + } if (val & INT_REG_CMDNK) { ms_set_err_code(chip, MS_CMD_NK); TRACE_RET(chip, STATUS_FAIL); @@ -1325,9 +1394,9 @@ static int ms_read_page(struct rtsx_chip *chip, u16 block_addr, u8 page_num) TRACE_RET(chip, STATUS_FAIL); } retval = ms_read_status_reg(chip); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { ms_set_err_code(chip, MS_FLASH_WRITE_ERROR); - + } } else { if (!(val & INT_REG_BREQ)) { ms_set_err_code(chip, MS_BREQ_ERROR); @@ -1337,11 +1406,13 @@ static int ms_read_page(struct rtsx_chip *chip, u16 block_addr, u8 page_num) } retval = ms_transfer_tpc(chip, MS_TM_NORMAL_READ, READ_PAGE_DATA, 0, NO_WAIT_INT); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } - if (ms_check_err_code(chip, MS_FLASH_WRITE_ERROR)) + if (ms_check_err_code(chip, MS_FLASH_WRITE_ERROR)) { TRACE_RET(chip, STATUS_FAIL); + } return STATUS_SUCCESS; } @@ -1354,20 +1425,22 @@ static int ms_set_bad_block(struct rtsx_chip *chip, u16 phy_blk) u8 val, data[8], extra[MS_EXTRA_SIZE]; retval = ms_read_extra_data(chip, phy_blk, 0, extra, MS_EXTRA_SIZE); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } retval = ms_set_rw_reg_addr(chip, OverwriteFlag, MS_EXTRA_SIZE, SystemParm, 7); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } ms_set_err_code(chip, MS_NO_ERROR); - if (CHK_MS4BIT(ms_card)) + if (CHK_MS4BIT(ms_card)) { data[0] = 0x88; - else + } else { data[0] = 0x80; - + } data[1] = 0; data[2] = (u8)(phy_blk >> 8); data[3] = (u8)phy_blk; @@ -1377,17 +1450,20 @@ static int ms_set_bad_block(struct rtsx_chip *chip, u16 phy_blk) data[7] = 0xFF; retval = ms_write_bytes(chip, WRITE_REG , 7, NO_WAIT_INT, data, 7); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } retval = ms_send_cmd(chip, BLOCK_WRITE, WAIT_INT); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } ms_set_err_code(chip, MS_NO_ERROR); retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, &val, 1); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } if (val & INT_REG_CMDNK) { ms_set_err_code(chip, MS_CMD_NK); @@ -1412,16 +1488,17 @@ static int ms_erase_block(struct rtsx_chip *chip, u16 phy_blk) u8 val, data[6]; retval = ms_set_rw_reg_addr(chip, OverwriteFlag, MS_EXTRA_SIZE, SystemParm, 6); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } ms_set_err_code(chip, MS_NO_ERROR); - if (CHK_MS4BIT(ms_card)) + if (CHK_MS4BIT(ms_card)) { data[0] = 0x88; - else + } else { data[0] = 0x80; - + } data[1] = 0; data[2] = (u8)(phy_blk >> 8); data[3] = (u8)phy_blk; @@ -1429,18 +1506,21 @@ static int ms_erase_block(struct rtsx_chip *chip, u16 phy_blk) data[5] = 0; retval = ms_write_bytes(chip, WRITE_REG, 6, NO_WAIT_INT, data, 6); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } ERASE_RTY: retval = ms_send_cmd(chip, BLOCK_ERASE, WAIT_INT); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } ms_set_err_code(chip, MS_NO_ERROR); retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, &val, 1); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } if (val & INT_REG_CMDNK) { if (i < 3) { @@ -1466,8 +1546,9 @@ static int ms_erase_block(struct rtsx_chip *chip, u16 phy_blk) static void ms_set_page_status(u16 log_blk, u8 type, u8 *extra, int extra_len) { - if (!extra || (extra_len < MS_EXTRA_SIZE)) + if (!extra || (extra_len < MS_EXTRA_SIZE)) { return; + } memset(extra, 0xFF, MS_EXTRA_SIZE); @@ -1502,8 +1583,9 @@ static int ms_init_page(struct rtsx_chip *chip, u16 phy_blk, u16 log_blk, u8 sta } retval = ms_write_extra_data(chip, phy_blk, i, extra, MS_EXTRA_SIZE); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } } return STATUS_SUCCESS; @@ -1521,23 +1603,27 @@ static int ms_copy_page(struct rtsx_chip *chip, u16 old_blk, u16 new_blk, RTSX_DEBUGP("start_page = %d, end_page = %d\n", start_page, end_page); retval = ms_read_extra_data(chip, new_blk, 0, extra, MS_EXTRA_SIZE); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } retval = ms_read_status_reg(chip); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } RTSX_READ_REG(chip, PPBUF_BASE2, &val); if (val & BUF_FULL) { retval = ms_send_cmd(chip, CLEAR_BUF, WAIT_INT); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, &val, 1); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } if (!(val & INT_REG_CED)) { ms_set_err_code(chip, MS_FLASH_WRITE_ERROR); @@ -1554,16 +1640,17 @@ static int ms_copy_page(struct rtsx_chip *chip, u16 old_blk, u16 new_blk, ms_read_extra_data(chip, old_blk, i, extra, MS_EXTRA_SIZE); retval = ms_set_rw_reg_addr(chip, OverwriteFlag, MS_EXTRA_SIZE, SystemParm, 6); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } ms_set_err_code(chip, MS_NO_ERROR); - if (CHK_MS4BIT(ms_card)) + if (CHK_MS4BIT(ms_card)) { data[0] = 0x88; - else + } else { data[0] = 0x80; - + } data[1] = 0; data[2] = (u8)(old_blk >> 8); data[3] = (u8)old_blk; @@ -1571,17 +1658,20 @@ static int ms_copy_page(struct rtsx_chip *chip, u16 old_blk, u16 new_blk, data[5] = i; retval = ms_write_bytes(chip, WRITE_REG , 6, NO_WAIT_INT, data, 6); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } retval = ms_send_cmd(chip, BLOCK_READ, WAIT_INT); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } ms_set_err_code(chip, MS_NO_ERROR); retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, &val, 1); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } if (val & INT_REG_CMDNK) { ms_set_err_code(chip, MS_CMD_NK); @@ -1599,14 +1689,15 @@ static int ms_copy_page(struct rtsx_chip *chip, u16 old_blk, u16 new_blk, } retval = ms_transfer_tpc(chip, MS_TM_NORMAL_READ, READ_PAGE_DATA, 0, NO_WAIT_INT); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } if (uncorrect_flag) { ms_set_page_status(log_blk, setPS_NG, extra, MS_EXTRA_SIZE); - if (i == 0) + if (i == 0) { extra[0] &= 0xEF; - + } ms_write_extra_data(chip, old_blk, i, extra, MS_EXTRA_SIZE); RTSX_DEBUGP("page %d : extra[0] = 0x%x\n", i, extra[0]); MS_SET_BAD_BLOCK_FLG(ms_card); @@ -1619,11 +1710,13 @@ static int ms_copy_page(struct rtsx_chip *chip, u16 old_blk, u16 new_blk, for (rty_cnt = 0; rty_cnt < MS_MAX_RETRY_COUNT; rty_cnt++) { retval = ms_transfer_tpc(chip, MS_TM_NORMAL_WRITE, WRITE_PAGE_DATA, 0, NO_WAIT_INT); - if (retval == STATUS_SUCCESS) + if (retval == STATUS_SUCCESS) { break; + } } - if (rty_cnt == MS_MAX_RETRY_COUNT) + if (rty_cnt == MS_MAX_RETRY_COUNT) { TRACE_RET(chip, STATUS_FAIL); + } } if (!(val & INT_REG_BREQ)) { @@ -1637,41 +1730,45 @@ static int ms_copy_page(struct rtsx_chip *chip, u16 old_blk, u16 new_blk, ms_set_err_code(chip, MS_NO_ERROR); - if (CHK_MS4BIT(ms_card)) + if (CHK_MS4BIT(ms_card)) { data[0] = 0x88; - else + } else { data[0] = 0x80; - + } data[1] = 0; data[2] = (u8)(new_blk >> 8); data[3] = (u8)new_blk; data[4] = 0x20; data[5] = i; - if ((extra[0] & 0x60) != 0x60) + if ((extra[0] & 0x60) != 0x60) { data[6] = extra[0]; - else + } else { data[6] = 0xF8; - + } data[6 + 1] = 0xFF; data[6 + 2] = (u8)(log_blk >> 8); data[6 + 3] = (u8)log_blk; - for (j = 4; j <= MS_EXTRA_SIZE; j++) + for (j = 4; j <= MS_EXTRA_SIZE; j++) { data[6 + j] = 0xFF; + } retval = ms_write_bytes(chip, WRITE_REG, (6 + MS_EXTRA_SIZE), NO_WAIT_INT, data, 16); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } retval = ms_send_cmd(chip, BLOCK_WRITE, WAIT_INT); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } ms_set_err_code(chip, MS_NO_ERROR); retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, &val, 1); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } if (val & INT_REG_CMDNK) { ms_set_err_code(chip, MS_CMD_NK); @@ -1687,16 +1784,17 @@ static int ms_copy_page(struct rtsx_chip *chip, u16 old_blk, u16 new_blk, if (i == 0) { retval = ms_set_rw_reg_addr(chip, OverwriteFlag, MS_EXTRA_SIZE, SystemParm, 7); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } ms_set_err_code(chip, MS_NO_ERROR); - if (CHK_MS4BIT(ms_card)) + if (CHK_MS4BIT(ms_card)) { data[0] = 0x88; - else + } else { data[0] = 0x80; - + } data[1] = 0; data[2] = (u8)(old_blk >> 8); data[3] = (u8)old_blk; @@ -1706,17 +1804,20 @@ static int ms_copy_page(struct rtsx_chip *chip, u16 old_blk, u16 new_blk, data[7] = 0xFF; retval = ms_write_bytes(chip, WRITE_REG, 7, NO_WAIT_INT, data, 8); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } retval = ms_send_cmd(chip, BLOCK_WRITE, WAIT_INT); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } ms_set_err_code(chip, MS_NO_ERROR); retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, &val, 1); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } if (val & INT_REG_CMDNK) { ms_set_err_code(chip, MS_CMD_NK); @@ -1747,24 +1848,28 @@ static int reset_ms(struct rtsx_chip *chip) #endif retval = ms_prepare_reset(chip); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } ms_card->ms_type |= TYPE_MS; retval = ms_send_cmd(chip, MS_RESET, NO_WAIT_INT); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } retval = ms_read_status_reg(chip); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } RTSX_READ_REG(chip, PPBUF_BASE2, &val); - if (val & WRT_PRTCT) + if (val & WRT_PRTCT) { chip->card_wp |= MS_CARD; - else + } else { chip->card_wp &= ~MS_CARD; + } i = 0; @@ -1808,18 +1913,21 @@ static int reset_ms(struct rtsx_chip *chip) } retval = ms_read_page(chip, ms_card->boot_block, 0); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } /* Read MS system information as sys_info */ rtsx_init_cmd(chip); - for (i = 0; i < 96; i++) + for (i = 0; i < 96; i++) { rtsx_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2 + 0x1A0 + i, 0, 0); + } retval = rtsx_send_cmd(chip, MS_CARD, 100); - if (retval < 0) + if (retval < 0) { TRACE_RET(chip, STATUS_FAIL); + } ptr = rtsx_get_cmd_data(chip); memcpy(ms_card->raw_sys_info, ptr, 96); @@ -1830,18 +1938,21 @@ static int reset_ms(struct rtsx_chip *chip) rtsx_add_cmd(chip, READ_REG_CMD, HEADER_ID0, 0, 0); rtsx_add_cmd(chip, READ_REG_CMD, HEADER_ID1, 0, 0); - for (reg_addr = DISABLED_BLOCK0; reg_addr <= DISABLED_BLOCK3; reg_addr++) + for (reg_addr = DISABLED_BLOCK0; reg_addr <= DISABLED_BLOCK3; reg_addr++) { rtsx_add_cmd(chip, READ_REG_CMD, reg_addr, 0, 0); + } - for (reg_addr = BLOCK_SIZE_0; reg_addr <= PAGE_SIZE_1; reg_addr++) + for (reg_addr = BLOCK_SIZE_0; reg_addr <= PAGE_SIZE_1; reg_addr++) { rtsx_add_cmd(chip, READ_REG_CMD, reg_addr, 0, 0); + } rtsx_add_cmd(chip, READ_REG_CMD, MS_Device_Type, 0, 0); rtsx_add_cmd(chip, READ_REG_CMD, MS_4bit_Support, 0, 0); retval = rtsx_send_cmd(chip, MS_CARD, 100); - if (retval < 0) + if (retval < 0) { TRACE_RET(chip, STATUS_FAIL); + } ptr = rtsx_get_cmd_data(chip); @@ -1864,8 +1975,9 @@ static int reset_ms(struct rtsx_chip *chip) goto RE_SEARCH; } - if ((ptr[14] == 1) || (ptr[14] == 3)) + if ((ptr[14] == 1) || (ptr[14] == 3)) { chip->card_wp |= MS_CARD; + } /* BLOCK_SIZE_0, BLOCK_SIZE_1 */ block_size = ((u16)ptr[6] << 8) | ptr[7]; @@ -1914,15 +2026,17 @@ static int reset_ms(struct rtsx_chip *chip) /* Switch I/F Mode */ if (ptr[15]) { retval = ms_set_rw_reg_addr(chip, 0, 0, SystemParm, 1); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } RTSX_WRITE_REG(chip, PPBUF_BASE2, 0xFF, 0x88); RTSX_WRITE_REG(chip, PPBUF_BASE2 + 1, 0xFF, 0); retval = ms_transfer_tpc(chip, MS_TM_WRITE_BYTES, WRITE_REG , 1, NO_WAIT_INT); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } RTSX_WRITE_REG(chip, MS_CFG, 0x58 | MS_NO_CHECK_INT, MS_BUS_WIDTH_4 | PUSH_TIME_ODD | MS_NO_CHECK_INT); @@ -1930,10 +2044,11 @@ static int reset_ms(struct rtsx_chip *chip) ms_card->ms_type |= MS_4BIT; } - if (CHK_MS4BIT(ms_card)) + if (CHK_MS4BIT(ms_card)) { chip->card_bus_width[chip->card2lun[MS_CARD]] = 4; - else + } else { chip->card_bus_width[chip->card2lun[MS_CARD]] = 1; + } return STATUS_SUCCESS; } @@ -1950,27 +2065,30 @@ static int ms_init_l2p_tbl(struct rtsx_chip *chip) size = ms_card->segment_cnt * sizeof(struct zone_entry); ms_card->segment = vzalloc(size); - if (ms_card->segment == NULL) + if (ms_card->segment == NULL) { TRACE_RET(chip, STATUS_FAIL); + } retval = ms_read_page(chip, ms_card->boot_block, 1); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_GOTO(chip, INIT_FAIL); + } reg_addr = PPBUF_BASE2; for (i = 0; i < (((ms_card->total_block >> 9) * 10) + 1); i++) { retval = rtsx_read_register(chip, reg_addr++, &val1); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_GOTO(chip, INIT_FAIL); - + } retval = rtsx_read_register(chip, reg_addr++, &val2); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_GOTO(chip, INIT_FAIL); + } defect_block = ((u16)val1 << 8) | val2; - if (defect_block == 0xFFFF) + if (defect_block == 0xFFFF) { break; - + } seg_no = defect_block / 512; ms_card->segment[seg_no].defect_list[ms_card->segment[seg_no].disable_count++] = defect_block; } @@ -2023,8 +2141,9 @@ static void ms_set_l2p_tbl(struct rtsx_chip *chip, int seg_no, u16 log_off, u16 return; segment = &(ms_card->segment[seg_no]); - if (segment->l2p_table) + if (segment->l2p_table) { segment->l2p_table[log_off] = phy_blk; + } } static void ms_set_unused_block(struct rtsx_chip *chip, u16 phy_blk) @@ -2037,9 +2156,9 @@ static void ms_set_unused_block(struct rtsx_chip *chip, u16 phy_blk) segment = &(ms_card->segment[seg_no]); segment->free_table[segment->set_index++] = phy_blk; - if (segment->set_index >= MS_FREE_TABLE_CNT) + if (segment->set_index >= MS_FREE_TABLE_CNT) { segment->set_index = 0; - + } segment->unused_blk_cnt++; } @@ -2056,9 +2175,9 @@ static u16 ms_get_unused_block(struct rtsx_chip *chip, int seg_no) phy_blk = segment->free_table[segment->get_index]; segment->free_table[segment->get_index++] = 0xFFFF; - if (segment->get_index >= MS_FREE_TABLE_CNT) + if (segment->get_index >= MS_FREE_TABLE_CNT) { segment->get_index = 0; - + } segment->unused_blk_cnt--; return phy_blk; @@ -2080,27 +2199,27 @@ static int ms_arbitrate_l2p(struct rtsx_chip *chip, u16 phy_blk, u16 log_off, u8 if (us1 != us2) { if (us1 == 0) { - if (!(chip->card_wp & MS_CARD)) + if (!(chip->card_wp & MS_CARD)) { ms_erase_block(chip, tmp_blk); - + } ms_set_unused_block(chip, tmp_blk); segment->l2p_table[log_off] = phy_blk; } else { - if (!(chip->card_wp & MS_CARD)) + if (!(chip->card_wp & MS_CARD)) { ms_erase_block(chip, phy_blk); - + } ms_set_unused_block(chip, phy_blk); } } else { if (phy_blk < tmp_blk) { - if (!(chip->card_wp & MS_CARD)) + if (!(chip->card_wp & MS_CARD)) { ms_erase_block(chip, phy_blk); - + } ms_set_unused_block(chip, phy_blk); } else { - if (!(chip->card_wp & MS_CARD)) + if (!(chip->card_wp & MS_CARD)) { ms_erase_block(chip, tmp_blk); - + } ms_set_unused_block(chip, tmp_blk); segment->l2p_table[log_off] = phy_blk; } @@ -2121,8 +2240,9 @@ static int ms_build_l2p_tbl(struct rtsx_chip *chip, int seg_no) if (ms_card->segment == NULL) { retval = ms_init_l2p_tbl(chip); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, retval); + } } if (ms_card->segment[seg_no].build_flag) { @@ -2130,24 +2250,27 @@ static int ms_build_l2p_tbl(struct rtsx_chip *chip, int seg_no) return STATUS_SUCCESS; } - if (seg_no == 0) + if (seg_no == 0) { table_size = 494; - else + } else { table_size = 496; + } segment = &(ms_card->segment[seg_no]); if (segment->l2p_table == NULL) { segment->l2p_table = (u16 *)vmalloc(table_size * 2); - if (segment->l2p_table == NULL) + if (segment->l2p_table == NULL) { TRACE_GOTO(chip, BUILD_FAIL); + } } memset((u8 *)(segment->l2p_table), 0xff, table_size * 2); if (segment->free_table == NULL) { segment->free_table = (u16 *)vmalloc(MS_FREE_TABLE_CNT * 2); - if (segment->free_table == NULL) + if (segment->free_table == NULL) { TRACE_GOTO(chip, BUILD_FAIL); + } } memset((u8 *)(segment->free_table), 0xff, MS_FREE_TABLE_CNT * 2); @@ -2245,11 +2368,13 @@ static int ms_build_l2p_tbl(struct rtsx_chip *chip, int seg_no) /* Logical Address Confirmation Process */ if (seg_no == ms_card->segment_cnt - 1) { - if (segment->unused_blk_cnt < 2) + if (segment->unused_blk_cnt < 2) { chip->card_wp |= MS_CARD; + } } else { - if (segment->unused_blk_cnt < 1) + if (segment->unused_blk_cnt < 1) { chip->card_wp |= MS_CARD; + } } if (chip->card_wp & MS_CARD) @@ -2263,9 +2388,9 @@ static int ms_build_l2p_tbl(struct rtsx_chip *chip, int seg_no) return STATUS_SUCCESS; } retval = ms_init_page(chip, phy_blk, log_blk, 0, 1); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_GOTO(chip, BUILD_FAIL); - + } segment->l2p_table[log_blk-ms_start_idx[seg_no]] = phy_blk; if (seg_no == ms_card->segment_cnt - 1) { if (segment->unused_blk_cnt < 2) { @@ -2294,14 +2419,16 @@ static int ms_build_l2p_tbl(struct rtsx_chip *chip, int seg_no) phy_blk = ms_get_unused_block(chip, 0); retval = ms_copy_page(chip, tmp_blk, phy_blk, log_blk, 0, ms_card->page_off + 1); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } segment->l2p_table[log_blk] = phy_blk; retval = ms_set_bad_block(chip, tmp_blk); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } } } } @@ -2331,12 +2458,14 @@ int reset_ms_card(struct rtsx_chip *chip) memset(ms_card, 0, sizeof(struct ms_info)); retval = enable_card_clock(chip, MS_CARD); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } retval = select_card(chip, MS_CARD); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } ms_card->ms_type = 0; @@ -2344,24 +2473,27 @@ int reset_ms_card(struct rtsx_chip *chip) if (retval != STATUS_SUCCESS) { if (ms_card->check_ms_flow) { retval = reset_ms(chip); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } } else { TRACE_RET(chip, STATUS_FAIL); } } retval = ms_set_init_para(chip); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } if (!CHK_MSPRO(ms_card)) { /* Build table for the last segment, * to check if L2P table block exists, erasing it */ retval = ms_build_l2p_tbl(chip, ms_card->total_block / 512 - 1); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } } RTSX_DEBUGP("ms_card->ms_type = 0x%x\n", ms_card->ms_type); @@ -2388,8 +2520,9 @@ static int mspro_set_rw_cmd(struct rtsx_chip *chip, u32 start_sec, u16 sec_cnt, if (retval == STATUS_SUCCESS) break; } - if (i == MS_MAX_RETRY_COUNT) + if (i == MS_MAX_RETRY_COUNT) { TRACE_RET(chip, STATUS_FAIL); + } return STATUS_SUCCESS; } @@ -2423,18 +2556,21 @@ static inline int ms_auto_tune_clock(struct rtsx_chip *chip) RTSX_DEBUGP("--%s--\n", __func__); if (chip->asic_code) { - if (ms_card->ms_clock > 30) + if (ms_card->ms_clock > 30) { ms_card->ms_clock -= 20; + } } else { - if (ms_card->ms_clock == CLK_80) + if (ms_card->ms_clock == CLK_80) { ms_card->ms_clock = CLK_60; - else if (ms_card->ms_clock == CLK_60) + } else if (ms_card->ms_clock == CLK_60) { ms_card->ms_clock = CLK_40; + } } retval = ms_switch_clock(chip); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } return STATUS_SUCCESS; } @@ -2480,13 +2616,15 @@ static int mspro_rw_multi_sector(struct scsi_cmnd *srb, struct rtsx_chip *chip, } retval = ms_switch_clock(chip); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } - if (srb->sc_data_direction == DMA_FROM_DEVICE) + if (srb->sc_data_direction == DMA_FROM_DEVICE) { trans_mode = MS_TM_AUTO_READ; - else + } else { trans_mode = MS_TM_AUTO_WRITE; + } RTSX_READ_REG(chip, MS_TRANS_CFG, &val); @@ -2501,8 +2639,9 @@ static int mspro_rw_multi_sector(struct scsi_cmnd *srb, struct rtsx_chip *chip, ms_card->total_sec_cnt = 0; if (val & MS_INT_BREQ) { retval = ms_send_cmd(chip, PRO_STOP, WAIT_INT); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } rtsx_write_register(chip, RBCTL, RB_FLUSH, RB_FLUSH); } @@ -2512,16 +2651,17 @@ static int mspro_rw_multi_sector(struct scsi_cmnd *srb, struct rtsx_chip *chip, if (!ms_card->seq_mode) { ms_card->total_sec_cnt = 0; if (sector_cnt >= SEQ_START_CRITERIA) { - if ((ms_card->capacity - start_sector) > 0xFE00) + if ((ms_card->capacity - start_sector) > 0xFE00) { count = 0xFE00; - else + } else { count = (u16)(ms_card->capacity - start_sector); - + } if (count > sector_cnt) { - if (mode_2k) + if (mode_2k) { ms_card->seq_mode |= MODE_2K_SEQ; - else + } else { ms_card->seq_mode |= MODE_512_SEQ; + } } } else { count = sector_cnt; @@ -2546,9 +2686,9 @@ static int mspro_rw_multi_sector(struct scsi_cmnd *srb, struct rtsx_chip *chip, TRACE_RET(chip, STATUS_FAIL); } - if (val & MS_INT_BREQ) + if (val & MS_INT_BREQ) { ms_send_cmd(chip, PRO_STOP, WAIT_INT); - + } if (val & (MS_CRC16_ERR | MS_RDY_TIMEOUT)) { RTSX_DEBUGP("MSPro CRC error, tune clock!\n"); chip->rw_need_retry = 1; @@ -2599,10 +2739,11 @@ static int mspro_read_format_progress(struct rtsx_chip *chip, const int short_da TRACE_RET(chip, STATUS_FAIL); } - if (short_data_len >= 256) + if (short_data_len >= 256) { cnt = 0; - else + } else { cnt = (u8)short_data_len; + } retval = rtsx_write_register(chip, MS_CFG, MS_NO_CHECK_INT, MS_NO_CHECK_INT); if (retval != STATUS_SUCCESS) { @@ -2637,8 +2778,9 @@ static int mspro_read_format_progress(struct rtsx_chip *chip, const int short_da ms_card->format_status = FORMAT_FAIL; TRACE_RET(chip, STATUS_FAIL); } - if (tmp & (MS_INT_CED | MS_INT_CMDNK | MS_INT_BREQ | MS_INT_ERR)) + if (tmp & (MS_INT_CED | MS_INT_CMDNK | MS_INT_BREQ | MS_INT_ERR)) { break; + } wait_timeout(1); } @@ -2701,12 +2843,14 @@ int mspro_format(struct scsi_cmnd *srb, struct rtsx_chip *chip, int short_data_l RTSX_DEBUGP("--%s--\n", __func__); retval = ms_switch_clock(chip); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } retval = ms_set_rw_reg_addr(chip, 0x00, 0x00, Pro_TPCParm, 0x01); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } memset(buf, 0, 2); switch (short_data_len) { @@ -2730,22 +2874,25 @@ int mspro_format(struct scsi_cmnd *srb, struct rtsx_chip *chip, int short_data_l if (retval == STATUS_SUCCESS) break; } - if (i == MS_MAX_RETRY_COUNT) + if (i == MS_MAX_RETRY_COUNT) { TRACE_RET(chip, STATUS_FAIL); + } - if (quick_format) + if (quick_format) { para = 0x0000; - else + } else { para = 0x0001; - + } retval = mspro_set_rw_cmd(chip, 0, para, PRO_FORMAT); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } RTSX_READ_REG(chip, MS_TRANS_CFG, &tmp); - if (tmp & (MS_INT_CMDNK | MS_INT_ERR)) + if (tmp & (MS_INT_CMDNK | MS_INT_ERR)) { TRACE_RET(chip, STATUS_FAIL); + } if ((tmp & (MS_INT_BREQ | MS_INT_CED)) == MS_INT_BREQ) { ms_card->pro_under_formatting = 1; @@ -2783,14 +2930,15 @@ static int ms_read_multiple_pages(struct rtsx_chip *chip, u16 phy_blk, u16 log_b } retval = ms_set_rw_reg_addr(chip, OverwriteFlag, MS_EXTRA_SIZE, SystemParm, 6); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } - if (CHK_MS4BIT(ms_card)) + if (CHK_MS4BIT(ms_card)) { data[0] = 0x88; - else + } else { data[0] = 0x80; - + } data[1] = 0; data[2] = (u8)(phy_blk >> 8); data[3] = (u8)phy_blk; @@ -2802,14 +2950,16 @@ static int ms_read_multiple_pages(struct rtsx_chip *chip, u16 phy_blk, u16 log_b if (retval == STATUS_SUCCESS) break; } - if (i == MS_MAX_RETRY_COUNT) + if (i == MS_MAX_RETRY_COUNT) { TRACE_RET(chip, STATUS_FAIL); + } ms_set_err_code(chip, MS_NO_ERROR); retval = ms_send_cmd(chip, BLOCK_READ, WAIT_INT); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } ptr = buf; @@ -2822,9 +2972,9 @@ static int ms_read_multiple_pages(struct rtsx_chip *chip, u16 phy_blk, u16 log_b } retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, &val, 1); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); - + } if (val & INT_REG_CMDNK) { ms_set_err_code(chip, MS_CMD_NK); TRACE_RET(chip, STATUS_FAIL); @@ -2856,14 +3006,15 @@ static int ms_read_multiple_pages(struct rtsx_chip *chip, u16 phy_blk, u16 log_b if (page_addr == (end_page - 1)) { if (!(val & INT_REG_CED)) { retval = ms_send_cmd(chip, BLOCK_END, WAIT_INT); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } } retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, &val, 1); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); - + } if (!(val & INT_REG_CED)) { ms_set_err_code(chip, MS_FLASH_READ_ERROR); TRACE_RET(chip, STATUS_FAIL); @@ -2928,14 +3079,15 @@ static int ms_write_multiple_pages(struct rtsx_chip *chip, u16 old_blk, u16 new_ if (!start_page) { retval = ms_set_rw_reg_addr(chip, OverwriteFlag, MS_EXTRA_SIZE, SystemParm, 7); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } - if (CHK_MS4BIT(ms_card)) + if (CHK_MS4BIT(ms_card)) { data[0] = 0x88; - else + } else { data[0] = 0x80; - + } data[1] = 0; data[2] = (u8)(old_blk >> 8); data[3] = (u8)old_blk; @@ -2945,66 +3097,74 @@ static int ms_write_multiple_pages(struct rtsx_chip *chip, u16 old_blk, u16 new_ data[7] = 0xFF; retval = ms_write_bytes(chip, WRITE_REG, 7, NO_WAIT_INT, data, 8); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } retval = ms_send_cmd(chip, BLOCK_WRITE, WAIT_INT); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } ms_set_err_code(chip, MS_NO_ERROR); retval = ms_transfer_tpc(chip, MS_TM_READ_BYTES, GET_INT, 1, NO_WAIT_INT); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } } retval = ms_set_rw_reg_addr(chip, OverwriteFlag, MS_EXTRA_SIZE, SystemParm, (6 + MS_EXTRA_SIZE)); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } ms_set_err_code(chip, MS_NO_ERROR); - if (CHK_MS4BIT(ms_card)) + if (CHK_MS4BIT(ms_card)) { data[0] = 0x88; - else + } else { data[0] = 0x80; - + } data[1] = 0; data[2] = (u8)(new_blk >> 8); data[3] = (u8)new_blk; - if ((end_page - start_page) == 1) + if ((end_page - start_page) == 1) { data[4] = 0x20; - else + } else { data[4] = 0; - + } data[5] = start_page; data[6] = 0xF8; data[7] = 0xFF; data[8] = (u8)(log_blk >> 8); data[9] = (u8)log_blk; - for (i = 0x0A; i < 0x10; i++) + for (i = 0x0A; i < 0x10; i++) { data[i] = 0xFF; + } for (i = 0; i < MS_MAX_RETRY_COUNT; i++) { retval = ms_write_bytes(chip, WRITE_REG, 6 + MS_EXTRA_SIZE, NO_WAIT_INT, data, 16); if (retval == STATUS_SUCCESS) break; } - if (i == MS_MAX_RETRY_COUNT) + if (i == MS_MAX_RETRY_COUNT) { TRACE_RET(chip, STATUS_FAIL); + } for (i = 0; i < MS_MAX_RETRY_COUNT; i++) { retval = ms_send_cmd(chip, BLOCK_WRITE, WAIT_INT); if (retval == STATUS_SUCCESS) break; } - if (i == MS_MAX_RETRY_COUNT) + if (i == MS_MAX_RETRY_COUNT) { TRACE_RET(chip, STATUS_FAIL); + } retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, &val, 1); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } ptr = buf; for (page_addr = start_page; page_addr < end_page; page_addr++) { @@ -3050,15 +3210,17 @@ static int ms_write_multiple_pages(struct rtsx_chip *chip, u16 old_blk, u16 new_ ms_set_err_code(chip, MS_TO_ERROR); rtsx_clear_ms_error(chip); - if (retval == -ETIMEDOUT) + if (retval == -ETIMEDOUT) { TRACE_RET(chip, STATUS_TIMEDOUT); - else + } else { TRACE_RET(chip, STATUS_FAIL); + } } retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, &val, 1); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } if ((end_page - start_page) == 1) { if (!(val & INT_REG_CED)) { @@ -3069,13 +3231,15 @@ static int ms_write_multiple_pages(struct rtsx_chip *chip, u16 old_blk, u16 new_ if (page_addr == (end_page - 1)) { if (!(val & INT_REG_CED)) { retval = ms_send_cmd(chip, BLOCK_END, WAIT_INT); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } } retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, &val, 1); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } } if ((page_addr == (end_page - 1)) || (page_addr == ms_card->page_off)) { @@ -3102,8 +3266,9 @@ static int ms_finish_write(struct rtsx_chip *chip, u16 old_blk, u16 new_blk, retval = ms_copy_page(chip, old_blk, new_blk, log_blk, page_off, ms_card->page_off + 1); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } seg_no = old_blk >> 9; @@ -3112,8 +3277,9 @@ static int ms_finish_write(struct rtsx_chip *chip, u16 old_blk, u16 new_blk, ms_set_bad_block(chip, old_blk); } else { retval = ms_erase_block(chip, old_blk); - if (retval == STATUS_SUCCESS) + if (retval == STATUS_SUCCESS) { ms_set_unused_block(chip, old_blk); + } } ms_set_l2p_tbl(chip, seg_no, log_blk - ms_start_idx[seg_no], new_blk); @@ -3128,8 +3294,9 @@ static int ms_prepare_write(struct rtsx_chip *chip, u16 old_blk, u16 new_blk, if (start_page) { retval = ms_copy_page(chip, old_blk, new_blk, log_blk, 0, start_page); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } } return STATUS_SUCCESS; @@ -3144,15 +3311,17 @@ int ms_delay_write(struct rtsx_chip *chip) if (delay_write->delay_write_flag) { retval = ms_set_init_para(chip); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } delay_write->delay_write_flag = 0; retval = ms_finish_write(chip, delay_write->old_phyblock, delay_write->new_phyblock, delay_write->logblock, delay_write->pageoff); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } } return STATUS_SUCCESS; @@ -3161,10 +3330,11 @@ int ms_delay_write(struct rtsx_chip *chip) static inline void ms_rw_fail(struct scsi_cmnd *srb, struct rtsx_chip *chip) { - if (srb->sc_data_direction == DMA_FROM_DEVICE) + if (srb->sc_data_direction == DMA_FROM_DEVICE) { set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); - else + } else { set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_WRITE_ERR); + } } static int ms_rw_multi_sector(struct scsi_cmnd *srb, struct rtsx_chip *chip, u32 start_sector, u16 sector_cnt) @@ -3279,11 +3449,11 @@ static int ms_rw_multi_sector(struct scsi_cmnd *srb, struct rtsx_chip *chip, u32 RTSX_DEBUGP("seg_no = %d, old_blk = 0x%x, new_blk = 0x%x\n", seg_no, old_blk, new_blk); while (total_sec_cnt) { - if ((start_page + total_sec_cnt) > (ms_card->page_off + 1)) + if ((start_page + total_sec_cnt) > (ms_card->page_off + 1)) { end_page = ms_card->page_off + 1; - else + } else { end_page = start_page + (u8)total_sec_cnt; - + } page_cnt = end_page - start_page; RTSX_DEBUGP("start_page = %d, end_page = %d, page_cnt = %d\n", @@ -3312,9 +3482,9 @@ static int ms_rw_multi_sector(struct scsi_cmnd *srb, struct rtsx_chip *chip, u32 if (srb->sc_data_direction == DMA_TO_DEVICE) { if (end_page == (ms_card->page_off + 1)) { retval = ms_erase_block(chip, old_blk); - if (retval == STATUS_SUCCESS) + if (retval == STATUS_SUCCESS) { ms_set_unused_block(chip, old_blk); - + } ms_set_l2p_tbl(chip, seg_no, log_blk - ms_start_idx[seg_no], new_blk); } } @@ -3395,10 +3565,11 @@ int ms_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip, u32 start_sector, u16 s struct ms_info *ms_card = &(chip->ms_card); int retval; - if (CHK_MSPRO(ms_card)) + if (CHK_MSPRO(ms_card)) { retval = mspro_rw_multi_sector(srb, chip, start_sector, sector_cnt); - else + } else { retval = ms_rw_multi_sector(srb, chip, start_sector, sector_cnt); + } return retval; } @@ -3438,12 +3609,14 @@ static int ms_poll_int(struct rtsx_chip *chip) rtsx_add_cmd(chip, CHECK_REG_CMD, MS_TRANS_CFG, MS_INT_CED, MS_INT_CED); retval = rtsx_send_cmd(chip, MS_CARD, 5000); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } val = *rtsx_get_cmd_data(chip); - if (val & MS_INT_ERR) + if (val & MS_INT_ERR) { TRACE_RET(chip, STATUS_FAIL); + } return STATUS_SUCCESS; } @@ -3505,8 +3678,9 @@ static int mg_send_ex_cmd(struct rtsx_chip *chip, u8 cmd, u8 entry_num) if (retval == STATUS_SUCCESS) break; } - if (i == MS_MAX_RETRY_COUNT) + if (i == MS_MAX_RETRY_COUNT) { TRACE_RET(chip, STATUS_FAIL); + } if (check_ms_err(chip)) { rtsx_clear_ms_error(chip); @@ -3523,13 +3697,14 @@ static int mg_set_tpc_para_sub(struct rtsx_chip *chip, int type, u8 mg_entry_num RTSX_DEBUGP("--%s--\n", __func__); - if (type == 0) + if (type == 0) { retval = ms_set_rw_reg_addr(chip, 0, 0, Pro_TPCParm, 1); - else + } else { retval = ms_set_rw_reg_addr(chip, 0, 0, Pro_DataCount1, 6); - - if (retval != STATUS_SUCCESS) + } + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } buf[0] = 0; buf[1] = 0; @@ -3540,8 +3715,9 @@ static int mg_set_tpc_para_sub(struct rtsx_chip *chip, int type, u8 mg_entry_num buf[5] = mg_entry_num; } retval = ms_write_bytes(chip, PRO_WRITE_REG, (type == 0) ? 1 : 6, NO_WAIT_INT, buf, 6); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } return STATUS_SUCCESS; } @@ -3563,8 +3739,9 @@ int mg_set_leaf_id(struct scsi_cmnd *srb, struct rtsx_chip *chip) ms_cleanup_work(chip); retval = ms_switch_clock(chip); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } retval = mg_send_ex_cmd(chip, MG_SET_LID, 0); if (retval != STATUS_SUCCESS) { @@ -3574,9 +3751,9 @@ int mg_set_leaf_id(struct scsi_cmnd *srb, struct rtsx_chip *chip) memset(buf1, 0, 32); rtsx_stor_get_xfer_buf(buf2, min(12, (int)scsi_bufflen(srb)), srb); - for (i = 0; i < 8; i++) + for (i = 0; i < 8; i++) { buf1[8+i] = buf2[4+i]; - + } retval = ms_write_bytes(chip, PRO_WRITE_SHORT_DATA, 32, WAIT_INT, buf1, 32); if (retval != STATUS_SUCCESS) { set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB); @@ -3603,12 +3780,14 @@ int mg_get_local_EKB(struct scsi_cmnd *srb, struct rtsx_chip *chip) ms_cleanup_work(chip); retval = ms_switch_clock(chip); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } buf = kmalloc(1540, GFP_KERNEL); - if (!buf) + if (!buf) { TRACE_RET(chip, STATUS_ERROR); + } buf[0] = 0x04; buf[1] = 0x1A; @@ -3656,8 +3835,9 @@ int mg_chg(struct scsi_cmnd *srb, struct rtsx_chip *chip) ms_cleanup_work(chip); retval = ms_switch_clock(chip); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } retval = mg_send_ex_cmd(chip, MG_GET_ID, 0); if (retval != STATUS_SUCCESS) { @@ -3695,12 +3875,12 @@ int mg_chg(struct scsi_cmnd *srb, struct rtsx_chip *chip) bufflen = min(12, (int)scsi_bufflen(srb)); rtsx_stor_get_xfer_buf(buf, bufflen, srb); - for (i = 0; i < 8; i++) + for (i = 0; i < 8; i++) { buf[i] = buf[4+i]; - - for (i = 0; i < 24; i++) + } + for (i = 0; i < 24; i++) { buf[8+i] = 0; - + } retval = ms_write_bytes(chip, PRO_WRITE_SHORT_DATA, 32, WAIT_INT, buf, 32); if (retval != STATUS_SUCCESS) { @@ -3731,8 +3911,9 @@ int mg_get_rsp_chg(struct scsi_cmnd *srb, struct rtsx_chip *chip) ms_cleanup_work(chip); retval = ms_switch_clock(chip); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } retval = mg_send_ex_cmd(chip, MG_MAKE_RMS, 0); if (retval != STATUS_SUCCESS) { @@ -3787,8 +3968,9 @@ int mg_rsp(struct scsi_cmnd *srb, struct rtsx_chip *chip) ms_cleanup_work(chip); retval = ms_switch_clock(chip); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } retval = mg_send_ex_cmd(chip, MG_MAKE_KSE, 0); if (retval != STATUS_SUCCESS) { @@ -3799,12 +3981,12 @@ int mg_rsp(struct scsi_cmnd *srb, struct rtsx_chip *chip) bufflen = min(12, (int)scsi_bufflen(srb)); rtsx_stor_get_xfer_buf(buf, bufflen, srb); - for (i = 0; i < 8; i++) + for (i = 0; i < 8; i++) { buf[i] = buf[4+i]; - - for (i = 0; i < 24; i++) + } + for (i = 0; i < 24; i++) { buf[8+i] = 0; - + } retval = ms_write_bytes(chip, PRO_WRITE_SHORT_DATA, 32, WAIT_INT, buf, 32); if (retval != STATUS_SUCCESS) { set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN); @@ -3834,12 +4016,14 @@ int mg_get_ICV(struct scsi_cmnd *srb, struct rtsx_chip *chip) ms_cleanup_work(chip); retval = ms_switch_clock(chip); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } buf = kmalloc(1028, GFP_KERNEL); - if (!buf) + if (!buf) { TRACE_RET(chip, STATUS_ERROR); + } buf[0] = 0x04; buf[1] = 0x02; @@ -3889,12 +4073,14 @@ int mg_set_ICV(struct scsi_cmnd *srb, struct rtsx_chip *chip) ms_cleanup_work(chip); retval = ms_switch_clock(chip); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } buf = kmalloc(1028, GFP_KERNEL); - if (!buf) + if (!buf) { TRACE_RET(chip, STATUS_ERROR); + } bufflen = min(1028, (int)scsi_bufflen(srb)); rtsx_stor_get_xfer_buf(buf, bufflen, srb); @@ -3902,10 +4088,11 @@ int mg_set_ICV(struct scsi_cmnd *srb, struct rtsx_chip *chip) retval = mg_send_ex_cmd(chip, MG_SET_IBD, ms_card->mg_entry_num); if (retval != STATUS_SUCCESS) { if (ms_card->mg_auth == 0) { - if ((buf[5] & 0xC0) != 0) + if ((buf[5] & 0xC0) != 0) { set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB); - else + } else { set_sense_type(chip, lun, SENSE_TYPE_MG_WRITE_ERR); + } } else { set_sense_type(chip, lun, SENSE_TYPE_MG_WRITE_ERR); } @@ -3934,10 +4121,11 @@ int mg_set_ICV(struct scsi_cmnd *srb, struct rtsx_chip *chip) if ((retval < 0) || check_ms_err(chip)) { rtsx_clear_ms_error(chip); if (ms_card->mg_auth == 0) { - if ((buf[5] & 0xC0) != 0) + if ((buf[5] & 0xC0) != 0) { set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB); - else + } else { set_sense_type(chip, lun, SENSE_TYPE_MG_WRITE_ERR); + } } else { set_sense_type(chip, lun, SENSE_TYPE_MG_WRITE_ERR); } @@ -3951,10 +4139,11 @@ int mg_set_ICV(struct scsi_cmnd *srb, struct rtsx_chip *chip) if ((retval != STATUS_SUCCESS) || check_ms_err(chip)) { rtsx_clear_ms_error(chip); if (ms_card->mg_auth == 0) { - if ((buf[5] & 0xC0) != 0) + if ((buf[5] & 0xC0) != 0) { set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB); - else + } else { set_sense_type(chip, lun, SENSE_TYPE_MG_WRITE_ERR); + } } else { set_sense_type(chip, lun, SENSE_TYPE_MG_WRITE_ERR); } @@ -3998,13 +4187,14 @@ int ms_power_off_card3v3(struct rtsx_chip *chip) int retval; retval = disable_card_clock(chip, MS_CARD); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); - + } if (chip->asic_code) { retval = ms_pull_ctl_disable(chip); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } } else { RTSX_WRITE_REG(chip, FPGA_PULL_CTL, FPGA_MS_PULL_CTL_BIT | 0x20, FPGA_MS_PULL_CTL_BIT); @@ -4012,8 +4202,9 @@ int ms_power_off_card3v3(struct rtsx_chip *chip) RTSX_WRITE_REG(chip, CARD_OE, MS_OUTPUT_EN, 0); if (!chip->ft2_fast_mode) { retval = card_power_off(chip, MS_CARD); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } } return STATUS_SUCCESS; @@ -4043,8 +4234,9 @@ int release_ms_card(struct rtsx_chip *chip) #endif retval = ms_power_off_card3v3(chip); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } return STATUS_SUCCESS; } diff --git a/trunk/drivers/staging/rts_pstor/rtsx.c b/trunk/drivers/staging/rts_pstor/rtsx.c index afe9c2e763d7..5fb05a2edebb 100644 --- a/trunk/drivers/staging/rts_pstor/rtsx.c +++ b/trunk/drivers/staging/rts_pstor/rtsx.c @@ -20,8 +20,6 @@ * No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China */ -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - #include #include #include @@ -172,14 +170,14 @@ static int queuecommand_lck(struct scsi_cmnd *srb, /* check for state-transition errors */ if (chip->srb != NULL) { - dev_err(&dev->pci->dev, "Error in %s: chip->srb = %p\n", + printk(KERN_ERR "Error in %s: chip->srb = %p\n", __func__, chip->srb); return SCSI_MLQUEUE_HOST_BUSY; } /* fail the command if we are disconnecting */ if (rtsx_chk_stat(chip, RTSX_STAT_DISCONNECT)) { - dev_info(&dev->pci->dev, "Fail command during disconnect\n"); + printk(KERN_INFO "Fail command during disconnect\n"); srb->result = DID_NO_CONNECT << 16; done(srb); return 0; @@ -206,14 +204,14 @@ static int command_abort(struct scsi_cmnd *srb) struct rtsx_dev *dev = host_to_rtsx(host); struct rtsx_chip *chip = dev->chip; - dev_info(&dev->pci->dev, "%s called\n", __func__); + printk(KERN_INFO "%s called\n", __func__); scsi_lock(host); /* Is this command still active? */ if (chip->srb != srb) { scsi_unlock(host); - dev_info(&dev->pci->dev, "-- nothing to abort\n"); + printk(KERN_INFO "-- nothing to abort\n"); return FAILED; } @@ -232,9 +230,8 @@ static int command_abort(struct scsi_cmnd *srb) static int device_reset(struct scsi_cmnd *srb) { int result = 0; - struct rtsx_dev *dev = host_to_rtsx(srb->device->host); - dev_info(&dev->pci->dev, "%s called\n", __func__); + printk(KERN_INFO "%s called\n", __func__); return result < 0 ? FAILED : SUCCESS; } @@ -243,9 +240,8 @@ static int device_reset(struct scsi_cmnd *srb) static int bus_reset(struct scsi_cmnd *srb) { int result = 0; - struct rtsx_dev *dev = host_to_rtsx(srb->device->host); - dev_info(&dev->pci->dev, "%s called\n", __func__); + printk(KERN_INFO "%s called\n", __func__); return result < 0 ? FAILED : SUCCESS; } @@ -307,15 +303,14 @@ static int rtsx_acquire_irq(struct rtsx_dev *dev) { struct rtsx_chip *chip = dev->chip; - dev_info(&dev->pci->dev, "%s: chip->msi_en = %d, pci->irq = %d\n", - __func__, chip->msi_en, dev->pci->irq); + printk(KERN_INFO "%s: chip->msi_en = %d, pci->irq = %d\n", + __func__, chip->msi_en, dev->pci->irq); if (request_irq(dev->pci->irq, rtsx_interrupt, chip->msi_en ? 0 : IRQF_SHARED, CR_DRIVER_NAME, dev)) { - dev_err(&dev->pci->dev, - "rtsx: unable to grab IRQ %d, disabling device\n", - dev->pci->irq); + printk(KERN_ERR "rtsx: unable to grab IRQ %d, " + "disabling device\n", dev->pci->irq); return -1; } @@ -352,8 +347,12 @@ static int rtsx_suspend(struct pci_dev *pci, pm_message_t state) struct rtsx_dev *dev = (struct rtsx_dev *)pci_get_drvdata(pci); struct rtsx_chip *chip; - if (!dev) + printk(KERN_INFO "Ready to suspend\n"); + + if (!dev) { + printk(KERN_ERR "Invalid memory\n"); return 0; + } /* lock the device pointers */ mutex_lock(&(dev->dev_mutex)); @@ -387,8 +386,12 @@ static int rtsx_resume(struct pci_dev *pci) struct rtsx_dev *dev = (struct rtsx_dev *)pci_get_drvdata(pci); struct rtsx_chip *chip; - if (!dev) + printk(KERN_INFO "Ready to resume\n"); + + if (!dev) { + printk(KERN_ERR "Invalid memory\n"); return 0; + } chip = dev->chip; @@ -398,9 +401,8 @@ static int rtsx_resume(struct pci_dev *pci) pci_set_power_state(pci, PCI_D0); pci_restore_state(pci); if (pci_enable_device(pci) < 0) { - dev_err(&dev->pci->dev, - "%s: pci_enable_device failed, disabling device\n", - CR_DRIVER_NAME); + printk(KERN_ERR "%s: pci_enable_device failed, " + "disabling device\n", CR_DRIVER_NAME); /* unlock the device pointers */ mutex_unlock(&dev->dev_mutex); return -EIO; @@ -433,8 +435,12 @@ static void rtsx_shutdown(struct pci_dev *pci) struct rtsx_dev *dev = (struct rtsx_dev *)pci_get_drvdata(pci); struct rtsx_chip *chip; - if (!dev) + printk(KERN_INFO "Ready to shutdown\n"); + + if (!dev) { + printk(KERN_ERR "Invalid memory\n"); return; + } chip = dev->chip; @@ -469,7 +475,7 @@ static int rtsx_control_thread(void *__dev) /* if the device has disconnected, we are free to exit */ if (rtsx_chk_stat(chip, RTSX_STAT_DISCONNECT)) { - dev_info(&dev->pci->dev, "-- rtsx-control exiting\n"); + printk(KERN_INFO "-- rtsx-control exiting\n"); mutex_unlock(&dev->dev_mutex); break; } @@ -489,7 +495,7 @@ static int rtsx_control_thread(void *__dev) * is UNKNOWN */ if (chip->srb->sc_data_direction == DMA_BIDIRECTIONAL) { - dev_err(&dev->pci->dev, "UNKNOWN data direction\n"); + printk(KERN_ERR "UNKNOWN data direction\n"); chip->srb->result = DID_ERROR << 16; } @@ -497,14 +503,14 @@ static int rtsx_control_thread(void *__dev) * the maximum known LUN */ else if (chip->srb->device->id) { - dev_err(&dev->pci->dev, "Bad target number (%d:%d)\n", + printk(KERN_ERR "Bad target number (%d:%d)\n", chip->srb->device->id, chip->srb->device->lun); chip->srb->result = DID_BAD_TARGET << 16; } else if (chip->srb->device->lun > chip->max_lun) { - dev_err(&dev->pci->dev, "Bad LUN (%d:%d)\n", + printk(KERN_ERR "Bad LUN (%d:%d)\n", chip->srb->device->id, chip->srb->device->lun); chip->srb->result = DID_BAD_TARGET << 16; @@ -528,7 +534,7 @@ static int rtsx_control_thread(void *__dev) chip->srb->scsi_done(chip->srb); } else { SkipForAbort: - dev_err(&dev->pci->dev, "scsi command aborted\n"); + printk(KERN_ERR "scsi command aborted\n"); } if (rtsx_chk_stat(chip, RTSX_STAT_ABORT)) { @@ -588,7 +594,7 @@ static int rtsx_polling_thread(void *__dev) /* if the device has disconnected, we are free to exit */ if (rtsx_chk_stat(chip, RTSX_STAT_DISCONNECT)) { - dev_info(&dev->pci->dev, "-- rtsx-polling exiting\n"); + printk(KERN_INFO "-- rtsx-polling exiting\n"); mutex_unlock(&dev->dev_mutex); break; } @@ -677,13 +683,13 @@ static irqreturn_t rtsx_interrupt(int irq, void *dev_id) /* Release all our dynamic resources */ static void rtsx_release_resources(struct rtsx_dev *dev) { - dev_info(&dev->pci->dev, "-- %s\n", __func__); + printk(KERN_INFO "-- %s\n", __func__); /* Tell the control thread to exit. The SCSI host must * already have been removed so it won't try to queue * any more commands. */ - dev_info(&dev->pci->dev, "-- sending exit command to thread\n"); + printk(KERN_INFO "-- sending exit command to thread\n"); complete(&dev->cmnd_ready); if (dev->ctl_thread) wait_for_completion(&dev->control_exit); @@ -768,9 +774,8 @@ static int rtsx_scan_thread(void *__dev) /* Wait for the timeout to expire or for a disconnect */ if (delay_use > 0) { - dev_info(&dev->pci->dev, - "%s: waiting for device to settle before scanning\n", - CR_DRIVER_NAME); + printk(KERN_INFO "%s: waiting for device " + "to settle before scanning\n", CR_DRIVER_NAME); wait_event_interruptible_timeout(dev->delay_wait, rtsx_chk_stat(chip, RTSX_STAT_DISCONNECT), delay_use * HZ); @@ -779,8 +784,7 @@ static int rtsx_scan_thread(void *__dev) /* If the device is still connected, perform the scanning */ if (!rtsx_chk_stat(chip, RTSX_STAT_DISCONNECT)) { scsi_scan_host(rtsx_to_host(dev)); - dev_info(&dev->pci->dev, "%s: device scan complete\n", - CR_DRIVER_NAME); + printk(KERN_INFO "%s: device scan complete\n", CR_DRIVER_NAME); /* Should we unbind if no devices were detected? */ } @@ -902,14 +906,14 @@ static int __devinit rtsx_probe(struct pci_dev *pci, err = pci_enable_device(pci); if (err < 0) { - dev_err(&pci->dev, "PCI enable device failed!\n"); + printk(KERN_ERR "PCI enable device failed!\n"); return err; } err = pci_request_regions(pci, CR_DRIVER_NAME); if (err < 0) { - dev_err(&pci->dev, "PCI request regions for %s failed!\n", - CR_DRIVER_NAME); + printk(KERN_ERR "PCI request regions for %s failed!\n", + CR_DRIVER_NAME); pci_disable_device(pci); return err; } @@ -920,7 +924,7 @@ static int __devinit rtsx_probe(struct pci_dev *pci, */ host = scsi_host_alloc(&rtsx_host_template, sizeof(*dev)); if (!host) { - dev_err(&pci->dev, "Unable to allocate the scsi host\n"); + printk(KERN_ERR "Unable to allocate the scsi host\n"); pci_release_regions(pci); pci_disable_device(pci); return -ENOMEM; @@ -945,12 +949,12 @@ static int __devinit rtsx_probe(struct pci_dev *pci, dev->pci = pci; dev->irq = -1; - dev_info(&pci->dev, "Resource length: 0x%x\n", - (unsigned int)pci_resource_len(pci, 0)); + printk(KERN_INFO "Resource length: 0x%x\n", + (unsigned int)pci_resource_len(pci, 0)); dev->addr = pci_resource_start(pci, 0); dev->remap_addr = ioremap_nocache(dev->addr, pci_resource_len(pci, 0)); if (dev->remap_addr == NULL) { - dev_err(&pci->dev, "ioremap error\n"); + printk(KERN_ERR "ioremap error\n"); err = -ENXIO; goto errout; } @@ -959,13 +963,13 @@ static int __devinit rtsx_probe(struct pci_dev *pci, * Using "unsigned long" cast here to eliminate gcc warning in * 64-bit system */ - dev_info(&pci->dev, "Original address: 0x%lx, remapped address: 0x%lx\n", - (unsigned long)(dev->addr), (unsigned long)(dev->remap_addr)); + printk(KERN_INFO "Original address: 0x%lx, remapped address: 0x%lx\n", + (unsigned long)(dev->addr), (unsigned long)(dev->remap_addr)); dev->rtsx_resv_buf = dma_alloc_coherent(&(pci->dev), RTSX_RESV_BUF_LEN, &(dev->rtsx_resv_buf_addr), GFP_KERNEL); if (dev->rtsx_resv_buf == NULL) { - dev_err(&pci->dev, "alloc dma buffer fail\n"); + printk(KERN_ERR "alloc dma buffer fail\n"); err = -ENXIO; goto errout; } @@ -979,7 +983,7 @@ static int __devinit rtsx_probe(struct pci_dev *pci, rtsx_init_options(dev->chip); - dev_info(&pci->dev, "pci->irq = %d\n", pci->irq); + printk(KERN_INFO "pci->irq = %d\n", pci->irq); if (dev->chip->msi_en) { if (pci_enable_msi(pci) < 0) @@ -1004,7 +1008,7 @@ static int __devinit rtsx_probe(struct pci_dev *pci, /* Start up our control thread */ th = kthread_run(rtsx_control_thread, dev, CR_DRIVER_NAME); if (IS_ERR(th)) { - dev_err(&pci->dev, "Unable to start control thread\n"); + printk(KERN_ERR "Unable to start control thread\n"); err = PTR_ERR(th); goto errout; } @@ -1012,14 +1016,14 @@ static int __devinit rtsx_probe(struct pci_dev *pci, err = scsi_add_host(host, &pci->dev); if (err) { - dev_err(&pci->dev, "Unable to add the scsi host\n"); + printk(KERN_ERR "Unable to add the scsi host\n"); goto errout; } /* Start up the thread for delayed SCSI-device scanning */ th = kthread_run(rtsx_scan_thread, dev, "rtsx-scan"); if (IS_ERR(th)) { - dev_err(&pci->dev, "Unable to start the device-scanning thread\n"); + printk(KERN_ERR "Unable to start the device-scanning thread\n"); complete(&dev->scanning_done); quiesce_and_remove_host(dev); err = PTR_ERR(th); @@ -1029,7 +1033,7 @@ static int __devinit rtsx_probe(struct pci_dev *pci, /* Start up the thread for polling thread */ th = kthread_run(rtsx_polling_thread, dev, "rtsx-polling"); if (IS_ERR(th)) { - dev_err(&pci->dev, "Unable to start the device-polling thread\n"); + printk(KERN_ERR "Unable to start the device-polling thread\n"); quiesce_and_remove_host(dev); err = PTR_ERR(th); goto errout; @@ -1042,7 +1046,7 @@ static int __devinit rtsx_probe(struct pci_dev *pci, /* We come here if there are any problems */ errout: - dev_err(&pci->dev, "rtsx_probe() failed\n"); + printk(KERN_ERR "rtsx_probe() failed\n"); release_everything(dev); return err; @@ -1053,7 +1057,7 @@ static void __devexit rtsx_remove(struct pci_dev *pci) { struct rtsx_dev *dev = (struct rtsx_dev *)pci_get_drvdata(pci); - dev_info(&pci->dev, "rtsx_remove() called\n"); + printk(KERN_INFO "rtsx_remove() called\n"); quiesce_and_remove_host(dev); release_everything(dev); @@ -1086,18 +1090,18 @@ static struct pci_driver driver = { static int __init rtsx_init(void) { - pr_info("Initializing Realtek PCIE storage driver...\n"); + printk(KERN_INFO "Initializing Realtek PCIE storage driver...\n"); return pci_register_driver(&driver); } static void __exit rtsx_exit(void) { - pr_info("rtsx_exit() called\n"); + printk(KERN_INFO "rtsx_exit() called\n"); pci_unregister_driver(&driver); - pr_info("%s module exit\n", CR_DRIVER_NAME); + printk(KERN_INFO "%s module exit\n", CR_DRIVER_NAME); } module_init(rtsx_init) diff --git a/trunk/drivers/staging/rts_pstor/rtsx_card.c b/trunk/drivers/staging/rts_pstor/rtsx_card.c index 539aa6a27788..4f971f2e930a 100644 --- a/trunk/drivers/staging/rts_pstor/rtsx_card.c +++ b/trunk/drivers/staging/rts_pstor/rtsx_card.c @@ -309,10 +309,11 @@ static void release_sdio(struct rtsx_chip *chip) if (chip->chip_insert_with_sdio) { chip->chip_insert_with_sdio = 0; - if (CHECK_PID(chip, 0x5288)) + if (CHECK_PID(chip, 0x5288)) { rtsx_write_register(chip, 0xFE5A, 0x08, 0x00); - else + } else { rtsx_write_register(chip, 0xFE70, 0x80, 0x00); + } } rtsx_write_register(chip, SDIO_CTRL, SDIO_CD_CTRL, 0); @@ -378,10 +379,11 @@ void rtsx_reset_cards(struct rtsx_chip *chip) if (chip->need_reset & XD_CARD) { chip->card_exist |= XD_CARD; - if (chip->xd_show_cnt >= MAX_SHOW_CNT) + if (chip->xd_show_cnt >= MAX_SHOW_CNT) { do_reset_xd_card(chip); - else + } else { chip->xd_show_cnt++; + } } if (CHECK_PID(chip, 0x5288) && CHECK_BARO_PKG(chip, QFN)) { if (chip->card_exist & XD_CARD) { @@ -402,10 +404,11 @@ void rtsx_reset_cards(struct rtsx_chip *chip) if (chip->need_reset & MS_CARD) { chip->card_exist |= MS_CARD; - if (chip->ms_show_cnt >= MAX_SHOW_CNT) + if (chip->ms_show_cnt >= MAX_SHOW_CNT) { do_reset_ms_card(chip); - else + } else { chip->ms_show_cnt++; + } } } @@ -470,12 +473,13 @@ void card_cd_debounce(struct rtsx_chip *chip, unsigned long *need_reset, unsigne release_map |= MS_CARD; } } else { - if (chip->int_reg & XD_EXIST) + if (chip->int_reg & XD_EXIST) { reset_map |= XD_CARD; - else if (chip->int_reg & SD_EXIST) + } else if (chip->int_reg & SD_EXIST) { reset_map |= SD_CARD; - else if (chip->int_reg & MS_EXIST) + } else if (chip->int_reg & MS_EXIST) { reset_map |= MS_CARD; + } } if (reset_map) { @@ -485,21 +489,21 @@ void card_cd_debounce(struct rtsx_chip *chip, unsigned long *need_reset, unsigne for (i = 0; i < (DEBOUNCE_CNT); i++) { chip->int_reg = rtsx_readl(chip, RTSX_BIPR); - if (chip->int_reg & XD_EXIST) + if (chip->int_reg & XD_EXIST) { xd_cnt++; - else + } else { xd_cnt = 0; - - if (chip->int_reg & SD_EXIST) + } + if (chip->int_reg & SD_EXIST) { sd_cnt++; - else + } else { sd_cnt = 0; - - if (chip->int_reg & MS_EXIST) + } + if (chip->int_reg & MS_EXIST) { ms_cnt++; - else + } else { ms_cnt = 0; - + } wait_timeout(30); } @@ -673,8 +677,9 @@ int switch_ssc_clock(struct rtsx_chip *chip, int clk) RTSX_DEBUGP("Switch SSC clock to %dMHz (cur_clk = %d)\n", clk, chip->cur_clk); - if ((clk <= 2) || (N > max_N)) + if ((clk <= 2) || (N > max_N)) { TRACE_RET(chip, STATUS_FAIL); + } mcu_cnt = (u8)(125/clk + 3); if (CHECK_PID(chip, 0x5209)) { @@ -695,29 +700,32 @@ int switch_ssc_clock(struct rtsx_chip *chip, int clk) if (chip->ssc_en) { if (CHECK_PID(chip, 0x5209)) { if (chip->cur_card == SD_CARD) { - if (CHK_SD_SDR104(sd_card)) + if (CHK_SD_SDR104(sd_card)) { ssc_depth = chip->ssc_depth_sd_sdr104; - else if (CHK_SD_SDR50(sd_card)) + } else if (CHK_SD_SDR50(sd_card)) { ssc_depth = chip->ssc_depth_sd_sdr50; - else if (CHK_SD_DDR50(sd_card)) + } else if (CHK_SD_DDR50(sd_card)) { ssc_depth = double_depth(chip->ssc_depth_sd_ddr50); - else if (CHK_SD_HS(sd_card)) + } else if (CHK_SD_HS(sd_card)) { ssc_depth = double_depth(chip->ssc_depth_sd_hs); - else if (CHK_MMC_52M(sd_card) || CHK_MMC_DDR52(sd_card)) + } else if (CHK_MMC_52M(sd_card) || CHK_MMC_DDR52(sd_card)) { ssc_depth = double_depth(chip->ssc_depth_mmc_52m); - else + } else { ssc_depth = double_depth(chip->ssc_depth_low_speed); + } } else if (chip->cur_card == MS_CARD) { if (CHK_MSPRO(ms_card)) { - if (CHK_HG8BIT(ms_card)) + if (CHK_HG8BIT(ms_card)) { ssc_depth = double_depth(chip->ssc_depth_ms_hg); - else + } else { ssc_depth = double_depth(chip->ssc_depth_ms_4bit); + } } else { - if (CHK_MS4BIT(ms_card)) + if (CHK_MS4BIT(ms_card)) { ssc_depth = double_depth(chip->ssc_depth_ms_4bit); - else + } else { ssc_depth = double_depth(chip->ssc_depth_low_speed); + } } } else { ssc_depth = double_depth(chip->ssc_depth_low_speed); @@ -725,23 +733,23 @@ int switch_ssc_clock(struct rtsx_chip *chip, int clk) if (ssc_depth) { if (div == CLK_DIV_2) { - if (ssc_depth > 1) + if (ssc_depth > 1) { ssc_depth -= 1; - else + } else { ssc_depth = SSC_DEPTH_4M; - + } } else if (div == CLK_DIV_4) { - if (ssc_depth > 2) + if (ssc_depth > 2) { ssc_depth -= 2; - else + } else { ssc_depth = SSC_DEPTH_4M; - + } } else if (div == CLK_DIV_8) { - if (ssc_depth > 3) + if (ssc_depth > 3) { ssc_depth -= 3; - else + } else { ssc_depth = SSC_DEPTH_4M; - + } } } } else { @@ -752,10 +760,11 @@ int switch_ssc_clock(struct rtsx_chip *chip, int clk) ssc_depth = 0; } - if (CHECK_PID(chip, 0x5209)) + if (CHECK_PID(chip, 0x5209)) { ssc_depth_mask = SSC_DEPTH_MASK; - else + } else { ssc_depth_mask = 0x03; + } RTSX_DEBUGP("ssc_depth = %d\n", ssc_depth); @@ -772,8 +781,9 @@ int switch_ssc_clock(struct rtsx_chip *chip, int clk) } retval = rtsx_send_cmd(chip, 0, WAIT_TIME); - if (retval < 0) + if (retval < 0) { TRACE_RET(chip, STATUS_ERROR); + } udelay(10); RTSX_WRITE_REG(chip, CLK_CTL, CLK_LOW_FREQ, 0); @@ -966,23 +976,25 @@ int card_power_on(struct rtsx_chip *chip, u8 card) rtsx_init_cmd(chip); rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PWR_CTL, mask, val1); - if (CHECK_PID(chip, 0x5209) && (card == SD_CARD)) + if (CHECK_PID(chip, 0x5209) && (card == SD_CARD)) { rtsx_add_cmd(chip, WRITE_REG_CMD, PWR_GATE_CTRL, LDO3318_PWR_MASK, LDO_SUSPEND); - + } retval = rtsx_send_cmd(chip, 0, 100); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } udelay(chip->pmos_pwr_on_interval); rtsx_init_cmd(chip); rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PWR_CTL, mask, val2); - if (CHECK_PID(chip, 0x5209) && (card == SD_CARD)) + if (CHECK_PID(chip, 0x5209) && (card == SD_CARD)) { rtsx_add_cmd(chip, WRITE_REG_CMD, PWR_GATE_CTRL, LDO3318_PWR_MASK, LDO_ON); - + } retval = rtsx_send_cmd(chip, 0, 100); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } return STATUS_SUCCESS; } @@ -1004,8 +1016,9 @@ int card_power_off(struct rtsx_chip *chip, u8 card) } RTSX_WRITE_REG(chip, CARD_PWR_CTL, mask, val); - if (CHECK_PID(chip, 0x5209) && (card == SD_CARD)) + if (CHECK_PID(chip, 0x5209) && (card == SD_CARD)) { RTSX_WRITE_REG(chip, PWR_GATE_CTRL, LDO3318_PWR_MASK, LDO_OFF); + } return STATUS_SUCCESS; } @@ -1016,8 +1029,9 @@ int card_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip, u32 sec_addr, u16 sec unsigned int lun = SCSI_LUN(srb); int i; - if (chip->rw_card[lun] == NULL) + if (chip->rw_card[lun] == NULL) { TRACE_RET(chip, STATUS_FAIL); + } for (i = 0; i < 3; i++) { chip->rw_need_retry = 0; @@ -1028,9 +1042,9 @@ int card_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip, u32 sec_addr, u16 sec rtsx_release_chip(chip); TRACE_RET(chip, STATUS_FAIL); } - if (detect_card_cd(chip, chip->cur_card) != STATUS_SUCCESS) + if (detect_card_cd(chip, chip->cur_card) != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); - + } if (!chip->rw_need_retry) { RTSX_DEBUGP("RW fail, but no need to retry\n"); break; @@ -1052,26 +1066,26 @@ int card_share_mode(struct rtsx_chip *chip, int card) if (CHECK_PID(chip, 0x5209) || CHECK_PID(chip, 0x5208)) { mask = CARD_SHARE_MASK; - if (card == SD_CARD) + if (card == SD_CARD) { value = CARD_SHARE_48_SD; - else if (card == MS_CARD) + } else if (card == MS_CARD) { value = CARD_SHARE_48_MS; - else if (card == XD_CARD) + } else if (card == XD_CARD) { value = CARD_SHARE_48_XD; - else + } else { TRACE_RET(chip, STATUS_FAIL); - + } } else if (CHECK_PID(chip, 0x5288)) { mask = 0x03; - if (card == SD_CARD) + if (card == SD_CARD) { value = CARD_SHARE_BAROSSA_SD; - else if (card == MS_CARD) + } else if (card == MS_CARD) { value = CARD_SHARE_BAROSSA_MS; - else if (card == XD_CARD) + } else if (card == XD_CARD) { value = CARD_SHARE_BAROSSA_XD; - else + } else { TRACE_RET(chip, STATUS_FAIL); - + } } else { TRACE_RET(chip, STATUS_FAIL); } @@ -1089,23 +1103,24 @@ int select_card(struct rtsx_chip *chip, int card) if (chip->cur_card != card) { u8 mod; - if (card == SD_CARD) + if (card == SD_CARD) { mod = SD_MOD_SEL; - else if (card == MS_CARD) + } else if (card == MS_CARD) { mod = MS_MOD_SEL; - else if (card == XD_CARD) + } else if (card == XD_CARD) { mod = XD_MOD_SEL; - else if (card == SPI_CARD) + } else if (card == SPI_CARD) { mod = SPI_MOD_SEL; - else + } else { TRACE_RET(chip, STATUS_FAIL); - + } RTSX_WRITE_REG(chip, CARD_SELECT, 0x07, mod); chip->cur_card = card; retval = card_share_mode(chip, card); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } } return STATUS_SUCCESS; @@ -1122,18 +1137,20 @@ void toggle_gpio(struct rtsx_chip *chip, u8 gpio) void turn_on_led(struct rtsx_chip *chip, u8 gpio) { - if (CHECK_PID(chip, 0x5288)) + if (CHECK_PID(chip, 0x5288)) { rtsx_write_register(chip, CARD_GPIO, (u8)(1 << gpio), (u8)(1 << gpio)); - else + } else { rtsx_write_register(chip, CARD_GPIO, (u8)(1 << gpio), 0); + } } void turn_off_led(struct rtsx_chip *chip, u8 gpio) { - if (CHECK_PID(chip, 0x5288)) + if (CHECK_PID(chip, 0x5288)) { rtsx_write_register(chip, CARD_GPIO, (u8)(1 << gpio), 0); - else + } else { rtsx_write_register(chip, CARD_GPIO, (u8)(1 << gpio), (u8)(1 << gpio)); + } } int detect_card_cd(struct rtsx_chip *chip, int card) @@ -1152,60 +1169,67 @@ int detect_card_cd(struct rtsx_chip *chip, int card) } status = rtsx_readl(chip, RTSX_BIPR); - if (!(status & card_cd)) + if (!(status & card_cd)) { TRACE_RET(chip, STATUS_FAIL); + } return STATUS_SUCCESS; } int check_card_exist(struct rtsx_chip *chip, unsigned int lun) { - if (chip->card_exist & chip->lun2card[lun]) + if (chip->card_exist & chip->lun2card[lun]) { return 1; + } return 0; } int check_card_ready(struct rtsx_chip *chip, unsigned int lun) { - if (chip->card_ready & chip->lun2card[lun]) + if (chip->card_ready & chip->lun2card[lun]) { return 1; + } return 0; } int check_card_wp(struct rtsx_chip *chip, unsigned int lun) { - if (chip->card_wp & chip->lun2card[lun]) + if (chip->card_wp & chip->lun2card[lun]) { return 1; + } return 0; } int check_card_fail(struct rtsx_chip *chip, unsigned int lun) { - if (chip->card_fail & chip->lun2card[lun]) + if (chip->card_fail & chip->lun2card[lun]) { return 1; + } return 0; } int check_card_ejected(struct rtsx_chip *chip, unsigned int lun) { - if (chip->card_ejected & chip->lun2card[lun]) + if (chip->card_ejected & chip->lun2card[lun]) { return 1; + } return 0; } u8 get_lun_card(struct rtsx_chip *chip, unsigned int lun) { - if ((chip->card_ready & chip->lun2card[lun]) == XD_CARD) + if ((chip->card_ready & chip->lun2card[lun]) == XD_CARD) { return (u8)XD_CARD; - else if ((chip->card_ready & chip->lun2card[lun]) == SD_CARD) + } else if ((chip->card_ready & chip->lun2card[lun]) == SD_CARD) { return (u8)SD_CARD; - else if ((chip->card_ready & chip->lun2card[lun]) == MS_CARD) + } else if ((chip->card_ready & chip->lun2card[lun]) == MS_CARD) { return (u8)MS_CARD; + } return 0; } diff --git a/trunk/drivers/staging/rts_pstor/rtsx_chip.c b/trunk/drivers/staging/rts_pstor/rtsx_chip.c index d8e691b99028..5452069fbe08 100644 --- a/trunk/drivers/staging/rts_pstor/rtsx_chip.c +++ b/trunk/drivers/staging/rts_pstor/rtsx_chip.c @@ -105,10 +105,11 @@ void rtsx_enable_bus_int(struct rtsx_chip *chip) reg |= DELINK_INT_EN; #ifdef SUPPORT_OCP if (CHECK_PID(chip, 0x5209)) { - if (CHECK_LUN_MODE(chip, SD_MS_2LUN)) + if (CHECK_LUN_MODE(chip, SD_MS_2LUN)) { reg |= MS_OC_INT_EN | SD_OC_INT_EN; - else + } else { reg |= SD_OC_INT_EN; + } } else { reg |= OC_INT_EN; } @@ -185,20 +186,20 @@ static int rtsx_pre_handle_sdio_new(struct rtsx_chip *chip) u8 cd_toggle_mask = 0; RTSX_READ_REG(chip, TLPTISTAT, &tmp); - if (CHECK_PID(chip, 0x5209)) + if (CHECK_PID(chip, 0x5209)) { cd_toggle_mask = 0x10; - else + } else { cd_toggle_mask = 0x08; - + } if (tmp & cd_toggle_mask) { /* Disable sdio_bus_auto_switch */ - if (CHECK_PID(chip, 0x5288)) + if (CHECK_PID(chip, 0x5288)) { RTSX_WRITE_REG(chip, 0xFE5A, 0x08, 0x00); - else if (CHECK_PID(chip, 0x5208)) + } else if (CHECK_PID(chip, 0x5208)) { RTSX_WRITE_REG(chip, 0xFE70, 0x80, 0x00); - else + } else { RTSX_WRITE_REG(chip, SDIO_CFG, SDIO_BUS_AUTO_SWITCH, 0); - + } RTSX_WRITE_REG(chip, TLPTISTAT, 0xFF, tmp); chip->need_reset |= SD_CARD; @@ -207,14 +208,16 @@ static int rtsx_pre_handle_sdio_new(struct rtsx_chip *chip) if (chip->asic_code) { retval = sd_pull_ctl_enable(chip); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } } else { RTSX_WRITE_REG(chip, FPGA_PULL_CTL, FPGA_SD_PULL_CTL_BIT | 0x20, 0); } retval = card_share_mode(chip, SD_CARD); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } /* Enable sdio_bus_auto_switch */ if (CHECK_PID(chip, 0x5288)) { @@ -229,11 +232,11 @@ static int rtsx_pre_handle_sdio_new(struct rtsx_chip *chip) chip->sd_io = 1; } } else { - if (CHECK_PID(chip, 0x5209)) + if (CHECK_PID(chip, 0x5209)) { RTSX_WRITE_REG(chip, TLPTISTAT, 0x10, 0x10); - else + } else { RTSX_WRITE_REG(chip, TLPTISTAT, 0x08, 0x08); - + } chip->need_reset |= SD_CARD; } @@ -254,47 +257,48 @@ int rtsx_reset_chip(struct rtsx_chip *chip) /* optimize PHY */ retval = rtsx_write_phy_register(chip, 0x00, 0xB966); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); - + } retval = rtsx_write_phy_register(chip, 0x01, 0x713F); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); - + } retval = rtsx_write_phy_register(chip, 0x03, 0xA549); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); - + } retval = rtsx_write_phy_register(chip, 0x06, 0xB235); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); - + } retval = rtsx_write_phy_register(chip, 0x07, 0xEF40); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); - + } retval = rtsx_write_phy_register(chip, 0x1E, 0xF8EB); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); - + } retval = rtsx_write_phy_register(chip, 0x19, 0xFE6C); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); - + } wait_timeout(1); retval = rtsx_write_phy_register(chip, 0x0A, 0x05C0); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); - + } retval = rtsx_write_cfg_dw(chip, 1, 0x110, 0xFFFF, 0xFFFF); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } retval = rtsx_read_phy_register(chip, 0x08, &val); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); - + } RTSX_DEBUGP("Read from phy 0x08: 0x%04x\n", val); if (chip->phy_voltage) { @@ -304,9 +308,9 @@ int rtsx_reset_chip(struct rtsx_chip *chip) val |= chip->phy_voltage; RTSX_DEBUGP("Write to phy 0x08: 0x%04x\n", val); retval = rtsx_write_phy_register(chip, 0x08, val); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); - + } } else { chip->phy_voltage = (u8)(val & 0x3F); RTSX_DEBUGP("Default, chip->phy_voltage = 0x%x\n", chip->phy_voltage); @@ -320,11 +324,11 @@ int rtsx_reset_chip(struct rtsx_chip *chip) #ifdef SUPPORT_OCP /* SSC power on, OCD power on */ - if (CHECK_LUN_MODE(chip, SD_MS_2LUN)) + if (CHECK_LUN_MODE(chip, SD_MS_2LUN)) { RTSX_WRITE_REG(chip, FPDCTL, OC_POWER_DOWN, 0); - else + } else { RTSX_WRITE_REG(chip, FPDCTL, OC_POWER_DOWN, MS_OC_POWER_DOWN); - + } if (CHECK_PID(chip, 0x5209)) { RTSX_WRITE_REG(chip, OCPPARA1, SD_OCP_TIME_MASK | MS_OCP_TIME_MASK, SD_OCP_TIME_800 | MS_OCP_TIME_800); @@ -348,8 +352,9 @@ int rtsx_reset_chip(struct rtsx_chip *chip) RTSX_WRITE_REG(chip, FPDCTL, OC_POWER_DOWN, OC_POWER_DOWN); #endif - if (!CHECK_PID(chip, 0x5288)) + if (!CHECK_PID(chip, 0x5288)) { RTSX_WRITE_REG(chip, CARD_GPIO_DIR, 0xFF, 0x03); + } /* Turn off LED */ RTSX_WRITE_REG(chip, CARD_GPIO, 0xFF, 0x03); @@ -359,8 +364,9 @@ int rtsx_reset_chip(struct rtsx_chip *chip) /* Card driving select */ RTSX_WRITE_REG(chip, CARD_DRIVE_SEL, 0xFF, chip->card_drive_sel); - if (CHECK_PID(chip, 0x5209)) + if (CHECK_PID(chip, 0x5209)) { RTSX_WRITE_REG(chip, SD30_DRIVE_SEL, 0x07, chip->sd30_drive_sel_3v3); + } #ifdef LED_AUTO_BLINK RTSX_WRITE_REG(chip, CARD_AUTO_BLINK, 0xFF, @@ -388,34 +394,36 @@ int rtsx_reset_chip(struct rtsx_chip *chip) if (CHK_SDIO_EXIST(chip)) { if (CHECK_PID(chip, 0x5209)) { retval = rtsx_write_cfg_dw(chip, 1, 0xC0, 0xFF, chip->aspm_l0s_l1_en); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); - + } } else if (CHECK_PID(chip, 0x5288)) { retval = rtsx_write_cfg_dw(chip, 2, 0xC0, 0xFF, chip->aspm_l0s_l1_en); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } } } } else { - if (CHECK_PID(chip, 0x5208)) + if (CHECK_PID(chip, 0x5208)) { RTSX_WRITE_REG(chip, ASPM_FORCE_CTL, 0xFF, 0x3F); + } retval = rtsx_write_config_byte(chip, LCTLR, chip->aspm_l0s_l1_en); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); - + } chip->aspm_level[0] = chip->aspm_l0s_l1_en; if (CHK_SDIO_EXIST(chip)) { chip->aspm_level[1] = chip->aspm_l0s_l1_en; - if (CHECK_PID(chip, 0x5288)) + if (CHECK_PID(chip, 0x5288)) { retval = rtsx_write_cfg_dw(chip, 2, 0xC0, 0xFF, chip->aspm_l0s_l1_en); - else + } else { retval = rtsx_write_cfg_dw(chip, 1, 0xC0, 0xFF, chip->aspm_l0s_l1_en); - - if (retval != STATUS_SUCCESS) + } + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); - + } } chip->aspm_enabled = 1; @@ -423,45 +431,49 @@ int rtsx_reset_chip(struct rtsx_chip *chip) } else { if (chip->asic_code && CHECK_PID(chip, 0x5208)) { retval = rtsx_write_phy_register(chip, 0x07, 0x0129); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } } retval = rtsx_write_config_byte(chip, LCTLR, chip->aspm_l0s_l1_en); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } } retval = rtsx_write_config_byte(chip, 0x81, 1); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } if (CHK_SDIO_EXIST(chip)) { - if (CHECK_PID(chip, 0x5288)) + if (CHECK_PID(chip, 0x5288)) { retval = rtsx_write_cfg_dw(chip, 2, 0xC0, 0xFF00, 0x0100); - else + } else { retval = rtsx_write_cfg_dw(chip, 1, 0xC0, 0xFF00, 0x0100); - - if (retval != STATUS_SUCCESS) + } + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); - + } } if (CHECK_PID(chip, 0x5209)) { retval = rtsx_write_cfg_dw(chip, 0, 0x70C, 0xFF000000, 0x5B); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } } if (CHECK_PID(chip, 0x5288)) { if (!CHK_SDIO_EXIST(chip)) { retval = rtsx_write_cfg_dw(chip, 2, 0xC0, 0xFFFF, 0x0103); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); - + } retval = rtsx_write_cfg_dw(chip, 2, 0x84, 0xFF, 0x03); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); - + } } } @@ -487,29 +499,29 @@ int rtsx_reset_chip(struct rtsx_chip *chip) if (chip->ic_version >= IC_VER_D) { u16 reg; retval = rtsx_read_phy_register(chip, 0x00, ®); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); - + } reg &= 0xFE7F; reg |= 0x80; retval = rtsx_write_phy_register(chip, 0x00, reg); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); - + } retval = rtsx_read_phy_register(chip, 0x1C, ®); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); - + } reg &= 0xFFF7; retval = rtsx_write_phy_register(chip, 0x1C, reg); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); - + } } - if (chip->driver_first_load && (chip->ic_version < IC_VER_C)) + if (chip->driver_first_load && (chip->ic_version < IC_VER_C)) { rtsx_calibration(chip); - + } } else { rtsx_enable_bus_int(chip); } @@ -538,18 +550,18 @@ int rtsx_reset_chip(struct rtsx_chip *chip) RTSX_DEBUGP("In rtsx_reset_chip, chip->int_reg = 0x%x\n", chip->int_reg); if (chip->int_reg & SD_EXIST) { #ifdef HW_AUTO_SWITCH_SD_BUS - if (CHECK_PID(chip, 0x5208) && (chip->ic_version < IC_VER_C)) + if (CHECK_PID(chip, 0x5208) && (chip->ic_version < IC_VER_C)) { retval = rtsx_pre_handle_sdio_old(chip); - else + } else { retval = rtsx_pre_handle_sdio_new(chip); - + } RTSX_DEBUGP("chip->need_reset = 0x%x (rtsx_reset_chip)\n", (unsigned int)(chip->need_reset)); #else /* HW_AUTO_SWITCH_SD_BUS */ retval = rtsx_pre_handle_sdio_old(chip); #endif /* HW_AUTO_SWITCH_SD_BUS */ - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); - + } } else { chip->sd_io = 0; RTSX_WRITE_REG(chip, SDIO_CTRL, SDIO_BUS_CTRL | SDIO_CD_CTRL, 0); @@ -560,8 +572,9 @@ int rtsx_reset_chip(struct rtsx_chip *chip) chip->need_reset |= XD_CARD; if (chip->int_reg & MS_EXIST) chip->need_reset |= MS_CARD; - if (chip->int_reg & CARD_EXIST) + if (chip->int_reg & CARD_EXIST) { RTSX_WRITE_REG(chip, SSC_CTL1, SSC_RSTB, SSC_RSTB); + } RTSX_DEBUGP("In rtsx_init_chip, chip->need_reset = 0x%x\n", (unsigned int)(chip->need_reset)); @@ -574,8 +587,9 @@ int rtsx_reset_chip(struct rtsx_chip *chip) if (chip->remote_wakeup_en && !chip->auto_delink_en) { RTSX_WRITE_REG(chip, WAKE_SEL_CTL, 0x07, 0x07); - if (chip->aux_pwr_exist) + if (chip->aux_pwr_exist) { RTSX_WRITE_REG(chip, PME_FORCE_CTL, 0xFF, 0x33); + } } else { RTSX_WRITE_REG(chip, WAKE_SEL_CTL, 0x07, 0x04); RTSX_WRITE_REG(chip, PME_FORCE_CTL, 0xFF, 0x30); @@ -584,16 +598,18 @@ int rtsx_reset_chip(struct rtsx_chip *chip) if (CHECK_PID(chip, 0x5208) && (chip->ic_version >= IC_VER_D)) { RTSX_WRITE_REG(chip, PETXCFG, 0x1C, 0x14); } else if (CHECK_PID(chip, 0x5209)) { - if (chip->force_clkreq_0) + if (chip->force_clkreq_0) { RTSX_WRITE_REG(chip, PETXCFG, 0x08, 0x08); - else + } else { RTSX_WRITE_REG(chip, PETXCFG, 0x08, 0x00); + } } if (chip->asic_code && CHECK_PID(chip, 0x5208)) { retval = rtsx_clr_phy_reg_bit(chip, 0x1C, 2); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } } if (chip->ft2_fast_mode) { @@ -649,10 +665,11 @@ static int rts5209_init(struct rtsx_chip *chip) u8 val = 0; val = rtsx_readb(chip, 0x1C); - if ((val & 0x10) == 0) + if ((val & 0x10) == 0) { chip->asic_code = 1; - else + } else { chip->asic_code = 0; + } chip->ic_version = val & 0x0F; chip->phy_debug_mode = 0; @@ -662,9 +679,9 @@ static int rts5209_init(struct rtsx_chip *chip) chip->ms_power_class_en = 0x03; retval = rtsx_read_cfg_dw(chip, 0, 0x724, &lval); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); - + } RTSX_DEBUGP("dw in 0x724: 0x%x\n", lval); val = (u8)lval; if (!(val & 0x80)) { @@ -673,16 +690,17 @@ static int rts5209_init(struct rtsx_chip *chip) else chip->lun_mode = SD_MS_2LUN; - if (val & 0x04) + if (val & 0x04) { SET_SDIO_EXIST(chip); - else + } else { CLR_SDIO_EXIST(chip); + } - if (val & 0x02) + if (val & 0x02) { chip->hw_bypass_sd = 0; - else + } else { chip->hw_bypass_sd = 1; - + } } else { SET_SDIO_EXIST(chip); chip->hw_bypass_sd = 0; @@ -696,21 +714,24 @@ static int rts5209_init(struct rtsx_chip *chip) val = (u8)(lval >> 8); clk = (val >> 5) & 0x07; - if (clk != 0x07) + if (clk != 0x07) { chip->asic_sd_sdr50_clk = 98 - clk * 2; + } - if (val & 0x10) + if (val & 0x10) { chip->auto_delink_en = 1; - else + } else { chip->auto_delink_en = 0; + } if (chip->ss_en == 2) { chip->ss_en = 0; } else { - if (val & 0x08) + if (val & 0x08) { chip->ss_en = 1; - else + } else { chip->ss_en = 0; + } } clk = val & 0x07; @@ -729,21 +750,21 @@ static int rts5209_init(struct rtsx_chip *chip) if (clk != 0x03) chip->asic_sd_ddr50_clk = (48 - clk * 2) * 2; - if (val & 0x01) + if (val & 0x01) { chip->sdr104_en = 1; - else + } else { chip->sdr104_en = 0; - - if (val & 0x02) + } + if (val & 0x02) { chip->ddr50_en = 1; - else + } else { chip->ddr50_en = 0; - - if (val & 0x04) + } + if (val & 0x04) { chip->sdr50_en = 1; - else + } else { chip->sdr50_en = 0; - + } val = (u8)(lval >> 24); @@ -751,10 +772,11 @@ static int rts5209_init(struct rtsx_chip *chip) if (clk != 0x07) chip->asic_sd_sdr104_clk = 206 - clk * 3; - if (val & 0x10) + if (val & 0x10) { chip->power_down_in_ss = 1; - else + } else { chip->power_down_in_ss = 0; + } chip->ms_power_class_en = val & 0x03; } @@ -764,19 +786,20 @@ static int rts5209_init(struct rtsx_chip *chip) retval = rtsx_read_pci_cfg_byte(0x00, 0x1C, 0x02, 0x58, ®58); - if (retval < 0) + if (retval < 0) { return STATUS_SUCCESS; - + } retval = rtsx_read_pci_cfg_byte(0x00, 0x1C, 0x02, 0x5B, ®5b); - if (retval < 0) + if (retval < 0) { return STATUS_SUCCESS; + } RTSX_DEBUGP("reg58 = 0x%x, reg5b = 0x%x\n", reg58, reg5b); - if ((reg58 == 0x00) && (reg5b == 0x01)) + if ((reg58 == 0x00) && (reg5b == 0x01)) { chip->auto_delink_en = 0; - + } } return STATUS_SUCCESS; @@ -790,23 +813,24 @@ static int rts5208_init(struct rtsx_chip *chip) RTSX_WRITE_REG(chip, CLK_SEL, 0x03, 0x03); RTSX_READ_REG(chip, CLK_SEL, &val); - if (val == 0) + if (val == 0) { chip->asic_code = 1; - else + } else { chip->asic_code = 0; + } if (chip->asic_code) { retval = rtsx_read_phy_register(chip, 0x1C, ®); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); - + } RTSX_DEBUGP("Value of phy register 0x1C is 0x%x\n", reg); chip->ic_version = (reg >> 4) & 0x07; - if (reg & PHY_DEBUG_MODE) + if (reg & PHY_DEBUG_MODE) { chip->phy_debug_mode = 1; - else + } else { chip->phy_debug_mode = 0; - + } } else { RTSX_READ_REG(chip, 0xFE80, &val); chip->ic_version = val; @@ -815,29 +839,33 @@ static int rts5208_init(struct rtsx_chip *chip) RTSX_READ_REG(chip, PDINFO, &val); RTSX_DEBUGP("PDINFO: 0x%x\n", val); - if (val & AUX_PWR_DETECTED) + if (val & AUX_PWR_DETECTED) { chip->aux_pwr_exist = 1; - else + } else { chip->aux_pwr_exist = 0; + } RTSX_READ_REG(chip, 0xFE50, &val); - if (val & 0x01) + if (val & 0x01) { chip->hw_bypass_sd = 1; - else + } else { chip->hw_bypass_sd = 0; + } rtsx_read_config_byte(chip, 0x0E, &val); - if (val & 0x80) + if (val & 0x80) { SET_SDIO_EXIST(chip); - else + } else { CLR_SDIO_EXIST(chip); + } if (chip->use_hw_setting) { RTSX_READ_REG(chip, CHANGE_LINK_STATE, &val); - if (val & 0x80) + if (val & 0x80) { chip->auto_delink_en = 1; - else + } else { chip->auto_delink_en = 0; + } } return STATUS_SUCCESS; @@ -851,57 +879,63 @@ static int rts5288_init(struct rtsx_chip *chip) RTSX_WRITE_REG(chip, CLK_SEL, 0x03, 0x03); RTSX_READ_REG(chip, CLK_SEL, &val); - if (val == 0) + if (val == 0) { chip->asic_code = 1; - else + } else { chip->asic_code = 0; + } chip->ic_version = 0; chip->phy_debug_mode = 0; RTSX_READ_REG(chip, PDINFO, &val); RTSX_DEBUGP("PDINFO: 0x%x\n", val); - if (val & AUX_PWR_DETECTED) + if (val & AUX_PWR_DETECTED) { chip->aux_pwr_exist = 1; - else + } else { chip->aux_pwr_exist = 0; + } RTSX_READ_REG(chip, CARD_SHARE_MODE, &val); RTSX_DEBUGP("CARD_SHARE_MODE: 0x%x\n", val); - if (val & 0x04) + if (val & 0x04) { chip->baro_pkg = QFN; - else + } else { chip->baro_pkg = LQFP; + } RTSX_READ_REG(chip, 0xFE5A, &val); - if (val & 0x10) + if (val & 0x10) { chip->hw_bypass_sd = 1; - else + } else { chip->hw_bypass_sd = 0; + } retval = rtsx_read_cfg_dw(chip, 0, 0x718, &lval); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); - + } max_func = (u8)((lval >> 29) & 0x07); RTSX_DEBUGP("Max function number: %d\n", max_func); - if (max_func == 0x02) + if (max_func == 0x02) { SET_SDIO_EXIST(chip); - else + } else { CLR_SDIO_EXIST(chip); + } if (chip->use_hw_setting) { RTSX_READ_REG(chip, CHANGE_LINK_STATE, &val); - if (val & 0x80) + if (val & 0x80) { chip->auto_delink_en = 1; - else + } else { chip->auto_delink_en = 0; + } - if (CHECK_BARO_PKG(chip, LQFP)) + if (CHECK_BARO_PKG(chip, LQFP)) { chip->lun_mode = SD_MS_1LUN; - else + } else { chip->lun_mode = DEFAULT_SINGLE; - + } } return STATUS_SUCCESS; @@ -956,21 +990,22 @@ int rtsx_init_chip(struct rtsx_chip *chip) chip->rw_fail_cnt[i] = 0; } - if (!check_sd_speed_prior(chip->sd_speed_prior)) + if (!check_sd_speed_prior(chip->sd_speed_prior)) { chip->sd_speed_prior = 0x01040203; - + } RTSX_DEBUGP("sd_speed_prior = 0x%08x\n", chip->sd_speed_prior); - if (!check_sd_current_prior(chip->sd_current_prior)) + if (!check_sd_current_prior(chip->sd_current_prior)) { chip->sd_current_prior = 0x00010203; - + } RTSX_DEBUGP("sd_current_prior = 0x%08x\n", chip->sd_current_prior); - if ((chip->sd_ddr_tx_phase > 31) || (chip->sd_ddr_tx_phase < 0)) + if ((chip->sd_ddr_tx_phase > 31) || (chip->sd_ddr_tx_phase < 0)) { chip->sd_ddr_tx_phase = 0; - - if ((chip->mmc_ddr_tx_phase > 31) || (chip->mmc_ddr_tx_phase < 0)) + } + if ((chip->mmc_ddr_tx_phase > 31) || (chip->mmc_ddr_tx_phase < 0)) { chip->mmc_ddr_tx_phase = 0; + } RTSX_WRITE_REG(chip, FPDCTL, SSC_POWER_DOWN, 0); wait_timeout(200); @@ -979,23 +1014,24 @@ int rtsx_init_chip(struct rtsx_chip *chip) if (CHECK_PID(chip, 0x5209)) { retval = rts5209_init(chip); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); - + } } else if (CHECK_PID(chip, 0x5208)) { retval = rts5208_init(chip); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); - + } } else if (CHECK_PID(chip, 0x5288)) { retval = rts5288_init(chip); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); - + } } - if (chip->ss_en == 2) + if (chip->ss_en == 2) { chip->ss_en = 0; + } RTSX_DEBUGP("chip->asic_code = %d\n", chip->asic_code); RTSX_DEBUGP("chip->ic_version = 0x%x\n", chip->ic_version); @@ -1032,8 +1068,9 @@ int rtsx_init_chip(struct rtsx_chip *chip) } retval = rtsx_reset_chip(chip); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } return STATUS_SUCCESS; } @@ -1081,19 +1118,19 @@ static void rtsx_monitor_aspm_config(struct rtsx_chip *chip) chip->aspm_level[1] = reg1; } - if ((reg0 & 0x03) && (reg1 & 0x03)) + if ((reg0 & 0x03) && (reg1 & 0x03)) { maybe_support_aspm = 1; - + } } else { - if (reg0 & 0x03) + if (reg0 & 0x03) { maybe_support_aspm = 1; - + } } if (reg_changed) { - if (maybe_support_aspm) + if (maybe_support_aspm) { chip->aspm_l0s_l1_en = 0x03; - + } RTSX_DEBUGP("aspm_level[0] = 0x%02x, aspm_level[1] = 0x%02x\n", chip->aspm_level[0], chip->aspm_level[1]); @@ -1140,13 +1177,13 @@ void rtsx_polling_func(struct rtsx_chip *chip) if (chip->ocp_int & MS_OC_INT) ms_power_off_card3v3(chip); } else { - if (chip->card_exist & SD_CARD) + if (chip->card_exist & SD_CARD) { sd_power_off_card3v3(chip); - else if (chip->card_exist & MS_CARD) + } else if (chip->card_exist & MS_CARD) { ms_power_off_card3v3(chip); - else if (chip->card_exist & XD_CARD) + } else if (chip->card_exist & XD_CARD) { xd_power_off_card3v3(chip); - + } } chip->ocp_int = 0; @@ -1189,9 +1226,9 @@ void rtsx_polling_func(struct rtsx_chip *chip) if (CHK_SDIO_EXIST(chip) && !CHK_SDIO_IGNORED(chip)) { u32 val; rtsx_read_cfg_dw(chip, 1, 0x04, &val); - if (val & 0x07) + if (val & 0x07) { ss_allowed = 0; - + } } } } else { @@ -1247,9 +1284,9 @@ void rtsx_polling_func(struct rtsx_chip *chip) turn_off_led(chip, LED_GPIO); - if (chip->auto_power_down && !chip->card_ready && !chip->sd_io) + if (chip->auto_power_down && !chip->card_ready && !chip->sd_io) { rtsx_force_power_down(chip, SSC_PDCTL | OC_PDCTL); - + } } } @@ -1262,9 +1299,9 @@ void rtsx_polling_func(struct rtsx_chip *chip) break; case RTSX_STAT_IDLE: - if (chip->sd_io && !chip->sd_int) + if (chip->sd_io && !chip->sd_int) { try_to_switch_sdio_ctrl(chip); - + } rtsx_enable_aspm(chip); break; @@ -1276,8 +1313,9 @@ void rtsx_polling_func(struct rtsx_chip *chip) #ifdef SUPPORT_OCP if (CHECK_LUN_MODE(chip, SD_MS_2LUN)) { #ifdef CONFIG_RTS_PSTOR_DEBUG - if (chip->ocp_stat & (SD_OC_NOW | SD_OC_EVER | MS_OC_NOW | MS_OC_EVER)) + if (chip->ocp_stat & (SD_OC_NOW | SD_OC_EVER | MS_OC_NOW | MS_OC_EVER)) { RTSX_DEBUGP("Over current, OCPSTAT is 0x%x\n", chip->ocp_stat); + } #endif if (chip->ocp_stat & (SD_OC_NOW | SD_OC_EVER)) { @@ -1324,27 +1362,28 @@ void rtsx_polling_func(struct rtsx_chip *chip) if (chip->auto_delink_cnt == delink_stage1_cnt) { rtsx_set_stat(chip, RTSX_STAT_DELINK); - if (chip->asic_code && CHECK_PID(chip, 0x5208)) + if (chip->asic_code && CHECK_PID(chip, 0x5208)) { rtsx_set_phy_reg_bit(chip, 0x1C, 2); - + } if (chip->card_exist) { RTSX_DEBUGP("False card inserted, do force delink\n"); - if (enter_L1) + if (enter_L1) { rtsx_write_register(chip, HOST_SLEEP_STATE, 0x03, 1); - + } rtsx_write_register(chip, CHANGE_LINK_STATE, 0x0A, 0x0A); - if (enter_L1) + if (enter_L1) { rtsx_enter_L1(chip); + } chip->auto_delink_cnt = delink_stage3_cnt + 1; } else { RTSX_DEBUGP("No card inserted, do delink\n"); - if (enter_L1) + if (enter_L1) { rtsx_write_register(chip, HOST_SLEEP_STATE, 0x03, 1); - + } #ifdef HW_INT_WRITE_CLR if (CHECK_PID(chip, 0x5209)) { rtsx_writel(chip, RTSX_BIPR, 0xFFFFFFFF); @@ -1353,21 +1392,22 @@ void rtsx_polling_func(struct rtsx_chip *chip) #endif rtsx_write_register(chip, CHANGE_LINK_STATE, 0x02, 0x02); - if (enter_L1) + if (enter_L1) { rtsx_enter_L1(chip); - + } } } if (chip->auto_delink_cnt == delink_stage2_cnt) { RTSX_DEBUGP("Try to do force delink\n"); - if (enter_L1) + if (enter_L1) { rtsx_exit_L1(chip); + } - if (chip->asic_code && CHECK_PID(chip, 0x5208)) + if (chip->asic_code && CHECK_PID(chip, 0x5208)) { rtsx_set_phy_reg_bit(chip, 0x1C, 2); - + } rtsx_write_register(chip, CHANGE_LINK_STATE, 0x0A, 0x0A); } @@ -1432,9 +1472,9 @@ int rtsx_write_register(struct rtsx_chip *chip, u16 addr, u8 mask, u8 data) for (i = 0; i < MAX_RW_REG_CNT; i++) { val = rtsx_readl(chip, RTSX_HAIMR); if ((val & (1 << 31)) == 0) { - if (data != (u8)val) + if (data != (u8)val) { TRACE_RET(chip, STATUS_FAIL); - + } return STATUS_SUCCESS; } } @@ -1447,8 +1487,9 @@ int rtsx_read_register(struct rtsx_chip *chip, u16 addr, u8 *data) u32 val = 2 << 30; int i; - if (data) + if (data) { *data = 0; + } val |= (u32)(addr & 0x3FFF) << 16; @@ -1456,15 +1497,18 @@ int rtsx_read_register(struct rtsx_chip *chip, u16 addr, u8 *data) for (i = 0; i < MAX_RW_REG_CNT; i++) { val = rtsx_readl(chip, RTSX_HAIMR); - if ((val & (1 << 31)) == 0) + if ((val & (1 << 31)) == 0) { break; + } } - if (i >= MAX_RW_REG_CNT) + if (i >= MAX_RW_REG_CNT) { TRACE_RET(chip, STATUS_TIMEDOUT); + } - if (data) + if (data) { *data = (u8)(val & 0xFF); + } return STATUS_SUCCESS; } @@ -1493,8 +1537,9 @@ int rtsx_write_cfg_dw(struct rtsx_chip *chip, u8 func_no, u16 addr, u32 mask, u3 for (i = 0; i < MAX_RW_REG_CNT; i++) { RTSX_READ_REG(chip, CFGRWCTL, &tmp); - if ((tmp & 0x80) == 0) + if ((tmp & 0x80) == 0) { break; + } } } @@ -1513,8 +1558,9 @@ int rtsx_read_cfg_dw(struct rtsx_chip *chip, u8 func_no, u16 addr, u32 *val) for (i = 0; i < MAX_RW_REG_CNT; i++) { RTSX_READ_REG(chip, CFGRWCTL, &tmp); - if ((tmp & 0x80) == 0) + if ((tmp & 0x80) == 0) { break; + } } for (i = 0; i < 4; i++) { @@ -1522,8 +1568,9 @@ int rtsx_read_cfg_dw(struct rtsx_chip *chip, u8 func_no, u16 addr, u32 *val) data |= (u32)tmp << (i * 8); } - if (val) + if (val) { *val = data; + } return STATUS_SUCCESS; } @@ -1538,19 +1585,21 @@ int rtsx_write_cfg_seq(struct rtsx_chip *chip, u8 func, u16 addr, u8 *buf, int l RTSX_DEBUGP("%s\n", __func__); - if (!buf) + if (!buf) { TRACE_RET(chip, STATUS_NOMEM); + } - if ((len + offset) % 4) + if ((len + offset) % 4) { dw_len = (len + offset) / 4 + 1; - else + } else { dw_len = (len + offset) / 4; - + } RTSX_DEBUGP("dw_len = %d\n", dw_len); data = vzalloc(dw_len * 4); - if (!data) + if (!data) { TRACE_RET(chip, STATUS_NOMEM); + } mask = vzalloc(dw_len * 4); if (!mask) { @@ -1596,16 +1645,17 @@ int rtsx_read_cfg_seq(struct rtsx_chip *chip, u8 func, u16 addr, u8 *buf, int le RTSX_DEBUGP("%s\n", __func__); - if ((len + offset) % 4) + if ((len + offset) % 4) { dw_len = (len + offset) / 4 + 1; - else + } else { dw_len = (len + offset) / 4; - + } RTSX_DEBUGP("dw_len = %d\n", dw_len); data = (u32 *)vmalloc(dw_len * 4); - if (!data) + if (!data) { TRACE_RET(chip, STATUS_NOMEM); + } for (i = 0; i < dw_len; i++) { retval = rtsx_read_cfg_dw(chip, func, aligned_addr + i * 4, data + i); @@ -1650,8 +1700,9 @@ int rtsx_write_phy_register(struct rtsx_chip *chip, u8 addr, u16 val) } } - if (!finished) + if (!finished) { TRACE_RET(chip, STATUS_FAIL); + } return STATUS_SUCCESS; } @@ -1673,8 +1724,9 @@ int rtsx_read_phy_register(struct rtsx_chip *chip, u8 addr, u16 *val) } } - if (!finished) + if (!finished) { TRACE_RET(chip, STATUS_FAIL); + } RTSX_READ_REG(chip, PHYDATA0, &tmp); data = tmp; @@ -1701,8 +1753,9 @@ int rtsx_read_efuse(struct rtsx_chip *chip, u8 addr, u8 *val) udelay(1); } - if (data & 0x80) + if (data & 0x80) { TRACE_RET(chip, STATUS_TIMEDOUT); + } RTSX_READ_REG(chip, EFUSE_DATA, &data); if (val) @@ -1733,8 +1786,9 @@ int rtsx_write_efuse(struct rtsx_chip *chip, u8 addr, u8 val) wait_timeout(3); } - if (data & 0x80) + if (data & 0x80) { TRACE_RET(chip, STATUS_TIMEDOUT); + } wait_timeout(5); } @@ -1748,14 +1802,15 @@ int rtsx_clr_phy_reg_bit(struct rtsx_chip *chip, u8 reg, u8 bit) u16 value; retval = rtsx_read_phy_register(chip, reg, &value); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); - + } if (value & (1 << bit)) { value &= ~(1 << bit); retval = rtsx_write_phy_register(chip, reg, value); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } } return STATUS_SUCCESS; @@ -1767,14 +1822,15 @@ int rtsx_set_phy_reg_bit(struct rtsx_chip *chip, u8 reg, u8 bit) u16 value; retval = rtsx_read_phy_register(chip, reg, &value); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); - + } if (0 == (value & (1 << bit))) { value |= (1 << bit); retval = rtsx_write_phy_register(chip, reg, value); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } } return STATUS_SUCCESS; @@ -1805,11 +1861,11 @@ static void rtsx_handle_pm_dstate(struct rtsx_chip *chip, u8 dstate) if (CHK_SDIO_EXIST(chip)) { u8 func_no; - if (CHECK_PID(chip, 0x5288)) + if (CHECK_PID(chip, 0x5288)) { func_no = 2; - else + } else { func_no = 1; - + } rtsx_read_cfg_dw(chip, func_no, 0x84, &ultmp); RTSX_DEBUGP("pm_dstate of function %d: 0x%x\n", (int)func_no, ultmp); rtsx_write_cfg_dw(chip, func_no, 0x84, 0xFF, dstate); @@ -1842,10 +1898,11 @@ void rtsx_enter_ss(struct rtsx_chip *chip) } if (CHK_SDIO_EXIST(chip)) { - if (CHECK_PID(chip, 0x5288)) + if (CHECK_PID(chip, 0x5288)) { rtsx_write_cfg_dw(chip, 2, 0xC0, 0xFF00, 0x0100); - else + } else { rtsx_write_cfg_dw(chip, 1, 0xC0, 0xFF00, 0x0100); + } } if (chip->auto_delink_en) { @@ -1896,11 +1953,11 @@ int rtsx_pre_handle_interrupt(struct rtsx_chip *chip) u32 ocp_int = 0; if (CHECK_PID(chip, 0x5209)) { - if (CHECK_LUN_MODE(chip, SD_MS_2LUN)) + if (CHECK_LUN_MODE(chip, SD_MS_2LUN)) { ocp_int = MS_OC_INT | SD_OC_INT; - else + } else { ocp_int = SD_OC_INT; - + } } else { ocp_int = OC_INT; } @@ -1919,8 +1976,9 @@ int rtsx_pre_handle_interrupt(struct rtsx_chip *chip) chip->int_reg = rtsx_readl(chip, RTSX_BIPR); #ifdef HW_INT_WRITE_CLR - if (CHECK_PID(chip, 0x5209)) + if (CHECK_PID(chip, 0x5209)) { rtsx_writel(chip, RTSX_BIPR, chip->int_reg); + } #endif if (((chip->int_reg & int_enable) == 0) || (chip->int_reg == 0xFFFFFFFF)) @@ -1930,8 +1988,9 @@ int rtsx_pre_handle_interrupt(struct rtsx_chip *chip) if (CHECK_PID(chip, 0x5209)) { u8 val; rtsx_read_config_byte(chip, 0x05, &val); - if (val & 0x04) + if (val & 0x04) { return STATUS_FAIL; + } } } @@ -2048,15 +2107,16 @@ void rtsx_do_before_power_down(struct rtsx_chip *chip, int pm_stat) RTSX_DEBUGP("Host enter S1\n"); rtsx_write_register(chip, HOST_SLEEP_STATE, 0x03, HOST_ENTER_S1); } else if (pm_stat == PM_S3) { - if (chip->s3_pwr_off_delay > 0) + if (chip->s3_pwr_off_delay > 0) { wait_timeout(chip->s3_pwr_off_delay); - + } RTSX_DEBUGP("Host enter S3\n"); rtsx_write_register(chip, HOST_SLEEP_STATE, 0x03, HOST_ENTER_S3); } - if (chip->do_delink_before_power_down && chip->auto_delink_en) + if (chip->do_delink_before_power_down && chip->auto_delink_en) { rtsx_write_register(chip, CHANGE_LINK_STATE, 0x02, 2); + } rtsx_force_power_down(chip, SSC_PDCTL | OC_PDCTL); @@ -2083,10 +2143,11 @@ void rtsx_enable_aspm(struct rtsx_chip *chip) if (CHK_SDIO_EXIST(chip)) { u16 val = chip->aspm_l0s_l1_en | 0x0100; - if (CHECK_PID(chip, 0x5288)) + if (CHECK_PID(chip, 0x5288)) { rtsx_write_cfg_dw(chip, 2, 0xC0, 0xFFFF, val); - else + } else { rtsx_write_cfg_dw(chip, 1, 0xC0, 0xFFFF, val); + } } } } @@ -2106,11 +2167,11 @@ void rtsx_disable_aspm(struct rtsx_chip *chip) if (chip->asic_code && CHECK_PID(chip, 0x5208)) rtsx_write_phy_register(chip, 0x07, 0x0129); - if (CHECK_PID(chip, 0x5208)) + if (CHECK_PID(chip, 0x5208)) { rtsx_write_register(chip, ASPM_FORCE_CTL, 0xF3, 0x30); - else + } else { rtsx_write_config_byte(chip, LCTLR, 0x00); - + } wait_timeout(1); } } @@ -2125,8 +2186,9 @@ int rtsx_read_ppbuf(struct rtsx_chip *chip, u8 *buf, int buf_len) u16 reg_addr; u8 *ptr; - if (!buf) + if (!buf) { TRACE_RET(chip, STATUS_ERROR); + } ptr = buf; reg_addr = PPBUF_BASE2; @@ -2137,8 +2199,9 @@ int rtsx_read_ppbuf(struct rtsx_chip *chip, u8 *buf, int buf_len) rtsx_add_cmd(chip, READ_REG_CMD, reg_addr++, 0, 0); retval = rtsx_send_cmd(chip, 0, 250); - if (retval < 0) + if (retval < 0) { TRACE_RET(chip, STATUS_FAIL); + } memcpy(ptr, rtsx_get_cmd_data(chip), 256); ptr += 256; @@ -2151,8 +2214,9 @@ int rtsx_read_ppbuf(struct rtsx_chip *chip, u8 *buf, int buf_len) rtsx_add_cmd(chip, READ_REG_CMD, reg_addr++, 0, 0); retval = rtsx_send_cmd(chip, 0, 250); - if (retval < 0) + if (retval < 0) { TRACE_RET(chip, STATUS_FAIL); + } } memcpy(ptr, rtsx_get_cmd_data(chip), buf_len%256); @@ -2167,8 +2231,9 @@ int rtsx_write_ppbuf(struct rtsx_chip *chip, u8 *buf, int buf_len) u16 reg_addr; u8 *ptr; - if (!buf) + if (!buf) { TRACE_RET(chip, STATUS_ERROR); + } ptr = buf; reg_addr = PPBUF_BASE2; @@ -2181,8 +2246,9 @@ int rtsx_write_ppbuf(struct rtsx_chip *chip, u8 *buf, int buf_len) } retval = rtsx_send_cmd(chip, 0, 250); - if (retval < 0) + if (retval < 0) { TRACE_RET(chip, STATUS_FAIL); + } } if (buf_len%256) { @@ -2194,8 +2260,9 @@ int rtsx_write_ppbuf(struct rtsx_chip *chip, u8 *buf, int buf_len) } retval = rtsx_send_cmd(chip, 0, 250); - if (retval < 0) + if (retval < 0) { TRACE_RET(chip, STATUS_FAIL); + } } return STATUS_SUCCESS; @@ -2203,8 +2270,9 @@ int rtsx_write_ppbuf(struct rtsx_chip *chip, u8 *buf, int buf_len) int rtsx_check_chip_exist(struct rtsx_chip *chip) { - if (rtsx_readl(chip, 0) == 0xFFFFFFFF) + if (rtsx_readl(chip, 0) == 0xFFFFFFFF) { TRACE_RET(chip, STATUS_FAIL); + } return STATUS_SUCCESS; } @@ -2220,15 +2288,17 @@ int rtsx_force_power_on(struct rtsx_chip *chip, u8 ctl) #ifdef SUPPORT_OCP if (ctl & OC_PDCTL) { mask |= SD_OC_POWER_DOWN; - if (CHECK_LUN_MODE(chip, SD_MS_2LUN)) + if (CHECK_LUN_MODE(chip, SD_MS_2LUN)) { mask |= MS_OC_POWER_DOWN; + } } #endif if (mask) { retval = rtsx_write_register(chip, FPDCTL, mask, 0); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } if (CHECK_PID(chip, 0x5288)) wait_timeout(200); @@ -2256,8 +2326,9 @@ int rtsx_force_power_down(struct rtsx_chip *chip, u8 ctl) if (mask) { val = mask; retval = rtsx_write_register(chip, FPDCTL, mask, val); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } } return STATUS_SUCCESS; diff --git a/trunk/drivers/staging/rts_pstor/rtsx_scsi.c b/trunk/drivers/staging/rts_pstor/rtsx_scsi.c index 86c41b3a42a3..f2e5842d4c90 100644 --- a/trunk/drivers/staging/rts_pstor/rtsx_scsi.c +++ b/trunk/drivers/staging/rts_pstor/rtsx_scsi.c @@ -135,9 +135,9 @@ void scsi_show_command(struct scsi_cmnd *srb) default: what = "(unknown command)"; unknown_cmd = 1; break; } - if (srb->cmnd[0] != TEST_UNIT_READY) + if (srb->cmnd[0] != TEST_UNIT_READY) { RTSX_DEBUGP("Command %s (%d bytes)\n", what, srb->cmd_len); - + } if (unknown_cmd) { RTSX_DEBUGP(""); for (i = 0; i < srb->cmd_len && i < 16; i++) @@ -317,11 +317,11 @@ static int inquiry(struct scsi_cmnd *srb, struct rtsx_chip *chip) }; if (CHECK_LUN_MODE(chip, SD_MS_2LUN)) { - if (chip->lun2card[lun] == SD_CARD) + if (chip->lun2card[lun] == SD_CARD) { inquiry_string = inquiry_sd; - else + } else { inquiry_string = inquiry_ms; - + } } else if (CHECK_LUN_MODE(chip, SD_MS_1LUN)) { inquiry_string = inquiry_sdms; } else { @@ -329,8 +329,9 @@ static int inquiry(struct scsi_cmnd *srb, struct rtsx_chip *chip) } buf = vmalloc(scsi_bufflen(srb)); - if (buf == NULL) + if (buf == NULL) { TRACE_RET(chip, TRANSPORT_ERROR); + } #ifdef SUPPORT_MAGIC_GATE if ((chip->mspro_formatter_enable) && @@ -339,21 +340,23 @@ static int inquiry(struct scsi_cmnd *srb, struct rtsx_chip *chip) if (chip->mspro_formatter_enable) #endif { - if (!card || (card == MS_CARD)) + if (!card || (card == MS_CARD)) { pro_formatter_flag = 1; + } } if (pro_formatter_flag) { - if (scsi_bufflen(srb) < 56) + if (scsi_bufflen(srb) < 56) { sendbytes = (unsigned char)(scsi_bufflen(srb)); - else + } else { sendbytes = 56; - + } } else { - if (scsi_bufflen(srb) < 36) + if (scsi_bufflen(srb) < 36) { sendbytes = (unsigned char)(scsi_bufflen(srb)); - else + } else { sendbytes = 36; + } } if (sendbytes > 8) { @@ -368,8 +371,9 @@ static int inquiry(struct scsi_cmnd *srb, struct rtsx_chip *chip) } if (pro_formatter_flag) { - if (sendbytes > 36) + if (sendbytes > 36) { memcpy(buf + 36, formatter_inquiry_str, sendbytes - 36); + } } scsi_set_resid(srb, 0); @@ -463,8 +467,9 @@ static int request_sense(struct scsi_cmnd *srb, struct rtsx_chip *chip) } buf = vmalloc(scsi_bufflen(srb)); - if (buf == NULL) + if (buf == NULL) { TRACE_RET(chip, TRANSPORT_ERROR); + } tmp = (unsigned char *)sense; memcpy(buf, tmp, scsi_bufflen(srb)); @@ -489,15 +494,15 @@ static void ms_mode_sense(struct rtsx_chip *chip, u8 cmd, if (cmd == MODE_SENSE) { sys_info_offset = 8; - if (data_size > 0x68) + if (data_size > 0x68) { data_size = 0x68; - + } buf[i++] = 0x67; /* Mode Data Length */ } else { sys_info_offset = 12; - if (data_size > 0x6C) + if (data_size > 0x6C) { data_size = 0x6C; - + } buf[i++] = 0x00; /* Mode Data Length (MSB) */ buf[i++] = 0x6A; /* Mode Data Length (LSB) */ } @@ -515,11 +520,11 @@ static void ms_mode_sense(struct rtsx_chip *chip, u8 cmd, } /* WP */ - if (check_card_wp(chip, lun)) + if (check_card_wp(chip, lun)) { buf[i++] = 0x80; - else + } else { buf[i++] = 0x00; - + } } else { buf[i++] = 0x00; /* MediaType */ buf[i++] = 0x00; /* WP */ @@ -540,10 +545,11 @@ static void ms_mode_sense(struct rtsx_chip *chip, u8 cmd, if (data_size >= 11) buf[i++] = 0x00; /* No Access Control */ if (data_size >= 12) { - if (support_format) + if (support_format) { buf[i++] = 0xC0; /* SF, SGM */ - else + } else { buf[i++] = 0x00; + } } } else { /* The Following Data is the content of "Page 0x20" */ @@ -554,10 +560,11 @@ static void ms_mode_sense(struct rtsx_chip *chip, u8 cmd, if (data_size >= 7) buf[i++] = 0x00; /* No Access Control */ if (data_size >= 8) { - if (support_format) + if (support_format) { buf[i++] = 0xC0; /* SF, SGM */ - else + } else { buf[i++] = 0x00; + } } } @@ -593,8 +600,9 @@ static int mode_sense(struct scsi_cmnd *srb, struct rtsx_chip *chip) if ((chip->lun2card[lun] & MS_CARD)) { if (!card || (card == MS_CARD)) { dataSize = 108; - if (chip->mspro_formatter_enable) + if (chip->mspro_formatter_enable) { pro_formatter_flag = 1; + } } } #else @@ -607,8 +615,9 @@ static int mode_sense(struct scsi_cmnd *srb, struct rtsx_chip *chip) #endif buf = kmalloc(dataSize, GFP_KERNEL); - if (buf == NULL) + if (buf == NULL) { TRACE_RET(chip, TRANSPORT_ERROR); + } pageCode = srb->cmnd[2] & 0x3f; @@ -623,11 +632,11 @@ static int mode_sense(struct scsi_cmnd *srb, struct rtsx_chip *chip) dataSize = 4; buf[0] = 0x03; buf[1] = 0x00; - if (check_card_wp(chip, lun)) + if (check_card_wp(chip, lun)) { buf[2] = 0x80; - else + } else { buf[2] = 0x00; - + } buf[3] = 0x00; } } else { @@ -639,10 +648,11 @@ static int mode_sense(struct scsi_cmnd *srb, struct rtsx_chip *chip) buf[0] = 0x00; buf[1] = 0x06; buf[2] = 0x00; - if (check_card_wp(chip, lun)) + if (check_card_wp(chip, lun)) { buf[3] = 0x80; - else + } else { buf[3] = 0x00; + } buf[4] = 0x00; buf[5] = 0x00; buf[6] = 0x00; @@ -749,11 +759,11 @@ static int read_write(struct scsi_cmnd *srb, struct rtsx_chip *chip) if (chip->rw_fail_cnt[lun] == 3) { RTSX_DEBUGP("read/write fail three times in succession\n"); - if (srb->sc_data_direction == DMA_FROM_DEVICE) + if (srb->sc_data_direction == DMA_FROM_DEVICE) { set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); - else + } else { set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_ERR); - + } TRACE_RET(chip, TRANSPORT_FAILED); } @@ -766,8 +776,9 @@ static int read_write(struct scsi_cmnd *srb, struct rtsx_chip *chip) if (CHECK_PID(chip, 0x5209) && chip->max_payload) { u8 val = 0x10 | (chip->max_payload << 5); retval = rtsx_write_cfg_dw(chip, 0, 0x78, 0xFF, val); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, TRANSPORT_ERROR); + } } } @@ -778,10 +789,11 @@ static int read_write(struct scsi_cmnd *srb, struct rtsx_chip *chip) set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT); } else { chip->rw_fail_cnt[lun]++; - if (srb->sc_data_direction == DMA_FROM_DEVICE) + if (srb->sc_data_direction == DMA_FROM_DEVICE) { set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); - else + } else { set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_ERR); + } } retval = TRANSPORT_FAILED; TRACE_GOTO(chip, Exit); @@ -796,8 +808,9 @@ static int read_write(struct scsi_cmnd *srb, struct rtsx_chip *chip) if (srb->sc_data_direction == DMA_TO_DEVICE) { if (CHECK_PID(chip, 0x5209) && chip->max_payload) { retval = rtsx_write_cfg_dw(chip, 0, 0x78, 0xFF, 0x10); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, TRANSPORT_ERROR); + } } } @@ -824,8 +837,9 @@ static int read_format_capacity(struct scsi_cmnd *srb, struct rtsx_chip *chip) buf_len = (scsi_bufflen(srb) > 12) ? 0x14 : 12; buf = kmalloc(buf_len, GFP_KERNEL); - if (buf == NULL) + if (buf == NULL) { TRACE_RET(chip, TRANSPORT_ERROR); + } buf[i++] = 0; buf[i++] = 0; @@ -850,20 +864,22 @@ static int read_format_capacity(struct scsi_cmnd *srb, struct rtsx_chip *chip) buf[i++] = (unsigned char)(card_size >> 8); buf[i++] = (unsigned char)card_size; - if (desc_cnt == 2) + if (desc_cnt == 2) { buf[i++] = 2; - else + } else { buf[i++] = 0; + } } else { buf[i++] = 0xFF; buf[i++] = 0xFF; buf[i++] = 0xFF; buf[i++] = 0xFF; - if (desc_cnt == 2) + if (desc_cnt == 2) { buf[i++] = 3; - else + } else { buf[i++] = 0; + } } buf[i++] = 0x00; @@ -900,8 +916,9 @@ static int read_capacity(struct scsi_cmnd *srb, struct rtsx_chip *chip) } buf = kmalloc(8, GFP_KERNEL); - if (buf == NULL) + if (buf == NULL) { TRACE_RET(chip, TRANSPORT_ERROR); + } card_size = get_card_size(chip, lun); buf[0] = (unsigned char)((card_size - 1) >> 24); @@ -939,8 +956,9 @@ static int read_eeprom(struct scsi_cmnd *srb, struct rtsx_chip *chip) len = ((u16)srb->cmnd[4] << 8) | srb->cmnd[5]; buf = (u8 *)vmalloc(len); - if (!buf) + if (!buf) { TRACE_RET(chip, TRANSPORT_ERROR); + } retval = rtsx_force_power_on(chip, SSC_PDCTL); if (retval != STATUS_SUCCESS) { @@ -998,8 +1016,9 @@ static int write_eeprom(struct scsi_cmnd *srb, struct rtsx_chip *chip) } else { len = (unsigned short)min(scsi_bufflen(srb), (unsigned int)len); buf = (u8 *)vmalloc(len); - if (buf == NULL) + if (buf == NULL) { TRACE_RET(chip, TRANSPORT_ERROR); + } rtsx_stor_get_xfer_buf(buf, len, srb); scsi_set_resid(srb, scsi_bufflen(srb) - len); @@ -1042,8 +1061,9 @@ static int read_mem(struct scsi_cmnd *srb, struct rtsx_chip *chip) } buf = (u8 *)vmalloc(len); - if (!buf) + if (!buf) { TRACE_RET(chip, TRANSPORT_ERROR); + } retval = rtsx_force_power_on(chip, SSC_PDCTL); if (retval != STATUS_SUCCESS) { @@ -1094,8 +1114,9 @@ static int write_mem(struct scsi_cmnd *srb, struct rtsx_chip *chip) len = (unsigned short)min(scsi_bufflen(srb), (unsigned int)len); buf = (u8 *)vmalloc(len); - if (buf == NULL) + if (buf == NULL) { TRACE_RET(chip, TRANSPORT_ERROR); + } rtsx_stor_get_xfer_buf(buf, len, srb); scsi_set_resid(srb, scsi_bufflen(srb) - len); @@ -1179,15 +1200,16 @@ static int trace_msg_cmd(struct scsi_cmnd *srb, struct rtsx_chip *chip) clear = srb->cmnd[2]; buf = (unsigned char *)vmalloc(scsi_bufflen(srb)); - if (buf == NULL) + if (buf == NULL) { TRACE_RET(chip, TRANSPORT_ERROR); + } ptr = buf; - if (chip->trace_msg[chip->msg_idx].valid) + if (chip->trace_msg[chip->msg_idx].valid) { msg_cnt = TRACE_ITEM_CNT; - else + } else { msg_cnt = chip->msg_idx; - + } *(ptr++) = (u8)(msg_cnt >> 24); *(ptr++) = (u8)(msg_cnt >> 16); *(ptr++) = (u8)(msg_cnt >> 8); @@ -1203,14 +1225,15 @@ static int trace_msg_cmd(struct scsi_cmnd *srb, struct rtsx_chip *chip) *(ptr++) = (u8)(chip->trace_msg[idx].line >> 8); *(ptr++) = (u8)(chip->trace_msg[idx].line); - for (j = 0; j < MSG_FUNC_LEN; j++) + for (j = 0; j < MSG_FUNC_LEN; j++) { *(ptr++) = chip->trace_msg[idx].func[j]; - - for (j = 0; j < MSG_FILE_LEN; j++) + } + for (j = 0; j < MSG_FILE_LEN; j++) { *(ptr++) = chip->trace_msg[idx].file[j]; - - for (j = 0; j < TIME_VAL_LEN; j++) + } + for (j = 0; j < TIME_VAL_LEN; j++) { *(ptr++) = chip->trace_msg[idx].timeval_buf[j]; + } } rtsx_stor_set_xfer_buf(buf, scsi_bufflen(srb), srb); @@ -1401,19 +1424,20 @@ static int dma_access_ring_buffer(struct scsi_cmnd *srb, struct rtsx_chip *chip) len = ((u16)(srb->cmnd[4]) << 8) | srb->cmnd[5]; len = min(len, (u16)scsi_bufflen(srb)); - if (srb->sc_data_direction == DMA_FROM_DEVICE) + if (srb->sc_data_direction == DMA_FROM_DEVICE) { RTSX_DEBUGP("Read from device\n"); - else + } else { RTSX_DEBUGP("Write to device\n"); + } retval = rtsx_transfer_data(chip, 0, scsi_sglist(srb), len, scsi_sg_count(srb), srb->sc_data_direction, 1000); if (retval < 0) { - if (srb->sc_data_direction == DMA_FROM_DEVICE) + if (srb->sc_data_direction == DMA_FROM_DEVICE) { set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); - else + } else { set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_ERR); - + } TRACE_RET(chip, TRANSPORT_FAILED); } scsi_set_resid(srb, 0); @@ -1438,20 +1462,22 @@ static int get_dev_status(struct scsi_cmnd *srb, struct rtsx_chip *chip) status[0] = (u8)(chip->product_id); status[1] = chip->ic_version; - if (chip->auto_delink_en) + if (chip->auto_delink_en) { status[2] = 0x10; - else + } else { status[2] = 0x00; + } status[3] = 20; status[4] = 10; status[5] = 05; status[6] = 21; - if (chip->card_wp) + if (chip->card_wp) { status[7] = 0x20; - else + } else { status[7] = 0x00; + } #ifdef SUPPORT_OCP status[8] = 0; @@ -1463,60 +1489,67 @@ static int get_dev_status(struct scsi_cmnd *srb, struct rtsx_chip *chip) oc_ever_mask = SD_OC_EVER; } - if (chip->ocp_stat & oc_now_mask) + if (chip->ocp_stat & oc_now_mask) { status[8] |= 0x02; - - if (chip->ocp_stat & oc_ever_mask) + } + if (chip->ocp_stat & oc_ever_mask) { status[8] |= 0x01; + } #endif if (card == SD_CARD) { if (CHK_SD(sd_card)) { if (CHK_SD_HCXC(sd_card)) { - if (sd_card->capacity > 0x4000000) + if (sd_card->capacity > 0x4000000) { status[0x0E] = 0x02; - else + } else { status[0x0E] = 0x01; + } } else { status[0x0E] = 0x00; } - if (CHK_SD_SDR104(sd_card)) + if (CHK_SD_SDR104(sd_card)) { status[0x0F] = 0x03; - else if (CHK_SD_DDR50(sd_card)) + } else if (CHK_SD_DDR50(sd_card)) { status[0x0F] = 0x04; - else if (CHK_SD_SDR50(sd_card)) + } else if (CHK_SD_SDR50(sd_card)) { status[0x0F] = 0x02; - else if (CHK_SD_HS(sd_card)) + } else if (CHK_SD_HS(sd_card)) { status[0x0F] = 0x01; - else + } else { status[0x0F] = 0x00; + } } else { - if (CHK_MMC_SECTOR_MODE(sd_card)) + if (CHK_MMC_SECTOR_MODE(sd_card)) { status[0x0E] = 0x01; - else + } else { status[0x0E] = 0x00; + } - if (CHK_MMC_DDR52(sd_card)) + if (CHK_MMC_DDR52(sd_card)) { status[0x0F] = 0x03; - else if (CHK_MMC_52M(sd_card)) + } else if (CHK_MMC_52M(sd_card)) { status[0x0F] = 0x02; - else if (CHK_MMC_26M(sd_card)) + } else if (CHK_MMC_26M(sd_card)) { status[0x0F] = 0x01; - else + } else { status[0x0F] = 0x00; + } } } else if (card == MS_CARD) { if (CHK_MSPRO(ms_card)) { - if (CHK_MSXC(ms_card)) + if (CHK_MSXC(ms_card)) { status[0x0E] = 0x01; - else + } else { status[0x0E] = 0x00; + } - if (CHK_HG8BIT(ms_card)) + if (CHK_HG8BIT(ms_card)) { status[0x0F] = 0x01; - else + } else { status[0x0F] = 0x00; + } } } @@ -1567,35 +1600,37 @@ static int set_chip_mode(struct scsi_cmnd *srb, struct rtsx_chip *chip) if (phy_debug_mode) { chip->phy_debug_mode = 1; retval = rtsx_write_register(chip, CDRESUMECTL, 0x77, 0); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, TRANSPORT_FAILED); - + } rtsx_disable_bus_int(chip); retval = rtsx_read_phy_register(chip, 0x1C, ®); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, TRANSPORT_FAILED); - + } reg |= 0x0001; retval = rtsx_write_phy_register(chip, 0x1C, reg); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, TRANSPORT_FAILED); + } } else { chip->phy_debug_mode = 0; retval = rtsx_write_register(chip, CDRESUMECTL, 0x77, 0x77); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, TRANSPORT_FAILED); - + } rtsx_enable_bus_int(chip); retval = rtsx_read_phy_register(chip, 0x1C, ®); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, TRANSPORT_FAILED); - + } reg &= 0xFFFE; retval = rtsx_write_phy_register(chip, 0x1C, reg); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, TRANSPORT_FAILED); + } } return TRANSPORT_GOOD; @@ -1702,8 +1737,9 @@ static int read_phy_register(struct scsi_cmnd *srb, struct rtsx_chip *chip) if (len) { buf = (u8 *)vmalloc(len); - if (!buf) + if (!buf) { TRACE_RET(chip, TRANSPORT_ERROR); + } retval = rtsx_force_power_on(chip, SSC_PDCTL); if (retval != STATUS_SUCCESS) { @@ -1759,8 +1795,9 @@ static int write_phy_register(struct scsi_cmnd *srb, struct rtsx_chip *chip) len = (unsigned short)min(scsi_bufflen(srb), (unsigned int)len); buf = (u8 *)vmalloc(len); - if (buf == NULL) + if (buf == NULL) { TRACE_RET(chip, TRANSPORT_ERROR); + } rtsx_stor_get_xfer_buf(buf, len, srb); scsi_set_resid(srb, scsi_bufflen(srb) - len); @@ -1849,8 +1886,9 @@ static int read_eeprom2(struct scsi_cmnd *srb, struct rtsx_chip *chip) len = ((u16)srb->cmnd[6] << 8) | srb->cmnd[7]; buf = (u8 *)vmalloc(len); - if (!buf) + if (!buf) { TRACE_RET(chip, TRANSPORT_ERROR); + } retval = rtsx_force_power_on(chip, SSC_PDCTL); if (retval != STATUS_SUCCESS) { @@ -1896,8 +1934,9 @@ static int write_eeprom2(struct scsi_cmnd *srb, struct rtsx_chip *chip) len = (unsigned short)min(scsi_bufflen(srb), (unsigned int)len); buf = (u8 *)vmalloc(len); - if (buf == NULL) + if (buf == NULL) { TRACE_RET(chip, TRANSPORT_ERROR); + } rtsx_stor_get_xfer_buf(buf, len, srb); scsi_set_resid(srb, scsi_bufflen(srb) - len); @@ -1941,8 +1980,9 @@ static int read_efuse(struct scsi_cmnd *srb, struct rtsx_chip *chip) len = srb->cmnd[5]; buf = (u8 *)vmalloc(len); - if (!buf) + if (!buf) { TRACE_RET(chip, TRANSPORT_ERROR); + } retval = rtsx_force_power_on(chip, SSC_PDCTL); if (retval != STATUS_SUCCESS) { @@ -1989,8 +2029,9 @@ static int write_efuse(struct scsi_cmnd *srb, struct rtsx_chip *chip) len = (u8)min(scsi_bufflen(srb), (unsigned int)len); buf = (u8 *)vmalloc(len); - if (buf == NULL) + if (buf == NULL) { TRACE_RET(chip, TRANSPORT_ERROR); + } rtsx_stor_get_xfer_buf(buf, len, srb); scsi_set_resid(srb, scsi_bufflen(srb) - len); @@ -2052,23 +2093,27 @@ static int write_efuse(struct scsi_cmnd *srb, struct rtsx_chip *chip) vfree(buf); retval = card_power_off(chip, SPI_CARD); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, TRANSPORT_ERROR); + } if (chip->asic_code) { retval = rtsx_write_register(chip, PWR_GATE_CTRL, LDO3318_PWR_MASK, LDO_OFF); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, TRANSPORT_ERROR); + } wait_timeout(600); retval = rtsx_write_phy_register(chip, 0x08, val); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, TRANSPORT_ERROR); + } retval = rtsx_write_register(chip, PWR_GATE_CTRL, LDO3318_PWR_MASK, LDO_ON); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, TRANSPORT_ERROR); + } } return result; @@ -2095,10 +2140,11 @@ static int read_cfg_byte(struct scsi_cmnd *srb, struct rtsx_chip *chip) RTSX_DEBUGP("%s: func = %d, addr = 0x%x, len = %d\n", __func__, func, addr, len); - if (CHK_SDIO_EXIST(chip) && !CHK_SDIO_IGNORED(chip)) + if (CHK_SDIO_EXIST(chip) && !CHK_SDIO_IGNORED(chip)) { func_max = 1; - else + } else { func_max = 0; + } if (func > func_max) { set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); @@ -2106,8 +2152,9 @@ static int read_cfg_byte(struct scsi_cmnd *srb, struct rtsx_chip *chip) } buf = (u8 *)vmalloc(len); - if (!buf) + if (!buf) { TRACE_RET(chip, TRANSPORT_ERROR); + } retval = rtsx_read_cfg_seq(chip, func, addr, buf, len); if (retval != STATUS_SUCCESS) { @@ -2146,10 +2193,11 @@ static int write_cfg_byte(struct scsi_cmnd *srb, struct rtsx_chip *chip) RTSX_DEBUGP("%s: func = %d, addr = 0x%x\n", __func__, func, addr); - if (CHK_SDIO_EXIST(chip) && !CHK_SDIO_IGNORED(chip)) + if (CHK_SDIO_EXIST(chip) && !CHK_SDIO_IGNORED(chip)) { func_max = 1; - else + } else { func_max = 0; + } if (func > func_max) { set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); @@ -2158,8 +2206,9 @@ static int write_cfg_byte(struct scsi_cmnd *srb, struct rtsx_chip *chip) len = (unsigned short)min(scsi_bufflen(srb), (unsigned int)len); buf = (u8 *)vmalloc(len); - if (!buf) + if (!buf) { TRACE_RET(chip, TRANSPORT_ERROR); + } rtsx_stor_get_xfer_buf(buf, len, srb); scsi_set_resid(srb, scsi_bufflen(srb) - len); @@ -2279,56 +2328,63 @@ static int read_status(struct scsi_cmnd *srb, struct rtsx_chip *chip) rtsx_status[4] = (u8)lun; if (CHECK_LUN_MODE(chip, SD_MS_2LUN)) { - if (chip->lun2card[lun] == SD_CARD) + if (chip->lun2card[lun] == SD_CARD) { rtsx_status[5] = 2; - else + } else { rtsx_status[5] = 3; + } } else { if (chip->card_exist) { - if (chip->card_exist & XD_CARD) + if (chip->card_exist & XD_CARD) { rtsx_status[5] = 4; - else if (chip->card_exist & SD_CARD) + } else if (chip->card_exist & SD_CARD) { rtsx_status[5] = 2; - else if (chip->card_exist & MS_CARD) + } else if (chip->card_exist & MS_CARD) { rtsx_status[5] = 3; - else + } else { rtsx_status[5] = 7; + } } else { rtsx_status[5] = 7; } } - if (CHECK_LUN_MODE(chip, SD_MS_2LUN)) + if (CHECK_LUN_MODE(chip, SD_MS_2LUN)) { rtsx_status[6] = 2; - else + } else { rtsx_status[6] = 1; + } rtsx_status[7] = (u8)(chip->product_id); rtsx_status[8] = chip->ic_version; - if (check_card_exist(chip, lun)) + if (check_card_exist(chip, lun)) { rtsx_status[9] = 1; - else + } else { rtsx_status[9] = 0; + } - if (CHECK_LUN_MODE(chip, SD_MS_2LUN)) + if (CHECK_LUN_MODE(chip, SD_MS_2LUN)) { rtsx_status[10] = 0; - else + } else { rtsx_status[10] = 1; + } if (CHECK_LUN_MODE(chip, SD_MS_2LUN)) { - if (chip->lun2card[lun] == SD_CARD) + if (chip->lun2card[lun] == SD_CARD) { rtsx_status[11] = SD_CARD; - else + } else { rtsx_status[11] = MS_CARD; + } } else { rtsx_status[11] = XD_CARD | SD_CARD | MS_CARD; } - if (check_card_ready(chip, lun)) + if (check_card_ready(chip, lun)) { rtsx_status[12] = 1; - else + } else { rtsx_status[12] = 0; + } if (get_lun_card(chip, lun) == XD_CARD) { rtsx_status[13] = 0x40; @@ -2365,26 +2421,29 @@ static int read_status(struct scsi_cmnd *srb, struct rtsx_chip *chip) } else { if (CHECK_LUN_MODE(chip, DEFAULT_SINGLE)) { #ifdef SUPPORT_SDIO - if (chip->sd_io && chip->sd_int) + if (chip->sd_io && chip->sd_int) { rtsx_status[13] = 0x60; - else + } else { rtsx_status[13] = 0x70; + } #else rtsx_status[13] = 0x70; #endif } else { - if (chip->lun2card[lun] == SD_CARD) + if (chip->lun2card[lun] == SD_CARD) { rtsx_status[13] = 0x20; - else + } else { rtsx_status[13] = 0x30; + } } } rtsx_status[14] = 0x78; - if (CHK_SDIO_EXIST(chip) && !CHK_SDIO_IGNORED(chip)) + if (CHK_SDIO_EXIST(chip) && !CHK_SDIO_IGNORED(chip)) { rtsx_status[15] = 0x83; - else + } else { rtsx_status[15] = 0x82; + } buf_len = min(scsi_bufflen(srb), (unsigned int)sizeof(rtsx_status)); rtsx_stor_set_xfer_buf(rtsx_status, buf_len, srb); @@ -2423,7 +2482,7 @@ static int spi_vendor_cmd(struct scsi_cmnd *srb, struct rtsx_chip *chip) unsigned int lun = SCSI_LUN(srb); u8 gpio_dir; - if (CHECK_PID(chip, 0x5208) || CHECK_PID(chip, 0x5288)) { + if (CHECK_PID(chip, 0x5208) && CHECK_PID(chip, 0x5288)) { set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); TRACE_RET(chip, TRANSPORT_FAILED); } @@ -2479,8 +2538,9 @@ static int spi_vendor_cmd(struct scsi_cmnd *srb, struct rtsx_chip *chip) rtsx_write_register(chip, CARD_GPIO_DIR, 0x07, gpio_dir); - if (result != STATUS_SUCCESS) + if (result != STATUS_SUCCESS) { TRACE_RET(chip, TRANSPORT_FAILED); + } return TRANSPORT_GOOD; } @@ -2550,12 +2610,13 @@ void led_shine(struct scsi_cmnd *srb, struct rtsx_chip *chip) unsigned int lun = SCSI_LUN(srb); u16 sec_cnt; - if ((srb->cmnd[0] == READ_10) || (srb->cmnd[0] == WRITE_10)) + if ((srb->cmnd[0] == READ_10) || (srb->cmnd[0] == WRITE_10)) { sec_cnt = ((u16)(srb->cmnd[7]) << 8) | srb->cmnd[8]; - else if ((srb->cmnd[0] == READ_6) || (srb->cmnd[0] == WRITE_6)) + } else if ((srb->cmnd[0] == READ_6) || (srb->cmnd[0] == WRITE_6)) { sec_cnt = srb->cmnd[4]; - else + } else { return; + } if (chip->rw_cap[lun] >= GPIO_TOGGLE_THRESHOLD) { toggle_gpio(chip, LED_GPIO); @@ -2598,10 +2659,11 @@ static int ms_format_cmnd(struct scsi_cmnd *srb, struct rtsx_chip *chip) } rtsx_set_stat(chip, RTSX_STAT_RUN); - if (srb->cmnd[8] & 0x01) + if (srb->cmnd[8] & 0x01) { quick_format = 0; - else + } else { quick_format = 1; + } if (!(chip->card_ready & MS_CARD)) { set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT); @@ -2662,25 +2724,27 @@ static int get_ms_information(struct scsi_cmnd *srb, struct rtsx_chip *chip) TRACE_RET(chip, TRANSPORT_FAILED); } - if (dev_info_id == 0x15) + if (dev_info_id == 0x15) { buf_len = data_len = 0x3A; - else + } else { buf_len = data_len = 0x6A; + } buf = kmalloc(buf_len, GFP_KERNEL); - if (!buf) + if (!buf) { TRACE_RET(chip, TRANSPORT_ERROR); + } i = 0; /* GET Memory Stick Media Information Response Header */ buf[i++] = 0x00; /* Data length MSB */ buf[i++] = data_len; /* Data length LSB */ /* Device Information Type Code */ - if (CHK_MSXC(ms_card)) + if (CHK_MSXC(ms_card)) { buf[i++] = 0x03; - else + } else { buf[i++] = 0x02; - + } /* SGM bit */ buf[i++] = 0x01; /* Reserved */ @@ -2695,11 +2759,11 @@ static int get_ms_information(struct scsi_cmnd *srb, struct rtsx_chip *chip) /* Device Information ID Number */ buf[i++] = dev_info_id; /* Device Information Length */ - if (dev_info_id == 0x15) + if (dev_info_id == 0x15) { data_len = 0x31; - else + } else { data_len = 0x61; - + } buf[i++] = 0x00; /* Data length MSB */ buf[i++] = data_len; /* Data length LSB */ /* Valid Bit */ @@ -2714,10 +2778,11 @@ static int get_ms_information(struct scsi_cmnd *srb, struct rtsx_chip *chip) rtsx_stor_set_xfer_buf(buf, buf_len, srb); - if (dev_info_id == 0x15) + if (dev_info_id == 0x15) { scsi_set_resid(srb, scsi_bufflen(srb)-0x3C); - else + } else { scsi_set_resid(srb, scsi_bufflen(srb)-0x6C); + } kfree(buf); return STATUS_SUCCESS; @@ -2728,11 +2793,13 @@ static int ms_sp_cmnd(struct scsi_cmnd *srb, struct rtsx_chip *chip) { int retval = TRANSPORT_ERROR; - if (srb->cmnd[2] == MS_FORMAT) + if (srb->cmnd[2] == MS_FORMAT) { retval = ms_format_cmnd(srb, chip); + } #ifdef SUPPORT_PCGL_1P18 - else if (srb->cmnd[2] == GET_MS_INFORMATION) + else if (srb->cmnd[2] == GET_MS_INFORMATION) { retval = get_ms_information(srb, chip); + } #endif return retval; @@ -2845,9 +2912,9 @@ static int mg_report_key(struct scsi_cmnd *srb, struct rtsx_chip *chip) (srb->cmnd[8] == 0x04) && (srb->cmnd[9] == 0x1C)) { retval = mg_get_local_EKB(srb, chip); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, TRANSPORT_FAILED); - + } } else { set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); TRACE_RET(chip, TRANSPORT_FAILED); @@ -2859,9 +2926,9 @@ static int mg_report_key(struct scsi_cmnd *srb, struct rtsx_chip *chip) (srb->cmnd[8] == 0x00) && (srb->cmnd[9] == 0x24)) { retval = mg_get_rsp_chg(srb, chip); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, TRANSPORT_FAILED); - + } } else { set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); TRACE_RET(chip, TRANSPORT_FAILED); @@ -2878,9 +2945,9 @@ static int mg_report_key(struct scsi_cmnd *srb, struct rtsx_chip *chip) (srb->cmnd[4] == 0x00) && (srb->cmnd[5] < 32)) { retval = mg_get_ICV(srb, chip); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, TRANSPORT_FAILED); - + } } else { set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); TRACE_RET(chip, TRANSPORT_FAILED); @@ -2947,9 +3014,9 @@ static int mg_send_key(struct scsi_cmnd *srb, struct rtsx_chip *chip) (srb->cmnd[8] == 0x00) && (srb->cmnd[9] == 0x0C)) { retval = mg_set_leaf_id(srb, chip); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, TRANSPORT_FAILED); - + } } else { set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); TRACE_RET(chip, TRANSPORT_FAILED); @@ -2961,9 +3028,9 @@ static int mg_send_key(struct scsi_cmnd *srb, struct rtsx_chip *chip) (srb->cmnd[8] == 0x00) && (srb->cmnd[9] == 0x0C)) { retval = mg_chg(srb, chip); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, TRANSPORT_FAILED); - + } } else { set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); TRACE_RET(chip, TRANSPORT_FAILED); @@ -2975,9 +3042,9 @@ static int mg_send_key(struct scsi_cmnd *srb, struct rtsx_chip *chip) (srb->cmnd[8] == 0x00) && (srb->cmnd[9] == 0x0C)) { retval = mg_rsp(srb, chip); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, TRANSPORT_FAILED); - + } } else { set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); TRACE_RET(chip, TRANSPORT_FAILED); @@ -2994,9 +3061,9 @@ static int mg_send_key(struct scsi_cmnd *srb, struct rtsx_chip *chip) (srb->cmnd[4] == 0x00) && (srb->cmnd[5] < 32)) { retval = mg_set_ICV(srb, chip); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, TRANSPORT_FAILED); - + } } else { set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); TRACE_RET(chip, TRANSPORT_FAILED); diff --git a/trunk/drivers/staging/rts_pstor/rtsx_transport.c b/trunk/drivers/staging/rts_pstor/rtsx_transport.c index 1f9a42480443..54a474235f26 100644 --- a/trunk/drivers/staging/rts_pstor/rtsx_transport.c +++ b/trunk/drivers/staging/rts_pstor/rtsx_transport.c @@ -218,9 +218,9 @@ void rtsx_add_cmd(struct rtsx_chip *chip, val |= (u32)data; spin_lock_irq(&chip->rtsx->reg_lock); - if (chip->ci < (HOST_CMDS_BUF_LEN / 4)) + if (chip->ci < (HOST_CMDS_BUF_LEN / 4)) { cb[(chip->ci)++] = cpu_to_le32(val); - + } spin_unlock_irq(&chip->rtsx->reg_lock); } @@ -244,14 +244,15 @@ int rtsx_send_cmd(struct rtsx_chip *chip, u8 card, int timeout) long timeleft; int err = 0; - if (card == SD_CARD) + if (card == SD_CARD) { rtsx->check_card_cd = SD_EXIST; - else if (card == MS_CARD) + } else if (card == MS_CARD) { rtsx->check_card_cd = MS_EXIST; - else if (card == XD_CARD) + } else if (card == XD_CARD) { rtsx->check_card_cd = XD_EXIST; - else + } else { rtsx->check_card_cd = 0; + } spin_lock_irq(&rtsx->reg_lock); @@ -280,11 +281,11 @@ int rtsx_send_cmd(struct rtsx_chip *chip, u8 card, int timeout) } spin_lock_irq(&rtsx->reg_lock); - if (rtsx->trans_result == TRANS_RESULT_FAIL) + if (rtsx->trans_result == TRANS_RESULT_FAIL) { err = -EIO; - else if (rtsx->trans_result == TRANS_RESULT_OK) + } else if (rtsx->trans_result == TRANS_RESULT_OK) { err = 0; - + } spin_unlock_irq(&rtsx->reg_lock); finish_send_cmd: @@ -340,21 +341,23 @@ static int rtsx_transfer_sglist_adma_partial(struct rtsx_chip *chip, u8 card, if ((sg == NULL) || (num_sg <= 0) || !offset || !index) return -EIO; - if (dma_dir == DMA_TO_DEVICE) + if (dma_dir == DMA_TO_DEVICE) { dir = HOST_TO_DEVICE; - else if (dma_dir == DMA_FROM_DEVICE) + } else if (dma_dir == DMA_FROM_DEVICE) { dir = DEVICE_TO_HOST; - else + } else { return -ENXIO; + } - if (card == SD_CARD) + if (card == SD_CARD) { rtsx->check_card_cd = SD_EXIST; - else if (card == MS_CARD) + } else if (card == MS_CARD) { rtsx->check_card_cd = MS_EXIST; - else if (card == XD_CARD) + } else if (card == XD_CARD) { rtsx->check_card_cd = XD_EXIST; - else + } else { rtsx->check_card_cd = 0; + } spin_lock_irq(&rtsx->reg_lock); @@ -402,10 +405,11 @@ static int rtsx_transfer_sglist_adma_partial(struct rtsx_chip *chip, u8 card, *offset = 0; *index = *index + 1; } - if ((i == (sg_cnt - 1)) || !resid) + if ((i == (sg_cnt - 1)) || !resid) { option = SG_VALID | SG_END | SG_TRANS_DATA; - else + } else { option = SG_VALID | SG_TRANS_DATA; + } rtsx_add_sg_tbl(chip, (u32)addr, (u32)len, option); @@ -464,11 +468,11 @@ static int rtsx_transfer_sglist_adma_partial(struct rtsx_chip *chip, u8 card, } spin_lock_irq(&rtsx->reg_lock); - if (rtsx->trans_result == TRANS_RESULT_FAIL) + if (rtsx->trans_result == TRANS_RESULT_FAIL) { err = -EIO; - else if (rtsx->trans_result == TRANS_RESULT_OK) + } else if (rtsx->trans_result == TRANS_RESULT_OK) { err = 0; - + } spin_unlock_irq(&rtsx->reg_lock); out: @@ -497,21 +501,23 @@ static int rtsx_transfer_sglist_adma(struct rtsx_chip *chip, u8 card, if ((sg == NULL) || (num_sg <= 0)) return -EIO; - if (dma_dir == DMA_TO_DEVICE) + if (dma_dir == DMA_TO_DEVICE) { dir = HOST_TO_DEVICE; - else if (dma_dir == DMA_FROM_DEVICE) + } else if (dma_dir == DMA_FROM_DEVICE) { dir = DEVICE_TO_HOST; - else + } else { return -ENXIO; + } - if (card == SD_CARD) + if (card == SD_CARD) { rtsx->check_card_cd = SD_EXIST; - else if (card == MS_CARD) + } else if (card == MS_CARD) { rtsx->check_card_cd = MS_EXIST; - else if (card == XD_CARD) + } else if (card == XD_CARD) { rtsx->check_card_cd = XD_EXIST; - else + } else { rtsx->check_card_cd = 0; + } spin_lock_irq(&rtsx->reg_lock); @@ -531,10 +537,11 @@ static int rtsx_transfer_sglist_adma(struct rtsx_chip *chip, u8 card, u32 val = TRIG_DMA; int sg_cnt, j; - if (i == buf_cnt / (HOST_SG_TBL_BUF_LEN / 8)) + if (i == buf_cnt / (HOST_SG_TBL_BUF_LEN / 8)) { sg_cnt = buf_cnt % (HOST_SG_TBL_BUF_LEN / 8); - else + } else { sg_cnt = (HOST_SG_TBL_BUF_LEN / 8); + } chip->sgi = 0; for (j = 0; j < sg_cnt; j++) { @@ -545,10 +552,11 @@ static int rtsx_transfer_sglist_adma(struct rtsx_chip *chip, u8 card, RTSX_DEBUGP("DMA addr: 0x%x, Len: 0x%x\n", (unsigned int)addr, len); - if (j == (sg_cnt - 1)) + if (j == (sg_cnt - 1)) { option = SG_VALID | SG_END | SG_TRANS_DATA; - else + } else { option = SG_VALID | SG_TRANS_DATA; + } rtsx_add_sg_tbl(chip, (u32)addr, (u32)len, option); @@ -607,11 +615,11 @@ static int rtsx_transfer_sglist_adma(struct rtsx_chip *chip, u8 card, } spin_lock_irq(&rtsx->reg_lock); - if (rtsx->trans_result == TRANS_RESULT_FAIL) + if (rtsx->trans_result == TRANS_RESULT_FAIL) { err = -EIO; - else if (rtsx->trans_result == TRANS_RESULT_OK) + } else if (rtsx->trans_result == TRANS_RESULT_OK) { err = 0; - + } spin_unlock_irq(&rtsx->reg_lock); out: @@ -639,25 +647,27 @@ static int rtsx_transfer_buf(struct rtsx_chip *chip, u8 card, void *buf, size_t if ((buf == NULL) || (len <= 0)) return -EIO; - if (dma_dir == DMA_TO_DEVICE) + if (dma_dir == DMA_TO_DEVICE) { dir = HOST_TO_DEVICE; - else if (dma_dir == DMA_FROM_DEVICE) + } else if (dma_dir == DMA_FROM_DEVICE) { dir = DEVICE_TO_HOST; - else + } else { return -ENXIO; + } addr = dma_map_single(&(rtsx->pci->dev), buf, len, dma_dir); if (!addr) return -ENOMEM; - if (card == SD_CARD) + if (card == SD_CARD) { rtsx->check_card_cd = SD_EXIST; - else if (card == MS_CARD) + } else if (card == MS_CARD) { rtsx->check_card_cd = MS_EXIST; - else if (card == XD_CARD) + } else if (card == XD_CARD) { rtsx->check_card_cd = XD_EXIST; - else + } else { rtsx->check_card_cd = 0; + } val |= (u32)(dir & 0x01) << 29; val |= (u32)(len & 0x00FFFFFF); @@ -688,11 +698,11 @@ static int rtsx_transfer_buf(struct rtsx_chip *chip, u8 card, void *buf, size_t } spin_lock_irq(&rtsx->reg_lock); - if (rtsx->trans_result == TRANS_RESULT_FAIL) + if (rtsx->trans_result == TRANS_RESULT_FAIL) { err = -EIO; - else if (rtsx->trans_result == TRANS_RESULT_OK) + } else if (rtsx->trans_result == TRANS_RESULT_OK) { err = 0; - + } spin_unlock_irq(&rtsx->reg_lock); out: diff --git a/trunk/drivers/staging/rts_pstor/sd.c b/trunk/drivers/staging/rts_pstor/sd.c index c6a581c47cbc..3cc9a489e4e8 100644 --- a/trunk/drivers/staging/rts_pstor/sd.c +++ b/trunk/drivers/staging/rts_pstor/sd.c @@ -192,9 +192,9 @@ static int sd_send_cmd_get_rsp(struct rtsx_chip *chip, u8 cmd_idx, stat_idx = 16; } else if (rsp_type != SD_RSP_TYPE_R0) { - for (reg_addr = REG_SD_CMD0; reg_addr <= REG_SD_CMD4; reg_addr++) + for (reg_addr = REG_SD_CMD0; reg_addr <= REG_SD_CMD4; reg_addr++) { rtsx_add_cmd(chip, READ_REG_CMD, reg_addr, 0, 0); - + } stat_idx = 5; } @@ -273,8 +273,9 @@ static int sd_send_cmd_get_rsp(struct rtsx_chip *chip, u8 cmd_idx, if ((rsp_type == SD_RSP_TYPE_R1) || (rsp_type == SD_RSP_TYPE_R1b)) { if ((cmd_idx != SEND_RELATIVE_ADDR) && (cmd_idx != SEND_IF_COND)) { if (cmd_idx != STOP_TRANSMISSION) { - if (ptr[1] & 0x80) + if (ptr[1] & 0x80) { TRACE_RET(chip, STATUS_FAIL); + } } #ifdef SUPPORT_SD_LOCK if (ptr[1] & 0x7D) @@ -293,10 +294,11 @@ static int sd_send_cmd_get_rsp(struct rtsx_chip *chip, u8 cmd_idx, RTSX_DEBUGP("ptr[3]: 0x%02x\n", ptr[3]); TRACE_RET(chip, STATUS_FAIL); } - if (ptr[3] & 0x01) + if (ptr[3] & 0x01) { sd_card->sd_data_buf_ready = 1; - else + } else { sd_card->sd_data_buf_ready = 0; + } } } @@ -320,15 +322,17 @@ static int sd_read_data(struct rtsx_chip *chip, if (!buf) buf_len = 0; - if (buf_len > 512) + if (buf_len > 512) { TRACE_RET(chip, STATUS_FAIL); + } rtsx_init_cmd(chip); if (cmd_len) { RTSX_DEBUGP("SD/MMC CMD %d\n", cmd[0] - 0x40); - for (i = 0; i < (cmd_len < 6 ? cmd_len : 6); i++) + for (i = 0; i < (cmd_len < 6 ? cmd_len : 6); i++) { rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD0 + i, 0xFF, cmd[i]); + } } rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_L, 0xFF, (u8)byte_cnt); rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_H, 0xFF, (u8)(byte_cnt >> 8)); @@ -340,9 +344,9 @@ static int sd_read_data(struct rtsx_chip *chip, rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG2, 0xFF, SD_CALCULATE_CRC7 | SD_CHECK_CRC16 | SD_NO_WAIT_BUSY_END | SD_CHECK_CRC7 | SD_RSP_LEN_6); - if (trans_mode != SD_TM_AUTO_TUNING) + if (trans_mode != SD_TM_AUTO_TUNING) { rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, PINGPONG_BUFFER); - + } rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER, 0xFF, trans_mode | SD_TRANSFER_START); rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER, SD_TRANSFER_END, SD_TRANSFER_END); @@ -358,8 +362,9 @@ static int sd_read_data(struct rtsx_chip *chip, if (buf && buf_len) { retval = rtsx_read_ppbuf(chip, buf, buf_len); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } } return STATUS_SUCCESS; @@ -385,8 +390,9 @@ static int sd_write_data(struct rtsx_chip *chip, u8 trans_mode, if (buf && buf_len) { retval = rtsx_write_ppbuf(chip, buf, buf_len); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } } rtsx_init_cmd(chip); @@ -444,13 +450,15 @@ static int sd_check_csd(struct rtsx_chip *chip, char check_wp) break; } - if (i == 6) + if (i == 6) { TRACE_RET(chip, STATUS_FAIL); + } memcpy(sd_card->raw_csd, rsp + 1, 15); - if (CHECK_PID(chip, 0x5209)) + if (CHECK_PID(chip, 0x5209)) { RTSX_READ_REG(chip, REG_SD_CMD5, sd_card->raw_csd + 15); + } RTSX_DEBUGP("CSD Response:\n"); RTSX_DUMP(sd_card->raw_csd, 16); @@ -461,34 +469,35 @@ static int sd_check_csd(struct rtsx_chip *chip, char check_wp) trans_speed = rsp[4]; if ((trans_speed & 0x07) == 0x02) { if ((trans_speed & 0xf8) >= 0x30) { - if (chip->asic_code) + if (chip->asic_code) { sd_card->sd_clock = 47; - else + } else { sd_card->sd_clock = CLK_50; - + } } else if ((trans_speed & 0xf8) == 0x28) { - if (chip->asic_code) + if (chip->asic_code) { sd_card->sd_clock = 39; - else + } else { sd_card->sd_clock = CLK_40; - + } } else if ((trans_speed & 0xf8) == 0x20) { - if (chip->asic_code) + if (chip->asic_code) { sd_card->sd_clock = 29; - else + } else { sd_card->sd_clock = CLK_30; - + } } else if ((trans_speed & 0xf8) >= 0x10) { - if (chip->asic_code) + if (chip->asic_code) { sd_card->sd_clock = 23; - else + } else { sd_card->sd_clock = CLK_20; - + } } else if ((trans_speed & 0x08) >= 0x08) { - if (chip->asic_code) + if (chip->asic_code) { sd_card->sd_clock = 19; - else + } else { sd_card->sd_clock = CLK_20; + } } else { TRACE_RET(chip, STATUS_FAIL); } @@ -518,9 +527,9 @@ static int sd_check_csd(struct rtsx_chip *chip, char check_wp) } if (check_wp) { - if (rsp[15] & 0x30) + if (rsp[15] & 0x30) { chip->card_wp |= SD_CARD; - + } RTSX_DEBUGP("CSD WP Status: 0x%x\n", rsp[15]); } @@ -559,21 +568,22 @@ static int sd_set_sample_push_timing(struct rtsx_chip *chip) CRC_FIX_CLK | SD30_VAR_CLK0 | SAMPLE_VAR_CLK1); RTSX_WRITE_REG(chip, CLK_CTL, CLK_LOW_FREQ, 0); - if ((chip->sd_ctl & SD_PUSH_POINT_CTL_MASK) == SD_PUSH_POINT_AUTO) + if ((chip->sd_ctl & SD_PUSH_POINT_CTL_MASK) == SD_PUSH_POINT_AUTO) { val = SD20_TX_NEG_EDGE; - else if ((chip->sd_ctl & SD_PUSH_POINT_CTL_MASK) == SD_PUSH_POINT_DELAY) + } else if ((chip->sd_ctl & SD_PUSH_POINT_CTL_MASK) == SD_PUSH_POINT_DELAY) { val = SD20_TX_14_AHEAD; - else + } else { val = SD20_TX_NEG_EDGE; - + } RTSX_WRITE_REG(chip, SD_PUSH_POINT_CTL, SD20_TX_SEL_MASK, val); if ((chip->sd_ctl & SD_SAMPLE_POINT_CTL_MASK) == SD_SAMPLE_POINT_AUTO) { if (chip->asic_code) { - if (CHK_SD_HS(sd_card) || CHK_MMC_52M(sd_card)) + if (CHK_SD_HS(sd_card) || CHK_MMC_52M(sd_card)) { val = SD20_RX_14_DELAY; - else + } else { val = SD20_RX_POS_EDGE; + } } else { val = SD20_RX_14_DELAY; } @@ -587,28 +597,32 @@ static int sd_set_sample_push_timing(struct rtsx_chip *chip) } else { u8 val = 0; - if ((chip->sd_ctl & SD_PUSH_POINT_CTL_MASK) == SD_PUSH_POINT_DELAY) + if ((chip->sd_ctl & SD_PUSH_POINT_CTL_MASK) == SD_PUSH_POINT_DELAY) { val |= 0x10; + } if ((chip->sd_ctl & SD_SAMPLE_POINT_CTL_MASK) == SD_SAMPLE_POINT_AUTO) { if (chip->asic_code) { if (CHK_SD_HS(sd_card) || CHK_MMC_52M(sd_card)) { - if (val & 0x10) + if (val & 0x10) { val |= 0x04; - else + } else { val |= 0x08; + } } } else { - if (val & 0x10) + if (val & 0x10) { val |= 0x04; - else + } else { val |= 0x08; + } } } else if ((chip->sd_ctl & SD_SAMPLE_POINT_CTL_MASK) == SD_SAMPLE_POINT_DELAY) { - if (val & 0x10) + if (val & 0x10) { val |= 0x04; - else + } else { val |= 0x08; + } } RTSX_WRITE_REG(chip, REG_SD_CFG1, 0x1C, val); @@ -622,40 +636,41 @@ static void sd_choose_proper_clock(struct rtsx_chip *chip) struct sd_info *sd_card = &(chip->sd_card); if (CHK_SD_SDR104(sd_card)) { - if (chip->asic_code) + if (chip->asic_code) { sd_card->sd_clock = chip->asic_sd_sdr104_clk; - else + } else { sd_card->sd_clock = chip->fpga_sd_sdr104_clk; - + } } else if (CHK_SD_DDR50(sd_card)) { - if (chip->asic_code) + if (chip->asic_code) { sd_card->sd_clock = chip->asic_sd_ddr50_clk; - else + } else { sd_card->sd_clock = chip->fpga_sd_ddr50_clk; - + } } else if (CHK_SD_SDR50(sd_card)) { - if (chip->asic_code) + if (chip->asic_code) { sd_card->sd_clock = chip->asic_sd_sdr50_clk; - else + } else { sd_card->sd_clock = chip->fpga_sd_sdr50_clk; - + } } else if (CHK_SD_HS(sd_card)) { - if (chip->asic_code) + if (chip->asic_code) { sd_card->sd_clock = chip->asic_sd_hs_clk; - else + } else { sd_card->sd_clock = chip->fpga_sd_hs_clk; - + } } else if (CHK_MMC_52M(sd_card) || CHK_MMC_DDR52(sd_card)) { - if (chip->asic_code) + if (chip->asic_code) { sd_card->sd_clock = chip->asic_mmc_52m_clk; - else + } else { sd_card->sd_clock = chip->fpga_mmc_52m_clk; - + } } else if (CHK_MMC_26M(sd_card)) { - if (chip->asic_code) + if (chip->asic_code) { sd_card->sd_clock = 48; - else + } else { sd_card->sd_clock = CLK_50; + } } } @@ -668,12 +683,13 @@ static int sd_set_clock_divider(struct rtsx_chip *chip, u8 clk_div) val = clk_div; } else { mask = 0x60; - if (clk_div == SD_CLK_DIVIDE_0) + if (clk_div == SD_CLK_DIVIDE_0) { val = 0x00; - else if (clk_div == SD_CLK_DIVIDE_128) + } else if (clk_div == SD_CLK_DIVIDE_128) { val = 0x40; - else if (clk_div == SD_CLK_DIVIDE_256) + } else if (clk_div == SD_CLK_DIVIDE_256) { val = 0x20; + } } RTSX_WRITE_REG(chip, REG_SD_CFG1, mask, val); @@ -687,14 +703,16 @@ static int sd_set_init_para(struct rtsx_chip *chip) int retval; retval = sd_set_sample_push_timing(chip); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } sd_choose_proper_clock(chip); retval = switch_clock(chip, sd_card->sd_clock); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } return STATUS_SUCCESS; } @@ -717,8 +735,9 @@ int sd_select_card(struct rtsx_chip *chip, int select) } retval = sd_send_cmd_get_rsp(chip, cmd_idx, addr, cmd_type, NULL, 0); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } return STATUS_SUCCESS; } @@ -731,18 +750,21 @@ static int sd_update_lock_status(struct rtsx_chip *chip) u8 rsp[5]; retval = sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr, SD_RSP_TYPE_R1, rsp, 5); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } - if (rsp[1] & 0x02) + if (rsp[1] & 0x02) { sd_card->sd_lock_status |= SD_LOCKED; - else + } else { sd_card->sd_lock_status &= ~SD_LOCKED; + } RTSX_DEBUGP("sd_card->sd_lock_status = 0x%x\n", sd_card->sd_lock_status); - if (rsp[1] & 0x01) + if (rsp[1] & 0x01) { TRACE_RET(chip, STATUS_FAIL); + } return STATUS_SUCCESS; } @@ -757,11 +779,13 @@ static int sd_wait_state_data_ready(struct rtsx_chip *chip, u8 state, u8 data_re for (i = 0; i < polling_cnt; i++) { retval = sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr, SD_RSP_TYPE_R1, rsp, 5); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } - if (((rsp[3] & 0x1E) == state) && ((rsp[3] & 0x01) == data_ready)) + if (((rsp[3] & 0x1E) == state) && ((rsp[3] & 0x01) == data_ready)) { return STATUS_SUCCESS; + } } TRACE_RET(chip, STATUS_FAIL); @@ -774,16 +798,18 @@ static int sd_change_bank_voltage(struct rtsx_chip *chip, u8 voltage) if (voltage == SD_IO_3V3) { if (chip->asic_code) { retval = rtsx_write_phy_register(chip, 0x08, 0x4FC0 | chip->phy_voltage); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } } else { RTSX_WRITE_REG(chip, SD_PAD_CTL, SD_IO_USING_1V8, 0); } } else if (voltage == SD_IO_1V8) { if (chip->asic_code) { retval = rtsx_write_phy_register(chip, 0x08, 0x4C40 | chip->phy_voltage); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } } else { RTSX_WRITE_REG(chip, SD_PAD_CTL, SD_IO_USING_1V8, SD_IO_USING_1V8); } @@ -802,8 +828,9 @@ static int sd_voltage_switch(struct rtsx_chip *chip) RTSX_WRITE_REG(chip, SD_BUS_STAT, SD_CLK_TOGGLE_EN | SD_CLK_FORCE_STOP, SD_CLK_TOGGLE_EN); retval = sd_send_cmd_get_rsp(chip, VOLTAGE_SWITCH, 0, SD_RSP_TYPE_R1, NULL, 0); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } udelay(chip->sd_voltage_switch_delay); @@ -815,9 +842,9 @@ static int sd_voltage_switch(struct rtsx_chip *chip) RTSX_WRITE_REG(chip, SD_BUS_STAT, 0xFF, SD_CLK_FORCE_STOP); retval = sd_change_bank_voltage(chip, SD_IO_1V8); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); - + } wait_timeout(50); RTSX_WRITE_REG(chip, SD_BUS_STAT, 0xFF, SD_CLK_TOGGLE_EN); @@ -866,8 +893,9 @@ static int sd_change_phase(struct rtsx_chip *chip, u8 sample_point, u8 tune_dir) if (tune_dir == TUNE_RX) { SD_VP_CTL = SD_VPRX_CTL; SD_DCMPS_CTL = SD_DCMPS_RX_CTL; - if (CHK_SD_DDR50(sd_card)) + if (CHK_SD_DDR50(sd_card)) { ddr_rx = 1; + } } else { SD_VP_CTL = SD_VPTX_CTL; SD_DCMPS_CTL = SD_DCMPS_TX_CTL; @@ -904,22 +932,23 @@ static int sd_change_phase(struct rtsx_chip *chip, u8 sample_point, u8 tune_dir) rtsx_add_cmd(chip, WRITE_REG_CMD, SD_DCMPS_CTL, DCMPS_CHANGE, DCMPS_CHANGE); rtsx_add_cmd(chip, CHECK_REG_CMD, SD_DCMPS_CTL, DCMPS_CHANGE_DONE, DCMPS_CHANGE_DONE); retval = rtsx_send_cmd(chip, SD_CARD, 100); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_GOTO(chip, Fail); + } val = *rtsx_get_cmd_data(chip); - if (val & DCMPS_ERROR) + if (val & DCMPS_ERROR) { TRACE_GOTO(chip, Fail); - - if ((val & DCMPS_CURRENT_PHASE) != sample_point) + } + if ((val & DCMPS_CURRENT_PHASE) != sample_point) { TRACE_GOTO(chip, Fail); - + } RTSX_WRITE_REG(chip, SD_DCMPS_CTL, DCMPS_CHANGE, 0); - if (ddr_rx) + if (ddr_rx) { RTSX_WRITE_REG(chip, SD_VP_CTL, PHASE_CHANGE, 0); - else + } else { RTSX_WRITE_REG(chip, CLK_CTL, CHANGE_CLK, 0); - + } udelay(50); } @@ -949,8 +978,9 @@ static int sd_check_spec(struct rtsx_chip *chip, u8 bus_width) u8 cmd[5], buf[8]; retval = sd_send_cmd_get_rsp(chip, APP_CMD, sd_card->sd_addr, SD_RSP_TYPE_R1, NULL, 0); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } cmd[0] = 0x40 | SEND_SCR; cmd[1] = 0; @@ -966,8 +996,9 @@ static int sd_check_spec(struct rtsx_chip *chip, u8 bus_width) memcpy(sd_card->raw_scr, buf, 8); - if ((buf[0] & 0x0F) == 0) + if ((buf[0] & 0x0F) == 0) { TRACE_RET(chip, STATUS_FAIL); + } return STATUS_SUCCESS; } @@ -1141,12 +1172,13 @@ static int sd_check_switch_mode(struct rtsx_chip *chip, u8 mode, */ u16 cc = ((u16)buf[0] << 8) | buf[1]; RTSX_DEBUGP("Maximum current consumption: %dmA\n", cc); - if ((cc == 0) || (cc > 800)) + if ((cc == 0) || (cc > 800)) { TRACE_RET(chip, STATUS_FAIL); - + } retval = sd_query_switch_result(chip, func_group, func_to_switch, buf, 64); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } if ((cc > 400) || (func_to_switch > CURRENT_LIMIT_400)) { RTSX_WRITE_REG(chip, OCPPARA2, SD_OCP_THD_MASK, chip->sd_800mA_ocp_thd); @@ -1160,12 +1192,13 @@ static int sd_check_switch_mode(struct rtsx_chip *chip, u8 mode, static u8 downgrade_switch_mode(u8 func_group, u8 func_to_switch) { if (func_group == SD_FUNC_GROUP_1) { - if (func_to_switch > HS_SUPPORT) + if (func_to_switch > HS_SUPPORT) { func_to_switch--; - + } } else if (func_group == SD_FUNC_GROUP_4) { - if (func_to_switch > CURRENT_LIMIT_200) + if (func_to_switch > CURRENT_LIMIT_200) { func_to_switch--; + } } return func_to_switch; @@ -1208,8 +1241,9 @@ static int sd_check_switch(struct rtsx_chip *chip, wait_timeout(20); } - if (!switch_good) + if (!switch_good) { TRACE_RET(chip, STATUS_FAIL); + } return STATUS_SUCCESS; } @@ -1224,8 +1258,9 @@ static int sd_switch_function(struct rtsx_chip *chip, u8 bus_width) /* Get supported functions */ retval = sd_check_switch_mode(chip, SD_CHECK_MODE, NO_ARGUMENT, NO_ARGUMENT, bus_width); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } sd_card->func_group1_mask &= ~(sd_card->sd_switch_fail); @@ -1254,9 +1289,9 @@ static int sd_switch_function(struct rtsx_chip *chip, u8 bus_width) break; case HS_SUPPORT: - if (sd_card->func_group1_mask & HS_SUPPORT_MASK) + if (sd_card->func_group1_mask & HS_SUPPORT_MASK) { func_to_switch = HS_SUPPORT; - + } break; default: @@ -1264,9 +1299,9 @@ static int sd_switch_function(struct rtsx_chip *chip, u8 bus_width) } - if (func_to_switch) + if (func_to_switch) { break; - + } } RTSX_DEBUGP("SD_FUNC_GROUP_1: func_to_switch = 0x%02x", func_to_switch); @@ -1295,21 +1330,23 @@ static int sd_switch_function(struct rtsx_chip *chip, u8 bus_width) TRACE_RET(chip, STATUS_FAIL); } - if (func_to_switch == SDR104_SUPPORT) + if (func_to_switch == SDR104_SUPPORT) { SET_SD_SDR104(sd_card); - else if (func_to_switch == DDR50_SUPPORT) + } else if (func_to_switch == DDR50_SUPPORT) { SET_SD_DDR50(sd_card); - else if (func_to_switch == SDR50_SUPPORT) + } else if (func_to_switch == SDR50_SUPPORT) { SET_SD_SDR50(sd_card); - else + } else { SET_SD_HS(sd_card); + } } if (CHK_SD_DDR50(sd_card)) { RTSX_WRITE_REG(chip, SD_PUSH_POINT_CTL, 0x06, 0x04); retval = sd_set_sample_push_timing(chip); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } } if (!func_to_switch || (func_to_switch == HS_SUPPORT)) { @@ -1325,35 +1362,36 @@ static int sd_switch_function(struct rtsx_chip *chip, u8 bus_width) for (i = 0; i < 4; i++) { switch ((u8)(chip->sd_current_prior >> (i*8))) { case CURRENT_LIMIT_800: - if (sd_card->func_group4_mask & CURRENT_LIMIT_800_MASK) + if (sd_card->func_group4_mask & CURRENT_LIMIT_800_MASK) { func_to_switch = CURRENT_LIMIT_800; - + } break; case CURRENT_LIMIT_600: - if (sd_card->func_group4_mask & CURRENT_LIMIT_600_MASK) + if (sd_card->func_group4_mask & CURRENT_LIMIT_600_MASK) { func_to_switch = CURRENT_LIMIT_600; - + } break; case CURRENT_LIMIT_400: - if (sd_card->func_group4_mask & CURRENT_LIMIT_400_MASK) + if (sd_card->func_group4_mask & CURRENT_LIMIT_400_MASK) { func_to_switch = CURRENT_LIMIT_400; - + } break; case CURRENT_LIMIT_200: - if (sd_card->func_group4_mask & CURRENT_LIMIT_200_MASK) + if (sd_card->func_group4_mask & CURRENT_LIMIT_200_MASK) { func_to_switch = CURRENT_LIMIT_200; - + } break; default: continue; } - if (func_to_switch != 0xFF) + if (func_to_switch != 0xFF) { break; + } } RTSX_DEBUGP("SD_FUNC_GROUP_4: func_to_switch = 0x%02x", func_to_switch); @@ -1361,14 +1399,16 @@ static int sd_switch_function(struct rtsx_chip *chip, u8 bus_width) if (func_to_switch <= CURRENT_LIMIT_800) { retval = sd_check_switch(chip, SD_FUNC_GROUP_4, func_to_switch, bus_width); if (retval != STATUS_SUCCESS) { - if (sd_check_err_code(chip, SD_NO_CARD)) + if (sd_check_err_code(chip, SD_NO_CARD)) { TRACE_RET(chip, STATUS_FAIL); + } } RTSX_DEBUGP("Switch current limit finished! (%d)\n", retval); } - if (CHK_SD_DDR50(sd_card)) + if (CHK_SD_DDR50(sd_card)) { RTSX_WRITE_REG(chip, SD_PUSH_POINT_CTL, 0x06, 0); + } return STATUS_SUCCESS; } @@ -1398,8 +1438,9 @@ static int sd_sdr_tuning_rx_cmd(struct rtsx_chip *chip, u8 sample_point) u8 cmd[5]; retval = sd_change_phase(chip, sample_point, TUNE_RX); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } cmd[0] = 0x40 | SEND_TUNING_PATTERN; cmd[1] = 0; @@ -1426,14 +1467,16 @@ static int sd_ddr_tuning_rx_cmd(struct rtsx_chip *chip, u8 sample_point) u8 cmd[5]; retval = sd_change_phase(chip, sample_point, TUNE_RX); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } RTSX_DEBUGP("sd ddr tuning rx\n"); retval = sd_send_cmd_get_rsp(chip, APP_CMD, sd_card->sd_addr, SD_RSP_TYPE_R1, NULL, 0); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } cmd[0] = 0x40 | SD_STATUS; cmd[1] = 0; @@ -1459,16 +1502,18 @@ static int mmc_ddr_tunning_rx_cmd(struct rtsx_chip *chip, u8 sample_point) int retval; u8 cmd[5], bus_width; - if (CHK_MMC_8BIT(sd_card)) + if (CHK_MMC_8BIT(sd_card)) { bus_width = SD_BUS_WIDTH_8; - else if (CHK_MMC_4BIT(sd_card)) + } else if (CHK_MMC_4BIT(sd_card)) { bus_width = SD_BUS_WIDTH_4; - else + } else { bus_width = SD_BUS_WIDTH_1; + } retval = sd_change_phase(chip, sample_point, TUNE_RX); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } RTSX_DEBUGP("mmc ddr tuning rx\n"); @@ -1496,8 +1541,9 @@ static int sd_sdr_tuning_tx_cmd(struct rtsx_chip *chip, u8 sample_point) int retval; retval = sd_change_phase(chip, sample_point, TUNE_TX); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } RTSX_WRITE_REG(chip, SD_CFG3, SD_RSP_80CLK_TIMEOUT_EN, SD_RSP_80CLK_TIMEOUT_EN); @@ -1522,23 +1568,26 @@ static int sd_ddr_tuning_tx_cmd(struct rtsx_chip *chip, u8 sample_point) u8 cmd[5], bus_width; retval = sd_change_phase(chip, sample_point, TUNE_TX); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } if (CHK_SD(sd_card)) { bus_width = SD_BUS_WIDTH_4; } else { - if (CHK_MMC_8BIT(sd_card)) + if (CHK_MMC_8BIT(sd_card)) { bus_width = SD_BUS_WIDTH_8; - else if (CHK_MMC_4BIT(sd_card)) + } else if (CHK_MMC_4BIT(sd_card)) { bus_width = SD_BUS_WIDTH_4; - else + } else { bus_width = SD_BUS_WIDTH_1; + } } retval = sd_wait_state_data_ready(chip, 0x08, 1, 1000); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } RTSX_WRITE_REG(chip, SD_CFG3, SD_RSP_80CLK_TIMEOUT_EN, SD_RSP_80CLK_TIMEOUT_EN); @@ -1572,10 +1621,11 @@ static u8 sd_search_final_phase(struct rtsx_chip *chip, u32 phase_map, u8 tune_d u8 final_phase = 0xFF; if (phase_map == 0xFFFFFFFF) { - if (tune_dir == TUNE_RX) + if (tune_dir == TUNE_RX) { final_phase = (u8)chip->sd_default_rx_phase; - else + } else { final_phase = (u8)chip->sd_default_tx_phase; + } goto Search_Finish; } @@ -1616,9 +1666,9 @@ static u8 sd_search_final_phase(struct rtsx_chip *chip, u32 phase_map, u8 tune_d path[0].start = path[cont_path_cnt - 1].start - MAX_PHASE - 1; path[0].len += path[cont_path_cnt - 1].len; path[0].mid = path[0].start + path[0].len / 2; - if (path[0].mid < 0) + if (path[0].mid < 0) { path[0].mid += MAX_PHASE + 1; - + } cont_path_cnt--; } @@ -1646,10 +1696,11 @@ static u8 sd_search_final_phase(struct rtsx_chip *chip, u32 phase_map, u8 tune_d int temp_final_phase = path[final_path_idx].end - (max_len - (6 + temp_mid)); - if (temp_final_phase < 0) + if (temp_final_phase < 0) { final_phase = (u8)(temp_final_phase + MAX_PHASE + 1); - else + } else { final_phase = (u8)temp_final_phase; + } } } else if (CHK_SD_SDR50(sd_card)) { if (max_len > 12) { @@ -1657,10 +1708,11 @@ static u8 sd_search_final_phase(struct rtsx_chip *chip, u32 phase_map, u8 tune_d int temp_final_phase = path[final_path_idx].end - (max_len - (3 + temp_mid)); - if (temp_final_phase < 0) + if (temp_final_phase < 0) { final_phase = (u8)(temp_final_phase + MAX_PHASE + 1); - else + } else { final_phase = (u8)temp_final_phase; + } } } } @@ -1680,16 +1732,17 @@ static int sd_tuning_rx(struct rtsx_chip *chip) int (*tuning_cmd)(struct rtsx_chip *chip, u8 sample_point); if (CHK_SD(sd_card)) { - if (CHK_SD_DDR50(sd_card)) + if (CHK_SD_DDR50(sd_card)) { tuning_cmd = sd_ddr_tuning_rx_cmd; - else + } else { tuning_cmd = sd_sdr_tuning_rx_cmd; - + } } else { - if (CHK_MMC_DDR52(sd_card)) + if (CHK_MMC_DDR52(sd_card)) { tuning_cmd = mmc_ddr_tunning_rx_cmd; - else + } else { TRACE_RET(chip, STATUS_FAIL); + } } for (i = 0; i < 3; i++) { @@ -1701,24 +1754,27 @@ static int sd_tuning_rx(struct rtsx_chip *chip) } retval = tuning_cmd(chip, (u8)j); - if (retval == STATUS_SUCCESS) + if (retval == STATUS_SUCCESS) { raw_phase_map[i] |= 1 << j; + } } } phase_map = raw_phase_map[0] & raw_phase_map[1] & raw_phase_map[2]; - for (i = 0; i < 3; i++) + for (i = 0; i < 3; i++) { RTSX_DEBUGP("RX raw_phase_map[%d] = 0x%08x\n", i, raw_phase_map[i]); - + } RTSX_DEBUGP("RX phase_map = 0x%08x\n", phase_map); final_phase = sd_search_final_phase(chip, phase_map, TUNE_RX); - if (final_phase == 0xFF) + if (final_phase == 0xFF) { TRACE_RET(chip, STATUS_FAIL); + } retval = sd_change_phase(chip, final_phase, TUNE_RX); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } return STATUS_SUCCESS; } @@ -1743,13 +1799,15 @@ static int sd_ddr_pre_tuning_tx(struct rtsx_chip *chip) } retval = sd_change_phase(chip, (u8)i, TUNE_TX); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { continue; + } retval = sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr, SD_RSP_TYPE_R1, NULL, 0); - if ((retval == STATUS_SUCCESS) || !sd_check_err_code(chip, SD_RSP_TIMEOUT)) + if ((retval == STATUS_SUCCESS) || !sd_check_err_code(chip, SD_RSP_TIMEOUT)) { phase_map |= 1 << i; + } } RTSX_WRITE_REG(chip, SD_CFG3, SD_RSP_80CLK_TIMEOUT_EN, 0); @@ -1757,12 +1815,14 @@ static int sd_ddr_pre_tuning_tx(struct rtsx_chip *chip) RTSX_DEBUGP("DDR TX pre tune phase_map = 0x%08x\n", phase_map); final_phase = sd_search_final_phase(chip, phase_map, TUNE_TX); - if (final_phase == 0xFF) + if (final_phase == 0xFF) { TRACE_RET(chip, STATUS_FAIL); + } retval = sd_change_phase(chip, final_phase, TUNE_TX); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } RTSX_DEBUGP("DDR TX pre tune phase: %d\n", (int)final_phase); @@ -1779,16 +1839,17 @@ static int sd_tuning_tx(struct rtsx_chip *chip) int (*tuning_cmd)(struct rtsx_chip *chip, u8 sample_point); if (CHK_SD(sd_card)) { - if (CHK_SD_DDR50(sd_card)) + if (CHK_SD_DDR50(sd_card)) { tuning_cmd = sd_ddr_tuning_tx_cmd; - else + } else { tuning_cmd = sd_sdr_tuning_tx_cmd; - + } } else { - if (CHK_MMC_DDR52(sd_card)) + if (CHK_MMC_DDR52(sd_card)) { tuning_cmd = sd_ddr_tuning_tx_cmd; - else + } else { TRACE_RET(chip, STATUS_FAIL); + } } for (i = 0; i < 3; i++) { @@ -1802,24 +1863,27 @@ static int sd_tuning_tx(struct rtsx_chip *chip) } retval = tuning_cmd(chip, (u8)j); - if (retval == STATUS_SUCCESS) + if (retval == STATUS_SUCCESS) { raw_phase_map[i] |= 1 << j; + } } } phase_map = raw_phase_map[0] & raw_phase_map[1] & raw_phase_map[2]; - for (i = 0; i < 3; i++) + for (i = 0; i < 3; i++) { RTSX_DEBUGP("TX raw_phase_map[%d] = 0x%08x\n", i, raw_phase_map[i]); - + } RTSX_DEBUGP("TX phase_map = 0x%08x\n", phase_map); final_phase = sd_search_final_phase(chip, phase_map, TUNE_TX); - if (final_phase == 0xFF) + if (final_phase == 0xFF) { TRACE_RET(chip, STATUS_FAIL); + } retval = sd_change_phase(chip, final_phase, TUNE_TX); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } return STATUS_SUCCESS; } @@ -1829,12 +1893,14 @@ static int sd_sdr_tuning(struct rtsx_chip *chip) int retval; retval = sd_tuning_tx(chip); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } retval = sd_tuning_rx(chip); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } return STATUS_SUCCESS; } @@ -1845,22 +1911,26 @@ static int sd_ddr_tuning(struct rtsx_chip *chip) if (!(chip->sd_ctl & SD_DDR_TX_PHASE_SET_BY_USER)) { retval = sd_ddr_pre_tuning_tx(chip); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } } else { retval = sd_change_phase(chip, (u8)chip->sd_ddr_tx_phase, TUNE_TX); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } } retval = sd_tuning_rx(chip); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } if (!(chip->sd_ctl & SD_DDR_TX_PHASE_SET_BY_USER)) { retval = sd_tuning_tx(chip); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } } return STATUS_SUCCESS; @@ -1872,22 +1942,26 @@ static int mmc_ddr_tuning(struct rtsx_chip *chip) if (!(chip->sd_ctl & MMC_DDR_TX_PHASE_SET_BY_USER)) { retval = sd_ddr_pre_tuning_tx(chip); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } } else { retval = sd_change_phase(chip, (u8)chip->mmc_ddr_tx_phase, TUNE_TX); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } } retval = sd_tuning_rx(chip); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } if (!(chip->sd_ctl & MMC_DDR_TX_PHASE_SET_BY_USER)) { retval = sd_tuning_tx(chip); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } } return STATUS_SUCCESS; @@ -1900,8 +1974,9 @@ int sd_switch_clock(struct rtsx_chip *chip) int re_tuning = 0; retval = select_card(chip, SD_CARD); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } if (CHECK_PID(chip, 0x5209) && (CHK_SD30_SPEED(sd_card) || CHK_MMC_DDR52(sd_card))) { @@ -1912,22 +1987,26 @@ int sd_switch_clock(struct rtsx_chip *chip) } retval = switch_clock(chip, sd_card->sd_clock); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } if (re_tuning) { if (CHK_SD(sd_card)) { - if (CHK_SD_DDR50(sd_card)) + if (CHK_SD_DDR50(sd_card)) { retval = sd_ddr_tuning(chip); - else + } else { retval = sd_sdr_tuning(chip); + } } else { - if (CHK_MMC_DDR52(sd_card)) + if (CHK_MMC_DDR52(sd_card)) { retval = mmc_ddr_tuning(chip); + } } - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } } return STATUS_SUCCESS; @@ -1938,10 +2017,11 @@ static int sd_prepare_reset(struct rtsx_chip *chip) struct sd_info *sd_card = &(chip->sd_card); int retval; - if (chip->asic_code) + if (chip->asic_code) { sd_card->sd_clock = 29; - else + } else { sd_card->sd_clock = CLK_30; + } sd_card->sd_type = 0; sd_card->seq_mode = 0; @@ -1957,8 +2037,9 @@ static int sd_prepare_reset(struct rtsx_chip *chip) chip->sd_io = 0; retval = sd_set_init_para(chip); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, retval); + } if (CHECK_PID(chip, 0x5209)) { RTSX_WRITE_REG(chip, REG_SD_CFG1, 0xFF, @@ -1972,8 +2053,9 @@ static int sd_prepare_reset(struct rtsx_chip *chip) RTSX_WRITE_REG(chip, CARD_STOP, SD_STOP | SD_CLR_ERR, SD_STOP | SD_CLR_ERR); retval = select_card(chip, SD_CARD); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } return STATUS_SUCCESS; } @@ -2040,8 +2122,9 @@ int sd_pull_ctl_enable(struct rtsx_chip *chip) } retval = rtsx_send_cmd(chip, SD_CARD, 100); - if (retval < 0) + if (retval < 0) { TRACE_RET(chip, STATUS_FAIL); + } return STATUS_SUCCESS; } @@ -2050,37 +2133,42 @@ static int sd_init_power(struct rtsx_chip *chip) { int retval; - if (CHECK_PID(chip, 0x5209)) + if (CHECK_PID(chip, 0x5209)) { RTSX_WRITE_REG(chip, PWR_GATE_CTRL, LDO3318_PWR_MASK, LDO_OFF); + } retval = sd_power_off_card3v3(chip); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } - if (!chip->ft2_fast_mode) + if (!chip->ft2_fast_mode) { wait_timeout(250); + } retval = enable_card_clock(chip, SD_CARD); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } if (chip->asic_code) { retval = sd_pull_ctl_enable(chip); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } } else { RTSX_WRITE_REG(chip, FPGA_PULL_CTL, FPGA_SD_PULL_CTL_BIT | 0x20, 0); } if (chip->ft2_fast_mode) { - if (CHECK_PID(chip, 0x5209)) + if (CHECK_PID(chip, 0x5209)) { RTSX_WRITE_REG(chip, PWR_GATE_CTRL, LDO3318_PWR_MASK, LDO_ON); - + } } else { retval = card_power_on(chip, SD_CARD); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); - + } wait_timeout(260); #ifdef SUPPORT_OCP @@ -2126,12 +2214,13 @@ static int sd_read_lba0(struct rtsx_chip *chip) if (CHK_SD(sd_card)) { bus_width = SD_BUS_WIDTH_4; } else { - if (CHK_MMC_8BIT(sd_card)) + if (CHK_MMC_8BIT(sd_card)) { bus_width = SD_BUS_WIDTH_8; - else if (CHK_MMC_4BIT(sd_card)) + } else if (CHK_MMC_4BIT(sd_card)) { bus_width = SD_BUS_WIDTH_4; - else + } else { bus_width = SD_BUS_WIDTH_1; + } } retval = sd_read_data(chip, SD_TM_NORMAL_READ, cmd, @@ -2154,8 +2243,9 @@ static int sd_check_wp_state(struct rtsx_chip *chip) retval = sd_send_cmd_get_rsp(chip, APP_CMD, sd_card->sd_addr, SD_RSP_TYPE_R1, NULL, 0); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } cmd[0] = 0x40 | SD_STATUS; cmd[1] = 0; @@ -2183,8 +2273,9 @@ static int sd_check_wp_state(struct rtsx_chip *chip) /* Check SD Machanical Write-Protect Switch */ val = rtsx_readl(chip, RTSX_BIPR); - if (val & SD_WRITE_PROTECT) + if (val & SD_WRITE_PROTECT) { chip->card_wp |= SD_CARD; + } return STATUS_SUCCESS; } @@ -2216,12 +2307,14 @@ static int reset_sd(struct rtsx_chip *chip) #endif retval = sd_prepare_reset(chip); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } retval = sd_dummy_clock(chip); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } if (CHK_SDIO_EXIST(chip) && !CHK_SDIO_IGNORED(chip) && try_sdio) { int rty_cnt = 0; @@ -2255,8 +2348,9 @@ static int reset_sd(struct rtsx_chip *chip) /* Start Initialization Process of SD Card */ RTY_SD_RST: retval = sd_send_cmd_get_rsp(chip, GO_IDLE_STATE, 0, SD_RSP_TYPE_R0, NULL, 0); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } wait_timeout(20); @@ -2283,8 +2377,9 @@ static int reset_sd(struct rtsx_chip *chip) voltage = SUPPORT_VOLTAGE; retval = sd_send_cmd_get_rsp(chip, GO_IDLE_STATE, 0, SD_RSP_TYPE_R0, NULL, 0); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } wait_timeout(20); } @@ -2298,38 +2393,42 @@ static int reset_sd(struct rtsx_chip *chip) } j++; - if (j < 3) + if (j < 3) { goto RTY_SD_RST; - else + } else { TRACE_RET(chip, STATUS_FAIL); + } } retval = sd_send_cmd_get_rsp(chip, SD_APP_OP_COND, voltage, SD_RSP_TYPE_R3, rsp, 5); if (retval != STATUS_SUCCESS) { k++; - if (k < 3) + if (k < 3) { goto RTY_SD_RST; - else + } else { TRACE_RET(chip, STATUS_FAIL); + } } i++; wait_timeout(20); } while (!(rsp[1] & 0x80) && (i < 255)); - if (i == 255) + if (i == 255) { TRACE_RET(chip, STATUS_FAIL); + } if (hi_cap_flow) { - if (rsp[1] & 0x40) + if (rsp[1] & 0x40) { SET_SD_HCXC(sd_card); - else + } else { CLR_SD_HCXC(sd_card); - - if (CHECK_PID(chip, 0x5209) && CHK_SD_HCXC(sd_card) && !sd20_mode) + } + if (CHECK_PID(chip, 0x5209) && CHK_SD_HCXC(sd_card) && !sd20_mode) { support_1v8 = (rsp[1] & 0x01) ? 1 : 0; - else + } else { support_1v8 = 0; + } } else { CLR_SD_HCXC(sd_card); support_1v8 = 0; @@ -2338,39 +2437,46 @@ static int reset_sd(struct rtsx_chip *chip) if (support_1v8) { retval = sd_voltage_switch(chip); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } } retval = sd_send_cmd_get_rsp(chip, ALL_SEND_CID, 0, SD_RSP_TYPE_R2, NULL, 0); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } for (i = 0; i < 3; i++) { retval = sd_send_cmd_get_rsp(chip, SEND_RELATIVE_ADDR, 0, SD_RSP_TYPE_R6, rsp, 5); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } sd_card->sd_addr = (u32)rsp[1] << 24; sd_card->sd_addr += (u32)rsp[2] << 16; - if (sd_card->sd_addr) + if (sd_card->sd_addr) { break; + } } retval = sd_check_csd(chip, 1); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } retval = sd_select_card(chip, 1); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } #ifdef SUPPORT_SD_LOCK SD_UNLOCK_ENTRY: retval = sd_update_lock_status(chip); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } if (sd_card->sd_lock_status & SD_LOCKED) { sd_card->sd_lock_status |= (SD_LOCK_1BIT_MODE | SD_PWD_EXIST); @@ -2381,21 +2487,23 @@ static int reset_sd(struct rtsx_chip *chip) #endif retval = sd_send_cmd_get_rsp(chip, APP_CMD, sd_card->sd_addr, SD_RSP_TYPE_R1, NULL, 0); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); - + } retval = sd_send_cmd_get_rsp(chip, SET_CLR_CARD_DETECT, 0, SD_RSP_TYPE_R1, NULL, 0); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } if (support_1v8) { retval = sd_send_cmd_get_rsp(chip, APP_CMD, sd_card->sd_addr, SD_RSP_TYPE_R1, NULL, 0); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); - + } retval = sd_send_cmd_get_rsp(chip, SET_BUS_WIDTH, 2, SD_RSP_TYPE_R1, NULL, 0); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } switch_bus_width = SD_BUS_WIDTH_4; } else { @@ -2403,12 +2511,14 @@ static int reset_sd(struct rtsx_chip *chip) } retval = sd_send_cmd_get_rsp(chip, SET_BLOCKLEN, 0x200, SD_RSP_TYPE_R1, NULL, 0); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } retval = sd_set_clock_divider(chip, SD_CLK_DIVIDE_0); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } if (!(sd_card->raw_csd[4] & 0x40)) sd_dont_switch = 1; @@ -2427,9 +2537,9 @@ static int reset_sd(struct rtsx_chip *chip) if (retval == STATUS_SUCCESS) { retval = sd_switch_function(chip, switch_bus_width); if (retval != STATUS_SUCCESS) { - if (CHECK_PID(chip, 0x5209)) + if (CHECK_PID(chip, 0x5209)) { sd_change_bank_voltage(chip, SD_IO_3V3); - + } sd_init_power(chip); sd_dont_switch = 1; try_sdio = 0; @@ -2438,9 +2548,9 @@ static int reset_sd(struct rtsx_chip *chip) } } else { if (support_1v8) { - if (CHECK_PID(chip, 0x5209)) + if (CHECK_PID(chip, 0x5209)) { sd_change_bank_voltage(chip, SD_IO_3V3); - + } sd_init_power(chip); sd_dont_switch = 1; try_sdio = 0; @@ -2452,12 +2562,13 @@ static int reset_sd(struct rtsx_chip *chip) if (!support_1v8) { retval = sd_send_cmd_get_rsp(chip, APP_CMD, sd_card->sd_addr, SD_RSP_TYPE_R1, NULL, 0); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); - + } retval = sd_send_cmd_get_rsp(chip, SET_BUS_WIDTH, 2, SD_RSP_TYPE_R1, NULL, 0); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } } #ifdef SUPPORT_SD_LOCK @@ -2470,22 +2581,24 @@ static int reset_sd(struct rtsx_chip *chip) RTSX_WRITE_REG(chip, SD30_DRIVE_SEL, 0x07, chip->sd30_drive_sel_1v8); retval = sd_set_init_para(chip); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } - if (CHK_SD_DDR50(sd_card)) + if (CHK_SD_DDR50(sd_card)) { retval = sd_ddr_tuning(chip); - else + } else { retval = sd_sdr_tuning(chip); + } if (retval != STATUS_SUCCESS) { if (sd20_mode) { TRACE_RET(chip, STATUS_FAIL); } else { retval = sd_init_power(chip); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); - + } try_sdio = 0; sd20_mode = 1; goto Switch_Fail; @@ -2496,8 +2609,9 @@ static int reset_sd(struct rtsx_chip *chip) if (CHK_SD_DDR50(sd_card)) { retval = sd_wait_state_data_ready(chip, 0x08, 1, 1000); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { read_lba0 = 0; + } } if (read_lba0) { @@ -2507,9 +2621,9 @@ static int reset_sd(struct rtsx_chip *chip) TRACE_RET(chip, STATUS_FAIL); } else { retval = sd_init_power(chip); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); - + } try_sdio = 0; sd20_mode = 1; goto Switch_Fail; @@ -2519,8 +2633,9 @@ static int reset_sd(struct rtsx_chip *chip) } retval = sd_check_wp_state(chip); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } chip->card_bus_width[chip->card2lun[SD_CARD]] = 4; @@ -2544,8 +2659,9 @@ static int mmc_test_switch_bus(struct rtsx_chip *chip, u8 width) int len; retval = sd_send_cmd_get_rsp(chip, BUSTEST_W, 0, SD_RSP_TYPE_R1, NULL, 0); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, SWITCH_FAIL); + } if (width == MMC_8BIT_BUS) { buf[0] = 0x55; @@ -2574,8 +2690,9 @@ static int mmc_test_switch_bus(struct rtsx_chip *chip, u8 width) rtsx_read_register(chip, REG_SD_STAT1, &val1); rtsx_read_register(chip, REG_SD_STAT2, &val2); rtsx_clear_sd_error(chip); - if ((val1 & 0xE0) || val2) + if ((val1 & 0xE0) || val2) { TRACE_RET(chip, SWITCH_ERR); + } } else { rtsx_clear_sd_error(chip); rtsx_write_register(chip, REG_SD_CFG3, 0x02, 0); @@ -2595,10 +2712,11 @@ static int mmc_test_switch_bus(struct rtsx_chip *chip, u8 width) rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD0, 0xFF, 0x40 | BUSTEST_R); - if (width == MMC_8BIT_BUS) + if (width == MMC_8BIT_BUS) { rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_L, 0xFF, 0x08); - else + } else { rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_L, 0xFF, 0x04); + } rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_L, 0xFF, 1); rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_H, 0xFF, 0); @@ -2611,8 +2729,9 @@ static int mmc_test_switch_bus(struct rtsx_chip *chip, u8 width) rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER, SD_TRANSFER_END, SD_TRANSFER_END); rtsx_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2, 0, 0); - if (width == MMC_8BIT_BUS) + if (width == MMC_8BIT_BUS) { rtsx_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2 + 1, 0, 0); + } retval = rtsx_send_cmd(chip, SD_CARD, 100); if (retval < 0) { @@ -2628,14 +2747,15 @@ static int mmc_test_switch_bus(struct rtsx_chip *chip, u8 width) u8 rsp[5]; u32 arg; - if (CHK_MMC_DDR52(sd_card)) + if (CHK_MMC_DDR52(sd_card)) { arg = 0x03B70600; - else + } else { arg = 0x03B70200; - + } retval = sd_send_cmd_get_rsp(chip, SWITCH, arg, SD_RSP_TYPE_R1b, rsp, 5); - if ((retval == STATUS_SUCCESS) && !(rsp[4] & MMC_SWITCH_ERR)) + if ((retval == STATUS_SUCCESS) && !(rsp[4] & MMC_SWITCH_ERR)) { return SWITCH_SUCCESS; + } } } else { RTSX_DEBUGP("BUSTEST_R [4bits]: 0x%02x\n", ptr[0]); @@ -2643,14 +2763,15 @@ static int mmc_test_switch_bus(struct rtsx_chip *chip, u8 width) u8 rsp[5]; u32 arg; - if (CHK_MMC_DDR52(sd_card)) + if (CHK_MMC_DDR52(sd_card)) { arg = 0x03B70500; - else + } else { arg = 0x03B70100; - + } retval = sd_send_cmd_get_rsp(chip, SWITCH, arg, SD_RSP_TYPE_R1b, rsp, 5); - if ((retval == STATUS_SUCCESS) && !(rsp[4] & MMC_SWITCH_ERR)) + if ((retval == STATUS_SUCCESS) && !(rsp[4] & MMC_SWITCH_ERR)) { return SWITCH_SUCCESS; + } } } @@ -2724,10 +2845,11 @@ static int mmc_switch_timing_bus(struct rtsx_chip *chip, int switch_ddr) card_type_mask = 0x03; } #else - if (chip->sd_ctl & SUPPORT_MMC_DDR_MODE) + if (chip->sd_ctl & SUPPORT_MMC_DDR_MODE) { card_type_mask = 0x07; - else + } else { card_type_mask = 0x03; + } #endif } else { card_type_mask = 0x03; @@ -2737,10 +2859,11 @@ static int mmc_switch_timing_bus(struct rtsx_chip *chip, int switch_ddr) u8 rsp[5]; if (card_type & 0x04) { - if (switch_ddr) + if (switch_ddr) { SET_MMC_DDR52(sd_card); - else + } else { SET_MMC_52M(sd_card); + } } else if (card_type & 0x02) { SET_MMC_52M(sd_card); } else { @@ -2749,14 +2872,16 @@ static int mmc_switch_timing_bus(struct rtsx_chip *chip, int switch_ddr) retval = sd_send_cmd_get_rsp(chip, SWITCH, 0x03B90100, SD_RSP_TYPE_R1b, rsp, 5); - if ((retval != STATUS_SUCCESS) || (rsp[4] & MMC_SWITCH_ERR)) + if ((retval != STATUS_SUCCESS) || (rsp[4] & MMC_SWITCH_ERR)) { CLR_MMC_HS(sd_card); + } } sd_choose_proper_clock(chip); retval = switch_clock(chip, sd_card->sd_clock); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } /* Test Bus Procedure */ retval = mmc_test_switch_bus(chip, MMC_8BIT_BUS); @@ -2804,15 +2929,17 @@ static int reset_mmc(struct rtsx_chip *chip) Switch_Fail: retval = sd_prepare_reset(chip); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, retval); + } SET_MMC(sd_card); RTY_MMC_RST: retval = sd_send_cmd_get_rsp(chip, GO_IDLE_STATE, 0, SD_RSP_TYPE_R0, NULL, 0); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } do { if (detect_card_cd(chip, SD_CARD) != STATUS_SUCCESS) { @@ -2846,47 +2973,56 @@ static int reset_mmc(struct rtsx_chip *chip) i++; } while (!(rsp[1] & 0x80) && (i < 255)); - if (i == 255) + if (i == 255) { TRACE_RET(chip, STATUS_FAIL); + } - if ((rsp[1] & 0x60) == 0x40) + if ((rsp[1] & 0x60) == 0x40) { SET_MMC_SECTOR_MODE(sd_card); - else + } else { CLR_MMC_SECTOR_MODE(sd_card); + } retval = sd_send_cmd_get_rsp(chip, ALL_SEND_CID, 0, SD_RSP_TYPE_R2, NULL, 0); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } sd_card->sd_addr = 0x00100000; retval = sd_send_cmd_get_rsp(chip, SET_RELATIVE_ADDR, sd_card->sd_addr, SD_RSP_TYPE_R6, rsp, 5); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } retval = sd_check_csd(chip, 1); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } spec_ver = (sd_card->raw_csd[0] & 0x3C) >> 2; retval = sd_select_card(chip, 1); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } retval = sd_send_cmd_get_rsp(chip, SET_BLOCKLEN, 0x200, SD_RSP_TYPE_R1, NULL, 0); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } #ifdef SUPPORT_SD_LOCK MMC_UNLOCK_ENTRY: retval = sd_update_lock_status(chip); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } #endif retval = sd_set_clock_divider(chip, SD_CLK_DIVIDE_0); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } chip->card_bus_width[chip->card2lun[SD_CARD]] = 1; @@ -2903,20 +3039,22 @@ static int reset_mmc(struct rtsx_chip *chip) } } - if (CHK_MMC_SECTOR_MODE(sd_card) && (sd_card->capacity == 0)) + if (CHK_MMC_SECTOR_MODE(sd_card) && (sd_card->capacity == 0)) { TRACE_RET(chip, STATUS_FAIL); + } if (switch_ddr && CHK_MMC_DDR52(sd_card)) { retval = sd_set_init_para(chip); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } retval = mmc_ddr_tuning(chip); if (retval != STATUS_SUCCESS) { retval = sd_init_power(chip); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); - + } switch_ddr = 0; TRACE_GOTO(chip, Switch_Fail); } @@ -2926,9 +3064,9 @@ static int reset_mmc(struct rtsx_chip *chip) retval = sd_read_lba0(chip); if (retval != STATUS_SUCCESS) { retval = sd_init_power(chip); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); - + } switch_ddr = 0; TRACE_GOTO(chip, Switch_Fail); } @@ -2944,8 +3082,9 @@ static int reset_mmc(struct rtsx_chip *chip) #endif temp = rtsx_readl(chip, RTSX_BIPR); - if (temp & SD_WRITE_PROTECT) + if (temp & SD_WRITE_PROTECT) { chip->card_wp |= SD_CARD; + } return STATUS_SUCCESS; } @@ -2961,31 +3100,36 @@ int reset_sd_card(struct rtsx_chip *chip) chip->capacity[chip->card2lun[SD_CARD]] = 0; retval = enable_card_clock(chip, SD_CARD); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } if (chip->ignore_sd && CHK_SDIO_EXIST(chip) && !CHK_SDIO_IGNORED(chip)) { if (chip->asic_code) { retval = sd_pull_ctl_enable(chip); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } } else { retval = rtsx_write_register(chip, FPGA_PULL_CTL, FPGA_SD_PULL_CTL_BIT | 0x20, 0); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } } retval = card_share_mode(chip, SD_CARD); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } chip->sd_io = 1; TRACE_RET(chip, STATUS_FAIL); } retval = sd_init_power(chip); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } if (chip->sd_ctl & RESET_MMC_FIRST) { retval = reset_mmc(chip); @@ -3024,17 +3168,18 @@ int reset_sd_card(struct rtsx_chip *chip) } retval = sd_set_clock_divider(chip, SD_CLK_DIVIDE_0); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); - + } RTSX_WRITE_REG(chip, REG_SD_BYTE_CNT_L, 0xFF, 0); RTSX_WRITE_REG(chip, REG_SD_BYTE_CNT_H, 0xFF, 2); chip->capacity[chip->card2lun[SD_CARD]] = sd_card->capacity; retval = sd_set_init_para(chip); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } RTSX_DEBUGP("sd_card->sd_type = 0x%x\n", sd_card->sd_type); @@ -3060,29 +3205,33 @@ static int reset_mmc_only(struct rtsx_chip *chip) chip->capacity[chip->card2lun[SD_CARD]] = sd_card->capacity = 0; retval = enable_card_clock(chip, SD_CARD); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } retval = sd_init_power(chip); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } retval = reset_mmc(chip); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } retval = sd_set_clock_divider(chip, SD_CLK_DIVIDE_0); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); - + } RTSX_WRITE_REG(chip, REG_SD_BYTE_CNT_L, 0xFF, 0); RTSX_WRITE_REG(chip, REG_SD_BYTE_CNT_H, 0xFF, 2); chip->capacity[chip->card2lun[SD_CARD]] = sd_card->capacity; retval = sd_set_init_para(chip); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } RTSX_DEBUGP("In reset_mmc_only, sd_card->sd_type = 0x%x\n", sd_card->sd_type); @@ -3106,8 +3255,9 @@ static int wait_data_buf_ready(struct rtsx_chip *chip) retval = sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr, SD_RSP_TYPE_R1, NULL, 0); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } if (sd_card->sd_data_buf_ready) { return sd_send_cmd_get_rsp(chip, SEND_STATUS, @@ -3127,18 +3277,19 @@ void sd_stop_seq_mode(struct rtsx_chip *chip) if (sd_card->seq_mode) { retval = sd_switch_clock(chip); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { return; + } retval = sd_send_cmd_get_rsp(chip, STOP_TRANSMISSION, 0, SD_RSP_TYPE_R1b, NULL, 0); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { sd_set_err_code(chip, SD_STS_ERR); - + } retval = sd_wait_state_data_ready(chip, 0x08, 1, 1000); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { sd_set_err_code(chip, SD_STS_ERR); - + } sd_card->seq_mode = 0; rtsx_write_register(chip, RBCTL, RB_FLUSH, RB_FLUSH); @@ -3151,8 +3302,9 @@ static inline int sd_auto_tune_clock(struct rtsx_chip *chip) int retval; if (chip->asic_code) { - if (sd_card->sd_clock > 30) + if (sd_card->sd_clock > 30) { sd_card->sd_clock -= 20; + } } else { switch (sd_card->sd_clock) { case CLK_200: @@ -3185,8 +3337,9 @@ static inline int sd_auto_tune_clock(struct rtsx_chip *chip) } retval = sd_switch_clock(chip); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } return STATUS_SUCCESS; } @@ -3224,10 +3377,11 @@ int sd_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip, u32 start_sector, u16 s } } - if (!CHK_SD_HCXC(sd_card) && !CHK_MMC_SECTOR_MODE(sd_card)) + if (!CHK_SD_HCXC(sd_card) && !CHK_MMC_SECTOR_MODE(sd_card)) { data_addr = start_sector << 9; - else + } else { data_addr = start_sector; + } sd_clr_err_code(chip); @@ -3282,19 +3436,21 @@ int sd_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip, u32 start_sector, u16 s rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, RING_BUFFER); - if (CHK_MMC_8BIT(sd_card)) + if (CHK_MMC_8BIT(sd_card)) { rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG1, 0x03, SD_BUS_WIDTH_8); - else if (CHK_MMC_4BIT(sd_card) || CHK_SD(sd_card)) + } else if (CHK_MMC_4BIT(sd_card) || CHK_SD(sd_card)) { rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG1, 0x03, SD_BUS_WIDTH_4); - else + } else { rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG1, 0x03, SD_BUS_WIDTH_1); + } if (sd_card->seq_mode) { cfg2 = SD_NO_CALCULATE_CRC7 | SD_CHECK_CRC16 | SD_NO_WAIT_BUSY_END | SD_NO_CHECK_CRC7 | SD_RSP_LEN_0; if (CHECK_PID(chip, 0x5209)) { - if (!CHK_SD30_SPEED(sd_card)) + if (!CHK_SD30_SPEED(sd_card)) { cfg2 |= SD_NO_CHECK_WAIT_CRC_TO; + } } rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG2, 0xFF, cfg2); @@ -3324,8 +3480,9 @@ int sd_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip, u32 start_sector, u16 s cfg2 = SD_CALCULATE_CRC7 | SD_CHECK_CRC16 | SD_NO_WAIT_BUSY_END | SD_CHECK_CRC7 | SD_RSP_LEN_6; if (CHECK_PID(chip, 0x5209)) { - if (!CHK_SD30_SPEED(sd_card)) + if (!CHK_SD30_SPEED(sd_card)) { cfg2 |= SD_NO_CHECK_WAIT_CRC_TO; + } } rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG2, 0xFF, cfg2); @@ -3366,8 +3523,9 @@ int sd_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip, u32 start_sector, u16 s cfg2 = SD_NO_CALCULATE_CRC7 | SD_CHECK_CRC16 | SD_NO_WAIT_BUSY_END | SD_NO_CHECK_CRC7 | SD_RSP_LEN_0; if (CHECK_PID(chip, 0x5209)) { - if (!CHK_SD30_SPEED(sd_card)) + if (!CHK_SD30_SPEED(sd_card)) { cfg2 |= SD_NO_CHECK_WAIT_CRC_TO; + } } rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG2, 0xFF, cfg2); @@ -3392,10 +3550,11 @@ int sd_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip, u32 start_sector, u16 s sd_card->seq_mode = 0; - if (retval == -ETIMEDOUT) + if (retval == -ETIMEDOUT) { err = STATUS_TIMEDOUT; - else + } else { err = STATUS_FAIL; + } rtsx_read_register(chip, REG_SD_STAT1, &stat); rtsx_clear_sd_error(chip); @@ -3481,8 +3640,9 @@ int ext_sd_send_cmd_get_rsp(struct rtsx_chip *chip, u8 cmd_idx, RTSX_DEBUGP("EXT SD/MMC CMD %d\n", cmd_idx); - if (rsp_type == SD_RSP_TYPE_R1b) + if (rsp_type == SD_RSP_TYPE_R1b) { timeout = 3000; + } RTY_SEND_CMD: @@ -3502,14 +3662,14 @@ int ext_sd_send_cmd_get_rsp(struct rtsx_chip *chip, u8 cmd_idx, rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER, SD_TRANSFER_END, SD_TRANSFER_END); if (rsp_type == SD_RSP_TYPE_R2) { - for (reg_addr = PPBUF_BASE2; reg_addr < PPBUF_BASE2 + 16; reg_addr++) + for (reg_addr = PPBUF_BASE2; reg_addr < PPBUF_BASE2 + 16; reg_addr++) { rtsx_add_cmd(chip, READ_REG_CMD, reg_addr, 0, 0); - + } stat_idx = 17; } else if (rsp_type != SD_RSP_TYPE_R0) { - for (reg_addr = REG_SD_CMD0; reg_addr <= REG_SD_CMD4; reg_addr++) + for (reg_addr = REG_SD_CMD0; reg_addr <= REG_SD_CMD4; reg_addr++) { rtsx_add_cmd(chip, READ_REG_CMD, reg_addr, 0, 0); - + } stat_idx = 6; } rtsx_add_cmd(chip, READ_REG_CMD, REG_SD_CMD5, 0, 0); @@ -3523,8 +3683,9 @@ int ext_sd_send_cmd_get_rsp(struct rtsx_chip *chip, u8 cmd_idx, if (rsp_type & SD_WAIT_BUSY_END) { retval = sd_check_data0_status(chip); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, retval); + } } else { sd_set_err_code(chip, SD_TO_ERR); } @@ -3532,8 +3693,9 @@ int ext_sd_send_cmd_get_rsp(struct rtsx_chip *chip, u8 cmd_idx, TRACE_RET(chip, STATUS_FAIL); } - if (rsp_type == SD_RSP_TYPE_R0) + if (rsp_type == SD_RSP_TYPE_R0) { return STATUS_SUCCESS; + } ptr = rtsx_get_cmd_data(chip) + 1; @@ -3562,8 +3724,9 @@ int ext_sd_send_cmd_get_rsp(struct rtsx_chip *chip, u8 cmd_idx, if ((cmd_idx == SELECT_CARD) || (cmd_idx == APP_CMD) || (cmd_idx == SEND_STATUS) || (cmd_idx == STOP_TRANSMISSION)) { if ((cmd_idx != STOP_TRANSMISSION) && (special_check == 0)) { - if (ptr[1] & 0x80) + if (ptr[1] & 0x80) { TRACE_RET(chip, STATUS_FAIL); + } } #ifdef SUPPORT_SD_LOCK if (ptr[1] & 0x7D) @@ -3573,23 +3736,26 @@ int ext_sd_send_cmd_get_rsp(struct rtsx_chip *chip, u8 cmd_idx, { TRACE_RET(chip, STATUS_FAIL); } - if (ptr[2] & 0xF8) + if (ptr[2] & 0xF8) { TRACE_RET(chip, STATUS_FAIL); + } if (cmd_idx == SELECT_CARD) { if (rsp_type == SD_RSP_TYPE_R2) { - if ((ptr[3] & 0x1E) != 0x04) + if ((ptr[3] & 0x1E) != 0x04) { TRACE_RET(chip, STATUS_FAIL); - + } } else if (rsp_type == SD_RSP_TYPE_R0) { - if ((ptr[3] & 0x1E) != 0x03) + if ((ptr[3] & 0x1E) != 0x03) { TRACE_RET(chip, STATUS_FAIL); + } } } } - if (rsp && rsp_len) + if (rsp && rsp_len) { memcpy(rsp, ptr, rsp_len); + } return STATUS_SUCCESS; } @@ -3599,27 +3765,29 @@ int ext_sd_get_rsp(struct rtsx_chip *chip, int len, u8 *rsp, u8 rsp_type) int retval, rsp_len; u16 reg_addr; - if (rsp_type == SD_RSP_TYPE_R0) + if (rsp_type == SD_RSP_TYPE_R0) { return STATUS_SUCCESS; + } rtsx_init_cmd(chip); if (rsp_type == SD_RSP_TYPE_R2) { - for (reg_addr = PPBUF_BASE2; reg_addr < PPBUF_BASE2 + 16; reg_addr++) + for (reg_addr = PPBUF_BASE2; reg_addr < PPBUF_BASE2 + 16; reg_addr++) { rtsx_add_cmd(chip, READ_REG_CMD, reg_addr, 0xFF, 0); - + } rsp_len = 17; } else if (rsp_type != SD_RSP_TYPE_R0) { - for (reg_addr = REG_SD_CMD0; reg_addr <= REG_SD_CMD4; reg_addr++) + for (reg_addr = REG_SD_CMD0; reg_addr <= REG_SD_CMD4; reg_addr++) { rtsx_add_cmd(chip, READ_REG_CMD, reg_addr, 0xFF, 0); - + } rsp_len = 6; } rtsx_add_cmd(chip, READ_REG_CMD, REG_SD_CMD5, 0xFF, 0); retval = rtsx_send_cmd(chip, SD_CARD, 100); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } if (rsp) { int min_len = (rsp_len < len) ? rsp_len : len; @@ -3690,8 +3858,9 @@ int sd_pass_thru_mode(struct scsi_cmnd *srb, struct rtsx_chip *chip) } buf[5] = (1 == CHK_SD(sd_card)) ? 0x01 : 0x02; - if (chip->card_wp & SD_CARD) + if (chip->card_wp & SD_CARD) { buf[5] |= 0x80; + } buf[6] = (u8)(sd_card->sd_addr >> 16); buf[7] = (u8)(sd_card->sd_addr >> 24); @@ -3706,8 +3875,9 @@ int sd_pass_thru_mode(struct scsi_cmnd *srb, struct rtsx_chip *chip) static inline int get_rsp_type(struct scsi_cmnd *srb, u8 *rsp_type, int *rsp_len) { - if (!rsp_type || !rsp_len) + if (!rsp_type || !rsp_len) { return STATUS_FAIL; + } switch (srb->cmnd[10]) { case 0x03: @@ -3757,8 +3927,9 @@ int sd_execute_no_data(struct scsi_cmnd *srb, struct rtsx_chip *chip) } retval = sd_switch_clock(chip); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, TRANSPORT_FAILED); + } if (sd_card->pre_cmd_err) { sd_card->pre_cmd_err = 0; @@ -3767,11 +3938,12 @@ int sd_execute_no_data(struct scsi_cmnd *srb, struct rtsx_chip *chip) } cmd_idx = srb->cmnd[2] & 0x3F; - if (srb->cmnd[1] & 0x02) + if (srb->cmnd[1] & 0x02) { standby = 1; - - if (srb->cmnd[1] & 0x01) + } + if (srb->cmnd[1] & 0x01) { acmd = 1; + } arg = ((u32)srb->cmnd[3] << 24) | ((u32)srb->cmnd[4] << 16) | ((u32)srb->cmnd[5] << 8) | srb->cmnd[6]; @@ -3784,56 +3956,64 @@ int sd_execute_no_data(struct scsi_cmnd *srb, struct rtsx_chip *chip) sd_card->last_rsp_type = rsp_type; retval = sd_switch_clock(chip); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, TRANSPORT_FAILED); + } #ifdef SUPPORT_SD_LOCK if ((sd_card->sd_lock_status & SD_LOCK_1BIT_MODE) == 0) { if (CHK_MMC_8BIT(sd_card)) { retval = rtsx_write_register(chip, REG_SD_CFG1, 0x03, SD_BUS_WIDTH_8); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, TRANSPORT_FAILED); - + } } else if (CHK_SD(sd_card) || CHK_MMC_4BIT(sd_card)) { retval = rtsx_write_register(chip, REG_SD_CFG1, 0x03, SD_BUS_WIDTH_4); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, TRANSPORT_FAILED); + } } } #else retval = rtsx_write_register(chip, REG_SD_CFG1, 0x03, SD_BUS_WIDTH_4); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, TRANSPORT_FAILED); + } #endif if (standby) { retval = sd_select_card(chip, 0); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_GOTO(chip, SD_Execute_Cmd_Failed); + } } if (acmd) { retval = ext_sd_send_cmd_get_rsp(chip, APP_CMD, sd_card->sd_addr, SD_RSP_TYPE_R1, NULL, 0, 0); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_GOTO(chip, SD_Execute_Cmd_Failed); + } } retval = ext_sd_send_cmd_get_rsp(chip, cmd_idx, arg, rsp_type, sd_card->rsp, rsp_len, 0); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_GOTO(chip, SD_Execute_Cmd_Failed); + } if (standby) { retval = sd_select_card(chip, 1); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_GOTO(chip, SD_Execute_Cmd_Failed); + } } #ifdef SUPPORT_SD_LOCK retval = sd_update_lock_status(chip); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_GOTO(chip, SD_Execute_Cmd_Failed); + } #endif scsi_set_resid(srb, 0); @@ -3844,8 +4024,9 @@ int sd_execute_no_data(struct scsi_cmnd *srb, struct rtsx_chip *chip) set_sense_type(chip, lun, SENSE_TYPE_NO_SENSE); release_sd_card(chip); do_reset_sd_card(chip); - if (!(chip->card_ready & SD_CARD)) + if (!(chip->card_ready & SD_CARD)) { set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT); + } TRACE_RET(chip, TRANSPORT_FAILED); } @@ -3872,18 +4053,20 @@ int sd_execute_read_data(struct scsi_cmnd *srb, struct rtsx_chip *chip) } retval = sd_switch_clock(chip); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, TRANSPORT_FAILED); + } cmd_idx = srb->cmnd[2] & 0x3F; - if (srb->cmnd[1] & 0x04) + if (srb->cmnd[1] & 0x04) { send_cmd12 = 1; - - if (srb->cmnd[1] & 0x02) + } + if (srb->cmnd[1] & 0x02) { standby = 1; - - if (srb->cmnd[1] & 0x01) + } + if (srb->cmnd[1] & 0x01) { acmd = 1; + } data_len = ((u32)srb->cmnd[7] << 16) | ((u32)srb->cmnd[8] << 8) | srb->cmnd[9]; @@ -3895,17 +4078,19 @@ int sd_execute_read_data(struct scsi_cmnd *srb, struct rtsx_chip *chip) sd_card->last_rsp_type = rsp_type; retval = sd_switch_clock(chip); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, TRANSPORT_FAILED); + } #ifdef SUPPORT_SD_LOCK if ((sd_card->sd_lock_status & SD_LOCK_1BIT_MODE) == 0) { - if (CHK_MMC_8BIT(sd_card)) + if (CHK_MMC_8BIT(sd_card)) { bus_width = SD_BUS_WIDTH_8; - else if (CHK_SD(sd_card) || CHK_MMC_4BIT(sd_card)) + } else if (CHK_SD(sd_card) || CHK_MMC_4BIT(sd_card)) { bus_width = SD_BUS_WIDTH_4; - else + } else { bus_width = SD_BUS_WIDTH_1; + } } else { bus_width = SD_BUS_WIDTH_4; } @@ -3917,21 +4102,24 @@ int sd_execute_read_data(struct scsi_cmnd *srb, struct rtsx_chip *chip) if (data_len < 512) { retval = ext_sd_send_cmd_get_rsp(chip, SET_BLOCKLEN, data_len, SD_RSP_TYPE_R1, NULL, 0, 0); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed); + } } if (standby) { retval = sd_select_card(chip, 0); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed); + } } if (acmd) { retval = ext_sd_send_cmd_get_rsp(chip, APP_CMD, sd_card->sd_addr, SD_RSP_TYPE_R1, NULL, 0, 0); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed); + } } if (data_len <= 512) { @@ -3950,8 +4138,9 @@ int sd_execute_read_data(struct scsi_cmnd *srb, struct rtsx_chip *chip) cmd[4] = srb->cmnd[6]; buf = kmalloc(data_len, GFP_KERNEL); - if (buf == NULL) + if (buf == NULL) { TRACE_RET(chip, TRANSPORT_ERROR); + } retval = sd_read_data(chip, SD_TM_NORMAL_READ, cmd, 5, byte_cnt, blk_cnt, bus_width, buf, data_len, 2000); @@ -4006,48 +4195,56 @@ int sd_execute_read_data(struct scsi_cmnd *srb, struct rtsx_chip *chip) } retval = ext_sd_get_rsp(chip, rsp_len, sd_card->rsp, rsp_type); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed); + } if (standby) { retval = sd_select_card(chip, 1); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed); + } } if (send_cmd12) { retval = ext_sd_send_cmd_get_rsp(chip, STOP_TRANSMISSION, 0, SD_RSP_TYPE_R1b, NULL, 0, 0); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed); + } } if (data_len < 512) { retval = ext_sd_send_cmd_get_rsp(chip, SET_BLOCKLEN, 0x200, SD_RSP_TYPE_R1, NULL, 0, 0); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed); + } retval = rtsx_write_register(chip, SD_BYTE_CNT_H, 0xFF, 0x02); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed); - + } retval = rtsx_write_register(chip, SD_BYTE_CNT_L, 0xFF, 0x00); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed); + } } - if ((srb->cmnd[1] & 0x02) || (srb->cmnd[1] & 0x04)) + if ((srb->cmnd[1] & 0x02) || (srb->cmnd[1] & 0x04)) { cmd13_checkbit = 1; + } for (i = 0; i < 3; i++) { retval = ext_sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr, SD_RSP_TYPE_R1, NULL, 0, cmd13_checkbit); - if (retval == STATUS_SUCCESS) + if (retval == STATUS_SUCCESS) { break; + } } - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed); + } scsi_set_resid(srb, 0); return TRANSPORT_GOOD; @@ -4055,13 +4252,14 @@ int sd_execute_read_data(struct scsi_cmnd *srb, struct rtsx_chip *chip) SD_Execute_Read_Cmd_Failed: sd_card->pre_cmd_err = 1; set_sense_type(chip, lun, SENSE_TYPE_NO_SENSE); - if (read_err) + if (read_err) { set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); - + } release_sd_card(chip); do_reset_sd_card(chip); - if (!(chip->card_ready & SD_CARD)) + if (!(chip->card_ready & SD_CARD)) { set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT); + } TRACE_RET(chip, TRANSPORT_FAILED); } @@ -4093,18 +4291,20 @@ int sd_execute_write_data(struct scsi_cmnd *srb, struct rtsx_chip *chip) } retval = sd_switch_clock(chip); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, TRANSPORT_FAILED); + } cmd_idx = srb->cmnd[2] & 0x3F; - if (srb->cmnd[1] & 0x04) + if (srb->cmnd[1] & 0x04) { send_cmd12 = 1; - - if (srb->cmnd[1] & 0x02) + } + if (srb->cmnd[1] & 0x02) { standby = 1; - - if (srb->cmnd[1] & 0x01) + } + if (srb->cmnd[1] & 0x01) { acmd = 1; + } data_len = ((u32)srb->cmnd[7] << 16) | ((u32)srb->cmnd[8] << 8) | srb->cmnd[9]; arg = ((u32)srb->cmnd[3] << 24) | ((u32)srb->cmnd[4] << 16) | @@ -4125,66 +4325,75 @@ int sd_execute_write_data(struct scsi_cmnd *srb, struct rtsx_chip *chip) sd_card->last_rsp_type = rsp_type; retval = sd_switch_clock(chip); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, TRANSPORT_FAILED); + } #ifdef SUPPORT_SD_LOCK if ((sd_card->sd_lock_status & SD_LOCK_1BIT_MODE) == 0) { if (CHK_MMC_8BIT(sd_card)) { retval = rtsx_write_register(chip, REG_SD_CFG1, 0x03, SD_BUS_WIDTH_8); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, TRANSPORT_FAILED); - + } } else if (CHK_SD(sd_card) || CHK_MMC_4BIT(sd_card)) { retval = rtsx_write_register(chip, REG_SD_CFG1, 0x03, SD_BUS_WIDTH_4); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, TRANSPORT_FAILED); + } } } #else retval = rtsx_write_register(chip, REG_SD_CFG1, 0x03, SD_BUS_WIDTH_4); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, TRANSPORT_FAILED); + } #endif if (data_len < 512) { retval = ext_sd_send_cmd_get_rsp(chip, SET_BLOCKLEN, data_len, SD_RSP_TYPE_R1, NULL, 0, 0); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed); + } } if (standby) { retval = sd_select_card(chip, 0); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed); + } } if (acmd) { retval = ext_sd_send_cmd_get_rsp(chip, APP_CMD, sd_card->sd_addr, SD_RSP_TYPE_R1, NULL, 0, 0); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed); + } } retval = ext_sd_send_cmd_get_rsp(chip, cmd_idx, arg, rsp_type, sd_card->rsp, rsp_len, 0); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed); + } if (data_len <= 512) { u16 i; u8 *buf; buf = kmalloc(data_len, GFP_KERNEL); - if (buf == NULL) + if (buf == NULL) { TRACE_RET(chip, TRANSPORT_ERROR); + } rtsx_stor_get_xfer_buf(buf, data_len, srb); #ifdef SUPPORT_SD_LOCK - if (cmd_idx == LOCK_UNLOCK) + if (cmd_idx == LOCK_UNLOCK) { lock_cmd_type = buf[0] & 0x0F; + } #endif if (data_len > 256) { @@ -4276,11 +4485,11 @@ int sd_execute_write_data(struct scsi_cmnd *srb, struct rtsx_chip *chip) } rtsx_init_cmd(chip); - if (CHECK_PID(chip, 0x5209)) + if (CHECK_PID(chip, 0x5209)) { rtsx_add_cmd(chip, CHECK_REG_CMD, SD_BUS_STAT, SD_DAT0_STATUS, SD_DAT0_STATUS); - else + } else { rtsx_add_cmd(chip, CHECK_REG_CMD, 0xFD30, 0x02, 0x02); - + } rtsx_send_cmd(chip, SD_CARD, 250); retval = sd_update_lock_status(chip); @@ -4293,53 +4502,61 @@ int sd_execute_write_data(struct scsi_cmnd *srb, struct rtsx_chip *chip) if (standby) { retval = sd_select_card(chip, 1); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed); + } } if (send_cmd12) { retval = ext_sd_send_cmd_get_rsp(chip, STOP_TRANSMISSION, 0, SD_RSP_TYPE_R1b, NULL, 0, 0); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed); + } } if (data_len < 512) { retval = ext_sd_send_cmd_get_rsp(chip, SET_BLOCKLEN, 0x200, SD_RSP_TYPE_R1, NULL, 0, 0); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed); + } retval = rtsx_write_register(chip, SD_BYTE_CNT_H, 0xFF, 0x02); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed); - + } rtsx_write_register(chip, SD_BYTE_CNT_L, 0xFF, 0x00); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed); + } } - if ((srb->cmnd[1] & 0x02) || (srb->cmnd[1] & 0x04)) + if ((srb->cmnd[1] & 0x02) || (srb->cmnd[1] & 0x04)) { cmd13_checkbit = 1; + } for (i = 0; i < 3; i++) { retval = ext_sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr, SD_RSP_TYPE_R1, NULL, 0, cmd13_checkbit); - if (retval == STATUS_SUCCESS) + if (retval == STATUS_SUCCESS) { break; + } } - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed); + } #ifdef SUPPORT_SD_LOCK if (cmd_idx == LOCK_UNLOCK) { if (!lock_cmd_fail) { RTSX_DEBUGP("lock_cmd_type = 0x%x\n", lock_cmd_type); - if (lock_cmd_type & SD_CLR_PWD) + if (lock_cmd_type & SD_CLR_PWD) { sd_card->sd_lock_status &= ~SD_PWD_EXIST; - - if (lock_cmd_type & SD_SET_PWD) + } + if (lock_cmd_type & SD_SET_PWD) { sd_card->sd_lock_status |= SD_PWD_EXIST; + } } RTSX_DEBUGP("sd_lock_state = 0x%x, sd_card->sd_lock_status = 0x%x\n", @@ -4376,13 +4593,14 @@ int sd_execute_write_data(struct scsi_cmnd *srb, struct rtsx_chip *chip) SD_Execute_Write_Cmd_Failed: sd_card->pre_cmd_err = 1; set_sense_type(chip, lun, SENSE_TYPE_NO_SENSE); - if (write_err) + if (write_err) { set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_ERR); - + } release_sd_card(chip); do_reset_sd_card(chip); - if (!(chip->card_ready & SD_CARD)) + if (!(chip->card_ready & SD_CARD)) { set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT); + } TRACE_RET(chip, TRANSPORT_FAILED); } @@ -4452,8 +4670,9 @@ int sd_hw_rst(struct scsi_cmnd *srb, struct rtsx_chip *chip) switch (srb->cmnd[1] & 0x0F) { case 0: #ifdef SUPPORT_SD_LOCK - if (0x64 == srb->cmnd[9]) + if (0x64 == srb->cmnd[9]) { sd_card->sd_lock_status |= SD_SDR_RST; + } #endif retval = reset_sd_card(chip); if (retval != STATUS_SUCCESS) { @@ -4504,23 +4723,26 @@ int sd_power_off_card3v3(struct rtsx_chip *chip) int retval; retval = disable_card_clock(chip, SD_CARD); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } RTSX_WRITE_REG(chip, CARD_OE, SD_OUTPUT_EN, 0); if (!chip->ft2_fast_mode) { retval = card_power_off(chip, SD_CARD); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } wait_timeout(50); } if (chip->asic_code) { retval = sd_pull_ctl_disable(chip); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } } else { RTSX_WRITE_REG(chip, FPGA_PULL_CTL, FPGA_SD_PULL_CTL_BIT | 0x20, FPGA_SD_PULL_CTL_BIT); @@ -4552,16 +4774,19 @@ int release_sd_card(struct rtsx_chip *chip) memset(sd_card->raw_scr, 0, 8); retval = sd_power_off_card3v3(chip); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } if (CHECK_PID(chip, 0x5209)) { retval = sd_change_bank_voltage(chip, SD_IO_3V3); - if (retval != STATUS_SUCCESS) + if (retval != STATUS_SUCCESS) { TRACE_RET(chip, STATUS_FAIL); + } - if (CHK_SD30_SPEED(sd_card)) + if (CHK_SD30_SPEED(sd_card)) { RTSX_WRITE_REG(chip, SD30_DRIVE_SEL, 0x07, chip->sd30_drive_sel_3v3); + } RTSX_WRITE_REG(chip, OCPPARA2, SD_OCP_THD_MASK, chip->sd_400mA_ocp_thd); } diff --git a/trunk/drivers/staging/rts_pstor/trace.h b/trunk/drivers/staging/rts_pstor/trace.h index cf60a1b872b3..bc83b49a4eb4 100644 --- a/trunk/drivers/staging/rts_pstor/trace.h +++ b/trunk/drivers/staging/rts_pstor/trace.h @@ -83,9 +83,33 @@ do { \ #endif #ifdef CONFIG_RTS_PSTOR_DEBUG -#define RTSX_DUMP(buf, buf_len) \ - print_hex_dump(KERN_DEBUG, RTSX_STOR, DUMP_PREFIX_NONE, \ - 16, 1, (buf), (buf_len), false) +static inline void rtsx_dump(u8 *buf, int buf_len) +{ + int i; + u8 tmp[16] = {0}; + u8 *_ptr = buf; + + for (i = 0; i < ((buf_len)/16); i++) { + RTSX_DEBUGP("%02x %02x %02x %02x %02x %02x %02x %02x " + "%02x %02x %02x %02x %02x %02x %02x %02x\n", + _ptr[0], _ptr[1], _ptr[2], _ptr[3], _ptr[4], _ptr[5], + _ptr[6], _ptr[7], _ptr[8], _ptr[9], _ptr[10], _ptr[11], + _ptr[12], _ptr[13], _ptr[14], _ptr[15]); + _ptr += 16; + } + if ((buf_len) % 16) { + memcpy(tmp, _ptr, (buf_len) % 16); + _ptr = tmp; + RTSX_DEBUGP("%02x %02x %02x %02x %02x %02x %02x %02x " + "%02x %02x %02x %02x %02x %02x %02x %02x\n", + _ptr[0], _ptr[1], _ptr[2], _ptr[3], _ptr[4], _ptr[5], + _ptr[6], _ptr[7], _ptr[8], _ptr[9], _ptr[10], _ptr[11], + _ptr[12], _ptr[13], _ptr[14], _ptr[15]); + } +} + +#define RTSX_DUMP(buf, buf_len) rtsx_dump((u8 *)(buf), (buf_len)) + #else #define RTSX_DUMP(buf, buf_len) #endif diff --git a/trunk/drivers/staging/sbe-2t3e3/2t3e3.h b/trunk/drivers/staging/sbe-2t3e3/2t3e3.h index ccad049c1122..383f2cfc1ad2 100644 --- a/trunk/drivers/staging/sbe-2t3e3/2t3e3.h +++ b/trunk/drivers/staging/sbe-2t3e3/2t3e3.h @@ -789,6 +789,7 @@ void dc_restart(struct channel *); void dc_receiver_onoff(struct channel *, u32); void dc_transmitter_onoff(struct channel *, u32); void dc_set_loopback(struct channel *, u32); +u32 dc_init_descriptor_list(struct channel *); void dc_clear_descriptor_list(struct channel *); void dc_drop_descriptor_list(struct channel *); void dc_set_output_port(struct channel *); diff --git a/trunk/drivers/staging/sbe-2t3e3/dc.c b/trunk/drivers/staging/sbe-2t3e3/dc.c index daadd6ea4978..9e81d9036a33 100644 --- a/trunk/drivers/staging/sbe-2t3e3/dc.c +++ b/trunk/drivers/staging/sbe-2t3e3/dc.c @@ -17,8 +17,6 @@ #include "2t3e3.h" #include "ctrl.h" -static int dc_init_descriptor_list(struct channel *sc); - void dc_init(struct channel *sc) { u32 val; @@ -309,7 +307,7 @@ void dc_set_loopback(struct channel *sc, u32 mode) SBE_2T3E3_21143_VAL_FULL_DUPLEX_MODE); } -static int dc_init_descriptor_list(struct channel *sc) +u32 dc_init_descriptor_list(struct channel *sc) { u32 i, j; struct sk_buff *m; @@ -319,7 +317,7 @@ static int dc_init_descriptor_list(struct channel *sc) sizeof(t3e3_rx_desc_t), GFP_KERNEL); if (sc->ether.rx_ring == NULL) { dev_err(&sc->pdev->dev, "SBE 2T3E3: no buffer space for RX ring\n"); - return -ENOMEM; + return ENOMEM; } if (sc->ether.tx_ring == NULL) @@ -329,7 +327,7 @@ static int dc_init_descriptor_list(struct channel *sc) kfree(sc->ether.rx_ring); sc->ether.rx_ring = NULL; dev_err(&sc->pdev->dev, "SBE 2T3E3: no buffer space for RX ring\n"); - return -ENOMEM; + return ENOMEM; } @@ -353,7 +351,7 @@ static int dc_init_descriptor_list(struct channel *sc) sc->ether.tx_ring = NULL; dev_err(&sc->pdev->dev, "SBE 2T3E3: token_alloc err:" " no buffer space for RX ring\n"); - return -ENOBUFS; + return ENOBUFS; } sc->ether.rx_data[i] = m; } diff --git a/trunk/drivers/staging/sbe-2t3e3/module.c b/trunk/drivers/staging/sbe-2t3e3/module.c index 8adb17816ad9..cd778b3a02b2 100644 --- a/trunk/drivers/staging/sbe-2t3e3/module.c +++ b/trunk/drivers/staging/sbe-2t3e3/module.c @@ -67,7 +67,6 @@ static int __devinit t3e3_init_channel(struct channel *channel, struct pci_dev * dev = alloc_hdlcdev(channel); if (!dev) { printk(KERN_ERR "SBE 2T3E3" ": Out of memory\n"); - err = -ENOMEM; goto free_regions; } @@ -83,9 +82,8 @@ static int __devinit t3e3_init_channel(struct channel *channel, struct pci_dev * else channel->h.slot = 0; - err = setup_device(dev, channel); - if (err) - goto free_dev; + if (setup_device(dev, channel)) + goto free_regions; pci_read_config_dword(channel->pdev, 0x40, &val); /* mask sleep mode */ pci_write_config_dword(channel->pdev, 0x40, val & 0x3FFFFFFF); @@ -94,19 +92,14 @@ static int __devinit t3e3_init_channel(struct channel *channel, struct pci_dev * pci_read_config_dword(channel->pdev, PCI_COMMAND, &channel->h.command); t3e3_init(channel); - err = request_irq(dev->irq, &t3e3_intr, IRQF_SHARED, dev->name, dev); - if (err) { + if (request_irq(dev->irq, &t3e3_intr, IRQF_SHARED, dev->name, dev)) { printk(KERN_WARNING "%s: could not get irq: %d\n", dev->name, dev->irq); - goto unregister_dev; + goto free_regions; } pci_set_drvdata(pdev, channel); return 0; -unregister_dev: - unregister_hdlc_device(dev); -free_dev: - free_netdev(dev); free_regions: pci_release_regions(pdev); disable: diff --git a/trunk/drivers/staging/sbe-2t3e3/netdev.c b/trunk/drivers/staging/sbe-2t3e3/netdev.c index 180c96327b9a..c7b5e8bb04ff 100644 --- a/trunk/drivers/staging/sbe-2t3e3/netdev.c +++ b/trunk/drivers/staging/sbe-2t3e3/netdev.c @@ -21,13 +21,13 @@ #include #include "2t3e3.h" -static int t3e3_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) +int t3e3_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) { struct channel *sc = dev_to_priv(dev); int cmd_2t3e3, len, rlen; t3e3_param_t param; t3e3_resp_t resp; - void __user *data = ifr->ifr_data + sizeof(cmd_2t3e3) + sizeof(len); + void *data = ifr->ifr_data + sizeof(cmd_2t3e3) + sizeof(len); if (cmd == SIOCWANDEV) return hdlc_ioctl(dev, ifr, cmd); @@ -82,7 +82,7 @@ static struct net_device_stats* t3e3_get_stats(struct net_device *dev) return nstats; } -static int t3e3_open(struct net_device *dev) +int t3e3_open(struct net_device *dev) { struct channel *sc = dev_to_priv(dev); int ret = hdlc_open(dev); @@ -97,7 +97,7 @@ static int t3e3_open(struct net_device *dev) return 0; } -static int t3e3_close(struct net_device *dev) +int t3e3_close(struct net_device *dev) { struct channel *sc = dev_to_priv(dev); hdlc_close(dev); diff --git a/trunk/drivers/staging/sep/sep_main.c b/trunk/drivers/staging/sep/sep_main.c index a414e52dd082..ca8946acba60 100644 --- a/trunk/drivers/staging/sep/sep_main.c +++ b/trunk/drivers/staging/sep/sep_main.c @@ -719,7 +719,7 @@ static int sep_mmap(struct file *filp, struct vm_area_struct *vma) if (remap_pfn_range(vma, vma->vm_start, bus_addr >> PAGE_SHIFT, vma->vm_end - vma->vm_start, vma->vm_page_prot)) { - dev_dbg(&sep->pdev->dev, "[PID%d] remap_pfn_range failed\n", + dev_dbg(&sep->pdev->dev, "[PID%d] remap_page_range failed\n", current->pid); error = -EAGAIN; goto end_function_with_error; diff --git a/trunk/drivers/staging/serqt_usb2/serqt_usb2.c b/trunk/drivers/staging/serqt_usb2/serqt_usb2.c index 5c969ade2eb7..8a362f7af379 100644 --- a/trunk/drivers/staging/serqt_usb2/serqt_usb2.c +++ b/trunk/drivers/staging/serqt_usb2/serqt_usb2.c @@ -247,6 +247,7 @@ static void ProcessLineStatus(struct quatech_port *qt_port, qt_port->shadowLSR = line_status & (SERIAL_LSR_OE | SERIAL_LSR_PE | SERIAL_LSR_FE | SERIAL_LSR_BI); + return; } static void ProcessModemStatus(struct quatech_port *qt_port, @@ -255,6 +256,7 @@ static void ProcessModemStatus(struct quatech_port *qt_port, qt_port->shadowMSR = modem_status; wake_up_interruptible(&qt_port->wait); + return; } static void ProcessRxChar(struct tty_struct *tty, struct usb_serial_port *port, @@ -313,8 +315,10 @@ static void qt_read_bulk_callback(struct urb *urb) } tty = tty_port_tty_get(&port->port); - if (!tty) + if (!tty) { + dbg("%s - bad tty pointer - exiting", __func__); return; + } data = urb->transfer_buffer; @@ -360,7 +364,7 @@ static void qt_read_bulk_callback(struct urb *urb) goto exit; } - if (RxCount) { + if (tty && RxCount) { flag_data = 0; for (i = 0; i < RxCount; ++i) { /* Look ahead code here */ @@ -424,7 +428,7 @@ static void qt_read_bulk_callback(struct urb *urb) dbg("%s - failed resubmitting read urb, error %d", __func__, result); else { - if (RxCount) { + if (tty && RxCount) { tty_flip_buffer_push(tty); tty_schedule_flip(tty); } @@ -702,7 +706,7 @@ static int qt_startup(struct usb_serial *serial) port = serial->port[i]; qt_port = kzalloc(sizeof(*qt_port), GFP_KERNEL); if (!qt_port) { - dbg("%s: kzalloc for quatech_port (%d) failed!.", + dbg("%s: kmalloc for quatech_port (%d) failed!.", __func__, i); for (--i; i >= 0; i--) { port = serial->port[i]; @@ -893,6 +897,8 @@ static int qt_open(struct tty_struct *tty, * Put this here to make it responsive to stty and defaults set by * the tty layer */ + /* FIXME: is this needed? */ + /* qt_set_termios(tty, port, NULL); */ /* Check to see if we've set up our endpoint info yet */ if (port0->open_ports == 1) { @@ -1189,7 +1195,7 @@ static void qt_set_termios(struct tty_struct *tty, struct usb_serial_port *port, struct ktermios *old_termios) { - struct ktermios *termios = &tty->termios; + struct ktermios *termios = tty->termios; unsigned char new_LCR = 0; unsigned int cflag = termios->c_cflag; unsigned int index; @@ -1198,7 +1204,7 @@ static void qt_set_termios(struct tty_struct *tty, index = tty->index - port->serial->minor; - switch (cflag & CSIZE) { + switch (cflag) { case CS5: new_LCR |= SERIAL_5_DATA; break; @@ -1209,8 +1215,6 @@ static void qt_set_termios(struct tty_struct *tty, new_LCR |= SERIAL_7_DATA; break; default: - termios->c_cflag &= ~CSIZE; - termios->c_cflag |= CS8; case CS8: new_LCR |= SERIAL_8_DATA; break; @@ -1297,7 +1301,7 @@ static void qt_set_termios(struct tty_struct *tty, dbg(__FILE__ "BoxSetSW_FlowCtrl (diabling) failed\n"); } - termios->c_cflag &= ~CMSPAR; + tty->termios->c_cflag &= ~CMSPAR; /* FIXME: Error cases should be returning the actual bits changed only */ } @@ -1408,7 +1412,7 @@ static int qt_tiocmget(struct tty_struct *tty) struct usb_serial_port *port = tty->driver_data; struct usb_serial *serial = get_usb_serial(port, __func__); struct quatech_port *qt_port = qt_get_port_private(port); - int retval; + int retval = -ENODEV; if (!serial) return -ENODEV; @@ -1426,7 +1430,7 @@ static int qt_tiocmset(struct tty_struct *tty, struct usb_serial_port *port = tty->driver_data; struct usb_serial *serial = get_usb_serial(port, __func__); struct quatech_port *qt_port = qt_get_port_private(port); - int retval; + int retval = -ENODEV; if (!serial) return -ENODEV; @@ -1454,6 +1458,7 @@ static void qt_throttle(struct tty_struct *tty) qt_port->RxHolding = 1; mutex_unlock(&qt_port->lock); + return; } static void qt_unthrottle(struct tty_struct *tty) @@ -1494,6 +1499,8 @@ static void qt_unthrottle(struct tty_struct *tty) } } mutex_unlock(&qt_port->lock); + return; + } static int qt_calc_num_ports(struct usb_serial *serial) diff --git a/trunk/drivers/staging/silicom/Kconfig b/trunk/drivers/staging/silicom/Kconfig deleted file mode 100644 index eda2e7d73645..000000000000 --- a/trunk/drivers/staging/silicom/Kconfig +++ /dev/null @@ -1,46 +0,0 @@ -# -# Silicom device configuration -# - -config NET_VENDOR_SILICOM - bool "Silicom devices" - default y - depends on PCI - ---help--- - If you have a network card (Ethernet) belonging to this class, - say Y. - - Note that the answer to this question does not directly affect - the kernel: saying N will just case the configurator to skip all - the questions regarding Silicom chipsets. If you say Y, you will be asked - for your specific chipset/driver in the following questions. - -if NET_VENDOR_SILICOM - -config SBYPASS - tristate "Silicom BypassCTL library support" - depends on PCI && NET - depends on m - ---help--- - If you have a network (Ethernet) controller of this type, say Y - - To compile this driver as a module, choose M here. The module - will be called bypass. - -config BPCTL - tristate "Silicom BypassCTL net support" - depends on PCI && NET - depends on m - select SBYPASS - select NET_CORE - select MII - ---help--- - If you have a network (Ethernet) controller of this type, say Y - or M and read the Ethernet-HOWTO, available from - . - - To compile this driver as a module, choose M here. The module - will be called bpctl_mod. - - -endif # NET_VENDOR_SILICOM diff --git a/trunk/drivers/staging/silicom/Makefile b/trunk/drivers/staging/silicom/Makefile deleted file mode 100644 index 80e6d12d156b..000000000000 --- a/trunk/drivers/staging/silicom/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -# -# Makefile for the Bypass network device drivers. -# - -obj-$(CONFIG_BPCTL) += bpctl_mod.o -obj-$(CONFIG_SBYPASS) += bypasslib/ - - -bpctl_mod-objs := bp_mod.o bp_proc.o diff --git a/trunk/drivers/staging/silicom/README b/trunk/drivers/staging/silicom/README deleted file mode 100644 index ae970b37fdc6..000000000000 --- a/trunk/drivers/staging/silicom/README +++ /dev/null @@ -1,14 +0,0 @@ - -Theory of Operation: - -The Silicom Bypass Network Interface Cards (NICs) are network cards with paired ports (2 or 4). -The pairs either act as a "wire" allowing the network packets to pass or insert the device in -between the two ports. When paired with the on-board hardware watchdog or other failsafe, -they provide high availability for the network in the face of software outages or maintenance. - -The software requirements are for a kernel level driver that interfaces with the bypass and watchdog, -as well as for control software. User control can be either the provided standalone executable -(/bin/bpctl) or the API exposed by the Silicom library. - - - diff --git a/trunk/drivers/staging/silicom/TODO b/trunk/drivers/staging/silicom/TODO deleted file mode 100644 index 09d07b0ea9c0..000000000000 --- a/trunk/drivers/staging/silicom/TODO +++ /dev/null @@ -1,8 +0,0 @@ -TODO: - - checkpatch.pl cleanups - - locking audit - - single module with all functionality - - userland - - fix monolithic build. - - diff --git a/trunk/drivers/staging/silicom/bits.h b/trunk/drivers/staging/silicom/bits.h deleted file mode 100644 index 8c411d0d4ecd..000000000000 --- a/trunk/drivers/staging/silicom/bits.h +++ /dev/null @@ -1,56 +0,0 @@ -/******************************************************************************/ -/* */ -/* Broadcom BCM5700 Linux Network Driver, Copyright (c) 2000 - 2004 Broadcom */ -/* Corporation. */ -/* All rights reserved. */ -/* */ -/* This program is free software; you can redistribute it and/or modify */ -/* it under the terms of the GNU General Public License as published by */ -/* the Free Software Foundation, located in the file LICENSE. */ -/* */ -/* History: */ -/* 02/25/00 Hav Khauv Initial version. */ -/******************************************************************************/ - -#ifndef BITS_H -#define BITS_H - -/******************************************************************************/ -/* Bit Mask definitions */ -/******************************************************************************/ - -#define BIT_NONE 0x00 -#define BIT_0 0x01 -#define BIT_1 0x02 -#define BIT_2 0x04 -#define BIT_3 0x08 -#define BIT_4 0x10 -#define BIT_5 0x20 -#define BIT_6 0x40 -#define BIT_7 0x80 -#define BIT_8 0x0100 -#define BIT_9 0x0200 -#define BIT_10 0x0400 -#define BIT_11 0x0800 -#define BIT_12 0x1000 -#define BIT_13 0x2000 -#define BIT_14 0x4000 -#define BIT_15 0x8000 -#define BIT_16 0x010000 -#define BIT_17 0x020000 -#define BIT_18 0x040000 -#define BIT_19 0x080000 -#define BIT_20 0x100000 -#define BIT_21 0x200000 -#define BIT_22 0x400000 -#define BIT_23 0x800000 -#define BIT_24 0x01000000 -#define BIT_25 0x02000000 -#define BIT_26 0x04000000 -#define BIT_27 0x08000000 -#define BIT_28 0x10000000 -#define BIT_29 0x20000000 -#define BIT_30 0x40000000 -#define BIT_31 0x80000000 - -#endif /* BITS_H */ diff --git a/trunk/drivers/staging/silicom/bp_ioctl.h b/trunk/drivers/staging/silicom/bp_ioctl.h deleted file mode 100644 index 57de34a69e8e..000000000000 --- a/trunk/drivers/staging/silicom/bp_ioctl.h +++ /dev/null @@ -1,140 +0,0 @@ -/******************************************************************************/ -/* */ -/* Silicom Bypass Control Utility, Copyright (c) 2005-2007 Silicom */ -/* All rights reserved. */ -/* */ -/* This program is free software; you can redistribute it and/or modify */ -/* it under the terms of the GNU General Public License as published by */ -/* the Free Software Foundation, located in the file LICENSE. */ -/* */ -/* */ -/******************************************************************************/ - -#ifndef BP_IOCTL_H -#define BP_IOCTL_H - -#define BP_CAP 0x01 /* BIT_0 */ -#define BP_STATUS_CAP 0x02 -#define BP_STATUS_CHANGE_CAP 0x04 -#define SW_CTL_CAP 0x08 -#define BP_DIS_CAP 0x10 -#define BP_DIS_STATUS_CAP 0x20 -#define STD_NIC_CAP 0x40 -#define BP_PWOFF_ON_CAP 0x80 -#define BP_PWOFF_OFF_CAP 0x0100 -#define BP_PWOFF_CTL_CAP 0x0200 -#define BP_PWUP_ON_CAP 0x0400 -#define BP_PWUP_OFF_CAP 0x0800 -#define BP_PWUP_CTL_CAP 0x1000 -#define WD_CTL_CAP 0x2000 -#define WD_STATUS_CAP 0x4000 -#define WD_TIMEOUT_CAP 0x8000 -#define TX_CTL_CAP 0x10000 -#define TX_STATUS_CAP 0x20000 -#define TAP_CAP 0x40000 -#define TAP_STATUS_CAP 0x80000 -#define TAP_STATUS_CHANGE_CAP 0x100000 -#define TAP_DIS_CAP 0x200000 -#define TAP_DIS_STATUS_CAP 0x400000 -#define TAP_PWUP_ON_CAP 0x800000 -#define TAP_PWUP_OFF_CAP 0x1000000 -#define TAP_PWUP_CTL_CAP 0x2000000 -#define NIC_CAP_NEG 0x4000000 -#define TPL_CAP 0x8000000 -#define DISC_CAP 0x10000000 -#define DISC_DIS_CAP 0x20000000 -#define DISC_PWUP_CTL_CAP 0x40000000 - -#define TPL2_CAP_EX 0x01 -#define DISC_PORT_CAP_EX 0x02 - -#define WD_MIN_TIME_MASK(val) (val & 0xf) -#define WD_STEP_COUNT_MASK(val) ((val & 0xf) << 5) -#define WDT_STEP_TIME 0x10 /* BIT_4 */ - -#define WD_MIN_TIME_GET(desc) (desc & 0xf) -#define WD_STEP_COUNT_GET(desc) ((desc>>5) & 0xf) - -typedef enum { - IF_SCAN, - GET_DEV_NUM, - IS_BYPASS, - GET_BYPASS_SLAVE, - GET_BYPASS_CAPS, - GET_WD_SET_CAPS, - SET_BYPASS, - GET_BYPASS, - GET_BYPASS_CHANGE, - SET_BYPASS_WD, - GET_BYPASS_WD, - GET_WD_EXPIRE_TIME, - RESET_BYPASS_WD_TIMER, - SET_DIS_BYPASS, - GET_DIS_BYPASS, - SET_BYPASS_PWOFF, - GET_BYPASS_PWOFF, - SET_BYPASS_PWUP, - GET_BYPASS_PWUP, - SET_STD_NIC, - GET_STD_NIC, - SET_TX, - GET_TX, - SET_TAP, - GET_TAP, - GET_TAP_CHANGE, - SET_DIS_TAP, - GET_DIS_TAP, - SET_TAP_PWUP, - GET_TAP_PWUP, - SET_WD_EXP_MODE, - GET_WD_EXP_MODE, - SET_WD_AUTORESET, - GET_WD_AUTORESET, - SET_TPL, - GET_TPL, - SET_DISC, - GET_DISC, - GET_DISC_CHANGE, - SET_DIS_DISC, - GET_DIS_DISC, - SET_DISC_PWUP, - GET_DISC_PWUP, - GET_BYPASS_INFO = 100, - GET_BP_WAIT_AT_PWUP, - SET_BP_WAIT_AT_PWUP, - GET_BP_HW_RESET, - SET_BP_HW_RESET, - SET_DISC_PORT, - GET_DISC_PORT, - SET_DISC_PORT_PWUP, - GET_DISC_PORT_PWUP, - SET_BP_FORCE_LINK, - GET_BP_FORCE_LINK, -#ifdef BP_SELF_TEST - SET_BP_SELF_TEST = 200, - GET_BP_SELF_TEST, -#endif - -} CMND_TYPE_SD; - -/* -* The major device number. We can't rely on dynamic -* registration any more, because ioctls need to know -* it. -*/ - -#define MAGIC_NUM 'J' - -/* for passing single values */ -struct bpctl_cmd { - int status; - int data[8]; - int in_param[8]; - int out_param[8]; -}; - -#define IOCTL_TX_MSG(cmd) _IOWR(MAGIC_NUM, cmd, struct bpctl_cmd) - -#define DEVICE_NAME "bpctl" - -#endif diff --git a/trunk/drivers/staging/silicom/bp_mod.c b/trunk/drivers/staging/silicom/bp_mod.c deleted file mode 100644 index 3cfd0516adfa..000000000000 --- a/trunk/drivers/staging/silicom/bp_mod.c +++ /dev/null @@ -1,8931 +0,0 @@ -/******************************************************************************/ -/* */ -/* Bypass Control utility, Copyright (c) 2005-20011 Silicom */ -/* */ -/* 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, located in the file LICENSE. */ -/* Copyright(c) 2007 - 2009 Intel Corporation. All rights reserved. */ -/* */ -/* */ -/******************************************************************************/ -#include - -#include /* We're doing kernel work */ -#include /* Specifically, a module */ -#include -#include -#include -#include -#include -#include -#include - -#include /* for get_user and put_user */ -#include -#include -#include - -#include "bp_ioctl.h" -#include "bp_mod.h" -#include "bypass.h" -#include "libbp_sd.h" - -#define SUCCESS 0 -#define BP_MOD_VER "9.0.4" -#define BP_MOD_DESCR "Silicom Bypass-SD Control driver" -#define BP_SYNC_FLAG 1 - -static int Device_Open = 0; -static int major_num = 0; - -MODULE_AUTHOR("Anna Lukin, annal@silicom.co.il"); -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION(BP_MOD_DESCR); -MODULE_VERSION(BP_MOD_VER); -spinlock_t bpvm_lock; - -#define lock_bpctl() \ -if (down_interruptible(&bpctl_sema)) { \ - return -ERESTARTSYS; \ -} \ - -#define unlock_bpctl() \ - up(&bpctl_sema); - -/* Media Types */ -typedef enum { - bp_copper = 0, - bp_fiber, - bp_cx4, - bp_none, -} bp_media_type; - -struct pfs_unit_sd { - struct proc_dir_entry *proc_entry; - char proc_name[32]; -}; - -struct bypass_pfs_sd { - char dir_name[32]; - struct proc_dir_entry *bypass_entry; - struct pfs_unit_sd bypass_info; - struct pfs_unit_sd bypass_slave; - struct pfs_unit_sd bypass_caps; - struct pfs_unit_sd wd_set_caps; - struct pfs_unit_sd bypass; - struct pfs_unit_sd bypass_change; - struct pfs_unit_sd bypass_wd; - struct pfs_unit_sd wd_expire_time; - struct pfs_unit_sd reset_bypass_wd; - struct pfs_unit_sd dis_bypass; - struct pfs_unit_sd bypass_pwup; - struct pfs_unit_sd bypass_pwoff; - struct pfs_unit_sd std_nic; - struct pfs_unit_sd tap; - struct pfs_unit_sd dis_tap; - struct pfs_unit_sd tap_pwup; - struct pfs_unit_sd tap_change; - struct pfs_unit_sd wd_exp_mode; - struct pfs_unit_sd wd_autoreset; - struct pfs_unit_sd tpl; - -}; - -typedef struct _bpctl_dev { - char *name; - char *desc; - struct pci_dev *pdev; /* PCI device */ - struct net_device *ndev; /* net device */ - unsigned long mem_map; - uint8_t bus; - uint8_t slot; - uint8_t func; - u_int32_t device; - u_int32_t vendor; - u_int32_t subvendor; - u_int32_t subdevice; - int ifindex; - uint32_t bp_caps; - uint32_t bp_caps_ex; - uint8_t bp_fw_ver; - int bp_ext_ver; - int wdt_status; - unsigned long bypass_wdt_on_time; - uint32_t bypass_timer_interval; - struct timer_list bp_timer; - uint32_t reset_time; - uint8_t bp_status_un; - atomic_t wdt_busy; - bp_media_type media_type; - int bp_tpl_flag; - struct timer_list bp_tpl_timer; - spinlock_t bypass_wr_lock; - int bp_10g; - int bp_10gb; - int bp_fiber5; - int bp_10g9; - int bp_i80; - int bp_540; - int (*hard_start_xmit_save) (struct sk_buff *skb, - struct net_device *dev); - const struct net_device_ops *old_ops; - struct net_device_ops new_ops; - int bp_self_test_flag; - char *bp_tx_data; - struct bypass_pfs_sd bypass_pfs_set; - -} bpctl_dev_t; - -static bpctl_dev_t *bpctl_dev_arr; - -static struct semaphore bpctl_sema; -static int device_num = 0; - -static int get_dev_idx(int ifindex); -static bpctl_dev_t *get_master_port_fn(bpctl_dev_t *pbpctl_dev); -static int disc_status(bpctl_dev_t *pbpctl_dev); -static int bypass_status(bpctl_dev_t *pbpctl_dev); -static int wdt_timer(bpctl_dev_t *pbpctl_dev, int *time_left); -static bpctl_dev_t *get_status_port_fn(bpctl_dev_t *pbpctl_dev); -static void if_scan_init(void); - -int bypass_proc_create_dev_sd(bpctl_dev_t *pbp_device_block); -int bypass_proc_remove_dev_sd(bpctl_dev_t *pbp_device_block); -int bp_proc_create(void); - -int is_bypass_fn(bpctl_dev_t *pbpctl_dev); -int get_dev_idx_bsf(int bus, int slot, int func); - -static unsigned long str_to_hex(char *p); -static int bp_device_event(struct notifier_block *unused, - unsigned long event, void *ptr) -{ - struct net_device *dev = ptr; - static bpctl_dev_t *pbpctl_dev = NULL, *pbpctl_dev_m = NULL; - int dev_num = 0, ret = 0, ret_d = 0, time_left = 0; - /* printk("BP_PROC_SUPPORT event =%d %s %d\n", event,dev->name, dev->ifindex ); */ - /* return NOTIFY_DONE; */ - if (!dev) - return NOTIFY_DONE; - if (event == NETDEV_REGISTER) { - { - struct ethtool_drvinfo drvinfo; - char cbuf[32]; - char *buf = NULL; - char res[10]; - int i = 0, ifindex, idx_dev = 0; - int bus = 0, slot = 0, func = 0; - ifindex = dev->ifindex; - - memset(res, 0, 10); - memset(&drvinfo, 0, sizeof(struct ethtool_drvinfo)); - - if (dev->ethtool_ops && dev->ethtool_ops->get_drvinfo) { - memset(&drvinfo, 0, sizeof(drvinfo)); - dev->ethtool_ops->get_drvinfo(dev, &drvinfo); - } else - return NOTIFY_DONE; - if (!drvinfo.bus_info) - return NOTIFY_DONE; - if (!strcmp(drvinfo.bus_info, "N/A")) - return NOTIFY_DONE; - memcpy(&cbuf, drvinfo.bus_info, 32); - buf = &cbuf[0]; - - while (*buf++ != ':') ; - for (i = 0; i < 10; i++, buf++) { - if (*buf == ':') - break; - res[i] = *buf; - - } - buf++; - bus = str_to_hex(res); - memset(res, 0, 10); - - for (i = 0; i < 10; i++, buf++) { - if (*buf == '.') - break; - res[i] = *buf; - - } - buf++; - slot = str_to_hex(res); - func = str_to_hex(buf); - idx_dev = get_dev_idx_bsf(bus, slot, func); - - if (idx_dev != -1) { - - bpctl_dev_arr[idx_dev].ifindex = ifindex; - bpctl_dev_arr[idx_dev].ndev = dev; - - bypass_proc_remove_dev_sd(&bpctl_dev_arr - [idx_dev]); - bypass_proc_create_dev_sd(&bpctl_dev_arr - [idx_dev]); - - } - - } - return NOTIFY_DONE; - - } - if (event == NETDEV_UNREGISTER) { - int idx_dev = 0; - for (idx_dev = 0; - ((bpctl_dev_arr[idx_dev].pdev != NULL) - && (idx_dev < device_num)); idx_dev++) { - if (bpctl_dev_arr[idx_dev].ndev == dev) { - bypass_proc_remove_dev_sd(&bpctl_dev_arr - [idx_dev]); - bpctl_dev_arr[idx_dev].ndev = NULL; - - return NOTIFY_DONE; - - } - - } - return NOTIFY_DONE; - } - if (event == NETDEV_CHANGENAME) { - int idx_dev = 0; - for (idx_dev = 0; - ((bpctl_dev_arr[idx_dev].pdev != NULL) - && (idx_dev < device_num)); idx_dev++) { - if (bpctl_dev_arr[idx_dev].ndev == dev) { - bypass_proc_remove_dev_sd(&bpctl_dev_arr - [idx_dev]); - bypass_proc_create_dev_sd(&bpctl_dev_arr - [idx_dev]); - - return NOTIFY_DONE; - - } - - } - return NOTIFY_DONE; - - } - - switch (event) { - - case NETDEV_CHANGE:{ - if (netif_carrier_ok(dev)) - return NOTIFY_DONE; - - if (((dev_num = get_dev_idx(dev->ifindex)) == -1) || - (!(pbpctl_dev = &bpctl_dev_arr[dev_num]))) - return NOTIFY_DONE; - - if ((is_bypass_fn(pbpctl_dev)) == 1) - pbpctl_dev_m = pbpctl_dev; - else - pbpctl_dev_m = get_master_port_fn(pbpctl_dev); - if (!pbpctl_dev_m) - return NOTIFY_DONE; - ret = bypass_status(pbpctl_dev_m); - if (ret == 1) - printk("bpmod: %s is in the Bypass mode now", - dev->name); - ret_d = disc_status(pbpctl_dev_m); - if (ret_d == 1) - printk - ("bpmod: %s is in the Disconnect mode now", - dev->name); - if (ret || ret_d) { - wdt_timer(pbpctl_dev_m, &time_left); - if (time_left == -1) - printk("; WDT has expired"); - printk(".\n"); - - } - return NOTIFY_DONE; - - } - - default: - return NOTIFY_DONE; - - } - return NOTIFY_DONE; - -} - -static struct notifier_block bp_notifier_block = { - .notifier_call = bp_device_event, -}; - -static int device_open(struct inode *inode, struct file *file) -{ -#ifdef DEBUG - printk("device_open(%p)\n", file); -#endif - Device_Open++; -/* -* Initialize the message -*/ - return SUCCESS; -} - -static int device_release(struct inode *inode, struct file *file) -{ -#ifdef DEBUG - printk("device_release(%p,%p)\n", inode, file); -#endif - Device_Open--; - return SUCCESS; -} - -int is_bypass_fn(bpctl_dev_t *pbpctl_dev); -int wdt_time_left(bpctl_dev_t *pbpctl_dev); - -static void write_pulse(bpctl_dev_t *pbpctl_dev, - unsigned int ctrl_ext, - unsigned char value, unsigned char len) -{ - unsigned char ctrl_val = 0; - unsigned int i = len; - unsigned int ctrl = 0; - bpctl_dev_t *pbpctl_dev_c = NULL; - - if (pbpctl_dev->bp_i80) - ctrl = BPCTL_READ_REG(pbpctl_dev, CTRL_EXT); - if (pbpctl_dev->bp_540) - ctrl = BP10G_READ_REG(pbpctl_dev, ESDP); - - if (pbpctl_dev->bp_10g9) { - if (!(pbpctl_dev_c = get_status_port_fn(pbpctl_dev))) - return; - ctrl = BP10G_READ_REG(pbpctl_dev_c, ESDP); - } - - while (i--) { - ctrl_val = (value >> i) & 0x1; - if (ctrl_val) { - if (pbpctl_dev->bp_10g9) { - - /* To start management : MCLK 1, MDIO 1, output */ - /* DATA 1 CLK 1 */ - /*BP10G_WRITE_REG(pbpctl_dev, I2CCTL, (ctrl_ext|BP10G_MCLK_DATA_OUT9|BP10G_MDIO_DATA_OUT9)); */ - BP10G_WRITE_REG(pbpctl_dev, I2CCTL, - ctrl_ext | - BP10G_MDIO_DATA_OUT9); - BP10G_WRITE_REG(pbpctl_dev_c, ESDP, - (ctrl | BP10G_MCLK_DATA_OUT9 | - BP10G_MCLK_DIR_OUT9)); - - } else if (pbpctl_dev->bp_fiber5) { - BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL, (ctrl_ext | - BPCTLI_CTRL_EXT_MCLK_DIR5 - | - BPCTLI_CTRL_EXT_MDIO_DIR5 - | - BPCTLI_CTRL_EXT_MDIO_DATA5 - | - BPCTLI_CTRL_EXT_MCLK_DATA5)); - - } else if (pbpctl_dev->bp_i80) { - BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL, (ctrl_ext | - BPCTLI_CTRL_EXT_MDIO_DIR80 - | - BPCTLI_CTRL_EXT_MDIO_DATA80)); - - BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, (ctrl | - BPCTLI_CTRL_EXT_MCLK_DIR80 - | - BPCTLI_CTRL_EXT_MCLK_DATA80)); - - } else if (pbpctl_dev->bp_540) { - BP10G_WRITE_REG(pbpctl_dev, ESDP, (ctrl | - BP540_MDIO_DIR - | - BP540_MDIO_DATA - | - BP540_MCLK_DIR - | - BP540_MCLK_DATA)); - - } else if (pbpctl_dev->bp_10gb) { - BP10GB_WRITE_REG(pbpctl_dev, MISC_REG_SPIO, - (ctrl_ext | BP10GB_MDIO_SET | - BP10GB_MCLK_SET) & - ~(BP10GB_MCLK_DIR | - BP10GB_MDIO_DIR | - BP10GB_MDIO_CLR | - BP10GB_MCLK_CLR)); - - } else if (!pbpctl_dev->bp_10g) - /* To start management : MCLK 1, MDIO 1, output */ - BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, - (ctrl_ext | - BPCTLI_CTRL_EXT_MCLK_DIR | - BPCTLI_CTRL_EXT_MDIO_DIR | - BPCTLI_CTRL_EXT_MDIO_DATA | - BPCTLI_CTRL_EXT_MCLK_DATA)); - else { - - /* To start management : MCLK 1, MDIO 1, output*/ - BP10G_WRITE_REG(pbpctl_dev, EODSDP, - (ctrl_ext | BP10G_MCLK_DATA_OUT - | BP10G_MDIO_DATA_OUT)); - - } - - usec_delay(PULSE_TIME); - if (pbpctl_dev->bp_10g9) { - - /*BP10G_WRITE_REG(pbpctl_dev, I2CCTL, ((ctrl_ext|BP10G_MDIO_DATA_OUT9)&~(BP10G_MCLK_DATA_OUT9))); */ - /* DATA 1 CLK 0 */ - BP10G_WRITE_REG(pbpctl_dev, I2CCTL, - ctrl_ext | - BP10G_MDIO_DATA_OUT9); - BP10G_WRITE_REG(pbpctl_dev_c, ESDP, - (ctrl | BP10G_MCLK_DIR_OUT9) & - ~BP10G_MCLK_DATA_OUT9); - - } else if (pbpctl_dev->bp_fiber5) { - BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL, - ((ctrl_ext | - BPCTLI_CTRL_EXT_MCLK_DIR5 | - BPCTLI_CTRL_EXT_MDIO_DIR5 | - BPCTLI_CTRL_EXT_MDIO_DATA5) - & - ~ - (BPCTLI_CTRL_EXT_MCLK_DATA5))); - - } else if (pbpctl_dev->bp_i80) { - BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL, (ctrl_ext | - BPCTLI_CTRL_EXT_MDIO_DIR80 - | - BPCTLI_CTRL_EXT_MDIO_DATA80)); - BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, - ((ctrl | - BPCTLI_CTRL_EXT_MCLK_DIR80) - & - ~ - (BPCTLI_CTRL_EXT_MCLK_DATA80))); - - } else if (pbpctl_dev->bp_540) { - BP10G_WRITE_REG(pbpctl_dev, ESDP, - (ctrl | BP540_MDIO_DIR | - BP540_MDIO_DATA | - BP540_MCLK_DIR) & - ~(BP540_MCLK_DATA)); - - } else if (pbpctl_dev->bp_10gb) { - - BP10GB_WRITE_REG(pbpctl_dev, MISC_REG_SPIO, - (ctrl_ext | BP10GB_MDIO_SET | - BP10GB_MCLK_CLR) & - ~(BP10GB_MCLK_DIR | - BP10GB_MDIO_DIR | - BP10GB_MDIO_CLR | - BP10GB_MCLK_SET)); - - } else if (!pbpctl_dev->bp_10g) - - BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, - ((ctrl_ext | - BPCTLI_CTRL_EXT_MCLK_DIR | - BPCTLI_CTRL_EXT_MDIO_DIR | - BPCTLI_CTRL_EXT_MDIO_DATA) - & - ~ - (BPCTLI_CTRL_EXT_MCLK_DATA))); - else { - - BP10G_WRITE_REG(pbpctl_dev, EODSDP, - ((ctrl_ext | - BP10G_MDIO_DATA_OUT) & - ~(BP10G_MCLK_DATA_OUT))); - } - - usec_delay(PULSE_TIME); - - } else { - if (pbpctl_dev->bp_10g9) { - /* DATA 0 CLK 1 */ - /*BP10G_WRITE_REG(pbpctl_dev, I2CCTL, ((ctrl_ext|BP10G_MCLK_DATA_OUT9)&~BP10G_MDIO_DATA_OUT9)); */ - BP10G_WRITE_REG(pbpctl_dev, I2CCTL, - (ctrl_ext & - ~BP10G_MDIO_DATA_OUT9)); - BP10G_WRITE_REG(pbpctl_dev_c, ESDP, - (ctrl | BP10G_MCLK_DATA_OUT9 | - BP10G_MCLK_DIR_OUT9)); - - } else if (pbpctl_dev->bp_fiber5) { - BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL, - ((ctrl_ext | - BPCTLI_CTRL_EXT_MCLK_DIR5 | - BPCTLI_CTRL_EXT_MDIO_DIR5 | - BPCTLI_CTRL_EXT_MCLK_DATA5) - & - ~ - (BPCTLI_CTRL_EXT_MDIO_DATA5))); - - } else if (pbpctl_dev->bp_i80) { - BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL, - ((ctrl_ext | - BPCTLI_CTRL_EXT_MDIO_DIR80) - & - ~ - (BPCTLI_CTRL_EXT_MDIO_DATA80))); - BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, - (ctrl | - BPCTLI_CTRL_EXT_MCLK_DIR80 | - BPCTLI_CTRL_EXT_MCLK_DATA80)); - - } else if (pbpctl_dev->bp_540) { - BP10G_WRITE_REG(pbpctl_dev, ESDP, - ((ctrl | BP540_MCLK_DIR | - BP540_MCLK_DATA | - BP540_MDIO_DIR) & - ~(BP540_MDIO_DATA))); - - } else if (pbpctl_dev->bp_10gb) { - BP10GB_WRITE_REG(pbpctl_dev, MISC_REG_SPIO, - (ctrl_ext | BP10GB_MDIO_CLR | - BP10GB_MCLK_SET) & - ~(BP10GB_MCLK_DIR | - BP10GB_MDIO_DIR | - BP10GB_MDIO_SET | - BP10GB_MCLK_CLR)); - - } else if (!pbpctl_dev->bp_10g) - - BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, - ((ctrl_ext | - BPCTLI_CTRL_EXT_MCLK_DIR | - BPCTLI_CTRL_EXT_MDIO_DIR | - BPCTLI_CTRL_EXT_MCLK_DATA) - & - ~ - (BPCTLI_CTRL_EXT_MDIO_DATA))); - else { - - BP10G_WRITE_REG(pbpctl_dev, EODSDP, - ((ctrl_ext | - BP10G_MCLK_DATA_OUT) & - ~BP10G_MDIO_DATA_OUT)); - - } - usec_delay(PULSE_TIME); - if (pbpctl_dev->bp_10g9) { - /* DATA 0 CLK 0 */ - /*BP10G_WRITE_REG(pbpctl_dev, I2CCTL, (ctrl_ext&~(BP10G_MCLK_DATA_OUT9|BP10G_MDIO_DATA_OUT9))); */ - BP10G_WRITE_REG(pbpctl_dev, I2CCTL, - (ctrl_ext & - ~BP10G_MDIO_DATA_OUT9)); - BP10G_WRITE_REG(pbpctl_dev_c, ESDP, - ((ctrl | BP10G_MCLK_DIR_OUT9) & - ~(BP10G_MCLK_DATA_OUT9))); - - } else if (pbpctl_dev->bp_fiber5) { - BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL, - ((ctrl_ext | - BPCTLI_CTRL_EXT_MCLK_DIR5 | - BPCTLI_CTRL_EXT_MDIO_DIR5) - & - ~(BPCTLI_CTRL_EXT_MCLK_DATA5 - | - BPCTLI_CTRL_EXT_MDIO_DATA5))); - - } else if (pbpctl_dev->bp_i80) { - BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL, - ((ctrl_ext | - BPCTLI_CTRL_EXT_MDIO_DIR80) - & - ~BPCTLI_CTRL_EXT_MDIO_DATA80)); - BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, - ((ctrl | - BPCTLI_CTRL_EXT_MCLK_DIR80) - & - ~ - (BPCTLI_CTRL_EXT_MCLK_DATA80))); - - } else if (pbpctl_dev->bp_540) { - BP10G_WRITE_REG(pbpctl_dev, ESDP, - ((ctrl | BP540_MCLK_DIR | - BP540_MDIO_DIR) & - ~(BP540_MDIO_DATA | - BP540_MCLK_DATA))); - } else if (pbpctl_dev->bp_10gb) { - - BP10GB_WRITE_REG(pbpctl_dev, MISC_REG_SPIO, - (ctrl_ext | BP10GB_MDIO_CLR | - BP10GB_MCLK_CLR) & - ~(BP10GB_MCLK_DIR | - BP10GB_MDIO_DIR | - BP10GB_MDIO_SET | - BP10GB_MCLK_SET)); - - } else if (!pbpctl_dev->bp_10g) - BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, - ((ctrl_ext | - BPCTLI_CTRL_EXT_MCLK_DIR | - BPCTLI_CTRL_EXT_MDIO_DIR) & - ~(BPCTLI_CTRL_EXT_MCLK_DATA - | - BPCTLI_CTRL_EXT_MDIO_DATA))); - else { - - BP10G_WRITE_REG(pbpctl_dev, EODSDP, - (ctrl_ext & - ~(BP10G_MCLK_DATA_OUT | - BP10G_MDIO_DATA_OUT))); - } - - usec_delay(PULSE_TIME); - } - - } -} - -static int read_pulse(bpctl_dev_t *pbpctl_dev, unsigned int ctrl_ext, - unsigned char len) -{ - unsigned char ctrl_val = 0; - unsigned int i = len; - unsigned int ctrl = 0; - bpctl_dev_t *pbpctl_dev_c = NULL; - - if (pbpctl_dev->bp_i80) - ctrl = BPCTL_READ_REG(pbpctl_dev, CTRL_EXT); - if (pbpctl_dev->bp_540) - ctrl = BP10G_READ_REG(pbpctl_dev, ESDP); - if (pbpctl_dev->bp_10g9) { - if (!(pbpctl_dev_c = get_status_port_fn(pbpctl_dev))) - return -1; - ctrl = BP10G_READ_REG(pbpctl_dev_c, ESDP); - } - - - while (i--) { - if (pbpctl_dev->bp_10g9) { - /*BP10G_WRITE_REG(pbpctl_dev, I2CCTL, ((ctrl_ext|BP10G_MDIO_DATA_OUT9)&~BP10G_MCLK_DATA_OUT9)); */ - /* DATA ? CLK 0 */ - BP10G_WRITE_REG(pbpctl_dev_c, ESDP, - ((ctrl | BP10G_MCLK_DIR_OUT9) & - ~(BP10G_MCLK_DATA_OUT9))); - - } else if (pbpctl_dev->bp_fiber5) { - BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL, ((ctrl_ext | - BPCTLI_CTRL_EXT_MCLK_DIR5) - & - ~ - (BPCTLI_CTRL_EXT_MDIO_DIR5 - | - BPCTLI_CTRL_EXT_MCLK_DATA5))); - - } else if (pbpctl_dev->bp_i80) { - BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL, - (ctrl_ext & - ~BPCTLI_CTRL_EXT_MDIO_DIR80)); - BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, - ((ctrl | BPCTLI_CTRL_EXT_MCLK_DIR80) - & ~(BPCTLI_CTRL_EXT_MCLK_DATA80))); - - } else if (pbpctl_dev->bp_540) { - BP10G_WRITE_REG(pbpctl_dev, ESDP, - ((ctrl | BP540_MCLK_DIR) & - ~(BP540_MDIO_DIR | BP540_MCLK_DATA))); - - } else if (pbpctl_dev->bp_10gb) { - - BP10GB_WRITE_REG(pbpctl_dev, MISC_REG_SPIO, - (ctrl_ext | BP10GB_MDIO_DIR | - BP10GB_MCLK_CLR) & ~(BP10GB_MCLK_DIR | - BP10GB_MDIO_CLR | - BP10GB_MDIO_SET | - BP10GB_MCLK_SET)); - - } else if (!pbpctl_dev->bp_10g) - BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, ((ctrl_ext | - BPCTLI_CTRL_EXT_MCLK_DIR) - & - ~ - (BPCTLI_CTRL_EXT_MDIO_DIR - | - BPCTLI_CTRL_EXT_MCLK_DATA))); - else { - - BP10G_WRITE_REG(pbpctl_dev, EODSDP, ((ctrl_ext | BP10G_MDIO_DATA_OUT) & ~BP10G_MCLK_DATA_OUT)); /* ? */ - /* printk("0x28=0x%x\n",BP10G_READ_REG(pbpctl_dev,EODSDP);); */ - - } - - usec_delay(PULSE_TIME); - if (pbpctl_dev->bp_10g9) { - /*BP10G_WRITE_REG(pbpctl_dev, I2CCTL, (ctrl_ext|BP10G_MCLK_DATA_OUT9|BP10G_MDIO_DATA_OUT9)); */ - /* DATA ? CLK 1 */ - BP10G_WRITE_REG(pbpctl_dev_c, ESDP, - (ctrl | BP10G_MCLK_DATA_OUT9 | - BP10G_MCLK_DIR_OUT9)); - - } else if (pbpctl_dev->bp_fiber5) { - BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL, ((ctrl_ext | - BPCTLI_CTRL_EXT_MCLK_DIR5 - | - BPCTLI_CTRL_EXT_MCLK_DATA5) - & - ~ - (BPCTLI_CTRL_EXT_MDIO_DIR5))); - - } else if (pbpctl_dev->bp_i80) { - BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL, - (ctrl_ext & - ~(BPCTLI_CTRL_EXT_MDIO_DIR80))); - BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, - (ctrl | BPCTLI_CTRL_EXT_MCLK_DIR80 | - BPCTLI_CTRL_EXT_MCLK_DATA80)); - - } else if (pbpctl_dev->bp_540) { - BP10G_WRITE_REG(pbpctl_dev, ESDP, - ((ctrl | BP540_MCLK_DIR | - BP540_MCLK_DATA) & - ~(BP540_MDIO_DIR))); - - } else if (pbpctl_dev->bp_10gb) { - BP10GB_WRITE_REG(pbpctl_dev, MISC_REG_SPIO, - (ctrl_ext | BP10GB_MDIO_DIR | - BP10GB_MCLK_SET) & ~(BP10GB_MCLK_DIR | - BP10GB_MDIO_CLR | - BP10GB_MDIO_SET | - BP10GB_MCLK_CLR)); - - } else if (!pbpctl_dev->bp_10g) - BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, ((ctrl_ext | - BPCTLI_CTRL_EXT_MCLK_DIR - | - BPCTLI_CTRL_EXT_MCLK_DATA) - & - ~ - (BPCTLI_CTRL_EXT_MDIO_DIR))); - else { - - BP10G_WRITE_REG(pbpctl_dev, EODSDP, - (ctrl_ext | BP10G_MCLK_DATA_OUT | - BP10G_MDIO_DATA_OUT)); - - } - if (pbpctl_dev->bp_10g9) { - ctrl_ext = BP10G_READ_REG(pbpctl_dev, I2CCTL); - - } else if ((pbpctl_dev->bp_fiber5) || (pbpctl_dev->bp_i80)) { - ctrl_ext = BPCTL_READ_REG(pbpctl_dev, CTRL); - } else if (pbpctl_dev->bp_540) { - ctrl_ext = BP10G_READ_REG(pbpctl_dev, ESDP); - } else if (pbpctl_dev->bp_10gb) - ctrl_ext = BP10GB_READ_REG(pbpctl_dev, MISC_REG_SPIO); - - else if (!pbpctl_dev->bp_10g) - ctrl_ext = BPCTL_READ_REG(pbpctl_dev, CTRL_EXT); - else - ctrl_ext = BP10G_READ_REG(pbpctl_dev, EODSDP); - - usec_delay(PULSE_TIME); - if (pbpctl_dev->bp_10g9) { - if (ctrl_ext & BP10G_MDIO_DATA_IN9) - ctrl_val |= 1 << i; - - } else if (pbpctl_dev->bp_fiber5) { - if (ctrl_ext & BPCTLI_CTRL_EXT_MDIO_DATA5) - ctrl_val |= 1 << i; - } else if (pbpctl_dev->bp_i80) { - if (ctrl_ext & BPCTLI_CTRL_EXT_MDIO_DATA80) - ctrl_val |= 1 << i; - } else if (pbpctl_dev->bp_540) { - if (ctrl_ext & BP540_MDIO_DATA) - ctrl_val |= 1 << i; - } else if (pbpctl_dev->bp_10gb) { - if (ctrl_ext & BP10GB_MDIO_DATA) - ctrl_val |= 1 << i; - - } else if (!pbpctl_dev->bp_10g) { - - if (ctrl_ext & BPCTLI_CTRL_EXT_MDIO_DATA) - ctrl_val |= 1 << i; - } else { - - if (ctrl_ext & BP10G_MDIO_DATA_IN) - ctrl_val |= 1 << i; - } - - } - - return ctrl_val; -} - -static void write_reg(bpctl_dev_t *pbpctl_dev, unsigned char value, - unsigned char addr) -{ - uint32_t ctrl_ext = 0, ctrl = 0; - bpctl_dev_t *pbpctl_dev_c = NULL; - unsigned long flags; - if (pbpctl_dev->bp_10g9) { - if (!(pbpctl_dev_c = get_status_port_fn(pbpctl_dev))) - return; - } - if ((pbpctl_dev->wdt_status == WDT_STATUS_EN) && - (pbpctl_dev->bp_ext_ver < PXG4BPFI_VER)) - wdt_time_left(pbpctl_dev); - -#ifdef BP_SYNC_FLAG - spin_lock_irqsave(&pbpctl_dev->bypass_wr_lock, flags); -#else - atomic_set(&pbpctl_dev->wdt_busy, 1); -#endif - if (pbpctl_dev->bp_10g9) { - - ctrl_ext = BP10G_READ_REG(pbpctl_dev, I2CCTL); - ctrl = BP10G_READ_REG(pbpctl_dev_c, ESDP); - /* DATA 0 CLK 0 */ - /* BP10G_WRITE_REG(pbpctl_dev, I2CCTL, (ctrl_ext&~(BP10G_MCLK_DATA_OUT9|BP10G_MDIO_DATA_OUT9))); */ - BP10G_WRITE_REG(pbpctl_dev, I2CCTL, - (ctrl_ext & ~BP10G_MDIO_DATA_OUT9)); - BP10G_WRITE_REG(pbpctl_dev_c, ESDP, - ((ctrl | BP10G_MCLK_DIR_OUT9) & - ~(BP10G_MCLK_DATA_OUT9))); - - } else if (pbpctl_dev->bp_fiber5) { - ctrl_ext = BPCTL_READ_REG(pbpctl_dev, CTRL); - BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL, ((ctrl_ext | - BPCTLI_CTRL_EXT_MCLK_DIR5 - | - BPCTLI_CTRL_EXT_MDIO_DIR5) - & - ~ - (BPCTLI_CTRL_EXT_MDIO_DATA5 - | - BPCTLI_CTRL_EXT_MCLK_DATA5))); - } else if (pbpctl_dev->bp_i80) { - ctrl_ext = BPCTL_READ_REG(pbpctl_dev, CTRL); - ctrl = BPCTL_READ_REG(pbpctl_dev, CTRL_EXT); - BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL, ((ctrl_ext | - BPCTLI_CTRL_EXT_MDIO_DIR80) - & - ~BPCTLI_CTRL_EXT_MDIO_DATA80)); - BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, - ((ctrl | BPCTLI_CTRL_EXT_MCLK_DIR80) & - ~BPCTLI_CTRL_EXT_MCLK_DATA80)); - - } else if (pbpctl_dev->bp_540) { - ctrl = ctrl_ext = BP10G_READ_REG(pbpctl_dev, ESDP); - BP10G_WRITE_REG(pbpctl_dev, ESDP, ((ctrl | - BP540_MDIO_DIR | - BP540_MCLK_DIR) & - ~(BP540_MDIO_DATA | - BP540_MCLK_DATA))); - - } else if (pbpctl_dev->bp_10gb) { - ctrl_ext = BP10GB_READ_REG(pbpctl_dev, MISC_REG_SPIO); - - BP10GB_WRITE_REG(pbpctl_dev, MISC_REG_SPIO, - (ctrl_ext | BP10GB_MDIO_CLR | BP10GB_MCLK_CLR) - & ~(BP10GB_MCLK_DIR | BP10GB_MDIO_DIR | - BP10GB_MDIO_SET | BP10GB_MCLK_SET)); - - } else if (!pbpctl_dev->bp_10g) { - - ctrl_ext = BPCTL_READ_REG(pbpctl_dev, CTRL_EXT); - BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, ((ctrl_ext | - BPCTLI_CTRL_EXT_MCLK_DIR - | - BPCTLI_CTRL_EXT_MDIO_DIR) - & - ~ - (BPCTLI_CTRL_EXT_MDIO_DATA - | - BPCTLI_CTRL_EXT_MCLK_DATA))); - } else { - ctrl = BP10G_READ_REG(pbpctl_dev, ESDP); - ctrl_ext = BP10G_READ_REG(pbpctl_dev, EODSDP); - BP10G_WRITE_REG(pbpctl_dev, EODSDP, - (ctrl_ext & - ~(BP10G_MCLK_DATA_OUT | BP10G_MDIO_DATA_OUT))); - } - usec_delay(CMND_INTERVAL); - - /*send sync cmd */ - write_pulse(pbpctl_dev, ctrl_ext, SYNC_CMD_VAL, SYNC_CMD_LEN); - /*send wr cmd */ - write_pulse(pbpctl_dev, ctrl_ext, WR_CMD_VAL, WR_CMD_LEN); - write_pulse(pbpctl_dev, ctrl_ext, addr, ADDR_CMD_LEN); - - /*write data */ - write_pulse(pbpctl_dev, ctrl_ext, value, WR_DATA_LEN); - if (pbpctl_dev->bp_10g9) { - /*BP10G_WRITE_REG(pbpctl_dev, I2CCTL, (ctrl_ext&~(BP10G_MCLK_DATA_OUT9|BP10G_MDIO_DATA_OUT9))); */ - /* DATA 0 CLK 0 */ - BP10G_WRITE_REG(pbpctl_dev, I2CCTL, - (ctrl_ext & ~BP10G_MDIO_DATA_OUT9)); - BP10G_WRITE_REG(pbpctl_dev_c, ESDP, - ((ctrl | BP10G_MCLK_DIR_OUT9) & - ~(BP10G_MCLK_DATA_OUT9))); - - } else if (pbpctl_dev->bp_fiber5) { - BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL, ((ctrl_ext | - BPCTLI_CTRL_EXT_MCLK_DIR5 - | - BPCTLI_CTRL_EXT_MDIO_DIR5) - & - ~ - (BPCTLI_CTRL_EXT_MDIO_DATA5 - | - BPCTLI_CTRL_EXT_MCLK_DATA5))); - } else if (pbpctl_dev->bp_i80) { - BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL, ((ctrl_ext | - BPCTLI_CTRL_EXT_MDIO_DIR80) - & - ~BPCTLI_CTRL_EXT_MDIO_DATA80)); - BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, - ((ctrl | BPCTLI_CTRL_EXT_MCLK_DIR80) & - ~BPCTLI_CTRL_EXT_MCLK_DATA80)); - } else if (pbpctl_dev->bp_540) { - BP10G_WRITE_REG(pbpctl_dev, ESDP, ((ctrl | - BP540_MDIO_DIR | - BP540_MCLK_DIR) & - ~(BP540_MDIO_DATA | - BP540_MCLK_DATA))); - } else if (pbpctl_dev->bp_10gb) { - BP10GB_WRITE_REG(pbpctl_dev, MISC_REG_SPIO, - (ctrl_ext | BP10GB_MDIO_CLR | BP10GB_MCLK_CLR) - & ~(BP10GB_MCLK_DIR | BP10GB_MDIO_DIR | - BP10GB_MDIO_SET | BP10GB_MCLK_SET)); - - } else if (!pbpctl_dev->bp_10g) - - BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, ((ctrl_ext | - BPCTLI_CTRL_EXT_MCLK_DIR - | - BPCTLI_CTRL_EXT_MDIO_DIR) - & - ~ - (BPCTLI_CTRL_EXT_MDIO_DATA - | - BPCTLI_CTRL_EXT_MCLK_DATA))); - else { - BP10G_WRITE_REG(pbpctl_dev, EODSDP, - (ctrl_ext & - ~(BP10G_MCLK_DATA_OUT | BP10G_MDIO_DATA_OUT))); - - } - - usec_delay(CMND_INTERVAL * 4); - - if ((pbpctl_dev->wdt_status == WDT_STATUS_EN) && - (pbpctl_dev->bp_ext_ver < PXG4BPFI_VER) && (addr == CMND_REG_ADDR)) - pbpctl_dev->bypass_wdt_on_time = jiffies; -#ifdef BP_SYNC_FLAG - spin_unlock_irqrestore(&pbpctl_dev->bypass_wr_lock, flags); -#else - atomic_set(&pbpctl_dev->wdt_busy, 0); -#endif - -} - -static void write_data(bpctl_dev_t *pbpctl_dev, unsigned char value) -{ - write_reg(pbpctl_dev, value, CMND_REG_ADDR); -} - -static int read_reg(bpctl_dev_t *pbpctl_dev, unsigned char addr) -{ - uint32_t ctrl_ext = 0, ctrl = 0, ctrl_value = 0; - bpctl_dev_t *pbpctl_dev_c = NULL; - -#ifdef BP_SYNC_FLAG - unsigned long flags; - spin_lock_irqsave(&pbpctl_dev->bypass_wr_lock, flags); -#else - atomic_set(&pbpctl_dev->wdt_busy, 1); -#endif - if (pbpctl_dev->bp_10g9) { - if (!(pbpctl_dev_c = get_status_port_fn(pbpctl_dev))) - return -1; - } - - if (pbpctl_dev->bp_10g9) { - ctrl_ext = BP10G_READ_REG(pbpctl_dev, I2CCTL); - ctrl = BP10G_READ_REG(pbpctl_dev_c, ESDP); - - /* BP10G_WRITE_REG(pbpctl_dev, I2CCTL, (ctrl_ext&~(BP10G_MCLK_DATA_OUT9|BP10G_MDIO_DATA_OUT9))); */ - /* DATA 0 CLK 0 */ - BP10G_WRITE_REG(pbpctl_dev, I2CCTL, - (ctrl_ext & ~BP10G_MDIO_DATA_OUT9)); - BP10G_WRITE_REG(pbpctl_dev_c, ESDP, - ((ctrl | BP10G_MCLK_DIR_OUT9) & - ~(BP10G_MCLK_DATA_OUT9))); - - } else if (pbpctl_dev->bp_fiber5) { - ctrl_ext = BPCTL_READ_REG(pbpctl_dev, CTRL); - - BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL, ((ctrl_ext | - BPCTLI_CTRL_EXT_MCLK_DIR5 - | - BPCTLI_CTRL_EXT_MDIO_DIR5) - & - ~ - (BPCTLI_CTRL_EXT_MDIO_DATA5 - | - BPCTLI_CTRL_EXT_MCLK_DATA5))); - } else if (pbpctl_dev->bp_i80) { - ctrl_ext = BPCTL_READ_REG(pbpctl_dev, CTRL); - ctrl = BPCTL_READ_REG(pbpctl_dev, CTRL_EXT); - - BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL, ((ctrl_ext | - BPCTLI_CTRL_EXT_MDIO_DIR80) - & - ~BPCTLI_CTRL_EXT_MDIO_DATA80)); - BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, - ((ctrl | BPCTLI_CTRL_EXT_MCLK_DIR80) & - ~BPCTLI_CTRL_EXT_MCLK_DATA80)); - } else if (pbpctl_dev->bp_540) { - ctrl_ext = BP10G_READ_REG(pbpctl_dev, ESDP); - ctrl = BP10G_READ_REG(pbpctl_dev, ESDP); - - BP10G_WRITE_REG(pbpctl_dev, ESDP, ((ctrl | BP540_MCLK_DIR | - BP540_MDIO_DIR) & - ~(BP540_MDIO_DATA | - BP540_MCLK_DATA))); - } else if (pbpctl_dev->bp_10gb) { - ctrl_ext = BP10GB_READ_REG(pbpctl_dev, MISC_REG_SPIO); - - BP10GB_WRITE_REG(pbpctl_dev, MISC_REG_SPIO, - (ctrl_ext | BP10GB_MDIO_CLR | BP10GB_MCLK_CLR) - & ~(BP10GB_MCLK_DIR | BP10GB_MDIO_DIR | - BP10GB_MDIO_SET | BP10GB_MCLK_SET)); -#if 0 - - /*BP10GB_WRITE_REG(pbpctl_dev, MISC_REG_SPIO, (ctrl_ext | BP10GB_MCLK_DIR | BP10GB_MDIO_DIR| - BP10GB_MCLK_CLR|BP10GB_MDIO_CLR)); - ctrl_ext = BP10GB_READ_REG(pbpctl_dev, MISC_REG_SPIO); - printk("1reg=%x\n", ctrl_ext); */ - - BP10GB_WRITE_REG(pbpctl_dev, MISC_REG_SPIO, ((ctrl_ext | - BP10GB_MCLK_SET | - BP10GB_MDIO_CLR)) - & ~(BP10GB_MCLK_CLR | BP10GB_MDIO_SET | - BP10GB_MCLK_DIR | BP10GB_MDIO_DIR)); - - /* bnx2x_set_spio(pbpctl_dev, 5, MISC_REGISTERS_SPIO_OUTPUT_LOW); - bnx2x_set_spio(pbpctl_dev, 4, MISC_REGISTERS_SPIO_OUTPUT_LOW); - bnx2x_set_spio(pbpctl_dev, 4, MISC_REGISTERS_SPIO_INPUT_HI_Z); */ - - ctrl_ext = BP10GB_READ_REG(pbpctl_dev, MISC_REG_SPIO); - - printk("2reg=%x\n", ctrl_ext); - -#ifdef BP_SYNC_FLAG - spin_unlock_irqrestore(&pbpctl_dev->bypass_wr_lock, flags); -#else - atomic_set(&pbpctl_dev->wdt_busy, 0); -#endif - - return 0; - -#endif - - } else if (!pbpctl_dev->bp_10g) { - - ctrl_ext = BPCTL_READ_REG(pbpctl_dev, CTRL_EXT); - - BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, ((ctrl_ext | - BPCTLI_CTRL_EXT_MCLK_DIR - | - BPCTLI_CTRL_EXT_MDIO_DIR) - & - ~ - (BPCTLI_CTRL_EXT_MDIO_DATA - | - BPCTLI_CTRL_EXT_MCLK_DATA))); - } else { - - ctrl = BP10G_READ_REG(pbpctl_dev, ESDP); - ctrl_ext = BP10G_READ_REG(pbpctl_dev, EODSDP); - BP10G_WRITE_REG(pbpctl_dev, EODSDP, - (ctrl_ext & - ~(BP10G_MCLK_DATA_OUT | BP10G_MDIO_DATA_OUT))); - - } - - usec_delay(CMND_INTERVAL); - - /*send sync cmd */ - write_pulse(pbpctl_dev, ctrl_ext, SYNC_CMD_VAL, SYNC_CMD_LEN); - /*send rd cmd */ - write_pulse(pbpctl_dev, ctrl_ext, RD_CMD_VAL, RD_CMD_LEN); - /*send addr */ - write_pulse(pbpctl_dev, ctrl_ext, addr, ADDR_CMD_LEN); - /*read data */ - /* zero */ - if (pbpctl_dev->bp_10g9) { - /* DATA 0 CLK 1 */ - /*BP10G_WRITE_REG(pbpctl_dev, I2CCTL, (ctrl_ext|BP10G_MCLK_DATA_OUT9|BP10G_MDIO_DATA_OUT9)); */ - BP10G_WRITE_REG(pbpctl_dev, I2CCTL, - (ctrl_ext | BP10G_MDIO_DATA_OUT9)); - BP10G_WRITE_REG(pbpctl_dev_c, ESDP, - (ctrl | BP10G_MCLK_DATA_OUT9 | - BP10G_MCLK_DIR_OUT9)); - - } else if (pbpctl_dev->bp_fiber5) { - BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL, ((ctrl_ext | - BPCTLI_CTRL_EXT_MCLK_DIR5 - | - BPCTLI_CTRL_EXT_MCLK_DATA5) - & - ~ - (BPCTLI_CTRL_EXT_MDIO_DIR5 - | - BPCTLI_CTRL_EXT_MDIO_DATA5))); - - } else if (pbpctl_dev->bp_i80) { - BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL, - (ctrl_ext & - ~(BPCTLI_CTRL_EXT_MDIO_DATA80 | - BPCTLI_CTRL_EXT_MDIO_DIR80))); - BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, - (ctrl | BPCTLI_CTRL_EXT_MCLK_DIR80 | - BPCTLI_CTRL_EXT_MCLK_DATA80)); - - } else if (pbpctl_dev->bp_540) { - BP10G_WRITE_REG(pbpctl_dev, ESDP, - (((ctrl | BP540_MDIO_DIR | BP540_MCLK_DIR | - BP540_MCLK_DATA) & ~BP540_MDIO_DATA))); - - } else if (pbpctl_dev->bp_10gb) { - - BP10GB_WRITE_REG(pbpctl_dev, MISC_REG_SPIO, - (ctrl_ext | BP10GB_MDIO_DIR | BP10GB_MCLK_SET) - & ~(BP10GB_MCLK_DIR | BP10GB_MDIO_SET | - BP10GB_MDIO_CLR | BP10GB_MCLK_CLR)); - - } else if (!pbpctl_dev->bp_10g) - BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, ((ctrl_ext | - BPCTLI_CTRL_EXT_MCLK_DIR - | - BPCTLI_CTRL_EXT_MCLK_DATA) - & - ~ - (BPCTLI_CTRL_EXT_MDIO_DIR - | - BPCTLI_CTRL_EXT_MDIO_DATA))); - else { - - BP10G_WRITE_REG(pbpctl_dev, EODSDP, - (ctrl_ext | BP10G_MCLK_DATA_OUT | - BP10G_MDIO_DATA_OUT)); - - - } - usec_delay(PULSE_TIME); - - ctrl_value = read_pulse(pbpctl_dev, ctrl_ext, RD_DATA_LEN); - - if (pbpctl_dev->bp_10g9) { - ctrl_ext = BP10G_READ_REG(pbpctl_dev, I2CCTL); - ctrl = BP10G_READ_REG(pbpctl_dev_c, ESDP); - - /* BP10G_WRITE_REG(pbpctl_dev, I2CCTL, (ctrl_ext&~(BP10G_MCLK_DATA_OUT9|BP10G_MDIO_DATA_OUT9))); */ - /* DATA 0 CLK 0 */ - BP10G_WRITE_REG(pbpctl_dev, I2CCTL, - (ctrl_ext & ~BP10G_MDIO_DATA_OUT9)); - BP10G_WRITE_REG(pbpctl_dev_c, ESDP, - ((ctrl | BP10G_MCLK_DIR_OUT9) & - ~(BP10G_MCLK_DATA_OUT9))); - - } else if (pbpctl_dev->bp_fiber5) { - BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL, ((ctrl_ext | - BPCTLI_CTRL_EXT_MCLK_DIR5 - | - BPCTLI_CTRL_EXT_MDIO_DIR5) - & - ~ - (BPCTLI_CTRL_EXT_MDIO_DATA5 - | - BPCTLI_CTRL_EXT_MCLK_DATA5))); - } else if (pbpctl_dev->bp_i80) { - BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL, ((ctrl_ext | - BPCTLI_CTRL_EXT_MDIO_DIR80) - & - ~BPCTLI_CTRL_EXT_MDIO_DATA80)); - BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, - ((ctrl | BPCTLI_CTRL_EXT_MCLK_DIR80) & - ~BPCTLI_CTRL_EXT_MCLK_DATA80)); - - } else if (pbpctl_dev->bp_540) { - ctrl = BP10G_READ_REG(pbpctl_dev, ESDP); - BP10G_WRITE_REG(pbpctl_dev, ESDP, ((ctrl | BP540_MCLK_DIR | - BP540_MDIO_DIR) & - ~(BP540_MDIO_DATA | - BP540_MCLK_DATA))); - - } else if (pbpctl_dev->bp_10gb) { - ctrl_ext = BP10GB_READ_REG(pbpctl_dev, MISC_REG_SPIO); - BP10GB_WRITE_REG(pbpctl_dev, MISC_REG_SPIO, - (ctrl_ext | BP10GB_MDIO_CLR | BP10GB_MCLK_CLR) - & ~(BP10GB_MCLK_DIR | BP10GB_MDIO_DIR | - BP10GB_MDIO_SET | BP10GB_MCLK_SET)); - - } else if (!pbpctl_dev->bp_10g) { - BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, ((ctrl_ext | - BPCTLI_CTRL_EXT_MCLK_DIR - | - BPCTLI_CTRL_EXT_MDIO_DIR) - & - ~ - (BPCTLI_CTRL_EXT_MDIO_DATA - | - BPCTLI_CTRL_EXT_MCLK_DATA))); - } else { - - ctrl = BP10G_READ_REG(pbpctl_dev, ESDP); - ctrl_ext = BP10G_READ_REG(pbpctl_dev, EODSDP); - BP10G_WRITE_REG(pbpctl_dev, EODSDP, - (ctrl_ext & - ~(BP10G_MCLK_DATA_OUT | BP10G_MDIO_DATA_OUT))); - - } - - usec_delay(CMND_INTERVAL * 4); -#ifdef BP_SYNC_FLAG - spin_unlock_irqrestore(&pbpctl_dev->bypass_wr_lock, flags); -#else - atomic_set(&pbpctl_dev->wdt_busy, 0); -#endif - - return ctrl_value; -} - -static int wdt_pulse(bpctl_dev_t *pbpctl_dev) -{ - uint32_t ctrl_ext = 0, ctrl = 0; - bpctl_dev_t *pbpctl_dev_c = NULL; - -#ifdef BP_SYNC_FLAG - unsigned long flags; - - spin_lock_irqsave(&pbpctl_dev->bypass_wr_lock, flags); -#else - - if ((atomic_read(&pbpctl_dev->wdt_busy)) == 1) - return -1; -#endif - if (pbpctl_dev->bp_10g9) { - if (!(pbpctl_dev_c = get_status_port_fn(pbpctl_dev))) - return -1; - } - - if (pbpctl_dev->bp_10g9) { - ctrl_ext = BP10G_READ_REG(pbpctl_dev, I2CCTL); - ctrl = BP10G_READ_REG(pbpctl_dev_c, ESDP); - - /* BP10G_WRITE_REG(pbpctl_dev, I2CCTL, (ctrl_ext&~(BP10G_MCLK_DATA_OUT9|BP10G_MDIO_DATA_OUT9))); */ - /* DATA 0 CLK 0 */ - BP10G_WRITE_REG(pbpctl_dev, I2CCTL, - (ctrl_ext & ~BP10G_MDIO_DATA_OUT9)); - BP10G_WRITE_REG(pbpctl_dev_c, ESDP, - ((ctrl | BP10G_MCLK_DIR_OUT9) & - ~(BP10G_MCLK_DATA_OUT9))); - - } else if (pbpctl_dev->bp_fiber5) { - ctrl_ext = BPCTL_READ_REG(pbpctl_dev, CTRL); - BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL, ((ctrl_ext | - BPCTLI_CTRL_EXT_MCLK_DIR5 - | - BPCTLI_CTRL_EXT_MDIO_DIR5) - & - ~ - (BPCTLI_CTRL_EXT_MDIO_DATA5 - | - BPCTLI_CTRL_EXT_MCLK_DATA5))); - } else if (pbpctl_dev->bp_i80) { - ctrl_ext = BPCTL_READ_REG(pbpctl_dev, CTRL); - ctrl = BPCTL_READ_REG(pbpctl_dev, CTRL_EXT); - BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL, ((ctrl_ext | - BPCTLI_CTRL_EXT_MDIO_DIR80) - & - ~BPCTLI_CTRL_EXT_MDIO_DATA80)); - BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, - ((ctrl | BPCTLI_CTRL_EXT_MCLK_DIR80) & - ~BPCTLI_CTRL_EXT_MCLK_DATA80)); - } else if (pbpctl_dev->bp_540) { - ctrl_ext = ctrl = BP10G_READ_REG(pbpctl_dev, ESDP); - BP10G_WRITE_REG(pbpctl_dev, ESDP, ((ctrl | BP540_MCLK_DIR | - BP540_MDIO_DIR) & - ~(BP540_MDIO_DATA | - BP540_MCLK_DATA))); - } else if (pbpctl_dev->bp_10gb) { - ctrl_ext = BP10GB_READ_REG(pbpctl_dev, MISC_REG_SPIO); - BP10GB_WRITE_REG(pbpctl_dev, MISC_REG_SPIO, - (ctrl_ext | BP10GB_MDIO_CLR | BP10GB_MCLK_CLR) - & ~(BP10GB_MCLK_DIR | BP10GB_MDIO_DIR | - BP10GB_MDIO_SET | BP10GB_MCLK_SET)); - - } else if (!pbpctl_dev->bp_10g) { - - ctrl_ext = BPCTL_READ_REG(pbpctl_dev, CTRL_EXT); - BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, ((ctrl_ext | - BPCTLI_CTRL_EXT_MCLK_DIR - | - BPCTLI_CTRL_EXT_MDIO_DIR) - & - ~ - (BPCTLI_CTRL_EXT_MDIO_DATA - | - BPCTLI_CTRL_EXT_MCLK_DATA))); - } else { - - ctrl = BP10G_READ_REG(pbpctl_dev, ESDP); - ctrl_ext = BP10G_READ_REG(pbpctl_dev, EODSDP); - BP10G_WRITE_REG(pbpctl_dev, EODSDP, - (ctrl_ext & - ~(BP10G_MCLK_DATA_OUT | BP10G_MDIO_DATA_OUT))); - - } - if (pbpctl_dev->bp_10g9) { - /* BP10G_WRITE_REG(pbpctl_dev, I2CCTL, ((ctrl_ext|BP10G_MCLK_DATA_OUT9)&~BP10G_MDIO_DATA_OUT9)); */ - /* DATA 0 CLK 1 */ - BP10G_WRITE_REG(pbpctl_dev, I2CCTL, - (ctrl_ext & ~BP10G_MDIO_DATA_OUT9)); - BP10G_WRITE_REG(pbpctl_dev_c, ESDP, - (ctrl | BP10G_MCLK_DATA_OUT9 | - BP10G_MCLK_DIR_OUT9)); - - } else if (pbpctl_dev->bp_fiber5) { - BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL, ((ctrl_ext | - BPCTLI_CTRL_EXT_MCLK_DIR5 - | - BPCTLI_CTRL_EXT_MDIO_DIR5 - | - BPCTLI_CTRL_EXT_MCLK_DATA5) - & - ~ - (BPCTLI_CTRL_EXT_MDIO_DATA5))); - } else if (pbpctl_dev->bp_i80) { - BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL, ((ctrl_ext | - BPCTLI_CTRL_EXT_MDIO_DIR80) - & - ~BPCTLI_CTRL_EXT_MDIO_DATA80)); - BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, - (ctrl | BPCTLI_CTRL_EXT_MCLK_DIR80 | - BPCTLI_CTRL_EXT_MCLK_DATA80)); - - } else if (pbpctl_dev->bp_540) { - BP10G_WRITE_REG(pbpctl_dev, ESDP, ((ctrl | - BP540_MDIO_DIR | - BP540_MCLK_DIR | - BP540_MCLK_DATA) & - ~BP540_MDIO_DATA)); - - } else if (pbpctl_dev->bp_10gb) { - ctrl_ext = BP10GB_READ_REG(pbpctl_dev, MISC_REG_SPIO); - - BP10GB_WRITE_REG(pbpctl_dev, MISC_REG_SPIO, - (ctrl_ext | BP10GB_MDIO_CLR | BP10GB_MCLK_SET) - & ~(BP10GB_MCLK_DIR | BP10GB_MDIO_DIR | - BP10GB_MDIO_SET | BP10GB_MCLK_CLR)); - - } else if (!pbpctl_dev->bp_10g) - BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, ((ctrl_ext | - BPCTLI_CTRL_EXT_MCLK_DIR - | - BPCTLI_CTRL_EXT_MDIO_DIR - | - BPCTLI_CTRL_EXT_MCLK_DATA) - & - ~ - (BPCTLI_CTRL_EXT_MDIO_DATA))); - else { - - BP10G_WRITE_REG(pbpctl_dev, EODSDP, - ((ctrl_ext | BP10G_MCLK_DATA_OUT) & - ~BP10G_MDIO_DATA_OUT)); - - } - - usec_delay(WDT_INTERVAL); - if (pbpctl_dev->bp_10g9) { - /* BP10G_WRITE_REG(pbpctl_dev, I2CCTL, (ctrl_ext&~(BP10G_MCLK_DATA_OUT9|BP10G_MDIO_DATA_OUT9))); */ - /* DATA 0 CLK 0 */ - BP10G_WRITE_REG(pbpctl_dev, I2CCTL, - (ctrl_ext & ~BP10G_MDIO_DATA_OUT9)); - BP10G_WRITE_REG(pbpctl_dev_c, ESDP, - ((ctrl | BP10G_MCLK_DIR_OUT9) & - ~(BP10G_MCLK_DATA_OUT9))); - - } else if (pbpctl_dev->bp_fiber5) { - BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL, ((ctrl_ext | - BPCTLI_CTRL_EXT_MCLK_DIR5 - | - BPCTLI_CTRL_EXT_MDIO_DIR5) - & - ~ - (BPCTLI_CTRL_EXT_MCLK_DATA5 - | - BPCTLI_CTRL_EXT_MDIO_DATA5))); - } else if (pbpctl_dev->bp_i80) { - BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL, ((ctrl_ext | - BPCTLI_CTRL_EXT_MDIO_DIR80) - & - ~BPCTLI_CTRL_EXT_MDIO_DATA80)); - BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, - ((ctrl | BPCTLI_CTRL_EXT_MCLK_DIR80) & - ~BPCTLI_CTRL_EXT_MCLK_DATA80)); - - } else if (pbpctl_dev->bp_540) { - BP10G_WRITE_REG(pbpctl_dev, ESDP, ((ctrl | BP540_MCLK_DIR | - BP540_MDIO_DIR) & - ~(BP540_MDIO_DATA | - BP540_MCLK_DATA))); - - } else if (pbpctl_dev->bp_10gb) { - ctrl_ext = BP10GB_READ_REG(pbpctl_dev, MISC_REG_SPIO); - BP10GB_WRITE_REG(pbpctl_dev, MISC_REG_SPIO, - (ctrl_ext | BP10GB_MDIO_CLR | BP10GB_MCLK_CLR) - & ~(BP10GB_MCLK_DIR | BP10GB_MDIO_DIR | - BP10GB_MDIO_SET | BP10GB_MCLK_SET)); - - } else if (!pbpctl_dev->bp_10g) - BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, ((ctrl_ext | - BPCTLI_CTRL_EXT_MCLK_DIR - | - BPCTLI_CTRL_EXT_MDIO_DIR) - & - ~ - (BPCTLI_CTRL_EXT_MCLK_DATA - | - BPCTLI_CTRL_EXT_MDIO_DATA))); - else { - - BP10G_WRITE_REG(pbpctl_dev, EODSDP, - (ctrl_ext & - ~(BP10G_MCLK_DATA_OUT | BP10G_MDIO_DATA_OUT))); - } - if ((pbpctl_dev->wdt_status == WDT_STATUS_EN) /*&& - (pbpctl_dev->bp_ext_verbypass_wdt_on_time = jiffies; -#ifdef BP_SYNC_FLAG - spin_unlock_irqrestore(&pbpctl_dev->bypass_wr_lock, flags); -#endif - usec_delay(CMND_INTERVAL * 4); - return 0; -} - -static void data_pulse(bpctl_dev_t *pbpctl_dev, unsigned char value) -{ - - uint32_t ctrl_ext = 0; -#ifdef BP_SYNC_FLAG - unsigned long flags; -#endif - wdt_time_left(pbpctl_dev); -#ifdef BP_SYNC_FLAG - spin_lock_irqsave(&pbpctl_dev->bypass_wr_lock, flags); -#else - atomic_set(&pbpctl_dev->wdt_busy, 1); -#endif - - ctrl_ext = BPCTL_READ_REG(pbpctl_dev, CTRL_EXT); - BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, ((ctrl_ext | - BPCTLI_CTRL_EXT_SDP6_DIR | - BPCTLI_CTRL_EXT_SDP7_DIR) & - ~(BPCTLI_CTRL_EXT_SDP6_DATA | - BPCTLI_CTRL_EXT_SDP7_DATA))); - - usec_delay(INIT_CMND_INTERVAL); - BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, ((ctrl_ext | - BPCTLI_CTRL_EXT_SDP6_DIR | - BPCTLI_CTRL_EXT_SDP7_DIR | - BPCTLI_CTRL_EXT_SDP6_DATA) & - ~ - (BPCTLI_CTRL_EXT_SDP7_DATA))); - usec_delay(INIT_CMND_INTERVAL); - - while (value) { - BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, ctrl_ext | - BPCTLI_CTRL_EXT_SDP6_DIR | - BPCTLI_CTRL_EXT_SDP7_DIR | - BPCTLI_CTRL_EXT_SDP6_DATA | - BPCTLI_CTRL_EXT_SDP7_DATA); - usec_delay(PULSE_INTERVAL); - BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, ((ctrl_ext | - BPCTLI_CTRL_EXT_SDP6_DIR - | - BPCTLI_CTRL_EXT_SDP7_DIR - | - BPCTLI_CTRL_EXT_SDP6_DATA) - & - ~BPCTLI_CTRL_EXT_SDP7_DATA)); - usec_delay(PULSE_INTERVAL); - value--; - - } - usec_delay(INIT_CMND_INTERVAL - PULSE_INTERVAL); - BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, ((ctrl_ext | - BPCTLI_CTRL_EXT_SDP6_DIR | - BPCTLI_CTRL_EXT_SDP7_DIR) & - ~(BPCTLI_CTRL_EXT_SDP6_DATA | - BPCTLI_CTRL_EXT_SDP7_DATA))); - usec_delay(WDT_TIME_CNT); - if (pbpctl_dev->wdt_status == WDT_STATUS_EN) - pbpctl_dev->bypass_wdt_on_time = jiffies; -#ifdef BP_SYNC_FLAG - spin_unlock_irqrestore(&pbpctl_dev->bypass_wr_lock, flags); -#else - atomic_set(&pbpctl_dev->wdt_busy, 0); -#endif - -} - -static int send_wdt_pulse(bpctl_dev_t *pbpctl_dev) -{ - uint32_t ctrl_ext = 0; - -#ifdef BP_SYNC_FLAG - unsigned long flags; - - spin_lock_irqsave(&pbpctl_dev->bypass_wr_lock, flags); -#else - - if ((atomic_read(&pbpctl_dev->wdt_busy)) == 1) - return -1; -#endif - wdt_time_left(pbpctl_dev); - ctrl_ext = BPCTL_READ_REG(pbpctl_dev, CTRL_EXT); - - BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, ctrl_ext | /* 1 */ - BPCTLI_CTRL_EXT_SDP7_DIR | - BPCTLI_CTRL_EXT_SDP7_DATA); - usec_delay(PULSE_INTERVAL); - BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, ((ctrl_ext | /* 0 */ - BPCTLI_CTRL_EXT_SDP7_DIR) & - ~BPCTLI_CTRL_EXT_SDP7_DATA)); - - usec_delay(PULSE_INTERVAL); - if (pbpctl_dev->wdt_status == WDT_STATUS_EN) - pbpctl_dev->bypass_wdt_on_time = jiffies; -#ifdef BP_SYNC_FLAG - spin_unlock_irqrestore(&pbpctl_dev->bypass_wr_lock, flags); -#endif - - return 0; -} - -void send_bypass_clear_pulse(bpctl_dev_t *pbpctl_dev, unsigned int value) -{ - uint32_t ctrl_ext = 0; - - ctrl_ext = BPCTL_READ_REG(pbpctl_dev, CTRL_EXT); - BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, ((ctrl_ext | /* 0 */ - BPCTLI_CTRL_EXT_SDP6_DIR) & - ~BPCTLI_CTRL_EXT_SDP6_DATA)); - - usec_delay(PULSE_INTERVAL); - while (value) { - BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, ctrl_ext | /* 1 */ - BPCTLI_CTRL_EXT_SDP6_DIR | - BPCTLI_CTRL_EXT_SDP6_DATA); - usec_delay(PULSE_INTERVAL); - value--; - } - BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, ((ctrl_ext | /* 0 */ - BPCTLI_CTRL_EXT_SDP6_DIR) & - ~BPCTLI_CTRL_EXT_SDP6_DATA)); - usec_delay(PULSE_INTERVAL); -} - -/* #endif OLD_FW */ -#ifdef BYPASS_DEBUG - -int pulse_set_fn(bpctl_dev_t *pbpctl_dev, unsigned int counter) -{ - uint32_t ctrl_ext = 0; - - if (!pbpctl_dev) - return -1; - - ctrl_ext = BPCTL_READ_REG(pbpctl_dev, CTRL_EXT); - write_pulse_1(pbpctl_dev, ctrl_ext, counter, counter); - - pbpctl_dev->bypass_wdt_status = 0; - if (pbpctl_dev->bp_ext_ver >= PXG2BPI_VER) { - write_pulse_1(pbpctl_dev, ctrl_ext, counter, counter); - } else { - wdt_time_left(pbpctl_dev); - if (pbpctl_dev->wdt_status == WDT_STATUS_EN) { - pbpctl_dev->wdt_status = 0; - data_pulse(pbpctl_dev, counter); - pbpctl_dev->wdt_status = WDT_STATUS_EN; - pbpctl_dev->bypass_wdt_on_time = jiffies; - - } else - data_pulse(pbpctl_dev, counter); - } - - return 0; -} - -int zero_set_fn(bpctl_dev_t *pbpctl_dev) -{ - uint32_t ctrl_ext = 0, ctrl_value = 0; - if (!pbpctl_dev) - return -1; - - if (pbpctl_dev->bp_ext_ver >= PXG2BPI_VER) { - printk("zero_set"); - - ctrl_ext = BPCTL_READ_REG(pbpctl_dev, CTRL_EXT); - - BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, ((ctrl_ext | - BPCTLI_CTRL_EXT_MCLK_DIR) - & - ~ - (BPCTLI_CTRL_EXT_MCLK_DATA - | - BPCTLI_CTRL_EXT_MDIO_DIR - | - BPCTLI_CTRL_EXT_MDIO_DATA))); - - } - return ctrl_value; -} - -int pulse_get2_fn(bpctl_dev_t *pbpctl_dev) -{ - uint32_t ctrl_ext = 0, ctrl_value = 0; - if (!pbpctl_dev) - return -1; - - if (pbpctl_dev->bp_ext_ver >= PXG2BPI_VER) { - printk("pulse_get_fn\n"); - ctrl_ext = BPCTL_READ_REG(pbpctl_dev, CTRL_EXT); - ctrl_value = read_pulse_2(pbpctl_dev, ctrl_ext); - printk("read:%d\n", ctrl_value); - } - return ctrl_value; -} - -int pulse_get1_fn(bpctl_dev_t *pbpctl_dev) -{ - uint32_t ctrl_ext = 0, ctrl_value = 0; - if (!pbpctl_dev) - return -1; - - if (pbpctl_dev->bp_ext_ver >= PXG2BPI_VER) { - - printk("pulse_get_fn\n"); - - ctrl_ext = BPCTL_READ_REG(pbpctl_dev, CTRL_EXT); - ctrl_value = read_pulse_1(pbpctl_dev, ctrl_ext); - printk("read:%d\n", ctrl_value); - } - return ctrl_value; -} - -int gpio6_set_fn(bpctl_dev_t *pbpctl_dev) -{ - uint32_t ctrl_ext = 0; - - ctrl_ext = BPCTL_READ_REG(pbpctl_dev, CTRL_EXT); - BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, ctrl_ext | - BPCTLI_CTRL_EXT_SDP6_DIR | - BPCTLI_CTRL_EXT_SDP6_DATA); - return 0; -} - -int gpio7_set_fn(bpctl_dev_t *pbpctl_dev) -{ - uint32_t ctrl_ext = 0; - - ctrl_ext = BPCTL_READ_REG(pbpctl_dev, CTRL_EXT); - BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, ctrl_ext | - BPCTLI_CTRL_EXT_SDP7_DIR | - BPCTLI_CTRL_EXT_SDP7_DATA); - return 0; -} - -int gpio7_clear_fn(bpctl_dev_t *pbpctl_dev) -{ - uint32_t ctrl_ext = 0; - - ctrl_ext = BPCTL_READ_REG(pbpctl_dev, CTRL_EXT); - BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, ((ctrl_ext | - BPCTLI_CTRL_EXT_SDP7_DIR) & - ~BPCTLI_CTRL_EXT_SDP7_DATA)); - return 0; -} - -int gpio6_clear_fn(bpctl_dev_t *pbpctl_dev) -{ - uint32_t ctrl_ext = 0; - - ctrl_ext = BPCTL_READ_REG(pbpctl_dev, CTRL_EXT); - BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, ((ctrl_ext | - BPCTLI_CTRL_EXT_SDP6_DIR) & - ~BPCTLI_CTRL_EXT_SDP6_DATA)); - return 0; -} -#endif /*BYPASS_DEBUG */ - -static bpctl_dev_t *get_status_port_fn(bpctl_dev_t *pbpctl_dev) -{ - int idx_dev = 0; - - if (pbpctl_dev == NULL) - return NULL; - - if ((pbpctl_dev->func == 0) || (pbpctl_dev->func == 2)) { - for (idx_dev = 0; - ((bpctl_dev_arr[idx_dev].pdev != NULL) - && (idx_dev < device_num)); idx_dev++) { - if ((bpctl_dev_arr[idx_dev].bus == pbpctl_dev->bus) - && (bpctl_dev_arr[idx_dev].slot == pbpctl_dev->slot) - && ((bpctl_dev_arr[idx_dev].func == 1) - && (pbpctl_dev->func == 0))) { - - return &(bpctl_dev_arr[idx_dev]); - } - if ((bpctl_dev_arr[idx_dev].bus == pbpctl_dev->bus) && - (bpctl_dev_arr[idx_dev].slot == pbpctl_dev->slot) && - ((bpctl_dev_arr[idx_dev].func == 3) - && (pbpctl_dev->func == 2))) { - - return &(bpctl_dev_arr[idx_dev]); - } - } - } - return NULL; -} - -static bpctl_dev_t *get_master_port_fn(bpctl_dev_t *pbpctl_dev) -{ - int idx_dev = 0; - - if (pbpctl_dev == NULL) - return NULL; - - if ((pbpctl_dev->func == 1) || (pbpctl_dev->func == 3)) { - for (idx_dev = 0; - ((bpctl_dev_arr[idx_dev].pdev != NULL) - && (idx_dev < device_num)); idx_dev++) { - if ((bpctl_dev_arr[idx_dev].bus == pbpctl_dev->bus) - && (bpctl_dev_arr[idx_dev].slot == pbpctl_dev->slot) - && ((bpctl_dev_arr[idx_dev].func == 0) - && (pbpctl_dev->func == 1))) { - - return &(bpctl_dev_arr[idx_dev]); - } - if ((bpctl_dev_arr[idx_dev].bus == pbpctl_dev->bus) && - (bpctl_dev_arr[idx_dev].slot == pbpctl_dev->slot) && - ((bpctl_dev_arr[idx_dev].func == 2) - && (pbpctl_dev->func == 3))) { - - return &(bpctl_dev_arr[idx_dev]); - } - } - } - return NULL; -} - -/**************************************/ -/**************INTEL API***************/ -/**************************************/ - -static void write_data_port_int(bpctl_dev_t *pbpctl_dev, - unsigned char ctrl_value) -{ - uint32_t value; - - value = BPCTL_READ_REG(pbpctl_dev, CTRL); -/* Make SDP0 Pin Directonality to Output */ - value |= BPCTLI_CTRL_SDP0_DIR; - BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL, value); - - value &= ~BPCTLI_CTRL_SDP0_DATA; - value |= ((ctrl_value & 0x1) << BPCTLI_CTRL_SDP0_SHIFT); - BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL, value); - - value = (BPCTL_READ_REG(pbpctl_dev, CTRL_EXT)); -/* Make SDP2 Pin Directonality to Output */ - value |= BPCTLI_CTRL_EXT_SDP6_DIR; - BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, value); - - value &= ~BPCTLI_CTRL_EXT_SDP6_DATA; - value |= (((ctrl_value & 0x2) >> 1) << BPCTLI_CTRL_EXT_SDP6_SHIFT); - BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, value); - -} - -static int write_data_int(bpctl_dev_t *pbpctl_dev, unsigned char value) -{ - bpctl_dev_t *pbpctl_dev_b = NULL; - - if (!(pbpctl_dev_b = get_status_port_fn(pbpctl_dev))) - return -1; - atomic_set(&pbpctl_dev->wdt_busy, 1); - write_data_port_int(pbpctl_dev, value & 0x3); - write_data_port_int(pbpctl_dev_b, ((value & 0xc) >> 2)); - atomic_set(&pbpctl_dev->wdt_busy, 0); - - return 0; -} - -static int wdt_pulse_int(bpctl_dev_t *pbpctl_dev) -{ - - if ((atomic_read(&pbpctl_dev->wdt_busy)) == 1) - return -1; - - if ((write_data_int(pbpctl_dev, RESET_WDT_INT)) < 0) - return -1; - msec_delay_bp(CMND_INTERVAL_INT); - if ((write_data_int(pbpctl_dev, CMND_OFF_INT)) < 0) - return -1; - msec_delay_bp(CMND_INTERVAL_INT); - - if (pbpctl_dev->wdt_status == WDT_STATUS_EN) - pbpctl_dev->bypass_wdt_on_time = jiffies; - - return 0; -} - -/*************************************/ -/************* COMMANDS **************/ -/*************************************/ - -/* CMND_ON 0x4 (100)*/ -int cmnd_on(bpctl_dev_t *pbpctl_dev) -{ - int ret = BP_NOT_CAP; - - if (pbpctl_dev->bp_caps & SW_CTL_CAP) { - if (INTEL_IF_SERIES(pbpctl_dev->subdevice)) - return 0; - if (pbpctl_dev->bp_ext_ver >= PXG2BPI_VER) - write_data(pbpctl_dev, CMND_ON); - else - data_pulse(pbpctl_dev, CMND_ON); - ret = 0; - } - return ret; -} - -/* CMND_OFF 0x2 (10)*/ -int cmnd_off(bpctl_dev_t *pbpctl_dev) -{ - int ret = BP_NOT_CAP; - - if (pbpctl_dev->bp_caps & SW_CTL_CAP) { - if (INTEL_IF_SERIES(pbpctl_dev->subdevice)) { - write_data_int(pbpctl_dev, CMND_OFF_INT); - msec_delay_bp(CMND_INTERVAL_INT); - } else if (pbpctl_dev->bp_ext_ver >= PXG2BPI_VER) - write_data(pbpctl_dev, CMND_OFF); - else - data_pulse(pbpctl_dev, CMND_OFF); - ret = 0; - }; - return ret; -} - -/* BYPASS_ON (0xa)*/ -int bypass_on(bpctl_dev_t *pbpctl_dev) -{ - int ret = BP_NOT_CAP; - - if (pbpctl_dev->bp_caps & BP_CAP) { - if (INTEL_IF_SERIES(pbpctl_dev->subdevice)) { - write_data_int(pbpctl_dev, BYPASS_ON_INT); - msec_delay_bp(BYPASS_DELAY_INT); - pbpctl_dev->bp_status_un = 0; - } else if (pbpctl_dev->bp_ext_ver >= PXG2BPI_VER) { - write_data(pbpctl_dev, BYPASS_ON); - if (pbpctl_dev->bp_ext_ver >= PXG2TBPI_VER) - msec_delay_bp(LATCH_DELAY); - } else - data_pulse(pbpctl_dev, BYPASS_ON); - ret = 0; - }; - return ret; -} - -/* BYPASS_OFF (0x8 111)*/ -int bypass_off(bpctl_dev_t *pbpctl_dev) -{ - int ret = BP_NOT_CAP; - - if (pbpctl_dev->bp_caps & BP_CAP) { - if (INTEL_IF_SERIES(pbpctl_dev->subdevice)) { - write_data_int(pbpctl_dev, DIS_BYPASS_CAP_INT); - msec_delay_bp(BYPASS_DELAY_INT); - write_data_int(pbpctl_dev, PWROFF_BYPASS_ON_INT); - msec_delay_bp(BYPASS_DELAY_INT); - pbpctl_dev->bp_status_un = 0; - } else if (pbpctl_dev->bp_ext_ver >= PXG2BPI_VER) { - write_data(pbpctl_dev, BYPASS_OFF); - if (pbpctl_dev->bp_ext_ver >= PXG2TBPI_VER) - msec_delay_bp(LATCH_DELAY); - } else - data_pulse(pbpctl_dev, BYPASS_OFF); - ret = 0; - } - return ret; -} - -/* TAP_OFF (0x9)*/ -int tap_off(bpctl_dev_t *pbpctl_dev) -{ - int ret = BP_NOT_CAP; - if ((pbpctl_dev->bp_caps & TAP_CAP) - && (pbpctl_dev->bp_ext_ver >= PXG2TBPI_VER)) { - write_data(pbpctl_dev, TAP_OFF); - msec_delay_bp(LATCH_DELAY); - ret = 0; - }; - return ret; -} - -/* TAP_ON (0xb)*/ -int tap_on(bpctl_dev_t *pbpctl_dev) -{ - int ret = BP_NOT_CAP; - if ((pbpctl_dev->bp_caps & TAP_CAP) - && (pbpctl_dev->bp_ext_ver >= PXG2TBPI_VER)) { - write_data(pbpctl_dev, TAP_ON); - msec_delay_bp(LATCH_DELAY); - ret = 0; - }; - return ret; -} - -/* DISC_OFF (0x9)*/ -int disc_off(bpctl_dev_t *pbpctl_dev) -{ - int ret = 0; - if ((pbpctl_dev->bp_caps & DISC_CAP) && (pbpctl_dev->bp_ext_ver >= 0x8)) { - write_data(pbpctl_dev, DISC_OFF); - msec_delay_bp(LATCH_DELAY); - } else - ret = BP_NOT_CAP; - return ret; -} - -/* DISC_ON (0xb)*/ -int disc_on(bpctl_dev_t *pbpctl_dev) -{ - int ret = 0; - if ((pbpctl_dev->bp_caps & DISC_CAP) && (pbpctl_dev->bp_ext_ver >= 0x8)) { - write_data(pbpctl_dev, /*DISC_ON */ 0x85); - msec_delay_bp(LATCH_DELAY); - } else - ret = BP_NOT_CAP; - return ret; -} - -/* DISC_PORT_ON */ -int disc_port_on(bpctl_dev_t *pbpctl_dev) -{ - int ret = 0; - bpctl_dev_t *pbpctl_dev_m; - - if ((is_bypass_fn(pbpctl_dev)) == 1) - pbpctl_dev_m = pbpctl_dev; - else - pbpctl_dev_m = get_master_port_fn(pbpctl_dev); - if (pbpctl_dev_m == NULL) - return BP_NOT_CAP; - - if (pbpctl_dev_m->bp_caps_ex & DISC_PORT_CAP_EX) { - if (is_bypass_fn(pbpctl_dev) == 1) { - - write_data(pbpctl_dev_m, TX_DISA); - } else { - - write_data(pbpctl_dev_m, TX_DISB); - } - - msec_delay_bp(LATCH_DELAY); - - } - return ret; -} - -/* DISC_PORT_OFF */ -int disc_port_off(bpctl_dev_t *pbpctl_dev) -{ - int ret = 0; - bpctl_dev_t *pbpctl_dev_m; - - if ((is_bypass_fn(pbpctl_dev)) == 1) - pbpctl_dev_m = pbpctl_dev; - else - pbpctl_dev_m = get_master_port_fn(pbpctl_dev); - if (pbpctl_dev_m == NULL) - return BP_NOT_CAP; - - if (pbpctl_dev_m->bp_caps_ex & DISC_PORT_CAP_EX) { - if (is_bypass_fn(pbpctl_dev) == 1) - write_data(pbpctl_dev_m, TX_ENA); - else - write_data(pbpctl_dev_m, TX_ENB); - - msec_delay_bp(LATCH_DELAY); - - } - return ret; -} - -/*TWO_PORT_LINK_HW_EN (0xe)*/ -int tpl_hw_on(bpctl_dev_t *pbpctl_dev) -{ - int ret = 0, ctrl = 0; - bpctl_dev_t *pbpctl_dev_b = NULL; - - if (!(pbpctl_dev_b = get_status_port_fn(pbpctl_dev))) - return BP_NOT_CAP; - - if (pbpctl_dev->bp_caps_ex & TPL2_CAP_EX) { - cmnd_on(pbpctl_dev); - write_data(pbpctl_dev, TPL2_ON); - msec_delay_bp(LATCH_DELAY + EEPROM_WR_DELAY); - cmnd_off(pbpctl_dev); - return ret; - } - - if (TPL_IF_SERIES(pbpctl_dev->subdevice)) { - ctrl = BPCTL_READ_REG(pbpctl_dev_b, CTRL); - BPCTL_BP_WRITE_REG(pbpctl_dev_b, CTRL, - ((ctrl | BPCTLI_CTRL_SWDPIO0) & - ~BPCTLI_CTRL_SWDPIN0)); - } else - ret = BP_NOT_CAP; - return ret; -} - -/*TWO_PORT_LINK_HW_DIS (0xc)*/ -int tpl_hw_off(bpctl_dev_t *pbpctl_dev) -{ - int ret = 0, ctrl = 0; - bpctl_dev_t *pbpctl_dev_b = NULL; - - if (!(pbpctl_dev_b = get_status_port_fn(pbpctl_dev))) - return BP_NOT_CAP; - if (pbpctl_dev->bp_caps_ex & TPL2_CAP_EX) { - cmnd_on(pbpctl_dev); - write_data(pbpctl_dev, TPL2_OFF); - msec_delay_bp(LATCH_DELAY + EEPROM_WR_DELAY); - cmnd_off(pbpctl_dev); - return ret; - } - if (TPL_IF_SERIES(pbpctl_dev->subdevice)) { - ctrl = BPCTL_READ_REG(pbpctl_dev_b, CTRL); - BPCTL_BP_WRITE_REG(pbpctl_dev_b, CTRL, - (ctrl | BPCTLI_CTRL_SWDPIO0 | - BPCTLI_CTRL_SWDPIN0)); - } else - ret = BP_NOT_CAP; - return ret; -} - -/* WDT_OFF (0x6 110)*/ -int wdt_off(bpctl_dev_t *pbpctl_dev) -{ - int ret = BP_NOT_CAP; - - if (pbpctl_dev->bp_caps & WD_CTL_CAP) { - if (INTEL_IF_SERIES(pbpctl_dev->subdevice)) { - bypass_off(pbpctl_dev); - } else if (pbpctl_dev->bp_ext_ver >= PXG2BPI_VER) - write_data(pbpctl_dev, WDT_OFF); - else - data_pulse(pbpctl_dev, WDT_OFF); - pbpctl_dev->wdt_status = WDT_STATUS_DIS; - ret = 0; - }; - return ret; -} - -/* WDT_ON (0x10)*/ - -/***Global***/ -static unsigned int - wdt_val_array[] = { 1000, 1500, 2000, 3000, 4000, 8000, 16000, 32000, 0 }; - -int wdt_on(bpctl_dev_t *pbpctl_dev, unsigned int timeout) -{ - - if (pbpctl_dev->bp_caps & WD_CTL_CAP) { - unsigned int pulse = 0, temp_value = 0, temp_cnt = 0; - pbpctl_dev->wdt_status = 0; - - if (INTEL_IF_SERIES(pbpctl_dev->subdevice)) { - for (; wdt_val_array[temp_cnt]; temp_cnt++) - if (timeout <= wdt_val_array[temp_cnt]) - break; - - if (!wdt_val_array[temp_cnt]) - temp_cnt--; - - timeout = wdt_val_array[temp_cnt]; - temp_cnt += 0x7; - - write_data_int(pbpctl_dev, DIS_BYPASS_CAP_INT); - msec_delay_bp(BYPASS_DELAY_INT); - pbpctl_dev->bp_status_un = 0; - write_data_int(pbpctl_dev, temp_cnt); - pbpctl_dev->bypass_wdt_on_time = jiffies; - msec_delay_bp(CMND_INTERVAL_INT); - pbpctl_dev->bypass_timer_interval = timeout; - } else { - timeout = - (timeout < - TIMEOUT_UNIT ? TIMEOUT_UNIT : (timeout > - WDT_TIMEOUT_MAX ? - WDT_TIMEOUT_MAX : - timeout)); - temp_value = timeout / 100; - while ((temp_value >>= 1)) - temp_cnt++; - if (timeout > ((1 << temp_cnt) * 100)) - temp_cnt++; - pbpctl_dev->bypass_wdt_on_time = jiffies; - pulse = (WDT_ON | temp_cnt); - if (pbpctl_dev->bp_ext_ver == OLD_IF_VER) - data_pulse(pbpctl_dev, pulse); - else - write_data(pbpctl_dev, pulse); - pbpctl_dev->bypass_timer_interval = - (1 << temp_cnt) * 100; - } - pbpctl_dev->wdt_status = WDT_STATUS_EN; - return 0; - } - return BP_NOT_CAP; -} - -void bp75_put_hw_semaphore_generic(bpctl_dev_t *pbpctl_dev) -{ - u32 swsm; - - swsm = BPCTL_READ_REG(pbpctl_dev, SWSM); - - swsm &= ~(BPCTLI_SWSM_SMBI | BPCTLI_SWSM_SWESMBI); - - BPCTL_WRITE_REG(pbpctl_dev, SWSM, swsm); -} - -s32 bp75_get_hw_semaphore_generic(bpctl_dev_t *pbpctl_dev) -{ - u32 swsm; - s32 ret_val = 0; - s32 timeout = 8192 + 1; - s32 i = 0; - - /* Get the SW semaphore */ - while (i < timeout) { - swsm = BPCTL_READ_REG(pbpctl_dev, SWSM); - if (!(swsm & BPCTLI_SWSM_SMBI)) - break; - - usec_delay(50); - i++; - } - - if (i == timeout) { - printk - ("bpctl_mod: Driver can't access device - SMBI bit is set.\n"); - ret_val = -1; - goto out; - } - - /* Get the FW semaphore. */ - for (i = 0; i < timeout; i++) { - swsm = BPCTL_READ_REG(pbpctl_dev, SWSM); - BPCTL_WRITE_REG(pbpctl_dev, SWSM, swsm | BPCTLI_SWSM_SWESMBI); - - /* Semaphore acquired if bit latched */ - if (BPCTL_READ_REG(pbpctl_dev, SWSM) & BPCTLI_SWSM_SWESMBI) - break; - - usec_delay(50); - } - - if (i == timeout) { - /* Release semaphores */ - bp75_put_hw_semaphore_generic(pbpctl_dev); - printk("bpctl_mod: Driver can't access the NVM\n"); - ret_val = -1; - goto out; - } - - out: - return ret_val; -} - -static void bp75_release_phy(bpctl_dev_t *pbpctl_dev) -{ - u16 mask = BPCTLI_SWFW_PHY0_SM; - u32 swfw_sync; - - if ((pbpctl_dev->func == 1) || (pbpctl_dev->func == 3)) - mask = BPCTLI_SWFW_PHY1_SM; - - while (bp75_get_hw_semaphore_generic(pbpctl_dev) != 0) ; - /* Empty */ - - swfw_sync = BPCTL_READ_REG(pbpctl_dev, SW_FW_SYNC); - swfw_sync &= ~mask; - BPCTL_WRITE_REG(pbpctl_dev, SW_FW_SYNC, swfw_sync); - - bp75_put_hw_semaphore_generic(pbpctl_dev); -} - -static s32 bp75_acquire_phy(bpctl_dev_t *pbpctl_dev) -{ - u16 mask = BPCTLI_SWFW_PHY0_SM; - u32 swfw_sync; - u32 swmask; - u32 fwmask; - s32 ret_val = 0; - s32 i = 0, timeout = 200; - - if ((pbpctl_dev->func == 1) || (pbpctl_dev->func == 3)) - mask = BPCTLI_SWFW_PHY1_SM; - - swmask = mask; - fwmask = mask << 16; - - while (i < timeout) { - if (bp75_get_hw_semaphore_generic(pbpctl_dev)) { - ret_val = -1; - goto out; - } - - swfw_sync = BPCTL_READ_REG(pbpctl_dev, SW_FW_SYNC); - if (!(swfw_sync & (fwmask | swmask))) - break; - - bp75_put_hw_semaphore_generic(pbpctl_dev); - mdelay(5); - i++; - } - - if (i == timeout) { - printk - ("bpctl_mod: Driver can't access resource, SW_FW_SYNC timeout.\n"); - ret_val = -1; - goto out; - } - - swfw_sync |= swmask; - BPCTL_WRITE_REG(pbpctl_dev, SW_FW_SYNC, swfw_sync); - - bp75_put_hw_semaphore_generic(pbpctl_dev); - - out: - return ret_val; -} - -s32 bp75_read_phy_reg_mdic(bpctl_dev_t *pbpctl_dev, u32 offset, u16 *data) -{ - u32 i, mdic = 0; - s32 ret_val = 0; - u32 phy_addr = 1; - - mdic = ((offset << BPCTLI_MDIC_REG_SHIFT) | - (phy_addr << BPCTLI_MDIC_PHY_SHIFT) | (BPCTLI_MDIC_OP_READ)); - - BPCTL_WRITE_REG(pbpctl_dev, MDIC, mdic); - - for (i = 0; i < (BPCTLI_GEN_POLL_TIMEOUT * 3); i++) { - usec_delay(50); - mdic = BPCTL_READ_REG(pbpctl_dev, MDIC); - if (mdic & BPCTLI_MDIC_READY) - break; - } - if (!(mdic & BPCTLI_MDIC_READY)) { - printk("bpctl_mod: MDI Read did not complete\n"); - ret_val = -1; - goto out; - } - if (mdic & BPCTLI_MDIC_ERROR) { - printk("bpctl_mod: MDI Error\n"); - ret_val = -1; - goto out; - } - *data = (u16) mdic; - - out: - return ret_val; -} - -s32 bp75_write_phy_reg_mdic(bpctl_dev_t *pbpctl_dev, u32 offset, u16 data) -{ - u32 i, mdic = 0; - s32 ret_val = 0; - u32 phy_addr = 1; - - mdic = (((u32) data) | - (offset << BPCTLI_MDIC_REG_SHIFT) | - (phy_addr << BPCTLI_MDIC_PHY_SHIFT) | (BPCTLI_MDIC_OP_WRITE)); - - BPCTL_WRITE_REG(pbpctl_dev, MDIC, mdic); - - for (i = 0; i < (BPCTLI_GEN_POLL_TIMEOUT * 3); i++) { - usec_delay(50); - mdic = BPCTL_READ_REG(pbpctl_dev, MDIC); - if (mdic & BPCTLI_MDIC_READY) - break; - } - if (!(mdic & BPCTLI_MDIC_READY)) { - printk("bpctl_mod: MDI Write did not complete\n"); - ret_val = -1; - goto out; - } - if (mdic & BPCTLI_MDIC_ERROR) { - printk("bpctl_mod: MDI Error\n"); - ret_val = -1; - goto out; - } - - out: - return ret_val; -} - -static s32 bp75_read_phy_reg(bpctl_dev_t *pbpctl_dev, u32 offset, u16 *data) -{ - s32 ret_val = 0; - - ret_val = bp75_acquire_phy(pbpctl_dev); - if (ret_val) - goto out; - - if (offset > BPCTLI_MAX_PHY_MULTI_PAGE_REG) { - ret_val = bp75_write_phy_reg_mdic(pbpctl_dev, - BPCTLI_IGP01E1000_PHY_PAGE_SELECT, - (u16) offset); - if (ret_val) - goto release; - } - - ret_val = - bp75_read_phy_reg_mdic(pbpctl_dev, - BPCTLI_MAX_PHY_REG_ADDRESS & offset, data); - - release: - bp75_release_phy(pbpctl_dev); - out: - return ret_val; -} - -static s32 bp75_write_phy_reg(bpctl_dev_t *pbpctl_dev, u32 offset, u16 data) -{ - s32 ret_val = 0; - - ret_val = bp75_acquire_phy(pbpctl_dev); - if (ret_val) - goto out; - - if (offset > BPCTLI_MAX_PHY_MULTI_PAGE_REG) { - ret_val = bp75_write_phy_reg_mdic(pbpctl_dev, - BPCTLI_IGP01E1000_PHY_PAGE_SELECT, - (u16) offset); - if (ret_val) - goto release; - } - - ret_val = - bp75_write_phy_reg_mdic(pbpctl_dev, - BPCTLI_MAX_PHY_REG_ADDRESS & offset, data); - - release: - bp75_release_phy(pbpctl_dev); - - out: - return ret_val; -} - -/* SET_TX (non-Bypass command :)) */ -static int set_tx(bpctl_dev_t *pbpctl_dev, int tx_state) -{ - int ret = 0, ctrl = 0; - bpctl_dev_t *pbpctl_dev_m; - if ((is_bypass_fn(pbpctl_dev)) == 1) - pbpctl_dev_m = pbpctl_dev; - else - pbpctl_dev_m = get_master_port_fn(pbpctl_dev); - if (pbpctl_dev_m == NULL) - return BP_NOT_CAP; - if (pbpctl_dev_m->bp_caps_ex & DISC_PORT_CAP_EX) { - ctrl = BPCTL_READ_REG(pbpctl_dev, CTRL); - if (!tx_state) { - if (pbpctl_dev->bp_540) { - ctrl = BP10G_READ_REG(pbpctl_dev, ESDP); - BP10G_WRITE_REG(pbpctl_dev, ESDP, - (ctrl | BP10G_SDP1_DIR | - BP10G_SDP1_DATA)); - - } else { - BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL, - (ctrl | BPCTLI_CTRL_SDP1_DIR - | BPCTLI_CTRL_SWDPIN1)); - } - } else { - if (pbpctl_dev->bp_540) { - ctrl = BP10G_READ_REG(pbpctl_dev, ESDP); - BP10G_WRITE_REG(pbpctl_dev, ESDP, - ((ctrl | BP10G_SDP1_DIR) & - ~BP10G_SDP1_DATA)); - } else { - BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL, - ((ctrl | - BPCTLI_CTRL_SDP1_DIR) & - ~BPCTLI_CTRL_SWDPIN1)); - } - return ret; - - } - } else if (pbpctl_dev->bp_caps & TX_CTL_CAP) { - if (PEG5_IF_SERIES(pbpctl_dev->subdevice)) { - if (tx_state) { - uint16_t mii_reg; - if (! - (ret = - bp75_read_phy_reg(pbpctl_dev, - BPCTLI_PHY_CONTROL, - &mii_reg))) { - if (mii_reg & BPCTLI_MII_CR_POWER_DOWN) { - ret = - bp75_write_phy_reg - (pbpctl_dev, - BPCTLI_PHY_CONTROL, - mii_reg & - ~BPCTLI_MII_CR_POWER_DOWN); - } - } - } else { - uint16_t mii_reg; - if (! - (ret = - bp75_read_phy_reg(pbpctl_dev, - BPCTLI_PHY_CONTROL, - &mii_reg))) { - - mii_reg |= BPCTLI_MII_CR_POWER_DOWN; - ret = - bp75_write_phy_reg(pbpctl_dev, - BPCTLI_PHY_CONTROL, - mii_reg); - } - } - - } - if (pbpctl_dev->bp_fiber5) { - ctrl = BPCTL_READ_REG(pbpctl_dev, CTRL_EXT); - - } else if (pbpctl_dev->bp_10gb) - ctrl = BP10GB_READ_REG(pbpctl_dev, MISC_REG_GPIO); - - else if (!pbpctl_dev->bp_10g) - ctrl = BPCTL_READ_REG(pbpctl_dev, CTRL); - else - ctrl = BP10G_READ_REG(pbpctl_dev, ESDP); - - if (!tx_state) - if (pbpctl_dev->bp_10g9) { - BP10G_WRITE_REG(pbpctl_dev, ESDP, - (ctrl | BP10G_SDP3_DATA | - BP10G_SDP3_DIR)); - - } else if (pbpctl_dev->bp_fiber5) { - BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, - (ctrl | - BPCTLI_CTRL_EXT_SDP6_DIR | - BPCTLI_CTRL_EXT_SDP6_DATA)); - - } else if (pbpctl_dev->bp_10gb) { - if ((pbpctl_dev->func == 1) - || (pbpctl_dev->func == 3)) - BP10GB_WRITE_REG(pbpctl_dev, - MISC_REG_GPIO, - (ctrl | - BP10GB_GPIO0_SET_P1) & - ~(BP10GB_GPIO0_CLR_P1 | - BP10GB_GPIO0_OE_P1)); - else - BP10GB_WRITE_REG(pbpctl_dev, - MISC_REG_GPIO, - (ctrl | - BP10GB_GPIO0_OE_P0 | - BP10GB_GPIO0_SET_P0)); - - } else if (pbpctl_dev->bp_i80) { - BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL, - (ctrl | BPCTLI_CTRL_SDP1_DIR - | BPCTLI_CTRL_SWDPIN1)); - - } else if (pbpctl_dev->bp_540) { - ctrl = BP10G_READ_REG(pbpctl_dev, ESDP); - BP10G_WRITE_REG(pbpctl_dev, ESDP, - (ctrl | BP10G_SDP1_DIR | - BP10G_SDP1_DATA)); - - } - - else if (!pbpctl_dev->bp_10g) - BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL, - (ctrl | BPCTLI_CTRL_SWDPIO0 | - BPCTLI_CTRL_SWDPIN0)); - - else - BP10G_WRITE_REG(pbpctl_dev, ESDP, - (ctrl | BP10G_SDP0_DATA | - BP10G_SDP0_DIR)); - - else { - if (pbpctl_dev->bp_10g9) { - BP10G_WRITE_REG(pbpctl_dev, ESDP, - ((ctrl | BP10G_SDP3_DIR) & - ~BP10G_SDP3_DATA)); - - } else if (pbpctl_dev->bp_fiber5) { - BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, - ((ctrl | - BPCTLI_CTRL_EXT_SDP6_DIR) & - ~BPCTLI_CTRL_EXT_SDP6_DATA)); - - } else if (pbpctl_dev->bp_10gb) { - if ((bpctl_dev_arr->func == 1) - || (bpctl_dev_arr->func == 3)) - BP10GB_WRITE_REG(pbpctl_dev, - MISC_REG_GPIO, - (ctrl | - BP10GB_GPIO0_CLR_P1) & - ~(BP10GB_GPIO0_SET_P1 | - BP10GB_GPIO0_OE_P1)); - else - BP10GB_WRITE_REG(pbpctl_dev, - MISC_REG_GPIO, - (ctrl | - BP10GB_GPIO0_OE_P0 | - BP10GB_GPIO0_CLR_P0)); - - } else if (pbpctl_dev->bp_i80) { - BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL, - ((ctrl | - BPCTLI_CTRL_SDP1_DIR) & - ~BPCTLI_CTRL_SWDPIN1)); - } else if (pbpctl_dev->bp_540) { - ctrl = BP10G_READ_REG(pbpctl_dev, ESDP); - BP10G_WRITE_REG(pbpctl_dev, ESDP, - ((ctrl | BP10G_SDP1_DIR) & - ~BP10G_SDP1_DATA)); - } - - else if (!pbpctl_dev->bp_10g) { - BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL, - ((ctrl | BPCTLI_CTRL_SWDPIO0) - & ~BPCTLI_CTRL_SWDPIN0)); - if (!PEGF_IF_SERIES(pbpctl_dev->subdevice)) { - BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL, - (ctrl & - ~ - (BPCTLI_CTRL_SDP0_DATA - | - BPCTLI_CTRL_SDP0_DIR))); - } - } else - BP10G_WRITE_REG(pbpctl_dev, ESDP, - ((ctrl | BP10G_SDP0_DIR) & - ~BP10G_SDP0_DATA)); - - } - - } else - ret = BP_NOT_CAP; - return ret; - -} - -/* SET_FORCE_LINK (non-Bypass command :)) */ -static int set_bp_force_link(bpctl_dev_t *pbpctl_dev, int tx_state) -{ - int ret = 0, ctrl = 0; - - if (DBI_IF_SERIES(pbpctl_dev->subdevice)) { - - if ((pbpctl_dev->bp_10g) || (pbpctl_dev->bp_10g9)) { - - ctrl = BPCTL_READ_REG(pbpctl_dev, CTRL); - if (!tx_state) - BP10G_WRITE_REG(pbpctl_dev, ESDP, - ctrl & ~BP10G_SDP1_DIR); - else - BP10G_WRITE_REG(pbpctl_dev, ESDP, - ((ctrl | BP10G_SDP1_DIR) & - ~BP10G_SDP1_DATA)); - return ret; - } - - } - return BP_NOT_CAP; -} - -/*RESET_CONT 0x20 */ -int reset_cont(bpctl_dev_t *pbpctl_dev) -{ - int ret = BP_NOT_CAP; - - if (pbpctl_dev->bp_caps & SW_CTL_CAP) { - if (INTEL_IF_SERIES(pbpctl_dev->subdevice)) - return BP_NOT_CAP; - if (pbpctl_dev->bp_ext_ver >= PXG2BPI_VER) - write_data(pbpctl_dev, RESET_CONT); - else - data_pulse(pbpctl_dev, RESET_CONT); - ret = 0; - }; - return ret; -} - -/*DIS_BYPASS_CAP 0x22 */ -int dis_bypass_cap(bpctl_dev_t *pbpctl_dev) -{ - - if (pbpctl_dev->bp_caps & BP_DIS_CAP) { - if (INTEL_IF_SERIES(pbpctl_dev->subdevice)) { - write_data_int(pbpctl_dev, DIS_BYPASS_CAP_INT); - msec_delay_bp(BYPASS_DELAY_INT); - } else { - write_data(pbpctl_dev, BYPASS_OFF); - msec_delay_bp(LATCH_DELAY); - write_data(pbpctl_dev, DIS_BYPASS_CAP); - msec_delay_bp(BYPASS_CAP_DELAY); - } - return 0; - } - return BP_NOT_CAP; -} - -/*EN_BYPASS_CAP 0x24 */ -int en_bypass_cap(bpctl_dev_t *pbpctl_dev) -{ - if (pbpctl_dev->bp_caps & BP_DIS_CAP) { - if (INTEL_IF_SERIES(pbpctl_dev->subdevice)) { - write_data_int(pbpctl_dev, PWROFF_BYPASS_ON_INT); - msec_delay_bp(BYPASS_DELAY_INT); - } else { - write_data(pbpctl_dev, EN_BYPASS_CAP); - msec_delay_bp(BYPASS_CAP_DELAY); - } - return 0; - } - return BP_NOT_CAP; -} - -/* BYPASS_STATE_PWRON 0x26*/ -int bypass_state_pwron(bpctl_dev_t *pbpctl_dev) -{ - if (pbpctl_dev->bp_caps & BP_PWUP_CTL_CAP) { - write_data(pbpctl_dev, BYPASS_STATE_PWRON); - if (pbpctl_dev->bp_ext_ver == PXG2BPI_VER) - msec_delay_bp(DFLT_PWRON_DELAY); - else - msec_delay_bp(LATCH_DELAY + EEPROM_WR_DELAY); - return 0; - } - return BP_NOT_CAP; -} - -/* NORMAL_STATE_PWRON 0x28*/ -int normal_state_pwron(bpctl_dev_t *pbpctl_dev) -{ - if ((pbpctl_dev->bp_caps & BP_PWUP_CTL_CAP) - || (pbpctl_dev->bp_caps & TAP_PWUP_CTL_CAP)) { - write_data(pbpctl_dev, NORMAL_STATE_PWRON); - if (pbpctl_dev->bp_ext_ver == PXG2BPI_VER) - msec_delay_bp(DFLT_PWRON_DELAY); - else - msec_delay_bp(LATCH_DELAY + EEPROM_WR_DELAY); - return 0; - } - return BP_NOT_CAP; -} - -/* BYPASS_STATE_PWROFF 0x27*/ -int bypass_state_pwroff(bpctl_dev_t *pbpctl_dev) -{ - if (pbpctl_dev->bp_caps & BP_PWOFF_CTL_CAP) { - write_data(pbpctl_dev, BYPASS_STATE_PWROFF); - msec_delay_bp(LATCH_DELAY + EEPROM_WR_DELAY); - return 0; - } - return BP_NOT_CAP; -} - -/* NORMAL_STATE_PWROFF 0x29*/ -int normal_state_pwroff(bpctl_dev_t *pbpctl_dev) -{ - if ((pbpctl_dev->bp_caps & BP_PWOFF_CTL_CAP)) { - write_data(pbpctl_dev, NORMAL_STATE_PWROFF); - msec_delay_bp(LATCH_DELAY + EEPROM_WR_DELAY); - return 0; - } - return BP_NOT_CAP; -} - -/*TAP_STATE_PWRON 0x2a*/ -int tap_state_pwron(bpctl_dev_t *pbpctl_dev) -{ - if (pbpctl_dev->bp_caps & TAP_PWUP_CTL_CAP) { - write_data(pbpctl_dev, TAP_STATE_PWRON); - msec_delay_bp(LATCH_DELAY + EEPROM_WR_DELAY); - return 0; - } - return BP_NOT_CAP; -} - -/*DIS_TAP_CAP 0x2c*/ -int dis_tap_cap(bpctl_dev_t *pbpctl_dev) -{ - if (pbpctl_dev->bp_caps & TAP_DIS_CAP) { - write_data(pbpctl_dev, DIS_TAP_CAP); - msec_delay_bp(BYPASS_CAP_DELAY); - return 0; - } - return BP_NOT_CAP; -} - -/*EN_TAP_CAP 0x2e*/ -int en_tap_cap(bpctl_dev_t *pbpctl_dev) -{ - if (pbpctl_dev->bp_caps & TAP_DIS_CAP) { - write_data(pbpctl_dev, EN_TAP_CAP); - msec_delay_bp(BYPASS_CAP_DELAY); - return 0; - } - return BP_NOT_CAP; -} - -/*DISC_STATE_PWRON 0x2a*/ -int disc_state_pwron(bpctl_dev_t *pbpctl_dev) -{ - if (pbpctl_dev->bp_caps & DISC_PWUP_CTL_CAP) { - if (pbpctl_dev->bp_ext_ver >= 0x8) { - write_data(pbpctl_dev, DISC_STATE_PWRON); - msec_delay_bp(LATCH_DELAY + EEPROM_WR_DELAY); - return BP_OK; - } - } - return BP_NOT_CAP; -} - -/*DIS_DISC_CAP 0x2c*/ -int dis_disc_cap(bpctl_dev_t *pbpctl_dev) -{ - if (pbpctl_dev->bp_caps & DISC_DIS_CAP) { - if (pbpctl_dev->bp_ext_ver >= 0x8) { - write_data(pbpctl_dev, DIS_DISC_CAP); - msec_delay_bp(BYPASS_CAP_DELAY); - return BP_OK; - } - } - return BP_NOT_CAP; -} - -/*DISC_STATE_PWRON 0x2a*/ -int disc_port_state_pwron(bpctl_dev_t *pbpctl_dev) -{ - int ret = 0; - bpctl_dev_t *pbpctl_dev_m; - - return BP_NOT_CAP; - - if ((is_bypass_fn(pbpctl_dev)) == 1) - pbpctl_dev_m = pbpctl_dev; - else - pbpctl_dev_m = get_master_port_fn(pbpctl_dev); - if (pbpctl_dev_m == NULL) - return BP_NOT_CAP; - - if (pbpctl_dev_m->bp_caps_ex & DISC_PORT_CAP_EX) { - if (is_bypass_fn(pbpctl_dev) == 1) - write_data(pbpctl_dev_m, TX_DISA_PWRUP); - else - write_data(pbpctl_dev_m, TX_DISB_PWRUP); - - msec_delay_bp(LATCH_DELAY); - - } - return ret; -} - -int normal_port_state_pwron(bpctl_dev_t *pbpctl_dev) -{ - int ret = 0; - bpctl_dev_t *pbpctl_dev_m; - return BP_NOT_CAP; - - if ((is_bypass_fn(pbpctl_dev)) == 1) - pbpctl_dev_m = pbpctl_dev; - else - pbpctl_dev_m = get_master_port_fn(pbpctl_dev); - if (pbpctl_dev_m == NULL) - return BP_NOT_CAP; - - if (pbpctl_dev_m->bp_caps_ex & DISC_PORT_CAP_EX) { - if (is_bypass_fn(pbpctl_dev) == 1) - write_data(pbpctl_dev_m, TX_ENA_PWRUP); - else - write_data(pbpctl_dev_m, TX_ENB_PWRUP); - - msec_delay_bp(LATCH_DELAY); - - } - return ret; -} - -/*EN_TAP_CAP 0x2e*/ -int en_disc_cap(bpctl_dev_t *pbpctl_dev) -{ - if (pbpctl_dev->bp_caps & DISC_DIS_CAP) { - if (pbpctl_dev->bp_ext_ver >= 0x8) { - write_data(pbpctl_dev, EN_DISC_CAP); - msec_delay_bp(BYPASS_CAP_DELAY); - return BP_OK; - } - } - return BP_NOT_CAP; -} - -int std_nic_on(bpctl_dev_t *pbpctl_dev) -{ - - if (pbpctl_dev->bp_caps & STD_NIC_CAP) { - - if (INTEL_IF_SERIES(pbpctl_dev->subdevice)) { - write_data_int(pbpctl_dev, DIS_BYPASS_CAP_INT); - msec_delay_bp(BYPASS_DELAY_INT); - pbpctl_dev->bp_status_un = 0; - return BP_OK; - } - - if (pbpctl_dev->bp_ext_ver >= 0x8) { - write_data(pbpctl_dev, STD_NIC_ON); - msec_delay_bp(BYPASS_CAP_DELAY); - return BP_OK; - - } - - if (pbpctl_dev->bp_ext_ver >= PXG2BPI_VER) { - wdt_off(pbpctl_dev); - - if (pbpctl_dev->bp_caps & BP_CAP) { - write_data(pbpctl_dev, BYPASS_OFF); - msec_delay_bp(LATCH_DELAY); - } - - if (pbpctl_dev->bp_caps & TAP_CAP) { - write_data(pbpctl_dev, TAP_OFF); - msec_delay_bp(LATCH_DELAY); - } - - write_data(pbpctl_dev, NORMAL_STATE_PWRON); - if (pbpctl_dev->bp_ext_ver == PXG2BPI_VER) - msec_delay_bp(DFLT_PWRON_DELAY); - else - msec_delay_bp(LATCH_DELAY + EEPROM_WR_DELAY); - - if (pbpctl_dev->bp_caps & BP_DIS_CAP) { - write_data(pbpctl_dev, DIS_BYPASS_CAP); - msec_delay_bp(BYPASS_CAP_DELAY); - } - - if (pbpctl_dev->bp_caps & TAP_DIS_CAP) { - write_data(pbpctl_dev, DIS_TAP_CAP); - msec_delay_bp(BYPASS_CAP_DELAY); - - } - return 0; - } - } - return BP_NOT_CAP; -} - -int std_nic_off(bpctl_dev_t *pbpctl_dev) -{ - - if (pbpctl_dev->bp_caps & STD_NIC_CAP) { - if (INTEL_IF_SERIES(pbpctl_dev->subdevice)) { - write_data_int(pbpctl_dev, PWROFF_BYPASS_ON_INT); - msec_delay_bp(BYPASS_DELAY_INT); - return BP_OK; - } - if (pbpctl_dev->bp_ext_ver >= 0x8) { - write_data(pbpctl_dev, STD_NIC_OFF); - msec_delay_bp(BYPASS_CAP_DELAY); - return BP_OK; - - } - - if (pbpctl_dev->bp_ext_ver >= PXG2BPI_VER) { - - if (pbpctl_dev->bp_caps & TAP_PWUP_CTL_CAP) { - write_data(pbpctl_dev, TAP_STATE_PWRON); - msec_delay_bp(LATCH_DELAY + EEPROM_WR_DELAY); - } - - if (pbpctl_dev->bp_caps & BP_PWUP_CTL_CAP) { - write_data(pbpctl_dev, BYPASS_STATE_PWRON); - if (pbpctl_dev->bp_ext_ver > PXG2BPI_VER) - msec_delay_bp(LATCH_DELAY + - EEPROM_WR_DELAY); - else - msec_delay_bp(DFLT_PWRON_DELAY); - } - - if (pbpctl_dev->bp_caps & TAP_DIS_CAP) { - write_data(pbpctl_dev, EN_TAP_CAP); - msec_delay_bp(BYPASS_CAP_DELAY); - } - if (pbpctl_dev->bp_caps & DISC_DIS_CAP) { - write_data(pbpctl_dev, EN_DISC_CAP); - msec_delay_bp(BYPASS_CAP_DELAY); - } - - if (pbpctl_dev->bp_caps & BP_DIS_CAP) { - write_data(pbpctl_dev, EN_BYPASS_CAP); - msec_delay_bp(BYPASS_CAP_DELAY); - } - - return 0; - } - } - return BP_NOT_CAP; -} - -int wdt_time_left(bpctl_dev_t *pbpctl_dev) -{ - - /* unsigned long curr_time=((long long)(jiffies*1000))/HZ, delta_time=0,wdt_on_time=((long long)(pbpctl_dev->bypass_wdt_on_time*1000))/HZ; */ - unsigned long curr_time = jiffies, delta_time = 0, wdt_on_time = - pbpctl_dev->bypass_wdt_on_time, delta_time_msec = 0; - int time_left = 0; - - switch (pbpctl_dev->wdt_status) { - case WDT_STATUS_DIS: - time_left = 0; - break; - case WDT_STATUS_EN: - delta_time = - (curr_time >= - wdt_on_time) ? (curr_time - wdt_on_time) : (~wdt_on_time + - curr_time); - delta_time_msec = jiffies_to_msecs(delta_time); - time_left = pbpctl_dev->bypass_timer_interval - delta_time_msec; - if (time_left < 0) { - time_left = -1; - pbpctl_dev->wdt_status = WDT_STATUS_EXP; - } - break; - case WDT_STATUS_EXP: - time_left = -1; - break; - } - - return time_left; -} - -static int wdt_timer(bpctl_dev_t *pbpctl_dev, int *time_left) -{ - int ret = 0; - if (pbpctl_dev->bp_caps & WD_CTL_CAP) { - { - if (pbpctl_dev->wdt_status == WDT_STATUS_UNKNOWN) - ret = BP_NOT_CAP; - else - *time_left = wdt_time_left(pbpctl_dev); - } - - } else - ret = BP_NOT_CAP; - return ret; -} - -static int wdt_timer_reload(bpctl_dev_t *pbpctl_dev) -{ - - int ret = 0; - - if ((pbpctl_dev->bp_caps & WD_CTL_CAP) && - (pbpctl_dev->wdt_status != WDT_STATUS_UNKNOWN)) { - if (pbpctl_dev->wdt_status == WDT_STATUS_DIS) - return 0; - if (pbpctl_dev->bp_ext_ver >= PXG2BPI_VER) - ret = wdt_pulse(pbpctl_dev); - else if (INTEL_IF_SERIES(pbpctl_dev->subdevice)) - ret = wdt_pulse_int(pbpctl_dev); - else - ret = send_wdt_pulse(pbpctl_dev); - /* if (ret==-1) - mod_timer(&pbpctl_dev->bp_timer, jiffies+1);*/ - return 1; - } - return BP_NOT_CAP; -} - -static void wd_reset_timer(unsigned long param) -{ - bpctl_dev_t *pbpctl_dev = (bpctl_dev_t *) param; -#ifdef BP_SELF_TEST - struct sk_buff *skb_tmp; -#endif - - if ((pbpctl_dev->bp_ext_ver >= PXG2BPI_VER) && - ((atomic_read(&pbpctl_dev->wdt_busy)) == 1)) { - mod_timer(&pbpctl_dev->bp_timer, jiffies + 1); - return; - } -#ifdef BP_SELF_TEST - - if (pbpctl_dev->bp_self_test_flag == 1) { - skb_tmp = dev_alloc_skb(BPTEST_DATA_LEN + 2); - if ((skb_tmp) && (pbpctl_dev->ndev) && (pbpctl_dev->bp_tx_data)) { - memcpy(skb_put(skb_tmp, BPTEST_DATA_LEN), - pbpctl_dev->bp_tx_data, BPTEST_DATA_LEN); - skb_tmp->dev = pbpctl_dev->ndev; - skb_tmp->protocol = - eth_type_trans(skb_tmp, pbpctl_dev->ndev); - skb_tmp->ip_summed = CHECKSUM_UNNECESSARY; - netif_receive_skb(skb_tmp); - goto bp_timer_reload; - return; - } - } -#endif - - wdt_timer_reload(pbpctl_dev); -#ifdef BP_SELF_TEST - bp_timer_reload: -#endif - if (pbpctl_dev->reset_time) { - mod_timer(&pbpctl_dev->bp_timer, - jiffies + (HZ * pbpctl_dev->reset_time) / 1000); - } -} - -/*WAIT_AT_PWRUP 0x80 */ -int bp_wait_at_pwup_en(bpctl_dev_t *pbpctl_dev) -{ - - if (pbpctl_dev->bp_caps & SW_CTL_CAP) { - if (pbpctl_dev->bp_ext_ver >= BP_FW_EXT_VER8) { - write_data(pbpctl_dev, BP_WAIT_AT_PWUP_EN); - msec_delay_bp(LATCH_DELAY + EEPROM_WR_DELAY); - - return BP_OK; - } - } - return BP_NOT_CAP; -} - -/*DIS_WAIT_AT_PWRUP 0x81 */ -int bp_wait_at_pwup_dis(bpctl_dev_t *pbpctl_dev) -{ - - if (pbpctl_dev->bp_caps & SW_CTL_CAP) { - - if (pbpctl_dev->bp_ext_ver >= BP_FW_EXT_VER8) { - write_data(pbpctl_dev, BP_WAIT_AT_PWUP_DIS); - msec_delay_bp(LATCH_DELAY + EEPROM_WR_DELAY); - - return BP_OK; - } - } - return BP_NOT_CAP; -} - -/*EN_HW_RESET 0x82 */ - -int bp_hw_reset_en(bpctl_dev_t *pbpctl_dev) -{ - - if (pbpctl_dev->bp_caps & SW_CTL_CAP) { - if (pbpctl_dev->bp_ext_ver >= BP_FW_EXT_VER8) { - write_data(pbpctl_dev, BP_HW_RESET_EN); - msec_delay_bp(LATCH_DELAY + EEPROM_WR_DELAY); - - return BP_OK; - } - } - return BP_NOT_CAP; -} - -/*DIS_HW_RESET 0x83 */ - -int bp_hw_reset_dis(bpctl_dev_t *pbpctl_dev) -{ - - if (pbpctl_dev->bp_caps & SW_CTL_CAP) { - if (pbpctl_dev->bp_ext_ver >= BP_FW_EXT_VER8) { - write_data(pbpctl_dev, BP_HW_RESET_DIS); - msec_delay_bp(LATCH_DELAY + EEPROM_WR_DELAY); - - return BP_OK; - } - } - return BP_NOT_CAP; -} - - -int wdt_exp_mode(bpctl_dev_t *pbpctl_dev, int mode) -{ - uint32_t status_reg = 0, status_reg1 = 0; - - if ((pbpctl_dev->bp_caps & (TAP_STATUS_CAP | DISC_CAP)) && - (pbpctl_dev->bp_caps & BP_CAP)) { - if (pbpctl_dev->bp_ext_ver >= PXE2TBPI_VER) { - - if ((pbpctl_dev->bp_ext_ver >= 0x8) && - (mode == 2) && (pbpctl_dev->bp_caps & DISC_CAP)) { - status_reg1 = - read_reg(pbpctl_dev, STATUS_DISC_REG_ADDR); - if (!(status_reg1 & WDTE_DISC_BPN_MASK)) - write_reg(pbpctl_dev, - status_reg1 | - WDTE_DISC_BPN_MASK, - STATUS_DISC_REG_ADDR); - return BP_OK; - } - } - status_reg = read_reg(pbpctl_dev, STATUS_TAP_REG_ADDR); - - if ((mode == 0) && (pbpctl_dev->bp_caps & BP_CAP)) { - if (pbpctl_dev->bp_ext_ver >= 0x8) { - status_reg1 = - read_reg(pbpctl_dev, STATUS_DISC_REG_ADDR); - if (status_reg1 & WDTE_DISC_BPN_MASK) - write_reg(pbpctl_dev, - status_reg1 & - ~WDTE_DISC_BPN_MASK, - STATUS_DISC_REG_ADDR); - } - if (status_reg & WDTE_TAP_BPN_MASK) - write_reg(pbpctl_dev, - status_reg & ~WDTE_TAP_BPN_MASK, - STATUS_TAP_REG_ADDR); - return BP_OK; - - } else if ((mode == 1) && (pbpctl_dev->bp_caps & TAP_CAP)) { - if (!(status_reg & WDTE_TAP_BPN_MASK)) - write_reg(pbpctl_dev, - status_reg | WDTE_TAP_BPN_MASK, - STATUS_TAP_REG_ADDR); - /*else return BP_NOT_CAP; */ - return BP_OK; - } - - } - return BP_NOT_CAP; -} - -int bypass_fw_ver(bpctl_dev_t *pbpctl_dev) -{ - if (is_bypass_fn(pbpctl_dev)) - return read_reg(pbpctl_dev, VER_REG_ADDR); - else - return BP_NOT_CAP; -} - -int bypass_sign_check(bpctl_dev_t *pbpctl_dev) -{ - - if (is_bypass_fn(pbpctl_dev)) - return (((read_reg(pbpctl_dev, PIC_SIGN_REG_ADDR)) == - PIC_SIGN_VALUE) ? 1 : 0); - else - return BP_NOT_CAP; -} - -static int tx_status(bpctl_dev_t *pbpctl_dev) -{ - uint32_t ctrl = 0; - bpctl_dev_t *pbpctl_dev_m; - if ((is_bypass_fn(pbpctl_dev)) == 1) - pbpctl_dev_m = pbpctl_dev; - else - pbpctl_dev_m = get_master_port_fn(pbpctl_dev); - if (pbpctl_dev_m == NULL) - return BP_NOT_CAP; - if (pbpctl_dev_m->bp_caps_ex & DISC_PORT_CAP_EX) { - - ctrl = BPCTL_READ_REG(pbpctl_dev, CTRL); - if (pbpctl_dev->bp_i80) - return ((ctrl & BPCTLI_CTRL_SWDPIN1) != 0 ? 0 : 1); - if (pbpctl_dev->bp_540) { - ctrl = BP10G_READ_REG(pbpctl_dev, ESDP); - - return ((ctrl & BP10G_SDP1_DATA) != 0 ? 0 : 1); - } - - } - - if (pbpctl_dev->bp_caps & TX_CTL_CAP) { - if (PEG5_IF_SERIES(pbpctl_dev->subdevice)) { - uint16_t mii_reg; - if (! - (bp75_read_phy_reg - (pbpctl_dev, BPCTLI_PHY_CONTROL, &mii_reg))) { - if (mii_reg & BPCTLI_MII_CR_POWER_DOWN) - return 0; - - else - return 1; - } - return -1; - } - - if (pbpctl_dev->bp_10g9) { - return ((BP10G_READ_REG(pbpctl_dev, ESDP) & - BP10G_SDP3_DATA) != 0 ? 0 : 1); - - } else if (pbpctl_dev->bp_fiber5) { - ctrl = BPCTL_READ_REG(pbpctl_dev, CTRL_EXT); - if (ctrl & BPCTLI_CTRL_EXT_SDP6_DATA) - return 0; - return 1; - } else if (pbpctl_dev->bp_10gb) { - ctrl = BP10GB_READ_REG(pbpctl_dev, MISC_REG_GPIO); - BP10GB_WRITE_REG(pbpctl_dev, MISC_REG_GPIO, - (ctrl | BP10GB_GPIO0_OE_P1) & - ~(BP10GB_GPIO0_SET_P1 | - BP10GB_GPIO0_CLR_P1)); - - if ((pbpctl_dev->func == 1) || (pbpctl_dev->func == 3)) - return (((BP10GB_READ_REG - (pbpctl_dev, - MISC_REG_GPIO)) & BP10GB_GPIO0_P1) != - 0 ? 0 : 1); - else - return (((BP10GB_READ_REG - (pbpctl_dev, - MISC_REG_GPIO)) & BP10GB_GPIO0_P0) != - 0 ? 0 : 1); - } - - if (!pbpctl_dev->bp_10g) { - - ctrl = BPCTL_READ_REG(pbpctl_dev, CTRL); - if (pbpctl_dev->bp_i80) - return ((ctrl & BPCTLI_CTRL_SWDPIN1) != - 0 ? 0 : 1); - if (pbpctl_dev->bp_540) { - ctrl = BP10G_READ_REG(pbpctl_dev, ESDP); - - return ((ctrl & BP10G_SDP1_DATA) != 0 ? 0 : 1); - } - - return ((ctrl & BPCTLI_CTRL_SWDPIN0) != 0 ? 0 : 1); - } else - return ((BP10G_READ_REG(pbpctl_dev, ESDP) & - BP10G_SDP0_DATA) != 0 ? 0 : 1); - - } - return BP_NOT_CAP; -} - -static int bp_force_link_status(bpctl_dev_t *pbpctl_dev) -{ - - if (DBI_IF_SERIES(pbpctl_dev->subdevice)) { - - if ((pbpctl_dev->bp_10g) || (pbpctl_dev->bp_10g9)) { - return ((BP10G_READ_REG(pbpctl_dev, ESDP) & - BP10G_SDP1_DIR) != 0 ? 1 : 0); - - } - } - return BP_NOT_CAP; -} - -int bypass_from_last_read(bpctl_dev_t *pbpctl_dev) -{ - uint32_t ctrl_ext = 0; - bpctl_dev_t *pbpctl_dev_b = NULL; - - if ((pbpctl_dev->bp_caps & SW_CTL_CAP) - && (pbpctl_dev_b = get_status_port_fn(pbpctl_dev))) { - ctrl_ext = BPCTL_READ_REG(pbpctl_dev_b, CTRL_EXT); - BPCTL_BP_WRITE_REG(pbpctl_dev_b, CTRL_EXT, - (ctrl_ext & ~BPCTLI_CTRL_EXT_SDP7_DIR)); - ctrl_ext = BPCTL_READ_REG(pbpctl_dev_b, CTRL_EXT); - if (ctrl_ext & BPCTLI_CTRL_EXT_SDP7_DATA) - return 0; - return 1; - } else - return BP_NOT_CAP; -} - -int bypass_status_clear(bpctl_dev_t *pbpctl_dev) -{ - bpctl_dev_t *pbpctl_dev_b = NULL; - - if ((pbpctl_dev->bp_caps & SW_CTL_CAP) - && (pbpctl_dev_b = get_status_port_fn(pbpctl_dev))) { - - send_bypass_clear_pulse(pbpctl_dev_b, 1); - return 0; - } else - return BP_NOT_CAP; -} - -int bypass_flag_status(bpctl_dev_t *pbpctl_dev) -{ - - if ((pbpctl_dev->bp_caps & BP_CAP)) { - if (pbpctl_dev->bp_ext_ver >= PXG2BPI_VER) { - return ((((read_reg(pbpctl_dev, STATUS_REG_ADDR)) & - BYPASS_FLAG_MASK) == - BYPASS_FLAG_MASK) ? 1 : 0); - } - } - return BP_NOT_CAP; -} - -int bypass_flag_status_clear(bpctl_dev_t *pbpctl_dev) -{ - - if (pbpctl_dev->bp_caps & BP_CAP) { - if (pbpctl_dev->bp_ext_ver >= PXG2BPI_VER) { - uint32_t status_reg = 0; - status_reg = read_reg(pbpctl_dev, STATUS_REG_ADDR); - write_reg(pbpctl_dev, status_reg & ~BYPASS_FLAG_MASK, - STATUS_REG_ADDR); - return 0; - } - } - return BP_NOT_CAP; -} - -int bypass_change_status(bpctl_dev_t *pbpctl_dev) -{ - int ret = BP_NOT_CAP; - - if (pbpctl_dev->bp_caps & BP_STATUS_CHANGE_CAP) { - if (pbpctl_dev->bp_ext_ver >= 0x8) { - ret = bypass_flag_status(pbpctl_dev); - bypass_flag_status_clear(pbpctl_dev); - } else if (pbpctl_dev->bp_ext_ver >= PXG2BPI_VER) { - ret = bypass_flag_status(pbpctl_dev); - bypass_flag_status_clear(pbpctl_dev); - } else { - ret = bypass_from_last_read(pbpctl_dev); - bypass_status_clear(pbpctl_dev); - } - } - return ret; -} - -int bypass_off_status(bpctl_dev_t *pbpctl_dev) -{ - - if (pbpctl_dev->bp_caps & BP_CAP) { - if (pbpctl_dev->bp_ext_ver >= PXG2BPI_VER) { - return ((((read_reg(pbpctl_dev, STATUS_REG_ADDR)) & - BYPASS_OFF_MASK) == BYPASS_OFF_MASK) ? 1 : 0); - } - } - return BP_NOT_CAP; -} - -static int bypass_status(bpctl_dev_t *pbpctl_dev) -{ - u32 ctrl_ext = 0; - if (pbpctl_dev->bp_caps & BP_CAP) { - - bpctl_dev_t *pbpctl_dev_b = NULL; - - if (!(pbpctl_dev_b = get_status_port_fn(pbpctl_dev))) - return BP_NOT_CAP; - - if (INTEL_IF_SERIES(pbpctl_dev->subdevice)) { - - if (!pbpctl_dev->bp_status_un) - return (((BPCTL_READ_REG - (pbpctl_dev_b, - CTRL_EXT)) & - BPCTLI_CTRL_EXT_SDP7_DATA) != - 0 ? 1 : 0); - else - return BP_NOT_CAP; - } - if (pbpctl_dev->bp_ext_ver >= 0x8) { - - if (pbpctl_dev->bp_10g9) { - ctrl_ext = BP10G_READ_REG(pbpctl_dev_b, I2CCTL); - BP10G_WRITE_REG(pbpctl_dev_b, I2CCTL, - (ctrl_ext | BP10G_I2C_CLK_OUT)); - return ((BP10G_READ_REG(pbpctl_dev_b, I2CCTL) & - BP10G_I2C_CLK_IN) != 0 ? 0 : 1); - - } else if (pbpctl_dev->bp_540) { - return (((BP10G_READ_REG(pbpctl_dev_b, ESDP)) & - BP10G_SDP0_DATA) != 0 ? 0 : 1); - } - - else if ((pbpctl_dev->bp_fiber5) - || (pbpctl_dev->bp_i80)) { - return (((BPCTL_READ_REG(pbpctl_dev_b, CTRL)) & - BPCTLI_CTRL_SWDPIN0) != 0 ? 0 : 1); - } else if (pbpctl_dev->bp_10gb) { - ctrl_ext = - BP10GB_READ_REG(pbpctl_dev, MISC_REG_GPIO); - BP10GB_WRITE_REG(pbpctl_dev, MISC_REG_GPIO, - (ctrl_ext | BP10GB_GPIO3_OE_P0) - & ~(BP10GB_GPIO3_SET_P0 | - BP10GB_GPIO3_CLR_P0)); - - return (((BP10GB_READ_REG - (pbpctl_dev, - MISC_REG_GPIO)) & BP10GB_GPIO3_P0) != - 0 ? 0 : 1); - } - - else if (!pbpctl_dev->bp_10g) - return (((BPCTL_READ_REG - (pbpctl_dev_b, - CTRL_EXT)) & - BPCTLI_CTRL_EXT_SDP7_DATA) != - 0 ? 0 : 1); - - else { - ctrl_ext = BP10G_READ_REG(pbpctl_dev_b, EODSDP); - BP10G_WRITE_REG(pbpctl_dev_b, EODSDP, - (ctrl_ext | - BP10G_SDP7_DATA_OUT)); - return ((BP10G_READ_REG(pbpctl_dev_b, EODSDP) & - BP10G_SDP7_DATA_IN) != 0 ? 0 : 1); - } - - } else if (pbpctl_dev->media_type == bp_copper) { - - return (((BPCTL_READ_REG(pbpctl_dev_b, CTRL)) & - BPCTLI_CTRL_SWDPIN1) != 0 ? 1 : 0); - } else { - if ((bypass_status_clear(pbpctl_dev)) >= 0) - return bypass_from_last_read(pbpctl_dev); - } - - } - return BP_NOT_CAP; -} - -int default_pwron_status(bpctl_dev_t *pbpctl_dev) -{ - - if (pbpctl_dev->bp_caps & SW_CTL_CAP) { - if (pbpctl_dev->bp_caps & BP_PWUP_CTL_CAP) { - if (pbpctl_dev->bp_ext_ver >= PXG2BPI_VER) { - return ((((read_reg - (pbpctl_dev, - STATUS_REG_ADDR)) & DFLT_PWRON_MASK) - == DFLT_PWRON_MASK) ? 0 : 1); - } - } /*else if ((!pbpctl_dev->bp_caps&BP_DIS_CAP)&& - (pbpctl_dev->bp_caps&BP_PWUP_ON_CAP)) - return 1; */ - } - return BP_NOT_CAP; -} - -static int default_pwroff_status(bpctl_dev_t *pbpctl_dev) -{ - - /*if ((!pbpctl_dev->bp_caps&BP_DIS_CAP)&& - (pbpctl_dev->bp_caps&BP_PWOFF_ON_CAP)) - return 1; */ - if ((pbpctl_dev->bp_caps & SW_CTL_CAP) - && (pbpctl_dev->bp_caps & BP_PWOFF_CTL_CAP)) { - return ((((read_reg(pbpctl_dev, STATUS_REG_ADDR)) & - DFLT_PWROFF_MASK) == DFLT_PWROFF_MASK) ? 0 : 1); - } - return BP_NOT_CAP; -} - -int dis_bypass_cap_status(bpctl_dev_t *pbpctl_dev) -{ - - if (pbpctl_dev->bp_caps & BP_DIS_CAP) { - if (pbpctl_dev->bp_ext_ver >= PXG2BPI_VER) { - return ((((read_reg(pbpctl_dev, STATUS_REG_ADDR)) & - DIS_BYPASS_CAP_MASK) == - DIS_BYPASS_CAP_MASK) ? 1 : 0); - } - } - return BP_NOT_CAP; -} - -int cmd_en_status(bpctl_dev_t *pbpctl_dev) -{ - - if (pbpctl_dev->bp_caps & SW_CTL_CAP) { - if (pbpctl_dev->bp_ext_ver >= PXG2BPI_VER) { - return ((((read_reg(pbpctl_dev, STATUS_REG_ADDR)) & - CMND_EN_MASK) == CMND_EN_MASK) ? 1 : 0); - } - } - return BP_NOT_CAP; -} - -int wdt_en_status(bpctl_dev_t *pbpctl_dev) -{ - - if (pbpctl_dev->bp_caps & WD_CTL_CAP) { - if (pbpctl_dev->bp_ext_ver >= PXG2BPI_VER) { - return ((((read_reg(pbpctl_dev, STATUS_REG_ADDR)) & - WDT_EN_MASK) == WDT_EN_MASK) ? 1 : 0); - } - } - return BP_NOT_CAP; -} - -int wdt_programmed(bpctl_dev_t *pbpctl_dev, int *timeout) -{ - int ret = 0; - if (pbpctl_dev->bp_caps & WD_CTL_CAP) { - if (pbpctl_dev->bp_ext_ver >= PXG2BPI_VER) { - if ((read_reg(pbpctl_dev, STATUS_REG_ADDR)) & - WDT_EN_MASK) { - u8 wdt_val; - wdt_val = read_reg(pbpctl_dev, WDT_REG_ADDR); - *timeout = (1 << wdt_val) * 100; - } else - *timeout = 0; - } else { - int curr_wdt_status = pbpctl_dev->wdt_status; - if (curr_wdt_status == WDT_STATUS_UNKNOWN) - *timeout = -1; - else - *timeout = - curr_wdt_status == - 0 ? 0 : pbpctl_dev->bypass_timer_interval; - }; - } else - ret = BP_NOT_CAP; - return ret; -} - -int bypass_support(bpctl_dev_t *pbpctl_dev) -{ - int ret = 0; - - if (pbpctl_dev->bp_caps & SW_CTL_CAP) { - if (pbpctl_dev->bp_ext_ver >= PXG2TBPI_VER) { - ret = - ((((read_reg(pbpctl_dev, PRODUCT_CAP_REG_ADDR)) & - BYPASS_SUPPORT_MASK) == - BYPASS_SUPPORT_MASK) ? 1 : 0); - } else if (pbpctl_dev->bp_ext_ver == PXG2BPI_VER) - ret = 1; - } else - ret = BP_NOT_CAP; - return ret; -} - -int tap_support(bpctl_dev_t *pbpctl_dev) -{ - int ret = 0; - - if (pbpctl_dev->bp_caps & SW_CTL_CAP) { - if (pbpctl_dev->bp_ext_ver >= PXG2TBPI_VER) { - ret = - ((((read_reg(pbpctl_dev, PRODUCT_CAP_REG_ADDR)) & - TAP_SUPPORT_MASK) == TAP_SUPPORT_MASK) ? 1 : 0); - } else if (pbpctl_dev->bp_ext_ver == PXG2BPI_VER) - ret = 0; - } else - ret = BP_NOT_CAP; - return ret; -} - -int normal_support(bpctl_dev_t *pbpctl_dev) -{ - int ret = BP_NOT_CAP; - - if (pbpctl_dev->bp_caps & SW_CTL_CAP) { - if (pbpctl_dev->bp_ext_ver >= PXG2TBPI_VER) { - ret = - ((((read_reg(pbpctl_dev, PRODUCT_CAP_REG_ADDR)) & - NORMAL_UNSUPPORT_MASK) == - NORMAL_UNSUPPORT_MASK) ? 0 : 1); - } else - ret = 1; - }; - return ret; -} - -int get_bp_prod_caps(bpctl_dev_t *pbpctl_dev) -{ - if ((pbpctl_dev->bp_caps & SW_CTL_CAP) && - (pbpctl_dev->bp_ext_ver >= PXG2TBPI_VER)) - return read_reg(pbpctl_dev, PRODUCT_CAP_REG_ADDR); - return BP_NOT_CAP; - -} - -int tap_flag_status(bpctl_dev_t *pbpctl_dev) -{ - - if (pbpctl_dev->bp_caps & TAP_STATUS_CAP) { - if (pbpctl_dev->bp_ext_ver >= PXG2TBPI_VER) - return ((((read_reg(pbpctl_dev, STATUS_TAP_REG_ADDR)) & - TAP_FLAG_MASK) == TAP_FLAG_MASK) ? 1 : 0); - - } - return BP_NOT_CAP; -} - -int tap_flag_status_clear(bpctl_dev_t *pbpctl_dev) -{ - uint32_t status_reg = 0; - if (pbpctl_dev->bp_caps & TAP_STATUS_CAP) { - if (pbpctl_dev->bp_ext_ver >= PXG2TBPI_VER) { - status_reg = read_reg(pbpctl_dev, STATUS_TAP_REG_ADDR); - write_reg(pbpctl_dev, status_reg & ~TAP_FLAG_MASK, - STATUS_TAP_REG_ADDR); - return 0; - } - } - return BP_NOT_CAP; -} - -int tap_change_status(bpctl_dev_t *pbpctl_dev) -{ - int ret = BP_NOT_CAP; - if (pbpctl_dev->bp_ext_ver >= PXG2TBPI_VER) { - if (pbpctl_dev->bp_caps & TAP_CAP) { - if (pbpctl_dev->bp_caps & BP_CAP) { - ret = tap_flag_status(pbpctl_dev); - tap_flag_status_clear(pbpctl_dev); - } else { - ret = bypass_from_last_read(pbpctl_dev); - bypass_status_clear(pbpctl_dev); - } - } - } - return ret; -} - -int tap_off_status(bpctl_dev_t *pbpctl_dev) -{ - if (pbpctl_dev->bp_caps & TAP_CAP) { - if (pbpctl_dev->bp_ext_ver >= PXG2TBPI_VER) - return ((((read_reg(pbpctl_dev, STATUS_TAP_REG_ADDR)) & - TAP_OFF_MASK) == TAP_OFF_MASK) ? 1 : 0); - } - return BP_NOT_CAP; -} - -int tap_status(bpctl_dev_t *pbpctl_dev) -{ - u32 ctrl_ext = 0; - - if (pbpctl_dev->bp_caps & TAP_CAP) { - bpctl_dev_t *pbpctl_dev_b = NULL; - - if (!(pbpctl_dev_b = get_status_port_fn(pbpctl_dev))) - return BP_NOT_CAP; - - if (pbpctl_dev->bp_ext_ver >= 0x8) { - if (!pbpctl_dev->bp_10g) - return (((BPCTL_READ_REG - (pbpctl_dev_b, - CTRL_EXT)) & - BPCTLI_CTRL_EXT_SDP6_DATA) != - 0 ? 0 : 1); - else { - ctrl_ext = BP10G_READ_REG(pbpctl_dev_b, EODSDP); - BP10G_WRITE_REG(pbpctl_dev_b, EODSDP, - (ctrl_ext | - BP10G_SDP6_DATA_OUT)); - return ((BP10G_READ_REG(pbpctl_dev_b, EODSDP) & - BP10G_SDP6_DATA_IN) != 0 ? 0 : 1); - } - - } else if (pbpctl_dev->media_type == bp_copper) - return (((BPCTL_READ_REG(pbpctl_dev, CTRL)) & - BPCTLI_CTRL_SWDPIN0) != 0 ? 1 : 0); - else { - if ((bypass_status_clear(pbpctl_dev)) >= 0) - return bypass_from_last_read(pbpctl_dev); - } - - } - return BP_NOT_CAP; -} - -int default_pwron_tap_status(bpctl_dev_t *pbpctl_dev) -{ - if (pbpctl_dev->bp_caps & TAP_PWUP_CTL_CAP) { - if (pbpctl_dev->bp_ext_ver >= PXG2TBPI_VER) - return ((((read_reg(pbpctl_dev, STATUS_TAP_REG_ADDR)) & - DFLT_PWRON_TAP_MASK) == - DFLT_PWRON_TAP_MASK) ? 1 : 0); - } - return BP_NOT_CAP; -} - -int dis_tap_cap_status(bpctl_dev_t *pbpctl_dev) -{ - if (pbpctl_dev->bp_caps & TAP_PWUP_CTL_CAP) { - if (pbpctl_dev->bp_ext_ver >= PXG2TBPI_VER) - return ((((read_reg(pbpctl_dev, STATUS_TAP_REG_ADDR)) & - DIS_TAP_CAP_MASK) == - DIS_TAP_CAP_MASK) ? 1 : 0); - } - return BP_NOT_CAP; -} - -int disc_flag_status(bpctl_dev_t *pbpctl_dev) -{ - - if (pbpctl_dev->bp_caps & DISC_CAP) { - if (pbpctl_dev->bp_ext_ver >= 0x8) - return ((((read_reg(pbpctl_dev, STATUS_DISC_REG_ADDR)) & - DISC_FLAG_MASK) == DISC_FLAG_MASK) ? 1 : 0); - - } - return BP_NOT_CAP; -} - -int disc_flag_status_clear(bpctl_dev_t *pbpctl_dev) -{ - uint32_t status_reg = 0; - if (pbpctl_dev->bp_caps & DISC_CAP) { - if (pbpctl_dev->bp_ext_ver >= 0x8) { - status_reg = read_reg(pbpctl_dev, STATUS_DISC_REG_ADDR); - write_reg(pbpctl_dev, status_reg & ~DISC_FLAG_MASK, - STATUS_DISC_REG_ADDR); - return BP_OK; - } - } - return BP_NOT_CAP; -} - -int disc_change_status(bpctl_dev_t *pbpctl_dev) -{ - int ret = BP_NOT_CAP; - if (pbpctl_dev->bp_caps & DISC_CAP) { - ret = disc_flag_status(pbpctl_dev); - disc_flag_status_clear(pbpctl_dev); - return ret; - } - return BP_NOT_CAP; -} - -int disc_off_status(bpctl_dev_t *pbpctl_dev) -{ - bpctl_dev_t *pbpctl_dev_b = NULL; - u32 ctrl_ext = 0; - - if (pbpctl_dev->bp_caps & DISC_CAP) { - if (!(pbpctl_dev_b = get_status_port_fn(pbpctl_dev))) - return BP_NOT_CAP; - if (DISCF_IF_SERIES(pbpctl_dev->subdevice)) - return ((((read_reg(pbpctl_dev, STATUS_DISC_REG_ADDR)) & - DISC_OFF_MASK) == DISC_OFF_MASK) ? 1 : 0); - - if (pbpctl_dev->bp_i80) { - return (((BPCTL_READ_REG(pbpctl_dev_b, CTRL_EXT)) & - BPCTLI_CTRL_EXT_SDP6_DATA) != 0 ? 1 : 0); - - } - if (pbpctl_dev->bp_540) { - ctrl_ext = BP10G_READ_REG(pbpctl_dev_b, ESDP); - return ((BP10G_READ_REG(pbpctl_dev_b, ESDP) & - BP10G_SDP2_DATA) != 0 ? 1 : 0); - - } - if (pbpctl_dev->media_type == bp_copper) { - -#if 0 - return ((((read_reg(pbpctl_dev, STATUS_DISC_REG_ADDR)) & - DISC_OFF_MASK) == DISC_OFF_MASK) ? 1 : 0); -#endif - if (!pbpctl_dev->bp_10g) - return (((BPCTL_READ_REG(pbpctl_dev_b, CTRL)) & - BPCTLI_CTRL_SWDPIN1) != 0 ? 1 : 0); - else - return ((BP10G_READ_REG(pbpctl_dev_b, ESDP) & - BP10G_SDP1_DATA) != 0 ? 1 : 0); - - } else { - - if (pbpctl_dev->bp_10g9) { - ctrl_ext = BP10G_READ_REG(pbpctl_dev_b, I2CCTL); - BP10G_WRITE_REG(pbpctl_dev_b, I2CCTL, - (ctrl_ext | - BP10G_I2C_DATA_OUT)); - return ((BP10G_READ_REG(pbpctl_dev_b, I2CCTL) & - BP10G_I2C_DATA_IN) != 0 ? 1 : 0); - - } else if (pbpctl_dev->bp_fiber5) { - return (((BPCTL_READ_REG(pbpctl_dev_b, CTRL)) & - BPCTLI_CTRL_SWDPIN1) != 0 ? 1 : 0); - } else if (pbpctl_dev->bp_10gb) { - ctrl_ext = - BP10GB_READ_REG(pbpctl_dev, MISC_REG_GPIO); - BP10GB_WRITE_REG(pbpctl_dev, MISC_REG_GPIO, - (ctrl_ext | BP10GB_GPIO3_OE_P1) - & ~(BP10GB_GPIO3_SET_P1 | - BP10GB_GPIO3_CLR_P1)); - - return (((BP10GB_READ_REG - (pbpctl_dev, - MISC_REG_GPIO)) & BP10GB_GPIO3_P1) != - 0 ? 1 : 0); - } - if (!pbpctl_dev->bp_10g) { - - return (((BPCTL_READ_REG - (pbpctl_dev_b, - CTRL_EXT)) & - BPCTLI_CTRL_EXT_SDP6_DATA) != - 0 ? 1 : 0); - } else { - ctrl_ext = BP10G_READ_REG(pbpctl_dev_b, EODSDP); - BP10G_WRITE_REG(pbpctl_dev_b, EODSDP, - (ctrl_ext | - BP10G_SDP6_DATA_OUT)); - return (((BP10G_READ_REG(pbpctl_dev_b, EODSDP)) - & BP10G_SDP6_DATA_IN) != 0 ? 1 : 0); - } - - } - } - return BP_NOT_CAP; -} - -static int disc_status(bpctl_dev_t *pbpctl_dev) -{ - int ctrl = 0; - if (pbpctl_dev->bp_caps & DISC_CAP) { - - if ((ctrl = disc_off_status(pbpctl_dev)) < 0) - return ctrl; - return ((ctrl == 0) ? 1 : 0); - - } - return BP_NOT_CAP; -} - -int default_pwron_disc_status(bpctl_dev_t *pbpctl_dev) -{ - if (pbpctl_dev->bp_caps & DISC_PWUP_CTL_CAP) { - if (pbpctl_dev->bp_ext_ver >= 0x8) - return ((((read_reg(pbpctl_dev, STATUS_DISC_REG_ADDR)) & - DFLT_PWRON_DISC_MASK) == - DFLT_PWRON_DISC_MASK) ? 1 : 0); - } - return BP_NOT_CAP; -} - -int dis_disc_cap_status(bpctl_dev_t *pbpctl_dev) -{ - if (pbpctl_dev->bp_caps & DIS_DISC_CAP) { - if (pbpctl_dev->bp_ext_ver >= 0x8) - return ((((read_reg(pbpctl_dev, STATUS_DISC_REG_ADDR)) & - DIS_DISC_CAP_MASK) == - DIS_DISC_CAP_MASK) ? 1 : 0); - } - return BP_NOT_CAP; -} - -int disc_port_status(bpctl_dev_t *pbpctl_dev) -{ - int ret = BP_NOT_CAP; - bpctl_dev_t *pbpctl_dev_m; - - if ((is_bypass_fn(pbpctl_dev)) == 1) - pbpctl_dev_m = pbpctl_dev; - else - pbpctl_dev_m = get_master_port_fn(pbpctl_dev); - if (pbpctl_dev_m == NULL) - return BP_NOT_CAP; - - if (pbpctl_dev_m->bp_caps_ex & DISC_PORT_CAP_EX) { - if (is_bypass_fn(pbpctl_dev) == 1) { - return ((((read_reg(pbpctl_dev, STATUS_TAP_REG_ADDR)) & - TX_DISA_MASK) == TX_DISA_MASK) ? 1 : 0); - } else - return ((((read_reg(pbpctl_dev, STATUS_TAP_REG_ADDR)) & - TX_DISB_MASK) == TX_DISB_MASK) ? 1 : 0); - - } - return ret; -} - -int default_pwron_disc_port_status(bpctl_dev_t *pbpctl_dev) -{ - int ret = BP_NOT_CAP; - bpctl_dev_t *pbpctl_dev_m; - - if ((is_bypass_fn(pbpctl_dev)) == 1) - pbpctl_dev_m = pbpctl_dev; - else - pbpctl_dev_m = get_master_port_fn(pbpctl_dev); - if (pbpctl_dev_m == NULL) - return BP_NOT_CAP; - - if (pbpctl_dev_m->bp_caps_ex & DISC_PORT_CAP_EX) { - if (is_bypass_fn(pbpctl_dev) == 1) - return ret; - /* return((((read_reg(pbpctl_dev,STATUS_TAP_REG_ADDR)) & TX_DISA_MASK)==TX_DISA_MASK)?1:0); */ - else - return ret; - /* return((((read_reg(pbpctl_dev,STATUS_TAP_REG_ADDR)) & TX_DISA_MASK)==TX_DISA_MASK)?1:0); */ - - } - return ret; -} - -int wdt_exp_mode_status(bpctl_dev_t *pbpctl_dev) -{ - if (pbpctl_dev->bp_caps & WD_CTL_CAP) { - if (pbpctl_dev->bp_ext_ver <= PXG2BPI_VER) - return 0; /* bypass mode */ - else if (pbpctl_dev->bp_ext_ver == PXG2TBPI_VER) - return 1; /* tap mode */ - else if (pbpctl_dev->bp_ext_ver >= PXE2TBPI_VER) { - if (pbpctl_dev->bp_ext_ver >= 0x8) { - if (((read_reg - (pbpctl_dev, - STATUS_DISC_REG_ADDR)) & - WDTE_DISC_BPN_MASK) == WDTE_DISC_BPN_MASK) - return 2; - } - return ((((read_reg(pbpctl_dev, STATUS_TAP_REG_ADDR)) & - WDTE_TAP_BPN_MASK) == - WDTE_TAP_BPN_MASK) ? 1 : 0); - } - } - return BP_NOT_CAP; -} - -int tpl2_flag_status(bpctl_dev_t *pbpctl_dev) -{ - - if (pbpctl_dev->bp_caps_ex & TPL2_CAP_EX) { - return ((((read_reg(pbpctl_dev, STATUS_DISC_REG_ADDR)) & - TPL2_FLAG_MASK) == TPL2_FLAG_MASK) ? 1 : 0); - - } - return BP_NOT_CAP; -} - -int tpl_hw_status(bpctl_dev_t *pbpctl_dev) -{ - bpctl_dev_t *pbpctl_dev_b = NULL; - - if (!(pbpctl_dev_b = get_status_port_fn(pbpctl_dev))) - return BP_NOT_CAP; - - if (TPL_IF_SERIES(pbpctl_dev->subdevice)) - return (((BPCTL_READ_REG(pbpctl_dev, CTRL)) & - BPCTLI_CTRL_SWDPIN0) != 0 ? 1 : 0); - return BP_NOT_CAP; -} - - -int bp_wait_at_pwup_status(bpctl_dev_t *pbpctl_dev) -{ - if (pbpctl_dev->bp_caps & SW_CTL_CAP) { - if (pbpctl_dev->bp_ext_ver >= 0x8) - return ((((read_reg(pbpctl_dev, CONT_CONFIG_REG_ADDR)) & - WAIT_AT_PWUP_MASK) == - WAIT_AT_PWUP_MASK) ? 1 : 0); - } - return BP_NOT_CAP; -} - -int bp_hw_reset_status(bpctl_dev_t *pbpctl_dev) -{ - - if (pbpctl_dev->bp_caps & SW_CTL_CAP) { - - if (pbpctl_dev->bp_ext_ver >= 0x8) - return ((((read_reg(pbpctl_dev, CONT_CONFIG_REG_ADDR)) & - EN_HW_RESET_MASK) == - EN_HW_RESET_MASK) ? 1 : 0); - } - return BP_NOT_CAP; -} - - -int std_nic_status(bpctl_dev_t *pbpctl_dev) -{ - int status_val = 0; - - if (pbpctl_dev->bp_caps & STD_NIC_CAP) { - if (INTEL_IF_SERIES(pbpctl_dev->subdevice)) - return BP_NOT_CAP; - if (pbpctl_dev->bp_ext_ver >= BP_FW_EXT_VER8) { - return ((((read_reg(pbpctl_dev, STATUS_DISC_REG_ADDR)) & - STD_NIC_ON_MASK) == STD_NIC_ON_MASK) ? 1 : 0); - } - - if (pbpctl_dev->bp_ext_ver >= PXG2BPI_VER) { - if (pbpctl_dev->bp_caps & BP_CAP) { - status_val = - read_reg(pbpctl_dev, STATUS_REG_ADDR); - if (((!(status_val & WDT_EN_MASK)) - && ((status_val & STD_NIC_MASK) == - STD_NIC_MASK))) - status_val = 1; - else - return 0; - } - if (pbpctl_dev->bp_caps & TAP_CAP) { - status_val = - read_reg(pbpctl_dev, STATUS_TAP_REG_ADDR); - if ((status_val & STD_NIC_TAP_MASK) == - STD_NIC_TAP_MASK) - status_val = 1; - else - return 0; - } - if (pbpctl_dev->bp_caps & TAP_CAP) { - if ((disc_off_status(pbpctl_dev))) - status_val = 1; - else - return 0; - } - - return status_val; - } - } - return BP_NOT_CAP; -} - -/******************************************************/ -/**************SW_INIT*********************************/ -/******************************************************/ -void bypass_caps_init(bpctl_dev_t *pbpctl_dev) -{ - u_int32_t ctrl_ext = 0; - bpctl_dev_t *pbpctl_dev_m = NULL; - -#ifdef BYPASS_DEBUG - int ret = 0; - if (!(INTEL_IF_SERIES(adapter->bp_device_block.subdevice))) { - ret = read_reg(pbpctl_dev, VER_REG_ADDR); - printk("VER_REG reg1=%x\n", ret); - ret = read_reg(pbpctl_dev, PRODUCT_CAP_REG_ADDR); - printk("PRODUCT_CAP reg=%x\n", ret); - ret = read_reg(pbpctl_dev, STATUS_TAP_REG_ADDR); - printk("STATUS_TAP reg1=%x\n", ret); - ret = read_reg(pbpctl_dev, 0x7); - printk("SIG_REG reg1=%x\n", ret); - ret = read_reg(pbpctl_dev, STATUS_REG_ADDR); - printk("STATUS_REG_ADDR=%x\n", ret); - ret = read_reg(pbpctl_dev, WDT_REG_ADDR); - printk("WDT_REG_ADDR=%x\n", ret); - ret = read_reg(pbpctl_dev, TMRL_REG_ADDR); - printk("TMRL_REG_ADDR=%x\n", ret); - ret = read_reg(pbpctl_dev, TMRH_REG_ADDR); - printk("TMRH_REG_ADDR=%x\n", ret); - } -#endif - if ((pbpctl_dev->bp_fiber5) || (pbpctl_dev->bp_10g9)) { - pbpctl_dev->media_type = bp_fiber; - } else if (pbpctl_dev->bp_10gb) { - if (BP10GB_CX4_SERIES(pbpctl_dev->subdevice)) - pbpctl_dev->media_type = bp_cx4; - else - pbpctl_dev->media_type = bp_fiber; - - } - - else if (pbpctl_dev->bp_540) - pbpctl_dev->media_type = bp_none; - else if (!pbpctl_dev->bp_10g) { - - ctrl_ext = BPCTL_READ_REG(pbpctl_dev, CTRL_EXT); - if ((ctrl_ext & BPCTLI_CTRL_EXT_LINK_MODE_MASK) == 0x0) - pbpctl_dev->media_type = bp_copper; - else - pbpctl_dev->media_type = bp_fiber; - - } else { - if (BP10G_CX4_SERIES(pbpctl_dev->subdevice)) - pbpctl_dev->media_type = bp_cx4; - else - pbpctl_dev->media_type = bp_fiber; - } - - if (is_bypass_fn(pbpctl_dev)) { - - pbpctl_dev->bp_caps |= BP_PWOFF_ON_CAP; - if (pbpctl_dev->media_type == bp_fiber) - pbpctl_dev->bp_caps |= - (TX_CTL_CAP | TX_STATUS_CAP | TPL_CAP); - - if (TPL_IF_SERIES(pbpctl_dev->subdevice)) { - pbpctl_dev->bp_caps |= TPL_CAP; - } - - if (INTEL_IF_SERIES(pbpctl_dev->subdevice)) { - pbpctl_dev->bp_caps |= - (BP_CAP | BP_STATUS_CAP | SW_CTL_CAP | - BP_PWUP_ON_CAP | BP_PWUP_OFF_CAP | BP_PWOFF_OFF_CAP - | WD_CTL_CAP | WD_STATUS_CAP | STD_NIC_CAP | - WD_TIMEOUT_CAP); - - pbpctl_dev->bp_ext_ver = OLD_IF_VER; - return; - } - - if ((pbpctl_dev->bp_fw_ver == 0xff) && - OLD_IF_SERIES(pbpctl_dev->subdevice)) { - - pbpctl_dev->bp_caps |= - (BP_CAP | BP_STATUS_CAP | BP_STATUS_CHANGE_CAP | - SW_CTL_CAP | BP_PWUP_ON_CAP | WD_CTL_CAP | - WD_STATUS_CAP | WD_TIMEOUT_CAP); - - pbpctl_dev->bp_ext_ver = OLD_IF_VER; - return; - } - - else { - switch (pbpctl_dev->bp_fw_ver) { - case BP_FW_VER_A0: - case BP_FW_VER_A1:{ - pbpctl_dev->bp_ext_ver = - (pbpctl_dev-> - bp_fw_ver & EXT_VER_MASK); - break; - } - default:{ - if ((bypass_sign_check(pbpctl_dev)) != - 1) { - pbpctl_dev->bp_caps = 0; - return; - } - pbpctl_dev->bp_ext_ver = - (pbpctl_dev-> - bp_fw_ver & EXT_VER_MASK); - } - } - } - - if (pbpctl_dev->bp_ext_ver == PXG2BPI_VER) - pbpctl_dev->bp_caps |= - (BP_CAP | BP_STATUS_CAP | BP_STATUS_CHANGE_CAP | - SW_CTL_CAP | BP_DIS_CAP | BP_DIS_STATUS_CAP | - BP_PWUP_ON_CAP | BP_PWUP_OFF_CAP | BP_PWUP_CTL_CAP - | WD_CTL_CAP | STD_NIC_CAP | WD_STATUS_CAP | - WD_TIMEOUT_CAP); - else if (pbpctl_dev->bp_ext_ver >= PXG2TBPI_VER) { - int cap_reg; - - pbpctl_dev->bp_caps |= - (SW_CTL_CAP | WD_CTL_CAP | WD_STATUS_CAP | - WD_TIMEOUT_CAP); - cap_reg = get_bp_prod_caps(pbpctl_dev); - - if ((cap_reg & NORMAL_UNSUPPORT_MASK) == - NORMAL_UNSUPPORT_MASK) - pbpctl_dev->bp_caps |= NIC_CAP_NEG; - else - pbpctl_dev->bp_caps |= STD_NIC_CAP; - - if ((normal_support(pbpctl_dev)) == 1) - - pbpctl_dev->bp_caps |= STD_NIC_CAP; - - else - pbpctl_dev->bp_caps |= NIC_CAP_NEG; - if ((cap_reg & BYPASS_SUPPORT_MASK) == - BYPASS_SUPPORT_MASK) { - pbpctl_dev->bp_caps |= - (BP_CAP | BP_STATUS_CAP | - BP_STATUS_CHANGE_CAP | BP_DIS_CAP | - BP_DIS_STATUS_CAP | BP_PWUP_ON_CAP | - BP_PWUP_OFF_CAP | BP_PWUP_CTL_CAP); - if (pbpctl_dev->bp_ext_ver >= BP_FW_EXT_VER7) - pbpctl_dev->bp_caps |= - BP_PWOFF_ON_CAP | BP_PWOFF_OFF_CAP | - BP_PWOFF_CTL_CAP; - } - if ((cap_reg & TAP_SUPPORT_MASK) == TAP_SUPPORT_MASK) { - pbpctl_dev->bp_caps |= - (TAP_CAP | TAP_STATUS_CAP | - TAP_STATUS_CHANGE_CAP | TAP_DIS_CAP | - TAP_DIS_STATUS_CAP | TAP_PWUP_ON_CAP | - TAP_PWUP_OFF_CAP | TAP_PWUP_CTL_CAP); - } - if (pbpctl_dev->bp_ext_ver >= BP_FW_EXT_VER8) { - if ((cap_reg & DISC_SUPPORT_MASK) == - DISC_SUPPORT_MASK) - pbpctl_dev->bp_caps |= - (DISC_CAP | DISC_DIS_CAP | - DISC_PWUP_CTL_CAP); - if ((cap_reg & TPL2_SUPPORT_MASK) == - TPL2_SUPPORT_MASK) { - pbpctl_dev->bp_caps_ex |= TPL2_CAP_EX; - pbpctl_dev->bp_caps |= TPL_CAP; - pbpctl_dev->bp_tpl_flag = - tpl2_flag_status(pbpctl_dev); - } - - } - - if (pbpctl_dev->bp_ext_ver >= BP_FW_EXT_VER9) { - if ((cap_reg & DISC_PORT_SUPPORT_MASK) == - DISC_PORT_SUPPORT_MASK) { - pbpctl_dev->bp_caps_ex |= - DISC_PORT_CAP_EX; - pbpctl_dev->bp_caps |= - (TX_CTL_CAP | TX_STATUS_CAP); - } - - } - - } - if (pbpctl_dev->bp_ext_ver >= PXG2BPI_VER) { - if ((read_reg(pbpctl_dev, STATUS_REG_ADDR)) & - WDT_EN_MASK) - pbpctl_dev->wdt_status = WDT_STATUS_EN; - else - pbpctl_dev->wdt_status = WDT_STATUS_DIS; - } - - } else if ((P2BPFI_IF_SERIES(pbpctl_dev->subdevice)) || - (PEGF5_IF_SERIES(pbpctl_dev->subdevice)) || - (PEGF80_IF_SERIES(pbpctl_dev->subdevice)) || - (BP10G9_IF_SERIES(pbpctl_dev->subdevice))) { - pbpctl_dev->bp_caps |= (TX_CTL_CAP | TX_STATUS_CAP); - } - if ((pbpctl_dev->subdevice & 0xa00) == 0xa00) - pbpctl_dev->bp_caps |= (TX_CTL_CAP | TX_STATUS_CAP); - if (PEG5_IF_SERIES(pbpctl_dev->subdevice)) - pbpctl_dev->bp_caps |= (TX_CTL_CAP | TX_STATUS_CAP); - - if (BP10GB_IF_SERIES(pbpctl_dev->subdevice)) { - pbpctl_dev->bp_caps &= ~(TX_CTL_CAP | TX_STATUS_CAP); - } - pbpctl_dev_m = get_master_port_fn(pbpctl_dev); - if (pbpctl_dev_m != NULL) { - int cap_reg = 0; - if (pbpctl_dev_m->bp_ext_ver >= 0x9) { - cap_reg = get_bp_prod_caps(pbpctl_dev_m); - if ((cap_reg & DISC_PORT_SUPPORT_MASK) == - DISC_PORT_SUPPORT_MASK) - pbpctl_dev->bp_caps |= - (TX_CTL_CAP | TX_STATUS_CAP); - pbpctl_dev->bp_caps_ex |= DISC_PORT_CAP_EX; - } - } -} - -int bypass_off_init(bpctl_dev_t *pbpctl_dev) -{ - int ret = 0; - - if ((ret = cmnd_on(pbpctl_dev)) < 0) - return ret; - if (INTEL_IF_SERIES(pbpctl_dev->subdevice)) - return dis_bypass_cap(pbpctl_dev); - wdt_off(pbpctl_dev); - if (pbpctl_dev->bp_caps & BP_CAP) - bypass_off(pbpctl_dev); - if (pbpctl_dev->bp_caps & TAP_CAP) - tap_off(pbpctl_dev); - cmnd_off(pbpctl_dev); - return 0; -} - -void remove_bypass_wd_auto(bpctl_dev_t *pbpctl_dev) -{ -#ifdef BP_SELF_TEST - bpctl_dev_t *pbpctl_dev_sl = NULL; -#endif - - if (pbpctl_dev->bp_caps & WD_CTL_CAP) { - - del_timer_sync(&pbpctl_dev->bp_timer); -#ifdef BP_SELF_TEST - pbpctl_dev_sl = get_status_port_fn(pbpctl_dev); -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,31)) - if (pbpctl_dev_sl && (pbpctl_dev_sl->ndev) - && (pbpctl_dev_sl->ndev->hard_start_xmit) - && (pbpctl_dev_sl->hard_start_xmit_save)) { - rtnl_lock(); - pbpctl_dev_sl->ndev->hard_start_xmit = - pbpctl_dev_sl->hard_start_xmit_save; - rtnl_unlock(); - } -#else - if (pbpctl_dev_sl && (pbpctl_dev_sl->ndev)) { - if ((pbpctl_dev_sl->ndev->netdev_ops) - && (pbpctl_dev_sl->old_ops)) { - rtnl_lock(); - pbpctl_dev_sl->ndev->netdev_ops = - pbpctl_dev_sl->old_ops; - pbpctl_dev_sl->old_ops = NULL; - - rtnl_unlock(); - - } - - } - -#endif -#endif - } - -} - -int init_bypass_wd_auto(bpctl_dev_t *pbpctl_dev) -{ - if (pbpctl_dev->bp_caps & WD_CTL_CAP) { - init_timer(&pbpctl_dev->bp_timer); - pbpctl_dev->bp_timer.function = &wd_reset_timer; - pbpctl_dev->bp_timer.data = (unsigned long)pbpctl_dev; - return 1; - } - return BP_NOT_CAP; -} - -#ifdef BP_SELF_TEST -int bp_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) -{ - bpctl_dev_t *pbpctl_dev = NULL, *pbpctl_dev_m = NULL; - int idx_dev = 0; - struct ethhdr *eth = (struct ethhdr *)skb->data; - - for (idx_dev = 0; - ((bpctl_dev_arr[idx_dev].ndev != NULL) && (idx_dev < device_num)); - idx_dev++) { - if (bpctl_dev_arr[idx_dev].ndev == dev) { - pbpctl_dev = &bpctl_dev_arr[idx_dev]; - break; - } - } - if (!pbpctl_dev) - return 1; - if ((htons(ETH_P_BPTEST) == eth->h_proto)) { - - pbpctl_dev_m = get_master_port_fn(pbpctl_dev); - if (pbpctl_dev_m) { - - if (bypass_status(pbpctl_dev_m)) { - cmnd_on(pbpctl_dev_m); - bypass_off(pbpctl_dev_m); - cmnd_off(pbpctl_dev_m); - } - wdt_timer_reload(pbpctl_dev_m); - } - dev_kfree_skb_irq(skb); - return 0; - } - return pbpctl_dev->hard_start_xmit_save(skb, dev); -} -#endif - -int set_bypass_wd_auto(bpctl_dev_t *pbpctl_dev, unsigned int param) -{ - if (pbpctl_dev->bp_caps & WD_CTL_CAP) { - if (pbpctl_dev->reset_time != param) { - if (INTEL_IF_SERIES(pbpctl_dev->subdevice)) - pbpctl_dev->reset_time = - (param < - WDT_AUTO_MIN_INT) ? WDT_AUTO_MIN_INT : - param; - else - pbpctl_dev->reset_time = param; - if (param) - mod_timer(&pbpctl_dev->bp_timer, jiffies); - } - return 0; - } - return BP_NOT_CAP; -} - -int get_bypass_wd_auto(bpctl_dev_t *pbpctl_dev) -{ - - if (pbpctl_dev->bp_caps & WD_CTL_CAP) { - return pbpctl_dev->reset_time; - } - return BP_NOT_CAP; -} - -#ifdef BP_SELF_TEST - -int set_bp_self_test(bpctl_dev_t *pbpctl_dev, unsigned int param) -{ - bpctl_dev_t *pbpctl_dev_sl = NULL; - - if (pbpctl_dev->bp_caps & WD_CTL_CAP) { - pbpctl_dev->bp_self_test_flag = param == 0 ? 0 : 1; - pbpctl_dev_sl = get_status_port_fn(pbpctl_dev); -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,31)) - if ((pbpctl_dev_sl->ndev) && - (pbpctl_dev_sl->ndev->hard_start_xmit)) { - rtnl_lock(); - if (pbpctl_dev->bp_self_test_flag == 1) { - - pbpctl_dev_sl->hard_start_xmit_save = - pbpctl_dev_sl->ndev->hard_start_xmit; - pbpctl_dev_sl->ndev->hard_start_xmit = - bp_hard_start_xmit; - } else if (pbpctl_dev_sl->hard_start_xmit_save) { - pbpctl_dev_sl->ndev->hard_start_xmit = - pbpctl_dev_sl->hard_start_xmit_save; - } - rtnl_unlock(); - } -#else - if ((pbpctl_dev_sl->ndev) && (pbpctl_dev_sl->ndev->netdev_ops)) { - rtnl_lock(); - if (pbpctl_dev->bp_self_test_flag == 1) { - - pbpctl_dev_sl->old_ops = - pbpctl_dev_sl->ndev->netdev_ops; - pbpctl_dev_sl->new_ops = - *pbpctl_dev_sl->old_ops; - pbpctl_dev_sl->new_ops.ndo_start_xmit = - bp_hard_start_xmit; - pbpctl_dev_sl->ndev->netdev_ops = - &pbpctl_dev_sl->new_ops; - - } else if (pbpctl_dev_sl->old_ops) { - pbpctl_dev_sl->ndev->netdev_ops = - pbpctl_dev_sl->old_ops; - pbpctl_dev_sl->old_ops = NULL; - } - rtnl_unlock(); - } -#endif - - set_bypass_wd_auto(pbpctl_dev, param); - return 0; - } - return BP_NOT_CAP; -} - -int get_bp_self_test(bpctl_dev_t *pbpctl_dev) -{ - - if (pbpctl_dev->bp_caps & WD_CTL_CAP) { - if (pbpctl_dev->bp_self_test_flag == 1) - return pbpctl_dev->reset_time; - else - return 0; - } - return BP_NOT_CAP; -} - -#endif - -/**************************************************************/ -/************************* API ********************************/ -/**************************************************************/ - -int is_bypass_fn(bpctl_dev_t *pbpctl_dev) -{ - if (!pbpctl_dev) - return -1; - - return (((pbpctl_dev->func == 0) || (pbpctl_dev->func == 2)) ? 1 : 0); -} - -int set_bypass_fn(bpctl_dev_t *pbpctl_dev, int bypass_mode) -{ - int ret = 0; - - if (!(pbpctl_dev->bp_caps & BP_CAP)) - return BP_NOT_CAP; - if ((ret = cmnd_on(pbpctl_dev)) < 0) - return ret; - if (!bypass_mode) - ret = bypass_off(pbpctl_dev); - else - ret = bypass_on(pbpctl_dev); - cmnd_off(pbpctl_dev); - - return ret; -} - -int get_bypass_fn(bpctl_dev_t *pbpctl_dev) -{ - return bypass_status(pbpctl_dev); -} - -int get_bypass_change_fn(bpctl_dev_t *pbpctl_dev) -{ - if (!pbpctl_dev) - return -1; - - return bypass_change_status(pbpctl_dev); -} - -int set_dis_bypass_fn(bpctl_dev_t *pbpctl_dev, int dis_param) -{ - int ret = 0; - if (!pbpctl_dev) - return -1; - - if (!(pbpctl_dev->bp_caps & BP_DIS_CAP)) - return BP_NOT_CAP; - if ((ret = cmnd_on(pbpctl_dev)) < 0) - return ret; - if (dis_param) - ret = dis_bypass_cap(pbpctl_dev); - else - ret = en_bypass_cap(pbpctl_dev); - cmnd_off(pbpctl_dev); - return ret; -} - -int get_dis_bypass_fn(bpctl_dev_t *pbpctl_dev) -{ - if (!pbpctl_dev) - return -1; - - return dis_bypass_cap_status(pbpctl_dev); -} - -int set_bypass_pwoff_fn(bpctl_dev_t *pbpctl_dev, int bypass_mode) -{ - int ret = 0; - if (!pbpctl_dev) - return -1; - - if (!(pbpctl_dev->bp_caps & BP_PWOFF_CTL_CAP)) - return BP_NOT_CAP; - if ((ret = cmnd_on(pbpctl_dev)) < 0) - return ret; - if (bypass_mode) - ret = bypass_state_pwroff(pbpctl_dev); - else - ret = normal_state_pwroff(pbpctl_dev); - cmnd_off(pbpctl_dev); - return ret; -} - -int get_bypass_pwoff_fn(bpctl_dev_t *pbpctl_dev) -{ - if (!pbpctl_dev) - return -1; - - return default_pwroff_status(pbpctl_dev); -} - -int set_bypass_pwup_fn(bpctl_dev_t *pbpctl_dev, int bypass_mode) -{ - int ret = 0; - if (!pbpctl_dev) - return -1; - - if (!(pbpctl_dev->bp_caps & BP_PWUP_CTL_CAP)) - return BP_NOT_CAP; - if ((ret = cmnd_on(pbpctl_dev)) < 0) - return ret; - if (bypass_mode) - ret = bypass_state_pwron(pbpctl_dev); - else - ret = normal_state_pwron(pbpctl_dev); - cmnd_off(pbpctl_dev); - return ret; -} - -int get_bypass_pwup_fn(bpctl_dev_t *pbpctl_dev) -{ - if (!pbpctl_dev) - return -1; - - return default_pwron_status(pbpctl_dev); -} - -int set_bypass_wd_fn(bpctl_dev_t *pbpctl_dev, int timeout) -{ - int ret = 0; - if (!pbpctl_dev) - return -1; - - if (!(pbpctl_dev->bp_caps & WD_CTL_CAP)) - return BP_NOT_CAP; - - if ((ret = cmnd_on(pbpctl_dev)) < 0) - return ret; - if (!timeout) - ret = wdt_off(pbpctl_dev); - else { - wdt_on(pbpctl_dev, timeout); - ret = pbpctl_dev->bypass_timer_interval; - } - cmnd_off(pbpctl_dev); - return ret; -} - -int get_bypass_wd_fn(bpctl_dev_t *pbpctl_dev, int *timeout) -{ - if (!pbpctl_dev) - return -1; - - return wdt_programmed(pbpctl_dev, timeout); -} - -int get_wd_expire_time_fn(bpctl_dev_t *pbpctl_dev, int *time_left) -{ - if (!pbpctl_dev) - return -1; - - return wdt_timer(pbpctl_dev, time_left); -} - -int reset_bypass_wd_timer_fn(bpctl_dev_t *pbpctl_dev) -{ - if (!pbpctl_dev) - return -1; - - return wdt_timer_reload(pbpctl_dev); -} - -int get_wd_set_caps_fn(bpctl_dev_t *pbpctl_dev) -{ - int bp_status = 0; - - unsigned int step_value = TIMEOUT_MAX_STEP + 1, bit_cnt = 0; - if (!pbpctl_dev) - return -1; - - if (INTEL_IF_SERIES(pbpctl_dev->subdevice)) - return BP_NOT_CAP; - - while ((step_value >>= 1)) - bit_cnt++; - - if (is_bypass_fn(pbpctl_dev)) { - bp_status = - WD_STEP_COUNT_MASK(bit_cnt) | WDT_STEP_TIME | - WD_MIN_TIME_MASK(TIMEOUT_UNIT / 100); - } else - return -1; - - return bp_status; -} - -int set_std_nic_fn(bpctl_dev_t *pbpctl_dev, int nic_mode) -{ - int ret = 0; - if (!pbpctl_dev) - return -1; - - if (!(pbpctl_dev->bp_caps & STD_NIC_CAP)) - return BP_NOT_CAP; - - if ((ret = cmnd_on(pbpctl_dev)) < 0) - return ret; - if (nic_mode) - ret = std_nic_on(pbpctl_dev); - else - ret = std_nic_off(pbpctl_dev); - cmnd_off(pbpctl_dev); - return ret; -} - -int get_std_nic_fn(bpctl_dev_t *pbpctl_dev) -{ - if (!pbpctl_dev) - return -1; - - return std_nic_status(pbpctl_dev); -} - -int set_tap_fn(bpctl_dev_t *pbpctl_dev, int tap_mode) -{ - if (!pbpctl_dev) - return -1; - - if ((pbpctl_dev->bp_caps & TAP_CAP) && ((cmnd_on(pbpctl_dev)) >= 0)) { - if (!tap_mode) - tap_off(pbpctl_dev); - else - tap_on(pbpctl_dev); - cmnd_off(pbpctl_dev); - return 0; - } - return BP_NOT_CAP; -} - -int get_tap_fn(bpctl_dev_t *pbpctl_dev) -{ - if (!pbpctl_dev) - return -1; - - return tap_status(pbpctl_dev); -} - -int set_tap_pwup_fn(bpctl_dev_t *pbpctl_dev, int tap_mode) -{ - int ret = 0; - if (!pbpctl_dev) - return -1; - - if ((pbpctl_dev->bp_caps & TAP_PWUP_CTL_CAP) - && ((cmnd_on(pbpctl_dev)) >= 0)) { - if (tap_mode) - ret = tap_state_pwron(pbpctl_dev); - else - ret = normal_state_pwron(pbpctl_dev); - cmnd_off(pbpctl_dev); - } else - ret = BP_NOT_CAP; - return ret; -} - -int get_tap_pwup_fn(bpctl_dev_t *pbpctl_dev) -{ - int ret = 0; - if (!pbpctl_dev) - return -1; - - if ((ret = default_pwron_tap_status(pbpctl_dev)) < 0) - return ret; - return ((ret == 0) ? 1 : 0); -} - -int get_tap_change_fn(bpctl_dev_t *pbpctl_dev) -{ - if (!pbpctl_dev) - return -1; - - return tap_change_status(pbpctl_dev); -} - -int set_dis_tap_fn(bpctl_dev_t *pbpctl_dev, int dis_param) -{ - int ret = 0; - if (!pbpctl_dev) - return -1; - - if ((pbpctl_dev->bp_caps & TAP_DIS_CAP) && ((cmnd_on(pbpctl_dev)) >= 0)) { - if (dis_param) - ret = dis_tap_cap(pbpctl_dev); - else - ret = en_tap_cap(pbpctl_dev); - cmnd_off(pbpctl_dev); - return ret; - } else - return BP_NOT_CAP; -} - -int get_dis_tap_fn(bpctl_dev_t *pbpctl_dev) -{ - if (!pbpctl_dev) - return -1; - - return dis_tap_cap_status(pbpctl_dev); -} - -int set_disc_fn(bpctl_dev_t *pbpctl_dev, int disc_mode) -{ - if (!pbpctl_dev) - return -1; - - if ((pbpctl_dev->bp_caps & DISC_CAP) && ((cmnd_on(pbpctl_dev)) >= 0)) { - if (!disc_mode) - disc_off(pbpctl_dev); - else - disc_on(pbpctl_dev); - cmnd_off(pbpctl_dev); - - return BP_OK; - } - return BP_NOT_CAP; -} - -int get_disc_fn(bpctl_dev_t *pbpctl_dev) -{ - int ret = 0; - if (!pbpctl_dev) - return -1; - - ret = disc_status(pbpctl_dev); - - return ret; -} - -int set_disc_pwup_fn(bpctl_dev_t *pbpctl_dev, int disc_mode) -{ - int ret = 0; - if (!pbpctl_dev) - return -1; - - if ((pbpctl_dev->bp_caps & DISC_PWUP_CTL_CAP) - && ((cmnd_on(pbpctl_dev)) >= 0)) { - if (disc_mode) - ret = disc_state_pwron(pbpctl_dev); - else - ret = normal_state_pwron(pbpctl_dev); - cmnd_off(pbpctl_dev); - } else - ret = BP_NOT_CAP; - return ret; -} - -int get_disc_pwup_fn(bpctl_dev_t *pbpctl_dev) -{ - int ret = 0; - if (!pbpctl_dev) - return -1; - - ret = default_pwron_disc_status(pbpctl_dev); - return (ret == 0 ? 1 : (ret < 0 ? BP_NOT_CAP : 0)); -} - -int get_disc_change_fn(bpctl_dev_t *pbpctl_dev) -{ - int ret = 0; - if (!pbpctl_dev) - return -1; - - ret = disc_change_status(pbpctl_dev); - return ret; -} - -int set_dis_disc_fn(bpctl_dev_t *pbpctl_dev, int dis_param) -{ - int ret = 0; - if (!pbpctl_dev) - return -1; - - if ((pbpctl_dev->bp_caps & DISC_DIS_CAP) - && ((cmnd_on(pbpctl_dev)) >= 0)) { - if (dis_param) - ret = dis_disc_cap(pbpctl_dev); - else - ret = en_disc_cap(pbpctl_dev); - cmnd_off(pbpctl_dev); - return ret; - } else - return BP_NOT_CAP; -} - -int get_dis_disc_fn(bpctl_dev_t *pbpctl_dev) -{ - int ret = 0; - if (!pbpctl_dev) - return -1; - - ret = dis_disc_cap_status(pbpctl_dev); - - return ret; -} - -int set_disc_port_fn(bpctl_dev_t *pbpctl_dev, int disc_mode) -{ - int ret = BP_NOT_CAP; - if (!pbpctl_dev) - return -1; - - if (!disc_mode) - ret = disc_port_off(pbpctl_dev); - else - ret = disc_port_on(pbpctl_dev); - - return ret; -} - -int get_disc_port_fn(bpctl_dev_t *pbpctl_dev) -{ - if (!pbpctl_dev) - return -1; - - return disc_port_status(pbpctl_dev); -} - -int set_disc_port_pwup_fn(bpctl_dev_t *pbpctl_dev, int disc_mode) -{ - int ret = BP_NOT_CAP; - if (!pbpctl_dev) - return -1; - - if (!disc_mode) - ret = normal_port_state_pwron(pbpctl_dev); - else - ret = disc_port_state_pwron(pbpctl_dev); - - return ret; -} - -int get_disc_port_pwup_fn(bpctl_dev_t *pbpctl_dev) -{ - int ret = 0; - if (!pbpctl_dev) - return -1; - - if ((ret = default_pwron_disc_port_status(pbpctl_dev)) < 0) - return ret; - return ((ret == 0) ? 1 : 0); -} - -int get_wd_exp_mode_fn(bpctl_dev_t *pbpctl_dev) -{ - if (!pbpctl_dev) - return -1; - - return wdt_exp_mode_status(pbpctl_dev); -} - -int set_wd_exp_mode_fn(bpctl_dev_t *pbpctl_dev, int param) -{ - if (!pbpctl_dev) - return -1; - - return wdt_exp_mode(pbpctl_dev, param); -} - -int reset_cont_fn(bpctl_dev_t *pbpctl_dev) -{ - int ret = 0; - if (!pbpctl_dev) - return -1; - - if ((ret = cmnd_on(pbpctl_dev)) < 0) - return ret; - return reset_cont(pbpctl_dev); -} - -int set_tx_fn(bpctl_dev_t *pbpctl_dev, int tx_state) -{ - - bpctl_dev_t *pbpctl_dev_b = NULL; - if (!pbpctl_dev) - return -1; - - if ((pbpctl_dev->bp_caps & TPL_CAP) && - (pbpctl_dev->bp_caps & SW_CTL_CAP)) { - if ((pbpctl_dev->bp_tpl_flag)) - return BP_NOT_CAP; - } else if ((pbpctl_dev_b = get_master_port_fn(pbpctl_dev))) { - if ((pbpctl_dev_b->bp_caps & TPL_CAP) && - (pbpctl_dev_b->bp_tpl_flag)) - return BP_NOT_CAP; - } - return set_tx(pbpctl_dev, tx_state); -} - -int set_bp_force_link_fn(int dev_num, int tx_state) -{ - static bpctl_dev_t *bpctl_dev_curr; - - if ((dev_num < 0) || (dev_num > device_num) - || (bpctl_dev_arr[dev_num].pdev == NULL)) - return -1; - bpctl_dev_curr = &bpctl_dev_arr[dev_num]; - - return set_bp_force_link(bpctl_dev_curr, tx_state); -} - -int set_wd_autoreset_fn(bpctl_dev_t *pbpctl_dev, int param) -{ - if (!pbpctl_dev) - return -1; - - return set_bypass_wd_auto(pbpctl_dev, param); -} - -int get_wd_autoreset_fn(bpctl_dev_t *pbpctl_dev) -{ - if (!pbpctl_dev) - return -1; - - return get_bypass_wd_auto(pbpctl_dev); -} - -#ifdef BP_SELF_TEST -int set_bp_self_test_fn(bpctl_dev_t *pbpctl_dev, int param) -{ - if (!pbpctl_dev) - return -1; - - return set_bp_self_test(pbpctl_dev, param); -} - -int get_bp_self_test_fn(bpctl_dev_t *pbpctl_dev) -{ - if (!pbpctl_dev) - return -1; - - return get_bp_self_test(pbpctl_dev); -} - -#endif - -int get_bypass_caps_fn(bpctl_dev_t *pbpctl_dev) -{ - if (!pbpctl_dev) - return -1; - - return pbpctl_dev->bp_caps; - -} - -int get_bypass_slave_fn(bpctl_dev_t *pbpctl_dev, bpctl_dev_t **pbpctl_dev_out) -{ - int idx_dev = 0; - if (!pbpctl_dev) - return -1; - - if ((pbpctl_dev->func == 0) || (pbpctl_dev->func == 2)) { - for (idx_dev = 0; - ((bpctl_dev_arr[idx_dev].pdev != NULL) - && (idx_dev < device_num)); idx_dev++) { - if ((bpctl_dev_arr[idx_dev].bus == pbpctl_dev->bus) - && (bpctl_dev_arr[idx_dev].slot == - pbpctl_dev->slot)) { - if ((pbpctl_dev->func == 0) - && (bpctl_dev_arr[idx_dev].func == 1)) { - *pbpctl_dev_out = - &bpctl_dev_arr[idx_dev]; - return 1; - } - if ((pbpctl_dev->func == 2) && - (bpctl_dev_arr[idx_dev].func == 3)) { - *pbpctl_dev_out = - &bpctl_dev_arr[idx_dev]; - return 1; - } - } - } - return -1; - } else - return 0; -} - -int is_bypass(bpctl_dev_t *pbpctl_dev) -{ - if (!pbpctl_dev) - return -1; - - if ((pbpctl_dev->func == 0) || (pbpctl_dev->func == 2)) - return 1; - else - return 0; -} - -int get_tx_fn(bpctl_dev_t *pbpctl_dev) -{ - bpctl_dev_t *pbpctl_dev_b = NULL; - if (!pbpctl_dev) - return -1; - - if ((pbpctl_dev->bp_caps & TPL_CAP) && - (pbpctl_dev->bp_caps & SW_CTL_CAP)) { - if ((pbpctl_dev->bp_tpl_flag)) - return BP_NOT_CAP; - } else if ((pbpctl_dev_b = get_master_port_fn(pbpctl_dev))) { - if ((pbpctl_dev_b->bp_caps & TPL_CAP) && - (pbpctl_dev_b->bp_tpl_flag)) - return BP_NOT_CAP; - } - return tx_status(pbpctl_dev); -} - -int get_bp_force_link_fn(int dev_num) -{ - static bpctl_dev_t *bpctl_dev_curr; - - if ((dev_num < 0) || (dev_num > device_num) - || (bpctl_dev_arr[dev_num].pdev == NULL)) - return -1; - bpctl_dev_curr = &bpctl_dev_arr[dev_num]; - - return bp_force_link_status(bpctl_dev_curr); -} - -static int get_bypass_link_status(bpctl_dev_t *pbpctl_dev) -{ - if (!pbpctl_dev) - return -1; - - if (pbpctl_dev->media_type == bp_fiber) - return ((BPCTL_READ_REG(pbpctl_dev, CTRL) & - BPCTLI_CTRL_SWDPIN1)); - else - return ((BPCTL_READ_REG(pbpctl_dev, STATUS) & - BPCTLI_STATUS_LU)); - -} - -static void bp_tpl_timer_fn(unsigned long param) -{ - bpctl_dev_t *pbpctl_dev = (bpctl_dev_t *) param; - uint32_t link1, link2; - bpctl_dev_t *pbpctl_dev_b = NULL; - - if (!(pbpctl_dev_b = get_status_port_fn(pbpctl_dev))) - return; - - if (!pbpctl_dev->bp_tpl_flag) { - set_tx(pbpctl_dev_b, 1); - set_tx(pbpctl_dev, 1); - return; - } - link1 = get_bypass_link_status(pbpctl_dev); - - link2 = get_bypass_link_status(pbpctl_dev_b); - if ((link1) && (tx_status(pbpctl_dev))) { - if ((!link2) && (tx_status(pbpctl_dev_b))) { - set_tx(pbpctl_dev, 0); - } else if (!tx_status(pbpctl_dev_b)) { - set_tx(pbpctl_dev_b, 1); - } - } else if ((!link1) && (tx_status(pbpctl_dev))) { - if ((link2) && (tx_status(pbpctl_dev_b))) { - set_tx(pbpctl_dev_b, 0); - } - } else if ((link1) && (!tx_status(pbpctl_dev))) { - if ((link2) && (tx_status(pbpctl_dev_b))) { - set_tx(pbpctl_dev, 1); - } - } else if ((!link1) && (!tx_status(pbpctl_dev))) { - if ((link2) && (tx_status(pbpctl_dev_b))) { - set_tx(pbpctl_dev, 1); - } - } - - mod_timer(&pbpctl_dev->bp_tpl_timer, jiffies + BP_LINK_MON_DELAY * HZ); -} - -void remove_bypass_tpl_auto(bpctl_dev_t *pbpctl_dev) -{ - bpctl_dev_t *pbpctl_dev_b = NULL; - if (!pbpctl_dev) - return; - pbpctl_dev_b = get_status_port_fn(pbpctl_dev); - - if (pbpctl_dev->bp_caps & TPL_CAP) { - del_timer_sync(&pbpctl_dev->bp_tpl_timer); - pbpctl_dev->bp_tpl_flag = 0; - pbpctl_dev_b = get_status_port_fn(pbpctl_dev); - if (pbpctl_dev_b) - set_tx(pbpctl_dev_b, 1); - set_tx(pbpctl_dev, 1); - } - return; -} - -int init_bypass_tpl_auto(bpctl_dev_t *pbpctl_dev) -{ - if (!pbpctl_dev) - return -1; - if (pbpctl_dev->bp_caps & TPL_CAP) { - init_timer(&pbpctl_dev->bp_tpl_timer); - pbpctl_dev->bp_tpl_timer.function = &bp_tpl_timer_fn; - pbpctl_dev->bp_tpl_timer.data = (unsigned long)pbpctl_dev; - return BP_OK; - } - return BP_NOT_CAP; -} - -int set_bypass_tpl_auto(bpctl_dev_t *pbpctl_dev, unsigned int param) -{ - if (!pbpctl_dev) - return -1; - if (pbpctl_dev->bp_caps & TPL_CAP) { - if ((param) && (!pbpctl_dev->bp_tpl_flag)) { - pbpctl_dev->bp_tpl_flag = param; - mod_timer(&pbpctl_dev->bp_tpl_timer, jiffies + 1); - return BP_OK; - }; - if ((!param) && (pbpctl_dev->bp_tpl_flag)) - remove_bypass_tpl_auto(pbpctl_dev); - - return BP_OK; - } - return BP_NOT_CAP; -} - -int get_bypass_tpl_auto(bpctl_dev_t *pbpctl_dev) -{ - if (!pbpctl_dev) - return -1; - if (pbpctl_dev->bp_caps & TPL_CAP) { - return pbpctl_dev->bp_tpl_flag; - } - return BP_NOT_CAP; -} - -int set_tpl_fn(bpctl_dev_t *pbpctl_dev, int tpl_mode) -{ - - bpctl_dev_t *pbpctl_dev_b = NULL; - if (!pbpctl_dev) - return -1; - - pbpctl_dev_b = get_status_port_fn(pbpctl_dev); - - if (pbpctl_dev->bp_caps & TPL_CAP) { - if (tpl_mode) { - if ((pbpctl_dev_b = get_status_port_fn(pbpctl_dev))) - set_tx(pbpctl_dev_b, 1); - set_tx(pbpctl_dev, 1); - } - if ((TPL_IF_SERIES(pbpctl_dev->subdevice)) || - (pbpctl_dev->bp_caps_ex & TPL2_CAP_EX)) { - pbpctl_dev->bp_tpl_flag = tpl_mode; - if (!tpl_mode) - tpl_hw_off(pbpctl_dev); - else - tpl_hw_on(pbpctl_dev); - } else - set_bypass_tpl_auto(pbpctl_dev, tpl_mode); - return 0; - } - return BP_NOT_CAP; -} - -int get_tpl_fn(bpctl_dev_t *pbpctl_dev) -{ - int ret = BP_NOT_CAP; - if (!pbpctl_dev) - return -1; - - if (pbpctl_dev->bp_caps & TPL_CAP) { - if (pbpctl_dev->bp_caps_ex & TPL2_CAP_EX) - return tpl2_flag_status(pbpctl_dev); - ret = pbpctl_dev->bp_tpl_flag; - } - return ret; -} - -int set_bp_wait_at_pwup_fn(bpctl_dev_t *pbpctl_dev, int tap_mode) -{ - if (!pbpctl_dev) - return -1; - - if (pbpctl_dev->bp_caps & SW_CTL_CAP) { - /* bp_lock(pbp_device_block); */ - cmnd_on(pbpctl_dev); - if (!tap_mode) - bp_wait_at_pwup_dis(pbpctl_dev); - else - bp_wait_at_pwup_en(pbpctl_dev); - cmnd_off(pbpctl_dev); - - /* bp_unlock(pbp_device_block); */ - return BP_OK; - } - return BP_NOT_CAP; -} - -int get_bp_wait_at_pwup_fn(bpctl_dev_t *pbpctl_dev) -{ - int ret = 0; - if (!pbpctl_dev) - return -1; - - /* bp_lock(pbp_device_block); */ - ret = bp_wait_at_pwup_status(pbpctl_dev); - /* bp_unlock(pbp_device_block); */ - - return ret; -} - -int set_bp_hw_reset_fn(bpctl_dev_t *pbpctl_dev, int tap_mode) -{ - if (!pbpctl_dev) - return -1; - - if (pbpctl_dev->bp_caps & SW_CTL_CAP) { - /* bp_lock(pbp_device_block); */ - cmnd_on(pbpctl_dev); - - if (!tap_mode) - bp_hw_reset_dis(pbpctl_dev); - else - bp_hw_reset_en(pbpctl_dev); - cmnd_off(pbpctl_dev); - /* bp_unlock(pbp_device_block); */ - return BP_OK; - } - return BP_NOT_CAP; -} - -int get_bp_hw_reset_fn(bpctl_dev_t *pbpctl_dev) -{ - int ret = 0; - if (!pbpctl_dev) - return -1; - - /* bp_lock(pbp_device_block); */ - ret = bp_hw_reset_status(pbpctl_dev); - - /* bp_unlock(pbp_device_block); */ - - return ret; -} - - -int get_bypass_info_fn(bpctl_dev_t *pbpctl_dev, char *dev_name, - char *add_param) -{ - if (!pbpctl_dev) - return -1; - if (!is_bypass_fn(pbpctl_dev)) - return -1; - strcpy(dev_name, pbpctl_dev->name); - *add_param = pbpctl_dev->bp_fw_ver; - return 0; -} - -int get_dev_idx_bsf(int bus, int slot, int func) -{ - int idx_dev = 0; - for (idx_dev = 0; - ((bpctl_dev_arr[idx_dev].pdev != NULL) && (idx_dev < device_num)); - idx_dev++) { - if ((bus == bpctl_dev_arr[idx_dev].bus) - && (slot == bpctl_dev_arr[idx_dev].slot) - && (func == bpctl_dev_arr[idx_dev].func)) - - return idx_dev; - } - return -1; -} - -static void str_low(char *str) -{ - int i; - - for (i = 0; i < strlen(str); i++) - if ((str[i] >= 65) && (str[i] <= 90)) - str[i] += 32; -} - -static unsigned long str_to_hex(char *p) -{ - unsigned long hex = 0; - unsigned long length = strlen(p), shift = 0; - unsigned char dig = 0; - - str_low(p); - length = strlen(p); - - if (length == 0) - return 0; - - do { - dig = p[--length]; - dig = dig < 'a' ? (dig - '0') : (dig - 'a' + 0xa); - hex |= (dig << shift); - shift += 4; - } while (length); - return hex; -} - -static int get_dev_idx(int ifindex) -{ - int idx_dev = 0; - - for (idx_dev = 0; - ((bpctl_dev_arr[idx_dev].pdev != NULL) && (idx_dev < device_num)); - idx_dev++) { - if (ifindex == bpctl_dev_arr[idx_dev].ifindex) - return idx_dev; - } - - return -1; -} - -static bpctl_dev_t *get_dev_idx_p(int ifindex) -{ - int idx_dev = 0; - - for (idx_dev = 0; - ((bpctl_dev_arr[idx_dev].pdev != NULL) && (idx_dev < device_num)); - idx_dev++) { - if (ifindex == bpctl_dev_arr[idx_dev].ifindex) - return &bpctl_dev_arr[idx_dev]; - } - - return NULL; -} - -static void if_scan_init(void) -{ - int idx_dev = 0; - struct net_device *dev; - int ifindex; - /* rcu_read_lock(); */ - /* rtnl_lock(); */ - /* rcu_read_lock(); */ -#if 1 -#if (LINUX_VERSION_CODE >= 0x020618) - for_each_netdev(&init_net, dev) -#elif (LINUX_VERSION_CODE >= 0x20616) - for_each_netdev(dev) -#else - for (dev = dev_base; dev; dev = dev->next) -#endif - { - - struct ethtool_drvinfo drvinfo; - char cbuf[32]; - char *buf = NULL; - char res[10]; - int i = 0; - int bus = 0, slot = 0, func = 0; - ifindex = dev->ifindex; - - memset(res, 0, 10); - memset(&drvinfo, 0, sizeof(struct ethtool_drvinfo)); - - if (dev->ethtool_ops && dev->ethtool_ops->get_drvinfo) { - memset(&drvinfo, 0, sizeof(drvinfo)); - dev->ethtool_ops->get_drvinfo(dev, &drvinfo); - } else - continue; - if (!drvinfo.bus_info) - continue; - if (!strcmp(drvinfo.bus_info, "N/A")) - continue; - memcpy(&cbuf, drvinfo.bus_info, 32); - buf = &cbuf[0]; - - while (*buf++ != ':') ; - for (i = 0; i < 10; i++, buf++) { - if (*buf == ':') - break; - res[i] = *buf; - - } - buf++; - bus = str_to_hex(res); - memset(res, 0, 10); - - for (i = 0; i < 10; i++, buf++) { - if (*buf == '.') - break; - res[i] = *buf; - - } - buf++; - slot = str_to_hex(res); - func = str_to_hex(buf); - idx_dev = get_dev_idx_bsf(bus, slot, func); - - if (idx_dev != -1) { - - bpctl_dev_arr[idx_dev].ifindex = ifindex; - bpctl_dev_arr[idx_dev].ndev = dev; - - } - - } -#endif - /* rtnl_unlock(); */ - /* rcu_read_unlock(); */ - -} - -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)) -static int device_ioctl(struct inode *inode, /* see include/linux/fs.h */ - struct file *file, /* ditto */ - unsigned int ioctl_num, /* number and param for ioctl */ - unsigned long ioctl_param) -#else -static long device_ioctl(struct file *file, /* ditto */ - unsigned int ioctl_num, /* number and param for ioctl */ - unsigned long ioctl_param) -#endif -{ - struct bpctl_cmd bpctl_cmd; - int dev_idx = 0; - bpctl_dev_t *pbpctl_dev_out; - void __user *argp = (void __user *)ioctl_param; - int ret = 0; - unsigned long flags; - - static bpctl_dev_t *pbpctl_dev; - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30)) - /* lock_kernel(); */ -#endif - lock_bpctl(); - /* local_irq_save(flags); */ - /* if(!spin_trylock_irqsave(&bpvm_lock)){ - local_irq_restore(flags); - unlock_bpctl(); - unlock_kernel(); - return -1; - } */ - /* spin_lock_irqsave(&bpvm_lock, flags); */ - -/* -* Switch according to the ioctl called -*/ - if (ioctl_num == IOCTL_TX_MSG(IF_SCAN)) { - if_scan_init(); - ret = SUCCESS; - goto bp_exit; - } - if (copy_from_user(&bpctl_cmd, argp, sizeof(struct bpctl_cmd))) { - - ret = -EFAULT; - goto bp_exit; - } - - if (ioctl_num == IOCTL_TX_MSG(GET_DEV_NUM)) { - bpctl_cmd.out_param[0] = device_num; - if (copy_to_user - (argp, (void *)&bpctl_cmd, sizeof(struct bpctl_cmd))) { - ret = -EFAULT; - goto bp_exit; - } - ret = SUCCESS; - goto bp_exit; - - } - /* lock_bpctl(); */ - /* preempt_disable(); */ - local_irq_save(flags); - if (!spin_trylock(&bpvm_lock)) { - local_irq_restore(flags); - unlock_bpctl(); - return -1; - } - -/* preempt_disable(); - rcu_read_lock(); - spin_lock_irqsave(&bpvm_lock, flags); -*/ - if ((bpctl_cmd.in_param[5]) || - (bpctl_cmd.in_param[6]) || (bpctl_cmd.in_param[7])) - dev_idx = get_dev_idx_bsf(bpctl_cmd.in_param[5], - bpctl_cmd.in_param[6], - bpctl_cmd.in_param[7]); - else if (bpctl_cmd.in_param[1] == 0) - dev_idx = bpctl_cmd.in_param[0]; - else - dev_idx = get_dev_idx(bpctl_cmd.in_param[1]); - - if (dev_idx < 0 || dev_idx > device_num) { - /* unlock_bpctl(); - preempt_enable(); */ - ret = -EOPNOTSUPP; - /* preempt_enable(); - rcu_read_unlock(); */ - spin_unlock_irqrestore(&bpvm_lock, flags); - goto bp_exit; - } - - bpctl_cmd.out_param[0] = bpctl_dev_arr[dev_idx].bus; - bpctl_cmd.out_param[1] = bpctl_dev_arr[dev_idx].slot; - bpctl_cmd.out_param[2] = bpctl_dev_arr[dev_idx].func; - bpctl_cmd.out_param[3] = bpctl_dev_arr[dev_idx].ifindex; - - if ((bpctl_dev_arr[dev_idx].bp_10gb) - && (!(bpctl_dev_arr[dev_idx].ifindex))) { - printk("Please load network driver for %s adapter!\n", - bpctl_dev_arr[dev_idx].name); - bpctl_cmd.status = -1; - ret = SUCCESS; - /* preempt_enable(); */ - /* rcu_read_unlock(); */ - spin_unlock_irqrestore(&bpvm_lock, flags); - goto bp_exit; - - } - if ((bpctl_dev_arr[dev_idx].bp_10gb) && (bpctl_dev_arr[dev_idx].ndev)) { - if (!(bpctl_dev_arr[dev_idx].ndev->flags & IFF_UP)) { - if (!(bpctl_dev_arr[dev_idx].ndev->flags & IFF_UP)) { - printk - ("Please bring up network interfaces for %s adapter!\n", - bpctl_dev_arr[dev_idx].name); - bpctl_cmd.status = -1; - ret = SUCCESS; - /* preempt_enable(); */ - /* rcu_read_unlock(); */ - spin_unlock_irqrestore(&bpvm_lock, flags); - goto bp_exit; - } - - } - } - - if ((dev_idx < 0) || (dev_idx > device_num) - || (bpctl_dev_arr[dev_idx].pdev == NULL)) { - bpctl_cmd.status = -1; - goto bpcmd_exit; - } - - pbpctl_dev = &bpctl_dev_arr[dev_idx]; - - switch (ioctl_num) { - case IOCTL_TX_MSG(SET_BYPASS_PWOFF): - bpctl_cmd.status = - set_bypass_pwoff_fn(pbpctl_dev, bpctl_cmd.in_param[2]); - break; - - case IOCTL_TX_MSG(GET_BYPASS_PWOFF): - bpctl_cmd.status = get_bypass_pwoff_fn(pbpctl_dev); - break; - - case IOCTL_TX_MSG(SET_BYPASS_PWUP): - bpctl_cmd.status = - set_bypass_pwup_fn(pbpctl_dev, bpctl_cmd.in_param[2]); - break; - - case IOCTL_TX_MSG(GET_BYPASS_PWUP): - bpctl_cmd.status = get_bypass_pwup_fn(pbpctl_dev); - break; - - case IOCTL_TX_MSG(SET_BYPASS_WD): - bpctl_cmd.status = - set_bypass_wd_fn(pbpctl_dev, bpctl_cmd.in_param[2]); - break; - - case IOCTL_TX_MSG(GET_BYPASS_WD): - bpctl_cmd.status = - get_bypass_wd_fn(pbpctl_dev, (int *)&(bpctl_cmd.data[0])); - break; - - case IOCTL_TX_MSG(GET_WD_EXPIRE_TIME): - bpctl_cmd.status = - get_wd_expire_time_fn(pbpctl_dev, - (int *)&(bpctl_cmd.data[0])); - break; - - case IOCTL_TX_MSG(RESET_BYPASS_WD_TIMER): - bpctl_cmd.status = reset_bypass_wd_timer_fn(pbpctl_dev); - break; - - case IOCTL_TX_MSG(GET_WD_SET_CAPS): - bpctl_cmd.status = get_wd_set_caps_fn(pbpctl_dev); - break; - - case IOCTL_TX_MSG(SET_STD_NIC): - bpctl_cmd.status = - set_std_nic_fn(pbpctl_dev, bpctl_cmd.in_param[2]); - break; - - case IOCTL_TX_MSG(GET_STD_NIC): - bpctl_cmd.status = get_std_nic_fn(pbpctl_dev); - break; - - case IOCTL_TX_MSG(SET_TAP): - bpctl_cmd.status = - set_tap_fn(pbpctl_dev, bpctl_cmd.in_param[2]); - break; - - case IOCTL_TX_MSG(GET_TAP): - bpctl_cmd.status = get_tap_fn(pbpctl_dev); - break; - - case IOCTL_TX_MSG(GET_TAP_CHANGE): - bpctl_cmd.status = get_tap_change_fn(pbpctl_dev); - break; - - case IOCTL_TX_MSG(SET_DIS_TAP): - bpctl_cmd.status = - set_dis_tap_fn(pbpctl_dev, bpctl_cmd.in_param[2]); - break; - - case IOCTL_TX_MSG(GET_DIS_TAP): - bpctl_cmd.status = get_dis_tap_fn(pbpctl_dev); - break; - - case IOCTL_TX_MSG(SET_TAP_PWUP): - bpctl_cmd.status = - set_tap_pwup_fn(pbpctl_dev, bpctl_cmd.in_param[2]); - break; - - case IOCTL_TX_MSG(GET_TAP_PWUP): - bpctl_cmd.status = get_tap_pwup_fn(pbpctl_dev); - break; - - case IOCTL_TX_MSG(SET_WD_EXP_MODE): - bpctl_cmd.status = - set_wd_exp_mode_fn(pbpctl_dev, bpctl_cmd.in_param[2]); - break; - - case IOCTL_TX_MSG(GET_WD_EXP_MODE): - bpctl_cmd.status = get_wd_exp_mode_fn(pbpctl_dev); - break; - - case IOCTL_TX_MSG(GET_DIS_BYPASS): - bpctl_cmd.status = get_dis_bypass_fn(pbpctl_dev); - break; - - case IOCTL_TX_MSG(SET_DIS_BYPASS): - bpctl_cmd.status = - set_dis_bypass_fn(pbpctl_dev, bpctl_cmd.in_param[2]); - break; - - case IOCTL_TX_MSG(GET_BYPASS_CHANGE): - bpctl_cmd.status = get_bypass_change_fn(pbpctl_dev); - break; - - case IOCTL_TX_MSG(GET_BYPASS): - bpctl_cmd.status = get_bypass_fn(pbpctl_dev); - break; - - case IOCTL_TX_MSG(SET_BYPASS): - bpctl_cmd.status = - set_bypass_fn(pbpctl_dev, bpctl_cmd.in_param[2]); - break; - - case IOCTL_TX_MSG(GET_BYPASS_CAPS): - bpctl_cmd.status = get_bypass_caps_fn(pbpctl_dev); - /*preempt_enable(); */ - /*rcu_read_unlock();*/ - spin_unlock_irqrestore(&bpvm_lock, flags); - if (copy_to_user - (argp, (void *)&bpctl_cmd, sizeof(struct bpctl_cmd))) { - /*unlock_bpctl(); */ - /*preempt_enable(); */ - ret = -EFAULT; - goto bp_exit; - } - goto bp_exit; - - case IOCTL_TX_MSG(GET_BYPASS_SLAVE): - bpctl_cmd.status = - get_bypass_slave_fn(pbpctl_dev, &pbpctl_dev_out); - if (bpctl_cmd.status == 1) { - bpctl_cmd.out_param[4] = pbpctl_dev_out->bus; - bpctl_cmd.out_param[5] = pbpctl_dev_out->slot; - bpctl_cmd.out_param[6] = pbpctl_dev_out->func; - bpctl_cmd.out_param[7] = pbpctl_dev_out->ifindex; - } - break; - - case IOCTL_TX_MSG(IS_BYPASS): - bpctl_cmd.status = is_bypass(pbpctl_dev); - break; - case IOCTL_TX_MSG(SET_TX): - bpctl_cmd.status = set_tx_fn(pbpctl_dev, bpctl_cmd.in_param[2]); - break; - case IOCTL_TX_MSG(GET_TX): - bpctl_cmd.status = get_tx_fn(pbpctl_dev); - break; - case IOCTL_TX_MSG(SET_WD_AUTORESET): - bpctl_cmd.status = - set_wd_autoreset_fn(pbpctl_dev, bpctl_cmd.in_param[2]); - - break; - case IOCTL_TX_MSG(GET_WD_AUTORESET): - - bpctl_cmd.status = get_wd_autoreset_fn(pbpctl_dev); - break; - case IOCTL_TX_MSG(SET_DISC): - bpctl_cmd.status = - set_disc_fn(pbpctl_dev, bpctl_cmd.in_param[2]); - break; - case IOCTL_TX_MSG(GET_DISC): - bpctl_cmd.status = get_disc_fn(pbpctl_dev); - break; - case IOCTL_TX_MSG(GET_DISC_CHANGE): - bpctl_cmd.status = get_disc_change_fn(pbpctl_dev); - break; - case IOCTL_TX_MSG(SET_DIS_DISC): - bpctl_cmd.status = - set_dis_disc_fn(pbpctl_dev, bpctl_cmd.in_param[2]); - break; - case IOCTL_TX_MSG(GET_DIS_DISC): - bpctl_cmd.status = get_dis_disc_fn(pbpctl_dev); - break; - case IOCTL_TX_MSG(SET_DISC_PWUP): - bpctl_cmd.status = - set_disc_pwup_fn(pbpctl_dev, bpctl_cmd.in_param[2]); - break; - case IOCTL_TX_MSG(GET_DISC_PWUP): - bpctl_cmd.status = get_disc_pwup_fn(pbpctl_dev); - break; - - case IOCTL_TX_MSG(GET_BYPASS_INFO): - - bpctl_cmd.status = - get_bypass_info_fn(pbpctl_dev, (char *)&bpctl_cmd.data, - (char *)&bpctl_cmd.out_param[4]); - break; - - case IOCTL_TX_MSG(SET_TPL): - bpctl_cmd.status = - set_tpl_fn(pbpctl_dev, bpctl_cmd.in_param[2]); - break; - - case IOCTL_TX_MSG(GET_TPL): - bpctl_cmd.status = get_tpl_fn(pbpctl_dev); - break; - case IOCTL_TX_MSG(SET_BP_WAIT_AT_PWUP): - bpctl_cmd.status = - set_bp_wait_at_pwup_fn(pbpctl_dev, bpctl_cmd.in_param[2]); - break; - - case IOCTL_TX_MSG(GET_BP_WAIT_AT_PWUP): - bpctl_cmd.status = get_bp_wait_at_pwup_fn(pbpctl_dev); - break; - case IOCTL_TX_MSG(SET_BP_HW_RESET): - bpctl_cmd.status = - set_bp_hw_reset_fn(pbpctl_dev, bpctl_cmd.in_param[2]); - break; - - case IOCTL_TX_MSG(GET_BP_HW_RESET): - bpctl_cmd.status = get_bp_hw_reset_fn(pbpctl_dev); - break; -#ifdef BP_SELF_TEST - case IOCTL_TX_MSG(SET_BP_SELF_TEST): - bpctl_cmd.status = - set_bp_self_test_fn(pbpctl_dev, bpctl_cmd.in_param[2]); - - break; - case IOCTL_TX_MSG(GET_BP_SELF_TEST): - bpctl_cmd.status = get_bp_self_test_fn(pbpctl_dev); - break; - -#endif -#if 0 - case IOCTL_TX_MSG(SET_DISC_PORT): - bpctl_cmd.status = - set_disc_port_fn(pbpctl_dev, bpctl_cmd.in_param[2]); - break; - - case IOCTL_TX_MSG(GET_DISC_PORT): - bpctl_cmd.status = get_disc_port_fn(pbpctl_dev); - break; - - case IOCTL_TX_MSG(SET_DISC_PORT_PWUP): - bpctl_cmd.status = - set_disc_port_pwup_fn(pbpctl_dev, bpctl_cmd.in_param[2]); - break; - - case IOCTL_TX_MSG(GET_DISC_PORT_PWUP): - bpctl_cmd.status = get_disc_port_pwup_fn(pbpctl_dev); - break; -#endif - case IOCTL_TX_MSG(SET_BP_FORCE_LINK): - bpctl_cmd.status = - set_bp_force_link_fn(dev_idx, bpctl_cmd.in_param[2]); - break; - - case IOCTL_TX_MSG(GET_BP_FORCE_LINK): - bpctl_cmd.status = get_bp_force_link_fn(dev_idx); - break; - - default: - /* unlock_bpctl(); */ - - ret = -EOPNOTSUPP; - /* preempt_enable(); */ - /* rcu_read_unlock();*/ - spin_unlock_irqrestore(&bpvm_lock, flags); - goto bp_exit; - } - /* unlock_bpctl(); */ - /* preempt_enable(); */ - bpcmd_exit: - /* rcu_read_unlock(); */ - spin_unlock_irqrestore(&bpvm_lock, flags); - if (copy_to_user(argp, (void *)&bpctl_cmd, sizeof(struct bpctl_cmd))) - ret = -EFAULT; - ret = SUCCESS; - bp_exit: -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30)) - /* unlock_kernel(); */ -#endif - /* spin_unlock_irqrestore(&bpvm_lock, flags); */ - unlock_bpctl(); - /* unlock_kernel(); */ - return ret; -} - -struct file_operations Fops = { - .owner = THIS_MODULE, -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)) - .ioctl = device_ioctl, -#else - .unlocked_ioctl = device_ioctl, -#endif - - .open = device_open, - .release = device_release, /* a.k.a. close */ -}; - -#ifndef PCI_DEVICE -#define PCI_DEVICE(vend,dev) \ - .vendor = (vend), .device = (dev), \ - .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID -#endif - -#define SILICOM_E1000BP_ETHERNET_DEVICE(device_id) {\ - PCI_DEVICE(SILICOM_VID, device_id)} - -typedef enum { - PXG2BPFI, - PXG2BPFIL, - PXG2BPFILX, - PXG2BPFILLX, - PXGBPI, - PXGBPIG, - PXG2TBFI, - PXG4BPI, - PXG4BPFI, - PEG4BPI, - PEG2BPI, - PEG4BPIN, - PEG2BPFI, - PEG2BPFILX, - PMCXG2BPFI, - PMCXG2BPFIN, - PEG4BPII, - PEG4BPFII, - PXG4BPFILX, - PMCXG2BPIN, - PMCXG4BPIN, - PXG2BISC1, - PEG2TBFI, - PXG2TBI, - PXG4BPFID, - PEG4BPFI, - PEG4BPIPT, - PXG6BPI, - PEG4BPIL, - PMCXG2BPIN2, - PMCXG4BPIN2, - PMCX2BPI, - PEG2BPFID, - PEG2BPFIDLX, - PMCX4BPI, - MEG2BPFILN, - MEG2BPFINX, - PEG4BPFILX, - PE10G2BPISR, - PE10G2BPILR, - MHIO8AD, - PE10G2BPICX4, - PEG2BPI5, - PEG6BPI, - PEG4BPFI5, - PEG4BPFI5LX, - MEG2BPFILXLN, - PEG2BPIX1, - MEG2BPFILXNX, - XE10G2BPIT, - XE10G2BPICX4, - XE10G2BPISR, - XE10G2BPILR, - PEG4BPIIO, - XE10G2BPIXR, - PE10GDBISR, - PE10GDBILR, - PEG2BISC6, - PEG6BPIFC, - PE10G2BPTCX4, - PE10G2BPTSR, - PE10G2BPTLR, - PE10G2BPTT, - PEG4BPI6, - PEG4BPFI6, - PEG4BPFI6LX, - PEG4BPFI6ZX, - PEG2BPI6, - PEG2BPFI6, - PEG2BPFI6LX, - PEG2BPFI6ZX, - PEG2BPFI6FLXM, - PEG4BPI6FC, - PEG4BPFI6FC, - PEG4BPFI6FCLX, - PEG4BPFI6FCZX, - PEG6BPI6, - PEG2BPI6SC6, - MEG2BPI6, - XEG2BPI6, - MEG4BPI6, - PEG2BPFI5, - PEG2BPFI5LX, - PXEG4BPFI, - M1EG2BPI6, - M1EG2BPFI6, - M1EG2BPFI6LX, - M1EG2BPFI6ZX, - M1EG4BPI6, - M1EG4BPFI6, - M1EG4BPFI6LX, - M1EG4BPFI6ZX, - M1EG6BPI6, - M1E2G4BPi80, - M1E2G4BPFi80, - M1E2G4BPFi80LX, - M1E2G4BPFi80ZX, - PE210G2SPI9, - M1E10G2BPI9CX4, - M1E10G2BPI9SR, - M1E10G2BPI9LR, - M1E10G2BPI9T, - PE210G2BPI9CX4, - PE210G2BPI9SR, - PE210G2BPI9LR, - PE210G2BPI9T, - M2EG2BPFI6, - M2EG2BPFI6LX, - M2EG2BPFI6ZX, - M2EG4BPI6, - M2EG4BPFI6, - M2EG4BPFI6LX, - M2EG4BPFI6ZX, - M2EG6BPI6, - PEG2DBI6, - PEG2DBFI6, - PEG2DBFI6LX, - PEG2DBFI6ZX, - PE2G4BPi80, - PE2G4BPFi80, - PE2G4BPFi80LX, - PE2G4BPFi80ZX, - PE2G4BPi80L, - M6E2G8BPi80A, - - PE2G2BPi35, - PAC1200BPi35, - PE2G2BPFi35, - PE2G2BPFi35LX, - PE2G2BPFi35ZX, - PE2G4BPi35, - PE2G4BPi35L, - PE2G4BPFi35, - PE2G4BPFi35LX, - PE2G4BPFi35ZX, - - PE2G6BPi35, - PE2G6BPi35CX, - - PE2G2BPi80, - PE2G2BPFi80, - PE2G2BPFi80LX, - PE2G2BPFi80ZX, - M2E10G2BPI9CX4, - M2E10G2BPI9SR, - M2E10G2BPI9LR, - M2E10G2BPI9T, - M6E2G8BPi80, - PE210G2DBi9SR, - PE210G2DBi9SRRB, - PE210G2DBi9LR, - PE210G2DBi9LRRB, - PE310G4DBi940SR, - PE310G4BPi9T, - PE310G4BPi9SR, - PE310G4BPi9LR, - PE210G2BPi40, -} board_t; - -typedef struct _bpmod_info_t { - unsigned int vendor; - unsigned int device; - unsigned int subvendor; - unsigned int subdevice; - unsigned int index; - char *bp_name; - -} bpmod_info_t; - -typedef struct _dev_desc { - char *name; -} dev_desc_t; - -dev_desc_t dev_desc[] = { - {"Silicom Bypass PXG2BPFI-SD series adapter"}, - {"Silicom Bypass PXG2BPFIL-SD series adapter"}, - {"Silicom Bypass PXG2BPFILX-SD series adapter"}, - {"Silicom Bypass PXG2BPFILLX-SD series adapter"}, - {"Silicom Bypass PXG2BPI-SD series adapter"}, - {"Silicom Bypass PXG2BPIG-SD series adapter"}, - {"Silicom Bypass PXG2TBFI-SD series adapter"}, - {"Silicom Bypass PXG4BPI-SD series adapter"}, - {"Silicom Bypass PXG4BPFI-SD series adapter"}, - {"Silicom Bypass PEG4BPI-SD series adapter"}, - {"Silicom Bypass PEG2BPI-SD series adapter"}, - {"Silicom Bypass PEG4BPIN-SD series adapter"}, - {"Silicom Bypass PEG2BPFI-SD series adapter"}, - {"Silicom Bypass PEG2BPFI-LX-SD series adapter"}, - {"Silicom Bypass PMCX2BPFI-SD series adapter"}, - {"Silicom Bypass PMCX2BPFI-N series adapter"}, - {"Intel Bypass PEG2BPII series adapter"}, - {"Intel Bypass PEG2BPFII series adapter"}, - {"Silicom Bypass PXG4BPFILX-SD series adapter"}, - {"Silicom Bypass PMCX2BPI-N series adapter"}, - {"Silicom Bypass PMCX4BPI-N series adapter"}, - {"Silicom Bypass PXG2BISC1-SD series adapter"}, - {"Silicom Bypass PEG2TBFI-SD series adapter"}, - {"Silicom Bypass PXG2TBI-SD series adapter"}, - {"Silicom Bypass PXG4BPFID-SD series adapter"}, - {"Silicom Bypass PEG4BPFI-SD series adapter"}, - {"Silicom Bypass PEG4BPIPT-SD series adapter"}, - {"Silicom Bypass PXG6BPI-SD series adapter"}, - {"Silicom Bypass PEG4BPIL-SD series adapter"}, - {"Silicom Bypass PMCX2BPI-N2 series adapter"}, - {"Silicom Bypass PMCX4BPI-N2 series adapter"}, - {"Silicom Bypass PMCX2BPI-SD series adapter"}, - {"Silicom Bypass PEG2BPFID-SD series adapter"}, - {"Silicom Bypass PEG2BPFIDLX-SD series adapter"}, - {"Silicom Bypass PMCX4BPI-SD series adapter"}, - {"Silicom Bypass MEG2BPFILN-SD series adapter"}, - {"Silicom Bypass MEG2BPFINX-SD series adapter"}, - {"Silicom Bypass PEG4BPFILX-SD series adapter"}, - {"Silicom Bypass PE10G2BPISR-SD series adapter"}, - {"Silicom Bypass PE10G2BPILR-SD series adapter"}, - {"Silicom Bypass MHIO8AD-SD series adapter"}, - {"Silicom Bypass PE10G2BPICX4-SD series adapter"}, - {"Silicom Bypass PEG2BPI5-SD series adapter"}, - {"Silicom Bypass PEG6BPI5-SD series adapter"}, - {"Silicom Bypass PEG4BPFI5-SD series adapter"}, - {"Silicom Bypass PEG4BPFI5LX-SD series adapter"}, - {"Silicom Bypass MEG2BPFILXLN-SD series adapter"}, - {"Silicom Bypass PEG2BPIX1-SD series adapter"}, - {"Silicom Bypass MEG2BPFILXNX-SD series adapter"}, - {"Silicom Bypass XE10G2BPIT-SD series adapter"}, - {"Silicom Bypass XE10G2BPICX4-SD series adapter"}, - {"Silicom Bypass XE10G2BPISR-SD series adapter"}, - {"Silicom Bypass XE10G2BPILR-SD series adapter"}, - {"Intel Bypass PEG2BPFII0 series adapter"}, - {"Silicom Bypass XE10G2BPIXR series adapter"}, - {"Silicom Bypass PE10G2DBISR series adapter"}, - {"Silicom Bypass PEG2BI5SC6 series adapter"}, - {"Silicom Bypass PEG6BPI5FC series adapter"}, - - {"Silicom Bypass PE10G2BPTCX4 series adapter"}, - {"Silicom Bypass PE10G2BPTSR series adapter"}, - {"Silicom Bypass PE10G2BPTLR series adapter"}, - {"Silicom Bypass PE10G2BPTT series adapter"}, - {"Silicom Bypass PEG4BPI6 series adapter"}, - {"Silicom Bypass PEG4BPFI6 series adapter"}, - {"Silicom Bypass PEG4BPFI6LX series adapter"}, - {"Silicom Bypass PEG4BPFI6ZX series adapter"}, - {"Silicom Bypass PEG2BPI6 series adapter"}, - {"Silicom Bypass PEG2BPFI6 series adapter"}, - {"Silicom Bypass PEG2BPFI6LX series adapter"}, - {"Silicom Bypass PEG2BPFI6ZX series adapter"}, - {"Silicom Bypass PEG2BPFI6FLXM series adapter"}, - {"Silicom Bypass PEG4BPI6FC series adapter"}, - {"Silicom Bypass PEG4BPFI6FC series adapter"}, - {"Silicom Bypass PEG4BPFI6FCLX series adapter"}, - {"Silicom Bypass PEG4BPFI6FCZX series adapter"}, - {"Silicom Bypass PEG6BPI6 series adapter"}, - {"Silicom Bypass PEG2BPI6SC6 series adapter"}, - {"Silicom Bypass MEG2BPI6 series adapter"}, - {"Silicom Bypass XEG2BPI6 series adapter"}, - {"Silicom Bypass MEG4BPI6 series adapter"}, - {"Silicom Bypass PEG2BPFI5-SD series adapter"}, - {"Silicom Bypass PEG2BPFI5LX-SD series adapter"}, - {"Silicom Bypass PXEG4BPFI-SD series adapter"}, - {"Silicom Bypass MxEG2BPI6 series adapter"}, - {"Silicom Bypass MxEG2BPFI6 series adapter"}, - {"Silicom Bypass MxEG2BPFI6LX series adapter"}, - {"Silicom Bypass MxEG2BPFI6ZX series adapter"}, - {"Silicom Bypass MxEG4BPI6 series adapter"}, - {"Silicom Bypass MxEG4BPFI6 series adapter"}, - {"Silicom Bypass MxEG4BPFI6LX series adapter"}, - {"Silicom Bypass MxEG4BPFI6ZX series adapter"}, - {"Silicom Bypass MxEG6BPI6 series adapter"}, - {"Silicom Bypass MxE2G4BPi80 series adapter"}, - {"Silicom Bypass MxE2G4BPFi80 series adapter"}, - {"Silicom Bypass MxE2G4BPFi80LX series adapter"}, - {"Silicom Bypass MxE2G4BPFi80ZX series adapter"}, - - {"Silicom Bypass PE210G2SPI9 series adapter"}, - - {"Silicom Bypass MxE210G2BPI9CX4 series adapter"}, - {"Silicom Bypass MxE210G2BPI9SR series adapter"}, - {"Silicom Bypass MxE210G2BPI9LR series adapter"}, - {"Silicom Bypass MxE210G2BPI9T series adapter"}, - - {"Silicom Bypass PE210G2BPI9CX4 series adapter"}, - {"Silicom Bypass PE210G2BPI9SR series adapter"}, - {"Silicom Bypass PE210G2BPI9LR series adapter"}, - {"Silicom Bypass PE210G2BPI9T series adapter"}, - - {"Silicom Bypass M2EG2BPFI6 series adapter"}, - {"Silicom Bypass M2EG2BPFI6LX series adapter"}, - {"Silicom Bypass M2EG2BPFI6ZX series adapter"}, - {"Silicom Bypass M2EG4BPI6 series adapter"}, - {"Silicom Bypass M2EG4BPFI6 series adapter"}, - {"Silicom Bypass M2EG4BPFI6LX series adapter"}, - {"Silicom Bypass M2EG4BPFI6ZX series adapter"}, - {"Silicom Bypass M2EG6BPI6 series adapter"}, - - {"Silicom Bypass PEG2DBI6 series adapter"}, - {"Silicom Bypass PEG2DBFI6 series adapter"}, - {"Silicom Bypass PEG2DBFI6LX series adapter"}, - {"Silicom Bypass PEG2DBFI6ZX series adapter"}, - - {"Silicom Bypass PE2G4BPi80 series adapter"}, - {"Silicom Bypass PE2G4BPFi80 series adapter"}, - {"Silicom Bypass PE2G4BPFi80LX series adapter"}, - {"Silicom Bypass PE2G4BPFi80ZX series adapter"}, - - {"Silicom Bypass PE2G4BPi80L series adapter"}, - {"Silicom Bypass MxE2G8BPi80A series adapter"}, - - {"Silicom Bypass PE2G2BPi35 series adapter"}, - {"Silicom Bypass PAC1200BPi35 series adapter"}, - {"Silicom Bypass PE2G2BPFi35 series adapter"}, - {"Silicom Bypass PE2G2BPFi35LX series adapter"}, - {"Silicom Bypass PE2G2BPFi35ZX series adapter"}, - - {"Silicom Bypass PE2G4BPi35 series adapter"}, - {"Silicom Bypass PE2G4BPi35L series adapter"}, - {"Silicom Bypass PE2G4BPFi35 series adapter"}, - {"Silicom Bypass PE2G4BPFi35LX series adapter"}, - {"Silicom Bypass PE2G4BPFi35ZX series adapter"}, - - {"Silicom Bypass PE2G6BPi35 series adapter"}, - {"Silicom Bypass PE2G6BPi35CX series adapter"}, - - {"Silicom Bypass PE2G2BPi80 series adapter"}, - {"Silicom Bypass PE2G2BPFi80 series adapter"}, - {"Silicom Bypass PE2G2BPFi80LX series adapter"}, - {"Silicom Bypass PE2G2BPFi80ZX series adapter"}, - - {"Silicom Bypass M2E10G2BPI9CX4 series adapter"}, - {"Silicom Bypass M2E10G2BPI9SR series adapter"}, - {"Silicom Bypass M2E10G2BPI9LR series adapter"}, - {"Silicom Bypass M2E10G2BPI9T series adapter"}, - {"Silicom Bypass MxE2G8BPi80 series adapter"}, - {"Silicom Bypass PE210G2DBi9SR series adapter"}, - {"Silicom Bypass PE210G2DBi9SRRB series adapter"}, - {"Silicom Bypass PE210G2DBi9LR series adapter"}, - {"Silicom Bypass PE210G2DBi9LRRB series adapter"}, - {"Silicom Bypass PE310G4DBi9-SR series adapter"}, - {"Silicom Bypass PE310G4BPi9T series adapter"}, - {"Silicom Bypass PE310G4BPi9SR series adapter"}, - {"Silicom Bypass PE310G4BPi9LR series adapter"}, - {"Silicom Bypass PE210G2BPi40T series adapter"}, - {0}, -}; - -static bpmod_info_t tx_ctl_pci_tbl[] = { - {0x8086, 0x107a, SILICOM_SVID, SILICOM_PXG2BPFI_SSID, PXG2BPFI, - "PXG2BPFI-SD"}, - {0x8086, 0x107a, SILICOM_SVID, SILICOM_PXG2BPFIL_SSID, PXG2BPFIL, - "PXG2BPFIL-SD"}, - {0x8086, 0x107a, SILICOM_SVID, SILICOM_PXG2BPFILX_SSID, PXG2BPFILX, - "PXG2BPFILX-SD"}, - {0x8086, 0x107a, SILICOM_SVID, SILICOM_PXG2BPFILLX_SSID, PXG2BPFILLX, - "PXG2BPFILLXSD"}, - {0x8086, 0x1010, SILICOM_SVID, SILICOM_PXGBPI_SSID, PXGBPI, - "PXG2BPI-SD"}, - {0x8086, 0x1079, SILICOM_SVID, SILICOM_PXGBPIG_SSID, PXGBPIG, - "PXG2BPIG-SD"}, - {0x8086, 0x107a, SILICOM_SVID, SILICOM_PXG2TBFI_SSID, PXG2TBFI, - "PXG2TBFI-SD"}, - {0x8086, 0x1079, SILICOM_SVID, SILICOM_PXG4BPI_SSID, PXG4BPI, - "PXG4BPI-SD"}, - {0x8086, 0x107a, SILICOM_SVID, SILICOM_PXG4BPFI_SSID, PXG4BPFI, - "PXG4BPFI-SD"}, - {0x8086, 0x107a, SILICOM_SVID, SILICOM_PXG4BPFILX_SSID, PXG4BPFILX, - "PXG4BPFILX-SD"}, - {0x8086, 0x1079, SILICOM_SVID, SILICOM_PEG4BPI_SSID, PEG4BPI, - "PEXG4BPI-SD"}, - {0x8086, 0x105e, SILICOM_SVID, SILICOM_PEG2BPI_SSID, PEG2BPI, - "PEG2BPI-SD"}, - {0x8086, 0x105e, SILICOM_SVID, SILICOM_PEG4BPIN_SSID, PEG4BPIN, - "PEG4BPI-SD"}, - {0x8086, 0x105f, SILICOM_SVID, SILICOM_PEG2BPFI_SSID, PEG2BPFI, - "PEG2BPFI-SD"}, - {0x8086, 0x105f, SILICOM_SVID, SILICOM_PEG2BPFILX_SSID, PEG2BPFILX, - "PEG2BPFILX-SD"}, - {0x8086, 0x107a, SILICOM_SVID, SILICOM_PMCXG2BPFI_SSID, PMCXG2BPFI, - "PMCX2BPFI-SD"}, - {0x8086, 0x107a, NOKIA_PMCXG2BPFIN_SVID, NOKIA_PMCXG2BPFIN_SSID, - PMCXG2BPFIN, "PMCX2BPFI-N"}, - {0x8086, INTEL_PEG4BPII_PID, 0x8086, INTEL_PEG4BPII_SSID, PEG4BPII, - "PEG4BPII"}, - {0x8086, INTEL_PEG4BPIIO_PID, 0x8086, INTEL_PEG4BPIIO_SSID, PEG4BPIIO, - "PEG4BPII0"}, - {0x8086, INTEL_PEG4BPFII_PID, 0x8086, INTEL_PEG4BPFII_SSID, PEG4BPFII, - "PEG4BPFII"}, - {0x8086, 0x1079, NOKIA_PMCXG2BPFIN_SVID, NOKIA_PMCXG2BPIN_SSID, - PMCXG2BPIN, "PMCX2BPI-N"}, - {0x8086, 0x1079, NOKIA_PMCXG2BPFIN_SVID, NOKIA_PMCXG4BPIN_SSID, - PMCXG4BPIN, "PMCX4BPI-N"}, - {0x8086, 0x1079, SILICOM_SVID, SILICOM_PXG2BISC1_SSID, PXG2BISC1, - "PXG2BISC1-SD"}, - {0x8086, 0x105f, SILICOM_SVID, SILICOM_PEG2TBFI_SSID, PEG2TBFI, - "PEG2TBFI-SD"}, - {0x8086, 0x1079, SILICOM_SVID, SILICOM_PXG2TBI_SSID, PXG2TBI, - "PXG2TBI-SD"}, - {0x8086, 0x107a, SILICOM_SVID, SILICOM_PXG4BPFID_SSID, PXG4BPFID, - "PXG4BPFID-SD"}, - {0x8086, 0x105f, SILICOM_SVID, SILICOM_PEG4BPFI_SSID, PEG4BPFI, - "PEG4BPFI-SD"}, - {0x8086, 0x105e, SILICOM_SVID, SILICOM_PEG4BPIPT_SSID, PEG4BPIPT, - "PEG4BPIPT-SD"}, - {0x8086, 0x1079, SILICOM_SVID, SILICOM_PXG6BPI_SSID, PXG6BPI, - "PXG6BPI-SD"}, - {0x8086, 0x10a7, SILICOM_SVID /*PCI_ANY_ID */ , - SILICOM_PEG4BPIL_SSID /*PCI_ANY_ID */ , PEG4BPIL, "PEG4BPIL-SD"}, - {0x8086, 0x1079, NOKIA_PMCXG2BPFIN_SVID, NOKIA_PMCXG2BPIN2_SSID, - PMCXG2BPIN2, "PMCX2BPI-N2"}, - {0x8086, 0x1079, NOKIA_PMCXG2BPFIN_SVID, NOKIA_PMCXG4BPIN2_SSID, - PMCXG4BPIN2, "PMCX4BPI-N2"}, - {0x8086, 0x1079, SILICOM_SVID, SILICOM_PMCX2BPI_SSID, PMCX2BPI, - "PMCX2BPI-SD"}, - {0x8086, 0x1079, SILICOM_SVID, SILICOM_PMCX4BPI_SSID, PMCX4BPI, - "PMCX4BPI-SD"}, - {0x8086, 0x105f, SILICOM_SVID, SILICOM_PEG2BPFID_SSID, PEG2BPFID, - "PEG2BPFID-SD"}, - {0x8086, 0x105f, SILICOM_SVID, SILICOM_PEG2BPFIDLX_SSID, PEG2BPFIDLX, - "PEG2BPFIDLXSD"}, - {0x8086, 0x105f, SILICOM_SVID, SILICOM_MEG2BPFILN_SSID, MEG2BPFILN, - "MEG2BPFILN-SD"}, - {0x8086, 0x105f, SILICOM_SVID, SILICOM_MEG2BPFINX_SSID, MEG2BPFINX, - "MEG2BPFINX-SD"}, - {0x8086, 0x105f, SILICOM_SVID, SILICOM_PEG4BPFILX_SSID, PEG4BPFILX, - "PEG4BPFILX-SD"}, - {0x8086, PCI_ANY_ID, SILICOM_SVID, SILICOM_PE10G2BPISR_SSID, - PE10G2BPISR, "PE10G2BPISR"}, - {0x8086, PCI_ANY_ID, SILICOM_SVID, SILICOM_PE10G2BPILR_SSID, - PE10G2BPILR, "PE10G2BPILR"}, - {0x8086, 0x10a9, SILICOM_SVID, SILICOM_MHIO8AD_SSID, MHIO8AD, - "MHIO8AD-SD"}, - {0x8086, PCI_ANY_ID, SILICOM_SVID, SILICOM_PE10G2BPICX4_SSID, - PE10G2BPISR, "PE10G2BPICX4"}, - {0x8086, 0x10a7, SILICOM_SVID /*PCI_ANY_ID */ , - SILICOM_PEG2BPI5_SSID /*PCI_ANY_ID */ , PEG2BPI5, "PEG2BPI5-SD"}, - {0x8086, 0x10a7, SILICOM_SVID /*PCI_ANY_ID */ , - SILICOM_PEG6BPI_SSID /*PCI_ANY_ID */ , PEG6BPI, "PEG6BPI5"}, - {0x8086, 0x10a9, SILICOM_SVID /*PCI_ANY_ID */ , SILICOM_PEG4BPFI5_SSID, - PEG4BPFI5, "PEG4BPFI5"}, - {0x8086, 0x10a9, SILICOM_SVID /*PCI_ANY_ID */ , - SILICOM_PEG4BPFI5LX_SSID, PEG4BPFI5LX, "PEG4BPFI5LX"}, - {0x8086, 0x105f, SILICOM_SVID, SILICOM_MEG2BPFILXLN_SSID, MEG2BPFILXLN, - "MEG2BPFILXLN"}, - {0x8086, 0x105e, SILICOM_SVID, SILICOM_PEG2BPIX1_SSID, PEG2BPIX1, - "PEG2BPIX1-SD"}, - {0x8086, 0x105f, SILICOM_SVID, SILICOM_MEG2BPFILXNX_SSID, MEG2BPFILXNX, - "MEG2BPFILXNX"}, - {0x8086, PCI_ANY_ID, SILICOM_SVID, SILICOM_XE10G2BPIT_SSID, XE10G2BPIT, - "XE10G2BPIT"}, - {0x8086, PCI_ANY_ID, SILICOM_SVID, SILICOM_XE10G2BPICX4_SSID, - XE10G2BPICX4, "XE10G2BPICX4"}, - {0x8086, 0x10C6, SILICOM_SVID, SILICOM_XE10G2BPISR_SSID, XE10G2BPISR, - "XE10G2BPISR"}, - {0x8086, 0x10C6, SILICOM_SVID, SILICOM_XE10G2BPILR_SSID, XE10G2BPILR, - "XE10G2BPILR"}, - {0x8086, 0x10C6, NOKIA_XE10G2BPIXR_SVID, NOKIA_XE10G2BPIXR_SSID, - XE10G2BPIXR, "XE10G2BPIXR"}, - {0x8086, 0x10C6, SILICOM_SVID, SILICOM_PE10GDBISR_SSID, PE10GDBISR, - "PE10G2DBISR"}, - {0x8086, 0x10C6, SILICOM_SVID, SILICOM_PE10GDBILR_SSID, PE10GDBILR, - "PE10G2DBILR"}, - {0x8086, 0x10a7, SILICOM_SVID /*PCI_ANY_ID */ , - SILICOM_PEG2BISC6_SSID /*PCI_ANY_ID */ , PEG2BISC6, "PEG2BI5SC6"}, - {0x8086, 0x10a7, SILICOM_SVID /*PCI_ANY_ID */ , - SILICOM_PEG6BPIFC_SSID /*PCI_ANY_ID */ , PEG6BPIFC, "PEG6BPI5FC"}, - - {BROADCOM_VID, BROADCOM_PE10G2_PID, SILICOM_SVID, - SILICOM_PE10G2BPTCX4_SSID, PE10G2BPTCX4, "PE10G2BPTCX4"}, - {BROADCOM_VID, BROADCOM_PE10G2_PID, SILICOM_SVID, - SILICOM_PE10G2BPTSR_SSID, PE10G2BPTSR, "PE10G2BPTSR"}, - {BROADCOM_VID, BROADCOM_PE10G2_PID, SILICOM_SVID, - SILICOM_PE10G2BPTLR_SSID, PE10G2BPTLR, "PE10G2BPTLR"}, - {BROADCOM_VID, BROADCOM_PE10G2_PID, SILICOM_SVID, - SILICOM_PE10G2BPTT_SSID, PE10G2BPTT, "PE10G2BPTT"}, - - /* {BROADCOM_VID, BROADCOM_PE10G2_PID, PCI_ANY_ID, PCI_ANY_ID, PE10G2BPTCX4, "PE10G2BPTCX4"}, */ - - {0x8086, 0x10c9, SILICOM_SVID /*PCI_ANY_ID */ , - SILICOM_PEG4BPI6_SSID /*PCI_ANY_ID */ , PEG4BPI6, "PEG4BPI6"}, - {0x8086, 0x10e6, SILICOM_SVID /*PCI_ANY_ID */ , - SILICOM_PEG4BPFI6_SSID /*PCI_ANY_ID */ , PEG4BPFI6, "PEG4BPFI6"}, - {0x8086, 0x10e6, SILICOM_SVID /*PCI_ANY_ID */ , - SILICOM_PEG4BPFI6LX_SSID /*PCI_ANY_ID */ , PEG4BPFI6LX, "PEG4BPFI6LX"}, - {0x8086, 0x10e6, SILICOM_SVID /*PCI_ANY_ID */ , - SILICOM_PEG4BPFI6ZX_SSID /*PCI_ANY_ID */ , PEG4BPFI6ZX, "PEG4BPFI6ZX"}, - {0x8086, 0x10c9, SILICOM_SVID /*PCI_ANY_ID */ , - SILICOM_PEG2BPI6_SSID /*PCI_ANY_ID */ , PEG2BPI6, "PEG2BPI6"}, - {0x8086, 0x10e6, SILICOM_SVID /*PCI_ANY_ID */ , - SILICOM_PEG2BPFI6_SSID /*PCI_ANY_ID */ , PEG2BPFI6, "PEG2BPFI6"}, - {0x8086, 0x10e6, SILICOM_SVID /*PCI_ANY_ID */ , - SILICOM_PEG2BPFI6LX_SSID /*PCI_ANY_ID */ , PEG2BPFI6LX, "PEG2BPFI6LX"}, - {0x8086, 0x10e6, SILICOM_SVID /*PCI_ANY_ID */ , - SILICOM_PEG2BPFI6ZX_SSID /*PCI_ANY_ID */ , PEG2BPFI6ZX, "PEG2BPFI6ZX"}, - {0x8086, 0x10e7, SILICOM_SVID /*PCI_ANY_ID */ , - SILICOM_PEG2BPFI6FLXM_SSID /*PCI_ANY_ID */ , PEG2BPFI6FLXM, - "PEG2BPFI6FLXM"}, - {0x8086, 0x10c9, SILICOM_SVID /*PCI_ANY_ID */ , - SILICOM_PEG4BPI6FC_SSID /*PCI_ANY_ID */ , PEG4BPI6FC, "PEG4BPI6FC"}, - {0x8086, 0x10e6, SILICOM_SVID /*PCI_ANY_ID */ , - SILICOM_PEG4BPFI6FC_SSID /*PCI_ANY_ID */ , PEG4BPFI6FC, "PEG4BPFI6FC"}, - {0x8086, 0x10e6, SILICOM_SVID /*PCI_ANY_ID */ , - SILICOM_PEG4BPFI6FCLX_SSID /*PCI_ANY_ID */ , PEG4BPFI6FCLX, - "PEG4BPFI6FCLX"}, - {0x8086, 0x10e6, SILICOM_SVID /*PCI_ANY_ID */ , - SILICOM_PEG4BPFI6FCZX_SSID /*PCI_ANY_ID */ , PEG4BPFI6FCZX, - "PEG4BPFI6FCZX"}, - {0x8086, 0x10c9, SILICOM_SVID /*PCI_ANY_ID */ , - SILICOM_PEG6BPI6_SSID /*PCI_ANY_ID */ , PEG6BPI6, "PEG6BPI6"}, - {0x8086, 0x10c9, SILICOM_SVID /*PCI_ANY_ID */ , - SILICOM_PEG2BPI6SC6_SSID /*PCI_ANY_ID */ , PEG2BPI6SC6, - "PEG6BPI62SC6"}, - {0x8086, 0x10c9, SILICOM_SVID /*PCI_ANY_ID */ , - SILICOM_MEG2BPI6_SSID /*PCI_ANY_ID */ , MEG2BPI6, "MEG2BPI6"}, - {0x8086, 0x10c9, SILICOM_SVID /*PCI_ANY_ID */ , - SILICOM_XEG2BPI6_SSID /*PCI_ANY_ID */ , XEG2BPI6, "XEG2BPI6"}, - {0x8086, 0x10c9, SILICOM_SVID /*PCI_ANY_ID */ , - SILICOM_MEG4BPI6_SSID /*PCI_ANY_ID */ , MEG4BPI6, "MEG4BPI6"}, - - {0x8086, 0x10a9, SILICOM_SVID /*PCI_ANY_ID */ , SILICOM_PEG2BPFI5_SSID, - PEG2BPFI5, "PEG2BPFI5"}, - {0x8086, 0x10a9, SILICOM_SVID /*PCI_ANY_ID */ , - SILICOM_PEG2BPFI5LX_SSID, PEG2BPFI5LX, "PEG2BPFI5LX"}, - - {0x8086, 0x105f, SILICOM_SVID, SILICOM_PXEG4BPFI_SSID, PXEG4BPFI, - "PXEG4BPFI-SD"}, - - {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , - SILICOM_M1EG2BPI6_SSID /*PCI_ANY_ID */ , M1EG2BPI6, "MxEG2BPI6"}, - - {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , - SILICOM_M1EG2BPFI6_SSID /*PCI_ANY_ID */ , M1EG2BPFI6, "MxEG2BPFI6"}, - {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , - SILICOM_M1EG2BPFI6LX_SSID /*PCI_ANY_ID */ , M1EG2BPFI6LX, - "MxEG2BPFI6LX"}, - {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , - SILICOM_M1EG2BPFI6ZX_SSID /*PCI_ANY_ID */ , M1EG2BPFI6ZX, - "MxEG2BPFI6ZX"}, - - {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , - SILICOM_M1EG4BPI6_SSID /*PCI_ANY_ID */ , M1EG4BPI6, "MxEG4BPI6"}, - - {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , - SILICOM_M1EG4BPFI6_SSID /*PCI_ANY_ID */ , M1EG4BPFI6, "MxEG4BPFI6"}, - {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , - SILICOM_M1EG4BPFI6LX_SSID /*PCI_ANY_ID */ , M1EG4BPFI6LX, - "MxEG4BPFI6LX"}, - {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , - SILICOM_M1EG4BPFI6ZX_SSID /*PCI_ANY_ID */ , M1EG4BPFI6ZX, - "MxEG4BPFI6ZX"}, - - {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , - SILICOM_M1EG6BPI6_SSID /*PCI_ANY_ID */ , M1EG6BPI6, "MxEG6BPI6"}, - - {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , - SILICOM_M1E2G4BPi80_SSID /*PCI_ANY_ID */ , M1E2G4BPi80, "MxE2G4BPi80"}, - {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , - SILICOM_M1E2G4BPFi80_SSID /*PCI_ANY_ID */ , M1E2G4BPFi80, - "MxE2G4BPFi80"}, - {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , - SILICOM_M1E2G4BPFi80LX_SSID /*PCI_ANY_ID */ , M1E2G4BPFi80LX, - "MxE2G4BPFi80LX"}, - {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , - SILICOM_M1E2G4BPFi80ZX_SSID /*PCI_ANY_ID */ , M1E2G4BPFi80ZX, - "MxE2G4BPFi80ZX"}, - - {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , - SILICOM_M2EG2BPFI6_SSID /*PCI_ANY_ID */ , M2EG2BPFI6, "M2EG2BPFI6"}, - {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , - SILICOM_M2EG2BPFI6LX_SSID /*PCI_ANY_ID */ , M2EG2BPFI6LX, - "M2EG2BPFI6LX"}, - {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , - SILICOM_M2EG2BPFI6ZX_SSID /*PCI_ANY_ID */ , M2EG2BPFI6ZX, - "M2EG2BPFI6ZX"}, - - {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , - SILICOM_M2EG4BPI6_SSID /*PCI_ANY_ID */ , M2EG4BPI6, "M2EG4BPI6"}, - - {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , - SILICOM_M2EG4BPFI6_SSID /*PCI_ANY_ID */ , M2EG4BPFI6, "M2EG4BPFI6"}, - {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , - SILICOM_M2EG4BPFI6LX_SSID /*PCI_ANY_ID */ , M2EG4BPFI6LX, - "M2EG4BPFI6LX"}, - {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , - SILICOM_M2EG4BPFI6ZX_SSID /*PCI_ANY_ID */ , M2EG4BPFI6ZX, - "M2EG4BPFI6ZX"}, - - {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , - SILICOM_M2EG6BPI6_SSID /*PCI_ANY_ID */ , M2EG6BPI6, "M2EG6BPI6"}, - - {0x8086, 0x10c9, SILICOM_SVID /*PCI_ANY_ID */ , - SILICOM_PEG2DBI6_SSID /*PCI_ANY_ID */ , PEG2DBI6, "PEG2DBI6"}, - {0x8086, 0x10e6, SILICOM_SVID /*PCI_ANY_ID */ , - SILICOM_PEG2DBFI6_SSID /*PCI_ANY_ID */ , PEG2DBFI6, "PEG2DBFI6"}, - {0x8086, 0x10e6, SILICOM_SVID /*PCI_ANY_ID */ , - SILICOM_PEG2DBFI6LX_SSID /*PCI_ANY_ID */ , PEG2DBFI6LX, "PEG2DBFI6LX"}, - {0x8086, 0x10e6, SILICOM_SVID /*PCI_ANY_ID */ , - SILICOM_PEG2DBFI6ZX_SSID /*PCI_ANY_ID */ , PEG2DBFI6ZX, "PEG2DBFI6ZX"}, - - {0x8086, 0x10F9, SILICOM_SVID /*PCI_ANY_ID */ , - SILICOM_PE210G2DBi9SR_SSID, PE210G2DBi9SR, "PE210G2DBi9SR"}, - {0x8086, 0x10F9, SILICOM_SVID /*PCI_ANY_ID */ , - SILICOM_PE210G2DBi9LR_SSID, PE210G2DBi9LR, "PE210G2DBi9LR"}, - {0x8086, 0x10F9, SILICOM_SVID /*PCI_ANY_ID */ , - SILICOM_PE310G4DBi940SR_SSID, PE310G4DBi940SR, "PE310G4DBi9SR"}, - - {0x8086, 0x10Fb, SILICOM_SVID /*PCI_ANY_ID */ , - SILICOM_PE310G4BPi9T_SSID, PE310G4BPi9T, "PE310G4BPi9T"}, - {0x8086, 0x10Fb, SILICOM_SVID /*PCI_ANY_ID */ , - SILICOM_PE310G4BPi9SR_SSID, PE310G4BPi9SR, "PE310G4BPi9SR"}, - {0x8086, 0x10Fb, SILICOM_SVID /*PCI_ANY_ID */ , - SILICOM_PE310G4BPi9LR_SSID, PE310G4BPi9LR, "PE310G4BPi9LR"}, - - {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , - SILICOM_PE2G4BPi80_SSID /*PCI_ANY_ID */ , PE2G4BPi80, "PE2G4BPi80"}, - {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , - SILICOM_PE2G4BPFi80_SSID /*PCI_ANY_ID */ , PE2G4BPFi80, "PE2G4BPFi80"}, - {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , - SILICOM_PE2G4BPFi80LX_SSID /*PCI_ANY_ID */ , PE2G4BPFi80LX, - "PE2G4BPFi80LX"}, - {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , - SILICOM_PE2G4BPFi80ZX_SSID /*PCI_ANY_ID */ , PE2G4BPFi80ZX, - "PE2G4BPFi80ZX"}, - - {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , - SILICOM_PE2G4BPi80L_SSID /*PCI_ANY_ID */ , PE2G4BPi80L, "PE2G4BPi80L"}, - - {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , - SILICOM_M6E2G8BPi80A_SSID /*PCI_ANY_ID */ , M6E2G8BPi80A, - "MxE2G8BPi80A"}, - - {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , - SILICOM_PE2G2BPi35_SSID /*PCI_ANY_ID */ , PE2G2BPi35, "PE2G2BPi35"}, - {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , - SILICOM_PAC1200BPi35_SSID /*PCI_ANY_ID */ , PAC1200BPi35, - "PAC1200BPi35"}, - - {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , - SILICOM_PE2G2BPFi35_SSID /*PCI_ANY_ID */ , PE2G2BPFi35, "PE2G2BPFi35"}, - {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , - SILICOM_PE2G2BPFi35LX_SSID /*PCI_ANY_ID */ , PE2G2BPFi35LX, - "PE2G2BPFi35LX"}, - {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , - SILICOM_PE2G2BPFi35ZX_SSID /*PCI_ANY_ID */ , PE2G2BPFi35ZX, - "PE2G2BPFi35ZX"}, - - {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , - SILICOM_PE2G4BPi35_SSID /*PCI_ANY_ID */ , PE2G4BPi35, "PE2G4BPi35"}, - - {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , - SILICOM_PE2G4BPi35L_SSID /*PCI_ANY_ID */ , PE2G4BPi35L, "PE2G4BPi35L"}, - - {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , - SILICOM_PE2G4BPFi35_SSID /*PCI_ANY_ID */ , PE2G4BPFi35, "PE2G4BPFi35"}, - {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , - SILICOM_PE2G4BPFi35LX_SSID /*PCI_ANY_ID */ , PE2G4BPFi35LX, - "PE2G4BPFi35LX"}, - {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , - SILICOM_PE2G4BPFi35ZX_SSID /*PCI_ANY_ID */ , PE2G4BPFi35ZX, - "PE2G4BPFi35ZX"}, - - {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , - SILICOM_PE2G6BPi35_SSID /*PCI_ANY_ID */ , PE2G6BPi35, "PE2G6BPi35"}, - - - {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , 0xaa0, PE2G6BPi35CX, - "PE2G6BPi35CX"}, - {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , 0xaa1, PE2G6BPi35CX, - "PE2G6BPi35CX"}, - {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , 0xaa2, PE2G6BPi35CX, - "PE2G6BPi35CX"}, - {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , 0xaa3, PE2G6BPi35CX, - "PE2G6BPi35CX"}, - {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , 0xaa4, PE2G6BPi35CX, - "PE2G6BPi35CX"}, - {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , 0xaa5, PE2G6BPi35CX, - "PE2G6BPi35CX"}, - {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , 0xaa6, PE2G6BPi35CX, - "PE2G6BPi35CX"}, - {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , 0xaa7, PE2G6BPi35CX, - "PE2G6BPi35CX"}, - {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , 0xaa8, PE2G6BPi35CX, - "PE2G6BPi35CX"}, - {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , 0xaa9, PE2G6BPi35CX, - "PE2G6BPi35CX"}, - {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , 0xaaa, PE2G6BPi35CX, - "PE2G6BPi35CX"}, - {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , 0xaab, PE2G6BPi35CX, - "PE2G6BPi35CX"}, - {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , 0xaac, PE2G6BPi35CX, - "PE2G6BPi35CX"}, - {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , 0xaad, PE2G6BPi35CX, - "PE2G6BPi35CX"}, - {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , 0xaae, PE2G6BPi35CX, - "PE2G6BPi35CX"}, - {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , 0xaaf, PE2G6BPi35CX, - "PE2G6BPi35CX"}, - {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , 0xab0, PE2G6BPi35CX, - "PE2G6BPi35CX"}, - {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , 0xab1, PE2G6BPi35CX, - "PE2G6BPi35CX"}, - {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , 0xab2, PE2G6BPi35CX, - "PE2G6BPi35CX"}, - {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , 0xab3, PE2G6BPi35CX, - "PE2G6BPi35CX"}, - {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , 0xab4, PE2G6BPi35CX, - "PE2G6BPi35CX"}, - {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , 0xab5, PE2G6BPi35CX, - "PE2G6BPi35CX"}, - {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , 0xab6, PE2G6BPi35CX, - "PE2G6BPi35CX"}, - {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , 0xab7, PE2G6BPi35CX, - "PE2G6BPi35CX"}, - {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , 0xab8, PE2G6BPi35CX, - "PE2G6BPi35CX"}, - {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , 0xab9, PE2G6BPi35CX, - "PE2G6BPi35CX"}, - {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , 0xaba, PE2G6BPi35CX, - "PE2G6BPi35CX"}, - {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , 0xabb, PE2G6BPi35CX, - "PE2G6BPi35CX"}, - {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , 0xabc, PE2G6BPi35CX, - "PE2G6BPi35CX"}, - {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , 0xabd, PE2G6BPi35CX, - "PE2G6BPi35CX"}, - {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , 0xabe, PE2G6BPi35CX, - "PE2G6BPi35CX"}, - {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , 0xabf, PE2G6BPi35CX, - "PE2G6BPi35CX"}, - - {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , - SILICOM_PE2G2BPi80_SSID /*PCI_ANY_ID */ , PE2G2BPi80, "PE2G2BPi80"}, - {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , - SILICOM_PE2G2BPFi80_SSID /*PCI_ANY_ID */ , PE2G2BPFi80, "PE2G2BPFi80"}, - {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , - SILICOM_PE2G2BPFi80LX_SSID /*PCI_ANY_ID */ , PE2G2BPFi80LX, - "PE2G2BPFi80LX"}, - {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , - SILICOM_PE2G2BPFi80ZX_SSID /*PCI_ANY_ID */ , PE2G2BPFi80ZX, - "PE2G2BPFi80ZX"}, - - {0x8086, 0x10c9, SILICOM_SVID /*PCI_ANY_ID */ , - SILICOM_MEG2BPI6_SSID /*PCI_ANY_ID */ , MEG2BPI6, "MEG2BPI6"}, - {0x8086, 0x10c9, SILICOM_SVID /*PCI_ANY_ID */ , - SILICOM_XEG2BPI6_SSID /*PCI_ANY_ID */ , XEG2BPI6, "XEG2BPI6"}, - -#if 0 - {0x8086, 0x10fb, 0x8086, INTEL_PE210G2SPI9_SSID, PE210G2SPI9, - "PE210G2SPI9"}, -#endif - {0x8086, 0x10fb, SILICOM_SVID /*PCI_ANY_ID */ , - SILICOM_M1E10G2BPI9CX4_SSID /*PCI_ANY_ID */ , M1E10G2BPI9CX4, - "MxE210G2BPI9CX4"}, - {0x8086, 0x10fb, SILICOM_SVID /*PCI_ANY_ID */ , - SILICOM_M1E10G2BPI9SR_SSID /*PCI_ANY_ID */ , M1E10G2BPI9SR, - "MxE210G2BPI9SR"}, - {0x8086, 0x10fb, SILICOM_SVID /*PCI_ANY_ID */ , - SILICOM_M1E10G2BPI9LR_SSID /*PCI_ANY_ID */ , M1E10G2BPI9LR, - "MxE210G2BPI9LR"}, - {0x8086, 0x10fb, SILICOM_SVID /*PCI_ANY_ID */ , - SILICOM_M1E10G2BPI9T_SSID /*PCI_ANY_ID */ , M1E10G2BPI9T, - "MxE210G2BPI9T"}, - - {0x8086, 0x10fb, SILICOM_SVID /*PCI_ANY_ID */ , - SILICOM_M2E10G2BPI9CX4_SSID /*PCI_ANY_ID */ , M2E10G2BPI9CX4, - "M2E10G2BPI9CX4"}, - {0x8086, 0x10fb, SILICOM_SVID /*PCI_ANY_ID */ , - SILICOM_M2E10G2BPI9SR_SSID /*PCI_ANY_ID */ , M2E10G2BPI9SR, - "M2E10G2BPI9SR"}, - {0x8086, 0x10fb, SILICOM_SVID /*PCI_ANY_ID */ , - SILICOM_M2E10G2BPI9LR_SSID /*PCI_ANY_ID */ , M2E10G2BPI9LR, - "M2E10G2BPI9LR"}, - {0x8086, 0x10fb, SILICOM_SVID /*PCI_ANY_ID */ , - SILICOM_M2E10G2BPI9T_SSID /*PCI_ANY_ID */ , M2E10G2BPI9T, - "M2E10G2BPI9T"}, - - {0x8086, 0x10fb, SILICOM_SVID, SILICOM_PE210G2BPI9CX4_SSID, - PE210G2BPI9CX4, "PE210G2BPI9CX4"}, - {0x8086, 0x10fb, SILICOM_SVID, SILICOM_PE210G2BPI9SR_SSID, - PE210G2BPI9SR, "PE210G2BPI9SR"}, - {0x8086, 0x10fb, SILICOM_SVID, SILICOM_PE210G2BPI9LR_SSID, - PE210G2BPI9LR, "PE210G2BPI9LR"}, - {0x8086, 0x10fb, SILICOM_SVID, SILICOM_PE210G2BPI9T_SSID, PE210G2BPI9T, - "PE210G2BPI9T"}, - -#if 0 - {0x1374, 0x2c, SILICOM_SVID, SILICOM_PXG4BPI_SSID, PXG4BPI, - "PXG4BPI-SD"}, - - {0x1374, 0x2d, SILICOM_SVID, SILICOM_PXG4BPFI_SSID, PXG4BPFI, - "PXG4BPFI-SD"}, - - {0x1374, 0x3f, SILICOM_SVID, SILICOM_PXG2TBI_SSID, PXG2TBI, - "PXG2TBI-SD"}, - - {0x1374, 0x3d, SILICOM_SVID, SILICOM_PXG2BISC1_SSID, PXG2BISC1, - "PXG2BISC1-SD"}, - - {0x1374, 0x40, SILICOM_SVID, SILICOM_PEG4BPFI_SSID, PEG4BPFI, - "PEG4BPFI-SD"}, - -#ifdef BP_SELF_TEST - {0x1374, 0x28, SILICOM_SVID, 0x28, PXGBPI, "PXG2BPI-SD"}, -#endif -#endif - {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , - SILICOM_M6E2G8BPi80_SSID /*PCI_ANY_ID */ , M6E2G8BPi80, "MxE2G8BPi80"}, - {0x8086, 0x1528, SILICOM_SVID /*PCI_ANY_ID */ , - SILICOM_PE210G2BPi40_SSID /*PCI_ANY_ID */ , PE210G2BPi40, - "PE210G2BPi40T"}, - - /* required last entry */ - {0,} -}; - -/* -* Initialize the module - Register the character device -*/ - -static int __init bypass_init_module(void) -{ - int ret_val, idx, idx_dev = 0; - struct pci_dev *pdev1 = NULL; - unsigned long mmio_start, mmio_len; - - printk(BP_MOD_DESCR " v" BP_MOD_VER "\n"); - ret_val = register_chrdev(major_num, DEVICE_NAME, &Fops); - if (ret_val < 0) { - printk("%s failed with %d\n", DEVICE_NAME, ret_val); - return ret_val; - } - major_num = ret_val; /* dynamic */ - for (idx = 0; tx_ctl_pci_tbl[idx].vendor; idx++) { - while ((pdev1 = pci_get_subsys(tx_ctl_pci_tbl[idx].vendor, - tx_ctl_pci_tbl[idx].device, - tx_ctl_pci_tbl[idx].subvendor, - tx_ctl_pci_tbl[idx].subdevice, - pdev1))) { - - device_num++; - } - } - if (!device_num) { - printk("No such device\n"); - unregister_chrdev(major_num, DEVICE_NAME); - return -1; - } - - bpctl_dev_arr = kmalloc((device_num) * sizeof(bpctl_dev_t), GFP_KERNEL); - - if (!bpctl_dev_arr) { - printk("Allocation error\n"); - unregister_chrdev(major_num, DEVICE_NAME); - return -1; - } - memset(bpctl_dev_arr, 0, ((device_num) * sizeof(bpctl_dev_t))); - - pdev1 = NULL; - for (idx = 0; tx_ctl_pci_tbl[idx].vendor; idx++) { - while ((pdev1 = pci_get_subsys(tx_ctl_pci_tbl[idx].vendor, - tx_ctl_pci_tbl[idx].device, - tx_ctl_pci_tbl[idx].subvendor, - tx_ctl_pci_tbl[idx].subdevice, - pdev1))) { - bpctl_dev_arr[idx_dev].pdev = pdev1; - - mmio_start = pci_resource_start(pdev1, 0); - mmio_len = pci_resource_len(pdev1, 0); - - bpctl_dev_arr[idx_dev].desc = - dev_desc[tx_ctl_pci_tbl[idx].index].name; - bpctl_dev_arr[idx_dev].name = - tx_ctl_pci_tbl[idx].bp_name; - bpctl_dev_arr[idx_dev].device = - tx_ctl_pci_tbl[idx].device; - bpctl_dev_arr[idx_dev].vendor = - tx_ctl_pci_tbl[idx].vendor; - bpctl_dev_arr[idx_dev].subdevice = - tx_ctl_pci_tbl[idx].subdevice; - bpctl_dev_arr[idx_dev].subvendor = - tx_ctl_pci_tbl[idx].subvendor; - /* bpctl_dev_arr[idx_dev].pdev=pdev1; */ - bpctl_dev_arr[idx_dev].func = PCI_FUNC(pdev1->devfn); - bpctl_dev_arr[idx_dev].slot = PCI_SLOT(pdev1->devfn); - bpctl_dev_arr[idx_dev].bus = pdev1->bus->number; - bpctl_dev_arr[idx_dev].mem_map = - (unsigned long)ioremap(mmio_start, mmio_len); -#ifdef BP_SYNC_FLAG - spin_lock_init(&bpctl_dev_arr[idx_dev].bypass_wr_lock); -#endif - if (BP10G9_IF_SERIES(bpctl_dev_arr[idx_dev].subdevice)) - bpctl_dev_arr[idx_dev].bp_10g9 = 1; - if (BP10G_IF_SERIES(bpctl_dev_arr[idx_dev].subdevice)) - bpctl_dev_arr[idx_dev].bp_10g = 1; - if (PEG540_IF_SERIES(bpctl_dev_arr[idx_dev].subdevice)) { - - bpctl_dev_arr[idx_dev].bp_540 = 1; - } - if (PEGF5_IF_SERIES(bpctl_dev_arr[idx_dev].subdevice)) - bpctl_dev_arr[idx_dev].bp_fiber5 = 1; - if (PEG80_IF_SERIES(bpctl_dev_arr[idx_dev].subdevice)) - bpctl_dev_arr[idx_dev].bp_i80 = 1; - if (PEGF80_IF_SERIES(bpctl_dev_arr[idx_dev].subdevice)) - bpctl_dev_arr[idx_dev].bp_i80 = 1; - if ((bpctl_dev_arr[idx_dev].subdevice & 0xa00) == 0xa00) - bpctl_dev_arr[idx_dev].bp_i80 = 1; - if (BP10GB_IF_SERIES(bpctl_dev_arr[idx_dev].subdevice)) { - if (bpctl_dev_arr[idx_dev].ifindex == 0) { - unregister_chrdev(major_num, - DEVICE_NAME); - printk - ("Please load network driver for %s adapter!\n", - bpctl_dev_arr[idx_dev].name); - return -1; - } - - if (bpctl_dev_arr[idx_dev].ndev) { - if (! - (bpctl_dev_arr[idx_dev].ndev-> - flags & IFF_UP)) { - if (! - (bpctl_dev_arr[idx_dev]. - ndev->flags & IFF_UP)) { - unregister_chrdev - (major_num, - DEVICE_NAME); - printk - ("Please bring up network interfaces for %s adapter!\n", - bpctl_dev_arr - [idx_dev].name); - return -1; - } - - } - } - bpctl_dev_arr[idx_dev].bp_10gb = 1; - } - - if (!bpctl_dev_arr[idx_dev].bp_10g9) { - - if (is_bypass_fn(&bpctl_dev_arr[idx_dev])) { - printk(KERN_INFO "%s found, ", - bpctl_dev_arr[idx_dev].name); - if ((OLD_IF_SERIES - (bpctl_dev_arr[idx_dev].subdevice)) - || - (INTEL_IF_SERIES - (bpctl_dev_arr[idx_dev]. - subdevice))) - bpctl_dev_arr[idx_dev]. - bp_fw_ver = 0xff; - else - bpctl_dev_arr[idx_dev]. - bp_fw_ver = - bypass_fw_ver(&bpctl_dev_arr - [idx_dev]); - if ((bpctl_dev_arr[idx_dev].bp_10gb == - 1) - && (bpctl_dev_arr[idx_dev]. - bp_fw_ver == 0xff)) { - int cnt = 100; - while (cnt--) { - iounmap((void - *) - (bpctl_dev_arr - [idx_dev]. - mem_map)); - mmio_start = - pci_resource_start - (pdev1, 0); - mmio_len = - pci_resource_len - (pdev1, 0); - - bpctl_dev_arr[idx_dev]. - mem_map = - (unsigned long) - ioremap(mmio_start, - mmio_len); - - bpctl_dev_arr[idx_dev]. - bp_fw_ver = - bypass_fw_ver - (&bpctl_dev_arr - [idx_dev]); - if (bpctl_dev_arr - [idx_dev]. - bp_fw_ver == 0xa8) - break; - - } - } - /* bpctl_dev_arr[idx_dev].bp_fw_ver=0xa8; */ - printk("firmware version: 0x%x\n", - bpctl_dev_arr[idx_dev]. - bp_fw_ver); - } - bpctl_dev_arr[idx_dev].wdt_status = - WDT_STATUS_UNKNOWN; - bpctl_dev_arr[idx_dev].reset_time = 0; - atomic_set(&bpctl_dev_arr[idx_dev].wdt_busy, 0); - bpctl_dev_arr[idx_dev].bp_status_un = 1; - - bypass_caps_init(&bpctl_dev_arr[idx_dev]); - - init_bypass_wd_auto(&bpctl_dev_arr[idx_dev]); - init_bypass_tpl_auto(&bpctl_dev_arr[idx_dev]); - if (NOKIA_SERIES - (bpctl_dev_arr[idx_dev].subdevice)) - reset_cont(&bpctl_dev_arr[idx_dev]); - } -#ifdef BP_SELF_TEST - if ((bpctl_dev_arr[idx_dev].bp_tx_data = - kmalloc(BPTEST_DATA_LEN, GFP_KERNEL))) { - - memset(bpctl_dev_arr[idx_dev].bp_tx_data, 0x0, - BPTEST_DATA_LEN); - - memset(bpctl_dev_arr[idx_dev].bp_tx_data, 0xff, - 6); - memset(bpctl_dev_arr[idx_dev].bp_tx_data + 6, - 0x0, 1); - memset(bpctl_dev_arr[idx_dev].bp_tx_data + 7, - 0xaa, 5); - -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,9)) - bpctl_dev_arr[idx_dev].bp_tx_data[12] = - (ETH_P_BPTEST >> 8) & 0xff; - bpctl_dev_arr[idx_dev].bp_tx_data[13] = - ETH_P_BPTEST & 0xff; -#else - *(__be16 *) (bpctl_dev_arr[idx_dev].bp_tx_data + - 12) = htons(ETH_P_BPTEST); -#endif - - } else - printk("bp_ctl: Memory allocation error!\n"); -#endif - idx_dev++; - - } - } - if_scan_init(); - - sema_init(&bpctl_sema, 1); - spin_lock_init(&bpvm_lock); - { - - bpctl_dev_t *pbpctl_dev_c = NULL; - for (idx_dev = 0; - ((bpctl_dev_arr[idx_dev].pdev != NULL) - && (idx_dev < device_num)); idx_dev++) { - if (bpctl_dev_arr[idx_dev].bp_10g9) { - pbpctl_dev_c = - get_status_port_fn(&bpctl_dev_arr[idx_dev]); - if (is_bypass_fn(&bpctl_dev_arr[idx_dev])) { - printk(KERN_INFO "%s found, ", - bpctl_dev_arr[idx_dev].name); - bpctl_dev_arr[idx_dev].bp_fw_ver = - bypass_fw_ver(&bpctl_dev_arr - [idx_dev]); - printk("firmware version: 0x%x\n", - bpctl_dev_arr[idx_dev]. - bp_fw_ver); - - } - bpctl_dev_arr[idx_dev].wdt_status = - WDT_STATUS_UNKNOWN; - bpctl_dev_arr[idx_dev].reset_time = 0; - atomic_set(&bpctl_dev_arr[idx_dev].wdt_busy, 0); - bpctl_dev_arr[idx_dev].bp_status_un = 1; - - bypass_caps_init(&bpctl_dev_arr[idx_dev]); - - init_bypass_wd_auto(&bpctl_dev_arr[idx_dev]); - init_bypass_tpl_auto(&bpctl_dev_arr[idx_dev]); - - } - - } - } - -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)) - inter_module_register("is_bypass_sd", THIS_MODULE, &is_bypass_sd); - inter_module_register("get_bypass_slave_sd", THIS_MODULE, - &get_bypass_slave_sd); - inter_module_register("get_bypass_caps_sd", THIS_MODULE, - &get_bypass_caps_sd); - inter_module_register("get_wd_set_caps_sd", THIS_MODULE, - &get_wd_set_caps_sd); - inter_module_register("set_bypass_sd", THIS_MODULE, &set_bypass_sd); - inter_module_register("get_bypass_sd", THIS_MODULE, &get_bypass_sd); - inter_module_register("get_bypass_change_sd", THIS_MODULE, - &get_bypass_change_sd); - inter_module_register("set_dis_bypass_sd", THIS_MODULE, - &set_dis_bypass_sd); - inter_module_register("get_dis_bypass_sd", THIS_MODULE, - &get_dis_bypass_sd); - inter_module_register("set_bypass_pwoff_sd", THIS_MODULE, - &set_bypass_pwoff_sd); - inter_module_register("get_bypass_pwoff_sd", THIS_MODULE, - &get_bypass_pwoff_sd); - inter_module_register("set_bypass_pwup_sd", THIS_MODULE, - &set_bypass_pwup_sd); - inter_module_register("get_bypass_pwup_sd", THIS_MODULE, - &get_bypass_pwup_sd); - inter_module_register("get_bypass_wd_sd", THIS_MODULE, - &get_bypass_wd_sd); - inter_module_register("set_bypass_wd_sd", THIS_MODULE, - &set_bypass_wd_sd); - inter_module_register("get_wd_expire_time_sd", THIS_MODULE, - &get_wd_expire_time_sd); - inter_module_register("reset_bypass_wd_timer_sd", THIS_MODULE, - &reset_bypass_wd_timer_sd); - inter_module_register("set_std_nic_sd", THIS_MODULE, &set_std_nic_sd); - inter_module_register("get_std_nic_sd", THIS_MODULE, &get_std_nic_sd); - inter_module_register("set_tx_sd", THIS_MODULE, &set_tx_sd); - inter_module_register("get_tx_sd", THIS_MODULE, &get_tx_sd); - inter_module_register("set_tpl_sd", THIS_MODULE, &set_tpl_sd); - inter_module_register("get_tpl_sd", THIS_MODULE, &get_tpl_sd); - - inter_module_register("set_bp_hw_reset_sd", THIS_MODULE, - &set_bp_hw_reset_sd); - inter_module_register("get_bp_hw_reset_sd", THIS_MODULE, - &get_bp_hw_reset_sd); - - inter_module_register("set_tap_sd", THIS_MODULE, &set_tap_sd); - inter_module_register("get_tap_sd", THIS_MODULE, &get_tap_sd); - inter_module_register("get_tap_change_sd", THIS_MODULE, - &get_tap_change_sd); - inter_module_register("set_dis_tap_sd", THIS_MODULE, &set_dis_tap_sd); - inter_module_register("get_dis_tap_sd", THIS_MODULE, &get_dis_tap_sd); - inter_module_register("set_tap_pwup_sd", THIS_MODULE, &set_tap_pwup_sd); - inter_module_register("get_tap_pwup_sd", THIS_MODULE, &get_tap_pwup_sd); - inter_module_register("set_bp_disc_sd", THIS_MODULE, &set_bp_disc_sd); - inter_module_register("get_bp_disc_sd", THIS_MODULE, &get_bp_disc_sd); - inter_module_register("get_bp_disc_change_sd", THIS_MODULE, - &get_bp_disc_change_sd); - inter_module_register("set_bp_dis_disc_sd", THIS_MODULE, - &set_bp_dis_disc_sd); - inter_module_register("get_bp_dis_disc_sd", THIS_MODULE, - &get_bp_dis_disc_sd); - inter_module_register("set_bp_disc_pwup_sd", THIS_MODULE, - &set_bp_disc_pwup_sd); - inter_module_register("get_bp_disc_pwup_sd", THIS_MODULE, - &get_bp_disc_pwup_sd); - inter_module_register("set_wd_exp_mode_sd", THIS_MODULE, - &set_wd_exp_mode_sd); - inter_module_register("get_wd_exp_mode_sd", THIS_MODULE, - &get_wd_exp_mode_sd); - inter_module_register("set_wd_autoreset_sd", THIS_MODULE, - &set_wd_autoreset_sd); - inter_module_register("get_wd_autoreset_sd", THIS_MODULE, - &get_wd_autoreset_sd); - inter_module_register("get_bypass_info_sd", THIS_MODULE, - &get_bypass_info_sd); - inter_module_register("bp_if_scan_sd", THIS_MODULE, &bp_if_scan_sd); - -#endif - register_netdevice_notifier(&bp_notifier_block); -#ifdef BP_PROC_SUPPORT - { - int i = 0; - /* unsigned long flags; */ - /* rcu_read_lock(); */ - bp_proc_create(); - for (i = 0; i < device_num; i++) { - if (bpctl_dev_arr[i].ifindex) { - /* spin_lock_irqsave(&bpvm_lock, flags); */ - bypass_proc_remove_dev_sd(&bpctl_dev_arr[i]); - bypass_proc_create_dev_sd(&bpctl_dev_arr[i]); - /* spin_unlock_irqrestore(&bpvm_lock, flags); */ - } - - } - /* rcu_read_unlock(); */ - } -#endif - - return 0; -} - -/* -* Cleanup - unregister the appropriate file from /proc -*/ -static void __exit bypass_cleanup_module(void) -{ - int i; -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23)) - int ret; -#endif - unregister_netdevice_notifier(&bp_notifier_block); - -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)) - inter_module_unregister("is_bypass_sd"); - inter_module_unregister("get_bypass_slave_sd"); - inter_module_unregister("get_bypass_caps_sd"); - inter_module_unregister("get_wd_set_caps_sd"); - inter_module_unregister("set_bypass_sd"); - inter_module_unregister("get_bypass_sd"); - inter_module_unregister("get_bypass_change_sd"); - inter_module_unregister("set_dis_bypass_sd"); - inter_module_unregister("get_dis_bypass_sd"); - inter_module_unregister("set_bypass_pwoff_sd"); - inter_module_unregister("get_bypass_pwoff_sd"); - inter_module_unregister("set_bypass_pwup_sd"); - inter_module_unregister("get_bypass_pwup_sd"); - inter_module_unregister("set_bypass_wd_sd"); - inter_module_unregister("get_bypass_wd_sd"); - inter_module_unregister("get_wd_expire_time_sd"); - inter_module_unregister("reset_bypass_wd_timer_sd"); - inter_module_unregister("set_std_nic_sd"); - inter_module_unregister("get_std_nic_sd"); - inter_module_unregister("set_tx_sd"); - inter_module_unregister("get_tx_sd"); - inter_module_unregister("set_tpl_sd"); - inter_module_unregister("get_tpl_sd"); - inter_module_unregister("set_tap_sd"); - inter_module_unregister("get_tap_sd"); - inter_module_unregister("get_tap_change_sd"); - inter_module_unregister("set_dis_tap_sd"); - inter_module_unregister("get_dis_tap_sd"); - inter_module_unregister("set_tap_pwup_sd"); - inter_module_unregister("get_tap_pwup_sd"); - inter_module_unregister("set_bp_disc_sd"); - inter_module_unregister("get_bp_disc_sd"); - inter_module_unregister("get_bp_disc_change_sd"); - inter_module_unregister("set_bp_dis_disc_sd"); - inter_module_unregister("get_bp_dis_disc_sd"); - inter_module_unregister("set_bp_disc_pwup_sd"); - inter_module_unregister("get_bp_disc_pwup_sd"); - inter_module_unregister("set_wd_exp_mode_sd"); - inter_module_unregister("get_wd_exp_mode_sd"); - inter_module_unregister("set_wd_autoreset_sd"); - inter_module_unregister("get_wd_autoreset_sd"); - inter_module_unregister("get_bypass_info_sd"); - inter_module_unregister("bp_if_scan_sd"); - -#endif - - for (i = 0; i < device_num; i++) { - /* unsigned long flags; */ -#ifdef BP_PROC_SUPPORT -/* spin_lock_irqsave(&bpvm_lock, flags); - rcu_read_lock(); */ - bypass_proc_remove_dev_sd(&bpctl_dev_arr[i]); -/* spin_unlock_irqrestore(&bpvm_lock, flags); - rcu_read_unlock(); */ -#endif - remove_bypass_wd_auto(&bpctl_dev_arr[i]); - bpctl_dev_arr[i].reset_time = 0; - - remove_bypass_tpl_auto(&bpctl_dev_arr[i]); - } - - /* unmap all devices */ - for (i = 0; i < device_num; i++) { -#ifdef BP_SELF_TEST - if (bpctl_dev_arr[i].bp_tx_data) - kfree(bpctl_dev_arr[i].bp_tx_data); -#endif - iounmap((void *)(bpctl_dev_arr[i].mem_map)); - } - - /* free all devices space */ - if (bpctl_dev_arr) - kfree(bpctl_dev_arr); - -/* -* Unregister the device -*/ -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23)) - ret = unregister_chrdev(major_num, DEVICE_NAME); -/* -* If there's an error, report it -*/ - if (ret < 0) - printk("Error in module_unregister_chrdev: %d\n", ret); -#else - unregister_chrdev(major_num, DEVICE_NAME); - -#endif -} - -module_init(bypass_init_module); -module_exit(bypass_cleanup_module); - -int is_bypass_sd(int ifindex) -{ - return is_bypass(get_dev_idx_p(ifindex)); -} - -int set_bypass_sd(int ifindex, int bypass_mode) -{ - - return set_bypass_fn(get_dev_idx_p(ifindex), bypass_mode); -} - -int get_bypass_sd(int ifindex) -{ - - return get_bypass_fn(get_dev_idx_p(ifindex)); -} - -int get_bypass_change_sd(int ifindex) -{ - - return get_bypass_change_fn(get_dev_idx_p(ifindex)); -} - -int set_dis_bypass_sd(int ifindex, int dis_param) -{ - return set_dis_bypass_fn(get_dev_idx_p(ifindex), dis_param); -} - -int get_dis_bypass_sd(int ifindex) -{ - - return get_dis_bypass_fn(get_dev_idx_p(ifindex)); -} - -int set_bypass_pwoff_sd(int ifindex, int bypass_mode) -{ - return set_bypass_pwoff_fn(get_dev_idx_p(ifindex), bypass_mode); - -} - -int get_bypass_pwoff_sd(int ifindex) -{ - return get_bypass_pwoff_fn(get_dev_idx_p(ifindex)); - -} - -int set_bypass_pwup_sd(int ifindex, int bypass_mode) -{ - return set_bypass_pwup_fn(get_dev_idx_p(ifindex), bypass_mode); - -} - -int get_bypass_pwup_sd(int ifindex) -{ - return get_bypass_pwup_fn(get_dev_idx_p(ifindex)); - -} - -int set_bypass_wd_sd(int if_index, int ms_timeout, int *ms_timeout_set) -{ - if ((is_bypass(get_dev_idx_p(if_index))) <= 0) - return BP_NOT_CAP; - *ms_timeout_set = set_bypass_wd_fn(get_dev_idx_p(if_index), ms_timeout); - return 0; -} - -int get_bypass_wd_sd(int ifindex, int *timeout) -{ - return get_bypass_wd_fn(get_dev_idx_p(ifindex), timeout); - -} - -int get_wd_expire_time_sd(int ifindex, int *time_left) -{ - return get_wd_expire_time_fn(get_dev_idx_p(ifindex), time_left); -} - -int reset_bypass_wd_timer_sd(int ifindex) -{ - return reset_bypass_wd_timer_fn(get_dev_idx_p(ifindex)); - -} - -int get_wd_set_caps_sd(int ifindex) -{ - return get_wd_set_caps_fn(get_dev_idx_p(ifindex)); - -} - -int set_std_nic_sd(int ifindex, int nic_mode) -{ - return set_std_nic_fn(get_dev_idx_p(ifindex), nic_mode); - -} - -int get_std_nic_sd(int ifindex) -{ - return get_std_nic_fn(get_dev_idx_p(ifindex)); - -} - -int set_tap_sd(int ifindex, int tap_mode) -{ - return set_tap_fn(get_dev_idx_p(ifindex), tap_mode); - -} - -int get_tap_sd(int ifindex) -{ - return get_tap_fn(get_dev_idx_p(ifindex)); - -} - -int set_tap_pwup_sd(int ifindex, int tap_mode) -{ - return set_tap_pwup_fn(get_dev_idx_p(ifindex), tap_mode); - -} - -int get_tap_pwup_sd(int ifindex) -{ - return get_tap_pwup_fn(get_dev_idx_p(ifindex)); - -} - -int get_tap_change_sd(int ifindex) -{ - return get_tap_change_fn(get_dev_idx_p(ifindex)); - -} - -int set_dis_tap_sd(int ifindex, int dis_param) -{ - return set_dis_tap_fn(get_dev_idx_p(ifindex), dis_param); - -} - -int get_dis_tap_sd(int ifindex) -{ - return get_dis_tap_fn(get_dev_idx_p(ifindex)); - -} - -int set_bp_disc_sd(int ifindex, int disc_mode) -{ - return set_disc_fn(get_dev_idx_p(ifindex), disc_mode); - -} - -int get_bp_disc_sd(int ifindex) -{ - return get_disc_fn(get_dev_idx_p(ifindex)); - -} - -int set_bp_disc_pwup_sd(int ifindex, int disc_mode) -{ - return set_disc_pwup_fn(get_dev_idx_p(ifindex), disc_mode); - -} - -int get_bp_disc_pwup_sd(int ifindex) -{ - return get_disc_pwup_fn(get_dev_idx_p(ifindex)); - -} - -int get_bp_disc_change_sd(int ifindex) -{ - return get_disc_change_fn(get_dev_idx_p(ifindex)); - -} - -int set_bp_dis_disc_sd(int ifindex, int dis_param) -{ - return set_dis_disc_fn(get_dev_idx_p(ifindex), dis_param); - -} - -int get_bp_dis_disc_sd(int ifindex) -{ - return get_dis_disc_fn(get_dev_idx_p(ifindex)); - -} - -int get_wd_exp_mode_sd(int ifindex) -{ - return get_wd_exp_mode_fn(get_dev_idx_p(ifindex)); -} - -int set_wd_exp_mode_sd(int ifindex, int param) -{ - return set_wd_exp_mode_fn(get_dev_idx_p(ifindex), param); - -} - -int reset_cont_sd(int ifindex) -{ - return reset_cont_fn(get_dev_idx_p(ifindex)); - -} - -int set_tx_sd(int ifindex, int tx_state) -{ - return set_tx_fn(get_dev_idx_p(ifindex), tx_state); - -} - -int set_tpl_sd(int ifindex, int tpl_state) -{ - return set_tpl_fn(get_dev_idx_p(ifindex), tpl_state); - -} - -int set_bp_hw_reset_sd(int ifindex, int status) -{ - return set_bp_hw_reset_fn(get_dev_idx_p(ifindex), status); - -} - -int set_wd_autoreset_sd(int ifindex, int param) -{ - return set_wd_autoreset_fn(get_dev_idx_p(ifindex), param); - -} - -int get_wd_autoreset_sd(int ifindex) -{ - return get_wd_autoreset_fn(get_dev_idx_p(ifindex)); - -} - -int get_bypass_caps_sd(int ifindex) -{ - return get_bypass_caps_fn(get_dev_idx_p(ifindex)); -} - -int get_bypass_slave_sd(int ifindex) -{ - bpctl_dev_t *pbpctl_dev_out; - int ret = get_bypass_slave_fn(get_dev_idx_p(ifindex), &pbpctl_dev_out); - if (ret == 1) - return pbpctl_dev_out->ifindex; - return -1; - -} - -int get_tx_sd(int ifindex) -{ - return get_tx_fn(get_dev_idx_p(ifindex)); - -} - -int get_tpl_sd(int ifindex) -{ - return get_tpl_fn(get_dev_idx_p(ifindex)); - -} - -int get_bp_hw_reset_sd(int ifindex) -{ - return get_bp_hw_reset_fn(get_dev_idx_p(ifindex)); - -} - -int get_bypass_info_sd(int ifindex, struct bp_info *bp_info) -{ - return get_bypass_info_fn(get_dev_idx_p(ifindex), bp_info->prod_name, &bp_info->fw_ver); -} - -int bp_if_scan_sd(void) -{ - if_scan_init(); - return 0; -} - -EXPORT_SYMBOL_NOVERS(is_bypass_sd); -EXPORT_SYMBOL_NOVERS(get_bypass_slave_sd); -EXPORT_SYMBOL_NOVERS(get_bypass_caps_sd); -EXPORT_SYMBOL_NOVERS(get_wd_set_caps_sd); -EXPORT_SYMBOL_NOVERS(set_bypass_sd); -EXPORT_SYMBOL_NOVERS(get_bypass_sd); -EXPORT_SYMBOL_NOVERS(get_bypass_change_sd); -EXPORT_SYMBOL_NOVERS(set_dis_bypass_sd); -EXPORT_SYMBOL_NOVERS(get_dis_bypass_sd); -EXPORT_SYMBOL_NOVERS(set_bypass_pwoff_sd); -EXPORT_SYMBOL_NOVERS(get_bypass_pwoff_sd); -EXPORT_SYMBOL_NOVERS(set_bypass_pwup_sd); -EXPORT_SYMBOL_NOVERS(get_bypass_pwup_sd); -EXPORT_SYMBOL_NOVERS(set_bypass_wd_sd); -EXPORT_SYMBOL_NOVERS(get_bypass_wd_sd); -EXPORT_SYMBOL_NOVERS(get_wd_expire_time_sd); -EXPORT_SYMBOL_NOVERS(reset_bypass_wd_timer_sd); -EXPORT_SYMBOL_NOVERS(set_std_nic_sd); -EXPORT_SYMBOL_NOVERS(get_std_nic_sd); -EXPORT_SYMBOL_NOVERS(set_tx_sd); -EXPORT_SYMBOL_NOVERS(get_tx_sd); -EXPORT_SYMBOL_NOVERS(set_tpl_sd); -EXPORT_SYMBOL_NOVERS(get_tpl_sd); -EXPORT_SYMBOL_NOVERS(set_bp_hw_reset_sd); -EXPORT_SYMBOL_NOVERS(get_bp_hw_reset_sd); -EXPORT_SYMBOL_NOVERS(set_tap_sd); -EXPORT_SYMBOL_NOVERS(get_tap_sd); -EXPORT_SYMBOL_NOVERS(get_tap_change_sd); -EXPORT_SYMBOL_NOVERS(set_dis_tap_sd); -EXPORT_SYMBOL_NOVERS(get_dis_tap_sd); -EXPORT_SYMBOL_NOVERS(set_tap_pwup_sd); -EXPORT_SYMBOL_NOVERS(get_tap_pwup_sd); -EXPORT_SYMBOL_NOVERS(set_wd_exp_mode_sd); -EXPORT_SYMBOL_NOVERS(get_wd_exp_mode_sd); -EXPORT_SYMBOL_NOVERS(set_wd_autoreset_sd); -EXPORT_SYMBOL_NOVERS(get_wd_autoreset_sd); -EXPORT_SYMBOL_NOVERS(set_bp_disc_sd); -EXPORT_SYMBOL_NOVERS(get_bp_disc_sd); -EXPORT_SYMBOL_NOVERS(get_bp_disc_change_sd); -EXPORT_SYMBOL_NOVERS(set_bp_dis_disc_sd); -EXPORT_SYMBOL_NOVERS(get_bp_dis_disc_sd); -EXPORT_SYMBOL_NOVERS(set_bp_disc_pwup_sd); -EXPORT_SYMBOL_NOVERS(get_bp_disc_pwup_sd); -EXPORT_SYMBOL_NOVERS(get_bypass_info_sd); -EXPORT_SYMBOL_NOVERS(bp_if_scan_sd); - -#define BP_PROC_DIR "bypass" - -#define GPIO6_SET_ENTRY_SD "gpio6_set" -#define GPIO6_CLEAR_ENTRY_SD "gpio6_clear" - -#define GPIO7_SET_ENTRY_SD "gpio7_set" -#define GPIO7_CLEAR_ENTRY_SD "gpio7_clear" - -#define PULSE_SET_ENTRY_SD "pulse_set" -#define ZERO_SET_ENTRY_SD "zero_set" -#define PULSE_GET1_ENTRY_SD "pulse_get1" -#define PULSE_GET2_ENTRY_SD "pulse_get2" - -#define CMND_ON_ENTRY_SD "cmnd_on" -#define CMND_OFF_ENTRY_SD "cmnd_off" -#define RESET_CONT_ENTRY_SD "reset_cont" - - /*COMMANDS*/ -#define BYPASS_INFO_ENTRY_SD "bypass_info" -#define BYPASS_SLAVE_ENTRY_SD "bypass_slave" -#define BYPASS_CAPS_ENTRY_SD "bypass_caps" -#define WD_SET_CAPS_ENTRY_SD "wd_set_caps" -#define BYPASS_ENTRY_SD "bypass" -#define BYPASS_CHANGE_ENTRY_SD "bypass_change" -#define BYPASS_WD_ENTRY_SD "bypass_wd" -#define WD_EXPIRE_TIME_ENTRY_SD "wd_expire_time" -#define RESET_BYPASS_WD_ENTRY_SD "reset_bypass_wd" -#define DIS_BYPASS_ENTRY_SD "dis_bypass" -#define BYPASS_PWUP_ENTRY_SD "bypass_pwup" -#define BYPASS_PWOFF_ENTRY_SD "bypass_pwoff" -#define STD_NIC_ENTRY_SD "std_nic" -#define STD_NIC_ENTRY_SD "std_nic" -#define TAP_ENTRY_SD "tap" -#define TAP_CHANGE_ENTRY_SD "tap_change" -#define DIS_TAP_ENTRY_SD "dis_tap" -#define TAP_PWUP_ENTRY_SD "tap_pwup" -#define TWO_PORT_LINK_ENTRY_SD "two_port_link" -#define WD_EXP_MODE_ENTRY_SD "wd_exp_mode" -#define WD_AUTORESET_ENTRY_SD "wd_autoreset" -#define TPL_ENTRY_SD "tpl" -#define WAIT_AT_PWUP_ENTRY_SD "wait_at_pwup" -#define HW_RESET_ENTRY_SD "hw_reset" -#define DISC_ENTRY_SD "disc" -#define DISC_CHANGE_ENTRY_SD "disc_change" -#define DIS_DISC_ENTRY_SD "dis_disc" -#define DISC_PWUP_ENTRY_SD "disc_pwup" -static struct proc_dir_entry *bp_procfs_dir; - -static struct proc_dir_entry *proc_getdir(char *name, - struct proc_dir_entry *proc_dir) -{ - struct proc_dir_entry *pde = proc_dir; - - for (pde = pde->subdir; pde; pde = pde->next) { - if (pde->namelen && (strcmp(name, pde->name) == 0)) { - /* directory exists */ - break; - } - } - if (pde == (struct proc_dir_entry *)0) { - /* create the directory */ -#if (LINUX_VERSION_CODE > 0x20300) - pde = proc_mkdir(name, proc_dir); -#else - pde = create_proc_entry(name, S_IFDIR, proc_dir); -#endif - if (pde == (struct proc_dir_entry *)0) { - - return pde; - } - } - - return pde; -} - -int bp_proc_create(void) -{ - bp_procfs_dir = proc_getdir(BP_PROC_DIR, init_net.proc_net); - if (bp_procfs_dir == (struct proc_dir_entry *)0) { - printk(KERN_DEBUG - "Could not create procfs nicinfo directory %s\n", - BP_PROC_DIR); - return -1; - } - return 0; -} - -int -bypass_proc_create_entry_sd(struct pfs_unit_sd *pfs_unit_curr, - char *proc_name, - write_proc_t *write_proc, - read_proc_t *read_proc, - struct proc_dir_entry *parent_pfs, void *data) -{ - strcpy(pfs_unit_curr->proc_name, proc_name); - pfs_unit_curr->proc_entry = create_proc_entry(pfs_unit_curr->proc_name, - S_IFREG | S_IRUSR | - S_IWUSR | S_IRGRP | - S_IROTH, parent_pfs); - if (pfs_unit_curr->proc_entry == NULL) - return -1; - - pfs_unit_curr->proc_entry->read_proc = read_proc; - pfs_unit_curr->proc_entry->write_proc = write_proc; - pfs_unit_curr->proc_entry->data = data; - - return 0; - -} - -int -get_bypass_info_pfs(char *page, char **start, off_t off, int count, - int *eof, void *data) -{ - bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data; - int len = 0; - - len += sprintf(page, "Name\t\t\t%s\n", pbp_device_block->name); - len += - sprintf(page + len, "Firmware version\t0x%x\n", - pbp_device_block->bp_fw_ver); - - *eof = 1; - return len; -} - -int -get_bypass_slave_pfs(char *page, char **start, off_t off, int count, - int *eof, void *data) -{ - bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data; - - int len = 0; - bpctl_dev_t *pbp_device_block_slave = NULL; - int idx_dev = 0; - struct net_device *net_slave_dev = NULL; - - if ((pbp_device_block->func == 0) || (pbp_device_block->func == 2)) { - for (idx_dev = 0; - ((bpctl_dev_arr[idx_dev].pdev != NULL) - && (idx_dev < device_num)); idx_dev++) { - if ((bpctl_dev_arr[idx_dev].bus == - pbp_device_block->bus) - && (bpctl_dev_arr[idx_dev].slot == - pbp_device_block->slot)) { - if ((pbp_device_block->func == 0) - && (bpctl_dev_arr[idx_dev].func == 1)) { - pbp_device_block_slave = - &bpctl_dev_arr[idx_dev]; - break; - } - if ((pbp_device_block->func == 2) && - (bpctl_dev_arr[idx_dev].func == 3)) { - pbp_device_block_slave = - &bpctl_dev_arr[idx_dev]; - break; - } - } - } - } else - pbp_device_block_slave = pbp_device_block; - if (!pbp_device_block_slave) { - len = sprintf(page, "fail\n"); - *eof = 1; - return len; - } - net_slave_dev = pbp_device_block_slave->ndev; - if (net_slave_dev) { - if (net_slave_dev) - len = sprintf(page, "%s\n", net_slave_dev->name); - else - len = sprintf(page, "fail\n"); - - } - - *eof = 1; - return len; -} - -int -get_bypass_caps_pfs(char *page, char **start, off_t off, int count, - int *eof, void *data) -{ - bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data; - - int len = 0, ret = 0; - - ret = get_bypass_caps_fn(pbp_device_block); - if (ret == BP_NOT_CAP) - len = sprintf(page, "-1\n"); - else - len = sprintf(page, "0x%x\n", ret); - *eof = 1; - return len; - -} - -int -get_wd_set_caps_pfs(char *page, char **start, off_t off, int count, - int *eof, void *data) -{ - bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data; - - int len = 0, ret = 0; - - ret = get_wd_set_caps_fn(pbp_device_block); - if (ret == BP_NOT_CAP) - len = sprintf(page, "-1\n"); - else - len = sprintf(page, "0x%x\n", ret); - *eof = 1; - return len; -} - -int -set_bypass_pfs(struct file *file, const char *buffer, - unsigned long count, void *data) -{ - - char kbuf[256]; - bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data; - - int bypass_param = 0, length = 0; - - if (count > (sizeof(kbuf) - 1)) - return -1; - - if (copy_from_user(&kbuf, buffer, count)) { - return -1; - } - - kbuf[count] = '\0'; - length = strlen(kbuf); - if (kbuf[length - 1] == '\n') - kbuf[--length] = '\0'; - - if (strcmp(kbuf, "on") == 0) - bypass_param = 1; - else if (strcmp(kbuf, "off") == 0) - bypass_param = 0; - - set_bypass_fn(pbp_device_block, bypass_param); - - return count; -} - -int -set_tap_pfs(struct file *file, const char *buffer, - unsigned long count, void *data) -{ - - char kbuf[256]; - bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data; - - int tap_param = 0, length = 0; - - if (count > (sizeof(kbuf) - 1)) - return -1; - - if (copy_from_user(&kbuf, buffer, count)) { - return -1; - } - - kbuf[count] = '\0'; - length = strlen(kbuf); - if (kbuf[length - 1] == '\n') - kbuf[--length] = '\0'; - - if (strcmp(kbuf, "on") == 0) - tap_param = 1; - else if (strcmp(kbuf, "off") == 0) - tap_param = 0; - - set_tap_fn(pbp_device_block, tap_param); - - return count; -} - -int -set_disc_pfs(struct file *file, const char *buffer, - unsigned long count, void *data) -{ - - char kbuf[256]; - bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data; - - int tap_param = 0, length = 0; - - if (count > (sizeof(kbuf) - 1)) - return -1; - - if (copy_from_user(&kbuf, buffer, count)) { - return -1; - } - - kbuf[count] = '\0'; - length = strlen(kbuf); - if (kbuf[length - 1] == '\n') - kbuf[--length] = '\0'; - - if (strcmp(kbuf, "on") == 0) - tap_param = 1; - else if (strcmp(kbuf, "off") == 0) - tap_param = 0; - - set_disc_fn(pbp_device_block, tap_param); - - return count; -} - -int -get_bypass_pfs(char *page, char **start, off_t off, int count, - int *eof, void *data) -{ - bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data; - - int len = 0, ret = 0; - - ret = get_bypass_fn(pbp_device_block); - if (ret == BP_NOT_CAP) - len = sprintf(page, "fail\n"); - else if (ret == 1) - len = sprintf(page, "on\n"); - else if (ret == 0) - len = sprintf(page, "off\n"); - - *eof = 1; - return len; -} - -int -get_tap_pfs(char *page, char **start, off_t off, int count, - int *eof, void *data) -{ - bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data; - - int len = 0, ret = 0; - - ret = get_tap_fn(pbp_device_block); - if (ret == BP_NOT_CAP) - len = sprintf(page, "fail\n"); - else if (ret == 1) - len = sprintf(page, "on\n"); - else if (ret == 0) - len = sprintf(page, "off\n"); - - *eof = 1; - return len; -} - -int -get_disc_pfs(char *page, char **start, off_t off, int count, - int *eof, void *data) -{ - bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data; - - int len = 0, ret = 0; - - ret = get_disc_fn(pbp_device_block); - if (ret == BP_NOT_CAP) - len = sprintf(page, "fail\n"); - else if (ret == 1) - len = sprintf(page, "on\n"); - else if (ret == 0) - len = sprintf(page, "off\n"); - - *eof = 1; - return len; -} - -int -get_bypass_change_pfs(char *page, char **start, off_t off, int count, - int *eof, void *data) -{ - bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data; - - int len = 0, ret = 0; - - ret = get_bypass_change_fn(pbp_device_block); - if (ret == 1) - len = sprintf(page, "on\n"); - else if (ret == 0) - len = sprintf(page, "off\n"); - else - len = sprintf(page, "fail\n"); - - *eof = 1; - return len; -} - -int -get_tap_change_pfs(char *page, char **start, off_t off, int count, - int *eof, void *data) -{ - bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data; - - int len = 0, ret = 0; - - ret = get_tap_change_fn(pbp_device_block); - if (ret == 1) - len = sprintf(page, "on\n"); - else if (ret == 0) - len = sprintf(page, "off\n"); - else - len = sprintf(page, "fail\n"); - - *eof = 1; - return len; -} - -int -get_disc_change_pfs(char *page, char **start, off_t off, int count, - int *eof, void *data) -{ - bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data; - - int len = 0, ret = 0; - - ret = get_disc_change_fn(pbp_device_block); - if (ret == 1) - len = sprintf(page, "on\n"); - else if (ret == 0) - len = sprintf(page, "off\n"); - else - len = sprintf(page, "fail\n"); - - *eof = 1; - return len; -} - -#define isdigit(c) (c >= '0' && c <= '9') -__inline static int atoi(char **s) -{ - int i = 0; - while (isdigit(**s)) - i = i * 10 + *((*s)++) - '0'; - return i; -} - -int -set_bypass_wd_pfs(struct file *file, const char *buffer, - unsigned long count, void *data) -{ - bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data; - int timeout; - int ret; - - ret = kstrtoint_from_user(buffer, count, 10, &timeout); - if (ret) - return ret; - set_bypass_wd_fn(pbp_device_block, timeout); - - return count; -} - -int -get_bypass_wd_pfs(char *page, char **start, off_t off, int count, - int *eof, void *data) -{ - bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data; - - int len = 0, ret = 0, timeout = 0; - - ret = get_bypass_wd_fn(pbp_device_block, &timeout); - if (ret == BP_NOT_CAP) - len = sprintf(page, "fail\n"); - else if (timeout == -1) - len = sprintf(page, "unknown\n"); - else if (timeout == 0) - len = sprintf(page, "disable\n"); - else - len = sprintf(page, "%d\n", timeout); - - *eof = 1; - return len; -} - -int -get_wd_expire_time_pfs(char *page, char **start, off_t off, int count, - int *eof, void *data) -{ - bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data; - - int len = 0, ret = 0, timeout = 0; - - ret = get_wd_expire_time_fn(pbp_device_block, &timeout); - if (ret == BP_NOT_CAP) - len = sprintf(page, "fail\n"); - else if (timeout == -1) - len = sprintf(page, "expire\n"); - else if (timeout == 0) - len = sprintf(page, "disable\n"); - - else - len = sprintf(page, "%d\n", timeout); - *eof = 1; - return len; -} - -int -get_tpl_pfs(char *page, char **start, off_t off, int count, - int *eof, void *data) -{ - bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data; - - int len = 0, ret = 0; - - ret = get_tpl_fn(pbp_device_block); - if (ret == BP_NOT_CAP) - len = sprintf(page, "fail\n"); - else if (ret == 1) - len = sprintf(page, "on\n"); - else if (ret == 0) - len = sprintf(page, "off\n"); - - *eof = 1; - return len; -} - -#ifdef PMC_FIX_FLAG -int -get_wait_at_pwup_pfs(char *page, char **start, off_t off, int count, - int *eof, void *data) -{ - bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data; - - int len = 0, ret = 0; - - ret = get_bp_wait_at_pwup_fn(pbp_device_block); - if (ret == BP_NOT_CAP) - len = sprintf(page, "fail\n"); - else if (ret == 1) - len = sprintf(page, "on\n"); - else if (ret == 0) - len = sprintf(page, "off\n"); - - *eof = 1; - return len; -} - -int -get_hw_reset_pfs(char *page, char **start, off_t off, int count, - int *eof, void *data) -{ - bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data; - - int len = 0, ret = 0; - - ret = get_bp_hw_reset_fn(pbp_device_block); - if (ret == BP_NOT_CAP) - len = sprintf(page, "fail\n"); - else if (ret == 1) - len = sprintf(page, "on\n"); - else if (ret == 0) - len = sprintf(page, "off\n"); - - *eof = 1; - return len; -} - -#endif /*PMC_WAIT_FLAG */ - -int -reset_bypass_wd_pfs(char *page, char **start, off_t off, int count, - int *eof, void *data) -{ - bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data; - - int len = 0, ret = 0; - - ret = reset_bypass_wd_timer_fn(pbp_device_block); - if (ret == BP_NOT_CAP) - len = sprintf(page, "fail\n"); - else if (ret == 0) - len = sprintf(page, "disable\n"); - else if (ret == 1) - len = sprintf(page, "success\n"); - - *eof = 1; - return len; -} - -int -set_dis_bypass_pfs(struct file *file, const char *buffer, - unsigned long count, void *data) -{ - - char kbuf[256]; - bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data; - - int bypass_param = 0, length = 0; - - if (count >= sizeof(kbuf)) - return -EINVAL; - - if (copy_from_user(&kbuf, buffer, count)) { - return -1; - } - - kbuf[count] = '\0'; - length = strlen(kbuf); - if (kbuf[length - 1] == '\n') - kbuf[--length] = '\0'; - - if (strcmp(kbuf, "on") == 0) - bypass_param = 1; - else if (strcmp(kbuf, "off") == 0) - bypass_param = 0; - - set_dis_bypass_fn(pbp_device_block, bypass_param); - - return count; -} - -int -set_dis_tap_pfs(struct file *file, const char *buffer, - unsigned long count, void *data) -{ - - char kbuf[256]; - bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data; - - int tap_param = 0, length = 0; - - if (count >= sizeof(kbuf)) - return -EINVAL; - - if (copy_from_user(&kbuf, buffer, count)) { - return -1; - } - - kbuf[count] = '\0'; - length = strlen(kbuf); - if (kbuf[length - 1] == '\n') - kbuf[--length] = '\0'; - - if (strcmp(kbuf, "on") == 0) - tap_param = 1; - else if (strcmp(kbuf, "off") == 0) - tap_param = 0; - - set_dis_tap_fn(pbp_device_block, tap_param); - - return count; -} - -int -set_dis_disc_pfs(struct file *file, const char *buffer, - unsigned long count, void *data) -{ - - char kbuf[256]; - bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data; - - int tap_param = 0, length = 0; - - if (count >= sizeof(kbuf)) - return -EINVAL; - - if (copy_from_user(&kbuf, buffer, count)) { - return -1; - } - - kbuf[count] = '\0'; - length = strlen(kbuf); - if (kbuf[length - 1] == '\n') - kbuf[--length] = '\0'; - - if (strcmp(kbuf, "on") == 0) - tap_param = 1; - else if (strcmp(kbuf, "off") == 0) - tap_param = 0; - - set_dis_disc_fn(pbp_device_block, tap_param); - - return count; -} - -int -get_dis_bypass_pfs(char *page, char **start, off_t off, int count, - int *eof, void *data) -{ - bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data; - - int len = 0, ret = 0; - - ret = get_dis_bypass_fn(pbp_device_block); - if (ret == BP_NOT_CAP) - len = sprintf(page, "fail\n"); - else if (ret == 0) - len = sprintf(page, "off\n"); - else - len = sprintf(page, "on\n"); - - *eof = 1; - return len; -} - -int -get_dis_tap_pfs(char *page, char **start, off_t off, int count, - int *eof, void *data) -{ - bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data; - - int len = 0, ret = 0; - - ret = get_dis_tap_fn(pbp_device_block); - if (ret == BP_NOT_CAP) - len = sprintf(page, "fail\n"); - else if (ret == 0) - len = sprintf(page, "off\n"); - else - len = sprintf(page, "on\n"); - - *eof = 1; - return len; -} - -int -get_dis_disc_pfs(char *page, char **start, off_t off, int count, - int *eof, void *data) -{ - bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data; - - int len = 0, ret = 0; - - ret = get_dis_disc_fn(pbp_device_block); - if (ret == BP_NOT_CAP) - len = sprintf(page, "fail\n"); - else if (ret == 0) - len = sprintf(page, "off\n"); - else - len = sprintf(page, "on\n"); - - *eof = 1; - return len; -} - -int -set_bypass_pwup_pfs(struct file *file, const char *buffer, - unsigned long count, void *data) -{ - - char kbuf[256]; - bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data; - - int bypass_param = 0, length = 0; - - if (count >= sizeof(kbuf)) - return -EINVAL; - - if (copy_from_user(&kbuf, buffer, count)) { - return -1; - } - - kbuf[count] = '\0'; - length = strlen(kbuf); - if (kbuf[length - 1] == '\n') - kbuf[--length] = '\0'; - - if (strcmp(kbuf, "on") == 0) - bypass_param = 1; - else if (strcmp(kbuf, "off") == 0) - bypass_param = 0; - - set_bypass_pwup_fn(pbp_device_block, bypass_param); - - return count; -} - -int -set_bypass_pwoff_pfs(struct file *file, const char *buffer, - unsigned long count, void *data) -{ - - char kbuf[256]; - bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data; - - int bypass_param = 0, length = 0; - - if (count >= sizeof(kbuf)) - return -EINVAL; - - if (copy_from_user(&kbuf, buffer, count)) { - return -1; - } - - kbuf[count] = '\0'; - length = strlen(kbuf); - if (kbuf[length - 1] == '\n') - kbuf[--length] = '\0'; - - if (strcmp(kbuf, "on") == 0) - bypass_param = 1; - else if (strcmp(kbuf, "off") == 0) - bypass_param = 0; - - set_bypass_pwoff_fn(pbp_device_block, bypass_param); - - return count; -} - -int -set_tap_pwup_pfs(struct file *file, const char *buffer, - unsigned long count, void *data) -{ - - char kbuf[256]; - bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data; - - int tap_param = 0, length = 0; - - if (count >= sizeof(kbuf)) - return -EINVAL; - - if (copy_from_user(&kbuf, buffer, count)) { - return -1; - } - - kbuf[count] = '\0'; - length = strlen(kbuf); - if (kbuf[length - 1] == '\n') - kbuf[--length] = '\0'; - - if (strcmp(kbuf, "on") == 0) - tap_param = 1; - else if (strcmp(kbuf, "off") == 0) - tap_param = 0; - - set_tap_pwup_fn(pbp_device_block, tap_param); - - return count; -} - -int -set_disc_pwup_pfs(struct file *file, const char *buffer, - unsigned long count, void *data) -{ - - char kbuf[256]; - bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data; - - int tap_param = 0, length = 0; - - if (count >= sizeof(kbuf)) - return -EINVAL; - - if (copy_from_user(&kbuf, buffer, count)) { - return -1; - } - - kbuf[count] = '\0'; - length = strlen(kbuf); - if (kbuf[length - 1] == '\n') - kbuf[--length] = '\0'; - - if (strcmp(kbuf, "on") == 0) - tap_param = 1; - else if (strcmp(kbuf, "off") == 0) - tap_param = 0; - - set_disc_pwup_fn(pbp_device_block, tap_param); - - return count; -} - -int -get_bypass_pwup_pfs(char *page, char **start, off_t off, int count, - int *eof, void *data) -{ - bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data; - - int len = 0, ret = 0; - - ret = get_bypass_pwup_fn(pbp_device_block); - if (ret == BP_NOT_CAP) - len = sprintf(page, "fail\n"); - else if (ret == 0) - len = sprintf(page, "off\n"); - else - len = sprintf(page, "on\n"); - - *eof = 1; - return len; -} - -int -get_bypass_pwoff_pfs(char *page, char **start, off_t off, int count, - int *eof, void *data) -{ - bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data; - - int len = 0, ret = 0; - - ret = get_bypass_pwoff_fn(pbp_device_block); - if (ret == BP_NOT_CAP) - len = sprintf(page, "fail\n"); - else if (ret == 0) - len = sprintf(page, "off\n"); - else - len = sprintf(page, "on\n"); - - *eof = 1; - return len; -} - -int -get_tap_pwup_pfs(char *page, char **start, off_t off, int count, - int *eof, void *data) -{ - bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data; - - int len = 0, ret = 0; - - ret = get_tap_pwup_fn(pbp_device_block); - if (ret == BP_NOT_CAP) - len = sprintf(page, "fail\n"); - else if (ret == 0) - len = sprintf(page, "off\n"); - else - len = sprintf(page, "on\n"); - - *eof = 1; - return len; -} - -int -get_disc_pwup_pfs(char *page, char **start, off_t off, int count, - int *eof, void *data) -{ - bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data; - - int len = 0, ret = 0; - - ret = get_disc_pwup_fn(pbp_device_block); - if (ret == BP_NOT_CAP) - len = sprintf(page, "fail\n"); - else if (ret == 0) - len = sprintf(page, "off\n"); - else - len = sprintf(page, "on\n"); - - *eof = 1; - return len; -} - -int -set_std_nic_pfs(struct file *file, const char *buffer, - unsigned long count, void *data) -{ - - char kbuf[256]; - bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data; - - int bypass_param = 0, length = 0; - - if (count >= sizeof(kbuf)) - return -EINVAL; - - if (copy_from_user(&kbuf, buffer, count)) { - return -1; - } - - kbuf[count] = '\0'; - length = strlen(kbuf); - if (kbuf[length - 1] == '\n') - kbuf[--length] = '\0'; - - if (strcmp(kbuf, "on") == 0) - bypass_param = 1; - else if (strcmp(kbuf, "off") == 0) - bypass_param = 0; - - set_std_nic_fn(pbp_device_block, bypass_param); - - return count; -} - -int -get_std_nic_pfs(char *page, char **start, off_t off, int count, - int *eof, void *data) -{ - bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data; - - int len = 0, ret = 0; - - ret = get_std_nic_fn(pbp_device_block); - if (ret == BP_NOT_CAP) - len = sprintf(page, "fail\n"); - else if (ret == 0) - len = sprintf(page, "off\n"); - else - len = sprintf(page, "on\n"); - - *eof = 1; - return len; -} - -int -get_wd_exp_mode_pfs(char *page, char **start, off_t off, int count, - int *eof, void *data) -{ - bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data; - - int len = 0, ret = 0; - - ret = get_wd_exp_mode_fn(pbp_device_block); - if (ret == 1) - len = sprintf(page, "tap\n"); - else if (ret == 0) - len = sprintf(page, "bypass\n"); - else if (ret == 2) - len = sprintf(page, "disc\n"); - - else - len = sprintf(page, "fail\n"); - - *eof = 1; - return len; -} - -int -set_wd_exp_mode_pfs(struct file *file, const char *buffer, - unsigned long count, void *data) -{ - - char kbuf[256]; - bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data; - - int bypass_param = 0, length = 0; - - if (count > (sizeof(kbuf) - 1)) - return -1; - - if (copy_from_user(&kbuf, buffer, count)) { - return -1; - } - - kbuf[count] = '\0'; - length = strlen(kbuf); - if (kbuf[length - 1] == '\n') - kbuf[--length] = '\0'; - - if (strcmp(kbuf, "tap") == 0) - bypass_param = 1; - else if (strcmp(kbuf, "bypass") == 0) - bypass_param = 0; - else if (strcmp(kbuf, "disc") == 0) - bypass_param = 2; - - set_wd_exp_mode_fn(pbp_device_block, bypass_param); - - return count; -} - -int -get_wd_autoreset_pfs(char *page, char **start, off_t off, int count, - int *eof, void *data) -{ - bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data; - - int len = 0, ret = 0; - - ret = get_wd_autoreset_fn(pbp_device_block); - if (ret >= 0) - len = sprintf(page, "%d\n", ret); - else - len = sprintf(page, "fail\n"); - - *eof = 1; - return len; -} - -int -set_wd_autoreset_pfs(struct file *file, const char *buffer, - unsigned long count, void *data) -{ - bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data; - int timeout; - int ret; - - ret = kstrtoint_from_user(buffer, count, 10, &timeout); - if (ret) - return ret; - set_wd_autoreset_fn(pbp_device_block, timeout); - - return count; -} - -int -set_tpl_pfs(struct file *file, const char *buffer, - unsigned long count, void *data) -{ - - char kbuf[256]; - bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data; - - int tpl_param = 0, length = 0; - - if (count > (sizeof(kbuf) - 1)) - return -1; - - if (copy_from_user(&kbuf, buffer, count)) { - return -1; - } - - kbuf[count] = '\0'; - length = strlen(kbuf); - if (kbuf[length - 1] == '\n') - kbuf[--length] = '\0'; - - if (strcmp(kbuf, "on") == 0) - tpl_param = 1; - else if (strcmp(kbuf, "off") == 0) - tpl_param = 0; - - set_tpl_fn(pbp_device_block, tpl_param); - - return count; -} - -#ifdef PMC_FIX_FLAG -int -set_wait_at_pwup_pfs(struct file *file, const char *buffer, - unsigned long count, void *data) -{ - - char kbuf[256]; - bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data; - - int tpl_param = 0, length = 0; - - if (count > (sizeof(kbuf) - 1)) - return -1; - - if (copy_from_user(&kbuf, buffer, count)) { - return -1; - } - - kbuf[count] = '\0'; - length = strlen(kbuf); - if (kbuf[length - 1] == '\n') - kbuf[--length] = '\0'; - - if (strcmp(kbuf, "on") == 0) - tpl_param = 1; - else if (strcmp(kbuf, "off") == 0) - tpl_param = 0; - - set_bp_wait_at_pwup_fn(pbp_device_block, tpl_param); - - return count; -} - -int -set_hw_reset_pfs(struct file *file, const char *buffer, - unsigned long count, void *data) -{ - - char kbuf[256]; - bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data; - - int tpl_param = 0, length = 0; - - if (count > (sizeof(kbuf) - 1)) - return -1; - - if (copy_from_user(&kbuf, buffer, count)) { - return -1; - } - - kbuf[count] = '\0'; - length = strlen(kbuf); - if (kbuf[length - 1] == '\n') - kbuf[--length] = '\0'; - - if (strcmp(kbuf, "on") == 0) - tpl_param = 1; - else if (strcmp(kbuf, "off") == 0) - tpl_param = 0; - - set_bp_hw_reset_fn(pbp_device_block, tpl_param); - - return count; -} - -#endif /*PMC_FIX_FLAG */ - -int bypass_proc_create_dev_sd(bpctl_dev_t *pbp_device_block) -{ - struct bypass_pfs_sd *current_pfs = &(pbp_device_block->bypass_pfs_set); - static struct proc_dir_entry *procfs_dir = NULL; - int ret = 0; - - if (!pbp_device_block->ndev) - return -1; - sprintf(current_pfs->dir_name, "bypass_%s", - pbp_device_block->ndev->name); - - if (!bp_procfs_dir) - return -1; - - /* create device proc dir */ - procfs_dir = proc_getdir(current_pfs->dir_name, bp_procfs_dir); - if (procfs_dir == 0) { - printk(KERN_DEBUG "Could not create procfs directory %s\n", - current_pfs->dir_name); - return -1; - } - current_pfs->bypass_entry = procfs_dir; - - if (bypass_proc_create_entry_sd(&(current_pfs->bypass_info), BYPASS_INFO_ENTRY_SD, NULL, /* write */ - get_bypass_info_pfs, /* read */ - procfs_dir, pbp_device_block)) - ret = -1; - - if (pbp_device_block->bp_caps & SW_CTL_CAP) { - - /* Create set param proc's */ - if (bypass_proc_create_entry_sd(&(current_pfs->bypass_slave), BYPASS_SLAVE_ENTRY_SD, NULL, /* write */ - get_bypass_slave_pfs, /* read */ - procfs_dir, pbp_device_block)) - ret = -1; - - if (bypass_proc_create_entry_sd(&(current_pfs->bypass_caps), BYPASS_CAPS_ENTRY_SD, NULL, /* write */ - get_bypass_caps_pfs, /* read */ - procfs_dir, pbp_device_block)) - ret = -1; - - if (bypass_proc_create_entry_sd(&(current_pfs->wd_set_caps), WD_SET_CAPS_ENTRY_SD, NULL, /* write */ - get_wd_set_caps_pfs, /* read */ - procfs_dir, pbp_device_block)) - ret = -1; - if (bypass_proc_create_entry_sd(&(current_pfs->bypass_wd), BYPASS_WD_ENTRY_SD, set_bypass_wd_pfs, /* write */ - get_bypass_wd_pfs, /* read */ - procfs_dir, pbp_device_block)) - ret = -1; - - if (bypass_proc_create_entry_sd(&(current_pfs->wd_expire_time), WD_EXPIRE_TIME_ENTRY_SD, NULL, /* write */ - get_wd_expire_time_pfs, /* read */ - procfs_dir, pbp_device_block)) - ret = -1; - - if (bypass_proc_create_entry_sd(&(current_pfs->reset_bypass_wd), RESET_BYPASS_WD_ENTRY_SD, NULL, /* write */ - reset_bypass_wd_pfs, /* read */ - procfs_dir, pbp_device_block)) - ret = -1; - - if (bypass_proc_create_entry_sd(&(current_pfs->std_nic), STD_NIC_ENTRY_SD, set_std_nic_pfs, /* write */ - get_std_nic_pfs, /* read */ - procfs_dir, pbp_device_block)) - ret = -1; - - if (pbp_device_block->bp_caps & BP_CAP) { - if (bypass_proc_create_entry_sd(&(current_pfs->bypass), BYPASS_ENTRY_SD, set_bypass_pfs, /* write */ - get_bypass_pfs, /* read */ - procfs_dir, - pbp_device_block)) - ret = -1; - - if (bypass_proc_create_entry_sd(&(current_pfs->dis_bypass), DIS_BYPASS_ENTRY_SD, set_dis_bypass_pfs, /* write */ - get_dis_bypass_pfs, /* read */ - procfs_dir, - pbp_device_block)) - ret = -1; - - if (bypass_proc_create_entry_sd(&(current_pfs->bypass_pwup), BYPASS_PWUP_ENTRY_SD, set_bypass_pwup_pfs, /* write */ - get_bypass_pwup_pfs, /* read */ - procfs_dir, - pbp_device_block)) - ret = -1; - if (bypass_proc_create_entry_sd(&(current_pfs->bypass_pwoff), BYPASS_PWOFF_ENTRY_SD, set_bypass_pwoff_pfs, /* write */ - get_bypass_pwoff_pfs, /* read */ - procfs_dir, - pbp_device_block)) - ret = -1; - - if (bypass_proc_create_entry_sd(&(current_pfs->bypass_change), BYPASS_CHANGE_ENTRY_SD, NULL, /* write */ - get_bypass_change_pfs, /* read */ - procfs_dir, - pbp_device_block)) - ret = -1; - } - - if (pbp_device_block->bp_caps & TAP_CAP) { - - if (bypass_proc_create_entry_sd(&(current_pfs->tap), TAP_ENTRY_SD, set_tap_pfs, /* write */ - get_tap_pfs, /* read */ - procfs_dir, - pbp_device_block)) - ret = -1; - - if (bypass_proc_create_entry_sd(&(current_pfs->dis_tap), DIS_TAP_ENTRY_SD, set_dis_tap_pfs, /* write */ - get_dis_tap_pfs, /* read */ - procfs_dir, - pbp_device_block)) - ret = -1; - - if (bypass_proc_create_entry_sd(&(current_pfs->tap_pwup), TAP_PWUP_ENTRY_SD, set_tap_pwup_pfs, /* write */ - get_tap_pwup_pfs, /* read */ - procfs_dir, - pbp_device_block)) - ret = -1; - - if (bypass_proc_create_entry_sd(&(current_pfs->tap_change), TAP_CHANGE_ENTRY_SD, NULL, /* write */ - get_tap_change_pfs, /* read */ - procfs_dir, - pbp_device_block)) - ret = -1; - } - if (pbp_device_block->bp_caps & DISC_CAP) { - - if (bypass_proc_create_entry_sd(&(current_pfs->tap), DISC_ENTRY_SD, set_disc_pfs, /* write */ - get_disc_pfs, /* read */ - procfs_dir, - pbp_device_block)) - ret = -1; -#if 1 - - if (bypass_proc_create_entry_sd(&(current_pfs->dis_tap), DIS_DISC_ENTRY_SD, set_dis_disc_pfs, /* write */ - get_dis_disc_pfs, /* read */ - procfs_dir, - pbp_device_block)) - ret = -1; -#endif - - if (bypass_proc_create_entry_sd(&(current_pfs->tap_pwup), DISC_PWUP_ENTRY_SD, set_disc_pwup_pfs, /* write */ - get_disc_pwup_pfs, /* read */ - procfs_dir, - pbp_device_block)) - ret = -1; - - if (bypass_proc_create_entry_sd(&(current_pfs->tap_change), DISC_CHANGE_ENTRY_SD, NULL, /* write */ - get_disc_change_pfs, /* read */ - procfs_dir, - pbp_device_block)) - ret = -1; - } - - if (bypass_proc_create_entry_sd(&(current_pfs->wd_exp_mode), WD_EXP_MODE_ENTRY_SD, set_wd_exp_mode_pfs, /* write */ - get_wd_exp_mode_pfs, /* read */ - procfs_dir, pbp_device_block)) - ret = -1; - - if (bypass_proc_create_entry_sd(&(current_pfs->wd_autoreset), WD_AUTORESET_ENTRY_SD, set_wd_autoreset_pfs, /* write */ - get_wd_autoreset_pfs, /* read */ - procfs_dir, pbp_device_block)) - ret = -1; - if (bypass_proc_create_entry_sd(&(current_pfs->tpl), TPL_ENTRY_SD, set_tpl_pfs, /* write */ - get_tpl_pfs, /* read */ - procfs_dir, pbp_device_block)) - ret = -1; -#ifdef PMC_FIX_FLAG - if (bypass_proc_create_entry_sd(&(current_pfs->tpl), WAIT_AT_PWUP_ENTRY_SD, set_wait_at_pwup_pfs, /* write */ - get_wait_at_pwup_pfs, /* read */ - procfs_dir, pbp_device_block)) - ret = -1; - if (bypass_proc_create_entry_sd(&(current_pfs->tpl), HW_RESET_ENTRY_SD, set_hw_reset_pfs, /* write */ - get_hw_reset_pfs, /* read */ - procfs_dir, pbp_device_block)) - ret = -1; - -#endif - - } - if (ret < 0) - printk(KERN_DEBUG "Create proc entry failed\n"); - - return ret; -} - -int bypass_proc_remove_dev_sd(bpctl_dev_t *pbp_device_block) -{ - - struct bypass_pfs_sd *current_pfs = &pbp_device_block->bypass_pfs_set; - struct proc_dir_entry *pde = current_pfs->bypass_entry, *pde_curr = - NULL; - char name[256]; - - if (!pde) - return 0; - for (pde = pde->subdir; pde;) { - strcpy(name, pde->name); - pde_curr = pde; - pde = pde->next; - remove_proc_entry(name, current_pfs->bypass_entry); - } - if (!pde) - remove_proc_entry(current_pfs->dir_name, bp_procfs_dir); - current_pfs->bypass_entry = NULL; - - return 0; -} diff --git a/trunk/drivers/staging/silicom/bp_mod.h b/trunk/drivers/staging/silicom/bp_mod.h deleted file mode 100644 index b8275f5611fa..000000000000 --- a/trunk/drivers/staging/silicom/bp_mod.h +++ /dev/null @@ -1,704 +0,0 @@ -/******************************************************************************/ -/* */ -/* Bypass Control utility, Copyright (c) 2005 Silicom */ -/* */ -/* 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, located in the file LICENSE. */ -/* */ -/* */ -/* bp_mod.h */ -/* */ -/******************************************************************************/ - -#ifndef BP_MOD_H -#define BP_MOD_H -#include "bits.h" - -#define EXPORT_SYMBOL_NOVERS EXPORT_SYMBOL - -#define usec_delay(x) udelay(x) -#ifndef msec_delay_bp -#define msec_delay_bp(x) \ -do { \ - int i; \ - if (1) { \ - for (i = 0; i < 1000; i++) { \ - udelay(x) ; \ - } \ - } else { \ - msleep(x); \ - } \ -} while (0) - -#endif - -#include - -#ifndef jiffies_to_msecs -#define jiffies_to_msecs(x) _kc_jiffies_to_msecs(x) -static inline unsigned int jiffies_to_msecs(const unsigned long j) -{ -#if HZ <= 1000 && !(1000 % HZ) - return (1000 / HZ) * j; -#elif HZ > 1000 && !(HZ % 1000) - return (j + (HZ / 1000) - 1) / (HZ / 1000); -#else - return (j * 1000) / HZ; -#endif -} -#endif - -#define SILICOM_VID 0x1374 -#define SILICOM_SVID 0x1374 - -#define SILICOM_PXG2BPFI_SSID 0x0026 -#define SILICOM_PXG2BPFILX_SSID 0x0027 -#define SILICOM_PXGBPI_SSID 0x0028 -#define SILICOM_PXGBPIG_SSID 0x0029 -#define SILICOM_PXG2TBFI_SSID 0x002a -#define SILICOM_PXG4BPI_SSID 0x002c -#define SILICOM_PXG4BPFI_SSID 0x002d -#define SILICOM_PXG4BPFILX_SSID 0x002e -#define SILICOM_PXG2BPFIL_SSID 0x002F -#define SILICOM_PXG2BPFILLX_SSID 0x0030 -#define SILICOM_PEG4BPI_SSID 0x0031 -#define SILICOM_PEG2BPI_SSID 0x0037 -#define SILICOM_PEG4BPIN_SSID 0x0038 -#define SILICOM_PEG2BPFI_SSID 0x0039 -#define SILICOM_PEG2BPFILX_SSID 0x003A -#define SILICOM_PMCXG2BPFI_SSID 0x003B -#define NOKIA_PMCXG2BPFIN_SSID 0x0510 -#define NOKIA_PMCXG2BPIN_SSID 0x0513 -#define NOKIA_PMCXG4BPIN_SSID 0x0514 -#define NOKIA_PMCXG2BPFIN_SVID 0x13B8 -#define NOKIA_PMCXG2BPIN2_SSID 0x0515 -#define NOKIA_PMCXG4BPIN2_SSID 0x0516 -#define SILICOM_PMCX2BPI_SSID 0x041 -#define SILICOM_PMCX4BPI_SSID 0x042 -#define SILICOM_PXG2BISC1_SSID 0x003d -#define SILICOM_PEG2TBFI_SSID 0x003E -#define SILICOM_PXG2TBI_SSID 0x003f -#define SILICOM_PXG4BPFID_SSID 0x0043 -#define SILICOM_PEG4BPFI_SSID 0x0040 -#define SILICOM_PEG4BPIPT_SSID 0x0044 -#define SILICOM_PXG6BPI_SSID 0x0045 -#define SILICOM_PEG4BPIL_SSID 0x0046 -#define SILICOM_PEG2BPI5_SSID 0x0052 -#define SILICOM_PEG6BPI_SSID 0x0053 -#define SILICOM_PEG4BPFI5_SSID 0x0050 -#define SILICOM_PEG4BPFI5LX_SSID 0x0051 -#define SILICOM_PEG2BISC6_SSID 0x54 - -#define SILICOM_PEG6BPIFC_SSID 0x55 - -#define SILICOM_PEG2BPFI5_SSID 0x0056 -#define SILICOM_PEG2BPFI5LX_SSID 0x0057 - -#define SILICOM_PXEG4BPFI_SSID 0x0058 - -#define SILICOM_PEG2BPFID_SSID 0x0047 -#define SILICOM_PEG2BPFIDLX_SSID 0x004C -#define SILICOM_MEG2BPFILN_SSID 0x0048 -#define SILICOM_MEG2BPFINX_SSID 0x0049 -#define SILICOM_PEG4BPFILX_SSID 0x004A -#define SILICOM_MHIO8AD_SSID 0x004F - -#define SILICOM_MEG2BPFILXLN_SSID 0x004b -#define SILICOM_PEG2BPIX1_SSID 0x004d -#define SILICOM_MEG2BPFILXNX_SSID 0x004e - -#define SILICOM_PE10G2BPISR_SSID 0x0102 -#define SILICOM_PE10G2BPILR_SSID 0x0103 -#define SILICOM_PE10G2BPICX4_SSID 0x0101 - -#define SILICOM_XE10G2BPILR_SSID 0x0163 -#define SILICOM_XE10G2BPISR_SSID 0x0162 -#define SILICOM_XE10G2BPICX4_SSID 0x0161 -#define SILICOM_XE10G2BPIT_SSID 0x0160 - -#define SILICOM_PE10GDBISR_SSID 0x0181 -#define SILICOM_PE10GDBILR_SSID 0x0182 - -#define SILICOM_PE210G2DBi9SR_SSID 0x0188 -#define SILICOM_PE210G2DBi9SRRB_SSID 0x0188 -#define SILICOM_PE210G2DBi9LR_SSID 0x0189 -#define SILICOM_PE210G2DBi9LRRB_SSID 0x0189 -#define SILICOM_PE310G4DBi940SR_SSID 0x018C - -#define SILICOM_PE310G4BPi9T_SSID 0x130 -#define SILICOM_PE310G4BPi9SR_SSID 0x132 -#define SILICOM_PE310G4BPi9LR_SSID 0x133 - -#define NOKIA_XE10G2BPIXR_SVID 0x13B8 -#define NOKIA_XE10G2BPIXR_SSID 0x051C - -#define INTEL_PEG4BPII_PID 0x10A0 -#define INTEL_PEG4BPFII_PID 0x10A1 -#define INTEL_PEG4BPII_SSID 0x11A0 -#define INTEL_PEG4BPFII_SSID 0x11A1 - -#define INTEL_PEG4BPIIO_SSID 0x10A0 -#define INTEL_PEG4BPIIO_PID 0x105e - -#define BROADCOM_VID 0x14e4 -#define BROADCOM_PE10G2_PID 0x164e - -#define SILICOM_PE10G2BPTCX4_SSID 0x0141 -#define SILICOM_PE10G2BPTSR_SSID 0x0142 -#define SILICOM_PE10G2BPTLR_SSID 0x0143 -#define SILICOM_PE10G2BPTT_SSID 0x0140 - -#define SILICOM_PEG4BPI6_SSID 0x0320 -#define SILICOM_PEG4BPFI6_SSID 0x0321 -#define SILICOM_PEG4BPFI6LX_SSID 0x0322 -#define SILICOM_PEG4BPFI6ZX_SSID 0x0323 - -#define SILICOM_PEG2BPI6_SSID 0x0300 -#define SILICOM_PEG2BPFI6_SSID 0x0301 -#define SILICOM_PEG2BPFI6LX_SSID 0x0302 -#define SILICOM_PEG2BPFI6ZX_SSID 0x0303 -#define SILICOM_PEG2BPFI6FLXM_SSID 0x0304 - -#define SILICOM_PEG2DBI6_SSID 0x0308 -#define SILICOM_PEG2DBFI6_SSID 0x0309 -#define SILICOM_PEG2DBFI6LX_SSID 0x030A -#define SILICOM_PEG2DBFI6ZX_SSID 0x030B - -#define SILICOM_MEG2BPI6_SSID 0x0310 -#define SILICOM_XEG2BPI6_SSID 0x0318 -#define SILICOM_PEG4BPI6FC_SSID 0x0328 -#define SILICOM_PEG4BPFI6FC_SSID 0x0329 -#define SILICOM_PEG4BPFI6FCLX_SSID 0x032A -#define SILICOM_PEG4BPFI6FCZX_SSID 0x032B - -#define SILICOM_PEG6BPI6_SSID 0x0340 - -#define SILICOM_PEG2BPI6SC6_SSID 0x0360 - -#define SILICOM_MEG2BPI6_SSID 0x0310 -#define SILICOM_XEG2BPI6_SSID 0x0318 -#define SILICOM_MEG4BPI6_SSID 0x0330 - -#define SILICOM_PE2G4BPi80L_SSID 0x0380 - -#define SILICOM_M6E2G8BPi80A_SSID 0x0474 - -#define SILICOM_PE2G4BPi35_SSID 0x03d8 - -#define SILICOM_PE2G4BPFi80_SSID 0x0381 -#define SILICOM_PE2G4BPFi80LX_SSID 0x0382 -#define SILICOM_PE2G4BPFi80ZX_SSID 0x0383 - -#define SILICOM_PE2G4BPi80_SSID 0x0388 - -#define SILICOM_PE2G2BPi80_SSID 0x0390 -#define SILICOM_PE2G2BPFi80_SSID 0x0391 -#define SILICOM_PE2G2BPFi80LX_SSID 0x0392 -#define SILICOM_PE2G2BPFi80ZX_SSID 0x0393 - -#define SILICOM_PE2G4BPi35L_SSID 0x03D0 -#define SILICOM_PE2G4BPFi35_SSID 0x03D1 -#define SILICOM_PE2G4BPFi35LX_SSID 0x03D2 -#define SILICOM_PE2G4BPFi35ZX_SSID 0x03D3 - -#define SILICOM_PE2G2BPi35_SSID 0x03c0 -#define SILICOM_PAC1200BPi35_SSID 0x03cc -#define SILICOM_PE2G2BPFi35_SSID 0x03C1 -#define SILICOM_PE2G2BPFi35LX_SSID 0x03C2 -#define SILICOM_PE2G2BPFi35ZX_SSID 0x03C3 - -#define SILICOM_PE2G6BPi35_SSID 0x03E0 -#define SILICOM_PE2G6BPi35CX_SSID 0x0AA0 - -#define INTEL_PE210G2SPI9_SSID 0x00C - -#define SILICOM_M1EG2BPI6_SSID 0x400 - -#define SILICOM_M1EG2BPFI6_SSID 0x0401 -#define SILICOM_M1EG2BPFI6LX_SSID 0x0402 -#define SILICOM_M1EG2BPFI6ZX_SSID 0x0403 - -#define SILICOM_M1EG4BPI6_SSID 0x0420 - -#define SILICOM_M1EG4BPFI6_SSID 0x0421 -#define SILICOM_M1EG4BPFI6LX_SSID 0x0422 -#define SILICOM_M1EG4BPFI6ZX_SSID 0x0423 - -#define SILICOM_M1EG6BPI6_SSID 0x0440 - -#define SILICOM_M1E2G4BPi80_SSID 0x0460 -#define SILICOM_M1E2G4BPFi80_SSID 0x0461 -#define SILICOM_M1E2G4BPFi80LX_SSID 0x0462 -#define SILICOM_M1E2G4BPFi80ZX_SSID 0x0463 - -#define SILICOM_M6E2G8BPi80_SSID 0x0470 -#define SILICOM_PE210G2BPi40_SSID 0x01a0 - -#define PEG540_IF_SERIES(pid) \ - ((pid == SILICOM_PE210G2BPi40_SSID)) - -#define OLD_IF_SERIES(pid)\ - ((pid == SILICOM_PXG2BPFI_SSID) || \ - (pid == SILICOM_PXG2BPFILX_SSID)) - -#define P2BPFI_IF_SERIES(pid) \ - ((pid == SILICOM_PXG2BPFI_SSID) || \ - (pid == SILICOM_PXG2BPFILX_SSID) || \ - (pid == SILICOM_PEG2BPFI_SSID) || \ - (pid == SILICOM_PEG2BPFID_SSID) || \ - (pid == SILICOM_PEG2BPFIDLX_SSID) || \ - (pid == SILICOM_MEG2BPFILN_SSID) || \ - (pid == SILICOM_MEG2BPFINX_SSID) || \ - (pid == SILICOM_PEG4BPFILX_SSID) || \ - (pid == SILICOM_PEG4BPFI_SSID) || \ - (pid == SILICOM_PXEG4BPFI_SSID) || \ - (pid == SILICOM_PXG4BPFID_SSID) || \ - (pid == SILICOM_PEG2TBFI_SSID) || \ - (pid == SILICOM_PE10G2BPISR_SSID) || \ - (pid == SILICOM_PE10G2BPILR_SSID) || \ - (pid == SILICOM_PEG2BPFILX_SSID) || \ - (pid == SILICOM_PMCXG2BPFI_SSID) || \ - (pid == SILICOM_MHIO8AD_SSID) || \ - (pid == SILICOM_PEG4BPFI5LX_SSID) || \ - (pid == SILICOM_PEG4BPFI5_SSID) || \ - (pid == SILICOM_PEG4BPFI6FC_SSID) || \ - (pid == SILICOM_PEG4BPFI6FCLX_SSID) || \ - (pid == SILICOM_PEG4BPFI6FCZX_SSID) || \ - (pid == NOKIA_PMCXG2BPFIN_SSID) || \ - (pid == SILICOM_MEG2BPFILXLN_SSID) || \ - (pid == SILICOM_MEG2BPFILXNX_SSID) || \ - (pid == SILICOM_XE10G2BPIT_SSID) || \ - (pid == SILICOM_XE10G2BPICX4_SSID) || \ - (pid == SILICOM_XE10G2BPISR_SSID) || \ - (pid == NOKIA_XE10G2BPIXR_SSID) || \ - (pid == SILICOM_PE10GDBISR_SSID) || \ - (pid == SILICOM_PE10GDBILR_SSID) || \ - (pid == SILICOM_XE10G2BPILR_SSID)) - -#define INTEL_IF_SERIES(pid) \ - ((pid == INTEL_PEG4BPII_SSID) || \ - (pid == INTEL_PEG4BPIIO_SSID) || \ - (pid == INTEL_PEG4BPFII_SSID)) - -#define NOKIA_SERIES(pid) \ - ((pid == NOKIA_PMCXG2BPIN_SSID) || \ - (pid == NOKIA_PMCXG4BPIN_SSID) || \ - (pid == SILICOM_PMCX4BPI_SSID) || \ - (pid == NOKIA_PMCXG2BPFIN_SSID) || \ - (pid == SILICOM_PMCXG2BPFI_SSID) || \ - (pid == NOKIA_PMCXG2BPIN2_SSID) || \ - (pid == NOKIA_PMCXG4BPIN2_SSID) || \ - (pid == SILICOM_PMCX2BPI_SSID)) - -#define DISCF_IF_SERIES(pid) \ - (pid == SILICOM_PEG2TBFI_SSID) - -#define PEGF_IF_SERIES(pid) \ - ((pid == SILICOM_PEG2BPFI_SSID) || \ - (pid == SILICOM_PEG2BPFID_SSID) || \ - (pid == SILICOM_PEG2BPFIDLX_SSID) || \ - (pid == SILICOM_PEG2BPFILX_SSID) || \ - (pid == SILICOM_PEG4BPFI_SSID) || \ - (pid == SILICOM_PXEG4BPFI_SSID) || \ - (pid == SILICOM_MEG2BPFILN_SSID) || \ - (pid == SILICOM_MEG2BPFINX_SSID) || \ - (pid == SILICOM_PEG4BPFILX_SSID) || \ - (pid == SILICOM_PEG2TBFI_SSID) || \ - (pid == SILICOM_MEG2BPFILXLN_SSID) || \ - (pid == SILICOM_MEG2BPFILXNX_SSID)) - -#define TPL_IF_SERIES(pid) \ - ((pid == SILICOM_PXG2BPFIL_SSID) || \ - (pid == SILICOM_PXG2BPFILLX_SSID) || \ - (pid == SILICOM_PXG2TBFI_SSID) || \ - (pid == SILICOM_PXG4BPFID_SSID) || \ - (pid == SILICOM_PXG4BPFI_SSID)) - -#define BP10G_IF_SERIES(pid) \ - ((pid == SILICOM_PE10G2BPISR_SSID) || \ - (pid == SILICOM_PE10G2BPICX4_SSID) || \ - (pid == SILICOM_PE10G2BPILR_SSID) || \ - (pid == SILICOM_XE10G2BPIT_SSID) || \ - (pid == SILICOM_XE10G2BPICX4_SSID) || \ - (pid == SILICOM_XE10G2BPISR_SSID) || \ - (pid == NOKIA_XE10G2BPIXR_SSID) || \ - (pid == SILICOM_PE10GDBISR_SSID) || \ - (pid == SILICOM_PE10GDBILR_SSID) || \ - (pid == SILICOM_XE10G2BPILR_SSID)) - -#define BP10GB_IF_SERIES(pid) \ - ((pid == SILICOM_PE10G2BPTCX4_SSID) || \ - (pid == SILICOM_PE10G2BPTSR_SSID) || \ - (pid == SILICOM_PE10G2BPTLR_SSID) || \ - (pid == SILICOM_PE10G2BPTT_SSID)) - -#define BP10G_CX4_SERIES(pid) \ - (pid == SILICOM_PE10G2BPICX4_SSID) - -#define BP10GB_CX4_SERIES(pid) \ - (pid == SILICOM_PE10G2BPTCX4_SSID) - -#define SILICOM_M2EG2BPFI6_SSID 0x0501 -#define SILICOM_M2EG2BPFI6LX_SSID 0x0502 -#define SILICOM_M2EG2BPFI6ZX_SSID 0x0503 -#define SILICOM_M2EG4BPI6_SSID 0x0520 - -#define SILICOM_M2EG4BPFI6_SSID 0x0521 -#define SILICOM_M2EG4BPFI6LX_SSID 0x0522 -#define SILICOM_M2EG4BPFI6ZX_SSID 0x0523 - -#define SILICOM_M2EG6BPI6_SSID 0x0540 - -#define SILICOM_M1E10G2BPI9CX4_SSID 0x481 -#define SILICOM_M1E10G2BPI9SR_SSID 0x482 -#define SILICOM_M1E10G2BPI9LR_SSID 0x483 -#define SILICOM_M1E10G2BPI9T_SSID 0x480 - -#define SILICOM_M2E10G2BPI9CX4_SSID 0x581 -#define SILICOM_M2E10G2BPI9SR_SSID 0x582 -#define SILICOM_M2E10G2BPI9LR_SSID 0x583 -#define SILICOM_M2E10G2BPI9T_SSID 0x580 - -#define SILICOM_PE210G2BPI9CX4_SSID 0x121 -#define SILICOM_PE210G2BPI9SR_SSID 0x122 -#define SILICOM_PE210G2BPI9LR_SSID 0x123 -#define SILICOM_PE210G2BPI9T_SSID 0x120 - -#define DBI_IF_SERIES(pid) \ - ((pid == SILICOM_PE10GDBISR_SSID) || \ - (pid == SILICOM_PE10GDBILR_SSID) || \ - (pid == SILICOM_XE10G2BPILR_SSID) || \ - (pid == SILICOM_PE210G2DBi9LR_SSID)) - -#define PEGF5_IF_SERIES(pid) \ - ((pid == SILICOM_PEG2BPFI5_SSID) || \ - (pid == SILICOM_PEG2BPFI5LX_SSID) || \ - (pid == SILICOM_PEG4BPFI6_SSID) || \ - (pid == SILICOM_PEG4BPFI6LX_SSID) || \ - (pid == SILICOM_PEG4BPFI6ZX_SSID) || \ - (pid == SILICOM_PEG2BPFI6_SSID) || \ - (pid == SILICOM_PEG2BPFI6LX_SSID) || \ - (pid == SILICOM_PEG2BPFI6ZX_SSID) || \ - (pid == SILICOM_PEG2BPFI6FLXM_SSID) || \ - (pid == SILICOM_PEG2DBFI6_SSID) || \ - (pid == SILICOM_PEG2DBFI6LX_SSID) || \ - (pid == SILICOM_PEG2DBFI6ZX_SSID) || \ - (pid == SILICOM_PEG4BPI6FC_SSID) || \ - (pid == SILICOM_PEG4BPFI6FCLX_SSID) || \ - (pid == SILICOM_PEG4BPI6FC_SSID) || \ - (pid == SILICOM_M1EG2BPFI6_SSID) || \ - (pid == SILICOM_M1EG2BPFI6LX_SSID) || \ - (pid == SILICOM_M1EG2BPFI6ZX_SSID) || \ - (pid == SILICOM_M1EG4BPFI6_SSID) || \ - (pid == SILICOM_M1EG4BPFI6LX_SSID) || \ - (pid == SILICOM_M1EG4BPFI6ZX_SSID) || \ - (pid == SILICOM_M2EG2BPFI6_SSID) || \ - (pid == SILICOM_M2EG2BPFI6LX_SSID) || \ - (pid == SILICOM_M2EG2BPFI6ZX_SSID) || \ - (pid == SILICOM_M2EG4BPFI6_SSID) || \ - (pid == SILICOM_M2EG4BPFI6LX_SSID) || \ - (pid == SILICOM_M2EG4BPFI6ZX_SSID) || \ - (pid == SILICOM_PEG4BPFI6FCZX_SSID)) - -#define PEG5_IF_SERIES(pid) \ - ((pid == SILICOM_PEG4BPI6_SSID) || \ - (pid == SILICOM_PEG2BPI6_SSID) || \ - (pid == SILICOM_PEG4BPI6FC_SSID) || \ - (pid == SILICOM_PEG6BPI6_SSID) || \ - (pid == SILICOM_PEG2BPI6SC6_SSID) || \ - (pid == SILICOM_MEG2BPI6_SSID) || \ - (pid == SILICOM_XEG2BPI6_SSID) || \ - (pid == SILICOM_MEG4BPI6_SSID) || \ - (pid == SILICOM_M1EG2BPI6_SSID) || \ - (pid == SILICOM_M1EG4BPI6_SSID) || \ - (pid == SILICOM_M1EG6BPI6_SSID) || \ - (pid == SILICOM_PEG6BPI_SSID) || \ - (pid == SILICOM_PEG4BPIL_SSID) || \ - (pid == SILICOM_PEG2BISC6_SSID) || \ - (pid == SILICOM_PEG2BPI5_SSID)) - -#define PEG80_IF_SERIES(pid) \ - ((pid == SILICOM_M1E2G4BPi80_SSID) || \ - (pid == SILICOM_M6E2G8BPi80_SSID) || \ - (pid == SILICOM_PE2G4BPi80L_SSID) || \ - (pid == SILICOM_M6E2G8BPi80A_SSID) || \ - (pid == SILICOM_PE2G2BPi35_SSID) || \ - (pid == SILICOM_PAC1200BPi35_SSID) || \ - (pid == SILICOM_PE2G4BPi35_SSID) || \ - (pid == SILICOM_PE2G4BPi35L_SSID) || \ - (pid == SILICOM_PE2G6BPi35_SSID) || \ - (pid == SILICOM_PE2G2BPi80_SSID) || \ - (pid == SILICOM_PE2G4BPi80_SSID) || \ - (pid == SILICOM_PE2G4BPFi80_SSID) || \ - (pid == SILICOM_PE2G4BPFi80LX_SSID) || \ - (pid == SILICOM_PE2G4BPFi80ZX_SSID) || \ - (pid == SILICOM_PE2G4BPFi80ZX_SSID) || \ - (pid == SILICOM_PE2G2BPFi80_SSID) || \ - (pid == SILICOM_PE2G2BPFi80LX_SSID) || \ - (pid == SILICOM_PE2G2BPFi80ZX_SSID) || \ - (pid == SILICOM_PE2G2BPFi35_SSID) || \ - (pid == SILICOM_PE2G2BPFi35LX_SSID) || \ - (pid == SILICOM_PE2G2BPFi35ZX_SSID) || \ - (pid == SILICOM_PE2G4BPFi35_SSID) || \ - (pid == SILICOM_PE2G4BPFi35LX_SSID) || \ - (pid == SILICOM_PE2G4BPFi35ZX_SSID)) - -#define PEGF80_IF_SERIES(pid) \ - ((pid == SILICOM_PE2G4BPFi80_SSID) || \ - (pid == SILICOM_PE2G4BPFi80LX_SSID) || \ - (pid == SILICOM_PE2G4BPFi80ZX_SSID) || \ - (pid == SILICOM_PE2G4BPFi80ZX_SSID) || \ - (pid == SILICOM_M1E2G4BPFi80_SSID) || \ - (pid == SILICOM_M1E2G4BPFi80LX_SSID) || \ - (pid == SILICOM_M1E2G4BPFi80ZX_SSID) || \ - (pid == SILICOM_PE2G2BPFi80_SSID) || \ - (pid == SILICOM_PE2G2BPFi80LX_SSID) || \ - (pid == SILICOM_PE2G2BPFi80ZX_SSID) || \ - (pid == SILICOM_PE2G2BPFi35_SSID) || \ - (pid == SILICOM_PE2G2BPFi35LX_SSID) || \ - (pid == SILICOM_PE2G2BPFi35ZX_SSID) || \ - (pid == SILICOM_PE2G4BPFi35_SSID) || \ - (pid == SILICOM_PE2G4BPFi35LX_SSID) || \ - (pid == SILICOM_PE2G4BPFi35ZX_SSID)) - -#define BP10G9_IF_SERIES(pid) \ - ((pid == INTEL_PE210G2SPI9_SSID) || \ - (pid == SILICOM_M1E10G2BPI9CX4_SSID) || \ - (pid == SILICOM_M1E10G2BPI9SR_SSID) || \ - (pid == SILICOM_M1E10G2BPI9LR_SSID) || \ - (pid == SILICOM_M1E10G2BPI9T_SSID) || \ - (pid == SILICOM_M2E10G2BPI9CX4_SSID) || \ - (pid == SILICOM_M2E10G2BPI9SR_SSID) || \ - (pid == SILICOM_M2E10G2BPI9LR_SSID) || \ - (pid == SILICOM_M2E10G2BPI9T_SSID) || \ - (pid == SILICOM_PE210G2BPI9CX4_SSID) || \ - (pid == SILICOM_PE210G2BPI9SR_SSID) || \ - (pid == SILICOM_PE210G2BPI9LR_SSID) || \ - (pid == SILICOM_PE210G2DBi9SR_SSID) || \ - (pid == SILICOM_PE210G2DBi9SRRB_SSID) || \ - (pid == SILICOM_PE210G2DBi9LR_SSID) || \ - (pid == SILICOM_PE210G2DBi9LRRB_SSID) || \ - (pid == SILICOM_PE310G4DBi940SR_SSID) || \ - (pid == SILICOM_PEG2BISC6_SSID) || \ - (pid == SILICOM_PE310G4BPi9T_SSID) || \ - (pid == SILICOM_PE310G4BPi9SR_SSID) || \ - (pid == SILICOM_PE310G4BPi9LR_SSID) || \ - (pid == SILICOM_PE210G2BPI9T_SSID)) - -/*******************************************************/ -/* 1G INTERFACE ****************************************/ -/*******************************************************/ - -/* Intel Registers */ -#define BPCTLI_CTRL 0x00000 -#define BPCTLI_CTRL_SWDPIO0 0x00400000 -#define BPCTLI_CTRL_SWDPIN0 0x00040000 - -#define BPCTLI_CTRL_EXT 0x00018 /* Extended Device Control - RW */ -#define BPCTLI_STATUS 0x00008 /* Device Status - RO */ - -/* HW related */ -#define BPCTLI_CTRL_EXT_SDP6_DATA 0x00000040 /* Value of SW Defineable Pin 6 */ -#define BPCTLI_CTRL_EXT_SDP7_DATA 0x00000080 /* Value of SW Defineable Pin 7 */ -#define BPCTLI_CTRL_SDP0_DATA 0x00040000 /* SWDPIN 0 value */ -#define BPCTLI_CTRL_EXT_SDP6_DIR 0x00000400 /* Direction of SDP6 0=in 1=out */ -#define BPCTLI_CTRL_EXT_SDP7_DIR 0x00000800 /* Direction of SDP7 0=in 1=out */ -#define BPCTLI_CTRL_SDP0_DIR 0x00400000 /* SDP0 Input or output */ -#define BPCTLI_CTRL_SWDPIN1 0x00080000 -#define BPCTLI_CTRL_SDP1_DIR 0x00800000 - -#define BPCTLI_STATUS_LU 0x00000002 /* Link up.0=no,1=link */ - -#define BPCTLI_CTRL_SDP0_SHIFT 18 -#define BPCTLI_CTRL_EXT_SDP6_SHIFT 6 - -#define BPCTLI_STATUS_TBIMODE 0x00000020 -#define BPCTLI_CTRL_EXT_LINK_MODE_PCIE_SERDES 0x00C00000 -#define BPCTLI_CTRL_EXT_LINK_MODE_MASK 0x00C00000 - -#define BPCTLI_CTRL_EXT_MCLK_DIR BPCTLI_CTRL_EXT_SDP7_DIR -#define BPCTLI_CTRL_EXT_MCLK_DATA BPCTLI_CTRL_EXT_SDP7_DATA -#define BPCTLI_CTRL_EXT_MDIO_DIR BPCTLI_CTRL_EXT_SDP6_DIR -#define BPCTLI_CTRL_EXT_MDIO_DATA BPCTLI_CTRL_EXT_SDP6_DATA - -#define BPCTLI_CTRL_EXT_MCLK_DIR5 BPCTLI_CTRL_SDP1_DIR -#define BPCTLI_CTRL_EXT_MCLK_DATA5 BPCTLI_CTRL_SWDPIN1 -#define BPCTLI_CTRL_EXT_MCLK_DIR80 BPCTLI_CTRL_EXT_SDP6_DIR -#define BPCTLI_CTRL_EXT_MCLK_DATA80 BPCTLI_CTRL_EXT_SDP6_DATA -#define BPCTLI_CTRL_EXT_MDIO_DIR5 BPCTLI_CTRL_SWDPIO0 -#define BPCTLI_CTRL_EXT_MDIO_DATA5 BPCTLI_CTRL_SWDPIN0 -#define BPCTLI_CTRL_EXT_MDIO_DIR80 BPCTLI_CTRL_SWDPIO0 -#define BPCTLI_CTRL_EXT_MDIO_DATA80 BPCTLI_CTRL_SWDPIN0 - -#define BPCTL_WRITE_REG(a, reg, value) \ - (writel((value), (void *)(((a)->mem_map) + BPCTLI_##reg))) - -#define BPCTL_READ_REG(a, reg) ( \ - readl((void *)((a)->mem_map) + BPCTLI_##reg)) - -#define BPCTL_WRITE_FLUSH(a) BPCTL_READ_REG(a, STATUS) - -#define BPCTL_BP_WRITE_REG(a, reg, value) ({ \ - BPCTL_WRITE_REG(a, reg, value); \ - BPCTL_WRITE_FLUSH(a); }) - -/**************************************************************/ -/************** 82575 Interface********************************/ -/**************************************************************/ - -#define BPCTLI_MII_CR_POWER_DOWN 0x0800 -#define BPCTLI_PHY_CONTROL 0x00 /* Control Register */ -#define BPCTLI_MDIC 0x00020 /* MDI Control - RW */ -#define BPCTLI_IGP01E1000_PHY_PAGE_SELECT 0x1F /* Page Select */ -#define BPCTLI_MAX_PHY_REG_ADDRESS 0x1F /* 5 bit address bus (0-0x1F) */ - -#define BPCTLI_MDIC_DATA_MASK 0x0000FFFF -#define BPCTLI_MDIC_REG_MASK 0x001F0000 -#define BPCTLI_MDIC_REG_SHIFT 16 -#define BPCTLI_MDIC_PHY_MASK 0x03E00000 -#define BPCTLI_MDIC_PHY_SHIFT 21 -#define BPCTLI_MDIC_OP_WRITE 0x04000000 -#define BPCTLI_MDIC_OP_READ 0x08000000 -#define BPCTLI_MDIC_READY 0x10000000 -#define BPCTLI_MDIC_INT_EN 0x20000000 -#define BPCTLI_MDIC_ERROR 0x40000000 - -#define BPCTLI_SWFW_PHY0_SM 0x02 -#define BPCTLI_SWFW_PHY1_SM 0x04 - -#define BPCTLI_SW_FW_SYNC 0x05B5C /* Software-Firmware Synchronization - RW */ - -#define BPCTLI_SWSM 0x05B50 /* SW Semaphore */ -#define BPCTLI_FWSM 0x05B54 /* FW Semaphore */ - -#define BPCTLI_SWSM_SMBI 0x00000001 /* Driver Semaphore bit */ -#define BPCTLI_SWSM_SWESMBI 0x00000002 /* FW Semaphore bit */ -#define BPCTLI_MAX_PHY_MULTI_PAGE_REG 0xF -#define BPCTLI_GEN_POLL_TIMEOUT 640 - -/********************************************************/ - -/********************************************************/ -/* 10G INTERFACE ****************************************/ -/********************************************************/ - -#define BP10G_I2CCTL 0x28 - -/* I2CCTL Bit Masks */ -#define BP10G_I2C_CLK_IN 0x00000001 -#define BP10G_I2C_CLK_OUT 0x00000002 -#define BP10G_I2C_DATA_IN 0x00000004 -#define BP10G_I2C_DATA_OUT 0x00000008 - -#define BP10G_ESDP 0x20 - -#define BP10G_SDP0_DIR 0x100 -#define BP10G_SDP1_DIR 0x200 -#define BP10G_SDP3_DIR 0x800 -#define BP10G_SDP4_DIR BIT_12 -#define BP10G_SDP5_DIR 0x2000 -#define BP10G_SDP0_DATA 0x001 -#define BP10G_SDP1_DATA 0x002 -#define BP10G_SDP3_DATA 0x008 -#define BP10G_SDP4_DATA 0x010 -#define BP10G_SDP5_DATA 0x020 - -#define BP10G_SDP2_DIR 0x400 -#define BP10G_SDP2_DATA 0x4 - -#define BP10G_EODSDP 0x28 - -#define BP10G_SDP6_DATA_IN 0x001 -#define BP10G_SDP6_DATA_OUT 0x002 - -#define BP10G_SDP7_DATA_IN 0x004 -#define BP10G_SDP7_DATA_OUT 0x008 - -#define BP10G_MCLK_DATA_OUT BP10G_SDP7_DATA_OUT -#define BP10G_MDIO_DATA_OUT BP10G_SDP6_DATA_OUT -#define BP10G_MDIO_DATA_IN BP10G_SDP6_DATA_IN - -#define BP10G_MDIO_DATA /*BP10G_SDP5_DATA*/ BP10G_SDP3_DATA -#define BP10G_MDIO_DIR /*BP10G_SDP5_DIR*/ BP10G_SDP3_DATA - -/*#define BP10G_MCLK_DATA_OUT9 BP10G_I2C_CLK_OUT -#define BP10G_MDIO_DATA_OUT9 BP10G_I2C_DATA_OUT*/ - - /*#define BP10G_MCLK_DATA_OUT9*//*BP10G_I2C_DATA_OUT */ -#define BP10G_MDIO_DATA_OUT9 BP10G_I2C_DATA_OUT /*BP10G_I2C_CLK_OUT */ - -/* VIA EOSDP ! */ -#define BP10G_MCLK_DATA_OUT9 BP10G_SDP4_DATA -#define BP10G_MCLK_DIR_OUT9 BP10G_SDP4_DIR - -/*#define BP10G_MDIO_DATA_IN9 BP10G_I2C_DATA_IN*/ - -#define BP10G_MDIO_DATA_IN9 BP10G_I2C_DATA_IN /*BP10G_I2C_CLK_IN */ - -#define BP540_MDIO_DATA /*BP10G_SDP5_DATA*/ BP10G_SDP0_DATA -#define BP540_MDIO_DIR /*BP10G_SDP5_DIR*/ BP10G_SDP0_DIR -#define BP540_MCLK_DATA BP10G_SDP2_DATA -#define BP540_MCLK_DIR BP10G_SDP2_DIR - -#define BP10G_WRITE_REG(a, reg, value) \ - (writel((value), (void *)(((a)->mem_map) + BP10G_##reg))) - -#define BP10G_READ_REG(a, reg) ( \ - readl((void *)((a)->mem_map) + BP10G_##reg)) - -/*****BROADCOM*******************************************/ - -#define BP10GB_MISC_REG_GPIO 0xa490 -#define BP10GB_GPIO3_P0 BIT_3 -#define BP10GB_GPIO3_P1 BIT_7 - -#define BP10GB_GPIO3_SET_P0 BIT_11 -#define BP10GB_GPIO3_CLR_P0 BIT_19 -#define BP10GB_GPIO3_OE_P0 BIT_27 - -#define BP10GB_GPIO3_SET_P1 BIT_15 -#define BP10GB_GPIO3_CLR_P1 BIT_23 -#define BP10GB_GPIO3_OE_P1 BIT_31 - -#define BP10GB_GPIO0_P1 0x10 -#define BP10GB_GPIO0_P0 0x1 -#define BP10GB_GPIO0_CLR_P0 0x10000 -#define BP10GB_GPIO0_CLR_P1 0x100000 -#define BP10GB_GPIO0_SET_P0 0x100 -#define BP10GB_GPIO0_SET_P1 0x1000 - -#define BP10GB_GPIO0_OE_P1 0x10000000 -#define BP10GB_GPIO0_OE_P0 0x1000000 - -#define BP10GB_MISC_REG_SPIO 0xa4fc -#define BP10GB_GPIO4_OE BIT_28 -#define BP10GB_GPIO5_OE BIT_29 -#define BP10GB_GPIO4_CLR BIT_20 -#define BP10GB_GPIO5_CLR BIT_21 -#define BP10GB_GPIO4_SET BIT_12 -#define BP10GB_GPIO5_SET BIT_13 -#define BP10GB_GPIO4 BIT_4 -#define BP10GB_GPIO5 BIT_5 - -#define BP10GB_MCLK_DIR BP10GB_GPIO5_OE -#define BP10GB_MDIO_DIR BP10GB_GPIO4_OE - -#define BP10GB_MCLK_DATA BP10GB_GPIO5 -#define BP10GB_MDIO_DATA BP10GB_GPIO4 - -#define BP10GB_MCLK_SET BP10GB_GPIO5_SET -#define BP10GB_MDIO_SET BP10GB_GPIO4_SET - -#define BP10GB_MCLK_CLR BP10GB_GPIO5_CLR -#define BP10GB_MDIO_CLR BP10GB_GPIO4_CLR - -#define BP10GB_WRITE_REG(a, reg, value) \ - (writel((value), (void *)(((a)->mem_map) + BP10GB_##reg))) - -#define BP10GB_READ_REG(a, reg) ( \ - readl((void *)((a)->mem_map) + BP10GB_##reg)) - -#endif - -int bp_proc_create(void); diff --git a/trunk/drivers/staging/silicom/bp_proc.c b/trunk/drivers/staging/silicom/bp_proc.c deleted file mode 100644 index 6ad4b27472e4..000000000000 --- a/trunk/drivers/staging/silicom/bp_proc.c +++ /dev/null @@ -1,1350 +0,0 @@ -/******************************************************************************/ -/* */ -/* Copyright (c) 2004-2006 Silicom, Ltd */ -/* All rights reserved. */ -/* */ -/* This program is free software; you can redistribute it and/or modify */ -/* it under the terms of the GNU General Public License as published by */ -/* the Free Software Foundation, located in the file LICENSE. */ -/* */ -/* */ -/******************************************************************************/ - -#include -#if defined(CONFIG_SMP) && ! defined(__SMP__) -#define __SMP__ -#endif - -#include -#include -#include -//#include -#include "bp_mod.h" - -#define BP_PROC_DIR "bypass" -//#define BYPASS_SUPPORT "bypass" - -#ifdef BYPASS_SUPPORT - -#define GPIO6_SET_ENTRY_SD "gpio6_set" -#define GPIO6_CLEAR_ENTRY_SD "gpio6_clear" - -#define GPIO7_SET_ENTRY_SD "gpio7_set" -#define GPIO7_CLEAR_ENTRY_SD "gpio7_clear" - -#define PULSE_SET_ENTRY_SD "pulse_set" -#define ZERO_SET_ENTRY_SD "zero_set" -#define PULSE_GET1_ENTRY_SD "pulse_get1" -#define PULSE_GET2_ENTRY_SD "pulse_get2" - -#define CMND_ON_ENTRY_SD "cmnd_on" -#define CMND_OFF_ENTRY_SD "cmnd_off" -#define RESET_CONT_ENTRY_SD "reset_cont" - - /*COMMANDS*/ -#define BYPASS_INFO_ENTRY_SD "bypass_info" -#define BYPASS_SLAVE_ENTRY_SD "bypass_slave" -#define BYPASS_CAPS_ENTRY_SD "bypass_caps" -#define WD_SET_CAPS_ENTRY_SD "wd_set_caps" -#define BYPASS_ENTRY_SD "bypass" -#define BYPASS_CHANGE_ENTRY_SD "bypass_change" -#define BYPASS_WD_ENTRY_SD "bypass_wd" -#define WD_EXPIRE_TIME_ENTRY_SD "wd_expire_time" -#define RESET_BYPASS_WD_ENTRY_SD "reset_bypass_wd" -#define DIS_BYPASS_ENTRY_SD "dis_bypass" -#define BYPASS_PWUP_ENTRY_SD "bypass_pwup" -#define BYPASS_PWOFF_ENTRY_SD "bypass_pwoff" -#define STD_NIC_ENTRY_SD "std_nic" -#define STD_NIC_ENTRY_SD "std_nic" -#define TAP_ENTRY_SD "tap" -#define TAP_CHANGE_ENTRY_SD "tap_change" -#define DIS_TAP_ENTRY_SD "dis_tap" -#define TAP_PWUP_ENTRY_SD "tap_pwup" -#define TWO_PORT_LINK_ENTRY_SD "two_port_link" -#define WD_EXP_MODE_ENTRY_SD "wd_exp_mode" -#define WD_AUTORESET_ENTRY_SD "wd_autoreset" -#define TPL_ENTRY_SD "tpl" -#define WAIT_AT_PWUP_ENTRY_SD "wait_at_pwup" -#define HW_RESET_ENTRY_SD "hw_reset" -#define DISC_ENTRY_SD "disc" -#define DISC_CHANGE_ENTRY_SD "disc_change" -#define DIS_DISC_ENTRY_SD "dis_disc" -#define DISC_PWUP_ENTRY_SD "disc_pwup" -#endif //bypass_support -static struct proc_dir_entry *bp_procfs_dir; - -static struct proc_dir_entry *proc_getdir(char *name, - struct proc_dir_entry *proc_dir) -{ - struct proc_dir_entry *pde = proc_dir; - for (pde = pde->subdir; pde; pde = pde->next) { - if (pde->namelen && (strcmp(name, pde->name) == 0)) { - /* directory exists */ - break; - } - } - if (pde == (struct proc_dir_entry *)0) { - /* create the directory */ - pde = create_proc_entry(name, S_IFDIR, proc_dir); - if (pde == (struct proc_dir_entry *)0) { - return (pde); - } - } - return (pde); -} - -#ifdef BYPASS_SUPPORT - -int -bypass_proc_create_entry_sd(struct pfs_unit *pfs_unit_curr, - char *proc_name, - write_proc_t * write_proc, - read_proc_t * read_proc, - struct proc_dir_entry *parent_pfs, void *data) -{ - strcpy(pfs_unit_curr->proc_name, proc_name); - pfs_unit_curr->proc_entry = create_proc_entry(pfs_unit_curr->proc_name, - S_IFREG | S_IRUSR | - S_IWUSR | S_IRGRP | - S_IROTH, parent_pfs); - if (pfs_unit_curr->proc_entry == 0) { - - return -1; - } - - pfs_unit_curr->proc_entry->read_proc = read_proc; - pfs_unit_curr->proc_entry->write_proc = write_proc; - pfs_unit_curr->proc_entry->data = data; - - return 0; - -} - -int -get_bypass_info_pfs(char *page, char **start, off_t off, int count, - int *eof, void *data) -{ - bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data; - int len = 0; - - len += sprintf(page, "Name\t\t\t%s\n", pbp_device_block->bp_name); - len += - sprintf(page + len, "Firmware version\t0x%x\n", - pbp_device_block->bp_fw_ver); - - *eof = 1; - return len; -} - -int -get_bypass_slave_pfs(char *page, char **start, off_t off, int count, - int *eof, void *data) -{ - bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data; - - struct pci_dev *pci_slave_dev = pbp_device_block->bp_slave; - struct net_device *net_slave_dev; - int len = 0; - - if (is_bypass_fn(pbp_device_block)) { - net_slave_dev = pci_get_drvdata(pci_slave_dev); - if (net_slave_dev) - len = sprintf(page, "%s\n", net_slave_dev->name); - else - len = sprintf(page, "fail\n"); - } else - len = sprintf(page, "fail\n"); - - *eof = 1; - return len; -} - -int -get_bypass_caps_pfs(char *page, char **start, off_t off, int count, - int *eof, void *data) -{ - bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data; - - int len = 0, ret = 0; - - ret = get_bypass_caps_fn(pbp_device_block); - if (ret == BP_NOT_CAP) - len = sprintf(page, "-1\n"); - else - len = sprintf(page, "0x%x\n", ret); - *eof = 1; - return len; - -} - -int -get_wd_set_caps_pfs(char *page, char **start, off_t off, int count, - int *eof, void *data) -{ - bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data; - - int len = 0, ret = 0; - - ret = get_wd_set_caps_fn(pbp_device_block); - if (ret == BP_NOT_CAP) - len = sprintf(page, "-1\n"); - else - len = sprintf(page, "0x%x\n", ret); - *eof = 1; - return len; -} - -int -set_bypass_pfs(struct file *file, const char *buffer, - unsigned long count, void *data) -{ - - char kbuf[256]; - bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data; - - int bypass_param = 0, length = 0; - - if (count > (sizeof(kbuf) - 1)) - return -1; - - if (copy_from_user(&kbuf, buffer, count)) { - return -1; - } - - kbuf[count] = '\0'; - length = strlen(kbuf); - if (kbuf[length - 1] == '\n') - kbuf[--length] = '\0'; - - if (strcmp(kbuf, "on") == 0) - bypass_param = 1; - else if (strcmp(kbuf, "off") == 0) - bypass_param = 0; - - set_bypass_fn(pbp_device_block, bypass_param); - - return count; -} - -int -set_tap_pfs(struct file *file, const char *buffer, - unsigned long count, void *data) -{ - - char kbuf[256]; - bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data; - - int tap_param = 0, length = 0; - - if (count > (sizeof(kbuf) - 1)) - return -1; - - if (copy_from_user(&kbuf, buffer, count)) { - return -1; - } - - kbuf[count] = '\0'; - length = strlen(kbuf); - if (kbuf[length - 1] == '\n') - kbuf[--length] = '\0'; - - if (strcmp(kbuf, "on") == 0) - tap_param = 1; - else if (strcmp(kbuf, "off") == 0) - tap_param = 0; - - set_tap_fn(pbp_device_block, tap_param); - - return count; -} - -int -set_disc_pfs(struct file *file, const char *buffer, - unsigned long count, void *data) -{ - - char kbuf[256]; - bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data; - - int tap_param = 0, length = 0; - - if (count > (sizeof(kbuf) - 1)) - return -1; - - if (copy_from_user(&kbuf, buffer, count)) { - return -1; - } - - kbuf[count] = '\0'; - length = strlen(kbuf); - if (kbuf[length - 1] == '\n') - kbuf[--length] = '\0'; - - if (strcmp(kbuf, "on") == 0) - tap_param = 1; - else if (strcmp(kbuf, "off") == 0) - tap_param = 0; - - set_disc_fn(pbp_device_block, tap_param); - - return count; -} - -int -get_bypass_pfs(char *page, char **start, off_t off, int count, - int *eof, void *data) -{ - bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data; - - int len = 0, ret = 0; - - ret = get_bypass_fn(pbp_device_block); - if (ret == BP_NOT_CAP) - len = sprintf(page, "fail\n"); - else if (ret == 1) - len = sprintf(page, "on\n"); - else if (ret == 0) - len = sprintf(page, "off\n"); - - *eof = 1; - return len; -} - -int -get_tap_pfs(char *page, char **start, off_t off, int count, - int *eof, void *data) -{ - bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data; - - int len = 0, ret = 0; - - ret = get_tap_fn(pbp_device_block); - if (ret == BP_NOT_CAP) - len = sprintf(page, "fail\n"); - else if (ret == 1) - len = sprintf(page, "on\n"); - else if (ret == 0) - len = sprintf(page, "off\n"); - - *eof = 1; - return len; -} - -int -get_disc_pfs(char *page, char **start, off_t off, int count, - int *eof, void *data) -{ - bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data; - - int len = 0, ret = 0; - - ret = get_disc_fn(pbp_device_block); - if (ret == BP_NOT_CAP) - len = sprintf(page, "fail\n"); - else if (ret == 1) - len = sprintf(page, "on\n"); - else if (ret == 0) - len = sprintf(page, "off\n"); - - *eof = 1; - return len; -} - -int -get_bypass_change_pfs(char *page, char **start, off_t off, int count, - int *eof, void *data) -{ - bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data; - - int len = 0, ret = 0; - - ret = get_bypass_change_fn(pbp_device_block); - if (ret == 1) - len = sprintf(page, "on\n"); - else if (ret == 0) - len = sprintf(page, "off\n"); - else - len = sprintf(page, "fail\n"); - - *eof = 1; - return len; -} - -int -get_tap_change_pfs(char *page, char **start, off_t off, int count, - int *eof, void *data) -{ - bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data; - - int len = 0, ret = 0; - - ret = get_tap_change_fn(pbp_device_block); - if (ret == 1) - len = sprintf(page, "on\n"); - else if (ret == 0) - len = sprintf(page, "off\n"); - else - len = sprintf(page, "fail\n"); - - *eof = 1; - return len; -} - -int -get_disc_change_pfs(char *page, char **start, off_t off, int count, - int *eof, void *data) -{ - bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data; - - int len = 0, ret = 0; - - ret = get_disc_change_fn(pbp_device_block); - if (ret == 1) - len = sprintf(page, "on\n"); - else if (ret == 0) - len = sprintf(page, "off\n"); - else - len = sprintf(page, "fail\n"); - - *eof = 1; - return len; -} - -int -set_bypass_wd_pfs(struct file *file, const char *buffer, - unsigned long count, void *data) -{ - - char kbuf[256]; - bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data; - - unsigned int timeout = 0; - char *timeout_ptr = kbuf; - - if (copy_from_user(&kbuf, buffer, count)) { - return -1; - } - - timeout_ptr = kbuf; - timeout = atoi(&timeout_ptr); - - set_bypass_wd_fn(pbp_device_block, timeout); - - return count; -} - -int -get_bypass_wd_pfs(char *page, char **start, off_t off, int count, - int *eof, void *data) -{ - bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data; - - int len = 0, ret = 0, timeout = 0; - - ret = get_bypass_wd_fn(pbp_device_block, &timeout); - if (ret == BP_NOT_CAP) - len = sprintf(page, "fail\n"); - else if (timeout == -1) - len = sprintf(page, "unknown\n"); - else if (timeout == 0) - len = sprintf(page, "disable\n"); - else - len = sprintf(page, "%d\n", timeout); - - *eof = 1; - return len; -} - -int -get_wd_expire_time_pfs(char *page, char **start, off_t off, int count, - int *eof, void *data) -{ - bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data; - - int len = 0, ret = 0, timeout = 0; - - ret = get_wd_expire_time_fn(pbp_device_block, &timeout); - if (ret == BP_NOT_CAP) - len = sprintf(page, "fail\n"); - else if (timeout == -1) - len = sprintf(page, "expire\n"); - else if (timeout == 0) - len = sprintf(page, "disable\n"); - - else - len = sprintf(page, "%d\n", timeout); - *eof = 1; - return len; -} - -int -get_tpl_pfs(char *page, char **start, off_t off, int count, - int *eof, void *data) -{ - bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data; - - int len = 0, ret = 0; - - ret = get_tpl_fn(pbp_device_block); - if (ret == BP_NOT_CAP) - len = sprintf(page, "fail\n"); - else if (ret == 1) - len = sprintf(page, "on\n"); - else if (ret == 0) - len = sprintf(page, "off\n"); - - *eof = 1; - return len; -} - -#ifdef PMC_FIX_FLAG -int -get_wait_at_pwup_pfs(char *page, char **start, off_t off, int count, - int *eof, void *data) -{ - bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data; - - int len = 0, ret = 0; - - ret = get_bp_wait_at_pwup_fn(pbp_device_block); - if (ret == BP_NOT_CAP) - len = sprintf(page, "fail\n"); - else if (ret == 1) - len = sprintf(page, "on\n"); - else if (ret == 0) - len = sprintf(page, "off\n"); - - *eof = 1; - return len; -} - -int -get_hw_reset_pfs(char *page, char **start, off_t off, int count, - int *eof, void *data) -{ - bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data; - - int len = 0, ret = 0; - - ret = get_bp_hw_reset_fn(pbp_device_block); - if (ret == BP_NOT_CAP) - len = sprintf(page, "fail\n"); - else if (ret == 1) - len = sprintf(page, "on\n"); - else if (ret == 0) - len = sprintf(page, "off\n"); - - *eof = 1; - return len; -} - -#endif /*PMC_WAIT_FLAG */ - -int -reset_bypass_wd_pfs(char *page, char **start, off_t off, int count, - int *eof, void *data) -{ - bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data; - - int len = 0, ret = 0; - - ret = reset_bypass_wd_timer_fn(pbp_device_block); - if (ret == BP_NOT_CAP) - len = sprintf(page, "fail\n"); - else if (ret == 0) - len = sprintf(page, "disable\n"); - else if (ret == 1) - len = sprintf(page, "success\n"); - - *eof = 1; - return len; -} - -int -set_dis_bypass_pfs(struct file *file, const char *buffer, - unsigned long count, void *data) -{ - - char kbuf[256]; - bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data; - - int bypass_param = 0, length = 0; - - if (copy_from_user(&kbuf, buffer, count)) { - return -1; - } - - kbuf[count] = '\0'; - length = strlen(kbuf); - if (kbuf[length - 1] == '\n') - kbuf[--length] = '\0'; - - if (strcmp(kbuf, "on") == 0) - bypass_param = 1; - else if (strcmp(kbuf, "off") == 0) - bypass_param = 0; - - set_dis_bypass_fn(pbp_device_block, bypass_param); - - return count; -} - -int -set_dis_tap_pfs(struct file *file, const char *buffer, - unsigned long count, void *data) -{ - - char kbuf[256]; - bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data; - - int tap_param = 0, length = 0; - - if (copy_from_user(&kbuf, buffer, count)) { - return -1; - } - - kbuf[count] = '\0'; - length = strlen(kbuf); - if (kbuf[length - 1] == '\n') - kbuf[--length] = '\0'; - - if (strcmp(kbuf, "on") == 0) - tap_param = 1; - else if (strcmp(kbuf, "off") == 0) - tap_param = 0; - - set_dis_tap_fn(pbp_device_block, tap_param); - - return count; -} - -int -set_dis_disc_pfs(struct file *file, const char *buffer, - unsigned long count, void *data) -{ - - char kbuf[256]; - bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data; - - int tap_param = 0, length = 0; - - if (copy_from_user(&kbuf, buffer, count)) { - return -1; - } - - kbuf[count] = '\0'; - length = strlen(kbuf); - if (kbuf[length - 1] == '\n') - kbuf[--length] = '\0'; - - if (strcmp(kbuf, "on") == 0) - tap_param = 1; - else if (strcmp(kbuf, "off") == 0) - tap_param = 0; - - set_dis_disc_fn(pbp_device_block, tap_param); - - return count; -} - -int -get_dis_bypass_pfs(char *page, char **start, off_t off, int count, - int *eof, void *data) -{ - bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data; - - int len = 0, ret = 0; - - ret = get_dis_bypass_fn(pbp_device_block); - if (ret == BP_NOT_CAP) - len = sprintf(page, "fail\n"); - else if (ret == 0) - len = sprintf(page, "off\n"); - else - len = sprintf(page, "on\n"); - - *eof = 1; - return len; -} - -int -get_dis_tap_pfs(char *page, char **start, off_t off, int count, - int *eof, void *data) -{ - bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data; - - int len = 0, ret = 0; - - ret = get_dis_tap_fn(pbp_device_block); - if (ret == BP_NOT_CAP) - len = sprintf(page, "fail\n"); - else if (ret == 0) - len = sprintf(page, "off\n"); - else - len = sprintf(page, "on\n"); - - *eof = 1; - return len; -} - -int -get_dis_disc_pfs(char *page, char **start, off_t off, int count, - int *eof, void *data) -{ - bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data; - - int len = 0, ret = 0; - - ret = get_dis_disc_fn(pbp_device_block); - if (ret == BP_NOT_CAP) - len = sprintf(page, "fail\n"); - else if (ret == 0) - len = sprintf(page, "off\n"); - else - len = sprintf(page, "on\n"); - - *eof = 1; - return len; -} - -int -set_bypass_pwup_pfs(struct file *file, const char *buffer, - unsigned long count, void *data) -{ - - char kbuf[256]; - bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data; - - int bypass_param = 0, length = 0; - - if (copy_from_user(&kbuf, buffer, count)) { - return -1; - } - - kbuf[count] = '\0'; - length = strlen(kbuf); - if (kbuf[length - 1] == '\n') - kbuf[--length] = '\0'; - - if (strcmp(kbuf, "on") == 0) - bypass_param = 1; - else if (strcmp(kbuf, "off") == 0) - bypass_param = 0; - - set_bypass_pwup_fn(pbp_device_block, bypass_param); - - return count; -} - -int -set_bypass_pwoff_pfs(struct file *file, const char *buffer, - unsigned long count, void *data) -{ - - char kbuf[256]; - bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data; - - int bypass_param = 0, length = 0; - - if (copy_from_user(&kbuf, buffer, count)) { - return -1; - } - - kbuf[count] = '\0'; - length = strlen(kbuf); - if (kbuf[length - 1] == '\n') - kbuf[--length] = '\0'; - - if (strcmp(kbuf, "on") == 0) - bypass_param = 1; - else if (strcmp(kbuf, "off") == 0) - bypass_param = 0; - - set_bypass_pwoff_fn(pbp_device_block, bypass_param); - - return count; -} - -int -set_tap_pwup_pfs(struct file *file, const char *buffer, - unsigned long count, void *data) -{ - - char kbuf[256]; - bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data; - - int tap_param = 0, length = 0; - - if (copy_from_user(&kbuf, buffer, count)) { - return -1; - } - - kbuf[count] = '\0'; - length = strlen(kbuf); - if (kbuf[length - 1] == '\n') - kbuf[--length] = '\0'; - - if (strcmp(kbuf, "on") == 0) - tap_param = 1; - else if (strcmp(kbuf, "off") == 0) - tap_param = 0; - - set_tap_pwup_fn(pbp_device_block, tap_param); - - return count; -} - -int -set_disc_pwup_pfs(struct file *file, const char *buffer, - unsigned long count, void *data) -{ - - char kbuf[256]; - bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data; - - int tap_param = 0, length = 0; - - if (copy_from_user(&kbuf, buffer, count)) { - return -1; - } - - kbuf[count] = '\0'; - length = strlen(kbuf); - if (kbuf[length - 1] == '\n') - kbuf[--length] = '\0'; - - if (strcmp(kbuf, "on") == 0) - tap_param = 1; - else if (strcmp(kbuf, "off") == 0) - tap_param = 0; - - set_disc_pwup_fn(pbp_device_block, tap_param); - - return count; -} - -int -get_bypass_pwup_pfs(char *page, char **start, off_t off, int count, - int *eof, void *data) -{ - bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data; - - int len = 0, ret = 0; - - ret = get_bypass_pwup_fn(pbp_device_block); - if (ret == BP_NOT_CAP) - len = sprintf(page, "fail\n"); - else if (ret == 0) - len = sprintf(page, "off\n"); - else - len = sprintf(page, "on\n"); - - *eof = 1; - return len; -} - -int -get_bypass_pwoff_pfs(char *page, char **start, off_t off, int count, - int *eof, void *data) -{ - bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data; - - int len = 0, ret = 0; - - ret = get_bypass_pwoff_fn(pbp_device_block); - if (ret == BP_NOT_CAP) - len = sprintf(page, "fail\n"); - else if (ret == 0) - len = sprintf(page, "off\n"); - else - len = sprintf(page, "on\n"); - - *eof = 1; - return len; -} - -int -get_tap_pwup_pfs(char *page, char **start, off_t off, int count, - int *eof, void *data) -{ - bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data; - - int len = 0, ret = 0; - - ret = get_tap_pwup_fn(pbp_device_block); - if (ret == BP_NOT_CAP) - len = sprintf(page, "fail\n"); - else if (ret == 0) - len = sprintf(page, "off\n"); - else - len = sprintf(page, "on\n"); - - *eof = 1; - return len; -} - -int -get_disc_pwup_pfs(char *page, char **start, off_t off, int count, - int *eof, void *data) -{ - bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data; - - int len = 0, ret = 0; - - ret = get_disc_pwup_fn(pbp_device_block); - if (ret == BP_NOT_CAP) - len = sprintf(page, "fail\n"); - else if (ret == 0) - len = sprintf(page, "off\n"); - else - len = sprintf(page, "on\n"); - - *eof = 1; - return len; -} - -int -set_std_nic_pfs(struct file *file, const char *buffer, - unsigned long count, void *data) -{ - - char kbuf[256]; - bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data; - - int bypass_param = 0, length = 0; - - if (copy_from_user(&kbuf, buffer, count)) { - return -1; - } - - kbuf[count] = '\0'; - length = strlen(kbuf); - if (kbuf[length - 1] == '\n') - kbuf[--length] = '\0'; - - if (strcmp(kbuf, "on") == 0) - bypass_param = 1; - else if (strcmp(kbuf, "off") == 0) - bypass_param = 0; - - set_std_nic_fn(pbp_device_block, bypass_param); - - return count; -} - -int -get_std_nic_pfs(char *page, char **start, off_t off, int count, - int *eof, void *data) -{ - bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data; - - int len = 0, ret = 0; - - ret = get_std_nic_fn(pbp_device_block); - if (ret == BP_NOT_CAP) - len = sprintf(page, "fail\n"); - else if (ret == 0) - len = sprintf(page, "off\n"); - else - len = sprintf(page, "on\n"); - - *eof = 1; - return len; -} - -int -get_wd_exp_mode_pfs(char *page, char **start, off_t off, int count, - int *eof, void *data) -{ - bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data; - - int len = 0, ret = 0; - - ret = get_wd_exp_mode_fn(pbp_device_block); - if (ret == 1) - len = sprintf(page, "tap\n"); - else if (ret == 0) - len = sprintf(page, "bypass\n"); - else if (ret == 2) - len = sprintf(page, "disc\n"); - - else - len = sprintf(page, "fail\n"); - - *eof = 1; - return len; -} - -int -set_wd_exp_mode_pfs(struct file *file, const char *buffer, - unsigned long count, void *data) -{ - - char kbuf[256]; - bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data; - - int bypass_param = 0, length = 0; - - if (count > (sizeof(kbuf) - 1)) - return -1; - - if (copy_from_user(&kbuf, buffer, count)) { - return -1; - } - - kbuf[count] = '\0'; - length = strlen(kbuf); - if (kbuf[length - 1] == '\n') - kbuf[--length] = '\0'; - - if (strcmp(kbuf, "tap") == 0) - bypass_param = 1; - else if (strcmp(kbuf, "bypass") == 0) - bypass_param = 0; - else if (strcmp(kbuf, "disc") == 0) - bypass_param = 2; - - set_wd_exp_mode_fn(pbp_device_block, bypass_param); - - return count; -} - -int -get_wd_autoreset_pfs(char *page, char **start, off_t off, int count, - int *eof, void *data) -{ - bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data; - - int len = 0, ret = 0; - - ret = get_wd_autoreset_fn(pbp_device_block); - if (ret >= 0) - len = sprintf(page, "%d\n", ret); - else - len = sprintf(page, "fail\n"); - - *eof = 1; - return len; -} - -int -set_wd_autoreset_pfs(struct file *file, const char *buffer, - unsigned long count, void *data) -{ - char kbuf[256]; - bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data; - u32 timeout = 0; - char *timeout_ptr = kbuf; - - if (copy_from_user(&kbuf, buffer, count)) { - return -1; - } - - timeout_ptr = kbuf; - timeout = atoi(&timeout_ptr); - - set_wd_autoreset_fn(pbp_device_block, timeout); - - return count; -} - -int -set_tpl_pfs(struct file *file, const char *buffer, - unsigned long count, void *data) -{ - - char kbuf[256]; - bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data; - - int tpl_param = 0, length = 0; - - if (count > (sizeof(kbuf) - 1)) - return -1; - - if (copy_from_user(&kbuf, buffer, count)) { - return -1; - } - - kbuf[count] = '\0'; - length = strlen(kbuf); - if (kbuf[length - 1] == '\n') - kbuf[--length] = '\0'; - - if (strcmp(kbuf, "on") == 0) - tpl_param = 1; - else if (strcmp(kbuf, "off") == 0) - tpl_param = 0; - - set_tpl_fn(pbp_device_block, tpl_param); - - return count; -} - -#ifdef PMC_FIX_FLAG -int -set_wait_at_pwup_pfs(struct file *file, const char *buffer, - unsigned long count, void *data) -{ - - char kbuf[256]; - bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data; - - int tpl_param = 0, length = 0; - - if (count > (sizeof(kbuf) - 1)) - return -1; - - if (copy_from_user(&kbuf, buffer, count)) { - return -1; - } - - kbuf[count] = '\0'; - length = strlen(kbuf); - if (kbuf[length - 1] == '\n') - kbuf[--length] = '\0'; - - if (strcmp(kbuf, "on") == 0) - tpl_param = 1; - else if (strcmp(kbuf, "off") == 0) - tpl_param = 0; - - set_bp_wait_at_pwup_fn(pbp_device_block, tpl_param); - - return count; -} - -int -set_hw_reset_pfs(struct file *file, const char *buffer, - unsigned long count, void *data) -{ - - char kbuf[256]; - bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data; - - int tpl_param = 0, length = 0; - - if (count > (sizeof(kbuf) - 1)) - return -1; - - if (copy_from_user(&kbuf, buffer, count)) { - return -1; - } - - kbuf[count] = '\0'; - length = strlen(kbuf); - if (kbuf[length - 1] == '\n') - kbuf[--length] = '\0'; - - if (strcmp(kbuf, "on") == 0) - tpl_param = 1; - else if (strcmp(kbuf, "off") == 0) - tpl_param = 0; - - set_bp_hw_reset_fn(pbp_device_block, tpl_param); - - return count; -} - -#endif /*PMC_FIX_FLAG */ - -int bypass_proc_create_dev_sd(bpctl_dev_t * pbp_device_block) -{ - struct bypass_pfs_sd *current_pfs = &(pbp_device_block->bypass_pfs_set); - static struct proc_dir_entry *procfs_dir = NULL; - int ret = 0; - - sprintf(current_pfs->dir_name, "bypass_%s", dev->name); - - if (!bp_procfs_dir) - return -1; - - /* create device proc dir */ - procfs_dir = proc_getdir(current_pfs->dir_name, bp_procfs_dir); - if (procfs_dir == 0) { - printk(KERN_DEBUG "Could not create procfs directory %s\n", - current_pfs->dir_name); - return -1; - } - current_pfs->bypass_entry = procfs_dir; - - if (bypass_proc_create_entry(&(current_pfs->bypass_info), BYPASS_INFO_ENTRY_SD, NULL, /* write */ - get_bypass_info_pfs, /* read */ - procfs_dir, pbp_device_block)) - ret = -1; - - if (pbp_device_block->bp_caps & SW_CTL_CAP) { - - /* Create set param proc's */ - if (bypass_proc_create_entry_sd(&(current_pfs->bypass_slave), BYPASS_SLAVE_ENTRY_SD, NULL, /* write */ - get_bypass_slave_pfs, /* read */ - procfs_dir, pbp_device_block)) - ret = -1; - - if (bypass_proc_create_entry_sd(&(current_pfs->bypass_caps), BYPASS_CAPS_ENTRY_SD, NULL, /* write */ - get_bypass_caps_pfs, /* read */ - procfs_dir, pbp_device_block)) - ret = -1; - - if (bypass_proc_create_entry_sd(&(current_pfs->wd_set_caps), WD_SET_CAPS_ENTRY_SD, NULL, /* write */ - get_wd_set_caps_pfs, /* read */ - procfs_dir, pbp_device_block)) - ret = -1; - if (bypass_proc_create_entry_sd(&(current_pfs->bypass_wd), BYPASS_WD_ENTRY_SD, set_bypass_wd_pfs, /* write */ - get_bypass_wd_pfs, /* read */ - procfs_dir, pbp_device_block)) - ret = -1; - - if (bypass_proc_create_entry_sd(&(current_pfs->wd_expire_time), WD_EXPIRE_TIME_ENTRY_SD, NULL, /* write */ - get_wd_expire_time_pfs, /* read */ - procfs_dir, pbp_device_block)) - ret = -1; - - if (bypass_proc_create_entry_sd(&(current_pfs->reset_bypass_wd), RESET_BYPASS_WD_ENTRY_SD, NULL, /* write */ - reset_bypass_wd_pfs, /* read */ - procfs_dir, pbp_device_block)) - ret = -1; - - if (bypass_proc_create_entry_sd(&(current_pfs->std_nic), STD_NIC_ENTRY_SD, set_std_nic_pfs, /* write */ - get_std_nic_pfs, /* read */ - procfs_dir, pbp_device_block)) - ret = -1; - - if (pbp_device_block->bp_caps & BP_CAP) { - if (bypass_proc_create_entry_sd(&(current_pfs->bypass), BYPASS_ENTRY_SD, set_bypass_pfs, /* write */ - get_bypass_pfs, /* read */ - procfs_dir, - pbp_device_block)) - ret = -1; - - if (bypass_proc_create_entry_sd(&(current_pfs->dis_bypass), DIS_BYPASS_ENTRY_SD, set_dis_bypass_pfs, /* write */ - get_dis_bypass_pfs, /* read */ - procfs_dir, - pbp_device_block)) - ret = -1; - - if (bypass_proc_create_entry_sd(&(current_pfs->bypass_pwup), BYPASS_PWUP_ENTRY_SD, set_bypass_pwup_pfs, /* write */ - get_bypass_pwup_pfs, /* read */ - procfs_dir, - pbp_device_block)) - ret = -1; - if (bypass_proc_create_entry_sd(&(current_pfs->bypass_pwoff), BYPASS_PWOFF_ENTRY_SD, set_bypass_pwoff_pfs, /* write */ - get_bypass_pwoff_pfs, /* read */ - procfs_dir, - pbp_device_block)) - ret = -1; - - if (bypass_proc_create_entry_sd(&(current_pfs->bypass_change), BYPASS_CHANGE_ENTRY_SD, NULL, /* write */ - get_bypass_change_pfs, /* read */ - procfs_dir, - pbp_device_block)) - ret = -1; - } - - if (pbp_device_block->bp_caps & TAP_CAP) { - - if (bypass_proc_create_entry_sd(&(current_pfs->tap), TAP_ENTRY_SD, set_tap_pfs, /* write */ - get_tap_pfs, /* read */ - procfs_dir, - pbp_device_block)) - ret = -1; - - if (bypass_proc_create_entry_sd(&(current_pfs->dis_tap), DIS_TAP_ENTRY_SD, set_dis_tap_pfs, /* write */ - get_dis_tap_pfs, /* read */ - procfs_dir, - pbp_device_block)) - ret = -1; - - if (bypass_proc_create_entry_sd(&(current_pfs->tap_pwup), TAP_PWUP_ENTRY_SD, set_tap_pwup_pfs, /* write */ - get_tap_pwup_pfs, /* read */ - procfs_dir, - pbp_device_block)) - ret = -1; - - if (bypass_proc_create_entry_sd(&(current_pfs->tap_change), TAP_CHANGE_ENTRY_SD, NULL, /* write */ - get_tap_change_pfs, /* read */ - procfs_dir, - pbp_device_block)) - ret = -1; - } - if (pbp_device_block->bp_caps & DISC_CAP) { - - if (bypass_proc_create_entry_sd(&(current_pfs->tap), DISC_ENTRY_SD, set_disc_pfs, /* write */ - get_disc_pfs, /* read */ - procfs_dir, - pbp_device_block)) - ret = -1; -#if 1 - - if (bypass_proc_create_entry_sd(&(current_pfs->dis_tap), DIS_DISC_ENTRY_SD, set_dis_disc_pfs, /* write */ - get_dis_disc_pfs, /* read */ - procfs_dir, - pbp_device_block)) - ret = -1; -#endif - - if (bypass_proc_create_entry_sd(&(current_pfs->tap_pwup), DISC_PWUP_ENTRY_SD, set_disc_pwup_pfs, /* write */ - get_disc_pwup_pfs, /* read */ - procfs_dir, - pbp_device_block)) - ret = -1; - - if (bypass_proc_create_entry_sd(&(current_pfs->tap_change), DISC_CHANGE_ENTRY_SD, NULL, /* write */ - get_disc_change_pfs, /* read */ - procfs_dir, - pbp_device_block)) - ret = -1; - } - - if (bypass_proc_create_entry_sd(&(current_pfs->wd_exp_mode), WD_EXP_MODE_ENTRY_SD, set_wd_exp_mode_pfs, /* write */ - get_wd_exp_mode_pfs, /* read */ - procfs_dir, pbp_device_block)) - ret = -1; - - if (bypass_proc_create_entry_sd(&(current_pfs->wd_autoreset), WD_AUTORESET_ENTRY_SD, set_wd_autoreset_pfs, /* write */ - get_wd_autoreset_pfs, /* read */ - procfs_dir, pbp_device_block)) - ret = -1; - if (bypass_proc_create_entry_sd(&(current_pfs->tpl), TPL_ENTRY_SD, set_tpl_pfs, /* write */ - get_tpl_pfs, /* read */ - procfs_dir, pbp_device_block)) - ret = -1; -#ifdef PMC_FIX_FLAG - if (bypass_proc_create_entry_sd(&(current_pfs->tpl), WAIT_AT_PWUP_ENTRY_SD, set_wait_at_pwup_pfs, /* write */ - get_wait_at_pwup_pfs, /* read */ - procfs_dir, pbp_device_block)) - ret = -1; - if (bypass_proc_create_entry_sd(&(current_pfs->tpl), HW_RESET_ENTRY_SD, set_hw_reset_pfs, /* write */ - get_hw_reset_pfs, /* read */ - procfs_dir, pbp_device_block)) - ret = -1; - -#endif - - } - if (ret < 0) - printk(KERN_DEBUG "Create proc entry failed\n"); - - return ret; -} - -int bypass_proc_remove_dev_sd(bpctl_dev_t * pbp_device_block) -{ - - struct bypass_pfs_sd *current_pfs = &pbp_device_block->bypass_pfs_set; - struct proc_dir_entry *pde = current_pfs->bypass_entry, *pde_curr = - NULL; - char name[256]; - - for (pde = pde->subdir; pde;) { - strcpy(name, pde->name); - pde_curr = pde; - pde = pde->next; - remove_proc_entry(name, current_pfs->bypass_entry); - } - if (!pde) - remove_proc_entry(current_pfs->dir_name, bp_procfs_dir); - - return 0; -} - -#endif /* BYPASS_SUPPORT */ diff --git a/trunk/drivers/staging/silicom/bypass.h b/trunk/drivers/staging/silicom/bypass.h deleted file mode 100644 index 08fa7a0fc8d8..000000000000 --- a/trunk/drivers/staging/silicom/bypass.h +++ /dev/null @@ -1,202 +0,0 @@ -/******************************************************************************/ -/* */ -/* Bypass Control utility, Copyright (c) 2005 Silicom */ -/* All rights reserved. */ -/* */ -/* This program is free software; you can redistribute it and/or modify */ -/* it under the terms of the GNU General Public License as published by */ -/* the Free Software Foundation, located in the file LICENSE. */ -/* */ -/* */ -/******************************************************************************/ - -#ifndef BYPASS_H -#define BYPASS_H - -/* Bypass related */ - -#define SYNC_CMD_VAL 2 /* 10b */ -#define SYNC_CMD_LEN 2 - -#define WR_CMD_VAL 2 /* 10b */ -#define WR_CMD_LEN 2 - -#define RD_CMD_VAL 1 /* 10b */ -#define RD_CMD_LEN 2 - -#define ADDR_CMD_LEN 4 - -#define WR_DATA_LEN 8 -#define RD_DATA_LEN 8 - -#define PIC_SIGN_REG_ADDR 0x7 -#define PIC_SIGN_VALUE 0xcd - -#define STATUS_REG_ADDR 0 -#define WDT_EN_MASK 0x01 /* BIT_0 */ -#define CMND_EN_MASK 0x02 /* BIT_1 */ -#define DIS_BYPASS_CAP_MASK 0x04 /* BIT_2 Bypass Cap is disable*/ -#define DFLT_PWRON_MASK 0x08 /* BIT_3 */ -#define BYPASS_OFF_MASK 0x10 /* BIT_4 */ -#define BYPASS_FLAG_MASK 0x20 /* BIT_5 */ -#define STD_NIC_MASK (DIS_BYPASS_CAP_MASK | BYPASS_OFF_MASK | DFLT_PWRON_MASK) -#define WD_EXP_FLAG_MASK 0x40 /* BIT_6 */ -#define DFLT_PWROFF_MASK 0x80 /* BIT_7 */ -#define STD_NIC_PWOFF_MASK (DIS_BYPASS_CAP_MASK | BYPASS_OFF_MASK | DFLT_PWRON_MASK | DFLT_PWROFF_MASK) - -#define PRODUCT_CAP_REG_ADDR 0x5 -#define BYPASS_SUPPORT_MASK 0x01 /* BIT_0 */ -#define TAP_SUPPORT_MASK 0x02 /* BIT_1 */ -#define NORMAL_UNSUPPORT_MASK 0x04 /* BIT_2 */ -#define DISC_SUPPORT_MASK 0x08 /* BIT_3 */ -#define TPL2_SUPPORT_MASK 0x10 /* BIT_4 */ -#define DISC_PORT_SUPPORT_MASK 0x20 /* BIT_5 */ - -#define STATUS_TAP_REG_ADDR 0x6 -#define WDTE_TAP_BPN_MASK 0x01 /* BIT_1 1 when wdt expired -> TAP, 0 - Bypass */ -#define DIS_TAP_CAP_MASK 0x04 /* BIT_2 TAP Cap is disable*/ -#define DFLT_PWRON_TAP_MASK 0x08 /* BIT_3 */ -#define TAP_OFF_MASK 0x10 /* BIT_4 */ -#define TAP_FLAG_MASK 0x20 /* BIT_5 */ -#define TX_DISA_MASK 0x40 -#define TX_DISB_MASK 0x80 - -#define STD_NIC_TAP_MASK (DIS_TAP_CAP_MASK | TAP_OFF_MASK | DFLT_PWRON_TAP_MASK) - -#define STATUS_DISC_REG_ADDR 13 -#define WDTE_DISC_BPN_MASK 0x01 /* BIT_0 1 when wdt expired -> TAP, 0 - Bypass */ -#define STD_NIC_ON_MASK 0x02 /* BIT_1 */ -#define DIS_DISC_CAP_MASK 0x04 /* BIT_2 TAP Cap is disable*/ -#define DFLT_PWRON_DISC_MASK 0x08 /* BIT_3 */ -#define DISC_OFF_MASK 0x10 /* BIT_4 */ -#define DISC_FLAG_MASK 0x20 /* BIT_5 */ -#define TPL2_FLAG_MASK 0x40 /* BIT_6 */ -#define STD_NIC_DISC_MASK DIS_DISC_CAP_MASK - -#define CONT_CONFIG_REG_ADDR 12 -#define EN_HW_RESET_MASK 0x2 /* BIT_1 */ -#define WAIT_AT_PWUP_MASK 0x1 /* BIT_0 */ - -#define VER_REG_ADDR 0x1 -#define BP_FW_VER_A0 0xa0 -#define BP_FW_VER_A1 0xa1 - -#define INT_VER_MASK 0xf0 -#define EXT_VER_MASK 0xf -/* */ -#define PXG2BPI_VER 0x0 -#define PXG2TBPI_VER 0x1 -#define PXE2TBPI_VER 0x2 -#define PXG4BPFI_VER 0x4 -#define BP_FW_EXT_VER7 0x6 -#define BP_FW_EXT_VER8 0x8 -#define BP_FW_EXT_VER9 0x9 - -#define OLD_IF_VER -1 - -#define CMND_REG_ADDR 10 /* 1010b */ -#define WDT_REG_ADDR 4 -#define TMRL_REG_ADDR 2 -#define TMRH_REG_ADDR 3 - -/* NEW_FW */ -#define WDT_INTERVAL 1 /* 5 //8 */ -#define WDT_CMND_INTERVAL 200 /* 50 */ -#define CMND_INTERVAL 200 /* 100 usec */ -#define PULSE_TIME 100 - -/* OLD_FW */ -#define INIT_CMND_INTERVAL 40 -#define PULSE_INTERVAL 5 -#define WDT_TIME_CNT 3 - -/* Intel Commands */ - -#define CMND_OFF_INT 0xf -#define PWROFF_BYPASS_ON_INT 0x5 -#define BYPASS_ON_INT 0x6 -#define DIS_BYPASS_CAP_INT 0x4 -#define RESET_WDT_INT 0x1 - -/* Intel timing */ - -#define BYPASS_DELAY_INT 4 /* msec */ -#define CMND_INTERVAL_INT 2 /* msec */ - -/* Silicom Commands */ -#define CMND_ON 0x4 -#define CMND_OFF 0x2 -#define BYPASS_ON 0xa -#define BYPASS_OFF 0x8 -#define PORT_LINK_EN 0xe -#define PORT_LINK_DIS 0xc -#define WDT_ON 0x10 /* 0x1f (11111) - max */ -#define TIMEOUT_UNIT 100 -#define TIMEOUT_MAX_STEP 15 -#define WDT_TIMEOUT_MIN 100 /* msec */ -#define WDT_TIMEOUT_MAX 3276800 /* msec */ -#define WDT_AUTO_MIN_INT 500 -#define WDT_TIMEOUT_DEF WDT_TIMEOUT_MIN -#define WDT_OFF 0x6 -#define WDT_RELOAD 0x9 -#define RESET_CONT 0x20 -#define DIS_BYPASS_CAP 0x22 -#define EN_BYPASS_CAP 0x24 -#define BYPASS_STATE_PWRON 0x26 -#define NORMAL_STATE_PWRON 0x28 -#define BYPASS_STATE_PWROFF 0x27 -#define NORMAL_STATE_PWROFF 0x29 -#define TAP_ON 0xb -#define TAP_OFF 0x9 -#define TAP_STATE_PWRON 0x2a -#define DIS_TAP_CAP 0x2c -#define EN_TAP_CAP 0x2e -#define STD_NIC_OFF 0x86 -#define STD_NIC_ON 0x84 -#define DISC_ON 0x85 -#define DISC_OFF 0x8a -#define DISC_STATE_PWRON 0x87 -#define DIS_DISC_CAP 0x88 -#define EN_DISC_CAP 0x89 -#define TPL2_ON 0x8c -#define TPL2_OFF 0x8b -#define BP_WAIT_AT_PWUP_EN 0x80 -#define BP_WAIT_AT_PWUP_DIS 0x81 -#define BP_HW_RESET_EN 0x82 -#define BP_HW_RESET_DIS 0x83 - -#define TX_DISA 0x8d -#define TX_DISB 0x8e -#define TX_ENA 0xA0 -#define TX_ENB 0xA1 - -#define TX_DISA_PWRUP 0xA2 -#define TX_DISB_PWRUP 0xA3 -#define TX_ENA_PWRUP 0xA4 -#define TX_ENB_PWRUP 0xA5 - -#define BYPASS_CAP_DELAY 21 /* msec */ -#define DFLT_PWRON_DELAY 10 /* msec */ -#define LATCH_DELAY 13 /* msec */ -#define EEPROM_WR_DELAY 8 /* msec */ - -#define BP_LINK_MON_DELAY 4 /* sec */ - -#define BP_FW_EXT_VER0 0xa0 -#define BP_FW_EXT_VER1 0xa1 -#define BP_FW_EXT_VER2 0xb1 - -#define BP_OK 0 -#define BP_NOT_CAP -1 -#define WDT_STATUS_EXP -2 -#define WDT_STATUS_UNKNOWN -1 -#define WDT_STATUS_EN 1 -#define WDT_STATUS_DIS 0 - -#ifdef BP_SELF_TEST -#define ETH_P_BPTEST 0xabba - -#define BPTEST_DATA_LEN 60 -#endif - -#endif /* BYPASS_H */ diff --git a/trunk/drivers/staging/silicom/bypasslib/Makefile b/trunk/drivers/staging/silicom/bypasslib/Makefile deleted file mode 100644 index 80e8b9bc9357..000000000000 --- a/trunk/drivers/staging/silicom/bypasslib/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -# -# Makefile for the Bypass network device drivers. -# - -obj-$(CONFIG_SBYPASS) += bypass.o - diff --git a/trunk/drivers/staging/silicom/bypasslib/bp_ioctl.h b/trunk/drivers/staging/silicom/bypasslib/bp_ioctl.h deleted file mode 100644 index 040c6fa8d5ad..000000000000 --- a/trunk/drivers/staging/silicom/bypasslib/bp_ioctl.h +++ /dev/null @@ -1,198 +0,0 @@ -/******************************************************************************/ -/* */ -/* bypass library, Copyright (c) 2004-2006 Silicom, Ltd */ -/* 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, located in the file LICENSE. */ -/* */ -/* */ -/* */ -/******************************************************************************/ - -#ifndef BP_IOCTL_H -#define BP_IOCTL_H - -#define BP_CAP 0x01 //BIT_0 -#define BP_STATUS_CAP 0x02 //BIT_1 -#define BP_STATUS_CHANGE_CAP 0x04 //BIT_2 -#define SW_CTL_CAP 0x08 //BIT_3 -#define BP_DIS_CAP 0x10 //BIT_4 -#define BP_DIS_STATUS_CAP 0x20 //BIT_5 -#define STD_NIC_CAP 0x40 //BIT_6 -#define BP_PWOFF_ON_CAP 0x80 //BIT_7 -#define BP_PWOFF_OFF_CAP 0x0100 //BIT_8 -#define BP_PWOFF_CTL_CAP 0x0200 //BIT_9 -#define BP_PWUP_ON_CAP 0x0400 //BIT_10 -#define BP_PWUP_OFF_CAP 0x0800 //BIT_11 -#define BP_PWUP_CTL_CAP 0x1000 //BIT_12 -#define WD_CTL_CAP 0x2000 //BIT_13 -#define WD_STATUS_CAP 0x4000 //BIT_14 -#define WD_TIMEOUT_CAP 0x8000 //BIT_15 -#define TX_CTL_CAP 0x10000 //BIT_16 -#define TX_STATUS_CAP 0x20000 //BIT_17 -#define TAP_CAP 0x40000 //BIT_18 -#define TAP_STATUS_CAP 0x80000 //BIT_19 -#define TAP_STATUS_CHANGE_CAP 0x100000 //BIT_20 -#define TAP_DIS_CAP 0x200000 //BIT_21 -#define TAP_DIS_STATUS_CAP 0x400000 //BIT_22 -#define TAP_PWUP_ON_CAP 0x800000 //BIT_23 -#define TAP_PWUP_OFF_CAP 0x1000000 //BIT 24 -#define TAP_PWUP_CTL_CAP 0x2000000 //BIT 25 -#define NIC_CAP_NEG 0x4000000 //BIT 26 -#define TPL_CAP 0x8000000 //BIT 27 -#define DISC_CAP 0x10000000 //BIT 28 -#define DISC_DIS_CAP 0x20000000 //BIT 29 -#define DISC_PWUP_CTL_CAP 0x40000000 //BIT 30 - -#define WD_MIN_TIME_MASK(val) (val & 0xf) -#define WD_STEP_COUNT_MASK(val) ((val & 0xf) << 5) -#define WDT_STEP_TIME 0x10 //BIT_4 - -#define WD_MIN_TIME_GET(desc) (desc & 0xf) -#define WD_STEP_COUNT_GET(desc) (desc>>5) & 0xf - -typedef enum { - IS_BYPASS = 1, - GET_BYPASS_SLAVE, - GET_BYPASS_CAPS, - GET_WD_SET_CAPS, - SET_BYPASS, - GET_BYPASS, - GET_BYPASS_CHANGE, - SET_BYPASS_WD, - GET_BYPASS_WD, - GET_WD_EXPIRE_TIME, - RESET_BYPASS_WD_TIMER, - SET_DIS_BYPASS, - GET_DIS_BYPASS, - SET_BYPASS_PWOFF, - GET_BYPASS_PWOFF, - SET_BYPASS_PWUP, - GET_BYPASS_PWUP, - SET_STD_NIC, - GET_STD_NIC, - SET_TX, - GET_TX, - SET_TAP, - GET_TAP, - GET_TAP_CHANGE, - SET_DIS_TAP, - GET_DIS_TAP, - SET_TAP_PWUP, - GET_TAP_PWUP, - SET_WD_EXP_MODE, - GET_WD_EXP_MODE, - SET_WD_AUTORESET, - GET_WD_AUTORESET, - SET_TPL, - GET_TPL, - SET_DISC, - GET_DISC, - GET_DISC_CHANGE, - SET_DIS_DISC, - GET_DIS_DISC, - SET_DISC_PWUP, - GET_DISC_PWUP, - - GET_BYPASS_INFO = 100, - GET_BP_WAIT_AT_PWUP, - SET_BP_WAIT_AT_PWUP, - GET_BP_HW_RESET, - SET_BP_HW_RESET, -} CMND_TYPE; - -typedef enum { - IF_SCAN_SD, - GET_DEV_NUM_SD, - IS_BYPASS_SD, - GET_BYPASS_SLAVE_SD, - GET_BYPASS_CAPS_SD, - GET_WD_SET_CAPS_SD, - SET_BYPASS_SD, - GET_BYPASS_SD, - GET_BYPASS_CHANGE_SD, - SET_BYPASS_WD_SD, - GET_BYPASS_WD_SD, - GET_WD_EXPIRE_TIME_SD, - RESET_BYPASS_WD_TIMER_SD, - SET_DIS_BYPASS_SD, - GET_DIS_BYPASS_SD, - SET_BYPASS_PWOFF_SD, - GET_BYPASS_PWOFF_SD, - SET_BYPASS_PWUP_SD, - GET_BYPASS_PWUP_SD, - SET_STD_NIC_SD, - GET_STD_NIC_SD, - SET_TX_SD, - GET_TX_SD, - SET_TAP_SD, - GET_TAP_SD, - GET_TAP_CHANGE_SD, - SET_DIS_TAP_SD, - GET_DIS_TAP_SD, - SET_TAP_PWUP_SD, - GET_TAP_PWUP_SD, - SET_WD_EXP_MODE_SD, - GET_WD_EXP_MODE_SD, - SET_WD_AUTORESET_SD, - GET_WD_AUTORESET_SD, - SET_TPL_SD, - GET_TPL_SD, - SET_DISC_SD, - GET_DISC_SD, - GET_DISC_CHANGE_SD, - SET_DIS_DISC_SD, - GET_DIS_DISC_SD, - SET_DISC_PWUP_SD, - GET_DISC_PWUP_SD, - - GET_BYPASS_INFO_SD = 100, - GET_BP_WAIT_AT_PWUP_SD, - SET_BP_WAIT_AT_PWUP_SD, - GET_BP_HW_RESET_SD, - SET_BP_HW_RESET_SD, - -} CMND_TYPE_SD; - -#define SIOCGIFBYPASS SIOCDEVPRIVATE+10 - -struct bp_info { - char prod_name[14]; - unsigned char fw_ver; -}; - -/* for passing single values */ -struct if_bypass { - char if_name[IFNAMSIZ]; - int cmd; - int data; -}; -struct if_bypass_info { - char if_name[IFNAMSIZ]; - char cmd; - struct bp_info bp_info; -}; - -/* -* The major device number. We can't rely on dynamic -* registration any more, because ioctls need to know -* it. -*/ - -#define MAGIC_NUM 'J' - -/* for passing single values */ -struct bpctl_cmd { - int status; - int data[8]; - int in_param[8]; - int out_param[8]; -}; - -#define IOCTL_TX_MSG(cmd) _IOWR(MAGIC_NUM, cmd, struct bpctl_cmd) - -#define DEVICE_NAME "bpctl" - -#endif diff --git a/trunk/drivers/staging/silicom/bypasslib/bplibk.h b/trunk/drivers/staging/silicom/bypasslib/bplibk.h deleted file mode 100644 index a1c85eec02f0..000000000000 --- a/trunk/drivers/staging/silicom/bypasslib/bplibk.h +++ /dev/null @@ -1,47 +0,0 @@ -/******************************************************************************/ -/* */ -/* bypass library, Copyright (c) 2004 Silicom, Ltd */ -/* */ -/* 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, located in the file LICENSE. */ -/* */ -/* */ -/* bplib.h */ -/* */ -/******************************************************************************/ -#ifndef BYPASS_H -#define BYPASS_H - -#include "bp_ioctl.h" -#include "libbp_sd.h" - -#define IF_NAME "eth" -#define SILICOM_VID 0x1374 -#define SILICOM_BP_PID_MIN 0x24 -#define SILICOM_BP_PID_MAX 0x5f -#define INTEL_PEG4BPII_PID 0x10a0 -#define INTEL_PEG4BPFII_PID 0x10a1 - -#define PEGII_IF_SERIES(vid, pid) \ - ((vid==0x8086)&& \ - ((pid==INTEL_PEG4BPII_PID)|| \ - (pid==INTEL_PEG4BPFII_PID))) - -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10)) -#define pci_get_class pci_find_class - -#define pci_get_device pci_find_device - -#endif - -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,10)) -#define EXPORT_SYMBOL_NOVERS EXPORT_SYMBOL -#endif - -#ifdef BP_VENDOR_SUPPORT -char *bp_desc_array[] = - { "e1000bp", "e1000bpe", "slcm5700", "bnx2xbp", "ixgbp", "ixgbpe", NULL }; -#endif - -#endif diff --git a/trunk/drivers/staging/silicom/bypasslib/bypass.c b/trunk/drivers/staging/silicom/bypasslib/bypass.c deleted file mode 100644 index 527829d58133..000000000000 --- a/trunk/drivers/staging/silicom/bypasslib/bypass.c +++ /dev/null @@ -1,529 +0,0 @@ -/******************************************************************************/ -/* */ -/* bypass library, Copyright (c) 2004-2007 Silicom, Ltd */ -/* */ -/* 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, located in the file LICENSE. */ -/* */ -/* */ -/* bypass.c */ -/* */ -/******************************************************************************/ - -#include -#if defined(CONFIG_SMP) && ! defined(__SMP__) -#define __SMP__ -#endif - -#include -#include -#include - -#include -#include - -#include // struct device, and other headers -#include -#include -#include -#include - -#include - -#include "bplibk.h" - -#define MOD_NAME "bypass" - -#define VERSION "\n"MOD_NAME" version 9.0.4\n" - -MODULE_AUTHOR("www.silicom.co.il"); - -MODULE_LICENSE("GPL"); - -int init_lib_module(void); -void cleanup_lib_module(void); - -static int do_cmd(struct net_device *dev, struct ifreq *ifr, int cmd, int *data) -{ - int ret = -1; - struct if_bypass *bypass_cb; - static int (*ioctl) (struct net_device *, struct ifreq *, int); - - bypass_cb = (struct if_bypass *)ifr; - bypass_cb->cmd = cmd; - bypass_cb->data = *data; - if ((dev->netdev_ops) && (ioctl = dev->netdev_ops->ndo_do_ioctl)) { - ret = ioctl(dev, ifr, SIOCGIFBYPASS); - *data = bypass_cb->data; - } - - return ret; -} - -static int doit(int cmd, int if_index, int *data) -{ - struct ifreq ifr; - int ret = -1; - struct net_device *dev; - struct net_device *n; - for_each_netdev_safe(&init_net, dev, n) { - - if (dev->ifindex == if_index) { - ret = do_cmd(dev, &ifr, cmd, data); - if (ret < 0) - ret = -1; - - } - } - - return ret; -} - -#define bp_symbol_get(fn_name) symbol_get(fn_name) -#define bp_symbol_put(fn_name) symbol_put(fn_name) - -#define SET_BPLIB_INT_FN(fn_name, arg_type, arg, ret) \ - ({ int (* fn_ex)(arg_type)=NULL; \ - fn_ex=bp_symbol_get(fn_name##_sd); \ - if(fn_ex) { \ - ret= fn_ex(arg); \ - bp_symbol_put(fn_name##_sd); \ - } else ret=-1; \ - }) - -#define SET_BPLIB_INT_FN2(fn_name, arg_type, arg, arg_type1, arg1, ret) \ - ({ int (* fn_ex)(arg_type,arg_type1)=NULL; \ - fn_ex=bp_symbol_get(fn_name##_sd); \ - if(fn_ex) { \ - ret= fn_ex(arg,arg1); \ - bp_symbol_put(fn_name##_sd); \ - } else ret=-1; \ - }) -#define SET_BPLIB_INT_FN3(fn_name, arg_type, arg, arg_type1, arg1,arg_type2, arg2, ret) \ - ({ int (* fn_ex)(arg_type,arg_type1, arg_type2)=NULL; \ - fn_ex=bp_symbol_get(fn_name##_sd); \ - if(fn_ex) { \ - ret= fn_ex(arg,arg1,arg2); \ - bp_symbol_put(fn_name##_sd); \ - } else ret=-1; \ - }) - -#define DO_BPLIB_GET_ARG_FN(fn_name,ioctl_val, if_index) \ - ({ int data, ret=0; \ - if(is_dev_sd(if_index)){ \ - SET_BPLIB_INT_FN(fn_name, int, if_index, ret); \ - return ret; \ - } \ - return doit(ioctl_val,if_index, &data); \ - }) - -#define DO_BPLIB_SET_ARG_FN(fn_name,ioctl_val,if_index,arg) \ - ({ int data, ret=0; \ - if(is_dev_sd(if_index)){ \ - SET_BPLIB_INT_FN2(fn_name, int, if_index, int, arg, ret); \ - return ret; \ - } \ - data=arg; \ - return doit(ioctl_val,if_index, &data); \ - }) - -static int is_dev_sd(int if_index) -{ - int ret = 0; - SET_BPLIB_INT_FN(is_bypass, int, if_index, ret); - return (ret >= 0 ? 1 : 0); -} - -int is_bypass_dev(int if_index) -{ - struct pci_dev *pdev = NULL; - struct net_device *dev = NULL; - struct ifreq ifr; - int ret = 0, data = 0; - - while ((pdev = pci_get_class(PCI_CLASS_NETWORK_ETHERNET << 8, pdev))) { - if ((dev = pci_get_drvdata(pdev)) != NULL) - if (((dev = pci_get_drvdata(pdev)) != NULL) && - (dev->ifindex == if_index)) { - if ((pdev->vendor == SILICOM_VID) && - (pdev->device >= SILICOM_BP_PID_MIN) && - (pdev->device <= SILICOM_BP_PID_MAX)) - goto send_cmd; -#if defined(BP_VENDOR_SUPPORT) && defined(ETHTOOL_GDRVINFO) - else { - struct ethtool_drvinfo info; - const struct ethtool_ops *ops = - dev->ethtool_ops; - int k = 0; - - if (ops->get_drvinfo) { - memset(&info, 0, sizeof(info)); - info.cmd = ETHTOOL_GDRVINFO; - ops->get_drvinfo(dev, &info); - for (; bp_desc_array[k]; k++) - if (! - (strcmp - (bp_desc_array[k], - info.driver))) - goto send_cmd; - - } - - } -#endif - return -1; - } - } - send_cmd: - ret = do_cmd(dev, &ifr, IS_BYPASS, &data); - return (ret < 0 ? -1 : ret); -} - -int is_bypass(int if_index) -{ - int ret = 0; - SET_BPLIB_INT_FN(is_bypass, int, if_index, ret); - - if (ret < 0) - return is_bypass_dev(if_index); - return ret; -} - -int get_bypass_slave(int if_index) -{ - DO_BPLIB_GET_ARG_FN(get_bypass_slave, GET_BYPASS_SLAVE, if_index); -} - -int get_bypass_caps(int if_index) -{ - DO_BPLIB_GET_ARG_FN(get_bypass_caps, GET_BYPASS_CAPS, if_index); -} - -int get_wd_set_caps(int if_index) -{ - DO_BPLIB_GET_ARG_FN(get_wd_set_caps, GET_WD_SET_CAPS, if_index); -} - -int set_bypass(int if_index, int bypass_mode) -{ - DO_BPLIB_SET_ARG_FN(set_bypass, SET_BYPASS, if_index, bypass_mode); -} - -int get_bypass(int if_index) -{ - DO_BPLIB_GET_ARG_FN(get_bypass, GET_BYPASS, if_index); -} - -int get_bypass_change(int if_index) -{ - DO_BPLIB_GET_ARG_FN(get_bypass_change, GET_BYPASS_CHANGE, if_index); -} - -int set_dis_bypass(int if_index, int dis_bypass) -{ - DO_BPLIB_SET_ARG_FN(set_dis_bypass, SET_DIS_BYPASS, if_index, - dis_bypass); -} - -int get_dis_bypass(int if_index) -{ - DO_BPLIB_GET_ARG_FN(get_dis_bypass, GET_DIS_BYPASS, if_index); -} - -int set_bypass_pwoff(int if_index, int bypass_mode) -{ - DO_BPLIB_SET_ARG_FN(set_bypass_pwoff, SET_BYPASS_PWOFF, if_index, - bypass_mode); -} - -int get_bypass_pwoff(int if_index) -{ - DO_BPLIB_GET_ARG_FN(get_bypass_pwoff, GET_BYPASS_PWOFF, if_index); -} - -int set_bypass_pwup(int if_index, int bypass_mode) -{ - DO_BPLIB_SET_ARG_FN(set_bypass_pwup, SET_BYPASS_PWUP, if_index, - bypass_mode); -} - -int get_bypass_pwup(int if_index) -{ - DO_BPLIB_GET_ARG_FN(get_bypass_pwup, GET_BYPASS_PWUP, if_index); -} - -int set_bypass_wd(int if_index, int ms_timeout, int *ms_timeout_set) -{ - int data = ms_timeout, ret = 0; - if (is_dev_sd(if_index)) - SET_BPLIB_INT_FN3(set_bypass_wd, int, if_index, int, ms_timeout, - int *, ms_timeout_set, ret); - else { - ret = doit(SET_BYPASS_WD, if_index, &data); - if (ret > 0) { - *ms_timeout_set = ret; - ret = 0; - } - } - return ret; -} - -int get_bypass_wd(int if_index, int *ms_timeout_set) -{ - int *data = ms_timeout_set, ret = 0; - if (is_dev_sd(if_index)) - SET_BPLIB_INT_FN2(get_bypass_wd, int, if_index, int *, - ms_timeout_set, ret); - else - ret = doit(GET_BYPASS_WD, if_index, data); - return ret; -} - -int get_wd_expire_time(int if_index, int *ms_time_left) -{ - int *data = ms_time_left, ret = 0; - if (is_dev_sd(if_index)) - SET_BPLIB_INT_FN2(get_wd_expire_time, int, if_index, int *, - ms_time_left, ret); - else { - ret = doit(GET_WD_EXPIRE_TIME, if_index, data); - if ((ret == 0) && (*data != 0)) - ret = 1; - } - return ret; -} - -int reset_bypass_wd_timer(int if_index) -{ - DO_BPLIB_GET_ARG_FN(reset_bypass_wd_timer, RESET_BYPASS_WD_TIMER, - if_index); -} - -int set_std_nic(int if_index, int bypass_mode) -{ - DO_BPLIB_SET_ARG_FN(set_std_nic, SET_STD_NIC, if_index, bypass_mode); -} - -int get_std_nic(int if_index) -{ - DO_BPLIB_GET_ARG_FN(get_std_nic, GET_STD_NIC, if_index); -} - -int set_tx(int if_index, int tx_state) -{ - DO_BPLIB_SET_ARG_FN(set_tx, SET_TX, if_index, tx_state); -} - -int get_tx(int if_index) -{ - DO_BPLIB_GET_ARG_FN(get_tx, GET_TX, if_index); -} - -int set_tap(int if_index, int tap_mode) -{ - DO_BPLIB_SET_ARG_FN(set_tap, SET_TAP, if_index, tap_mode); -} - -int get_tap(int if_index) -{ - DO_BPLIB_GET_ARG_FN(get_tap, GET_TAP, if_index); -} - -int get_tap_change(int if_index) -{ - DO_BPLIB_GET_ARG_FN(get_tap_change, GET_TAP_CHANGE, if_index); -} - -int set_dis_tap(int if_index, int dis_tap) -{ - DO_BPLIB_SET_ARG_FN(set_dis_tap, SET_DIS_TAP, if_index, dis_tap); -} - -int get_dis_tap(int if_index) -{ - DO_BPLIB_GET_ARG_FN(get_dis_tap, GET_DIS_TAP, if_index); -} - -int set_tap_pwup(int if_index, int tap_mode) -{ - DO_BPLIB_SET_ARG_FN(set_tap_pwup, SET_TAP_PWUP, if_index, tap_mode); -} - -int get_tap_pwup(int if_index) -{ - DO_BPLIB_GET_ARG_FN(get_tap_pwup, GET_TAP_PWUP, if_index); -} - -int set_bp_disc(int if_index, int disc_mode) -{ - DO_BPLIB_SET_ARG_FN(set_bp_disc, SET_DISC, if_index, disc_mode); -} - -int get_bp_disc(int if_index) -{ - DO_BPLIB_GET_ARG_FN(get_bp_disc, GET_DISC, if_index); -} - -int get_bp_disc_change(int if_index) -{ - DO_BPLIB_GET_ARG_FN(get_bp_disc_change, GET_DISC_CHANGE, if_index); -} - -int set_bp_dis_disc(int if_index, int dis_disc) -{ - DO_BPLIB_SET_ARG_FN(set_bp_dis_disc, SET_DIS_DISC, if_index, dis_disc); -} - -int get_bp_dis_disc(int if_index) -{ - DO_BPLIB_GET_ARG_FN(get_bp_dis_disc, GET_DIS_DISC, if_index); -} - -int set_bp_disc_pwup(int if_index, int disc_mode) -{ - DO_BPLIB_SET_ARG_FN(set_bp_disc_pwup, SET_DISC_PWUP, if_index, - disc_mode); -} - -int get_bp_disc_pwup(int if_index) -{ - DO_BPLIB_GET_ARG_FN(get_bp_disc_pwup, GET_DISC_PWUP, if_index); -} - -int set_wd_exp_mode(int if_index, int mode) -{ - DO_BPLIB_SET_ARG_FN(set_wd_exp_mode, SET_WD_EXP_MODE, if_index, mode); -} - -int get_wd_exp_mode(int if_index) -{ - DO_BPLIB_GET_ARG_FN(get_wd_exp_mode, GET_WD_EXP_MODE, if_index); -} - -int set_wd_autoreset(int if_index, int time) -{ - DO_BPLIB_SET_ARG_FN(set_wd_autoreset, SET_WD_AUTORESET, if_index, time); -} - -int get_wd_autoreset(int if_index) -{ - DO_BPLIB_GET_ARG_FN(get_wd_autoreset, GET_WD_AUTORESET, if_index); -} - -int set_tpl(int if_index, int tpl_mode) -{ - DO_BPLIB_SET_ARG_FN(set_tpl, SET_TPL, if_index, tpl_mode); -} - -int get_tpl(int if_index) -{ - DO_BPLIB_GET_ARG_FN(get_tpl, GET_TPL, if_index); -} - -int set_bp_hw_reset(int if_index, int mode) -{ - DO_BPLIB_SET_ARG_FN(set_tpl, SET_BP_HW_RESET, if_index, mode); -} - -int get_bp_hw_reset(int if_index) -{ - DO_BPLIB_GET_ARG_FN(get_tpl, GET_BP_HW_RESET, if_index); -} - -int get_bypass_info(int if_index, struct bp_info *bp_info) -{ - int ret = 0; - if (is_dev_sd(if_index)) { - SET_BPLIB_INT_FN2(get_bypass_info, int, if_index, - struct bp_info *, bp_info, ret); - } else { - static int (*ioctl) (struct net_device *, struct ifreq *, int); - struct net_device *dev; - - struct net_device *n; - for_each_netdev_safe(&init_net, dev, n) { - if (dev->ifindex == if_index) { - struct if_bypass_info *bypass_cb; - struct ifreq ifr; - - memset(&ifr, 0, sizeof(ifr)); - bypass_cb = (struct if_bypass_info *)𝔦 - bypass_cb->cmd = GET_BYPASS_INFO; - - if ((dev->netdev_ops) && - (ioctl = dev->netdev_ops->ndo_do_ioctl)) { - ret = ioctl(dev, &ifr, SIOCGIFBYPASS); - } - - else - ret = -1; - if (ret == 0) - memcpy(bp_info, &bypass_cb->bp_info, - sizeof(struct bp_info)); - ret = (ret < 0 ? -1 : 0); - break; - } - } - } - return ret; -} - -int init_lib_module() -{ - - printk(VERSION); - return 0; -} - -void cleanup_lib_module() -{ -} - -EXPORT_SYMBOL_NOVERS(is_bypass); -EXPORT_SYMBOL_NOVERS(get_bypass_slave); -EXPORT_SYMBOL_NOVERS(get_bypass_caps); -EXPORT_SYMBOL_NOVERS(get_wd_set_caps); -EXPORT_SYMBOL_NOVERS(set_bypass); -EXPORT_SYMBOL_NOVERS(get_bypass); -EXPORT_SYMBOL_NOVERS(get_bypass_change); -EXPORT_SYMBOL_NOVERS(set_dis_bypass); -EXPORT_SYMBOL_NOVERS(get_dis_bypass); -EXPORT_SYMBOL_NOVERS(set_bypass_pwoff); -EXPORT_SYMBOL_NOVERS(get_bypass_pwoff); -EXPORT_SYMBOL_NOVERS(set_bypass_pwup); -EXPORT_SYMBOL_NOVERS(get_bypass_pwup); -EXPORT_SYMBOL_NOVERS(set_bypass_wd); -EXPORT_SYMBOL_NOVERS(get_bypass_wd); -EXPORT_SYMBOL_NOVERS(get_wd_expire_time); -EXPORT_SYMBOL_NOVERS(reset_bypass_wd_timer); -EXPORT_SYMBOL_NOVERS(set_std_nic); -EXPORT_SYMBOL_NOVERS(get_std_nic); -EXPORT_SYMBOL_NOVERS(set_tx); -EXPORT_SYMBOL_NOVERS(get_tx); -EXPORT_SYMBOL_NOVERS(set_tap); -EXPORT_SYMBOL_NOVERS(get_tap); -EXPORT_SYMBOL_NOVERS(get_tap_change); -EXPORT_SYMBOL_NOVERS(set_dis_tap); -EXPORT_SYMBOL_NOVERS(get_dis_tap); -EXPORT_SYMBOL_NOVERS(set_tap_pwup); -EXPORT_SYMBOL_NOVERS(get_tap_pwup); -EXPORT_SYMBOL_NOVERS(set_bp_disc); -EXPORT_SYMBOL_NOVERS(get_bp_disc); -EXPORT_SYMBOL_NOVERS(get_bp_disc_change); -EXPORT_SYMBOL_NOVERS(set_bp_dis_disc); -EXPORT_SYMBOL_NOVERS(get_bp_dis_disc); -EXPORT_SYMBOL_NOVERS(set_bp_disc_pwup); -EXPORT_SYMBOL_NOVERS(get_bp_disc_pwup); -EXPORT_SYMBOL_NOVERS(set_wd_exp_mode); -EXPORT_SYMBOL_NOVERS(get_wd_exp_mode); -EXPORT_SYMBOL_NOVERS(set_wd_autoreset); -EXPORT_SYMBOL_NOVERS(get_wd_autoreset); -EXPORT_SYMBOL_NOVERS(set_tpl); -EXPORT_SYMBOL_NOVERS(get_tpl); -EXPORT_SYMBOL_NOVERS(set_bp_hw_reset); -EXPORT_SYMBOL_NOVERS(get_bp_hw_reset); -EXPORT_SYMBOL_NOVERS(get_bypass_info); - -module_init(init_lib_module); -module_exit(cleanup_lib_module); diff --git a/trunk/drivers/staging/silicom/bypasslib/libbp_sd.h b/trunk/drivers/staging/silicom/bypasslib/libbp_sd.h deleted file mode 100644 index 3b4f8364ed18..000000000000 --- a/trunk/drivers/staging/silicom/bypasslib/libbp_sd.h +++ /dev/null @@ -1,509 +0,0 @@ -/******************************************************************************/ -/* */ -/* bypass library, Copyright (c) 2004 Silicom, Ltd */ -/* 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, located in the file LICENSE. */ -/* */ -/* Ver 1.0.0 */ -/* */ -/* libbypass.h */ -/* */ -/******************************************************************************/ - -/** - * is_bypass - check if device is a Bypass controlling device - * @if_index: network device index - * - * Output: - * 1 - if device is bypass controlling device, - * 0 - if device is bypass slave device - * -1 - device not support Bypass - **/ -int is_bypass_sd(int if_index); - -/** - * get_bypass_slave - get second port participate in the Bypass pair - * @if_index: network device index - * - * Output: - * network device index of the slave device - * -1 - on failure (device not support Bypass or it's a slave device) - **/ -int get_bypass_slave_sd(int if_index); - -/** - * get_bypass_caps - get second port participate in the Bypass pair - * @if_index: network device index - * - * Output: - * flags word on success;flag word is a 32-bit mask word with each bit defines different - * capability as described bellow. - * Value of 1 for supporting this feature. 0 for not supporting this feature. - * -1 - on failure (if the device is not capable of the operation or not a Bypass device) - * Bit feature description - * - * 0 BP_CAP The interface is Bypass capable in general - * - * 1 BP_STATUS_CAP The interface can report of the current Bypass mode - * - * 2 BP_STATUS_CHANGE_CAP The interface can report on a change to bypass mode from - * the last time the mode was defined - * - * 3 SW_CTL_CAP The interface is Software controlled capable for bypass/non bypass modes. - * - * 4 BP_DIS_CAP The interface is capable of disabling the Bypass mode at all times. - * This mode will retain its mode even during power loss and also after - * power recovery. This will overcome on any bypass operation due to - * watchdog timeout or set bypass command. - * - * 5 BP_DIS_STATUS_CAP The interface can report of the current DIS_BP_CAP - * - * 6 STD_NIC_CAP The interface is capable to be configured to operate as standard, non Bypass, - * NIC interface (have direct connection to interfaces at all power modes) - * - * 7 BP_PWOFF_NO_CAP The interface can be in Bypass mode at power off state - * - * 8 BP_PWOFF_OFF_CAP The interface can disconnect the Bypass mode at power off state without - * effecting all the other states of operation - * - * 9 BP_PWOFF_CTL_CAP The behavior of the Bypass mode at Power-off state can be controlled by - * software without effecting any other state - * - *10 BP_PWUP_ON_CAP The interface can be in Bypass mode when power is turned on - * (until the system take control of the bypass functionality) - * - *11 BP_PWUP_OFF_CAP The interface can disconnect from Bypass mode when power is turned on - * (until the system take control of the bypass functionality) - * - *12 BP_PWUP_CTL_CAP The behavior of the Bypass mode at Power-up can be controlled by software - * - *13 WD_CTL_CAP The interface has watchdog capabilities to turn to Bypass mode when not reset - * for defined period of time. - * - *14 WD_STATUS_CAP The interface can report on the watchdog status (Active/inactive) - * - *15 WD_TIMEOUT_CAP The interface can report the time left till watchdog triggers to Bypass mode. - * - *16-31 RESERVED - * - * **/ -int get_bypass_caps_sd(int if_index); - -/** - * get_wd_set_caps - Obtain watchdog timer setting capabilities - * @if_index: network device index - * - * Output: - * - * Set of numbers defining the various parameters of the watchdog capable - * to be set to as described bellow. - * -1 - on failure (device not support Bypass or it's a slave device) - * - * Bit feature description - * - * 0-3 WD_MIN_TIME The interface WD minimal time period in 100mS units - * - * 4 WD_STEP_TIME The steps of the WD timer in - * 0 - for linear steps (WD_MIN_TIME * X) - * 1 - for multiply by 2 from previous step (WD_MIN_TIME * 2^X) - * - * 5-8 WD_STEP_COUNT Number of steps the WD timer supports in 2^X - * (X bit available for defining the value) - * - * - * - **/ -int get_wd_set_caps_sd(int if_index); - -/** - * set_bypass - set Bypass state - * @if_index: network device index of the controlling device - * @bypass_mode: bypass mode (1=on, 0=off) - * Output: - * 0 - on success - * -1 - on failure (device not support Bypass or it's a slave device) - **/ -int set_bypass_sd(int if_index, int bypass_mode); - -/** - * get_bypass - Get Bypass mode state - * @if_index: network device index of the controlling device - * Output: - * 0/1 - (off/on) on success - * -1 - on failure (device not support Bypass or it's a slave device) - **/ -int get_bypass_sd(int if_index); - -/** - * get_bypass_change - Get change of Bypass mode state from last status check - * @if_index: network device index of the controlling device - * Output: - * 0/1 - (off/on) on success - * -1 - on failure (device not support Bypass or it's a slave device) - **/ -int get_bypass_change_sd(int if_index); - -/** - * set_dis_bypass - Set Disable Bypass mode - * @if_index: network device index of the controlling device - * @dis_bypass: disable bypass(1=dis, 0=en) - * Output: - * 0 - on success - * -1 - on failure (device is not capable of the operation ordevice not support Bypass - * or it's a slave device) - **/ -int set_dis_bypass_sd(int if_index, int dis_bypass); - -/** - * get_dis_bypass - Get Disable Bypass mode state - * @if_index: network device index of the controlling device - * Output: - * 0/1 - on success (normal Bypass mode/ Disable bypass) - * -1 - on failure (device is not capable of the operation ordevice not support Bypass - * or it's a slave device) - **/ -int get_dis_bypass_sd(int if_index); - -/** - * set_bypass_pwoff - Set Bypass mode at power-off state - * @if_index: network device index of the controlling device - * @bypass_mode: bypass mode setting at power off state (1=BP en, 0=BP Dis) - * Output: - * 0 - on success - * -1 - on failure (device is not capable of the operation ordevice not support Bypass - * or it's a slave device) - **/ -int set_bypass_pwoff_sd(int if_index, int bypass_mode); - -/** - * get_bypass_pwoff - Get Bypass mode state at power-off state - * @if_index: network device index of the controlling device - * Output: - * 0/1 - on success (Disable bypass at power off state / normal Bypass mode) - * -1 - on failure (device is not capable of the operation ordevice not support Bypass - * or it's a slave device) - **/ -int get_bypass_pwoff_sd(int if_index); - -/** - * set_bypass_pwup - Set Bypass mode at power-up state - * @if_index: network device index of the controlling device - * @bypass_mode: bypass mode setting at power up state (1=BP en, 0=BP Dis) - * Output: - * 0 - on success - * -1 - on failure (device is not capable of the operation ordevice not support Bypass - * or it's a slave device) - **/ -int set_bypass_pwup_sd(int if_index, int bypass_mode); - -/** - * get_bypass_pwup - Get Bypass mode state at power-up state - * @if_index: network device index of the controlling device - * Output: - * 0/1 - on success (Disable bypass at power up state / normal Bypass mode) - * -1 - on failure (device is not capable of the operation ordevice not support Bypass - * or it's a slave device) - **/ -int get_bypass_pwup_sd(int if_index); - -/** - * set_bypass_wd - Set watchdog state - * @if_index: network device index of the controlling device - * @ms_timeout: requested timeout (in ms units), 0 for disabling the watchdog timer - * @ms_timeout_set(output): requested timeout (in ms units), - * that the adapter supports and will be used by the watchdog - * Output: - * 0 - on success - * -1 - on failure (device is not capable of the operation ordevice not support Bypass - * or it's a slave device) - **/ -int set_bypass_wd_sd(int if_index, int ms_timeout, int *ms_timeout_set); - -/** - * get_bypass_wd - Get watchdog state - * @if_index: network device index of the controlling device - * @ms_timeout (output): WDT timeout (in ms units), - * -1 for unknown wdt status - * 0 if WDT is disabled - * Output: - * 0 - on success - * -1 - on failure (device is not capable of the operation ordevice not support Bypass - * or it's a slave device) - **/ -int get_bypass_wd_sd(int if_index, int *ms_timeout_set); - -/** - * get_wd_expire_time - Get watchdog expire - * @if_index: network device index of the controlling device - * @ms_time_left (output): time left till watchdog time expire, - * -1 if WDT has expired - * 0 if WDT is disabled - * Output: - * 0 - on success - * -1 - on failure (device is not capable of the operation ordevice not support Bypass - * or it's a slave device or unknown wdt status) - **/ -int get_wd_expire_time_sd(int if_index, int *ms_time_left); - -/** - * reset_bypass_wd_timer - Reset watchdog timer - * @if_index: network device index of the controlling device - * - * Output: - * 1 - on success - * 0 - watchdog is not configured - * -1 - on failure (device is not capable of the operation ordevice not support Bypass - * or it's a slave device or unknown wdt status) - **/ -int reset_bypass_wd_timer_sd(int if_index); - -/** - * set_std_nic - Standard NIC mode of operation - * @if_index: network device index of the controlling device - * @nic_mode: 0/1 (Default Bypass mode / Standard NIC mode) - * - * Output: - * 0 - on success - * -1 - on failure (device is not capable of the operation ordevice not support Bypass - * or it's a slave device) - **/ -int set_std_nic_sd(int if_index, int nic_mode); - -/** - * get_std_nic - Get Standard NIC mode setting - * @if_index: network device index of the controlling device - * - * Output: - * 0/1 (Default Bypass mode / Standard NIC mode) on success - * -1 - on failure (device is not capable of the operation ordevice not support Bypass - * or it's a slave device) - **/ -int get_std_nic_sd(int if_index); - -/** - * set_tx - set transmitter enable/disable - * @if_index: network device index of the controlling device - * @tx_state: 0/1 (Transmit Disable / Transmit Enable) - * - * Output: - * 0 - on success - * -1 - on failure (device is not capable of the operation ) - **/ -int set_tx_sd(int if_index, int tx_state); - -/** - * get_std_nic - get transmitter state (disable / enable) - * @if_index: network device index of the controlling device - * - * Output: - * 0/1 (ransmit Disable / Transmit Enable) on success - * -1 - on failure (device is not capable of the operation ordevice not support Bypass) - **/ -int get_tx_sd(int if_index); - -/** - * set_tap - set TAP state - * @if_index: network device index of the controlling device - * @tap_mode: 1 tap mode , 0 normal nic mode - * Output: - * 0 - on success - * -1 - on failure (device not support TAP or it's a slave device) - **/ -int set_tap_sd(int if_index, int tap_mode); - -/** - * get_tap - Get TAP mode state - * @if_index: network device index of the controlling device - * Output: - * 0/1 - (off/on) on success - * -1 - on failure (device not support TAP or it's a slave device) - **/ -int get_tap_sd(int if_index); - -/** - * get_tap_change - Get change of TAP mode state from last status check - * @if_index: network device index of the controlling device - * Output: - * 0/1 - (off/on) on success - * -1 - on failure (device not support TAP or it's a slave device) - **/ -int get_tap_change_sd(int if_index); - -/** - * set_dis_tap - Set Disable TAP mode - * @if_index: network device index of the controlling device - * @dis_tap: disable tap(1=dis, 0=en) - * Output: - * 0 - on success - * -1 - on failure (device is not capable of the operation ordevice not support TAP - * or it's a slave device) - **/ -int set_dis_tap_sd(int if_index, int dis_tap); - -/** - * get_dis_tap - Get Disable TAP mode state - * @if_index: network device index of the controlling device - * Output: - * 0/1 - on success (normal TAP mode/ Disable TAP) - * -1 - on failure (device is not capable of the operation ordevice not support TAP - * or it's a slave device) - **/ -int get_dis_tap_sd(int if_index); - -/** - * set_tap_pwup - Set TAP mode at power-up state - * @if_index: network device index of the controlling device - * @bypass_mode: tap mode setting at power up state (1=TAP en, 0=TAP Dis) - * Output: - * 0 - on success - * -1 - on failure (device is not capable of the operation ordevice not support TAP - * or it's a slave device) - **/ -int set_tap_pwup_sd(int if_index, int tap_mode); - -/** - * get_tap_pwup - Get TAP mode state at power-up state - * @if_index: network device index of the controlling device - * Output: - * 0/1 - on success (Disable TAP at power up state / normal TAP mode) - * -1 - on failure (device is not capable of the operation ordevice not support TAP - * or it's a slave device) - **/ -int get_tap_pwup_sd(int if_index); - -/** - * set_bp_disc - set Disconnect state - * @if_index: network device index of the controlling device - * @tap_mode: 1 disc mode , 0 non-disc mode - * Output: - * 0 - on success - * -1 - on failure (device not support Disconnect or it's a slave device) - **/ -int set_bp_disc_sd(int if_index, int disc_mode); - -/** - * get_bp_disc - Get Disconnect mode state - * @if_index: network device index of the controlling device - * Output: - * 0/1 - (off/on) on success - * -1 - on failure (device not support Disconnect or it's a slave device) - **/ -int get_bp_disc_sd(int if_index); - -/** - * get_bp_disc_change - Get change of Disconnect mode state from last status check - * @if_index: network device index of the controlling device - * Output: - * 0/1 - (off/on) on success - * -1 - on failure (device not support Disconnect or it's a slave device) - **/ -int get_bp_disc_change_sd(int if_index); - -/** - * set_bp_dis_disc - Set Disable Disconnect mode - * @if_index: network device index of the controlling device - * @dis_tap: disable tap(1=dis, 0=en) - * Output: - * 0 - on success - * -1 - on failure (device is not capable ofthe operation ordevice not support Disconnect - * or it's a slave device) - **/ -int set_bp_dis_disc_sd(int if_index, int dis_disc); - -/** - * get_dis_tap - Get Disable Disconnect mode state - * @if_index: network device index of the controlling device - * Output: - * 0/1 - on success (normal Disconnect mode/ Disable Disconnect) - * -1 - on failure (device is not capable of the operation ordevice not support Disconnect - * or it's a slave device) - **/ -int get_bp_dis_disc_sd(int if_index); - -/** - * set_bp_disc_pwup - Set Disconnect mode at power-up state - * @if_index: network device index of the controlling device - * @disc_mode: tap mode setting at power up state (1=Disc en, 0=Disc Dis) - * Output: - * 0 - on success - * -1 - on failure (device is not capable of the operation ordevice not support Disconnect - * or it's a slave device) - **/ -int set_bp_disc_pwup_sd(int if_index, int disc_mode); - -/** - * get_bp_disc_pwup - Get Disconnect mode state at power-up state - * @if_index: network device index of the controlling device - * Output: - * 0/1 - on success (Disable Disconnect at power up state / normal Disconnect mode) - * -1 - on failure (device is not capable of the operation ordevice not support TAP - * or it's a slave device) - **/ -int get_bp_disc_pwup_sd(int if_index); - -/** - * set_wd_exp_mode - Set adapter state when WDT expired. - * @if_index: network device index of the controlling device - * @bypass_mode: adapter mode (1=tap mode, 0=bypass mode) - * Output: - * 0 - on success - * -1 - on failure (device not support Bypass or it's a slave device) - **/ -int set_wd_exp_mode_sd(int if_index, int bypass_mode); - -/** - * get_wd_exp_mode - Get adapter state when WDT expired. - * @if_index: network device index of the controlling device - * Output: - * 0/1 - (bypass/tap) on success - * -1 - on failure (device not support Bypass or it's a slave device) - **/ -int get_wd_exp_mode_sd(int if_index); - -/** - * set_wd_autoreset - reset WDT periodically. - * @if_index: network device index of the controlling device - * @bypass_mode: adapter mode (1=tap mode, 0=bypass mode) - * Output: - * 1 - on success - * -1 - on failure (device is not capable of the operation ordevice not support Bypass - * or it's a slave device or unknown wdt status) - **/ -int set_wd_autoreset_sd(int if_index, int time); - -/** - * set_wd_autoreset - reset WDT periodically. - * @if_index: network device index of the controlling device - * @bypass_mode: adapter mode (1=tap mode, 0=bypass mode) - * Output: - * 1 - on success - * -1 - on failure (device is not capable of the operation ordevice not support Bypass - * or it's a slave device or unknown wdt status) - **/ -int get_wd_autoreset_sd(int if_index); - -/** - * set_tpl - set TPL state - * @if_index: network device index of the controlling device - * @tpl_mode: 1 tpl mode , 0 normal nic mode - * Output: - * 0 - on success - * -1 - on failure (device not support TPL) - **/ -int set_tpl_sd(int if_index, int tpl_mode); - -/** - * get_tpl - Get TPL mode state - * @if_index: network device index of the controlling device - * Output: - * 0/1 - (off/on) on success - * -1 - on failure (device not support TPL or it's a slave device) - **/ -int get_tpl_sd(int if_index); - -int get_bypass_info_sd(int if_index, struct bp_info *bp_info); -int bp_if_scan_sd(void); -/*int get_dev_num_sd(void);*/ diff --git a/trunk/drivers/staging/silicom/libbp_sd.h b/trunk/drivers/staging/silicom/libbp_sd.h deleted file mode 100644 index 065277f81c78..000000000000 --- a/trunk/drivers/staging/silicom/libbp_sd.h +++ /dev/null @@ -1,550 +0,0 @@ -/******************************************************************************/ -/* */ -/* bypass library, Copyright (c) 2004 Silicom, Ltd */ -/* 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, located in the file LICENSE. */ -/* */ -/* Ver 1.0.0 */ -/* */ -/* libbypass.h */ -/* */ -/******************************************************************************/ - -#define BP_CAP 0x01 /* BIT_0 */ -#define BP_STATUS_CAP 0x02 -#define BP_STATUS_CHANGE_CAP 0x04 -#define SW_CTL_CAP 0x08 -#define BP_DIS_CAP 0x10 -#define BP_DIS_STATUS_CAP 0x20 -#define STD_NIC_CAP 0x40 -#define BP_PWOFF_ON_CAP 0x80 -#define BP_PWOFF_OFF_CAP 0x0100 -#define BP_PWOFF_CTL_CAP 0x0200 -#define BP_PWUP_ON_CAP 0x0400 -#define BP_PWUP_OFF_CAP 0x0800 -#define BP_PWUP_CTL_CAP 0x1000 -#define WD_CTL_CAP 0x2000 -#define WD_STATUS_CAP 0x4000 -#define WD_TIMEOUT_CAP 0x8000 -#define TX_CTL_CAP 0x10000 -#define TX_STATUS_CAP 0x20000 -#define TAP_CAP 0x40000 -#define TAP_STATUS_CAP 0x80000 -#define TAP_STATUS_CHANGE_CAP 0x100000 -#define TAP_DIS_CAP 0x200000 -#define TAP_DIS_STATUS_CAP 0x400000 -#define TAP_PWUP_ON_CAP 0x800000 -#define TAP_PWUP_OFF_CAP 0x1000000 -#define TAP_PWUP_CTL_CAP 0x2000000 -#define NIC_CAP_NEG 0x4000000 /* BIT 26 */ - -#define WD_MIN_TIME_GET(desc) (desc & 0xf) -#define WDT_STEP_TIME 0x10 - -struct bp_info { - char prod_name[14]; - unsigned char fw_ver; -}; - -/** - * is_bypass - check if device is a Bypass controlling device - * @if_index: network device index - * - * Output: - * 1 - if device is bypass controlling device, - * 0 - if device is bypass slave device - * -1 - device not support Bypass - **/ -int is_bypass_sd(int if_index); - -/** - * get_bypass_slave - get second port participate in the Bypass pair - * @if_index: network device index - * - * Output: - * network device index of the slave device - * -1 - on failure (device not support Bypass or it's a slave device) - **/ -int get_bypass_slave_sd(int if_index); - -/** - * get_bypass_caps - get second port participate in the Bypass pair - * @if_index: network device index - * - * Output: - * flags word on success;flag word is a 32-bit mask word with each bit defines different - * capability as described bellow. - * Value of 1 for supporting this feature. 0 for not supporting this feature. - * -1 - on failure (if the device is not capable of the operation or not a Bypass device) - * Bit feature description - * - * 0 BP_CAP The interface is Bypass capable in general - * - * 1 BP_STATUS_CAP The interface can report of the current Bypass mode - * - * 2 BP_STATUS_CHANGE_CAP The interface can report on a change to bypass mode from - * the last time the mode was defined - * - * 3 SW_CTL_CAP The interface is Software controlled capable for bypass/non bypass modes. - * - * 4 BP_DIS_CAP The interface is capable of disabling the Bypass mode at all times. - * This mode will retain its mode even during power loss and also after - * power recovery. This will overcome on any bypass operation due to - * watchdog timeout or set bypass command. - * - * 5 BP_DIS_STATUS_CAP The interface can report of the current DIS_BP_CAP - * - * 6 STD_NIC_CAP The interface is capable to be configured to operate as standard, non Bypass, - * NIC interface (have direct connection to interfaces at all power modes) - * - * 7 BP_PWOFF_NO_CAP The interface can be in Bypass mode at power off state - * - * 8 BP_PWOFF_OFF_CAP The interface can disconnect the Bypass mode at power off state without - * effecting all the other states of operation - * - * 9 BP_PWOFF_CTL_CAP The behavior of the Bypass mode at Power-off state can be controlled by - * software without effecting any other state - * - *10 BP_PWUP_ON_CAP The interface can be in Bypass mode when power is turned on - * (until the system take control of the bypass functionality) - * - *11 BP_PWUP_OFF_CAP The interface can disconnect from Bypass mode when power is turned on - * (until the system take control of the bypass functionality) - * - *12 BP_PWUP_CTL_CAP The behavior of the Bypass mode at Power-up can be controlled by software - * - *13 WD_CTL_CAP The interface has watchdog capabilities to turn to Bypass mode when not reset - * for defined period of time. - * - *14 WD_STATUS_CAP The interface can report on the watchdog status (Active/inactive) - * - *15 WD_TIMEOUT_CAP The interface can report the time left till watchdog triggers to Bypass mode. - * - *16-31 RESERVED - * - * **/ -int get_bypass_caps_sd(int if_index); - -/** - * get_wd_set_caps - Obtain watchdog timer setting capabilities - * @if_index: network device index - * - * Output: - * - * Set of numbers defining the various parameters of the watchdog capable - * to be set to as described bellow. - * -1 - on failure (device not support Bypass or it's a slave device) - * - * Bit feature description - * - * 0-3 WD_MIN_TIME The interface WD minimal time period in 100mS units - * - * 4 WD_STEP_TIME The steps of the WD timer in - * 0 - for linear steps (WD_MIN_TIME * X) - * 1 - for multiply by 2 from previous step (WD_MIN_TIME * 2^X) - * - * 5-8 WD_STEP_COUNT Number of steps the WD timer supports in 2^X - * (X bit available for defining the value) - * - * - * - **/ -int get_wd_set_caps_sd(int if_index); - -/** - * set_bypass - set Bypass state - * @if_index: network device index of the controlling device - * @bypass_mode: bypass mode (1=on, 0=off) - * Output: - * 0 - on success - * -1 - on failure (device not support Bypass or it's a slave device) - **/ -int set_bypass_sd(int if_index, int bypass_mode); - -/** - * get_bypass - Get Bypass mode state - * @if_index: network device index of the controlling device - * Output: - * 0/1 - (off/on) on success - * -1 - on failure (device not support Bypass or it's a slave device) - **/ -int get_bypass_sd(int if_index); - -/** - * get_bypass_change - Get change of Bypass mode state from last status check - * @if_index: network device index of the controlling device - * Output: - * 0/1 - (off/on) on success - * -1 - on failure (device not support Bypass or it's a slave device) - **/ -int get_bypass_change_sd(int if_index); - -/** - * set_dis_bypass - Set Disable Bypass mode - * @if_index: network device index of the controlling device - * @dis_bypass: disable bypass(1=dis, 0=en) - * Output: - * 0 - on success - * -1 - on failure (device is not capable of the operation ordevice not support Bypass - * or it's a slave device) - **/ -int set_dis_bypass_sd(int if_index, int dis_bypass); - -/** - * get_dis_bypass - Get Disable Bypass mode state - * @if_index: network device index of the controlling device - * Output: - * 0/1 - on success (normal Bypass mode/ Disable bypass) - * -1 - on failure (device is not capable of the operation ordevice not support Bypass - * or it's a slave device) - **/ -int get_dis_bypass_sd(int if_index); - -/** - * set_bypass_pwoff - Set Bypass mode at power-off state - * @if_index: network device index of the controlling device - * @bypass_mode: bypass mode setting at power off state (1=BP en, 0=BP Dis) - * Output: - * 0 - on success - * -1 - on failure (device is not capable of the operation ordevice not support Bypass - * or it's a slave device) - **/ -int set_bypass_pwoff_sd(int if_index, int bypass_mode); - -/** - * get_bypass_pwoff - Get Bypass mode state at power-off state - * @if_index: network device index of the controlling device - * Output: - * 0/1 - on success (Disable bypass at power off state / normal Bypass mode) - * -1 - on failure (device is not capable of the operation ordevice not support Bypass - * or it's a slave device) - **/ -int get_bypass_pwoff_sd(int if_index); - -/** - * set_bypass_pwup - Set Bypass mode at power-up state - * @if_index: network device index of the controlling device - * @bypass_mode: bypass mode setting at power up state (1=BP en, 0=BP Dis) - * Output: - * 0 - on success - * -1 - on failure (device is not capable of the operation ordevice not support Bypass - * or it's a slave device) - **/ -int set_bypass_pwup_sd(int if_index, int bypass_mode); - -/** - * get_bypass_pwup - Get Bypass mode state at power-up state - * @if_index: network device index of the controlling device - * Output: - * 0/1 - on success (Disable bypass at power up state / normal Bypass mode) - * -1 - on failure (device is not capable of the operation ordevice not support Bypass - * or it's a slave device) - **/ -int get_bypass_pwup_sd(int if_index); - -/** - * set_bypass_wd - Set watchdog state - * @if_index: network device index of the controlling device - * @ms_timeout: requested timeout (in ms units), 0 for disabling the watchdog timer - * @ms_timeout_set(output): requested timeout (in ms units), - * that the adapter supports and will be used by the watchdog - * Output: - * 0 - on success - * -1 - on failure (device is not capable of the operation ordevice not support Bypass - * or it's a slave device) - **/ -int set_bypass_wd_sd(int if_index, int ms_timeout, int *ms_timeout_set); - -/** - * get_bypass_wd - Get watchdog state - * @if_index: network device index of the controlling device - * @ms_timeout (output): WDT timeout (in ms units), - * -1 for unknown wdt status - * 0 if WDT is disabled - * Output: - * 0 - on success - * -1 - on failure (device is not capable of the operation ordevice not support Bypass - * or it's a slave device) - **/ -int get_bypass_wd_sd(int if_index, int *ms_timeout_set); - -/** - * get_wd_expire_time - Get watchdog expire - * @if_index: network device index of the controlling device - * @ms_time_left (output): time left till watchdog time expire, - * -1 if WDT has expired - * 0 if WDT is disabled - * Output: - * 0 - on success - * -1 - on failure (device is not capable of the operation ordevice not support Bypass - * or it's a slave device or unknown wdt status) - **/ -int get_wd_expire_time_sd(int if_index, int *ms_time_left); - -/** - * reset_bypass_wd_timer - Reset watchdog timer - * @if_index: network device index of the controlling device - * - * Output: - * 1 - on success - * 0 - watchdog is not configured - * -1 - on failure (device is not capable of the operation ordevice not support Bypass - * or it's a slave device or unknown wdt status) - **/ -int reset_bypass_wd_timer_sd(int if_index); - -/** - * set_std_nic - Standard NIC mode of operation - * @if_index: network device index of the controlling device - * @nic_mode: 0/1 (Default Bypass mode / Standard NIC mode) - * - * Output: - * 0 - on success - * -1 - on failure (device is not capable of the operation ordevice not support Bypass - * or it's a slave device) - **/ -int set_std_nic_sd(int if_index, int nic_mode); - -/** - * get_std_nic - Get Standard NIC mode setting - * @if_index: network device index of the controlling device - * - * Output: - * 0/1 (Default Bypass mode / Standard NIC mode) on success - * -1 - on failure (device is not capable of the operation ordevice not support Bypass - * or it's a slave device) - **/ -int get_std_nic_sd(int if_index); - -/** - * set_tx - set transmitter enable/disable - * @if_index: network device index of the controlling device - * @tx_state: 0/1 (Transmit Disable / Transmit Enable) - * - * Output: - * 0 - on success - * -1 - on failure (device is not capable of the operation ) - **/ -int set_tx_sd(int if_index, int tx_state); - -/** - * get_tx - get transmitter state (disable / enable) - * @if_index: network device index of the controlling device - * - * Output: - * 0/1 (ransmit Disable / Transmit Enable) on success - * -1 - on failure (device is not capable of the operation ordevice not support Bypass) - **/ -int get_tx_sd(int if_index); - -/** - * set_tpl - set TPL enable/disable - * @if_index: network device index of the controlling device - * @tx_state: 0/1 (TPL Disable / TPL Enable) - * - * Output: - * 0 - on success - * -1 - on failure (device is not capable of the operation ) - **/ -int set_tpl_sd(int if_index, int tpl_state); - -/** - * get_tpl - get TPL state (disable / enable) - * @if_index: network device index of the controlling device - * - * Output: - * 0/1 (TPL Disable / TPL Enable) on success - * -1 - on failure (device is not capable of the operation) - **/ -int get_tpl_sd(int if_index); - -int get_bp_hw_reset_sd(int if_index); - -int set_bp_hw_reset_sd(int if_index, int status); - -/** - * set_tap - set TAP state - * @if_index: network device index of the controlling device - * @tap_mode: 1 tap mode , 0 normal nic mode - * Output: - * 0 - on success - * -1 - on failure (device not support TAP or it's a slave device) - **/ -int set_tap_sd(int if_index, int tap_mode); - -/** - * get_tap - Get TAP mode state - * @if_index: network device index of the controlling device - * Output: - * 0/1 - (off/on) on success - * -1 - on failure (device not support TAP or it's a slave device) - **/ -int get_tap_sd(int if_index); - -/** - * get_tap_change - Get change of TAP mode state from last status check - * @if_index: network device index of the controlling device - * Output: - * 0/1 - (off/on) on success - * -1 - on failure (device not support TAP or it's a slave device) - **/ -int get_tap_change_sd(int if_index); - -/** - * set_dis_tap - Set Disable TAP mode - * @if_index: network device index of the controlling device - * @dis_tap: disable tap(1=dis, 0=en) - * Output: - * 0 - on success - * -1 - on failure (device is not capable of the operation ordevice not support TAP - * or it's a slave device) - **/ -int set_dis_tap_sd(int if_index, int dis_tap); - -/** - * get_dis_tap - Get Disable TAP mode state - * @if_index: network device index of the controlling device - * Output: - * 0/1 - on success (normal TAP mode/ Disable TAP) - * -1 - on failure (device is not capable of the operation ordevice not support TAP - * or it's a slave device) - **/ -int get_dis_tap_sd(int if_index); - -/** - * set_tap_pwup - Set TAP mode at power-up state - * @if_index: network device index of the controlling device - * @bypass_mode: tap mode setting at power up state (1=TAP en, 0=TAP Dis) - * Output: - * 0 - on success - * -1 - on failure (device is not capable of the operation ordevice not support TAP - * or it's a slave device) - **/ -int set_tap_pwup_sd(int if_index, int tap_mode); - -/** - * get_tap_pwup - Get TAP mode state at power-up state - * @if_index: network device index of the controlling device - * Output: - * 0/1 - on success (Disable TAP at power up state / normal TAP mode) - * -1 - on failure (device is not capable of the operation ordevice not support TAP - * or it's a slave device) - **/ -int get_tap_pwup_sd(int if_index); - -/** - * set_wd_exp_mode - Set adapter state when WDT expired. - * @if_index: network device index of the controlling device - * @bypass_mode: adapter mode (1=tap mode, 0=bypass mode) - * Output: - * 0 - on success - * -1 - on failure (device not support Bypass or it's a slave device) - **/ -int set_wd_exp_mode_sd(int if_index, int bypass_mode); - -/** - * get_wd_exp_mode - Get adapter state when WDT expired. - * @if_index: network device index of the controlling device - * Output: - * 0/1 - (bypass/tap) on success - * -1 - on failure (device not support Bypass or it's a slave device) - **/ -int get_wd_exp_mode_sd(int if_index); - -/** - * set_wd_autoreset - reset WDT periodically. - * @if_index: network device index of the controlling device - * @bypass_mode: adapter mode (1=tap mode, 0=bypass mode) - * Output: - * 1 - on success - * -1 - on failure (device is not capable of the operation ordevice not support Bypass - * or it's a slave device or unknown wdt status) - **/ -int set_wd_autoreset_sd(int if_index, int time); - -/** - * set_wd_autoreset - reset WDT periodically. - * @if_index: network device index of the controlling device - * @bypass_mode: adapter mode (1=tap mode, 0=bypass mode) - * Output: - * 1 - on success - * -1 - on failure (device is not capable of the operation ordevice not support Bypass - * or it's a slave device or unknown wdt status) - **/ -int get_wd_autoreset_sd(int if_index); -/** - * set_disc - set DISC state - * @if_index: network device index of the controlling device - * @tap_mode: 1 DISC mode , 0 normal nic mode - * Output: - * 0 - on success - * -1 - on failure (device not support disconnect or it's a slave device) - **/ -int set_bp_disc_sd(int if_index, int disc_mode); - -/** - * get_disc - Get disc mode state - * @if_index: network device index of the controlling device - * Output: - * 0/1 - (off/on) on success - * -1 - on failure (device not support disconnect or it's a slave device) - **/ -int get_bp_disc_sd(int if_index); - -/** - * get_disc_change - Get change of DISC mode state from last status check - * @if_index: network device index of the controlling device - * Output: - * 0/1 - (off/on) on success - * -1 - on failure (device not support disconnect or it's a slave device) - **/ -int get_bp_disc_change_sd(int if_index); - -/** - * set_dis_disc - Set Disable DISC mode - * @if_index: network device index of the controlling device - * @dis_disc: disable disconnect(1=dis, 0=en) - * Output: - * 0 - on success - * -1 - on failure (device is not capable of the operation ordevice not support DISC - * or it's a slave device) - **/ -int set_bp_dis_disc_sd(int if_index, int dis_disc); - -/** - * get_dis_disc - Get Disable DISC mode state - * @if_index: network device index of the controlling device - * Output: - * 0/1 - on success (normal DISC mode/ Disable DISC) - * -1 - on failure (device is not capable of the operation ordevice not support TAP - * or it's a slave device) - **/ -int get_bp_dis_disc_sd(int if_index); - -/** - * set_disc_pwup - Set DISC mode at power-up state - * @if_index: network device index of the controlling device - * @disc_mode: DISC mode setting at power up state (1= en, 0= Dis) - * Output: - * 0 - on success - * -1 - on failure (device is not capable of the operation ordevice not support DISC - * or it's a slave device) - **/ -int set_bp_disc_pwup_sd(int if_index, int disc_mode); - -/** - * get_disc_pwup - Get DISC mode state at power-up state - * @if_index: network device index of the controlling device - * Output: - * 0/1 - on success (Disable DISC at power up state / normal DISC mode) - * -1 - on failure (device is not capable of the operation ordevice not support DISC - * or it's a slave device) - **/ -int get_bp_disc_pwup_sd(int if_index); - -int get_bypass_info_sd(int if_index, struct bp_info *bp_info); -int bp_if_scan_sd(void); -/*int get_dev_num_sd(void);*/ diff --git a/trunk/drivers/staging/slicoss/slicoss.c b/trunk/drivers/staging/slicoss/slicoss.c index cd920dad85cd..56829fc032ff 100644 --- a/trunk/drivers/staging/slicoss/slicoss.c +++ b/trunk/drivers/staging/slicoss/slicoss.c @@ -514,7 +514,8 @@ static int slic_card_download_gbrcv(struct adapter *adapter) file = "slicoss/gbrcvucode.sys"; break; default: - return -ENOENT; + ASSERT(0); + break; } ret = request_firmware(&fw, file, &adapter->pcidev->dev); @@ -528,16 +529,15 @@ static int slic_card_download_gbrcv(struct adapter *adapter) index += 4; switch (adapter->devid) { case SLIC_2GB_DEVICE_ID: - if (rcvucodelen != OasisRcvUCodeLen) { - release_firmware(fw); + if (rcvucodelen != OasisRcvUCodeLen) return -EINVAL; - } break; case SLIC_1GB_DEVICE_ID: - if (rcvucodelen != GBRcvUCodeLen) { - release_firmware(fw); + if (rcvucodelen != GBRcvUCodeLen) return -EINVAL; - } + break; + default: + ASSERT(0); break; } /* start download */ @@ -2552,6 +2552,7 @@ static void slic_mcast_set_list(struct net_device *dev) if (status == 0) slic_mcast_set_mask(adapter); } + return; } #define XMIT_FAIL_LINK_STATE 1 @@ -3131,6 +3132,7 @@ static int slic_entry_open(struct net_device *dev) { struct adapter *adapter = netdev_priv(dev); struct sliccard *card = adapter->card; + u32 locked = 0; int status; ASSERT(adapter); @@ -3140,6 +3142,7 @@ static int slic_entry_open(struct net_device *dev) spin_lock_irqsave(&slic_global.driver_lock.lock, slic_global.driver_lock.flags); + locked = 1; if (!adapter->activated) { card->adapters_activated++; slic_global.num_slic_ports_active++; @@ -3153,15 +3156,23 @@ static int slic_entry_open(struct net_device *dev) slic_global.num_slic_ports_active--; adapter->activated = 0; } - goto spin_unlock; + if (locked) { + spin_unlock_irqrestore(&slic_global.driver_lock.lock, + slic_global.driver_lock.flags); + locked = 0; + } + return status; } if (!card->master) card->master = adapter; -spin_unlock: - spin_unlock_irqrestore(&slic_global.driver_lock.lock, - slic_global.driver_lock.flags); - return status; + if (locked) { + spin_unlock_irqrestore(&slic_global.driver_lock.lock, + slic_global.driver_lock.flags); + locked = 0; + } + + return 0; } static void slic_card_cleanup(struct sliccard *card) @@ -3701,8 +3712,9 @@ static void slic_init_adapter(struct net_device *netdev, phys_shmem); ASSERT(adapter->pshmem); - if (adapter->pshmem) - memset(adapter->pshmem, 0, sizeof(struct slic_shmem)); + memset(adapter->pshmem, 0, sizeof(struct slic_shmem)); + + return; } static const struct net_device_ops slic_netdev_ops = { diff --git a/trunk/drivers/staging/sm7xxfb/sm7xx.h b/trunk/drivers/staging/sm7xxfb/sm7xx.h index 85998615b801..333f33c3dc66 100644 --- a/trunk/drivers/staging/sm7xxfb/sm7xx.h +++ b/trunk/drivers/staging/sm7xxfb/sm7xx.h @@ -29,7 +29,7 @@ #define dac_reg (0x3c8) #define dac_val (0x3c9) -extern void __iomem *smtc_RegBaseAddress; +extern char __iomem *smtc_RegBaseAddress; #define smtc_mmiowb(dat, reg) writeb(dat, smtc_RegBaseAddress + reg) #define smtc_mmioww(dat, reg) writew(dat, smtc_RegBaseAddress + reg) #define smtc_mmiowl(dat, reg) writel(dat, smtc_RegBaseAddress + reg) diff --git a/trunk/drivers/staging/sm7xxfb/sm7xxfb.c b/trunk/drivers/staging/sm7xxfb/sm7xxfb.c index f27182d4dea6..1c1780c70fbb 100644 --- a/trunk/drivers/staging/sm7xxfb/sm7xxfb.c +++ b/trunk/drivers/staging/sm7xxfb/sm7xxfb.c @@ -43,11 +43,11 @@ struct smtcfb_info { u16 chip_id; u8 chip_rev_id; - void __iomem *lfb; /* linear frame buffer */ - void __iomem *dp_regs; /* drawing processor control regs */ - void __iomem *vp_regs; /* video processor control regs */ - void __iomem *cp_regs; /* capture processor control regs */ - void __iomem *mmio; /* memory map IO port */ + unsigned char __iomem *m_pMMIO; + char __iomem *m_pLFB; + char *m_pDPR; + char *m_pVPR; + char *m_pCPR; u_int width; u_int height; @@ -56,7 +56,8 @@ struct smtcfb_info { u32 colreg[17]; }; -void __iomem *smtc_RegBaseAddress; /* Memory Map IO starting address */ +char __iomem *smtc_RegBaseAddress; /* Memory Map IO starting address */ +char __iomem *smtc_VRAMBaseAddress; /* video memory starting address */ static struct fb_var_screeninfo smtcfb_var = { .xres = 1024, @@ -71,20 +72,14 @@ static struct fb_var_screeninfo smtcfb_var = { .height = -1, .width = -1, .vmode = FB_VMODE_NONINTERLACED, - .nonstd = 0, - .accel_flags = FB_ACCELF_TEXT, }; static struct fb_fix_screeninfo smtcfb_fix = { - .id = "smXXXfb", + .id = "sm712fb", .type = FB_TYPE_PACKED_PIXELS, .visual = FB_VISUAL_TRUECOLOR, .line_length = 800 * 3, .accel = FB_ACCEL_SMI_LYNX, - .type_aux = 0, - .xpanstep = 0, - .ypanstep = 0, - .ywrapstep = 0, }; struct vesa_mode { @@ -550,28 +545,28 @@ static void sm7xx_set_timing(struct smtcfb_info *sfb) smtc_mmiowb(0x67, 0x3c2); /* set VPR registers */ - writel(0x0, sfb->vp_regs + 0x0C); - writel(0x0, sfb->vp_regs + 0x40); + writel(0x0, sfb->m_pVPR + 0x0C); + writel(0x0, sfb->m_pVPR + 0x40); /* set data width */ m_nScreenStride = (sfb->width * sfb->fb.var.bits_per_pixel) / 64; switch (sfb->fb.var.bits_per_pixel) { case 8: - writel(0x0, sfb->vp_regs + 0x0); + writel(0x0, sfb->m_pVPR + 0x0); break; case 16: - writel(0x00020000, sfb->vp_regs + 0x0); + writel(0x00020000, sfb->m_pVPR + 0x0); break; case 24: - writel(0x00040000, sfb->vp_regs + 0x0); + writel(0x00040000, sfb->m_pVPR + 0x0); break; case 32: - writel(0x00030000, sfb->vp_regs + 0x0); + writel(0x00030000, sfb->m_pVPR + 0x0); break; } writel((u32) (((m_nScreenStride + 2) << 16) | m_nScreenStride), - sfb->vp_regs + 0x10); + sfb->m_pVPR + 0x10); } @@ -678,9 +673,9 @@ static struct fb_ops smtcfb_ops = { }; /* - * alloc struct smtcfb_info and assign default values + * alloc struct smtcfb_info and assign the default value */ -static struct smtcfb_info *smtc_alloc_fb_info(struct pci_dev *pdev) +static struct smtcfb_info *smtc_alloc_fb_info(struct pci_dev *pdev, char *name) { struct smtcfb_info *sfb; @@ -691,12 +686,32 @@ static struct smtcfb_info *smtc_alloc_fb_info(struct pci_dev *pdev) sfb->pdev = pdev; - sfb->fb.flags = FBINFO_FLAG_DEFAULT; - sfb->fb.fbops = &smtcfb_ops; - sfb->fb.fix = smtcfb_fix; - sfb->fb.var = smtcfb_var; - sfb->fb.pseudo_palette = sfb->colreg; - sfb->fb.par = sfb; + /* init sfb->fb with default value */ + + sfb->fb.flags = FBINFO_FLAG_DEFAULT; + sfb->fb.fbops = &smtcfb_ops; + + sfb->fb.fix = smtcfb_fix; + strcpy(sfb->fb.fix.id, name); + + sfb->fb.fix.type = FB_TYPE_PACKED_PIXELS; + sfb->fb.fix.type_aux = 0; + sfb->fb.fix.xpanstep = 0; + sfb->fb.fix.ypanstep = 0; + sfb->fb.fix.ywrapstep = 0; + sfb->fb.fix.accel = FB_ACCEL_SMI_LYNX; + + sfb->fb.var = smtcfb_var; + sfb->fb.var.nonstd = 0; + sfb->fb.var.activate = FB_ACTIVATE_NOW; + sfb->fb.var.height = -1; + sfb->fb.var.width = -1; + sfb->fb.var.accel_flags = FB_ACCELF_TEXT; + sfb->fb.var.vmode = FB_VMODE_NONINTERLACED; + + sfb->fb.pseudo_palette = sfb->colreg; + + sfb->fb.par = sfb; return sfb; } @@ -736,7 +751,7 @@ static int smtc_map_smem(struct smtcfb_info *sfb, sfb->fb.fix.smem_len = smem_len; - sfb->fb.screen_base = sfb->lfb; + sfb->fb.screen_base = smtc_VRAMBaseAddress; if (!sfb->fb.screen_base) { dev_err(&pdev->dev, @@ -773,8 +788,9 @@ static int __devinit smtcfb_pci_probe(struct pci_dev *pdev, { struct smtcfb_info *sfb; u_long smem_size = 0x00800000; /* default 8MB */ + char name[16]; int err; - unsigned long mmio_base; + unsigned long pFramebufferPhysical; dev_info(&pdev->dev, "Silicon Motion display driver."); @@ -782,9 +798,7 @@ static int __devinit smtcfb_pci_probe(struct pci_dev *pdev, if (err) return err; - sprintf(smtcfb_fix.id, "sm%Xfb", ent->device); - - sfb = smtc_alloc_fb_info(pdev); + sfb = smtc_alloc_fb_info(pdev, name); if (!sfb) { err = -ENOMEM; @@ -792,6 +806,7 @@ static int __devinit smtcfb_pci_probe(struct pci_dev *pdev, } sfb->chip_id = ent->device; + sprintf(name, "sm%Xfb", sfb->chip_id); pci_set_drvdata(pdev, sfb); @@ -814,28 +829,33 @@ static int __devinit smtcfb_pci_probe(struct pci_dev *pdev, sfb->fb.var.bits_per_pixel = (smtc_scr_info.lfb_depth = 32); #endif /* Map address and memory detection */ - mmio_base = pci_resource_start(pdev, 0); + pFramebufferPhysical = pci_resource_start(pdev, 0); pci_read_config_byte(pdev, PCI_REVISION_ID, &sfb->chip_rev_id); switch (sfb->chip_id) { case 0x710: case 0x712: - sfb->fb.fix.mmio_start = mmio_base + 0x00400000; + sfb->fb.fix.mmio_start = pFramebufferPhysical + 0x00400000; sfb->fb.fix.mmio_len = 0x00400000; smem_size = SM712_VIDEOMEMORYSIZE; #ifdef __BIG_ENDIAN - sfb->lfb = ioremap(mmio_base, 0x00c00000); + sfb->m_pLFB = (smtc_VRAMBaseAddress = + ioremap(pFramebufferPhysical, 0x00c00000)); #else - sfb->lfb = ioremap(mmio_base, 0x00800000); + sfb->m_pLFB = (smtc_VRAMBaseAddress = + ioremap(pFramebufferPhysical, 0x00800000)); #endif - sfb->mmio = (smtc_RegBaseAddress = - sfb->lfb + 0x00700000); - sfb->dp_regs = sfb->lfb + 0x00408000; - sfb->vp_regs = sfb->lfb + 0x0040c000; + sfb->m_pMMIO = (smtc_RegBaseAddress = + smtc_VRAMBaseAddress + 0x00700000); + sfb->m_pDPR = smtc_VRAMBaseAddress + 0x00408000; + sfb->m_pVPR = sfb->m_pLFB + 0x0040c000; #ifdef __BIG_ENDIAN if (sfb->fb.var.bits_per_pixel == 32) { - sfb->lfb += 0x800000; - dev_info(&pdev->dev, "sfb->lfb=%p", sfb->lfb); + smtc_VRAMBaseAddress += 0x800000; + sfb->m_pLFB += 0x800000; + dev_info(&pdev->dev, + "smtc_VRAMBaseAddress=%p sfb->m_pLFB=%p", + smtc_VRAMBaseAddress, sfb->m_pLFB); } #endif if (!smtc_RegBaseAddress) { @@ -859,14 +879,15 @@ static int __devinit smtcfb_pci_probe(struct pci_dev *pdev, #endif break; case 0x720: - sfb->fb.fix.mmio_start = mmio_base; + sfb->fb.fix.mmio_start = pFramebufferPhysical; sfb->fb.fix.mmio_len = 0x00200000; smem_size = SM722_VIDEOMEMORYSIZE; - sfb->dp_regs = ioremap(mmio_base, 0x00a00000); - sfb->lfb = sfb->dp_regs + 0x00200000; - sfb->mmio = (smtc_RegBaseAddress = - sfb->dp_regs + 0x000c0000); - sfb->vp_regs = sfb->dp_regs + 0x800; + sfb->m_pDPR = ioremap(pFramebufferPhysical, 0x00a00000); + sfb->m_pLFB = (smtc_VRAMBaseAddress = + sfb->m_pDPR + 0x00200000); + sfb->m_pMMIO = (smtc_RegBaseAddress = + sfb->m_pDPR + 0x000c0000); + sfb->m_pVPR = sfb->m_pDPR + 0x800; smtc_seqw(0x62, 0xff); smtc_seqw(0x6a, 0x0d); diff --git a/trunk/drivers/staging/speakup/i18n.c b/trunk/drivers/staging/speakup/i18n.c index 7c1658b971dc..ca01734d13c5 100644 --- a/trunk/drivers/staging/speakup/i18n.c +++ b/trunk/drivers/staging/speakup/i18n.c @@ -555,7 +555,6 @@ ssize_t msg_set(enum msg_index_t index, char *text, size_t length) && index <= MSG_FORMATTED_END) && !fmt_validate(speakup_default_msgs[index], newstr)) { - kfree(newstr); return -EINVAL; } spk_lock(flags); diff --git a/trunk/drivers/staging/speakup/serialio.h b/trunk/drivers/staging/speakup/serialio.h index 55d68b5ad165..614271f9b99f 100644 --- a/trunk/drivers/staging/speakup/serialio.h +++ b/trunk/drivers/staging/speakup/serialio.h @@ -1,7 +1,8 @@ #ifndef _SPEAKUP_SERIAL_H #define _SPEAKUP_SERIAL_H -#include /* for rs_table, serial constants */ +#include /* for rs_table, serial constants & + serial_uart_config */ #include /* for more serial constants */ #ifndef __sparc__ #include diff --git a/trunk/drivers/staging/speakup/speakup_soft.c b/trunk/drivers/staging/speakup/speakup_soft.c index e2f5c81e7548..42cdafeea35e 100644 --- a/trunk/drivers/staging/speakup/speakup_soft.c +++ b/trunk/drivers/staging/speakup/speakup_soft.c @@ -40,13 +40,13 @@ static int softsynth_is_alive(struct spk_synth *synth); static unsigned char get_index(void); static struct miscdevice synth_device; -static int init_pos; +static int initialized; static int misc_registered; static struct var_t vars[] = { { CAPS_START, .u.s = {"\x01+3p" } }, { CAPS_STOP, .u.s = {"\x01-3p" } }, - { RATE, .u.n = {"\x01%ds", 2, 0, 9, 0, 0, NULL } }, + { RATE, .u.n = {"\x01%ds", 5, 0, 9, 0, 0, NULL } }, { PITCH, .u.n = {"\x01%dp", 5, 0, 9, 0, 0, NULL } }, { VOL, .u.n = {"\x01%dv", 5, 0, 9, 0, 0, NULL } }, { TONE, .u.n = {"\x01%dx", 1, 0, 2, 0, 0, NULL } }, @@ -194,7 +194,7 @@ static int softsynth_close(struct inode *inode, struct file *fp) unsigned long flags; spk_lock(flags); synth_soft.alive = 0; - init_pos = 0; + initialized = 0; spk_unlock(flags); /* Make sure we let applications go before leaving */ speakup_start_ttys(); @@ -239,8 +239,13 @@ static ssize_t softsynth_read(struct file *fp, char *buf, size_t count, ch = '\x18'; } else if (synth_buffer_empty()) { break; - } else if (init[init_pos]) { - ch = init[init_pos++]; + } else if (!initialized) { + if (*init) { + ch = *init; + init++; + } else { + initialized = 1; + } } else { ch = synth_buffer_getc(); } diff --git a/trunk/drivers/staging/telephony/ixj.c b/trunk/drivers/staging/telephony/ixj.c index 1cfa0b07d725..b303c9192e17 100644 --- a/trunk/drivers/staging/telephony/ixj.c +++ b/trunk/drivers/staging/telephony/ixj.c @@ -7057,7 +7057,7 @@ static int ixj_selfprobe(IXJ *j) printk(KERN_INFO "Enable Line Monitor\n"); if (ixjdebug & 0x0002) - printk(KERN_INFO "Set Line Monitor to Asynchronous Mode\n"); + printk(KERN_INFO "Set Line Monitor to Asyncronous Mode\n"); if (ixj_WriteDSPCommand(0x7E01, j)) /* Asynchronous Line Monitor */ return -1; @@ -7068,7 +7068,7 @@ static int ixj_selfprobe(IXJ *j) if (ixj_WriteDSPCommand(0x5151, j)) /* Enable DTMF detection */ return -1; - if (ixj_WriteDSPCommand(0x6E01, j)) /* Set Asynchronous Tone Generation */ + if (ixj_WriteDSPCommand(0x6E01, j)) /* Set Asyncronous Tone Generation */ return -1; set_rec_depth(j, 2); /* Set Record Channel Limit to 2 frames */ diff --git a/trunk/drivers/staging/tidspbridge/Documentation/error-codes b/trunk/drivers/staging/tidspbridge/Documentation/error-codes index ad73cba058eb..12826e2a3aaa 100644 --- a/trunk/drivers/staging/tidspbridge/Documentation/error-codes +++ b/trunk/drivers/staging/tidspbridge/Documentation/error-codes @@ -69,7 +69,7 @@ The error codes used by this driver are: Invalid pointer or handler. [EEXIST] - Attempted to create a channel manager when one already exists. + Attempted to create a channel manager when one already exists. [EINVAL] Invalid argument. diff --git a/trunk/drivers/staging/tidspbridge/core/_tiomap.h b/trunk/drivers/staging/tidspbridge/core/_tiomap.h index 543a127c7d4d..7cb587103975 100644 --- a/trunk/drivers/staging/tidspbridge/core/_tiomap.h +++ b/trunk/drivers/staging/tidspbridge/core/_tiomap.h @@ -219,7 +219,7 @@ static const struct map_l4_peripheral l4_peripheral_table[] = { /* MBX_PM_MAX_RESOURCES: CORE 2 Clock Resources. */ #define MBX_CORE2_RESOURCES 1 -/* MBX_PM_MAX_RESOURCES: TOTAL Clock Resources. */ +/* MBX_PM_MAX_RESOURCES: TOTAL Clock Reosurces. */ #define MBX_PM_MAX_RESOURCES 11 /* Power Management Commands */ diff --git a/trunk/drivers/staging/tidspbridge/core/chnl_sm.c b/trunk/drivers/staging/tidspbridge/core/chnl_sm.c index 16fa3462fbbe..e0c7e4c470c8 100644 --- a/trunk/drivers/staging/tidspbridge/core/chnl_sm.c +++ b/trunk/drivers/staging/tidspbridge/core/chnl_sm.c @@ -20,7 +20,7 @@ * The lower edge functions must be implemented by the Bridge driver * writer, and are declared in chnl_sm.h. * - * Care is taken in this code to prevent simultaneous access to channel + * Care is taken in this code to prevent simulataneous access to channel * queues from * 1. Threads. * 2. io_dpc(), scheduled from the io_isr() as an event. @@ -34,7 +34,7 @@ * Channel Invariant: * There is an important invariant condition which must be maintained per * channel outside of bridge_chnl_get_ioc() and IO_Dispatch(), violation of - * which may cause timeouts and/or failure of function sync_wait_on_event. + * which may cause timeouts and/or failure offunction sync_wait_on_event. * This invariant condition is: * * list_empty(&pchnl->io_completions) ==> pchnl->sync_event is reset @@ -94,7 +94,7 @@ int bridge_chnl_add_io_req(struct chnl_object *chnl_obj, void *host_buf, struct dev_object *dev_obj; u8 dw_state; bool is_eos; - struct chnl_mgr *chnl_mgr_obj; + struct chnl_mgr *chnl_mgr_obj = pchnl->chnl_mgr_obj; u8 *host_sys_buf = NULL; bool sched_dpc = false; u16 mb_val = 0; @@ -153,7 +153,6 @@ int bridge_chnl_add_io_req(struct chnl_object *chnl_obj, void *host_buf, * If DPC is scheduled in process context (iosm_schedule) and any * non-mailbox interrupt occurs, that DPC will run and break CS. Hence * we disable ALL DPCs. We will try to disable ONLY IO DPC later. */ - chnl_mgr_obj = pchnl->chnl_mgr_obj; spin_lock_bh(&chnl_mgr_obj->chnl_mgr_lock); omap_mbox_disable_irq(dev_ctxt->mbox, IRQ_RX); if (pchnl->chnl_type == CHNL_PCPY) { @@ -603,7 +602,7 @@ int bridge_chnl_get_ioc(struct chnl_object *chnl_obj, u32 timeout, /* Since DSPStream_Reclaim() does not take a timeout * parameter, we pass the stream's timeout value to * bridge_chnl_get_ioc. We cannot determine whether or not - * we have waited in user mode. Since the stream's timeout + * we have waited in User mode. Since the stream's timeout * value may be non-zero, we still have to set the event. * Therefore, this optimization is taken out. * diff --git a/trunk/drivers/staging/tidspbridge/core/dsp-clock.c b/trunk/drivers/staging/tidspbridge/core/dsp-clock.c index 7eac01e5fe0b..c7df34e6b60b 100644 --- a/trunk/drivers/staging/tidspbridge/core/dsp-clock.c +++ b/trunk/drivers/staging/tidspbridge/core/dsp-clock.c @@ -16,8 +16,6 @@ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ -#define L4_34XX_BASE 0x48000000 - #include /* ----------------------------------- Host OS */ diff --git a/trunk/drivers/staging/tidspbridge/core/io_sm.c b/trunk/drivers/staging/tidspbridge/core/io_sm.c index e322fb7aebe1..480a3845a24c 100644 --- a/trunk/drivers/staging/tidspbridge/core/io_sm.c +++ b/trunk/drivers/staging/tidspbridge/core/io_sm.c @@ -837,8 +837,8 @@ static void io_dispatch_pm(struct io_mgr *pio_mgr) /* * ======== io_dpc ======== * Deferred procedure call for shared memory channel driver ISR. Carries - * out the dispatch of I/O as a non-preemptible event. It can only be - * pre-empted by an ISR. + * out the dispatch of I/O as a non-preemptible event.It can only be + * pre-empted by an ISR. */ void io_dpc(unsigned long ref_data) { @@ -877,7 +877,7 @@ void io_dpc(unsigned long ref_data) pio_mgr->intr_val); } } - /* Proc-copy channel dispatch */ + /* Proc-copy chanel dispatch */ input_chnl(pio_mgr, NULL, IO_SERVICE); output_chnl(pio_mgr, NULL, IO_SERVICE); @@ -938,7 +938,7 @@ int io_mbox_msg(struct notifier_block *self, unsigned long len, void *msg) /* * ======== io_request_chnl ======== * Purpose: - * Request channel I/O from the DSP. Sets flags in shared memory, then + * Request chanenel I/O from the DSP. Sets flags in shared memory, then * interrupts the DSP. */ void io_request_chnl(struct io_mgr *io_manager, struct chnl_object *pchnl, @@ -2208,7 +2208,7 @@ void dump_dl_modules(struct bridge_dev_context *bridge_context) module_struct->num_sects); /* - * The section name strings start immediately following + * The section name strings start immedialty following * the array of dll_sect structures. */ sect_str = (char *) &module_struct-> diff --git a/trunk/drivers/staging/tidspbridge/core/sync.c b/trunk/drivers/staging/tidspbridge/core/sync.c index 7bb550acaf4a..995986a9d03b 100644 --- a/trunk/drivers/staging/tidspbridge/core/sync.c +++ b/trunk/drivers/staging/tidspbridge/core/sync.c @@ -49,7 +49,7 @@ void sync_set_event(struct sync_object *event) * @timeout timeout on waiting for the evetns. * @pu_index index of the event set. * - * These functions will wait until any of the array element is set or until + * This functios will wait until any of the array element is set or until * timeout. In case of success the function will return 0 and * @pu_index will store the index of the array element set or in case * of timeout the function will return -ETIME or in case of diff --git a/trunk/drivers/staging/tidspbridge/core/tiomap3430.c b/trunk/drivers/staging/tidspbridge/core/tiomap3430.c index 012c5a0cc6c8..f9609ce2c163 100644 --- a/trunk/drivers/staging/tidspbridge/core/tiomap3430.c +++ b/trunk/drivers/staging/tidspbridge/core/tiomap3430.c @@ -328,7 +328,7 @@ static int bridge_brd_read(struct bridge_dev_context *dev_ctxt, ul_num_bytes, mem_type); return status; } - /* copy the data from DSP memory */ + /* copy the data from DSP memory, */ memcpy(host_buff, (void *)(dsp_base_addr + offset), ul_num_bytes); return status; } @@ -415,10 +415,10 @@ static int bridge_brd_start(struct bridge_dev_context *dev_ctxt, /* Assert RST1 i.e only the RST only for DSP megacell */ if (!status) { /* - * XXX: OMAP343X_CTRL_BASE ioremapping MUST be removed once ctrl + * XXX: ioremapping MUST be removed once ctrl * function is made available. */ - void __iomem *ctrl = ioremap(0x48002000, SZ_4K); + void __iomem *ctrl = ioremap(OMAP343X_CTRL_BASE, SZ_4K); if (!ctrl) return -ENOMEM; @@ -1745,7 +1745,7 @@ static int mem_map_vmalloc(struct bridge_dev_context *dev_context, pa_next = page_to_phys(page[0]); while (!status && (i < num_pages)) { /* - * Reuse pa_next from the previous iteration to avoid + * Reuse pa_next from the previous iteraion to avoid * an extra va2pa call */ pa_curr = pa_next; diff --git a/trunk/drivers/staging/tidspbridge/core/tiomap3430_pwr.c b/trunk/drivers/staging/tidspbridge/core/tiomap3430_pwr.c index 58a1d6dcf098..16a4aafa86ae 100644 --- a/trunk/drivers/staging/tidspbridge/core/tiomap3430_pwr.c +++ b/trunk/drivers/staging/tidspbridge/core/tiomap3430_pwr.c @@ -356,7 +356,7 @@ int pre_scale_dsp(struct bridge_dev_context *dev_context, void *pargs) dev_dbg(bridge, "OPP: %s IVA in sleep. No message to DSP\n"); return 0; } else if ((dev_context->brd_state == BRD_RUNNING)) { - /* Send a prenotification to DSP */ + /* Send a prenotificatio to DSP */ dev_dbg(bridge, "OPP: %s sent notification to DSP\n", __func__); sm_interrupt_dsp(dev_context, MBX_PM_SETPOINT_PRENOTIFY); return 0; diff --git a/trunk/drivers/staging/tidspbridge/core/wdt.c b/trunk/drivers/staging/tidspbridge/core/wdt.c index e5adad08f1c4..870f934f4f3b 100644 --- a/trunk/drivers/staging/tidspbridge/core/wdt.c +++ b/trunk/drivers/staging/tidspbridge/core/wdt.c @@ -25,8 +25,7 @@ #include -#define OMAP34XX_WDT3_BASE (0x49000000 + 0x30000) -#define INT_34XX_WDT3_IRQ 36 +#define OMAP34XX_WDT3_BASE (L4_PER_34XX_BASE + 0x30000) static struct dsp_wdt_setting dsp_wdt; @@ -62,9 +61,9 @@ int dsp_wdt_init(void) dsp_wdt.fclk = clk_get(NULL, "wdt3_fck"); - if (!IS_ERR(dsp_wdt.fclk)) { + if (dsp_wdt.fclk) { dsp_wdt.iclk = clk_get(NULL, "wdt3_ick"); - if (IS_ERR(dsp_wdt.iclk)) { + if (!dsp_wdt.iclk) { clk_put(dsp_wdt.fclk); dsp_wdt.fclk = NULL; ret = -EFAULT; diff --git a/trunk/drivers/staging/tidspbridge/dynload/tramp.c b/trunk/drivers/staging/tidspbridge/dynload/tramp.c index 404af1895980..60d22ea47055 100644 --- a/trunk/drivers/staging/tidspbridge/dynload/tramp.c +++ b/trunk/drivers/staging/tidspbridge/dynload/tramp.c @@ -81,7 +81,7 @@ static u8 priv_h2a(u8 value) * Description: Generate a trampoline symbol name (ASCII) using the value * of the symbol. This places the new name into the user buffer. * The name is fixed in length and of the form: __$dbTR__xxxxxxxx - * (where "xxxxxxxx" is the hex value). + * (where "xxxxxxxx" is the hex value. */ static void priv_tramp_sym_gen_name(u32 value, char *dst) { @@ -414,7 +414,7 @@ static int priv_tramp_sym_finalize(struct dload_state *dlthis) /* Copy the symbol contents into the flat table */ *new_sym = cur_sym->sym_info; - /* Now finalize the symbol. If it is in the tramp + /* Now finaize the symbol. If it is in the tramp * section, we need to adjust for the section start. * If it is external then we don't need to adjust at * all. @@ -773,7 +773,7 @@ static int priv_img_pkt_dup(struct dload_state *dlthis, int ret_val = 0; struct tramp_img_dup_relo *dup_relo = NULL; - /* Determine if this image packet is already being tracked in the + /* Determinne if this image packet is already being tracked in the dup list for other trampolines. */ dup_pkt = priv_dup_find(dlthis, secnn, image_offset); @@ -998,7 +998,7 @@ int dload_tramp_generate(struct dload_state *dlthis, s16 secnn, /* * Function: dload_tramp_pkt_update * Description: Update the duplicate copy of this image packet, which the - * trampoline layer is already tracking. This call is critical + * trampoline layer is already tracking. This is call is critical * to make if trampolines were generated anywhere within the * packet and first pass relo continued on the remainder. The * trampoline layer needs the updates image data so when 2nd diff --git a/trunk/drivers/staging/tidspbridge/gen/uuidutil.c b/trunk/drivers/staging/tidspbridge/gen/uuidutil.c index b7d8313d1acb..b44656cf7858 100644 --- a/trunk/drivers/staging/tidspbridge/gen/uuidutil.c +++ b/trunk/drivers/staging/tidspbridge/gen/uuidutil.c @@ -26,6 +26,27 @@ /* ----------------------------------- This */ #include +/* + * ======== uuid_uuid_to_string ======== + * Purpose: + * Converts a struct dsp_uuid to a string. + * Note: snprintf format specifier is: + * %[flags] [width] [.precision] [{h | l | I64 | L}]type + */ +void uuid_uuid_to_string(struct dsp_uuid *uuid_obj, char *sz_uuid, + s32 size) +{ + s32 i; /* return result from snprintf. */ + + i = snprintf(sz_uuid, size, + "%.8X_%.4X_%.4X_%.2X%.2X_%.2X%.2X%.2X%.2X%.2X%.2X", + uuid_obj->data1, uuid_obj->data2, uuid_obj->data3, + uuid_obj->data4, uuid_obj->data5, + uuid_obj->data6[0], uuid_obj->data6[1], + uuid_obj->data6[2], uuid_obj->data6[3], + uuid_obj->data6[4], uuid_obj->data6[5]); +} + static s32 uuid_hex_to_bin(char *buf, s32 len) { s32 i; diff --git a/trunk/drivers/staging/tidspbridge/hw/hw_mmu.c b/trunk/drivers/staging/tidspbridge/hw/hw_mmu.c index 71cb82293649..8a93d55ca596 100644 --- a/trunk/drivers/staging/tidspbridge/hw/hw_mmu.c +++ b/trunk/drivers/staging/tidspbridge/hw/hw_mmu.c @@ -61,7 +61,7 @@ enum hw_mmu_page_size_t { * Type : hw_status * Description : 0 -- No errors occurred * RET_BAD_NULL_PARAM -- A Pointer - * Parameter was set to NULL + * Paramater was set to NULL * * PURPOSE: : Flush the TLB entry pointed by the * lock counter register @@ -103,7 +103,7 @@ static hw_status mmu_flush_entry(const void __iomem *base_address); * * Type : hw_status * Description : 0 -- No errors occurred - * RET_BAD_NULL_PARAM -- A Pointer Parameter + * RET_BAD_NULL_PARAM -- A Pointer Paramater * was set to NULL * RET_PARAM_OUT_OF_RANGE -- Input Parameter out * of Range @@ -148,7 +148,7 @@ static hw_status mmu_set_cam_entry(const void __iomem *base_address, * * Type : hw_status * Description : 0 -- No errors occurred - * RET_BAD_NULL_PARAM -- A Pointer Parameter + * RET_BAD_NULL_PARAM -- A Pointer Paramater * was set to NULL * RET_PARAM_OUT_OF_RANGE -- Input Parameter * out of Range diff --git a/trunk/drivers/staging/tidspbridge/include/dspbridge/dspioctl.h b/trunk/drivers/staging/tidspbridge/include/dspbridge/dspioctl.h index 0fcda1978921..0c7ec04448f1 100644 --- a/trunk/drivers/staging/tidspbridge/include/dspbridge/dspioctl.h +++ b/trunk/drivers/staging/tidspbridge/include/dspbridge/dspioctl.h @@ -51,7 +51,7 @@ #define BRDIOCTL_POSTSCALE_NOTIFY (BRDIOCTL_PWRCONTROL + 0xA) #define BRDIOCTL_CONSTRAINT_REQUEST (BRDIOCTL_PWRCONTROL + 0xB) -/* Number of actual DSP-MMU TLB entries */ +/* Number of actual DSP-MMU TLB entrries */ #define BRDIOCTL_NUMOFMMUTLB 32 struct bridge_ioctl_extproc { diff --git a/trunk/drivers/staging/tidspbridge/include/dspbridge/mbx_sh.h b/trunk/drivers/staging/tidspbridge/include/dspbridge/mbx_sh.h index d4cb3948baba..7424c888d637 100644 --- a/trunk/drivers/staging/tidspbridge/include/dspbridge/mbx_sh.h +++ b/trunk/drivers/staging/tidspbridge/include/dspbridge/mbx_sh.h @@ -22,7 +22,7 @@ * mailbox interrupt's cmd value received. The class value are defined * as a bit (10 thru 15) being set. * - * Note: Only 16 bits of each is used. Other 16 bit data reg available. + * Note: Only 16 bits of each is used. Other 16 bit data reg available. * * 16 bit Mbx bit defns: * diff --git a/trunk/drivers/staging/tidspbridge/include/dspbridge/node.h b/trunk/drivers/staging/tidspbridge/include/dspbridge/node.h index 68ed74a86c95..7397b7a12f7a 100644 --- a/trunk/drivers/staging/tidspbridge/include/dspbridge/node.h +++ b/trunk/drivers/staging/tidspbridge/include/dspbridge/node.h @@ -220,7 +220,7 @@ extern int node_create_mgr(struct node_mgr **node_man, * Parameters: * noderes: Node resource info handle returned from * node_allocate(). - * pr_ctxt: Pointer to process context data. + * pr_ctxt: Poninter to process context data. * Returns: * 0: Success. * -EFAULT: Invalid hnode. diff --git a/trunk/drivers/staging/tidspbridge/include/dspbridge/ntfy.h b/trunk/drivers/staging/tidspbridge/include/dspbridge/ntfy.h index 6bb94d20e99a..cbc8819c61cc 100644 --- a/trunk/drivers/staging/tidspbridge/include/dspbridge/ntfy.h +++ b/trunk/drivers/staging/tidspbridge/include/dspbridge/ntfy.h @@ -78,7 +78,7 @@ static inline void ntfy_init(struct ntfy_object *no) * ntfy_delete() - delete list of nofy events registered. * @ntfy_obj: Pointer to the ntfy object structure. * - * This function is used to remove all the notify events registered. + * This function is used to remove all the notify events registered. * unregister function is not needed in this function, to unregister * a ntfy_event please look at ntfy_register function. * diff --git a/trunk/drivers/staging/tidspbridge/include/dspbridge/proc.h b/trunk/drivers/staging/tidspbridge/include/dspbridge/proc.h index 851b356d7a51..a82380ebc041 100644 --- a/trunk/drivers/staging/tidspbridge/include/dspbridge/proc.h +++ b/trunk/drivers/staging/tidspbridge/include/dspbridge/proc.h @@ -263,7 +263,7 @@ extern int proc_get_processor_id(void *proc, u32 * proc_id); * Returns: * 0 : Success. * -EFAULT : Invalid processor handle. - * -EPERM : General failure while retrieving processor trace + * -EPERM : General failure while retireving processor trace * Buffer. * Requires: * pbuf is not NULL diff --git a/trunk/drivers/staging/tidspbridge/include/dspbridge/strm.h b/trunk/drivers/staging/tidspbridge/include/dspbridge/strm.h index 97aee4c63d24..dacf0c234fd1 100644 --- a/trunk/drivers/staging/tidspbridge/include/dspbridge/strm.h +++ b/trunk/drivers/staging/tidspbridge/include/dspbridge/strm.h @@ -203,7 +203,7 @@ extern int strm_issue(struct strm_object *stream_obj, u8 * pbuf, * index: Stream index. * pattr: Pointer to structure containing attributes to be * applied to stream. Cannot be NULL. - * strmres: Location to store stream resource info handle on output. + * strmres: Location to store stream resuorce info handle on output. * Returns: * 0: Success. * -EFAULT: Invalid hnode. diff --git a/trunk/drivers/staging/tidspbridge/include/dspbridge/sync.h b/trunk/drivers/staging/tidspbridge/include/dspbridge/sync.h index 58a0d5c5543d..b1e75eb8847c 100644 --- a/trunk/drivers/staging/tidspbridge/include/dspbridge/sync.h +++ b/trunk/drivers/staging/tidspbridge/include/dspbridge/sync.h @@ -78,7 +78,7 @@ void sync_set_event(struct sync_object *event); * @event: events to wait for it. * @timeout timeout on waiting for the evetn. * - * This function will wait until @event is set or until timeout. In case of + * This functios will wait until @event is set or until timeout. In case of * success the function will return 0 and * in case of timeout the function will return -ETIME * in case of signal the function will return -ERESTARTSYS @@ -106,7 +106,7 @@ static inline int sync_wait_on_event(struct sync_object *event, * @timeout timeout on waiting for the evetns. * @pu_index index of the event set. * - * This function will wait until any of the array element is set or until + * This functios will wait until any of the array element is set or until * timeout. In case of success the function will return 0 and * @pu_index will store the index of the array element set and in case * of timeout the function will return -ETIME. diff --git a/trunk/drivers/staging/tidspbridge/include/dspbridge/uuidutil.h b/trunk/drivers/staging/tidspbridge/include/dspbridge/uuidutil.h index 414bf71d652d..9a994753e9ba 100644 --- a/trunk/drivers/staging/tidspbridge/include/dspbridge/uuidutil.h +++ b/trunk/drivers/staging/tidspbridge/include/dspbridge/uuidutil.h @@ -21,6 +21,26 @@ #define MAXUUIDLEN 37 +/* + * ======== uuid_uuid_to_string ======== + * Purpose: + * Converts a dsp_uuid to an ANSI string. + * Parameters: + * uuid_obj: Pointer to a dsp_uuid object. + * sz_uuid: Pointer to a buffer to receive a NULL-terminated UUID + * string. + * size: Maximum size of the sz_uuid string. + * Returns: + * Requires: + * uuid_obj & sz_uuid are non-NULL values. + * Ensures: + * Lenghth of sz_uuid is less than MAXUUIDLEN. + * Details: + * UUID string limit currently set at MAXUUIDLEN. + */ +void uuid_uuid_to_string(struct dsp_uuid *uuid_obj, char *sz_uuid, + s32 size); + /* * ======== uuid_uuid_from_string ======== * Purpose: diff --git a/trunk/drivers/staging/tidspbridge/rmgr/dbdcd.c b/trunk/drivers/staging/tidspbridge/rmgr/dbdcd.c index 9d52c3cb92f0..12a1d34b3954 100644 --- a/trunk/drivers/staging/tidspbridge/rmgr/dbdcd.c +++ b/trunk/drivers/staging/tidspbridge/rmgr/dbdcd.c @@ -346,13 +346,11 @@ int dcd_get_object_def(struct dcd_manager *hdcd_mgr, struct dcd_manager *dcd_mgr_obj = hdcd_mgr; /* ptr to DCD mgr */ struct cod_libraryobj *lib = NULL; int status = 0; - int len; u32 ul_addr = 0; /* Used by cod_get_section */ u32 ul_len = 0; /* Used by cod_get_section */ u32 dw_buf_size; /* Used by REG functions */ char sz_reg_key[DCD_MAXPATHLENGTH]; char *sz_uuid; /*[MAXUUIDLEN]; */ - char *tmp; struct dcd_key_elem *dcd_key = NULL; char sz_sect_name[MAXUUIDLEN + 2]; /* ".[UUID]\0" */ char *psz_coff_buf; @@ -397,7 +395,7 @@ int dcd_get_object_def(struct dcd_manager *hdcd_mgr, } /* Create UUID value to set in registry. */ - snprintf(sz_uuid, MAXUUIDLEN, "%pUL", obj_uuid); + uuid_uuid_to_string(obj_uuid, sz_uuid, MAXUUIDLEN); if ((strlen(sz_reg_key) + MAXUUIDLEN) < DCD_MAXPATHLENGTH) strncat(sz_reg_key, sz_uuid, MAXUUIDLEN); @@ -431,27 +429,12 @@ int dcd_get_object_def(struct dcd_manager *hdcd_mgr, } /* Ensure sz_uuid + 1 is not greater than sizeof sz_sect_name. */ - len = strlen(sz_uuid); - if (len + 1 > sizeof(sz_sect_name)) { - status = -EPERM; - goto func_end; - } /* Create section name based on node UUID. A period is * pre-pended to the UUID string to form the section name. * I.e. ".24BC8D90_BB45_11d4_B756_006008BDB66F" */ - - len -= 4; /* uuid has 4 delimiters '-' */ - tmp = sz_uuid; - strncpy(sz_sect_name, ".", 2); - do { - char *uuid = strsep(&tmp, "-"); - if (!uuid) - break; - len -= strlen(uuid); - strncat(sz_sect_name, uuid, strlen(uuid) + 1); - } while (len && strncat(sz_sect_name, "_", 2)); + strncat(sz_sect_name, sz_uuid, strlen(sz_uuid)); /* Get section information. */ status = cod_get_section(lib, sz_sect_name, &ul_addr, &ul_len); @@ -480,7 +463,7 @@ int dcd_get_object_def(struct dcd_manager *hdcd_mgr, status = cod_read_section(lib, sz_sect_name, psz_coff_buf, ul_len); #endif if (!status) { - /* Compress DSP buffer to conform to PC format. */ + /* Compres DSP buffer to conform to PC format. */ if (strstr(dcd_key->path, "iva") == NULL) { compress_buf(psz_coff_buf, ul_len, DSPWORDSIZE); } else { @@ -683,7 +666,7 @@ int dcd_get_library_name(struct dcd_manager *hdcd_mgr, status = -EPERM; } /* Create UUID value to find match in registry. */ - snprintf(sz_uuid, MAXUUIDLEN, "%pUL", uuid_obj); + uuid_uuid_to_string(uuid_obj, sz_uuid, MAXUUIDLEN); if ((strlen(sz_reg_key) + MAXUUIDLEN) < DCD_MAXPATHLENGTH) strncat(sz_reg_key, sz_uuid, MAXUUIDLEN); else @@ -723,7 +706,7 @@ int dcd_get_library_name(struct dcd_manager *hdcd_mgr, } else { status = -EPERM; } - snprintf(sz_uuid, MAXUUIDLEN, "%pUL", uuid_obj); + uuid_uuid_to_string(uuid_obj, sz_uuid, MAXUUIDLEN); if ((strlen(sz_reg_key) + MAXUUIDLEN) < DCD_MAXPATHLENGTH) strncat(sz_reg_key, sz_uuid, MAXUUIDLEN); else @@ -814,7 +797,7 @@ int dcd_register_object(struct dsp_uuid *uuid_obj, status = -EPERM; /* Create UUID value to set in registry. */ - snprintf(sz_uuid, MAXUUIDLEN, "%pUL", uuid_obj); + uuid_uuid_to_string(uuid_obj, sz_uuid, MAXUUIDLEN); if ((strlen(sz_reg_key) + MAXUUIDLEN) < DCD_MAXPATHLENGTH) strncat(sz_reg_key, sz_uuid, MAXUUIDLEN); else diff --git a/trunk/drivers/staging/tidspbridge/rmgr/drv_interface.c b/trunk/drivers/staging/tidspbridge/rmgr/drv_interface.c index 6acea2b56aa4..3cac01492063 100644 --- a/trunk/drivers/staging/tidspbridge/rmgr/drv_interface.c +++ b/trunk/drivers/staging/tidspbridge/rmgr/drv_interface.c @@ -613,6 +613,16 @@ static struct platform_driver bridge_driver = { #endif }; +static int __init bridge_init(void) +{ + return platform_driver_register(&bridge_driver); +} + +static void __exit bridge_exit(void) +{ + platform_driver_unregister(&bridge_driver); +} + /* To remove all process resources before removing the process from the * process context list */ int drv_remove_all_resources(void *process_ctxt) @@ -626,4 +636,6 @@ int drv_remove_all_resources(void *process_ctxt) return status; } -module_platform_driver(bridge_driver); +/* Bridge driver initialization and de-initialization functions */ +module_init(bridge_init); +module_exit(bridge_exit); diff --git a/trunk/drivers/staging/tidspbridge/rmgr/dspdrv.c b/trunk/drivers/staging/tidspbridge/rmgr/dspdrv.c index d460f5823c6b..dc767b183cdf 100644 --- a/trunk/drivers/staging/tidspbridge/rmgr/dspdrv.c +++ b/trunk/drivers/staging/tidspbridge/rmgr/dspdrv.c @@ -72,7 +72,7 @@ u32 dsp_init(u32 *init_status) /* Unwind whatever was loaded */ if (status) { - /* irrespective of the status of dev_remove_device we continue + /* irrespective of the status of dev_remove_device we conitinue * unloading. Get the Driver Object iterate through and remove. * Reset the status to E_FAIL to avoid going through * api_init_complete2. */ @@ -92,7 +92,7 @@ u32 dsp_init(u32 *init_status) func_cont: /* Attempt to Start the Board */ if (!status) { - /* BRD_AutoStart could fail if the dsp executable is not the + /* BRD_AutoStart could fail if the dsp execuetable is not the * correct one. We should not propagate that error * into the device loader. */ (void)api_init_complete2(); diff --git a/trunk/drivers/staging/tidspbridge/rmgr/mgr.c b/trunk/drivers/staging/tidspbridge/rmgr/mgr.c index b32ba0ad2a07..8a1e9287cff6 100644 --- a/trunk/drivers/staging/tidspbridge/rmgr/mgr.c +++ b/trunk/drivers/staging/tidspbridge/rmgr/mgr.c @@ -262,8 +262,8 @@ int mgr_enum_processor_info(u32 processor_id, IVAPROCTYPE_ARM7) proc_detect = true; } - /* User applications only check for chip type, so - * this is a clumsy overwrite */ + /* User applciatiuons aonly check for chip type, so + * this clumsy overwrite */ processor_info->processor_type = DSPTYPE64; } else { dev_dbg(bridge, "%s: Failed to get DCD processor info " diff --git a/trunk/drivers/staging/tidspbridge/rmgr/nldr.c b/trunk/drivers/staging/tidspbridge/rmgr/nldr.c index 6309221b64a5..30d5480fcdcc 100644 --- a/trunk/drivers/staging/tidspbridge/rmgr/nldr.c +++ b/trunk/drivers/staging/tidspbridge/rmgr/nldr.c @@ -898,7 +898,7 @@ static int add_ovly_info(void *handle, struct dbll_sect_info *sect_info, nldr_obj->ovly_table[i].execute_sects++; } else { - /* Put in "other" sections */ + /* Put in "other" sectins */ status = add_ovly_sect(nldr_obj, &nldr_obj-> diff --git a/trunk/drivers/staging/tidspbridge/rmgr/node.c b/trunk/drivers/staging/tidspbridge/rmgr/node.c index c2fc6137c770..7fb426c5251c 100644 --- a/trunk/drivers/staging/tidspbridge/rmgr/node.c +++ b/trunk/drivers/staging/tidspbridge/rmgr/node.c @@ -1613,7 +1613,7 @@ int node_get_attr(struct node_object *hnode, return -EFAULT; hnode_mgr = hnode->node_mgr; - /* Enter hnode_mgr critical section since we're accessing + /* Enter hnode_mgr critical section (since we're accessing * data that could be changed by node_change_priority() and * node_connect(). */ mutex_lock(&hnode_mgr->node_mgr_lock); @@ -2714,7 +2714,8 @@ static int get_node_props(struct dcd_manager *hdcd_mgr, hnode->ntype = node_type = pndb_props->ntype; /* Create UUID value to set in registry. */ - snprintf(sz_uuid, MAXUUIDLEN, "%pUL", node_uuid); + uuid_uuid_to_string((struct dsp_uuid *)node_uuid, sz_uuid, + MAXUUIDLEN); dev_dbg(bridge, "(node) UUID: %s\n", sz_uuid); /* Fill in message args that come from NDB */ diff --git a/trunk/drivers/staging/tidspbridge/rmgr/proc.c b/trunk/drivers/staging/tidspbridge/rmgr/proc.c index 5e43938ab7fa..7e4f12f6be42 100644 --- a/trunk/drivers/staging/tidspbridge/rmgr/proc.c +++ b/trunk/drivers/staging/tidspbridge/rmgr/proc.c @@ -300,7 +300,7 @@ proc_attach(u32 processor_id, if (status) goto func_end; - /* If we made it this far, create the Processor object: */ + /* If we made it this far, create the Proceesor object: */ p_proc_object = kzalloc(sizeof(struct proc_object), GFP_KERNEL); /* Fill out the Processor Object: */ if (p_proc_object == NULL) { diff --git a/trunk/drivers/staging/usbip/Kconfig b/trunk/drivers/staging/usbip/Kconfig index 199b1d4c0b85..dd13c0220681 100644 --- a/trunk/drivers/staging/usbip/Kconfig +++ b/trunk/drivers/staging/usbip/Kconfig @@ -1,6 +1,6 @@ config USBIP_CORE - tristate "USB/IP support" - depends on USB && NET + tristate "USB/IP support (EXPERIMENTAL)" + depends on USB && NET && EXPERIMENTAL default N ---help--- This enables pushing USB packets over IP to allow remote diff --git a/trunk/drivers/staging/usbip/stub_dev.c b/trunk/drivers/staging/usbip/stub_dev.c index c8d79a7f0e0e..92ced35e6b7f 100644 --- a/trunk/drivers/staging/usbip/stub_dev.c +++ b/trunk/drivers/staging/usbip/stub_dev.c @@ -187,14 +187,10 @@ static void stub_shutdown_connection(struct usbip_device *ud) } /* 1. stop threads */ - if (ud->tcp_rx) { + if (ud->tcp_rx) kthread_stop_put(ud->tcp_rx); - ud->tcp_rx = NULL; - } - if (ud->tcp_tx) { + if (ud->tcp_tx) kthread_stop_put(ud->tcp_tx); - ud->tcp_tx = NULL; - } /* * 2. close the socket diff --git a/trunk/drivers/staging/usbip/stub_rx.c b/trunk/drivers/staging/usbip/stub_rx.c index 694cfd7596f3..1d5b3fc62160 100644 --- a/trunk/drivers/staging/usbip/stub_rx.c +++ b/trunk/drivers/staging/usbip/stub_rx.c @@ -155,7 +155,7 @@ static int tweak_set_configuration_cmd(struct urb *urb) * eventually reassigned to the device as far as driver matching * condition is kept. * - * Unfortunately, an existing usbip connection will be dropped + * Unfortunatelly, an existing usbip connection will be dropped * due to this driver unbinding. So, skip here. * A user may need to set a special configuration value before * exporting the device. diff --git a/trunk/drivers/staging/usbip/usbip_common.c b/trunk/drivers/staging/usbip/usbip_common.c index 891984238cdc..70f230269329 100644 --- a/trunk/drivers/staging/usbip/usbip_common.c +++ b/trunk/drivers/staging/usbip/usbip_common.c @@ -22,9 +22,7 @@ #include #include #include -#include #include -#include #include #include "usbip_common.h" @@ -38,8 +36,6 @@ unsigned long usbip_debug_flag = 0xffffffff; unsigned long usbip_debug_flag; #endif EXPORT_SYMBOL_GPL(usbip_debug_flag); -module_param(usbip_debug_flag, ulong, S_IRUGO|S_IWUSR); -MODULE_PARM_DESC(usbip_debug_flag, "debug flags (defined in usbip_common.h)"); /* FIXME */ struct device_attribute dev_attr_usbip_debug; diff --git a/trunk/drivers/staging/usbip/userspace/configure.ac b/trunk/drivers/staging/usbip/userspace/configure.ac index 43e641e5ac06..bf5cf49cb554 100644 --- a/trunk/drivers/staging/usbip/userspace/configure.ac +++ b/trunk/drivers/staging/usbip/userspace/configure.ac @@ -56,11 +56,11 @@ AC_ARG_WITH([tcp-wrappers], [AS_HELP_STRING([--with-tcp-wrappers], [use the libwrap (TCP wrappers) library])], dnl [ACTION-IF-GIVEN] - [if test "$withval" = "yes"; then + [saved_LIBS="$LIBS" + if test "$withval" = "yes"; then AC_MSG_RESULT([yes]) AC_MSG_CHECKING([for hosts_access in -lwrap]) - saved_LIBS="$LIBS" - LIBS="-lwrap $saved_LIBS" + LIBS="-lwrap $LIBS" AC_TRY_LINK( [int hosts_access(); int allow_severity, deny_severity;], [hosts_access()], @@ -69,9 +69,9 @@ AC_ARG_WITH([tcp-wrappers], [use tcp wrapper]) wrap_LIB="-lwrap"], [AC_MSG_RESULT([not found]); exit 1]) else - AC_MSG_RESULT([no]); - LIBS="$saved_LIBS" - fi], + AC_MSG_RESULT([no]) + fi + LIBS="$saved_LIBS"], dnl [ACTION-IF-NOT-GIVEN] [AC_MSG_RESULT([(default)]) AC_MSG_CHECKING([for hosts_access in -lwrap]) diff --git a/trunk/drivers/staging/usbip/userspace/doc/usbip.8 b/trunk/drivers/staging/usbip/userspace/doc/usbip.8 index 6e0d74503792..1653bb2cd7d1 100644 --- a/trunk/drivers/staging/usbip/userspace/doc/usbip.8 +++ b/trunk/drivers/staging/usbip/userspace/doc/usbip.8 @@ -3,87 +3,69 @@ usbip \- manage USB/IP devices .SH SYNOPSIS .B usbip -[\foptions\R] <\fIcommand\fR> <\fIargs\fR> +[\fIoptions\fR] .SH DESCRIPTION -On a USB/IP server, devices can be listed, bound, and unbound using -this program. On a USB/IP client, devices exported by USB/IP servers -can be listed, attached and detached. +Devices exported by USB/IP servers can be listed, attached and +detached using this program. .SH OPTIONS .HP -\fB\-\-debug\fR +\fB\-a\fR, \fB\-\-attach\fR .IP -Print debugging information. -.PP - -.HP -\fB\-\-log\fR -.IP -Log to syslog. -.PP - -.SH COMMANDS -.HP -\fBversion\fR -.IP -Show version and exit. +Attach a remote USB device. .PP .HP -\fBhelp\fR [\fIcommand\fR] +\fB\-x\fR, \fB\-\-attachall\fR .IP -Print the program help message, or help on a specific command, and -then exit. +Attach all remote USB devices on the specific host. .PP .HP -\fBattach\fR \-\-host=<\fIhost\fR> \-\-busid=<\fIbus_id\fR> -.IP -Attach a remote USB device. -.PP - -.HP -\fBdetach\fR \-\-port=<\fIport\fR> +\fB\-d\fR, \fB\-\-detach\fR .IP Detach an imported USB device. .PP .HP -\fBbind\fR \-\-busid=<\fIbusid\fR> +\fB\-l\fR, \fB\-\-list\fR .IP -Make a device exportable. +List exported USB devices. .PP .HP -\fBunbind\fR \-\-busid=<\fIbusid\fR> +\fB\-p\fR, \fB\-\-port\fR .IP -Stop exporting a device so it can be used by a local driver. +List virtual USB port status. .PP .HP -\fBlist\fR \-\-remote=<\fIhost\fR> +\fB\-D\fR, \fB\-\-debug\fR .IP -List USB devices exported by a remote host. +Print debugging information. .PP .HP -\fBlist\fR \-\-local +\fB\-v\fR, \fB\-\-version\fR .IP -List local USB devices. +Show version. .PP - .SH EXAMPLES - client:# usbip list --remote=server + client:# usbip --list server - List exportable usb devices on the server. - client:# usbip attach --host=server --busid=1-2 + client:# usbip --attach server 1-2 - Connect the remote USB device. - client:# usbip detach --port=0 + client:# usbip --port + - Show virtual port status. + + client:# usbip --detach 0 - Detach the usb device. .SH "SEE ALSO" -\fBusbipd\fP\fB(8)\fB\fP +\fBusbipd\fP\fB(8)\fB\fP, +\fBusbip_attach_driver\fP\fB(8)\fB\fP diff --git a/trunk/drivers/staging/usbip/userspace/doc/usbip_bind_driver.8 b/trunk/drivers/staging/usbip/userspace/doc/usbip_bind_driver.8 new file mode 100644 index 000000000000..d43bbd6be934 --- /dev/null +++ b/trunk/drivers/staging/usbip/userspace/doc/usbip_bind_driver.8 @@ -0,0 +1,42 @@ +.TH USBIP_BIND_DRIVER "8" "February 2009" "usbip" "System Administration Utilities" +.SH NAME +usbip_bind_driver \- change driver binding for USB/IP + +.SH SYNOPSIS +.B usbip_bind_driver +[\fIoptions\fR] + +.SH DESCRIPTION +Driver bindings for USB devices can be changed using +this program. It is used to export and unexport USB +devices over USB/IP. + +.SH OPTIONS +.TP +\fB\-u\fR, \fB\-\-usbip\fR +Make a device exportable +.TP +\fB\-o\fR, \fB\-\-other\fR +Use a device by a local driver +.TP +\fB\-l\fR, \fB\-\-list\fR +Print usb devices and their drivers +.TP +\fB\-L\fR, \fB\-\-list2\fR +Print usb devices and their drivers in parseable mode + +.SH EXAMPLES + + server:# usbip_bind_driver --list + - List driver assignments for usb devices. + + server:# usbip_bind_driver --usbip 1-2 + - Bind usbip-host.ko to the device of busid 1-2. + - A usb device 1-2 is now exportable to other hosts! + + server:# usbip_bind_driver --other 1-2 + - Shutdown exporting and use the device locally. + +.SH "SEE ALSO" +\fBusbip\fP\fB(8)\fB\fP, +\fBusbipd\fP\fB(8)\fB\fP diff --git a/trunk/drivers/staging/usbip/userspace/doc/usbipd.8 b/trunk/drivers/staging/usbip/userspace/doc/usbipd.8 index d896936f1780..006559f1df25 100644 --- a/trunk/drivers/staging/usbip/userspace/doc/usbipd.8 +++ b/trunk/drivers/staging/usbip/userspace/doc/usbipd.8 @@ -10,7 +10,7 @@ usbipd \- USB/IP server daemon provides USB/IP clients access to exported USB devices. Devices have to explicitly be exported using -.B usbip bind +.B usbip_bind_driver before usbipd makes them available to other hosts. The daemon accepts connections from USB/IP clients @@ -29,11 +29,6 @@ Run as a daemon process. Print debugging information. .PP -\fB\-h\fR, \fB\-\-help\fR -.IP -Print the program help message and exit. -.PP - .HP \fB\-v\fR, \fB\-\-version\fR .IP @@ -53,14 +48,15 @@ USB/IP client can connect and use exported devices. server:# usbipd -D - Start usbip daemon. - server:# usbip list --local + server:# usbip_bind_driver --list - List driver assignments for usb devices. - server:# usbip bind --busid=1-2 + server:# usbip_bind_driver --usbip 1-2 - Bind usbip-host.ko to the device of busid 1-2. - A usb device 1-2 is now exportable to other hosts! - - Use 'usbip unbind --busid=1-2' when you want to shutdown exporting and use the device locally. + - Use 'usbip_bind_driver --other 1-2' when you want to shutdown exporting and use the device locally. .SH "SEE ALSO" -\fBusbip\fP\fB(8)\fB\fP +\fBusbip\fP\fB(8)\fB\fP, +\fBusbip_attach_driver\fP\fB(8)\fB\fP diff --git a/trunk/drivers/staging/usbip/vhci_hcd.c b/trunk/drivers/staging/usbip/vhci_hcd.c index 620d1beb4587..12a9a5fbc797 100644 --- a/trunk/drivers/staging/usbip/vhci_hcd.c +++ b/trunk/drivers/staging/usbip/vhci_hcd.c @@ -220,7 +220,7 @@ static int vhci_hub_status(struct usb_hcd *hcd, char *buf) pr_info("changed %d\n", changed); - if ((hcd->state == HC_STATE_SUSPENDED) && (changed == 1)) + if (hcd->state == HC_STATE_SUSPENDED) usb_hcd_resume_root_hub(hcd); done: @@ -749,7 +749,6 @@ static void vhci_device_unlink_cleanup(struct vhci_device *vdev) { struct vhci_unlink *unlink, *tmp; - spin_lock(&the_controller->lock); spin_lock(&vdev->priv_lock); list_for_each_entry_safe(unlink, tmp, &vdev->unlink_tx, list) { @@ -758,12 +757,9 @@ static void vhci_device_unlink_cleanup(struct vhci_device *vdev) kfree(unlink); } - while (!list_empty(&vdev->unlink_rx)) { + list_for_each_entry_safe(unlink, tmp, &vdev->unlink_rx, list) { struct urb *urb; - unlink = list_first_entry(&vdev->unlink_rx, struct vhci_unlink, - list); - /* give back URB of unanswered unlink request */ pr_info("unlink cleanup rx %lu\n", unlink->unlink_seqnum); @@ -778,24 +774,18 @@ static void vhci_device_unlink_cleanup(struct vhci_device *vdev) urb->status = -ENODEV; + spin_lock(&the_controller->lock); usb_hcd_unlink_urb_from_ep(vhci_to_hcd(the_controller), urb); - - list_del(&unlink->list); - - spin_unlock(&vdev->priv_lock); spin_unlock(&the_controller->lock); usb_hcd_giveback_urb(vhci_to_hcd(the_controller), urb, urb->status); - spin_lock(&the_controller->lock); - spin_lock(&vdev->priv_lock); - + list_del(&unlink->list); kfree(unlink); } spin_unlock(&vdev->priv_lock); - spin_unlock(&the_controller->lock); } /* @@ -814,14 +804,11 @@ static void vhci_shutdown_connection(struct usbip_device *ud) } /* kill threads related to this sdev, if v.c. exists */ - if (vdev->ud.tcp_rx) { + if (vdev->ud.tcp_rx) kthread_stop_put(vdev->ud.tcp_rx); - vdev->ud.tcp_rx = NULL; - } - if (vdev->ud.tcp_tx) { + if (vdev->ud.tcp_tx) kthread_stop_put(vdev->ud.tcp_tx); - vdev->ud.tcp_tx = NULL; - } + pr_info("stop threads\n"); /* active connection is closed */ @@ -841,11 +828,11 @@ static void vhci_shutdown_connection(struct usbip_device *ud) * disable endpoints. pending urbs are unlinked(dequeued). * * NOTE: After calling rh_port_disconnect(), the USB device drivers of a - * detached device should release used urbs in a cleanup function (i.e. + * deteched device should release used urbs in a cleanup function(i.e. * xxx_disconnect()). Therefore, vhci_hcd does not need to release * pushed urbs and their private data in this function. * - * NOTE: vhci_dequeue() must be considered carefully. When shutting down + * NOTE: vhci_dequeue() must be considered carefully. When shutdowning * a connection, vhci_shutdown_connection() expects vhci_dequeue() * gives back pushed urbs and frees their private data by request of * the cleanup function of a USB driver. When unlinking a urb with an diff --git a/trunk/drivers/staging/vme/devices/vme_pio2_core.c b/trunk/drivers/staging/vme/devices/vme_pio2_core.c index dad8281915bf..4bf8e05ac312 100644 --- a/trunk/drivers/staging/vme/devices/vme_pio2_core.c +++ b/trunk/drivers/staging/vme/devices/vme_pio2_core.c @@ -10,8 +10,6 @@ * option) any later version. */ -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - #include #include #include @@ -165,13 +163,15 @@ static int __init pio2_init(void) int retval = 0; if (bus_num == 0) { - pr_err("No cards, skipping registration\n"); + printk(KERN_ERR "%s: No cards, skipping registration\n", + driver_name); goto err_nocard; } if (bus_num > PIO2_CARDS_MAX) { - pr_err("Driver only able to handle %d PIO2 Cards\n", - PIO2_CARDS_MAX); + printk(KERN_ERR + "%s: Driver only able to handle %d PIO2 Cards\n", + driver_name, PIO2_CARDS_MAX); bus_num = PIO2_CARDS_MAX; } diff --git a/trunk/drivers/staging/vme/devices/vme_user.c b/trunk/drivers/staging/vme/devices/vme_user.c index c3f94f311ca7..e25645e226e3 100644 --- a/trunk/drivers/staging/vme/devices/vme_user.c +++ b/trunk/drivers/staging/vme/devices/vme_user.c @@ -64,13 +64,13 @@ static unsigned int bus_num; * * However the VME driver at http://www.vmelinux.org/ is rather old and doesn't * even support the tsi148 chipset (which has 8 master and 8 slave windows). - * We'll run with this for now as far as possible, however it probably makes + * We'll run with this or now as far as possible, however it probably makes * sense to get rid of the old mappings and just do everything dynamically. * * So for now, we'll restrict the driver to providing 4 masters and 4 slaves as * defined above and try to support at least some of the interface from - * http://www.vmelinux.org/ as an alternative the driver can be written - * providing a saner interface later. + * http://www.vmelinux.org/ as an alternative drive can be written providing a + * saner interface later. * * The vmelinux.org driver never supported slave images, the devices reserved * for slaves were repurposed to support all 8 master images on the UniverseII! @@ -242,7 +242,7 @@ static ssize_t resource_to_user(int minor, char __user *buf, size_t count, } /* - * We are going to alloc a page during init per window for small transfers. + * We are going ot alloc a page during init per window for small transfers. * Small transfers will go user space -> buffer -> VME. Larger (more than a * page) transfers will lock the user space buffer into memory and then * transfer the data directly from the user space buffers out to VME. @@ -396,7 +396,7 @@ static ssize_t vme_user_write(struct file *file, const char __user *buf, default: retval = -EINVAL; } - + mutex_unlock(&image[minor].mutex); if (retval > 0) diff --git a/trunk/drivers/staging/vt6655/80211mgr.h b/trunk/drivers/staging/vt6655/80211mgr.h index 65780f28db41..3bdab3f56f1c 100644 --- a/trunk/drivers/staging/vt6655/80211mgr.h +++ b/trunk/drivers/staging/vt6655/80211mgr.h @@ -186,7 +186,7 @@ // -// Cipher Suite Selectors defined in 802.11i +// Cipher Suite Selectors defiened in 802.11i // #define WLAN_11i_CSS_USE_GROUP 0 #define WLAN_11i_CSS_WEP40 1 diff --git a/trunk/drivers/staging/vt6655/baseband.c b/trunk/drivers/staging/vt6655/baseband.c index 8d2c6a789ab2..e7b93a21e3b2 100644 --- a/trunk/drivers/staging/vt6655/baseband.c +++ b/trunk/drivers/staging/vt6655/baseband.c @@ -28,8 +28,8 @@ * Functions: * BBuGetFrameTime - Calculate data frame transmitting time * BBvCaculateParameter - Caculate PhyLength, PhyService and Phy Signal parameter for baseband Tx - * BBbReadEmbedded - Embedded read baseband register via MAC - * BBbWriteEmbedded - Embedded write baseband register via MAC + * BBbReadEmbeded - Embeded read baseband register via MAC + * BBbWriteEmbeded - Embeded write baseband register via MAC * BBbIsRegBitsOn - Test if baseband register bits on * BBbIsRegBitsOff - Test if baseband register bits off * BBbVT3253Init - VIA VT3253 baseband chip init code @@ -40,7 +40,7 @@ * Revision History: * 06-10-2003 Bryan YC Fan: Re-write codes to support VT3253 spec. * 08-07-2003 Bryan YC Fan: Add MAXIM2827/2825 and RFMD2959 support. - * 08-26-2003 Kyle Hsu : Modify BBuGetFrameTime() and BBvCalculateParameter(). + * 08-26-2003 Kyle Hsu : Modify BBuGetFrameTime() and BBvCaculateParameter(). * cancel the setting of MAC_REG_SOFTPWRCTL on BBbVT3253Init(). * Add the comments. * 09-01-2003 Bryan YC Fan: RF & BB tables updated. @@ -1826,7 +1826,7 @@ BBuGetFrameTime ( } /* - * Description: Calculate Length, Service, and Signal fields of Phy for Tx + * Description: Caculate Length, Service, and Signal fields of Phy for Tx * * Parameters: * In: @@ -1842,7 +1842,7 @@ BBuGetFrameTime ( * */ void -BBvCalculateParameter ( +BBvCaculateParameter ( PSDevice pDevice, unsigned int cbFrameLength, unsigned short wRate, @@ -2001,7 +2001,7 @@ BBvCalculateParameter ( } /* - * Description: Read a byte from BASEBAND, by embedded programming + * Description: Read a byte from BASEBAND, by embeded programming * * Parameters: * In: @@ -2013,7 +2013,7 @@ BBvCalculateParameter ( * Return Value: true if succeeded; false if failed. * */ -bool BBbReadEmbedded (unsigned long dwIoBase, unsigned char byBBAddr, unsigned char *pbyData) +bool BBbReadEmbeded (unsigned long dwIoBase, unsigned char byBBAddr, unsigned char *pbyData) { unsigned short ww; unsigned char byValue; @@ -2043,7 +2043,7 @@ bool BBbReadEmbedded (unsigned long dwIoBase, unsigned char byBBAddr, unsigned c /* - * Description: Write a Byte to BASEBAND, by embedded programming + * Description: Write a Byte to BASEBAND, by embeded programming * * Parameters: * In: @@ -2056,7 +2056,7 @@ bool BBbReadEmbedded (unsigned long dwIoBase, unsigned char byBBAddr, unsigned c * Return Value: true if succeeded; false if failed. * */ -bool BBbWriteEmbedded (unsigned long dwIoBase, unsigned char byBBAddr, unsigned char byData) +bool BBbWriteEmbeded (unsigned long dwIoBase, unsigned char byBBAddr, unsigned char byData) { unsigned short ww; unsigned char byValue; @@ -2102,7 +2102,7 @@ bool BBbIsRegBitsOn (unsigned long dwIoBase, unsigned char byBBAddr, unsigned ch { unsigned char byOrgData; - BBbReadEmbedded(dwIoBase, byBBAddr, &byOrgData); + BBbReadEmbeded(dwIoBase, byBBAddr, &byOrgData); return (byOrgData & byTestBits) == byTestBits; } @@ -2125,7 +2125,7 @@ bool BBbIsRegBitsOff (unsigned long dwIoBase, unsigned char byBBAddr, unsigned c { unsigned char byOrgData; - BBbReadEmbedded(dwIoBase, byBBAddr, &byOrgData); + BBbReadEmbeded(dwIoBase, byBBAddr, &byOrgData); return (byOrgData & byTestBits) == 0; } @@ -2155,14 +2155,14 @@ bool BBbVT3253Init (PSDevice pDevice) if (byRFType == RF_RFMD2959) { if (byLocalID <= REV_ID_VT3253_A1) { for (ii = 0; ii < CB_VT3253_INIT_FOR_RFMD; ii++) { - bResult &= BBbWriteEmbedded(dwIoBase,byVT3253InitTab_RFMD[ii][0],byVT3253InitTab_RFMD[ii][1]); + bResult &= BBbWriteEmbeded(dwIoBase,byVT3253InitTab_RFMD[ii][0],byVT3253InitTab_RFMD[ii][1]); } } else { for (ii = 0; ii < CB_VT3253B0_INIT_FOR_RFMD; ii++) { - bResult &= BBbWriteEmbedded(dwIoBase,byVT3253B0_RFMD[ii][0],byVT3253B0_RFMD[ii][1]); + bResult &= BBbWriteEmbeded(dwIoBase,byVT3253B0_RFMD[ii][0],byVT3253B0_RFMD[ii][1]); } for (ii = 0; ii < CB_VT3253B0_AGC_FOR_RFMD2959; ii++) { - bResult &= BBbWriteEmbedded(dwIoBase,byVT3253B0_AGC4_RFMD2959[ii][0],byVT3253B0_AGC4_RFMD2959[ii][1]); + bResult &= BBbWriteEmbeded(dwIoBase,byVT3253B0_AGC4_RFMD2959[ii][0],byVT3253B0_AGC4_RFMD2959[ii][1]); } VNSvOutPortD(dwIoBase + MAC_REG_ITRTMSET, 0x23); MACvRegBitsOn(dwIoBase, MAC_REG_PAPEDELAY, BIT0); @@ -2177,10 +2177,10 @@ bool BBbVT3253Init (PSDevice pDevice) pDevice->ldBmThreshold[3] = 0; } else if ((byRFType == RF_AIROHA) || (byRFType == RF_AL2230S) ) { for (ii = 0; ii < CB_VT3253B0_INIT_FOR_AIROHA2230; ii++) { - bResult &= BBbWriteEmbedded(dwIoBase,byVT3253B0_AIROHA2230[ii][0],byVT3253B0_AIROHA2230[ii][1]); + bResult &= BBbWriteEmbeded(dwIoBase,byVT3253B0_AIROHA2230[ii][0],byVT3253B0_AIROHA2230[ii][1]); } for (ii = 0; ii < CB_VT3253B0_AGC; ii++) { - bResult &= BBbWriteEmbedded(dwIoBase,byVT3253B0_AGC[ii][0],byVT3253B0_AGC[ii][1]); + bResult &= BBbWriteEmbeded(dwIoBase,byVT3253B0_AGC[ii][0],byVT3253B0_AGC[ii][1]); } pDevice->abyBBVGA[0] = 0x1C; pDevice->abyBBVGA[1] = 0x10; @@ -2192,10 +2192,10 @@ bool BBbVT3253Init (PSDevice pDevice) pDevice->ldBmThreshold[3] = 0; } else if (byRFType == RF_UW2451) { for (ii = 0; ii < CB_VT3253B0_INIT_FOR_UW2451; ii++) { - bResult &= BBbWriteEmbedded(dwIoBase,byVT3253B0_UW2451[ii][0],byVT3253B0_UW2451[ii][1]); + bResult &= BBbWriteEmbeded(dwIoBase,byVT3253B0_UW2451[ii][0],byVT3253B0_UW2451[ii][1]); } for (ii = 0; ii < CB_VT3253B0_AGC; ii++) { - bResult &= BBbWriteEmbedded(dwIoBase,byVT3253B0_AGC[ii][0],byVT3253B0_AGC[ii][1]); + bResult &= BBbWriteEmbeded(dwIoBase,byVT3253B0_AGC[ii][0],byVT3253B0_AGC[ii][1]); } VNSvOutPortB(dwIoBase + MAC_REG_ITRTMSET, 0x23); MACvRegBitsOn(dwIoBase, MAC_REG_PAPEDELAY, BIT0); @@ -2210,28 +2210,28 @@ bool BBbVT3253Init (PSDevice pDevice) pDevice->ldBmThreshold[3] = 0; } else if (byRFType == RF_UW2452) { for (ii = 0; ii < CB_VT3253B0_INIT_FOR_UW2451; ii++) { - bResult &= BBbWriteEmbedded(dwIoBase,byVT3253B0_UW2451[ii][0],byVT3253B0_UW2451[ii][1]); + bResult &= BBbWriteEmbeded(dwIoBase,byVT3253B0_UW2451[ii][0],byVT3253B0_UW2451[ii][1]); } // Init ANT B select,TX Config CR09 = 0x61->0x45, 0x45->0x41(VC1/VC2 define, make the ANT_A, ANT_B inverted) - //bResult &= BBbWriteEmbedded(dwIoBase,0x09,0x41); + //bResult &= BBbWriteEmbeded(dwIoBase,0x09,0x41); // Init ANT B select,RX Config CR10 = 0x28->0x2A, 0x2A->0x28(VC1/VC2 define, make the ANT_A, ANT_B inverted) - //bResult &= BBbWriteEmbedded(dwIoBase,0x0a,0x28); + //bResult &= BBbWriteEmbeded(dwIoBase,0x0a,0x28); // Select VC1/VC2, CR215 = 0x02->0x06 - bResult &= BBbWriteEmbedded(dwIoBase,0xd7,0x06); + bResult &= BBbWriteEmbeded(dwIoBase,0xd7,0x06); //{{RobertYu:20050125, request by Jack - bResult &= BBbWriteEmbedded(dwIoBase,0x90,0x20); - bResult &= BBbWriteEmbedded(dwIoBase,0x97,0xeb); + bResult &= BBbWriteEmbeded(dwIoBase,0x90,0x20); + bResult &= BBbWriteEmbeded(dwIoBase,0x97,0xeb); //}} //{{RobertYu:20050221, request by Jack - bResult &= BBbWriteEmbedded(dwIoBase,0xa6,0x00); - bResult &= BBbWriteEmbedded(dwIoBase,0xa8,0x30); + bResult &= BBbWriteEmbeded(dwIoBase,0xa6,0x00); + bResult &= BBbWriteEmbeded(dwIoBase,0xa8,0x30); //}} - bResult &= BBbWriteEmbedded(dwIoBase,0xb0,0x58); + bResult &= BBbWriteEmbeded(dwIoBase,0xb0,0x58); for (ii = 0; ii < CB_VT3253B0_AGC; ii++) { - bResult &= BBbWriteEmbedded(dwIoBase,byVT3253B0_AGC[ii][0],byVT3253B0_AGC[ii][1]); + bResult &= BBbWriteEmbeded(dwIoBase,byVT3253B0_AGC[ii][0],byVT3253B0_AGC[ii][1]); } //VNSvOutPortB(dwIoBase + MAC_REG_ITRTMSET, 0x23); // RobertYu: 20050104, 20050131 disable PA_Delay //MACvRegBitsOn(dwIoBase, MAC_REG_PAPEDELAY, BIT0); // RobertYu: 20050104, 20050131 disable PA_Delay @@ -2248,10 +2248,10 @@ bool BBbVT3253Init (PSDevice pDevice) } else if (byRFType == RF_VT3226) { for (ii = 0; ii < CB_VT3253B0_INIT_FOR_AIROHA2230; ii++) { - bResult &= BBbWriteEmbedded(dwIoBase,byVT3253B0_AIROHA2230[ii][0],byVT3253B0_AIROHA2230[ii][1]); + bResult &= BBbWriteEmbeded(dwIoBase,byVT3253B0_AIROHA2230[ii][0],byVT3253B0_AIROHA2230[ii][1]); } for (ii = 0; ii < CB_VT3253B0_AGC; ii++) { - bResult &= BBbWriteEmbedded(dwIoBase,byVT3253B0_AGC[ii][0],byVT3253B0_AGC[ii][1]); + bResult &= BBbWriteEmbeded(dwIoBase,byVT3253B0_AGC[ii][0],byVT3253B0_AGC[ii][1]); } pDevice->abyBBVGA[0] = 0x1C; pDevice->abyBBVGA[1] = 0x10; @@ -2266,20 +2266,20 @@ bool BBbVT3253Init (PSDevice pDevice) //{{ RobertYu: 20050104 } else if (byRFType == RF_AIROHA7230) { for (ii = 0; ii < CB_VT3253B0_INIT_FOR_AIROHA2230; ii++) { - bResult &= BBbWriteEmbedded(dwIoBase,byVT3253B0_AIROHA2230[ii][0],byVT3253B0_AIROHA2230[ii][1]); + bResult &= BBbWriteEmbeded(dwIoBase,byVT3253B0_AIROHA2230[ii][0],byVT3253B0_AIROHA2230[ii][1]); } //{{ RobertYu:20050223, request by JerryChung // Init ANT B select,TX Config CR09 = 0x61->0x45, 0x45->0x41(VC1/VC2 define, make the ANT_A, ANT_B inverted) - //bResult &= BBbWriteEmbedded(dwIoBase,0x09,0x41); + //bResult &= BBbWriteEmbeded(dwIoBase,0x09,0x41); // Init ANT B select,RX Config CR10 = 0x28->0x2A, 0x2A->0x28(VC1/VC2 define, make the ANT_A, ANT_B inverted) - //bResult &= BBbWriteEmbedded(dwIoBase,0x0a,0x28); + //bResult &= BBbWriteEmbeded(dwIoBase,0x0a,0x28); // Select VC1/VC2, CR215 = 0x02->0x06 - bResult &= BBbWriteEmbedded(dwIoBase,0xd7,0x06); + bResult &= BBbWriteEmbeded(dwIoBase,0xd7,0x06); //}} for (ii = 0; ii < CB_VT3253B0_AGC; ii++) { - bResult &= BBbWriteEmbedded(dwIoBase,byVT3253B0_AGC[ii][0],byVT3253B0_AGC[ii][1]); + bResult &= BBbWriteEmbeded(dwIoBase,byVT3253B0_AGC[ii][0],byVT3253B0_AGC[ii][1]); } pDevice->abyBBVGA[0] = 0x1C; pDevice->abyBBVGA[1] = 0x10; @@ -2297,8 +2297,8 @@ bool BBbVT3253Init (PSDevice pDevice) } if (byLocalID > REV_ID_VT3253_A1) { - BBbWriteEmbedded(dwIoBase, 0x04, 0x7F); - BBbWriteEmbedded(dwIoBase, 0x0D, 0x01); + BBbWriteEmbeded(dwIoBase, 0x04, 0x7F); + BBbWriteEmbeded(dwIoBase, 0x0D, 0x01); } return bResult; @@ -2324,7 +2324,7 @@ void BBvReadAllRegs (unsigned long dwIoBase, unsigned char *pbyBBRegs) int ii; unsigned char byBase = 1; for (ii = 0; ii < BB_MAX_CONTEXT_SIZE; ii++) { - BBbReadEmbedded(dwIoBase, (unsigned char)(ii*byBase), pbyBBRegs); + BBbReadEmbeded(dwIoBase, (unsigned char)(ii*byBase), pbyBBRegs); pbyBBRegs += byBase; } } @@ -2350,39 +2350,39 @@ void BBvLoopbackOn (PSDevice pDevice) unsigned long dwIoBase = pDevice->PortOffset; //CR C9 = 0x00 - BBbReadEmbedded(dwIoBase, 0xC9, &pDevice->byBBCRc9);//CR201 - BBbWriteEmbedded(dwIoBase, 0xC9, 0); - BBbReadEmbedded(dwIoBase, 0x4D, &pDevice->byBBCR4d);//CR77 - BBbWriteEmbedded(dwIoBase, 0x4D, 0x90); + BBbReadEmbeded(dwIoBase, 0xC9, &pDevice->byBBCRc9);//CR201 + BBbWriteEmbeded(dwIoBase, 0xC9, 0); + BBbReadEmbeded(dwIoBase, 0x4D, &pDevice->byBBCR4d);//CR77 + BBbWriteEmbeded(dwIoBase, 0x4D, 0x90); //CR 88 = 0x02(CCK), 0x03(OFDM) - BBbReadEmbedded(dwIoBase, 0x88, &pDevice->byBBCR88);//CR136 + BBbReadEmbeded(dwIoBase, 0x88, &pDevice->byBBCR88);//CR136 if (pDevice->uConnectionRate <= RATE_11M) { //CCK // Enable internal digital loopback: CR33 |= 0000 0001 - BBbReadEmbedded(dwIoBase, 0x21, &byData);//CR33 - BBbWriteEmbedded(dwIoBase, 0x21, (unsigned char)(byData | 0x01));//CR33 + BBbReadEmbeded(dwIoBase, 0x21, &byData);//CR33 + BBbWriteEmbeded(dwIoBase, 0x21, (unsigned char)(byData | 0x01));//CR33 // CR154 = 0x00 - BBbWriteEmbedded(dwIoBase, 0x9A, 0); //CR154 + BBbWriteEmbeded(dwIoBase, 0x9A, 0); //CR154 - BBbWriteEmbedded(dwIoBase, 0x88, 0x02);//CR239 + BBbWriteEmbeded(dwIoBase, 0x88, 0x02);//CR239 } else { //OFDM // Enable internal digital loopback:CR154 |= 0000 0001 - BBbReadEmbedded(dwIoBase, 0x9A, &byData);//CR154 - BBbWriteEmbedded(dwIoBase, 0x9A, (unsigned char)(byData | 0x01));//CR154 + BBbReadEmbeded(dwIoBase, 0x9A, &byData);//CR154 + BBbWriteEmbeded(dwIoBase, 0x9A, (unsigned char)(byData | 0x01));//CR154 // CR33 = 0x00 - BBbWriteEmbedded(dwIoBase, 0x21, 0); //CR33 + BBbWriteEmbeded(dwIoBase, 0x21, 0); //CR33 - BBbWriteEmbedded(dwIoBase, 0x88, 0x03);//CR239 + BBbWriteEmbeded(dwIoBase, 0x88, 0x03);//CR239 } //CR14 = 0x00 - BBbWriteEmbedded(dwIoBase, 0x0E, 0);//CR14 + BBbWriteEmbeded(dwIoBase, 0x0E, 0);//CR14 // Disable TX_IQUN - BBbReadEmbedded(pDevice->PortOffset, 0x09, &pDevice->byBBCR09); - BBbWriteEmbedded(pDevice->PortOffset, 0x09, (unsigned char)(pDevice->byBBCR09 & 0xDE)); + BBbReadEmbeded(pDevice->PortOffset, 0x09, &pDevice->byBBCR09); + BBbWriteEmbeded(pDevice->PortOffset, 0x09, (unsigned char)(pDevice->byBBCR09 & 0xDE)); } /* @@ -2403,22 +2403,22 @@ void BBvLoopbackOff (PSDevice pDevice) unsigned char byData; unsigned long dwIoBase = pDevice->PortOffset; - BBbWriteEmbedded(dwIoBase, 0xC9, pDevice->byBBCRc9);//CR201 - BBbWriteEmbedded(dwIoBase, 0x88, pDevice->byBBCR88);//CR136 - BBbWriteEmbedded(dwIoBase, 0x09, pDevice->byBBCR09);//CR136 - BBbWriteEmbedded(dwIoBase, 0x4D, pDevice->byBBCR4d);//CR77 + BBbWriteEmbeded(dwIoBase, 0xC9, pDevice->byBBCRc9);//CR201 + BBbWriteEmbeded(dwIoBase, 0x88, pDevice->byBBCR88);//CR136 + BBbWriteEmbeded(dwIoBase, 0x09, pDevice->byBBCR09);//CR136 + BBbWriteEmbeded(dwIoBase, 0x4D, pDevice->byBBCR4d);//CR77 if (pDevice->uConnectionRate <= RATE_11M) { // CCK // Set the CR33 Bit2 to disable internal Loopback. - BBbReadEmbedded(dwIoBase, 0x21, &byData);//CR33 - BBbWriteEmbedded(dwIoBase, 0x21, (unsigned char)(byData & 0xFE));//CR33 + BBbReadEmbeded(dwIoBase, 0x21, &byData);//CR33 + BBbWriteEmbeded(dwIoBase, 0x21, (unsigned char)(byData & 0xFE));//CR33 } else { // OFDM - BBbReadEmbedded(dwIoBase, 0x9A, &byData);//CR154 - BBbWriteEmbedded(dwIoBase, 0x9A, (unsigned char)(byData & 0xFE));//CR154 + BBbReadEmbeded(dwIoBase, 0x9A, &byData);//CR154 + BBbWriteEmbeded(dwIoBase, 0x9A, (unsigned char)(byData & 0xFE));//CR154 } - BBbReadEmbedded(dwIoBase, 0x0E, &byData);//CR14 - BBbWriteEmbedded(dwIoBase, 0x0E, (unsigned char)(byData | 0x80));//CR14 + BBbReadEmbeded(dwIoBase, 0x0E, &byData);//CR14 + BBbWriteEmbeded(dwIoBase, 0x0E, (unsigned char)(byData | 0x80));//CR14 } @@ -2442,7 +2442,7 @@ BBvSetShortSlotTime (PSDevice pDevice) unsigned char byBBRxConf=0; unsigned char byBBVGA=0; - BBbReadEmbedded(pDevice->PortOffset, 0x0A, &byBBRxConf);//CR10 + BBbReadEmbeded(pDevice->PortOffset, 0x0A, &byBBRxConf);//CR10 if (pDevice->bShortSlotTime) { byBBRxConf &= 0xDF;//1101 1111 @@ -2451,12 +2451,12 @@ BBvSetShortSlotTime (PSDevice pDevice) } // patch for 3253B0 Baseband with Cardbus module - BBbReadEmbedded(pDevice->PortOffset, 0xE7, &byBBVGA); + BBbReadEmbeded(pDevice->PortOffset, 0xE7, &byBBVGA); if (byBBVGA == pDevice->abyBBVGA[0]) { byBBRxConf |= 0x20;//0010 0000 } - BBbWriteEmbedded(pDevice->PortOffset, 0x0A, byBBRxConf);//CR10 + BBbWriteEmbeded(pDevice->PortOffset, 0x0A, byBBRxConf);//CR10 } @@ -2464,9 +2464,9 @@ void BBvSetVGAGainOffset(PSDevice pDevice, unsigned char byData) { unsigned char byBBRxConf=0; - BBbWriteEmbedded(pDevice->PortOffset, 0xE7, byData); + BBbWriteEmbeded(pDevice->PortOffset, 0xE7, byData); - BBbReadEmbedded(pDevice->PortOffset, 0x0A, &byBBRxConf);//CR10 + BBbReadEmbeded(pDevice->PortOffset, 0x0A, &byBBRxConf);//CR10 // patch for 3253B0 Baseband with Cardbus module if (byData == pDevice->abyBBVGA[0]) { byBBRxConf |= 0x20;//0010 0000 @@ -2476,7 +2476,7 @@ void BBvSetVGAGainOffset(PSDevice pDevice, unsigned char byData) byBBRxConf |= 0x20;//0010 0000 } pDevice->byBBVGACurrent = byData; - BBbWriteEmbedded(pDevice->PortOffset, 0x0A, byBBRxConf);//CR10 + BBbWriteEmbeded(pDevice->PortOffset, 0x0A, byBBRxConf);//CR10 } @@ -2495,10 +2495,10 @@ void BBvSetVGAGainOffset(PSDevice pDevice, unsigned char byData) void BBvSoftwareReset (unsigned long dwIoBase) { - BBbWriteEmbedded(dwIoBase, 0x50, 0x40); - BBbWriteEmbedded(dwIoBase, 0x50, 0); - BBbWriteEmbedded(dwIoBase, 0x9C, 0x01); - BBbWriteEmbedded(dwIoBase, 0x9C, 0); + BBbWriteEmbeded(dwIoBase, 0x50, 0x40); + BBbWriteEmbeded(dwIoBase, 0x50, 0); + BBbWriteEmbeded(dwIoBase, 0x9C, 0x01); + BBbWriteEmbeded(dwIoBase, 0x9C, 0); } /* @@ -2518,9 +2518,9 @@ BBvPowerSaveModeON (unsigned long dwIoBase) { unsigned char byOrgData; - BBbReadEmbedded(dwIoBase, 0x0D, &byOrgData); + BBbReadEmbeded(dwIoBase, 0x0D, &byOrgData); byOrgData |= BIT0; - BBbWriteEmbedded(dwIoBase, 0x0D, byOrgData); + BBbWriteEmbeded(dwIoBase, 0x0D, byOrgData); } /* @@ -2540,9 +2540,9 @@ BBvPowerSaveModeOFF (unsigned long dwIoBase) { unsigned char byOrgData; - BBbReadEmbedded(dwIoBase, 0x0D, &byOrgData); + BBbReadEmbeded(dwIoBase, 0x0D, &byOrgData); byOrgData &= ~(BIT0); - BBbWriteEmbedded(dwIoBase, 0x0D, byOrgData); + BBbWriteEmbeded(dwIoBase, 0x0D, byOrgData); } /* @@ -2567,7 +2567,7 @@ BBvSetTxAntennaMode (unsigned long dwIoBase, unsigned char byAntennaMode) #ifdef PLICE_DEBUG //printk("Enter BBvSetTxAntennaMode\n"); #endif - BBbReadEmbedded(dwIoBase, 0x09, &byBBTxConf);//CR09 + BBbReadEmbeded(dwIoBase, 0x09, &byBBTxConf);//CR09 if (byAntennaMode == ANT_DIVERSITY) { // bit 1 is diversity byBBTxConf |= 0x02; @@ -2581,7 +2581,7 @@ BBvSetTxAntennaMode (unsigned long dwIoBase, unsigned char byAntennaMode) byBBTxConf &= 0xFD; // 1111 1101 byBBTxConf |= 0x04; } - BBbWriteEmbedded(dwIoBase, 0x09, byBBTxConf);//CR09 + BBbWriteEmbeded(dwIoBase, 0x09, byBBTxConf);//CR09 } @@ -2606,7 +2606,7 @@ BBvSetRxAntennaMode (unsigned long dwIoBase, unsigned char byAntennaMode) { unsigned char byBBRxConf; - BBbReadEmbedded(dwIoBase, 0x0A, &byBBRxConf);//CR10 + BBbReadEmbeded(dwIoBase, 0x0A, &byBBRxConf);//CR10 if (byAntennaMode == ANT_DIVERSITY) { byBBRxConf |= 0x01; @@ -2616,7 +2616,7 @@ BBvSetRxAntennaMode (unsigned long dwIoBase, unsigned char byAntennaMode) byBBRxConf &= 0xFE; // 1111 1110 byBBRxConf |= 0x02; } - BBbWriteEmbedded(dwIoBase, 0x0A, byBBRxConf);//CR10 + BBbWriteEmbeded(dwIoBase, 0x0A, byBBRxConf);//CR10 } @@ -2635,15 +2635,15 @@ BBvSetRxAntennaMode (unsigned long dwIoBase, unsigned char byAntennaMode) void BBvSetDeepSleep (unsigned long dwIoBase, unsigned char byLocalID) { - BBbWriteEmbedded(dwIoBase, 0x0C, 0x17);//CR12 - BBbWriteEmbedded(dwIoBase, 0x0D, 0xB9);//CR13 + BBbWriteEmbeded(dwIoBase, 0x0C, 0x17);//CR12 + BBbWriteEmbeded(dwIoBase, 0x0D, 0xB9);//CR13 } void BBvExitDeepSleep (unsigned long dwIoBase, unsigned char byLocalID) { - BBbWriteEmbedded(dwIoBase, 0x0C, 0x00);//CR12 - BBbWriteEmbedded(dwIoBase, 0x0D, 0x01);//CR13 + BBbWriteEmbeded(dwIoBase, 0x0C, 0x00);//CR12 + BBbWriteEmbeded(dwIoBase, 0x0D, 0x01);//CR13 } diff --git a/trunk/drivers/staging/vt6655/baseband.h b/trunk/drivers/staging/vt6655/baseband.h index 9b5bc9c58d9f..be2d68909490 100644 --- a/trunk/drivers/staging/vt6655/baseband.h +++ b/trunk/drivers/staging/vt6655/baseband.h @@ -73,12 +73,12 @@ #define BBvClearFOE(dwIoBase) \ { \ - BBbWriteEmbedded(dwIoBase, 0xB1, 0); \ + BBbWriteEmbeded(dwIoBase, 0xB1, 0); \ } #define BBvSetFOE(dwIoBase) \ { \ - BBbWriteEmbedded(dwIoBase, 0xB1, 0x0C); \ + BBbWriteEmbeded(dwIoBase, 0xB1, 0x0C); \ } @@ -97,7 +97,7 @@ BBuGetFrameTime( ); void -BBvCalculateParameter ( +BBvCaculateParameter ( PSDevice pDevice, unsigned int cbFrameLength, unsigned short wRate, @@ -107,8 +107,8 @@ BBvCalculateParameter ( unsigned char *pbyPhySgn ); -bool BBbReadEmbedded(unsigned long dwIoBase, unsigned char byBBAddr, unsigned char *pbyData); -bool BBbWriteEmbedded(unsigned long dwIoBase, unsigned char byBBAddr, unsigned char byData); +bool BBbReadEmbeded(unsigned long dwIoBase, unsigned char byBBAddr, unsigned char *pbyData); +bool BBbWriteEmbeded(unsigned long dwIoBase, unsigned char byBBAddr, unsigned char byData); void BBvReadAllRegs(unsigned long dwIoBase, unsigned char *pbyBBRegs); void BBvLoopbackOn(PSDevice pDevice); diff --git a/trunk/drivers/staging/vt6655/bssdb.c b/trunk/drivers/staging/vt6655/bssdb.c index fe57fb880a8f..fcffa4f0f4e3 100644 --- a/trunk/drivers/staging/vt6655/bssdb.c +++ b/trunk/drivers/staging/vt6655/bssdb.c @@ -784,8 +784,8 @@ BSSDBbIsSTAInNodeDB(void *pMgmtObject, unsigned char *abyDstAddr, /*+ * * Routine Description: - * Find an empty node and allocat it; if there is no empty node, - * then use the most inactive one. + * Find an empty node and allocated; if no empty found, + * instand used of most inactive one. * * Return Value: * None diff --git a/trunk/drivers/staging/vt6655/card.c b/trunk/drivers/staging/vt6655/card.c index 319ca482f003..2721e0798496 100644 --- a/trunk/drivers/staging/vt6655/card.c +++ b/trunk/drivers/staging/vt6655/card.c @@ -28,9 +28,9 @@ * CARDbIsOFDMinBasicRate - Check if any OFDM rate is in BasicRateSet * CARDvSetLoopbackMode - Set Loopback mode * CARDbSoftwareReset - Sortware reset NIC - * CARDqGetTSFOffset - Calculate TSFOffset + * CARDqGetTSFOffset - Caculate TSFOffset * CARDbGetCurrentTSF - Read Current NIC TSF counter - * CARDqGetNextTBTT - Calculate Next Beacon TSF counter + * CARDqGetNextTBTT - Caculate Next Beacon TSF counter * CARDvSetFirstNextTBTT - Set NIC Beacon time * CARDvUpdateNextTBTT - Sync. NIC Beacon time * CARDbRadioPowerOff - Turn Off NIC Radio Power @@ -100,7 +100,7 @@ const unsigned short cwRXBCNTSFOff[MAX_RATE] = static void -s_vCalculateOFDMRParameter( +s_vCaculateOFDMRParameter( unsigned char byRate, CARD_PHY_TYPE ePHYType, unsigned char *pbyTxRate, @@ -111,7 +111,7 @@ s_vCalculateOFDMRParameter( /*--------------------- Export Functions --------------------------*/ /* - * Description: Calculate TxRate and RsvTime fields for RSPINF in OFDM mode. + * Description: Caculate TxRate and RsvTime fields for RSPINF in OFDM mode. * * Parameters: * In: @@ -126,7 +126,7 @@ s_vCalculateOFDMRParameter( */ static void -s_vCalculateOFDMRParameter ( +s_vCaculateOFDMRParameter ( unsigned char byRate, CARD_PHY_TYPE ePHYType, unsigned char *pbyTxRate, @@ -251,7 +251,7 @@ s_vSetRSPINF (PSDevice pDevice, CARD_PHY_TYPE ePHYType, void *pvSupportRateIEs, MACvSelectPage1(pDevice->PortOffset); //RSPINF_b_1 - BBvCalculateParameter(pDevice, + BBvCaculateParameter(pDevice, 14, VNTWIFIbyGetACKTxRate(RATE_1M, pvSupportRateIEs, pvExtSupportRateIEs), PK_TYPE_11B, @@ -262,7 +262,7 @@ s_vSetRSPINF (PSDevice pDevice, CARD_PHY_TYPE ePHYType, void *pvSupportRateIEs, VNSvOutPortD(pDevice->PortOffset + MAC_REG_RSPINF_B_1, MAKEDWORD(wLen,MAKEWORD(bySignal,byServ))); ///RSPINF_b_2 - BBvCalculateParameter(pDevice, + BBvCaculateParameter(pDevice, 14, VNTWIFIbyGetACKTxRate(RATE_2M, pvSupportRateIEs, pvExtSupportRateIEs), PK_TYPE_11B, @@ -273,7 +273,7 @@ s_vSetRSPINF (PSDevice pDevice, CARD_PHY_TYPE ePHYType, void *pvSupportRateIEs, VNSvOutPortD(pDevice->PortOffset + MAC_REG_RSPINF_B_2, MAKEDWORD(wLen,MAKEWORD(bySignal,byServ))); //RSPINF_b_5 - BBvCalculateParameter(pDevice, + BBvCaculateParameter(pDevice, 14, VNTWIFIbyGetACKTxRate(RATE_5M, pvSupportRateIEs, pvExtSupportRateIEs), PK_TYPE_11B, @@ -284,7 +284,7 @@ s_vSetRSPINF (PSDevice pDevice, CARD_PHY_TYPE ePHYType, void *pvSupportRateIEs, VNSvOutPortD(pDevice->PortOffset + MAC_REG_RSPINF_B_5, MAKEDWORD(wLen,MAKEWORD(bySignal,byServ))); //RSPINF_b_11 - BBvCalculateParameter(pDevice, + BBvCaculateParameter(pDevice, 14, VNTWIFIbyGetACKTxRate(RATE_11M, pvSupportRateIEs, pvExtSupportRateIEs), PK_TYPE_11B, @@ -295,51 +295,51 @@ s_vSetRSPINF (PSDevice pDevice, CARD_PHY_TYPE ePHYType, void *pvSupportRateIEs, VNSvOutPortD(pDevice->PortOffset + MAC_REG_RSPINF_B_11, MAKEDWORD(wLen,MAKEWORD(bySignal,byServ))); //RSPINF_a_6 - s_vCalculateOFDMRParameter(RATE_6M, + s_vCaculateOFDMRParameter(RATE_6M, ePHYType, &byTxRate, &byRsvTime); VNSvOutPortW(pDevice->PortOffset + MAC_REG_RSPINF_A_6, MAKEWORD(byTxRate,byRsvTime)); //RSPINF_a_9 - s_vCalculateOFDMRParameter(RATE_9M, + s_vCaculateOFDMRParameter(RATE_9M, ePHYType, &byTxRate, &byRsvTime); VNSvOutPortW(pDevice->PortOffset + MAC_REG_RSPINF_A_9, MAKEWORD(byTxRate,byRsvTime)); //RSPINF_a_12 - s_vCalculateOFDMRParameter(RATE_12M, + s_vCaculateOFDMRParameter(RATE_12M, ePHYType, &byTxRate, &byRsvTime); VNSvOutPortW(pDevice->PortOffset + MAC_REG_RSPINF_A_12, MAKEWORD(byTxRate,byRsvTime)); //RSPINF_a_18 - s_vCalculateOFDMRParameter(RATE_18M, + s_vCaculateOFDMRParameter(RATE_18M, ePHYType, &byTxRate, &byRsvTime); VNSvOutPortW(pDevice->PortOffset + MAC_REG_RSPINF_A_18, MAKEWORD(byTxRate,byRsvTime)); //RSPINF_a_24 - s_vCalculateOFDMRParameter(RATE_24M, + s_vCaculateOFDMRParameter(RATE_24M, ePHYType, &byTxRate, &byRsvTime); VNSvOutPortW(pDevice->PortOffset + MAC_REG_RSPINF_A_24, MAKEWORD(byTxRate,byRsvTime)); //RSPINF_a_36 - s_vCalculateOFDMRParameter( + s_vCaculateOFDMRParameter( VNTWIFIbyGetACKTxRate(RATE_36M, pvSupportRateIEs, pvExtSupportRateIEs), ePHYType, &byTxRate, &byRsvTime); VNSvOutPortW(pDevice->PortOffset + MAC_REG_RSPINF_A_36, MAKEWORD(byTxRate,byRsvTime)); //RSPINF_a_48 - s_vCalculateOFDMRParameter( + s_vCaculateOFDMRParameter( VNTWIFIbyGetACKTxRate(RATE_48M, pvSupportRateIEs, pvExtSupportRateIEs), ePHYType, &byTxRate, &byRsvTime); VNSvOutPortW(pDevice->PortOffset + MAC_REG_RSPINF_A_48, MAKEWORD(byTxRate,byRsvTime)); //RSPINF_a_54 - s_vCalculateOFDMRParameter( + s_vCaculateOFDMRParameter( VNTWIFIbyGetACKTxRate(RATE_54M, pvSupportRateIEs, pvExtSupportRateIEs), ePHYType, &byTxRate, @@ -461,22 +461,22 @@ bool CARDbSetPhyParameter (void *pDeviceHandler, CARD_PHY_TYPE ePHYType, unsigne pDevice->abyBBVGA[0] = 0x20; pDevice->abyBBVGA[2] = 0x10; pDevice->abyBBVGA[3] = 0x10; - BBbReadEmbedded(pDevice->PortOffset, 0xE7, &byData); + BBbReadEmbeded(pDevice->PortOffset, 0xE7, &byData); if (byData == 0x1C) { - BBbWriteEmbedded(pDevice->PortOffset, 0xE7, pDevice->abyBBVGA[0]); + BBbWriteEmbeded(pDevice->PortOffset, 0xE7, pDevice->abyBBVGA[0]); } } else if (pDevice->byRFType == RF_UW2452) { MACvSetBBType(pDevice->PortOffset, BB_TYPE_11A); pDevice->abyBBVGA[0] = 0x18; - BBbReadEmbedded(pDevice->PortOffset, 0xE7, &byData); + BBbReadEmbeded(pDevice->PortOffset, 0xE7, &byData); if (byData == 0x14) { - BBbWriteEmbedded(pDevice->PortOffset, 0xE7, pDevice->abyBBVGA[0]); - BBbWriteEmbedded(pDevice->PortOffset, 0xE1, 0x57); + BBbWriteEmbeded(pDevice->PortOffset, 0xE7, pDevice->abyBBVGA[0]); + BBbWriteEmbeded(pDevice->PortOffset, 0xE1, 0x57); } } else { MACvSetBBType(pDevice->PortOffset, BB_TYPE_11A); } - BBbWriteEmbedded(pDevice->PortOffset, 0x88, 0x03); + BBbWriteEmbeded(pDevice->PortOffset, 0x88, 0x03); bySlot = C_SLOT_SHORT; bySIFS = C_SIFS_A; byDIFS = C_SIFS_A + 2*C_SLOT_SHORT; @@ -490,19 +490,19 @@ bool CARDbSetPhyParameter (void *pDeviceHandler, CARD_PHY_TYPE ePHYType, unsigne pDevice->abyBBVGA[0] = 0x1C; pDevice->abyBBVGA[2] = 0x00; pDevice->abyBBVGA[3] = 0x00; - BBbReadEmbedded(pDevice->PortOffset, 0xE7, &byData); + BBbReadEmbeded(pDevice->PortOffset, 0xE7, &byData); if (byData == 0x20) { - BBbWriteEmbedded(pDevice->PortOffset, 0xE7, pDevice->abyBBVGA[0]); + BBbWriteEmbeded(pDevice->PortOffset, 0xE7, pDevice->abyBBVGA[0]); } } else if (pDevice->byRFType == RF_UW2452) { pDevice->abyBBVGA[0] = 0x14; - BBbReadEmbedded(pDevice->PortOffset, 0xE7, &byData); + BBbReadEmbeded(pDevice->PortOffset, 0xE7, &byData); if (byData == 0x18) { - BBbWriteEmbedded(pDevice->PortOffset, 0xE7, pDevice->abyBBVGA[0]); - BBbWriteEmbedded(pDevice->PortOffset, 0xE1, 0xD3); + BBbWriteEmbeded(pDevice->PortOffset, 0xE7, pDevice->abyBBVGA[0]); + BBbWriteEmbeded(pDevice->PortOffset, 0xE1, 0xD3); } } - BBbWriteEmbedded(pDevice->PortOffset, 0x88, 0x02); + BBbWriteEmbeded(pDevice->PortOffset, 0x88, 0x02); bySlot = C_SLOT_LONG; bySIFS = C_SIFS_BG; byDIFS = C_SIFS_BG + 2*C_SLOT_LONG; @@ -517,19 +517,19 @@ bool CARDbSetPhyParameter (void *pDeviceHandler, CARD_PHY_TYPE ePHYType, unsigne pDevice->abyBBVGA[0] = 0x1C; pDevice->abyBBVGA[2] = 0x00; pDevice->abyBBVGA[3] = 0x00; - BBbReadEmbedded(pDevice->PortOffset, 0xE7, &byData); + BBbReadEmbeded(pDevice->PortOffset, 0xE7, &byData); if (byData == 0x20) { - BBbWriteEmbedded(pDevice->PortOffset, 0xE7, pDevice->abyBBVGA[0]); + BBbWriteEmbeded(pDevice->PortOffset, 0xE7, pDevice->abyBBVGA[0]); } } else if (pDevice->byRFType == RF_UW2452) { pDevice->abyBBVGA[0] = 0x14; - BBbReadEmbedded(pDevice->PortOffset, 0xE7, &byData); + BBbReadEmbeded(pDevice->PortOffset, 0xE7, &byData); if (byData == 0x18) { - BBbWriteEmbedded(pDevice->PortOffset, 0xE7, pDevice->abyBBVGA[0]); - BBbWriteEmbedded(pDevice->PortOffset, 0xE1, 0xD3); + BBbWriteEmbeded(pDevice->PortOffset, 0xE7, pDevice->abyBBVGA[0]); + BBbWriteEmbeded(pDevice->PortOffset, 0xE1, 0xD3); } } - BBbWriteEmbedded(pDevice->PortOffset, 0x88, 0x08); + BBbWriteEmbeded(pDevice->PortOffset, 0x88, 0x08); bySIFS = C_SIFS_BG; if(VNTWIFIbIsShortSlotTime(wCapInfo)) { bySlot = C_SLOT_SHORT; @@ -1354,8 +1354,7 @@ CARDbSetQuiet ( /* * * Description: - * Do Quiet, It will be called by either ISR(after start) - * or VNTWIFI(before start) so we do not need a SPINLOCK + * Do Quiet, It will called by either ISR (after start) or VNTWIFI (before start) so do not need SPINLOCK * * Parameters: * In: @@ -1739,7 +1738,7 @@ void CARDvSetRSPINF (void *pDeviceHandler, CARD_PHY_TYPE ePHYType) MACvSelectPage1(pDevice->PortOffset); //RSPINF_b_1 - BBvCalculateParameter(pDevice, + BBvCaculateParameter(pDevice, 14, CARDwGetCCKControlRate((void *)pDevice, RATE_1M), PK_TYPE_11B, @@ -1750,7 +1749,7 @@ void CARDvSetRSPINF (void *pDeviceHandler, CARD_PHY_TYPE ePHYType) VNSvOutPortD(pDevice->PortOffset + MAC_REG_RSPINF_B_1, MAKEDWORD(wLen,MAKEWORD(bySignal,byServ))); ///RSPINF_b_2 - BBvCalculateParameter(pDevice, + BBvCaculateParameter(pDevice, 14, CARDwGetCCKControlRate((void *)pDevice, RATE_2M), PK_TYPE_11B, @@ -1761,7 +1760,7 @@ void CARDvSetRSPINF (void *pDeviceHandler, CARD_PHY_TYPE ePHYType) VNSvOutPortD(pDevice->PortOffset + MAC_REG_RSPINF_B_2, MAKEDWORD(wLen,MAKEWORD(bySignal,byServ))); //RSPINF_b_5 - BBvCalculateParameter(pDevice, + BBvCaculateParameter(pDevice, 14, CARDwGetCCKControlRate((void *)pDevice, RATE_5M), PK_TYPE_11B, @@ -1772,7 +1771,7 @@ void CARDvSetRSPINF (void *pDeviceHandler, CARD_PHY_TYPE ePHYType) VNSvOutPortD(pDevice->PortOffset + MAC_REG_RSPINF_B_5, MAKEDWORD(wLen,MAKEWORD(bySignal,byServ))); //RSPINF_b_11 - BBvCalculateParameter(pDevice, + BBvCaculateParameter(pDevice, 14, CARDwGetCCKControlRate((void *)pDevice, RATE_11M), PK_TYPE_11B, @@ -1783,56 +1782,56 @@ void CARDvSetRSPINF (void *pDeviceHandler, CARD_PHY_TYPE ePHYType) VNSvOutPortD(pDevice->PortOffset + MAC_REG_RSPINF_B_11, MAKEDWORD(wLen,MAKEWORD(bySignal,byServ))); //RSPINF_a_6 - s_vCalculateOFDMRParameter(RATE_6M, + s_vCaculateOFDMRParameter(RATE_6M, ePHYType, &byTxRate, &byRsvTime); VNSvOutPortW(pDevice->PortOffset + MAC_REG_RSPINF_A_6, MAKEWORD(byTxRate,byRsvTime)); //RSPINF_a_9 - s_vCalculateOFDMRParameter(RATE_9M, + s_vCaculateOFDMRParameter(RATE_9M, ePHYType, &byTxRate, &byRsvTime); VNSvOutPortW(pDevice->PortOffset + MAC_REG_RSPINF_A_9, MAKEWORD(byTxRate,byRsvTime)); //RSPINF_a_12 - s_vCalculateOFDMRParameter(RATE_12M, + s_vCaculateOFDMRParameter(RATE_12M, ePHYType, &byTxRate, &byRsvTime); VNSvOutPortW(pDevice->PortOffset + MAC_REG_RSPINF_A_12, MAKEWORD(byTxRate,byRsvTime)); //RSPINF_a_18 - s_vCalculateOFDMRParameter(RATE_18M, + s_vCaculateOFDMRParameter(RATE_18M, ePHYType, &byTxRate, &byRsvTime); VNSvOutPortW(pDevice->PortOffset + MAC_REG_RSPINF_A_18, MAKEWORD(byTxRate,byRsvTime)); //RSPINF_a_24 - s_vCalculateOFDMRParameter(RATE_24M, + s_vCaculateOFDMRParameter(RATE_24M, ePHYType, &byTxRate, &byRsvTime); VNSvOutPortW(pDevice->PortOffset + MAC_REG_RSPINF_A_24, MAKEWORD(byTxRate,byRsvTime)); //RSPINF_a_36 - s_vCalculateOFDMRParameter(CARDwGetOFDMControlRate((void *)pDevice, RATE_36M), + s_vCaculateOFDMRParameter(CARDwGetOFDMControlRate((void *)pDevice, RATE_36M), ePHYType, &byTxRate, &byRsvTime); VNSvOutPortW(pDevice->PortOffset + MAC_REG_RSPINF_A_36, MAKEWORD(byTxRate,byRsvTime)); //RSPINF_a_48 - s_vCalculateOFDMRParameter(CARDwGetOFDMControlRate((void *)pDevice, RATE_48M), + s_vCaculateOFDMRParameter(CARDwGetOFDMControlRate((void *)pDevice, RATE_48M), ePHYType, &byTxRate, &byRsvTime); VNSvOutPortW(pDevice->PortOffset + MAC_REG_RSPINF_A_48, MAKEWORD(byTxRate,byRsvTime)); //RSPINF_a_54 - s_vCalculateOFDMRParameter(CARDwGetOFDMControlRate((void *)pDevice, RATE_54M), + s_vCaculateOFDMRParameter(CARDwGetOFDMControlRate((void *)pDevice, RATE_54M), ePHYType, &byTxRate, &byRsvTime); VNSvOutPortW(pDevice->PortOffset + MAC_REG_RSPINF_A_54, MAKEWORD(byTxRate,byRsvTime)); //RSPINF_a_72 - s_vCalculateOFDMRParameter(CARDwGetOFDMControlRate((void *)pDevice, RATE_54M), + s_vCaculateOFDMRParameter(CARDwGetOFDMControlRate((void *)pDevice, RATE_54M), ePHYType, &byTxRate, &byRsvTime); @@ -2042,7 +2041,7 @@ bool CARDbSoftwareReset (void *pDeviceHandler) /* - * Description: Calculate TSF offset of two TSF input + * Description: Caculate TSF offset of two TSF input * Get TSF Offset from RxBCN's TSF and local TSF * * Parameters: diff --git a/trunk/drivers/staging/vt6655/datarate.c b/trunk/drivers/staging/vt6655/datarate.c index b86ec1b6d187..efbb8f45f728 100644 --- a/trunk/drivers/staging/vt6655/datarate.c +++ b/trunk/drivers/staging/vt6655/datarate.c @@ -126,7 +126,7 @@ DATARATEbyGetRateIdx ( /*+ * * Routine Description: - * Rate fallback Algorithm Implementation + * Rate fallback Algorithm Implementaion * * Parameters: * In: diff --git a/trunk/drivers/staging/vt6655/device.h b/trunk/drivers/staging/vt6655/device.h index e54e00bc5665..c5e6b98d3e4e 100644 --- a/trunk/drivers/staging/vt6655/device.h +++ b/trunk/drivers/staging/vt6655/device.h @@ -327,7 +327,7 @@ typedef struct tagSDeFragControlBlock //flags for driver status #define DEVICE_FLAGS_OPENED 0x00010000UL #define DEVICE_FLAGS_WOL_ENABLED 0x00080000UL -//flags for capabilities +//flags for capbilities #define DEVICE_FLAGS_TX_ALIGN 0x01000000UL #define DEVICE_FLAGS_HAVE_CAM 0x02000000UL #define DEVICE_FLAGS_FLOW_CTRL 0x04000000UL @@ -567,7 +567,7 @@ typedef struct __device_info { bool bPrvActive4RadioOFF; bool bGPIOBlockRead; - // Beacon related + // Beacon releated unsigned short wSeqCounter; unsigned short wBCNBufLen; bool bBeaconBufReady; diff --git a/trunk/drivers/staging/vt6655/device_main.c b/trunk/drivers/staging/vt6655/device_main.c index 9e3b3f2bbe53..89d1c22695a0 100644 --- a/trunk/drivers/staging/vt6655/device_main.c +++ b/trunk/drivers/staging/vt6655/device_main.c @@ -290,7 +290,7 @@ DEFINE_PCI_DEVICE_TABLE(vt6655_pci_id_table) = { static int vt6655_probe(struct pci_dev *pcid, const struct pci_device_id *ent); -static void vt6655_init_info(struct pci_dev* pcid, PSDevice* ppDevice, PCHIP_INFO); +static bool vt6655_init_info(struct pci_dev* pcid, PSDevice* ppDevice, PCHIP_INFO); static void device_free_info(PSDevice pDevice); static bool device_get_pci_info(PSDevice, struct pci_dev* pcid); static void device_print_info(PSDevice pDevice); @@ -347,22 +347,21 @@ static int Config_FileGetParameter(unsigned char *string, -static char* get_chip_name(int chip_id) -{ - int i; - for (i = 0; chip_info_table[i].name != NULL; i++) - if (chip_info_table[i].chip_id == chip_id) - break; - return chip_info_table[i].name; +static char* get_chip_name(int chip_id) { + int i; + for (i=0;chip_info_table[i].name!=NULL;i++) + if (chip_info_table[i].chip_id==chip_id) + break; + return chip_info_table[i].name; } static void __devexit vt6655_remove(struct pci_dev *pcid) { - PSDevice pDevice = pci_get_drvdata(pcid); + PSDevice pDevice=pci_get_drvdata(pcid); - if (pDevice == NULL) - return; - device_free_info(pDevice); + if (pDevice==NULL) + return; + device_free_info(pDevice); } @@ -398,29 +397,31 @@ device_set_bool_opt(unsigned int *opt, int val,bool def,u32 flag, char* name,cha } } */ -static void device_get_options(PSDevice pDevice, int index, char* devname) -{ - POPTIONS pOpts = &(pDevice->sOpts); - - pOpts->nRxDescs0 = RX_DESC_DEF0; - pOpts->nRxDescs1 = RX_DESC_DEF1; - pOpts->nTxDescs[0] = TX_DESC_DEF0; - pOpts->nTxDescs[1] = TX_DESC_DEF1; - pOpts->flags |= DEVICE_FLAGS_IP_ALIGN; - pOpts->int_works = INT_WORKS_DEF; - pOpts->rts_thresh = RTS_THRESH_DEF; - pOpts->frag_thresh = FRAG_THRESH_DEF; - pOpts->data_rate = DATA_RATE_DEF; - pOpts->channel_num = CHANNEL_DEF; - - pOpts->flags |= DEVICE_FLAGS_PREAMBLE_TYPE; - pOpts->flags |= DEVICE_FLAGS_OP_MODE; - //pOpts->flags|=DEVICE_FLAGS_PS_MODE; - pOpts->short_retry = SHORT_RETRY_DEF; - pOpts->long_retry = LONG_RETRY_DEF; - pOpts->bbp_type = BBP_TYPE_DEF; - pOpts->flags |= DEVICE_FLAGS_80211h_MODE; - pOpts->flags |= DEVICE_FLAGS_DiversityANT; +static void +device_get_options(PSDevice pDevice, int index, char* devname) { + + POPTIONS pOpts = &(pDevice->sOpts); + pOpts->nRxDescs0=RX_DESC_DEF0; + pOpts->nRxDescs1=RX_DESC_DEF1; + pOpts->nTxDescs[0]=TX_DESC_DEF0; + pOpts->nTxDescs[1]=TX_DESC_DEF1; +pOpts->flags|=DEVICE_FLAGS_IP_ALIGN; + pOpts->int_works=INT_WORKS_DEF; + pOpts->rts_thresh=RTS_THRESH_DEF; + pOpts->frag_thresh=FRAG_THRESH_DEF; + pOpts->data_rate=DATA_RATE_DEF; + pOpts->channel_num=CHANNEL_DEF; + +pOpts->flags|=DEVICE_FLAGS_PREAMBLE_TYPE; +pOpts->flags|=DEVICE_FLAGS_OP_MODE; +//pOpts->flags|=DEVICE_FLAGS_PS_MODE; + pOpts->short_retry=SHORT_RETRY_DEF; + pOpts->long_retry=LONG_RETRY_DEF; + pOpts->bbp_type=BBP_TYPE_DEF; +pOpts->flags|=DEVICE_FLAGS_80211h_MODE; +pOpts->flags|=DEVICE_FLAGS_DiversityANT; + + } static void @@ -517,7 +518,7 @@ static void s_vCompleteCurrentMeasure (PSDevice pDevice, unsigned char byResult) // -// Initialisation of MAC & BBP registers +// Initialiation of MAC & BBP registers // static void device_init_registers(PSDevice pDevice, DEVICE_INIT_TYPE InitType) @@ -893,15 +894,18 @@ static bool device_release_WPADEV(PSDevice pDevice) return true; } + static const struct net_device_ops device_netdev_ops = { - .ndo_open = device_open, - .ndo_stop = device_close, - .ndo_do_ioctl = device_ioctl, - .ndo_get_stats = device_get_stats, - .ndo_start_xmit = device_xmit, - .ndo_set_rx_mode = device_set_multi, + .ndo_open = device_open, + .ndo_stop = device_close, + .ndo_do_ioctl = device_ioctl, + .ndo_get_stats = device_get_stats, + .ndo_start_xmit = device_xmit, + .ndo_set_rx_mode = device_set_multi, }; + + static int __devinit vt6655_probe(struct pci_dev *pcid, const struct pci_device_id *ent) { @@ -922,7 +926,7 @@ vt6655_probe(struct pci_dev *pcid, const struct pci_device_id *ent) if (dev == NULL) { printk(KERN_ERR DEVICE_NAME ": allocate net device failed \n"); - return -ENOMEM; + return -ENODEV; } // Chain it all together @@ -935,7 +939,9 @@ vt6655_probe(struct pci_dev *pcid, const struct pci_device_id *ent) bFirst=false; } - vt6655_init_info(pcid, &pDevice, pChip_info); + if (!vt6655_init_info(pcid, &pDevice, pChip_info)) { + return -ENOMEM; + } pDevice->dev = dev; pDevice->next_module = root_device_dev; root_device_dev = dev; @@ -1058,7 +1064,7 @@ vt6655_probe(struct pci_dev *pcid, const struct pci_device_id *ent) //Mask out the options cannot be set to the chip pDevice->sOpts.flags &= pChip_info->flags; - //Enable the chip specified capabilities + //Enable the chip specified capbilities pDevice->flags = pDevice->sOpts.flags | (pChip_info->flags & 0xFF000000UL); pDevice->tx_80211 = device_dma0_tx_80211; pDevice->sMgmtObj.pAdapter = (void *)pDevice; @@ -1099,7 +1105,7 @@ static void device_print_info(PSDevice pDevice) } -static void __devinit vt6655_init_info(struct pci_dev* pcid, PSDevice* ppDevice, +static bool __devinit vt6655_init_info(struct pci_dev* pcid, PSDevice* ppDevice, PCHIP_INFO pChip_info) { PSDevice p; @@ -1123,6 +1129,8 @@ static void __devinit vt6655_init_info(struct pci_dev* pcid, PSDevice* ppDevice, (*ppDevice)->multicast_limit =32; spin_lock_init(&((*ppDevice)->lock)); + + return true; } static bool device_get_pci_info(PSDevice pDevice, struct pci_dev* pcid) { @@ -1670,7 +1678,7 @@ static int device_tx_srv(PSDevice pDevice, unsigned int uIdx) { uFrameSize = pTD->pTDInfo->dwReqCount - uFIFOHeaderSize; pTxBufHead = (PSTxBufHead) (pTD->pTDInfo->buf); // Update the statistics based on the Transmit status - // now, we DONT check TSR0_CDH + // now, we DO'NT check TSR0_CDH STAvUpdateTDStatCounter(&pDevice->scStatistic, byTsr0, byTsr1, @@ -2652,7 +2660,7 @@ static irqreturn_t device_intr(int irq, void *dev_instance) { (pDevice->byLocalID != REV_ID_VT3253_B0) && (pDevice->bBSSIDFilter == true)) { // update RSSI - //BBbReadEmbedded(pDevice->PortOffset, 0x3E, &byRSSI); + //BBbReadEmbeded(pDevice->PortOffset, 0x3E, &byRSSI); //pDevice->uCurrRSSI = byRSSI; } */ diff --git a/trunk/drivers/staging/vt6655/dpc.c b/trunk/drivers/staging/vt6655/dpc.c index 373e9e4fc87d..e8a71ba4b92c 100644 --- a/trunk/drivers/staging/vt6655/dpc.c +++ b/trunk/drivers/staging/vt6655/dpc.c @@ -718,7 +718,7 @@ device_receive_frame ( if ((*pbyRSSI != 0) && (pMgmt->pCurrBSS!=NULL)) { RFvRSSITodBm(pDevice, *pbyRSSI, &ldBm); - // Monitor if RSSI is too strong. + // Moniter if RSSI is too strong. pMgmt->pCurrBSS->byRSSIStatCnt++; pMgmt->pCurrBSS->byRSSIStatCnt %= RSSI_STAT_COUNT; pMgmt->pCurrBSS->ldBmAverage[pMgmt->pCurrBSS->byRSSIStatCnt] = ldBm; diff --git a/trunk/drivers/staging/vt6655/hostap.c b/trunk/drivers/staging/vt6655/hostap.c index 67b1b88b1b89..6ac6f452b261 100644 --- a/trunk/drivers/staging/vt6655/hostap.c +++ b/trunk/drivers/staging/vt6655/hostap.c @@ -495,7 +495,9 @@ static int hostap_set_encryption(PSDevice pDevice, return -EINVAL; } - if (is_broadcast_ether_addr(param->sta_addr)) { + if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff && + param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff && + param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) { if (param->u.crypt.idx >= MAX_GROUP_KEY) return -EINVAL; iNodeIndex = 0; @@ -714,7 +716,9 @@ static int hostap_get_encryption(PSDevice pDevice, param->u.crypt.err = 0; - if (is_broadcast_ether_addr(param->sta_addr)) { + if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff && + param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff && + param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) { iNodeIndex = 0; } else { if (BSSDBbIsSTAInNodeDB(pMgmt, param->sta_addr, &iNodeIndex) == false) { diff --git a/trunk/drivers/staging/vt6655/ioctl.c b/trunk/drivers/staging/vt6655/ioctl.c index afed6e33dfc7..ef197efab049 100644 --- a/trunk/drivers/staging/vt6655/ioctl.c +++ b/trunk/drivers/staging/vt6655/ioctl.c @@ -111,7 +111,7 @@ int private_ioctl(PSDevice pDevice, struct ifreq *rq) break; case WLAN_CMD_ZONETYPE_SET: - /* mike add :can't support. */ + /* mike add :cann't support. */ result = -EOPNOTSUPP; break; @@ -539,8 +539,11 @@ int private_ioctl(PSDevice pDevice, struct ifreq *rq) pMgmt->abyIBSSSuppRates[3] |= BIT7; } - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Support Rate= %*ph\n", - 4, pMgmt->abyIBSSSuppRates + 2); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Support Rate= %x %x %x %x\n", + pMgmt->abyIBSSSuppRates[2], + pMgmt->abyIBSSSuppRates[3], + pMgmt->abyIBSSSuppRates[4], + pMgmt->abyIBSSSuppRates[5]); netif_stop_queue(pDevice->dev); spin_lock_irq(&pDevice->lock); diff --git a/trunk/drivers/staging/vt6655/iwctl.c b/trunk/drivers/staging/vt6655/iwctl.c index 5cdda8dab854..77aad7f5ae76 100644 --- a/trunk/drivers/staging/vt6655/iwctl.c +++ b/trunk/drivers/staging/vt6655/iwctl.c @@ -358,7 +358,7 @@ int iwctl_giwscan(struct net_device *dev, /* - * Wireless Handler : set frequency or channel + * Wireless Handler : set frequence or channel */ int iwctl_siwfreq(struct net_device *dev, @@ -404,7 +404,7 @@ int iwctl_siwfreq(struct net_device *dev, } /* - * Wireless Handler : get frequency or channel + * Wireless Handler : get frequence or channel */ int iwctl_giwfreq(struct net_device *dev, @@ -1346,7 +1346,7 @@ if((wrq->flags & IW_ENCODE_DISABLED)==0){ }else if(index>0){ //when the length is 0 the request only changes the default transmit key index - //check the new key if it has a non zero length + //check the new key has a non zero lenget if(pDevice->bEncryptionEnable==false) { rc = -EINVAL; diff --git a/trunk/drivers/staging/vt6655/key.c b/trunk/drivers/staging/vt6655/key.c index 194fedc715fa..774b0d4a7e06 100644 --- a/trunk/drivers/staging/vt6655/key.c +++ b/trunk/drivers/staging/vt6655/key.c @@ -372,7 +372,7 @@ bool KeybRemoveKey ( int i; if (is_broadcast_ether_addr(pbyBSSID)) { - // delete all keys + // dealte all key if ((dwKeyIndex & PAIRWISE_KEY) != 0) { for (i=0;iKeyTable[i].PairwiseKey.bKeyValid = false; diff --git a/trunk/drivers/staging/vt6655/mac.c b/trunk/drivers/staging/vt6655/mac.c index 30c261579412..f8d1651341f8 100644 --- a/trunk/drivers/staging/vt6655/mac.c +++ b/trunk/drivers/staging/vt6655/mac.c @@ -56,9 +56,9 @@ * MACbSafeStop - Stop MAC function * MACbShutdown - Shut down MAC * MACvInitialize - Initialize MAC - * MACvSetCurrRxDescAddr - Set Rx Descriptors Address - * MACvSetCurrTx0DescAddr - Set Tx0 Descriptors Address - * MACvSetCurrTx1DescAddr - Set Tx1 Descriptors Address + * MACvSetCurrRxDescAddr - Set Rx Descriptos Address + * MACvSetCurrTx0DescAddr - Set Tx0 Descriptos Address + * MACvSetCurrTx1DescAddr - Set Tx1 Descriptos Address * MACvTimer0MicroSDelay - Micro Second Delay Loop by MAC * * Revision History: @@ -1498,7 +1498,7 @@ int ii; wOffset += (uKeyIdx * 4); for (ii=0;ii<4;ii++) { - // always push 128 bits + // alway push 128 bits DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"3.(%d) wOffset: %d, Data: %lX\n", ii, wOffset+ii, *pdwKey); VNSvOutPortW(dwIoBase + MAC_REG_MISCFFNDEX, wOffset+ii); VNSvOutPortD(dwIoBase + MAC_REG_MISCFFDATA, *pdwKey++); @@ -1567,7 +1567,7 @@ int ii; wOffset++; wOffset++; wOffset += (uKeyIdx * 4); - // always push 128 bits + // alway push 128 bits for (ii=0; ii<3; ii++) { DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"(%d) wOffset: %d, Data: %lX\n", ii, wOffset+ii, *pdwKey); VNSvOutPortW(dwIoBase + MAC_REG_MISCFFNDEX, wOffset+ii); @@ -1696,7 +1696,7 @@ int ii; wOffset += (uKeyIdx * 4); DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"1. wOffset: %d, Data: %lX, idx:%d\n", wOffset, *pdwKey, uKeyIdx); - // always push 128 bits + // alway push 128 bits for (ii=0; ii<4; ii++) { DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"2.(%d) wOffset: %d, Data: %lX\n", ii, wOffset+ii, *pdwKey); VNSvOutPortW(dwIoBase + MAC_REG_MISCFFNDEX, wOffset+ii); diff --git a/trunk/drivers/staging/vt6655/mac.h b/trunk/drivers/staging/vt6655/mac.h index adfb366f4901..e3ccfee90268 100644 --- a/trunk/drivers/staging/vt6655/mac.h +++ b/trunk/drivers/staging/vt6655/mac.h @@ -586,7 +586,7 @@ #define PKT_TYPE_NONE 0x00 // turn off receiver #define PKT_TYPE_ALL_MULTICAST 0x80 #define PKT_TYPE_PROMISCUOUS 0x40 -#define PKT_TYPE_DIRECTED 0x20 // obsolete, directed address is always accepted +#define PKT_TYPE_DIRECTED 0x20 // obselete, directed address is always accepted #define PKT_TYPE_BROADCAST 0x10 #define PKT_TYPE_MULTICAST 0x08 #define PKT_TYPE_ERROR_WPA 0x04 diff --git a/trunk/drivers/staging/vt6655/mib.c b/trunk/drivers/staging/vt6655/mib.c index 63ae4adddf2f..1b91a8370954 100644 --- a/trunk/drivers/staging/vt6655/mib.c +++ b/trunk/drivers/staging/vt6655/mib.c @@ -191,7 +191,7 @@ void STAvUpdateRDStatCounter (PSStatCounter pStatistic, pStatistic->ullRsrOK++; if (cbFrameLength >= ETH_ALEN) { - // update counters in case of successful transmit + // update counters in case that successful transmit if (byRSR & RSR_ADDRBROAD) { pStatistic->ullRxBroadcastFrames++; pStatistic->ullRxBroadcastBytes += (unsigned long long) cbFrameLength; diff --git a/trunk/drivers/staging/vt6655/power.c b/trunk/drivers/staging/vt6655/power.c index 661d534304cc..4c0b02e8f0b5 100644 --- a/trunk/drivers/staging/vt6655/power.c +++ b/trunk/drivers/staging/vt6655/power.c @@ -207,7 +207,7 @@ PSbConsiderPowerDown( if (pDevice->bCmdRunning) return false; - // Force PSEN on + // Froce PSEN on MACvRegBitsOn(pDevice->PortOffset, MAC_REG_PSCTL, PSCTL_PSEN); // check if all TD are empty, diff --git a/trunk/drivers/staging/vt6655/rf.c b/trunk/drivers/staging/vt6655/rf.c index aaa231aaf4e9..aa696650b86c 100644 --- a/trunk/drivers/staging/vt6655/rf.c +++ b/trunk/drivers/staging/vt6655/rf.c @@ -26,7 +26,7 @@ * Date: Feb. 19, 2004 * * Functions: - * IFRFbWriteEmbedded - Embedded write RF register via MAC + * IFRFbWriteEmbeded - Embeded write RF register via MAC * * Revision History: * @@ -453,18 +453,18 @@ bool s_bAL7230Init (unsigned long dwIoBase) BBvPowerSaveModeOFF(dwIoBase); //RobertYu:20050106, have DC value for Calibration for (ii = 0; ii < CB_AL7230_INIT_SEQ; ii++) - bResult &= IFRFbWriteEmbedded(dwIoBase, dwAL7230InitTable[ii]); + bResult &= IFRFbWriteEmbeded(dwIoBase, dwAL7230InitTable[ii]); // PLL On MACvWordRegBitsOn(dwIoBase, MAC_REG_SOFTPWRCTL, SOFTPWRCTL_SWPE3); //Calibration MACvTimer0MicroSDelay(dwIoBase, 150);//150us - bResult &= IFRFbWriteEmbedded(dwIoBase, (0x9ABA8F00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW)); //TXDCOC:active, RCK:disable + bResult &= IFRFbWriteEmbeded(dwIoBase, (0x9ABA8F00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW)); //TXDCOC:active, RCK:diable MACvTimer0MicroSDelay(dwIoBase, 30);//30us - bResult &= IFRFbWriteEmbedded(dwIoBase, (0x3ABA8F00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW)); //TXDCOC:disable, RCK:active + bResult &= IFRFbWriteEmbeded(dwIoBase, (0x3ABA8F00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW)); //TXDCOC:diable, RCK:active MACvTimer0MicroSDelay(dwIoBase, 30);//30us - bResult &= IFRFbWriteEmbedded(dwIoBase, dwAL7230InitTable[CB_AL7230_INIT_SEQ-1]); //TXDCOC:disable, RCK:disable + bResult &= IFRFbWriteEmbeded(dwIoBase, dwAL7230InitTable[CB_AL7230_INIT_SEQ-1]); //TXDCOC:diable, RCK:diable MACvWordRegBitsOn(dwIoBase, MAC_REG_SOFTPWRCTL, (SOFTPWRCTL_SWPE3 | SOFTPWRCTL_SWPE2 | @@ -490,9 +490,9 @@ bool s_bAL7230SelectChannel (unsigned long dwIoBase, unsigned char byChannel) // PLLON Off MACvWordRegBitsOff(dwIoBase, MAC_REG_SOFTPWRCTL, SOFTPWRCTL_SWPE3); - bResult &= IFRFbWriteEmbedded (dwIoBase, dwAL7230ChannelTable0[byChannel-1]); //Reg0 - bResult &= IFRFbWriteEmbedded (dwIoBase, dwAL7230ChannelTable1[byChannel-1]); //Reg1 - bResult &= IFRFbWriteEmbedded (dwIoBase, dwAL7230ChannelTable2[byChannel-1]); //Reg4 + bResult &= IFRFbWriteEmbeded (dwIoBase, dwAL7230ChannelTable0[byChannel-1]); //Reg0 + bResult &= IFRFbWriteEmbeded (dwIoBase, dwAL7230ChannelTable1[byChannel-1]); //Reg1 + bResult &= IFRFbWriteEmbeded (dwIoBase, dwAL7230ChannelTable2[byChannel-1]); //Reg4 // PLLOn On MACvWordRegBitsOn(dwIoBase, MAC_REG_SOFTPWRCTL, SOFTPWRCTL_SWPE3); @@ -574,7 +574,7 @@ bool s_bAL7230SelectChannel (unsigned long dwIoBase, unsigned char byChannel) /*--------------------- Export Functions --------------------------*/ /* - * Description: Write to IF/RF, by embedded programming + * Description: Write to IF/RF, by embeded programming * * Parameters: * In: @@ -586,7 +586,7 @@ bool s_bAL7230SelectChannel (unsigned long dwIoBase, unsigned char byChannel) * Return Value: true if succeeded; false if failed. * */ -bool IFRFbWriteEmbedded (unsigned long dwIoBase, unsigned long dwData) +bool IFRFbWriteEmbeded (unsigned long dwIoBase, unsigned long dwData) { unsigned short ww; unsigned long dwValue; @@ -669,11 +669,11 @@ bool RFbAL2230Init (unsigned long dwIoBase) //patch abnormal AL2230 frequency output //2008-8-21 chester - IFRFbWriteEmbedded(dwIoBase, (0x07168700+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW)); + IFRFbWriteEmbeded(dwIoBase, (0x07168700+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW)); for (ii = 0; ii < CB_AL2230_INIT_SEQ; ii++) - bResult &= IFRFbWriteEmbedded(dwIoBase, dwAL2230InitTable[ii]); + bResult &= IFRFbWriteEmbeded(dwIoBase, dwAL2230InitTable[ii]); //2008-8-21 chester MACvTimer0MicroSDelay(dwIoBase, 30); //delay 30 us @@ -681,11 +681,11 @@ MACvTimer0MicroSDelay(dwIoBase, 30); //delay 30 us MACvWordRegBitsOn(dwIoBase, MAC_REG_SOFTPWRCTL, SOFTPWRCTL_SWPE3); MACvTimer0MicroSDelay(dwIoBase, 150);//150us - bResult &= IFRFbWriteEmbedded(dwIoBase, (0x00d80f00+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW)); + bResult &= IFRFbWriteEmbeded(dwIoBase, (0x00d80f00+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW)); MACvTimer0MicroSDelay(dwIoBase, 30);//30us - bResult &= IFRFbWriteEmbedded(dwIoBase, (0x00780f00+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW)); + bResult &= IFRFbWriteEmbeded(dwIoBase, (0x00780f00+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW)); MACvTimer0MicroSDelay(dwIoBase, 30);//30us - bResult &= IFRFbWriteEmbedded(dwIoBase, dwAL2230InitTable[CB_AL2230_INIT_SEQ-1]); + bResult &= IFRFbWriteEmbeded(dwIoBase, dwAL2230InitTable[CB_AL2230_INIT_SEQ-1]); MACvWordRegBitsOn(dwIoBase, MAC_REG_SOFTPWRCTL, (SOFTPWRCTL_SWPE3 | SOFTPWRCTL_SWPE2 | @@ -704,8 +704,8 @@ bool RFbAL2230SelectChannel (unsigned long dwIoBase, unsigned char byChannel) bResult = true; - bResult &= IFRFbWriteEmbedded (dwIoBase, dwAL2230ChannelTable0[byChannel-1]); - bResult &= IFRFbWriteEmbedded (dwIoBase, dwAL2230ChannelTable1[byChannel-1]); + bResult &= IFRFbWriteEmbeded (dwIoBase, dwAL2230ChannelTable0[byChannel-1]); + bResult &= IFRFbWriteEmbeded (dwIoBase, dwAL2230ChannelTable1[byChannel-1]); // Set Channel[7] = 0 to tell H/W channel is changing now. VNSvOutPortB(dwIoBase + MAC_REG_CHANNEL, (byChannel & 0x7F)); @@ -817,7 +817,7 @@ bool bResult = true; switch (pDevice->byRFType) { case RF_AIROHA7230 : - bResult = IFRFbWriteEmbedded (pDevice->PortOffset, 0x1ABAEF00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW); + bResult = IFRFbWriteEmbeded (pDevice->PortOffset, 0x1ABAEF00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW); break; default : bResult = true; @@ -1072,23 +1072,23 @@ unsigned long dwMax7230Pwr = 0; switch (pDevice->byRFType) { case RF_AIROHA : - bResult &= IFRFbWriteEmbedded(pDevice->PortOffset, dwAL2230PowerTable[byPwr]); + bResult &= IFRFbWriteEmbeded(pDevice->PortOffset, dwAL2230PowerTable[byPwr]); if (uRATE <= RATE_11M) { - bResult &= IFRFbWriteEmbedded(pDevice->PortOffset, 0x0001B400+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW); + bResult &= IFRFbWriteEmbeded(pDevice->PortOffset, 0x0001B400+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW); } else { - bResult &= IFRFbWriteEmbedded(pDevice->PortOffset, 0x0005A400+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW); + bResult &= IFRFbWriteEmbeded(pDevice->PortOffset, 0x0005A400+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW); } break; case RF_AL2230S : - bResult &= IFRFbWriteEmbedded(pDevice->PortOffset, dwAL2230PowerTable[byPwr]); + bResult &= IFRFbWriteEmbeded(pDevice->PortOffset, dwAL2230PowerTable[byPwr]); if (uRATE <= RATE_11M) { - bResult &= IFRFbWriteEmbedded(pDevice->PortOffset, 0x040C1400+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW); - bResult &= IFRFbWriteEmbedded(pDevice->PortOffset, 0x00299B00+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW); + bResult &= IFRFbWriteEmbeded(pDevice->PortOffset, 0x040C1400+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW); + bResult &= IFRFbWriteEmbeded(pDevice->PortOffset, 0x00299B00+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW); }else { - bResult &= IFRFbWriteEmbedded(pDevice->PortOffset, 0x0005A400+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW); - bResult &= IFRFbWriteEmbedded(pDevice->PortOffset, 0x00099B00+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW); + bResult &= IFRFbWriteEmbeded(pDevice->PortOffset, 0x0005A400+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW); + bResult &= IFRFbWriteEmbeded(pDevice->PortOffset, 0x00099B00+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW); } break; @@ -1098,7 +1098,7 @@ unsigned long dwMax7230Pwr = 0; dwMax7230Pwr = 0x080C0B00 | ( (byPwr) << 12 ) | (BY_AL7230_REG_LEN << 3 ) | IFREGCTL_REGW; - bResult &= IFRFbWriteEmbedded(pDevice->PortOffset, dwMax7230Pwr); + bResult &= IFRFbWriteEmbeded(pDevice->PortOffset, dwMax7230Pwr); break; @@ -1166,24 +1166,24 @@ bool RFbAL7230SelectChannelPostProcess (unsigned long dwIoBase, unsigned char by if( (byOldChannel <= CB_MAX_CHANNEL_24G) && (byNewChannel > CB_MAX_CHANNEL_24G) ) { // Change from 2.4G to 5G - bResult &= IFRFbWriteEmbedded(dwIoBase, dwAL7230InitTableAMode[2]); //Reg2 - bResult &= IFRFbWriteEmbedded(dwIoBase, dwAL7230InitTableAMode[3]); //Reg3 - bResult &= IFRFbWriteEmbedded(dwIoBase, dwAL7230InitTableAMode[5]); //Reg5 - bResult &= IFRFbWriteEmbedded(dwIoBase, dwAL7230InitTableAMode[7]); //Reg7 - bResult &= IFRFbWriteEmbedded(dwIoBase, dwAL7230InitTableAMode[10]);//Reg10 - bResult &= IFRFbWriteEmbedded(dwIoBase, dwAL7230InitTableAMode[12]);//Reg12 - bResult &= IFRFbWriteEmbedded(dwIoBase, dwAL7230InitTableAMode[15]);//Reg15 + bResult &= IFRFbWriteEmbeded(dwIoBase, dwAL7230InitTableAMode[2]); //Reg2 + bResult &= IFRFbWriteEmbeded(dwIoBase, dwAL7230InitTableAMode[3]); //Reg3 + bResult &= IFRFbWriteEmbeded(dwIoBase, dwAL7230InitTableAMode[5]); //Reg5 + bResult &= IFRFbWriteEmbeded(dwIoBase, dwAL7230InitTableAMode[7]); //Reg7 + bResult &= IFRFbWriteEmbeded(dwIoBase, dwAL7230InitTableAMode[10]);//Reg10 + bResult &= IFRFbWriteEmbeded(dwIoBase, dwAL7230InitTableAMode[12]);//Reg12 + bResult &= IFRFbWriteEmbeded(dwIoBase, dwAL7230InitTableAMode[15]);//Reg15 } else if( (byOldChannel > CB_MAX_CHANNEL_24G) && (byNewChannel <= CB_MAX_CHANNEL_24G) ) { // change from 5G to 2.4G - bResult &= IFRFbWriteEmbedded(dwIoBase, dwAL7230InitTable[2]); //Reg2 - bResult &= IFRFbWriteEmbedded(dwIoBase, dwAL7230InitTable[3]); //Reg3 - bResult &= IFRFbWriteEmbedded(dwIoBase, dwAL7230InitTable[5]); //Reg5 - bResult &= IFRFbWriteEmbedded(dwIoBase, dwAL7230InitTable[7]); //Reg7 - bResult &= IFRFbWriteEmbedded(dwIoBase, dwAL7230InitTable[10]);//Reg10 - bResult &= IFRFbWriteEmbedded(dwIoBase, dwAL7230InitTable[12]);//Reg12 - bResult &= IFRFbWriteEmbedded(dwIoBase, dwAL7230InitTable[15]);//Reg15 + bResult &= IFRFbWriteEmbeded(dwIoBase, dwAL7230InitTable[2]); //Reg2 + bResult &= IFRFbWriteEmbeded(dwIoBase, dwAL7230InitTable[3]); //Reg3 + bResult &= IFRFbWriteEmbeded(dwIoBase, dwAL7230InitTable[5]); //Reg5 + bResult &= IFRFbWriteEmbeded(dwIoBase, dwAL7230InitTable[7]); //Reg7 + bResult &= IFRFbWriteEmbeded(dwIoBase, dwAL7230InitTable[10]);//Reg10 + bResult &= IFRFbWriteEmbeded(dwIoBase, dwAL7230InitTable[12]);//Reg12 + bResult &= IFRFbWriteEmbeded(dwIoBase, dwAL7230InitTable[15]);//Reg15 } return bResult; diff --git a/trunk/drivers/staging/vt6655/rf.h b/trunk/drivers/staging/vt6655/rf.h index 1da0fdeb2e1c..73f09693ee7a 100644 --- a/trunk/drivers/staging/vt6655/rf.h +++ b/trunk/drivers/staging/vt6655/rf.h @@ -75,7 +75,7 @@ /*--------------------- Export Functions --------------------------*/ -bool IFRFbWriteEmbedded(unsigned long dwIoBase, unsigned long dwData); +bool IFRFbWriteEmbeded(unsigned long dwIoBase, unsigned long dwData); bool RFbSelectChannel(unsigned long dwIoBase, unsigned char byRFType, unsigned char byChannel); bool RFbInit ( PSDevice pDevice diff --git a/trunk/drivers/staging/vt6655/rxtx.c b/trunk/drivers/staging/vt6655/rxtx.c index 4972e57845c2..6935b37d5444 100644 --- a/trunk/drivers/staging/vt6655/rxtx.c +++ b/trunk/drivers/staging/vt6655/rxtx.c @@ -27,7 +27,7 @@ * Functions: * s_vGenerateTxParameter - Generate tx dma required parameter. * vGenerateMACHeader - Translate 802.3 to 802.11 header - * cbGetFragCount - Calculate fragment number count + * cbGetFragCount - Caculate fragment number count * csBeacon_xmit - beacon tx function * csMgmt_xmit - management tx function * s_cbFillTxBufHead - fulfill tx dma buffer header @@ -733,11 +733,11 @@ s_uFillDataHead ( if (byFBOption == AUTO_FB_NONE) { PSTxDataHead_g pBuf = (PSTxDataHead_g)pTxDataHead; //Get SignalField,ServiceField,Length - BBvCalculateParameter(pDevice, cbFrameLength, wCurrentRate, byPktType, + BBvCaculateParameter(pDevice, cbFrameLength, wCurrentRate, byPktType, (unsigned short *)&(wLen), (unsigned char *)&(pBuf->byServiceField_a), (unsigned char *)&(pBuf->bySignalField_a) ); pBuf->wTransmitLength_a = cpu_to_le16(wLen); - BBvCalculateParameter(pDevice, cbFrameLength, pDevice->byTopCCKBasicRate, PK_TYPE_11B, + BBvCaculateParameter(pDevice, cbFrameLength, pDevice->byTopCCKBasicRate, PK_TYPE_11B, (unsigned short *)&(wLen), (unsigned char *)&(pBuf->byServiceField_b), (unsigned char *)&(pBuf->bySignalField_b) ); pBuf->wTransmitLength_b = cpu_to_le16(wLen); @@ -759,11 +759,11 @@ s_uFillDataHead ( // Auto Fallback PSTxDataHead_g_FB pBuf = (PSTxDataHead_g_FB)pTxDataHead; //Get SignalField,ServiceField,Length - BBvCalculateParameter(pDevice, cbFrameLength, wCurrentRate, byPktType, + BBvCaculateParameter(pDevice, cbFrameLength, wCurrentRate, byPktType, (unsigned short *)&(wLen), (unsigned char *)&(pBuf->byServiceField_a), (unsigned char *)&(pBuf->bySignalField_a) ); pBuf->wTransmitLength_a = cpu_to_le16(wLen); - BBvCalculateParameter(pDevice, cbFrameLength, pDevice->byTopCCKBasicRate, PK_TYPE_11B, + BBvCaculateParameter(pDevice, cbFrameLength, pDevice->byTopCCKBasicRate, PK_TYPE_11B, (unsigned short *)&(wLen), (unsigned char *)&(pBuf->byServiceField_b), (unsigned char *)&(pBuf->bySignalField_b) ); pBuf->wTransmitLength_b = cpu_to_le16(wLen); @@ -788,7 +788,7 @@ s_uFillDataHead ( // Auto Fallback PSTxDataHead_a_FB pBuf = (PSTxDataHead_a_FB)pTxDataHead; //Get SignalField,ServiceField,Length - BBvCalculateParameter(pDevice, cbFrameLength, wCurrentRate, byPktType, + BBvCaculateParameter(pDevice, cbFrameLength, wCurrentRate, byPktType, (unsigned short *)&(wLen), (unsigned char *)&(pBuf->byServiceField), (unsigned char *)&(pBuf->bySignalField) ); pBuf->wTransmitLength = cpu_to_le16(wLen); @@ -805,7 +805,7 @@ s_uFillDataHead ( } else { PSTxDataHead_ab pBuf = (PSTxDataHead_ab)pTxDataHead; //Get SignalField,ServiceField,Length - BBvCalculateParameter(pDevice, cbFrameLength, wCurrentRate, byPktType, + BBvCaculateParameter(pDevice, cbFrameLength, wCurrentRate, byPktType, (unsigned short *)&(wLen), (unsigned char *)&(pBuf->byServiceField), (unsigned char *)&(pBuf->bySignalField) ); pBuf->wTransmitLength = cpu_to_le16(wLen); @@ -823,7 +823,7 @@ s_uFillDataHead ( else { PSTxDataHead_ab pBuf = (PSTxDataHead_ab)pTxDataHead; //Get SignalField,ServiceField,Length - BBvCalculateParameter(pDevice, cbFrameLength, wCurrentRate, byPktType, + BBvCaculateParameter(pDevice, cbFrameLength, wCurrentRate, byPktType, (unsigned short *)&(wLen), (unsigned char *)&(pBuf->byServiceField), (unsigned char *)&(pBuf->bySignalField) ); pBuf->wTransmitLength = cpu_to_le16(wLen); @@ -871,11 +871,11 @@ s_vFillRTSHead ( if (byFBOption == AUTO_FB_NONE) { PSRTS_g pBuf = (PSRTS_g)pvRTS; //Get SignalField,ServiceField,Length - BBvCalculateParameter(pDevice, uRTSFrameLen, pDevice->byTopCCKBasicRate, PK_TYPE_11B, + BBvCaculateParameter(pDevice, uRTSFrameLen, pDevice->byTopCCKBasicRate, PK_TYPE_11B, (unsigned short *)&(wLen), (unsigned char *)&(pBuf->byServiceField_b), (unsigned char *)&(pBuf->bySignalField_b) ); pBuf->wTransmitLength_b = cpu_to_le16(wLen); - BBvCalculateParameter(pDevice, uRTSFrameLen, pDevice->byTopOFDMBasicRate, byPktType, + BBvCaculateParameter(pDevice, uRTSFrameLen, pDevice->byTopOFDMBasicRate, byPktType, (unsigned short *)&(wLen), (unsigned char *)&(pBuf->byServiceField_a), (unsigned char *)&(pBuf->bySignalField_a) ); pBuf->wTransmitLength_a = cpu_to_le16(wLen); @@ -904,11 +904,11 @@ s_vFillRTSHead ( else { PSRTS_g_FB pBuf = (PSRTS_g_FB)pvRTS; //Get SignalField,ServiceField,Length - BBvCalculateParameter(pDevice, uRTSFrameLen, pDevice->byTopCCKBasicRate, PK_TYPE_11B, + BBvCaculateParameter(pDevice, uRTSFrameLen, pDevice->byTopCCKBasicRate, PK_TYPE_11B, (unsigned short *)&(wLen), (unsigned char *)&(pBuf->byServiceField_b), (unsigned char *)&(pBuf->bySignalField_b) ); pBuf->wTransmitLength_b = cpu_to_le16(wLen); - BBvCalculateParameter(pDevice, uRTSFrameLen, pDevice->byTopOFDMBasicRate, byPktType, + BBvCaculateParameter(pDevice, uRTSFrameLen, pDevice->byTopOFDMBasicRate, byPktType, (unsigned short *)&(wLen), (unsigned char *)&(pBuf->byServiceField_a), (unsigned char *)&(pBuf->bySignalField_a) ); pBuf->wTransmitLength_a = cpu_to_le16(wLen); @@ -946,7 +946,7 @@ s_vFillRTSHead ( if (byFBOption == AUTO_FB_NONE) { PSRTS_ab pBuf = (PSRTS_ab)pvRTS; //Get SignalField,ServiceField,Length - BBvCalculateParameter(pDevice, uRTSFrameLen, pDevice->byTopOFDMBasicRate, byPktType, + BBvCaculateParameter(pDevice, uRTSFrameLen, pDevice->byTopOFDMBasicRate, byPktType, (unsigned short *)&(wLen), (unsigned char *)&(pBuf->byServiceField), (unsigned char *)&(pBuf->bySignalField) ); pBuf->wTransmitLength = cpu_to_le16(wLen); @@ -975,7 +975,7 @@ s_vFillRTSHead ( else { PSRTS_a_FB pBuf = (PSRTS_a_FB)pvRTS; //Get SignalField,ServiceField,Length - BBvCalculateParameter(pDevice, uRTSFrameLen, pDevice->byTopOFDMBasicRate, byPktType, + BBvCaculateParameter(pDevice, uRTSFrameLen, pDevice->byTopOFDMBasicRate, byPktType, (unsigned short *)&(wLen), (unsigned char *)&(pBuf->byServiceField), (unsigned char *)&(pBuf->bySignalField) ); pBuf->wTransmitLength = cpu_to_le16(wLen); @@ -1005,7 +1005,7 @@ s_vFillRTSHead ( else if (byPktType == PK_TYPE_11B) { PSRTS_ab pBuf = (PSRTS_ab)pvRTS; //Get SignalField,ServiceField,Length - BBvCalculateParameter(pDevice, uRTSFrameLen, pDevice->byTopCCKBasicRate, PK_TYPE_11B, + BBvCaculateParameter(pDevice, uRTSFrameLen, pDevice->byTopCCKBasicRate, PK_TYPE_11B, (unsigned short *)&(wLen), (unsigned char *)&(pBuf->byServiceField), (unsigned char *)&(pBuf->bySignalField) ); pBuf->wTransmitLength = cpu_to_le16(wLen); @@ -1065,7 +1065,7 @@ s_vFillCTSHead ( // Auto Fall back PSCTS_FB pBuf = (PSCTS_FB)pvCTS; //Get SignalField,ServiceField,Length - BBvCalculateParameter(pDevice, uCTSFrameLen, pDevice->byTopCCKBasicRate, PK_TYPE_11B, + BBvCaculateParameter(pDevice, uCTSFrameLen, pDevice->byTopCCKBasicRate, PK_TYPE_11B, (unsigned short *)&(wLen), (unsigned char *)&(pBuf->byServiceField_b), (unsigned char *)&(pBuf->bySignalField_b) ); @@ -1092,7 +1092,7 @@ s_vFillCTSHead ( } else { //if (byFBOption != AUTO_FB_NONE && uDMAIdx != TYPE_ATIMDMA && uDMAIdx != TYPE_BEACONDMA) PSCTS pBuf = (PSCTS)pvCTS; //Get SignalField,ServiceField,Length - BBvCalculateParameter(pDevice, uCTSFrameLen, pDevice->byTopCCKBasicRate, PK_TYPE_11B, + BBvCaculateParameter(pDevice, uCTSFrameLen, pDevice->byTopCCKBasicRate, PK_TYPE_11B, (unsigned short *)&(wLen), (unsigned char *)&(pBuf->byServiceField_b), (unsigned char *)&(pBuf->bySignalField_b) ); pBuf->wTransmitLength_b = cpu_to_le16(wLen); @@ -2568,7 +2568,7 @@ CMD_STATUS csMgmt_xmit(PSDevice pDevice, PSTxMgmtPacket pPacket) { if (bIsPSPOLL) { // The MAC will automatically replace the Duration-field of MAC header by Duration-field // of FIFO control header. - // This will cause AID-field of PS-POLL packet to be incorrect (Because PS-POLL's AID field is + // This will cause AID-field of PS-POLL packet be incorrect (Because PS-POLL's AID field is // in the same place of other packet's Duration-field). // And it will cause Cisco-AP to issue Disassociation-packet if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) { @@ -2664,7 +2664,7 @@ CMD_STATUS csBeacon_xmit(PSDevice pDevice, PSTxMgmtPacket pPacket) { wCurrentRate, false, 0, 0, 1, AUTO_FB_NONE)); } - BBvCalculateParameter(pDevice, cbFrameSize, wCurrentRate, byPktType, + BBvCaculateParameter(pDevice, cbFrameSize, wCurrentRate, byPktType, (unsigned short *)&(wLen), (unsigned char *)&(pTxDataHead->byServiceField), (unsigned char *)&(pTxDataHead->bySignalField) ); pTxDataHead->wTransmitLength = cpu_to_le16(wLen); @@ -2860,7 +2860,7 @@ vDMA0_tx_80211(PSDevice pDevice, struct sk_buff *skb, unsigned char *pbMPDU, un // SetPower will cause error power TX state for OFDM Date packet in TX buffer. // 2004.11.11 Kyle -- Using OFDM power to tx MngPkt will decrease the connection capability. - // And cmd timer will wait data pkt TX to finish before scanning so it's OK + // And cmd timer will wait data pkt TX finish before scanning so it's OK // to set power here. if (pDevice->pMgmt->eScanState != WMAC_NO_SCANNING) { RFbSetPower(pDevice, wCurrentRate, pDevice->byCurrentCh); @@ -2957,7 +2957,7 @@ vDMA0_tx_80211(PSDevice pDevice, struct sk_buff *skb, unsigned char *pbMPDU, un pTxBufHead->wFragCtl |= cpu_to_le16((unsigned short)cbMacHdLen << 10); // Notes: - // Although spec says MMPDU can be fragmented; In most casses, + // Although spec says MMPDU can be fragmented; In most case, // no one will send a MMPDU under fragmentation. With RTS may occur. pDevice->bAES = false; //Set FRAGCTL_WEPTYP diff --git a/trunk/drivers/staging/vt6655/tcrc.c b/trunk/drivers/staging/vt6655/tcrc.c index 1313c4cd0860..f9c28bf8a6af 100644 --- a/trunk/drivers/staging/vt6655/tcrc.c +++ b/trunk/drivers/staging/vt6655/tcrc.c @@ -18,7 +18,7 @@ * * File: tcrc.c * - * Purpose: Implement functions to calculate CRC + * Purpose: Implement functions to caculate CRC * * Author: Tevin Chen * diff --git a/trunk/drivers/staging/vt6655/tcrc.h b/trunk/drivers/staging/vt6655/tcrc.h index a2044212d1c9..d0449855beb1 100644 --- a/trunk/drivers/staging/vt6655/tcrc.h +++ b/trunk/drivers/staging/vt6655/tcrc.h @@ -18,7 +18,7 @@ * * File: tcrc.h * - * Purpose: Implement functions to calculate CRC + * Purpose: Implement functions to caculate CRC * * Author: Tevin Chen * diff --git a/trunk/drivers/staging/vt6655/tether.c b/trunk/drivers/staging/vt6655/tether.c index 28554bf75549..1cf8508e407d 100644 --- a/trunk/drivers/staging/vt6655/tether.c +++ b/trunk/drivers/staging/vt6655/tether.c @@ -25,7 +25,7 @@ * Date: May 21, 1996 * * Functions: - * ETHbyGetHashIndexByCrc32 - Calculate multicast hash value by CRC32 + * ETHbyGetHashIndexByCrc32 - Caculate multicast hash value by CRC32 * ETHbIsBufferCrc32Ok - Check CRC value of the buffer if Ok or not * * Revision History: @@ -50,7 +50,7 @@ /* - * Description: Calculate multicast hash value by CRC32 + * Description: Caculate multicast hash value by CRC32 * * Parameters: * In: diff --git a/trunk/drivers/staging/vt6655/tkip.c b/trunk/drivers/staging/vt6655/tkip.c index f141ba1cbb9b..ed3eac17ae8d 100644 --- a/trunk/drivers/staging/vt6655/tkip.c +++ b/trunk/drivers/staging/vt6655/tkip.c @@ -170,7 +170,7 @@ unsigned int rotr1(unsigned int a) /* - * Description: Calculate RC4Key fom TK, TA, and TSC + * Description: Caculate RC4Key fom TK, TA, and TSC * * Parameters: * In: diff --git a/trunk/drivers/staging/vt6655/vntwifi.c b/trunk/drivers/staging/vt6655/vntwifi.c index 62c44b87d310..d645ecd89417 100644 --- a/trunk/drivers/staging/vt6655/vntwifi.c +++ b/trunk/drivers/staging/vt6655/vntwifi.c @@ -60,7 +60,7 @@ * Parameters: * In: * pMgmtHandle - pointer to management object - * eOPMode - Operation Mode + * eOPMode - Opreation Mode * Out: * none * diff --git a/trunk/drivers/staging/vt6655/wcmd.c b/trunk/drivers/staging/vt6655/wcmd.c index 94bd1fc42c93..7b5b99c8cf14 100644 --- a/trunk/drivers/staging/vt6655/wcmd.c +++ b/trunk/drivers/staging/vt6655/wcmd.c @@ -121,7 +121,7 @@ vAdHocBeaconStop(PSDevice pDevice) /* * temporarily stop Beacon packet for AdHoc Server - * if all of the following conditions are met: + * if all of the following coditions are met: * (1) STA is in AdHoc mode * (2) VT3253 is programmed as automatic Beacon Transmitting * (3) One of the following conditions is met @@ -812,8 +812,8 @@ printk("chester-abyDesireSSID=%s\n",((PWLAN_IE_SSID)pMgmt->abyDesireSSID)->abySS DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "sta ps tx fail \n"); } pMgmt->sNodeDBTable[ii].wEnQueueCnt--; - // check if sta ps enabled, and wait next pspoll. - // if sta ps disable, then send all pending buffers. + // check if sta ps enable, wait next pspoll + // if sta ps disable, send all pending buffers. if (pMgmt->sNodeDBTable[ii].bPSEnable) break; } diff --git a/trunk/drivers/staging/vt6655/wmgr.c b/trunk/drivers/staging/vt6655/wmgr.c index b6f99ecbbeb5..c46d51908ac0 100644 --- a/trunk/drivers/staging/vt6655/wmgr.c +++ b/trunk/drivers/staging/vt6655/wmgr.c @@ -26,8 +26,8 @@ * Date: May 8, 2002 * * Functions: - * nsMgrObjectInitial - Initialize Management Object data structure - * vMgrObjectReset - Reset Management Object data structure + * nsMgrObjectInitial - Initialize Management Objet data structure + * vMgrObjectReset - Reset Management Objet data structure * vMgrAssocBeginSta - Start associate function * vMgrReAssocBeginSta - Start reassociate function * vMgrDisassocBeginSta - Start disassociate function @@ -54,7 +54,7 @@ * bMgrPrepareBeaconToSend - Prepare Beacon frame * s_vMgrLogStatus - Log 802.11 Status * vMgrRxManagePacket - Rcv management frame dispatch function - * s_vMgrFormatTIM- Assembler TIM field of beacon + * s_vMgrFormatTIM- Assember TIM field of beacon * vMgrTimerInit- Initial 1-sec and command call back funtions * * Revision History: @@ -425,7 +425,7 @@ vMgrTimerInit( /*+ * * Routine Description: - * Reset the management object structure. + * Reset the management object structure. * * Return Value: * None. @@ -1287,14 +1287,14 @@ s_vMgrRxAuthentication( vMgrDecodeAuthen(&sFrame); switch (cpu_to_le16((*(sFrame.pwAuthSequence )))){ case 1: - //AP function + //AP funciton s_vMgrRxAuthenSequence_1(pDevice,pMgmt, &sFrame); break; case 2: s_vMgrRxAuthenSequence_2(pDevice, pMgmt, &sFrame); break; case 3: - //AP function + //AP funciton s_vMgrRxAuthenSequence_3(pDevice, pMgmt, &sFrame); break; case 4: @@ -1923,7 +1923,7 @@ s_vMgrRxBeacon( byIEChannel = sFrame.pDSParms->byCurrChannel; } if (byCurrChannel != byIEChannel) { - // adjust channel info. bcs we rcv adjacent channel packets + // adjust channel info. bcs we rcv adjcent channel pakckets bChannelHit = false; byCurrChannel = byIEChannel; } @@ -2081,7 +2081,7 @@ if(ChannelExceedZoneType(pDevice,byCurrChannel)==true) } } // - // Basic Rate Set may change dynamically + // Basic Rate Set may change dynamiclly // if (pBSSList->eNetworkTypeInUse == PHY_TYPE_11B) { uRateLen = WLAN_RATES_MAXLEN_11B; @@ -2134,7 +2134,7 @@ if(ChannelExceedZoneType(pDevice,byCurrChannel)==true) } // DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Beacon 2 \n"); - // check if CF field exists + // check if CF field exisit if (WLAN_GET_CAP_INFO_ESS(*sFrame.pwCapInfo)) { if (sFrame.pCFParms->wCFPDurRemaining > 0) { // TODO: deal with CFP period to set NAV @@ -2244,7 +2244,7 @@ if(ChannelExceedZoneType(pDevice,byCurrChannel)==true) if (pMgmt->sNodeDBTable[0].uInActiveCount != 0) pMgmt->sNodeDBTable[0].uInActiveCount = 0; - // adhoc mode:TSF updated only when beacon larger than local TSF + // adhoc mode:TSF updated only when beacon larger then local TSF if (bTSFLargeDiff && bTSFOffsetPostive && (pMgmt->eCurrState == WMAC_STATE_JOINTED)) bUpdateTSF = true; @@ -2252,7 +2252,7 @@ if(ChannelExceedZoneType(pDevice,byCurrChannel)==true) // During dpc, already in spinlocked. if (BSSDBbIsSTAInNodeDB(pMgmt, sFrame.pHdr->sA3.abyAddr2, &uNodeIndex)) { - // Update the STA, (Technically the Beacons of all the IBSS nodes + // Update the STA, (Techically the Beacons of all the IBSS nodes // should be identical, but that's not happening in practice. pMgmt->abyCurrSuppRates[1] = RATEuSetIE((PWLAN_IE_SUPP_RATES)sFrame.pSuppRates, (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates, @@ -2305,7 +2305,7 @@ if(ChannelExceedZoneType(pDevice,byCurrChannel)==true) */ } - // if other stations joined, indicate connection to upper layer.. + // if other stations jointed, indicate connect to upper layer.. if (pMgmt->eCurrState == WMAC_STATE_STARTED) { DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Current IBSS State: [Started]........to: [Jointed] \n"); pMgmt->eCurrState = WMAC_STATE_JOINTED; @@ -3081,8 +3081,8 @@ s_vMgrSynchBSS ( // } // } // if( uSameBssidNum>=2) { //we only check AP in hidden sssid mode - if ((pMgmt->eAuthenMode == WMAC_AUTH_WPAPSK) || //networkmanager 0.7.0 does not give the pairwise-key selection, - (pMgmt->eAuthenMode == WMAC_AUTH_WPA2PSK)) { // so we need re-select it according to real pairwise-key info. + if ((pMgmt->eAuthenMode == WMAC_AUTH_WPAPSK) || //networkmanager 0.7.0 does not give the pairwise-key selsection, + (pMgmt->eAuthenMode == WMAC_AUTH_WPA2PSK)) { // so we need re-selsect it according to real pairwise-key info. if(pCurr->bWPAValid == true) { //WPA-PSK pMgmt->eAuthenMode = WMAC_AUTH_WPAPSK; if(pCurr->abyPKType[0] == WPA_TKIP) { @@ -3193,7 +3193,7 @@ s_vMgrFormatTIM( * * * Return Value: - * PTR to frame; or NULL on allocation failure + * PTR to frame; or NULL on allocation failue * -*/ @@ -3310,7 +3310,7 @@ s_MgrMakeBeacon( *((unsigned short *)(sFrame.pBuf + sFrame.len + sFrame.pRSNWPA->len))=0; sFrame.pRSNWPA->len +=2; - // RSN Capabilities + // RSN Capabilites *((unsigned short *)(sFrame.pBuf + sFrame.len + sFrame.pRSNWPA->len))=0; sFrame.pRSNWPA->len +=2; sFrame.len += sFrame.pRSNWPA->len + WLAN_IEHDR_LEN; @@ -3420,7 +3420,7 @@ s_MgrMakeBeacon( * * * Return Value: - * PTR to frame; or NULL on allocation failure + * PTR to frame; or NULL on allocation failue * -*/ @@ -3611,7 +3611,7 @@ s_MgrMakeProbeResponse( * * * Return Value: - * A ptr to frame or NULL on allocation failure + * A ptr to frame or NULL on allocation failue * -*/ @@ -3652,7 +3652,7 @@ s_MgrMakeAssocRequest( memcpy( sFrame.pHdr->sA3.abyAddr2, pMgmt->abyMACAddr, WLAN_ADDR_LEN); memcpy( sFrame.pHdr->sA3.abyAddr3, pMgmt->abyCurrBSSID, WLAN_BSSID_LEN); - // Set the capability and listen interval + // Set the capibility and listen interval *(sFrame.pwCapInfo) = cpu_to_le16(wCurrCapInfo); *(sFrame.pwListenInterval) = cpu_to_le16(wListenInterval); @@ -3762,7 +3762,7 @@ s_MgrMakeAssocRequest( sFrame.pRSNWPA->len +=6; - // RSN Capabilities + // RSN Capabilites *pbyRSN++=0x00; *pbyRSN++=0x00; @@ -3831,7 +3831,7 @@ s_MgrMakeAssocRequest( } sFrame.pRSN->len +=6; - // RSN Capabilities + // RSN Capabilites if (pMgmt->pCurrBSS->sRSNCapObj.bRSNCapExist == true) { memcpy(&sFrame.pRSN->abyRSN[16], &pMgmt->pCurrBSS->sRSNCapObj.wRSNCap, 2); } else { @@ -3886,7 +3886,7 @@ s_MgrMakeAssocRequest( * * * Return Value: - * A ptr to frame or NULL on allocation failure + * A ptr to frame or NULL on allocation failue * -*/ @@ -3929,7 +3929,7 @@ s_MgrMakeReAssocRequest( memcpy( sFrame.pHdr->sA3.abyAddr2, pMgmt->abyMACAddr, WLAN_ADDR_LEN); memcpy( sFrame.pHdr->sA3.abyAddr3, pMgmt->abyCurrBSSID, WLAN_BSSID_LEN); - /* Set the capability and listen interval */ + /* Set the capibility and listen interval */ *(sFrame.pwCapInfo) = cpu_to_le16(wCurrCapInfo); *(sFrame.pwListenInterval) = cpu_to_le16(wListenInterval); @@ -4019,7 +4019,7 @@ s_MgrMakeReAssocRequest( sFrame.pRSNWPA->len +=6; - // RSN Capabilities + // RSN Capabilites *pbyRSN++=0x00; *pbyRSN++=0x00; sFrame.pRSNWPA->len +=2; @@ -4087,7 +4087,7 @@ s_MgrMakeReAssocRequest( } sFrame.pRSN->len +=6; - // RSN Capabilities + // RSN Capabilites if (pMgmt->pCurrBSS->sRSNCapObj.bRSNCapExist == true) { memcpy(&sFrame.pRSN->abyRSN[16], &pMgmt->pCurrBSS->sRSNCapObj.wRSNCap, 2); } else { @@ -4138,7 +4138,7 @@ s_MgrMakeReAssocRequest( * * * Return Value: - * PTR to frame; or NULL on allocation failure + * PTR to frame; or NULL on allocation failue * -*/ @@ -4212,7 +4212,7 @@ s_MgrMakeAssocResponse( * * * Return Value: - * PTR to frame; or NULL on allocation failure + * PTR to frame; or NULL on allocation failue * -*/ @@ -4333,7 +4333,7 @@ s_vMgrRxProbeResponse( byIEChannel = sFrame.pDSParms->byCurrChannel; } if (byCurrChannel != byIEChannel) { - // adjust channel info. bcs we rcv adjacent channel packets + // adjust channel info. bcs we rcv adjcent channel pakckets bChannelHit = false; byCurrChannel = byIEChannel; } diff --git a/trunk/drivers/staging/vt6655/wmgr.h b/trunk/drivers/staging/vt6655/wmgr.h index bfa67ae5d40a..e3ae562f521a 100644 --- a/trunk/drivers/staging/vt6655/wmgr.h +++ b/trunk/drivers/staging/vt6655/wmgr.h @@ -286,7 +286,7 @@ typedef struct tagSMgmtObject CMD_STATE eCommandState; unsigned int uScanChannel; - // Desire joining BSS vars + // Desire joinning BSS vars unsigned char abyDesireSSID[WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1]; unsigned char abyDesireBSSID[WLAN_BSSID_LEN]; @@ -310,7 +310,7 @@ typedef struct tagSMgmtObject unsigned int uScanEndCh; unsigned short wScanSteps; unsigned int uScanBSSType; - // Desire scanning vars + // Desire scannig vars unsigned char abyScanSSID[WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1]; unsigned char abyScanBSSID[WLAN_BSSID_LEN]; diff --git a/trunk/drivers/staging/vt6655/wpa.c b/trunk/drivers/staging/vt6655/wpa.c index 4412fe9396a4..0afb9fe0379a 100644 --- a/trunk/drivers/staging/vt6655/wpa.c +++ b/trunk/drivers/staging/vt6655/wpa.c @@ -229,7 +229,7 @@ WPA_ParseRSN ( * Parameters: * In: * byCmd - Search type - * byEncrypt- Encrypt Type + * byEncrypt- Encrcypt Type * pBSSList - BSS list * Out: * none diff --git a/trunk/drivers/staging/vt6655/wpa2.c b/trunk/drivers/staging/vt6655/wpa2.c index 884db1abe123..744799cfe832 100644 --- a/trunk/drivers/staging/vt6655/wpa2.c +++ b/trunk/drivers/staging/vt6655/wpa2.c @@ -175,16 +175,16 @@ WPA2vParseRSN ( pBSSNode->abyCSSPK[j++] = WLAN_11i_CSS_USE_GROUP; bUseGK = true; } else if ( !memcmp(pbyOUI, abyOUIWEP40, 4)) { - // Invalid CSS, continue to parsing + // Invialid CSS, continue to parsing } else if ( !memcmp(pbyOUI, abyOUITKIP, 4)) { if (pBSSNode->byCSSGK != WLAN_11i_CSS_CCMP) pBSSNode->abyCSSPK[j++] = WLAN_11i_CSS_TKIP; else - ; // Invalid CSS, continue to parsing + ; // Invialid CSS, continue to parsing } else if ( !memcmp(pbyOUI, abyOUICCMP, 4)) { pBSSNode->abyCSSPK[j++] = WLAN_11i_CSS_CCMP; } else if ( !memcmp(pbyOUI, abyOUIWEP104, 4)) { - // Invalid CSS, continue to parsing + // Invialid CSS, continue to parsing } else { // any vendor checks here pBSSNode->abyCSSPK[j++] = WLAN_11i_CSS_UNKNOWN; @@ -329,7 +329,7 @@ WPA2uSetIEs( } pRSNIEs->len +=6; - // RSN Capabilities + // RSN Capabilites if (pMgmt->pCurrBSS->sRSNCapObj.bRSNCapExist == true) { memcpy(&pRSNIEs->abyRSN[16], &pMgmt->pCurrBSS->sRSNCapObj.wRSNCap, 2); } else { diff --git a/trunk/drivers/staging/vt6655/wpactl.c b/trunk/drivers/staging/vt6655/wpactl.c index 2b6ae1e403bf..732ba88dc796 100644 --- a/trunk/drivers/staging/vt6655/wpactl.c +++ b/trunk/drivers/staging/vt6655/wpactl.c @@ -77,7 +77,7 @@ static void wpadev_setup(struct net_device *dev) /* * Description: - * register netdev for wpa supplicant daemon + * register netdev for wpa supplicant deamon * * Parameters: * In: @@ -164,7 +164,7 @@ static int wpa_release_wpadev(PSDevice pDevice) /* * Description: - * Set enable/disable dev for wpa supplicant daemon + * Set enable/disable dev for wpa supplicant deamon * * Parameters: * In: @@ -847,7 +847,7 @@ else if(!bWepEnabled) pDevice->eEncryptionStatus = Ndis802_11EncryptionDisabled; else pDevice->eEncryptionStatus = Ndis802_11Encryption1Enabled; //pMgmt->eAuthenMode = WMAC_AUTH_OPEN; - //pMgmt->bShareKeyAlgorithm = false; //20080717-06, by chester//Fix Open mode, WEP encryption + //pMgmt->bShareKeyAlgorithm = false; //20080717-06, by chester//Fix Open mode, WEP encrytion } //mike save old encryption status pDevice->eOldEncryptionStatus = pDevice->eEncryptionStatus; diff --git a/trunk/drivers/staging/vt6655/wroute.c b/trunk/drivers/staging/vt6655/wroute.c index 82e93cb82053..66e2eeae628b 100644 --- a/trunk/drivers/staging/vt6655/wroute.c +++ b/trunk/drivers/staging/vt6655/wroute.c @@ -18,7 +18,7 @@ * * File: wroute.c * - * Purpose: handle WMAC frame relay & filtering + * Purpose: handle WMAC frame relay & filterring * * Author: Lyndon Chen * diff --git a/trunk/drivers/staging/vt6656/80211mgr.h b/trunk/drivers/staging/vt6656/80211mgr.h index e5db73be0e71..515b9c1d4d10 100644 --- a/trunk/drivers/staging/vt6656/80211mgr.h +++ b/trunk/drivers/staging/vt6656/80211mgr.h @@ -191,7 +191,7 @@ // -// Cipher Suite Selectors defined in 802.11i +// Cipher Suite Selectors defiened in 802.11i // #define WLAN_11i_CSS_USE_GROUP 0 #define WLAN_11i_CSS_WEP40 1 @@ -720,7 +720,7 @@ typedef struct tagWLAN_FR_AUTHEN { } WLAN_FR_AUTHEN, *PWLAN_FR_AUTHEN; -// Deauthentication +// Deauthenication typedef struct tagWLAN_FR_DEAUTHEN { unsigned int uType; diff --git a/trunk/drivers/staging/vt6656/baseband.c b/trunk/drivers/staging/vt6656/baseband.c index 385501595b4d..06f27f624db4 100644 --- a/trunk/drivers/staging/vt6656/baseband.c +++ b/trunk/drivers/staging/vt6656/baseband.c @@ -27,7 +27,7 @@ * * Functions: * BBuGetFrameTime - Calculate data frame transmitting time - * BBvCalculateParameter - Calculate PhyLength, PhyService and Phy Signal parameter for baseband Tx + * BBvCaculateParameter - Caculate PhyLength, PhyService and Phy Signal parameter for baseband Tx * BBbVT3184Init - VIA VT3184 baseband chip init code * BBvLoopbackOn - Turn on BaseBand Loopback mode * BBvLoopbackOff - Turn off BaseBand Loopback mode @@ -741,7 +741,7 @@ BBuGetFrameTime ( } /* - * Description: Calculate Length, Service, and Signal fields of Phy for Tx + * Description: Caculate Length, Service, and Signal fields of Phy for Tx * * Parameters: * In: @@ -757,7 +757,7 @@ BBuGetFrameTime ( * */ void -BBvCalculateParameter ( +BBvCaculateParameter ( PSDevice pDevice, unsigned int cbFrameLength, WORD wRate, diff --git a/trunk/drivers/staging/vt6656/baseband.h b/trunk/drivers/staging/vt6656/baseband.h index 844d5a8b13e5..8db8cd07d5f5 100644 --- a/trunk/drivers/staging/vt6656/baseband.h +++ b/trunk/drivers/staging/vt6656/baseband.h @@ -104,7 +104,7 @@ BBuGetFrameTime( WORD wRate ); -void BBvCalculateParameter(PSDevice pDevice, +void BBvCaculateParameter(PSDevice pDevice, unsigned int cbFrameLength, WORD wRate, BYTE byPacketType, diff --git a/trunk/drivers/staging/vt6656/bssdb.c b/trunk/drivers/staging/vt6656/bssdb.c index 2ac066df8340..099936771e69 100644 --- a/trunk/drivers/staging/vt6656/bssdb.c +++ b/trunk/drivers/staging/vt6656/bssdb.c @@ -226,7 +226,7 @@ PKnownBSS BSSpSearchBSSList(void *hDeviceContext, if (pSelect == NULL) { pSelect = pCurrBSS; } else { - // compare RSSI, select the strongest signal + // compare RSSI, select signal strong one if (pCurrBSS->uRSSI < pSelect->uRSSI) { pSelect = pCurrBSS; } @@ -274,9 +274,9 @@ void BSSvClearBSSList(void *hDeviceContext, BOOL bKeepCurrBSSID) if (pMgmt->sBSSList[ii].bActive && !compare_ether_addr(pMgmt->sBSSList[ii].abyBSSID, pMgmt->abyCurrBSSID)) { - //mike mark: there are two BSSID's in list. If that AP is in hidden ssid mode, one SSID is null, - // but other's might not be obvious, so if it associate's with your STA, - // you must keep the two of them!! + //mike mark: there are two same BSSID in list if that AP is in hidden ssid mode,one 's SSID is null, + // but other's is obvious, so if it acssociate with your STA exactly,you must keep two + // of them!!!!!!!!! // bKeepCurrBSSID = FALSE; continue; } @@ -489,7 +489,7 @@ BOOL BSSbInsertToBSSList(void *hDeviceContext, } if (pDevice->bUpdateBBVGA) { - // Monitor if RSSI is too strong. + // Moniter if RSSI is too strong. pBSSList->byRSSIStatCnt = 0; RFvRSSITodBm(pDevice, (BYTE)(pRxPacket->uRSSI), &pBSSList->ldBmMAX); pBSSList->ldBmAverage[0] = pBSSList->ldBmMAX; @@ -621,7 +621,7 @@ BOOL BSSbUpdateToBSSList(void *hDeviceContext, if (pRxPacket->uRSSI != 0) { RFvRSSITodBm(pDevice, (BYTE)(pRxPacket->uRSSI), &ldBm); - // Monitor if RSSI is too strong. + // Moniter if RSSI is too strong. pBSSList->byRSSIStatCnt++; pBSSList->byRSSIStatCnt %= RSSI_STAT_COUNT; pBSSList->ldBmAverage[pBSSList->byRSSIStatCnt] = ldBm; @@ -687,8 +687,8 @@ BOOL BSSbIsSTAInNodeDB(void *hDeviceContext, /*+ * * Routine Description: - * Find an empty node and allocate it; if no empty node - * is found, then use the most inactive one. + * Find an empty node and allocated; if no empty found, + * instand used of most inactive one. * * Return Value: * None @@ -718,7 +718,7 @@ void BSSvCreateOneNode(void *hDeviceContext, unsigned int *puNodeIndex) } } - // if not found replace uInActiveCount with the largest one. + // if not found replace uInActiveCount is largest one. if ( ii == (MAX_NODE_NUM + 1)) { *puNodeIndex = SelectIndex; DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Replace inactive node = %d\n", SelectIndex); diff --git a/trunk/drivers/staging/vt6656/card.c b/trunk/drivers/staging/vt6656/card.c index 826520b03383..e3ddc0b55317 100644 --- a/trunk/drivers/staging/vt6656/card.c +++ b/trunk/drivers/staging/vt6656/card.c @@ -28,9 +28,9 @@ * CARDbIsOFDMinBasicRate - Check if any OFDM rate is in BasicRateSet * CARDvSetLoopbackMode - Set Loopback mode * CARDbSoftwareReset - Sortware reset NIC - * CARDqGetTSFOffset - Calculate TSFOffset + * CARDqGetTSFOffset - Caculate TSFOffset * CARDbGetCurrentTSF - Read Current NIC TSF counter - * CARDqGetNextTBTT - Calculate Next Beacon TSF counter + * CARDqGetNextTBTT - Caculate Next Beacon TSF counter * CARDvSetFirstNextTBTT - Set NIC Beacon time * CARDvUpdateNextTBTT - Sync. NIC Beacon time * CARDbRadioPowerOff - Turn Off NIC Radio Power @@ -40,7 +40,7 @@ * * Revision History: * 06-10-2003 Bryan YC Fan: Re-write codes to support VT3253 spec. - * 08-26-2003 Kyle Hsu: Modify the definition type of dwIoBase. + * 08-26-2003 Kyle Hsu: Modify the defination type of dwIoBase. * 09-01-2003 Bryan YC Fan: Add vUpdateIFS(). * */ @@ -200,7 +200,7 @@ static WORD swGetOFDMControlRate(void *pDeviceHandler, WORD wRateIdx) } /* - * Description: Calculate TxRate and RsvTime fields for RSPINF in OFDM mode. + * Description: Caculate TxRate and RsvTime fields for RSPINF in OFDM mode. * * Parameters: * In: @@ -214,7 +214,7 @@ static WORD swGetOFDMControlRate(void *pDeviceHandler, WORD wRateIdx) * */ void -CARDvCalculateOFDMRParameter ( +CARDvCaculateOFDMRParameter ( WORD wRate, BYTE byBBType, PBYTE pbyTxRate, @@ -337,7 +337,7 @@ void CARDvSetRSPINF(void *pDeviceHandler, BYTE byBBType) int i; //RSPINF_b_1 - BBvCalculateParameter(pDevice, + BBvCaculateParameter(pDevice, 14, swGetCCKControlRate(pDevice, RATE_1M), PK_TYPE_11B, @@ -347,7 +347,7 @@ void CARDvSetRSPINF(void *pDeviceHandler, BYTE byBBType) ); ///RSPINF_b_2 - BBvCalculateParameter(pDevice, + BBvCaculateParameter(pDevice, 14, swGetCCKControlRate(pDevice, RATE_2M), PK_TYPE_11B, @@ -357,7 +357,7 @@ void CARDvSetRSPINF(void *pDeviceHandler, BYTE byBBType) ); //RSPINF_b_5 - BBvCalculateParameter(pDevice, + BBvCaculateParameter(pDevice, 14, swGetCCKControlRate(pDevice, RATE_5M), PK_TYPE_11B, @@ -367,7 +367,7 @@ void CARDvSetRSPINF(void *pDeviceHandler, BYTE byBBType) ); //RSPINF_b_11 - BBvCalculateParameter(pDevice, + BBvCaculateParameter(pDevice, 14, swGetCCKControlRate(pDevice, RATE_11M), PK_TYPE_11B, @@ -377,55 +377,55 @@ void CARDvSetRSPINF(void *pDeviceHandler, BYTE byBBType) ); //RSPINF_a_6 - CARDvCalculateOFDMRParameter (RATE_6M, + CARDvCaculateOFDMRParameter (RATE_6M, byBBType, &abyTxRate[0], &abyRsvTime[0]); //RSPINF_a_9 - CARDvCalculateOFDMRParameter (RATE_9M, + CARDvCaculateOFDMRParameter (RATE_9M, byBBType, &abyTxRate[1], &abyRsvTime[1]); //RSPINF_a_12 - CARDvCalculateOFDMRParameter (RATE_12M, + CARDvCaculateOFDMRParameter (RATE_12M, byBBType, &abyTxRate[2], &abyRsvTime[2]); //RSPINF_a_18 - CARDvCalculateOFDMRParameter (RATE_18M, + CARDvCaculateOFDMRParameter (RATE_18M, byBBType, &abyTxRate[3], &abyRsvTime[3]); //RSPINF_a_24 - CARDvCalculateOFDMRParameter (RATE_24M, + CARDvCaculateOFDMRParameter (RATE_24M, byBBType, &abyTxRate[4], &abyRsvTime[4]); //RSPINF_a_36 - CARDvCalculateOFDMRParameter (swGetOFDMControlRate(pDevice, RATE_36M), + CARDvCaculateOFDMRParameter (swGetOFDMControlRate(pDevice, RATE_36M), byBBType, &abyTxRate[5], &abyRsvTime[5]); //RSPINF_a_48 - CARDvCalculateOFDMRParameter (swGetOFDMControlRate(pDevice, RATE_48M), + CARDvCaculateOFDMRParameter (swGetOFDMControlRate(pDevice, RATE_48M), byBBType, &abyTxRate[6], &abyRsvTime[6]); //RSPINF_a_54 - CARDvCalculateOFDMRParameter (swGetOFDMControlRate(pDevice, RATE_54M), + CARDvCaculateOFDMRParameter (swGetOFDMControlRate(pDevice, RATE_54M), byBBType, &abyTxRate[7], &abyRsvTime[7]); //RSPINF_a_72 - CARDvCalculateOFDMRParameter (swGetOFDMControlRate(pDevice, RATE_54M), + CARDvCaculateOFDMRParameter (swGetOFDMControlRate(pDevice, RATE_54M), byBBType, &abyTxRate[8], &abyRsvTime[8]); @@ -640,7 +640,7 @@ BYTE CARDbyGetPktType(void *pDeviceHandler) /* - * Description: Calculate TSF offset of two TSF input + * Description: Caculate TSF offset of two TSF input * Get TSF Offset from RxBCN's TSF and local TSF * * Parameters: diff --git a/trunk/drivers/staging/vt6656/device.h b/trunk/drivers/staging/vt6656/device.h index 6370d1039103..171dd68cf5b2 100644 --- a/trunk/drivers/staging/vt6656/device.h +++ b/trunk/drivers/staging/vt6656/device.h @@ -478,7 +478,7 @@ typedef struct __device_info { unsigned int cbTD; // - // Variables to track resources for the Interrupt In Pipe + // Variables to track resources for the Interript In Pipe // INT_BUFFER intBuf; BOOL fKillEventPollingThread; diff --git a/trunk/drivers/staging/vt6656/dpc.c b/trunk/drivers/staging/vt6656/dpc.c index 28edf9e7efcb..e4bdf2a2b582 100644 --- a/trunk/drivers/staging/vt6656/dpc.c +++ b/trunk/drivers/staging/vt6656/dpc.c @@ -200,7 +200,7 @@ s_vProcessRxMACHeader ( } else if (!compare_ether_addr(pbyRxBuffer, &pDevice->abySNAP_RFC1042[0])) { cbHeaderSize += 6; pwType = (PWORD) (pbyRxBufferAddr + cbHeaderSize); - if ((*pwType == cpu_to_be16(ETH_P_IPX)) || + if ((*pwType == cpu_to_le16(ETH_P_IPX)) || (*pwType == cpu_to_le16(0xF380))) { cbHeaderSize -= 8; pwType = (PWORD) (pbyRxBufferAddr + cbHeaderSize); @@ -748,7 +748,7 @@ RXbBulkInProcessData ( if ((*pbyRSSI != 0) && (pMgmt->pCurrBSS!=NULL)) { RFvRSSITodBm(pDevice, *pbyRSSI, &ldBm); - // Monitor if RSSI is too strong. + // Moniter if RSSI is too strong. pMgmt->pCurrBSS->byRSSIStatCnt++; pMgmt->pCurrBSS->byRSSIStatCnt %= RSSI_STAT_COUNT; pMgmt->pCurrBSS->ldBmAverage[pMgmt->pCurrBSS->byRSSIStatCnt] = ldBm; diff --git a/trunk/drivers/staging/vt6656/hostap.c b/trunk/drivers/staging/vt6656/hostap.c index 0a73d4060ee1..682002a5b8d7 100644 --- a/trunk/drivers/staging/vt6656/hostap.c +++ b/trunk/drivers/staging/vt6656/hostap.c @@ -18,7 +18,7 @@ * * File: hostap.c * - * Purpose: handle hostap daemon ioctl input/out functions + * Purpose: handle hostap deamon ioctl input/out functions * * Author: Lyndon Chen * @@ -48,7 +48,7 @@ static int msglevel =MSG_LEVEL_INFO; /* * Description: - * register net_device (AP) for hostap daemon + * register net_device (AP) for hostap deamon * * Parameters: * In: @@ -176,7 +176,7 @@ int vt6656_hostap_set_hostapd(PSDevice pDevice, int val, int rtnl_locked) /* * Description: - * remove station function supported for hostap daemon + * remove station function supported for hostap deamon * * Parameters: * In: @@ -204,7 +204,7 @@ static int hostap_remove_sta(PSDevice pDevice, /* * Description: - * add a station from hostap daemon + * add a station from hostap deamon * * Parameters: * In: @@ -439,7 +439,9 @@ static int hostap_set_encryption(PSDevice pDevice, return -EINVAL; } - if (is_broadcast_ether_addr(param->sta_addr)) { + if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff && + param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff && + param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) { if (param->u.crypt.idx >= MAX_GROUP_KEY) return -EINVAL; iNodeIndex = 0; @@ -661,7 +663,9 @@ static int hostap_get_encryption(PSDevice pDevice, param->u.crypt.err = 0; - if (is_broadcast_ether_addr(param->sta_addr)) { + if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff && + param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff && + param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) { iNodeIndex = 0; } else { if (BSSbIsSTAInNodeDB(pDevice, param->sta_addr, &iNodeIndex) == FALSE) { @@ -682,7 +686,7 @@ static int hostap_get_encryption(PSDevice pDevice, /* * Description: - * vt6656_hostap_ioctl main function supported for hostap daemon. + * vt6656_hostap_ioctl main function supported for hostap deamon. * * Parameters: * In: @@ -728,8 +732,8 @@ int vt6656_hostap_ioctl(PSDevice pDevice, struct iw_point *p) break; case VIAWGET_HOSTAPD_SET_ASSOC_AP_ADDR: DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_HOSTAPD_SET_ASSOC_AP_ADDR \n"); - ret = -EOPNOTSUPP; - goto out; + return -EOPNOTSUPP; + break; case VIAWGET_HOSTAPD_FLUSH: DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_HOSTAPD_FLUSH \n"); spin_lock_irq(&pDevice->lock); @@ -773,13 +777,13 @@ int vt6656_hostap_ioctl(PSDevice pDevice, struct iw_point *p) case VIAWGET_HOSTAPD_STA_CLEAR_STATS: DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_HOSTAPD_STA_CLEAR_STATS \n"); - ret = -EOPNOTSUPP; - goto out; + return -EOPNOTSUPP; + default: DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "vt6656_hostap_ioctl: unknown cmd=%d\n", (int)param->cmd); - ret = -EOPNOTSUPP; - goto out; + return -EOPNOTSUPP; + break; } diff --git a/trunk/drivers/staging/vt6656/int.c b/trunk/drivers/staging/vt6656/int.c index bba31caae036..eba4b5061cf7 100644 --- a/trunk/drivers/staging/vt6656/int.c +++ b/trunk/drivers/staging/vt6656/int.c @@ -149,7 +149,7 @@ void INTnsProcessData(PSDevice pDevice) pMgmt->sNodeDBTable[0].bRxPSPoll = FALSE; } else if (pMgmt->byDTIMCount == 0) { - /* check if multicast tx buffering */ + /* check if mutltcast tx bufferring */ pMgmt->byDTIMCount = pMgmt->byDTIMPeriod-1; pMgmt->sNodeDBTable[0].bRxPSPoll = TRUE; diff --git a/trunk/drivers/staging/vt6656/ioctl.c b/trunk/drivers/staging/vt6656/ioctl.c index b6af5f691128..5b9a84f95185 100644 --- a/trunk/drivers/staging/vt6656/ioctl.c +++ b/trunk/drivers/staging/vt6656/ioctl.c @@ -526,8 +526,11 @@ int private_ioctl(PSDevice pDevice, struct ifreq *rq) pMgmt->abyIBSSSuppRates[3] |= BIT7; } - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Support Rate= %*ph\n", - 4, pMgmt->abyIBSSSuppRates + 2); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Support Rate= %x %x %x %x\n", + pMgmt->abyIBSSSuppRates[2], + pMgmt->abyIBSSSuppRates[3], + pMgmt->abyIBSSSuppRates[4], + pMgmt->abyIBSSSuppRates[5]); netif_stop_queue(pDevice->dev); spin_lock_irq(&pDevice->lock); @@ -617,7 +620,7 @@ int private_ioctl(PSDevice pDevice, struct ifreq *rq) result = -EFAULT; break; } - /* for some AP's maybe a good authentication */ + /* for some AP maybe good authenticate */ if (wpa_Result.key_mgmt == 0x20) pMgmt->Cisco_cckm = 1; else @@ -641,7 +644,7 @@ int private_ioctl(PSDevice pDevice, struct ifreq *rq) break; default: - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Private command not supported..\n"); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Private command not support..\n"); } return result; diff --git a/trunk/drivers/staging/vt6656/iwctl.c b/trunk/drivers/staging/vt6656/iwctl.c index 8f198749ca51..8b9894b1146a 100644 --- a/trunk/drivers/staging/vt6656/iwctl.c +++ b/trunk/drivers/staging/vt6656/iwctl.c @@ -674,7 +674,7 @@ int iwctl_giwaplist(struct net_device *dev, struct iw_request_info *info, jj++; } - wrq->flags = 1; // Should be defined + wrq->flags = 1; // Should be define'd wrq->length = jj; memcpy(extra, sock, sizeof(struct sockaddr) * jj); memcpy(extra + sizeof(struct sockaddr) * jj, qual, sizeof(struct iw_quality) * jj); diff --git a/trunk/drivers/staging/vt6656/key.c b/trunk/drivers/staging/vt6656/key.c index a61fcb9591aa..ee62a06a75f4 100644 --- a/trunk/drivers/staging/vt6656/key.c +++ b/trunk/drivers/staging/vt6656/key.c @@ -403,7 +403,7 @@ BOOL KeybRemoveKey( BOOL bReturnValue = FALSE; if (is_broadcast_ether_addr(pbyBSSID)) { - // delete all keys + // dealte all key if ((dwKeyIndex & PAIRWISE_KEY) != 0) { for (i=0;iKeyTable[i].PairwiseKey.bKeyValid = FALSE; @@ -618,7 +618,7 @@ BOOL KeybGetTransmitKey(PSKeyManagement pTable, PBYTE pbyBSSID, DWORD dwKeyType, /* - * Description: Check Pairwise Key + * Description: Check Pairewise Key * * Parameters: * In: diff --git a/trunk/drivers/staging/vt6656/main_usb.c b/trunk/drivers/staging/vt6656/main_usb.c index ad422dea702b..b06fd5b723fa 100644 --- a/trunk/drivers/staging/vt6656/main_usb.c +++ b/trunk/drivers/staging/vt6656/main_usb.c @@ -29,14 +29,14 @@ * vt6656_probe - module initial (insmod) driver entry * device_remove1 - module remove entry * device_open - allocate dma/descripter resource & initial mac/bbp function - * device_xmit - asynchronous data tx function + * device_xmit - asynchrous data tx function * device_set_multi - set mac filter * device_ioctl - ioctl entry - * device_close - shutdown mac/bbp & free dma/descriptor resource + * device_close - shutdown mac/bbp & free dma/descripter resource * device_alloc_frag_buf - rx fragement pre-allocated function * device_free_tx_bufs - free tx buffer function * device_dma0_tx_80211- tx 802.11 frame via dma0 - * device_dma0_xmit- tx PS buffered frame via dma0 + * device_dma0_xmit- tx PS bufferred frame via dma0 * device_init_registers- initial MAC & BBP & RF internal registers. * device_init_rings- initial tx/rx ring buffer * device_init_defrag_cb- initial & allocate de-fragement buffer. @@ -189,7 +189,7 @@ DEVICE_PARAM(b80211hEnable, "802.11h mode"); // Static vars definitions // -static struct usb_device_id vt6656_table[] = { +static struct usb_device_id vt6656_table[] __devinitdata = { {USB_DEVICE(VNT_USB_VENDOR_ID, VNT_USB_PRODUCT_ID)}, {} }; @@ -316,7 +316,7 @@ static void device_init_diversity_timer(PSDevice pDevice) // -// Initialization of MAC & BBP registers +// Initialiation of MAC & BBP registers // static BOOL device_init_registers(PSDevice pDevice, DEVICE_INIT_TYPE InitType) @@ -639,7 +639,7 @@ static BOOL device_release_WPADEV(PSDevice pDevice) viawget_wpa_header *wpahdr; int ii=0; // wait_queue_head_t Set_wait; - //send device close to wpa_supplicant layer + //send device close to wpa_supplicnat layer if (pDevice->bWPADEVUp==TRUE) { wpahdr = (viawget_wpa_header *)pDevice->skb->data; wpahdr->type = VIAWGET_DEVICECLOSE_MSG; @@ -1010,7 +1010,7 @@ static int device_open(struct net_device *dev) { } if (device_init_defrag_cb(pDevice)== FALSE) { - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " Initial defragment cb fail \n"); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " Initial defragement cb fail \n"); goto free_rx_tx; } @@ -1296,7 +1296,7 @@ static inline u32 ether_crc(int length, unsigned char *data) return crc; } -//find out the start position of str2 from str1 +//find out the start position of str2 from str1 static unsigned char *kstrstr(const unsigned char *str1, const unsigned char *str2) { int str1_len = strlen(str1); @@ -1345,7 +1345,7 @@ static int Config_FileGetParameter(unsigned char *string, } memset(buf2,0,100); - memcpy(buf2,start_p,end_p-start_p); //get the target line + memcpy(buf2,start_p,end_p-start_p); //get the tartget line buf2[end_p-start_p]='\0'; //find value @@ -1396,7 +1396,7 @@ static unsigned char *Config_FileOperation(PSDevice pDevice) } if(!(filp->f_op) || !(filp->f_op->read) ||!(filp->f_op->write)) { - printk("file %s is not read or writeable?\n",config_path); + printk("file %s cann't readable or writable?\n",config_path); result = -1; goto error1; } @@ -1969,7 +1969,7 @@ static int device_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) { default: rc = -EOPNOTSUPP; - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Ioctl command not supported..%x\n", cmd); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Ioctl command not support..%x\n", cmd); } diff --git a/trunk/drivers/staging/vt6656/power.c b/trunk/drivers/staging/vt6656/power.c index ab3a55462056..b3136773b5da 100644 --- a/trunk/drivers/staging/vt6656/power.c +++ b/trunk/drivers/staging/vt6656/power.c @@ -19,7 +19,7 @@ * * File: power.c * - * Purpose: Handles 802.11 power management functions + * Purpose: Handles 802.11 power management functions * * Author: Lyndon Chen * diff --git a/trunk/drivers/staging/vt6656/rf.c b/trunk/drivers/staging/vt6656/rf.c index 593cdc713b0e..3fd0478a9a54 100644 --- a/trunk/drivers/staging/vt6656/rf.c +++ b/trunk/drivers/staging/vt6656/rf.c @@ -26,7 +26,7 @@ * Date: Feb. 19, 2004 * * Functions: - * IFRFbWriteEmbedded - Embedded write RF register via MAC + * IFRFbWriteEmbeded - Embeded write RF register via MAC * * Revision History: * @@ -711,7 +711,7 @@ const BYTE RFaby11aChannelIndex[200] = { /*--------------------- Export Functions --------------------------*/ /* - * Description: Write to IF/RF, by embedded programming + * Description: Write to IF/RF, by embeded programming * * Parameters: * In: @@ -722,7 +722,7 @@ const BYTE RFaby11aChannelIndex[200] = { * Return Value: TRUE if succeeded; FALSE if failed. * */ -BOOL IFRFbWriteEmbedded (PSDevice pDevice, DWORD dwData) +BOOL IFRFbWriteEmbeded (PSDevice pDevice, DWORD dwData) { BYTE pbyData[4]; @@ -828,23 +828,23 @@ BOOL bResult = TRUE; case RF_AL2230 : if (pDevice->byCurPwr >= AL2230_PWR_IDX_LEN) return FALSE; - bResult &= IFRFbWriteEmbedded(pDevice, dwAL2230PowerTable[pDevice->byCurPwr]); + bResult &= IFRFbWriteEmbeded(pDevice, dwAL2230PowerTable[pDevice->byCurPwr]); if (uRATE <= RATE_11M) - bResult &= IFRFbWriteEmbedded(pDevice, 0x0001B400+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW); + bResult &= IFRFbWriteEmbeded(pDevice, 0x0001B400+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW); else - bResult &= IFRFbWriteEmbedded(pDevice, 0x0005A400+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW); + bResult &= IFRFbWriteEmbeded(pDevice, 0x0005A400+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW); break; case RF_AL2230S : if (pDevice->byCurPwr >= AL2230_PWR_IDX_LEN) return FALSE; - bResult &= IFRFbWriteEmbedded(pDevice, dwAL2230PowerTable[pDevice->byCurPwr]); + bResult &= IFRFbWriteEmbeded(pDevice, dwAL2230PowerTable[pDevice->byCurPwr]); if (uRATE <= RATE_11M) { - bResult &= IFRFbWriteEmbedded(pDevice, 0x040C1400+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW); - bResult &= IFRFbWriteEmbedded(pDevice, 0x00299B00+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW); + bResult &= IFRFbWriteEmbeded(pDevice, 0x040C1400+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW); + bResult &= IFRFbWriteEmbeded(pDevice, 0x00299B00+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW); }else { - bResult &= IFRFbWriteEmbedded(pDevice, 0x0005A400+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW); - bResult &= IFRFbWriteEmbedded(pDevice, 0x00099B00+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW); + bResult &= IFRFbWriteEmbeded(pDevice, 0x0005A400+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW); + bResult &= IFRFbWriteEmbeded(pDevice, 0x00099B00+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW); } break; @@ -854,10 +854,10 @@ BOOL bResult = TRUE; DWORD dwMax7230Pwr; if (uRATE <= RATE_11M) { //RobertYu:20060426, for better 11b mask - bResult &= IFRFbWriteEmbedded(pDevice, 0x111BB900+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW); + bResult &= IFRFbWriteEmbeded(pDevice, 0x111BB900+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW); } else { - bResult &= IFRFbWriteEmbedded(pDevice, 0x221BB900+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW); + bResult &= IFRFbWriteEmbeded(pDevice, 0x221BB900+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW); } if (pDevice->byCurPwr > AL7230_PWR_IDX_LEN) return FALSE; @@ -866,7 +866,7 @@ BOOL bResult = TRUE; dwMax7230Pwr = 0x080C0B00 | ( (pDevice->byCurPwr) << 12 ) | (BY_AL7230_REG_LEN << 3 ) | IFREGCTL_REGW; - bResult &= IFRFbWriteEmbedded(pDevice, dwMax7230Pwr); + bResult &= IFRFbWriteEmbeded(pDevice, dwMax7230Pwr); break; } break; @@ -879,7 +879,7 @@ BOOL bResult = TRUE; return FALSE; dwVT3226Pwr = ((0x3F-pDevice->byCurPwr) << 20 ) | ( 0x17 << 8 ) /* Reg7 */ | (BY_VT3226_REG_LEN << 3 ) | IFREGCTL_REGW; - bResult &= IFRFbWriteEmbedded(pDevice, dwVT3226Pwr); + bResult &= IFRFbWriteEmbeded(pDevice, dwVT3226Pwr); break; } @@ -894,27 +894,27 @@ BOOL bResult = TRUE; dwVT3226Pwr = ((0x3F-pDevice->byCurPwr) << 20 ) | ( 0xE07 << 8 ) /* Reg7 */ | //RobertYu:20060420, TWIF 1.10 (BY_VT3226_REG_LEN << 3 ) | IFREGCTL_REGW; - bResult &= IFRFbWriteEmbedded(pDevice, dwVT3226Pwr); + bResult &= IFRFbWriteEmbeded(pDevice, dwVT3226Pwr); - bResult &= IFRFbWriteEmbedded(pDevice, 0x03C6A200+(BY_VT3226_REG_LEN<<3)+IFREGCTL_REGW); + bResult &= IFRFbWriteEmbeded(pDevice, 0x03C6A200+(BY_VT3226_REG_LEN<<3)+IFREGCTL_REGW); if (pDevice->sMgmtObj.eScanState != WMAC_NO_SCANNING) { // scanning, the channel number is pDevice->uScanChannel DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"@@@@ RFbRawSetPower> 11B mode uCurrChannel[%d]\n", pDevice->sMgmtObj.uScanChannel); - bResult &= IFRFbWriteEmbedded(pDevice, dwVT3226D0LoCurrentTable[pDevice->sMgmtObj.uScanChannel-1]); //RobertYu:20060420, sometimes didn't change channel just set power with different rate + bResult &= IFRFbWriteEmbeded(pDevice, dwVT3226D0LoCurrentTable[pDevice->sMgmtObj.uScanChannel-1]); //RobertYu:20060420, sometimes didn't change channel just set power with different rate } else { DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"@@@@ RFbRawSetPower> 11B mode uCurrChannel[%d]\n", pDevice->sMgmtObj.uCurrChannel); - bResult &= IFRFbWriteEmbedded(pDevice, dwVT3226D0LoCurrentTable[pDevice->sMgmtObj.uCurrChannel-1]); //RobertYu:20060420, sometimes didn't change channel just set power with different rate + bResult &= IFRFbWriteEmbeded(pDevice, dwVT3226D0LoCurrentTable[pDevice->sMgmtObj.uCurrChannel-1]); //RobertYu:20060420, sometimes didn't change channel just set power with different rate } - bResult &= IFRFbWriteEmbedded(pDevice, 0x015C0800+(BY_VT3226_REG_LEN<<3)+IFREGCTL_REGW); //RobertYu:20060420, ok now, new switching power (mini-pci can have bigger power consumption) + bResult &= IFRFbWriteEmbeded(pDevice, 0x015C0800+(BY_VT3226_REG_LEN<<3)+IFREGCTL_REGW); //RobertYu:20060420, ok now, new switching power (mini-pci can have bigger power consumption) } else { DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"@@@@ RFbRawSetPower> 11G mode\n"); dwVT3226Pwr = ((0x3F-pDevice->byCurPwr) << 20 ) | ( 0x7 << 8 ) /* Reg7 */ | //RobertYu:20060420, TWIF 1.10 (BY_VT3226_REG_LEN << 3 ) | IFREGCTL_REGW; - bResult &= IFRFbWriteEmbedded(pDevice, dwVT3226Pwr); - bResult &= IFRFbWriteEmbedded(pDevice, 0x00C6A200+(BY_VT3226_REG_LEN<<3)+IFREGCTL_REGW); //RobertYu:20060327 - bResult &= IFRFbWriteEmbedded(pDevice, 0x016BC600+(BY_VT3226_REG_LEN<<3)+IFREGCTL_REGW); //RobertYu:20060111 - bResult &= IFRFbWriteEmbedded(pDevice, 0x00900800+(BY_VT3226_REG_LEN<<3)+IFREGCTL_REGW); //RobertYu:20060111 + bResult &= IFRFbWriteEmbeded(pDevice, dwVT3226Pwr); + bResult &= IFRFbWriteEmbeded(pDevice, 0x00C6A200+(BY_VT3226_REG_LEN<<3)+IFREGCTL_REGW); //RobertYu:20060327 + bResult &= IFRFbWriteEmbeded(pDevice, 0x016BC600+(BY_VT3226_REG_LEN<<3)+IFREGCTL_REGW); //RobertYu:20060111 + bResult &= IFRFbWriteEmbeded(pDevice, 0x00900800+(BY_VT3226_REG_LEN<<3)+IFREGCTL_REGW); //RobertYu:20060111 } break; } @@ -929,7 +929,7 @@ BOOL bResult = TRUE; dwVT3342Pwr = ((0x3F-pDevice->byCurPwr) << 20 ) | ( 0x27 << 8 ) /* Reg7 */ | (BY_VT3342_REG_LEN << 3 ) | IFREGCTL_REGW; - bResult &= IFRFbWriteEmbedded(pDevice, dwVT3342Pwr); + bResult &= IFRFbWriteEmbeded(pDevice, dwVT3342Pwr); break; } @@ -1048,7 +1048,7 @@ BYTE abyArray[256]; wLength1, abyArray ); - //Channel Table 0 + //Channle Table 0 wValue = 0; while ( wLength2 > 0 ) { @@ -1106,7 +1106,7 @@ BYTE abyArray[256]; wLength1, abyArray); - //Channel Table 0 + //Channle Table 0 wValue = 0; while ( wLength2 > 0 ) { @@ -1141,9 +1141,9 @@ BOOL s_bVT3226D0_11bLoCurrentAdjust( bResult = TRUE; if( b11bMode ) - bResult &= IFRFbWriteEmbedded(pDevice, dwVT3226D0LoCurrentTable[byChannel-1]); + bResult &= IFRFbWriteEmbeded(pDevice, dwVT3226D0LoCurrentTable[byChannel-1]); else - bResult &= IFRFbWriteEmbedded(pDevice, 0x016BC600+(BY_VT3226_REG_LEN<<3)+IFREGCTL_REGW); //RobertYu:20060412 + bResult &= IFRFbWriteEmbeded(pDevice, 0x016BC600+(BY_VT3226_REG_LEN<<3)+IFREGCTL_REGW); //RobertYu:20060412 return bResult; } diff --git a/trunk/drivers/staging/vt6656/rf.h b/trunk/drivers/staging/vt6656/rf.h index 72eb27ac436b..f5ba8fd7f816 100644 --- a/trunk/drivers/staging/vt6656/rf.h +++ b/trunk/drivers/staging/vt6656/rf.h @@ -63,7 +63,7 @@ extern const BYTE RFaby11aChannelIndex[200]; /*--------------------- Export Functions --------------------------*/ -BOOL IFRFbWriteEmbedded(PSDevice pDevice, DWORD dwData); +BOOL IFRFbWriteEmbeded(PSDevice pDevice, DWORD dwData); BOOL RFbSetPower(PSDevice pDevice, unsigned int uRATE, unsigned int uCH); BOOL RFbRawSetPower( diff --git a/trunk/drivers/staging/vt6656/rxtx.c b/trunk/drivers/staging/vt6656/rxtx.c index 339083879883..bb464527fc1b 100644 --- a/trunk/drivers/staging/vt6656/rxtx.c +++ b/trunk/drivers/staging/vt6656/rxtx.c @@ -841,7 +841,7 @@ s_uFillDataHead ( if ((uDMAIdx == TYPE_ATIMDMA) || (uDMAIdx == TYPE_BEACONDMA)) { PSTxDataHead_ab pBuf = (PSTxDataHead_ab) pTxDataHead; //Get SignalField,ServiceField,Length - BBvCalculateParameter(pDevice, cbFrameLength, wCurrentRate, byPktType, + BBvCaculateParameter(pDevice, cbFrameLength, wCurrentRate, byPktType, (PWORD)&(pBuf->wTransmitLength), (PBYTE)&(pBuf->byServiceField), (PBYTE)&(pBuf->bySignalField) ); //Get Duration and TimeStampOff @@ -858,10 +858,10 @@ s_uFillDataHead ( if (byFBOption == AUTO_FB_NONE) { PSTxDataHead_g pBuf = (PSTxDataHead_g)pTxDataHead; //Get SignalField,ServiceField,Length - BBvCalculateParameter(pDevice, cbFrameLength, wCurrentRate, byPktType, + BBvCaculateParameter(pDevice, cbFrameLength, wCurrentRate, byPktType, (PWORD)&(pBuf->wTransmitLength_a), (PBYTE)&(pBuf->byServiceField_a), (PBYTE)&(pBuf->bySignalField_a) ); - BBvCalculateParameter(pDevice, cbFrameLength, pDevice->byTopCCKBasicRate, PK_TYPE_11B, + BBvCaculateParameter(pDevice, cbFrameLength, pDevice->byTopCCKBasicRate, PK_TYPE_11B, (PWORD)&(pBuf->wTransmitLength_b), (PBYTE)&(pBuf->byServiceField_b), (PBYTE)&(pBuf->bySignalField_b) ); //Get Duration and TimeStamp @@ -881,10 +881,10 @@ s_uFillDataHead ( // Auto Fallback PSTxDataHead_g_FB pBuf = (PSTxDataHead_g_FB)pTxDataHead; //Get SignalField,ServiceField,Length - BBvCalculateParameter(pDevice, cbFrameLength, wCurrentRate, byPktType, + BBvCaculateParameter(pDevice, cbFrameLength, wCurrentRate, byPktType, (PWORD)&(pBuf->wTransmitLength_a), (PBYTE)&(pBuf->byServiceField_a), (PBYTE)&(pBuf->bySignalField_a) ); - BBvCalculateParameter(pDevice, cbFrameLength, pDevice->byTopCCKBasicRate, PK_TYPE_11B, + BBvCaculateParameter(pDevice, cbFrameLength, pDevice->byTopCCKBasicRate, PK_TYPE_11B, (PWORD)&(pBuf->wTransmitLength_b), (PBYTE)&(pBuf->byServiceField_b), (PBYTE)&(pBuf->bySignalField_b) ); //Get Duration and TimeStamp @@ -907,7 +907,7 @@ s_uFillDataHead ( // Auto Fallback PSTxDataHead_a_FB pBuf = (PSTxDataHead_a_FB)pTxDataHead; //Get SignalField,ServiceField,Length - BBvCalculateParameter(pDevice, cbFrameLength, wCurrentRate, byPktType, + BBvCaculateParameter(pDevice, cbFrameLength, wCurrentRate, byPktType, (PWORD)&(pBuf->wTransmitLength), (PBYTE)&(pBuf->byServiceField), (PBYTE)&(pBuf->bySignalField) ); //Get Duration and TimeStampOff @@ -924,7 +924,7 @@ s_uFillDataHead ( } else { PSTxDataHead_ab pBuf = (PSTxDataHead_ab)pTxDataHead; //Get SignalField,ServiceField,Length - BBvCalculateParameter(pDevice, cbFrameLength, wCurrentRate, byPktType, + BBvCaculateParameter(pDevice, cbFrameLength, wCurrentRate, byPktType, (PWORD)&(pBuf->wTransmitLength), (PBYTE)&(pBuf->byServiceField), (PBYTE)&(pBuf->bySignalField) ); //Get Duration and TimeStampOff @@ -942,7 +942,7 @@ s_uFillDataHead ( else if (byPktType == PK_TYPE_11B) { PSTxDataHead_ab pBuf = (PSTxDataHead_ab)pTxDataHead; //Get SignalField,ServiceField,Length - BBvCalculateParameter(pDevice, cbFrameLength, wCurrentRate, byPktType, + BBvCaculateParameter(pDevice, cbFrameLength, wCurrentRate, byPktType, (PWORD)&(pBuf->wTransmitLength), (PBYTE)&(pBuf->byServiceField), (PBYTE)&(pBuf->bySignalField) ); //Get Duration and TimeStampOff @@ -987,17 +987,17 @@ s_vFillRTSHead ( uRTSFrameLen -= 4; } - // Note: So far RTSHead doesn't appear in ATIM & Beacom DMA, so we don't need to take them into account. + // Note: So far RTSHead dosen't appear in ATIM & Beacom DMA, so we don't need to take them into account. // Otherwise, we need to modified codes for them. if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) { if (byFBOption == AUTO_FB_NONE) { PSRTS_g pBuf = (PSRTS_g)pvRTS; //Get SignalField,ServiceField,Length - BBvCalculateParameter(pDevice, uRTSFrameLen, pDevice->byTopCCKBasicRate, PK_TYPE_11B, + BBvCaculateParameter(pDevice, uRTSFrameLen, pDevice->byTopCCKBasicRate, PK_TYPE_11B, (PWORD)&(wLen), (PBYTE)&(pBuf->byServiceField_b), (PBYTE)&(pBuf->bySignalField_b) ); pBuf->wTransmitLength_b = cpu_to_le16(wLen); - BBvCalculateParameter(pDevice, uRTSFrameLen, pDevice->byTopOFDMBasicRate, byPktType, + BBvCaculateParameter(pDevice, uRTSFrameLen, pDevice->byTopOFDMBasicRate, byPktType, (PWORD)&(wLen), (PBYTE)&(pBuf->byServiceField_a), (PBYTE)&(pBuf->bySignalField_a) ); pBuf->wTransmitLength_a = cpu_to_le16(wLen); @@ -1035,11 +1035,11 @@ s_vFillRTSHead ( else { PSRTS_g_FB pBuf = (PSRTS_g_FB)pvRTS; //Get SignalField,ServiceField,Length - BBvCalculateParameter(pDevice, uRTSFrameLen, pDevice->byTopCCKBasicRate, PK_TYPE_11B, + BBvCaculateParameter(pDevice, uRTSFrameLen, pDevice->byTopCCKBasicRate, PK_TYPE_11B, (PWORD)&(wLen), (PBYTE)&(pBuf->byServiceField_b), (PBYTE)&(pBuf->bySignalField_b) ); pBuf->wTransmitLength_b = cpu_to_le16(wLen); - BBvCalculateParameter(pDevice, uRTSFrameLen, pDevice->byTopOFDMBasicRate, byPktType, + BBvCaculateParameter(pDevice, uRTSFrameLen, pDevice->byTopOFDMBasicRate, byPktType, (PWORD)&(wLen), (PBYTE)&(pBuf->byServiceField_a), (PBYTE)&(pBuf->bySignalField_a) ); pBuf->wTransmitLength_a = cpu_to_le16(wLen); @@ -1084,7 +1084,7 @@ s_vFillRTSHead ( if (byFBOption == AUTO_FB_NONE) { PSRTS_ab pBuf = (PSRTS_ab)pvRTS; //Get SignalField,ServiceField,Length - BBvCalculateParameter(pDevice, uRTSFrameLen, pDevice->byTopOFDMBasicRate, byPktType, + BBvCaculateParameter(pDevice, uRTSFrameLen, pDevice->byTopOFDMBasicRate, byPktType, (PWORD)&(wLen), (PBYTE)&(pBuf->byServiceField), (PBYTE)&(pBuf->bySignalField) ); pBuf->wTransmitLength = cpu_to_le16(wLen); @@ -1119,7 +1119,7 @@ s_vFillRTSHead ( else { PSRTS_a_FB pBuf = (PSRTS_a_FB)pvRTS; //Get SignalField,ServiceField,Length - BBvCalculateParameter(pDevice, uRTSFrameLen, pDevice->byTopOFDMBasicRate, byPktType, + BBvCaculateParameter(pDevice, uRTSFrameLen, pDevice->byTopOFDMBasicRate, byPktType, (PWORD)&(wLen), (PBYTE)&(pBuf->byServiceField), (PBYTE)&(pBuf->bySignalField) ); pBuf->wTransmitLength = cpu_to_le16(wLen); @@ -1155,7 +1155,7 @@ s_vFillRTSHead ( else if (byPktType == PK_TYPE_11B) { PSRTS_ab pBuf = (PSRTS_ab)pvRTS; //Get SignalField,ServiceField,Length - BBvCalculateParameter(pDevice, uRTSFrameLen, pDevice->byTopCCKBasicRate, PK_TYPE_11B, + BBvCaculateParameter(pDevice, uRTSFrameLen, pDevice->byTopCCKBasicRate, PK_TYPE_11B, (PWORD)&(wLen), (PBYTE)&(pBuf->byServiceField), (PBYTE)&(pBuf->bySignalField) ); pBuf->wTransmitLength = cpu_to_le16(wLen); @@ -1221,7 +1221,7 @@ s_vFillCTSHead ( // Auto Fall back PSCTS_FB pBuf = (PSCTS_FB)pvCTS; //Get SignalField,ServiceField,Length - BBvCalculateParameter(pDevice, uCTSFrameLen, pDevice->byTopCCKBasicRate, PK_TYPE_11B, + BBvCaculateParameter(pDevice, uCTSFrameLen, pDevice->byTopCCKBasicRate, PK_TYPE_11B, (PWORD)&(wLen), (PBYTE)&(pBuf->byServiceField_b), (PBYTE)&(pBuf->bySignalField_b) ); pBuf->wTransmitLength_b = cpu_to_le16(wLen); @@ -1246,7 +1246,7 @@ s_vFillCTSHead ( } else { //if (byFBOption != AUTO_FB_NONE && uDMAIdx != TYPE_ATIMDMA && uDMAIdx != TYPE_BEACONDMA) PSCTS pBuf = (PSCTS)pvCTS; //Get SignalField,ServiceField,Length - BBvCalculateParameter(pDevice, uCTSFrameLen, pDevice->byTopCCKBasicRate, PK_TYPE_11B, + BBvCaculateParameter(pDevice, uCTSFrameLen, pDevice->byTopCCKBasicRate, PK_TYPE_11B, (PWORD)&(wLen), (PBYTE)&(pBuf->byServiceField_b), (PBYTE)&(pBuf->bySignalField_b) ); pBuf->wTransmitLength_b = cpu_to_le16(wLen); @@ -1699,7 +1699,7 @@ s_bPacketToWirelessUsb( // 802.1H if (ntohs(psEthHeader->wType) > ETH_DATA_LEN) { if (pDevice->dwDiagRefCount == 0) { - if ((psEthHeader->wType == cpu_to_be16(ETH_P_IPX)) || + if ((psEthHeader->wType == cpu_to_le16(ETH_P_IPX)) || (psEthHeader->wType == cpu_to_le16(0xF380))) { memcpy((PBYTE) (pbyPayloadHead), abySNAP_Bridgetunnel, 6); @@ -1827,7 +1827,7 @@ s_bPacketToWirelessUsb( * * Parameters: * In: - * pDevice - Pointer to adapter + * pDevice - Pointer to adpater * dwTxBufferAddr - Transmit Buffer * pPacket - Packet from upper layer * cbPacketSize - Transmit Data Length @@ -2198,7 +2198,7 @@ CMD_STATUS csMgmt_xmit( if (bIsPSPOLL) { // The MAC will automatically replace the Duration-field of MAC header by Duration-field - // of FIFO control header. + // of FIFO control header. // This will cause AID-field of PS-POLL packet be incorrect (Because PS-POLL's AID field is // in the same place of other packet's Duration-field). // And it will cause Cisco-AP to issue Disassociation-packet @@ -2272,7 +2272,7 @@ csBeacon_xmit( wCurrentRate = RATE_6M; pTxDataHead = (PSTxDataHead_ab) (pbyTxBufferAddr + wTxBufSize); //Get SignalField,ServiceField,Length - BBvCalculateParameter(pDevice, cbFrameSize, wCurrentRate, PK_TYPE_11A, + BBvCaculateParameter(pDevice, cbFrameSize, wCurrentRate, PK_TYPE_11A, (PWORD)&(pTxDataHead->wTransmitLength), (PBYTE)&(pTxDataHead->byServiceField), (PBYTE)&(pTxDataHead->bySignalField) ); //Get Duration and TimeStampOff @@ -2285,7 +2285,7 @@ csBeacon_xmit( pTxBufHead->wFIFOCtl |= FIFOCTL_11B; pTxDataHead = (PSTxDataHead_ab) (pbyTxBufferAddr + wTxBufSize); //Get SignalField,ServiceField,Length - BBvCalculateParameter(pDevice, cbFrameSize, wCurrentRate, PK_TYPE_11B, + BBvCaculateParameter(pDevice, cbFrameSize, wCurrentRate, PK_TYPE_11B, (PWORD)&(pTxDataHead->wTransmitLength), (PBYTE)&(pTxDataHead->byServiceField), (PBYTE)&(pTxDataHead->bySignalField) ); //Get Duration and TimeStampOff @@ -2473,7 +2473,7 @@ vDMA0_tx_80211(PSDevice pDevice, struct sk_buff *skb) { cbMacHdLen = WLAN_HDR_ADDR3_LEN; } - // hostapd daemon ext support rate patch + // hostapd deamon ext support rate patch if (WLAN_GET_FC_FSTYPE(p80211Header->sA4.wFrameCtl) == WLAN_FSTYPE_ASSOCRESP) { if (((PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates)->len != 0) { @@ -2591,7 +2591,7 @@ vDMA0_tx_80211(PSDevice pDevice, struct sk_buff *skb) { pMACHeader->wFrameCtl &= cpu_to_le16(0xfffc); memcpy(pbyPayloadHead, (skb->data + cbMacHdLen), cbFrameBodySize); - // replace support rate, patch for hostapd daemon( only support 11M) + // replace support rate, patch for hostapd deamon( only support 11M) if (WLAN_GET_FC_FSTYPE(p80211Header->sA4.wFrameCtl) == WLAN_FSTYPE_ASSOCRESP) { if (cbExtSuppRate != 0) { if (((PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates)->len != 0) @@ -2770,7 +2770,7 @@ int nsDMA_tx_packet(PSDevice pDevice, unsigned int uDMAIdx, struct sk_buff *skb) pMgmt->abyPSTxMap[0] |= byMask[0]; return 0; } - // multicast/broadcast data rate + // muticast/broadcast data rate if (pDevice->byBBType != BB_TYPE_11A) pDevice->wCurrentRate = RATE_2M; @@ -2838,10 +2838,10 @@ int nsDMA_tx_packet(PSDevice pDevice, unsigned int uDMAIdx, struct sk_buff *skb) Packet_Type = skb->data[ETH_HLEN+1]; Descriptor_type = skb->data[ETH_HLEN+1+1+2]; Key_info = (skb->data[ETH_HLEN+1+1+2+1] << 8)|(skb->data[ETH_HLEN+1+1+2+2]); - if (pDevice->sTxEthHeader.wType == cpu_to_be16(ETH_P_PAE)) { - /* 802.1x OR eapol-key challenge frame transfer */ - if (((Protocol_Version == 1) || (Protocol_Version == 2)) && - (Packet_Type == 3)) { + if (pDevice->sTxEthHeader.wType == cpu_to_le16(ETH_P_PAE)) { + /* 802.1x OR eapol-key challenge frame transfer */ + if (((Protocol_Version == 1) || (Protocol_Version == 2)) && + (Packet_Type == 3)) { bTxeapol_key = TRUE; if(!(Key_info & BIT3) && //WPA or RSN group-key challenge (Key_info & BIT8) && (Key_info & BIT9)) { //send 2/2 key @@ -2855,7 +2855,7 @@ int nsDMA_tx_packet(PSDevice pDevice, unsigned int uDMAIdx, struct sk_buff *skb) } PRINT_K("Authentication completed!!\n"); } - else if((Key_info & BIT3) && (Descriptor_type==2) && //RSN pairwise-key challenge + else if((Key_info & BIT3) && (Descriptor_type==2) && //RSN pairse-key challenge (Key_info & BIT8) && (Key_info & BIT9)) { pDevice->fWPA_Authened = TRUE; PRINT_K("WPA2 Authentication completed!!\n"); @@ -2987,19 +2987,19 @@ int nsDMA_tx_packet(PSDevice pDevice, unsigned int uDMAIdx, struct sk_buff *skb) } } - if (pDevice->sTxEthHeader.wType == cpu_to_be16(ETH_P_PAE)) { - if (pDevice->byBBType != BB_TYPE_11A) { - pDevice->wCurrentRate = RATE_1M; - pDevice->byACKRate = RATE_1M; - pDevice->byTopCCKBasicRate = RATE_1M; - pDevice->byTopOFDMBasicRate = RATE_6M; - } else { - pDevice->wCurrentRate = RATE_6M; - pDevice->byACKRate = RATE_6M; - pDevice->byTopCCKBasicRate = RATE_1M; - pDevice->byTopOFDMBasicRate = RATE_6M; - } - } + if (pDevice->sTxEthHeader.wType == cpu_to_le16(ETH_P_PAE)) { + if (pDevice->byBBType != BB_TYPE_11A) { + pDevice->wCurrentRate = RATE_1M; + pDevice->byACKRate = RATE_1M; + pDevice->byTopCCKBasicRate = RATE_1M; + pDevice->byTopOFDMBasicRate = RATE_6M; + } else { + pDevice->wCurrentRate = RATE_6M; + pDevice->byACKRate = RATE_6M; + pDevice->byTopCCKBasicRate = RATE_1M; + pDevice->byTopOFDMBasicRate = RATE_6M; + } + } DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "dma_tx: pDevice->wCurrentRate = %d\n", @@ -3015,7 +3015,7 @@ int nsDMA_tx_packet(PSDevice pDevice, unsigned int uDMAIdx, struct sk_buff *skb) if (bNeedEncryption == TRUE) { DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ntohs Pkt Type=%04x\n", ntohs(pDevice->sTxEthHeader.wType)); - if ((pDevice->sTxEthHeader.wType) == cpu_to_be16(ETH_P_PAE)) { + if ((pDevice->sTxEthHeader.wType) == cpu_to_le16(ETH_P_PAE)) { bNeedEncryption = FALSE; DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Pkt Type=%04x\n", (pDevice->sTxEthHeader.wType)); if ((pMgmt->eCurrMode == WMAC_MODE_ESS_STA) && (pMgmt->eCurrState == WMAC_STATE_ASSOC)) { diff --git a/trunk/drivers/staging/vt6656/tcrc.c b/trunk/drivers/staging/vt6656/tcrc.c index 2237eeb5ec5b..e25021e850a0 100644 --- a/trunk/drivers/staging/vt6656/tcrc.c +++ b/trunk/drivers/staging/vt6656/tcrc.c @@ -18,7 +18,7 @@ * * File: tcrc.c * - * Purpose: Implement functions to calculate CRC + * Purpose: Implement functions to caculate CRC * * Author: Tevin Chen * diff --git a/trunk/drivers/staging/vt6656/tcrc.h b/trunk/drivers/staging/vt6656/tcrc.h index dc54bd8fc4fc..4dfd01e477a4 100644 --- a/trunk/drivers/staging/vt6656/tcrc.h +++ b/trunk/drivers/staging/vt6656/tcrc.h @@ -18,7 +18,7 @@ * * File: tcrc.h * - * Purpose: Implement functions to calculate CRC + * Purpose: Implement functions to caculate CRC * * Author: Tevin Chen * diff --git a/trunk/drivers/staging/vt6656/tether.c b/trunk/drivers/staging/vt6656/tether.c index 083b2153a271..4f368f174b21 100644 --- a/trunk/drivers/staging/vt6656/tether.c +++ b/trunk/drivers/staging/vt6656/tether.c @@ -25,7 +25,7 @@ * Date: May 21, 1996 * * Functions: - * ETHbyGetHashIndexByCrc32 - Calculate multicast hash value by CRC32 + * ETHbyGetHashIndexByCrc32 - Caculate multicast hash value by CRC32 * ETHbIsBufferCrc32Ok - Check CRC value of the buffer if Ok or not * * Revision History: @@ -50,7 +50,7 @@ /* - * Description: Calculate multicast hash value by CRC32 + * Description: Caculate multicast hash value by CRC32 * * Parameters: * In: diff --git a/trunk/drivers/staging/vt6656/tkip.c b/trunk/drivers/staging/vt6656/tkip.c index 003123e550f6..0715636cb9cb 100644 --- a/trunk/drivers/staging/vt6656/tkip.c +++ b/trunk/drivers/staging/vt6656/tkip.c @@ -168,7 +168,7 @@ static unsigned int rotr1(unsigned int a) /* - * Description: Calculate RC4Key fom TK, TA, and TSC + * Description: Caculate RC4Key fom TK, TA, and TSC * * Parameters: * In: diff --git a/trunk/drivers/staging/vt6656/wcmd.c b/trunk/drivers/staging/vt6656/wcmd.c index 586fbe1627f7..9d2caa819f47 100644 --- a/trunk/drivers/staging/vt6656/wcmd.c +++ b/trunk/drivers/staging/vt6656/wcmd.c @@ -263,7 +263,7 @@ s_vProbeChannel( * * * Return Value: - * A ptr to Tx frame or NULL on allocation failure + * A ptr to Tx frame or NULL on allocation failue * -*/ @@ -751,7 +751,7 @@ void vRunCommand(void *hDeviceContext) pDevice->nTxDataTimeCout = 0; } else { - // printk("mike:-->First time trigger TimerTxData InSleep\n"); + // printk("mike:-->First time triger TimerTxData InSleep\n"); } pDevice->IsTxDataTrigger = TRUE; add_timer(&pDevice->sTimerTxData); @@ -794,7 +794,7 @@ void vRunCommand(void *hDeviceContext) DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "vMgrCreateOwnIBSS fail!\n"); } - // always turn off unicast bit + // alway turn off unicast bit MACvRegBitsOff(pDevice, MAC_REG_RCR, RCR_UNICAST); pDevice->byRxMode &= ~RCR_UNICAST; DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "wcmd: rx_mode = %x\n", pDevice->byRxMode ); @@ -946,7 +946,7 @@ void vRunCommand(void *hDeviceContext) pItemSSID = (PWLAN_IE_SSID)pMgmt->abyCurrSSID; pItemSSID->len = 0; memset(pItemSSID->abySSID, 0, WLAN_SSID_MAXLEN); - //clear desired SSID + //clear dessire SSID pItemSSID = (PWLAN_IE_SSID)pMgmt->abyDesireSSID; pItemSSID->len = 0; memset(pItemSSID->abySSID, 0, WLAN_SSID_MAXLEN); diff --git a/trunk/drivers/staging/vt6656/wctl.c b/trunk/drivers/staging/vt6656/wctl.c index 9249263b2da8..c231ae7176f5 100644 --- a/trunk/drivers/staging/vt6656/wctl.c +++ b/trunk/drivers/staging/vt6656/wctl.c @@ -89,7 +89,7 @@ BOOL WCTLbIsDuplicate (PSCache pCache, PS802_11Header pMACHeader) ADD_ONE_WITH_WRAP_AROUND(uIndex, DUPLICATE_RX_CACHE_LENGTH); } } - /* Not found in cache - insert */ + /* Not fount in cache - insert */ pCacheEntry = &pCache->asCacheEntry[pCache->uInPtr]; pCacheEntry->wFmSequence = pMACHeader->wSeqCtl; memcpy(&(pCacheEntry->abyAddr2[0]), &(pMACHeader->abyAddr2[0]), ETH_ALEN); diff --git a/trunk/drivers/staging/vt6656/wmgr.c b/trunk/drivers/staging/vt6656/wmgr.c index 7db6a8d3508b..f08e2d15c7b3 100644 --- a/trunk/drivers/staging/vt6656/wmgr.c +++ b/trunk/drivers/staging/vt6656/wmgr.c @@ -27,7 +27,7 @@ * * Functions: * nsMgrObjectInitial - Initialize Management Objet data structure - * vMgrObjectReset - Reset Management Object data structure + * vMgrObjectReset - Reset Management Objet data structure * vMgrAssocBeginSta - Start associate function * vMgrReAssocBeginSta - Start reassociate function * vMgrDisassocBeginSta - Start disassociate function @@ -54,7 +54,7 @@ * bMgrPrepareBeaconToSend - Prepare Beacon frame * s_vMgrLogStatus - Log 802.11 Status * vMgrRxManagePacket - Rcv management frame dispatch function - * s_vMgrFormatTIM- Assembler TIM field of beacon + * s_vMgrFormatTIM- Assember TIM field of beacon * vMgrTimerInit- Initial 1-sec and command call back funtions * * Revision History: @@ -2032,7 +2032,7 @@ if(ChannelExceedZoneType(pDevice,byCurrChannel)==TRUE) } // - // Preamble may change dynamically + // Preamble may change dynamiclly // byOldPreambleType = pDevice->byPreambleType; if (WLAN_GET_CAP_INFO_SHORTPREAMBLE(pBSSList->wCapInfo)) { @@ -2044,7 +2044,7 @@ if(ChannelExceedZoneType(pDevice,byCurrChannel)==TRUE) if (pDevice->byPreambleType != byOldPreambleType) CARDvSetRSPINF(pDevice, (BYTE)pDevice->byBBType); // - // Basic Rate Set may change dynamically + // Basic Rate Set may change dynamiclly // if (pBSSList->eNetworkTypeInUse == PHY_TYPE_11B) { uRateLen = WLAN_RATES_MAXLEN_11B; @@ -2188,7 +2188,7 @@ if(ChannelExceedZoneType(pDevice,byCurrChannel)==TRUE) // During dpc, already in spinlocked. if (BSSbIsSTAInNodeDB(pDevice, sFrame.pHdr->sA3.abyAddr2, &uNodeIndex)) { - // Update the STA, (Technically the Beacons of all the IBSS nodes + // Update the STA, (Techically the Beacons of all the IBSS nodes // should be identical, but that's not happening in practice. pMgmt->abyCurrSuppRates[1] = RATEuSetIE((PWLAN_IE_SUPP_RATES)sFrame.pSuppRates, (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates, @@ -2722,7 +2722,7 @@ void vMgrJoinBSSBegin(void *hDeviceContext, PCMD_STATUS pStatus) memcpy(pDevice->abyBSSID, pCurr->abyBSSID, WLAN_BSSID_LEN); // Add current BSS to Candidate list - // This should only work for WPA2 BSS, and WPA2 BSS check must be done before. + // This should only works for WPA2 BSS, and WPA2 BSS check must be done before. if (pMgmt->eAuthenMode == WMAC_AUTH_WPA2) { BOOL bResult = bAdd_PMKID_Candidate((void *) pDevice, pMgmt->abyCurrBSSID, @@ -3181,7 +3181,7 @@ s_vMgrFormatTIM( * * * Return Value: - * PTR to frame; or NULL on allocation failure + * PTR to frame; or NULL on allocation failue * -*/ @@ -3353,7 +3353,7 @@ s_MgrMakeBeacon( * * * Return Value: - * PTR to frame; or NULL on allocation failure + * PTR to frame; or NULL on allocation failue * -*/ @@ -3528,7 +3528,7 @@ s_MgrMakeAssocRequest( memcpy( sFrame.pHdr->sA3.abyAddr2, pMgmt->abyMACAddr, WLAN_ADDR_LEN); memcpy( sFrame.pHdr->sA3.abyAddr3, pMgmt->abyCurrBSSID, WLAN_BSSID_LEN); - // Set the capability and listen interval + // Set the capibility and listen interval *(sFrame.pwCapInfo) = cpu_to_le16(wCurrCapInfo); *(sFrame.pwListenInterval) = cpu_to_le16(wListenInterval); @@ -3749,7 +3749,7 @@ s_MgrMakeAssocRequest( * * * Return Value: - * A ptr to frame or NULL on allocation failure + * A ptr to frame or NULL on allocation failue * -*/ @@ -3792,7 +3792,7 @@ s_MgrMakeReAssocRequest( memcpy( sFrame.pHdr->sA3.abyAddr2, pMgmt->abyMACAddr, WLAN_ADDR_LEN); memcpy( sFrame.pHdr->sA3.abyAddr3, pMgmt->abyCurrBSSID, WLAN_BSSID_LEN); - /* Set the capability and listen interval */ + /* Set the capibility and listen interval */ *(sFrame.pwCapInfo) = cpu_to_le16(wCurrCapInfo); *(sFrame.pwListenInterval) = cpu_to_le16(wListenInterval); @@ -4004,7 +4004,7 @@ s_MgrMakeReAssocRequest( * * * Return Value: - * PTR to frame; or NULL on allocation failure + * PTR to frame; or NULL on allocation failue * -*/ @@ -4077,7 +4077,7 @@ s_MgrMakeAssocResponse( * * * Return Value: - * PTR to frame; or NULL on allocation failure + * PTR to frame; or NULL on allocation failue * -*/ diff --git a/trunk/drivers/staging/vt6656/wpa.c b/trunk/drivers/staging/vt6656/wpa.c index f6429a26ae0f..b16d4ddc117b 100644 --- a/trunk/drivers/staging/vt6656/wpa.c +++ b/trunk/drivers/staging/vt6656/wpa.c @@ -231,7 +231,7 @@ WPA_ParseRSN( * Parameters: * In: * byCmd - Search type - * byEncrypt- Encrypt Type + * byEncrypt- Encrcypt Type * pBSSList - BSS list * Out: * none diff --git a/trunk/drivers/staging/vt6656/wpa2.c b/trunk/drivers/staging/vt6656/wpa2.c index c0926976627d..d4f3f7530ee4 100644 --- a/trunk/drivers/staging/vt6656/wpa2.c +++ b/trunk/drivers/staging/vt6656/wpa2.c @@ -174,16 +174,16 @@ WPA2vParseRSN ( pBSSNode->abyCSSPK[j++] = WLAN_11i_CSS_USE_GROUP; bUseGK = TRUE; } else if ( !memcmp(pbyOUI, abyOUIWEP40, 4)) { - // Invalid CSS, continue parsing + // Invialid CSS, continue to parsing } else if ( !memcmp(pbyOUI, abyOUITKIP, 4)) { if (pBSSNode->byCSSGK != WLAN_11i_CSS_CCMP) pBSSNode->abyCSSPK[j++] = WLAN_11i_CSS_TKIP; else - ; // Invalid CSS, continue parsing + ; // Invialid CSS, continue to parsing } else if ( !memcmp(pbyOUI, abyOUICCMP, 4)) { pBSSNode->abyCSSPK[j++] = WLAN_11i_CSS_CCMP; } else if ( !memcmp(pbyOUI, abyOUIWEP104, 4)) { - // Invalid CSS, continue parsing + // Invialid CSS, continue to parsing } else { // any vendor checks here pBSSNode->abyCSSPK[j++] = WLAN_11i_CSS_UNKNOWN; diff --git a/trunk/drivers/staging/vt6656/wpactl.c b/trunk/drivers/staging/vt6656/wpactl.c index 3e65aa132011..5435e8205b2c 100644 --- a/trunk/drivers/staging/vt6656/wpactl.c +++ b/trunk/drivers/staging/vt6656/wpactl.c @@ -74,7 +74,7 @@ static void wpadev_setup(struct net_device *dev) /* * Description: - * register netdev for wpa supplicant daemon + * register netdev for wpa supplicant deamon * * Parameters: * In: @@ -154,7 +154,7 @@ static int wpa_release_wpadev(PSDevice pDevice) /* * Description: - * Set enable/disable dev for wpa supplicant daemon + * Set enable/disable dev for wpa supplicant deamon * * Parameters: * In: @@ -326,7 +326,7 @@ int wpa_set_wpadev(PSDevice pDevice, int val) if ((byKeyDecMode == KEY_CTL_TKIP) && (param->u.wpa_key.key_len != MAX_KEY_LEN)) { // TKIP Key must be 256 bits - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "return - TKIP Key must be 256 bits!\n"); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "return- TKIP Key must be 256 bits!\n"); return -EINVAL; } // Check AES key length diff --git a/trunk/drivers/staging/winbond/Kconfig b/trunk/drivers/staging/winbond/Kconfig index a29f60836b77..132671d96d0d 100644 --- a/trunk/drivers/staging/winbond/Kconfig +++ b/trunk/drivers/staging/winbond/Kconfig @@ -1,6 +1,6 @@ config W35UND tristate "IS89C35 WLAN USB driver" - depends on MAC80211 && WLAN && USB + depends on MAC80211 && WLAN && USB && EXPERIMENTAL default n ---help--- This is highly experimental driver for Winbond WIFI card. diff --git a/trunk/drivers/staging/winbond/localpara.h b/trunk/drivers/staging/winbond/localpara.h index 84effc47d79d..d7980575bed1 100644 --- a/trunk/drivers/staging/winbond/localpara.h +++ b/trunk/drivers/staging/winbond/localpara.h @@ -137,7 +137,7 @@ struct wb_local_para { u8 iPowerSaveMode; /* 0 indicates on, 1 indicates off */ u8 ATIMmode; u8 ExcludeUnencrypted; - /* Unit time count for the decision to enter PS mode */ + /* Unit ime count for the decision to enter PS mode */ u16 CheckCountForPS; u8 boHasTxActivity;/* tx activity has occurred */ u8 boMacPsValid; /* Power save mode obtained from H/W is valid or not */ @@ -187,7 +187,7 @@ struct wb_local_para { u8 reserved7[3]; struct chan_info CurrentChan; /* Current channel no. and channel band. It may be changed by scanning. */ - u8 boHandover; /* Roaming, Handover to other AP. */ + u8 boHandover; /* Roaming, Hnadover to other AP. */ u8 boCCAbusy; u16 CWMax; /* It may not be the real value that H/W used */ diff --git a/trunk/drivers/staging/winbond/mds.c b/trunk/drivers/staging/winbond/mds.c index 1b8b8ace39e0..c9f0e8f856a0 100644 --- a/trunk/drivers/staging/winbond/mds.c +++ b/trunk/drivers/staging/winbond/mds.c @@ -569,7 +569,7 @@ Mds_SendComplete(struct wbsoft_priv *adapter, struct T02_descriptor *pT02) unsigned char SendOK = true; u8 RetryCount, TxRate; - if (pT02->T02_IgnoreResult) /* Don't care about the result */ + if (pT02->T02_IgnoreResult) /* Don't care the result */ return; if (pT02->T02_IsLastMpdu) { /* TODO: DTO -- get the retry count and fragment count */ diff --git a/trunk/drivers/staging/winbond/mto.c b/trunk/drivers/staging/winbond/mto.c index 560c0ab617d1..1b52ebd4b011 100644 --- a/trunk/drivers/staging/winbond/mto.c +++ b/trunk/drivers/staging/winbond/mto.c @@ -23,7 +23,7 @@ #include "core.h" /* Declare SQ3 to rate and fragmentation threshold table */ -/* Declare fragmentation threshold table */ +/* Declare fragmentation thresholds table */ #define MTO_MAX_FRAG_TH_LEVELS 5 #define MTO_MAX_DATA_RATE_LEVELS 12 diff --git a/trunk/drivers/staging/winbond/phy_calibration.c b/trunk/drivers/staging/winbond/phy_calibration.c index cabae3466704..77a3fff708c6 100644 --- a/trunk/drivers/staging/winbond/phy_calibration.c +++ b/trunk/drivers/staging/winbond/phy_calibration.c @@ -399,7 +399,7 @@ void _rxadc_dc_offset_cancellation_winbond(struct hw_data *phw_data, u32 frequen val |= MASK_ADC_DC_CAL_STR; hw_set_dxx_reg(phw_data, REG_MODE_CTRL, val); - /* e. The results are shown in "adc_dc_cal_i[8:0] and adc_dc_cal_q[8:0]" */ + /* e. The result are shown in "adc_dc_cal_i[8:0] and adc_dc_cal_q[8:0]" */ #ifdef _DEBUG hw_get_dxx_reg(phw_data, REG_OFFSET_READ, &val); PHY_DEBUG(("[CAL] REG_OFFSET_READ = 0x%08X\n", val)); @@ -720,7 +720,7 @@ u8 _tx_iq_calibration_loop_winbond(struct hw_data *phw_data, for (capture_time = 0; capture_time < 10; capture_time++) { /* * a. Set iqcal_mode[1:0] to 0x2 and set "calib_start" to 0x1 to - * enable "IQ calibration Mode II" + * enable "IQ alibration Mode II" */ reg_mode_ctrl &= ~(MASK_IQCAL_TONE_SEL|MASK_IQCAL_MODE); reg_mode_ctrl &= ~MASK_IQCAL_MODE; @@ -750,7 +750,7 @@ u8 _tx_iq_calibration_loop_winbond(struct hw_data *phw_data, /* * d. Set iqcal_mode[1:0] to 0x3 and set "calib_start" to 0x1 to - * enable "IQ calibration Mode II" + * enable "IQ alibration Mode II" */ /* hw_get_dxx_reg(phw_data, REG_MODE_CTRL, &val); */ hw_get_dxx_reg(phw_data, REG_MODE_CTRL, ®_mode_ctrl); @@ -980,7 +980,7 @@ void _tx_iq_calibration_winbond(struct hw_data *phw_data) phy_set_rf_data(phw_data, 0, (0<<24)|0xFDF1C0); /* ; [BB-chip]: Calibration (6f).Send test pattern */ /* ; [BB-chip]: Calibration (6g). Search RXGCL optimal value */ - /* ; [BB-chip]: Calibration (6h). Calculate TX-path IQ imbalance and setting TX path IQ compensation table */ + /* ; [BB-chip]: Calibration (6h). Caculate TX-path IQ imbalance and setting TX path IQ compensation table */ /* phy_set_rf_data(phw_data, 3, (3<<24)|0x025586); */ msleep(30); /* 20060612.1.a 30ms delay. Add the follow 2 lines */ @@ -1373,7 +1373,7 @@ u8 _rx_iq_calibration_loop_winbond(struct hw_data *phw_data, u16 factor, u32 fre /***************************************************************/ void _rx_iq_calibration_winbond(struct hw_data *phw_data, u32 frequency) { -/* figo 20050523 marked this flag for can't compile for release */ +/* figo 20050523 marked this flag for can't compile for relesase */ #ifdef _DEBUG s32 rx_cal_reg[4]; u32 val; @@ -1397,7 +1397,7 @@ void _rx_iq_calibration_winbond(struct hw_data *phw_data, u32 frequency) /* ; [BB-chip]: Calibration (7f). Send test pattern */ /* ; [BB-chip]: Calibration (7g). Search RXGCL optimal value */ - /* ; [BB-chip]: Calibration (7h). Calculate RX-path IQ imbalance and setting RX path IQ compensation table */ + /* ; [BB-chip]: Calibration (7h). Caculate RX-path IQ imbalance and setting RX path IQ compensation table */ result = _rx_iq_calibration_loop_winbond(phw_data, 12589, frequency); @@ -1454,7 +1454,7 @@ void phy_calibration_winbond(struct hw_data *phw_data, u32 frequency) _rxadc_dc_offset_cancellation_winbond(phw_data, frequency); /* _txidac_dc_offset_cancellation_winbond(phw_data); */ - /* _txqdac_dc_offset_cancellation_winbond(phw_data); */ + /* _txqdac_dc_offset_cacellation_winbond(phw_data); */ _tx_iq_calibration_winbond(phw_data); _rx_iq_calibration_winbond(phw_data, frequency); diff --git a/trunk/drivers/staging/winbond/reg.c b/trunk/drivers/staging/winbond/reg.c index 5ecf9a121e78..1b38d6d225c9 100644 --- a/trunk/drivers/staging/winbond/reg.c +++ b/trunk/drivers/staging/winbond/reg.c @@ -693,7 +693,7 @@ u32 w89rf242_rf_data[] = { (0x0E << 24) | 0x5557DC, /* 1555F ; IBSC (0x0E) -- IRLNA & IRLNB (PTAT & Const current)=01/01; FA5976B_1.3F */ (0x10 << 24) | 0x000C20, /* 00030 ; TMODA (0x10) -- LNA_gain_step=0011 ; LNA=15/16dB */ (0x11 << 24) | 0x0C0022, /* 03000 ; TMODB (0x11) -- Turn ON RX-Q path Test Switch; To improve IQ path group delay (FA5976A_1.3C) */ - (0x12 << 24) | 0x000024 /* TMODC (0x12) -- Turn OFF Temperature sensor */ + (0x12 << 24) | 0x000024 /* TMODC (0x12) -- Turn OFF Tempearure sensor */ }; u32 w89rf242_channel_data_24[][2] = { diff --git a/trunk/drivers/staging/winbond/sme_api.h b/trunk/drivers/staging/winbond/sme_api.h index 652ae7085a5f..8f4596c9e9b3 100644 --- a/trunk/drivers/staging/winbond/sme_api.h +++ b/trunk/drivers/staging/winbond/sme_api.h @@ -12,6 +12,7 @@ #include "localpara.h" /****************** CONSTANT AND MACRO SECTION ******************************/ +#define _INLINE __inline #define MEDIA_STATE_DISCONNECTED 0 #define MEDIA_STATE_CONNECTED 1 @@ -25,17 +26,17 @@ /* OID_802_11_BSSID */ s8 sme_get_bssid(void *pcore_data, u8 *pbssid); -s8 sme_get_desired_bssid(void *pcore_data, u8 *pbssid); /* Unused */ +s8 sme_get_desired_bssid(void *pcore_data, u8 *pbssid); /* Not use */ s8 sme_set_desired_bssid(void *pcore_data, u8 *pbssid); /* OID_802_11_SSID */ s8 sme_get_ssid(void *pcore_data, u8 *pssid, u8 *pssid_len); -s8 sme_get_desired_ssid(void *pcore_data, u8 *pssid, u8 *pssid_len);/* Unused */ +s8 sme_get_desired_ssid(void *pcore_data, u8 *pssid, u8 *pssid_len);/* Not use */ s8 sme_set_desired_ssid(void *pcore_data, u8 *pssid, u8 ssid_len); /* OID_802_11_INFRASTRUCTURE_MODE */ s8 sme_get_bss_type(void *pcore_data, u8 *pbss_type); -s8 sme_get_desired_bss_type(void *pcore_data, u8 *pbss_type); /* Unused */ +s8 sme_get_desired_bss_type(void *pcore_data, u8 *pbss_type); /* Not use */ s8 sme_set_desired_bss_type(void *pcore_data, u8 bss_type); /* OID_802_11_FRAGMENTATION_THRESHOLD */ @@ -106,7 +107,7 @@ s8 sme_set_bssid_list_scan(void *pcore_data, void *pscan_para); s8 sme_set_reload_defaults(void *pcore_data, u8 reload_type); -/*------------------------- non-standard ----------------------------------*/ +/*------------------------- none-standard ----------------------------------*/ s8 sme_get_connect_status(void *pcore_data, u8 *pstatus); /*--------------------------------------------------------------------------*/ @@ -137,7 +138,7 @@ s8 sme_set_txrate_policy(void *pcore_data, u8 policy); s8 sme_get_txrate_policy(void *pcore_data, u8 *policy); s8 sme_get_cwmin_value(void *pcore_data, u8 *cwmin); s8 sme_get_cwmax_value(void *pcore_data, u16 *cwmax); -s8 sme_get_ms_radio_mode(void *pcore_data, u8 *pMsRadioOff); +s8 sme_get_ms_radio_mode(void *pcore_data, u8 * pMsRadioOff); s8 sme_set_ms_radio_mode(void *pcore_data, u8 boMsRadioOff); void sme_get_tx_power_level(void *pcore_data, u32 *TxPower); diff --git a/trunk/drivers/staging/winbond/wb35reg.c b/trunk/drivers/staging/winbond/wb35reg.c index 1bff7d1c9a77..da595f16f634 100644 --- a/trunk/drivers/staging/winbond/wb35reg.c +++ b/trunk/drivers/staging/winbond/wb35reg.c @@ -217,7 +217,7 @@ unsigned char Wb35Reg_Write(struct hw_data *pHwData, u16 RegisterNo, u32 Registe * This command will be executed with a user defined value. When it completes, * this value is useful. For example, hal_set_current_channel will use it. * true : read command process successfully - * false : register not supported + * false : register not support */ unsigned char Wb35Reg_WriteWithCallbackValue(struct hw_data *pHwData, u16 RegisterNo, @@ -631,7 +631,7 @@ unsigned char Wb35Reg_initial(struct hw_data *pHwData) * CardComputeCrc -- * * Description: - * Runs the AUTODIN II CRC algorithm on the buffers Buffer length. + * Runs the AUTODIN II CRC algorithm on buffer Buffer of length, Length. * * Arguments: * Buffer - the input buffer diff --git a/trunk/drivers/staging/winbond/wb35tx.c b/trunk/drivers/staging/winbond/wb35tx.c index 30a77ccfe480..5df39d46cda4 100644 --- a/trunk/drivers/staging/winbond/wb35tx.c +++ b/trunk/drivers/staging/winbond/wb35tx.c @@ -1,13 +1,13 @@ -/* - * Copyright (c) 1996-2002 Winbond Electronic Corporation - * - * Module Name: - * Wb35Tx.c - * - * Abstract: - * Processing the Tx message and put into down layer - * - */ +//============================================================================ +// Copyright (c) 1996-2002 Winbond Electronic Corporation +// +// Module Name: +// Wb35Tx.c +// +// Abstract: +// Processing the Tx message and put into down layer +// +//============================================================================ #include #include @@ -15,7 +15,7 @@ #include "mds_f.h" unsigned char -Wb35Tx_get_tx_buffer(struct hw_data *pHwData, u8 **pBuffer) +Wb35Tx_get_tx_buffer(struct hw_data * pHwData, u8 **pBuffer) { struct wb35_tx *pWb35Tx = &pHwData->Wb35Tx; @@ -25,29 +25,28 @@ Wb35Tx_get_tx_buffer(struct hw_data *pHwData, u8 **pBuffer) static void Wb35Tx(struct wbsoft_priv *adapter); -static void Wb35Tx_complete(struct urb *pUrb) +static void Wb35Tx_complete(struct urb * pUrb) { struct wbsoft_priv *adapter = pUrb->context; - struct hw_data *pHwData = &adapter->sHwData; + struct hw_data * pHwData = &adapter->sHwData; struct wb35_tx *pWb35Tx = &pHwData->Wb35Tx; struct wb35_mds *pMds = &adapter->Mds; printk("wb35: tx complete\n"); - /* Variable setting */ + // Variable setting pWb35Tx->EP4vm_state = VM_COMPLETED; - pWb35Tx->EP4VM_status = pUrb->status; /* Store the last result of Irp */ - /* Set the owner. Free the owner bit always. */ - pMds->TxOwner[pWb35Tx->TxSendIndex] = 0; + pWb35Tx->EP4VM_status = pUrb->status; //Store the last result of Irp + pMds->TxOwner[ pWb35Tx->TxSendIndex ] = 0;// Set the owner. Free the owner bit always. pWb35Tx->TxSendIndex++; pWb35Tx->TxSendIndex %= MAX_USB_TX_BUFFER_NUMBER; - if (pHwData->SurpriseRemove) /* Let WbWlanHalt handle surprise remove */ + if (pHwData->SurpriseRemove) // Let WbWlanHalt to handle surprise remove goto error; if (pWb35Tx->tx_halt) goto error; - /* The URB is completed, check the result */ + // The URB is completed, check the result if (pWb35Tx->EP4VM_status != 0) { printk("URB submission failed\n"); pWb35Tx->EP4vm_state = VM_STOP; @@ -65,42 +64,43 @@ static void Wb35Tx_complete(struct urb *pUrb) static void Wb35Tx(struct wbsoft_priv *adapter) { - struct hw_data *pHwData = &adapter->sHwData; + struct hw_data * pHwData = &adapter->sHwData; struct wb35_tx *pWb35Tx = &pHwData->Wb35Tx; u8 *pTxBufferAddress; struct wb35_mds *pMds = &adapter->Mds; - struct urb *pUrb = (struct urb *)pWb35Tx->Tx4Urb; - int retv; + struct urb * pUrb = (struct urb *)pWb35Tx->Tx4Urb; + int retv; u32 SendIndex; + if (pHwData->SurpriseRemove) goto cleanup; if (pWb35Tx->tx_halt) goto cleanup; - /* Ownership checking */ + // Ownership checking SendIndex = pWb35Tx->TxSendIndex; - /* No more data need to be sent, return immediately */ - if (!pMds->TxOwner[SendIndex]) + if (!pMds->TxOwner[SendIndex]) //No more data need to be sent, return immediately goto cleanup; pTxBufferAddress = pWb35Tx->TxBuffer[SendIndex]; - - /* Issuing URB */ + // + // Issuing URB + // usb_fill_bulk_urb(pUrb, pHwData->udev, usb_sndbulkpipe(pHwData->udev, 4), - pTxBufferAddress, pMds->TxBufferSize[SendIndex], + pTxBufferAddress, pMds->TxBufferSize[ SendIndex ], Wb35Tx_complete, adapter); pWb35Tx->EP4vm_state = VM_RUNNING; retv = usb_submit_urb(pUrb, GFP_ATOMIC); - if (retv < 0) { + if (retv<0) { printk("EP4 Tx Irp sending error\n"); goto cleanup; } - /* Check if driver needs issue Irp for EP2 */ + // Check if driver needs issue Irp for EP2 pWb35Tx->TxFillCount += pMds->TxCountInBuffer[SendIndex]; if (pWb35Tx->TxFillCount > 12) Wb35Tx_EP2VM_start(adapter); @@ -115,10 +115,10 @@ static void Wb35Tx(struct wbsoft_priv *adapter) void Wb35Tx_start(struct wbsoft_priv *adapter) { - struct hw_data *pHwData = &adapter->sHwData; + struct hw_data * pHwData = &adapter->sHwData; struct wb35_tx *pWb35Tx = &pHwData->Wb35Tx; - /* Allow only one thread to run into function */ + // Allow only one thread to run into function if (atomic_inc_return(&pWb35Tx->TxFireCounter) == 1) { pWb35Tx->EP4vm_state = VM_RUNNING; Wb35Tx(adapter); @@ -126,7 +126,7 @@ void Wb35Tx_start(struct wbsoft_priv *adapter) atomic_dec(&pWb35Tx->TxFireCounter); } -unsigned char Wb35Tx_initial(struct hw_data *pHwData) +unsigned char Wb35Tx_initial(struct hw_data * pHwData) { struct wb35_tx *pWb35Tx = &pHwData->Wb35Tx; @@ -135,50 +135,54 @@ unsigned char Wb35Tx_initial(struct hw_data *pHwData) return false; pWb35Tx->Tx2Urb = usb_alloc_urb(0, GFP_ATOMIC); - if (!pWb35Tx->Tx2Urb) { - usb_free_urb(pWb35Tx->Tx4Urb); + if (!pWb35Tx->Tx2Urb) + { + usb_free_urb( pWb35Tx->Tx4Urb ); return false; } return true; } -void Wb35Tx_stop(struct hw_data *pHwData) +//====================================================== +void Wb35Tx_stop(struct hw_data * pHwData) { struct wb35_tx *pWb35Tx = &pHwData->Wb35Tx; - /* Try to cancel the Trp of EP2 */ + // Trying to canceling the Trp of EP2 if (pWb35Tx->EP2vm_state == VM_RUNNING) - /* Only use unlink, let Wb35Tx_destroy free them */ - usb_unlink_urb(pWb35Tx->Tx2Urb); + usb_unlink_urb( pWb35Tx->Tx2Urb ); // Only use unlink, let Wb35Tx_destrot to free them pr_debug("EP2 Tx stop\n"); - /* Try to cancel the Irp of EP4 */ + // Trying to canceling the Irp of EP4 if (pWb35Tx->EP4vm_state == VM_RUNNING) - /* Only use unlink, let Wb35Tx_destroy free them */ - usb_unlink_urb(pWb35Tx->Tx4Urb); + usb_unlink_urb( pWb35Tx->Tx4Urb ); // Only use unlink, let Wb35Tx_destrot to free them pr_debug("EP4 Tx stop\n"); } -void Wb35Tx_destroy(struct hw_data *pHwData) +//====================================================== +void Wb35Tx_destroy(struct hw_data * pHwData) { struct wb35_tx *pWb35Tx = &pHwData->Wb35Tx; - /* Wait for VM stop */ + // Wait for VM stop do { - msleep(10); /* Delay for waiting function enter 940623.1.a */ - } while ((pWb35Tx->EP2vm_state != VM_STOP) && (pWb35Tx->EP4vm_state != VM_STOP)); - msleep(10); /* Delay for waiting function enter 940623.1.b */ + msleep(10); // Delay for waiting function enter 940623.1.a + } while( (pWb35Tx->EP2vm_state != VM_STOP) && (pWb35Tx->EP4vm_state != VM_STOP) ); + msleep(10); // Delay for waiting function enter 940623.1.b + + if (pWb35Tx->Tx4Urb) + usb_free_urb( pWb35Tx->Tx4Urb ); - usb_free_urb(pWb35Tx->Tx4Urb); - usb_free_urb(pWb35Tx->Tx2Urb); + if (pWb35Tx->Tx2Urb) + usb_free_urb( pWb35Tx->Tx2Urb ); pr_debug("Wb35Tx_destroy OK\n"); } void Wb35Tx_CurrentTime(struct wbsoft_priv *adapter, u32 TimeCount) { - struct hw_data *pHwData = &adapter->sHwData; + struct hw_data * pHwData = &adapter->sHwData; struct wb35_tx *pWb35Tx = &pHwData->Wb35Tx; unsigned char Trigger = false; @@ -195,45 +199,46 @@ void Wb35Tx_CurrentTime(struct wbsoft_priv *adapter, u32 TimeCount) static void Wb35Tx_EP2VM(struct wbsoft_priv *adapter); -static void Wb35Tx_EP2VM_complete(struct urb *pUrb) +static void Wb35Tx_EP2VM_complete(struct urb * pUrb) { struct wbsoft_priv *adapter = pUrb->context; - struct hw_data *pHwData = &adapter->sHwData; + struct hw_data * pHwData = &adapter->sHwData; struct T02_descriptor T02, TSTATUS; struct wb35_tx *pWb35Tx = &pHwData->Wb35Tx; - u32 *pltmp = (u32 *)pWb35Tx->EP2_buf; + u32 * pltmp = (u32 *)pWb35Tx->EP2_buf; u32 i; u16 InterruptInLength; - /* Variable setting */ + + // Variable setting pWb35Tx->EP2vm_state = VM_COMPLETED; pWb35Tx->EP2VM_status = pUrb->status; - /* For Linux 2.4. Interrupt will always trigger */ - if (pHwData->SurpriseRemove) /* Let WbWlanHalt handle surprise remove */ + // For Linux 2.4. Interrupt will always trigger + if (pHwData->SurpriseRemove) // Let WbWlanHalt to handle surprise remove goto error; if (pWb35Tx->tx_halt) goto error; - /* The Urb is completed, check the result */ + //The Urb is completed, check the result if (pWb35Tx->EP2VM_status != 0) { printk("EP2 IoCompleteRoutine return error\n"); - pWb35Tx->EP2vm_state = VM_STOP; + pWb35Tx->EP2vm_state= VM_STOP; goto error; } - /* Update the Tx result */ + // Update the Tx result InterruptInLength = pUrb->actual_length; - /* Modify for minimum memory access and DWORD alignment. */ - T02.value = cpu_to_le32(pltmp[0]) >> 8; /* [31:8] -> [24:0] */ - InterruptInLength -= 1; /* 20051221.1.c Modify the follow for more stable */ - InterruptInLength >>= 2; /* InterruptInLength/4 */ + // Modify for minimum memory access and DWORD alignment. + T02.value = cpu_to_le32(pltmp[0]) >> 8; // [31:8] -> [24:0] + InterruptInLength -= 1;// 20051221.1.c Modify the follow for more stable + InterruptInLength >>= 2; // InterruptInLength/4 for (i = 1; i <= InterruptInLength; i++) { T02.value |= ((cpu_to_le32(pltmp[i]) & 0xff) << 24); - TSTATUS.value = T02.value; /* 20061009 anson's endian */ - Mds_SendComplete(adapter, &TSTATUS); + TSTATUS.value = T02.value; //20061009 anson's endian + Mds_SendComplete( adapter, &TSTATUS ); T02.value = cpu_to_le32(pltmp[i]) >> 8; } @@ -245,10 +250,10 @@ static void Wb35Tx_EP2VM_complete(struct urb *pUrb) static void Wb35Tx_EP2VM(struct wbsoft_priv *adapter) { - struct hw_data *pHwData = &adapter->sHwData; + struct hw_data * pHwData = &adapter->sHwData; struct wb35_tx *pWb35Tx = &pHwData->Wb35Tx; - struct urb *pUrb = (struct urb *)pWb35Tx->Tx2Urb; - u32 *pltmp = (u32 *)pWb35Tx->EP2_buf; + struct urb * pUrb = (struct urb *)pWb35Tx->Tx2Urb; + u32 * pltmp = (u32 *)pWb35Tx->EP2_buf; int retv; if (pHwData->SurpriseRemove) @@ -257,10 +262,11 @@ static void Wb35Tx_EP2VM(struct wbsoft_priv *adapter) if (pWb35Tx->tx_halt) goto error; - /* Issuing URB */ - usb_fill_int_urb(pUrb, pHwData->udev, usb_rcvintpipe(pHwData->udev, 2), - pltmp, MAX_INTERRUPT_LENGTH, Wb35Tx_EP2VM_complete, - adapter, 32); + // + // Issuing URB + // + usb_fill_int_urb( pUrb, pHwData->udev, usb_rcvintpipe(pHwData->udev,2), + pltmp, MAX_INTERRUPT_LENGTH, Wb35Tx_EP2VM_complete, adapter, 32); pWb35Tx->EP2vm_state = VM_RUNNING; retv = usb_submit_urb(pUrb, GFP_ATOMIC); @@ -278,10 +284,10 @@ static void Wb35Tx_EP2VM(struct wbsoft_priv *adapter) void Wb35Tx_EP2VM_start(struct wbsoft_priv *adapter) { - struct hw_data *pHwData = &adapter->sHwData; + struct hw_data * pHwData = &adapter->sHwData; struct wb35_tx *pWb35Tx = &pHwData->Wb35Tx; - /* Allow only one thread to run into function */ + // Allow only one thread to run into function if (atomic_inc_return(&pWb35Tx->TxResultCount) == 1) { pWb35Tx->EP2vm_state = VM_RUNNING; Wb35Tx_EP2VM(adapter); diff --git a/trunk/drivers/staging/winbond/wb35tx_s.h b/trunk/drivers/staging/winbond/wb35tx_s.h index 715f87d6ac5b..f70f43395591 100644 --- a/trunk/drivers/staging/winbond/wb35tx_s.h +++ b/trunk/drivers/staging/winbond/wb35tx_s.h @@ -3,37 +3,45 @@ #include "mds_s.h" -/* IS89C35 Tx related definition */ -#define TX_INTERFACE 0 /* Interface 1 */ -#define TX_PIPE 3 /* Endpoint 4 */ -#define TX_INTERRUPT 1 /* Endpoint 2 */ -#define MAX_INTERRUPT_LENGTH 64 /* It must be 64 for EP2 hardware */ +//==================================== +// IS89C35 Tx related definition +//==================================== +#define TX_INTERFACE 0 // Interface 1 +#define TX_PIPE 3 // endpoint 4 +#define TX_INTERRUPT 1 // endpoint 2 +#define MAX_INTERRUPT_LENGTH 64 // It must be 64 for EP2 hardware + + + +//==================================== +// Internal variable for module +//==================================== + -/* Internal variable for module */ struct wb35_tx { - /* For Tx buffer */ + // For Tx buffer u8 TxBuffer[ MAX_USB_TX_BUFFER_NUMBER ][ MAX_USB_TX_BUFFER ]; - /* For Interrupt pipe */ + // For Interrupt pipe u8 EP2_buf[MAX_INTERRUPT_LENGTH]; - atomic_t TxResultCount; /* For thread control of EP2 931130.4.m */ - atomic_t TxFireCounter; /* For thread control of EP4 931130.4.n */ - u32 ByteTransfer; + atomic_t TxResultCount;// For thread control of EP2 931130.4.m + atomic_t TxFireCounter;// For thread control of EP4 931130.4.n + u32 ByteTransfer; - u32 TxSendIndex; /* The next index of Mds array to be sent */ - u32 EP2vm_state; /* for EP2vm state */ - u32 EP4vm_state; /* for EP4vm state */ - u32 tx_halt; /* Stopping VM */ + u32 TxSendIndex;// The next index of Mds array to be sent + u32 EP2vm_state; // for EP2vm state + u32 EP4vm_state; // for EP4vm state + u32 tx_halt; // Stopping VM - struct urb *Tx4Urb; - struct urb *Tx2Urb; + struct urb * Tx4Urb; + struct urb * Tx2Urb; int EP2VM_status; int EP4VM_status; - u32 TxFillCount; /* 20060928 */ - u32 TxTimer; /* 20060928 Add if sending packet is greater than 13 */ + u32 TxFillCount; // 20060928 + u32 TxTimer; // 20060928 Add if sending packet not great than 13 }; #endif diff --git a/trunk/drivers/staging/winbond/wbusb.c b/trunk/drivers/staging/winbond/wbusb.c index 0ca857ac473e..ef360547ecec 100644 --- a/trunk/drivers/staging/winbond/wbusb.c +++ b/trunk/drivers/staging/winbond/wbusb.c @@ -25,7 +25,7 @@ MODULE_DESCRIPTION("IS89C35 802.11bg WLAN USB Driver"); MODULE_LICENSE("GPL"); MODULE_VERSION("0.1"); -static const struct usb_device_id wb35_table[] = { +static const struct usb_device_id wb35_table[] __devinitconst = { { USB_DEVICE(0x0416, 0x0035) }, { USB_DEVICE(0x18E8, 0x6201) }, { USB_DEVICE(0x18E8, 0x6206) }, diff --git a/trunk/drivers/staging/wlags49_h2/README.ubuntu b/trunk/drivers/staging/wlags49_h2/README.ubuntu index bfad7dc7725f..5f1cfb8fd427 100644 --- a/trunk/drivers/staging/wlags49_h2/README.ubuntu +++ b/trunk/drivers/staging/wlags49_h2/README.ubuntu @@ -46,12 +46,12 @@ If you have a card using the HERMES II.5 chip you have to make changes to the Makefile and uncomment -DHERMES25. This will build driver wlags49_h25_cs. -Note: You can determine the type with command "pccardctrl info" +Note: You can detemine the type with command "pccardctrl info" MANIFID: 0156,0002 = HERMES - not supported by this driver MANIFID: 0156,0003 = HERMES II (Wireless B) MANIFID: 0156,0004 = HERMES II.5 (Wireless B/G) -After successful compile type command +After succesfull compile type command sudo make install @@ -81,7 +81,7 @@ The linux driver files (wl_xxxx.c) are changed in the following ways: - Addaptations of Andrey Borzenkov applied to 7.22 source - Alterations to avoid most HCF_ASSERTs -- Switching interrupts off and on in the HCF --- Bugfixes, things that were apparently wrong like reporting link status +-- Bugfixes, things that were aparently wrong like reporting link status change which checked a variable that was not changed in HCF anymore. -- Used on WEP but setting keys via SIOCSIWENCODEEXT was not supported -- Recovery actions added @@ -93,7 +93,7 @@ have to "open" the device first to get a handle and after "close" no changed; the former ioctl functions are now called before "open" and after "close", which was not expected. One of the problems was enable/ disable of interrupts in the HCF. Interrupt handling starts at "open" -so if a former "ioctl" routine is called before "open" or after "close" +so if a former "ioctl" routinge is called before "open" or after "close" then nothing should be done with interrupt switching in the HCF. Once this was solved most HCF_ASSERTS went away. @@ -120,8 +120,8 @@ include the man page. Even though setting parameters on the module does not work anymore but it provides some information about all the settings. -I have no personal contact with Agere, but others have. Agere -agreed to make their software available under the BSD license. +I have not have personal contact with Agere, but others have. Agere +agreed to make their software available under the BSD licence. This driver is based on the 7.22 version. The following was mailed by Agere to Andrey Borzenkov about this: diff --git a/trunk/drivers/staging/wlags49_h2/TODO b/trunk/drivers/staging/wlags49_h2/TODO index f1a45611b236..94032b6ac2b5 100644 --- a/trunk/drivers/staging/wlags49_h2/TODO +++ b/trunk/drivers/staging/wlags49_h2/TODO @@ -1,4 +1,4 @@ -First of all, the best thing would be that this driver becomes obsolete by +First of all, the best thing would be that this driver becomes obsolte by adding support for Hermes II and Hermes II.5 cards to the existing orinoco driver. The orinoco driver currently only supports Hermes I based cards. Since this will not happen by magic and has not happened until now this @@ -10,11 +10,11 @@ list. TODO: - verify against a Hermes II.5 card - - verify with WPA encryption (both with H2 and H2.5 cards) + - verify with WPA encription (both with H2 and H2.5 cards) - sometimes the card does not initialize correctly, retry mechanisms - are built in to catch most cases but not all + are build in to catch most cases but not all - once the driver runs it is very stable, but I have the impression - that some of the critical sections take some time. + some the crittical sections take to long - the driver is split into a Hermes II and a Hermes II.5 part, it would be nice to handle both with one module instead of two - review by the wireless developer community @@ -25,7 +25,7 @@ TODO: DONE: - verified against a Hermes II card (Thomson Speedtouch 110 PCMCIA card) - - verified with WEP encryption + - verified with WEP encription Please send any patches or complaints about this driver to Greg Kroah-Hartman and Cc: Henk de Groot diff --git a/trunk/drivers/staging/wlags49_h2/hcf.c b/trunk/drivers/staging/wlags49_h2/hcf.c index 4aac26d486f1..423544634ae5 100644 --- a/trunk/drivers/staging/wlags49_h2/hcf.c +++ b/trunk/drivers/staging/wlags49_h2/hcf.c @@ -508,7 +508,7 @@ HCF_STATIC hcf_16* BASED xxxx[ ] = { * - HCF_ACT_INT_FORCE_ON enable interrupt generation by WaveLAN NIC * - HCF_ACT_INT_OFF disable interrupt generation by WaveLAN NIC * - HCF_ACT_INT_ON compensate 1 HCF_ACT_INT_OFF, enable interrupt generation if balance reached - * - HCF_ACT_PRS_SCAN Hermes Probe Response Scan (F102) command + * - HCF_ACT_PRS_SCAN Hermes Probe Respons Scan (F102) command * - HCF_ACT_RX_ACK acknowledge non-DMA receiver to Hermes * - HCF_ACT_SCAN Hermes Inquire Scan (F101) command (non-WARP only) * - HCF_ACT_SLEEP DDS Sleep request @@ -571,7 +571,7 @@ HCF_STATIC hcf_16* BASED xxxx[ ] = { * The F/W is wokenup by the HCF when the NIC Interrupts mode are disabled, i.e. at the first HCF_ACT_INT_OFF * after going into sleep. * - * The following Miscellaneous actions are defined: + * The following Miscellanuous actions are defined: * * o HCF_ACT_RX_ACK: Receiver Acknowledgement (non-DMA, non-USB mode only) * Acking the receiver, frees the NIC memory used to hold the Rx frame and allows the F/W to @@ -579,7 +579,7 @@ HCF_STATIC hcf_16* BASED xxxx[ ] = { * If the MSF does not need access (any longer) to the current frame, e.g. because it is rejected based on the * look ahead or copied to another buffer, the receiver may be acked. Acking earlier is assumed to have the * potential of improving the performance. - * If the MSF does not explicitly ack the receiver, the acking is done implicitly if: + * If the MSF does not explitly ack te receiver, the acking is done implicitly if: * - the received frame fits in the look ahead buffer, by the hcf_service_nic call that reported the Rx frame * - if not in the above step, by hcf_rcv_msg (assuming hcf_rcv_msg is called) * - if neither of the above implicit acks nor an explicit ack by the MSF, by the first hcf_service_nic after @@ -591,9 +591,9 @@ HCF_STATIC hcf_16* BASED xxxx[ ] = { * The Inquire Tallies command requests the F/W to provide its current set of tallies. * See also hcf_get_info with CFG_TALLIES as parameter. * - * o HCF_ACT_PRS_SCAN: Inquire Probe Response Scan command + * o HCF_ACT_PRS_SCAN: Inquire Probe Respons Scan command * This command is only operational if the F/W is enabled. - * The Probe Response Scan command starts a scan sequence. + * The Probe Respons Scan command starts a scan sequence. * The HCF puts the result of this action in an MSF defined buffer (see CFG_RID_LOG_STRCT). * * o HCF_ACT_SCAN: Inquire Scan command @@ -606,7 +606,7 @@ HCF_STATIC hcf_16* BASED xxxx[ ] = { * - NIC interrupts are not disabled while required by parameter action. * - an invalid code is specified in parameter action. * - HCF_ACT_INT_ON commands outnumber the HCF_ACT_INT_OFF commands. - * - reentrancy, may be caused by calling hcf_functions without adequate protection against NIC interrupts or + * - reentrancy, may be caused by calling hcf_functions without adequate protection against NIC interrupts or * multi-threading * * - Since the HCF does not maintain status information relative to the F/W enabled state, it is not asserted @@ -625,7 +625,7 @@ HCF_STATIC hcf_16* BASED xxxx[ ] = { * change in HREG_EV_STAT matching a bit in HREG_INT_EN, i.e. not if invoked as result of another device * generating an interrupt on the shared interrupt line. * Note 1: it has been observed that under certain adverse conditions on certain platforms the writing of - * HREG_INT_EN can apparently fail, therefore it is paramount that HREG_INT_EN is written again with 0 for + * HREG_INT_EN can apparently fail, therefor it is paramount that HREG_INT_EN is written again with 0 for * each and every call to HCF_ACT_INT_OFF. * Note 2: it has been observed that under certain H/W & S/W architectures this logic is called when there is * no NIC at all. To cater for this, the value of HREG_INT_EN is validated. If the unused bit 0x0100 is set, @@ -902,7 +902,7 @@ hcf_action( IFBP ifbp, hcf_16 action ) * - A command other than Continue, Enable, Disable, Connect or Disconnect is given. * - An invalid combination of the subfields is given or a bit outside the subfields is given. * - any return code besides HCF_SUCCESS. - * - reentrancy, may be caused by calling a hcf_function without adequate protection against NIC interrupts or + * - reentrancy, may be caused by calling a hcf_function without adequate protection against NIC interrupts or * multi-threading * *.DIAGRAM @@ -1030,7 +1030,7 @@ hcf_cntl( IFBP ifbp, hcf_16 cmd ) * hcf_connect passes the MSF-defined location of the IFB to the HCF and grants or revokes access right for the * HCF to the IFB. Revoking is done by specifying HCF_DISCONNECT rather than an I/O address for the parameter * io_base. Every call of hcf_connect in "connect" mode, must eventually be followed by a call of hcf_connect - * in "disconnect" mode. Calling hcf_connect in "connect"/"disconnect" mode can not be nested. + * in "disconnect" mode. Clalling hcf_connect in "connect"/"disconnect" mode can not be nested. * The IFB address must be used as a handle with all subsequent HCF-function calls and the HCF uses the IFB * address as a handle when it performs a call(back) of an MSF-function (i.e. msf_assert). * @@ -1058,7 +1058,7 @@ hcf_cntl( IFBP ifbp, hcf_16 cmd ) * specification for S/W reset * Note 2: it turns out that on some H/W constellations, the clock to access the EEProm is not lowered * to an appropriate frequency by HREG_IO_SRESET. By giving an HCMD_INI first, this problem is worked around. - *2b: Experimentally it is determined over a wide range of F/W versions that are waiting for the for Cmd bit in + *2b: Experimentally it is determined over a wide range of F/W versions that waiting for the for Cmd bit in * Ev register gives a workable strategy. The available documentation does not give much clues. *4: clear and initialize the IFB * The HCF house keeping info is designed such that zero is the appropriate initial value for as much as diff --git a/trunk/drivers/staging/wlags49_h2/hcfcfg.h b/trunk/drivers/staging/wlags49_h2/hcfcfg.h index 869b5c343a86..39fb4d326f65 100644 --- a/trunk/drivers/staging/wlags49_h2/hcfcfg.h +++ b/trunk/drivers/staging/wlags49_h2/hcfcfg.h @@ -21,7 +21,7 @@ * hcfcfg.tpl list all #defines which must be specified to: * adjust the HCF functions defined in HCF.C to the characteristics of a specific environment * o maximum sizes for messages -* o Endianness +* o Endianess * Compiler specific macros * o port I/O macros * o type definitions diff --git a/trunk/drivers/staging/wlags49_h2/hcfdef.h b/trunk/drivers/staging/wlags49_h2/hcfdef.h index 74c0f713c57e..30744e194a23 100644 --- a/trunk/drivers/staging/wlags49_h2/hcfdef.h +++ b/trunk/drivers/staging/wlags49_h2/hcfdef.h @@ -652,15 +652,15 @@ err: you used an invalid bitmask; #if 0 //get compiler going #if HCF_EX_INT_TICK != HREG_EV_TICK ;? out dated checking -err: someone redefined these macros while the implementation assumes they are equal; +err: someone redefined these macros while the implemenation assumes they are equal; #endif #if HCF_EX_INT_TX_OK != HFS_TX_CNTL_TX_OK || HFS_TX_CNTL_TX_OK != HREG_EV_TX_OK ;? out dated checking -err: someone redefined these macros while the implementation assumes they are equal; +err: someone redefined these macros while the implemenation assumes they are equal; #endif #if HCF_EX_INT_TX_EX != HFS_TX_CNTL_TX_EX || HFS_TX_CNTL_TX_EX != HREG_EV_TX_EX ;? out dated checking -err: someone redefined these macros while the implementation assumes they are equal; +err: someone redefined these macros while the implemenation assumes they are equal; #endif #endif // 0 get compiler going diff --git a/trunk/drivers/staging/wlags49_h2/mdd.h b/trunk/drivers/staging/wlags49_h2/mdd.h index 0c914971c1ef..5c3515f31a16 100644 --- a/trunk/drivers/staging/wlags49_h2/mdd.h +++ b/trunk/drivers/staging/wlags49_h2/mdd.h @@ -652,7 +652,7 @@ XX1( CFG_SCAN, SCAN_RS_STRCT, scan_result[32] ) /*Scan results * #define CFG_CNF_WDS_ADDR6 0xFC16 //[AP] Port 6 MAC Adrs of corresponding WDS Link node #define CFG_CNF_PM_MCAST_BUF 0xFC17 //[AP] Switch for PM buffereing of Multicast Messages #define CFG_CNF_MCAST_PM_BUF CFG_CNF_PM_MCAST_BUF //name does not match H-II spec -#define CFG_CNF_REJECT_ANY 0xFC18 //[AP] Switch for PM buffering of Multicast Messages +#define CFG_CNF_REJECT_ANY 0xFC18 //[AP] Switch for PM buffereing of Multicast Messages #define CFG_CNF_ENCRYPTION 0xFC20 //select en/de-cryption of Tx/Rx messages #define CFG_CNF_AUTHENTICATION 0xFC21 //[STA] selects Authentication algorithm @@ -844,13 +844,13 @@ XX1( CFG_SCAN, SCAN_RS_STRCT, scan_result[32] ) /*Scan results * #define HCF_SUCCESS 0x00 // OK -#define HCF_ERR_TIME_OUT 0x04 // Expected Hermes event did not occur in expected time +#define HCF_ERR_TIME_OUT 0x04 // Expected Hermes event did not occure in expected time #define HCF_ERR_NO_NIC 0x05 /* card not found (usually yanked away during hcfio_in_string * Also: card is either absent or disabled while it should be neither */ #define HCF_ERR_LEN 0x08 /* buffer size insufficient * - IFB_ConfigTable too small * - hcf_get_info buffer has a size of 0 or 1 or less than needed - * to accommodate all data + * to accomodate all data * - hcf_put_info: CFG_DLNV_DATA exceeds intermediate * buffer size */ #define HCF_ERR_INCOMP_PRI 0x09 // primary functions are not compatible @@ -1004,7 +1004,7 @@ XX1( CFG_SCAN, SCAN_RS_STRCT, scan_result[32] ) /*Scan results * #define CFG_CURRENT_LINK_STATUS 0x090B //Latest link status got through 0xF200 LinkEvent /*============================================================ INFORMATION FRAMES =========================*/ -#define CFG_INFO_FRAME_MIN 0xF000 //lowest value representing an Information Frame +#define CFG_INFO_FRAME_MIN 0xF000 //lowest value representing an Informatio Frame #define CFG_TALLIES 0xF100 //Communications Tallies #define CFG_SCAN 0xF101 //Scan results diff --git a/trunk/drivers/staging/wlags49_h2/sta_h2.c b/trunk/drivers/staging/wlags49_h2/sta_h2.c index 00dffe2ed8f1..f9a38523724c 100644 --- a/trunk/drivers/staging/wlags49_h2/sta_h2.c +++ b/trunk/drivers/staging/wlags49_h2/sta_h2.c @@ -26,7 +26,7 @@ #include "hcfcfg.h" // to get hcf_16 etc defined as well as - // possible settings which influence mdd.h or dhf.h + // possible settings which inluence mdd.h or dhf.h #include "mdd.h" //to get COMP_ID_STA etc defined #include "dhf.h" //used to be "fhfmem.h", to get memblock,plugrecord, diff --git a/trunk/drivers/staging/wlags49_h2/sta_h25.c b/trunk/drivers/staging/wlags49_h2/sta_h25.c index 5b6f670d8ef2..86ca1cdd8497 100644 --- a/trunk/drivers/staging/wlags49_h2/sta_h25.c +++ b/trunk/drivers/staging/wlags49_h2/sta_h25.c @@ -25,7 +25,7 @@ #include "hcfcfg.h" // to get hcf_16 etc defined as well as - // possible settings which influence mdd.h or dhf.h + // possible settings which inluence mdd.h or dhf.h #include "mdd.h" //to get COMP_ID_STA etc defined #include "dhf.h" //used to be "fhfmem.h", to get memblock,plugrecord, diff --git a/trunk/drivers/staging/wlags49_h2/wl_enc.h b/trunk/drivers/staging/wlags49_h2/wl_enc.h index 1804611276b8..46629f3b112b 100644 --- a/trunk/drivers/staging/wlags49_h2/wl_enc.h +++ b/trunk/drivers/staging/wlags49_h2/wl_enc.h @@ -106,7 +106,7 @@ ENCSTRCT, *PENCSTRCT; /******************************************************************************* - * function prototypes + * function prrottypes ******************************************************************************/ int wl_wep_code( char *szCrypt, char *szDest, void *Data, int nLen ); diff --git a/trunk/drivers/staging/wlags49_h2/wl_if.h b/trunk/drivers/staging/wlags49_h2/wl_if.h index 6d66dabf032c..6a26130f5a3a 100644 --- a/trunk/drivers/staging/wlags49_h2/wl_if.h +++ b/trunk/drivers/staging/wlags49_h2/wl_if.h @@ -95,7 +95,7 @@ // Manufacture ID: 0156,0003 // Lowest measurment for noise floor seen is value 54 // Highest signal strength in close proximity to the AP seen is value 118 -// Very good must be around 100 (otherwise its never "full scale" +// Very good must be arround 100 (otherwise its never "full scale" // All other constants are derrived from these. This makes the signal gauge // work for me... #define HCF_MIN_SIGNAL_LEVEL 54 diff --git a/trunk/drivers/staging/wlags49_h2/wl_internal.h b/trunk/drivers/staging/wlags49_h2/wl_internal.h index b23078164149..553601f48873 100644 --- a/trunk/drivers/staging/wlags49_h2/wl_internal.h +++ b/trunk/drivers/staging/wlags49_h2/wl_internal.h @@ -11,7 +11,7 @@ * *------------------------------------------------------------------------------ * - * Header for definitions and macros internal to the drvier. + * Header for defintions and macros internal to the drvier. * *------------------------------------------------------------------------------ * @@ -838,7 +838,7 @@ typedef struct dma_strct DESC_STRCT *rx_packet[NUM_RX_DESC]; DESC_STRCT *rx_reclaim_desc, *tx_reclaim_desc; // Descriptors for host-reclaim purposes (see HCF) int tx_rsc_ind; // DMA Tx resource indicator is maintained in the MSF, not in the HCF - int rx_rsc_ind; // Also added rx resource indicator so that cleanup can be performed if alloc fails + int rx_rsc_ind; // Also added rx rsource indicator so that cleanup can be performed if alloc fails int status; } DMA_STRCT; diff --git a/trunk/drivers/staging/wlags49_h2/wl_main.c b/trunk/drivers/staging/wlags49_h2/wl_main.c index f5f120a62460..204107829577 100644 --- a/trunk/drivers/staging/wlags49_h2/wl_main.c +++ b/trunk/drivers/staging/wlags49_h2/wl_main.c @@ -63,7 +63,7 @@ * constant definitions ******************************************************************************/ -/* Allow support for calling system fcns to access F/W image file */ +/* Allow support for calling system fcns to access F/W iamge file */ #define __KERNEL_SYSCALLS__ /******************************************************************************* @@ -128,7 +128,7 @@ #include #endif /* BUS_PCI */ /******************************************************************************* - * macro definitions + * macro defintions ******************************************************************************/ #define VALID_PARAM(C) \ { \ @@ -1163,7 +1163,7 @@ int rc; CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.version_major ), CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.version_minor )); - /* now we will get the MAC address of the card */ + /* now we wil get the MAC address of the card */ lp->ltvRecord.len = 4; if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_AP ) { lp->ltvRecord.typ = CFG_NIC_MAC_ADDR; @@ -1374,7 +1374,7 @@ int wl_put_ltv_init( struct wl_private *lp ) lp->ltvRecord.len = 2; lp->ltvRecord.typ = CFG_CNTL_OPT; - /* The Card Services build must ALWAYS be configured for 16-bit I/O. PCI or + /* The Card Services build must ALWAYS configure for 16-bit I/O. PCI or CardBus can be set to either 16/32 bit I/O, or Bus Master DMA, but only for Hermes-2.5 */ #ifdef BUS_PCMCIA @@ -1627,7 +1627,7 @@ int wl_put_ltv( struct wl_private *lp ) lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( lp->TxRateControl[0] ); #endif // WARP -//;?skip temporarily to see whether the RID or something else is the problem hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); +//;?skip temporarily to see whether the RID or something else is the probelm hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); DBG_TRACE( DbgInfo, "CFG_TX_RATE_CNTL 2.4GHz : 0x%04x\n", lp->TxRateControl[0] ); @@ -2474,7 +2474,7 @@ void wl_resume(struct net_device *dev) * * DESCRIPTION: * - * This function performs a check on the device and calls wl_remove() if + * This function perfroms a check on the device and calls wl_remove() if * necessary. This function can be used for all bus types, but exists mostly * for the benefit of the Card Services driver, as there are times when * wl_remove() does not get called. @@ -2596,7 +2596,7 @@ int wl_enable( struct wl_private *lp ) lp->portState = WVLAN_PORT_STATE_ENABLED; //;?bad mnemonic, NIC iso PORT #ifdef ENABLE_DMA if ( lp->use_dma ) { - wl_pci_dma_hcf_supply( lp ); //;?always successful? + wl_pci_dma_hcf_supply( lp ); //;?always succes? } #endif } @@ -2874,7 +2874,7 @@ int wl_mbx( struct wl_private *lp ) * DESCRIPTION: * * This function will perform the tedious task of endian translating all - * fields within a mailbox message which need translating. + * fields withtin a mailbox message which need translating. * * PARAMETERS: * @@ -2989,7 +2989,7 @@ void wl_endian_translate_mailbox( ltv_t *ltv ) * * DESCRIPTION: * - * This function processes the mailbox data. + * This function will process the mailbox data. * * PARAMETERS: * diff --git a/trunk/drivers/staging/wlags49_h2/wl_netdev.c b/trunk/drivers/staging/wlags49_h2/wl_netdev.c index fb421407e106..824b85232353 100644 --- a/trunk/drivers/staging/wlags49_h2/wl_netdev.c +++ b/trunk/drivers/staging/wlags49_h2/wl_netdev.c @@ -652,6 +652,7 @@ void wl_tx_timeout( struct net_device *dev ) wl_unlock( lp, &flags ); DBG_LEAVE( DbgInfo ); + return; } // wl_tx_timeout /*============================================================================*/ @@ -835,7 +836,8 @@ int wl_tx( struct sk_buff *skb, struct net_device *dev, int port ) txF->frame.port = port; /* Move the frame to the txQ */ /* NOTE: Here's where we would do priority queueing */ - list_move(&(txF->node), &(lp->txQ[0])); + list_del( &( txF->node )); + list_add( &( txF->node ), &( lp->txQ[0] )); lp->txQ_count++; if( lp->txQ_count >= DEFAULT_NUM_TX_FRAMES ) { @@ -1250,7 +1252,7 @@ struct net_device * wl_device_alloc( void ) netif_stop_queue( dev ); - /* Allocate virtual devices for WDS support if needed */ + /* Allocate virutal devices for WDS support if needed */ WL_WDS_DEVICE_ALLOC( lp ); DBG_LEAVE( DbgInfo ); @@ -1290,6 +1292,7 @@ void wl_device_dealloc( struct net_device *dev ) free_netdev( dev ); DBG_LEAVE( DbgInfo ); + return; } // wl_device_dealloc /*============================================================================*/ @@ -1544,6 +1547,7 @@ void wl_wds_device_alloc( struct wl_private *lp ) WL_WDS_NETIF_STOP_QUEUE( lp ); DBG_LEAVE( DbgInfo ); + return; } // wl_wds_device_alloc /*============================================================================*/ @@ -1589,6 +1593,7 @@ void wl_wds_device_dealloc( struct wl_private *lp ) } DBG_LEAVE( DbgInfo ); + return; } // wl_wds_device_dealloc /*============================================================================*/ @@ -1599,7 +1604,7 @@ void wl_wds_device_dealloc( struct wl_private *lp ) * DESCRIPTION: * * Used to start the netif queues of all the "virtual" network devices - * which represent the WDS ports. + * which repesent the WDS ports. * * PARAMETERS: * @@ -1624,6 +1629,8 @@ void wl_wds_netif_start_queue( struct wl_private *lp ) } } } + + return; } // wl_wds_netif_start_queue /*============================================================================*/ @@ -1634,7 +1641,7 @@ void wl_wds_netif_start_queue( struct wl_private *lp ) * DESCRIPTION: * * Used to stop the netif queues of all the "virtual" network devices - * which represent the WDS ports. + * which repesent the WDS ports. * * PARAMETERS: * @@ -1659,6 +1666,8 @@ void wl_wds_netif_stop_queue( struct wl_private *lp ) } } } + + return; } // wl_wds_netif_stop_queue /*============================================================================*/ @@ -1669,7 +1678,7 @@ void wl_wds_netif_stop_queue( struct wl_private *lp ) * DESCRIPTION: * * Used to wake the netif queues of all the "virtual" network devices - * which represent the WDS ports. + * which repesent the WDS ports. * * PARAMETERS: * @@ -1694,6 +1703,8 @@ void wl_wds_netif_wake_queue( struct wl_private *lp ) } } } + + return; } // wl_wds_netif_wake_queue /*============================================================================*/ @@ -1704,7 +1715,7 @@ void wl_wds_netif_wake_queue( struct wl_private *lp ) * DESCRIPTION: * * Used to signal the network layer that carrier is present on all of the - * "virtual" network devices which represent the WDS ports. + * "virtual" network devices which repesent the WDS ports. * * PARAMETERS: * @@ -1727,6 +1738,8 @@ void wl_wds_netif_carrier_on( struct wl_private *lp ) } } } + + return; } // wl_wds_netif_carrier_on /*============================================================================*/ @@ -1737,7 +1750,7 @@ void wl_wds_netif_carrier_on( struct wl_private *lp ) * DESCRIPTION: * * Used to signal the network layer that carrier is NOT present on all of - * the "virtual" network devices which represent the WDS ports. + * the "virtual" network devices which repesent the WDS ports. * * PARAMETERS: * @@ -1750,15 +1763,18 @@ void wl_wds_netif_carrier_on( struct wl_private *lp ) ******************************************************************************/ void wl_wds_netif_carrier_off( struct wl_private *lp ) { - int count; + int count; + /*------------------------------------------------------------------------*/ - if(lp != NULL) { - for(count = 0; count < NUM_WDS_PORTS; count++) { - if(lp->wds_port[count].is_registered) - netif_carrier_off(lp->wds_port[count].dev); - } - } + if( lp != NULL ) { + for( count = 0; count < NUM_WDS_PORTS; count++ ) { + if( lp->wds_port[count].is_registered ) { + netif_carrier_off( lp->wds_port[count].dev ); + } + } + } + return; } // wl_wds_netif_carrier_off /*============================================================================*/ @@ -1794,19 +1810,22 @@ int wl_send_dma( struct wl_private *lp, struct sk_buff *skb, int port ) DBG_FUNC( "wl_send_dma" ); - if( lp == NULL ) { + if( lp == NULL ) + { DBG_ERROR( DbgInfo, "Private adapter struct is NULL\n" ); return FALSE; } - if( lp->dev == NULL ) { + if( lp->dev == NULL ) + { DBG_ERROR( DbgInfo, "net_device struct in wl_private is NULL\n" ); return FALSE; } /* AGAIN, ALL THE QUEUEING DONE HERE IN I/O MODE IS NOT PERFORMED */ - if( skb == NULL ) { + if( skb == NULL ) + { DBG_WARNING (DbgInfo, "Nothing to send.\n"); return FALSE; } @@ -1816,7 +1835,8 @@ int wl_send_dma( struct wl_private *lp, struct sk_buff *skb, int port ) /* Get a free descriptor */ desc = wl_pci_dma_get_tx_packet( lp ); - if( desc == NULL ) { + if( desc == NULL ) + { if( lp->netif_queue_on == TRUE ) { netif_stop_queue( lp->dev ); WL_WDS_NETIF_STOP_QUEUE( lp ); @@ -1832,7 +1852,8 @@ int wl_send_dma( struct wl_private *lp, struct sk_buff *skb, int port ) desc_next = desc->next_desc_addr; - if( desc_next->buf_addr == NULL ) { + if( desc_next->buf_addr == NULL ) + { DBG_ERROR( DbgInfo, "DMA descriptor buf_addr is NULL\n" ); return FALSE; } diff --git a/trunk/drivers/staging/wlags49_h2/wl_pci.c b/trunk/drivers/staging/wlags49_h2/wl_pci.c index a09c3ac793a2..0b31b01bd490 100644 --- a/trunk/drivers/staging/wlags49_h2/wl_pci.c +++ b/trunk/drivers/staging/wlags49_h2/wl_pci.c @@ -223,7 +223,7 @@ int wl_adapter_init_module( void ) ******************************************************************************/ void wl_adapter_cleanup_module( void ) { - //;?how come wl_adapter_cleanup_module is located in a seemingly pci specific module + //;?how comes wl_adapter_cleanup_module is located in a seemingly pci specific module DBG_FUNC( "wl_adapter_cleanup_module" ); DBG_ENTER( DbgInfo ); @@ -385,7 +385,7 @@ int wl_adapter_is_open( struct net_device *dev ) * DESCRIPTION: * * Registered in the pci_driver structure, this function is called when the - * PCI subsystem finds a new PCI device which matches the information contained + * PCI subsystem finds a new PCI device which matches the infomation contained * in the pci_device_id table. * * PARAMETERS: @@ -424,7 +424,7 @@ int __devinit wl_pci_probe( struct pci_dev *pdev, * DESCRIPTION: * * Registered in the pci_driver structure, this function is called when the - * PCI subsystem detects that a PCI device which matches the information + * PCI subsystem detects that a PCI device which matches the infomation * contained in the pci_device_id table has been removed. * * PARAMETERS: @@ -899,7 +899,7 @@ int wl_pci_dma_free_tx_packet( struct pci_dev *pdev, struct wl_private *lp, * DESCRIPTION: * * Allocates a single Rx packet, consisting of two descriptors and one - * contiguous buffer. The buffer starts with the hermes-specific header. + * contiguous buffer. THe buffer starts with the hermes-specific header. * One descriptor points at the start, the other at offset 0x3a of the * buffer. * diff --git a/trunk/drivers/staging/wlags49_h2/wl_priv.c b/trunk/drivers/staging/wlags49_h2/wl_priv.c index 87e1e4123126..f30e5ee4bca3 100644 --- a/trunk/drivers/staging/wlags49_h2/wl_priv.c +++ b/trunk/drivers/staging/wlags49_h2/wl_priv.c @@ -225,7 +225,7 @@ int wvlan_uil_connect( struct uilreq *urq, struct wl_private *lp ) * * DESCRIPTION: * - * Disconnect from the UIL after a request has been completed. + * Disonnect from the UIL after a request has been completed. * * PARAMETERS: * diff --git a/trunk/drivers/staging/wlags49_h2/wl_profile.c b/trunk/drivers/staging/wlags49_h2/wl_profile.c index beabf5916df7..0e49272bc7a8 100644 --- a/trunk/drivers/staging/wlags49_h2/wl_profile.c +++ b/trunk/drivers/staging/wlags49_h2/wl_profile.c @@ -910,7 +910,7 @@ int parse_mac_address(char *value, u_char *byte_array) memset(byte_field, '\0', 3); while (value[value_offset] != '\0') { - /* Skip over the colon chars separating the bytes, if they exist */ + /* Skip over the colon chars seperating the bytes, if they exist */ if (value[value_offset] == ':') { value_offset++; continue; diff --git a/trunk/drivers/staging/wlags49_h2/wl_version.h b/trunk/drivers/staging/wlags49_h2/wl_version.h index 037b5266428c..3deacfac9d25 100644 --- a/trunk/drivers/staging/wlags49_h2/wl_version.h +++ b/trunk/drivers/staging/wlags49_h2/wl_version.h @@ -152,7 +152,7 @@ err: define bus type; /******************************************************************************* - * bus architecture specific defines, includes, etc. + * bus architechture specific defines, includes, etc. ******************************************************************************/ /* * There doesn't seem to be a difference for PCMCIA and PCI anymore, at least diff --git a/trunk/drivers/staging/wlags49_h2/wl_wext.c b/trunk/drivers/staging/wlags49_h2/wl_wext.c index f553366cccc5..7ff0a108da13 100644 --- a/trunk/drivers/staging/wlags49_h2/wl_wext.c +++ b/trunk/drivers/staging/wlags49_h2/wl_wext.c @@ -62,7 +62,6 @@ #include #include #include -#include #include #include @@ -174,7 +173,7 @@ static int hermes_clear_tkip_keys(ltv_t *ltv, u16 key_idx, u8 *addr) switch (key_idx) { case 0: - if (!is_broadcast_ether_addr(addr)) { + if (memcmp(addr, "\xff\xff\xff\xff\xff\xff", ETH_ALEN) != 0) { ltv->len = 7; ltv->typ = CFG_REMOVE_TKIP_MAPPED_KEY; memcpy(<v->u.u8[0], addr, ETH_ALEN); @@ -606,7 +605,7 @@ static int wireless_get_range(struct net_device *dev, struct iw_request_info *in if (retries < 10) { retries++; - /* Holding the lock too long, makes a gap to allow other processes */ + /* Holding the lock too long, make a gap to allow other processes */ wl_unlock(lp, &flags); wl_lock( lp, &flags ); @@ -618,7 +617,7 @@ static int wireless_get_range(struct net_device *dev, struct iw_request_info *in goto out_unlock; } - /* Holding the lock too long, makes a gap to allow other processes */ + /* Holding the lock too long, make a gap to allow other processes */ wl_unlock(lp, &flags); wl_lock( lp, &flags ); @@ -631,7 +630,7 @@ static int wireless_get_range(struct net_device *dev, struct iw_request_info *in } } - /* Holding the lock too long, makes a gap to allow other processes */ + /* Holding the lock too long, make a gap to allow other processes */ wl_unlock(lp, &flags); wl_lock( lp, &flags ); @@ -694,7 +693,7 @@ static int wireless_get_range(struct net_device *dev, struct iw_request_info *in /* Encryption */ - /* Holding the lock too long, makes a gap to allow other processes */ + /* Holding the lock too long, make a gap to allow other processes */ wl_unlock(lp, &flags); wl_lock( lp, &flags ); @@ -721,7 +720,7 @@ static int wireless_get_range(struct net_device *dev, struct iw_request_info *in // Retry Limits and Lifetime - NOT SUPPORTED - /* Holding the lock too long, makes a gap to allow other processes */ + /* Holding the lock too long, make a gap to allow other processes */ wl_unlock(lp, &flags); wl_lock( lp, &flags ); @@ -2596,7 +2595,7 @@ static int wireless_set_scan(struct net_device *dev, struct iw_request_info *inf int retries = 0; /*------------------------------------------------------------------------*/ - //;? Note: shows results as trace, returns always 0 unless BUSY + //;? Note: shows results as trace, retruns always 0 unless BUSY DBG_FUNC( "wireless_set_scan" ); DBG_ENTER( DbgInfo ); @@ -2646,7 +2645,7 @@ static int wireless_set_scan(struct net_device *dev, struct iw_request_info *inf DBG_TRACE( DbgInfo, "CFG_SCAN_CHANNEL result : 0x%x\n", status ); - // Holding the lock too long, makes a gap to allow other processes + // Holding the lock too long, make a gap to allow other processes wl_unlock(lp, &flags); wl_lock( lp, &flags ); @@ -2657,7 +2656,7 @@ static int wireless_set_scan(struct net_device *dev, struct iw_request_info *inf DBG_TRACE( DbgInfo, "Reset card to recover, attempt: %d\n", retries ); wl_reset( dev ); - // Holding the lock too long, makes a gap to allow other processes + // Holding the lock too long, make a gap to allow other processes wl_unlock(lp, &flags); wl_lock( lp, &flags ); @@ -2674,7 +2673,7 @@ static int wireless_set_scan(struct net_device *dev, struct iw_request_info *inf status = hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord )); - // Holding the lock too long, makes a gap to allow other processes + // Holding the lock too long, make a gap to allow other processes wl_unlock(lp, &flags); wl_lock( lp, &flags ); @@ -2682,7 +2681,7 @@ static int wireless_set_scan(struct net_device *dev, struct iw_request_info *inf /* Initiate the scan */ /* NOTE: Using HCF_ACT_SCAN has been removed, as using HCF_ACT_ACS_SCAN to - retrieve probe response must always be used to support WPA */ + retrieve probe responses must always be used to support WPA */ status = hcf_action( &( lp->hcfCtx ), HCF_ACT_ACS_SCAN ); if( status == HCF_SUCCESS ) { @@ -3055,7 +3054,7 @@ static void flush_tx(struct wl_private *lp) * Make sure that there is no data queued up in the firmware * before setting the TKIP keys. If this check is not * performed, some data may be sent out with incorrect MIC - * and cause synchronization errors with the AP + * and cause synchronizarion errors with the AP */ /* Check every 1ms for 100ms */ for (count = 0; count < 100; count++) { @@ -3655,7 +3654,7 @@ void wl_wext_event_ap( struct net_device *dev ) this event BEFORE sending the association event, as there are timing issues with the hostap supplicant. The supplicant will attempt to process an EAPOL-Key frame from an AP before receiving this information, which - is required for a proper processed frame. */ + is required properly process the said frame. */ wl_wext_event_assoc_ie( dev ); /* Get the BSSID */ diff --git a/trunk/drivers/staging/wlags49_h25/Kconfig b/trunk/drivers/staging/wlags49_h25/Kconfig index dd8dc4d62c64..bf5664a51cd4 100644 --- a/trunk/drivers/staging/wlags49_h25/Kconfig +++ b/trunk/drivers/staging/wlags49_h25/Kconfig @@ -8,4 +8,4 @@ config WLAGS49_H25 Driver for wireless cards using Agere's HERMES II.5 chipset which are identified with Manufacture ID: 0156,0004 The software is a modified version of wl_lkm_722_abg.tar.gz - from the Agere Systems website, adapted for Ubuntu 9.04. + from the Agere Systems website, addapted for Ubuntu 9.04. diff --git a/trunk/drivers/staging/wlags49_h25/TODO b/trunk/drivers/staging/wlags49_h25/TODO index ec71ad3245e4..94032b6ac2b5 100644 --- a/trunk/drivers/staging/wlags49_h25/TODO +++ b/trunk/drivers/staging/wlags49_h25/TODO @@ -1,4 +1,4 @@ -First of all, the best thing would be that this driver becomes obsolete by +First of all, the best thing would be that this driver becomes obsolte by adding support for Hermes II and Hermes II.5 cards to the existing orinoco driver. The orinoco driver currently only supports Hermes I based cards. Since this will not happen by magic and has not happened until now this @@ -10,11 +10,11 @@ list. TODO: - verify against a Hermes II.5 card - - verify with WPA encryption (both with H2 and H2.5 cards) + - verify with WPA encription (both with H2 and H2.5 cards) - sometimes the card does not initialize correctly, retry mechanisms are build in to catch most cases but not all - once the driver runs it is very stable, but I have the impression - some the critical sections take to long + some the crittical sections take to long - the driver is split into a Hermes II and a Hermes II.5 part, it would be nice to handle both with one module instead of two - review by the wireless developer community @@ -25,7 +25,7 @@ TODO: DONE: - verified against a Hermes II card (Thomson Speedtouch 110 PCMCIA card) - - verified with WEP encryption + - verified with WEP encription Please send any patches or complaints about this driver to Greg Kroah-Hartman and Cc: Henk de Groot diff --git a/trunk/drivers/staging/wlan-ng/cfg80211.c b/trunk/drivers/staging/wlan-ng/cfg80211.c index 18c06a59c091..fabff4d650ef 100644 --- a/trunk/drivers/staging/wlan-ng/cfg80211.c +++ b/trunk/drivers/staging/wlan-ng/cfg80211.c @@ -1,7 +1,7 @@ /* cfg80211 Interface for prism2_usb module */ -/* Prism2 channel/frequency/bitrate declarations */ +/* Prism2 channell/frequency/bitrate declarations */ static const struct ieee80211_channel prism2_channels[] = { { .center_freq = 2412 }, { .center_freq = 2417 }, @@ -327,11 +327,11 @@ int prism2_get_station(struct wiphy *wiphy, struct net_device *dev, return result; } -int prism2_scan(struct wiphy *wiphy, struct cfg80211_scan_request *request) +int prism2_scan(struct wiphy *wiphy, struct net_device *dev, + struct cfg80211_scan_request *request) { - struct net_device *dev; struct prism2_wiphy_private *priv = wiphy_priv(wiphy); - wlandevice_t *wlandev; + wlandevice_t *wlandev = dev->ml_priv; struct p80211msg_dot11req_scan msg1; struct p80211msg_dot11req_scan_results msg2; struct cfg80211_bss *bss; @@ -345,9 +345,6 @@ int prism2_scan(struct wiphy *wiphy, struct cfg80211_scan_request *request) if (!request) return -EINVAL; - dev = request->wdev->netdev; - wlandev = dev->ml_priv; - if (priv->scan_request && priv->scan_request != request) return -EBUSY; @@ -502,7 +499,7 @@ int prism2_connect(struct wiphy *wiphy, struct net_device *dev, goto exit; } - /* Set the authorization */ + /* Set the authorisation */ if ((sme->auth_type == NL80211_AUTHTYPE_OPEN_SYSTEM) || ((sme->auth_type == NL80211_AUTHTYPE_AUTOMATIC) && !is_wep)) msg_join.authtype.data = P80211ENUM_authalg_opensystem; diff --git a/trunk/drivers/staging/wlan-ng/hfa384x_usb.c b/trunk/drivers/staging/wlan-ng/hfa384x_usb.c index f180c3d8b012..7843dfdaa3cf 100644 --- a/trunk/drivers/staging/wlan-ng/hfa384x_usb.c +++ b/trunk/drivers/staging/wlan-ng/hfa384x_usb.c @@ -2140,7 +2140,11 @@ int hfa384x_drvr_flashdl_write(hfa384x_t *hw, u32 daddr, void *buf, u32 len) ----------------------------------------------------------------*/ int hfa384x_drvr_getconfig(hfa384x_t *hw, u16 rid, void *buf, u16 len) { - return hfa384x_dorrid_wait(hw, rid, buf, len); + int result; + + result = hfa384x_dorrid_wait(hw, rid, buf, len); + + return result; } /*---------------------------------------------------------------- @@ -3786,7 +3790,7 @@ static void hfa384x_ctlxout_callback(struct urb *urb) #endif if ((urb->status == -ESHUTDOWN) || (urb->status == -ENODEV) || (hw == NULL)) - return; + goto done; retry: spin_lock_irqsave(&hw->ctlxq.lock, flags); @@ -3799,7 +3803,7 @@ static void hfa384x_ctlxout_callback(struct urb *urb) */ if (list_empty(&hw->ctlxq.active)) { spin_unlock_irqrestore(&hw->ctlxq.lock, flags); - return; + goto done; } /* @@ -3882,6 +3886,9 @@ static void hfa384x_ctlxout_callback(struct urb *urb) if (run_queue) hfa384x_usbctlxq_run(hw); + +done: + ; } /*---------------------------------------------------------------- @@ -3978,10 +3985,15 @@ static void hfa384x_usbctlx_resptimerfn(unsigned long data) if (unlocked_usbctlx_cancel_async(hw, ctlx) == 0) { spin_unlock_irqrestore(&hw->ctlxq.lock, flags); hfa384x_usbctlxq_run(hw); - return; + goto done; } } + spin_unlock_irqrestore(&hw->ctlxq.lock, flags); + +done: + ; + } /*---------------------------------------------------------------- @@ -4045,20 +4057,23 @@ static void hfa384x_usb_throttlefn(unsigned long data) static int hfa384x_usbctlx_submit(hfa384x_t *hw, hfa384x_usbctlx_t *ctlx) { unsigned long flags; + int ret; spin_lock_irqsave(&hw->ctlxq.lock, flags); if (hw->wlandev->hwremoved) { spin_unlock_irqrestore(&hw->ctlxq.lock, flags); - return -ENODEV; - } + ret = -ENODEV; + } else { + ctlx->state = CTLX_PENDING; + list_add_tail(&ctlx->list, &hw->ctlxq.pending); - ctlx->state = CTLX_PENDING; - list_add_tail(&ctlx->list, &hw->ctlxq.pending); - spin_unlock_irqrestore(&hw->ctlxq.lock, flags); - hfa384x_usbctlxq_run(hw); + spin_unlock_irqrestore(&hw->ctlxq.lock, flags); + hfa384x_usbctlxq_run(hw); + ret = 0; + } - return 0; + return ret; } /*---------------------------------------------------------------- diff --git a/trunk/drivers/staging/wlan-ng/p80211conv.c b/trunk/drivers/staging/wlan-ng/p80211conv.c index 3df753b51e89..f53a27a2e3fe 100644 --- a/trunk/drivers/staging/wlan-ng/p80211conv.c +++ b/trunk/drivers/staging/wlan-ng/p80211conv.c @@ -559,17 +559,17 @@ void p80211skb_rxmeta_detach(struct sk_buff *skb) /* Sanity checks */ if (skb == NULL) { /* bad skb */ pr_debug("Called w/ null skb.\n"); - return; + goto exit; } frmmeta = P80211SKB_FRMMETA(skb); if (frmmeta == NULL) { /* no magic */ pr_debug("Called w/ bad frmmeta magic.\n"); - return; + goto exit; } rxmeta = frmmeta->rx; if (rxmeta == NULL) { /* bad meta ptr */ pr_debug("Called w/ bad rxmeta ptr.\n"); - return; + goto exit; } /* Free rxmeta */ @@ -577,6 +577,8 @@ void p80211skb_rxmeta_detach(struct sk_buff *skb) /* Clear skb->cb */ memset(skb->cb, 0, sizeof(skb->cb)); +exit: + return; } /*---------------------------------------------------------------- @@ -658,4 +660,5 @@ void p80211skb_free(struct wlandevice *wlandev, struct sk_buff *skb) else printk(KERN_ERR "Freeing an skb (%p) w/ no frmmeta.\n", skb); dev_kfree_skb(skb); + return; } diff --git a/trunk/drivers/staging/wlan-ng/p80211netdev.c b/trunk/drivers/staging/wlan-ng/p80211netdev.c index 750330f064f9..0f51b4ab3631 100644 --- a/trunk/drivers/staging/wlan-ng/p80211netdev.c +++ b/trunk/drivers/staging/wlan-ng/p80211netdev.c @@ -240,7 +240,10 @@ void p80211netdev_rx(wlandevice_t *wlandev, struct sk_buff *skb) { /* Enqueue for post-irq processing */ skb_queue_tail(&wlandev->nsd_rxq, skb); + tasklet_schedule(&wlandev->rx_bh); + + return; } /*---------------------------------------------------------------- @@ -461,7 +464,7 @@ static int p80211knetdev_hard_start_xmit(struct sk_buff *skb, /*---------------------------------------------------------------- * p80211knetdev_set_multicast_list * -* Called from higher layers whenever there's a need to set/clear +* Called from higher lavers whenever there's a need to set/clear * promiscuous mode or rewrite the multicast list. * * Arguments: @@ -641,7 +644,7 @@ static int p80211knetdev_set_mac_address(netdevice_t *dev, void *addr) p80211item_unk392_t *mibattr; p80211item_pstr6_t *macaddr; p80211item_uint32_t *resultcode; - int result; + int result = 0; /* If we're running, we don't allow MAC address changes */ if (netif_running(dev)) @@ -803,13 +806,15 @@ int wlan_setup(wlandevice_t *wlandev, struct device *physdev) * Arguments: * wlandev ptr to the wlandev structure for the * interface. +* Returns: +* zero on success, non-zero otherwise. * Call Context: * Should be process thread. We'll assume it might be * interrupt though. When we add support for statically * compiled drivers, this function will be called in the * context of the kernel startup code. ----------------------------------------------------------------*/ -void wlan_unsetup(wlandevice_t *wlandev) +int wlan_unsetup(wlandevice_t *wlandev) { struct wireless_dev *wdev; @@ -822,6 +827,8 @@ void wlan_unsetup(wlandevice_t *wlandev) free_netdev(wlandev->netdev); wlandev->netdev = NULL; } + + return 0; } /*---------------------------------------------------------------- @@ -845,7 +852,13 @@ void wlan_unsetup(wlandevice_t *wlandev) ----------------------------------------------------------------*/ int register_wlandev(wlandevice_t *wlandev) { - return register_netdev(wlandev->netdev); + int i = 0; + + i = register_netdev(wlandev->netdev); + if (i) + return i; + + return 0; } /*---------------------------------------------------------------- diff --git a/trunk/drivers/staging/wlan-ng/p80211netdev.h b/trunk/drivers/staging/wlan-ng/p80211netdev.h index 2fecca2302f4..85884176b661 100644 --- a/trunk/drivers/staging/wlan-ng/p80211netdev.h +++ b/trunk/drivers/staging/wlan-ng/p80211netdev.h @@ -235,7 +235,7 @@ int wep_encrypt(wlandevice_t *wlandev, u8 *buf, u8 *dst, u32 len, int keynum, u8 *iv, u8 *icv); int wlan_setup(wlandevice_t *wlandev, struct device *physdev); -void wlan_unsetup(wlandevice_t *wlandev); +int wlan_unsetup(wlandevice_t *wlandev); int register_wlandev(wlandevice_t *wlandev); int unregister_wlandev(wlandevice_t *wlandev); void p80211netdev_rx(wlandevice_t *wlandev, struct sk_buff *skb); diff --git a/trunk/drivers/staging/wlan-ng/p80211req.c b/trunk/drivers/staging/wlan-ng/p80211req.c index cdfd808d6854..179194e7d2aa 100644 --- a/trunk/drivers/staging/wlan-ng/p80211req.c +++ b/trunk/drivers/staging/wlan-ng/p80211req.c @@ -73,7 +73,7 @@ #include "p80211req.h" static void p80211req_handlemsg(wlandevice_t *wlandev, struct p80211msg *msg); -static void p80211req_mibset_mibget(wlandevice_t *wlandev, +static int p80211req_mibset_mibget(wlandevice_t *wlandev, struct p80211msg_dot11req_mibget *mib_msg, int isget); @@ -155,29 +155,32 @@ static void p80211req_handlemsg(wlandevice_t *wlandev, struct p80211msg *msg) switch (msg->msgcode) { case DIDmsg_lnxreq_hostwep:{ - struct p80211msg_lnxreq_hostwep *req = - (struct p80211msg_lnxreq_hostwep *) msg; - wlandev->hostwep &= - ~(HOSTWEP_DECRYPT | HOSTWEP_ENCRYPT); - if (req->decrypt.data == P80211ENUM_truth_true) - wlandev->hostwep |= HOSTWEP_DECRYPT; - if (req->encrypt.data == P80211ENUM_truth_true) - wlandev->hostwep |= HOSTWEP_ENCRYPT; - - break; - } + struct p80211msg_lnxreq_hostwep *req = + (struct p80211msg_lnxreq_hostwep *) msg; + wlandev->hostwep &= + ~(HOSTWEP_DECRYPT | HOSTWEP_ENCRYPT); + if (req->decrypt.data == P80211ENUM_truth_true) + wlandev->hostwep |= HOSTWEP_DECRYPT; + if (req->encrypt.data == P80211ENUM_truth_true) + wlandev->hostwep |= HOSTWEP_ENCRYPT; + + break; + } case DIDmsg_dot11req_mibget: case DIDmsg_dot11req_mibset:{ - int isget = (msg->msgcode == DIDmsg_dot11req_mibget); - struct p80211msg_dot11req_mibget *mib_msg = - (struct p80211msg_dot11req_mibget *) msg; - p80211req_mibset_mibget(wlandev, mib_msg, isget); - break; - } + int isget = (msg->msgcode == DIDmsg_dot11req_mibget); + struct p80211msg_dot11req_mibget *mib_msg = + (struct p80211msg_dot11req_mibget *) msg; + p80211req_mibset_mibget(wlandev, mib_msg, isget); + } + default: + ; } /* switch msg->msgcode */ + + return; } -static void p80211req_mibset_mibget(wlandevice_t *wlandev, +static int p80211req_mibset_mibget(wlandevice_t *wlandev, struct p80211msg_dot11req_mibget *mib_msg, int isget) { @@ -187,65 +190,76 @@ static void p80211req_mibset_mibget(wlandevice_t *wlandev, switch (mibitem->did) { case DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey0:{ - if (!isget) - wep_change_key(wlandev, 0, key, pstr->len); - break; - } + if (!isget) + wep_change_key(wlandev, 0, key, pstr->len); + break; + } case DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey1:{ - if (!isget) - wep_change_key(wlandev, 1, key, pstr->len); - break; - } + if (!isget) + wep_change_key(wlandev, 1, key, pstr->len); + break; + } case DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey2:{ - if (!isget) - wep_change_key(wlandev, 2, key, pstr->len); - break; - } + if (!isget) + wep_change_key(wlandev, 2, key, pstr->len); + break; + } case DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey3:{ - if (!isget) - wep_change_key(wlandev, 3, key, pstr->len); - break; - } + if (!isget) + wep_change_key(wlandev, 3, key, pstr->len); + break; + } case DIDmib_dot11smt_dot11PrivacyTable_dot11WEPDefaultKeyID:{ - u32 *data = (u32 *) mibitem->data; + u32 *data = (u32 *) mibitem->data; - if (isget) { - *data = wlandev->hostwep & HOSTWEP_DEFAULTKEY_MASK; - } else { - wlandev->hostwep &= ~(HOSTWEP_DEFAULTKEY_MASK); - wlandev->hostwep |= (*data & HOSTWEP_DEFAULTKEY_MASK); + if (isget) { + *data = + wlandev->hostwep & HOSTWEP_DEFAULTKEY_MASK; + } else { + wlandev->hostwep &= ~(HOSTWEP_DEFAULTKEY_MASK); + + wlandev->hostwep |= + (*data & HOSTWEP_DEFAULTKEY_MASK); + } + break; } - break; - } case DIDmib_dot11smt_dot11PrivacyTable_dot11PrivacyInvoked:{ - u32 *data = (u32 *) mibitem->data; - - if (isget) { - if (wlandev->hostwep & HOSTWEP_PRIVACYINVOKED) - *data = P80211ENUM_truth_true; - else - *data = P80211ENUM_truth_false; - } else { - wlandev->hostwep &= ~(HOSTWEP_PRIVACYINVOKED); - if (*data == P80211ENUM_truth_true) - wlandev->hostwep |= HOSTWEP_PRIVACYINVOKED; + u32 *data = (u32 *) mibitem->data; + + if (isget) { + if (wlandev->hostwep & HOSTWEP_PRIVACYINVOKED) + *data = P80211ENUM_truth_true; + else + *data = P80211ENUM_truth_false; + } else { + wlandev->hostwep &= ~(HOSTWEP_PRIVACYINVOKED); + if (*data == P80211ENUM_truth_true) + wlandev->hostwep |= + HOSTWEP_PRIVACYINVOKED; + } + break; } - break; - } case DIDmib_dot11smt_dot11PrivacyTable_dot11ExcludeUnencrypted:{ - u32 *data = (u32 *) mibitem->data; - - if (isget) { - if (wlandev->hostwep & HOSTWEP_EXCLUDEUNENCRYPTED) - *data = P80211ENUM_truth_true; - else - *data = P80211ENUM_truth_false; - } else { - wlandev->hostwep &= ~(HOSTWEP_EXCLUDEUNENCRYPTED); - if (*data == P80211ENUM_truth_true) - wlandev->hostwep |= HOSTWEP_EXCLUDEUNENCRYPTED; + u32 *data = (u32 *) mibitem->data; + + if (isget) { + if (wlandev->hostwep & + HOSTWEP_EXCLUDEUNENCRYPTED) + *data = P80211ENUM_truth_true; + else + *data = P80211ENUM_truth_false; + } else { + wlandev->hostwep &= + ~(HOSTWEP_EXCLUDEUNENCRYPTED); + if (*data == P80211ENUM_truth_true) + wlandev->hostwep |= + HOSTWEP_EXCLUDEUNENCRYPTED; + } + break; } - break; - } + default: + ; } + + return 0; } diff --git a/trunk/drivers/staging/wlan-ng/p80211types.h b/trunk/drivers/staging/wlan-ng/p80211types.h index 8cb4fc6448a0..f043090ef86d 100644 --- a/trunk/drivers/staging/wlan-ng/p80211types.h +++ b/trunk/drivers/staging/wlan-ng/p80211types.h @@ -197,7 +197,7 @@ P80211DID_LSB_ACCESS) /*----------------------------------------------------------------*/ -/* The following structure types are used for the representation */ +/* The following structure types are used for the represenation */ /* of ENUMint type metadata. */ typedef struct p80211enumpair { diff --git a/trunk/drivers/staging/wlan-ng/p80211wep.c b/trunk/drivers/staging/wlan-ng/p80211wep.c index 77e50a4aa7e9..80c2d3b672bb 100644 --- a/trunk/drivers/staging/wlan-ng/p80211wep.c +++ b/trunk/drivers/staging/wlan-ng/p80211wep.c @@ -134,8 +134,10 @@ int wep_change_key(wlandevice_t *wlandev, int keynum, u8 *key, int keylen) return -1; #ifdef WEP_DEBUG - printk(KERN_DEBUG "WEP key %d len %d = %*phC\n", keynum, keylen, - 8, key); + printk(KERN_DEBUG + "WEP key %d len %d = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", + keynum, keylen, key[0], key[1], key[2], key[3], key[4], key[5], + key[6], key[7]); #endif wlandev->wep_keylens[keynum] = keylen; @@ -182,8 +184,10 @@ int wep_decrypt(wlandevice_t *wlandev, u8 *buf, u32 len, int key_override, keylen += 3; /* add in IV bytes */ #ifdef WEP_DEBUG - printk(KERN_DEBUG "D %d: %*ph (%d %d) %*phC\n", len, 3, key, - keyidx, keylen, 5, key + 3); + printk(KERN_DEBUG + "D %d: %02x %02x %02x (%d %d) %02x:%02x:%02x:%02x:%02x\n", len, + key[0], key[1], key[2], keyidx, keylen, key[3], key[4], key[5], + key[6], key[7]); #endif /* set up the RC4 state */ @@ -259,8 +263,10 @@ int wep_encrypt(wlandevice_t *wlandev, u8 *buf, u8 *dst, u32 len, int keynum, keylen += 3; /* add in IV bytes */ #ifdef WEP_DEBUG - printk(KERN_DEBUG "E %d (%d/%d %d) %*ph %*phC\n", len, - iv[3], keynum, keylen, 3, key, 5, key + 3); + printk(KERN_DEBUG + "E %d (%d/%d %d) %02x %02x %02x %02x:%02x:%02x:%02x:%02x\n", len, + iv[3], keynum, keylen, key[0], key[1], key[2], key[3], key[4], + key[5], key[6], key[7]); #endif /* set up the RC4 state */ diff --git a/trunk/drivers/staging/wlan-ng/prism2fw.c b/trunk/drivers/staging/wlan-ng/prism2fw.c index 0dfd2a4933ef..66c9aa972310 100644 --- a/trunk/drivers/staging/wlan-ng/prism2fw.c +++ b/trunk/drivers/staging/wlan-ng/prism2fw.c @@ -123,27 +123,27 @@ struct imgchunk { /* s-record image processing */ /* Data records */ -static unsigned int ns3data; -static struct s3datarec s3data[S3DATA_MAX]; +unsigned int ns3data; +struct s3datarec s3data[S3DATA_MAX]; /* Plug records */ -static unsigned int ns3plug; -static struct s3plugrec s3plug[S3PLUG_MAX]; +unsigned int ns3plug; +struct s3plugrec s3plug[S3PLUG_MAX]; /* CRC records */ -static unsigned int ns3crc; -static struct s3crcrec s3crc[S3CRC_MAX]; +unsigned int ns3crc; +struct s3crcrec s3crc[S3CRC_MAX]; /* Info records */ -static unsigned int ns3info; -static struct s3inforec s3info[S3INFO_MAX]; +unsigned int ns3info; +struct s3inforec s3info[S3INFO_MAX]; /* S7 record (there _better_ be only one) */ -static u32 startaddr; +u32 startaddr; /* Load image chunks */ -static unsigned int nfchunks; -static struct imgchunk fchunk[CHUNKS_MAX]; +unsigned int nfchunks; +struct imgchunk fchunk[CHUNKS_MAX]; /* Note that for the following pdrec_t arrays, the len and code */ /* fields are stored in HOST byte order. The mkpdrlist() function */ @@ -151,11 +151,11 @@ static struct imgchunk fchunk[CHUNKS_MAX]; /*----------------------------------------------------------------*/ /* PDA, built from [card|newfile]+[addfile1+addfile2...] */ -static struct pda pda; -static hfa384x_compident_t nicid; -static hfa384x_caplevel_t rfid; -static hfa384x_caplevel_t macid; -static hfa384x_caplevel_t priid; +struct pda pda; +hfa384x_compident_t nicid; +hfa384x_caplevel_t rfid; +hfa384x_caplevel_t macid; +hfa384x_caplevel_t priid; /*================================================================*/ /* Local Function Declarations */ @@ -237,7 +237,7 @@ int prism2_fwtry(struct usb_device *udev, wlandevice_t *wlandev) * 0 - success * ~0 - failure ----------------------------------------------------------------*/ -static int prism2_fwapply(const struct ihex_binrec *rfptr, wlandevice_t *wlandev) +int prism2_fwapply(const struct ihex_binrec *rfptr, wlandevice_t *wlandev) { signed int result = 0; struct p80211msg_dot11req_mibget getmsg; @@ -376,7 +376,7 @@ static int prism2_fwapply(const struct ihex_binrec *rfptr, wlandevice_t *wlandev * 0 success * ~0 failure ----------------------------------------------------------------*/ -static int crcimage(struct imgchunk *fchunk, unsigned int nfchunks, +int crcimage(struct imgchunk *fchunk, unsigned int nfchunks, struct s3crcrec *s3crc, unsigned int ns3crc) { int result = 0; @@ -440,7 +440,7 @@ static int crcimage(struct imgchunk *fchunk, unsigned int nfchunks, * Returns: * nothing ----------------------------------------------------------------*/ -static void free_chunks(struct imgchunk *fchunk, unsigned int *nfchunks) +void free_chunks(struct imgchunk *fchunk, unsigned int *nfchunks) { int i; for (i = 0; i < *nfchunks; i++) @@ -462,7 +462,7 @@ static void free_chunks(struct imgchunk *fchunk, unsigned int *nfchunks) * Returns: * nothing ----------------------------------------------------------------*/ -static void free_srecs(void) +void free_srecs(void) { ns3data = 0; memset(s3data, 0, sizeof(s3data)); @@ -489,7 +489,7 @@ static void free_srecs(void) * 0 - success * ~0 - failure (probably an errno) ----------------------------------------------------------------*/ -static int mkimage(struct imgchunk *clist, unsigned int *ccnt) +int mkimage(struct imgchunk *clist, unsigned int *ccnt) { int result = 0; int i; @@ -582,7 +582,7 @@ static int mkimage(struct imgchunk *clist, unsigned int *ccnt) * 0 - success * ~0 - failure (probably an errno) ----------------------------------------------------------------*/ -static int mkpdrlist(struct pda *pda) +int mkpdrlist(struct pda *pda) { int result = 0; u16 *pda16 = (u16 *) pda->buf; @@ -656,7 +656,7 @@ static int mkpdrlist(struct pda *pda) * 0 success * ~0 failure ----------------------------------------------------------------*/ -static int plugimage(struct imgchunk *fchunk, unsigned int nfchunks, +int plugimage(struct imgchunk *fchunk, unsigned int nfchunks, struct s3plugrec *s3plug, unsigned int ns3plug, struct pda *pda) { int result = 0; @@ -764,7 +764,7 @@ static int plugimage(struct imgchunk *fchunk, unsigned int nfchunks, * 0 - success * ~0 - failure (probably an errno) ----------------------------------------------------------------*/ -static int read_cardpda(struct pda *pda, wlandevice_t *wlandev) +int read_cardpda(struct pda *pda, wlandevice_t *wlandev) { int result = 0; struct p80211msg_p2req_readpda msg; @@ -806,7 +806,7 @@ static int read_cardpda(struct pda *pda, wlandevice_t *wlandev) * * Note also that the start address record, originally an S7 record in * the srec file, is expected in the fw file to be like a data record but -* with a certain address to make it identifiable. +* with a certain address to make it identiable. * * Here's the SREC format that the fw should have come from: * S[37]nnaaaaaaaaddd...dddcc @@ -854,7 +854,7 @@ static int read_cardpda(struct pda *pda, wlandevice_t *wlandev) * 0 - success * ~0 - failure (probably an errno) ----------------------------------------------------------------*/ -static int read_fwfile(const struct ihex_binrec *record) +int read_fwfile(const struct ihex_binrec *record) { int i; int rcnt = 0; @@ -978,7 +978,7 @@ static int read_fwfile(const struct ihex_binrec *record) * 0 success * ~0 failure ----------------------------------------------------------------*/ -static int writeimage(wlandevice_t *wlandev, struct imgchunk *fchunk, +int writeimage(wlandevice_t *wlandev, struct imgchunk *fchunk, unsigned int nfchunks) { int result = 0; @@ -1130,7 +1130,7 @@ static int writeimage(wlandevice_t *wlandev, struct imgchunk *fchunk, return result; } -static int validate_identity(void) +int validate_identity(void) { int i; int result = 1; diff --git a/trunk/drivers/staging/wlan-ng/prism2sta.c b/trunk/drivers/staging/wlan-ng/prism2sta.c index 8d2277bb898f..1dfd9aa5e9fe 100644 --- a/trunk/drivers/staging/wlan-ng/prism2sta.c +++ b/trunk/drivers/staging/wlan-ng/prism2sta.c @@ -242,6 +242,7 @@ static int prism2sta_close(wlandevice_t *wlandev) ----------------------------------------------------------------*/ static void prism2sta_reset(wlandevice_t *wlandev) { + return; } /*---------------------------------------------------------------- @@ -987,6 +988,7 @@ static void prism2sta_inf_handover(wlandevice_t *wlandev, hfa384x_InfFrame_t *inf) { pr_debug("received infoframe:HANDOVER (unhandled)\n"); + return; } /*---------------------------------------------------------------- @@ -1033,6 +1035,8 @@ static void prism2sta_inf_tallies(wlandevice_t *wlandev, for (i = 0; i < cnt; i++, dst++, src16++) *dst += le16_to_cpu(*src16); } + + return; } /*---------------------------------------------------------------- @@ -1089,6 +1093,8 @@ static void prism2sta_inf_scanresults(wlandevice_t *wlandev, printk(KERN_ERR "setconfig(joinreq) failed, result=%d\n", result); } + + return; } /*---------------------------------------------------------------- @@ -1188,6 +1194,7 @@ static void prism2sta_inf_chinforesults(wlandevice_t *wlandev, atomic_set(&hw->channel_info.done, 2); hw->channel_info.count = n; + return; } void prism2sta_processing_defer(struct work_struct *data) @@ -1211,7 +1218,7 @@ void prism2sta_processing_defer(struct work_struct *data) /* Now let's handle the linkstatus stuff */ if (hw->link_status == hw->link_status_new) - return; + goto failed; hw->link_status = hw->link_status_new; @@ -1265,7 +1272,7 @@ void prism2sta_processing_defer(struct work_struct *data) pr_debug ("getconfig(0x%02x) failed, result = %d\n", HFA384x_RID_CURRENTBSSID, result); - return; + goto failed; } result = hfa384x_drvr_getconfig(hw, @@ -1275,7 +1282,7 @@ void prism2sta_processing_defer(struct work_struct *data) pr_debug ("getconfig(0x%02x) failed, result = %d\n", HFA384x_RID_CURRENTSSID, result); - return; + goto failed; } prism2mgmt_bytestr2pstr((hfa384x_bytestr_t *) &ssid, (p80211pstrd_t *) & @@ -1289,7 +1296,7 @@ void prism2sta_processing_defer(struct work_struct *data) pr_debug ("getconfig(0x%02x) failed, result = %d\n", HFA384x_RID_PORTSTATUS, result); - return; + goto failed; } wlandev->macmode = (portstatus == HFA384x_PSTATUS_CONN_IBSS) ? @@ -1348,7 +1355,7 @@ void prism2sta_processing_defer(struct work_struct *data) if (result) { pr_debug("getconfig(0x%02x) failed, result = %d\n", HFA384x_RID_CURRENTBSSID, result); - return; + goto failed; } result = hfa384x_drvr_getconfig(hw, @@ -1357,7 +1364,7 @@ void prism2sta_processing_defer(struct work_struct *data) if (result) { pr_debug("getconfig(0x%02x) failed, result = %d\n", HFA384x_RID_CURRENTSSID, result); - return; + goto failed; } prism2mgmt_bytestr2pstr((hfa384x_bytestr_t *) &ssid, (p80211pstrd_t *) &wlandev->ssid); @@ -1436,10 +1443,14 @@ void prism2sta_processing_defer(struct work_struct *data) /* This is bad, IO port problems? */ printk(KERN_WARNING "unknown linkstatus=0x%02x\n", hw->link_status); - return; + goto failed; + break; } wlandev->linkstatus = (hw->link_status == HFA384x_LINK_CONNECTED); + +failed: + return; } /*---------------------------------------------------------------- @@ -1467,6 +1478,8 @@ static void prism2sta_inf_linkstatus(wlandevice_t *wlandev, hw->link_status_new = le16_to_cpu(inf->info.linkstatus.linkstatus); schedule_work(&hw->link_bh); + + return; } /*---------------------------------------------------------------- @@ -1527,6 +1540,8 @@ static void prism2sta_inf_assocstatus(wlandevice_t *wlandev, printk(KERN_WARNING "authfail assocstatus info frame received for authenticated station.\n"); } + + return; } /*---------------------------------------------------------------- @@ -1716,6 +1731,7 @@ static void prism2sta_inf_authreq_defer(wlandevice_t *wlandev, "setconfig(authenticatestation) failed, result=%d\n", result); } + return; } /*---------------------------------------------------------------- @@ -1742,6 +1758,8 @@ static void prism2sta_inf_psusercnt(wlandevice_t *wlandev, hfa384x_t *hw = (hfa384x_t *) wlandev->priv; hw->psusercount = le16_to_cpu(inf->info.psusercnt.usercnt); + + return; } /*---------------------------------------------------------------- @@ -1807,6 +1825,7 @@ void prism2sta_ev_info(wlandevice_t *wlandev, hfa384x_InfFrame_t *inf) "Unknown info type=0x%02x\n", inf->infotype); break; } + return; } /*---------------------------------------------------------------- @@ -1831,6 +1850,8 @@ void prism2sta_ev_info(wlandevice_t *wlandev, hfa384x_InfFrame_t *inf) void prism2sta_ev_txexc(wlandevice_t *wlandev, u16 status) { pr_debug("TxExc status=0x%x.\n", status); + + return; } /*---------------------------------------------------------------- @@ -1854,6 +1875,7 @@ void prism2sta_ev_tx(wlandevice_t *wlandev, u16 status) pr_debug("Tx Complete, status=0x%04x\n", status); /* update linux network stats */ wlandev->linux_stats.tx_packets++; + return; } /*---------------------------------------------------------------- @@ -1875,6 +1897,7 @@ void prism2sta_ev_tx(wlandevice_t *wlandev, u16 status) void prism2sta_ev_rx(wlandevice_t *wlandev, struct sk_buff *skb) { p80211netdev_rx(wlandev, skb); + return; } /*---------------------------------------------------------------- @@ -1896,6 +1919,7 @@ void prism2sta_ev_rx(wlandevice_t *wlandev, struct sk_buff *skb) void prism2sta_ev_alloc(wlandevice_t *wlandev) { netif_wake_queue(wlandev->netdev); + return; } /*---------------------------------------------------------------- @@ -1964,12 +1988,12 @@ void prism2sta_commsqual_defer(struct work_struct *data) int result = 0; if (hw->wlandev->hwremoved) - return; + goto done; /* we don't care if we're in AP mode */ if ((wlandev->macmode == WLAN_MACMODE_NONE) || (wlandev->macmode == WLAN_MACMODE_ESS_AP)) { - return; + goto done; } /* It only makes sense to poll these in non-IBSS */ @@ -1980,7 +2004,7 @@ void prism2sta_commsqual_defer(struct work_struct *data) if (result) { printk(KERN_ERR "error fetching commsqual\n"); - return; + goto done; } pr_debug("commsqual %d %d %d\n", @@ -1997,7 +2021,7 @@ void prism2sta_commsqual_defer(struct work_struct *data) if (result) { pr_debug("get signal rate failed, result = %d\n", result); - return; + goto done; } switch (mibitem->data) { @@ -2024,7 +2048,7 @@ void prism2sta_commsqual_defer(struct work_struct *data) if (result) { pr_debug("getconfig(0x%02x) failed, result = %d\n", HFA384x_RID_CURRENTBSSID, result); - return; + goto done; } result = hfa384x_drvr_getconfig(hw, @@ -2033,13 +2057,16 @@ void prism2sta_commsqual_defer(struct work_struct *data) if (result) { pr_debug("getconfig(0x%02x) failed, result = %d\n", HFA384x_RID_CURRENTSSID, result); - return; + goto done; } prism2mgmt_bytestr2pstr((hfa384x_bytestr_t *) &ssid, (p80211pstrd_t *) &wlandev->ssid); /* Reschedule timer */ mod_timer(&hw->commsqual_timer, jiffies + HZ); + +done: + ; } void prism2sta_commsqual_timer(unsigned long data) diff --git a/trunk/drivers/staging/xgifb/XGI_main_26.c b/trunk/drivers/staging/xgifb/XGI_main_26.c index f775c5453845..64ffd70eb7dc 100644 --- a/trunk/drivers/staging/xgifb/XGI_main_26.c +++ b/trunk/drivers/staging/xgifb/XGI_main_26.c @@ -6,7 +6,6 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -#include #include #ifdef CONFIG_MTRR @@ -330,7 +329,6 @@ static int XGIfb_validate_mode(struct xgifb_video_info *xgifb_info, int myindex) { u16 xres, yres; struct xgi_hw_device_info *hw_info = &xgifb_info->hw_info; - unsigned long required_mem; if (xgifb_info->chip == XG21) { if (xgifb_info->display2 == XGIFB_DISP_LCD) { @@ -347,13 +345,13 @@ static int XGIfb_validate_mode(struct xgifb_video_info *xgifb_info, int myindex) } } - goto check_memory; + return myindex; } /* FIXME: for now, all is valid on XG27 */ if (xgifb_info->chip == XG27) - goto check_memory; + return myindex; if (!(XGIbios_mode[myindex].chipset & MD_XGI315)) return -1; @@ -541,12 +539,6 @@ static int XGIfb_validate_mode(struct xgifb_video_info *xgifb_info, int myindex) case XGIFB_DISP_NONE: break; } - -check_memory: - required_mem = XGIbios_mode[myindex].xres * XGIbios_mode[myindex].yres * - XGIbios_mode[myindex].bpp / 8; - if (required_mem > xgifb_info->video_size) - return -1; return myindex; } @@ -921,10 +913,17 @@ static void XGIfb_post_setmode(struct xgifb_video_info *xgifb_info) } if ((filter >= 0) && (filter <= 7)) { - pr_debug("FilterTable[%d]-%d: %*ph\n", + pr_debug("FilterTable[%d]-%d: %02x %02x %02x %02x\n", filter_tb, filter, - 4, XGI_TV_filter[filter_tb]. - filter[filter]); + XGI_TV_filter[filter_tb]. + filter[filter][0], + XGI_TV_filter[filter_tb]. + filter[filter][1], + XGI_TV_filter[filter_tb]. + filter[filter][2], + XGI_TV_filter[filter_tb]. + filter[filter][3] + ); xgifb_reg_set( XGIPART2, 0x35, @@ -1405,10 +1404,11 @@ static int XGIfb_pan_display(struct fb_var_screeninfo *var, if (var->yoffset < 0 || var->yoffset >= info->var.yres_virtual || var->xoffset) return -EINVAL; - } else if (var->xoffset + info->var.xres > info->var.xres_virtual + } else { + if (var->xoffset + info->var.xres > info->var.xres_virtual || var->yoffset + info->var.yres - > info->var.yres_virtual) { - return -EINVAL; + > info->var.yres_virtual) + return -EINVAL; } err = XGIfb_pan_var(var, info); if (err < 0) @@ -1471,9 +1471,6 @@ static int XGIfb_get_dram_size(struct xgifb_video_info *xgifb_info) xgifb_reg_set(XGISR, IND_SIS_DRAM_SIZE, 0x51); reg = xgifb_reg_get(XGISR, IND_SIS_DRAM_SIZE); - if (!reg) - return -1; - switch ((reg & XGI_DRAM_SIZE_MASK) >> 4) { case XGI_DRAM_SIZE_1MB: xgifb_info->video_size = 0x100000; @@ -1704,7 +1701,6 @@ static int __devinit xgifb_probe(struct pci_dev *pdev, struct fb_info *fb_info; struct xgifb_video_info *xgifb_info; struct xgi_hw_device_info *hw_info; - unsigned long video_size_max; fb_info = framebuffer_alloc(sizeof(*xgifb_info), &pdev->dev); if (!fb_info) @@ -1725,7 +1721,6 @@ static int __devinit xgifb_probe(struct pci_dev *pdev, xgifb_info->subsysvendor = pdev->subsystem_vendor; xgifb_info->subsysdevice = pdev->subsystem_device; - video_size_max = pci_resource_len(pdev, 0); xgifb_info->video_base = pci_resource_start(pdev, 0); xgifb_info->mmio_base = pci_resource_start(pdev, 1); xgifb_info->mmio_size = pci_resource_len(pdev, 1); @@ -1782,10 +1777,10 @@ static int __devinit xgifb_probe(struct pci_dev *pdev, hw_info->jChipType = xgifb_info->chip; if (XGIfb_get_dram_size(xgifb_info)) { - xgifb_info->video_size = min_t(unsigned long, video_size_max, - SZ_16M); - } else if (xgifb_info->video_size > video_size_max) { - xgifb_info->video_size = video_size_max; + dev_err(&pdev->dev, + "Fatal error: Unable to determine RAM size.\n"); + ret = -ENODEV; + goto error_disable; } /* Enable PCI_LINEAR_ADDRESSING and MMIO_ENABLE */ diff --git a/trunk/drivers/staging/xgifb/vb_def.h b/trunk/drivers/staging/xgifb/vb_def.h index 77137e4452a0..69078d933a47 100644 --- a/trunk/drivers/staging/xgifb/vb_def.h +++ b/trunk/drivers/staging/xgifb/vb_def.h @@ -3,7 +3,9 @@ #include "../../video/sis/initdef.h" #define VB_XGI301C 0x0020 /* for 301C */ +#define VB_YPbPr1080i 0x03 +#define LVDSCRT1Len 15 #define SupportCRT2in301C 0x0100 /* for 301C */ #define SetCHTVOverScan 0x8000 @@ -20,6 +22,15 @@ #define XGI_CRT2_PORT_00 (0x00 - 0x030) +/* ============================================================= + for 310 +============================================================== */ +#define ModeSoftSetting 0x04 + +/* ---------------- SetMode Stack */ +#define CRT1Len 15 +#define VCLKLen 4 + #define SupportAllCRT2 0x0078 #define NoSupportTV 0x0070 #define NoSupportHiVisionTV 0x0060 @@ -104,6 +115,16 @@ #define ActiveHiTV 0x08 #define ActiveYPbPr 0x10 +/* --------------------------------------------------------- */ +/* translated from asm code 301def.h */ +/* */ +/* --------------------------------------------------------- */ +#define LVDSCRT1Len_H 8 +#define LVDSCRT1Len_V 7 +#define LCDDesDataLen 6 +#define LVDSDesDataLen2 8 +#define LCDDesDataLen2 8 + #define NTSC1024x768HT 1908 #define YPbPrTV525iHT 1716 /* YPbPr */ diff --git a/trunk/drivers/staging/xgifb/vb_init.c b/trunk/drivers/staging/xgifb/vb_init.c index 7739dbd9f029..80dba6a425ba 100644 --- a/trunk/drivers/staging/xgifb/vb_init.c +++ b/trunk/drivers/staging/xgifb/vb_init.c @@ -1269,7 +1269,7 @@ static unsigned char GetXG27FPBits(struct vb_device_info *pVBInfo) if (temp <= 2) temp &= 0x03; else - temp = ((temp & 0x04) >> 1) | ((~temp) & 0x01); + temp = ((temp & 0x04) >> 1) || ((~temp) & 0x01); xgifb_reg_set(pVBInfo->P3d4, 0x4A, CR4A); @@ -1299,6 +1299,8 @@ unsigned char XGIInitNew(struct pci_dev *pdev) outb(0x67, (pVBInfo->BaseAddr + 0x12)); /* 3c2 <- 67 ,ynlai */ + pVBInfo->ISXPDOS = 0; + pVBInfo->P3c4 = pVBInfo->BaseAddr + 0x14; pVBInfo->P3d4 = pVBInfo->BaseAddr + 0x24; pVBInfo->P3c0 = pVBInfo->BaseAddr + 0x10; @@ -1492,6 +1494,7 @@ unsigned char XGIInitNew(struct pci_dev *pdev) XGINew_SetModeScratch(HwDeviceExtension, pVBInfo); xgifb_reg_set(pVBInfo->P3d4, 0x8c, 0x87); + xgifb_reg_set(pVBInfo->P3c4, 0x14, 0x31); return 1; } /* end of init */ diff --git a/trunk/drivers/staging/xgifb/vb_setmode.c b/trunk/drivers/staging/xgifb/vb_setmode.c index e95a1655a6ce..e81149fc66e3 100644 --- a/trunk/drivers/staging/xgifb/vb_setmode.c +++ b/trunk/drivers/staging/xgifb/vb_setmode.c @@ -23,18 +23,20 @@ static const unsigned short XGINew_VGA_DAC[] = { void InitTo330Pointer(unsigned char ChipType, struct vb_device_info *pVBInfo) { - pVBInfo->StandTable = &XGI330_StandTable; - pVBInfo->EModeIDTable = XGI330_EModeIDTable; - pVBInfo->RefIndex = XGI330_RefIndex; - pVBInfo->XGINEWUB_CRT1Table = XGI_CRT1Table; - - pVBInfo->MCLKData = XGI340New_MCLKData; - pVBInfo->ECLKData = XGI340_ECLKData; - pVBInfo->VCLKData = XGI_VCLKData; - pVBInfo->VBVCLKData = XGI_VBVCLKData; + pVBInfo->StandTable = (struct SiS_StandTable_S *) &XGI330_StandTable; + pVBInfo->EModeIDTable = (struct XGI_ExtStruct *) XGI330_EModeIDTable; + pVBInfo->RefIndex = (struct XGI_Ext2Struct *) XGI330_RefIndex; + pVBInfo->XGINEWUB_CRT1Table + = (struct XGI_CRT1TableStruct *) XGI_CRT1Table; + + pVBInfo->MCLKData = (struct SiS_MCLKData *) XGI340New_MCLKData; + pVBInfo->ECLKData = (struct XGI_ECLKDataStruct *) XGI340_ECLKData; + pVBInfo->VCLKData = (struct SiS_VCLKData *) XGI_VCLKData; + pVBInfo->VBVCLKData = (struct SiS_VBVCLKData *) XGI_VBVCLKData; pVBInfo->ScreenOffset = XGI330_ScreenOffset; - pVBInfo->StResInfo = XGI330_StResInfo; - pVBInfo->ModeResInfo = XGI330_ModeResInfo; + pVBInfo->StResInfo = (struct SiS_StResInfo_S *) XGI330_StResInfo; + pVBInfo->ModeResInfo + = (struct SiS_ModeResInfo_S *) XGI330_ModeResInfo; pVBInfo->LCDResInfo = 0; pVBInfo->LCDTypeInfo = 0; @@ -54,9 +56,24 @@ void InitTo330Pointer(unsigned char ChipType, struct vb_device_info *pVBInfo) pVBInfo->SR21 = 0xa3; pVBInfo->SR22 = 0xfb; - pVBInfo->TimingH = XGI_TimingH; - pVBInfo->TimingV = XGI_TimingV; - pVBInfo->UpdateCRT1 = XGI_UpdateCRT1Table; + pVBInfo->NTSCTiming = XGI330_NTSCTiming; + pVBInfo->PALTiming = XGI330_PALTiming; + pVBInfo->HiTVExtTiming = XGI330_HiTVExtTiming; + pVBInfo->HiTVSt1Timing = XGI330_HiTVSt1Timing; + pVBInfo->HiTVSt2Timing = XGI330_HiTVSt2Timing; + pVBInfo->HiTVTextTiming = XGI330_HiTVTextTiming; + pVBInfo->YPbPr750pTiming = XGI330_YPbPr750pTiming; + pVBInfo->YPbPr525pTiming = XGI330_YPbPr525pTiming; + pVBInfo->YPbPr525iTiming = XGI330_YPbPr525iTiming; + pVBInfo->HiTVGroup3Data = XGI330_HiTVGroup3Data; + pVBInfo->HiTVGroup3Simu = XGI330_HiTVGroup3Simu; + pVBInfo->HiTVGroup3Text = XGI330_HiTVGroup3Text; + pVBInfo->Ren525pGroup3 = XGI330_Ren525pGroup3; + pVBInfo->Ren750pGroup3 = XGI330_Ren750pGroup3; + + pVBInfo->TimingH = (struct XGI_TimingHStruct *) XGI_TimingH; + pVBInfo->TimingV = (struct XGI_TimingVStruct *) XGI_TimingV; + pVBInfo->UpdateCRT1 = (struct XGI_XG21CRT1Struct *) XGI_UpdateCRT1Table; /* 310 customization related */ if ((pVBInfo->VBType & VB_SIS301LV) || (pVBInfo->VBType & VB_SIS302LV)) @@ -69,7 +86,8 @@ void InitTo330Pointer(unsigned char ChipType, struct vb_device_info *pVBInfo) if (ChipType == XG27) { unsigned char temp; - pVBInfo->MCLKData = XGI27New_MCLKData; + pVBInfo->MCLKData + = (struct SiS_MCLKData *) XGI27New_MCLKData; pVBInfo->CR40 = XGI27_cr41; pVBInfo->XGINew_CR97 = 0xc1; pVBInfo->SR15 = XG27_SR13; @@ -98,9 +116,11 @@ static void XGI_SetSeqRegs(unsigned short ModeNo, i = XGI_SetCRT2ToLCDA; if (pVBInfo->VBInfo & XGI_SetCRT2ToLCDA) { tempah |= 0x01; - } else if (pVBInfo->VBInfo & (SetCRT2ToTV | SetCRT2ToLCD)) { - if (pVBInfo->VBInfo & SetInSlaveMode) - tempah |= 0x01; + } else { + if (pVBInfo->VBInfo & (SetCRT2ToTV | SetCRT2ToLCD)) { + if (pVBInfo->VBInfo & SetInSlaveMode) + tempah |= 0x01; + } } tempah |= 0x20; /* screen off */ @@ -145,9 +165,10 @@ static void XGI_SetATTRegs(unsigned short ModeNo, if ((modeflag & Charx8Dot) && i == 0x13) { /* ifndef Dot9 */ if (pVBInfo->VBInfo & XGI_SetCRT2ToLCDA) { ARdata = 0; - } else if ((pVBInfo->VBInfo & + } else { + if ((pVBInfo->VBInfo & (SetCRT2ToTV | SetCRT2ToLCD)) && - (pVBInfo->VBInfo & SetInSlaveMode)) { + (pVBInfo->VBInfo & SetInSlaveMode)) ARdata = 0; } } @@ -237,45 +258,59 @@ static unsigned char XGI_AjustCRT2Rate(unsigned short ModeNo, } if (pVBInfo->VBInfo & SetCRT2ToHiVision) { /* for HiTV */ - tempax |= SupportHiVision; - if ((pVBInfo->VBInfo & SetInSlaveMode) && - ((resinfo == 4) || - (resinfo == 3 && - (pVBInfo->SetFlag & TVSimuMode)) || - (resinfo > 7))) + if ((pVBInfo->VBType & VB_SIS301LV) && + (pVBInfo->VBExtInfo == VB_YPbPr1080i)) { + tempax |= SupportYPbPr750p; + if ((pVBInfo->VBInfo & SetInSlaveMode) && + ((resinfo == 3) || + (resinfo == 4) || + (resinfo > 7))) return 0; - } else if (pVBInfo->VBInfo & (SetCRT2ToAVIDEO | + } else { + tempax |= SupportHiVision; + if ((pVBInfo->VBInfo & SetInSlaveMode) && + ((resinfo == 4) || + (resinfo == 3 && + (pVBInfo->SetFlag & TVSimuMode)) || + (resinfo > 7))) + return 0; + } + } else { + if (pVBInfo->VBInfo & (SetCRT2ToAVIDEO | SetCRT2ToSVIDEO | SetCRT2ToSCART | SetCRT2ToYPbPr525750 | SetCRT2ToHiVision)) { - tempax |= SupportTV; - - if (pVBInfo->VBType & (VB_SIS301B | - VB_SIS302B | - VB_SIS301LV | - VB_SIS302LV | - VB_XGI301C)) - tempax |= SupportTV1024; - - if (!(pVBInfo->VBInfo & TVSetPAL) && - (modeflag & NoSupportSimuTV) && - (pVBInfo->VBInfo & SetInSlaveMode) && - (!(pVBInfo->VBInfo & SetNotSimuMode))) - return 0; + tempax |= SupportTV; + + if (pVBInfo->VBType & (VB_SIS301B | + VB_SIS302B | + VB_SIS301LV | + VB_SIS302LV | + VB_XGI301C)) + tempax |= SupportTV1024; + + if (!(pVBInfo->VBInfo & TVSetPAL) && + (modeflag & NoSupportSimuTV) && + (pVBInfo->VBInfo & SetInSlaveMode) && + (!(pVBInfo->VBInfo & SetNotSimuMode))) + return 0; + } } - } else if (pVBInfo->VBInfo & SetCRT2ToLCD) { /* for LVDS */ - tempax |= SupportLCD; + } else { /* for LVDS */ + if (pVBInfo->VBInfo & SetCRT2ToLCD) { + tempax |= SupportLCD; - if (resinfo > 0x08) - return 0; /* 1024x768 */ + if (resinfo > 0x08) + return 0; /* 1024x768 */ - if (pVBInfo->LCDResInfo < Panel_1024x768) { - if (resinfo > 0x07) - return 0; /* 800x600 */ + if (pVBInfo->LCDResInfo < Panel_1024x768) { + if (resinfo > 0x07) + return 0; /* 800x600 */ - if (resinfo == 0x04) - return 0; /* 512x384 */ + if (resinfo == 0x04) + return 0; /* 512x384 */ + } } } @@ -934,8 +969,13 @@ static unsigned short XGI_GetVCLK2Ptr(unsigned short ModeNo, } /* 301lv */ - if (pVBInfo->VBType & VB_SIS301LV) { - if (pVBInfo->SetFlag & RPLLDIV2XO) + if ((pVBInfo->VBType & VB_SIS301LV) && + !(pVBInfo->VBExtInfo == VB_YPbPr1080i)) { + if (pVBInfo->VBExtInfo == YPbPr750p) + VCLKIndex = XGI_YPbPr750pVCLK; + else if (pVBInfo->VBExtInfo == YPbPr525p) + VCLKIndex = YPbPr525pVCLK; + else if (pVBInfo->SetFlag & RPLLDIV2XO) VCLKIndex = YPbPr525iVCLK_2; else VCLKIndex = YPbPr525iVCLK; @@ -951,11 +991,13 @@ static unsigned short XGI_GetVCLK2Ptr(unsigned short ModeNo, Ext_CRTVCLK; VCLKIndex &= IndexMask; } - } else if ((pVBInfo->LCDResInfo == Panel_800x600) || - (pVBInfo->LCDResInfo == Panel_320x480)) { /* LVDS */ - VCLKIndex = VCLK40; /* LVDSXlat1VCLK */ - } else { - VCLKIndex = VCLK65_315 + 2; /* LVDSXlat2VCLK, LVDSXlat3VCLK */ + } else { /* LVDS */ + if ((pVBInfo->LCDResInfo == Panel_800x600) || + (pVBInfo->LCDResInfo == Panel_320x480)) + VCLKIndex = VCLK40; /* LVDSXlat1VCLK */ + else + VCLKIndex = VCLK65_315 + 2; /* LVDSXlat2VCLK, + LVDSXlat3VCLK */ } return VCLKIndex; @@ -1310,7 +1352,7 @@ static void *XGI_GetLcdPtr(unsigned short BX, unsigned short ModeNo, unsigned short RefreshRateTableIndex, struct vb_device_info *pVBInfo) { - unsigned short i, tempdx, tempbx, tempal, modeflag, table; + unsigned short i, tempdx, tempcx, tempbx, tempal, modeflag, table; struct XGI330_LCDDataTablStruct *tempdi = NULL; @@ -1335,6 +1377,15 @@ static void *XGI_GetLcdPtr(unsigned short BX, unsigned short ModeNo, tempal = (tempal & 0x0f); } + tempcx = LCDLenList[tempbx]; + + if (pVBInfo->LCDInfo & EnableScalingLCD) { /* ScaleLCD */ + if ((tempbx == 5) || (tempbx) == 7) + tempcx = LCDDesDataLen2; + else if ((tempbx == 3) || (tempbx == 8)) + tempcx = LVDSDesDataLen2; + } + switch (tempbx) { case 0: case 1: @@ -1352,6 +1403,14 @@ static void *XGI_GetLcdPtr(unsigned short BX, unsigned short ModeNo, case 5: tempdi = XGI_LCDDesDataTable; break; + case 6: + tempdi = XGI_EPLCHLCDRegPtr; + break; + case 7: + case 8: + case 9: + tempdi = NULL; + break; default: break; } @@ -1705,20 +1764,62 @@ static void *XGI_GetLcdPtr(unsigned short BX, unsigned short ModeNo, default: break; } + } else if (table == 6) { + switch (tempdi[i].DATAPTR) { + case 0: + return &XGI_CH7017LV1024x768[tempal]; + break; + case 1: + return &XGI_CH7017LV1400x1050[tempal]; + break; + default: + break; + } } return NULL; } -static struct SiS_TVData const *XGI_GetTVPtr(unsigned short ModeNo, +static void *XGI_GetTVPtr(unsigned short BX, unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex, struct vb_device_info *pVBInfo) { - unsigned short i, tempdx, tempal, modeflag; + unsigned short i, tempdx, tempbx, tempal, modeflag, table; + struct XGI330_TVDataTablStruct *tempdi = NULL; + tempbx = BX; modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag; tempal = pVBInfo->RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC; tempal = tempal & 0x3f; + table = tempbx; + + switch (tempbx) { + case 0: + tempdi = NULL; + break; + case 1: + tempdi = NULL; + break; + case 2: + case 6: + tempdi = xgifb_chrontel_tv; + break; + case 3: + tempdi = NULL; + break; + case 4: + tempdi = XGI_TVDataTable; + break; + case 5: + tempdi = NULL; + break; + default: + break; + } + + if (tempdi == NULL) /* OEMUtil */ + return NULL; + tempdx = pVBInfo->TVInfo; if (pVBInfo->VBInfo & SetInSlaveMode) @@ -1729,14 +1830,78 @@ static struct SiS_TVData const *XGI_GetTVPtr(unsigned short ModeNo, i = 0; - while (XGI_TVDataTable[i].MASK != 0xffff) { - if ((tempdx & XGI_TVDataTable[i].MASK) == - XGI_TVDataTable[i].CAP) + while (tempdi[i].MASK != 0xffff) { + if ((tempdx & tempdi[i].MASK) == tempdi[i].CAP) break; i++; } - return &XGI_TVDataTable[i].DATAPTR[tempal]; + if (table == 0x04) { + switch (tempdi[i].DATAPTR) { + case 0: + return &XGI_ExtPALData[tempal]; + break; + case 1: + return &XGI_ExtNTSCData[tempal]; + break; + case 2: + return &XGI_StPALData[tempal]; + break; + case 3: + return &XGI_StNTSCData[tempal]; + break; + case 4: + return &XGI_ExtHiTVData[tempal]; + break; + case 5: + return &XGI_St2HiTVData[tempal]; + break; + case 6: + return &XGI_ExtYPbPr525iData[tempal]; + break; + case 7: + return &XGI_ExtYPbPr525pData[tempal]; + break; + case 8: + return &XGI_ExtYPbPr750pData[tempal]; + break; + case 9: + return &XGI_StYPbPr525iData[tempal]; + break; + case 10: + return &XGI_StYPbPr525pData[tempal]; + break; + case 11: + return &XGI_StYPbPr750pData[tempal]; + break; + case 12: /* avoid system hang */ + return &XGI_ExtNTSCData[tempal]; + break; + case 13: + return &XGI_St1HiTVData[tempal]; + break; + default: + break; + } + } else if (table == 0x02) { + switch (tempdi[i].DATAPTR) { + case 0: + return &XGI_CHTVUNTSCData[tempal]; + break; + case 1: + return &XGI_CHTVONTSCData[tempal]; + break; + case 2: + return &XGI_CHTVUPALData[tempal]; + break; + case 3: + return &XGI_CHTVOPALData[tempal]; + break; + default: + break; + } + } + return NULL; } static void XGI_GetLVDSData(unsigned short ModeNo, unsigned short ModeIdIndex, @@ -1749,8 +1914,9 @@ static void XGI_GetLVDSData(unsigned short ModeNo, unsigned short ModeIdIndex, tempbx = 2; if (pVBInfo->VBInfo & (SetCRT2ToLCD | XGI_SetCRT2ToLCDA)) { - LCDPtr = XGI_GetLcdPtr(tempbx, ModeNo, ModeIdIndex, - RefreshRateTableIndex, pVBInfo); + LCDPtr = (struct SiS_LVDSData *)XGI_GetLcdPtr(tempbx, + ModeNo, ModeIdIndex, RefreshRateTableIndex, + pVBInfo); pVBInfo->VGAHT = LCDPtr->VGAHT; pVBInfo->VGAVT = LCDPtr->VGAVT; pVBInfo->HT = LCDPtr->LCDHT; @@ -1796,8 +1962,11 @@ static void XGI_ModCRT1Regs(unsigned short ModeNo, unsigned short ModeIdIndex, tempbx = 0; if (pVBInfo->VBInfo & (SetCRT2ToLCD | XGI_SetCRT2ToLCDA)) { - LCDPtr = XGI_GetLcdPtr(tempbx, ModeNo, ModeIdIndex, - RefreshRateTableIndex, pVBInfo); + LCDPtr = (struct XGI_LVDSCRT1HDataStruct *) + XGI_GetLcdPtr(tempbx, ModeNo, + ModeIdIndex, + RefreshRateTableIndex, + pVBInfo); for (i = 0; i < 8; i++) pVBInfo->TimingH[0].data[i] = LCDPtr[0].Reg[i]; @@ -1808,8 +1977,13 @@ static void XGI_ModCRT1Regs(unsigned short ModeNo, unsigned short ModeIdIndex, tempbx = 1; if (pVBInfo->VBInfo & (SetCRT2ToLCD | XGI_SetCRT2ToLCDA)) { - LCDPtr1 = XGI_GetLcdPtr(tempbx, ModeNo, ModeIdIndex, - RefreshRateTableIndex, pVBInfo); + LCDPtr1 = (struct XGI_LVDSCRT1VDataStruct *) + XGI_GetLcdPtr( + tempbx, + ModeNo, + ModeIdIndex, + RefreshRateTableIndex, + pVBInfo); for (i = 0; i < 7; i++) pVBInfo->TimingV[0].data[i] = LCDPtr1[0].Reg[i]; } @@ -1901,11 +2075,23 @@ static void XGI_SetLVDSRegs(unsigned short ModeNo, unsigned short ModeIdIndex, modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag; tempbx = 3; if (pVBInfo->LCDInfo & EnableScalingLCD) - LCDPtr1 = XGI_GetLcdPtr(tempbx, ModeNo, ModeIdIndex, - RefreshRateTableIndex, pVBInfo); + LCDPtr1 = + (struct XGI330_LCDDataDesStruct2 *) + XGI_GetLcdPtr( + tempbx, + ModeNo, + ModeIdIndex, + RefreshRateTableIndex, + pVBInfo); else - LCDPtr = XGI_GetLcdPtr(tempbx, ModeNo, ModeIdIndex, - RefreshRateTableIndex, pVBInfo); + LCDPtr = + (struct XGI_LCDDesStruct *) + XGI_GetLcdPtr( + tempbx, + ModeNo, + ModeIdIndex, + RefreshRateTableIndex, + pVBInfo); XGI_GetLCDSync(&tempax, &tempbx, pVBInfo); push1 = tempbx; @@ -2252,8 +2438,8 @@ static void XGI_GetVCLKLen(unsigned char tempal, unsigned char *di_0, | VB_SIS301LV | VB_SIS302LV | VB_XGI301C)) { if ((!(pVBInfo->VBInfo & XGI_SetCRT2ToLCDA)) && (pVBInfo->SetFlag & ProgrammingCRT2)) { - *di_0 = XGI_VBVCLKData[tempal].Part4_A; - *di_1 = XGI_VBVCLKData[tempal].Part4_B; + *di_0 = (unsigned char) XGI_VBVCLKData[tempal].SR2B; + *di_1 = XGI_VBVCLKData[tempal].SR2C; } } else { *di_0 = XGI_VCLKData[tempal].SR2B; @@ -2448,16 +2634,21 @@ static void XGI_GetVBInfo(unsigned short ModeNo, unsigned short ModeIdIndex, temp = xgifb_reg_get(pVBInfo->P3d4, 0x38); - if (pVBInfo->IF_DEF_LVDS == 0) { - if (pVBInfo->VBType & - (VB_SIS302B | - VB_SIS301LV | - VB_SIS302LV | - VB_XGI301C)) { - if (temp & EnableDualEdge) { - tempbx |= SetCRT2ToDualEdge; - if (temp & SetToLCDA) - tempbx |= XGI_SetCRT2ToLCDA; + if (pVBInfo->IF_DEF_LCDA == 1) { + + if (((HwDeviceExtension->jChipType >= XG20) || + (HwDeviceExtension->jChipType >= XG40)) && + (pVBInfo->IF_DEF_LVDS == 0)) { + if (pVBInfo->VBType & + (VB_SIS302B | + VB_SIS301LV | + VB_SIS302LV | + VB_XGI301C)) { + if (temp & EnableDualEdge) { + tempbx |= SetCRT2ToDualEdge; + if (temp & SetToLCDA) + tempbx |= XGI_SetCRT2ToLCDA; + } } } } @@ -2496,10 +2687,11 @@ static void XGI_GetVBInfo(unsigned short ModeNo, unsigned short ModeIdIndex, temp = 0x09FC; else temp = 0x097C; - } else if (pVBInfo->IF_DEF_HiVision == 1) { - temp = 0x01FC; } else { - temp = 0x017C; + if (pVBInfo->IF_DEF_HiVision == 1) + temp = 0x01FC; + else + temp = 0x017C; } } else { /* 3nd party chip */ temp = SetCRT2ToLCD; @@ -2510,17 +2702,19 @@ static void XGI_GetVBInfo(unsigned short ModeNo, unsigned short ModeIdIndex, tempbx = 0; } - if (!(pVBInfo->VBType & VB_NoLCD)) { - if (tempbx & XGI_SetCRT2ToLCDA) { - if (tempbx & SetSimuScanMode) - tempbx &= (~(SetCRT2ToLCD | - SetCRT2ToRAMDAC | - SwitchCRT2)); - else - tempbx &= (~(SetCRT2ToLCD | - SetCRT2ToRAMDAC | - SetCRT2ToTV | - SwitchCRT2)); + if (pVBInfo->IF_DEF_LCDA == 1) { /* Select Display Device */ + if (!(pVBInfo->VBType & VB_NoLCD)) { + if (tempbx & XGI_SetCRT2ToLCDA) { + if (tempbx & SetSimuScanMode) + tempbx &= (~(SetCRT2ToLCD | + SetCRT2ToRAMDAC | + SwitchCRT2)); + else + tempbx &= (~(SetCRT2ToLCD | + SetCRT2ToRAMDAC | + SetCRT2ToTV | + SwitchCRT2)); + } } } @@ -2583,9 +2777,11 @@ static void XGI_GetVBInfo(unsigned short ModeNo, unsigned short ModeIdIndex, if (!(tempbx & DisableCRT2Display)) { if ((!(tempbx & DriverMode)) || (!(modeflag & CRT2Mode))) { - if (!(tempbx & XGI_SetCRT2ToLCDA)) - tempbx |= (SetInSlaveMode | - SetSimuScanMode); + if (pVBInfo->IF_DEF_LCDA == 1) { + if (!(tempbx & XGI_SetCRT2ToLCDA)) + tempbx |= (SetInSlaveMode | + SetSimuScanMode); + } } /* LCD+TV can't support in slave mode @@ -2671,17 +2867,19 @@ static void XGI_GetTVInfo(unsigned short ModeNo, unsigned short ModeIdIndex, if (pVBInfo->VBInfo & SetCRT2ToHiVision) { if (pVBInfo->VBInfo & SetInSlaveMode) tempbx &= (~RPLLDIV2XO); - } else if (tempbx & - (TVSetYPbPr525p | TVSetYPbPr750p)) { + } else { + if (tempbx & + (TVSetYPbPr525p | TVSetYPbPr750p)) tempbx &= (~RPLLDIV2XO); - } else if (!(pVBInfo->VBType & + else if (!(pVBInfo->VBType & (VB_SIS301B | VB_SIS302B | VB_SIS301LV | VB_SIS302LV | VB_XGI301C))) { - if (tempbx & TVSimuMode) - tempbx &= (~RPLLDIV2XO); + if (tempbx & TVSimuMode) + tempbx &= (~RPLLDIV2XO); + } } } } @@ -2762,6 +2960,20 @@ static unsigned char XGI_GetLCDInfo(unsigned short ModeNo, tempbx |= SetLCDtoNonExpanding; } + if (pVBInfo->IF_DEF_ExpLink == 1) { + if (modeflag & HalfDCLK) { + if (!(tempbx & SetLCDtoNonExpanding)) { + tempbx |= XGI_EnableLVDSDDA; + } else { + if (pVBInfo->LCDResInfo == Panel_1024x768) { + if (resinfo == 4) {/* 512x384 */ + tempbx |= XGI_EnableLVDSDDA; + } + } + } + } + } + if (pVBInfo->VBInfo & SetInSlaveMode) { if (pVBInfo->VBInfo & SetNotSimuMode) tempbx |= XGI_LCDVESATiming; @@ -2910,6 +3122,33 @@ static void XGI_XG27BLSignalVDD(unsigned short tempbh, unsigned short tempbl, xgifb_reg_and_or(pVBInfo->P3d4, 0x48, ~tempbh, tempbl); } +/* --------------------------------------------------------------------- */ +/* Function : XGI_XG21SetPanelDelay */ +/* Input : */ +/* Output : */ +/* Description : */ +/* I/P : bl : 1 ; T1 : the duration between CPL on and signal on */ +/* : bl : 2 ; T2 : the duration signal on and Vdd on */ +/* : bl : 3 ; T3 : the duration between CPL off and signal off */ +/* : bl : 4 ; T4 : the duration signal off and Vdd off */ +/* --------------------------------------------------------------------- */ +static void XGI_XG21SetPanelDelay(struct xgifb_video_info *xgifb_info, + unsigned short tempbl, + struct vb_device_info *pVBInfo) +{ + if (tempbl == 1) + mdelay(xgifb_info->lvds_data.PSC_S1); + + if (tempbl == 2) + mdelay(xgifb_info->lvds_data.PSC_S2); + + if (tempbl == 3) + mdelay(xgifb_info->lvds_data.PSC_S3); + + if (tempbl == 4) + mdelay(xgifb_info->lvds_data.PSC_S4); +} + static void XGI_DisplayOn(struct xgifb_video_info *xgifb_info, struct xgi_hw_device_info *pXGIHWDE, struct vb_device_info *pVBInfo) @@ -2921,12 +3160,12 @@ static void XGI_DisplayOn(struct xgifb_video_info *xgifb_info, if (!(XGI_XG21GetPSCValue(pVBInfo) & 0x1)) { /* LVDS VDD on */ XGI_XG21BLSignalVDD(0x01, 0x01, pVBInfo); - mdelay(xgifb_info->lvds_data.PSC_S2); + XGI_XG21SetPanelDelay(xgifb_info, 2, pVBInfo); } if (!(XGI_XG21GetPSCValue(pVBInfo) & 0x20)) /* LVDS signal on */ XGI_XG21BLSignalVDD(0x20, 0x20, pVBInfo); - mdelay(xgifb_info->lvds_data.PSC_S3); + XGI_XG21SetPanelDelay(xgifb_info, 3, pVBInfo); /* LVDS backlight on */ XGI_XG21BLSignalVDD(0x02, 0x02, pVBInfo); } else { @@ -2941,12 +3180,12 @@ static void XGI_DisplayOn(struct xgifb_video_info *xgifb_info, if (!(XGI_XG27GetPSCValue(pVBInfo) & 0x1)) { /* LVDS VDD on */ XGI_XG27BLSignalVDD(0x01, 0x01, pVBInfo); - mdelay(xgifb_info->lvds_data.PSC_S2); + XGI_XG21SetPanelDelay(xgifb_info, 2, pVBInfo); } if (!(XGI_XG27GetPSCValue(pVBInfo) & 0x20)) /* LVDS signal on */ XGI_XG27BLSignalVDD(0x20, 0x20, pVBInfo); - mdelay(xgifb_info->lvds_data.PSC_S3); + XGI_XG21SetPanelDelay(xgifb_info, 3, pVBInfo); /* LVDS backlight on */ XGI_XG27BLSignalVDD(0x02, 0x02, pVBInfo); } else { @@ -2966,7 +3205,7 @@ void XGI_DisplayOff(struct xgifb_video_info *xgifb_info, if (pVBInfo->IF_DEF_LVDS == 1) { /* LVDS backlight off */ XGI_XG21BLSignalVDD(0x02, 0x00, pVBInfo); - mdelay(xgifb_info->lvds_data.PSC_S3); + XGI_XG21SetPanelDelay(xgifb_info, 3, pVBInfo); } else { /* DVO/DVI signal off */ XGI_XG21BLSignalVDD(0x20, 0x00, pVBInfo); @@ -2977,7 +3216,7 @@ void XGI_DisplayOff(struct xgifb_video_info *xgifb_info, if ((XGI_XG27GetPSCValue(pVBInfo) & 0x2)) { /* LVDS backlight off */ XGI_XG27BLSignalVDD(0x02, 0x00, pVBInfo); - mdelay(xgifb_info->lvds_data.PSC_S3); + XGI_XG21SetPanelDelay(xgifb_info, 3, pVBInfo); } if (pVBInfo->IF_DEF_LVDS == 0) @@ -3139,6 +3378,7 @@ static void XGI_GetCRT2Data(unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short tempax = 0, tempbx, modeflag, resinfo; struct SiS_LCDData *LCDPtr = NULL; + struct SiS_TVData *TVPtr = NULL; /* si+Ext_ResInfo */ modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag; @@ -3155,8 +3395,9 @@ static void XGI_GetCRT2Data(unsigned short ModeNo, unsigned short ModeIdIndex, tempbx = 4; if (pVBInfo->VBInfo & (SetCRT2ToLCD | XGI_SetCRT2ToLCDA)) { - LCDPtr = XGI_GetLcdPtr(tempbx, ModeNo, ModeIdIndex, - RefreshRateTableIndex, pVBInfo); + LCDPtr = (struct SiS_LCDData *) XGI_GetLcdPtr(tempbx, + ModeNo, ModeIdIndex, RefreshRateTableIndex, + pVBInfo); pVBInfo->RVBHCMAX = LCDPtr->RVBHCMAX; pVBInfo->RVBHCFACT = LCDPtr->RVBHCFACT; @@ -3238,10 +3479,10 @@ static void XGI_GetCRT2Data(unsigned short ModeNo, unsigned short ModeIdIndex, } if (pVBInfo->VBInfo & (SetCRT2ToTV)) { - struct SiS_TVData const *TVPtr; - - TVPtr = XGI_GetTVPtr(ModeNo, ModeIdIndex, RefreshRateTableIndex, - pVBInfo); + tempbx = 4; + TVPtr = (struct SiS_TVData *) XGI_GetTVPtr(tempbx, + ModeNo, ModeIdIndex, RefreshRateTableIndex, + pVBInfo); pVBInfo->RVBHCMAX = TVPtr->RVBHCMAX; pVBInfo->RVBHCFACT = TVPtr->RVBHCFACT; @@ -3641,9 +3882,16 @@ static void XGI_SetLockRegs(unsigned short ModeNo, unsigned short ModeIdIndex, | VB_SIS302LV | VB_XGI301C))) temp += 2; - if ((pVBInfo->VBInfo & SetCRT2ToHiVision) && - !(pVBInfo->VBType & VB_SIS301LV) && (resinfo == 7)) + if (pVBInfo->VBInfo & SetCRT2ToHiVision) { + if (pVBInfo->VBType & VB_SIS301LV) { + if (pVBInfo->VBExtInfo == VB_YPbPr1080i) { + if (resinfo == 7) + temp -= 2; + } + } else if (resinfo == 7) { temp -= 2; + } + } } /* 0x05 Horizontal Display Start */ @@ -3813,16 +4061,18 @@ static void XGI_SetLockRegs(unsigned short ModeNo, unsigned short ModeIdIndex, } else { tempbx -= 10; } - } else if (pVBInfo->TVInfo & TVSimuMode) { - if (pVBInfo->TVInfo & TVSetPAL) { - if (pVBInfo->VBType & VB_SIS301LV) { - if (!(pVBInfo->TVInfo & - (TVSetYPbPr525p | - TVSetYPbPr750p | - TVSetHiVision))) + } else { + if (pVBInfo->TVInfo & TVSimuMode) { + if (pVBInfo->TVInfo & TVSetPAL) { + if (pVBInfo->VBType & VB_SIS301LV) { + if (!(pVBInfo->TVInfo & + (TVSetYPbPr525p | + TVSetYPbPr750p | + TVSetHiVision))) + tempbx += 40; + } else { tempbx += 40; - } else { - tempbx += 40; + } } } } @@ -3904,7 +4154,7 @@ static void XGI_SetGroup2(unsigned short ModeNo, unsigned short ModeIdIndex, { unsigned short i, j, tempax, tempbx, tempcx, temp, push1, push2, modeflag, resinfo, crt2crtc; - unsigned char const *TimingPoint; + unsigned char *TimingPoint; unsigned long longtemp, tempeax, tempebx, temp2, tempecx; @@ -3936,33 +4186,33 @@ static void XGI_SetGroup2(unsigned short ModeNo, unsigned short ModeIdIndex, tempax = (tempax & 0xff00) >> 8; xgifb_reg_set(pVBInfo->Part2Port, 0x0, tempax); - TimingPoint = XGI330_NTSCTiming; + TimingPoint = pVBInfo->NTSCTiming; if (pVBInfo->TVInfo & TVSetPAL) - TimingPoint = XGI330_PALTiming; + TimingPoint = pVBInfo->PALTiming; if (pVBInfo->VBInfo & SetCRT2ToHiVision) { - TimingPoint = XGI330_HiTVExtTiming; + TimingPoint = pVBInfo->HiTVExtTiming; if (pVBInfo->VBInfo & SetInSlaveMode) - TimingPoint = XGI330_HiTVSt2Timing; + TimingPoint = pVBInfo->HiTVSt2Timing; if (pVBInfo->SetFlag & TVSimuMode) - TimingPoint = XGI330_HiTVSt1Timing; + TimingPoint = pVBInfo->HiTVSt1Timing; if (!(modeflag & Charx8Dot)) - TimingPoint = XGI330_HiTVTextTiming; + TimingPoint = pVBInfo->HiTVTextTiming; } if (pVBInfo->VBInfo & SetCRT2ToYPbPr525750) { if (pVBInfo->TVInfo & TVSetYPbPr525i) - TimingPoint = XGI330_YPbPr525iTiming; + TimingPoint = pVBInfo->YPbPr525iTiming; if (pVBInfo->TVInfo & TVSetYPbPr525p) - TimingPoint = XGI330_YPbPr525pTiming; + TimingPoint = pVBInfo->YPbPr525pTiming; if (pVBInfo->TVInfo & TVSetYPbPr750p) - TimingPoint = XGI330_YPbPr750pTiming; + TimingPoint = pVBInfo->YPbPr750pTiming; } for (i = 0x01, j = 0; i <= 0x2D; i++, j++) @@ -4135,9 +4385,11 @@ static void XGI_SetGroup2(unsigned short ModeNo, unsigned short ModeIdIndex, temp += 1; } } - } else if (pVBInfo->VBInfo & SetInSlaveMode) { - if (ModeNo == 0x2f) - temp += 1; + } else { + if (pVBInfo->VBInfo & SetInSlaveMode) { + if (ModeNo == 0x2f) + temp += 1; + } } } @@ -4392,8 +4644,8 @@ static void XGI_SetLCDRegs(unsigned short ModeNo, unsigned short ModeIdIndex, /* Customized LCDB Des no add */ tempbx = 5; - LCDBDesPtr = XGI_GetLcdPtr(tempbx, ModeNo, ModeIdIndex, - RefreshRateTableIndex, pVBInfo); + LCDBDesPtr = (struct XGI_LCDDesStruct *) XGI_GetLcdPtr(tempbx, ModeNo, + ModeIdIndex, RefreshRateTableIndex, pVBInfo); tempah = pVBInfo->LCDResInfo; tempah &= PanelResInfo; @@ -4624,7 +4876,7 @@ static void XGI_SetGroup3(unsigned short ModeNo, unsigned short ModeIdIndex, struct vb_device_info *pVBInfo) { unsigned short i; - unsigned char const *tempdi; + unsigned char *tempdi; unsigned short modeflag; /* si+Ext_ResInfo */ @@ -4653,18 +4905,18 @@ static void XGI_SetGroup3(unsigned short ModeNo, unsigned short ModeIdIndex, if (pVBInfo->TVInfo & TVSetYPbPr525i) return; - tempdi = XGI330_HiTVGroup3Data; + tempdi = pVBInfo->HiTVGroup3Data; if (pVBInfo->SetFlag & TVSimuMode) { - tempdi = XGI330_HiTVGroup3Simu; + tempdi = pVBInfo->HiTVGroup3Simu; if (!(modeflag & Charx8Dot)) - tempdi = XGI330_HiTVGroup3Text; + tempdi = pVBInfo->HiTVGroup3Text; } if (pVBInfo->TVInfo & TVSetYPbPr525p) - tempdi = XGI330_Ren525pGroup3; + tempdi = pVBInfo->Ren525pGroup3; if (pVBInfo->TVInfo & TVSetYPbPr750p) - tempdi = XGI330_Ren750pGroup3; + tempdi = pVBInfo->Ren750pGroup3; for (i = 0; i <= 0x3E; i++) xgifb_reg_set(pVBInfo->Part3Port, i, tempdi[i]); @@ -4802,11 +5054,13 @@ static void XGI_SetGroup4(unsigned short ModeNo, unsigned short ModeIdIndex, if (pVBInfo->VBInfo & SetCRT2ToLCD) { if (tempax > 800) tempax -= 800; - } else if (pVBInfo->VGAHDE > 800) { - if (pVBInfo->VGAHDE == 1024) - tempax = (tempax * 25 / 32) - 1; - else - tempax = (tempax * 20 / 32) - 1; + } else { + if (pVBInfo->VGAHDE > 800) { + if (pVBInfo->VGAHDE == 1024) + tempax = (tempax * 25 / 32) - 1; + else + tempax = (tempax * 20 / 32) - 1; + } } tempax -= 1; @@ -4847,7 +5101,9 @@ static void XGI_SetGroup4(unsigned short ModeNo, unsigned short ModeIdIndex, } /* end 301b */ - XGI_SetCRT2VCLK(ModeNo, ModeIdIndex, RefreshRateTableIndex, pVBInfo); + if (pVBInfo->ISXPDOS == 0) + XGI_SetCRT2VCLK(ModeNo, ModeIdIndex, RefreshRateTableIndex, + pVBInfo); } static void XGINew_EnableCRT2(struct vb_device_info *pVBInfo) @@ -6158,10 +6414,12 @@ static void XGI_EnableBridge(struct xgifb_video_info *xgifb_info, if (pVBInfo->SetFlag & EnableChA) { /* Power on */ xgifb_reg_set(pVBInfo->Part1Port, 0x1E, 0x20); - } else if (pVBInfo->VBInfo & SetCRT2ToDualEdge) { - /* Power on */ - xgifb_reg_set(pVBInfo->Part1Port, - 0x1E, 0x20); + } else { + if (pVBInfo->VBInfo & SetCRT2ToDualEdge) { + /* Power on */ + xgifb_reg_set(pVBInfo->Part1Port, + 0x1E, 0x20); + } } } @@ -6349,6 +6607,7 @@ unsigned char XGISetModeNew(struct xgifb_video_info *xgifb_info, struct vb_device_info *pVBInfo = &VBINF; pVBInfo->BaseAddr = xgifb_info->vga_base; pVBInfo->IF_DEF_LVDS = 0; + pVBInfo->IF_DEF_LCDA = 1; if (HwDeviceExtension->jChipType >= XG20) { pVBInfo->IF_DEF_YPbPr = 0; @@ -6419,14 +6678,16 @@ unsigned char XGISetModeNew(struct xgifb_video_info *xgifb_info, XGI_SetLCDAGroup(ModeNo, ModeIdIndex, HwDeviceExtension, pVBInfo); } - } else if (!(pVBInfo->VBInfo & SwitchCRT2)) { - XGI_SetCRT1Group(xgifb_info, - HwDeviceExtension, ModeNo, - ModeIdIndex, pVBInfo); - if (pVBInfo->VBInfo & XGI_SetCRT2ToLCDA) { - XGI_SetLCDAGroup(ModeNo, ModeIdIndex, - HwDeviceExtension, - pVBInfo); + } else { + if (!(pVBInfo->VBInfo & SwitchCRT2)) { + XGI_SetCRT1Group(xgifb_info, + HwDeviceExtension, ModeNo, + ModeIdIndex, pVBInfo); + if (pVBInfo->VBInfo & XGI_SetCRT2ToLCDA) { + XGI_SetLCDAGroup(ModeNo, ModeIdIndex, + HwDeviceExtension, + pVBInfo); + } } } diff --git a/trunk/drivers/staging/xgifb/vb_struct.h b/trunk/drivers/staging/xgifb/vb_struct.h index 70158c2c68af..22c8eb9810d6 100644 --- a/trunk/drivers/staging/xgifb/vb_struct.h +++ b/trunk/drivers/staging/xgifb/vb_struct.h @@ -43,6 +43,13 @@ struct XGI_LCDDesStruct { unsigned short LCDVRS; }; +struct XGI_LCDDataTablStruct { + unsigned char PANELID; + unsigned short MASK; + unsigned short CAP; + unsigned short DATAPTR; +}; + struct XGI330_LCDDataDesStruct2 { unsigned short LCDHDES; unsigned short LCDHRS; @@ -52,6 +59,19 @@ struct XGI330_LCDDataDesStruct2 { unsigned short LCDVSync; }; + +struct XGI330_TVDataStruct { + unsigned short RVBHCMAX; + unsigned short RVBHCFACT; + unsigned short VGAHT; + unsigned short VGAVT; + unsigned short TVHDE; + unsigned short TVVDE; + unsigned short RVBHRS; + unsigned char FlickerMode; + unsigned short HALFRVBHRS; +}; + struct XGI330_LCDDataTablStruct { unsigned char PANELID; unsigned short MASK; @@ -62,7 +82,7 @@ struct XGI330_LCDDataTablStruct { struct XGI330_TVDataTablStruct { unsigned short MASK; unsigned short CAP; - struct SiS_TVData const *DATAPTR; + unsigned short DATAPTR; }; @@ -117,10 +137,10 @@ struct XGI21_LVDSCapStruct { unsigned short LVDSVSYNC; unsigned char VCLKData1; unsigned char VCLKData2; - unsigned char PSC_S1; /* Duration between CPL on and signal on */ - unsigned char PSC_S2; /* Duration signal on and Vdd on */ - unsigned char PSC_S3; /* Duration between CPL off and signal off */ - unsigned char PSC_S4; /* Duration signal off and Vdd off */ + unsigned char PSC_S1; + unsigned char PSC_S2; + unsigned char PSC_S3; + unsigned char PSC_S4; unsigned char PSC_S5; }; @@ -135,6 +155,7 @@ struct XGI301C_Tap4TimingStruct { }; struct vb_device_info { + unsigned char ISXPDOS; unsigned long P3c4, P3d4, P3c0, P3ce, P3c2, P3cc; unsigned long P3ca, P3c6, P3c7, P3c8, P3c9, P3da; unsigned long Part0Port, Part1Port, Part2Port; @@ -147,10 +168,12 @@ struct vb_device_info { unsigned short ModeType; unsigned short IF_DEF_LVDS, IF_DEF_TRUMPION, IF_DEF_DSTN; unsigned short IF_DEF_CRT2Monitor; - unsigned short IF_DEF_YPbPr; + unsigned short IF_DEF_LCDA, IF_DEF_YPbPr; + unsigned short IF_DEF_ExpLink; unsigned short IF_DEF_HiVision; unsigned short LCDResInfo, LCDTypeInfo, VBType;/*301b*/ unsigned short VBInfo, TVInfo, LCDInfo; + unsigned short VBExtInfo;/*301lv*/ unsigned short SetFlag; unsigned short NewFlickerMode; unsigned short SelectCRT2Rate; @@ -174,6 +197,20 @@ struct vb_device_info { struct SiS_MCLKData *MCLKData; struct XGI_ECLKDataStruct *ECLKData; + unsigned char *NTSCTiming; + unsigned char *PALTiming; + unsigned char *HiTVExtTiming; + unsigned char *HiTVSt1Timing; + unsigned char *HiTVSt2Timing; + unsigned char *HiTVTextTiming; + unsigned char *YPbPr750pTiming; + unsigned char *YPbPr525pTiming; + unsigned char *YPbPr525iTiming; + unsigned char *HiTVGroup3Data; + unsigned char *HiTVGroup3Simu; + unsigned char *HiTVGroup3Text; + unsigned char *Ren525pGroup3; + unsigned char *Ren750pGroup3; unsigned char *ScreenOffset; unsigned char *pXGINew_DRAMTypeDefinition; unsigned char XGINew_CR97; diff --git a/trunk/drivers/staging/xgifb/vb_table.h b/trunk/drivers/staging/xgifb/vb_table.h index 180aae042cea..1c168461411d 100644 --- a/trunk/drivers/staging/xgifb/vb_table.h +++ b/trunk/drivers/staging/xgifb/vb_table.h @@ -403,6 +403,13 @@ static struct XGI_CRT1TableStruct XGI_CRT1Table[] = { 0x03, 0xDE, 0xC0, 0x84, 0xBF, 0x04, 0x90} } /* 0x47 */ }; +static unsigned char XGI_CH7017LV1024x768[] = { + 0x60, 0x02, 0x00, 0x07, 0x40, 0xED, + 0xA3, 0xC8, 0xC7, 0xAC, 0xE0, 0x02}; +static unsigned char XGI_CH7017LV1400x1050[] = { + 0x60, 0x03, 0x11, 0x00, 0x40, 0xE3, + 0xAD, 0xDB, 0xF6, 0xAC, 0xE0, 0x02}; + /*add for new UNIVGABIOS*/ static struct SiS_LCDData XGI_StLCD1024x768Data[] = { {62, 25, 800, 546, 1344, 806}, @@ -518,7 +525,18 @@ static struct SiS_LCDData XGI_StLCD1600x1200Data[] = { {1, 1, 2160, 1250, 2160, 1250} /* 09 (1600x1200) */ }; -#define XGI_CetLCD1400x1050Data XGI_CetLCD1280x1024Data +static struct SiS_LCDData XGI_CetLCD1400x1050Data[] = { + {1, 1, 1688, 1066, 1688, 1066}, /* 00 (320x200,320x400, + 640x200,640x400) */ + {1, 1, 1688, 1066, 1688, 1066}, /* 01 (320x350,640x350) */ + {1, 1, 1688, 1066, 1688, 1066}, /* 02 (360x400,720x400) */ + {1, 1, 1688, 1066, 1688, 1066}, /* 03 (720x350) */ + {1, 1, 1688, 1066, 1688, 1066}, /* 04 (640x480x60Hz) */ + {1, 1, 1688, 1066, 1688, 1066}, /* 05 (800x600x60Hz) */ + {1, 1, 1688, 1066, 1688, 1066}, /* 06 (1024x768x60Hz) */ + {1, 1, 1688, 1066, 1688, 1066}, /* 07 (1280x1024x60Hz) */ + {1, 1, 1688, 1066, 1688, 1066} /* 08 (1400x1050x60Hz) */ +}; static struct SiS_LCDData XGI_NoScalingData[] = { {1, 1, 800, 449, 800, 449}, @@ -565,7 +583,17 @@ static struct SiS_LCDData xgifb_lcd_1280x1024x75[] = { {1, 1, 1688, 1066, 1688, 1066} /* ; 07 (1280x1024x75Hz) */ }; -#define XGI_CetLCD1280x1024x75Data XGI_CetLCD1280x1024Data +static struct SiS_LCDData XGI_CetLCD1280x1024x75Data[] = { + {1, 1, 1688, 1066, 1688, 1066}, /* ; 00 (320x200,320x400, + 640x200,640x400) */ + {1, 1, 1688, 1066, 1688, 1066}, /* ; 01 (320x350,640x350) */ + {1, 1, 1688, 1066, 1688, 1066}, /* ; 02 (360x400,720x400) */ + {1, 1, 1688, 1066, 1688, 1066}, /* ; 03 (720x350) */ + {1, 1, 1688, 1066, 1688, 1066}, /* ; 04 (640x480x75Hz) */ + {1, 1, 1688, 1066, 1688, 1066}, /* ; 05 (800x600x75Hz) */ + {1, 1, 1688, 1066, 1688, 1066}, /* ; 06 (1024x768x75Hz) */ + {1, 1, 1688, 1066, 1688, 1066} /* ; 07 (1280x1024x75Hz) */ +}; static struct SiS_LCDData XGI_NoScalingDatax75[] = { {1, 1, 800, 449, 800, 449}, /* ; 00 (320x200, 320x400, @@ -875,7 +903,7 @@ static struct XGI330_LCDDataDesStruct2 XGI_NoScalingDesDatax75[] = { {9, 1337, 0, 771, 112, 6} /* ; 0A (1280x768x60Hz) */ }; -static const struct SiS_TVData XGI_StPALData[] = { +static struct XGI330_TVDataStruct XGI_StPALData[] = { {1, 1, 864, 525, 1270, 400, 100, 0, 760}, {1, 1, 864, 525, 1270, 350, 100, 0, 760}, {1, 1, 864, 525, 1270, 400, 0, 0, 720}, @@ -884,7 +912,7 @@ static const struct SiS_TVData XGI_StPALData[] = { {1, 1, 864, 525, 1270, 600, 50, 0, 0} }; -static const struct SiS_TVData XGI_ExtPALData[] = { +static struct XGI330_TVDataStruct XGI_ExtPALData[] = { {2, 1, 1080, 463, 1270, 500, 50, 0, 50}, {15, 7, 1152, 413, 1270, 500, 50, 0, 50}, {2, 1, 1080, 463, 1270, 500, 50, 0, 50}, @@ -895,7 +923,7 @@ static const struct SiS_TVData XGI_ExtPALData[] = { {3, 2, 1080, 619, 1270, 540, 438, 0, 438} }; -static const struct SiS_TVData XGI_StNTSCData[] = { +static struct XGI330_TVDataStruct XGI_StNTSCData[] = { {1, 1, 858, 525, 1270, 400, 50, 0, 760}, {1, 1, 858, 525, 1270, 350, 50, 0, 640}, {1, 1, 858, 525, 1270, 400, 0, 0, 720}, @@ -903,7 +931,7 @@ static const struct SiS_TVData XGI_StNTSCData[] = { {1, 1, 858, 525, 1270, 480, 0, 0, 760} }; -static const struct SiS_TVData XGI_ExtNTSCData[] = { +static struct XGI330_TVDataStruct XGI_ExtNTSCData[] = { {9, 5, 1001, 453, 1270, 420, 171, 0, 171}, {12, 5, 858, 403, 1270, 420, 171, 0, 171}, {9, 5, 1001, 453, 1270, 420, 171, 0, 171}, @@ -915,7 +943,7 @@ static const struct SiS_TVData XGI_ExtNTSCData[] = { {3, 2, 1001, 533, 1270, 420, 0, 0, 0} }; -static const struct SiS_TVData XGI_St1HiTVData[] = { +static struct XGI330_TVDataStruct XGI_St1HiTVData[] = { {1, 1, 892, 563, 690, 800, 0, 0, 0}, /* 00 (320x200,320x400, 640x200,640x400) */ {1, 1, 892, 563, 690, 700, 0, 0, 0}, /* 01 (320x350,640x350) */ @@ -925,7 +953,7 @@ static const struct SiS_TVData XGI_St1HiTVData[] = { {8, 5, 1050, 683, 1648, 960, 0x150, 1, 0} /* 05 (400x300,800x600) */ }; -static const struct SiS_TVData XGI_St2HiTVData[] = { +static struct XGI330_TVDataStruct XGI_St2HiTVData[] = { {3, 1, 840, 483, 1648, 960, 0x032, 0, 0}, /* 00 (320x200,320x400, 640x200,640x400) */ {1, 1, 892, 563, 690, 700, 0, 0, 0}, /* 01 (320x350,640x350) */ @@ -935,7 +963,7 @@ static const struct SiS_TVData XGI_St2HiTVData[] = { {8, 5, 1050, 683, 1648, 960, 0x17C, 1, 0} /* 05 (400x300,800x600) */ }; -static const struct SiS_TVData XGI_ExtHiTVData[] = { +static struct XGI330_TVDataStruct XGI_ExtHiTVData[] = { {6, 1, 840, 563, 1632, 960, 0, 0, 0}, /* 00 (320x200,320x400, 640x200,640x400) */ {3, 1, 960, 563, 1632, 960, 0, 0, 0}, /* 01 (320x350,640x350) */ @@ -950,7 +978,7 @@ static const struct SiS_TVData XGI_ExtHiTVData[] = { {8, 5, 1750, 803, 1648, 960, 0x128, 0, 0} /* 0A (1280x720) */ }; -static const struct SiS_TVData XGI_ExtYPbPr525iData[] = { +static struct XGI330_TVDataStruct XGI_ExtYPbPr525iData[] = { { 9, 5, 1001, 453, 1270, 420, 171, 0, 171}, { 12, 5, 858, 403, 1270, 420, 171, 0, 171}, { 9, 5, 1001, 453, 1270, 420, 171, 0, 171}, @@ -962,7 +990,7 @@ static const struct SiS_TVData XGI_ExtYPbPr525iData[] = { { 3, 2, 1001, 533, 1250, 420, 0, 0, 0} }; -static const struct SiS_TVData XGI_StYPbPr525iData[] = { +static struct XGI330_TVDataStruct XGI_StYPbPr525iData[] = { {1, 1, 858, 525, 1270, 400, 50, 0, 760}, {1, 1, 858, 525, 1270, 350, 50, 0, 640}, {1, 1, 858, 525, 1270, 400, 0, 0, 720}, @@ -970,7 +998,7 @@ static const struct SiS_TVData XGI_StYPbPr525iData[] = { {1, 1, 858, 525, 1270, 480, 0, 0, 760}, }; -static const struct SiS_TVData XGI_ExtYPbPr525pData[] = { +static struct XGI330_TVDataStruct XGI_ExtYPbPr525pData[] = { { 9, 5, 1001, 453, 1270, 420, 171, 0, 171}, { 12, 5, 858, 403, 1270, 420, 171, 0, 171}, { 9, 5, 1001, 453, 1270, 420, 171, 0, 171}, @@ -982,7 +1010,7 @@ static const struct SiS_TVData XGI_ExtYPbPr525pData[] = { { 3, 2, 1001, 533, 1270, 420, 0, 0, 0} }; -static const struct SiS_TVData XGI_StYPbPr525pData[] = { +static struct XGI330_TVDataStruct XGI_StYPbPr525pData[] = { {1, 1, 1716, 525, 1270, 400, 50, 0, 760}, {1, 1, 1716, 525, 1270, 350, 50, 0, 640}, {1, 1, 1716, 525, 1270, 400, 0, 0, 720}, @@ -990,7 +1018,7 @@ static const struct SiS_TVData XGI_StYPbPr525pData[] = { {1, 1, 1716, 525, 1270, 480, 0, 0, 760}, }; -static const struct SiS_TVData XGI_ExtYPbPr750pData[] = { +static struct XGI330_TVDataStruct XGI_ExtYPbPr750pData[] = { { 3, 1, 935, 470, 1130, 680, 50, 0, 0}, /* 00 (320x200,320x400, 640x200,640x400) */ {24, 7, 935, 420, 1130, 680, 50, 0, 0}, /* 01 (320x350,640x350) */ @@ -1005,7 +1033,7 @@ static const struct SiS_TVData XGI_ExtYPbPr750pData[] = { {10, 9, 1320, 830, 1130, 640, 50, 0, 0} }; -static const struct SiS_TVData XGI_StYPbPr750pData[] = { +static struct XGI330_TVDataStruct XGI_StYPbPr750pData[] = { {1, 1, 1650, 750, 1280, 400, 50, 0, 760}, {1, 1, 1650, 750, 1280, 350, 50, 0, 640}, {1, 1, 1650, 750, 1280, 400, 0, 0, 720}, @@ -1013,7 +1041,7 @@ static const struct SiS_TVData XGI_StYPbPr750pData[] = { {1, 1, 1650, 750, 1280, 480, 0, 0, 760}, }; -static const unsigned char XGI330_NTSCTiming[] = { +static unsigned char XGI330_NTSCTiming[] = { 0x17, 0x1d, 0x03, 0x09, 0x05, 0x06, 0x0c, 0x0c, 0x94, 0x49, 0x01, 0x0a, 0x06, 0x0d, 0x04, 0x0a, 0x06, 0x14, 0x0d, 0x04, 0x0a, 0x00, 0x85, 0x1b, @@ -1024,7 +1052,7 @@ static const unsigned char XGI330_NTSCTiming[] = { 0x00, 0x40, 0x44, 0x00, 0xdb, 0x02, 0x3b, 0x00 }; -static const unsigned char XGI330_PALTiming[] = { +static unsigned char XGI330_PALTiming[] = { 0x21, 0x5A, 0x35, 0x6e, 0x04, 0x38, 0x3d, 0x70, 0x94, 0x49, 0x01, 0x12, 0x06, 0x3e, 0x35, 0x6d, 0x06, 0x14, 0x3e, 0x35, 0x6d, 0x00, 0x45, 0x2b, @@ -1035,7 +1063,7 @@ static const unsigned char XGI330_PALTiming[] = { 0x00, 0x40, 0x3e, 0x00, 0xe1, 0x02, 0x28, 0x00 }; -static const unsigned char XGI330_HiTVExtTiming[] = { +static unsigned char XGI330_HiTVExtTiming[] = { 0x2D, 0x60, 0x2C, 0x5F, 0x08, 0x31, 0x3A, 0x64, 0x28, 0x02, 0x01, 0x3D, 0x06, 0x3E, 0x35, 0x6D, 0x06, 0x14, 0x3E, 0x35, 0x6D, 0x00, 0xC5, 0x3F, @@ -1047,7 +1075,7 @@ static const unsigned char XGI330_HiTVExtTiming[] = { 0x27, 0x00, 0xfc, 0xff, 0x6a, 0x00 }; -static const unsigned char XGI330_HiTVSt1Timing[] = { +static unsigned char XGI330_HiTVSt1Timing[] = { 0x32, 0x65, 0x2C, 0x5F, 0x08, 0x31, 0x3A, 0x65, 0x28, 0x02, 0x01, 0x3D, 0x06, 0x3E, 0x35, 0x6D, 0x06, 0x14, 0x3E, 0x35, 0x6D, 0x00, 0xC5, 0x3F, @@ -1059,7 +1087,7 @@ static const unsigned char XGI330_HiTVSt1Timing[] = { 0x0E, 0x00, 0xfc, 0xff, 0x2d, 0x00 }; -static const unsigned char XGI330_HiTVSt2Timing[] = { +static unsigned char XGI330_HiTVSt2Timing[] = { 0x32, 0x65, 0x2C, 0x5F, 0x08, 0x31, 0x3A, 0x64, 0x28, 0x02, 0x01, 0x3D, 0x06, 0x3E, 0x35, 0x6D, 0x06, 0x14, 0x3E, 0x35, 0x6D, 0x00, 0xC5, 0x3F, @@ -1071,7 +1099,7 @@ static const unsigned char XGI330_HiTVSt2Timing[] = { 0x27, 0x00, 0xFC, 0xff, 0x6a, 0x00 }; -static const unsigned char XGI330_HiTVTextTiming[] = { +static unsigned char XGI330_HiTVTextTiming[] = { 0x32, 0x65, 0x2C, 0x5F, 0x08, 0x31, 0x3A, 0x65, 0x28, 0x02, 0x01, 0x3D, 0x06, 0x3E, 0x35, 0x6D, 0x06, 0x14, 0x3E, 0x35, 0x6D, 0x00, 0xC5, 0x3F, @@ -1083,7 +1111,7 @@ static const unsigned char XGI330_HiTVTextTiming[] = { 0x11, 0x00, 0xFC, 0xFF, 0x32, 0x00 }; -static const unsigned char XGI330_YPbPr750pTiming[] = { +static unsigned char XGI330_YPbPr750pTiming[] = { 0x30, 0x1d, 0xe8, 0x09, 0x09, 0xed, 0x0c, 0x0c, 0x98, 0x0a, 0x01, 0x0c, 0x06, 0x0d, 0x04, 0x0a, 0x06, 0x14, 0x0d, 0x04, 0x0a, 0x00, 0x85, 0x3f, @@ -1095,7 +1123,7 @@ static const unsigned char XGI330_YPbPr750pTiming[] = { 0x11, 0x00, 0xfc, 0xff, 0x32, 0x00 }; -static const unsigned char XGI330_YPbPr525pTiming[] = { +static unsigned char XGI330_YPbPr525pTiming[] = { 0x3E, 0x11, 0x06, 0x09, 0x0b, 0x0c, 0x0c, 0x0c, 0x98, 0x0a, 0x01, 0x0d, 0x06, 0x0d, 0x04, 0x0a, 0x06, 0x14, 0x0d, 0x04, 0x0a, 0x00, 0x85, 0x3f, @@ -1107,7 +1135,7 @@ static const unsigned char XGI330_YPbPr525pTiming[] = { 0x11, 0x00, 0xFC, 0xFF, 0x32, 0x00 }; -static const unsigned char XGI330_YPbPr525iTiming[] = { +static unsigned char XGI330_YPbPr525iTiming[] = { 0x1B, 0x21, 0x03, 0x09, 0x05, 0x06, 0x0C, 0x0C, 0x94, 0x49, 0x01, 0x0A, 0x06, 0x0D, 0x04, 0x0A, 0x06, 0x14, 0x0D, 0x04, 0x0A, 0x00, 0x85, 0x1B, @@ -1119,7 +1147,7 @@ static const unsigned char XGI330_YPbPr525iTiming[] = { 0x44, 0x00, 0xDB, 0x02, 0x3B, 0x00 }; -static const unsigned char XGI330_HiTVGroup3Data[] = { +static unsigned char XGI330_HiTVGroup3Data[] = { 0x00, 0x1A, 0x22, 0x63, 0x62, 0x22, 0x08, 0x5F, 0x05, 0x21, 0xB2, 0xB2, 0x55, 0x77, 0x2A, 0xA6, 0x25, 0x2F, 0x47, 0xFA, 0xC8, 0xFF, 0x8E, 0x20, @@ -1130,7 +1158,7 @@ static const unsigned char XGI330_HiTVGroup3Data[] = { 0x18, 0x05, 0x18, 0x05, 0x4C, 0xA8, 0x01 }; -static const unsigned char XGI330_HiTVGroup3Simu[] = { +static unsigned char XGI330_HiTVGroup3Simu[] = { 0x00, 0x1A, 0x22, 0x63, 0x62, 0x22, 0x08, 0x95, 0xDB, 0x20, 0xB8, 0xB8, 0x55, 0x47, 0x2A, 0xA6, 0x25, 0x2F, 0x47, 0xFA, 0xC8, 0xFF, 0x8E, 0x20, @@ -1141,7 +1169,7 @@ static const unsigned char XGI330_HiTVGroup3Simu[] = { 0x18, 0x05, 0x18, 0x05, 0x4C, 0xA8, 0x01 }; -static const unsigned char XGI330_HiTVGroup3Text[] = { +static unsigned char XGI330_HiTVGroup3Text[] = { 0x00, 0x1A, 0x22, 0x63, 0x62, 0x22, 0x08, 0xA7, 0xF5, 0x20, 0xCE, 0xCE, 0x55, 0x47, 0x2A, 0xA6, 0x25, 0x2F, 0x47, 0xFA, 0xC8, 0xFF, 0x8E, 0x20, @@ -1152,7 +1180,7 @@ static const unsigned char XGI330_HiTVGroup3Text[] = { 0x18, 0x05, 0x18, 0x05, 0x4C, 0xA8, 0x01 }; -static const unsigned char XGI330_Ren525pGroup3[] = { +static unsigned char XGI330_Ren525pGroup3[] = { 0x00, 0x14, 0x15, 0x25, 0x55, 0x15, 0x0b, 0x13, 0xB1, 0x41, 0x62, 0x62, 0xFF, 0xF4, 0x45, 0xa6, 0x25, 0x2F, 0x67, 0xF6, 0xbf, 0xFF, 0x8E, 0x20, @@ -1163,7 +1191,7 @@ static const unsigned char XGI330_Ren525pGroup3[] = { 0x1a, 0x1F, 0x25, 0x2a, 0x4C, 0xAA, 0x01 }; -static const unsigned char XGI330_Ren750pGroup3[] = { +static unsigned char XGI330_Ren750pGroup3[] = { 0x00, 0x14, 0x15, 0x25, 0x55, 0x15, 0x0b, 0x7a, 0x54, 0x41, 0xE7, 0xE7, 0xFF, 0xF4, 0x45, 0xa6, 0x25, 0x2F, 0x67, 0xF6, 0xbf, 0xFF, 0x8E, 0x20, @@ -1208,7 +1236,17 @@ static struct SiS_LVDSData XGI_LVDS1280x1024Data_1[] = { {1688, 1066, 1688, 1066} }; -#define XGI_LVDS1280x1024Data_2 XGI_LVDS1024x768Data_2 +static struct SiS_LVDSData XGI_LVDS1280x1024Data_2[] = { + {1344, 806, 1344, 806}, + {1344, 806, 1344, 806}, + {1344, 806, 1344, 806}, + {1344, 806, 1344, 806}, + {1344, 806, 1344, 806}, + {1344, 806, 1344, 806}, + {1344, 806, 1344, 806}, + {800, 449, 1280, 801}, + {800, 525, 1280, 813} +}; static struct SiS_LVDSData XGI_LVDS1400x1050Data_1[] = { {928, 416, 1688, 1066}, @@ -1494,6 +1532,42 @@ static struct XGI330_LCDDataDesStruct2 XGI_LVDSNoScalingDesDatax75[] = { {0, 1328, 0, 771, 112, 6} /* ; 0A (1280x768x75Hz) */ }; +static struct SiS_LVDSData XGI_CHTVUNTSCData[] = { + { 840, 600, 840, 600}, + { 840, 600, 840, 600}, + { 840, 600, 840, 600}, + { 840, 600, 840, 600}, + { 784, 600, 784, 600}, + {1064, 750, 1064, 750} +}; + +static struct SiS_LVDSData XGI_CHTVONTSCData[] = { + { 840, 525, 840, 525}, + { 840, 525, 840, 525}, + { 840, 525, 840, 525}, + { 840, 525, 840, 525}, + { 784, 525, 784, 525}, + {1040, 700, 1040, 700} +}; + +static struct SiS_LVDSData XGI_CHTVUPALData[] = { + {1008, 625, 1008, 625}, + {1008, 625, 1008, 625}, + {1008, 625, 1008, 625}, + {1008, 625, 1008, 625}, + { 840, 750, 840, 750}, + { 936, 836, 936, 836} +}; + +static struct SiS_LVDSData XGI_CHTVOPALData[] = { + {1008, 625, 1008, 625}, + {1008, 625, 1008, 625}, + {1008, 625, 1008, 625}, + {1008, 625, 1008, 625}, + {840, 625, 840, 625}, + {960, 750, 960, 750} +}; + /* CR00,CR02,CR03,CR04,CR05,SR0B,SR0C,SR0E */ static struct XGI_LVDSCRT1HDataStruct XGI_LVDSCRT11024x768_1_H[] = { { {0x4B, 0x27, 0x8F, 0x32, 0x1B, 0x00, 0x45, 0x00} }, /* 00 (320x) */ @@ -1859,21 +1933,49 @@ static struct XGI330_LCDDataTablStruct XGI_EPLLCDDesDataPtr[] = { {0xFF, 0x0000, 0x0000, 0} }; -static const struct XGI330_TVDataTablStruct XGI_TVDataTable[] = { - {0x09E1, 0x0001, XGI_ExtPALData}, - {0x09E1, 0x0000, XGI_ExtNTSCData}, - {0x09E1, 0x0801, XGI_StPALData}, - {0x09E1, 0x0800, XGI_StNTSCData}, - {0x49E0, 0x0100, XGI_ExtHiTVData}, - {0x49E0, 0x4100, XGI_St2HiTVData}, - {0x49E0, 0x4900, XGI_St1HiTVData}, - {0x09E0, 0x0020, XGI_ExtYPbPr525iData}, - {0x09E0, 0x0040, XGI_ExtYPbPr525pData}, - {0x09E0, 0x0080, XGI_ExtYPbPr750pData}, - {0x09E0, 0x0820, XGI_StYPbPr525iData}, - {0x09E0, 0x0840, XGI_StYPbPr525pData}, - {0x09E0, 0x0880, XGI_StYPbPr750pData}, - {0xffff, 0x0000, XGI_ExtNTSCData}, +static struct XGI330_LCDDataTablStruct XGI_EPLCHLCDRegPtr[] = { + {Panel_1024x768, 0x0000, 0x0000, 0}, /* XGI_CH7017LV1024x768 */ + {Panel_1400x1050, 0x0000, 0x0000, 1}, /* XGI_CH7017LV1400x1050 */ + {0xFF, 0x0000, 0x0000, 0} +}; + +static struct XGI330_TVDataTablStruct XGI_TVDataTable[] = { + {0x09E1, 0x0001, 0}, /* XGI_ExtPALData */ + {0x09E1, 0x0000, 1}, /* XGI_ExtNTSCData */ + {0x09E1, 0x0801, 2}, /* XGI_StPALData */ + {0x09E1, 0x0800, 3}, /* XGI_StNTSCData */ + {0x49E0, 0x0100, 4}, /* XGI_ExtHiTVData */ + {0x49E0, 0x4100, 5}, /* XGI_St2HiTVData */ + {0x49E0, 0x4900, 13}, /* XGI_St1HiTVData */ + {0x09E0, 0x0020, 6}, /* XGI_ExtYPbPr525iData */ + {0x09E0, 0x0040, 7}, /* XGI_ExtYPbPr525pData */ + {0x09E0, 0x0080, 8}, /* XGI_ExtYPbPr750pData */ + {0x09E0, 0x0820, 9}, /* XGI_StYPbPr525iData */ + {0x09E0, 0x0840, 10}, /* XGI_StYPbPr525pData */ + {0x09E0, 0x0880, 11}, /* XGI_StYPbPr750pData */ + {0xffff, 0x0000, 12} /* END */ +}; + +/* Chrontel 7017 TV List */ +static struct XGI330_TVDataTablStruct xgifb_chrontel_tv[] = { + {0x0011, 0x0000, 0}, /* UNTSC */ + {0x0011, 0x0010, 1}, /* ONTSC */ + {0x0011, 0x0001, 2}, /* UPAL */ + {0x0011, 0x0011, 3}, /* OPAL */ + {0xFFFF, 0x0000, 4} +}; + +static unsigned short LCDLenList[] = { + LVDSCRT1Len_H, + LVDSCRT1Len_V, + LVDSDataLen, + LCDDesDataLen, + LCDDataLen, + LCDDesDataLen, + 0, + LCDDesDataLen, + LCDDesDataLen, + 0 }; /* Dual link only */ @@ -2234,7 +2336,7 @@ static struct SiS_VCLKData XGI_VCLKData[] = { {0xFF, 0x00, 0} /* End mark */ }; -static struct SiS_VBVCLKData XGI_VBVCLKData[] = { +static struct SiS_VCLKData XGI_VBVCLKData[] = { {0x1B, 0xE1, 25}, /* 00 (25.175MHz) */ {0x4E, 0xE4, 28}, /* 01 (28.322MHz) */ {0x57, 0xE4, 31}, /* 02 (31.500MHz) */ diff --git a/trunk/drivers/staging/zcache/tmem.c b/trunk/drivers/staging/zcache/tmem.c index 56c8e606ad1c..eaa90213457b 100644 --- a/trunk/drivers/staging/zcache/tmem.c +++ b/trunk/drivers/staging/zcache/tmem.c @@ -3,7 +3,7 @@ * * Copyright (c) 2009-2011, Dan Magenheimer, Oracle Corp. * - * The primary purpose of Transcendent Memory ("tmem") is to map object-oriented + * The primary purpose of Transcedent Memory ("tmem") is to map object-oriented * "handles" (triples containing a pool id, and object id, and an index), to * pages in a page-accessible memory (PAM). Tmem references the PAM pages via * an abstract "pampd" (PAM page-descriptor), which can be operated on by a diff --git a/trunk/drivers/staging/zcache/zcache-main.c b/trunk/drivers/staging/zcache/zcache-main.c index 52b43b7b83d7..c214977b4ab4 100644 --- a/trunk/drivers/staging/zcache/zcache-main.c +++ b/trunk/drivers/staging/zcache/zcache-main.c @@ -1251,12 +1251,13 @@ static int zcache_pampd_get_data_and_free(char *data, size_t *bufsize, bool raw, void *pampd, struct tmem_pool *pool, struct tmem_oid *oid, uint32_t index) { + int ret = 0; + BUG_ON(!is_ephemeral(pool)); - if (zbud_decompress((struct page *)(data), pampd) < 0) - return -EINVAL; + zbud_decompress((struct page *)(data), pampd); zbud_free_and_delist((struct zbud_hdr *)pampd); atomic_dec(&zcache_curr_eph_pampd_count); - return 0; + return ret; } /* diff --git a/trunk/drivers/staging/zsmalloc/zsmalloc-main.c b/trunk/drivers/staging/zsmalloc/zsmalloc-main.c index 09a9d35d436f..8b0bcb626a7f 100644 --- a/trunk/drivers/staging/zsmalloc/zsmalloc-main.c +++ b/trunk/drivers/staging/zsmalloc/zsmalloc-main.c @@ -75,140 +75,9 @@ #include #include #include -#include -#include -#include #include "zsmalloc.h" - -/* - * This must be power of 2 and greater than of equal to sizeof(link_free). - * These two conditions ensure that any 'struct link_free' itself doesn't - * span more than 1 page which avoids complex case of mapping 2 pages simply - * to restore link_free pointer values. - */ -#define ZS_ALIGN 8 - -/* - * A single 'zspage' is composed of up to 2^N discontiguous 0-order (single) - * pages. ZS_MAX_ZSPAGE_ORDER defines upper limit on N. - */ -#define ZS_MAX_ZSPAGE_ORDER 2 -#define ZS_MAX_PAGES_PER_ZSPAGE (_AC(1, UL) << ZS_MAX_ZSPAGE_ORDER) - -/* - * Object location (, ) is encoded as - * as single (void *) handle value. - * - * Note that object index is relative to system - * page it is stored in, so for each sub-page belonging - * to a zspage, obj_idx starts with 0. - * - * This is made more complicated by various memory models and PAE. - */ - -#ifndef MAX_PHYSMEM_BITS -#ifdef CONFIG_HIGHMEM64G -#define MAX_PHYSMEM_BITS 36 -#else /* !CONFIG_HIGHMEM64G */ -/* - * If this definition of MAX_PHYSMEM_BITS is used, OBJ_INDEX_BITS will just - * be PAGE_SHIFT - */ -#define MAX_PHYSMEM_BITS BITS_PER_LONG -#endif -#endif -#define _PFN_BITS (MAX_PHYSMEM_BITS - PAGE_SHIFT) -#define OBJ_INDEX_BITS (BITS_PER_LONG - _PFN_BITS) -#define OBJ_INDEX_MASK ((_AC(1, UL) << OBJ_INDEX_BITS) - 1) - -#define MAX(a, b) ((a) >= (b) ? (a) : (b)) -/* ZS_MIN_ALLOC_SIZE must be multiple of ZS_ALIGN */ -#define ZS_MIN_ALLOC_SIZE \ - MAX(32, (ZS_MAX_PAGES_PER_ZSPAGE << PAGE_SHIFT >> OBJ_INDEX_BITS)) -#define ZS_MAX_ALLOC_SIZE PAGE_SIZE - -/* - * On systems with 4K page size, this gives 254 size classes! There is a - * trader-off here: - * - Large number of size classes is potentially wasteful as free page are - * spread across these classes - * - Small number of size classes causes large internal fragmentation - * - Probably its better to use specific size classes (empirically - * determined). NOTE: all those class sizes must be set as multiple of - * ZS_ALIGN to make sure link_free itself never has to span 2 pages. - * - * ZS_MIN_ALLOC_SIZE and ZS_SIZE_CLASS_DELTA must be multiple of ZS_ALIGN - * (reason above) - */ -#define ZS_SIZE_CLASS_DELTA 16 -#define ZS_SIZE_CLASSES ((ZS_MAX_ALLOC_SIZE - ZS_MIN_ALLOC_SIZE) / \ - ZS_SIZE_CLASS_DELTA + 1) - -/* - * We do not maintain any list for completely empty or full pages - */ -enum fullness_group { - ZS_ALMOST_FULL, - ZS_ALMOST_EMPTY, - _ZS_NR_FULLNESS_GROUPS, - - ZS_EMPTY, - ZS_FULL -}; - -/* - * We assign a page to ZS_ALMOST_EMPTY fullness group when: - * n <= N / f, where - * n = number of allocated objects - * N = total number of objects zspage can store - * f = 1/fullness_threshold_frac - * - * Similarly, we assign zspage to: - * ZS_ALMOST_FULL when n > N / f - * ZS_EMPTY when n == 0 - * ZS_FULL when n == N - * - * (see: fix_fullness_group()) - */ -static const int fullness_threshold_frac = 4; - -struct size_class { - /* - * Size of objects stored in this class. Must be multiple - * of ZS_ALIGN. - */ - int size; - unsigned int index; - - /* Number of PAGE_SIZE sized pages to combine to form a 'zspage' */ - int pages_per_zspage; - - spinlock_t lock; - - /* stats */ - u64 pages_allocated; - - struct page *fullness_list[_ZS_NR_FULLNESS_GROUPS]; -}; - -/* - * Placed within free objects to form a singly linked list. - * For every zspage, first_page->freelist gives head of this list. - * - * This must be power of 2 and less than or equal to ZS_ALIGN - */ -struct link_free { - /* Handle of next free chunk (encodes ) */ - void *next; -}; - -struct zs_pool { - struct size_class size_class[ZS_SIZE_CLASSES]; - - gfp_t flags; /* allocation flags used when growing pool */ - const char *name; -}; +#include "zsmalloc_int.h" /* * A zspage's class index and fullness group @@ -219,30 +88,6 @@ struct zs_pool { #define CLASS_IDX_MASK ((1 << CLASS_IDX_BITS) - 1) #define FULLNESS_MASK ((1 << FULLNESS_BITS) - 1) -/* - * By default, zsmalloc uses a copy-based object mapping method to access - * allocations that span two pages. However, if a particular architecture - * 1) Implements local_flush_tlb_kernel_range() and 2) Performs VM mapping - * faster than copying, then it should be added here so that - * USE_PGTABLE_MAPPING is defined. This causes zsmalloc to use page table - * mapping rather than copying - * for object mapping. -*/ -#if defined(CONFIG_ARM) -#define USE_PGTABLE_MAPPING -#endif - -struct mapping_area { -#ifdef USE_PGTABLE_MAPPING - struct vm_struct *vm; /* vm area for mapping object that span pages */ -#else - char *vm_buf; /* copy buffer for objects that span pages */ -#endif - char *vm_addr; /* address of kmap_atomic()'ed pages */ - enum zs_mapmode vm_mm; /* mapping mode */ -}; - - /* per-cpu VM mapping areas for zspage accesses that cross page boundaries */ static DEFINE_PER_CPU(struct mapping_area, zs_map_area); @@ -625,83 +470,16 @@ static struct page *find_get_zspage(struct size_class *class) return page; } -#ifdef USE_PGTABLE_MAPPING -static inline int __zs_cpu_up(struct mapping_area *area) -{ - /* - * Make sure we don't leak memory if a cpu UP notification - * and zs_init() race and both call zs_cpu_up() on the same cpu - */ - if (area->vm) - return 0; - area->vm = alloc_vm_area(PAGE_SIZE * 2, NULL); - if (!area->vm) - return -ENOMEM; - return 0; -} - -static inline void __zs_cpu_down(struct mapping_area *area) -{ - if (area->vm) - free_vm_area(area->vm); - area->vm = NULL; -} - -static inline void *__zs_map_object(struct mapping_area *area, - struct page *pages[2], int off, int size) -{ - BUG_ON(map_vm_area(area->vm, PAGE_KERNEL, &pages)); - area->vm_addr = area->vm->addr; - return area->vm_addr + off; -} - -static inline void __zs_unmap_object(struct mapping_area *area, - struct page *pages[2], int off, int size) -{ - unsigned long addr = (unsigned long)area->vm_addr; - unsigned long end = addr + (PAGE_SIZE * 2); - - flush_cache_vunmap(addr, end); - unmap_kernel_range_noflush(addr, PAGE_SIZE * 2); - local_flush_tlb_kernel_range(addr, end); -} - -#else /* USE_PGTABLE_MAPPING */ - -static inline int __zs_cpu_up(struct mapping_area *area) -{ - /* - * Make sure we don't leak memory if a cpu UP notification - * and zs_init() race and both call zs_cpu_up() on the same cpu - */ - if (area->vm_buf) - return 0; - area->vm_buf = (char *)__get_free_page(GFP_KERNEL); - if (!area->vm_buf) - return -ENOMEM; - return 0; -} - -static inline void __zs_cpu_down(struct mapping_area *area) -{ - if (area->vm_buf) - free_page((unsigned long)area->vm_buf); - area->vm_buf = NULL; -} - -static void *__zs_map_object(struct mapping_area *area, - struct page *pages[2], int off, int size) +static void zs_copy_map_object(char *buf, struct page *firstpage, + int off, int size) { + struct page *pages[2]; int sizes[2]; void *addr; - char *buf = area->vm_buf; - /* disable page faults to match kmap_atomic() return conditions */ - pagefault_disable(); - - /* no read fastpath */ - if (area->vm_mm == ZS_MM_WO) - goto out; + pages[0] = firstpage; + pages[1] = get_next_page(firstpage); + BUG_ON(!pages[1]); sizes[0] = PAGE_SIZE - off; sizes[1] = size - sizes[0]; @@ -713,20 +491,18 @@ static void *__zs_map_object(struct mapping_area *area, addr = kmap_atomic(pages[1]); memcpy(buf + sizes[0], addr, sizes[1]); kunmap_atomic(addr); -out: - return area->vm_buf; } -static void __zs_unmap_object(struct mapping_area *area, - struct page *pages[2], int off, int size) +static void zs_copy_unmap_object(char *buf, struct page *firstpage, + int off, int size) { + struct page *pages[2]; int sizes[2]; void *addr; - char *buf = area->vm_buf; - /* no write fastpath */ - if (area->vm_mm == ZS_MM_RO) - goto out; + pages[0] = firstpage; + pages[1] = get_next_page(firstpage); + BUG_ON(!pages[1]); sizes[0] = PAGE_SIZE - off; sizes[1] = size - sizes[0]; @@ -738,31 +514,34 @@ static void __zs_unmap_object(struct mapping_area *area, addr = kmap_atomic(pages[1]); memcpy(addr, buf + sizes[0], sizes[1]); kunmap_atomic(addr); - -out: - /* enable page faults to match kunmap_atomic() return conditions */ - pagefault_enable(); } -#endif /* USE_PGTABLE_MAPPING */ - static int zs_cpu_notifier(struct notifier_block *nb, unsigned long action, void *pcpu) { - int ret, cpu = (long)pcpu; + int cpu = (long)pcpu; struct mapping_area *area; switch (action) { case CPU_UP_PREPARE: area = &per_cpu(zs_map_area, cpu); - ret = __zs_cpu_up(area); - if (ret) - return notifier_from_errno(ret); + /* + * Make sure we don't leak memory if a cpu UP notification + * and zs_init() race and both call zs_cpu_up() on the same cpu + */ + if (area->vm_buf) + return 0; + area->vm_buf = (char *)__get_free_page(GFP_KERNEL); + if (!area->vm_buf) + return -ENOMEM; + return 0; break; case CPU_DEAD: case CPU_UP_CANCELED: area = &per_cpu(zs_map_area, cpu); - __zs_cpu_down(area); + if (area->vm_buf) + free_page((unsigned long)area->vm_buf); + area->vm_buf = NULL; break; } @@ -979,36 +758,28 @@ void *zs_map_object(struct zs_pool *pool, unsigned long handle, enum fullness_group fg; struct size_class *class; struct mapping_area *area; - struct page *pages[2]; BUG_ON(!handle); - /* - * Because we use per-cpu mapping areas shared among the - * pools/users, we can't allow mapping in interrupt context - * because it can corrupt another users mappings. - */ - BUG_ON(in_interrupt()); - obj_handle_to_location(handle, &page, &obj_idx); get_zspage_mapping(get_first_page(page), &class_idx, &fg); class = &pool->size_class[class_idx]; off = obj_idx_to_offset(page, obj_idx, class->size); area = &get_cpu_var(zs_map_area); - area->vm_mm = mm; if (off + class->size <= PAGE_SIZE) { /* this object is contained entirely within a page */ area->vm_addr = kmap_atomic(page); return area->vm_addr + off; } - /* this object spans two pages */ - pages[0] = page; - pages[1] = get_next_page(page); - BUG_ON(!pages[1]); + /* disable page faults to match kmap_atomic() return conditions */ + pagefault_disable(); - return __zs_map_object(area, pages, off, class->size); + if (mm != ZS_MM_WO) + zs_copy_map_object(area->vm_buf, page, off, class->size); + area->vm_addr = NULL; + return area->vm_buf; } EXPORT_SYMBOL_GPL(zs_map_object); @@ -1022,6 +793,17 @@ void zs_unmap_object(struct zs_pool *pool, unsigned long handle) struct size_class *class; struct mapping_area *area; + area = &__get_cpu_var(zs_map_area); + /* single-page object fastpath */ + if (area->vm_addr) { + kunmap_atomic(area->vm_addr); + goto out; + } + + /* no write fastpath */ + if (area->vm_mm == ZS_MM_RO) + goto pfenable; + BUG_ON(!handle); obj_handle_to_location(handle, &page, &obj_idx); @@ -1029,18 +811,12 @@ void zs_unmap_object(struct zs_pool *pool, unsigned long handle) class = &pool->size_class[class_idx]; off = obj_idx_to_offset(page, obj_idx, class->size); - area = &__get_cpu_var(zs_map_area); - if (off + class->size <= PAGE_SIZE) - kunmap_atomic(area->vm_addr); - else { - struct page *pages[2]; - - pages[0] = page; - pages[1] = get_next_page(page); - BUG_ON(!pages[1]); + zs_copy_unmap_object(area->vm_buf, page, off, class->size); - __zs_unmap_object(area, pages, off, class->size); - } +pfenable: + /* enable page faults to match kunmap_atomic() return conditions */ + pagefault_enable(); +out: put_cpu_var(zs_map_area); } EXPORT_SYMBOL_GPL(zs_unmap_object); diff --git a/trunk/drivers/staging/zsmalloc/zsmalloc_int.h b/trunk/drivers/staging/zsmalloc/zsmalloc_int.h new file mode 100644 index 000000000000..528051767733 --- /dev/null +++ b/trunk/drivers/staging/zsmalloc/zsmalloc_int.h @@ -0,0 +1,155 @@ +/* + * zsmalloc memory allocator + * + * Copyright (C) 2011 Nitin Gupta + * + * This code is released using a dual license strategy: BSD/GPL + * You can choose the license that better fits your requirements. + * + * Released under the terms of 3-clause BSD License + * Released under the terms of GNU General Public License Version 2.0 + */ + +#ifndef _ZS_MALLOC_INT_H_ +#define _ZS_MALLOC_INT_H_ + +#include +#include +#include + +/* + * This must be power of 2 and greater than of equal to sizeof(link_free). + * These two conditions ensure that any 'struct link_free' itself doesn't + * span more than 1 page which avoids complex case of mapping 2 pages simply + * to restore link_free pointer values. + */ +#define ZS_ALIGN 8 + +/* + * A single 'zspage' is composed of up to 2^N discontiguous 0-order (single) + * pages. ZS_MAX_ZSPAGE_ORDER defines upper limit on N. + */ +#define ZS_MAX_ZSPAGE_ORDER 2 +#define ZS_MAX_PAGES_PER_ZSPAGE (_AC(1, UL) << ZS_MAX_ZSPAGE_ORDER) + +/* + * Object location (, ) is encoded as + * as single (void *) handle value. + * + * Note that object index is relative to system + * page it is stored in, so for each sub-page belonging + * to a zspage, obj_idx starts with 0. + * + * This is made more complicated by various memory models and PAE. + */ + +#ifndef MAX_PHYSMEM_BITS +#ifdef CONFIG_HIGHMEM64G +#define MAX_PHYSMEM_BITS 36 +#else /* !CONFIG_HIGHMEM64G */ +/* + * If this definition of MAX_PHYSMEM_BITS is used, OBJ_INDEX_BITS will just + * be PAGE_SHIFT + */ +#define MAX_PHYSMEM_BITS BITS_PER_LONG +#endif +#endif +#define _PFN_BITS (MAX_PHYSMEM_BITS - PAGE_SHIFT) +#define OBJ_INDEX_BITS (BITS_PER_LONG - _PFN_BITS) +#define OBJ_INDEX_MASK ((_AC(1, UL) << OBJ_INDEX_BITS) - 1) + +#define MAX(a, b) ((a) >= (b) ? (a) : (b)) +/* ZS_MIN_ALLOC_SIZE must be multiple of ZS_ALIGN */ +#define ZS_MIN_ALLOC_SIZE \ + MAX(32, (ZS_MAX_PAGES_PER_ZSPAGE << PAGE_SHIFT >> OBJ_INDEX_BITS)) +#define ZS_MAX_ALLOC_SIZE PAGE_SIZE + +/* + * On systems with 4K page size, this gives 254 size classes! There is a + * trader-off here: + * - Large number of size classes is potentially wasteful as free page are + * spread across these classes + * - Small number of size classes causes large internal fragmentation + * - Probably its better to use specific size classes (empirically + * determined). NOTE: all those class sizes must be set as multiple of + * ZS_ALIGN to make sure link_free itself never has to span 2 pages. + * + * ZS_MIN_ALLOC_SIZE and ZS_SIZE_CLASS_DELTA must be multiple of ZS_ALIGN + * (reason above) + */ +#define ZS_SIZE_CLASS_DELTA 16 +#define ZS_SIZE_CLASSES ((ZS_MAX_ALLOC_SIZE - ZS_MIN_ALLOC_SIZE) / \ + ZS_SIZE_CLASS_DELTA + 1) + +/* + * We do not maintain any list for completely empty or full pages + */ +enum fullness_group { + ZS_ALMOST_FULL, + ZS_ALMOST_EMPTY, + _ZS_NR_FULLNESS_GROUPS, + + ZS_EMPTY, + ZS_FULL +}; + +/* + * We assign a page to ZS_ALMOST_EMPTY fullness group when: + * n <= N / f, where + * n = number of allocated objects + * N = total number of objects zspage can store + * f = 1/fullness_threshold_frac + * + * Similarly, we assign zspage to: + * ZS_ALMOST_FULL when n > N / f + * ZS_EMPTY when n == 0 + * ZS_FULL when n == N + * + * (see: fix_fullness_group()) + */ +static const int fullness_threshold_frac = 4; + +struct mapping_area { + char *vm_buf; /* copy buffer for objects that span pages */ + char *vm_addr; /* address of kmap_atomic()'ed pages */ + enum zs_mapmode vm_mm; /* mapping mode */ +}; + +struct size_class { + /* + * Size of objects stored in this class. Must be multiple + * of ZS_ALIGN. + */ + int size; + unsigned int index; + + /* Number of PAGE_SIZE sized pages to combine to form a 'zspage' */ + int pages_per_zspage; + + spinlock_t lock; + + /* stats */ + u64 pages_allocated; + + struct page *fullness_list[_ZS_NR_FULLNESS_GROUPS]; +}; + +/* + * Placed within free objects to form a singly linked list. + * For every zspage, first_page->freelist gives head of this list. + * + * This must be power of 2 and less than or equal to ZS_ALIGN + */ +struct link_free { + /* Handle of next free chunk (encodes ) */ + void *next; +}; + +struct zs_pool { + struct size_class size_class[ZS_SIZE_CLASSES]; + + gfp_t flags; /* allocation flags used when growing pool */ + const char *name; +}; + +#endif diff --git a/trunk/drivers/target/iscsi/iscsi_target_login.c b/trunk/drivers/target/iscsi/iscsi_target_login.c index 6aba4395e8d8..0694d9b1bce6 100644 --- a/trunk/drivers/target/iscsi/iscsi_target_login.c +++ b/trunk/drivers/target/iscsi/iscsi_target_login.c @@ -221,7 +221,6 @@ static int iscsi_login_zero_tsih_s1( { struct iscsi_session *sess = NULL; struct iscsi_login_req *pdu = (struct iscsi_login_req *)buf; - int ret; sess = kzalloc(sizeof(struct iscsi_session), GFP_KERNEL); if (!sess) { @@ -258,17 +257,9 @@ static int iscsi_login_zero_tsih_s1( return -ENOMEM; } spin_lock(&sess_idr_lock); - ret = idr_get_new(&sess_idr, NULL, &sess->session_index); + idr_get_new(&sess_idr, NULL, &sess->session_index); spin_unlock(&sess_idr_lock); - if (ret < 0) { - pr_err("idr_get_new() for sess_idr failed\n"); - iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR, - ISCSI_LOGIN_STATUS_NO_RESOURCES); - kfree(sess); - return -ENOMEM; - } - sess->creation_time = get_jiffies_64(); spin_lock_init(&sess->session_stats_lock); /* diff --git a/trunk/drivers/target/iscsi/iscsi_target_parameters.c b/trunk/drivers/target/iscsi/iscsi_target_parameters.c index 240f7aa76ed1..0c4760fabfc0 100644 --- a/trunk/drivers/target/iscsi/iscsi_target_parameters.c +++ b/trunk/drivers/target/iscsi/iscsi_target_parameters.c @@ -662,7 +662,7 @@ int iscsi_extract_key_value(char *textbuf, char **key, char **value) { *value = strchr(textbuf, '='); if (!*value) { - pr_err("Unable to locate \"=\" separator for key," + pr_err("Unable to locate \"=\" seperator for key," " ignoring request.\n"); return -1; } @@ -1269,7 +1269,7 @@ static int iscsi_check_value(struct iscsi_param *param, char *value) comma_ptr = strchr(value, ','); if (comma_ptr && !IS_TYPE_VALUE_LIST(param)) { - pr_err("Detected value separator \",\", but" + pr_err("Detected value seperator \",\", but" " key \"%s\" does not allow a value list," " protocol error.\n", param->name); return -1; diff --git a/trunk/drivers/target/target_core_alua.c b/trunk/drivers/target/target_core_alua.c index 41641ba54828..91799973081a 100644 --- a/trunk/drivers/target/target_core_alua.c +++ b/trunk/drivers/target/target_core_alua.c @@ -218,13 +218,6 @@ int target_emulate_set_target_port_groups(struct se_cmd *cmd) cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; return -EINVAL; } - if (cmd->data_length < 4) { - pr_warn("SET TARGET PORT GROUPS parameter list length %u too" - " small\n", cmd->data_length); - cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; - return -EINVAL; - } - buf = transport_kmap_data_sg(cmd); /* diff --git a/trunk/drivers/target/target_core_device.c b/trunk/drivers/target/target_core_device.c index 9fc9a6006ca0..cf2c66f3c116 100644 --- a/trunk/drivers/target/target_core_device.c +++ b/trunk/drivers/target/target_core_device.c @@ -669,13 +669,6 @@ int target_report_luns(struct se_cmd *se_cmd) unsigned char *buf; u32 lun_count = 0, offset = 8, i; - if (se_cmd->data_length < 16) { - pr_warn("REPORT LUNS allocation length %u too small\n", - se_cmd->data_length); - se_cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; - return -EINVAL; - } - buf = transport_kmap_data_sg(se_cmd); if (!buf) return -ENOMEM; diff --git a/trunk/drivers/target/target_core_iblock.c b/trunk/drivers/target/target_core_iblock.c index 9ba495477fd2..76db75e836ed 100644 --- a/trunk/drivers/target/target_core_iblock.c +++ b/trunk/drivers/target/target_core_iblock.c @@ -325,30 +325,17 @@ static int iblock_execute_unmap(struct se_cmd *cmd) struct iblock_dev *ibd = dev->dev_ptr; unsigned char *buf, *ptr = NULL; sector_t lba; - int size; + int size = cmd->data_length; u32 range; int ret = 0; int dl, bd_dl; - if (cmd->data_length < 8) { - pr_warn("UNMAP parameter list length %u too small\n", - cmd->data_length); - cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; - return -EINVAL; - } - buf = transport_kmap_data_sg(cmd); dl = get_unaligned_be16(&buf[0]); bd_dl = get_unaligned_be16(&buf[2]); - size = cmd->data_length - 8; - if (bd_dl > size) - pr_warn("UNMAP parameter list length %u too small, ignoring bd_dl %u\n", - cmd->data_length, bd_dl); - else - size = bd_dl; - + size = min(size - 8, bd_dl); if (size / 16 > dev->se_sub_dev->se_dev_attrib.max_unmap_block_desc_count) { cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; ret = -EINVAL; diff --git a/trunk/drivers/target/target_core_pr.c b/trunk/drivers/target/target_core_pr.c index 956c84c6b666..1e946502c378 100644 --- a/trunk/drivers/target/target_core_pr.c +++ b/trunk/drivers/target/target_core_pr.c @@ -1540,14 +1540,6 @@ static int core_scsi3_decode_spec_i_port( tidh_new->dest_local_nexus = 1; list_add_tail(&tidh_new->dest_list, &tid_dest_list); - if (cmd->data_length < 28) { - pr_warn("SPC-PR: Received PR OUT parameter list" - " length too small: %u\n", cmd->data_length); - cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; - ret = -EINVAL; - goto out; - } - buf = transport_kmap_data_sg(cmd); /* * For a PERSISTENT RESERVE OUT specify initiator ports payload, diff --git a/trunk/drivers/target/target_core_pscsi.c b/trunk/drivers/target/target_core_pscsi.c index 9d7ce3daa262..6e32ff6f2fa0 100644 --- a/trunk/drivers/target/target_core_pscsi.c +++ b/trunk/drivers/target/target_core_pscsi.c @@ -667,32 +667,24 @@ static void pscsi_free_device(void *p) kfree(pdv); } -static void pscsi_transport_complete(struct se_cmd *cmd, struct scatterlist *sg, - unsigned char *sense_buffer) +static int pscsi_transport_complete(struct se_cmd *cmd, struct scatterlist *sg) { struct pscsi_dev_virt *pdv = cmd->se_dev->dev_ptr; struct scsi_device *sd = pdv->pdv_sd; int result; struct pscsi_plugin_task *pt = cmd->priv; - unsigned char *cdb; - /* - * Special case for REPORT_LUNs handling where pscsi_plugin_task has - * not been allocated because TCM is handling the emulation directly. - */ - if (!pt) - return; + unsigned char *cdb = &pt->pscsi_cdb[0]; - cdb = &pt->pscsi_cdb[0]; result = pt->pscsi_result; /* * Hack to make sure that Write-Protect modepage is set if R/O mode is * forced. */ - if (!cmd->se_deve || !cmd->data_length) - goto after_mode_sense; - if (((cdb[0] == MODE_SENSE) || (cdb[0] == MODE_SENSE_10)) && (status_byte(result) << 1) == SAM_STAT_GOOD) { + if (!cmd->se_deve) + goto after_mode_sense; + if (cmd->se_deve->lun_flags & TRANSPORT_LUNFLAGS_READ_ONLY) { unsigned char *buf = transport_kmap_data_sg(cmd); @@ -709,7 +701,7 @@ static void pscsi_transport_complete(struct se_cmd *cmd, struct scatterlist *sg, } after_mode_sense: - if (sd->type != TYPE_TAPE || !cmd->data_length) + if (sd->type != TYPE_TAPE) goto after_mode_select; /* @@ -751,10 +743,10 @@ static void pscsi_transport_complete(struct se_cmd *cmd, struct scatterlist *sg, } after_mode_select: - if (sense_buffer && (status_byte(result) & CHECK_CONDITION)) { - memcpy(sense_buffer, pt->pscsi_sense, TRANSPORT_SENSE_BUFFER); - cmd->se_cmd_flags |= SCF_TRANSPORT_TASK_SENSE; - } + if (status_byte(result) & CHECK_CONDITION) + return 1; + + return 0; } enum { @@ -1185,6 +1177,13 @@ static int pscsi_execute_cmd(struct se_cmd *cmd) return -ENOMEM; } +static unsigned char *pscsi_get_sense_buffer(struct se_cmd *cmd) +{ + struct pscsi_plugin_task *pt = cmd->priv; + + return pt->pscsi_sense; +} + /* pscsi_get_device_rev(): * * @@ -1267,6 +1266,7 @@ static struct se_subsystem_api pscsi_template = { .check_configfs_dev_params = pscsi_check_configfs_dev_params, .set_configfs_dev_params = pscsi_set_configfs_dev_params, .show_configfs_dev_params = pscsi_show_configfs_dev_params, + .get_sense_buffer = pscsi_get_sense_buffer, .get_device_rev = pscsi_get_device_rev, .get_device_type = pscsi_get_device_type, .get_blocks = pscsi_get_blocks, diff --git a/trunk/drivers/target/target_core_spc.c b/trunk/drivers/target/target_core_spc.c index 388a922c8f6d..4c861de538c9 100644 --- a/trunk/drivers/target/target_core_spc.c +++ b/trunk/drivers/target/target_core_spc.c @@ -877,11 +877,9 @@ static int spc_emulate_modesense(struct se_cmd *cmd) static int spc_emulate_request_sense(struct se_cmd *cmd) { unsigned char *cdb = cmd->t_task_cdb; - unsigned char *rbuf; + unsigned char *buf; u8 ua_asc = 0, ua_ascq = 0; - unsigned char buf[SE_SENSE_BUF]; - - memset(buf, 0, SE_SENSE_BUF); + int err = 0; if (cdb[1] & 0x01) { pr_err("REQUEST_SENSE description emulation not" @@ -890,21 +888,20 @@ static int spc_emulate_request_sense(struct se_cmd *cmd) return -ENOSYS; } - rbuf = transport_kmap_data_sg(cmd); - if (cmd->scsi_sense_reason != 0) { - /* - * Out of memory. We will fail with CHECK CONDITION, so - * we must not clear the unit attention condition. - */ - target_complete_cmd(cmd, CHECK_CONDITION); - return 0; - } else if (!core_scsi3_ua_clear_for_request_sense(cmd, &ua_asc, &ua_ascq)) { + buf = transport_kmap_data_sg(cmd); + + if (!core_scsi3_ua_clear_for_request_sense(cmd, &ua_asc, &ua_ascq)) { /* * CURRENT ERROR, UNIT ATTENTION */ buf[0] = 0x70; buf[SPC_SENSE_KEY_OFFSET] = UNIT_ATTENTION; + if (cmd->data_length < 18) { + buf[7] = 0x00; + err = -EINVAL; + goto end; + } /* * The Additional Sense Code (ASC) from the UNIT ATTENTION */ @@ -918,6 +915,11 @@ static int spc_emulate_request_sense(struct se_cmd *cmd) buf[0] = 0x70; buf[SPC_SENSE_KEY_OFFSET] = NO_SENSE; + if (cmd->data_length < 18) { + buf[7] = 0x00; + err = -EINVAL; + goto end; + } /* * NO ADDITIONAL SENSE INFORMATION */ @@ -925,11 +927,8 @@ static int spc_emulate_request_sense(struct se_cmd *cmd) buf[7] = 0x0A; } - if (rbuf) { - memcpy(rbuf, buf, min_t(u32, sizeof(buf), cmd->data_length)); - transport_kunmap_data_sg(cmd); - } - +end: + transport_kunmap_data_sg(cmd); target_complete_cmd(cmd, GOOD); return 0; } diff --git a/trunk/drivers/target/target_core_transport.c b/trunk/drivers/target/target_core_transport.c index 269f54488397..0eaae23d12b5 100644 --- a/trunk/drivers/target/target_core_transport.c +++ b/trunk/drivers/target/target_core_transport.c @@ -567,34 +567,6 @@ static void target_complete_failure_work(struct work_struct *work) transport_generic_request_failure(cmd); } -/* - * Used when asking transport to copy Sense Data from the underlying - * Linux/SCSI struct scsi_cmnd - */ -static unsigned char *transport_get_sense_buffer(struct se_cmd *cmd) -{ - unsigned char *buffer = cmd->sense_buffer; - struct se_device *dev = cmd->se_dev; - u32 offset = 0; - - WARN_ON(!cmd->se_lun); - - if (!dev) - return NULL; - - if (cmd->se_cmd_flags & SCF_SENT_CHECK_CONDITION) - return NULL; - - offset = cmd->se_tfo->set_fabric_sense_len(cmd, TRANSPORT_SENSE_BUFFER); - - /* Automatically padded */ - cmd->scsi_sense_length = TRANSPORT_SENSE_BUFFER + offset; - - pr_debug("HBA_[%u]_PLUG[%s]: Requesting sense for SAM STATUS: 0x%02x\n", - dev->se_hba->hba_id, dev->transport->name, cmd->scsi_status); - return &buffer[offset]; -} - void target_complete_cmd(struct se_cmd *cmd, u8 scsi_status) { struct se_device *dev = cmd->se_dev; @@ -608,11 +580,11 @@ void target_complete_cmd(struct se_cmd *cmd, u8 scsi_status) cmd->transport_state &= ~CMD_T_BUSY; if (dev && dev->transport->transport_complete) { - dev->transport->transport_complete(cmd, - cmd->t_data_sg, - transport_get_sense_buffer(cmd)); - if (cmd->se_cmd_flags & SCF_TRANSPORT_TASK_SENSE) + if (dev->transport->transport_complete(cmd, + cmd->t_data_sg) != 0) { + cmd->se_cmd_flags |= SCF_TRANSPORT_TASK_SENSE; success = 1; + } } /* @@ -1193,6 +1165,8 @@ int target_cmd_size_check(struct se_cmd *cmd, unsigned int size) " 0x%02x\n", cmd->se_tfo->get_fabric_name(), cmd->data_length, size, cmd->t_task_cdb[0]); + cmd->cmd_spdtl = size; + if (cmd->data_direction == DMA_TO_DEVICE) { pr_err("Rejecting underflow/overflow" " WRITE data\n"); @@ -1209,20 +1183,15 @@ int target_cmd_size_check(struct se_cmd *cmd, unsigned int size) /* Returns CHECK_CONDITION + INVALID_CDB_FIELD */ goto out_invalid_cdb_field; } - /* - * For the overflow case keep the existing fabric provided - * ->data_length. Otherwise for the underflow case, reset - * ->data_length to the smaller SCSI expected data transfer - * length. - */ + if (size > cmd->data_length) { cmd->se_cmd_flags |= SCF_OVERFLOW_BIT; cmd->residual_count = (size - cmd->data_length); } else { cmd->se_cmd_flags |= SCF_UNDERFLOW_BIT; cmd->residual_count = (cmd->data_length - size); - cmd->data_length = size; } + cmd->data_length = size; } return 0; @@ -1848,6 +1817,61 @@ void target_execute_cmd(struct se_cmd *cmd) } EXPORT_SYMBOL(target_execute_cmd); +/* + * Used to obtain Sense Data from underlying Linux/SCSI struct scsi_cmnd + */ +static int transport_get_sense_data(struct se_cmd *cmd) +{ + unsigned char *buffer = cmd->sense_buffer, *sense_buffer = NULL; + struct se_device *dev = cmd->se_dev; + unsigned long flags; + u32 offset = 0; + + WARN_ON(!cmd->se_lun); + + if (!dev) + return 0; + + spin_lock_irqsave(&cmd->t_state_lock, flags); + if (cmd->se_cmd_flags & SCF_SENT_CHECK_CONDITION) { + spin_unlock_irqrestore(&cmd->t_state_lock, flags); + return 0; + } + + if (!(cmd->se_cmd_flags & SCF_TRANSPORT_TASK_SENSE)) + goto out; + + if (!dev->transport->get_sense_buffer) { + pr_err("dev->transport->get_sense_buffer is NULL\n"); + goto out; + } + + sense_buffer = dev->transport->get_sense_buffer(cmd); + if (!sense_buffer) { + pr_err("ITT 0x%08x cmd %p: Unable to locate" + " sense buffer for task with sense\n", + cmd->se_tfo->get_task_tag(cmd), cmd); + goto out; + } + + spin_unlock_irqrestore(&cmd->t_state_lock, flags); + + offset = cmd->se_tfo->set_fabric_sense_len(cmd, TRANSPORT_SENSE_BUFFER); + + memcpy(&buffer[offset], sense_buffer, TRANSPORT_SENSE_BUFFER); + + /* Automatically padded */ + cmd->scsi_sense_length = TRANSPORT_SENSE_BUFFER + offset; + + pr_debug("HBA_[%u]_PLUG[%s]: Set SAM STATUS: 0x%02x and sense\n", + dev->se_hba->hba_id, dev->transport->name, cmd->scsi_status); + return 0; + +out: + spin_unlock_irqrestore(&cmd->t_state_lock, flags); + return -1; +} + /* * Process all commands up to the last received ORDERED task attribute which * requires another blocking boundary @@ -1963,7 +1987,7 @@ static void transport_handle_queue_full( static void target_complete_ok_work(struct work_struct *work) { struct se_cmd *cmd = container_of(work, struct se_cmd, work); - int ret; + int reason = 0, ret; /* * Check if we need to move delayed/dormant tasks from cmds on the @@ -1980,19 +2004,23 @@ static void target_complete_ok_work(struct work_struct *work) schedule_work(&cmd->se_dev->qf_work_queue); /* - * Check if we need to send a sense buffer from + * Check if we need to retrieve a sense buffer from * the struct se_cmd in question. */ if (cmd->se_cmd_flags & SCF_TRANSPORT_TASK_SENSE) { - WARN_ON(!cmd->scsi_status); - ret = transport_send_check_condition_and_sense( - cmd, 0, 1); - if (ret == -EAGAIN || ret == -ENOMEM) - goto queue_full; + if (transport_get_sense_data(cmd) < 0) + reason = TCM_NON_EXISTENT_LUN; - transport_lun_remove_cmd(cmd); - transport_cmd_check_stop_to_fabric(cmd); - return; + if (cmd->scsi_status) { + ret = transport_send_check_condition_and_sense( + cmd, reason, 1); + if (ret == -EAGAIN || ret == -ENOMEM) + goto queue_full; + + transport_lun_remove_cmd(cmd); + transport_cmd_check_stop_to_fabric(cmd); + return; + } } /* * Check for a callback, used by amongst other things @@ -2190,6 +2218,7 @@ void *transport_kmap_data_sg(struct se_cmd *cmd) struct page **pages; int i; + BUG_ON(!sg); /* * We need to take into account a possible offset here for fabrics like * tcm_loop who may be using a contig buffer from the SCSI midlayer for @@ -2197,17 +2226,13 @@ void *transport_kmap_data_sg(struct se_cmd *cmd) */ if (!cmd->t_data_nents) return NULL; - - BUG_ON(!sg); - if (cmd->t_data_nents == 1) + else if (cmd->t_data_nents == 1) return kmap(sg_page(sg)) + sg->offset; /* >1 page. use vmap */ pages = kmalloc(sizeof(*pages) * cmd->t_data_nents, GFP_KERNEL); - if (!pages) { - cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + if (!pages) return NULL; - } /* convert sg[] to pages[] */ for_each_sg(cmd->t_data_sg, sg, cmd->t_data_nents, i) { @@ -2216,10 +2241,8 @@ void *transport_kmap_data_sg(struct se_cmd *cmd) cmd->t_data_vmap = vmap(pages, cmd->t_data_nents, VM_MAP, PAGE_KERNEL); kfree(pages); - if (!cmd->t_data_vmap) { - cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + if (!cmd->t_data_vmap) return NULL; - } return cmd->t_data_vmap + cmd->t_data_sg[0].offset; } @@ -2271,9 +2294,9 @@ transport_generic_get_mem(struct se_cmd *cmd) return 0; out: - while (i > 0) { - i--; + while (i >= 0) { __free_page(sg_page(&cmd->t_data_sg[i])); + i--; } kfree(cmd->t_data_sg); cmd->t_data_sg = NULL; @@ -2300,19 +2323,21 @@ int transport_generic_new_cmd(struct se_cmd *cmd) if (ret < 0) goto out_fail; } - /* - * If this command doesn't have any payload and we don't have to call - * into the fabric for data transfers, go ahead and complete it right - * away. - */ - if (!cmd->data_length && - cmd->t_task_cdb[0] != REQUEST_SENSE && - cmd->se_dev->transport->transport_type != TRANSPORT_PLUGIN_PHBA_PDEV) { + + /* Workaround for handling zero-length control CDBs */ + if (!(cmd->se_cmd_flags & SCF_SCSI_DATA_CDB) && !cmd->data_length) { spin_lock_irq(&cmd->t_state_lock); cmd->t_state = TRANSPORT_COMPLETE; cmd->transport_state |= CMD_T_ACTIVE; spin_unlock_irq(&cmd->t_state_lock); + if (cmd->t_task_cdb[0] == REQUEST_SENSE) { + u8 ua_asc = 0, ua_ascq = 0; + + core_scsi3_ua_clear_for_request_sense(cmd, + &ua_asc, &ua_ascq); + } + INIT_WORK(&cmd->work, target_complete_ok_work); queue_work(target_completion_wq, &cmd->work); return 0; diff --git a/trunk/drivers/target/tcm_fc/tcm_fc.h b/trunk/drivers/target/tcm_fc/tcm_fc.h index eea69358ced3..c5eb3c33c3db 100644 --- a/trunk/drivers/target/tcm_fc/tcm_fc.h +++ b/trunk/drivers/target/tcm_fc/tcm_fc.h @@ -131,7 +131,6 @@ extern struct list_head ft_lport_list; extern struct mutex ft_lport_lock; extern struct fc4_prov ft_prov; extern struct target_fabric_configfs *ft_configfs; -extern unsigned int ft_debug_logging; /* * Fabric methods. diff --git a/trunk/drivers/target/tcm_fc/tfc_cmd.c b/trunk/drivers/target/tcm_fc/tfc_cmd.c index 823e6922249d..b9cb5006177e 100644 --- a/trunk/drivers/target/tcm_fc/tfc_cmd.c +++ b/trunk/drivers/target/tcm_fc/tfc_cmd.c @@ -48,7 +48,7 @@ /* * Dump cmd state for debugging. */ -static void _ft_dump_cmd(struct ft_cmd *cmd, const char *caller) +void ft_dump_cmd(struct ft_cmd *cmd, const char *caller) { struct fc_exch *ep; struct fc_seq *sp; @@ -80,12 +80,6 @@ static void _ft_dump_cmd(struct ft_cmd *cmd, const char *caller) } } -void ft_dump_cmd(struct ft_cmd *cmd, const char *caller) -{ - if (unlikely(ft_debug_logging)) - _ft_dump_cmd(cmd, caller); -} - static void ft_free_cmd(struct ft_cmd *cmd) { struct fc_frame *fp; diff --git a/trunk/drivers/target/tcm_fc/tfc_sess.c b/trunk/drivers/target/tcm_fc/tfc_sess.c index 3c9e5b57caab..87901fa74dd7 100644 --- a/trunk/drivers/target/tcm_fc/tfc_sess.c +++ b/trunk/drivers/target/tcm_fc/tfc_sess.c @@ -456,9 +456,7 @@ static void ft_prlo(struct fc_rport_priv *rdata) struct ft_tport *tport; mutex_lock(&ft_lport_lock); - tport = rcu_dereference_protected(rdata->local_port->prov[FC_TYPE_FCP], - lockdep_is_held(&ft_lport_lock)); - + tport = rcu_dereference(rdata->local_port->prov[FC_TYPE_FCP]); if (!tport) { mutex_unlock(&ft_lport_lock); return; diff --git a/trunk/drivers/tty/Kconfig b/trunk/drivers/tty/Kconfig index d8e05eeab232..830cd62d8492 100644 --- a/trunk/drivers/tty/Kconfig +++ b/trunk/drivers/tty/Kconfig @@ -214,8 +214,8 @@ config CYCLADES If you haven't heard about it, it's safe to say N. config CYZ_INTR - bool "Cyclades-Z interrupt mode operation" - depends on CYCLADES + bool "Cyclades-Z interrupt mode operation (EXPERIMENTAL)" + depends on EXPERIMENTAL && CYCLADES help The Cyclades-Z family of multiport cards allows 2 (two) driver op modes: polling and interrupt. In polling mode, the driver will check @@ -285,7 +285,7 @@ config SYNCLINK_GT config NOZOMI tristate "HSDPA Broadband Wireless Data Card - Globe Trotter" - depends on PCI + depends on PCI && EXPERIMENTAL help If you have a HSDPA driver Broadband Wireless Data Card - Globe Trotter PCMCIA card, say Y here. @@ -294,7 +294,7 @@ config NOZOMI will be called nozomi. config ISI - tristate "Multi-Tech multiport card support" + tristate "Multi-Tech multiport card support (EXPERIMENTAL)" depends on SERIAL_NONSTANDARD && PCI select FW_LOADER help @@ -317,6 +317,7 @@ config N_HDLC config N_GSM tristate "GSM MUX line discipline support (EXPERIMENTAL)" + depends on EXPERIMENTAL depends on NET help This line discipline provides support for the GSM MUX protocol and diff --git a/trunk/drivers/tty/amiserial.c b/trunk/drivers/tty/amiserial.c index 42d0a2581a87..6cc4358f68c1 100644 --- a/trunk/drivers/tty/amiserial.c +++ b/trunk/drivers/tty/amiserial.c @@ -420,7 +420,7 @@ static void check_modem_status(struct serial_state *info) tty_hangup(port->tty); } } - if (tty_port_cts_enabled(port)) { + if (port->flags & ASYNC_CTS_FLOW) { if (port->tty->hw_stopped) { if (!(status & SER_CTS)) { #if (defined(SERIAL_DEBUG_INTR) || defined(SERIAL_DEBUG_FLOW)) @@ -646,7 +646,7 @@ static void shutdown(struct tty_struct *tty, struct serial_state *info) custom.adkcon = AC_UARTBRK; mb(); - if (tty->termios.c_cflag & HUPCL) + if (tty->termios->c_cflag & HUPCL) info->MCR &= ~(SER_DTR|SER_RTS); rtsdtr_ctrl(info->MCR); @@ -670,7 +670,7 @@ static void change_speed(struct tty_struct *tty, struct serial_state *info, int bits; unsigned long flags; - cflag = tty->termios.c_cflag; + cflag = tty->termios->c_cflag; /* Byte size is always 8 bits plus parity bit if requested */ @@ -707,8 +707,8 @@ static void change_speed(struct tty_struct *tty, struct serial_state *info, /* If the quotient is zero refuse the change */ if (!quot && old_termios) { /* FIXME: Will need updating for new tty in the end */ - tty->termios.c_cflag &= ~CBAUD; - tty->termios.c_cflag |= (old_termios->c_cflag & CBAUD); + tty->termios->c_cflag &= ~CBAUD; + tty->termios->c_cflag |= (old_termios->c_cflag & CBAUD); baud = tty_get_baud_rate(tty); if (!baud) baud = 9600; @@ -984,7 +984,7 @@ static void rs_throttle(struct tty_struct * tty) if (I_IXOFF(tty)) rs_send_xchar(tty, STOP_CHAR(tty)); - if (tty->termios.c_cflag & CRTSCTS) + if (tty->termios->c_cflag & CRTSCTS) info->MCR &= ~SER_RTS; local_irq_save(flags); @@ -1012,7 +1012,7 @@ static void rs_unthrottle(struct tty_struct * tty) else rs_send_xchar(tty, START_CHAR(tty)); } - if (tty->termios.c_cflag & CRTSCTS) + if (tty->termios->c_cflag & CRTSCTS) info->MCR |= SER_RTS; local_irq_save(flags); rtsdtr_ctrl(info->MCR); @@ -1033,7 +1033,7 @@ static int get_serial_info(struct tty_struct *tty, struct serial_state *state, if (!retinfo) return -EFAULT; memset(&tmp, 0, sizeof(tmp)); - tty_lock(tty); + tty_lock(); tmp.line = tty->index; tmp.port = state->port; tmp.flags = state->tport.flags; @@ -1042,7 +1042,7 @@ static int get_serial_info(struct tty_struct *tty, struct serial_state *state, tmp.close_delay = state->tport.close_delay; tmp.closing_wait = state->tport.closing_wait; tmp.custom_divisor = state->custom_divisor; - tty_unlock(tty); + tty_unlock(); if (copy_to_user(retinfo,&tmp,sizeof(*retinfo))) return -EFAULT; return 0; @@ -1059,12 +1059,12 @@ static int set_serial_info(struct tty_struct *tty, struct serial_state *state, if (copy_from_user(&new_serial,new_info,sizeof(new_serial))) return -EFAULT; - tty_lock(tty); + tty_lock(); change_spd = ((new_serial.flags ^ port->flags) & ASYNC_SPD_MASK) || new_serial.custom_divisor != state->custom_divisor; if (new_serial.irq || new_serial.port != state->port || new_serial.xmit_fifo_size != state->xmit_fifo_size) { - tty_unlock(tty); + tty_unlock(); return -EINVAL; } @@ -1074,7 +1074,7 @@ static int set_serial_info(struct tty_struct *tty, struct serial_state *state, (new_serial.xmit_fifo_size != state->xmit_fifo_size) || ((new_serial.flags & ~ASYNC_USR_MASK) != (port->flags & ~ASYNC_USR_MASK))) { - tty_unlock(tty); + tty_unlock(); return -EPERM; } port->flags = ((port->flags & ~ASYNC_USR_MASK) | @@ -1084,7 +1084,7 @@ static int set_serial_info(struct tty_struct *tty, struct serial_state *state, } if (new_serial.baud_base < 9600) { - tty_unlock(tty); + tty_unlock(); return -EINVAL; } @@ -1116,7 +1116,7 @@ static int set_serial_info(struct tty_struct *tty, struct serial_state *state, } } else retval = startup(tty, state); - tty_unlock(tty); + tty_unlock(); return retval; } @@ -1330,7 +1330,7 @@ static void rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios) { struct serial_state *info = tty->driver_data; unsigned long flags; - unsigned int cflag = tty->termios.c_cflag; + unsigned int cflag = tty->termios->c_cflag; change_speed(tty, info, old_termios); @@ -1347,7 +1347,7 @@ static void rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios) if (!(old_termios->c_cflag & CBAUD) && (cflag & CBAUD)) { info->MCR |= SER_DTR; - if (!(tty->termios.c_cflag & CRTSCTS) || + if (!(tty->termios->c_cflag & CRTSCTS) || !test_bit(TTY_THROTTLED, &tty->flags)) { info->MCR |= SER_RTS; } @@ -1358,7 +1358,7 @@ static void rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios) /* Handle turning off CRTSCTS */ if ((old_termios->c_cflag & CRTSCTS) && - !(tty->termios.c_cflag & CRTSCTS)) { + !(tty->termios->c_cflag & CRTSCTS)) { tty->hw_stopped = 0; rs_start(tty); } @@ -1371,7 +1371,7 @@ static void rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios) * or not. Hence, this may change..... */ if (!(old_termios->c_cflag & CLOCAL) && - (tty->termios.c_cflag & CLOCAL)) + (tty->termios->c_cflag & CLOCAL)) wake_up_interruptible(&info->open_wait); #endif } @@ -1710,6 +1710,10 @@ static int __init amiga_serial_probe(struct platform_device *pdev) serial_driver->flags = TTY_DRIVER_REAL_RAW; tty_set_operations(serial_driver, &serial_ops); + error = tty_register_driver(serial_driver); + if (error) + goto fail_put_tty_driver; + state = rs_table; state->port = (int)&custom.serdatr; /* Just to give it a value */ state->custom_divisor = 0; @@ -1720,11 +1724,6 @@ static int __init amiga_serial_probe(struct platform_device *pdev) state->icount.overrun = state->icount.brk = 0; tty_port_init(&state->tport); state->tport.ops = &amiga_port_ops; - tty_port_link_device(&state->tport, serial_driver, 0); - - error = tty_register_driver(serial_driver); - if (error) - goto fail_put_tty_driver; printk(KERN_INFO "ttyS0 is the amiga builtin serial port\n"); diff --git a/trunk/drivers/tty/bfin_jtag_comm.c b/trunk/drivers/tty/bfin_jtag_comm.c index 02b7d3a09696..61fc74fe1747 100644 --- a/trunk/drivers/tty/bfin_jtag_comm.c +++ b/trunk/drivers/tty/bfin_jtag_comm.c @@ -263,7 +263,6 @@ static int __init bfin_jc_init(void) bfin_jc_driver->subtype = SERIAL_TYPE_NORMAL; bfin_jc_driver->init_termios = tty_std_termios; tty_set_operations(bfin_jc_driver, &bfin_jc_ops); - tty_port_link_device(&port, bfin_jc_driver, 0); ret = tty_register_driver(bfin_jc_driver); if (ret) diff --git a/trunk/drivers/tty/cyclades.c b/trunk/drivers/tty/cyclades.c index 0a6a0bc1b598..e61cabdd69df 100644 --- a/trunk/drivers/tty/cyclades.c +++ b/trunk/drivers/tty/cyclades.c @@ -727,7 +727,7 @@ static void cyy_chip_modem(struct cyclades_card *cinfo, int chip, else tty_hangup(tty); } - if ((mdm_change & CyCTS) && tty_port_cts_enabled(&info->port)) { + if ((mdm_change & CyCTS) && (info->port.flags & ASYNC_CTS_FLOW)) { if (tty->hw_stopped) { if (mdm_status & CyCTS) { /* cy_start isn't used @@ -1459,7 +1459,7 @@ static void cy_shutdown(struct cyclades_port *info, struct tty_struct *tty) info->port.xmit_buf = NULL; free_page((unsigned long)temp); } - if (tty->termios.c_cflag & HUPCL) + if (tty->termios->c_cflag & HUPCL) cyy_change_rts_dtr(info, 0, TIOCM_RTS | TIOCM_DTR); cyy_issue_cmd(info, CyCHAN_CTL | CyDIS_RCVR); @@ -1488,7 +1488,7 @@ static void cy_shutdown(struct cyclades_port *info, struct tty_struct *tty) free_page((unsigned long)temp); } - if (tty->termios.c_cflag & HUPCL) + if (tty->termios->c_cflag & HUPCL) tty_port_lower_dtr_rts(&info->port); set_bit(TTY_IO_ERROR, &tty->flags); @@ -1599,7 +1599,7 @@ static int cy_open(struct tty_struct *tty, struct file *filp) * If the port is the middle of closing, bail out now */ if (tty_hung_up_p(filp) || (info->port.flags & ASYNC_CLOSING)) { - wait_event_interruptible_tty(tty, info->port.close_wait, + wait_event_interruptible_tty(info->port.close_wait, !(info->port.flags & ASYNC_CLOSING)); return (info->port.flags & ASYNC_HUP_NOTIFY) ? -EAGAIN: -ERESTARTSYS; } @@ -1999,11 +1999,14 @@ static void cy_set_line_char(struct cyclades_port *info, struct tty_struct *tty) int baud, baud_rate = 0; int i; + if (!tty->termios) /* XXX can this happen at all? */ + return; + if (info->line == -1) return; - cflag = tty->termios.c_cflag; - iflag = tty->termios.c_iflag; + cflag = tty->termios->c_cflag; + iflag = tty->termios->c_iflag; /* * Set up the tty->alt_speed kludge @@ -2822,7 +2825,7 @@ static void cy_set_termios(struct tty_struct *tty, struct ktermios *old_termios) cy_set_line_char(info, tty); if ((old_termios->c_cflag & CRTSCTS) && - !(tty->termios.c_cflag & CRTSCTS)) { + !(tty->termios->c_cflag & CRTSCTS)) { tty->hw_stopped = 0; cy_start(tty); } @@ -2834,7 +2837,7 @@ static void cy_set_termios(struct tty_struct *tty, struct ktermios *old_termios) * or not. Hence, this may change..... */ if (!(old_termios->c_cflag & CLOCAL) && - (tty->termios.c_cflag & CLOCAL)) + (tty->termios->c_cflag & CLOCAL)) wake_up_interruptible(&info->port.open_wait); #endif } /* cy_set_termios */ @@ -2896,7 +2899,7 @@ static void cy_throttle(struct tty_struct *tty) info->throttle = 1; } - if (tty->termios.c_cflag & CRTSCTS) { + if (tty->termios->c_cflag & CRTSCTS) { if (!cy_is_Z(card)) { spin_lock_irqsave(&card->card_lock, flags); cyy_change_rts_dtr(info, 0, TIOCM_RTS); @@ -2935,7 +2938,7 @@ static void cy_unthrottle(struct tty_struct *tty) cy_send_xchar(tty, START_CHAR(tty)); } - if (tty->termios.c_cflag & CRTSCTS) { + if (tty->termios->c_cflag & CRTSCTS) { card = info->card; if (!cy_is_Z(card)) { spin_lock_irqsave(&card->card_lock, flags); @@ -3286,10 +3289,9 @@ static unsigned short __devinit cyy_init_card(void __iomem *true_base_addr, static int __init cy_detect_isa(void) { #ifdef CONFIG_ISA - struct cyclades_card *card; unsigned short cy_isa_irq, nboard; void __iomem *cy_isa_address; - unsigned short i, j, k, cy_isa_nchan; + unsigned short i, j, cy_isa_nchan; int isparam = 0; nboard = 0; @@ -3347,8 +3349,7 @@ static int __init cy_detect_isa(void) } /* fill the next cy_card structure available */ for (j = 0; j < NR_CARDS; j++) { - card = &cy_card[j]; - if (card->base_addr == NULL) + if (cy_card[j].base_addr == NULL) break; } if (j == NR_CARDS) { /* no more cy_cards available */ @@ -3362,7 +3363,7 @@ static int __init cy_detect_isa(void) /* allocate IRQ */ if (request_irq(cy_isa_irq, cyy_interrupt, - 0, "Cyclom-Y", card)) { + 0, "Cyclom-Y", &cy_card[j])) { printk(KERN_ERR "Cyclom-Y/ISA found at 0x%lx, but " "could not allocate IRQ#%d.\n", (unsigned long)cy_isa_address, cy_isa_irq); @@ -3371,16 +3372,16 @@ static int __init cy_detect_isa(void) } /* set cy_card */ - card->base_addr = cy_isa_address; - card->ctl_addr.p9050 = NULL; - card->irq = (int)cy_isa_irq; - card->bus_index = 0; - card->first_line = cy_next_channel; - card->num_chips = cy_isa_nchan / CyPORTS_PER_CHIP; - card->nports = cy_isa_nchan; - if (cy_init_card(card)) { - card->base_addr = NULL; - free_irq(cy_isa_irq, card); + cy_card[j].base_addr = cy_isa_address; + cy_card[j].ctl_addr.p9050 = NULL; + cy_card[j].irq = (int)cy_isa_irq; + cy_card[j].bus_index = 0; + cy_card[j].first_line = cy_next_channel; + cy_card[j].num_chips = cy_isa_nchan / CyPORTS_PER_CHIP; + cy_card[j].nports = cy_isa_nchan; + if (cy_init_card(&cy_card[j])) { + cy_card[j].base_addr = NULL; + free_irq(cy_isa_irq, &cy_card[j]); iounmap(cy_isa_address); continue; } @@ -3392,10 +3393,9 @@ static int __init cy_detect_isa(void) (unsigned long)(cy_isa_address + (CyISA_Ywin - 1)), cy_isa_irq, cy_isa_nchan, cy_next_channel); - for (k = 0, j = cy_next_channel; - j < cy_next_channel + cy_isa_nchan; j++, k++) - tty_port_register_device(&card->ports[k].port, - cy_serial_driver, j, NULL); + for (j = cy_next_channel; + j < cy_next_channel + cy_isa_nchan; j++) + tty_register_device(cy_serial_driver, j, NULL); cy_next_channel += cy_isa_nchan; } return nboard; @@ -3695,11 +3695,10 @@ static int __devinit cyz_load_fw(struct pci_dev *pdev, void __iomem *base_addr, static int __devinit cy_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { - struct cyclades_card *card; void __iomem *addr0 = NULL, *addr2 = NULL; char *card_name = NULL; u32 uninitialized_var(mailbox); - unsigned int device_id, nchan = 0, card_no, i, j; + unsigned int device_id, nchan = 0, card_no, i; unsigned char plx_ver; int retval, irq; @@ -3830,8 +3829,7 @@ static int __devinit cy_pci_probe(struct pci_dev *pdev, } /* fill the next cy_card structure available */ for (card_no = 0; card_no < NR_CARDS; card_no++) { - card = &cy_card[card_no]; - if (card->base_addr == NULL) + if (cy_card[card_no].base_addr == NULL) break; } if (card_no == NR_CARDS) { /* no more cy_cards available */ @@ -3845,26 +3843,27 @@ static int __devinit cy_pci_probe(struct pci_dev *pdev, device_id == PCI_DEVICE_ID_CYCLOM_Y_Hi) { /* allocate IRQ */ retval = request_irq(irq, cyy_interrupt, - IRQF_SHARED, "Cyclom-Y", card); + IRQF_SHARED, "Cyclom-Y", &cy_card[card_no]); if (retval) { dev_err(&pdev->dev, "could not allocate IRQ\n"); goto err_unmap; } - card->num_chips = nchan / CyPORTS_PER_CHIP; + cy_card[card_no].num_chips = nchan / CyPORTS_PER_CHIP; } else { struct FIRM_ID __iomem *firm_id = addr2 + ID_ADDRESS; struct ZFW_CTRL __iomem *zfw_ctrl; zfw_ctrl = addr2 + (readl(&firm_id->zfwctrl_addr) & 0xfffff); - card->hw_ver = mailbox; - card->num_chips = (unsigned int)-1; - card->board_ctrl = &zfw_ctrl->board_ctrl; + cy_card[card_no].hw_ver = mailbox; + cy_card[card_no].num_chips = (unsigned int)-1; + cy_card[card_no].board_ctrl = &zfw_ctrl->board_ctrl; #ifdef CONFIG_CYZ_INTR /* allocate IRQ only if board has an IRQ */ if (irq != 0 && irq != 255) { retval = request_irq(irq, cyz_interrupt, - IRQF_SHARED, "Cyclades-Z", card); + IRQF_SHARED, "Cyclades-Z", + &cy_card[card_no]); if (retval) { dev_err(&pdev->dev, "could not allocate IRQ\n"); goto err_unmap; @@ -3874,17 +3873,17 @@ static int __devinit cy_pci_probe(struct pci_dev *pdev, } /* set cy_card */ - card->base_addr = addr2; - card->ctl_addr.p9050 = addr0; - card->irq = irq; - card->bus_index = 1; - card->first_line = cy_next_channel; - card->nports = nchan; - retval = cy_init_card(card); + cy_card[card_no].base_addr = addr2; + cy_card[card_no].ctl_addr.p9050 = addr0; + cy_card[card_no].irq = irq; + cy_card[card_no].bus_index = 1; + cy_card[card_no].first_line = cy_next_channel; + cy_card[card_no].nports = nchan; + retval = cy_init_card(&cy_card[card_no]); if (retval) goto err_null; - pci_set_drvdata(pdev, card); + pci_set_drvdata(pdev, &cy_card[card_no]); if (device_id == PCI_DEVICE_ID_CYCLOM_Y_Lo || device_id == PCI_DEVICE_ID_CYCLOM_Y_Hi) { @@ -3910,15 +3909,14 @@ static int __devinit cy_pci_probe(struct pci_dev *pdev, dev_info(&pdev->dev, "%s/PCI #%d found: %d channels starting from " "port %d.\n", card_name, card_no + 1, nchan, cy_next_channel); - for (j = 0, i = cy_next_channel; i < cy_next_channel + nchan; i++, j++) - tty_port_register_device(&card->ports[j].port, - cy_serial_driver, i, &pdev->dev); + for (i = cy_next_channel; i < cy_next_channel + nchan; i++) + tty_register_device(cy_serial_driver, i, &pdev->dev); cy_next_channel += nchan; return 0; err_null: - card->base_addr = NULL; - free_irq(irq, card); + cy_card[card_no].base_addr = NULL; + free_irq(irq, &cy_card[card_no]); err_unmap: iounmap(addr0); if (addr2) diff --git a/trunk/drivers/tty/ehv_bytechan.c b/trunk/drivers/tty/ehv_bytechan.c index 4ab936b7aac6..4813684cb634 100644 --- a/trunk/drivers/tty/ehv_bytechan.c +++ b/trunk/drivers/tty/ehv_bytechan.c @@ -738,17 +738,16 @@ static int __devinit ehv_bc_tty_probe(struct platform_device *pdev) goto error; } - tty_port_init(&bc->port); - bc->port.ops = &ehv_bc_tty_port_ops; - - bc->dev = tty_port_register_device(&bc->port, ehv_bc_driver, i, - &pdev->dev); + bc->dev = tty_register_device(ehv_bc_driver, i, &pdev->dev); if (IS_ERR(bc->dev)) { ret = PTR_ERR(bc->dev); dev_err(&pdev->dev, "could not register tty (ret=%i)\n", ret); goto error; } + tty_port_init(&bc->port); + bc->port.ops = &ehv_bc_tty_port_ops; + dev_set_drvdata(&pdev->dev, bc); dev_info(&pdev->dev, "registered /dev/%s%u for byte channel %u\n", diff --git a/trunk/drivers/tty/hvc/Kconfig b/trunk/drivers/tty/hvc/Kconfig index f47b734c6a7a..0282a83f51fb 100644 --- a/trunk/drivers/tty/hvc/Kconfig +++ b/trunk/drivers/tty/hvc/Kconfig @@ -76,7 +76,7 @@ config HVC_XEN_FRONTEND config HVC_UDBG bool "udbg based fake hypervisor console" - depends on PPC + depends on PPC && EXPERIMENTAL select HVC_DRIVER default n help diff --git a/trunk/drivers/tty/hvc/hvc_console.c b/trunk/drivers/tty/hvc/hvc_console.c index 4a652999380f..2d691eb7c40a 100644 --- a/trunk/drivers/tty/hvc/hvc_console.c +++ b/trunk/drivers/tty/hvc/hvc_console.c @@ -299,33 +299,20 @@ static void hvc_unthrottle(struct tty_struct *tty) hvc_kick(); } -static int hvc_install(struct tty_driver *driver, struct tty_struct *tty) -{ - struct hvc_struct *hp; - int rc; - - /* Auto increments kref reference if found. */ - if (!(hp = hvc_get_by_index(tty->index))) - return -ENODEV; - - tty->driver_data = hp; - - rc = tty_port_install(&hp->port, driver, tty); - if (rc) - tty_port_put(&hp->port); - return rc; -} - /* * The TTY interface won't be used until after the vio layer has exposed the vty * adapter to the kernel. */ static int hvc_open(struct tty_struct *tty, struct file * filp) { - struct hvc_struct *hp = tty->driver_data; + struct hvc_struct *hp; unsigned long flags; int rc = 0; + /* Auto increments kref reference if found. */ + if (!(hp = hvc_get_by_index(tty->index))) + return -ENODEV; + spin_lock_irqsave(&hp->port.lock, flags); /* Check and then increment for fast path open. */ if (hp->port.count++ > 0) { @@ -335,6 +322,7 @@ static int hvc_open(struct tty_struct *tty, struct file * filp) } /* else count == 0 */ spin_unlock_irqrestore(&hp->port.lock, flags); + tty->driver_data = hp; tty_port_tty_set(&hp->port, tty); if (hp->ops->notifier_add) @@ -401,11 +389,6 @@ static void hvc_close(struct tty_struct *tty, struct file * filp) hp->vtermno, hp->port.count); spin_unlock_irqrestore(&hp->port.lock, flags); } -} - -static void hvc_cleanup(struct tty_struct *tty) -{ - struct hvc_struct *hp = tty->driver_data; tty_port_put(&hp->port); } @@ -558,7 +541,7 @@ static int hvc_write_room(struct tty_struct *tty) struct hvc_struct *hp = tty->driver_data; if (!hp) - return 0; + return -1; return hp->outbuf_size - hp->n_outbuf; } @@ -809,10 +792,8 @@ static void hvc_poll_put_char(struct tty_driver *driver, int line, char ch) #endif static const struct tty_operations hvc_ops = { - .install = hvc_install, .open = hvc_open, .close = hvc_close, - .cleanup = hvc_cleanup, .write = hvc_write, .hangup = hvc_hangup, .unthrottle = hvc_unthrottle, diff --git a/trunk/drivers/tty/hvc/hvcs.c b/trunk/drivers/tty/hvc/hvcs.c index cab5c7adf8e8..d56788c83974 100644 --- a/trunk/drivers/tty/hvc/hvcs.c +++ b/trunk/drivers/tty/hvc/hvcs.c @@ -1102,20 +1102,27 @@ static struct hvcs_struct *hvcs_get_by_index(int index) return NULL; } -static int hvcs_install(struct tty_driver *driver, struct tty_struct *tty) +/* + * This is invoked via the tty_open interface when a user app connects to the + * /dev node. + */ +static int hvcs_open(struct tty_struct *tty, struct file *filp) { struct hvcs_struct *hvcsd; - struct vio_dev *vdev; - unsigned long unit_address, flags; + int rc, retval = 0; + unsigned long flags; unsigned int irq; - int retval; + struct vio_dev *vdev; + unsigned long unit_address; + + if (tty->driver_data) + goto fast_open; /* * Is there a vty-server that shares the same index? * This function increments the kref index. */ - hvcsd = hvcs_get_by_index(tty->index); - if (!hvcsd) { + if (!(hvcsd = hvcs_get_by_index(tty->index))) { printk(KERN_WARNING "HVCS: open failed, no device associated" " with tty->index %d.\n", tty->index); return -ENODEV; @@ -1123,16 +1130,11 @@ static int hvcs_install(struct tty_driver *driver, struct tty_struct *tty) spin_lock_irqsave(&hvcsd->lock, flags); - if (hvcsd->connected == 0) { - retval = hvcs_partner_connect(hvcsd); - if (retval) { - spin_unlock_irqrestore(&hvcsd->lock, flags); - printk(KERN_WARNING "HVCS: partner connect failed.\n"); - goto err_put; - } - } + if (hvcsd->connected == 0) + if ((retval = hvcs_partner_connect(hvcsd))) + goto error_release; - hvcsd->port.count = 0; + hvcsd->port.count = 1; hvcsd->port.tty = tty; tty->driver_data = hvcsd; @@ -1153,48 +1155,37 @@ static int hvcs_install(struct tty_driver *driver, struct tty_struct *tty) * This must be done outside of the spinlock because it requests irqs * and will grab the spinlock and free the connection if it fails. */ - retval = hvcs_enable_device(hvcsd, unit_address, irq, vdev); - if (retval) { + if (((rc = hvcs_enable_device(hvcsd, unit_address, irq, vdev)))) { + tty_port_put(&hvcsd->port); printk(KERN_WARNING "HVCS: enable device failed.\n"); - goto err_put; + return rc; } - retval = tty_port_install(&hvcsd->port, driver, tty); - if (retval) - goto err_irq; - - return 0; -err_irq: - spin_lock_irqsave(&hvcsd->lock, flags); - vio_disable_interrupts(hvcsd->vdev); - spin_unlock_irqrestore(&hvcsd->lock, flags); - free_irq(irq, hvcsd); -err_put: - tty_port_put(&hvcsd->port); - - return retval; -} + goto open_success; -/* - * This is invoked via the tty_open interface when a user app connects to the - * /dev node. - */ -static int hvcs_open(struct tty_struct *tty, struct file *filp) -{ - struct hvcs_struct *hvcsd = tty->driver_data; - unsigned long flags; +fast_open: + hvcsd = tty->driver_data; spin_lock_irqsave(&hvcsd->lock, flags); + tty_port_get(&hvcsd->port); hvcsd->port.count++; hvcsd->todo_mask |= HVCS_SCHED_READ; spin_unlock_irqrestore(&hvcsd->lock, flags); +open_success: hvcs_kick(); printk(KERN_INFO "HVCS: vty-server@%X connection opened.\n", hvcsd->vdev->unit_address ); return 0; + +error_release: + spin_unlock_irqrestore(&hvcsd->lock, flags); + tty_port_put(&hvcsd->port); + + printk(KERN_WARNING "HVCS: partner connect failed.\n"); + return retval; } static void hvcs_close(struct tty_struct *tty, struct file *filp) @@ -1245,6 +1236,7 @@ static void hvcs_close(struct tty_struct *tty, struct file *filp) tty->driver_data = NULL; free_irq(irq, hvcsd); + tty_port_put(&hvcsd->port); return; } else if (hvcsd->port.count < 0) { printk(KERN_ERR "HVCS: vty-server@%X open_count: %d" @@ -1253,12 +1245,6 @@ static void hvcs_close(struct tty_struct *tty, struct file *filp) } spin_unlock_irqrestore(&hvcsd->lock, flags); -} - -static void hvcs_cleanup(struct tty_struct * tty) -{ - struct hvcs_struct *hvcsd = tty->driver_data; - tty_port_put(&hvcsd->port); } @@ -1445,10 +1431,8 @@ static int hvcs_chars_in_buffer(struct tty_struct *tty) } static const struct tty_operations hvcs_ops = { - .install = hvcs_install, .open = hvcs_open, .close = hvcs_close, - .cleanup = hvcs_cleanup, .hangup = hvcs_hangup, .write = hvcs_write, .write_room = hvcs_write_room, diff --git a/trunk/drivers/tty/hvc/hvsi.c b/trunk/drivers/tty/hvc/hvsi.c index 0083bc1f63f4..6f5bc49c441f 100644 --- a/trunk/drivers/tty/hvc/hvsi.c +++ b/trunk/drivers/tty/hvc/hvsi.c @@ -1080,8 +1080,6 @@ static int __init hvsi_init(void) struct hvsi_struct *hp = &hvsi_ports[i]; int ret = 1; - tty_port_link_device(&hp->port, hvsi_driver, i); - ret = request_irq(hp->virq, hvsi_interrupt, 0, "hvsi", hp); if (ret) printk(KERN_ERR "HVSI: couldn't reserve irq 0x%x (error %i)\n", diff --git a/trunk/drivers/tty/hvc/hvsi_lib.c b/trunk/drivers/tty/hvc/hvsi_lib.c index 3396eb9d57a3..59c135dd5d20 100644 --- a/trunk/drivers/tty/hvc/hvsi_lib.c +++ b/trunk/drivers/tty/hvc/hvsi_lib.c @@ -400,7 +400,7 @@ void hvsilib_close(struct hvsi_priv *pv, struct hvc_struct *hp) spin_unlock_irqrestore(&hp->lock, flags); /* Clear our own DTR */ - if (!pv->tty || (pv->tty->termios.c_cflag & HUPCL)) + if (!pv->tty || (pv->tty->termios->c_cflag & HUPCL)) hvsilib_write_mctrl(pv, 0); /* Tear down the connection */ diff --git a/trunk/drivers/tty/ipwireless/network.c b/trunk/drivers/tty/ipwireless/network.c index d2af155dec8b..57c8b481113f 100644 --- a/trunk/drivers/tty/ipwireless/network.c +++ b/trunk/drivers/tty/ipwireless/network.c @@ -274,12 +274,7 @@ static void do_go_online(struct work_struct *work_go_online) network->xaccm[0] = ~0U; network->xaccm[3] = 0x60000000U; network->raccm = ~0U; - if (ppp_register_channel(channel) < 0) { - printk(KERN_ERR IPWIRELESS_PCCARD_NAME - ": unable to register PPP channel\n"); - kfree(channel); - return; - } + ppp_register_channel(channel); spin_lock_irqsave(&network->lock, flags); network->ppp_channel = channel; } diff --git a/trunk/drivers/tty/ipwireless/tty.c b/trunk/drivers/tty/ipwireless/tty.c index 160f0ad9589d..f8b5fa0093a3 100644 --- a/trunk/drivers/tty/ipwireless/tty.c +++ b/trunk/drivers/tty/ipwireless/tty.c @@ -476,7 +476,7 @@ static int add_tty(int j, mutex_init(&ttys[j]->ipw_tty_mutex); tty_port_init(&ttys[j]->port); - tty_port_register_device(&ttys[j]->port, ipw_tty_driver, j, NULL); + tty_register_device(ipw_tty_driver, j, NULL); ipwireless_associate_network_tty(network, channel_idx, ttys[j]); if (secondary_channel_idx != -1) diff --git a/trunk/drivers/tty/isicom.c b/trunk/drivers/tty/isicom.c index d7492e183607..e1235accab74 100644 --- a/trunk/drivers/tty/isicom.c +++ b/trunk/drivers/tty/isicom.c @@ -600,7 +600,7 @@ static irqreturn_t isicom_interrupt(int irq, void *dev_id) port->status &= ~ISI_DCD; } - if (tty_port_cts_enabled(&port->port)) { + if (port->port.flags & ASYNC_CTS_FLOW) { if (tty->hw_stopped) { if (header & ISI_CTS) { port->port.tty->hw_stopped = 0; @@ -702,7 +702,7 @@ static void isicom_config_port(struct tty_struct *tty) /* 1,2,3,4 => 57.6, 115.2, 230, 460 kbps resp. */ if (baud < 1 || baud > 4) - tty->termios.c_cflag &= ~CBAUDEX; + tty->termios->c_cflag &= ~CBAUDEX; else baud += 15; } @@ -1196,8 +1196,8 @@ static void isicom_set_termios(struct tty_struct *tty, if (isicom_paranoia_check(port, tty->name, "isicom_set_termios")) return; - if (tty->termios.c_cflag == old_termios->c_cflag && - tty->termios.c_iflag == old_termios->c_iflag) + if (tty->termios->c_cflag == old_termios->c_cflag && + tty->termios->c_iflag == old_termios->c_iflag) return; spin_lock_irqsave(&port->card->card_lock, flags); @@ -1205,7 +1205,7 @@ static void isicom_set_termios(struct tty_struct *tty, spin_unlock_irqrestore(&port->card->card_lock, flags); if ((old_termios->c_cflag & CRTSCTS) && - !(tty->termios.c_cflag & CRTSCTS)) { + !(tty->termios->c_cflag & CRTSCTS)) { tty->hw_stopped = 0; isicom_start(tty); } @@ -1611,8 +1611,7 @@ static int __devinit isicom_probe(struct pci_dev *pdev, goto errunri; for (index = 0; index < board->port_count; index++) - tty_port_register_device(&board->ports[index].port, - isicom_normal, board->index * 16 + index, + tty_register_device(isicom_normal, board->index * 16 + index, &pdev->dev); return 0; diff --git a/trunk/drivers/tty/moxa.c b/trunk/drivers/tty/moxa.c index 56e616b9109a..324467d28a54 100644 --- a/trunk/drivers/tty/moxa.c +++ b/trunk/drivers/tty/moxa.c @@ -169,7 +169,6 @@ static DEFINE_SPINLOCK(moxa_lock); static unsigned long baseaddr[MAX_BOARDS]; static unsigned int type[MAX_BOARDS]; static unsigned int numports[MAX_BOARDS]; -static struct tty_port moxa_service_port; MODULE_AUTHOR("William Chen"); MODULE_DESCRIPTION("MOXA Intellio Family Multiport Board Device Driver"); @@ -368,10 +367,10 @@ static int moxa_ioctl(struct tty_struct *tty, tmp.dcd = 1; ttyp = tty_port_tty_get(&p->port); - if (!ttyp) + if (!ttyp || !ttyp->termios) tmp.cflag = p->cflag; else - tmp.cflag = ttyp->termios.c_cflag; + tmp.cflag = ttyp->termios->c_cflag; tty_kref_put(ttyp); copy: if (copy_to_user(argm, &tmp, sizeof(tmp))) @@ -835,7 +834,7 @@ static int moxa_init_board(struct moxa_board_conf *brd, struct device *dev) const struct firmware *fw; const char *file; struct moxa_port *p; - unsigned int i, first_idx; + unsigned int i; int ret; brd->ports = kcalloc(MAX_PORTS_PER_BOARD, sizeof(*brd->ports), @@ -888,11 +887,6 @@ static int moxa_init_board(struct moxa_board_conf *brd, struct device *dev) mod_timer(&moxaTimer, jiffies + HZ / 50); spin_unlock_bh(&moxa_lock); - first_idx = (brd - moxa_boards) * MAX_PORTS_PER_BOARD; - for (i = 0; i < brd->numPorts; i++) - tty_port_register_device(&brd->ports[i].port, moxaDriver, - first_idx + i, dev); - return 0; err_free: kfree(brd->ports); @@ -902,7 +896,7 @@ static int moxa_init_board(struct moxa_board_conf *brd, struct device *dev) static void moxa_board_deinit(struct moxa_board_conf *brd) { - unsigned int a, opened, first_idx; + unsigned int a, opened; mutex_lock(&moxa_openlock); spin_lock_bh(&moxa_lock); @@ -931,10 +925,6 @@ static void moxa_board_deinit(struct moxa_board_conf *brd) mutex_lock(&moxa_openlock); } - first_idx = (brd - moxa_boards) * MAX_PORTS_PER_BOARD; - for (a = 0; a < brd->numPorts; a++) - tty_unregister_device(moxaDriver, first_idx + a); - iounmap(brd->basemem); brd->basemem = NULL; kfree(brd->ports); @@ -977,7 +967,6 @@ static int __devinit moxa_pci_probe(struct pci_dev *pdev, board->basemem = ioremap_nocache(pci_resource_start(pdev, 2), 0x4000); if (board->basemem == NULL) { dev_err(&pdev->dev, "can't remap io space 2\n"); - retval = -ENOMEM; goto err_reg; } @@ -1042,14 +1031,9 @@ static int __init moxa_init(void) printk(KERN_INFO "MOXA Intellio family driver version %s\n", MOXA_VERSION); - - tty_port_init(&moxa_service_port); - - moxaDriver = tty_alloc_driver(MAX_PORTS + 1, - TTY_DRIVER_REAL_RAW | - TTY_DRIVER_DYNAMIC_DEV); - if (IS_ERR(moxaDriver)) - return PTR_ERR(moxaDriver); + moxaDriver = alloc_tty_driver(MAX_PORTS + 1); + if (!moxaDriver) + return -ENOMEM; moxaDriver->name = "ttyMX"; moxaDriver->major = ttymajor; @@ -1060,9 +1044,8 @@ static int __init moxa_init(void) moxaDriver->init_termios.c_cflag = B9600 | CS8 | CREAD | CLOCAL | HUPCL; moxaDriver->init_termios.c_ispeed = 9600; moxaDriver->init_termios.c_ospeed = 9600; + moxaDriver->flags = TTY_DRIVER_REAL_RAW; tty_set_operations(moxaDriver, &moxa_ops); - /* Having one more port only for ioctls is ugly */ - tty_port_link_device(&moxa_service_port, moxaDriver, MAX_PORTS); if (tty_register_driver(moxaDriver)) { printk(KERN_ERR "can't register MOXA Smartio tty driver!\n"); @@ -1195,7 +1178,7 @@ static int moxa_open(struct tty_struct *tty, struct file *filp) mutex_lock(&ch->port.mutex); if (!(ch->port.flags & ASYNC_INITIALIZED)) { ch->statusflags = 0; - moxa_set_tty_param(tty, &tty->termios); + moxa_set_tty_param(tty, tty->termios); MoxaPortLineCtrl(ch, 1, 1); MoxaPortEnable(ch); MoxaSetFifo(ch, ch->type == PORT_16550A); @@ -1210,7 +1193,7 @@ static int moxa_open(struct tty_struct *tty, struct file *filp) static void moxa_close(struct tty_struct *tty, struct file *filp) { struct moxa_port *ch = tty->driver_data; - ch->cflag = tty->termios.c_cflag; + ch->cflag = tty->termios->c_cflag; tty_port_close(&ch->port, tty, filp); } @@ -1481,7 +1464,7 @@ static void moxa_poll(unsigned long ignored) static void moxa_set_tty_param(struct tty_struct *tty, struct ktermios *old_termios) { - register struct ktermios *ts = &tty->termios; + register struct ktermios *ts = tty->termios; struct moxa_port *ch = tty->driver_data; int rts, cts, txflow, rxflow, xany, baud; diff --git a/trunk/drivers/tty/mxser.c b/trunk/drivers/tty/mxser.c index cfda47dabd28..90cc680c4f0e 100644 --- a/trunk/drivers/tty/mxser.c +++ b/trunk/drivers/tty/mxser.c @@ -643,7 +643,7 @@ static int mxser_change_speed(struct tty_struct *tty, int ret = 0; unsigned char status; - cflag = tty->termios.c_cflag; + cflag = tty->termios->c_cflag; if (!info->ioaddr) return ret; @@ -830,7 +830,7 @@ static void mxser_check_modem_status(struct tty_struct *tty, wake_up_interruptible(&port->port.open_wait); } - if (tty_port_cts_enabled(&port->port)) { + if (port->port.flags & ASYNC_CTS_FLOW) { if (tty->hw_stopped) { if (status & UART_MSR_CTS) { tty->hw_stopped = 0; @@ -1520,10 +1520,10 @@ static int mxser_ioctl_special(unsigned int cmd, void __user *argp) tty = tty_port_tty_get(port); - if (!tty) + if (!tty || !tty->termios) ms.cflag = ip->normal_termios.c_cflag; else - ms.cflag = tty->termios.c_cflag; + ms.cflag = tty->termios->c_cflag; tty_kref_put(tty); spin_lock_irq(&ip->slock); status = inb(ip->ioaddr + UART_MSR); @@ -1589,13 +1589,13 @@ static int mxser_ioctl_special(unsigned int cmd, void __user *argp) tty = tty_port_tty_get(&ip->port); - if (!tty) { + if (!tty || !tty->termios) { cflag = ip->normal_termios.c_cflag; iflag = ip->normal_termios.c_iflag; me->baudrate[p] = tty_termios_baud_rate(&ip->normal_termios); } else { - cflag = tty->termios.c_cflag; - iflag = tty->termios.c_iflag; + cflag = tty->termios->c_cflag; + iflag = tty->termios->c_iflag; me->baudrate[p] = tty_get_baud_rate(tty); } tty_kref_put(tty); @@ -1853,7 +1853,7 @@ static void mxser_stoprx(struct tty_struct *tty) } } - if (tty->termios.c_cflag & CRTSCTS) { + if (tty->termios->c_cflag & CRTSCTS) { info->MCR &= ~UART_MCR_RTS; outb(info->MCR, info->ioaddr + UART_MCR); } @@ -1890,7 +1890,7 @@ static void mxser_unthrottle(struct tty_struct *tty) } } - if (tty->termios.c_cflag & CRTSCTS) { + if (tty->termios->c_cflag & CRTSCTS) { info->MCR |= UART_MCR_RTS; outb(info->MCR, info->ioaddr + UART_MCR); } @@ -1939,14 +1939,14 @@ static void mxser_set_termios(struct tty_struct *tty, struct ktermios *old_termi spin_unlock_irqrestore(&info->slock, flags); if ((old_termios->c_cflag & CRTSCTS) && - !(tty->termios.c_cflag & CRTSCTS)) { + !(tty->termios->c_cflag & CRTSCTS)) { tty->hw_stopped = 0; mxser_start(tty); } /* Handle sw stopped */ if ((old_termios->c_iflag & IXON) && - !(tty->termios.c_iflag & IXON)) { + !(tty->termios->c_iflag & IXON)) { tty->stopped = 0; if (info->board->chip_flag) { @@ -2337,36 +2337,11 @@ static struct tty_port_operations mxser_port_ops = { * The MOXA Smartio/Industio serial driver boot-time initialization code! */ -static bool allow_overlapping_vector; -module_param(allow_overlapping_vector, bool, S_IRUGO); -MODULE_PARM_DESC(allow_overlapping_vector, "whether we allow ISA cards to be configured such that vector overlabs IO ports (default=no)"); - -static bool mxser_overlapping_vector(struct mxser_board *brd) -{ - return allow_overlapping_vector && - brd->vector >= brd->ports[0].ioaddr && - brd->vector < brd->ports[0].ioaddr + 8 * brd->info->nports; -} - -static int mxser_request_vector(struct mxser_board *brd) -{ - if (mxser_overlapping_vector(brd)) - return 0; - return request_region(brd->vector, 1, "mxser(vector)") ? 0 : -EIO; -} - -static void mxser_release_vector(struct mxser_board *brd) -{ - if (mxser_overlapping_vector(brd)) - return; - release_region(brd->vector, 1); -} - static void mxser_release_ISA_res(struct mxser_board *brd) { free_irq(brd->irq, brd); release_region(brd->ports[0].ioaddr, 8 * brd->info->nports); - mxser_release_vector(brd); + release_region(brd->vector, 1); } static int __devinit mxser_initbrd(struct mxser_board *brd, @@ -2421,7 +2396,7 @@ static int __devinit mxser_initbrd(struct mxser_board *brd, static int __init mxser_get_ISA_conf(int cap, struct mxser_board *brd) { - int id, i, bits, ret; + int id, i, bits; unsigned short regs[16], irq; unsigned char scratch, scratch2; @@ -2517,15 +2492,13 @@ static int __init mxser_get_ISA_conf(int cap, struct mxser_board *brd) 8 * brd->info->nports - 1); return -EIO; } - - ret = mxser_request_vector(brd); - if (ret) { + if (!request_region(brd->vector, 1, "mxser(vector)")) { release_region(brd->ports[0].ioaddr, 8 * brd->info->nports); printk(KERN_ERR "mxser: can't request interrupt vector region: " "0x%.8lx-0x%.8lx\n", brd->ports[0].ioaddr, brd->ports[0].ioaddr + 8 * brd->info->nports - 1); - return ret; + return -EIO; } return brd->info->nports; @@ -2625,8 +2598,7 @@ static int __devinit mxser_probe(struct pci_dev *pdev, goto err_rel3; for (i = 0; i < brd->info->nports; i++) - tty_port_register_device(&brd->ports[i].port, mxvar_sdriver, - brd->idx + i, &pdev->dev); + tty_register_device(mxvar_sdriver, brd->idx + i, &pdev->dev); pci_set_drvdata(pdev, brd); @@ -2723,8 +2695,7 @@ static int __init mxser_module_init(void) brd->idx = m * MXSER_PORTS_PER_BOARD; for (i = 0; i < brd->info->nports; i++) - tty_port_register_device(&brd->ports[i].port, - mxvar_sdriver, brd->idx + i, NULL); + tty_register_device(mxvar_sdriver, brd->idx + i, NULL); m++; } diff --git a/trunk/drivers/tty/n_gsm.c b/trunk/drivers/tty/n_gsm.c index 1e8e8ce55959..c43b683b6eb8 100644 --- a/trunk/drivers/tty/n_gsm.c +++ b/trunk/drivers/tty/n_gsm.c @@ -108,7 +108,7 @@ struct gsm_mux_net { */ struct gsm_msg { - struct list_head list; + struct gsm_msg *next; u8 addr; /* DLCI address + flags */ u8 ctrl; /* Control byte + flags */ unsigned int len; /* Length of data block (can be zero) */ @@ -245,7 +245,8 @@ struct gsm_mux { unsigned int tx_bytes; /* TX data outstanding */ #define TX_THRESH_HI 8192 #define TX_THRESH_LO 2048 - struct list_head tx_list; /* Pending data packets */ + struct gsm_msg *tx_head; /* Pending data packets */ + struct gsm_msg *tx_tail; /* Control messages */ struct timer_list t2_timer; /* Retransmit timer for commands */ @@ -488,7 +489,7 @@ static void gsm_print_packet(const char *hdr, int addr, int cr, default: if (!(control & 0x01)) { pr_cont("I N(S)%d N(R)%d", - (control & 0x0E) >> 1, (control & 0xE0) >> 5); + (control & 0x0E) >> 1, (control & 0xE) >> 5); } else switch (control & 0x0F) { case RR: pr_cont("RR(%d)", (control & 0xE0) >> 5); @@ -662,7 +663,7 @@ static struct gsm_msg *gsm_data_alloc(struct gsm_mux *gsm, u8 addr, int len, m->len = len; m->addr = addr; m->ctrl = ctrl; - INIT_LIST_HEAD(&m->list); + m->next = NULL; return m; } @@ -672,21 +673,22 @@ static struct gsm_msg *gsm_data_alloc(struct gsm_mux *gsm, u8 addr, int len, * * The tty device has called us to indicate that room has appeared in * the transmit queue. Ram more data into the pipe if we have any - * If we have been flow-stopped by a CMD_FCOFF, then we can only - * send messages on DLCI0 until CMD_FCON * * FIXME: lock against link layer control transmissions */ static void gsm_data_kick(struct gsm_mux *gsm) { - struct gsm_msg *msg, *nmsg; + struct gsm_msg *msg = gsm->tx_head; int len; int skip_sof = 0; - list_for_each_entry_safe(msg, nmsg, &gsm->tx_list, list) { - if (gsm->constipated && msg->addr) - continue; + /* FIXME: We need to apply this solely to data messages */ + if (gsm->constipated) + return; + + while (gsm->tx_head != NULL) { + msg = gsm->tx_head; if (gsm->encoding != 0) { gsm->txframe[0] = GSM1_SOF; len = gsm_stuff_frame(msg->data, @@ -709,13 +711,14 @@ static void gsm_data_kick(struct gsm_mux *gsm) len - skip_sof) < 0) break; /* FIXME: Can eliminate one SOF in many more cases */ + gsm->tx_head = msg->next; + if (gsm->tx_head == NULL) + gsm->tx_tail = NULL; gsm->tx_bytes -= msg->len; + kfree(msg); /* For a burst of frames skip the extra SOF within the burst */ skip_sof = 1; - - list_del(&msg->list); - kfree(msg); } } @@ -765,7 +768,11 @@ static void __gsm_data_queue(struct gsm_dlci *dlci, struct gsm_msg *msg) msg->data = dp; /* Add to the actual output queue */ - list_add_tail(&msg->list, &gsm->tx_list); + if (gsm->tx_tail) + gsm->tx_tail->next = msg; + else + gsm->tx_head = msg; + gsm->tx_tail = msg; gsm->tx_bytes += msg->len; gsm_data_kick(gsm); } @@ -868,7 +875,7 @@ static int gsm_dlci_data_output_framed(struct gsm_mux *gsm, /* dlci->skb is locked by tx_lock */ if (dlci->skb == NULL) { - dlci->skb = skb_dequeue_tail(&dlci->skb_list); + dlci->skb = skb_dequeue(&dlci->skb_list); if (dlci->skb == NULL) return 0; first = 1; @@ -879,7 +886,7 @@ static int gsm_dlci_data_output_framed(struct gsm_mux *gsm, if (len > gsm->mtu) { if (dlci->adaption == 3) { /* Over long frame, bin it */ - dev_kfree_skb_any(dlci->skb); + kfree_skb(dlci->skb); dlci->skb = NULL; return 0; } @@ -892,11 +899,8 @@ static int gsm_dlci_data_output_framed(struct gsm_mux *gsm, /* FIXME: need a timer or something to kick this so it can't get stuck with no work outstanding and no buffer free */ - if (msg == NULL) { - skb_queue_tail(&dlci->skb_list, dlci->skb); - dlci->skb = NULL; + if (msg == NULL) return -ENOMEM; - } dp = msg->data; if (dlci->adaption == 4) { /* Interruptible framed (Packetised Data) */ @@ -908,7 +912,7 @@ static int gsm_dlci_data_output_framed(struct gsm_mux *gsm, skb_pull(dlci->skb, len); __gsm_data_queue(dlci, msg); if (last) { - dev_kfree_skb_any(dlci->skb); + kfree_skb(dlci->skb); dlci->skb = NULL; } return size; @@ -967,22 +971,16 @@ static void gsm_dlci_data_sweep(struct gsm_mux *gsm) static void gsm_dlci_data_kick(struct gsm_dlci *dlci) { unsigned long flags; - int sweep; - - if (dlci->constipated) - return; spin_lock_irqsave(&dlci->gsm->tx_lock, flags); /* If we have nothing running then we need to fire up */ - sweep = (dlci->gsm->tx_bytes < TX_THRESH_LO); if (dlci->gsm->tx_bytes == 0) { if (dlci->net) gsm_dlci_data_output_framed(dlci->gsm, dlci); else gsm_dlci_data_output(dlci->gsm, dlci); - } - if (sweep) - gsm_dlci_data_sweep(dlci->gsm); + } else if (dlci->gsm->tx_bytes < TX_THRESH_LO) + gsm_dlci_data_sweep(dlci->gsm); spin_unlock_irqrestore(&dlci->gsm->tx_lock, flags); } @@ -1029,7 +1027,6 @@ static void gsm_process_modem(struct tty_struct *tty, struct gsm_dlci *dlci, { int mlines = 0; u8 brk = 0; - int fc; /* The modem status command can either contain one octet (v.24 signals) or two octets (v.24 signals + break signals). The length field will @@ -1041,21 +1038,19 @@ static void gsm_process_modem(struct tty_struct *tty, struct gsm_dlci *dlci, else { brk = modem & 0x7f; modem = (modem >> 7) & 0x7f; - } + }; /* Flow control/ready to communicate */ - fc = (modem & MDM_FC) || !(modem & MDM_RTR); - if (fc && !dlci->constipated) { + if (modem & MDM_FC) { /* Need to throttle our output on this device */ dlci->constipated = 1; - } else if (!fc && dlci->constipated) { + } + if (modem & MDM_RTC) { + mlines |= TIOCM_DSR | TIOCM_DTR; dlci->constipated = 0; gsm_dlci_data_kick(dlci); } - /* Map modem bits */ - if (modem & MDM_RTC) - mlines |= TIOCM_DSR | TIOCM_DTR; if (modem & MDM_RTR) mlines |= TIOCM_RTS | TIOCM_CTS; if (modem & MDM_IC) @@ -1066,7 +1061,7 @@ static void gsm_process_modem(struct tty_struct *tty, struct gsm_dlci *dlci, /* Carrier drop -> hangup */ if (tty) { if ((mlines & TIOCM_CD) == 0 && (dlci->modem_rx & TIOCM_CD)) - if (!(tty->termios.c_cflag & CLOCAL)) + if (!(tty->termios->c_cflag & CLOCAL)) tty_hangup(tty); if (brk & 0x01) tty_insert_flip_char(tty, 0, TTY_BREAK); @@ -1195,8 +1190,6 @@ static void gsm_control_message(struct gsm_mux *gsm, unsigned int command, u8 *data, int clen) { u8 buf[1]; - unsigned long flags; - switch (command) { case CMD_CLD: { struct gsm_dlci *dlci = gsm->dlci[0]; @@ -1213,18 +1206,16 @@ static void gsm_control_message(struct gsm_mux *gsm, unsigned int command, gsm_control_reply(gsm, CMD_TEST, data, clen); break; case CMD_FCON: - /* Modem can accept data again */ - gsm->constipated = 0; + /* Modem wants us to STFU */ + gsm->constipated = 1; gsm_control_reply(gsm, CMD_FCON, NULL, 0); - /* Kick the link in case it is idling */ - spin_lock_irqsave(&gsm->tx_lock, flags); - gsm_data_kick(gsm); - spin_unlock_irqrestore(&gsm->tx_lock, flags); break; case CMD_FCOFF: - /* Modem wants us to STFU */ - gsm->constipated = 1; + /* Modem can accept data again */ + gsm->constipated = 0; gsm_control_reply(gsm, CMD_FCOFF, NULL, 0); + /* Kick the link in case it is idling */ + gsm_data_kick(gsm); break; case CMD_MSC: /* Out of band modem line change indicator for a DLCI */ @@ -1677,7 +1668,7 @@ static void gsm_dlci_free(struct kref *ref) dlci->gsm->dlci[dlci->addr] = NULL; kfifo_free(dlci->fifo); while ((dlci->skb = skb_dequeue(&dlci->skb_list))) - dev_kfree_skb(dlci->skb); + kfree_skb(dlci->skb); kfree(dlci); } @@ -2016,7 +2007,7 @@ void gsm_cleanup_mux(struct gsm_mux *gsm) { int i; struct gsm_dlci *dlci = gsm->dlci[0]; - struct gsm_msg *txq, *ntxq; + struct gsm_msg *txq; struct gsm_control *gc; gsm->dead = 1; @@ -2051,9 +2042,11 @@ void gsm_cleanup_mux(struct gsm_mux *gsm) if (gsm->dlci[i]) gsm_dlci_release(gsm->dlci[i]); /* Now wipe the queues */ - list_for_each_entry_safe(txq, ntxq, &gsm->tx_list, list) + for (txq = gsm->tx_head; txq != NULL; txq = gsm->tx_head) { + gsm->tx_head = txq->next; kfree(txq); - INIT_LIST_HEAD(&gsm->tx_list); + } + gsm->tx_tail = NULL; } EXPORT_SYMBOL_GPL(gsm_cleanup_mux); @@ -2164,7 +2157,6 @@ struct gsm_mux *gsm_alloc_mux(void) } spin_lock_init(&gsm->lock); kref_init(&gsm->ref); - INIT_LIST_HEAD(&gsm->tx_list); gsm->t1 = T1; gsm->t2 = T2; @@ -2281,7 +2273,7 @@ static void gsmld_receive_buf(struct tty_struct *tty, const unsigned char *cp, gsm->error(gsm, *dp, flags); break; default: - WARN_ONCE(1, "%s: unknown flag %d\n", + WARN_ONCE("%s: unknown flag %d\n", tty_name(tty, buf), flags); break; } @@ -2385,12 +2377,12 @@ static void gsmld_write_wakeup(struct tty_struct *tty) /* Queue poll */ clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags); - spin_lock_irqsave(&gsm->tx_lock, flags); gsm_data_kick(gsm); if (gsm->tx_bytes < TX_THRESH_LO) { + spin_lock_irqsave(&gsm->tx_lock, flags); gsm_dlci_data_sweep(gsm); + spin_unlock_irqrestore(&gsm->tx_lock, flags); } - spin_unlock_irqrestore(&gsm->tx_lock, flags); } /** @@ -2876,14 +2868,14 @@ static const struct tty_port_operations gsm_port_ops = { .dtr_rts = gsm_dtr_rts, }; -static int gsmtty_install(struct tty_driver *driver, struct tty_struct *tty) + +static int gsmtty_open(struct tty_struct *tty, struct file *filp) { struct gsm_mux *gsm; struct gsm_dlci *dlci; + struct tty_port *port; unsigned int line = tty->index; unsigned int mux = line >> 6; - bool alloc = false; - int ret; line = line & 0x3F; @@ -2897,35 +2889,14 @@ static int gsmtty_install(struct tty_driver *driver, struct tty_struct *tty) gsm = gsm_mux[mux]; if (gsm->dead) return -EL2HLT; - /* If DLCI 0 is not yet fully open return an error. This is ok from a locking - perspective as we don't have to worry about this if DLCI0 is lost */ - if (gsm->dlci[0] && gsm->dlci[0]->state != DLCI_OPEN) - return -EL2NSYNC; dlci = gsm->dlci[line]; - if (dlci == NULL) { - alloc = true; + if (dlci == NULL) dlci = gsm_dlci_alloc(gsm, line); - } if (dlci == NULL) return -ENOMEM; - ret = tty_port_install(&dlci->port, driver, tty); - if (ret) { - if (alloc) - dlci_put(dlci); - return ret; - } - - tty->driver_data = dlci; - - return 0; -} - -static int gsmtty_open(struct tty_struct *tty, struct file *filp) -{ - struct gsm_dlci *dlci = tty->driver_data; - struct tty_port *port = &dlci->port; - + port = &dlci->port; port->count++; + tty->driver_data = dlci; dlci_get(dlci); dlci_get(dlci->gsm->dlci[0]); mux_get(dlci->gsm); @@ -3072,13 +3043,13 @@ static void gsmtty_set_termios(struct tty_struct *tty, struct ktermios *old) the RPN control message. This however rapidly gets nasty as we then have to remap modem signals each way according to whether our virtual cable is null modem etc .. */ - tty_termios_copy_hw(&tty->termios, old); + tty_termios_copy_hw(tty->termios, old); } static void gsmtty_throttle(struct tty_struct *tty) { struct gsm_dlci *dlci = tty->driver_data; - if (tty->termios.c_cflag & CRTSCTS) + if (tty->termios->c_cflag & CRTSCTS) dlci->modem_tx &= ~TIOCM_DTR; dlci->throttled = 1; /* Send an MSC with DTR cleared */ @@ -3088,7 +3059,7 @@ static void gsmtty_throttle(struct tty_struct *tty) static void gsmtty_unthrottle(struct tty_struct *tty) { struct gsm_dlci *dlci = tty->driver_data; - if (tty->termios.c_cflag & CRTSCTS) + if (tty->termios->c_cflag & CRTSCTS) dlci->modem_tx |= TIOCM_DTR; dlci->throttled = 0; /* Send an MSC with DTR set */ @@ -3114,7 +3085,6 @@ static int gsmtty_break_ctl(struct tty_struct *tty, int state) /* Virtual ttys for the demux */ static const struct tty_operations gsmtty_ops = { - .install = gsmtty_install, .open = gsmtty_open, .close = gsmtty_close, .write = gsmtty_write, diff --git a/trunk/drivers/tty/n_r3964.c b/trunk/drivers/tty/n_r3964.c index 1e6405070ce6..5c6c31459a2f 100644 --- a/trunk/drivers/tty/n_r3964.c +++ b/trunk/drivers/tty/n_r3964.c @@ -1065,7 +1065,7 @@ static ssize_t r3964_read(struct tty_struct *tty, struct file *file, TRACE_L("read()"); - tty_lock(tty); + tty_lock(); pClient = findClient(pInfo, task_pid(current)); if (pClient) { @@ -1077,7 +1077,7 @@ static ssize_t r3964_read(struct tty_struct *tty, struct file *file, goto unlock; } /* block until there is a message: */ - wait_event_interruptible_tty(tty, pInfo->read_wait, + wait_event_interruptible_tty(pInfo->read_wait, (pMsg = remove_msg(pInfo, pClient))); } @@ -1107,7 +1107,7 @@ static ssize_t r3964_read(struct tty_struct *tty, struct file *file, } ret = -EPERM; unlock: - tty_unlock(tty); + tty_unlock(); return ret; } @@ -1156,7 +1156,7 @@ static ssize_t r3964_write(struct tty_struct *tty, struct file *file, pHeader->locks = 0; pHeader->owner = NULL; - tty_lock(tty); + tty_lock(); pClient = findClient(pInfo, task_pid(current)); if (pClient) { @@ -1175,7 +1175,7 @@ static ssize_t r3964_write(struct tty_struct *tty, struct file *file, add_tx_queue(pInfo, pHeader); trigger_transmit(pInfo); - tty_unlock(tty); + tty_unlock(); return 0; } diff --git a/trunk/drivers/tty/n_tty.c b/trunk/drivers/tty/n_tty.c index 8c0b7b42319c..ee1c268f5f9d 100644 --- a/trunk/drivers/tty/n_tty.c +++ b/trunk/drivers/tty/n_tty.c @@ -92,17 +92,9 @@ static inline int tty_put_user(struct tty_struct *tty, unsigned char x, static void n_tty_set_room(struct tty_struct *tty) { - int left; - int old_left; - /* tty->read_cnt is not read locked ? */ - if (I_PARMRK(tty)) { - /* Multiply read_cnt by 3, since each byte might take up to - * three times as many spaces when PARMRK is set (depending on - * its flags, e.g. parity error). */ - left = N_TTY_BUF_SIZE - tty->read_cnt * 3 - 1; - } else - left = N_TTY_BUF_SIZE - tty->read_cnt - 1; + int left = N_TTY_BUF_SIZE - tty->read_cnt - 1; + int old_left; /* * If we are doing input canonicalization, and there are no @@ -1440,12 +1432,6 @@ static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp, */ if (tty->receive_room < TTY_THRESHOLD_THROTTLE) tty_throttle(tty); - - /* FIXME: there is a tiny race here if the receive room check runs - before the other work executes and empties the buffer (upping - the receiving room and unthrottling. We then throttle and get - stuck. This has been observed and traced down by Vincent Pillet/ - We need to address this when we sort out out the rx path locking */ } int is_ignored(int sig) @@ -1474,7 +1460,7 @@ static void n_tty_set_termios(struct tty_struct *tty, struct ktermios *old) BUG_ON(!tty); if (old) - canon_change = (old->c_lflag ^ tty->termios.c_lflag) & ICANON; + canon_change = (old->c_lflag ^ tty->termios->c_lflag) & ICANON; if (canon_change) { memset(&tty->read_flags, 0, sizeof tty->read_flags); tty->canon_head = tty->read_tail; @@ -1742,8 +1728,7 @@ static ssize_t n_tty_read(struct tty_struct *tty, struct file *file, do_it_again: - if (WARN_ON(!tty->read_buf)) - return -EAGAIN; + BUG_ON(!tty->read_buf); c = job_control(tty, file); if (c < 0) @@ -1847,13 +1832,13 @@ static ssize_t n_tty_read(struct tty_struct *tty, struct file *file, if (tty->icanon && !L_EXTPROC(tty)) { /* N.B. avoid overrun if nr == 0 */ - spin_lock_irqsave(&tty->read_lock, flags); while (nr && tty->read_cnt) { int eol; eol = test_and_clear_bit(tty->read_tail, tty->read_flags); c = tty->read_buf[tty->read_tail]; + spin_lock_irqsave(&tty->read_lock, flags); tty->read_tail = ((tty->read_tail+1) & (N_TTY_BUF_SIZE-1)); tty->read_cnt--; @@ -1871,19 +1856,15 @@ static ssize_t n_tty_read(struct tty_struct *tty, struct file *file, if (tty_put_user(tty, c, b++)) { retval = -EFAULT; b--; - spin_lock_irqsave(&tty->read_lock, flags); break; } nr--; } if (eol) { tty_audit_push(tty); - spin_lock_irqsave(&tty->read_lock, flags); break; } - spin_lock_irqsave(&tty->read_lock, flags); } - spin_unlock_irqrestore(&tty->read_lock, flags); if (retval) break; } else { diff --git a/trunk/drivers/tty/nozomi.c b/trunk/drivers/tty/nozomi.c index b917c9424954..e7592f9037da 100644 --- a/trunk/drivers/tty/nozomi.c +++ b/trunk/drivers/tty/nozomi.c @@ -1473,8 +1473,8 @@ static int __devinit nozomi_card_init(struct pci_dev *pdev, port->dc = dc; tty_port_init(&port->port); port->port.ops = &noz_tty_port_ops; - tty_dev = tty_port_register_device(&port->port, ntty_driver, - dc->index_start + i, &pdev->dev); + tty_dev = tty_register_device(ntty_driver, dc->index_start + i, + &pdev->dev); if (IS_ERR(tty_dev)) { ret = PTR_ERR(tty_dev); diff --git a/trunk/drivers/tty/pty.c b/trunk/drivers/tty/pty.c index a82b39939a9c..5505ffc91da4 100644 --- a/trunk/drivers/tty/pty.c +++ b/trunk/drivers/tty/pty.c @@ -47,7 +47,6 @@ static void pty_close(struct tty_struct *tty, struct file *filp) wake_up_interruptible(&tty->read_wait); wake_up_interruptible(&tty->write_wait); tty->packet = 0; - /* Review - krefs on tty_link ?? */ if (!tty->link) return; tty->link->packet = 0; @@ -63,9 +62,9 @@ static void pty_close(struct tty_struct *tty, struct file *filp) mutex_unlock(&devpts_mutex); } #endif - tty_unlock(tty); + tty_unlock(); tty_vhangup(tty->link); - tty_lock(tty); + tty_lock(); } } @@ -232,8 +231,8 @@ static int pty_open(struct tty_struct *tty, struct file *filp) static void pty_set_termios(struct tty_struct *tty, struct ktermios *old_termios) { - tty->termios.c_cflag &= ~(CSIZE | PARENB); - tty->termios.c_cflag |= (CS8 | CREAD); + tty->termios->c_cflag &= ~(CSIZE | PARENB); + tty->termios->c_cflag |= (CS8 | CREAD); } /** @@ -283,110 +282,60 @@ int pty_resize(struct tty_struct *tty, struct winsize *ws) return 0; } -/** - * pty_common_install - set up the pty pair - * @driver: the pty driver - * @tty: the tty being instantiated - * @bool: legacy, true if this is BSD style - * - * Perform the initial set up for the tty/pty pair. Called from the - * tty layer when the port is first opened. - * - * Locking: the caller must hold the tty_mutex - */ -static int pty_common_install(struct tty_driver *driver, struct tty_struct *tty, - bool legacy) +/* Traditional BSD devices */ +#ifdef CONFIG_LEGACY_PTYS + +static int pty_install(struct tty_driver *driver, struct tty_struct *tty) { struct tty_struct *o_tty; - struct tty_port *ports[2]; int idx = tty->index; - int retval = -ENOMEM; + int retval; o_tty = alloc_tty_struct(); if (!o_tty) - goto err; - ports[0] = kmalloc(sizeof **ports, GFP_KERNEL); - ports[1] = kmalloc(sizeof **ports, GFP_KERNEL); - if (!ports[0] || !ports[1]) - goto err_free_tty; + return -ENOMEM; if (!try_module_get(driver->other->owner)) { /* This cannot in fact currently happen */ + retval = -ENOMEM; goto err_free_tty; } initialize_tty_struct(o_tty, driver->other, idx); - if (legacy) { - /* We always use new tty termios data so we can do this - the easy way .. */ - retval = tty_init_termios(tty); - if (retval) - goto err_deinit_tty; - - retval = tty_init_termios(o_tty); - if (retval) - goto err_free_termios; - - driver->other->ttys[idx] = o_tty; - driver->ttys[idx] = tty; - } else { - memset(&tty->termios_locked, 0, sizeof(tty->termios_locked)); - tty->termios = driver->init_termios; - memset(&o_tty->termios_locked, 0, sizeof(tty->termios_locked)); - o_tty->termios = driver->other->init_termios; - } + /* We always use new tty termios data so we can do this + the easy way .. */ + retval = tty_init_termios(tty); + if (retval) + goto err_deinit_tty; + + retval = tty_init_termios(o_tty); + if (retval) + goto err_free_termios; /* * Everything allocated ... set up the o_tty structure. */ + driver->other->ttys[idx] = o_tty; tty_driver_kref_get(driver->other); if (driver->subtype == PTY_TYPE_MASTER) o_tty->count++; /* Establish the links in both directions */ tty->link = o_tty; o_tty->link = tty; - tty_port_init(ports[0]); - tty_port_init(ports[1]); - o_tty->port = ports[0]; - tty->port = ports[1]; tty_driver_kref_get(driver); tty->count++; + driver->ttys[idx] = tty; return 0; err_free_termios: - if (legacy) - tty_free_termios(tty); + tty_free_termios(tty); err_deinit_tty: deinitialize_tty_struct(o_tty); module_put(o_tty->driver->owner); err_free_tty: - kfree(ports[0]); - kfree(ports[1]); free_tty_struct(o_tty); -err: return retval; } -static void pty_cleanup(struct tty_struct *tty) -{ - kfree(tty->port); -} - -/* Traditional BSD devices */ -#ifdef CONFIG_LEGACY_PTYS - -static int pty_install(struct tty_driver *driver, struct tty_struct *tty) -{ - return pty_common_install(driver, tty, true); -} - -static void pty_remove(struct tty_driver *driver, struct tty_struct *tty) -{ - struct tty_struct *pair = tty->link; - driver->ttys[tty->index] = NULL; - if (pair) - pair->driver->ttys[pair->index] = NULL; -} - static int pty_bsd_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg) { @@ -417,9 +366,7 @@ static const struct tty_operations master_pty_ops_bsd = { .unthrottle = pty_unthrottle, .set_termios = pty_set_termios, .ioctl = pty_bsd_ioctl, - .cleanup = pty_cleanup, - .resize = pty_resize, - .remove = pty_remove + .resize = pty_resize }; static const struct tty_operations slave_pty_ops_bsd = { @@ -432,9 +379,7 @@ static const struct tty_operations slave_pty_ops_bsd = { .chars_in_buffer = pty_chars_in_buffer, .unthrottle = pty_unthrottle, .set_termios = pty_set_termios, - .cleanup = pty_cleanup, - .resize = pty_resize, - .remove = pty_remove + .resize = pty_resize }; static void __init legacy_pty_init(void) @@ -444,18 +389,12 @@ static void __init legacy_pty_init(void) if (legacy_count <= 0) return; - pty_driver = tty_alloc_driver(legacy_count, - TTY_DRIVER_RESET_TERMIOS | - TTY_DRIVER_REAL_RAW | - TTY_DRIVER_DYNAMIC_ALLOC); - if (IS_ERR(pty_driver)) + pty_driver = alloc_tty_driver(legacy_count); + if (!pty_driver) panic("Couldn't allocate pty driver"); - pty_slave_driver = tty_alloc_driver(legacy_count, - TTY_DRIVER_RESET_TERMIOS | - TTY_DRIVER_REAL_RAW | - TTY_DRIVER_DYNAMIC_ALLOC); - if (IS_ERR(pty_slave_driver)) + pty_slave_driver = alloc_tty_driver(legacy_count); + if (!pty_slave_driver) panic("Couldn't allocate pty slave driver"); pty_driver->driver_name = "pty_master"; @@ -471,6 +410,7 @@ static void __init legacy_pty_init(void) pty_driver->init_termios.c_lflag = 0; pty_driver->init_termios.c_ispeed = 38400; pty_driver->init_termios.c_ospeed = 38400; + pty_driver->flags = TTY_DRIVER_RESET_TERMIOS | TTY_DRIVER_REAL_RAW; pty_driver->other = pty_slave_driver; tty_set_operations(pty_driver, &master_pty_ops_bsd); @@ -484,6 +424,8 @@ static void __init legacy_pty_init(void) pty_slave_driver->init_termios.c_cflag = B38400 | CS8 | CREAD; pty_slave_driver->init_termios.c_ispeed = 38400; pty_slave_driver->init_termios.c_ospeed = 38400; + pty_slave_driver->flags = TTY_DRIVER_RESET_TERMIOS | + TTY_DRIVER_REAL_RAW; pty_slave_driver->other = pty_driver; tty_set_operations(pty_slave_driver, &slave_pty_ops_bsd); @@ -555,22 +497,78 @@ static struct tty_struct *pts_unix98_lookup(struct tty_driver *driver, return tty; } +static void pty_unix98_shutdown(struct tty_struct *tty) +{ + tty_driver_remove_tty(tty->driver, tty); + /* We have our own method as we don't use the tty index */ + kfree(tty->termios); +} + /* We have no need to install and remove our tty objects as devpts does all the work for us */ static int pty_unix98_install(struct tty_driver *driver, struct tty_struct *tty) { - return pty_common_install(driver, tty, false); + struct tty_struct *o_tty; + int idx = tty->index; + + o_tty = alloc_tty_struct(); + if (!o_tty) + return -ENOMEM; + if (!try_module_get(driver->other->owner)) { + /* This cannot in fact currently happen */ + goto err_free_tty; + } + initialize_tty_struct(o_tty, driver->other, idx); + + tty->termios = kzalloc(sizeof(struct ktermios[2]), GFP_KERNEL); + if (tty->termios == NULL) + goto err_free_mem; + *tty->termios = driver->init_termios; + tty->termios_locked = tty->termios + 1; + + o_tty->termios = kzalloc(sizeof(struct ktermios[2]), GFP_KERNEL); + if (o_tty->termios == NULL) + goto err_free_mem; + *o_tty->termios = driver->other->init_termios; + o_tty->termios_locked = o_tty->termios + 1; + + tty_driver_kref_get(driver->other); + if (driver->subtype == PTY_TYPE_MASTER) + o_tty->count++; + /* Establish the links in both directions */ + tty->link = o_tty; + o_tty->link = tty; + /* + * All structures have been allocated, so now we install them. + * Failures after this point use release_tty to clean up, so + * there's no need to null out the local pointers. + */ + tty_driver_kref_get(driver); + tty->count++; + return 0; +err_free_mem: + deinitialize_tty_struct(o_tty); + kfree(o_tty->termios); + kfree(tty->termios); + module_put(o_tty->driver->owner); +err_free_tty: + free_tty_struct(o_tty); + return -ENOMEM; +} + +static void ptm_unix98_remove(struct tty_driver *driver, struct tty_struct *tty) +{ } -static void pty_unix98_remove(struct tty_driver *driver, struct tty_struct *tty) +static void pts_unix98_remove(struct tty_driver *driver, struct tty_struct *tty) { } static const struct tty_operations ptm_unix98_ops = { .lookup = ptm_unix98_lookup, .install = pty_unix98_install, - .remove = pty_unix98_remove, + .remove = ptm_unix98_remove, .open = pty_open, .close = pty_close, .write = pty_write, @@ -580,14 +578,14 @@ static const struct tty_operations ptm_unix98_ops = { .unthrottle = pty_unthrottle, .set_termios = pty_set_termios, .ioctl = pty_unix98_ioctl, - .resize = pty_resize, - .cleanup = pty_cleanup + .shutdown = pty_unix98_shutdown, + .resize = pty_resize }; static const struct tty_operations pty_unix98_ops = { .lookup = pts_unix98_lookup, .install = pty_unix98_install, - .remove = pty_unix98_remove, + .remove = pts_unix98_remove, .open = pty_open, .close = pty_close, .write = pty_write, @@ -596,7 +594,7 @@ static const struct tty_operations pty_unix98_ops = { .chars_in_buffer = pty_chars_in_buffer, .unthrottle = pty_unthrottle, .set_termios = pty_set_termios, - .cleanup = pty_cleanup, + .shutdown = pty_unix98_shutdown }; /** @@ -624,28 +622,26 @@ static int ptmx_open(struct inode *inode, struct file *filp) return retval; /* find a device that is not in use. */ - mutex_lock(&devpts_mutex); + tty_lock(); index = devpts_new_index(inode); + tty_unlock(); if (index < 0) { retval = index; - mutex_unlock(&devpts_mutex); goto err_file; } - mutex_unlock(&devpts_mutex); - mutex_lock(&tty_mutex); + mutex_lock(&devpts_mutex); tty = tty_init_dev(ptm_driver, index); + mutex_unlock(&devpts_mutex); + tty_lock(); + mutex_unlock(&tty_mutex); if (IS_ERR(tty)) { retval = PTR_ERR(tty); goto out; } - /* The tty returned here is locked so we can safely - drop the mutex */ - mutex_unlock(&tty_mutex); - set_bit(TTY_PTY_LOCK, &tty->flags); /* LOCK THE SLAVE */ tty_add_file(tty, filp); @@ -658,15 +654,15 @@ static int ptmx_open(struct inode *inode, struct file *filp) if (retval) goto err_release; - tty_unlock(tty); + tty_unlock(); return 0; err_release: - tty_unlock(tty); + tty_unlock(); tty_release(inode, filp); return retval; out: - mutex_unlock(&tty_mutex); devpts_kill_index(inode, index); + tty_unlock(); err_file: tty_free_file(filp); return retval; @@ -676,21 +672,11 @@ static struct file_operations ptmx_fops; static void __init unix98_pty_init(void) { - ptm_driver = tty_alloc_driver(NR_UNIX98_PTY_MAX, - TTY_DRIVER_RESET_TERMIOS | - TTY_DRIVER_REAL_RAW | - TTY_DRIVER_DYNAMIC_DEV | - TTY_DRIVER_DEVPTS_MEM | - TTY_DRIVER_DYNAMIC_ALLOC); - if (IS_ERR(ptm_driver)) + ptm_driver = alloc_tty_driver(NR_UNIX98_PTY_MAX); + if (!ptm_driver) panic("Couldn't allocate Unix98 ptm driver"); - pts_driver = tty_alloc_driver(NR_UNIX98_PTY_MAX, - TTY_DRIVER_RESET_TERMIOS | - TTY_DRIVER_REAL_RAW | - TTY_DRIVER_DYNAMIC_DEV | - TTY_DRIVER_DEVPTS_MEM | - TTY_DRIVER_DYNAMIC_ALLOC); - if (IS_ERR(pts_driver)) + pts_driver = alloc_tty_driver(NR_UNIX98_PTY_MAX); + if (!pts_driver) panic("Couldn't allocate Unix98 pts driver"); ptm_driver->driver_name = "pty_master"; @@ -706,6 +692,8 @@ static void __init unix98_pty_init(void) ptm_driver->init_termios.c_lflag = 0; ptm_driver->init_termios.c_ispeed = 38400; ptm_driver->init_termios.c_ospeed = 38400; + ptm_driver->flags = TTY_DRIVER_RESET_TERMIOS | TTY_DRIVER_REAL_RAW | + TTY_DRIVER_DYNAMIC_DEV | TTY_DRIVER_DEVPTS_MEM; ptm_driver->other = pts_driver; tty_set_operations(ptm_driver, &ptm_unix98_ops); @@ -719,6 +707,8 @@ static void __init unix98_pty_init(void) pts_driver->init_termios.c_cflag = B38400 | CS8 | CREAD; pts_driver->init_termios.c_ispeed = 38400; pts_driver->init_termios.c_ospeed = 38400; + pts_driver->flags = TTY_DRIVER_RESET_TERMIOS | TTY_DRIVER_REAL_RAW | + TTY_DRIVER_DYNAMIC_DEV | TTY_DRIVER_DEVPTS_MEM; pts_driver->other = ptm_driver; tty_set_operations(pts_driver, &pty_unix98_ops); diff --git a/trunk/drivers/tty/rocket.c b/trunk/drivers/tty/rocket.c index 9700d34b20a3..777d5f9cf6cc 100644 --- a/trunk/drivers/tty/rocket.c +++ b/trunk/drivers/tty/rocket.c @@ -704,8 +704,8 @@ static void init_r_port(int board, int aiop, int chan, struct pci_dev *pci_dev) spin_lock_init(&info->slock); mutex_init(&info->write_mtx); rp_table[line] = info; - tty_port_register_device(&info->port, rocket_driver, line, - pci_dev ? &pci_dev->dev : NULL); + tty_register_device(rocket_driver, line, pci_dev ? &pci_dev->dev : + NULL); } /* @@ -720,7 +720,7 @@ static void configure_r_port(struct tty_struct *tty, struct r_port *info, unsigned rocketMode; int bits, baud, divisor; CHANNEL_t *cp; - struct ktermios *t = &tty->termios; + struct ktermios *t = tty->termios; cp = &info->channel; cflag = t->c_cflag; @@ -978,7 +978,7 @@ static int rp_open(struct tty_struct *tty, struct file *filp) tty->alt_speed = 460800; configure_r_port(tty, info, NULL); - if (tty->termios.c_cflag & CBAUD) { + if (tty->termios->c_cflag & CBAUD) { sSetDTR(cp); sSetRTS(cp); } @@ -1089,35 +1089,35 @@ static void rp_set_termios(struct tty_struct *tty, if (rocket_paranoia_check(info, "rp_set_termios")) return; - cflag = tty->termios.c_cflag; + cflag = tty->termios->c_cflag; /* * This driver doesn't support CS5 or CS6 */ if (((cflag & CSIZE) == CS5) || ((cflag & CSIZE) == CS6)) - tty->termios.c_cflag = + tty->termios->c_cflag = ((cflag & ~CSIZE) | (old_termios->c_cflag & CSIZE)); /* Or CMSPAR */ - tty->termios.c_cflag &= ~CMSPAR; + tty->termios->c_cflag &= ~CMSPAR; configure_r_port(tty, info, old_termios); cp = &info->channel; /* Handle transition to B0 status */ - if ((old_termios->c_cflag & CBAUD) && !(tty->termios.c_cflag & CBAUD)) { + if ((old_termios->c_cflag & CBAUD) && !(tty->termios->c_cflag & CBAUD)) { sClrDTR(cp); sClrRTS(cp); } /* Handle transition away from B0 status */ - if (!(old_termios->c_cflag & CBAUD) && (tty->termios.c_cflag & CBAUD)) { - if (!tty->hw_stopped || !(tty->termios.c_cflag & CRTSCTS)) + if (!(old_termios->c_cflag & CBAUD) && (tty->termios->c_cflag & CBAUD)) { + if (!tty->hw_stopped || !(tty->termios->c_cflag & CRTSCTS)) sSetRTS(cp); sSetDTR(cp); } - if ((old_termios->c_cflag & CRTSCTS) && !(tty->termios.c_cflag & CRTSCTS)) { + if ((old_termios->c_cflag & CRTSCTS) && !(tty->termios->c_cflag & CRTSCTS)) { tty->hw_stopped = 0; rp_start(tty); } diff --git a/trunk/drivers/tty/serial/68328serial.c b/trunk/drivers/tty/serial/68328serial.c index 66c38a3f74ce..3ed20e435e59 100644 --- a/trunk/drivers/tty/serial/68328serial.c +++ b/trunk/drivers/tty/serial/68328serial.c @@ -515,7 +515,7 @@ static void change_speed(struct m68k_serial *info, struct tty_struct *tty) unsigned cflag; int i; - cflag = tty->termios.c_cflag; + cflag = tty->termios->c_cflag; if (!(port = info->port)) return; @@ -617,7 +617,7 @@ static void rs_set_ldisc(struct tty_struct *tty) if (serial_paranoia_check(info, tty->name, "rs_set_ldisc")) return; - info->is_cons = (tty->termios.c_line == N_TTY); + info->is_cons = (tty->termios->c_line == N_TTY); printk("ttyS%d console mode %s\n", info->line, info->is_cons ? "on" : "off"); } @@ -985,7 +985,7 @@ static void rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios) change_speed(info, tty); if ((old_termios->c_cflag & CRTSCTS) && - !(tty->termios.c_cflag & CRTSCTS)) { + !(tty->termios->c_cflag & CRTSCTS)) { tty->hw_stopped = 0; rs_start(tty); } @@ -1070,7 +1070,7 @@ static void rs_close(struct tty_struct *tty, struct file * filp) if (tty->ldisc.close) (tty->ldisc.close)(tty); tty->ldisc = ldiscs[N_TTY]; - tty->termios.c_line = N_TTY; + tty->termios->c_line = N_TTY; if (tty->ldisc.open) (tty->ldisc.open)(tty); } @@ -1189,6 +1189,12 @@ rs68328_init(void) serial_driver->flags = TTY_DRIVER_REAL_RAW; tty_set_operations(serial_driver, &rs_ops); + if (tty_register_driver(serial_driver)) { + put_tty_driver(serial_driver); + printk(KERN_ERR "Couldn't register serial driver\n"); + return -ENOMEM; + } + local_irq_save(flags); for(i=0;itport, serial_driver, i); } local_irq_restore(flags); - - if (tty_register_driver(serial_driver)) { - put_tty_driver(serial_driver); - printk(KERN_ERR "Couldn't register serial driver\n"); - return -ENOMEM; - } - return 0; } diff --git a/trunk/drivers/tty/serial/8250/8250.c b/trunk/drivers/tty/serial/8250/8250.c index 3ba4234592bc..8123f784bcda 100644 --- a/trunk/drivers/tty/serial/8250/8250.c +++ b/trunk/drivers/tty/serial/8250/8250.c @@ -290,9 +290,6 @@ static const struct serial8250_config uart_config[] = { UART_FCR_R_TRIG_00 | UART_FCR_T_TRIG_00, .flags = UART_CAP_FIFO, }, - [PORT_8250_CIR] = { - .name = "CIR port" - } }; /* Uart divisor latch read */ @@ -1040,7 +1037,6 @@ static void autoconfig(struct uart_8250_port *up, unsigned int probeflags) unsigned char save_lcr, save_mcr; struct uart_port *port = &up->port; unsigned long flags; - unsigned int old_capabilities; if (!port->iobase && !port->mapbase && !port->membase) return; @@ -1091,7 +1087,6 @@ static void autoconfig(struct uart_8250_port *up, unsigned int probeflags) /* * We failed; there's nothing here */ - spin_unlock_irqrestore(&port->lock, flags); DEBUG_AUTOCONF("IER test failed (%02x, %02x) ", scratch2, scratch3); goto out; @@ -1115,7 +1110,6 @@ static void autoconfig(struct uart_8250_port *up, unsigned int probeflags) status1 = serial_in(up, UART_MSR) & 0xF0; serial_out(up, UART_MCR, save_mcr); if (status1 != 0x90) { - spin_unlock_irqrestore(&port->lock, flags); DEBUG_AUTOCONF("LOOP test failed (%02x) ", status1); goto out; @@ -1138,6 +1132,8 @@ static void autoconfig(struct uart_8250_port *up, unsigned int probeflags) serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO); scratch = serial_in(up, UART_IIR) >> 6; + DEBUG_AUTOCONF("iir=%d ", scratch); + switch (scratch) { case 0: autoconfig_8250(up); @@ -1171,13 +1167,19 @@ static void autoconfig(struct uart_8250_port *up, unsigned int probeflags) serial_out(up, UART_LCR, save_lcr); + if (up->capabilities != uart_config[port->type].flags) { + printk(KERN_WARNING + "ttyS%d: detected caps %08x should be %08x\n", + serial_index(port), up->capabilities, + uart_config[port->type].flags); + } + port->fifosize = uart_config[up->port.type].fifo_size; - old_capabilities = up->capabilities; up->capabilities = uart_config[port->type].flags; up->tx_loadsz = uart_config[port->type].tx_loadsz; if (port->type == PORT_UNKNOWN) - goto out_lock; + goto out; /* * Reset the UART. @@ -1194,16 +1196,8 @@ static void autoconfig(struct uart_8250_port *up, unsigned int probeflags) else serial_out(up, UART_IER, 0); -out_lock: + out: spin_unlock_irqrestore(&port->lock, flags); - if (up->capabilities != old_capabilities) { - printk(KERN_WARNING - "ttyS%d: detected caps %08x should be %08x\n", - serial_index(port), old_capabilities, - up->capabilities); - } -out: - DEBUG_AUTOCONF("iir=%d ", scratch); DEBUG_AUTOCONF("type=%s\n", uart_config[port->type].name); } @@ -1903,9 +1897,6 @@ static int serial8250_startup(struct uart_port *port) unsigned char lsr, iir; int retval; - if (port->type == PORT_8250_CIR) - return -ENODEV; - port->fifosize = uart_config[up->port.type].fifo_size; up->tx_loadsz = uart_config[up->port.type].tx_loadsz; up->capabilities = uart_config[up->port.type].flags; @@ -2211,7 +2202,6 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios, unsigned char cval, fcr = 0; unsigned long flags; unsigned int baud, quot; - int fifo_bug = 0; switch (termios->c_cflag & CSIZE) { case CS5: @@ -2231,11 +2221,8 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios, if (termios->c_cflag & CSTOPB) cval |= UART_LCR_STOP; - if (termios->c_cflag & PARENB) { + if (termios->c_cflag & PARENB) cval |= UART_LCR_PARITY; - if (up->bugs & UART_BUG_PARITY) - fifo_bug = 1; - } if (!(termios->c_cflag & PARODD)) cval |= UART_LCR_EPAR; #ifdef CMSPAR @@ -2259,7 +2246,7 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios, if (up->capabilities & UART_CAP_FIFO && port->fifosize > 1) { fcr = uart_config[port->type].fcr; - if (baud < 2400 || fifo_bug) { + if (baud < 2400) { fcr &= ~UART_FCR_TRIGGER_MASK; fcr |= UART_FCR_TRIGGER_1; } @@ -2349,7 +2336,7 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios, serial_port_out(port, UART_EFR, efr); } -#ifdef CONFIG_ARCH_OMAP1 +#ifdef CONFIG_ARCH_OMAP /* Workaround to enable 115200 baud on OMAP1510 internal ports */ if (cpu_is_omap1510() && is_omap_port(up)) { if (baud == 115200) { @@ -2439,7 +2426,7 @@ static unsigned int serial8250_port_size(struct uart_8250_port *pt) { if (pt->port.iotype == UPIO_AU) return 0x1000; -#ifdef CONFIG_ARCH_OMAP1 +#ifdef CONFIG_ARCH_OMAP if (is_omap_port(pt)) return 0x16 << pt->port.regshift; #endif @@ -2563,10 +2550,7 @@ static int serial8250_request_port(struct uart_port *port) { struct uart_8250_port *up = container_of(port, struct uart_8250_port, port); - int ret; - - if (port->type == PORT_8250_CIR) - return -ENODEV; + int ret = 0; ret = serial8250_request_std_resource(up); if (ret == 0 && port->type == PORT_RSA) { @@ -2585,9 +2569,6 @@ static void serial8250_config_port(struct uart_port *port, int flags) int probeflags = PROBE_ANY; int ret; - if (port->type == PORT_8250_CIR) - return; - /* * Find the region that we can probe for. This in turn * tells us whether we can probe for the type of port. @@ -2687,9 +2668,6 @@ static void __init serial8250_isa_init_ports(void) return; first = 0; - if (nr_uarts > UART_NR) - nr_uarts = UART_NR; - for (i = 0; i < nr_uarts; i++) { struct uart_8250_port *up = &serial8250_ports[i]; struct uart_port *port = &up->port; @@ -2699,7 +2677,6 @@ static void __init serial8250_isa_init_ports(void) init_timer(&up->timer); up->timer.function = serial8250_timeout; - up->cur_iotype = 0xFF; /* * ALPHA_KLUDGE_MCR needs to be killed. @@ -2751,9 +2728,13 @@ serial8250_register_ports(struct uart_driver *drv, struct device *dev) for (i = 0; i < nr_uarts; i++) { struct uart_8250_port *up = &serial8250_ports[i]; + up->cur_iotype = 0xFF; + } - if (up->port.dev) - continue; + serial8250_isa_init_ports(); + + for (i = 0; i < nr_uarts; i++) { + struct uart_8250_port *up = &serial8250_ports[i]; up->port.dev = dev; @@ -2878,6 +2859,9 @@ static struct console serial8250_console = { static int __init serial8250_console_init(void) { + if (nr_uarts > UART_NR) + nr_uarts = UART_NR; + serial8250_isa_init_ports(); register_console(&serial8250_console); return 0; @@ -2995,36 +2979,36 @@ void serial8250_resume_port(int line) static int __devinit serial8250_probe(struct platform_device *dev) { struct plat_serial8250_port *p = dev->dev.platform_data; - struct uart_8250_port uart; + struct uart_port port; int ret, i, irqflag = 0; - memset(&uart, 0, sizeof(uart)); + memset(&port, 0, sizeof(struct uart_port)); if (share_irqs) irqflag = IRQF_SHARED; for (i = 0; p && p->flags != 0; p++, i++) { - uart.port.iobase = p->iobase; - uart.port.membase = p->membase; - uart.port.irq = p->irq; - uart.port.irqflags = p->irqflags; - uart.port.uartclk = p->uartclk; - uart.port.regshift = p->regshift; - uart.port.iotype = p->iotype; - uart.port.flags = p->flags; - uart.port.mapbase = p->mapbase; - uart.port.hub6 = p->hub6; - uart.port.private_data = p->private_data; - uart.port.type = p->type; - uart.port.serial_in = p->serial_in; - uart.port.serial_out = p->serial_out; - uart.port.handle_irq = p->handle_irq; - uart.port.handle_break = p->handle_break; - uart.port.set_termios = p->set_termios; - uart.port.pm = p->pm; - uart.port.dev = &dev->dev; - uart.port.irqflags |= irqflag; - ret = serial8250_register_8250_port(&uart); + port.iobase = p->iobase; + port.membase = p->membase; + port.irq = p->irq; + port.irqflags = p->irqflags; + port.uartclk = p->uartclk; + port.regshift = p->regshift; + port.iotype = p->iotype; + port.flags = p->flags; + port.mapbase = p->mapbase; + port.hub6 = p->hub6; + port.private_data = p->private_data; + port.type = p->type; + port.serial_in = p->serial_in; + port.serial_out = p->serial_out; + port.handle_irq = p->handle_irq; + port.handle_break = p->handle_break; + port.set_termios = p->set_termios; + port.pm = p->pm; + port.dev = &dev->dev; + port.irqflags |= irqflag; + ret = serial8250_register_port(&port); if (ret < 0) { dev_err(&dev->dev, "unable to register port at index %d " "(IO%lx MEM%llx IRQ%d): %d\n", i, @@ -3097,7 +3081,7 @@ static struct platform_driver serial8250_isa_driver = { static struct platform_device *serial8250_isa_devs; /* - * serial8250_register_8250_port and serial8250_unregister_port allows for + * serial8250_register_port and serial8250_unregister_port allows for * 16x50 serial ports to be configured at run-time, to support PCMCIA * modems and PCI multiport cards. */ @@ -3159,9 +3143,8 @@ int serial8250_register_8250_port(struct uart_8250_port *up) mutex_lock(&serial_mutex); uart = serial8250_find_match_or_unused(&up->port); - if (uart && uart->port.type != PORT_8250_CIR) { - if (uart->port.dev) - uart_remove_one_port(&serial8250_reg, &uart->port); + if (uart) { + uart_remove_one_port(&serial8250_reg, &uart->port); uart->port.iobase = up->port.iobase; uart->port.membase = up->port.membase; @@ -3172,7 +3155,6 @@ int serial8250_register_8250_port(struct uart_8250_port *up) uart->port.regshift = up->port.regshift; uart->port.iotype = up->port.iotype; uart->port.flags = up->port.flags | UPF_BOOT_AUTOCONF; - uart->bugs = up->bugs; uart->port.mapbase = up->port.mapbase; uart->port.private_data = up->port.private_data; if (up->port.dev) @@ -3215,6 +3197,29 @@ int serial8250_register_8250_port(struct uart_8250_port *up) } EXPORT_SYMBOL(serial8250_register_8250_port); +/** + * serial8250_register_port - register a serial port + * @port: serial port template + * + * Configure the serial port specified by the request. If the + * port exists and is in use, it is hung up and unregistered + * first. + * + * The port is then probed and if necessary the IRQ is autodetected + * If this fails an error is returned. + * + * On success the port is ready to use and the line number is returned. + */ +int serial8250_register_port(struct uart_port *port) +{ + struct uart_8250_port up; + + memset(&up, 0, sizeof(up)); + memcpy(&up.port, port, sizeof(*port)); + return serial8250_register_8250_port(&up); +} +EXPORT_SYMBOL(serial8250_register_port); + /** * serial8250_unregister_port - remove a 16x50 serial port at runtime * @line: serial line number @@ -3245,7 +3250,8 @@ static int __init serial8250_init(void) { int ret; - serial8250_isa_init_ports(); + if (nr_uarts > UART_NR) + nr_uarts = UART_NR; printk(KERN_INFO "Serial: 8250/16550 driver, " "%d ports, IRQ sharing %sabled\n", nr_uarts, @@ -3260,15 +3266,11 @@ static int __init serial8250_init(void) if (ret) goto out; - ret = serial8250_pnp_init(); - if (ret) - goto unreg_uart_drv; - serial8250_isa_devs = platform_device_alloc("serial8250", PLAT8250_DEV_LEGACY); if (!serial8250_isa_devs) { ret = -ENOMEM; - goto unreg_pnp; + goto unreg_uart_drv; } ret = platform_device_add(serial8250_isa_devs); @@ -3284,8 +3286,6 @@ static int __init serial8250_init(void) platform_device_del(serial8250_isa_devs); put_dev: platform_device_put(serial8250_isa_devs); -unreg_pnp: - serial8250_pnp_exit(); unreg_uart_drv: #ifdef CONFIG_SPARC sunserial_unregister_minors(&serial8250_reg, UART_NR); @@ -3310,8 +3310,6 @@ static void __exit serial8250_exit(void) platform_driver_unregister(&serial8250_isa_driver); platform_device_unregister(isa_dev); - serial8250_pnp_exit(); - #ifdef CONFIG_SPARC sunserial_unregister_minors(&serial8250_reg, UART_NR); #else diff --git a/trunk/drivers/tty/serial/8250/8250.h b/trunk/drivers/tty/serial/8250/8250.h index 5a76f9c8d36b..f9719d167c8d 100644 --- a/trunk/drivers/tty/serial/8250/8250.h +++ b/trunk/drivers/tty/serial/8250/8250.h @@ -13,6 +13,36 @@ #include +struct uart_8250_port { + struct uart_port port; + struct timer_list timer; /* "no irq" timer */ + struct list_head list; /* ports on this IRQ */ + unsigned short capabilities; /* port capabilities */ + unsigned short bugs; /* port bugs */ + unsigned int tx_loadsz; /* transmit fifo load size */ + unsigned char acr; + unsigned char ier; + unsigned char lcr; + unsigned char mcr; + unsigned char mcr_mask; /* mask of user bits */ + unsigned char mcr_force; /* mask of forced bits */ + unsigned char cur_iotype; /* Running I/O type */ + + /* + * Some bits in registers are cleared on a read, so they must + * be saved whenever the register is read but the bits will not + * be immediately processed. + */ +#define LSR_SAVE_FLAGS UART_LSR_BRK_ERROR_BITS + unsigned char lsr_saved_flags; +#define MSR_SAVE_FLAGS UART_MSR_ANY_DELTA + unsigned char msr_saved_flags; + + /* 8250 specific callbacks */ + int (*dl_read)(struct uart_8250_port *); + void (*dl_write)(struct uart_8250_port *, int); +}; + struct old_serial_port { unsigned int uart; unsigned int baud_base; @@ -26,6 +56,9 @@ struct old_serial_port { unsigned long irqflags; }; +/* + * This replaces serial_uart_config in include/linux/serial.h + */ struct serial8250_config { const char *name; unsigned short fifo_size; @@ -45,7 +78,6 @@ struct serial8250_config { #define UART_BUG_TXEN (1 << 1) /* UART has buggy TX IIR status */ #define UART_BUG_NOMSR (1 << 2) /* UART has buggy MSR status bits (Au1x00) */ #define UART_BUG_THRE (1 << 3) /* UART has buggy THRE reassertion */ -#define UART_BUG_PARITY (1 << 4) /* UART mishandles parity if FIFO enabled */ #define PROBE_RSA (1 << 0) #define PROBE_ANY (~0) @@ -97,12 +129,3 @@ static inline void serial_dl_write(struct uart_8250_port *up, int value) #else #define ALPHA_KLUDGE_MCR 0 #endif - -#ifdef CONFIG_SERIAL_8250_PNP -int serial8250_pnp_init(void); -void serial8250_pnp_exit(void); -#else -static inline int serial8250_pnp_init(void) { return 0; } -static inline void serial8250_pnp_exit(void) { } -#endif - diff --git a/trunk/drivers/tty/serial/8250/8250_acorn.c b/trunk/drivers/tty/serial/8250/8250_acorn.c index 857498312a9a..b0ce8c56f1a4 100644 --- a/trunk/drivers/tty/serial/8250/8250_acorn.c +++ b/trunk/drivers/tty/serial/8250/8250_acorn.c @@ -43,7 +43,7 @@ serial_card_probe(struct expansion_card *ec, const struct ecard_id *id) { struct serial_card_info *info; struct serial_card_type *type = id->data; - struct uart_8250_port uart; + struct uart_port port; unsigned long bus_addr; unsigned int i; @@ -62,19 +62,19 @@ serial_card_probe(struct expansion_card *ec, const struct ecard_id *id) ecard_set_drvdata(ec, info); - memset(&uart, 0, sizeof(struct uart_8250_port)); - uart.port.irq = ec->irq; - uart.port.flags = UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ; - uart.port.uartclk = type->uartclk; - uart.port.iotype = UPIO_MEM; - uart.port.regshift = 2; - uart.port.dev = &ec->dev; + memset(&port, 0, sizeof(struct uart_port)); + port.irq = ec->irq; + port.flags = UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ; + port.uartclk = type->uartclk; + port.iotype = UPIO_MEM; + port.regshift = 2; + port.dev = &ec->dev; for (i = 0; i < info->num_ports; i ++) { - uart.port.membase = info->vaddr + type->offset[i]; - uart.port.mapbase = bus_addr + type->offset[i]; + port.membase = info->vaddr + type->offset[i]; + port.mapbase = bus_addr + type->offset[i]; - info->ports[i] = serial8250_register_8250_port(&uart); + info->ports[i] = serial8250_register_port(&port); } return 0; diff --git a/trunk/drivers/tty/serial/8250/8250_dw.c b/trunk/drivers/tty/serial/8250/8250_dw.c index c3b2ec0c8c0b..f574eef3075f 100644 --- a/trunk/drivers/tty/serial/8250/8250_dw.c +++ b/trunk/drivers/tty/serial/8250/8250_dw.c @@ -89,7 +89,7 @@ static int dw8250_handle_irq(struct uart_port *p) static int __devinit dw8250_probe(struct platform_device *pdev) { - struct uart_8250_port uart = {}; + struct uart_port port = {}; struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); struct resource *irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); struct device_node *np = pdev->dev.of_node; @@ -104,28 +104,28 @@ static int __devinit dw8250_probe(struct platform_device *pdev) data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); if (!data) return -ENOMEM; - uart.port.private_data = data; - - spin_lock_init(&uart.port.lock); - uart.port.mapbase = regs->start; - uart.port.irq = irq->start; - uart.port.handle_irq = dw8250_handle_irq; - uart.port.type = PORT_8250; - uart.port.flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF | UPF_IOREMAP | + port.private_data = data; + + spin_lock_init(&port.lock); + port.mapbase = regs->start; + port.irq = irq->start; + port.handle_irq = dw8250_handle_irq; + port.type = PORT_8250; + port.flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF | UPF_IOREMAP | UPF_FIXED_PORT | UPF_FIXED_TYPE; - uart.port.dev = &pdev->dev; + port.dev = &pdev->dev; - uart.port.iotype = UPIO_MEM; - uart.port.serial_in = dw8250_serial_in; - uart.port.serial_out = dw8250_serial_out; + port.iotype = UPIO_MEM; + port.serial_in = dw8250_serial_in; + port.serial_out = dw8250_serial_out; if (!of_property_read_u32(np, "reg-io-width", &val)) { switch (val) { case 1: break; case 4: - uart.port.iotype = UPIO_MEM32; - uart.port.serial_in = dw8250_serial_in32; - uart.port.serial_out = dw8250_serial_out32; + port.iotype = UPIO_MEM32; + port.serial_in = dw8250_serial_in32; + port.serial_out = dw8250_serial_out32; break; default: dev_err(&pdev->dev, "unsupported reg-io-width (%u)\n", @@ -135,15 +135,15 @@ static int __devinit dw8250_probe(struct platform_device *pdev) } if (!of_property_read_u32(np, "reg-shift", &val)) - uart.port.regshift = val; + port.regshift = val; if (of_property_read_u32(np, "clock-frequency", &val)) { dev_err(&pdev->dev, "no clock-frequency property set\n"); return -EINVAL; } - uart.port.uartclk = val; + port.uartclk = val; - data->line = serial8250_register_8250_port(&uart); + data->line = serial8250_register_port(&port); if (data->line < 0) return data->line; diff --git a/trunk/drivers/tty/serial/8250/8250_gsc.c b/trunk/drivers/tty/serial/8250/8250_gsc.c index 097dff9c08ad..d8c0ffbfa6e3 100644 --- a/trunk/drivers/tty/serial/8250/8250_gsc.c +++ b/trunk/drivers/tty/serial/8250/8250_gsc.c @@ -26,7 +26,7 @@ static int __init serial_init_chip(struct parisc_device *dev) { - struct uart_8250_port uart; + struct uart_port port; unsigned long address; int err; @@ -48,21 +48,21 @@ static int __init serial_init_chip(struct parisc_device *dev) if (dev->id.sversion != 0x8d) address += 0x800; - memset(&uart, 0, sizeof(uart)); - uart.port.iotype = UPIO_MEM; + memset(&port, 0, sizeof(port)); + port.iotype = UPIO_MEM; /* 7.272727MHz on Lasi. Assumed the same for Dino, Wax and Timi. */ - uart.port.uartclk = 7272727; - uart.port.mapbase = address; - uart.port.membase = ioremap_nocache(address, 16); - uart.port.irq = dev->irq; - uart.port.flags = UPF_BOOT_AUTOCONF; - uart.port.dev = &dev->dev; - - err = serial8250_register_8250_port(&uart); + port.uartclk = 7272727; + port.mapbase = address; + port.membase = ioremap_nocache(address, 16); + port.irq = dev->irq; + port.flags = UPF_BOOT_AUTOCONF; + port.dev = &dev->dev; + + err = serial8250_register_port(&port); if (err < 0) { printk(KERN_WARNING - "serial8250_register_8250_port returned error %d\n", err); - iounmap(uart.port.membase); + "serial8250_register_port returned error %d\n", err); + iounmap(port.membase); return err; } diff --git a/trunk/drivers/tty/serial/8250/8250_hp300.c b/trunk/drivers/tty/serial/8250/8250_hp300.c index 8f1dd2cc00a8..c13438c93012 100644 --- a/trunk/drivers/tty/serial/8250/8250_hp300.c +++ b/trunk/drivers/tty/serial/8250/8250_hp300.c @@ -171,7 +171,7 @@ static int __devinit hpdca_init_one(struct dio_dev *d, return 0; } #endif - memset(&uart, 0, sizeof(uart)); + memset(&port, 0, sizeof(struct uart_port)); /* Memory mapped I/O */ port.iotype = UPIO_MEM; @@ -182,7 +182,7 @@ static int __devinit hpdca_init_one(struct dio_dev *d, port.membase = (char *)(port.mapbase + DIO_VIRADDRBASE); port.regshift = 1; port.dev = &d->dev; - line = serial8250_register_8250_port(&uart); + line = serial8250_register_port(&port); if (line < 0) { printk(KERN_NOTICE "8250_hp300: register_serial() DCA scode %d" @@ -210,7 +210,7 @@ static int __init hp300_8250_init(void) #ifdef CONFIG_HPAPCI int line; unsigned long base; - struct uart_8250_port uart; + struct uart_port uport; struct hp300_port *port; int i; #endif @@ -248,26 +248,26 @@ static int __init hp300_8250_init(void) if (!port) return -ENOMEM; - memset(&uart, 0, sizeof(uart)); + memset(&uport, 0, sizeof(struct uart_port)); base = (FRODO_BASE + FRODO_APCI_OFFSET(i)); /* Memory mapped I/O */ - uart.port.iotype = UPIO_MEM; - uart.port.flags = UPF_SKIP_TEST | UPF_SHARE_IRQ \ + uport.iotype = UPIO_MEM; + uport.flags = UPF_SKIP_TEST | UPF_SHARE_IRQ \ | UPF_BOOT_AUTOCONF; /* XXX - no interrupt support yet */ - uart.port.irq = 0; - uart.port.uartclk = HPAPCI_BAUD_BASE * 16; - uart.port.mapbase = base; - uart.port.membase = (char *)(base + DIO_VIRADDRBASE); - uart.port.regshift = 2; + uport.irq = 0; + uport.uartclk = HPAPCI_BAUD_BASE * 16; + uport.mapbase = base; + uport.membase = (char *)(base + DIO_VIRADDRBASE); + uport.regshift = 2; - line = serial8250_register_8250_port(&uart); + line = serial8250_register_port(&uport); if (line < 0) { printk(KERN_NOTICE "8250_hp300: register_serial() APCI" - " %d irq %d failed\n", i, uart.port.irq); + " %d irq %d failed\n", i, uport.irq); kfree(port); continue; } diff --git a/trunk/drivers/tty/serial/8250/8250_pci.c b/trunk/drivers/tty/serial/8250/8250_pci.c index 17b7d26abf41..28e7c7cce893 100644 --- a/trunk/drivers/tty/serial/8250/8250_pci.c +++ b/trunk/drivers/tty/serial/8250/8250_pci.c @@ -44,7 +44,7 @@ struct pci_serial_quirk { int (*init)(struct pci_dev *dev); int (*setup)(struct serial_private *, const struct pciserial_board *, - struct uart_8250_port *, int); + struct uart_port *, int); void (*exit)(struct pci_dev *dev); }; @@ -59,7 +59,7 @@ struct serial_private { }; static int pci_default_setup(struct serial_private*, - const struct pciserial_board*, struct uart_8250_port *, int); + const struct pciserial_board*, struct uart_port*, int); static void moan_device(const char *str, struct pci_dev *dev) { @@ -74,7 +74,7 @@ static void moan_device(const char *str, struct pci_dev *dev) } static int -setup_port(struct serial_private *priv, struct uart_8250_port *port, +setup_port(struct serial_private *priv, struct uart_port *port, int bar, int offset, int regshift) { struct pci_dev *dev = priv->dev; @@ -93,17 +93,17 @@ setup_port(struct serial_private *priv, struct uart_8250_port *port, if (!priv->remapped_bar[bar]) return -ENOMEM; - port->port.iotype = UPIO_MEM; - port->port.iobase = 0; - port->port.mapbase = base + offset; - port->port.membase = priv->remapped_bar[bar] + offset; - port->port.regshift = regshift; + port->iotype = UPIO_MEM; + port->iobase = 0; + port->mapbase = base + offset; + port->membase = priv->remapped_bar[bar] + offset; + port->regshift = regshift; } else { - port->port.iotype = UPIO_PORT; - port->port.iobase = base + offset; - port->port.mapbase = 0; - port->port.membase = NULL; - port->port.regshift = 0; + port->iotype = UPIO_PORT; + port->iobase = base + offset; + port->mapbase = 0; + port->membase = NULL; + port->regshift = 0; } return 0; } @@ -113,7 +113,7 @@ setup_port(struct serial_private *priv, struct uart_8250_port *port, */ static int addidata_apci7800_setup(struct serial_private *priv, const struct pciserial_board *board, - struct uart_8250_port *port, int idx) + struct uart_port *port, int idx) { unsigned int bar = 0, offset = board->first_offset; bar = FL_GET_BASE(board->flags); @@ -140,7 +140,7 @@ static int addidata_apci7800_setup(struct serial_private *priv, */ static int afavlab_setup(struct serial_private *priv, const struct pciserial_board *board, - struct uart_8250_port *port, int idx) + struct uart_port *port, int idx) { unsigned int bar, offset = board->first_offset; @@ -195,7 +195,7 @@ static int pci_hp_diva_init(struct pci_dev *dev) static int pci_hp_diva_setup(struct serial_private *priv, const struct pciserial_board *board, - struct uart_8250_port *port, int idx) + struct uart_port *port, int idx) { unsigned int offset = board->first_offset; unsigned int bar = FL_GET_BASE(board->flags); @@ -370,7 +370,7 @@ static void __devexit pci_ni8430_exit(struct pci_dev *dev) /* SBS Technologies Inc. PMC-OCTPRO and P-OCTAL cards */ static int sbs_setup(struct serial_private *priv, const struct pciserial_board *board, - struct uart_8250_port *port, int idx) + struct uart_port *port, int idx) { unsigned int bar, offset = board->first_offset; @@ -525,7 +525,7 @@ static int pci_siig_init(struct pci_dev *dev) static int pci_siig_setup(struct serial_private *priv, const struct pciserial_board *board, - struct uart_8250_port *port, int idx) + struct uart_port *port, int idx) { unsigned int bar = FL_GET_BASE(board->flags) + idx, offset = 0; @@ -619,7 +619,7 @@ static int pci_timedia_init(struct pci_dev *dev) static int pci_timedia_setup(struct serial_private *priv, const struct pciserial_board *board, - struct uart_8250_port *port, int idx) + struct uart_port *port, int idx) { unsigned int bar = 0, offset = board->first_offset; @@ -653,7 +653,7 @@ pci_timedia_setup(struct serial_private *priv, static int titan_400l_800l_setup(struct serial_private *priv, const struct pciserial_board *board, - struct uart_8250_port *port, int idx) + struct uart_port *port, int idx) { unsigned int bar, offset = board->first_offset; @@ -754,7 +754,7 @@ static int pci_ni8430_init(struct pci_dev *dev) static int pci_ni8430_setup(struct serial_private *priv, const struct pciserial_board *board, - struct uart_8250_port *port, int idx) + struct uart_port *port, int idx) { void __iomem *p; unsigned long base, len; @@ -781,7 +781,7 @@ pci_ni8430_setup(struct serial_private *priv, static int pci_netmos_9900_setup(struct serial_private *priv, const struct pciserial_board *board, - struct uart_8250_port *port, int idx) + struct uart_port *port, int idx) { unsigned int bar; @@ -1032,17 +1032,10 @@ static int pci_oxsemi_tornado_init(struct pci_dev *dev) return number_uarts; } -static int pci_asix_setup(struct serial_private *priv, - const struct pciserial_board *board, - struct uart_8250_port *port, int idx) -{ - port->bugs |= UART_BUG_PARITY; - return pci_default_setup(priv, board, port, idx); -} - -static int pci_default_setup(struct serial_private *priv, +static int +pci_default_setup(struct serial_private *priv, const struct pciserial_board *board, - struct uart_8250_port *port, int idx) + struct uart_port *port, int idx) { unsigned int bar, offset = board->first_offset, maxnr; @@ -1064,15 +1057,15 @@ static int pci_default_setup(struct serial_private *priv, static int ce4100_serial_setup(struct serial_private *priv, const struct pciserial_board *board, - struct uart_8250_port *port, int idx) + struct uart_port *port, int idx) { int ret; ret = setup_port(priv, port, 0, 0, board->reg_shift); - port->port.iotype = UPIO_MEM32; - port->port.type = PORT_XSCALE; - port->port.flags = (port->port.flags | UPF_FIXED_PORT | UPF_FIXED_TYPE); - port->port.regshift = 2; + port->iotype = UPIO_MEM32; + port->type = PORT_XSCALE; + port->flags = (port->flags | UPF_FIXED_PORT | UPF_FIXED_TYPE); + port->regshift = 2; return ret; } @@ -1080,16 +1073,16 @@ ce4100_serial_setup(struct serial_private *priv, static int pci_omegapci_setup(struct serial_private *priv, const struct pciserial_board *board, - struct uart_8250_port *port, int idx) + struct uart_port *port, int idx) { return setup_port(priv, port, 2, idx * 8, 0); } static int skip_tx_en_setup(struct serial_private *priv, const struct pciserial_board *board, - struct uart_8250_port *port, int idx) + struct uart_port *port, int idx) { - port->port.flags |= UPF_NO_TXEN_TEST; + port->flags |= UPF_NO_TXEN_TEST; printk(KERN_DEBUG "serial8250: skipping TxEn test for device " "[%04x:%04x] subsystem [%04x:%04x]\n", priv->dev->vendor, @@ -1138,11 +1131,11 @@ static unsigned int kt_serial_in(struct uart_port *p, int offset) static int kt_serial_setup(struct serial_private *priv, const struct pciserial_board *board, - struct uart_8250_port *port, int idx) + struct uart_port *port, int idx) { - port->port.flags |= UPF_BUG_THRE; - port->port.serial_in = kt_serial_in; - port->port.handle_break = kt_handle_break; + port->flags |= UPF_BUG_THRE; + port->serial_in = kt_serial_in; + port->handle_break = kt_handle_break; return skip_tx_en_setup(priv, board, port, idx); } @@ -1158,19 +1151,9 @@ static int pci_eg20t_init(struct pci_dev *dev) static int pci_xr17c154_setup(struct serial_private *priv, const struct pciserial_board *board, - struct uart_8250_port *port, int idx) + struct uart_port *port, int idx) { - port->port.flags |= UPF_EXAR_EFR; - return pci_default_setup(priv, board, port, idx); -} - -static int -pci_wch_ch353_setup(struct serial_private *priv, - const struct pciserial_board *board, - struct uart_8250_port *port, int idx) -{ - port->port.flags |= UPF_FIXED_TYPE; - port->port.type = PORT_16550A; + port->flags |= UPF_EXAR_EFR; return pci_default_setup(priv, board, port, idx); } @@ -1181,8 +1164,6 @@ pci_wch_ch353_setup(struct serial_private *priv, #define PCI_SUBDEVICE_ID_OCTPRO422 0x0208 #define PCI_SUBDEVICE_ID_POCTAL232 0x0308 #define PCI_SUBDEVICE_ID_POCTAL422 0x0408 -#define PCI_SUBDEVICE_ID_SIIG_DUAL_00 0x2500 -#define PCI_SUBDEVICE_ID_SIIG_DUAL_30 0x2530 #define PCI_VENDOR_ID_ADVANTECH 0x13fe #define PCI_DEVICE_ID_INTEL_CE4100_UART 0x2e66 #define PCI_DEVICE_ID_ADVANTECH_PCI3620 0x3620 @@ -1206,13 +1187,6 @@ pci_wch_ch353_setup(struct serial_private *priv, #define PCIE_DEVICE_ID_NEO_2_OX_IBM 0x00F6 #define PCI_DEVICE_ID_PLX_CRONYX_OMEGA 0xc001 #define PCI_DEVICE_ID_INTEL_PATSBURG_KT 0x1d3d -#define PCI_VENDOR_ID_WCH 0x4348 -#define PCI_DEVICE_ID_WCH_CH353_4S 0x3453 -#define PCI_DEVICE_ID_WCH_CH353_2S1PF 0x5046 -#define PCI_DEVICE_ID_WCH_CH353_2S1P 0x7053 -#define PCI_VENDOR_ID_AGESTAR 0x5372 -#define PCI_DEVICE_ID_AGESTAR_9375 0x6872 -#define PCI_VENDOR_ID_ASIX 0x9710 /* Unknown vendors/cards - this should not be in linux/pci_ids.h */ #define PCI_SUBDEVICE_ID_UNKNOWN_0x1584 0x1584 @@ -1752,41 +1726,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = { .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, .setup = pci_omegapci_setup, - }, - /* WCH CH353 2S1P card (16550 clone) */ - { - .vendor = PCI_VENDOR_ID_WCH, - .device = PCI_DEVICE_ID_WCH_CH353_2S1P, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .setup = pci_wch_ch353_setup, - }, - /* WCH CH353 4S card (16550 clone) */ - { - .vendor = PCI_VENDOR_ID_WCH, - .device = PCI_DEVICE_ID_WCH_CH353_4S, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .setup = pci_wch_ch353_setup, - }, - /* WCH CH353 2S1PF card (16550 clone) */ - { - .vendor = PCI_VENDOR_ID_WCH, - .device = PCI_DEVICE_ID_WCH_CH353_2S1PF, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .setup = pci_wch_ch353_setup, - }, - /* - * ASIX devices with FIFO bug - */ - { - .vendor = PCI_VENDOR_ID_ASIX, - .device = PCI_ANY_ID, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .setup = pci_asix_setup, - }, + }, /* * Default "match everything" terminator entry */ @@ -1947,6 +1887,7 @@ enum pci_board_num_t { pbn_panacom, pbn_panacom2, pbn_panacom4, + pbn_exsys_4055, pbn_plx_romulus, pbn_oxsemi, pbn_oxsemi_1_4000000, @@ -2452,6 +2393,13 @@ static struct pciserial_board pci_boards[] __devinitdata = { .reg_shift = 7, }, + [pbn_exsys_4055] = { + .flags = FL_BASE2, + .num_ports = 4, + .base_baud = 115200, + .uart_offset = 8, + }, + /* I think this entry is broken - the first_offset looks wrong --rmk */ [pbn_plx_romulus] = { .flags = FL_BASE2, @@ -2676,14 +2624,10 @@ static struct pciserial_board pci_boards[] __devinitdata = { }, }; -static const struct pci_device_id blacklist[] = { - /* softmodems */ +static const struct pci_device_id softmodem_blacklist[] = { { PCI_VDEVICE(AL, 0x5457), }, /* ALi Corporation M5457 AC'97 Modem */ { PCI_VDEVICE(MOTOROLA, 0x3052), }, /* Motorola Si3052-based modem */ { PCI_DEVICE(0x1543, 0x3052), }, /* Si3052-based modem, default IDs */ - - /* multi-io cards handled by parport_serial */ - { PCI_DEVICE(0x4348, 0x7053), }, /* WCH CH353 2S1P */ }; /* @@ -2694,7 +2638,7 @@ static const struct pci_device_id blacklist[] = { static int __devinit serial_pci_guess_board(struct pci_dev *dev, struct pciserial_board *board) { - const struct pci_device_id *bldev; + const struct pci_device_id *blacklist; int num_iomem, num_port, first_port = -1, i; /* @@ -2711,13 +2655,13 @@ serial_pci_guess_board(struct pci_dev *dev, struct pciserial_board *board) /* * Do not access blacklisted devices that are known not to - * feature serial ports or are handled by other modules. + * feature serial ports. */ - for (bldev = blacklist; - bldev < blacklist + ARRAY_SIZE(blacklist); - bldev++) { - if (dev->vendor == bldev->vendor && - dev->device == bldev->device) + for (blacklist = softmodem_blacklist; + blacklist < softmodem_blacklist + ARRAY_SIZE(softmodem_blacklist); + blacklist++) { + if (dev->vendor == blacklist->vendor && + dev->device == blacklist->device) return -ENODEV; } @@ -2784,7 +2728,7 @@ serial_pci_matches(const struct pciserial_board *board, struct serial_private * pciserial_init_ports(struct pci_dev *dev, const struct pciserial_board *board) { - struct uart_8250_port uart; + struct uart_port serial_port; struct serial_private *priv; struct pci_serial_quirk *quirk; int rc, nr_ports, i; @@ -2824,22 +2768,22 @@ pciserial_init_ports(struct pci_dev *dev, const struct pciserial_board *board) priv->dev = dev; priv->quirk = quirk; - memset(&uart, 0, sizeof(uart)); - uart.port.flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ; - uart.port.uartclk = board->base_baud * 16; - uart.port.irq = get_pci_irq(dev, board); - uart.port.dev = &dev->dev; + memset(&serial_port, 0, sizeof(struct uart_port)); + serial_port.flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ; + serial_port.uartclk = board->base_baud * 16; + serial_port.irq = get_pci_irq(dev, board); + serial_port.dev = &dev->dev; for (i = 0; i < nr_ports; i++) { - if (quirk->setup(priv, board, &uart, i)) + if (quirk->setup(priv, board, &serial_port, i)) break; #ifdef SERIAL_DEBUG_PCI printk(KERN_DEBUG "Setup PCI port: port %lx, irq %d, type %d\n", - uart.port.iobase, uart.port.irq, uart.port.iotype); + serial_port.iobase, serial_port.irq, serial_port.iotype); #endif - priv->line[i] = serial8250_register_8250_port(&uart); + priv->line[i] = serial8250_register_port(&serial_port); if (priv->line[i] < 0) { printk(KERN_WARNING "Couldn't register serial port %s: %d\n", pci_name(dev), priv->line[i]); break; @@ -3249,7 +3193,7 @@ static struct pci_device_id serial_pci_tbl[] = { { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050, PCI_SUBVENDOR_ID_EXSYS, PCI_SUBDEVICE_ID_EXSYS_4055, 0, 0, - pbn_b2_4_115200 }, + pbn_exsys_4055 }, /* * Megawolf Romulus PCI Serial Card, from Mike Hudson * (Exoray@isys.ca) @@ -3288,11 +3232,8 @@ static struct pci_device_id serial_pci_tbl[] = { * For now just used the hex ID 0x950a. */ { PCI_VENDOR_ID_OXSEMI, 0x950a, - PCI_SUBVENDOR_ID_SIIG, PCI_SUBDEVICE_ID_SIIG_DUAL_00, - 0, 0, pbn_b0_2_115200 }, - { PCI_VENDOR_ID_OXSEMI, 0x950a, - PCI_SUBVENDOR_ID_SIIG, PCI_SUBDEVICE_ID_SIIG_DUAL_30, - 0, 0, pbn_b0_2_115200 }, + PCI_SUBVENDOR_ID_SIIG, PCI_SUBDEVICE_ID_SIIG_DUAL_SERIAL, 0, 0, + pbn_b0_2_115200 }, { PCI_VENDOR_ID_OXSEMI, 0x950a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, pbn_b0_2_1130000 }, @@ -4237,25 +4178,6 @@ static struct pci_device_id serial_pci_tbl[] = { PCI_ANY_ID, PCI_ANY_ID, 0, 0, pbn_omegapci }, - /* - * AgeStar as-prs2-009 - */ - { PCI_VENDOR_ID_AGESTAR, PCI_DEVICE_ID_AGESTAR_9375, - PCI_ANY_ID, PCI_ANY_ID, - 0, 0, pbn_b0_bt_2_115200 }, - - /* - * WCH CH353 series devices: The 2S1P is handled by parport_serial - * so not listed here. - */ - { PCI_VENDOR_ID_WCH, PCI_DEVICE_ID_WCH_CH353_4S, - PCI_ANY_ID, PCI_ANY_ID, - 0, 0, pbn_b0_bt_4_115200 }, - - { PCI_VENDOR_ID_WCH, PCI_DEVICE_ID_WCH_CH353_2S1PF, - PCI_ANY_ID, PCI_ANY_ID, - 0, 0, pbn_b0_bt_2_115200 }, - /* * These entries match devices with class COMMUNICATION_SERIAL, * COMMUNICATION_MODEM or COMMUNICATION_MULTISERIAL @@ -4314,7 +4236,7 @@ static void serial8250_io_resume(struct pci_dev *dev) pciserial_resume_ports(priv); } -static const struct pci_error_handlers serial8250_err_handler = { +static struct pci_error_handlers serial8250_err_handler = { .error_detected = serial8250_io_error_detected, .slot_reset = serial8250_io_slot_reset, .resume = serial8250_io_resume, diff --git a/trunk/drivers/tty/serial/8250/8250_pnp.c b/trunk/drivers/tty/serial/8250/8250_pnp.c index f8ee25001dd0..a2f236510ff1 100644 --- a/trunk/drivers/tty/serial/8250/8250_pnp.c +++ b/trunk/drivers/tty/serial/8250/8250_pnp.c @@ -1,5 +1,5 @@ /* - * Probe for 8250/16550-type ISAPNP serial ports. + * Probe module for 8250/16550-type ISAPNP serial ports. * * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o. * @@ -25,7 +25,7 @@ #include "8250.h" #define UNKNOWN_DEV 0x3000 -#define CIR_PORT 0x0800 + static const struct pnp_device_id pnp_dev_table[] = { /* Archtek America Corp. */ @@ -362,9 +362,6 @@ static const struct pnp_device_id pnp_dev_table[] = { { "PNPCXXX", UNKNOWN_DEV }, /* More unknown PnP modems */ { "PNPDXXX", UNKNOWN_DEV }, - /* Winbond CIR port, should not be probed. We should keep track - of it to prevent the legacy serial driver from probing it */ - { "WEC1022", CIR_PORT }, { "", 0 } }; @@ -412,7 +409,7 @@ static int __devinit check_resources(struct pnp_dev *dev) * PnP modems, alternatively we must hardcode all modems in pnp_devices[] * table. */ -static int __devinit serial_pnp_guess_board(struct pnp_dev *dev) +static int __devinit serial_pnp_guess_board(struct pnp_dev *dev, int *flags) { if (!(check_name(pnp_dev_name(dev)) || (dev->card && check_name(dev->card->name)))) @@ -427,49 +424,42 @@ static int __devinit serial_pnp_guess_board(struct pnp_dev *dev) static int __devinit serial_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id) { - struct uart_8250_port uart; + struct uart_port port; int ret, line, flags = dev_id->driver_data; if (flags & UNKNOWN_DEV) { - ret = serial_pnp_guess_board(dev); + ret = serial_pnp_guess_board(dev, &flags); if (ret < 0) return ret; } - memset(&uart, 0, sizeof(uart)); + memset(&port, 0, sizeof(struct uart_port)); if (pnp_irq_valid(dev, 0)) - uart.port.irq = pnp_irq(dev, 0); - if ((flags & CIR_PORT) && pnp_port_valid(dev, 2)) { - uart.port.iobase = pnp_port_start(dev, 2); - uart.port.iotype = UPIO_PORT; - } else if (pnp_port_valid(dev, 0)) { - uart.port.iobase = pnp_port_start(dev, 0); - uart.port.iotype = UPIO_PORT; + port.irq = pnp_irq(dev, 0); + if (pnp_port_valid(dev, 0)) { + port.iobase = pnp_port_start(dev, 0); + port.iotype = UPIO_PORT; } else if (pnp_mem_valid(dev, 0)) { - uart.port.mapbase = pnp_mem_start(dev, 0); - uart.port.iotype = UPIO_MEM; - uart.port.flags = UPF_IOREMAP; + port.mapbase = pnp_mem_start(dev, 0); + port.iotype = UPIO_MEM; + port.flags = UPF_IOREMAP; } else return -ENODEV; #ifdef SERIAL_DEBUG_PNP printk(KERN_DEBUG "Setup PNP port: port %x, mem 0x%lx, irq %d, type %d\n", - uart.port.iobase, uart.port.mapbase, uart.port.irq, uart.port.iotype); + port.iobase, port.mapbase, port.irq, port.iotype); #endif - if (flags & CIR_PORT) { - uart.port.flags |= UPF_FIXED_PORT | UPF_FIXED_TYPE; - uart.port.type = PORT_8250_CIR; - } - uart.port.flags |= UPF_SKIP_TEST | UPF_BOOT_AUTOCONF; + port.flags |= UPF_SKIP_TEST | UPF_BOOT_AUTOCONF; if (pnp_irq_flags(dev, 0) & IORESOURCE_IRQ_SHAREABLE) - uart.port.flags |= UPF_SHARE_IRQ; - uart.port.uartclk = 1843200; - uart.port.dev = &dev->dev; + port.flags |= UPF_SHARE_IRQ; + port.uartclk = 1843200; + port.dev = &dev->dev; - line = serial8250_register_8250_port(&uart); - if (line < 0 || (flags & CIR_PORT)) + line = serial8250_register_port(&port); + if (line < 0) return -ENODEV; pnp_set_drvdata(dev, (void *)((long)line + 1)); @@ -517,13 +507,18 @@ static struct pnp_driver serial_pnp_driver = { .id_table = pnp_dev_table, }; -int serial8250_pnp_init(void) +static int __init serial8250_pnp_init(void) { return pnp_register_driver(&serial_pnp_driver); } -void serial8250_pnp_exit(void) +static void __exit serial8250_pnp_exit(void) { pnp_unregister_driver(&serial_pnp_driver); } +module_init(serial8250_pnp_init); +module_exit(serial8250_pnp_exit); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Generic 8250/16x50 PnP serial driver"); diff --git a/trunk/drivers/tty/serial/8250/Kconfig b/trunk/drivers/tty/serial/8250/Kconfig index f3d283f2e3aa..a27dd0569bd7 100644 --- a/trunk/drivers/tty/serial/8250/Kconfig +++ b/trunk/drivers/tty/serial/8250/Kconfig @@ -33,14 +33,6 @@ config SERIAL_8250 Most people will say Y or M here, so that they can use serial mice, modems and similar devices connecting to the standard serial ports. -config SERIAL_8250_PNP - bool "8250/16550 PNP device support" if EXPERT - depends on SERIAL_8250 && PNP - default y - ---help--- - This builds standard PNP serial support. You may be able to - disable this feature if you only need legacy serial support. - config SERIAL_8250_CONSOLE bool "Console on 8250/16550 and compatible serial port" depends on SERIAL_8250=y @@ -93,6 +85,14 @@ config SERIAL_8250_PCI disable this feature if you only need legacy serial support. Saves about 9K. +config SERIAL_8250_PNP + tristate "8250/16550 PNP device support" if EXPERT + depends on SERIAL_8250 && PNP + default SERIAL_8250 + help + This builds standard PNP serial support. You may be able to + disable this feature if you only need legacy serial support. + config SERIAL_8250_HP300 tristate depends on SERIAL_8250 && HP300 diff --git a/trunk/drivers/tty/serial/8250/Makefile b/trunk/drivers/tty/serial/8250/Makefile index 108fe7fe13e2..d7533c7d2c1a 100644 --- a/trunk/drivers/tty/serial/8250/Makefile +++ b/trunk/drivers/tty/serial/8250/Makefile @@ -2,9 +2,8 @@ # Makefile for the 8250 serial device drivers. # -obj-$(CONFIG_SERIAL_8250) += 8250_core.o -8250_core-y := 8250.o -8250_core-$(CONFIG_SERIAL_8250_PNP) += 8250_pnp.o +obj-$(CONFIG_SERIAL_8250) += 8250.o +obj-$(CONFIG_SERIAL_8250_PNP) += 8250_pnp.o obj-$(CONFIG_SERIAL_8250_GSC) += 8250_gsc.o obj-$(CONFIG_SERIAL_8250_PCI) += 8250_pci.o obj-$(CONFIG_SERIAL_8250_HP300) += 8250_hp300.o diff --git a/trunk/drivers/tty/serial/8250/serial_cs.c b/trunk/drivers/tty/serial/8250/serial_cs.c index b7d48b346393..29b695d041ec 100644 --- a/trunk/drivers/tty/serial/8250/serial_cs.c +++ b/trunk/drivers/tty/serial/8250/serial_cs.c @@ -73,7 +73,7 @@ struct serial_quirk { unsigned int prodid; int multi; /* 1 = multifunction, > 1 = # ports */ void (*config)(struct pcmcia_device *); - void (*setup)(struct pcmcia_device *, struct uart_8250_port *); + void (*setup)(struct pcmcia_device *, struct uart_port *); void (*wakeup)(struct pcmcia_device *); int (*post)(struct pcmcia_device *); }; @@ -105,9 +105,9 @@ struct serial_cfg_mem { * Elan VPU16551 UART with 14.7456MHz oscillator * manfid 0x015D, 0x4C45 */ -static void quirk_setup_brainboxes_0104(struct pcmcia_device *link, struct uart_8250_port *uart) +static void quirk_setup_brainboxes_0104(struct pcmcia_device *link, struct uart_port *port) { - uart->port.uartclk = 14745600; + port->uartclk = 14745600; } static int quirk_post_ibm(struct pcmcia_device *link) @@ -343,25 +343,25 @@ static void serial_detach(struct pcmcia_device *link) static int setup_serial(struct pcmcia_device *handle, struct serial_info * info, unsigned int iobase, int irq) { - struct uart_8250_port uart; + struct uart_port port; int line; - memset(&uart, 0, sizeof(uart)); - uart.port.iobase = iobase; - uart.port.irq = irq; - uart.port.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_SHARE_IRQ; - uart.port.uartclk = 1843200; - uart.port.dev = &handle->dev; + memset(&port, 0, sizeof (struct uart_port)); + port.iobase = iobase; + port.irq = irq; + port.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_SHARE_IRQ; + port.uartclk = 1843200; + port.dev = &handle->dev; if (buggy_uart) - uart.port.flags |= UPF_BUGGY_UART; + port.flags |= UPF_BUGGY_UART; if (info->quirk && info->quirk->setup) - info->quirk->setup(handle, &uart); + info->quirk->setup(handle, &port); - line = serial8250_register_8250_port(&uart); + line = serial8250_register_port(&port); if (line < 0) { - pr_err("serial_cs: serial8250_register_8250_port() at 0x%04lx, irq %d failed\n", - (unsigned long)iobase, irq); + printk(KERN_NOTICE "serial_cs: serial8250_register_port() at " + "0x%04lx, irq %d failed\n", (u_long)iobase, irq); return -EINVAL; } diff --git a/trunk/drivers/tty/serial/Kconfig b/trunk/drivers/tty/serial/Kconfig index 233fbaaf2559..070b442c1f81 100644 --- a/trunk/drivers/tty/serial/Kconfig +++ b/trunk/drivers/tty/serial/Kconfig @@ -141,25 +141,6 @@ config SERIAL_ATMEL_TTYAT Say Y if you have an external 8250/16C550 UART. If unsure, say N. -config SERIAL_KGDB_NMI - bool "Serial console over KGDB NMI debugger port" - depends on KGDB_SERIAL_CONSOLE - help - This special driver allows you to temporary use NMI debugger port - as a normal console (assuming that the port is attached to KGDB). - - Unlike KDB's disable_nmi command, with this driver you are always - able to go back to the debugger using KGDB escape sequence ($3#33). - This is because this console driver processes the input in NMI - context, and thus is able to intercept the magic sequence. - - Note that since the console interprets input and uses polling - communication methods, for things like PPP you still must fully - detach debugger port from the KGDB NMI (i.e. disable_nmi), and - use raw console. - - If unsure, say N. - config SERIAL_KS8695 bool "Micrel KS8695 (Centaur) serial port support" depends on ARCH_KS8695 @@ -179,12 +160,10 @@ config SERIAL_KS8695_CONSOLE config SERIAL_CLPS711X tristate "CLPS711X serial port support" - depends on ARCH_CLPS711X + depends on ARM && ARCH_CLPS711X select SERIAL_CORE - default y help - This enables the driver for the on-chip UARTs of the Cirrus - Logic EP711x/EP721x/EP731x processors. + ::: To be written ::: config SERIAL_CLPS711X_CONSOLE bool "Support for console on CLPS711X serial port" @@ -194,7 +173,9 @@ config SERIAL_CLPS711X_CONSOLE Even if you say Y here, the currently visible virtual console (/dev/tty0) will still be used as the system console by default, but you can alter that using a kernel command line option such as - "console=ttyCL1". + "console=ttyCL1". (Try "man bootparam" or see the documentation of + your boot loader (lilo or loadlin) about how to pass options to the + kernel at boot time.) config SERIAL_SAMSUNG tristate "Samsung SoC serial support" @@ -276,19 +257,12 @@ config SERIAL_MAX3100 help MAX3100 chip support -config SERIAL_MAX310X - bool "MAX310X support" +config SERIAL_MAX3107 + tristate "MAX3107 support" depends on SPI select SERIAL_CORE - select REGMAP_SPI if SPI - default n help - This selects support for an advanced UART from Maxim (Dallas). - Supported ICs are MAX3107, MAX3108. - Each IC contains 128 words each of receive and transmit FIFO - that can be controlled through I2C or high-speed SPI. - - Say Y here if you want to support this ICs. + MAX3107 chip support config SERIAL_DZ bool "DECstation DZ serial driver" @@ -712,7 +686,7 @@ config SERIAL_SH_SCI_CONSOLE config SERIAL_SH_SCI_DMA bool "DMA support" - depends on SERIAL_SH_SCI && SH_DMAE + depends on SERIAL_SH_SCI && SH_DMAE && EXPERIMENTAL config SERIAL_PNX8XXX bool "Enable PNX8XXX SoCs' UART Support" @@ -730,25 +704,6 @@ config SERIAL_PNX8XXX_CONSOLE If you have a MIPS-based Philips SoC such as PNX8550 or PNX8330 and you want to use serial console, say Y. Otherwise, say N. -config SERIAL_HS_LPC32XX - tristate "LPC32XX high speed serial port support" - depends on ARCH_LPC32XX && OF - select SERIAL_CORE - help - Support for the LPC32XX high speed serial ports (up to 900kbps). - Those are UARTs completely different from the Standard UARTs on the - LPC32XX SoC. - Choose M or Y here to build this driver. - -config SERIAL_HS_LPC32XX_CONSOLE - bool "Enable LPC32XX high speed UART serial console" - depends on SERIAL_HS_LPC32XX - select SERIAL_CORE_CONSOLE - help - If you would like to be able to use one of the high speed serial - ports on the LPC32XX as the console, you can do so by answering - Y to this option. - config SERIAL_CORE tristate @@ -1149,24 +1104,6 @@ config SERIAL_SC26XX_CONSOLE help Support for Console on SC2681/SC2692 serial ports. -config SERIAL_SCCNXP - bool "SCCNXP serial port support" - depends on !SERIAL_SC26XX - select SERIAL_CORE - default n - help - This selects support for an advanced UART from NXP (Philips). - Supported ICs are SCC2681, SCC2691, SCC2692, SC28L91, SC28L92, - SC28L202, SCC68681 and SCC68692. - Positioned as a replacement for the driver SC26XX. - -config SERIAL_SCCNXP_CONSOLE - bool "Console on SCCNXP serial port" - depends on SERIAL_SCCNXP - select SERIAL_CORE_CONSOLE - help - Support for console on SCCNXP serial ports. - config SERIAL_BFIN_SPORT tristate "Blackfin SPORT emulate UART" depends on BLACKFIN @@ -1323,7 +1260,7 @@ config SERIAL_ALTERA_UART_CONSOLE config SERIAL_IFX6X60 tristate "SPI protocol driver for Infineon 6x60 modem (EXPERIMENTAL)" - depends on GPIOLIB && SPI + depends on GPIOLIB && SPI && EXPERIMENTAL help Support for the IFX6x60 modem devices on Intel MID platforms. diff --git a/trunk/drivers/tty/serial/Makefile b/trunk/drivers/tty/serial/Makefile index 4f694dafa719..7257c5d898ae 100644 --- a/trunk/drivers/tty/serial/Makefile +++ b/trunk/drivers/tty/serial/Makefile @@ -28,13 +28,12 @@ obj-$(CONFIG_SERIAL_BFIN) += bfin_uart.o obj-$(CONFIG_SERIAL_BFIN_SPORT) += bfin_sport_uart.o obj-$(CONFIG_SERIAL_SAMSUNG) += samsung.o obj-$(CONFIG_SERIAL_MAX3100) += max3100.o -obj-$(CONFIG_SERIAL_MAX310X) += max310x.o +obj-$(CONFIG_SERIAL_MAX3107) += max3107.o obj-$(CONFIG_SERIAL_IP22_ZILOG) += ip22zilog.o obj-$(CONFIG_SERIAL_MUX) += mux.o obj-$(CONFIG_SERIAL_68328) += 68328serial.o obj-$(CONFIG_SERIAL_MCF) += mcf.o obj-$(CONFIG_SERIAL_PMACZILOG) += pmac_zilog.o -obj-$(CONFIG_SERIAL_HS_LPC32XX) += lpc32xx_hs.o obj-$(CONFIG_SERIAL_DZ) += dz.o obj-$(CONFIG_SERIAL_ZS) += zs.o obj-$(CONFIG_SERIAL_SH_SCI) += sh-sci.o @@ -48,7 +47,6 @@ obj-$(CONFIG_SERIAL_MPSC) += mpsc.o obj-$(CONFIG_SERIAL_SB1250_DUART) += sb1250-duart.o obj-$(CONFIG_ETRAX_SERIAL) += crisv10.o obj-$(CONFIG_SERIAL_SC26XX) += sc26xx.o -obj-$(CONFIG_SERIAL_SCCNXP) += sccnxp.o obj-$(CONFIG_SERIAL_JSM) += jsm/ obj-$(CONFIG_SERIAL_TXX9) += serial_txx9.o obj-$(CONFIG_SERIAL_VR41XX) += vr41xx_siu.o @@ -61,7 +59,6 @@ obj-$(CONFIG_SERIAL_MSM_HS) += msm_serial_hs.o obj-$(CONFIG_SERIAL_NETX) += netx-serial.o obj-$(CONFIG_SERIAL_OF_PLATFORM) += of_serial.o obj-$(CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL) += nwpserial.o -obj-$(CONFIG_SERIAL_KGDB_NMI) += kgdb_nmi.o obj-$(CONFIG_SERIAL_KS8695) += serial_ks8695.o obj-$(CONFIG_SERIAL_OMAP) += omap-serial.o obj-$(CONFIG_SERIAL_ALTERA_UART) += altera_uart.o diff --git a/trunk/drivers/tty/serial/altera_uart.c b/trunk/drivers/tty/serial/altera_uart.c index 15d80b9fb303..1f0330915d5a 100644 --- a/trunk/drivers/tty/serial/altera_uart.c +++ b/trunk/drivers/tty/serial/altera_uart.c @@ -591,7 +591,7 @@ static int __devinit altera_uart_probe(struct platform_device *pdev) port->ops = &altera_uart_ops; port->flags = UPF_BOOT_AUTOCONF; - platform_set_drvdata(pdev, port); + dev_set_drvdata(&pdev->dev, port); uart_add_one_port(&altera_uart_driver, port); @@ -600,11 +600,11 @@ static int __devinit altera_uart_probe(struct platform_device *pdev) static int __devexit altera_uart_remove(struct platform_device *pdev) { - struct uart_port *port = platform_get_drvdata(pdev); + struct uart_port *port = dev_get_drvdata(&pdev->dev); if (port) { uart_remove_one_port(&altera_uart_driver, port); - platform_set_drvdata(pdev, NULL); + dev_set_drvdata(&pdev->dev, NULL); port->mapbase = 0; } diff --git a/trunk/drivers/tty/serial/amba-pl010.c b/trunk/drivers/tty/serial/amba-pl010.c index 22317dd16474..0d91a540bf11 100644 --- a/trunk/drivers/tty/serial/amba-pl010.c +++ b/trunk/drivers/tty/serial/amba-pl010.c @@ -312,12 +312,16 @@ static int pl010_startup(struct uart_port *port) struct uart_amba_port *uap = (struct uart_amba_port *)port; int retval; + retval = clk_prepare(uap->clk); + if (retval) + goto out; + /* * Try to enable the clock producer. */ - retval = clk_prepare_enable(uap->clk); + retval = clk_enable(uap->clk); if (retval) - goto out; + goto clk_unprep; uap->port.uartclk = clk_get_rate(uap->clk); @@ -342,7 +346,9 @@ static int pl010_startup(struct uart_port *port) return 0; clk_dis: - clk_disable_unprepare(uap->clk); + clk_disable(uap->clk); + clk_unprep: + clk_unprepare(uap->clk); out: return retval; } @@ -369,7 +375,8 @@ static void pl010_shutdown(struct uart_port *port) /* * Shut down the clock producer */ - clk_disable_unprepare(uap->clk); + clk_disable(uap->clk); + clk_unprepare(uap->clk); } static void diff --git a/trunk/drivers/tty/serial/amba-pl011.c b/trunk/drivers/tty/serial/amba-pl011.c index d7e1edec50b5..d3553b5d3fca 100644 --- a/trunk/drivers/tty/serial/amba-pl011.c +++ b/trunk/drivers/tty/serial/amba-pl011.c @@ -52,8 +52,6 @@ #include #include #include -#include -#include #include #include @@ -77,6 +75,7 @@ struct vendor_data { unsigned int lcrh_tx; unsigned int lcrh_rx; bool oversampling; + bool interrupt_may_hang; /* vendor-specific */ bool dma_threshold; bool cts_event_workaround; }; @@ -97,6 +96,7 @@ static struct vendor_data vendor_st = { .lcrh_tx = ST_UART011_LCRH_TX, .lcrh_rx = ST_UART011_LCRH_RX, .oversampling = true, + .interrupt_may_hang = true, .dma_threshold = true, .cts_event_workaround = true, }; @@ -147,6 +147,7 @@ struct uart_amba_port { unsigned int old_cr; /* state during shutdown */ bool autorts; char type[12]; + bool interrupt_may_hang; /* vendor-specific */ #ifdef CONFIG_DMA_ENGINE /* DMA stuff */ bool using_tx_dma; @@ -1214,14 +1215,14 @@ static irqreturn_t pl011_int(int irq, void *dev_id) return IRQ_RETVAL(handled); } -static unsigned int pl011_tx_empty(struct uart_port *port) +static unsigned int pl01x_tx_empty(struct uart_port *port) { struct uart_amba_port *uap = (struct uart_amba_port *)port; unsigned int status = readw(uap->port.membase + UART01x_FR); return status & (UART01x_FR_BUSY|UART01x_FR_TXFF) ? 0 : TIOCSER_TEMT; } -static unsigned int pl011_get_mctrl(struct uart_port *port) +static unsigned int pl01x_get_mctrl(struct uart_port *port) { struct uart_amba_port *uap = (struct uart_amba_port *)port; unsigned int result = 0; @@ -1284,40 +1285,11 @@ static void pl011_break_ctl(struct uart_port *port, int break_state) } #ifdef CONFIG_CONSOLE_POLL - -static void pl011_quiesce_irqs(struct uart_port *port) -{ - struct uart_amba_port *uap = (struct uart_amba_port *)port; - unsigned char __iomem *regs = uap->port.membase; - - writew(readw(regs + UART011_MIS), regs + UART011_ICR); - /* - * There is no way to clear TXIM as this is "ready to transmit IRQ", so - * we simply mask it. start_tx() will unmask it. - * - * Note we can race with start_tx(), and if the race happens, the - * polling user might get another interrupt just after we clear it. - * But it should be OK and can happen even w/o the race, e.g. - * controller immediately got some new data and raised the IRQ. - * - * And whoever uses polling routines assumes that it manages the device - * (including tx queue), so we're also fine with start_tx()'s caller - * side. - */ - writew(readw(regs + UART011_IMSC) & ~UART011_TXIM, regs + UART011_IMSC); -} - -static int pl011_get_poll_char(struct uart_port *port) +static int pl010_get_poll_char(struct uart_port *port) { struct uart_amba_port *uap = (struct uart_amba_port *)port; unsigned int status; - /* - * The caller might need IRQs lowered, e.g. if used with KDB NMI - * debugger. - */ - pl011_quiesce_irqs(port); - status = readw(uap->port.membase + UART01x_FR); if (status & UART01x_FR_RXFE) return NO_POLL_CHAR; @@ -1325,7 +1297,7 @@ static int pl011_get_poll_char(struct uart_port *port) return readw(uap->port.membase + UART01x_DR); } -static void pl011_put_poll_char(struct uart_port *port, +static void pl010_put_poll_char(struct uart_port *port, unsigned char ch) { struct uart_amba_port *uap = (struct uart_amba_port *)port; @@ -1338,9 +1310,10 @@ static void pl011_put_poll_char(struct uart_port *port, #endif /* CONFIG_CONSOLE_POLL */ -static int pl011_hwinit(struct uart_port *port) +static int pl011_startup(struct uart_port *port) { struct uart_amba_port *uap = (struct uart_amba_port *)port; + unsigned int cr; int retval; /* Optionaly enable pins to be muxed in and configured */ @@ -1351,12 +1324,16 @@ static int pl011_hwinit(struct uart_port *port) "could not set default pins\n"); } + retval = clk_prepare(uap->clk); + if (retval) + goto out; + /* * Try to enable the clock producer. */ - retval = clk_prepare_enable(uap->clk); + retval = clk_enable(uap->clk); if (retval) - goto out; + goto clk_unprep; uap->port.uartclk = clk_get_rate(uap->clk); @@ -1364,37 +1341,6 @@ static int pl011_hwinit(struct uart_port *port) writew(UART011_OEIS | UART011_BEIS | UART011_PEIS | UART011_FEIS | UART011_RTIS | UART011_RXIS, uap->port.membase + UART011_ICR); - /* - * Save interrupts enable mask, and enable RX interrupts in case if - * the interrupt is used for NMI entry. - */ - uap->im = readw(uap->port.membase + UART011_IMSC); - writew(UART011_RTIM | UART011_RXIM, uap->port.membase + UART011_IMSC); - - if (uap->port.dev->platform_data) { - struct amba_pl011_data *plat; - - plat = uap->port.dev->platform_data; - if (plat->init) - plat->init(); - } - return 0; - out: - return retval; -} - -static int pl011_startup(struct uart_port *port) -{ - struct uart_amba_port *uap = (struct uart_amba_port *)port; - unsigned int cr; - int retval; - - retval = pl011_hwinit(port); - if (retval) - goto clk_dis; - - writew(uap->im, uap->port.membase + UART011_IMSC); - /* * Allocate the IRQ */ @@ -1454,10 +1400,21 @@ static int pl011_startup(struct uart_port *port) writew(uap->im, uap->port.membase + UART011_IMSC); spin_unlock_irq(&uap->port.lock); + if (uap->port.dev->platform_data) { + struct amba_pl011_data *plat; + + plat = uap->port.dev->platform_data; + if (plat->init) + plat->init(); + } + return 0; clk_dis: - clk_disable_unprepare(uap->clk); + clk_disable(uap->clk); + clk_unprep: + clk_unprepare(uap->clk); + out: return retval; } @@ -1516,7 +1473,8 @@ static void pl011_shutdown(struct uart_port *port) /* * Shut down the clock producer */ - clk_disable_unprepare(uap->clk); + clk_disable(uap->clk); + clk_unprepare(uap->clk); /* Optionally let pins go into sleep states */ if (!IS_ERR(uap->pins_sleep)) { retval = pinctrl_select_state(uap->pinctrl, uap->pins_sleep); @@ -1645,26 +1603,13 @@ pl011_set_termios(struct uart_port *port, struct ktermios *termios, old_cr &= ~ST_UART011_CR_OVSFACT; } - /* - * Workaround for the ST Micro oversampling variants to - * increase the bitrate slightly, by lowering the divisor, - * to avoid delayed sampling of start bit at high speeds, - * else we see data corruption. - */ - if (uap->vendor->oversampling) { - if ((baud >= 3000000) && (baud < 3250000) && (quot > 1)) - quot -= 1; - else if ((baud > 3250000) && (quot > 2)) - quot -= 2; - } /* Set baud rate */ writew(quot & 0x3f, port->membase + UART011_FBRD); writew(quot >> 6, port->membase + UART011_IBRD); /* * ----------v----------v----------v----------v----- - * NOTE: lcrh_tx and lcrh_rx MUST BE WRITTEN AFTER - * UART011_FBRD & UART011_IBRD. + * NOTE: MUST BE WRITTEN AFTER UARTLCR_M & UARTLCR_L * ----------^----------^----------^----------^----- */ writew(lcr_h, port->membase + uap->lcrh_rx); @@ -1692,7 +1637,7 @@ static const char *pl011_type(struct uart_port *port) /* * Release the memory region(s) being used by 'port' */ -static void pl011_release_port(struct uart_port *port) +static void pl010_release_port(struct uart_port *port) { release_mem_region(port->mapbase, SZ_4K); } @@ -1700,7 +1645,7 @@ static void pl011_release_port(struct uart_port *port) /* * Request the memory region(s) being used by 'port' */ -static int pl011_request_port(struct uart_port *port) +static int pl010_request_port(struct uart_port *port) { return request_mem_region(port->mapbase, SZ_4K, "uart-pl011") != NULL ? 0 : -EBUSY; @@ -1709,18 +1654,18 @@ static int pl011_request_port(struct uart_port *port) /* * Configure/autoconfigure the port. */ -static void pl011_config_port(struct uart_port *port, int flags) +static void pl010_config_port(struct uart_port *port, int flags) { if (flags & UART_CONFIG_TYPE) { port->type = PORT_AMBA; - pl011_request_port(port); + pl010_request_port(port); } } /* * verify the new serial_struct (for TIOCSSERIAL). */ -static int pl011_verify_port(struct uart_port *port, struct serial_struct *ser) +static int pl010_verify_port(struct uart_port *port, struct serial_struct *ser) { int ret = 0; if (ser->type != PORT_UNKNOWN && ser->type != PORT_AMBA) @@ -1733,9 +1678,9 @@ static int pl011_verify_port(struct uart_port *port, struct serial_struct *ser) } static struct uart_ops amba_pl011_pops = { - .tx_empty = pl011_tx_empty, + .tx_empty = pl01x_tx_empty, .set_mctrl = pl011_set_mctrl, - .get_mctrl = pl011_get_mctrl, + .get_mctrl = pl01x_get_mctrl, .stop_tx = pl011_stop_tx, .start_tx = pl011_start_tx, .stop_rx = pl011_stop_rx, @@ -1746,14 +1691,13 @@ static struct uart_ops amba_pl011_pops = { .flush_buffer = pl011_dma_flush_buffer, .set_termios = pl011_set_termios, .type = pl011_type, - .release_port = pl011_release_port, - .request_port = pl011_request_port, - .config_port = pl011_config_port, - .verify_port = pl011_verify_port, + .release_port = pl010_release_port, + .request_port = pl010_request_port, + .config_port = pl010_config_port, + .verify_port = pl010_verify_port, #ifdef CONFIG_CONSOLE_POLL - .poll_init = pl011_hwinit, - .poll_get_char = pl011_get_poll_char, - .poll_put_char = pl011_put_poll_char, + .poll_get_char = pl010_get_poll_char, + .poll_put_char = pl010_put_poll_char, #endif }; @@ -1925,38 +1869,6 @@ static struct uart_driver amba_reg = { .cons = AMBA_CONSOLE, }; -static int pl011_probe_dt_alias(int index, struct device *dev) -{ - struct device_node *np; - static bool seen_dev_with_alias = false; - static bool seen_dev_without_alias = false; - int ret = index; - - if (!IS_ENABLED(CONFIG_OF)) - return ret; - - np = dev->of_node; - if (!np) - return ret; - - ret = of_alias_get_id(np, "serial"); - if (IS_ERR_VALUE(ret)) { - seen_dev_without_alias = true; - ret = index; - } else { - seen_dev_with_alias = true; - if (ret >= ARRAY_SIZE(amba_ports) || amba_ports[ret] != NULL) { - dev_warn(dev, "requested serial port %d not available.\n", ret); - ret = index; - } - } - - if (seen_dev_with_alias && seen_dev_without_alias) - dev_warn(dev, "aliased and non-aliased serial devices found in device tree. Serial port enumeration may be unpredictable.\n"); - - return ret; -} - static int pl011_probe(struct amba_device *dev, const struct amba_id *id) { struct uart_amba_port *uap; @@ -1979,8 +1891,6 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id) goto out; } - i = pl011_probe_dt_alias(i, &dev->dev); - base = ioremap(dev->res.start, resource_size(&dev->res)); if (!base) { ret = -ENOMEM; @@ -2013,6 +1923,7 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id) uap->lcrh_tx = vendor->lcrh_tx; uap->old_cr = 0; uap->fifosize = vendor->fifosize; + uap->interrupt_may_hang = vendor->interrupt_may_hang; uap->port.dev = &dev->dev; uap->port.mapbase = dev->res.start; uap->port.membase = base; diff --git a/trunk/drivers/tty/serial/bfin_uart.c b/trunk/drivers/tty/serial/bfin_uart.c index 9242d56ba267..bd97db23985b 100644 --- a/trunk/drivers/tty/serial/bfin_uart.c +++ b/trunk/drivers/tty/serial/bfin_uart.c @@ -182,7 +182,7 @@ static void bfin_serial_start_tx(struct uart_port *port) * To avoid losting RX interrupt, we reset IR function * before sending data. */ - if (tty->termios.c_line == N_IRDA) + if (tty->termios->c_line == N_IRDA) bfin_serial_reset_irda(port); #ifdef CONFIG_SERIAL_BFIN_DMA diff --git a/trunk/drivers/tty/serial/cpm_uart/cpm_uart_core.c b/trunk/drivers/tty/serial/cpm_uart/cpm_uart_core.c index d0dd9194cecc..b418947b7107 100644 --- a/trunk/drivers/tty/serial/cpm_uart/cpm_uart_core.c +++ b/trunk/drivers/tty/serial/cpm_uart/cpm_uart_core.c @@ -71,7 +71,7 @@ static void cpm_uart_initbd(struct uart_cpm_port *pinfo); /**************************************************************/ -#define HW_BUF_SPD_THRESHOLD 2400 +#define HW_BUF_SPD_THRESHOLD 9600 /* * Check, if transmit buffers are processed @@ -417,7 +417,6 @@ static int cpm_uart_startup(struct uart_port *port) clrbits32(&pinfo->sccp->scc_gsmrl, SCC_GSMRL_ENR); clrbits16(&pinfo->sccp->scc_sccm, UART_SCCM_RX); } - cpm_uart_initbd(pinfo); cpm_line_cr_cmd(pinfo, CPM_CR_INIT_TRX); } /* Install interrupt handler. */ @@ -501,28 +500,16 @@ static void cpm_uart_set_termios(struct uart_port *port, struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port; smc_t __iomem *smcp = pinfo->smcp; scc_t __iomem *sccp = pinfo->sccp; - int maxidl; pr_debug("CPM uart[%d]:set_termios\n", port->line); baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk / 16); - if (baud < HW_BUF_SPD_THRESHOLD || + if (baud <= HW_BUF_SPD_THRESHOLD || (pinfo->port.state && pinfo->port.state->port.tty->low_latency)) pinfo->rx_fifosize = 1; else pinfo->rx_fifosize = RX_BUF_SIZE; - /* MAXIDL is the timeout after which a receive buffer is closed - * when not full if no more characters are received. - * We calculate it from the baudrate so that the duration is - * always the same at standard rates: about 4ms. - */ - maxidl = baud / 2400; - if (maxidl < 1) - maxidl = 1; - if (maxidl > 0x10) - maxidl = 0x10; - /* Character length programmed into the mode register is the * sum of: 1 start bit, number of data bits, 0 or 1 parity bit, * 1 or 2 stop bits, minus 1. @@ -623,7 +610,6 @@ static void cpm_uart_set_termios(struct uart_port *port, * SMC/SCC receiver is disabled. */ out_be16(&pinfo->smcup->smc_mrblr, pinfo->rx_fifosize); - out_be16(&pinfo->smcup->smc_maxidl, maxidl); /* Set the mode register. We want to keep a copy of the * enables, because we want to put them back if they were @@ -636,7 +622,6 @@ static void cpm_uart_set_termios(struct uart_port *port, SMCMR_SM_UART | prev_mode); } else { out_be16(&pinfo->sccup->scc_genscc.scc_mrblr, pinfo->rx_fifosize); - out_be16(&pinfo->sccup->scc_maxidl, maxidl); out_be16(&sccp->scc_psmr, (sbits << 12) | scval); } @@ -813,7 +798,7 @@ static void cpm_uart_init_scc(struct uart_cpm_port *pinfo) cpm_set_scc_fcr(sup); out_be16(&sup->scc_genscc.scc_mrblr, pinfo->rx_fifosize); - out_be16(&sup->scc_maxidl, 0x10); + out_be16(&sup->scc_maxidl, pinfo->rx_fifosize); out_be16(&sup->scc_brkcr, 1); out_be16(&sup->scc_parec, 0); out_be16(&sup->scc_frmec, 0); @@ -887,7 +872,7 @@ static void cpm_uart_init_smc(struct uart_cpm_port *pinfo) /* Using idle character time requires some additional tuning. */ out_be16(&up->smc_mrblr, pinfo->rx_fifosize); - out_be16(&up->smc_maxidl, 0x10); + out_be16(&up->smc_maxidl, pinfo->rx_fifosize); out_be16(&up->smc_brklen, 0); out_be16(&up->smc_brkec, 0); out_be16(&up->smc_brkcr, 1); diff --git a/trunk/drivers/tty/serial/crisv10.c b/trunk/drivers/tty/serial/crisv10.c index 35ee6a2c6877..80b6b1b1f725 100644 --- a/trunk/drivers/tty/serial/crisv10.c +++ b/trunk/drivers/tty/serial/crisv10.c @@ -955,7 +955,7 @@ static const struct control_pins e100_modem_pins[NR_PORTS] = /* Calculate the chartime depending on baudrate, numbor of bits etc. */ static void update_char_time(struct e100_serial * info) { - tcflag_t cflags = info->port.tty->termios.c_cflag; + tcflag_t cflags = info->port.tty->termios->c_cflag; int bits; /* calc. number of bits / data byte */ @@ -1473,7 +1473,7 @@ rs_stop(struct tty_struct *tty) xoff = IO_FIELD(R_SERIAL0_XOFF, xoff_char, STOP_CHAR(info->port.tty)); xoff |= IO_STATE(R_SERIAL0_XOFF, tx_stop, stop); - if (tty->termios.c_iflag & IXON ) { + if (tty->termios->c_iflag & IXON ) { xoff |= IO_STATE(R_SERIAL0_XOFF, auto_xoff, enable); } @@ -1496,7 +1496,7 @@ rs_start(struct tty_struct *tty) info->xmit.tail,SERIAL_XMIT_SIZE))); xoff = IO_FIELD(R_SERIAL0_XOFF, xoff_char, STOP_CHAR(tty)); xoff |= IO_STATE(R_SERIAL0_XOFF, tx_stop, enable); - if (tty->termios.c_iflag & IXON ) { + if (tty->termios->c_iflag & IXON ) { xoff |= IO_STATE(R_SERIAL0_XOFF, auto_xoff, enable); } @@ -2929,7 +2929,7 @@ shutdown(struct e100_serial * info) descr[i].buf = 0; } - if (!info->port.tty || (info->port.tty->termios.c_cflag & HUPCL)) { + if (!info->port.tty || (info->port.tty->termios->c_cflag & HUPCL)) { /* hang up DTR and RTS if HUPCL is enabled */ e100_dtr(info, 0); e100_rts(info, 0); /* could check CRTSCTS before doing this */ @@ -2953,12 +2953,12 @@ change_speed(struct e100_serial *info) unsigned long flags; /* first some safety checks */ - if (!info->port.tty) + if (!info->port.tty || !info->port.tty->termios) return; if (!info->ioport) return; - cflag = info->port.tty->termios.c_cflag; + cflag = info->port.tty->termios->c_cflag; /* possibly, the tx/rx should be disabled first to do this safely */ @@ -3088,7 +3088,7 @@ change_speed(struct e100_serial *info) info->ioport[REG_REC_CTRL] = info->rx_ctrl; xoff = IO_FIELD(R_SERIAL0_XOFF, xoff_char, STOP_CHAR(info->port.tty)); xoff |= IO_STATE(R_SERIAL0_XOFF, tx_stop, enable); - if (info->port.tty->termios.c_iflag & IXON ) { + if (info->port.tty->termios->c_iflag & IXON ) { DFLOW(DEBUG_LOG(info->line, "FLOW XOFF enabled 0x%02X\n", STOP_CHAR(info->port.tty))); xoff |= IO_STATE(R_SERIAL0_XOFF, auto_xoff, enable); @@ -3355,7 +3355,7 @@ rs_throttle(struct tty_struct * tty) DFLOW(DEBUG_LOG(info->line,"rs_throttle %lu\n", tty->ldisc.chars_in_buffer(tty))); /* Do RTS before XOFF since XOFF might take some time */ - if (tty->termios.c_cflag & CRTSCTS) { + if (tty->termios->c_cflag & CRTSCTS) { /* Turn off RTS line */ e100_rts(info, 0); } @@ -3377,7 +3377,7 @@ rs_unthrottle(struct tty_struct * tty) DFLOW(DEBUG_LOG(info->line,"rs_unthrottle ldisc %d\n", tty->ldisc.chars_in_buffer(tty))); DFLOW(DEBUG_LOG(info->line,"rs_unthrottle flip.count: %i\n", tty->flip.count)); /* Do RTS before XOFF since XOFF might take some time */ - if (tty->termios.c_cflag & CRTSCTS) { + if (tty->termios->c_cflag & CRTSCTS) { /* Assert RTS line */ e100_rts(info, 1); } @@ -3748,7 +3748,7 @@ rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios) /* Handle turning off CRTSCTS */ if ((old_termios->c_cflag & CRTSCTS) && - !(tty->termios.c_cflag & CRTSCTS)) { + !(tty->termios->c_cflag & CRTSCTS)) { tty->hw_stopped = 0; rs_start(tty); } @@ -3815,7 +3815,7 @@ rs_close(struct tty_struct *tty, struct file * filp) * separate termios for callout and dialin. */ if (info->flags & ASYNC_NORMAL_ACTIVE) - info->normal_termios = tty->termios; + info->normal_termios = *tty->termios; /* * Now we wait for the transmit buffer to clear; and we notify * the line discipline to only process XON/XOFF characters. @@ -3976,7 +3976,7 @@ block_til_ready(struct tty_struct *tty, struct file * filp, */ if (tty_hung_up_p(filp) || (info->flags & ASYNC_CLOSING)) { - wait_event_interruptible_tty(tty, info->close_wait, + wait_event_interruptible_tty(info->close_wait, !(info->flags & ASYNC_CLOSING)); #ifdef SERIAL_DO_RESTART if (info->flags & ASYNC_HUP_NOTIFY) @@ -3998,7 +3998,7 @@ block_til_ready(struct tty_struct *tty, struct file * filp, return 0; } - if (tty->termios.c_cflag & CLOCAL) { + if (tty->termios->c_cflag & CLOCAL) { do_clocal = 1; } @@ -4052,9 +4052,9 @@ block_til_ready(struct tty_struct *tty, struct file * filp, printk("block_til_ready blocking: ttyS%d, count = %d\n", info->line, info->count); #endif - tty_unlock(tty); + tty_unlock(); schedule(); - tty_lock(tty); + tty_lock(); } set_current_state(TASK_RUNNING); remove_wait_queue(&info->open_wait, &wait); @@ -4115,7 +4115,7 @@ rs_open(struct tty_struct *tty, struct file * filp) */ if (tty_hung_up_p(filp) || (info->flags & ASYNC_CLOSING)) { - wait_event_interruptible_tty(tty, info->close_wait, + wait_event_interruptible_tty(info->close_wait, !(info->flags & ASYNC_CLOSING)); #ifdef SERIAL_DO_RESTART return ((info->flags & ASYNC_HUP_NOTIFY) ? @@ -4219,7 +4219,7 @@ rs_open(struct tty_struct *tty, struct file * filp) } if ((info->count == 1) && (info->flags & ASYNC_SPLIT_TERMIOS)) { - tty->termios = info->normal_termios; + *tty->termios = info->normal_termios; change_speed(info); } @@ -4443,12 +4443,14 @@ static int __init rs_init(void) B115200 | CS8 | CREAD | HUPCL | CLOCAL; /* is normally B9600 default... */ driver->init_termios.c_ispeed = 115200; driver->init_termios.c_ospeed = 115200; - driver->flags = TTY_DRIVER_REAL_RAW; + driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV; tty_set_operations(driver, &rs_ops); serial_driver = driver; - + if (tty_register_driver(driver)) + panic("Couldn't register serial driver\n"); /* do some initializing for the separate ports */ + for (i = 0, info = rs_table; i < NR_PORTS; i++,info++) { if (info->enabled) { if (cris_request_io_interface(info->io_if, @@ -4500,12 +4502,7 @@ static int __init rs_init(void) printk(KERN_INFO "%s%d at %p is a builtin UART with DMA\n", serial_driver->name, info->line, info->ioport); } - tty_port_link_device(&info->port, driver, i); } - - if (tty_register_driver(driver)) - panic("Couldn't register serial driver\n"); - #ifdef CONFIG_ETRAX_FAST_TIMER #ifdef CONFIG_ETRAX_SERIAL_FAST_TIMER memset(fast_timers, 0, sizeof(fast_timers)); diff --git a/trunk/drivers/tty/serial/ifx6x60.c b/trunk/drivers/tty/serial/ifx6x60.c index 5b9bc19ed134..144cd3987d4c 100644 --- a/trunk/drivers/tty/serial/ifx6x60.c +++ b/trunk/drivers/tty/serial/ifx6x60.c @@ -800,8 +800,8 @@ static int ifx_spi_create_port(struct ifx_spi_device *ifx_dev) tty_port_init(pport); pport->ops = &ifx_tty_port_ops; ifx_dev->minor = IFX_SPI_TTY_ID; - ifx_dev->tty_dev = tty_port_register_device(pport, tty_drv, - ifx_dev->minor, &ifx_dev->spi_dev->dev); + ifx_dev->tty_dev = tty_register_device(tty_drv, ifx_dev->minor, + &ifx_dev->spi_dev->dev); if (IS_ERR(ifx_dev->tty_dev)) { dev_dbg(&ifx_dev->spi_dev->dev, "%s: registering tty device failed", __func__); @@ -1331,7 +1331,7 @@ static const struct spi_device_id ifx_id_table[] = { MODULE_DEVICE_TABLE(spi, ifx_id_table); /* spi operations */ -static struct spi_driver ifx_spi_driver = { +static const struct spi_driver ifx_spi_driver = { .driver = { .name = DRVNAME, .pm = &ifx_spi_pm, diff --git a/trunk/drivers/tty/serial/imx.c b/trunk/drivers/tty/serial/imx.c index efeb8becfa43..d5c689d6217e 100644 --- a/trunk/drivers/tty/serial/imx.c +++ b/trunk/drivers/tty/serial/imx.c @@ -132,7 +132,6 @@ #define UCR4_OREN (1<<1) /* Receiver overrun interrupt enable */ #define UCR4_DREN (1<<0) /* Recv data ready interrupt enable */ #define UFCR_RXTL_SHF 0 /* Receiver trigger level shift */ -#define UFCR_DCEDTE (1<<6) /* DCE/DTE mode select */ #define UFCR_RFDIV (7<<7) /* Reference freq divider mask */ #define UFCR_RFDIV_REG(x) (((x) < 7 ? 6 - (x) : 6) << 7) #define UFCR_TXTL_SHF 10 /* Transmitter trigger level shift */ @@ -207,7 +206,7 @@ struct imx_port { unsigned short trcv_delay; /* transceiver delay */ struct clk *clk_ipg; struct clk *clk_per; - const struct imx_uart_data *devdata; + struct imx_uart_data *devdata; }; struct imx_port_ucrs { @@ -668,11 +667,22 @@ static void imx_break_ctl(struct uart_port *port, int break_state) static int imx_setup_ufcr(struct imx_port *sport, unsigned int mode) { unsigned int val; + unsigned int ufcr_rfdiv; + + /* set receiver / transmitter trigger level. + * RFDIV is set such way to satisfy requested uartclk value + */ + val = TXTL << 10 | RXTL; + ufcr_rfdiv = (clk_get_rate(sport->clk_per) + sport->port.uartclk / 2) + / sport->port.uartclk; + + if(!ufcr_rfdiv) + ufcr_rfdiv = 1; + + val |= UFCR_RFDIV_REG(ufcr_rfdiv); - /* set receiver / transmitter trigger level */ - val = readl(sport->port.membase + UFCR) & (UFCR_RFDIV | UFCR_DCEDTE); - val |= TXTL << UFCR_TXTL_SHF | RXTL; writel(val, sport->port.membase + UFCR); + return 0; } @@ -744,7 +754,6 @@ static int imx_startup(struct uart_port *port) } } - spin_lock_irqsave(&sport->port.lock, flags); /* * Finally, clear and enable interrupts */ @@ -798,6 +807,7 @@ static int imx_startup(struct uart_port *port) /* * Enable modem status interrupts */ + spin_lock_irqsave(&sport->port.lock,flags); imx_enable_ms(&sport->port); spin_unlock_irqrestore(&sport->port.lock,flags); @@ -827,13 +837,10 @@ static void imx_shutdown(struct uart_port *port) { struct imx_port *sport = (struct imx_port *)port; unsigned long temp; - unsigned long flags; - spin_lock_irqsave(&sport->port.lock, flags); temp = readl(sport->port.membase + UCR2); temp &= ~(UCR2_TXEN); writel(temp, sport->port.membase + UCR2); - spin_unlock_irqrestore(&sport->port.lock, flags); if (USE_IRDA(sport)) { struct imxuart_platform_data *pdata; @@ -862,14 +869,12 @@ static void imx_shutdown(struct uart_port *port) * Disable all interrupts, port and break condition. */ - spin_lock_irqsave(&sport->port.lock, flags); temp = readl(sport->port.membase + UCR1); temp &= ~(UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_RTSDEN | UCR1_UARTEN); if (USE_IRDA(sport)) temp &= ~(UCR1_IREN); writel(temp, sport->port.membase + UCR1); - spin_unlock_irqrestore(&sport->port.lock, flags); } static void @@ -1212,9 +1217,6 @@ imx_console_write(struct console *co, const char *s, unsigned int count) struct imx_port *sport = imx_ports[co->index]; struct imx_port_ucrs old_ucr; unsigned int ucr1; - unsigned long flags; - - spin_lock_irqsave(&sport->port.lock, flags); /* * First, save UCR1/2/3 and then disable interrupts @@ -1240,8 +1242,6 @@ imx_console_write(struct console *co, const char *s, unsigned int count) while (!(readl(sport->port.membase + USR2) & USR2_TXDC)); imx_port_ucrs_restore(&sport->port, &old_ucr); - - spin_unlock_irqrestore(&sport->port.lock, flags); } /* @@ -1373,7 +1373,8 @@ static int serial_imx_suspend(struct platform_device *dev, pm_message_t state) val |= UCR3_AWAKEN; writel(val, sport->port.membase + UCR3); - uart_suspend_port(&imx_reg, &sport->port); + if (sport) + uart_suspend_port(&imx_reg, &sport->port); return 0; } @@ -1388,7 +1389,8 @@ static int serial_imx_resume(struct platform_device *dev) val &= ~UCR3_AWAKEN; writel(val, sport->port.membase + UCR3); - uart_resume_port(&imx_reg, &sport->port); + if (sport) + uart_resume_port(&imx_reg, &sport->port); return 0; } @@ -1503,21 +1505,18 @@ static int serial_imx_probe(struct platform_device *pdev) pinctrl = devm_pinctrl_get_select_default(&pdev->dev); if (IS_ERR(pinctrl)) { ret = PTR_ERR(pinctrl); - dev_err(&pdev->dev, "failed to get default pinctrl: %d\n", ret); goto unmap; } sport->clk_ipg = devm_clk_get(&pdev->dev, "ipg"); if (IS_ERR(sport->clk_ipg)) { ret = PTR_ERR(sport->clk_ipg); - dev_err(&pdev->dev, "failed to get ipg clk: %d\n", ret); goto unmap; } sport->clk_per = devm_clk_get(&pdev->dev, "per"); if (IS_ERR(sport->clk_per)) { ret = PTR_ERR(sport->clk_per); - dev_err(&pdev->dev, "failed to get per clk: %d\n", ret); goto unmap; } @@ -1538,7 +1537,7 @@ static int serial_imx_probe(struct platform_device *pdev) ret = uart_add_one_port(&imx_reg, &sport->port); if (ret) goto deinit; - platform_set_drvdata(pdev, sport); + platform_set_drvdata(pdev, &sport->port); return 0; deinit: diff --git a/trunk/drivers/tty/serial/ioc3_serial.c b/trunk/drivers/tty/serial/ioc3_serial.c index 5ac52898a0bb..758ff310f7f8 100644 --- a/trunk/drivers/tty/serial/ioc3_serial.c +++ b/trunk/drivers/tty/serial/ioc3_serial.c @@ -1120,14 +1120,13 @@ static inline int do_read(struct uart_port *the_port, char *buf, int len) struct ioc3_port *port = get_ioc3_port(the_port); struct ring *inring; struct ring_entry *entry; - struct port_hooks *hooks; + struct port_hooks *hooks = port->ip_hooks; int byte_num; char *sc; int loop_counter; BUG_ON(!(len >= 0)); BUG_ON(!port); - hooks = port->ip_hooks; /* There is a nasty timing issue in the IOC3. When the rx_timer * expires or the rx_high condition arises, we take an interrupt. diff --git a/trunk/drivers/tty/serial/ioc4_serial.c b/trunk/drivers/tty/serial/ioc4_serial.c index 3e7da10cebba..e16894fb2ca3 100644 --- a/trunk/drivers/tty/serial/ioc4_serial.c +++ b/trunk/drivers/tty/serial/ioc4_serial.c @@ -1803,7 +1803,7 @@ static inline int ic4_startup_local(struct uart_port *the_port) ioc4_set_proto(port, the_port->mapbase); /* set the speed of the serial port */ - ioc4_change_speed(the_port, &state->port.tty->termios, + ioc4_change_speed(the_port, state->port.tty->termios, (struct ktermios *)0); return 0; @@ -2069,14 +2069,13 @@ static inline int do_read(struct uart_port *the_port, unsigned char *buf, struct ioc4_port *port = get_ioc4_port(the_port, 0); struct ring *inring; struct ring_entry *entry; - struct hooks *hooks; + struct hooks *hooks = port->ip_hooks; int byte_num; char *sc; int loop_counter; BUG_ON(!(len >= 0)); BUG_ON(!port); - hooks = port->ip_hooks; /* There is a nasty timing issue in the IOC4. When the rx_timer * expires or the rx_high condition arises, we take an interrupt. diff --git a/trunk/drivers/tty/serial/jsm/jsm_driver.c b/trunk/drivers/tty/serial/jsm/jsm_driver.c index 5ab3c3b595e4..7545fe1b9925 100644 --- a/trunk/drivers/tty/serial/jsm/jsm_driver.c +++ b/trunk/drivers/tty/serial/jsm/jsm_driver.c @@ -54,7 +54,7 @@ static pci_ers_result_t jsm_io_error_detected(struct pci_dev *pdev, static pci_ers_result_t jsm_io_slot_reset(struct pci_dev *pdev); static void jsm_io_resume(struct pci_dev *pdev); -static const struct pci_error_handlers jsm_err_handler = { +static struct pci_error_handlers jsm_err_handler = { .error_detected = jsm_io_error_detected, .slot_reset = jsm_io_slot_reset, .resume = jsm_io_resume, diff --git a/trunk/drivers/tty/serial/jsm/jsm_tty.c b/trunk/drivers/tty/serial/jsm/jsm_tty.c index 71397961773c..434bd881fcae 100644 --- a/trunk/drivers/tty/serial/jsm/jsm_tty.c +++ b/trunk/drivers/tty/serial/jsm/jsm_tty.c @@ -161,7 +161,7 @@ static void jsm_tty_send_xchar(struct uart_port *port, char ch) struct ktermios *termios; spin_lock_irqsave(&port->lock, lock_flags); - termios = &port->state->port.tty->termios; + termios = port->state->port.tty->termios; if (ch == termios->c_cc[VSTART]) channel->ch_bd->bd_ops->send_start_character(channel); @@ -250,7 +250,7 @@ static int jsm_tty_open(struct uart_port *port) channel->ch_cached_lsr = 0; channel->ch_stops_sent = 0; - termios = &port->state->port.tty->termios; + termios = port->state->port.tty->termios; channel->ch_c_cflag = termios->c_cflag; channel->ch_c_iflag = termios->c_iflag; channel->ch_c_oflag = termios->c_oflag; @@ -283,7 +283,7 @@ static void jsm_tty_close(struct uart_port *port) jsm_printk(CLOSE, INFO, &channel->ch_bd->pci_dev, "start\n"); bd = channel->ch_bd; - ts = &port->state->port.tty->termios; + ts = port->state->port.tty->termios; channel->ch_flags &= ~(CH_STOPI); @@ -567,7 +567,7 @@ void jsm_input(struct jsm_channel *ch) *input data and return immediately. */ if (!tp || - !(tp->termios.c_cflag & CREAD) ) { + !(tp->termios->c_cflag & CREAD) ) { jsm_printk(READ, INFO, &ch->ch_bd->pci_dev, "input. dropping %d bytes on port %d...\n", data_len, ch->ch_portnum); diff --git a/trunk/drivers/tty/serial/kgdb_nmi.c b/trunk/drivers/tty/serial/kgdb_nmi.c deleted file mode 100644 index d185247ba1aa..000000000000 --- a/trunk/drivers/tty/serial/kgdb_nmi.c +++ /dev/null @@ -1,402 +0,0 @@ -/* - * KGDB NMI serial console - * - * Copyright 2010 Google, Inc. - * Arve Hjønnevåg - * Colin Cross - * Copyright 2012 Linaro Ltd. - * Anton Vorontsov - * - * 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static int kgdb_nmi_knock = 1; -module_param_named(knock, kgdb_nmi_knock, int, 0600); -MODULE_PARM_DESC(knock, "if set to 1 (default), the special '$3#33' command " \ - "must be used to enter the debugger; when set to 0, " \ - "hitting return key is enough to enter the debugger; " \ - "when set to -1, the debugger is entered immediately " \ - "upon NMI"); - -static char *kgdb_nmi_magic = "$3#33"; -module_param_named(magic, kgdb_nmi_magic, charp, 0600); -MODULE_PARM_DESC(magic, "magic sequence to enter NMI debugger (default $3#33)"); - -static bool kgdb_nmi_tty_enabled; - -static void kgdb_nmi_console_write(struct console *co, const char *s, uint c) -{ - int i; - - if (!kgdb_nmi_tty_enabled || atomic_read(&kgdb_active) >= 0) - return; - - for (i = 0; i < c; i++) - dbg_io_ops->write_char(s[i]); -} - -static struct tty_driver *kgdb_nmi_tty_driver; - -static struct tty_driver *kgdb_nmi_console_device(struct console *co, int *idx) -{ - *idx = co->index; - return kgdb_nmi_tty_driver; -} - -static struct console kgdb_nmi_console = { - .name = "ttyNMI", - .write = kgdb_nmi_console_write, - .device = kgdb_nmi_console_device, - .flags = CON_PRINTBUFFER | CON_ANYTIME | CON_ENABLED, - .index = -1, -}; - -/* - * This is usually the maximum rate on debug ports. We make fifo large enough - * to make copy-pasting to the terminal usable. - */ -#define KGDB_NMI_BAUD 115200 -#define KGDB_NMI_FIFO_SIZE roundup_pow_of_two(KGDB_NMI_BAUD / 8 / HZ) - -struct kgdb_nmi_tty_priv { - struct tty_port port; - struct tasklet_struct tlet; - STRUCT_KFIFO(char, KGDB_NMI_FIFO_SIZE) fifo; -}; - -static struct kgdb_nmi_tty_priv *kgdb_nmi_port_to_priv(struct tty_port *port) -{ - return container_of(port, struct kgdb_nmi_tty_priv, port); -} - -/* - * Our debugging console is polled in a tasklet, so we'll check for input - * every tick. In HZ-less mode, we should program the next tick. We have - * to use the lowlevel stuff as no locks should be grabbed. - */ -#ifdef CONFIG_HIGH_RES_TIMERS -static void kgdb_tty_poke(void) -{ - tick_program_event(ktime_get(), 0); -} -#else -static inline void kgdb_tty_poke(void) {} -#endif - -static struct tty_port *kgdb_nmi_port; - -static void kgdb_tty_recv(int ch) -{ - struct kgdb_nmi_tty_priv *priv; - char c = ch; - - if (!kgdb_nmi_port || ch < 0) - return; - /* - * Can't use port->tty->driver_data as tty might be not there. Tasklet - * will check for tty and will get the ref, but here we don't have to - * do that, and actually, we can't: we're in NMI context, no locks are - * possible. - */ - priv = kgdb_nmi_port_to_priv(kgdb_nmi_port); - kfifo_in(&priv->fifo, &c, 1); - kgdb_tty_poke(); -} - -static int kgdb_nmi_poll_one_knock(void) -{ - static int n; - int c = -1; - const char *magic = kgdb_nmi_magic; - size_t m = strlen(magic); - bool printch = 0; - - c = dbg_io_ops->read_char(); - if (c == NO_POLL_CHAR) - return c; - - if (!kgdb_nmi_knock && (c == '\r' || c == '\n')) { - return 1; - } else if (c == magic[n]) { - n = (n + 1) % m; - if (!n) - return 1; - printch = 1; - } else { - n = 0; - } - - if (kgdb_nmi_tty_enabled) { - kgdb_tty_recv(c); - return 0; - } - - if (printch) { - kdb_printf("%c", c); - return 0; - } - - kdb_printf("\r%s %s to enter the debugger> %*s", - kgdb_nmi_knock ? "Type" : "Hit", - kgdb_nmi_knock ? magic : "", (int)m, ""); - while (m--) - kdb_printf("\b"); - return 0; -} - -/** - * kgdb_nmi_poll_knock - Check if it is time to enter the debugger - * - * "Serial ports are often noisy, especially when muxed over another port (we - * often use serial over the headset connector). Noise on the async command - * line just causes characters that are ignored, on a command line that blocked - * execution noise would be catastrophic." -- Colin Cross - * - * So, this function implements KGDB/KDB knocking on the serial line: we won't - * enter the debugger until we receive a known magic phrase (which is actually - * "$3#33", known as "escape to KDB" command. There is also a relaxed variant - * of knocking, i.e. just pressing the return key is enough to enter the - * debugger. And if knocking is disabled, the function always returns 1. - */ -bool kgdb_nmi_poll_knock(void) -{ - if (kgdb_nmi_knock < 0) - return 1; - - while (1) { - int ret; - - ret = kgdb_nmi_poll_one_knock(); - if (ret == NO_POLL_CHAR) - return 0; - else if (ret == 1) - break; - } - return 1; -} - -/* - * The tasklet is cheap, it does not cause wakeups when reschedules itself, - * instead it waits for the next tick. - */ -static void kgdb_nmi_tty_receiver(unsigned long data) -{ - struct kgdb_nmi_tty_priv *priv = (void *)data; - struct tty_struct *tty; - char ch; - - tasklet_schedule(&priv->tlet); - - if (likely(!kgdb_nmi_tty_enabled || !kfifo_len(&priv->fifo))) - return; - - /* Port is there, but tty might be hung up, check. */ - tty = tty_port_tty_get(kgdb_nmi_port); - if (!tty) - return; - - while (kfifo_out(&priv->fifo, &ch, 1)) - tty_insert_flip_char(priv->port.tty, ch, TTY_NORMAL); - tty_flip_buffer_push(priv->port.tty); - - tty_kref_put(tty); -} - -static int kgdb_nmi_tty_activate(struct tty_port *port, struct tty_struct *tty) -{ - struct kgdb_nmi_tty_priv *priv = tty->driver_data; - - kgdb_nmi_port = port; - tasklet_schedule(&priv->tlet); - return 0; -} - -static void kgdb_nmi_tty_shutdown(struct tty_port *port) -{ - struct kgdb_nmi_tty_priv *priv = port->tty->driver_data; - - tasklet_kill(&priv->tlet); - kgdb_nmi_port = NULL; -} - -static const struct tty_port_operations kgdb_nmi_tty_port_ops = { - .activate = kgdb_nmi_tty_activate, - .shutdown = kgdb_nmi_tty_shutdown, -}; - -static int kgdb_nmi_tty_install(struct tty_driver *drv, struct tty_struct *tty) -{ - struct kgdb_nmi_tty_priv *priv; - int ret; - - priv = kzalloc(sizeof(*priv), GFP_KERNEL); - if (!priv) - return -ENOMEM; - - INIT_KFIFO(priv->fifo); - tasklet_init(&priv->tlet, kgdb_nmi_tty_receiver, (unsigned long)priv); - tty_port_init(&priv->port); - priv->port.ops = &kgdb_nmi_tty_port_ops; - tty->driver_data = priv; - - ret = tty_port_install(&priv->port, drv, tty); - if (ret) { - pr_err("%s: can't install tty port: %d\n", __func__, ret); - goto err; - } - return 0; -err: - kfree(priv); - return ret; -} - -static void kgdb_nmi_tty_cleanup(struct tty_struct *tty) -{ - struct kgdb_nmi_tty_priv *priv = tty->driver_data; - - tty->driver_data = NULL; - kfree(priv); -} - -static int kgdb_nmi_tty_open(struct tty_struct *tty, struct file *file) -{ - struct kgdb_nmi_tty_priv *priv = tty->driver_data; - - return tty_port_open(&priv->port, tty, file); -} - -static void kgdb_nmi_tty_close(struct tty_struct *tty, struct file *file) -{ - struct kgdb_nmi_tty_priv *priv = tty->driver_data; - - tty_port_close(&priv->port, tty, file); -} - -static void kgdb_nmi_tty_hangup(struct tty_struct *tty) -{ - struct kgdb_nmi_tty_priv *priv = tty->driver_data; - - tty_port_hangup(&priv->port); -} - -static int kgdb_nmi_tty_write_room(struct tty_struct *tty) -{ - /* Actually, we can handle any amount as we use polled writes. */ - return 2048; -} - -static int kgdb_nmi_tty_write(struct tty_struct *tty, const unchar *buf, int c) -{ - int i; - - for (i = 0; i < c; i++) - dbg_io_ops->write_char(buf[i]); - return c; -} - -static const struct tty_operations kgdb_nmi_tty_ops = { - .open = kgdb_nmi_tty_open, - .close = kgdb_nmi_tty_close, - .install = kgdb_nmi_tty_install, - .cleanup = kgdb_nmi_tty_cleanup, - .hangup = kgdb_nmi_tty_hangup, - .write_room = kgdb_nmi_tty_write_room, - .write = kgdb_nmi_tty_write, -}; - -static int kgdb_nmi_enable_console(int argc, const char *argv[]) -{ - kgdb_nmi_tty_enabled = !(argc == 1 && !strcmp(argv[1], "off")); - return 0; -} - -int kgdb_register_nmi_console(void) -{ - int ret; - - if (!arch_kgdb_ops.enable_nmi) - return 0; - - kgdb_nmi_tty_driver = alloc_tty_driver(1); - if (!kgdb_nmi_tty_driver) { - pr_err("%s: cannot allocate tty\n", __func__); - return -ENOMEM; - } - kgdb_nmi_tty_driver->driver_name = "ttyNMI"; - kgdb_nmi_tty_driver->name = "ttyNMI"; - kgdb_nmi_tty_driver->num = 1; - kgdb_nmi_tty_driver->type = TTY_DRIVER_TYPE_SERIAL; - kgdb_nmi_tty_driver->subtype = SERIAL_TYPE_NORMAL; - kgdb_nmi_tty_driver->flags = TTY_DRIVER_REAL_RAW; - kgdb_nmi_tty_driver->init_termios = tty_std_termios; - tty_termios_encode_baud_rate(&kgdb_nmi_tty_driver->init_termios, - KGDB_NMI_BAUD, KGDB_NMI_BAUD); - tty_set_operations(kgdb_nmi_tty_driver, &kgdb_nmi_tty_ops); - - ret = tty_register_driver(kgdb_nmi_tty_driver); - if (ret) { - pr_err("%s: can't register tty driver: %d\n", __func__, ret); - goto err_drv_reg; - } - - ret = kdb_register("nmi_console", kgdb_nmi_enable_console, "[off]", - "switch to Linux NMI console", 0); - if (ret) { - pr_err("%s: can't register kdb command: %d\n", __func__, ret); - goto err_kdb_reg; - } - - register_console(&kgdb_nmi_console); - arch_kgdb_ops.enable_nmi(1); - - return 0; -err_kdb_reg: - tty_unregister_driver(kgdb_nmi_tty_driver); -err_drv_reg: - put_tty_driver(kgdb_nmi_tty_driver); - return ret; -} -EXPORT_SYMBOL_GPL(kgdb_register_nmi_console); - -int kgdb_unregister_nmi_console(void) -{ - int ret; - - if (!arch_kgdb_ops.enable_nmi) - return 0; - arch_kgdb_ops.enable_nmi(0); - - kdb_unregister("nmi_console"); - - ret = unregister_console(&kgdb_nmi_console); - if (ret) - return ret; - - ret = tty_unregister_driver(kgdb_nmi_tty_driver); - if (ret) - return ret; - put_tty_driver(kgdb_nmi_tty_driver); - - return 0; -} -EXPORT_SYMBOL_GPL(kgdb_unregister_nmi_console); diff --git a/trunk/drivers/tty/serial/kgdboc.c b/trunk/drivers/tty/serial/kgdboc.c index 3f63d834cbc9..2b42a01a81c6 100644 --- a/trunk/drivers/tty/serial/kgdboc.c +++ b/trunk/drivers/tty/serial/kgdboc.c @@ -145,8 +145,6 @@ __setup("kgdboc=", kgdboc_option_setup); static void cleanup_kgdboc(void) { - if (kgdb_unregister_nmi_console()) - return; kgdboc_unregister_kbd(); if (configured == 1) kgdb_unregister_io_module(&kgdboc_io_ops); @@ -200,18 +198,11 @@ static int configure_kgdboc(void) if (err) goto noconfig; - err = kgdb_register_nmi_console(); - if (err) - goto nmi_con_failed; - configured = 1; return 0; -nmi_con_failed: - kgdb_unregister_io_module(&kgdboc_io_ops); noconfig: - kgdboc_unregister_kbd(); config[0] = 0; configured = 0; cleanup_kgdboc(); diff --git a/trunk/drivers/tty/serial/lpc32xx_hs.c b/trunk/drivers/tty/serial/lpc32xx_hs.c deleted file mode 100644 index ba3af3bf6d43..000000000000 --- a/trunk/drivers/tty/serial/lpc32xx_hs.c +++ /dev/null @@ -1,823 +0,0 @@ -/* - * High Speed Serial Ports on NXP LPC32xx SoC - * - * Authors: Kevin Wells - * Roland Stigge - * - * Copyright (C) 2010 NXP Semiconductors - * Copyright (C) 2012 Roland Stigge - * - * 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. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* - * High Speed UART register offsets - */ -#define LPC32XX_HSUART_FIFO(x) ((x) + 0x00) -#define LPC32XX_HSUART_LEVEL(x) ((x) + 0x04) -#define LPC32XX_HSUART_IIR(x) ((x) + 0x08) -#define LPC32XX_HSUART_CTRL(x) ((x) + 0x0C) -#define LPC32XX_HSUART_RATE(x) ((x) + 0x10) - -#define LPC32XX_HSU_BREAK_DATA (1 << 10) -#define LPC32XX_HSU_ERROR_DATA (1 << 9) -#define LPC32XX_HSU_RX_EMPTY (1 << 8) - -#define LPC32XX_HSU_TX_LEV(n) (((n) >> 8) & 0xFF) -#define LPC32XX_HSU_RX_LEV(n) ((n) & 0xFF) - -#define LPC32XX_HSU_TX_INT_SET (1 << 6) -#define LPC32XX_HSU_RX_OE_INT (1 << 5) -#define LPC32XX_HSU_BRK_INT (1 << 4) -#define LPC32XX_HSU_FE_INT (1 << 3) -#define LPC32XX_HSU_RX_TIMEOUT_INT (1 << 2) -#define LPC32XX_HSU_RX_TRIG_INT (1 << 1) -#define LPC32XX_HSU_TX_INT (1 << 0) - -#define LPC32XX_HSU_HRTS_INV (1 << 21) -#define LPC32XX_HSU_HRTS_TRIG_8B (0x0 << 19) -#define LPC32XX_HSU_HRTS_TRIG_16B (0x1 << 19) -#define LPC32XX_HSU_HRTS_TRIG_32B (0x2 << 19) -#define LPC32XX_HSU_HRTS_TRIG_48B (0x3 << 19) -#define LPC32XX_HSU_HRTS_EN (1 << 18) -#define LPC32XX_HSU_TMO_DISABLED (0x0 << 16) -#define LPC32XX_HSU_TMO_INACT_4B (0x1 << 16) -#define LPC32XX_HSU_TMO_INACT_8B (0x2 << 16) -#define LPC32XX_HSU_TMO_INACT_16B (0x3 << 16) -#define LPC32XX_HSU_HCTS_INV (1 << 15) -#define LPC32XX_HSU_HCTS_EN (1 << 14) -#define LPC32XX_HSU_OFFSET(n) ((n) << 9) -#define LPC32XX_HSU_BREAK (1 << 8) -#define LPC32XX_HSU_ERR_INT_EN (1 << 7) -#define LPC32XX_HSU_RX_INT_EN (1 << 6) -#define LPC32XX_HSU_TX_INT_EN (1 << 5) -#define LPC32XX_HSU_RX_TL1B (0x0 << 2) -#define LPC32XX_HSU_RX_TL4B (0x1 << 2) -#define LPC32XX_HSU_RX_TL8B (0x2 << 2) -#define LPC32XX_HSU_RX_TL16B (0x3 << 2) -#define LPC32XX_HSU_RX_TL32B (0x4 << 2) -#define LPC32XX_HSU_RX_TL48B (0x5 << 2) -#define LPC32XX_HSU_TX_TLEMPTY (0x0 << 0) -#define LPC32XX_HSU_TX_TL0B (0x0 << 0) -#define LPC32XX_HSU_TX_TL4B (0x1 << 0) -#define LPC32XX_HSU_TX_TL8B (0x2 << 0) -#define LPC32XX_HSU_TX_TL16B (0x3 << 0) - -#define MODNAME "lpc32xx_hsuart" - -struct lpc32xx_hsuart_port { - struct uart_port port; -}; - -#define FIFO_READ_LIMIT 128 -#define MAX_PORTS 3 -#define LPC32XX_TTY_NAME "ttyTX" -static struct lpc32xx_hsuart_port lpc32xx_hs_ports[MAX_PORTS]; - -#ifdef CONFIG_SERIAL_HS_LPC32XX_CONSOLE -static void wait_for_xmit_empty(struct uart_port *port) -{ - unsigned int timeout = 10000; - - do { - if (LPC32XX_HSU_TX_LEV(readl(LPC32XX_HSUART_LEVEL( - port->membase))) == 0) - break; - if (--timeout == 0) - break; - udelay(1); - } while (1); -} - -static void wait_for_xmit_ready(struct uart_port *port) -{ - unsigned int timeout = 10000; - - while (1) { - if (LPC32XX_HSU_TX_LEV(readl(LPC32XX_HSUART_LEVEL( - port->membase))) < 32) - break; - if (--timeout == 0) - break; - udelay(1); - } -} - -static void lpc32xx_hsuart_console_putchar(struct uart_port *port, int ch) -{ - wait_for_xmit_ready(port); - writel((u32)ch, LPC32XX_HSUART_FIFO(port->membase)); -} - -static void lpc32xx_hsuart_console_write(struct console *co, const char *s, - unsigned int count) -{ - struct lpc32xx_hsuart_port *up = &lpc32xx_hs_ports[co->index]; - unsigned long flags; - int locked = 1; - - touch_nmi_watchdog(); - local_irq_save(flags); - if (up->port.sysrq) - locked = 0; - else if (oops_in_progress) - locked = spin_trylock(&up->port.lock); - else - spin_lock(&up->port.lock); - - uart_console_write(&up->port, s, count, lpc32xx_hsuart_console_putchar); - wait_for_xmit_empty(&up->port); - - if (locked) - spin_unlock(&up->port.lock); - local_irq_restore(flags); -} - -static int __init lpc32xx_hsuart_console_setup(struct console *co, - char *options) -{ - struct uart_port *port; - int baud = 115200; - int bits = 8; - int parity = 'n'; - int flow = 'n'; - - if (co->index >= MAX_PORTS) - co->index = 0; - - port = &lpc32xx_hs_ports[co->index].port; - if (!port->membase) - return -ENODEV; - - if (options) - uart_parse_options(options, &baud, &parity, &bits, &flow); - - return uart_set_options(port, co, baud, parity, bits, flow); -} - -static struct uart_driver lpc32xx_hsuart_reg; -static struct console lpc32xx_hsuart_console = { - .name = LPC32XX_TTY_NAME, - .write = lpc32xx_hsuart_console_write, - .device = uart_console_device, - .setup = lpc32xx_hsuart_console_setup, - .flags = CON_PRINTBUFFER, - .index = -1, - .data = &lpc32xx_hsuart_reg, -}; - -static int __init lpc32xx_hsuart_console_init(void) -{ - register_console(&lpc32xx_hsuart_console); - return 0; -} -console_initcall(lpc32xx_hsuart_console_init); - -#define LPC32XX_HSUART_CONSOLE (&lpc32xx_hsuart_console) -#else -#define LPC32XX_HSUART_CONSOLE NULL -#endif - -static struct uart_driver lpc32xx_hs_reg = { - .owner = THIS_MODULE, - .driver_name = MODNAME, - .dev_name = LPC32XX_TTY_NAME, - .nr = MAX_PORTS, - .cons = LPC32XX_HSUART_CONSOLE, -}; -static int uarts_registered; - -static unsigned int __serial_get_clock_div(unsigned long uartclk, - unsigned long rate) -{ - u32 div, goodrate, hsu_rate, l_hsu_rate, comprate; - u32 rate_diff; - - /* Find the closest divider to get the desired clock rate */ - div = uartclk / rate; - goodrate = hsu_rate = (div / 14) - 1; - if (hsu_rate != 0) - hsu_rate--; - - /* Tweak divider */ - l_hsu_rate = hsu_rate + 3; - rate_diff = 0xFFFFFFFF; - - while (hsu_rate < l_hsu_rate) { - comprate = uartclk / ((hsu_rate + 1) * 14); - if (abs(comprate - rate) < rate_diff) { - goodrate = hsu_rate; - rate_diff = abs(comprate - rate); - } - - hsu_rate++; - } - if (hsu_rate > 0xFF) - hsu_rate = 0xFF; - - return goodrate; -} - -static void __serial_uart_flush(struct uart_port *port) -{ - u32 tmp; - int cnt = 0; - - while ((readl(LPC32XX_HSUART_LEVEL(port->membase)) > 0) && - (cnt++ < FIFO_READ_LIMIT)) - tmp = readl(LPC32XX_HSUART_FIFO(port->membase)); -} - -static void __serial_lpc32xx_rx(struct uart_port *port) -{ - unsigned int tmp, flag; - struct tty_struct *tty = tty_port_tty_get(&port->state->port); - - if (!tty) { - /* Discard data: no tty available */ - while (!(readl(LPC32XX_HSUART_FIFO(port->membase)) & - LPC32XX_HSU_RX_EMPTY)) - ; - - return; - } - - /* Read data from FIFO and push into terminal */ - tmp = readl(LPC32XX_HSUART_FIFO(port->membase)); - while (!(tmp & LPC32XX_HSU_RX_EMPTY)) { - flag = TTY_NORMAL; - port->icount.rx++; - - if (tmp & LPC32XX_HSU_ERROR_DATA) { - /* Framing error */ - writel(LPC32XX_HSU_FE_INT, - LPC32XX_HSUART_IIR(port->membase)); - port->icount.frame++; - flag = TTY_FRAME; - tty_insert_flip_char(tty, 0, TTY_FRAME); - } - - tty_insert_flip_char(tty, (tmp & 0xFF), flag); - - tmp = readl(LPC32XX_HSUART_FIFO(port->membase)); - } - tty_flip_buffer_push(tty); - tty_kref_put(tty); -} - -static void __serial_lpc32xx_tx(struct uart_port *port) -{ - struct circ_buf *xmit = &port->state->xmit; - unsigned int tmp; - - if (port->x_char) { - writel((u32)port->x_char, LPC32XX_HSUART_FIFO(port->membase)); - port->icount.tx++; - port->x_char = 0; - return; - } - - if (uart_circ_empty(xmit) || uart_tx_stopped(port)) - goto exit_tx; - - /* Transfer data */ - while (LPC32XX_HSU_TX_LEV(readl( - LPC32XX_HSUART_LEVEL(port->membase))) < 64) { - writel((u32) xmit->buf[xmit->tail], - LPC32XX_HSUART_FIFO(port->membase)); - xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); - port->icount.tx++; - if (uart_circ_empty(xmit)) - break; - } - - if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) - uart_write_wakeup(port); - -exit_tx: - if (uart_circ_empty(xmit)) { - tmp = readl(LPC32XX_HSUART_CTRL(port->membase)); - tmp &= ~LPC32XX_HSU_TX_INT_EN; - writel(tmp, LPC32XX_HSUART_CTRL(port->membase)); - } -} - -static irqreturn_t serial_lpc32xx_interrupt(int irq, void *dev_id) -{ - struct uart_port *port = dev_id; - struct tty_struct *tty = tty_port_tty_get(&port->state->port); - u32 status; - - spin_lock(&port->lock); - - /* Read UART status and clear latched interrupts */ - status = readl(LPC32XX_HSUART_IIR(port->membase)); - - if (status & LPC32XX_HSU_BRK_INT) { - /* Break received */ - writel(LPC32XX_HSU_BRK_INT, LPC32XX_HSUART_IIR(port->membase)); - port->icount.brk++; - uart_handle_break(port); - } - - /* Framing error */ - if (status & LPC32XX_HSU_FE_INT) - writel(LPC32XX_HSU_FE_INT, LPC32XX_HSUART_IIR(port->membase)); - - if (status & LPC32XX_HSU_RX_OE_INT) { - /* Receive FIFO overrun */ - writel(LPC32XX_HSU_RX_OE_INT, - LPC32XX_HSUART_IIR(port->membase)); - port->icount.overrun++; - if (tty) { - tty_insert_flip_char(tty, 0, TTY_OVERRUN); - tty_schedule_flip(tty); - } - } - - /* Data received? */ - if (status & (LPC32XX_HSU_RX_TIMEOUT_INT | LPC32XX_HSU_RX_TRIG_INT)) { - __serial_lpc32xx_rx(port); - if (tty) - tty_flip_buffer_push(tty); - } - - /* Transmit data request? */ - if ((status & LPC32XX_HSU_TX_INT) && (!uart_tx_stopped(port))) { - writel(LPC32XX_HSU_TX_INT, LPC32XX_HSUART_IIR(port->membase)); - __serial_lpc32xx_tx(port); - } - - spin_unlock(&port->lock); - tty_kref_put(tty); - - return IRQ_HANDLED; -} - -/* port->lock is not held. */ -static unsigned int serial_lpc32xx_tx_empty(struct uart_port *port) -{ - unsigned int ret = 0; - - if (LPC32XX_HSU_TX_LEV(readl(LPC32XX_HSUART_LEVEL(port->membase))) == 0) - ret = TIOCSER_TEMT; - - return ret; -} - -/* port->lock held by caller. */ -static void serial_lpc32xx_set_mctrl(struct uart_port *port, - unsigned int mctrl) -{ - /* No signals are supported on HS UARTs */ -} - -/* port->lock is held by caller and interrupts are disabled. */ -static unsigned int serial_lpc32xx_get_mctrl(struct uart_port *port) -{ - /* No signals are supported on HS UARTs */ - return TIOCM_CAR | TIOCM_DSR | TIOCM_CTS; -} - -/* port->lock held by caller. */ -static void serial_lpc32xx_stop_tx(struct uart_port *port) -{ - u32 tmp; - - tmp = readl(LPC32XX_HSUART_CTRL(port->membase)); - tmp &= ~LPC32XX_HSU_TX_INT_EN; - writel(tmp, LPC32XX_HSUART_CTRL(port->membase)); -} - -/* port->lock held by caller. */ -static void serial_lpc32xx_start_tx(struct uart_port *port) -{ - u32 tmp; - - __serial_lpc32xx_tx(port); - tmp = readl(LPC32XX_HSUART_CTRL(port->membase)); - tmp |= LPC32XX_HSU_TX_INT_EN; - writel(tmp, LPC32XX_HSUART_CTRL(port->membase)); -} - -/* port->lock held by caller. */ -static void serial_lpc32xx_stop_rx(struct uart_port *port) -{ - u32 tmp; - - tmp = readl(LPC32XX_HSUART_CTRL(port->membase)); - tmp &= ~(LPC32XX_HSU_RX_INT_EN | LPC32XX_HSU_ERR_INT_EN); - writel(tmp, LPC32XX_HSUART_CTRL(port->membase)); - - writel((LPC32XX_HSU_BRK_INT | LPC32XX_HSU_RX_OE_INT | - LPC32XX_HSU_FE_INT), LPC32XX_HSUART_IIR(port->membase)); -} - -/* port->lock held by caller. */ -static void serial_lpc32xx_enable_ms(struct uart_port *port) -{ - /* Modem status is not supported */ -} - -/* port->lock is not held. */ -static void serial_lpc32xx_break_ctl(struct uart_port *port, - int break_state) -{ - unsigned long flags; - u32 tmp; - - spin_lock_irqsave(&port->lock, flags); - tmp = readl(LPC32XX_HSUART_CTRL(port->membase)); - if (break_state != 0) - tmp |= LPC32XX_HSU_BREAK; - else - tmp &= ~LPC32XX_HSU_BREAK; - writel(tmp, LPC32XX_HSUART_CTRL(port->membase)); - spin_unlock_irqrestore(&port->lock, flags); -} - -/* LPC3250 Errata HSUART.1: Hang workaround via loopback mode on inactivity */ -static void lpc32xx_loopback_set(resource_size_t mapbase, int state) -{ - int bit; - u32 tmp; - - switch (mapbase) { - case LPC32XX_HS_UART1_BASE: - bit = 0; - break; - case LPC32XX_HS_UART2_BASE: - bit = 1; - break; - case LPC32XX_HS_UART7_BASE: - bit = 6; - break; - default: - WARN(1, "lpc32xx_hs: Warning: Unknown port at %08x\n", mapbase); - return; - } - - tmp = readl(LPC32XX_UARTCTL_CLOOP); - if (state) - tmp |= (1 << bit); - else - tmp &= ~(1 << bit); - writel(tmp, LPC32XX_UARTCTL_CLOOP); -} - -/* port->lock is not held. */ -static int serial_lpc32xx_startup(struct uart_port *port) -{ - int retval; - unsigned long flags; - u32 tmp; - - spin_lock_irqsave(&port->lock, flags); - - __serial_uart_flush(port); - - writel((LPC32XX_HSU_TX_INT | LPC32XX_HSU_FE_INT | - LPC32XX_HSU_BRK_INT | LPC32XX_HSU_RX_OE_INT), - LPC32XX_HSUART_IIR(port->membase)); - - writel(0xFF, LPC32XX_HSUART_RATE(port->membase)); - - /* - * Set receiver timeout, HSU offset of 20, no break, no interrupts, - * and default FIFO trigger levels - */ - tmp = LPC32XX_HSU_TX_TL8B | LPC32XX_HSU_RX_TL32B | - LPC32XX_HSU_OFFSET(20) | LPC32XX_HSU_TMO_INACT_4B; - writel(tmp, LPC32XX_HSUART_CTRL(port->membase)); - - lpc32xx_loopback_set(port->mapbase, 0); /* get out of loopback mode */ - - spin_unlock_irqrestore(&port->lock, flags); - - retval = request_irq(port->irq, serial_lpc32xx_interrupt, - 0, MODNAME, port); - if (!retval) - writel((tmp | LPC32XX_HSU_RX_INT_EN | LPC32XX_HSU_ERR_INT_EN), - LPC32XX_HSUART_CTRL(port->membase)); - - return retval; -} - -/* port->lock is not held. */ -static void serial_lpc32xx_shutdown(struct uart_port *port) -{ - u32 tmp; - unsigned long flags; - - spin_lock_irqsave(&port->lock, flags); - - tmp = LPC32XX_HSU_TX_TL8B | LPC32XX_HSU_RX_TL32B | - LPC32XX_HSU_OFFSET(20) | LPC32XX_HSU_TMO_INACT_4B; - writel(tmp, LPC32XX_HSUART_CTRL(port->membase)); - - lpc32xx_loopback_set(port->mapbase, 1); /* go to loopback mode */ - - spin_unlock_irqrestore(&port->lock, flags); - - free_irq(port->irq, port); -} - -/* port->lock is not held. */ -static void serial_lpc32xx_set_termios(struct uart_port *port, - struct ktermios *termios, - struct ktermios *old) -{ - unsigned long flags; - unsigned int baud, quot; - u32 tmp; - - /* Always 8-bit, no parity, 1 stop bit */ - termios->c_cflag &= ~(CSIZE | CSTOPB | PARENB | PARODD); - termios->c_cflag |= CS8; - - termios->c_cflag &= ~(HUPCL | CMSPAR | CLOCAL | CRTSCTS); - - baud = uart_get_baud_rate(port, termios, old, 0, - port->uartclk / 14); - - quot = __serial_get_clock_div(port->uartclk, baud); - - spin_lock_irqsave(&port->lock, flags); - - /* Ignore characters? */ - tmp = readl(LPC32XX_HSUART_CTRL(port->membase)); - if ((termios->c_cflag & CREAD) == 0) - tmp &= ~(LPC32XX_HSU_RX_INT_EN | LPC32XX_HSU_ERR_INT_EN); - else - tmp |= LPC32XX_HSU_RX_INT_EN | LPC32XX_HSU_ERR_INT_EN; - writel(tmp, LPC32XX_HSUART_CTRL(port->membase)); - - writel(quot, LPC32XX_HSUART_RATE(port->membase)); - - uart_update_timeout(port, termios->c_cflag, baud); - - spin_unlock_irqrestore(&port->lock, flags); - - /* Don't rewrite B0 */ - if (tty_termios_baud_rate(termios)) - tty_termios_encode_baud_rate(termios, baud, baud); -} - -static const char *serial_lpc32xx_type(struct uart_port *port) -{ - return MODNAME; -} - -static void serial_lpc32xx_release_port(struct uart_port *port) -{ - if ((port->iotype == UPIO_MEM32) && (port->mapbase)) { - if (port->flags & UPF_IOREMAP) { - iounmap(port->membase); - port->membase = NULL; - } - - release_mem_region(port->mapbase, SZ_4K); - } -} - -static int serial_lpc32xx_request_port(struct uart_port *port) -{ - int ret = -ENODEV; - - if ((port->iotype == UPIO_MEM32) && (port->mapbase)) { - ret = 0; - - if (!request_mem_region(port->mapbase, SZ_4K, MODNAME)) - ret = -EBUSY; - else if (port->flags & UPF_IOREMAP) { - port->membase = ioremap(port->mapbase, SZ_4K); - if (!port->membase) { - release_mem_region(port->mapbase, SZ_4K); - ret = -ENOMEM; - } - } - } - - return ret; -} - -static void serial_lpc32xx_config_port(struct uart_port *port, int uflags) -{ - int ret; - - ret = serial_lpc32xx_request_port(port); - if (ret < 0) - return; - port->type = PORT_UART00; - port->fifosize = 64; - - __serial_uart_flush(port); - - writel((LPC32XX_HSU_TX_INT | LPC32XX_HSU_FE_INT | - LPC32XX_HSU_BRK_INT | LPC32XX_HSU_RX_OE_INT), - LPC32XX_HSUART_IIR(port->membase)); - - writel(0xFF, LPC32XX_HSUART_RATE(port->membase)); - - /* Set receiver timeout, HSU offset of 20, no break, no interrupts, - and default FIFO trigger levels */ - writel(LPC32XX_HSU_TX_TL8B | LPC32XX_HSU_RX_TL32B | - LPC32XX_HSU_OFFSET(20) | LPC32XX_HSU_TMO_INACT_4B, - LPC32XX_HSUART_CTRL(port->membase)); -} - -static int serial_lpc32xx_verify_port(struct uart_port *port, - struct serial_struct *ser) -{ - int ret = 0; - - if (ser->type != PORT_UART00) - ret = -EINVAL; - - return ret; -} - -static struct uart_ops serial_lpc32xx_pops = { - .tx_empty = serial_lpc32xx_tx_empty, - .set_mctrl = serial_lpc32xx_set_mctrl, - .get_mctrl = serial_lpc32xx_get_mctrl, - .stop_tx = serial_lpc32xx_stop_tx, - .start_tx = serial_lpc32xx_start_tx, - .stop_rx = serial_lpc32xx_stop_rx, - .enable_ms = serial_lpc32xx_enable_ms, - .break_ctl = serial_lpc32xx_break_ctl, - .startup = serial_lpc32xx_startup, - .shutdown = serial_lpc32xx_shutdown, - .set_termios = serial_lpc32xx_set_termios, - .type = serial_lpc32xx_type, - .release_port = serial_lpc32xx_release_port, - .request_port = serial_lpc32xx_request_port, - .config_port = serial_lpc32xx_config_port, - .verify_port = serial_lpc32xx_verify_port, -}; - -/* - * Register a set of serial devices attached to a platform device - */ -static int __devinit serial_hs_lpc32xx_probe(struct platform_device *pdev) -{ - struct lpc32xx_hsuart_port *p = &lpc32xx_hs_ports[uarts_registered]; - int ret = 0; - struct resource *res; - - if (uarts_registered >= MAX_PORTS) { - dev_err(&pdev->dev, - "Error: Number of possible ports exceeded (%d)!\n", - uarts_registered + 1); - return -ENXIO; - } - - memset(p, 0, sizeof(*p)); - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - dev_err(&pdev->dev, - "Error getting mem resource for HS UART port %d\n", - uarts_registered); - return -ENXIO; - } - p->port.mapbase = res->start; - p->port.membase = NULL; - - p->port.irq = platform_get_irq(pdev, 0); - if (p->port.irq < 0) { - dev_err(&pdev->dev, "Error getting irq for HS UART port %d\n", - uarts_registered); - return p->port.irq; - } - - p->port.iotype = UPIO_MEM32; - p->port.uartclk = LPC32XX_MAIN_OSC_FREQ; - p->port.regshift = 2; - p->port.flags = UPF_BOOT_AUTOCONF | UPF_FIXED_PORT | UPF_IOREMAP; - p->port.dev = &pdev->dev; - p->port.ops = &serial_lpc32xx_pops; - p->port.line = uarts_registered++; - spin_lock_init(&p->port.lock); - - /* send port to loopback mode by default */ - lpc32xx_loopback_set(p->port.mapbase, 1); - - ret = uart_add_one_port(&lpc32xx_hs_reg, &p->port); - - platform_set_drvdata(pdev, p); - - return ret; -} - -/* - * Remove serial ports registered against a platform device. - */ -static int __devexit serial_hs_lpc32xx_remove(struct platform_device *pdev) -{ - struct lpc32xx_hsuart_port *p = platform_get_drvdata(pdev); - - uart_remove_one_port(&lpc32xx_hs_reg, &p->port); - - return 0; -} - - -#ifdef CONFIG_PM -static int serial_hs_lpc32xx_suspend(struct platform_device *pdev, - pm_message_t state) -{ - struct lpc32xx_hsuart_port *p = platform_get_drvdata(pdev); - - uart_suspend_port(&lpc32xx_hs_reg, &p->port); - - return 0; -} - -static int serial_hs_lpc32xx_resume(struct platform_device *pdev) -{ - struct lpc32xx_hsuart_port *p = platform_get_drvdata(pdev); - - uart_resume_port(&lpc32xx_hs_reg, &p->port); - - return 0; -} -#else -#define serial_hs_lpc32xx_suspend NULL -#define serial_hs_lpc32xx_resume NULL -#endif - -static const struct of_device_id serial_hs_lpc32xx_dt_ids[] = { - { .compatible = "nxp,lpc3220-hsuart" }, - { /* sentinel */ } -}; - -MODULE_DEVICE_TABLE(of, serial_hs_lpc32xx_dt_ids); - -static struct platform_driver serial_hs_lpc32xx_driver = { - .probe = serial_hs_lpc32xx_probe, - .remove = __devexit_p(serial_hs_lpc32xx_remove), - .suspend = serial_hs_lpc32xx_suspend, - .resume = serial_hs_lpc32xx_resume, - .driver = { - .name = MODNAME, - .owner = THIS_MODULE, - .of_match_table = serial_hs_lpc32xx_dt_ids, - }, -}; - -static int __init lpc32xx_hsuart_init(void) -{ - int ret; - - ret = uart_register_driver(&lpc32xx_hs_reg); - if (ret) - return ret; - - ret = platform_driver_register(&serial_hs_lpc32xx_driver); - if (ret) - uart_unregister_driver(&lpc32xx_hs_reg); - - return ret; -} - -static void __exit lpc32xx_hsuart_exit(void) -{ - platform_driver_unregister(&serial_hs_lpc32xx_driver); - uart_unregister_driver(&lpc32xx_hs_reg); -} - -module_init(lpc32xx_hsuart_init); -module_exit(lpc32xx_hsuart_exit); - -MODULE_AUTHOR("Kevin Wells "); -MODULE_AUTHOR("Roland Stigge "); -MODULE_DESCRIPTION("NXP LPC32XX High Speed UART driver"); -MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/tty/serial/m32r_sio.c b/trunk/drivers/tty/serial/m32r_sio.c index b13949ad3408..a0703624d5e5 100644 --- a/trunk/drivers/tty/serial/m32r_sio.c +++ b/trunk/drivers/tty/serial/m32r_sio.c @@ -44,6 +44,8 @@ #include #include +#define PORT_M32R_BASE PORT_M32R_SIO +#define PORT_INDEX(x) (x - PORT_M32R_BASE + 1) #define BAUD_RATE 115200 #include @@ -130,6 +132,22 @@ struct irq_info { static struct irq_info irq_lists[NR_IRQS]; +/* + * Here we define the default xmit fifo size used for each type of UART. + */ +static const struct serial_uart_config uart_config[] = { + [PORT_UNKNOWN] = { + .name = "unknown", + .dfl_xmit_fifo_size = 1, + .flags = 0, + }, + [PORT_INDEX(PORT_M32R_SIO)] = { + .name = "M32RSIO", + .dfl_xmit_fifo_size = 1, + .flags = 0, + }, +}; + #ifdef CONFIG_SERIAL_M32R_PLDSIO #define __sio_in(x) inw((unsigned long)(x)) @@ -889,7 +907,8 @@ static void m32r_sio_config_port(struct uart_port *port, int unused) spin_lock_irqsave(&up->port.lock, flags); - up->port.fifosize = 1; + up->port.type = (PORT_M32R_SIO - PORT_M32R_BASE + 1); + up->port.fifosize = uart_config[up->port.type].dfl_xmit_fifo_size; spin_unlock_irqrestore(&up->port.lock, flags); } @@ -897,11 +916,23 @@ static void m32r_sio_config_port(struct uart_port *port, int unused) static int m32r_sio_verify_port(struct uart_port *port, struct serial_struct *ser) { - if (ser->irq >= nr_irqs || ser->irq < 0 || ser->baud_base < 9600) + if (ser->irq >= nr_irqs || ser->irq < 0 || + ser->baud_base < 9600 || ser->type < PORT_UNKNOWN || + ser->type >= ARRAY_SIZE(uart_config)) return -EINVAL; return 0; } +static const char * +m32r_sio_type(struct uart_port *port) +{ + int type = port->type; + + if (type >= ARRAY_SIZE(uart_config)) + type = 0; + return uart_config[type].name; +} + static struct uart_ops m32r_sio_pops = { .tx_empty = m32r_sio_tx_empty, .set_mctrl = m32r_sio_set_mctrl, @@ -915,6 +946,7 @@ static struct uart_ops m32r_sio_pops = { .shutdown = m32r_sio_shutdown, .set_termios = m32r_sio_set_termios, .pm = m32r_sio_pm, + .type = m32r_sio_type, .release_port = m32r_sio_release_port, .request_port = m32r_sio_request_port, .config_port = m32r_sio_config_port, diff --git a/trunk/drivers/tty/serial/max3100.c b/trunk/drivers/tty/serial/max3100.c index 0f24486be532..b4902b99cfd2 100644 --- a/trunk/drivers/tty/serial/max3100.c +++ b/trunk/drivers/tty/serial/max3100.c @@ -827,16 +827,14 @@ static int __devexit max3100_remove(struct spi_device *spi) /* find out the index for the chip we are removing */ for (i = 0; i < MAX_MAX3100; i++) - if (max3100s[i] == s) { - dev_dbg(&spi->dev, "%s: removing port %d\n", __func__, i); - uart_remove_one_port(&max3100_uart_driver, &max3100s[i]->port); - kfree(max3100s[i]); - max3100s[i] = NULL; + if (max3100s[i] == s) break; - } - WARN_ON(i == MAX_MAX3100); - + dev_dbg(&spi->dev, "%s: removing port %d\n", __func__, i); + uart_remove_one_port(&max3100_uart_driver, &max3100s[i]->port); + kfree(max3100s[i]); + max3100s[i] = NULL; + /* check if this is the last chip we have */ for (i = 0; i < MAX_MAX3100; i++) if (max3100s[i]) { @@ -912,7 +910,17 @@ static struct spi_driver max3100_driver = { .resume = max3100_resume, }; -module_spi_driver(max3100_driver); +static int __init max3100_init(void) +{ + return spi_register_driver(&max3100_driver); +} +module_init(max3100_init); + +static void __exit max3100_exit(void) +{ + spi_unregister_driver(&max3100_driver); +} +module_exit(max3100_exit); MODULE_DESCRIPTION("MAX3100 driver"); MODULE_AUTHOR("Christian Pellegrin "); diff --git a/trunk/drivers/tty/serial/max3107.c b/trunk/drivers/tty/serial/max3107.c new file mode 100644 index 000000000000..17c7ba805d98 --- /dev/null +++ b/trunk/drivers/tty/serial/max3107.c @@ -0,0 +1,1215 @@ +/* + * max3107.c - spi uart protocol driver for Maxim 3107 + * Based on max3100.c + * by Christian Pellegrin + * and max3110.c + * by Feng Tang + * + * Copyright (C) Aavamobile 2009 + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * 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 +#include +#include "max3107.h" + +static const struct baud_table brg26_ext[] = { + { 300, MAX3107_BRG26_B300 }, + { 600, MAX3107_BRG26_B600 }, + { 1200, MAX3107_BRG26_B1200 }, + { 2400, MAX3107_BRG26_B2400 }, + { 4800, MAX3107_BRG26_B4800 }, + { 9600, MAX3107_BRG26_B9600 }, + { 19200, MAX3107_BRG26_B19200 }, + { 57600, MAX3107_BRG26_B57600 }, + { 115200, MAX3107_BRG26_B115200 }, + { 230400, MAX3107_BRG26_B230400 }, + { 460800, MAX3107_BRG26_B460800 }, + { 921600, MAX3107_BRG26_B921600 }, + { 0, 0 } +}; + +static const struct baud_table brg13_int[] = { + { 300, MAX3107_BRG13_IB300 }, + { 600, MAX3107_BRG13_IB600 }, + { 1200, MAX3107_BRG13_IB1200 }, + { 2400, MAX3107_BRG13_IB2400 }, + { 4800, MAX3107_BRG13_IB4800 }, + { 9600, MAX3107_BRG13_IB9600 }, + { 19200, MAX3107_BRG13_IB19200 }, + { 57600, MAX3107_BRG13_IB57600 }, + { 115200, MAX3107_BRG13_IB115200 }, + { 230400, MAX3107_BRG13_IB230400 }, + { 460800, MAX3107_BRG13_IB460800 }, + { 921600, MAX3107_BRG13_IB921600 }, + { 0, 0 } +}; + +static u32 get_new_brg(int baud, struct max3107_port *s) +{ + int i; + const struct baud_table *baud_tbl = s->baud_tbl; + + for (i = 0; i < 13; i++) { + if (baud == baud_tbl[i].baud) + return baud_tbl[i].new_brg; + } + + return 0; +} + +/* Perform SPI transfer for write/read of device register(s) */ +int max3107_rw(struct max3107_port *s, u8 *tx, u8 *rx, int len) +{ + struct spi_message spi_msg; + struct spi_transfer spi_xfer; + + /* Initialize SPI ,message */ + spi_message_init(&spi_msg); + + /* Initialize SPI transfer */ + memset(&spi_xfer, 0, sizeof spi_xfer); + spi_xfer.len = len; + spi_xfer.tx_buf = tx; + spi_xfer.rx_buf = rx; + spi_xfer.speed_hz = MAX3107_SPI_SPEED; + + /* Add SPI transfer to SPI message */ + spi_message_add_tail(&spi_xfer, &spi_msg); + +#ifdef DBG_TRACE_SPI_DATA + { + int i; + pr_info("tx len %d:\n", spi_xfer.len); + for (i = 0 ; i < spi_xfer.len && i < 32 ; i++) + pr_info(" %x", ((u8 *)spi_xfer.tx_buf)[i]); + pr_info("\n"); + } +#endif + + /* Perform synchronous SPI transfer */ + if (spi_sync(s->spi, &spi_msg)) { + dev_err(&s->spi->dev, "spi_sync failure\n"); + return -EIO; + } + +#ifdef DBG_TRACE_SPI_DATA + if (spi_xfer.rx_buf) { + int i; + pr_info("rx len %d:\n", spi_xfer.len); + for (i = 0 ; i < spi_xfer.len && i < 32 ; i++) + pr_info(" %x", ((u8 *)spi_xfer.rx_buf)[i]); + pr_info("\n"); + } +#endif + return 0; +} +EXPORT_SYMBOL_GPL(max3107_rw); + +/* Puts received data to circular buffer */ +static void put_data_to_circ_buf(struct max3107_port *s, unsigned char *data, + int len) +{ + struct uart_port *port = &s->port; + struct tty_struct *tty; + + if (!port->state) + return; + + tty = port->state->port.tty; + if (!tty) + return; + + /* Insert received data */ + tty_insert_flip_string(tty, data, len); + /* Update RX counter */ + port->icount.rx += len; +} + +/* Handle data receiving */ +static void max3107_handlerx(struct max3107_port *s, u16 rxlvl) +{ + int i; + int j; + int len; /* SPI transfer buffer length */ + u16 *buf; + u8 *valid_str; + + if (!s->rx_enabled) + /* RX is disabled */ + return; + + if (rxlvl == 0) { + /* RX fifo is empty */ + return; + } else if (rxlvl >= MAX3107_RX_FIFO_SIZE) { + dev_warn(&s->spi->dev, "Possible RX FIFO overrun %d\n", rxlvl); + /* Ensure sanity of RX level */ + rxlvl = MAX3107_RX_FIFO_SIZE; + } + if ((s->rxbuf == 0) || (s->rxstr == 0)) { + dev_warn(&s->spi->dev, "Rx buffer/str isn't ready\n"); + return; + } + buf = s->rxbuf; + valid_str = s->rxstr; + while (rxlvl) { + pr_debug("rxlvl %d\n", rxlvl); + /* Clear buffer */ + memset(buf, 0, sizeof(u16) * (MAX3107_RX_FIFO_SIZE + 2)); + len = 0; + if (s->irqen_reg & MAX3107_IRQ_RXFIFO_BIT) { + /* First disable RX FIFO interrupt */ + pr_debug("Disabling RX INT\n"); + buf[0] = (MAX3107_WRITE_BIT | MAX3107_IRQEN_REG); + s->irqen_reg &= ~MAX3107_IRQ_RXFIFO_BIT; + buf[0] |= s->irqen_reg; + len++; + } + /* Just increase the length by amount of words in FIFO since + * buffer was zeroed and SPI transfer of 0x0000 means reading + * from RX FIFO + */ + len += rxlvl; + /* Append RX level query */ + buf[len] = MAX3107_RXFIFOLVL_REG; + len++; + + /* Perform the SPI transfer */ + if (max3107_rw(s, (u8 *)buf, (u8 *)buf, len * 2)) { + dev_err(&s->spi->dev, "SPI transfer for RX h failed\n"); + return; + } + + /* Skip RX FIFO interrupt disabling word if it was added */ + j = ((len - 1) - rxlvl); + /* Read received words */ + for (i = 0; i < rxlvl; i++, j++) + valid_str[i] = (u8)buf[j]; + put_data_to_circ_buf(s, valid_str, rxlvl); + /* Get new RX level */ + rxlvl = (buf[len - 1] & MAX3107_SPI_RX_DATA_MASK); + } + + if (s->rx_enabled) { + /* RX still enabled, re-enable RX FIFO interrupt */ + pr_debug("Enabling RX INT\n"); + buf[0] = (MAX3107_WRITE_BIT | MAX3107_IRQEN_REG); + s->irqen_reg |= MAX3107_IRQ_RXFIFO_BIT; + buf[0] |= s->irqen_reg; + if (max3107_rw(s, (u8 *)buf, NULL, 2)) + dev_err(&s->spi->dev, "RX FIFO INT enabling failed\n"); + } + + /* Push the received data to receivers */ + if (s->port.state->port.tty) + tty_flip_buffer_push(s->port.state->port.tty); +} + + +/* Handle data sending */ +static void max3107_handletx(struct max3107_port *s) +{ + struct circ_buf *xmit = &s->port.state->xmit; + int i; + unsigned long flags; + int len; /* SPI transfer buffer length */ + u16 *buf; + + if (!s->tx_fifo_empty) + /* Don't send more data before previous data is sent */ + return; + + if (uart_circ_empty(xmit) || uart_tx_stopped(&s->port)) + /* No data to send or TX is stopped */ + return; + + if (!s->txbuf) { + dev_warn(&s->spi->dev, "Txbuf isn't ready\n"); + return; + } + buf = s->txbuf; + /* Get length of data pending in circular buffer */ + len = uart_circ_chars_pending(xmit); + if (len) { + /* Limit to size of TX FIFO */ + if (len > MAX3107_TX_FIFO_SIZE) + len = MAX3107_TX_FIFO_SIZE; + + pr_debug("txlen %d\n", len); + + /* Update TX counter */ + s->port.icount.tx += len; + + /* TX FIFO will no longer be empty */ + s->tx_fifo_empty = 0; + + i = 0; + if (s->irqen_reg & MAX3107_IRQ_TXEMPTY_BIT) { + /* First disable TX empty interrupt */ + pr_debug("Disabling TE INT\n"); + buf[i] = (MAX3107_WRITE_BIT | MAX3107_IRQEN_REG); + s->irqen_reg &= ~MAX3107_IRQ_TXEMPTY_BIT; + buf[i] |= s->irqen_reg; + i++; + len++; + } + /* Add data to send */ + spin_lock_irqsave(&s->port.lock, flags); + for ( ; i < len ; i++) { + buf[i] = (MAX3107_WRITE_BIT | MAX3107_THR_REG); + buf[i] |= ((u16)xmit->buf[xmit->tail] & + MAX3107_SPI_TX_DATA_MASK); + xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); + } + spin_unlock_irqrestore(&s->port.lock, flags); + if (!(s->irqen_reg & MAX3107_IRQ_TXEMPTY_BIT)) { + /* Enable TX empty interrupt */ + pr_debug("Enabling TE INT\n"); + buf[i] = (MAX3107_WRITE_BIT | MAX3107_IRQEN_REG); + s->irqen_reg |= MAX3107_IRQ_TXEMPTY_BIT; + buf[i] |= s->irqen_reg; + i++; + len++; + } + if (!s->tx_enabled) { + /* Enable TX */ + pr_debug("Enable TX\n"); + buf[i] = (MAX3107_WRITE_BIT | MAX3107_MODE1_REG); + spin_lock_irqsave(&s->data_lock, flags); + s->mode1_reg &= ~MAX3107_MODE1_TXDIS_BIT; + buf[i] |= s->mode1_reg; + spin_unlock_irqrestore(&s->data_lock, flags); + s->tx_enabled = 1; + i++; + len++; + } + + /* Perform the SPI transfer */ + if (max3107_rw(s, (u8 *)buf, NULL, len*2)) { + dev_err(&s->spi->dev, + "SPI transfer TX handling failed\n"); + return; + } + } + + /* Indicate wake up if circular buffer is getting low on data */ + if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) + uart_write_wakeup(&s->port); + +} + +/* Handle interrupts + * Also reads and returns current RX FIFO level + */ +static u16 handle_interrupt(struct max3107_port *s) +{ + u16 buf[4]; /* Buffer for SPI transfers */ + u8 irq_status; + u16 rx_level; + unsigned long flags; + + /* Read IRQ status register */ + buf[0] = MAX3107_IRQSTS_REG; + /* Read status IRQ status register */ + buf[1] = MAX3107_STS_IRQSTS_REG; + /* Read LSR IRQ status register */ + buf[2] = MAX3107_LSR_IRQSTS_REG; + /* Query RX level */ + buf[3] = MAX3107_RXFIFOLVL_REG; + + if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 8)) { + dev_err(&s->spi->dev, + "SPI transfer for INTR handling failed\n"); + return 0; + } + + irq_status = (u8)buf[0]; + pr_debug("IRQSTS %x\n", irq_status); + rx_level = (buf[3] & MAX3107_SPI_RX_DATA_MASK); + + if (irq_status & MAX3107_IRQ_LSR_BIT) { + /* LSR interrupt */ + if (buf[2] & MAX3107_LSR_RXTO_BIT) + /* RX timeout interrupt, + * handled by normal RX handling + */ + pr_debug("RX TO INT\n"); + } + + if (irq_status & MAX3107_IRQ_TXEMPTY_BIT) { + /* Tx empty interrupt, + * disable TX and set tx_fifo_empty flag + */ + pr_debug("TE INT, disabling TX\n"); + buf[0] = (MAX3107_WRITE_BIT | MAX3107_MODE1_REG); + spin_lock_irqsave(&s->data_lock, flags); + s->mode1_reg |= MAX3107_MODE1_TXDIS_BIT; + buf[0] |= s->mode1_reg; + spin_unlock_irqrestore(&s->data_lock, flags); + if (max3107_rw(s, (u8 *)buf, NULL, 2)) + dev_err(&s->spi->dev, "SPI transfer TX dis failed\n"); + s->tx_enabled = 0; + s->tx_fifo_empty = 1; + } + + if (irq_status & MAX3107_IRQ_RXFIFO_BIT) + /* RX FIFO interrupt, + * handled by normal RX handling + */ + pr_debug("RFIFO INT\n"); + + /* Return RX level */ + return rx_level; +} + +/* Trigger work thread*/ +static void max3107_dowork(struct max3107_port *s) +{ + if (!work_pending(&s->work) && !freezing(current) && !s->suspended) + queue_work(s->workqueue, &s->work); + else + dev_warn(&s->spi->dev, "interrup isn't serviced normally!\n"); +} + +/* Work thread */ +static void max3107_work(struct work_struct *w) +{ + struct max3107_port *s = container_of(w, struct max3107_port, work); + u16 rxlvl = 0; + int len; /* SPI transfer buffer length */ + u16 buf[5]; /* Buffer for SPI transfers */ + unsigned long flags; + + /* Start by reading current RX FIFO level */ + buf[0] = MAX3107_RXFIFOLVL_REG; + if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 2)) { + dev_err(&s->spi->dev, "SPI transfer RX lev failed\n"); + rxlvl = 0; + } else { + rxlvl = (buf[0] & MAX3107_SPI_RX_DATA_MASK); + } + + do { + pr_debug("rxlvl %d\n", rxlvl); + + /* Handle RX */ + max3107_handlerx(s, rxlvl); + rxlvl = 0; + + if (s->handle_irq) { + /* Handle pending interrupts + * We also get new RX FIFO level since new data may + * have been received while pushing received data to + * receivers + */ + s->handle_irq = 0; + rxlvl = handle_interrupt(s); + } + + /* Handle TX */ + max3107_handletx(s); + + /* Handle configuration changes */ + len = 0; + spin_lock_irqsave(&s->data_lock, flags); + if (s->mode1_commit) { + pr_debug("mode1_commit\n"); + buf[len] = (MAX3107_WRITE_BIT | MAX3107_MODE1_REG); + buf[len++] |= s->mode1_reg; + s->mode1_commit = 0; + } + if (s->lcr_commit) { + pr_debug("lcr_commit\n"); + buf[len] = (MAX3107_WRITE_BIT | MAX3107_LCR_REG); + buf[len++] |= s->lcr_reg; + s->lcr_commit = 0; + } + if (s->brg_commit) { + pr_debug("brg_commit\n"); + buf[len] = (MAX3107_WRITE_BIT | MAX3107_BRGDIVMSB_REG); + buf[len++] |= ((s->brg_cfg >> 16) & + MAX3107_SPI_TX_DATA_MASK); + buf[len] = (MAX3107_WRITE_BIT | MAX3107_BRGDIVLSB_REG); + buf[len++] |= ((s->brg_cfg >> 8) & + MAX3107_SPI_TX_DATA_MASK); + buf[len] = (MAX3107_WRITE_BIT | MAX3107_BRGCFG_REG); + buf[len++] |= ((s->brg_cfg) & 0xff); + s->brg_commit = 0; + } + spin_unlock_irqrestore(&s->data_lock, flags); + + if (len > 0) { + if (max3107_rw(s, (u8 *)buf, NULL, len * 2)) + dev_err(&s->spi->dev, + "SPI transfer config failed\n"); + } + + /* Reloop if interrupt handling indicated data in RX FIFO */ + } while (rxlvl); + +} + +/* Set sleep mode */ +static void max3107_set_sleep(struct max3107_port *s, int mode) +{ + u16 buf[1]; /* Buffer for SPI transfer */ + unsigned long flags; + pr_debug("enter, mode %d\n", mode); + + buf[0] = (MAX3107_WRITE_BIT | MAX3107_MODE1_REG); + spin_lock_irqsave(&s->data_lock, flags); + switch (mode) { + case MAX3107_DISABLE_FORCED_SLEEP: + s->mode1_reg &= ~MAX3107_MODE1_FORCESLEEP_BIT; + break; + case MAX3107_ENABLE_FORCED_SLEEP: + s->mode1_reg |= MAX3107_MODE1_FORCESLEEP_BIT; + break; + case MAX3107_DISABLE_AUTOSLEEP: + s->mode1_reg &= ~MAX3107_MODE1_AUTOSLEEP_BIT; + break; + case MAX3107_ENABLE_AUTOSLEEP: + s->mode1_reg |= MAX3107_MODE1_AUTOSLEEP_BIT; + break; + default: + spin_unlock_irqrestore(&s->data_lock, flags); + dev_warn(&s->spi->dev, "invalid sleep mode\n"); + return; + } + buf[0] |= s->mode1_reg; + spin_unlock_irqrestore(&s->data_lock, flags); + + if (max3107_rw(s, (u8 *)buf, NULL, 2)) + dev_err(&s->spi->dev, "SPI transfer sleep mode failed\n"); + + if (mode == MAX3107_DISABLE_AUTOSLEEP || + mode == MAX3107_DISABLE_FORCED_SLEEP) + msleep(MAX3107_WAKEUP_DELAY); +} + +/* Perform full register initialization */ +static void max3107_register_init(struct max3107_port *s) +{ + u16 buf[11]; /* Buffer for SPI transfers */ + + /* 1. Configure baud rate, 9600 as default */ + s->baud = 9600; + /* the below is default*/ + if (s->ext_clk) { + s->brg_cfg = MAX3107_BRG26_B9600; + s->baud_tbl = (struct baud_table *)brg26_ext; + } else { + s->brg_cfg = MAX3107_BRG13_IB9600; + s->baud_tbl = (struct baud_table *)brg13_int; + } + + if (s->pdata->init) + s->pdata->init(s); + + buf[0] = (MAX3107_WRITE_BIT | MAX3107_BRGDIVMSB_REG) + | ((s->brg_cfg >> 16) & MAX3107_SPI_TX_DATA_MASK); + buf[1] = (MAX3107_WRITE_BIT | MAX3107_BRGDIVLSB_REG) + | ((s->brg_cfg >> 8) & MAX3107_SPI_TX_DATA_MASK); + buf[2] = (MAX3107_WRITE_BIT | MAX3107_BRGCFG_REG) + | ((s->brg_cfg) & 0xff); + + /* 2. Configure LCR register, 8N1 mode by default */ + s->lcr_reg = MAX3107_LCR_WORD_LEN_8; + buf[3] = (MAX3107_WRITE_BIT | MAX3107_LCR_REG) + | s->lcr_reg; + + /* 3. Configure MODE 1 register */ + s->mode1_reg = 0; + /* Enable IRQ pin */ + s->mode1_reg |= MAX3107_MODE1_IRQSEL_BIT; + /* Disable TX */ + s->mode1_reg |= MAX3107_MODE1_TXDIS_BIT; + s->tx_enabled = 0; + /* RX is enabled */ + s->rx_enabled = 1; + buf[4] = (MAX3107_WRITE_BIT | MAX3107_MODE1_REG) + | s->mode1_reg; + + /* 4. Configure MODE 2 register */ + buf[5] = (MAX3107_WRITE_BIT | MAX3107_MODE2_REG); + if (s->loopback) { + /* Enable loopback */ + buf[5] |= MAX3107_MODE2_LOOPBACK_BIT; + } + /* Reset FIFOs */ + buf[5] |= MAX3107_MODE2_FIFORST_BIT; + s->tx_fifo_empty = 1; + + /* 5. Configure FIFO trigger level register */ + buf[6] = (MAX3107_WRITE_BIT | MAX3107_FIFOTRIGLVL_REG); + /* RX FIFO trigger for 16 words, TX FIFO trigger not used */ + buf[6] |= (MAX3107_FIFOTRIGLVL_RX(16) | MAX3107_FIFOTRIGLVL_TX(0)); + + /* 6. Configure flow control levels */ + buf[7] = (MAX3107_WRITE_BIT | MAX3107_FLOWLVL_REG); + /* Flow control halt level 96, resume level 48 */ + buf[7] |= (MAX3107_FLOWLVL_RES(48) | MAX3107_FLOWLVL_HALT(96)); + + /* 7. Configure flow control */ + buf[8] = (MAX3107_WRITE_BIT | MAX3107_FLOWCTRL_REG); + /* Enable auto CTS and auto RTS flow control */ + buf[8] |= (MAX3107_FLOWCTRL_AUTOCTS_BIT | MAX3107_FLOWCTRL_AUTORTS_BIT); + + /* 8. Configure RX timeout register */ + buf[9] = (MAX3107_WRITE_BIT | MAX3107_RXTO_REG); + /* Timeout after 48 character intervals */ + buf[9] |= 0x0030; + + /* 9. Configure LSR interrupt enable register */ + buf[10] = (MAX3107_WRITE_BIT | MAX3107_LSR_IRQEN_REG); + /* Enable RX timeout interrupt */ + buf[10] |= MAX3107_LSR_RXTO_BIT; + + /* Perform SPI transfer */ + if (max3107_rw(s, (u8 *)buf, NULL, 22)) + dev_err(&s->spi->dev, "SPI transfer for init failed\n"); + + /* 10. Clear IRQ status register by reading it */ + buf[0] = MAX3107_IRQSTS_REG; + + /* 11. Configure interrupt enable register */ + /* Enable LSR interrupt */ + s->irqen_reg = MAX3107_IRQ_LSR_BIT; + /* Enable RX FIFO interrupt */ + s->irqen_reg |= MAX3107_IRQ_RXFIFO_BIT; + buf[1] = (MAX3107_WRITE_BIT | MAX3107_IRQEN_REG) + | s->irqen_reg; + + /* 12. Clear FIFO reset that was set in step 6 */ + buf[2] = (MAX3107_WRITE_BIT | MAX3107_MODE2_REG); + if (s->loopback) { + /* Keep loopback enabled */ + buf[2] |= MAX3107_MODE2_LOOPBACK_BIT; + } + + /* Perform SPI transfer */ + if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 6)) + dev_err(&s->spi->dev, "SPI transfer for init failed\n"); + +} + +/* IRQ handler */ +static irqreturn_t max3107_irq(int irqno, void *dev_id) +{ + struct max3107_port *s = dev_id; + + if (irqno != s->spi->irq) { + /* Unexpected IRQ */ + return IRQ_NONE; + } + + /* Indicate irq */ + s->handle_irq = 1; + + /* Trigger work thread */ + max3107_dowork(s); + + return IRQ_HANDLED; +} + +/* HW suspension function + * + * Currently autosleep is used to decrease current consumption, alternative + * approach would be to set the chip to reset mode if UART is not being + * used but that would mess the GPIOs + * + */ +void max3107_hw_susp(struct max3107_port *s, int suspend) +{ + pr_debug("enter, suspend %d\n", suspend); + + if (suspend) { + /* Suspend requested, + * enable autosleep to decrease current consumption + */ + s->suspended = 1; + max3107_set_sleep(s, MAX3107_ENABLE_AUTOSLEEP); + } else { + /* Resume requested, + * disable autosleep + */ + s->suspended = 0; + max3107_set_sleep(s, MAX3107_DISABLE_AUTOSLEEP); + } +} +EXPORT_SYMBOL_GPL(max3107_hw_susp); + +/* Modem status IRQ enabling */ +static void max3107_enable_ms(struct uart_port *port) +{ + /* Modem status not supported */ +} + +/* Data send function */ +static void max3107_start_tx(struct uart_port *port) +{ + struct max3107_port *s = container_of(port, struct max3107_port, port); + + /* Trigger work thread for sending data */ + max3107_dowork(s); +} + +/* Function for checking that there is no pending transfers */ +static unsigned int max3107_tx_empty(struct uart_port *port) +{ + struct max3107_port *s = container_of(port, struct max3107_port, port); + + pr_debug("returning %d\n", + (s->tx_fifo_empty && uart_circ_empty(&s->port.state->xmit))); + return s->tx_fifo_empty && uart_circ_empty(&s->port.state->xmit); +} + +/* Function for stopping RX */ +static void max3107_stop_rx(struct uart_port *port) +{ + struct max3107_port *s = container_of(port, struct max3107_port, port); + unsigned long flags; + + /* Set RX disabled in MODE 1 register */ + spin_lock_irqsave(&s->data_lock, flags); + s->mode1_reg |= MAX3107_MODE1_RXDIS_BIT; + s->mode1_commit = 1; + spin_unlock_irqrestore(&s->data_lock, flags); + /* Set RX disabled */ + s->rx_enabled = 0; + /* Trigger work thread for doing the actual configuration change */ + max3107_dowork(s); +} + +/* Function for returning control pin states */ +static unsigned int max3107_get_mctrl(struct uart_port *port) +{ + /* DCD and DSR are not wired and CTS/RTS is handled automatically + * so just indicate DSR and CAR asserted + */ + return TIOCM_DSR | TIOCM_CAR; +} + +/* Function for setting control pin states */ +static void max3107_set_mctrl(struct uart_port *port, unsigned int mctrl) +{ + /* DCD and DSR are not wired and CTS/RTS is hadnled automatically + * so do nothing + */ +} + +/* Function for configuring UART parameters */ +static void max3107_set_termios(struct uart_port *port, + struct ktermios *termios, + struct ktermios *old) +{ + struct max3107_port *s = container_of(port, struct max3107_port, port); + struct tty_struct *tty; + int baud; + u16 new_lcr = 0; + u32 new_brg = 0; + unsigned long flags; + + if (!port->state) + return; + + tty = port->state->port.tty; + if (!tty) + return; + + /* Get new LCR register values */ + /* Word size */ + if ((termios->c_cflag & CSIZE) == CS7) + new_lcr |= MAX3107_LCR_WORD_LEN_7; + else + new_lcr |= MAX3107_LCR_WORD_LEN_8; + + /* Parity */ + if (termios->c_cflag & PARENB) { + new_lcr |= MAX3107_LCR_PARITY_BIT; + if (!(termios->c_cflag & PARODD)) + new_lcr |= MAX3107_LCR_EVENPARITY_BIT; + } + + /* Stop bits */ + if (termios->c_cflag & CSTOPB) { + /* 2 stop bits */ + new_lcr |= MAX3107_LCR_STOPLEN_BIT; + } + + /* Mask termios capabilities we don't support */ + termios->c_cflag &= ~CMSPAR; + + /* Set status ignore mask */ + s->port.ignore_status_mask = 0; + if (termios->c_iflag & IGNPAR) + s->port.ignore_status_mask |= MAX3107_ALL_ERRORS; + + /* Set low latency to immediately handle pushed data */ + s->port.state->port.tty->low_latency = 1; + + /* Get new baud rate generator configuration */ + baud = tty_get_baud_rate(tty); + + spin_lock_irqsave(&s->data_lock, flags); + new_brg = get_new_brg(baud, s); + /* if can't find the corrent config, use previous */ + if (!new_brg) { + baud = s->baud; + new_brg = s->brg_cfg; + } + spin_unlock_irqrestore(&s->data_lock, flags); + tty_termios_encode_baud_rate(termios, baud, baud); + s->baud = baud; + + /* Update timeout according to new baud rate */ + uart_update_timeout(port, termios->c_cflag, baud); + + spin_lock_irqsave(&s->data_lock, flags); + if (s->lcr_reg != new_lcr) { + s->lcr_reg = new_lcr; + s->lcr_commit = 1; + } + if (s->brg_cfg != new_brg) { + s->brg_cfg = new_brg; + s->brg_commit = 1; + } + spin_unlock_irqrestore(&s->data_lock, flags); + + /* Trigger work thread for doing the actual configuration change */ + max3107_dowork(s); +} + +/* Port shutdown function */ +static void max3107_shutdown(struct uart_port *port) +{ + struct max3107_port *s = container_of(port, struct max3107_port, port); + + if (s->suspended && s->pdata->hw_suspend) + s->pdata->hw_suspend(s, 0); + + /* Free the interrupt */ + free_irq(s->spi->irq, s); + + if (s->workqueue) { + /* Flush and destroy work queue */ + flush_workqueue(s->workqueue); + destroy_workqueue(s->workqueue); + s->workqueue = NULL; + } + + /* Suspend HW */ + if (s->pdata->hw_suspend) + s->pdata->hw_suspend(s, 1); +} + +/* Port startup function */ +static int max3107_startup(struct uart_port *port) +{ + struct max3107_port *s = container_of(port, struct max3107_port, port); + + /* Initialize work queue */ + s->workqueue = create_freezable_workqueue("max3107"); + if (!s->workqueue) { + dev_err(&s->spi->dev, "Workqueue creation failed\n"); + return -EBUSY; + } + INIT_WORK(&s->work, max3107_work); + + /* Setup IRQ */ + if (request_irq(s->spi->irq, max3107_irq, IRQF_TRIGGER_FALLING, + "max3107", s)) { + dev_err(&s->spi->dev, "IRQ reguest failed\n"); + destroy_workqueue(s->workqueue); + s->workqueue = NULL; + return -EBUSY; + } + + /* Resume HW */ + if (s->pdata->hw_suspend) + s->pdata->hw_suspend(s, 0); + + /* Init registers */ + max3107_register_init(s); + + return 0; +} + +/* Port type function */ +static const char *max3107_type(struct uart_port *port) +{ + struct max3107_port *s = container_of(port, struct max3107_port, port); + return s->spi->modalias; +} + +/* Port release function */ +static void max3107_release_port(struct uart_port *port) +{ + /* Do nothing */ +} + +/* Port request function */ +static int max3107_request_port(struct uart_port *port) +{ + /* Do nothing */ + return 0; +} + +/* Port config function */ +static void max3107_config_port(struct uart_port *port, int flags) +{ + struct max3107_port *s = container_of(port, struct max3107_port, port); + s->port.type = PORT_MAX3107; +} + +/* Port verify function */ +static int max3107_verify_port(struct uart_port *port, + struct serial_struct *ser) +{ + if (ser->type == PORT_UNKNOWN || ser->type == PORT_MAX3107) + return 0; + + return -EINVAL; +} + +/* Port stop TX function */ +static void max3107_stop_tx(struct uart_port *port) +{ + /* Do nothing */ +} + +/* Port break control function */ +static void max3107_break_ctl(struct uart_port *port, int break_state) +{ + /* We don't support break control, do nothing */ +} + + +/* Port functions */ +static struct uart_ops max3107_ops = { + .tx_empty = max3107_tx_empty, + .set_mctrl = max3107_set_mctrl, + .get_mctrl = max3107_get_mctrl, + .stop_tx = max3107_stop_tx, + .start_tx = max3107_start_tx, + .stop_rx = max3107_stop_rx, + .enable_ms = max3107_enable_ms, + .break_ctl = max3107_break_ctl, + .startup = max3107_startup, + .shutdown = max3107_shutdown, + .set_termios = max3107_set_termios, + .type = max3107_type, + .release_port = max3107_release_port, + .request_port = max3107_request_port, + .config_port = max3107_config_port, + .verify_port = max3107_verify_port, +}; + +/* UART driver data */ +static struct uart_driver max3107_uart_driver = { + .owner = THIS_MODULE, + .driver_name = "ttyMAX", + .dev_name = "ttyMAX", + .nr = 1, +}; + +static int driver_registered = 0; + + + +/* 'Generic' platform data */ +static struct max3107_plat generic_plat_data = { + .loopback = 0, + .ext_clk = 1, + .hw_suspend = max3107_hw_susp, + .polled_mode = 0, + .poll_time = 0, +}; + + +/*******************************************************************/ + +/** + * max3107_probe - SPI bus probe entry point + * @spi: the spi device + * + * SPI wants us to probe this device and if appropriate claim it. + * Perform any platform specific requirements and then initialise + * the device. + */ + +int max3107_probe(struct spi_device *spi, struct max3107_plat *pdata) +{ + struct max3107_port *s; + u16 buf[2]; /* Buffer for SPI transfers */ + int retval; + + pr_info("enter max3107 probe\n"); + + /* Allocate port structure */ + s = kzalloc(sizeof(*s), GFP_KERNEL); + if (!s) { + pr_err("Allocating port structure failed\n"); + return -ENOMEM; + } + + s->pdata = pdata; + + /* SPI Rx buffer + * +2 for RX FIFO interrupt + * disabling and RX level query + */ + s->rxbuf = kzalloc(sizeof(u16) * (MAX3107_RX_FIFO_SIZE+2), GFP_KERNEL); + if (!s->rxbuf) { + pr_err("Allocating RX buffer failed\n"); + retval = -ENOMEM; + goto err_free4; + } + s->rxstr = kzalloc(sizeof(u8) * MAX3107_RX_FIFO_SIZE, GFP_KERNEL); + if (!s->rxstr) { + pr_err("Allocating RX buffer failed\n"); + retval = -ENOMEM; + goto err_free3; + } + /* SPI Tx buffer + * SPI transfer buffer + * +3 for TX FIFO empty + * interrupt disabling and + * enabling and TX enabling + */ + s->txbuf = kzalloc(sizeof(u16) * MAX3107_TX_FIFO_SIZE + 3, GFP_KERNEL); + if (!s->txbuf) { + pr_err("Allocating TX buffer failed\n"); + retval = -ENOMEM; + goto err_free2; + } + /* Initialize shared data lock */ + spin_lock_init(&s->data_lock); + + /* SPI intializations */ + dev_set_drvdata(&spi->dev, s); + spi->mode = SPI_MODE_0; + spi->dev.platform_data = pdata; + spi->bits_per_word = 16; + s->ext_clk = pdata->ext_clk; + s->loopback = pdata->loopback; + spi_setup(spi); + s->spi = spi; + + /* Check REV ID to ensure we are talking to what we expect */ + buf[0] = MAX3107_REVID_REG; + if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 2)) { + dev_err(&s->spi->dev, "SPI transfer for REVID read failed\n"); + retval = -EIO; + goto err_free1; + } + if ((buf[0] & MAX3107_SPI_RX_DATA_MASK) != MAX3107_REVID1 && + (buf[0] & MAX3107_SPI_RX_DATA_MASK) != MAX3107_REVID2) { + dev_err(&s->spi->dev, "REVID %x does not match\n", + (buf[0] & MAX3107_SPI_RX_DATA_MASK)); + retval = -ENODEV; + goto err_free1; + } + + /* Disable all interrupts */ + buf[0] = (MAX3107_WRITE_BIT | MAX3107_IRQEN_REG | 0x0000); + buf[0] |= 0x0000; + + /* Configure clock source */ + buf[1] = (MAX3107_WRITE_BIT | MAX3107_CLKSRC_REG); + if (s->ext_clk) { + /* External clock */ + buf[1] |= MAX3107_CLKSRC_EXTCLK_BIT; + } + + /* PLL bypass ON */ + buf[1] |= MAX3107_CLKSRC_PLLBYP_BIT; + + /* Perform SPI transfer */ + if (max3107_rw(s, (u8 *)buf, NULL, 4)) { + dev_err(&s->spi->dev, "SPI transfer for init failed\n"); + retval = -EIO; + goto err_free1; + } + + /* Register UART driver */ + if (!driver_registered) { + retval = uart_register_driver(&max3107_uart_driver); + if (retval) { + dev_err(&s->spi->dev, "Registering UART driver failed\n"); + goto err_free1; + } + driver_registered = 1; + } + + /* Initialize UART port data */ + s->port.fifosize = 128; + s->port.ops = &max3107_ops; + s->port.line = 0; + s->port.dev = &spi->dev; + s->port.uartclk = 9600; + s->port.flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF; + s->port.irq = s->spi->irq; + s->port.type = PORT_MAX3107; + + /* Add UART port */ + retval = uart_add_one_port(&max3107_uart_driver, &s->port); + if (retval < 0) { + dev_err(&s->spi->dev, "Adding UART port failed\n"); + goto err_free1; + } + + if (pdata->configure) { + retval = pdata->configure(s); + if (retval < 0) + goto err_free1; + } + + /* Go to suspend mode */ + if (pdata->hw_suspend) + pdata->hw_suspend(s, 1); + + return 0; + +err_free1: + kfree(s->txbuf); +err_free2: + kfree(s->rxstr); +err_free3: + kfree(s->rxbuf); +err_free4: + kfree(s); + return retval; +} +EXPORT_SYMBOL_GPL(max3107_probe); + +/* Driver remove function */ +int max3107_remove(struct spi_device *spi) +{ + struct max3107_port *s = dev_get_drvdata(&spi->dev); + + pr_info("enter max3107 remove\n"); + + /* Remove port */ + if (uart_remove_one_port(&max3107_uart_driver, &s->port)) + dev_warn(&s->spi->dev, "Removing UART port failed\n"); + + + /* Free TxRx buffer */ + kfree(s->rxbuf); + kfree(s->rxstr); + kfree(s->txbuf); + + /* Free port structure */ + kfree(s); + + return 0; +} +EXPORT_SYMBOL_GPL(max3107_remove); + +/* Driver suspend function */ +int max3107_suspend(struct spi_device *spi, pm_message_t state) +{ +#ifdef CONFIG_PM + struct max3107_port *s = dev_get_drvdata(&spi->dev); + + pr_debug("enter suspend\n"); + + /* Suspend UART port */ + uart_suspend_port(&max3107_uart_driver, &s->port); + + /* Go to suspend mode */ + if (s->pdata->hw_suspend) + s->pdata->hw_suspend(s, 1); +#endif /* CONFIG_PM */ + return 0; +} +EXPORT_SYMBOL_GPL(max3107_suspend); + +/* Driver resume function */ +int max3107_resume(struct spi_device *spi) +{ +#ifdef CONFIG_PM + struct max3107_port *s = dev_get_drvdata(&spi->dev); + + pr_debug("enter resume\n"); + + /* Resume from suspend */ + if (s->pdata->hw_suspend) + s->pdata->hw_suspend(s, 0); + + /* Resume UART port */ + uart_resume_port(&max3107_uart_driver, &s->port); +#endif /* CONFIG_PM */ + return 0; +} +EXPORT_SYMBOL_GPL(max3107_resume); + +static int max3107_probe_generic(struct spi_device *spi) +{ + return max3107_probe(spi, &generic_plat_data); +} + +/* Spi driver data */ +static struct spi_driver max3107_driver = { + .driver = { + .name = "max3107", + .owner = THIS_MODULE, + }, + .probe = max3107_probe_generic, + .remove = __devexit_p(max3107_remove), + .suspend = max3107_suspend, + .resume = max3107_resume, +}; + +/* Driver init function */ +static int __init max3107_init(void) +{ + pr_info("enter max3107 init\n"); + return spi_register_driver(&max3107_driver); +} + +/* Driver exit function */ +static void __exit max3107_exit(void) +{ + pr_info("enter max3107 exit\n"); + /* Unregister UART driver */ + if (driver_registered) + uart_unregister_driver(&max3107_uart_driver); + spi_unregister_driver(&max3107_driver); +} + +module_init(max3107_init); +module_exit(max3107_exit); + +MODULE_DESCRIPTION("MAX3107 driver"); +MODULE_AUTHOR("Aavamobile"); +MODULE_ALIAS("spi:max3107"); +MODULE_LICENSE("GPL v2"); diff --git a/trunk/drivers/tty/serial/max3107.h b/trunk/drivers/tty/serial/max3107.h new file mode 100644 index 000000000000..8415fc723b96 --- /dev/null +++ b/trunk/drivers/tty/serial/max3107.h @@ -0,0 +1,441 @@ +/* + * max3107.h - spi uart protocol driver header for Maxim 3107 + * + * Copyright (C) Aavamobile 2009 + * Based on serial_max3100.h by Christian Pellegrin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#ifndef _MAX3107_H +#define _MAX3107_H + +/* Serial error status definitions */ +#define MAX3107_PARITY_ERROR 1 +#define MAX3107_FRAME_ERROR 2 +#define MAX3107_OVERRUN_ERROR 4 +#define MAX3107_ALL_ERRORS (MAX3107_PARITY_ERROR | \ + MAX3107_FRAME_ERROR | \ + MAX3107_OVERRUN_ERROR) + +/* GPIO definitions */ +#define MAX3107_GPIO_BASE 88 +#define MAX3107_GPIO_COUNT 4 + + +/* GPIO connected to chip's reset pin */ +#define MAX3107_RESET_GPIO 87 + + +/* Chip reset delay */ +#define MAX3107_RESET_DELAY 10 + +/* Chip wakeup delay */ +#define MAX3107_WAKEUP_DELAY 50 + + +/* Sleep mode definitions */ +#define MAX3107_DISABLE_FORCED_SLEEP 0 +#define MAX3107_ENABLE_FORCED_SLEEP 1 +#define MAX3107_DISABLE_AUTOSLEEP 2 +#define MAX3107_ENABLE_AUTOSLEEP 3 + + +/* Definitions for register access with SPI transfers + * + * SPI transfer format: + * + * Master to slave bits xzzzzzzzyyyyyyyy + * Slave to master bits aaaaaaaabbbbbbbb + * + * where: + * x = 0 for reads, 1 for writes + * z = register address + * y = new register value if write, 0 if read + * a = unspecified + * b = register value if read, unspecified if write + */ + +/* SPI speed */ +#define MAX3107_SPI_SPEED (3125000 * 2) + +/* Write bit */ +#define MAX3107_WRITE_BIT (1 << 15) + +/* SPI TX data mask */ +#define MAX3107_SPI_RX_DATA_MASK (0x00ff) + +/* SPI RX data mask */ +#define MAX3107_SPI_TX_DATA_MASK (0x00ff) + +/* Register access masks */ +#define MAX3107_RHR_REG (0x0000) /* RX FIFO */ +#define MAX3107_THR_REG (0x0000) /* TX FIFO */ +#define MAX3107_IRQEN_REG (0x0100) /* IRQ enable */ +#define MAX3107_IRQSTS_REG (0x0200) /* IRQ status */ +#define MAX3107_LSR_IRQEN_REG (0x0300) /* LSR IRQ enable */ +#define MAX3107_LSR_IRQSTS_REG (0x0400) /* LSR IRQ status */ +#define MAX3107_SPCHR_IRQEN_REG (0x0500) /* Special char IRQ enable */ +#define MAX3107_SPCHR_IRQSTS_REG (0x0600) /* Special char IRQ status */ +#define MAX3107_STS_IRQEN_REG (0x0700) /* Status IRQ enable */ +#define MAX3107_STS_IRQSTS_REG (0x0800) /* Status IRQ status */ +#define MAX3107_MODE1_REG (0x0900) /* MODE1 */ +#define MAX3107_MODE2_REG (0x0a00) /* MODE2 */ +#define MAX3107_LCR_REG (0x0b00) /* LCR */ +#define MAX3107_RXTO_REG (0x0c00) /* RX timeout */ +#define MAX3107_HDPIXDELAY_REG (0x0d00) /* Auto transceiver delays */ +#define MAX3107_IRDA_REG (0x0e00) /* IRDA settings */ +#define MAX3107_FLOWLVL_REG (0x0f00) /* Flow control levels */ +#define MAX3107_FIFOTRIGLVL_REG (0x1000) /* FIFO IRQ trigger levels */ +#define MAX3107_TXFIFOLVL_REG (0x1100) /* TX FIFO level */ +#define MAX3107_RXFIFOLVL_REG (0x1200) /* RX FIFO level */ +#define MAX3107_FLOWCTRL_REG (0x1300) /* Flow control */ +#define MAX3107_XON1_REG (0x1400) /* XON1 character */ +#define MAX3107_XON2_REG (0x1500) /* XON2 character */ +#define MAX3107_XOFF1_REG (0x1600) /* XOFF1 character */ +#define MAX3107_XOFF2_REG (0x1700) /* XOFF2 character */ +#define MAX3107_GPIOCFG_REG (0x1800) /* GPIO config */ +#define MAX3107_GPIODATA_REG (0x1900) /* GPIO data */ +#define MAX3107_PLLCFG_REG (0x1a00) /* PLL config */ +#define MAX3107_BRGCFG_REG (0x1b00) /* Baud rate generator conf */ +#define MAX3107_BRGDIVLSB_REG (0x1c00) /* Baud rate divisor LSB */ +#define MAX3107_BRGDIVMSB_REG (0x1d00) /* Baud rate divisor MSB */ +#define MAX3107_CLKSRC_REG (0x1e00) /* Clock source */ +#define MAX3107_REVID_REG (0x1f00) /* Revision identification */ + +/* IRQ register bits */ +#define MAX3107_IRQ_LSR_BIT (1 << 0) /* LSR interrupt */ +#define MAX3107_IRQ_SPCHR_BIT (1 << 1) /* Special char interrupt */ +#define MAX3107_IRQ_STS_BIT (1 << 2) /* Status interrupt */ +#define MAX3107_IRQ_RXFIFO_BIT (1 << 3) /* RX FIFO interrupt */ +#define MAX3107_IRQ_TXFIFO_BIT (1 << 4) /* TX FIFO interrupt */ +#define MAX3107_IRQ_TXEMPTY_BIT (1 << 5) /* TX FIFO empty interrupt */ +#define MAX3107_IRQ_RXEMPTY_BIT (1 << 6) /* RX FIFO empty interrupt */ +#define MAX3107_IRQ_CTS_BIT (1 << 7) /* CTS interrupt */ + +/* LSR register bits */ +#define MAX3107_LSR_RXTO_BIT (1 << 0) /* RX timeout */ +#define MAX3107_LSR_RXOVR_BIT (1 << 1) /* RX overrun */ +#define MAX3107_LSR_RXPAR_BIT (1 << 2) /* RX parity error */ +#define MAX3107_LSR_FRERR_BIT (1 << 3) /* Frame error */ +#define MAX3107_LSR_RXBRK_BIT (1 << 4) /* RX break */ +#define MAX3107_LSR_RXNOISE_BIT (1 << 5) /* RX noise */ +#define MAX3107_LSR_UNDEF6_BIT (1 << 6) /* Undefined/not used */ +#define MAX3107_LSR_CTS_BIT (1 << 7) /* CTS pin state */ + +/* Special character register bits */ +#define MAX3107_SPCHR_XON1_BIT (1 << 0) /* XON1 character */ +#define MAX3107_SPCHR_XON2_BIT (1 << 1) /* XON2 character */ +#define MAX3107_SPCHR_XOFF1_BIT (1 << 2) /* XOFF1 character */ +#define MAX3107_SPCHR_XOFF2_BIT (1 << 3) /* XOFF2 character */ +#define MAX3107_SPCHR_BREAK_BIT (1 << 4) /* RX break */ +#define MAX3107_SPCHR_MULTIDROP_BIT (1 << 5) /* 9-bit multidrop addr char */ +#define MAX3107_SPCHR_UNDEF6_BIT (1 << 6) /* Undefined/not used */ +#define MAX3107_SPCHR_UNDEF7_BIT (1 << 7) /* Undefined/not used */ + +/* Status register bits */ +#define MAX3107_STS_GPIO0_BIT (1 << 0) /* GPIO 0 interrupt */ +#define MAX3107_STS_GPIO1_BIT (1 << 1) /* GPIO 1 interrupt */ +#define MAX3107_STS_GPIO2_BIT (1 << 2) /* GPIO 2 interrupt */ +#define MAX3107_STS_GPIO3_BIT (1 << 3) /* GPIO 3 interrupt */ +#define MAX3107_STS_UNDEF4_BIT (1 << 4) /* Undefined/not used */ +#define MAX3107_STS_CLKREADY_BIT (1 << 5) /* Clock ready */ +#define MAX3107_STS_SLEEP_BIT (1 << 6) /* Sleep interrupt */ +#define MAX3107_STS_UNDEF7_BIT (1 << 7) /* Undefined/not used */ + +/* MODE1 register bits */ +#define MAX3107_MODE1_RXDIS_BIT (1 << 0) /* RX disable */ +#define MAX3107_MODE1_TXDIS_BIT (1 << 1) /* TX disable */ +#define MAX3107_MODE1_TXHIZ_BIT (1 << 2) /* TX pin three-state */ +#define MAX3107_MODE1_RTSHIZ_BIT (1 << 3) /* RTS pin three-state */ +#define MAX3107_MODE1_TRNSCVCTRL_BIT (1 << 4) /* Transceiver ctrl enable */ +#define MAX3107_MODE1_FORCESLEEP_BIT (1 << 5) /* Force sleep mode */ +#define MAX3107_MODE1_AUTOSLEEP_BIT (1 << 6) /* Auto sleep enable */ +#define MAX3107_MODE1_IRQSEL_BIT (1 << 7) /* IRQ pin enable */ + +/* MODE2 register bits */ +#define MAX3107_MODE2_RST_BIT (1 << 0) /* Chip reset */ +#define MAX3107_MODE2_FIFORST_BIT (1 << 1) /* FIFO reset */ +#define MAX3107_MODE2_RXTRIGINV_BIT (1 << 2) /* RX FIFO INT invert */ +#define MAX3107_MODE2_RXEMPTINV_BIT (1 << 3) /* RX FIFO empty INT invert */ +#define MAX3107_MODE2_SPCHR_BIT (1 << 4) /* Special chr detect enable */ +#define MAX3107_MODE2_LOOPBACK_BIT (1 << 5) /* Internal loopback enable */ +#define MAX3107_MODE2_MULTIDROP_BIT (1 << 6) /* 9-bit multidrop enable */ +#define MAX3107_MODE2_ECHOSUPR_BIT (1 << 7) /* ECHO suppression enable */ + +/* LCR register bits */ +#define MAX3107_LCR_LENGTH0_BIT (1 << 0) /* Word length bit 0 */ +#define MAX3107_LCR_LENGTH1_BIT (1 << 1) /* Word length bit 1 + * + * Word length bits table: + * 00 -> 5 bit words + * 01 -> 6 bit words + * 10 -> 7 bit words + * 11 -> 8 bit words + */ +#define MAX3107_LCR_STOPLEN_BIT (1 << 2) /* STOP length bit + * + * STOP length bit table: + * 0 -> 1 stop bit + * 1 -> 1-1.5 stop bits if + * word length is 5, + * 2 stop bits otherwise + */ +#define MAX3107_LCR_PARITY_BIT (1 << 3) /* Parity bit enable */ +#define MAX3107_LCR_EVENPARITY_BIT (1 << 4) /* Even parity bit enable */ +#define MAX3107_LCR_FORCEPARITY_BIT (1 << 5) /* 9-bit multidrop parity */ +#define MAX3107_LCR_TXBREAK_BIT (1 << 6) /* TX break enable */ +#define MAX3107_LCR_RTS_BIT (1 << 7) /* RTS pin control */ +#define MAX3107_LCR_WORD_LEN_5 (0x0000) +#define MAX3107_LCR_WORD_LEN_6 (0x0001) +#define MAX3107_LCR_WORD_LEN_7 (0x0002) +#define MAX3107_LCR_WORD_LEN_8 (0x0003) + + +/* IRDA register bits */ +#define MAX3107_IRDA_IRDAEN_BIT (1 << 0) /* IRDA mode enable */ +#define MAX3107_IRDA_SIR_BIT (1 << 1) /* SIR mode enable */ +#define MAX3107_IRDA_SHORTIR_BIT (1 << 2) /* Short SIR mode enable */ +#define MAX3107_IRDA_MIR_BIT (1 << 3) /* MIR mode enable */ +#define MAX3107_IRDA_RXINV_BIT (1 << 4) /* RX logic inversion enable */ +#define MAX3107_IRDA_TXINV_BIT (1 << 5) /* TX logic inversion enable */ +#define MAX3107_IRDA_UNDEF6_BIT (1 << 6) /* Undefined/not used */ +#define MAX3107_IRDA_UNDEF7_BIT (1 << 7) /* Undefined/not used */ + +/* Flow control trigger level register masks */ +#define MAX3107_FLOWLVL_HALT_MASK (0x000f) /* Flow control halt level */ +#define MAX3107_FLOWLVL_RES_MASK (0x00f0) /* Flow control resume level */ +#define MAX3107_FLOWLVL_HALT(words) ((words/8) & 0x000f) +#define MAX3107_FLOWLVL_RES(words) (((words/8) & 0x000f) << 4) + +/* FIFO interrupt trigger level register masks */ +#define MAX3107_FIFOTRIGLVL_TX_MASK (0x000f) /* TX FIFO trigger level */ +#define MAX3107_FIFOTRIGLVL_RX_MASK (0x00f0) /* RX FIFO trigger level */ +#define MAX3107_FIFOTRIGLVL_TX(words) ((words/8) & 0x000f) +#define MAX3107_FIFOTRIGLVL_RX(words) (((words/8) & 0x000f) << 4) + +/* Flow control register bits */ +#define MAX3107_FLOWCTRL_AUTORTS_BIT (1 << 0) /* Auto RTS flow ctrl enable */ +#define MAX3107_FLOWCTRL_AUTOCTS_BIT (1 << 1) /* Auto CTS flow ctrl enable */ +#define MAX3107_FLOWCTRL_GPIADDR_BIT (1 << 2) /* Enables that GPIO inputs + * are used in conjunction with + * XOFF2 for definition of + * special character */ +#define MAX3107_FLOWCTRL_SWFLOWEN_BIT (1 << 3) /* Auto SW flow ctrl enable */ +#define MAX3107_FLOWCTRL_SWFLOW0_BIT (1 << 4) /* SWFLOW bit 0 */ +#define MAX3107_FLOWCTRL_SWFLOW1_BIT (1 << 5) /* SWFLOW bit 1 + * + * SWFLOW bits 1 & 0 table: + * 00 -> no transmitter flow + * control + * 01 -> receiver compares + * XON2 and XOFF2 + * and controls + * transmitter + * 10 -> receiver compares + * XON1 and XOFF1 + * and controls + * transmitter + * 11 -> receiver compares + * XON1, XON2, XOFF1 and + * XOFF2 and controls + * transmitter + */ +#define MAX3107_FLOWCTRL_SWFLOW2_BIT (1 << 6) /* SWFLOW bit 2 */ +#define MAX3107_FLOWCTRL_SWFLOW3_BIT (1 << 7) /* SWFLOW bit 3 + * + * SWFLOW bits 3 & 2 table: + * 00 -> no received flow + * control + * 01 -> transmitter generates + * XON2 and XOFF2 + * 10 -> transmitter generates + * XON1 and XOFF1 + * 11 -> transmitter generates + * XON1, XON2, XOFF1 and + * XOFF2 + */ + +/* GPIO configuration register bits */ +#define MAX3107_GPIOCFG_GP0OUT_BIT (1 << 0) /* GPIO 0 output enable */ +#define MAX3107_GPIOCFG_GP1OUT_BIT (1 << 1) /* GPIO 1 output enable */ +#define MAX3107_GPIOCFG_GP2OUT_BIT (1 << 2) /* GPIO 2 output enable */ +#define MAX3107_GPIOCFG_GP3OUT_BIT (1 << 3) /* GPIO 3 output enable */ +#define MAX3107_GPIOCFG_GP0OD_BIT (1 << 4) /* GPIO 0 open-drain enable */ +#define MAX3107_GPIOCFG_GP1OD_BIT (1 << 5) /* GPIO 1 open-drain enable */ +#define MAX3107_GPIOCFG_GP2OD_BIT (1 << 6) /* GPIO 2 open-drain enable */ +#define MAX3107_GPIOCFG_GP3OD_BIT (1 << 7) /* GPIO 3 open-drain enable */ + +/* GPIO DATA register bits */ +#define MAX3107_GPIODATA_GP0OUT_BIT (1 << 0) /* GPIO 0 output value */ +#define MAX3107_GPIODATA_GP1OUT_BIT (1 << 1) /* GPIO 1 output value */ +#define MAX3107_GPIODATA_GP2OUT_BIT (1 << 2) /* GPIO 2 output value */ +#define MAX3107_GPIODATA_GP3OUT_BIT (1 << 3) /* GPIO 3 output value */ +#define MAX3107_GPIODATA_GP0IN_BIT (1 << 4) /* GPIO 0 input value */ +#define MAX3107_GPIODATA_GP1IN_BIT (1 << 5) /* GPIO 1 input value */ +#define MAX3107_GPIODATA_GP2IN_BIT (1 << 6) /* GPIO 2 input value */ +#define MAX3107_GPIODATA_GP3IN_BIT (1 << 7) /* GPIO 3 input value */ + +/* PLL configuration register masks */ +#define MAX3107_PLLCFG_PREDIV_MASK (0x003f) /* PLL predivision value */ +#define MAX3107_PLLCFG_PLLFACTOR_MASK (0x00c0) /* PLL multiplication factor */ + +/* Baud rate generator configuration register masks and bits */ +#define MAX3107_BRGCFG_FRACT_MASK (0x000f) /* Fractional portion of + * Baud rate generator divisor + */ +#define MAX3107_BRGCFG_2XMODE_BIT (1 << 4) /* Double baud rate */ +#define MAX3107_BRGCFG_4XMODE_BIT (1 << 5) /* Quadruple baud rate */ +#define MAX3107_BRGCFG_UNDEF6_BIT (1 << 6) /* Undefined/not used */ +#define MAX3107_BRGCFG_UNDEF7_BIT (1 << 7) /* Undefined/not used */ + +/* Clock source register bits */ +#define MAX3107_CLKSRC_INTOSC_BIT (1 << 0) /* Internal osc enable */ +#define MAX3107_CLKSRC_CRYST_BIT (1 << 1) /* Crystal osc enable */ +#define MAX3107_CLKSRC_PLL_BIT (1 << 2) /* PLL enable */ +#define MAX3107_CLKSRC_PLLBYP_BIT (1 << 3) /* PLL bypass */ +#define MAX3107_CLKSRC_EXTCLK_BIT (1 << 4) /* External clock enable */ +#define MAX3107_CLKSRC_UNDEF5_BIT (1 << 5) /* Undefined/not used */ +#define MAX3107_CLKSRC_UNDEF6_BIT (1 << 6) /* Undefined/not used */ +#define MAX3107_CLKSRC_CLK2RTS_BIT (1 << 7) /* Baud clk to RTS pin */ + + +/* HW definitions */ +#define MAX3107_RX_FIFO_SIZE 128 +#define MAX3107_TX_FIFO_SIZE 128 +#define MAX3107_REVID1 0x00a0 +#define MAX3107_REVID2 0x00a1 + + +/* Baud rate generator configuration values for external clock 13MHz */ +#define MAX3107_BRG13_B300 (0x0A9400 | 0x05) +#define MAX3107_BRG13_B600 (0x054A00 | 0x03) +#define MAX3107_BRG13_B1200 (0x02A500 | 0x01) +#define MAX3107_BRG13_B2400 (0x015200 | 0x09) +#define MAX3107_BRG13_B4800 (0x00A900 | 0x04) +#define MAX3107_BRG13_B9600 (0x005400 | 0x0A) +#define MAX3107_BRG13_B19200 (0x002A00 | 0x05) +#define MAX3107_BRG13_B38400 (0x001500 | 0x03) +#define MAX3107_BRG13_B57600 (0x000E00 | 0x02) +#define MAX3107_BRG13_B115200 (0x000700 | 0x01) +#define MAX3107_BRG13_B230400 (0x000300 | 0x08) +#define MAX3107_BRG13_B460800 (0x000100 | 0x0c) +#define MAX3107_BRG13_B921600 (0x000100 | 0x1c) + +/* Baud rate generator configuration values for external clock 26MHz */ +#define MAX3107_BRG26_B300 (0x152800 | 0x0A) +#define MAX3107_BRG26_B600 (0x0A9400 | 0x05) +#define MAX3107_BRG26_B1200 (0x054A00 | 0x03) +#define MAX3107_BRG26_B2400 (0x02A500 | 0x01) +#define MAX3107_BRG26_B4800 (0x015200 | 0x09) +#define MAX3107_BRG26_B9600 (0x00A900 | 0x04) +#define MAX3107_BRG26_B19200 (0x005400 | 0x0A) +#define MAX3107_BRG26_B38400 (0x002A00 | 0x05) +#define MAX3107_BRG26_B57600 (0x001C00 | 0x03) +#define MAX3107_BRG26_B115200 (0x000E00 | 0x02) +#define MAX3107_BRG26_B230400 (0x000700 | 0x01) +#define MAX3107_BRG26_B460800 (0x000300 | 0x08) +#define MAX3107_BRG26_B921600 (0x000100 | 0x0C) + +/* Baud rate generator configuration values for internal clock */ +#define MAX3107_BRG13_IB300 (0x008000 | 0x00) +#define MAX3107_BRG13_IB600 (0x004000 | 0x00) +#define MAX3107_BRG13_IB1200 (0x002000 | 0x00) +#define MAX3107_BRG13_IB2400 (0x001000 | 0x00) +#define MAX3107_BRG13_IB4800 (0x000800 | 0x00) +#define MAX3107_BRG13_IB9600 (0x000400 | 0x00) +#define MAX3107_BRG13_IB19200 (0x000200 | 0x00) +#define MAX3107_BRG13_IB38400 (0x000100 | 0x00) +#define MAX3107_BRG13_IB57600 (0x000000 | 0x0B) +#define MAX3107_BRG13_IB115200 (0x000000 | 0x05) +#define MAX3107_BRG13_IB230400 (0x000000 | 0x03) +#define MAX3107_BRG13_IB460800 (0x000000 | 0x00) +#define MAX3107_BRG13_IB921600 (0x000000 | 0x00) + + +struct baud_table { + int baud; + u32 new_brg; +}; + +struct max3107_port { + /* UART port structure */ + struct uart_port port; + + /* SPI device structure */ + struct spi_device *spi; + +#if defined(CONFIG_GPIOLIB) + /* GPIO chip structure */ + struct gpio_chip chip; +#endif + + /* Workqueue that does all the magic */ + struct workqueue_struct *workqueue; + struct work_struct work; + + /* Lock for shared data */ + spinlock_t data_lock; + + /* Device configuration */ + int ext_clk; /* 1 if external clock used */ + int loopback; /* Current loopback mode state */ + int baud; /* Current baud rate */ + + /* State flags */ + int suspended; /* Indicates suspend mode */ + int tx_fifo_empty; /* Flag for TX FIFO state */ + int rx_enabled; /* Flag for receiver state */ + int tx_enabled; /* Flag for transmitter state */ + + u16 irqen_reg; /* Current IRQ enable register value */ + /* Shared data */ + u16 mode1_reg; /* Current mode1 register value*/ + int mode1_commit; /* Flag for setting new mode1 register value */ + u16 lcr_reg; /* Current LCR register value */ + int lcr_commit; /* Flag for setting new LCR register value */ + u32 brg_cfg; /* Current Baud rate generator config */ + int brg_commit; /* Flag for setting new baud rate generator + * config + */ + struct baud_table *baud_tbl; + int handle_irq; /* Indicates that IRQ should be handled */ + + /* Rx buffer and str*/ + u16 *rxbuf; + u8 *rxstr; + /* Tx buffer*/ + u16 *txbuf; + + struct max3107_plat *pdata; /* Platform data */ +}; + +/* Platform data structure */ +struct max3107_plat { + /* Loopback mode enable */ + int loopback; + /* External clock enable */ + int ext_clk; + /* Called during the register initialisation */ + void (*init)(struct max3107_port *s); + /* Called when the port is found and configured */ + int (*configure)(struct max3107_port *s); + /* HW suspend function */ + void (*hw_suspend) (struct max3107_port *s, int suspend); + /* Polling mode enable */ + int polled_mode; + /* Polling period if polling mode enabled */ + int poll_time; +}; + +extern int max3107_rw(struct max3107_port *s, u8 *tx, u8 *rx, int len); +extern void max3107_hw_susp(struct max3107_port *s, int suspend); +extern int max3107_probe(struct spi_device *spi, struct max3107_plat *pdata); +extern int max3107_remove(struct spi_device *spi); +extern int max3107_suspend(struct spi_device *spi, pm_message_t state); +extern int max3107_resume(struct spi_device *spi); + +#endif /* _LINUX_SERIAL_MAX3107_H */ diff --git a/trunk/drivers/tty/serial/max310x.c b/trunk/drivers/tty/serial/max310x.c deleted file mode 100644 index 2bc28a59d385..000000000000 --- a/trunk/drivers/tty/serial/max310x.c +++ /dev/null @@ -1,1260 +0,0 @@ -/* - * Maxim (Dallas) MAX3107/8 serial driver - * - * Copyright (C) 2012 Alexander Shiyan - * - * Based on max3100.c, by Christian Pellegrin - * Based on max3110.c, by Feng Tang - * Based on max3107.c, by Aavamobile - * - * 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. - */ - -/* TODO: MAX3109 support (Dual) */ -/* TODO: MAX14830 support (Quad) */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define MAX310X_MAJOR 204 -#define MAX310X_MINOR 209 - -/* MAX310X register definitions */ -#define MAX310X_RHR_REG (0x00) /* RX FIFO */ -#define MAX310X_THR_REG (0x00) /* TX FIFO */ -#define MAX310X_IRQEN_REG (0x01) /* IRQ enable */ -#define MAX310X_IRQSTS_REG (0x02) /* IRQ status */ -#define MAX310X_LSR_IRQEN_REG (0x03) /* LSR IRQ enable */ -#define MAX310X_LSR_IRQSTS_REG (0x04) /* LSR IRQ status */ -#define MAX310X_SPCHR_IRQEN_REG (0x05) /* Special char IRQ enable */ -#define MAX310X_SPCHR_IRQSTS_REG (0x06) /* Special char IRQ status */ -#define MAX310X_STS_IRQEN_REG (0x07) /* Status IRQ enable */ -#define MAX310X_STS_IRQSTS_REG (0x08) /* Status IRQ status */ -#define MAX310X_MODE1_REG (0x09) /* MODE1 */ -#define MAX310X_MODE2_REG (0x0a) /* MODE2 */ -#define MAX310X_LCR_REG (0x0b) /* LCR */ -#define MAX310X_RXTO_REG (0x0c) /* RX timeout */ -#define MAX310X_HDPIXDELAY_REG (0x0d) /* Auto transceiver delays */ -#define MAX310X_IRDA_REG (0x0e) /* IRDA settings */ -#define MAX310X_FLOWLVL_REG (0x0f) /* Flow control levels */ -#define MAX310X_FIFOTRIGLVL_REG (0x10) /* FIFO IRQ trigger levels */ -#define MAX310X_TXFIFOLVL_REG (0x11) /* TX FIFO level */ -#define MAX310X_RXFIFOLVL_REG (0x12) /* RX FIFO level */ -#define MAX310X_FLOWCTRL_REG (0x13) /* Flow control */ -#define MAX310X_XON1_REG (0x14) /* XON1 character */ -#define MAX310X_XON2_REG (0x15) /* XON2 character */ -#define MAX310X_XOFF1_REG (0x16) /* XOFF1 character */ -#define MAX310X_XOFF2_REG (0x17) /* XOFF2 character */ -#define MAX310X_GPIOCFG_REG (0x18) /* GPIO config */ -#define MAX310X_GPIODATA_REG (0x19) /* GPIO data */ -#define MAX310X_PLLCFG_REG (0x1a) /* PLL config */ -#define MAX310X_BRGCFG_REG (0x1b) /* Baud rate generator conf */ -#define MAX310X_BRGDIVLSB_REG (0x1c) /* Baud rate divisor LSB */ -#define MAX310X_BRGDIVMSB_REG (0x1d) /* Baud rate divisor MSB */ -#define MAX310X_CLKSRC_REG (0x1e) /* Clock source */ -/* Only present in MAX3107 */ -#define MAX3107_REVID_REG (0x1f) /* Revision identification */ - -/* IRQ register bits */ -#define MAX310X_IRQ_LSR_BIT (1 << 0) /* LSR interrupt */ -#define MAX310X_IRQ_SPCHR_BIT (1 << 1) /* Special char interrupt */ -#define MAX310X_IRQ_STS_BIT (1 << 2) /* Status interrupt */ -#define MAX310X_IRQ_RXFIFO_BIT (1 << 3) /* RX FIFO interrupt */ -#define MAX310X_IRQ_TXFIFO_BIT (1 << 4) /* TX FIFO interrupt */ -#define MAX310X_IRQ_TXEMPTY_BIT (1 << 5) /* TX FIFO empty interrupt */ -#define MAX310X_IRQ_RXEMPTY_BIT (1 << 6) /* RX FIFO empty interrupt */ -#define MAX310X_IRQ_CTS_BIT (1 << 7) /* CTS interrupt */ - -/* LSR register bits */ -#define MAX310X_LSR_RXTO_BIT (1 << 0) /* RX timeout */ -#define MAX310X_LSR_RXOVR_BIT (1 << 1) /* RX overrun */ -#define MAX310X_LSR_RXPAR_BIT (1 << 2) /* RX parity error */ -#define MAX310X_LSR_FRERR_BIT (1 << 3) /* Frame error */ -#define MAX310X_LSR_RXBRK_BIT (1 << 4) /* RX break */ -#define MAX310X_LSR_RXNOISE_BIT (1 << 5) /* RX noise */ -#define MAX310X_LSR_CTS_BIT (1 << 7) /* CTS pin state */ - -/* Special character register bits */ -#define MAX310X_SPCHR_XON1_BIT (1 << 0) /* XON1 character */ -#define MAX310X_SPCHR_XON2_BIT (1 << 1) /* XON2 character */ -#define MAX310X_SPCHR_XOFF1_BIT (1 << 2) /* XOFF1 character */ -#define MAX310X_SPCHR_XOFF2_BIT (1 << 3) /* XOFF2 character */ -#define MAX310X_SPCHR_BREAK_BIT (1 << 4) /* RX break */ -#define MAX310X_SPCHR_MULTIDROP_BIT (1 << 5) /* 9-bit multidrop addr char */ - -/* Status register bits */ -#define MAX310X_STS_GPIO0_BIT (1 << 0) /* GPIO 0 interrupt */ -#define MAX310X_STS_GPIO1_BIT (1 << 1) /* GPIO 1 interrupt */ -#define MAX310X_STS_GPIO2_BIT (1 << 2) /* GPIO 2 interrupt */ -#define MAX310X_STS_GPIO3_BIT (1 << 3) /* GPIO 3 interrupt */ -#define MAX310X_STS_CLKREADY_BIT (1 << 5) /* Clock ready */ -#define MAX310X_STS_SLEEP_BIT (1 << 6) /* Sleep interrupt */ - -/* MODE1 register bits */ -#define MAX310X_MODE1_RXDIS_BIT (1 << 0) /* RX disable */ -#define MAX310X_MODE1_TXDIS_BIT (1 << 1) /* TX disable */ -#define MAX310X_MODE1_TXHIZ_BIT (1 << 2) /* TX pin three-state */ -#define MAX310X_MODE1_RTSHIZ_BIT (1 << 3) /* RTS pin three-state */ -#define MAX310X_MODE1_TRNSCVCTRL_BIT (1 << 4) /* Transceiver ctrl enable */ -#define MAX310X_MODE1_FORCESLEEP_BIT (1 << 5) /* Force sleep mode */ -#define MAX310X_MODE1_AUTOSLEEP_BIT (1 << 6) /* Auto sleep enable */ -#define MAX310X_MODE1_IRQSEL_BIT (1 << 7) /* IRQ pin enable */ - -/* MODE2 register bits */ -#define MAX310X_MODE2_RST_BIT (1 << 0) /* Chip reset */ -#define MAX310X_MODE2_FIFORST_BIT (1 << 1) /* FIFO reset */ -#define MAX310X_MODE2_RXTRIGINV_BIT (1 << 2) /* RX FIFO INT invert */ -#define MAX310X_MODE2_RXEMPTINV_BIT (1 << 3) /* RX FIFO empty INT invert */ -#define MAX310X_MODE2_SPCHR_BIT (1 << 4) /* Special chr detect enable */ -#define MAX310X_MODE2_LOOPBACK_BIT (1 << 5) /* Internal loopback enable */ -#define MAX310X_MODE2_MULTIDROP_BIT (1 << 6) /* 9-bit multidrop enable */ -#define MAX310X_MODE2_ECHOSUPR_BIT (1 << 7) /* ECHO suppression enable */ - -/* LCR register bits */ -#define MAX310X_LCR_LENGTH0_BIT (1 << 0) /* Word length bit 0 */ -#define MAX310X_LCR_LENGTH1_BIT (1 << 1) /* Word length bit 1 - * - * Word length bits table: - * 00 -> 5 bit words - * 01 -> 6 bit words - * 10 -> 7 bit words - * 11 -> 8 bit words - */ -#define MAX310X_LCR_STOPLEN_BIT (1 << 2) /* STOP length bit - * - * STOP length bit table: - * 0 -> 1 stop bit - * 1 -> 1-1.5 stop bits if - * word length is 5, - * 2 stop bits otherwise - */ -#define MAX310X_LCR_PARITY_BIT (1 << 3) /* Parity bit enable */ -#define MAX310X_LCR_EVENPARITY_BIT (1 << 4) /* Even parity bit enable */ -#define MAX310X_LCR_FORCEPARITY_BIT (1 << 5) /* 9-bit multidrop parity */ -#define MAX310X_LCR_TXBREAK_BIT (1 << 6) /* TX break enable */ -#define MAX310X_LCR_RTS_BIT (1 << 7) /* RTS pin control */ -#define MAX310X_LCR_WORD_LEN_5 (0x00) -#define MAX310X_LCR_WORD_LEN_6 (0x01) -#define MAX310X_LCR_WORD_LEN_7 (0x02) -#define MAX310X_LCR_WORD_LEN_8 (0x03) - -/* IRDA register bits */ -#define MAX310X_IRDA_IRDAEN_BIT (1 << 0) /* IRDA mode enable */ -#define MAX310X_IRDA_SIR_BIT (1 << 1) /* SIR mode enable */ -#define MAX310X_IRDA_SHORTIR_BIT (1 << 2) /* Short SIR mode enable */ -#define MAX310X_IRDA_MIR_BIT (1 << 3) /* MIR mode enable */ -#define MAX310X_IRDA_RXINV_BIT (1 << 4) /* RX logic inversion enable */ -#define MAX310X_IRDA_TXINV_BIT (1 << 5) /* TX logic inversion enable */ - -/* Flow control trigger level register masks */ -#define MAX310X_FLOWLVL_HALT_MASK (0x000f) /* Flow control halt level */ -#define MAX310X_FLOWLVL_RES_MASK (0x00f0) /* Flow control resume level */ -#define MAX310X_FLOWLVL_HALT(words) ((words / 8) & 0x0f) -#define MAX310X_FLOWLVL_RES(words) (((words / 8) & 0x0f) << 4) - -/* FIFO interrupt trigger level register masks */ -#define MAX310X_FIFOTRIGLVL_TX_MASK (0x0f) /* TX FIFO trigger level */ -#define MAX310X_FIFOTRIGLVL_RX_MASK (0xf0) /* RX FIFO trigger level */ -#define MAX310X_FIFOTRIGLVL_TX(words) ((words / 8) & 0x0f) -#define MAX310X_FIFOTRIGLVL_RX(words) (((words / 8) & 0x0f) << 4) - -/* Flow control register bits */ -#define MAX310X_FLOWCTRL_AUTORTS_BIT (1 << 0) /* Auto RTS flow ctrl enable */ -#define MAX310X_FLOWCTRL_AUTOCTS_BIT (1 << 1) /* Auto CTS flow ctrl enable */ -#define MAX310X_FLOWCTRL_GPIADDR_BIT (1 << 2) /* Enables that GPIO inputs - * are used in conjunction with - * XOFF2 for definition of - * special character */ -#define MAX310X_FLOWCTRL_SWFLOWEN_BIT (1 << 3) /* Auto SW flow ctrl enable */ -#define MAX310X_FLOWCTRL_SWFLOW0_BIT (1 << 4) /* SWFLOW bit 0 */ -#define MAX310X_FLOWCTRL_SWFLOW1_BIT (1 << 5) /* SWFLOW bit 1 - * - * SWFLOW bits 1 & 0 table: - * 00 -> no transmitter flow - * control - * 01 -> receiver compares - * XON2 and XOFF2 - * and controls - * transmitter - * 10 -> receiver compares - * XON1 and XOFF1 - * and controls - * transmitter - * 11 -> receiver compares - * XON1, XON2, XOFF1 and - * XOFF2 and controls - * transmitter - */ -#define MAX310X_FLOWCTRL_SWFLOW2_BIT (1 << 6) /* SWFLOW bit 2 */ -#define MAX310X_FLOWCTRL_SWFLOW3_BIT (1 << 7) /* SWFLOW bit 3 - * - * SWFLOW bits 3 & 2 table: - * 00 -> no received flow - * control - * 01 -> transmitter generates - * XON2 and XOFF2 - * 10 -> transmitter generates - * XON1 and XOFF1 - * 11 -> transmitter generates - * XON1, XON2, XOFF1 and - * XOFF2 - */ - -/* GPIO configuration register bits */ -#define MAX310X_GPIOCFG_GP0OUT_BIT (1 << 0) /* GPIO 0 output enable */ -#define MAX310X_GPIOCFG_GP1OUT_BIT (1 << 1) /* GPIO 1 output enable */ -#define MAX310X_GPIOCFG_GP2OUT_BIT (1 << 2) /* GPIO 2 output enable */ -#define MAX310X_GPIOCFG_GP3OUT_BIT (1 << 3) /* GPIO 3 output enable */ -#define MAX310X_GPIOCFG_GP0OD_BIT (1 << 4) /* GPIO 0 open-drain enable */ -#define MAX310X_GPIOCFG_GP1OD_BIT (1 << 5) /* GPIO 1 open-drain enable */ -#define MAX310X_GPIOCFG_GP2OD_BIT (1 << 6) /* GPIO 2 open-drain enable */ -#define MAX310X_GPIOCFG_GP3OD_BIT (1 << 7) /* GPIO 3 open-drain enable */ - -/* GPIO DATA register bits */ -#define MAX310X_GPIODATA_GP0OUT_BIT (1 << 0) /* GPIO 0 output value */ -#define MAX310X_GPIODATA_GP1OUT_BIT (1 << 1) /* GPIO 1 output value */ -#define MAX310X_GPIODATA_GP2OUT_BIT (1 << 2) /* GPIO 2 output value */ -#define MAX310X_GPIODATA_GP3OUT_BIT (1 << 3) /* GPIO 3 output value */ -#define MAX310X_GPIODATA_GP0IN_BIT (1 << 4) /* GPIO 0 input value */ -#define MAX310X_GPIODATA_GP1IN_BIT (1 << 5) /* GPIO 1 input value */ -#define MAX310X_GPIODATA_GP2IN_BIT (1 << 6) /* GPIO 2 input value */ -#define MAX310X_GPIODATA_GP3IN_BIT (1 << 7) /* GPIO 3 input value */ - -/* PLL configuration register masks */ -#define MAX310X_PLLCFG_PREDIV_MASK (0x3f) /* PLL predivision value */ -#define MAX310X_PLLCFG_PLLFACTOR_MASK (0xc0) /* PLL multiplication factor */ - -/* Baud rate generator configuration register bits */ -#define MAX310X_BRGCFG_2XMODE_BIT (1 << 4) /* Double baud rate */ -#define MAX310X_BRGCFG_4XMODE_BIT (1 << 5) /* Quadruple baud rate */ - -/* Clock source register bits */ -#define MAX310X_CLKSRC_CRYST_BIT (1 << 1) /* Crystal osc enable */ -#define MAX310X_CLKSRC_PLL_BIT (1 << 2) /* PLL enable */ -#define MAX310X_CLKSRC_PLLBYP_BIT (1 << 3) /* PLL bypass */ -#define MAX310X_CLKSRC_EXTCLK_BIT (1 << 4) /* External clock enable */ -#define MAX310X_CLKSRC_CLK2RTS_BIT (1 << 7) /* Baud clk to RTS pin */ - -/* Misc definitions */ -#define MAX310X_FIFO_SIZE (128) - -/* MAX3107 specific */ -#define MAX3107_REV_ID (0xa0) -#define MAX3107_REV_MASK (0xfe) - -/* IRQ status bits definitions */ -#define MAX310X_IRQ_TX (MAX310X_IRQ_TXFIFO_BIT | \ - MAX310X_IRQ_TXEMPTY_BIT) -#define MAX310X_IRQ_RX (MAX310X_IRQ_RXFIFO_BIT | \ - MAX310X_IRQ_RXEMPTY_BIT) - -/* Supported chip types */ -enum { - MAX310X_TYPE_MAX3107 = 3107, - MAX310X_TYPE_MAX3108 = 3108, -}; - -struct max310x_port { - struct uart_driver uart; - struct uart_port port; - - const char *name; - int uartclk; - - unsigned int nr_gpio; -#ifdef CONFIG_GPIOLIB - struct gpio_chip gpio; -#endif - - struct regmap *regmap; - struct regmap_config regcfg; - - struct workqueue_struct *wq; - struct work_struct tx_work; - - struct mutex max310x_mutex; - - struct max310x_pdata *pdata; -}; - -static bool max3107_8_reg_writeable(struct device *dev, unsigned int reg) -{ - switch (reg) { - case MAX310X_IRQSTS_REG: - case MAX310X_LSR_IRQSTS_REG: - case MAX310X_SPCHR_IRQSTS_REG: - case MAX310X_STS_IRQSTS_REG: - case MAX310X_TXFIFOLVL_REG: - case MAX310X_RXFIFOLVL_REG: - case MAX3107_REVID_REG: /* Only available on MAX3107 */ - return false; - default: - break; - } - - return true; -} - -static bool max310x_reg_volatile(struct device *dev, unsigned int reg) -{ - switch (reg) { - case MAX310X_RHR_REG: - case MAX310X_IRQSTS_REG: - case MAX310X_LSR_IRQSTS_REG: - case MAX310X_SPCHR_IRQSTS_REG: - case MAX310X_STS_IRQSTS_REG: - case MAX310X_TXFIFOLVL_REG: - case MAX310X_RXFIFOLVL_REG: - case MAX310X_GPIODATA_REG: - return true; - default: - break; - } - - return false; -} - -static bool max310x_reg_precious(struct device *dev, unsigned int reg) -{ - switch (reg) { - case MAX310X_RHR_REG: - case MAX310X_IRQSTS_REG: - case MAX310X_SPCHR_IRQSTS_REG: - case MAX310X_STS_IRQSTS_REG: - return true; - default: - break; - } - - return false; -} - -static void max310x_set_baud(struct max310x_port *s, int baud) -{ - unsigned int mode = 0, div = s->uartclk / baud; - - if (!(div / 16)) { - /* Mode x2 */ - mode = MAX310X_BRGCFG_2XMODE_BIT; - div = (s->uartclk * 2) / baud; - } - - if (!(div / 16)) { - /* Mode x4 */ - mode = MAX310X_BRGCFG_4XMODE_BIT; - div = (s->uartclk * 4) / baud; - } - - regmap_write(s->regmap, MAX310X_BRGDIVMSB_REG, - ((div / 16) >> 8) & 0xff); - regmap_write(s->regmap, MAX310X_BRGDIVLSB_REG, (div / 16) & 0xff); - regmap_write(s->regmap, MAX310X_BRGCFG_REG, (div % 16) | mode); -} - -static void max310x_wait_pll(struct max310x_port *s) -{ - int tryes = 1000; - - /* Wait for PLL only if crystal is used */ - if (!(s->pdata->driver_flags & MAX310X_EXT_CLK)) { - unsigned int sts = 0; - - while (tryes--) { - regmap_read(s->regmap, MAX310X_STS_IRQSTS_REG, &sts); - if (sts & MAX310X_STS_CLKREADY_BIT) - break; - } - } -} - -static int __devinit max310x_update_best_err(unsigned long f, long *besterr) -{ - /* Use baudrate 115200 for calculate error */ - long err = f % (115200 * 16); - - if ((*besterr < 0) || (*besterr > err)) { - *besterr = err; - return 0; - } - - return 1; -} - -static int __devinit max310x_set_ref_clk(struct max310x_port *s) -{ - unsigned int div, clksrc, pllcfg = 0; - long besterr = -1; - unsigned long fdiv, fmul, bestfreq = s->pdata->frequency; - - /* First, update error without PLL */ - max310x_update_best_err(s->pdata->frequency, &besterr); - - /* Try all possible PLL dividers */ - for (div = 1; (div <= 63) && besterr; div++) { - fdiv = DIV_ROUND_CLOSEST(s->pdata->frequency, div); - - /* Try multiplier 6 */ - fmul = fdiv * 6; - if ((fdiv >= 500000) && (fdiv <= 800000)) - if (!max310x_update_best_err(fmul, &besterr)) { - pllcfg = (0 << 6) | div; - bestfreq = fmul; - } - /* Try multiplier 48 */ - fmul = fdiv * 48; - if ((fdiv >= 850000) && (fdiv <= 1200000)) - if (!max310x_update_best_err(fmul, &besterr)) { - pllcfg = (1 << 6) | div; - bestfreq = fmul; - } - /* Try multiplier 96 */ - fmul = fdiv * 96; - if ((fdiv >= 425000) && (fdiv <= 1000000)) - if (!max310x_update_best_err(fmul, &besterr)) { - pllcfg = (2 << 6) | div; - bestfreq = fmul; - } - /* Try multiplier 144 */ - fmul = fdiv * 144; - if ((fdiv >= 390000) && (fdiv <= 667000)) - if (!max310x_update_best_err(fmul, &besterr)) { - pllcfg = (3 << 6) | div; - bestfreq = fmul; - } - } - - /* Configure clock source */ - if (s->pdata->driver_flags & MAX310X_EXT_CLK) - clksrc = MAX310X_CLKSRC_EXTCLK_BIT; - else - clksrc = MAX310X_CLKSRC_CRYST_BIT; - - /* Configure PLL */ - if (pllcfg) { - clksrc |= MAX310X_CLKSRC_PLL_BIT; - regmap_write(s->regmap, MAX310X_PLLCFG_REG, pllcfg); - } else - clksrc |= MAX310X_CLKSRC_PLLBYP_BIT; - - regmap_write(s->regmap, MAX310X_CLKSRC_REG, clksrc); - - if (pllcfg) - max310x_wait_pll(s); - - dev_dbg(s->port.dev, "Reference clock set to %lu Hz\n", bestfreq); - - return (int)bestfreq; -} - -static void max310x_handle_rx(struct max310x_port *s, unsigned int rxlen) -{ - unsigned int sts = 0, ch = 0, flag; - struct tty_struct *tty = tty_port_tty_get(&s->port.state->port); - - if (!tty) - return; - - if (unlikely(rxlen >= MAX310X_FIFO_SIZE)) { - dev_warn(s->port.dev, "Possible RX FIFO overrun %d\n", rxlen); - /* Ensure sanity of RX level */ - rxlen = MAX310X_FIFO_SIZE; - } - - dev_dbg(s->port.dev, "RX Len = %u\n", rxlen); - - while (rxlen--) { - regmap_read(s->regmap, MAX310X_RHR_REG, &ch); - regmap_read(s->regmap, MAX310X_LSR_IRQSTS_REG, &sts); - - sts &= MAX310X_LSR_RXPAR_BIT | MAX310X_LSR_FRERR_BIT | - MAX310X_LSR_RXOVR_BIT | MAX310X_LSR_RXBRK_BIT; - - s->port.icount.rx++; - flag = TTY_NORMAL; - - if (unlikely(sts)) { - if (sts & MAX310X_LSR_RXBRK_BIT) { - s->port.icount.brk++; - if (uart_handle_break(&s->port)) - continue; - } else if (sts & MAX310X_LSR_RXPAR_BIT) - s->port.icount.parity++; - else if (sts & MAX310X_LSR_FRERR_BIT) - s->port.icount.frame++; - else if (sts & MAX310X_LSR_RXOVR_BIT) - s->port.icount.overrun++; - - sts &= s->port.read_status_mask; - if (sts & MAX310X_LSR_RXBRK_BIT) - flag = TTY_BREAK; - else if (sts & MAX310X_LSR_RXPAR_BIT) - flag = TTY_PARITY; - else if (sts & MAX310X_LSR_FRERR_BIT) - flag = TTY_FRAME; - else if (sts & MAX310X_LSR_RXOVR_BIT) - flag = TTY_OVERRUN; - } - - if (uart_handle_sysrq_char(s->port, ch)) - continue; - - if (sts & s->port.ignore_status_mask) - continue; - - uart_insert_char(&s->port, sts, MAX310X_LSR_RXOVR_BIT, - ch, flag); - } - - tty_flip_buffer_push(tty); - - tty_kref_put(tty); -} - -static void max310x_handle_tx(struct max310x_port *s) -{ - struct circ_buf *xmit = &s->port.state->xmit; - unsigned int txlen = 0, to_send; - - if (unlikely(s->port.x_char)) { - regmap_write(s->regmap, MAX310X_THR_REG, s->port.x_char); - s->port.icount.tx++; - s->port.x_char = 0; - return; - } - - if (uart_circ_empty(xmit) || uart_tx_stopped(&s->port)) - return; - - /* Get length of data pending in circular buffer */ - to_send = uart_circ_chars_pending(xmit); - if (likely(to_send)) { - /* Limit to size of TX FIFO */ - regmap_read(s->regmap, MAX310X_TXFIFOLVL_REG, &txlen); - txlen = MAX310X_FIFO_SIZE - txlen; - to_send = (to_send > txlen) ? txlen : to_send; - - dev_dbg(s->port.dev, "TX Len = %u\n", to_send); - - /* Add data to send */ - s->port.icount.tx += to_send; - while (to_send--) { - regmap_write(s->regmap, MAX310X_THR_REG, - xmit->buf[xmit->tail]); - xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); - }; - } - - if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) - uart_write_wakeup(&s->port); -} - -static irqreturn_t max310x_ist(int irq, void *dev_id) -{ - struct max310x_port *s = (struct max310x_port *)dev_id; - unsigned int ists = 0, lsr = 0, rxlen = 0; - - mutex_lock(&s->max310x_mutex); - - for (;;) { - /* Read IRQ status & RX FIFO level */ - regmap_read(s->regmap, MAX310X_IRQSTS_REG, &ists); - regmap_read(s->regmap, MAX310X_LSR_IRQSTS_REG, &lsr); - regmap_read(s->regmap, MAX310X_RXFIFOLVL_REG, &rxlen); - if (!ists && !(lsr & MAX310X_LSR_RXTO_BIT) && !rxlen) - break; - - dev_dbg(s->port.dev, "IRQ status: 0x%02x\n", ists); - - if (rxlen) - max310x_handle_rx(s, rxlen); - if (ists & MAX310X_IRQ_TX) - max310x_handle_tx(s); - if (ists & MAX310X_IRQ_CTS_BIT) - uart_handle_cts_change(&s->port, - !!(lsr & MAX310X_LSR_CTS_BIT)); - } - - mutex_unlock(&s->max310x_mutex); - - return IRQ_HANDLED; -} - -static void max310x_wq_proc(struct work_struct *ws) -{ - struct max310x_port *s = container_of(ws, struct max310x_port, tx_work); - - mutex_lock(&s->max310x_mutex); - max310x_handle_tx(s); - mutex_unlock(&s->max310x_mutex); -} - -static void max310x_start_tx(struct uart_port *port) -{ - struct max310x_port *s = container_of(port, struct max310x_port, port); - - queue_work(s->wq, &s->tx_work); -} - -static void max310x_stop_tx(struct uart_port *port) -{ - /* Do nothing */ -} - -static void max310x_stop_rx(struct uart_port *port) -{ - /* Do nothing */ -} - -static unsigned int max310x_tx_empty(struct uart_port *port) -{ - unsigned int val = 0; - struct max310x_port *s = container_of(port, struct max310x_port, port); - - mutex_lock(&s->max310x_mutex); - regmap_read(s->regmap, MAX310X_TXFIFOLVL_REG, &val); - mutex_unlock(&s->max310x_mutex); - - return val ? 0 : TIOCSER_TEMT; -} - -static void max310x_enable_ms(struct uart_port *port) -{ - /* Modem status not supported */ -} - -static unsigned int max310x_get_mctrl(struct uart_port *port) -{ - /* DCD and DSR are not wired and CTS/RTS is handled automatically - * so just indicate DSR and CAR asserted - */ - return TIOCM_DSR | TIOCM_CAR; -} - -static void max310x_set_mctrl(struct uart_port *port, unsigned int mctrl) -{ - /* DCD and DSR are not wired and CTS/RTS is hadnled automatically - * so do nothing - */ -} - -static void max310x_break_ctl(struct uart_port *port, int break_state) -{ - struct max310x_port *s = container_of(port, struct max310x_port, port); - - mutex_lock(&s->max310x_mutex); - regmap_update_bits(s->regmap, MAX310X_LCR_REG, - MAX310X_LCR_TXBREAK_BIT, - break_state ? MAX310X_LCR_TXBREAK_BIT : 0); - mutex_unlock(&s->max310x_mutex); -} - -static void max310x_set_termios(struct uart_port *port, - struct ktermios *termios, - struct ktermios *old) -{ - struct max310x_port *s = container_of(port, struct max310x_port, port); - unsigned int lcr, flow = 0; - int baud; - - mutex_lock(&s->max310x_mutex); - - /* Mask termios capabilities we don't support */ - termios->c_cflag &= ~CMSPAR; - termios->c_iflag &= ~IXANY; - - /* Word size */ - switch (termios->c_cflag & CSIZE) { - case CS5: - lcr = MAX310X_LCR_WORD_LEN_5; - break; - case CS6: - lcr = MAX310X_LCR_WORD_LEN_6; - break; - case CS7: - lcr = MAX310X_LCR_WORD_LEN_7; - break; - case CS8: - default: - lcr = MAX310X_LCR_WORD_LEN_8; - break; - } - - /* Parity */ - if (termios->c_cflag & PARENB) { - lcr |= MAX310X_LCR_PARITY_BIT; - if (!(termios->c_cflag & PARODD)) - lcr |= MAX310X_LCR_EVENPARITY_BIT; - } - - /* Stop bits */ - if (termios->c_cflag & CSTOPB) - lcr |= MAX310X_LCR_STOPLEN_BIT; /* 2 stops */ - - /* Update LCR register */ - regmap_write(s->regmap, MAX310X_LCR_REG, lcr); - - /* Set read status mask */ - port->read_status_mask = MAX310X_LSR_RXOVR_BIT; - if (termios->c_iflag & INPCK) - port->read_status_mask |= MAX310X_LSR_RXPAR_BIT | - MAX310X_LSR_FRERR_BIT; - if (termios->c_iflag & (BRKINT | PARMRK)) - port->read_status_mask |= MAX310X_LSR_RXBRK_BIT; - - /* Set status ignore mask */ - port->ignore_status_mask = 0; - if (termios->c_iflag & IGNBRK) - port->ignore_status_mask |= MAX310X_LSR_RXBRK_BIT; - if (!(termios->c_cflag & CREAD)) - port->ignore_status_mask |= MAX310X_LSR_RXPAR_BIT | - MAX310X_LSR_RXOVR_BIT | - MAX310X_LSR_FRERR_BIT | - MAX310X_LSR_RXBRK_BIT; - - /* Configure flow control */ - regmap_write(s->regmap, MAX310X_XON1_REG, termios->c_cc[VSTART]); - regmap_write(s->regmap, MAX310X_XOFF1_REG, termios->c_cc[VSTOP]); - if (termios->c_cflag & CRTSCTS) - flow |= MAX310X_FLOWCTRL_AUTOCTS_BIT | - MAX310X_FLOWCTRL_AUTORTS_BIT; - if (termios->c_iflag & IXON) - flow |= MAX310X_FLOWCTRL_SWFLOW3_BIT | - MAX310X_FLOWCTRL_SWFLOWEN_BIT; - if (termios->c_iflag & IXOFF) - flow |= MAX310X_FLOWCTRL_SWFLOW1_BIT | - MAX310X_FLOWCTRL_SWFLOWEN_BIT; - regmap_write(s->regmap, MAX310X_FLOWCTRL_REG, flow); - - /* Get baud rate generator configuration */ - baud = uart_get_baud_rate(port, termios, old, - port->uartclk / 16 / 0xffff, - port->uartclk / 4); - - /* Setup baudrate generator */ - max310x_set_baud(s, baud); - - /* Update timeout according to new baud rate */ - uart_update_timeout(port, termios->c_cflag, baud); - - mutex_unlock(&s->max310x_mutex); -} - -static int max310x_startup(struct uart_port *port) -{ - unsigned int val, line = port->line; - struct max310x_port *s = container_of(port, struct max310x_port, port); - - if (s->pdata->suspend) - s->pdata->suspend(0); - - mutex_lock(&s->max310x_mutex); - - /* Configure baud rate, 9600 as default */ - max310x_set_baud(s, 9600); - - /* Configure LCR register, 8N1 mode by default */ - val = MAX310X_LCR_WORD_LEN_8; - regmap_write(s->regmap, MAX310X_LCR_REG, val); - - /* Configure MODE1 register */ - regmap_update_bits(s->regmap, MAX310X_MODE1_REG, - MAX310X_MODE1_TRNSCVCTRL_BIT, - (s->pdata->uart_flags[line] & MAX310X_AUTO_DIR_CTRL) - ? MAX310X_MODE1_TRNSCVCTRL_BIT : 0); - - /* Configure MODE2 register */ - val = MAX310X_MODE2_RXEMPTINV_BIT; - if (s->pdata->uart_flags[line] & MAX310X_LOOPBACK) - val |= MAX310X_MODE2_LOOPBACK_BIT; - if (s->pdata->uart_flags[line] & MAX310X_ECHO_SUPRESS) - val |= MAX310X_MODE2_ECHOSUPR_BIT; - - /* Reset FIFOs */ - val |= MAX310X_MODE2_FIFORST_BIT; - regmap_write(s->regmap, MAX310X_MODE2_REG, val); - - /* Configure FIFO trigger level register */ - /* RX FIFO trigger for 16 words, TX FIFO trigger for 64 words */ - val = MAX310X_FIFOTRIGLVL_RX(16) | MAX310X_FIFOTRIGLVL_TX(64); - regmap_write(s->regmap, MAX310X_FIFOTRIGLVL_REG, val); - - /* Configure flow control levels */ - /* Flow control halt level 96, resume level 48 */ - val = MAX310X_FLOWLVL_RES(48) | MAX310X_FLOWLVL_HALT(96); - regmap_write(s->regmap, MAX310X_FLOWLVL_REG, val); - - /* Clear timeout register */ - regmap_write(s->regmap, MAX310X_RXTO_REG, 0); - - /* Configure LSR interrupt enable register */ - /* Enable RX timeout interrupt */ - val = MAX310X_LSR_RXTO_BIT; - regmap_write(s->regmap, MAX310X_LSR_IRQEN_REG, val); - - /* Clear FIFO reset */ - regmap_update_bits(s->regmap, MAX310X_MODE2_REG, - MAX310X_MODE2_FIFORST_BIT, 0); - - /* Clear IRQ status register by reading it */ - regmap_read(s->regmap, MAX310X_IRQSTS_REG, &val); - - /* Configure interrupt enable register */ - /* Enable CTS change interrupt */ - val = MAX310X_IRQ_CTS_BIT; - /* Enable RX, TX interrupts */ - val |= MAX310X_IRQ_RX | MAX310X_IRQ_TX; - regmap_write(s->regmap, MAX310X_IRQEN_REG, val); - - mutex_unlock(&s->max310x_mutex); - - return 0; -} - -static void max310x_shutdown(struct uart_port *port) -{ - struct max310x_port *s = container_of(port, struct max310x_port, port); - - /* Disable all interrupts */ - mutex_lock(&s->max310x_mutex); - regmap_write(s->regmap, MAX310X_IRQEN_REG, 0); - mutex_unlock(&s->max310x_mutex); - - if (s->pdata->suspend) - s->pdata->suspend(1); -} - -static const char *max310x_type(struct uart_port *port) -{ - struct max310x_port *s = container_of(port, struct max310x_port, port); - - return (port->type == PORT_MAX310X) ? s->name : NULL; -} - -static int max310x_request_port(struct uart_port *port) -{ - /* Do nothing */ - return 0; -} - -static void max310x_release_port(struct uart_port *port) -{ - /* Do nothing */ -} - -static void max310x_config_port(struct uart_port *port, int flags) -{ - if (flags & UART_CONFIG_TYPE) - port->type = PORT_MAX310X; -} - -static int max310x_verify_port(struct uart_port *port, struct serial_struct *ser) -{ - if ((ser->type == PORT_UNKNOWN) || (ser->type == PORT_MAX310X)) - return 0; - if (ser->irq == port->irq) - return 0; - - return -EINVAL; -} - -static struct uart_ops max310x_ops = { - .tx_empty = max310x_tx_empty, - .set_mctrl = max310x_set_mctrl, - .get_mctrl = max310x_get_mctrl, - .stop_tx = max310x_stop_tx, - .start_tx = max310x_start_tx, - .stop_rx = max310x_stop_rx, - .enable_ms = max310x_enable_ms, - .break_ctl = max310x_break_ctl, - .startup = max310x_startup, - .shutdown = max310x_shutdown, - .set_termios = max310x_set_termios, - .type = max310x_type, - .request_port = max310x_request_port, - .release_port = max310x_release_port, - .config_port = max310x_config_port, - .verify_port = max310x_verify_port, -}; - -static int max310x_suspend(struct spi_device *spi, pm_message_t state) -{ - int ret; - struct max310x_port *s = dev_get_drvdata(&spi->dev); - - dev_dbg(&spi->dev, "Suspend\n"); - - ret = uart_suspend_port(&s->uart, &s->port); - - mutex_lock(&s->max310x_mutex); - - /* Enable sleep mode */ - regmap_update_bits(s->regmap, MAX310X_MODE1_REG, - MAX310X_MODE1_FORCESLEEP_BIT, - MAX310X_MODE1_FORCESLEEP_BIT); - - mutex_unlock(&s->max310x_mutex); - - if (s->pdata->suspend) - s->pdata->suspend(1); - - return ret; -} - -static int max310x_resume(struct spi_device *spi) -{ - struct max310x_port *s = dev_get_drvdata(&spi->dev); - - dev_dbg(&spi->dev, "Resume\n"); - - if (s->pdata->suspend) - s->pdata->suspend(0); - - mutex_lock(&s->max310x_mutex); - - /* Disable sleep mode */ - regmap_update_bits(s->regmap, MAX310X_MODE1_REG, - MAX310X_MODE1_FORCESLEEP_BIT, - 0); - - max310x_wait_pll(s); - - mutex_unlock(&s->max310x_mutex); - - return uart_resume_port(&s->uart, &s->port); -} - -#ifdef CONFIG_GPIOLIB -static int max310x_gpio_get(struct gpio_chip *chip, unsigned offset) -{ - unsigned int val = 0; - struct max310x_port *s = container_of(chip, struct max310x_port, gpio); - - mutex_lock(&s->max310x_mutex); - regmap_read(s->regmap, MAX310X_GPIODATA_REG, &val); - mutex_unlock(&s->max310x_mutex); - - return !!((val >> 4) & (1 << offset)); -} - -static void max310x_gpio_set(struct gpio_chip *chip, unsigned offset, int value) -{ - struct max310x_port *s = container_of(chip, struct max310x_port, gpio); - - mutex_lock(&s->max310x_mutex); - regmap_update_bits(s->regmap, MAX310X_GPIODATA_REG, 1 << offset, value ? - 1 << offset : 0); - mutex_unlock(&s->max310x_mutex); -} - -static int max310x_gpio_direction_input(struct gpio_chip *chip, unsigned offset) -{ - struct max310x_port *s = container_of(chip, struct max310x_port, gpio); - - mutex_lock(&s->max310x_mutex); - - regmap_update_bits(s->regmap, MAX310X_GPIOCFG_REG, 1 << offset, 0); - - mutex_unlock(&s->max310x_mutex); - - return 0; -} - -static int max310x_gpio_direction_output(struct gpio_chip *chip, - unsigned offset, int value) -{ - struct max310x_port *s = container_of(chip, struct max310x_port, gpio); - - mutex_lock(&s->max310x_mutex); - - regmap_update_bits(s->regmap, MAX310X_GPIOCFG_REG, 1 << offset, - 1 << offset); - regmap_update_bits(s->regmap, MAX310X_GPIODATA_REG, 1 << offset, value ? - 1 << offset : 0); - - mutex_unlock(&s->max310x_mutex); - - return 0; -} -#endif - -/* Generic platform data */ -static struct max310x_pdata generic_plat_data = { - .driver_flags = MAX310X_EXT_CLK, - .uart_flags[0] = MAX310X_ECHO_SUPRESS, - .frequency = 26000000, -}; - -static int __devinit max310x_probe(struct spi_device *spi) -{ - struct max310x_port *s; - struct device *dev = &spi->dev; - int chiptype = spi_get_device_id(spi)->driver_data; - struct max310x_pdata *pdata = dev->platform_data; - unsigned int val = 0; - int ret; - - /* Check for IRQ */ - if (spi->irq <= 0) { - dev_err(dev, "No IRQ specified\n"); - return -ENOTSUPP; - } - - /* Alloc port structure */ - s = devm_kzalloc(dev, sizeof(struct max310x_port), GFP_KERNEL); - if (!s) { - dev_err(dev, "Error allocating port structure\n"); - return -ENOMEM; - } - dev_set_drvdata(dev, s); - - if (!pdata) { - dev_warn(dev, "No platform data supplied, using defaults\n"); - pdata = &generic_plat_data; - } - s->pdata = pdata; - - /* Individual chip settings */ - switch (chiptype) { - case MAX310X_TYPE_MAX3107: - s->name = "MAX3107"; - s->nr_gpio = 4; - s->uart.nr = 1; - s->regcfg.max_register = 0x1f; - break; - case MAX310X_TYPE_MAX3108: - s->name = "MAX3108"; - s->nr_gpio = 4; - s->uart.nr = 1; - s->regcfg.max_register = 0x1e; - break; - default: - dev_err(dev, "Unsupported chip type %i\n", chiptype); - return -ENOTSUPP; - } - - /* Check input frequency */ - if ((pdata->driver_flags & MAX310X_EXT_CLK) && - ((pdata->frequency < 500000) || (pdata->frequency > 35000000))) - goto err_freq; - /* Check frequency for quartz */ - if (!(pdata->driver_flags & MAX310X_EXT_CLK) && - ((pdata->frequency < 1000000) || (pdata->frequency > 4000000))) - goto err_freq; - - mutex_init(&s->max310x_mutex); - - /* Setup SPI bus */ - spi->mode = SPI_MODE_0; - spi->bits_per_word = 8; - spi->max_speed_hz = 26000000; - spi_setup(spi); - - /* Setup regmap */ - s->regcfg.reg_bits = 8; - s->regcfg.val_bits = 8; - s->regcfg.read_flag_mask = 0x00; - s->regcfg.write_flag_mask = 0x80; - s->regcfg.cache_type = REGCACHE_RBTREE; - s->regcfg.writeable_reg = max3107_8_reg_writeable; - s->regcfg.volatile_reg = max310x_reg_volatile; - s->regcfg.precious_reg = max310x_reg_precious; - s->regmap = devm_regmap_init_spi(spi, &s->regcfg); - if (IS_ERR(s->regmap)) { - ret = PTR_ERR(s->regmap); - dev_err(dev, "Failed to initialize register map\n"); - goto err_out; - } - - /* Reset chip & check SPI function */ - ret = regmap_write(s->regmap, MAX310X_MODE2_REG, MAX310X_MODE2_RST_BIT); - if (ret) { - dev_err(dev, "SPI transfer failed\n"); - goto err_out; - } - /* Clear chip reset */ - regmap_write(s->regmap, MAX310X_MODE2_REG, 0); - - switch (chiptype) { - case MAX310X_TYPE_MAX3107: - /* Check REV ID to ensure we are talking to what we expect */ - regmap_read(s->regmap, MAX3107_REVID_REG, &val); - if (((val & MAX3107_REV_MASK) != MAX3107_REV_ID)) { - dev_err(dev, "%s ID 0x%02x does not match\n", - s->name, val); - ret = -ENODEV; - goto err_out; - } - break; - case MAX310X_TYPE_MAX3108: - /* MAX3108 have not REV ID register, we just check default value - * from clocksource register to make sure everything works. - */ - regmap_read(s->regmap, MAX310X_CLKSRC_REG, &val); - if (val != (MAX310X_CLKSRC_EXTCLK_BIT | - MAX310X_CLKSRC_PLLBYP_BIT)) { - dev_err(dev, "%s not present\n", s->name); - ret = -ENODEV; - goto err_out; - } - break; - } - - /* Board specific configure */ - if (pdata->init) - pdata->init(); - if (pdata->suspend) - pdata->suspend(0); - - /* Calculate referecne clock */ - s->uartclk = max310x_set_ref_clk(s); - - /* Disable all interrupts */ - regmap_write(s->regmap, MAX310X_IRQEN_REG, 0); - - /* Setup MODE1 register */ - val = MAX310X_MODE1_IRQSEL_BIT; /* Enable IRQ pin */ - if (pdata->driver_flags & MAX310X_AUTOSLEEP) - val = MAX310X_MODE1_AUTOSLEEP_BIT; - regmap_write(s->regmap, MAX310X_MODE1_REG, val); - - /* Setup interrupt */ - ret = devm_request_threaded_irq(dev, spi->irq, NULL, max310x_ist, - IRQF_TRIGGER_FALLING | IRQF_ONESHOT, - dev_name(dev), s); - if (ret) { - dev_err(dev, "Unable to reguest IRQ %i\n", spi->irq); - goto err_out; - } - - /* Register UART driver */ - s->uart.owner = THIS_MODULE; - s->uart.driver_name = dev_name(dev); - s->uart.dev_name = "ttyMAX"; - s->uart.major = MAX310X_MAJOR; - s->uart.minor = MAX310X_MINOR; - ret = uart_register_driver(&s->uart); - if (ret) { - dev_err(dev, "Registering UART driver failed\n"); - goto err_out; - } - - /* Initialize workqueue for start TX */ - s->wq = create_freezable_workqueue(dev_name(dev)); - INIT_WORK(&s->tx_work, max310x_wq_proc); - - /* Initialize UART port data */ - s->port.line = 0; - s->port.dev = dev; - s->port.irq = spi->irq; - s->port.type = PORT_MAX310X; - s->port.fifosize = MAX310X_FIFO_SIZE; - s->port.flags = UPF_SKIP_TEST | UPF_FIXED_TYPE; - s->port.iotype = UPIO_PORT; - s->port.membase = (void __iomem *)0xffffffff; /* Bogus value */ - s->port.uartclk = s->uartclk; - s->port.ops = &max310x_ops; - uart_add_one_port(&s->uart, &s->port); - -#ifdef CONFIG_GPIOLIB - /* Setup GPIO cotroller */ - if (pdata->gpio_base) { - s->gpio.owner = THIS_MODULE; - s->gpio.dev = dev; - s->gpio.label = dev_name(dev); - s->gpio.direction_input = max310x_gpio_direction_input; - s->gpio.get = max310x_gpio_get; - s->gpio.direction_output= max310x_gpio_direction_output; - s->gpio.set = max310x_gpio_set; - s->gpio.base = pdata->gpio_base; - s->gpio.ngpio = s->nr_gpio; - if (gpiochip_add(&s->gpio)) { - /* Indicate that we should not call gpiochip_remove */ - s->gpio.base = 0; - } - } else - dev_info(dev, "GPIO support not enabled\n"); -#endif - - /* Go to suspend mode */ - if (pdata->suspend) - pdata->suspend(1); - - return 0; - -err_freq: - dev_err(dev, "Frequency parameter incorrect\n"); - ret = -EINVAL; - -err_out: - dev_set_drvdata(dev, NULL); - - return ret; -} - -static int __devexit max310x_remove(struct spi_device *spi) -{ - struct device *dev = &spi->dev; - struct max310x_port *s = dev_get_drvdata(dev); - int ret = 0; - - dev_dbg(dev, "Removing port\n"); - - devm_free_irq(dev, s->port.irq, s); - - destroy_workqueue(s->wq); - - uart_remove_one_port(&s->uart, &s->port); - - uart_unregister_driver(&s->uart); - -#ifdef CONFIG_GPIOLIB - if (s->pdata->gpio_base) { - ret = gpiochip_remove(&s->gpio); - if (ret) - dev_err(dev, "Failed to remove gpio chip: %d\n", ret); - } -#endif - - dev_set_drvdata(dev, NULL); - - if (s->pdata->suspend) - s->pdata->suspend(1); - if (s->pdata->exit) - s->pdata->exit(); - - return ret; -} - -static const struct spi_device_id max310x_id_table[] = { - { "max3107", MAX310X_TYPE_MAX3107 }, - { "max3108", MAX310X_TYPE_MAX3108 }, -}; -MODULE_DEVICE_TABLE(spi, max310x_id_table); - -static struct spi_driver max310x_driver = { - .driver = { - .name = "max310x", - .owner = THIS_MODULE, - }, - .probe = max310x_probe, - .remove = __devexit_p(max310x_remove), - .suspend = max310x_suspend, - .resume = max310x_resume, - .id_table = max310x_id_table, -}; -module_spi_driver(max310x_driver); - -MODULE_LICENSE("GPL v2"); -MODULE_AUTHOR("Alexander Shiyan "); -MODULE_DESCRIPTION("MAX310X serial driver"); diff --git a/trunk/drivers/tty/serial/mpc52xx_uart.c b/trunk/drivers/tty/serial/mpc52xx_uart.c index f19d04ed8586..bedac0d4c9ce 100644 --- a/trunk/drivers/tty/serial/mpc52xx_uart.c +++ b/trunk/drivers/tty/serial/mpc52xx_uart.c @@ -775,15 +775,11 @@ mpc52xx_uart_set_termios(struct uart_port *port, struct ktermios *new, } if (new->c_cflag & PARENB) { - if (new->c_cflag & CMSPAR) - mr1 |= MPC52xx_PSC_MODE_PARFORCE; - - /* With CMSPAR, PARODD also means high parity (same as termios) */ mr1 |= (new->c_cflag & PARODD) ? MPC52xx_PSC_MODE_PARODD : MPC52xx_PSC_MODE_PAREVEN; - } else { + } else mr1 |= MPC52xx_PSC_MODE_PARNONE; - } + mr2 = 0; diff --git a/trunk/drivers/tty/serial/msm_serial.c b/trunk/drivers/tty/serial/msm_serial.c index 033e0bc9ebab..8131e2c28015 100644 --- a/trunk/drivers/tty/serial/msm_serial.c +++ b/trunk/drivers/tty/serial/msm_serial.c @@ -896,7 +896,7 @@ static int __init msm_serial_probe(struct platform_device *pdev) return PTR_ERR(msm_port->clk); if (msm_port->is_uartdm) - clk_set_rate(msm_port->clk, 1843200); + clk_set_rate(msm_port->clk, 7372800); port->uartclk = clk_get_rate(msm_port->clk); printk(KERN_INFO "uartclk = %d\n", port->uartclk); diff --git a/trunk/drivers/tty/serial/msm_smd_tty.c b/trunk/drivers/tty/serial/msm_smd_tty.c index 925d1fa153db..b25e6ee71443 100644 --- a/trunk/drivers/tty/serial/msm_smd_tty.c +++ b/trunk/drivers/tty/serial/msm_smd_tty.c @@ -223,11 +223,9 @@ static int __init smd_tty_init(void) return ret; for (i = 0; i < smd_tty_channels_len; i++) { - struct tty_port *port = &smd_tty[smd_tty_channels[i].id].port; - tty_port_init(port); - port->ops = &smd_tty_port_ops; - tty_port_register_device(port, smd_tty_driver, - smd_tty_channels[i].id, NULL); + tty_port_init(&smd_tty[smd_tty_channels[i].id].port); + smd_tty[smd_tty_channels[i].id].port.ops = &smd_tty_port_ops; + tty_register_device(smd_tty_driver, smd_tty_channels[i].id, 0); } return 0; diff --git a/trunk/drivers/tty/serial/mxs-auart.c b/trunk/drivers/tty/serial/mxs-auart.c index 6db3baa39a97..2e341b81ff89 100644 --- a/trunk/drivers/tty/serial/mxs-auart.c +++ b/trunk/drivers/tty/serial/mxs-auart.c @@ -73,7 +73,6 @@ #define AUART_CTRL0_CLKGATE (1 << 30) #define AUART_CTRL2_CTSEN (1 << 15) -#define AUART_CTRL2_RTSEN (1 << 14) #define AUART_CTRL2_RTS (1 << 11) #define AUART_CTRL2_RXE (1 << 9) #define AUART_CTRL2_TXE (1 << 8) @@ -260,12 +259,9 @@ static void mxs_auart_set_mctrl(struct uart_port *u, unsigned mctrl) u32 ctrl = readl(u->membase + AUART_CTRL2); - ctrl &= ~AUART_CTRL2_RTSEN; - if (mctrl & TIOCM_RTS) { - if (tty_port_cts_enabled(&u->state->port)) - ctrl |= AUART_CTRL2_RTSEN; - } - + ctrl &= ~AUART_CTRL2_RTS; + if (mctrl & TIOCM_RTS) + ctrl |= AUART_CTRL2_RTS; s->ctrl = mctrl; writel(ctrl, u->membase + AUART_CTRL2); } @@ -363,9 +359,9 @@ static void mxs_auart_settermios(struct uart_port *u, /* figure out the hardware flow control settings */ if (cflag & CRTSCTS) - ctrl2 |= AUART_CTRL2_CTSEN | AUART_CTRL2_RTSEN; + ctrl2 |= AUART_CTRL2_CTSEN; else - ctrl2 &= ~(AUART_CTRL2_CTSEN | AUART_CTRL2_RTSEN); + ctrl2 &= ~AUART_CTRL2_CTSEN; /* set baud rate */ baud = uart_get_baud_rate(u, termios, old, 0, u->uartclk); @@ -457,11 +453,11 @@ static void mxs_auart_shutdown(struct uart_port *u) writel(AUART_CTRL2_UARTEN, u->membase + AUART_CTRL2_CLR); + writel(AUART_CTRL0_CLKGATE, u->membase + AUART_CTRL0_SET); + writel(AUART_INTR_RXIEN | AUART_INTR_RTIEN | AUART_INTR_CTSMIEN, u->membase + AUART_INTR_CLR); - writel(AUART_CTRL0_CLKGATE, u->membase + AUART_CTRL0_SET); - clk_disable_unprepare(s->clk); } @@ -781,7 +777,6 @@ static int __devinit mxs_auart_probe(struct platform_device *pdev) auart_port[pdev->id] = NULL; free_irq(s->irq, s); out_free_clk: - put_device(s->dev); clk_put(s->clk); out_free: kfree(s); @@ -797,7 +792,6 @@ static int __devexit mxs_auart_remove(struct platform_device *pdev) auart_port[pdev->id] = NULL; - put_device(s->dev); clk_put(s->clk); free_irq(s->irq, s); kfree(s); diff --git a/trunk/drivers/tty/serial/of_serial.c b/trunk/drivers/tty/serial/of_serial.c index df443b908ca3..34e71874a892 100644 --- a/trunk/drivers/tty/serial/of_serial.c +++ b/trunk/drivers/tty/serial/of_serial.c @@ -105,10 +105,6 @@ static int __devinit of_platform_serial_setup(struct platform_device *ofdev, port->uartclk = clk; port->flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF | UPF_IOREMAP | UPF_FIXED_PORT | UPF_FIXED_TYPE; - - if (of_find_property(np, "no-loopback-test", NULL)) - port->flags |= UPF_SKIP_TEST; - port->dev = &ofdev->dev; if (type == PORT_TEGRA) @@ -148,15 +144,8 @@ static int __devinit of_platform_serial_probe(struct platform_device *ofdev) switch (port_type) { #ifdef CONFIG_SERIAL_8250 case PORT_8250 ... PORT_MAX_8250: - { - /* For now the of bindings don't support the extra - 8250 specific bits */ - struct uart_8250_port port8250; - memset(&port8250, 0, sizeof(port8250)); - port8250.port = port; - ret = serial8250_register_8250_port(&port8250); + ret = serial8250_register_port(&port); break; - } #endif #ifdef CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL case PORT_NWPSERIAL: diff --git a/trunk/drivers/tty/serial/omap-serial.c b/trunk/drivers/tty/serial/omap-serial.c index ccc2f35adff1..d3cda0cb2df0 100644 --- a/trunk/drivers/tty/serial/omap-serial.c +++ b/trunk/drivers/tty/serial/omap-serial.c @@ -32,16 +32,16 @@ #include #include #include -#include #include +#include #include #include #include #include #include -#include -#include +#include +#include #include #define UART_BUILD_REVISION(x, y) (((x) << 8) | (y)) @@ -57,8 +57,8 @@ #define OMAP_UART_SCR_RX_TRIG_GRANU1_MASK (1 << 7) /* FCR register bitmasks */ +#define OMAP_UART_FCR_RX_FIFO_TRIG_SHIFT 6 #define OMAP_UART_FCR_RX_FIFO_TRIG_MASK (0x3 << 6) -#define OMAP_UART_FCR_TX_FIFO_TRIG_MASK (0x3 << 4) /* MVR register bitmasks */ #define OMAP_UART_MVR_SCHEME_SHIFT 30 @@ -71,52 +71,12 @@ #define OMAP_UART_MVR_MAJ_SHIFT 8 #define OMAP_UART_MVR_MIN_MASK 0x3f -struct uart_omap_port { - struct uart_port port; - struct uart_omap_dma uart_dma; - struct device *dev; - - unsigned char ier; - unsigned char lcr; - unsigned char mcr; - unsigned char fcr; - unsigned char efr; - unsigned char dll; - unsigned char dlh; - unsigned char mdr1; - unsigned char scr; - - int use_dma; - /* - * Some bits in registers are cleared on a read, so they must - * be saved whenever the register is read but the bits will not - * be immediately processed. - */ - unsigned int lsr_break_flag; - unsigned char msr_saved_flags; - char name[20]; - unsigned long port_activity; - u32 context_loss_cnt; - u32 errata; - u8 wakeups_enabled; - unsigned int irq_pending:1; - - int DTR_gpio; - int DTR_inverted; - int DTR_active; - - struct pm_qos_request pm_qos_request; - u32 latency; - u32 calc_latency; - struct work_struct qos_work; - struct pinctrl *pins; -}; - -#define to_uart_omap_port(p) ((container_of((p), struct uart_omap_port, port))) - static struct uart_omap_port *ui[OMAP_MAX_HSUART_PORTS]; /* Forward declaration of functions */ +static void uart_tx_dma_callback(int lch, u16 ch_status, void *data); +static void serial_omap_rxdma_poll(unsigned long uart_no); +static int serial_omap_start_rxdma(struct uart_omap_port *up); static void serial_omap_mdr1_errataset(struct uart_omap_port *up, u8 mdr1); static struct workqueue_struct *serial_omap_uart_wq; @@ -141,46 +101,6 @@ static inline void serial_omap_clear_fifos(struct uart_omap_port *up) serial_out(up, UART_FCR, 0); } -static int serial_omap_get_context_loss_count(struct uart_omap_port *up) -{ - struct omap_uart_port_info *pdata = up->dev->platform_data; - - if (!pdata || !pdata->get_context_loss_count) - return 0; - - return pdata->get_context_loss_count(up->dev); -} - -static void serial_omap_set_forceidle(struct uart_omap_port *up) -{ - struct omap_uart_port_info *pdata = up->dev->platform_data; - - if (!pdata || !pdata->set_forceidle) - return; - - pdata->set_forceidle(up->dev); -} - -static void serial_omap_set_noidle(struct uart_omap_port *up) -{ - struct omap_uart_port_info *pdata = up->dev->platform_data; - - if (!pdata || !pdata->set_noidle) - return; - - pdata->set_noidle(up->dev); -} - -static void serial_omap_enable_wakeup(struct uart_omap_port *up, bool enable) -{ - struct omap_uart_port_info *pdata = up->dev->platform_data; - - if (!pdata || !pdata->enable_wakeup) - return; - - pdata->enable_wakeup(up->dev, enable); -} - /* * serial_omap_get_divisor - calculate divisor value * @port: uart port info @@ -206,55 +126,151 @@ serial_omap_get_divisor(struct uart_port *port, unsigned int baud) return port->uartclk/(baud * divisor); } +static void serial_omap_stop_rxdma(struct uart_omap_port *up) +{ + if (up->uart_dma.rx_dma_used) { + del_timer(&up->uart_dma.rx_timer); + omap_stop_dma(up->uart_dma.rx_dma_channel); + omap_free_dma(up->uart_dma.rx_dma_channel); + up->uart_dma.rx_dma_channel = OMAP_UART_DMA_CH_FREE; + up->uart_dma.rx_dma_used = false; + pm_runtime_mark_last_busy(&up->pdev->dev); + pm_runtime_put_autosuspend(&up->pdev->dev); + } +} + static void serial_omap_enable_ms(struct uart_port *port) { - struct uart_omap_port *up = to_uart_omap_port(port); + struct uart_omap_port *up = (struct uart_omap_port *)port; dev_dbg(up->port.dev, "serial_omap_enable_ms+%d\n", up->port.line); - pm_runtime_get_sync(up->dev); + pm_runtime_get_sync(&up->pdev->dev); up->ier |= UART_IER_MSI; serial_out(up, UART_IER, up->ier); - pm_runtime_mark_last_busy(up->dev); - pm_runtime_put_autosuspend(up->dev); + pm_runtime_put(&up->pdev->dev); } static void serial_omap_stop_tx(struct uart_port *port) { - struct uart_omap_port *up = to_uart_omap_port(port); + struct uart_omap_port *up = (struct uart_omap_port *)port; + struct omap_uart_port_info *pdata = up->pdev->dev.platform_data; + + if (up->use_dma && + up->uart_dma.tx_dma_channel != OMAP_UART_DMA_CH_FREE) { + /* + * Check if dma is still active. If yes do nothing, + * return. Else stop dma + */ + if (omap_get_dma_active_status(up->uart_dma.tx_dma_channel)) + return; + omap_stop_dma(up->uart_dma.tx_dma_channel); + omap_free_dma(up->uart_dma.tx_dma_channel); + up->uart_dma.tx_dma_channel = OMAP_UART_DMA_CH_FREE; + pm_runtime_mark_last_busy(&up->pdev->dev); + pm_runtime_put_autosuspend(&up->pdev->dev); + } - pm_runtime_get_sync(up->dev); + pm_runtime_get_sync(&up->pdev->dev); if (up->ier & UART_IER_THRI) { up->ier &= ~UART_IER_THRI; serial_out(up, UART_IER, up->ier); } - serial_omap_set_forceidle(up); + if (!up->use_dma && pdata && pdata->set_forceidle) + pdata->set_forceidle(up->pdev); - pm_runtime_mark_last_busy(up->dev); - pm_runtime_put_autosuspend(up->dev); + pm_runtime_mark_last_busy(&up->pdev->dev); + pm_runtime_put_autosuspend(&up->pdev->dev); } static void serial_omap_stop_rx(struct uart_port *port) { - struct uart_omap_port *up = to_uart_omap_port(port); + struct uart_omap_port *up = (struct uart_omap_port *)port; - pm_runtime_get_sync(up->dev); + pm_runtime_get_sync(&up->pdev->dev); + if (up->use_dma) + serial_omap_stop_rxdma(up); up->ier &= ~UART_IER_RLSI; up->port.read_status_mask &= ~UART_LSR_DR; serial_out(up, UART_IER, up->ier); - pm_runtime_mark_last_busy(up->dev); - pm_runtime_put_autosuspend(up->dev); + pm_runtime_mark_last_busy(&up->pdev->dev); + pm_runtime_put_autosuspend(&up->pdev->dev); +} + +static inline void receive_chars(struct uart_omap_port *up, + unsigned int *status) +{ + struct tty_struct *tty = up->port.state->port.tty; + unsigned int flag, lsr = *status; + unsigned char ch = 0; + int max_count = 256; + + do { + if (likely(lsr & UART_LSR_DR)) + ch = serial_in(up, UART_RX); + flag = TTY_NORMAL; + up->port.icount.rx++; + + if (unlikely(lsr & UART_LSR_BRK_ERROR_BITS)) { + /* + * For statistics only + */ + if (lsr & UART_LSR_BI) { + lsr &= ~(UART_LSR_FE | UART_LSR_PE); + up->port.icount.brk++; + /* + * We do the SysRQ and SAK checking + * here because otherwise the break + * may get masked by ignore_status_mask + * or read_status_mask. + */ + if (uart_handle_break(&up->port)) + goto ignore_char; + } else if (lsr & UART_LSR_PE) { + up->port.icount.parity++; + } else if (lsr & UART_LSR_FE) { + up->port.icount.frame++; + } + + if (lsr & UART_LSR_OE) + up->port.icount.overrun++; + + /* + * Mask off conditions which should be ignored. + */ + lsr &= up->port.read_status_mask; + +#ifdef CONFIG_SERIAL_OMAP_CONSOLE + if (up->port.line == up->port.cons->index) { + /* Recover the break flag from console xmit */ + lsr |= up->lsr_break_flag; + } +#endif + if (lsr & UART_LSR_BI) + flag = TTY_BREAK; + else if (lsr & UART_LSR_PE) + flag = TTY_PARITY; + else if (lsr & UART_LSR_FE) + flag = TTY_FRAME; + } + + if (uart_handle_sysrq_char(&up->port, ch)) + goto ignore_char; + uart_insert_char(&up->port, lsr, UART_LSR_OE, ch, flag); +ignore_char: + lsr = serial_in(up, UART_LSR); + } while ((lsr & (UART_LSR_DR | UART_LSR_BI)) && (max_count-- > 0)); + spin_unlock(&up->port.lock); + tty_flip_buffer_push(tty); + spin_lock(&up->port.lock); } -static void transmit_chars(struct uart_omap_port *up, unsigned int lsr) +static void transmit_chars(struct uart_omap_port *up) { struct circ_buf *xmit = &up->port.state->xmit; int count; - if (!(lsr & UART_LSR_THRE)) - return; - if (up->port.x_char) { serial_out(up, UART_TX, up->port.x_char); up->port.icount.tx++; @@ -274,11 +290,8 @@ static void transmit_chars(struct uart_omap_port *up, unsigned int lsr) break; } while (--count > 0); - if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) { - spin_unlock(&up->port.lock); + if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) uart_write_wakeup(&up->port); - spin_lock(&up->port.lock); - } if (uart_circ_empty(xmit)) serial_omap_stop_tx(&up->port); @@ -294,13 +307,70 @@ static inline void serial_omap_enable_ier_thri(struct uart_omap_port *up) static void serial_omap_start_tx(struct uart_port *port) { - struct uart_omap_port *up = to_uart_omap_port(port); + struct uart_omap_port *up = (struct uart_omap_port *)port; + struct omap_uart_port_info *pdata = up->pdev->dev.platform_data; + struct circ_buf *xmit; + unsigned int start; + int ret = 0; + + if (!up->use_dma) { + pm_runtime_get_sync(&up->pdev->dev); + serial_omap_enable_ier_thri(up); + if (pdata && pdata->set_noidle) + pdata->set_noidle(up->pdev); + pm_runtime_mark_last_busy(&up->pdev->dev); + pm_runtime_put_autosuspend(&up->pdev->dev); + return; + } + + if (up->uart_dma.tx_dma_used) + return; + + xmit = &up->port.state->xmit; + + if (up->uart_dma.tx_dma_channel == OMAP_UART_DMA_CH_FREE) { + pm_runtime_get_sync(&up->pdev->dev); + ret = omap_request_dma(up->uart_dma.uart_dma_tx, + "UART Tx DMA", + (void *)uart_tx_dma_callback, up, + &(up->uart_dma.tx_dma_channel)); + + if (ret < 0) { + serial_omap_enable_ier_thri(up); + return; + } + } + spin_lock(&(up->uart_dma.tx_lock)); + up->uart_dma.tx_dma_used = true; + spin_unlock(&(up->uart_dma.tx_lock)); - pm_runtime_get_sync(up->dev); - serial_omap_enable_ier_thri(up); - serial_omap_set_noidle(up); - pm_runtime_mark_last_busy(up->dev); - pm_runtime_put_autosuspend(up->dev); + start = up->uart_dma.tx_buf_dma_phys + + (xmit->tail & (UART_XMIT_SIZE - 1)); + + up->uart_dma.tx_buf_size = uart_circ_chars_pending(xmit); + /* + * It is a circular buffer. See if the buffer has wounded back. + * If yes it will have to be transferred in two separate dma + * transfers + */ + if (start + up->uart_dma.tx_buf_size >= + up->uart_dma.tx_buf_dma_phys + UART_XMIT_SIZE) + up->uart_dma.tx_buf_size = + (up->uart_dma.tx_buf_dma_phys + + UART_XMIT_SIZE) - start; + + omap_set_dma_dest_params(up->uart_dma.tx_dma_channel, 0, + OMAP_DMA_AMODE_CONSTANT, + up->uart_dma.uart_base, 0, 0); + omap_set_dma_src_params(up->uart_dma.tx_dma_channel, 0, + OMAP_DMA_AMODE_POST_INC, start, 0, 0); + omap_set_dma_transfer_params(up->uart_dma.tx_dma_channel, + OMAP_DMA_DATA_TYPE_S8, + up->uart_dma.tx_buf_size, 1, + OMAP_DMA_SYNC_ELEMENT, + up->uart_dma.uart_dma_tx, 0); + /* FIXME: Cache maintenance needed here? */ + omap_start_dma(up->uart_dma.tx_dma_channel); } static unsigned int check_modem_status(struct uart_omap_port *up) @@ -331,162 +401,76 @@ static unsigned int check_modem_status(struct uart_omap_port *up) return status; } -static void serial_omap_rlsi(struct uart_omap_port *up, unsigned int lsr) -{ - unsigned int flag; - unsigned char ch = 0; - - if (likely(lsr & UART_LSR_DR)) - ch = serial_in(up, UART_RX); - - up->port.icount.rx++; - flag = TTY_NORMAL; - - if (lsr & UART_LSR_BI) { - flag = TTY_BREAK; - lsr &= ~(UART_LSR_FE | UART_LSR_PE); - up->port.icount.brk++; - /* - * We do the SysRQ and SAK checking - * here because otherwise the break - * may get masked by ignore_status_mask - * or read_status_mask. - */ - if (uart_handle_break(&up->port)) - return; - - } - - if (lsr & UART_LSR_PE) { - flag = TTY_PARITY; - up->port.icount.parity++; - } - - if (lsr & UART_LSR_FE) { - flag = TTY_FRAME; - up->port.icount.frame++; - } - - if (lsr & UART_LSR_OE) - up->port.icount.overrun++; - -#ifdef CONFIG_SERIAL_OMAP_CONSOLE - if (up->port.line == up->port.cons->index) { - /* Recover the break flag from console xmit */ - lsr |= up->lsr_break_flag; - } -#endif - uart_insert_char(&up->port, lsr, UART_LSR_OE, 0, flag); -} - -static void serial_omap_rdi(struct uart_omap_port *up, unsigned int lsr) -{ - unsigned char ch = 0; - unsigned int flag; - - if (!(lsr & UART_LSR_DR)) - return; - - ch = serial_in(up, UART_RX); - flag = TTY_NORMAL; - up->port.icount.rx++; - - if (uart_handle_sysrq_char(&up->port, ch)) - return; - - uart_insert_char(&up->port, lsr, UART_LSR_OE, ch, flag); -} - /** * serial_omap_irq() - This handles the interrupt from one port * @irq: uart port irq number * @dev_id: uart port info */ -static irqreturn_t serial_omap_irq(int irq, void *dev_id) +static inline irqreturn_t serial_omap_irq(int irq, void *dev_id) { struct uart_omap_port *up = dev_id; - struct tty_struct *tty = up->port.state->port.tty; unsigned int iir, lsr; - unsigned int type; - irqreturn_t ret = IRQ_NONE; - int max_count = 256; - - spin_lock(&up->port.lock); - pm_runtime_get_sync(up->dev); - - do { - iir = serial_in(up, UART_IIR); - if (iir & UART_IIR_NO_INT) - break; - - ret = IRQ_HANDLED; - lsr = serial_in(up, UART_LSR); + unsigned long flags; - /* extract IRQ type from IIR register */ - type = iir & 0x3e; + pm_runtime_get_sync(&up->pdev->dev); + iir = serial_in(up, UART_IIR); + if (iir & UART_IIR_NO_INT) { + pm_runtime_mark_last_busy(&up->pdev->dev); + pm_runtime_put_autosuspend(&up->pdev->dev); + return IRQ_NONE; + } - switch (type) { - case UART_IIR_MSI: - check_modem_status(up); - break; - case UART_IIR_THRI: - transmit_chars(up, lsr); - break; - case UART_IIR_RX_TIMEOUT: - /* FALLTHROUGH */ - case UART_IIR_RDI: - serial_omap_rdi(up, lsr); - break; - case UART_IIR_RLSI: - serial_omap_rlsi(up, lsr); - break; - case UART_IIR_CTS_RTS_DSR: - /* simply try again */ - break; - case UART_IIR_XOFF: - /* FALLTHROUGH */ - default: - break; + spin_lock_irqsave(&up->port.lock, flags); + lsr = serial_in(up, UART_LSR); + if (iir & UART_IIR_RLSI) { + if (!up->use_dma) { + if (lsr & UART_LSR_DR) + receive_chars(up, &lsr); + } else { + up->ier &= ~(UART_IER_RDI | UART_IER_RLSI); + serial_out(up, UART_IER, up->ier); + if ((serial_omap_start_rxdma(up) != 0) && + (lsr & UART_LSR_DR)) + receive_chars(up, &lsr); } - } while (!(iir & UART_IIR_NO_INT) && max_count--); + } - spin_unlock(&up->port.lock); + check_modem_status(up); + if ((lsr & UART_LSR_THRE) && (iir & UART_IIR_THRI)) + transmit_chars(up); - tty_flip_buffer_push(tty); + spin_unlock_irqrestore(&up->port.lock, flags); + pm_runtime_mark_last_busy(&up->pdev->dev); + pm_runtime_put_autosuspend(&up->pdev->dev); - pm_runtime_mark_last_busy(up->dev); - pm_runtime_put_autosuspend(up->dev); up->port_activity = jiffies; - - return ret; + return IRQ_HANDLED; } static unsigned int serial_omap_tx_empty(struct uart_port *port) { - struct uart_omap_port *up = to_uart_omap_port(port); + struct uart_omap_port *up = (struct uart_omap_port *)port; unsigned long flags = 0; unsigned int ret = 0; - pm_runtime_get_sync(up->dev); + pm_runtime_get_sync(&up->pdev->dev); dev_dbg(up->port.dev, "serial_omap_tx_empty+%d\n", up->port.line); spin_lock_irqsave(&up->port.lock, flags); ret = serial_in(up, UART_LSR) & UART_LSR_TEMT ? TIOCSER_TEMT : 0; spin_unlock_irqrestore(&up->port.lock, flags); - pm_runtime_mark_last_busy(up->dev); - pm_runtime_put_autosuspend(up->dev); + pm_runtime_put(&up->pdev->dev); return ret; } static unsigned int serial_omap_get_mctrl(struct uart_port *port) { - struct uart_omap_port *up = to_uart_omap_port(port); + struct uart_omap_port *up = (struct uart_omap_port *)port; unsigned int status; unsigned int ret = 0; - pm_runtime_get_sync(up->dev); + pm_runtime_get_sync(&up->pdev->dev); status = check_modem_status(up); - pm_runtime_mark_last_busy(up->dev); - pm_runtime_put_autosuspend(up->dev); + pm_runtime_put(&up->pdev->dev); dev_dbg(up->port.dev, "serial_omap_get_mctrl+%d\n", up->port.line); @@ -503,7 +487,7 @@ static unsigned int serial_omap_get_mctrl(struct uart_port *port) static void serial_omap_set_mctrl(struct uart_port *port, unsigned int mctrl) { - struct uart_omap_port *up = to_uart_omap_port(port); + struct uart_omap_port *up = (struct uart_omap_port *)port; unsigned char mcr = 0; dev_dbg(up->port.dev, "serial_omap_set_mctrl+%d\n", up->port.line); @@ -518,31 +502,20 @@ static void serial_omap_set_mctrl(struct uart_port *port, unsigned int mctrl) if (mctrl & TIOCM_LOOP) mcr |= UART_MCR_LOOP; - pm_runtime_get_sync(up->dev); + pm_runtime_get_sync(&up->pdev->dev); up->mcr = serial_in(up, UART_MCR); up->mcr |= mcr; serial_out(up, UART_MCR, up->mcr); - pm_runtime_mark_last_busy(up->dev); - pm_runtime_put_autosuspend(up->dev); - - if (gpio_is_valid(up->DTR_gpio) && - !!(mctrl & TIOCM_DTR) != up->DTR_active) { - up->DTR_active = !up->DTR_active; - if (gpio_cansleep(up->DTR_gpio)) - schedule_work(&up->qos_work); - else - gpio_set_value(up->DTR_gpio, - up->DTR_active != up->DTR_inverted); - } + pm_runtime_put(&up->pdev->dev); } static void serial_omap_break_ctl(struct uart_port *port, int break_state) { - struct uart_omap_port *up = to_uart_omap_port(port); + struct uart_omap_port *up = (struct uart_omap_port *)port; unsigned long flags = 0; dev_dbg(up->port.dev, "serial_omap_break_ctl+%d\n", up->port.line); - pm_runtime_get_sync(up->dev); + pm_runtime_get_sync(&up->pdev->dev); spin_lock_irqsave(&up->port.lock, flags); if (break_state == -1) up->lcr |= UART_LCR_SBC; @@ -550,13 +523,12 @@ static void serial_omap_break_ctl(struct uart_port *port, int break_state) up->lcr &= ~UART_LCR_SBC; serial_out(up, UART_LCR, up->lcr); spin_unlock_irqrestore(&up->port.lock, flags); - pm_runtime_mark_last_busy(up->dev); - pm_runtime_put_autosuspend(up->dev); + pm_runtime_put(&up->pdev->dev); } static int serial_omap_startup(struct uart_port *port) { - struct uart_omap_port *up = to_uart_omap_port(port); + struct uart_omap_port *up = (struct uart_omap_port *)port; unsigned long flags = 0; int retval; @@ -570,7 +542,7 @@ static int serial_omap_startup(struct uart_port *port) dev_dbg(up->port.dev, "serial_omap_startup+%d\n", up->port.line); - pm_runtime_get_sync(up->dev); + pm_runtime_get_sync(&up->pdev->dev); /* * Clear the FIFO buffers and disable them. * (they will be reenabled in set_termios()) @@ -601,6 +573,20 @@ static int serial_omap_startup(struct uart_port *port) spin_unlock_irqrestore(&up->port.lock, flags); up->msr_saved_flags = 0; + if (up->use_dma) { + free_page((unsigned long)up->port.state->xmit.buf); + up->port.state->xmit.buf = dma_alloc_coherent(NULL, + UART_XMIT_SIZE, + (dma_addr_t *)&(up->uart_dma.tx_buf_dma_phys), + 0); + init_timer(&(up->uart_dma.rx_timer)); + up->uart_dma.rx_timer.function = serial_omap_rxdma_poll; + up->uart_dma.rx_timer.data = up->port.line; + /* Currently the buffer size is 4KB. Can increase it */ + up->uart_dma.rx_buf = dma_alloc_coherent(NULL, + up->uart_dma.rx_buf_size, + (dma_addr_t *)&(up->uart_dma.rx_buf_dma_phys), 0); + } /* * Finally, enable interrupts. Note: Modem status interrupts * are set via set_termios(), which will be occurring imminently @@ -612,20 +598,20 @@ static int serial_omap_startup(struct uart_port *port) /* Enable module level wake up */ serial_out(up, UART_OMAP_WER, OMAP_UART_WER_MOD_WKUP); - pm_runtime_mark_last_busy(up->dev); - pm_runtime_put_autosuspend(up->dev); + pm_runtime_mark_last_busy(&up->pdev->dev); + pm_runtime_put_autosuspend(&up->pdev->dev); up->port_activity = jiffies; return 0; } static void serial_omap_shutdown(struct uart_port *port) { - struct uart_omap_port *up = to_uart_omap_port(port); + struct uart_omap_port *up = (struct uart_omap_port *)port; unsigned long flags = 0; dev_dbg(up->port.dev, "serial_omap_shutdown+%d\n", up->port.line); - pm_runtime_get_sync(up->dev); + pm_runtime_get_sync(&up->pdev->dev); /* * Disable interrupts from this port */ @@ -648,9 +634,19 @@ static void serial_omap_shutdown(struct uart_port *port) */ if (serial_in(up, UART_LSR) & UART_LSR_DR) (void) serial_in(up, UART_RX); + if (up->use_dma) { + dma_free_coherent(up->port.dev, + UART_XMIT_SIZE, up->port.state->xmit.buf, + up->uart_dma.tx_buf_dma_phys); + up->port.state->xmit.buf = NULL; + serial_omap_stop_rx(port); + dma_free_coherent(up->port.dev, + up->uart_dma.rx_buf_size, up->uart_dma.rx_buf, + up->uart_dma.rx_buf_dma_phys); + up->uart_dma.rx_buf = NULL; + } - pm_runtime_mark_last_busy(up->dev); - pm_runtime_put_autosuspend(up->dev); + pm_runtime_put(&up->pdev->dev); free_irq(up->port.irq, up); } @@ -671,19 +667,19 @@ serial_omap_configure_xonxoff /* * IXON Flag: - * Flow control for OMAP.TX - * OMAP.RX should listen for XON/XOFF + * Enable XON/XOFF flow control on output. + * Transmit XON1, XOFF1 */ if (termios->c_iflag & IXON) - up->efr |= OMAP_UART_SW_RX; + up->efr |= OMAP_UART_SW_TX; /* * IXOFF Flag: - * Flow control for OMAP.RX - * OMAP.TX should send XON/XOFF + * Enable XON/XOFF flow control on input. + * Receiver compares XON1, XOFF1. */ if (termios->c_iflag & IXOFF) - up->efr |= OMAP_UART_SW_TX; + up->efr |= OMAP_UART_SW_RX; serial_out(up, UART_EFR, up->efr | UART_EFR_ECB); serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A); @@ -719,16 +715,13 @@ static void serial_omap_uart_qos_work(struct work_struct *work) qos_work); pm_qos_update_request(&up->pm_qos_request, up->latency); - if (gpio_is_valid(up->DTR_gpio)) - gpio_set_value_cansleep(up->DTR_gpio, - up->DTR_active != up->DTR_inverted); } static void serial_omap_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *old) { - struct uart_omap_port *up = to_uart_omap_port(port); + struct uart_omap_port *up = (struct uart_omap_port *)port; unsigned char cval = 0; unsigned char efr = 0; unsigned long flags = 0; @@ -775,12 +768,14 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios, up->fcr = UART_FCR_R_TRIG_01 | UART_FCR_T_TRIG_01 | UART_FCR_ENABLE_FIFO; + if (up->use_dma) + up->fcr |= UART_FCR_DMA_SELECT; /* * Ok, we're now changing the port state. Do it with * interrupts disabled. */ - pm_runtime_get_sync(up->dev); + pm_runtime_get_sync(&up->pdev->dev); spin_lock_irqsave(&up->port.lock, flags); /* @@ -850,13 +845,14 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios, up->scr |= OMAP_UART_SCR_RX_TRIG_GRANU1_MASK; - /* Set receive FIFO threshold to 16 characters and - * transmit FIFO threshold to 16 spaces - */ - up->fcr &= ~OMAP_UART_FCR_RX_FIFO_TRIG_MASK; - up->fcr &= ~OMAP_UART_FCR_TX_FIFO_TRIG_MASK; - up->fcr |= UART_FCR6_R_TRIGGER_16 | UART_FCR6_T_TRIGGER_24 | - UART_FCR_ENABLE_FIFO; + if (up->use_dma) { + serial_out(up, UART_TI752_TLR, 0); + up->scr |= UART_FCR_TRIGGER_4; + } else { + /* Set receive FIFO threshold to 1 byte */ + up->fcr &= ~OMAP_UART_FCR_RX_FIFO_TRIG_MASK; + up->fcr |= (0x1 << OMAP_UART_FCR_RX_FIFO_TRIG_SHIFT); + } serial_out(up, UART_FCR, up->fcr); serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); @@ -928,30 +924,20 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios, serial_omap_configure_xonxoff(up, termios); spin_unlock_irqrestore(&up->port.lock, flags); - pm_runtime_mark_last_busy(up->dev); - pm_runtime_put_autosuspend(up->dev); + pm_runtime_put(&up->pdev->dev); dev_dbg(up->port.dev, "serial_omap_set_termios+%d\n", up->port.line); } -static int serial_omap_set_wake(struct uart_port *port, unsigned int state) -{ - struct uart_omap_port *up = to_uart_omap_port(port); - - serial_omap_enable_wakeup(up, state); - - return 0; -} - static void serial_omap_pm(struct uart_port *port, unsigned int state, unsigned int oldstate) { - struct uart_omap_port *up = to_uart_omap_port(port); + struct uart_omap_port *up = (struct uart_omap_port *)port; unsigned char efr; dev_dbg(up->port.dev, "serial_omap_pm+%d\n", up->port.line); - pm_runtime_get_sync(up->dev); + pm_runtime_get_sync(&up->pdev->dev); serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); efr = serial_in(up, UART_EFR); serial_out(up, UART_EFR, efr | UART_EFR_ECB); @@ -962,15 +948,14 @@ serial_omap_pm(struct uart_port *port, unsigned int state, serial_out(up, UART_EFR, efr); serial_out(up, UART_LCR, 0); - if (!device_may_wakeup(up->dev)) { + if (!device_may_wakeup(&up->pdev->dev)) { if (!state) - pm_runtime_forbid(up->dev); + pm_runtime_forbid(&up->pdev->dev); else - pm_runtime_allow(up->dev); + pm_runtime_allow(&up->pdev->dev); } - pm_runtime_mark_last_busy(up->dev); - pm_runtime_put_autosuspend(up->dev); + pm_runtime_put(&up->pdev->dev); } static void serial_omap_release_port(struct uart_port *port) @@ -986,7 +971,7 @@ static int serial_omap_request_port(struct uart_port *port) static void serial_omap_config_port(struct uart_port *port, int flags) { - struct uart_omap_port *up = to_uart_omap_port(port); + struct uart_omap_port *up = (struct uart_omap_port *)port; dev_dbg(up->port.dev, "serial_omap_config_port+%d\n", up->port.line); @@ -1004,7 +989,7 @@ serial_omap_verify_port(struct uart_port *port, struct serial_struct *ser) static const char * serial_omap_type(struct uart_port *port) { - struct uart_omap_port *up = to_uart_omap_port(port); + struct uart_omap_port *up = (struct uart_omap_port *)port; dev_dbg(up->port.dev, "serial_omap_type+%d\n", up->port.line); return up->name; @@ -1047,33 +1032,26 @@ static inline void wait_for_xmitr(struct uart_omap_port *up) static void serial_omap_poll_put_char(struct uart_port *port, unsigned char ch) { - struct uart_omap_port *up = to_uart_omap_port(port); + struct uart_omap_port *up = (struct uart_omap_port *)port; - pm_runtime_get_sync(up->dev); + pm_runtime_get_sync(&up->pdev->dev); wait_for_xmitr(up); serial_out(up, UART_TX, ch); - pm_runtime_mark_last_busy(up->dev); - pm_runtime_put_autosuspend(up->dev); + pm_runtime_put(&up->pdev->dev); } static int serial_omap_poll_get_char(struct uart_port *port) { - struct uart_omap_port *up = to_uart_omap_port(port); + struct uart_omap_port *up = (struct uart_omap_port *)port; unsigned int status; - pm_runtime_get_sync(up->dev); + pm_runtime_get_sync(&up->pdev->dev); status = serial_in(up, UART_LSR); - if (!(status & UART_LSR_DR)) { - status = NO_POLL_CHAR; - goto out; - } + if (!(status & UART_LSR_DR)) + return NO_POLL_CHAR; status = serial_in(up, UART_RX); - -out: - pm_runtime_mark_last_busy(up->dev); - pm_runtime_put_autosuspend(up->dev); - + pm_runtime_put(&up->pdev->dev); return status; } @@ -1087,7 +1065,7 @@ static struct uart_driver serial_omap_reg; static void serial_omap_console_putchar(struct uart_port *port, int ch) { - struct uart_omap_port *up = to_uart_omap_port(port); + struct uart_omap_port *up = (struct uart_omap_port *)port; wait_for_xmitr(up); serial_out(up, UART_TX, ch); @@ -1102,7 +1080,7 @@ serial_omap_console_write(struct console *co, const char *s, unsigned int ier; int locked = 1; - pm_runtime_get_sync(up->dev); + pm_runtime_get_sync(&up->pdev->dev); local_irq_save(flags); if (up->port.sysrq) @@ -1136,8 +1114,8 @@ serial_omap_console_write(struct console *co, const char *s, if (up->msr_saved_flags) check_modem_status(up); - pm_runtime_mark_last_busy(up->dev); - pm_runtime_put_autosuspend(up->dev); + pm_runtime_mark_last_busy(&up->pdev->dev); + pm_runtime_put_autosuspend(&up->pdev->dev); if (locked) spin_unlock(&up->port.lock); local_irq_restore(flags); @@ -1201,7 +1179,6 @@ static struct uart_ops serial_omap_pops = { .shutdown = serial_omap_shutdown, .set_termios = serial_omap_set_termios, .pm = serial_omap_pm, - .set_wake = serial_omap_set_wake, .type = serial_omap_type, .release_port = serial_omap_release_port, .request_port = serial_omap_request_port, @@ -1226,8 +1203,10 @@ static int serial_omap_suspend(struct device *dev) { struct uart_omap_port *up = dev_get_drvdata(dev); - uart_suspend_port(&serial_omap_reg, &up->port); - flush_work_sync(&up->qos_work); + if (up) { + uart_suspend_port(&serial_omap_reg, &up->port); + flush_work_sync(&up->qos_work); + } return 0; } @@ -1236,13 +1215,156 @@ static int serial_omap_resume(struct device *dev) { struct uart_omap_port *up = dev_get_drvdata(dev); - uart_resume_port(&serial_omap_reg, &up->port); - + if (up) + uart_resume_port(&serial_omap_reg, &up->port); return 0; } #endif -static void __devinit omap_serial_fill_features_erratas(struct uart_omap_port *up) +static void serial_omap_rxdma_poll(unsigned long uart_no) +{ + struct uart_omap_port *up = ui[uart_no]; + unsigned int curr_dma_pos, curr_transmitted_size; + int ret = 0; + + curr_dma_pos = omap_get_dma_dst_pos(up->uart_dma.rx_dma_channel); + if ((curr_dma_pos == up->uart_dma.prev_rx_dma_pos) || + (curr_dma_pos == 0)) { + if (jiffies_to_msecs(jiffies - up->port_activity) < + up->uart_dma.rx_timeout) { + mod_timer(&up->uart_dma.rx_timer, jiffies + + usecs_to_jiffies(up->uart_dma.rx_poll_rate)); + } else { + serial_omap_stop_rxdma(up); + up->ier |= (UART_IER_RDI | UART_IER_RLSI); + serial_out(up, UART_IER, up->ier); + } + return; + } + + curr_transmitted_size = curr_dma_pos - + up->uart_dma.prev_rx_dma_pos; + up->port.icount.rx += curr_transmitted_size; + tty_insert_flip_string(up->port.state->port.tty, + up->uart_dma.rx_buf + + (up->uart_dma.prev_rx_dma_pos - + up->uart_dma.rx_buf_dma_phys), + curr_transmitted_size); + tty_flip_buffer_push(up->port.state->port.tty); + up->uart_dma.prev_rx_dma_pos = curr_dma_pos; + if (up->uart_dma.rx_buf_size + + up->uart_dma.rx_buf_dma_phys == curr_dma_pos) { + ret = serial_omap_start_rxdma(up); + if (ret < 0) { + serial_omap_stop_rxdma(up); + up->ier |= (UART_IER_RDI | UART_IER_RLSI); + serial_out(up, UART_IER, up->ier); + } + } else { + mod_timer(&up->uart_dma.rx_timer, jiffies + + usecs_to_jiffies(up->uart_dma.rx_poll_rate)); + } + up->port_activity = jiffies; +} + +static void uart_rx_dma_callback(int lch, u16 ch_status, void *data) +{ + return; +} + +static int serial_omap_start_rxdma(struct uart_omap_port *up) +{ + int ret = 0; + + if (up->uart_dma.rx_dma_channel == -1) { + pm_runtime_get_sync(&up->pdev->dev); + ret = omap_request_dma(up->uart_dma.uart_dma_rx, + "UART Rx DMA", + (void *)uart_rx_dma_callback, up, + &(up->uart_dma.rx_dma_channel)); + if (ret < 0) + return ret; + + omap_set_dma_src_params(up->uart_dma.rx_dma_channel, 0, + OMAP_DMA_AMODE_CONSTANT, + up->uart_dma.uart_base, 0, 0); + omap_set_dma_dest_params(up->uart_dma.rx_dma_channel, 0, + OMAP_DMA_AMODE_POST_INC, + up->uart_dma.rx_buf_dma_phys, 0, 0); + omap_set_dma_transfer_params(up->uart_dma.rx_dma_channel, + OMAP_DMA_DATA_TYPE_S8, + up->uart_dma.rx_buf_size, 1, + OMAP_DMA_SYNC_ELEMENT, + up->uart_dma.uart_dma_rx, 0); + } + up->uart_dma.prev_rx_dma_pos = up->uart_dma.rx_buf_dma_phys; + /* FIXME: Cache maintenance needed here? */ + omap_start_dma(up->uart_dma.rx_dma_channel); + mod_timer(&up->uart_dma.rx_timer, jiffies + + usecs_to_jiffies(up->uart_dma.rx_poll_rate)); + up->uart_dma.rx_dma_used = true; + return ret; +} + +static void serial_omap_continue_tx(struct uart_omap_port *up) +{ + struct circ_buf *xmit = &up->port.state->xmit; + unsigned int start = up->uart_dma.tx_buf_dma_phys + + (xmit->tail & (UART_XMIT_SIZE - 1)); + + if (uart_circ_empty(xmit)) + return; + + up->uart_dma.tx_buf_size = uart_circ_chars_pending(xmit); + /* + * It is a circular buffer. See if the buffer has wounded back. + * If yes it will have to be transferred in two separate dma + * transfers + */ + if (start + up->uart_dma.tx_buf_size >= + up->uart_dma.tx_buf_dma_phys + UART_XMIT_SIZE) + up->uart_dma.tx_buf_size = + (up->uart_dma.tx_buf_dma_phys + UART_XMIT_SIZE) - start; + omap_set_dma_dest_params(up->uart_dma.tx_dma_channel, 0, + OMAP_DMA_AMODE_CONSTANT, + up->uart_dma.uart_base, 0, 0); + omap_set_dma_src_params(up->uart_dma.tx_dma_channel, 0, + OMAP_DMA_AMODE_POST_INC, start, 0, 0); + omap_set_dma_transfer_params(up->uart_dma.tx_dma_channel, + OMAP_DMA_DATA_TYPE_S8, + up->uart_dma.tx_buf_size, 1, + OMAP_DMA_SYNC_ELEMENT, + up->uart_dma.uart_dma_tx, 0); + /* FIXME: Cache maintenance needed here? */ + omap_start_dma(up->uart_dma.tx_dma_channel); +} + +static void uart_tx_dma_callback(int lch, u16 ch_status, void *data) +{ + struct uart_omap_port *up = (struct uart_omap_port *)data; + struct circ_buf *xmit = &up->port.state->xmit; + + xmit->tail = (xmit->tail + up->uart_dma.tx_buf_size) & \ + (UART_XMIT_SIZE - 1); + up->port.icount.tx += up->uart_dma.tx_buf_size; + + if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) + uart_write_wakeup(&up->port); + + if (uart_circ_empty(xmit)) { + spin_lock(&(up->uart_dma.tx_lock)); + serial_omap_stop_tx(&up->port); + up->uart_dma.tx_dma_used = false; + spin_unlock(&(up->uart_dma.tx_lock)); + } else { + omap_stop_dma(up->uart_dma.tx_dma_channel); + serial_omap_continue_tx(up); + } + up->port_activity = jiffies; + return; +} + +static void omap_serial_fill_features_erratas(struct uart_omap_port *up) { u32 mvr, scheme; u16 revision, major, minor; @@ -1267,7 +1389,7 @@ static void __devinit omap_serial_fill_features_erratas(struct uart_omap_port *u minor = (mvr & OMAP_UART_MVR_MIN_MASK); break; default: - dev_warn(up->dev, + dev_warn(&up->pdev->dev, "Unknown %s revision, defaulting to highest\n", up->name); /* highest possible revision */ @@ -1295,7 +1417,7 @@ static void __devinit omap_serial_fill_features_erratas(struct uart_omap_port *u } } -static __devinit struct omap_uart_port_info *of_get_uart_port_info(struct device *dev) +static struct omap_uart_port_info *of_get_uart_port_info(struct device *dev) { struct omap_uart_port_info *omap_up_info; @@ -1308,12 +1430,12 @@ static __devinit struct omap_uart_port_info *of_get_uart_port_info(struct device return omap_up_info; } -static int __devinit serial_omap_probe(struct platform_device *pdev) +static int serial_omap_probe(struct platform_device *pdev) { struct uart_omap_port *up; - struct resource *mem, *irq; + struct resource *mem, *irq, *dma_tx, *dma_rx; struct omap_uart_port_info *omap_up_info = pdev->dev.platform_data; - int ret; + int ret = -ENOSPC; if (pdev->dev.of_node) omap_up_info = of_get_uart_port_info(&pdev->dev); @@ -1336,30 +1458,19 @@ static int __devinit serial_omap_probe(struct platform_device *pdev) return -EBUSY; } - if (gpio_is_valid(omap_up_info->DTR_gpio) && - omap_up_info->DTR_present) { - ret = gpio_request(omap_up_info->DTR_gpio, "omap-serial"); - if (ret < 0) - return ret; - ret = gpio_direction_output(omap_up_info->DTR_gpio, - omap_up_info->DTR_inverted); - if (ret < 0) - return ret; - } + dma_rx = platform_get_resource_byname(pdev, IORESOURCE_DMA, "rx"); + if (!dma_rx) + return -ENXIO; + + dma_tx = platform_get_resource_byname(pdev, IORESOURCE_DMA, "tx"); + if (!dma_tx) + return -ENXIO; up = devm_kzalloc(&pdev->dev, sizeof(*up), GFP_KERNEL); if (!up) return -ENOMEM; - if (gpio_is_valid(omap_up_info->DTR_gpio) && - omap_up_info->DTR_present) { - up->DTR_gpio = omap_up_info->DTR_gpio; - up->DTR_inverted = omap_up_info->DTR_inverted; - } else - up->DTR_gpio = -EINVAL; - up->DTR_active = 0; - - up->dev = &pdev->dev; + up->pdev = pdev; up->port.dev = &pdev->dev; up->port.type = PORT_OMAP; up->port.iotype = UPIO_MEM; @@ -1381,13 +1492,6 @@ static int __devinit serial_omap_probe(struct platform_device *pdev) goto err_port_line; } - up->pins = devm_pinctrl_get_select_default(&pdev->dev); - if (IS_ERR(up->pins)) { - dev_warn(&pdev->dev, "did not get pins for uart%i error: %li\n", - up->port.line, PTR_ERR(up->pins)); - up->pins = NULL; - } - sprintf(up->name, "OMAP UART%d", up->port.line); up->port.mapbase = mem->start; up->port.membase = devm_ioremap(&pdev->dev, mem->start, @@ -1405,6 +1509,20 @@ static int __devinit serial_omap_probe(struct platform_device *pdev) dev_warn(&pdev->dev, "No clock speed specified: using default:" "%d\n", DEFAULT_CLK_SPEED); } + up->uart_dma.uart_base = mem->start; + + if (omap_up_info->dma_enabled) { + up->uart_dma.uart_dma_tx = dma_tx->start; + up->uart_dma.uart_dma_rx = dma_rx->start; + up->use_dma = 1; + up->uart_dma.rx_buf_size = omap_up_info->dma_rx_buf_size; + up->uart_dma.rx_timeout = omap_up_info->dma_rx_timeout; + up->uart_dma.rx_poll_rate = omap_up_info->dma_rx_poll_rate; + spin_lock_init(&(up->uart_dma.tx_lock)); + spin_lock_init(&(up->uart_dma.rx_lock)); + up->uart_dma.tx_dma_channel = OMAP_UART_DMA_CH_FREE; + up->uart_dma.rx_dma_channel = OMAP_UART_DMA_CH_FREE; + } up->latency = PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE; up->calc_latency = PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE; @@ -1413,13 +1531,12 @@ static int __devinit serial_omap_probe(struct platform_device *pdev) serial_omap_uart_wq = create_singlethread_workqueue(up->name); INIT_WORK(&up->qos_work, serial_omap_uart_qos_work); - platform_set_drvdata(pdev, up); - pm_runtime_enable(&pdev->dev); pm_runtime_use_autosuspend(&pdev->dev); pm_runtime_set_autosuspend_delay(&pdev->dev, omap_up_info->autosuspend_timeout); pm_runtime_irq_safe(&pdev->dev); + pm_runtime_enable(&pdev->dev); pm_runtime_get_sync(&pdev->dev); omap_serial_fill_features_erratas(up); @@ -1431,8 +1548,8 @@ static int __devinit serial_omap_probe(struct platform_device *pdev) if (ret != 0) goto err_add_port; - pm_runtime_mark_last_busy(up->dev); - pm_runtime_put_autosuspend(up->dev); + pm_runtime_put(&pdev->dev); + platform_set_drvdata(pdev, up); return 0; err_add_port: @@ -1445,15 +1562,17 @@ static int __devinit serial_omap_probe(struct platform_device *pdev) return ret; } -static int __devexit serial_omap_remove(struct platform_device *dev) +static int serial_omap_remove(struct platform_device *dev) { struct uart_omap_port *up = platform_get_drvdata(dev); - pm_runtime_put_sync(up->dev); - pm_runtime_disable(up->dev); - uart_remove_one_port(&serial_omap_reg, &up->port); - pm_qos_remove_request(&up->pm_qos_request); + if (up) { + pm_runtime_disable(&up->pdev->dev); + uart_remove_one_port(&serial_omap_reg, &up->port); + pm_qos_remove_request(&up->pm_qos_request); + } + platform_set_drvdata(dev, NULL); return 0; } @@ -1483,7 +1602,7 @@ static void serial_omap_mdr1_errataset(struct uart_omap_port *up, u8 mdr1) timeout--; if (!timeout) { /* Should *never* happen. we warn and carry on */ - dev_crit(up->dev, "Errata i202: timedout %x\n", + dev_crit(&up->pdev->dev, "Errata i202: timedout %x\n", serial_in(up, UART_LSR)); break; } @@ -1529,23 +1648,29 @@ static int serial_omap_runtime_suspend(struct device *dev) if (!up) return -EINVAL; - if (!pdata) + if (!pdata || !pdata->enable_wakeup) return 0; - up->context_loss_cnt = serial_omap_get_context_loss_count(up); + if (pdata->get_context_loss_count) + up->context_loss_cnt = pdata->get_context_loss_count(dev); if (device_may_wakeup(dev)) { if (!up->wakeups_enabled) { - serial_omap_enable_wakeup(up, true); + pdata->enable_wakeup(up->pdev, true); up->wakeups_enabled = true; } } else { if (up->wakeups_enabled) { - serial_omap_enable_wakeup(up, false); + pdata->enable_wakeup(up->pdev, false); up->wakeups_enabled = false; } } + /* Errata i291 */ + if (up->use_dma && pdata->set_forceidle && + (up->errata & UART_ERRATA_i291_DMA_FORCEIDLE)) + pdata->set_forceidle(up->pdev); + up->latency = PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE; schedule_work(&up->qos_work); @@ -1555,14 +1680,24 @@ static int serial_omap_runtime_suspend(struct device *dev) static int serial_omap_runtime_resume(struct device *dev) { struct uart_omap_port *up = dev_get_drvdata(dev); + struct omap_uart_port_info *pdata = dev->platform_data; - u32 loss_cnt = serial_omap_get_context_loss_count(up); + if (up && pdata) { + if (pdata->get_context_loss_count) { + u32 loss_cnt = pdata->get_context_loss_count(dev); - if (up->context_loss_cnt != loss_cnt) - serial_omap_restore_context(up); + if (up->context_loss_cnt != loss_cnt) + serial_omap_restore_context(up); + } - up->latency = up->calc_latency; - schedule_work(&up->qos_work); + /* Errata i291 */ + if (up->use_dma && pdata->set_noidle && + (up->errata & UART_ERRATA_i291_DMA_FORCEIDLE)) + pdata->set_noidle(up->pdev); + + up->latency = up->calc_latency; + schedule_work(&up->qos_work); + } return 0; } @@ -1586,7 +1721,7 @@ MODULE_DEVICE_TABLE(of, omap_serial_of_match); static struct platform_driver serial_omap_driver = { .probe = serial_omap_probe, - .remove = __devexit_p(serial_omap_remove), + .remove = serial_omap_remove, .driver = { .name = DRIVER_NAME, .pm = &serial_omap_dev_pm_ops, diff --git a/trunk/drivers/tty/serial/pch_uart.c b/trunk/drivers/tty/serial/pch_uart.c index 4cd6c2381528..558ce8509a9a 100644 --- a/trunk/drivers/tty/serial/pch_uart.c +++ b/trunk/drivers/tty/serial/pch_uart.c @@ -979,10 +979,6 @@ static unsigned int dma_handle_tx(struct eg20t_port *priv) priv->tx_dma_use = 1; priv->sg_tx_p = kzalloc(sizeof(struct scatterlist)*num, GFP_ATOMIC); - if (!priv->sg_tx_p) { - dev_err(priv->port.dev, "%s:kzalloc Failed\n", __func__); - return 0; - } sg_init_table(priv->sg_tx_p, num); /* Initialize SG table */ sg = priv->sg_tx_p; diff --git a/trunk/drivers/tty/serial/pmac_zilog.c b/trunk/drivers/tty/serial/pmac_zilog.c index 333c8d012b0e..654755a990df 100644 --- a/trunk/drivers/tty/serial/pmac_zilog.c +++ b/trunk/drivers/tty/serial/pmac_zilog.c @@ -1348,16 +1348,10 @@ static int pmz_verify_port(struct uart_port *port, struct serial_struct *ser) static int pmz_poll_get_char(struct uart_port *port) { struct uart_pmac_port *uap = (struct uart_pmac_port *)port; - int tries = 2; - while (tries) { - if ((read_zsreg(uap, R0) & Rx_CH_AV) != 0) - return read_zsdata(uap); - if (tries--) - udelay(5); - } - - return NO_POLL_CHAR; + while ((read_zsreg(uap, R0) & Rx_CH_AV) == 0) + udelay(5); + return read_zsdata(uap); } static void pmz_poll_put_char(struct uart_port *port, unsigned char c) diff --git a/trunk/drivers/tty/serial/pxa.c b/trunk/drivers/tty/serial/pxa.c index 9033fc6e0e4e..5847a4b855f7 100644 --- a/trunk/drivers/tty/serial/pxa.c +++ b/trunk/drivers/tty/serial/pxa.c @@ -670,19 +670,9 @@ serial_pxa_console_write(struct console *co, const char *s, unsigned int count) { struct uart_pxa_port *up = serial_pxa_ports[co->index]; unsigned int ier; - unsigned long flags; - int locked = 1; clk_prepare_enable(up->clk); - local_irq_save(flags); - if (up->port.sysrq) - locked = 0; - else if (oops_in_progress) - locked = spin_trylock(&up->port.lock); - else - spin_lock(&up->port.lock); - /* * First save the IER then disable the interrupts */ @@ -698,10 +688,6 @@ serial_pxa_console_write(struct console *co, const char *s, unsigned int count) wait_for_xmitr(up); serial_out(up, UART_IER, ier); - if (locked) - spin_unlock(&up->port.lock); - local_irq_restore(flags); - clk_disable_unprepare(up->clk); } diff --git a/trunk/drivers/tty/serial/samsung.c b/trunk/drivers/tty/serial/samsung.c index 7f04717176aa..02d07bfcfa8a 100644 --- a/trunk/drivers/tty/serial/samsung.c +++ b/trunk/drivers/tty/serial/samsung.c @@ -82,7 +82,7 @@ static inline const char *s3c24xx_serial_portname(struct uart_port *port) static int s3c24xx_serial_txempty_nofifo(struct uart_port *port) { - return rd_regl(port, S3C2410_UTRSTAT) & S3C2410_UTRSTAT_TXE; + return (rd_regl(port, S3C2410_UTRSTAT) & S3C2410_UTRSTAT_TXE); } /* @@ -268,7 +268,7 @@ s3c24xx_serial_rx_chars(int irq, void *dev_id) dbg("break!\n"); port->icount.brk++; if (uart_handle_break(port)) - goto ignore_char; + goto ignore_char; } if (uerstat & S3C2410_UERSTAT_FRAME) @@ -459,7 +459,7 @@ static int s3c24xx_serial_startup(struct uart_port *port) s3c24xx_serial_portname(port), ourport); if (ret != 0) { - dev_err(port->dev, "cannot get irq %d\n", ourport->rx_irq); + printk(KERN_ERR "cannot get irq %d\n", ourport->rx_irq); return ret; } @@ -473,7 +473,7 @@ static int s3c24xx_serial_startup(struct uart_port *port) s3c24xx_serial_portname(port), ourport); if (ret) { - dev_err(port->dev, "cannot get irq %d\n", ourport->tx_irq); + printk(KERN_ERR "cannot get irq %d\n", ourport->tx_irq); goto err; } @@ -502,7 +502,7 @@ static int s3c64xx_serial_startup(struct uart_port *port) ret = request_irq(port->irq, s3c64xx_serial_handle_irq, IRQF_SHARED, s3c24xx_serial_portname(port), ourport); if (ret) { - dev_err(port->dev, "cannot get irq %d\n", port->irq); + printk(KERN_ERR "cannot get irq %d\n", port->irq); return ret; } @@ -529,7 +529,7 @@ static void s3c24xx_serial_pm(struct uart_port *port, unsigned int level, switch (level) { case 3: - if (!IS_ERR(ourport->baudclk)) + if (!IS_ERR(ourport->baudclk) && ourport->baudclk != NULL) clk_disable(ourport->baudclk); clk_disable(ourport->clk); @@ -538,12 +538,12 @@ static void s3c24xx_serial_pm(struct uart_port *port, unsigned int level, case 0: clk_enable(ourport->clk); - if (!IS_ERR(ourport->baudclk)) + if (!IS_ERR(ourport->baudclk) && ourport->baudclk != NULL) clk_enable(ourport->baudclk); break; default: - dev_err(port->dev, "s3c24xx_serial: unknown pm %d\n", level); + printk(KERN_ERR "s3c24xx_serial: unknown pm %d\n", level); } } @@ -604,6 +604,7 @@ static unsigned int s3c24xx_serial_getclk(struct s3c24xx_uart_port *ourport, char clkname[MAX_CLK_NAME_LENGTH]; int calc_deviation, deviation = (1 << 30) - 1; + *best_clk = NULL; clk_sel = (ourport->cfg->clk_sel) ? ourport->cfg->clk_sel : ourport->info->def_clk_sel; for (cnt = 0; cnt < info->num_clks; cnt++) { @@ -612,7 +613,7 @@ static unsigned int s3c24xx_serial_getclk(struct s3c24xx_uart_port *ourport, sprintf(clkname, "clk_uart_baud%d", cnt); clk = clk_get(ourport->port.dev, clkname); - if (IS_ERR(clk)) + if (IS_ERR_OR_NULL(clk)) continue; rate = clk_get_rate(clk); @@ -683,7 +684,7 @@ static void s3c24xx_serial_set_termios(struct uart_port *port, { struct s3c2410_uartcfg *cfg = s3c24xx_port_to_cfg(port); struct s3c24xx_uart_port *ourport = to_ourport(port); - struct clk *clk = ERR_PTR(-EINVAL); + struct clk *clk = NULL; unsigned long flags; unsigned int baud, quot, clk_sel = 0; unsigned int ulcon; @@ -704,7 +705,7 @@ static void s3c24xx_serial_set_termios(struct uart_port *port, quot = s3c24xx_serial_getclk(ourport, baud, &clk, &clk_sel); if (baud == 38400 && (port->flags & UPF_SPD_MASK) == UPF_SPD_CUST) quot = port->custom_divisor; - if (IS_ERR(clk)) + if (!clk) return; /* check to see if we need to change clock source */ @@ -712,9 +713,9 @@ static void s3c24xx_serial_set_termios(struct uart_port *port, if (ourport->baudclk != clk) { s3c24xx_serial_setsource(port, clk_sel); - if (!IS_ERR(ourport->baudclk)) { + if (ourport->baudclk != NULL && !IS_ERR(ourport->baudclk)) { clk_disable(ourport->baudclk); - ourport->baudclk = ERR_PTR(-EINVAL); + ourport->baudclk = NULL; } clk_enable(clk); @@ -876,24 +877,11 @@ s3c24xx_serial_verify_port(struct uart_port *port, struct serial_struct *ser) static struct console s3c24xx_serial_console; -static int __init s3c24xx_serial_console_init(void) -{ - register_console(&s3c24xx_serial_console); - return 0; -} -console_initcall(s3c24xx_serial_console_init); - #define S3C24XX_SERIAL_CONSOLE &s3c24xx_serial_console #else #define S3C24XX_SERIAL_CONSOLE NULL #endif -#ifdef CONFIG_CONSOLE_POLL -static int s3c24xx_serial_get_poll_char(struct uart_port *port); -static void s3c24xx_serial_put_poll_char(struct uart_port *port, - unsigned char c); -#endif - static struct uart_ops s3c24xx_serial_ops = { .pm = s3c24xx_serial_pm, .tx_empty = s3c24xx_serial_tx_empty, @@ -912,10 +900,6 @@ static struct uart_ops s3c24xx_serial_ops = { .request_port = s3c24xx_serial_request_port, .config_port = s3c24xx_serial_config_port, .verify_port = s3c24xx_serial_verify_port, -#ifdef CONFIG_CONSOLE_POLL - .poll_get_char = s3c24xx_serial_get_poll_char, - .poll_put_char = s3c24xx_serial_put_poll_char, -#endif }; static struct uart_driver s3c24xx_uart_drv = { @@ -1052,10 +1036,10 @@ static int s3c24xx_serial_cpufreq_transition(struct notifier_block *nb, if (tty == NULL) goto exit; - termios = &tty->termios; + termios = tty->termios; if (termios == NULL) { - dev_warn(uport->dev, "%s: no termios?\n", __func__); + printk(KERN_WARNING "%s: no termios?\n", __func__); goto exit; } @@ -1130,7 +1114,7 @@ static int s3c24xx_serial_init_port(struct s3c24xx_uart_port *ourport, res = platform_get_resource(platdev, IORESOURCE_MEM, 0); if (res == NULL) { - dev_err(port->dev, "failed to find memory resource for uart\n"); + printk(KERN_ERR "failed to find memory resource for uart\n"); return -EINVAL; } @@ -1146,7 +1130,7 @@ static int s3c24xx_serial_init_port(struct s3c24xx_uart_port *ourport, ourport->rx_irq = ret; ourport->tx_irq = ret + 1; } - + ret = platform_get_irq(platdev, 1); if (ret > 0) ourport->tx_irq = ret; @@ -1176,11 +1160,7 @@ static ssize_t s3c24xx_serial_show_clksrc(struct device *dev, struct uart_port *port = s3c24xx_dev_to_port(dev); struct s3c24xx_uart_port *ourport = to_ourport(port); - if (IS_ERR(ourport->baudclk)) - return -EINVAL; - - return snprintf(buf, PAGE_SIZE, "* %s\n", - ourport->baudclk->name ?: "(null)"); + return snprintf(buf, PAGE_SIZE, "* %s\n", ourport->baudclk->name); } static DEVICE_ATTR(clock_source, S_IRUGO, s3c24xx_serial_show_clksrc, NULL); @@ -1220,7 +1200,6 @@ static int s3c24xx_serial_probe(struct platform_device *pdev) return -ENODEV; } - ourport->baudclk = ERR_PTR(-EINVAL); ourport->info = ourport->drv_data->info; ourport->cfg = (pdev->dev.platform_data) ? (struct s3c2410_uartcfg *)pdev->dev.platform_data : @@ -1333,36 +1312,6 @@ s3c24xx_serial_console_txrdy(struct uart_port *port, unsigned int ufcon) return (utrstat & S3C2410_UTRSTAT_TXE) ? 1 : 0; } -#ifdef CONFIG_CONSOLE_POLL -/* - * Console polling routines for writing and reading from the uart while - * in an interrupt or debug context. - */ - -static int s3c24xx_serial_get_poll_char(struct uart_port *port) -{ - struct s3c24xx_uart_port *ourport = to_ourport(port); - unsigned int ufstat; - - ufstat = rd_regl(port, S3C2410_UFSTAT); - if (s3c24xx_serial_rx_fifocnt(ourport, ufstat) == 0) - return NO_POLL_CHAR; - - return rd_regb(port, S3C2410_URXH); -} - -static void s3c24xx_serial_put_poll_char(struct uart_port *port, - unsigned char c) -{ - unsigned int ufcon = rd_regl(cons_uart, S3C2410_UFCON); - - while (!s3c24xx_serial_console_txrdy(port, ufcon)) - cpu_relax(); - wr_regb(cons_uart, S3C2410_UTXH, c); -} - -#endif /* CONFIG_CONSOLE_POLL */ - static void s3c24xx_serial_console_putchar(struct uart_port *port, int ch) { @@ -1438,7 +1387,7 @@ s3c24xx_serial_get_options(struct uart_port *port, int *baud, sprintf(clk_name, "clk_uart_baud%d", clk_sel); clk = clk_get(port->dev, clk_name); - if (!IS_ERR(clk)) + if (!IS_ERR(clk) && clk != NULL) rate = clk_get_rate(clk); else rate = 1; @@ -1730,8 +1679,8 @@ static int __init s3c24xx_serial_modinit(void) ret = uart_register_driver(&s3c24xx_uart_drv); if (ret < 0) { - pr_err("Failed to register Samsung UART driver\n"); - return ret; + printk(KERN_ERR "failed to register UART driver\n"); + return -1; } return platform_driver_register(&samsung_serial_driver); diff --git a/trunk/drivers/tty/serial/sc26xx.c b/trunk/drivers/tty/serial/sc26xx.c index 9d664242b312..e0b4b0a30a5a 100644 --- a/trunk/drivers/tty/serial/sc26xx.c +++ b/trunk/drivers/tty/serial/sc26xx.c @@ -20,10 +20,6 @@ #include #include #include -#include - -#warning "Please try migrate to use new driver SCCNXP and report the status" \ - "in the linux-serial mailing list." #if defined(CONFIG_MAGIC_SYSRQ) #define SUPPORT_SYSRQ diff --git a/trunk/drivers/tty/serial/sccnxp.c b/trunk/drivers/tty/serial/sccnxp.c deleted file mode 100644 index b7086d004f5f..000000000000 --- a/trunk/drivers/tty/serial/sccnxp.c +++ /dev/null @@ -1,990 +0,0 @@ -/* - * NXP (Philips) SCC+++(SCN+++) serial driver - * - * Copyright (C) 2012 Alexander Shiyan - * - * Based on sc26xx.c, by Thomas Bogendörfer (tsbogend@alpha.franken.de) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#if defined(CONFIG_SERIAL_SCCNXP_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) -#define SUPPORT_SYSRQ -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define SCCNXP_NAME "uart-sccnxp" -#define SCCNXP_MAJOR 204 -#define SCCNXP_MINOR 205 - -#define SCCNXP_MR_REG (0x00) -# define MR0_BAUD_NORMAL (0 << 0) -# define MR0_BAUD_EXT1 (1 << 0) -# define MR0_BAUD_EXT2 (5 << 0) -# define MR0_FIFO (1 << 3) -# define MR0_TXLVL (1 << 4) -# define MR1_BITS_5 (0 << 0) -# define MR1_BITS_6 (1 << 0) -# define MR1_BITS_7 (2 << 0) -# define MR1_BITS_8 (3 << 0) -# define MR1_PAR_EVN (0 << 2) -# define MR1_PAR_ODD (1 << 2) -# define MR1_PAR_NO (4 << 2) -# define MR2_STOP1 (7 << 0) -# define MR2_STOP2 (0xf << 0) -#define SCCNXP_SR_REG (0x01) -#define SCCNXP_CSR_REG SCCNXP_SR_REG -# define SR_RXRDY (1 << 0) -# define SR_FULL (1 << 1) -# define SR_TXRDY (1 << 2) -# define SR_TXEMT (1 << 3) -# define SR_OVR (1 << 4) -# define SR_PE (1 << 5) -# define SR_FE (1 << 6) -# define SR_BRK (1 << 7) -#define SCCNXP_CR_REG (0x02) -# define CR_RX_ENABLE (1 << 0) -# define CR_RX_DISABLE (1 << 1) -# define CR_TX_ENABLE (1 << 2) -# define CR_TX_DISABLE (1 << 3) -# define CR_CMD_MRPTR1 (0x01 << 4) -# define CR_CMD_RX_RESET (0x02 << 4) -# define CR_CMD_TX_RESET (0x03 << 4) -# define CR_CMD_STATUS_RESET (0x04 << 4) -# define CR_CMD_BREAK_RESET (0x05 << 4) -# define CR_CMD_START_BREAK (0x06 << 4) -# define CR_CMD_STOP_BREAK (0x07 << 4) -# define CR_CMD_MRPTR0 (0x0b << 4) -#define SCCNXP_RHR_REG (0x03) -#define SCCNXP_THR_REG SCCNXP_RHR_REG -#define SCCNXP_IPCR_REG (0x04) -#define SCCNXP_ACR_REG SCCNXP_IPCR_REG -# define ACR_BAUD0 (0 << 7) -# define ACR_BAUD1 (1 << 7) -# define ACR_TIMER_MODE (6 << 4) -#define SCCNXP_ISR_REG (0x05) -#define SCCNXP_IMR_REG SCCNXP_ISR_REG -# define IMR_TXRDY (1 << 0) -# define IMR_RXRDY (1 << 1) -# define ISR_TXRDY(x) (1 << ((x * 4) + 0)) -# define ISR_RXRDY(x) (1 << ((x * 4) + 1)) -#define SCCNXP_IPR_REG (0x0d) -#define SCCNXP_OPCR_REG SCCNXP_IPR_REG -#define SCCNXP_SOP_REG (0x0e) -#define SCCNXP_ROP_REG (0x0f) - -/* Route helpers */ -#define MCTRL_MASK(sig) (0xf << (sig)) -#define MCTRL_IBIT(cfg, sig) ((((cfg) >> (sig)) & 0xf) - LINE_IP0) -#define MCTRL_OBIT(cfg, sig) ((((cfg) >> (sig)) & 0xf) - LINE_OP0) - -/* Supported chip types */ -enum { - SCCNXP_TYPE_SC2681 = 2681, - SCCNXP_TYPE_SC2691 = 2691, - SCCNXP_TYPE_SC2692 = 2692, - SCCNXP_TYPE_SC2891 = 2891, - SCCNXP_TYPE_SC2892 = 2892, - SCCNXP_TYPE_SC28202 = 28202, - SCCNXP_TYPE_SC68681 = 68681, - SCCNXP_TYPE_SC68692 = 68692, -}; - -struct sccnxp_port { - struct uart_driver uart; - struct uart_port port[SCCNXP_MAX_UARTS]; - - const char *name; - int irq; - - u8 imr; - u8 addr_mask; - int freq_std; - - int flags; -#define SCCNXP_HAVE_IO 0x00000001 -#define SCCNXP_HAVE_MR0 0x00000002 - -#ifdef CONFIG_SERIAL_SCCNXP_CONSOLE - struct console console; -#endif - - struct mutex sccnxp_mutex; - - struct sccnxp_pdata pdata; -}; - -static inline u8 sccnxp_raw_read(void __iomem *base, u8 reg, u8 shift) -{ - return readb(base + (reg << shift)); -} - -static inline void sccnxp_raw_write(void __iomem *base, u8 reg, u8 shift, u8 v) -{ - writeb(v, base + (reg << shift)); -} - -static inline u8 sccnxp_read(struct uart_port *port, u8 reg) -{ - struct sccnxp_port *s = dev_get_drvdata(port->dev); - - return sccnxp_raw_read(port->membase, reg & s->addr_mask, - port->regshift); -} - -static inline void sccnxp_write(struct uart_port *port, u8 reg, u8 v) -{ - struct sccnxp_port *s = dev_get_drvdata(port->dev); - - sccnxp_raw_write(port->membase, reg & s->addr_mask, port->regshift, v); -} - -static inline u8 sccnxp_port_read(struct uart_port *port, u8 reg) -{ - return sccnxp_read(port, (port->line << 3) + reg); -} - -static inline void sccnxp_port_write(struct uart_port *port, u8 reg, u8 v) -{ - sccnxp_write(port, (port->line << 3) + reg, v); -} - -static int sccnxp_update_best_err(int a, int b, int *besterr) -{ - int err = abs(a - b); - - if ((*besterr < 0) || (*besterr > err)) { - *besterr = err; - return 0; - } - - return 1; -} - -struct baud_table { - u8 csr; - u8 acr; - u8 mr0; - int baud; -}; - -const struct baud_table baud_std[] = { - { 0, ACR_BAUD0, MR0_BAUD_NORMAL, 50, }, - { 0, ACR_BAUD1, MR0_BAUD_NORMAL, 75, }, - { 1, ACR_BAUD0, MR0_BAUD_NORMAL, 110, }, - { 2, ACR_BAUD0, MR0_BAUD_NORMAL, 134, }, - { 3, ACR_BAUD1, MR0_BAUD_NORMAL, 150, }, - { 3, ACR_BAUD0, MR0_BAUD_NORMAL, 200, }, - { 4, ACR_BAUD0, MR0_BAUD_NORMAL, 300, }, - { 0, ACR_BAUD1, MR0_BAUD_EXT1, 450, }, - { 1, ACR_BAUD0, MR0_BAUD_EXT2, 880, }, - { 3, ACR_BAUD1, MR0_BAUD_EXT1, 900, }, - { 5, ACR_BAUD0, MR0_BAUD_NORMAL, 600, }, - { 7, ACR_BAUD0, MR0_BAUD_NORMAL, 1050, }, - { 2, ACR_BAUD0, MR0_BAUD_EXT2, 1076, }, - { 6, ACR_BAUD0, MR0_BAUD_NORMAL, 1200, }, - { 10, ACR_BAUD1, MR0_BAUD_NORMAL, 1800, }, - { 7, ACR_BAUD1, MR0_BAUD_NORMAL, 2000, }, - { 8, ACR_BAUD0, MR0_BAUD_NORMAL, 2400, }, - { 5, ACR_BAUD1, MR0_BAUD_EXT1, 3600, }, - { 9, ACR_BAUD0, MR0_BAUD_NORMAL, 4800, }, - { 10, ACR_BAUD0, MR0_BAUD_NORMAL, 7200, }, - { 11, ACR_BAUD0, MR0_BAUD_NORMAL, 9600, }, - { 8, ACR_BAUD0, MR0_BAUD_EXT1, 14400, }, - { 12, ACR_BAUD1, MR0_BAUD_NORMAL, 19200, }, - { 9, ACR_BAUD0, MR0_BAUD_EXT1, 28800, }, - { 12, ACR_BAUD0, MR0_BAUD_NORMAL, 38400, }, - { 11, ACR_BAUD0, MR0_BAUD_EXT1, 57600, }, - { 12, ACR_BAUD1, MR0_BAUD_EXT1, 115200, }, - { 12, ACR_BAUD0, MR0_BAUD_EXT1, 230400, }, - { 0, 0, 0, 0 } -}; - -static int sccnxp_set_baud(struct uart_port *port, int baud) -{ - struct sccnxp_port *s = dev_get_drvdata(port->dev); - int div_std, tmp_baud, bestbaud = baud, besterr = -1; - u8 i, acr = 0, csr = 0, mr0 = 0; - - /* Find best baud from table */ - for (i = 0; baud_std[i].baud && besterr; i++) { - if (baud_std[i].mr0 && !(s->flags & SCCNXP_HAVE_MR0)) - continue; - div_std = DIV_ROUND_CLOSEST(s->freq_std, baud_std[i].baud); - tmp_baud = DIV_ROUND_CLOSEST(port->uartclk, div_std); - if (!sccnxp_update_best_err(baud, tmp_baud, &besterr)) { - acr = baud_std[i].acr; - csr = baud_std[i].csr; - mr0 = baud_std[i].mr0; - bestbaud = tmp_baud; - } - } - - if (s->flags & SCCNXP_HAVE_MR0) { - /* Enable FIFO, set half level for TX */ - mr0 |= MR0_FIFO | MR0_TXLVL; - /* Update MR0 */ - sccnxp_port_write(port, SCCNXP_CR_REG, CR_CMD_MRPTR0); - sccnxp_port_write(port, SCCNXP_MR_REG, mr0); - } - - sccnxp_port_write(port, SCCNXP_ACR_REG, acr | ACR_TIMER_MODE); - sccnxp_port_write(port, SCCNXP_CSR_REG, (csr << 4) | csr); - - if (baud != bestbaud) - dev_dbg(port->dev, "Baudrate desired: %i, calculated: %i\n", - baud, bestbaud); - - return bestbaud; -} - -static void sccnxp_enable_irq(struct uart_port *port, int mask) -{ - struct sccnxp_port *s = dev_get_drvdata(port->dev); - - s->imr |= mask << (port->line * 4); - sccnxp_write(port, SCCNXP_IMR_REG, s->imr); -} - -static void sccnxp_disable_irq(struct uart_port *port, int mask) -{ - struct sccnxp_port *s = dev_get_drvdata(port->dev); - - s->imr &= ~(mask << (port->line * 4)); - sccnxp_write(port, SCCNXP_IMR_REG, s->imr); -} - -static void sccnxp_set_bit(struct uart_port *port, int sig, int state) -{ - u8 bitmask; - struct sccnxp_port *s = dev_get_drvdata(port->dev); - - if (s->pdata.mctrl_cfg[port->line] & MCTRL_MASK(sig)) { - bitmask = 1 << MCTRL_OBIT(s->pdata.mctrl_cfg[port->line], sig); - if (state) - sccnxp_write(port, SCCNXP_SOP_REG, bitmask); - else - sccnxp_write(port, SCCNXP_ROP_REG, bitmask); - } -} - -static void sccnxp_handle_rx(struct uart_port *port) -{ - u8 sr; - unsigned int ch, flag; - struct tty_struct *tty = tty_port_tty_get(&port->state->port); - - if (!tty) - return; - - for (;;) { - sr = sccnxp_port_read(port, SCCNXP_SR_REG); - if (!(sr & SR_RXRDY)) - break; - sr &= SR_PE | SR_FE | SR_OVR | SR_BRK; - - ch = sccnxp_port_read(port, SCCNXP_RHR_REG); - - port->icount.rx++; - flag = TTY_NORMAL; - - if (unlikely(sr)) { - if (sr & SR_BRK) { - port->icount.brk++; - if (uart_handle_break(port)) - continue; - } else if (sr & SR_PE) - port->icount.parity++; - else if (sr & SR_FE) - port->icount.frame++; - else if (sr & SR_OVR) - port->icount.overrun++; - - sr &= port->read_status_mask; - if (sr & SR_BRK) - flag = TTY_BREAK; - else if (sr & SR_PE) - flag = TTY_PARITY; - else if (sr & SR_FE) - flag = TTY_FRAME; - else if (sr & SR_OVR) - flag = TTY_OVERRUN; - } - - if (uart_handle_sysrq_char(port, ch)) - continue; - - if (sr & port->ignore_status_mask) - continue; - - uart_insert_char(port, sr, SR_OVR, ch, flag); - } - - tty_flip_buffer_push(tty); - - tty_kref_put(tty); -} - -static void sccnxp_handle_tx(struct uart_port *port) -{ - u8 sr; - struct circ_buf *xmit = &port->state->xmit; - struct sccnxp_port *s = dev_get_drvdata(port->dev); - - if (unlikely(port->x_char)) { - sccnxp_port_write(port, SCCNXP_THR_REG, port->x_char); - port->icount.tx++; - port->x_char = 0; - return; - } - - if (uart_circ_empty(xmit) || uart_tx_stopped(port)) { - /* Disable TX if FIFO is empty */ - if (sccnxp_port_read(port, SCCNXP_SR_REG) & SR_TXEMT) { - sccnxp_disable_irq(port, IMR_TXRDY); - - /* Set direction to input */ - if (s->flags & SCCNXP_HAVE_IO) - sccnxp_set_bit(port, DIR_OP, 0); - } - return; - } - - while (!uart_circ_empty(xmit)) { - sr = sccnxp_port_read(port, SCCNXP_SR_REG); - if (!(sr & SR_TXRDY)) - break; - - sccnxp_port_write(port, SCCNXP_THR_REG, xmit->buf[xmit->tail]); - xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); - port->icount.tx++; - } - - if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) - uart_write_wakeup(port); -} - -static irqreturn_t sccnxp_ist(int irq, void *dev_id) -{ - int i; - u8 isr; - struct sccnxp_port *s = (struct sccnxp_port *)dev_id; - - mutex_lock(&s->sccnxp_mutex); - - for (;;) { - isr = sccnxp_read(&s->port[0], SCCNXP_ISR_REG); - isr &= s->imr; - if (!isr) - break; - - dev_dbg(s->port[0].dev, "IRQ status: 0x%02x\n", isr); - - for (i = 0; i < s->uart.nr; i++) { - if (isr & ISR_RXRDY(i)) - sccnxp_handle_rx(&s->port[i]); - if (isr & ISR_TXRDY(i)) - sccnxp_handle_tx(&s->port[i]); - } - } - - mutex_unlock(&s->sccnxp_mutex); - - return IRQ_HANDLED; -} - -static void sccnxp_start_tx(struct uart_port *port) -{ - struct sccnxp_port *s = dev_get_drvdata(port->dev); - - mutex_lock(&s->sccnxp_mutex); - - /* Set direction to output */ - if (s->flags & SCCNXP_HAVE_IO) - sccnxp_set_bit(port, DIR_OP, 1); - - sccnxp_enable_irq(port, IMR_TXRDY); - - mutex_unlock(&s->sccnxp_mutex); -} - -static void sccnxp_stop_tx(struct uart_port *port) -{ - /* Do nothing */ -} - -static void sccnxp_stop_rx(struct uart_port *port) -{ - struct sccnxp_port *s = dev_get_drvdata(port->dev); - - mutex_lock(&s->sccnxp_mutex); - sccnxp_port_write(port, SCCNXP_CR_REG, CR_RX_DISABLE); - mutex_unlock(&s->sccnxp_mutex); -} - -static unsigned int sccnxp_tx_empty(struct uart_port *port) -{ - u8 val; - struct sccnxp_port *s = dev_get_drvdata(port->dev); - - mutex_lock(&s->sccnxp_mutex); - val = sccnxp_port_read(port, SCCNXP_SR_REG); - mutex_unlock(&s->sccnxp_mutex); - - return (val & SR_TXEMT) ? TIOCSER_TEMT : 0; -} - -static void sccnxp_enable_ms(struct uart_port *port) -{ - /* Do nothing */ -} - -static void sccnxp_set_mctrl(struct uart_port *port, unsigned int mctrl) -{ - struct sccnxp_port *s = dev_get_drvdata(port->dev); - - if (!(s->flags & SCCNXP_HAVE_IO)) - return; - - mutex_lock(&s->sccnxp_mutex); - - sccnxp_set_bit(port, DTR_OP, mctrl & TIOCM_DTR); - sccnxp_set_bit(port, RTS_OP, mctrl & TIOCM_RTS); - - mutex_unlock(&s->sccnxp_mutex); -} - -static unsigned int sccnxp_get_mctrl(struct uart_port *port) -{ - u8 bitmask, ipr; - struct sccnxp_port *s = dev_get_drvdata(port->dev); - unsigned int mctrl = TIOCM_DSR | TIOCM_CTS | TIOCM_CAR; - - if (!(s->flags & SCCNXP_HAVE_IO)) - return mctrl; - - mutex_lock(&s->sccnxp_mutex); - - ipr = ~sccnxp_read(port, SCCNXP_IPCR_REG); - - if (s->pdata.mctrl_cfg[port->line] & MCTRL_MASK(DSR_IP)) { - bitmask = 1 << MCTRL_IBIT(s->pdata.mctrl_cfg[port->line], - DSR_IP); - mctrl &= ~TIOCM_DSR; - mctrl |= (ipr & bitmask) ? TIOCM_DSR : 0; - } - if (s->pdata.mctrl_cfg[port->line] & MCTRL_MASK(CTS_IP)) { - bitmask = 1 << MCTRL_IBIT(s->pdata.mctrl_cfg[port->line], - CTS_IP); - mctrl &= ~TIOCM_CTS; - mctrl |= (ipr & bitmask) ? TIOCM_CTS : 0; - } - if (s->pdata.mctrl_cfg[port->line] & MCTRL_MASK(DCD_IP)) { - bitmask = 1 << MCTRL_IBIT(s->pdata.mctrl_cfg[port->line], - DCD_IP); - mctrl &= ~TIOCM_CAR; - mctrl |= (ipr & bitmask) ? TIOCM_CAR : 0; - } - if (s->pdata.mctrl_cfg[port->line] & MCTRL_MASK(RNG_IP)) { - bitmask = 1 << MCTRL_IBIT(s->pdata.mctrl_cfg[port->line], - RNG_IP); - mctrl &= ~TIOCM_RNG; - mctrl |= (ipr & bitmask) ? TIOCM_RNG : 0; - } - - mutex_unlock(&s->sccnxp_mutex); - - return mctrl; -} - -static void sccnxp_break_ctl(struct uart_port *port, int break_state) -{ - struct sccnxp_port *s = dev_get_drvdata(port->dev); - - mutex_lock(&s->sccnxp_mutex); - sccnxp_port_write(port, SCCNXP_CR_REG, break_state ? - CR_CMD_START_BREAK : CR_CMD_STOP_BREAK); - mutex_unlock(&s->sccnxp_mutex); -} - -static void sccnxp_set_termios(struct uart_port *port, - struct ktermios *termios, struct ktermios *old) -{ - struct sccnxp_port *s = dev_get_drvdata(port->dev); - u8 mr1, mr2; - int baud; - - mutex_lock(&s->sccnxp_mutex); - - /* Mask termios capabilities we don't support */ - termios->c_cflag &= ~CMSPAR; - - /* Disable RX & TX, reset break condition, status and FIFOs */ - sccnxp_port_write(port, SCCNXP_CR_REG, CR_CMD_RX_RESET | - CR_RX_DISABLE | CR_TX_DISABLE); - sccnxp_port_write(port, SCCNXP_CR_REG, CR_CMD_TX_RESET); - sccnxp_port_write(port, SCCNXP_CR_REG, CR_CMD_STATUS_RESET); - sccnxp_port_write(port, SCCNXP_CR_REG, CR_CMD_BREAK_RESET); - - /* Word size */ - switch (termios->c_cflag & CSIZE) { - case CS5: - mr1 = MR1_BITS_5; - break; - case CS6: - mr1 = MR1_BITS_6; - break; - case CS7: - mr1 = MR1_BITS_7; - break; - case CS8: - default: - mr1 = MR1_BITS_8; - break; - } - - /* Parity */ - if (termios->c_cflag & PARENB) { - if (termios->c_cflag & PARODD) - mr1 |= MR1_PAR_ODD; - } else - mr1 |= MR1_PAR_NO; - - /* Stop bits */ - mr2 = (termios->c_cflag & CSTOPB) ? MR2_STOP2 : MR2_STOP1; - - /* Update desired format */ - sccnxp_port_write(port, SCCNXP_CR_REG, CR_CMD_MRPTR1); - sccnxp_port_write(port, SCCNXP_MR_REG, mr1); - sccnxp_port_write(port, SCCNXP_MR_REG, mr2); - - /* Set read status mask */ - port->read_status_mask = SR_OVR; - if (termios->c_iflag & INPCK) - port->read_status_mask |= SR_PE | SR_FE; - if (termios->c_iflag & (BRKINT | PARMRK)) - port->read_status_mask |= SR_BRK; - - /* Set status ignore mask */ - port->ignore_status_mask = 0; - if (termios->c_iflag & IGNBRK) - port->ignore_status_mask |= SR_BRK; - if (!(termios->c_cflag & CREAD)) - port->ignore_status_mask |= SR_PE | SR_OVR | SR_FE | SR_BRK; - - /* Setup baudrate */ - baud = uart_get_baud_rate(port, termios, old, 50, - (s->flags & SCCNXP_HAVE_MR0) ? - 230400 : 38400); - baud = sccnxp_set_baud(port, baud); - - /* Update timeout according to new baud rate */ - uart_update_timeout(port, termios->c_cflag, baud); - - if (tty_termios_baud_rate(termios)) - tty_termios_encode_baud_rate(termios, baud, baud); - - /* Enable RX & TX */ - sccnxp_port_write(port, SCCNXP_CR_REG, CR_RX_ENABLE | CR_TX_ENABLE); - - mutex_unlock(&s->sccnxp_mutex); -} - -static int sccnxp_startup(struct uart_port *port) -{ - struct sccnxp_port *s = dev_get_drvdata(port->dev); - - mutex_lock(&s->sccnxp_mutex); - - if (s->flags & SCCNXP_HAVE_IO) { - /* Outputs are controlled manually */ - sccnxp_write(port, SCCNXP_OPCR_REG, 0); - } - - /* Reset break condition, status and FIFOs */ - sccnxp_port_write(port, SCCNXP_CR_REG, CR_CMD_RX_RESET); - sccnxp_port_write(port, SCCNXP_CR_REG, CR_CMD_TX_RESET); - sccnxp_port_write(port, SCCNXP_CR_REG, CR_CMD_STATUS_RESET); - sccnxp_port_write(port, SCCNXP_CR_REG, CR_CMD_BREAK_RESET); - - /* Enable RX & TX */ - sccnxp_port_write(port, SCCNXP_CR_REG, CR_RX_ENABLE | CR_TX_ENABLE); - - /* Enable RX interrupt */ - sccnxp_enable_irq(port, IMR_RXRDY); - - mutex_unlock(&s->sccnxp_mutex); - - return 0; -} - -static void sccnxp_shutdown(struct uart_port *port) -{ - struct sccnxp_port *s = dev_get_drvdata(port->dev); - - mutex_lock(&s->sccnxp_mutex); - - /* Disable interrupts */ - sccnxp_disable_irq(port, IMR_TXRDY | IMR_RXRDY); - - /* Disable TX & RX */ - sccnxp_port_write(port, SCCNXP_CR_REG, CR_RX_DISABLE | CR_TX_DISABLE); - - /* Leave direction to input */ - if (s->flags & SCCNXP_HAVE_IO) - sccnxp_set_bit(port, DIR_OP, 0); - - mutex_unlock(&s->sccnxp_mutex); -} - -static const char *sccnxp_type(struct uart_port *port) -{ - struct sccnxp_port *s = dev_get_drvdata(port->dev); - - return (port->type == PORT_SC26XX) ? s->name : NULL; -} - -static void sccnxp_release_port(struct uart_port *port) -{ - /* Do nothing */ -} - -static int sccnxp_request_port(struct uart_port *port) -{ - /* Do nothing */ - return 0; -} - -static void sccnxp_config_port(struct uart_port *port, int flags) -{ - if (flags & UART_CONFIG_TYPE) - port->type = PORT_SC26XX; -} - -static int sccnxp_verify_port(struct uart_port *port, struct serial_struct *s) -{ - if ((s->type == PORT_UNKNOWN) || (s->type == PORT_SC26XX)) - return 0; - if (s->irq == port->irq) - return 0; - - return -EINVAL; -} - -static const struct uart_ops sccnxp_ops = { - .tx_empty = sccnxp_tx_empty, - .set_mctrl = sccnxp_set_mctrl, - .get_mctrl = sccnxp_get_mctrl, - .stop_tx = sccnxp_stop_tx, - .start_tx = sccnxp_start_tx, - .stop_rx = sccnxp_stop_rx, - .enable_ms = sccnxp_enable_ms, - .break_ctl = sccnxp_break_ctl, - .startup = sccnxp_startup, - .shutdown = sccnxp_shutdown, - .set_termios = sccnxp_set_termios, - .type = sccnxp_type, - .release_port = sccnxp_release_port, - .request_port = sccnxp_request_port, - .config_port = sccnxp_config_port, - .verify_port = sccnxp_verify_port, -}; - -#ifdef CONFIG_SERIAL_SCCNXP_CONSOLE -static void sccnxp_console_putchar(struct uart_port *port, int c) -{ - int tryes = 100000; - - while (tryes--) { - if (sccnxp_port_read(port, SCCNXP_SR_REG) & SR_TXRDY) { - sccnxp_port_write(port, SCCNXP_THR_REG, c); - break; - } - barrier(); - } -} - -static void sccnxp_console_write(struct console *co, const char *c, unsigned n) -{ - struct sccnxp_port *s = (struct sccnxp_port *)co->data; - struct uart_port *port = &s->port[co->index]; - - mutex_lock(&s->sccnxp_mutex); - uart_console_write(port, c, n, sccnxp_console_putchar); - mutex_unlock(&s->sccnxp_mutex); -} - -static int sccnxp_console_setup(struct console *co, char *options) -{ - struct sccnxp_port *s = (struct sccnxp_port *)co->data; - struct uart_port *port = &s->port[(co->index > 0) ? co->index : 0]; - int baud = 9600, bits = 8, parity = 'n', flow = 'n'; - - if (options) - uart_parse_options(options, &baud, &parity, &bits, &flow); - - return uart_set_options(port, co, baud, parity, bits, flow); -} -#endif - -static int __devinit sccnxp_probe(struct platform_device *pdev) -{ - struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - int chiptype = pdev->id_entry->driver_data; - struct sccnxp_pdata *pdata = dev_get_platdata(&pdev->dev); - int i, ret, fifosize, freq_min, freq_max; - struct sccnxp_port *s; - void __iomem *membase; - - if (!res) { - dev_err(&pdev->dev, "Missing memory resource data\n"); - return -EADDRNOTAVAIL; - } - - dev_set_name(&pdev->dev, SCCNXP_NAME); - - s = devm_kzalloc(&pdev->dev, sizeof(struct sccnxp_port), GFP_KERNEL); - if (!s) { - dev_err(&pdev->dev, "Error allocating port structure\n"); - return -ENOMEM; - } - platform_set_drvdata(pdev, s); - - mutex_init(&s->sccnxp_mutex); - - /* Individual chip settings */ - switch (chiptype) { - case SCCNXP_TYPE_SC2681: - s->name = "SC2681"; - s->uart.nr = 2; - s->freq_std = 3686400; - s->addr_mask = 0x0f; - s->flags = SCCNXP_HAVE_IO; - fifosize = 3; - freq_min = 1000000; - freq_max = 4000000; - break; - case SCCNXP_TYPE_SC2691: - s->name = "SC2691"; - s->uart.nr = 1; - s->freq_std = 3686400; - s->addr_mask = 0x07; - s->flags = 0; - fifosize = 3; - freq_min = 1000000; - freq_max = 4000000; - break; - case SCCNXP_TYPE_SC2692: - s->name = "SC2692"; - s->uart.nr = 2; - s->freq_std = 3686400; - s->addr_mask = 0x0f; - s->flags = SCCNXP_HAVE_IO; - fifosize = 3; - freq_min = 1000000; - freq_max = 4000000; - break; - case SCCNXP_TYPE_SC2891: - s->name = "SC2891"; - s->uart.nr = 1; - s->freq_std = 3686400; - s->addr_mask = 0x0f; - s->flags = SCCNXP_HAVE_IO | SCCNXP_HAVE_MR0; - fifosize = 16; - freq_min = 100000; - freq_max = 8000000; - break; - case SCCNXP_TYPE_SC2892: - s->name = "SC2892"; - s->uart.nr = 2; - s->freq_std = 3686400; - s->addr_mask = 0x0f; - s->flags = SCCNXP_HAVE_IO | SCCNXP_HAVE_MR0; - fifosize = 16; - freq_min = 100000; - freq_max = 8000000; - break; - case SCCNXP_TYPE_SC28202: - s->name = "SC28202"; - s->uart.nr = 2; - s->freq_std = 14745600; - s->addr_mask = 0x7f; - s->flags = SCCNXP_HAVE_IO | SCCNXP_HAVE_MR0; - fifosize = 256; - freq_min = 1000000; - freq_max = 50000000; - break; - case SCCNXP_TYPE_SC68681: - s->name = "SC68681"; - s->uart.nr = 2; - s->freq_std = 3686400; - s->addr_mask = 0x0f; - s->flags = SCCNXP_HAVE_IO; - fifosize = 3; - freq_min = 1000000; - freq_max = 4000000; - break; - case SCCNXP_TYPE_SC68692: - s->name = "SC68692"; - s->uart.nr = 2; - s->freq_std = 3686400; - s->addr_mask = 0x0f; - s->flags = SCCNXP_HAVE_IO; - fifosize = 3; - freq_min = 1000000; - freq_max = 4000000; - break; - default: - dev_err(&pdev->dev, "Unsupported chip type %i\n", chiptype); - ret = -ENOTSUPP; - goto err_out; - } - - if (!pdata) { - dev_warn(&pdev->dev, - "No platform data supplied, using defaults\n"); - s->pdata.frequency = s->freq_std; - } else - memcpy(&s->pdata, pdata, sizeof(struct sccnxp_pdata)); - - s->irq = platform_get_irq(pdev, 0); - if (s->irq <= 0) { - dev_err(&pdev->dev, "Missing irq resource data\n"); - ret = -ENXIO; - goto err_out; - } - - /* Check input frequency */ - if ((s->pdata.frequency < freq_min) || - (s->pdata.frequency > freq_max)) { - dev_err(&pdev->dev, "Frequency out of bounds\n"); - ret = -EINVAL; - goto err_out; - } - - membase = devm_request_and_ioremap(&pdev->dev, res); - if (!membase) { - dev_err(&pdev->dev, "Failed to ioremap\n"); - ret = -EIO; - goto err_out; - } - - s->uart.owner = THIS_MODULE; - s->uart.dev_name = "ttySC"; - s->uart.major = SCCNXP_MAJOR; - s->uart.minor = SCCNXP_MINOR; -#ifdef CONFIG_SERIAL_SCCNXP_CONSOLE - s->uart.cons = &s->console; - s->uart.cons->device = uart_console_device; - s->uart.cons->write = sccnxp_console_write; - s->uart.cons->setup = sccnxp_console_setup; - s->uart.cons->flags = CON_PRINTBUFFER; - s->uart.cons->index = -1; - s->uart.cons->data = s; - strcpy(s->uart.cons->name, "ttySC"); -#endif - ret = uart_register_driver(&s->uart); - if (ret) { - dev_err(&pdev->dev, "Registering UART driver failed\n"); - goto err_out; - } - - for (i = 0; i < s->uart.nr; i++) { - s->port[i].line = i; - s->port[i].dev = &pdev->dev; - s->port[i].irq = s->irq; - s->port[i].type = PORT_SC26XX; - s->port[i].fifosize = fifosize; - s->port[i].flags = UPF_SKIP_TEST | UPF_FIXED_TYPE; - s->port[i].iotype = UPIO_MEM; - s->port[i].mapbase = res->start; - s->port[i].membase = membase; - s->port[i].regshift = s->pdata.reg_shift; - s->port[i].uartclk = s->pdata.frequency; - s->port[i].ops = &sccnxp_ops; - uart_add_one_port(&s->uart, &s->port[i]); - /* Set direction to input */ - if (s->flags & SCCNXP_HAVE_IO) - sccnxp_set_bit(&s->port[i], DIR_OP, 0); - } - - /* Disable interrupts */ - s->imr = 0; - sccnxp_write(&s->port[0], SCCNXP_IMR_REG, 0); - - /* Board specific configure */ - if (s->pdata.init) - s->pdata.init(); - - ret = devm_request_threaded_irq(&pdev->dev, s->irq, NULL, sccnxp_ist, - IRQF_TRIGGER_FALLING | IRQF_ONESHOT, - dev_name(&pdev->dev), s); - if (!ret) - return 0; - - dev_err(&pdev->dev, "Unable to reguest IRQ %i\n", s->irq); - -err_out: - platform_set_drvdata(pdev, NULL); - - return ret; -} - -static int __devexit sccnxp_remove(struct platform_device *pdev) -{ - int i; - struct sccnxp_port *s = platform_get_drvdata(pdev); - - devm_free_irq(&pdev->dev, s->irq, s); - - for (i = 0; i < s->uart.nr; i++) - uart_remove_one_port(&s->uart, &s->port[i]); - - uart_unregister_driver(&s->uart); - platform_set_drvdata(pdev, NULL); - - if (s->pdata.exit) - s->pdata.exit(); - - return 0; -} - -static const struct platform_device_id sccnxp_id_table[] = { - { "sc2681", SCCNXP_TYPE_SC2681 }, - { "sc2691", SCCNXP_TYPE_SC2691 }, - { "sc2692", SCCNXP_TYPE_SC2692 }, - { "sc2891", SCCNXP_TYPE_SC2891 }, - { "sc2892", SCCNXP_TYPE_SC2892 }, - { "sc28202", SCCNXP_TYPE_SC28202 }, - { "sc68681", SCCNXP_TYPE_SC68681 }, - { "sc68692", SCCNXP_TYPE_SC68692 }, -}; -MODULE_DEVICE_TABLE(platform, sccnxp_id_table); - -static struct platform_driver sccnxp_uart_driver = { - .driver = { - .name = SCCNXP_NAME, - .owner = THIS_MODULE, - }, - .probe = sccnxp_probe, - .remove = __devexit_p(sccnxp_remove), - .id_table = sccnxp_id_table, -}; -module_platform_driver(sccnxp_uart_driver); - -MODULE_LICENSE("GPL v2"); -MODULE_AUTHOR("Alexander Shiyan "); -MODULE_DESCRIPTION("SCCNXP serial driver"); diff --git a/trunk/drivers/tty/serial/serial_core.c b/trunk/drivers/tty/serial/serial_core.c index 0fcfd98a9566..a21dc8e3b7c0 100644 --- a/trunk/drivers/tty/serial/serial_core.c +++ b/trunk/drivers/tty/serial/serial_core.c @@ -159,7 +159,7 @@ static int uart_port_startup(struct tty_struct *tty, struct uart_state *state, retval = uport->ops->startup(uport); if (retval == 0) { if (uart_console(uport) && uport->cons->cflag) { - tty->termios.c_cflag = uport->cons->cflag; + tty->termios->c_cflag = uport->cons->cflag; uport->cons->cflag = 0; } /* @@ -172,11 +172,11 @@ static int uart_port_startup(struct tty_struct *tty, struct uart_state *state, * Setup the RTS and DTR signals once the * port is open and ready to respond. */ - if (tty->termios.c_cflag & CBAUD) + if (tty->termios->c_cflag & CBAUD) uart_set_mctrl(uport, TIOCM_RTS | TIOCM_DTR); } - if (tty_port_cts_enabled(port)) { + if (port->flags & ASYNC_CTS_FLOW) { spin_lock_irq(&uport->lock); if (!(uport->ops->get_mctrl(uport) & TIOCM_CTS)) tty->hw_stopped = 1; @@ -240,7 +240,7 @@ static void uart_shutdown(struct tty_struct *tty, struct uart_state *state) /* * Turn off DTR and RTS early. */ - if (!tty || (tty->termios.c_cflag & HUPCL)) + if (!tty || (tty->termios->c_cflag & HUPCL)) uart_clear_mctrl(uport, TIOCM_DTR | TIOCM_RTS); uart_port_shutdown(port); @@ -440,10 +440,10 @@ static void uart_change_speed(struct tty_struct *tty, struct uart_state *state, * If we have no tty, termios, or the port does not exist, * then we can't set the parameters for this port. */ - if (!tty || uport->type == PORT_UNKNOWN) + if (!tty || !tty->termios || uport->type == PORT_UNKNOWN) return; - termios = &tty->termios; + termios = tty->termios; /* * Set flags based on termios cflag @@ -614,7 +614,7 @@ static void uart_throttle(struct tty_struct *tty) if (I_IXOFF(tty)) uart_send_xchar(tty, STOP_CHAR(tty)); - if (tty->termios.c_cflag & CRTSCTS) + if (tty->termios->c_cflag & CRTSCTS) uart_clear_mctrl(state->uart_port, TIOCM_RTS); } @@ -630,48 +630,42 @@ static void uart_unthrottle(struct tty_struct *tty) uart_send_xchar(tty, START_CHAR(tty)); } - if (tty->termios.c_cflag & CRTSCTS) + if (tty->termios->c_cflag & CRTSCTS) uart_set_mctrl(port, TIOCM_RTS); } -static void uart_get_info(struct tty_port *port, - struct uart_state *state, - struct serial_struct *retinfo) -{ - struct uart_port *uport = state->uart_port; - - memset(retinfo, 0, sizeof(*retinfo)); - - retinfo->type = uport->type; - retinfo->line = uport->line; - retinfo->port = uport->iobase; - if (HIGH_BITS_OFFSET) - retinfo->port_high = (long) uport->iobase >> HIGH_BITS_OFFSET; - retinfo->irq = uport->irq; - retinfo->flags = uport->flags; - retinfo->xmit_fifo_size = uport->fifosize; - retinfo->baud_base = uport->uartclk / 16; - retinfo->close_delay = jiffies_to_msecs(port->close_delay) / 10; - retinfo->closing_wait = port->closing_wait == ASYNC_CLOSING_WAIT_NONE ? - ASYNC_CLOSING_WAIT_NONE : - jiffies_to_msecs(port->closing_wait) / 10; - retinfo->custom_divisor = uport->custom_divisor; - retinfo->hub6 = uport->hub6; - retinfo->io_type = uport->iotype; - retinfo->iomem_reg_shift = uport->regshift; - retinfo->iomem_base = (void *)(unsigned long)uport->mapbase; -} - -static int uart_get_info_user(struct uart_state *state, +static int uart_get_info(struct uart_state *state, struct serial_struct __user *retinfo) { + struct uart_port *uport = state->uart_port; struct tty_port *port = &state->port; struct serial_struct tmp; + memset(&tmp, 0, sizeof(tmp)); + /* Ensure the state we copy is consistent and no hardware changes occur as we go */ mutex_lock(&port->mutex); - uart_get_info(port, state, &tmp); + + tmp.type = uport->type; + tmp.line = uport->line; + tmp.port = uport->iobase; + if (HIGH_BITS_OFFSET) + tmp.port_high = (long) uport->iobase >> HIGH_BITS_OFFSET; + tmp.irq = uport->irq; + tmp.flags = uport->flags; + tmp.xmit_fifo_size = uport->fifosize; + tmp.baud_base = uport->uartclk / 16; + tmp.close_delay = jiffies_to_msecs(port->close_delay) / 10; + tmp.closing_wait = port->closing_wait == ASYNC_CLOSING_WAIT_NONE ? + ASYNC_CLOSING_WAIT_NONE : + jiffies_to_msecs(port->closing_wait) / 10; + tmp.custom_divisor = uport->custom_divisor; + tmp.hub6 = uport->hub6; + tmp.io_type = uport->iotype; + tmp.iomem_reg_shift = uport->regshift; + tmp.iomem_base = (void *)(unsigned long)uport->mapbase; + mutex_unlock(&port->mutex); if (copy_to_user(retinfo, &tmp, sizeof(*retinfo))) @@ -679,30 +673,42 @@ static int uart_get_info_user(struct uart_state *state, return 0; } -static int uart_set_info(struct tty_struct *tty, struct tty_port *port, - struct uart_state *state, - struct serial_struct *new_info) +static int uart_set_info(struct tty_struct *tty, struct uart_state *state, + struct serial_struct __user *newinfo) { + struct serial_struct new_serial; struct uart_port *uport = state->uart_port; + struct tty_port *port = &state->port; unsigned long new_port; unsigned int change_irq, change_port, closing_wait; unsigned int old_custom_divisor, close_delay; upf_t old_flags, new_flags; int retval = 0; - new_port = new_info->port; + if (copy_from_user(&new_serial, newinfo, sizeof(new_serial))) + return -EFAULT; + + new_port = new_serial.port; if (HIGH_BITS_OFFSET) - new_port += (unsigned long) new_info->port_high << HIGH_BITS_OFFSET; + new_port += (unsigned long) new_serial.port_high << HIGH_BITS_OFFSET; - new_info->irq = irq_canonicalize(new_info->irq); - close_delay = msecs_to_jiffies(new_info->close_delay * 10); - closing_wait = new_info->closing_wait == ASYNC_CLOSING_WAIT_NONE ? + new_serial.irq = irq_canonicalize(new_serial.irq); + close_delay = msecs_to_jiffies(new_serial.close_delay * 10); + closing_wait = new_serial.closing_wait == ASYNC_CLOSING_WAIT_NONE ? ASYNC_CLOSING_WAIT_NONE : - msecs_to_jiffies(new_info->closing_wait * 10); + msecs_to_jiffies(new_serial.closing_wait * 10); + /* + * This semaphore protects port->count. It is also + * very useful to prevent opens. Also, take the + * port configuration semaphore to make sure that a + * module insertion/removal doesn't change anything + * under us. + */ + mutex_lock(&port->mutex); change_irq = !(uport->flags & UPF_FIXED_PORT) - && new_info->irq != uport->irq; + && new_serial.irq != uport->irq; /* * Since changing the 'type' of the port changes its resource @@ -711,29 +717,29 @@ static int uart_set_info(struct tty_struct *tty, struct tty_port *port, */ change_port = !(uport->flags & UPF_FIXED_PORT) && (new_port != uport->iobase || - (unsigned long)new_info->iomem_base != uport->mapbase || - new_info->hub6 != uport->hub6 || - new_info->io_type != uport->iotype || - new_info->iomem_reg_shift != uport->regshift || - new_info->type != uport->type); + (unsigned long)new_serial.iomem_base != uport->mapbase || + new_serial.hub6 != uport->hub6 || + new_serial.io_type != uport->iotype || + new_serial.iomem_reg_shift != uport->regshift || + new_serial.type != uport->type); old_flags = uport->flags; - new_flags = new_info->flags; + new_flags = new_serial.flags; old_custom_divisor = uport->custom_divisor; if (!capable(CAP_SYS_ADMIN)) { retval = -EPERM; if (change_irq || change_port || - (new_info->baud_base != uport->uartclk / 16) || + (new_serial.baud_base != uport->uartclk / 16) || (close_delay != port->close_delay) || (closing_wait != port->closing_wait) || - (new_info->xmit_fifo_size && - new_info->xmit_fifo_size != uport->fifosize) || + (new_serial.xmit_fifo_size && + new_serial.xmit_fifo_size != uport->fifosize) || (((new_flags ^ old_flags) & ~UPF_USR_MASK) != 0)) goto exit; uport->flags = ((uport->flags & ~UPF_USR_MASK) | (new_flags & UPF_USR_MASK)); - uport->custom_divisor = new_info->custom_divisor; + uport->custom_divisor = new_serial.custom_divisor; goto check_and_exit; } @@ -741,10 +747,10 @@ static int uart_set_info(struct tty_struct *tty, struct tty_port *port, * Ask the low level driver to verify the settings. */ if (uport->ops->verify_port) - retval = uport->ops->verify_port(uport, new_info); + retval = uport->ops->verify_port(uport, &new_serial); - if ((new_info->irq >= nr_irqs) || (new_info->irq < 0) || - (new_info->baud_base < 9600)) + if ((new_serial.irq >= nr_irqs) || (new_serial.irq < 0) || + (new_serial.baud_base < 9600)) retval = -EINVAL; if (retval) @@ -784,11 +790,11 @@ static int uart_set_info(struct tty_struct *tty, struct tty_port *port, uport->ops->release_port(uport); uport->iobase = new_port; - uport->type = new_info->type; - uport->hub6 = new_info->hub6; - uport->iotype = new_info->io_type; - uport->regshift = new_info->iomem_reg_shift; - uport->mapbase = (unsigned long)new_info->iomem_base; + uport->type = new_serial.type; + uport->hub6 = new_serial.hub6; + uport->iotype = new_serial.io_type; + uport->regshift = new_serial.iomem_reg_shift; + uport->mapbase = (unsigned long)new_serial.iomem_base; /* * Claim and map the new regions @@ -829,16 +835,16 @@ static int uart_set_info(struct tty_struct *tty, struct tty_port *port, } if (change_irq) - uport->irq = new_info->irq; + uport->irq = new_serial.irq; if (!(uport->flags & UPF_FIXED_PORT)) - uport->uartclk = new_info->baud_base * 16; + uport->uartclk = new_serial.baud_base * 16; uport->flags = (uport->flags & ~UPF_CHANGE_MASK) | (new_flags & UPF_CHANGE_MASK); - uport->custom_divisor = new_info->custom_divisor; + uport->custom_divisor = new_serial.custom_divisor; port->close_delay = close_delay; port->closing_wait = closing_wait; - if (new_info->xmit_fifo_size) - uport->fifosize = new_info->xmit_fifo_size; + if (new_serial.xmit_fifo_size) + uport->fifosize = new_serial.xmit_fifo_size; if (port->tty) port->tty->low_latency = (uport->flags & UPF_LOW_LATENCY) ? 1 : 0; @@ -867,28 +873,6 @@ static int uart_set_info(struct tty_struct *tty, struct tty_port *port, } else retval = uart_startup(tty, state, 1); exit: - return retval; -} - -static int uart_set_info_user(struct tty_struct *tty, struct uart_state *state, - struct serial_struct __user *newinfo) -{ - struct serial_struct new_serial; - struct tty_port *port = &state->port; - int retval; - - if (copy_from_user(&new_serial, newinfo, sizeof(new_serial))) - return -EFAULT; - - /* - * This semaphore protects port->count. It is also - * very useful to prevent opens. Also, take the - * port configuration semaphore to make sure that a - * module insertion/removal doesn't change anything - * under us. - */ - mutex_lock(&port->mutex); - retval = uart_set_info(tty, port, state, &new_serial); mutex_unlock(&port->mutex); return retval; } @@ -1131,11 +1115,11 @@ uart_ioctl(struct tty_struct *tty, unsigned int cmd, */ switch (cmd) { case TIOCGSERIAL: - ret = uart_get_info_user(state, uarg); + ret = uart_get_info(state, uarg); break; case TIOCSSERIAL: - ret = uart_set_info_user(tty, state, uarg); + ret = uart_set_info(tty, state, uarg); break; case TIOCSERCONFIG: @@ -1203,7 +1187,7 @@ static void uart_set_ldisc(struct tty_struct *tty) struct uart_port *uport = state->uart_port; if (uport->ops->set_ldisc) - uport->ops->set_ldisc(uport, tty->termios.c_line); + uport->ops->set_ldisc(uport, tty->termios->c_line); } static void uart_set_termios(struct tty_struct *tty, @@ -1211,7 +1195,7 @@ static void uart_set_termios(struct tty_struct *tty, { struct uart_state *state = tty->driver_data; unsigned long flags; - unsigned int cflag = tty->termios.c_cflag; + unsigned int cflag = tty->termios->c_cflag; /* @@ -1222,9 +1206,9 @@ static void uart_set_termios(struct tty_struct *tty, */ #define RELEVANT_IFLAG(iflag) ((iflag) & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK)) if ((cflag ^ old_termios->c_cflag) == 0 && - tty->termios.c_ospeed == old_termios->c_ospeed && - tty->termios.c_ispeed == old_termios->c_ispeed && - RELEVANT_IFLAG(tty->termios.c_iflag ^ old_termios->c_iflag) == 0) { + tty->termios->c_ospeed == old_termios->c_ospeed && + tty->termios->c_ispeed == old_termios->c_ispeed && + RELEVANT_IFLAG(tty->termios->c_iflag ^ old_termios->c_iflag) == 0) { return; } @@ -1976,8 +1960,8 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *uport) /* * If that's unset, use the tty termios setting. */ - if (port->tty && termios.c_cflag == 0) - termios = port->tty->termios; + if (port->tty && port->tty->termios && termios.c_cflag == 0) + termios = *(port->tty->termios); if (console_suspend_enabled) uart_change_pm(state, 0); @@ -2129,7 +2113,6 @@ static int uart_poll_init(struct tty_driver *driver, int line, char *options) int bits = 8; int parity = 'n'; int flow = 'n'; - int ret; if (!state || !state->uart_port) return -1; @@ -2138,22 +2121,6 @@ static int uart_poll_init(struct tty_driver *driver, int line, char *options) if (!(port->ops->poll_get_char && port->ops->poll_put_char)) return -1; - if (port->ops->poll_init) { - struct tty_port *tport = &state->port; - - ret = 0; - mutex_lock(&tport->mutex); - /* - * We don't set ASYNCB_INITIALIZED as we only initialized the - * hw, e.g. state->xmit is still uninitialized. - */ - if (!test_bit(ASYNCB_INITIALIZED, &tport->flags)) - ret = port->ops->poll_init(port); - mutex_unlock(&tport->mutex); - if (ret) - return ret; - } - if (options) { uart_parse_options(options, &baud, &parity, &bits, &flow); return uart_set_options(port, NULL, baud, parity, bits, flow); @@ -2326,36 +2293,6 @@ struct tty_driver *uart_console_device(struct console *co, int *index) return p->tty_driver; } -static ssize_t uart_get_attr_uartclk(struct device *dev, - struct device_attribute *attr, char *buf) -{ - int ret; - struct tty_port *port = dev_get_drvdata(dev); - struct uart_state *state = container_of(port, struct uart_state, port); - - mutex_lock(&state->port.mutex); - ret = snprintf(buf, PAGE_SIZE, "%d\n", state->uart_port->uartclk); - mutex_unlock(&state->port.mutex); - - return ret; -} - -static DEVICE_ATTR(uartclk, S_IRUSR | S_IRGRP, uart_get_attr_uartclk, NULL); - -static struct attribute *tty_dev_attrs[] = { - &dev_attr_uartclk.attr, - NULL, - }; - -static const struct attribute_group tty_dev_attr_group = { - .attrs = tty_dev_attrs, - }; - -static const struct attribute_group *tty_dev_attr_groups[] = { - &tty_dev_attr_group, - NULL - }; - /** * uart_add_one_port - attach a driver-defined port structure * @drv: pointer to the uart low level driver structure for this port @@ -2409,8 +2346,7 @@ int uart_add_one_port(struct uart_driver *drv, struct uart_port *uport) * Register the port whether it's detected or not. This allows * setserial to be used to alter this ports parameters. */ - tty_dev = tty_port_register_device_attr(port, drv->tty_driver, - uport->line, uport->dev, port, tty_dev_attr_groups); + tty_dev = tty_register_device(drv->tty_driver, uport->line, uport->dev); if (likely(!IS_ERR(tty_dev))) { device_set_wakeup_capable(tty_dev, 1); } else { @@ -2518,12 +2454,9 @@ void uart_handle_dcd_change(struct uart_port *uport, unsigned int status) { struct uart_state *state = uport->state; struct tty_port *port = &state->port; - struct tty_ldisc *ld = NULL; + struct tty_ldisc *ld = tty_ldisc_ref(port->tty); struct pps_event_time ts; - struct tty_struct *tty = port->tty; - if (tty) - ld = tty_ldisc_ref(tty); if (ld && ld->ops->dcd_change) pps_get_ts(&ts); @@ -2536,12 +2469,12 @@ void uart_handle_dcd_change(struct uart_port *uport, unsigned int status) if (port->flags & ASYNC_CHECK_CD) { if (status) wake_up_interruptible(&port->open_wait); - else if (tty) - tty_hangup(tty); + else if (port->tty) + tty_hangup(port->tty); } if (ld && ld->ops->dcd_change) - ld->ops->dcd_change(tty, status, &ts); + ld->ops->dcd_change(port->tty, status, &ts); if (ld) tty_ldisc_deref(ld); } @@ -2559,7 +2492,7 @@ void uart_handle_cts_change(struct uart_port *uport, unsigned int status) uport->icount.cts++; - if (tty_port_cts_enabled(port)) { + if (port->flags & ASYNC_CTS_FLOW) { if (tty->hw_stopped) { if (status) { tty->hw_stopped = 0; diff --git a/trunk/drivers/tty/serial/sirfsoc_uart.c b/trunk/drivers/tty/serial/sirfsoc_uart.c index a9e2bd1ab534..5b3eda2024fe 100644 --- a/trunk/drivers/tty/serial/sirfsoc_uart.c +++ b/trunk/drivers/tty/serial/sirfsoc_uart.c @@ -668,7 +668,7 @@ int sirfsoc_uart_probe(struct platform_device *pdev) if (res == NULL) { dev_err(&pdev->dev, "Insufficient resources.\n"); ret = -EFAULT; - goto err; + goto irq_err; } port->irq = res->start; @@ -676,7 +676,7 @@ int sirfsoc_uart_probe(struct platform_device *pdev) sirfport->p = pinctrl_get_select_default(&pdev->dev); ret = IS_ERR(sirfport->p); if (ret) - goto err; + goto pin_err; } port->ops = &sirfsoc_uart_ops; @@ -695,6 +695,9 @@ int sirfsoc_uart_probe(struct platform_device *pdev) platform_set_drvdata(pdev, NULL); if (sirfport->hw_flow_ctrl) pinctrl_put(sirfport->p); +pin_err: +irq_err: + devm_iounmap(&pdev->dev, port->membase); err: return ret; } @@ -706,6 +709,7 @@ static int sirfsoc_uart_remove(struct platform_device *pdev) platform_set_drvdata(pdev, NULL); if (sirfport->hw_flow_ctrl) pinctrl_put(sirfport->p); + devm_iounmap(&pdev->dev, port->membase); uart_remove_one_port(&sirfsoc_uart_drv, port); return 0; } diff --git a/trunk/drivers/tty/serial/sunsu.c b/trunk/drivers/tty/serial/sunsu.c index b97913dcdbff..675303b8ed84 100644 --- a/trunk/drivers/tty/serial/sunsu.c +++ b/trunk/drivers/tty/serial/sunsu.c @@ -58,16 +58,10 @@ enum su_type { SU_PORT_NONE, SU_PORT_MS, SU_PORT_KBD, SU_PORT_PORT }; static char *su_typev[] = { "su(???)", "su(mouse)", "su(kbd)", "su(serial)" }; -struct serial_uart_config { - char *name; - int dfl_xmit_fifo_size; - int flags; -}; - /* * Here we define the default xmit fifo size used for each type of UART. */ -static const struct serial_uart_config uart_config[] = { +static const struct serial_uart_config uart_config[PORT_MAX_8250+1] = { { "unknown", 1, 0 }, { "8250", 1, 0 }, { "16450", 1, 0 }, diff --git a/trunk/drivers/tty/synclink.c b/trunk/drivers/tty/synclink.c index 70e3a525bc82..593d40ad0a6b 100644 --- a/trunk/drivers/tty/synclink.c +++ b/trunk/drivers/tty/synclink.c @@ -1359,7 +1359,7 @@ static void mgsl_isr_io_pin( struct mgsl_struct *info ) } } - if (tty_port_cts_enabled(&info->port) && + if ( (info->port.flags & ASYNC_CTS_FLOW) && (status & MISCSTATUS_CTS_LATCHED) ) { if (info->port.tty->hw_stopped) { if (status & MISCSTATUS_CTS) { @@ -1840,22 +1840,22 @@ static void shutdown(struct mgsl_struct * info) usc_DisableInterrupts(info,RECEIVE_DATA + RECEIVE_STATUS + TRANSMIT_DATA + TRANSMIT_STATUS + IO_PIN + MISC ); usc_DisableDmaInterrupts(info,DICR_MASTER + DICR_TRANSMIT + DICR_RECEIVE); - + /* Disable DMAEN (Port 7, Bit 14) */ /* This disconnects the DMA request signal from the ISA bus */ /* on the ISA adapter. This has no effect for the PCI adapter */ usc_OutReg(info, PCR, (u16)((usc_InReg(info, PCR) | BIT15) | BIT14)); - + /* Disable INTEN (Port 6, Bit12) */ /* This disconnects the IRQ request signal to the ISA bus */ /* on the ISA adapter. This has no effect for the PCI adapter */ usc_OutReg(info, PCR, (u16)((usc_InReg(info, PCR) | BIT13) | BIT12)); - - if (!info->port.tty || info->port.tty->termios.c_cflag & HUPCL) { + + if (!info->port.tty || info->port.tty->termios->c_cflag & HUPCL) { info->serial_signals &= ~(SerialSignal_DTR + SerialSignal_RTS); usc_set_serial_signals(info); } - + spin_unlock_irqrestore(&info->irq_spinlock,flags); mgsl_release_resources(info); @@ -1895,7 +1895,7 @@ static void mgsl_program_hw(struct mgsl_struct *info) usc_EnableInterrupts(info, IO_PIN); usc_get_serial_signals(info); - if (info->netcount || info->port.tty->termios.c_cflag & CREAD) + if (info->netcount || info->port.tty->termios->c_cflag & CREAD) usc_start_receiver(info); spin_unlock_irqrestore(&info->irq_spinlock,flags); @@ -1908,14 +1908,14 @@ static void mgsl_change_params(struct mgsl_struct *info) unsigned cflag; int bits_per_char; - if (!info->port.tty) + if (!info->port.tty || !info->port.tty->termios) return; if (debug_level >= DEBUG_LEVEL_INFO) printk("%s(%d):mgsl_change_params(%s)\n", __FILE__,__LINE__, info->device_name ); - cflag = info->port.tty->termios.c_cflag; + cflag = info->port.tty->termios->c_cflag; /* if B0 rate (hangup) specified then negate DTR and RTS */ /* otherwise assert DTR and RTS */ @@ -2367,8 +2367,8 @@ static void mgsl_throttle(struct tty_struct * tty) if (I_IXOFF(tty)) mgsl_send_xchar(tty, STOP_CHAR(tty)); - - if (tty->termios.c_cflag & CRTSCTS) { + + if (tty->termios->c_cflag & CRTSCTS) { spin_lock_irqsave(&info->irq_spinlock,flags); info->serial_signals &= ~SerialSignal_RTS; usc_set_serial_signals(info); @@ -2401,8 +2401,8 @@ static void mgsl_unthrottle(struct tty_struct * tty) else mgsl_send_xchar(tty, START_CHAR(tty)); } - - if (tty->termios.c_cflag & CRTSCTS) { + + if (tty->termios->c_cflag & CRTSCTS) { spin_lock_irqsave(&info->irq_spinlock,flags); info->serial_signals |= SerialSignal_RTS; usc_set_serial_signals(info); @@ -3045,7 +3045,7 @@ static void mgsl_set_termios(struct tty_struct *tty, struct ktermios *old_termio /* Handle transition to B0 status */ if (old_termios->c_cflag & CBAUD && - !(tty->termios.c_cflag & CBAUD)) { + !(tty->termios->c_cflag & CBAUD)) { info->serial_signals &= ~(SerialSignal_RTS + SerialSignal_DTR); spin_lock_irqsave(&info->irq_spinlock,flags); usc_set_serial_signals(info); @@ -3054,9 +3054,9 @@ static void mgsl_set_termios(struct tty_struct *tty, struct ktermios *old_termio /* Handle transition away from B0 status */ if (!(old_termios->c_cflag & CBAUD) && - tty->termios.c_cflag & CBAUD) { + tty->termios->c_cflag & CBAUD) { info->serial_signals |= SerialSignal_DTR; - if (!(tty->termios.c_cflag & CRTSCTS) || + if (!(tty->termios->c_cflag & CRTSCTS) || !test_bit(TTY_THROTTLED, &tty->flags)) { info->serial_signals |= SerialSignal_RTS; } @@ -3067,7 +3067,7 @@ static void mgsl_set_termios(struct tty_struct *tty, struct ktermios *old_termio /* Handle turning off CRTSCTS */ if (old_termios->c_cflag & CRTSCTS && - !(tty->termios.c_cflag & CRTSCTS)) { + !(tty->termios->c_cflag & CRTSCTS)) { tty->hw_stopped = 0; mgsl_start(tty); } @@ -3287,7 +3287,7 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp, return 0; } - if (tty->termios.c_cflag & CLOCAL) + if (tty->termios->c_cflag & CLOCAL) do_clocal = true; /* Wait for carrier detect and the line to become @@ -3313,7 +3313,7 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp, port->blocked_open++; while (1) { - if (tty->termios.c_cflag & CBAUD) + if (tty->termios->c_cflag & CBAUD) tty_port_raise_dtr_rts(port); set_current_state(TASK_INTERRUPTIBLE); @@ -3338,9 +3338,9 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp, printk("%s(%d):block_til_ready blocking on %s count=%d\n", __FILE__,__LINE__, tty->driver->name, port->count ); - tty_unlock(tty); + tty_unlock(); schedule(); - tty_lock(tty); + tty_lock(); } set_current_state(TASK_RUNNING); @@ -3362,29 +3362,6 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp, } /* end of block_til_ready() */ -static int mgsl_install(struct tty_driver *driver, struct tty_struct *tty) -{ - struct mgsl_struct *info; - int line = tty->index; - - /* verify range of specified line number */ - if (line >= mgsl_device_count) { - printk("%s(%d):mgsl_open with invalid line #%d.\n", - __FILE__, __LINE__, line); - return -ENODEV; - } - - /* find the info structure for the specified line */ - info = mgsl_device_list; - while (info && info->line != line) - info = info->next_device; - if (mgsl_paranoia_check(info, tty->name, "mgsl_open")) - return -ENODEV; - tty->driver_data = info; - - return tty_port_install(&info->port, driver, tty); -} - /* mgsl_open() * * Called when a port is opened. Init and enable port. @@ -3397,10 +3374,26 @@ static int mgsl_install(struct tty_driver *driver, struct tty_struct *tty) */ static int mgsl_open(struct tty_struct *tty, struct file * filp) { - struct mgsl_struct *info = tty->driver_data; + struct mgsl_struct *info; + int retval, line; unsigned long flags; - int retval; + /* verify range of specified line number */ + line = tty->index; + if (line >= mgsl_device_count) { + printk("%s(%d):mgsl_open with invalid line #%d.\n", + __FILE__,__LINE__,line); + return -ENODEV; + } + + /* find the info structure for the specified line */ + info = mgsl_device_list; + while(info && info->line != line) + info = info->next_device; + if (mgsl_paranoia_check(info, tty->name, "mgsl_open")) + return -ENODEV; + + tty->driver_data = info; info->port.tty = tty; if (debug_level >= DEBUG_LEVEL_INFO) @@ -4304,7 +4297,6 @@ static struct mgsl_struct* mgsl_allocate_device(void) } /* end of mgsl_allocate_device()*/ static const struct tty_operations mgsl_ops = { - .install = mgsl_install, .open = mgsl_open, .close = mgsl_close, .write = mgsl_write, diff --git a/trunk/drivers/tty/synclink_gt.c b/trunk/drivers/tty/synclink_gt.c index b38e954eedd3..aa1debf97cc7 100644 --- a/trunk/drivers/tty/synclink_gt.c +++ b/trunk/drivers/tty/synclink_gt.c @@ -785,7 +785,7 @@ static void set_termios(struct tty_struct *tty, struct ktermios *old_termios) /* Handle transition to B0 status */ if (old_termios->c_cflag & CBAUD && - !(tty->termios.c_cflag & CBAUD)) { + !(tty->termios->c_cflag & CBAUD)) { info->signals &= ~(SerialSignal_RTS + SerialSignal_DTR); spin_lock_irqsave(&info->lock,flags); set_signals(info); @@ -794,9 +794,9 @@ static void set_termios(struct tty_struct *tty, struct ktermios *old_termios) /* Handle transition away from B0 status */ if (!(old_termios->c_cflag & CBAUD) && - tty->termios.c_cflag & CBAUD) { + tty->termios->c_cflag & CBAUD) { info->signals |= SerialSignal_DTR; - if (!(tty->termios.c_cflag & CRTSCTS) || + if (!(tty->termios->c_cflag & CRTSCTS) || !test_bit(TTY_THROTTLED, &tty->flags)) { info->signals |= SerialSignal_RTS; } @@ -807,7 +807,7 @@ static void set_termios(struct tty_struct *tty, struct ktermios *old_termios) /* Handle turning off CRTSCTS */ if (old_termios->c_cflag & CRTSCTS && - !(tty->termios.c_cflag & CRTSCTS)) { + !(tty->termios->c_cflag & CRTSCTS)) { tty->hw_stopped = 0; tx_release(tty); } @@ -1372,7 +1372,7 @@ static void throttle(struct tty_struct * tty) DBGINFO(("%s throttle\n", info->device_name)); if (I_IXOFF(tty)) send_xchar(tty, STOP_CHAR(tty)); - if (tty->termios.c_cflag & CRTSCTS) { + if (tty->termios->c_cflag & CRTSCTS) { spin_lock_irqsave(&info->lock,flags); info->signals &= ~SerialSignal_RTS; set_signals(info); @@ -1397,7 +1397,7 @@ static void unthrottle(struct tty_struct * tty) else send_xchar(tty, START_CHAR(tty)); } - if (tty->termios.c_cflag & CRTSCTS) { + if (tty->termios->c_cflag & CRTSCTS) { spin_lock_irqsave(&info->lock,flags); info->signals |= SerialSignal_RTS; set_signals(info); @@ -2053,7 +2053,7 @@ static void cts_change(struct slgt_info *info, unsigned short status) wake_up_interruptible(&info->event_wait_q); info->pending_bh |= BH_STATUS; - if (tty_port_cts_enabled(&info->port)) { + if (info->port.flags & ASYNC_CTS_FLOW) { if (info->port.tty) { if (info->port.tty->hw_stopped) { if (info->signals & SerialSignal_CTS) { @@ -2493,7 +2493,7 @@ static void shutdown(struct slgt_info *info) slgt_irq_off(info, IRQ_ALL | IRQ_MASTER); - if (!info->port.tty || info->port.tty->termios.c_cflag & HUPCL) { + if (!info->port.tty || info->port.tty->termios->c_cflag & HUPCL) { info->signals &= ~(SerialSignal_DTR + SerialSignal_RTS); set_signals(info); } @@ -2534,7 +2534,7 @@ static void program_hw(struct slgt_info *info) get_signals(info); if (info->netcount || - (info->port.tty && info->port.tty->termios.c_cflag & CREAD)) + (info->port.tty && info->port.tty->termios->c_cflag & CREAD)) rx_start(info); spin_unlock_irqrestore(&info->lock,flags); @@ -2548,11 +2548,11 @@ static void change_params(struct slgt_info *info) unsigned cflag; int bits_per_char; - if (!info->port.tty) + if (!info->port.tty || !info->port.tty->termios) return; DBGINFO(("%s change_params\n", info->device_name)); - cflag = info->port.tty->termios.c_cflag; + cflag = info->port.tty->termios->c_cflag; /* if B0 rate (hangup) specified then negate DTR and RTS */ /* otherwise assert DTR and RTS */ @@ -3292,7 +3292,7 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, return 0; } - if (tty->termios.c_cflag & CLOCAL) + if (tty->termios->c_cflag & CLOCAL) do_clocal = true; /* Wait for carrier detect and the line to become @@ -3314,7 +3314,7 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, port->blocked_open++; while (1) { - if ((tty->termios.c_cflag & CBAUD)) + if ((tty->termios->c_cflag & CBAUD)) tty_port_raise_dtr_rts(port); set_current_state(TASK_INTERRUPTIBLE); @@ -3336,9 +3336,9 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, } DBGINFO(("%s block_til_ready wait\n", tty->driver->name)); - tty_unlock(tty); + tty_unlock(); schedule(); - tty_lock(tty); + tty_lock(); } set_current_state(TASK_RUNNING); @@ -3689,11 +3689,8 @@ static void device_init(int adapter_num, struct pci_dev *pdev) } } - for (i = 0; i < port_count; ++i) { - struct slgt_info *info = port_array[i]; - tty_port_register_device(&info->port, serial_driver, info->line, - &info->pdev->dev); - } + for (i=0; i < port_count; ++i) + tty_register_device(serial_driver, port_array[i]->line, &(port_array[i]->pdev->dev)); } static int __devinit init_one(struct pci_dev *dev, diff --git a/trunk/drivers/tty/synclinkmp.c b/trunk/drivers/tty/synclinkmp.c index f17d9f3d84a2..a3dddc12d2fe 100644 --- a/trunk/drivers/tty/synclinkmp.c +++ b/trunk/drivers/tty/synclinkmp.c @@ -711,11 +711,15 @@ static void ldisc_receive_buf(struct tty_struct *tty, /* tty callbacks */ -static int install(struct tty_driver *driver, struct tty_struct *tty) +/* Called when a port is opened. Init and enable port. + */ +static int open(struct tty_struct *tty, struct file *filp) { SLMP_INFO *info; - int line = tty->index; + int retval, line; + unsigned long flags; + line = tty->index; if (line >= synclinkmp_device_count) { printk("%s(%d): open with invalid line #%d.\n", __FILE__,__LINE__,line); @@ -723,30 +727,17 @@ static int install(struct tty_driver *driver, struct tty_struct *tty) } info = synclinkmp_device_list; - while (info && info->line != line) + while(info && info->line != line) info = info->next_device; if (sanity_check(info, tty->name, "open")) return -ENODEV; - if (info->init_error) { + if ( info->init_error ) { printk("%s(%d):%s device is not allocated, init error=%d\n", - __FILE__, __LINE__, info->device_name, - info->init_error); + __FILE__,__LINE__,info->device_name,info->init_error); return -ENODEV; } tty->driver_data = info; - - return tty_port_install(&info->port, driver, tty); -} - -/* Called when a port is opened. Init and enable port. - */ -static int open(struct tty_struct *tty, struct file *filp) -{ - SLMP_INFO *info = tty->driver_data; - unsigned long flags; - int retval; - info->port.tty = tty; if (debug_level >= DEBUG_LEVEL_INFO) @@ -882,7 +873,7 @@ static void set_termios(struct tty_struct *tty, struct ktermios *old_termios) /* Handle transition to B0 status */ if (old_termios->c_cflag & CBAUD && - !(tty->termios.c_cflag & CBAUD)) { + !(tty->termios->c_cflag & CBAUD)) { info->serial_signals &= ~(SerialSignal_RTS + SerialSignal_DTR); spin_lock_irqsave(&info->lock,flags); set_signals(info); @@ -891,9 +882,9 @@ static void set_termios(struct tty_struct *tty, struct ktermios *old_termios) /* Handle transition away from B0 status */ if (!(old_termios->c_cflag & CBAUD) && - tty->termios.c_cflag & CBAUD) { + tty->termios->c_cflag & CBAUD) { info->serial_signals |= SerialSignal_DTR; - if (!(tty->termios.c_cflag & CRTSCTS) || + if (!(tty->termios->c_cflag & CRTSCTS) || !test_bit(TTY_THROTTLED, &tty->flags)) { info->serial_signals |= SerialSignal_RTS; } @@ -904,7 +895,7 @@ static void set_termios(struct tty_struct *tty, struct ktermios *old_termios) /* Handle turning off CRTSCTS */ if (old_termios->c_cflag & CRTSCTS && - !(tty->termios.c_cflag & CRTSCTS)) { + !(tty->termios->c_cflag & CRTSCTS)) { tty->hw_stopped = 0; tx_release(tty); } @@ -1482,7 +1473,7 @@ static void throttle(struct tty_struct * tty) if (I_IXOFF(tty)) send_xchar(tty, STOP_CHAR(tty)); - if (tty->termios.c_cflag & CRTSCTS) { + if (tty->termios->c_cflag & CRTSCTS) { spin_lock_irqsave(&info->lock,flags); info->serial_signals &= ~SerialSignal_RTS; set_signals(info); @@ -1511,7 +1502,7 @@ static void unthrottle(struct tty_struct * tty) send_xchar(tty, START_CHAR(tty)); } - if (tty->termios.c_cflag & CRTSCTS) { + if (tty->termios->c_cflag & CRTSCTS) { spin_lock_irqsave(&info->lock,flags); info->serial_signals |= SerialSignal_RTS; set_signals(info); @@ -2500,7 +2491,7 @@ static void isr_io_pin( SLMP_INFO *info, u16 status ) } } - if (tty_port_cts_enabled(&info->port) && + if ( (info->port.flags & ASYNC_CTS_FLOW) && (status & MISCSTATUS_CTS_LATCHED) ) { if ( info->port.tty ) { if (info->port.tty->hw_stopped) { @@ -2717,7 +2708,7 @@ static void shutdown(SLMP_INFO * info) reset_port(info); - if (!info->port.tty || info->port.tty->termios.c_cflag & HUPCL) { + if (!info->port.tty || info->port.tty->termios->c_cflag & HUPCL) { info->serial_signals &= ~(SerialSignal_DTR + SerialSignal_RTS); set_signals(info); } @@ -2758,7 +2749,7 @@ static void program_hw(SLMP_INFO *info) get_signals(info); - if (info->netcount || (info->port.tty && info->port.tty->termios.c_cflag & CREAD) ) + if (info->netcount || (info->port.tty && info->port.tty->termios->c_cflag & CREAD) ) rx_start(info); spin_unlock_irqrestore(&info->lock,flags); @@ -2771,14 +2762,14 @@ static void change_params(SLMP_INFO *info) unsigned cflag; int bits_per_char; - if (!info->port.tty) + if (!info->port.tty || !info->port.tty->termios) return; if (debug_level >= DEBUG_LEVEL_INFO) printk("%s(%d):%s change_params()\n", __FILE__,__LINE__, info->device_name ); - cflag = info->port.tty->termios.c_cflag; + cflag = info->port.tty->termios->c_cflag; /* if B0 rate (hangup) specified then negate DTR and RTS */ /* otherwise assert DTR and RTS */ @@ -3315,7 +3306,7 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, return 0; } - if (tty->termios.c_cflag & CLOCAL) + if (tty->termios->c_cflag & CLOCAL) do_clocal = true; /* Wait for carrier detect and the line to become @@ -3341,7 +3332,7 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, port->blocked_open++; while (1) { - if (tty->termios.c_cflag & CBAUD) + if (tty->termios->c_cflag & CBAUD) tty_port_raise_dtr_rts(port); set_current_state(TASK_INTERRUPTIBLE); @@ -3366,9 +3357,9 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, printk("%s(%d):%s block_til_ready() count=%d\n", __FILE__,__LINE__, tty->driver->name, port->count ); - tty_unlock(tty); + tty_unlock(); schedule(); - tty_lock(tty); + tty_lock(); } set_current_state(TASK_RUNNING); @@ -3890,7 +3881,6 @@ static void device_init(int adapter_num, struct pci_dev *pdev) } static const struct tty_operations ops = { - .install = install, .open = open, .close = close, .write = write, diff --git a/trunk/drivers/tty/tty_io.c b/trunk/drivers/tty/tty_io.c index 8a5a8b064616..b425c79675ad 100644 --- a/trunk/drivers/tty/tty_io.c +++ b/trunk/drivers/tty/tty_io.c @@ -181,13 +181,10 @@ struct tty_struct *alloc_tty_struct(void) void free_tty_struct(struct tty_struct *tty) { - if (!tty) - return; if (tty->dev) put_device(tty->dev); kfree(tty->write_buf); tty_buffer_free_all(tty); - tty->magic = 0xDEADDEAD; kfree(tty); } @@ -576,7 +573,7 @@ void __tty_hangup(struct tty_struct *tty) } spin_unlock(&redirect_lock); - tty_lock(tty); + tty_lock(); /* some functions below drop BTM, so we need this bit */ set_bit(TTY_HUPPING, &tty->flags); @@ -669,7 +666,7 @@ void __tty_hangup(struct tty_struct *tty) clear_bit(TTY_HUPPING, &tty->flags); tty_ldisc_enable(tty); - tty_unlock(tty); + tty_unlock(); if (f) fput(f); @@ -1106,12 +1103,12 @@ void tty_write_message(struct tty_struct *tty, char *msg) { if (tty) { mutex_lock(&tty->atomic_write_lock); - tty_lock(tty); + tty_lock(); if (tty->ops->write && !test_bit(TTY_CLOSING, &tty->flags)) { - tty_unlock(tty); + tty_unlock(); tty->ops->write(tty, msg, strlen(msg)); } else - tty_unlock(tty); + tty_unlock(); tty_write_unlock(tty); } return; @@ -1216,10 +1213,7 @@ static void pty_line_name(struct tty_driver *driver, int index, char *p) */ static void tty_line_name(struct tty_driver *driver, int index, char *p) { - if (driver->flags & TTY_DRIVER_UNNUMBERED_NODE) - strcpy(p, driver->name); - else - sprintf(p, "%s%d", driver->name, index + driver->name_base); + sprintf(p, "%s%d", driver->name, index + driver->name_base); } /** @@ -1255,19 +1249,21 @@ int tty_init_termios(struct tty_struct *tty) struct ktermios *tp; int idx = tty->index; - if (tty->driver->flags & TTY_DRIVER_RESET_TERMIOS) - tty->termios = tty->driver->init_termios; - else { - /* Check for lazy saved data */ - tp = tty->driver->termios[idx]; - if (tp != NULL) - tty->termios = *tp; - else - tty->termios = tty->driver->init_termios; + tp = tty->driver->termios[idx]; + if (tp == NULL) { + tp = kzalloc(sizeof(struct ktermios[2]), GFP_KERNEL); + if (tp == NULL) + return -ENOMEM; + memcpy(tp, &tty->driver->init_termios, + sizeof(struct ktermios)); + tty->driver->termios[idx] = tp; } + tty->termios = tp; + tty->termios_locked = tp + 1; + /* Compatibility until drivers always set this */ - tty->termios.c_ispeed = tty_termios_input_baud_rate(&tty->termios); - tty->termios.c_ospeed = tty_termios_baud_rate(&tty->termios); + tty->termios->c_ispeed = tty_termios_input_baud_rate(tty->termios); + tty->termios->c_ospeed = tty_termios_baud_rate(tty->termios); return 0; } EXPORT_SYMBOL_GPL(tty_init_termios); @@ -1407,18 +1403,10 @@ struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx) } initialize_tty_struct(tty, driver, idx); - tty_lock(tty); retval = tty_driver_install_tty(driver, tty); if (retval < 0) goto err_deinit_tty; - if (!tty->port) - tty->port = driver->ports[idx]; - - WARN_RATELIMIT(!tty->port, - "%s: %s driver does not set tty->port. This will crash the kernel later. Fix the driver!\n", - __func__, tty->driver->name); - /* * Structures all installed ... call the ldisc open routines. * If we fail here just call release_tty to clean up. No need @@ -1427,11 +1415,9 @@ struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx) retval = tty_ldisc_setup(tty, tty->link); if (retval) goto err_release_tty; - /* Return the tty locked so that it cannot vanish under the caller */ return tty; err_deinit_tty: - tty_unlock(tty); deinitialize_tty_struct(tty); free_tty_struct(tty); err_module_put: @@ -1440,7 +1426,6 @@ struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx) /* call the tty release_tty routine to clean out this slot */ err_release_tty: - tty_unlock(tty); printk_ratelimited(KERN_INFO "tty_init_dev: ldisc open failed, " "clearing slot %d\n", idx); release_tty(tty, idx); @@ -1451,25 +1436,22 @@ void tty_free_termios(struct tty_struct *tty) { struct ktermios *tp; int idx = tty->index; - - /* If the port is going to reset then it has no termios to save */ - if (tty->driver->flags & TTY_DRIVER_RESET_TERMIOS) - return; - - /* Stash the termios data */ - tp = tty->driver->termios[idx]; - if (tp == NULL) { - tp = kmalloc(sizeof(struct ktermios), GFP_KERNEL); - if (tp == NULL) { - pr_warn("tty: no memory to save termios state.\n"); - return; - } - tty->driver->termios[idx] = tp; + /* Kill this flag and push into drivers for locking etc */ + if (tty->driver->flags & TTY_DRIVER_RESET_TERMIOS) { + /* FIXME: Locking on ->termios array */ + tp = tty->termios; + tty->driver->termios[idx] = NULL; + kfree(tp); } - *tp = tty->termios; } EXPORT_SYMBOL(tty_free_termios); +void tty_shutdown(struct tty_struct *tty) +{ + tty_driver_remove_tty(tty->driver, tty); + tty_free_termios(tty); +} +EXPORT_SYMBOL(tty_shutdown); /** * release_one_tty - release tty structure memory @@ -1480,6 +1462,7 @@ EXPORT_SYMBOL(tty_free_termios); * in use. It also gets called when setup of a device fails. * * Locking: + * tty_mutex - sometimes only * takes the file list lock internally when working on the list * of ttys that the driver keeps. * @@ -1512,6 +1495,11 @@ static void queue_release_one_tty(struct kref *kref) { struct tty_struct *tty = container_of(kref, struct tty_struct, kref); + if (tty->ops->shutdown) + tty->ops->shutdown(tty); + else + tty_shutdown(tty); + /* The hangup queue is now free so we can reuse it rather than waste a chunk of memory for each port */ INIT_WORK(&tty->hangup_work, release_one_tty); @@ -1540,20 +1528,16 @@ EXPORT_SYMBOL(tty_kref_put); * and decrement the refcount of the backing module. * * Locking: - * tty_mutex + * tty_mutex - sometimes only * takes the file list lock internally when working on the list * of ttys that the driver keeps. + * FIXME: should we require tty_mutex is held here ?? * */ static void release_tty(struct tty_struct *tty, int idx) { /* This should always be true but check for the moment */ WARN_ON(tty->index != idx); - WARN_ON(!mutex_is_locked(&tty_mutex)); - if (tty->ops->shutdown) - tty->ops->shutdown(tty); - tty_free_termios(tty); - tty_driver_remove_tty(tty->driver, tty); if (tty->link) tty_kref_put(tty->link); @@ -1588,12 +1572,22 @@ static int tty_release_checks(struct tty_struct *tty, struct tty_struct *o_tty, __func__, idx, tty->name); return -1; } + if (tty->termios != tty->driver->termios[idx]) { + printk(KERN_DEBUG "%s: driver.termios[%d] not termios for (%s)\n", + __func__, idx, tty->name); + return -1; + } if (tty->driver->other) { if (o_tty != tty->driver->other->ttys[idx]) { printk(KERN_DEBUG "%s: other->table[%d] not o_tty for (%s)\n", __func__, idx, tty->name); return -1; } + if (o_tty->termios != tty->driver->other->termios[idx]) { + printk(KERN_DEBUG "%s: other->termios[%d] not o_termios for (%s)\n", + __func__, idx, tty->name); + return -1; + } if (o_tty->link != tty) { printk(KERN_DEBUG "%s: bad pty pointers\n", __func__); return -1; @@ -1634,7 +1628,7 @@ int tty_release(struct inode *inode, struct file *filp) if (tty_paranoia_check(tty, inode, __func__)) return 0; - tty_lock(tty); + tty_lock(); check_tty_count(tty, __func__); __tty_fasync(-1, filp, 0); @@ -1643,11 +1637,10 @@ int tty_release(struct inode *inode, struct file *filp) pty_master = (tty->driver->type == TTY_DRIVER_TYPE_PTY && tty->driver->subtype == PTY_TYPE_MASTER); devpts = (tty->driver->flags & TTY_DRIVER_DEVPTS_MEM) != 0; - /* Review: parallel close */ o_tty = tty->link; if (tty_release_checks(tty, o_tty, idx)) { - tty_unlock(tty); + tty_unlock(); return 0; } @@ -1659,7 +1652,7 @@ int tty_release(struct inode *inode, struct file *filp) if (tty->ops->close) tty->ops->close(tty, filp); - tty_unlock(tty); + tty_unlock(); /* * Sanity check: if tty->count is going to zero, there shouldn't be * any waiters on tty->read_wait or tty->write_wait. We test the @@ -1682,7 +1675,7 @@ int tty_release(struct inode *inode, struct file *filp) opens on /dev/tty */ mutex_lock(&tty_mutex); - tty_lock_pair(tty, o_tty); + tty_lock(); tty_closing = tty->count <= 1; o_tty_closing = o_tty && (o_tty->count <= (pty_master ? 1 : 0)); @@ -1713,7 +1706,7 @@ int tty_release(struct inode *inode, struct file *filp) printk(KERN_WARNING "%s: %s: read/write wait queue active!\n", __func__, tty_name(tty, buf)); - tty_unlock_pair(tty, o_tty); + tty_unlock(); mutex_unlock(&tty_mutex); schedule(); } @@ -1722,9 +1715,6 @@ int tty_release(struct inode *inode, struct file *filp) * The closing flags are now consistent with the open counts on * both sides, and we've completed the last operation that could * block, so it's safe to proceed with closing. - * - * We must *not* drop the tty_mutex until we ensure that a further - * entry into tty_open can not pick up this tty. */ if (pty_master) { if (--o_tty->count < 0) { @@ -1776,13 +1766,12 @@ int tty_release(struct inode *inode, struct file *filp) } mutex_unlock(&tty_mutex); - tty_unlock_pair(tty, o_tty); - /* At this point the TTY_CLOSING flag should ensure a dead tty - cannot be re-opened by a racing opener */ /* check whether both sides are closing ... */ - if (!tty_closing || (o_tty && !o_tty_closing)) + if (!tty_closing || (o_tty && !o_tty_closing)) { + tty_unlock(); return 0; + } #ifdef TTY_DEBUG_HANGUP printk(KERN_DEBUG "%s: freeing tty structure...\n", __func__); @@ -1793,17 +1782,14 @@ int tty_release(struct inode *inode, struct file *filp) tty_ldisc_release(tty, o_tty); /* * The release_tty function takes care of the details of clearing - * the slots and preserving the termios structure. The tty_unlock_pair - * should be safe as we keep a kref while the tty is locked (so the - * unlock never unlocks a freed tty). + * the slots and preserving the termios structure. */ - mutex_lock(&tty_mutex); release_tty(tty, idx); - mutex_unlock(&tty_mutex); /* Make this pty number available for reallocation */ if (devpts) devpts_kill_index(inode, idx); + tty_unlock(); return 0; } @@ -1907,9 +1893,6 @@ static struct tty_driver *tty_lookup_driver(dev_t device, struct file *filp, * Locking: tty_mutex protects tty, tty_lookup_driver and tty_init_dev. * tty->count should protect the rest. * ->siglock protects ->signal/->sighand - * - * Note: the tty_unlock/lock cases without a ref are only safe due to - * tty_mutex */ static int tty_open(struct inode *inode, struct file *filp) @@ -1933,7 +1916,8 @@ static int tty_open(struct inode *inode, struct file *filp) retval = 0; mutex_lock(&tty_mutex); - /* This is protected by the tty_mutex */ + tty_lock(); + tty = tty_open_current_tty(device, filp); if (IS_ERR(tty)) { retval = PTR_ERR(tty); @@ -1954,19 +1938,17 @@ static int tty_open(struct inode *inode, struct file *filp) } if (tty) { - tty_lock(tty); retval = tty_reopen(tty); - if (retval < 0) { - tty_unlock(tty); + if (retval) tty = ERR_PTR(retval); - } - } else /* Returns with the tty_lock held for now */ + } else tty = tty_init_dev(driver, index); mutex_unlock(&tty_mutex); if (driver) tty_driver_kref_put(driver); if (IS_ERR(tty)) { + tty_unlock(); retval = PTR_ERR(tty); goto err_file; } @@ -1995,7 +1977,7 @@ static int tty_open(struct inode *inode, struct file *filp) printk(KERN_DEBUG "%s: error %d in opening %s...\n", __func__, retval, tty->name); #endif - tty_unlock(tty); /* need to call tty_release without BTM */ + tty_unlock(); /* need to call tty_release without BTM */ tty_release(inode, filp); if (retval != -ERESTARTSYS) return retval; @@ -2007,15 +1989,17 @@ static int tty_open(struct inode *inode, struct file *filp) /* * Need to reset f_op in case a hangup happened. */ + tty_lock(); if (filp->f_op == &hung_up_tty_fops) filp->f_op = &tty_fops; + tty_unlock(); goto retry_open; } - tty_unlock(tty); + tty_unlock(); mutex_lock(&tty_mutex); - tty_lock(tty); + tty_lock(); spin_lock_irq(¤t->sighand->siglock); if (!noctty && current->signal->leader && @@ -2023,10 +2007,11 @@ static int tty_open(struct inode *inode, struct file *filp) tty->session == NULL) __proc_set_tty(current, tty); spin_unlock_irq(¤t->sighand->siglock); - tty_unlock(tty); + tty_unlock(); mutex_unlock(&tty_mutex); return 0; err_unlock: + tty_unlock(); mutex_unlock(&tty_mutex); /* after locks to avoid deadlock */ if (!IS_ERR_OR_NULL(driver)) @@ -2109,13 +2094,10 @@ static int __tty_fasync(int fd, struct file *filp, int on) static int tty_fasync(int fd, struct file *filp, int on) { - struct tty_struct *tty = file_tty(filp); int retval; - - tty_lock(tty); + tty_lock(); retval = __tty_fasync(fd, filp, on); - tty_unlock(tty); - + tty_unlock(); return retval; } @@ -2774,7 +2756,7 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg) if (ld->ops->ioctl) { retval = ld->ops->ioctl(tty, file, cmd, arg); if (retval == -ENOIOCTLCMD) - retval = -ENOTTY; + retval = -EINVAL; } tty_ldisc_deref(ld); return retval; @@ -2952,7 +2934,6 @@ void initialize_tty_struct(struct tty_struct *tty, tty->pgrp = NULL; tty->overrun_time = jiffies; tty_buffer_init(tty); - mutex_init(&tty->legacy_mutex); mutex_init(&tty->termios_mutex); mutex_init(&tty->ldisc_mutex); init_waitqueue_head(&tty->write_wait); @@ -3010,15 +2991,6 @@ EXPORT_SYMBOL_GPL(tty_put_char); struct class *tty_class; -static int tty_cdev_add(struct tty_driver *driver, dev_t dev, - unsigned int index, unsigned int count) -{ - /* init here, since reused cdevs cause crashes */ - cdev_init(&driver->cdevs[index], &tty_fops); - driver->cdevs[index].owner = driver->owner; - return cdev_add(&driver->cdevs[index], dev, count); -} - /** * tty_register_device - register a tty device * @driver: the tty driver that describes the tty device @@ -3040,47 +3012,9 @@ static int tty_cdev_add(struct tty_driver *driver, dev_t dev, struct device *tty_register_device(struct tty_driver *driver, unsigned index, struct device *device) -{ - return tty_register_device_attr(driver, index, device, NULL, NULL); -} -EXPORT_SYMBOL(tty_register_device); - -static void tty_device_create_release(struct device *dev) -{ - pr_debug("device: '%s': %s\n", dev_name(dev), __func__); - kfree(dev); -} - -/** - * tty_register_device_attr - register a tty device - * @driver: the tty driver that describes the tty device - * @index: the index in the tty driver for this tty device - * @device: a struct device that is associated with this tty device. - * This field is optional, if there is no known struct device - * for this tty device it can be set to NULL safely. - * @drvdata: Driver data to be set to device. - * @attr_grp: Attribute group to be set on device. - * - * Returns a pointer to the struct device for this tty device - * (or ERR_PTR(-EFOO) on error). - * - * This call is required to be made to register an individual tty device - * if the tty driver's flags have the TTY_DRIVER_DYNAMIC_DEV bit set. If - * that bit is not set, this function should not be called by a tty - * driver. - * - * Locking: ?? - */ -struct device *tty_register_device_attr(struct tty_driver *driver, - unsigned index, struct device *device, - void *drvdata, - const struct attribute_group **attr_grp) { char name[64]; - dev_t devt = MKDEV(driver->major, driver->minor_start) + index; - struct device *dev = NULL; - int retval = -ENODEV; - bool cdev = false; + dev_t dev = MKDEV(driver->major, driver->minor_start) + index; if (index >= driver->num) { printk(KERN_ERR "Attempt to register invalid tty line number " @@ -3093,40 +3027,9 @@ struct device *tty_register_device_attr(struct tty_driver *driver, else tty_line_name(driver, index, name); - if (!(driver->flags & TTY_DRIVER_DYNAMIC_ALLOC)) { - retval = tty_cdev_add(driver, devt, index, 1); - if (retval) - goto error; - cdev = true; - } - - dev = kzalloc(sizeof(*dev), GFP_KERNEL); - if (!dev) { - retval = -ENOMEM; - goto error; - } - - dev->devt = devt; - dev->class = tty_class; - dev->parent = device; - dev->release = tty_device_create_release; - dev_set_name(dev, "%s", name); - dev->groups = attr_grp; - dev_set_drvdata(dev, drvdata); - - retval = device_register(dev); - if (retval) - goto error; - - return dev; - -error: - put_device(dev); - if (cdev) - cdev_del(&driver->cdevs[index]); - return ERR_PTR(retval); + return device_create(tty_class, device, dev, NULL, name); } -EXPORT_SYMBOL_GPL(tty_register_device_attr); +EXPORT_SYMBOL(tty_register_device); /** * tty_unregister_device - unregister a tty device @@ -3143,82 +3046,31 @@ void tty_unregister_device(struct tty_driver *driver, unsigned index) { device_destroy(tty_class, MKDEV(driver->major, driver->minor_start) + index); - if (!(driver->flags & TTY_DRIVER_DYNAMIC_ALLOC)) - cdev_del(&driver->cdevs[index]); } EXPORT_SYMBOL(tty_unregister_device); -/** - * __tty_alloc_driver -- allocate tty driver - * @lines: count of lines this driver can handle at most - * @owner: module which is repsonsible for this driver - * @flags: some of TTY_DRIVER_* flags, will be set in driver->flags - * - * This should not be called directly, some of the provided macros should be - * used instead. Use IS_ERR and friends on @retval. - */ -struct tty_driver *__tty_alloc_driver(unsigned int lines, struct module *owner, - unsigned long flags) +struct tty_driver *__alloc_tty_driver(int lines, struct module *owner) { struct tty_driver *driver; - unsigned int cdevs = 1; - int err; - - if (!lines || (flags & TTY_DRIVER_UNNUMBERED_NODE && lines > 1)) - return ERR_PTR(-EINVAL); driver = kzalloc(sizeof(struct tty_driver), GFP_KERNEL); - if (!driver) - return ERR_PTR(-ENOMEM); - - kref_init(&driver->kref); - driver->magic = TTY_DRIVER_MAGIC; - driver->num = lines; - driver->owner = owner; - driver->flags = flags; - - if (!(flags & TTY_DRIVER_DEVPTS_MEM)) { - driver->ttys = kcalloc(lines, sizeof(*driver->ttys), - GFP_KERNEL); - driver->termios = kcalloc(lines, sizeof(*driver->termios), - GFP_KERNEL); - if (!driver->ttys || !driver->termios) { - err = -ENOMEM; - goto err_free_all; - } + if (driver) { + kref_init(&driver->kref); + driver->magic = TTY_DRIVER_MAGIC; + driver->num = lines; + driver->owner = owner; + /* later we'll move allocation of tables here */ } - - if (!(flags & TTY_DRIVER_DYNAMIC_ALLOC)) { - driver->ports = kcalloc(lines, sizeof(*driver->ports), - GFP_KERNEL); - if (!driver->ports) { - err = -ENOMEM; - goto err_free_all; - } - cdevs = lines; - } - - driver->cdevs = kcalloc(cdevs, sizeof(*driver->cdevs), GFP_KERNEL); - if (!driver->cdevs) { - err = -ENOMEM; - goto err_free_all; - } - return driver; -err_free_all: - kfree(driver->ports); - kfree(driver->ttys); - kfree(driver->termios); - kfree(driver); - return ERR_PTR(err); } -EXPORT_SYMBOL(__tty_alloc_driver); +EXPORT_SYMBOL(__alloc_tty_driver); static void destruct_tty_driver(struct kref *kref) { struct tty_driver *driver = container_of(kref, struct tty_driver, kref); int i; struct ktermios *tp; + void *p; if (driver->flags & TTY_DRIVER_INSTALLED) { /* @@ -3235,14 +3087,13 @@ static void destruct_tty_driver(struct kref *kref) if (!(driver->flags & TTY_DRIVER_DYNAMIC_DEV)) tty_unregister_device(driver, i); } + p = driver->ttys; proc_tty_unregister_driver(driver); - if (driver->flags & TTY_DRIVER_DYNAMIC_ALLOC) - cdev_del(&driver->cdevs[0]); + driver->ttys = NULL; + driver->termios = NULL; + kfree(p); + cdev_del(&driver->cdev); } - kfree(driver->cdevs); - kfree(driver->ports); - kfree(driver->termios); - kfree(driver->ttys); kfree(driver); } @@ -3273,8 +3124,15 @@ int tty_register_driver(struct tty_driver *driver) int error; int i; dev_t dev; + void **p = NULL; struct device *d; + if (!(driver->flags & TTY_DRIVER_DEVPTS_MEM) && driver->num) { + p = kzalloc(driver->num * 2 * sizeof(void *), GFP_KERNEL); + if (!p) + return -ENOMEM; + } + if (!driver->major) { error = alloc_chrdev_region(&dev, driver->minor_start, driver->num, driver->name); @@ -3286,13 +3144,28 @@ int tty_register_driver(struct tty_driver *driver) dev = MKDEV(driver->major, driver->minor_start); error = register_chrdev_region(dev, driver->num, driver->name); } - if (error < 0) - goto err; + if (error < 0) { + kfree(p); + return error; + } - if (driver->flags & TTY_DRIVER_DYNAMIC_ALLOC) { - error = tty_cdev_add(driver, dev, 0, driver->num); - if (error) - goto err_unreg_char; + if (p) { + driver->ttys = (struct tty_struct **)p; + driver->termios = (struct ktermios **)(p + driver->num); + } else { + driver->ttys = NULL; + driver->termios = NULL; + } + + cdev_init(&driver->cdev, &tty_fops); + driver->cdev.owner = driver->owner; + error = cdev_add(&driver->cdev, dev, driver->num); + if (error) { + unregister_chrdev_region(dev, driver->num); + driver->ttys = NULL; + driver->termios = NULL; + kfree(p); + return error; } mutex_lock(&tty_mutex); @@ -3304,7 +3177,7 @@ int tty_register_driver(struct tty_driver *driver) d = tty_register_device(driver, i, NULL); if (IS_ERR(d)) { error = PTR_ERR(d); - goto err_unreg_devs; + goto err; } } } @@ -3312,7 +3185,7 @@ int tty_register_driver(struct tty_driver *driver) driver->flags |= TTY_DRIVER_INSTALLED; return 0; -err_unreg_devs: +err: for (i--; i >= 0; i--) tty_unregister_device(driver, i); @@ -3320,11 +3193,13 @@ int tty_register_driver(struct tty_driver *driver) list_del(&driver->tty_drivers); mutex_unlock(&tty_mutex); -err_unreg_char: unregister_chrdev_region(dev, driver->num); -err: + driver->ttys = NULL; + driver->termios = NULL; + kfree(p); return error; } + EXPORT_SYMBOL(tty_register_driver); /* diff --git a/trunk/drivers/tty/tty_ioctl.c b/trunk/drivers/tty/tty_ioctl.c index 12b1fa0f4f86..a1b9a2f68567 100644 --- a/trunk/drivers/tty/tty_ioctl.c +++ b/trunk/drivers/tty/tty_ioctl.c @@ -410,7 +410,7 @@ EXPORT_SYMBOL_GPL(tty_termios_encode_baud_rate); void tty_encode_baud_rate(struct tty_struct *tty, speed_t ibaud, speed_t obaud) { - tty_termios_encode_baud_rate(&tty->termios, ibaud, obaud); + tty_termios_encode_baud_rate(tty->termios, ibaud, obaud); } EXPORT_SYMBOL_GPL(tty_encode_baud_rate); @@ -427,7 +427,7 @@ EXPORT_SYMBOL_GPL(tty_encode_baud_rate); speed_t tty_get_baud_rate(struct tty_struct *tty) { - speed_t baud = tty_termios_baud_rate(&tty->termios); + speed_t baud = tty_termios_baud_rate(tty->termios); if (baud == 38400 && tty->alt_speed) { if (!tty->warned) { @@ -509,14 +509,14 @@ int tty_set_termios(struct tty_struct *tty, struct ktermios *new_termios) /* FIXME: we need to decide on some locking/ordering semantics for the set_termios notification eventually */ mutex_lock(&tty->termios_mutex); - old_termios = tty->termios; - tty->termios = *new_termios; - unset_locked_termios(&tty->termios, &old_termios, &tty->termios_locked); + old_termios = *tty->termios; + *tty->termios = *new_termios; + unset_locked_termios(tty->termios, &old_termios, tty->termios_locked); /* See if packet mode change of state. */ if (tty->link && tty->link->packet) { int extproc = (old_termios.c_lflag & EXTPROC) | - (tty->termios.c_lflag & EXTPROC); + (tty->termios->c_lflag & EXTPROC); int old_flow = ((old_termios.c_iflag & IXON) && (old_termios.c_cc[VSTOP] == '\023') && (old_termios.c_cc[VSTART] == '\021')); @@ -542,7 +542,7 @@ int tty_set_termios(struct tty_struct *tty, struct ktermios *new_termios) if (tty->ops->set_termios) (*tty->ops->set_termios)(tty, &old_termios); else - tty_termios_copy_hw(&tty->termios, &old_termios); + tty_termios_copy_hw(tty->termios, &old_termios); ld = tty_ldisc_ref(tty); if (ld != NULL) { @@ -578,7 +578,7 @@ static int set_termios(struct tty_struct *tty, void __user *arg, int opt) return retval; mutex_lock(&tty->termios_mutex); - tmp_termios = tty->termios; + memcpy(&tmp_termios, tty->termios, sizeof(struct ktermios)); mutex_unlock(&tty->termios_mutex); if (opt & TERMIOS_TERMIO) { @@ -632,14 +632,14 @@ static int set_termios(struct tty_struct *tty, void __user *arg, int opt) static void copy_termios(struct tty_struct *tty, struct ktermios *kterm) { mutex_lock(&tty->termios_mutex); - *kterm = tty->termios; + memcpy(kterm, tty->termios, sizeof(struct ktermios)); mutex_unlock(&tty->termios_mutex); } static void copy_termios_locked(struct tty_struct *tty, struct ktermios *kterm) { mutex_lock(&tty->termios_mutex); - *kterm = tty->termios_locked; + memcpy(kterm, tty->termios_locked, sizeof(struct ktermios)); mutex_unlock(&tty->termios_mutex); } @@ -707,16 +707,16 @@ static int get_sgflags(struct tty_struct *tty) { int flags = 0; - if (!(tty->termios.c_lflag & ICANON)) { - if (tty->termios.c_lflag & ISIG) + if (!(tty->termios->c_lflag & ICANON)) { + if (tty->termios->c_lflag & ISIG) flags |= 0x02; /* cbreak */ else flags |= 0x20; /* raw */ } - if (tty->termios.c_lflag & ECHO) + if (tty->termios->c_lflag & ECHO) flags |= 0x08; /* echo */ - if (tty->termios.c_oflag & OPOST) - if (tty->termios.c_oflag & ONLCR) + if (tty->termios->c_oflag & OPOST) + if (tty->termios->c_oflag & ONLCR) flags |= 0x10; /* crmod */ return flags; } @@ -726,10 +726,10 @@ static int get_sgttyb(struct tty_struct *tty, struct sgttyb __user *sgttyb) struct sgttyb tmp; mutex_lock(&tty->termios_mutex); - tmp.sg_ispeed = tty->termios.c_ispeed; - tmp.sg_ospeed = tty->termios.c_ospeed; - tmp.sg_erase = tty->termios.c_cc[VERASE]; - tmp.sg_kill = tty->termios.c_cc[VKILL]; + tmp.sg_ispeed = tty->termios->c_ispeed; + tmp.sg_ospeed = tty->termios->c_ospeed; + tmp.sg_erase = tty->termios->c_cc[VERASE]; + tmp.sg_kill = tty->termios->c_cc[VKILL]; tmp.sg_flags = get_sgflags(tty); mutex_unlock(&tty->termios_mutex); @@ -787,7 +787,7 @@ static int set_sgttyb(struct tty_struct *tty, struct sgttyb __user *sgttyb) return -EFAULT; mutex_lock(&tty->termios_mutex); - termios = tty->termios; + termios = *tty->termios; termios.c_cc[VERASE] = tmp.sg_erase; termios.c_cc[VKILL] = tmp.sg_kill; set_sgflags(&termios, tmp.sg_flags); @@ -808,12 +808,12 @@ static int get_tchars(struct tty_struct *tty, struct tchars __user *tchars) struct tchars tmp; mutex_lock(&tty->termios_mutex); - tmp.t_intrc = tty->termios.c_cc[VINTR]; - tmp.t_quitc = tty->termios.c_cc[VQUIT]; - tmp.t_startc = tty->termios.c_cc[VSTART]; - tmp.t_stopc = tty->termios.c_cc[VSTOP]; - tmp.t_eofc = tty->termios.c_cc[VEOF]; - tmp.t_brkc = tty->termios.c_cc[VEOL2]; /* what is brkc anyway? */ + tmp.t_intrc = tty->termios->c_cc[VINTR]; + tmp.t_quitc = tty->termios->c_cc[VQUIT]; + tmp.t_startc = tty->termios->c_cc[VSTART]; + tmp.t_stopc = tty->termios->c_cc[VSTOP]; + tmp.t_eofc = tty->termios->c_cc[VEOF]; + tmp.t_brkc = tty->termios->c_cc[VEOL2]; /* what is brkc anyway? */ mutex_unlock(&tty->termios_mutex); return copy_to_user(tchars, &tmp, sizeof(tmp)) ? -EFAULT : 0; } @@ -825,12 +825,12 @@ static int set_tchars(struct tty_struct *tty, struct tchars __user *tchars) if (copy_from_user(&tmp, tchars, sizeof(tmp))) return -EFAULT; mutex_lock(&tty->termios_mutex); - tty->termios.c_cc[VINTR] = tmp.t_intrc; - tty->termios.c_cc[VQUIT] = tmp.t_quitc; - tty->termios.c_cc[VSTART] = tmp.t_startc; - tty->termios.c_cc[VSTOP] = tmp.t_stopc; - tty->termios.c_cc[VEOF] = tmp.t_eofc; - tty->termios.c_cc[VEOL2] = tmp.t_brkc; /* what is brkc anyway? */ + tty->termios->c_cc[VINTR] = tmp.t_intrc; + tty->termios->c_cc[VQUIT] = tmp.t_quitc; + tty->termios->c_cc[VSTART] = tmp.t_startc; + tty->termios->c_cc[VSTOP] = tmp.t_stopc; + tty->termios->c_cc[VEOF] = tmp.t_eofc; + tty->termios->c_cc[VEOL2] = tmp.t_brkc; /* what is brkc anyway? */ mutex_unlock(&tty->termios_mutex); return 0; } @@ -842,14 +842,14 @@ static int get_ltchars(struct tty_struct *tty, struct ltchars __user *ltchars) struct ltchars tmp; mutex_lock(&tty->termios_mutex); - tmp.t_suspc = tty->termios.c_cc[VSUSP]; + tmp.t_suspc = tty->termios->c_cc[VSUSP]; /* what is dsuspc anyway? */ - tmp.t_dsuspc = tty->termios.c_cc[VSUSP]; - tmp.t_rprntc = tty->termios.c_cc[VREPRINT]; + tmp.t_dsuspc = tty->termios->c_cc[VSUSP]; + tmp.t_rprntc = tty->termios->c_cc[VREPRINT]; /* what is flushc anyway? */ - tmp.t_flushc = tty->termios.c_cc[VEOL2]; - tmp.t_werasc = tty->termios.c_cc[VWERASE]; - tmp.t_lnextc = tty->termios.c_cc[VLNEXT]; + tmp.t_flushc = tty->termios->c_cc[VEOL2]; + tmp.t_werasc = tty->termios->c_cc[VWERASE]; + tmp.t_lnextc = tty->termios->c_cc[VLNEXT]; mutex_unlock(&tty->termios_mutex); return copy_to_user(ltchars, &tmp, sizeof(tmp)) ? -EFAULT : 0; } @@ -862,14 +862,14 @@ static int set_ltchars(struct tty_struct *tty, struct ltchars __user *ltchars) return -EFAULT; mutex_lock(&tty->termios_mutex); - tty->termios.c_cc[VSUSP] = tmp.t_suspc; + tty->termios->c_cc[VSUSP] = tmp.t_suspc; /* what is dsuspc anyway? */ - tty->termios.c_cc[VEOL2] = tmp.t_dsuspc; - tty->termios.c_cc[VREPRINT] = tmp.t_rprntc; + tty->termios->c_cc[VEOL2] = tmp.t_dsuspc; + tty->termios->c_cc[VREPRINT] = tmp.t_rprntc; /* what is flushc anyway? */ - tty->termios.c_cc[VEOL2] = tmp.t_flushc; - tty->termios.c_cc[VWERASE] = tmp.t_werasc; - tty->termios.c_cc[VLNEXT] = tmp.t_lnextc; + tty->termios->c_cc[VEOL2] = tmp.t_flushc; + tty->termios->c_cc[VWERASE] = tmp.t_werasc; + tty->termios->c_cc[VLNEXT] = tmp.t_lnextc; mutex_unlock(&tty->termios_mutex); return 0; } @@ -920,12 +920,12 @@ static int tty_change_softcar(struct tty_struct *tty, int arg) struct ktermios old; mutex_lock(&tty->termios_mutex); - old = tty->termios; - tty->termios.c_cflag &= ~CLOCAL; - tty->termios.c_cflag |= bit; + old = *tty->termios; + tty->termios->c_cflag &= ~CLOCAL; + tty->termios->c_cflag |= bit; if (tty->ops->set_termios) tty->ops->set_termios(tty, &old); - if ((tty->termios.c_cflag & CLOCAL) != bit) + if ((tty->termios->c_cflag & CLOCAL) != bit) ret = -EINVAL; mutex_unlock(&tty->termios_mutex); return ret; @@ -1031,7 +1031,7 @@ int tty_mode_ioctl(struct tty_struct *tty, struct file *file, (struct termios __user *) arg)) return -EFAULT; mutex_lock(&real_tty->termios_mutex); - real_tty->termios_locked = kterm; + memcpy(real_tty->termios_locked, &kterm, sizeof(struct ktermios)); mutex_unlock(&real_tty->termios_mutex); return 0; #else @@ -1048,7 +1048,7 @@ int tty_mode_ioctl(struct tty_struct *tty, struct file *file, (struct termios __user *) arg)) return -EFAULT; mutex_lock(&real_tty->termios_mutex); - real_tty->termios_locked = kterm; + memcpy(real_tty->termios_locked, &kterm, sizeof(struct ktermios)); mutex_unlock(&real_tty->termios_mutex); return ret; #endif diff --git a/trunk/drivers/tty/tty_ldisc.c b/trunk/drivers/tty/tty_ldisc.c index 4d7b56268c79..6f99c9959f0c 100644 --- a/trunk/drivers/tty/tty_ldisc.c +++ b/trunk/drivers/tty/tty_ldisc.c @@ -413,7 +413,7 @@ EXPORT_SYMBOL_GPL(tty_ldisc_flush); static void tty_set_termios_ldisc(struct tty_struct *tty, int num) { mutex_lock(&tty->termios_mutex); - tty->termios.c_line = num; + tty->termios->c_line = num; mutex_unlock(&tty->termios_mutex); } @@ -568,7 +568,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) if (IS_ERR(new_ldisc)) return PTR_ERR(new_ldisc); - tty_lock(tty); + tty_lock(); /* * We need to look at the tty locking here for pty/tty pairs * when both sides try to change in parallel. @@ -582,12 +582,12 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) */ if (tty->ldisc->ops->num == ldisc) { - tty_unlock(tty); + tty_unlock(); tty_ldisc_put(new_ldisc); return 0; } - tty_unlock(tty); + tty_unlock(); /* * Problem: What do we do if this blocks ? * We could deadlock here @@ -595,7 +595,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) tty_wait_until_sent(tty, 0); - tty_lock(tty); + tty_lock(); mutex_lock(&tty->ldisc_mutex); /* @@ -605,10 +605,10 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) while (test_bit(TTY_LDISC_CHANGING, &tty->flags)) { mutex_unlock(&tty->ldisc_mutex); - tty_unlock(tty); + tty_unlock(); wait_event(tty_ldisc_wait, test_bit(TTY_LDISC_CHANGING, &tty->flags) == 0); - tty_lock(tty); + tty_lock(); mutex_lock(&tty->ldisc_mutex); } @@ -623,7 +623,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) o_ldisc = tty->ldisc; - tty_unlock(tty); + tty_unlock(); /* * Make sure we don't change while someone holds a * reference to the line discipline. The TTY_LDISC bit @@ -650,7 +650,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) retval = tty_ldisc_wait_idle(tty, 5 * HZ); - tty_lock(tty); + tty_lock(); mutex_lock(&tty->ldisc_mutex); /* handle wait idle failure locked */ @@ -665,7 +665,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) clear_bit(TTY_LDISC_CHANGING, &tty->flags); mutex_unlock(&tty->ldisc_mutex); tty_ldisc_put(new_ldisc); - tty_unlock(tty); + tty_unlock(); return -EIO; } @@ -708,7 +708,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) if (o_work) schedule_work(&o_tty->buf.work); mutex_unlock(&tty->ldisc_mutex); - tty_unlock(tty); + tty_unlock(); return retval; } @@ -722,9 +722,9 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) static void tty_reset_termios(struct tty_struct *tty) { mutex_lock(&tty->termios_mutex); - tty->termios = tty->driver->init_termios; - tty->termios.c_ispeed = tty_termios_input_baud_rate(&tty->termios); - tty->termios.c_ospeed = tty_termios_baud_rate(&tty->termios); + *tty->termios = tty->driver->init_termios; + tty->termios->c_ispeed = tty_termios_input_baud_rate(tty->termios); + tty->termios->c_ospeed = tty_termios_baud_rate(tty->termios); mutex_unlock(&tty->termios_mutex); } @@ -816,11 +816,11 @@ void tty_ldisc_hangup(struct tty_struct *tty) * need to wait for another function taking the BTM */ clear_bit(TTY_LDISC, &tty->flags); - tty_unlock(tty); + tty_unlock(); cancel_work_sync(&tty->buf.work); mutex_unlock(&tty->ldisc_mutex); retry: - tty_lock(tty); + tty_lock(); mutex_lock(&tty->ldisc_mutex); /* At this point we have a closed ldisc and we want to @@ -831,7 +831,7 @@ void tty_ldisc_hangup(struct tty_struct *tty) if (atomic_read(&tty->ldisc->users) != 1) { char cur_n[TASK_COMM_LEN], tty_n[64]; long timeout = 3 * HZ; - tty_unlock(tty); + tty_unlock(); while (tty_ldisc_wait_idle(tty, timeout) == -EBUSY) { timeout = MAX_SCHEDULE_TIMEOUT; @@ -846,7 +846,7 @@ void tty_ldisc_hangup(struct tty_struct *tty) if (reset == 0) { - if (!tty_ldisc_reinit(tty, tty->termios.c_line)) + if (!tty_ldisc_reinit(tty, tty->termios->c_line)) err = tty_ldisc_open(tty, tty->ldisc); else err = 1; @@ -894,23 +894,6 @@ int tty_ldisc_setup(struct tty_struct *tty, struct tty_struct *o_tty) tty_ldisc_enable(tty); return 0; } - -static void tty_ldisc_kill(struct tty_struct *tty) -{ - mutex_lock(&tty->ldisc_mutex); - /* - * Now kill off the ldisc - */ - tty_ldisc_close(tty, tty->ldisc); - tty_ldisc_put(tty->ldisc); - /* Force an oops if we mess this up */ - tty->ldisc = NULL; - - /* Ensure the next open requests the N_TTY ldisc */ - tty_set_termios_ldisc(tty, N_TTY); - mutex_unlock(&tty->ldisc_mutex); -} - /** * tty_ldisc_release - release line discipline * @tty: tty being shut down @@ -929,21 +912,28 @@ void tty_ldisc_release(struct tty_struct *tty, struct tty_struct *o_tty) * race with the set_ldisc code path. */ - tty_lock_pair(tty, o_tty); + tty_unlock(); tty_ldisc_halt(tty); tty_ldisc_flush_works(tty); - if (o_tty) { - tty_ldisc_halt(o_tty); - tty_ldisc_flush_works(o_tty); - } + tty_lock(); - /* This will need doing differently if we need to lock */ - tty_ldisc_kill(tty); + mutex_lock(&tty->ldisc_mutex); + /* + * Now kill off the ldisc + */ + tty_ldisc_close(tty, tty->ldisc); + tty_ldisc_put(tty->ldisc); + /* Force an oops if we mess this up */ + tty->ldisc = NULL; + + /* Ensure the next open requests the N_TTY ldisc */ + tty_set_termios_ldisc(tty, N_TTY); + mutex_unlock(&tty->ldisc_mutex); + /* This will need doing differently if we need to lock */ if (o_tty) - tty_ldisc_kill(o_tty); + tty_ldisc_release(o_tty, NULL); - tty_unlock_pair(tty, o_tty); /* And the memory resources remaining (buffers, termios) will be disposed of when the kref hits zero */ } diff --git a/trunk/drivers/tty/tty_mutex.c b/trunk/drivers/tty/tty_mutex.c index 67feac9e6ebb..9ff986c32a21 100644 --- a/trunk/drivers/tty/tty_mutex.c +++ b/trunk/drivers/tty/tty_mutex.c @@ -4,70 +4,29 @@ #include #include -/* Legacy tty mutex glue */ - -enum { - TTY_MUTEX_NORMAL, - TTY_MUTEX_NESTED, -}; +/* + * The 'big tty mutex' + * + * This mutex is taken and released by tty_lock() and tty_unlock(), + * replacing the older big kernel lock. + * It can no longer be taken recursively, and does not get + * released implicitly while sleeping. + * + * Don't use in new code. + */ +static DEFINE_MUTEX(big_tty_mutex); /* * Getting the big tty mutex. */ - -static void __lockfunc tty_lock_nested(struct tty_struct *tty, - unsigned int subclass) +void __lockfunc tty_lock(void) { - if (tty->magic != TTY_MAGIC) { - printk(KERN_ERR "L Bad %p\n", tty); - WARN_ON(1); - return; - } - tty_kref_get(tty); - mutex_lock_nested(&tty->legacy_mutex, subclass); -} - -void __lockfunc tty_lock(struct tty_struct *tty) -{ - return tty_lock_nested(tty, TTY_MUTEX_NORMAL); + mutex_lock(&big_tty_mutex); } EXPORT_SYMBOL(tty_lock); -void __lockfunc tty_unlock(struct tty_struct *tty) +void __lockfunc tty_unlock(void) { - if (tty->magic != TTY_MAGIC) { - printk(KERN_ERR "U Bad %p\n", tty); - WARN_ON(1); - return; - } - mutex_unlock(&tty->legacy_mutex); - tty_kref_put(tty); + mutex_unlock(&big_tty_mutex); } EXPORT_SYMBOL(tty_unlock); - -/* - * Getting the big tty mutex for a pair of ttys with lock ordering - * On a non pty/tty pair tty2 can be NULL which is just fine. - */ -void __lockfunc tty_lock_pair(struct tty_struct *tty, - struct tty_struct *tty2) -{ - if (tty < tty2) { - tty_lock(tty); - tty_lock_nested(tty2, TTY_MUTEX_NESTED); - } else { - if (tty2 && tty2 != tty) - tty_lock(tty2); - tty_lock_nested(tty, TTY_MUTEX_NESTED); - } -} -EXPORT_SYMBOL(tty_lock_pair); - -void __lockfunc tty_unlock_pair(struct tty_struct *tty, - struct tty_struct *tty2) -{ - tty_unlock(tty); - if (tty2 && tty2 != tty) - tty_unlock(tty2); -} -EXPORT_SYMBOL(tty_unlock_pair); diff --git a/trunk/drivers/tty/tty_port.c b/trunk/drivers/tty/tty_port.c index d7bdd8d0c23f..bf6e238146ae 100644 --- a/trunk/drivers/tty/tty_port.c +++ b/trunk/drivers/tty/tty_port.c @@ -33,70 +33,6 @@ void tty_port_init(struct tty_port *port) } EXPORT_SYMBOL(tty_port_init); -/** - * tty_port_link_device - link tty and tty_port - * @port: tty_port of the device - * @driver: tty_driver for this device - * @index: index of the tty - * - * Provide the tty layer wit ha link from a tty (specified by @index) to a - * tty_port (@port). Use this only if neither tty_port_register_device nor - * tty_port_install is used in the driver. If used, this has to be called before - * tty_register_driver. - */ -void tty_port_link_device(struct tty_port *port, - struct tty_driver *driver, unsigned index) -{ - if (WARN_ON(index >= driver->num)) - return; - driver->ports[index] = port; -} -EXPORT_SYMBOL_GPL(tty_port_link_device); - -/** - * tty_port_register_device - register tty device - * @port: tty_port of the device - * @driver: tty_driver for this device - * @index: index of the tty - * @device: parent if exists, otherwise NULL - * - * It is the same as tty_register_device except the provided @port is linked to - * a concrete tty specified by @index. Use this or tty_port_install (or both). - * Call tty_port_link_device as a last resort. - */ -struct device *tty_port_register_device(struct tty_port *port, - struct tty_driver *driver, unsigned index, - struct device *device) -{ - tty_port_link_device(port, driver, index); - return tty_register_device(driver, index, device); -} -EXPORT_SYMBOL_GPL(tty_port_register_device); - -/** - * tty_port_register_device_attr - register tty device - * @port: tty_port of the device - * @driver: tty_driver for this device - * @index: index of the tty - * @device: parent if exists, otherwise NULL - * @drvdata: Driver data to be set to device. - * @attr_grp: Attribute group to be set on device. - * - * It is the same as tty_register_device_attr except the provided @port is - * linked to a concrete tty specified by @index. Use this or tty_port_install - * (or both). Call tty_port_link_device as a last resort. - */ -struct device *tty_port_register_device_attr(struct tty_port *port, - struct tty_driver *driver, unsigned index, - struct device *device, void *drvdata, - const struct attribute_group **attr_grp) -{ - tty_port_link_device(port, driver, index); - return tty_register_device_attr(driver, index, device, drvdata, - attr_grp); -} -EXPORT_SYMBOL_GPL(tty_port_register_device_attr); - int tty_port_alloc_xmit_buf(struct tty_port *port) { /* We may sleep in get_zeroed_page() */ @@ -294,7 +230,7 @@ int tty_port_block_til_ready(struct tty_port *port, /* block if port is in the process of being closed */ if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING) { - wait_event_interruptible_tty(tty, port->close_wait, + wait_event_interruptible_tty(port->close_wait, !(port->flags & ASYNC_CLOSING)); if (port->flags & ASYNC_HUP_NOTIFY) return -EAGAIN; @@ -310,7 +246,7 @@ int tty_port_block_til_ready(struct tty_port *port, } if (filp->f_flags & O_NONBLOCK) { /* Indicate we are open */ - if (tty->termios.c_cflag & CBAUD) + if (tty->termios->c_cflag & CBAUD) tty_port_raise_dtr_rts(port); port->flags |= ASYNC_NORMAL_ACTIVE; return 0; @@ -334,7 +270,7 @@ int tty_port_block_til_ready(struct tty_port *port, while (1) { /* Indicate we are open */ - if (tty->termios.c_cflag & CBAUD) + if (tty->termios->c_cflag & CBAUD) tty_port_raise_dtr_rts(port); prepare_to_wait(&port->open_wait, &wait, TASK_INTERRUPTIBLE); @@ -360,9 +296,9 @@ int tty_port_block_til_ready(struct tty_port *port, retval = -ERESTARTSYS; break; } - tty_unlock(tty); + tty_unlock(); schedule(); - tty_lock(tty); + tty_lock(); } finish_wait(&port->open_wait, &wait); @@ -433,7 +369,7 @@ int tty_port_close_start(struct tty_port *port, /* Drop DTR/RTS if HUPCL is set. This causes any attached modem to hang up the line */ - if (tty->termios.c_cflag & HUPCL) + if (tty->termios->c_cflag & HUPCL) tty_port_lower_dtr_rts(port); /* Don't call port->drop for the last reference. Callers will want @@ -477,24 +413,6 @@ void tty_port_close(struct tty_port *port, struct tty_struct *tty, } EXPORT_SYMBOL(tty_port_close); -/** - * tty_port_install - generic tty->ops->install handler - * @port: tty_port of the device - * @driver: tty_driver for this device - * @tty: tty to be installed - * - * It is the same as tty_standard_install except the provided @port is linked - * to a concrete tty specified by @tty. Use this or tty_port_register_device - * (or both). Call tty_port_link_device as a last resort. - */ -int tty_port_install(struct tty_port *port, struct tty_driver *driver, - struct tty_struct *tty) -{ - tty->port = port; - return tty_standard_install(driver, tty); -} -EXPORT_SYMBOL_GPL(tty_port_install); - int tty_port_open(struct tty_port *port, struct tty_struct *tty, struct file *filp) { diff --git a/trunk/drivers/tty/vt/keyboard.c b/trunk/drivers/tty/vt/keyboard.c index 681765baef69..48cc6f25cfd3 100644 --- a/trunk/drivers/tty/vt/keyboard.c +++ b/trunk/drivers/tty/vt/keyboard.c @@ -119,7 +119,6 @@ static const int NR_TYPES = ARRAY_SIZE(max_vals); static struct input_handler kbd_handler; static DEFINE_SPINLOCK(kbd_event_lock); -static DEFINE_SPINLOCK(led_lock); static unsigned long key_down[BITS_TO_LONGS(KEY_CNT)]; /* keyboard key bitmap */ static unsigned char shift_down[NR_SHIFT]; /* shift state counters.. */ static bool dead_key_next; @@ -311,7 +310,7 @@ static void put_queue(struct vc_data *vc, int ch) if (tty) { tty_insert_flip_char(tty, ch, 0); - tty_schedule_flip(tty); + con_schedule_flip(tty); } } @@ -326,7 +325,7 @@ static void puts_queue(struct vc_data *vc, char *cp) tty_insert_flip_char(tty, *cp, 0); cp++; } - tty_schedule_flip(tty); + con_schedule_flip(tty); } static void applkey(struct vc_data *vc, int key, char mode) @@ -587,7 +586,7 @@ static void fn_send_intr(struct vc_data *vc) if (!tty) return; tty_insert_flip_char(tty, 0, TTY_BREAK); - tty_schedule_flip(tty); + con_schedule_flip(tty); } static void fn_scroll_forw(struct vc_data *vc) @@ -985,7 +984,7 @@ static void k_brl(struct vc_data *vc, unsigned char value, char up_flag) * or (ii) whatever pattern of lights people want to show using KDSETLED, * or (iii) specified bits of specified words in kernel memory. */ -static unsigned char getledstate(void) +unsigned char getledstate(void) { return ledstate; } @@ -993,7 +992,7 @@ static unsigned char getledstate(void) void setledstate(struct kbd_struct *kbd, unsigned int led) { unsigned long flags; - spin_lock_irqsave(&led_lock, flags); + spin_lock_irqsave(&kbd_event_lock, flags); if (!(led & ~7)) { ledioctl = led; kbd->ledmode = LED_SHOW_IOCTL; @@ -1001,7 +1000,7 @@ void setledstate(struct kbd_struct *kbd, unsigned int led) kbd->ledmode = LED_SHOW_FLAGS; set_leds(); - spin_unlock_irqrestore(&led_lock, flags); + spin_unlock_irqrestore(&kbd_event_lock, flags); } static inline unsigned char getleds(void) @@ -1050,13 +1049,13 @@ static int kbd_update_leds_helper(struct input_handle *handle, void *data) */ int vt_get_leds(int console, int flag) { + unsigned long flags; struct kbd_struct * kbd = kbd_table + console; int ret; - unsigned long flags; - spin_lock_irqsave(&led_lock, flags); + spin_lock_irqsave(&kbd_event_lock, flags); ret = vc_kbd_led(kbd, flag); - spin_unlock_irqrestore(&led_lock, flags); + spin_unlock_irqrestore(&kbd_event_lock, flags); return ret; } @@ -1092,11 +1091,11 @@ void vt_set_led_state(int console, int leds) void vt_kbd_con_start(int console) { struct kbd_struct * kbd = kbd_table + console; - unsigned long flags; - spin_lock_irqsave(&led_lock, flags); +/* unsigned long flags; */ +/* spin_lock_irqsave(&kbd_event_lock, flags); */ clr_vc_kbd_led(kbd, VC_SCROLLOCK); set_leds(); - spin_unlock_irqrestore(&led_lock, flags); +/* spin_unlock_irqrestore(&kbd_event_lock, flags); */ } /** @@ -1105,15 +1104,21 @@ void vt_kbd_con_start(int console) * * Handle console stop. This is a wrapper for the VT layer * so that we can keep kbd knowledge internal + * + * FIXME: We eventually need to hold the kbd lock here to protect + * the LED updating. We can't do it yet because fn_hold calls stop_tty + * and start_tty under the kbd_event_lock, while normal tty paths + * don't hold the lock. We probably need to split out an LED lock + * but not during an -rc release! */ void vt_kbd_con_stop(int console) { struct kbd_struct * kbd = kbd_table + console; - unsigned long flags; - spin_lock_irqsave(&led_lock, flags); +/* unsigned long flags; */ +/* spin_lock_irqsave(&kbd_event_lock, flags); */ set_vc_kbd_led(kbd, VC_SCROLLOCK); set_leds(); - spin_unlock_irqrestore(&led_lock, flags); +/* spin_unlock_irqrestore(&kbd_event_lock, flags); */ } /* @@ -1125,12 +1130,7 @@ void vt_kbd_con_stop(int console) */ static void kbd_bh(unsigned long dummy) { - unsigned char leds; - unsigned long flags; - - spin_lock_irqsave(&led_lock, flags); - leds = getleds(); - spin_unlock_irqrestore(&led_lock, flags); + unsigned char leds = getleds(); if (leds != ledstate) { input_handler_for_each_handle(&kbd_handler, &leds, @@ -2035,11 +2035,11 @@ int vt_do_kdskled(int console, int cmd, unsigned long arg, int perm) return -EPERM; if (arg & ~0x77) return -EINVAL; - spin_lock_irqsave(&led_lock, flags); + spin_lock_irqsave(&kbd_event_lock, flags); kbd->ledflagstate = (arg & 7); kbd->default_ledflagstate = ((arg >> 4) & 7); set_leds(); - spin_unlock_irqrestore(&led_lock, flags); + spin_unlock_irqrestore(&kbd_event_lock, flags); return 0; /* the ioctls below only set the lights, not the functions */ @@ -2134,10 +2134,8 @@ void vt_reset_keyboard(int console) clr_vc_kbd_mode(kbd, VC_CRLF); kbd->lockstate = 0; kbd->slockstate = 0; - spin_lock(&led_lock); kbd->ledmode = LED_SHOW_FLAGS; kbd->ledflagstate = kbd->default_ledflagstate; - spin_unlock(&led_lock); /* do not do set_leds here because this causes an endless tasklet loop when the keyboard hasn't been initialized yet */ spin_unlock_irqrestore(&kbd_event_lock, flags); diff --git a/trunk/drivers/tty/vt/vt.c b/trunk/drivers/tty/vt/vt.c index 999ca63afdef..84cbf298c094 100644 --- a/trunk/drivers/tty/vt/vt.c +++ b/trunk/drivers/tty/vt/vt.c @@ -537,27 +537,45 @@ void complement_pos(struct vc_data *vc, int offset) static void insert_char(struct vc_data *vc, unsigned int nr) { - unsigned short *p = (unsigned short *) vc->vc_pos; + unsigned short *p, *q = (unsigned short *)vc->vc_pos; - scr_memmovew(p + nr, p, vc->vc_cols - vc->vc_x); - scr_memsetw(p, vc->vc_video_erase_char, nr * 2); + p = q + vc->vc_cols - nr - vc->vc_x; + while (--p >= q) + scr_writew(scr_readw(p), p + nr); + scr_memsetw(q, vc->vc_video_erase_char, nr * 2); vc->vc_need_wrap = 0; - if (DO_UPDATE(vc)) - do_update_region(vc, (unsigned long) p, - (vc->vc_cols - vc->vc_x) / 2 + 1); + if (DO_UPDATE(vc)) { + unsigned short oldattr = vc->vc_attr; + vc->vc_sw->con_bmove(vc, vc->vc_y, vc->vc_x, vc->vc_y, vc->vc_x + nr, 1, + vc->vc_cols - vc->vc_x - nr); + vc->vc_attr = vc->vc_video_erase_char >> 8; + while (nr--) + vc->vc_sw->con_putc(vc, vc->vc_video_erase_char, vc->vc_y, vc->vc_x + nr); + vc->vc_attr = oldattr; + } } static void delete_char(struct vc_data *vc, unsigned int nr) { - unsigned short *p = (unsigned short *) vc->vc_pos; + unsigned int i = vc->vc_x; + unsigned short *p = (unsigned short *)vc->vc_pos; - scr_memcpyw(p, p + nr, vc->vc_cols - vc->vc_x - nr); - scr_memsetw(p + vc->vc_cols - vc->vc_x - nr, vc->vc_video_erase_char, - nr * 2); + while (++i <= vc->vc_cols - nr) { + scr_writew(scr_readw(p+nr), p); + p++; + } + scr_memsetw(p, vc->vc_video_erase_char, nr * 2); vc->vc_need_wrap = 0; - if (DO_UPDATE(vc)) - do_update_region(vc, (unsigned long) p, - (vc->vc_cols - vc->vc_x) / 2); + if (DO_UPDATE(vc)) { + unsigned short oldattr = vc->vc_attr; + vc->vc_sw->con_bmove(vc, vc->vc_y, vc->vc_x + nr, vc->vc_y, vc->vc_x, 1, + vc->vc_cols - vc->vc_x - nr); + vc->vc_attr = vc->vc_video_erase_char >> 8; + while (nr--) + vc->vc_sw->con_putc(vc, vc->vc_video_erase_char, vc->vc_y, + vc->vc_cols - 1 - nr); + vc->vc_attr = oldattr; + } } static int softcursor_original; @@ -1154,26 +1172,45 @@ static void csi_J(struct vc_data *vc, int vpar) case 0: /* erase from cursor to end of display */ count = (vc->vc_scr_end - vc->vc_pos) >> 1; start = (unsigned short *)vc->vc_pos; + if (DO_UPDATE(vc)) { + /* do in two stages */ + vc->vc_sw->con_clear(vc, vc->vc_y, vc->vc_x, 1, + vc->vc_cols - vc->vc_x); + vc->vc_sw->con_clear(vc, vc->vc_y + 1, 0, + vc->vc_rows - vc->vc_y - 1, + vc->vc_cols); + } break; case 1: /* erase from start to cursor */ count = ((vc->vc_pos - vc->vc_origin) >> 1) + 1; start = (unsigned short *)vc->vc_origin; + if (DO_UPDATE(vc)) { + /* do in two stages */ + vc->vc_sw->con_clear(vc, 0, 0, vc->vc_y, + vc->vc_cols); + vc->vc_sw->con_clear(vc, vc->vc_y, 0, 1, + vc->vc_x + 1); + } break; case 3: /* erase scroll-back buffer (and whole display) */ scr_memsetw(vc->vc_screenbuf, vc->vc_video_erase_char, vc->vc_screenbuf_size >> 1); set_origin(vc); + if (CON_IS_VISIBLE(vc)) + update_screen(vc); /* fall through */ case 2: /* erase whole display */ count = vc->vc_cols * vc->vc_rows; start = (unsigned short *)vc->vc_origin; + if (DO_UPDATE(vc)) + vc->vc_sw->con_clear(vc, 0, 0, + vc->vc_rows, + vc->vc_cols); break; default: return; } scr_memsetw(start, vc->vc_video_erase_char, 2 * count); - if (DO_UPDATE(vc)) - do_update_region(vc, (unsigned long) start, count); vc->vc_need_wrap = 0; } @@ -1186,22 +1223,29 @@ static void csi_K(struct vc_data *vc, int vpar) case 0: /* erase from cursor to end of line */ count = vc->vc_cols - vc->vc_x; start = (unsigned short *)vc->vc_pos; + if (DO_UPDATE(vc)) + vc->vc_sw->con_clear(vc, vc->vc_y, vc->vc_x, 1, + vc->vc_cols - vc->vc_x); break; case 1: /* erase from start of line to cursor */ start = (unsigned short *)(vc->vc_pos - (vc->vc_x << 1)); count = vc->vc_x + 1; + if (DO_UPDATE(vc)) + vc->vc_sw->con_clear(vc, vc->vc_y, 0, 1, + vc->vc_x + 1); break; case 2: /* erase whole line */ start = (unsigned short *)(vc->vc_pos - (vc->vc_x << 1)); count = vc->vc_cols; + if (DO_UPDATE(vc)) + vc->vc_sw->con_clear(vc, vc->vc_y, 0, 1, + vc->vc_cols); break; default: return; } scr_memsetw(start, vc->vc_video_erase_char, 2 * count); vc->vc_need_wrap = 0; - if (DO_UPDATE(vc)) - do_update_region(vc, (unsigned long) start, count); } static void csi_X(struct vc_data *vc, int vpar) /* erase the following vpar positions */ @@ -1336,7 +1380,7 @@ static void respond_string(const char *p, struct tty_struct *tty) tty_insert_flip_char(tty, *p, 0); p++; } - tty_schedule_flip(tty); + con_schedule_flip(tty); } static void cursor_report(struct vc_data *vc, struct tty_struct *tty) @@ -2748,52 +2792,41 @@ static void con_flush_chars(struct tty_struct *tty) /* * Allocate the console screen memory. */ -static int con_install(struct tty_driver *driver, struct tty_struct *tty) +static int con_open(struct tty_struct *tty, struct file *filp) { unsigned int currcons = tty->index; - struct vc_data *vc; - int ret; + int ret = 0; console_lock(); - ret = vc_allocate(currcons); - if (ret) - goto unlock; + if (tty->driver_data == NULL) { + ret = vc_allocate(currcons); + if (ret == 0) { + struct vc_data *vc = vc_cons[currcons].d; - vc = vc_cons[currcons].d; - - /* Still being freed */ - if (vc->port.tty) { - ret = -ERESTARTSYS; - goto unlock; - } - - ret = tty_port_install(&vc->port, driver, tty); - if (ret) - goto unlock; - - tty->driver_data = vc; - vc->port.tty = tty; + /* Still being freed */ + if (vc->port.tty) { + console_unlock(); + return -ERESTARTSYS; + } + tty->driver_data = vc; + vc->port.tty = tty; - if (!tty->winsize.ws_row && !tty->winsize.ws_col) { - tty->winsize.ws_row = vc_cons[currcons].d->vc_rows; - tty->winsize.ws_col = vc_cons[currcons].d->vc_cols; + if (!tty->winsize.ws_row && !tty->winsize.ws_col) { + tty->winsize.ws_row = vc_cons[currcons].d->vc_rows; + tty->winsize.ws_col = vc_cons[currcons].d->vc_cols; + } + if (vc->vc_utf) + tty->termios->c_iflag |= IUTF8; + else + tty->termios->c_iflag &= ~IUTF8; + console_unlock(); + return ret; + } } - if (vc->vc_utf) - tty->termios.c_iflag |= IUTF8; - else - tty->termios.c_iflag &= ~IUTF8; -unlock: console_unlock(); return ret; } -static int con_open(struct tty_struct *tty, struct file *filp) -{ - /* everything done in install */ - return 0; -} - - static void con_close(struct tty_struct *tty, struct file *filp) { /* Nothing to do - we defer to shutdown */ @@ -2806,6 +2839,7 @@ static void con_shutdown(struct tty_struct *tty) console_lock(); vc->port.tty = NULL; console_unlock(); + tty_shutdown(tty); } static int default_italic_color = 2; // green (ASCII) @@ -2913,7 +2947,6 @@ static int __init con_init(void) console_initcall(con_init); static const struct tty_operations con_ops = { - .install = con_install, .open = con_open, .close = con_close, .write = con_write, diff --git a/trunk/drivers/usb/Kconfig b/trunk/drivers/usb/Kconfig index 7065df6036ca..a7773a3e02b1 100644 --- a/trunk/drivers/usb/Kconfig +++ b/trunk/drivers/usb/Kconfig @@ -13,7 +13,7 @@ config USB_ARCH_HAS_OHCI default y if PXA3xx default y if ARCH_EP93XX default y if ARCH_AT91 - default y if ARCH_PNX4008 + default y if ARCH_PNX4008 && I2C default y if MFD_TC6393XB default y if ARCH_W90X900 default y if ARCH_DAVINCI_DA8XX diff --git a/trunk/drivers/usb/chipidea/Kconfig b/trunk/drivers/usb/chipidea/Kconfig index 47e499c9c0b6..8337fb5d988d 100644 --- a/trunk/drivers/usb/chipidea/Kconfig +++ b/trunk/drivers/usb/chipidea/Kconfig @@ -1,9 +1,9 @@ config USB_CHIPIDEA tristate "ChipIdea Highspeed Dual Role Controller" - depends on USB || USB_GADGET + depends on USB help - Say Y here if your system has a dual role high speed USB - controller based on ChipIdea silicon IP. Currently, only the + Say Y here if your system has a dual role high speed USB + controller based on ChipIdea silicon IP. Currently, only the peripheral mode is supported. When compiled dynamically, the module will be called ci-hdrc.ko. @@ -12,7 +12,7 @@ if USB_CHIPIDEA config USB_CHIPIDEA_UDC bool "ChipIdea device controller" - depends on USB_GADGET=y || USB_GADGET=USB_CHIPIDEA + depends on USB_GADGET select USB_GADGET_DUALSPEED help Say Y here to enable device controller functionality of the @@ -20,7 +20,6 @@ config USB_CHIPIDEA_UDC config USB_CHIPIDEA_HOST bool "ChipIdea host controller" - depends on USB=y || USB=USB_CHIPIDEA select USB_EHCI_ROOT_HUB_TT help Say Y here to enable host controller functionality of the diff --git a/trunk/drivers/usb/chipidea/udc.c b/trunk/drivers/usb/chipidea/udc.c index d214448b677e..c7a032a4f0c5 100644 --- a/trunk/drivers/usb/chipidea/udc.c +++ b/trunk/drivers/usb/chipidea/udc.c @@ -78,7 +78,8 @@ static inline int ep_to_bit(struct ci13xxx *ci, int n) } /** - * hw_device_state: enables/disables interrupts (execute without interruption) + * hw_device_state: enables/disables interrupts & starts/stops device (execute + * without interruption) * @dma: 0 => disable, !0 => enable and set dma engine * * This function returns an error code @@ -90,7 +91,9 @@ static int hw_device_state(struct ci13xxx *ci, u32 dma) /* interrupt, error, port change, reset, sleep/suspend */ hw_write(ci, OP_USBINTR, ~0, USBi_UI|USBi_UEI|USBi_PCI|USBi_URI|USBi_SLI); + hw_write(ci, OP_USBCMD, USBCMD_RS, USBCMD_RS); } else { + hw_write(ci, OP_USBCMD, USBCMD_RS, 0); hw_write(ci, OP_USBINTR, ~0, 0); } return 0; @@ -771,7 +774,10 @@ __acquires(mEp->lock) { struct ci13xxx_req *mReq, *mReqTemp; struct ci13xxx_ep *mEpTemp = mEp; - int retval = 0; + int uninitialized_var(retval); + + if (list_empty(&mEp->qh.queue)) + return -EINVAL; list_for_each_entry_safe(mReq, mReqTemp, &mEp->qh.queue, queue) { @@ -1414,21 +1420,6 @@ static int ci13xxx_vbus_draw(struct usb_gadget *_gadget, unsigned mA) return -ENOTSUPP; } -/* Change Data+ pullup status - * this func is used by usb_gadget_connect/disconnet - */ -static int ci13xxx_pullup(struct usb_gadget *_gadget, int is_on) -{ - struct ci13xxx *ci = container_of(_gadget, struct ci13xxx, gadget); - - if (is_on) - hw_write(ci, OP_USBCMD, USBCMD_RS, USBCMD_RS); - else - hw_write(ci, OP_USBCMD, USBCMD_RS, 0); - - return 0; -} - static int ci13xxx_start(struct usb_gadget *gadget, struct usb_gadget_driver *driver); static int ci13xxx_stop(struct usb_gadget *gadget, @@ -1441,7 +1432,6 @@ static int ci13xxx_stop(struct usb_gadget *gadget, static const struct usb_gadget_ops usb_gadget_ops = { .vbus_session = ci13xxx_vbus_session, .wakeup = ci13xxx_wakeup, - .pullup = ci13xxx_pullup, .vbus_draw = ci13xxx_vbus_draw, .udc_start = ci13xxx_start, .udc_stop = ci13xxx_stop, @@ -1465,12 +1455,7 @@ static int init_eps(struct ci13xxx *ci) mEp->ep.name = mEp->name; mEp->ep.ops = &usb_ep_ops; - /* - * for ep0: maxP defined in desc, for other - * eps, maxP is set by epautoconfig() called - * by gadget layer - */ - mEp->ep.maxpacket = (unsigned short)~0; + mEp->ep.maxpacket = CTRL_PAYLOAD_MAX; INIT_LIST_HEAD(&mEp->qh.queue); mEp->qh.ptr = dma_pool_alloc(ci->qh_pool, GFP_KERNEL, @@ -1490,7 +1475,6 @@ static int init_eps(struct ci13xxx *ci) else ci->ep0in = mEp; - mEp->ep.maxpacket = CTRL_PAYLOAD_MAX; continue; } @@ -1500,17 +1484,6 @@ static int init_eps(struct ci13xxx *ci) return retval; } -static void destroy_eps(struct ci13xxx *ci) -{ - int i; - - for (i = 0; i < ci->hw_ep_max; i++) { - struct ci13xxx_ep *mEp = &ci->ci13xxx_ep[i]; - - dma_pool_free(ci->qh_pool, mEp->qh.ptr, mEp->qh.dma); - } -} - /** * ci13xxx_start: register a gadget driver * @gadget: our gadget @@ -1718,7 +1691,7 @@ static int udc_start(struct ci13xxx *ci) if (ci->platdata->flags & CI13XXX_REQUIRE_TRANSCEIVER) { if (ci->transceiver == NULL) { retval = -ENODEV; - goto destroy_eps; + goto free_pools; } } @@ -1756,7 +1729,7 @@ static int udc_start(struct ci13xxx *ci) remove_trans: if (!IS_ERR_OR_NULL(ci->transceiver)) { - otg_set_peripheral(ci->transceiver->otg, NULL); + otg_set_peripheral(ci->transceiver->otg, &ci->gadget); if (ci->global_phy) usb_put_phy(ci->transceiver); } @@ -1769,8 +1742,6 @@ static int udc_start(struct ci13xxx *ci) put_transceiver: if (!IS_ERR_OR_NULL(ci->transceiver) && ci->global_phy) usb_put_phy(ci->transceiver); -destroy_eps: - destroy_eps(ci); free_pools: dma_pool_destroy(ci->td_pool); free_qh_pool: @@ -1785,12 +1756,18 @@ static int udc_start(struct ci13xxx *ci) */ static void udc_stop(struct ci13xxx *ci) { + int i; + if (ci == NULL) return; usb_del_gadget_udc(&ci->gadget); - destroy_eps(ci); + for (i = 0; i < ci->hw_ep_max; i++) { + struct ci13xxx_ep *mEp = &ci->ci13xxx_ep[i]; + + dma_pool_free(ci->qh_pool, mEp->qh.ptr, mEp->qh.dma); + } dma_pool_destroy(ci->td_pool); dma_pool_destroy(ci->qh_pool); diff --git a/trunk/drivers/usb/class/cdc-acm.c b/trunk/drivers/usb/class/cdc-acm.c index ff7b5a8d501c..56d6bf668488 100644 --- a/trunk/drivers/usb/class/cdc-acm.c +++ b/trunk/drivers/usb/class/cdc-acm.c @@ -826,7 +826,7 @@ static void acm_tty_set_termios(struct tty_struct *tty, struct ktermios *termios_old) { struct acm *acm = tty->driver_data; - struct ktermios *termios = &tty->termios; + struct ktermios *termios = tty->termios; struct usb_cdc_line_coding newline; int newctrl = acm->ctrlout; @@ -1104,8 +1104,7 @@ static int acm_probe(struct usb_interface *intf, } - if (data_interface->cur_altsetting->desc.bNumEndpoints < 2 || - control_interface->cur_altsetting->desc.bNumEndpoints == 0) + if (data_interface->cur_altsetting->desc.bNumEndpoints < 2) return -EINVAL; epctrl = &control_interface->cur_altsetting->endpoint[0].desc; @@ -1299,8 +1298,7 @@ static int acm_probe(struct usb_interface *intf, usb_set_intfdata(data_interface, acm); usb_get_intf(control_interface); - tty_port_register_device(&acm->port, acm_tty_driver, minor, - &control_interface->dev); + tty_register_device(acm_tty_driver, minor, &control_interface->dev); return 0; alloc_fail7: diff --git a/trunk/drivers/usb/class/cdc-wdm.c b/trunk/drivers/usb/class/cdc-wdm.c index 5f0cb417b736..65a55abb791f 100644 --- a/trunk/drivers/usb/class/cdc-wdm.c +++ b/trunk/drivers/usb/class/cdc-wdm.c @@ -109,14 +109,12 @@ static struct usb_driver wdm_driver; /* return intfdata if we own the interface, else look up intf in the list */ static struct wdm_device *wdm_find_device(struct usb_interface *intf) { - struct wdm_device *desc; + struct wdm_device *desc = NULL; spin_lock(&wdm_device_list_lock); list_for_each_entry(desc, &wdm_device_list, device_list) if (desc->intf == intf) - goto found; - desc = NULL; -found: + break; spin_unlock(&wdm_device_list_lock); return desc; @@ -124,14 +122,12 @@ static struct wdm_device *wdm_find_device(struct usb_interface *intf) static struct wdm_device *wdm_find_device_by_minor(int minor) { - struct wdm_device *desc; + struct wdm_device *desc = NULL; spin_lock(&wdm_device_list_lock); list_for_each_entry(desc, &wdm_device_list, device_list) if (desc->intf->minor == minor) - goto found; - desc = NULL; -found: + break; spin_unlock(&wdm_device_list_lock); return desc; diff --git a/trunk/drivers/usb/core/devices.c b/trunk/drivers/usb/core/devices.c index 3440812b4a84..d95696584762 100644 --- a/trunk/drivers/usb/core/devices.c +++ b/trunk/drivers/usb/core/devices.c @@ -624,7 +624,7 @@ static ssize_t usb_device_read(struct file *file, char __user *buf, /* print devices for all busses */ list_for_each_entry(bus, &usb_bus_list, bus_list) { /* recurse through all children of the root hub */ - if (!bus_to_hcd(bus)->rh_registered) + if (!bus->root_hub) continue; usb_lock_device(bus->root_hub); ret = usb_device_dump(&buf, &nbytes, &skip_bytes, ppos, diff --git a/trunk/drivers/usb/core/hcd.c b/trunk/drivers/usb/core/hcd.c index 75ba2091f9b4..bc84106ac057 100644 --- a/trunk/drivers/usb/core/hcd.c +++ b/trunk/drivers/usb/core/hcd.c @@ -1011,7 +1011,10 @@ static int register_root_hub(struct usb_hcd *hcd) if (retval) { dev_err (parent_dev, "can't register root hub for %s, %d\n", dev_name(&usb_dev->dev), retval); - } else { + } + mutex_unlock(&usb_bus_list_lock); + + if (retval == 0) { spin_lock_irq (&hcd_root_hub_lock); hcd->rh_registered = 1; spin_unlock_irq (&hcd_root_hub_lock); @@ -1020,7 +1023,6 @@ static int register_root_hub(struct usb_hcd *hcd) if (HCD_DEAD(hcd)) usb_hc_died (hcd); /* This time clean up */ } - mutex_unlock(&usb_bus_list_lock); return retval; } diff --git a/trunk/drivers/usb/core/quirks.c b/trunk/drivers/usb/core/quirks.c index e77a8e8eaa23..f15501f4c585 100644 --- a/trunk/drivers/usb/core/quirks.c +++ b/trunk/drivers/usb/core/quirks.c @@ -71,10 +71,6 @@ static const struct usb_device_id usb_quirk_list[] = { { USB_DEVICE(0x04b4, 0x0526), .driver_info = USB_QUIRK_CONFIG_INTF_STRINGS }, - /* Microchip Joss Optical infrared touchboard device */ - { USB_DEVICE(0x04d8, 0x000c), .driver_info = - USB_QUIRK_CONFIG_INTF_STRINGS }, - /* Samsung Android phone modem - ID conflict with SPH-I500 */ { USB_DEVICE(0x04e8, 0x6601), .driver_info = USB_QUIRK_CONFIG_INTF_STRINGS }, diff --git a/trunk/drivers/usb/dwc3/core.c b/trunk/drivers/usb/dwc3/core.c index a68ff53124dc..c34452a7304f 100644 --- a/trunk/drivers/usb/dwc3/core.c +++ b/trunk/drivers/usb/dwc3/core.c @@ -436,21 +436,16 @@ static int __devinit dwc3_probe(struct platform_device *pdev) dev_err(dev, "missing IRQ\n"); return -ENODEV; } - dwc->xhci_resources[1].start = res->start; - dwc->xhci_resources[1].end = res->end; - dwc->xhci_resources[1].flags = res->flags; - dwc->xhci_resources[1].name = res->name; + dwc->xhci_resources[1] = *res; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { dev_err(dev, "missing memory resource\n"); return -ENODEV; } - dwc->xhci_resources[0].start = res->start; + dwc->xhci_resources[0] = *res; dwc->xhci_resources[0].end = dwc->xhci_resources[0].start + DWC3_XHCI_REGS_END; - dwc->xhci_resources[0].flags = res->flags; - dwc->xhci_resources[0].name = res->name; /* * Request memory region but exclude xHCI regs, diff --git a/trunk/drivers/usb/dwc3/ep0.c b/trunk/drivers/usb/dwc3/ep0.c index e4d5ca86b9da..9b94886b66e5 100644 --- a/trunk/drivers/usb/dwc3/ep0.c +++ b/trunk/drivers/usb/dwc3/ep0.c @@ -720,6 +720,7 @@ static void dwc3_ep0_complete_data(struct dwc3 *dwc, transferred = min_t(u32, ur->length, transfer_size - length); memcpy(ur->buf, dwc->ep0_bounce, transferred); + dwc->ep0_bounced = false; } else { transferred = ur->length - length; } diff --git a/trunk/drivers/usb/dwc3/gadget.c b/trunk/drivers/usb/dwc3/gadget.c index c2813c2b005a..58fdfad96b4d 100644 --- a/trunk/drivers/usb/dwc3/gadget.c +++ b/trunk/drivers/usb/dwc3/gadget.c @@ -263,11 +263,8 @@ void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req, if (req->request.status == -EINPROGRESS) req->request.status = status; - if (dwc->ep0_bounced && dep->number == 0) - dwc->ep0_bounced = false; - else - usb_gadget_unmap_request(&dwc->gadget, &req->request, - req->direction); + usb_gadget_unmap_request(&dwc->gadget, &req->request, + req->direction); dev_dbg(dwc->dev, "request %p from %s completed %d/%d ===> %d\n", req, dep->name, req->request.actual, @@ -1029,7 +1026,6 @@ static void __dwc3_gadget_start_isoc(struct dwc3 *dwc, if (list_empty(&dep->request_list)) { dev_vdbg(dwc->dev, "ISOC ep %s run out for requests.\n", dep->name); - dep->flags |= DWC3_EP_PENDING_REQUEST; return; } @@ -1093,17 +1089,6 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req) if (dep->flags & DWC3_EP_PENDING_REQUEST) { int ret; - /* - * If xfernotready is already elapsed and it is a case - * of isoc transfer, then issue END TRANSFER, so that - * you can receive xfernotready again and can have - * notion of current microframe. - */ - if (usb_endpoint_xfer_isoc(dep->endpoint.desc)) { - dwc3_stop_active_transfer(dwc, dep->number); - return 0; - } - ret = __dwc3_gadget_kick_transfer(dep, 0, true); if (ret && ret != -EBUSY) { struct dwc3 *dwc = dep->dwc; diff --git a/trunk/drivers/usb/early/ehci-dbgp.c b/trunk/drivers/usb/early/ehci-dbgp.c index 89dcf155d57e..ee0ebacf8227 100644 --- a/trunk/drivers/usb/early/ehci-dbgp.c +++ b/trunk/drivers/usb/early/ehci-dbgp.c @@ -450,7 +450,7 @@ static int dbgp_ehci_startup(void) writel(FLAG_CF, &ehci_regs->configured_flag); /* Wait until the controller is no longer halted */ - loop = 1000; + loop = 10; do { status = readl(&ehci_regs->status); if (!(status & STS_HALT)) diff --git a/trunk/drivers/usb/gadget/at91_udc.c b/trunk/drivers/usb/gadget/at91_udc.c index 1e35963bd4ed..c9e66dfb02e6 100644 --- a/trunk/drivers/usb/gadget/at91_udc.c +++ b/trunk/drivers/usb/gadget/at91_udc.c @@ -475,7 +475,8 @@ static int at91_ep_enable(struct usb_ep *_ep, unsigned long flags; if (!_ep || !ep - || !desc || _ep->name == ep0name + || !desc || ep->ep.desc + || _ep->name == ep0name || desc->bDescriptorType != USB_DT_ENDPOINT || (maxpacket = usb_endpoint_maxp(desc)) == 0 || maxpacket > ep->maxpacket) { @@ -529,6 +530,7 @@ static int at91_ep_enable(struct usb_ep *_ep, tmp |= AT91_UDP_EPEDS; __raw_writel(tmp, ep->creg); + ep->ep.desc = desc; ep->ep.maxpacket = maxpacket; /* @@ -1633,6 +1635,7 @@ static int at91_start(struct usb_gadget *gadget, udc->driver = driver; udc->gadget.dev.driver = &driver->driver; udc->gadget.dev.of_node = udc->pdev->dev.of_node; + dev_set_drvdata(&udc->gadget.dev, &driver->driver); udc->enabled = 1; udc->selfpowered = 1; @@ -1653,6 +1656,7 @@ static int at91_stop(struct usb_gadget *gadget, spin_unlock_irqrestore(&udc->lock, flags); udc->gadget.dev.driver = NULL; + dev_set_drvdata(&udc->gadget.dev, NULL); udc->driver = NULL; DBG("unbound from %s\n", driver->driver.name); diff --git a/trunk/drivers/usb/gadget/dummy_hcd.c b/trunk/drivers/usb/gadget/dummy_hcd.c index afdbb1cbf5d9..b799106027ad 100644 --- a/trunk/drivers/usb/gadget/dummy_hcd.c +++ b/trunk/drivers/usb/gadget/dummy_hcd.c @@ -1916,27 +1916,6 @@ static int dummy_hub_status(struct usb_hcd *hcd, char *buf) return retval; } -/* usb 3.0 root hub device descriptor */ -struct { - struct usb_bos_descriptor bos; - struct usb_ss_cap_descriptor ss_cap; -} __packed usb3_bos_desc = { - - .bos = { - .bLength = USB_DT_BOS_SIZE, - .bDescriptorType = USB_DT_BOS, - .wTotalLength = cpu_to_le16(sizeof(usb3_bos_desc)), - .bNumDeviceCaps = 1, - }, - .ss_cap = { - .bLength = USB_DT_USB_SS_CAP_SIZE, - .bDescriptorType = USB_DT_DEVICE_CAPABILITY, - .bDevCapabilityType = USB_SS_CAP_TYPE, - .wSpeedSupported = cpu_to_le16(USB_5GBPS_OPERATION), - .bFunctionalitySupport = ilog2(USB_5GBPS_OPERATION), - }, -}; - static inline void ss_hub_descriptor(struct usb_hub_descriptor *desc) { @@ -2027,18 +2006,6 @@ static int dummy_hub_control( else hub_descriptor((struct usb_hub_descriptor *) buf); break; - - case DeviceRequest | USB_REQ_GET_DESCRIPTOR: - if (hcd->speed != HCD_USB3) - goto error; - - if ((wValue >> 8) != USB_DT_BOS) - goto error; - - memcpy(buf, &usb3_bos_desc, sizeof(usb3_bos_desc)); - retval = sizeof(usb3_bos_desc); - break; - case GetHubStatus: *(__le32 *) buf = cpu_to_le32(0); break; @@ -2536,8 +2503,10 @@ static int dummy_hcd_probe(struct platform_device *pdev) hs_hcd->has_tt = 1; retval = usb_add_hcd(hs_hcd, 0, 0); - if (retval) - goto put_usb2_hcd; + if (retval != 0) { + usb_put_hcd(hs_hcd); + return retval; + } if (mod_data.is_super_speed) { ss_hcd = usb_create_shared_hcd(&dummy_hcd, &pdev->dev, @@ -2556,8 +2525,6 @@ static int dummy_hcd_probe(struct platform_device *pdev) put_usb3_hcd: usb_put_hcd(ss_hcd); dealloc_usb2_hcd: - usb_remove_hcd(hs_hcd); -put_usb2_hcd: usb_put_hcd(hs_hcd); the_controller.hs_hcd = the_controller.ss_hcd = NULL; return retval; diff --git a/trunk/drivers/usb/gadget/f_fs.c b/trunk/drivers/usb/gadget/f_fs.c index 829aba75a6df..8adc79d1b402 100644 --- a/trunk/drivers/usb/gadget/f_fs.c +++ b/trunk/drivers/usb/gadget/f_fs.c @@ -34,15 +34,11 @@ /* Debugging ****************************************************************/ #ifdef VERBOSE_DEBUG -#ifndef pr_vdebug # define pr_vdebug pr_debug -#endif /* pr_vdebug */ # define ffs_dump_mem(prefix, ptr, len) \ print_hex_dump_bytes(pr_fmt(prefix ": "), DUMP_PREFIX_NONE, ptr, len) #else -#ifndef pr_vdebug # define pr_vdebug(...) do { } while (0) -#endif /* pr_vdebug */ # define ffs_dump_mem(prefix, ptr, len) do { } while (0) #endif /* VERBOSE_DEBUG */ diff --git a/trunk/drivers/usb/gadget/s3c-hsotg.c b/trunk/drivers/usb/gadget/s3c-hsotg.c index 0bb617e1dda2..b13e0bb5f5b8 100644 --- a/trunk/drivers/usb/gadget/s3c-hsotg.c +++ b/trunk/drivers/usb/gadget/s3c-hsotg.c @@ -3599,7 +3599,6 @@ static int __devinit s3c_hsotg_probe(struct platform_device *pdev) if (hsotg->num_of_eps == 0) { dev_err(dev, "wrong number of EPs (zero)\n"); - ret = -EINVAL; goto err_supplies; } @@ -3607,7 +3606,6 @@ static int __devinit s3c_hsotg_probe(struct platform_device *pdev) GFP_KERNEL); if (!eps) { dev_err(dev, "cannot get memory\n"); - ret = -ENOMEM; goto err_supplies; } @@ -3624,7 +3622,6 @@ static int __devinit s3c_hsotg_probe(struct platform_device *pdev) GFP_KERNEL); if (!hsotg->ctrl_req) { dev_err(dev, "failed to allocate ctrl req\n"); - ret = -ENOMEM; goto err_ep_mem; } diff --git a/trunk/drivers/usb/gadget/u_ether.c b/trunk/drivers/usb/gadget/u_ether.c index 0e5230926154..90e82e288eb9 100644 --- a/trunk/drivers/usb/gadget/u_ether.c +++ b/trunk/drivers/usb/gadget/u_ether.c @@ -669,8 +669,6 @@ static int eth_stop(struct net_device *net) spin_lock_irqsave(&dev->lock, flags); if (dev->port_usb) { struct gether *link = dev->port_usb; - const struct usb_endpoint_descriptor *in; - const struct usb_endpoint_descriptor *out; if (link->close) link->close(link); @@ -684,14 +682,10 @@ static int eth_stop(struct net_device *net) * their own pace; the network stack can handle old packets. * For the moment we leave this here, since it works. */ - in = link->in_ep->desc; - out = link->out_ep->desc; usb_ep_disable(link->in_ep); usb_ep_disable(link->out_ep); if (netif_carrier_ok(net)) { DBG(dev, "host still using in/out endpoints\n"); - link->in_ep->desc = in; - link->out_ep->desc = out; usb_ep_enable(link->in_ep); usb_ep_enable(link->out_ep); } diff --git a/trunk/drivers/usb/gadget/u_serial.c b/trunk/drivers/usb/gadget/u_serial.c index f1739526820f..5b3f5fffea92 100644 --- a/trunk/drivers/usb/gadget/u_serial.c +++ b/trunk/drivers/usb/gadget/u_serial.c @@ -132,15 +132,11 @@ static unsigned n_ports; #ifdef VERBOSE_DEBUG -#ifndef pr_vdebug #define pr_vdebug(fmt, arg...) \ pr_debug(fmt, ##arg) -#endif /* pr_vdebug */ #else -#ifndef pr_vdebig #define pr_vdebug(fmt, arg...) \ ({ if (0) pr_debug(fmt, ##arg); }) -#endif /* pr_vdebug */ #endif /*-------------------------------------------------------------------------*/ @@ -1133,8 +1129,7 @@ int gserial_setup(struct usb_gadget *g, unsigned count) for (i = 0; i < count; i++) { struct device *tty_dev; - tty_dev = tty_port_register_device(&ports[i].port->port, - gs_tty_driver, i, &g->dev); + tty_dev = tty_register_device(gs_tty_driver, i, &g->dev); if (IS_ERR(tty_dev)) pr_warning("%s: no classdev for port %d, err %ld\n", __func__, i, PTR_ERR(tty_dev)); diff --git a/trunk/drivers/usb/host/ehci-omap.c b/trunk/drivers/usb/host/ehci-omap.c index d7fe287d0678..bb55eb4a7d48 100644 --- a/trunk/drivers/usb/host/ehci-omap.c +++ b/trunk/drivers/usb/host/ehci-omap.c @@ -56,6 +56,15 @@ #define EHCI_INSNREG05_ULPI_EXTREGADD_SHIFT 8 #define EHCI_INSNREG05_ULPI_WRDATA_SHIFT 0 +/* Errata i693 */ +static struct clk *utmi_p1_fck; +static struct clk *utmi_p2_fck; +static struct clk *xclk60mhsp1_ck; +static struct clk *xclk60mhsp2_ck; +static struct clk *usbhost_p1_fck; +static struct clk *usbhost_p2_fck; +static struct clk *init_60m_fclk; + /*-------------------------------------------------------------------------*/ static const struct hc_driver ehci_omap_hc_driver; @@ -71,6 +80,40 @@ static inline u32 ehci_read(void __iomem *base, u32 reg) return __raw_readl(base + reg); } +/* Erratum i693 workaround sequence */ +static void omap_ehci_erratum_i693(struct ehci_hcd *ehci) +{ + int ret = 0; + + /* Switch to the internal 60 MHz clock */ + ret = clk_set_parent(utmi_p1_fck, init_60m_fclk); + if (ret != 0) + ehci_err(ehci, "init_60m_fclk set parent" + "failed error:%d\n", ret); + + ret = clk_set_parent(utmi_p2_fck, init_60m_fclk); + if (ret != 0) + ehci_err(ehci, "init_60m_fclk set parent" + "failed error:%d\n", ret); + + clk_enable(usbhost_p1_fck); + clk_enable(usbhost_p2_fck); + + /* Wait 1ms and switch back to the external clock */ + mdelay(1); + ret = clk_set_parent(utmi_p1_fck, xclk60mhsp1_ck); + if (ret != 0) + ehci_err(ehci, "xclk60mhsp1_ck set parent" + "failed error:%d\n", ret); + + ret = clk_set_parent(utmi_p2_fck, xclk60mhsp2_ck); + if (ret != 0) + ehci_err(ehci, "xclk60mhsp2_ck set parent" + "failed error:%d\n", ret); + + clk_disable(usbhost_p1_fck); + clk_disable(usbhost_p2_fck); +} static void omap_ehci_soft_phy_reset(struct usb_hcd *hcd, u8 port) { @@ -152,6 +195,50 @@ static int omap_ehci_init(struct usb_hcd *hcd) return rc; } +static int omap_ehci_hub_control( + struct usb_hcd *hcd, + u16 typeReq, + u16 wValue, + u16 wIndex, + char *buf, + u16 wLength +) +{ + struct ehci_hcd *ehci = hcd_to_ehci(hcd); + u32 __iomem *status_reg = &ehci->regs->port_status[ + (wIndex & 0xff) - 1]; + u32 temp; + unsigned long flags; + int retval = 0; + + spin_lock_irqsave(&ehci->lock, flags); + + if (typeReq == SetPortFeature && wValue == USB_PORT_FEAT_SUSPEND) { + temp = ehci_readl(ehci, status_reg); + if ((temp & PORT_PE) == 0 || (temp & PORT_RESET) != 0) { + retval = -EPIPE; + goto done; + } + + temp &= ~PORT_WKCONN_E; + temp |= PORT_WKDISC_E | PORT_WKOC_E; + ehci_writel(ehci, temp | PORT_SUSPEND, status_reg); + + omap_ehci_erratum_i693(ehci); + + set_bit((wIndex & 0xff) - 1, &ehci->suspended_ports); + goto done; + } + + spin_unlock_irqrestore(&ehci->lock, flags); + + /* Handle the hub control events here */ + return ehci_hub_control(hcd, typeReq, wValue, wIndex, buf, wLength); +done: + spin_unlock_irqrestore(&ehci->lock, flags); + return retval; +} + static void disable_put_regulator( struct ehci_hcd_omap_platform_data *pdata) { @@ -264,9 +351,79 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev) goto err_pm_runtime; } + /* get clocks */ + utmi_p1_fck = clk_get(dev, "utmi_p1_gfclk"); + if (IS_ERR(utmi_p1_fck)) { + ret = PTR_ERR(utmi_p1_fck); + dev_err(dev, "utmi_p1_gfclk failed error:%d\n", ret); + goto err_add_hcd; + } + + xclk60mhsp1_ck = clk_get(dev, "xclk60mhsp1_ck"); + if (IS_ERR(xclk60mhsp1_ck)) { + ret = PTR_ERR(xclk60mhsp1_ck); + dev_err(dev, "xclk60mhsp1_ck failed error:%d\n", ret); + goto err_utmi_p1_fck; + } + + utmi_p2_fck = clk_get(dev, "utmi_p2_gfclk"); + if (IS_ERR(utmi_p2_fck)) { + ret = PTR_ERR(utmi_p2_fck); + dev_err(dev, "utmi_p2_gfclk failed error:%d\n", ret); + goto err_xclk60mhsp1_ck; + } + + xclk60mhsp2_ck = clk_get(dev, "xclk60mhsp2_ck"); + if (IS_ERR(xclk60mhsp2_ck)) { + ret = PTR_ERR(xclk60mhsp2_ck); + dev_err(dev, "xclk60mhsp2_ck failed error:%d\n", ret); + goto err_utmi_p2_fck; + } + + usbhost_p1_fck = clk_get(dev, "usb_host_hs_utmi_p1_clk"); + if (IS_ERR(usbhost_p1_fck)) { + ret = PTR_ERR(usbhost_p1_fck); + dev_err(dev, "usbhost_p1_fck failed error:%d\n", ret); + goto err_xclk60mhsp2_ck; + } + + usbhost_p2_fck = clk_get(dev, "usb_host_hs_utmi_p2_clk"); + if (IS_ERR(usbhost_p2_fck)) { + ret = PTR_ERR(usbhost_p2_fck); + dev_err(dev, "usbhost_p2_fck failed error:%d\n", ret); + goto err_usbhost_p1_fck; + } + + init_60m_fclk = clk_get(dev, "init_60m_fclk"); + if (IS_ERR(init_60m_fclk)) { + ret = PTR_ERR(init_60m_fclk); + dev_err(dev, "init_60m_fclk failed error:%d\n", ret); + goto err_usbhost_p2_fck; + } return 0; +err_usbhost_p2_fck: + clk_put(usbhost_p2_fck); + +err_usbhost_p1_fck: + clk_put(usbhost_p1_fck); + +err_xclk60mhsp2_ck: + clk_put(xclk60mhsp2_ck); + +err_utmi_p2_fck: + clk_put(utmi_p2_fck); + +err_xclk60mhsp1_ck: + clk_put(xclk60mhsp1_ck); + +err_utmi_p1_fck: + clk_put(utmi_p1_fck); + +err_add_hcd: + usb_remove_hcd(hcd); + err_pm_runtime: disable_put_regulator(pdata); pm_runtime_put_sync(dev); @@ -297,6 +454,14 @@ static int ehci_hcd_omap_remove(struct platform_device *pdev) iounmap(hcd->regs); usb_put_hcd(hcd); + clk_put(utmi_p1_fck); + clk_put(utmi_p2_fck); + clk_put(xclk60mhsp1_ck); + clk_put(xclk60mhsp2_ck); + clk_put(usbhost_p1_fck); + clk_put(usbhost_p2_fck); + clk_put(init_60m_fclk); + pm_runtime_put_sync(dev); pm_runtime_disable(dev); @@ -367,7 +532,7 @@ static const struct hc_driver ehci_omap_hc_driver = { * root hub support */ .hub_status_data = ehci_hub_status_data, - .hub_control = ehci_hub_control, + .hub_control = omap_ehci_hub_control, .bus_suspend = ehci_bus_suspend, .bus_resume = ehci_bus_resume, diff --git a/trunk/drivers/usb/host/ehci-q.c b/trunk/drivers/usb/host/ehci-q.c index 4b66374bdc8e..9bc39ca460c8 100644 --- a/trunk/drivers/usb/host/ehci-q.c +++ b/trunk/drivers/usb/host/ehci-q.c @@ -128,17 +128,9 @@ qh_refresh (struct ehci_hcd *ehci, struct ehci_qh *qh) else { qtd = list_entry (qh->qtd_list.next, struct ehci_qtd, qtd_list); - /* - * first qtd may already be partially processed. - * If we come here during unlink, the QH overlay region - * might have reference to the just unlinked qtd. The - * qtd is updated in qh_completions(). Update the QH - * overlay here. - */ - if (cpu_to_hc32(ehci, qtd->qtd_dma) == qh->hw->hw_current) { - qh->hw->hw_qtd_next = qtd->hw_next; + /* first qtd may already be partially processed */ + if (cpu_to_hc32(ehci, qtd->qtd_dma) == qh->hw->hw_current) qtd = NULL; - } } if (qtd) diff --git a/trunk/drivers/usb/host/ehci-sead3.c b/trunk/drivers/usb/host/ehci-sead3.c index 0c9e43cfaff5..58c96bd50d22 100644 --- a/trunk/drivers/usb/host/ehci-sead3.c +++ b/trunk/drivers/usb/host/ehci-sead3.c @@ -40,7 +40,7 @@ static int ehci_sead3_setup(struct usb_hcd *hcd) ehci->need_io_watchdog = 0; /* Set burst length to 16 words. */ - ehci_writel(ehci, 0x1010, &ehci->regs->reserved1[1]); + ehci_writel(ehci, 0x1010, &ehci->regs->reserved[1]); return ret; } diff --git a/trunk/drivers/usb/host/ehci-tegra.c b/trunk/drivers/usb/host/ehci-tegra.c index 26dedb30ad0b..950e95efa381 100644 --- a/trunk/drivers/usb/host/ehci-tegra.c +++ b/trunk/drivers/usb/host/ehci-tegra.c @@ -799,12 +799,11 @@ static int tegra_ehci_remove(struct platform_device *pdev) #endif usb_remove_hcd(hcd); + usb_put_hcd(hcd); tegra_usb_phy_close(tegra->phy); iounmap(hcd->regs); - usb_put_hcd(hcd); - clk_disable_unprepare(tegra->clk); clk_put(tegra->clk); diff --git a/trunk/drivers/usb/host/isp1362-hcd.c b/trunk/drivers/usb/host/isp1362-hcd.c index 256326322cfd..2ed112d3e159 100644 --- a/trunk/drivers/usb/host/isp1362-hcd.c +++ b/trunk/drivers/usb/host/isp1362-hcd.c @@ -543,12 +543,12 @@ static void postproc_ep(struct isp1362_hcd *isp1362_hcd, struct isp1362_ep *ep) usb_pipein(urb->pipe) ? "IN" : "OUT", ep->nextpid, short_ok ? "" : "not_", PTD_GET_COUNT(ptd), ep->maxpacket, len); - /* save the data underrun error code for later and - * proceed with the status stage - */ - urb->actual_length += PTD_GET_COUNT(ptd); if (usb_pipecontrol(urb->pipe)) { ep->nextpid = USB_PID_ACK; + /* save the data underrun error code for later and + * proceed with the status stage + */ + urb->actual_length += PTD_GET_COUNT(ptd); BUG_ON(urb->actual_length > urb->transfer_buffer_length); if (urb->status == -EINPROGRESS) diff --git a/trunk/drivers/usb/host/ohci-at91.c b/trunk/drivers/usb/host/ohci-at91.c index 0bf72f943b00..a665b3eaa746 100644 --- a/trunk/drivers/usb/host/ohci-at91.c +++ b/trunk/drivers/usb/host/ohci-at91.c @@ -467,8 +467,7 @@ static irqreturn_t ohci_hcd_at91_overcurrent_irq(int irq, void *data) /* From the GPIO notifying the over-current situation, find * out the corresponding port */ at91_for_each_port(port) { - if (gpio_is_valid(pdata->overcurrent_pin[port]) && - gpio_to_irq(pdata->overcurrent_pin[port]) == irq) { + if (gpio_to_irq(pdata->overcurrent_pin[port]) == irq) { gpio = pdata->overcurrent_pin[port]; break; } @@ -571,16 +570,6 @@ static int __devinit ohci_hcd_at91_drv_probe(struct platform_device *pdev) if (pdata) { at91_for_each_port(i) { - /* - * do not configure PIO if not in relation with - * real USB port on board - */ - if (i >= pdata->ports) { - pdata->vbus_pin[i] = -EINVAL; - pdata->overcurrent_pin[i] = -EINVAL; - break; - } - if (!gpio_is_valid(pdata->vbus_pin[i])) continue; gpio = pdata->vbus_pin[i]; diff --git a/trunk/drivers/usb/host/ohci-omap.c b/trunk/drivers/usb/host/ohci-omap.c index f8b2d91851f7..e7d75d295988 100644 --- a/trunk/drivers/usb/host/ohci-omap.c +++ b/trunk/drivers/usb/host/ohci-omap.c @@ -403,6 +403,8 @@ static int usb_hcd_omap_probe (const struct hc_driver *driver, static inline void usb_hcd_omap_remove (struct usb_hcd *hcd, struct platform_device *pdev) { + struct ohci_hcd *ohci = hcd_to_ohci (hcd); + usb_remove_hcd(hcd); if (!IS_ERR_OR_NULL(hcd->phy)) { (void) otg_set_host(hcd->phy->otg, 0); diff --git a/trunk/drivers/usb/host/ohci-pxa27x.c b/trunk/drivers/usb/host/ohci-pxa27x.c index e1a3cc6d28dc..77f4402aca03 100644 --- a/trunk/drivers/usb/host/ohci-pxa27x.c +++ b/trunk/drivers/usb/host/ohci-pxa27x.c @@ -23,6 +23,8 @@ #include #include #include +#include +#include #include #include #include @@ -272,6 +274,67 @@ static void pxa27x_stop_hc(struct pxa27x_ohci *ohci, struct device *dev) clk_disable_unprepare(ohci->clk); } +#ifdef CONFIG_OF +static const struct of_device_id pxa_ohci_dt_ids[] = { + { .compatible = "marvell,pxa-ohci" }, + { } +}; + +MODULE_DEVICE_TABLE(of, pxa_ohci_dt_ids); + +static u64 pxa_ohci_dma_mask = DMA_BIT_MASK(32); + +static int __devinit ohci_pxa_of_init(struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; + struct pxaohci_platform_data *pdata; + u32 tmp; + + if (!np) + return 0; + + /* Right now device-tree probed devices don't get dma_mask set. + * Since shared usb code relies on it, set it here for now. + * Once we have dma capability bindings this can go away. + */ + if (!pdev->dev.dma_mask) + pdev->dev.dma_mask = &pxa_ohci_dma_mask; + + pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) + return -ENOMEM; + + if (of_get_property(np, "marvell,enable-port1", NULL)) + pdata->flags |= ENABLE_PORT1; + if (of_get_property(np, "marvell,enable-port2", NULL)) + pdata->flags |= ENABLE_PORT2; + if (of_get_property(np, "marvell,enable-port3", NULL)) + pdata->flags |= ENABLE_PORT3; + if (of_get_property(np, "marvell,port-sense-low", NULL)) + pdata->flags |= POWER_SENSE_LOW; + if (of_get_property(np, "marvell,power-control-low", NULL)) + pdata->flags |= POWER_CONTROL_LOW; + if (of_get_property(np, "marvell,no-oc-protection", NULL)) + pdata->flags |= NO_OC_PROTECTION; + if (of_get_property(np, "marvell,oc-mode-perport", NULL)) + pdata->flags |= OC_MODE_PERPORT; + if (!of_property_read_u32(np, "marvell,power-on-delay", &tmp)) + pdata->power_on_delay = tmp; + if (!of_property_read_u32(np, "marvell,port-mode", &tmp)) + pdata->port_mode = tmp; + if (!of_property_read_u32(np, "marvell,power-budget", &tmp)) + pdata->power_budget = tmp; + + pdev->dev.platform_data = pdata; + + return 0; +} +#else +static int __devinit ohci_pxa_of_init(struct platform_device *pdev) +{ + return 0; +} +#endif /*-------------------------------------------------------------------------*/ @@ -297,6 +360,10 @@ int usb_hcd_pxa27x_probe (const struct hc_driver *driver, struct platform_device struct resource *r; struct clk *usb_clk; + retval = ohci_pxa_of_init(pdev); + if (retval) + return retval; + inf = pdev->dev.platform_data; if (!inf) @@ -544,6 +611,7 @@ static struct platform_driver ohci_hcd_pxa27x_driver = { .driver = { .name = "pxa27x-ohci", .owner = THIS_MODULE, + .of_match_table = of_match_ptr(pxa_ohci_dt_ids), #ifdef CONFIG_PM .pm = &ohci_hcd_pxa27x_pm_ops, #endif diff --git a/trunk/drivers/usb/host/pci-quirks.c b/trunk/drivers/usb/host/pci-quirks.c index 966d1484ee79..df0828cb2aa3 100644 --- a/trunk/drivers/usb/host/pci-quirks.c +++ b/trunk/drivers/usb/host/pci-quirks.c @@ -75,9 +75,7 @@ #define NB_PIF0_PWRDOWN_1 0x01100013 #define USB_INTEL_XUSB2PR 0xD0 -#define USB_INTEL_USB2PRM 0xD4 #define USB_INTEL_USB3_PSSEN 0xD8 -#define USB_INTEL_USB3PRM 0xDC static struct amd_chipset_info { struct pci_dev *nb_dev; @@ -774,18 +772,10 @@ void usb_enable_xhci_ports(struct pci_dev *xhci_pdev) return; } - /* Read USB3PRM, the USB 3.0 Port Routing Mask Register - * Indicate the ports that can be changed from OS. - */ - pci_read_config_dword(xhci_pdev, USB_INTEL_USB3PRM, - &ports_available); - - dev_dbg(&xhci_pdev->dev, "Configurable ports to enable SuperSpeed: 0x%x\n", - ports_available); - + ports_available = 0xffffffff; /* Write USB3_PSSEN, the USB 3.0 Port SuperSpeed Enable - * Register, to turn on SuperSpeed terminations for the - * switchable ports. + * Register, to turn on SuperSpeed terminations for all + * available ports. */ pci_write_config_dword(xhci_pdev, USB_INTEL_USB3_PSSEN, cpu_to_le32(ports_available)); @@ -795,16 +785,7 @@ void usb_enable_xhci_ports(struct pci_dev *xhci_pdev) dev_dbg(&xhci_pdev->dev, "USB 3.0 ports that are now enabled " "under xHCI: 0x%x\n", ports_available); - /* Read XUSB2PRM, xHCI USB 2.0 Port Routing Mask Register - * Indicate the USB 2.0 ports to be controlled by the xHCI host. - */ - - pci_read_config_dword(xhci_pdev, USB_INTEL_USB2PRM, - &ports_available); - - dev_dbg(&xhci_pdev->dev, "Configurable USB 2.0 ports to hand over to xCHI: 0x%x\n", - ports_available); - + ports_available = 0xffffffff; /* Write XUSB2PR, the xHC USB 2.0 Port Routing Register, to * switch the USB 2.0 power and data lines over to the xHCI * host. @@ -819,13 +800,6 @@ void usb_enable_xhci_ports(struct pci_dev *xhci_pdev) } EXPORT_SYMBOL_GPL(usb_enable_xhci_ports); -void usb_disable_xhci_ports(struct pci_dev *xhci_pdev) -{ - pci_write_config_dword(xhci_pdev, USB_INTEL_USB3_PSSEN, 0x0); - pci_write_config_dword(xhci_pdev, USB_INTEL_XUSB2PR, 0x0); -} -EXPORT_SYMBOL_GPL(usb_disable_xhci_ports); - /** * PCI Quirks for xHCI. * @@ -841,12 +815,12 @@ static void __devinit quirk_usb_handoff_xhci(struct pci_dev *pdev) void __iomem *op_reg_base; u32 val; int timeout; - int len = pci_resource_len(pdev, 0); if (!mmio_resource_enabled(pdev, 0)) return; - base = ioremap_nocache(pci_resource_start(pdev, 0), len); + base = ioremap_nocache(pci_resource_start(pdev, 0), + pci_resource_len(pdev, 0)); if (base == NULL) return; @@ -856,17 +830,9 @@ static void __devinit quirk_usb_handoff_xhci(struct pci_dev *pdev) */ ext_cap_offset = xhci_find_next_cap_offset(base, XHCI_HCC_PARAMS_OFFSET); do { - if ((ext_cap_offset + sizeof(val)) > len) { - /* We're reading garbage from the controller */ - dev_warn(&pdev->dev, - "xHCI controller failing to respond"); - return; - } - if (!ext_cap_offset) /* We've reached the end of the extended capabilities */ goto hc_init; - val = readl(base + ext_cap_offset); if (XHCI_EXT_CAPS_ID(val) == XHCI_EXT_CAPS_LEGACY) break; @@ -897,10 +863,9 @@ static void __devinit quirk_usb_handoff_xhci(struct pci_dev *pdev) /* Disable any BIOS SMIs and clear all SMI events*/ writel(val, base + ext_cap_offset + XHCI_LEGACY_CONTROL_OFFSET); -hc_init: if (usb_is_intel_switchable_xhci(pdev)) usb_enable_xhci_ports(pdev); - +hc_init: op_reg_base = base + XHCI_HC_LENGTH(readl(base)); /* Wait for the host controller to be ready before writing any diff --git a/trunk/drivers/usb/host/pci-quirks.h b/trunk/drivers/usb/host/pci-quirks.h index 7f69a39163ce..b1002a8ef96f 100644 --- a/trunk/drivers/usb/host/pci-quirks.h +++ b/trunk/drivers/usb/host/pci-quirks.h @@ -10,12 +10,10 @@ void usb_amd_quirk_pll_disable(void); void usb_amd_quirk_pll_enable(void); bool usb_is_intel_switchable_xhci(struct pci_dev *pdev); void usb_enable_xhci_ports(struct pci_dev *xhci_pdev); -void usb_disable_xhci_ports(struct pci_dev *xhci_pdev); #else static inline void usb_amd_quirk_pll_disable(void) {} static inline void usb_amd_quirk_pll_enable(void) {} static inline void usb_amd_dev_put(void) {} -static inline void usb_disable_xhci_ports(struct pci_dev *xhci_pdev) {} #endif /* CONFIG_PCI */ #endif /* __LINUX_USB_PCI_QUIRKS_H */ diff --git a/trunk/drivers/usb/host/xhci-hub.c b/trunk/drivers/usb/host/xhci-hub.c index d5eb357aa5c4..74bfc868b7ad 100644 --- a/trunk/drivers/usb/host/xhci-hub.c +++ b/trunk/drivers/usb/host/xhci-hub.c @@ -493,48 +493,11 @@ static void xhci_hub_report_link_state(u32 *status, u32 status_reg) * when this bit is set. */ pls |= USB_PORT_STAT_CONNECTION; - } else { - /* - * If CAS bit isn't set but the Port is already at - * Compliance Mode, fake a connection so the USB core - * notices the Compliance state and resets the port. - * This resolves an issue generated by the SN65LVPE502CP - * in which sometimes the port enters compliance mode - * caused by a delay on the host-device negotiation. - */ - if (pls == USB_SS_PORT_LS_COMP_MOD) - pls |= USB_PORT_STAT_CONNECTION; } - /* update status field */ *status |= pls; } -/* - * Function for Compliance Mode Quirk. - * - * This Function verifies if all xhc USB3 ports have entered U0, if so, - * the compliance mode timer is deleted. A port won't enter - * compliance mode if it has previously entered U0. - */ -void xhci_del_comp_mod_timer(struct xhci_hcd *xhci, u32 status, u16 wIndex) -{ - u32 all_ports_seen_u0 = ((1 << xhci->num_usb3_ports)-1); - bool port_in_u0 = ((status & PORT_PLS_MASK) == XDEV_U0); - - if (!(xhci->quirks & XHCI_COMP_MODE_QUIRK)) - return; - - if ((xhci->port_status_u0 != all_ports_seen_u0) && port_in_u0) { - xhci->port_status_u0 |= 1 << wIndex; - if (xhci->port_status_u0 == all_ports_seen_u0) { - del_timer_sync(&xhci->comp_mode_recovery_timer); - xhci_dbg(xhci, "All USB3 ports have entered U0 already!\n"); - xhci_dbg(xhci, "Compliance Mode Recovery Timer Deleted.\n"); - } - } -} - int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, u16 wIndex, char *buf, u16 wLength) { @@ -688,11 +651,6 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, /* Update Port Link State for super speed ports*/ if (hcd->speed == HCD_USB3) { xhci_hub_report_link_state(&status, temp); - /* - * Verify if all USB3 Ports Have entered U0 already. - * Delete Compliance Mode Timer if so. - */ - xhci_del_comp_mod_timer(xhci, temp, wIndex); } if (bus_state->port_c_suspend & (1 << wIndex)) status |= 1 << USB_PORT_FEAT_C_SUSPEND; diff --git a/trunk/drivers/usb/host/xhci-pci.c b/trunk/drivers/usb/host/xhci-pci.c index 9bfd4ca1153c..18b231b0c5d3 100644 --- a/trunk/drivers/usb/host/xhci-pci.c +++ b/trunk/drivers/usb/host/xhci-pci.c @@ -94,21 +94,11 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci) xhci->quirks |= XHCI_EP_LIMIT_QUIRK; xhci->limit_active_eps = 64; xhci->quirks |= XHCI_SW_BW_CHECKING; - /* - * PPT desktop boards DH77EB and DH77DF will power back on after - * a few seconds of being shutdown. The fix for this is to - * switch the ports from xHCI to EHCI on shutdown. We can't use - * DMI information to find those particular boards (since each - * vendor will change the board name), so we have to key off all - * PPT chipsets. - */ - xhci->quirks |= XHCI_SPURIOUS_REBOOT; } if (pdev->vendor == PCI_VENDOR_ID_ETRON && pdev->device == PCI_DEVICE_ID_ASROCK_P67) { xhci->quirks |= XHCI_RESET_ON_RESUME; xhci_dbg(xhci, "QUIRK: Resetting on resume\n"); - xhci->quirks |= XHCI_TRUST_TX_LENGTH; } if (pdev->vendor == PCI_VENDOR_ID_VIA) xhci->quirks |= XHCI_RESET_ON_RESUME; diff --git a/trunk/drivers/usb/host/xhci-plat.c b/trunk/drivers/usb/host/xhci-plat.c index df90fe51b4aa..689bc18b051d 100644 --- a/trunk/drivers/usb/host/xhci-plat.c +++ b/trunk/drivers/usb/host/xhci-plat.c @@ -118,7 +118,7 @@ static int xhci_plat_probe(struct platform_device *pdev) goto put_hcd; } - hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len); + hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); if (!hcd->regs) { dev_dbg(&pdev->dev, "error mapping memory\n"); ret = -EFAULT; diff --git a/trunk/drivers/usb/host/xhci-ring.c b/trunk/drivers/usb/host/xhci-ring.c index 643c2f3f3e73..8275645889da 100644 --- a/trunk/drivers/usb/host/xhci-ring.c +++ b/trunk/drivers/usb/host/xhci-ring.c @@ -145,37 +145,29 @@ static void next_trb(struct xhci_hcd *xhci, */ static void inc_deq(struct xhci_hcd *xhci, struct xhci_ring *ring) { + union xhci_trb *next; unsigned long long addr; ring->deq_updates++; - /* - * If this is not event ring, and the dequeue pointer - * is not on a link TRB, there is one more usable TRB - */ + /* If this is not event ring, there is one more usable TRB */ if (ring->type != TYPE_EVENT && !last_trb(xhci, ring, ring->deq_seg, ring->dequeue)) ring->num_trbs_free++; + next = ++(ring->dequeue); - do { - /* - * Update the dequeue pointer further if that was a link TRB or - * we're at the end of an event ring segment (which doesn't have - * link TRBS) - */ - if (last_trb(xhci, ring, ring->deq_seg, ring->dequeue)) { - if (ring->type == TYPE_EVENT && - last_trb_on_last_seg(xhci, ring, - ring->deq_seg, ring->dequeue)) { - ring->cycle_state = (ring->cycle_state ? 0 : 1); - } - ring->deq_seg = ring->deq_seg->next; - ring->dequeue = ring->deq_seg->trbs; - } else { - ring->dequeue++; + /* Update the dequeue pointer further if that was a link TRB or we're at + * the end of an event ring segment (which doesn't have link TRBS) + */ + while (last_trb(xhci, ring, ring->deq_seg, next)) { + if (ring->type == TYPE_EVENT && last_trb_on_last_seg(xhci, + ring, ring->deq_seg, next)) { + ring->cycle_state = (ring->cycle_state ? 0 : 1); } - } while (last_trb(xhci, ring, ring->deq_seg, ring->dequeue)); - + ring->deq_seg = ring->deq_seg->next; + ring->dequeue = ring->deq_seg->trbs; + next = ring->dequeue; + } addr = (unsigned long long) xhci_trb_virt_to_dma(ring->deq_seg, ring->dequeue); } @@ -2081,8 +2073,8 @@ static int handle_tx_event(struct xhci_hcd *xhci, if (xhci->quirks & XHCI_TRUST_TX_LENGTH) trb_comp_code = COMP_SHORT_TX; else - xhci_warn_ratelimited(xhci, - "WARN Successful completion on short TX: needs XHCI_TRUST_TX_LENGTH quirk?\n"); + xhci_warn(xhci, "WARN Successful completion on short TX: " + "needs XHCI_TRUST_TX_LENGTH quirk?\n"); case COMP_SHORT_TX: break; case COMP_STOP: diff --git a/trunk/drivers/usb/host/xhci.c b/trunk/drivers/usb/host/xhci.c index 6ece0ed288d4..7648b2d4b268 100644 --- a/trunk/drivers/usb/host/xhci.c +++ b/trunk/drivers/usb/host/xhci.c @@ -26,7 +26,6 @@ #include #include #include -#include #include "xhci.h" @@ -167,7 +166,7 @@ int xhci_reset(struct xhci_hcd *xhci) xhci_writel(xhci, command, &xhci->op_regs->command); ret = handshake(xhci, &xhci->op_regs->command, - CMD_RESET, 0, 10 * 1000 * 1000); + CMD_RESET, 0, 250 * 1000); if (ret) return ret; @@ -176,8 +175,7 @@ int xhci_reset(struct xhci_hcd *xhci) * xHCI cannot write to any doorbells or operational registers other * than status until the "Controller Not Ready" flag is cleared. */ - ret = handshake(xhci, &xhci->op_regs->status, - STS_CNR, 0, 10 * 1000 * 1000); + ret = handshake(xhci, &xhci->op_regs->status, STS_CNR, 0, 250 * 1000); for (i = 0; i < 2; ++i) { xhci->bus_state[i].port_c_suspend = 0; @@ -399,95 +397,6 @@ static void xhci_msix_sync_irqs(struct xhci_hcd *xhci) #endif -static void compliance_mode_recovery(unsigned long arg) -{ - struct xhci_hcd *xhci; - struct usb_hcd *hcd; - u32 temp; - int i; - - xhci = (struct xhci_hcd *)arg; - - for (i = 0; i < xhci->num_usb3_ports; i++) { - temp = xhci_readl(xhci, xhci->usb3_ports[i]); - if ((temp & PORT_PLS_MASK) == USB_SS_PORT_LS_COMP_MOD) { - /* - * Compliance Mode Detected. Letting USB Core - * handle the Warm Reset - */ - xhci_dbg(xhci, "Compliance Mode Detected->Port %d!\n", - i + 1); - xhci_dbg(xhci, "Attempting Recovery routine!\n"); - hcd = xhci->shared_hcd; - - if (hcd->state == HC_STATE_SUSPENDED) - usb_hcd_resume_root_hub(hcd); - - usb_hcd_poll_rh_status(hcd); - } - } - - if (xhci->port_status_u0 != ((1 << xhci->num_usb3_ports)-1)) - mod_timer(&xhci->comp_mode_recovery_timer, - jiffies + msecs_to_jiffies(COMP_MODE_RCVRY_MSECS)); -} - -/* - * Quirk to work around issue generated by the SN65LVPE502CP USB3.0 re-driver - * that causes ports behind that hardware to enter compliance mode sometimes. - * The quirk creates a timer that polls every 2 seconds the link state of - * each host controller's port and recovers it by issuing a Warm reset - * if Compliance mode is detected, otherwise the port will become "dead" (no - * device connections or disconnections will be detected anymore). Becasue no - * status event is generated when entering compliance mode (per xhci spec), - * this quirk is needed on systems that have the failing hardware installed. - */ -static void compliance_mode_recovery_timer_init(struct xhci_hcd *xhci) -{ - xhci->port_status_u0 = 0; - init_timer(&xhci->comp_mode_recovery_timer); - - xhci->comp_mode_recovery_timer.data = (unsigned long) xhci; - xhci->comp_mode_recovery_timer.function = compliance_mode_recovery; - xhci->comp_mode_recovery_timer.expires = jiffies + - msecs_to_jiffies(COMP_MODE_RCVRY_MSECS); - - set_timer_slack(&xhci->comp_mode_recovery_timer, - msecs_to_jiffies(COMP_MODE_RCVRY_MSECS)); - add_timer(&xhci->comp_mode_recovery_timer); - xhci_dbg(xhci, "Compliance Mode Recovery Timer Initialized.\n"); -} - -/* - * This function identifies the systems that have installed the SN65LVPE502CP - * USB3.0 re-driver and that need the Compliance Mode Quirk. - * Systems: - * Vendor: Hewlett-Packard -> System Models: Z420, Z620 and Z820 - */ -static bool compliance_mode_recovery_timer_quirk_check(void) -{ - const char *dmi_product_name, *dmi_sys_vendor; - - dmi_product_name = dmi_get_system_info(DMI_PRODUCT_NAME); - dmi_sys_vendor = dmi_get_system_info(DMI_SYS_VENDOR); - - if (!(strstr(dmi_sys_vendor, "Hewlett-Packard"))) - return false; - - if (strstr(dmi_product_name, "Z420") || - strstr(dmi_product_name, "Z620") || - strstr(dmi_product_name, "Z820")) - return true; - - return false; -} - -static int xhci_all_ports_seen_u0(struct xhci_hcd *xhci) -{ - return (xhci->port_status_u0 == ((1 << xhci->num_usb3_ports)-1)); -} - - /* * Initialize memory for HCD and xHC (one-time init). * @@ -511,12 +420,6 @@ int xhci_init(struct usb_hcd *hcd) retval = xhci_mem_init(xhci, GFP_KERNEL); xhci_dbg(xhci, "Finished xhci_init\n"); - /* Initializing Compliance Mode Recovery Data If Needed */ - if (compliance_mode_recovery_timer_quirk_check()) { - xhci->quirks |= XHCI_COMP_MODE_QUIRK; - compliance_mode_recovery_timer_init(xhci); - } - return retval; } @@ -725,11 +628,6 @@ void xhci_stop(struct usb_hcd *hcd) del_timer_sync(&xhci->event_ring_timer); #endif - /* Deleting Compliance Mode Recovery Timer */ - if ((xhci->quirks & XHCI_COMP_MODE_QUIRK) && - (!(xhci_all_ports_seen_u0(xhci)))) - del_timer_sync(&xhci->comp_mode_recovery_timer); - if (xhci->quirks & XHCI_AMD_PLL_FIX) usb_amd_dev_put(); @@ -760,9 +658,6 @@ void xhci_shutdown(struct usb_hcd *hcd) { struct xhci_hcd *xhci = hcd_to_xhci(hcd); - if (xhci->quirks & XHCI_SPURIOUS_REBOOT) - usb_disable_xhci_ports(to_pci_dev(hcd->self.controller)); - spin_lock_irq(&xhci->lock); xhci_halt(xhci); spin_unlock_irq(&xhci->lock); @@ -907,16 +802,6 @@ int xhci_suspend(struct xhci_hcd *xhci) } spin_unlock_irq(&xhci->lock); - /* - * Deleting Compliance Mode Recovery Timer because the xHCI Host - * is about to be suspended. - */ - if ((xhci->quirks & XHCI_COMP_MODE_QUIRK) && - (!(xhci_all_ports_seen_u0(xhci)))) { - del_timer_sync(&xhci->comp_mode_recovery_timer); - xhci_dbg(xhci, "Compliance Mode Recovery Timer Deleted!\n"); - } - /* step 5: remove core well power */ /* synchronize irq when using MSI-X */ xhci_msix_sync_irqs(xhci); @@ -1049,16 +934,6 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated) usb_hcd_resume_root_hub(hcd); usb_hcd_resume_root_hub(xhci->shared_hcd); } - - /* - * If system is subject to the Quirk, Compliance Mode Timer needs to - * be re-initialized Always after a system resume. Ports are subject - * to suffer the Compliance Mode issue again. It doesn't matter if - * ports have entered previously to U0 before system's suspension. - */ - if (xhci->quirks & XHCI_COMP_MODE_QUIRK) - compliance_mode_recovery_timer_init(xhci); - return retval; } #endif /* CONFIG_PM */ diff --git a/trunk/drivers/usb/host/xhci.h b/trunk/drivers/usb/host/xhci.h index 1a05908c6673..55c0785810c9 100644 --- a/trunk/drivers/usb/host/xhci.h +++ b/trunk/drivers/usb/host/xhci.h @@ -1494,8 +1494,6 @@ struct xhci_hcd { #define XHCI_TRUST_TX_LENGTH (1 << 10) #define XHCI_LPM_SUPPORT (1 << 11) #define XHCI_INTEL_HOST (1 << 12) -#define XHCI_SPURIOUS_REBOOT (1 << 13) -#define XHCI_COMP_MODE_QUIRK (1 << 14) unsigned int num_active_eps; unsigned int limit_active_eps; /* There are two roothubs to keep track of bus suspend info for */ @@ -1512,11 +1510,6 @@ struct xhci_hcd { unsigned sw_lpm_support:1; /* support xHCI 1.0 spec USB2 hardware LPM */ unsigned hw_lpm_support:1; - /* Compliance Mode Recovery Data */ - struct timer_list comp_mode_recovery_timer; - u32 port_status_u0; -/* Compliance Mode Timer Triggered every 2 seconds */ -#define COMP_MODE_RCVRY_MSECS 2000 }; /* convert between an HCD pointer and the corresponding EHCI_HCD */ @@ -1544,8 +1537,6 @@ static inline struct usb_hcd *xhci_to_hcd(struct xhci_hcd *xhci) dev_err(xhci_to_hcd(xhci)->self.controller , fmt , ## args) #define xhci_warn(xhci, fmt, args...) \ dev_warn(xhci_to_hcd(xhci)->self.controller , fmt , ## args) -#define xhci_warn_ratelimited(xhci, fmt, args...) \ - dev_warn_ratelimited(xhci_to_hcd(xhci)->self.controller , fmt , ## args) /* TODO: copied from ehci.h - can be refactored? */ /* xHCI spec says all registers are little endian */ diff --git a/trunk/drivers/usb/misc/emi62.c b/trunk/drivers/usb/misc/emi62.c index ae794b90766b..ff08015b230c 100644 --- a/trunk/drivers/usb/misc/emi62.c +++ b/trunk/drivers/usb/misc/emi62.c @@ -232,7 +232,7 @@ static int emi62_load_firmware (struct usb_device *dev) return err; } -static const struct usb_device_id id_table[] = { +static const struct usb_device_id id_table[] __devinitconst = { { USB_DEVICE(EMI62_VENDOR_ID, EMI62_PRODUCT_ID) }, { } /* Terminating entry */ }; diff --git a/trunk/drivers/usb/musb/Kconfig b/trunk/drivers/usb/musb/Kconfig index 6259f0d99324..ef0c3f9f0947 100644 --- a/trunk/drivers/usb/musb/Kconfig +++ b/trunk/drivers/usb/musb/Kconfig @@ -8,7 +8,7 @@ config USB_MUSB_HDRC tristate 'Inventra Highspeed Dual Role Controller (TI, ADI, ...)' depends on USB && USB_GADGET select NOP_USB_XCEIV if (ARCH_DAVINCI || MACH_OMAP3EVM || BLACKFIN) - select NOP_USB_XCEIV if (SOC_TI81XX || SOC_AM33XX) + select NOP_USB_XCEIV if (SOC_OMAPTI81XX || SOC_OMAPAM33XX) select TWL4030_USB if MACH_OMAP_3430SDP select TWL6030_USB if MACH_OMAP_4430SDP || MACH_OMAP4_PANDA select USB_OTG_UTILS @@ -57,7 +57,7 @@ config USB_MUSB_AM35X config USB_MUSB_DSPS tristate "TI DSPS platforms" - depends on SOC_TI81XX || SOC_AM33XX + depends on SOC_OMAPTI81XX || SOC_OMAPAM33XX config USB_MUSB_BLACKFIN tristate "Blackfin" diff --git a/trunk/drivers/usb/musb/musb_dsps.c b/trunk/drivers/usb/musb/musb_dsps.c index 494772fc9e23..217808d9fbe1 100644 --- a/trunk/drivers/usb/musb/musb_dsps.c +++ b/trunk/drivers/usb/musb/musb_dsps.c @@ -479,9 +479,9 @@ static int __devinit dsps_create_musb_pdev(struct dsps_glue *glue, u8 id) ret = -ENODEV; goto err0; } + strcpy((u8 *)res->name, "mc"); res->parent = NULL; resources[1] = *res; - resources[1].name = "mc"; /* allocate the child platform device */ musb = platform_device_alloc("musb-hdrc", -1); @@ -566,28 +566,27 @@ static int __devinit dsps_probe(struct platform_device *pdev) } platform_set_drvdata(pdev, glue); + /* create the child platform device for first instances of musb */ + ret = dsps_create_musb_pdev(glue, 0); + if (ret != 0) { + dev_err(&pdev->dev, "failed to create child pdev\n"); + goto err2; + } + /* enable the usbss clocks */ pm_runtime_enable(&pdev->dev); ret = pm_runtime_get_sync(&pdev->dev); if (ret < 0) { dev_err(&pdev->dev, "pm_runtime_get_sync FAILED"); - goto err2; - } - - /* create the child platform device for first instances of musb */ - ret = dsps_create_musb_pdev(glue, 0); - if (ret != 0) { - dev_err(&pdev->dev, "failed to create child pdev\n"); goto err3; } return 0; err3: - pm_runtime_put(&pdev->dev); -err2: pm_runtime_disable(&pdev->dev); +err2: kfree(glue->wrp); err1: kfree(glue); diff --git a/trunk/drivers/usb/musb/musb_host.c b/trunk/drivers/usb/musb/musb_host.c index 1ae378d5fc6f..4bb717d0bd41 100644 --- a/trunk/drivers/usb/musb/musb_host.c +++ b/trunk/drivers/usb/musb/musb_host.c @@ -2049,7 +2049,7 @@ static int musb_urb_enqueue( * we only have work to do in the former case. */ spin_lock_irqsave(&musb->lock, flags); - if (hep->hcpriv || !next_urb(qh)) { + if (hep->hcpriv) { /* some concurrent activity submitted another urb to hep... * odd, rare, error prone, but legal. */ diff --git a/trunk/drivers/usb/musb/musbhsdma.c b/trunk/drivers/usb/musb/musbhsdma.c index c1be687e00ec..57a608584e16 100644 --- a/trunk/drivers/usb/musb/musbhsdma.c +++ b/trunk/drivers/usb/musb/musbhsdma.c @@ -388,7 +388,7 @@ dma_controller_create(struct musb *musb, void __iomem *base) struct platform_device *pdev = to_platform_device(dev); int irq = platform_get_irq_byname(pdev, "dma"); - if (irq <= 0) { + if (irq == 0) { dev_err(dev, "No DMA interrupt line!\n"); return NULL; } diff --git a/trunk/drivers/usb/musb/tusb6010.c b/trunk/drivers/usb/musb/tusb6010.c index 341625442377..1a1bd9cf40c5 100644 --- a/trunk/drivers/usb/musb/tusb6010.c +++ b/trunk/drivers/usb/musb/tusb6010.c @@ -1215,7 +1215,7 @@ static int __devinit tusb_probe(struct platform_device *pdev) ret = platform_device_add(musb); if (ret) { dev_err(&pdev->dev, "failed to register musb device\n"); - goto err2; + goto err1; } return 0; diff --git a/trunk/drivers/usb/renesas_usbhs/common.c b/trunk/drivers/usb/renesas_usbhs/common.c index 681da06170c2..8c9bb1ad3069 100644 --- a/trunk/drivers/usb/renesas_usbhs/common.c +++ b/trunk/drivers/usb/renesas_usbhs/common.c @@ -603,12 +603,12 @@ static int usbhsc_resume(struct device *dev) struct usbhs_priv *priv = dev_get_drvdata(dev); struct platform_device *pdev = usbhs_priv_to_pdev(priv); + usbhs_platform_call(priv, phy_reset, pdev); + if (!usbhsc_flags_has(priv, USBHSF_RUNTIME_PWCTRL)) usbhsc_power_ctrl(priv, 1); - usbhs_platform_call(priv, phy_reset, pdev); - - usbhsc_drvcllbck_notify_hotplug(pdev); + usbhsc_hotplug(priv); return 0; } diff --git a/trunk/drivers/usb/renesas_usbhs/fifo.c b/trunk/drivers/usb/renesas_usbhs/fifo.c index 143c4e9e1be4..ecd173032fd4 100644 --- a/trunk/drivers/usb/renesas_usbhs/fifo.c +++ b/trunk/drivers/usb/renesas_usbhs/fifo.c @@ -818,7 +818,7 @@ static int usbhsf_dma_prepare_push(struct usbhs_pkt *pkt, int *is_done) usbhs_pipe_is_dcp(pipe)) goto usbhsf_pio_prepare_push; - if (len & 0x7) /* 8byte alignment */ + if (len % 4) /* 32bit alignment */ goto usbhsf_pio_prepare_push; if ((uintptr_t)(pkt->buf + pkt->actual) & 0x7) /* 8byte alignment */ @@ -905,7 +905,7 @@ static int usbhsf_dma_try_pop(struct usbhs_pkt *pkt, int *is_done) /* use PIO if packet is less than pio_dma_border */ len = usbhsf_fifo_rcv_len(priv, fifo); len = min(pkt->length - pkt->actual, len); - if (len & 0x7) /* 8byte alignment */ + if (len % 4) /* 32bit alignment */ goto usbhsf_pio_prepare_pop_unselect; if (len < usbhs_get_dparam(priv, pio_dma_border)) diff --git a/trunk/drivers/usb/renesas_usbhs/mod_host.c b/trunk/drivers/usb/renesas_usbhs/mod_host.c index 9b69a1323294..1834cf50888c 100644 --- a/trunk/drivers/usb/renesas_usbhs/mod_host.c +++ b/trunk/drivers/usb/renesas_usbhs/mod_host.c @@ -1266,12 +1266,6 @@ static int usbhsh_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, return ret; } -static int usbhsh_bus_nop(struct usb_hcd *hcd) -{ - /* nothing to do */ - return 0; -} - static struct hc_driver usbhsh_driver = { .description = usbhsh_hcd_name, .hcd_priv_size = sizeof(struct usbhsh_hpriv), @@ -1296,8 +1290,6 @@ static struct hc_driver usbhsh_driver = { */ .hub_status_data = usbhsh_hub_status_data, .hub_control = usbhsh_hub_control, - .bus_suspend = usbhsh_bus_nop, - .bus_resume = usbhsh_bus_nop, }; /* diff --git a/trunk/drivers/usb/serial/ark3116.c b/trunk/drivers/usb/serial/ark3116.c index 3b98fb733362..f8ce97d8b0ad 100644 --- a/trunk/drivers/usb/serial/ark3116.c +++ b/trunk/drivers/usb/serial/ark3116.c @@ -215,7 +215,7 @@ static void ark3116_release(struct usb_serial *serial) static void ark3116_init_termios(struct tty_struct *tty) { - struct ktermios *termios = &tty->termios; + struct ktermios *termios = tty->termios; *termios = tty_std_termios; termios->c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; @@ -229,7 +229,7 @@ static void ark3116_set_termios(struct tty_struct *tty, { struct usb_serial *serial = port->serial; struct ark3116_private *priv = usb_get_serial_port_data(port); - struct ktermios *termios = &tty->termios; + struct ktermios *termios = tty->termios; unsigned int cflag = termios->c_cflag; int bps = tty_get_baud_rate(tty); int quot; diff --git a/trunk/drivers/usb/serial/belkin_sa.c b/trunk/drivers/usb/serial/belkin_sa.c index a46df73ee96e..6b7365632951 100644 --- a/trunk/drivers/usb/serial/belkin_sa.c +++ b/trunk/drivers/usb/serial/belkin_sa.c @@ -307,7 +307,7 @@ static void belkin_sa_set_termios(struct tty_struct *tty, unsigned long control_state; int bad_flow_control; speed_t baud; - struct ktermios *termios = &tty->termios; + struct ktermios *termios = tty->termios; iflag = termios->c_iflag; cflag = termios->c_cflag; diff --git a/trunk/drivers/usb/serial/bus.c b/trunk/drivers/usb/serial/bus.c index c15f2e7cefc7..f398d1e34474 100644 --- a/trunk/drivers/usb/serial/bus.c +++ b/trunk/drivers/usb/serial/bus.c @@ -61,23 +61,18 @@ static int usb_serial_device_probe(struct device *dev) goto exit; } - /* make sure suspend/resume doesn't race against port_probe */ - retval = usb_autopm_get_interface(port->serial->interface); - if (retval) - goto exit; - driver = port->serial->type; if (driver->port_probe) { retval = driver->port_probe(port); if (retval) - goto exit_with_autopm; + goto exit; } retval = device_create_file(dev, &dev_attr_port_number); if (retval) { if (driver->port_remove) retval = driver->port_remove(port); - goto exit_with_autopm; + goto exit; } minor = port->number; @@ -86,8 +81,6 @@ static int usb_serial_device_probe(struct device *dev) "%s converter now attached to ttyUSB%d\n", driver->description, minor); -exit_with_autopm: - usb_autopm_put_interface(port->serial->interface); exit: return retval; } @@ -103,9 +96,6 @@ static int usb_serial_device_remove(struct device *dev) if (!port) return -ENODEV; - /* make sure suspend/resume doesn't race against port_remove */ - usb_autopm_get_interface(port->serial->interface); - device_remove_file(&port->dev, &dev_attr_port_number); driver = port->serial->type; @@ -117,7 +107,6 @@ static int usb_serial_device_remove(struct device *dev) dev_info(dev, "%s converter now disconnected from ttyUSB%d\n", driver->description, minor); - usb_autopm_put_interface(port->serial->interface); return retval; } diff --git a/trunk/drivers/usb/serial/console.c b/trunk/drivers/usb/serial/console.c index 9a564286bfd7..b9cca6dcde07 100644 --- a/trunk/drivers/usb/serial/console.c +++ b/trunk/drivers/usb/serial/console.c @@ -165,8 +165,8 @@ static int usb_console_setup(struct console *co, char *options) } if (serial->type->set_termios) { - tty->termios.c_cflag = cflag; - tty_termios_encode_baud_rate(&tty->termios, baud, baud); + tty->termios->c_cflag = cflag; + tty_termios_encode_baud_rate(tty->termios, baud, baud); memset(&dummy, 0, sizeof(struct ktermios)); serial->type->set_termios(tty, port, &dummy); diff --git a/trunk/drivers/usb/serial/cp210x.c b/trunk/drivers/usb/serial/cp210x.c index ba5e07e188a0..1e71079ce33b 100644 --- a/trunk/drivers/usb/serial/cp210x.c +++ b/trunk/drivers/usb/serial/cp210x.c @@ -469,7 +469,7 @@ static void cp210x_get_termios(struct tty_struct *tty, if (tty) { cp210x_get_termios_port(tty->driver_data, - &tty->termios.c_cflag, &baud); + &tty->termios->c_cflag, &baud); tty_encode_baud_rate(tty, baud, baud); } @@ -631,7 +631,7 @@ static void cp210x_change_speed(struct tty_struct *tty, { u32 baud; - baud = tty->termios.c_ospeed; + baud = tty->termios->c_ospeed; /* This maps the requested rate to a rate valid on cp2102 or cp2103, * or to an arbitrary rate in [1M,2M]. @@ -665,10 +665,10 @@ static void cp210x_set_termios(struct tty_struct *tty, if (!tty) return; - cflag = tty->termios.c_cflag; + cflag = tty->termios->c_cflag; old_cflag = old_termios->c_cflag; - if (tty->termios.c_ospeed != old_termios->c_ospeed) + if (tty->termios->c_ospeed != old_termios->c_ospeed) cp210x_change_speed(tty, port, old_termios); /* If the number of data bits is to be updated */ diff --git a/trunk/drivers/usb/serial/cypress_m8.c b/trunk/drivers/usb/serial/cypress_m8.c index be34f153e566..b78c34eb5d3f 100644 --- a/trunk/drivers/usb/serial/cypress_m8.c +++ b/trunk/drivers/usb/serial/cypress_m8.c @@ -922,38 +922,38 @@ static void cypress_set_termios(struct tty_struct *tty, early enough */ if (!priv->termios_initialized) { if (priv->chiptype == CT_EARTHMATE) { - tty->termios = tty_std_termios; - tty->termios.c_cflag = B4800 | CS8 | CREAD | HUPCL | + *(tty->termios) = tty_std_termios; + tty->termios->c_cflag = B4800 | CS8 | CREAD | HUPCL | CLOCAL; - tty->termios.c_ispeed = 4800; - tty->termios.c_ospeed = 4800; + tty->termios->c_ispeed = 4800; + tty->termios->c_ospeed = 4800; } else if (priv->chiptype == CT_CYPHIDCOM) { - tty->termios = tty_std_termios; - tty->termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | + *(tty->termios) = tty_std_termios; + tty->termios->c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; - tty->termios.c_ispeed = 9600; - tty->termios.c_ospeed = 9600; + tty->termios->c_ispeed = 9600; + tty->termios->c_ospeed = 9600; } else if (priv->chiptype == CT_CA42V2) { - tty->termios = tty_std_termios; - tty->termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | + *(tty->termios) = tty_std_termios; + tty->termios->c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; - tty->termios.c_ispeed = 9600; - tty->termios.c_ospeed = 9600; + tty->termios->c_ispeed = 9600; + tty->termios->c_ospeed = 9600; } priv->termios_initialized = 1; } spin_unlock_irqrestore(&priv->lock, flags); /* Unsupported features need clearing */ - tty->termios.c_cflag &= ~(CMSPAR|CRTSCTS); + tty->termios->c_cflag &= ~(CMSPAR|CRTSCTS); - cflag = tty->termios.c_cflag; - iflag = tty->termios.c_iflag; + cflag = tty->termios->c_cflag; + iflag = tty->termios->c_iflag; /* check if there are new settings */ if (old_termios) { spin_lock_irqsave(&priv->lock, flags); - priv->tmp_termios = tty->termios; + priv->tmp_termios = *(tty->termios); spin_unlock_irqrestore(&priv->lock, flags); } @@ -1021,7 +1021,7 @@ static void cypress_set_termios(struct tty_struct *tty, "4800bps."); /* define custom termios settings for NMEA protocol */ - tty->termios.c_iflag /* input modes - */ + tty->termios->c_iflag /* input modes - */ &= ~(IGNBRK /* disable ignore break */ | BRKINT /* disable break causes interrupt */ | PARMRK /* disable mark parity errors */ @@ -1031,10 +1031,10 @@ static void cypress_set_termios(struct tty_struct *tty, | ICRNL /* disable translate CR to NL */ | IXON); /* disable enable XON/XOFF flow control */ - tty->termios.c_oflag /* output modes */ + tty->termios->c_oflag /* output modes */ &= ~OPOST; /* disable postprocess output char */ - tty->termios.c_lflag /* line discipline modes */ + tty->termios->c_lflag /* line discipline modes */ &= ~(ECHO /* disable echo input characters */ | ECHONL /* disable echo new line */ | ICANON /* disable erase, kill, werase, and rprnt @@ -1200,7 +1200,7 @@ static void cypress_read_int_callback(struct urb *urb) /* hangup, as defined in acm.c... this might be a bad place for it * though */ - if (tty && !(tty->termios.c_cflag & CLOCAL) && + if (tty && !(tty->termios->c_cflag & CLOCAL) && !(priv->current_status & UART_CD)) { dbg("%s - calling hangup", __func__); tty_hangup(tty); diff --git a/trunk/drivers/usb/serial/digi_acceleport.c b/trunk/drivers/usb/serial/digi_acceleport.c index afd9d2ec577b..b5cd838093ef 100644 --- a/trunk/drivers/usb/serial/digi_acceleport.c +++ b/trunk/drivers/usb/serial/digi_acceleport.c @@ -687,8 +687,8 @@ static void digi_set_termios(struct tty_struct *tty, struct usb_serial_port *port, struct ktermios *old_termios) { struct digi_port *priv = usb_get_serial_port_data(port); - unsigned int iflag = tty->termios.c_iflag; - unsigned int cflag = tty->termios.c_cflag; + unsigned int iflag = tty->termios->c_iflag; + unsigned int cflag = tty->termios->c_cflag; unsigned int old_iflag = old_termios->c_iflag; unsigned int old_cflag = old_termios->c_cflag; unsigned char buf[32]; @@ -709,7 +709,7 @@ static void digi_set_termios(struct tty_struct *tty, /* don't set RTS if using hardware flow control */ /* and throttling input */ modem_signals = TIOCM_DTR; - if (!(tty->termios.c_cflag & CRTSCTS) || + if (!(tty->termios->c_cflag & CRTSCTS) || !test_bit(TTY_THROTTLED, &tty->flags)) modem_signals |= TIOCM_RTS; digi_set_modem_signals(port, modem_signals, 1); @@ -748,7 +748,7 @@ static void digi_set_termios(struct tty_struct *tty, } } /* set parity */ - tty->termios.c_cflag &= ~CMSPAR; + tty->termios->c_cflag &= ~CMSPAR; if ((cflag&(PARENB|PARODD)) != (old_cflag&(PARENB|PARODD))) { if (cflag&PARENB) { @@ -1124,8 +1124,8 @@ static int digi_open(struct tty_struct *tty, struct usb_serial_port *port) /* set termios settings */ if (tty) { - not_termios.c_cflag = ~tty->termios.c_cflag; - not_termios.c_iflag = ~tty->termios.c_iflag; + not_termios.c_cflag = ~tty->termios->c_cflag; + not_termios.c_iflag = ~tty->termios->c_iflag; digi_set_termios(tty, port, ¬_termios); } return 0; @@ -1500,7 +1500,7 @@ static int digi_read_oob_callback(struct urb *urb) rts = 0; if (tty) - rts = tty->termios.c_cflag & CRTSCTS; + rts = tty->termios->c_cflag & CRTSCTS; if (tty && opcode == DIGI_CMD_READ_INPUT_SIGNALS) { spin_lock(&priv->dp_port_lock); diff --git a/trunk/drivers/usb/serial/empeg.c b/trunk/drivers/usb/serial/empeg.c index 34e86383090a..cdf61dd07318 100644 --- a/trunk/drivers/usb/serial/empeg.c +++ b/trunk/drivers/usb/serial/empeg.c @@ -87,7 +87,7 @@ static int empeg_startup(struct usb_serial *serial) static void empeg_init_termios(struct tty_struct *tty) { - struct ktermios *termios = &tty->termios; + struct ktermios *termios = tty->termios; /* * The empeg-car player wants these particular tty settings. diff --git a/trunk/drivers/usb/serial/f81232.c b/trunk/drivers/usb/serial/f81232.c index 79451ee12ca0..499b15fd82f1 100644 --- a/trunk/drivers/usb/serial/f81232.c +++ b/trunk/drivers/usb/serial/f81232.c @@ -173,11 +173,10 @@ static void f81232_set_termios(struct tty_struct *tty, /* FIXME - Stubbed out for now */ /* Don't change anything if nothing has changed */ - if (!tty_termios_hw_change(&tty->termios, old_termios)) + if (!tty_termios_hw_change(tty->termios, old_termios)) return; /* Do the real work here... */ - tty_termios_copy_hw(&tty->termios, old_termios); } static int f81232_tiocmget(struct tty_struct *tty) diff --git a/trunk/drivers/usb/serial/ftdi_sio.c b/trunk/drivers/usb/serial/ftdi_sio.c index 0c8d1c226273..bc912e5a3beb 100644 --- a/trunk/drivers/usb/serial/ftdi_sio.c +++ b/trunk/drivers/usb/serial/ftdi_sio.c @@ -704,7 +704,6 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(FTDI_VID, FTDI_PCDJ_DAC2_PID) }, { USB_DEVICE(FTDI_VID, FTDI_RRCIRKITS_LOCOBUFFER_PID) }, { USB_DEVICE(FTDI_VID, FTDI_ASK_RDR400_PID) }, - { USB_DEVICE(FTDI_VID, FTDI_NZR_SEM_USB_PID) }, { USB_DEVICE(ICOM_VID, ICOM_ID_1_PID) }, { USB_DEVICE(ICOM_VID, ICOM_OPC_U_UC_PID) }, { USB_DEVICE(ICOM_VID, ICOM_ID_RP2C1_PID) }, @@ -805,33 +804,13 @@ static struct usb_device_id id_table_combined [] = { .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, { USB_DEVICE(ADI_VID, ADI_GNICEPLUS_PID), .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, - { USB_DEVICE_AND_INTERFACE_INFO(MICROCHIP_VID, MICROCHIP_USB_BOARD_PID, - USB_CLASS_VENDOR_SPEC, - USB_SUBCLASS_VENDOR_SPEC, 0x00) }, + { USB_DEVICE(MICROCHIP_VID, MICROCHIP_USB_BOARD_PID) }, { USB_DEVICE(JETI_VID, JETI_SPC1201_PID) }, { USB_DEVICE(MARVELL_VID, MARVELL_SHEEVAPLUG_PID), .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, { USB_DEVICE(LARSENBRUSGAARD_VID, LB_ALTITRACK_PID) }, { USB_DEVICE(GN_OTOMETRICS_VID, AURICAL_USB_PID) }, - { USB_DEVICE(FTDI_VID, PI_C865_PID) }, - { USB_DEVICE(FTDI_VID, PI_C857_PID) }, - { USB_DEVICE(PI_VID, PI_C866_PID) }, - { USB_DEVICE(PI_VID, PI_C663_PID) }, - { USB_DEVICE(PI_VID, PI_C725_PID) }, - { USB_DEVICE(PI_VID, PI_E517_PID) }, - { USB_DEVICE(PI_VID, PI_C863_PID) }, { USB_DEVICE(PI_VID, PI_E861_PID) }, - { USB_DEVICE(PI_VID, PI_C867_PID) }, - { USB_DEVICE(PI_VID, PI_E609_PID) }, - { USB_DEVICE(PI_VID, PI_E709_PID) }, - { USB_DEVICE(PI_VID, PI_100F_PID) }, - { USB_DEVICE(PI_VID, PI_1011_PID) }, - { USB_DEVICE(PI_VID, PI_1012_PID) }, - { USB_DEVICE(PI_VID, PI_1013_PID) }, - { USB_DEVICE(PI_VID, PI_1014_PID) }, - { USB_DEVICE(PI_VID, PI_1015_PID) }, - { USB_DEVICE(PI_VID, PI_1016_PID) }, - { USB_DEVICE(KONDO_VID, KONDO_USB_SERIAL_PID) }, { USB_DEVICE(BAYER_VID, BAYER_CONTOUR_CABLE_PID) }, { USB_DEVICE(FTDI_VID, MARVELL_OPENRD_PID), .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, @@ -2102,7 +2081,7 @@ static void ftdi_set_termios(struct tty_struct *tty, { struct usb_device *dev = port->serial->dev; struct ftdi_private *priv = usb_get_serial_port_data(port); - struct ktermios *termios = &tty->termios; + struct ktermios *termios = tty->termios; unsigned int cflag = termios->c_cflag; __u16 urb_value; /* will hold the new flags */ diff --git a/trunk/drivers/usb/serial/ftdi_sio_ids.h b/trunk/drivers/usb/serial/ftdi_sio_ids.h index 41fe5826100c..5661c7e2d415 100644 --- a/trunk/drivers/usb/serial/ftdi_sio_ids.h +++ b/trunk/drivers/usb/serial/ftdi_sio_ids.h @@ -75,9 +75,6 @@ #define FTDI_OPENDCC_GATEWAY_PID 0xBFDB #define FTDI_OPENDCC_GBM_PID 0xBFDC -/* NZR SEM 16+ USB (http://www.nzr.de) */ -#define FTDI_NZR_SEM_USB_PID 0xC1E0 /* NZR SEM-LOG16+ */ - /* * RR-CirKits LocoBuffer USB (http://www.rr-cirkits.com) */ @@ -542,10 +539,7 @@ /* * Microchip Technology, Inc. * - * MICROCHIP_VID (0x04D8) and MICROCHIP_USB_BOARD_PID (0x000A) are - * used by single function CDC ACM class based firmware demo - * applications. The VID/PID has also been used in firmware - * emulating FTDI serial chips by: + * MICROCHIP_VID (0x04D8) and MICROCHIP_USB_BOARD_PID (0x000A) are also used by: * Hornby Elite - Digital Command Control Console * http://www.hornby.com/hornby-dcc/controllers/ */ @@ -797,34 +791,8 @@ * Physik Instrumente * http://www.physikinstrumente.com/en/products/ */ -/* These two devices use the VID of FTDI */ -#define PI_C865_PID 0xe0a0 /* PI C-865 Piezomotor Controller */ -#define PI_C857_PID 0xe0a1 /* PI Encoder Trigger Box */ - #define PI_VID 0x1a72 /* Vendor ID */ -#define PI_C866_PID 0x1000 /* PI C-866 Piezomotor Controller */ -#define PI_C663_PID 0x1001 /* PI C-663 Mercury-Step */ -#define PI_C725_PID 0x1002 /* PI C-725 Piezomotor Controller */ -#define PI_E517_PID 0x1005 /* PI E-517 Digital Piezo Controller Operation Module */ -#define PI_C863_PID 0x1007 /* PI C-863 */ -#define PI_E861_PID 0x1008 /* PI E-861 Piezomotor Controller */ -#define PI_C867_PID 0x1009 /* PI C-867 Piezomotor Controller */ -#define PI_E609_PID 0x100D /* PI E-609 Digital Piezo Controller */ -#define PI_E709_PID 0x100E /* PI E-709 Digital Piezo Controller */ -#define PI_100F_PID 0x100F /* PI Digital Piezo Controller */ -#define PI_1011_PID 0x1011 /* PI Digital Piezo Controller */ -#define PI_1012_PID 0x1012 /* PI Motion Controller */ -#define PI_1013_PID 0x1013 /* PI Motion Controller */ -#define PI_1014_PID 0x1014 /* PI Device */ -#define PI_1015_PID 0x1015 /* PI Device */ -#define PI_1016_PID 0x1016 /* PI Digital Servo Module */ - -/* - * Kondo Kagaku Co.Ltd. - * http://www.kondo-robot.com/EN - */ -#define KONDO_VID 0x165c -#define KONDO_USB_SERIAL_PID 0x0002 +#define PI_E861_PID 0x1008 /* E-861 piezo controller USB connection */ /* * Bayer Ascensia Contour blood glucose meter USB-converter cable. diff --git a/trunk/drivers/usb/serial/io_edgeport.c b/trunk/drivers/usb/serial/io_edgeport.c index f435575c4e6e..e1f5ccd1e8f8 100644 --- a/trunk/drivers/usb/serial/io_edgeport.c +++ b/trunk/drivers/usb/serial/io_edgeport.c @@ -1458,7 +1458,7 @@ static void edge_throttle(struct tty_struct *tty) } /* if we are implementing RTS/CTS, toggle that line */ - if (tty->termios.c_cflag & CRTSCTS) { + if (tty->termios->c_cflag & CRTSCTS) { edge_port->shadowMCR &= ~MCR_RTS; status = send_cmd_write_uart_register(edge_port, MCR, edge_port->shadowMCR); @@ -1497,7 +1497,7 @@ static void edge_unthrottle(struct tty_struct *tty) return; } /* if we are implementing RTS/CTS, toggle that line */ - if (tty->termios.c_cflag & CRTSCTS) { + if (tty->termios->c_cflag & CRTSCTS) { edge_port->shadowMCR |= MCR_RTS; send_cmd_write_uart_register(edge_port, MCR, edge_port->shadowMCR); @@ -1516,9 +1516,9 @@ static void edge_set_termios(struct tty_struct *tty, struct edgeport_port *edge_port = usb_get_serial_port_data(port); unsigned int cflag; - cflag = tty->termios.c_cflag; + cflag = tty->termios->c_cflag; dbg("%s - clfag %08x iflag %08x", __func__, - tty->termios.c_cflag, tty->termios.c_iflag); + tty->termios->c_cflag, tty->termios->c_iflag); dbg("%s - old clfag %08x old iflag %08x", __func__, old_termios->c_cflag, old_termios->c_iflag); @@ -1987,7 +1987,7 @@ static void process_rcvd_status(struct edgeport_serial *edge_serial, tty = tty_port_tty_get(&edge_port->port->port); if (tty) { change_port_settings(tty, - edge_port, &tty->termios); + edge_port, tty->termios); tty_kref_put(tty); } @@ -2570,7 +2570,7 @@ static void change_port_settings(struct tty_struct *tty, return; } - cflag = tty->termios.c_cflag; + cflag = tty->termios->c_cflag; switch (cflag & CSIZE) { case CS5: diff --git a/trunk/drivers/usb/serial/io_ti.c b/trunk/drivers/usb/serial/io_ti.c index 765978ae752e..3936904c6419 100644 --- a/trunk/drivers/usb/serial/io_ti.c +++ b/trunk/drivers/usb/serial/io_ti.c @@ -1870,7 +1870,7 @@ static int edge_open(struct tty_struct *tty, struct usb_serial_port *port) /* set up the port settings */ if (tty) - edge_set_termios(tty, port, &tty->termios); + edge_set_termios(tty, port, tty->termios); /* open up the port */ @@ -2272,13 +2272,13 @@ static void change_port_settings(struct tty_struct *tty, config = kmalloc (sizeof (*config), GFP_KERNEL); if (!config) { - tty->termios = *old_termios; + *tty->termios = *old_termios; dev_err(&edge_port->port->dev, "%s - out of memory\n", __func__); return; } - cflag = tty->termios.c_cflag; + cflag = tty->termios->c_cflag; config->wFlags = 0; @@ -2362,7 +2362,7 @@ static void change_port_settings(struct tty_struct *tty, } else dbg("%s - OUTBOUND XON/XOFF is disabled", __func__); - tty->termios.c_cflag &= ~CMSPAR; + tty->termios->c_cflag &= ~CMSPAR; /* Round the baud rate */ baud = tty_get_baud_rate(tty); @@ -2408,10 +2408,10 @@ static void edge_set_termios(struct tty_struct *tty, struct edgeport_port *edge_port = usb_get_serial_port_data(port); unsigned int cflag; - cflag = tty->termios.c_cflag; + cflag = tty->termios->c_cflag; dbg("%s - clfag %08x iflag %08x", __func__, - tty->termios.c_cflag, tty->termios.c_iflag); + tty->termios->c_cflag, tty->termios->c_iflag); dbg("%s - old clfag %08x old iflag %08x", __func__, old_termios->c_cflag, old_termios->c_iflag); dbg("%s - port %d", __func__, port->number); diff --git a/trunk/drivers/usb/serial/ipw.c b/trunk/drivers/usb/serial/ipw.c index 2cb30c535839..5811d34b6c6b 100644 --- a/trunk/drivers/usb/serial/ipw.c +++ b/trunk/drivers/usb/serial/ipw.c @@ -227,6 +227,7 @@ static void ipw_release(struct usb_serial *serial) { struct usb_wwan_intf_private *data = usb_get_serial_data(serial); + usb_wwan_release(serial); usb_set_serial_data(serial, NULL); kfree(data); } @@ -308,12 +309,12 @@ static struct usb_serial_driver ipw_device = { .description = "IPWireless converter", .id_table = id_table, .num_ports = 1, + .disconnect = usb_wwan_disconnect, .open = ipw_open, .close = ipw_close, .probe = ipw_probe, .attach = usb_wwan_startup, .release = ipw_release, - .port_remove = usb_wwan_port_remove, .dtr_rts = ipw_dtr_rts, .write = usb_wwan_write, }; diff --git a/trunk/drivers/usb/serial/ir-usb.c b/trunk/drivers/usb/serial/ir-usb.c index 5a96692b12a2..fc09414c960f 100644 --- a/trunk/drivers/usb/serial/ir-usb.c +++ b/trunk/drivers/usb/serial/ir-usb.c @@ -381,7 +381,7 @@ static void ir_set_termios(struct tty_struct *tty, ir_xbof = ir_xbof_change(xbof) ; /* Only speed changes are supported */ - tty_termios_copy_hw(&tty->termios, old_termios); + tty_termios_copy_hw(tty->termios, old_termios); tty_encode_baud_rate(tty, baud, baud); /* diff --git a/trunk/drivers/usb/serial/iuu_phoenix.c b/trunk/drivers/usb/serial/iuu_phoenix.c index bf3864045c18..22b1eb5040b7 100644 --- a/trunk/drivers/usb/serial/iuu_phoenix.c +++ b/trunk/drivers/usb/serial/iuu_phoenix.c @@ -921,7 +921,7 @@ static void iuu_set_termios(struct tty_struct *tty, { const u32 supported_mask = CMSPAR|PARENB|PARODD; struct iuu_private *priv = usb_get_serial_port_data(port); - unsigned int cflag = tty->termios.c_cflag; + unsigned int cflag = tty->termios->c_cflag; int status; u32 actual; u32 parity; @@ -930,7 +930,7 @@ static void iuu_set_termios(struct tty_struct *tty, u32 newval = cflag & supported_mask; /* Just use the ospeed. ispeed should be the same. */ - baud = tty->termios.c_ospeed; + baud = tty->termios->c_ospeed; dbg("%s - enter c_ospeed or baud=%d", __func__, baud); @@ -961,13 +961,13 @@ static void iuu_set_termios(struct tty_struct *tty, * settings back over and then adjust them */ if (old_termios) - tty_termios_copy_hw(&tty->termios, old_termios); + tty_termios_copy_hw(tty->termios, old_termios); if (status != 0) /* Set failed - return old bits */ return; /* Re-encode speed, parity and csize */ tty_encode_baud_rate(tty, baud, baud); - tty->termios.c_cflag &= ~(supported_mask|CSIZE); - tty->termios.c_cflag |= newval | csize; + tty->termios->c_cflag &= ~(supported_mask|CSIZE); + tty->termios->c_cflag |= newval | csize; } static void iuu_close(struct usb_serial_port *port) @@ -993,14 +993,14 @@ static void iuu_close(struct usb_serial_port *port) static void iuu_init_termios(struct tty_struct *tty) { - tty->termios = tty_std_termios; - tty->termios.c_cflag = CLOCAL | CREAD | CS8 | B9600 + *(tty->termios) = tty_std_termios; + tty->termios->c_cflag = CLOCAL | CREAD | CS8 | B9600 | TIOCM_CTS | CSTOPB | PARENB; - tty->termios.c_ispeed = 9600; - tty->termios.c_ospeed = 9600; - tty->termios.c_lflag = 0; - tty->termios.c_oflag = 0; - tty->termios.c_iflag = 0; + tty->termios->c_ispeed = 9600; + tty->termios->c_ospeed = 9600; + tty->termios->c_lflag = 0; + tty->termios->c_oflag = 0; + tty->termios->c_iflag = 0; } static int iuu_open(struct tty_struct *tty, struct usb_serial_port *port) @@ -1012,8 +1012,8 @@ static int iuu_open(struct tty_struct *tty, struct usb_serial_port *port) u32 actual; struct iuu_private *priv = usb_get_serial_port_data(port); - baud = tty->termios.c_ospeed; - tty->termios.c_ispeed = baud; + baud = tty->termios->c_ospeed; + tty->termios->c_ispeed = baud; /* Re-encode speed */ tty_encode_baud_rate(tty, baud, baud); diff --git a/trunk/drivers/usb/serial/keyspan.c b/trunk/drivers/usb/serial/keyspan.c index 7bcbb47e1449..af0b70eaf032 100644 --- a/trunk/drivers/usb/serial/keyspan.c +++ b/trunk/drivers/usb/serial/keyspan.c @@ -158,7 +158,7 @@ static void keyspan_set_termios(struct tty_struct *tty, p_priv = usb_get_serial_port_data(port); d_details = p_priv->device_details; - cflag = tty->termios.c_cflag; + cflag = tty->termios->c_cflag; device_port = port->number - port->serial->minor; /* Baud rate calculation takes baud rate as an integer @@ -179,7 +179,7 @@ static void keyspan_set_termios(struct tty_struct *tty, p_priv->flow_control = (cflag & CRTSCTS) ? flow_cts : flow_none; /* Mark/Space not supported */ - tty->termios.c_cflag &= ~CMSPAR; + tty->termios->c_cflag &= ~CMSPAR; keyspan_send_setup(port, 0); } @@ -1086,7 +1086,7 @@ static int keyspan_open(struct tty_struct *tty, struct usb_serial_port *port) device_port = port->number - port->serial->minor; if (tty) { - cflag = tty->termios.c_cflag; + cflag = tty->termios->c_cflag; /* Baud rate calculation takes baud rate as an integer so other rates can be generated if desired. */ baud_rate = tty_get_baud_rate(tty); diff --git a/trunk/drivers/usb/serial/keyspan_pda.c b/trunk/drivers/usb/serial/keyspan_pda.c index dcada8615fcf..a4ac3cfeffc4 100644 --- a/trunk/drivers/usb/serial/keyspan_pda.c +++ b/trunk/drivers/usb/serial/keyspan_pda.c @@ -338,7 +338,7 @@ static void keyspan_pda_set_termios(struct tty_struct *tty, 7[EOMS]1: 10 bit, b0/b7 is parity 7[EOMS]2: 11 bit, b0/b7 is parity, extra bit always (mark?) - HW flow control is dictated by the tty->termios.c_cflags & CRTSCTS + HW flow control is dictated by the tty->termios->c_cflags & CRTSCTS bit. For now, just do baud. */ @@ -353,7 +353,7 @@ static void keyspan_pda_set_termios(struct tty_struct *tty, } /* Only speed can change so copy the old h/w parameters then encode the new speed */ - tty_termios_copy_hw(&tty->termios, old_termios); + tty_termios_copy_hw(tty->termios, old_termios); tty_encode_baud_rate(tty, speed, speed); } diff --git a/trunk/drivers/usb/serial/kl5kusb105.c b/trunk/drivers/usb/serial/kl5kusb105.c index def9ad258715..5bed59cd5776 100644 --- a/trunk/drivers/usb/serial/kl5kusb105.c +++ b/trunk/drivers/usb/serial/kl5kusb105.c @@ -311,12 +311,12 @@ static int klsi_105_open(struct tty_struct *tty, struct usb_serial_port *port) /* set up termios structure */ spin_lock_irqsave(&priv->lock, flags); - priv->termios.c_iflag = tty->termios.c_iflag; - priv->termios.c_oflag = tty->termios.c_oflag; - priv->termios.c_cflag = tty->termios.c_cflag; - priv->termios.c_lflag = tty->termios.c_lflag; + priv->termios.c_iflag = tty->termios->c_iflag; + priv->termios.c_oflag = tty->termios->c_oflag; + priv->termios.c_cflag = tty->termios->c_cflag; + priv->termios.c_lflag = tty->termios->c_lflag; for (i = 0; i < NCCS; i++) - priv->termios.c_cc[i] = tty->termios.c_cc[i]; + priv->termios.c_cc[i] = tty->termios->c_cc[i]; priv->cfg.pktlen = cfg->pktlen; priv->cfg.baudrate = cfg->baudrate; priv->cfg.databits = cfg->databits; @@ -445,9 +445,9 @@ static void klsi_105_set_termios(struct tty_struct *tty, struct ktermios *old_termios) { struct klsi_105_private *priv = usb_get_serial_port_data(port); - unsigned int iflag = tty->termios.c_iflag; + unsigned int iflag = tty->termios->c_iflag; unsigned int old_iflag = old_termios->c_iflag; - unsigned int cflag = tty->termios.c_cflag; + unsigned int cflag = tty->termios->c_cflag; unsigned int old_cflag = old_termios->c_cflag; struct klsi_105_port_settings *cfg; unsigned long flags; @@ -560,7 +560,7 @@ static void klsi_105_set_termios(struct tty_struct *tty, if ((cflag & (PARENB|PARODD)) != (old_cflag & (PARENB|PARODD)) || (cflag & CSTOPB) != (old_cflag & CSTOPB)) { /* Not currently supported */ - tty->termios.c_cflag &= ~(PARENB|PARODD|CSTOPB); + tty->termios->c_cflag &= ~(PARENB|PARODD|CSTOPB); #if 0 priv->last_lcr = 0; @@ -587,7 +587,7 @@ static void klsi_105_set_termios(struct tty_struct *tty, || (iflag & IXON) != (old_iflag & IXON) || (cflag & CRTSCTS) != (old_cflag & CRTSCTS)) { /* Not currently supported */ - tty->termios.c_cflag &= ~CRTSCTS; + tty->termios->c_cflag &= ~CRTSCTS; /* Drop DTR/RTS if no flow control otherwise assert */ #if 0 if ((iflag & IXOFF) || (iflag & IXON) || (cflag & CRTSCTS)) diff --git a/trunk/drivers/usb/serial/kobil_sct.c b/trunk/drivers/usb/serial/kobil_sct.c index bf5c74965d34..fafeabb64c55 100644 --- a/trunk/drivers/usb/serial/kobil_sct.c +++ b/trunk/drivers/usb/serial/kobil_sct.c @@ -191,11 +191,11 @@ static void kobil_release(struct usb_serial *serial) static void kobil_init_termios(struct tty_struct *tty) { /* Default to echo off and other sane device settings */ - tty->termios.c_lflag = 0; - tty->termios.c_iflag &= ~(ISIG | ICANON | ECHO | IEXTEN | XCASE); - tty->termios.c_iflag |= IGNBRK | IGNPAR | IXOFF; + tty->termios->c_lflag = 0; + tty->termios->c_lflag &= ~(ISIG | ICANON | ECHO | IEXTEN | XCASE); + tty->termios->c_iflag = IGNBRK | IGNPAR | IXOFF; /* do NOT translate CR to CR-NL (0x0A -> 0x0A 0x0D) */ - tty->termios.c_oflag &= ~ONLCR; + tty->termios->c_oflag &= ~ONLCR; } static int kobil_open(struct tty_struct *tty, struct usb_serial_port *port) @@ -581,14 +581,14 @@ static void kobil_set_termios(struct tty_struct *tty, struct kobil_private *priv; int result; unsigned short urb_val = 0; - int c_cflag = tty->termios.c_cflag; + int c_cflag = tty->termios->c_cflag; speed_t speed; priv = usb_get_serial_port_data(port); if (priv->device_type == KOBIL_USBTWIN_PRODUCT_ID || priv->device_type == KOBIL_KAAN_SIM_PRODUCT_ID) { /* This device doesn't support ioctl calls */ - tty_termios_copy_hw(&tty->termios, old); + *tty->termios = *old; return; } @@ -612,7 +612,7 @@ static void kobil_set_termios(struct tty_struct *tty, urb_val |= SUSBCR_SPASB_EvenParity; } else urb_val |= SUSBCR_SPASB_NoParity; - tty->termios.c_cflag &= ~CMSPAR; + tty->termios->c_cflag &= ~CMSPAR; tty_encode_baud_rate(tty, speed, speed); result = usb_control_msg(port->serial->dev, diff --git a/trunk/drivers/usb/serial/mct_u232.c b/trunk/drivers/usb/serial/mct_u232.c index df98cffdba65..a71fa0aa0406 100644 --- a/trunk/drivers/usb/serial/mct_u232.c +++ b/trunk/drivers/usb/serial/mct_u232.c @@ -454,7 +454,7 @@ static int mct_u232_open(struct tty_struct *tty, struct usb_serial_port *port) * either. */ spin_lock_irqsave(&priv->lock, flags); - if (tty && (tty->termios.c_cflag & CBAUD)) + if (tty && (tty->termios->c_cflag & CBAUD)) priv->control_state = TIOCM_DTR | TIOCM_RTS; else priv->control_state = 0; @@ -634,7 +634,7 @@ static void mct_u232_set_termios(struct tty_struct *tty, { struct usb_serial *serial = port->serial; struct mct_u232_private *priv = usb_get_serial_port_data(port); - struct ktermios *termios = &tty->termios; + struct ktermios *termios = tty->termios; unsigned int cflag = termios->c_cflag; unsigned int old_cflag = old_termios->c_cflag; unsigned long flags; diff --git a/trunk/drivers/usb/serial/metro-usb.c b/trunk/drivers/usb/serial/metro-usb.c index 2b0627b5fe2c..d47eb06fe463 100644 --- a/trunk/drivers/usb/serial/metro-usb.c +++ b/trunk/drivers/usb/serial/metro-usb.c @@ -130,6 +130,12 @@ static void metrousb_read_int_callback(struct urb *urb) /* Set the data read from the usb port into the serial port buffer. */ tty = tty_port_tty_get(&port->port); + if (!tty) { + dev_err(&port->dev, "%s - bad tty pointer - exiting\n", + __func__); + return; + } + if (tty && urb->actual_length) { /* Loop through the data copying each byte to the tty layer. */ tty_insert_flip_string(tty, data, urb->actual_length); diff --git a/trunk/drivers/usb/serial/mos7720.c b/trunk/drivers/usb/serial/mos7720.c index 012f67b2e4cc..a07dd3c8cfef 100644 --- a/trunk/drivers/usb/serial/mos7720.c +++ b/trunk/drivers/usb/serial/mos7720.c @@ -1349,7 +1349,7 @@ static void mos7720_throttle(struct tty_struct *tty) } /* if we are implementing RTS/CTS, toggle that line */ - if (tty->termios.c_cflag & CRTSCTS) { + if (tty->termios->c_cflag & CRTSCTS) { mos7720_port->shadowMCR &= ~UART_MCR_RTS; write_mos_reg(port->serial, port->number - port->serial->minor, MCR, mos7720_port->shadowMCR); @@ -1383,7 +1383,7 @@ static void mos7720_unthrottle(struct tty_struct *tty) } /* if we are implementing RTS/CTS, toggle that line */ - if (tty->termios.c_cflag & CRTSCTS) { + if (tty->termios->c_cflag & CRTSCTS) { mos7720_port->shadowMCR |= UART_MCR_RTS; write_mos_reg(port->serial, port->number - port->serial->minor, MCR, mos7720_port->shadowMCR); @@ -1604,8 +1604,8 @@ static void change_port_settings(struct tty_struct *tty, lStop = 0x00; /* 1 stop bit */ lParity = 0x00; /* No parity */ - cflag = tty->termios.c_cflag; - iflag = tty->termios.c_iflag; + cflag = tty->termios->c_cflag; + iflag = tty->termios->c_iflag; /* Change the number of bits */ switch (cflag & CSIZE) { @@ -1753,11 +1753,11 @@ static void mos7720_set_termios(struct tty_struct *tty, dbg("%s\n", "setting termios - ASPIRE"); - cflag = tty->termios.c_cflag; + cflag = tty->termios->c_cflag; dbg("%s - cflag %08x iflag %08x", __func__, - tty->termios.c_cflag, - RELEVANT_IFLAG(tty->termios.c_iflag)); + tty->termios->c_cflag, + RELEVANT_IFLAG(tty->termios->c_iflag)); dbg("%s - old cflag %08x old iflag %08x", __func__, old_termios->c_cflag, diff --git a/trunk/drivers/usb/serial/mos7840.c b/trunk/drivers/usb/serial/mos7840.c index 402c32d7accb..57eca2448424 100644 --- a/trunk/drivers/usb/serial/mos7840.c +++ b/trunk/drivers/usb/serial/mos7840.c @@ -82,7 +82,8 @@ * Defines used for sending commands to port */ -#define MOS_WDR_TIMEOUT 5000 /* default urb timeout */ +#define WAIT_FOR_EVER (HZ * 0) /* timeout urb is wait for ever */ +#define MOS_WDR_TIMEOUT (HZ * 5) /* default urb timeout */ #define MOS_PORT1 0x0200 #define MOS_PORT2 0x0300 @@ -1231,12 +1232,9 @@ static int mos7840_chars_in_buffer(struct tty_struct *tty) return 0; spin_lock_irqsave(&mos7840_port->pool_lock, flags); - for (i = 0; i < NUM_URBS; ++i) { - if (mos7840_port->busy[i]) { - struct urb *urb = mos7840_port->write_urb_pool[i]; - chars += urb->transfer_buffer_length; - } - } + for (i = 0; i < NUM_URBS; ++i) + if (mos7840_port->busy[i]) + chars += URB_TRANSFER_BUFFER_SIZE; spin_unlock_irqrestore(&mos7840_port->pool_lock, flags); dbg("%s - returns %d", __func__, chars); return chars; @@ -1346,7 +1344,7 @@ static void mos7840_close(struct usb_serial_port *port) static void mos7840_block_until_chase_response(struct tty_struct *tty, struct moschip_port *mos7840_port) { - int timeout = msecs_to_jiffies(1000); + int timeout = 1 * HZ; int wait = 10; int count; @@ -1651,7 +1649,7 @@ static void mos7840_throttle(struct tty_struct *tty) return; } /* if we are implementing RTS/CTS, toggle that line */ - if (tty->termios.c_cflag & CRTSCTS) { + if (tty->termios->c_cflag & CRTSCTS) { mos7840_port->shadowMCR &= ~MCR_RTS; status = mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, mos7840_port->shadowMCR); @@ -1694,7 +1692,7 @@ static void mos7840_unthrottle(struct tty_struct *tty) } /* if we are implementing RTS/CTS, toggle that line */ - if (tty->termios.c_cflag & CRTSCTS) { + if (tty->termios->c_cflag & CRTSCTS) { mos7840_port->shadowMCR |= MCR_RTS; status = mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, mos7840_port->shadowMCR); @@ -2000,8 +1998,8 @@ static void mos7840_change_port_settings(struct tty_struct *tty, lStop = LCR_STOP_1; lParity = LCR_PAR_NONE; - cflag = tty->termios.c_cflag; - iflag = tty->termios.c_iflag; + cflag = tty->termios->c_cflag; + iflag = tty->termios->c_iflag; /* Change the number of bits */ if (cflag & CSIZE) { @@ -2161,10 +2159,10 @@ static void mos7840_set_termios(struct tty_struct *tty, dbg("%s", "setting termios - "); - cflag = tty->termios.c_cflag; + cflag = tty->termios->c_cflag; dbg("%s - clfag %08x iflag %08x", __func__, - tty->termios.c_cflag, RELEVANT_IFLAG(tty->termios.c_iflag)); + tty->termios->c_cflag, RELEVANT_IFLAG(tty->termios->c_iflag)); dbg("%s - old clfag %08x old iflag %08x", __func__, old_termios->c_cflag, RELEVANT_IFLAG(old_termios->c_iflag)); dbg("%s - port %d", __func__, port->number); @@ -2674,7 +2672,7 @@ static int mos7840_startup(struct usb_serial *serial) /* setting configuration feature to one */ usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), - (__u8) 0x03, 0x00, 0x01, 0x00, NULL, 0x00, MOS_WDR_TIMEOUT); + (__u8) 0x03, 0x00, 0x01, 0x00, NULL, 0x00, 5 * HZ); return 0; error: for (/* nothing */; i >= 0; i--) { diff --git a/trunk/drivers/usb/serial/option.c b/trunk/drivers/usb/serial/option.c index 5ce88d1bc6f1..08ff9b862049 100644 --- a/trunk/drivers/usb/serial/option.c +++ b/trunk/drivers/usb/serial/option.c @@ -80,9 +80,85 @@ static void option_instat_callback(struct urb *urb); #define OPTION_PRODUCT_GTM380_MODEM 0x7201 #define HUAWEI_VENDOR_ID 0x12D1 +#define HUAWEI_PRODUCT_E600 0x1001 +#define HUAWEI_PRODUCT_E220 0x1003 +#define HUAWEI_PRODUCT_E220BIS 0x1004 +#define HUAWEI_PRODUCT_E1401 0x1401 +#define HUAWEI_PRODUCT_E1402 0x1402 +#define HUAWEI_PRODUCT_E1403 0x1403 +#define HUAWEI_PRODUCT_E1404 0x1404 +#define HUAWEI_PRODUCT_E1405 0x1405 +#define HUAWEI_PRODUCT_E1406 0x1406 +#define HUAWEI_PRODUCT_E1407 0x1407 +#define HUAWEI_PRODUCT_E1408 0x1408 +#define HUAWEI_PRODUCT_E1409 0x1409 +#define HUAWEI_PRODUCT_E140A 0x140A +#define HUAWEI_PRODUCT_E140B 0x140B +#define HUAWEI_PRODUCT_E140C 0x140C +#define HUAWEI_PRODUCT_E140D 0x140D +#define HUAWEI_PRODUCT_E140E 0x140E +#define HUAWEI_PRODUCT_E140F 0x140F +#define HUAWEI_PRODUCT_E1410 0x1410 +#define HUAWEI_PRODUCT_E1411 0x1411 +#define HUAWEI_PRODUCT_E1412 0x1412 +#define HUAWEI_PRODUCT_E1413 0x1413 +#define HUAWEI_PRODUCT_E1414 0x1414 +#define HUAWEI_PRODUCT_E1415 0x1415 +#define HUAWEI_PRODUCT_E1416 0x1416 +#define HUAWEI_PRODUCT_E1417 0x1417 +#define HUAWEI_PRODUCT_E1418 0x1418 +#define HUAWEI_PRODUCT_E1419 0x1419 +#define HUAWEI_PRODUCT_E141A 0x141A +#define HUAWEI_PRODUCT_E141B 0x141B +#define HUAWEI_PRODUCT_E141C 0x141C +#define HUAWEI_PRODUCT_E141D 0x141D +#define HUAWEI_PRODUCT_E141E 0x141E +#define HUAWEI_PRODUCT_E141F 0x141F +#define HUAWEI_PRODUCT_E1420 0x1420 +#define HUAWEI_PRODUCT_E1421 0x1421 +#define HUAWEI_PRODUCT_E1422 0x1422 +#define HUAWEI_PRODUCT_E1423 0x1423 +#define HUAWEI_PRODUCT_E1424 0x1424 +#define HUAWEI_PRODUCT_E1425 0x1425 +#define HUAWEI_PRODUCT_E1426 0x1426 +#define HUAWEI_PRODUCT_E1427 0x1427 +#define HUAWEI_PRODUCT_E1428 0x1428 +#define HUAWEI_PRODUCT_E1429 0x1429 +#define HUAWEI_PRODUCT_E142A 0x142A +#define HUAWEI_PRODUCT_E142B 0x142B +#define HUAWEI_PRODUCT_E142C 0x142C +#define HUAWEI_PRODUCT_E142D 0x142D +#define HUAWEI_PRODUCT_E142E 0x142E +#define HUAWEI_PRODUCT_E142F 0x142F +#define HUAWEI_PRODUCT_E1430 0x1430 +#define HUAWEI_PRODUCT_E1431 0x1431 +#define HUAWEI_PRODUCT_E1432 0x1432 +#define HUAWEI_PRODUCT_E1433 0x1433 +#define HUAWEI_PRODUCT_E1434 0x1434 +#define HUAWEI_PRODUCT_E1435 0x1435 +#define HUAWEI_PRODUCT_E1436 0x1436 +#define HUAWEI_PRODUCT_E1437 0x1437 +#define HUAWEI_PRODUCT_E1438 0x1438 +#define HUAWEI_PRODUCT_E1439 0x1439 +#define HUAWEI_PRODUCT_E143A 0x143A +#define HUAWEI_PRODUCT_E143B 0x143B +#define HUAWEI_PRODUCT_E143C 0x143C +#define HUAWEI_PRODUCT_E143D 0x143D +#define HUAWEI_PRODUCT_E143E 0x143E +#define HUAWEI_PRODUCT_E143F 0x143F #define HUAWEI_PRODUCT_K4505 0x1464 #define HUAWEI_PRODUCT_K3765 0x1465 +#define HUAWEI_PRODUCT_E14AC 0x14AC +#define HUAWEI_PRODUCT_K3806 0x14AE #define HUAWEI_PRODUCT_K4605 0x14C6 +#define HUAWEI_PRODUCT_K5005 0x14C8 +#define HUAWEI_PRODUCT_K3770 0x14C9 +#define HUAWEI_PRODUCT_K3771 0x14CA +#define HUAWEI_PRODUCT_K4510 0x14CB +#define HUAWEI_PRODUCT_K4511 0x14CC +#define HUAWEI_PRODUCT_ETS1220 0x1803 +#define HUAWEI_PRODUCT_E353 0x1506 +#define HUAWEI_PRODUCT_E173S 0x1C05 #define QUANTA_VENDOR_ID 0x0408 #define QUANTA_PRODUCT_Q101 0xEA02 @@ -539,123 +615,104 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE(QUANTA_VENDOR_ID, QUANTA_PRODUCT_GLX) }, { USB_DEVICE(QUANTA_VENDOR_ID, QUANTA_PRODUCT_GKE) }, { USB_DEVICE(QUANTA_VENDOR_ID, QUANTA_PRODUCT_GLE) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E600, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E220, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E220BIS, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1401, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1402, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1403, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1404, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1405, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1406, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1407, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1408, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1409, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E140A, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E140B, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E140C, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E140D, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E140E, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E140F, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1410, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1411, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1412, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1413, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1414, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1415, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1416, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1417, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1418, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1419, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E141A, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E141B, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E141C, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E141D, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E141E, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E141F, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1420, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1421, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1422, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1423, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1424, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1425, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1426, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1427, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1428, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1429, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E142A, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E142B, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E142C, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E142D, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E142E, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E142F, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1430, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1431, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1432, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1433, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1434, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1435, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1436, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1437, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1438, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1439, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143A, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143B, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143C, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143D, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143E, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143F, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E173S, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4505, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t) &huawei_cdc12_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3765, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t) &huawei_cdc12_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_ETS1220, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E14AC, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3806, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4605, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t) &huawei_cdc12_blacklist }, - { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0xff, 0xff) }, - { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x01) }, - { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x02) }, - { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x03) }, - { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x04) }, - { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x05) }, - { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x06) }, - { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x0A) }, - { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x0B) }, - { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x0D) }, - { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x0E) }, - { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x0F) }, - { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x10) }, - { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x12) }, - { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x13) }, - { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x14) }, - { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x15) }, - { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x17) }, - { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x18) }, - { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x19) }, - { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x1A) }, - { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x1B) }, - { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x1C) }, - { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x31) }, - { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x32) }, - { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x33) }, - { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x34) }, - { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x35) }, - { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x36) }, - { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x3A) }, - { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x3B) }, - { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x3D) }, - { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x3E) }, - { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x3F) }, - { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x48) }, - { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x49) }, - { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x4A) }, - { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x4B) }, - { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x4C) }, - { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x61) }, - { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x62) }, - { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x63) }, - { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x64) }, - { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x65) }, - { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x66) }, - { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x6A) }, - { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x6B) }, - { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x6D) }, - { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x6E) }, - { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x6F) }, - { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x78) }, - { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x79) }, - { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x7A) }, - { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x7B) }, - { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x7C) }, - { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x01) }, - { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x02) }, - { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x03) }, - { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x04) }, - { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x05) }, - { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x06) }, - { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x0A) }, - { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x0B) }, - { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x0D) }, - { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x0E) }, - { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x0F) }, - { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x10) }, - { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x12) }, - { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x13) }, - { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x14) }, - { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x15) }, - { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x17) }, - { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x18) }, - { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x19) }, - { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x1A) }, - { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x1B) }, - { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x1C) }, - { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x31) }, - { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x32) }, - { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x33) }, - { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x34) }, - { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x35) }, - { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x36) }, - { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x3A) }, - { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x3B) }, - { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x3D) }, - { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x3E) }, - { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x3F) }, - { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x48) }, - { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x49) }, - { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x4A) }, - { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x4B) }, - { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x4C) }, - { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x61) }, - { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x62) }, - { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x63) }, - { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x64) }, - { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x65) }, - { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x66) }, - { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x6A) }, - { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x6B) }, - { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x6D) }, - { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x6E) }, - { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x6F) }, - { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x78) }, - { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x79) }, - { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x7A) }, - { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x7B) }, - { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x7C) }, - - + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4605, 0xff, 0x01, 0x31) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4605, 0xff, 0x01, 0x32) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K5005, 0xff, 0x01, 0x31) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K5005, 0xff, 0x01, 0x32) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K5005, 0xff, 0x01, 0x33) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3770, 0xff, 0x02, 0x31) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3770, 0xff, 0x02, 0x32) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3771, 0xff, 0x02, 0x31) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3771, 0xff, 0x02, 0x32) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4510, 0xff, 0x01, 0x31) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4510, 0xff, 0x01, 0x32) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4511, 0xff, 0x01, 0x31) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4511, 0xff, 0x01, 0x32) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x01, 0x01) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x01, 0x02) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x01, 0x03) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x01, 0x10) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x01, 0x12) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x01, 0x13) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x02, 0x01) }, /* E398 3G Modem */ + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x02, 0x02) }, /* E398 3G PC UI Interface */ + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x02, 0x03) }, /* E398 3G Application Interface */ { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V640) }, { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V620) }, { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V740) }, @@ -1090,10 +1147,6 @@ static const struct usb_device_id option_ids[] = { .driver_info = (kernel_ulong_t)&zte_ad3812_z_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MC2716, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t)&zte_mc2716_z_blacklist }, - { USB_VENDOR_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff, 0x02, 0x01) }, - { USB_VENDOR_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff, 0x02, 0x05) }, - { USB_VENDOR_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff, 0x86, 0x10) }, - { USB_DEVICE(BENQ_VENDOR_ID, BENQ_PRODUCT_H10) }, { USB_DEVICE(DLINK_VENDOR_ID, DLINK_PRODUCT_DWM_652) }, { USB_DEVICE(ALINK_VENDOR_ID, DLINK_PRODUCT_DWM_652_U5) }, /* Yes, ALINK_VENDOR_ID */ @@ -1244,8 +1297,8 @@ static struct usb_serial_driver option_1port_device = { .tiocmset = usb_wwan_tiocmset, .ioctl = usb_wwan_ioctl, .attach = usb_wwan_startup, + .disconnect = usb_wwan_disconnect, .release = option_release, - .port_remove = usb_wwan_port_remove, .read_int_callback = option_instat_callback, #ifdef CONFIG_PM .suspend = usb_wwan_suspend, @@ -1361,6 +1414,8 @@ static void option_release(struct usb_serial *serial) struct usb_wwan_intf_private *intfdata = usb_get_serial_data(serial); struct option_private *priv = intfdata->private; + usb_wwan_release(serial); + kfree(priv); kfree(intfdata); } diff --git a/trunk/drivers/usb/serial/oti6858.c b/trunk/drivers/usb/serial/oti6858.c index 9f555560bfbf..5976b65ab6ee 100644 --- a/trunk/drivers/usb/serial/oti6858.c +++ b/trunk/drivers/usb/serial/oti6858.c @@ -404,10 +404,10 @@ static int oti6858_chars_in_buffer(struct tty_struct *tty) static void oti6858_init_termios(struct tty_struct *tty) { - tty->termios = tty_std_termios; - tty->termios.c_cflag = B38400 | CS8 | CREAD | HUPCL | CLOCAL; - tty->termios.c_ispeed = 38400; - tty->termios.c_ospeed = 38400; + *(tty->termios) = tty_std_termios; + tty->termios->c_cflag = B38400 | CS8 | CREAD | HUPCL | CLOCAL; + tty->termios->c_ispeed = 38400; + tty->termios->c_ospeed = 38400; } static void oti6858_set_termios(struct tty_struct *tty, @@ -425,7 +425,7 @@ static void oti6858_set_termios(struct tty_struct *tty, return; } - cflag = tty->termios.c_cflag; + cflag = tty->termios->c_cflag; spin_lock_irqsave(&priv->lock, flags); divisor = priv->pending_setup.divisor; diff --git a/trunk/drivers/usb/serial/pl2303.c b/trunk/drivers/usb/serial/pl2303.c index 2b9108a8ea64..13b8dd6481f5 100644 --- a/trunk/drivers/usb/serial/pl2303.c +++ b/trunk/drivers/usb/serial/pl2303.c @@ -260,16 +260,16 @@ static void pl2303_set_termios(struct tty_struct *tty, serial settings even to the same values as before. Thus we actually need to filter in this specific case */ - if (!tty_termios_hw_change(&tty->termios, old_termios)) + if (!tty_termios_hw_change(tty->termios, old_termios)) return; - cflag = tty->termios.c_cflag; + cflag = tty->termios->c_cflag; buf = kzalloc(7, GFP_KERNEL); if (!buf) { dev_err(&port->dev, "%s - out of memory.\n", __func__); /* Report back no change occurred */ - tty->termios = *old_termios; + *tty->termios = *old_termios; return; } diff --git a/trunk/drivers/usb/serial/qcserial.c b/trunk/drivers/usb/serial/qcserial.c index bfd50779f0c9..8d103019d6aa 100644 --- a/trunk/drivers/usb/serial/qcserial.c +++ b/trunk/drivers/usb/serial/qcserial.c @@ -199,49 +199,43 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id) /* default to enabling interface */ altsetting = 0; + switch (ifnum) { + /* Composite mode; don't bind to the QMI/net interface as that + * gets handled by other drivers. + */ - /* Composite mode; don't bind to the QMI/net interface as that - * gets handled by other drivers. - */ - - if (is_gobi1k) { /* Gobi 1K USB layout: * 0: serial port (doesn't respond) * 1: serial port (doesn't respond) * 2: AT-capable modem port * 3: QMI/net - */ - if (ifnum == 2) - dev_dbg(dev, "Modem port found\n"); - else - altsetting = -1; - } else { - /* Gobi 2K+ USB layout: + * + * Gobi 2K+ USB layout: * 0: QMI/net * 1: DM/DIAG (use libqcdm from ModemManager for communication) * 2: AT-capable modem port * 3: NMEA */ - switch (ifnum) { - case 0: - /* Don't claim the QMI/net interface */ + + case 1: + if (is_gobi1k) altsetting = -1; - break; - case 1: + else dev_dbg(dev, "Gobi 2K+ DM/DIAG interface found\n"); - break; - case 2: - dev_dbg(dev, "Modem port found\n"); - break; - case 3: + break; + case 2: + dev_dbg(dev, "Modem port found\n"); + break; + case 3: + if (is_gobi1k) + altsetting = -1; + else /* * NMEA (serial line 9600 8N1) * # echo "\$GPS_START" > /dev/ttyUSBx * # echo "\$GPS_STOP" > /dev/ttyUSBx */ dev_dbg(dev, "Gobi 2K+ NMEA GPS interface found\n"); - break; - } } done: @@ -268,7 +262,8 @@ static void qc_release(struct usb_serial *serial) { struct usb_wwan_intf_private *priv = usb_get_serial_data(serial); - /* Free the private data allocated in qcprobe */ + /* Call usb_wwan release & free the private data allocated in qcprobe */ + usb_wwan_release(serial); usb_set_serial_data(serial, NULL); kfree(priv); } @@ -288,8 +283,8 @@ static struct usb_serial_driver qcdevice = { .write_room = usb_wwan_write_room, .chars_in_buffer = usb_wwan_chars_in_buffer, .attach = usb_wwan_startup, + .disconnect = usb_wwan_disconnect, .release = qc_release, - .port_remove = usb_wwan_port_remove, #ifdef CONFIG_PM .suspend = usb_wwan_suspend, .resume = usb_wwan_resume, diff --git a/trunk/drivers/usb/serial/quatech2.c b/trunk/drivers/usb/serial/quatech2.c index 7df9cdb053ed..151670b6b72a 100644 --- a/trunk/drivers/usb/serial/quatech2.c +++ b/trunk/drivers/usb/serial/quatech2.c @@ -275,7 +275,7 @@ static void qt2_set_termios(struct tty_struct *tty, { struct usb_device *dev = port->serial->dev; struct qt2_port_private *port_priv; - struct ktermios *termios = &tty->termios; + struct ktermios *termios = tty->termios; u16 baud; unsigned int cflag = termios->c_cflag; u16 new_lcr = 0; @@ -406,7 +406,7 @@ static int qt2_open(struct tty_struct *tty, struct usb_serial_port *port) port_priv->device_port = (u8) device_port; if (tty) - qt2_set_termios(tty, port, &tty->termios); + qt2_set_termios(tty, port, tty->termios); return 0; diff --git a/trunk/drivers/usb/serial/sierra.c b/trunk/drivers/usb/serial/sierra.c index b14ebbd73567..0274710cced5 100644 --- a/trunk/drivers/usb/serial/sierra.c +++ b/trunk/drivers/usb/serial/sierra.c @@ -382,7 +382,7 @@ static int sierra_send_setup(struct usb_serial_port *port) static void sierra_set_termios(struct tty_struct *tty, struct usb_serial_port *port, struct ktermios *old_termios) { - tty_termios_copy_hw(&tty->termios, old_termios); + tty_termios_copy_hw(tty->termios, old_termios); sierra_send_setup(port); } diff --git a/trunk/drivers/usb/serial/spcp8x5.c b/trunk/drivers/usb/serial/spcp8x5.c index ab68a4d74d61..cad608984710 100644 --- a/trunk/drivers/usb/serial/spcp8x5.c +++ b/trunk/drivers/usb/serial/spcp8x5.c @@ -316,10 +316,10 @@ static void spcp8x5_dtr_rts(struct usb_serial_port *port, int on) static void spcp8x5_init_termios(struct tty_struct *tty) { /* for the 1st time call this function */ - tty->termios = tty_std_termios; - tty->termios.c_cflag = B115200 | CS8 | CREAD | HUPCL | CLOCAL; - tty->termios.c_ispeed = 115200; - tty->termios.c_ospeed = 115200; + *(tty->termios) = tty_std_termios; + tty->termios->c_cflag = B115200 | CS8 | CREAD | HUPCL | CLOCAL; + tty->termios->c_ispeed = 115200; + tty->termios->c_ospeed = 115200; } /* set the serial param for transfer. we should check if we really need to @@ -330,7 +330,7 @@ static void spcp8x5_set_termios(struct tty_struct *tty, struct usb_serial *serial = port->serial; struct spcp8x5_private *priv = usb_get_serial_port_data(port); unsigned long flags; - unsigned int cflag = tty->termios.c_cflag; + unsigned int cflag = tty->termios->c_cflag; unsigned int old_cflag = old_termios->c_cflag; unsigned short uartdata; unsigned char buf[2] = {0, 0}; @@ -340,7 +340,7 @@ static void spcp8x5_set_termios(struct tty_struct *tty, /* check that they really want us to change something */ - if (!tty_termios_hw_change(&tty->termios, old_termios)) + if (!tty_termios_hw_change(tty->termios, old_termios)) return; /* set DTR/RTS active */ diff --git a/trunk/drivers/usb/serial/ssu100.c b/trunk/drivers/usb/serial/ssu100.c index cf2d30cf7588..3fee23bf0c14 100644 --- a/trunk/drivers/usb/serial/ssu100.c +++ b/trunk/drivers/usb/serial/ssu100.c @@ -216,7 +216,7 @@ static void ssu100_set_termios(struct tty_struct *tty, struct ktermios *old_termios) { struct usb_device *dev = port->serial->dev; - struct ktermios *termios = &tty->termios; + struct ktermios *termios = tty->termios; u16 baud, divisor, remainder; unsigned int cflag = termios->c_cflag; u16 urb_value = 0; /* will hold the new flags */ @@ -322,7 +322,7 @@ static int ssu100_open(struct tty_struct *tty, struct usb_serial_port *port) dbg("%s - set uart failed", __func__); if (tty) - ssu100_set_termios(tty, port, &tty->termios); + ssu100_set_termios(tty, port, tty->termios); return usb_serial_generic_open(tty, port); } diff --git a/trunk/drivers/usb/serial/ti_usb_3410_5052.c b/trunk/drivers/usb/serial/ti_usb_3410_5052.c index f502a16aac21..a4404f5ad68e 100644 --- a/trunk/drivers/usb/serial/ti_usb_3410_5052.c +++ b/trunk/drivers/usb/serial/ti_usb_3410_5052.c @@ -520,7 +520,7 @@ static int ti_open(struct tty_struct *tty, struct usb_serial_port *port) } if (tty) - ti_set_termios(tty, port, &tty->termios); + ti_set_termios(tty, port, tty->termios); dbg("%s - sending TI_OPEN_PORT", __func__); status = ti_command_out_sync(tdev, TI_OPEN_PORT, @@ -562,7 +562,7 @@ static int ti_open(struct tty_struct *tty, struct usb_serial_port *port) usb_clear_halt(dev, port->read_urb->pipe); if (tty) - ti_set_termios(tty, port, &tty->termios); + ti_set_termios(tty, port, tty->termios); dbg("%s - sending TI_OPEN_PORT (2)", __func__); status = ti_command_out_sync(tdev, TI_OPEN_PORT, @@ -831,8 +831,8 @@ static void ti_set_termios(struct tty_struct *tty, int port_number = port->number - port->serial->minor; unsigned int mcr; - cflag = tty->termios.c_cflag; - iflag = tty->termios.c_iflag; + cflag = tty->termios->c_cflag; + iflag = tty->termios->c_iflag; dbg("%s - cflag %08x, iflag %08x", __func__, cflag, iflag); dbg("%s - old clfag %08x, old iflag %08x", __func__, @@ -871,7 +871,7 @@ static void ti_set_termios(struct tty_struct *tty, } /* CMSPAR isn't supported by this driver */ - tty->termios.c_cflag &= ~CMSPAR; + tty->termios->c_cflag &= ~CMSPAR; if (cflag & PARENB) { if (cflag & PARODD) { diff --git a/trunk/drivers/usb/serial/usb-serial.c b/trunk/drivers/usb/serial/usb-serial.c index aa4b0d775992..27483f91a4a3 100644 --- a/trunk/drivers/usb/serial/usb-serial.c +++ b/trunk/drivers/usb/serial/usb-serial.c @@ -207,7 +207,7 @@ static int serial_install(struct tty_driver *driver, struct tty_struct *tty) if (retval) goto error_get_interface; - retval = tty_port_install(&port->port, driver, tty); + retval = tty_standard_install(driver, tty); if (retval) goto error_init_termios; @@ -305,7 +305,8 @@ static void serial_close(struct tty_struct *tty, struct file *filp) * Do the resource freeing and refcount dropping for the port. * Avoid freeing the console. * - * Called asynchronously after the last tty kref is dropped. + * Called asynchronously after the last tty kref is dropped, + * and the tty layer has already done the tty_shutdown(tty); */ static void serial_cleanup(struct tty_struct *tty) { @@ -422,7 +423,7 @@ static void serial_set_termios(struct tty_struct *tty, struct ktermios *old) if (port->serial->type->set_termios) port->serial->type->set_termios(tty, port, old); else - tty_termios_copy_hw(&tty->termios, old); + tty_termios_copy_hw(tty->termios, old); } static int serial_break(struct tty_struct *tty, int break_state) diff --git a/trunk/drivers/usb/serial/usb-wwan.h b/trunk/drivers/usb/serial/usb-wwan.h index 1f034d2397c6..c47b6ec03063 100644 --- a/trunk/drivers/usb/serial/usb-wwan.h +++ b/trunk/drivers/usb/serial/usb-wwan.h @@ -9,7 +9,8 @@ extern void usb_wwan_dtr_rts(struct usb_serial_port *port, int on); extern int usb_wwan_open(struct tty_struct *tty, struct usb_serial_port *port); extern void usb_wwan_close(struct usb_serial_port *port); extern int usb_wwan_startup(struct usb_serial *serial); -extern int usb_wwan_port_remove(struct usb_serial_port *port); +extern void usb_wwan_disconnect(struct usb_serial *serial); +extern void usb_wwan_release(struct usb_serial *serial); extern int usb_wwan_write_room(struct tty_struct *tty); extern void usb_wwan_set_termios(struct tty_struct *tty, struct usb_serial_port *port, diff --git a/trunk/drivers/usb/serial/usb_wwan.c b/trunk/drivers/usb/serial/usb_wwan.c index 72b678d90831..f35971dff4a5 100644 --- a/trunk/drivers/usb/serial/usb_wwan.c +++ b/trunk/drivers/usb/serial/usb_wwan.c @@ -67,7 +67,7 @@ void usb_wwan_set_termios(struct tty_struct *tty, struct usb_wwan_intf_private *intfdata = port->serial->private; /* Doesn't support option setting */ - tty_termios_copy_hw(&tty->termios, old_termios); + tty_termios_copy_hw(tty->termios, old_termios); if (intfdata->send_setup) intfdata->send_setup(port); @@ -565,52 +565,62 @@ int usb_wwan_startup(struct usb_serial *serial) } EXPORT_SYMBOL(usb_wwan_startup); -int usb_wwan_port_remove(struct usb_serial_port *port) +static void stop_read_write_urbs(struct usb_serial *serial) { - int i; + int i, j; + struct usb_serial_port *port; struct usb_wwan_port_private *portdata; - portdata = usb_get_serial_port_data(port); - usb_set_serial_port_data(port, NULL); - - /* Stop reading/writing urbs and free them */ - for (i = 0; i < N_IN_URB; i++) { - usb_kill_urb(portdata->in_urbs[i]); - usb_free_urb(portdata->in_urbs[i]); - free_page((unsigned long)portdata->in_buffer[i]); - } - for (i = 0; i < N_OUT_URB; i++) { - usb_kill_urb(portdata->out_urbs[i]); - usb_free_urb(portdata->out_urbs[i]); - kfree(portdata->out_buffer[i]); + /* Stop reading/writing urbs */ + for (i = 0; i < serial->num_ports; ++i) { + port = serial->port[i]; + portdata = usb_get_serial_port_data(port); + for (j = 0; j < N_IN_URB; j++) + usb_kill_urb(portdata->in_urbs[j]); + for (j = 0; j < N_OUT_URB; j++) + usb_kill_urb(portdata->out_urbs[j]); } +} - /* Now free port private data */ - kfree(portdata); - return 0; +void usb_wwan_disconnect(struct usb_serial *serial) +{ + stop_read_write_urbs(serial); } -EXPORT_SYMBOL(usb_wwan_port_remove); +EXPORT_SYMBOL(usb_wwan_disconnect); -#ifdef CONFIG_PM -static void stop_read_write_urbs(struct usb_serial *serial) +void usb_wwan_release(struct usb_serial *serial) { int i, j; struct usb_serial_port *port; struct usb_wwan_port_private *portdata; - /* Stop reading/writing urbs */ + /* Now free them */ for (i = 0; i < serial->num_ports; ++i) { port = serial->port[i]; portdata = usb_get_serial_port_data(port); - if (!portdata) - continue; - for (j = 0; j < N_IN_URB; j++) - usb_kill_urb(portdata->in_urbs[j]); - for (j = 0; j < N_OUT_URB; j++) - usb_kill_urb(portdata->out_urbs[j]); + + for (j = 0; j < N_IN_URB; j++) { + usb_free_urb(portdata->in_urbs[j]); + free_page((unsigned long) + portdata->in_buffer[j]); + portdata->in_urbs[j] = NULL; + } + for (j = 0; j < N_OUT_URB; j++) { + usb_free_urb(portdata->out_urbs[j]); + kfree(portdata->out_buffer[j]); + portdata->out_urbs[j] = NULL; + } + } + + /* Now free per port private data */ + for (i = 0; i < serial->num_ports; i++) { + port = serial->port[i]; + kfree(usb_get_serial_port_data(port)); } } +EXPORT_SYMBOL(usb_wwan_release); +#ifdef CONFIG_PM int usb_wwan_suspend(struct usb_serial *serial, pm_message_t message) { struct usb_wwan_intf_private *intfdata = serial->private; @@ -702,7 +712,7 @@ int usb_wwan_resume(struct usb_serial *serial) /* skip closed ports */ spin_lock_irq(&intfdata->susp_lock); - if (!portdata || !portdata->opened) { + if (!portdata->opened) { spin_unlock_irq(&intfdata->susp_lock); continue; } diff --git a/trunk/drivers/usb/serial/whiteheat.c b/trunk/drivers/usb/serial/whiteheat.c index b36077de72b9..473635e7f5db 100644 --- a/trunk/drivers/usb/serial/whiteheat.c +++ b/trunk/drivers/usb/serial/whiteheat.c @@ -724,7 +724,7 @@ static void firm_setup_port(struct tty_struct *tty) { struct usb_serial_port *port = tty->driver_data; struct whiteheat_port_settings port_settings; - unsigned int cflag = tty->termios.c_cflag; + unsigned int cflag = tty->termios->c_cflag; port_settings.port = port->number + 1; diff --git a/trunk/drivers/vfio/pci/vfio_pci_intrs.c b/trunk/drivers/vfio/pci/vfio_pci_intrs.c index d8dedc7d3910..211a4920b88a 100644 --- a/trunk/drivers/vfio/pci/vfio_pci_intrs.c +++ b/trunk/drivers/vfio/pci/vfio_pci_intrs.c @@ -76,24 +76,9 @@ static int virqfd_wakeup(wait_queue_t *wait, unsigned mode, int sync, void *key) schedule_work(&virqfd->inject); } - if (flags & POLLHUP) { - unsigned long flags; - spin_lock_irqsave(&virqfd->vdev->irqlock, flags); - - /* - * The eventfd is closing, if the virqfd has not yet been - * queued for release, as determined by testing whether the - * vdev pointer to it is still valid, queue it now. As - * with kvm irqfds, we know we won't race against the virqfd - * going away because we hold wqh->lock to get here. - */ - if (*(virqfd->pvirqfd) == virqfd) { - *(virqfd->pvirqfd) = NULL; - virqfd_deactivate(virqfd); - } - - spin_unlock_irqrestore(&virqfd->vdev->irqlock, flags); - } + if (flags & POLLHUP) + /* The eventfd is closing, detach from VFIO */ + virqfd_deactivate(virqfd); return 0; } @@ -108,6 +93,7 @@ static void virqfd_ptable_queue_proc(struct file *file, static void virqfd_shutdown(struct work_struct *work) { struct virqfd *virqfd = container_of(work, struct virqfd, shutdown); + struct virqfd **pvirqfd = virqfd->pvirqfd; u64 cnt; eventfd_ctx_remove_wait_queue(virqfd->eventfd, &virqfd->wait, &cnt); @@ -115,6 +101,7 @@ static void virqfd_shutdown(struct work_struct *work) eventfd_ctx_put(virqfd->eventfd); kfree(virqfd); + *pvirqfd = NULL; } static void virqfd_inject(struct work_struct *work) @@ -135,11 +122,15 @@ static int virqfd_enable(struct vfio_pci_device *vdev, int ret = 0; unsigned int events; + if (*pvirqfd) + return -EBUSY; + virqfd = kzalloc(sizeof(*virqfd), GFP_KERNEL); if (!virqfd) return -ENOMEM; virqfd->pvirqfd = pvirqfd; + *pvirqfd = virqfd; virqfd->vdev = vdev; virqfd->handler = handler; virqfd->thread = thread; @@ -162,23 +153,6 @@ static int virqfd_enable(struct vfio_pci_device *vdev, virqfd->eventfd = ctx; - /* - * virqfds can be released by closing the eventfd or directly - * through ioctl. These are both done through a workqueue, so - * we update the pointer to the virqfd under lock to avoid - * pushing multiple jobs to release the same virqfd. - */ - spin_lock_irq(&vdev->irqlock); - - if (*pvirqfd) { - spin_unlock_irq(&vdev->irqlock); - ret = -EBUSY; - goto fail; - } - *pvirqfd = virqfd; - - spin_unlock_irq(&vdev->irqlock); - /* * Install our own custom wake-up handling so we are notified via * a callback whenever someone signals the underlying eventfd. @@ -213,29 +187,19 @@ static int virqfd_enable(struct vfio_pci_device *vdev, fput(file); kfree(virqfd); + *pvirqfd = NULL; return ret; } -static void virqfd_disable(struct vfio_pci_device *vdev, - struct virqfd **pvirqfd) +static void virqfd_disable(struct virqfd *virqfd) { - unsigned long flags; - - spin_lock_irqsave(&vdev->irqlock, flags); - - if (*pvirqfd) { - virqfd_deactivate(*pvirqfd); - *pvirqfd = NULL; - } + if (!virqfd) + return; - spin_unlock_irqrestore(&vdev->irqlock, flags); + virqfd_deactivate(virqfd); - /* - * Block until we know all outstanding shutdown jobs have completed. - * Even if we don't queue the job, flush the wq to be sure it's - * been released. - */ + /* Block until we know all outstanding shutdown jobs have completed. */ flush_workqueue(vfio_irqfd_cleanup_wq); } @@ -428,8 +392,8 @@ static int vfio_intx_set_signal(struct vfio_pci_device *vdev, int fd) static void vfio_intx_disable(struct vfio_pci_device *vdev) { vfio_intx_set_signal(vdev, -1); - virqfd_disable(vdev, &vdev->ctx[0].unmask); - virqfd_disable(vdev, &vdev->ctx[0].mask); + virqfd_disable(vdev->ctx[0].unmask); + virqfd_disable(vdev->ctx[0].mask); vdev->irq_type = VFIO_PCI_NUM_IRQS; vdev->num_ctx = 0; kfree(vdev->ctx); @@ -575,8 +539,8 @@ static void vfio_msi_disable(struct vfio_pci_device *vdev, bool msix) vfio_msi_set_block(vdev, 0, vdev->num_ctx, NULL, msix); for (i = 0; i < vdev->num_ctx; i++) { - virqfd_disable(vdev, &vdev->ctx[i].unmask); - virqfd_disable(vdev, &vdev->ctx[i].mask); + virqfd_disable(vdev->ctx[i].unmask); + virqfd_disable(vdev->ctx[i].mask); } if (msix) { @@ -613,7 +577,7 @@ static int vfio_pci_set_intx_unmask(struct vfio_pci_device *vdev, vfio_send_intx_eventfd, NULL, &vdev->ctx[0].unmask, fd); - virqfd_disable(vdev, &vdev->ctx[0].unmask); + virqfd_disable(vdev->ctx[0].unmask); } return 0; diff --git a/trunk/drivers/vfio/vfio.c b/trunk/drivers/vfio/vfio.c index 17830c9c7cc6..9591e2b509d7 100644 --- a/trunk/drivers/vfio/vfio.c +++ b/trunk/drivers/vfio/vfio.c @@ -264,7 +264,6 @@ static struct vfio_group *vfio_create_group(struct iommu_group *iommu_group) return group; } -/* called with vfio.group_lock held */ static void vfio_group_release(struct kref *kref) { struct vfio_group *group = container_of(kref, struct vfio_group, kref); @@ -288,7 +287,13 @@ static void vfio_group_release(struct kref *kref) static void vfio_group_put(struct vfio_group *group) { - kref_put_mutex(&group->kref, vfio_group_release, &vfio.group_lock); + mutex_lock(&vfio.group_lock); + /* + * Release needs to unlock to unregister the notifier, so only + * unlock if not released. + */ + if (!kref_put(&group->kref, vfio_group_release)) + mutex_unlock(&vfio.group_lock); } /* Assume group_lock or group reference is held */ @@ -396,6 +401,7 @@ static void vfio_device_release(struct kref *kref) struct vfio_device, kref); struct vfio_group *group = device->group; + mutex_lock(&group->device_lock); list_del(&device->group_next); mutex_unlock(&group->device_lock); @@ -410,9 +416,8 @@ static void vfio_device_release(struct kref *kref) /* Device reference always implies a group reference */ static void vfio_device_put(struct vfio_device *device) { - struct vfio_group *group = device->group; - kref_put_mutex(&device->kref, vfio_device_release, &group->device_lock); - vfio_group_put(group); + kref_put(&device->kref, vfio_device_release); + vfio_group_put(device->group); } static void vfio_device_get(struct vfio_device *device) @@ -1111,10 +1116,10 @@ static int vfio_group_get_device_fd(struct vfio_group *group, char *buf) */ filep->f_mode |= (FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE); + fd_install(ret, filep); + vfio_device_get(device); atomic_inc(&group->container_users); - - fd_install(ret, filep); break; } mutex_unlock(&group->device_lock); diff --git a/trunk/drivers/vhost/Kconfig b/trunk/drivers/vhost/Kconfig index 202bba6c997c..e4e2fd1b5107 100644 --- a/trunk/drivers/vhost/Kconfig +++ b/trunk/drivers/vhost/Kconfig @@ -9,6 +9,3 @@ config VHOST_NET To compile this driver as a module, choose M here: the module will be called vhost_net. -if STAGING -source "drivers/vhost/Kconfig.tcm" -endif diff --git a/trunk/drivers/vhost/Kconfig.tcm b/trunk/drivers/vhost/Kconfig.tcm deleted file mode 100644 index a9c6f76e3208..000000000000 --- a/trunk/drivers/vhost/Kconfig.tcm +++ /dev/null @@ -1,6 +0,0 @@ -config TCM_VHOST - tristate "TCM_VHOST fabric module (EXPERIMENTAL)" - depends on TARGET_CORE && EVENTFD && EXPERIMENTAL && m - default n - ---help--- - Say M here to enable the TCM_VHOST fabric module for use with virtio-scsi guests diff --git a/trunk/drivers/vhost/Makefile b/trunk/drivers/vhost/Makefile index a27b053bc9ab..72dd02050bb9 100644 --- a/trunk/drivers/vhost/Makefile +++ b/trunk/drivers/vhost/Makefile @@ -1,4 +1,2 @@ obj-$(CONFIG_VHOST_NET) += vhost_net.o vhost_net-y := vhost.o net.o - -obj-$(CONFIG_TCM_VHOST) += tcm_vhost.o diff --git a/trunk/drivers/vhost/tcm_vhost.c b/trunk/drivers/vhost/tcm_vhost.c deleted file mode 100644 index ed8e2e6c8df2..000000000000 --- a/trunk/drivers/vhost/tcm_vhost.c +++ /dev/null @@ -1,1649 +0,0 @@ -/******************************************************************************* - * Vhost kernel TCM fabric driver for virtio SCSI initiators - * - * (C) Copyright 2010-2012 RisingTide Systems LLC. - * (C) Copyright 2010-2012 IBM Corp. - * - * Licensed to the Linux Foundation under the General Public License (GPL) version 2. - * - * Authors: Nicholas A. Bellinger - * Stefan Hajnoczi - * - * 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. - * - ****************************************************************************/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include /* TODO vhost.h currently depends on this */ -#include - -#include "vhost.c" -#include "vhost.h" -#include "tcm_vhost.h" - -enum { - VHOST_SCSI_VQ_CTL = 0, - VHOST_SCSI_VQ_EVT = 1, - VHOST_SCSI_VQ_IO = 2, -}; - -struct vhost_scsi { - struct tcm_vhost_tpg *vs_tpg; /* Protected by vhost_scsi->dev.mutex */ - struct vhost_dev dev; - struct vhost_virtqueue vqs[3]; - - struct vhost_work vs_completion_work; /* cmd completion work item */ - struct list_head vs_completion_list; /* cmd completion queue */ - spinlock_t vs_completion_lock; /* protects s_completion_list */ -}; - -/* Local pointer to allocated TCM configfs fabric module */ -static struct target_fabric_configfs *tcm_vhost_fabric_configfs; - -static struct workqueue_struct *tcm_vhost_workqueue; - -/* Global spinlock to protect tcm_vhost TPG list for vhost IOCTL access */ -static DEFINE_MUTEX(tcm_vhost_mutex); -static LIST_HEAD(tcm_vhost_list); - -static int tcm_vhost_check_true(struct se_portal_group *se_tpg) -{ - return 1; -} - -static int tcm_vhost_check_false(struct se_portal_group *se_tpg) -{ - return 0; -} - -static char *tcm_vhost_get_fabric_name(void) -{ - return "vhost"; -} - -static u8 tcm_vhost_get_fabric_proto_ident(struct se_portal_group *se_tpg) -{ - struct tcm_vhost_tpg *tpg = container_of(se_tpg, - struct tcm_vhost_tpg, se_tpg); - struct tcm_vhost_tport *tport = tpg->tport; - - switch (tport->tport_proto_id) { - case SCSI_PROTOCOL_SAS: - return sas_get_fabric_proto_ident(se_tpg); - case SCSI_PROTOCOL_FCP: - return fc_get_fabric_proto_ident(se_tpg); - case SCSI_PROTOCOL_ISCSI: - return iscsi_get_fabric_proto_ident(se_tpg); - default: - pr_err("Unknown tport_proto_id: 0x%02x, using" - " SAS emulation\n", tport->tport_proto_id); - break; - } - - return sas_get_fabric_proto_ident(se_tpg); -} - -static char *tcm_vhost_get_fabric_wwn(struct se_portal_group *se_tpg) -{ - struct tcm_vhost_tpg *tpg = container_of(se_tpg, - struct tcm_vhost_tpg, se_tpg); - struct tcm_vhost_tport *tport = tpg->tport; - - return &tport->tport_name[0]; -} - -static u16 tcm_vhost_get_tag(struct se_portal_group *se_tpg) -{ - struct tcm_vhost_tpg *tpg = container_of(se_tpg, - struct tcm_vhost_tpg, se_tpg); - return tpg->tport_tpgt; -} - -static u32 tcm_vhost_get_default_depth(struct se_portal_group *se_tpg) -{ - return 1; -} - -static u32 tcm_vhost_get_pr_transport_id(struct se_portal_group *se_tpg, - struct se_node_acl *se_nacl, - struct t10_pr_registration *pr_reg, - int *format_code, - unsigned char *buf) -{ - struct tcm_vhost_tpg *tpg = container_of(se_tpg, - struct tcm_vhost_tpg, se_tpg); - struct tcm_vhost_tport *tport = tpg->tport; - - switch (tport->tport_proto_id) { - case SCSI_PROTOCOL_SAS: - return sas_get_pr_transport_id(se_tpg, se_nacl, pr_reg, - format_code, buf); - case SCSI_PROTOCOL_FCP: - return fc_get_pr_transport_id(se_tpg, se_nacl, pr_reg, - format_code, buf); - case SCSI_PROTOCOL_ISCSI: - return iscsi_get_pr_transport_id(se_tpg, se_nacl, pr_reg, - format_code, buf); - default: - pr_err("Unknown tport_proto_id: 0x%02x, using" - " SAS emulation\n", tport->tport_proto_id); - break; - } - - return sas_get_pr_transport_id(se_tpg, se_nacl, pr_reg, - format_code, buf); -} - -static u32 tcm_vhost_get_pr_transport_id_len(struct se_portal_group *se_tpg, - struct se_node_acl *se_nacl, - struct t10_pr_registration *pr_reg, - int *format_code) -{ - struct tcm_vhost_tpg *tpg = container_of(se_tpg, - struct tcm_vhost_tpg, se_tpg); - struct tcm_vhost_tport *tport = tpg->tport; - - switch (tport->tport_proto_id) { - case SCSI_PROTOCOL_SAS: - return sas_get_pr_transport_id_len(se_tpg, se_nacl, pr_reg, - format_code); - case SCSI_PROTOCOL_FCP: - return fc_get_pr_transport_id_len(se_tpg, se_nacl, pr_reg, - format_code); - case SCSI_PROTOCOL_ISCSI: - return iscsi_get_pr_transport_id_len(se_tpg, se_nacl, pr_reg, - format_code); - default: - pr_err("Unknown tport_proto_id: 0x%02x, using" - " SAS emulation\n", tport->tport_proto_id); - break; - } - - return sas_get_pr_transport_id_len(se_tpg, se_nacl, pr_reg, - format_code); -} - -static char *tcm_vhost_parse_pr_out_transport_id(struct se_portal_group *se_tpg, - const char *buf, - u32 *out_tid_len, - char **port_nexus_ptr) -{ - struct tcm_vhost_tpg *tpg = container_of(se_tpg, - struct tcm_vhost_tpg, se_tpg); - struct tcm_vhost_tport *tport = tpg->tport; - - switch (tport->tport_proto_id) { - case SCSI_PROTOCOL_SAS: - return sas_parse_pr_out_transport_id(se_tpg, buf, out_tid_len, - port_nexus_ptr); - case SCSI_PROTOCOL_FCP: - return fc_parse_pr_out_transport_id(se_tpg, buf, out_tid_len, - port_nexus_ptr); - case SCSI_PROTOCOL_ISCSI: - return iscsi_parse_pr_out_transport_id(se_tpg, buf, out_tid_len, - port_nexus_ptr); - default: - pr_err("Unknown tport_proto_id: 0x%02x, using" - " SAS emulation\n", tport->tport_proto_id); - break; - } - - return sas_parse_pr_out_transport_id(se_tpg, buf, out_tid_len, - port_nexus_ptr); -} - -static struct se_node_acl *tcm_vhost_alloc_fabric_acl( - struct se_portal_group *se_tpg) -{ - struct tcm_vhost_nacl *nacl; - - nacl = kzalloc(sizeof(struct tcm_vhost_nacl), GFP_KERNEL); - if (!nacl) { - pr_err("Unable to alocate struct tcm_vhost_nacl\n"); - return NULL; - } - - return &nacl->se_node_acl; -} - -static void tcm_vhost_release_fabric_acl(struct se_portal_group *se_tpg, - struct se_node_acl *se_nacl) -{ - struct tcm_vhost_nacl *nacl = container_of(se_nacl, - struct tcm_vhost_nacl, se_node_acl); - kfree(nacl); -} - -static u32 tcm_vhost_tpg_get_inst_index(struct se_portal_group *se_tpg) -{ - return 1; -} - -static void tcm_vhost_release_cmd(struct se_cmd *se_cmd) -{ - return; -} - -static int tcm_vhost_shutdown_session(struct se_session *se_sess) -{ - return 0; -} - -static void tcm_vhost_close_session(struct se_session *se_sess) -{ - return; -} - -static u32 tcm_vhost_sess_get_index(struct se_session *se_sess) -{ - return 0; -} - -static int tcm_vhost_write_pending(struct se_cmd *se_cmd) -{ - /* Go ahead and process the write immediately */ - target_execute_cmd(se_cmd); - return 0; -} - -static int tcm_vhost_write_pending_status(struct se_cmd *se_cmd) -{ - return 0; -} - -static void tcm_vhost_set_default_node_attrs(struct se_node_acl *nacl) -{ - return; -} - -static u32 tcm_vhost_get_task_tag(struct se_cmd *se_cmd) -{ - return 0; -} - -static int tcm_vhost_get_cmd_state(struct se_cmd *se_cmd) -{ - return 0; -} - -static void vhost_scsi_complete_cmd(struct tcm_vhost_cmd *tv_cmd) -{ - struct vhost_scsi *vs = tv_cmd->tvc_vhost; - - spin_lock_bh(&vs->vs_completion_lock); - list_add_tail(&tv_cmd->tvc_completion_list, &vs->vs_completion_list); - spin_unlock_bh(&vs->vs_completion_lock); - - vhost_work_queue(&vs->dev, &vs->vs_completion_work); -} - -static int tcm_vhost_queue_data_in(struct se_cmd *se_cmd) -{ - struct tcm_vhost_cmd *tv_cmd = container_of(se_cmd, - struct tcm_vhost_cmd, tvc_se_cmd); - vhost_scsi_complete_cmd(tv_cmd); - return 0; -} - -static int tcm_vhost_queue_status(struct se_cmd *se_cmd) -{ - struct tcm_vhost_cmd *tv_cmd = container_of(se_cmd, - struct tcm_vhost_cmd, tvc_se_cmd); - vhost_scsi_complete_cmd(tv_cmd); - return 0; -} - -static int tcm_vhost_queue_tm_rsp(struct se_cmd *se_cmd) -{ - return 0; -} - -static u16 tcm_vhost_set_fabric_sense_len(struct se_cmd *se_cmd, - u32 sense_length) -{ - return 0; -} - -static u16 tcm_vhost_get_fabric_sense_len(void) -{ - return 0; -} - -static void vhost_scsi_free_cmd(struct tcm_vhost_cmd *tv_cmd) -{ - struct se_cmd *se_cmd = &tv_cmd->tvc_se_cmd; - - /* TODO locking against target/backend threads? */ - transport_generic_free_cmd(se_cmd, 1); - - if (tv_cmd->tvc_sgl_count) { - u32 i; - for (i = 0; i < tv_cmd->tvc_sgl_count; i++) - put_page(sg_page(&tv_cmd->tvc_sgl[i])); - - kfree(tv_cmd->tvc_sgl); - } - - kfree(tv_cmd); -} - -/* Dequeue a command from the completion list */ -static struct tcm_vhost_cmd *vhost_scsi_get_cmd_from_completion( - struct vhost_scsi *vs) -{ - struct tcm_vhost_cmd *tv_cmd = NULL; - - spin_lock_bh(&vs->vs_completion_lock); - if (list_empty(&vs->vs_completion_list)) { - spin_unlock_bh(&vs->vs_completion_lock); - return NULL; - } - - list_for_each_entry(tv_cmd, &vs->vs_completion_list, - tvc_completion_list) { - list_del(&tv_cmd->tvc_completion_list); - break; - } - spin_unlock_bh(&vs->vs_completion_lock); - return tv_cmd; -} - -/* Fill in status and signal that we are done processing this command - * - * This is scheduled in the vhost work queue so we are called with the owner - * process mm and can access the vring. - */ -static void vhost_scsi_complete_cmd_work(struct vhost_work *work) -{ - struct vhost_scsi *vs = container_of(work, struct vhost_scsi, - vs_completion_work); - struct tcm_vhost_cmd *tv_cmd; - - while ((tv_cmd = vhost_scsi_get_cmd_from_completion(vs))) { - struct virtio_scsi_cmd_resp v_rsp; - struct se_cmd *se_cmd = &tv_cmd->tvc_se_cmd; - int ret; - - pr_debug("%s tv_cmd %p resid %u status %#02x\n", __func__, - tv_cmd, se_cmd->residual_count, se_cmd->scsi_status); - - memset(&v_rsp, 0, sizeof(v_rsp)); - v_rsp.resid = se_cmd->residual_count; - /* TODO is status_qualifier field needed? */ - v_rsp.status = se_cmd->scsi_status; - v_rsp.sense_len = se_cmd->scsi_sense_length; - memcpy(v_rsp.sense, tv_cmd->tvc_sense_buf, - v_rsp.sense_len); - ret = copy_to_user(tv_cmd->tvc_resp, &v_rsp, sizeof(v_rsp)); - if (likely(ret == 0)) - vhost_add_used(&vs->vqs[2], tv_cmd->tvc_vq_desc, 0); - else - pr_err("Faulted on virtio_scsi_cmd_resp\n"); - - vhost_scsi_free_cmd(tv_cmd); - } - - vhost_signal(&vs->dev, &vs->vqs[2]); -} - -static struct tcm_vhost_cmd *vhost_scsi_allocate_cmd( - struct tcm_vhost_tpg *tv_tpg, - struct virtio_scsi_cmd_req *v_req, - u32 exp_data_len, - int data_direction) -{ - struct tcm_vhost_cmd *tv_cmd; - struct tcm_vhost_nexus *tv_nexus; - struct se_portal_group *se_tpg = &tv_tpg->se_tpg; - struct se_session *se_sess; - struct se_cmd *se_cmd; - int sam_task_attr; - - tv_nexus = tv_tpg->tpg_nexus; - if (!tv_nexus) { - pr_err("Unable to locate active struct tcm_vhost_nexus\n"); - return ERR_PTR(-EIO); - } - se_sess = tv_nexus->tvn_se_sess; - - tv_cmd = kzalloc(sizeof(struct tcm_vhost_cmd), GFP_ATOMIC); - if (!tv_cmd) { - pr_err("Unable to allocate struct tcm_vhost_cmd\n"); - return ERR_PTR(-ENOMEM); - } - INIT_LIST_HEAD(&tv_cmd->tvc_completion_list); - tv_cmd->tvc_tag = v_req->tag; - - se_cmd = &tv_cmd->tvc_se_cmd; - /* - * Locate the SAM Task Attr from virtio_scsi_cmd_req - */ - sam_task_attr = v_req->task_attr; - /* - * Initialize struct se_cmd descriptor from TCM infrastructure - */ - transport_init_se_cmd(se_cmd, se_tpg->se_tpg_tfo, se_sess, exp_data_len, - data_direction, sam_task_attr, - &tv_cmd->tvc_sense_buf[0]); - -#if 0 /* FIXME: vhost_scsi_allocate_cmd() BIDI operation */ - if (bidi) - se_cmd->se_cmd_flags |= SCF_BIDI; -#endif - return tv_cmd; -} - -/* - * Map a user memory range into a scatterlist - * - * Returns the number of scatterlist entries used or -errno on error. - */ -static int vhost_scsi_map_to_sgl(struct scatterlist *sgl, - unsigned int sgl_count, void __user *ptr, size_t len, int write) -{ - struct scatterlist *sg = sgl; - unsigned int npages = 0; - int ret; - - while (len > 0) { - struct page *page; - unsigned int offset = (uintptr_t)ptr & ~PAGE_MASK; - unsigned int nbytes = min_t(unsigned int, - PAGE_SIZE - offset, len); - - if (npages == sgl_count) { - ret = -ENOBUFS; - goto err; - } - - ret = get_user_pages_fast((unsigned long)ptr, 1, write, &page); - BUG_ON(ret == 0); /* we should either get our page or fail */ - if (ret < 0) - goto err; - - sg_set_page(sg, page, nbytes, offset); - ptr += nbytes; - len -= nbytes; - sg++; - npages++; - } - return npages; - -err: - /* Put pages that we hold */ - for (sg = sgl; sg != &sgl[npages]; sg++) - put_page(sg_page(sg)); - return ret; -} - -static int vhost_scsi_map_iov_to_sgl(struct tcm_vhost_cmd *tv_cmd, - struct iovec *iov, unsigned int niov, int write) -{ - int ret; - unsigned int i; - u32 sgl_count; - struct scatterlist *sg; - - /* - * Find out how long sglist needs to be - */ - sgl_count = 0; - for (i = 0; i < niov; i++) { - sgl_count += (((uintptr_t)iov[i].iov_base + iov[i].iov_len + - PAGE_SIZE - 1) >> PAGE_SHIFT) - - ((uintptr_t)iov[i].iov_base >> PAGE_SHIFT); - } - /* TODO overflow checking */ - - sg = kmalloc(sizeof(tv_cmd->tvc_sgl[0]) * sgl_count, GFP_ATOMIC); - if (!sg) - return -ENOMEM; - pr_debug("%s sg %p sgl_count %u is_err %d\n", __func__, - sg, sgl_count, !sg); - sg_init_table(sg, sgl_count); - - tv_cmd->tvc_sgl = sg; - tv_cmd->tvc_sgl_count = sgl_count; - - pr_debug("Mapping %u iovecs for %u pages\n", niov, sgl_count); - for (i = 0; i < niov; i++) { - ret = vhost_scsi_map_to_sgl(sg, sgl_count, iov[i].iov_base, - iov[i].iov_len, write); - if (ret < 0) { - for (i = 0; i < tv_cmd->tvc_sgl_count; i++) - put_page(sg_page(&tv_cmd->tvc_sgl[i])); - kfree(tv_cmd->tvc_sgl); - tv_cmd->tvc_sgl = NULL; - tv_cmd->tvc_sgl_count = 0; - return ret; - } - - sg += ret; - sgl_count -= ret; - } - return 0; -} - -static void tcm_vhost_submission_work(struct work_struct *work) -{ - struct tcm_vhost_cmd *tv_cmd = - container_of(work, struct tcm_vhost_cmd, work); - struct se_cmd *se_cmd = &tv_cmd->tvc_se_cmd; - struct scatterlist *sg_ptr, *sg_bidi_ptr = NULL; - int rc, sg_no_bidi = 0; - /* - * Locate the struct se_lun pointer based on v_req->lun, and - * attach it to struct se_cmd - */ - rc = transport_lookup_cmd_lun(&tv_cmd->tvc_se_cmd, tv_cmd->tvc_lun); - if (rc < 0) { - pr_err("Failed to look up lun: %d\n", tv_cmd->tvc_lun); - transport_send_check_condition_and_sense(&tv_cmd->tvc_se_cmd, - tv_cmd->tvc_se_cmd.scsi_sense_reason, 0); - transport_generic_free_cmd(se_cmd, 0); - return; - } - - rc = target_setup_cmd_from_cdb(se_cmd, tv_cmd->tvc_cdb); - if (rc == -ENOMEM) { - transport_send_check_condition_and_sense(se_cmd, - TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE, 0); - transport_generic_free_cmd(se_cmd, 0); - return; - } else if (rc < 0) { - if (se_cmd->se_cmd_flags & SCF_SCSI_RESERVATION_CONFLICT) - tcm_vhost_queue_status(se_cmd); - else - transport_send_check_condition_and_sense(se_cmd, - se_cmd->scsi_sense_reason, 0); - transport_generic_free_cmd(se_cmd, 0); - return; - } - - if (tv_cmd->tvc_sgl_count) { - sg_ptr = tv_cmd->tvc_sgl; - /* - * For BIDI commands, pass in the extra READ buffer - * to transport_generic_map_mem_to_cmd() below.. - */ -/* FIXME: Fix BIDI operation in tcm_vhost_submission_work() */ -#if 0 - if (se_cmd->se_cmd_flags & SCF_BIDI) { - sg_bidi_ptr = NULL; - sg_no_bidi = 0; - } -#endif - } else { - sg_ptr = NULL; - } - - rc = transport_generic_map_mem_to_cmd(se_cmd, sg_ptr, - tv_cmd->tvc_sgl_count, sg_bidi_ptr, - sg_no_bidi); - if (rc < 0) { - transport_send_check_condition_and_sense(se_cmd, - se_cmd->scsi_sense_reason, 0); - transport_generic_free_cmd(se_cmd, 0); - return; - } - transport_handle_cdb_direct(se_cmd); -} - -static void vhost_scsi_handle_vq(struct vhost_scsi *vs) -{ - struct vhost_virtqueue *vq = &vs->vqs[2]; - struct virtio_scsi_cmd_req v_req; - struct tcm_vhost_tpg *tv_tpg; - struct tcm_vhost_cmd *tv_cmd; - u32 exp_data_len, data_first, data_num, data_direction; - unsigned out, in, i; - int head, ret; - - /* Must use ioctl VHOST_SCSI_SET_ENDPOINT */ - tv_tpg = vs->vs_tpg; - if (unlikely(!tv_tpg)) { - pr_err("%s endpoint not set\n", __func__); - return; - } - - mutex_lock(&vq->mutex); - vhost_disable_notify(&vs->dev, vq); - - for (;;) { - head = vhost_get_vq_desc(&vs->dev, vq, vq->iov, - ARRAY_SIZE(vq->iov), &out, &in, - NULL, NULL); - pr_debug("vhost_get_vq_desc: head: %d, out: %u in: %u\n", - head, out, in); - /* On error, stop handling until the next kick. */ - if (unlikely(head < 0)) - break; - /* Nothing new? Wait for eventfd to tell us they refilled. */ - if (head == vq->num) { - if (unlikely(vhost_enable_notify(&vs->dev, vq))) { - vhost_disable_notify(&vs->dev, vq); - continue; - } - break; - } - -/* FIXME: BIDI operation */ - if (out == 1 && in == 1) { - data_direction = DMA_NONE; - data_first = 0; - data_num = 0; - } else if (out == 1 && in > 1) { - data_direction = DMA_FROM_DEVICE; - data_first = out + 1; - data_num = in - 1; - } else if (out > 1 && in == 1) { - data_direction = DMA_TO_DEVICE; - data_first = 1; - data_num = out - 1; - } else { - vq_err(vq, "Invalid buffer layout out: %u in: %u\n", - out, in); - break; - } - - /* - * Check for a sane resp buffer so we can report errors to - * the guest. - */ - if (unlikely(vq->iov[out].iov_len != - sizeof(struct virtio_scsi_cmd_resp))) { - vq_err(vq, "Expecting virtio_scsi_cmd_resp, got %zu" - " bytes\n", vq->iov[out].iov_len); - break; - } - - if (unlikely(vq->iov[0].iov_len != sizeof(v_req))) { - vq_err(vq, "Expecting virtio_scsi_cmd_req, got %zu" - " bytes\n", vq->iov[0].iov_len); - break; - } - pr_debug("Calling __copy_from_user: vq->iov[0].iov_base: %p," - " len: %zu\n", vq->iov[0].iov_base, sizeof(v_req)); - ret = __copy_from_user(&v_req, vq->iov[0].iov_base, - sizeof(v_req)); - if (unlikely(ret)) { - vq_err(vq, "Faulted on virtio_scsi_cmd_req\n"); - break; - } - - exp_data_len = 0; - for (i = 0; i < data_num; i++) - exp_data_len += vq->iov[data_first + i].iov_len; - - tv_cmd = vhost_scsi_allocate_cmd(tv_tpg, &v_req, - exp_data_len, data_direction); - if (IS_ERR(tv_cmd)) { - vq_err(vq, "vhost_scsi_allocate_cmd failed %ld\n", - PTR_ERR(tv_cmd)); - break; - } - pr_debug("Allocated tv_cmd: %p exp_data_len: %d, data_direction" - ": %d\n", tv_cmd, exp_data_len, data_direction); - - tv_cmd->tvc_vhost = vs; - - if (unlikely(vq->iov[out].iov_len != - sizeof(struct virtio_scsi_cmd_resp))) { - vq_err(vq, "Expecting virtio_scsi_cmd_resp, got %zu" - " bytes, out: %d, in: %d\n", - vq->iov[out].iov_len, out, in); - break; - } - - tv_cmd->tvc_resp = vq->iov[out].iov_base; - - /* - * Copy in the recieved CDB descriptor into tv_cmd->tvc_cdb - * that will be used by tcm_vhost_new_cmd_map() and down into - * target_setup_cmd_from_cdb() - */ - memcpy(tv_cmd->tvc_cdb, v_req.cdb, TCM_VHOST_MAX_CDB_SIZE); - /* - * Check that the recieved CDB size does not exceeded our - * hardcoded max for tcm_vhost - */ - /* TODO what if cdb was too small for varlen cdb header? */ - if (unlikely(scsi_command_size(tv_cmd->tvc_cdb) > - TCM_VHOST_MAX_CDB_SIZE)) { - vq_err(vq, "Received SCSI CDB with command_size: %d that" - " exceeds SCSI_MAX_VARLEN_CDB_SIZE: %d\n", - scsi_command_size(tv_cmd->tvc_cdb), - TCM_VHOST_MAX_CDB_SIZE); - break; /* TODO */ - } - tv_cmd->tvc_lun = ((v_req.lun[2] << 8) | v_req.lun[3]) & 0x3FFF; - - pr_debug("vhost_scsi got command opcode: %#02x, lun: %d\n", - tv_cmd->tvc_cdb[0], tv_cmd->tvc_lun); - - if (data_direction != DMA_NONE) { - ret = vhost_scsi_map_iov_to_sgl(tv_cmd, - &vq->iov[data_first], data_num, - data_direction == DMA_TO_DEVICE); - if (unlikely(ret)) { - vq_err(vq, "Failed to map iov to sgl\n"); - break; /* TODO */ - } - } - - /* - * Save the descriptor from vhost_get_vq_desc() to be used to - * complete the virtio-scsi request in TCM callback context via - * tcm_vhost_queue_data_in() and tcm_vhost_queue_status() - */ - tv_cmd->tvc_vq_desc = head; - /* - * Dispatch tv_cmd descriptor for cmwq execution in process - * context provided by tcm_vhost_workqueue. This also ensures - * tv_cmd is executed on the same kworker CPU as this vhost - * thread to gain positive L2 cache locality effects.. - */ - INIT_WORK(&tv_cmd->work, tcm_vhost_submission_work); - queue_work(tcm_vhost_workqueue, &tv_cmd->work); - } - - mutex_unlock(&vq->mutex); -} - -static void vhost_scsi_ctl_handle_kick(struct vhost_work *work) -{ - pr_debug("%s: The handling func for control queue.\n", __func__); -} - -static void vhost_scsi_evt_handle_kick(struct vhost_work *work) -{ - pr_debug("%s: The handling func for event queue.\n", __func__); -} - -static void vhost_scsi_handle_kick(struct vhost_work *work) -{ - struct vhost_virtqueue *vq = container_of(work, struct vhost_virtqueue, - poll.work); - struct vhost_scsi *vs = container_of(vq->dev, struct vhost_scsi, dev); - - vhost_scsi_handle_vq(vs); -} - -/* - * Called from vhost_scsi_ioctl() context to walk the list of available - * tcm_vhost_tpg with an active struct tcm_vhost_nexus - */ -static int vhost_scsi_set_endpoint( - struct vhost_scsi *vs, - struct vhost_scsi_target *t) -{ - struct tcm_vhost_tport *tv_tport; - struct tcm_vhost_tpg *tv_tpg; - int index; - - mutex_lock(&vs->dev.mutex); - /* Verify that ring has been setup correctly. */ - for (index = 0; index < vs->dev.nvqs; ++index) { - /* Verify that ring has been setup correctly. */ - if (!vhost_vq_access_ok(&vs->vqs[index])) { - mutex_unlock(&vs->dev.mutex); - return -EFAULT; - } - } - mutex_unlock(&vs->dev.mutex); - - mutex_lock(&tcm_vhost_mutex); - list_for_each_entry(tv_tpg, &tcm_vhost_list, tv_tpg_list) { - mutex_lock(&tv_tpg->tv_tpg_mutex); - if (!tv_tpg->tpg_nexus) { - mutex_unlock(&tv_tpg->tv_tpg_mutex); - continue; - } - if (tv_tpg->tv_tpg_vhost_count != 0) { - mutex_unlock(&tv_tpg->tv_tpg_mutex); - continue; - } - tv_tport = tv_tpg->tport; - - if (!strcmp(tv_tport->tport_name, t->vhost_wwpn) && - (tv_tpg->tport_tpgt == t->vhost_tpgt)) { - tv_tpg->tv_tpg_vhost_count++; - mutex_unlock(&tv_tpg->tv_tpg_mutex); - mutex_unlock(&tcm_vhost_mutex); - - mutex_lock(&vs->dev.mutex); - if (vs->vs_tpg) { - mutex_unlock(&vs->dev.mutex); - mutex_lock(&tv_tpg->tv_tpg_mutex); - tv_tpg->tv_tpg_vhost_count--; - mutex_unlock(&tv_tpg->tv_tpg_mutex); - return -EEXIST; - } - - vs->vs_tpg = tv_tpg; - smp_mb__after_atomic_inc(); - mutex_unlock(&vs->dev.mutex); - return 0; - } - mutex_unlock(&tv_tpg->tv_tpg_mutex); - } - mutex_unlock(&tcm_vhost_mutex); - return -EINVAL; -} - -static int vhost_scsi_clear_endpoint( - struct vhost_scsi *vs, - struct vhost_scsi_target *t) -{ - struct tcm_vhost_tport *tv_tport; - struct tcm_vhost_tpg *tv_tpg; - int index, ret; - - mutex_lock(&vs->dev.mutex); - /* Verify that ring has been setup correctly. */ - for (index = 0; index < vs->dev.nvqs; ++index) { - if (!vhost_vq_access_ok(&vs->vqs[index])) { - ret = -EFAULT; - goto err; - } - } - - if (!vs->vs_tpg) { - ret = -ENODEV; - goto err; - } - tv_tpg = vs->vs_tpg; - tv_tport = tv_tpg->tport; - - if (strcmp(tv_tport->tport_name, t->vhost_wwpn) || - (tv_tpg->tport_tpgt != t->vhost_tpgt)) { - pr_warn("tv_tport->tport_name: %s, tv_tpg->tport_tpgt: %hu" - " does not match t->vhost_wwpn: %s, t->vhost_tpgt: %hu\n", - tv_tport->tport_name, tv_tpg->tport_tpgt, - t->vhost_wwpn, t->vhost_tpgt); - ret = -EINVAL; - goto err; - } - tv_tpg->tv_tpg_vhost_count--; - vs->vs_tpg = NULL; - mutex_unlock(&vs->dev.mutex); - - return 0; - -err: - mutex_unlock(&vs->dev.mutex); - return ret; -} - -static int vhost_scsi_open(struct inode *inode, struct file *f) -{ - struct vhost_scsi *s; - int r; - - s = kzalloc(sizeof(*s), GFP_KERNEL); - if (!s) - return -ENOMEM; - - vhost_work_init(&s->vs_completion_work, vhost_scsi_complete_cmd_work); - INIT_LIST_HEAD(&s->vs_completion_list); - spin_lock_init(&s->vs_completion_lock); - - s->vqs[VHOST_SCSI_VQ_CTL].handle_kick = vhost_scsi_ctl_handle_kick; - s->vqs[VHOST_SCSI_VQ_EVT].handle_kick = vhost_scsi_evt_handle_kick; - s->vqs[VHOST_SCSI_VQ_IO].handle_kick = vhost_scsi_handle_kick; - r = vhost_dev_init(&s->dev, s->vqs, 3); - if (r < 0) { - kfree(s); - return r; - } - - f->private_data = s; - return 0; -} - -static int vhost_scsi_release(struct inode *inode, struct file *f) -{ - struct vhost_scsi *s = f->private_data; - - if (s->vs_tpg && s->vs_tpg->tport) { - struct vhost_scsi_target backend; - - memcpy(backend.vhost_wwpn, s->vs_tpg->tport->tport_name, - sizeof(backend.vhost_wwpn)); - backend.vhost_tpgt = s->vs_tpg->tport_tpgt; - vhost_scsi_clear_endpoint(s, &backend); - } - - vhost_dev_cleanup(&s->dev, false); - kfree(s); - return 0; -} - -static void vhost_scsi_flush_vq(struct vhost_scsi *vs, int index) -{ - vhost_poll_flush(&vs->dev.vqs[index].poll); -} - -static void vhost_scsi_flush(struct vhost_scsi *vs) -{ - vhost_scsi_flush_vq(vs, VHOST_SCSI_VQ_CTL); - vhost_scsi_flush_vq(vs, VHOST_SCSI_VQ_EVT); - vhost_scsi_flush_vq(vs, VHOST_SCSI_VQ_IO); -} - -static int vhost_scsi_set_features(struct vhost_scsi *vs, u64 features) -{ - if (features & ~VHOST_FEATURES) - return -EOPNOTSUPP; - - mutex_lock(&vs->dev.mutex); - if ((features & (1 << VHOST_F_LOG_ALL)) && - !vhost_log_access_ok(&vs->dev)) { - mutex_unlock(&vs->dev.mutex); - return -EFAULT; - } - vs->dev.acked_features = features; - smp_wmb(); - vhost_scsi_flush(vs); - mutex_unlock(&vs->dev.mutex); - return 0; -} - -static long vhost_scsi_ioctl(struct file *f, unsigned int ioctl, - unsigned long arg) -{ - struct vhost_scsi *vs = f->private_data; - struct vhost_scsi_target backend; - void __user *argp = (void __user *)arg; - u64 __user *featurep = argp; - u64 features; - int r, abi_version = VHOST_SCSI_ABI_VERSION; - - switch (ioctl) { - case VHOST_SCSI_SET_ENDPOINT: - if (copy_from_user(&backend, argp, sizeof backend)) - return -EFAULT; - if (backend.reserved != 0) - return -EOPNOTSUPP; - - return vhost_scsi_set_endpoint(vs, &backend); - case VHOST_SCSI_CLEAR_ENDPOINT: - if (copy_from_user(&backend, argp, sizeof backend)) - return -EFAULT; - if (backend.reserved != 0) - return -EOPNOTSUPP; - - return vhost_scsi_clear_endpoint(vs, &backend); - case VHOST_SCSI_GET_ABI_VERSION: - if (copy_to_user(argp, &abi_version, sizeof abi_version)) - return -EFAULT; - return 0; - case VHOST_GET_FEATURES: - features = VHOST_FEATURES; - if (copy_to_user(featurep, &features, sizeof features)) - return -EFAULT; - return 0; - case VHOST_SET_FEATURES: - if (copy_from_user(&features, featurep, sizeof features)) - return -EFAULT; - return vhost_scsi_set_features(vs, features); - default: - mutex_lock(&vs->dev.mutex); - r = vhost_dev_ioctl(&vs->dev, ioctl, arg); - mutex_unlock(&vs->dev.mutex); - return r; - } -} - -#ifdef CONFIG_COMPAT -static long vhost_scsi_compat_ioctl(struct file *f, unsigned int ioctl, - unsigned long arg) -{ - return vhost_scsi_ioctl(f, ioctl, (unsigned long)compat_ptr(arg)); -} -#endif - -static const struct file_operations vhost_scsi_fops = { - .owner = THIS_MODULE, - .release = vhost_scsi_release, - .unlocked_ioctl = vhost_scsi_ioctl, -#ifdef CONFIG_COMPAT - .compat_ioctl = vhost_scsi_compat_ioctl, -#endif - .open = vhost_scsi_open, - .llseek = noop_llseek, -}; - -static struct miscdevice vhost_scsi_misc = { - MISC_DYNAMIC_MINOR, - "vhost-scsi", - &vhost_scsi_fops, -}; - -static int __init vhost_scsi_register(void) -{ - return misc_register(&vhost_scsi_misc); -} - -static int vhost_scsi_deregister(void) -{ - return misc_deregister(&vhost_scsi_misc); -} - -static char *tcm_vhost_dump_proto_id(struct tcm_vhost_tport *tport) -{ - switch (tport->tport_proto_id) { - case SCSI_PROTOCOL_SAS: - return "SAS"; - case SCSI_PROTOCOL_FCP: - return "FCP"; - case SCSI_PROTOCOL_ISCSI: - return "iSCSI"; - default: - break; - } - - return "Unknown"; -} - -static int tcm_vhost_port_link(struct se_portal_group *se_tpg, - struct se_lun *lun) -{ - struct tcm_vhost_tpg *tv_tpg = container_of(se_tpg, - struct tcm_vhost_tpg, se_tpg); - - mutex_lock(&tv_tpg->tv_tpg_mutex); - tv_tpg->tv_tpg_port_count++; - mutex_unlock(&tv_tpg->tv_tpg_mutex); - - return 0; -} - -static void tcm_vhost_port_unlink(struct se_portal_group *se_tpg, - struct se_lun *se_lun) -{ - struct tcm_vhost_tpg *tv_tpg = container_of(se_tpg, - struct tcm_vhost_tpg, se_tpg); - - mutex_lock(&tv_tpg->tv_tpg_mutex); - tv_tpg->tv_tpg_port_count--; - mutex_unlock(&tv_tpg->tv_tpg_mutex); -} - -static struct se_node_acl *tcm_vhost_make_nodeacl( - struct se_portal_group *se_tpg, - struct config_group *group, - const char *name) -{ - struct se_node_acl *se_nacl, *se_nacl_new; - struct tcm_vhost_nacl *nacl; - u64 wwpn = 0; - u32 nexus_depth; - - /* tcm_vhost_parse_wwn(name, &wwpn, 1) < 0) - return ERR_PTR(-EINVAL); */ - se_nacl_new = tcm_vhost_alloc_fabric_acl(se_tpg); - if (!se_nacl_new) - return ERR_PTR(-ENOMEM); - - nexus_depth = 1; - /* - * se_nacl_new may be released by core_tpg_add_initiator_node_acl() - * when converting a NodeACL from demo mode -> explict - */ - se_nacl = core_tpg_add_initiator_node_acl(se_tpg, se_nacl_new, - name, nexus_depth); - if (IS_ERR(se_nacl)) { - tcm_vhost_release_fabric_acl(se_tpg, se_nacl_new); - return se_nacl; - } - /* - * Locate our struct tcm_vhost_nacl and set the FC Nport WWPN - */ - nacl = container_of(se_nacl, struct tcm_vhost_nacl, se_node_acl); - nacl->iport_wwpn = wwpn; - - return se_nacl; -} - -static void tcm_vhost_drop_nodeacl(struct se_node_acl *se_acl) -{ - struct tcm_vhost_nacl *nacl = container_of(se_acl, - struct tcm_vhost_nacl, se_node_acl); - core_tpg_del_initiator_node_acl(se_acl->se_tpg, se_acl, 1); - kfree(nacl); -} - -static int tcm_vhost_make_nexus(struct tcm_vhost_tpg *tv_tpg, - const char *name) -{ - struct se_portal_group *se_tpg; - struct tcm_vhost_nexus *tv_nexus; - - mutex_lock(&tv_tpg->tv_tpg_mutex); - if (tv_tpg->tpg_nexus) { - mutex_unlock(&tv_tpg->tv_tpg_mutex); - pr_debug("tv_tpg->tpg_nexus already exists\n"); - return -EEXIST; - } - se_tpg = &tv_tpg->se_tpg; - - tv_nexus = kzalloc(sizeof(struct tcm_vhost_nexus), GFP_KERNEL); - if (!tv_nexus) { - mutex_unlock(&tv_tpg->tv_tpg_mutex); - pr_err("Unable to allocate struct tcm_vhost_nexus\n"); - return -ENOMEM; - } - /* - * Initialize the struct se_session pointer - */ - tv_nexus->tvn_se_sess = transport_init_session(); - if (IS_ERR(tv_nexus->tvn_se_sess)) { - mutex_unlock(&tv_tpg->tv_tpg_mutex); - kfree(tv_nexus); - return -ENOMEM; - } - /* - * Since we are running in 'demo mode' this call with generate a - * struct se_node_acl for the tcm_vhost struct se_portal_group with - * the SCSI Initiator port name of the passed configfs group 'name'. - */ - tv_nexus->tvn_se_sess->se_node_acl = core_tpg_check_initiator_node_acl( - se_tpg, (unsigned char *)name); - if (!tv_nexus->tvn_se_sess->se_node_acl) { - mutex_unlock(&tv_tpg->tv_tpg_mutex); - pr_debug("core_tpg_check_initiator_node_acl() failed" - " for %s\n", name); - transport_free_session(tv_nexus->tvn_se_sess); - kfree(tv_nexus); - return -ENOMEM; - } - /* - * Now register the TCM vhost virtual I_T Nexus as active with the - * call to __transport_register_session() - */ - __transport_register_session(se_tpg, tv_nexus->tvn_se_sess->se_node_acl, - tv_nexus->tvn_se_sess, tv_nexus); - tv_tpg->tpg_nexus = tv_nexus; - - mutex_unlock(&tv_tpg->tv_tpg_mutex); - return 0; -} - -static int tcm_vhost_drop_nexus(struct tcm_vhost_tpg *tpg) -{ - struct se_session *se_sess; - struct tcm_vhost_nexus *tv_nexus; - - mutex_lock(&tpg->tv_tpg_mutex); - tv_nexus = tpg->tpg_nexus; - if (!tv_nexus) { - mutex_unlock(&tpg->tv_tpg_mutex); - return -ENODEV; - } - - se_sess = tv_nexus->tvn_se_sess; - if (!se_sess) { - mutex_unlock(&tpg->tv_tpg_mutex); - return -ENODEV; - } - - if (tpg->tv_tpg_port_count != 0) { - mutex_unlock(&tpg->tv_tpg_mutex); - pr_err("Unable to remove TCM_vhost I_T Nexus with" - " active TPG port count: %d\n", - tpg->tv_tpg_port_count); - return -EBUSY; - } - - if (tpg->tv_tpg_vhost_count != 0) { - mutex_unlock(&tpg->tv_tpg_mutex); - pr_err("Unable to remove TCM_vhost I_T Nexus with" - " active TPG vhost count: %d\n", - tpg->tv_tpg_vhost_count); - return -EBUSY; - } - - pr_debug("TCM_vhost_ConfigFS: Removing I_T Nexus to emulated" - " %s Initiator Port: %s\n", tcm_vhost_dump_proto_id(tpg->tport), - tv_nexus->tvn_se_sess->se_node_acl->initiatorname); - /* - * Release the SCSI I_T Nexus to the emulated vhost Target Port - */ - transport_deregister_session(tv_nexus->tvn_se_sess); - tpg->tpg_nexus = NULL; - mutex_unlock(&tpg->tv_tpg_mutex); - - kfree(tv_nexus); - return 0; -} - -static ssize_t tcm_vhost_tpg_show_nexus(struct se_portal_group *se_tpg, - char *page) -{ - struct tcm_vhost_tpg *tv_tpg = container_of(se_tpg, - struct tcm_vhost_tpg, se_tpg); - struct tcm_vhost_nexus *tv_nexus; - ssize_t ret; - - mutex_lock(&tv_tpg->tv_tpg_mutex); - tv_nexus = tv_tpg->tpg_nexus; - if (!tv_nexus) { - mutex_unlock(&tv_tpg->tv_tpg_mutex); - return -ENODEV; - } - ret = snprintf(page, PAGE_SIZE, "%s\n", - tv_nexus->tvn_se_sess->se_node_acl->initiatorname); - mutex_unlock(&tv_tpg->tv_tpg_mutex); - - return ret; -} - -static ssize_t tcm_vhost_tpg_store_nexus(struct se_portal_group *se_tpg, - const char *page, - size_t count) -{ - struct tcm_vhost_tpg *tv_tpg = container_of(se_tpg, - struct tcm_vhost_tpg, se_tpg); - struct tcm_vhost_tport *tport_wwn = tv_tpg->tport; - unsigned char i_port[TCM_VHOST_NAMELEN], *ptr, *port_ptr; - int ret; - /* - * Shutdown the active I_T nexus if 'NULL' is passed.. - */ - if (!strncmp(page, "NULL", 4)) { - ret = tcm_vhost_drop_nexus(tv_tpg); - return (!ret) ? count : ret; - } - /* - * Otherwise make sure the passed virtual Initiator port WWN matches - * the fabric protocol_id set in tcm_vhost_make_tport(), and call - * tcm_vhost_make_nexus(). - */ - if (strlen(page) >= TCM_VHOST_NAMELEN) { - pr_err("Emulated NAA Sas Address: %s, exceeds" - " max: %d\n", page, TCM_VHOST_NAMELEN); - return -EINVAL; - } - snprintf(&i_port[0], TCM_VHOST_NAMELEN, "%s", page); - - ptr = strstr(i_port, "naa."); - if (ptr) { - if (tport_wwn->tport_proto_id != SCSI_PROTOCOL_SAS) { - pr_err("Passed SAS Initiator Port %s does not" - " match target port protoid: %s\n", i_port, - tcm_vhost_dump_proto_id(tport_wwn)); - return -EINVAL; - } - port_ptr = &i_port[0]; - goto check_newline; - } - ptr = strstr(i_port, "fc."); - if (ptr) { - if (tport_wwn->tport_proto_id != SCSI_PROTOCOL_FCP) { - pr_err("Passed FCP Initiator Port %s does not" - " match target port protoid: %s\n", i_port, - tcm_vhost_dump_proto_id(tport_wwn)); - return -EINVAL; - } - port_ptr = &i_port[3]; /* Skip over "fc." */ - goto check_newline; - } - ptr = strstr(i_port, "iqn."); - if (ptr) { - if (tport_wwn->tport_proto_id != SCSI_PROTOCOL_ISCSI) { - pr_err("Passed iSCSI Initiator Port %s does not" - " match target port protoid: %s\n", i_port, - tcm_vhost_dump_proto_id(tport_wwn)); - return -EINVAL; - } - port_ptr = &i_port[0]; - goto check_newline; - } - pr_err("Unable to locate prefix for emulated Initiator Port:" - " %s\n", i_port); - return -EINVAL; - /* - * Clear any trailing newline for the NAA WWN - */ -check_newline: - if (i_port[strlen(i_port)-1] == '\n') - i_port[strlen(i_port)-1] = '\0'; - - ret = tcm_vhost_make_nexus(tv_tpg, port_ptr); - if (ret < 0) - return ret; - - return count; -} - -TF_TPG_BASE_ATTR(tcm_vhost, nexus, S_IRUGO | S_IWUSR); - -static struct configfs_attribute *tcm_vhost_tpg_attrs[] = { - &tcm_vhost_tpg_nexus.attr, - NULL, -}; - -static struct se_portal_group *tcm_vhost_make_tpg(struct se_wwn *wwn, - struct config_group *group, - const char *name) -{ - struct tcm_vhost_tport *tport = container_of(wwn, - struct tcm_vhost_tport, tport_wwn); - - struct tcm_vhost_tpg *tpg; - unsigned long tpgt; - int ret; - - if (strstr(name, "tpgt_") != name) - return ERR_PTR(-EINVAL); - if (kstrtoul(name + 5, 10, &tpgt) || tpgt > UINT_MAX) - return ERR_PTR(-EINVAL); - - tpg = kzalloc(sizeof(struct tcm_vhost_tpg), GFP_KERNEL); - if (!tpg) { - pr_err("Unable to allocate struct tcm_vhost_tpg"); - return ERR_PTR(-ENOMEM); - } - mutex_init(&tpg->tv_tpg_mutex); - INIT_LIST_HEAD(&tpg->tv_tpg_list); - tpg->tport = tport; - tpg->tport_tpgt = tpgt; - - ret = core_tpg_register(&tcm_vhost_fabric_configfs->tf_ops, wwn, - &tpg->se_tpg, tpg, TRANSPORT_TPG_TYPE_NORMAL); - if (ret < 0) { - kfree(tpg); - return NULL; - } - mutex_lock(&tcm_vhost_mutex); - list_add_tail(&tpg->tv_tpg_list, &tcm_vhost_list); - mutex_unlock(&tcm_vhost_mutex); - - return &tpg->se_tpg; -} - -static void tcm_vhost_drop_tpg(struct se_portal_group *se_tpg) -{ - struct tcm_vhost_tpg *tpg = container_of(se_tpg, - struct tcm_vhost_tpg, se_tpg); - - mutex_lock(&tcm_vhost_mutex); - list_del(&tpg->tv_tpg_list); - mutex_unlock(&tcm_vhost_mutex); - /* - * Release the virtual I_T Nexus for this vhost TPG - */ - tcm_vhost_drop_nexus(tpg); - /* - * Deregister the se_tpg from TCM.. - */ - core_tpg_deregister(se_tpg); - kfree(tpg); -} - -static struct se_wwn *tcm_vhost_make_tport(struct target_fabric_configfs *tf, - struct config_group *group, - const char *name) -{ - struct tcm_vhost_tport *tport; - char *ptr; - u64 wwpn = 0; - int off = 0; - - /* if (tcm_vhost_parse_wwn(name, &wwpn, 1) < 0) - return ERR_PTR(-EINVAL); */ - - tport = kzalloc(sizeof(struct tcm_vhost_tport), GFP_KERNEL); - if (!tport) { - pr_err("Unable to allocate struct tcm_vhost_tport"); - return ERR_PTR(-ENOMEM); - } - tport->tport_wwpn = wwpn; - /* - * Determine the emulated Protocol Identifier and Target Port Name - * based on the incoming configfs directory name. - */ - ptr = strstr(name, "naa."); - if (ptr) { - tport->tport_proto_id = SCSI_PROTOCOL_SAS; - goto check_len; - } - ptr = strstr(name, "fc."); - if (ptr) { - tport->tport_proto_id = SCSI_PROTOCOL_FCP; - off = 3; /* Skip over "fc." */ - goto check_len; - } - ptr = strstr(name, "iqn."); - if (ptr) { - tport->tport_proto_id = SCSI_PROTOCOL_ISCSI; - goto check_len; - } - - pr_err("Unable to locate prefix for emulated Target Port:" - " %s\n", name); - kfree(tport); - return ERR_PTR(-EINVAL); - -check_len: - if (strlen(name) >= TCM_VHOST_NAMELEN) { - pr_err("Emulated %s Address: %s, exceeds" - " max: %d\n", name, tcm_vhost_dump_proto_id(tport), - TCM_VHOST_NAMELEN); - kfree(tport); - return ERR_PTR(-EINVAL); - } - snprintf(&tport->tport_name[0], TCM_VHOST_NAMELEN, "%s", &name[off]); - - pr_debug("TCM_VHost_ConfigFS: Allocated emulated Target" - " %s Address: %s\n", tcm_vhost_dump_proto_id(tport), name); - - return &tport->tport_wwn; -} - -static void tcm_vhost_drop_tport(struct se_wwn *wwn) -{ - struct tcm_vhost_tport *tport = container_of(wwn, - struct tcm_vhost_tport, tport_wwn); - - pr_debug("TCM_VHost_ConfigFS: Deallocating emulated Target" - " %s Address: %s\n", tcm_vhost_dump_proto_id(tport), - tport->tport_name); - - kfree(tport); -} - -static ssize_t tcm_vhost_wwn_show_attr_version( - struct target_fabric_configfs *tf, - char *page) -{ - return sprintf(page, "TCM_VHOST fabric module %s on %s/%s" - "on "UTS_RELEASE"\n", TCM_VHOST_VERSION, utsname()->sysname, - utsname()->machine); -} - -TF_WWN_ATTR_RO(tcm_vhost, version); - -static struct configfs_attribute *tcm_vhost_wwn_attrs[] = { - &tcm_vhost_wwn_version.attr, - NULL, -}; - -static struct target_core_fabric_ops tcm_vhost_ops = { - .get_fabric_name = tcm_vhost_get_fabric_name, - .get_fabric_proto_ident = tcm_vhost_get_fabric_proto_ident, - .tpg_get_wwn = tcm_vhost_get_fabric_wwn, - .tpg_get_tag = tcm_vhost_get_tag, - .tpg_get_default_depth = tcm_vhost_get_default_depth, - .tpg_get_pr_transport_id = tcm_vhost_get_pr_transport_id, - .tpg_get_pr_transport_id_len = tcm_vhost_get_pr_transport_id_len, - .tpg_parse_pr_out_transport_id = tcm_vhost_parse_pr_out_transport_id, - .tpg_check_demo_mode = tcm_vhost_check_true, - .tpg_check_demo_mode_cache = tcm_vhost_check_true, - .tpg_check_demo_mode_write_protect = tcm_vhost_check_false, - .tpg_check_prod_mode_write_protect = tcm_vhost_check_false, - .tpg_alloc_fabric_acl = tcm_vhost_alloc_fabric_acl, - .tpg_release_fabric_acl = tcm_vhost_release_fabric_acl, - .tpg_get_inst_index = tcm_vhost_tpg_get_inst_index, - .release_cmd = tcm_vhost_release_cmd, - .shutdown_session = tcm_vhost_shutdown_session, - .close_session = tcm_vhost_close_session, - .sess_get_index = tcm_vhost_sess_get_index, - .sess_get_initiator_sid = NULL, - .write_pending = tcm_vhost_write_pending, - .write_pending_status = tcm_vhost_write_pending_status, - .set_default_node_attributes = tcm_vhost_set_default_node_attrs, - .get_task_tag = tcm_vhost_get_task_tag, - .get_cmd_state = tcm_vhost_get_cmd_state, - .queue_data_in = tcm_vhost_queue_data_in, - .queue_status = tcm_vhost_queue_status, - .queue_tm_rsp = tcm_vhost_queue_tm_rsp, - .get_fabric_sense_len = tcm_vhost_get_fabric_sense_len, - .set_fabric_sense_len = tcm_vhost_set_fabric_sense_len, - /* - * Setup callers for generic logic in target_core_fabric_configfs.c - */ - .fabric_make_wwn = tcm_vhost_make_tport, - .fabric_drop_wwn = tcm_vhost_drop_tport, - .fabric_make_tpg = tcm_vhost_make_tpg, - .fabric_drop_tpg = tcm_vhost_drop_tpg, - .fabric_post_link = tcm_vhost_port_link, - .fabric_pre_unlink = tcm_vhost_port_unlink, - .fabric_make_np = NULL, - .fabric_drop_np = NULL, - .fabric_make_nodeacl = tcm_vhost_make_nodeacl, - .fabric_drop_nodeacl = tcm_vhost_drop_nodeacl, -}; - -static int tcm_vhost_register_configfs(void) -{ - struct target_fabric_configfs *fabric; - int ret; - - pr_debug("TCM_VHOST fabric module %s on %s/%s" - " on "UTS_RELEASE"\n", TCM_VHOST_VERSION, utsname()->sysname, - utsname()->machine); - /* - * Register the top level struct config_item_type with TCM core - */ - fabric = target_fabric_configfs_init(THIS_MODULE, "vhost"); - if (IS_ERR(fabric)) { - pr_err("target_fabric_configfs_init() failed\n"); - return PTR_ERR(fabric); - } - /* - * Setup fabric->tf_ops from our local tcm_vhost_ops - */ - fabric->tf_ops = tcm_vhost_ops; - /* - * Setup default attribute lists for various fabric->tf_cit_tmpl - */ - TF_CIT_TMPL(fabric)->tfc_wwn_cit.ct_attrs = tcm_vhost_wwn_attrs; - TF_CIT_TMPL(fabric)->tfc_tpg_base_cit.ct_attrs = tcm_vhost_tpg_attrs; - TF_CIT_TMPL(fabric)->tfc_tpg_attrib_cit.ct_attrs = NULL; - TF_CIT_TMPL(fabric)->tfc_tpg_param_cit.ct_attrs = NULL; - TF_CIT_TMPL(fabric)->tfc_tpg_np_base_cit.ct_attrs = NULL; - TF_CIT_TMPL(fabric)->tfc_tpg_nacl_base_cit.ct_attrs = NULL; - TF_CIT_TMPL(fabric)->tfc_tpg_nacl_attrib_cit.ct_attrs = NULL; - TF_CIT_TMPL(fabric)->tfc_tpg_nacl_auth_cit.ct_attrs = NULL; - TF_CIT_TMPL(fabric)->tfc_tpg_nacl_param_cit.ct_attrs = NULL; - /* - * Register the fabric for use within TCM - */ - ret = target_fabric_configfs_register(fabric); - if (ret < 0) { - pr_err("target_fabric_configfs_register() failed" - " for TCM_VHOST\n"); - return ret; - } - /* - * Setup our local pointer to *fabric - */ - tcm_vhost_fabric_configfs = fabric; - pr_debug("TCM_VHOST[0] - Set fabric -> tcm_vhost_fabric_configfs\n"); - return 0; -}; - -static void tcm_vhost_deregister_configfs(void) -{ - if (!tcm_vhost_fabric_configfs) - return; - - target_fabric_configfs_deregister(tcm_vhost_fabric_configfs); - tcm_vhost_fabric_configfs = NULL; - pr_debug("TCM_VHOST[0] - Cleared tcm_vhost_fabric_configfs\n"); -}; - -static int __init tcm_vhost_init(void) -{ - int ret = -ENOMEM; - /* - * Use our own dedicated workqueue for submitting I/O into - * target core to avoid contention within system_wq. - */ - tcm_vhost_workqueue = alloc_workqueue("tcm_vhost", 0, 0); - if (!tcm_vhost_workqueue) - goto out; - - ret = vhost_scsi_register(); - if (ret < 0) - goto out_destroy_workqueue; - - ret = tcm_vhost_register_configfs(); - if (ret < 0) - goto out_vhost_scsi_deregister; - - return 0; - -out_vhost_scsi_deregister: - vhost_scsi_deregister(); -out_destroy_workqueue: - destroy_workqueue(tcm_vhost_workqueue); -out: - return ret; -}; - -static void tcm_vhost_exit(void) -{ - tcm_vhost_deregister_configfs(); - vhost_scsi_deregister(); - destroy_workqueue(tcm_vhost_workqueue); -}; - -MODULE_DESCRIPTION("TCM_VHOST series fabric driver"); -MODULE_LICENSE("GPL"); -module_init(tcm_vhost_init); -module_exit(tcm_vhost_exit); diff --git a/trunk/drivers/vhost/tcm_vhost.h b/trunk/drivers/vhost/tcm_vhost.h deleted file mode 100644 index d9e93557d669..000000000000 --- a/trunk/drivers/vhost/tcm_vhost.h +++ /dev/null @@ -1,103 +0,0 @@ -#define TCM_VHOST_VERSION "v0.1" -#define TCM_VHOST_NAMELEN 256 -#define TCM_VHOST_MAX_CDB_SIZE 32 - -struct tcm_vhost_cmd { - /* Descriptor from vhost_get_vq_desc() for virt_queue segment */ - int tvc_vq_desc; - /* The Tag from include/linux/virtio_scsi.h:struct virtio_scsi_cmd_req */ - u64 tvc_tag; - /* The number of scatterlists associated with this cmd */ - u32 tvc_sgl_count; - /* Saved unpacked SCSI LUN for tcm_vhost_submission_work() */ - u32 tvc_lun; - /* Pointer to the SGL formatted memory from virtio-scsi */ - struct scatterlist *tvc_sgl; - /* Pointer to response */ - struct virtio_scsi_cmd_resp __user *tvc_resp; - /* Pointer to vhost_scsi for our device */ - struct vhost_scsi *tvc_vhost; - /* The TCM I/O descriptor that is accessed via container_of() */ - struct se_cmd tvc_se_cmd; - /* work item used for cmwq dispatch to tcm_vhost_submission_work() */ - struct work_struct work; - /* Copy of the incoming SCSI command descriptor block (CDB) */ - unsigned char tvc_cdb[TCM_VHOST_MAX_CDB_SIZE]; - /* Sense buffer that will be mapped into outgoing status */ - unsigned char tvc_sense_buf[TRANSPORT_SENSE_BUFFER]; - /* Completed commands list, serviced from vhost worker thread */ - struct list_head tvc_completion_list; -}; - -struct tcm_vhost_nexus { - /* Pointer to TCM session for I_T Nexus */ - struct se_session *tvn_se_sess; -}; - -struct tcm_vhost_nacl { - /* Binary World Wide unique Port Name for Vhost Initiator port */ - u64 iport_wwpn; - /* ASCII formatted WWPN for Sas Initiator port */ - char iport_name[TCM_VHOST_NAMELEN]; - /* Returned by tcm_vhost_make_nodeacl() */ - struct se_node_acl se_node_acl; -}; - -struct tcm_vhost_tpg { - /* Vhost port target portal group tag for TCM */ - u16 tport_tpgt; - /* Used to track number of TPG Port/Lun Links wrt to explict I_T Nexus shutdown */ - int tv_tpg_port_count; - /* Used for vhost_scsi device reference to tpg_nexus, protected by tv_tpg_mutex */ - int tv_tpg_vhost_count; - /* list for tcm_vhost_list */ - struct list_head tv_tpg_list; - /* Used to protect access for tpg_nexus */ - struct mutex tv_tpg_mutex; - /* Pointer to the TCM VHost I_T Nexus for this TPG endpoint */ - struct tcm_vhost_nexus *tpg_nexus; - /* Pointer back to tcm_vhost_tport */ - struct tcm_vhost_tport *tport; - /* Returned by tcm_vhost_make_tpg() */ - struct se_portal_group se_tpg; -}; - -struct tcm_vhost_tport { - /* SCSI protocol the tport is providing */ - u8 tport_proto_id; - /* Binary World Wide unique Port Name for Vhost Target port */ - u64 tport_wwpn; - /* ASCII formatted WWPN for Vhost Target port */ - char tport_name[TCM_VHOST_NAMELEN]; - /* Returned by tcm_vhost_make_tport() */ - struct se_wwn tport_wwn; -}; - -/* - * As per request from MST, keep TCM_VHOST related ioctl defines out of - * linux/vhost.h (user-space) for now.. - */ - -#include - -/* - * Used by QEMU userspace to ensure a consistent vhost-scsi ABI. - * - * ABI Rev 0: July 2012 version starting point for v3.6-rc merge candidate + - * RFC-v2 vhost-scsi userspace. Add GET_ABI_VERSION ioctl usage - */ - -#define VHOST_SCSI_ABI_VERSION 0 - -struct vhost_scsi_target { - int abi_version; - char vhost_wwpn[TRANSPORT_IQN_LEN]; - unsigned short vhost_tpgt; - unsigned short reserved; -}; - -/* VHOST_SCSI specific defines */ -#define VHOST_SCSI_SET_ENDPOINT _IOW(VHOST_VIRTIO, 0x40, struct vhost_scsi_target) -#define VHOST_SCSI_CLEAR_ENDPOINT _IOW(VHOST_VIRTIO, 0x41, struct vhost_scsi_target) -/* Changing this breaks userspace. */ -#define VHOST_SCSI_GET_ABI_VERSION _IOW(VHOST_VIRTIO, 0x42, int) diff --git a/trunk/drivers/video/auo_k190x.c b/trunk/drivers/video/auo_k190x.c index c03ecdd31e4c..77da6a2f43dc 100644 --- a/trunk/drivers/video/auo_k190x.c +++ b/trunk/drivers/video/auo_k190x.c @@ -987,6 +987,7 @@ int __devinit auok190x_common_probe(struct platform_device *pdev, fb_dealloc_cmap(&info->cmap); err_cmap: fb_deferred_io_cleanup(info); + kfree(info->fbdefio); err_defio: vfree((void *)info->screen_base); err_irq: @@ -1021,6 +1022,7 @@ int __devexit auok190x_common_remove(struct platform_device *pdev) fb_dealloc_cmap(&info->cmap); fb_deferred_io_cleanup(info); + kfree(info->fbdefio); vfree((void *)info->screen_base); diff --git a/trunk/drivers/video/backlight/88pm860x_bl.c b/trunk/drivers/video/backlight/88pm860x_bl.c index f49181c73113..f75da8758adc 100644 --- a/trunk/drivers/video/backlight/88pm860x_bl.c +++ b/trunk/drivers/video/backlight/88pm860x_bl.c @@ -228,6 +228,7 @@ static int pm860x_backlight_probe(struct platform_device *pdev) data->port = pdata->flags; if (data->port < 0) { dev_err(&pdev->dev, "wrong platform data is assigned"); + kfree(data); return -EINVAL; } diff --git a/trunk/drivers/video/console/bitblit.c b/trunk/drivers/video/console/bitblit.c index 61b182bf32a2..28b1a834906b 100644 --- a/trunk/drivers/video/console/bitblit.c +++ b/trunk/drivers/video/console/bitblit.c @@ -162,7 +162,7 @@ static void bit_putcs(struct vc_data *vc, struct fb_info *info, image.depth = 1; if (attribute) { - buf = kmalloc(cellsize, GFP_ATOMIC); + buf = kmalloc(cellsize, GFP_KERNEL); if (!buf) return; } diff --git a/trunk/drivers/video/console/fbcon.c b/trunk/drivers/video/console/fbcon.c index fdefa8fd72c4..2e471c22abf5 100644 --- a/trunk/drivers/video/console/fbcon.c +++ b/trunk/drivers/video/console/fbcon.c @@ -372,15 +372,8 @@ static void fb_flashcursor(struct work_struct *work) struct vc_data *vc = NULL; int c; int mode; - int ret; - - /* FIXME: we should sort out the unbind locking instead */ - /* instead we just fail to flash the cursor if we can't get - * the lock instead of blocking fbcon deinit */ - ret = console_trylock(); - if (ret == 0) - return; + console_lock(); if (ops && ops->currcon != -1) vc = vc_cons[ops->currcon].d; @@ -449,7 +442,7 @@ static int __init fb_console_setup(char *this_opt) while ((options = strsep(&this_opt, ",")) != NULL) { if (!strncmp(options, "font:", 5)) - strlcpy(fontname, options + 5, sizeof(fontname)); + strcpy(fontname, options + 5); if (!strncmp(options, "scrollback:", 11)) { options += 11; diff --git a/trunk/drivers/video/efifb.c b/trunk/drivers/video/efifb.c index 932abaa58a89..b4a632ada401 100644 --- a/trunk/drivers/video/efifb.c +++ b/trunk/drivers/video/efifb.c @@ -553,9 +553,7 @@ static int __init efifb_init(void) int ret; char *option = NULL; - if (screen_info.orig_video_isVGA != VIDEO_TYPE_EFI || - !(screen_info.capabilities & VIDEO_CAPABILITY_SKIP_QUIRKS)) - dmi_check_system(dmi_system_table); + dmi_check_system(dmi_system_table); if (screen_info.orig_video_isVGA != VIDEO_TYPE_EFI) return -ENODEV; diff --git a/trunk/drivers/video/exynos/exynos_mipi_dsi.c b/trunk/drivers/video/exynos/exynos_mipi_dsi.c index 663c308d0e73..4bc2b8a5dd8b 100644 --- a/trunk/drivers/video/exynos/exynos_mipi_dsi.c +++ b/trunk/drivers/video/exynos/exynos_mipi_dsi.c @@ -461,7 +461,7 @@ static int exynos_mipi_dsi_probe(struct platform_device *pdev) done: platform_set_drvdata(pdev, dsim); - dev_dbg(&pdev->dev, "%s() completed successfully (%s mode)\n", __func__, + dev_dbg(&pdev->dev, "%s() completed sucessfuly (%s mode)\n", __func__, dsim_config->e_interface == DSIM_COMMAND ? "CPU" : "RGB"); return 0; diff --git a/trunk/drivers/video/mb862xx/mb862xxfbdrv.c b/trunk/drivers/video/mb862xx/mb862xxfbdrv.c index 57d940be5f3d..00ce1f34b496 100644 --- a/trunk/drivers/video/mb862xx/mb862xxfbdrv.c +++ b/trunk/drivers/video/mb862xx/mb862xxfbdrv.c @@ -328,8 +328,6 @@ static int mb862xxfb_ioctl(struct fb_info *fbi, unsigned int cmd, case MB862XX_L1_SET_CFG: if (copy_from_user(l1_cfg, argp, sizeof(*l1_cfg))) return -EFAULT; - if (l1_cfg->dh == 0 || l1_cfg->dw == 0) - return -EINVAL; if ((l1_cfg->sw >= l1_cfg->dw) && (l1_cfg->sh >= l1_cfg->dh)) { /* downscaling */ outreg(cap, GC_CAP_CSC, diff --git a/trunk/drivers/video/omap2/dss/sdi.c b/trunk/drivers/video/omap2/dss/sdi.c index f43bfe17b3b6..5d31699fbd3c 100644 --- a/trunk/drivers/video/omap2/dss/sdi.c +++ b/trunk/drivers/video/omap2/dss/sdi.c @@ -105,20 +105,6 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev) sdi_config_lcd_manager(dssdev); - /* - * LCLK and PCLK divisors are located in shadow registers, and we - * normally write them to DISPC registers when enabling the output. - * However, SDI uses pck-free as source clock for its PLL, and pck-free - * is affected by the divisors. And as we need the PLL before enabling - * the output, we need to write the divisors early. - * - * It seems just writing to the DISPC register is enough, and we don't - * need to care about the shadow register mechanism for pck-free. The - * exact reason for this is unknown. - */ - dispc_mgr_set_clock_div(dssdev->manager->id, - &sdi.mgr_config.clock_info); - dss_sdi_init(dssdev->phy.sdi.datapairs); r = dss_sdi_enable(); if (r) diff --git a/trunk/drivers/video/omap2/omapfb/omapfb-main.c b/trunk/drivers/video/omap2/omapfb/omapfb-main.c index fc671d3d8004..08ec1a7103f2 100644 --- a/trunk/drivers/video/omap2/omapfb/omapfb-main.c +++ b/trunk/drivers/video/omap2/omapfb/omapfb-main.c @@ -1192,7 +1192,7 @@ static int _setcolreg(struct fb_info *fbi, u_int regno, u_int red, u_int green, break; if (regno < 16) { - u32 pal; + u16 pal; pal = ((red >> (16 - var->red.length)) << var->red.offset) | ((green >> (16 - var->green.length)) << diff --git a/trunk/drivers/video/tmiofb.c b/trunk/drivers/video/tmiofb.c index b244f060f151..8e4a446b5ed1 100644 --- a/trunk/drivers/video/tmiofb.c +++ b/trunk/drivers/video/tmiofb.c @@ -694,10 +694,6 @@ static int __devinit tmiofb_probe(struct platform_device *dev) dev_err(&dev->dev, "NULL platform data!\n"); return -EINVAL; } - if (ccr == NULL || lcr == NULL || vram == NULL || irq < 0) { - dev_err(&dev->dev, "missing resources\n"); - return -EINVAL; - } info = framebuffer_alloc(sizeof(struct tmiofb_par), &dev->dev); diff --git a/trunk/drivers/vme/bridges/vme_ca91cx42.c b/trunk/drivers/vme/bridges/vme_ca91cx42.c index 1425d22cf956..e0df92ec44bd 100644 --- a/trunk/drivers/vme/bridges/vme_ca91cx42.c +++ b/trunk/drivers/vme/bridges/vme_ca91cx42.c @@ -1603,7 +1603,7 @@ static int ca91cx42_probe(struct pci_dev *pdev, const struct pci_device_id *id) { int retval, i; u32 data; - struct list_head *pos = NULL, *n; + struct list_head *pos = NULL; struct vme_bridge *ca91cx42_bridge; struct ca91cx42_driver *ca91cx42_device; struct vme_master_resource *master_image; @@ -1821,28 +1821,28 @@ static int ca91cx42_probe(struct pci_dev *pdev, const struct pci_device_id *id) ca91cx42_crcsr_exit(ca91cx42_bridge, pdev); err_lm: /* resources are stored in link list */ - list_for_each_safe(pos, n, &ca91cx42_bridge->lm_resources) { + list_for_each(pos, &ca91cx42_bridge->lm_resources) { lm = list_entry(pos, struct vme_lm_resource, list); list_del(pos); kfree(lm); } err_dma: /* resources are stored in link list */ - list_for_each_safe(pos, n, &ca91cx42_bridge->dma_resources) { + list_for_each(pos, &ca91cx42_bridge->dma_resources) { dma_ctrlr = list_entry(pos, struct vme_dma_resource, list); list_del(pos); kfree(dma_ctrlr); } err_slave: /* resources are stored in link list */ - list_for_each_safe(pos, n, &ca91cx42_bridge->slave_resources) { + list_for_each(pos, &ca91cx42_bridge->slave_resources) { slave_image = list_entry(pos, struct vme_slave_resource, list); list_del(pos); kfree(slave_image); } err_master: /* resources are stored in link list */ - list_for_each_safe(pos, n, &ca91cx42_bridge->master_resources) { + list_for_each(pos, &ca91cx42_bridge->master_resources) { master_image = list_entry(pos, struct vme_master_resource, list); list_del(pos); @@ -1868,7 +1868,7 @@ static int ca91cx42_probe(struct pci_dev *pdev, const struct pci_device_id *id) static void ca91cx42_remove(struct pci_dev *pdev) { - struct list_head *pos = NULL, *n; + struct list_head *pos = NULL; struct vme_master_resource *master_image; struct vme_slave_resource *slave_image; struct vme_dma_resource *dma_ctrlr; @@ -1905,28 +1905,28 @@ static void ca91cx42_remove(struct pci_dev *pdev) ca91cx42_crcsr_exit(ca91cx42_bridge, pdev); /* resources are stored in link list */ - list_for_each_safe(pos, n, &ca91cx42_bridge->lm_resources) { + list_for_each(pos, &ca91cx42_bridge->lm_resources) { lm = list_entry(pos, struct vme_lm_resource, list); list_del(pos); kfree(lm); } /* resources are stored in link list */ - list_for_each_safe(pos, n, &ca91cx42_bridge->dma_resources) { + list_for_each(pos, &ca91cx42_bridge->dma_resources) { dma_ctrlr = list_entry(pos, struct vme_dma_resource, list); list_del(pos); kfree(dma_ctrlr); } /* resources are stored in link list */ - list_for_each_safe(pos, n, &ca91cx42_bridge->slave_resources) { + list_for_each(pos, &ca91cx42_bridge->slave_resources) { slave_image = list_entry(pos, struct vme_slave_resource, list); list_del(pos); kfree(slave_image); } /* resources are stored in link list */ - list_for_each_safe(pos, n, &ca91cx42_bridge->master_resources) { + list_for_each(pos, &ca91cx42_bridge->master_resources) { master_image = list_entry(pos, struct vme_master_resource, list); list_del(pos); diff --git a/trunk/drivers/vme/bridges/vme_tsi148.c b/trunk/drivers/vme/bridges/vme_tsi148.c index 5fbd08ffb9c2..880d9242e349 100644 --- a/trunk/drivers/vme/bridges/vme_tsi148.c +++ b/trunk/drivers/vme/bridges/vme_tsi148.c @@ -2350,7 +2350,7 @@ static int tsi148_probe(struct pci_dev *pdev, const struct pci_device_id *id) { int retval, i, master_num; u32 data; - struct list_head *pos = NULL, *n; + struct list_head *pos = NULL; struct vme_bridge *tsi148_bridge; struct tsi148_driver *tsi148_device; struct vme_master_resource *master_image; @@ -2615,28 +2615,28 @@ static int tsi148_probe(struct pci_dev *pdev, const struct pci_device_id *id) err_crcsr: err_lm: /* resources are stored in link list */ - list_for_each_safe(pos, n, &tsi148_bridge->lm_resources) { + list_for_each(pos, &tsi148_bridge->lm_resources) { lm = list_entry(pos, struct vme_lm_resource, list); list_del(pos); kfree(lm); } err_dma: /* resources are stored in link list */ - list_for_each_safe(pos, n, &tsi148_bridge->dma_resources) { + list_for_each(pos, &tsi148_bridge->dma_resources) { dma_ctrlr = list_entry(pos, struct vme_dma_resource, list); list_del(pos); kfree(dma_ctrlr); } err_slave: /* resources are stored in link list */ - list_for_each_safe(pos, n, &tsi148_bridge->slave_resources) { + list_for_each(pos, &tsi148_bridge->slave_resources) { slave_image = list_entry(pos, struct vme_slave_resource, list); list_del(pos); kfree(slave_image); } err_master: /* resources are stored in link list */ - list_for_each_safe(pos, n, &tsi148_bridge->master_resources) { + list_for_each(pos, &tsi148_bridge->master_resources) { master_image = list_entry(pos, struct vme_master_resource, list); list_del(pos); diff --git a/trunk/drivers/w1/masters/Kconfig b/trunk/drivers/w1/masters/Kconfig index 7e984034a11b..5ceb1cd50195 100644 --- a/trunk/drivers/w1/masters/Kconfig +++ b/trunk/drivers/w1/masters/Kconfig @@ -60,6 +60,7 @@ config W1_MASTER_GPIO config HDQ_MASTER_OMAP tristate "OMAP HDQ driver" + depends on ARCH_OMAP2PLUS help Say Y here if you want support for the 1-wire or HDQ Interface on an OMAP processor. diff --git a/trunk/drivers/w1/masters/ds1wm.c b/trunk/drivers/w1/masters/ds1wm.c index 7c294f4dc0ed..530a2d309063 100644 --- a/trunk/drivers/w1/masters/ds1wm.c +++ b/trunk/drivers/w1/masters/ds1wm.c @@ -349,7 +349,7 @@ static void ds1wm_search(void *data, struct w1_master *master_dev, "pass: %d entering ASM\n", pass); ds1wm_write_register(ds1wm_data, DS1WM_CMD, DS1WM_CMD_SRA); dev_dbg(&ds1wm_data->pdev->dev, - "pass: %d beginning nibble loop\n", pass); + "pass: %d begining nibble loop\n", pass); r_prime = 0; d = 0; diff --git a/trunk/drivers/w1/masters/omap_hdq.c b/trunk/drivers/w1/masters/omap_hdq.c index ca8e60bb2f9c..4b0fcf3c2d03 100644 --- a/trunk/drivers/w1/masters/omap_hdq.c +++ b/trunk/drivers/w1/masters/omap_hdq.c @@ -18,6 +18,9 @@ #include #include +#include +#include + #include "../w1.h" #include "../w1_int.h" @@ -70,11 +73,11 @@ struct hdq_data { }; static int __devinit omap_hdq_probe(struct platform_device *pdev); -static int __devexit omap_hdq_remove(struct platform_device *pdev); +static int omap_hdq_remove(struct platform_device *pdev); static struct platform_driver omap_hdq_driver = { .probe = omap_hdq_probe, - .remove = __devexit_p(omap_hdq_remove), + .remove = omap_hdq_remove, .driver = { .name = "omap_hdq", }, @@ -535,35 +538,39 @@ static void omap_w1_write_byte(void *_hdq, u8 byte) hdq_data->init_trans = 0; mutex_unlock(&hdq_data->hdq_mutex); } + + return; } static int __devinit omap_hdq_probe(struct platform_device *pdev) { - struct device *dev = &pdev->dev; struct hdq_data *hdq_data; struct resource *res; int ret, irq; u8 rev; - hdq_data = devm_kzalloc(dev, sizeof(*hdq_data), GFP_KERNEL); + hdq_data = kmalloc(sizeof(*hdq_data), GFP_KERNEL); if (!hdq_data) { dev_dbg(&pdev->dev, "unable to allocate memory\n"); - return -ENOMEM; + ret = -ENOMEM; + goto err_kmalloc; } - hdq_data->dev = dev; + hdq_data->dev = &pdev->dev; platform_set_drvdata(pdev, hdq_data); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { dev_dbg(&pdev->dev, "unable to get resource\n"); - return -ENXIO; + ret = -ENXIO; + goto err_resource; } - hdq_data->hdq_base = devm_request_and_ioremap(dev, res); + hdq_data->hdq_base = ioremap(res->start, SZ_4K); if (!hdq_data->hdq_base) { dev_dbg(&pdev->dev, "ioremap failed\n"); - return -ENOMEM; + ret = -EINVAL; + goto err_ioremap; } hdq_data->hdq_usecount = 0; @@ -584,8 +591,7 @@ static int __devinit omap_hdq_probe(struct platform_device *pdev) goto err_irq; } - ret = devm_request_irq(dev, irq, hdq_isr, IRQF_DISABLED, - "omap_hdq", hdq_data); + ret = request_irq(irq, hdq_isr, IRQF_DISABLED, "omap_hdq", hdq_data); if (ret < 0) { dev_dbg(&pdev->dev, "could not request irq\n"); goto err_irq; @@ -610,10 +616,19 @@ static int __devinit omap_hdq_probe(struct platform_device *pdev) err_w1: pm_runtime_disable(&pdev->dev); + iounmap(hdq_data->hdq_base); + +err_ioremap: +err_resource: + platform_set_drvdata(pdev, NULL); + kfree(hdq_data); + +err_kmalloc: return ret; + } -static int __devexit omap_hdq_remove(struct platform_device *pdev) +static int omap_hdq_remove(struct platform_device *pdev) { struct hdq_data *hdq_data = platform_get_drvdata(pdev); @@ -629,11 +644,27 @@ static int __devexit omap_hdq_remove(struct platform_device *pdev) /* remove module dependency */ pm_runtime_disable(&pdev->dev); + free_irq(INT_24XX_HDQ_IRQ, hdq_data); + platform_set_drvdata(pdev, NULL); + iounmap(hdq_data->hdq_base); + kfree(hdq_data); return 0; } -module_platform_driver(omap_hdq_driver); +static int __init +omap_hdq_init(void) +{ + return platform_driver_register(&omap_hdq_driver); +} +module_init(omap_hdq_init); + +static void __exit +omap_hdq_exit(void) +{ + platform_driver_unregister(&omap_hdq_driver); +} +module_exit(omap_hdq_exit); module_param(w1_id, int, S_IRUSR); MODULE_PARM_DESC(w1_id, "1-wire id for the slave detection"); diff --git a/trunk/drivers/w1/masters/w1-gpio.c b/trunk/drivers/w1/masters/w1-gpio.c index 6012c4ea3206..df600d14974d 100644 --- a/trunk/drivers/w1/masters/w1-gpio.c +++ b/trunk/drivers/w1/masters/w1-gpio.c @@ -14,8 +14,6 @@ #include #include #include -#include -#include #include "../w1.h" #include "../w1_int.h" @@ -44,55 +42,12 @@ static u8 w1_gpio_read_bit(void *data) return gpio_get_value(pdata->pin) ? 1 : 0; } -#ifdef CONFIG_OF -static struct of_device_id w1_gpio_dt_ids[] = { - { .compatible = "w1-gpio" }, - {} -}; -MODULE_DEVICE_TABLE(of, w1_gpio_dt_ids); - -static int w1_gpio_probe_dt(struct platform_device *pdev) -{ - struct w1_gpio_platform_data *pdata = pdev->dev.platform_data; - struct device_node *np = pdev->dev.of_node; - const struct of_device_id *of_id = - of_match_device(w1_gpio_dt_ids, &pdev->dev); - - if (!of_id) - return 0; - - pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); - if (!pdata) - return -ENOMEM; - - if (of_get_property(np, "linux,open-drain", NULL)) - pdata->is_open_drain = 1; - - pdata->pin = of_get_gpio(np, 0); - pdata->ext_pullup_enable_pin = of_get_gpio(np, 1); - pdev->dev.platform_data = pdata; - - return 0; -} -#else -static int w1_gpio_probe_dt(struct platform_device *pdev) -{ - return 0; -} -#endif - static int __init w1_gpio_probe(struct platform_device *pdev) { struct w1_bus_master *master; - struct w1_gpio_platform_data *pdata; + struct w1_gpio_platform_data *pdata = pdev->dev.platform_data; int err; - err = w1_gpio_probe_dt(pdev); - if (err < 0) - return err; - - pdata = pdev->dev.platform_data; - if (!pdata) return -ENXIO; @@ -104,13 +59,6 @@ static int __init w1_gpio_probe(struct platform_device *pdev) if (err) goto free_master; - if (gpio_is_valid(pdata->ext_pullup_enable_pin)) { - err = gpio_request_one(pdata->ext_pullup_enable_pin, - GPIOF_INIT_LOW, "w1 pullup"); - if (err < 0) - goto free_gpio; - } - master->data = pdata; master->read_bit = w1_gpio_read_bit; @@ -124,21 +72,15 @@ static int __init w1_gpio_probe(struct platform_device *pdev) err = w1_add_master_device(master); if (err) - goto free_gpio_ext_pu; + goto free_gpio; if (pdata->enable_external_pullup) pdata->enable_external_pullup(1); - if (gpio_is_valid(pdata->ext_pullup_enable_pin)) - gpio_set_value(pdata->ext_pullup_enable_pin, 1); - platform_set_drvdata(pdev, master); return 0; - free_gpio_ext_pu: - if (gpio_is_valid(pdata->ext_pullup_enable_pin)) - gpio_free(pdata->ext_pullup_enable_pin); free_gpio: gpio_free(pdata->pin); free_master: @@ -155,9 +97,6 @@ static int __exit w1_gpio_remove(struct platform_device *pdev) if (pdata->enable_external_pullup) pdata->enable_external_pullup(0); - if (gpio_is_valid(pdata->ext_pullup_enable_pin)) - gpio_set_value(pdata->ext_pullup_enable_pin, 0); - w1_remove_master_device(master); gpio_free(pdata->pin); kfree(master); @@ -196,7 +135,6 @@ static struct platform_driver w1_gpio_driver = { .driver = { .name = "w1-gpio", .owner = THIS_MODULE, - .of_match_table = of_match_ptr(w1_gpio_dt_ids), }, .remove = __exit_p(w1_gpio_remove), .suspend = w1_gpio_suspend, diff --git a/trunk/drivers/w1/slaves/w1_therm.c b/trunk/drivers/w1/slaves/w1_therm.c index 92d08e7fcba2..d90062b211f8 100644 --- a/trunk/drivers/w1/slaves/w1_therm.c +++ b/trunk/drivers/w1/slaves/w1_therm.c @@ -91,11 +91,6 @@ static struct w1_family w1_therm_family_DS28EA00 = { .fops = &w1_therm_fops, }; -static struct w1_family w1_therm_family_DS1825 = { - .fid = W1_THERM_DS1825, - .fops = &w1_therm_fops, -}; - struct w1_therm_family_converter { u8 broken; @@ -125,10 +120,6 @@ static struct w1_therm_family_converter w1_therm_families[] = { .f = &w1_therm_family_DS28EA00, .convert = w1_DS18B20_convert_temp }, - { - .f = &w1_therm_family_DS1825, - .convert = w1_DS18B20_convert_temp - } }; static inline int w1_DS18B20_convert_temp(u8 rom[9]) diff --git a/trunk/drivers/w1/w1_family.h b/trunk/drivers/w1/w1_family.h index a1f0ce151d53..b00ada44a89b 100644 --- a/trunk/drivers/w1/w1_family.h +++ b/trunk/drivers/w1/w1_family.h @@ -39,7 +39,6 @@ #define W1_EEPROM_DS2431 0x2D #define W1_FAMILY_DS2760 0x30 #define W1_FAMILY_DS2780 0x32 -#define W1_THERM_DS1825 0x3B #define W1_FAMILY_DS2781 0x3D #define W1_THERM_DS28EA00 0x42 diff --git a/trunk/drivers/watchdog/booke_wdt.c b/trunk/drivers/watchdog/booke_wdt.c index 5b06d31ab6a9..3fe82d0e8caa 100644 --- a/trunk/drivers/watchdog/booke_wdt.c +++ b/trunk/drivers/watchdog/booke_wdt.c @@ -166,17 +166,18 @@ static long booke_wdt_ioctl(struct file *file, switch (cmd) { case WDIOC_GETSUPPORT: - return copy_to_user(p, &ident, sizeof(ident)) ? -EFAULT : 0; + if (copy_to_user((void *)arg, &ident, sizeof(ident))) + return -EFAULT; case WDIOC_GETSTATUS: return put_user(0, p); case WDIOC_GETBOOTSTATUS: /* XXX: something is clearing TSR */ tmp = mfspr(SPRN_TSR) & TSR_WRS(3); /* returns CARDRESET if last reset was caused by the WDT */ - return put_user((tmp ? WDIOF_CARDRESET : 0), p); + return (tmp ? WDIOF_CARDRESET : 0); case WDIOC_SETOPTIONS: if (get_user(tmp, p)) - return -EFAULT; + return -EINVAL; if (tmp == WDIOS_ENABLECARD) { booke_wdt_ping(); break; diff --git a/trunk/drivers/watchdog/da9052_wdt.c b/trunk/drivers/watchdog/da9052_wdt.c index f7abbaeebcaf..3f75129eb0a9 100644 --- a/trunk/drivers/watchdog/da9052_wdt.c +++ b/trunk/drivers/watchdog/da9052_wdt.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include diff --git a/trunk/drivers/watchdog/hpwdt.c b/trunk/drivers/watchdog/hpwdt.c index ae60406ea8a1..1eff743ec497 100644 --- a/trunk/drivers/watchdog/hpwdt.c +++ b/trunk/drivers/watchdog/hpwdt.c @@ -814,9 +814,6 @@ static int __devinit hpwdt_init_one(struct pci_dev *dev, hpwdt_timer_reg = pci_mem_addr + 0x70; hpwdt_timer_con = pci_mem_addr + 0x72; - /* Make sure that timer is disabled until /dev/watchdog is opened */ - hpwdt_stop(); - /* Make sure that we have a valid soft_margin */ if (hpwdt_change_timer(soft_margin)) hpwdt_change_timer(DEFAULT_MARGIN); diff --git a/trunk/drivers/watchdog/watchdog_core.c b/trunk/drivers/watchdog/watchdog_core.c index 3796434991fa..6aa46a90ff02 100644 --- a/trunk/drivers/watchdog/watchdog_core.c +++ b/trunk/drivers/watchdog/watchdog_core.c @@ -128,12 +128,11 @@ EXPORT_SYMBOL_GPL(watchdog_register_device); void watchdog_unregister_device(struct watchdog_device *wdd) { int ret; - int devno; + int devno = wdd->cdev.dev; if (wdd == NULL) return; - devno = wdd->cdev.dev; ret = watchdog_dev_unregister(wdd); if (ret) pr_err("error unregistering /dev/watchdog (err=%d)\n", ret); diff --git a/trunk/drivers/xen/gntdev.c b/trunk/drivers/xen/gntdev.c index 7f1241608489..1ffd03bf8e10 100644 --- a/trunk/drivers/xen/gntdev.c +++ b/trunk/drivers/xen/gntdev.c @@ -314,9 +314,8 @@ static int __unmap_grant_pages(struct grant_map *map, int offset, int pages) } } - err = gnttab_unmap_refs(map->unmap_ops + offset, - use_ptemod ? map->kmap_ops + offset : NULL, map->pages + offset, - pages); + err = gnttab_unmap_refs(map->unmap_ops + offset, map->pages + offset, + pages, true); if (err) return err; diff --git a/trunk/drivers/xen/grant-table.c b/trunk/drivers/xen/grant-table.c index 006726688baf..0bfc1ef11259 100644 --- a/trunk/drivers/xen/grant-table.c +++ b/trunk/drivers/xen/grant-table.c @@ -870,8 +870,7 @@ int gnttab_map_refs(struct gnttab_map_grant_ref *map_ops, EXPORT_SYMBOL_GPL(gnttab_map_refs); int gnttab_unmap_refs(struct gnttab_unmap_grant_ref *unmap_ops, - struct gnttab_map_grant_ref *kmap_ops, - struct page **pages, unsigned int count) + struct page **pages, unsigned int count, bool clear_pte) { int i, ret; bool lazy = false; @@ -889,8 +888,7 @@ int gnttab_unmap_refs(struct gnttab_unmap_grant_ref *unmap_ops, } for (i = 0; i < count; i++) { - ret = m2p_remove_override(pages[i], kmap_ops ? - &kmap_ops[i] : NULL); + ret = m2p_remove_override(pages[i], clear_pte); if (ret) return ret; } diff --git a/trunk/drivers/xen/platform-pci.c b/trunk/drivers/xen/platform-pci.c index 97ca359ae2bd..d4c50d63acbc 100644 --- a/trunk/drivers/xen/platform-pci.c +++ b/trunk/drivers/xen/platform-pci.c @@ -101,6 +101,19 @@ static int platform_pci_resume(struct pci_dev *pdev) return 0; } +static void __devinit prepare_shared_info(void) +{ +#ifdef CONFIG_KEXEC + unsigned long addr; + struct shared_info *hvm_shared_info; + + addr = alloc_xen_mmio(PAGE_SIZE); + hvm_shared_info = ioremap(addr, PAGE_SIZE); + memset(hvm_shared_info, 0, PAGE_SIZE); + xen_hvm_prepare_kexec(hvm_shared_info, addr >> PAGE_SHIFT); +#endif +} + static int __devinit platform_pci_init(struct pci_dev *pdev, const struct pci_device_id *ent) { @@ -138,6 +151,8 @@ static int __devinit platform_pci_init(struct pci_dev *pdev, platform_mmio = mmio_addr; platform_mmiolen = mmio_len; + prepare_shared_info(); + if (!xen_have_vector_callback) { ret = xen_allocate_irq(pdev); if (ret) { diff --git a/trunk/drivers/xen/swiotlb-xen.c b/trunk/drivers/xen/swiotlb-xen.c index 4d519488d304..1afb4fba11b4 100644 --- a/trunk/drivers/xen/swiotlb-xen.c +++ b/trunk/drivers/xen/swiotlb-xen.c @@ -232,7 +232,7 @@ xen_swiotlb_alloc_coherent(struct device *hwdev, size_t size, return ret; if (hwdev && hwdev->coherent_dma_mask) - dma_mask = dma_alloc_coherent_mask(hwdev, flags); + dma_mask = hwdev->coherent_dma_mask; phys = virt_to_phys(ret); dev_addr = xen_phys_to_bus(phys); diff --git a/trunk/drivers/xen/xen-pciback/pci_stub.c b/trunk/drivers/xen/xen-pciback/pci_stub.c index 92ff01dbeb10..097e536e8672 100644 --- a/trunk/drivers/xen/xen-pciback/pci_stub.c +++ b/trunk/drivers/xen/xen-pciback/pci_stub.c @@ -353,16 +353,16 @@ static int __devinit pcistub_init_device(struct pci_dev *dev) if (err) goto config_release; + dev_dbg(&dev->dev, "reseting (FLR, D3, etc) the device\n"); + __pci_reset_function_locked(dev); + /* We need the device active to save the state. */ dev_dbg(&dev->dev, "save state of device\n"); pci_save_state(dev); dev_data->pci_saved_state = pci_store_saved_state(dev); if (!dev_data->pci_saved_state) dev_err(&dev->dev, "Could not store PCI conf saved state!\n"); - else { - dev_dbg(&dev->dev, "reseting (FLR, D3, etc) the device\n"); - __pci_reset_function_locked(dev); - } + /* Now disable the device (this also ensures some private device * data is setup before we export) */ @@ -871,7 +871,7 @@ static void xen_pcibk_error_resume(struct pci_dev *dev) } /*add xen_pcibk AER handling*/ -static const struct pci_error_handlers xen_pcibk_error_handler = { +static struct pci_error_handlers xen_pcibk_error_handler = { .error_detected = xen_pcibk_error_detected, .mmio_enabled = xen_pcibk_mmio_enabled, .slot_reset = xen_pcibk_slot_reset, diff --git a/trunk/drivers/zorro/zorro.c b/trunk/drivers/zorro/zorro.c index 858c9714b2f3..181fa8158a8b 100644 --- a/trunk/drivers/zorro/zorro.c +++ b/trunk/drivers/zorro/zorro.c @@ -37,6 +37,7 @@ struct zorro_dev zorro_autocon[ZORRO_NUM_AUTO]; */ struct zorro_bus { + struct list_head devices; /* list of devices on this bus */ struct device dev; }; @@ -135,6 +136,7 @@ static int __init amiga_zorro_probe(struct platform_device *pdev) if (!bus) return -ENOMEM; + INIT_LIST_HEAD(&bus->devices); bus->dev.parent = &pdev->dev; dev_set_name(&bus->dev, "zorro"); error = device_register(&bus->dev); diff --git a/trunk/firmware/Makefile b/trunk/firmware/Makefile index fdc9ff045ef8..344713b11669 100644 --- a/trunk/firmware/Makefile +++ b/trunk/firmware/Makefile @@ -40,6 +40,7 @@ fw-shipped-$(CONFIG_BNX2) += bnx2/bnx2-mips-09-6.2.1a.fw \ bnx2/bnx2-mips-06-6.2.1.fw \ bnx2/bnx2-rv2p-06-6.0.15.fw fw-shipped-$(CONFIG_CASSINI) += sun/cassini.bin +fw-shipped-$(CONFIG_COMPUTONE) += intelliport2.bin fw-shipped-$(CONFIG_CHELSIO_T3) += cxgb3/t3b_psram-1.1.0.bin \ cxgb3/t3c_psram-1.1.0.bin \ cxgb3/t3fw-7.10.0.bin \ diff --git a/trunk/firmware/intelliport2.bin.ihex b/trunk/firmware/intelliport2.bin.ihex new file mode 100644 index 000000000000..e9cfe8cb2b21 --- /dev/null +++ b/trunk/firmware/intelliport2.bin.ihex @@ -0,0 +1,2147 @@ +:100000003C4237180201030000000000000000001D +:10001000576564204465632030312031323A3234F0 +:100020003A33302031393939000000000000000037 +:10003000E96C0F426547694E6E496E47206F462056 +:10004000634F6445CC135A15E8167618041A921BB0 +:10005000201DAE1E3C20CA215823E6247426022807 +:1000600090291E2BAC2C3A2EC82F5631E432723414 +:1000700000368E371C39AA3A383CC63D543FE24020 +:100080007042FE438C451A47A848364AC44B524D2D +:10009000E04E6E50FC518A531855A6563458C2593A +:1000A000505BDE5C6C5EFA5F88611663A464326646 +:1000B000C0674E69DC6A6A6CF86D866F1471A27253 +:1000C0003074BE754C776C778C77AC7733DB8ADC19 +:1000D0005333DB250700750A8A1E080183E30CEB06 +:1000E00020903C01750A8A1E080180E3C0EB129043 +:1000F0008A1E0D013C02750680E30CEB049080E340 +:10010000C053508B1EBA138EDBE86A65558BEC53D7 +:100110001E2BC08ED88B5E04C1E304035E06D1E3C0 +:100120002E8B9F44008D472A1E5A1F5B5DC3558B43 +:10013000EC531E2BC08ED88B5E04C1E304035E0615 +:10014000D1E32E8B9F44008D47341E5A1F5B5DC345 +:10015000FB558BEC53515256571E061E0733C08E6B +:10016000D88B5E04268A47592503008BF0D1E62EF2 +:100170008BB4C400C1E0042602471AD1E08BE82EFC +:100180008BAE4400892C268A471C88440F268A4758 +:100190001D884410268A471E884411268A471F88D6 +:1001A0004412268A4720884413268A472388441409 +:1001B000268A4724884415268A475A88440E33C025 +:1001C00089440689440888440B88440AB021B464F1 +:1001D000894404894402B05588440D88440CE86A77 +:1001E00000725BE8C900E8C110894408807C0F01F7 +:1001F0007429E82B02E87F02807C0F03741DE8A9B4 +:10020000108BF82B44083DA00F7210897C0833C076 +:1002100087440685C07504C6440AFF8A440A84C020 +:10022000750BB80800E86A4AE8A90173BFE84F01F6 +:100230008166487FFF83667ABFB002E8040E8A4475 +:100240000A98071F5F5E5A595B5DC3814E48800064 +:10025000B040E83D4AE88940732AE84D108BD8B099 +:1002600005E82E4AF6462702751AE83D102BC33DD5 +:10027000581B72EB8166487FFFB002E8C40DC6448C +:100280000A01F9C3834E7A40F8C3FBB001E8024A81 +:10029000FAE8991EE40A84C075F0B04EE60AFBB095 +:1002A00001E8EE49FAE8851EE40A84C075F0C3FA55 +:1002B000E87A1EE4EC884416E4E4884417E4F888FD +:1002C0004418E4F0884419E41088441AE41288447D +:1002D0001BE41488441CE43488441DE43688441E1E +:1002E000E4D824018AE0E4DA24020AC488441F8A9C +:1002F0004410E8CD1F8A4411E835218A4412E88968 +:10030000218A4413E84321C686A10000E414241086 +:10031000E614E412243DE6128A44153C01721E776D +:1003200016B011E634B013E636E4140C10E614E40B +:10033000120C40E612EB06E4120C02E6128A440F9D +:100340003C0174063C02740AEB0EE4120C08E6123F +:10035000EB06E4120C10E612E82FFF8A44143C026C +:100360007508B05588440C88440DB021B4648944A4 +:1003700004894402E40C0C10E60CE8ED39FBC3E8F8 +:100380005F3F7308FBB00AE80849EBF3FAE89D1DEC +:100390008A64168A441789869400E6E48AC4E6ECE7 +:1003A0008A64188A441989869600E6F08AC4E6F8B9 +:1003B0008A441AE6108A441BE6128A441CE6148A10 +:1003C000441DE6348A441EE6368A441FE6D8E6DA3F +:1003D000E9B7FE90FA8A440EE6FEE402A80175052C +:1003E00033C0FBF8C333C0E400FBF9C38A64148054 +:1003F000FC02742BFEC0FEC780FF4E721C74098085 +:10040000FF507308B00AEB17B00DEB1302DC32FF9C +:1004100080FB7F7C02B3218AC33C7F7C02B021C376 +:10042000FA807C0B047602FBC38B46243D080072E5 +:10043000F68E46028B7E228A440C8B5C02AAE8ABC5 +:10044000FFAAE8A7FFAAE8A3FFAAE89FFF88440C39 +:10045000895C0280440B04897E22836E24048346D7 +:100460001A04807E26027406806626FDFBC360B0F7 +:10047000FDE8023F61FBC3FA807C0F037509C644A7 +:100480000B00E8E538FBC3C47E148B4E3A85C97572 +:1004900035268B0D4747E3EA3B7E047622B80200FF +:1004A00039462E7707C7462E0000EB138B5E2C894A +:1004B0005E0426C70700004343895E2C29462E852B +:1004C000C978CE894E3A8A440D8B5C04268A25472A +:1004D0003AC47516FE4C0BFF4406E80FFFE2ED88A8 +:1004E000440D895C04894E3AEBA7C6440AFEE879BC +:1004F00038FBC390E8B30D8AE88A0ECB13B3078AA2 +:10050000C1EEEB00EC3AC1750902CDFECB75F0EB04 +:100510000C90880ECB138AE8BBFFFFF9C3880ECB83 +:1005200013F8C390BB3F3F8A8E9E00BAFE00EC8A50 +:10053000E832C122C37502F8C3F9C390E8E5FF733E +:1005400001C3BAD000BB03038A8E9F00EC8AE83255 +:10055000C122C37502F8C3F9C39033C08ED88EC0D0 +:10056000803EC813007507B00AE82647EBF2FB335C +:10057000DB8A1EC913434383FB7E760733DBB0025D +:10058000E80F472E8BAF4400837E080074E7881E77 +:10059000C913B002E8FB46FAF7463840007414E885 +:1005A000961BE87FFF721C33D28A969F0083C20E8F +:1005B000EB0C90E8771BE883FF7208BA4800E83339 +:1005C000FF73AB23CB898E9A0089969C00FE86B57B +:1005D00000C606C81300B00AE8670AFBEB891018CA +:1005E000082833C0A005018AC824407524C7067CAA +:1005F000128E45C70642120100C606541202B00808 +:10060000F6C1017402B004A34612A24C12A29412C5 +:10061000C3C7067C12B645A00F0184C0750E6A00E0 +:100620001FC60693121E9C0EE8B10C90C70644121A +:100630000100A342128BD8C1E304881E9412BEE2CB +:10064000052BF08BC833DB8BFB2EAC888548128AD8 +:10065000D80C05E6FE8AE0EB00E4FE32C4A83F7445 +:1006600003E99E00E400888550128AE02430BA1025 +:10067000FF3C30741280FC04740ABA0403F60608C6 +:1006800001FE7403BA080F88954C1202FA32C0F6C4 +:10069000C4087402B001888558128AC43C35745B62 +:1006A0003C3674573C3474533C04744F3C14744BC4 +:1006B0003C157447A8407425C685541204D1E7B48C +:1006C000038AC389855C128AC38AE380CC01898549 +:1006D0006412D1EF47E203EB1A90E96CFFC6855430 +:1006E0001202D1E78AE68AC30C0489855C12D1EF35 +:1006F00047E2E733C08AC7A34612C3C68554120631 +:10070000EBBBC68554120033C08885501288854CD7 +:100710001288855812EBA6C7462602128B461E8900 +:1007200046008946228B4620894624C7461A000087 +:10073000C3C7463C8000C7463801001E568B763042 +:100740008976048976148E5E0633C089044646890C +:10075000762C89463A8B4632484889462E5E1FC31E +:1007600033C089464889464AC74646AE0189464E47 +:100770008B46448946508B4642894640894608C389 +:1007800033C0894676894678C7467A1000561E8B54 +:10079000767089761089760C8E5E12C70400008B05 +:1007A00046728946741F5EC3895618895602895657 +:1007B0000689560A89560E8956128956168BD84BC9 +:1007C0004BC1E302BF0200897E1E03FB897E30031A +:1007D000FB897E4203FB897E7083EB08895E20895A +:1007E0005E32895E44895E7250E82BFFE871FFE853 +:1007F0003FFFE88BFF58C3B83075C1E8040E5B03B8 +:10080000C3A3BA13833E4212007407803E941200C1 +:10081000750E6A001FC60693121E9C0EE8BD0A9054 +:10082000B8307AC1E80440A3C0132B061201F7D8F0 +:1008300033D28BCA8A0E9412F7F13D8000770E6A8C +:10084000001FC6069312259C0EE8900A90483DFFB3 +:10085000077203B8FF07A3C21333C98A0E94123379 +:10086000F6B800092E8BAC440089464C404646E25F +:10087000F38A0E941233F68B16C013A1C2132E8B7B +:10088000AC4400E822FF03D04646E2F2C333C02E58 +:100890008BAD44008946084747E2F4C35133C00A90 +:1008A000C22E8BAD440089869E00814E38002047C1 +:1008B00047FEC480FC04720432E4FEC0E2E35983C4 +:1008C000E9107405F7D9E8C4FFC35133C00AC22E3A +:1008D0008BAD440089869E00834E3840474780C4D4 +:1008E00010790432E4FEC0E2E65983E9107405F79A +:1008F000D9E899FFC3E8D2FFC38D089C08CA08F560 +:10090000088B0E421233F6515633DB8BCB8A944858 +:10091000128A8C4C128A9C54128BFEC1E70585DB2F +:100920007502B1102EFF97F9085E5946E2D9C3014E +:10093000CC03D000E802D000E801D000E800D000ED +:10094000E804D0A8DA00DC00DE01D803CC03CC0335 +:10095000CC04D0A8DA20DC00DE03CC03CC03CC002E +:10096000D803CC03CC03CC03CC03CC03CC03CC0303 +:10097000CC03CC03CC03CC03CC03CC03CC03CC03FF +:10098000CC04D000DA20DC03DE01D803CC03CC0396 +:10099000CC03CC00D800CC00D0000056521E0E1F55 +:1009A000BE2F0933D2FCAD85C0740D8AD4EEAD855F +:1009B000C074058AD4EEEBEE1F5A5EC3E48084C097 +:1009C00074167814B027E6FCB011E634E4FC3C273A +:1009D0007506E4117502F8C3F9C383C206B0BFEE11 +:1009E00083EA02B010EE8886AF00B01183C204EE35 +:1009F00083C202EEB01383C202EE83C202EE2EA1C6 +:100A00004C2D8986940083EA0EEE83C2028AC4EEDE +:100A100083C204B003EE8886A80083EA0432C0EEE5 +:100A200083C202B089EE8886A6000C06EEB040B400 +:100A30003889461CC74636380083C20432C0EE8867 +:100A400086A700C383C206B0BFEE83EA02EC3A86F3 +:100A5000AF00752483C204EC3C11751C83C206EC04 +:100A60003C13751483EA088A86A800EE83EA02EC38 +:100A700024C03CC07502F8C3F9C333C98BD18BF1D4 +:100A80008A0E9412C1E9022E8BAC4400F74638005E +:100A900020740E8A869E00E6FE32C0E68042E8FAA6 +:100AA000FE83C608E2E185D27403E80508C333C9B2 +:100AB0008BF18A0E94122E8BAC4400F7463840001E +:100AC0007406E87316E812FF4646E2EAC333C98BA0 +:100AD000F18A0E9412C1E9022E8BAC4400F746381D +:100AE00000207416E84616E8D2FE730E6A001FC690 +:100AF0000693121C9C0EE8E3079083C608E2D9C354 +:100B000033C98BF18A0E94122E8BAC4400F7463811 +:100B100040007416E82116E82AFF730E6A001FC60B +:100B20000693121C9C0EE8B307904646E2DAC30C0B +:100B300000001000131200001400283C001B3E00AF +:100B4000002A00002C0000420014D80000DA000047 +:100B50003400113600133800113A001300005650CB +:100B600052BE2F0B2EAD85C07406922EACEEEBF468 +:100B70005A585EC3532EA16022E6E4E6F08AC4E62A +:100B8000ECE6F8E8D8FFB04BE610B050E612B0380B +:100B9000E614E8AE15B046E60AE8A715B01AE60A6C +:100BA000E8A015B022E60AE89915E8FD068BD8E41E +:100BB00016A8047518E8F2062BC33D320072F06ADD +:100BC000001FC6069312239C0EE8100790E8DA0671 +:100BD0002BC33D2400771BB031E6FC565155B910AC +:100BE000002E8BAC4400814E3880004646E2F25D18 +:100BF000595EE869FFE84B15B046E60AE844155B24 +:100C0000C333F68B0E42122E8BAC4400F7463800ED +:100C1000207406E81715E85BFF83C620E2E9C38B62 +:100C2000C20504008946282EA14C2D89868E008994 +:100C300086900089869200C686A3000AC686C300F5 +:100C4000035283C2048A86A6000C06EE5A83C202AF +:100C5000B005EE8886A500C3E803FFE8E514B042BE +:100C6000E60AF74638800074062EA19C22EB042E7B +:100C7000A16C22C7461C0C008986940089869600C8 +:100C800089868E008986900089869200E6F0E6E4E7 +:100C90008AC4E6F8E6ECC686C30003E8A514B01AD9 +:100CA000E60AB0108886A500E60CC333C98BF18A2A +:100CB0000E94122E8BAC4400F7463840007406E8C0 +:100CC0007614E85AFF4646E2EAC333C98BF18A0E2E +:100CD00094122E8BAC4400F7463800207406E84C82 +:100CE00014E874FF4646E2EAC390833E441200755E +:100CF00014B001BA0601EE2AC0EEB002EEB004EE66 +:100D0000B80002EB0FBA0601B040EEB801008A0E3F +:100D10000E01D3E0A38812C3A18812A384122D2050 +:100D200000A38A122D2000A38212C706861220007B +:100D3000C70680123200C3833E44120074768B0EC5 +:100D4000421233F68AA4541284E4745F8A844812EF +:100D50000C04E6FEF6C4047425B01BBA0000EEEBEA +:100D6000002AC0BA0200EEEB00B003EEEB0032C086 +:100D7000BA0200EEEB00BA0000B000EEEB2DB01F9F +:100D8000BA0000EEEB002AC0BA0200EEEB00B0039E +:100D9000EEEB00D1E68A845D12D1EEF6D0BA020005 +:100DA000EEEB00BA0000B00AEEEB00E404EB00E466 +:100DB0000446E290C390B81400BA3EFFEFB80600B4 +:100DC000BA32FFEFB80F00BA34FFEFBA36FFEF8345 +:100DD0003E4412007516B81100BA38FFEFB8120081 +:100DE000BA3AFFEFB81B00BA3CFFEFC3B81100BA24 +:100DF00038FFEFB81200BA3AFFEFB81B00BA3CFF59 +:100E0000EFC3B8FC00BA28FFEFFB833E4412007426 +:100E100007B8CC00BA28FFEFC300FFFF202428FF4B +:100E20002CFFFF303438FFFF3C903C0F770EBB198E +:100E30000E2ED73CFF74058AD8F8C3902ADBF9C37D +:100E4000833E4412007427A00601802606013080EC +:100E50003E0601307518B90200BFC413BA0601EC92 +:100E6000A82075F8BA0401EDABE2F1EB1690B904D5 +:100E700000BFC413BA0601ECA82075F8BA0401EC4F +:100E8000AAE2F1FA90BEC413AD80E43F80FC027484 +:100E90000E6A001FC60693120A9C0EE83E0490AD2F +:100EA0003C0F75ED8AC4E881FF72E6881E1A01C600 +:100EB000068E1200B0000A061A01BA0001EEC6063C +:100EC0008F1240833E4412007506B80C00EB04906C +:100ED000B84C00BA28FFEFC3833E4412007501C32B +:100EE000A150120B0652120AC4A80874F2A00F01F6 +:100EF0002AE450FF36BA131FE8505683C4026A0032 +:100F00001F33C0A3BC13A00F01A3BE138B1EBC13C1 +:100F10008A875012F687501208740D24078AE0BEA3 +:100F2000CC00A0BC13E8943DFF06BC13FF0EBE131B +:100F300075DAC3901E33C08ED8B001E8543D1FC38C +:100F400033C98BF18A0E94122E8BAC4400C74662D3 +:100F50003844C7467CFC3BC7467EE23BC7868000E0 +:100F6000EC3CE8AB16C686C00011837E080074070F +:100F70005156E833335E594646E2CDC333C98BF14F +:100F80008BF98A0E9412C1E902E3132E8BAC440054 +:100F90008A869E0088856C1283C60847E2EDC3FAF4 +:100FA000FCB0C0BA0001EE33C08ED88EC08ED0BF68 +:100FB0001601B9CC772BCFD1E9F3ABBC4012E8D9FD +:100FC00002E8703CBECC0FE8F23CF49033C08ED8FF +:100FD0008EC08ED0F6060A0180740BBE3555E8DB54 +:100FE0003CB001E8AC3CE8B300E8F6F5E808F8E806 +:100FF0000FF9E885FAE8B6FAE8EFFCE8C210E80372 +:101000003CE8B2FDE830FDE85402C6068F12C0E8A5 +:10101000BBFAE8EBFAE8E9FBE8AFFCE88DFCE81F77 +:10102000FFE858FFE8DBFDE816FE33C0BE5A05E8CE +:101030008A3CE8A3FEE8E0FCFBBEA444E87D3CE972 +:10104000CA2D56988BF08B425285C07527C74252E5 +:10105000010053368B9C2C01F6C301750C36896850 +:10106000523689AC2C015B5EC33689AC2C013689C3 +:10107000AC1C015B5EC356988BF033ED368B841C41 +:1010800001A80175158BE833C08742523689841C4C +:1010900001A80174053689842C015EC3565133F6CC +:1010A000B80100B9080089841C0189842C014646D6 +:1010B000E2F4595EC390BB01008BE8FF4E6E740AE8 +:1010C0008BDD8B4658A80174F0C38B4648A90800F5 +:1010D0007445F7463840007427E85C1080C2068AE1 +:1010E00086A80024BF8886A800EE60B0FEE886329D +:1010F00061B002E84CFF8B464824F7894648EB175D +:10110000E82A10814E2600408A86A5000C028886B7 +:10111000A500E60C8B4648A904007414B002E8212F +:10112000FF8B464824FB89464860B0DFE8473261C0 +:1011300033C0874658F6C301750B36894758A80156 +:10114000750DE974FFA32201A8017503E96AFF89FF +:101150001E3201C3BB01008BE8F74638400074150E +:10116000E8D50F80C20AECA840750A8BDD8B465685 +:10117000A80174E3C38B462680E4FE80CC02894636 +:1011800026B002E8BCFE33C0874656F6C301750A96 +:1011900036894756A801750BEBBDA32001A8017540 +:1011A00002EBB4891E3001C3601E062BC08ED8A08E +:1011B000901284C07549A12201A8017503E8F6FECA +:1011C000A12001A8017503E88AFFA1AC13487805A6 +:1011D0007445A3AC13A1AE134878057451A3AE13A4 +:1011E000A1B0134878057463A3B013A17E124078B0 +:1011F00003A37E12B80080BA22FFEF071F61CFA0C1 +:101200009112403C02720B33C0A29112FF167C1265 +:10121000EBA4A29112EB9FA08E1232068F12A28E27 +:10122000120A061A01BA0001EEB82C01EBA4833EA3 +:101230008412107211BA28FFED0C81EFE85337BA0F +:1012400028FFED247EEFB80400EB92C6068D120154 +:10125000E83F37C6068D1200A1B213EB8B908A1EB1 +:101260000B012AFF6BC319BA62FFEFB80A00BA601C +:10127000FFEFB801E0BA66FFEFB8FFFFBA52FFEF29 +:10128000B809C0BA56FFEFC706AC132C01C706AEAB +:10129000130400C606911200C3908A1E0B012AFF98 +:1012A0006BC305D1E8A31801C39052BA50FFED5AA1 +:1012B000C39053518B1E1801B9320590E2FE4B7555 +:1012C000F7595BC3B080BA00010A061A01EEC39059 +:1012D000B040EBF2B0C0EBEEB000EBEAFA60061EF5 +:1012E000162BDB8EDB2EA1BA4C2EA3924CA09312B0 +:1012F000988BE889262D7A803ECA13007403E96B27 +:1013000042E8C0FFE8ABFFE8A8FFB020C606901295 +:1013100000FF167C128BFD83FF0A7211E8B9FFE80B +:1013200090FFE8ABFFE88AFF83EF0AEBEA0BFF745C +:101330000FE8A4FFE87BFFE89AFFE875FF4F75F11F +:10134000E895FFE86CFFEBB98A86A50024FDEE88DE +:1013500086A500C38A86A6000C02EEC38B7638F7FA +:10136000C6010074EF8B4E368B462E3BC173028B49 +:10137000C82BC189462E014E34C47E0426010D8B34 +:101380007E2C83EA04F36C8EC1897E2C3B463C7232 +:1013900012F7C62000750B83CE20897638B000E89E +:1013A000A0FCC3F7C60400741B8BD883CE108976CB +:1013B000388A86A70024FE8886A70083C208EE83A9 +:1013C000EA088BC33D40007201C3814E380004839C +:1013D000C2028A86A50024FA8886A500EEC38A8602 +:1013E000A6000C02EEC3F74638010074F18B4E2EB6 +:1013F00032DB8ABEA30083C206C476048B7E2C83B4 +:10140000F908722CECA80174168AE083EA0AEC83CE +:10141000C20A84E77551AAFEC34983F90873E5320D +:10142000FF26011C015E34897604894E2E897E2CAC +:101430003B4E3C7211F64638207401C3834E38206F +:10144000B000E8FDFBC3F64638047415834E38102F +:101450008A86A70024FE8886A70083EA02EE83C25C +:10146000023D4000725DC332FF26031C85DB740918 +:1014700026891C8BF74747494980E41E80CCC0264B +:101480008904F6C41074278B7638F7C60010740BE5 +:1014900050FE86B200B00AE8A8FB58F7C6000174F7 +:1014A0000DE882268B76388B4E2E8B7E04AB8BF725 +:1014B00033C0AB32DB8ABEA300494983F9087217F7 +:1014C000E941FF814E38000483C2F88A86A50024D2 +:1014D000FA8886A500EEC3E945FF83C208EC88863A +:1014E000AA00C0E8048AE08AC88686A90032E08B98 +:1014F0005E3E84E3744F8AC18B4E26F6C504740C9D +:10150000A808740580E1BFEB0380C940F6C50874E4 +:101510000CA802740580E17FEB0380C980884E2609 +:101520008BF08A86A50084C97408A802741524FD6E +:10153000EB06A802750D0C028886A50083EA0AEE68 +:1015400083C20A8BC684E77501C3C686BA0001B0A0 +:101550000EE8EEFAF74638000274EE837E2E06722D +:10156000E88AA6AA00C45E048B7E2CB0FFAAB00253 +:10157000AB26830703836E2E03897E2CF646382024 +:101580007401C3834E3820B000E8B6FAC39083EAF2 +:1015900008E9B4FD83C2068B5E26F6C3C075EF8BE7 +:1015A0004E1CEC8886A40083EA0AA82075028ACD26 +:1015B00032ED8B461A3BC87318014E2A2BC189465F +:1015C0001AC57600F36E8ED98976003D2000723000 +:1015D000C385C074318BC801462AC57600F36E8E70 +:1015E000D980CB02895E26E832F1F6C701751683F1 +:1015F000C202E853FDF6C710750BB002E843FAC308 +:10160000F6C70174F0C380CB02895E26F6C7017469 +:10161000DE83C202E831FDF686A40040740B80E749 +:10162000FE80CF02895E26EBCCB004E814FAC3C07A +:10163000C2C8CAC4C6CCCED0D2D8DAD4D6DCDE90EA +:10164000E90E01E4C48AE0E4C48BD083F90872F0A7 +:1016500026833F0074048BDF49498BFB8ADE83E3DA +:101660000F2E8AA72F16ABF6C4107424F7C60010ED +:10167000740B50FE86B200B00AE8C6F958F7C600EF +:1016800001740DE8A0248B76388B4E2E8B7E04AB34 +:10169000897E0433C0AB4949894E2E897E2C8BC18B +:1016A000EB4E90EB9E90E4D684C07963E6D08AC876 +:1016B00025030003D8D1E32E8BAF4400888EAE0003 +:1016C0008B4E2EC45E048B7E2C8B7638E4862407EA +:1016D0003C0375CFE41C913BC173028BC82BC189BD +:1016E000462E014E3426010FBAC400F36C897E2CBD +:1016F0003B463C721CF7C62000750B83CE208976D2 +:1017000038B000E83CF98A86AE00243FE6D6C3F93B +:10171000C3F7C60A007435F7C61000752F83CE10C4 +:10172000897638F7C60200740E50E4D824FEE6D855 +:1017300058F7C6080074155051B9E803E40A84C08C +:10174000E0FA84C07504B024E60A59583D4000739D +:10175000B58A86A50024EF8886A500E60C81CE1008 +:1017600004897638EBA00008040C0109050D020A73 +:10177000060E030B070F004080C02060A0E0105051 +:1017800090D03070B0F0E4D2E6D08AC825030003D0 +:10179000D8D1E32E8BAF4400888EAE00E4D8C0E8E9 +:1017A000048BD82E8A8766178AE08AC88686A900A5 +:1017B00032E0E4988B5E3E84E374548AC18B4E26FB +:1017C000F6C504740CA808740580E1BFEB0380C95A +:1017D00040F6C508740CA802740580E17FEB038015 +:1017E000C980884E268BF08A86A500F6C1FD740854 +:1017F000A806741924F9EB0FA8067511F6C5017532 +:10180000040C04EB020C028886A500E60C8BC6844F +:10181000E775098A86AE00243FE6D2C3C686BA00C1 +:1018200001B00EE81CF8F74638000274E6837E2EFD +:101830000672E08A86A9008AE08686AA008AC832F3 +:10184000C480C90B22C1C0E4040AE0C45E048B7EDC +:101850002CB0FFAAB002AB26830703836E2E038948 +:101860007E2CF646382075AB834E3820B000E8D188 +:10187000F7EBA090E41224DFE61281E3FE9F895E7D +:1018800026836648F7EB7390F6C72075E7E4120CE1 +:1018900020E61232C0E6C6B083E6C680CF20895E5D +:1018A000268A86A5000C028886A500E60CEB7490BB +:1018B000F6C74075D3E4120C20E61232C0E6C6B07B +:1018C00081E6C680E7DF80CB01895E26B006E8713D +:1018D000F7908A86A50024F9E60C8886A500EB43DC +:1018E000E4D4E6D08BF825030003D8D1E32E8BAFE8 +:1018F00044008B5E26F6C76075B6F6C3C075D3BAD2 +:10190000C6008B4E1C8B461A3BC8731E014E2A2BF9 +:10191000C189461AC57600F36E8ED98976003D20BE +:1019200000723D8BC7243FE6D4C385C074398BC891 +:1019300001462AC57600F36E8ED983CB02895E26D6 +:10194000E8D9EDF6C70175398A86A50024F9E60CB9 +:101950008886A500F6C71075CAB002E8E4F6EBC3A6 +:10196000F6C70174EFEBBCF6C70174DC8A86A500EC +:10197000A802741181E3FFFE81CB0002895E26EB91 +:10198000C78A86A50024FB0C02E60C8886A500EB1E +:101990009290FDF7DF7FFEFBEFBF0004000405041B +:1019A00005040104000405040504060406040504F6 +:1019B00005040604060405040504020400040504E5 +:1019C00005040104000405040504060406040504D6 +:1019D00005040604060405040504070407040504B9 +:1019E00005040704070405040504060406040504A9 +:1019F0000504060406040504050407040704050499 +:101A00000504070407040504050406040604050488 +:101A10000504060406040504050403040004050483 +:101A20000504010400040504050406040604050475 +:101A30000504060406040504050402040004050464 +:101A40000504010400040504050406040604050455 +:101A50000504060406040504050407040704050438 +:101A60000504070407040504050406040604050428 +:101A70000504060406040504050407040704050418 +:101A80000504070407040504050406040604050408 +:101A90000504060406040504050433DB8AD88A8796 +:101AA0006C12E6FEC1E302E4CEA8047509A8027434 +:101AB00003E92CFEF9C35053E8CBFC5B58A8027431 +:101AC00003E91CFEF8C333DB8AD88A876C12E6FE72 +:101AD000C1E302E9D0FB9A1AC61A00000200040012 +:101AE00002000600020004000200080002000400D8 +:101AF000020006000200040002000A0002000400C6 +:101B000002000600020004000200080002000400B7 +:101B1000020006000200040002000C0002000400A3 +:101B20000200060002000400020008000200040097 +:101B3000020006000200040002000A000200040085 +:101B40000200060002000400020008000200040077 +:101B5000020006000200040002000E000200040061 +:101B60000200060002000400020008000200040057 +:101B7000020006000200040002000A000200040045 +:101B80000200060002000400020008000200040037 +:101B9000020006000200040002000C000200040023 +:101BA0000200060002000400020008000200040017 +:101BB000020006000200040002000A000200040005 +:101BC00002000600020004000200080002000400F7 +:101BD00002000600020004000200C390DA1494150B +:101BE0005C13E613DA1BDA1BE613DA1B8B94641220 +:101BF000C1E604A80174355033C08AC2E6FEE4A0F1 +:101C000085C074278BD82E8A9FDA1A52562E8BA83D +:101C100044008B5628ECA801750D8886AD00240E73 +:101C20008AD82EFF97DC1B5E5AEBCD58A80274367B +:101C300083C61033C08AC6E6FEE4A085C074278B35 +:101C4000D82E8A9FDA1A52562E8BA844008B56281B +:101C5000ECA801750D8886AD00240E8AD82EFF975A +:101C6000DC1B5E5AEBCDC39032E48BD88BD02E8A2E +:101C70009F9A192E2297921956528AC3240303C69B +:101C800080E304D0EB2EFF97D61A585EA955007555 +:101C9000D9C3601E062BC08ED8A15C12E6FEE400FC +:101CA00022C4740833F6E8BFFFEBEE90E40407E4C7 +:101CB000041FB80080BA22FFEF61CF90601E062B90 +:101CC000C08ED8A15E12E6FEE40022C47408BE04F1 +:101CD00000E894FFEBEDE40407E4041FB80080BAC9 +:101CE00022FFEF61CF90601E062BC08ED8A15C1240 +:101CF000E6FEE40022C4741833F6E86BFFA160121C +:101D0000E6FEE40022C474E5BE0800E85AFFEBDDFD +:101D1000A16012E6FEE40022C475EDE40407E404C9 +:101D2000A15C12E6FEE4041FE404B80080BA22FFBE +:101D3000EF61CF90601E062BC08ED8A15E12E6FE2A +:101D4000E40022C47419BE0400E81CFFA16212E67C +:101D5000FEE40022C474E4BE0C00E80BFFEBDCA13F +:101D60006212E6FEE40022C475EDE40407E404A177 +:101D70005E12E6FEE4041FE404B80080BA22FFEF1E +:101D800061CF601E062BC08ED8A15C12E6FEE480F7 +:101D900084C4740833F6E853FEEBEE90B80080BAC2 +:101DA00022FFEF071F61CF90601E062BC08ED8A1C7 +:101DB0005E12E6FEE48084C47408BE0200E82CFED5 +:101DC000EBEDB80080BA22FFEF071F61CF90601ED5 +:101DD000062BC08ED8A16012E6FEE48084C474088D +:101DE000BE0400E806FEEBEDB80080BA22FFEF0764 +:101DF0001F61CF90601E062BC08ED8A16212E6FE36 +:101E0000E48084C47408BE0600E8E0FDEBEDB80091 +:101E100080BA22FFEF071F61CF90601E062BC08E95 +:101E2000D8A15C12E6FEE40022C4741833F6E83749 +:101E3000FEA16012E6FEE48084C474E5BE0400E8FE +:101E4000AAFDEBDDA16012E6FEE48084C475EDA17D +:101E50005C12E6FEE40407E4041FB80080BA22FF27 +:101E6000EF61CF90601E062BC08ED8A15E12E6FEF9 +:101E7000E40022C47419BE0400E8ECFDA16212E67D +:101E8000FEE48084C474E4BE0600E85FFDEBDCA1E0 +:101E90006212E6FEE48084C475EDA15E12E6FEE403 +:101EA0000407E4041FB80080BA22FFEF61CF601E70 +:101EB000062BC08ED8A15C12E6FEE48084C47418A0 +:101EC00033F6E827FDA16012E6FEE40022C474E5C3 +:101ED000BE0800E892FDEBDDA16012E6FEE4002200 +:101EE000C475EDE40407E4041FB80080BA22FFEFD4 +:101EF00061CF601E062BC08ED8A15E12E6FEE48084 +:101F000084C47419BE0200E8E2FCA16212E6FEE499 +:101F10000022C474E4BE0C00E84DFDEBDCA16212AB +:101F2000E6FEE40022C475EDE40407E4041FB800F3 +:101F300080BA22FFEF61CF90601E062BC08ED8A121 +:101F40005C12E6FEE48084C4741833F6E89DFCA1BC +:101F50006012E6FEE48084C474E5BE0400E88CFCF4 +:101F6000EBDDA16012E6FEE48084C475ED071FB8C6 +:101F70000080BA22FFEF61CF601E062BC08ED8A171 +:101F80005E12E6FEE48084C47419BE0200E85CFCC4 +:101F9000A16212E6FEE48084C474E4BE0600E84B4D +:101FA000FCEBDCA16212E6FEE48084C475ED071F41 +:101FB000B80080BA22FFEF61CF90601E062BC08E62 +:101FC000D8902AC0E6FEE4CEA801741433DBE8D52D +:101FD000F6EBEF90B80080BA22FFEF071F61CF90B9 +:101FE000F60605010175EDB001E6FEE4CEA8017428 +:101FF000E3BB0400E8AFF6EBC990601E062BC08E71 +:10200000D890FB90FA2AC0E6FEE4CEA802741333FF +:10201000DBE8CCF8EBECB80080BA22FFEF071F61D9 +:10202000CF90A80474F033DBE85BF7EBD590601E2B +:10203000062BC08ED890FB90FAB001E6FEE4CEA845 +:10204000027415BB0400E897F8EBEB90B80080BA77 +:1020500022FFEF071F61CF90A80474F0BB0400E8D3 +:1020600024F7EBD26A001FC6069312099C0EE86B98 +:10207000F2906A001FC6069312299C0EE85DF2904A +:10208000722072207220CE1D921CE61C1A1E722035 +:10209000821DAE1E381F7220821D72207220381FD2 +:1020A000722072207220F41DBC1C341D641E72202C +:1020B000A81DF21E781F7220A81D72207220781FA2 +:1020C000FCB940008CCBB864202BFFAB93AB93E200 +:1020D000FAC7064C00A811833E4412007520C706BB +:1020E0003C00084BC7063000BA1FC7063400FA1F71 +:1020F000F6060501017506C70638002E20C3C7067F +:102100003C00564B33DB8A1E5412C1E302021E56BA +:10211000122E8B878020A330008A1E5512C1E30245 +:10212000021E57122E8B87A020A33400C38B869EDD +:1021300000E6FE86C4E6D0C38B869E00E6FE33D260 +:102140008AD4C351B91027E40A909084C07405E280 +:10215000F659F9C359F8C384C0781E518AE88AC871 +:10216000B80100D3E0098698003AAEA00059751076 +:10217000E8A9E5834E2602F9C39889869800EBF01A +:10218000F8C384C07812518AE08AC8B80100D3E04D +:1021900059F7D021869800C3C78698000000C383F2 +:1021A000C2048A86A6000C04EE83EA04C3E893FF07 +:1021B0007204B082E60AC38B4626A8FD74118A8693 +:1021C000A500A806740824F98886A500E60CC3F6C5 +:1021D000C401740A8A86A50024FB0C02EB0CA80239 +:1021E000750F8A86A50024FD0C043A86A50075D8D3 +:1021F000C38A86A500EBCFE4D833DB8AD8C0EB04D2 +:102200002E8A9F6617889EA9008B5E2680E33FF684 +:10221000C7047407A810750380CB40F6C70874077D +:10222000A880750380CB40885E268A86A500F6C309 +:10223000FD740DA806740824F98886A500E60CC371 +:10224000F6C70174040C02EBF0F6C30275E90C0446 +:10225000EBE7C404C4048504590448044104C303DF +:10226000820341038202570241028201410182003E +:1022700041004E02AD0157012D002B002700210027 +:102280001600F404F404A3046F045B045104F40383 +:10229000A3035103A3026D025102A3015101A30044 +:1022A00051006202D9016D01380036003100290069 +:1022B0001B005157BF0200EB0F905156BF0100EBBE +:1022C00007905156BF0300903C197602B017988BC7 +:1022D000F08A82C4002AE48BF083FE187346D1E6AC +:1022E0002E8B8C5222F74638800074052E8B8C8200 +:1022F00022F7C7020074123B8E9400740C898E94EE +:10230000008AC5E6EC8AC1E6E4F7C7010074123B17 +:102310008E9600740C898E96008AC5E6F88AC1E60E +:10232000F05E59C377068B8E8E00EBC58B8E9000C6 +:10233000EBBFD503F6003E0010000400CA043301D1 +:102340004D00140005000103050709000102030404 +:1023500080841E00A02526000000608BF033FF2E35 +:10236000A150232E8B165223BB3223F74638800010 +:10237000740C2EA154232E8B165623BB3C23B90577 +:10238000002E3B31730A4747E2F7B8FFFFEB1D9081 +:10239000D1EF2E8A8D46232AEDD1EAD1D8E2FAF781 +:1023A000F6050200C1E8022E8AA54B232EA358236E +:1023B000612EA15823C3080020008000000260099C +:1023C0000800200080000002000800000100020058 +:1023D0000300040052565785C074053D0109760379 +:1023E000B80109BF5B01F7463880007403BFB20132 +:1023F00033F62E3B84B62376044646EBF5F7E72EFC +:102400008BBCC02303C783D200D1E7F7F72E8AA481 +:10241000CA235F5E5AC3E43E80BEC30003750CF757 +:10242000467A200074050C80E63EC3247FE63EC356 +:1024300024038886C3008AE0E41024FC0AC4E61062 +:10244000808EA10042E8CEFFC390568BF083E60752 +:10245000D1E62EFFA458249068246C2470247424A0 +:102460007824872487248724B400EB0EB4C0EB0AB9 +:10247000B440EB06B420EB02B4A0E410241F0AC45D +:10248000E610808EA100425EC3903C0277128AE083 +:10249000E41024F3C0E4020AC4E610808EA10042D6 +:1024A000C3908B5E3884C0741F3C02742083CB08B9 +:1024B0008B462E3B463C770CE888FC7207B024E63E +:1024C0000A83CB10895E38C383E3F7EBF7F7C310B9 +:1024D0000074F5E86DFC72EC8A86C000E638B02323 +:1024E000E60AEBE08B5E388B462E3B463CE4D87721 +:1024F0000B24FE80CB12E6D8895E38C30C0180CB5A +:1025000002EBF35033DBC1E804250F0F8AD82E8A83 +:102510008766178ADC2E8AA7661709463E58C3507D +:1025200033DBC1E804250F0F8AD82E8A8766178A05 +:10253000DC2E8AA76617F7D021463E58C38B463E4D +:1025400033DB8AD80ADC2E8A877617E62C8AE0E409 +:102550002A240F0AC4E62A8A86A50084E4750DA8F9 +:10256000807411247F8886A500E60CC3A8807504BA +:102570000C80EBF1C31E6033C933D233F68ED98D94 +:10258000BEFD00578B0584C074168BD1428BFE4F65 +:10259000780938A3E40074084F79F788A2E400466C +:1025A0005F83C7094183F91072D989B6860089967D +:1025B0008400611FC353C7466600008B4664A94070 +:1025C00000740DB300A980007402B37F889EC1001F +:1025D00032DBA90200740380CB40A9004074038061 +:1025E000CB02A90080740380CB01A9301E74038044 +:1025F000CBBCA90020740380CB08A904017403801C +:10260000CB10A90800740380CB20889EC2005BC356 +:102610000651575016078DBEC400B91F0033C0AA1B +:1026200040E2FC8B86920089868E00898690005855 +:102630005F5907C3E4D8C0E80453250F008BD82E98 +:102640008A8766178886A9005AC30886AC00C686A2 +:10265000BA0001B00EE8EAE9C3AD36A3B413AD3653 +:10266000A3B613AD36A3B81383E90636F706B6133F +:102670000F00C38A4626F74648800074020C108873 +:1026800086BD0032C0837E1A00750E8B5E4043808B +:10269000E3FE3B5E0875020C01837E3A00750D1E59 +:1026A000C55E148B1F1F85DB75020C02F7463810C0 +:1026B0000074020C048B5E7AF7C3020074020C08EB +:1026C000F7C3040074020C10F7C3080074020C2056 +:1026D000F7C3400074020C408886BF00C3906A00B4 +:1026E0001FC60693120D9C0EE8F1EB90B002E6DADD +:1026F000F8C333C0E6DAF8C3B001E6D8F8C333C094 +:10270000E6D8F8C3B0FFE84EFAE8A1FAF8C3AC493E +:10271000E8AFFBF8C390AC49E815FDF8C390AC49AD +:10272000E867FDF8C390AC49E81FFDF8C390AC49D9 +:10273000E634F8C3AC49E636F8C3AC493C02771F2F +:1027400084C0751DE41424EFE614E412243FE6125D +:10275000E416A8047409E8EAF97204B018E60AF865 +:10276000C38AE0E4140C10E614E4120CC0F6C401B1 +:102770007402247FE612F8C3AC49E825FDF8C39043 +:10278000B80040E87DFDE8B4FDE8A8FEB001E8B976 +:10279000FEF8C390B80040E885FDE8A0FDF8C390BE +:1027A000B80010E85DFDE894FDE888FEB008E899FF +:1027B000FEF8C390B80010E865FDE880FDF8C3900E +:1027C000B80080E83DFDE874FDE868FEB002E879F5 +:1027D000FEF8C390B80080E845FDE860FDF8C390BE +:1027E000B80020E81DFDE854FDE848FEB004E859B3 +:1027F000FEF8C390B80020E825FDE840FDF8C3903E +:10280000AC49E84814E43C24E70AC4E63CF8C39029 +:10281000B8FC3B89467CE43C0C18E63CF8C3E41267 +:102820000C02E612F8C3E41224FDEBF6E8B5FCF85E +:10283000C390836638FDF8C3AC49A8017406834E83 +:102840007A20EB0483667ADFE8CBFBF8C3908A86B4 +:10285000A5000C0224FB8886A500E60C814E26010B +:1028600020AC4932E489466E834E48084946F9C394 +:102870008A86A5000C0224FB8886A500E60C814E02 +:10288000260120ACB40AF6E4EBD8E8FA13E43C24C1 +:10289000F80AC4E63CF8C390AD4949894664A901E9 +:1028A00000741B8BD883E3FA751AA90400740FE433 +:1028B0003E0C02E63EB83844894662F8C390E43ED6 +:1028C00024FCEBEFE43E24FCE63EE8E8FCB8AA403A +:1028D000EBE6E86EF87205B018E60AF8C390AC496A +:1028E000E8CFF9F8C390AC49E8CFF9F8C390E868AD +:1028F000FD750632C0E6DAF8C3B002E6DA36A0B4F7 +:102900001324103410E8160136A1B413A901007481 +:1029100005E8FCFEEB0EA90200740432C0EB02B025 +:1029200001E8DEFE36A1B413E8B513E43C24F80A4E +:10293000C4E63C36A1B413C1E805250100E8FAFE5F +:1029400036A0B5132410E859FB32C0368A26B513D9 +:10295000F6C4047409FEC0F6C4087402FEC0E8DBC5 +:10296000FD36A1B613250F00E857F936A1B613C1FD +:10297000E804250300E8B8FA36A1B613C1E8052536 +:102980000200E805FB36A1B613F6C401750432C097 +:10299000EB0980E402D0ECB0022AC4E8ACFA36F6C7 +:1029A00006B713407405E883FEEB03E884FE36F6B1 +:1029B00006B713207405E865FEEB03E868FEF8C36C +:1029C000E4120C01E612F8C3E41224FEEBF6E41460 +:1029D00024F00C05E614E42A24F00C06E62AF8C3D9 +:1029E000E42A24F0E62AE41424F00C07E614F8C3E1 +:1029F000AD4949E864F989868E00F8C3AD4949E8D4 +:102A000058F989869000F8C3834E2604E8A8F7F8A1 +:102A1000C390836626FBE89EF7F8C390AC4984C058 +:102A2000750DE41024EFE610808EA10042F8C3E497 +:102A3000100C10EBF190AC493C02760232C0C0E0C1 +:102A400004A82074020C0824188AE0E41224E70A7F +:102A5000C4E612808EA10044F8C3AC498886C00049 +:102A6000F8C3AC49E63AF8C3AC4984C07408E41230 +:102A70000C04E612F8C3E41224FBEBF6AC49E8D6EA +:102A8000F67303E827F7F8C3E412A802740424FDE0 +:102A9000E612B8F000E887FA816626FFF3E857F7F8 +:102AA000E89AFAF8C390B88000E857FA804E2708F1 +:102AB000E844F7E887FAF8C3B88000E861FA81666D +:102AC00026FFF7E831F7E874FAF8C390B81000E889 +:102AD00031FA804E2704E81EF7E861FAF8C3B8100F +:102AE00000E83BFA816626FFFBE80BF7E84EFAF8B0 +:102AF000C39033C0AC493C017304B001EB063C0CFD +:102B00007602B00C89461CF8C390814E2600208ABC +:102B100086A5000C0224FB8886A500E60C834E26C1 +:102B200001F8C390814E2600408A86A5000C0288D9 +:102B300086A500E60CF8C390AC4950E805F658723B +:102B400008E638B023E60AF8C3F9C390AC50ADE804 +:102B500082F85AF6C201741239869600740C89867E +:102B60009600E6F086E0E6F886E0F6C202741039D8 +:102B7000869400740A89869400E6E486E0E6EC8395 +:102B8000E903C390E4168886BC00E8E6FA33DBE488 +:102B90000CA806740380CB01A810740380CB02A894 +:102BA00080740380CB04E4128AE024180AD8E4DAA3 +:102BB000F6C4027407A840750380CB20A8027509EB +:102BC000E42AA80F740380CB40F74638020074094A +:102BD000E4D8A801750380CB80889EBE00FE86B431 +:102BE00000B00AE85CE4F8C3AC493C027441771FCA +:102BF00050E84FF558720C84C0740AB012E60A808F +:102C00004E3801F8C3B011E60A806638FEF8C38B6F +:102C1000463825FFF7894638A9000475E68A86A557 +:102C200000A81075DE0C108886A500E60CF8C3819C +:102C30004E3800088A86A500A81074C724EFEBE779 +:102C4000AD49493C0172113C0C770D508AE0E41407 +:102C500025F00F0AC4E614588AC484C07402E64200 +:102C6000F8C3E8CFF9FE86B900B00EE8D4E3F8C3A4 +:102C70003A86AF00741F8886AF008AE080C206B033 +:102C8000BFEE80EA028AC4EE8A86A80080C202EE05 +:102C900080EA068AC4C38B463E85C08A86A5007436 +:102CA00012A808750D0C088886A50080C202EE8067 +:102CB000EA02C3A80874FB24F7EBEC8B462684C019 +:102CC00074168A86A500A802740D24FD8886A500C6 +:102CD00083C202EE83EA02C38A86A500A80275F7C2 +:102CE0000C02EBE85283C20CECC0E8048886A90011 +:102CF0008B5E2680E33FF6C7047407A8087503803F +:102D0000CB40F6C7087407A802750380CB80885EA5 +:102D1000268A86A50084DB7410A802740A24FD8824 +:102D200086A50083EA0AEE5AC3A80275FA0C02EBE4 +:102D3000EE90FFFF00480030BA20C41A00180012BD +:102D4000000C0006000300028001C000600030009B +:102D50001800CD0100018000100010000E000C00D2 +:102D6000080000000000060004000300020001004B +:102D70005251563C1E7747988BF08A82C40032E449 +:102D800083FE18743D83FE19743E83FE1E772FD197 +:102D9000E62E8B8C322D3B8E94007422898E94000B +:102DA00083C2068A86A8008AE00C80EE83EA068A3F +:102DB000C1EE83C2028AC5EE83C2048AC4EE5E59A4 +:102DC0005AC38B8E8E00EBCE8B8E9000EBC8525187 +:102DD0003D05007703B805008BC8BA0200B800D0E3 +:102DE000F7F1050100D1E8595AC38B467AA820743F +:102DF0000B80BEC3000375040C01EB0224FE894660 +:102E00007AC324038886C3008AA6A8008ADC80E4EB +:102E1000FC0AC43AC3740B8886A80083C206EE83FA +:102E2000EA06E8C5FFC30008183828903C04772359 +:102E300032E48BD82E8A87262E8AA6A8008ADC80C8 +:102E4000E4C70AC43AC3740B8886A80083C206EE9E +:102E500083EA06C384C07402B0048AA6A8008ADC90 +:102E600080E4FB0AC43AC3740B8886A80083C206B8 +:102E7000EE83EA06C3908B5E3884C074343C0274DF +:102E80003B8A86AF000C04E8E6FD8B462E3B463CB1 +:102E9000771BF7C30004751581CB000483C2028A37 +:102EA00086A50024FA8886A500EE83EA02895E38AA +:102EB000C38A86AF0024FBE8B6FDEBF1F7C3100030 +:102EC00074EFEBED83C20CEC83EA0CC0E804888657 +:102ED000A900C3908A86A7000C018886A7008BDA18 +:102EE00080C208EE8BD3F8C38A86A70024FEEBEAE3 +:102EF0008A86A7000C02EBE28A86A70024FDEBDAA3 +:102F0000B0FFE852F2E897F2F8C3AC49E861FEF886 +:102F1000C390AC49E8EBFEF8C390AC49E835FFF844 +:102F2000C390AC49E805FFF8C3905283C206B0BF16 +:102F3000EE5283C202AC49EE5A8A86A800EE5AF8D5 +:102F4000C3905283C206B0BFEE5283C206EBE69036 +:102F5000AC493C02770D84C0750B8A86AF0024FD16 +:102F6000E80DFDF8C3508A86AF000C02E801FD5B56 +:102F700083C2088A86A700F6C301740C24DF888602 +:102F8000A700EE83EA08F8C30C20EBF2AC49E8E5B1 +:102F9000FEF8C390B80040E869F5E8F9FCE824FFC2 +:102FA000B001E8A5F6F8C390B80040E871F5E8E58F +:102FB000FCF8C390B80010E849F5E8D9FCE804FF34 +:102FC000B008E885F6F8C390B80010E851F5E8C5F8 +:102FD000FCF8C390B80080E829F5E8B9FCE8E4FE05 +:102FE000B002E865F6F8C390B80080E831F5E8A5CE +:102FF000FCF8C390B80020E809F5E899FCE8C4FEA5 +:10300000B004E845F6F8C390B80020E811F5E8856B +:10301000FCF8C390AC49E8340CF8C390B8FC3B8989 +:10302000467CF8C38A86AF000C80E843FCF8C39066 +:103030008A86AF00247FEBF28A86AF000C40E82F2F +:10304000FCF8C3908A86AF0024BFEBF2AC49A8011C +:103050007407834E7A20EB059083667ADFE88AFD59 +:10306000F8C383C2068A86A8000C408886A800EEB2 +:1030700083EA06AC4932E489466E834E2601834ECC +:103080004808B006E8BBDF4946F9C39083C2068A08 +:1030900086A8000C408886A800EE83EA06ACB40A35 +:1030A000F6E4EBD0E8E00BF8C390AD4949894664FB +:1030B000A9010074198BD883E3FA750AA904007476 +:1030C0000DB8E23FEB0BE8ECF4B8AA40EB03B838DC +:1030D00044894662F8C38A86AF00A802740A24FDB8 +:1030E000E88DFB0C02E888FBF8C3AC49E881FCF8EA +:1030F000C390AC49E879FCF8C390E85CF57505E845 +:10310000E6FDF8C3E8CDFD36A0B41324103410E872 +:10311000260136A1B413A901007405E8FEFEEB0EEA +:10312000A90200740432C0EB02B001E8E8FE36A147 +:10313000B413E8AB0B36A1B413C1E805250100E8D0 +:103140000CFF36A0B5132410E82BFD32C0368A26BA +:10315000B513F6C4047409FEC0F6C4087402FEC0B8 +:10316000E8EFFD36A1B613250F00E803FC36A1B643 +:1031700013C1E804250300E888FC36A1B613C1E8B2 +:1031800005250200E8CDFC36A1B613F6C40175048E +:1031900032C0EB0980E402D0ECB0022AC4E88CFC17 +:1031A00036F606B713407405E88DFEEB03E894FE8F +:1031B00036F606B713207405E869FEEB03E870FEE7 +:1031C000F8C3F8C38B4638A9040075230D040089A1 +:1031D000463883C2088B462E3B463C7314834E38D8 +:1031E000108A86A70024FE8886A700EE83EA08F8E6 +:1031F000C38A86A7000C01EBEE908B4638A9040029 +:10320000740625FBFF894638F8C3AD4949E8BEFB83 +:1032100089868E00F8C3AD4949E8B2FB89869000E3 +:10322000F8C3834E2604E892FAF8C390836626FB1F +:10323000E888FAF8C390AC4984C07507808EA30073 +:1032400004F8C380A6A300FBF8C3AC4983C2083CC2 +:1032500002760232C03C017412770B8A86A70024E2 +:10326000EF8886A700EE83EA08F8C38A86A7000CD9 +:1032700010EBEE905283C206B0BFEE5283C204AC94 +:1032800049EE5A8A86A800EE5AF8C3905283C206C5 +:10329000B0BFEE5283C208EBE690AC49F8C3AC492C +:1032A000E8B4EE7303E8F7EEF8C38A86AF00247F34 +:1032B000E8BDF9B8F000E866F2816626FFF3E8237E +:1032C000FAE8D2F9F8C3B88000E837F2804E270850 +:1032D000E811FAE8C0F9F8C3B88000E841F2816665 +:1032E00026FFF7E8FEF9E8ADF9F8C390B81000E85A +:1032F00011F2804E2704E8EBF9E89AF9F8C3B81008 +:1033000000E8FFF1816626FFFBE8D8F9F8C3AC4975 +:10331000F8C383C2068A86A8000C408886A800EEFF +:1033200083EA06F8C39083C2068A86A80024BFEB0E +:10333000EA90AC498AE080C20AEC80EA0AA82074CC +:10334000058AC4EEF8C30651578B4E24E3344989ED +:103350004E24FF461A8E46028B7E228AC4AA897E9C +:10336000228B462624FD89462675298A86A500A833 +:1033700002752180C2020C028886A500EE80EA0256 +:10338000EB12C47E003B7E1E760A4F268825897E7E +:1033900000FF461A5F5907F8C390ACAD83E9038577 +:1033A000C074053D00207205B8FFFFEB03C1E003C8 +:1033B0003B8694007426898694008BD85283C2067B +:1033C0008A86A8008AE00C80EE83EA068AC3EE8330 +:1033D000C2028AC7EE83C2048AC4EE5AF8C3B08818 +:1033E0008886BC00E88CF233DB8A86A500A80274CC +:1033F0000380CB01A805740380CB02A80874038066 +:10340000CB04F686A70010740380CB108A86A9002F +:10341000F6C304750A83C20CEC83EA0CC0E8048A84 +:10342000E08A86AF00A8807408F6C401750380CBDB +:1034300020F686A70002750AF74638040074038058 +:10344000CB40889EBE00FE86B400B00AE8F3DBF8ED +:10345000C3FE86B400B00AE8E8DBF8C3AC493C021E +:103460007437771084C07406804E3801F8C38066C4 +:1034700038FEF8C38B463825FFF7894638A9000483 +:1034800075EA8A86A500A80175E20C0583C2028848 +:1034900086A500EE83EA02F8C3814E3800088A86CA +:1034A000A500A80174C624FAEBE2AD4949F8C3901F +:1034B000E811FAFE86B900B00EE886DBF8C3B0FF6B +:1034C000E8BFECF8C39083667AFBB000E873DBF8E2 +:1034D000C390AC49E853D9721136881E1A0136A040 +:1034E0008E120AC352BA0001EE5AF8C3AC4932E454 +:1034F00036A38612050600368B1E88122BD8368915 +:103500001E8A12F8C390AD8BD8AD83E90403C32B98 +:103510004676894678F7467A0200740A83667AFD11 +:10352000B80000E81CDBF8C3061607AC49250F00FD +:103530006BC0098DBEFD0003F8AC49250F00AA85BC +:10354000C074082BC8518BC8F3A459E827F0E8448D +:103550000307F8C333C0AC4936A3B21336A3B01384 +:10356000F8C383667AEFE82C03F8C390834E7A1091 +:10357000EBF4E89BF0F8C390AD3C19770E3C19775B +:103580000A8BF881E7FF0088A6C400F8C390834E39 +:103590002620AC4932E4D1E08BD8C1E30203C389D1 +:1035A000466E834E4804B006E897DA4946F9C39060 +:1035B000FE86B300B00AE889DAF8C39033C0AC499C +:1035C0006BC00A89868A00F8C390AC4932E43D0A90 +:1035D000007705B80A00EB083D5A007203B85A009C +:1035E00051F7D80564008BC88B4644F7E1B96400F5 +:1035F000F7F189464659F8C3AC49E885EBF8C39022 +:10360000AC4984C07507816638FFFDF8C3814E3828 +:103610000002F74638400075088A86A9008886AA05 +:1036200000F8C3905156E87F0C5E59F8C390FE86AF +:10363000B600B00AE80BDAF8C390FE86B700B00A0D +:10364000E8FFD9F8C390FE86B800B00AE8F3D9F8CD +:10365000C39000905155AC2EA2523633C9AD8BF9B0 +:10366000C1E705A9010074232E8BAD4400837E08B9 +:103670000074182E803E523601740960B004E8BB15 +:103680000C61EB0760B0FBE8EC0C614747D1E875D3 +:10369000D24183F90472C65D5983E905F746384083 +:1036A000007405E887EAF8C3E88DEAF8C39036C6E7 +:1036B00006C81301F8C333C0AC4936A38012AC4925 +:1036C000362B068812F7D836A38212F8C390DE266E +:1036D000DE26EC26F226F826FE2604270E271627DD +:1036E0001E2726272E273427BE34C634D2343A2745 +:1036F000782780279427A027B427C027D427E0273E +:10370000F42700281028EC34DE261E2826282C2832 +:10371000322838284E288A28063528359828BE2889 +:10372000D228DE28E628543562356C35EE28C029CB +:10373000C829CE29E02972357835F029FC298E3543 +:10374000082A122A1C2AB035362ABC355A2A622A7F +:10375000682ACA357C2AF835882AA62AB82ACC2AAB +:10376000DE2AF22A00360A2B242B2436382B4C2B47 +:10377000842B2E363A3646365436E82BAE36402C5D +:10378000622CB6367028DE26DE26D42EE82EF02EE9 +:10379000F82E002F0A2F122F1A2F222F2A2F422FF6 +:1037A000BE34C634D234502F8C2F942FA82FB42F70 +:1037B000C82FD42FE82FF42F083014301C30EC34ED +:1037C000DE2624303030383044304C306230A43083 +:1037D00006352835AA30CE30D630EA30F2305435AE +:1037E00062356C35FA30C231C231C431FA317235CA +:1037F00078350A3216328E3522322C323632B035D6 +:103800004A32BC3574328C329A32CA359E32F8351F +:10381000AA32C632D832EC32FE320E3300361233C0 +:103820002633243632339A33DE332E363A36463652 +:1038300054365C34AE36AA34B034B6368C30E32815 +:10384000F7463840007532E8E3E833C0AC493D5BE9 +:103850000077198BD8D1E32EFF97CE36720B85C92E +:1038600075E88B4648E81A0CC34E41C36A001FC670 +:103870000693120C9C0EE863DAE8BCE833C0AC494E +:103880003D5B0077E78BD8D1E32EFF97863772D95F +:1038900085C975E8C3F7467A1000750F83BE8400AA +:1038A000007408B8483A89868000C381BE8000EC65 +:1038B0003C74F783BE8800007505B8EC3CEBE7F775 +:1038C000467A080075401E608B8E88003B4E7477E8 +:1038D000333B4E78772EC47E108BDF26033D47475F +:1038E00033C08ED88DB6F4008BC1F7467A010075CF +:1038F0001DF3A4260107294678014676294674B0AF +:103900000CE83ED7611FC78688000000EBACE3E3FC +:103910005090AC247FAAE2FA58EBD8908B8E8800A6 +:10392000E3468B9E8A0085DB743EBA50FFED2B8602 +:1039300082003BC372378DB6F400C47E108BDF2645 +:10394000033D47478BC1161FF7467A01007524F3E4 +:10395000A4260107294678014676294674C7868839 +:10396000000000B00CE8DAD683667AF7C3B000E84E +:10397000D0D6C3E3DC50AC247FAAE2FA58EBD29055 +:103980001E6033C08ED88DB6FD008B8688008B9666 +:1039900084003A0475108BDE468BC88DBEF400F3AC +:1039A000A674668BF39083C6094A75E68DB6FD0052 +:1039B0008B9684003A0473108BDE468BC88DBEF460 +:1039C00000F3A674768BF39083C6094A75E68DB62C +:1039D000F400ACF7467A01007402247F1EC55E1025 +:1039E0008B37884002468937FF4E78FF4676FF4E78 +:1039F000741F8B8E880049898E8800E3438DB6F44E +:103A0000008BFE46F3A4E97DFFC576108B1C85DB99 +:103A1000740803F383C60383E6FE8B8684002BC2FF +:103A2000B48089044646C7040000897610834E7A24 +:103A300004C78688000000611FF9C333C0611FC33B +:103A4000B08084C0611FC3908B4E782B8E88007627 +:103A50002789B68C008B5E743BCB72028BCB3BC844 +:103A600072028BC88BC1E34433D28EC28BD183BE2A +:103A70008800007406E98E0033C0C38B5E10031FFC +:103A8000434352F7467A0100752AAC8DBEE4008BA1 +:103A90008E8600F2AE74348807434A75ED588B5E0B +:103AA0001001072946780146762946748BC62B8675 +:103AB0008C00C390AC8DBEE4008B8E8600F2AE7499 +:103AC0000A247F8807434A75EBEBD28886F400C747 +:103AD0008688000100582BC2740E8B5E10010729E6 +:103AE000467801467629467440E894FE72BE4A75CF +:103AF0001583BE8A000074B4BA50FFED8986820037 +:103B0000834E7A08EBA68DBEF40003BE8800A4FFA6 +:103B1000868800E86AFE729479064A748FE95BFF32 +:103B20004A74CEEBE19050E811CC8B467439467262 +:103B300074271E565133C9C5760CAD74107809032D +:103B4000C805010024FE03F03B761076ED294E7681 +:103B5000014E78E837CC595E1F58C390C47E1026BA +:103B60008B1D83C30326891D4B03FBAB91AAB803AE +:103B700000294678014676294674C390C47E1026F3 +:103B80008B1D4326891D4303FBAAFF4E78FF467613 +:103B9000FF4E74C3E8E5FFC38081848582838687F6 +:103BA00050538ADC83E30ED1EB2E8A87983B08863C +:103BB000B000FE86B100B00AE887D45B58C3508AD3 +:103BC000C8B8FF00E895FF58C3908A86BB00E8ABF1 +:103BD000FFC3E8CBFFE8F2FFC390E8C3FFE8B4FF00 +:103BE000C39033C0E895FFC3B8FF0033C9E86CFF4A +:103BF000C390B8FF01B110E862FFC390C3FC3BE281 +:103C00003BF23BF23BFC3BE23BE83BE83BFC3BE26C +:103C10003BE83BE83BFC3BE23BE23BE23B00100085 +:103C20000000100000001000000010000000100054 +:103C3000000010000000100000001000000008004C +:103C40000000080000000800000008000051538B2D +:103C50004E3881E1FFEEA804740481C900018AE0B6 +:103C600080E4032418D0E40AC433DB8AD82E8B877F +:103C7000FD3B89467C2E0B8F1D3C894E38D1EB2EA7 +:103C80008AA73D3C5B59C3AC493C01721D74203C82 +:103C900003722374283C08722B74303C20723774F2 +:103CA0003ABBDA3B32E4895E7EC3BBA03BEBF5BB9B +:103CB000943BB401EBF0BBFC3BB402EBE9BBE23B51 +:103CC000B403EBE2BBBE3BB404EBDBBBCA3BAC4989 +:103CD0008886BB00EBCEBBD23BEBF3BBFC3BEBC41B +:103CE000A9040075D1A9080075DAEBD18B5E748B3D +:103CF0004E783BCB72028BCB3BC872028BC88BC118 +:103D0000E32CC47E108BDF26033D4747F7467A013C +:103D100000751CF7C70100740249A4D1E9F3A5732B +:103D200001A4260107294678014676294674C35026 +:103D300053BB7F7FF7C70100740549AC22C3AAD1EA +:103D4000E9E31D9CAD23C3AB497414AD23C3AB4958 +:103D5000740DAD23C3AB497406AD23C3ABE2E59D3F +:103D60007304AC22C3AB5B58EBB8E8CEC98B5E38AA +:103D7000F7C310047501C3F7C340007405E8B8E346 +:103D8000EB03E8A8E3816638EFFBF6C310743CF65A +:103D9000C3027406E4D80C01E6D8F6C30474118398 +:103DA000C2088A86A7000C01EE8886A70083EA086D +:103DB000F6C308740FE88BE3720A8A86C000E638FF +:103DC000B023E60AF7C300047501C3F7C300087502 +:103DD000F98A86A500F6C340750DA81075EC0C1085 +:103DE0008886A500E60CC3A80175DF83C2020C0516 +:103DF000EE8886A500C3B000E847D2EB0FB002E81A +:103E0000900EEB08836638DF834E7A0233C08ED87B +:103E1000FAA0921240A292123C05721EC60692129D +:103E200000FBB001E86B0EFAA1260123062A01A8C7 +:103E3000017507E8E207E8610990B000E837D2FBB6 +:103E400085ED74B9FAF7467A460075C08B46783D21 +:103E50000A0072B08B4E7483F950729A836638DF11 +:103E6000C576148B463A85C07558AD85C0750FE888 +:103E7000F8FEF7467A08007493E8A0FAEB8E3B76DA +:103E8000047621B90200394E2E7705C7462E000070 +:103E9000568B762C897604C7040000464689762C1A +:103EA000294E2E5E85C07917F6C4107405FF567C26 +:103EB000EB03FF567E897614B00CE885D1EB86893A +:103EC000463AFF96800029463A897614B00CE8718C +:103ED000D1E971FF0000000000000000080410029A +:103EE00001200000000000000000000000000000B1 +:103EF00000000000808080808080808080808080C2 +:103F000080808080808080808080808080808080B1 +:103F100080808080808080808080808080808080A1 +:103F20008080808080808080808080808080808091 +:103F30008080808080C0C0C0C0C0C0C0C0C0C0C0C1 +:103F4000C0C0C0C0C0C0C0C0C0C0C0C0C0C0C080B1 +:103F500080808000808080808080808080808080E1 +:103F60008080808080808080808080808080808051 +:103F70008080808080808080808080808080808041 +:103F80008080808080808080808080808080808031 +:103F90008080808080808080808080808080808021 +:103FA0008080808080808080808080808080808011 +:103FB0008080808080808080808080808080808001 +:103FC00080808080808080808080808080808080F1 +:103FD000808080804E417841D041F44106421842B1 +:103FE000C3908E46028B7E22897E6C806627FD8B75 +:103FF000562483FA0472E983EA028BD93BCA76021B +:104000008BCAB00A57518BFEF2AE8BC1595F751E39 +:1040100050402BC874062BD12BD9F3A4594B4A4AD4 +:10402000B00DAAA43BCA76028BCAE313EBD42BD9FA +:10403000F7C601007402A449D1E9F3A57301A4896C +:104040007E222B7E6C297E24017E1A8BCB807E26DD +:10405000027405806626FDC360B0FDE8180361C3E5 +:10406000C390E87C0272F990834E26208B466A89C1 +:10407000466E8B46480D040025BFFF894648B006B2 +:10408000E8BFCFC3897E222B7E6C017E1A297E2455 +:10409000807E26027405836626FDC360B0FDE8D5E8 +:1040A0000261C3908ABEC200EB24F7464840007507 +:1040B000B18E46028B7E22897E6C8B562483EA0A5F +:1040C000789E03D7806627FD33C08ABEC200E3B462 +:1040D0003BFA77B0AC49932E8A87D43E9322DF75A2 +:1040E00017AAE3A03BFA779CAC49932E8A87D43E6B +:1040F0009322DF7503AAEBD6F6C37F7505FF4666EC +:10410000EBDFF6C340750C8BD883EB08D1E32EFFB1 +:10411000A7D43FFF46662C20EBC785C0742C894688 +:104120006A834E4840897E222B7E6C017E1A297E4E +:1041300024807E26027408836626FDE8A301C360FE +:10414000B0FDE8310261E89801C3E957FF908B5E4A +:10415000664B7803895E66AA8B5E64F7C3002075A0 +:1041600003E940FFF7C3400074088A86C100AAE94A +:1041700032FFB83200EBA3908B5E66895E6883C322 +:104180000880E3F8895E668B5E6481E3001881FB3A +:104190000018742DAA85DB7425F746644000751855 +:1041A00081FB0010740C8B46662B4668C1E004E965 +:1041B00068FFB86400E962FF8A86C100AAAAE9E341 +:1041C000FE518B4E662B4E68B020F3AA59E9D4FEFF +:1041D0008B5E66895E688B5E64F7C324007410C7CB +:1041E00046660000F7C304007405B00DAAB00AAA21 +:1041F000EB489090AAF7466400407406B8D007E9EF +:1042000018FFE99FFE90AAF7466400807406B8D0B4 +:1042100007E906FFE98DFE908B5E66895E6885DBA7 +:10422000750C8B5E64F7C310007406E976FE8B5E36 +:1042300064F7C308007427B00AAAF7C32000751FEB +:10424000F7C300017503E95BFEF7C340007506B8CC +:104250006400E9C5FE8A86C100AAAAE946FEAAC78B +:1042600046660000F7C3000674F1F7C340007419F6 +:104270008A86C10081E3000681FB00047206760293 +:10428000AAAAAAAAAAAAE91BFE81E3000681FB004A +:1042900004720E7606B89600E97FFEB86400E979EC +:1042A000FE8B4668E973FE90368B0EDA1283F93284 +:1042B000731D1E0633C08ED88EC08D764CBFDC12A7 +:1042C00003F9A5A5A583C106890EDA12071FC3B09D +:1042D00008E86ECDC390836648FEE893C4E8C8FF43 +:1042E000C3F6462702750F9CFA837E1A0074098074 +:1042F0004E27019DF9C3F8C35052F7463840007469 +:104300001DE834DE83C20AECA840752783EA088AD8 +:1043100086A5000C028886A500EE5A58EBD1E80C61 +:10432000DE8A86A50024FB0C028886A500E60C5ACE +:1043300058EBBC804E27025A589DF8C30846269C6D +:10434000FA8A8EA500F7463840007514F6C1067447 +:1043500023E8D9DD8AC124F98886A500E60C9DC32F +:10436000F6C102740FE8D0DD83C2028AC124FD8841 +:1043700086A500EE9DC38B5E2622C3884626740167 +:10438000C3806627FD9CFA8A8EA500F74638400058 +:104390007516F6C104750FE893DD8AC124FD0C047F +:1043A0008886A500E60C9DC3F6C10275F9E888DD94 +:1043B00083C20AECA820750E83EA088AC10C028821 +:1043C00086A500EE9DC383EA0A33C98A4E1C8B463C +:1043D0001A3BC8731B014E2A2BC189461A1EC5768B +:1043E00000F36E1F89760083C2028A86A500EBCD9A +:1043F00085C0741201462A8BC81EC57600F36E1F55 +:10440000897600894E1AF6C701752380CB02895E32 +:1044100026E808C383C2028A86A50024FDEE8886AA +:10442000A500F6C7107505B002E816CC9DC383C27F +:10443000028A86A500EB86908BD18B46243BC876FA +:10444000028BC82BD12BC18BD9E322806627FD8E2E +:1044500046028B7E22F7C601007402A449D1E9F31B +:10446000A57301A4897E22894624015E1A8BCA8025 +:104470007E26027405806626FDC360B0FDE8F6FE68 +:1044800061C350E40A84C0750A8686A10084C074A2 +:104490000AE60A580C20894648F9C35824DF8946A1 +:1044A00048F8C390FBB002E8E807FAE82E01FBB039 +:1044B00001E8DE07FAB002E8BCCBFB85ED74E5FA53 +:1044C0008E5E0AFB90FA8B46488B7640A88C75DE90 +:1044D000A820741A50E855DC58E8A6FF7310B00203 +:1044E000E85FCBEBC99025FF008BC8EB3690A801A5 +:1044F00075224683E6FE3B76087479AD8AFCB3F0FC +:1045000022FB3AFB74E03ABEA000742EE8D2FD73A1 +:1045100077EB9B908AE024FC8846488B4E4AF6C491 +:1045200002741DE8BBFD7286E813F3897640E393BD +:10453000834E4803894E4AE974FF25FF0F8BC890CC +:104540008B86980085C0741A518A8EA000C0E90439 +:10455000BA0100D3E25923C2740803F1897640E915 +:1045600061FFFF5662E3F5834E4801894E4A897622 +:1045700040E93AFF814E2600108B46503B46467775 +:1045800003E852FDE927FF9088BEA000EBAC0A06C5 +:1045900090128AE0BA0601B004EEEC84C07512B045 +:1045A00004EE8AC4EE32E4A8807406C706841200C2 +:1045B0000088269012C30A0690128AE0BA0601EC1F +:1045C000A80175EDBA08018AC4EE32E4A88074E14E +:1045D000C7068412000088269012C39036F706247E +:1045E0000101007530368B0EDA1280F936732633EE +:1045F000C08EC08ED8BFDC1203F9B008E877CA8538 +:10460000ED740E8D764CA5A5A580C10680F9367295 +:10461000E9890EDA12C3C390F7062601010075F688 +:104620008B0E201385C975EE33C08EC08ED8BF2483 +:1046300013B93600B00AE83DCA85ED7506E91201E6 +:10464000E90A0133DB8A464C8AA6B300FECC780E19 +:1046500088A6B3000ADCB40AAB83E90276E28AA634 +:10466000B200FECC780E88A6B2000ADCB408AB8398 +:10467000E90276CC8AA6B100FECC78188ABEB000DA +:10468000750488A6B00088A6B1000ADC8AE7AB836F +:10469000E90276AC8AA6B400FECC781F88A6B400E6 +:1046A0000ADCB40BAB8A86BC008AA6BD00AB8B8645 +:1046B000BE00AB83E90676888A464C8AA6B600FE21 +:1046C000CC781988A6B6000ADCB40CABE8DBCBAB1F +:1046D0008B462AAB83E90676748A464C8AA6B700D5 +:1046E000FECC781988A6B7000ADCB40DABE8BACBCB +:1046F000AB8B4634AB83E90676538A464C8AA6B820 +:1047000000FECC781988A6B8000ADCB40EABA15024 +:1047100012ABA15212AB83E90676328A464C8AA6C6 +:10472000B500FECC781888A6B5000ADCB40FAB8BB8 +:10473000869A00AB8B869C00AB83E906760F84DB00 +:104740007503E9EFFEB00AE8F8C8E9E7FEB00AE849 +:10475000F0C8F7D983C1368BC10D800086C4A3226F +:10476000134141890E2013C3A184122BC17211A3DE +:104770008412BE2213D1E9F36F90890E2013F8C37F +:10478000F9C3C381EF6A1374F98BC70D800086C427 +:10479000A368134747893E6613C3F7062A01010041 +:1047A00075E08B0E6613E30780F92077D54949330E +:1047B000C08EC08ED8BF6A138BF703F983C6343B13 +:1047C000FE77C0B00EE8AEC885ED74B78A464C8A55 +:1047D000B6B900FECE781588B6B9008AA6A90080C1 +:1047E000CCC0AB84F67405B00EE856C88AB6BA00E1 +:1047F000FECE78CB8A9EA9008ABEAB008A563F8A3D +:10480000F332F70AB6AC00C686AC000022F2744B55 +:10481000F6C608740FB402F6C3087502B403AB8081 +:10482000E6F77437F6C601740FB400F6C3017502DB +:10483000B401AB80E6FE7423F6C602740FB404F62E +:10484000C3027502B405AB80E6FD740FF6C60474AE +:104850000AB406F6C3047502B407ABC686BA0000F4 +:10486000889EAB00E958FF90A184122BC17211A35E +:104870008412BE6813D1E9F36F90890E6613F8C3F2 +:10488000F9C3A1841241412BC17223A384128BC1AD +:10489000484832E40C8086C4EF9090909090BEDC43 +:1048A000124949D1E9F36F90890EDA12F8C3F9C3BE +:1048B0008AC88A464CB40183EB06EF9090909090A2 +:1048C000B80100EF90909090908AC1EF90909090F6 +:1048D00090E99700E9AC0033C08ED8891E8412C3DA +:1048E000368B1E8412FB90FAB00CE889C785ED74F4 +:1048F000E6C5760C83FB1472DBFB90FAAD85C078BD +:10490000AF74E28BFE03F8368B0E86123BC1770242 +:104910008BC883EB043BD977028BCB33C08A464CE0 +:10492000EF90909090908BC1EF90909090904180FC +:10493000E1FE2BD951D1E9F36F90598BC74024FE8A +:104940003BC674272BFE4E4E538B5E103BF3721307 +:10495000031F83C30380E3FEC7070000836E740256 +:10496000895E105B893C89760CEB8989760C3976F7 +:104970001077817208833C007403E977FFE80DBE6D +:10498000E962FF36891E8412B00CE8B5C633C08ECA +:10499000D8C3A184123D10007277BA04013B068887 +:1049A000127506C7067E1200008B0EDA12E30BE8C2 +:1049B000D0FE7257C7067E12FF7F8B0E2013E30BCB +:1049C000E8A5FD7246C7067E12FF7F8B0E6613E3D5 +:1049D0000BE894FE7235C7067E12FF7FA12801A95D +:1049E00001007503E8F9FE803E8D1200751DA1845B +:1049F000123D200076153B0682127609A17E123BFD +:104A0000068012720C800E901280C3B080FF167C5C +:104A100012C3800E901240C36A001FC6069312177D +:104A20009C0EE8B7C86A001FC6069312209C0EE8C9 +:104A3000AAC86A001FC6069312169C0EE89DC8906D +:104A4000BA0601ECA82075CAFB90FABA0401ED90F1 +:104A5000909090903A06941277BE33DB8AD8D1E3D7 +:104A60002E8BAF4400C47E0885FF74B9F6C4C075B0 +:104A70005532C0C1E00280E4F08BF0ED9090909050 +:104A80009085C074BB8BC84180E1FE0BC68B5E5025 +:104A90004B4B2BD9789CAB8BC1404001464ED1E9A2 +:104AA000F36D90895E50897E088B462680E4EF89FD +:104AB0004626F6C401750CF746480C007505B00291 +:104AC000E87FC5E97AFF86C48BC883E13F4180E176 +:104AD000FEE30A3C807209243FB4F0EBB0E960FFCA +:104AE000253F0033FF8EC7BF96128BF7D1E9F36DD8 +:104AF000908BC8E848EDE947FF906A001FC606930F +:104B0000121B9C0EE8D5C790601E0633C08ED88E4F +:104B1000C0BA0601ECA80474E1B006EEECA28C1257 +:104B2000A8407411A18812A38412C6068D1200E851 +:104B300060FEA08C12A8807403E804FFB80080BA5D +:104B400022FFEF071F61CF906A001FC60693121B5A +:104B50009C0EE887C790601E0633C08ED88EC0BA00 +:104B60000601ECA80474E1BA0801ECA28C12A8407A +:104B70007411A18812A38412C6068D1200E812FED9 +:104B8000A08C12A8807403E8B6FEB80080BA22FF99 +:104B9000EF071F61CF90EE86E0EE86E0EC86E0EC5A +:104BA00086E080E1FEF36C9080E1FEF36E900500FC +:104BB0007547A84B05007548A84B0500A348A84BAE +:104BC00005003549A84B06009848964B0600BA48A0 +:104BD000964B0600C348964B0600CB48964B060002 +:104BE0002049964B06002849964B06004E4A9C4B9E +:104BF00006007B4A9C4B05009E4AA24B0500EC4AEE +:104C0000A24B00001E06833E4412007409A0060158 +:104C100024303C30741A8CC88ED88EC0BBAE4B8BFF +:104C20000FE30D8B7F028B7704F3A483C306EBEFB6 +:104C3000071FC39033C0A33E01B90C01BE40018BD6 +:104C4000FE81C6B40F89048BC62BF13BC777F6A350 +:104C50003C01C3901E0660368B2E3E018B5E003BEE +:104C6000EB742B8B7602891C89770236A13C018973 +:104C7000460036892E3C018BEBFF4E0674088B6E86 +:104C800000FF4E0675F836892E3E018B66046107DB +:104C90001FC31E0660368B2E3E0198894606896624 +:104CA000043B6E0074108B6E00FF4E0675F836895B +:104CB0002E3E018B660461071FC3C3901E06609CD5 +:104CC000FA33ED8EDD8B2E3C0185ED743D8B4E006D +:104CD000890E3C018BCC8DA60A01561E06608966A2 +:104CE00004C746080F1AC7460601008B1E3E018501 +:104CF000DB741D8BC58707894600895E028BD889C6 +:104D00006F028BE19D61071FF8C39D61071FF9C307 +:104D1000892E3E01896E00896E0287E19D8BE1EB51 +:104D2000E4000D0A5465726D696E616C73207375D1 +:104D300070706F727465643A0D0A312920414E53C8 +:104D40004920636F6D70617469626C650D0A322968 +:104D500020577973652033300D0A506C6561736597 +:104D60002073656C6563743A20000D0A636F646597 +:104D7000207365676D656E743D000D0A4D6F6E6939 +:104D8000746F722076322E350A0D0A3E000D0A50DD +:104D90006172646F6E3F000D0A4E6F206164647231 +:104DA00065737320737065636966696564000D0AD5 +:104DB0003A000D0A004C6F633D000D0A4641544114 +:104DC0004C204552524F523D000D0A4D6F6E697492 +:104DD0006F7220636F6D6D616E64733A2D0D0A20E2 +:104DE0002020442C645B5B787878783A5D7878781A +:104DF000785D202D2064756D70206D656D6F727902 +:104E00000D0A2020204C2C6C5B5B787878783A5D1A +:104E1000787878785D202D2064756D702073696EC8 +:104E2000676C65206C696E650D0A202020452C6535 +:104E30005B5B787878783A5D787878785D202D209B +:104E400065646974206D656D6F72790D0A2020208C +:104E5000462C665B5B78787878205D787878785D2A +:104E6000202D2066696C6C206D656D6F72792070E5 +:104E70006172616772617068730D0A202020495B5E +:104E8000787878785D202020202020202020202D78 +:104E900020776F726420696E7075742066726F6D12 +:104EA00020706F72740D0A202020695B7878787802 +:104EB0005D202020202020202020202D20627974B9 +:104EC0006520696E7075742066726F6D20706F72E8 +:104ED000740D0A2020204F78787878207878202068 +:104EE000202020202020202D206F757470757420C4 +:104EF000776F726420746F20706F72740D0A2020B7 +:104F0000206F787878782078782020202020202042 +:104F100020202D206F75747075742062797465205F +:104F2000746F20706F72740D0A202020475B5B78CD +:104F30007878783A5D787878785D2020202D206721 +:104F40006F746F20616464726573730D0A20202092 +:104F5000575B5B787878783A5D787878785D202050 +:104F6000202D207761746368206120776F72640D53 +:104F70000A20202043202020202020202020202024 +:104F800020202020202D20696E7465727275707447 +:104F900073206F66660D0A202020532020202020D9 +:104FA00020202020202020202020202D20696E7409 +:104FB00065727275707473206F6E0D0A20202073F5 +:104FC00020202020202020202020202020202020E1 +:104FD0002D2073696E676C6520737465700D0A20EF +:104FE000202042787878782020202020202020203F +:104FF0002020202D20627265616B706F696E7420B5 +:105000007365740D0A20202062202020202020209B +:105010002020202020202020202D20627265616B1E +:10502000706F696E7420636C6561720D0A202020B8 +:10503000522020202020202020202020202020203E +:10504000202D207265737461727420627265616BC9 +:10505000706F696E740D0A2020207220202020209D +:1050600020202020202020202020202D2072656755 +:105070006973746572732061742062726B70740D51 +:105080000A202020582C78206E202020202020204C +:1050900020202020202D206578616D696E652063B9 +:1050A00068616E6E656C206E0D0A202020482C3FD2 +:1050B00020202020202020202020202020202D20E3 +:1050C00074686973206D657373616765001B5B327B +:1050D0004A1B5B313B3148414E5349205465726D48 +:1050E000696E616C0D0A0A001B5B4B001B5B4A007A +:1050F0001B5B324A1B5B313B3148001B5B44201B6E +:105100005B44001B5B313B373248001B5B003B00BC +:1051100048001B5B73001B5B75001B7A2B0B7F1B0E +:105120007A2E0C7F1B7A2D087F1B7A2C0A7F1B7A24 +:1051300022087F1A57797365203330205465726DC9 +:10514000696E616C0D0A001B54001B59001A001E89 +:105150000008200800001B3D0000001B46000D0059 +:105160003F4464456546664767486849694F6F43F1 +:1051700063537342625272577758784C6C3C60D4D8 +:1051800057D45750585058D659D659B459B4593C99 +:10519000603C606C57485726570657905790579871 +:1051A00057485F0C5F585F335F405FA057A057FEC2 +:1051B00059FE59DC57DC5788619861C061CC61D8D1 +:1051C00061F66102622262F8564A625862605920B2 +:1051D00020666C6167733D00202061783D002020CF +:1051E00062783D00202063783D00202064783D00F7 +:1051F000202063733D00202064733D0020206573F0 +:105200003D00202073733D00202064693D00202074 +:1052100073693D00202062703D00202073703D00C6 +:10522000202069703D00206368616E656C3D002040 +:105230002020207365673D002074695F7374723DA0 +:10524000002074695F746F733D002074695F6D6145 +:10525000783D002074695F6261733D002074695F6E +:1052600073697A3D002074695F7374663D00207431 +:10527000695F726F6F3D002074695F666C673D0007 +:105280002074695F746F743D002072695F70636E93 +:105290003D002072695F7374723D002072695F7314 +:1052A00074663D002072695F726F6F3D0020726905 +:1052B0005F6261733D002072695F73697A3D00200F +:1052C00072695F746F743D002072695F6D696E3D35 +:1052D000002072695F666C673D002072695F746FC1 +:1052E000733D002072695F7468723D002074685FCE +:1052F0007374663D002074685F7374723D0020749F +:10530000685F6261733D002074685F73697A3D0075 +:105310002074685F7472673D002074685F666C6714 +:105320003D002074685F636E743D002072685F7397 +:1053300074723D002072685F7374663D002072686D +:105340005F6261733D002072685F73697A3D00207F +:1053500072685F7370613D002072685F61736F3DBA +:10536000002072685F726F6F3D002072685F666C2C +:10537000673D00206D5F636172653D002070745F62 +:10538000666C6F3D002061735F666C6F3D0020723C +:105390006D5F666C6F3D00202020715F696E3D007F +:1053A0002020715F6F75743D0020715F6472616EC3 +:1053B0003D002020715F74696D3D00202020715FE9 +:1053C00066633D0020715F737461743D0020715FFE +:1053D000646174613D0020715F6D6F646D3D0020FC +:1053E00068616E645F6F3D002068616E645F623D5E +:1053F000002068616E645F653D002068616E645FD7 +:10540000693D0020206F706F73743D002020746927 +:105410006D656F3D0020637573746D313D002063D1 +:105420007573746D323D0020637573746D643D0057 +:10543000207478726174653D0020727872617465C1 +:105440003D002020635F6D61703D0020635F6164FB +:1054500064723D0020635F616973723D0020635F89 +:10546000787461673D0020635F646566723D00206B +:10547000635F666C73683D002074786D6178733D7E +:10548000002072695F656D733D002020635F6C735F +:10549000723D002020635F6965723D002020635FDC +:1054A0006663723D002020635F6D63723D002020C3 +:1054B000635F6C63723D002020635F6473733D0023 +:1054C00020635F647373693D0020635F647373726C +:1054D0003D002020635F6973723D002020635F639D +:1054E00061723D002020635F6566723D0020635F4E +:1054F000657273743D0020635F65636E743D0020C8 +:10550000635F62726B633D0020635F626F6B633D3C +:105510000020635F7265706C3D0020635F6363739E +:10552000723D0020635F737474313D0020635F73CC +:105530007474323D002BC08ED88EC0E8C200E8E5FE +:1055400000FABF8400C705DC568C4D02BF0C00C7B3 +:10555000056E5E8C4D02BF0400C705BA5E8C4D021D +:10556000E8F10090E84901E81600F490E8E500BE93 +:10557000BA4DE8090CA09312E85D0CE8C209EBE40F +:10558000E8D50CE8C40C0AC074F68B1EF8793C0D03 +:10559000742E3C0874173C7F741383FB207FE188D2 +:1055A00087D67943891EF879E8770CEBD30BDB7447 +:1055B000CF4B891EF8798B36167AE8C10BEBC19078 +:1055C000E80200EBBBC687D679000BDB741EA0D6C1 +:1055D00079BF6051B91D008BD9060E07F2AE077571 +:1055E00017412BD9D1E32EFF977D519033C0A3F8FB +:1055F00079BE894DE8870BC3BE8D4DE8800BEBEC7F +:10560000BA0002B093EEB055EEBA1002B093EEB00D +:10561000AAEEBA0002EC3C557508BA1002EC3CAA9E +:105620007403E82FF6C3BA0402B01AEEB020EEB04D +:1056300030EEB040EEB080EEBA0002B013EEB0072C +:10564000EEBA0802B080EEBA0202B0BBEEBA0402B3 +:10565000B005EEC3C606CA1301C706F8790000C636 +:1056600006F67901C706D0790000C706D279000096 +:10567000C706D4790000C706FA790000C706FC798E +:105680000000C706FE790000C706007A0000C706C2 +:10569000027ACE598C0E047AC706067A0000C70635 +:1056A000277A0000C606297A00C6062A7A00C39027 +:1056B000BE224DE8C80AE83F002C313C0177F7E8EC +:1056C00081098B360C7AE8B50ABE6A4DE8AF0A0E3E +:1056D00058E8F80ABE7A4DE8A40AC39060D1E38383 +:1056E000FB1873111EBA00008EDA2EFF97B7518B8C +:1056F000EC8946101F61CF90E84F0B0AC07505E892 +:10570000560BEBF4C390833EF879017416BED7793B +:10571000E8310A8BD0AC3C2C74043C207505E8239E +:105720000AEEC3E9D2FE833EF8790174F6BED7795A +:10573000E8110A8BD0AC3C2C74083C207404E9B707 +:10574000FE90E8FF09EFC3908B16067A833EF87946 +:1057500001740BBED779E8EB098BD0A3067AB02091 +:10576000E8570B8B16067AECE86F0BC38B16067A9C +:10577000833EF87901740BBED779E8C7098BD0A3B3 +:10578000067AB020E8330B8B16067AEDE8670BC378 +:10579000FAC606F67900C390C606F67901FBC390F7 +:1057A00006E85809B020E8110B268B05E8470BB036 +:1057B00008E8060BE8030BE8000BE8FD0AB8010057 +:1057C000E8CFF4BA0202EC24017502EBDCBA06025F +:1057D000EC07C390C706087A1000EB06C706087AE4 +:1057E0000100068E06FC798B3EFA79E80E09E80B7B +:1057F00000893EFA798C06FC7907C390BEB24DE869 +:105800007C098B16087A52E82A09E80F0AE80C0A84 +:1058100033DBB9100090268A01E8BC09E8FD094392 +:10582000E2F4E8F709E8F40933DBB9100090268ABE +:10583000013C2072053C7E760390B02EE8E30943DC +:10584000E2ECBEB24DE8360983C7105A4A75B7C3B9 +:10585000068E06007A8B3EFE79E8A008893EFE7926 +:105860008C06007A578B360E7AE81209C706087A3A +:105870001000BA0002E8E800E881FF5FBA0000E823 +:10588000DE00BEB54DE8F6088CC0E83F09B03AE846 +:1058900090098BC7E83509E87E08E8C30090E8B7AF +:1058A00009E8A6090AC074F63C0B750683EF10EBF5 +:1058B00019903C0A750683C710EB0F903C0C7504D9 +:1058C00047EB07903C0875244F908B36FE798BC7C9 +:1058D0002BC63D000172A53D1001720483EE20909D +:1058E00083C6108936FE79578BFEEB803C2E7508F7 +:1058F000BA0113E86A0007C3C6060A7A0232C990E1 +:105900003C30724C3C39760C245F3C4172423C4640 +:10591000773E2C072C3050E8CC085802C8FE0E0AFF +:105920007A740FC0E104E82F09E81E090AC074F672 +:10593000EBCE26880DE8E0078AD0E823008AC13C38 +:105940002072053C7E760390B02EE8D508E970FF02 +:10595000E8C507E80A00268A05E87C08E91DFF90EB +:10596000F606267A02750286F2528B361A7AE80D0E +:10597000085A528AC60206247AF606267A01750665 +:10598000E89F08EB0D9032E4E80D088B361C7AE8AE +:10599000EC075A8AC20206257AF606267A017506AF +:1059A000E87F08EB069032E4E8ED078B361E7AE8D4 +:1059B000CC07C390068E06047A8B3E027AE83C0739 +:1059C000893E027A8C06047A07FF1E027AC3BE97CC +:1059D0004DE8AA07CB900657BED779E866078BD863 +:1059E000E861078BC82BCB78118EC3BF0000B8FFCE +:1059F000FF51B90800F3AB59E2F75F07C39006BE49 +:105A0000D779E83F078BD8D1E32E8B9F4400BE2681 +:105A100052E8F1088BC3E8DD08B80100E873F2E84A +:105A2000E008BE2F52E8DD088B4718E8C808BE77AB +:105A300052E8D1088B4726E8BC08BE5352E8C50897 +:105A40008B471EE8B008BE5C52E8B9088B4720E8D7 +:105A5000A408BE6E52E8AD088B4724E89808BE80C3 +:105A600052E8A1088B472AE88C08E89508BE38520E +:105A7000E892088B07E87E08BE4152E887088B470A +:105A80001AE87208BE4A52E87B088B471CE8660891 +:105A9000BE6552E86F088B4722E85A08E86308BEE3 +:105AA000D152E860088B4738E84B08BEAD52E85445 +:105AB000088B4730E83F08BEB652E848088B4732AB +:105AC000E83308BEA452E83C088B472EE82708BEFE +:105AD000BF52E830088B4734E81B08E82408BE8929 +:105AE00052E821088B4704E80C08BE9252E81508DA +:105AF0008B4714E80008BE9B52E809088B472CE846 +:105B0000F407BEC852E8FD078B4736E8E807BEDA5F +:105B100052E8F1078B473AE8DC07BEE352E8E507B5 +:105B20008B473CE8D007E8D907BE1953E8D6078B66 +:105B30004748E8C107BEFE52E8CA078B4742E8B5AE +:105B400007BE0753E8BE078B4744E8A907BE7C534E +:105B5000E8B2078B474CE89D07BE8553E8A6078B44 +:105B6000474EE89107BE8E53E89A078B4750E88569 +:105B700007E88E07BE2253E88B078B474AE8760773 +:105B8000BEEC52E87F078B4708E86A07BEF552E88B +:105B900073078B4740E85E07BE1053E867078B47E3 +:105BA00046E85207E85B07BE6A53E858078B477A16 +:105BB000E84307BE3D53E84C078B4770E83707BE04 +:105BC0004653E840078B4772E82B07BE4F53E83433 +:105BD000078B4774E81F07E82807BE2B53E8250703 +:105BE0008B470CE81007BE3453E819078B4710E8C1 +:105BF0000407BE5853E80D078B4776E8F806BE61E8 +:105C000053E801078B4778E8EC06BE7353E8F506C6 +:105C10008B473EE8E006E8E906BE9753E8E6068BC8 +:105C20004752E8D106BEA053E8DA068B4754E8C5D0 +:105C300006BEA953E8CE068B4756E8B906BEB25356 +:105C4000E8C2068B4758E8AD06BEBB53E8B6068BE4 +:105C5000475AE8A106BEC453E8AA068B475CE895FC +:105C600006E89E06BECD53E89B068B475EE8860697 +:105C7000BED653E88F068B4760E87A06BEDF53E84E +:105C800083068B4762E86E06BEE853E877068B47CB +:105C90007CE86206BEF153E86B068B477EE8560649 +:105CA000BEFA53E85F068B878000E84906E8520693 +:105CB000BE4254E84F068B879E00E83906BE035467 +:105CC000E842068B4764E82D06BE0C54E836068B86 +:105CD000476EE82106BE1554E82A068B878E00E839 +:105CE0001406BE1E54E81D068B879000E80706BE0A +:105CF0002754E810068B879200E8FA05E80306BEF1 +:105D00003054E800068B879400E8EA05BE3954E871 +:105D1000F3058B879600E8DD05BE6F54E8E6058B3A +:105D2000879800E8D005BE5D54E8D9058A87A000B1 +:105D3000E8A705BE5454E8CC058A4728E89B05BE71 +:105D40006654E8C0058A87A100E88E05E8B305BE61 +:105D50007854E8B0058A87A200E87E05BE8154E841 +:105D6000A3058A87A300E87105BE8A54E896058AD0 +:105D700087A400E86405BE9354E889058A87A500D6 +:105D8000E85705BE9C54E87C058A87A600E84A05CA +:105D9000BEA554E86F058A87A700E83D05BEAE544E +:105DA000E862058A87A800E83005E85505BEB754C3 +:105DB000E852058A87A900E82005BEC054E84505D9 +:105DC0008A87AA00E81305BEC954E838058A87AB5C +:105DD00000E80605BED254E82B058A87AD00E8F935 +:105DE00004BEDB54E81E058A87AE00E8EC04BEE47E +:105DF00054E811058A87AF00E8DF04BEED54E804DB +:105E0000058A87B000E8D204E8F704BEF654E8F447 +:105E1000048A87B100E8C204BEFF54E8E7048A8719 +:105E2000B200E8B504BE0855E8DA048A87B300E892 +:105E3000A804BE1155E8CD048A87BB00E89B04E89E +:105E4000C004BE1A55E8BD048A87BC00E88B04BEB6 +:105E50002355E8B0048A87BE00E87E04BE2C55E8CE +:105E6000A3048A87BF00E87104E8960407C36006AC +:105E70001E168BECFF4E16F7461A00027401FBB893 +:105E800000008ED88EC0892E2D7AE8CB0081661A4C +:105E9000FFFEC6062A7A00E8D800B8005FA32B7A76 +:105EA000E85D00803E2A7A00740A814E1A0001C61D +:105EB000062A7A00171F0761CF9060061E168BEC2A +:105EC000F7461A00027401FBB800008ED88EC08914 +:105ED0002E2D7A81661AFFFEC6062A7A00E8920005 +:105EE000B8005FA32B7AE81700803E2A7A00740A74 +:105EF000814E1A0001C6062A7A00171F0761CF904B +:105F0000B8F000E88CEDFF262B7AC390065356803C +:105F10003E297A007403E83F00BED779E825028B5A +:105F2000D8A3277A2E8A07A2297AB0CC2E88075EBA +:105F30005B07C3C6062A7A00B80A5FA32B7AC39010 +:105F40008B2E2D7AE82B00C3C6062A7A01E80800BA +:105F5000B80A5FA32B7AC39057803E297A00740F4A +:105F60008B3E277AA0297A2E8805C606297A005FFB +:105F7000C390BEB24DE80602BED851E80002FF76DB +:105F80001458E84702BEDE51E8F301FF760E58E8E8 +:105F90003A02BEE451E8E601FF761258E82D02BE4F +:105FA000EA51E8D901FF761058E82002BE1452E801 +:105FB000CC01FF760A58E81302BE1A52E8BF01FF6F +:105FC000760C58E80602BECF51E8B201FF761A58A7 +:105FD000E8F901BEB24DE8A501BEF051E89F01FF0E +:105FE000761858E8E601BEF651E89201FF760258AD +:105FF000E8D901BEFC51E88501FF760458E8CC01E0 +:10600000BE0252E87801FF760058E8BF01BE085290 +:10601000E86B01FF760658E8B201BE0E52E85E0159 +:10602000FF760858E8A501BE2052E85101FF761618 +:1060300058E89801BE894DE84401C390BEC94DE8B7 +:106040003C01C33C0074053C017459C3C7060C7A7B +:10605000CD50C7060E7AF050C706107AE850C70632 +:10606000127AEC50C706147AF450C706167AFB5021 +:10607000C706187A0351C7061A7A0B51C7061C7A4D +:106080000E51C7061E7A1051C706207A1251C70654 +:10609000227A1651C606247A01C606257A01C6065A +:1060A000267A03C3C7060C7A1A51C7060E7A4D51D9 +:1060B000C706107A4751C706127A4A51C706147AA2 +:1060C0004F51C706167A5151C706187A5551C7065F +:1060D0001A7A5651C7061C7A5951C7061E7A5A5168 +:1060E000C706207A5B51C706227A5E51C606247A1B +:1060F00020C606257A20C606267A02C3A1F879486A +:106100007414BED779E83C008BF8AC3C3A75078E26 +:10611000C7E830008BF8C3908BC72B06FE798AF056 +:10612000240F8AD002D002D080C20BC0EE0480C6F9 +:1061300003043DC38CC0E89300B03AE8E4008BC789 +:10614000E88900C35133C990AC3C2074FB900AC06D +:1061500074262C3072223C0976143C11721A2C07DA +:106160003C0F760A3C2A72102C203C0F770A98C10B +:10617000E10403C8ACEBD7904E8BC159C390068C99 +:10618000C88EC0E8020007C3268A04460AC0740607 +:10619000E88F00EBF390C3900BC0747A5133D2B9FF +:1061A000E803F7F18BCAE803008BC159BA6400F623 +:1061B000F2E80C008AC498B20AF6F2E802008AC437 +:1061C000500AF074050430E8580058C386C4E80744 +:1061D0000086C4E80200C390C1C804E80800C1C03A +:1061E00004E80200C3905350240FBBCA622ED7E8C4 +:1061F0003000585BC39086C4E8070086C4E80200FC +:10620000C39050B908008AE032C0D1C00430E81110 +:1062100000E2F558C390B030E80700C3B020E801B1 +:1062200000C3568B36D0798884D0774681E6FF014B +:10623000FF06D4798936D079813ED479FE0175087C +:1062400056E814005EEBF1905EC3BA0202EC240142 +:106250007404BA0602ECC390803EF67900740960BB +:10626000B80100E82CEA6190BA0202ECA804742894 +:106270008B36D279833ED47900741D8A84D07746D8 +:1062800081E6FF018936D279FF0ED479BA0602EE93 +:10629000BA0202ECA80475DCA1D479C352BA060292 +:1062A000EE5AC3905250BA0202ECA8047408585A2D +:1062B000E8E9FFF9C390585AF8C35250BA0202EC09 +:1062C000A80474FB585AE8D3FFC330313233343555 +:1062D0003637383941424344454653508AE080E4DA +:1062E0000FBBCA62C0E8042ED7E8CEFF8AC42ED7FF +:1062F000E8C7FF585BC386E0E8DFFF86E0E8DAFF27 +:10630000C390BEB24D502EAC3C007405E8ABFFEB21 +:10631000F558C390C808000056578B7604BF040098 +:10632000C746FC0000C746FA0000C746F8000083D5 +:106330007E0600750E56E8B60E590BC075058BC764 +:10634000E95B018B46FC8946FE0BFF7505B8010031 +:10635000EB0233C05056E8A40D5959B4008946FCED +:106360008B5EFC83FB087603E92B01D1E32EFFA7AC +:10637000B264B80300E92601837EFA007414C746AC +:10638000FA00008A445898508A44599850E8C20F3D +:106390005959837EF800740AC746F8000056E89BF6 +:1063A0000859837E060075058BC7E9F10083FF0459 +:1063B0007503E9E6008BC7E9E400837EFE00750300 +:1063C000BF0200E9D500837EFE007503BF0100E92E +:1063D000C9008B5EFE83FB077603E98600D1E32EBE +:1063E000FFA7A26433FFE97F00BF0400807C580F41 +:1063F0007422837EF800751CFE44586A0856E87EB5 +:106400000C59598A445804805056E8720C5959C79F +:1064100046FA0100837EF800740AC746F800005669 +:10642000E8190859EB42BF0400807C5800742283AD +:106430007EF800751CFE4C586A0856E8410C595904 +:106440008A445804805056E8350C5959C746FA0119 +:1064500000837EF800740AC746F8000056E8DC079F +:1064600059EB05BF0400EB00EB31BF0400EB2CC778 +:1064700046F801006A0856E8050C5959807C58090D +:106480007D04B00FEB02B00004805056E8F00B59C9 +:1064900059BF0400EB05BF0400EB00E9A5FE5F5EF9 +:1064A000C9C3E4636364636463646364E963266427 +:1064B00051647863BA63C6639664D2636A646A643B +:1064C0006F647263C808000056578B76048B7E0891 +:1064D0006A0156E8A90B59598A4606C0E0060480AD +:1064E0005056E89A0B5959C746FE0000897EF8EBD2 +:1064F00003FF46FE8B5EF8FF46F8803F0075F2838F +:106500007EFE107D25B810002B46FED1F88946FC92 +:10651000C746FA0000EB0B6A2056E8620B5959FF98 +:1065200046FA8B46FA3B46FC7CEDEB0C8BDF478A48 +:10653000075056E8490B5959803D0075EF6A0256DD +:10654000E83C0B5959EB005F5EC9C3C80400005614 +:10655000578B7E04C746FE0000BE1400E909018B7C +:106560005EFE83C3042BDF8A87AC0B88445AC64483 +:1065700058088A46FE884459C744060000C6441994 +:1065800000C6441A00C6441B00C6441D0DC6441E66 +:1065900003C6441F00C6442000C6442100C6445B15 +:1065A00000C6445D00C6445E00C6445F00C6446049 +:1065B00000C746FC0000EB0D8B5EFCD1E3C740300A +:1065C0000000FF46FC837EFC107CEDC746FC00000B +:1065D000EB0A8B5EFCC6405000FF46FC837EFC0449 +:1065E0007CF0C744540000C7445600008A445A98BF +:1065F000BAF80023D0B805000BC28946FC9CFA8A81 +:1066000046FCBAFE00EEBA0000EC9D24088846FC69 +:10661000837EFC007502EB4AFF76FEE87A0C59682F +:10662000350256E8320A59590BC07534683802569B +:10663000E8250A59590BC0752768420256E8180A1E +:1066400059590BC0751A684C0256E80B0A59590B78 +:10665000C0750D68560256E8FE0959590BC0740200 +:10666000EB00FF46FE83C662397EFE7D03E9EFFE46 +:10667000EB005F5EC9C3C808000056578B4604BADA +:106680006200F7EA0514008BF0837E06007405B8FB +:106690001000EB03B808008944048A460888445C6B +:1066A00056E85904598BF88BC78944568944548A53 +:1066B000445D88442F0BFF751D68C20F6A0156E8C0 +:1066C00002FE83C406EB006A0156E847FC59590BE9 +:1066D000C075F4BF0100897EFAB90500BBE96A2ED6 +:1066E0008B073B46FA74074343E2F4E9A4032EFF09 +:1066F000670AC744060200C74408F4088B5E04D149 +:10670000E38B87FC0889440A33C08BF8894454E939 +:10671000800356E8BB0559BF01008A445D88446088 +:10672000E96F03837C04087530807C5C0175158AF1 +:10673000445DB400D1E08BD8FFB7E40856E8F70811 +:106740005959EB138A445DB400D1E08BD8FFB7C42C +:106750000856E8E2085959EB2E807C5C0175158AD1 +:10676000445DB400D1E08BD8FFB7D40856E8C70821 +:106770005959EB138A445DB400D1E08BD8FFB7B40C +:106780000856E8B20859596A0156E887FB59598BEF +:10679000D883FB03772AD1E32EFFA7E16ABF01006C +:1067A0008A445D88445EEB188A445D04FF240788B0 +:1067B000445DEB0C8A445DFEC0240788445DEB0019 +:1067C000E9CF028A445DB400D1E08BD8FFB7FD0267 +:1067D00056E863085959681D0356E85A0859596A1A +:1067E0000156E82FFB59598BD883FB037736D1E349 +:1067F0002EFFA7D96ABF01008A445D88445FEB245D +:106800008A445D04FF8A540480C2FF22C288445D2A +:10681000EB128A445DFEC08A540480C2FF22C28803 +:10682000445DEB00E96B028B5C0683C3FED1E38B16 +:10683000400889048B1CFF77066A0056E885FC83B4 +:10684000C4068B5C064BD1E38B40088944028B5C09 +:1068500002FF77066A0156E86AFC83C4066A01569D +:10686000E8B1FA59598BD883FB037603E91F02D1AB +:10687000E32EFFA7D16A8B5C028B47048944028B0D +:106880005C02803F44750D8B5C028A4701B4003B7B +:1068900044047DE28B4604D1E08B1C03D88B440278 +:1068A0008947088B5C064BD1E38B4402894008E999 +:1068B000DE018B5C028B47028944028B5C02803FC5 +:1068C00044750D8B5C028A4701B4003B44047DE2B1 +:1068D0008B4604D1E08B1C03D88B44028947088B7C +:1068E0005C064BD1E38B4402894008E9A201BF0159 +:1068F00000E99C018B5C028A07B4008946F8B90C58 +:1069000000BBA16A2E8B073B46F874074343E2F4B1 +:10691000E977012EFF67188B4604D1E08B5C0203F8 +:10692000D88B47088B5C06FF4406D1E38940088B6F +:106930001C807F010074128B5C028A47018B1C8AC9 +:106940005701B6008BDA884018E94001FF4C06E990 +:106950003A018B5C028A47018B1C8A5701B6008B77 +:10696000DA884018E925018B5C028A47018B1C8A72 +:106970005701B6008BDA884018FF4C06E90D018BF1 +:106980005C028A47018B1C8A5701B6008BDA3040C3 +:1069900018E9F800B8F0108BF88944548A445F88ED +:1069A000445DE9E7008A441C983D020074073D03FA +:1069B000007402EB07C746FE0000EB2B8A441C98CC +:1069C000D1E08BD8FFB7690256E86B0659596A01C6 +:1069D00056E840F959598946FE837EFE00740683C5 +:1069E0007EFE0375E9EB00837EFE0374628A441C1D +:1069F00098D1E08BD8FFB76D0256E83A0659595640 +:106A0000E84D97598946FC8B5EFC83EBFE83FB03C4 +:106A10007733D1E32EFFA7996A68AC0256E81706D0 +:106A20005959EB23688F0256E80C065959EB186840 +:106A3000750256E801065959EB0D68C60256E8F68C +:106A4000055959EB02EB006A0156E8C7F85959BFDE +:106A50000100EB3868DD0256E8DC0559596A015639 +:106A6000E8B1F85959BF0100EB22B8D0308BF88952 +:106A700044548A446088445DEB12B8E0208BF88966 +:106A800044548A445E88445DEB02EB00EB02EB0069 +:106A9000EB00E941FC5F5EC9C3196A246A2F6A3AB8 +:106AA0006A0000010002000400410042004300446B +:106AB00000800081008200FF001769546A7A6AA58D +:106AC00069526994696A6A676952697F6967694C42 +:106AD00069F4687668B268EE68F56700681268F570 +:106AE000679D67A867B4679D6700000100F010E02C +:106AF00020D0302768F266C36723671267C8040096 +:106B00000056578B76048A4459988946FC6A098B4B +:106B100046FC05840150E8930859598BF88BC7252A +:106B200000F03D001075558BC725F0003DF0007555 +:106B30004B8BC725000FC1F8088946FE8B44043BE8 +:106B400046FE7D0533C0E9EF008BC7250F00BA0F65 +:106B5000002BD03B56FE740533C0E9DB00C744026E +:106B600004098A46FE88445F88445D8B5EFCD1E35D +:106B7000C787FC080409B8F010E9BC008BC72500E2 +:106B8000F03D002075528BC725F0003DE0007548B0 +:106B90008BC725000FC1F8088946FE837EFE087E5C +:106BA0000533C0E992008BC7250F00BA0F002BD028 +:106BB0003B56FE740533C0EB7F90C744020C098A34 +:106BC00046FE88445E88445D8B5EFCD1E3C787FC4B +:106BD000080C09B8E020EB608BC72500F03D0030C1 +:106BE00075528BC725F0003DD00075488BC7250036 +:106BF0000FC1F8088946FE8B44043B46FE7D0433F2 +:106C0000C0EB358BC7250F00BA0F002BD03B56FECB +:106C1000740433C0EB22C7440214098A46FE884438 +:106C20006088445D8B5EFCD1E3C787FC081409B81B +:106C3000D030EB0433C0EB005F5EC9C3C806000070 +:106C4000568B76046A0856E8350459598A44580424 +:106C5000805056E8290459598B44543B4456750AD0 +:106C60008A445D3A442F7502EB648B445489445640 +:106C70008B5C028A470188442F8A445DB400C1E0DE +:106C8000088B54540BD08A445DB400BB0F002BD842 +:106C90000BD38956FE6A108A445998050400990559 +:106CA000400183D2005250E8540883C4068956FC40 +:106CB0008946FA8B46FE0946FA834EFC006A19FFA4 +:106CC00076FCFF76FAE8730783C406E8FE075EC920 +:106CD000C3C81C000056578B5E048A4759988BF036 +:106CE0008B5E048A475DB4008946E6837EE6007DBC +:106CF0000A8B5E048B4704488946E68B5E048B470B +:106D0000043B46E67F05C746E600008B5E048A46E4 +:106D1000E688475D8BDED1E38B9F5902C647022090 +:106D20008BDED1E38B9F5902C64703308BDED1E364 +:106D30008B9F6102C64702208BDED1E38B9F6102ED +:106D4000C64703308B46E68946FA837EFA007418FC +:106D50008B46FABB0A0033D2F7F380C2308BDED108 +:106D6000E38B9F5902885703BB0A008B46FA33D244 +:106D7000F7F38946FA837EFA0074188B46FABB0A49 +:106D80000033D2F7F380C2308BDED1E38B9F590200 +:106D90008857028B46E68946FA837EFA0074188B80 +:106DA00046FABB0A0033D2F7F380C2308BDED1E360 +:106DB0008B9F6102885703BB0A008B46FA33D2F7D8 +:106DC000F38946FA837EFA0074188B46FABB0A00F0 +:106DD00033D2F7F380C2308BDED1E38B9F61028820 +:106DE00057028B5EE6D1E3FFB712026A00FF76041A +:106DF000E8D1F683C40668D30F6A01FF7604E8C3BE +:106E0000F683C406FF76E656E8019359598956F28F +:106E10008946F0FF76E656E8149359598956EE896B +:106E200046EC9CFAC45EF0268B078946EAC45EEC09 +:106E3000268B078946E8BA50FFED8946FE9DC74676 +:106E4000E40100E8EEA0BA50FFED8946FC8B46FC59 +:106E50002B46FE3DE8037303E980019CFABA50FF1C +:106E6000ED8946FC8B46FC2B46FE8946F8C45EF055 +:106E7000268B072B46EA8946F6C45EF0268B0789E7 +:106E800046EAC45EEC268B072B46E88946F4C45ECE +:106E9000EC268B078946E8BA50FFED8946FE9D81B6 +:106EA0007EF8E803761CFF76F8FF76F6E87601595F +:106EB000598946F6FF76F8FF76F4E8680159598952 +:106EC00046F4BF0E00EB178BDED1E38B9F5902C651 +:106ED00001208BDED1E38B9F6102C601204783FF37 +:106EE0001176E48BDED1E38B9F5902C6470D308BC0 +:106EF000DED1E38B9F6102C6470D30837EF60977B2 +:106F000005B80D00EB26837EF6637705B80E00EB1F +:106F10001B817EF6E7037705B80F00EB0F817EF645 +:106F20000F277705B81000EB03B811008BF8EB259D +:106F30008B46F6BB0A0033D2F7F380C2308BDED12A +:106F4000E38B9F590288114FBB0A008B46F633D260 +:106F5000F7F38946F6837EF60075D5837EF40977CC +:106F600005B80D00EB26837EF4637705B80E00EBC1 +:106F70001B817EF4E7037705B80F00EB0F817EF4E9 +:106F80000F277705B81000EB03B811008BF8EB253D +:106F90008B46F4BB0A0033D2F7F380C2308BDED1CC +:106FA000E38B9F610288114FBB0A008B46F433D2FA +:106FB000F7F38946F4837EF40075D58BDED1E3FFC9 +:106FC000B75902FF7604E86E0059598BDED1E3FF12 +:106FD000B76102FF7604E85E0059596A00FF760443 +:106FE000E831F359598BD883FB04771FD1E32EFF87 +:106FF000A71B70EB22C746E40000FF4EE6EB0CC770 +:1070000046E40000FF46E6EB02EB00837EE40074FA +:1070100003E92AFEE9D4FC5F5EC9C3F36FF56FFF95 +:107020006FF36F0970558BEC8B4604B9E803F7E1F9 +:107030008B4E06F7F15DC3558BEC568B7606EB0E47 +:107040008BDE468A0750FF7604E833005959803CAE +:107050000075EDEB005E5DC3558BEC568B7606EB51 +:10706000148BDE468A0750FF7604E8450059590B19 +:10707000C07402EB07803C0075E7EB005E5DC3C89F +:10708000020000568B76048A445A988946FE9CFA80 +:107090008A46FEBAFE00EEBA0200ECA80274069D13 +:1070A000E8919EEBE9BA00008A4606EE9DEB005E91 +:1070B000C9C3C8040000568B76048A445A9889468E +:1070C000FEE8E6A18946FCE8E0A12B46FC3DB80BB2 +:1070D0007605B80100EB239CFA8A46FEBAFE00EE64 +:1070E000BA0200ECA80274069DE8489EEBD9BA00EB +:1070F000008A4606EE9D33C0EB005EC9C3C804009B +:107100000056578B7604837E0600740756E8030109 +:1071100059EB0556E8A200598846FF807EFF0877A4 +:10712000068A46FFE98400807EFF0F7603EB7990A4 +:107130008A46FFB4002D0A008BD883FB047767D101 +:10714000E32EFFA7AF71B000EB6156E86B0059B4B6 +:1071500000250F008946FC56E85E0059B4008BF804 +:1071600056E8550059B400C1E0088BD703D08BFA1C +:107170008B5EFCD1E3897830EB2E56E83B005988D2 +:10718000445BEB2456E831005988445056E8290006 +:107190005988445156E821005988445256E819004C +:1071A00059884453EB02EB00E95BFF5F5EC9C346BD +:1071B00071A6714A717A718471C8040000568B7689 +:1071C000048A445A988946FE9CFA8A46FEBAFE0012 +:1071D000EEBA0200ECA80175069DE8579DEBE9BAEE +:1071E0000000EC8846FD9D8A46FDEB005EC9C3C8E1 +:1071F000020000568B76048A445A988946FE9CFA0F +:107200008A46FEBAFE00EEBA0200EC32E424019D8A +:107210005EC9C3C8060000568B76048A445A988912 +:1072200046FEE885A08946FAE87FA02B46FA3DB8DD +:107230000B7604B008EB249CFA8A46FEBAFE00EEF8 +:10724000BA0200ECA80175069DE8E89CEBDABA00EA +:1072500000EC8846FD9D8A46FDEB005EC9C3558B58 +:10726000EC568B56048A4606EE33F6EB035058462E +:1072700083FE147CF85E5DC3C8020000568B560482 +:10728000EC8846FF33F6EB0350584683FE147CF837 +:107290008A46FFEB005EC9C3C802000056578B76D2 +:1072A00004833EB00B00751FBA8801B000EEBA86A9 +:1072B00001B000EE6A096A00683001E87D0183C40C +:1072C00006C706B00B01006A098BC605800150E8AD +:1072D000DA0059598BF88BC7C1E80C250F00894695 +:1072E000FE8BC7C1E808250F008B56FE83F20C3BCE +:1072F000C275218BC7C1E804250F008B56FE83F2AF +:10730000063BC2750F8BC7250F008B56FE83F20913 +:107310003BC2740D6A0756E838005959C746FE0744 +:10732000008A46FE0480A233028BC6BA6200F7EAE6 +:107330008A56FE8BD888976C006832028BC6BA6278 +:1073400000F7EA05140050E80EFD5959EB005F5EA6 +:10735000C9C3C8020000568B760683E60F8BC6C1F0 +:10736000E00C8BD683F20CC1E2080BC28BD683F201 +:1073700006C1E2040BC28BD683F2090BC28946FE1A +:107380006A196A108B46049905400183D200525055 +:10739000E86B0183C4060B46FE83CA005250E89A8C +:1073A0000083C406E82501EB005EC9C3558BEC568B +:1073B0005733FF6A01688601E8A3FE5959B1102AC4 +:1073C0004E06D3660433F6EB2E817E0400807204F1 +:1073D000B001EB02B00050688801E881FE59596A9B +:1073E00003688601E877FE59596A01688601E86DED +:1073F000FE5959D16604463B76067CCD33F6EB2424 +:10740000D1E76A03688601E854FE59596A01688623 +:1074100001E84AFE5959688801E85CFE599825013F +:10742000000BF84683FE107CD76A00688601E82DC1 +:10743000FE59598BC7EB005F5E5DC3558BEC565709 +:107440008B7E086A01688601E813FE5959B820004E +:107450002BC750FF7606FF7604E8A20083C4068996 +:10746000560689460433F6EB47817E060080720C8F +:107470007506837E04007204B001EB02B000506810 +:107480008801E8D9FD59596A03688601E8CFFD599A +:10749000596A01688601E8C5FD59596A01FF7606F7 +:1074A000FF7604E8580083C40689560689460446D8 +:1074B0003BF77CB56A00688601E8A2FD59596A006D +:1074C000688601E898FD59595F5E5DC3558BEC569F +:1074D0006A01688601E886FD595933F6EB00688831 +:1074E00001E894FD59A80175088BC6463D64007CEF +:1074F000ED6A00688601E865FD59595E5DC3C80400 +:1075000000008B46048B56068B4E08E306D1E0D173 +:10751000D2E2FA8946FC8956FE8B56FE8B46FCEB7E +:1075200000C9C300000000000000000000000000CF +:1075300050726576696F7573204D656E7500426592 +:1075400067696E00000000000000000000000000FD +:10755000000000000000000000000000000000002B +:10756000000000000000000000000000000000001B +:10757000000000000000000000000000000000000B +:1075800000000000000000000000000000000000FB +:1075900000000000000000000000000000000000EB +:1075A00000000000000000000000000000000000DB +:1075B00000000000000000000000000000000000CB +:1075C00000000000000000000000000000000000BB +:1075D00000000000000000000000000000000000AB +:1075E000000000000000000000000000000000009B +:1075F000000000000000000000000000000000008B +:10760000000000000000000000000000000000007A +:10761000000000000000000000000000000000006A +:10762000000000000000000000000000000000005A +:10763000000000000000000000000000000000004A +:10764000000000000000000000000000000000003A +:10765000000000000000000000000000000000002A +:10766000000000000000000000000000000000001A +:10767000000000000000000000000000000000000A +:1076800000000000000000000000000000000000FA +:1076900000000000000000000000000000000000EA +:1076A00000000000000000000000000000000000DA +:1076B00000000000000000000000000000000000CA +:1076C000000000000000000000000000506F727415 +:1076D000203000506F7274203100506F727420326D +:1076E00000506F7274203300506F72742034005059 +:1076F0006F7274203500506F7274203600506F72B4 +:1077000074203700506F7274203800506F727420EC +:107710003900506F727420313000506F7274203114 +:107720003100506F727420313200506F727420310A +:107730003300506F727420313400506F72742031F6 +:1077400035009C01A301AA01B101B801BF01C60126 +:10775000CD01D401DB01E201EA01F201FA010202EA +:107760000A02080000078100038080809F919591A4 +:107770009F000381848E95848484840003828484A2 +:107780008484958E8400048800B20BC60BDA0BEE5D +:107790000B020C160C2A0C3E0C520C770C9C0CBEE7 +:1077A0000CE00C020D01802054657374205061734D +:1077B000736564201F20507265737320800200017E +:1077C00080204D697373696E67205278204461741C +:1077D000611F205072657373208002000180204277 +:1077E00061642052782044617461201F20507265CA +:1077F000737320800200018020586D7472204275DE +:1078000073791F20507265737320800200018020FD +:107810006E6F742063757272656E746C791F2020B0 +:10782000696D706C656D656E7465640200240D2F62 +:107830000D3A0D450D500D5B0D660D710D7C0D87DC +:107840000D920D9D0DA80DB30DBE0DC90D53802CCD +:107850003254442053862C334454522053822C33C8 +:10786000525453201F53812C3252442053852C32C2 +:1078700043442053832C334354532053842C3344A8 +:1078800053522053872C3252492702000180202076 +:10789000444344202D2070696E2032301F275385C9 +:1078A0002E31818263908081828384858687888956 +:1078B0008A8B8C8D8E8F27020001802020445352AA +:1078C000202D2070696E2031311F2753842E318185 +:1078D000826390808182838485868788898A8B8C65 +:1078E0008D8E8F27020001802020435453202D20AD +:1078F00070696E20341F2753832E318182639080FC +:107900008182838485868788898A8B8C8D8E8F2758 +:107910000200018020205249202D2070696E203203 +:10792000321F2753872E3181826390808182838426 +:1079300085868788898A8B8C8D8E8F2702000180AF +:107940002020445452202D2070696E20362F381F7D +:107950002753862E3181826390808182838485863D +:107960008788898A8B8C8D8E8F270200018020204A +:10797000525453202D2070696E20351F2753822EBC +:107980003181826390808182838485868788898A19 +:107990008B8C8D8E8F27020001802020527844200E +:1079A0002D2070696E20321F2753812E30534D8158 +:1079B000826390808182838485868788898A8B8C84 +:1079C0008D8E8F27020001802020547844202D20A6 +:1079D00070696E20331F2753802E30534D81826390 +:1079E00090808182838485868788898A8B8C8D8E1E +:1079F0008F27020001802020444344202D207069FD +:107A00006E20351F2753852E3181826390808182BD +:107A1000838485868788898A8B8C8D8E8F27020048 +:107A200001802020445352202D2070696E20351F84 +:107A30002753842E3181826390808182838485865E +:107A40008788898A8B8C8D8E8F2702000180202069 +:107A5000435453202D2070696E20311F2753832EED +:107A60003181826390808182838485868788898A38 +:107A70008B8C8D8E8F270200018020205249202D73 +:107A800020286E2E632E291F2753872E3181826373 +:107A900090808182838485868788898A8B8C8D8E6D +:107AA0008F27020001802020445452202D2070692D +:107AB0006E20321F2753862E31818263908081820F +:107AC000838485868788898A8B8C8D8E8F27020098 +:107AD00001802020525453202D2070696E20371FC2 +:107AE0002753822E318182639080818283848586B0 +:107AF0008788898A8B8C8D8E8F27020001802020B9 +:107B0000527844202D2070696E20361F2753812E15 +:107B100030534D81826390808182838485868788FB +:107B2000898A8B8C8D8E8F270200018020205478CB +:107B300044202D2070696E20331F2753802E305330 +:107B40004D81826390808182838485868788898A3B +:107B50008B8C8D8E8F27020001802020444344208F +:107B60002D2070696E20351F202020202753852E60 +:107B700031818263888081828384858687270200A1 +:107B800001802020445352202D2070696E20351F23 +:107B9000202020202753842E318182638880818297 +:107BA0008384858687270200018020204354532048 +:107BB0002D2070696E20311F202020202753832E16 +:107BC0003181826388808182838485868727020051 +:107BD000018020205249202D20286E2E632E291F3F +:107BE000202020202753872E318182638880818244 +:107BF00083848586872702000180202044545220F8 +:107C00002D2070696E20321F202020202753862EC1 +:107C10003181826388808182838485868727020000 +:107C200001802020525453202D2070696E20371F70 +:107C3000202020202753822E3181826388808182F8 +:107C40008384858687270200018020205278442083 +:107C50002D2070696E20361F202020202753812E72 +:107C600030534D8182638880818283848586872713 +:107C7000020001802020547844202D2070696E205D +:107C8000331F202020202753802E30534D818263C4 +:107C90008880818283848586872702000180202056 +:107CA000444344202D2070696E2032301F20202054 +:107CB000202753852E318182638880818283848549 +:107CC000868727020001802020445352202D2070F7 +:107CD000696E2031311F202020202753842E3181CE +:107CE0008263888081828384858687270200018061 +:107CF0002020435453202D2070696E20341F2020F3 +:107D000020202753832E318182638880818283845F +:107D1000858687270200018020205249202D20706F +:107D2000696E2032321F202020202753872E318178 +:107D30008263888081828384858687270200018010 +:107D40002020445452202D2070696E20362F381F79 +:107D5000202020202753862E3181826388808182D3 +:107D60008384858687270200018020205254532077 +:107D70002D2070696E20351F202020202753822E51 +:107D8000318182638880818283848586872702008F +:107D900001802020527844202D2070696E20321FEF +:107DA000202020202753812E30534D8182638880EC +:107DB0008182838485868727020001802020547871 +:107DC00044202D2070696E20331F2020202027534F +:107DD000802E30534D8182638880818283848586A2 +:107DE0008727020068049604B6033C040E04890346 +:107DF0005C03E20360088A08BE0738080E0895078E +:107E00006C07E6071C057405FA05C404F004CC05EC +:107E1000A00548057806C806420728065006180738 +:107E2000F006A0060000F408F408D40D04090409C3 +:107E30000409040942000C091C09E50D020014099B +:107E40000409F40D43001C090C09050E0004040983 +:107E50001409120E2C092C092C092C0900003C09CC +:107E60006C091E0E740974097409740900014C0927 +:107E70002C092D0E740974097409740900025C0937 +:107E80003C093D0E740974097409740900036C09F6 +:107E90004C094D0E7409740974097409FF002C090A +:107EA0005C09000000058409EC095E0EF409F40980 +:107EB000F409F409000694097409680EAC0AAC0AC6 +:107EC000AC0AAC0A0007A4098409720EBC0ABC0AF9 +:107ED000BC0ABC0A0008B40994097C0ED40AD40A6E +:107EE000D40AD40A000BC409A409830EFC0AFC0AB4 +:107EF000FC0AFC0A000CD409B409900E140B140BF4 +:107F0000140B140B0002E409C409A00E2C0B2C0B5B +:107F10002C0B2C0B0400EC09D4090E00FF00740993 +:107F2000E40900008201FC09A40AAC0E8202040AE2 +:107F3000F409AF0E82030C0AFC09B20E8204140A83 +:107F4000040AB60E82051C0A0C0ABC0E8206240A1C +:107F5000140AC00E82072C0A1C0AC40E8208340AB6 +:107F6000240AC80E82093C0A2C0ACC0E820A440A52 +:107F7000340AD10E82104C0A3C0AD60E820B540AE7 +:107F8000440ADB0E82115C0A4C0AE00E820C640A81 +:107F9000540AE50E82126C0A5C0AEA0E820D740A1B +:107FA000640AEF0E820E7C0A6C0AF40E820F840AB9 +:107FB000740AFB0E82138C0A7C0A020F8214940A44 +:107FC000840A090F82159C0A8C0A100F8216A40AD3 +:107FD000940A170F8217F4099C0A1E0F8202B40A32 +:107FE000B40A260F8203AC0AAC0A2D0F8200C40A21 +:107FF000CC0A340F8201CC0ABC0A3F0F8202BC0AB1 +:10800000C40A4D0F8200DC0AF40A590F8201E40A07 +:10801000D40A630F8202EC0ADC0A6E0F8203F40AB0 +:10802000E40A7A0F8204D40AEC0A870F8200040B58 +:108030000C0B930F82010C0BFC0A9B0F8202FC0AB3 +:10804000040BA70F82001C0B240BB00F8201240B22 +:10805000140BB50F8202140B1C0BBE0F4400340B23 +:10806000A40B9C0144013C0B2C0BA3014402440BC8 +:10807000340BAA0144034C0B3C0BB1014404540BD8 +:10808000440BB80144055C0B4C0BBF014406640B68 +:10809000540BC60144076C0B5C0BCD014408740BF8 +:1080A000640BD40144097C0B6C0BDB01440A840B88 +:1080B000740BE201440B8C0B7C0BEA01440C940B17 +:1080C000840BF201440D9C0B8C0BFA01440EA40BA3 +:1080D000940B0202440F2C0B9C0B0A02171F0F2F4C +:1080E0000000018078783A20747820637073202A29 +:1080F0002A2A2A2A0200018078783A20747820639C +:108100007073202A2A2A2A2A0200018078783A20CD +:10811000747820637073202A2A2A2A2A0200018098 +:1081200078783A20747820637073202A2A2A2A2AC1 +:10813000020001C078783A20726320637073202AAD +:108140002A2A2A2A020001C078783A207263206322 +:108150007073202A2A2A2A2A020001C078783A203D +:10816000726320637073202A2A2A2A2A020001C01F +:1081700078783A20726320637073202A2A2A2A2A88 +:1081800002000180496E7374616C6C204C6F6F70DB +:108190006261636B1F5072657373208020746F205F +:1081A000737461727402000180204361626C652007 +:1081B000746F2052656D6F74651F50726573732004 +:1081C0008020746F20737461727402000180204CEF +:1081D0006F63616C204C6F6F706261636B201F2056 +:1081E0002052756E6E696E67202E2E2E0200018061 +:1081F00052656D6F7465204C6F6F706261636B20A8 +:108200001F202052756E6E696E67202E2E2E020082 +:10821000018020496E74726E6C204C6F6F706261C9 +:10822000636B1F202052756E6E696E67202E2E2E96 +:10823000020001805472616E736D69742050617424 +:108240007465726E1F202052756E6E696E67202EE7 +:108250002E2E020001802020303A2027438000018A +:10826000802020313A202743810001802020323AAB +:10827000202743820001802020333A2027438300B7 +:1082800001802020343A20274384000180202035BB +:108290003A202743850001802020363A2027438654 +:1082A0000001802020373A202743870001802020CA +:1082B000383A202743880001802020393A2027437C +:1082C000890001802031303A2027438A0001802034 +:1082D00031313A2027438B0001802031323A202768 +:1082E000438C0001802031333A2027438D000180E8 +:1082F0002031343A2027438E0001802031353A2046 +:1083000027438F002A2A204D61696E20204D656E1B +:1083100075202A2A004D6F6E69746F72206120509B +:108320006F7274004D6F6E69746F722061205369B3 +:10833000676E616C00457374696D617465204350AC +:108340005300446961676E6F7374696373004C6FA7 +:1083500063616C204C6F6F706261636B0052656D7E +:108360006F7465204C6F6F706261636B00496E744F +:10837000726E6C204C6F6F706261636B005472613F +:108380006E736D6974205061747465726E00426121 +:10839000756420526174650044617461204269749F +:1083A000730053746F702042697473005061726976 +:1083B00074790044617461205061747465726E0058 +:1083C000547820466C6F7720436F6E74726F6C0028 +:1083D000506F7274204E756D6265720035300037D3 +:1083E0003500313130003133342E35003135300035 +:1083F00032303000333030003630300031323030FF +:10840000003138303000323030300032343030001B +:1084100033363030003438303000373230300039C5 +:108420003630300031392C3230300033382C343093 +:10843000300035362C3030300035372C36303000B7 +:1084400036342C3030300037362C38303000313173 +:10845000352C323030003720626974730038206266 +:1084600069747300312073746F7020626974003115 +:108470002E352073746F702062697473003220731C +:10848000746F702062697473006E6F20706172691E +:108490007479006F64642070617269747900657624 +:1084A000656E207061726974790073706163652014 +:1084B000706172697479006D61726B2070617269AC +:1084C000747900436F6C756D6E7300426172626502 +:1084D0007220506F6C650055555555552E2E2E0047 +:1084E0004E6F6E6500586F6E2F586F66660043546E +:1084F00053005072657373208020666F72206D6523 +:108500006E750028636F756E74696E672E2E2E2946 +:108510000000654E64204F6620436F4465000000F4 +:10852000000000000000000000000000000000004B +:10853000000000000000000000000000000000003B +:10854000000000000000000000000000000000002B +:10855000000000000000000000000000000000001B +:10856000000000000000000000000000000000000B +:1085700000000000000000000000000000000000FB +:1085800000000000000000000000000000000000EB +:1085900000000000000000000000000000000000DB +:1085A00000000000000000000000000000000000CB +:1085B00000000000000000000000000000000000BB +:1085C00000000000000000000000000000000000AB +:1085D000000000000000000000000000000000009B +:1085E000000000000000000000000000000000008B +:1085F000000000000000000000000000000000007B +:00000001FF +/* Intelliport II loadware */ +/* -31232 bytes read from ff.lod */ diff --git a/trunk/fs/autofs4/expire.c b/trunk/fs/autofs4/expire.c index 842d00048a65..1feb68ecef95 100644 --- a/trunk/fs/autofs4/expire.c +++ b/trunk/fs/autofs4/expire.c @@ -94,21 +94,25 @@ static struct dentry *get_next_positive_subdir(struct dentry *prev, { struct autofs_sb_info *sbi = autofs4_sbi(root->d_sb); struct list_head *next; - struct dentry *q; + struct dentry *p, *q; spin_lock(&sbi->lookup_lock); - spin_lock(&root->d_lock); - if (prev) - next = prev->d_u.d_child.next; - else { + if (prev == NULL) { + spin_lock(&root->d_lock); prev = dget_dlock(root); next = prev->d_subdirs.next; + p = prev; + goto start; } -cont: + p = prev; + spin_lock(&p->d_lock); +again: + next = p->d_u.d_child.next; +start: if (next == &root->d_subdirs) { - spin_unlock(&root->d_lock); + spin_unlock(&p->d_lock); spin_unlock(&sbi->lookup_lock); dput(prev); return NULL; @@ -117,15 +121,16 @@ static struct dentry *get_next_positive_subdir(struct dentry *prev, q = list_entry(next, struct dentry, d_u.d_child); spin_lock_nested(&q->d_lock, DENTRY_D_LOCK_NESTED); - /* Already gone or negative dentry (under construction) - try next */ - if (q->d_count == 0 || !simple_positive(q)) { - spin_unlock(&q->d_lock); - next = q->d_u.d_child.next; - goto cont; + /* Negative dentry - try next */ + if (!simple_positive(q)) { + spin_unlock(&p->d_lock); + lock_set_subclass(&q->d_lock.dep_map, 0, _RET_IP_); + p = q; + goto again; } dget_dlock(q); spin_unlock(&q->d_lock); - spin_unlock(&root->d_lock); + spin_unlock(&p->d_lock); spin_unlock(&sbi->lookup_lock); dput(prev); @@ -399,6 +404,11 @@ struct dentry *autofs4_expire_indirect(struct super_block *sb, DPRINTK("checking mountpoint %p %.*s", dentry, (int)dentry->d_name.len, dentry->d_name.name); + /* Path walk currently on this dentry? */ + ino_count = atomic_read(&ino->count) + 2; + if (dentry->d_count > ino_count) + goto next; + /* Can we umount this guy */ if (autofs4_mount_busy(mnt, dentry)) goto next; diff --git a/trunk/fs/bio.c b/trunk/fs/bio.c index 71072ab99128..73922abba832 100644 --- a/trunk/fs/bio.c +++ b/trunk/fs/bio.c @@ -73,7 +73,7 @@ static struct kmem_cache *bio_find_or_create_slab(unsigned int extra_size) { unsigned int sz = sizeof(struct bio) + extra_size; struct kmem_cache *slab = NULL; - struct bio_slab *bslab, *new_bio_slabs; + struct bio_slab *bslab; unsigned int i, entry = -1; mutex_lock(&bio_slab_lock); @@ -97,12 +97,11 @@ static struct kmem_cache *bio_find_or_create_slab(unsigned int extra_size) if (bio_slab_nr == bio_slab_max && entry == -1) { bio_slab_max <<= 1; - new_bio_slabs = krealloc(bio_slabs, - bio_slab_max * sizeof(struct bio_slab), - GFP_KERNEL); - if (!new_bio_slabs) + bio_slabs = krealloc(bio_slabs, + bio_slab_max * sizeof(struct bio_slab), + GFP_KERNEL); + if (!bio_slabs) goto out_unlock; - bio_slabs = new_bio_slabs; } if (entry == -1) entry = bio_slab_nr++; @@ -1313,7 +1312,7 @@ EXPORT_SYMBOL(bio_copy_kern); * Note that this code is very hard to test under normal circumstances because * direct-io pins the pages with get_user_pages(). This makes * is_page_cache_freeable return false, and the VM will not clean the pages. - * But other code (eg, flusher threads) could clean the pages if they are mapped + * But other code (eg, pdflush) could clean the pages if they are mapped * pagecache. * * Simply disabling the call to bio_set_pages_dirty() is a good way to test the diff --git a/trunk/fs/block_dev.c b/trunk/fs/block_dev.c index 38e721b35d45..1e519195d45b 100644 --- a/trunk/fs/block_dev.c +++ b/trunk/fs/block_dev.c @@ -1578,12 +1578,10 @@ ssize_t blkdev_aio_write(struct kiocb *iocb, const struct iovec *iov, unsigned long nr_segs, loff_t pos) { struct file *file = iocb->ki_filp; - struct blk_plug plug; ssize_t ret; BUG_ON(iocb->ki_pos != pos); - blk_start_plug(&plug); ret = __generic_file_aio_write(iocb, iov, nr_segs, &iocb->ki_pos); if (ret > 0 || ret == -EIOCBQUEUED) { ssize_t err; @@ -1592,7 +1590,6 @@ ssize_t blkdev_aio_write(struct kiocb *iocb, const struct iovec *iov, if (err < 0 && ret > 0) ret = err; } - blk_finish_plug(&plug); return ret; } EXPORT_SYMBOL_GPL(blkdev_aio_write); diff --git a/trunk/fs/btrfs/backref.c b/trunk/fs/btrfs/backref.c index ff6475f409d6..a256f3b2a845 100644 --- a/trunk/fs/btrfs/backref.c +++ b/trunk/fs/btrfs/backref.c @@ -1438,10 +1438,10 @@ int iterate_inodes_from_logical(u64 logical, struct btrfs_fs_info *fs_info, ret = extent_from_logical(fs_info, logical, path, &found_key); btrfs_release_path(path); + if (ret & BTRFS_EXTENT_FLAG_TREE_BLOCK) + ret = -EINVAL; if (ret < 0) return ret; - if (ret & BTRFS_EXTENT_FLAG_TREE_BLOCK) - return -EINVAL; extent_item_pos = logical - found_key.objectid; ret = iterate_extent_inodes(fs_info, found_key.objectid, diff --git a/trunk/fs/btrfs/compression.c b/trunk/fs/btrfs/compression.c index 43d1c5a3a030..86eff48dab78 100644 --- a/trunk/fs/btrfs/compression.c +++ b/trunk/fs/btrfs/compression.c @@ -818,7 +818,6 @@ static void free_workspace(int type, struct list_head *workspace) btrfs_compress_op[idx]->free_workspace(workspace); atomic_dec(alloc_workspace); wake: - smp_mb(); if (waitqueue_active(workspace_wait)) wake_up(workspace_wait); } diff --git a/trunk/fs/btrfs/ctree.c b/trunk/fs/btrfs/ctree.c index 6d183f60d63a..9d7621f271ff 100644 --- a/trunk/fs/btrfs/ctree.c +++ b/trunk/fs/btrfs/ctree.c @@ -420,6 +420,12 @@ void btrfs_put_tree_mod_seq(struct btrfs_fs_info *fs_info, } spin_unlock(&fs_info->tree_mod_seq_lock); + /* + * we removed the lowest blocker from the blocker list, so there may be + * more processible delayed refs. + */ + wake_up(&fs_info->tree_mod_seq_wait); + /* * anything that's lower than the lowest existing (read: blocked) * sequence number can be removed from the tree. @@ -625,9 +631,6 @@ __tree_mod_log_free_eb(struct btrfs_fs_info *fs_info, struct extent_buffer *eb) u32 nritems; int ret; - if (btrfs_header_level(eb) == 0) - return; - nritems = btrfs_header_nritems(eb); for (i = nritems - 1; i >= 0; i--) { ret = tree_mod_log_insert_key_locked(fs_info, eb, i, diff --git a/trunk/fs/btrfs/ctree.h b/trunk/fs/btrfs/ctree.h index 9821b672f5a2..4bab807227ad 100644 --- a/trunk/fs/btrfs/ctree.h +++ b/trunk/fs/btrfs/ctree.h @@ -116,7 +116,7 @@ struct btrfs_ordered_sum; #define BTRFS_FREE_SPACE_OBJECTID -11ULL /* - * The inode number assigned to the special inode for storing + * The inode number assigned to the special inode for sotring * free ino cache */ #define BTRFS_FREE_INO_OBJECTID -12ULL @@ -1252,6 +1252,7 @@ struct btrfs_fs_info { atomic_t tree_mod_seq; struct list_head tree_mod_seq_list; struct seq_list tree_mod_seq_elem; + wait_queue_head_t tree_mod_seq_wait; /* this protects tree_mod_log */ rwlock_t tree_mod_log_lock; @@ -3191,7 +3192,7 @@ int btrfs_del_csums(struct btrfs_trans_handle *trans, int btrfs_lookup_bio_sums(struct btrfs_root *root, struct inode *inode, struct bio *bio, u32 *dst); int btrfs_lookup_bio_sums_dio(struct btrfs_root *root, struct inode *inode, - struct bio *bio, u64 logical_offset); + struct bio *bio, u64 logical_offset, u32 *dst); int btrfs_insert_file_extent(struct btrfs_trans_handle *trans, struct btrfs_root *root, u64 objectid, u64 pos, diff --git a/trunk/fs/btrfs/delayed-inode.c b/trunk/fs/btrfs/delayed-inode.c index 07d5eeb1e6f1..335605c8ceab 100644 --- a/trunk/fs/btrfs/delayed-inode.c +++ b/trunk/fs/btrfs/delayed-inode.c @@ -512,8 +512,8 @@ static void __btrfs_remove_delayed_item(struct btrfs_delayed_item *delayed_item) rb_erase(&delayed_item->rb_node, root); delayed_item->delayed_node->count--; - if (atomic_dec_return(&delayed_root->items) < - BTRFS_DELAYED_BACKGROUND && + atomic_dec(&delayed_root->items); + if (atomic_read(&delayed_root->items) < BTRFS_DELAYED_BACKGROUND && waitqueue_active(&delayed_root->wait)) wake_up(&delayed_root->wait); } @@ -1028,10 +1028,9 @@ static int btrfs_delete_delayed_items(struct btrfs_trans_handle *trans, btrfs_release_delayed_item(prev); ret = 0; btrfs_release_path(path); - if (curr) { - mutex_unlock(&node->mutex); + if (curr) goto do_again; - } else + else goto delete_fail; } @@ -1056,7 +1055,8 @@ static void btrfs_release_delayed_inode(struct btrfs_delayed_node *delayed_node) delayed_node->count--; delayed_root = delayed_node->root->fs_info->delayed_root; - if (atomic_dec_return(&delayed_root->items) < + atomic_dec(&delayed_root->items); + if (atomic_read(&delayed_root->items) < BTRFS_DELAYED_BACKGROUND && waitqueue_active(&delayed_root->wait)) wake_up(&delayed_root->wait); diff --git a/trunk/fs/btrfs/delayed-ref.c b/trunk/fs/btrfs/delayed-ref.c index ae9411773397..da7419ed01bb 100644 --- a/trunk/fs/btrfs/delayed-ref.c +++ b/trunk/fs/btrfs/delayed-ref.c @@ -38,14 +38,17 @@ static int comp_tree_refs(struct btrfs_delayed_tree_ref *ref2, struct btrfs_delayed_tree_ref *ref1) { - if (ref1->root < ref2->root) - return -1; - if (ref1->root > ref2->root) - return 1; - if (ref1->parent < ref2->parent) - return -1; - if (ref1->parent > ref2->parent) - return 1; + if (ref1->node.type == BTRFS_TREE_BLOCK_REF_KEY) { + if (ref1->root < ref2->root) + return -1; + if (ref1->root > ref2->root) + return 1; + } else { + if (ref1->parent < ref2->parent) + return -1; + if (ref1->parent > ref2->parent) + return 1; + } return 0; } @@ -82,8 +85,7 @@ static int comp_data_refs(struct btrfs_delayed_data_ref *ref2, * type of the delayed backrefs and content of delayed backrefs. */ static int comp_entry(struct btrfs_delayed_ref_node *ref2, - struct btrfs_delayed_ref_node *ref1, - bool compare_seq) + struct btrfs_delayed_ref_node *ref1) { if (ref1->bytenr < ref2->bytenr) return -1; @@ -100,12 +102,10 @@ static int comp_entry(struct btrfs_delayed_ref_node *ref2, if (ref1->type > ref2->type) return 1; /* merging of sequenced refs is not allowed */ - if (compare_seq) { - if (ref1->seq < ref2->seq) - return -1; - if (ref1->seq > ref2->seq) - return 1; - } + if (ref1->seq < ref2->seq) + return -1; + if (ref1->seq > ref2->seq) + return 1; if (ref1->type == BTRFS_TREE_BLOCK_REF_KEY || ref1->type == BTRFS_SHARED_BLOCK_REF_KEY) { return comp_tree_refs(btrfs_delayed_node_to_tree_ref(ref2), @@ -139,7 +139,7 @@ static struct btrfs_delayed_ref_node *tree_insert(struct rb_root *root, entry = rb_entry(parent_node, struct btrfs_delayed_ref_node, rb_node); - cmp = comp_entry(entry, ins, 1); + cmp = comp_entry(entry, ins); if (cmp < 0) p = &(*p)->rb_left; else if (cmp > 0) @@ -233,114 +233,6 @@ int btrfs_delayed_ref_lock(struct btrfs_trans_handle *trans, return 0; } -static void inline drop_delayed_ref(struct btrfs_trans_handle *trans, - struct btrfs_delayed_ref_root *delayed_refs, - struct btrfs_delayed_ref_node *ref) -{ - rb_erase(&ref->rb_node, &delayed_refs->root); - ref->in_tree = 0; - btrfs_put_delayed_ref(ref); - delayed_refs->num_entries--; - if (trans->delayed_ref_updates) - trans->delayed_ref_updates--; -} - -static int merge_ref(struct btrfs_trans_handle *trans, - struct btrfs_delayed_ref_root *delayed_refs, - struct btrfs_delayed_ref_node *ref, u64 seq) -{ - struct rb_node *node; - int merged = 0; - int mod = 0; - int done = 0; - - node = rb_prev(&ref->rb_node); - while (node) { - struct btrfs_delayed_ref_node *next; - - next = rb_entry(node, struct btrfs_delayed_ref_node, rb_node); - node = rb_prev(node); - if (next->bytenr != ref->bytenr) - break; - if (seq && next->seq >= seq) - break; - if (comp_entry(ref, next, 0)) - continue; - - if (ref->action == next->action) { - mod = next->ref_mod; - } else { - if (ref->ref_mod < next->ref_mod) { - struct btrfs_delayed_ref_node *tmp; - - tmp = ref; - ref = next; - next = tmp; - done = 1; - } - mod = -next->ref_mod; - } - - merged++; - drop_delayed_ref(trans, delayed_refs, next); - ref->ref_mod += mod; - if (ref->ref_mod == 0) { - drop_delayed_ref(trans, delayed_refs, ref); - break; - } else { - /* - * You can't have multiples of the same ref on a tree - * block. - */ - WARN_ON(ref->type == BTRFS_TREE_BLOCK_REF_KEY || - ref->type == BTRFS_SHARED_BLOCK_REF_KEY); - } - - if (done) - break; - node = rb_prev(&ref->rb_node); - } - - return merged; -} - -void btrfs_merge_delayed_refs(struct btrfs_trans_handle *trans, - struct btrfs_fs_info *fs_info, - struct btrfs_delayed_ref_root *delayed_refs, - struct btrfs_delayed_ref_head *head) -{ - struct rb_node *node; - u64 seq = 0; - - spin_lock(&fs_info->tree_mod_seq_lock); - if (!list_empty(&fs_info->tree_mod_seq_list)) { - struct seq_list *elem; - - elem = list_first_entry(&fs_info->tree_mod_seq_list, - struct seq_list, list); - seq = elem->seq; - } - spin_unlock(&fs_info->tree_mod_seq_lock); - - node = rb_prev(&head->node.rb_node); - while (node) { - struct btrfs_delayed_ref_node *ref; - - ref = rb_entry(node, struct btrfs_delayed_ref_node, - rb_node); - if (ref->bytenr != head->node.bytenr) - break; - - /* We can't merge refs that are outside of our seq count */ - if (seq && ref->seq >= seq) - break; - if (merge_ref(trans, delayed_refs, ref, seq)) - node = rb_prev(&head->node.rb_node); - else - node = rb_prev(node); - } -} - int btrfs_check_delayed_seq(struct btrfs_fs_info *fs_info, struct btrfs_delayed_ref_root *delayed_refs, u64 seq) @@ -444,11 +336,18 @@ update_existing_ref(struct btrfs_trans_handle *trans, * every changing the extent allocation tree. */ existing->ref_mod--; - if (existing->ref_mod == 0) - drop_delayed_ref(trans, delayed_refs, existing); - else + if (existing->ref_mod == 0) { + rb_erase(&existing->rb_node, + &delayed_refs->root); + existing->in_tree = 0; + btrfs_put_delayed_ref(existing); + delayed_refs->num_entries--; + if (trans->delayed_ref_updates) + trans->delayed_ref_updates--; + } else { WARN_ON(existing->type == BTRFS_TREE_BLOCK_REF_KEY || existing->type == BTRFS_SHARED_BLOCK_REF_KEY); + } } else { WARN_ON(existing->type == BTRFS_TREE_BLOCK_REF_KEY || existing->type == BTRFS_SHARED_BLOCK_REF_KEY); @@ -763,6 +662,9 @@ int btrfs_add_delayed_tree_ref(struct btrfs_fs_info *fs_info, add_delayed_tree_ref(fs_info, trans, &ref->node, bytenr, num_bytes, parent, ref_root, level, action, for_cow); + if (!need_ref_seq(for_cow, ref_root) && + waitqueue_active(&fs_info->tree_mod_seq_wait)) + wake_up(&fs_info->tree_mod_seq_wait); spin_unlock(&delayed_refs->lock); if (need_ref_seq(for_cow, ref_root)) btrfs_qgroup_record_ref(trans, &ref->node, extent_op); @@ -811,6 +713,9 @@ int btrfs_add_delayed_data_ref(struct btrfs_fs_info *fs_info, add_delayed_data_ref(fs_info, trans, &ref->node, bytenr, num_bytes, parent, ref_root, owner, offset, action, for_cow); + if (!need_ref_seq(for_cow, ref_root) && + waitqueue_active(&fs_info->tree_mod_seq_wait)) + wake_up(&fs_info->tree_mod_seq_wait); spin_unlock(&delayed_refs->lock); if (need_ref_seq(for_cow, ref_root)) btrfs_qgroup_record_ref(trans, &ref->node, extent_op); @@ -839,6 +744,8 @@ int btrfs_add_delayed_extent_op(struct btrfs_fs_info *fs_info, num_bytes, BTRFS_UPDATE_DELAYED_HEAD, extent_op->is_data); + if (waitqueue_active(&fs_info->tree_mod_seq_wait)) + wake_up(&fs_info->tree_mod_seq_wait); spin_unlock(&delayed_refs->lock); return 0; } diff --git a/trunk/fs/btrfs/delayed-ref.h b/trunk/fs/btrfs/delayed-ref.h index c9d703693df0..0d7c90c366b6 100644 --- a/trunk/fs/btrfs/delayed-ref.h +++ b/trunk/fs/btrfs/delayed-ref.h @@ -18,7 +18,7 @@ #ifndef __DELAYED_REF__ #define __DELAYED_REF__ -/* these are the possible values of struct btrfs_delayed_ref_node->action */ +/* these are the possible values of struct btrfs_delayed_ref->action */ #define BTRFS_ADD_DELAYED_REF 1 /* add one backref to the tree */ #define BTRFS_DROP_DELAYED_REF 2 /* delete one backref from the tree */ #define BTRFS_ADD_DELAYED_EXTENT 3 /* record a full extent allocation */ @@ -167,10 +167,6 @@ int btrfs_add_delayed_extent_op(struct btrfs_fs_info *fs_info, struct btrfs_trans_handle *trans, u64 bytenr, u64 num_bytes, struct btrfs_delayed_extent_op *extent_op); -void btrfs_merge_delayed_refs(struct btrfs_trans_handle *trans, - struct btrfs_fs_info *fs_info, - struct btrfs_delayed_ref_root *delayed_refs, - struct btrfs_delayed_ref_head *head); struct btrfs_delayed_ref_head * btrfs_find_delayed_ref_head(struct btrfs_trans_handle *trans, u64 bytenr); diff --git a/trunk/fs/btrfs/disk-io.c b/trunk/fs/btrfs/disk-io.c index 22e98e04c2ea..62e0cafd6e25 100644 --- a/trunk/fs/btrfs/disk-io.c +++ b/trunk/fs/btrfs/disk-io.c @@ -377,13 +377,9 @@ static int btree_read_extent_buffer_pages(struct btrfs_root *root, ret = read_extent_buffer_pages(io_tree, eb, start, WAIT_COMPLETE, btree_get_extent, mirror_num); - if (!ret) { - if (!verify_parent_transid(io_tree, eb, + if (!ret && !verify_parent_transid(io_tree, eb, parent_transid, 0)) - break; - else - ret = -EIO; - } + break; /* * This buffer's crc is fine, but its contents are corrupted, so @@ -758,7 +754,9 @@ static void run_one_async_done(struct btrfs_work *work) limit = btrfs_async_submit_limit(fs_info); limit = limit * 2 / 3; - if (atomic_dec_return(&fs_info->nr_async_submits) < limit && + atomic_dec(&fs_info->nr_async_submits); + + if (atomic_read(&fs_info->nr_async_submits) < limit && waitqueue_active(&fs_info->async_submit_wait)) wake_up(&fs_info->async_submit_wait); @@ -2034,6 +2032,8 @@ int open_ctree(struct super_block *sb, fs_info->free_chunk_space = 0; fs_info->tree_mod_log = RB_ROOT; + init_waitqueue_head(&fs_info->tree_mod_seq_wait); + /* readahead state */ INIT_RADIX_TREE(&fs_info->reada_tree, GFP_NOFS & ~__GFP_WAIT); spin_lock_init(&fs_info->reada_lock); @@ -2528,7 +2528,8 @@ int open_ctree(struct super_block *sb, goto fail_trans_kthread; /* do not make disk changes in broken FS */ - if (btrfs_super_log_root(disk_super) != 0) { + if (btrfs_super_log_root(disk_super) != 0 && + !(fs_info->fs_state & BTRFS_SUPER_FLAG_ERROR)) { u64 bytenr = btrfs_super_log_root(disk_super); if (fs_devices->rw_devices == 0) { @@ -3188,14 +3189,30 @@ int close_ctree(struct btrfs_root *root) /* clear out the rbtree of defraggable inodes */ btrfs_run_defrag_inodes(fs_info); + /* + * Here come 2 situations when btrfs is broken to flip readonly: + * + * 1. when btrfs flips readonly somewhere else before + * btrfs_commit_super, sb->s_flags has MS_RDONLY flag, + * and btrfs will skip to write sb directly to keep + * ERROR state on disk. + * + * 2. when btrfs flips readonly just in btrfs_commit_super, + * and in such case, btrfs cannot write sb via btrfs_commit_super, + * and since fs_state has been set BTRFS_SUPER_FLAG_ERROR flag, + * btrfs will cleanup all FS resources first and write sb then. + */ if (!(fs_info->sb->s_flags & MS_RDONLY)) { ret = btrfs_commit_super(root); if (ret) printk(KERN_ERR "btrfs: commit super ret %d\n", ret); } - if (fs_info->fs_state & BTRFS_SUPER_FLAG_ERROR) - btrfs_error_commit_super(root); + if (fs_info->fs_state & BTRFS_SUPER_FLAG_ERROR) { + ret = btrfs_error_commit_super(root); + if (ret) + printk(KERN_ERR "btrfs: commit super ret %d\n", ret); + } btrfs_put_block_group_cache(fs_info); @@ -3417,11 +3434,18 @@ static int btrfs_check_super_valid(struct btrfs_fs_info *fs_info, if (read_only) return 0; + if (fs_info->fs_state & BTRFS_SUPER_FLAG_ERROR) { + printk(KERN_WARNING "warning: mount fs with errors, " + "running btrfsck is recommended\n"); + } + return 0; } -void btrfs_error_commit_super(struct btrfs_root *root) +int btrfs_error_commit_super(struct btrfs_root *root) { + int ret; + mutex_lock(&root->fs_info->cleaner_mutex); btrfs_run_delayed_iputs(root); mutex_unlock(&root->fs_info->cleaner_mutex); @@ -3431,6 +3455,10 @@ void btrfs_error_commit_super(struct btrfs_root *root) /* cleanup FS via transaction */ btrfs_cleanup_transaction(root); + + ret = write_ctree_super(NULL, root, 0); + + return ret; } static void btrfs_destroy_ordered_operations(struct btrfs_root *root) @@ -3754,17 +3782,14 @@ int btrfs_cleanup_transaction(struct btrfs_root *root) /* FIXME: cleanup wait for commit */ t->in_commit = 1; t->blocked = 1; - smp_mb(); if (waitqueue_active(&root->fs_info->transaction_blocked_wait)) wake_up(&root->fs_info->transaction_blocked_wait); t->blocked = 0; - smp_mb(); if (waitqueue_active(&root->fs_info->transaction_wait)) wake_up(&root->fs_info->transaction_wait); t->commit_done = 1; - smp_mb(); if (waitqueue_active(&t->commit_wait)) wake_up(&t->commit_wait); diff --git a/trunk/fs/btrfs/disk-io.h b/trunk/fs/btrfs/disk-io.h index c5b00a735fef..95e147eea239 100644 --- a/trunk/fs/btrfs/disk-io.h +++ b/trunk/fs/btrfs/disk-io.h @@ -54,7 +54,7 @@ int write_ctree_super(struct btrfs_trans_handle *trans, struct btrfs_root *root, int max_mirrors); struct buffer_head *btrfs_read_dev_super(struct block_device *bdev); int btrfs_commit_super(struct btrfs_root *root); -void btrfs_error_commit_super(struct btrfs_root *root); +int btrfs_error_commit_super(struct btrfs_root *root); struct extent_buffer *btrfs_find_tree_block(struct btrfs_root *root, u64 bytenr, u32 blocksize); struct btrfs_root *btrfs_read_fs_root_no_radix(struct btrfs_root *tree_root, diff --git a/trunk/fs/btrfs/extent-tree.c b/trunk/fs/btrfs/extent-tree.c index ba58024d40d3..4e1b153b7c47 100644 --- a/trunk/fs/btrfs/extent-tree.c +++ b/trunk/fs/btrfs/extent-tree.c @@ -2251,16 +2251,6 @@ static noinline int run_clustered_refs(struct btrfs_trans_handle *trans, } } - /* - * We need to try and merge add/drops of the same ref since we - * can run into issues with relocate dropping the implicit ref - * and then it being added back again before the drop can - * finish. If we merged anything we need to re-loop so we can - * get a good ref. - */ - btrfs_merge_delayed_refs(trans, fs_info, delayed_refs, - locked_ref); - /* * locked_ref is the head node, so we have to go one * node back for any delayed ref updates @@ -2328,23 +2318,12 @@ static noinline int run_clustered_refs(struct btrfs_trans_handle *trans, ref->in_tree = 0; rb_erase(&ref->rb_node, &delayed_refs->root); delayed_refs->num_entries--; - if (locked_ref) { - /* - * when we play the delayed ref, also correct the - * ref_mod on head - */ - switch (ref->action) { - case BTRFS_ADD_DELAYED_REF: - case BTRFS_ADD_DELAYED_EXTENT: - locked_ref->node.ref_mod -= ref->ref_mod; - break; - case BTRFS_DROP_DELAYED_REF: - locked_ref->node.ref_mod += ref->ref_mod; - break; - default: - WARN_ON(1); - } - } + /* + * we modified num_entries, but as we're currently running + * delayed refs, skip + * wake_up(&delayed_refs->seq_wait); + * here. + */ spin_unlock(&delayed_refs->lock); ret = run_one_delayed_ref(trans, root, ref, extent_op, @@ -2371,6 +2350,22 @@ static noinline int run_clustered_refs(struct btrfs_trans_handle *trans, return count; } +static void wait_for_more_refs(struct btrfs_fs_info *fs_info, + struct btrfs_delayed_ref_root *delayed_refs, + unsigned long num_refs, + struct list_head *first_seq) +{ + spin_unlock(&delayed_refs->lock); + pr_debug("waiting for more refs (num %ld, first %p)\n", + num_refs, first_seq); + wait_event(fs_info->tree_mod_seq_wait, + num_refs != delayed_refs->num_entries || + fs_info->tree_mod_seq_list.next != first_seq); + pr_debug("done waiting for more refs (num %ld, first %p)\n", + delayed_refs->num_entries, fs_info->tree_mod_seq_list.next); + spin_lock(&delayed_refs->lock); +} + #ifdef SCRAMBLE_DELAYED_REFS /* * Normally delayed refs get processed in ascending bytenr order. This @@ -2465,11 +2460,13 @@ int btrfs_run_delayed_refs(struct btrfs_trans_handle *trans, struct btrfs_delayed_ref_root *delayed_refs; struct btrfs_delayed_ref_node *ref; struct list_head cluster; + struct list_head *first_seq = NULL; int ret; u64 delayed_start; int run_all = count == (unsigned long)-1; int run_most = 0; - int loops; + unsigned long num_refs = 0; + int consider_waiting; /* We'll clean this up in btrfs_cleanup_transaction */ if (trans->aborted) @@ -2487,7 +2484,7 @@ int btrfs_run_delayed_refs(struct btrfs_trans_handle *trans, delayed_refs = &trans->transaction->delayed_refs; INIT_LIST_HEAD(&cluster); again: - loops = 0; + consider_waiting = 0; spin_lock(&delayed_refs->lock); #ifdef SCRAMBLE_DELAYED_REFS @@ -2515,6 +2512,31 @@ int btrfs_run_delayed_refs(struct btrfs_trans_handle *trans, if (ret) break; + if (delayed_start >= delayed_refs->run_delayed_start) { + if (consider_waiting == 0) { + /* + * btrfs_find_ref_cluster looped. let's do one + * more cycle. if we don't run any delayed ref + * during that cycle (because we can't because + * all of them are blocked) and if the number of + * refs doesn't change, we avoid busy waiting. + */ + consider_waiting = 1; + num_refs = delayed_refs->num_entries; + first_seq = root->fs_info->tree_mod_seq_list.next; + } else { + wait_for_more_refs(root->fs_info, delayed_refs, + num_refs, first_seq); + /* + * after waiting, things have changed. we + * dropped the lock and someone else might have + * run some refs, built new clusters and so on. + * therefore, we restart staleness detection. + */ + consider_waiting = 0; + } + } + ret = run_clustered_refs(trans, root, &cluster); if (ret < 0) { spin_unlock(&delayed_refs->lock); @@ -2527,26 +2549,9 @@ int btrfs_run_delayed_refs(struct btrfs_trans_handle *trans, if (count == 0) break; - if (delayed_start >= delayed_refs->run_delayed_start) { - if (loops == 0) { - /* - * btrfs_find_ref_cluster looped. let's do one - * more cycle. if we don't run any delayed ref - * during that cycle (because we can't because - * all of them are blocked), bail out. - */ - loops = 1; - } else { - /* - * no runnable refs left, stop trying - */ - BUG_ON(run_all); - break; - } - } - if (ret) { + if (ret || delayed_refs->run_delayed_start == 0) { /* refs were run, let's reset staleness detection */ - loops = 0; + consider_waiting = 0; } } @@ -3002,16 +3007,17 @@ static int cache_save_setup(struct btrfs_block_group_cache *block_group, } spin_unlock(&block_group->lock); - /* - * Try to preallocate enough space based on how big the block group is. - * Keep in mind this has to include any pinned space which could end up - * taking up quite a bit since it's not folded into the other space - * cache. - */ - num_pages = (int)div64_u64(block_group->key.offset, 256 * 1024 * 1024); + num_pages = (int)div64_u64(block_group->key.offset, 1024 * 1024 * 1024); if (!num_pages) num_pages = 1; + /* + * Just to make absolutely sure we have enough space, we're going to + * preallocate 12 pages worth of space for each block group. In + * practice we ought to use at most 8, but we need extra space so we can + * add our header and have a terminator between the extents and the + * bitmaps. + */ num_pages *= 16; num_pages *= PAGE_CACHE_SIZE; @@ -4565,10 +4571,8 @@ int btrfs_delalloc_reserve_metadata(struct inode *inode, u64 num_bytes) if (root->fs_info->quota_enabled) { ret = btrfs_qgroup_reserve(root, num_bytes + nr_extents * root->leafsize); - if (ret) { - mutex_unlock(&BTRFS_I(inode)->delalloc_mutex); + if (ret) return ret; - } } ret = reserve_metadata_bytes(root, block_rsv, to_reserve, flush); @@ -5290,6 +5294,9 @@ static noinline int check_ref_cleanup(struct btrfs_trans_handle *trans, rb_erase(&head->node.rb_node, &delayed_refs->root); delayed_refs->num_entries--; + smp_mb(); + if (waitqueue_active(&root->fs_info->tree_mod_seq_wait)) + wake_up(&root->fs_info->tree_mod_seq_wait); /* * we don't take a ref on the node because we're removing it from the diff --git a/trunk/fs/btrfs/extent_io.c b/trunk/fs/btrfs/extent_io.c index 4c878476bb91..45c81bb4ac82 100644 --- a/trunk/fs/btrfs/extent_io.c +++ b/trunk/fs/btrfs/extent_io.c @@ -2330,10 +2330,23 @@ static void end_bio_extent_readpage(struct bio *bio, int err) if (uptodate && tree->ops && tree->ops->readpage_end_io_hook) { ret = tree->ops->readpage_end_io_hook(page, start, end, state, mirror); - if (ret) + if (ret) { + /* no IO indicated but software detected errors + * in the block, either checksum errors or + * issues with the contents */ + struct btrfs_root *root = + BTRFS_I(page->mapping->host)->root; + struct btrfs_device *device; + uptodate = 0; - else + device = btrfs_find_device_for_logical( + root, start, mirror); + if (device) + btrfs_dev_stat_inc_and_print(device, + BTRFS_DEV_STAT_CORRUPTION_ERRS); + } else { clean_io_failure(start, page); + } } if (!uptodate && tree->ops && tree->ops->readpage_io_failed_hook) { diff --git a/trunk/fs/btrfs/file-item.c b/trunk/fs/btrfs/file-item.c index 857d93cd01dc..b45b9de0c21d 100644 --- a/trunk/fs/btrfs/file-item.c +++ b/trunk/fs/btrfs/file-item.c @@ -272,9 +272,9 @@ int btrfs_lookup_bio_sums(struct btrfs_root *root, struct inode *inode, } int btrfs_lookup_bio_sums_dio(struct btrfs_root *root, struct inode *inode, - struct bio *bio, u64 offset) + struct bio *bio, u64 offset, u32 *dst) { - return __btrfs_lookup_bio_sums(root, inode, bio, offset, NULL, 1); + return __btrfs_lookup_bio_sums(root, inode, bio, offset, dst, 1); } int btrfs_lookup_csums_range(struct btrfs_root *root, u64 start, u64 end, diff --git a/trunk/fs/btrfs/inode.c b/trunk/fs/btrfs/inode.c index 316b07a866d2..83baec24946d 100644 --- a/trunk/fs/btrfs/inode.c +++ b/trunk/fs/btrfs/inode.c @@ -324,8 +324,7 @@ static noinline int add_async_extent(struct async_cow *cow, * If this code finds it can't get good compression, it puts an * entry onto the work queue to write the uncompressed bytes. This * makes sure that both compressed inodes and uncompressed inodes - * are written in the same order that the flusher thread sent them - * down. + * are written in the same order that pdflush sent them down. */ static noinline int compress_file_range(struct inode *inode, struct page *locked_page, @@ -1008,7 +1007,9 @@ static noinline void async_cow_submit(struct btrfs_work *work) nr_pages = (async_cow->end - async_cow->start + PAGE_CACHE_SIZE) >> PAGE_CACHE_SHIFT; - if (atomic_sub_return(nr_pages, &root->fs_info->async_delalloc_pages) < + atomic_sub(nr_pages, &root->fs_info->async_delalloc_pages); + + if (atomic_read(&root->fs_info->async_delalloc_pages) < 5 * 1024 * 1024 && waitqueue_active(&root->fs_info->async_submit_wait)) wake_up(&root->fs_info->async_submit_wait); @@ -1883,11 +1884,8 @@ static int btrfs_finish_ordered_io(struct btrfs_ordered_extent *ordered_extent) trans = btrfs_join_transaction_nolock(root); else trans = btrfs_join_transaction(root); - if (IS_ERR(trans)) { - ret = PTR_ERR(trans); - trans = NULL; - goto out; - } + if (IS_ERR(trans)) + return PTR_ERR(trans); trans->block_rsv = &root->fs_info->delalloc_block_rsv; ret = btrfs_update_inode_fallback(trans, root, inode); if (ret) /* -ENOMEM or corruption */ @@ -1971,8 +1969,8 @@ static int btrfs_finish_ordered_io(struct btrfs_ordered_extent *ordered_extent) ordered_extent->len - 1, NULL, GFP_NOFS); /* - * This needs to be done to make sure anybody waiting knows we are done - * updating everything for this ordered extent. + * This needs to be dont to make sure anybody waiting knows we are done + * upating everything for this ordered extent. */ btrfs_remove_ordered_extent(inode, ordered_extent); @@ -3175,7 +3173,7 @@ int btrfs_unlink_subvol(struct btrfs_trans_handle *trans, btrfs_i_size_write(dir, dir->i_size - name_len * 2); inode_inc_iversion(dir); dir->i_mtime = dir->i_ctime = CURRENT_TIME; - ret = btrfs_update_inode_fallback(trans, root, dir); + ret = btrfs_update_inode(trans, root, dir); if (ret) btrfs_abort_transaction(trans, root, ret); out: @@ -5775,112 +5773,18 @@ static noinline int can_nocow_odirect(struct btrfs_trans_handle *trans, return ret; } -static int lock_extent_direct(struct inode *inode, u64 lockstart, u64 lockend, - struct extent_state **cached_state, int writing) -{ - struct btrfs_ordered_extent *ordered; - int ret = 0; - - while (1) { - lock_extent_bits(&BTRFS_I(inode)->io_tree, lockstart, lockend, - 0, cached_state); - /* - * We're concerned with the entire range that we're going to be - * doing DIO to, so we need to make sure theres no ordered - * extents in this range. - */ - ordered = btrfs_lookup_ordered_range(inode, lockstart, - lockend - lockstart + 1); - - /* - * We need to make sure there are no buffered pages in this - * range either, we could have raced between the invalidate in - * generic_file_direct_write and locking the extent. The - * invalidate needs to happen so that reads after a write do not - * get stale data. - */ - if (!ordered && (!writing || - !test_range_bit(&BTRFS_I(inode)->io_tree, - lockstart, lockend, EXTENT_UPTODATE, 0, - *cached_state))) - break; - - unlock_extent_cached(&BTRFS_I(inode)->io_tree, lockstart, lockend, - cached_state, GFP_NOFS); - - if (ordered) { - btrfs_start_ordered_extent(inode, ordered, 1); - btrfs_put_ordered_extent(ordered); - } else { - /* Screw you mmap */ - ret = filemap_write_and_wait_range(inode->i_mapping, - lockstart, - lockend); - if (ret) - break; - - /* - * If we found a page that couldn't be invalidated just - * fall back to buffered. - */ - ret = invalidate_inode_pages2_range(inode->i_mapping, - lockstart >> PAGE_CACHE_SHIFT, - lockend >> PAGE_CACHE_SHIFT); - if (ret) - break; - } - - cond_resched(); - } - - return ret; -} - static int btrfs_get_blocks_direct(struct inode *inode, sector_t iblock, struct buffer_head *bh_result, int create) { struct extent_map *em; struct btrfs_root *root = BTRFS_I(inode)->root; - struct extent_state *cached_state = NULL; u64 start = iblock << inode->i_blkbits; - u64 lockstart, lockend; u64 len = bh_result->b_size; struct btrfs_trans_handle *trans; - int unlock_bits = EXTENT_LOCKED; - int ret; - - if (create) { - ret = btrfs_delalloc_reserve_space(inode, len); - if (ret) - return ret; - unlock_bits |= EXTENT_DELALLOC | EXTENT_DIRTY; - } else { - len = min_t(u64, len, root->sectorsize); - } - - lockstart = start; - lockend = start + len - 1; - - /* - * If this errors out it's because we couldn't invalidate pagecache for - * this range and we need to fallback to buffered. - */ - if (lock_extent_direct(inode, lockstart, lockend, &cached_state, create)) - return -ENOTBLK; - - if (create) { - ret = set_extent_bit(&BTRFS_I(inode)->io_tree, lockstart, - lockend, EXTENT_DELALLOC, NULL, - &cached_state, GFP_NOFS); - if (ret) - goto unlock_err; - } em = btrfs_get_extent(inode, NULL, 0, start, len, 0); - if (IS_ERR(em)) { - ret = PTR_ERR(em); - goto unlock_err; - } + if (IS_ERR(em)) + return PTR_ERR(em); /* * Ok for INLINE and COMPRESSED extents we need to fallback on buffered @@ -5899,16 +5803,17 @@ static int btrfs_get_blocks_direct(struct inode *inode, sector_t iblock, if (test_bit(EXTENT_FLAG_COMPRESSED, &em->flags) || em->block_start == EXTENT_MAP_INLINE) { free_extent_map(em); - ret = -ENOTBLK; - goto unlock_err; + return -ENOTBLK; } /* Just a good old fashioned hole, return */ if (!create && (em->block_start == EXTENT_MAP_HOLE || test_bit(EXTENT_FLAG_PREALLOC, &em->flags))) { free_extent_map(em); - ret = 0; - goto unlock_err; + /* DIO will do one hole at a time, so just unlock a sector */ + unlock_extent(&BTRFS_I(inode)->io_tree, start, + start + root->sectorsize - 1); + return 0; } /* @@ -5921,9 +5826,8 @@ static int btrfs_get_blocks_direct(struct inode *inode, sector_t iblock, * */ if (!create) { - len = min(len, em->len - (start - em->start)); - lockstart = start + len; - goto unlock; + len = em->len - (start - em->start); + goto map; } if (test_bit(EXTENT_FLAG_PREALLOC, &em->flags) || @@ -5955,7 +5859,7 @@ static int btrfs_get_blocks_direct(struct inode *inode, sector_t iblock, btrfs_end_transaction(trans, root); if (ret) { free_extent_map(em); - goto unlock_err; + return ret; } goto unlock; } @@ -5968,12 +5872,14 @@ static int btrfs_get_blocks_direct(struct inode *inode, sector_t iblock, */ len = bh_result->b_size; em = btrfs_new_extent_direct(inode, em, start, len); - if (IS_ERR(em)) { - ret = PTR_ERR(em); - goto unlock_err; - } + if (IS_ERR(em)) + return PTR_ERR(em); len = min(len, em->len - (start - em->start)); unlock: + clear_extent_bit(&BTRFS_I(inode)->io_tree, start, start + len - 1, + EXTENT_LOCKED | EXTENT_DELALLOC | EXTENT_DIRTY, 1, + 0, NULL, GFP_NOFS); +map: bh_result->b_blocknr = (em->block_start + (start - em->start)) >> inode->i_blkbits; bh_result->b_size = len; @@ -5991,44 +5897,9 @@ static int btrfs_get_blocks_direct(struct inode *inode, sector_t iblock, i_size_write(inode, start + len); } - /* - * In the case of write we need to clear and unlock the entire range, - * in the case of read we need to unlock only the end area that we - * aren't using if there is any left over space. - */ - if (lockstart < lockend) { - if (create && len < lockend - lockstart) { - clear_extent_bit(&BTRFS_I(inode)->io_tree, lockstart, - lockstart + len - 1, unlock_bits, 1, 0, - &cached_state, GFP_NOFS); - /* - * Beside unlock, we also need to cleanup reserved space - * for the left range by attaching EXTENT_DO_ACCOUNTING. - */ - clear_extent_bit(&BTRFS_I(inode)->io_tree, - lockstart + len, lockend, - unlock_bits | EXTENT_DO_ACCOUNTING, - 1, 0, NULL, GFP_NOFS); - } else { - clear_extent_bit(&BTRFS_I(inode)->io_tree, lockstart, - lockend, unlock_bits, 1, 0, - &cached_state, GFP_NOFS); - } - } else { - free_extent_state(cached_state); - } - free_extent_map(em); return 0; - -unlock_err: - if (create) - unlock_bits |= EXTENT_DO_ACCOUNTING; - - clear_extent_bit(&BTRFS_I(inode)->io_tree, lockstart, lockend, - unlock_bits, 1, 0, &cached_state, GFP_NOFS); - return ret; } struct btrfs_dio_private { @@ -6036,6 +5907,7 @@ struct btrfs_dio_private { u64 logical_offset; u64 disk_bytenr; u64 bytes; + u32 *csums; void *private; /* number of bios pending for this dio */ @@ -6055,6 +5927,7 @@ static void btrfs_endio_direct_read(struct bio *bio, int err) struct inode *inode = dip->inode; struct btrfs_root *root = BTRFS_I(inode)->root; u64 start; + u32 *private = dip->csums; start = dip->logical_offset; do { @@ -6062,12 +5935,8 @@ static void btrfs_endio_direct_read(struct bio *bio, int err) struct page *page = bvec->bv_page; char *kaddr; u32 csum = ~(u32)0; - u64 private = ~(u32)0; unsigned long flags; - if (get_state_private(&BTRFS_I(inode)->io_tree, - start, &private)) - goto failed; local_irq_save(flags); kaddr = kmap_atomic(page); csum = btrfs_csum_data(root, kaddr + bvec->bv_offset, @@ -6077,18 +5946,18 @@ static void btrfs_endio_direct_read(struct bio *bio, int err) local_irq_restore(flags); flush_dcache_page(bvec->bv_page); - if (csum != private) { -failed: + if (csum != *private) { printk(KERN_ERR "btrfs csum failed ino %llu off" " %llu csum %u private %u\n", (unsigned long long)btrfs_ino(inode), (unsigned long long)start, - csum, (unsigned)private); + csum, *private); err = -EIO; } } start += bvec->bv_len; + private++; bvec++; } while (bvec <= bvec_end); @@ -6096,6 +5965,7 @@ static void btrfs_endio_direct_read(struct bio *bio, int err) dip->logical_offset + dip->bytes - 1); bio->bi_private = dip->private; + kfree(dip->csums); kfree(dip); /* If we had a csum failure make sure to clear the uptodate flag */ @@ -6201,7 +6071,7 @@ static struct bio *btrfs_dio_bio_alloc(struct block_device *bdev, static inline int __btrfs_submit_dio_bio(struct bio *bio, struct inode *inode, int rw, u64 file_offset, int skip_sum, - int async_submit) + u32 *csums, int async_submit) { int write = rw & REQ_WRITE; struct btrfs_root *root = BTRFS_I(inode)->root; @@ -6234,7 +6104,8 @@ static inline int __btrfs_submit_dio_bio(struct bio *bio, struct inode *inode, if (ret) goto err; } else if (!skip_sum) { - ret = btrfs_lookup_bio_sums_dio(root, inode, bio, file_offset); + ret = btrfs_lookup_bio_sums_dio(root, inode, bio, + file_offset, csums); if (ret) goto err; } @@ -6260,8 +6131,10 @@ static int btrfs_submit_direct_hook(int rw, struct btrfs_dio_private *dip, u64 submit_len = 0; u64 map_length; int nr_pages = 0; + u32 *csums = dip->csums; int ret = 0; int async_submit = 0; + int write = rw & REQ_WRITE; map_length = orig_bio->bi_size; ret = btrfs_map_block(map_tree, READ, start_sector << 9, @@ -6297,13 +6170,16 @@ static int btrfs_submit_direct_hook(int rw, struct btrfs_dio_private *dip, atomic_inc(&dip->pending_bios); ret = __btrfs_submit_dio_bio(bio, inode, rw, file_offset, skip_sum, - async_submit); + csums, async_submit); if (ret) { bio_put(bio); atomic_dec(&dip->pending_bios); goto out_err; } + /* Write's use the ordered csums */ + if (!write && !skip_sum) + csums = csums + nr_pages; start_sector += submit_len >> 9; file_offset += submit_len; @@ -6333,7 +6209,7 @@ static int btrfs_submit_direct_hook(int rw, struct btrfs_dio_private *dip, submit: ret = __btrfs_submit_dio_bio(bio, inode, rw, file_offset, skip_sum, - async_submit); + csums, async_submit); if (!ret) return 0; @@ -6369,6 +6245,17 @@ static void btrfs_submit_direct(int rw, struct bio *bio, struct inode *inode, ret = -ENOMEM; goto free_ordered; } + dip->csums = NULL; + + /* Write's use the ordered csum stuff, so we don't need dip->csums */ + if (!write && !skip_sum) { + dip->csums = kmalloc(sizeof(u32) * bio->bi_vcnt, GFP_NOFS); + if (!dip->csums) { + kfree(dip); + ret = -ENOMEM; + goto free_ordered; + } + } dip->private = bio->bi_private; dip->inode = inode; @@ -6453,22 +6340,132 @@ static ssize_t check_direct_IO(struct btrfs_root *root, int rw, struct kiocb *io out: return retval; } - static ssize_t btrfs_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov, loff_t offset, unsigned long nr_segs) { struct file *file = iocb->ki_filp; struct inode *inode = file->f_mapping->host; + struct btrfs_ordered_extent *ordered; + struct extent_state *cached_state = NULL; + u64 lockstart, lockend; + ssize_t ret; + int writing = rw & WRITE; + int write_bits = 0; + size_t count = iov_length(iov, nr_segs); if (check_direct_IO(BTRFS_I(inode)->root, rw, iocb, iov, - offset, nr_segs)) + offset, nr_segs)) { return 0; + } + + lockstart = offset; + lockend = offset + count - 1; + + if (writing) { + ret = btrfs_delalloc_reserve_space(inode, count); + if (ret) + goto out; + } + + while (1) { + lock_extent_bits(&BTRFS_I(inode)->io_tree, lockstart, lockend, + 0, &cached_state); + /* + * We're concerned with the entire range that we're going to be + * doing DIO to, so we need to make sure theres no ordered + * extents in this range. + */ + ordered = btrfs_lookup_ordered_range(inode, lockstart, + lockend - lockstart + 1); + + /* + * We need to make sure there are no buffered pages in this + * range either, we could have raced between the invalidate in + * generic_file_direct_write and locking the extent. The + * invalidate needs to happen so that reads after a write do not + * get stale data. + */ + if (!ordered && (!writing || + !test_range_bit(&BTRFS_I(inode)->io_tree, + lockstart, lockend, EXTENT_UPTODATE, 0, + cached_state))) + break; + + unlock_extent_cached(&BTRFS_I(inode)->io_tree, lockstart, lockend, + &cached_state, GFP_NOFS); + + if (ordered) { + btrfs_start_ordered_extent(inode, ordered, 1); + btrfs_put_ordered_extent(ordered); + } else { + /* Screw you mmap */ + ret = filemap_write_and_wait_range(file->f_mapping, + lockstart, + lockend); + if (ret) + goto out; + + /* + * If we found a page that couldn't be invalidated just + * fall back to buffered. + */ + ret = invalidate_inode_pages2_range(file->f_mapping, + lockstart >> PAGE_CACHE_SHIFT, + lockend >> PAGE_CACHE_SHIFT); + if (ret) { + if (ret == -EBUSY) + ret = 0; + goto out; + } + } + + cond_resched(); + } - return __blockdev_direct_IO(rw, iocb, inode, + /* + * we don't use btrfs_set_extent_delalloc because we don't want + * the dirty or uptodate bits + */ + if (writing) { + write_bits = EXTENT_DELALLOC | EXTENT_DO_ACCOUNTING; + ret = set_extent_bit(&BTRFS_I(inode)->io_tree, lockstart, lockend, + EXTENT_DELALLOC, NULL, &cached_state, + GFP_NOFS); + if (ret) { + clear_extent_bit(&BTRFS_I(inode)->io_tree, lockstart, + lockend, EXTENT_LOCKED | write_bits, + 1, 0, &cached_state, GFP_NOFS); + goto out; + } + } + + free_extent_state(cached_state); + cached_state = NULL; + + ret = __blockdev_direct_IO(rw, iocb, inode, BTRFS_I(inode)->root->fs_info->fs_devices->latest_bdev, iov, offset, nr_segs, btrfs_get_blocks_direct, NULL, btrfs_submit_direct, 0); + + if (ret < 0 && ret != -EIOCBQUEUED) { + clear_extent_bit(&BTRFS_I(inode)->io_tree, offset, + offset + iov_length(iov, nr_segs) - 1, + EXTENT_LOCKED | write_bits, 1, 0, + &cached_state, GFP_NOFS); + } else if (ret >= 0 && ret < iov_length(iov, nr_segs)) { + /* + * We're falling back to buffered, unlock the section we didn't + * do IO on. + */ + clear_extent_bit(&BTRFS_I(inode)->io_tree, offset + ret, + offset + iov_length(iov, nr_segs) - 1, + EXTENT_LOCKED | write_bits, 1, 0, + &cached_state, GFP_NOFS); + } +out: + free_extent_state(cached_state); + return ret; } static int btrfs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, diff --git a/trunk/fs/btrfs/ioctl.c b/trunk/fs/btrfs/ioctl.c index 9df50fa8a078..bc2f6ffff3cf 100644 --- a/trunk/fs/btrfs/ioctl.c +++ b/trunk/fs/btrfs/ioctl.c @@ -424,7 +424,7 @@ static noinline int create_subvol(struct btrfs_root *root, uuid_le_gen(&new_uuid); memcpy(root_item.uuid, new_uuid.b, BTRFS_UUID_SIZE); root_item.otime.sec = cpu_to_le64(cur_time.tv_sec); - root_item.otime.nsec = cpu_to_le32(cur_time.tv_nsec); + root_item.otime.nsec = cpu_to_le64(cur_time.tv_nsec); root_item.ctime = root_item.otime; btrfs_set_root_ctransid(&root_item, trans->transid); btrfs_set_root_otransid(&root_item, trans->transid); @@ -664,6 +664,10 @@ static noinline int btrfs_mksubvol(struct path *parent, struct dentry *dentry; int error; + error = mnt_want_write(parent->mnt); + if (error) + return error; + mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT); dentry = lookup_one_len(name, parent->dentry, namelen); @@ -699,6 +703,7 @@ static noinline int btrfs_mksubvol(struct path *parent, dput(dentry); out_unlock: mutex_unlock(&dir->i_mutex); + mnt_drop_write(parent->mnt); return error; } diff --git a/trunk/fs/btrfs/locking.c b/trunk/fs/btrfs/locking.c index 2a1762c66041..a44eff074805 100644 --- a/trunk/fs/btrfs/locking.c +++ b/trunk/fs/btrfs/locking.c @@ -67,7 +67,7 @@ void btrfs_clear_lock_blocking_rw(struct extent_buffer *eb, int rw) { if (eb->lock_nested) { read_lock(&eb->lock); - if (eb->lock_nested && current->pid == eb->lock_owner) { + if (&eb->lock_nested && current->pid == eb->lock_owner) { read_unlock(&eb->lock); return; } diff --git a/trunk/fs/btrfs/ordered-data.c b/trunk/fs/btrfs/ordered-data.c index 051c7fe551dd..643335a4fe3c 100644 --- a/trunk/fs/btrfs/ordered-data.c +++ b/trunk/fs/btrfs/ordered-data.c @@ -596,7 +596,7 @@ void btrfs_start_ordered_extent(struct inode *inode, /* * pages in the range can be dirty, clean or writeback. We * start IO on any dirty ones so the wait doesn't stall waiting - * for the flusher thread to find them + * for pdflush to find them */ if (!test_bit(BTRFS_ORDERED_DIRECT, &entry->flags)) filemap_fdatawrite_range(inode->i_mapping, start, end); diff --git a/trunk/fs/btrfs/qgroup.c b/trunk/fs/btrfs/qgroup.c index b65015581744..bc424ae5a81a 100644 --- a/trunk/fs/btrfs/qgroup.c +++ b/trunk/fs/btrfs/qgroup.c @@ -1364,10 +1364,8 @@ int btrfs_qgroup_inherit(struct btrfs_trans_handle *trans, spin_lock(&fs_info->qgroup_lock); dstgroup = add_qgroup_rb(fs_info, objectid); - if (IS_ERR(dstgroup)) { - ret = PTR_ERR(dstgroup); + if (!dstgroup) goto unlock; - } if (srcid) { srcgroup = find_qgroup_rb(fs_info, srcid); diff --git a/trunk/fs/btrfs/root-tree.c b/trunk/fs/btrfs/root-tree.c index 10d8e4d88071..6bb465cca20f 100644 --- a/trunk/fs/btrfs/root-tree.c +++ b/trunk/fs/btrfs/root-tree.c @@ -544,8 +544,8 @@ void btrfs_update_root_times(struct btrfs_trans_handle *trans, struct timespec ct = CURRENT_TIME; spin_lock(&root->root_times_lock); - item->ctransid = cpu_to_le64(trans->transid); + item->ctransid = trans->transid; item->ctime.sec = cpu_to_le64(ct.tv_sec); - item->ctime.nsec = cpu_to_le32(ct.tv_nsec); + item->ctime.nsec = cpu_to_le64(ct.tv_nsec); spin_unlock(&root->root_times_lock); } diff --git a/trunk/fs/btrfs/super.c b/trunk/fs/btrfs/super.c index 83d6f9f9c220..8c6e61d6eed5 100644 --- a/trunk/fs/btrfs/super.c +++ b/trunk/fs/btrfs/super.c @@ -100,6 +100,10 @@ static void __save_error_info(struct btrfs_fs_info *fs_info) fs_info->fs_state = BTRFS_SUPER_FLAG_ERROR; } +/* NOTE: + * We move write_super stuff at umount in order to avoid deadlock + * for umount hold all lock. + */ static void save_error_info(struct btrfs_fs_info *fs_info) { __save_error_info(fs_info); @@ -838,6 +842,7 @@ int btrfs_sync_fs(struct super_block *sb, int wait) struct btrfs_trans_handle *trans; struct btrfs_fs_info *fs_info = btrfs_sb(sb); struct btrfs_root *root = fs_info->tree_root; + int ret; trace_btrfs_sync_fs(wait); @@ -848,17 +853,11 @@ int btrfs_sync_fs(struct super_block *sb, int wait) btrfs_wait_ordered_extents(root, 0, 0); - spin_lock(&fs_info->trans_lock); - if (!fs_info->running_transaction) { - spin_unlock(&fs_info->trans_lock); - return 0; - } - spin_unlock(&fs_info->trans_lock); - - trans = btrfs_join_transaction(root); + trans = btrfs_start_transaction(root, 0); if (IS_ERR(trans)) return PTR_ERR(trans); - return btrfs_commit_transaction(trans, root); + ret = btrfs_commit_transaction(trans, root); + return ret; } static int btrfs_show_options(struct seq_file *seq, struct dentry *dentry) @@ -1535,8 +1534,6 @@ static int btrfs_show_devname(struct seq_file *m, struct dentry *root) while (cur_devices) { head = &cur_devices->devices; list_for_each_entry(dev, head, dev_list) { - if (dev->missing) - continue; if (!first_dev || dev->devid < first_dev->devid) first_dev = dev; } diff --git a/trunk/fs/btrfs/transaction.c b/trunk/fs/btrfs/transaction.c index 27c26004e050..17be3dedacba 100644 --- a/trunk/fs/btrfs/transaction.c +++ b/trunk/fs/btrfs/transaction.c @@ -1031,7 +1031,6 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans, btrfs_i_size_write(parent_inode, parent_inode->i_size + dentry->d_name.len * 2); - parent_inode->i_mtime = parent_inode->i_ctime = CURRENT_TIME; ret = btrfs_update_inode(trans, parent_root, parent_inode); if (ret) goto abort_trans_dput; @@ -1067,7 +1066,7 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans, memcpy(new_root_item->parent_uuid, root->root_item.uuid, BTRFS_UUID_SIZE); new_root_item->otime.sec = cpu_to_le64(cur_time.tv_sec); - new_root_item->otime.nsec = cpu_to_le32(cur_time.tv_nsec); + new_root_item->otime.nsec = cpu_to_le64(cur_time.tv_nsec); btrfs_set_root_otransid(new_root_item, trans->transid); memset(&new_root_item->stime, 0, sizeof(new_root_item->stime)); memset(&new_root_item->rtime, 0, sizeof(new_root_item->rtime)); diff --git a/trunk/fs/btrfs/volumes.c b/trunk/fs/btrfs/volumes.c index 88b969aeeb71..b8708f994e67 100644 --- a/trunk/fs/btrfs/volumes.c +++ b/trunk/fs/btrfs/volumes.c @@ -227,8 +227,9 @@ static noinline void run_scheduled_bios(struct btrfs_device *device) cur = pending; pending = pending->bi_next; cur->bi_next = NULL; + atomic_dec(&fs_info->nr_async_bios); - if (atomic_dec_return(&fs_info->nr_async_bios) < limit && + if (atomic_read(&fs_info->nr_async_bios) < limit && waitqueue_active(&fs_info->async_submit_wait)) wake_up(&fs_info->async_submit_wait); @@ -568,11 +569,9 @@ static int __btrfs_close_devices(struct btrfs_fs_devices *fs_devices) memcpy(new_device, device, sizeof(*new_device)); /* Safe because we are under uuid_mutex */ - if (device->name) { - name = rcu_string_strdup(device->name->str, GFP_NOFS); - BUG_ON(device->name && !name); /* -ENOMEM */ - rcu_assign_pointer(new_device->name, name); - } + name = rcu_string_strdup(device->name->str, GFP_NOFS); + BUG_ON(device->name && !name); /* -ENOMEM */ + rcu_assign_pointer(new_device->name, name); new_device->bdev = NULL; new_device->writeable = 0; new_device->in_fs_metadata = 0; @@ -1745,6 +1744,10 @@ int btrfs_init_new_device(struct btrfs_root *root, char *device_path) device->fs_devices = root->fs_info->fs_devices; + /* + * we don't want write_supers to jump in here with our device + * half setup + */ mutex_lock(&root->fs_info->fs_devices->device_list_mutex); list_add_rcu(&device->dev_list, &root->fs_info->fs_devices->devices); list_add(&device->dev_alloc_list, @@ -4606,6 +4609,28 @@ int btrfs_read_sys_array(struct btrfs_root *root) return ret; } +struct btrfs_device *btrfs_find_device_for_logical(struct btrfs_root *root, + u64 logical, int mirror_num) +{ + struct btrfs_mapping_tree *map_tree = &root->fs_info->mapping_tree; + int ret; + u64 map_length = 0; + struct btrfs_bio *bbio = NULL; + struct btrfs_device *device; + + BUG_ON(mirror_num == 0); + ret = btrfs_map_block(map_tree, WRITE, logical, &map_length, &bbio, + mirror_num); + if (ret) { + BUG_ON(bbio != NULL); + return NULL; + } + BUG_ON(mirror_num != bbio->mirror_num); + device = bbio->stripes[mirror_num - 1].dev; + kfree(bbio); + return device; +} + int btrfs_read_chunk_tree(struct btrfs_root *root) { struct btrfs_path *path; diff --git a/trunk/fs/btrfs/volumes.h b/trunk/fs/btrfs/volumes.h index 53c06af92e8d..5479325987b3 100644 --- a/trunk/fs/btrfs/volumes.h +++ b/trunk/fs/btrfs/volumes.h @@ -289,6 +289,8 @@ int btrfs_cancel_balance(struct btrfs_fs_info *fs_info); int btrfs_chunk_readonly(struct btrfs_root *root, u64 chunk_offset); int find_free_dev_extent(struct btrfs_device *device, u64 num_bytes, u64 *start, u64 *max_avail); +struct btrfs_device *btrfs_find_device_for_logical(struct btrfs_root *root, + u64 logical, int mirror_num); void btrfs_dev_stat_print_on_error(struct btrfs_device *device); void btrfs_dev_stat_inc_and_print(struct btrfs_device *dev, int index); int btrfs_get_dev_stats(struct btrfs_root *root, diff --git a/trunk/fs/buffer.c b/trunk/fs/buffer.c index 58e2e7b77372..9f6d2e41281d 100644 --- a/trunk/fs/buffer.c +++ b/trunk/fs/buffer.c @@ -914,7 +914,7 @@ link_dev_buffers(struct page *page, struct buffer_head *head) /* * Initialise the state of a blockdev page's buffers. */ -static sector_t +static void init_page_buffers(struct page *page, struct block_device *bdev, sector_t block, int size) { @@ -936,41 +936,33 @@ init_page_buffers(struct page *page, struct block_device *bdev, block++; bh = bh->b_this_page; } while (bh != head); - - /* - * Caller needs to validate requested block against end of device. - */ - return end_block; } /* * Create the page-cache page that contains the requested block. * - * This is used purely for blockdev mappings. + * This is user purely for blockdev mappings. */ -static int +static struct page * grow_dev_page(struct block_device *bdev, sector_t block, - pgoff_t index, int size, int sizebits) + pgoff_t index, int size) { struct inode *inode = bdev->bd_inode; struct page *page; struct buffer_head *bh; - sector_t end_block; - int ret = 0; /* Will call free_more_memory() */ page = find_or_create_page(inode->i_mapping, index, (mapping_gfp_mask(inode->i_mapping) & ~__GFP_FS)|__GFP_MOVABLE); if (!page) - return ret; + return NULL; BUG_ON(!PageLocked(page)); if (page_has_buffers(page)) { bh = page_buffers(page); if (bh->b_size == size) { - end_block = init_page_buffers(page, bdev, - index << sizebits, size); - goto done; + init_page_buffers(page, bdev, block, size); + return page; } if (!try_to_free_buffers(page)) goto failed; @@ -990,14 +982,14 @@ grow_dev_page(struct block_device *bdev, sector_t block, */ spin_lock(&inode->i_mapping->private_lock); link_dev_buffers(page, bh); - end_block = init_page_buffers(page, bdev, index << sizebits, size); + init_page_buffers(page, bdev, block, size); spin_unlock(&inode->i_mapping->private_lock); -done: - ret = (block < end_block) ? 1 : -ENXIO; + return page; + failed: unlock_page(page); page_cache_release(page); - return ret; + return NULL; } /* @@ -1007,6 +999,7 @@ grow_dev_page(struct block_device *bdev, sector_t block, static int grow_buffers(struct block_device *bdev, sector_t block, int size) { + struct page *page; pgoff_t index; int sizebits; @@ -1030,14 +1023,22 @@ grow_buffers(struct block_device *bdev, sector_t block, int size) bdevname(bdev, b)); return -EIO; } - + block = index << sizebits; /* Create a page with the proper size buffers.. */ - return grow_dev_page(bdev, block, index, size, sizebits); + page = grow_dev_page(bdev, block, index, size); + if (!page) + return 0; + unlock_page(page); + page_cache_release(page); + return 1; } static struct buffer_head * __getblk_slow(struct block_device *bdev, sector_t block, int size) { + int ret; + struct buffer_head *bh; + /* Size must be multiple of hard sectorsize */ if (unlikely(size & (bdev_logical_block_size(bdev)-1) || (size < 512 || size > PAGE_SIZE))) { @@ -1050,20 +1051,21 @@ __getblk_slow(struct block_device *bdev, sector_t block, int size) return NULL; } - for (;;) { - struct buffer_head *bh; - int ret; +retry: + bh = __find_get_block(bdev, block, size); + if (bh) + return bh; + ret = grow_buffers(bdev, block, size); + if (ret == 0) { + free_more_memory(); + goto retry; + } else if (ret > 0) { bh = __find_get_block(bdev, block, size); if (bh) return bh; - - ret = grow_buffers(bdev, block, size); - if (ret < 0) - return NULL; - if (ret == 0) - free_more_memory(); } + return NULL; } /* @@ -1319,6 +1321,10 @@ EXPORT_SYMBOL(__find_get_block); * which corresponds to the passed block_device, block and size. The * returned buffer has its reference count incremented. * + * __getblk() cannot fail - it just keeps trying. If you pass it an + * illegal block number, __getblk() will happily return a buffer_head + * which represents the non-existent block. Very weird. + * * __getblk() will lock up the machine if grow_dev_page's try_to_free_buffers() * attempt is failing. FIXME, perhaps? */ diff --git a/trunk/fs/ceph/debugfs.c b/trunk/fs/ceph/debugfs.c index 6d59006bfa27..fb962efdacee 100644 --- a/trunk/fs/ceph/debugfs.c +++ b/trunk/fs/ceph/debugfs.c @@ -201,7 +201,6 @@ int ceph_fs_debugfs_init(struct ceph_fs_client *fsc) int err = -ENOMEM; dout("ceph_fs_debugfs_init\n"); - BUG_ON(!fsc->client->debugfs_dir); fsc->debugfs_congestion_kb = debugfs_create_file("writeback_congestion_kb", 0600, diff --git a/trunk/fs/ceph/inode.c b/trunk/fs/ceph/inode.c index 4b5762ef7c2b..9fff9f3b17e4 100644 --- a/trunk/fs/ceph/inode.c +++ b/trunk/fs/ceph/inode.c @@ -992,15 +992,11 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req, if (rinfo->head->is_dentry) { struct inode *dir = req->r_locked_dir; - if (dir) { - err = fill_inode(dir, &rinfo->diri, rinfo->dirfrag, - session, req->r_request_started, -1, - &req->r_caps_reservation); - if (err < 0) - return err; - } else { - WARN_ON_ONCE(1); - } + err = fill_inode(dir, &rinfo->diri, rinfo->dirfrag, + session, req->r_request_started, -1, + &req->r_caps_reservation); + if (err < 0) + return err; } /* @@ -1008,7 +1004,6 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req, * will have trouble splicing in the virtual snapdir later */ if (rinfo->head->is_dentry && !req->r_aborted && - req->r_locked_dir && (rinfo->head->is_target || strncmp(req->r_dentry->d_name.name, fsc->mount_options->snapdir_name, req->r_dentry->d_name.len))) { diff --git a/trunk/fs/ceph/ioctl.c b/trunk/fs/ceph/ioctl.c index 1396ceb46797..8e3fb69fbe62 100644 --- a/trunk/fs/ceph/ioctl.c +++ b/trunk/fs/ceph/ioctl.c @@ -42,8 +42,7 @@ static long __validate_layout(struct ceph_mds_client *mdsc, /* validate striping parameters */ if ((l->object_size & ~PAGE_MASK) || (l->stripe_unit & ~PAGE_MASK) || - (l->stripe_unit != 0 && - ((unsigned)l->object_size % (unsigned)l->stripe_unit))) + ((unsigned)l->object_size % (unsigned)l->stripe_unit)) return -EINVAL; /* make sure it's a valid data pool */ diff --git a/trunk/fs/cifs/cifs_unicode.c b/trunk/fs/cifs/cifs_unicode.c index 53cf2aabce87..7dab9c04ad52 100644 --- a/trunk/fs/cifs/cifs_unicode.c +++ b/trunk/fs/cifs/cifs_unicode.c @@ -328,7 +328,7 @@ cifsConvertToUTF16(__le16 *target, const char *source, int srclen, } ctoUTF16_out: - return j; + return i; } #ifdef CONFIG_CIFS_SMB2 diff --git a/trunk/fs/cifs/cifssmb.c b/trunk/fs/cifs/cifssmb.c index f0cf934ba877..074923ce593d 100644 --- a/trunk/fs/cifs/cifssmb.c +++ b/trunk/fs/cifs/cifssmb.c @@ -1576,14 +1576,9 @@ cifs_readv_callback(struct mid_q_entry *mid) /* result already set, check signature */ if (server->sec_mode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) { - int rc = 0; - - rc = cifs_verify_signature(rdata->iov, rdata->nr_iov, - server, - mid->sequence_number + 1); - if (rc) - cERROR(1, "SMB signature verification returned " - "error = %d", rc); + if (cifs_verify_signature(rdata->iov, rdata->nr_iov, + server, mid->sequence_number + 1)) + cERROR(1, "Unexpected SMB signature"); } /* FIXME: should this be counted toward the initiating task? */ task_io_account_read(rdata->bytes); diff --git a/trunk/fs/cifs/dir.c b/trunk/fs/cifs/dir.c index 781025be48bc..cbe709ad6663 100644 --- a/trunk/fs/cifs/dir.c +++ b/trunk/fs/cifs/dir.c @@ -356,12 +356,19 @@ cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned int xid, cifs_create_set_dentry: if (rc != 0) { cFYI(1, "Create worked, get_inode_info failed rc = %d", rc); - CIFSSMBClose(xid, tcon, *fileHandle); goto out; } d_drop(direntry); d_add(direntry, newinode); + /* ENOENT for create? How weird... */ + rc = -ENOENT; + if (!newinode) { + CIFSSMBClose(xid, tcon, *fileHandle); + goto out; + } + rc = 0; + out: kfree(buf); kfree(full_path); diff --git a/trunk/fs/cifs/file.c b/trunk/fs/cifs/file.c index 71e9ad9f5961..9154192b0683 100644 --- a/trunk/fs/cifs/file.c +++ b/trunk/fs/cifs/file.c @@ -917,7 +917,7 @@ cifs_push_mandatory_locks(struct cifsFileInfo *cfile) if (!buf) { mutex_unlock(&cinode->lock_mutex); free_xid(xid); - return -ENOMEM; + return rc; } for (i = 0; i < 2; i++) { diff --git a/trunk/fs/cifs/inode.c b/trunk/fs/cifs/inode.c index cb79c7edecb0..7354877fa3bd 100644 --- a/trunk/fs/cifs/inode.c +++ b/trunk/fs/cifs/inode.c @@ -124,10 +124,10 @@ cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr) { struct cifsInodeInfo *cifs_i = CIFS_I(inode); struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); + unsigned long oldtime = cifs_i->time; cifs_revalidate_cache(inode, fattr); - spin_lock(&inode->i_lock); inode->i_atime = fattr->cf_atime; inode->i_mtime = fattr->cf_mtime; inode->i_ctime = fattr->cf_ctime; @@ -148,6 +148,9 @@ cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr) else cifs_i->time = jiffies; + cFYI(1, "inode 0x%p old_time=%ld new_time=%ld", inode, + oldtime, cifs_i->time); + cifs_i->delete_pending = fattr->cf_flags & CIFS_FATTR_DELETE_PENDING; cifs_i->server_eof = fattr->cf_eof; @@ -155,6 +158,7 @@ cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr) * Can't safely change the file size here if the client is writing to * it due to potential races. */ + spin_lock(&inode->i_lock); if (is_size_safe_to_change(cifs_i, fattr->cf_eof)) { i_size_write(inode, fattr->cf_eof); @@ -855,14 +859,12 @@ struct inode *cifs_root_iget(struct super_block *sb) if (rc && tcon->ipc) { cFYI(1, "ipc connection - fake read inode"); - spin_lock(&inode->i_lock); inode->i_mode |= S_IFDIR; set_nlink(inode, 2); inode->i_op = &cifs_ipc_inode_ops; inode->i_fop = &simple_dir_operations; inode->i_uid = cifs_sb->mnt_uid; inode->i_gid = cifs_sb->mnt_gid; - spin_unlock(&inode->i_lock); } else if (rc) { iget_failed(inode); inode = ERR_PTR(rc); @@ -1108,15 +1110,6 @@ cifs_rename_pending_delete(char *full_path, struct dentry *dentry, goto out_close; } -/* copied from fs/nfs/dir.c with small changes */ -static void -cifs_drop_nlink(struct inode *inode) -{ - spin_lock(&inode->i_lock); - if (inode->i_nlink > 0) - drop_nlink(inode); - spin_unlock(&inode->i_lock); -} /* * If dentry->d_inode is null (usually meaning the cached dentry @@ -1173,13 +1166,13 @@ int cifs_unlink(struct inode *dir, struct dentry *dentry) psx_del_no_retry: if (!rc) { if (inode) - cifs_drop_nlink(inode); + drop_nlink(inode); } else if (rc == -ENOENT) { d_drop(dentry); } else if (rc == -ETXTBSY) { rc = cifs_rename_pending_delete(full_path, dentry, xid); if (rc == 0) - cifs_drop_nlink(inode); + drop_nlink(inode); } else if ((rc == -EACCES) && (dosattr == 0) && inode) { attrs = kzalloc(sizeof(*attrs), GFP_KERNEL); if (attrs == NULL) { @@ -1248,10 +1241,9 @@ cifs_mkdir_qinfo(struct inode *inode, struct dentry *dentry, umode_t mode, * setting nlink not necessary except in cases where we failed to get it * from the server or was set bogus */ - spin_lock(&dentry->d_inode->i_lock); if ((dentry->d_inode) && (dentry->d_inode->i_nlink < 2)) set_nlink(dentry->d_inode, 2); - spin_unlock(&dentry->d_inode->i_lock); + mode &= ~current_umask(); /* must turn on setgid bit if parent dir has it */ if (inode->i_mode & S_ISGID) diff --git a/trunk/fs/cifs/link.c b/trunk/fs/cifs/link.c index e6ce3b112875..09e4b3ae4564 100644 --- a/trunk/fs/cifs/link.c +++ b/trunk/fs/cifs/link.c @@ -433,9 +433,7 @@ cifs_hardlink(struct dentry *old_file, struct inode *inode, if (old_file->d_inode) { cifsInode = CIFS_I(old_file->d_inode); if (rc == 0) { - spin_lock(&old_file->d_inode->i_lock); inc_nlink(old_file->d_inode); - spin_unlock(&old_file->d_inode->i_lock); /* BB should we make this contingent on superblock flag NOATIME? */ /* old_file->d_inode->i_ctime = CURRENT_TIME;*/ /* parent dir timestamps will update from srv diff --git a/trunk/fs/cifs/smb2misc.c b/trunk/fs/cifs/smb2misc.c index e4d3b9964167..a4ff5d547554 100644 --- a/trunk/fs/cifs/smb2misc.c +++ b/trunk/fs/cifs/smb2misc.c @@ -52,8 +52,7 @@ check_smb2_hdr(struct smb2_hdr *hdr, __u64 mid) cERROR(1, "Bad protocol string signature header %x", *(unsigned int *) hdr->ProtocolId); if (mid != hdr->MessageId) - cERROR(1, "Mids do not match: %llu and %llu", mid, - hdr->MessageId); + cERROR(1, "Mids do not match"); } cERROR(1, "Bad SMB detected. The Mid=%llu", hdr->MessageId); return 1; @@ -108,7 +107,7 @@ smb2_check_message(char *buf, unsigned int length) * ie Validate the wct via smb2_struct_sizes table above */ - if (length < sizeof(struct smb2_pdu)) { + if (length < 2 + sizeof(struct smb2_hdr)) { if ((length >= sizeof(struct smb2_hdr)) && (hdr->Status != 0)) { pdu->StructureSize2 = 0; /* @@ -122,15 +121,15 @@ smb2_check_message(char *buf, unsigned int length) return 1; } if (len > CIFSMaxBufSize + MAX_SMB2_HDR_SIZE - 4) { - cERROR(1, "SMB length greater than maximum, mid=%llu", mid); + cERROR(1, "SMB length greater than maximum, mid=%lld", mid); return 1; } if (check_smb2_hdr(hdr, mid)) return 1; - if (hdr->StructureSize != SMB2_HEADER_STRUCTURE_SIZE) { - cERROR(1, "Illegal structure size %u", + if (hdr->StructureSize != SMB2_HEADER_SIZE) { + cERROR(1, "Illegal structure size %d", le16_to_cpu(hdr->StructureSize)); return 1; } @@ -162,9 +161,8 @@ smb2_check_message(char *buf, unsigned int length) if (4 + len != clc_len) { cFYI(1, "Calculated size %u length %u mismatch mid %llu", clc_len, 4 + len, mid); - /* server can return one byte more */ - if (clc_len == 4 + len + 1) - return 0; + if (clc_len == 4 + len + 1) /* BB FIXME (fix samba) */ + return 0; /* BB workaround Samba 3 bug SessSetup rsp */ return 1; } return 0; diff --git a/trunk/fs/cifs/smb2pdu.h b/trunk/fs/cifs/smb2pdu.h index 15dc8eea8273..f37a1b41b402 100644 --- a/trunk/fs/cifs/smb2pdu.h +++ b/trunk/fs/cifs/smb2pdu.h @@ -87,6 +87,10 @@ #define SMB2_PROTO_NUMBER __constant_cpu_to_le32(0x424d53fe) +#define SMB2_HEADER_SIZE __constant_le16_to_cpu(64) + +#define SMB2_ERROR_STRUCTURE_SIZE2 __constant_le16_to_cpu(9) + /* * SMB2 Header Definition * @@ -95,9 +99,6 @@ * "PDU" : "Protocol Data Unit" (ie a network "frame") * */ - -#define SMB2_HEADER_STRUCTURE_SIZE __constant_cpu_to_le16(64) - struct smb2_hdr { __be32 smb2_buf_length; /* big endian on wire */ /* length is only two or three bytes - with @@ -139,9 +140,6 @@ struct smb2_pdu { * command code name for the struct. Note that structures must be packed. * */ - -#define SMB2_ERROR_STRUCTURE_SIZE2 __constant_cpu_to_le16(9) - struct smb2_err_rsp { struct smb2_hdr hdr; __le16 StructureSize; diff --git a/trunk/fs/cifs/transport.c b/trunk/fs/cifs/transport.c index d9b639b95fa8..83867ef348df 100644 --- a/trunk/fs/cifs/transport.c +++ b/trunk/fs/cifs/transport.c @@ -503,16 +503,13 @@ cifs_check_receive(struct mid_q_entry *mid, struct TCP_Server_Info *server, /* convert the length into a more usable form */ if (server->sec_mode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) { struct kvec iov; - int rc = 0; iov.iov_base = mid->resp_buf; iov.iov_len = len; /* FIXME: add code to kill session */ - rc = cifs_verify_signature(&iov, 1, server, - mid->sequence_number + 1); - if (rc) - cERROR(1, "SMB signature verification returned error = " - "%d", rc); + if (cifs_verify_signature(&iov, 1, server, + mid->sequence_number + 1) != 0) + cERROR(1, "Unexpected SMB signature"); } /* BB special case reconnect tid and uid here? */ diff --git a/trunk/fs/compat.c b/trunk/fs/compat.c index 1bdb350ea5d3..6161255fac45 100644 --- a/trunk/fs/compat.c +++ b/trunk/fs/compat.c @@ -1155,14 +1155,11 @@ compat_sys_readv(unsigned long fd, const struct compat_iovec __user *vec, struct file *file; int fput_needed; ssize_t ret; - loff_t pos; file = fget_light(fd, &fput_needed); if (!file) return -EBADF; - pos = file->f_pos; - ret = compat_readv(file, vec, vlen, &pos); - file->f_pos = pos; + ret = compat_readv(file, vec, vlen, &file->f_pos); fput_light(file, fput_needed); return ret; } @@ -1224,14 +1221,11 @@ compat_sys_writev(unsigned long fd, const struct compat_iovec __user *vec, struct file *file; int fput_needed; ssize_t ret; - loff_t pos; file = fget_light(fd, &fput_needed); if (!file) return -EBADF; - pos = file->f_pos; - ret = compat_writev(file, vec, vlen, &pos); - file->f_pos = pos; + ret = compat_writev(file, vec, vlen, &file->f_pos); fput_light(file, fput_needed); return ret; } diff --git a/trunk/fs/compat_ioctl.c b/trunk/fs/compat_ioctl.c index 59f8db4a39a7..debdfe0fc809 100644 --- a/trunk/fs/compat_ioctl.c +++ b/trunk/fs/compat_ioctl.c @@ -866,12 +866,6 @@ COMPATIBLE_IOCTL(TIOCGPTN) COMPATIBLE_IOCTL(TIOCSPTLCK) COMPATIBLE_IOCTL(TIOCSERGETLSR) COMPATIBLE_IOCTL(TIOCSIG) -#ifdef TIOCSRS485 -COMPATIBLE_IOCTL(TIOCSRS485) -#endif -#ifdef TIOCGRS485 -COMPATIBLE_IOCTL(TIOCGRS485) -#endif #ifdef TCGETS2 COMPATIBLE_IOCTL(TCGETS2) COMPATIBLE_IOCTL(TCSETS2) diff --git a/trunk/fs/dcache.c b/trunk/fs/dcache.c index 693f95bf1cae..8086636bf796 100644 --- a/trunk/fs/dcache.c +++ b/trunk/fs/dcache.c @@ -389,7 +389,7 @@ static struct dentry *d_kill(struct dentry *dentry, struct dentry *parent) * Inform try_to_ascend() that we are no longer attached to the * dentry tree */ - dentry->d_flags |= DCACHE_DENTRY_KILLED; + dentry->d_flags |= DCACHE_DISCONNECTED; if (parent) spin_unlock(&parent->d_lock); dentry_iput(dentry); @@ -1048,7 +1048,7 @@ static struct dentry *try_to_ascend(struct dentry *old, int locked, unsigned seq * or deletion */ if (new != old->d_parent || - (old->d_flags & DCACHE_DENTRY_KILLED) || + (old->d_flags & DCACHE_DISCONNECTED) || (!locked && read_seqretry(&rename_lock, seq))) { spin_unlock(&new->d_lock); new = NULL; @@ -1134,8 +1134,6 @@ int have_submounts(struct dentry *parent) return 1; rename_retry: - if (locked) - goto again; locked = 1; write_seqlock(&rename_lock); goto again; @@ -1143,7 +1141,7 @@ int have_submounts(struct dentry *parent) EXPORT_SYMBOL(have_submounts); /* - * Search the dentry child list of the specified parent, + * Search the dentry child list for the specified parent, * and move any unused dentries to the end of the unused * list for prune_dcache(). We descend to the next level * whenever the d_subdirs list is non-empty and continue @@ -1238,8 +1236,6 @@ static int select_parent(struct dentry *parent, struct list_head *dispose) rename_retry: if (found) return found; - if (locked) - goto again; locked = 1; write_seqlock(&rename_lock); goto again; @@ -3039,8 +3035,6 @@ void d_genocide(struct dentry *root) return; rename_retry: - if (locked) - goto again; locked = 1; write_seqlock(&rename_lock); goto again; diff --git a/trunk/fs/debugfs/file.c b/trunk/fs/debugfs/file.c index c5ca6ae5a30c..2340f6978d6e 100644 --- a/trunk/fs/debugfs/file.c +++ b/trunk/fs/debugfs/file.c @@ -526,51 +526,73 @@ struct array_data { u32 elements; }; -static size_t u32_format_array(char *buf, size_t bufsize, - u32 *array, int array_size) +static int u32_array_open(struct inode *inode, struct file *file) +{ + file->private_data = NULL; + return nonseekable_open(inode, file); +} + +static size_t format_array(char *buf, size_t bufsize, const char *fmt, + u32 *array, u32 array_size) { size_t ret = 0; + u32 i; - while (--array_size >= 0) { + for (i = 0; i < array_size; i++) { size_t len; - char term = array_size ? ' ' : '\n'; - len = snprintf(buf, bufsize, "%u%c", *array++, term); + len = snprintf(buf, bufsize, fmt, array[i]); + len++; /* ' ' or '\n' */ ret += len; - buf += len; - bufsize -= len; + if (buf) { + buf += len; + bufsize -= len; + buf[-1] = (i == array_size-1) ? '\n' : ' '; + } } + + ret++; /* \0 */ + if (buf) + *buf = '\0'; + return ret; } -static int u32_array_open(struct inode *inode, struct file *file) +static char *format_array_alloc(const char *fmt, u32 *array, + u32 array_size) { - struct array_data *data = inode->i_private; - int size, elements = data->elements; - char *buf; - - /* - * Max size: - * - 10 digits + ' '/'\n' = 11 bytes per number - * - terminating NUL character - */ - size = elements*11; - buf = kmalloc(size+1, GFP_KERNEL); - if (!buf) - return -ENOMEM; - buf[size] = 0; - - file->private_data = buf; - u32_format_array(buf, size, data->array, data->elements); + size_t len = format_array(NULL, 0, fmt, array, array_size); + char *ret; - return nonseekable_open(inode, file); + ret = kmalloc(len, GFP_KERNEL); + if (ret == NULL) + return NULL; + + format_array(ret, len, fmt, array, array_size); + return ret; } static ssize_t u32_array_read(struct file *file, char __user *buf, size_t len, loff_t *ppos) { - size_t size = strlen(file->private_data); + struct inode *inode = file->f_path.dentry->d_inode; + struct array_data *data = inode->i_private; + size_t size; + + if (*ppos == 0) { + if (file->private_data) { + kfree(file->private_data); + file->private_data = NULL; + } + + file->private_data = format_array_alloc("%u", data->array, + data->elements); + } + + size = 0; + if (file->private_data) + size = strlen(file->private_data); return simple_read_from_buffer(buf, len, ppos, file->private_data, size); diff --git a/trunk/fs/debugfs/inode.c b/trunk/fs/debugfs/inode.c index 6393fd61d5c4..4733eab34a23 100644 --- a/trunk/fs/debugfs/inode.c +++ b/trunk/fs/debugfs/inode.c @@ -28,7 +28,7 @@ #include #include -#define DEBUGFS_DEFAULT_MODE 0700 +#define DEBUGFS_DEFAULT_MODE 0755 static struct vfsmount *debugfs_mount; static int debugfs_mount_count; @@ -291,9 +291,9 @@ static struct file_system_type debug_fs_type = { .kill_sb = kill_litter_super, }; -static struct dentry *__create_file(const char *name, umode_t mode, - struct dentry *parent, void *data, - const struct file_operations *fops) +struct dentry *__create_file(const char *name, umode_t mode, + struct dentry *parent, void *data, + const struct file_operations *fops) { struct dentry *dentry = NULL; int error; diff --git a/trunk/fs/direct-io.c b/trunk/fs/direct-io.c index f86c720dba0e..1faf4cb56f39 100644 --- a/trunk/fs/direct-io.c +++ b/trunk/fs/direct-io.c @@ -1062,7 +1062,6 @@ do_blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode, unsigned long user_addr; size_t bytes; struct buffer_head map_bh = { 0, }; - struct blk_plug plug; if (rw & WRITE) rw = WRITE_ODIRECT; @@ -1178,8 +1177,6 @@ do_blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode, PAGE_SIZE - user_addr / PAGE_SIZE); } - blk_start_plug(&plug); - for (seg = 0; seg < nr_segs; seg++) { user_addr = (unsigned long)iov[seg].iov_base; sdio.size += bytes = iov[seg].iov_len; @@ -1238,8 +1235,6 @@ do_blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode, if (sdio.bio) dio_bio_submit(dio, &sdio); - blk_finish_plug(&plug); - /* * It is possible that, we return short IO due to end of file. * In that case, we need to release all the pages we got hold on. diff --git a/trunk/fs/ecryptfs/file.c b/trunk/fs/ecryptfs/file.c index d45ba4568128..44ce5c6a541d 100644 --- a/trunk/fs/ecryptfs/file.c +++ b/trunk/fs/ecryptfs/file.c @@ -275,14 +275,8 @@ static int ecryptfs_open(struct inode *inode, struct file *file) static int ecryptfs_flush(struct file *file, fl_owner_t td) { - struct file *lower_file = ecryptfs_file_to_lower(file); - - if (lower_file->f_op && lower_file->f_op->flush) { - filemap_write_and_wait(file->f_mapping); - return lower_file->f_op->flush(lower_file, td); - } - - return 0; + return file->f_mode & FMODE_WRITE + ? filemap_write_and_wait(file->f_mapping) : 0; } static int ecryptfs_release(struct inode *inode, struct file *file) diff --git a/trunk/fs/ecryptfs/inode.c b/trunk/fs/ecryptfs/inode.c index cc7709e7c508..534b129ea676 100644 --- a/trunk/fs/ecryptfs/inode.c +++ b/trunk/fs/ecryptfs/inode.c @@ -619,7 +619,6 @@ ecryptfs_rename(struct inode *old_dir, struct dentry *old_dentry, struct dentry *lower_old_dir_dentry; struct dentry *lower_new_dir_dentry; struct dentry *trap = NULL; - struct inode *target_inode; lower_old_dentry = ecryptfs_dentry_to_lower(old_dentry); lower_new_dentry = ecryptfs_dentry_to_lower(new_dentry); @@ -627,7 +626,6 @@ ecryptfs_rename(struct inode *old_dir, struct dentry *old_dentry, dget(lower_new_dentry); lower_old_dir_dentry = dget_parent(lower_old_dentry); lower_new_dir_dentry = dget_parent(lower_new_dentry); - target_inode = new_dentry->d_inode; trap = lock_rename(lower_old_dir_dentry, lower_new_dir_dentry); /* source should not be ancestor of target */ if (trap == lower_old_dentry) { @@ -643,9 +641,6 @@ ecryptfs_rename(struct inode *old_dir, struct dentry *old_dentry, lower_new_dir_dentry->d_inode, lower_new_dentry); if (rc) goto out_lock; - if (target_inode) - fsstack_copy_attr_all(target_inode, - ecryptfs_inode_to_lower(target_inode)); fsstack_copy_attr_all(new_dir, lower_new_dir_dentry->d_inode); if (new_dir != old_dir) fsstack_copy_attr_all(old_dir, lower_old_dir_dentry->d_inode); diff --git a/trunk/fs/ecryptfs/main.c b/trunk/fs/ecryptfs/main.c index 9b627c15010a..2768138eefee 100644 --- a/trunk/fs/ecryptfs/main.c +++ b/trunk/fs/ecryptfs/main.c @@ -162,7 +162,6 @@ void ecryptfs_put_lower_file(struct inode *inode) inode_info = ecryptfs_inode_to_private(inode); if (atomic_dec_and_mutex_lock(&inode_info->lower_file_count, &inode_info->lower_file_mutex)) { - filemap_write_and_wait(inode->i_mapping); fput(inode_info->lower_file); inode_info->lower_file = NULL; mutex_unlock(&inode_info->lower_file_mutex); diff --git a/trunk/fs/eventpoll.c b/trunk/fs/eventpoll.c index eedec84c1809..1c8b55670804 100644 --- a/trunk/fs/eventpoll.c +++ b/trunk/fs/eventpoll.c @@ -1654,8 +1654,8 @@ SYSCALL_DEFINE1(epoll_create1, int, flags) error = PTR_ERR(file); goto out_free_fd; } - ep->file = file; fd_install(fd, file); + ep->file = file; return fd; out_free_fd: diff --git a/trunk/fs/exofs/inode.c b/trunk/fs/exofs/inode.c index 1562c27a2fab..5badb0c039de 100644 --- a/trunk/fs/exofs/inode.c +++ b/trunk/fs/exofs/inode.c @@ -37,12 +37,15 @@ #define EXOFS_DBGMSG2(M...) do {} while (0) +enum {MAX_PAGES_KMALLOC = PAGE_SIZE / sizeof(struct page *), }; + unsigned exofs_max_io_pages(struct ore_layout *layout, unsigned expected_pages) { - unsigned pages = min_t(unsigned, expected_pages, - layout->max_io_length / PAGE_SIZE); + unsigned pages = min_t(unsigned, expected_pages, MAX_PAGES_KMALLOC); + /* TODO: easily support bio chaining */ + pages = min_t(unsigned, pages, layout->max_io_length / PAGE_SIZE); return pages; } @@ -98,8 +101,7 @@ static void _pcol_reset(struct page_collect *pcol) * it might not end here. don't be left with nothing */ if (!pcol->expected_pages) - pcol->expected_pages = - exofs_max_io_pages(&pcol->sbi->layout, ~0); + pcol->expected_pages = MAX_PAGES_KMALLOC; } static int pcol_try_alloc(struct page_collect *pcol) @@ -387,8 +389,6 @@ static int readpage_strip(void *data, struct page *page) size_t len; int ret; - BUG_ON(!PageLocked(page)); - /* FIXME: Just for debugging, will be removed */ if (PageUptodate(page)) EXOFS_ERR("PageUptodate(0x%lx, 0x%lx)\n", pcol->inode->i_ino, @@ -572,16 +572,8 @@ static struct page *__r4w_get_page(void *priv, u64 offset, bool *uptodate) if (!pcol->that_locked_page || (pcol->that_locked_page->index != index)) { - struct page *page; - loff_t i_size = i_size_read(pcol->inode); - - if (offset >= i_size) { - *uptodate = true; - EXOFS_DBGMSG("offset >= i_size index=0x%lx\n", index); - return ZERO_PAGE(0); - } + struct page *page = find_get_page(pcol->inode->i_mapping, index); - page = find_get_page(pcol->inode->i_mapping, index); if (!page) { page = find_or_create_page(pcol->inode->i_mapping, index, GFP_NOFS); @@ -610,13 +602,12 @@ static void __r4w_put_page(void *priv, struct page *page) { struct page_collect *pcol = priv; - if ((pcol->that_locked_page != page) && (ZERO_PAGE(0) != page)) { + if (pcol->that_locked_page != page) { EXOFS_DBGMSG("index=0x%lx\n", page->index); page_cache_release(page); return; } - EXOFS_DBGMSG("that_locked_page index=0x%lx\n", - ZERO_PAGE(0) == page ? -1 : page->index); + EXOFS_DBGMSG("that_locked_page index=0x%lx\n", page->index); } static const struct _ore_r4w_op _r4w_op = { diff --git a/trunk/fs/exofs/ore.c b/trunk/fs/exofs/ore.c index 1585db1aa365..24a49d47e935 100644 --- a/trunk/fs/exofs/ore.c +++ b/trunk/fs/exofs/ore.c @@ -837,11 +837,11 @@ static int _write_mirror(struct ore_io_state *ios, int cur_comp) bio->bi_rw |= REQ_WRITE; } - osd_req_write(or, _ios_obj(ios, cur_comp), - per_dev->offset, bio, per_dev->length); + osd_req_write(or, _ios_obj(ios, dev), per_dev->offset, + bio, per_dev->length); ORE_DBGMSG("write(0x%llx) offset=0x%llx " "length=0x%llx dev=%d\n", - _LLU(_ios_obj(ios, cur_comp)->id), + _LLU(_ios_obj(ios, dev)->id), _LLU(per_dev->offset), _LLU(per_dev->length), dev); } else if (ios->kern_buff) { @@ -853,20 +853,20 @@ static int _write_mirror(struct ore_io_state *ios, int cur_comp) (ios->si.unit_off + ios->length > ios->layout->stripe_unit)); - ret = osd_req_write_kern(or, _ios_obj(ios, cur_comp), + ret = osd_req_write_kern(or, _ios_obj(ios, per_dev->dev), per_dev->offset, ios->kern_buff, ios->length); if (unlikely(ret)) goto out; ORE_DBGMSG2("write_kern(0x%llx) offset=0x%llx " "length=0x%llx dev=%d\n", - _LLU(_ios_obj(ios, cur_comp)->id), + _LLU(_ios_obj(ios, dev)->id), _LLU(per_dev->offset), _LLU(ios->length), per_dev->dev); } else { - osd_req_set_attributes(or, _ios_obj(ios, cur_comp)); + osd_req_set_attributes(or, _ios_obj(ios, dev)); ORE_DBGMSG2("obj(0x%llx) set_attributes=%d dev=%d\n", - _LLU(_ios_obj(ios, cur_comp)->id), + _LLU(_ios_obj(ios, dev)->id), ios->out_attr_len, dev); } diff --git a/trunk/fs/exofs/super.c b/trunk/fs/exofs/super.c index dde41a75c7c8..433783624d10 100644 --- a/trunk/fs/exofs/super.c +++ b/trunk/fs/exofs/super.c @@ -400,6 +400,8 @@ static int exofs_sync_fs(struct super_block *sb, int wait) ret = ore_write(ios); if (unlikely(ret)) EXOFS_ERR("%s: ore_write failed.\n", __func__); + else + sb->s_dirt = 0; unlock_super(sb); @@ -410,6 +412,14 @@ static int exofs_sync_fs(struct super_block *sb, int wait) return ret; } +static void exofs_write_super(struct super_block *sb) +{ + if (!(sb->s_flags & MS_RDONLY)) + exofs_sync_fs(sb, 1); + else + sb->s_dirt = 0; +} + static void _exofs_print_device(const char *msg, const char *dev_path, struct osd_dev *od, u64 pid) { @@ -942,6 +952,7 @@ static const struct super_operations exofs_sops = { .write_inode = exofs_write_inode, .evict_inode = exofs_evict_inode, .put_super = exofs_put_super, + .write_super = exofs_write_super, .sync_fs = exofs_sync_fs, .statfs = exofs_statfs, }; diff --git a/trunk/fs/ext2/balloc.c b/trunk/fs/ext2/balloc.c index 2616d0ea5c5c..376aa77f3ca7 100644 --- a/trunk/fs/ext2/balloc.c +++ b/trunk/fs/ext2/balloc.c @@ -479,7 +479,7 @@ void ext2_discard_reservation(struct inode *inode) /** * ext2_free_blocks() -- Free given blocks and update quota and i_blocks * @inode: inode - * @block: start physical block to free + * @block: start physcial block to free * @count: number of blocks to free */ void ext2_free_blocks (struct inode * inode, unsigned long block, diff --git a/trunk/fs/ext3/balloc.c b/trunk/fs/ext3/balloc.c index 7320a66e958f..90d901f0486b 100644 --- a/trunk/fs/ext3/balloc.c +++ b/trunk/fs/ext3/balloc.c @@ -483,7 +483,7 @@ void ext3_discard_reservation(struct inode *inode) * ext3_free_blocks_sb() -- Free given blocks and update quota * @handle: handle to this transaction * @sb: super block - * @block: start physical block to free + * @block: start physcial block to free * @count: number of blocks to free * @pdquot_freed_blocks: pointer to quota */ diff --git a/trunk/fs/ext3/inode.c b/trunk/fs/ext3/inode.c index 7e87e37a372a..9a4a5c48b1c9 100644 --- a/trunk/fs/ext3/inode.c +++ b/trunk/fs/ext3/inode.c @@ -3072,8 +3072,6 @@ static int ext3_do_update_inode(handle_t *handle, struct ext3_inode_info *ei = EXT3_I(inode); struct buffer_head *bh = iloc->bh; int err = 0, rc, block; - int need_datasync = 0; - __le32 disksize; uid_t i_uid; gid_t i_gid; @@ -3115,11 +3113,7 @@ static int ext3_do_update_inode(handle_t *handle, raw_inode->i_gid_high = 0; } raw_inode->i_links_count = cpu_to_le16(inode->i_nlink); - disksize = cpu_to_le32(ei->i_disksize); - if (disksize != raw_inode->i_size) { - need_datasync = 1; - raw_inode->i_size = disksize; - } + raw_inode->i_size = cpu_to_le32(ei->i_disksize); raw_inode->i_atime = cpu_to_le32(inode->i_atime.tv_sec); raw_inode->i_ctime = cpu_to_le32(inode->i_ctime.tv_sec); raw_inode->i_mtime = cpu_to_le32(inode->i_mtime.tv_sec); @@ -3135,11 +3129,8 @@ static int ext3_do_update_inode(handle_t *handle, if (!S_ISREG(inode->i_mode)) { raw_inode->i_dir_acl = cpu_to_le32(ei->i_dir_acl); } else { - disksize = cpu_to_le32(ei->i_disksize >> 32); - if (disksize != raw_inode->i_size_high) { - raw_inode->i_size_high = disksize; - need_datasync = 1; - } + raw_inode->i_size_high = + cpu_to_le32(ei->i_disksize >> 32); if (ei->i_disksize > 0x7fffffffULL) { struct super_block *sb = inode->i_sb; if (!EXT3_HAS_RO_COMPAT_FEATURE(sb, @@ -3192,8 +3183,6 @@ static int ext3_do_update_inode(handle_t *handle, ext3_clear_inode_state(inode, EXT3_STATE_NEW); atomic_set(&ei->i_sync_tid, handle->h_transaction->t_tid); - if (need_datasync) - atomic_set(&ei->i_datasync_tid, handle->h_transaction->t_tid); out_brelse: brelse (bh); ext3_std_error(inode->i_sb, err); @@ -3207,7 +3196,7 @@ static int ext3_do_update_inode(handle_t *handle, * * - Within generic_file_write() for O_SYNC files. * Here, there will be no transaction running. We wait for any running - * transaction to commit. + * trasnaction to commit. * * - Within sys_sync(), kupdate and such. * We wait on commit, if tol to. @@ -3470,6 +3459,14 @@ ext3_reserve_inode_write(handle_t *handle, struct inode *inode, * inode out, but prune_icache isn't a user-visible syncing function. * Whenever the user wants stuff synced (sys_sync, sys_msync, sys_fsync) * we start and wait on commits. + * + * Is this efficient/effective? Well, we're being nice to the system + * by cleaning up our inodes proactively so they can be reaped + * without I/O. But we are potentially leaving up to five seconds' + * worth of inodes floating about which prune_icache wants us to + * write out. One way to fix that would be to get prune_icache() + * to do a write_super() to free up some memory. It has the desired + * effect. */ int ext3_mark_inode_dirty(handle_t *handle, struct inode *inode) { diff --git a/trunk/fs/ext3/super.c b/trunk/fs/ext3/super.c index 8c892e93d8e7..ff9bcdc5b0d5 100644 --- a/trunk/fs/ext3/super.c +++ b/trunk/fs/ext3/super.c @@ -64,6 +64,11 @@ static int ext3_freeze(struct super_block *sb); /* * Wrappers for journal_start/end. + * + * The only special thing we need to do here is to make sure that all + * journal_end calls result in the superblock being marked dirty, so + * that sync() will call the filesystem's write_super callback if + * appropriate. */ handle_t *ext3_journal_start_sb(struct super_block *sb, int nblocks) { @@ -85,6 +90,12 @@ handle_t *ext3_journal_start_sb(struct super_block *sb, int nblocks) return journal_start(journal, nblocks); } +/* + * The only special thing we need to do here is to make sure that all + * journal_stop calls result in the superblock being marked dirty, so + * that sync() will call the filesystem's write_super callback if + * appropriate. + */ int __ext3_journal_stop(const char *where, handle_t *handle) { struct super_block *sb; diff --git a/trunk/fs/ext4/balloc.c b/trunk/fs/ext4/balloc.c index 1b5089067d01..d23b31ca9d7a 100644 --- a/trunk/fs/ext4/balloc.c +++ b/trunk/fs/ext4/balloc.c @@ -280,18 +280,14 @@ struct ext4_group_desc * ext4_get_group_desc(struct super_block *sb, return desc; } -/* - * Return the block number which was discovered to be invalid, or 0 if - * the block bitmap is valid. - */ -static ext4_fsblk_t ext4_valid_block_bitmap(struct super_block *sb, - struct ext4_group_desc *desc, - unsigned int block_group, - struct buffer_head *bh) +static int ext4_valid_block_bitmap(struct super_block *sb, + struct ext4_group_desc *desc, + unsigned int block_group, + struct buffer_head *bh) { ext4_grpblk_t offset; ext4_grpblk_t next_zero_bit; - ext4_fsblk_t blk; + ext4_fsblk_t bitmap_blk; ext4_fsblk_t group_first_block; if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_FLEX_BG)) { @@ -301,33 +297,37 @@ static ext4_fsblk_t ext4_valid_block_bitmap(struct super_block *sb, * or it has to also read the block group where the bitmaps * are located to verify they are set. */ - return 0; + return 1; } group_first_block = ext4_group_first_block_no(sb, block_group); /* check whether block bitmap block number is set */ - blk = ext4_block_bitmap(sb, desc); - offset = blk - group_first_block; + bitmap_blk = ext4_block_bitmap(sb, desc); + offset = bitmap_blk - group_first_block; if (!ext4_test_bit(offset, bh->b_data)) /* bad block bitmap */ - return blk; + goto err_out; /* check whether the inode bitmap block number is set */ - blk = ext4_inode_bitmap(sb, desc); - offset = blk - group_first_block; + bitmap_blk = ext4_inode_bitmap(sb, desc); + offset = bitmap_blk - group_first_block; if (!ext4_test_bit(offset, bh->b_data)) /* bad block bitmap */ - return blk; + goto err_out; /* check whether the inode table block number is set */ - blk = ext4_inode_table(sb, desc); - offset = blk - group_first_block; + bitmap_blk = ext4_inode_table(sb, desc); + offset = bitmap_blk - group_first_block; next_zero_bit = ext4_find_next_zero_bit(bh->b_data, offset + EXT4_SB(sb)->s_itb_per_group, offset); - if (next_zero_bit < offset + EXT4_SB(sb)->s_itb_per_group) - /* bad bitmap for inode tables */ - return blk; + if (next_zero_bit >= offset + EXT4_SB(sb)->s_itb_per_group) + /* good bitmap for inode tables */ + return 1; + +err_out: + ext4_error(sb, "Invalid block bitmap - block_group = %d, block = %llu", + block_group, bitmap_blk); return 0; } @@ -336,26 +336,14 @@ void ext4_validate_block_bitmap(struct super_block *sb, unsigned int block_group, struct buffer_head *bh) { - ext4_fsblk_t blk; - if (buffer_verified(bh)) return; ext4_lock_group(sb, block_group); - blk = ext4_valid_block_bitmap(sb, desc, block_group, bh); - if (unlikely(blk != 0)) { - ext4_unlock_group(sb, block_group); - ext4_error(sb, "bg %u: block %llu: invalid block bitmap", - block_group, blk); - return; - } - if (unlikely(!ext4_block_bitmap_csum_verify(sb, block_group, - desc, bh, EXT4_BLOCKS_PER_GROUP(sb) / 8))) { - ext4_unlock_group(sb, block_group); - ext4_error(sb, "bg %u: bad block bitmap checksum", block_group); - return; - } - set_buffer_verified(bh); + if (ext4_valid_block_bitmap(sb, desc, block_group, bh) && + ext4_block_bitmap_csum_verify(sb, block_group, desc, bh, + EXT4_BLOCKS_PER_GROUP(sb) / 8)) + set_buffer_verified(bh); ext4_unlock_group(sb, block_group); } diff --git a/trunk/fs/ext4/bitmap.c b/trunk/fs/ext4/bitmap.c index 5c2d1813ebe9..f8716eab9995 100644 --- a/trunk/fs/ext4/bitmap.c +++ b/trunk/fs/ext4/bitmap.c @@ -79,6 +79,7 @@ int ext4_block_bitmap_csum_verify(struct super_block *sb, ext4_group_t group, if (provided == calculated) return 1; + ext4_error(sb, "Bad block bitmap checksum: block_group = %u", group); return 0; } diff --git a/trunk/fs/ext4/extents.c b/trunk/fs/ext4/extents.c index aabbb3f53683..cd0c7ed06772 100644 --- a/trunk/fs/ext4/extents.c +++ b/trunk/fs/ext4/extents.c @@ -2662,7 +2662,6 @@ static int ext4_ext_remove_space(struct inode *inode, ext4_lblk_t start, } path[0].p_depth = depth; path[0].p_hdr = ext_inode_hdr(inode); - i = 0; if (ext4_ext_check(inode, path[0].p_hdr, depth)) { err = -EIO; diff --git a/trunk/fs/ext4/inode.c b/trunk/fs/ext4/inode.c index c862ee5fe79d..6324f74e0342 100644 --- a/trunk/fs/ext4/inode.c +++ b/trunk/fs/ext4/inode.c @@ -1970,7 +1970,7 @@ static void ext4_end_io_buffer_write(struct buffer_head *bh, int uptodate); * This function can get called via... * - ext4_da_writepages after taking page lock (have journal handle) * - journal_submit_inode_data_buffers (no journal handle) - * - shrink_page_list via the kswapd/direct reclaim (no journal handle) + * - shrink_page_list via pdflush (no journal handle) * - grab_page_cache when doing write_begin (have journal handle) * * We don't do any block allocation in this function. If we have page with @@ -3313,7 +3313,7 @@ int ext4_discard_partial_page_buffers(handle_t *handle, * handle: The journal handle * inode: The files inode * page: A locked page that contains the offset "from" - * from: The starting byte offset (from the beginning of the file) + * from: The starting byte offset (from the begining of the file) * to begin discarding * len: The length of bytes to discard * flags: Optional flags that may be used: @@ -3321,11 +3321,11 @@ int ext4_discard_partial_page_buffers(handle_t *handle, * EXT4_DISCARD_PARTIAL_PG_ZERO_UNMAPPED * Only zero the regions of the page whose buffer heads * have already been unmapped. This flag is appropriate - * for updating the contents of a page whose blocks may + * for updateing the contents of a page whose blocks may * have already been released, and we only want to zero * out the regions that correspond to those released blocks. * - * Returns zero on success or negative on failure. + * Returns zero on sucess or negative on failure. */ static int ext4_discard_partial_page_buffers_no_lock(handle_t *handle, struct inode *inode, struct page *page, loff_t from, @@ -3486,7 +3486,7 @@ int ext4_can_truncate(struct inode *inode) * @offset: The offset where the hole will begin * @len: The length of the hole * - * Returns: 0 on success or negative on failure + * Returns: 0 on sucess or negative on failure */ int ext4_punch_hole(struct file *file, loff_t offset, loff_t length) @@ -4008,7 +4008,7 @@ static int ext4_inode_blocks_set(handle_t *handle, if (i_blocks <= ~0U) { /* - * i_blocks can be represented in a 32 bit variable + * i_blocks can be represnted in a 32 bit variable * as multiple of 512 bytes */ raw_inode->i_blocks_lo = cpu_to_le32(i_blocks); @@ -4169,7 +4169,7 @@ static int ext4_do_update_inode(handle_t *handle, * * - Within generic_file_write() for O_SYNC files. * Here, there will be no transaction running. We wait for any running - * transaction to commit. + * trasnaction to commit. * * - Within sys_sync(), kupdate and such. * We wait on commit, if tol to. @@ -4413,7 +4413,7 @@ static int ext4_index_trans_blocks(struct inode *inode, int nrblocks, int chunk) * worse case, the indexs blocks spread over different block groups * * If datablocks are discontiguous, they are possible to spread over - * different block groups too. If they are contiguous, with flexbg, + * different block groups too. If they are contiuguous, with flexbg, * they could still across block group boundary. * * Also account for superblock, inode, quota and xattr blocks @@ -4589,6 +4589,14 @@ static int ext4_expand_extra_isize(struct inode *inode, * inode out, but prune_icache isn't a user-visible syncing function. * Whenever the user wants stuff synced (sys_sync, sys_msync, sys_fsync) * we start and wait on commits. + * + * Is this efficient/effective? Well, we're being nice to the system + * by cleaning up our inodes proactively so they can be reaped + * without I/O. But we are potentially leaving up to five seconds' + * worth of inodes floating about which prune_icache wants us to + * write out. One way to fix that would be to get prune_icache() + * to do a write_super() to free up some memory. It has the desired + * effect. */ int ext4_mark_inode_dirty(handle_t *handle, struct inode *inode) { diff --git a/trunk/fs/ext4/mballoc.c b/trunk/fs/ext4/mballoc.c index 08778f6cdfe9..8eae94771c45 100644 --- a/trunk/fs/ext4/mballoc.c +++ b/trunk/fs/ext4/mballoc.c @@ -4709,7 +4709,7 @@ void ext4_free_blocks(handle_t *handle, struct inode *inode, * ext4_group_add_blocks() -- Add given blocks to an existing group * @handle: handle to this transaction * @sb: super block - * @block: start physical block to add to the block group + * @block: start physcial block to add to the block group * @count: number of blocks to free * * This marks the blocks as free in the bitmap and buddy. diff --git a/trunk/fs/ext4/super.c b/trunk/fs/ext4/super.c index c6e0cb3d1f4a..d76ec8277d3f 100644 --- a/trunk/fs/ext4/super.c +++ b/trunk/fs/ext4/super.c @@ -326,6 +326,11 @@ static void ext4_put_nojournal(handle_t *handle) /* * Wrappers for jbd2_journal_start/end. + * + * The only special thing we need to do here is to make sure that all + * journal_end calls result in the superblock being marked dirty, so + * that sync() will call the filesystem's write_super callback if + * appropriate. */ handle_t *ext4_journal_start_sb(struct super_block *sb, int nblocks) { @@ -351,6 +356,12 @@ handle_t *ext4_journal_start_sb(struct super_block *sb, int nblocks) return jbd2_journal_start(journal, nblocks); } +/* + * The only special thing we need to do here is to make sure that all + * jbd2_journal_stop calls result in the superblock being marked dirty, so + * that sync() will call the filesystem's write_super callback if + * appropriate. + */ int __ext4_journal_stop(const char *where, unsigned int line, handle_t *handle) { struct super_block *sb; @@ -948,7 +959,6 @@ static struct inode *ext4_alloc_inode(struct super_block *sb) ei->i_reserved_meta_blocks = 0; ei->i_allocated_meta_blocks = 0; ei->i_da_metadata_calc_len = 0; - ei->i_da_metadata_calc_last_lblock = 0; spin_lock_init(&(ei->i_block_reservation_lock)); #ifdef CONFIG_QUOTA ei->i_reserved_quota = 0; @@ -3109,10 +3119,6 @@ static int count_overhead(struct super_block *sb, ext4_group_t grp, ext4_group_t i, ngroups = ext4_get_groups_count(sb); int s, j, count = 0; - if (!EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_BIGALLOC)) - return (ext4_bg_has_super(sb, grp) + ext4_bg_num_gdb(sb, grp) + - sbi->s_itb_per_group + 2); - first_block = le32_to_cpu(sbi->s_es->s_first_data_block) + (grp * EXT4_BLOCKS_PER_GROUP(sb)); last_block = first_block + EXT4_BLOCKS_PER_GROUP(sb) - 1; @@ -4424,7 +4430,6 @@ static void ext4_clear_journal_err(struct super_block *sb, ext4_commit_super(sb, 1); jbd2_journal_clear_err(journal); - jbd2_journal_update_sb_errno(journal); } } diff --git a/trunk/fs/fs-writeback.c b/trunk/fs/fs-writeback.c index 6d46c0d78338..be3efc4f64f4 100644 --- a/trunk/fs/fs-writeback.c +++ b/trunk/fs/fs-writeback.c @@ -577,6 +577,10 @@ static long writeback_chunk_size(struct backing_dev_info *bdi, /* * Write a portion of b_io inodes which belong to @sb. * + * If @only_this_sb is true, then find and write all such + * inodes. Otherwise write only ones which go sequentially + * in reverse order. + * * Return the number of pages and/or inodes written. */ static long writeback_sb_inodes(struct super_block *sb, diff --git a/trunk/fs/fuse/control.c b/trunk/fs/fuse/control.c index 75a20c092dd4..03ff5b1eba93 100644 --- a/trunk/fs/fuse/control.c +++ b/trunk/fs/fuse/control.c @@ -117,7 +117,7 @@ static ssize_t fuse_conn_max_background_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { - unsigned uninitialized_var(val); + unsigned val; ssize_t ret; ret = fuse_conn_limit_write(file, buf, count, ppos, &val, @@ -154,7 +154,7 @@ static ssize_t fuse_conn_congestion_threshold_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { - unsigned uninitialized_var(val); + unsigned val; ssize_t ret; ret = fuse_conn_limit_write(file, buf, count, ppos, &val, diff --git a/trunk/fs/fuse/cuse.c b/trunk/fs/fuse/cuse.c index ee8d55042298..3426521f3205 100644 --- a/trunk/fs/fuse/cuse.c +++ b/trunk/fs/fuse/cuse.c @@ -396,7 +396,7 @@ static void cuse_process_init_reply(struct fuse_conn *fc, struct fuse_req *req) err_region: unregister_chrdev_region(devt, 1); err: - fuse_conn_kill(fc); + fc->conn_error = 1; goto out; } @@ -532,6 +532,8 @@ static int cuse_channel_release(struct inode *inode, struct file *file) cdev_del(cc->cdev); } + /* kill connection and shutdown channel */ + fuse_conn_kill(&cc->fc); rc = fuse_dev_release(inode, file); /* puts the base reference */ return rc; diff --git a/trunk/fs/fuse/dev.c b/trunk/fs/fuse/dev.c index f4246cfc8d87..7df2b5e8fbe1 100644 --- a/trunk/fs/fuse/dev.c +++ b/trunk/fs/fuse/dev.c @@ -1576,7 +1576,6 @@ static int fuse_retrieve(struct fuse_conn *fc, struct inode *inode, req->pages[req->num_pages] = page; req->num_pages++; - offset = 0; num -= this_num; total_len += this_num; index++; diff --git a/trunk/fs/fuse/dir.c b/trunk/fs/fuse/dir.c index 324bc0850534..8964cf3999b2 100644 --- a/trunk/fs/fuse/dir.c +++ b/trunk/fs/fuse/dir.c @@ -383,9 +383,6 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry, struct fuse_entry_out outentry; struct fuse_file *ff; - /* Userspace expects S_IFREG in create mode */ - BUG_ON((mode & S_IFMT) != S_IFREG); - forget = fuse_alloc_forget(); err = -ENOMEM; if (!forget) diff --git a/trunk/fs/fuse/file.c b/trunk/fs/fuse/file.c index aba15f1b7ad2..93d8d6c9494d 100644 --- a/trunk/fs/fuse/file.c +++ b/trunk/fs/fuse/file.c @@ -703,16 +703,13 @@ static ssize_t fuse_file_aio_read(struct kiocb *iocb, const struct iovec *iov, unsigned long nr_segs, loff_t pos) { struct inode *inode = iocb->ki_filp->f_mapping->host; - struct fuse_conn *fc = get_fuse_conn(inode); - /* - * In auto invalidate mode, always update attributes on read. - * Otherwise, only update if we attempt to read past EOF (to ensure - * i_size is up to date). - */ - if (fc->auto_inval_data || - (pos + iov_length(iov, nr_segs) > i_size_read(inode))) { + if (pos + iov_length(iov, nr_segs) > i_size_read(inode)) { int err; + /* + * If trying to read past EOF, make sure the i_size + * attribute is up-to-date. + */ err = fuse_update_attributes(inode, NULL, iocb->ki_filp, NULL); if (err) return err; @@ -1703,7 +1700,7 @@ static int fuse_verify_ioctl_iov(struct iovec *iov, size_t count) size_t n; u32 max = FUSE_MAX_PAGES_PER_REQ << PAGE_SHIFT; - for (n = 0; n < count; n++, iov++) { + for (n = 0; n < count; n++) { if (iov->iov_len > (size_t) max) return -ENOMEM; max -= iov->iov_len; diff --git a/trunk/fs/fuse/fuse_i.h b/trunk/fs/fuse/fuse_i.h index e24dd74e3068..771fb6322c07 100644 --- a/trunk/fs/fuse/fuse_i.h +++ b/trunk/fs/fuse/fuse_i.h @@ -484,9 +484,6 @@ struct fuse_conn { /** Is fallocate not implemented by fs? */ unsigned no_fallocate:1; - /** Use enhanced/automatic page cache invalidation. */ - unsigned auto_inval_data:1; - /** The number of requests waiting for completion */ atomic_t num_waiting; diff --git a/trunk/fs/fuse/inode.c b/trunk/fs/fuse/inode.c index fca222dabe3c..1cd61652018c 100644 --- a/trunk/fs/fuse/inode.c +++ b/trunk/fs/fuse/inode.c @@ -197,7 +197,6 @@ void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr, struct fuse_conn *fc = get_fuse_conn(inode); struct fuse_inode *fi = get_fuse_inode(inode); loff_t oldsize; - struct timespec old_mtime; spin_lock(&fc->lock); if (attr_version != 0 && fi->attr_version > attr_version) { @@ -205,35 +204,15 @@ void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr, return; } - old_mtime = inode->i_mtime; fuse_change_attributes_common(inode, attr, attr_valid); oldsize = inode->i_size; i_size_write(inode, attr->size); spin_unlock(&fc->lock); - if (S_ISREG(inode->i_mode)) { - bool inval = false; - - if (oldsize != attr->size) { - truncate_pagecache(inode, oldsize, attr->size); - inval = true; - } else if (fc->auto_inval_data) { - struct timespec new_mtime = { - .tv_sec = attr->mtime, - .tv_nsec = attr->mtimensec, - }; - - /* - * Auto inval mode also checks and invalidates if mtime - * has changed. - */ - if (!timespec_equal(&old_mtime, &new_mtime)) - inval = true; - } - - if (inval) - invalidate_inode_pages2(inode->i_mapping); + if (S_ISREG(inode->i_mode) && oldsize != attr->size) { + truncate_pagecache(inode, oldsize, attr->size); + invalidate_inode_pages2(inode->i_mapping); } } @@ -367,6 +346,11 @@ void fuse_conn_kill(struct fuse_conn *fc) wake_up_all(&fc->waitq); wake_up_all(&fc->blocked_waitq); wake_up_all(&fc->reserved_req_waitq); + mutex_lock(&fuse_mutex); + list_del(&fc->entry); + fuse_ctl_remove_conn(fc); + mutex_unlock(&fuse_mutex); + fuse_bdi_destroy(fc); } EXPORT_SYMBOL_GPL(fuse_conn_kill); @@ -375,14 +359,7 @@ static void fuse_put_super(struct super_block *sb) struct fuse_conn *fc = get_fuse_conn_super(sb); fuse_send_destroy(fc); - fuse_conn_kill(fc); - mutex_lock(&fuse_mutex); - list_del(&fc->entry); - fuse_ctl_remove_conn(fc); - mutex_unlock(&fuse_mutex); - fuse_bdi_destroy(fc); - fuse_conn_put(fc); } @@ -857,8 +834,6 @@ static void process_init_reply(struct fuse_conn *fc, struct fuse_req *req) fc->big_writes = 1; if (arg->flags & FUSE_DONT_MASK) fc->dont_mask = 1; - if (arg->flags & FUSE_AUTO_INVAL_DATA) - fc->auto_inval_data = 1; } else { ra_pages = fc->max_read / PAGE_CACHE_SIZE; fc->no_lock = 1; @@ -884,8 +859,7 @@ static void fuse_send_init(struct fuse_conn *fc, struct fuse_req *req) arg->max_readahead = fc->bdi.ra_pages * PAGE_CACHE_SIZE; arg->flags |= FUSE_ASYNC_READ | FUSE_POSIX_LOCKS | FUSE_ATOMIC_O_TRUNC | FUSE_EXPORT_SUPPORT | FUSE_BIG_WRITES | FUSE_DONT_MASK | - FUSE_SPLICE_WRITE | FUSE_SPLICE_MOVE | FUSE_SPLICE_READ | - FUSE_FLOCK_LOCKS | FUSE_IOCTL_DIR | FUSE_AUTO_INVAL_DATA; + FUSE_FLOCK_LOCKS; req->in.h.opcode = FUSE_INIT; req->in.numargs = 1; req->in.args[0].size = sizeof(*arg); diff --git a/trunk/fs/gfs2/aops.c b/trunk/fs/gfs2/aops.c index 01c4975da4bc..d6526347d386 100644 --- a/trunk/fs/gfs2/aops.c +++ b/trunk/fs/gfs2/aops.c @@ -612,7 +612,6 @@ static int gfs2_write_begin(struct file *file, struct address_space *mapping, struct gfs2_sbd *sdp = GFS2_SB(mapping->host); struct gfs2_inode *m_ip = GFS2_I(sdp->sd_statfs_inode); unsigned int data_blocks = 0, ind_blocks = 0, rblocks; - unsigned requested = 0; int alloc_required; int error = 0; pgoff_t index = pos >> PAGE_CACHE_SHIFT; @@ -642,8 +641,7 @@ static int gfs2_write_begin(struct file *file, struct address_space *mapping, if (error) goto out_unlock; - requested = data_blocks + ind_blocks; - error = gfs2_inplace_reserve(ip, requested); + error = gfs2_inplace_reserve(ip, data_blocks + ind_blocks); if (error) goto out_qunlock; } @@ -656,7 +654,7 @@ static int gfs2_write_begin(struct file *file, struct address_space *mapping, if (&ip->i_inode == sdp->sd_rindex) rblocks += 2 * RES_STATFS; if (alloc_required) - rblocks += gfs2_rg_blocks(ip, requested); + rblocks += gfs2_rg_blocks(ip); error = gfs2_trans_begin(sdp, rblocks, PAGE_CACHE_SIZE/sdp->sd_sb.sb_bsize); @@ -870,7 +868,8 @@ static int gfs2_write_end(struct file *file, struct address_space *mapping, brelse(dibh); failed: gfs2_trans_end(sdp); - gfs2_inplace_release(ip); + if (gfs2_mb_reserved(ip)) + gfs2_inplace_release(ip); if (ip->i_res->rs_qa_qd_num) gfs2_quota_unlock(ip); if (inode == sdp->sd_rindex) { @@ -1024,7 +1023,7 @@ static ssize_t gfs2_direct_IO(int rw, struct kiocb *iocb, offset, nr_segs, gfs2_get_block_direct, NULL, NULL, 0); out: - gfs2_glock_dq(&gh); + gfs2_glock_dq_m(1, &gh); gfs2_holder_uninit(&gh); return rv; } diff --git a/trunk/fs/gfs2/bmap.c b/trunk/fs/gfs2/bmap.c index 1fd3ae237bdd..49cd7dd4a9fa 100644 --- a/trunk/fs/gfs2/bmap.c +++ b/trunk/fs/gfs2/bmap.c @@ -786,7 +786,7 @@ static int do_strip(struct gfs2_inode *ip, struct buffer_head *dibh, goto out_rlist; if (gfs2_rs_active(ip->i_res)) /* needs to be done with the rgrp glock held */ - gfs2_rs_deltree(ip, ip->i_res); + gfs2_rs_deltree(ip->i_res); error = gfs2_trans_begin(sdp, rg_blocks + RES_DINODE + RES_INDIRECT + RES_STATFS + RES_QUOTA, diff --git a/trunk/fs/gfs2/file.c b/trunk/fs/gfs2/file.c index 30e21997a1a1..d1d791ef38de 100644 --- a/trunk/fs/gfs2/file.c +++ b/trunk/fs/gfs2/file.c @@ -322,29 +322,6 @@ static long gfs2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) return -ENOTTY; } -/** - * gfs2_size_hint - Give a hint to the size of a write request - * @file: The struct file - * @offset: The file offset of the write - * @size: The length of the write - * - * When we are about to do a write, this function records the total - * write size in order to provide a suitable hint to the lower layers - * about how many blocks will be required. - * - */ - -static void gfs2_size_hint(struct file *filep, loff_t offset, size_t size) -{ - struct inode *inode = filep->f_dentry->d_inode; - struct gfs2_sbd *sdp = GFS2_SB(inode); - struct gfs2_inode *ip = GFS2_I(inode); - size_t blks = (size + sdp->sd_sb.sb_bsize - 1) >> sdp->sd_sb.sb_bsize_shift; - int hint = min_t(size_t, INT_MAX, blks); - - atomic_set(&ip->i_res->rs_sizehint, hint); -} - /** * gfs2_allocate_page_backing - Use bmap to allocate blocks * @page: The (locked) page to allocate backing for @@ -405,7 +382,8 @@ static int gfs2_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) if (ret) return ret; - gfs2_size_hint(vma->vm_file, pos, PAGE_CACHE_SIZE); + atomic_set(&ip->i_res->rs_sizehint, + PAGE_CACHE_SIZE >> sdp->sd_sb.sb_bsize_shift); gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh); ret = gfs2_glock_nq(&gh); @@ -441,7 +419,7 @@ static int gfs2_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) rblocks += data_blocks ? data_blocks : 1; if (ind_blocks || data_blocks) { rblocks += RES_STATFS + RES_QUOTA; - rblocks += gfs2_rg_blocks(ip, data_blocks + ind_blocks); + rblocks += gfs2_rg_blocks(ip); } ret = gfs2_trans_begin(sdp, rblocks, 0); if (ret) @@ -685,8 +663,7 @@ static ssize_t gfs2_file_aio_write(struct kiocb *iocb, const struct iovec *iov, if (ret) return ret; - gfs2_size_hint(file, pos, writesize); - + atomic_set(&ip->i_res->rs_sizehint, writesize >> sdp->sd_sb.sb_bsize_shift); if (file->f_flags & O_APPEND) { struct gfs2_holder gh; @@ -812,7 +789,7 @@ static long gfs2_fallocate(struct file *file, int mode, loff_t offset, if (unlikely(error)) goto out_uninit; - gfs2_size_hint(file, offset, len); + atomic_set(&ip->i_res->rs_sizehint, len >> sdp->sd_sb.sb_bsize_shift); while (len > 0) { if (len < bytes) @@ -845,7 +822,7 @@ static long gfs2_fallocate(struct file *file, int mode, loff_t offset, &max_bytes, &data_blocks, &ind_blocks); rblocks = RES_DINODE + ind_blocks + RES_STATFS + RES_QUOTA + - RES_RG_HDR + gfs2_rg_blocks(ip, data_blocks + ind_blocks); + RES_RG_HDR + gfs2_rg_blocks(ip); if (gfs2_is_jdata(ip)) rblocks += data_blocks ? data_blocks : 1; diff --git a/trunk/fs/gfs2/glock.c b/trunk/fs/gfs2/glock.c index e6c2fd53cab2..1ed81f40da0d 100644 --- a/trunk/fs/gfs2/glock.c +++ b/trunk/fs/gfs2/glock.c @@ -185,6 +185,20 @@ static void gfs2_glock_remove_from_lru(struct gfs2_glock *gl) spin_unlock(&lru_lock); } +/** + * __gfs2_glock_schedule_for_reclaim - Add a glock to the reclaim list + * @gl: the glock + * + * If the glock is demotable, then we add it (or move it) to the end + * of the glock LRU list. + */ + +static void __gfs2_glock_schedule_for_reclaim(struct gfs2_glock *gl) +{ + if (demote_ok(gl)) + gfs2_glock_add_to_lru(gl); +} + /** * gfs2_glock_put_nolock() - Decrement reference count on glock * @gl: The glock to put @@ -869,14 +883,7 @@ static int gfs2_glock_demote_wait(void *word) return 0; } -/** - * gfs2_glock_wait - wait on a glock acquisition - * @gh: the glock holder - * - * Returns: 0 on success - */ - -int gfs2_glock_wait(struct gfs2_holder *gh) +static void wait_on_holder(struct gfs2_holder *gh) { unsigned long time1 = jiffies; @@ -887,7 +894,12 @@ int gfs2_glock_wait(struct gfs2_holder *gh) gh->gh_gl->gl_hold_time = min(gh->gh_gl->gl_hold_time + GL_GLOCK_HOLD_INCR, GL_GLOCK_MAX_HOLD); - return gh->gh_error; +} + +static void wait_on_demote(struct gfs2_glock *gl) +{ + might_sleep(); + wait_on_bit(&gl->gl_flags, GLF_DEMOTE, gfs2_glock_demote_wait, TASK_UNINTERRUPTIBLE); } /** @@ -917,6 +929,19 @@ static void handle_callback(struct gfs2_glock *gl, unsigned int state, trace_gfs2_demote_rq(gl); } +/** + * gfs2_glock_wait - wait on a glock acquisition + * @gh: the glock holder + * + * Returns: 0 on success + */ + +int gfs2_glock_wait(struct gfs2_holder *gh) +{ + wait_on_holder(gh); + return gh->gh_error; +} + void gfs2_print_dbg(struct seq_file *seq, const char *fmt, ...) { struct va_format vaf; @@ -954,7 +979,7 @@ __acquires(&gl->gl_spin) struct gfs2_sbd *sdp = gl->gl_sbd; struct list_head *insert_pt = NULL; struct gfs2_holder *gh2; - int try_futile = 0; + int try_lock = 0; BUG_ON(gh->gh_owner_pid == NULL); if (test_and_set_bit(HIF_WAIT, &gh->gh_iflags)) @@ -962,7 +987,7 @@ __acquires(&gl->gl_spin) if (gh->gh_flags & (LM_FLAG_TRY | LM_FLAG_TRY_1CB)) { if (test_bit(GLF_LOCK, &gl->gl_flags)) - try_futile = !may_grant(gl, gh); + try_lock = 1; if (test_bit(GLF_INVALIDATE_IN_PROGRESS, &gl->gl_flags)) goto fail; } @@ -971,8 +996,9 @@ __acquires(&gl->gl_spin) if (unlikely(gh2->gh_owner_pid == gh->gh_owner_pid && (gh->gh_gl->gl_ops->go_type != LM_TYPE_FLOCK))) goto trap_recursive; - if (try_futile && - !(gh2->gh_flags & (LM_FLAG_TRY | LM_FLAG_TRY_1CB))) { + if (try_lock && + !(gh2->gh_flags & (LM_FLAG_TRY | LM_FLAG_TRY_1CB)) && + !may_grant(gl, gh)) { fail: gh->gh_error = GLR_TRYFAILED; gfs2_holder_wake(gh); @@ -1095,9 +1121,8 @@ void gfs2_glock_dq(struct gfs2_holder *gh) !test_bit(GLF_DEMOTE, &gl->gl_flags)) fast_path = 1; } - if (!test_bit(GLF_LFLUSH, &gl->gl_flags) && demote_ok(gl)) - gfs2_glock_add_to_lru(gl); - + if (!test_bit(GLF_LFLUSH, &gl->gl_flags)) + __gfs2_glock_schedule_for_reclaim(gl); trace_gfs2_glock_queue(gh, 0); spin_unlock(&gl->gl_spin); if (likely(fast_path)) @@ -1116,8 +1141,7 @@ void gfs2_glock_dq_wait(struct gfs2_holder *gh) { struct gfs2_glock *gl = gh->gh_gl; gfs2_glock_dq(gh); - might_sleep(); - wait_on_bit(&gl->gl_flags, GLF_DEMOTE, gfs2_glock_demote_wait, TASK_UNINTERRUPTIBLE); + wait_on_demote(gl); } /** diff --git a/trunk/fs/gfs2/glops.c b/trunk/fs/gfs2/glops.c index 32cc4fde975c..4bdcf3784187 100644 --- a/trunk/fs/gfs2/glops.c +++ b/trunk/fs/gfs2/glops.c @@ -94,7 +94,6 @@ static void gfs2_ail_empty_gl(struct gfs2_glock *gl) /* A shortened, inline version of gfs2_trans_begin() */ tr.tr_reserved = 1 + gfs2_struct2blk(sdp, tr.tr_revokes, sizeof(u64)); tr.tr_ip = (unsigned long)__builtin_return_address(0); - sb_start_intwrite(sdp->sd_vfs); gfs2_log_reserve(sdp, tr.tr_reserved); BUG_ON(current->journal_info); current->journal_info = &tr; diff --git a/trunk/fs/gfs2/incore.h b/trunk/fs/gfs2/incore.h index 3d469d37345e..aaecc8085fc5 100644 --- a/trunk/fs/gfs2/incore.h +++ b/trunk/fs/gfs2/incore.h @@ -99,26 +99,9 @@ struct gfs2_rgrpd { #define GFS2_RDF_MASK 0xf0000000 /* mask for internal flags */ spinlock_t rd_rsspin; /* protects reservation related vars */ struct rb_root rd_rstree; /* multi-block reservation tree */ + u32 rd_rs_cnt; /* count of current reservations */ }; -struct gfs2_rbm { - struct gfs2_rgrpd *rgd; - struct gfs2_bitmap *bi; /* Bitmap must belong to the rgd */ - u32 offset; /* The offset is bitmap relative */ -}; - -static inline u64 gfs2_rbm_to_block(const struct gfs2_rbm *rbm) -{ - return rbm->rgd->rd_data0 + (rbm->bi->bi_start * GFS2_NBBY) + rbm->offset; -} - -static inline bool gfs2_rbm_eq(const struct gfs2_rbm *rbm1, - const struct gfs2_rbm *rbm2) -{ - return (rbm1->rgd == rbm2->rgd) && (rbm1->bi == rbm2->bi) && - (rbm1->offset == rbm2->offset); -} - enum gfs2_state_bits { BH_Pinned = BH_PrivateStart, BH_Escaped = BH_PrivateStart + 1, @@ -267,11 +250,18 @@ struct gfs2_blkreserv { /* components used during write (step 1): */ atomic_t rs_sizehint; /* hint of the write size */ + /* components used during inplace_reserve (step 2): */ + u32 rs_requested; /* Filled in by caller of gfs2_inplace_reserve() */ + + /* components used during get_local_rgrp (step 3): */ + struct gfs2_rgrpd *rs_rgd; /* pointer to the gfs2_rgrpd */ struct gfs2_holder rs_rgd_gh; /* Filled in by get_local_rgrp */ struct rb_node rs_node; /* link to other block reservations */ - struct gfs2_rbm rs_rbm; /* Start of reservation */ + + /* components used during block searches and assignments (step 4): */ + struct gfs2_bitmap *rs_bi; /* bitmap for the current allocation */ + u32 rs_biblk; /* start block relative to the bi */ u32 rs_free; /* how many blocks are still free */ - u64 rs_inum; /* Inode number for reservation */ /* ancillary quota stuff */ struct gfs2_quota_data *rs_qa_qd[2 * MAXQUOTAS]; diff --git a/trunk/fs/gfs2/inode.c b/trunk/fs/gfs2/inode.c index 381893ceefa4..4ce22e547308 100644 --- a/trunk/fs/gfs2/inode.c +++ b/trunk/fs/gfs2/inode.c @@ -712,9 +712,14 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry, if (error) goto fail_gunlock2; - error = gfs2_rs_alloc(ip); - if (error) - goto fail_gunlock2; + /* The newly created inode needs a reservation so it can allocate + xattrs. At the same time, we want new blocks allocated to the new + dinode to be as contiguous as possible. Since we allocated the + dinode block under the directory's reservation, we transfer + ownership of that reservation to the new inode. The directory + doesn't need a reservation unless it needs a new allocation. */ + ip->i_res = dip->i_res; + dip->i_res = NULL; error = gfs2_acl_create(dip, inode); if (error) @@ -732,7 +737,10 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry, brelse(bh); gfs2_trans_end(sdp); - gfs2_inplace_release(dip); + /* Check if we reserved space in the rgrp. Function link_dinode may + not, depending on whether alloc is required. */ + if (gfs2_mb_reserved(dip)) + gfs2_inplace_release(dip); gfs2_quota_unlock(dip); mark_inode_dirty(inode); gfs2_glock_dq_uninit_m(2, ghs); @@ -889,7 +897,7 @@ static int gfs2_link(struct dentry *old_dentry, struct inode *dir, goto out_gunlock_q; error = gfs2_trans_begin(sdp, sdp->sd_max_dirres + - gfs2_rg_blocks(dip, sdp->sd_max_dirres) + + gfs2_rg_blocks(dip) + 2 * RES_DINODE + RES_STATFS + RES_QUOTA, 0); if (error) @@ -1370,7 +1378,7 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry, goto out_gunlock_q; error = gfs2_trans_begin(sdp, sdp->sd_max_dirres + - gfs2_rg_blocks(ndip, sdp->sd_max_dirres) + + gfs2_rg_blocks(ndip) + 4 * RES_DINODE + 4 * RES_LEAF + RES_STATFS + RES_QUOTA + 4, 0); if (error) @@ -1714,9 +1722,7 @@ static int gfs2_setxattr(struct dentry *dentry, const char *name, gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh); ret = gfs2_glock_nq(&gh); if (ret == 0) { - ret = gfs2_rs_alloc(ip); - if (ret == 0) - ret = generic_setxattr(dentry, name, data, size, flags); + ret = generic_setxattr(dentry, name, data, size, flags); gfs2_glock_dq(&gh); } gfs2_holder_uninit(&gh); @@ -1751,9 +1757,7 @@ static int gfs2_removexattr(struct dentry *dentry, const char *name) gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh); ret = gfs2_glock_nq(&gh); if (ret == 0) { - ret = gfs2_rs_alloc(ip); - if (ret == 0) - ret = generic_removexattr(dentry, name); + ret = generic_removexattr(dentry, name); gfs2_glock_dq(&gh); } gfs2_holder_uninit(&gh); diff --git a/trunk/fs/gfs2/meta_io.c b/trunk/fs/gfs2/meta_io.c index 22255d96b27e..3a56c8d94de0 100644 --- a/trunk/fs/gfs2/meta_io.c +++ b/trunk/fs/gfs2/meta_io.c @@ -52,7 +52,7 @@ static int gfs2_aspace_writepage(struct page *page, struct writeback_control *wb /* * If it's a fully non-blocking write attempt and we cannot * lock the buffer then redirty the page. Note that this can - * potentially cause a busy-wait loop from flusher thread and kswapd + * potentially cause a busy-wait loop from pdflush and kswapd * activity, but those code paths have their own higher-level * throttling. */ diff --git a/trunk/fs/gfs2/ops_fstype.c b/trunk/fs/gfs2/ops_fstype.c index e443966c8106..e5af9dc420ef 100644 --- a/trunk/fs/gfs2/ops_fstype.c +++ b/trunk/fs/gfs2/ops_fstype.c @@ -19,7 +19,6 @@ #include #include #include -#include #include "gfs2.h" #include "incore.h" @@ -767,7 +766,6 @@ static int init_journal(struct gfs2_sbd *sdp, int undo) return error; } -static struct lock_class_key gfs2_quota_imutex_key; static int init_inodes(struct gfs2_sbd *sdp, int undo) { @@ -805,12 +803,6 @@ static int init_inodes(struct gfs2_sbd *sdp, int undo) fs_err(sdp, "can't get quota file inode: %d\n", error); goto fail_rindex; } - /* - * i_mutex on quota files is special. Since this inode is hidden system - * file, we are safe to define locking ourselves. - */ - lockdep_set_class(&sdp->sd_quota_inode->i_mutex, - &gfs2_quota_imutex_key); error = gfs2_rindex_update(sdp); if (error) diff --git a/trunk/fs/gfs2/quota.c b/trunk/fs/gfs2/quota.c index 4021deca61ef..a3bde91645c2 100644 --- a/trunk/fs/gfs2/quota.c +++ b/trunk/fs/gfs2/quota.c @@ -765,7 +765,6 @@ static int do_sync(unsigned int num_qd, struct gfs2_quota_data **qda) struct gfs2_holder *ghs, i_gh; unsigned int qx, x; struct gfs2_quota_data *qd; - unsigned reserved; loff_t offset; unsigned int nalloc = 0, blocks; int error; @@ -782,7 +781,7 @@ static int do_sync(unsigned int num_qd, struct gfs2_quota_data **qda) return -ENOMEM; sort(qda, num_qd, sizeof(struct gfs2_quota_data *), sort_qd, NULL); - mutex_lock(&ip->i_inode.i_mutex); + mutex_lock_nested(&ip->i_inode.i_mutex, I_MUTEX_QUOTA); for (qx = 0; qx < num_qd; qx++) { error = gfs2_glock_nq_init(qda[qx]->qd_gl, LM_ST_EXCLUSIVE, GL_NOCACHE, &ghs[qx]); @@ -812,13 +811,13 @@ static int do_sync(unsigned int num_qd, struct gfs2_quota_data **qda) * two blocks need to be updated instead of 1 */ blocks = num_qd * data_blocks + RES_DINODE + num_qd + 3; - reserved = 1 + (nalloc * (data_blocks + ind_blocks)); - error = gfs2_inplace_reserve(ip, reserved); + error = gfs2_inplace_reserve(ip, 1 + + (nalloc * (data_blocks + ind_blocks))); if (error) goto out_alloc; if (nalloc) - blocks += gfs2_rg_blocks(ip, reserved) + nalloc * ind_blocks + RES_STATFS; + blocks += gfs2_rg_blocks(ip) + nalloc * ind_blocks + RES_STATFS; error = gfs2_trans_begin(sdp, blocks, 0); if (error) @@ -1599,7 +1598,7 @@ static int gfs2_set_dqblk(struct super_block *sb, int type, qid_t id, error = gfs2_inplace_reserve(ip, blocks); if (error) goto out_i; - blocks += gfs2_rg_blocks(ip, blocks); + blocks += gfs2_rg_blocks(ip); } /* Some quotas span block boundaries and can update two blocks, diff --git a/trunk/fs/gfs2/rgrp.c b/trunk/fs/gfs2/rgrp.c index 3cc402ce6fea..4d34887a601d 100644 --- a/trunk/fs/gfs2/rgrp.c +++ b/trunk/fs/gfs2/rgrp.c @@ -35,6 +35,9 @@ #define BFITNOENT ((u32)~0) #define NO_BLOCK ((u64)~0) +#define RSRV_CONTENTION_FACTOR 4 +#define RGRP_RSRV_MAX_CONTENDERS 2 + #if BITS_PER_LONG == 32 #define LBITMASK (0x55555555UL) #define LBITSKIP55 (0x55555555UL) @@ -64,48 +67,53 @@ static const char valid_change[16] = { 1, 0, 0, 0 }; -static int gfs2_rbm_find(struct gfs2_rbm *rbm, u8 state, u32 minext, - const struct gfs2_inode *ip, bool nowrap); - +static u32 rgblk_search(struct gfs2_rgrpd *rgd, u32 goal, + unsigned char old_state, + struct gfs2_bitmap **rbi); /** * gfs2_setbit - Set a bit in the bitmaps - * @rbm: The position of the bit to set - * @do_clone: Also set the clone bitmap, if it exists + * @rgd: the resource group descriptor + * @buf2: the clone buffer that holds the bitmaps + * @bi: the bitmap structure + * @block: the block to set * @new_state: the new state of the block * */ -static inline void gfs2_setbit(const struct gfs2_rbm *rbm, bool do_clone, +static inline void gfs2_setbit(struct gfs2_rgrpd *rgd, unsigned char *buf2, + struct gfs2_bitmap *bi, u32 block, unsigned char new_state) { unsigned char *byte1, *byte2, *end, cur_state; - unsigned int buflen = rbm->bi->bi_len; - const unsigned int bit = (rbm->offset % GFS2_NBBY) * GFS2_BIT_SIZE; + unsigned int buflen = bi->bi_len; + const unsigned int bit = (block % GFS2_NBBY) * GFS2_BIT_SIZE; - byte1 = rbm->bi->bi_bh->b_data + rbm->bi->bi_offset + (rbm->offset / GFS2_NBBY); - end = rbm->bi->bi_bh->b_data + rbm->bi->bi_offset + buflen; + byte1 = bi->bi_bh->b_data + bi->bi_offset + (block / GFS2_NBBY); + end = bi->bi_bh->b_data + bi->bi_offset + buflen; BUG_ON(byte1 >= end); cur_state = (*byte1 >> bit) & GFS2_BIT_MASK; if (unlikely(!valid_change[new_state * 4 + cur_state])) { - printk(KERN_WARNING "GFS2: buf_blk = 0x%x old_state=%d, " - "new_state=%d\n", rbm->offset, cur_state, new_state); - printk(KERN_WARNING "GFS2: rgrp=0x%llx bi_start=0x%x\n", - (unsigned long long)rbm->rgd->rd_addr, - rbm->bi->bi_start); - printk(KERN_WARNING "GFS2: bi_offset=0x%x bi_len=0x%x\n", - rbm->bi->bi_offset, rbm->bi->bi_len); + printk(KERN_WARNING "GFS2: buf_blk = 0x%llx old_state=%d, " + "new_state=%d\n", + (unsigned long long)block, cur_state, new_state); + printk(KERN_WARNING "GFS2: rgrp=0x%llx bi_start=0x%lx\n", + (unsigned long long)rgd->rd_addr, + (unsigned long)bi->bi_start); + printk(KERN_WARNING "GFS2: bi_offset=0x%lx bi_len=0x%lx\n", + (unsigned long)bi->bi_offset, + (unsigned long)bi->bi_len); dump_stack(); - gfs2_consist_rgrpd(rbm->rgd); + gfs2_consist_rgrpd(rgd); return; } *byte1 ^= (cur_state ^ new_state) << bit; - if (do_clone && rbm->bi->bi_clone) { - byte2 = rbm->bi->bi_clone + rbm->bi->bi_offset + (rbm->offset / GFS2_NBBY); + if (buf2) { + byte2 = buf2 + bi->bi_offset + (block / GFS2_NBBY); cur_state = (*byte2 >> bit) & GFS2_BIT_MASK; *byte2 ^= (cur_state ^ new_state) << bit; } @@ -113,21 +121,30 @@ static inline void gfs2_setbit(const struct gfs2_rbm *rbm, bool do_clone, /** * gfs2_testbit - test a bit in the bitmaps - * @rbm: The bit to test + * @rgd: the resource group descriptor + * @buffer: the buffer that holds the bitmaps + * @buflen: the length (in bytes) of the buffer + * @block: the block to read * - * Returns: The two bit block state of the requested bit */ -static inline u8 gfs2_testbit(const struct gfs2_rbm *rbm) +static inline unsigned char gfs2_testbit(struct gfs2_rgrpd *rgd, + const unsigned char *buffer, + unsigned int buflen, u32 block) { - const u8 *buffer = rbm->bi->bi_bh->b_data + rbm->bi->bi_offset; - const u8 *byte; + const unsigned char *byte, *end; + unsigned char cur_state; unsigned int bit; - byte = buffer + (rbm->offset / GFS2_NBBY); - bit = (rbm->offset % GFS2_NBBY) * GFS2_BIT_SIZE; + byte = buffer + (block / GFS2_NBBY); + bit = (block % GFS2_NBBY) * GFS2_BIT_SIZE; + end = buffer + buflen; + + gfs2_assert(rgd->rd_sbd, byte < end); - return (*byte >> bit) & GFS2_BIT_MASK; + cur_state = (*byte >> bit) & GFS2_BIT_MASK; + + return cur_state; } /** @@ -175,7 +192,7 @@ static inline u64 gfs2_bit_search(const __le64 *ptr, u64 mask, u8 state) */ static inline int rs_cmp(u64 blk, u32 len, struct gfs2_blkreserv *rs) { - u64 startblk = gfs2_rbm_to_block(&rs->rs_rbm); + u64 startblk = gfs2_rs_startblk(rs); if (blk >= startblk + rs->rs_free) return 1; @@ -184,6 +201,36 @@ static inline int rs_cmp(u64 blk, u32 len, struct gfs2_blkreserv *rs) return 0; } +/** + * rs_find - Find a rgrp multi-block reservation that contains a given block + * @rgd: The rgrp + * @rgblk: The block we're looking for, relative to the rgrp + */ +static struct gfs2_blkreserv *rs_find(struct gfs2_rgrpd *rgd, u32 rgblk) +{ + struct rb_node **newn; + int rc; + u64 fsblk = rgblk + rgd->rd_data0; + + spin_lock(&rgd->rd_rsspin); + newn = &rgd->rd_rstree.rb_node; + while (*newn) { + struct gfs2_blkreserv *cur = + rb_entry(*newn, struct gfs2_blkreserv, rs_node); + rc = rs_cmp(fsblk, 1, cur); + if (rc < 0) + newn = &((*newn)->rb_left); + else if (rc > 0) + newn = &((*newn)->rb_right); + else { + spin_unlock(&rgd->rd_rsspin); + return cur; + } + } + spin_unlock(&rgd->rd_rsspin); + return NULL; +} + /** * gfs2_bitfit - Search an rgrp's bitmap buffer to find a bit-pair representing * a block in a given allocation state. @@ -215,6 +262,8 @@ static u32 gfs2_bitfit(const u8 *buf, const unsigned int len, u64 mask = 0x5555555555555555ULL; u32 bit; + BUG_ON(state > 3); + /* Mask off bits we don't care about at the start of the search */ mask <<= spoint; tmp = gfs2_bit_search(ptr, mask, state); @@ -235,131 +284,6 @@ static u32 gfs2_bitfit(const u8 *buf, const unsigned int len, return (((const unsigned char *)ptr - buf) * GFS2_NBBY) + bit; } -/** - * gfs2_rbm_from_block - Set the rbm based upon rgd and block number - * @rbm: The rbm with rgd already set correctly - * @block: The block number (filesystem relative) - * - * This sets the bi and offset members of an rbm based on a - * resource group and a filesystem relative block number. The - * resource group must be set in the rbm on entry, the bi and - * offset members will be set by this function. - * - * Returns: 0 on success, or an error code - */ - -static int gfs2_rbm_from_block(struct gfs2_rbm *rbm, u64 block) -{ - u64 rblock = block - rbm->rgd->rd_data0; - u32 goal = (u32)rblock; - int x; - - if (WARN_ON_ONCE(rblock > UINT_MAX)) - return -EINVAL; - if (block >= rbm->rgd->rd_data0 + rbm->rgd->rd_data) - return -E2BIG; - - for (x = 0; x < rbm->rgd->rd_length; x++) { - rbm->bi = rbm->rgd->rd_bits + x; - if (goal < (rbm->bi->bi_start + rbm->bi->bi_len) * GFS2_NBBY) { - rbm->offset = goal - (rbm->bi->bi_start * GFS2_NBBY); - break; - } - } - - return 0; -} - -/** - * gfs2_unaligned_extlen - Look for free blocks which are not byte aligned - * @rbm: Position to search (value/result) - * @n_unaligned: Number of unaligned blocks to check - * @len: Decremented for each block found (terminate on zero) - * - * Returns: true if a non-free block is encountered - */ - -static bool gfs2_unaligned_extlen(struct gfs2_rbm *rbm, u32 n_unaligned, u32 *len) -{ - u64 block; - u32 n; - u8 res; - - for (n = 0; n < n_unaligned; n++) { - res = gfs2_testbit(rbm); - if (res != GFS2_BLKST_FREE) - return true; - (*len)--; - if (*len == 0) - return true; - block = gfs2_rbm_to_block(rbm); - if (gfs2_rbm_from_block(rbm, block + 1)) - return true; - } - - return false; -} - -/** - * gfs2_free_extlen - Return extent length of free blocks - * @rbm: Starting position - * @len: Max length to check - * - * Starting at the block specified by the rbm, see how many free blocks - * there are, not reading more than len blocks ahead. This can be done - * using memchr_inv when the blocks are byte aligned, but has to be done - * on a block by block basis in case of unaligned blocks. Also this - * function can cope with bitmap boundaries (although it must stop on - * a resource group boundary) - * - * Returns: Number of free blocks in the extent - */ - -static u32 gfs2_free_extlen(const struct gfs2_rbm *rrbm, u32 len) -{ - struct gfs2_rbm rbm = *rrbm; - u32 n_unaligned = rbm.offset & 3; - u32 size = len; - u32 bytes; - u32 chunk_size; - u8 *ptr, *start, *end; - u64 block; - - if (n_unaligned && - gfs2_unaligned_extlen(&rbm, 4 - n_unaligned, &len)) - goto out; - - n_unaligned = len & 3; - /* Start is now byte aligned */ - while (len > 3) { - start = rbm.bi->bi_bh->b_data; - if (rbm.bi->bi_clone) - start = rbm.bi->bi_clone; - end = start + rbm.bi->bi_bh->b_size; - start += rbm.bi->bi_offset; - BUG_ON(rbm.offset & 3); - start += (rbm.offset / GFS2_NBBY); - bytes = min_t(u32, len / GFS2_NBBY, (end - start)); - ptr = memchr_inv(start, 0, bytes); - chunk_size = ((ptr == NULL) ? bytes : (ptr - start)); - chunk_size *= GFS2_NBBY; - BUG_ON(len < chunk_size); - len -= chunk_size; - block = gfs2_rbm_to_block(&rbm); - gfs2_rbm_from_block(&rbm, block + chunk_size); - n_unaligned = 3; - if (ptr) - break; - n_unaligned = len & 3; - } - - /* Deal with any bits left over at the end */ - if (n_unaligned) - gfs2_unaligned_extlen(&rbm, n_unaligned, &len); -out: - return size - len; -} - /** * gfs2_bitcount - count the number of bits in a certain state * @rgd: the resource group descriptor @@ -563,8 +487,6 @@ int gfs2_rs_alloc(struct gfs2_inode *ip) if (!res) error = -ENOMEM; - RB_CLEAR_NODE(&res->rs_node); - down_write(&ip->i_rw_mutex); if (ip->i_res) kmem_cache_free(gfs2_rsrv_cachep, res); @@ -574,12 +496,11 @@ int gfs2_rs_alloc(struct gfs2_inode *ip) return error; } -static void dump_rs(struct seq_file *seq, const struct gfs2_blkreserv *rs) +static void dump_rs(struct seq_file *seq, struct gfs2_blkreserv *rs) { - gfs2_print_dbg(seq, " B: n:%llu s:%llu b:%u f:%u\n", - (unsigned long long)rs->rs_inum, - (unsigned long long)gfs2_rbm_to_block(&rs->rs_rbm), - rs->rs_rbm.offset, rs->rs_free); + gfs2_print_dbg(seq, " r: %llu s:%llu b:%u f:%u\n", + rs->rs_rgd->rd_addr, gfs2_rs_startblk(rs), rs->rs_biblk, + rs->rs_free); } /** @@ -587,26 +508,41 @@ static void dump_rs(struct seq_file *seq, const struct gfs2_blkreserv *rs) * @rs: The reservation to remove * */ -static void __rs_deltree(struct gfs2_inode *ip, struct gfs2_blkreserv *rs) +static void __rs_deltree(struct gfs2_blkreserv *rs) { struct gfs2_rgrpd *rgd; if (!gfs2_rs_active(rs)) return; - rgd = rs->rs_rbm.rgd; - trace_gfs2_rs(rs, TRACE_RS_TREEDEL); - rb_erase(&rs->rs_node, &rgd->rd_rstree); - RB_CLEAR_NODE(&rs->rs_node); + rgd = rs->rs_rgd; + /* We can't do this: The reason is that when the rgrp is invalidated, + it's in the "middle" of acquiring the glock, but the HOLDER bit + isn't set yet: + BUG_ON(!gfs2_glock_is_locked_by_me(rs->rs_rgd->rd_gl));*/ + trace_gfs2_rs(NULL, rs, TRACE_RS_TREEDEL); + + if (!RB_EMPTY_ROOT(&rgd->rd_rstree)) + rb_erase(&rs->rs_node, &rgd->rd_rstree); + BUG_ON(!rgd->rd_rs_cnt); + rgd->rd_rs_cnt--; if (rs->rs_free) { /* return reserved blocks to the rgrp and the ip */ - BUG_ON(rs->rs_rbm.rgd->rd_reserved < rs->rs_free); - rs->rs_rbm.rgd->rd_reserved -= rs->rs_free; + BUG_ON(rs->rs_rgd->rd_reserved < rs->rs_free); + rs->rs_rgd->rd_reserved -= rs->rs_free; rs->rs_free = 0; - clear_bit(GBF_FULL, &rs->rs_rbm.bi->bi_flags); + clear_bit(GBF_FULL, &rs->rs_bi->bi_flags); smp_mb__after_clear_bit(); } + /* We can't change any of the step 1 or step 2 components of the rs. + E.g. We can't set rs_rgd to NULL because the rgd glock is held and + dequeued through this pointer. + Can't: atomic_set(&rs->rs_sizehint, 0); + Can't: rs->rs_requested = 0; + Can't: rs->rs_rgd = NULL;*/ + rs->rs_bi = NULL; + rs->rs_biblk = 0; } /** @@ -614,16 +550,17 @@ static void __rs_deltree(struct gfs2_inode *ip, struct gfs2_blkreserv *rs) * @rs: The reservation to remove * */ -void gfs2_rs_deltree(struct gfs2_inode *ip, struct gfs2_blkreserv *rs) +void gfs2_rs_deltree(struct gfs2_blkreserv *rs) { struct gfs2_rgrpd *rgd; - rgd = rs->rs_rbm.rgd; - if (rgd) { - spin_lock(&rgd->rd_rsspin); - __rs_deltree(ip, rs); - spin_unlock(&rgd->rd_rsspin); - } + if (!gfs2_rs_active(rs)) + return; + + rgd = rs->rs_rgd; + spin_lock(&rgd->rd_rsspin); + __rs_deltree(rs); + spin_unlock(&rgd->rd_rsspin); } /** @@ -635,7 +572,8 @@ void gfs2_rs_delete(struct gfs2_inode *ip) { down_write(&ip->i_rw_mutex); if (ip->i_res) { - gfs2_rs_deltree(ip, ip->i_res); + gfs2_rs_deltree(ip->i_res); + trace_gfs2_rs(ip, ip->i_res, TRACE_RS_DELETE); BUG_ON(ip->i_res->rs_free); kmem_cache_free(gfs2_rsrv_cachep, ip->i_res); ip->i_res = NULL; @@ -659,7 +597,7 @@ static void return_all_reservations(struct gfs2_rgrpd *rgd) spin_lock(&rgd->rd_rsspin); while ((n = rb_first(&rgd->rd_rstree))) { rs = rb_entry(n, struct gfs2_blkreserv, rs_node); - __rs_deltree(NULL, rs); + __rs_deltree(rs); } spin_unlock(&rgd->rd_rsspin); } @@ -1332,276 +1270,211 @@ int gfs2_fitrim(struct file *filp, void __user *argp) /** * rs_insert - insert a new multi-block reservation into the rgrp's rb_tree + * @bi: the bitmap with the blocks * @ip: the inode structure + * @biblk: the 32-bit block number relative to the start of the bitmap + * @amount: the number of blocks to reserve * + * Returns: NULL - reservation was already taken, so not inserted + * pointer to the inserted reservation */ -static void rs_insert(struct gfs2_inode *ip) +static struct gfs2_blkreserv *rs_insert(struct gfs2_bitmap *bi, + struct gfs2_inode *ip, u32 biblk, + int amount) { struct rb_node **newn, *parent = NULL; int rc; struct gfs2_blkreserv *rs = ip->i_res; - struct gfs2_rgrpd *rgd = rs->rs_rbm.rgd; - u64 fsblock = gfs2_rbm_to_block(&rs->rs_rbm); - - BUG_ON(gfs2_rs_active(rs)); + struct gfs2_rgrpd *rgd = rs->rs_rgd; + u64 fsblock = gfs2_bi2rgd_blk(bi, biblk) + rgd->rd_data0; spin_lock(&rgd->rd_rsspin); newn = &rgd->rd_rstree.rb_node; + BUG_ON(!ip->i_res); + BUG_ON(gfs2_rs_active(rs)); + /* Figure out where to put new node */ + /*BUG_ON(!gfs2_glock_is_locked_by_me(rgd->rd_gl));*/ while (*newn) { struct gfs2_blkreserv *cur = rb_entry(*newn, struct gfs2_blkreserv, rs_node); parent = *newn; - rc = rs_cmp(fsblock, rs->rs_free, cur); + rc = rs_cmp(fsblock, amount, cur); if (rc > 0) newn = &((*newn)->rb_right); else if (rc < 0) newn = &((*newn)->rb_left); else { spin_unlock(&rgd->rd_rsspin); - WARN_ON(1); - return; + return NULL; /* reservation already in use */ } } + /* Do our reservation work */ + rs = ip->i_res; + rs->rs_free = amount; + rs->rs_biblk = biblk; + rs->rs_bi = bi; rb_link_node(&rs->rs_node, parent, newn); rb_insert_color(&rs->rs_node, &rgd->rd_rstree); + /* Do our inode accounting for the reservation */ + /*BUG_ON(!gfs2_glock_is_locked_by_me(ip->i_gl));*/ + /* Do our rgrp accounting for the reservation */ - rgd->rd_reserved += rs->rs_free; /* blocks reserved */ + rgd->rd_reserved += amount; /* blocks reserved */ + rgd->rd_rs_cnt++; /* number of in-tree reservations */ spin_unlock(&rgd->rd_rsspin); - trace_gfs2_rs(rs, TRACE_RS_INSERT); + trace_gfs2_rs(ip, rs, TRACE_RS_INSERT); + return rs; } /** - * rg_mblk_search - find a group of multiple free blocks to form a reservation + * unclaimed_blocks - return number of blocks that aren't spoken for + */ +static u32 unclaimed_blocks(struct gfs2_rgrpd *rgd) +{ + return rgd->rd_free_clone - rgd->rd_reserved; +} + +/** + * rg_mblk_search - find a group of multiple free blocks * @rgd: the resource group descriptor + * @rs: the block reservation * @ip: pointer to the inode for which we're reserving blocks - * @requested: number of blocks required for this allocation * + * This is very similar to rgblk_search, except we're looking for whole + * 64-bit words that represent a chunk of 32 free blocks. I'm only focusing + * on aligned dwords for speed's sake. + * + * Returns: 0 if successful or BFITNOENT if there isn't enough free space */ -static void rg_mblk_search(struct gfs2_rgrpd *rgd, struct gfs2_inode *ip, - unsigned requested) +static int rg_mblk_search(struct gfs2_rgrpd *rgd, struct gfs2_inode *ip) { - struct gfs2_rbm rbm = { .rgd = rgd, }; - u64 goal; - struct gfs2_blkreserv *rs = ip->i_res; - u32 extlen; - u32 free_blocks = rgd->rd_free_clone - rgd->rd_reserved; - int ret; - - extlen = max_t(u32, atomic_read(&rs->rs_sizehint), requested); - extlen = clamp(extlen, RGRP_RSRV_MINBLKS, free_blocks); - if ((rgd->rd_free_clone < rgd->rd_reserved) || (free_blocks < extlen)) - return; + struct gfs2_bitmap *bi = rgd->rd_bits; + const u32 length = rgd->rd_length; + u32 blk; + unsigned int buf, x, search_bytes; + u8 *buffer = NULL; + u8 *ptr, *end, *nonzero; + u32 goal, rsv_bytes; + struct gfs2_blkreserv *rs; + u32 best_rs_bytes, unclaimed; + int best_rs_blocks; /* Find bitmap block that contains bits for goal block */ if (rgrp_contains_block(rgd, ip->i_goal)) - goal = ip->i_goal; + goal = ip->i_goal - rgd->rd_data0; else - goal = rgd->rd_last_alloc + rgd->rd_data0; - - if (WARN_ON(gfs2_rbm_from_block(&rbm, goal))) - return; - - ret = gfs2_rbm_find(&rbm, GFS2_BLKST_FREE, extlen, ip, true); - if (ret == 0) { - rs->rs_rbm = rbm; - rs->rs_free = extlen; - rs->rs_inum = ip->i_no_addr; - rs_insert(ip); + goal = rgd->rd_last_alloc; + for (buf = 0; buf < length; buf++) { + bi = rgd->rd_bits + buf; + /* Convert scope of "goal" from rgrp-wide to within + found bit block */ + if (goal < (bi->bi_start + bi->bi_len) * GFS2_NBBY) { + goal -= bi->bi_start * GFS2_NBBY; + goto do_search; + } } -} - -/** - * gfs2_next_unreserved_block - Return next block that is not reserved - * @rgd: The resource group - * @block: The starting block - * @length: The required length - * @ip: Ignore any reservations for this inode - * - * If the block does not appear in any reservation, then return the - * block number unchanged. If it does appear in the reservation, then - * keep looking through the tree of reservations in order to find the - * first block number which is not reserved. - */ + buf = 0; + goal = 0; + +do_search: + best_rs_blocks = max_t(int, atomic_read(&ip->i_res->rs_sizehint), + (RGRP_RSRV_MINBLKS * rgd->rd_length)); + best_rs_bytes = (best_rs_blocks * + (1 + (RSRV_CONTENTION_FACTOR * rgd->rd_rs_cnt))) / + GFS2_NBBY; /* 1 + is for our not-yet-created reservation */ + best_rs_bytes = ALIGN(best_rs_bytes, sizeof(u64)); + unclaimed = unclaimed_blocks(rgd); + if (best_rs_bytes * GFS2_NBBY > unclaimed) + best_rs_bytes = unclaimed >> GFS2_BIT_SIZE; + + for (x = 0; x <= length; x++) { + bi = rgd->rd_bits + buf; -static u64 gfs2_next_unreserved_block(struct gfs2_rgrpd *rgd, u64 block, - u32 length, - const struct gfs2_inode *ip) -{ - struct gfs2_blkreserv *rs; - struct rb_node *n; - int rc; + if (test_bit(GBF_FULL, &bi->bi_flags)) + goto skip; - spin_lock(&rgd->rd_rsspin); - n = rgd->rd_rstree.rb_node; - while (n) { - rs = rb_entry(n, struct gfs2_blkreserv, rs_node); - rc = rs_cmp(block, length, rs); - if (rc < 0) - n = n->rb_left; - else if (rc > 0) - n = n->rb_right; + WARN_ON(!buffer_uptodate(bi->bi_bh)); + if (bi->bi_clone) + buffer = bi->bi_clone + bi->bi_offset; else - break; - } - - if (n) { - while ((rs_cmp(block, length, rs) == 0) && (ip->i_res != rs)) { - block = gfs2_rbm_to_block(&rs->rs_rbm) + rs->rs_free; - n = n->rb_right; - if (n == NULL) - break; - rs = rb_entry(n, struct gfs2_blkreserv, rs_node); + buffer = bi->bi_bh->b_data + bi->bi_offset; + + /* We have to keep the reservations aligned on u64 boundaries + otherwise we could get situations where a byte can't be + used because it's after a reservation, but a free bit still + is within the reservation's area. */ + ptr = buffer + ALIGN(goal >> GFS2_BIT_SIZE, sizeof(u64)); + end = (buffer + bi->bi_len); + while (ptr < end) { + rsv_bytes = 0; + if ((ptr + best_rs_bytes) <= end) + search_bytes = best_rs_bytes; + else + search_bytes = end - ptr; + BUG_ON(!search_bytes); + nonzero = memchr_inv(ptr, 0, search_bytes); + /* If the lot is all zeroes, reserve the whole size. If + there's enough zeroes to satisfy the request, use + what we can. If there's not enough, keep looking. */ + if (nonzero == NULL) + rsv_bytes = search_bytes; + else if ((nonzero - ptr) * GFS2_NBBY >= + ip->i_res->rs_requested) + rsv_bytes = (nonzero - ptr); + + if (rsv_bytes) { + blk = ((ptr - buffer) * GFS2_NBBY); + BUG_ON(blk >= bi->bi_len * GFS2_NBBY); + rs = rs_insert(bi, ip, blk, + rsv_bytes * GFS2_NBBY); + if (IS_ERR(rs)) + return PTR_ERR(rs); + if (rs) + return 0; + } + ptr += ALIGN(search_bytes, sizeof(u64)); } +skip: + /* Try next bitmap block (wrap back to rgrp header + if at end) */ + buf++; + buf %= length; + goal = 0; } - spin_unlock(&rgd->rd_rsspin); - return block; + return BFITNOENT; } /** - * gfs2_reservation_check_and_update - Check for reservations during block alloc - * @rbm: The current position in the resource group - * @ip: The inode for which we are searching for blocks - * @minext: The minimum extent length + * try_rgrp_fit - See if a given reservation will fit in a given RG + * @rgd: the RG data + * @ip: the inode * - * This checks the current position in the rgrp to see whether there is - * a reservation covering this block. If not then this function is a - * no-op. If there is, then the position is moved to the end of the - * contiguous reservation(s) so that we are pointing at the first - * non-reserved block. + * If there's room for the requested blocks to be allocated from the RG: + * This will try to get a multi-block reservation first, and if that doesn't + * fit, it will take what it can. * - * Returns: 0 if no reservation, 1 if @rbm has changed, otherwise an error + * Returns: 1 on success (it fits), 0 on failure (it doesn't fit) */ -static int gfs2_reservation_check_and_update(struct gfs2_rbm *rbm, - const struct gfs2_inode *ip, - u32 minext) +static int try_rgrp_fit(struct gfs2_rgrpd *rgd, struct gfs2_inode *ip) { - u64 block = gfs2_rbm_to_block(rbm); - u32 extlen = 1; - u64 nblock; - int ret; - - /* - * If we have a minimum extent length, then skip over any extent - * which is less than the min extent length in size. - */ - if (minext) { - extlen = gfs2_free_extlen(rbm, minext); - nblock = block + extlen; - if (extlen < minext) - goto fail; - } + struct gfs2_blkreserv *rs = ip->i_res; - /* - * Check the extent which has been found against the reservations - * and skip if parts of it are already reserved - */ - nblock = gfs2_next_unreserved_block(rbm->rgd, block, extlen, ip); - if (nblock == block) + if (rgd->rd_flags & (GFS2_RGF_NOALLOC | GFS2_RDF_ERROR)) return 0; -fail: - ret = gfs2_rbm_from_block(rbm, nblock); - if (ret < 0) - return ret; - return 1; -} - -/** - * gfs2_rbm_find - Look for blocks of a particular state - * @rbm: Value/result starting position and final position - * @state: The state which we want to find - * @minext: The requested extent length (0 for a single block) - * @ip: If set, check for reservations - * @nowrap: Stop looking at the end of the rgrp, rather than wrapping - * around until we've reached the starting point. - * - * Side effects: - * - If looking for free blocks, we set GBF_FULL on each bitmap which - * has no free blocks in it. - * - * Returns: 0 on success, -ENOSPC if there is no block of the requested state - */ - -static int gfs2_rbm_find(struct gfs2_rbm *rbm, u8 state, u32 minext, - const struct gfs2_inode *ip, bool nowrap) -{ - struct buffer_head *bh; - struct gfs2_bitmap *initial_bi; - u32 initial_offset; - u32 offset; - u8 *buffer; - int index; - int n = 0; - int iters = rbm->rgd->rd_length; - int ret; - - /* If we are not starting at the beginning of a bitmap, then we - * need to add one to the bitmap count to ensure that we search - * the starting bitmap twice. - */ - if (rbm->offset != 0) - iters++; - - while(1) { - if (test_bit(GBF_FULL, &rbm->bi->bi_flags) && - (state == GFS2_BLKST_FREE)) - goto next_bitmap; - - bh = rbm->bi->bi_bh; - buffer = bh->b_data + rbm->bi->bi_offset; - WARN_ON(!buffer_uptodate(bh)); - if (state != GFS2_BLKST_UNLINKED && rbm->bi->bi_clone) - buffer = rbm->bi->bi_clone + rbm->bi->bi_offset; - initial_offset = rbm->offset; - offset = gfs2_bitfit(buffer, rbm->bi->bi_len, rbm->offset, state); - if (offset == BFITNOENT) - goto bitmap_full; - rbm->offset = offset; - if (ip == NULL) - return 0; - - initial_bi = rbm->bi; - ret = gfs2_reservation_check_and_update(rbm, ip, minext); - if (ret == 0) - return 0; - if (ret > 0) { - n += (rbm->bi - initial_bi); - goto next_iter; - } - if (ret == -E2BIG) { - index = 0; - rbm->offset = 0; - n += (rbm->bi - initial_bi); - goto res_covered_end_of_rgrp; - } - return ret; - -bitmap_full: /* Mark bitmap as full and fall through */ - if ((state == GFS2_BLKST_FREE) && initial_offset == 0) - set_bit(GBF_FULL, &rbm->bi->bi_flags); - -next_bitmap: /* Find next bitmap in the rgrp */ - rbm->offset = 0; - index = rbm->bi - rbm->rgd->rd_bits; - index++; - if (index == rbm->rgd->rd_length) - index = 0; -res_covered_end_of_rgrp: - rbm->bi = &rbm->rgd->rd_bits[index]; - if ((index == 0) && nowrap) - break; - n++; -next_iter: - if (n >= iters) - break; - } + /* Look for a multi-block reservation. */ + if (unclaimed_blocks(rgd) >= RGRP_RSRV_MINBLKS && + rg_mblk_search(rgd, ip) != BFITNOENT) + return 1; + if (unclaimed_blocks(rgd) >= rs->rs_requested) + return 1; - return -ENOSPC; + return 0; } /** @@ -1616,33 +1489,34 @@ static int gfs2_rbm_find(struct gfs2_rbm *rbm, u8 state, u32 minext, static void try_rgrp_unlink(struct gfs2_rgrpd *rgd, u64 *last_unlinked, u64 skip) { - u64 block; + u32 goal = 0, block; + u64 no_addr; struct gfs2_sbd *sdp = rgd->rd_sbd; struct gfs2_glock *gl; struct gfs2_inode *ip; int error; int found = 0; - struct gfs2_rbm rbm = { .rgd = rgd, .bi = rgd->rd_bits, .offset = 0 }; + struct gfs2_bitmap *bi; - while (1) { + while (goal < rgd->rd_data) { down_write(&sdp->sd_log_flush_lock); - error = gfs2_rbm_find(&rbm, GFS2_BLKST_UNLINKED, 0, NULL, true); + block = rgblk_search(rgd, goal, GFS2_BLKST_UNLINKED, &bi); up_write(&sdp->sd_log_flush_lock); - if (error == -ENOSPC) - break; - if (WARN_ON_ONCE(error)) + if (block == BFITNOENT) break; - block = gfs2_rbm_to_block(&rbm); - if (gfs2_rbm_from_block(&rbm, block + 1)) - break; - if (*last_unlinked != NO_BLOCK && block <= *last_unlinked) + block = gfs2_bi2rgd_blk(bi, block); + /* rgblk_search can return a block < goal, so we need to + keep it marching forward. */ + no_addr = block + rgd->rd_data0; + goal = max(block + 1, goal + 1); + if (*last_unlinked != NO_BLOCK && no_addr <= *last_unlinked) continue; - if (block == skip) + if (no_addr == skip) continue; - *last_unlinked = block; + *last_unlinked = no_addr; - error = gfs2_glock_get(sdp, block, &gfs2_inode_glops, CREATE, &gl); + error = gfs2_glock_get(sdp, no_addr, &gfs2_inode_glops, CREATE, &gl); if (error) continue; @@ -1669,19 +1543,6 @@ static void try_rgrp_unlink(struct gfs2_rgrpd *rgd, u64 *last_unlinked, u64 skip return; } -static bool gfs2_select_rgrp(struct gfs2_rgrpd **pos, const struct gfs2_rgrpd *begin) -{ - struct gfs2_rgrpd *rgd = *pos; - - rgd = gfs2_rgrpd_get_next(rgd); - if (rgd == NULL) - rgd = gfs2_rgrpd_get_next(NULL); - *pos = rgd; - if (rgd != begin) /* If we didn't wrap */ - return true; - return false; -} - /** * gfs2_inplace_reserve - Reserve space in the filesystem * @ip: the inode to reserve space for @@ -1701,96 +1562,103 @@ int gfs2_inplace_reserve(struct gfs2_inode *ip, u32 requested) if (sdp->sd_args.ar_rgrplvb) flags |= GL_SKIP; - if (gfs2_assert_warn(sdp, requested)) - return -EINVAL; + rs->rs_requested = requested; + if (gfs2_assert_warn(sdp, requested)) { + error = -EINVAL; + goto out; + } if (gfs2_rs_active(rs)) { - begin = rs->rs_rbm.rgd; + begin = rs->rs_rgd; flags = 0; /* Yoda: Do or do not. There is no try */ } else if (ip->i_rgd && rgrp_contains_block(ip->i_rgd, ip->i_goal)) { - rs->rs_rbm.rgd = begin = ip->i_rgd; + rs->rs_rgd = begin = ip->i_rgd; } else { - rs->rs_rbm.rgd = begin = gfs2_blk2rgrpd(sdp, ip->i_goal, 1); + rs->rs_rgd = begin = gfs2_blk2rgrpd(sdp, ip->i_goal, 1); } - if (rs->rs_rbm.rgd == NULL) + if (rs->rs_rgd == NULL) return -EBADSLT; while (loops < 3) { - rg_locked = 1; - - if (!gfs2_glock_is_locked_by_me(rs->rs_rbm.rgd->rd_gl)) { - rg_locked = 0; - error = gfs2_glock_nq_init(rs->rs_rbm.rgd->rd_gl, + rg_locked = 0; + + if (gfs2_glock_is_locked_by_me(rs->rs_rgd->rd_gl)) { + rg_locked = 1; + error = 0; + } else if (!loops && !gfs2_rs_active(rs) && + rs->rs_rgd->rd_rs_cnt > RGRP_RSRV_MAX_CONTENDERS) { + /* If the rgrp already is maxed out for contenders, + we can eliminate it as a "first pass" without even + requesting the rgrp glock. */ + error = GLR_TRYFAILED; + } else { + error = gfs2_glock_nq_init(rs->rs_rgd->rd_gl, LM_ST_EXCLUSIVE, flags, &rs->rs_rgd_gh); - if (error == GLR_TRYFAILED) - goto next_rgrp; - if (unlikely(error)) - return error; - if (sdp->sd_args.ar_rgrplvb) { - error = update_rgrp_lvb(rs->rs_rbm.rgd); - if (unlikely(error)) { + if (!error && sdp->sd_args.ar_rgrplvb) { + error = update_rgrp_lvb(rs->rs_rgd); + if (error) { gfs2_glock_dq_uninit(&rs->rs_rgd_gh); return error; } } } + switch (error) { + case 0: + if (gfs2_rs_active(rs)) { + if (unclaimed_blocks(rs->rs_rgd) + + rs->rs_free >= rs->rs_requested) { + ip->i_rgd = rs->rs_rgd; + return 0; + } + /* We have a multi-block reservation, but the + rgrp doesn't have enough free blocks to + satisfy the request. Free the reservation + and look for a suitable rgrp. */ + gfs2_rs_deltree(rs); + } + if (try_rgrp_fit(rs->rs_rgd, ip)) { + if (sdp->sd_args.ar_rgrplvb) + gfs2_rgrp_bh_get(rs->rs_rgd); + ip->i_rgd = rs->rs_rgd; + return 0; + } + if (rs->rs_rgd->rd_flags & GFS2_RDF_CHECK) { + if (sdp->sd_args.ar_rgrplvb) + gfs2_rgrp_bh_get(rs->rs_rgd); + try_rgrp_unlink(rs->rs_rgd, &last_unlinked, + ip->i_no_addr); + } + if (!rg_locked) + gfs2_glock_dq_uninit(&rs->rs_rgd_gh); + /* fall through */ + case GLR_TRYFAILED: + rs->rs_rgd = gfs2_rgrpd_get_next(rs->rs_rgd); + rs->rs_rgd = rs->rs_rgd ? : begin; /* if NULL, wrap */ + if (rs->rs_rgd != begin) /* If we didn't wrap */ + break; - /* Skip unuseable resource groups */ - if (rs->rs_rbm.rgd->rd_flags & (GFS2_RGF_NOALLOC | GFS2_RDF_ERROR)) - goto skip_rgrp; - - if (sdp->sd_args.ar_rgrplvb) - gfs2_rgrp_bh_get(rs->rs_rbm.rgd); - - /* Get a reservation if we don't already have one */ - if (!gfs2_rs_active(rs)) - rg_mblk_search(rs->rs_rbm.rgd, ip, requested); - - /* Skip rgrps when we can't get a reservation on first pass */ - if (!gfs2_rs_active(rs) && (loops < 1)) - goto check_rgrp; - - /* If rgrp has enough free space, use it */ - if (rs->rs_rbm.rgd->rd_free_clone >= requested) { - ip->i_rgd = rs->rs_rbm.rgd; - return 0; - } - - /* Drop reservation, if we couldn't use reserved rgrp */ - if (gfs2_rs_active(rs)) - gfs2_rs_deltree(ip, rs); -check_rgrp: - /* Check for unlinked inodes which can be reclaimed */ - if (rs->rs_rbm.rgd->rd_flags & GFS2_RDF_CHECK) - try_rgrp_unlink(rs->rs_rbm.rgd, &last_unlinked, - ip->i_no_addr); -skip_rgrp: - /* Unlock rgrp if required */ - if (!rg_locked) - gfs2_glock_dq_uninit(&rs->rs_rgd_gh); -next_rgrp: - /* Find the next rgrp, and continue looking */ - if (gfs2_select_rgrp(&rs->rs_rbm.rgd, begin)) - continue; - - /* If we've scanned all the rgrps, but found no free blocks - * then this checks for some less likely conditions before - * trying again. - */ - flags &= ~LM_FLAG_TRY; - loops++; - /* Check that fs hasn't grown if writing to rindex */ - if (ip == GFS2_I(sdp->sd_rindex) && !sdp->sd_rindex_uptodate) { - error = gfs2_ri_update(ip); - if (error) - return error; + flags &= ~LM_FLAG_TRY; + loops++; + /* Check that fs hasn't grown if writing to rindex */ + if (ip == GFS2_I(sdp->sd_rindex) && + !sdp->sd_rindex_uptodate) { + error = gfs2_ri_update(ip); + if (error) + goto out; + } else if (loops == 2) + /* Flushing the log may release space */ + gfs2_log_flush(sdp, NULL); + break; + default: + goto out; } - /* Flushing the log may release space */ - if (loops == 2) - gfs2_log_flush(sdp, NULL); } + error = -ENOSPC; - return -ENOSPC; +out: + if (error) + rs->rs_requested = 0; + return error; } /** @@ -1804,8 +1672,15 @@ void gfs2_inplace_release(struct gfs2_inode *ip) { struct gfs2_blkreserv *rs = ip->i_res; + if (!rs) + return; + + if (!rs->rs_free) + gfs2_rs_deltree(rs); + if (rs->rs_rgd_gh.gh_gl) gfs2_glock_dq_uninit(&rs->rs_rgd_gh); + rs->rs_requested = 0; } /** @@ -1818,47 +1693,173 @@ void gfs2_inplace_release(struct gfs2_inode *ip) static unsigned char gfs2_get_block_type(struct gfs2_rgrpd *rgd, u64 block) { - struct gfs2_rbm rbm = { .rgd = rgd, }; - int ret; + struct gfs2_bitmap *bi = NULL; + u32 length, rgrp_block, buf_block; + unsigned int buf; + unsigned char type; + + length = rgd->rd_length; + rgrp_block = block - rgd->rd_data0; + + for (buf = 0; buf < length; buf++) { + bi = rgd->rd_bits + buf; + if (rgrp_block < (bi->bi_start + bi->bi_len) * GFS2_NBBY) + break; + } - ret = gfs2_rbm_from_block(&rbm, block); - WARN_ON_ONCE(ret != 0); + gfs2_assert(rgd->rd_sbd, buf < length); + buf_block = rgrp_block - bi->bi_start * GFS2_NBBY; - return gfs2_testbit(&rbm); + type = gfs2_testbit(rgd, bi->bi_bh->b_data + bi->bi_offset, + bi->bi_len, buf_block); + + return type; } +/** + * rgblk_search - find a block in @state + * @rgd: the resource group descriptor + * @goal: the goal block within the RG (start here to search for avail block) + * @state: GFS2_BLKST_XXX the before-allocation state to find + * @rbi: address of the pointer to the bitmap containing the block found + * + * Walk rgrp's bitmap to find bits that represent a block in @state. + * + * This function never fails, because we wouldn't call it unless we + * know (from reservation results, etc.) that a block is available. + * + * Scope of @goal is just within rgrp, not the whole filesystem. + * Scope of @returned block is just within bitmap, not the whole filesystem. + * + * Returns: the block number found relative to the bitmap rbi + */ + +static u32 rgblk_search(struct gfs2_rgrpd *rgd, u32 goal, unsigned char state, + struct gfs2_bitmap **rbi) +{ + struct gfs2_bitmap *bi = NULL; + const u32 length = rgd->rd_length; + u32 biblk = BFITNOENT; + unsigned int buf, x; + const u8 *buffer = NULL; + + *rbi = NULL; + /* Find bitmap block that contains bits for goal block */ + for (buf = 0; buf < length; buf++) { + bi = rgd->rd_bits + buf; + /* Convert scope of "goal" from rgrp-wide to within found bit block */ + if (goal < (bi->bi_start + bi->bi_len) * GFS2_NBBY) { + goal -= bi->bi_start * GFS2_NBBY; + goto do_search; + } + } + buf = 0; + goal = 0; + +do_search: + /* Search (up to entire) bitmap in this rgrp for allocatable block. + "x <= length", instead of "x < length", because we typically start + the search in the middle of a bit block, but if we can't find an + allocatable block anywhere else, we want to be able wrap around and + search in the first part of our first-searched bit block. */ + for (x = 0; x <= length; x++) { + bi = rgd->rd_bits + buf; + + if (test_bit(GBF_FULL, &bi->bi_flags) && + (state == GFS2_BLKST_FREE)) + goto skip; + + /* The GFS2_BLKST_UNLINKED state doesn't apply to the clone + bitmaps, so we must search the originals for that. */ + buffer = bi->bi_bh->b_data + bi->bi_offset; + WARN_ON(!buffer_uptodate(bi->bi_bh)); + if (state != GFS2_BLKST_UNLINKED && bi->bi_clone) + buffer = bi->bi_clone + bi->bi_offset; + + while (1) { + struct gfs2_blkreserv *rs; + u32 rgblk; + + biblk = gfs2_bitfit(buffer, bi->bi_len, goal, state); + if (biblk == BFITNOENT) + break; + /* Check if this block is reserved() */ + rgblk = gfs2_bi2rgd_blk(bi, biblk); + rs = rs_find(rgd, rgblk); + if (rs == NULL) + break; + + BUG_ON(rs->rs_bi != bi); + biblk = BFITNOENT; + /* This should jump to the first block after the + reservation. */ + goal = rs->rs_biblk + rs->rs_free; + if (goal >= bi->bi_len * GFS2_NBBY) + break; + } + if (biblk != BFITNOENT) + break; + + if ((goal == 0) && (state == GFS2_BLKST_FREE)) + set_bit(GBF_FULL, &bi->bi_flags); + + /* Try next bitmap block (wrap back to rgrp header if at end) */ +skip: + buf++; + buf %= length; + goal = 0; + } + + if (biblk != BFITNOENT) + *rbi = bi; + + return biblk; +} /** * gfs2_alloc_extent - allocate an extent from a given bitmap - * @rbm: the resource group information + * @rgd: the resource group descriptor + * @bi: the bitmap within the rgrp + * @blk: the block within the bitmap * @dinode: TRUE if the first block we allocate is for a dinode - * @n: The extent length (value/result) + * @n: The extent length * - * Add the bitmap buffer to the transaction. + * Add the found bitmap buffer to the transaction. * Set the found bits to @new_state to change block's allocation state. + * Returns: starting block number of the extent (fs scope) */ -static void gfs2_alloc_extent(const struct gfs2_rbm *rbm, bool dinode, - unsigned int *n) +static u64 gfs2_alloc_extent(struct gfs2_rgrpd *rgd, struct gfs2_bitmap *bi, + u32 blk, bool dinode, unsigned int *n) { - struct gfs2_rbm pos = { .rgd = rbm->rgd, }; const unsigned int elen = *n; - u64 block; - int ret; - - *n = 1; - block = gfs2_rbm_to_block(rbm); - gfs2_trans_add_bh(rbm->rgd->rd_gl, rbm->bi->bi_bh, 1); - gfs2_setbit(rbm, true, dinode ? GFS2_BLKST_DINODE : GFS2_BLKST_USED); - block++; + u32 goal, rgblk; + const u8 *buffer = NULL; + struct gfs2_blkreserv *rs; + + *n = 0; + buffer = bi->bi_bh->b_data + bi->bi_offset; + gfs2_trans_add_bh(rgd->rd_gl, bi->bi_bh, 1); + gfs2_setbit(rgd, bi->bi_clone, bi, blk, + dinode ? GFS2_BLKST_DINODE : GFS2_BLKST_USED); + (*n)++; + goal = blk; while (*n < elen) { - ret = gfs2_rbm_from_block(&pos, block); - if (ret || gfs2_testbit(&pos) != GFS2_BLKST_FREE) + goal++; + if (goal >= (bi->bi_len * GFS2_NBBY)) + break; + rgblk = gfs2_bi2rgd_blk(bi, goal); + rs = rs_find(rgd, rgblk); + if (rs) /* Oops, we bumped into someone's reservation */ + break; + if (gfs2_testbit(rgd, buffer, bi->bi_len, goal) != + GFS2_BLKST_FREE) break; - gfs2_trans_add_bh(pos.rgd->rd_gl, pos.bi->bi_bh, 1); - gfs2_setbit(&pos, true, GFS2_BLKST_USED); + gfs2_setbit(rgd, bi->bi_clone, bi, goal, GFS2_BLKST_USED); (*n)++; - block++; } + blk = gfs2_bi2rgd_blk(bi, blk); + rgd->rd_last_alloc = blk + *n - 1; + return rgd->rd_data0 + blk; } /** @@ -1874,30 +1875,46 @@ static void gfs2_alloc_extent(const struct gfs2_rbm *rbm, bool dinode, static struct gfs2_rgrpd *rgblk_free(struct gfs2_sbd *sdp, u64 bstart, u32 blen, unsigned char new_state) { - struct gfs2_rbm rbm; + struct gfs2_rgrpd *rgd; + struct gfs2_bitmap *bi = NULL; + u32 length, rgrp_blk, buf_blk; + unsigned int buf; - rbm.rgd = gfs2_blk2rgrpd(sdp, bstart, 1); - if (!rbm.rgd) { + rgd = gfs2_blk2rgrpd(sdp, bstart, 1); + if (!rgd) { if (gfs2_consist(sdp)) fs_err(sdp, "block = %llu\n", (unsigned long long)bstart); return NULL; } + length = rgd->rd_length; + + rgrp_blk = bstart - rgd->rd_data0; + while (blen--) { - gfs2_rbm_from_block(&rbm, bstart); - bstart++; - if (!rbm.bi->bi_clone) { - rbm.bi->bi_clone = kmalloc(rbm.bi->bi_bh->b_size, - GFP_NOFS | __GFP_NOFAIL); - memcpy(rbm.bi->bi_clone + rbm.bi->bi_offset, - rbm.bi->bi_bh->b_data + rbm.bi->bi_offset, - rbm.bi->bi_len); + for (buf = 0; buf < length; buf++) { + bi = rgd->rd_bits + buf; + if (rgrp_blk < (bi->bi_start + bi->bi_len) * GFS2_NBBY) + break; + } + + gfs2_assert(rgd->rd_sbd, buf < length); + + buf_blk = rgrp_blk - bi->bi_start * GFS2_NBBY; + rgrp_blk++; + + if (!bi->bi_clone) { + bi->bi_clone = kmalloc(bi->bi_bh->b_size, + GFP_NOFS | __GFP_NOFAIL); + memcpy(bi->bi_clone + bi->bi_offset, + bi->bi_bh->b_data + bi->bi_offset, + bi->bi_len); } - gfs2_trans_add_bh(rbm.rgd->rd_gl, rbm.bi->bi_bh, 1); - gfs2_setbit(&rbm, false, new_state); + gfs2_trans_add_bh(rgd->rd_gl, bi->bi_bh, 1); + gfs2_setbit(rgd, NULL, bi, buf_blk, new_state); } - return rbm.rgd; + return rgd; } /** @@ -1939,41 +1956,56 @@ static void gfs2_rgrp_error(struct gfs2_rgrpd *rgd) } /** - * gfs2_adjust_reservation - Adjust (or remove) a reservation after allocation - * @ip: The inode we have just allocated blocks for - * @rbm: The start of the allocated blocks - * @len: The extent length + * claim_reserved_blks - Claim previously reserved blocks + * @ip: the inode that's claiming the reservation + * @dinode: 1 if this block is a dinode block, otherwise data block + * @nblocks: desired extent length * - * Adjusts a reservation after an allocation has taken place. If the - * reservation does not match the allocation, or if it is now empty - * then it is removed. + * Lay claim to previously allocated block reservation blocks. + * Returns: Starting block number of the blocks claimed. + * Sets *nblocks to the actual extent length allocated. */ - -static void gfs2_adjust_reservation(struct gfs2_inode *ip, - const struct gfs2_rbm *rbm, unsigned len) +static u64 claim_reserved_blks(struct gfs2_inode *ip, bool dinode, + unsigned int *nblocks) { struct gfs2_blkreserv *rs = ip->i_res; - struct gfs2_rgrpd *rgd = rbm->rgd; - unsigned rlen; - u64 block; - int ret; + struct gfs2_rgrpd *rgd = rs->rs_rgd; + struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); + struct gfs2_bitmap *bi; + u64 start_block = gfs2_rs_startblk(rs); + const unsigned int elen = *nblocks; + + /*BUG_ON(!gfs2_glock_is_locked_by_me(ip->i_gl));*/ + gfs2_assert_withdraw(sdp, rgd); + /*BUG_ON(!gfs2_glock_is_locked_by_me(rgd->rd_gl));*/ + bi = rs->rs_bi; + gfs2_trans_add_bh(rgd->rd_gl, bi->bi_bh, 1); + + for (*nblocks = 0; *nblocks < elen && rs->rs_free; (*nblocks)++) { + /* Make sure the bitmap hasn't changed */ + gfs2_setbit(rgd, bi->bi_clone, bi, rs->rs_biblk, + dinode ? GFS2_BLKST_DINODE : GFS2_BLKST_USED); + rs->rs_biblk++; + rs->rs_free--; + + BUG_ON(!rgd->rd_reserved); + rgd->rd_reserved--; + dinode = false; + trace_gfs2_rs(ip, rs, TRACE_RS_CLAIM); + } - spin_lock(&rgd->rd_rsspin); - if (gfs2_rs_active(rs)) { - if (gfs2_rbm_eq(&rs->rs_rbm, rbm)) { - block = gfs2_rbm_to_block(rbm); - ret = gfs2_rbm_from_block(&rs->rs_rbm, block + len); - rlen = min(rs->rs_free, len); - rs->rs_free -= rlen; - rgd->rd_reserved -= rlen; - trace_gfs2_rs(rs, TRACE_RS_CLAIM); - if (rs->rs_free && !ret) - goto out; - } - __rs_deltree(ip, rs); + if (!rs->rs_free) { + struct gfs2_rgrpd *rgd = ip->i_res->rs_rgd; + + gfs2_rs_deltree(rs); + /* -nblocks because we haven't returned to do the math yet. + I'm doing the math backwards to prevent negative numbers, + but think of it as: + if (unclaimed_blocks(rgd) - *nblocks >= RGRP_RSRV_MINBLKS */ + if (unclaimed_blocks(rgd) >= RGRP_RSRV_MINBLKS + *nblocks) + rg_mblk_search(rgd, ip); } -out: - spin_unlock(&rgd->rd_rsspin); + return start_block; } /** @@ -1992,40 +2024,47 @@ int gfs2_alloc_blocks(struct gfs2_inode *ip, u64 *bn, unsigned int *nblocks, { struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); struct buffer_head *dibh; - struct gfs2_rbm rbm = { .rgd = ip->i_rgd, }; + struct gfs2_rgrpd *rgd; unsigned int ndata; - u64 goal; + u32 goal, blk; /* block, within the rgrp scope */ u64 block; /* block, within the file system scope */ int error; + struct gfs2_bitmap *bi; - if (gfs2_rs_active(ip->i_res)) - goal = gfs2_rbm_to_block(&ip->i_res->rs_rbm); - else if (!dinode && rgrp_contains_block(rbm.rgd, ip->i_goal)) - goal = ip->i_goal; - else - goal = rbm.rgd->rd_last_alloc + rbm.rgd->rd_data0; - - gfs2_rbm_from_block(&rbm, goal); - error = gfs2_rbm_find(&rbm, GFS2_BLKST_FREE, 0, ip, false); + /* Only happens if there is a bug in gfs2, return something distinctive + * to ensure that it is noticed. + */ + if (ip->i_res->rs_requested == 0) + return -ECANCELED; + + /* Check if we have a multi-block reservation, and if so, claim the + next free block from it. */ + if (gfs2_rs_active(ip->i_res)) { + BUG_ON(!ip->i_res->rs_free); + rgd = ip->i_res->rs_rgd; + block = claim_reserved_blks(ip, dinode, nblocks); + } else { + rgd = ip->i_rgd; - if (error == -ENOSPC) { - gfs2_rbm_from_block(&rbm, goal); - error = gfs2_rbm_find(&rbm, GFS2_BLKST_FREE, 0, NULL, false); - } + if (!dinode && rgrp_contains_block(rgd, ip->i_goal)) + goal = ip->i_goal - rgd->rd_data0; + else + goal = rgd->rd_last_alloc; + + blk = rgblk_search(rgd, goal, GFS2_BLKST_FREE, &bi); + + /* Since all blocks are reserved in advance, this shouldn't + happen */ + if (blk == BFITNOENT) { + printk(KERN_WARNING "BFITNOENT, nblocks=%u\n", + *nblocks); + printk(KERN_WARNING "FULL=%d\n", + test_bit(GBF_FULL, &rgd->rd_bits->bi_flags)); + goto rgrp_error; + } - /* Since all blocks are reserved in advance, this shouldn't happen */ - if (error) { - fs_warn(sdp, "inum=%llu error=%d, nblocks=%u, full=%d\n", - (unsigned long long)ip->i_no_addr, error, *nblocks, - test_bit(GBF_FULL, &rbm.rgd->rd_bits->bi_flags)); - goto rgrp_error; + block = gfs2_alloc_extent(rgd, bi, blk, dinode, nblocks); } - - gfs2_alloc_extent(&rbm, dinode, nblocks); - block = gfs2_rbm_to_block(&rbm); - rbm.rgd->rd_last_alloc = block - rbm.rgd->rd_data0; - if (gfs2_rs_active(ip->i_res)) - gfs2_adjust_reservation(ip, &rbm, *nblocks); ndata = *nblocks; if (dinode) ndata--; @@ -2042,22 +2081,22 @@ int gfs2_alloc_blocks(struct gfs2_inode *ip, u64 *bn, unsigned int *nblocks, brelse(dibh); } } - if (rbm.rgd->rd_free < *nblocks) { + if (rgd->rd_free < *nblocks) { printk(KERN_WARNING "nblocks=%u\n", *nblocks); goto rgrp_error; } - rbm.rgd->rd_free -= *nblocks; + rgd->rd_free -= *nblocks; if (dinode) { - rbm.rgd->rd_dinodes++; - *generation = rbm.rgd->rd_igeneration++; + rgd->rd_dinodes++; + *generation = rgd->rd_igeneration++; if (*generation == 0) - *generation = rbm.rgd->rd_igeneration++; + *generation = rgd->rd_igeneration++; } - gfs2_trans_add_bh(rbm.rgd->rd_gl, rbm.rgd->rd_bits[0].bi_bh, 1); - gfs2_rgrp_out(rbm.rgd, rbm.rgd->rd_bits[0].bi_bh->b_data); - gfs2_rgrp_ondisk2lvb(rbm.rgd->rd_rgl, rbm.rgd->rd_bits[0].bi_bh->b_data); + gfs2_trans_add_bh(rgd->rd_gl, rgd->rd_bits[0].bi_bh, 1); + gfs2_rgrp_out(rgd, rgd->rd_bits[0].bi_bh->b_data); + gfs2_rgrp_ondisk2lvb(rgd->rd_rgl, rgd->rd_bits[0].bi_bh->b_data); gfs2_statfs_change(sdp, 0, -(s64)*nblocks, dinode ? 1 : 0); if (dinode) @@ -2071,14 +2110,14 @@ int gfs2_alloc_blocks(struct gfs2_inode *ip, u64 *bn, unsigned int *nblocks, gfs2_quota_change(ip, ndata, ip->i_inode.i_uid, ip->i_inode.i_gid); - rbm.rgd->rd_free_clone -= *nblocks; - trace_gfs2_block_alloc(ip, rbm.rgd, block, *nblocks, + rgd->rd_free_clone -= *nblocks; + trace_gfs2_block_alloc(ip, rgd, block, *nblocks, dinode ? GFS2_BLKST_DINODE : GFS2_BLKST_USED); *bn = block; return 0; rgrp_error: - gfs2_rgrp_error(rbm.rgd); + gfs2_rgrp_error(rgd); return -EIO; } diff --git a/trunk/fs/gfs2/rgrp.h b/trunk/fs/gfs2/rgrp.h index 24077958dcf6..ca6e26729b86 100644 --- a/trunk/fs/gfs2/rgrp.h +++ b/trunk/fs/gfs2/rgrp.h @@ -46,7 +46,7 @@ extern int gfs2_alloc_blocks(struct gfs2_inode *ip, u64 *bn, unsigned int *n, bool dinode, u64 *generation); extern int gfs2_rs_alloc(struct gfs2_inode *ip); -extern void gfs2_rs_deltree(struct gfs2_inode *ip, struct gfs2_blkreserv *rs); +extern void gfs2_rs_deltree(struct gfs2_blkreserv *rs); extern void gfs2_rs_delete(struct gfs2_inode *ip); extern void __gfs2_free_blocks(struct gfs2_inode *ip, u64 bstart, u32 blen, int meta); extern void gfs2_free_meta(struct gfs2_inode *ip, u64 bstart, u32 blen); @@ -73,10 +73,30 @@ extern int gfs2_rgrp_send_discards(struct gfs2_sbd *sdp, u64 offset, const struct gfs2_bitmap *bi, unsigned minlen, u64 *ptrimmed); extern int gfs2_fitrim(struct file *filp, void __user *argp); -/* This is how to tell if a reservation is in the rgrp tree: */ -static inline bool gfs2_rs_active(struct gfs2_blkreserv *rs) +/* This is how to tell if a multi-block reservation is "inplace" reserved: */ +static inline int gfs2_mb_reserved(struct gfs2_inode *ip) { - return rs && !RB_EMPTY_NODE(&rs->rs_node); + if (ip->i_res && ip->i_res->rs_requested) + return 1; + return 0; +} + +/* This is how to tell if a multi-block reservation is in the rgrp tree: */ +static inline int gfs2_rs_active(struct gfs2_blkreserv *rs) +{ + if (rs && rs->rs_bi) + return 1; + return 0; +} + +static inline u32 gfs2_bi2rgd_blk(const struct gfs2_bitmap *bi, u32 blk) +{ + return (bi->bi_start * GFS2_NBBY) + blk; +} + +static inline u64 gfs2_rs_startblk(const struct gfs2_blkreserv *rs) +{ + return gfs2_bi2rgd_blk(rs->rs_bi, rs->rs_biblk) + rs->rs_rgd->rd_data0; } #endif /* __RGRP_DOT_H__ */ diff --git a/trunk/fs/gfs2/super.c b/trunk/fs/gfs2/super.c index a8d90f2f576c..fc3168f47a14 100644 --- a/trunk/fs/gfs2/super.c +++ b/trunk/fs/gfs2/super.c @@ -1366,8 +1366,6 @@ static int gfs2_show_options(struct seq_file *s, struct dentry *root) val = sdp->sd_tune.gt_statfs_quantum; if (val != 30) seq_printf(s, ",statfs_quantum=%d", val); - else if (sdp->sd_tune.gt_statfs_slow) - seq_puts(s, ",statfs_quantum=0"); val = sdp->sd_tune.gt_quota_quantum; if (val != 60) seq_printf(s, ",quota_quantum=%d", val); @@ -1545,11 +1543,6 @@ static void gfs2_evict_inode(struct inode *inode) out_truncate: gfs2_log_flush(sdp, ip->i_gl); - if (test_bit(GLF_DIRTY, &ip->i_gl->gl_flags)) { - struct address_space *metamapping = gfs2_glock2aspace(ip->i_gl); - filemap_fdatawrite(metamapping); - filemap_fdatawait(metamapping); - } write_inode_now(inode, 1); gfs2_ail_flush(ip->i_gl, 0); @@ -1564,7 +1557,7 @@ static void gfs2_evict_inode(struct inode *inode) out_unlock: /* Error path for case 1 */ if (gfs2_rs_active(ip->i_res)) - gfs2_rs_deltree(ip, ip->i_res); + gfs2_rs_deltree(ip->i_res); if (test_bit(HIF_HOLDER, &ip->i_iopen_gh.gh_iflags)) gfs2_glock_dq(&ip->i_iopen_gh); diff --git a/trunk/fs/gfs2/trace_gfs2.h b/trunk/fs/gfs2/trace_gfs2.h index bbdc78af60ca..a25c252fe412 100644 --- a/trunk/fs/gfs2/trace_gfs2.h +++ b/trunk/fs/gfs2/trace_gfs2.h @@ -509,9 +509,10 @@ TRACE_EVENT(gfs2_block_alloc, /* Keep track of multi-block reservations as they are allocated/freed */ TRACE_EVENT(gfs2_rs, - TP_PROTO(const struct gfs2_blkreserv *rs, u8 func), + TP_PROTO(const struct gfs2_inode *ip, const struct gfs2_blkreserv *rs, + u8 func), - TP_ARGS(rs, func), + TP_ARGS(ip, rs, func), TP_STRUCT__entry( __field( dev_t, dev ) @@ -525,17 +526,18 @@ TRACE_EVENT(gfs2_rs, ), TP_fast_assign( - __entry->dev = rs->rs_rbm.rgd->rd_sbd->sd_vfs->s_dev; - __entry->rd_addr = rs->rs_rbm.rgd->rd_addr; - __entry->rd_free_clone = rs->rs_rbm.rgd->rd_free_clone; - __entry->rd_reserved = rs->rs_rbm.rgd->rd_reserved; - __entry->inum = rs->rs_inum; - __entry->start = gfs2_rbm_to_block(&rs->rs_rbm); + __entry->dev = rs->rs_rgd ? rs->rs_rgd->rd_sbd->sd_vfs->s_dev : 0; + __entry->rd_addr = rs->rs_rgd ? rs->rs_rgd->rd_addr : 0; + __entry->rd_free_clone = rs->rs_rgd ? rs->rs_rgd->rd_free_clone : 0; + __entry->rd_reserved = rs->rs_rgd ? rs->rs_rgd->rd_reserved : 0; + __entry->inum = ip ? ip->i_no_addr : 0; + __entry->start = gfs2_rs_startblk(rs); __entry->free = rs->rs_free; __entry->func = func; ), - TP_printk("%u,%u bmap %llu resrv %llu rg:%llu rf:%lu rr:%lu %s f:%lu", + TP_printk("%u,%u bmap %llu resrv %llu rg:%llu rf:%lu rr:%lu %s " + "f:%lu", MAJOR(__entry->dev), MINOR(__entry->dev), (unsigned long long)__entry->inum, (unsigned long long)__entry->start, diff --git a/trunk/fs/gfs2/trans.h b/trunk/fs/gfs2/trans.h index bf2ae9aeee7a..41f42cdccbb8 100644 --- a/trunk/fs/gfs2/trans.h +++ b/trunk/fs/gfs2/trans.h @@ -28,10 +28,11 @@ struct gfs2_glock; /* reserve either the number of blocks to be allocated plus the rg header * block, or all of the blocks in the rg, whichever is smaller */ -static inline unsigned int gfs2_rg_blocks(const struct gfs2_inode *ip, unsigned requested) +static inline unsigned int gfs2_rg_blocks(const struct gfs2_inode *ip) { - if (requested < ip->i_rgd->rd_length) - return requested + 1; + const struct gfs2_blkreserv *rs = ip->i_res; + if (rs && rs->rs_requested < ip->i_rgd->rd_length) + return rs->rs_requested + 1; return ip->i_rgd->rd_length; } diff --git a/trunk/fs/gfs2/xattr.c b/trunk/fs/gfs2/xattr.c index db330e5518cd..27a0b4a901f5 100644 --- a/trunk/fs/gfs2/xattr.c +++ b/trunk/fs/gfs2/xattr.c @@ -448,18 +448,17 @@ ssize_t gfs2_listxattr(struct dentry *dentry, char *buffer, size_t size) } /** - * ea_iter_unstuffed - copies the unstuffed xattr data to/from the - * request buffer + * ea_get_unstuffed - actually copies the unstuffed data into the + * request buffer * @ip: The GFS2 inode * @ea: The extended attribute header structure - * @din: The data to be copied in - * @dout: The data to be copied out (one of din,dout will be NULL) + * @data: The data to be copied * * Returns: errno */ -static int gfs2_iter_unstuffed(struct gfs2_inode *ip, struct gfs2_ea_header *ea, - const char *din, char *dout) +static int ea_get_unstuffed(struct gfs2_inode *ip, struct gfs2_ea_header *ea, + char *data) { struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); struct buffer_head **bh; @@ -468,8 +467,6 @@ static int gfs2_iter_unstuffed(struct gfs2_inode *ip, struct gfs2_ea_header *ea, __be64 *dataptrs = GFS2_EA2DATAPTRS(ea); unsigned int x; int error = 0; - unsigned char *pos; - unsigned cp_size; bh = kcalloc(nptrs, sizeof(struct buffer_head *), GFP_NOFS); if (!bh) @@ -500,21 +497,12 @@ static int gfs2_iter_unstuffed(struct gfs2_inode *ip, struct gfs2_ea_header *ea, goto out; } - pos = bh[x]->b_data + sizeof(struct gfs2_meta_header); - cp_size = (sdp->sd_jbsize > amount) ? amount : sdp->sd_jbsize; - - if (dout) { - memcpy(dout, pos, cp_size); - dout += sdp->sd_jbsize; - } - - if (din) { - gfs2_trans_add_bh(ip->i_gl, bh[x], 1); - memcpy(pos, din, cp_size); - din += sdp->sd_jbsize; - } + memcpy(data, bh[x]->b_data + sizeof(struct gfs2_meta_header), + (sdp->sd_jbsize > amount) ? amount : sdp->sd_jbsize); amount -= sdp->sd_jbsize; + data += sdp->sd_jbsize; + brelse(bh[x]); } @@ -535,7 +523,7 @@ static int gfs2_ea_get_copy(struct gfs2_inode *ip, struct gfs2_ea_location *el, memcpy(data, GFS2_EA2DATA(el->el_ea), len); return len; } - ret = gfs2_iter_unstuffed(ip, el->el_ea, NULL, data); + ret = ea_get_unstuffed(ip, el->el_ea, data); if (ret < 0) return ret; return len; @@ -739,7 +727,7 @@ static int ea_alloc_skeleton(struct gfs2_inode *ip, struct gfs2_ea_request *er, goto out_gunlock_q; error = gfs2_trans_begin(GFS2_SB(&ip->i_inode), - blks + gfs2_rg_blocks(ip, blks) + + blks + gfs2_rg_blocks(ip) + RES_DINODE + RES_STATFS + RES_QUOTA, 0); if (error) goto out_ipres; @@ -1232,23 +1220,69 @@ static int gfs2_xattr_set(struct dentry *dentry, const char *name, size, flags, type); } - static int ea_acl_chmod_unstuffed(struct gfs2_inode *ip, struct gfs2_ea_header *ea, char *data) { struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); + struct buffer_head **bh; unsigned int amount = GFS2_EA_DATA_LEN(ea); unsigned int nptrs = DIV_ROUND_UP(amount, sdp->sd_jbsize); - int ret; + __be64 *dataptrs = GFS2_EA2DATAPTRS(ea); + unsigned int x; + int error; - ret = gfs2_trans_begin(sdp, nptrs + RES_DINODE, 0); - if (ret) - return ret; + bh = kcalloc(nptrs, sizeof(struct buffer_head *), GFP_NOFS); + if (!bh) + return -ENOMEM; - ret = gfs2_iter_unstuffed(ip, ea, data, NULL); - gfs2_trans_end(sdp); + error = gfs2_trans_begin(sdp, nptrs + RES_DINODE, 0); + if (error) + goto out; + + for (x = 0; x < nptrs; x++) { + error = gfs2_meta_read(ip->i_gl, be64_to_cpu(*dataptrs), 0, + bh + x); + if (error) { + while (x--) + brelse(bh[x]); + goto fail; + } + dataptrs++; + } - return ret; + for (x = 0; x < nptrs; x++) { + error = gfs2_meta_wait(sdp, bh[x]); + if (error) { + for (; x < nptrs; x++) + brelse(bh[x]); + goto fail; + } + if (gfs2_metatype_check(sdp, bh[x], GFS2_METATYPE_ED)) { + for (; x < nptrs; x++) + brelse(bh[x]); + error = -EIO; + goto fail; + } + + gfs2_trans_add_bh(ip->i_gl, bh[x], 1); + + memcpy(bh[x]->b_data + sizeof(struct gfs2_meta_header), data, + (sdp->sd_jbsize > amount) ? amount : sdp->sd_jbsize); + + amount -= sdp->sd_jbsize; + data += sdp->sd_jbsize; + + brelse(bh[x]); + } + +out: + kfree(bh); + return error; + +fail: + gfs2_trans_end(sdp); + kfree(bh); + return error; } int gfs2_xattr_acl_chmod(struct gfs2_inode *ip, struct iattr *attr, char *data) diff --git a/trunk/fs/hfs/mdb.c b/trunk/fs/hfs/mdb.c index b7ec224910c5..5fd51a5833ff 100644 --- a/trunk/fs/hfs/mdb.c +++ b/trunk/fs/hfs/mdb.c @@ -236,10 +236,10 @@ int hfs_mdb_get(struct super_block *sb) * hfs_mdb_commit() * * Description: - * This updates the MDB on disk. + * This updates the MDB on disk (look also at hfs_write_super()). * It does not check, if the superblock has been modified, or * if the filesystem has been mounted read-only. It is mainly - * called by hfs_sync_fs() and flush_mdb(). + * called by hfs_write_super() and hfs_btree_extend(). * Input Variable(s): * struct hfs_mdb *mdb: Pointer to the hfs MDB * int backup; diff --git a/trunk/fs/jbd/journal.c b/trunk/fs/jbd/journal.c index a2862339323b..425c2f2cf170 100644 --- a/trunk/fs/jbd/journal.c +++ b/trunk/fs/jbd/journal.c @@ -534,8 +534,8 @@ int journal_start_commit(journal_t *journal, tid_t *ptid) ret = 1; } else if (journal->j_committing_transaction) { /* - * If commit has been started, then we have to wait for - * completion of that transaction. + * If ext3_write_super() recently started a commit, then we + * have to wait for completion of that transaction */ if (ptid) *ptid = journal->j_committing_transaction->t_tid; @@ -1113,11 +1113,6 @@ static void mark_journal_empty(journal_t *journal) BUG_ON(!mutex_is_locked(&journal->j_checkpoint_mutex)); spin_lock(&journal->j_state_lock); - /* Is it already empty? */ - if (sb->s_start == 0) { - spin_unlock(&journal->j_state_lock); - return; - } jbd_debug(1, "JBD: Marking journal as empty (seq %d)\n", journal->j_tail_sequence); diff --git a/trunk/fs/jbd2/journal.c b/trunk/fs/jbd2/journal.c index e149b99a7ffb..e9a3c4c85594 100644 --- a/trunk/fs/jbd2/journal.c +++ b/trunk/fs/jbd2/journal.c @@ -612,8 +612,8 @@ int jbd2_journal_start_commit(journal_t *journal, tid_t *ptid) ret = 1; } else if (journal->j_committing_transaction) { /* - * If commit has been started, then we have to wait for - * completion of that transaction. + * If ext3_write_super() recently started a commit, then we + * have to wait for completion of that transaction */ if (ptid) *ptid = journal->j_committing_transaction->t_tid; @@ -1377,7 +1377,7 @@ static void jbd2_mark_journal_empty(journal_t *journal) * Update a journal's errno. Write updated superblock to disk waiting for IO * to complete. */ -void jbd2_journal_update_sb_errno(journal_t *journal) +static void jbd2_journal_update_sb_errno(journal_t *journal) { journal_superblock_t *sb = journal->j_superblock; @@ -1390,7 +1390,6 @@ void jbd2_journal_update_sb_errno(journal_t *journal) jbd2_write_superblock(journal, WRITE_SYNC); } -EXPORT_SYMBOL(jbd2_journal_update_sb_errno); /* * Read the superblock for a given journal, performing initial diff --git a/trunk/fs/libfs.c b/trunk/fs/libfs.c index 7cc37ca19cd8..a74cb1725ac6 100644 --- a/trunk/fs/libfs.c +++ b/trunk/fs/libfs.c @@ -874,7 +874,7 @@ struct dentry *generic_fh_to_dentry(struct super_block *sb, struct fid *fid, EXPORT_SYMBOL_GPL(generic_fh_to_dentry); /** - * generic_fh_to_parent - generic helper for the fh_to_parent export operation + * generic_fh_to_dentry - generic helper for the fh_to_parent export operation * @sb: filesystem to do the file handle conversion on * @fid: file handle to convert * @fh_len: length of the file handle in bytes diff --git a/trunk/fs/lockd/svclock.c b/trunk/fs/lockd/svclock.c index 8d80c990dffd..fb1a2bedbe97 100644 --- a/trunk/fs/lockd/svclock.c +++ b/trunk/fs/lockd/svclock.c @@ -289,6 +289,7 @@ static void nlmsvc_free_block(struct kref *kref) dprintk("lockd: freeing block %p...\n", block); /* Remove block from file's list of blocks */ + mutex_lock(&file->f_mutex); list_del_init(&block->b_flist); mutex_unlock(&file->f_mutex); @@ -302,7 +303,7 @@ static void nlmsvc_free_block(struct kref *kref) static void nlmsvc_release_block(struct nlm_block *block) { if (block != NULL) - kref_put_mutex(&block->b_count, nlmsvc_free_block, &block->b_file->f_mutex); + kref_put(&block->b_count, nlmsvc_free_block); } /* diff --git a/trunk/fs/logfs/dev_bdev.c b/trunk/fs/logfs/dev_bdev.c index e784a217b500..df0de27c2733 100644 --- a/trunk/fs/logfs/dev_bdev.c +++ b/trunk/fs/logfs/dev_bdev.c @@ -26,7 +26,6 @@ static int sync_request(struct page *page, struct block_device *bdev, int rw) struct completion complete; bio_init(&bio); - bio.bi_max_vecs = 1; bio.bi_io_vec = &bio_vec; bio_vec.bv_page = page; bio_vec.bv_len = PAGE_SIZE; @@ -96,11 +95,12 @@ static int __bdev_writeseg(struct super_block *sb, u64 ofs, pgoff_t index, struct address_space *mapping = super->s_mapping_inode->i_mapping; struct bio *bio; struct page *page; - unsigned int max_pages; + struct request_queue *q = bdev_get_queue(sb->s_bdev); + unsigned int max_pages = queue_max_hw_sectors(q) >> (PAGE_SHIFT - 9); int i; - max_pages = min(nr_pages, (size_t) bio_get_nr_vecs(super->s_bdev)); - + if (max_pages > BIO_MAX_PAGES) + max_pages = BIO_MAX_PAGES; bio = bio_alloc(GFP_NOFS, max_pages); BUG_ON(!bio); @@ -190,11 +190,12 @@ static int do_erase(struct super_block *sb, u64 ofs, pgoff_t index, { struct logfs_super *super = logfs_super(sb); struct bio *bio; - unsigned int max_pages; + struct request_queue *q = bdev_get_queue(sb->s_bdev); + unsigned int max_pages = queue_max_hw_sectors(q) >> (PAGE_SHIFT - 9); int i; - max_pages = min(nr_pages, (size_t) bio_get_nr_vecs(super->s_bdev)); - + if (max_pages > BIO_MAX_PAGES) + max_pages = BIO_MAX_PAGES; bio = bio_alloc(GFP_NOFS, max_pages); BUG_ON(!bio); diff --git a/trunk/fs/logfs/inode.c b/trunk/fs/logfs/inode.c index 6984562738d3..a422f42238b2 100644 --- a/trunk/fs/logfs/inode.c +++ b/trunk/fs/logfs/inode.c @@ -156,26 +156,10 @@ static void __logfs_destroy_inode(struct inode *inode) call_rcu(&inode->i_rcu, logfs_i_callback); } -static void __logfs_destroy_meta_inode(struct inode *inode) -{ - struct logfs_inode *li = logfs_inode(inode); - BUG_ON(li->li_block); - call_rcu(&inode->i_rcu, logfs_i_callback); -} - static void logfs_destroy_inode(struct inode *inode) { struct logfs_inode *li = logfs_inode(inode); - if (inode->i_ino < LOGFS_RESERVED_INOS) { - /* - * The reserved inodes are never destroyed unless we are in - * unmont path. - */ - __logfs_destroy_meta_inode(inode); - return; - } - BUG_ON(list_empty(&li->li_freeing_list)); spin_lock(&logfs_inode_lock); li->li_refcount--; @@ -389,8 +373,8 @@ static void logfs_put_super(struct super_block *sb) { struct logfs_super *super = logfs_super(sb); /* kill the meta-inodes */ - iput(super->s_segfile_inode); iput(super->s_master_inode); + iput(super->s_segfile_inode); iput(super->s_mapping_inode); } diff --git a/trunk/fs/logfs/journal.c b/trunk/fs/logfs/journal.c index 2a09b8d73989..1e1c369df22b 100644 --- a/trunk/fs/logfs/journal.c +++ b/trunk/fs/logfs/journal.c @@ -565,7 +565,7 @@ static void write_wbuf(struct super_block *sb, struct logfs_area *area, index = ofs >> PAGE_SHIFT; page_ofs = ofs & (PAGE_SIZE - 1); - page = find_or_create_page(mapping, index, GFP_NOFS); + page = find_lock_page(mapping, index); BUG_ON(!page); memcpy(wbuf, page_address(page) + page_ofs, super->s_writesize); unlock_page(page); diff --git a/trunk/fs/logfs/readwrite.c b/trunk/fs/logfs/readwrite.c index 5be0abef603d..f1cb512c5019 100644 --- a/trunk/fs/logfs/readwrite.c +++ b/trunk/fs/logfs/readwrite.c @@ -2189,6 +2189,7 @@ void logfs_evict_inode(struct inode *inode) return; } + BUG_ON(inode->i_ino < LOGFS_RESERVED_INOS); page = inode_to_page(inode); BUG_ON(!page); /* FIXME: Use emergency page */ logfs_put_write_page(page); diff --git a/trunk/fs/logfs/segment.c b/trunk/fs/logfs/segment.c index 038da0991794..e28d090c98d6 100644 --- a/trunk/fs/logfs/segment.c +++ b/trunk/fs/logfs/segment.c @@ -886,7 +886,7 @@ static struct logfs_area *alloc_area(struct super_block *sb) static void map_invalidatepage(struct page *page, unsigned long l) { - return; + BUG(); } static int map_releasepage(struct page *page, gfp_t g) diff --git a/trunk/fs/namei.c b/trunk/fs/namei.c index dd1ed1b8e98e..1b464390dde8 100644 --- a/trunk/fs/namei.c +++ b/trunk/fs/namei.c @@ -352,7 +352,6 @@ int __inode_permission(struct inode *inode, int mask) /** * sb_permission - Check superblock-level permissions * @sb: Superblock of inode to check permission on - * @inode: Inode to check permission on * @mask: Right to check for (%MAY_READ, %MAY_WRITE, %MAY_EXEC) * * Separate out file-system wide checks from inode-specific permission checks. @@ -657,7 +656,6 @@ int sysctl_protected_hardlinks __read_mostly = 1; /** * may_follow_link - Check symlink following for unsafe situations * @link: The path of the symlink - * @nd: nameidata pathwalk data * * In the case of the sysctl_protected_symlinks sysctl being enabled, * CAP_DAC_OVERRIDE needs to be specifically ignored if the symlink is @@ -2416,7 +2414,7 @@ static int atomic_open(struct nameidata *nd, struct dentry *dentry, goto out; } - mode = op->mode; + mode = op->mode & S_IALLUGO; if ((open_flag & O_CREAT) && !IS_POSIXACL(dir)) mode &= ~current_umask(); @@ -2454,7 +2452,7 @@ static int atomic_open(struct nameidata *nd, struct dentry *dentry, } if (open_flag & O_CREAT) { - error = may_o_create(&nd->path, dentry, mode); + error = may_o_create(&nd->path, dentry, op->mode); if (error) { create_error = error; if (open_flag & O_EXCL) @@ -2491,10 +2489,6 @@ static int atomic_open(struct nameidata *nd, struct dentry *dentry, dput(dentry); dentry = file->f_path.dentry; } - if (create_error && dentry->d_inode == NULL) { - error = create_error; - goto out; - } goto looked_up; } diff --git a/trunk/fs/namespace.c b/trunk/fs/namespace.c index 7bdf7907413f..4d31f73e2561 100644 --- a/trunk/fs/namespace.c +++ b/trunk/fs/namespace.c @@ -1886,14 +1886,8 @@ static int do_add_mount(struct mount *newmnt, struct path *path, int mnt_flags) return err; err = -EINVAL; - if (unlikely(!check_mnt(real_mount(path->mnt)))) { - /* that's acceptable only for automounts done in private ns */ - if (!(mnt_flags & MNT_SHRINKABLE)) - goto unlock; - /* ... and for those we'd better have mountpoint still alive */ - if (!real_mount(path->mnt)->mnt_ns) - goto unlock; - } + if (!(mnt_flags & MNT_SHRINKABLE) && !check_mnt(real_mount(path->mnt))) + goto unlock; /* Refuse the same filesystem on the same mount point */ err = -EBUSY; diff --git a/trunk/fs/nfs/Makefile b/trunk/fs/nfs/Makefile index b7db60897f91..8bf3a3f6925a 100644 --- a/trunk/fs/nfs/Makefile +++ b/trunk/fs/nfs/Makefile @@ -12,19 +12,19 @@ nfs-$(CONFIG_ROOT_NFS) += nfsroot.o nfs-$(CONFIG_SYSCTL) += sysctl.o nfs-$(CONFIG_NFS_FSCACHE) += fscache.o fscache-index.o -obj-$(CONFIG_NFS_V2) += nfsv2.o -nfsv2-y := nfs2super.o proc.o nfs2xdr.o +obj-$(CONFIG_NFS_V2) += nfs2.o +nfs2-y := nfs2super.o proc.o nfs2xdr.o -obj-$(CONFIG_NFS_V3) += nfsv3.o -nfsv3-y := nfs3super.o nfs3client.o nfs3proc.o nfs3xdr.o -nfsv3-$(CONFIG_NFS_V3_ACL) += nfs3acl.o +obj-$(CONFIG_NFS_V3) += nfs3.o +nfs3-y := nfs3super.o nfs3client.o nfs3proc.o nfs3xdr.o +nfs3-$(CONFIG_NFS_V3_ACL) += nfs3acl.o -obj-$(CONFIG_NFS_V4) += nfsv4.o -nfsv4-y := nfs4proc.o nfs4xdr.o nfs4state.o nfs4renewd.o nfs4super.o nfs4file.o \ +obj-$(CONFIG_NFS_V4) += nfs4.o +nfs4-y := nfs4proc.o nfs4xdr.o nfs4state.o nfs4renewd.o nfs4super.o nfs4file.o \ delegation.o idmap.o callback.o callback_xdr.o callback_proc.o \ nfs4namespace.o nfs4getroot.o nfs4client.o -nfsv4-$(CONFIG_SYSCTL) += nfs4sysctl.o -nfsv4-$(CONFIG_NFS_V4_1) += pnfs.o pnfs_dev.o +nfs4-$(CONFIG_SYSCTL) += nfs4sysctl.o +nfs4-$(CONFIG_NFS_V4_1) += pnfs.o pnfs_dev.o obj-$(CONFIG_PNFS_FILE_LAYOUT) += nfs_layout_nfsv41_files.o nfs_layout_nfsv41_files-y := nfs4filelayout.o nfs4filelayoutdev.o diff --git a/trunk/fs/nfs/client.c b/trunk/fs/nfs/client.c index 99694442b93f..9fc0d9dfc91b 100644 --- a/trunk/fs/nfs/client.c +++ b/trunk/fs/nfs/client.c @@ -105,7 +105,7 @@ struct nfs_subversion *get_nfs_version(unsigned int version) if (IS_ERR(nfs)) { mutex_lock(&nfs_version_mutex); - request_module("nfsv%d", version); + request_module("nfs%d", version); nfs = find_nfs_version(version); mutex_unlock(&nfs_version_mutex); } diff --git a/trunk/fs/nfs/file.c b/trunk/fs/nfs/file.c index 6a7fcab7ecb3..75d6d0a3d32e 100644 --- a/trunk/fs/nfs/file.c +++ b/trunk/fs/nfs/file.c @@ -287,12 +287,10 @@ nfs_file_fsync(struct file *file, loff_t start, loff_t end, int datasync) struct inode *inode = file->f_path.dentry->d_inode; ret = filemap_write_and_wait_range(inode->i_mapping, start, end); - if (ret != 0) - goto out; mutex_lock(&inode->i_mutex); ret = nfs_file_fsync_commit(file, start, end, datasync); mutex_unlock(&inode->i_mutex); -out: + return ret; } diff --git a/trunk/fs/nfs/idmap.c b/trunk/fs/nfs/idmap.c index a850079467d8..b701358c39c3 100644 --- a/trunk/fs/nfs/idmap.c +++ b/trunk/fs/nfs/idmap.c @@ -61,12 +61,6 @@ struct idmap { struct mutex idmap_mutex; }; -struct idmap_legacy_upcalldata { - struct rpc_pipe_msg pipe_msg; - struct idmap_msg idmap_msg; - struct idmap *idmap; -}; - /** * nfs_fattr_init_names - initialise the nfs_fattr owner_name/group_name fields * @fattr: fully initialised struct nfs_fattr @@ -330,7 +324,6 @@ static ssize_t nfs_idmap_get_key(const char *name, size_t namelen, ret = nfs_idmap_request_key(&key_type_id_resolver_legacy, name, namelen, type, data, data_size, idmap); - idmap->idmap_key_cons = NULL; mutex_unlock(&idmap->idmap_mutex); } return ret; @@ -387,13 +380,11 @@ static const match_table_t nfs_idmap_tokens = { static int nfs_idmap_legacy_upcall(struct key_construction *, const char *, void *); static ssize_t idmap_pipe_downcall(struct file *, const char __user *, size_t); -static void idmap_release_pipe(struct inode *); static void idmap_pipe_destroy_msg(struct rpc_pipe_msg *); static const struct rpc_pipe_ops idmap_upcall_ops = { .upcall = rpc_pipe_generic_upcall, .downcall = idmap_pipe_downcall, - .release_pipe = idmap_release_pipe, .destroy_msg = idmap_pipe_destroy_msg, }; @@ -625,8 +616,7 @@ void nfs_idmap_quit(void) nfs_idmap_quit_keyring(); } -static int nfs_idmap_prepare_message(char *desc, struct idmap *idmap, - struct idmap_msg *im, +static int nfs_idmap_prepare_message(char *desc, struct idmap_msg *im, struct rpc_pipe_msg *msg) { substring_t substr; @@ -669,7 +659,6 @@ static int nfs_idmap_legacy_upcall(struct key_construction *cons, const char *op, void *aux) { - struct idmap_legacy_upcalldata *data; struct rpc_pipe_msg *msg; struct idmap_msg *im; struct idmap *idmap = (struct idmap *)aux; @@ -677,15 +666,15 @@ static int nfs_idmap_legacy_upcall(struct key_construction *cons, int ret = -ENOMEM; /* msg and im are freed in idmap_pipe_destroy_msg */ - data = kmalloc(sizeof(*data), GFP_KERNEL); - if (!data) - goto out1; + msg = kmalloc(sizeof(*msg), GFP_KERNEL); + if (!msg) + goto out0; - msg = &data->pipe_msg; - im = &data->idmap_msg; - data->idmap = idmap; + im = kmalloc(sizeof(*im), GFP_KERNEL); + if (!im) + goto out1; - ret = nfs_idmap_prepare_message(key->description, idmap, im, msg); + ret = nfs_idmap_prepare_message(key->description, im, msg); if (ret < 0) goto out2; @@ -694,15 +683,15 @@ static int nfs_idmap_legacy_upcall(struct key_construction *cons, ret = rpc_queue_upcall(idmap->idmap_pipe, msg); if (ret < 0) - goto out3; + goto out2; return ret; -out3: - idmap->idmap_key_cons = NULL; out2: - kfree(data); + kfree(im); out1: + kfree(msg); +out0: complete_request_key(cons, ret); return ret; } @@ -760,8 +749,9 @@ idmap_pipe_downcall(struct file *filp, const char __user *src, size_t mlen) } if (!(im.im_status & IDMAP_STATUS_SUCCESS)) { - ret = -ENOKEY; - goto out; + ret = mlen; + complete_request_key(cons, -ENOKEY); + goto out_incomplete; } namelen_in = strnlen(im.im_name, IDMAP_NAMESZ); @@ -778,32 +768,16 @@ idmap_pipe_downcall(struct file *filp, const char __user *src, size_t mlen) out: complete_request_key(cons, ret); +out_incomplete: return ret; } static void idmap_pipe_destroy_msg(struct rpc_pipe_msg *msg) { - struct idmap_legacy_upcalldata *data = container_of(msg, - struct idmap_legacy_upcalldata, - pipe_msg); - struct idmap *idmap = data->idmap; - struct key_construction *cons; - if (msg->errno) { - cons = ACCESS_ONCE(idmap->idmap_key_cons); - idmap->idmap_key_cons = NULL; - complete_request_key(cons, msg->errno); - } /* Free memory allocated in nfs_idmap_legacy_upcall() */ - kfree(data); -} - -static void -idmap_release_pipe(struct inode *inode) -{ - struct rpc_inode *rpci = RPC_I(inode); - struct idmap *idmap = (struct idmap *)rpci->private; - idmap->idmap_key_cons = NULL; + kfree(msg->data); + kfree(msg); } int nfs_map_name_to_uid(const struct nfs_server *server, const char *name, size_t namelen, __u32 *uid) diff --git a/trunk/fs/nfs/inode.c b/trunk/fs/nfs/inode.c index 9b47610338f5..c6e895f0fbf3 100644 --- a/trunk/fs/nfs/inode.c +++ b/trunk/fs/nfs/inode.c @@ -154,7 +154,7 @@ static void nfs_zap_caches_locked(struct inode *inode) nfsi->attrtimeo = NFS_MINATTRTIMEO(inode); nfsi->attrtimeo_timestamp = jiffies; - memset(NFS_I(inode)->cookieverf, 0, sizeof(NFS_I(inode)->cookieverf)); + memset(NFS_COOKIEVERF(inode), 0, sizeof(NFS_COOKIEVERF(inode))); if (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)) nfsi->cache_validity |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL|NFS_INO_REVAL_PAGECACHE; else diff --git a/trunk/fs/nfs/nfs3proc.c b/trunk/fs/nfs/nfs3proc.c index 69322096c325..0952c791df36 100644 --- a/trunk/fs/nfs/nfs3proc.c +++ b/trunk/fs/nfs/nfs3proc.c @@ -69,7 +69,7 @@ do_proc_get_root(struct rpc_clnt *client, struct nfs_fh *fhandle, nfs_fattr_init(info->fattr); status = rpc_call_sync(client, &msg, 0); dprintk("%s: reply fsinfo: %d\n", __func__, status); - if (status == 0 && !(info->fattr->valid & NFS_ATTR_FATTR)) { + if (!(info->fattr->valid & NFS_ATTR_FATTR)) { msg.rpc_proc = &nfs3_procedures[NFS3PROC_GETATTR]; msg.rpc_resp = info->fattr; status = rpc_call_sync(client, &msg, 0); @@ -643,7 +643,7 @@ nfs3_proc_readdir(struct dentry *dentry, struct rpc_cred *cred, u64 cookie, struct page **pages, unsigned int count, int plus) { struct inode *dir = dentry->d_inode; - __be32 *verf = NFS_I(dir)->cookieverf; + __be32 *verf = NFS_COOKIEVERF(dir); struct nfs3_readdirargs arg = { .fh = NFS_FH(dir), .cookie = cookie, diff --git a/trunk/fs/nfs/nfs4_fs.h b/trunk/fs/nfs/nfs4_fs.h index da0618aeeadb..3b950dd81e81 100644 --- a/trunk/fs/nfs/nfs4_fs.h +++ b/trunk/fs/nfs/nfs4_fs.h @@ -205,9 +205,6 @@ extern const struct dentry_operations nfs4_dentry_operations; int nfs_atomic_open(struct inode *, struct dentry *, struct file *, unsigned, umode_t, int *); -/* super.c */ -extern struct file_system_type nfs4_fs_type; - /* nfs4namespace.c */ rpc_authflavor_t nfs_find_best_sec(struct nfs4_secinfo_flavors *); struct rpc_clnt *nfs4_create_sec_client(struct rpc_clnt *, struct inode *, struct qstr *); diff --git a/trunk/fs/nfs/nfs4client.c b/trunk/fs/nfs/nfs4client.c index 24eb663f8ed5..cbcdfaf32505 100644 --- a/trunk/fs/nfs/nfs4client.c +++ b/trunk/fs/nfs/nfs4client.c @@ -74,7 +74,7 @@ struct nfs_client *nfs4_alloc_client(const struct nfs_client_initdata *cl_init) return clp; error: - nfs_free_client(clp); + kfree(clp); return ERR_PTR(err); } diff --git a/trunk/fs/nfs/nfs4file.c b/trunk/fs/nfs/nfs4file.c index eb5eb8eef4d3..acb65e7887f8 100644 --- a/trunk/fs/nfs/nfs4file.c +++ b/trunk/fs/nfs/nfs4file.c @@ -96,15 +96,13 @@ nfs4_file_fsync(struct file *file, loff_t start, loff_t end, int datasync) struct inode *inode = file->f_path.dentry->d_inode; ret = filemap_write_and_wait_range(inode->i_mapping, start, end); - if (ret != 0) - goto out; mutex_lock(&inode->i_mutex); ret = nfs_file_fsync_commit(file, start, end, datasync); if (!ret && !datasync) /* application has asked for meta-data sync */ ret = pnfs_layoutcommit_inode(inode, true); mutex_unlock(&inode->i_mutex); -out: + return ret; } diff --git a/trunk/fs/nfs/nfs4proc.c b/trunk/fs/nfs/nfs4proc.c index 1e50326d00dd..a99a8d948721 100644 --- a/trunk/fs/nfs/nfs4proc.c +++ b/trunk/fs/nfs/nfs4proc.c @@ -3215,11 +3215,11 @@ static int _nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred, dentry->d_parent->d_name.name, dentry->d_name.name, (unsigned long long)cookie); - nfs4_setup_readdir(cookie, NFS_I(dir)->cookieverf, dentry, &args); + nfs4_setup_readdir(cookie, NFS_COOKIEVERF(dir), dentry, &args); res.pgbase = args.pgbase; status = nfs4_call_sync(NFS_SERVER(dir)->client, NFS_SERVER(dir), &msg, &args.seq_args, &res.seq_res, 0); if (status >= 0) { - memcpy(NFS_I(dir)->cookieverf, res.verifier.data, NFS4_VERIFIER_SIZE); + memcpy(NFS_COOKIEVERF(dir), res.verifier.data, NFS4_VERIFIER_SIZE); status += args.pgbase; } @@ -3653,11 +3653,11 @@ static inline int nfs4_server_supports_acls(struct nfs_server *server) && (server->acl_bitmask & ACL4_SUPPORT_DENY_ACL); } -/* Assuming that XATTR_SIZE_MAX is a multiple of PAGE_SIZE, and that - * it's OK to put sizeof(void) * (XATTR_SIZE_MAX/PAGE_SIZE) bytes on +/* Assuming that XATTR_SIZE_MAX is a multiple of PAGE_CACHE_SIZE, and that + * it's OK to put sizeof(void) * (XATTR_SIZE_MAX/PAGE_CACHE_SIZE) bytes on * the stack. */ -#define NFS4ACL_MAXPAGES DIV_ROUND_UP(XATTR_SIZE_MAX, PAGE_SIZE) +#define NFS4ACL_MAXPAGES (XATTR_SIZE_MAX >> PAGE_CACHE_SHIFT) static int buf_to_pages_noslab(const void *buf, size_t buflen, struct page **pages, unsigned int *pgbase) @@ -3668,7 +3668,7 @@ static int buf_to_pages_noslab(const void *buf, size_t buflen, spages = pages; do { - len = min_t(size_t, PAGE_SIZE, buflen); + len = min_t(size_t, PAGE_CACHE_SIZE, buflen); newpage = alloc_page(GFP_KERNEL); if (newpage == NULL) @@ -3737,10 +3737,9 @@ static inline ssize_t nfs4_read_cached_acl(struct inode *inode, char *buf, size_ static void nfs4_write_cached_acl(struct inode *inode, struct page **pages, size_t pgbase, size_t acl_len) { struct nfs4_cached_acl *acl; - size_t buflen = sizeof(*acl) + acl_len; - if (buflen <= PAGE_SIZE) { - acl = kmalloc(buflen, GFP_KERNEL); + if (pages && acl_len <= PAGE_SIZE) { + acl = kmalloc(sizeof(*acl) + acl_len, GFP_KERNEL); if (acl == NULL) goto out; acl->cached = 1; @@ -3782,15 +3781,17 @@ static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t bu .rpc_argp = &args, .rpc_resp = &res, }; - unsigned int npages = DIV_ROUND_UP(buflen, PAGE_SIZE); - int ret = -ENOMEM, i; + int ret = -ENOMEM, npages, i; + size_t acl_len = 0; + npages = (buflen + PAGE_SIZE - 1) >> PAGE_SHIFT; /* As long as we're doing a round trip to the server anyway, * let's be prepared for a page of acl data. */ if (npages == 0) npages = 1; - if (npages > ARRAY_SIZE(pages)) - return -ERANGE; + + /* Add an extra page to handle the bitmap returned */ + npages++; for (i = 0; i < npages; i++) { pages[i] = alloc_page(GFP_KERNEL); @@ -3806,6 +3807,11 @@ static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t bu args.acl_len = npages * PAGE_SIZE; args.acl_pgbase = 0; + /* Let decode_getfacl know not to fail if the ACL data is larger than + * the page we send as a guess */ + if (buf == NULL) + res.acl_flags |= NFS4_ACL_LEN_REQUEST; + dprintk("%s buf %p buflen %zu npages %d args.acl_len %zu\n", __func__, buf, buflen, npages, args.acl_len); ret = nfs4_call_sync(NFS_SERVER(inode)->client, NFS_SERVER(inode), @@ -3813,19 +3819,20 @@ static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t bu if (ret) goto out_free; - /* Handle the case where the passed-in buffer is too short */ - if (res.acl_flags & NFS4_ACL_TRUNC) { - /* Did the user only issue a request for the acl length? */ - if (buf == NULL) - goto out_ok; + acl_len = res.acl_len - res.acl_data_offset; + if (acl_len > args.acl_len) + nfs4_write_cached_acl(inode, NULL, 0, acl_len); + else + nfs4_write_cached_acl(inode, pages, res.acl_data_offset, + acl_len); + if (buf) { ret = -ERANGE; - goto out_free; + if (acl_len > buflen) + goto out_free; + _copy_from_pages(buf, pages, res.acl_data_offset, + acl_len); } - nfs4_write_cached_acl(inode, pages, res.acl_data_offset, res.acl_len); - if (buf) - _copy_from_pages(buf, pages, res.acl_data_offset, res.acl_len); -out_ok: - ret = res.acl_len; + ret = acl_len; out_free: for (i = 0; i < npages; i++) if (pages[i]) @@ -3883,13 +3890,10 @@ static int __nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t bufl .rpc_argp = &arg, .rpc_resp = &res, }; - unsigned int npages = DIV_ROUND_UP(buflen, PAGE_SIZE); int ret, i; if (!nfs4_server_supports_acls(server)) return -EOPNOTSUPP; - if (npages > ARRAY_SIZE(pages)) - return -ERANGE; i = buf_to_pages_noslab(buf, buflen, arg.acl_pages, &arg.acl_pgbase); if (i < 0) return i; @@ -6219,58 +6223,11 @@ static void nfs4_layoutget_done(struct rpc_task *task, void *calldata) dprintk("<-- %s\n", __func__); } -static size_t max_response_pages(struct nfs_server *server) -{ - u32 max_resp_sz = server->nfs_client->cl_session->fc_attrs.max_resp_sz; - return nfs_page_array_len(0, max_resp_sz); -} - -static void nfs4_free_pages(struct page **pages, size_t size) -{ - int i; - - if (!pages) - return; - - for (i = 0; i < size; i++) { - if (!pages[i]) - break; - __free_page(pages[i]); - } - kfree(pages); -} - -static struct page **nfs4_alloc_pages(size_t size, gfp_t gfp_flags) -{ - struct page **pages; - int i; - - pages = kcalloc(size, sizeof(struct page *), gfp_flags); - if (!pages) { - dprintk("%s: can't alloc array of %zu pages\n", __func__, size); - return NULL; - } - - for (i = 0; i < size; i++) { - pages[i] = alloc_page(gfp_flags); - if (!pages[i]) { - dprintk("%s: failed to allocate page\n", __func__); - nfs4_free_pages(pages, size); - return NULL; - } - } - - return pages; -} - static void nfs4_layoutget_release(void *calldata) { struct nfs4_layoutget *lgp = calldata; - struct nfs_server *server = NFS_SERVER(lgp->args.inode); - size_t max_pages = max_response_pages(server); dprintk("--> %s\n", __func__); - nfs4_free_pages(lgp->args.layout.pages, max_pages); put_nfs_open_context(lgp->args.ctx); kfree(calldata); dprintk("<-- %s\n", __func__); @@ -6282,10 +6239,9 @@ static const struct rpc_call_ops nfs4_layoutget_call_ops = { .rpc_release = nfs4_layoutget_release, }; -void nfs4_proc_layoutget(struct nfs4_layoutget *lgp, gfp_t gfp_flags) +int nfs4_proc_layoutget(struct nfs4_layoutget *lgp) { struct nfs_server *server = NFS_SERVER(lgp->args.inode); - size_t max_pages = max_response_pages(server); struct rpc_task *task; struct rpc_message msg = { .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LAYOUTGET], @@ -6303,19 +6259,12 @@ void nfs4_proc_layoutget(struct nfs4_layoutget *lgp, gfp_t gfp_flags) dprintk("--> %s\n", __func__); - lgp->args.layout.pages = nfs4_alloc_pages(max_pages, gfp_flags); - if (!lgp->args.layout.pages) { - nfs4_layoutget_release(lgp); - return; - } - lgp->args.layout.pglen = max_pages * PAGE_SIZE; - lgp->res.layoutp = &lgp->args.layout; lgp->res.seq_res.sr_slot = NULL; nfs41_init_sequence(&lgp->args.seq_args, &lgp->res.seq_res, 0); task = rpc_run_task(&task_setup_data); if (IS_ERR(task)) - return; + return PTR_ERR(task); status = nfs4_wait_for_completion_rpc_task(task); if (status == 0) status = task->tk_status; @@ -6323,7 +6272,7 @@ void nfs4_proc_layoutget(struct nfs4_layoutget *lgp, gfp_t gfp_flags) status = pnfs_layout_process(lgp); rpc_put_task(task); dprintk("<-- %s status=%d\n", __func__, status); - return; + return status; } static void @@ -6355,8 +6304,12 @@ static void nfs4_layoutreturn_done(struct rpc_task *task, void *calldata) return; } spin_lock(&lo->plh_inode->i_lock); - if (task->tk_status == 0 && lrp->res.lrs_present) - pnfs_set_layout_stateid(lo, &lrp->res.stateid, true); + if (task->tk_status == 0) { + if (lrp->res.lrs_present) { + pnfs_set_layout_stateid(lo, &lrp->res.stateid, true); + } else + BUG_ON(!list_empty(&lo->plh_segs)); + } lo->plh_block_lgets--; spin_unlock(&lo->plh_inode->i_lock); dprintk("<-- %s\n", __func__); diff --git a/trunk/fs/nfs/nfs4super.c b/trunk/fs/nfs/nfs4super.c index bd61221ad2c5..12a31a9dbcdd 100644 --- a/trunk/fs/nfs/nfs4super.c +++ b/trunk/fs/nfs/nfs4super.c @@ -23,6 +23,14 @@ static struct dentry *nfs4_referral_mount(struct file_system_type *fs_type, static struct dentry *nfs4_remote_referral_mount(struct file_system_type *fs_type, int flags, const char *dev_name, void *raw_data); +static struct file_system_type nfs4_fs_type = { + .owner = THIS_MODULE, + .name = "nfs4", + .mount = nfs_fs_mount, + .kill_sb = nfs_kill_super, + .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA, +}; + static struct file_system_type nfs4_remote_fs_type = { .owner = THIS_MODULE, .name = "nfs4", @@ -336,8 +344,14 @@ static int __init init_nfs_v4(void) if (err) goto out1; + err = register_filesystem(&nfs4_fs_type); + if (err < 0) + goto out2; + register_nfs_version(&nfs_v4); return 0; +out2: + nfs4_unregister_sysctl(); out1: nfs_idmap_quit(); out: @@ -347,6 +361,7 @@ static int __init init_nfs_v4(void) static void __exit exit_nfs_v4(void) { unregister_nfs_version(&nfs_v4); + unregister_filesystem(&nfs4_fs_type); nfs4_unregister_sysctl(); nfs_idmap_quit(); } diff --git a/trunk/fs/nfs/nfs4xdr.c b/trunk/fs/nfs/nfs4xdr.c index 8dba6bd48557..ca13483edd60 100644 --- a/trunk/fs/nfs/nfs4xdr.c +++ b/trunk/fs/nfs/nfs4xdr.c @@ -5045,19 +5045,22 @@ static int decode_getacl(struct xdr_stream *xdr, struct rpc_rqst *req, struct nfs_getaclres *res) { unsigned int savep; + __be32 *bm_p; uint32_t attrlen, bitmap[3] = {0}; int status; - unsigned int pg_offset; + size_t page_len = xdr->buf->page_len; res->acl_len = 0; if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0) goto out; - xdr_enter_page(xdr, xdr->buf->page_len); - - /* Calculate the offset of the page data */ - pg_offset = xdr->buf->head[0].iov_len; + bm_p = xdr->p; + res->acl_data_offset = be32_to_cpup(bm_p) + 2; + res->acl_data_offset <<= 2; + /* Check if the acl data starts beyond the allocated buffer */ + if (res->acl_data_offset > page_len) + return -ERANGE; if ((status = decode_attr_bitmap(xdr, bitmap)) != 0) goto out; @@ -5071,16 +5074,23 @@ static int decode_getacl(struct xdr_stream *xdr, struct rpc_rqst *req, /* The bitmap (xdr len + bitmaps) and the attr xdr len words * are stored with the acl data to handle the problem of * variable length bitmaps.*/ - res->acl_data_offset = xdr_stream_pos(xdr) - pg_offset; - res->acl_len = attrlen; - - /* Check for receive buffer overflow */ - if (res->acl_len > (xdr->nwords << 2) || - res->acl_len + res->acl_data_offset > xdr->buf->page_len) { - res->acl_flags |= NFS4_ACL_TRUNC; - dprintk("NFS: acl reply: attrlen %u > page_len %u\n", - attrlen, xdr->nwords << 2); + xdr->p = bm_p; + + /* We ignore &savep and don't do consistency checks on + * the attr length. Let userspace figure it out.... */ + attrlen += res->acl_data_offset; + if (attrlen > page_len) { + if (res->acl_flags & NFS4_ACL_LEN_REQUEST) { + /* getxattr interface called with a NULL buf */ + res->acl_len = attrlen; + goto out; + } + dprintk("NFS: acl reply: attrlen %u > page_len %zu\n", + attrlen, page_len); + return -EINVAL; } + xdr_read_pages(xdr, attrlen); + res->acl_len = attrlen; } else status = -EOPNOTSUPP; @@ -6225,8 +6235,7 @@ static int nfs4_xdr_dec_open(struct rpc_rqst *rqstp, struct xdr_stream *xdr, status = decode_open(xdr, res); if (status) goto out; - status = decode_getfh(xdr, &res->fh); - if (status) + if (decode_getfh(xdr, &res->fh) != 0) goto out; decode_getfattr(xdr, res->f_attr, res->server); out: diff --git a/trunk/fs/nfs/objlayout/objio_osd.c b/trunk/fs/nfs/objlayout/objio_osd.c index ea6d111b03e9..f50d3e8d6f22 100644 --- a/trunk/fs/nfs/objlayout/objio_osd.c +++ b/trunk/fs/nfs/objlayout/objio_osd.c @@ -570,66 +570,17 @@ static bool objio_pg_test(struct nfs_pageio_descriptor *pgio, return false; return pgio->pg_count + req->wb_bytes <= - (unsigned long)pgio->pg_layout_private; -} - -void objio_init_read(struct nfs_pageio_descriptor *pgio, struct nfs_page *req) -{ - pnfs_generic_pg_init_read(pgio, req); - if (unlikely(pgio->pg_lseg == NULL)) - return; /* Not pNFS */ - - pgio->pg_layout_private = (void *) - OBJIO_LSEG(pgio->pg_lseg)->layout.max_io_length; -} - -static bool aligned_on_raid_stripe(u64 offset, struct ore_layout *layout, - unsigned long *stripe_end) -{ - u32 stripe_off; - unsigned stripe_size; - - if (layout->raid_algorithm == PNFS_OSD_RAID_0) - return true; - - stripe_size = layout->stripe_unit * - (layout->group_width - layout->parity); - - div_u64_rem(offset, stripe_size, &stripe_off); - if (!stripe_off) - return true; - - *stripe_end = stripe_size - stripe_off; - return false; -} - -void objio_init_write(struct nfs_pageio_descriptor *pgio, struct nfs_page *req) -{ - unsigned long stripe_end = 0; - - pnfs_generic_pg_init_write(pgio, req); - if (unlikely(pgio->pg_lseg == NULL)) - return; /* Not pNFS */ - - if (req->wb_offset || - !aligned_on_raid_stripe(req->wb_index * PAGE_SIZE, - &OBJIO_LSEG(pgio->pg_lseg)->layout, - &stripe_end)) { - pgio->pg_layout_private = (void *)stripe_end; - } else { - pgio->pg_layout_private = (void *) - OBJIO_LSEG(pgio->pg_lseg)->layout.max_io_length; - } + OBJIO_LSEG(pgio->pg_lseg)->layout.max_io_length; } static const struct nfs_pageio_ops objio_pg_read_ops = { - .pg_init = objio_init_read, + .pg_init = pnfs_generic_pg_init_read, .pg_test = objio_pg_test, .pg_doio = pnfs_generic_pg_readpages, }; static const struct nfs_pageio_ops objio_pg_write_ops = { - .pg_init = objio_init_write, + .pg_init = pnfs_generic_pg_init_write, .pg_test = objio_pg_test, .pg_doio = pnfs_generic_pg_writepages, }; diff --git a/trunk/fs/nfs/pagelist.c b/trunk/fs/nfs/pagelist.c index 311a79681e2b..1a6732ed04a4 100644 --- a/trunk/fs/nfs/pagelist.c +++ b/trunk/fs/nfs/pagelist.c @@ -49,7 +49,6 @@ void nfs_pgheader_init(struct nfs_pageio_descriptor *desc, hdr->io_start = req_offset(hdr->req); hdr->good_bytes = desc->pg_count; hdr->dreq = desc->pg_dreq; - hdr->layout_private = desc->pg_layout_private; hdr->release = release; hdr->completion_ops = desc->pg_completion_ops; if (hdr->completion_ops->init_hdr) @@ -269,7 +268,6 @@ void nfs_pageio_init(struct nfs_pageio_descriptor *desc, desc->pg_error = 0; desc->pg_lseg = NULL; desc->pg_dreq = NULL; - desc->pg_layout_private = NULL; } EXPORT_SYMBOL_GPL(nfs_pageio_init); diff --git a/trunk/fs/nfs/pnfs.c b/trunk/fs/nfs/pnfs.c index 2e00feacd4be..76875bfcf19c 100644 --- a/trunk/fs/nfs/pnfs.c +++ b/trunk/fs/nfs/pnfs.c @@ -583,6 +583,9 @@ send_layoutget(struct pnfs_layout_hdr *lo, struct nfs_server *server = NFS_SERVER(ino); struct nfs4_layoutget *lgp; struct pnfs_layout_segment *lseg = NULL; + struct page **pages = NULL; + int i; + u32 max_resp_sz, max_pages; dprintk("--> %s\n", __func__); @@ -591,6 +594,20 @@ send_layoutget(struct pnfs_layout_hdr *lo, if (lgp == NULL) return NULL; + /* allocate pages for xdr post processing */ + max_resp_sz = server->nfs_client->cl_session->fc_attrs.max_resp_sz; + max_pages = nfs_page_array_len(0, max_resp_sz); + + pages = kcalloc(max_pages, sizeof(struct page *), gfp_flags); + if (!pages) + goto out_err_free; + + for (i = 0; i < max_pages; i++) { + pages[i] = alloc_page(gfp_flags); + if (!pages[i]) + goto out_err_free; + } + lgp->args.minlength = PAGE_CACHE_SIZE; if (lgp->args.minlength > range->length) lgp->args.minlength = range->length; @@ -599,19 +616,39 @@ send_layoutget(struct pnfs_layout_hdr *lo, lgp->args.type = server->pnfs_curr_ld->id; lgp->args.inode = ino; lgp->args.ctx = get_nfs_open_context(ctx); + lgp->args.layout.pages = pages; + lgp->args.layout.pglen = max_pages * PAGE_SIZE; lgp->lsegpp = &lseg; lgp->gfp_flags = gfp_flags; /* Synchronously retrieve layout information from server and * store in lseg. */ - nfs4_proc_layoutget(lgp, gfp_flags); + nfs4_proc_layoutget(lgp); if (!lseg) { /* remember that LAYOUTGET failed and suspend trying */ set_bit(lo_fail_bit(range->iomode), &lo->plh_flags); } + /* free xdr pages */ + for (i = 0; i < max_pages; i++) + __free_page(pages[i]); + kfree(pages); + return lseg; + +out_err_free: + /* free any allocated xdr pages, lgp as it's not used */ + if (pages) { + for (i = 0; i < max_pages; i++) { + if (!pages[i]) + break; + __free_page(pages[i]); + } + kfree(pages); + } + kfree(lgp); + return NULL; } /* diff --git a/trunk/fs/nfs/pnfs.h b/trunk/fs/nfs/pnfs.h index 745aa1b39e7c..2c6c80503ba4 100644 --- a/trunk/fs/nfs/pnfs.h +++ b/trunk/fs/nfs/pnfs.h @@ -172,7 +172,7 @@ extern int nfs4_proc_getdevicelist(struct nfs_server *server, struct pnfs_devicelist *devlist); extern int nfs4_proc_getdeviceinfo(struct nfs_server *server, struct pnfs_device *dev); -extern void nfs4_proc_layoutget(struct nfs4_layoutget *lgp, gfp_t gfp_flags); +extern int nfs4_proc_layoutget(struct nfs4_layoutget *lgp); extern int nfs4_proc_layoutreturn(struct nfs4_layoutreturn *lrp); /* pnfs.c */ diff --git a/trunk/fs/nfs/super.c b/trunk/fs/nfs/super.c index d2c7f5db0847..ac6a3c55dce4 100644 --- a/trunk/fs/nfs/super.c +++ b/trunk/fs/nfs/super.c @@ -319,34 +319,6 @@ EXPORT_SYMBOL_GPL(nfs_sops); static void nfs4_validate_mount_flags(struct nfs_parsed_mount_data *); static int nfs4_validate_mount_data(void *options, struct nfs_parsed_mount_data *args, const char *dev_name); - -struct file_system_type nfs4_fs_type = { - .owner = THIS_MODULE, - .name = "nfs4", - .mount = nfs_fs_mount, - .kill_sb = nfs_kill_super, - .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA, -}; -EXPORT_SYMBOL_GPL(nfs4_fs_type); - -static int __init register_nfs4_fs(void) -{ - return register_filesystem(&nfs4_fs_type); -} - -static void unregister_nfs4_fs(void) -{ - unregister_filesystem(&nfs4_fs_type); -} -#else -static int __init register_nfs4_fs(void) -{ - return 0; -} - -static void unregister_nfs4_fs(void) -{ -} #endif static struct shrinker acl_shrinker = { @@ -365,18 +337,12 @@ int __init register_nfs_fs(void) if (ret < 0) goto error_0; - ret = register_nfs4_fs(); - if (ret < 0) - goto error_1; - ret = nfs_register_sysctl(); if (ret < 0) - goto error_2; + goto error_1; register_shrinker(&acl_shrinker); return 0; -error_2: - unregister_nfs4_fs(); error_1: unregister_filesystem(&nfs_fs_type); error_0: @@ -390,7 +356,6 @@ void __exit unregister_nfs_fs(void) { unregister_shrinker(&acl_shrinker); nfs_unregister_sysctl(); - unregister_nfs4_fs(); unregister_filesystem(&nfs_fs_type); } @@ -1537,7 +1502,7 @@ static int nfs_parse_mount_options(char *raw, /* * verify that any proto=/mountproto= options match the address - * families in the addr=/mountaddr= options. + * familiies in the addr=/mountaddr= options. */ if (protofamily != AF_UNSPEC && protofamily != mnt->nfs_server.address.ss_family) @@ -1867,7 +1832,6 @@ static int nfs23_validate_mount_data(void *options, memcpy(sap, &data->addr, sizeof(data->addr)); args->nfs_server.addrlen = sizeof(data->addr); - args->nfs_server.port = ntohs(data->addr.sin_port); if (!nfs_verify_server_address(sap)) goto out_no_address; @@ -2565,7 +2529,6 @@ static int nfs4_validate_mount_data(void *options, return -EFAULT; if (!nfs_verify_server_address(sap)) goto out_no_address; - args->nfs_server.port = ntohs(((struct sockaddr_in *)sap)->sin_port); if (data->auth_flavourlen) { if (data->auth_flavourlen > 1) @@ -2682,6 +2645,4 @@ MODULE_PARM_DESC(max_session_slots, "Maximum number of outstanding NFSv4.1 " module_param(send_implementation_id, ushort, 0644); MODULE_PARM_DESC(send_implementation_id, "Send implementation ID with NFSv4.1 exchange_id"); -MODULE_ALIAS("nfs4"); - #endif /* CONFIG_NFS_V4 */ diff --git a/trunk/fs/nfs/write.c b/trunk/fs/nfs/write.c index e3b55372726c..5829d0ce7cfb 100644 --- a/trunk/fs/nfs/write.c +++ b/trunk/fs/nfs/write.c @@ -1814,19 +1814,19 @@ int __init nfs_init_writepagecache(void) nfs_wdata_mempool = mempool_create_slab_pool(MIN_POOL_WRITE, nfs_wdata_cachep); if (nfs_wdata_mempool == NULL) - goto out_destroy_write_cache; + return -ENOMEM; nfs_cdata_cachep = kmem_cache_create("nfs_commit_data", sizeof(struct nfs_commit_data), 0, SLAB_HWCACHE_ALIGN, NULL); if (nfs_cdata_cachep == NULL) - goto out_destroy_write_mempool; + return -ENOMEM; nfs_commit_mempool = mempool_create_slab_pool(MIN_POOL_COMMIT, nfs_wdata_cachep); if (nfs_commit_mempool == NULL) - goto out_destroy_commit_cache; + return -ENOMEM; /* * NFS congestion size, scale with available memory. @@ -1849,20 +1849,11 @@ int __init nfs_init_writepagecache(void) nfs_congestion_kb = 256*1024; return 0; - -out_destroy_commit_cache: - kmem_cache_destroy(nfs_cdata_cachep); -out_destroy_write_mempool: - mempool_destroy(nfs_wdata_mempool); -out_destroy_write_cache: - kmem_cache_destroy(nfs_wdata_cachep); - return -ENOMEM; } void nfs_destroy_writepagecache(void) { mempool_destroy(nfs_commit_mempool); - kmem_cache_destroy(nfs_cdata_cachep); mempool_destroy(nfs_wdata_mempool); kmem_cache_destroy(nfs_wdata_cachep); } diff --git a/trunk/fs/nfsd/nfs4callback.c b/trunk/fs/nfsd/nfs4callback.c index 4c7bd35b1876..cbaf4f8bb7b7 100644 --- a/trunk/fs/nfsd/nfs4callback.c +++ b/trunk/fs/nfsd/nfs4callback.c @@ -651,12 +651,12 @@ static int setup_callback_client(struct nfs4_client *clp, struct nfs4_cb_conn *c if (clp->cl_minorversion == 0) { if (!clp->cl_cred.cr_principal && - (clp->cl_cred.cr_flavor >= RPC_AUTH_GSS_KRB5)) + (clp->cl_flavor >= RPC_AUTH_GSS_KRB5)) return -EINVAL; args.client_name = clp->cl_cred.cr_principal; args.prognumber = conn->cb_prog, args.protocol = XPRT_TRANSPORT_TCP; - args.authflavor = clp->cl_cred.cr_flavor; + args.authflavor = clp->cl_flavor; clp->cl_cb_ident = conn->cb_ident; } else { if (!conn->cb_xprt) diff --git a/trunk/fs/nfsd/state.h b/trunk/fs/nfsd/state.h index 22bd0a66c356..e6173147f982 100644 --- a/trunk/fs/nfsd/state.h +++ b/trunk/fs/nfsd/state.h @@ -231,6 +231,7 @@ struct nfs4_client { nfs4_verifier cl_verifier; /* generated by client */ time_t cl_time; /* time of last lease renewal */ struct sockaddr_storage cl_addr; /* client ipaddress */ + u32 cl_flavor; /* setclientid pseudoflavor */ struct svc_cred cl_cred; /* setclientid principal */ clientid_t cl_clientid; /* generated by server */ nfs4_verifier cl_confirm; /* generated by server */ diff --git a/trunk/fs/nilfs2/super.c b/trunk/fs/nilfs2/super.c index 6a10812711c1..6522cac6057c 100644 --- a/trunk/fs/nilfs2/super.c +++ b/trunk/fs/nilfs2/super.c @@ -676,13 +676,17 @@ static const struct super_operations nilfs_sops = { .alloc_inode = nilfs_alloc_inode, .destroy_inode = nilfs_destroy_inode, .dirty_inode = nilfs_dirty_inode, + /* .write_inode = nilfs_write_inode, */ + /* .drop_inode = nilfs_drop_inode, */ .evict_inode = nilfs_evict_inode, .put_super = nilfs_put_super, + /* .write_super = nilfs_write_super, */ .sync_fs = nilfs_sync_fs, .freeze_fs = nilfs_freeze, .unfreeze_fs = nilfs_unfreeze, .statfs = nilfs_statfs, .remount_fs = nilfs_remount, + /* .umount_begin */ .show_options = nilfs_show_options }; diff --git a/trunk/fs/nilfs2/the_nilfs.h b/trunk/fs/nilfs2/the_nilfs.h index be1267a34cea..6eee4177807b 100644 --- a/trunk/fs/nilfs2/the_nilfs.h +++ b/trunk/fs/nilfs2/the_nilfs.h @@ -107,6 +107,8 @@ struct the_nilfs { * used for * - loading the latest checkpoint exclusively. * - allocating a new full segment. + * - protecting s_dirt in the super_block struct + * (see nilfs_write_super) and the following fields. */ struct buffer_head *ns_sbh[2]; struct nilfs_super_block *ns_sbp[2]; diff --git a/trunk/fs/open.c b/trunk/fs/open.c index e1f2cdb91a4d..f3d96e7e7b19 100644 --- a/trunk/fs/open.c +++ b/trunk/fs/open.c @@ -717,7 +717,7 @@ static int do_dentry_open(struct file *f, * here, so just reset the state. */ file_reset_write(f); - __mnt_drop_write(f->f_path.mnt); + mnt_drop_write(f->f_path.mnt); } } cleanup_file: @@ -852,10 +852,9 @@ static inline int build_open_flags(int flags, umode_t mode, struct open_flags *o int lookup_flags = 0; int acc_mode; - if (flags & O_CREAT) - op->mode = (mode & S_IALLUGO) | S_IFREG; - else - op->mode = 0; + if (!(flags & O_CREAT)) + mode = 0; + op->mode = mode; /* Must never be set by userspace */ flags &= ~FMODE_NONOTIFY; diff --git a/trunk/fs/proc/proc_sysctl.c b/trunk/fs/proc/proc_sysctl.c index eb7cc91b7258..dfafeb2b05a0 100644 --- a/trunk/fs/proc/proc_sysctl.c +++ b/trunk/fs/proc/proc_sysctl.c @@ -462,6 +462,9 @@ static struct dentry *proc_sys_lookup(struct inode *dir, struct dentry *dentry, err = ERR_PTR(-ENOMEM); inode = proc_sys_make_inode(dir->i_sb, h ? h : head, p); + if (h) + sysctl_head_finish(h); + if (!inode) goto out; @@ -470,8 +473,6 @@ static struct dentry *proc_sys_lookup(struct inode *dir, struct dentry *dentry, d_add(dentry, inode); out: - if (h) - sysctl_head_finish(h); sysctl_head_finish(head); return err; } diff --git a/trunk/fs/quota/dquot.c b/trunk/fs/quota/dquot.c index c495a3055e2a..36a29b753c79 100644 --- a/trunk/fs/quota/dquot.c +++ b/trunk/fs/quota/dquot.c @@ -1589,10 +1589,10 @@ int __dquot_alloc_space(struct inode *inode, qsize_t number, int flags) goto out; } + down_read(&sb_dqopt(inode->i_sb)->dqptr_sem); for (cnt = 0; cnt < MAXQUOTAS; cnt++) warn[cnt].w_type = QUOTA_NL_NOWARN; - down_read(&sb_dqopt(inode->i_sb)->dqptr_sem); spin_lock(&dq_data_lock); for (cnt = 0; cnt < MAXQUOTAS; cnt++) { if (!dquots[cnt]) diff --git a/trunk/fs/reiserfs/bitmap.c b/trunk/fs/reiserfs/bitmap.c index a98b7740a0fc..4c0c7d163d15 100644 --- a/trunk/fs/reiserfs/bitmap.c +++ b/trunk/fs/reiserfs/bitmap.c @@ -1334,7 +1334,9 @@ struct buffer_head *reiserfs_read_bitmap_block(struct super_block *sb, else if (bitmap == 0) block = (REISERFS_DISK_OFFSET_IN_BYTES >> sb->s_blocksize_bits) + 1; + reiserfs_write_unlock(sb); bh = sb_bread(sb, block); + reiserfs_write_lock(sb); if (bh == NULL) reiserfs_warning(sb, "sh-2029: %s: bitmap block (#%u) " "reading failed", __func__, block); diff --git a/trunk/fs/reiserfs/inode.c b/trunk/fs/reiserfs/inode.c index 855da58db145..a6d4268fb6c1 100644 --- a/trunk/fs/reiserfs/inode.c +++ b/trunk/fs/reiserfs/inode.c @@ -76,10 +76,10 @@ void reiserfs_evict_inode(struct inode *inode) ; } out: - reiserfs_write_unlock_once(inode->i_sb, depth); clear_inode(inode); /* note this must go after the journal_end to prevent deadlock */ dquot_drop(inode); inode->i_blocks = 0; + reiserfs_write_unlock_once(inode->i_sb, depth); return; no_delete: diff --git a/trunk/fs/stat.c b/trunk/fs/stat.c index 208039eec6c7..b6ff11825fc8 100644 --- a/trunk/fs/stat.c +++ b/trunk/fs/stat.c @@ -58,7 +58,7 @@ EXPORT_SYMBOL(vfs_getattr); int vfs_fstat(unsigned int fd, struct kstat *stat) { int fput_needed; - struct file *f = fget_raw_light(fd, &fput_needed); + struct file *f = fget_light(fd, &fput_needed); int error = -EBADF; if (f) { @@ -326,7 +326,7 @@ SYSCALL_DEFINE3(readlink, const char __user *, path, char __user *, buf, /* ---------- LFS-64 ----------- */ -#if defined(__ARCH_WANT_STAT64) || defined(__ARCH_WANT_COMPAT_STAT64) +#ifdef __ARCH_WANT_STAT64 #ifndef INIT_STRUCT_STAT64_PADDING # define INIT_STRUCT_STAT64_PADDING(st) memset(&st, 0, sizeof(st)) @@ -415,7 +415,7 @@ SYSCALL_DEFINE4(fstatat64, int, dfd, const char __user *, filename, return error; return cp_new_stat64(&stat, statbuf); } -#endif /* __ARCH_WANT_STAT64 || __ARCH_WANT_COMPAT_STAT64 */ +#endif /* __ARCH_WANT_STAT64 */ /* Caller is here responsible for sufficient locking (ie. inode->i_lock) */ void __inode_add_bytes(struct inode *inode, loff_t bytes) diff --git a/trunk/fs/super.c b/trunk/fs/super.c index 0902cfa6a12e..b05cf47463d0 100644 --- a/trunk/fs/super.c +++ b/trunk/fs/super.c @@ -536,6 +536,46 @@ void drop_super(struct super_block *sb) EXPORT_SYMBOL(drop_super); +/** + * sync_supers - helper for periodic superblock writeback + * + * Call the write_super method if present on all dirty superblocks in + * the system. This is for the periodic writeback used by most older + * filesystems. For data integrity superblock writeback use + * sync_filesystems() instead. + * + * Note: check the dirty flag before waiting, so we don't + * hold up the sync while mounting a device. (The newly + * mounted device won't need syncing.) + */ +void sync_supers(void) +{ + struct super_block *sb, *p = NULL; + + spin_lock(&sb_lock); + list_for_each_entry(sb, &super_blocks, s_list) { + if (hlist_unhashed(&sb->s_instances)) + continue; + if (sb->s_op->write_super && sb->s_dirt) { + sb->s_count++; + spin_unlock(&sb_lock); + + down_read(&sb->s_umount); + if (sb->s_root && sb->s_dirt && (sb->s_flags & MS_BORN)) + sb->s_op->write_super(sb); + up_read(&sb->s_umount); + + spin_lock(&sb_lock); + if (p) + __put_super(p); + p = sb; + } + } + if (p) + __put_super(p); + spin_unlock(&sb_lock); +} + /** * iterate_supers - call function for all active superblocks * @f: function to call diff --git a/trunk/fs/sysfs/symlink.c b/trunk/fs/sysfs/symlink.c index 3c9eb5624f5e..a7ac78f8e67a 100644 --- a/trunk/fs/sysfs/symlink.c +++ b/trunk/fs/sysfs/symlink.c @@ -113,7 +113,7 @@ int sysfs_create_link(struct kobject *kobj, struct kobject *target, * @target: object we're pointing to. * @name: name of the symlink. * - * This function does the same as sysfs_create_link(), but it + * This function does the same as sysf_create_link(), but it * doesn't warn if the link already exists. */ int sysfs_create_link_nowarn(struct kobject *kobj, struct kobject *target, diff --git a/trunk/fs/ubifs/debug.h b/trunk/fs/ubifs/debug.h index 760de723dadb..8b8cc4e945f4 100644 --- a/trunk/fs/ubifs/debug.h +++ b/trunk/fs/ubifs/debug.h @@ -167,7 +167,7 @@ struct ubifs_global_debug_info { #define ubifs_dbg_msg(type, fmt, ...) \ pr_debug("UBIFS DBG " type ": " fmt "\n", ##__VA_ARGS__) -#define DBG_KEY_BUF_LEN 48 +#define DBG_KEY_BUF_LEN 32 #define ubifs_dbg_msg_key(type, key, fmt, ...) do { \ char __tmp_key_buf[DBG_KEY_BUF_LEN]; \ pr_debug("UBIFS DBG " type ": " fmt "%s\n", ##__VA_ARGS__, \ diff --git a/trunk/fs/ubifs/file.c b/trunk/fs/ubifs/file.c index 7bd6e72afd11..35389ca2d267 100644 --- a/trunk/fs/ubifs/file.c +++ b/trunk/fs/ubifs/file.c @@ -37,11 +37,11 @@ * * A thing to keep in mind: inode @i_mutex is locked in most VFS operations we * implement. However, this is not true for 'ubifs_writepage()', which may be - * called with @i_mutex unlocked. For example, when flusher thread is doing - * background write-back, it calls 'ubifs_writepage()' with unlocked @i_mutex. - * At "normal" work-paths the @i_mutex is locked in 'ubifs_writepage()', e.g. - * in the "sys_write -> alloc_pages -> direct reclaim path". So, in - * 'ubifs_writepage()' we are only guaranteed that the page is locked. + * called with @i_mutex unlocked. For example, when pdflush is doing background + * write-back, it calls 'ubifs_writepage()' with unlocked @i_mutex. At "normal" + * work-paths the @i_mutex is locked in 'ubifs_writepage()', e.g. in the + * "sys_write -> alloc_pages -> direct reclaim path". So, in 'ubifs_writepage()' + * we are only guaranteed that the page is locked. * * Similarly, @i_mutex is not always locked in 'ubifs_readpage()', e.g., the * read-ahead path does not lock it ("sys_read -> generic_file_aio_read -> diff --git a/trunk/fs/ubifs/lpt.c b/trunk/fs/ubifs/lpt.c index 8640920766ed..ce33b2beb151 100644 --- a/trunk/fs/ubifs/lpt.c +++ b/trunk/fs/ubifs/lpt.c @@ -1749,10 +1749,7 @@ int ubifs_lpt_init(struct ubifs_info *c, int rd, int wr) return 0; out_err: - if (wr) - ubifs_lpt_free(c, 1); - if (rd) - ubifs_lpt_free(c, 0); + ubifs_lpt_free(c, 0); return err; } diff --git a/trunk/fs/ubifs/recovery.c b/trunk/fs/ubifs/recovery.c index edeec499c048..c30d976b4be8 100644 --- a/trunk/fs/ubifs/recovery.c +++ b/trunk/fs/ubifs/recovery.c @@ -788,7 +788,7 @@ struct ubifs_scan_leb *ubifs_recover_leb(struct ubifs_info *c, int lnum, corrupted_rescan: /* Re-scan the corrupted data with verbose messages */ - ubifs_err("corruption %d", ret); + ubifs_err("corruptio %d", ret); ubifs_scan_a_node(c, buf, len, lnum, offs, 1); corrupted: ubifs_scanned_corruption(c, lnum, offs, buf); diff --git a/trunk/fs/ubifs/replay.c b/trunk/fs/ubifs/replay.c index 94d78fc5d4e0..eba46d4a7619 100644 --- a/trunk/fs/ubifs/replay.c +++ b/trunk/fs/ubifs/replay.c @@ -1026,6 +1026,7 @@ int ubifs_replay_journal(struct ubifs_info *c) c->replaying = 1; lnum = c->ltail_lnum = c->lhead_lnum; + lnum = UBIFS_LOG_LNUM; do { err = replay_log_leb(c, lnum, 0, c->sbuf); if (err == 1) @@ -1034,7 +1035,7 @@ int ubifs_replay_journal(struct ubifs_info *c) if (err) goto out; lnum = ubifs_next_log_lnum(c, lnum); - } while (lnum != c->ltail_lnum); + } while (lnum != UBIFS_LOG_LNUM); err = replay_buds(c); if (err) diff --git a/trunk/fs/ubifs/super.c b/trunk/fs/ubifs/super.c index 71a197f0f93d..1c766c39c038 100644 --- a/trunk/fs/ubifs/super.c +++ b/trunk/fs/ubifs/super.c @@ -303,7 +303,7 @@ static int ubifs_write_inode(struct inode *inode, struct writeback_control *wbc) mutex_lock(&ui->ui_mutex); /* * Due to races between write-back forced by budgeting - * (see 'sync_some_inodes()') and background write-back, the inode may + * (see 'sync_some_inodes()') and pdflush write-back, the inode may * have already been synchronized, do not do this again. This might * also happen if it was synchronized in an VFS operation, e.g. * 'ubifs_link()'. @@ -1157,6 +1157,9 @@ static int check_free_space(struct ubifs_info *c) * * This function mounts UBIFS file system. Returns zero in case of success and * a negative error code in case of failure. + * + * Note, the function does not de-allocate resources it it fails half way + * through, and the caller has to do this instead. */ static int mount_ubifs(struct ubifs_info *c) { diff --git a/trunk/fs/udf/file.c b/trunk/fs/udf/file.c index d1c6093fd3d3..7f3f7ba3df6e 100644 --- a/trunk/fs/udf/file.c +++ b/trunk/fs/udf/file.c @@ -39,24 +39,20 @@ #include "udf_i.h" #include "udf_sb.h" -static void __udf_adinicb_readpage(struct page *page) +static int udf_adinicb_readpage(struct file *file, struct page *page) { struct inode *inode = page->mapping->host; char *kaddr; struct udf_inode_info *iinfo = UDF_I(inode); + BUG_ON(!PageLocked(page)); + kaddr = kmap(page); + memset(kaddr, 0, PAGE_CACHE_SIZE); memcpy(kaddr, iinfo->i_ext.i_data + iinfo->i_lenEAttr, inode->i_size); - memset(kaddr + inode->i_size, 0, PAGE_CACHE_SIZE - inode->i_size); flush_dcache_page(page); SetPageUptodate(page); kunmap(page); -} - -static int udf_adinicb_readpage(struct file *file, struct page *page) -{ - BUG_ON(!PageLocked(page)); - __udf_adinicb_readpage(page); unlock_page(page); return 0; @@ -81,25 +77,6 @@ static int udf_adinicb_writepage(struct page *page, return 0; } -static int udf_adinicb_write_begin(struct file *file, - struct address_space *mapping, loff_t pos, - unsigned len, unsigned flags, struct page **pagep, - void **fsdata) -{ - struct page *page; - - if (WARN_ON_ONCE(pos >= PAGE_CACHE_SIZE)) - return -EIO; - page = grab_cache_page_write_begin(mapping, 0, flags); - if (!page) - return -ENOMEM; - *pagep = page; - - if (!PageUptodate(page) && len != PAGE_CACHE_SIZE) - __udf_adinicb_readpage(page); - return 0; -} - static int udf_adinicb_write_end(struct file *file, struct address_space *mapping, loff_t pos, unsigned len, unsigned copied, @@ -121,8 +98,8 @@ static int udf_adinicb_write_end(struct file *file, const struct address_space_operations udf_adinicb_aops = { .readpage = udf_adinicb_readpage, .writepage = udf_adinicb_writepage, - .write_begin = udf_adinicb_write_begin, - .write_end = udf_adinicb_write_end, + .write_begin = simple_write_begin, + .write_end = udf_adinicb_write_end, }; static ssize_t udf_file_aio_write(struct kiocb *iocb, const struct iovec *iov, diff --git a/trunk/fs/udf/inode.c b/trunk/fs/udf/inode.c index aa233469b3c1..fafaad795cd6 100644 --- a/trunk/fs/udf/inode.c +++ b/trunk/fs/udf/inode.c @@ -1124,17 +1124,14 @@ int udf_setsize(struct inode *inode, loff_t newsize) if (err) return err; down_write(&iinfo->i_data_sem); - } else { + } else iinfo->i_lenAlloc = newsize; - goto set_size; - } } err = udf_extend_file(inode, newsize); if (err) { up_write(&iinfo->i_data_sem); return err; } -set_size: truncate_setsize(inode, newsize); up_write(&iinfo->i_data_sem); } else { diff --git a/trunk/fs/udf/super.c b/trunk/fs/udf/super.c index 18fc038a438d..dcbf98722afc 100644 --- a/trunk/fs/udf/super.c +++ b/trunk/fs/udf/super.c @@ -1344,7 +1344,6 @@ static int udf_load_logicalvol(struct super_block *sb, sector_t block, udf_err(sb, "error loading logical volume descriptor: " "Partition table too long (%u > %lu)\n", table_len, sb->s_blocksize - sizeof(*lvd)); - ret = 1; goto out_bh; } @@ -1389,10 +1388,8 @@ static int udf_load_logicalvol(struct super_block *sb, sector_t block, UDF_ID_SPARABLE, strlen(UDF_ID_SPARABLE))) { if (udf_load_sparable_map(sb, map, - (struct sparablePartitionMap *)gpm) < 0) { - ret = 1; + (struct sparablePartitionMap *)gpm) < 0) goto out_bh; - } } else if (!strncmp(upm2->partIdent.ident, UDF_ID_METADATA, strlen(UDF_ID_METADATA))) { @@ -2003,8 +2000,6 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent) if (!silent) pr_notice("Rescanning with blocksize %d\n", UDF_DEFAULT_BLOCKSIZE); - brelse(sbi->s_lvid_bh); - sbi->s_lvid_bh = NULL; uopt.blocksize = UDF_DEFAULT_BLOCKSIZE; ret = udf_load_vrs(sb, &uopt, silent, &fileset); } diff --git a/trunk/fs/xfs/xfs_buf.c b/trunk/fs/xfs/xfs_buf.c index 933b7930b863..d7a9dd735e1e 100644 --- a/trunk/fs/xfs/xfs_buf.c +++ b/trunk/fs/xfs/xfs_buf.c @@ -96,7 +96,6 @@ xfs_buf_lru_add( atomic_inc(&bp->b_hold); list_add_tail(&bp->b_lru, &btp->bt_lru); btp->bt_lru_nr++; - bp->b_lru_flags &= ~_XBF_LRU_DISPOSE; } spin_unlock(&btp->bt_lru_lock); } @@ -155,8 +154,7 @@ xfs_buf_stale( struct xfs_buftarg *btp = bp->b_target; spin_lock(&btp->bt_lru_lock); - if (!list_empty(&bp->b_lru) && - !(bp->b_lru_flags & _XBF_LRU_DISPOSE)) { + if (!list_empty(&bp->b_lru)) { list_del_init(&bp->b_lru); btp->bt_lru_nr--; atomic_dec(&bp->b_hold); @@ -1503,7 +1501,6 @@ xfs_buftarg_shrink( */ list_move(&bp->b_lru, &dispose); btp->bt_lru_nr--; - bp->b_lru_flags |= _XBF_LRU_DISPOSE; } spin_unlock(&btp->bt_lru_lock); diff --git a/trunk/fs/xfs/xfs_buf.h b/trunk/fs/xfs/xfs_buf.h index 7c0b6a0a1557..d03b73b9604e 100644 --- a/trunk/fs/xfs/xfs_buf.h +++ b/trunk/fs/xfs/xfs_buf.h @@ -38,28 +38,27 @@ typedef enum { XBRW_ZERO = 3, /* Zero target memory */ } xfs_buf_rw_t; -#define XBF_READ (1 << 0) /* buffer intended for reading from device */ -#define XBF_WRITE (1 << 1) /* buffer intended for writing to device */ -#define XBF_READ_AHEAD (1 << 2) /* asynchronous read-ahead */ -#define XBF_ASYNC (1 << 4) /* initiator will not wait for completion */ -#define XBF_DONE (1 << 5) /* all pages in the buffer uptodate */ -#define XBF_STALE (1 << 6) /* buffer has been staled, do not find it */ +#define XBF_READ (1 << 0) /* buffer intended for reading from device */ +#define XBF_WRITE (1 << 1) /* buffer intended for writing to device */ +#define XBF_READ_AHEAD (1 << 2) /* asynchronous read-ahead */ +#define XBF_ASYNC (1 << 4) /* initiator will not wait for completion */ +#define XBF_DONE (1 << 5) /* all pages in the buffer uptodate */ +#define XBF_STALE (1 << 6) /* buffer has been staled, do not find it */ /* I/O hints for the BIO layer */ -#define XBF_SYNCIO (1 << 10)/* treat this buffer as synchronous I/O */ -#define XBF_FUA (1 << 11)/* force cache write through mode */ -#define XBF_FLUSH (1 << 12)/* flush the disk cache before a write */ +#define XBF_SYNCIO (1 << 10)/* treat this buffer as synchronous I/O */ +#define XBF_FUA (1 << 11)/* force cache write through mode */ +#define XBF_FLUSH (1 << 12)/* flush the disk cache before a write */ /* flags used only as arguments to access routines */ -#define XBF_TRYLOCK (1 << 16)/* lock requested, but do not wait */ -#define XBF_UNMAPPED (1 << 17)/* do not map the buffer */ +#define XBF_TRYLOCK (1 << 16)/* lock requested, but do not wait */ +#define XBF_UNMAPPED (1 << 17)/* do not map the buffer */ /* flags used only internally */ -#define _XBF_PAGES (1 << 20)/* backed by refcounted pages */ -#define _XBF_KMEM (1 << 21)/* backed by heap memory */ -#define _XBF_DELWRI_Q (1 << 22)/* buffer on a delwri queue */ -#define _XBF_COMPOUND (1 << 23)/* compound buffer */ -#define _XBF_LRU_DISPOSE (1 << 24)/* buffer being discarded */ +#define _XBF_PAGES (1 << 20)/* backed by refcounted pages */ +#define _XBF_KMEM (1 << 21)/* backed by heap memory */ +#define _XBF_DELWRI_Q (1 << 22)/* buffer on a delwri queue */ +#define _XBF_COMPOUND (1 << 23)/* compound buffer */ typedef unsigned int xfs_buf_flags_t; @@ -73,13 +72,12 @@ typedef unsigned int xfs_buf_flags_t; { XBF_SYNCIO, "SYNCIO" }, \ { XBF_FUA, "FUA" }, \ { XBF_FLUSH, "FLUSH" }, \ - { XBF_TRYLOCK, "TRYLOCK" }, /* should never be set */\ + { XBF_TRYLOCK, "TRYLOCK" }, /* should never be set */\ { XBF_UNMAPPED, "UNMAPPED" }, /* ditto */\ { _XBF_PAGES, "PAGES" }, \ { _XBF_KMEM, "KMEM" }, \ { _XBF_DELWRI_Q, "DELWRI_Q" }, \ - { _XBF_COMPOUND, "COMPOUND" }, \ - { _XBF_LRU_DISPOSE, "LRU_DISPOSE" } + { _XBF_COMPOUND, "COMPOUND" } typedef struct xfs_buftarg { dev_t bt_dev; @@ -126,12 +124,7 @@ typedef struct xfs_buf { xfs_buf_flags_t b_flags; /* status flags */ struct semaphore b_sema; /* semaphore for lockables */ - /* - * concurrent access to b_lru and b_lru_flags are protected by - * bt_lru_lock and not by b_sema - */ struct list_head b_lru; /* lru list */ - xfs_buf_flags_t b_lru_flags; /* internal lru status flags */ wait_queue_head_t b_waiters; /* unpin waiters */ struct list_head b_list; struct xfs_perag *b_pag; /* contains rbtree root */ diff --git a/trunk/fs/xfs/xfs_discard.c b/trunk/fs/xfs/xfs_discard.c index 69cf4fcde03e..f9c3fe304a17 100644 --- a/trunk/fs/xfs/xfs_discard.c +++ b/trunk/fs/xfs/xfs_discard.c @@ -179,14 +179,12 @@ xfs_ioc_trim( * used by the fstrim application. In the end it really doesn't * matter as trimming blocks is an advisory interface. */ - if (range.start >= XFS_FSB_TO_B(mp, mp->m_sb.sb_dblocks) || - range.minlen > XFS_FSB_TO_B(mp, XFS_ALLOC_AG_MAX_USABLE(mp))) - return -XFS_ERROR(EINVAL); - start = BTOBB(range.start); end = start + BTOBBT(range.len) - 1; minlen = BTOBB(max_t(u64, granularity, range.minlen)); + if (XFS_BB_TO_FSB(mp, start) >= mp->m_sb.sb_dblocks) + return -XFS_ERROR(EINVAL); if (end > XFS_FSB_TO_BB(mp, mp->m_sb.sb_dblocks) - 1) end = XFS_FSB_TO_BB(mp, mp->m_sb.sb_dblocks)- 1; diff --git a/trunk/fs/xfs/xfs_ialloc.c b/trunk/fs/xfs/xfs_ialloc.c index 5aceb3f8ecd6..21e37b55f7e5 100644 --- a/trunk/fs/xfs/xfs_ialloc.c +++ b/trunk/fs/xfs/xfs_ialloc.c @@ -962,22 +962,23 @@ xfs_dialloc( if (!pag->pagi_freecount && !okalloc) goto nextag; - /* - * Then read in the AGI buffer and recheck with the AGI buffer - * lock held. - */ error = xfs_ialloc_read_agi(mp, tp, agno, &agbp); if (error) goto out_error; + /* + * Once the AGI has been read in we have to recheck + * pagi_freecount with the AGI buffer lock held. + */ if (pag->pagi_freecount) { xfs_perag_put(pag); goto out_alloc; } - if (!okalloc) - goto nextag_relse_buffer; - + if (!okalloc) { + xfs_trans_brelse(tp, agbp); + goto nextag; + } error = xfs_ialloc_ag_alloc(tp, agbp, &ialloced); if (error) { @@ -1006,8 +1007,6 @@ xfs_dialloc( return 0; } -nextag_relse_buffer: - xfs_trans_brelse(tp, agbp); nextag: xfs_perag_put(pag); if (++agno == mp->m_sb.sb_agcount) diff --git a/trunk/fs/xfs/xfs_rtalloc.c b/trunk/fs/xfs/xfs_rtalloc.c index ca28a4ba4b54..92d4331cd4f1 100644 --- a/trunk/fs/xfs/xfs_rtalloc.c +++ b/trunk/fs/xfs/xfs_rtalloc.c @@ -857,7 +857,7 @@ xfs_rtbuf_get( xfs_buf_t *bp; /* block buffer, result */ xfs_inode_t *ip; /* bitmap or summary inode */ xfs_bmbt_irec_t map; - int nmap = 1; + int nmap; int error; /* error value */ ip = issum ? mp->m_rsumip : mp->m_rbmip; diff --git a/trunk/fs/xfs/xfs_super.c b/trunk/fs/xfs/xfs_super.c index 19e2380fb867..bdaf4cb9f4a2 100644 --- a/trunk/fs/xfs/xfs_super.c +++ b/trunk/fs/xfs/xfs_super.c @@ -919,7 +919,6 @@ xfs_fs_put_super( struct xfs_mount *mp = XFS_M(sb); xfs_filestream_unmount(mp); - cancel_delayed_work_sync(&mp->m_sync_work); xfs_unmountfs(mp); xfs_syncd_stop(mp); xfs_freesb(mp); diff --git a/trunk/include/acpi/acpixf.h b/trunk/include/acpi/acpixf.h index 26a92fc28a59..2c744c7a5b3d 100644 --- a/trunk/include/acpi/acpixf.h +++ b/trunk/include/acpi/acpixf.h @@ -491,11 +491,11 @@ acpi_get_sleep_type_data(u8 sleep_state, u8 * slp_typ_a, u8 * slp_typ_b); acpi_status acpi_enter_sleep_state_prep(u8 sleep_state); -acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state); +acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state, u8 flags); ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status asmlinkage acpi_enter_sleep_state_s4bios(void)) -acpi_status acpi_leave_sleep_state_prep(u8 sleep_state); +acpi_status acpi_leave_sleep_state_prep(u8 sleep_state, u8 flags); acpi_status acpi_leave_sleep_state(u8 sleep_state); diff --git a/trunk/include/acpi/actypes.h b/trunk/include/acpi/actypes.h index 3d00bd5bd7e3..3af87de6a68c 100644 --- a/trunk/include/acpi/actypes.h +++ b/trunk/include/acpi/actypes.h @@ -803,7 +803,7 @@ typedef u8 acpi_adr_space_type; /* Sleep function dispatch */ -typedef acpi_status(*ACPI_SLEEP_FUNCTION) (u8 sleep_state); +typedef acpi_status(*ACPI_SLEEP_FUNCTION) (u8 sleep_state, u8 flags); struct acpi_sleep_functions { ACPI_SLEEP_FUNCTION legacy_function; diff --git a/trunk/include/asm-generic/bitops/builtin-__ffs.h b/trunk/include/asm-generic/bitops/builtin-__ffs.h deleted file mode 100644 index 90041e3a41f0..000000000000 --- a/trunk/include/asm-generic/bitops/builtin-__ffs.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef _ASM_GENERIC_BITOPS_BUILTIN___FFS_H_ -#define _ASM_GENERIC_BITOPS_BUILTIN___FFS_H_ - -/** - * __ffs - find first bit in word. - * @word: The word to search - * - * Undefined if no bit exists, so code should check against 0 first. - */ -static __always_inline unsigned long __ffs(unsigned long word) -{ - return __builtin_ctzl(word); -} - -#endif diff --git a/trunk/include/asm-generic/bitops/builtin-__fls.h b/trunk/include/asm-generic/bitops/builtin-__fls.h deleted file mode 100644 index 0248f386635f..000000000000 --- a/trunk/include/asm-generic/bitops/builtin-__fls.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef _ASM_GENERIC_BITOPS_BUILTIN___FLS_H_ -#define _ASM_GENERIC_BITOPS_BUILTIN___FLS_H_ - -/** - * __fls - find last (most-significant) set bit in a long word - * @word: the word to search - * - * Undefined if no set bit exists, so code should check against 0 first. - */ -static __always_inline unsigned long __fls(unsigned long word) -{ - return (sizeof(word) * 8) - 1 - __builtin_clzl(word); -} - -#endif diff --git a/trunk/include/asm-generic/bitops/builtin-ffs.h b/trunk/include/asm-generic/bitops/builtin-ffs.h deleted file mode 100644 index 064825829e1c..000000000000 --- a/trunk/include/asm-generic/bitops/builtin-ffs.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef _ASM_GENERIC_BITOPS_BUILTIN_FFS_H_ -#define _ASM_GENERIC_BITOPS_BUILTIN_FFS_H_ - -/** - * ffs - find first bit set - * @x: the word to search - * - * This is defined the same way as - * the libc and compiler builtin ffs routines, therefore - * differs in spirit from the above ffz (man ffs). - */ -static __always_inline int ffs(int x) -{ - return __builtin_ffs(x); -} - -#endif diff --git a/trunk/include/asm-generic/bitops/builtin-fls.h b/trunk/include/asm-generic/bitops/builtin-fls.h deleted file mode 100644 index eda652d0ac7f..000000000000 --- a/trunk/include/asm-generic/bitops/builtin-fls.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef _ASM_GENERIC_BITOPS_BUILTIN_FLS_H_ -#define _ASM_GENERIC_BITOPS_BUILTIN_FLS_H_ - -/** - * fls - find last (most-significant) bit set - * @x: the word to search - * - * This is defined the same way as ffs. - * Note fls(0) = 0, fls(1) = 1, fls(0x80000000) = 32. - */ -static __always_inline int fls(int x) -{ - return x ? sizeof(x) * 8 - __builtin_clz(x) : 0; -} - -#endif diff --git a/trunk/include/asm-generic/mutex-xchg.h b/trunk/include/asm-generic/mutex-xchg.h index c04e0db8a2d6..580a6d35c700 100644 --- a/trunk/include/asm-generic/mutex-xchg.h +++ b/trunk/include/asm-generic/mutex-xchg.h @@ -26,13 +26,7 @@ static inline void __mutex_fastpath_lock(atomic_t *count, void (*fail_fn)(atomic_t *)) { if (unlikely(atomic_xchg(count, 0) != 1)) - /* - * We failed to acquire the lock, so mark it contended - * to ensure that any waiting tasks are woken up by the - * unlock slow path. - */ - if (likely(atomic_xchg(count, -1) != 1)) - fail_fn(count); + fail_fn(count); } /** @@ -49,8 +43,7 @@ static inline int __mutex_fastpath_lock_retval(atomic_t *count, int (*fail_fn)(atomic_t *)) { if (unlikely(atomic_xchg(count, 0) != 1)) - if (likely(atomic_xchg(count, -1) != 1)) - return fail_fn(count); + return fail_fn(count); return 0; } diff --git a/trunk/include/asm-generic/unistd.h b/trunk/include/asm-generic/unistd.h index 3748ec92dcbc..991ef01cd77e 100644 --- a/trunk/include/asm-generic/unistd.h +++ b/trunk/include/asm-generic/unistd.h @@ -691,11 +691,9 @@ __SC_COMP(__NR_process_vm_readv, sys_process_vm_readv, \ #define __NR_process_vm_writev 271 __SC_COMP(__NR_process_vm_writev, sys_process_vm_writev, \ compat_sys_process_vm_writev) -#define __NR_kcmp 272 -__SYSCALL(__NR_kcmp, sys_kcmp) #undef __NR_syscalls -#define __NR_syscalls 273 +#define __NR_syscalls 272 /* * All syscalls below here should go away really, diff --git a/trunk/include/clocksource/arm_generic.h b/trunk/include/clocksource/arm_generic.h deleted file mode 100644 index 5b41b0d27f0f..000000000000 --- a/trunk/include/clocksource/arm_generic.h +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (C) 2012 ARM 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 __CLKSOURCE_ARM_GENERIC_H -#define __CLKSOURCE_ARM_GENERIC_H - -extern int arm_generic_timer_init(void); - -#endif diff --git a/trunk/include/drm/drm_crtc.h b/trunk/include/drm/drm_crtc.h index bfacf0d5a225..a1a0386e0160 100644 --- a/trunk/include/drm/drm_crtc.h +++ b/trunk/include/drm/drm_crtc.h @@ -118,8 +118,7 @@ enum drm_mode_status { .hdisplay = (hd), .hsync_start = (hss), .hsync_end = (hse), \ .htotal = (ht), .hskew = (hsk), .vdisplay = (vd), \ .vsync_start = (vss), .vsync_end = (vse), .vtotal = (vt), \ - .vscan = (vs), .flags = (f), .vrefresh = 0, \ - .base.type = DRM_MODE_OBJECT_MODE + .vscan = (vs), .flags = (f), .vrefresh = 0 #define CRTC_INTERLACE_HALVE_V 0x1 /* halve V values for interlacing */ @@ -167,6 +166,8 @@ struct drm_display_mode { int crtc_vsync_start; int crtc_vsync_end; int crtc_vtotal; + int crtc_hadjusted; + int crtc_vadjusted; /* Driver private mode info */ int private_size; diff --git a/trunk/include/drm/drm_fourcc.h b/trunk/include/drm/drm_fourcc.h index f4621184a9b4..bdf0152cbbe9 100644 --- a/trunk/include/drm/drm_fourcc.h +++ b/trunk/include/drm/drm_fourcc.h @@ -107,7 +107,8 @@ #define DRM_FORMAT_NV16 fourcc_code('N', 'V', '1', '6') /* 2x1 subsampled Cr:Cb plane */ #define DRM_FORMAT_NV61 fourcc_code('N', 'V', '6', '1') /* 2x1 subsampled Cb:Cr plane */ -/* special NV12 tiled format */ +/* 2 non contiguous plane YCbCr */ +#define DRM_FORMAT_NV12M fourcc_code('N', 'M', '1', '2') /* 2x2 subsampled Cr:Cb plane */ #define DRM_FORMAT_NV12MT fourcc_code('T', 'M', '1', '2') /* 2x2 subsampled Cr:Cb plane 64x32 macroblocks */ /* @@ -130,4 +131,7 @@ #define DRM_FORMAT_YUV444 fourcc_code('Y', 'U', '2', '4') /* non-subsampled Cb (1) and Cr (2) planes */ #define DRM_FORMAT_YVU444 fourcc_code('Y', 'V', '2', '4') /* non-subsampled Cr (1) and Cb (2) planes */ +/* 3 non contiguous plane YCbCr */ +#define DRM_FORMAT_YUV420M fourcc_code('Y', 'M', '1', '2') /* 2x2 subsampled Cb (1) and Cr (2) planes */ + #endif /* DRM_FOURCC_H */ diff --git a/trunk/include/drm/drm_mode.h b/trunk/include/drm/drm_mode.h index 3d6301b6ec16..5581980b14f6 100644 --- a/trunk/include/drm/drm_mode.h +++ b/trunk/include/drm/drm_mode.h @@ -359,9 +359,8 @@ struct drm_mode_mode_cmd { struct drm_mode_modeinfo mode; }; -#define DRM_MODE_CURSOR_BO 0x01 -#define DRM_MODE_CURSOR_MOVE 0x02 -#define DRM_MODE_CURSOR_FLAGS 0x03 +#define DRM_MODE_CURSOR_BO (1<<0) +#define DRM_MODE_CURSOR_MOVE (1<<1) /* * depending on the value in flags different members are used. diff --git a/trunk/include/drm/drm_pciids.h b/trunk/include/drm/drm_pciids.h index c78bb997e2c6..7ff5c99b1638 100644 --- a/trunk/include/drm/drm_pciids.h +++ b/trunk/include/drm/drm_pciids.h @@ -213,12 +213,9 @@ {0x1002, 0x6800, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6801, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6802, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ - {0x1002, 0x6806, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6808, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6809, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6810, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \ - {0x1002, 0x6816, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \ - {0x1002, 0x6817, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6818, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6819, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6820, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ diff --git a/trunk/include/drm/radeon_drm.h b/trunk/include/drm/radeon_drm.h index dc3a8cd7db8a..58056865b8e9 100644 --- a/trunk/include/drm/radeon_drm.h +++ b/trunk/include/drm/radeon_drm.h @@ -964,8 +964,6 @@ struct drm_radeon_cs { #define RADEON_INFO_IB_VM_MAX_SIZE 0x0f /* max pipes - needed for compute shaders */ #define RADEON_INFO_MAX_PIPES 0x10 -/* timestamp for GL_ARB_timer_query (OpenGL), returns the current GPU clock */ -#define RADEON_INFO_TIMESTAMP 0x11 struct drm_radeon_info { uint32_t request; diff --git a/trunk/include/linux/Kbuild b/trunk/include/linux/Kbuild index c57e064666e4..d9a754474878 100644 --- a/trunk/include/linux/Kbuild +++ b/trunk/include/linux/Kbuild @@ -84,6 +84,7 @@ header-y += capability.h header-y += capi.h header-y += cciss_defs.h header-y += cciss_ioctl.h +header-y += cdk.h header-y += cdrom.h header-y += cgroupstats.h header-y += chio.h @@ -92,6 +93,7 @@ header-y += cn_proc.h header-y += coda.h header-y += coda_psdev.h header-y += coff.h +header-y += comstats.h header-y += connector.h header-y += const.h header-y += cramfs_fs.h @@ -138,6 +140,7 @@ header-y += fuse.h header-y += futex.h header-y += gameport.h header-y += gen_stats.h +header-y += generic_serial.h header-y += genetlink.h header-y += gfs2_ondisk.h header-y += gigaset_dev.h @@ -369,7 +372,6 @@ header-y += tipc.h header-y += tipc_config.h header-y += toshiba.h header-y += tty.h -header-y += tty_flags.h header-y += types.h header-y += udf_fs_i.h header-y += udp.h @@ -389,7 +391,6 @@ header-y += v4l2-dv-timings.h header-y += v4l2-mediabus.h header-y += v4l2-subdev.h header-y += veth.h -header-y += vfio.h header-y += vhost.h header-y += videodev2.h header-y += virtio_9p.h diff --git a/trunk/include/linux/acpi.h b/trunk/include/linux/acpi.h index 90be98981102..3ad510b25283 100644 --- a/trunk/include/linux/acpi.h +++ b/trunk/include/linux/acpi.h @@ -96,7 +96,7 @@ void acpi_table_print_madt_entry (struct acpi_subtable_header *madt); void acpi_numa_slit_init (struct acpi_table_slit *slit); void acpi_numa_processor_affinity_init (struct acpi_srat_cpu_affinity *pa); void acpi_numa_x2apic_affinity_init(struct acpi_srat_x2apic_cpu_affinity *pa); -int acpi_numa_memory_affinity_init (struct acpi_srat_mem_affinity *ma); +void acpi_numa_memory_affinity_init (struct acpi_srat_mem_affinity *ma); void acpi_numa_arch_fixup(void); #ifdef CONFIG_ACPI_HOTPLUG_CPU @@ -138,9 +138,9 @@ void acpi_penalize_isa_irq(int irq, int active); void acpi_pci_irq_disable (struct pci_dev *dev); struct acpi_pci_driver { - struct list_head node; - int (*add)(struct acpi_pci_root *root); - void (*remove)(struct acpi_pci_root *root); + struct acpi_pci_driver *next; + int (*add)(acpi_handle handle); + void (*remove)(acpi_handle handle); }; int acpi_pci_register_driver(struct acpi_pci_driver *driver); diff --git a/trunk/include/linux/amba/serial.h b/trunk/include/linux/amba/serial.h index f612c783170f..d117b29d1062 100644 --- a/trunk/include/linux/amba/serial.h +++ b/trunk/include/linux/amba/serial.h @@ -205,6 +205,7 @@ struct amba_pl011_data { void *dma_tx_param; void (*init) (void); void (*exit) (void); + void (*reset) (void); }; #endif diff --git a/trunk/include/linux/atmel-ssc.h b/trunk/include/linux/atmel-ssc.h index 4eb31752e2b7..06023393fba9 100644 --- a/trunk/include/linux/atmel-ssc.h +++ b/trunk/include/linux/atmel-ssc.h @@ -3,7 +3,6 @@ #include #include -#include struct ssc_device { struct list_head list; diff --git a/trunk/include/linux/backing-dev.h b/trunk/include/linux/backing-dev.h index 2a9a9abc9126..c97c6b9cd38e 100644 --- a/trunk/include/linux/backing-dev.h +++ b/trunk/include/linux/backing-dev.h @@ -124,6 +124,7 @@ void bdi_start_writeback(struct backing_dev_info *bdi, long nr_pages, void bdi_start_background_writeback(struct backing_dev_info *bdi); int bdi_writeback_thread(void *data); int bdi_has_dirty_io(struct backing_dev_info *bdi); +void bdi_arm_supers_timer(void); void bdi_wakeup_thread_delayed(struct backing_dev_info *bdi); void bdi_lock_two(struct bdi_writeback *wb1, struct bdi_writeback *wb2); diff --git a/trunk/include/linux/bcma/bcma_driver_chipcommon.h b/trunk/include/linux/bcma/bcma_driver_chipcommon.h index d323a4b4143c..3c80885fa829 100644 --- a/trunk/include/linux/bcma/bcma_driver_chipcommon.h +++ b/trunk/include/linux/bcma/bcma_driver_chipcommon.h @@ -89,12 +89,6 @@ #define BCMA_CC_CHIPST_4313_OTP_PRESENT 2 #define BCMA_CC_CHIPST_4331_SPROM_PRESENT 2 #define BCMA_CC_CHIPST_4331_OTP_PRESENT 4 -#define BCMA_CC_CHIPST_43228_ILP_DIV_EN 0x00000001 -#define BCMA_CC_CHIPST_43228_OTP_PRESENT 0x00000002 -#define BCMA_CC_CHIPST_43228_SERDES_REFCLK_PADSEL 0x00000004 -#define BCMA_CC_CHIPST_43228_SDIO_MODE 0x00000008 -#define BCMA_CC_CHIPST_43228_SDIO_OTP_PRESENT 0x00000010 -#define BCMA_CC_CHIPST_43228_SDIO_RESET 0x00000020 #define BCMA_CC_CHIPST_4706_PKG_OPTION BIT(0) /* 0: full-featured package 1: low-cost package */ #define BCMA_CC_CHIPST_4706_SFLASH_PRESENT BIT(1) /* 0: parallel, 1: serial flash is present */ #define BCMA_CC_CHIPST_4706_SFLASH_TYPE BIT(2) /* 0: 8b-p/ST-s flash, 1: 16b-p/Atmal-s flash */ diff --git a/trunk/include/linux/blkdev.h b/trunk/include/linux/blkdev.h index 4a2ab7c85393..4e72a9d48232 100644 --- a/trunk/include/linux/blkdev.h +++ b/trunk/include/linux/blkdev.h @@ -601,7 +601,7 @@ static inline void blk_clear_rl_full(struct request_list *rl, bool sync) * it already be started by driver. */ #define RQ_NOMERGE_FLAGS \ - (REQ_NOMERGE | REQ_STARTED | REQ_SOFTBARRIER | REQ_FLUSH | REQ_FUA | REQ_DISCARD) + (REQ_NOMERGE | REQ_STARTED | REQ_SOFTBARRIER | REQ_FLUSH | REQ_FUA) #define rq_mergeable(rq) \ (!((rq)->cmd_flags & RQ_NOMERGE_FLAGS) && \ (((rq)->cmd_flags & REQ_DISCARD) || \ @@ -894,8 +894,6 @@ extern void blk_queue_flush_queueable(struct request_queue *q, bool queueable); extern struct backing_dev_info *blk_get_backing_dev_info(struct block_device *bdev); extern int blk_rq_map_sg(struct request_queue *, struct request *, struct scatterlist *); -extern int blk_bio_map_sg(struct request_queue *q, struct bio *bio, - struct scatterlist *sglist); extern void blk_dump_rq_flags(struct request *, char *); extern long nr_blockdev_pages(void); @@ -1141,16 +1139,6 @@ static inline int queue_limit_discard_alignment(struct queue_limits *lim, sector & (lim->discard_granularity - 1); } -static inline int bdev_discard_alignment(struct block_device *bdev) -{ - struct request_queue *q = bdev_get_queue(bdev); - - if (bdev != bdev->bd_contains) - return bdev->bd_part->discard_alignment; - - return q->limits.discard_alignment; -} - static inline unsigned int queue_discard_zeroes_data(struct request_queue *q) { if (q->limits.max_discard_sectors && q->limits.discard_zeroes_data == 1) diff --git a/trunk/include/linux/can.h b/trunk/include/linux/can.h index e52958d7c2d1..018055efc034 100644 --- a/trunk/include/linux/can.h +++ b/trunk/include/linux/can.h @@ -74,21 +74,20 @@ struct can_frame { /* * defined bits for canfd_frame.flags * - * The use of struct canfd_frame implies the Extended Data Length (EDL) bit to - * be set in the CAN frame bitstream on the wire. The EDL bit switch turns - * the CAN controllers bitstream processor into the CAN FD mode which creates - * two new options within the CAN FD frame specification: + * As the default for CAN FD should be to support the high data rate in the + * payload section of the frame (HDR) and to support up to 64 byte in the + * data section (EDL) the bits are only set in the non-default case. + * Btw. as long as there's no real implementation for CAN FD network driver + * these bits are only preliminary. * - * Bit Rate Switch - to indicate a second bitrate is/was used for the payload - * Error State Indicator - represents the error state of the transmitting node - * - * As the CANFD_ESI bit is internally generated by the transmitting CAN - * controller only the CANFD_BRS bit is relevant for real CAN controllers when - * building a CAN FD frame for transmission. Setting the CANFD_ESI bit can make - * sense for virtual CAN interfaces to test applications with echoed frames. + * RX: NOHDR/NOEDL - info about received CAN FD frame + * ESI - bit from originating CAN controller + * TX: NOHDR/NOEDL - control per-frame settings if supported by CAN controller + * ESI - bit is set by local CAN controller */ -#define CANFD_BRS 0x01 /* bit rate switch (second bitrate for payload data) */ -#define CANFD_ESI 0x02 /* error state indicator of the transmitting node */ +#define CANFD_NOHDR 0x01 /* frame without high data rate */ +#define CANFD_NOEDL 0x02 /* frame without extended data length */ +#define CANFD_ESI 0x04 /* error state indicator */ /** * struct canfd_frame - CAN flexible data rate frame structure diff --git a/trunk/include/linux/cd1400.h b/trunk/include/linux/cd1400.h new file mode 100644 index 000000000000..1dc3ab0523fd --- /dev/null +++ b/trunk/include/linux/cd1400.h @@ -0,0 +1,292 @@ +/*****************************************************************************/ + +/* + * cd1400.h -- cd1400 UART hardware info. + * + * Copyright (C) 1996-1998 Stallion Technologies + * Copyright (C) 1994-1996 Greg Ungerer. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/*****************************************************************************/ +#ifndef _CD1400_H +#define _CD1400_H +/*****************************************************************************/ + +/* + * Define the number of async ports per cd1400 uart chip. + */ +#define CD1400_PORTS 4 + +/* + * Define the cd1400 uarts internal FIFO sizes. + */ +#define CD1400_TXFIFOSIZE 12 +#define CD1400_RXFIFOSIZE 12 + +/* + * Local RX FIFO thresh hold level. Also define the RTS thresh hold + * based on the RX thresh hold. + */ +#define FIFO_RXTHRESHOLD 6 +#define FIFO_RTSTHRESHOLD 7 + +/*****************************************************************************/ + +/* + * Define the cd1400 register addresses. These are all the valid + * registers with the cd1400. Some are global, some virtual, some + * per port. + */ +#define GFRCR 0x40 +#define CAR 0x68 +#define GCR 0x4b +#define SVRR 0x67 +#define RICR 0x44 +#define TICR 0x45 +#define MICR 0x46 +#define RIR 0x6b +#define TIR 0x6a +#define MIR 0x69 +#define PPR 0x7e + +#define RIVR 0x43 +#define TIVR 0x42 +#define MIVR 0x41 +#define TDR 0x63 +#define RDSR 0x62 +#define MISR 0x4c +#define EOSRR 0x60 + +#define LIVR 0x18 +#define CCR 0x05 +#define SRER 0x06 +#define COR1 0x08 +#define COR2 0x09 +#define COR3 0x0a +#define COR4 0x1e +#define COR5 0x1f +#define CCSR 0x0b +#define RDCR 0x0e +#define SCHR1 0x1a +#define SCHR2 0x1b +#define SCHR3 0x1c +#define SCHR4 0x1d +#define SCRL 0x22 +#define SCRH 0x23 +#define LNC 0x24 +#define MCOR1 0x15 +#define MCOR2 0x16 +#define RTPR 0x21 +#define MSVR1 0x6c +#define MSVR2 0x6d +#define PSVR 0x6f +#define RBPR 0x78 +#define RCOR 0x7c +#define TBPR 0x72 +#define TCOR 0x76 + +/*****************************************************************************/ + +/* + * Define the set of baud rate clock divisors. + */ +#define CD1400_CLK0 8 +#define CD1400_CLK1 32 +#define CD1400_CLK2 128 +#define CD1400_CLK3 512 +#define CD1400_CLK4 2048 + +#define CD1400_NUMCLKS 5 + +/*****************************************************************************/ + +/* + * Define the clock pre-scalar value to be a 5 ms clock. This should be + * OK for now. It would probably be better to make it 10 ms, but we + * can't fit that divisor into 8 bits! + */ +#define PPR_SCALAR 244 + +/*****************************************************************************/ + +/* + * Define values used to set character size options. + */ +#define COR1_CHL5 0x00 +#define COR1_CHL6 0x01 +#define COR1_CHL7 0x02 +#define COR1_CHL8 0x03 + +/* + * Define values used to set the number of stop bits. + */ +#define COR1_STOP1 0x00 +#define COR1_STOP15 0x04 +#define COR1_STOP2 0x08 + +/* + * Define values used to set the parity scheme in use. + */ +#define COR1_PARNONE 0x00 +#define COR1_PARFORCE 0x20 +#define COR1_PARENB 0x40 +#define COR1_PARIGNORE 0x10 + +#define COR1_PARODD 0x80 +#define COR1_PAREVEN 0x00 + +#define COR2_IXM 0x80 +#define COR2_TXIBE 0x40 +#define COR2_ETC 0x20 +#define COR2_LLM 0x10 +#define COR2_RLM 0x08 +#define COR2_RTSAO 0x04 +#define COR2_CTSAE 0x02 + +#define COR3_SCDRNG 0x80 +#define COR3_SCD34 0x40 +#define COR3_FCT 0x20 +#define COR3_SCD12 0x10 + +/* + * Define values used by COR4. + */ +#define COR4_BRKINT 0x08 +#define COR4_IGNBRK 0x18 + +/*****************************************************************************/ + +/* + * Define the modem control register values. + * Note that the actual hardware is a little different to the conventional + * pin names on the cd1400. + */ +#define MSVR1_DTR 0x01 +#define MSVR1_DSR 0x10 +#define MSVR1_RI 0x20 +#define MSVR1_CTS 0x40 +#define MSVR1_DCD 0x80 + +#define MSVR2_RTS 0x02 +#define MSVR2_DSR 0x10 +#define MSVR2_RI 0x20 +#define MSVR2_CTS 0x40 +#define MSVR2_DCD 0x80 + +#define MCOR1_DCD 0x80 +#define MCOR1_CTS 0x40 +#define MCOR1_RI 0x20 +#define MCOR1_DSR 0x10 + +#define MCOR2_DCD 0x80 +#define MCOR2_CTS 0x40 +#define MCOR2_RI 0x20 +#define MCOR2_DSR 0x10 + +/*****************************************************************************/ + +/* + * Define the bits used with the service (interrupt) enable register. + */ +#define SRER_NNDT 0x01 +#define SRER_TXEMPTY 0x02 +#define SRER_TXDATA 0x04 +#define SRER_RXDATA 0x10 +#define SRER_MODEM 0x80 + +/*****************************************************************************/ + +/* + * Define operational commands for the command register. + */ +#define CCR_RESET 0x80 +#define CCR_CORCHANGE 0x4e +#define CCR_SENDCH 0x20 +#define CCR_CHANCTRL 0x10 + +#define CCR_TXENABLE (CCR_CHANCTRL | 0x08) +#define CCR_TXDISABLE (CCR_CHANCTRL | 0x04) +#define CCR_RXENABLE (CCR_CHANCTRL | 0x02) +#define CCR_RXDISABLE (CCR_CHANCTRL | 0x01) + +#define CCR_SENDSCHR1 (CCR_SENDCH | 0x01) +#define CCR_SENDSCHR2 (CCR_SENDCH | 0x02) +#define CCR_SENDSCHR3 (CCR_SENDCH | 0x03) +#define CCR_SENDSCHR4 (CCR_SENDCH | 0x04) + +#define CCR_RESETCHAN (CCR_RESET | 0x00) +#define CCR_RESETFULL (CCR_RESET | 0x01) +#define CCR_TXFLUSHFIFO (CCR_RESET | 0x02) + +#define CCR_MAXWAIT 10000 + +/*****************************************************************************/ + +/* + * Define the valid acknowledgement types (for hw ack cycle). + */ +#define ACK_TYPMASK 0x07 +#define ACK_TYPTX 0x02 +#define ACK_TYPMDM 0x01 +#define ACK_TYPRXGOOD 0x03 +#define ACK_TYPRXBAD 0x07 + +#define SVRR_RX 0x01 +#define SVRR_TX 0x02 +#define SVRR_MDM 0x04 + +#define ST_OVERRUN 0x01 +#define ST_FRAMING 0x02 +#define ST_PARITY 0x04 +#define ST_BREAK 0x08 +#define ST_SCHAR1 0x10 +#define ST_SCHAR2 0x20 +#define ST_SCHAR3 0x30 +#define ST_SCHAR4 0x40 +#define ST_RANGE 0x70 +#define ST_SCHARMASK 0x70 +#define ST_TIMEOUT 0x80 + +#define MISR_DCD 0x80 +#define MISR_CTS 0x40 +#define MISR_RI 0x20 +#define MISR_DSR 0x10 + +/*****************************************************************************/ + +/* + * Defines for the CCSR status register. + */ +#define CCSR_RXENABLED 0x80 +#define CCSR_RXFLOWON 0x40 +#define CCSR_RXFLOWOFF 0x20 +#define CCSR_TXENABLED 0x08 +#define CCSR_TXFLOWON 0x04 +#define CCSR_TXFLOWOFF 0x02 + +/*****************************************************************************/ + +/* + * Define the embedded commands. + */ +#define ETC_CMD 0x00 +#define ETC_STARTBREAK 0x81 +#define ETC_DELAY 0x82 +#define ETC_STOPBREAK 0x83 + +/*****************************************************************************/ +#endif diff --git a/trunk/include/linux/cdk.h b/trunk/include/linux/cdk.h new file mode 100644 index 000000000000..80093a8d4f64 --- /dev/null +++ b/trunk/include/linux/cdk.h @@ -0,0 +1,486 @@ +/*****************************************************************************/ + +/* + * cdk.h -- CDK interface definitions. + * + * Copyright (C) 1996-1998 Stallion Technologies + * Copyright (C) 1994-1996 Greg Ungerer. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/*****************************************************************************/ +#ifndef _CDK_H +#define _CDK_H +/*****************************************************************************/ + +#pragma pack(2) + +/* + * The following set of definitions is used to communicate with the + * shared memory interface of the Stallion intelligent multiport serial + * boards. The definitions in this file are taken directly from the + * document titled "Generic Stackable Interface, Downloader and + * Communications Development Kit". + */ + +/* + * Define the set of important shared memory addresses. These are + * required to initialize the board and get things started. All of these + * addresses are relative to the start of the shared memory. + */ +#define CDK_SIGADDR 0x200 +#define CDK_FEATADDR 0x280 +#define CDK_CDKADDR 0x300 +#define CDK_RDYADDR 0x262 + +#define CDK_ALIVEMARKER 13 + +/* + * On hardware power up the ROMs located on the EasyConnection 8/64 will + * fill out the following signature information into shared memory. This + * way the host system can quickly determine that the board is present + * and is operational. + */ +typedef struct cdkecpsig { + unsigned long magic; + unsigned short romver; + unsigned short cputype; + unsigned char panelid[8]; +} cdkecpsig_t; + +#define ECP_MAGIC 0x21504345 + +/* + * On hardware power up the ROMs located on the ONboard, Stallion and + * Brumbys will fill out the following signature information into shared + * memory. This way the host system can quickly determine that the board + * is present and is operational. + */ +typedef struct cdkonbsig { + unsigned short magic0; + unsigned short magic1; + unsigned short magic2; + unsigned short magic3; + unsigned short romver; + unsigned short memoff; + unsigned short memseg; + unsigned short amask0; + unsigned short pic; + unsigned short status; + unsigned short btype; + unsigned short clkticks; + unsigned short clkspeed; + unsigned short amask1; + unsigned short amask2; +} cdkonbsig_t; + +#define ONB_MAGIC0 0xf2a7 +#define ONB_MAGIC1 0xa149 +#define ONB_MAGIC2 0x6352 +#define ONB_MAGIC3 0xf121 + +/* + * Define the feature area structure. The feature area is the set of + * startup parameters used by the slave image when it starts executing. + * They allow for the specification of buffer sizes, debug trace, etc. + */ +typedef struct cdkfeature { + unsigned long debug; + unsigned long banner; + unsigned long etype; + unsigned long nrdevs; + unsigned long brdspec; + unsigned long txrqsize; + unsigned long rxrqsize; + unsigned long flags; +} cdkfeature_t; + +#define ETYP_DDK 0 +#define ETYP_CDK 1 + +/* + * Define the CDK header structure. This is the info that the slave + * environment sets up after it has been downloaded and started. It + * essentially provides a memory map for the shared memory interface. + */ +typedef struct cdkhdr { + unsigned short command; + unsigned short status; + unsigned short port; + unsigned short mode; + unsigned long cmd_buf[14]; + unsigned short alive_cnt; + unsigned short intrpt_mode; + unsigned char intrpt_id[8]; + unsigned char ver_release; + unsigned char ver_modification; + unsigned char ver_fix; + unsigned char deadman_restart; + unsigned short deadman; + unsigned short nrdevs; + unsigned long memp; + unsigned long hostp; + unsigned long slavep; + unsigned char hostreq; + unsigned char slavereq; + unsigned char cmd_reserved[30]; +} cdkhdr_t; + +#define MODE_DDK 0 +#define MODE_CDK 1 + +#define IMD_INTR 0x0 +#define IMD_PPINTR 0x1 +#define IMD_POLL 0xff + +/* + * Define the memory mapping structure. This structure is pointed to by + * the memp field in the stlcdkhdr struct. As many as these structures + * as required are laid out in shared memory to define how the rest of + * shared memory is divided up. There will be one for each port. + */ +typedef struct cdkmem { + unsigned short dtype; + unsigned long offset; +} cdkmem_t; + +#define TYP_UNDEFINED 0x0 +#define TYP_ASYNCTRL 0x1 +#define TYP_ASYNC 0x20 +#define TYP_PARALLEL 0x40 +#define TYP_SYNCX21 0x60 + +/*****************************************************************************/ + +/* + * Following is a set of defines and structures used to actually deal + * with the serial ports on the board. Firstly is the set of commands + * that can be applied to ports. + */ +#define ASYCMD (((unsigned long) 'a') << 8) + +#define A_NULL (ASYCMD | 0) +#define A_FLUSH (ASYCMD | 1) +#define A_BREAK (ASYCMD | 2) +#define A_GETPORT (ASYCMD | 3) +#define A_SETPORT (ASYCMD | 4) +#define A_SETPORTF (ASYCMD | 5) +#define A_SETPORTFTX (ASYCMD | 6) +#define A_SETPORTFRX (ASYCMD | 7) +#define A_GETSIGNALS (ASYCMD | 8) +#define A_SETSIGNALS (ASYCMD | 9) +#define A_SETSIGNALSF (ASYCMD | 10) +#define A_SETSIGNALSFTX (ASYCMD | 11) +#define A_SETSIGNALSFRX (ASYCMD | 12) +#define A_GETNOTIFY (ASYCMD | 13) +#define A_SETNOTIFY (ASYCMD | 14) +#define A_NOTIFY (ASYCMD | 15) +#define A_PORTCTRL (ASYCMD | 16) +#define A_GETSTATS (ASYCMD | 17) +#define A_RQSTATE (ASYCMD | 18) +#define A_FLOWSTATE (ASYCMD | 19) +#define A_CLEARSTATS (ASYCMD | 20) + +/* + * Define those arguments used for simple commands. + */ +#define FLUSHRX 0x1 +#define FLUSHTX 0x2 + +#define BREAKON -1 +#define BREAKOFF -2 + +/* + * Define the port setting structure, and all those defines that go along + * with it. Basically this structure defines the characteristics of this + * port: baud rate, chars, parity, input/output char cooking etc. + */ +typedef struct asyport { + unsigned long baudout; + unsigned long baudin; + unsigned long iflag; + unsigned long oflag; + unsigned long lflag; + unsigned long pflag; + unsigned long flow; + unsigned long spare1; + unsigned short vtime; + unsigned short vmin; + unsigned short txlo; + unsigned short txhi; + unsigned short rxlo; + unsigned short rxhi; + unsigned short rxhog; + unsigned short spare2; + unsigned char csize; + unsigned char stopbs; + unsigned char parity; + unsigned char stopin; + unsigned char startin; + unsigned char stopout; + unsigned char startout; + unsigned char parmark; + unsigned char brkmark; + unsigned char cc[11]; +} asyport_t; + +#define PT_STOP1 0x0 +#define PT_STOP15 0x1 +#define PT_STOP2 0x2 + +#define PT_NOPARITY 0x0 +#define PT_ODDPARITY 0x1 +#define PT_EVENPARITY 0x2 +#define PT_MARKPARITY 0x3 +#define PT_SPACEPARITY 0x4 + +#define F_NONE 0x0 +#define F_IXON 0x1 +#define F_IXOFF 0x2 +#define F_IXANY 0x4 +#define F_IOXANY 0x8 +#define F_RTSFLOW 0x10 +#define F_CTSFLOW 0x20 +#define F_DTRFLOW 0x40 +#define F_DCDFLOW 0x80 +#define F_DSROFLOW 0x100 +#define F_DSRIFLOW 0x200 + +#define FI_NORX 0x1 +#define FI_RAW 0x2 +#define FI_ISTRIP 0x4 +#define FI_UCLC 0x8 +#define FI_INLCR 0x10 +#define FI_ICRNL 0x20 +#define FI_IGNCR 0x40 +#define FI_IGNBREAK 0x80 +#define FI_DSCRDBREAK 0x100 +#define FI_1MARKBREAK 0x200 +#define FI_2MARKBREAK 0x400 +#define FI_XCHNGBREAK 0x800 +#define FI_IGNRXERRS 0x1000 +#define FI_DSCDRXERRS 0x2000 +#define FI_1MARKRXERRS 0x4000 +#define FI_2MARKRXERRS 0x8000 +#define FI_XCHNGRXERRS 0x10000 +#define FI_DSCRDNULL 0x20000 + +#define FO_OLCUC 0x1 +#define FO_ONLCR 0x2 +#define FO_OOCRNL 0x4 +#define FO_ONOCR 0x8 +#define FO_ONLRET 0x10 +#define FO_ONL 0x20 +#define FO_OBS 0x40 +#define FO_OVT 0x80 +#define FO_OFF 0x100 +#define FO_OTAB1 0x200 +#define FO_OTAB2 0x400 +#define FO_OTAB3 0x800 +#define FO_OCR1 0x1000 +#define FO_OCR2 0x2000 +#define FO_OCR3 0x4000 +#define FO_OFILL 0x8000 +#define FO_ODELL 0x10000 + +#define P_RTSLOCK 0x1 +#define P_CTSLOCK 0x2 +#define P_MAPRTS 0x4 +#define P_MAPCTS 0x8 +#define P_LOOPBACK 0x10 +#define P_DTRFOLLOW 0x20 +#define P_FAKEDCD 0x40 + +#define P_RXIMIN 0x10000 +#define P_RXITIME 0x20000 +#define P_RXTHOLD 0x40000 + +/* + * Define a structure to communicate serial port signal and data state + * information. + */ +typedef struct asysigs { + unsigned long data; + unsigned long signal; + unsigned long sigvalue; +} asysigs_t; + +#define DT_TXBUSY 0x1 +#define DT_TXEMPTY 0x2 +#define DT_TXLOW 0x4 +#define DT_TXHIGH 0x8 +#define DT_TXFULL 0x10 +#define DT_TXHOG 0x20 +#define DT_TXFLOWED 0x40 +#define DT_TXBREAK 0x80 + +#define DT_RXBUSY 0x100 +#define DT_RXEMPTY 0x200 +#define DT_RXLOW 0x400 +#define DT_RXHIGH 0x800 +#define DT_RXFULL 0x1000 +#define DT_RXHOG 0x2000 +#define DT_RXFLOWED 0x4000 +#define DT_RXBREAK 0x8000 + +#define SG_DTR 0x1 +#define SG_DCD 0x2 +#define SG_RTS 0x4 +#define SG_CTS 0x8 +#define SG_DSR 0x10 +#define SG_RI 0x20 + +/* + * Define the notification setting structure. This is used to tell the + * port what events we want to be informed about. Fields here use the + * same defines as for the asysigs structure above. + */ +typedef struct asynotify { + unsigned long ctrl; + unsigned long data; + unsigned long signal; + unsigned long sigvalue; +} asynotify_t; + +/* + * Define the port control structure. It is used to do fine grain + * control operations on the port. + */ +typedef struct { + unsigned long rxctrl; + unsigned long txctrl; + char rximdch; + char tximdch; + char spare1; + char spare2; +} asyctrl_t; + +#define CT_ENABLE 0x1 +#define CT_DISABLE 0x2 +#define CT_STOP 0x4 +#define CT_START 0x8 +#define CT_STARTFLOW 0x10 +#define CT_STOPFLOW 0x20 +#define CT_SENDCHR 0x40 + +/* + * Define the stats structure kept for each port. This is a useful set + * of data collected for each port on the slave. The A_GETSTATS command + * is used to retrieve this data from the slave. + */ +typedef struct asystats { + unsigned long opens; + unsigned long txchars; + unsigned long rxchars; + unsigned long txringq; + unsigned long rxringq; + unsigned long txmsgs; + unsigned long rxmsgs; + unsigned long txflushes; + unsigned long rxflushes; + unsigned long overruns; + unsigned long framing; + unsigned long parity; + unsigned long ringover; + unsigned long lost; + unsigned long rxstart; + unsigned long rxstop; + unsigned long txstart; + unsigned long txstop; + unsigned long dcdcnt; + unsigned long dtrcnt; + unsigned long ctscnt; + unsigned long rtscnt; + unsigned long dsrcnt; + unsigned long ricnt; + unsigned long txbreaks; + unsigned long rxbreaks; + unsigned long signals; + unsigned long state; + unsigned long hwid; +} asystats_t; + +/*****************************************************************************/ + +/* + * All command and control communication with a device on the slave is + * via a control block in shared memory. Each device has its own control + * block, defined by the following structure. The control block allows + * the host to open, close and control the device on the slave. + */ +typedef struct cdkctrl { + unsigned char open; + unsigned char close; + unsigned long openarg; + unsigned long closearg; + unsigned long cmd; + unsigned long status; + unsigned long args[32]; +} cdkctrl_t; + +/* + * Each device on the slave passes data to and from the host via a ring + * queue in shared memory. Define a ring queue structure to hold the + * vital information about each ring queue. Two ring queues will be + * allocated for each port, one for receive data and one for transmit + * data. + */ +typedef struct cdkasyrq { + unsigned long offset; + unsigned short size; + unsigned short head; + unsigned short tail; +} cdkasyrq_t; + +/* + * Each asynchronous port is defined in shared memory by the following + * structure. It contains a control block to command a device, and also + * the necessary data channel information as well. + */ +typedef struct cdkasy { + cdkctrl_t ctrl; + unsigned short notify; + asynotify_t changed; + unsigned short receive; + cdkasyrq_t rxq; + unsigned short transmit; + cdkasyrq_t txq; +} cdkasy_t; + +#pragma pack() + +/*****************************************************************************/ + +/* + * Define the set of ioctls used by the driver to do special things + * to the board. These include interrupting it, and initializing + * the driver after board startup and shutdown. + */ +#include + +#define STL_BINTR _IO('s',20) +#define STL_BSTART _IO('s',21) +#define STL_BSTOP _IO('s',22) +#define STL_BRESET _IO('s',23) + +/* + * Define a set of ioctl extensions, used to get at special stuff. + */ +#define STL_GETPFLAG _IO('s',80) +#define STL_SETPFLAG _IO('s',81) + +/*****************************************************************************/ +#endif diff --git a/trunk/include/linux/clk-provider.h b/trunk/include/linux/clk-provider.h index c12731582920..77335fac943e 100644 --- a/trunk/include/linux/clk-provider.h +++ b/trunk/include/linux/clk-provider.h @@ -26,7 +26,6 @@ #define CLK_IGNORE_UNUSED BIT(3) /* do not gate even if unused */ #define CLK_IS_ROOT BIT(4) /* root clk, has no parent */ #define CLK_IS_BASIC BIT(5) /* Basic clk, can't do a to_clk_foo() */ -#define CLK_GET_RATE_NOCACHE BIT(6) /* do not use the cached clk rate */ struct clk_hw; @@ -361,11 +360,6 @@ int of_clk_add_provider(struct device_node *np, void of_clk_del_provider(struct device_node *np); struct clk *of_clk_src_simple_get(struct of_phandle_args *clkspec, void *data); -struct clk_onecell_data { - struct clk **clks; - unsigned int clk_num; -}; -struct clk *of_clk_src_onecell_get(struct of_phandle_args *clkspec, void *data); const char *of_clk_get_parent_name(struct device_node *np, int index); void of_clk_init(const struct of_device_id *matches); diff --git a/trunk/include/linux/compaction.h b/trunk/include/linux/compaction.h index ef658147e4e8..133ddcf83397 100644 --- a/trunk/include/linux/compaction.h +++ b/trunk/include/linux/compaction.h @@ -22,7 +22,7 @@ extern int sysctl_extfrag_handler(struct ctl_table *table, int write, extern int fragmentation_index(struct zone *zone, unsigned int order); extern unsigned long try_to_compact_pages(struct zonelist *zonelist, int order, gfp_t gfp_mask, nodemask_t *mask, - bool sync, bool *contended); + bool sync); extern int compact_pgdat(pg_data_t *pgdat, int order); extern unsigned long compaction_suitable(struct zone *zone, int order); @@ -64,7 +64,7 @@ static inline bool compaction_deferred(struct zone *zone, int order) #else static inline unsigned long try_to_compact_pages(struct zonelist *zonelist, int order, gfp_t gfp_mask, nodemask_t *nodemask, - bool sync, bool *contended) + bool sync) { return COMPACT_CONTINUE; } diff --git a/trunk/include/linux/compiler-gcc4.h b/trunk/include/linux/compiler-gcc4.h index 934bc34d5f99..2f4079175afb 100644 --- a/trunk/include/linux/compiler-gcc4.h +++ b/trunk/include/linux/compiler-gcc4.h @@ -49,13 +49,6 @@ #endif #endif -#if __GNUC_MINOR__ >= 6 -/* - * Tell the optimizer that something else uses this function or variable. - */ -#define __visible __attribute__((externally_visible)) -#endif - #if __GNUC_MINOR__ > 0 #define __compiletime_object_size(obj) __builtin_object_size(obj, 0) #endif diff --git a/trunk/include/linux/compiler.h b/trunk/include/linux/compiler.h index f430e4162f41..923d093c9cea 100644 --- a/trunk/include/linux/compiler.h +++ b/trunk/include/linux/compiler.h @@ -278,10 +278,6 @@ void ftrace_likely_update(struct ftrace_branch_data *f, int val, int expect); # define __section(S) __attribute__ ((__section__(#S))) #endif -#ifndef __visible -#define __visible -#endif - /* Are two types/vars the same type (ignoring qualifiers)? */ #ifndef __same_type # define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b)) diff --git a/trunk/include/linux/comstats.h b/trunk/include/linux/comstats.h new file mode 100644 index 000000000000..3f5ea8e8026d --- /dev/null +++ b/trunk/include/linux/comstats.h @@ -0,0 +1,119 @@ +/*****************************************************************************/ + +/* + * comstats.h -- Serial Port Stats. + * + * Copyright (C) 1996-1998 Stallion Technologies + * Copyright (C) 1994-1996 Greg Ungerer. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/*****************************************************************************/ +#ifndef _COMSTATS_H +#define _COMSTATS_H +/*****************************************************************************/ + +/* + * Serial port stats structure. The structure itself is UART + * independent, but some fields may be UART/driver specific (for + * example state). + */ + +typedef struct { + unsigned long brd; + unsigned long panel; + unsigned long port; + unsigned long hwid; + unsigned long type; + unsigned long txtotal; + unsigned long rxtotal; + unsigned long txbuffered; + unsigned long rxbuffered; + unsigned long rxoverrun; + unsigned long rxparity; + unsigned long rxframing; + unsigned long rxlost; + unsigned long txbreaks; + unsigned long rxbreaks; + unsigned long txxon; + unsigned long txxoff; + unsigned long rxxon; + unsigned long rxxoff; + unsigned long txctson; + unsigned long txctsoff; + unsigned long rxrtson; + unsigned long rxrtsoff; + unsigned long modem; + unsigned long state; + unsigned long flags; + unsigned long ttystate; + unsigned long cflags; + unsigned long iflags; + unsigned long oflags; + unsigned long lflags; + unsigned long signals; +} comstats_t; + + +/* + * Board stats structure. Returns useful info about the board. + */ + +#define COM_MAXPANELS 8 + +typedef struct { + unsigned long panel; + unsigned long type; + unsigned long hwid; + unsigned long nrports; +} companel_t; + +typedef struct { + unsigned long brd; + unsigned long type; + unsigned long hwid; + unsigned long state; + unsigned long ioaddr; + unsigned long ioaddr2; + unsigned long memaddr; + unsigned long irq; + unsigned long nrpanels; + unsigned long nrports; + companel_t panels[COM_MAXPANELS]; +} combrd_t; + + +/* + * Define the ioctl operations for stats stuff. + */ +#include + +#define COM_GETPORTSTATS _IO('c',30) +#define COM_CLRPORTSTATS _IO('c',31) +#define COM_GETBRDSTATS _IO('c',32) + + +/* + * Define the set of ioctls that give user level access to the + * private port, panel and board structures. The argument required + * will be driver dependent! + */ +#define COM_READPORT _IO('c',40) +#define COM_READBOARD _IO('c',41) +#define COM_READPANEL _IO('c',42) + +/*****************************************************************************/ +#endif diff --git a/trunk/include/linux/cpuidle.h b/trunk/include/linux/cpuidle.h index 279b1eaa8b73..040b13b5c14a 100644 --- a/trunk/include/linux/cpuidle.h +++ b/trunk/include/linux/cpuidle.h @@ -194,10 +194,6 @@ static inline int cpuidle_play_dead(void) {return -ENODEV; } #ifdef CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED void cpuidle_coupled_parallel_barrier(struct cpuidle_device *dev, atomic_t *a); -#else -static inline void cpuidle_coupled_parallel_barrier(struct cpuidle_device *dev, atomic_t *a) -{ -} #endif /****************************** diff --git a/trunk/include/linux/dcache.h b/trunk/include/linux/dcache.h index 59200795482e..caa34e50537e 100644 --- a/trunk/include/linux/dcache.h +++ b/trunk/include/linux/dcache.h @@ -206,8 +206,6 @@ struct dentry_operations { #define DCACHE_MANAGED_DENTRY \ (DCACHE_MOUNTED|DCACHE_NEED_AUTOMOUNT|DCACHE_MANAGE_TRANSIT) -#define DCACHE_DENTRY_KILLED 0x100000 - extern seqlock_t rename_lock; static inline int dname_external(struct dentry *dentry) diff --git a/trunk/include/linux/device.h b/trunk/include/linux/device.h index af92883bb4a6..52a5f15a2223 100644 --- a/trunk/include/linux/device.h +++ b/trunk/include/linux/device.h @@ -536,10 +536,6 @@ extern void *__devres_alloc(dr_release_t release, size_t size, gfp_t gfp, #else extern void *devres_alloc(dr_release_t release, size_t size, gfp_t gfp); #endif -extern void devres_for_each_res(struct device *dev, dr_release_t release, - dr_match_t match, void *match_data, - void (*fn)(struct device *, void *, void *), - void *data); extern void devres_free(void *res); extern void devres_add(struct device *dev, void *res); extern void *devres_find(struct device *dev, dr_release_t release, @@ -895,15 +891,12 @@ extern const char *dev_driver_string(const struct device *dev); #ifdef CONFIG_PRINTK -extern __printf(3, 0) -int dev_vprintk_emit(int level, const struct device *dev, - const char *fmt, va_list args); -extern __printf(3, 4) -int dev_printk_emit(int level, const struct device *dev, const char *fmt, ...); - +extern int __dev_printk(const char *level, const struct device *dev, + struct va_format *vaf); extern __printf(3, 4) int dev_printk(const char *level, const struct device *dev, - const char *fmt, ...); + const char *fmt, ...) + ; extern __printf(2, 3) int dev_emerg(const struct device *dev, const char *fmt, ...); extern __printf(2, 3) @@ -921,14 +914,6 @@ int _dev_info(const struct device *dev, const char *fmt, ...); #else -static inline __printf(3, 0) -int dev_vprintk_emit(int level, const struct device *dev, - const char *fmt, va_list args) -{ return 0; } -static inline __printf(3, 4) -int dev_printk_emit(int level, const struct device *dev, const char *fmt, ...) -{ return 0; } - static inline int __dev_printk(const char *level, const struct device *dev, struct va_format *vaf) { return 0; } @@ -961,32 +946,6 @@ int _dev_info(const struct device *dev, const char *fmt, ...) #endif -/* - * Stupid hackaround for existing uses of non-printk uses dev_info - * - * Note that the definition of dev_info below is actually _dev_info - * and a macro is used to avoid redefining dev_info - */ - -#define dev_info(dev, fmt, arg...) _dev_info(dev, fmt, ##arg) - -#if defined(CONFIG_DYNAMIC_DEBUG) -#define dev_dbg(dev, format, ...) \ -do { \ - dynamic_dev_dbg(dev, format, ##__VA_ARGS__); \ -} while (0) -#elif defined(DEBUG) -#define dev_dbg(dev, format, arg...) \ - dev_printk(KERN_DEBUG, dev, format, ##arg) -#else -#define dev_dbg(dev, format, arg...) \ -({ \ - if (0) \ - dev_printk(KERN_DEBUG, dev, format, ##arg); \ - 0; \ -}) -#endif - #define dev_level_ratelimited(dev_level, dev, fmt, ...) \ do { \ static DEFINE_RATELIMIT_STATE(_rs, \ @@ -1010,21 +969,33 @@ do { \ dev_level_ratelimited(dev_notice, dev, fmt, ##__VA_ARGS__) #define dev_info_ratelimited(dev, fmt, ...) \ dev_level_ratelimited(dev_info, dev, fmt, ##__VA_ARGS__) -#if defined(CONFIG_DYNAMIC_DEBUG) || defined(DEBUG) #define dev_dbg_ratelimited(dev, fmt, ...) \ -do { \ - static DEFINE_RATELIMIT_STATE(_rs, \ - DEFAULT_RATELIMIT_INTERVAL, \ - DEFAULT_RATELIMIT_BURST); \ - DEFINE_DYNAMIC_DEBUG_METADATA(descriptor, fmt); \ - if (unlikely(descriptor.flags & _DPRINTK_FLAGS_PRINT) && \ - __ratelimit(&_rs)) \ - __dynamic_pr_debug(&descriptor, pr_fmt(fmt), \ - ##__VA_ARGS__); \ + dev_level_ratelimited(dev_dbg, dev, fmt, ##__VA_ARGS__) + +/* + * Stupid hackaround for existing uses of non-printk uses dev_info + * + * Note that the definition of dev_info below is actually _dev_info + * and a macro is used to avoid redefining dev_info + */ + +#define dev_info(dev, fmt, arg...) _dev_info(dev, fmt, ##arg) + +#if defined(CONFIG_DYNAMIC_DEBUG) +#define dev_dbg(dev, format, ...) \ +do { \ + dynamic_dev_dbg(dev, format, ##__VA_ARGS__); \ } while (0) +#elif defined(DEBUG) +#define dev_dbg(dev, format, arg...) \ + dev_printk(KERN_DEBUG, dev, format, ##arg) #else -#define dev_dbg_ratelimited(dev, fmt, ...) \ - no_printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__) +#define dev_dbg(dev, format, arg...) \ +({ \ + if (0) \ + dev_printk(KERN_DEBUG, dev, format, ##arg); \ + 0; \ +}) #endif #ifdef VERBOSE_DEBUG diff --git a/trunk/include/linux/efi-bgrt.h b/trunk/include/linux/efi-bgrt.h deleted file mode 100644 index 051b21fedf68..000000000000 --- a/trunk/include/linux/efi-bgrt.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef _LINUX_EFI_BGRT_H -#define _LINUX_EFI_BGRT_H - -#ifdef CONFIG_ACPI_BGRT - -#include - -void efi_bgrt_init(void); - -/* The BGRT data itself; only valid if bgrt_image != NULL. */ -extern void *bgrt_image; -extern size_t bgrt_image_size; -extern struct acpi_table_bgrt *bgrt_tab; - -#else /* !CONFIG_ACPI_BGRT */ - -static inline void efi_bgrt_init(void) {} - -#endif /* !CONFIG_ACPI_BGRT */ - -#endif /* _LINUX_EFI_BGRT_H */ diff --git a/trunk/include/linux/efi.h b/trunk/include/linux/efi.h index 8670eb1eb8cd..103adc6d7e3a 100644 --- a/trunk/include/linux/efi.h +++ b/trunk/include/linux/efi.h @@ -496,14 +496,6 @@ extern void efi_map_pal_code (void); extern void efi_memmap_walk (efi_freemem_callback_t callback, void *arg); extern void efi_gettimeofday (struct timespec *ts); extern void efi_enter_virtual_mode (void); /* switch EFI to virtual mode, if possible */ -#ifdef CONFIG_X86 -extern void efi_late_init(void); -extern void efi_free_boot_services(void); -#else -static inline void efi_late_init(void) {} -static inline void efi_free_boot_services(void) {} -#endif -extern void __iomem *efi_lookup_mapped_addr(u64 phys_addr); extern u64 efi_get_iobase (void); extern u32 efi_mem_type (unsigned long phys_addr); extern u64 efi_mem_attributes (unsigned long phys_addr); @@ -511,8 +503,6 @@ extern u64 efi_mem_attribute (unsigned long phys_addr, unsigned long size); extern int __init efi_uart_console_only (void); extern void efi_initialize_iomem_resources(struct resource *code_resource, struct resource *data_resource, struct resource *bss_resource); -extern unsigned long efi_get_time(void); -extern int efi_set_rtc_mmss(unsigned long nowtime); extern void efi_reserve_boot_services(void); extern struct efi_memory_map memmap; diff --git a/trunk/include/linux/elf.h b/trunk/include/linux/elf.h index 0a05051a8924..999b4f52e8e5 100644 --- a/trunk/include/linux/elf.h +++ b/trunk/include/linux/elf.h @@ -387,11 +387,7 @@ typedef struct elf64_shdr { #define NT_S390_PREFIX 0x305 /* s390 prefix register */ #define NT_S390_LAST_BREAK 0x306 /* s390 breaking event address */ #define NT_S390_SYSTEM_CALL 0x307 /* s390 system call restart data */ -#define NT_S390_TDB 0x308 /* s390 transaction diagnostic block */ #define NT_ARM_VFP 0x400 /* ARM VFP/NEON registers */ -#define NT_ARM_TLS 0x401 /* ARM TLS register */ -#define NT_ARM_HW_BREAK 0x402 /* ARM hardware breakpoint registers */ -#define NT_ARM_HW_WATCH 0x403 /* ARM hardware watchpoint registers */ /* Note header in a PT_NOTE section */ diff --git a/trunk/include/linux/extcon.h b/trunk/include/linux/extcon.h index 7443a560c9d0..cdd401477656 100644 --- a/trunk/include/linux/extcon.h +++ b/trunk/include/linux/extcon.h @@ -30,19 +30,19 @@ /* * The standard cable name is to help support general notifier - * and notifiee device drivers to share the common names. + * and notifee device drivers to share the common names. * Please use standard cable names unless your notifier device has * a very unique and abnormal cable or * the cable type is supposed to be used with only one unique - * pair of notifier/notifiee devices. + * pair of notifier/notifee devices. * * Please add any other "standard" cables used with extcon dev. * * You may add a dot and number to specify version or specification * of the specific cable if it is required. (e.g., "Fast-charger.18" * and "Fast-charger.10" for 1.8A and 1.0A chargers) - * However, the notifiee and notifier should be able to handle such - * string and if the notifiee can negotiate the protocol or identify, + * However, the notifee and notifier should be able to handle such + * string and if the notifee can negotiate the protocol or idenify, * you don't need such convention. This convention is helpful when * notifier can distinguish but notifiee cannot. */ @@ -76,7 +76,7 @@ struct extcon_cable; * struct extcon_dev - An extcon device represents one external connector. * @name The name of this extcon device. Parent device name is used * if NULL. - * @supported_cable Array of supported cable names ending with NULL. + * @supported_cable Array of supported cable name ending with NULL. * If supported_cable is NULL, cable name related APIs * are disabled. * @mutually_exclusive Array of mutually exclusive set of cables that cannot @@ -95,7 +95,7 @@ struct extcon_cable; * @state Attach/detach state of this extcon. Do not provide at * register-time * @nh Notifier for the state change events from this extcon - * @entry To support list of extcon devices so that users can search + * @entry To support list of extcon devices so that uses can search * for extcon devices based on the extcon name. * @lock * @max_supported Internal value to store the number of cables. @@ -199,7 +199,7 @@ extern int extcon_update_state(struct extcon_dev *edev, u32 mask, u32 state); /* * get/set_cable_state access each bit of the 32b encoded state value. * They are used to access the status of each cable based on the cable_name - * or cable_index, which is retrieved by extcon_find_cable_index + * or cable_index, which is retrived by extcon_find_cable_index */ extern int extcon_find_cable_index(struct extcon_dev *sdev, const char *cable_name); @@ -226,9 +226,9 @@ extern int extcon_unregister_interest(struct extcon_specific_cable_nb *nb); /* * Following APIs are to monitor every action of a notifier. - * Registrar gets notified for every external port of a connection device. + * Registerer gets notified for every external port of a connection device. * Probably this could be used to debug an action of notifier; however, - * we do not recommend to use this for normal 'notifiee' device drivers who + * we do not recommend to use this at normal 'notifiee' device drivers who * want to be notified by a specific external port of the notifier. */ extern int extcon_register_notifier(struct extcon_dev *edev, diff --git a/trunk/include/linux/extcon/extcon-adc-jack.h b/trunk/include/linux/extcon/extcon-adc-jack.h deleted file mode 100644 index 20e9eef25d4c..000000000000 --- a/trunk/include/linux/extcon/extcon-adc-jack.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * include/linux/extcon/extcon-adc-jack.h - * - * Analog Jack extcon driver with ADC-based detection capability. - * - * Copyright (C) 2012 Samsung Electronics - * MyungJoo Ham - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - */ - -#ifndef _EXTCON_ADC_JACK_H_ -#define _EXTCON_ADC_JACK_H_ __FILE__ - -#include -#include - -/** - * struct adc_jack_cond - condition to use an extcon state - * @state - the corresponding extcon state (if 0, this struct denotes - * the last adc_jack_cond element among the array) - * @min_adc - min adc value for this condition - * @max_adc - max adc value for this condition - * - * For example, if { .state = 0x3, .min_adc = 100, .max_adc = 200}, it means - * that if ADC value is between (inclusive) 100 and 200, than the cable 0 and - * 1 are attached (1<<0 | 1<<1 == 0x3) - * - * Note that you don't need to describe condition for "no cable attached" - * because when no adc_jack_cond is met, state = 0 is automatically chosen. - */ -struct adc_jack_cond { - u32 state; /* extcon state value. 0 if invalid */ - u32 min_adc; - u32 max_adc; -}; - -/** - * struct adc_jack_pdata - platform data for adc jack device. - * @name - name of the extcon device. If null, "adc-jack" is used. - * @consumer_channel - Unique name to identify the channel on the consumer - * side. This typically describes the channels used within - * the consumer. E.g. 'battery_voltage' - * @cable_names - array of cable names ending with null. - * @adc_contitions - array of struct adc_jack_cond conditions ending - * with .state = 0 entry. This describes how to decode - * adc values into extcon state. - * @irq_flags - irq flags used for the @irq - * @handling_delay_ms - in some devices, we need to read ADC value some - * milli-seconds after the interrupt occurs. You may - * describe such delays with @handling_delay_ms, which - * is rounded-off by jiffies. - */ -struct adc_jack_pdata { - const char *name; - const char *consumer_channel; - /* - * The last entry should be NULL - */ - const char **cable_names; - /* The last entry's state should be 0 */ - struct adc_jack_cond *adc_conditions; - - unsigned long irq_flags; - unsigned long handling_delay_ms; /* in ms */ -}; - -#endif /* _EXTCON_ADC_JACK_H */ diff --git a/trunk/include/linux/firmware.h b/trunk/include/linux/firmware.h index e4279fedb93a..1e7c01189fa6 100644 --- a/trunk/include/linux/firmware.h +++ b/trunk/include/linux/firmware.h @@ -12,9 +12,6 @@ struct firmware { size_t size; const u8 *data; struct page **pages; - - /* firmware loader private fields */ - void *priv; }; struct module; @@ -47,8 +44,6 @@ int request_firmware_nowait( void (*cont)(const struct firmware *fw, void *context)); void release_firmware(const struct firmware *fw); -int cache_firmware(const char *name); -int uncache_firmware(const char *name); #else static inline int request_firmware(const struct firmware **fw, const char *name, @@ -67,16 +62,6 @@ static inline int request_firmware_nowait( static inline void release_firmware(const struct firmware *fw) { } - -static inline int cache_firmware(const char *name) -{ - return -ENOENT; -} - -static inline int uncache_firmware(const char *name) -{ - return -EINVAL; -} #endif #endif diff --git a/trunk/include/linux/fs.h b/trunk/include/linux/fs.h index aa110476a95b..38dba16c4176 100644 --- a/trunk/include/linux/fs.h +++ b/trunk/include/linux/fs.h @@ -1491,6 +1491,7 @@ struct sb_writers { struct super_block { struct list_head s_list; /* Keep this first */ dev_t s_dev; /* search index; _not_ kdev_t */ + unsigned char s_dirt; unsigned char s_blocksize_bits; unsigned long s_blocksize; loff_t s_maxbytes; /* Max file size */ @@ -1860,6 +1861,7 @@ struct super_operations { int (*drop_inode) (struct inode *); void (*evict_inode) (struct inode *); void (*put_super) (struct super_block *); + void (*write_super) (struct super_block *); int (*sync_fs)(struct super_block *sb, int wait); int (*freeze_fs) (struct super_block *); int (*unfreeze_fs) (struct super_block *); @@ -2395,6 +2397,7 @@ extern int vfs_fsync_range(struct file *file, loff_t start, loff_t end, int datasync); extern int vfs_fsync(struct file *file, int datasync); extern int generic_write_sync(struct file *file, loff_t pos, loff_t count); +extern void sync_supers(void); extern void emergency_sync(void); extern void emergency_remount(void); #ifdef CONFIG_BLOCK diff --git a/trunk/include/linux/ftrace.h b/trunk/include/linux/ftrace.h index a52f2f4fe030..55e6d63d46d0 100644 --- a/trunk/include/linux/ftrace.h +++ b/trunk/include/linux/ftrace.h @@ -10,7 +10,6 @@ #include #include #include -#include #include #include #include @@ -19,28 +18,6 @@ #include -/* - * If the arch supports passing the variable contents of - * function_trace_op as the third parameter back from the - * mcount call, then the arch should define this as 1. - */ -#ifndef ARCH_SUPPORTS_FTRACE_OPS -#define ARCH_SUPPORTS_FTRACE_OPS 0 -#endif - -/* - * If the arch's mcount caller does not support all of ftrace's - * features, then it must call an indirect function that - * does. Or at least does enough to prevent any unwelcomed side effects. - */ -#if !defined(CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST) || \ - !ARCH_SUPPORTS_FTRACE_OPS -# define FTRACE_FORCE_LIST_FUNC 1 -#else -# define FTRACE_FORCE_LIST_FUNC 0 -#endif - - struct module; struct ftrace_hash; @@ -52,10 +29,7 @@ ftrace_enable_sysctl(struct ctl_table *table, int write, void __user *buffer, size_t *lenp, loff_t *ppos); -struct ftrace_ops; - -typedef void (*ftrace_func_t)(unsigned long ip, unsigned long parent_ip, - struct ftrace_ops *op, struct pt_regs *regs); +typedef void (*ftrace_func_t)(unsigned long ip, unsigned long parent_ip); /* * FTRACE_OPS_FL_* bits denote the state of ftrace_ops struct and are @@ -71,33 +45,12 @@ typedef void (*ftrace_func_t)(unsigned long ip, unsigned long parent_ip, * could be controled by following calls: * ftrace_function_local_enable * ftrace_function_local_disable - * SAVE_REGS - The ftrace_ops wants regs saved at each function called - * and passed to the callback. If this flag is set, but the - * architecture does not support passing regs - * (ARCH_SUPPORTS_FTRACE_SAVE_REGS is not defined), then the - * ftrace_ops will fail to register, unless the next flag - * is set. - * SAVE_REGS_IF_SUPPORTED - This is the same as SAVE_REGS, but if the - * handler can handle an arch that does not save regs - * (the handler tests if regs == NULL), then it can set - * this flag instead. It will not fail registering the ftrace_ops - * but, the regs field will be NULL if the arch does not support - * passing regs to the handler. - * Note, if this flag is set, the SAVE_REGS flag will automatically - * get set upon registering the ftrace_ops, if the arch supports it. - * RECURSION_SAFE - The ftrace_ops can set this to tell the ftrace infrastructure - * that the call back has its own recursion protection. If it does - * not set this, then the ftrace infrastructure will add recursion - * protection for the caller. */ enum { - FTRACE_OPS_FL_ENABLED = 1 << 0, - FTRACE_OPS_FL_GLOBAL = 1 << 1, - FTRACE_OPS_FL_DYNAMIC = 1 << 2, - FTRACE_OPS_FL_CONTROL = 1 << 3, - FTRACE_OPS_FL_SAVE_REGS = 1 << 4, - FTRACE_OPS_FL_SAVE_REGS_IF_SUPPORTED = 1 << 5, - FTRACE_OPS_FL_RECURSION_SAFE = 1 << 6, + FTRACE_OPS_FL_ENABLED = 1 << 0, + FTRACE_OPS_FL_GLOBAL = 1 << 1, + FTRACE_OPS_FL_DYNAMIC = 1 << 2, + FTRACE_OPS_FL_CONTROL = 1 << 3, }; struct ftrace_ops { @@ -210,8 +163,7 @@ static inline int ftrace_function_local_disabled(struct ftrace_ops *ops) return *this_cpu_ptr(ops->disabled); } -extern void ftrace_stub(unsigned long a0, unsigned long a1, - struct ftrace_ops *op, struct pt_regs *regs); +extern void ftrace_stub(unsigned long a0, unsigned long a1); #else /* !CONFIG_FUNCTION_TRACER */ /* @@ -220,10 +172,6 @@ extern void ftrace_stub(unsigned long a0, unsigned long a1, */ #define register_ftrace_function(ops) ({ 0; }) #define unregister_ftrace_function(ops) ({ 0; }) -static inline int ftrace_nr_registered_ops(void) -{ - return 0; -} static inline void clear_ftrace_function(void) { } static inline void ftrace_kill(void) { } static inline void ftrace_stop(void) { } @@ -279,33 +227,12 @@ extern void unregister_ftrace_function_probe_all(char *glob); extern int ftrace_text_reserved(void *start, void *end); -extern int ftrace_nr_registered_ops(void); - -/* - * The dyn_ftrace record's flags field is split into two parts. - * the first part which is '0-FTRACE_REF_MAX' is a counter of - * the number of callbacks that have registered the function that - * the dyn_ftrace descriptor represents. - * - * The second part is a mask: - * ENABLED - the function is being traced - * REGS - the record wants the function to save regs - * REGS_EN - the function is set up to save regs. - * - * When a new ftrace_ops is registered and wants a function to save - * pt_regs, the rec->flag REGS is set. When the function has been - * set up to save regs, the REG_EN flag is set. Once a function - * starts saving regs it will do so until all ftrace_ops are removed - * from tracing that function. - */ enum { - FTRACE_FL_ENABLED = (1UL << 29), - FTRACE_FL_REGS = (1UL << 30), - FTRACE_FL_REGS_EN = (1UL << 31) + FTRACE_FL_ENABLED = (1 << 30), }; -#define FTRACE_FL_MASK (0x7UL << 29) -#define FTRACE_REF_MAX ((1UL << 29) - 1) +#define FTRACE_FL_MASK (0x3UL << 30) +#define FTRACE_REF_MAX ((1 << 30) - 1) struct dyn_ftrace { union { @@ -317,8 +244,6 @@ struct dyn_ftrace { }; int ftrace_force_update(void); -int ftrace_set_filter_ip(struct ftrace_ops *ops, unsigned long ip, - int remove, int reset); int ftrace_set_filter(struct ftrace_ops *ops, unsigned char *buf, int len, int reset); int ftrace_set_notrace(struct ftrace_ops *ops, unsigned char *buf, @@ -338,23 +263,9 @@ enum { FTRACE_STOP_FUNC_RET = (1 << 4), }; -/* - * The FTRACE_UPDATE_* enum is used to pass information back - * from the ftrace_update_record() and ftrace_test_record() - * functions. These are called by the code update routines - * to find out what is to be done for a given function. - * - * IGNORE - The function is already what we want it to be - * MAKE_CALL - Start tracing the function - * MODIFY_CALL - Stop saving regs for the function - * MODIFY_CALL_REGS - Start saving regs for the function - * MAKE_NOP - Stop tracing the function - */ enum { FTRACE_UPDATE_IGNORE, FTRACE_UPDATE_MAKE_CALL, - FTRACE_UPDATE_MODIFY_CALL, - FTRACE_UPDATE_MODIFY_CALL_REGS, FTRACE_UPDATE_MAKE_NOP, }; @@ -406,9 +317,7 @@ extern int ftrace_dyn_arch_init(void *data); extern void ftrace_replace_code(int enable); extern int ftrace_update_ftrace_func(ftrace_func_t func); extern void ftrace_caller(void); -extern void ftrace_regs_caller(void); extern void ftrace_call(void); -extern void ftrace_regs_call(void); extern void mcount_call(void); void ftrace_modify_all_code(int command); @@ -416,15 +325,6 @@ void ftrace_modify_all_code(int command); #ifndef FTRACE_ADDR #define FTRACE_ADDR ((unsigned long)ftrace_caller) #endif - -#ifndef FTRACE_REGS_ADDR -#ifdef ARCH_SUPPORTS_FTRACE_SAVE_REGS -# define FTRACE_REGS_ADDR ((unsigned long)ftrace_regs_caller) -#else -# define FTRACE_REGS_ADDR FTRACE_ADDR -#endif -#endif - #ifdef CONFIG_FUNCTION_GRAPH_TRACER extern void ftrace_graph_caller(void); extern int ftrace_enable_ftrace_graph_caller(void); @@ -480,39 +380,6 @@ extern int ftrace_make_nop(struct module *mod, */ extern int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr); -#ifdef ARCH_SUPPORTS_FTRACE_SAVE_REGS -/** - * ftrace_modify_call - convert from one addr to another (no nop) - * @rec: the mcount call site record - * @old_addr: the address expected to be currently called to - * @addr: the address to change to - * - * This is a very sensitive operation and great care needs - * to be taken by the arch. The operation should carefully - * read the location, check to see if what is read is indeed - * what we expect it to be, and then on success of the compare, - * it should write to the location. - * - * The code segment at @rec->ip should be a caller to @old_addr - * - * Return must be: - * 0 on success - * -EFAULT on error reading the location - * -EINVAL on a failed compare of the contents - * -EPERM on error writing to the location - * Any other value will be considered a failure. - */ -extern int ftrace_modify_call(struct dyn_ftrace *rec, unsigned long old_addr, - unsigned long addr); -#else -/* Should never be called */ -static inline int ftrace_modify_call(struct dyn_ftrace *rec, unsigned long old_addr, - unsigned long addr) -{ - return -EINVAL; -} -#endif - /* May be defined in arch */ extern int ftrace_arch_read_dyn_info(char *buf, int size); @@ -520,7 +387,7 @@ extern int skip_trace(unsigned long ip); extern void ftrace_disable_daemon(void); extern void ftrace_enable_daemon(void); -#else /* CONFIG_DYNAMIC_FTRACE */ +#else static inline int skip_trace(unsigned long ip) { return 0; } static inline int ftrace_force_update(void) { return 0; } static inline void ftrace_disable_daemon(void) { } @@ -538,10 +405,6 @@ static inline int ftrace_text_reserved(void *start, void *end) { return 0; } -static inline unsigned long ftrace_location(unsigned long ip) -{ - return 0; -} /* * Again users of functions that have ftrace_ops may not @@ -550,7 +413,6 @@ static inline unsigned long ftrace_location(unsigned long ip) */ #define ftrace_regex_open(ops, flag, inod, file) ({ -ENODEV; }) #define ftrace_set_early_filter(ops, buf, enable) do { } while (0) -#define ftrace_set_filter_ip(ops, ip, remove, reset) ({ -ENODEV; }) #define ftrace_set_filter(ops, buf, len, reset) ({ -ENODEV; }) #define ftrace_set_notrace(ops, buf, len, reset) ({ -ENODEV; }) #define ftrace_free_filter(ops) do { } while (0) diff --git a/trunk/include/linux/ftrace_event.h b/trunk/include/linux/ftrace_event.h index 642928cf57b4..af961d6f7ab1 100644 --- a/trunk/include/linux/ftrace_event.h +++ b/trunk/include/linux/ftrace_event.h @@ -306,10 +306,9 @@ extern void *perf_trace_buf_prepare(int size, unsigned short type, static inline void perf_trace_buf_submit(void *raw_data, int size, int rctx, u64 addr, - u64 count, struct pt_regs *regs, void *head, - struct task_struct *task) + u64 count, struct pt_regs *regs, void *head) { - perf_tp_event(addr, count, raw_data, size, regs, head, rctx, task); + perf_tp_event(addr, count, raw_data, size, regs, head, rctx); } #endif diff --git a/trunk/include/linux/fuse.h b/trunk/include/linux/fuse.h index d8c713e148e3..9303348965fb 100644 --- a/trunk/include/linux/fuse.h +++ b/trunk/include/linux/fuse.h @@ -57,9 +57,6 @@ * * 7.19 * - add FUSE_FALLOCATE - * - * 7.20 - * - add FUSE_AUTO_INVAL_DATA */ #ifndef _LINUX_FUSE_H @@ -91,7 +88,7 @@ #define FUSE_KERNEL_VERSION 7 /** Minor version number of this interface */ -#define FUSE_KERNEL_MINOR_VERSION 20 +#define FUSE_KERNEL_MINOR_VERSION 19 /** The node ID of the root inode */ #define FUSE_ROOT_ID 1 @@ -166,19 +163,10 @@ struct fuse_file_lock { /** * INIT request/reply flags * - * FUSE_ASYNC_READ: asynchronous read requests * FUSE_POSIX_LOCKS: remote locking for POSIX file locks - * FUSE_FILE_OPS: kernel sends file handle for fstat, etc... (not yet supported) - * FUSE_ATOMIC_O_TRUNC: handles the O_TRUNC open flag in the filesystem * FUSE_EXPORT_SUPPORT: filesystem handles lookups of "." and ".." - * FUSE_BIG_WRITES: filesystem can handle write size larger than 4kB * FUSE_DONT_MASK: don't apply umask to file mode on create operations - * FUSE_SPLICE_WRITE: kernel supports splice write on the device - * FUSE_SPLICE_MOVE: kernel supports splice move on the device - * FUSE_SPLICE_READ: kernel supports splice read on the device * FUSE_FLOCK_LOCKS: remote locking for BSD style file locks - * FUSE_HAS_IOCTL_DIR: kernel supports ioctl on directories - * FUSE_AUTO_INVAL_DATA: automatically invalidate cached pages */ #define FUSE_ASYNC_READ (1 << 0) #define FUSE_POSIX_LOCKS (1 << 1) @@ -187,12 +175,7 @@ struct fuse_file_lock { #define FUSE_EXPORT_SUPPORT (1 << 4) #define FUSE_BIG_WRITES (1 << 5) #define FUSE_DONT_MASK (1 << 6) -#define FUSE_SPLICE_WRITE (1 << 7) -#define FUSE_SPLICE_MOVE (1 << 8) -#define FUSE_SPLICE_READ (1 << 9) #define FUSE_FLOCK_LOCKS (1 << 10) -#define FUSE_HAS_IOCTL_DIR (1 << 11) -#define FUSE_AUTO_INVAL_DATA (1 << 12) /** * CUSE INIT request/reply flags diff --git a/trunk/include/linux/generic_serial.h b/trunk/include/linux/generic_serial.h new file mode 100644 index 000000000000..79b3eb37243a --- /dev/null +++ b/trunk/include/linux/generic_serial.h @@ -0,0 +1,35 @@ +/* + * generic_serial.h + * + * Copyright (C) 1998 R.E.Wolff@BitWizard.nl + * + * written for the SX serial driver. + * + * Version 0.1 -- December, 1998. + */ + +#ifndef GENERIC_SERIAL_H +#define GENERIC_SERIAL_H + +#warning Use of this header is deprecated. +#warning Since nobody sets the constants defined here for you, you should not, in any case, use them. Including the header is thus pointless. + +/* Flags */ +/* Warning: serial.h defines some ASYNC_ flags, they say they are "only" + used in serial.c, but they are also used in all other serial drivers. + Make sure they don't clash with these here... */ +#define GS_TX_INTEN 0x00800000 +#define GS_RX_INTEN 0x00400000 +#define GS_ACTIVE 0x00200000 + +#define GS_TYPE_NORMAL 1 + +#define GS_DEBUG_FLUSH 0x00000001 +#define GS_DEBUG_BTR 0x00000002 +#define GS_DEBUG_TERMIOS 0x00000004 +#define GS_DEBUG_STUFF 0x00000008 +#define GS_DEBUG_CLOSE 0x00000010 +#define GS_DEBUG_FLOW 0x00000020 +#define GS_DEBUG_WRITE 0x00000040 + +#endif diff --git a/trunk/include/linux/hardirq.h b/trunk/include/linux/hardirq.h index cab3da3d0949..bb7f30971858 100644 --- a/trunk/include/linux/hardirq.h +++ b/trunk/include/linux/hardirq.h @@ -22,7 +22,7 @@ * * - bits 16-25 are the hardirq count (max # of nested hardirqs: 1024) * - bit 26 is the NMI_MASK - * - bit 27 is the PREEMPT_ACTIVE flag + * - bit 28 is the PREEMPT_ACTIVE flag * * PREEMPT_MASK: 0x000000ff * SOFTIRQ_MASK: 0x0000ff00 @@ -132,11 +132,11 @@ extern void synchronize_irq(unsigned int irq); struct task_struct; #if !defined(CONFIG_VIRT_CPU_ACCOUNTING) && !defined(CONFIG_IRQ_TIME_ACCOUNTING) -static inline void vtime_account(struct task_struct *tsk) +static inline void account_system_vtime(struct task_struct *tsk) { } #else -extern void vtime_account(struct task_struct *tsk); +extern void account_system_vtime(struct task_struct *tsk); #endif #if defined(CONFIG_TINY_RCU) || defined(CONFIG_TINY_PREEMPT_RCU) @@ -162,7 +162,7 @@ extern void rcu_nmi_exit(void); */ #define __irq_enter() \ do { \ - vtime_account(current); \ + account_system_vtime(current); \ add_preempt_count(HARDIRQ_OFFSET); \ trace_hardirq_enter(); \ } while (0) @@ -178,7 +178,7 @@ extern void irq_enter(void); #define __irq_exit() \ do { \ trace_hardirq_exit(); \ - vtime_account(current); \ + account_system_vtime(current); \ sub_preempt_count(HARDIRQ_OFFSET); \ } while (0) diff --git a/trunk/include/linux/hid-sensor-hub.h b/trunk/include/linux/hid-sensor-hub.h deleted file mode 100644 index 0aa5f4c42ae6..000000000000 --- a/trunk/include/linux/hid-sensor-hub.h +++ /dev/null @@ -1,160 +0,0 @@ -/* - * HID Sensors Driver - * Copyright (c) 2012, Intel Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * - */ -#ifndef _HID_SENSORS_HUB_H -#define _HID_SENSORS_HUB_H - -#include -#include - -/** - * struct hid_sensor_hub_attribute_info - Attribute info - * @usage_id: Parent usage id of a physical device. - * @attrib_id: Attribute id for this attribute. - * @report_id: Report id in which this information resides. - * @index: Field index in the report. - * @units: Measurment unit for this attribute. - * @unit_expo: Exponent used in the data. - * @size: Size in bytes for data size. - */ -struct hid_sensor_hub_attribute_info { - u32 usage_id; - u32 attrib_id; - s32 report_id; - s32 index; - s32 units; - s32 unit_expo; - s32 size; -}; - -/** - * struct hid_sensor_hub_device - Stores the hub instance data - * @hdev: Stores the hid instance. - * @vendor_id: Vendor id of hub device. - * @product_id: Product id of hub device. - */ -struct hid_sensor_hub_device { - struct hid_device *hdev; - u32 vendor_id; - u32 product_id; -}; - -/** - * struct hid_sensor_hub_callbacks - Client callback functions - * @pdev: Platform device instance of the client driver. - * @suspend: Suspend callback. - * @resume: Resume callback. - * @capture_sample: Callback to get a sample. - * @send_event: Send notification to indicate all samples are - * captured, process and send event - */ -struct hid_sensor_hub_callbacks { - struct platform_device *pdev; - int (*suspend)(struct hid_sensor_hub_device *hsdev, void *priv); - int (*resume)(struct hid_sensor_hub_device *hsdev, void *priv); - int (*capture_sample)(struct hid_sensor_hub_device *hsdev, - u32 usage_id, size_t raw_len, char *raw_data, - void *priv); - int (*send_event)(struct hid_sensor_hub_device *hsdev, u32 usage_id, - void *priv); -}; - -/* Registration functions */ - -/** -* sensor_hub_register_callback() - Register client callbacks -* @hsdev: Hub device instance. -* @usage_id: Usage id of the client (E.g. 0x200076 for Gyro). -* @usage_callback: Callback function storage -* -* Used to register callbacks by client processing drivers. Sensor -* hub core driver will call these callbacks to offload processing -* of data streams and notifications. -*/ -int sensor_hub_register_callback(struct hid_sensor_hub_device *hsdev, - u32 usage_id, - struct hid_sensor_hub_callbacks *usage_callback); - -/** -* sensor_hub_remove_callback() - Remove client callbacks -* @hsdev: Hub device instance. -* @usage_id: Usage id of the client (E.g. 0x200076 for Gyro). -* -* If there is a callback registred, this call will remove that -* callbacks, so that it will stop data and event notifications. -*/ -int sensor_hub_remove_callback(struct hid_sensor_hub_device *hsdev, - u32 usage_id); - - -/* Hid sensor hub core interfaces */ - -/** -* sensor_hub_input_get_attribute_info() - Get an attribute information -* @hsdev: Hub device instance. -* @type: Type of this attribute, input/output/feature -* @usage_id: Attribute usage id of parent physical device as per spec -* @attr_usage_id: Attribute usage id as per spec -* @info: return information about attribute after parsing report -* -* Parses report and returns the attribute information such as report id, -* field index, units and exponet etc. -*/ -int sensor_hub_input_get_attribute_info(struct hid_sensor_hub_device *hsdev, - u8 type, - u32 usage_id, u32 attr_usage_id, - struct hid_sensor_hub_attribute_info *info); - -/** -* sensor_hub_input_attr_get_raw_value() - Synchronous read request -* @usage_id: Attribute usage id of parent physical device as per spec -* @attr_usage_id: Attribute usage id as per spec -* @report_id: Report id to look for -* -* Issues a synchronous read request for an input attribute. Returns -* data upto 32 bits. Since client can get events, so this call should -* not be used for data paths, this will impact performance. -*/ - -int sensor_hub_input_attr_get_raw_value(struct hid_sensor_hub_device *hsdev, - u32 usage_id, - u32 attr_usage_id, u32 report_id); -/** -* sensor_hub_set_feature() - Feature set request -* @report_id: Report id to look for -* @field_index: Field index inside a report -* @value: Value to set -* -* Used to set a field in feature report. For example this can set polling -* interval, sensitivity, activate/deactivate state. -*/ -int sensor_hub_set_feature(struct hid_sensor_hub_device *hsdev, u32 report_id, - u32 field_index, s32 value); - -/** -* sensor_hub_get_feature() - Feature get request -* @report_id: Report id to look for -* @field_index: Field index inside a report -* @value: Place holder for return value -* -* Used to get a field in feature report. For example this can get polling -* interval, sensitivity, activate/deactivate state. -*/ -int sensor_hub_get_feature(struct hid_sensor_hub_device *hsdev, u32 report_id, - u32 field_index, s32 *value); -#endif diff --git a/trunk/include/linux/hid-sensor-ids.h b/trunk/include/linux/hid-sensor-ids.h deleted file mode 100644 index ca8d7e94eb3c..000000000000 --- a/trunk/include/linux/hid-sensor-ids.h +++ /dev/null @@ -1,112 +0,0 @@ -/* - * HID Sensors Driver - * Copyright (c) 2012, Intel Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * - */ -#ifndef _HID_SENSORS_IDS_H -#define _HID_SENSORS_IDS_H - -#define HID_UP_SENSOR 0x00200000 -#define HID_MAX_PHY_DEVICES 0xFF - -/* Accel 3D (200073) */ -#define HID_USAGE_SENSOR_ACCEL_3D 0x200073 -#define HID_USAGE_SENSOR_ACCEL_X_AXIS 0x200453 -#define HID_USAGE_SENSOR_ACCEL_Y_AXIS 0x200454 -#define HID_USAGE_SENSOR_ACCEL_Z_AXIS 0x200455 - -/* ALS (200041) */ -#define HID_USAGE_SENSOR_ALS 0x200041 -#define HID_USAGE_SENSOR_LIGHT_ILLUM 0x2004d1 - -/* Gyro 3D: (200076) */ -#define HID_USAGE_SENSOR_GYRO_3D 0x200076 -#define HID_USAGE_SENSOR_ANGL_VELOCITY_X_AXIS 0x200457 -#define HID_USAGE_SENSOR_ANGL_VELOCITY_Y_AXIS 0x200458 -#define HID_USAGE_SENSOR_ANGL_VELOCITY_Z_AXIS 0x200459 - -/*ORIENTATION: Compass 3D: (200083) */ -#define HID_USAGE_SENSOR_COMPASS_3D 0x200083 -#define HID_USAGE_SENSOR_ORIENT_MAGN_HEADING 0x200471 -#define HID_USAGE_SENSOR_ORIENT_MAGN_HEADING_X 0x200472 -#define HID_USAGE_SENSOR_ORIENT_MAGN_HEADING_Y 0x200473 -#define HID_USAGE_SENSOR_ORIENT_MAGN_HEADING_Z 0x200474 - -#define HID_USAGE_SENSOR_ORIENT_COMP_MAGN_NORTH 0x200475 -#define HID_USAGE_SENSOR_ORIENT_COMP_TRUE_NORTH 0x200476 -#define HID_USAGE_SENSOR_ORIENT_MAGN_NORTH 0x200477 -#define HID_USAGE_SENSOR_ORIENT_TRUE_NORTH 0x200478 - -#define HID_USAGE_SENSOR_ORIENT_DISTANCE 0x200479 -#define HID_USAGE_SENSOR_ORIENT_DISTANCE_X 0x20047A -#define HID_USAGE_SENSOR_ORIENT_DISTANCE_Y 0x20047B -#define HID_USAGE_SENSOR_ORIENT_DISTANCE_Z 0x20047C -#define HID_USAGE_SENSOR_ORIENT_DISTANCE_OUT_OF_RANGE 0x20047D -#define HID_USAGE_SENSOR_ORIENT_TILT 0x20047E -#define HID_USAGE_SENSOR_ORIENT_TILT_X 0x20047F -#define HID_USAGE_SENSOR_ORIENT_TILT_Y 0x200480 -#define HID_USAGE_SENSOR_ORIENT_TILT_Z 0x200481 -#define HID_USAGE_SENSOR_ORIENT_ROTATION_MATRIX 0x200482 -#define HID_USAGE_SENSOR_ORIENT_QUATERNION 0x200483 -#define HID_USAGE_SENSOR_ORIENT_MAGN_FLUX 0x200484 - -#define HID_USAGE_SENSOR_ORIENT_MAGN_FLUX_X_AXIS 0x200485 -#define HID_USAGE_SENSOR_ORIENT_MAGN_FLUX_Y_AXIS 0x200486 -#define HID_USAGE_SENSOR_ORIENT_MAGN_FLUX_Z_AXIS 0x200487 - -/* Units */ -#define HID_USAGE_SENSOR_UNITS_NOT_SPECIFIED 0x00 -#define HID_USAGE_SENSOR_UNITS_LUX 0x01 -#define HID_USAGE_SENSOR_UNITS_KELVIN 0x01000100 -#define HID_USAGE_SENSOR_UNITS_FAHRENHEIT 0x03000100 -#define HID_USAGE_SENSOR_UNITS_PASCAL 0xF1E1 -#define HID_USAGE_SENSOR_UNITS_NEWTON 0x11E1 -#define HID_USAGE_SENSOR_UNITS_METERS_PER_SECOND 0x11F0 -#define HID_USAGE_SENSOR_UNITS_METERS_PER_SEC_SQRD 0x11E0 -#define HID_USAGE_SENSOR_UNITS_FARAD 0xE14F2000 -#define HID_USAGE_SENSOR_UNITS_AMPERE 0x01001000 -#define HID_USAGE_SENSOR_UNITS_WATT 0x21d1 -#define HID_USAGE_SENSOR_UNITS_HENRY 0x21E1E000 -#define HID_USAGE_SENSOR_UNITS_OHM 0x21D1E000 -#define HID_USAGE_SENSOR_UNITS_VOLT 0x21D1F000 -#define HID_USAGE_SENSOR_UNITS_HERTZ 0x01F0 -#define HID_USAGE_SENSOR_UNITS_DEGREES_PER_SEC_SQRD 0x14E0 -#define HID_USAGE_SENSOR_UNITS_RADIANS 0x12 -#define HID_USAGE_SENSOR_UNITS_RADIANS_PER_SECOND 0x12F0 -#define HID_USAGE_SENSOR_UNITS_RADIANS_PER_SEC_SQRD 0x12E0 -#define HID_USAGE_SENSOR_UNITS_SECOND 0x0110 -#define HID_USAGE_SENSOR_UNITS_GAUSS 0x01E1F000 -#define HID_USAGE_SENSOR_UNITS_GRAM 0x0101 -#define HID_USAGE_SENSOR_UNITS_CENTIMETER 0x11 -#define HID_USAGE_SENSOR_UNITS_G 0x1A -#define HID_USAGE_SENSOR_UNITS_MILLISECOND 0x19 -#define HID_USAGE_SENSOR_UNITS_PERCENT 0x17 -#define HID_USAGE_SENSOR_UNITS_DEGREES 0x14 -#define HID_USAGE_SENSOR_UNITS_DEGREES_PER_SECOND 0x15 - -/* Common selectors */ -#define HID_USAGE_SENSOR_PROP_REPORT_INTERVAL 0x20030E -#define HID_USAGE_SENSOR_PROP_SENSITIVITY_ABS 0x20030F -#define HID_USAGE_SENSOR_PROP_SENSITIVITY_RANGE_PCT 0x200310 -#define HID_USAGE_SENSOR_PROP_SENSITIVITY_REL_PCT 0x200311 -#define HID_USAGE_SENSOR_PROP_ACCURACY 0x200312 -#define HID_USAGE_SENSOR_PROP_RESOLUTION 0x200313 -#define HID_USAGE_SENSOR_PROP_RANGE_MAXIMUM 0x200314 -#define HID_USAGE_SENSOR_PROP_RANGE_MINIMUM 0x200315 -#define HID_USAGE_SENSOR_PROP_REPORT_STATE 0x200316 -#define HID_USAGE_SENSOR_PROY_POWER_STATE 0x200319 - -#endif diff --git a/trunk/include/linux/hid.h b/trunk/include/linux/hid.h index 7e1f37db7582..42970de1b40c 100644 --- a/trunk/include/linux/hid.h +++ b/trunk/include/linux/hid.h @@ -414,7 +414,7 @@ struct hid_field { __u16 dpad; /* dpad input code */ }; -#define HID_MAX_FIELDS 256 +#define HID_MAX_FIELDS 128 struct hid_report { struct list_head list; @@ -626,7 +626,6 @@ struct hid_usage_id { * @report_fixup: called before report descriptor parsing (NULL means nop) * @input_mapping: invoked on input registering before mapping an usage * @input_mapped: invoked on input registering after mapping an usage - * @input_configured: invoked just before the device is registered * @feature_mapping: invoked on feature registering * @suspend: invoked on suspend (NULL means nop) * @resume: invoked on resume if device was not reset (NULL means nop) @@ -671,8 +670,6 @@ struct hid_driver { int (*input_mapped)(struct hid_device *hdev, struct hid_input *hidinput, struct hid_field *field, struct hid_usage *usage, unsigned long **bit, int *max); - void (*input_configured)(struct hid_device *hdev, - struct hid_input *hidinput); void (*feature_mapping)(struct hid_device *hdev, struct hid_field *field, struct hid_usage *usage); diff --git a/trunk/include/linux/hyperv.h b/trunk/include/linux/hyperv.h index e73b852156b1..68ed7f7e1fc9 100644 --- a/trunk/include/linux/hyperv.h +++ b/trunk/include/linux/hyperv.h @@ -122,53 +122,12 @@ #define REG_U32 4 #define REG_U64 8 -/* - * As we look at expanding the KVP functionality to include - * IP injection functionality, we need to maintain binary - * compatibility with older daemons. - * - * The KVP opcodes are defined by the host and it was unfortunate - * that I chose to treat the registration operation as part of the - * KVP operations defined by the host. - * Here is the level of compatibility - * (between the user level daemon and the kernel KVP driver) that we - * will implement: - * - * An older daemon will always be supported on a newer driver. - * A given user level daemon will require a minimal version of the - * kernel driver. - * If we cannot handle the version differences, we will fail gracefully - * (this can happen when we have a user level daemon that is more - * advanced than the KVP driver. - * - * We will use values used in this handshake for determining if we have - * workable user level daemon and the kernel driver. We begin by taking the - * registration opcode out of the KVP opcode namespace. We will however, - * maintain compatibility with the existing user-level daemon code. - */ - -/* - * Daemon code not supporting IP injection (legacy daemon). - */ - -#define KVP_OP_REGISTER 4 - -/* - * Daemon code supporting IP injection. - * The KVP opcode field is used to communicate the - * registration information; so define a namespace that - * will be distinct from the host defined KVP opcode. - */ - -#define KVP_OP_REGISTER1 100 - enum hv_kvp_exchg_op { KVP_OP_GET = 0, KVP_OP_SET, KVP_OP_DELETE, KVP_OP_ENUMERATE, - KVP_OP_GET_IP_INFO, - KVP_OP_SET_IP_INFO, + KVP_OP_REGISTER, KVP_OP_COUNT /* Number of operations, must be last. */ }; @@ -181,39 +140,6 @@ enum hv_kvp_exchg_pool { KVP_POOL_COUNT /* Number of pools, must be last. */ }; -/* - * Some Hyper-V status codes. - */ - -#define HV_S_OK 0x00000000 -#define HV_E_FAIL 0x80004005 -#define HV_S_CONT 0x80070103 -#define HV_ERROR_NOT_SUPPORTED 0x80070032 -#define HV_ERROR_MACHINE_LOCKED 0x800704F7 -#define HV_ERROR_DEVICE_NOT_CONNECTED 0x8007048F -#define HV_INVALIDARG 0x80070057 -#define HV_GUID_NOTFOUND 0x80041002 - -#define ADDR_FAMILY_NONE 0x00 -#define ADDR_FAMILY_IPV4 0x01 -#define ADDR_FAMILY_IPV6 0x02 - -#define MAX_ADAPTER_ID_SIZE 128 -#define MAX_IP_ADDR_SIZE 1024 -#define MAX_GATEWAY_SIZE 512 - - -struct hv_kvp_ipaddr_value { - __u16 adapter_id[MAX_ADAPTER_ID_SIZE]; - __u8 addr_family; - __u8 dhcp_enabled; - __u16 ip_addr[MAX_IP_ADDR_SIZE]; - __u16 sub_net[MAX_IP_ADDR_SIZE]; - __u16 gate_way[MAX_GATEWAY_SIZE]; - __u16 dns_addr[MAX_IP_ADDR_SIZE]; -} __attribute__((packed)); - - struct hv_kvp_hdr { __u8 operation; __u8 pool; @@ -255,26 +181,16 @@ struct hv_kvp_register { }; struct hv_kvp_msg { - union { - struct hv_kvp_hdr kvp_hdr; - int error; - }; + struct hv_kvp_hdr kvp_hdr; union { struct hv_kvp_msg_get kvp_get; struct hv_kvp_msg_set kvp_set; struct hv_kvp_msg_delete kvp_delete; struct hv_kvp_msg_enumerate kvp_enum_data; - struct hv_kvp_ipaddr_value kvp_ip_val; struct hv_kvp_register kvp_register; } body; } __attribute__((packed)); -struct hv_kvp_ip_msg { - __u8 operation; - __u8 pool; - struct hv_kvp_ipaddr_value kvp_ip_val; -} __attribute__((packed)); - #ifdef __KERNEL__ #include #include @@ -489,7 +405,7 @@ struct vmtransfer_page_range { struct vmtransfer_page_packet_header { struct vmpacket_descriptor d; u16 xfer_pageset_id; - u8 sender_owns_set; + bool sender_owns_set; u8 reserved; u32 range_cnt; struct vmtransfer_page_range ranges[1]; @@ -643,7 +559,7 @@ struct vmbus_channel_query_vmbus_version { /* VMBus Version Supported parameters */ struct vmbus_channel_version_supported { struct vmbus_channel_message_header header; - u8 version_supported; + bool version_supported; } __packed; /* Offer Channel parameters */ @@ -652,7 +568,7 @@ struct vmbus_channel_offer_channel { struct vmbus_channel_offer offer; u32 child_relid; u8 monitorid; - u8 monitor_allocated; + bool monitor_allocated; } __packed; /* Rescind Offer parameters */ @@ -788,7 +704,7 @@ struct vmbus_channel_initiate_contact { struct vmbus_channel_version_response { struct vmbus_channel_message_header header; - u8 version_supported; + bool version_supported; } __packed; enum vmbus_channel_state { @@ -1061,6 +977,11 @@ void vmbus_driver_unregister(struct hv_driver *hv_driver); #define ICMSGHDRFLAG_REQUEST 2 #define ICMSGHDRFLAG_RESPONSE 4 +#define HV_S_OK 0x00000000 +#define HV_E_FAIL 0x80004005 +#define HV_S_CONT 0x80070103 +#define HV_ERROR_NOT_SUPPORTED 0x80070032 +#define HV_ERROR_MACHINE_LOCKED 0x800704F7 /* * While we want to handle util services as regular devices, diff --git a/trunk/include/linux/i2c-pnx.h b/trunk/include/linux/i2c-pnx.h index 49ed17fdf055..1bc74afe7a35 100644 --- a/trunk/include/linux/i2c-pnx.h +++ b/trunk/include/linux/i2c-pnx.h @@ -22,7 +22,6 @@ struct i2c_pnx_mif { struct timer_list timer; /* Timeout */ u8 * buf; /* Data buffer */ int len; /* Length of data buffer */ - int order; /* RX Bytes to order via TX */ }; struct i2c_pnx_algo_data { diff --git a/trunk/include/linux/if_team.h b/trunk/include/linux/if_team.h index aa2e167e1ef4..6960fc1841a7 100644 --- a/trunk/include/linux/if_team.h +++ b/trunk/include/linux/if_team.h @@ -96,6 +96,21 @@ static inline void team_netpoll_send_skb(struct team_port *port, } #endif +static inline int team_dev_queue_xmit(struct team *team, struct team_port *port, + struct sk_buff *skb) +{ + BUILD_BUG_ON(sizeof(skb->queue_mapping) != + sizeof(qdisc_skb_cb(skb)->slave_dev_queue_mapping)); + skb_set_queue_mapping(skb, qdisc_skb_cb(skb)->slave_dev_queue_mapping); + + skb->dev = port->dev; + if (unlikely(netpoll_tx_running(port->dev))) { + team_netpoll_send_skb(port, skb); + return 0; + } + return dev_queue_xmit(skb); +} + struct team_mode_ops { int (*init)(struct team *team); void (*exit)(struct team *team); @@ -185,21 +200,6 @@ struct team { long mode_priv[TEAM_MODE_PRIV_LONGS]; }; -static inline int team_dev_queue_xmit(struct team *team, struct team_port *port, - struct sk_buff *skb) -{ - BUILD_BUG_ON(sizeof(skb->queue_mapping) != - sizeof(qdisc_skb_cb(skb)->slave_dev_queue_mapping)); - skb_set_queue_mapping(skb, qdisc_skb_cb(skb)->slave_dev_queue_mapping); - - skb->dev = port->dev; - if (unlikely(netpoll_tx_running(team->dev))) { - team_netpoll_send_skb(port, skb); - return 0; - } - return dev_queue_xmit(skb); -} - static inline struct hlist_head *team_port_index_hash(struct team *team, int port_index) { diff --git a/trunk/include/linux/iio/adc/ad_sigma_delta.h b/trunk/include/linux/iio/adc/ad_sigma_delta.h deleted file mode 100644 index 2e4eab9868a3..000000000000 --- a/trunk/include/linux/iio/adc/ad_sigma_delta.h +++ /dev/null @@ -1,173 +0,0 @@ -/* - * Support code for Analog Devices Sigma-Delta ADCs - * - * Copyright 2012 Analog Devices Inc. - * Author: Lars-Peter Clausen - * - * Licensed under the GPL-2. - */ -#ifndef __AD_SIGMA_DELTA_H__ -#define __AD_SIGMA_DELTA_H__ - -enum ad_sigma_delta_mode { - AD_SD_MODE_CONTINUOUS = 0, - AD_SD_MODE_SINGLE = 1, - AD_SD_MODE_IDLE = 2, - AD_SD_MODE_POWERDOWN = 3, -}; - -/** - * struct ad_sigma_delta_calib_data - Calibration data for Sigma Delta devices - * @mode: Calibration mode. - * @channel: Calibration channel. - */ -struct ad_sd_calib_data { - unsigned int mode; - unsigned int channel; -}; - -struct ad_sigma_delta; -struct iio_dev; - -/** - * struct ad_sigma_delta_info - Sigma Delta driver specific callbacks and options - * @set_channel: Will be called to select the current channel, may be NULL. - * @set_mode: Will be called to select the current mode, may be NULL. - * @postprocess_sample: Is called for each sampled data word, can be used to - * modify or drop the sample data, it, may be NULL. - * @has_registers: true if the device has writable and readable registers, false - * if there is just one read-only sample data shift register. - * @addr_shift: Shift of the register address in the communications register. - * @read_mask: Mask for the communications register having the read bit set. - */ -struct ad_sigma_delta_info { - int (*set_channel)(struct ad_sigma_delta *, unsigned int channel); - int (*set_mode)(struct ad_sigma_delta *, enum ad_sigma_delta_mode mode); - int (*postprocess_sample)(struct ad_sigma_delta *, unsigned int raw_sample); - bool has_registers; - unsigned int addr_shift; - unsigned int read_mask; -}; - -/** - * struct ad_sigma_delta - Sigma Delta device struct - * @spi: The spi device associated with the Sigma Delta device. - * @trig: The IIO trigger associated with the Sigma Delta device. - * - * Most of the fields are private to the sigma delta library code and should not - * be accessed by individual drivers. - */ -struct ad_sigma_delta { - struct spi_device *spi; - struct iio_trigger *trig; - -/* private: */ - struct completion completion; - bool irq_dis; - - bool bus_locked; - - uint8_t comm; - - const struct ad_sigma_delta_info *info; - - /* - * DMA (thus cache coherency maintenance) requires the - * transfer buffers to live in their own cache lines. - */ - uint8_t data[4] ____cacheline_aligned; -}; - -static inline int ad_sigma_delta_set_channel(struct ad_sigma_delta *sd, - unsigned int channel) -{ - if (sd->info->set_channel) - return sd->info->set_channel(sd, channel); - - return 0; -} - -static inline int ad_sigma_delta_set_mode(struct ad_sigma_delta *sd, - unsigned int mode) -{ - if (sd->info->set_mode) - return sd->info->set_mode(sd, mode); - - return 0; -} - -static inline int ad_sigma_delta_postprocess_sample(struct ad_sigma_delta *sd, - unsigned int raw_sample) -{ - if (sd->info->postprocess_sample) - return sd->info->postprocess_sample(sd, raw_sample); - - return 0; -} - -void ad_sd_set_comm(struct ad_sigma_delta *sigma_delta, uint8_t comm); -int ad_sd_write_reg(struct ad_sigma_delta *sigma_delta, unsigned int reg, - unsigned int size, unsigned int val); -int ad_sd_read_reg(struct ad_sigma_delta *sigma_delta, unsigned int reg, - unsigned int size, unsigned int *val); - -int ad_sigma_delta_single_conversion(struct iio_dev *indio_dev, - const struct iio_chan_spec *chan, int *val); -int ad_sd_calibrate_all(struct ad_sigma_delta *sigma_delta, - const struct ad_sd_calib_data *cd, unsigned int n); -int ad_sd_init(struct ad_sigma_delta *sigma_delta, struct iio_dev *indio_dev, - struct spi_device *spi, const struct ad_sigma_delta_info *info); - -int ad_sd_setup_buffer_and_trigger(struct iio_dev *indio_dev); -void ad_sd_cleanup_buffer_and_trigger(struct iio_dev *indio_dev); - -int ad_sd_validate_trigger(struct iio_dev *indio_dev, struct iio_trigger *trig); - -#define __AD_SD_CHANNEL(_si, _channel1, _channel2, _address, _bits, \ - _storagebits, _shift, _extend_name, _type) \ - { \ - .type = (_type), \ - .differential = (_channel2 == -1 ? 0 : 1), \ - .indexed = 1, \ - .channel = (_channel1), \ - .channel2 = (_channel2), \ - .address = (_address), \ - .extend_name = (_extend_name), \ - .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \ - IIO_CHAN_INFO_SCALE_SHARED_BIT | \ - IIO_CHAN_INFO_OFFSET_SEPARATE_BIT, \ - .scan_index = (_si), \ - .scan_type = { \ - .sign = 'u', \ - .realbits = (_bits), \ - .storagebits = (_storagebits), \ - .shift = (_shift), \ - .endianness = IIO_BE, \ - }, \ - } - -#define AD_SD_DIFF_CHANNEL(_si, _channel1, _channel2, _address, _bits, \ - _storagebits, _shift) \ - __AD_SD_CHANNEL(_si, _channel1, _channel2, _address, _bits, \ - _storagebits, _shift, NULL, IIO_VOLTAGE) - -#define AD_SD_SHORTED_CHANNEL(_si, _channel, _address, _bits, \ - _storagebits, _shift) \ - __AD_SD_CHANNEL(_si, _channel, _channel, _address, _bits, \ - _storagebits, _shift, "shorted", IIO_VOLTAGE) - -#define AD_SD_CHANNEL(_si, _channel, _address, _bits, \ - _storagebits, _shift) \ - __AD_SD_CHANNEL(_si, _channel, -1, _address, _bits, \ - _storagebits, _shift, NULL, IIO_VOLTAGE) - -#define AD_SD_TEMP_CHANNEL(_si, _address, _bits, _storagebits, _shift) \ - __AD_SD_CHANNEL(_si, 0, -1, _address, _bits, \ - _storagebits, _shift, NULL, IIO_TEMP) - -#define AD_SD_SUPPLY_CHANNEL(_si, _channel, _address, _bits, _storagebits, \ - _shift) \ - __AD_SD_CHANNEL(_si, _channel, -1, _address, _bits, \ - _storagebits, _shift, "supply", IIO_VOLTAGE) - -#endif diff --git a/trunk/include/linux/iio/buffer.h b/trunk/include/linux/iio/buffer.h index c629b3a1d9a9..8ba516fc2ec6 100644 --- a/trunk/include/linux/iio/buffer.h +++ b/trunk/include/linux/iio/buffer.h @@ -36,7 +36,7 @@ struct iio_buffer; * any of them not existing. **/ struct iio_buffer_access_funcs { - int (*store_to)(struct iio_buffer *buffer, u8 *data); + int (*store_to)(struct iio_buffer *buffer, u8 *data, s64 timestamp); int (*read_first_n)(struct iio_buffer *buffer, size_t n, char __user *buf); @@ -118,8 +118,10 @@ int iio_scan_mask_set(struct iio_dev *indio_dev, * iio_push_to_buffer() - push to a registered buffer. * @buffer: IIO buffer structure for device * @data: the data to push to the buffer + * @timestamp: timestamp to associate with the data */ -int iio_push_to_buffer(struct iio_buffer *buffer, unsigned char *data); +int iio_push_to_buffer(struct iio_buffer *buffer, unsigned char *data, + s64 timestamp); int iio_update_demux(struct iio_dev *indio_dev); diff --git a/trunk/include/linux/iio/consumer.h b/trunk/include/linux/iio/consumer.h index e875bcf0478f..e2657e6d4d26 100644 --- a/trunk/include/linux/iio/consumer.h +++ b/trunk/include/linux/iio/consumer.h @@ -8,7 +8,7 @@ * the Free Software Foundation. */ #ifndef _IIO_INKERN_CONSUMER_H_ -#define _IIO_INKERN_CONSUMER_H_ +#define _IIO_INKERN_CONSUMER_H #include struct iio_dev; @@ -61,7 +61,7 @@ void iio_channel_release_all(struct iio_channel *chan); /** * iio_read_channel_raw() - read from a given channel - * @chan: The channel being queried. + * @channel: The channel being queried. * @val: Value read back. * * Note raw reads from iio channels are in adc counts and hence @@ -70,21 +70,6 @@ void iio_channel_release_all(struct iio_channel *chan); int iio_read_channel_raw(struct iio_channel *chan, int *val); -/** - * iio_read_channel_processed() - read processed value from a given channel - * @chan: The channel being queried. - * @val: Value read back. - * - * Returns an error code or 0. - * - * This function will read a processed value from a channel. A processed value - * means that this value will have the correct unit and not some device internal - * representation. If the device does not support reporting a processed value - * the function will query the raw value and the channels scale and offset and - * do the appropriate transformation. - */ -int iio_read_channel_processed(struct iio_channel *chan, int *val); - /** * iio_get_channel_type() - get the type of a channel * @channel: The channel being queried. @@ -97,7 +82,7 @@ int iio_get_channel_type(struct iio_channel *channel, /** * iio_read_channel_scale() - read the scale value for a channel - * @chan: The channel being queried. + * @channel: The channel being queried. * @val: First part of value read back. * @val2: Second part of value read back. * @@ -108,27 +93,4 @@ int iio_get_channel_type(struct iio_channel *channel, int iio_read_channel_scale(struct iio_channel *chan, int *val, int *val2); -/** - * iio_convert_raw_to_processed() - Converts a raw value to a processed value - * @chan: The channel being queried - * @raw: The raw IIO to convert - * @processed: The result of the conversion - * @scale: Scale factor to apply during the conversion - * - * Returns an error code or 0. - * - * This function converts a raw value to processed value for a specific channel. - * A raw value is the device internal representation of a sample and the value - * returned by iio_read_channel_raw, so the unit of that value is device - * depended. A processed value on the other hand is value has a normed unit - * according with the IIO specification. - * - * The scale factor allows to increase the precession of the returned value. For - * a scale factor of 1 the function will return the result in the normal IIO - * unit for the channel type. E.g. millivolt for voltage channels, if you want - * nanovolts instead pass 1000 as the scale factor. - */ -int iio_convert_raw_to_processed(struct iio_channel *chan, int raw, - int *processed, unsigned int scale); - #endif diff --git a/trunk/include/linux/iio/frequency/adf4350.h b/trunk/include/linux/iio/frequency/adf4350.h index be91f344d5fc..b76b4a87065e 100644 --- a/trunk/include/linux/iio/frequency/adf4350.h +++ b/trunk/include/linux/iio/frequency/adf4350.h @@ -87,8 +87,6 @@ #define ADF4350_MAX_BANDSEL_CLK 125000 /* Hz */ #define ADF4350_MAX_FREQ_REFIN 250000000 /* Hz */ #define ADF4350_MAX_MODULUS 4095 -#define ADF4350_MAX_R_CNT 1023 - /** * struct adf4350_platform_data - platform specific information diff --git a/trunk/include/linux/iio/iio.h b/trunk/include/linux/iio/iio.h index c0ae76ac4e0b..be82936c4089 100644 --- a/trunk/include/linux/iio/iio.h +++ b/trunk/include/linux/iio/iio.h @@ -35,13 +35,10 @@ enum iio_chan_info_enum { IIO_CHAN_INFO_FREQUENCY, IIO_CHAN_INFO_PHASE, IIO_CHAN_INFO_HARDWAREGAIN, - IIO_CHAN_INFO_HYSTERESIS, }; #define IIO_CHAN_INFO_SHARED_BIT(type) BIT(type*2) #define IIO_CHAN_INFO_SEPARATE_BIT(type) BIT(type*2 + 1) -#define IIO_CHAN_INFO_BITS(type) (IIO_CHAN_INFO_SHARED_BIT(type) | \ - IIO_CHAN_INFO_SEPARATE_BIT(type)) #define IIO_CHAN_INFO_RAW_SEPARATE_BIT \ IIO_CHAN_INFO_SEPARATE_BIT(IIO_CHAN_INFO_RAW) @@ -103,10 +100,6 @@ enum iio_chan_info_enum { IIO_CHAN_INFO_SEPARATE_BIT(IIO_CHAN_INFO_HARDWAREGAIN) #define IIO_CHAN_INFO_HARDWAREGAIN_SHARED_BIT \ IIO_CHAN_INFO_SHARED_BIT(IIO_CHAN_INFO_HARDWAREGAIN) -#define IIO_CHAN_INFO_HYSTERESIS_SEPARATE_BIT \ - IIO_CHAN_INFO_SEPARATE_BIT(IIO_CHAN_INFO_HYSTERESIS) -#define IIO_CHAN_INFO_HYSTERESIS_SHARED_BIT \ - IIO_CHAN_INFO_SHARED_BIT(IIO_CHAN_INFO_HYSTERESIS) enum iio_endian { IIO_CPU, @@ -171,7 +164,7 @@ ssize_t iio_enum_write(struct iio_dev *indio_dev, * IIO_ENUM() - Initialize enum extended channel attribute * @_name: Attribute name * @_shared: Whether the attribute is shared between all channels - * @_e: Pointer to an iio_enum struct + * @_e: Pointer to a iio_enum struct * * This should usually be used together with IIO_ENUM_AVAILABLE() */ @@ -187,9 +180,9 @@ ssize_t iio_enum_write(struct iio_dev *indio_dev, /** * IIO_ENUM_AVAILABLE() - Initialize enum available extended channel attribute * @_name: Attribute name ("_available" will be appended to the name) - * @_e: Pointer to an iio_enum struct + * @_e: Pointer to a iio_enum struct * - * Creates a read only attribute which lists all the available enum items in a + * Creates a read only attribute which list all the available enum items in a * space separated list. This should usually be used together with IIO_ENUM() */ #define IIO_ENUM_AVAILABLE(_name, _e) \ @@ -236,7 +229,6 @@ ssize_t iio_enum_write(struct iio_dev *indio_dev, * @indexed: Specify the channel has a numerical index. If not, * the channel index number will be suppressed for sysfs * attributes but not for event codes. - * @output: Channel is output. * @differential: Channel is differential. */ struct iio_chan_spec { @@ -263,21 +255,6 @@ struct iio_chan_spec { unsigned differential:1; }; - -/** - * iio_channel_has_info() - Checks whether a channel supports a info attribute - * @chan: The channel to be queried - * @type: Type of the info attribute to be checked - * - * Returns true if the channels supports reporting values for the given info - * attribute type, false otherwise. - */ -static inline bool iio_channel_has_info(const struct iio_chan_spec *chan, - enum iio_chan_info_enum type) -{ - return chan->info_mask & IIO_CHAN_INFO_BITS(type); -} - #define IIO_ST(si, rb, sb, sh) \ { .sign = si, .realbits = rb, .storagebits = sb, .shift = sh } @@ -335,9 +312,6 @@ struct iio_dev; * Meaning is event dependent. * @validate_trigger: function to validate the trigger when the * current trigger gets changed. - * @update_scan_mode: function to configure device and scan buffer when - * channels have changed - * @debugfs_reg_access: function to read or write register value of device **/ struct iio_info { struct module *driver_module; @@ -393,10 +367,10 @@ struct iio_info { * scan mask is valid for the device. */ struct iio_buffer_setup_ops { - int (*preenable)(struct iio_dev *); - int (*postenable)(struct iio_dev *); - int (*predisable)(struct iio_dev *); - int (*postdisable)(struct iio_dev *); + int (*preenable)(struct iio_dev *); + int (*postenable)(struct iio_dev *); + int (*predisable)(struct iio_dev *); + int (*postdisable)(struct iio_dev *); bool (*validate_scan_mask)(struct iio_dev *indio_dev, const unsigned long *scan_mask); }; @@ -542,31 +516,6 @@ static inline struct iio_dev *iio_device_get(struct iio_dev *indio_dev) return indio_dev ? dev_to_iio_dev(get_device(&indio_dev->dev)) : NULL; } - -/** - * iio_device_set_drvdata() - Set device driver data - * @indio_dev: IIO device structure - * @data: Driver specific data - * - * Allows to attach an arbitrary pointer to an IIO device, which can later be - * retrieved by iio_device_get_drvdata(). - */ -static inline void iio_device_set_drvdata(struct iio_dev *indio_dev, void *data) -{ - dev_set_drvdata(&indio_dev->dev, data); -} - -/** - * iio_device_get_drvdata() - Get device driver data - * @indio_dev: IIO device structure - * - * Returns the data previously set with iio_device_set_drvdata() - */ -static inline void *iio_device_get_drvdata(struct iio_dev *indio_dev) -{ - return dev_get_drvdata(&indio_dev->dev); -} - /* Can we make this smaller? */ #define IIO_ALIGN L1_CACHE_BYTES /** diff --git a/trunk/include/linux/iio/kfifo_buf.h b/trunk/include/linux/iio/kfifo_buf.h index 25eeac762e84..014d5a13b32b 100644 --- a/trunk/include/linux/iio/kfifo_buf.h +++ b/trunk/include/linux/iio/kfifo_buf.h @@ -1,5 +1,3 @@ -#ifndef __LINUX_IIO_KFIFO_BUF_H__ -#define __LINUX_IIO_KFIFO_BUF_H__ #include #include @@ -8,4 +6,3 @@ struct iio_buffer *iio_kfifo_allocate(struct iio_dev *indio_dev); void iio_kfifo_free(struct iio_buffer *r); -#endif diff --git a/trunk/include/linux/iio/machine.h b/trunk/include/linux/iio/machine.h index 809a3f08d5a5..400a453ff67b 100644 --- a/trunk/include/linux/iio/machine.h +++ b/trunk/include/linux/iio/machine.h @@ -8,9 +8,6 @@ * the Free Software Foundation. */ -#ifndef __LINUX_IIO_MACHINE_H__ -#define __LINUX_IIO_MACHINE_H__ - /** * struct iio_map - description of link between consumer and device channels * @adc_channel_label: Label used to identify the channel on the provider. @@ -25,5 +22,3 @@ struct iio_map { const char *consumer_dev_name; const char *consumer_channel; }; - -#endif diff --git a/trunk/include/linux/iio/trigger.h b/trunk/include/linux/iio/trigger.h index 20239da1d0f7..a9819940a84c 100644 --- a/trunk/include/linux/iio/trigger.h +++ b/trunk/include/linux/iio/trigger.h @@ -29,7 +29,7 @@ struct iio_subirq { * instances of a given device. **/ struct iio_trigger_ops { - struct module *owner; + struct module *owner; int (*set_trigger_state)(struct iio_trigger *trig, bool state); int (*try_reenable)(struct iio_trigger *trig); int (*validate_device)(struct iio_trigger *trig, @@ -39,7 +39,7 @@ struct iio_trigger_ops { /** * struct iio_trigger - industrial I/O trigger device - * @ops: [DRIVER] operations structure + * * @id: [INTERN] unique id number * @name: [DRIVER] unique name * @dev: [DRIVER] associated device (if relevant) @@ -76,19 +76,19 @@ struct iio_trigger { static inline struct iio_trigger *to_iio_trigger(struct device *d) { return container_of(d, struct iio_trigger, dev); -} +}; static inline void iio_trigger_put(struct iio_trigger *trig) { module_put(trig->ops->owner); put_device(&trig->dev); -} +}; static inline void iio_trigger_get(struct iio_trigger *trig) { get_device(&trig->dev); __module_get(trig->ops->owner); -} +}; /** * iio_trigger_register() - register a trigger with the IIO core @@ -104,8 +104,7 @@ void iio_trigger_unregister(struct iio_trigger *trig_info); /** * iio_trigger_poll() - called on a trigger occurring - * @trig: trigger which occurred - * @time: timestamp when trigger occurred + * @trig: trigger which occurred * * Typically called in relevant hardware interrupt handler. **/ diff --git a/trunk/include/linux/iio/trigger_consumer.h b/trunk/include/linux/iio/trigger_consumer.h index c4f8c7409666..60d64b356945 100644 --- a/trunk/include/linux/iio/trigger_consumer.h +++ b/trunk/include/linux/iio/trigger_consumer.h @@ -7,15 +7,6 @@ * the Free Software Foundation. */ -#ifndef __LINUX_IIO_TRIGGER_CONSUMER_H__ -#define __LINUX_IIO_TRIGGER_CONSUMER_H__ - -#include -#include - -struct iio_dev; -struct iio_trigger; - /** * struct iio_poll_func - poll function pair * @@ -59,5 +50,3 @@ void iio_trigger_notify_done(struct iio_trigger *trig); */ int iio_triggered_buffer_postenable(struct iio_dev *indio_dev); int iio_triggered_buffer_predisable(struct iio_dev *indio_dev); - -#endif diff --git a/trunk/include/linux/iio/types.h b/trunk/include/linux/iio/types.h index 5c647ecfd5ba..44e397705d7f 100644 --- a/trunk/include/linux/iio/types.h +++ b/trunk/include/linux/iio/types.h @@ -57,6 +57,5 @@ enum iio_modifier { #define IIO_VAL_INT_PLUS_MICRO 2 #define IIO_VAL_INT_PLUS_NANO 3 #define IIO_VAL_INT_PLUS_MICRO_DB 4 -#define IIO_VAL_FRACTIONAL 10 #endif /* _IIO_TYPES_H_ */ diff --git a/trunk/include/linux/input.h b/trunk/include/linux/input.h index ba4874302939..725dcd0f63a4 100644 --- a/trunk/include/linux/input.h +++ b/trunk/include/linux/input.h @@ -1168,18 +1168,6 @@ struct ff_effect { #include #include -/** - * struct input_value - input value representation - * @type: type of value (EV_KEY, EV_ABS, etc) - * @code: the value code - * @value: the value - */ -struct input_value { - __u16 type; - __u16 code; - __s32 value; -}; - /** * struct input_dev - represents an input device * @name: name of the device @@ -1215,7 +1203,11 @@ struct input_value { * software autorepeat * @timer: timer for software autorepeat * @rep: current values for autorepeat parameters (delay, rate) - * @mt: pointer to multitouch state + * @mt: pointer to array of struct input_mt_slot holding current values + * of tracked contacts + * @mtsize: number of MT slots the device uses + * @slot: MT slot currently being transmitted + * @trkid: stores MT tracking ID for the current contact * @absinfo: array of &struct input_absinfo elements holding information * about absolute axes (current value, min, max, flat, fuzz, * resolution) @@ -1252,6 +1244,7 @@ struct input_value { * last user closes the device * @going_away: marks devices that are in a middle of unregistering and * causes input_open_device*() fail with -ENODEV. + * @sync: set to %true when there were no new events since last EV_SYN * @dev: driver model's view of this device * @h_list: list of input handles associated with the device. When * accessing the list dev->mutex must be held @@ -1294,7 +1287,10 @@ struct input_dev { int rep[REP_CNT]; - struct input_mt *mt; + struct input_mt_slot *mt; + int mtsize; + int slot; + int trkid; struct input_absinfo *absinfo; @@ -1316,14 +1312,12 @@ struct input_dev { unsigned int users; bool going_away; + bool sync; + struct device dev; struct list_head h_list; struct list_head node; - - unsigned int num_vals; - unsigned int max_vals; - struct input_value *vals; }; #define to_input_dev(d) container_of(d, struct input_dev, dev) @@ -1384,9 +1378,6 @@ struct input_handle; * @event: event handler. This method is being called by input core with * interrupts disabled and dev->event_lock spinlock held and so * it may not sleep - * @events: event sequence handler. This method is being called by - * input core with interrupts disabled and dev->event_lock - * spinlock held and so it may not sleep * @filter: similar to @event; separates normal event handlers from * "filters". * @match: called after comparing device's id with handler's id_table @@ -1423,8 +1414,6 @@ struct input_handler { void *private; void (*event)(struct input_handle *handle, unsigned int type, unsigned int code, int value); - void (*events)(struct input_handle *handle, - const struct input_value *vals, unsigned int count); bool (*filter)(struct input_handle *handle, unsigned int type, unsigned int code, int value); bool (*match)(struct input_handler *handler, struct input_dev *dev); int (*connect)(struct input_handler *handler, struct input_dev *dev, const struct input_device_id *id); diff --git a/trunk/include/linux/input/eeti_ts.h b/trunk/include/linux/input/eeti_ts.h index 16625d799b6f..f875b316249d 100644 --- a/trunk/include/linux/input/eeti_ts.h +++ b/trunk/include/linux/input/eeti_ts.h @@ -2,7 +2,6 @@ #define LINUX_INPUT_EETI_TS_H struct eeti_ts_platform_data { - int irq_gpio; unsigned int irq_active_high; }; diff --git a/trunk/include/linux/input/mt.h b/trunk/include/linux/input/mt.h index cc5cca774bab..f86737586e19 100644 --- a/trunk/include/linux/input/mt.h +++ b/trunk/include/linux/input/mt.h @@ -15,41 +15,12 @@ #define TRKID_MAX 0xffff -#define INPUT_MT_POINTER 0x0001 /* pointer device, e.g. trackpad */ -#define INPUT_MT_DIRECT 0x0002 /* direct device, e.g. touchscreen */ -#define INPUT_MT_DROP_UNUSED 0x0004 /* drop contacts not seen in frame */ -#define INPUT_MT_TRACK 0x0008 /* use in-kernel tracking */ - /** * struct input_mt_slot - represents the state of an input MT slot * @abs: holds current values of ABS_MT axes for this slot - * @frame: last frame at which input_mt_report_slot_state() was called - * @key: optional driver designation of this slot */ struct input_mt_slot { int abs[ABS_MT_LAST - ABS_MT_FIRST + 1]; - unsigned int frame; - unsigned int key; -}; - -/** - * struct input_mt - state of tracked contacts - * @trkid: stores MT tracking ID for the next contact - * @num_slots: number of MT slots the device uses - * @slot: MT slot currently being transmitted - * @flags: input_mt operation flags - * @frame: increases every time input_mt_sync_frame() is called - * @red: reduced cost matrix for in-kernel tracking - * @slots: array of slots holding current values of tracked contacts - */ -struct input_mt { - int trkid; - int num_slots; - int slot; - unsigned int flags; - unsigned int frame; - int *red; - struct input_mt_slot slots[]; }; static inline void input_mt_set_value(struct input_mt_slot *slot, @@ -64,18 +35,12 @@ static inline int input_mt_get_value(const struct input_mt_slot *slot, return slot->abs[code - ABS_MT_FIRST]; } -static inline bool input_mt_is_active(const struct input_mt_slot *slot) -{ - return input_mt_get_value(slot, ABS_MT_TRACKING_ID) >= 0; -} - -int input_mt_init_slots(struct input_dev *dev, unsigned int num_slots, - unsigned int flags); +int input_mt_init_slots(struct input_dev *dev, unsigned int num_slots); void input_mt_destroy_slots(struct input_dev *dev); -static inline int input_mt_new_trkid(struct input_mt *mt) +static inline int input_mt_new_trkid(struct input_dev *dev) { - return mt->trkid++ & TRKID_MAX; + return dev->trkid++ & TRKID_MAX; } static inline void input_mt_slot(struct input_dev *dev, int slot) @@ -99,20 +64,4 @@ void input_mt_report_slot_state(struct input_dev *dev, void input_mt_report_finger_count(struct input_dev *dev, int count); void input_mt_report_pointer_emulation(struct input_dev *dev, bool use_count); -void input_mt_sync_frame(struct input_dev *dev); - -/** - * struct input_mt_pos - contact position - * @x: horizontal coordinate - * @y: vertical coordinate - */ -struct input_mt_pos { - s16 x, y; -}; - -int input_mt_assign_slots(struct input_dev *dev, int *slots, - const struct input_mt_pos *pos, int num_pos); - -int input_mt_get_slot_by_key(struct input_dev *dev, int key); - #endif diff --git a/trunk/include/linux/interrupt.h b/trunk/include/linux/interrupt.h index 5e4e6170f43a..c5f856a040b9 100644 --- a/trunk/include/linux/interrupt.h +++ b/trunk/include/linux/interrupt.h @@ -430,8 +430,6 @@ enum NR_SOFTIRQS }; -#define SOFTIRQ_STOP_IDLE_MASK (~(1 << RCU_SOFTIRQ)) - /* map softirq index to softirq name. update 'softirq_to_name' in * kernel/softirq.c when adding a new softirq. */ diff --git a/trunk/include/linux/iommu.h b/trunk/include/linux/iommu.h index f3b99e1c1042..54d6d690073c 100644 --- a/trunk/include/linux/iommu.h +++ b/trunk/include/linux/iommu.h @@ -20,7 +20,6 @@ #define __LINUX_IOMMU_H #include -#include #define IOMMU_READ (1) #define IOMMU_WRITE (2) @@ -31,7 +30,6 @@ struct iommu_group; struct bus_type; struct device; struct iommu_domain; -struct notifier_block; /* iommu fault flags */ #define IOMMU_FAULT_READ 0x0 @@ -256,78 +254,72 @@ static inline void iommu_set_fault_handler(struct iommu_domain *domain, { } -static inline int iommu_attach_group(struct iommu_domain *domain, - struct iommu_group *group) +int iommu_attach_group(struct iommu_domain *domain, struct iommu_group *group) { return -ENODEV; } -static inline void iommu_detach_group(struct iommu_domain *domain, - struct iommu_group *group) +void iommu_detach_group(struct iommu_domain *domain, struct iommu_group *group) { } -static inline struct iommu_group *iommu_group_alloc(void) +struct iommu_group *iommu_group_alloc(void) { return ERR_PTR(-ENODEV); } -static inline void *iommu_group_get_iommudata(struct iommu_group *group) +void *iommu_group_get_iommudata(struct iommu_group *group) { return NULL; } -static inline void iommu_group_set_iommudata(struct iommu_group *group, - void *iommu_data, - void (*release)(void *iommu_data)) +void iommu_group_set_iommudata(struct iommu_group *group, void *iommu_data, + void (*release)(void *iommu_data)) { } -static inline int iommu_group_set_name(struct iommu_group *group, - const char *name) +int iommu_group_set_name(struct iommu_group *group, const char *name) { return -ENODEV; } -static inline int iommu_group_add_device(struct iommu_group *group, - struct device *dev) +int iommu_group_add_device(struct iommu_group *group, struct device *dev) { return -ENODEV; } -static inline void iommu_group_remove_device(struct device *dev) +void iommu_group_remove_device(struct device *dev) { } -static inline int iommu_group_for_each_dev(struct iommu_group *group, - void *data, - int (*fn)(struct device *, void *)) +int iommu_group_for_each_dev(struct iommu_group *group, void *data, + int (*fn)(struct device *, void *)) { return -ENODEV; } -static inline struct iommu_group *iommu_group_get(struct device *dev) +struct iommu_group *iommu_group_get(struct device *dev) { return NULL; } -static inline void iommu_group_put(struct iommu_group *group) +void iommu_group_put(struct iommu_group *group) { } -static inline int iommu_group_register_notifier(struct iommu_group *group, - struct notifier_block *nb) +int iommu_group_register_notifier(struct iommu_group *group, + struct notifier_block *nb) { return -ENODEV; } -static inline int iommu_group_unregister_notifier(struct iommu_group *group, - struct notifier_block *nb) +int iommu_group_unregister_notifier(struct iommu_group *group, + struct notifier_block *nb) { return 0; } -static inline int iommu_group_id(struct iommu_group *group) +int iommu_group_id(struct iommu_group *group) { return -ENODEV; } diff --git a/trunk/include/linux/ipv6.h b/trunk/include/linux/ipv6.h index 879db26ec401..379e433e15e0 100644 --- a/trunk/include/linux/ipv6.h +++ b/trunk/include/linux/ipv6.h @@ -369,7 +369,6 @@ struct ipv6_pinfo { __u8 rcv_tclass; __u32 dst_cookie; - __u32 rx_dst_cookie; struct ipv6_mc_socklist __rcu *ipv6_mc_list; struct ipv6_ac_socklist *ipv6_ac_list; diff --git a/trunk/include/linux/irq.h b/trunk/include/linux/irq.h index 216b0ba109d7..553fb66da130 100644 --- a/trunk/include/linux/irq.h +++ b/trunk/include/linux/irq.h @@ -349,7 +349,6 @@ enum { IRQCHIP_MASK_ON_SUSPEND = (1 << 2), IRQCHIP_ONOFFLINE_ENABLED = (1 << 3), IRQCHIP_SKIP_SET_WAKE = (1 << 4), - IRQCHIP_ONESHOT_SAFE = (1 << 5), }; /* This include will go away once we isolated irq_desc usage to core code */ diff --git a/trunk/include/linux/irqdesc.h b/trunk/include/linux/irqdesc.h index 0ba014c55056..9a323d12de1c 100644 --- a/trunk/include/linux/irqdesc.h +++ b/trunk/include/linux/irqdesc.h @@ -10,10 +10,12 @@ struct irq_affinity_notify; struct proc_dir_entry; +struct timer_rand_state; struct module; /** * struct irq_desc - interrupt descriptor * @irq_data: per irq and chip data passed down to chip functions + * @timer_rand_state: pointer to timer rand state struct * @kstat_irqs: irq stats per cpu * @handle_irq: highlevel irq-events handler * @preflow_handler: handler called before the flow handler (currently used by sparc) diff --git a/trunk/include/linux/istallion.h b/trunk/include/linux/istallion.h new file mode 100644 index 000000000000..ad700a60c158 --- /dev/null +++ b/trunk/include/linux/istallion.h @@ -0,0 +1,123 @@ +/*****************************************************************************/ + +/* + * istallion.h -- stallion intelligent multiport serial driver. + * + * Copyright (C) 1996-1998 Stallion Technologies + * Copyright (C) 1994-1996 Greg Ungerer. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/*****************************************************************************/ +#ifndef _ISTALLION_H +#define _ISTALLION_H +/*****************************************************************************/ + +/* + * Define important driver constants here. + */ +#define STL_MAXBRDS 4 +#define STL_MAXPANELS 4 +#define STL_MAXPORTS 64 +#define STL_MAXCHANS (STL_MAXPORTS + 1) +#define STL_MAXDEVS (STL_MAXBRDS * STL_MAXPORTS) + + +/* + * Define a set of structures to hold all the board/panel/port info + * for our ports. These will be dynamically allocated as required at + * driver initialization time. + */ + +/* + * Port and board structures to hold status info about each object. + * The board structure contains pointers to structures for each port + * connected to it. Panels are not distinguished here, since + * communication with the slave board will always be on a per port + * basis. + */ +struct stliport { + unsigned long magic; + struct tty_port port; + unsigned int portnr; + unsigned int panelnr; + unsigned int brdnr; + unsigned long state; + unsigned int devnr; + int baud_base; + int custom_divisor; + int closing_wait; + int rc; + int argsize; + void *argp; + unsigned int rxmarkmsk; + wait_queue_head_t raw_wait; + struct asysigs asig; + unsigned long addr; + unsigned long rxoffset; + unsigned long txoffset; + unsigned long sigs; + unsigned long pflag; + unsigned int rxsize; + unsigned int txsize; + unsigned char reqbit; + unsigned char portidx; + unsigned char portbit; +}; + +/* + * Use a structure of function pointers to do board level operations. + * These include, enable/disable, paging shared memory, interrupting, etc. + */ +struct stlibrd { + unsigned long magic; + unsigned int brdnr; + unsigned int brdtype; + unsigned long state; + unsigned int nrpanels; + unsigned int nrports; + unsigned int nrdevs; + unsigned int iobase; + int iosize; + unsigned long memaddr; + void __iomem *membase; + unsigned long memsize; + int pagesize; + int hostoffset; + int slaveoffset; + int bitsize; + int enabval; + unsigned int panels[STL_MAXPANELS]; + int panelids[STL_MAXPANELS]; + void (*init)(struct stlibrd *brdp); + void (*enable)(struct stlibrd *brdp); + void (*reenable)(struct stlibrd *brdp); + void (*disable)(struct stlibrd *brdp); + void __iomem *(*getmemptr)(struct stlibrd *brdp, unsigned long offset, int line); + void (*intr)(struct stlibrd *brdp); + void (*reset)(struct stlibrd *brdp); + struct stliport *ports[STL_MAXPORTS]; +}; + + +/* + * Define MAGIC numbers used for above structures. + */ +#define STLI_PORTMAGIC 0xe671c7a1 +#define STLI_BOARDMAGIC 0x4bc6c825 + +/*****************************************************************************/ +#endif diff --git a/trunk/include/linux/jbd2.h b/trunk/include/linux/jbd2.h index 3efc43f3f162..f334c7fab967 100644 --- a/trunk/include/linux/jbd2.h +++ b/trunk/include/linux/jbd2.h @@ -1125,7 +1125,6 @@ extern int jbd2_journal_destroy (journal_t *); extern int jbd2_journal_recover (journal_t *journal); extern int jbd2_journal_wipe (journal_t *, int); extern int jbd2_journal_skip_recovery (journal_t *); -extern void jbd2_journal_update_sb_errno(journal_t *); extern void jbd2_journal_update_sb_log_tail (journal_t *, tid_t, unsigned long, int); extern void __jbd2_journal_abort_hard (journal_t *); diff --git a/trunk/include/linux/jiffies.h b/trunk/include/linux/jiffies.h index 82680541576d..265e2c3cbd1c 100644 --- a/trunk/include/linux/jiffies.h +++ b/trunk/include/linux/jiffies.h @@ -39,6 +39,9 @@ # error Invalid value of HZ. #endif +/* LATCH is used in the interval timer and ftape setup. */ +#define LATCH ((CLOCK_TICK_RATE + HZ/2) / HZ) /* For divider */ + /* Suppose we want to divide two numbers NOM and DEN: NOM/DEN, then we can * improve accuracy by shifting LSH bits, hence calculating: * (NOM << LSH) / DEN @@ -51,30 +54,18 @@ #define SH_DIV(NOM,DEN,LSH) ( (((NOM) / (DEN)) << (LSH)) \ + ((((NOM) % (DEN)) << (LSH)) + (DEN) / 2) / (DEN)) -#ifdef CLOCK_TICK_RATE -/* LATCH is used in the interval timer and ftape setup. */ -# define LATCH ((CLOCK_TICK_RATE + HZ/2) / HZ) /* For divider */ - -/* - * HZ is the requested value. However the CLOCK_TICK_RATE may not allow - * for exactly HZ. So SHIFTED_HZ is high res HZ ("<< 8" is for accuracy) - */ -# define SHIFTED_HZ (SH_DIV(CLOCK_TICK_RATE, LATCH, 8)) -#else -# define SHIFTED_HZ (HZ << 8) -#endif +/* HZ is the requested value. ACTHZ is actual HZ ("<< 8" is for accuracy) */ +#define ACTHZ (SH_DIV (CLOCK_TICK_RATE, LATCH, 8)) -/* TICK_NSEC is the time between ticks in nsec assuming SHIFTED_HZ */ -#define TICK_NSEC (SH_DIV(1000000UL * 1000, SHIFTED_HZ, 8)) +/* TICK_NSEC is the time between ticks in nsec assuming real ACTHZ */ +#define TICK_NSEC (SH_DIV (1000000UL * 1000, ACTHZ, 8)) /* TICK_USEC is the time between ticks in usec assuming fake USER_HZ */ #define TICK_USEC ((1000000UL + USER_HZ/2) / USER_HZ) -/* - * TICK_USEC_TO_NSEC is the time between ticks in nsec assuming SHIFTED_HZ and - * a value TUSEC for TICK_USEC (can be set bij adjtimex) - */ -#define TICK_USEC_TO_NSEC(TUSEC) (SH_DIV(TUSEC * USER_HZ * 1000, SHIFTED_HZ, 8)) +/* TICK_USEC_TO_NSEC is the time between ticks in nsec assuming real ACTHZ and */ +/* a value TUSEC for TICK_USEC (can be set bij adjtimex) */ +#define TICK_USEC_TO_NSEC(TUSEC) (SH_DIV (TUSEC * USER_HZ * 1000, ACTHZ, 8)) /* some arch's have a small-data section that can be accessed register-relative * but that can only take up to, say, 4-byte variables. jiffies being part of diff --git a/trunk/include/linux/kbd_kern.h b/trunk/include/linux/kbd_kern.h index b7c8cdc1d422..daf4a3a40ee0 100644 --- a/trunk/include/linux/kbd_kern.h +++ b/trunk/include/linux/kbd_kern.h @@ -65,6 +65,7 @@ struct kbd_struct { extern int kbd_init(void); +extern unsigned char getledstate(void); extern void setledstate(struct kbd_struct *kbd, unsigned int led); extern int do_poke_blanked_console; @@ -144,4 +145,16 @@ void compute_shiftstate(void); extern unsigned int keymap_count; +/* console.c */ + +static inline void con_schedule_flip(struct tty_struct *t) +{ + unsigned long flags; + spin_lock_irqsave(&t->buf.lock, flags); + if (t->buf.tail != NULL) + t->buf.tail->commit = t->buf.tail->used; + spin_unlock_irqrestore(&t->buf.lock, flags); + schedule_work(&t->buf.work); +} + #endif diff --git a/trunk/include/linux/kdb.h b/trunk/include/linux/kdb.h index 7f6fe6e015bc..064725854db8 100644 --- a/trunk/include/linux/kdb.h +++ b/trunk/include/linux/kdb.h @@ -13,14 +13,6 @@ * Copyright (C) 2009 Jason Wessel */ -typedef enum { - KDB_REPEAT_NONE = 0, /* Do not repeat this command */ - KDB_REPEAT_NO_ARGS, /* Repeat the command without arguments */ - KDB_REPEAT_WITH_ARGS, /* Repeat the command including its arguments */ -} kdb_repeat_t; - -typedef int (*kdb_func_t)(int, const char **); - #ifdef CONFIG_KGDB_KDB #include #include @@ -40,6 +32,14 @@ extern atomic_t kdb_event; #define KDB_MAXARGS 16 /* Maximum number of arguments to a function */ +typedef enum { + KDB_REPEAT_NONE = 0, /* Do not repeat this command */ + KDB_REPEAT_NO_ARGS, /* Repeat the command without arguments */ + KDB_REPEAT_WITH_ARGS, /* Repeat the command including its arguments */ +} kdb_repeat_t; + +typedef int (*kdb_func_t)(int, const char **); + /* KDB return codes from a command or internal kdb function */ #define KDB_NOTFOUND (-1) #define KDB_ARGCOUNT (-2) @@ -75,6 +75,8 @@ extern const char *kdb_diemsg; #define KDB_FLAG_CATASTROPHIC (1 << 1) /* A catastrophic event has occurred */ #define KDB_FLAG_CMD_INTERRUPT (1 << 2) /* Previous command was interrupted */ #define KDB_FLAG_NOIPI (1 << 3) /* Do not send IPIs */ +#define KDB_FLAG_ONLY_DO_DUMP (1 << 4) /* Only do a dump, used when + * kdb is off */ #define KDB_FLAG_NO_CONSOLE (1 << 5) /* No console is available, * kdb is disabled */ #define KDB_FLAG_NO_VT_CONSOLE (1 << 6) /* No VT console is available, do @@ -149,14 +151,11 @@ extern int kdb_register_repeat(char *, kdb_func_t, char *, char *, short, kdb_repeat_t); extern int kdb_unregister(char *); #else /* ! CONFIG_KGDB_KDB */ -static inline __printf(1, 2) int kdb_printf(const char *fmt, ...) { return 0; } -static inline void kdb_init(int level) {} -static inline int kdb_register(char *cmd, kdb_func_t func, char *usage, - char *help, short minlen) { return 0; } -static inline int kdb_register_repeat(char *cmd, kdb_func_t func, char *usage, - char *help, short minlen, - kdb_repeat_t repeat) { return 0; } -static inline int kdb_unregister(char *cmd) { return 0; } +#define kdb_printf(...) +#define kdb_init(x) +#define kdb_register(...) +#define kdb_register_repeat(...) +#define kdb_uregister(x) #endif /* CONFIG_KGDB_KDB */ enum { KDB_NOT_INITIALIZED, diff --git a/trunk/include/linux/kernel.h b/trunk/include/linux/kernel.h index 2451f1f7a1d9..604382143bcf 100644 --- a/trunk/include/linux/kernel.h +++ b/trunk/include/linux/kernel.h @@ -82,18 +82,10 @@ __x - (__x % (y)); \ } \ ) - -/* - * Divide positive or negative dividend by positive divisor and round - * to closest integer. Result is undefined for negative divisors. - */ #define DIV_ROUND_CLOSEST(x, divisor)( \ { \ - typeof(x) __x = x; \ - typeof(divisor) __d = divisor; \ - (((typeof(x))-1) > 0 || (__x) > 0) ? \ - (((__x) + ((__d) / 2)) / (__d)) : \ - (((__x) - ((__d) / 2)) / (__d)); \ + typeof(divisor) __divisor = divisor; \ + (((x) + ((__divisor) / 2)) / (__divisor)); \ } \ ) diff --git a/trunk/include/linux/kernel_stat.h b/trunk/include/linux/kernel_stat.h index 36d12f0884c3..2fbd9053c2df 100644 --- a/trunk/include/linux/kernel_stat.h +++ b/trunk/include/linux/kernel_stat.h @@ -130,12 +130,4 @@ extern void account_process_tick(struct task_struct *, int user); extern void account_steal_ticks(unsigned long ticks); extern void account_idle_ticks(unsigned long ticks); -#ifdef CONFIG_VIRT_CPU_ACCOUNTING -extern void vtime_task_switch(struct task_struct *prev); -extern void vtime_account_system(struct task_struct *tsk); -extern void vtime_account_idle(struct task_struct *tsk); -#else -static inline void vtime_task_switch(struct task_struct *prev) { } -#endif - #endif /* _LINUX_KERNEL_STAT_H */ diff --git a/trunk/include/linux/kgdb.h b/trunk/include/linux/kgdb.h index 4dff0c6ed58f..c4d2fc194ede 100644 --- a/trunk/include/linux/kgdb.h +++ b/trunk/include/linux/kgdb.h @@ -240,7 +240,6 @@ extern void kgdb_arch_late(void); * hardware breakpoints. * @correct_hw_break: Allow an architecture to specify how to correct the * hardware debug registers. - * @enable_nmi: Manage NMI-triggered entry to KGDB */ struct kgdb_arch { unsigned char gdb_bpt_instr[BREAK_INSTR_SIZE]; @@ -253,8 +252,6 @@ struct kgdb_arch { void (*disable_hw_break)(struct pt_regs *regs); void (*remove_all_hw_break)(void); void (*correct_hw_break)(void); - - void (*enable_nmi)(bool on); }; /** @@ -286,16 +283,6 @@ extern struct kgdb_arch arch_kgdb_ops; extern unsigned long __weak kgdb_arch_pc(int exception, struct pt_regs *regs); -#ifdef CONFIG_SERIAL_KGDB_NMI -extern int kgdb_register_nmi_console(void); -extern int kgdb_unregister_nmi_console(void); -extern bool kgdb_nmi_poll_knock(void); -#else -static inline int kgdb_register_nmi_console(void) { return 0; } -static inline int kgdb_unregister_nmi_console(void) { return 0; } -static inline bool kgdb_nmi_poll_knock(void) { return 1; } -#endif - extern int kgdb_register_io_module(struct kgdb_io *local_kgdb_io_ops); extern void kgdb_unregister_io_module(struct kgdb_io *local_kgdb_io_ops); extern struct kgdb_io *dbg_io_ops; diff --git a/trunk/include/linux/kobject.h b/trunk/include/linux/kobject.h index 1e57449395b1..fc615a97e2d3 100644 --- a/trunk/include/linux/kobject.h +++ b/trunk/include/linux/kobject.h @@ -224,7 +224,7 @@ static inline int kobject_uevent_env(struct kobject *kobj, static inline __printf(2, 3) int add_uevent_var(struct kobj_uevent_env *env, const char *format, ...) -{ return -ENOMEM; } +{ return 0; } static inline int kobject_action_type(const char *buf, size_t count, enum kobject_action *type) diff --git a/trunk/include/linux/kprobes.h b/trunk/include/linux/kprobes.h index 23755ba42abc..b6e1f8c00577 100644 --- a/trunk/include/linux/kprobes.h +++ b/trunk/include/linux/kprobes.h @@ -38,7 +38,6 @@ #include #include #include -#include #ifdef CONFIG_KPROBES #include @@ -49,26 +48,14 @@ #define KPROBE_REENTER 0x00000004 #define KPROBE_HIT_SSDONE 0x00000008 -/* - * If function tracer is enabled and the arch supports full - * passing of pt_regs to function tracing, then kprobes can - * optimize on top of function tracing. - */ -#if defined(CONFIG_FUNCTION_TRACER) && defined(ARCH_SUPPORTS_FTRACE_SAVE_REGS) \ - && defined(ARCH_SUPPORTS_KPROBES_ON_FTRACE) -# define KPROBES_CAN_USE_FTRACE -#endif - /* Attach to insert probes on any functions which should be ignored*/ #define __kprobes __attribute__((__section__(".kprobes.text"))) - #else /* CONFIG_KPROBES */ typedef int kprobe_opcode_t; struct arch_specific_insn { int dummy; }; #define __kprobes - #endif /* CONFIG_KPROBES */ struct kprobe; @@ -141,7 +128,6 @@ struct kprobe { * NOTE: * this flag is only for optimized_kprobe. */ -#define KPROBE_FLAG_FTRACE 8 /* probe is using ftrace */ /* Has this kprobe gone ? */ static inline int kprobe_gone(struct kprobe *p) @@ -160,13 +146,6 @@ static inline int kprobe_optimized(struct kprobe *p) { return p->flags & KPROBE_FLAG_OPTIMIZED; } - -/* Is this kprobe uses ftrace ? */ -static inline int kprobe_ftrace(struct kprobe *p) -{ - return p->flags & KPROBE_FLAG_FTRACE; -} - /* * Special probe type that uses setjmp-longjmp type tricks to resume * execution at a specified entry with a matching prototype corresponding @@ -316,12 +295,6 @@ extern int proc_kprobes_optimization_handler(struct ctl_table *table, #endif #endif /* CONFIG_OPTPROBES */ -#ifdef KPROBES_CAN_USE_FTRACE -extern void kprobe_ftrace_handler(unsigned long ip, unsigned long parent_ip, - struct ftrace_ops *ops, struct pt_regs *regs); -extern int arch_prepare_kprobe_ftrace(struct kprobe *p); -#endif - /* Get the kprobe at this addr (if any) - called with preemption disabled */ struct kprobe *get_kprobe(void *addr); diff --git a/trunk/include/linux/kref.h b/trunk/include/linux/kref.h index 65af6887872f..9c07dcebded7 100644 --- a/trunk/include/linux/kref.h +++ b/trunk/include/linux/kref.h @@ -18,7 +18,6 @@ #include #include #include -#include struct kref { atomic_t refcount; @@ -94,21 +93,4 @@ static inline int kref_put(struct kref *kref, void (*release)(struct kref *kref) { return kref_sub(kref, 1, release); } - -static inline int kref_put_mutex(struct kref *kref, - void (*release)(struct kref *kref), - struct mutex *lock) -{ - WARN_ON(release == NULL); - if (unlikely(!atomic_add_unless(&kref->refcount, -1, 1))) { - mutex_lock(lock); - if (unlikely(!atomic_dec_and_test(&kref->refcount))) { - mutex_unlock(lock); - return 0; - } - release(kref); - return 1; - } - return 0; -} #endif /* _KREF_H_ */ diff --git a/trunk/include/linux/kthread.h b/trunk/include/linux/kthread.h index 8d816646f766..22ccf9dee177 100644 --- a/trunk/include/linux/kthread.h +++ b/trunk/include/linux/kthread.h @@ -14,11 +14,6 @@ struct task_struct *kthread_create_on_node(int (*threadfn)(void *data), kthread_create_on_node(threadfn, data, -1, namefmt, ##arg) -struct task_struct *kthread_create_on_cpu(int (*threadfn)(void *data), - void *data, - unsigned int cpu, - const char *namefmt); - /** * kthread_run - create and wake a thread. * @threadfn: the function to run until signal_pending(current). @@ -39,13 +34,9 @@ struct task_struct *kthread_create_on_cpu(int (*threadfn)(void *data), void kthread_bind(struct task_struct *k, unsigned int cpu); int kthread_stop(struct task_struct *k); -bool kthread_should_stop(void); -bool kthread_should_park(void); +int kthread_should_stop(void); bool kthread_freezable_should_stop(bool *was_frozen); void *kthread_data(struct task_struct *k); -int kthread_park(struct task_struct *k); -void kthread_unpark(struct task_struct *k); -void kthread_parkme(void); int kthreadd(void *unused); extern struct task_struct *kthreadd_task; diff --git a/trunk/include/linux/ktime.h b/trunk/include/linux/ktime.h index 06177ba10a16..603bec2913b0 100644 --- a/trunk/include/linux/ktime.h +++ b/trunk/include/linux/ktime.h @@ -58,6 +58,13 @@ union ktime { typedef union ktime ktime_t; /* Kill this */ +#define KTIME_MAX ((s64)~((u64)1 << 63)) +#if (BITS_PER_LONG == 64) +# define KTIME_SEC_MAX (KTIME_MAX / NSEC_PER_SEC) +#else +# define KTIME_SEC_MAX LONG_MAX +#endif + /* * ktime_t definitions when using the 64-bit scalar representation: */ diff --git a/trunk/include/linux/kvm_host.h b/trunk/include/linux/kvm_host.h index 8a59e0abe5fa..b70b48b01098 100644 --- a/trunk/include/linux/kvm_host.h +++ b/trunk/include/linux/kvm_host.h @@ -685,7 +685,7 @@ static inline int kvm_deassign_device(struct kvm *kvm, static inline void kvm_guest_enter(void) { BUG_ON(preemptible()); - vtime_account(current); + account_system_vtime(current); current->flags |= PF_VCPU; /* KVM does not hold any references to rcu protected data when it * switches CPU into a guest mode. In fact switching to a guest mode @@ -699,7 +699,7 @@ static inline void kvm_guest_enter(void) static inline void kvm_guest_exit(void) { - vtime_account(current); + account_system_vtime(current); current->flags &= ~PF_VCPU; } diff --git a/trunk/include/linux/mISDNhw.h b/trunk/include/linux/mISDNhw.h index 9d96d5d4dfed..d0752eca9b44 100644 --- a/trunk/include/linux/mISDNhw.h +++ b/trunk/include/linux/mISDNhw.h @@ -183,7 +183,7 @@ extern int mISDN_initbchannel(struct bchannel *, unsigned short, unsigned short); extern int mISDN_freedchannel(struct dchannel *); extern void mISDN_clear_bchannel(struct bchannel *); -extern void mISDN_freebchannel(struct bchannel *); +extern int mISDN_freebchannel(struct bchannel *); extern int mISDN_ctrl_bchannel(struct bchannel *, struct mISDN_ctrl_req *); extern void queue_ch_frame(struct mISDNchannel *, u_int, int, struct sk_buff *); diff --git a/trunk/include/linux/memory.h b/trunk/include/linux/memory.h index ff9a9f8e0ed9..1ac7f6e405f9 100644 --- a/trunk/include/linux/memory.h +++ b/trunk/include/linux/memory.h @@ -19,7 +19,7 @@ #include #include -#define MIN_MEMORY_BLOCK_SIZE (1UL << SECTION_SIZE_BITS) +#define MIN_MEMORY_BLOCK_SIZE (1 << SECTION_SIZE_BITS) struct memory_block { unsigned long start_section_nr; diff --git a/trunk/include/linux/mfd/core.h b/trunk/include/linux/mfd/core.h index cebe97ee98b8..3a8435a8058f 100644 --- a/trunk/include/linux/mfd/core.h +++ b/trunk/include/linux/mfd/core.h @@ -16,8 +16,6 @@ #include -struct irq_domain; - /* * This struct describes the MFD part ("cell"). * After registration the copy of this structure will become the platform data @@ -100,7 +98,7 @@ static inline const struct mfd_cell *mfd_get_cell(struct platform_device *pdev) extern int mfd_add_devices(struct device *parent, int id, struct mfd_cell *cells, int n_devs, struct resource *mem_base, - int irq_base, struct irq_domain *irq_domain); + int irq_base); extern void mfd_remove_devices(struct device *parent); diff --git a/trunk/include/linux/mfd/dbx500-prcmu.h b/trunk/include/linux/mfd/dbx500-prcmu.h index c410d99bd667..5b90e94399e1 100644 --- a/trunk/include/linux/mfd/dbx500-prcmu.h +++ b/trunk/include/linux/mfd/dbx500-prcmu.h @@ -136,7 +136,6 @@ enum prcmu_clock { PRCMU_TIMCLK, PRCMU_PLLSOC0, PRCMU_PLLSOC1, - PRCMU_ARMSS, PRCMU_PLLDDR, PRCMU_PLLDSI, PRCMU_DSI0CLK, diff --git a/trunk/include/linux/mfd/ezx-pcap.h b/trunk/include/linux/mfd/ezx-pcap.h index 32a1b5cfeba1..40c372165f3e 100644 --- a/trunk/include/linux/mfd/ezx-pcap.h +++ b/trunk/include/linux/mfd/ezx-pcap.h @@ -16,7 +16,6 @@ struct pcap_subdev { struct pcap_platform_data { unsigned int irq_base; unsigned int config; - int gpio; void (*init) (void *); /* board specific init */ int num_subdevs; struct pcap_subdev *subdevs; diff --git a/trunk/include/linux/mfd/max77686.h b/trunk/include/linux/mfd/max77686.h index 46c0f320ed76..3d7ae4d7fd36 100644 --- a/trunk/include/linux/mfd/max77686.h +++ b/trunk/include/linux/mfd/max77686.h @@ -74,7 +74,6 @@ enum max77686_regulators { struct max77686_regulator_data { int id; struct regulator_init_data *initdata; - struct device_node *of_node; }; enum max77686_opmode { diff --git a/trunk/include/linux/mfd/max8998.h b/trunk/include/linux/mfd/max8998.h index 6823548d0c0a..f4f0dfa4698a 100644 --- a/trunk/include/linux/mfd/max8998.h +++ b/trunk/include/linux/mfd/max8998.h @@ -67,7 +67,7 @@ struct max8998_regulator_data { /** * struct max8998_board - packages regulator init data * @regulators: array of defined regulators - * @num_regulators: number of regulators used + * @num_regulators: number of regultors used * @irq_base: base IRQ number for max8998, required for IRQs * @ono: power onoff IRQ number for max8998 * @buck_voltage_lock: Do NOT change the values of the following six diff --git a/trunk/include/linux/mfd/tps65217.h b/trunk/include/linux/mfd/tps65217.h index 7cd83d826ed8..12c06870829a 100644 --- a/trunk/include/linux/mfd/tps65217.h +++ b/trunk/include/linux/mfd/tps65217.h @@ -22,9 +22,6 @@ #include #include -/* TPS chip id list */ -#define TPS65217 0xF0 - /* I2C ID for TPS65217 part */ #define TPS65217_I2C_ID 0x24 @@ -251,11 +248,13 @@ struct tps_info { struct tps65217 { struct device *dev; struct tps65217_board *pdata; - unsigned int id; struct regulator_desc desc[TPS65217_NUM_REGULATOR]; struct regulator_dev *rdev[TPS65217_NUM_REGULATOR]; struct tps_info *info[TPS65217_NUM_REGULATOR]; struct regmap *regmap; + + /* Client devices */ + struct platform_device *regulator_pdev[TPS65217_NUM_REGULATOR]; }; static inline struct tps65217 *dev_to_tps65217(struct device *dev) @@ -263,11 +262,6 @@ static inline struct tps65217 *dev_to_tps65217(struct device *dev) return dev_get_drvdata(dev); } -static inline int tps65217_chip_id(struct tps65217 *tps65217) -{ - return tps65217->id; -} - int tps65217_reg_read(struct tps65217 *tps, unsigned int reg, unsigned int *val); int tps65217_reg_write(struct tps65217 *tps, unsigned int reg, diff --git a/trunk/include/linux/mfd/tps6586x.h b/trunk/include/linux/mfd/tps6586x.h index 94514710a03f..f350fd0ba1df 100644 --- a/trunk/include/linux/mfd/tps6586x.h +++ b/trunk/include/linux/mfd/tps6586x.h @@ -14,7 +14,6 @@ #define TPS6586X_SLEW_RATE_MASK 0x07 enum { - TPS6586X_ID_SYS, TPS6586X_ID_SM_0, TPS6586X_ID_SM_1, TPS6586X_ID_SM_2, diff --git a/trunk/include/linux/micrel_phy.h b/trunk/include/linux/micrel_phy.h index de201203bc7c..61f0905bdc48 100644 --- a/trunk/include/linux/micrel_phy.h +++ b/trunk/include/linux/micrel_phy.h @@ -1,15 +1,3 @@ -/* - * include/linux/micrel_phy.h - * - * Micrel PHY IDs - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - */ - #ifndef _MICREL_PHY_H #define _MICREL_PHY_H @@ -17,11 +5,10 @@ #define PHY_ID_KSZ9021 0x00221610 #define PHY_ID_KS8737 0x00221720 -#define PHY_ID_KSZ8021 0x00221555 -#define PHY_ID_KSZ8041 0x00221510 -#define PHY_ID_KSZ8051 0x00221550 +#define PHY_ID_KS8041 0x00221510 +#define PHY_ID_KS8051 0x00221550 /* both for ks8001 Rev. A/B, and for ks8721 Rev 3. */ -#define PHY_ID_KSZ8001 0x0022161A +#define PHY_ID_KS8001 0x0022161A /* struct phy_device dev_flags definitions */ #define MICREL_PHY_50MHZ_CLK 0x00000001 diff --git a/trunk/include/linux/mlx4/device.h b/trunk/include/linux/mlx4/device.h index 6e1b0f973a03..bd6c9fcdf2dd 100644 --- a/trunk/include/linux/mlx4/device.h +++ b/trunk/include/linux/mlx4/device.h @@ -796,19 +796,6 @@ enum mlx4_net_trans_rule_id { MLX4_NET_TRANS_RULE_NUM, /* should be last */ }; -extern const u16 __sw_id_hw[]; - -static inline int map_hw_to_sw_id(u16 header_id) -{ - - int i; - for (i = 0; i < MLX4_NET_TRANS_RULE_NUM; i++) { - if (header_id == __sw_id_hw[i]) - return i; - } - return -EINVAL; -} - enum mlx4_net_trans_promisc_mode { MLX4_FS_PROMISC_NONE = 0, MLX4_FS_PROMISC_UPLINK, diff --git a/trunk/include/linux/mmc/card.h b/trunk/include/linux/mmc/card.h index 4b27f9f503e4..111aca5e97f3 100644 --- a/trunk/include/linux/mmc/card.h +++ b/trunk/include/linux/mmc/card.h @@ -239,7 +239,6 @@ struct mmc_card { #define MMC_QUIRK_BLK_NO_CMD23 (1<<7) /* Avoid CMD23 for regular multiblock */ #define MMC_QUIRK_BROKEN_BYTE_MODE_512 (1<<8) /* Avoid sending 512 bytes in */ #define MMC_QUIRK_LONG_READ_TIME (1<<9) /* Data read time > CSD says */ -#define MMC_QUIRK_SEC_ERASE_TRIM_BROKEN (1<<10) /* Skip secure for erase/trim */ /* byte mode */ unsigned int poweroff_notify_state; /* eMMC4.5 notify feature */ #define MMC_NO_POWER_NOTIFICATION 0 diff --git a/trunk/include/linux/mod_devicetable.h b/trunk/include/linux/mod_devicetable.h index 70c6a359b2f4..6955045199b0 100644 --- a/trunk/include/linux/mod_devicetable.h +++ b/trunk/include/linux/mod_devicetable.h @@ -600,12 +600,4 @@ struct x86_cpu_id { #define X86_MODEL_ANY 0 #define X86_FEATURE_ANY 0 /* Same as FPU, you can't test for that */ -#define IPACK_ANY_FORMAT 0xff -#define IPACK_ANY_ID (~0) -struct ipack_device_id { - __u8 format; /* Format version or IPACK_ANY_ID */ - __u32 vendor; /* Vendor ID or IPACK_ANY_ID */ - __u32 device; /* Device ID or IPACK_ANY_ID */ -}; - #endif /* LINUX_MOD_DEVICETABLE_H */ diff --git a/trunk/include/linux/mv643xx_eth.h b/trunk/include/linux/mv643xx_eth.h index 49258e0ed1c6..51bf8ada6dc0 100644 --- a/trunk/include/linux/mv643xx_eth.h +++ b/trunk/include/linux/mv643xx_eth.h @@ -15,8 +15,6 @@ #define MV643XX_ETH_SIZE_REG_4 0x2224 #define MV643XX_ETH_BASE_ADDR_ENABLE_REG 0x2290 -#define MV643XX_TX_CSUM_DEFAULT_LIMIT 0 - struct mv643xx_eth_shared_platform_data { struct mbus_dram_target_info *dram; struct platform_device *shared_smi; diff --git a/trunk/include/linux/netdevice.h b/trunk/include/linux/netdevice.h index 5f49cc0a107e..eb06e58bed0b 100644 --- a/trunk/include/linux/netdevice.h +++ b/trunk/include/linux/netdevice.h @@ -953,8 +953,7 @@ struct net_device_ops { #ifdef CONFIG_NET_POLL_CONTROLLER void (*ndo_poll_controller)(struct net_device *dev); int (*ndo_netpoll_setup)(struct net_device *dev, - struct netpoll_info *info, - gfp_t gfp); + struct netpoll_info *info); void (*ndo_netpoll_cleanup)(struct net_device *dev); #endif int (*ndo_set_vf_mac)(struct net_device *dev, @@ -1301,8 +1300,6 @@ struct net_device { /* for setting kernel sock attribute on TCP connection setup */ #define GSO_MAX_SIZE 65536 unsigned int gso_max_size; -#define GSO_MAX_SEGS 65535 - u16 gso_max_segs; #ifdef CONFIG_DCB /* Data Center Bridging netlink ops */ @@ -1522,8 +1519,6 @@ struct packet_type { struct sk_buff **(*gro_receive)(struct sk_buff **head, struct sk_buff *skb); int (*gro_complete)(struct sk_buff *skb); - bool (*id_match)(struct packet_type *ptype, - struct sock *sk); void *af_packet_priv; struct list_head list; }; @@ -2720,6 +2715,9 @@ static inline const char *netdev_name(const struct net_device *dev) return dev->name; } +extern int __netdev_printk(const char *level, const struct net_device *dev, + struct va_format *vaf); + extern __printf(3, 4) int netdev_printk(const char *level, const struct net_device *dev, const char *format, ...); diff --git a/trunk/include/linux/netfilter/nf_conntrack_sip.h b/trunk/include/linux/netfilter/nf_conntrack_sip.h index 89f2a627f3f0..0dfc8b7210a3 100644 --- a/trunk/include/linux/netfilter/nf_conntrack_sip.h +++ b/trunk/include/linux/netfilter/nf_conntrack_sip.h @@ -164,7 +164,7 @@ extern int ct_sip_parse_address_param(const struct nf_conn *ct, const char *dptr unsigned int dataoff, unsigned int datalen, const char *name, unsigned int *matchoff, unsigned int *matchlen, - union nf_inet_addr *addr, bool delim); + union nf_inet_addr *addr); extern int ct_sip_parse_numerical_param(const struct nf_conn *ct, const char *dptr, unsigned int off, unsigned int datalen, const char *name, diff --git a/trunk/include/linux/netpoll.h b/trunk/include/linux/netpoll.h index 66d5379c305e..28f5389c924b 100644 --- a/trunk/include/linux/netpoll.h +++ b/trunk/include/linux/netpoll.h @@ -23,7 +23,6 @@ struct netpoll { u8 remote_mac[ETH_ALEN]; struct list_head rx; /* rx_np list element */ - struct rcu_head rcu; }; struct netpoll_info { @@ -39,40 +38,28 @@ struct netpoll_info { struct delayed_work tx_work; struct netpoll *netpoll; - struct rcu_head rcu; }; void netpoll_send_udp(struct netpoll *np, const char *msg, int len); void netpoll_print_options(struct netpoll *np); int netpoll_parse_options(struct netpoll *np, char *opt); -int __netpoll_setup(struct netpoll *np, struct net_device *ndev, gfp_t gfp); +int __netpoll_setup(struct netpoll *np, struct net_device *ndev); int netpoll_setup(struct netpoll *np); int netpoll_trap(void); void netpoll_set_trap(int trap); void __netpoll_cleanup(struct netpoll *np); -void __netpoll_free_rcu(struct netpoll *np); void netpoll_cleanup(struct netpoll *np); -int __netpoll_rx(struct sk_buff *skb, struct netpoll_info *npinfo); +int __netpoll_rx(struct sk_buff *skb); void netpoll_send_skb_on_dev(struct netpoll *np, struct sk_buff *skb, struct net_device *dev); static inline void netpoll_send_skb(struct netpoll *np, struct sk_buff *skb) { - unsigned long flags; - local_irq_save(flags); netpoll_send_skb_on_dev(np, skb, np->dev); - local_irq_restore(flags); } #ifdef CONFIG_NETPOLL -static inline bool netpoll_rx_on(struct sk_buff *skb) -{ - struct netpoll_info *npinfo = rcu_dereference_bh(skb->dev->npinfo); - - return npinfo && (!list_empty(&npinfo->rx_np) || npinfo->rx_flags); -} - static inline bool netpoll_rx(struct sk_buff *skb) { struct netpoll_info *npinfo; @@ -80,14 +67,14 @@ static inline bool netpoll_rx(struct sk_buff *skb) bool ret = false; local_irq_save(flags); + npinfo = rcu_dereference_bh(skb->dev->npinfo); - if (!netpoll_rx_on(skb)) + if (!npinfo || (list_empty(&npinfo->rx_np) && !npinfo->rx_flags)) goto out; - npinfo = rcu_dereference_bh(skb->dev->npinfo); spin_lock(&npinfo->rx_lock); /* check rx_flags again with the lock held */ - if (npinfo->rx_flags && __netpoll_rx(skb, npinfo)) + if (npinfo->rx_flags && __netpoll_rx(skb)) ret = true; spin_unlock(&npinfo->rx_lock); @@ -96,6 +83,13 @@ static inline bool netpoll_rx(struct sk_buff *skb) return ret; } +static inline int netpoll_rx_on(struct sk_buff *skb) +{ + struct netpoll_info *npinfo = rcu_dereference_bh(skb->dev->npinfo); + + return npinfo && (!list_empty(&npinfo->rx_np) || npinfo->rx_flags); +} + static inline int netpoll_receive_skb(struct sk_buff *skb) { if (!list_empty(&skb->dev->napi_list)) @@ -125,7 +119,7 @@ static inline void netpoll_poll_unlock(void *have) } } -static inline bool netpoll_tx_running(struct net_device *dev) +static inline int netpoll_tx_running(struct net_device *dev) { return irqs_disabled(); } @@ -133,11 +127,11 @@ static inline bool netpoll_tx_running(struct net_device *dev) #else static inline bool netpoll_rx(struct sk_buff *skb) { - return false; + return 0; } -static inline bool netpoll_rx_on(struct sk_buff *skb) +static inline int netpoll_rx_on(struct sk_buff *skb) { - return false; + return 0; } static inline int netpoll_receive_skb(struct sk_buff *skb) { @@ -153,9 +147,9 @@ static inline void netpoll_poll_unlock(void *have) static inline void netpoll_netdev_init(struct net_device *dev) { } -static inline bool netpoll_tx_running(struct net_device *dev) +static inline int netpoll_tx_running(struct net_device *dev) { - return false; + return 0; } #endif diff --git a/trunk/include/linux/nfs_fs.h b/trunk/include/linux/nfs_fs.h index 4b03f56e280e..1f8fc7f9bcd8 100644 --- a/trunk/include/linux/nfs_fs.h +++ b/trunk/include/linux/nfs_fs.h @@ -265,6 +265,11 @@ static inline const struct nfs_rpc_ops *NFS_PROTO(const struct inode *inode) return NFS_SERVER(inode)->nfs_client->rpc_ops; } +static inline __be32 *NFS_COOKIEVERF(const struct inode *inode) +{ + return NFS_I(inode)->cookieverf; +} + static inline unsigned NFS_MINATTRTIMEO(const struct inode *inode) { struct nfs_server *nfss = NFS_SERVER(inode); diff --git a/trunk/include/linux/nfs_page.h b/trunk/include/linux/nfs_page.h index 92ce5783b707..880805774f9f 100644 --- a/trunk/include/linux/nfs_page.h +++ b/trunk/include/linux/nfs_page.h @@ -69,7 +69,6 @@ struct nfs_pageio_descriptor { const struct nfs_pgio_completion_ops *pg_completion_ops; struct pnfs_layout_segment *pg_lseg; struct nfs_direct_req *pg_dreq; - void *pg_layout_private; }; #define NFS_WBACK_BUSY(req) (test_bit(PG_BUSY,&(req)->wb_flags)) diff --git a/trunk/include/linux/nfs_xdr.h b/trunk/include/linux/nfs_xdr.h index be9cf3c7e79e..00485e084394 100644 --- a/trunk/include/linux/nfs_xdr.h +++ b/trunk/include/linux/nfs_xdr.h @@ -652,7 +652,7 @@ struct nfs_getaclargs { }; /* getxattr ACL interface flags */ -#define NFS4_ACL_TRUNC 0x0001 /* ACL was truncated */ +#define NFS4_ACL_LEN_REQUEST 0x0001 /* zero length getxattr buffer */ struct nfs_getaclres { size_t acl_len; size_t acl_data_offset; @@ -1248,7 +1248,6 @@ struct nfs_pgio_header { void (*release) (struct nfs_pgio_header *hdr); const struct nfs_pgio_completion_ops *completion_ops; struct nfs_direct_req *dreq; - void *layout_private; spinlock_t lock; /* fields protected by lock */ int pnfs_error; diff --git a/trunk/include/linux/nvme.h b/trunk/include/linux/nvme.h index c25cccaa555a..9490a00529f4 100644 --- a/trunk/include/linux/nvme.h +++ b/trunk/include/linux/nvme.h @@ -35,10 +35,8 @@ struct nvme_bar { __u64 acq; /* Admin CQ Base Address */ }; -#define NVME_CAP_MQES(cap) ((cap) & 0xffff) #define NVME_CAP_TIMEOUT(cap) (((cap) >> 24) & 0xff) #define NVME_CAP_STRIDE(cap) (((cap) >> 32) & 0xf) -#define NVME_CAP_MPSMIN(cap) (((cap) >> 48) & 0xf) enum { NVME_CC_ENABLE = 1 << 0, diff --git a/trunk/include/linux/of.h b/trunk/include/linux/of.h index 1b1163225f3b..5919ee33f2b7 100644 --- a/trunk/include/linux/of.h +++ b/trunk/include/linux/of.h @@ -190,17 +190,10 @@ extern struct device_node *of_get_parent(const struct device_node *node); extern struct device_node *of_get_next_parent(struct device_node *node); extern struct device_node *of_get_next_child(const struct device_node *node, struct device_node *prev); -extern struct device_node *of_get_next_available_child( - const struct device_node *node, struct device_node *prev); - #define for_each_child_of_node(parent, child) \ for (child = of_get_next_child(parent, NULL); child != NULL; \ child = of_get_next_child(parent, child)) -#define for_each_available_child_of_node(parent, child) \ - for (child = of_get_next_available_child(parent, NULL); child != NULL; \ - child = of_get_next_available_child(parent, child)) - static inline int of_get_child_count(const struct device_node *np) { struct device_node *child; diff --git a/trunk/include/linux/pci-acpi.h b/trunk/include/linux/pci-acpi.h index 9a22b5efb384..248fba2af98a 100644 --- a/trunk/include/linux/pci-acpi.h +++ b/trunk/include/linux/pci-acpi.h @@ -22,24 +22,19 @@ extern phys_addr_t acpi_pci_root_get_mcfg_addr(acpi_handle handle); static inline acpi_handle acpi_find_root_bridge_handle(struct pci_dev *pdev) { struct pci_bus *pbus = pdev->bus; - /* Find a PCI root bus */ while (!pci_is_root_bus(pbus)) pbus = pbus->parent; - - return DEVICE_ACPI_HANDLE(pbus->bridge); + return acpi_get_pci_rootbridge_handle(pci_domain_nr(pbus), + pbus->number); } static inline acpi_handle acpi_pci_get_bridge_handle(struct pci_bus *pbus) { - struct device *dev; - - if (pci_is_root_bus(pbus)) - dev = pbus->bridge; - else - dev = &pbus->self->dev; - - return DEVICE_ACPI_HANDLE(dev); + if (!pci_is_root_bus(pbus)) + return DEVICE_ACPI_HANDLE(&(pbus->self->dev)); + return acpi_get_pci_rootbridge_handle(pci_domain_nr(pbus), + pbus->number); } #endif diff --git a/trunk/include/linux/pci.h b/trunk/include/linux/pci.h index be1de01de1c4..5faa8310eec9 100644 --- a/trunk/include/linux/pci.h +++ b/trunk/include/linux/pci.h @@ -254,10 +254,10 @@ struct pci_dev { u8 revision; /* PCI revision, low byte of class word */ u8 hdr_type; /* PCI header type (`multi' flag masked out) */ u8 pcie_cap; /* PCI-E capability offset */ + u8 pcie_type:4; /* PCI-E device/port type */ u8 pcie_mpss:3; /* PCI-E Max Payload Size Supported */ u8 rom_base_reg; /* which config register controls the ROM */ u8 pin; /* which interrupt pin this device uses */ - u16 pcie_flags_reg; /* cached PCI-E Capabilities Register */ struct pci_driver *driver; /* which driver has allocated this device */ u64 dma_mask; /* Mask of the bits of bus address this @@ -369,6 +369,7 @@ static inline struct pci_dev *pci_physfn(struct pci_dev *dev) extern struct pci_dev *alloc_pci_dev(void); +#define pci_dev_b(n) list_entry(n, struct pci_dev, bus_list) #define to_pci_dev(n) container_of(n, struct pci_dev, dev) #define for_each_pci_dev(d) while ((d = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, d)) != NULL) @@ -595,7 +596,7 @@ struct pci_driver { int (*resume_early) (struct pci_dev *dev); int (*resume) (struct pci_dev *dev); /* Device woken up */ void (*shutdown) (struct pci_dev *dev); - const struct pci_error_handlers *err_handler; + struct pci_error_handlers *err_handler; struct device_driver driver; struct pci_dynids dynids; }; @@ -733,7 +734,9 @@ u8 pci_common_swizzle(struct pci_dev *dev, u8 *pinp); extern struct pci_dev *pci_dev_get(struct pci_dev *dev); extern void pci_dev_put(struct pci_dev *dev); extern void pci_remove_bus(struct pci_bus *b); +extern void __pci_remove_bus_device(struct pci_dev *dev); extern void pci_stop_and_remove_bus_device(struct pci_dev *dev); +extern void pci_stop_bus_device(struct pci_dev *dev); void pci_setup_cardbus(struct pci_bus *bus); extern void pci_sort_breadthfirst(void); #define dev_is_pci(d) ((d)->bus == &pci_bus_type) @@ -752,7 +755,6 @@ enum pci_lost_interrupt_reason pci_lost_interrupt(struct pci_dev *dev); int pci_find_capability(struct pci_dev *dev, int cap); int pci_find_next_capability(struct pci_dev *dev, u8 pos, int cap); int pci_find_ext_capability(struct pci_dev *dev, int cap); -int pci_find_next_ext_capability(struct pci_dev *dev, int pos, int cap); int pci_find_ht_capability(struct pci_dev *dev, int ht_cap); int pci_find_next_ht_capability(struct pci_dev *dev, int pos, int ht_cap); struct pci_bus *pci_find_next_bus(const struct pci_bus *from); @@ -814,39 +816,6 @@ static inline int pci_write_config_dword(const struct pci_dev *dev, int where, return pci_bus_write_config_dword(dev->bus, dev->devfn, where, val); } -int pcie_capability_read_word(struct pci_dev *dev, int pos, u16 *val); -int pcie_capability_read_dword(struct pci_dev *dev, int pos, u32 *val); -int pcie_capability_write_word(struct pci_dev *dev, int pos, u16 val); -int pcie_capability_write_dword(struct pci_dev *dev, int pos, u32 val); -int pcie_capability_clear_and_set_word(struct pci_dev *dev, int pos, - u16 clear, u16 set); -int pcie_capability_clear_and_set_dword(struct pci_dev *dev, int pos, - u32 clear, u32 set); - -static inline int pcie_capability_set_word(struct pci_dev *dev, int pos, - u16 set) -{ - return pcie_capability_clear_and_set_word(dev, pos, 0, set); -} - -static inline int pcie_capability_set_dword(struct pci_dev *dev, int pos, - u32 set) -{ - return pcie_capability_clear_and_set_dword(dev, pos, 0, set); -} - -static inline int pcie_capability_clear_word(struct pci_dev *dev, int pos, - u16 clear) -{ - return pcie_capability_clear_and_set_word(dev, pos, clear, 0); -} - -static inline int pcie_capability_clear_dword(struct pci_dev *dev, int pos, - u32 clear) -{ - return pcie_capability_clear_and_set_dword(dev, pos, clear, 0); -} - /* user-space driven config access */ int pci_user_read_config_byte(struct pci_dev *dev, int where, u8 *val); int pci_user_read_config_word(struct pci_dev *dev, int where, u16 *val); @@ -1044,6 +1013,7 @@ void pci_unregister_driver(struct pci_driver *dev); module_driver(__pci_driver, pci_register_driver, \ pci_unregister_driver) +void pci_stop_and_remove_behind_bridge(struct pci_dev *dev); struct pci_driver *pci_dev_driver(const struct pci_dev *dev); int pci_add_dynid(struct pci_driver *drv, unsigned int vendor, unsigned int device, @@ -1061,8 +1031,6 @@ int pci_cfg_space_size_ext(struct pci_dev *dev); int pci_cfg_space_size(struct pci_dev *dev); unsigned char pci_bus_max_busnr(struct pci_bus *bus); void pci_setup_bridge(struct pci_bus *bus); -resource_size_t pcibios_window_alignment(struct pci_bus *bus, - unsigned long type); #define PCI_VGA_STATE_CHANGE_BRIDGE (1 << 0) #define PCI_VGA_STATE_CHANGE_DECODES (1 << 1) @@ -1504,7 +1472,7 @@ enum pci_fixup_pass { /* Anonymous variables would be nice... */ #define DECLARE_PCI_FIXUP_SECTION(section, name, vendor, device, class, \ class_shift, hook) \ - static const struct pci_fixup __pci_fixup_##name __used \ + static const struct pci_fixup const __pci_fixup_##name __used \ __attribute__((__section__(#section), aligned((sizeof(void *))))) \ = { vendor, device, class, class_shift, hook }; @@ -1682,15 +1650,6 @@ static inline bool pci_is_pcie(struct pci_dev *dev) return !!pci_pcie_cap(dev); } -/** - * pci_pcie_type - get the PCIe device/port type - * @dev: PCI device - */ -static inline int pci_pcie_type(const struct pci_dev *dev) -{ - return (dev->pcie_flags_reg & PCI_EXP_FLAGS_TYPE) >> 4; -} - void pci_request_acs(void); bool pci_acs_enabled(struct pci_dev *pdev, u16 acs_flags); bool pci_acs_path_enabled(struct pci_dev *start, diff --git a/trunk/include/linux/pci_ids.h b/trunk/include/linux/pci_ids.h index 8d3c42719387..fc3526077348 100644 --- a/trunk/include/linux/pci_ids.h +++ b/trunk/include/linux/pci_ids.h @@ -1847,6 +1847,7 @@ #define PCI_DEVICE_ID_SIIG_8S_20x_650 0x2081 #define PCI_DEVICE_ID_SIIG_8S_20x_850 0x2082 #define PCI_SUBDEVICE_ID_SIIG_QUARTET_SERIAL 0x2050 +#define PCI_SUBDEVICE_ID_SIIG_DUAL_SERIAL 0x2530 #define PCI_VENDOR_ID_RADISYS 0x1331 @@ -2148,7 +2149,7 @@ #define PCI_DEVICE_ID_TIGON3_5704S 0x16a8 #define PCI_DEVICE_ID_NX2_57800_VF 0x16a9 #define PCI_DEVICE_ID_NX2_5706S 0x16aa -#define PCI_DEVICE_ID_NX2_57840_MF 0x16a4 +#define PCI_DEVICE_ID_NX2_57840_MF 0x16ab #define PCI_DEVICE_ID_NX2_5708S 0x16ac #define PCI_DEVICE_ID_NX2_57840_VF 0x16ad #define PCI_DEVICE_ID_NX2_57810_MF 0x16ae diff --git a/trunk/include/linux/pci_regs.h b/trunk/include/linux/pci_regs.h index 20ae747ddf34..7fb75b143755 100644 --- a/trunk/include/linux/pci_regs.h +++ b/trunk/include/linux/pci_regs.h @@ -549,7 +549,6 @@ #define PCI_EXP_LNKCAP2_SLS_8_0GB 0x04 /* Current Link Speed 8.0GT/s */ #define PCI_EXP_LNKCAP2_CROSSLINK 0x100 /* Crosslink supported */ #define PCI_EXP_LNKCTL2 48 /* Link Control 2 */ -#define PCI_EXP_LNKSTA2 50 /* Link Status 2 */ #define PCI_EXP_SLTCTL2 56 /* Slot Control 2 */ /* Extended Capabilities (PCI-X 2.0 and Express) */ @@ -678,12 +677,6 @@ #define PCI_PWR_CAP_BUDGET(x) ((x) & 1) /* Included in system budget */ #define PCI_EXT_CAP_PWR_SIZEOF 16 -/* Vendor-Specific (VSEC, PCI_EXT_CAP_ID_VNDR) */ -#define PCI_VNDR_HEADER 4 /* Vendor-Specific Header */ -#define PCI_VNDR_HEADER_ID(x) ((x) & 0xffff) -#define PCI_VNDR_HEADER_REV(x) (((x) >> 16) & 0xf) -#define PCI_VNDR_HEADER_LEN(x) (((x) >> 20) & 0xfff) - /* * Hypertransport sub capability types * diff --git a/trunk/include/linux/pcieport_if.h b/trunk/include/linux/pcieport_if.h index e6f91b1406d8..6775532b92a9 100644 --- a/trunk/include/linux/pcieport_if.h +++ b/trunk/include/linux/pcieport_if.h @@ -49,7 +49,7 @@ struct pcie_port_service_driver { int (*resume) (struct pcie_device *dev); /* Service Error Recovery Handler */ - const struct pci_error_handlers *err_handler; + struct pci_error_handlers *err_handler; /* Link Reset Capability - AER service driver specific */ pci_ers_result_t (*reset_link) (struct pci_dev *dev); diff --git a/trunk/include/linux/perf_event.h b/trunk/include/linux/perf_event.h index 599afc4bb67e..76c5c8b724a7 100644 --- a/trunk/include/linux/perf_event.h +++ b/trunk/include/linux/perf_event.h @@ -130,10 +130,8 @@ enum perf_event_sample_format { PERF_SAMPLE_STREAM_ID = 1U << 9, PERF_SAMPLE_RAW = 1U << 10, PERF_SAMPLE_BRANCH_STACK = 1U << 11, - PERF_SAMPLE_REGS_USER = 1U << 12, - PERF_SAMPLE_STACK_USER = 1U << 13, - PERF_SAMPLE_MAX = 1U << 14, /* non-ABI */ + PERF_SAMPLE_MAX = 1U << 12, /* non-ABI */ }; /* @@ -164,15 +162,6 @@ enum perf_branch_sample_type { PERF_SAMPLE_BRANCH_KERNEL|\ PERF_SAMPLE_BRANCH_HV) -/* - * Values to determine ABI of the registers dump. - */ -enum perf_sample_regs_abi { - PERF_SAMPLE_REGS_ABI_NONE = 0, - PERF_SAMPLE_REGS_ABI_32 = 1, - PERF_SAMPLE_REGS_ABI_64 = 2, -}; - /* * The format of the data returned by read() on a perf event fd, * as specified by attr.read_format: @@ -205,8 +194,6 @@ enum perf_event_read_format { #define PERF_ATTR_SIZE_VER0 64 /* sizeof first published struct */ #define PERF_ATTR_SIZE_VER1 72 /* add: config2 */ #define PERF_ATTR_SIZE_VER2 80 /* add: branch_sample_type */ -#define PERF_ATTR_SIZE_VER3 96 /* add: sample_regs_user */ - /* add: sample_stack_user */ /* * Hardware event_id to monitor via a performance monitoring event: @@ -268,10 +255,7 @@ struct perf_event_attr { exclude_host : 1, /* don't count in host */ exclude_guest : 1, /* don't count in guest */ - exclude_callchain_kernel : 1, /* exclude kernel callchains */ - exclude_callchain_user : 1, /* exclude user callchains */ - - __reserved_1 : 41; + __reserved_1 : 43; union { __u32 wakeup_events; /* wakeup every n events */ @@ -287,25 +271,9 @@ struct perf_event_attr { __u64 bp_len; __u64 config2; /* extension of config1 */ }; - __u64 branch_sample_type; /* enum perf_branch_sample_type */ - - /* - * Defines set of user regs to dump on samples. - * See asm/perf_regs.h for details. - */ - __u64 sample_regs_user; - - /* - * Defines size of the user stack to dump on samples. - */ - __u32 sample_stack_user; - - /* Align to u64. */ - __u32 __reserved_2; + __u64 branch_sample_type; /* enum branch_sample_type */ }; -#define perf_flags(attr) (*(&(attr)->read_format + 1)) - /* * Ioctls that can be done on a perf event fd: */ @@ -580,13 +548,6 @@ enum perf_event_type { * char data[size];}&& PERF_SAMPLE_RAW * * { u64 from, to, flags } lbr[nr];} && PERF_SAMPLE_BRANCH_STACK - * - * { u64 abi; # enum perf_sample_regs_abi - * u64 regs[weight(mask)]; } && PERF_SAMPLE_REGS_USER - * - * { u64 size; - * char data[size]; - * u64 dyn_size; } && PERF_SAMPLE_STACK_USER * }; */ PERF_RECORD_SAMPLE = 9, @@ -648,7 +609,6 @@ struct perf_guest_info_callbacks { #include #include #include -#include #include struct perf_callchain_entry { @@ -694,11 +654,6 @@ struct perf_branch_stack { struct perf_branch_entry entries[0]; }; -struct perf_regs_user { - __u64 abi; - struct pt_regs *regs; -}; - struct task_struct; /* @@ -971,7 +926,7 @@ struct perf_event { struct hw_perf_event hw; struct perf_event_context *ctx; - atomic_long_t refcount; + struct file *filp; /* * These accumulate total time (in nanoseconds) that children @@ -1178,8 +1133,6 @@ struct perf_sample_data { struct perf_callchain_entry *callchain; struct perf_raw_record *raw; struct perf_branch_stack *br_stack; - struct perf_regs_user regs_user; - u64 stack_user_size; }; static inline void perf_sample_data_init(struct perf_sample_data *data, @@ -1189,10 +1142,7 @@ static inline void perf_sample_data_init(struct perf_sample_data *data, data->addr = addr; data->raw = NULL; data->br_stack = NULL; - data->period = period; - data->regs_user.abi = PERF_SAMPLE_REGS_ABI_NONE; - data->regs_user.regs = NULL; - data->stack_user_size = 0; + data->period = period; } extern void perf_output_sample(struct perf_output_handle *handle, @@ -1322,8 +1272,7 @@ static inline bool perf_paranoid_kernel(void) extern void perf_event_init(void); extern void perf_tp_event(u64 addr, u64 count, void *record, int entry_size, struct pt_regs *regs, - struct hlist_head *head, int rctx, - struct task_struct *task); + struct hlist_head *head, int rctx); extern void perf_bp_event(struct perf_event *event, void *data); #ifndef perf_misc_flags @@ -1340,15 +1289,12 @@ static inline bool has_branch_stack(struct perf_event *event) extern int perf_output_begin(struct perf_output_handle *handle, struct perf_event *event, unsigned int size); extern void perf_output_end(struct perf_output_handle *handle); -extern unsigned int perf_output_copy(struct perf_output_handle *handle, +extern void perf_output_copy(struct perf_output_handle *handle, const void *buf, unsigned int len); -extern unsigned int perf_output_skip(struct perf_output_handle *handle, - unsigned int len); extern int perf_swevent_get_recursion_context(void); extern void perf_swevent_put_recursion_context(int rctx); extern void perf_event_enable(struct perf_event *event); extern void perf_event_disable(struct perf_event *event); -extern int __perf_event_disable(void *info); extern void perf_event_task_tick(void); #else static inline void @@ -1387,7 +1333,6 @@ static inline int perf_swevent_get_recursion_context(void) { return -1; } static inline void perf_swevent_put_recursion_context(int rctx) { } static inline void perf_event_enable(struct perf_event *event) { } static inline void perf_event_disable(struct perf_event *event) { } -static inline int __perf_event_disable(void *info) { return -1; } static inline void perf_event_task_tick(void) { } #endif diff --git a/trunk/include/linux/perf_regs.h b/trunk/include/linux/perf_regs.h deleted file mode 100644 index 3c73d5fe18be..000000000000 --- a/trunk/include/linux/perf_regs.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef _LINUX_PERF_REGS_H -#define _LINUX_PERF_REGS_H - -#ifdef CONFIG_HAVE_PERF_REGS -#include -u64 perf_reg_value(struct pt_regs *regs, int idx); -int perf_reg_validate(u64 mask); -u64 perf_reg_abi(struct task_struct *task); -#else -static inline u64 perf_reg_value(struct pt_regs *regs, int idx) -{ - return 0; -} - -static inline int perf_reg_validate(u64 mask) -{ - return mask ? -ENOSYS : 0; -} - -static inline u64 perf_reg_abi(struct task_struct *task) -{ - return PERF_SAMPLE_REGS_ABI_NONE; -} -#endif /* CONFIG_HAVE_PERF_REGS */ -#endif /* _LINUX_PERF_REGS_H */ diff --git a/trunk/include/linux/pinctrl/consumer.h b/trunk/include/linux/pinctrl/consumer.h index e9b7f4350844..6dd96fb45482 100644 --- a/trunk/include/linux/pinctrl/consumer.h +++ b/trunk/include/linux/pinctrl/consumer.h @@ -20,7 +20,6 @@ /* This struct is private to the core and should be regarded as a cookie */ struct pinctrl; struct pinctrl_state; -struct device; #ifdef CONFIG_PINCTRL diff --git a/trunk/include/linux/platform_data/ad5755.h b/trunk/include/linux/platform_data/ad5755.h deleted file mode 100644 index a5a1cb751874..000000000000 --- a/trunk/include/linux/platform_data/ad5755.h +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright 2012 Analog Devices Inc. - * - * Licensed under the GPL-2. - */ -#ifndef __LINUX_PLATFORM_DATA_AD5755_H__ -#define __LINUX_PLATFORM_DATA_AD5755_H__ - -enum ad5755_mode { - AD5755_MODE_VOLTAGE_0V_5V = 0, - AD5755_MODE_VOLTAGE_0V_10V = 1, - AD5755_MODE_VOLTAGE_PLUSMINUS_5V = 2, - AD5755_MODE_VOLTAGE_PLUSMINUS_10V = 3, - AD5755_MODE_CURRENT_4mA_20mA = 4, - AD5755_MODE_CURRENT_0mA_20mA = 5, - AD5755_MODE_CURRENT_0mA_24mA = 6, -}; - -enum ad5755_dc_dc_phase { - AD5755_DC_DC_PHASE_ALL_SAME_EDGE = 0, - AD5755_DC_DC_PHASE_A_B_SAME_EDGE_C_D_OPP_EDGE = 1, - AD5755_DC_DC_PHASE_A_C_SAME_EDGE_B_D_OPP_EDGE = 2, - AD5755_DC_DC_PHASE_90_DEGREE = 3, -}; - -enum ad5755_dc_dc_freq { - AD5755_DC_DC_FREQ_250kHZ = 0, - AD5755_DC_DC_FREQ_410kHZ = 1, - AD5755_DC_DC_FREQ_650kHZ = 2, -}; - -enum ad5755_dc_dc_maxv { - AD5755_DC_DC_MAXV_23V = 0, - AD5755_DC_DC_MAXV_24V5 = 1, - AD5755_DC_DC_MAXV_27V = 2, - AD5755_DC_DC_MAXV_29V5 = 3, -}; - -enum ad5755_slew_rate { - AD5755_SLEW_RATE_64k = 0, - AD5755_SLEW_RATE_32k = 1, - AD5755_SLEW_RATE_16k = 2, - AD5755_SLEW_RATE_8k = 3, - AD5755_SLEW_RATE_4k = 4, - AD5755_SLEW_RATE_2k = 5, - AD5755_SLEW_RATE_1k = 6, - AD5755_SLEW_RATE_500 = 7, - AD5755_SLEW_RATE_250 = 8, - AD5755_SLEW_RATE_125 = 9, - AD5755_SLEW_RATE_64 = 10, - AD5755_SLEW_RATE_32 = 11, - AD5755_SLEW_RATE_16 = 12, - AD5755_SLEW_RATE_8 = 13, - AD5755_SLEW_RATE_4 = 14, - AD5755_SLEW_RATE_0_5 = 15, -}; - -enum ad5755_slew_step_size { - AD5755_SLEW_STEP_SIZE_1 = 0, - AD5755_SLEW_STEP_SIZE_2 = 1, - AD5755_SLEW_STEP_SIZE_4 = 2, - AD5755_SLEW_STEP_SIZE_8 = 3, - AD5755_SLEW_STEP_SIZE_16 = 4, - AD5755_SLEW_STEP_SIZE_32 = 5, - AD5755_SLEW_STEP_SIZE_64 = 6, - AD5755_SLEW_STEP_SIZE_128 = 7, - AD5755_SLEW_STEP_SIZE_256 = 8, -}; - -/** - * struct ad5755_platform_data - AD5755 DAC driver platform data - * @ext_dc_dc_compenstation_resistor: Whether an external DC-DC converter - * compensation register is used. - * @dc_dc_phase: DC-DC converter phase. - * @dc_dc_freq: DC-DC converter frequency. - * @dc_dc_maxv: DC-DC maximum allowed boost voltage. - * @dac.mode: The mode to be used for the DAC output. - * @dac.ext_current_sense_resistor: Whether an external current sense resistor - * is used. - * @dac.enable_voltage_overrange: Whether to enable 20% voltage output overrange. - * @dac.slew.enable: Whether to enable digital slew. - * @dac.slew.rate: Slew rate of the digital slew. - * @dac.slew.step_size: Slew step size of the digital slew. - **/ -struct ad5755_platform_data { - bool ext_dc_dc_compenstation_resistor; - enum ad5755_dc_dc_phase dc_dc_phase; - enum ad5755_dc_dc_freq dc_dc_freq; - enum ad5755_dc_dc_maxv dc_dc_maxv; - - struct { - enum ad5755_mode mode; - bool ext_current_sense_resistor; - bool enable_voltage_overrange; - struct { - bool enable; - enum ad5755_slew_rate rate; - enum ad5755_slew_step_size step_size; - } slew; - } dac[4]; -}; - -#endif diff --git a/trunk/include/linux/platform_data/ad7791.h b/trunk/include/linux/platform_data/ad7791.h deleted file mode 100644 index f9e4db1b82ae..000000000000 --- a/trunk/include/linux/platform_data/ad7791.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef __LINUX_PLATFORM_DATA_AD7791__ -#define __LINUX_PLATFORM_DATA_AD7791__ - -/** - * struct ad7791_platform_data - AD7791 device platform data - * @buffered: If set to true configure the device for buffered input mode. - * @burnout_current: If set to true the 100mA burnout current is enabled. - * @unipolar: If set to true sample in unipolar mode, if set to false sample in - * bipolar mode. - */ -struct ad7791_platform_data { - bool buffered; - bool burnout_current; - bool unipolar; -}; - -#endif diff --git a/trunk/include/linux/platform_data/clk-realview.h b/trunk/include/linux/platform_data/clk-realview.h deleted file mode 100644 index 2e426a7dbc51..000000000000 --- a/trunk/include/linux/platform_data/clk-realview.h +++ /dev/null @@ -1 +0,0 @@ -void realview_clk_init(void __iomem *sysbase, bool is_pb1176); diff --git a/trunk/include/linux/platform_data/clk-ux500.h b/trunk/include/linux/platform_data/clk-ux500.h deleted file mode 100644 index 3af0da1f3be5..000000000000 --- a/trunk/include/linux/platform_data/clk-ux500.h +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Clock definitions for ux500 platforms - * - * Copyright (C) 2012 ST-Ericsson SA - * Author: Ulf Hansson - * - * License terms: GNU General Public License (GPL) version 2 - */ - -#ifndef __CLK_UX500_H -#define __CLK_UX500_H - -void u8500_clk_init(void); -void u9540_clk_init(void); -void u8540_clk_init(void); - -#endif /* __CLK_UX500_H */ diff --git a/trunk/include/linux/platform_data/max310x.h b/trunk/include/linux/platform_data/max310x.h deleted file mode 100644 index 91648bf5fc5c..000000000000 --- a/trunk/include/linux/platform_data/max310x.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Maxim (Dallas) MAX3107/8 serial driver - * - * Copyright (C) 2012 Alexander Shiyan - * - * Based on max3100.c, by Christian Pellegrin - * Based on max3110.c, by Feng Tang - * Based on max3107.c, by Aavamobile - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#ifndef _MAX310X_H_ -#define _MAX310X_H_ - -/* - * Example board initialization data: - * - * static struct max310x_pdata max3107_pdata = { - * .driver_flags = MAX310X_EXT_CLK, - * .uart_flags[0] = MAX310X_ECHO_SUPRESS | MAX310X_AUTO_DIR_CTRL, - * .frequency = 3686400, - * .gpio_base = -1, - * }; - * - * static struct spi_board_info spi_device_max3107[] = { - * { - * .modalias = "max3107", - * .irq = IRQ_EINT3, - * .bus_num = 1, - * .chip_select = 1, - * .platform_data = &max3107_pdata, - * }, - * }; - */ - -#define MAX310X_MAX_UARTS 1 - -/* MAX310X platform data structure */ -struct max310x_pdata { - /* Flags global to driver */ - const u8 driver_flags:2; -#define MAX310X_EXT_CLK (0x00000001) /* External clock enable */ -#define MAX310X_AUTOSLEEP (0x00000002) /* Enable AutoSleep mode */ - /* Flags global to UART port */ - const u8 uart_flags[MAX310X_MAX_UARTS]; -#define MAX310X_LOOPBACK (0x00000001) /* Loopback mode enable */ -#define MAX310X_ECHO_SUPRESS (0x00000002) /* Enable echo supress */ -#define MAX310X_AUTO_DIR_CTRL (0x00000004) /* Enable Auto direction - * control (RS-485) - */ - /* Frequency (extrenal clock or crystal) */ - const int frequency; - /* GPIO base number (can be negative) */ - const int gpio_base; - /* Called during startup */ - void (*init)(void); - /* Called before finish */ - void (*exit)(void); - /* Suspend callback */ - void (*suspend)(int do_suspend); -}; - -#endif diff --git a/trunk/include/linux/platform_data/sccnxp.h b/trunk/include/linux/platform_data/sccnxp.h deleted file mode 100644 index 7311ccd3217f..000000000000 --- a/trunk/include/linux/platform_data/sccnxp.h +++ /dev/null @@ -1,93 +0,0 @@ -/* - * NXP (Philips) SCC+++(SCN+++) serial driver - * - * Copyright (C) 2012 Alexander Shiyan - * - * Based on sc26xx.c, by Thomas Bogendörfer (tsbogend@alpha.franken.de) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#ifndef __SCCNXP_H -#define __SCCNXP_H - -#define SCCNXP_MAX_UARTS 2 - -/* Output lines */ -#define LINE_OP0 1 -#define LINE_OP1 2 -#define LINE_OP2 3 -#define LINE_OP3 4 -#define LINE_OP4 5 -#define LINE_OP5 6 -#define LINE_OP6 7 -#define LINE_OP7 8 - -/* Input lines */ -#define LINE_IP0 9 -#define LINE_IP1 10 -#define LINE_IP2 11 -#define LINE_IP3 12 -#define LINE_IP4 13 -#define LINE_IP5 14 -#define LINE_IP6 15 - -/* Signals */ -#define DTR_OP 0 /* DTR */ -#define RTS_OP 4 /* RTS */ -#define DSR_IP 8 /* DSR */ -#define CTS_IP 12 /* CTS */ -#define DCD_IP 16 /* DCD */ -#define RNG_IP 20 /* RNG */ - -#define DIR_OP 24 /* Special signal for control RS-485. - * Goes high when transmit, - * then goes low. - */ - -/* Routing control signal 'sig' to line 'line' */ -#define MCTRL_SIG(sig, line) ((line) << (sig)) - -/* - * Example board initialization data: - * - * static struct resource sc2892_resources[] = { - * DEFINE_RES_MEM(UART_PHYS_START, 0x10), - * DEFINE_RES_IRQ(IRQ_EXT2), - * }; - * - * static struct sccnxp_pdata sc2892_info = { - * .frequency = 3686400, - * .mctrl_cfg[0] = MCTRL_SIG(DIR_OP, LINE_OP0), - * .mctrl_cfg[1] = MCTRL_SIG(DIR_OP, LINE_OP1), - * }; - * - * static struct platform_device sc2892 = { - * .name = "sc2892", - * .id = -1, - * .resource = sc2892_resources, - * .num_resources = ARRAY_SIZE(sc2892_resources), - * .dev = { - * .platform_data = &sc2892_info, - * }, - * }; - */ - -/* SCCNXP platform data structure */ -struct sccnxp_pdata { - /* Frequency (extrenal clock or crystal) */ - int frequency; - /* Shift for A0 line */ - const u8 reg_shift; - /* Modem control lines configuration */ - const u32 mctrl_cfg[SCCNXP_MAX_UARTS]; - /* Called during startup */ - void (*init)(void); - /* Called before finish */ - void (*exit)(void); -}; - -#endif diff --git a/trunk/include/linux/platform_device.h b/trunk/include/linux/platform_device.h index 5711e9525a2a..60e9994ef405 100644 --- a/trunk/include/linux/platform_device.h +++ b/trunk/include/linux/platform_device.h @@ -14,15 +14,11 @@ #include #include -#define PLATFORM_DEVID_NONE (-1) -#define PLATFORM_DEVID_AUTO (-2) - struct mfd_cell; struct platform_device { const char * name; int id; - bool id_auto; struct device dev; u32 num_resources; struct resource * resource; diff --git a/trunk/include/linux/pm.h b/trunk/include/linux/pm.h index 88f034a23f2c..f067e60a3832 100644 --- a/trunk/include/linux/pm.h +++ b/trunk/include/linux/pm.h @@ -638,7 +638,6 @@ extern void __suspend_report_result(const char *function, void *fn, int ret); } while (0) extern int device_pm_wait_for_dev(struct device *sub, struct device *dev); -extern void dpm_for_each_dev(void *data, void (*fn)(struct device *, void *)); extern int pm_generic_prepare(struct device *dev); extern int pm_generic_suspend_late(struct device *dev); @@ -678,10 +677,6 @@ static inline int device_pm_wait_for_dev(struct device *a, struct device *b) return 0; } -static inline void dpm_for_each_dev(void *data, void (*fn)(struct device *, void *)) -{ -} - #define pm_generic_prepare NULL #define pm_generic_suspend NULL #define pm_generic_resume NULL diff --git a/trunk/include/linux/power/generic-adc-battery.h b/trunk/include/linux/power/generic-adc-battery.h deleted file mode 100644 index b1ebe08533b6..000000000000 --- a/trunk/include/linux/power/generic-adc-battery.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (C) 2012, Anish Kumar - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef GENERIC_ADC_BATTERY_H -#define GENERIC_ADC_BATTERY_H - -/** - * struct gab_platform_data - platform_data for generic adc iio battery driver. - * @battery_info: recommended structure to specify static power supply - * parameters - * @cal_charge: calculate charge level. - * @gpio_charge_finished: gpio for the charger. - * @gpio_inverted: Should be 1 if the GPIO is active low otherwise 0 - * @jitter_delay: delay required after the interrupt to check battery - * status.Default set is 10ms. - */ -struct gab_platform_data { - struct power_supply_info battery_info; - int (*cal_charge)(long value); - int gpio_charge_finished; - bool gpio_inverted; - int jitter_delay; -}; - -#endif /* GENERIC_ADC_BATTERY_H */ diff --git a/trunk/include/linux/rcupdate.h b/trunk/include/linux/rcupdate.h index 7c968e4f929e..115ead2b5155 100644 --- a/trunk/include/linux/rcupdate.h +++ b/trunk/include/linux/rcupdate.h @@ -191,21 +191,6 @@ extern void rcu_idle_enter(void); extern void rcu_idle_exit(void); extern void rcu_irq_enter(void); extern void rcu_irq_exit(void); - -#ifdef CONFIG_RCU_USER_QS -extern void rcu_user_enter(void); -extern void rcu_user_exit(void); -extern void rcu_user_enter_after_irq(void); -extern void rcu_user_exit_after_irq(void); -extern void rcu_user_hooks_switch(struct task_struct *prev, - struct task_struct *next); -#else -static inline void rcu_user_enter(void) { } -static inline void rcu_user_exit(void) { } -static inline void rcu_user_enter_after_irq(void) { } -static inline void rcu_user_exit_after_irq(void) { } -#endif /* CONFIG_RCU_USER_QS */ - extern void exit_rcu(void); /** @@ -225,12 +210,14 @@ extern void exit_rcu(void); * to nest RCU_NONIDLE() wrappers, but the nesting level is currently * quite limited. If deeper nesting is required, it will be necessary * to adjust DYNTICK_TASK_NESTING_VALUE accordingly. + * + * This macro may be used from process-level code only. */ #define RCU_NONIDLE(a) \ do { \ - rcu_irq_enter(); \ + rcu_idle_exit(); \ do { a; } while (0); \ - rcu_irq_exit(); \ + rcu_idle_enter(); \ } while (0) /* diff --git a/trunk/include/linux/regmap.h b/trunk/include/linux/regmap.h index e3bcc3f4dcb8..7f7e00df3adf 100644 --- a/trunk/include/linux/regmap.h +++ b/trunk/include/linux/regmap.h @@ -285,7 +285,6 @@ struct regmap_irq { * @ack_base: Base ack address. If zero then the chip is clear on read. * @wake_base: Base address for wake enables. If zero unsupported. * @irq_reg_stride: Stride to use for chips where registers are not contiguous. - * @runtime_pm: Hold a runtime PM lock on the device when accessing it. * * @num_regs: Number of registers in each control bank. * @irqs: Descriptors for individual IRQs. Interrupt numbers are @@ -300,8 +299,6 @@ struct regmap_irq_chip { unsigned int ack_base; unsigned int wake_base; unsigned int irq_reg_stride; - unsigned int mask_invert; - bool runtime_pm; int num_regs; diff --git a/trunk/include/linux/regulator/consumer.h b/trunk/include/linux/regulator/consumer.h index c43cd3556b1f..da339fd8c755 100644 --- a/trunk/include/linux/regulator/consumer.h +++ b/trunk/include/linux/regulator/consumer.h @@ -177,8 +177,6 @@ int regulator_set_mode(struct regulator *regulator, unsigned int mode); unsigned int regulator_get_mode(struct regulator *regulator); int regulator_set_optimum_mode(struct regulator *regulator, int load_uA); -int regulator_allow_bypass(struct regulator *regulator, bool allow); - /* regulator notifier block */ int regulator_register_notifier(struct regulator *regulator, struct notifier_block *nb); @@ -330,12 +328,6 @@ static inline int regulator_set_optimum_mode(struct regulator *regulator, return REGULATOR_MODE_NORMAL; } -static inline int regulator_allow_bypass(struct regulator *regulator, - bool allow) -{ - return 0; -} - static inline int regulator_register_notifier(struct regulator *regulator, struct notifier_block *nb) { @@ -360,11 +352,4 @@ static inline void regulator_set_drvdata(struct regulator *regulator, #endif -static inline int regulator_set_voltage_tol(struct regulator *regulator, - int new_uV, int tol_uV) -{ - return regulator_set_voltage(regulator, - new_uV - tol_uV, new_uV + tol_uV); -} - #endif diff --git a/trunk/include/linux/regulator/driver.h b/trunk/include/linux/regulator/driver.h index 7932a3bf21bd..bac4c871f3bd 100644 --- a/trunk/include/linux/regulator/driver.h +++ b/trunk/include/linux/regulator/driver.h @@ -32,8 +32,6 @@ enum regulator_status { REGULATOR_STATUS_NORMAL, REGULATOR_STATUS_IDLE, REGULATOR_STATUS_STANDBY, - /* The regulator is enabled but not regulating */ - REGULATOR_STATUS_BYPASS, /* in case that any other status doesn't apply */ REGULATOR_STATUS_UNDEFINED, }; @@ -60,7 +58,6 @@ enum regulator_status { * regulator_desc.n_voltages. Voltages may be reported in any order. * * @set_current_limit: Configure a limit for a current-limited regulator. - * The driver should select the current closest to max_uA. * @get_current_limit: Get the configured limit for a current-limited regulator. * * @set_mode: Set the configured operating mode for the regulator. @@ -70,9 +67,6 @@ enum regulator_status { * @get_optimum_mode: Get the most efficient operating mode for the regulator * when running with the specified parameters. * - * @set_bypass: Set the regulator in bypass mode. - * @get_bypass: Get the regulator bypass mode state. - * * @enable_time: Time taken for the regulator voltage output voltage to * stabilise after being enabled, in microseconds. * @set_ramp_delay: Set the ramp delay for the regulator. The driver should @@ -139,10 +133,6 @@ struct regulator_ops { unsigned int (*get_optimum_mode) (struct regulator_dev *, int input_uV, int output_uV, int load_uA); - /* control and report on bypass mode */ - int (*set_bypass)(struct regulator_dev *dev, bool enable); - int (*get_bypass)(struct regulator_dev *dev, bool *enable); - /* the operations below are for configuration of regulator state when * its parent PMIC enters a global STANDBY/HIBERNATE state */ @@ -215,8 +205,6 @@ struct regulator_desc { unsigned int vsel_mask; unsigned int enable_reg; unsigned int enable_mask; - unsigned int bypass_reg; - unsigned int bypass_mask; unsigned int enable_time; }; @@ -233,8 +221,7 @@ struct regulator_desc { * @driver_data: private regulator data * @of_node: OpenFirmware node to parse for device tree bindings (may be * NULL). - * @regmap: regmap to use for core regmap helpers if dev_get_regulator() is - * insufficient. + * @regmap: regmap to use for core regmap helpers * @ena_gpio: GPIO controlling regulator enable. * @ena_gpio_invert: Sense for GPIO enable control. * @ena_gpio_flags: Flags to use when calling gpio_request_one() @@ -266,7 +253,6 @@ struct regulator_dev { int exclusive; u32 use_count; u32 open_count; - u32 bypass_count; /* lists we belong to */ struct list_head list; /* list of all regulators */ @@ -324,8 +310,6 @@ int regulator_disable_regmap(struct regulator_dev *rdev); int regulator_set_voltage_time_sel(struct regulator_dev *rdev, unsigned int old_selector, unsigned int new_selector); -int regulator_set_bypass_regmap(struct regulator_dev *rdev, bool enable); -int regulator_get_bypass_regmap(struct regulator_dev *rdev, bool *enable); void *regulator_get_init_drvdata(struct regulator_init_data *reg_init_data); diff --git a/trunk/include/linux/regulator/fan53555.h b/trunk/include/linux/regulator/fan53555.h deleted file mode 100644 index 5c45c85d52ca..000000000000 --- a/trunk/include/linux/regulator/fan53555.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * fan53555.h - Fairchild Regulator FAN53555 Driver - * - * Copyright (C) 2012 Marvell Technology Ltd. - * Yunfan Zhang - * - * This package is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - */ - -#ifndef __FAN53555_H__ - -/* VSEL ID */ -enum { - FAN53555_VSEL_ID_0 = 0, - FAN53555_VSEL_ID_1, -}; - -/* Transition slew rate limiting from a low to high voltage. - * ----------------------- - * Bin |Slew Rate(mV/uS) - * ------|---------------- - * 000 | 64.00 - * ------|---------------- - * 001 | 32.00 - * ------|---------------- - * 010 | 16.00 - * ------|---------------- - * 011 | 8.00 - * ------|---------------- - * 100 | 4.00 - * ------|---------------- - * 101 | 2.00 - * ------|---------------- - * 110 | 1.00 - * ------|---------------- - * 111 | 0.50 - * ----------------------- - */ -enum { - FAN53555_SLEW_RATE_64MV = 0, - FAN53555_SLEW_RATE_32MV, - FAN53555_SLEW_RATE_16MV, - FAN53555_SLEW_RATE_8MV, - FAN53555_SLEW_RATE_4MV, - FAN53555_SLEW_RATE_2MV, - FAN53555_SLEW_RATE_1MV, - FAN53555_SLEW_RATE_0_5MV, -}; - -struct fan53555_platform_data { - struct regulator_init_data *regulator; - unsigned int slew_rate; - /* Sleep VSEL ID */ - unsigned int sleep_vsel_id; -}; - -#endif /* __FAN53555_H__ */ diff --git a/trunk/include/linux/regulator/machine.h b/trunk/include/linux/regulator/machine.h index 36adbc82de6a..40dd0a394cfa 100644 --- a/trunk/include/linux/regulator/machine.h +++ b/trunk/include/linux/regulator/machine.h @@ -32,7 +32,6 @@ struct regulator; * board/machine. * STATUS: Regulator can be enabled and disabled. * DRMS: Dynamic Regulator Mode Switching is enabled for this regulator. - * BYPASS: Regulator can be put into bypass mode */ #define REGULATOR_CHANGE_VOLTAGE 0x1 @@ -40,7 +39,6 @@ struct regulator; #define REGULATOR_CHANGE_MODE 0x4 #define REGULATOR_CHANGE_STATUS 0x8 #define REGULATOR_CHANGE_DRMS 0x10 -#define REGULATOR_CHANGE_BYPASS 0x20 /** * struct regulator_state - regulator state during low power system states diff --git a/trunk/include/linux/sc26198.h b/trunk/include/linux/sc26198.h new file mode 100644 index 000000000000..7ca35abad387 --- /dev/null +++ b/trunk/include/linux/sc26198.h @@ -0,0 +1,533 @@ +/*****************************************************************************/ + +/* + * sc26198.h -- SC26198 UART hardware info. + * + * Copyright (C) 1995-1998 Stallion Technologies + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/*****************************************************************************/ +#ifndef _SC26198_H +#define _SC26198_H +/*****************************************************************************/ + +/* + * Define the number of async ports per sc26198 uart device. + */ +#define SC26198_PORTS 8 + +/* + * Baud rate timing clocks. All derived from a master 14.7456 MHz clock. + */ +#define SC26198_MASTERCLOCK 14745600L +#define SC26198_DCLK (SC26198_MASTERCLOCK) +#define SC26198_CCLK (SC26198_MASTERCLOCK / 2) +#define SC26198_BCLK (SC26198_MASTERCLOCK / 4) + +/* + * Define internal FIFO sizes for the 26198 ports. + */ +#define SC26198_TXFIFOSIZE 16 +#define SC26198_RXFIFOSIZE 16 + +/*****************************************************************************/ + +/* + * Global register definitions. These registers are global to each 26198 + * device, not specific ports on it. + */ +#define TSTR 0x0d +#define GCCR 0x0f +#define ICR 0x1b +#define WDTRCR 0x1d +#define IVR 0x1f +#define BRGTRUA 0x84 +#define GPOSR 0x87 +#define GPOC 0x8b +#define UCIR 0x8c +#define CIR 0x8c +#define BRGTRUB 0x8d +#define GRXFIFO 0x8e +#define GTXFIFO 0x8e +#define GCCR2 0x8f +#define BRGTRLA 0x94 +#define GPOR 0x97 +#define GPOD 0x9b +#define BRGTCR 0x9c +#define GICR 0x9c +#define BRGTRLB 0x9d +#define GIBCR 0x9d +#define GITR 0x9f + +/* + * Per port channel registers. These are the register offsets within + * the port address space, so need to have the port address (0 to 7) + * inserted in bit positions 4:6. + */ +#define MR0 0x00 +#define MR1 0x01 +#define IOPCR 0x02 +#define BCRBRK 0x03 +#define BCRCOS 0x04 +#define BCRX 0x06 +#define BCRA 0x07 +#define XONCR 0x08 +#define XOFFCR 0x09 +#define ARCR 0x0a +#define RXCSR 0x0c +#define TXCSR 0x0e +#define MR2 0x80 +#define SR 0x81 +#define SCCR 0x81 +#define ISR 0x82 +#define IMR 0x82 +#define TXFIFO 0x83 +#define RXFIFO 0x83 +#define IPR 0x84 +#define IOPIOR 0x85 +#define XISR 0x86 + +/* + * For any given port calculate the address to use to access a specified + * register. This is only used for unusual access, mostly this is done + * through the assembler access routines. + */ +#define SC26198_PORTREG(port,reg) ((((port) & 0x07) << 4) | (reg)) + +/*****************************************************************************/ + +/* + * Global configuration control register bit definitions. + */ +#define GCCR_NOACK 0x00 +#define GCCR_IVRACK 0x02 +#define GCCR_IVRCHANACK 0x04 +#define GCCR_IVRTYPCHANACK 0x06 +#define GCCR_ASYNCCYCLE 0x00 +#define GCCR_SYNCCYCLE 0x40 + +/*****************************************************************************/ + +/* + * Mode register 0 bit definitions. + */ +#define MR0_ADDRNONE 0x00 +#define MR0_AUTOWAKE 0x01 +#define MR0_AUTODOZE 0x02 +#define MR0_AUTOWAKEDOZE 0x03 +#define MR0_SWFNONE 0x00 +#define MR0_SWFTX 0x04 +#define MR0_SWFRX 0x08 +#define MR0_SWFRXTX 0x0c +#define MR0_TXMASK 0x30 +#define MR0_TXEMPTY 0x00 +#define MR0_TXHIGH 0x10 +#define MR0_TXHALF 0x20 +#define MR0_TXRDY 0x00 +#define MR0_ADDRNT 0x00 +#define MR0_ADDRT 0x40 +#define MR0_SWFNT 0x00 +#define MR0_SWFT 0x80 + +/* + * Mode register 1 bit definitions. + */ +#define MR1_CS5 0x00 +#define MR1_CS6 0x01 +#define MR1_CS7 0x02 +#define MR1_CS8 0x03 +#define MR1_PAREVEN 0x00 +#define MR1_PARODD 0x04 +#define MR1_PARENB 0x00 +#define MR1_PARFORCE 0x08 +#define MR1_PARNONE 0x10 +#define MR1_PARSPECIAL 0x18 +#define MR1_ERRCHAR 0x00 +#define MR1_ERRBLOCK 0x20 +#define MR1_ISRUNMASKED 0x00 +#define MR1_ISRMASKED 0x40 +#define MR1_AUTORTS 0x80 + +/* + * Mode register 2 bit definitions. + */ +#define MR2_STOP1 0x00 +#define MR2_STOP15 0x01 +#define MR2_STOP2 0x02 +#define MR2_STOP916 0x03 +#define MR2_RXFIFORDY 0x00 +#define MR2_RXFIFOHALF 0x04 +#define MR2_RXFIFOHIGH 0x08 +#define MR2_RXFIFOFULL 0x0c +#define MR2_AUTOCTS 0x10 +#define MR2_TXRTS 0x20 +#define MR2_MODENORM 0x00 +#define MR2_MODEAUTOECHO 0x40 +#define MR2_MODELOOP 0x80 +#define MR2_MODEREMECHO 0xc0 + +/*****************************************************************************/ + +/* + * Baud Rate Generator (BRG) selector values. + */ +#define BRG_50 0x00 +#define BRG_75 0x01 +#define BRG_150 0x02 +#define BRG_200 0x03 +#define BRG_300 0x04 +#define BRG_450 0x05 +#define BRG_600 0x06 +#define BRG_900 0x07 +#define BRG_1200 0x08 +#define BRG_1800 0x09 +#define BRG_2400 0x0a +#define BRG_3600 0x0b +#define BRG_4800 0x0c +#define BRG_7200 0x0d +#define BRG_9600 0x0e +#define BRG_14400 0x0f +#define BRG_19200 0x10 +#define BRG_28200 0x11 +#define BRG_38400 0x12 +#define BRG_57600 0x13 +#define BRG_115200 0x14 +#define BRG_230400 0x15 +#define BRG_GIN0 0x16 +#define BRG_GIN1 0x17 +#define BRG_CT0 0x18 +#define BRG_CT1 0x19 +#define BRG_RX2TX316 0x1b +#define BRG_RX2TX31 0x1c + +#define SC26198_MAXBAUD 921600 + +/*****************************************************************************/ + +/* + * Command register command definitions. + */ +#define CR_NULL 0x04 +#define CR_ADDRNORMAL 0x0c +#define CR_RXRESET 0x14 +#define CR_TXRESET 0x1c +#define CR_CLEARRXERR 0x24 +#define CR_BREAKRESET 0x2c +#define CR_TXSTARTBREAK 0x34 +#define CR_TXSTOPBREAK 0x3c +#define CR_RTSON 0x44 +#define CR_RTSOFF 0x4c +#define CR_ADDRINIT 0x5c +#define CR_RXERRBLOCK 0x6c +#define CR_TXSENDXON 0x84 +#define CR_TXSENDXOFF 0x8c +#define CR_GANGXONSET 0x94 +#define CR_GANGXOFFSET 0x9c +#define CR_GANGXONINIT 0xa4 +#define CR_GANGXOFFINIT 0xac +#define CR_HOSTXON 0xb4 +#define CR_HOSTXOFF 0xbc +#define CR_CANCELXOFF 0xc4 +#define CR_ADDRRESET 0xdc +#define CR_RESETALLPORTS 0xf4 +#define CR_RESETALL 0xfc + +#define CR_RXENABLE 0x01 +#define CR_TXENABLE 0x02 + +/*****************************************************************************/ + +/* + * Channel status register. + */ +#define SR_RXRDY 0x01 +#define SR_RXFULL 0x02 +#define SR_TXRDY 0x04 +#define SR_TXEMPTY 0x08 +#define SR_RXOVERRUN 0x10 +#define SR_RXPARITY 0x20 +#define SR_RXFRAMING 0x40 +#define SR_RXBREAK 0x80 + +#define SR_RXERRS (SR_RXPARITY | SR_RXFRAMING | SR_RXOVERRUN) + +/*****************************************************************************/ + +/* + * Interrupt status register and interrupt mask register bit definitions. + */ +#define IR_TXRDY 0x01 +#define IR_RXRDY 0x02 +#define IR_RXBREAK 0x04 +#define IR_XONXOFF 0x10 +#define IR_ADDRRECOG 0x20 +#define IR_RXWATCHDOG 0x40 +#define IR_IOPORT 0x80 + +/*****************************************************************************/ + +/* + * Interrupt vector register field definitions. + */ +#define IVR_CHANMASK 0x07 +#define IVR_TYPEMASK 0x18 +#define IVR_CONSTMASK 0xc0 + +#define IVR_RXDATA 0x10 +#define IVR_RXBADDATA 0x18 +#define IVR_TXDATA 0x08 +#define IVR_OTHER 0x00 + +/*****************************************************************************/ + +/* + * BRG timer control register bit definitions. + */ +#define BRGCTCR_DISABCLK0 0x00 +#define BRGCTCR_ENABCLK0 0x08 +#define BRGCTCR_DISABCLK1 0x00 +#define BRGCTCR_ENABCLK1 0x80 + +#define BRGCTCR_0SCLK16 0x00 +#define BRGCTCR_0SCLK32 0x01 +#define BRGCTCR_0SCLK64 0x02 +#define BRGCTCR_0SCLK128 0x03 +#define BRGCTCR_0X1 0x04 +#define BRGCTCR_0X12 0x05 +#define BRGCTCR_0IO1A 0x06 +#define BRGCTCR_0GIN0 0x07 + +#define BRGCTCR_1SCLK16 0x00 +#define BRGCTCR_1SCLK32 0x10 +#define BRGCTCR_1SCLK64 0x20 +#define BRGCTCR_1SCLK128 0x30 +#define BRGCTCR_1X1 0x40 +#define BRGCTCR_1X12 0x50 +#define BRGCTCR_1IO1B 0x60 +#define BRGCTCR_1GIN1 0x70 + +/*****************************************************************************/ + +/* + * Watch dog timer enable register. + */ +#define WDTRCR_ENABALL 0xff + +/*****************************************************************************/ + +/* + * XON/XOFF interrupt status register. + */ +#define XISR_TXCHARMASK 0x03 +#define XISR_TXCHARNORMAL 0x00 +#define XISR_TXWAIT 0x01 +#define XISR_TXXOFFPEND 0x02 +#define XISR_TXXONPEND 0x03 + +#define XISR_TXFLOWMASK 0x0c +#define XISR_TXNORMAL 0x00 +#define XISR_TXSTOPPEND 0x04 +#define XISR_TXSTARTED 0x08 +#define XISR_TXSTOPPED 0x0c + +#define XISR_RXFLOWMASK 0x30 +#define XISR_RXFLOWNONE 0x00 +#define XISR_RXXONSENT 0x10 +#define XISR_RXXOFFSENT 0x20 + +#define XISR_RXXONGOT 0x40 +#define XISR_RXXOFFGOT 0x80 + +/*****************************************************************************/ + +/* + * Current interrupt register. + */ +#define CIR_TYPEMASK 0xc0 +#define CIR_TYPEOTHER 0x00 +#define CIR_TYPETX 0x40 +#define CIR_TYPERXGOOD 0x80 +#define CIR_TYPERXBAD 0xc0 + +#define CIR_RXDATA 0x80 +#define CIR_RXBADDATA 0x40 +#define CIR_TXDATA 0x40 + +#define CIR_CHANMASK 0x07 +#define CIR_CNTMASK 0x38 + +#define CIR_SUBTYPEMASK 0x38 +#define CIR_SUBNONE 0x00 +#define CIR_SUBCOS 0x08 +#define CIR_SUBADDR 0x10 +#define CIR_SUBXONXOFF 0x18 +#define CIR_SUBBREAK 0x28 + +/*****************************************************************************/ + +/* + * Global interrupting channel register. + */ +#define GICR_CHANMASK 0x07 + +/*****************************************************************************/ + +/* + * Global interrupting byte count register. + */ +#define GICR_COUNTMASK 0x0f + +/*****************************************************************************/ + +/* + * Global interrupting type register. + */ +#define GITR_RXMASK 0xc0 +#define GITR_RXNONE 0x00 +#define GITR_RXBADDATA 0x80 +#define GITR_RXGOODDATA 0xc0 +#define GITR_TXDATA 0x20 + +#define GITR_SUBTYPEMASK 0x07 +#define GITR_SUBNONE 0x00 +#define GITR_SUBCOS 0x01 +#define GITR_SUBADDR 0x02 +#define GITR_SUBXONXOFF 0x03 +#define GITR_SUBBREAK 0x05 + +/*****************************************************************************/ + +/* + * Input port change register. + */ +#define IPR_CTS 0x01 +#define IPR_DTR 0x02 +#define IPR_RTS 0x04 +#define IPR_DCD 0x08 +#define IPR_CTSCHANGE 0x10 +#define IPR_DTRCHANGE 0x20 +#define IPR_RTSCHANGE 0x40 +#define IPR_DCDCHANGE 0x80 + +#define IPR_CHANGEMASK 0xf0 + +/*****************************************************************************/ + +/* + * IO port interrupt and output register. + */ +#define IOPR_CTS 0x01 +#define IOPR_DTR 0x02 +#define IOPR_RTS 0x04 +#define IOPR_DCD 0x08 +#define IOPR_CTSCOS 0x10 +#define IOPR_DTRCOS 0x20 +#define IOPR_RTSCOS 0x40 +#define IOPR_DCDCOS 0x80 + +/*****************************************************************************/ + +/* + * IO port configuration register. + */ +#define IOPCR_SETCTS 0x00 +#define IOPCR_SETDTR 0x04 +#define IOPCR_SETRTS 0x10 +#define IOPCR_SETDCD 0x00 + +#define IOPCR_SETSIGS (IOPCR_SETRTS | IOPCR_SETRTS | IOPCR_SETDTR | IOPCR_SETDCD) + +/*****************************************************************************/ + +/* + * General purpose output select register. + */ +#define GPORS_TXC1XA 0x08 +#define GPORS_TXC16XA 0x09 +#define GPORS_RXC16XA 0x0a +#define GPORS_TXC16XB 0x0b +#define GPORS_GPOR3 0x0c +#define GPORS_GPOR2 0x0d +#define GPORS_GPOR1 0x0e +#define GPORS_GPOR0 0x0f + +/*****************************************************************************/ + +/* + * General purpose output register. + */ +#define GPOR_0 0x01 +#define GPOR_1 0x02 +#define GPOR_2 0x04 +#define GPOR_3 0x08 + +/*****************************************************************************/ + +/* + * General purpose output clock register. + */ +#define GPORC_0NONE 0x00 +#define GPORC_0GIN0 0x01 +#define GPORC_0GIN1 0x02 +#define GPORC_0IO3A 0x02 + +#define GPORC_1NONE 0x00 +#define GPORC_1GIN0 0x04 +#define GPORC_1GIN1 0x08 +#define GPORC_1IO3C 0x0c + +#define GPORC_2NONE 0x00 +#define GPORC_2GIN0 0x10 +#define GPORC_2GIN1 0x20 +#define GPORC_2IO3E 0x20 + +#define GPORC_3NONE 0x00 +#define GPORC_3GIN0 0x40 +#define GPORC_3GIN1 0x80 +#define GPORC_3IO3G 0xc0 + +/*****************************************************************************/ + +/* + * General purpose output data register. + */ +#define GPOD_0MASK 0x03 +#define GPOD_0SET1 0x00 +#define GPOD_0SET0 0x01 +#define GPOD_0SETR0 0x02 +#define GPOD_0SETIO3B 0x03 + +#define GPOD_1MASK 0x0c +#define GPOD_1SET1 0x00 +#define GPOD_1SET0 0x04 +#define GPOD_1SETR0 0x08 +#define GPOD_1SETIO3D 0x0c + +#define GPOD_2MASK 0x30 +#define GPOD_2SET1 0x00 +#define GPOD_2SET0 0x10 +#define GPOD_2SETR0 0x20 +#define GPOD_2SETIO3F 0x30 + +#define GPOD_3MASK 0xc0 +#define GPOD_3SET1 0x00 +#define GPOD_3SET0 0x40 +#define GPOD_3SETR0 0x80 +#define GPOD_3SETIO3H 0xc0 + +/*****************************************************************************/ +#endif diff --git a/trunk/include/linux/sched.h b/trunk/include/linux/sched.h index 765dffbb085e..c147e7024f11 100644 --- a/trunk/include/linux/sched.h +++ b/trunk/include/linux/sched.h @@ -273,11 +273,11 @@ extern void init_idle_bootup_task(struct task_struct *idle); extern int runqueue_is_locked(int cpu); #if defined(CONFIG_SMP) && defined(CONFIG_NO_HZ) -extern void nohz_balance_enter_idle(int cpu); +extern void select_nohz_load_balancer(int stop_tick); extern void set_cpu_sd_state_idle(void); extern int get_nohz_timer_target(void); #else -static inline void nohz_balance_enter_idle(int cpu) { } +static inline void select_nohz_load_balancer(int stop_tick) { } static inline void set_cpu_sd_state_idle(void) { } #endif @@ -334,6 +334,14 @@ static inline void lockup_detector_init(void) } #endif +#if defined(CONFIG_LOCKUP_DETECTOR) && defined(CONFIG_SUSPEND) +void lockup_detector_bootcpu_resume(void); +#else +static inline void lockup_detector_bootcpu_resume(void) +{ +} +#endif + #ifdef CONFIG_DETECT_HUNG_TASK extern unsigned int sysctl_hung_task_panic; extern unsigned long sysctl_hung_task_check_count; @@ -446,9 +454,6 @@ extern int get_dumpable(struct mm_struct *mm); #define MMF_VM_HUGEPAGE 17 /* set when VM_HUGEPAGE is set on vma */ #define MMF_EXE_FILE_CHANGED 18 /* see prctl_set_mm_exe_file() */ -#define MMF_HAS_UPROBES 19 /* has uprobes */ -#define MMF_RECALC_UPROBES 20 /* MMF_HAS_UPROBES can be wrong */ - #define MMF_INIT_MASK (MMF_DUMPABLE_MASK | MMF_DUMP_FILTER_MASK) struct sighand_struct { @@ -681,6 +686,11 @@ struct signal_struct { * (notably. ptrace) */ }; +/* Context switch must be unlocked if interrupts are to be enabled */ +#ifdef __ARCH_WANT_INTERRUPTS_ON_CTXSW +# define __ARCH_WANT_UNLOCKED_CTXSW +#endif + /* * Bits in flags field of signal_struct. */ @@ -858,6 +868,7 @@ enum cpu_idle_type { #define SD_BALANCE_FORK 0x0008 /* Balance on fork, clone */ #define SD_BALANCE_WAKE 0x0010 /* Balance on wakeup */ #define SD_WAKE_AFFINE 0x0020 /* Wake task to waking CPU */ +#define SD_PREFER_LOCAL 0x0040 /* Prefer to keep tasks local to this domain */ #define SD_SHARE_CPUPOWER 0x0080 /* Domain members share cpu power */ #define SD_SHARE_PKG_RESOURCES 0x0200 /* Domain members share cpu pkg resources */ #define SD_SERIALIZE 0x0400 /* Only a single load balancing instance */ @@ -951,6 +962,7 @@ struct sched_domain { unsigned int smt_gain; int flags; /* See SD_* */ int level; + int idle_buddy; /* cpu assigned to select_idle_sibling() */ /* Runtime fields. */ unsigned long last_balance; /* init to jiffies. units in jiffies */ @@ -1882,14 +1894,6 @@ static inline void rcu_copy_process(struct task_struct *p) #endif -static inline void rcu_switch(struct task_struct *prev, - struct task_struct *next) -{ -#ifdef CONFIG_RCU_USER_QS - rcu_user_hooks_switch(prev, next); -#endif -} - static inline void tsk_restore_flags(struct task_struct *task, unsigned long orig_flags, unsigned long flags) { diff --git a/trunk/include/linux/screen_info.h b/trunk/include/linux/screen_info.h index fb3c5a8fef3d..899fbb487c94 100644 --- a/trunk/include/linux/screen_info.h +++ b/trunk/include/linux/screen_info.h @@ -68,8 +68,6 @@ struct screen_info { #define VIDEO_FLAGS_NOCURSOR (1 << 0) /* The video mode has no cursor set */ -#define VIDEO_CAPABILITY_SKIP_QUIRKS (1 << 0) - #ifdef __KERNEL__ extern struct screen_info screen_info; diff --git a/trunk/include/linux/security.h b/trunk/include/linux/security.h index d143b8e01954..4e5a73cdbbef 100644 --- a/trunk/include/linux/security.h +++ b/trunk/include/linux/security.h @@ -118,7 +118,6 @@ void reset_security_ops(void); extern unsigned long mmap_min_addr; extern unsigned long dac_mmap_min_addr; #else -#define mmap_min_addr 0UL #define dac_mmap_min_addr 0UL #endif @@ -1243,6 +1242,8 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts) * Check that the @parent process has sufficient permission to trace the * current process before allowing the current process to present itself * to the @parent process for tracing. + * The parent process will still have to undergo the ptrace_access_check + * checks before it is allowed to trace this one. * @parent contains the task_struct structure for debugger process. * Return 0 if permission is granted. * @capget: diff --git a/trunk/include/linux/serial.h b/trunk/include/linux/serial.h index 861e51de476b..90e9f981358a 100644 --- a/trunk/include/linux/serial.h +++ b/trunk/include/linux/serial.h @@ -12,12 +12,9 @@ #include -#include - #ifdef __KERNEL__ #include - /* * Counters of the input lines (CTS, DSR, RI, CD) interrupts */ @@ -86,11 +83,89 @@ struct serial_struct { #define SERIAL_IO_HUB6 1 #define SERIAL_IO_MEM 2 +struct serial_uart_config { + char *name; + int dfl_xmit_fifo_size; + int flags; +}; + #define UART_CLEAR_FIFO 0x01 #define UART_USE_FIFO 0x02 #define UART_STARTECH 0x04 #define UART_NATSEMI 0x08 +/* + * Definitions for async_struct (and serial_struct) flags field + * + * Define ASYNCB_* for convenient use with {test,set,clear}_bit. + */ +#define ASYNCB_HUP_NOTIFY 0 /* Notify getty on hangups and closes + * on the callout port */ +#define ASYNCB_FOURPORT 1 /* Set OU1, OUT2 per AST Fourport settings */ +#define ASYNCB_SAK 2 /* Secure Attention Key (Orange book) */ +#define ASYNCB_SPLIT_TERMIOS 3 /* Separate termios for dialin/callout */ +#define ASYNCB_SPD_HI 4 /* Use 56000 instead of 38400 bps */ +#define ASYNCB_SPD_VHI 5 /* Use 115200 instead of 38400 bps */ +#define ASYNCB_SKIP_TEST 6 /* Skip UART test during autoconfiguration */ +#define ASYNCB_AUTO_IRQ 7 /* Do automatic IRQ during + * autoconfiguration */ +#define ASYNCB_SESSION_LOCKOUT 8 /* Lock out cua opens based on session */ +#define ASYNCB_PGRP_LOCKOUT 9 /* Lock out cua opens based on pgrp */ +#define ASYNCB_CALLOUT_NOHUP 10 /* Don't do hangups for cua device */ +#define ASYNCB_HARDPPS_CD 11 /* Call hardpps when CD goes high */ +#define ASYNCB_SPD_SHI 12 /* Use 230400 instead of 38400 bps */ +#define ASYNCB_LOW_LATENCY 13 /* Request low latency behaviour */ +#define ASYNCB_BUGGY_UART 14 /* This is a buggy UART, skip some safety + * checks. Note: can be dangerous! */ +#define ASYNCB_AUTOPROBE 15 /* Port was autoprobed by PCI or PNP code */ +#define ASYNCB_LAST_USER 15 + +/* Internal flags used only by kernel */ +#define ASYNCB_INITIALIZED 31 /* Serial port was initialized */ +#define ASYNCB_SUSPENDED 30 /* Serial port is suspended */ +#define ASYNCB_NORMAL_ACTIVE 29 /* Normal device is active */ +#define ASYNCB_BOOT_AUTOCONF 28 /* Autoconfigure port on bootup */ +#define ASYNCB_CLOSING 27 /* Serial port is closing */ +#define ASYNCB_CTS_FLOW 26 /* Do CTS flow control */ +#define ASYNCB_CHECK_CD 25 /* i.e., CLOCAL */ +#define ASYNCB_SHARE_IRQ 24 /* for multifunction cards, no longer used */ +#define ASYNCB_CONS_FLOW 23 /* flow control for console */ +#define ASYNCB_FIRST_KERNEL 22 + +#define ASYNC_HUP_NOTIFY (1U << ASYNCB_HUP_NOTIFY) +#define ASYNC_SUSPENDED (1U << ASYNCB_SUSPENDED) +#define ASYNC_FOURPORT (1U << ASYNCB_FOURPORT) +#define ASYNC_SAK (1U << ASYNCB_SAK) +#define ASYNC_SPLIT_TERMIOS (1U << ASYNCB_SPLIT_TERMIOS) +#define ASYNC_SPD_HI (1U << ASYNCB_SPD_HI) +#define ASYNC_SPD_VHI (1U << ASYNCB_SPD_VHI) +#define ASYNC_SKIP_TEST (1U << ASYNCB_SKIP_TEST) +#define ASYNC_AUTO_IRQ (1U << ASYNCB_AUTO_IRQ) +#define ASYNC_SESSION_LOCKOUT (1U << ASYNCB_SESSION_LOCKOUT) +#define ASYNC_PGRP_LOCKOUT (1U << ASYNCB_PGRP_LOCKOUT) +#define ASYNC_CALLOUT_NOHUP (1U << ASYNCB_CALLOUT_NOHUP) +#define ASYNC_HARDPPS_CD (1U << ASYNCB_HARDPPS_CD) +#define ASYNC_SPD_SHI (1U << ASYNCB_SPD_SHI) +#define ASYNC_LOW_LATENCY (1U << ASYNCB_LOW_LATENCY) +#define ASYNC_BUGGY_UART (1U << ASYNCB_BUGGY_UART) +#define ASYNC_AUTOPROBE (1U << ASYNCB_AUTOPROBE) + +#define ASYNC_FLAGS ((1U << (ASYNCB_LAST_USER + 1)) - 1) +#define ASYNC_USR_MASK (ASYNC_SPD_MASK|ASYNC_CALLOUT_NOHUP| \ + ASYNC_LOW_LATENCY) +#define ASYNC_SPD_CUST (ASYNC_SPD_HI|ASYNC_SPD_VHI) +#define ASYNC_SPD_WARP (ASYNC_SPD_HI|ASYNC_SPD_SHI) +#define ASYNC_SPD_MASK (ASYNC_SPD_HI|ASYNC_SPD_VHI|ASYNC_SPD_SHI) + +#define ASYNC_INITIALIZED (1U << ASYNCB_INITIALIZED) +#define ASYNC_NORMAL_ACTIVE (1U << ASYNCB_NORMAL_ACTIVE) +#define ASYNC_BOOT_AUTOCONF (1U << ASYNCB_BOOT_AUTOCONF) +#define ASYNC_CLOSING (1U << ASYNCB_CLOSING) +#define ASYNC_CTS_FLOW (1U << ASYNCB_CTS_FLOW) +#define ASYNC_CHECK_CD (1U << ASYNCB_CHECK_CD) +#define ASYNC_SHARE_IRQ (1U << ASYNCB_SHARE_IRQ) +#define ASYNC_CONS_FLOW (1U << ASYNCB_CONS_FLOW) +#define ASYNC_INTERNAL_FLAGS (~((1U << ASYNCB_FIRST_KERNEL) - 1)) /* * Multiport serial configuration structure --- external structure diff --git a/trunk/include/linux/serial167.h b/trunk/include/linux/serial167.h new file mode 100644 index 000000000000..59c81b708562 --- /dev/null +++ b/trunk/include/linux/serial167.h @@ -0,0 +1,157 @@ +/* + * serial167.h + * + * Richard Hirst [richard@sleepie.demon.co.uk] + * + * Based on cyclades.h + */ + +struct cyclades_monitor { + unsigned long int_count; + unsigned long char_count; + unsigned long char_max; + unsigned long char_last; +}; + +/* + * This is our internal structure for each serial port's state. + * + * Many fields are paralleled by the structure used by the serial_struct + * structure. + * + * For definitions of the flags field, see tty.h + */ + +struct cyclades_port { + int magic; + int type; + int card; + int line; + int flags; /* defined in tty.h */ + struct tty_struct *tty; + int read_status_mask; + int timeout; + int xmit_fifo_size; + int cor1,cor2,cor3,cor4,cor5,cor6,cor7; + int tbpr,tco,rbpr,rco; + int ignore_status_mask; + int close_delay; + int IER; /* Interrupt Enable Register */ + unsigned long last_active; + int count; /* # of fd on device */ + int x_char; /* to be pushed out ASAP */ + int x_break; + int blocked_open; /* # of blocked opens */ + unsigned char *xmit_buf; + int xmit_head; + int xmit_tail; + int xmit_cnt; + int default_threshold; + int default_timeout; + wait_queue_head_t open_wait; + wait_queue_head_t close_wait; + struct cyclades_monitor mon; +}; + +#define CYCLADES_MAGIC 0x4359 + +#define CYGETMON 0x435901 +#define CYGETTHRESH 0x435902 +#define CYSETTHRESH 0x435903 +#define CYGETDEFTHRESH 0x435904 +#define CYSETDEFTHRESH 0x435905 +#define CYGETTIMEOUT 0x435906 +#define CYSETTIMEOUT 0x435907 +#define CYGETDEFTIMEOUT 0x435908 +#define CYSETDEFTIMEOUT 0x435909 + +#define CyMaxChipsPerCard 1 + +/**** cd2401 registers ****/ + +#define CyGFRCR (0x81) +#define CyCCR (0x13) +#define CyCLR_CHAN (0x40) +#define CyINIT_CHAN (0x20) +#define CyCHIP_RESET (0x10) +#define CyENB_XMTR (0x08) +#define CyDIS_XMTR (0x04) +#define CyENB_RCVR (0x02) +#define CyDIS_RCVR (0x01) +#define CyCAR (0xee) +#define CyIER (0x11) +#define CyMdmCh (0x80) +#define CyRxExc (0x20) +#define CyRxData (0x08) +#define CyTxMpty (0x02) +#define CyTxRdy (0x01) +#define CyLICR (0x26) +#define CyRISR (0x89) +#define CyTIMEOUT (0x80) +#define CySPECHAR (0x70) +#define CyOVERRUN (0x08) +#define CyPARITY (0x04) +#define CyFRAME (0x02) +#define CyBREAK (0x01) +#define CyREOIR (0x84) +#define CyTEOIR (0x85) +#define CyMEOIR (0x86) +#define CyNOTRANS (0x08) +#define CyRFOC (0x30) +#define CyRDR (0xf8) +#define CyTDR (0xf8) +#define CyMISR (0x8b) +#define CyRISR (0x89) +#define CyTISR (0x8a) +#define CyMSVR1 (0xde) +#define CyMSVR2 (0xdf) +#define CyDSR (0x80) +#define CyDCD (0x40) +#define CyCTS (0x20) +#define CyDTR (0x02) +#define CyRTS (0x01) +#define CyRTPRL (0x25) +#define CyRTPRH (0x24) +#define CyCOR1 (0x10) +#define CyPARITY_NONE (0x00) +#define CyPARITY_E (0x40) +#define CyPARITY_O (0xC0) +#define Cy_5_BITS (0x04) +#define Cy_6_BITS (0x05) +#define Cy_7_BITS (0x06) +#define Cy_8_BITS (0x07) +#define CyCOR2 (0x17) +#define CyETC (0x20) +#define CyCtsAE (0x02) +#define CyCOR3 (0x16) +#define Cy_1_STOP (0x02) +#define Cy_2_STOP (0x04) +#define CyCOR4 (0x15) +#define CyREC_FIFO (0x0F) /* Receive FIFO threshold */ +#define CyCOR5 (0x14) +#define CyCOR6 (0x18) +#define CyCOR7 (0x07) +#define CyRBPR (0xcb) +#define CyRCOR (0xc8) +#define CyTBPR (0xc3) +#define CyTCOR (0xc0) +#define CySCHR1 (0x1f) +#define CySCHR2 (0x1e) +#define CyTPR (0xda) +#define CyPILR1 (0xe3) +#define CyPILR2 (0xe0) +#define CyPILR3 (0xe1) +#define CyCMR (0x1b) +#define CyASYNC (0x02) +#define CyLICR (0x26) +#define CyLIVR (0x09) +#define CySCRL (0x23) +#define CySCRH (0x22) +#define CyTFTC (0x80) + + +/* max number of chars in the FIFO */ + +#define CyMAX_CHAR_FIFO 12 + +/***************************************************************************/ diff --git a/trunk/include/linux/serial_8250.h b/trunk/include/linux/serial_8250.h index c174c90fb3fb..a416e92012ef 100644 --- a/trunk/include/linux/serial_8250.h +++ b/trunk/include/linux/serial_8250.h @@ -65,38 +65,11 @@ enum { * platform device. Using these will make your driver * dependent on the 8250 driver. */ - -struct uart_8250_port { - struct uart_port port; - struct timer_list timer; /* "no irq" timer */ - struct list_head list; /* ports on this IRQ */ - unsigned short capabilities; /* port capabilities */ - unsigned short bugs; /* port bugs */ - unsigned int tx_loadsz; /* transmit fifo load size */ - unsigned char acr; - unsigned char ier; - unsigned char lcr; - unsigned char mcr; - unsigned char mcr_mask; /* mask of user bits */ - unsigned char mcr_force; /* mask of forced bits */ - unsigned char cur_iotype; /* Running I/O type */ - - /* - * Some bits in registers are cleared on a read, so they must - * be saved whenever the register is read but the bits will not - * be immediately processed. - */ -#define LSR_SAVE_FLAGS UART_LSR_BRK_ERROR_BITS - unsigned char lsr_saved_flags; -#define MSR_SAVE_FLAGS UART_MSR_ANY_DELTA - unsigned char msr_saved_flags; - - /* 8250 specific callbacks */ - int (*dl_read)(struct uart_8250_port *); - void (*dl_write)(struct uart_8250_port *, int); -}; +struct uart_port; +struct uart_8250_port; int serial8250_register_8250_port(struct uart_8250_port *); +int serial8250_register_port(struct uart_port *); void serial8250_unregister_port(int line); void serial8250_suspend_port(int line); void serial8250_resume_port(int line); diff --git a/trunk/include/linux/serial_core.h b/trunk/include/linux/serial_core.h index f9b22ec7a9f3..0253c2022e53 100644 --- a/trunk/include/linux/serial_core.h +++ b/trunk/include/linux/serial_core.h @@ -48,8 +48,7 @@ #define PORT_TEGRA 20 /* NVIDIA Tegra internal UART */ #define PORT_XR17D15X 21 /* Exar XR17D15x UART */ #define PORT_LPC3220 22 /* NXP LPC32xx SoC "Standard" UART */ -#define PORT_8250_CIR 23 /* CIR infrared port, has its own driver */ -#define PORT_MAX_8250 23 /* max port ID */ +#define PORT_MAX_8250 22 /* max port ID */ /* * ARM specific type numbers. These are not currently guaranteed @@ -194,8 +193,8 @@ /* SH-SCI */ #define PORT_SCIFB 93 -/* MAX310X */ -#define PORT_MAX310X 94 +/* MAX3107 */ +#define PORT_MAX3107 94 /* High Speed UART for Medfield */ #define PORT_MFD 95 @@ -275,7 +274,6 @@ struct uart_ops { int (*verify_port)(struct uart_port *, struct serial_struct *); int (*ioctl)(struct uart_port *, unsigned int, unsigned long); #ifdef CONFIG_CONSOLE_POLL - int (*poll_init)(struct uart_port *); void (*poll_put_char)(struct uart_port *, unsigned char); int (*poll_get_char)(struct uart_port *); #endif diff --git a/trunk/include/linux/serial_reg.h b/trunk/include/linux/serial_reg.h index 5ed325e88a81..8ce70d76f836 100644 --- a/trunk/include/linux/serial_reg.h +++ b/trunk/include/linux/serial_reg.h @@ -40,10 +40,6 @@ #define UART_IIR_BUSY 0x07 /* DesignWare APB Busy Detect */ -#define UART_IIR_RX_TIMEOUT 0x0c /* OMAP RX Timeout interrupt */ -#define UART_IIR_XOFF 0x10 /* OMAP XOFF/Special Character */ -#define UART_IIR_CTS_RTS_DSR 0x20 /* OMAP CTS/RTS/DSR Change */ - #define UART_FCR 2 /* Out: FIFO Control Register */ #define UART_FCR_ENABLE_FIFO 0x01 /* Enable the FIFO */ #define UART_FCR_CLEAR_RCVR 0x02 /* Clear the RCVR FIFO */ diff --git a/trunk/include/linux/smpboot.h b/trunk/include/linux/smpboot.h deleted file mode 100644 index e0106d8581d3..000000000000 --- a/trunk/include/linux/smpboot.h +++ /dev/null @@ -1,43 +0,0 @@ -#ifndef _LINUX_SMPBOOT_H -#define _LINUX_SMPBOOT_H - -#include - -struct task_struct; -/* Cookie handed to the thread_fn*/ -struct smpboot_thread_data; - -/** - * struct smp_hotplug_thread - CPU hotplug related thread descriptor - * @store: Pointer to per cpu storage for the task pointers - * @list: List head for core management - * @thread_should_run: Check whether the thread should run or not. Called with - * preemption disabled. - * @thread_fn: The associated thread function - * @setup: Optional setup function, called when the thread gets - * operational the first time - * @cleanup: Optional cleanup function, called when the thread - * should stop (module exit) - * @park: Optional park function, called when the thread is - * parked (cpu offline) - * @unpark: Optional unpark function, called when the thread is - * unparked (cpu online) - * @thread_comm: The base name of the thread - */ -struct smp_hotplug_thread { - struct task_struct __percpu **store; - struct list_head list; - int (*thread_should_run)(unsigned int cpu); - void (*thread_fn)(unsigned int cpu); - void (*setup)(unsigned int cpu); - void (*cleanup)(unsigned int cpu, bool online); - void (*park)(unsigned int cpu); - void (*unpark)(unsigned int cpu); - const char *thread_comm; -}; - -int smpboot_register_percpu_thread(struct smp_hotplug_thread *plug_thread); -void smpboot_unregister_percpu_thread(struct smp_hotplug_thread *plug_thread); -int smpboot_thread_schedule(void); - -#endif diff --git a/trunk/include/linux/stallion.h b/trunk/include/linux/stallion.h new file mode 100644 index 000000000000..336af33c6ea4 --- /dev/null +++ b/trunk/include/linux/stallion.h @@ -0,0 +1,147 @@ +/*****************************************************************************/ + +/* + * stallion.h -- stallion multiport serial driver. + * + * Copyright (C) 1996-1998 Stallion Technologies + * Copyright (C) 1994-1996 Greg Ungerer. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/*****************************************************************************/ +#ifndef _STALLION_H +#define _STALLION_H +/*****************************************************************************/ + +/* + * Define important driver constants here. + */ +#define STL_MAXBRDS 4 +#define STL_MAXPANELS 4 +#define STL_MAXBANKS 8 +#define STL_PORTSPERPANEL 16 +#define STL_MAXPORTS 64 +#define STL_MAXDEVS (STL_MAXBRDS * STL_MAXPORTS) + + +/* + * Define a set of structures to hold all the board/panel/port info + * for our ports. These will be dynamically allocated as required. + */ + +/* + * Define a ring queue structure for each port. This will hold the + * TX data waiting to be output. Characters are fed into this buffer + * from the line discipline (or even direct from user space!) and + * then fed into the UARTs during interrupts. Will use a classic ring + * queue here for this. The good thing about this type of ring queue + * is that the head and tail pointers can be updated without interrupt + * protection - since "write" code only needs to change the head, and + * interrupt code only needs to change the tail. + */ +struct stlrq { + char *buf; + char *head; + char *tail; +}; + +/* + * Port, panel and board structures to hold status info about each. + * The board structure contains pointers to structures for each panel + * connected to it, and in turn each panel structure contains pointers + * for each port structure for each port on that panel. Note that + * the port structure also contains the board and panel number that it + * is associated with, this makes it (fairly) easy to get back to the + * board/panel info for a port. + */ +struct stlport { + unsigned long magic; + struct tty_port port; + unsigned int portnr; + unsigned int panelnr; + unsigned int brdnr; + int ioaddr; + int uartaddr; + unsigned int pagenr; + unsigned long istate; + int baud_base; + int custom_divisor; + int close_delay; + int closing_wait; + int openwaitcnt; + int brklen; + unsigned int sigs; + unsigned int rxignoremsk; + unsigned int rxmarkmsk; + unsigned int imr; + unsigned int crenable; + unsigned long clk; + unsigned long hwid; + void *uartp; + comstats_t stats; + struct stlrq tx; +}; + +struct stlpanel { + unsigned long magic; + unsigned int panelnr; + unsigned int brdnr; + unsigned int pagenr; + unsigned int nrports; + int iobase; + void *uartp; + void (*isr)(struct stlpanel *panelp, unsigned int iobase); + unsigned int hwid; + unsigned int ackmask; + struct stlport *ports[STL_PORTSPERPANEL]; +}; + +struct stlbrd { + unsigned long magic; + unsigned int brdnr; + unsigned int brdtype; + unsigned int state; + unsigned int nrpanels; + unsigned int nrports; + unsigned int nrbnks; + int irq; + int irqtype; + int (*isr)(struct stlbrd *brdp); + unsigned int ioaddr1; + unsigned int ioaddr2; + unsigned int iosize1; + unsigned int iosize2; + unsigned int iostatus; + unsigned int ioctrl; + unsigned int ioctrlval; + unsigned int hwid; + unsigned long clk; + unsigned int bnkpageaddr[STL_MAXBANKS]; + unsigned int bnkstataddr[STL_MAXBANKS]; + struct stlpanel *bnk2panel[STL_MAXBANKS]; + struct stlpanel *panels[STL_MAXPANELS]; +}; + + +/* + * Define MAGIC numbers used for above structures. + */ +#define STL_PORTMAGIC 0x5a7182c9 +#define STL_PANELMAGIC 0x7ef621a1 +#define STL_BOARDMAGIC 0xa2267f52 + +/*****************************************************************************/ +#endif diff --git a/trunk/include/linux/string.h b/trunk/include/linux/string.h index b9178812d9df..ffe0442e18d2 100644 --- a/trunk/include/linux/string.h +++ b/trunk/include/linux/string.h @@ -144,8 +144,8 @@ static inline bool strstarts(const char *str, const char *prefix) { return strncmp(str, prefix, strlen(prefix)) == 0; } +#endif extern size_t memweight(const void *ptr, size_t bytes); -#endif /* __KERNEL__ */ #endif /* _LINUX_STRING_H_ */ diff --git a/trunk/include/linux/sunrpc/xprt.h b/trunk/include/linux/sunrpc/xprt.h index bf8c49ff7530..cff40aa7db62 100644 --- a/trunk/include/linux/sunrpc/xprt.h +++ b/trunk/include/linux/sunrpc/xprt.h @@ -114,7 +114,6 @@ struct rpc_xprt_ops { void (*set_buffer_size)(struct rpc_xprt *xprt, size_t sndsize, size_t rcvsize); int (*reserve_xprt)(struct rpc_xprt *xprt, struct rpc_task *task); void (*release_xprt)(struct rpc_xprt *xprt, struct rpc_task *task); - void (*alloc_slot)(struct rpc_xprt *xprt, struct rpc_task *task); void (*rpcbind)(struct rpc_task *task); void (*set_port)(struct rpc_xprt *xprt, unsigned short port); void (*connect)(struct rpc_task *task); @@ -282,8 +281,6 @@ void xprt_connect(struct rpc_task *task); void xprt_reserve(struct rpc_task *task); int xprt_reserve_xprt(struct rpc_xprt *xprt, struct rpc_task *task); int xprt_reserve_xprt_cong(struct rpc_xprt *xprt, struct rpc_task *task); -void xprt_alloc_slot(struct rpc_xprt *xprt, struct rpc_task *task); -void xprt_lock_and_alloc_slot(struct rpc_xprt *xprt, struct rpc_task *task); int xprt_prepare_transmit(struct rpc_task *task); void xprt_transmit(struct rpc_task *task); void xprt_end_transmit(struct rpc_task *task); diff --git a/trunk/include/linux/task_work.h b/trunk/include/linux/task_work.h index ca5a1cf27dae..fb46b03b1852 100644 --- a/trunk/include/linux/task_work.h +++ b/trunk/include/linux/task_work.h @@ -18,7 +18,8 @@ void task_work_run(void); static inline void exit_task_work(struct task_struct *task) { - task_work_run(); + if (unlikely(task->task_works)) + task_work_run(); } #endif /* _LINUX_TASK_WORK_H */ diff --git a/trunk/include/linux/ti_wilink_st.h b/trunk/include/linux/ti_wilink_st.h index 932b76392248..3ca0269dd0b5 100644 --- a/trunk/include/linux/ti_wilink_st.h +++ b/trunk/include/linux/ti_wilink_st.h @@ -281,10 +281,9 @@ struct kim_data_s { long st_kim_start(void *); long st_kim_stop(void *); +void st_kim_recv(void *, const unsigned char *, long count); void st_kim_complete(void *); void kim_st_list_protocols(struct st_data_s *, void *); -void st_kim_recv(void *, const unsigned char *, long); - /* * BTS headers diff --git a/trunk/include/linux/time.h b/trunk/include/linux/time.h index b51e664c83e7..c81c5e40fcb5 100644 --- a/trunk/include/linux/time.h +++ b/trunk/include/linux/time.h @@ -107,36 +107,11 @@ static inline struct timespec timespec_sub(struct timespec lhs, return ts_delta; } -#define KTIME_MAX ((s64)~((u64)1 << 63)) -#if (BITS_PER_LONG == 64) -# define KTIME_SEC_MAX (KTIME_MAX / NSEC_PER_SEC) -#else -# define KTIME_SEC_MAX LONG_MAX -#endif - /* * Returns true if the timespec is norm, false if denorm: */ -static inline bool timespec_valid(const struct timespec *ts) -{ - /* Dates before 1970 are bogus */ - if (ts->tv_sec < 0) - return false; - /* Can't have more nanoseconds then a second */ - if ((unsigned long)ts->tv_nsec >= NSEC_PER_SEC) - return false; - return true; -} - -static inline bool timespec_valid_strict(const struct timespec *ts) -{ - if (!timespec_valid(ts)) - return false; - /* Disallow values that could overflow ktime_t */ - if ((unsigned long long)ts->tv_sec >= KTIME_SEC_MAX) - return false; - return true; -} +#define timespec_valid(ts) \ + (((ts)->tv_sec >= 0) && (((unsigned long) (ts)->tv_nsec) < NSEC_PER_SEC)) extern void read_persistent_clock(struct timespec *ts); extern void read_boot_clock(struct timespec *ts); diff --git a/trunk/include/linux/timer.h b/trunk/include/linux/timer.h index 8c5a197e1587..6abd9138beda 100644 --- a/trunk/include/linux/timer.h +++ b/trunk/include/linux/timer.h @@ -49,112 +49,147 @@ extern struct tvec_base boot_tvec_bases; #endif /* - * Note that all tvec_bases are at least 4 byte aligned and lower two bits - * of base in timer_list is guaranteed to be zero. Use them for flags. + * Note that all tvec_bases are 2 byte aligned and lower bit of + * base in timer_list is guaranteed to be zero. Use the LSB to + * indicate whether the timer is deferrable. * * A deferrable timer will work normally when the system is busy, but * will not cause a CPU to come out of idle just to service it; instead, * the timer will be serviced when the CPU eventually wakes up with a * subsequent non-deferrable timer. - * - * An irqsafe timer is executed with IRQ disabled and it's safe to wait for - * the completion of the running instance from IRQ handlers, for example, - * by calling del_timer_sync(). - * - * Note: The irq disabled callback execution is a special case for - * workqueue locking issues. It's not meant for executing random crap - * with interrupts disabled. Abuse is monitored! */ -#define TIMER_DEFERRABLE 0x1LU -#define TIMER_IRQSAFE 0x2LU +#define TBASE_DEFERRABLE_FLAG (0x1) -#define TIMER_FLAG_MASK 0x3LU - -#define __TIMER_INITIALIZER(_function, _expires, _data, _flags) { \ +#define TIMER_INITIALIZER(_function, _expires, _data) { \ .entry = { .prev = TIMER_ENTRY_STATIC }, \ .function = (_function), \ .expires = (_expires), \ .data = (_data), \ - .base = (void *)((unsigned long)&boot_tvec_bases + (_flags)), \ + .base = &boot_tvec_bases, \ .slack = -1, \ __TIMER_LOCKDEP_MAP_INITIALIZER( \ __FILE__ ":" __stringify(__LINE__)) \ } -#define TIMER_INITIALIZER(_function, _expires, _data) \ - __TIMER_INITIALIZER((_function), (_expires), (_data), 0) +#define TBASE_MAKE_DEFERRED(ptr) ((struct tvec_base *) \ + ((unsigned char *)(ptr) + TBASE_DEFERRABLE_FLAG)) -#define TIMER_DEFERRED_INITIALIZER(_function, _expires, _data) \ - __TIMER_INITIALIZER((_function), (_expires), (_data), TIMER_DEFERRABLE) +#define TIMER_DEFERRED_INITIALIZER(_function, _expires, _data) {\ + .entry = { .prev = TIMER_ENTRY_STATIC }, \ + .function = (_function), \ + .expires = (_expires), \ + .data = (_data), \ + .base = TBASE_MAKE_DEFERRED(&boot_tvec_bases), \ + __TIMER_LOCKDEP_MAP_INITIALIZER( \ + __FILE__ ":" __stringify(__LINE__)) \ + } #define DEFINE_TIMER(_name, _function, _expires, _data) \ struct timer_list _name = \ TIMER_INITIALIZER(_function, _expires, _data) -void init_timer_key(struct timer_list *timer, unsigned int flags, - const char *name, struct lock_class_key *key); - -#ifdef CONFIG_DEBUG_OBJECTS_TIMERS -extern void init_timer_on_stack_key(struct timer_list *timer, - unsigned int flags, const char *name, - struct lock_class_key *key); -extern void destroy_timer_on_stack(struct timer_list *timer); -#else -static inline void destroy_timer_on_stack(struct timer_list *timer) { } -static inline void init_timer_on_stack_key(struct timer_list *timer, - unsigned int flags, const char *name, - struct lock_class_key *key) -{ - init_timer_key(timer, flags, name, key); -} -#endif +void init_timer_key(struct timer_list *timer, + const char *name, + struct lock_class_key *key); +void init_timer_deferrable_key(struct timer_list *timer, + const char *name, + struct lock_class_key *key); #ifdef CONFIG_LOCKDEP -#define __init_timer(_timer, _flags) \ +#define init_timer(timer) \ do { \ static struct lock_class_key __key; \ - init_timer_key((_timer), (_flags), #_timer, &__key); \ + init_timer_key((timer), #timer, &__key); \ } while (0) -#define __init_timer_on_stack(_timer, _flags) \ +#define init_timer_deferrable(timer) \ do { \ static struct lock_class_key __key; \ - init_timer_on_stack_key((_timer), (_flags), #_timer, &__key); \ + init_timer_deferrable_key((timer), #timer, &__key); \ } while (0) -#else -#define __init_timer(_timer, _flags) \ - init_timer_key((_timer), (_flags), NULL, NULL) -#define __init_timer_on_stack(_timer, _flags) \ - init_timer_on_stack_key((_timer), (_flags), NULL, NULL) -#endif -#define init_timer(timer) \ - __init_timer((timer), 0) -#define init_timer_deferrable(timer) \ - __init_timer((timer), TIMER_DEFERRABLE) #define init_timer_on_stack(timer) \ - __init_timer_on_stack((timer), 0) - -#define __setup_timer(_timer, _fn, _data, _flags) \ do { \ - __init_timer((_timer), (_flags)); \ - (_timer)->function = (_fn); \ - (_timer)->data = (_data); \ + static struct lock_class_key __key; \ + init_timer_on_stack_key((timer), #timer, &__key); \ } while (0) -#define __setup_timer_on_stack(_timer, _fn, _data, _flags) \ +#define setup_timer(timer, fn, data) \ do { \ - __init_timer_on_stack((_timer), (_flags)); \ - (_timer)->function = (_fn); \ - (_timer)->data = (_data); \ + static struct lock_class_key __key; \ + setup_timer_key((timer), #timer, &__key, (fn), (data));\ } while (0) -#define setup_timer(timer, fn, data) \ - __setup_timer((timer), (fn), (data), 0) #define setup_timer_on_stack(timer, fn, data) \ - __setup_timer_on_stack((timer), (fn), (data), 0) + do { \ + static struct lock_class_key __key; \ + setup_timer_on_stack_key((timer), #timer, &__key, \ + (fn), (data)); \ + } while (0) #define setup_deferrable_timer_on_stack(timer, fn, data) \ - __setup_timer_on_stack((timer), (fn), (data), TIMER_DEFERRABLE) + do { \ + static struct lock_class_key __key; \ + setup_deferrable_timer_on_stack_key((timer), #timer, \ + &__key, (fn), \ + (data)); \ + } while (0) +#else +#define init_timer(timer)\ + init_timer_key((timer), NULL, NULL) +#define init_timer_deferrable(timer)\ + init_timer_deferrable_key((timer), NULL, NULL) +#define init_timer_on_stack(timer)\ + init_timer_on_stack_key((timer), NULL, NULL) +#define setup_timer(timer, fn, data)\ + setup_timer_key((timer), NULL, NULL, (fn), (data)) +#define setup_timer_on_stack(timer, fn, data)\ + setup_timer_on_stack_key((timer), NULL, NULL, (fn), (data)) +#define setup_deferrable_timer_on_stack(timer, fn, data)\ + setup_deferrable_timer_on_stack_key((timer), NULL, NULL, (fn), (data)) +#endif + +#ifdef CONFIG_DEBUG_OBJECTS_TIMERS +extern void init_timer_on_stack_key(struct timer_list *timer, + const char *name, + struct lock_class_key *key); +extern void destroy_timer_on_stack(struct timer_list *timer); +#else +static inline void destroy_timer_on_stack(struct timer_list *timer) { } +static inline void init_timer_on_stack_key(struct timer_list *timer, + const char *name, + struct lock_class_key *key) +{ + init_timer_key(timer, name, key); +} +#endif + +static inline void setup_timer_key(struct timer_list * timer, + const char *name, + struct lock_class_key *key, + void (*function)(unsigned long), + unsigned long data) +{ + timer->function = function; + timer->data = data; + init_timer_key(timer, name, key); +} + +static inline void setup_timer_on_stack_key(struct timer_list *timer, + const char *name, + struct lock_class_key *key, + void (*function)(unsigned long), + unsigned long data) +{ + timer->function = function; + timer->data = data; + init_timer_on_stack_key(timer, name, key); +} + +extern void setup_deferrable_timer_on_stack_key(struct timer_list *timer, + const char *name, + struct lock_class_key *key, + void (*function)(unsigned long), + unsigned long data); /** * timer_pending - is a timer pending? diff --git a/trunk/include/linux/timex.h b/trunk/include/linux/timex.h index 7c5ceb20e03a..99bc88b1fc02 100644 --- a/trunk/include/linux/timex.h +++ b/trunk/include/linux/timex.h @@ -232,7 +232,7 @@ struct timex { * estimated error = NTP dispersion. */ extern unsigned long tick_usec; /* USER_HZ period (usec) */ -extern unsigned long tick_nsec; /* SHIFTED_HZ period (nsec) */ +extern unsigned long tick_nsec; /* ACTHZ period (nsec) */ extern void ntp_init(void); extern void ntp_clear(void); diff --git a/trunk/include/linux/topology.h b/trunk/include/linux/topology.h index d3cf0d6e7712..e91cd43394df 100644 --- a/trunk/include/linux/topology.h +++ b/trunk/include/linux/topology.h @@ -129,6 +129,7 @@ int arch_update_cpu_topology(void); | 1*SD_BALANCE_FORK \ | 0*SD_BALANCE_WAKE \ | 1*SD_WAKE_AFFINE \ + | 0*SD_PREFER_LOCAL \ | 0*SD_SHARE_CPUPOWER \ | 1*SD_SHARE_PKG_RESOURCES \ | 0*SD_SERIALIZE \ @@ -159,10 +160,10 @@ int arch_update_cpu_topology(void); | 1*SD_BALANCE_FORK \ | 0*SD_BALANCE_WAKE \ | 1*SD_WAKE_AFFINE \ + | 0*SD_PREFER_LOCAL \ | 0*SD_SHARE_CPUPOWER \ | 0*SD_SHARE_PKG_RESOURCES \ | 0*SD_SERIALIZE \ - | 1*SD_PREFER_SIBLING \ , \ .last_balance = jiffies, \ .balance_interval = 1, \ diff --git a/trunk/include/linux/tracepoint.h b/trunk/include/linux/tracepoint.h index 2f322c38bd4d..802de56c41e8 100644 --- a/trunk/include/linux/tracepoint.h +++ b/trunk/include/linux/tracepoint.h @@ -136,22 +136,6 @@ static inline void tracepoint_synchronize_unregister(void) postrcu; \ } while (0) -#ifndef MODULE -#define __DECLARE_TRACE_RCU(name, proto, args, cond, data_proto, data_args) \ - static inline void trace_##name##_rcuidle(proto) \ - { \ - if (static_key_false(&__tracepoint_##name.key)) \ - __DO_TRACE(&__tracepoint_##name, \ - TP_PROTO(data_proto), \ - TP_ARGS(data_args), \ - TP_CONDITION(cond), \ - rcu_idle_exit(), \ - rcu_idle_enter()); \ - } -#else -#define __DECLARE_TRACE_RCU(name, proto, args, cond, data_proto, data_args) -#endif - /* * Make sure the alignment of the structure in the __tracepoints section will * not add unwanted padding between the beginning of the section and the @@ -167,8 +151,16 @@ static inline void tracepoint_synchronize_unregister(void) TP_ARGS(data_args), \ TP_CONDITION(cond),,); \ } \ - __DECLARE_TRACE_RCU(name, PARAMS(proto), PARAMS(args), \ - PARAMS(cond), PARAMS(data_proto), PARAMS(data_args)) \ + static inline void trace_##name##_rcuidle(proto) \ + { \ + if (static_key_false(&__tracepoint_##name.key)) \ + __DO_TRACE(&__tracepoint_##name, \ + TP_PROTO(data_proto), \ + TP_ARGS(data_args), \ + TP_CONDITION(cond), \ + rcu_idle_exit(), \ + rcu_idle_enter()); \ + } \ static inline int \ register_trace_##name(void (*probe)(data_proto), void *data) \ { \ diff --git a/trunk/include/linux/tty.h b/trunk/include/linux/tty.h index 1509b86825d8..9f47ab540f65 100644 --- a/trunk/include/linux/tty.h +++ b/trunk/include/linux/tty.h @@ -43,7 +43,6 @@ #include #include #include -#include @@ -104,28 +103,28 @@ struct tty_bufhead { #define TTY_PARITY 3 #define TTY_OVERRUN 4 -#define INTR_CHAR(tty) ((tty)->termios.c_cc[VINTR]) -#define QUIT_CHAR(tty) ((tty)->termios.c_cc[VQUIT]) -#define ERASE_CHAR(tty) ((tty)->termios.c_cc[VERASE]) -#define KILL_CHAR(tty) ((tty)->termios.c_cc[VKILL]) -#define EOF_CHAR(tty) ((tty)->termios.c_cc[VEOF]) -#define TIME_CHAR(tty) ((tty)->termios.c_cc[VTIME]) -#define MIN_CHAR(tty) ((tty)->termios.c_cc[VMIN]) -#define SWTC_CHAR(tty) ((tty)->termios.c_cc[VSWTC]) -#define START_CHAR(tty) ((tty)->termios.c_cc[VSTART]) -#define STOP_CHAR(tty) ((tty)->termios.c_cc[VSTOP]) -#define SUSP_CHAR(tty) ((tty)->termios.c_cc[VSUSP]) -#define EOL_CHAR(tty) ((tty)->termios.c_cc[VEOL]) -#define REPRINT_CHAR(tty) ((tty)->termios.c_cc[VREPRINT]) -#define DISCARD_CHAR(tty) ((tty)->termios.c_cc[VDISCARD]) -#define WERASE_CHAR(tty) ((tty)->termios.c_cc[VWERASE]) -#define LNEXT_CHAR(tty) ((tty)->termios.c_cc[VLNEXT]) -#define EOL2_CHAR(tty) ((tty)->termios.c_cc[VEOL2]) - -#define _I_FLAG(tty, f) ((tty)->termios.c_iflag & (f)) -#define _O_FLAG(tty, f) ((tty)->termios.c_oflag & (f)) -#define _C_FLAG(tty, f) ((tty)->termios.c_cflag & (f)) -#define _L_FLAG(tty, f) ((tty)->termios.c_lflag & (f)) +#define INTR_CHAR(tty) ((tty)->termios->c_cc[VINTR]) +#define QUIT_CHAR(tty) ((tty)->termios->c_cc[VQUIT]) +#define ERASE_CHAR(tty) ((tty)->termios->c_cc[VERASE]) +#define KILL_CHAR(tty) ((tty)->termios->c_cc[VKILL]) +#define EOF_CHAR(tty) ((tty)->termios->c_cc[VEOF]) +#define TIME_CHAR(tty) ((tty)->termios->c_cc[VTIME]) +#define MIN_CHAR(tty) ((tty)->termios->c_cc[VMIN]) +#define SWTC_CHAR(tty) ((tty)->termios->c_cc[VSWTC]) +#define START_CHAR(tty) ((tty)->termios->c_cc[VSTART]) +#define STOP_CHAR(tty) ((tty)->termios->c_cc[VSTOP]) +#define SUSP_CHAR(tty) ((tty)->termios->c_cc[VSUSP]) +#define EOL_CHAR(tty) ((tty)->termios->c_cc[VEOL]) +#define REPRINT_CHAR(tty) ((tty)->termios->c_cc[VREPRINT]) +#define DISCARD_CHAR(tty) ((tty)->termios->c_cc[VDISCARD]) +#define WERASE_CHAR(tty) ((tty)->termios->c_cc[VWERASE]) +#define LNEXT_CHAR(tty) ((tty)->termios->c_cc[VLNEXT]) +#define EOL2_CHAR(tty) ((tty)->termios->c_cc[VEOL2]) + +#define _I_FLAG(tty, f) ((tty)->termios->c_iflag & (f)) +#define _O_FLAG(tty, f) ((tty)->termios->c_oflag & (f)) +#define _C_FLAG(tty, f) ((tty)->termios->c_cflag & (f)) +#define _L_FLAG(tty, f) ((tty)->termios->c_lflag & (f)) #define I_IGNBRK(tty) _I_FLAG((tty), IGNBRK) #define I_BRKINT(tty) _I_FLAG((tty), BRKINT) @@ -269,11 +268,10 @@ struct tty_struct { struct mutex ldisc_mutex; struct tty_ldisc *ldisc; - struct mutex legacy_mutex; struct mutex termios_mutex; spinlock_t ctrl_lock; /* Termios values are protected by the termios mutex */ - struct ktermios termios, termios_locked; + struct ktermios *termios, *termios_locked; struct termiox *termiox; /* May be NULL for unsupported */ char name[64]; struct pid *pgrp; /* Protected by ctrl lock */ @@ -412,10 +410,6 @@ extern int tty_register_driver(struct tty_driver *driver); extern int tty_unregister_driver(struct tty_driver *driver); extern struct device *tty_register_device(struct tty_driver *driver, unsigned index, struct device *dev); -extern struct device *tty_register_device_attr(struct tty_driver *driver, - unsigned index, struct device *device, - void *drvdata, - const struct attribute_group **attr_grp); extern void tty_unregister_device(struct tty_driver *driver, unsigned index); extern int tty_read_raw_data(struct tty_struct *tty, unsigned char *bufp, int buflen); @@ -429,6 +423,7 @@ extern void tty_unthrottle(struct tty_struct *tty); extern int tty_do_resize(struct tty_struct *tty, struct winsize *ws); extern void tty_driver_remove_tty(struct tty_driver *driver, struct tty_struct *tty); +extern void tty_shutdown(struct tty_struct *tty); extern void tty_free_termios(struct tty_struct *tty); extern int is_current_pgrp_orphaned(void); extern struct pid *tty_get_pgrp(struct tty_struct *tty); @@ -502,15 +497,6 @@ extern int tty_write_lock(struct tty_struct *tty, int ndelay); #define tty_is_writelocked(tty) (mutex_is_locked(&tty->atomic_write_lock)) extern void tty_port_init(struct tty_port *port); -extern void tty_port_link_device(struct tty_port *port, - struct tty_driver *driver, unsigned index); -extern struct device *tty_port_register_device(struct tty_port *port, - struct tty_driver *driver, unsigned index, - struct device *device); -extern struct device *tty_port_register_device_attr(struct tty_port *port, - struct tty_driver *driver, unsigned index, - struct device *device, void *drvdata, - const struct attribute_group **attr_grp); extern int tty_port_alloc_xmit_buf(struct tty_port *port); extern void tty_port_free_xmit_buf(struct tty_port *port); extern void tty_port_put(struct tty_port *port); @@ -522,12 +508,6 @@ static inline struct tty_port *tty_port_get(struct tty_port *port) return port; } -/* If the cts flow control is enabled, return true. */ -static inline bool tty_port_cts_enabled(struct tty_port *port) -{ - return port->flags & ASYNC_CTS_FLOW; -} - extern struct tty_struct *tty_port_tty_get(struct tty_port *port); extern void tty_port_tty_set(struct tty_port *port, struct tty_struct *tty); extern int tty_port_carrier_raised(struct tty_port *port); @@ -541,8 +521,6 @@ extern int tty_port_close_start(struct tty_port *port, extern void tty_port_close_end(struct tty_port *port, struct tty_struct *tty); extern void tty_port_close(struct tty_port *port, struct tty_struct *tty, struct file *filp); -extern int tty_port_install(struct tty_port *port, struct tty_driver *driver, - struct tty_struct *tty); extern int tty_port_open(struct tty_port *port, struct tty_struct *tty, struct file *filp); static inline int tty_port_users(struct tty_port *port) @@ -627,12 +605,8 @@ extern long vt_compat_ioctl(struct tty_struct *tty, /* tty_mutex.c */ /* functions for preparation of BKL removal */ -extern void __lockfunc tty_lock(struct tty_struct *tty); -extern void __lockfunc tty_unlock(struct tty_struct *tty); -extern void __lockfunc tty_lock_pair(struct tty_struct *tty, - struct tty_struct *tty2); -extern void __lockfunc tty_unlock_pair(struct tty_struct *tty, - struct tty_struct *tty2); +extern void __lockfunc tty_lock(void) __acquires(tty_lock); +extern void __lockfunc tty_unlock(void) __releases(tty_lock); /* * this shall be called only from where BTM is held (like close) @@ -647,9 +621,9 @@ extern void __lockfunc tty_unlock_pair(struct tty_struct *tty, static inline void tty_wait_until_sent_from_close(struct tty_struct *tty, long timeout) { - tty_unlock(tty); /* tty->ops->close holds the BTM, drop it while waiting */ + tty_unlock(); /* tty->ops->close holds the BTM, drop it while waiting */ tty_wait_until_sent(tty, timeout); - tty_lock(tty); + tty_lock(); } /* @@ -664,16 +638,16 @@ static inline void tty_wait_until_sent_from_close(struct tty_struct *tty, * * Do not use in new code. */ -#define wait_event_interruptible_tty(tty, wq, condition) \ +#define wait_event_interruptible_tty(wq, condition) \ ({ \ int __ret = 0; \ if (!(condition)) { \ - __wait_event_interruptible_tty(tty, wq, condition, __ret); \ + __wait_event_interruptible_tty(wq, condition, __ret); \ } \ __ret; \ }) -#define __wait_event_interruptible_tty(tty, wq, condition, ret) \ +#define __wait_event_interruptible_tty(wq, condition, ret) \ do { \ DEFINE_WAIT(__wait); \ \ @@ -682,9 +656,9 @@ do { \ if (condition) \ break; \ if (!signal_pending(current)) { \ - tty_unlock(tty); \ + tty_unlock(); \ schedule(); \ - tty_lock(tty); \ + tty_lock(); \ continue; \ } \ ret = -ERESTARTSYS; \ diff --git a/trunk/include/linux/tty_driver.h b/trunk/include/linux/tty_driver.h index dd976cfb6131..6e6dbb7447b6 100644 --- a/trunk/include/linux/tty_driver.h +++ b/trunk/include/linux/tty_driver.h @@ -45,9 +45,14 @@ * * void (*shutdown)(struct tty_struct * tty); * - * This routine is called under the tty lock when a particular tty device - * is closed for the last time. It executes before the tty resources - * are freed so may execute while another function holds a tty kref. + * This routine is called synchronously when a particular tty device + * is closed for the last time freeing up the resources. + * Note that tty_shutdown() is not called if ops->shutdown is defined. + * This means one is responsible to take care of calling ops->remove (e.g. + * via tty_driver_remove_tty) and releasing tty->termios. + * Note that this hook may be called from *all* the contexts where one + * uses tty refcounting (e.g. tty_port_tty_get). + * * * void (*cleanup)(struct tty_struct * tty); * @@ -289,18 +294,18 @@ struct tty_operations { struct tty_driver { int magic; /* magic number for this structure */ struct kref kref; /* Reference management */ - struct cdev *cdevs; + struct cdev cdev; struct module *owner; const char *driver_name; const char *name; int name_base; /* offset of printed name */ int major; /* major device number */ int minor_start; /* start of minor device number */ - unsigned int num; /* number of devices allocated */ + int num; /* number of devices allocated */ short type; /* type of tty driver */ short subtype; /* subtype of tty driver */ struct ktermios init_termios; /* Initial termios */ - unsigned long flags; /* tty driver flags */ + int flags; /* tty driver flags */ struct proc_dir_entry *proc_entry; /* /proc fs entry */ struct tty_driver *other; /* only used for the PTY driver */ @@ -308,7 +313,6 @@ struct tty_driver { * Pointer to the tty data structures */ struct tty_struct **ttys; - struct tty_port **ports; struct ktermios **termios; void *driver_state; @@ -322,8 +326,7 @@ struct tty_driver { extern struct list_head tty_drivers; -extern struct tty_driver *__tty_alloc_driver(unsigned int lines, - struct module *owner, unsigned long flags); +extern struct tty_driver *__alloc_tty_driver(int lines, struct module *owner); extern void put_tty_driver(struct tty_driver *driver); extern void tty_set_operations(struct tty_driver *driver, const struct tty_operations *op); @@ -331,21 +334,7 @@ extern struct tty_driver *tty_find_polling_driver(char *name, int *line); extern void tty_driver_kref_put(struct tty_driver *driver); -/* Use TTY_DRIVER_* flags below */ -#define tty_alloc_driver(lines, flags) \ - __tty_alloc_driver(lines, THIS_MODULE, flags) - -/* - * DEPRECATED Do not use this in new code, use tty_alloc_driver instead. - * (And change the return value checks.) - */ -static inline struct tty_driver *alloc_tty_driver(unsigned int lines) -{ - struct tty_driver *ret = tty_alloc_driver(lines, 0); - if (IS_ERR(ret)) - return NULL; - return ret; -} +#define alloc_tty_driver(lines) __alloc_tty_driver(lines, THIS_MODULE) static inline struct tty_driver *tty_driver_kref_get(struct tty_driver *d) { @@ -391,14 +380,6 @@ static inline struct tty_driver *tty_driver_kref_get(struct tty_driver *d) * the requested timeout to the caller instead of using a simple * on/off interface. * - * TTY_DRIVER_DYNAMIC_ALLOC -- do not allocate structures which are - * needed per line for this driver as it would waste memory. - * The driver will take care. - * - * TTY_DRIVER_UNNUMBERED_NODE -- do not create numbered /dev nodes. In - * other words create /dev/ttyprintk and not /dev/ttyprintk0. - * Applicable only when a driver for a single tty device is - * being allocated. */ #define TTY_DRIVER_INSTALLED 0x0001 #define TTY_DRIVER_RESET_TERMIOS 0x0002 @@ -406,8 +387,6 @@ static inline struct tty_driver *tty_driver_kref_get(struct tty_driver *d) #define TTY_DRIVER_DYNAMIC_DEV 0x0008 #define TTY_DRIVER_DEVPTS_MEM 0x0010 #define TTY_DRIVER_HARDWARE_BREAK 0x0020 -#define TTY_DRIVER_DYNAMIC_ALLOC 0x0040 -#define TTY_DRIVER_UNNUMBERED_NODE 0x0080 /* tty driver types */ #define TTY_DRIVER_TYPE_SYSTEM 0x0001 diff --git a/trunk/include/linux/tty_flags.h b/trunk/include/linux/tty_flags.h deleted file mode 100644 index eefcb483a2c0..000000000000 --- a/trunk/include/linux/tty_flags.h +++ /dev/null @@ -1,78 +0,0 @@ -#ifndef _LINUX_TTY_FLAGS_H -#define _LINUX_TTY_FLAGS_H - -/* - * Definitions for async_struct (and serial_struct) flags field also - * shared by the tty_port flags structures. - * - * Define ASYNCB_* for convenient use with {test,set,clear}_bit. - */ -#define ASYNCB_HUP_NOTIFY 0 /* Notify getty on hangups and closes - * on the callout port */ -#define ASYNCB_FOURPORT 1 /* Set OU1, OUT2 per AST Fourport settings */ -#define ASYNCB_SAK 2 /* Secure Attention Key (Orange book) */ -#define ASYNCB_SPLIT_TERMIOS 3 /* Separate termios for dialin/callout */ -#define ASYNCB_SPD_HI 4 /* Use 56000 instead of 38400 bps */ -#define ASYNCB_SPD_VHI 5 /* Use 115200 instead of 38400 bps */ -#define ASYNCB_SKIP_TEST 6 /* Skip UART test during autoconfiguration */ -#define ASYNCB_AUTO_IRQ 7 /* Do automatic IRQ during - * autoconfiguration */ -#define ASYNCB_SESSION_LOCKOUT 8 /* Lock out cua opens based on session */ -#define ASYNCB_PGRP_LOCKOUT 9 /* Lock out cua opens based on pgrp */ -#define ASYNCB_CALLOUT_NOHUP 10 /* Don't do hangups for cua device */ -#define ASYNCB_HARDPPS_CD 11 /* Call hardpps when CD goes high */ -#define ASYNCB_SPD_SHI 12 /* Use 230400 instead of 38400 bps */ -#define ASYNCB_LOW_LATENCY 13 /* Request low latency behaviour */ -#define ASYNCB_BUGGY_UART 14 /* This is a buggy UART, skip some safety - * checks. Note: can be dangerous! */ -#define ASYNCB_AUTOPROBE 15 /* Port was autoprobed by PCI or PNP code */ -#define ASYNCB_LAST_USER 15 - -/* Internal flags used only by kernel */ -#define ASYNCB_INITIALIZED 31 /* Serial port was initialized */ -#define ASYNCB_SUSPENDED 30 /* Serial port is suspended */ -#define ASYNCB_NORMAL_ACTIVE 29 /* Normal device is active */ -#define ASYNCB_BOOT_AUTOCONF 28 /* Autoconfigure port on bootup */ -#define ASYNCB_CLOSING 27 /* Serial port is closing */ -#define ASYNCB_CTS_FLOW 26 /* Do CTS flow control */ -#define ASYNCB_CHECK_CD 25 /* i.e., CLOCAL */ -#define ASYNCB_SHARE_IRQ 24 /* for multifunction cards, no longer used */ -#define ASYNCB_CONS_FLOW 23 /* flow control for console */ -#define ASYNCB_FIRST_KERNEL 22 - -#define ASYNC_HUP_NOTIFY (1U << ASYNCB_HUP_NOTIFY) -#define ASYNC_SUSPENDED (1U << ASYNCB_SUSPENDED) -#define ASYNC_FOURPORT (1U << ASYNCB_FOURPORT) -#define ASYNC_SAK (1U << ASYNCB_SAK) -#define ASYNC_SPLIT_TERMIOS (1U << ASYNCB_SPLIT_TERMIOS) -#define ASYNC_SPD_HI (1U << ASYNCB_SPD_HI) -#define ASYNC_SPD_VHI (1U << ASYNCB_SPD_VHI) -#define ASYNC_SKIP_TEST (1U << ASYNCB_SKIP_TEST) -#define ASYNC_AUTO_IRQ (1U << ASYNCB_AUTO_IRQ) -#define ASYNC_SESSION_LOCKOUT (1U << ASYNCB_SESSION_LOCKOUT) -#define ASYNC_PGRP_LOCKOUT (1U << ASYNCB_PGRP_LOCKOUT) -#define ASYNC_CALLOUT_NOHUP (1U << ASYNCB_CALLOUT_NOHUP) -#define ASYNC_HARDPPS_CD (1U << ASYNCB_HARDPPS_CD) -#define ASYNC_SPD_SHI (1U << ASYNCB_SPD_SHI) -#define ASYNC_LOW_LATENCY (1U << ASYNCB_LOW_LATENCY) -#define ASYNC_BUGGY_UART (1U << ASYNCB_BUGGY_UART) -#define ASYNC_AUTOPROBE (1U << ASYNCB_AUTOPROBE) - -#define ASYNC_FLAGS ((1U << (ASYNCB_LAST_USER + 1)) - 1) -#define ASYNC_USR_MASK (ASYNC_SPD_MASK|ASYNC_CALLOUT_NOHUP| \ - ASYNC_LOW_LATENCY) -#define ASYNC_SPD_CUST (ASYNC_SPD_HI|ASYNC_SPD_VHI) -#define ASYNC_SPD_WARP (ASYNC_SPD_HI|ASYNC_SPD_SHI) -#define ASYNC_SPD_MASK (ASYNC_SPD_HI|ASYNC_SPD_VHI|ASYNC_SPD_SHI) - -#define ASYNC_INITIALIZED (1U << ASYNCB_INITIALIZED) -#define ASYNC_NORMAL_ACTIVE (1U << ASYNCB_NORMAL_ACTIVE) -#define ASYNC_BOOT_AUTOCONF (1U << ASYNCB_BOOT_AUTOCONF) -#define ASYNC_CLOSING (1U << ASYNCB_CLOSING) -#define ASYNC_CTS_FLOW (1U << ASYNCB_CTS_FLOW) -#define ASYNC_CHECK_CD (1U << ASYNCB_CHECK_CD) -#define ASYNC_SHARE_IRQ (1U << ASYNCB_SHARE_IRQ) -#define ASYNC_CONS_FLOW (1U << ASYNCB_CONS_FLOW) -#define ASYNC_INTERNAL_FLAGS (~((1U << ASYNCB_FIRST_KERNEL) - 1)) - -#endif diff --git a/trunk/include/linux/uprobes.h b/trunk/include/linux/uprobes.h index e6f0331e3d45..efe4b3308c74 100644 --- a/trunk/include/linux/uprobes.h +++ b/trunk/include/linux/uprobes.h @@ -99,27 +99,25 @@ struct xol_area { struct uprobes_state { struct xol_area *xol_area; + atomic_t count; }; - extern int __weak set_swbp(struct arch_uprobe *aup, struct mm_struct *mm, unsigned long vaddr); -extern int __weak set_orig_insn(struct arch_uprobe *aup, struct mm_struct *mm, unsigned long vaddr); +extern int __weak set_orig_insn(struct arch_uprobe *aup, struct mm_struct *mm, unsigned long vaddr, bool verify); extern bool __weak is_swbp_insn(uprobe_opcode_t *insn); extern int uprobe_register(struct inode *inode, loff_t offset, struct uprobe_consumer *uc); extern void uprobe_unregister(struct inode *inode, loff_t offset, struct uprobe_consumer *uc); extern int uprobe_mmap(struct vm_area_struct *vma); extern void uprobe_munmap(struct vm_area_struct *vma, unsigned long start, unsigned long end); -extern void uprobe_dup_mmap(struct mm_struct *oldmm, struct mm_struct *newmm); extern void uprobe_free_utask(struct task_struct *t); extern void uprobe_copy_process(struct task_struct *t); extern unsigned long __weak uprobe_get_swbp_addr(struct pt_regs *regs); -extern void __weak arch_uprobe_enable_step(struct arch_uprobe *arch); -extern void __weak arch_uprobe_disable_step(struct arch_uprobe *arch); extern int uprobe_post_sstep_notifier(struct pt_regs *regs); extern int uprobe_pre_sstep_notifier(struct pt_regs *regs); extern void uprobe_notify_resume(struct pt_regs *regs); extern bool uprobe_deny_signal(void); extern bool __weak arch_uprobe_skip_sstep(struct arch_uprobe *aup, struct pt_regs *regs); extern void uprobe_clear_state(struct mm_struct *mm); +extern void uprobe_reset_state(struct mm_struct *mm); #else /* !CONFIG_UPROBES */ struct uprobes_state { }; @@ -140,10 +138,6 @@ static inline void uprobe_munmap(struct vm_area_struct *vma, unsigned long start, unsigned long end) { } -static inline void -uprobe_dup_mmap(struct mm_struct *oldmm, struct mm_struct *newmm) -{ -} static inline void uprobe_notify_resume(struct pt_regs *regs) { } @@ -164,5 +158,8 @@ static inline void uprobe_copy_process(struct task_struct *t) static inline void uprobe_clear_state(struct mm_struct *mm) { } +static inline void uprobe_reset_state(struct mm_struct *mm) +{ +} #endif /* !CONFIG_UPROBES */ #endif /* _LINUX_UPROBES_H */ diff --git a/trunk/include/linux/w1-gpio.h b/trunk/include/linux/w1-gpio.h index 065e3ae79ab0..3adeff82212f 100644 --- a/trunk/include/linux/w1-gpio.h +++ b/trunk/include/linux/w1-gpio.h @@ -19,7 +19,6 @@ struct w1_gpio_platform_data { unsigned int pin; unsigned int is_open_drain:1; void (*enable_external_pullup)(int enable); - unsigned int ext_pullup_enable_pin; }; #endif /* _LINUX_W1_GPIO_H */ diff --git a/trunk/include/linux/writeback.h b/trunk/include/linux/writeback.h index 50c3e8fa06a8..c66fe3332d83 100644 --- a/trunk/include/linux/writeback.h +++ b/trunk/include/linux/writeback.h @@ -104,6 +104,7 @@ static inline void wait_on_inode(struct inode *inode) wait_on_bit(&inode->i_state, __I_NEW, inode_wait, TASK_UNINTERRUPTIBLE); } + /* * mm/page-writeback.c */ diff --git a/trunk/include/linux/xfrm.h b/trunk/include/linux/xfrm.h index 28e493b5b94c..22e61fdf75a2 100644 --- a/trunk/include/linux/xfrm.h +++ b/trunk/include/linux/xfrm.h @@ -84,8 +84,6 @@ struct xfrm_replay_state { __u32 bitmap; }; -#define XFRMA_REPLAY_ESN_MAX 4096 - struct xfrm_replay_state_esn { unsigned int bmp_len; __u32 oseq; diff --git a/trunk/include/net/bluetooth/smp.h b/trunk/include/net/bluetooth/smp.h index 8b27927b2a55..ca356a734920 100644 --- a/trunk/include/net/bluetooth/smp.h +++ b/trunk/include/net/bluetooth/smp.h @@ -136,7 +136,7 @@ struct smp_chan { }; /* SMP Commands */ -int smp_conn_security(struct hci_conn *hcon, __u8 sec_level); +int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level); int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb); int smp_distribute_keys(struct l2cap_conn *conn, __u8 force); int smp_user_confirm_reply(struct hci_conn *conn, u16 mgmt_op, __le32 passkey); diff --git a/trunk/include/net/cfg80211.h b/trunk/include/net/cfg80211.h index 3d254e10ff30..493fa0c79005 100644 --- a/trunk/include/net/cfg80211.h +++ b/trunk/include/net/cfg80211.h @@ -96,7 +96,6 @@ enum ieee80211_band { * is not permitted. * @IEEE80211_CHAN_NO_HT40MINUS: extension channel below this channel * is not permitted. - * @IEEE80211_CHAN_NO_OFDM: OFDM is not allowed on this channel. */ enum ieee80211_channel_flags { IEEE80211_CHAN_DISABLED = 1<<0, @@ -105,7 +104,6 @@ enum ieee80211_channel_flags { IEEE80211_CHAN_RADAR = 1<<3, IEEE80211_CHAN_NO_HT40PLUS = 1<<4, IEEE80211_CHAN_NO_HT40MINUS = 1<<5, - IEEE80211_CHAN_NO_OFDM = 1<<6, }; #define IEEE80211_CHAN_NO_HT40 \ diff --git a/trunk/include/net/codel.h b/trunk/include/net/codel.h index 389cf621161d..550debfc2403 100644 --- a/trunk/include/net/codel.h +++ b/trunk/include/net/codel.h @@ -305,8 +305,6 @@ static struct sk_buff *codel_dequeue(struct Qdisc *sch, } } } else if (drop) { - u32 delta; - if (params->ecn && INET_ECN_set_ce(skb)) { stats->ecn_mark++; } else { @@ -322,11 +320,9 @@ static struct sk_buff *codel_dequeue(struct Qdisc *sch, * assume that the drop rate that controlled the queue on the * last cycle is a good starting point to control it now. */ - delta = vars->count - vars->lastcount; - if (delta > 1 && - codel_time_before(now - vars->drop_next, + if (codel_time_before(now - vars->drop_next, 16 * params->interval)) { - vars->count = delta; + vars->count = (vars->count - vars->lastcount) | 1; /* we dont care if rec_inv_sqrt approximation * is not very precise : * Next Newton steps will correct it quadratically. diff --git a/trunk/include/net/dst.h b/trunk/include/net/dst.h index 621e3513ef5e..baf597890064 100644 --- a/trunk/include/net/dst.h +++ b/trunk/include/net/dst.h @@ -110,7 +110,7 @@ struct dst_entry { }; extern u32 *dst_cow_metrics_generic(struct dst_entry *dst, unsigned long old); -extern const u32 dst_default_metrics[]; +extern const u32 dst_default_metrics[RTAX_MAX]; #define DST_METRICS_READ_ONLY 0x1UL #define __DST_METRICS_PTR(Y) \ diff --git a/trunk/include/net/inet_connection_sock.h b/trunk/include/net/inet_connection_sock.h index ba1d3615acbb..5ee66f517b4f 100644 --- a/trunk/include/net/inet_connection_sock.h +++ b/trunk/include/net/inet_connection_sock.h @@ -39,7 +39,6 @@ struct inet_connection_sock_af_ops { int (*queue_xmit)(struct sk_buff *skb, struct flowi *fl); void (*send_check)(struct sock *sk, struct sk_buff *skb); int (*rebuild_header)(struct sock *sk); - void (*sk_rx_dst_set)(struct sock *sk, const struct sk_buff *skb); int (*conn_request)(struct sock *sk, struct sk_buff *skb); struct sock *(*syn_recv_sock)(struct sock *sk, struct sk_buff *skb, struct request_sock *req, diff --git a/trunk/include/net/inet_sock.h b/trunk/include/net/inet_sock.h index 613cfa401672..83b567fe1941 100644 --- a/trunk/include/net/inet_sock.h +++ b/trunk/include/net/inet_sock.h @@ -249,4 +249,13 @@ static inline __u8 inet_sk_flowi_flags(const struct sock *sk) return flags; } +static inline void inet_sk_rx_dst_set(struct sock *sk, const struct sk_buff *skb) +{ + struct dst_entry *dst = skb_dst(skb); + + dst_hold(dst); + sk->sk_rx_dst = dst; + inet_sk(sk)->rx_dst_ifindex = skb->skb_iif; +} + #endif /* _INET_SOCK_H */ diff --git a/trunk/include/net/ip.h b/trunk/include/net/ip.h index 5a5d84d3d2c6..bd5e444a19ce 100644 --- a/trunk/include/net/ip.h +++ b/trunk/include/net/ip.h @@ -120,7 +120,7 @@ extern struct sk_buff *__ip_make_skb(struct sock *sk, struct flowi4 *fl4, struct sk_buff_head *queue, struct inet_cork *cork); -extern int ip_send_skb(struct net *net, struct sk_buff *skb); +extern int ip_send_skb(struct sk_buff *skb); extern int ip_push_pending_frames(struct sock *sk, struct flowi4 *fl4); extern void ip_flush_pending_frames(struct sock *sk); extern struct sk_buff *ip_make_skb(struct sock *sk, diff --git a/trunk/include/net/ip6_fib.h b/trunk/include/net/ip6_fib.h index 9fc7114159e8..0fedbd8d747a 100644 --- a/trunk/include/net/ip6_fib.h +++ b/trunk/include/net/ip6_fib.h @@ -111,8 +111,9 @@ struct rt6_info { struct inet6_dev *rt6i_idev; unsigned long _rt6i_peer; - u32 rt6i_genid; - +#ifdef CONFIG_XFRM + u32 rt6i_flow_cache_genid; +#endif /* more non-fragment space at head required */ unsigned short rt6i_nfheader_len; diff --git a/trunk/include/net/irda/ircomm_tty.h b/trunk/include/net/irda/ircomm_tty.h index 80ffde3bb164..59ba38bc400f 100644 --- a/trunk/include/net/irda/ircomm_tty.h +++ b/trunk/include/net/irda/ircomm_tty.h @@ -52,16 +52,21 @@ /* Same for payload size. See qos.c for the smallest max data size */ #define IRCOMM_TTY_DATA_UNINITIALISED (64 - IRCOMM_TTY_HDR_UNINITIALISED) +/* Those are really defined in include/linux/serial.h - Jean II */ +#define ASYNC_B_INITIALIZED 31 /* Serial port was initialized */ +#define ASYNC_B_NORMAL_ACTIVE 29 /* Normal device is active */ +#define ASYNC_B_CLOSING 27 /* Serial port is closing */ + /* * IrCOMM TTY driver state */ struct ircomm_tty_cb { irda_queue_t queue; /* Must be first */ - struct tty_port port; magic_t magic; int state; /* Connect state */ + struct tty_struct *tty; struct ircomm_cb *ircomm; /* IrCOMM layer instance */ struct sk_buff *tx_skb; /* Transmit buffer */ @@ -75,6 +80,7 @@ struct ircomm_tty_cb { LOCAL_FLOW flow; /* IrTTP flow status */ int line; + unsigned long flags; __u8 dlsap_sel; __u8 slsap_sel; @@ -91,10 +97,19 @@ struct ircomm_tty_cb { void *skey; void *ckey; + wait_queue_head_t open_wait; + wait_queue_head_t close_wait; struct timer_list watchdog_timer; struct work_struct tqueue; + unsigned short close_delay; + unsigned short closing_wait; /* time to wait before closing */ + + int open_count; + int blocked_open; /* # of blocked opens */ + /* Protect concurent access to : + * o self->open_count * o self->ctrl_skb * o self->tx_skb * Maybe other things may gain to be protected as well... diff --git a/trunk/include/net/llc.h b/trunk/include/net/llc.h index f2d0fc570527..226c846cab08 100644 --- a/trunk/include/net/llc.h +++ b/trunk/include/net/llc.h @@ -133,7 +133,7 @@ extern int llc_build_and_send_ui_pkt(struct llc_sap *sap, struct sk_buff *skb, extern void llc_sap_handler(struct llc_sap *sap, struct sk_buff *skb); extern void llc_conn_handler(struct llc_sap *sap, struct sk_buff *skb); -extern void llc_station_init(void); +extern int llc_station_init(void); extern void llc_station_exit(void); #ifdef CONFIG_PROC_FS diff --git a/trunk/include/net/net_namespace.h b/trunk/include/net/net_namespace.h index fd87963a0ea5..ae1cd6c9ba52 100644 --- a/trunk/include/net/net_namespace.h +++ b/trunk/include/net/net_namespace.h @@ -102,7 +102,6 @@ struct net { #endif struct netns_ipvs *ipvs; struct sock *diag_nlsk; - atomic_t rt_genid; }; @@ -301,14 +300,5 @@ static inline void unregister_net_sysctl_table(struct ctl_table_header *header) } #endif -static inline int rt_genid(struct net *net) -{ - return atomic_read(&net->rt_genid); -} - -static inline void rt_genid_bump(struct net *net) -{ - atomic_inc(&net->rt_genid); -} #endif /* __NET_NET_NAMESPACE_H */ diff --git a/trunk/include/net/netfilter/nf_conntrack_ecache.h b/trunk/include/net/netfilter/nf_conntrack_ecache.h index 4a045cda9c60..e1ce1048fe5f 100644 --- a/trunk/include/net/netfilter/nf_conntrack_ecache.h +++ b/trunk/include/net/netfilter/nf_conntrack_ecache.h @@ -18,7 +18,6 @@ struct nf_conntrack_ecache { u16 ctmask; /* bitmask of ct events to be delivered */ u16 expmask; /* bitmask of expect events to be delivered */ u32 pid; /* netlink pid of destroyer */ - struct timer_list timeout; }; static inline struct nf_conntrack_ecache * diff --git a/trunk/include/net/netns/ipv4.h b/trunk/include/net/netns/ipv4.h index eb24dbccd81e..1474dd65c66f 100644 --- a/trunk/include/net/netns/ipv4.h +++ b/trunk/include/net/netns/ipv4.h @@ -65,6 +65,7 @@ struct netns_ipv4 { unsigned int sysctl_ping_group_range[2]; long sysctl_tcp_mem[3]; + atomic_t rt_genid; atomic_t dev_addr_genid; #ifdef CONFIG_IP_MROUTE diff --git a/trunk/include/net/route.h b/trunk/include/net/route.h index da22243d2760..776a27f1ab78 100644 --- a/trunk/include/net/route.h +++ b/trunk/include/net/route.h @@ -108,7 +108,7 @@ extern struct ip_rt_acct __percpu *ip_rt_acct; struct in_device; extern int ip_rt_init(void); -extern void rt_cache_flush(struct net *net); +extern void rt_cache_flush(struct net *net, int how); extern void rt_flush_dev(struct net_device *dev); extern struct rtable *__ip_route_output_key(struct net *, struct flowi4 *flp); extern struct rtable *ip_route_output_flow(struct net *, struct flowi4 *flp, diff --git a/trunk/include/net/scm.h b/trunk/include/net/scm.h index 7dc0854f0b38..079d7887dac1 100644 --- a/trunk/include/net/scm.h +++ b/trunk/include/net/scm.h @@ -70,11 +70,9 @@ static __inline__ void scm_destroy(struct scm_cookie *scm) } static __inline__ int scm_send(struct socket *sock, struct msghdr *msg, - struct scm_cookie *scm, bool forcecreds) + struct scm_cookie *scm) { memset(scm, 0, sizeof(*scm)); - if (forcecreds) - scm_set_cred(scm, task_tgid(current), current_cred()); unix_get_peersec_dgram(sock, scm); if (msg->msg_controllen <= 0) return 0; diff --git a/trunk/include/net/sock.h b/trunk/include/net/sock.h index adb7da20b5a1..b3730239bf18 100644 --- a/trunk/include/net/sock.h +++ b/trunk/include/net/sock.h @@ -218,7 +218,6 @@ struct cg_proto; * @sk_route_nocaps: forbidden route capabilities (e.g NETIF_F_GSO_MASK) * @sk_gso_type: GSO type (e.g. %SKB_GSO_TCPV4) * @sk_gso_max_size: Maximum GSO segment size to build - * @sk_gso_max_segs: Maximum number of GSO segments * @sk_lingertime: %SO_LINGER l_linger setting * @sk_backlog: always used with the per-socket spinlock held * @sk_callback_lock: used with the callbacks in the end of this struct @@ -339,7 +338,6 @@ struct sock { netdev_features_t sk_route_nocaps; int sk_gso_type; unsigned int sk_gso_max_size; - u16 sk_gso_max_segs; int sk_rcvlowat; unsigned long sk_lingertime; struct sk_buff_head sk_error_queue; @@ -1332,7 +1330,7 @@ static inline bool sk_wmem_schedule(struct sock *sk, int size) } static inline bool -sk_rmem_schedule(struct sock *sk, struct sk_buff *skb, int size) +sk_rmem_schedule(struct sock *sk, struct sk_buff *skb, unsigned int size) { if (!sk_has_account(sk)) return true; diff --git a/trunk/include/net/tcp.h b/trunk/include/net/tcp.h index 1f000ffe7075..e19124b84cd2 100644 --- a/trunk/include/net/tcp.h +++ b/trunk/include/net/tcp.h @@ -464,7 +464,6 @@ extern int tcp_disconnect(struct sock *sk, int flags); void tcp_connect_init(struct sock *sk); void tcp_finish_connect(struct sock *sk, struct sk_buff *skb); int tcp_send_rcvq(struct sock *sk, struct msghdr *msg, size_t size); -void inet_sk_rx_dst_set(struct sock *sk, const struct sk_buff *skb); /* From syncookies.c */ extern __u32 syncookie_secret[2][16-4+SHA_DIGEST_WORDS]; diff --git a/trunk/include/net/xfrm.h b/trunk/include/net/xfrm.h index 639dd1316d37..d9509eb29b80 100644 --- a/trunk/include/net/xfrm.h +++ b/trunk/include/net/xfrm.h @@ -213,9 +213,6 @@ struct xfrm_state { struct xfrm_lifetime_cur curlft; struct tasklet_hrtimer mtimer; - /* used to fix curlft->add_time when changing date */ - long saved_tmo; - /* Last used time */ unsigned long lastused; @@ -241,7 +238,6 @@ static inline struct net *xs_net(struct xfrm_state *x) /* xflags - make enum if more show up */ #define XFRM_TIME_DEFER 1 -#define XFRM_SOFT_EXPIRE 2 enum { XFRM_STATE_VOID, @@ -273,9 +269,6 @@ struct xfrm_replay { int (*check)(struct xfrm_state *x, struct sk_buff *skb, __be32 net_seq); - int (*recheck)(struct xfrm_state *x, - struct sk_buff *skb, - __be32 net_seq); void (*notify)(struct xfrm_state *x, int event); int (*overflow)(struct xfrm_state *x, struct sk_buff *skb); }; @@ -295,8 +288,6 @@ struct xfrm_policy_afinfo { struct flowi *fl, int reverse); int (*get_tos)(const struct flowi *fl); - void (*init_dst)(struct net *net, - struct xfrm_dst *dst); int (*init_path)(struct xfrm_dst *path, struct dst_entry *dst, int nfheader_len); diff --git a/trunk/include/sound/pcm.h b/trunk/include/sound/pcm.h index cdca2ab1e711..c75c0d1a85e2 100644 --- a/trunk/include/sound/pcm.h +++ b/trunk/include/sound/pcm.h @@ -1075,8 +1075,7 @@ static inline void snd_pcm_limit_isa_dma_size(int dma, size_t *max) const char *snd_pcm_format_name(snd_pcm_format_t format); /** - * snd_pcm_stream_str - Get a string naming the direction of a stream - * @substream: the pcm substream instance + * Get a string naming the direction of a stream */ static inline const char *snd_pcm_stream_str(struct snd_pcm_substream *substream) { diff --git a/trunk/include/target/target_core_backend.h b/trunk/include/target/target_core_backend.h index 941c84bf1065..f1405d335a96 100644 --- a/trunk/include/target/target_core_backend.h +++ b/trunk/include/target/target_core_backend.h @@ -23,9 +23,7 @@ struct se_subsystem_api { struct se_device *(*create_virtdevice)(struct se_hba *, struct se_subsystem_dev *, void *); void (*free_device)(void *); - void (*transport_complete)(struct se_cmd *cmd, - struct scatterlist *, - unsigned char *); + int (*transport_complete)(struct se_cmd *cmd, struct scatterlist *); int (*parse_cdb)(struct se_cmd *cmd); ssize_t (*check_configfs_dev_params)(struct se_hba *, diff --git a/trunk/include/target/target_core_base.h b/trunk/include/target/target_core_base.h index 5be89373ceac..128ce46fa48a 100644 --- a/trunk/include/target/target_core_base.h +++ b/trunk/include/target/target_core_base.h @@ -121,7 +121,6 @@ #define SE_INQUIRY_BUF 512 #define SE_MODE_PAGE_BUF 512 -#define SE_SENSE_BUF 96 /* struct se_hba->hba_flags */ enum hba_flags_table { @@ -504,6 +503,8 @@ struct se_cmd { u32 se_ordered_id; /* Total size in bytes associated with command */ u32 data_length; + /* SCSI Presented Data Transfer Length */ + u32 cmd_spdtl; u32 residual_count; u32 orig_fe_lun; /* Persistent Reservation key */ diff --git a/trunk/include/trace/define_trace.h b/trunk/include/trace/define_trace.h index 1905ca8dd399..b0b4eb24d592 100644 --- a/trunk/include/trace/define_trace.h +++ b/trunk/include/trace/define_trace.h @@ -1,5 +1,5 @@ /* - * Trace files that want to automate creation of all tracepoints defined + * Trace files that want to automate creationg of all tracepoints defined * in their file should include this file. The following are macros that the * trace file may define: * diff --git a/trunk/include/trace/events/kmem.h b/trunk/include/trace/events/kmem.h index 08fa27244da7..5f889f16b0c8 100644 --- a/trunk/include/trace/events/kmem.h +++ b/trunk/include/trace/events/kmem.h @@ -214,7 +214,7 @@ TRACE_EVENT(mm_page_alloc, TP_printk("page=%p pfn=%lu order=%d migratetype=%d gfp_flags=%s", __entry->page, - __entry->page ? page_to_pfn(__entry->page) : 0, + page_to_pfn(__entry->page), __entry->order, __entry->migratetype, show_gfp_flags(__entry->gfp_flags)) @@ -240,7 +240,7 @@ DECLARE_EVENT_CLASS(mm_page, TP_printk("page=%p pfn=%lu order=%u migratetype=%d percpu_refill=%d", __entry->page, - __entry->page ? page_to_pfn(__entry->page) : 0, + page_to_pfn(__entry->page), __entry->order, __entry->migratetype, __entry->order == 0) diff --git a/trunk/include/trace/events/sched.h b/trunk/include/trace/events/sched.h index 5a8671e8a67f..ea7a2035456d 100644 --- a/trunk/include/trace/events/sched.h +++ b/trunk/include/trace/events/sched.h @@ -73,9 +73,6 @@ DECLARE_EVENT_CLASS(sched_wakeup_template, __entry->prio = p->prio; __entry->success = success; __entry->target_cpu = task_cpu(p); - ) - TP_perf_assign( - __perf_task(p); ), TP_printk("comm=%s pid=%d prio=%d success=%d target_cpu=%03d", @@ -328,7 +325,6 @@ DECLARE_EVENT_CLASS(sched_stat_template, ) TP_perf_assign( __perf_count(delay); - __perf_task(tsk); ), TP_printk("comm=%s pid=%d delay=%Lu [ns]", diff --git a/trunk/include/trace/ftrace.h b/trunk/include/trace/ftrace.h index a763888a36f9..c6bc2faaf261 100644 --- a/trunk/include/trace/ftrace.h +++ b/trunk/include/trace/ftrace.h @@ -712,9 +712,6 @@ __attribute__((section("_ftrace_events"))) *__event_##call = &event_##call #undef __perf_count #define __perf_count(c) __count = (c) -#undef __perf_task -#define __perf_task(t) __task = (t) - #undef TP_perf_assign #define TP_perf_assign(args...) args @@ -728,7 +725,6 @@ perf_trace_##call(void *__data, proto) \ struct ftrace_raw_##call *entry; \ struct pt_regs __regs; \ u64 __addr = 0, __count = 1; \ - struct task_struct *__task = NULL; \ struct hlist_head *head; \ int __entry_size; \ int __data_size; \ @@ -756,7 +752,7 @@ perf_trace_##call(void *__data, proto) \ \ head = this_cpu_ptr(event_call->perf_events); \ perf_trace_buf_submit(entry, __entry_size, rctx, __addr, \ - __count, &__regs, head, __task); \ + __count, &__regs, head); \ } /* diff --git a/trunk/include/xen/events.h b/trunk/include/xen/events.h index 04399b28e821..9c641deb65d2 100644 --- a/trunk/include/xen/events.h +++ b/trunk/include/xen/events.h @@ -58,6 +58,8 @@ void notify_remote_via_irq(int irq); void xen_irq_resume(void); +void xen_hvm_prepare_kexec(struct shared_info *sip, unsigned long pfn); + /* Clear an irq's pending state, in preparation for polling on it */ void xen_clear_irq_pending(int irq); void xen_set_irq_pending(int irq); diff --git a/trunk/include/xen/grant_table.h b/trunk/include/xen/grant_table.h index f19fff8650e9..11e27c3af3cb 100644 --- a/trunk/include/xen/grant_table.h +++ b/trunk/include/xen/grant_table.h @@ -187,7 +187,6 @@ int gnttab_map_refs(struct gnttab_map_grant_ref *map_ops, struct gnttab_map_grant_ref *kmap_ops, struct page **pages, unsigned int count); int gnttab_unmap_refs(struct gnttab_unmap_grant_ref *unmap_ops, - struct gnttab_map_grant_ref *kunmap_ops, - struct page **pages, unsigned int count); + struct page **pages, unsigned int count, bool clear_pte); #endif /* __ASM_GNTTAB_H__ */ diff --git a/trunk/init/Kconfig b/trunk/init/Kconfig index 73e4adfa91dc..af6c7f8ba019 100644 --- a/trunk/init/Kconfig +++ b/trunk/init/Kconfig @@ -267,106 +267,6 @@ config POSIX_MQUEUE_SYSCTL depends on SYSCTL default y -config FHANDLE - bool "open by fhandle syscalls" - select EXPORTFS - help - If you say Y here, a user level program will be able to map - file names to handle and then later use the handle for - different file system operations. This is useful in implementing - userspace file servers, which now track files using handles instead - of names. The handle would remain the same even if file names - get renamed. Enables open_by_handle_at(2) and name_to_handle_at(2) - syscalls. - -config AUDIT - bool "Auditing support" - depends on NET - help - Enable auditing infrastructure that can be used with another - kernel subsystem, such as SELinux (which requires this for - logging of avc messages output). Does not do system-call - auditing without CONFIG_AUDITSYSCALL. - -config AUDITSYSCALL - bool "Enable system-call auditing support" - depends on AUDIT && (X86 || PPC || S390 || IA64 || UML || SPARC64 || SUPERH || (ARM && AEABI && !OABI_COMPAT)) - default y if SECURITY_SELINUX - help - Enable low-overhead system-call auditing infrastructure that - can be used independently or with another kernel subsystem, - such as SELinux. - -config AUDIT_WATCH - def_bool y - depends on AUDITSYSCALL - select FSNOTIFY - -config AUDIT_TREE - def_bool y - depends on AUDITSYSCALL - select FSNOTIFY - -config AUDIT_LOGINUID_IMMUTABLE - bool "Make audit loginuid immutable" - depends on AUDIT - help - The config option toggles if a task setting its loginuid requires - CAP_SYS_AUDITCONTROL or if that task should require no special permissions - but should instead only allow setting its loginuid if it was never - previously set. On systems which use systemd or a similar central - process to restart login services this should be set to true. On older - systems in which an admin would typically have to directly stop and - start processes this should be set to false. Setting this to true allows - one to drop potentially dangerous capabilites from the login tasks, - but may not be backwards compatible with older init systems. - -source "kernel/irq/Kconfig" -source "kernel/time/Kconfig" - -menu "CPU/Task time and stats accounting" - -choice - prompt "Cputime accounting" - default TICK_CPU_ACCOUNTING if !PPC64 - default VIRT_CPU_ACCOUNTING if PPC64 - -# Kind of a stub config for the pure tick based cputime accounting -config TICK_CPU_ACCOUNTING - bool "Simple tick based cputime accounting" - depends on !S390 - help - This is the basic tick based cputime accounting that maintains - statistics about user, system and idle time spent on per jiffies - granularity. - - If unsure, say Y. - -config VIRT_CPU_ACCOUNTING - bool "Deterministic task and CPU time accounting" - depends on HAVE_VIRT_CPU_ACCOUNTING - help - Select this option to enable more accurate task and CPU time - accounting. This is done by reading a CPU counter on each - kernel entry and exit and on transitions within the kernel - between system, softirq and hardirq state, so there is a - small performance impact. In the case of s390 or IBM POWER > 5, - this also enables accounting of stolen time on logically-partitioned - systems. - -config IRQ_TIME_ACCOUNTING - bool "Fine granularity task level IRQ time accounting" - depends on HAVE_IRQ_TIME_ACCOUNTING - help - Select this option to enable fine granularity task irq time - accounting. This is done by reading a timestamp on each - transitions between softirq and hardirq state, so there can be a - small performance impact. - - If in doubt, say N here. - -endchoice - config BSD_PROCESS_ACCT bool "BSD Process Accounting" help @@ -392,6 +292,18 @@ config BSD_PROCESS_ACCT_V3 for processing it. A preliminary version of these tools is available at . +config FHANDLE + bool "open by fhandle syscalls" + select EXPORTFS + help + If you say Y here, a user level program will be able to map + file names to handle and then later use the handle for + different file system operations. This is useful in implementing + userspace file servers, which now track files using handles instead + of names. The handle would remain the same even if file names + get renamed. Enables open_by_handle_at(2) and name_to_handle_at(2) + syscalls. + config TASKSTATS bool "Export task/process statistics through netlink (EXPERIMENTAL)" depends on NET @@ -434,7 +346,50 @@ config TASK_IO_ACCOUNTING Say N if unsure. -endmenu # "CPU/Task time and stats accounting" +config AUDIT + bool "Auditing support" + depends on NET + help + Enable auditing infrastructure that can be used with another + kernel subsystem, such as SELinux (which requires this for + logging of avc messages output). Does not do system-call + auditing without CONFIG_AUDITSYSCALL. + +config AUDITSYSCALL + bool "Enable system-call auditing support" + depends on AUDIT && (X86 || PPC || S390 || IA64 || UML || SPARC64 || SUPERH || (ARM && AEABI && !OABI_COMPAT)) + default y if SECURITY_SELINUX + help + Enable low-overhead system-call auditing infrastructure that + can be used independently or with another kernel subsystem, + such as SELinux. + +config AUDIT_WATCH + def_bool y + depends on AUDITSYSCALL + select FSNOTIFY + +config AUDIT_TREE + def_bool y + depends on AUDITSYSCALL + select FSNOTIFY + +config AUDIT_LOGINUID_IMMUTABLE + bool "Make audit loginuid immutable" + depends on AUDIT + help + The config option toggles if a task setting its loginuid requires + CAP_SYS_AUDITCONTROL or if that task should require no special permissions + but should instead only allow setting its loginuid if it was never + previously set. On systems which use systemd or a similar central + process to restart login services this should be set to true. On older + systems in which an admin would typically have to directly stop and + start processes this should be set to false. Setting this to true allows + one to drop potentially dangerous capabilites from the login tasks, + but may not be backwards compatible with older init systems. + +source "kernel/irq/Kconfig" +source "kernel/time/Kconfig" menu "RCU Subsystem" @@ -486,24 +441,6 @@ config PREEMPT_RCU This option enables preemptible-RCU code that is common between the TREE_PREEMPT_RCU and TINY_PREEMPT_RCU implementations. -config RCU_USER_QS - bool "Consider userspace as in RCU extended quiescent state" - depends on HAVE_RCU_USER_QS && SMP - help - This option sets hooks on kernel / userspace boundaries and - puts RCU in extended quiescent state when the CPU runs in - userspace. It means that when a CPU runs in userspace, it is - excluded from the global RCU state machine and thus doesn't - to keep the timer tick on for RCU. - -config RCU_USER_QS_FORCE - bool "Force userspace extended QS by default" - depends on RCU_USER_QS - help - Set the hooks in user/kernel boundaries by default in order to - test this feature that treats userspace as an extended quiescent - state until we have a real user like a full adaptive nohz option. - config RCU_FANOUT int "Tree-based hierarchical RCU fanout value" range 2 64 if 64BIT @@ -1216,8 +1153,7 @@ menuconfig EXPERT config UID16 bool "Enable 16-bit UID system calls" if EXPERT - depends on ARM || BLACKFIN || CRIS || FRV || H8300 || X86_32 || M68K || (S390 && !64BIT) || SUPERH || SPARC32 || (SPARC64 && COMPAT) || UML || (X86_64 && IA32_EMULATION) \ - || AARCH32_EMULATION + depends on ARM || BLACKFIN || CRIS || FRV || H8300 || X86_32 || M68K || (S390 && !64BIT) || SUPERH || SPARC32 || (SPARC64 && COMPAT) || UML || (X86_64 && IA32_EMULATION) default y help This enables the legacy 16-bit UID syscall wrappers. @@ -1265,7 +1201,13 @@ config KALLSYMS_ALL Say N unless you really need all symbols. config HOTPLUG - def_bool y + bool "Support for hot-pluggable devices" if EXPERT + default y + help + This option is provided for the case where no hotplug or uevent + capabilities is wanted by the kernel. You should only consider + disabling this option for embedded systems that do not use modules, a + dynamic /dev tree, or dynamic device discovery. Just say Y. config PRINTK default y diff --git a/trunk/init/main.c b/trunk/init/main.c index db34c0ec4711..e60679de61c3 100644 --- a/trunk/init/main.c +++ b/trunk/init/main.c @@ -461,6 +461,10 @@ static void __init mm_init(void) percpu_init_late(); pgtable_cache_init(); vmalloc_init(); +#ifdef CONFIG_X86 + if (efi_enabled) + efi_enter_virtual_mode(); +#endif } asmlinkage void __init start_kernel(void) @@ -602,10 +606,6 @@ asmlinkage void __init start_kernel(void) calibrate_delay(); pidmap_init(); anon_vma_init(); -#ifdef CONFIG_X86 - if (efi_enabled) - efi_enter_virtual_mode(); -#endif thread_info_cache_init(); cred_init(); fork_init(totalram_pages); @@ -631,11 +631,6 @@ asmlinkage void __init start_kernel(void) acpi_early_init(); /* before LAPIC and SMP init */ sfi_init_late(); - if (efi_enabled) { - efi_late_init(); - efi_free_boot_services(); - } - ftrace_init(); /* Do the rest non-__init'ed, we're now alive */ diff --git a/trunk/ipc/mqueue.c b/trunk/ipc/mqueue.c index 9a08acc9e649..f8e54f5b9080 100644 --- a/trunk/ipc/mqueue.c +++ b/trunk/ipc/mqueue.c @@ -726,6 +726,7 @@ static struct file *do_create(struct ipc_namespace *ipc_ns, struct inode *dir, struct mq_attr *attr) { const struct cred *cred = current_cred(); + struct file *result; int ret; if (attr) { @@ -747,11 +748,21 @@ static struct file *do_create(struct ipc_namespace *ipc_ns, struct inode *dir, } mode &= ~current_umask(); - ret = vfs_create(dir, path->dentry, mode, true); - path->dentry->d_fsdata = NULL; + ret = mnt_want_write(path->mnt); if (ret) return ERR_PTR(ret); - return dentry_open(path, oflag, cred); + ret = vfs_create(dir, path->dentry, mode, true); + path->dentry->d_fsdata = NULL; + if (!ret) + result = dentry_open(path, oflag, cred); + else + result = ERR_PTR(ret); + /* + * dentry_open() took a persistent mnt_want_write(), + * so we can now drop this one. + */ + mnt_drop_write(path->mnt); + return result; } /* Opens existing queue */ @@ -777,9 +788,7 @@ SYSCALL_DEFINE4(mq_open, const char __user *, u_name, int, oflag, umode_t, mode, struct mq_attr attr; int fd, error; struct ipc_namespace *ipc_ns = current->nsproxy->ipc_ns; - struct vfsmount *mnt = ipc_ns->mq_mnt; - struct dentry *root = mnt->mnt_root; - int ro; + struct dentry *root = ipc_ns->mq_mnt->mnt_root; if (u_attr && copy_from_user(&attr, u_attr, sizeof(struct mq_attr))) return -EFAULT; @@ -793,7 +802,6 @@ SYSCALL_DEFINE4(mq_open, const char __user *, u_name, int, oflag, umode_t, mode, if (fd < 0) goto out_putname; - ro = mnt_want_write(mnt); /* we'll drop it in any case */ error = 0; mutex_lock(&root->d_inode->i_mutex); path.dentry = lookup_one_len(name, root, strlen(name)); @@ -801,7 +809,7 @@ SYSCALL_DEFINE4(mq_open, const char __user *, u_name, int, oflag, umode_t, mode, error = PTR_ERR(path.dentry); goto out_putfd; } - path.mnt = mntget(mnt); + path.mnt = mntget(ipc_ns->mq_mnt); if (oflag & O_CREAT) { if (path.dentry->d_inode) { /* entry already exists */ @@ -812,10 +820,6 @@ SYSCALL_DEFINE4(mq_open, const char __user *, u_name, int, oflag, umode_t, mode, } filp = do_open(&path, oflag); } else { - if (ro) { - error = ro; - goto out; - } filp = do_create(ipc_ns, root->d_inode, &path, oflag, mode, u_attr ? &attr : NULL); @@ -841,7 +845,6 @@ SYSCALL_DEFINE4(mq_open, const char __user *, u_name, int, oflag, umode_t, mode, fd = error; } mutex_unlock(&root->d_inode->i_mutex); - mnt_drop_write(mnt); out_putname: putname(name); return fd; @@ -854,38 +857,40 @@ SYSCALL_DEFINE1(mq_unlink, const char __user *, u_name) struct dentry *dentry; struct inode *inode = NULL; struct ipc_namespace *ipc_ns = current->nsproxy->ipc_ns; - struct vfsmount *mnt = ipc_ns->mq_mnt; name = getname(u_name); if (IS_ERR(name)) return PTR_ERR(name); - err = mnt_want_write(mnt); - if (err) - goto out_name; - mutex_lock_nested(&mnt->mnt_root->d_inode->i_mutex, I_MUTEX_PARENT); - dentry = lookup_one_len(name, mnt->mnt_root, strlen(name)); + mutex_lock_nested(&ipc_ns->mq_mnt->mnt_root->d_inode->i_mutex, + I_MUTEX_PARENT); + dentry = lookup_one_len(name, ipc_ns->mq_mnt->mnt_root, strlen(name)); if (IS_ERR(dentry)) { err = PTR_ERR(dentry); goto out_unlock; } - inode = dentry->d_inode; - if (!inode) { + if (!dentry->d_inode) { err = -ENOENT; - } else { - ihold(inode); - err = vfs_unlink(dentry->d_parent->d_inode, dentry); + goto out_err; } + + inode = dentry->d_inode; + if (inode) + ihold(inode); + err = mnt_want_write(ipc_ns->mq_mnt); + if (err) + goto out_err; + err = vfs_unlink(dentry->d_parent->d_inode, dentry); + mnt_drop_write(ipc_ns->mq_mnt); +out_err: dput(dentry); out_unlock: - mutex_unlock(&mnt->mnt_root->d_inode->i_mutex); + mutex_unlock(&ipc_ns->mq_mnt->mnt_root->d_inode->i_mutex); + putname(name); if (inode) iput(inode); - mnt_drop_write(mnt); -out_name: - putname(name); return err; } diff --git a/trunk/kernel/Kconfig.locks b/trunk/kernel/Kconfig.locks index 44511d100eaa..2251882daf53 100644 --- a/trunk/kernel/Kconfig.locks +++ b/trunk/kernel/Kconfig.locks @@ -87,9 +87,6 @@ config ARCH_INLINE_WRITE_UNLOCK_IRQ config ARCH_INLINE_WRITE_UNLOCK_IRQRESTORE bool -config UNINLINE_SPIN_UNLOCK - bool - # # lock_* functions are inlined when: # - DEBUG_SPINLOCK=n and GENERIC_LOCKBREAK=n and ARCH_INLINE_*LOCK=y @@ -106,120 +103,100 @@ config UNINLINE_SPIN_UNLOCK # - DEBUG_SPINLOCK=n and ARCH_INLINE_*LOCK=y # -if !DEBUG_SPINLOCK - config INLINE_SPIN_TRYLOCK - def_bool y - depends on ARCH_INLINE_SPIN_TRYLOCK + def_bool !DEBUG_SPINLOCK && ARCH_INLINE_SPIN_TRYLOCK config INLINE_SPIN_TRYLOCK_BH - def_bool y - depends on ARCH_INLINE_SPIN_TRYLOCK_BH + def_bool !DEBUG_SPINLOCK && ARCH_INLINE_SPIN_TRYLOCK_BH config INLINE_SPIN_LOCK - def_bool y - depends on !GENERIC_LOCKBREAK && ARCH_INLINE_SPIN_LOCK + def_bool !DEBUG_SPINLOCK && !GENERIC_LOCKBREAK && ARCH_INLINE_SPIN_LOCK config INLINE_SPIN_LOCK_BH - def_bool y - depends on !GENERIC_LOCKBREAK && ARCH_INLINE_SPIN_LOCK_BH + def_bool !DEBUG_SPINLOCK && !GENERIC_LOCKBREAK && \ + ARCH_INLINE_SPIN_LOCK_BH config INLINE_SPIN_LOCK_IRQ - def_bool y - depends on !GENERIC_LOCKBREAK && ARCH_INLINE_SPIN_LOCK_IRQ + def_bool !DEBUG_SPINLOCK && !GENERIC_LOCKBREAK && \ + ARCH_INLINE_SPIN_LOCK_IRQ config INLINE_SPIN_LOCK_IRQSAVE - def_bool y - depends on !GENERIC_LOCKBREAK && ARCH_INLINE_SPIN_LOCK_IRQSAVE + def_bool !DEBUG_SPINLOCK && !GENERIC_LOCKBREAK && \ + ARCH_INLINE_SPIN_LOCK_IRQSAVE + +config UNINLINE_SPIN_UNLOCK + bool config INLINE_SPIN_UNLOCK_BH - def_bool y - depends on ARCH_INLINE_SPIN_UNLOCK_BH + def_bool !DEBUG_SPINLOCK && ARCH_INLINE_SPIN_UNLOCK_BH config INLINE_SPIN_UNLOCK_IRQ - def_bool y - depends on !PREEMPT || ARCH_INLINE_SPIN_UNLOCK_BH + def_bool !DEBUG_SPINLOCK && (!PREEMPT || ARCH_INLINE_SPIN_UNLOCK_BH) config INLINE_SPIN_UNLOCK_IRQRESTORE - def_bool y - depends on ARCH_INLINE_SPIN_UNLOCK_IRQRESTORE + def_bool !DEBUG_SPINLOCK && ARCH_INLINE_SPIN_UNLOCK_IRQRESTORE config INLINE_READ_TRYLOCK - def_bool y - depends on ARCH_INLINE_READ_TRYLOCK + def_bool !DEBUG_SPINLOCK && ARCH_INLINE_READ_TRYLOCK config INLINE_READ_LOCK - def_bool y - depends on !GENERIC_LOCKBREAK && ARCH_INLINE_READ_LOCK + def_bool !DEBUG_SPINLOCK && !GENERIC_LOCKBREAK && ARCH_INLINE_READ_LOCK config INLINE_READ_LOCK_BH - def_bool y - depends on !GENERIC_LOCKBREAK && ARCH_INLINE_READ_LOCK_BH + def_bool !DEBUG_SPINLOCK && !GENERIC_LOCKBREAK && \ + ARCH_INLINE_READ_LOCK_BH config INLINE_READ_LOCK_IRQ - def_bool y - depends on !GENERIC_LOCKBREAK && ARCH_INLINE_READ_LOCK_IRQ + def_bool !DEBUG_SPINLOCK && !GENERIC_LOCKBREAK && \ + ARCH_INLINE_READ_LOCK_IRQ config INLINE_READ_LOCK_IRQSAVE - def_bool y - depends on !GENERIC_LOCKBREAK && ARCH_INLINE_READ_LOCK_IRQSAVE + def_bool !DEBUG_SPINLOCK && !GENERIC_LOCKBREAK && \ + ARCH_INLINE_READ_LOCK_IRQSAVE config INLINE_READ_UNLOCK - def_bool y - depends on !PREEMPT || ARCH_INLINE_READ_UNLOCK + def_bool !DEBUG_SPINLOCK && (!PREEMPT || ARCH_INLINE_READ_UNLOCK) config INLINE_READ_UNLOCK_BH - def_bool y - depends on ARCH_INLINE_READ_UNLOCK_BH + def_bool !DEBUG_SPINLOCK && ARCH_INLINE_READ_UNLOCK_BH config INLINE_READ_UNLOCK_IRQ - def_bool y - depends on !PREEMPT || ARCH_INLINE_READ_UNLOCK_BH + def_bool !DEBUG_SPINLOCK && (!PREEMPT || ARCH_INLINE_READ_UNLOCK_BH) config INLINE_READ_UNLOCK_IRQRESTORE - def_bool y - depends on ARCH_INLINE_READ_UNLOCK_IRQRESTORE + def_bool !DEBUG_SPINLOCK && ARCH_INLINE_READ_UNLOCK_IRQRESTORE config INLINE_WRITE_TRYLOCK - def_bool y - depends on ARCH_INLINE_WRITE_TRYLOCK + def_bool !DEBUG_SPINLOCK && ARCH_INLINE_WRITE_TRYLOCK config INLINE_WRITE_LOCK - def_bool y - depends on !GENERIC_LOCKBREAK && ARCH_INLINE_WRITE_LOCK + def_bool !DEBUG_SPINLOCK && !GENERIC_LOCKBREAK && ARCH_INLINE_WRITE_LOCK config INLINE_WRITE_LOCK_BH - def_bool y - depends on !GENERIC_LOCKBREAK && ARCH_INLINE_WRITE_LOCK_BH + def_bool !DEBUG_SPINLOCK && !GENERIC_LOCKBREAK && \ + ARCH_INLINE_WRITE_LOCK_BH config INLINE_WRITE_LOCK_IRQ - def_bool y - depends on !GENERIC_LOCKBREAK && ARCH_INLINE_WRITE_LOCK_IRQ + def_bool !DEBUG_SPINLOCK && !GENERIC_LOCKBREAK && \ + ARCH_INLINE_WRITE_LOCK_IRQ config INLINE_WRITE_LOCK_IRQSAVE - def_bool y - depends on !GENERIC_LOCKBREAK && ARCH_INLINE_WRITE_LOCK_IRQSAVE + def_bool !DEBUG_SPINLOCK && !GENERIC_LOCKBREAK && \ + ARCH_INLINE_WRITE_LOCK_IRQSAVE config INLINE_WRITE_UNLOCK - def_bool y - depends on !PREEMPT || ARCH_INLINE_WRITE_UNLOCK + def_bool !DEBUG_SPINLOCK && (!PREEMPT || ARCH_INLINE_WRITE_UNLOCK) config INLINE_WRITE_UNLOCK_BH - def_bool y - depends on ARCH_INLINE_WRITE_UNLOCK_BH + def_bool !DEBUG_SPINLOCK && ARCH_INLINE_WRITE_UNLOCK_BH config INLINE_WRITE_UNLOCK_IRQ - def_bool y - depends on !PREEMPT || ARCH_INLINE_WRITE_UNLOCK_BH + def_bool !DEBUG_SPINLOCK && (!PREEMPT || ARCH_INLINE_WRITE_UNLOCK_BH) config INLINE_WRITE_UNLOCK_IRQRESTORE - def_bool y - depends on ARCH_INLINE_WRITE_UNLOCK_IRQRESTORE - -endif + def_bool !DEBUG_SPINLOCK && ARCH_INLINE_WRITE_UNLOCK_IRQRESTORE config MUTEX_SPIN_ON_OWNER - def_bool y - depends on SMP && !DEBUG_MUTEXES + def_bool SMP && !DEBUG_MUTEXES diff --git a/trunk/kernel/Makefile b/trunk/kernel/Makefile index 5404911eaee9..c0cc67ad764c 100644 --- a/trunk/kernel/Makefile +++ b/trunk/kernel/Makefile @@ -10,7 +10,7 @@ obj-y = fork.o exec_domain.o panic.o printk.o \ kthread.o wait.o kfifo.o sys_ni.o posix-cpu-timers.o mutex.o \ hrtimer.o rwsem.o nsproxy.o srcu.o semaphore.o \ notifier.o ksysfs.o cred.o \ - async.o range.o groups.o lglock.o smpboot.o + async.o range.o groups.o lglock.o ifdef CONFIG_FUNCTION_TRACER # Do not trace debug files and internal ftrace files @@ -46,6 +46,7 @@ obj-$(CONFIG_DEBUG_RT_MUTEXES) += rtmutex-debug.o obj-$(CONFIG_RT_MUTEX_TESTER) += rtmutex-tester.o obj-$(CONFIG_GENERIC_ISA_DMA) += dma.o obj-$(CONFIG_SMP) += smp.o +obj-$(CONFIG_SMP) += smpboot.o ifneq ($(CONFIG_SMP),y) obj-y += up.o endif @@ -97,7 +98,7 @@ obj-$(CONFIG_COMPAT_BINFMT_ELF) += elfcore.o obj-$(CONFIG_BINFMT_ELF_FDPIC) += elfcore.o obj-$(CONFIG_FUNCTION_TRACER) += trace/ obj-$(CONFIG_TRACING) += trace/ -obj-$(CONFIG_TRACE_CLOCK) += trace/ +obj-$(CONFIG_X86_DS) += trace/ obj-$(CONFIG_RING_BUFFER) += trace/ obj-$(CONFIG_TRACEPOINTS) += trace/ obj-$(CONFIG_IRQ_WORK) += irq_work.o diff --git a/trunk/kernel/audit_tree.c b/trunk/kernel/audit_tree.c index ed206fd88cca..3a5ca582ba1e 100644 --- a/trunk/kernel/audit_tree.c +++ b/trunk/kernel/audit_tree.c @@ -250,6 +250,7 @@ static void untag_chunk(struct node *p) spin_unlock(&hash_lock); spin_unlock(&entry->lock); fsnotify_destroy_mark(entry); + fsnotify_put_mark(entry); goto out; } @@ -258,7 +259,7 @@ static void untag_chunk(struct node *p) fsnotify_duplicate_mark(&new->mark, entry); if (fsnotify_add_mark(&new->mark, new->mark.group, new->mark.i.inode, NULL, 1)) { - fsnotify_put_mark(&new->mark); + free_chunk(new); goto Fallback; } @@ -292,7 +293,7 @@ static void untag_chunk(struct node *p) spin_unlock(&hash_lock); spin_unlock(&entry->lock); fsnotify_destroy_mark(entry); - fsnotify_put_mark(&new->mark); /* drop initial reference */ + fsnotify_put_mark(entry); goto out; Fallback: @@ -321,7 +322,7 @@ static int create_chunk(struct inode *inode, struct audit_tree *tree) entry = &chunk->mark; if (fsnotify_add_mark(entry, audit_tree_group, inode, NULL, 0)) { - fsnotify_put_mark(entry); + free_chunk(chunk); return -ENOSPC; } @@ -346,7 +347,6 @@ static int create_chunk(struct inode *inode, struct audit_tree *tree) insert_hash(chunk); spin_unlock(&hash_lock); spin_unlock(&entry->lock); - fsnotify_put_mark(entry); /* drop initial reference */ return 0; } @@ -396,7 +396,7 @@ static int tag_chunk(struct inode *inode, struct audit_tree *tree) fsnotify_duplicate_mark(chunk_entry, old_entry); if (fsnotify_add_mark(chunk_entry, chunk_entry->group, chunk_entry->i.inode, NULL, 1)) { spin_unlock(&old_entry->lock); - fsnotify_put_mark(chunk_entry); + free_chunk(chunk); fsnotify_put_mark(old_entry); return -ENOSPC; } @@ -444,8 +444,8 @@ static int tag_chunk(struct inode *inode, struct audit_tree *tree) spin_unlock(&chunk_entry->lock); spin_unlock(&old_entry->lock); fsnotify_destroy_mark(old_entry); - fsnotify_put_mark(chunk_entry); /* drop initial reference */ fsnotify_put_mark(old_entry); /* pair to fsnotify_find mark_entry */ + fsnotify_put_mark(old_entry); /* and kill it */ return 0; } @@ -916,12 +916,7 @@ static void audit_tree_freeing_mark(struct fsnotify_mark *entry, struct fsnotify struct audit_chunk *chunk = container_of(entry, struct audit_chunk, mark); evict_chunk(chunk); - - /* - * We are guaranteed to have at least one reference to the mark from - * either the inode or the caller of fsnotify_destroy_mark(). - */ - BUG_ON(atomic_read(&entry->refcnt) < 1); + fsnotify_put_mark(entry); } static bool audit_tree_send_event(struct fsnotify_group *group, struct inode *inode, diff --git a/trunk/kernel/cpu.c b/trunk/kernel/cpu.c index f560598807c1..14d32588cccd 100644 --- a/trunk/kernel/cpu.c +++ b/trunk/kernel/cpu.c @@ -280,13 +280,12 @@ static int __ref _cpu_down(unsigned int cpu, int tasks_frozen) __func__, cpu); goto out_release; } - smpboot_park_threads(cpu); err = __stop_machine(take_cpu_down, &tcd_param, cpumask_of(cpu)); if (err) { /* CPU didn't die: tell everyone. Can't complain. */ - smpboot_unpark_threads(cpu); cpu_notify_nofail(CPU_DOWN_FAILED | mod, hcpu); + goto out_release; } BUG_ON(cpu_online(cpu)); @@ -355,10 +354,6 @@ static int __cpuinit _cpu_up(unsigned int cpu, int tasks_frozen) goto out; } - ret = smpboot_create_threads(cpu); - if (ret) - goto out; - ret = __cpu_notify(CPU_UP_PREPARE | mod, hcpu, -1, &nr_calls); if (ret) { nr_calls--; @@ -373,9 +368,6 @@ static int __cpuinit _cpu_up(unsigned int cpu, int tasks_frozen) goto out_notify; BUG_ON(!cpu_online(cpu)); - /* Wake the per cpu threads */ - smpboot_unpark_threads(cpu); - /* Now call notifier in preparation. */ cpu_notify(CPU_ONLINE | mod, hcpu); @@ -447,6 +439,14 @@ EXPORT_SYMBOL_GPL(cpu_up); #ifdef CONFIG_PM_SLEEP_SMP static cpumask_var_t frozen_cpus; +void __weak arch_disable_nonboot_cpus_begin(void) +{ +} + +void __weak arch_disable_nonboot_cpus_end(void) +{ +} + int disable_nonboot_cpus(void) { int cpu, first_cpu, error = 0; @@ -458,6 +458,7 @@ int disable_nonboot_cpus(void) * with the userspace trying to use the CPU hotplug at the same time */ cpumask_clear(frozen_cpus); + arch_disable_nonboot_cpus_begin(); printk("Disabling non-boot CPUs ...\n"); for_each_online_cpu(cpu) { @@ -473,6 +474,8 @@ int disable_nonboot_cpus(void) } } + arch_disable_nonboot_cpus_end(); + if (!error) { BUG_ON(num_online_cpus() > 1); /* Make sure the CPUs won't be enabled by someone else */ diff --git a/trunk/kernel/debug/debug_core.c b/trunk/kernel/debug/debug_core.c index 17e073c309e6..0557f24c6bca 100644 --- a/trunk/kernel/debug/debug_core.c +++ b/trunk/kernel/debug/debug_core.c @@ -672,10 +672,6 @@ kgdb_handle_exception(int evector, int signo, int ecode, struct pt_regs *regs) { struct kgdb_state kgdb_var; struct kgdb_state *ks = &kgdb_var; - int ret = 0; - - if (arch_kgdb_ops.enable_nmi) - arch_kgdb_ops.enable_nmi(0); ks->cpu = raw_smp_processor_id(); ks->ex_vector = evector; @@ -685,15 +681,11 @@ kgdb_handle_exception(int evector, int signo, int ecode, struct pt_regs *regs) ks->linux_regs = regs; if (kgdb_reenter_check(ks)) - goto out; /* Ouch, double exception ! */ + return 0; /* Ouch, double exception ! */ if (kgdb_info[ks->cpu].enter_kgdb != 0) - goto out; + return 0; - ret = kgdb_cpu_enter(ks, regs, DCPU_WANT_MASTER); -out: - if (arch_kgdb_ops.enable_nmi) - arch_kgdb_ops.enable_nmi(1); - return ret; + return kgdb_cpu_enter(ks, regs, DCPU_WANT_MASTER); } int kgdb_nmicallback(int cpu, void *regs) diff --git a/trunk/kernel/debug/kdb/kdb_debugger.c b/trunk/kernel/debug/kdb/kdb_debugger.c index be7b33b73d30..8b68ce78ff17 100644 --- a/trunk/kernel/debug/kdb/kdb_debugger.c +++ b/trunk/kernel/debug/kdb/kdb_debugger.c @@ -12,7 +12,6 @@ #include #include #include -#include #include "kdb_private.h" #include "../debug_core.h" @@ -53,9 +52,6 @@ int kdb_stub(struct kgdb_state *ks) if (atomic_read(&kgdb_setting_breakpoint)) reason = KDB_REASON_KEYBOARD; - if (in_nmi()) - reason = KDB_REASON_NMI; - for (i = 0, bp = kdb_breakpoints; i < KDB_MAXBPT; i++, bp++) { if ((bp->bp_enabled) && (bp->bp_addr == addr)) { reason = KDB_REASON_BREAK; diff --git a/trunk/kernel/debug/kdb/kdb_io.c b/trunk/kernel/debug/kdb/kdb_io.c index 0a69d2adc4f3..bb9520f0f6ff 100644 --- a/trunk/kernel/debug/kdb/kdb_io.c +++ b/trunk/kernel/debug/kdb/kdb_io.c @@ -715,6 +715,9 @@ int vkdb_printf(const char *fmt, va_list ap) /* check for having reached the LINES number of printed lines */ if (kdb_nextline == linecount) { char buf1[16] = ""; +#if defined(CONFIG_SMP) + char buf2[32]; +#endif /* Watch out for recursion here. Any routine that calls * kdb_printf will come back through here. And kdb_read @@ -729,6 +732,14 @@ int vkdb_printf(const char *fmt, va_list ap) if (moreprompt == NULL) moreprompt = "more> "; +#if defined(CONFIG_SMP) + if (strchr(moreprompt, '%')) { + sprintf(buf2, moreprompt, get_cpu()); + put_cpu(); + moreprompt = buf2; + } +#endif + kdb_input_flush(); c = console_drivers; diff --git a/trunk/kernel/debug/kdb/kdb_main.c b/trunk/kernel/debug/kdb/kdb_main.c index 1261dc7eaeb9..1f91413edb87 100644 --- a/trunk/kernel/debug/kdb/kdb_main.c +++ b/trunk/kernel/debug/kdb/kdb_main.c @@ -21,7 +21,6 @@ #include #include #include -#include #include #include #include @@ -140,10 +139,11 @@ static const int __nkdb_err = sizeof(kdbmsgs) / sizeof(kdbmsg_t); static char *__env[] = { #if defined(CONFIG_SMP) "PROMPT=[%d]kdb> ", + "MOREPROMPT=[%d]more> ", #else "PROMPT=kdb> ", -#endif "MOREPROMPT=more> ", +#endif "RADIX=16", "MDCOUNT=8", /* lines of md output */ KDB_PLATFORM_ENV, @@ -1236,6 +1236,18 @@ static int kdb_local(kdb_reason_t reason, int error, struct pt_regs *regs, *cmdbuf = '\0'; *(cmd_hist[cmd_head]) = '\0'; + if (KDB_FLAG(ONLY_DO_DUMP)) { + /* kdb is off but a catastrophic error requires a dump. + * Take the dump and reboot. + * Turn on logging so the kdb output appears in the log + * buffer in the dump. + */ + const char *setargs[] = { "set", "LOGGING", "1" }; + kdb_set(2, setargs); + kdb_reboot(0, NULL); + /*NOTREACHED*/ + } + do_full_getstr: #if defined(CONFIG_SMP) snprintf(kdb_prompt_str, CMD_BUFLEN, kdbgetenv("PROMPT"), @@ -2108,32 +2120,6 @@ static int kdb_dmesg(int argc, const char **argv) return 0; } #endif /* CONFIG_PRINTK */ - -/* Make sure we balance enable/disable calls, must disable first. */ -static atomic_t kdb_nmi_disabled; - -static int kdb_disable_nmi(int argc, const char *argv[]) -{ - if (atomic_read(&kdb_nmi_disabled)) - return 0; - atomic_set(&kdb_nmi_disabled, 1); - arch_kgdb_ops.enable_nmi(0); - return 0; -} - -static int kdb_param_enable_nmi(const char *val, const struct kernel_param *kp) -{ - if (!atomic_add_unless(&kdb_nmi_disabled, -1, 0)) - return -EINVAL; - arch_kgdb_ops.enable_nmi(1); - return 0; -} - -static const struct kernel_param_ops kdb_param_ops_enable_nmi = { - .set = kdb_param_enable_nmi, -}; -module_param_cb(enable_nmi, &kdb_param_ops_enable_nmi, NULL, 0600); - /* * kdb_cpu - This function implements the 'cpu' command. * cpu [] @@ -2878,10 +2864,6 @@ static void __init kdb_inittab(void) kdb_register_repeat("dmesg", kdb_dmesg, "[lines]", "Display syslog buffer", 0, KDB_REPEAT_NONE); #endif - if (arch_kgdb_ops.enable_nmi) { - kdb_register_repeat("disable_nmi", kdb_disable_nmi, "", - "Disable NMI entry to KDB", 0, KDB_REPEAT_NONE); - } kdb_register_repeat("defcmd", kdb_defcmd, "name \"usage\" \"help\"", "Define a set of commands, down to endefcmd", 0, KDB_REPEAT_NONE); kdb_register_repeat("kill", kdb_kill, "<-signal> ", diff --git a/trunk/kernel/events/callchain.c b/trunk/kernel/events/callchain.c index c77206184b8b..6581a040f399 100644 --- a/trunk/kernel/events/callchain.c +++ b/trunk/kernel/events/callchain.c @@ -153,17 +153,11 @@ put_callchain_entry(int rctx) put_recursion_context(__get_cpu_var(callchain_recursion), rctx); } -struct perf_callchain_entry * -perf_callchain(struct perf_event *event, struct pt_regs *regs) +struct perf_callchain_entry *perf_callchain(struct pt_regs *regs) { int rctx; struct perf_callchain_entry *entry; - int kernel = !event->attr.exclude_callchain_kernel; - int user = !event->attr.exclude_callchain_user; - - if (!kernel && !user) - return NULL; entry = get_callchain_entry(&rctx); if (rctx == -1) @@ -174,29 +168,18 @@ perf_callchain(struct perf_event *event, struct pt_regs *regs) entry->nr = 0; - if (kernel && !user_mode(regs)) { + if (!user_mode(regs)) { perf_callchain_store(entry, PERF_CONTEXT_KERNEL); perf_callchain_kernel(entry, regs); + if (current->mm) + regs = task_pt_regs(current); + else + regs = NULL; } - if (user) { - if (!user_mode(regs)) { - if (current->mm) - regs = task_pt_regs(current); - else - regs = NULL; - } - - if (regs) { - /* - * Disallow cross-task user callchains. - */ - if (event->ctx->task && event->ctx->task != current) - goto exit_put; - - perf_callchain_store(entry, PERF_CONTEXT_USER); - perf_callchain_user(entry, regs); - } + if (regs) { + perf_callchain_store(entry, PERF_CONTEXT_USER); + perf_callchain_user(entry, regs); } exit_put: diff --git a/trunk/kernel/events/core.c b/trunk/kernel/events/core.c index 7b9df353ba1b..f1cf0edeb39a 100644 --- a/trunk/kernel/events/core.c +++ b/trunk/kernel/events/core.c @@ -36,7 +36,6 @@ #include #include #include -#include #include "internal.h" @@ -1254,7 +1253,7 @@ static void perf_remove_from_context(struct perf_event *event) /* * Cross CPU call to disable a performance event */ -int __perf_event_disable(void *info) +static int __perf_event_disable(void *info) { struct perf_event *event = info; struct perf_event_context *ctx = event->ctx; @@ -2936,12 +2935,12 @@ EXPORT_SYMBOL_GPL(perf_event_release_kernel); /* * Called when the last reference to the file is gone. */ -static void put_event(struct perf_event *event) +static int perf_release(struct inode *inode, struct file *file) { + struct perf_event *event = file->private_data; struct task_struct *owner; - if (!atomic_long_dec_and_test(&event->refcount)) - return; + file->private_data = NULL; rcu_read_lock(); owner = ACCESS_ONCE(event->owner); @@ -2976,13 +2975,7 @@ static void put_event(struct perf_event *event) put_task_struct(owner); } - perf_event_release_kernel(event); -} - -static int perf_release(struct inode *inode, struct file *file) -{ - put_event(file->private_data); - return 0; + return perf_event_release_kernel(event); } u64 perf_event_read_value(struct perf_event *event, u64 *enabled, u64 *running) @@ -3234,7 +3227,7 @@ static int perf_event_period(struct perf_event *event, u64 __user *arg) static const struct file_operations perf_fops; -static struct file *perf_fget_light(int fd, int *fput_needed) +static struct perf_event *perf_fget_light(int fd, int *fput_needed) { struct file *file; @@ -3248,7 +3241,7 @@ static struct file *perf_fget_light(int fd, int *fput_needed) return ERR_PTR(-EBADF); } - return file; + return file->private_data; } static int perf_event_set_output(struct perf_event *event, @@ -3280,21 +3273,19 @@ static long perf_ioctl(struct file *file, unsigned int cmd, unsigned long arg) case PERF_EVENT_IOC_SET_OUTPUT: { - struct file *output_file = NULL; struct perf_event *output_event = NULL; int fput_needed = 0; int ret; if (arg != -1) { - output_file = perf_fget_light(arg, &fput_needed); - if (IS_ERR(output_file)) - return PTR_ERR(output_file); - output_event = output_file->private_data; + output_event = perf_fget_light(arg, &fput_needed); + if (IS_ERR(output_event)) + return PTR_ERR(output_event); } ret = perf_event_set_output(event, output_event); if (output_event) - fput_light(output_file, fput_needed); + fput_light(output_event->filp, fput_needed); return ret; } @@ -3765,132 +3756,6 @@ int perf_unregister_guest_info_callbacks(struct perf_guest_info_callbacks *cbs) } EXPORT_SYMBOL_GPL(perf_unregister_guest_info_callbacks); -static void -perf_output_sample_regs(struct perf_output_handle *handle, - struct pt_regs *regs, u64 mask) -{ - int bit; - - for_each_set_bit(bit, (const unsigned long *) &mask, - sizeof(mask) * BITS_PER_BYTE) { - u64 val; - - val = perf_reg_value(regs, bit); - perf_output_put(handle, val); - } -} - -static void perf_sample_regs_user(struct perf_regs_user *regs_user, - struct pt_regs *regs) -{ - if (!user_mode(regs)) { - if (current->mm) - regs = task_pt_regs(current); - else - regs = NULL; - } - - if (regs) { - regs_user->regs = regs; - regs_user->abi = perf_reg_abi(current); - } -} - -/* - * Get remaining task size from user stack pointer. - * - * It'd be better to take stack vma map and limit this more - * precisly, but there's no way to get it safely under interrupt, - * so using TASK_SIZE as limit. - */ -static u64 perf_ustack_task_size(struct pt_regs *regs) -{ - unsigned long addr = perf_user_stack_pointer(regs); - - if (!addr || addr >= TASK_SIZE) - return 0; - - return TASK_SIZE - addr; -} - -static u16 -perf_sample_ustack_size(u16 stack_size, u16 header_size, - struct pt_regs *regs) -{ - u64 task_size; - - /* No regs, no stack pointer, no dump. */ - if (!regs) - return 0; - - /* - * Check if we fit in with the requested stack size into the: - * - TASK_SIZE - * If we don't, we limit the size to the TASK_SIZE. - * - * - remaining sample size - * If we don't, we customize the stack size to - * fit in to the remaining sample size. - */ - - task_size = min((u64) USHRT_MAX, perf_ustack_task_size(regs)); - stack_size = min(stack_size, (u16) task_size); - - /* Current header size plus static size and dynamic size. */ - header_size += 2 * sizeof(u64); - - /* Do we fit in with the current stack dump size? */ - if ((u16) (header_size + stack_size) < header_size) { - /* - * If we overflow the maximum size for the sample, - * we customize the stack dump size to fit in. - */ - stack_size = USHRT_MAX - header_size - sizeof(u64); - stack_size = round_up(stack_size, sizeof(u64)); - } - - return stack_size; -} - -static void -perf_output_sample_ustack(struct perf_output_handle *handle, u64 dump_size, - struct pt_regs *regs) -{ - /* Case of a kernel thread, nothing to dump */ - if (!regs) { - u64 size = 0; - perf_output_put(handle, size); - } else { - unsigned long sp; - unsigned int rem; - u64 dyn_size; - - /* - * We dump: - * static size - * - the size requested by user or the best one we can fit - * in to the sample max size - * data - * - user stack dump data - * dynamic size - * - the actual dumped size - */ - - /* Static size. */ - perf_output_put(handle, dump_size); - - /* Data. */ - sp = perf_user_stack_pointer(regs); - rem = __output_copy_user(handle, (void *) sp, dump_size); - dyn_size = dump_size - rem; - - perf_output_skip(handle, rem); - - /* Dynamic size. */ - perf_output_put(handle, dyn_size); - } -} - static void __perf_event_header__init_id(struct perf_event_header *header, struct perf_sample_data *data, struct perf_event *event) @@ -4151,28 +4016,6 @@ void perf_output_sample(struct perf_output_handle *handle, perf_output_put(handle, nr); } } - - if (sample_type & PERF_SAMPLE_REGS_USER) { - u64 abi = data->regs_user.abi; - - /* - * If there are no regs to dump, notice it through - * first u64 being zero (PERF_SAMPLE_REGS_ABI_NONE). - */ - perf_output_put(handle, abi); - - if (abi) { - u64 mask = event->attr.sample_regs_user; - perf_output_sample_regs(handle, - data->regs_user.regs, - mask); - } - } - - if (sample_type & PERF_SAMPLE_STACK_USER) - perf_output_sample_ustack(handle, - data->stack_user_size, - data->regs_user.regs); } void perf_prepare_sample(struct perf_event_header *header, @@ -4196,7 +4039,7 @@ void perf_prepare_sample(struct perf_event_header *header, if (sample_type & PERF_SAMPLE_CALLCHAIN) { int size = 1; - data->callchain = perf_callchain(event, regs); + data->callchain = perf_callchain(regs); if (data->callchain) size += data->callchain->nr; @@ -4224,49 +4067,6 @@ void perf_prepare_sample(struct perf_event_header *header, } header->size += size; } - - if (sample_type & PERF_SAMPLE_REGS_USER) { - /* regs dump ABI info */ - int size = sizeof(u64); - - perf_sample_regs_user(&data->regs_user, regs); - - if (data->regs_user.regs) { - u64 mask = event->attr.sample_regs_user; - size += hweight64(mask) * sizeof(u64); - } - - header->size += size; - } - - if (sample_type & PERF_SAMPLE_STACK_USER) { - /* - * Either we need PERF_SAMPLE_STACK_USER bit to be allways - * processed as the last one or have additional check added - * in case new sample type is added, because we could eat - * up the rest of the sample size. - */ - struct perf_regs_user *uregs = &data->regs_user; - u16 stack_size = event->attr.sample_stack_user; - u16 size = sizeof(u64); - - if (!uregs->abi) - perf_sample_regs_user(uregs, regs); - - stack_size = perf_sample_ustack_size(stack_size, header->size, - uregs->regs); - - /* - * If there is something to dump, add space for the dump - * itself and for the field that tells the dynamic size, - * which is how many have been actually dumped. - */ - if (stack_size) - size += sizeof(u64) + stack_size; - - data->stack_user_size = stack_size; - header->size += size; - } } static void perf_event_output(struct perf_event *event, @@ -5409,8 +5209,7 @@ static int perf_tp_event_match(struct perf_event *event, } void perf_tp_event(u64 addr, u64 count, void *record, int entry_size, - struct pt_regs *regs, struct hlist_head *head, int rctx, - struct task_struct *task) + struct pt_regs *regs, struct hlist_head *head, int rctx) { struct perf_sample_data data; struct perf_event *event; @@ -5429,31 +5228,6 @@ void perf_tp_event(u64 addr, u64 count, void *record, int entry_size, perf_swevent_event(event, count, &data, regs); } - /* - * If we got specified a target task, also iterate its context and - * deliver this event there too. - */ - if (task && task != current) { - struct perf_event_context *ctx; - struct trace_entry *entry = record; - - rcu_read_lock(); - ctx = rcu_dereference(task->perf_event_ctxp[perf_sw_context]); - if (!ctx) - goto unlock; - - list_for_each_entry_rcu(event, &ctx->event_list, event_entry) { - if (event->attr.type != PERF_TYPE_TRACEPOINT) - continue; - if (event->attr.config != entry->type) - continue; - if (perf_tp_event_match(event, &data, regs)) - perf_swevent_event(event, count, &data, regs); - } -unlock: - rcu_read_unlock(); - } - perf_swevent_put_recursion_context(rctx); } EXPORT_SYMBOL_GPL(perf_tp_event); @@ -6150,7 +5924,6 @@ perf_event_alloc(struct perf_event_attr *attr, int cpu, mutex_init(&event->mmap_mutex); - atomic_long_set(&event->refcount, 1); event->cpu = cpu; event->attr = *attr; event->group_leader = group_leader; @@ -6343,28 +6116,6 @@ static int perf_copy_attr(struct perf_event_attr __user *uattr, attr->branch_sample_type = mask; } } - - if (attr->sample_type & PERF_SAMPLE_REGS_USER) { - ret = perf_reg_validate(attr->sample_regs_user); - if (ret) - return ret; - } - - if (attr->sample_type & PERF_SAMPLE_STACK_USER) { - if (!arch_perf_have_user_stack_dump()) - return -ENOSYS; - - /* - * We have __u32 type for the size, but so far - * we can only use __u16 as maximum due to the - * __u16 sample size limit. - */ - if (attr->sample_stack_user >= USHRT_MAX) - ret = -EINVAL; - else if (!IS_ALIGNED(attr->sample_stack_user, sizeof(u64))) - ret = -EINVAL; - } - out: return ret; @@ -6483,12 +6234,12 @@ SYSCALL_DEFINE5(perf_event_open, return event_fd; if (group_fd != -1) { - group_file = perf_fget_light(group_fd, &fput_needed); - if (IS_ERR(group_file)) { - err = PTR_ERR(group_file); + group_leader = perf_fget_light(group_fd, &fput_needed); + if (IS_ERR(group_leader)) { + err = PTR_ERR(group_leader); goto err_fd; } - group_leader = group_file->private_data; + group_file = group_leader->filp; if (flags & PERF_FLAG_FD_OUTPUT) output_event = group_leader; if (flags & PERF_FLAG_FD_NO_GROUP) @@ -6625,6 +6376,7 @@ SYSCALL_DEFINE5(perf_event_open, put_ctx(gctx); } + event->filp = event_file; WARN_ON_ONCE(ctx->parent_ctx); mutex_lock(&ctx->mutex); @@ -6718,6 +6470,7 @@ perf_event_create_kernel_counter(struct perf_event_attr *attr, int cpu, goto err_free; } + event->filp = NULL; WARN_ON_ONCE(ctx->parent_ctx); mutex_lock(&ctx->mutex); perf_install_in_context(ctx, event, cpu); @@ -6799,7 +6552,7 @@ static void sync_child_event(struct perf_event *child_event, * Release the parent event, if this was the last * reference to it. */ - put_event(parent_event); + fput(parent_event->filp); } static void @@ -6875,8 +6628,9 @@ static void perf_event_exit_task_context(struct task_struct *child, int ctxn) * * __perf_event_exit_task() * sync_child_event() - * put_event() - * mutex_lock(&ctx->mutex) + * fput(parent_event->filp) + * perf_release() + * mutex_lock(&ctx->mutex) * * But since its the parent context it won't be the same instance. */ @@ -6944,7 +6698,7 @@ static void perf_free_event(struct perf_event *event, list_del_init(&event->child_list); mutex_unlock(&parent->child_mutex); - put_event(parent); + fput(parent->filp); perf_group_detach(event); list_del_event(event, ctx); @@ -7024,12 +6778,6 @@ inherit_event(struct perf_event *parent_event, NULL, NULL); if (IS_ERR(child_event)) return child_event; - - if (!atomic_long_inc_not_zero(&parent_event->refcount)) { - free_event(child_event); - return NULL; - } - get_ctx(child_ctx); /* @@ -7070,6 +6818,14 @@ inherit_event(struct perf_event *parent_event, add_event_to_ctx(child_event, child_ctx); raw_spin_unlock_irqrestore(&child_ctx->lock, flags); + /* + * Get a reference to the parent filp - we will fput it + * when the child event exits. This is safe to do because + * we are in the parent and we know that the filp still + * exists and has a nonzero count: + */ + atomic_long_inc(&parent_event->filp->f_count); + /* * Link this into the parent event's child list */ diff --git a/trunk/kernel/events/hw_breakpoint.c b/trunk/kernel/events/hw_breakpoint.c index 9a7b487c6fe2..bb38c4d3ee12 100644 --- a/trunk/kernel/events/hw_breakpoint.c +++ b/trunk/kernel/events/hw_breakpoint.c @@ -453,16 +453,7 @@ int modify_user_hw_breakpoint(struct perf_event *bp, struct perf_event_attr *att int old_type = bp->attr.bp_type; int err = 0; - /* - * modify_user_hw_breakpoint can be invoked with IRQs disabled and hence it - * will not be possible to raise IPIs that invoke __perf_event_disable. - * So call the function directly after making sure we are targeting the - * current task. - */ - if (irqs_disabled() && bp->ctx && bp->ctx->task == current) - __perf_event_disable(bp); - else - perf_event_disable(bp); + perf_event_disable(bp); bp->attr.bp_addr = attr->bp_addr; bp->attr.bp_type = attr->bp_type; diff --git a/trunk/kernel/events/internal.h b/trunk/kernel/events/internal.h index d56a64c99a8b..b0b107f90afc 100644 --- a/trunk/kernel/events/internal.h +++ b/trunk/kernel/events/internal.h @@ -2,7 +2,6 @@ #define _KERNEL_EVENTS_INTERNAL_H #include -#include /* Buffer handling */ @@ -77,56 +76,32 @@ static inline unsigned long perf_data_size(struct ring_buffer *rb) return rb->nr_pages << (PAGE_SHIFT + page_order(rb)); } -#define DEFINE_OUTPUT_COPY(func_name, memcpy_func) \ -static inline unsigned int \ -func_name(struct perf_output_handle *handle, \ - const void *buf, unsigned int len) \ -{ \ - unsigned long size, written; \ - \ - do { \ - size = min_t(unsigned long, handle->size, len); \ - \ - written = memcpy_func(handle->addr, buf, size); \ - \ - len -= written; \ - handle->addr += written; \ - buf += written; \ - handle->size -= written; \ - if (!handle->size) { \ - struct ring_buffer *rb = handle->rb; \ - \ - handle->page++; \ - handle->page &= rb->nr_pages - 1; \ - handle->addr = rb->data_pages[handle->page]; \ - handle->size = PAGE_SIZE << page_order(rb); \ - } \ - } while (len && written == size); \ - \ - return len; \ -} - -static inline int memcpy_common(void *dst, const void *src, size_t n) +static inline void +__output_copy(struct perf_output_handle *handle, + const void *buf, unsigned int len) { - memcpy(dst, src, n); - return n; + do { + unsigned long size = min_t(unsigned long, handle->size, len); + + memcpy(handle->addr, buf, size); + + len -= size; + handle->addr += size; + buf += size; + handle->size -= size; + if (!handle->size) { + struct ring_buffer *rb = handle->rb; + + handle->page++; + handle->page &= rb->nr_pages - 1; + handle->addr = rb->data_pages[handle->page]; + handle->size = PAGE_SIZE << page_order(rb); + } + } while (len); } -DEFINE_OUTPUT_COPY(__output_copy, memcpy_common) - -#define MEMCPY_SKIP(dst, src, n) (n) - -DEFINE_OUTPUT_COPY(__output_skip, MEMCPY_SKIP) - -#ifndef arch_perf_out_copy_user -#define arch_perf_out_copy_user __copy_from_user_inatomic -#endif - -DEFINE_OUTPUT_COPY(__output_copy_user, arch_perf_out_copy_user) - /* Callchain handling */ -extern struct perf_callchain_entry * -perf_callchain(struct perf_event *event, struct pt_regs *regs); +extern struct perf_callchain_entry *perf_callchain(struct pt_regs *regs); extern int get_callchain_buffers(void); extern void put_callchain_buffers(void); @@ -158,20 +133,4 @@ static inline void put_recursion_context(int *recursion, int rctx) recursion[rctx]--; } -#ifdef CONFIG_HAVE_PERF_USER_STACK_DUMP -static inline bool arch_perf_have_user_stack_dump(void) -{ - return true; -} - -#define perf_user_stack_pointer(regs) user_stack_pointer(regs) -#else -static inline bool arch_perf_have_user_stack_dump(void) -{ - return false; -} - -#define perf_user_stack_pointer(regs) 0 -#endif /* CONFIG_HAVE_PERF_USER_STACK_DUMP */ - #endif /* _KERNEL_EVENTS_INTERNAL_H */ diff --git a/trunk/kernel/events/ring_buffer.c b/trunk/kernel/events/ring_buffer.c index 23cb34ff3973..6ddaba43fb7a 100644 --- a/trunk/kernel/events/ring_buffer.c +++ b/trunk/kernel/events/ring_buffer.c @@ -182,16 +182,10 @@ int perf_output_begin(struct perf_output_handle *handle, return -ENOSPC; } -unsigned int perf_output_copy(struct perf_output_handle *handle, +void perf_output_copy(struct perf_output_handle *handle, const void *buf, unsigned int len) { - return __output_copy(handle, buf, len); -} - -unsigned int perf_output_skip(struct perf_output_handle *handle, - unsigned int len) -{ - return __output_skip(handle, NULL, len); + __output_copy(handle, buf, len); } void perf_output_end(struct perf_output_handle *handle) diff --git a/trunk/kernel/events/uprobes.c b/trunk/kernel/events/uprobes.c index 912ef48d28ab..c08a22d02f72 100644 --- a/trunk/kernel/events/uprobes.c +++ b/trunk/kernel/events/uprobes.c @@ -280,10 +280,12 @@ static int read_opcode(struct mm_struct *mm, unsigned long vaddr, uprobe_opcode_ if (ret <= 0) return ret; + lock_page(page); vaddr_new = kmap_atomic(page); vaddr &= ~PAGE_MASK; memcpy(opcode, vaddr_new + vaddr, UPROBE_SWBP_INSN_SIZE); kunmap_atomic(vaddr_new); + unlock_page(page); put_page(page); @@ -332,7 +334,7 @@ int __weak set_swbp(struct arch_uprobe *auprobe, struct mm_struct *mm, unsigned */ result = is_swbp_at_addr(mm, vaddr); if (result == 1) - return 0; + return -EEXIST; if (result) return result; @@ -345,22 +347,24 @@ int __weak set_swbp(struct arch_uprobe *auprobe, struct mm_struct *mm, unsigned * @mm: the probed process address space. * @auprobe: arch specific probepoint information. * @vaddr: the virtual address to insert the opcode. + * @verify: if true, verify existance of breakpoint instruction. * * For mm @mm, restore the original opcode (opcode) at @vaddr. * Return 0 (success) or a negative errno. */ int __weak -set_orig_insn(struct arch_uprobe *auprobe, struct mm_struct *mm, unsigned long vaddr) +set_orig_insn(struct arch_uprobe *auprobe, struct mm_struct *mm, unsigned long vaddr, bool verify) { - int result; - - result = is_swbp_at_addr(mm, vaddr); - if (!result) - return -EINVAL; + if (verify) { + int result; - if (result != 1) - return result; + result = is_swbp_at_addr(mm, vaddr); + if (!result) + return -EINVAL; + if (result != 1) + return result; + } return write_opcode(auprobe, mm, vaddr, *(uprobe_opcode_t *)auprobe->insn); } @@ -411,10 +415,11 @@ static struct uprobe *__find_uprobe(struct inode *inode, loff_t offset) static struct uprobe *find_uprobe(struct inode *inode, loff_t offset) { struct uprobe *uprobe; + unsigned long flags; - spin_lock(&uprobes_treelock); + spin_lock_irqsave(&uprobes_treelock, flags); uprobe = __find_uprobe(inode, offset); - spin_unlock(&uprobes_treelock); + spin_unlock_irqrestore(&uprobes_treelock, flags); return uprobe; } @@ -461,11 +466,12 @@ static struct uprobe *__insert_uprobe(struct uprobe *uprobe) */ static struct uprobe *insert_uprobe(struct uprobe *uprobe) { + unsigned long flags; struct uprobe *u; - spin_lock(&uprobes_treelock); + spin_lock_irqsave(&uprobes_treelock, flags); u = __insert_uprobe(uprobe); - spin_unlock(&uprobes_treelock); + spin_unlock_irqrestore(&uprobes_treelock, flags); /* For now assume that the instruction need not be single-stepped */ uprobe->flags |= UPROBE_SKIP_SSTEP; @@ -643,7 +649,6 @@ static int install_breakpoint(struct uprobe *uprobe, struct mm_struct *mm, struct vm_area_struct *vma, unsigned long vaddr) { - bool first_uprobe; int ret; /* @@ -654,7 +659,7 @@ install_breakpoint(struct uprobe *uprobe, struct mm_struct *mm, * Hence behave as if probe already existed. */ if (!uprobe->consumers) - return 0; + return -EEXIST; if (!(uprobe->flags & UPROBE_COPY_INSN)) { ret = copy_insn(uprobe, vma->vm_file); @@ -676,18 +681,17 @@ install_breakpoint(struct uprobe *uprobe, struct mm_struct *mm, } /* - * set MMF_HAS_UPROBES in advance for uprobe_pre_sstep_notifier(), - * the task can hit this breakpoint right after __replace_page(). + * Ideally, should be updating the probe count after the breakpoint + * has been successfully inserted. However a thread could hit the + * breakpoint we just inserted even before the probe count is + * incremented. If this is the first breakpoint placed, breakpoint + * notifier might ignore uprobes and pass the trap to the thread. + * Hence increment before and decrement on failure. */ - first_uprobe = !test_bit(MMF_HAS_UPROBES, &mm->flags); - if (first_uprobe) - set_bit(MMF_HAS_UPROBES, &mm->flags); - + atomic_inc(&mm->uprobes_state.count); ret = set_swbp(&uprobe->arch, mm, vaddr); - if (!ret) - clear_bit(MMF_RECALC_UPROBES, &mm->flags); - else if (first_uprobe) - clear_bit(MMF_HAS_UPROBES, &mm->flags); + if (ret) + atomic_dec(&mm->uprobes_state.count); return ret; } @@ -695,12 +699,8 @@ install_breakpoint(struct uprobe *uprobe, struct mm_struct *mm, static void remove_breakpoint(struct uprobe *uprobe, struct mm_struct *mm, unsigned long vaddr) { - /* can happen if uprobe_register() fails */ - if (!test_bit(MMF_HAS_UPROBES, &mm->flags)) - return; - - set_bit(MMF_RECALC_UPROBES, &mm->flags); - set_orig_insn(&uprobe->arch, mm, vaddr); + if (!set_orig_insn(&uprobe->arch, mm, vaddr, true)) + atomic_dec(&mm->uprobes_state.count); } /* @@ -710,9 +710,11 @@ remove_breakpoint(struct uprobe *uprobe, struct mm_struct *mm, unsigned long vad */ static void delete_uprobe(struct uprobe *uprobe) { - spin_lock(&uprobes_treelock); + unsigned long flags; + + spin_lock_irqsave(&uprobes_treelock, flags); rb_erase(&uprobe->rb_node, &uprobes_tree); - spin_unlock(&uprobes_treelock); + spin_unlock_irqrestore(&uprobes_treelock, flags); iput(uprobe->inode); put_uprobe(uprobe); atomic_dec(&uprobe_events); @@ -829,11 +831,17 @@ static int register_for_each_vma(struct uprobe *uprobe, bool is_register) vaddr_to_offset(vma, info->vaddr) != uprobe->offset) goto unlock; - if (is_register) + if (is_register) { err = install_breakpoint(uprobe, mm, vma, info->vaddr); - else + /* + * We can race against uprobe_mmap(), see the + * comment near uprobe_hash(). + */ + if (err == -EEXIST) + err = 0; + } else { remove_breakpoint(uprobe, mm, info->vaddr); - + } unlock: up_write(&mm->mmap_sem); free: @@ -900,8 +908,7 @@ int uprobe_register(struct inode *inode, loff_t offset, struct uprobe_consumer * } mutex_unlock(uprobes_hash(inode)); - if (uprobe) - put_uprobe(uprobe); + put_uprobe(uprobe); return ret; } @@ -971,6 +978,7 @@ static void build_probe_list(struct inode *inode, struct list_head *head) { loff_t min, max; + unsigned long flags; struct rb_node *n, *t; struct uprobe *u; @@ -978,7 +986,7 @@ static void build_probe_list(struct inode *inode, min = vaddr_to_offset(vma, start); max = min + (end - start) - 1; - spin_lock(&uprobes_treelock); + spin_lock_irqsave(&uprobes_treelock, flags); n = find_node_in_range(inode, min, max); if (n) { for (t = n; t; t = rb_prev(t)) { @@ -996,20 +1004,27 @@ static void build_probe_list(struct inode *inode, atomic_inc(&u->ref); } } - spin_unlock(&uprobes_treelock); + spin_unlock_irqrestore(&uprobes_treelock, flags); } /* - * Called from mmap_region/vma_adjust with mm->mmap_sem acquired. + * Called from mmap_region. + * called with mm->mmap_sem acquired. * - * Currently we ignore all errors and always return 0, the callers - * can't handle the failure anyway. + * Return -ve no if we fail to insert probes and we cannot + * bail-out. + * Return 0 otherwise. i.e: + * + * - successful insertion of probes + * - (or) no possible probes to be inserted. + * - (or) insertion of probes failed but we can bail-out. */ int uprobe_mmap(struct vm_area_struct *vma) { struct list_head tmp_list; struct uprobe *uprobe, *u; struct inode *inode; + int ret, count; if (!atomic_read(&uprobe_events) || !valid_vma(vma, true)) return 0; @@ -1021,35 +1036,44 @@ int uprobe_mmap(struct vm_area_struct *vma) mutex_lock(uprobes_mmap_hash(inode)); build_probe_list(inode, vma, vma->vm_start, vma->vm_end, &tmp_list); + ret = 0; + count = 0; + list_for_each_entry_safe(uprobe, u, &tmp_list, pending_list) { - if (!fatal_signal_pending(current)) { + if (!ret) { unsigned long vaddr = offset_to_vaddr(vma, uprobe->offset); - install_breakpoint(uprobe, vma->vm_mm, vma, vaddr); + + ret = install_breakpoint(uprobe, vma->vm_mm, vma, vaddr); + /* + * We can race against uprobe_register(), see the + * comment near uprobe_hash(). + */ + if (ret == -EEXIST) { + ret = 0; + + if (!is_swbp_at_addr(vma->vm_mm, vaddr)) + continue; + + /* + * Unable to insert a breakpoint, but + * breakpoint lies underneath. Increment the + * probe count. + */ + atomic_inc(&vma->vm_mm->uprobes_state.count); + } + + if (!ret) + count++; } put_uprobe(uprobe); } - mutex_unlock(uprobes_mmap_hash(inode)); - - return 0; -} - -static bool -vma_has_uprobes(struct vm_area_struct *vma, unsigned long start, unsigned long end) -{ - loff_t min, max; - struct inode *inode; - struct rb_node *n; - - inode = vma->vm_file->f_mapping->host; - min = vaddr_to_offset(vma, start); - max = min + (end - start) - 1; + mutex_unlock(uprobes_mmap_hash(inode)); - spin_lock(&uprobes_treelock); - n = find_node_in_range(inode, min, max); - spin_unlock(&uprobes_treelock); + if (ret) + atomic_sub(count, &vma->vm_mm->uprobes_state.count); - return !!n; + return ret; } /* @@ -1057,18 +1081,37 @@ vma_has_uprobes(struct vm_area_struct *vma, unsigned long start, unsigned long e */ void uprobe_munmap(struct vm_area_struct *vma, unsigned long start, unsigned long end) { + struct list_head tmp_list; + struct uprobe *uprobe, *u; + struct inode *inode; + if (!atomic_read(&uprobe_events) || !valid_vma(vma, false)) return; if (!atomic_read(&vma->vm_mm->mm_users)) /* called by mmput() ? */ return; - if (!test_bit(MMF_HAS_UPROBES, &vma->vm_mm->flags) || - test_bit(MMF_RECALC_UPROBES, &vma->vm_mm->flags)) + if (!atomic_read(&vma->vm_mm->uprobes_state.count)) + return; + + inode = vma->vm_file->f_mapping->host; + if (!inode) return; - if (vma_has_uprobes(vma, start, end)) - set_bit(MMF_RECALC_UPROBES, &vma->vm_mm->flags); + mutex_lock(uprobes_mmap_hash(inode)); + build_probe_list(inode, vma, start, end, &tmp_list); + + list_for_each_entry_safe(uprobe, u, &tmp_list, pending_list) { + unsigned long vaddr = offset_to_vaddr(vma, uprobe->offset); + /* + * An unregister could have removed the probe before + * unmap. So check before we decrement the count. + */ + if (is_swbp_at_addr(vma->vm_mm, vaddr) == 1) + atomic_dec(&vma->vm_mm->uprobes_state.count); + put_uprobe(uprobe); + } + mutex_unlock(uprobes_mmap_hash(inode)); } /* Slot allocation for XOL */ @@ -1170,15 +1213,13 @@ void uprobe_clear_state(struct mm_struct *mm) kfree(area); } -void uprobe_dup_mmap(struct mm_struct *oldmm, struct mm_struct *newmm) +/* + * uprobe_reset_state - Free the area allocated for slots. + */ +void uprobe_reset_state(struct mm_struct *mm) { - newmm->uprobes_state.xol_area = NULL; - - if (test_bit(MMF_HAS_UPROBES, &oldmm->flags)) { - set_bit(MMF_HAS_UPROBES, &newmm->flags); - /* unconditionally, dup_mmap() skips VM_DONTCOPY vmas */ - set_bit(MMF_RECALC_UPROBES, &newmm->flags); - } + mm->uprobes_state.xol_area = NULL; + atomic_set(&mm->uprobes_state.count, 0); } /* @@ -1396,25 +1437,6 @@ static bool can_skip_sstep(struct uprobe *uprobe, struct pt_regs *regs) return false; } -static void mmf_recalc_uprobes(struct mm_struct *mm) -{ - struct vm_area_struct *vma; - - for (vma = mm->mmap; vma; vma = vma->vm_next) { - if (!valid_vma(vma, false)) - continue; - /* - * This is not strictly accurate, we can race with - * uprobe_unregister() and see the already removed - * uprobe if delete_uprobe() was not yet called. - */ - if (vma_has_uprobes(vma, vma->vm_start, vma->vm_end)) - return; - } - - clear_bit(MMF_HAS_UPROBES, &mm->flags); -} - static struct uprobe *find_active_uprobe(unsigned long bp_vaddr, int *is_swbp) { struct mm_struct *mm = current->mm; @@ -1436,24 +1458,11 @@ static struct uprobe *find_active_uprobe(unsigned long bp_vaddr, int *is_swbp) } else { *is_swbp = -EFAULT; } - - if (!uprobe && test_and_clear_bit(MMF_RECALC_UPROBES, &mm->flags)) - mmf_recalc_uprobes(mm); up_read(&mm->mmap_sem); return uprobe; } -void __weak arch_uprobe_enable_step(struct arch_uprobe *arch) -{ - user_enable_single_step(current); -} - -void __weak arch_uprobe_disable_step(struct arch_uprobe *arch) -{ - user_disable_single_step(current); -} - /* * Run handler and ask thread to singlestep. * Ensure all non-fatal signals cannot interrupt thread while it singlesteps. @@ -1500,7 +1509,7 @@ static void handle_swbp(struct pt_regs *regs) utask->state = UTASK_SSTEP; if (!pre_ssout(uprobe, regs, bp_vaddr)) { - arch_uprobe_enable_step(&uprobe->arch); + user_enable_single_step(current); return; } @@ -1509,15 +1518,17 @@ static void handle_swbp(struct pt_regs *regs) utask->active_uprobe = NULL; utask->state = UTASK_RUNNING; } - if (!(uprobe->flags & UPROBE_SKIP_SSTEP)) + if (uprobe) { + if (!(uprobe->flags & UPROBE_SKIP_SSTEP)) - /* - * cannot singlestep; cannot skip instruction; - * re-execute the instruction. - */ - instruction_pointer_set(regs, bp_vaddr); + /* + * cannot singlestep; cannot skip instruction; + * re-execute the instruction. + */ + instruction_pointer_set(regs, bp_vaddr); - put_uprobe(uprobe); + put_uprobe(uprobe); + } } /* @@ -1536,10 +1547,10 @@ static void handle_singlestep(struct uprobe_task *utask, struct pt_regs *regs) else WARN_ON_ONCE(1); - arch_uprobe_disable_step(&uprobe->arch); put_uprobe(uprobe); utask->active_uprobe = NULL; utask->state = UTASK_RUNNING; + user_disable_single_step(current); xol_free_insn_slot(current); spin_lock_irq(¤t->sighand->siglock); @@ -1578,7 +1589,8 @@ int uprobe_pre_sstep_notifier(struct pt_regs *regs) { struct uprobe_task *utask; - if (!current->mm || !test_bit(MMF_HAS_UPROBES, ¤t->mm->flags)) + if (!current->mm || !atomic_read(¤t->mm->uprobes_state.count)) + /* task is currently not uprobed */ return 0; utask = current->utask; diff --git a/trunk/kernel/fork.c b/trunk/kernel/fork.c index 5a0e74d89a5a..3bd2280d79f6 100644 --- a/trunk/kernel/fork.c +++ b/trunk/kernel/fork.c @@ -353,7 +353,6 @@ static int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm) down_write(&oldmm->mmap_sem); flush_cache_dup_mm(oldmm); - uprobe_dup_mmap(oldmm, mm); /* * Not linked in yet - no deadlock potential: */ @@ -455,6 +454,9 @@ static int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm) if (retval) goto out; + + if (file && uprobe_mmap(tmp)) + goto out; } /* a new mm has just been created */ arch_dup_mmap(oldmm, mm); @@ -837,6 +839,8 @@ struct mm_struct *dup_mm(struct task_struct *tsk) #ifdef CONFIG_TRANSPARENT_HUGEPAGE mm->pmd_huge_pte = NULL; #endif + uprobe_reset_state(mm); + if (!mm_init(mm, tsk)) goto fail_nomem; @@ -1276,7 +1280,11 @@ static struct task_struct *copy_process(unsigned long clone_flags, #endif #ifdef CONFIG_TRACE_IRQFLAGS p->irq_events = 0; +#ifdef __ARCH_WANT_INTERRUPTS_ON_CTXSW + p->hardirqs_enabled = 1; +#else p->hardirqs_enabled = 0; +#endif p->hardirq_enable_ip = 0; p->hardirq_enable_event = 0; p->hardirq_disable_ip = _THIS_IP_; diff --git a/trunk/kernel/futex.c b/trunk/kernel/futex.c index 3717e7b306e0..e2b0fb9a0b3b 100644 --- a/trunk/kernel/futex.c +++ b/trunk/kernel/futex.c @@ -2231,11 +2231,11 @@ int handle_early_requeue_pi_wakeup(struct futex_hash_bucket *hb, * @uaddr2: the pi futex we will take prior to returning to user-space * * The caller will wait on uaddr and will be requeued by futex_requeue() to - * uaddr2 which must be PI aware and unique from uaddr. Normal wakeup will wake - * on uaddr2 and complete the acquisition of the rt_mutex prior to returning to - * userspace. This ensures the rt_mutex maintains an owner when it has waiters; - * without one, the pi logic would not know which task to boost/deboost, if - * there was a need to. + * uaddr2 which must be PI aware. Normal wakeup will wake on uaddr2 and + * complete the acquisition of the rt_mutex prior to returning to userspace. + * This ensures the rt_mutex maintains an owner when it has waiters; without + * one, the pi logic wouldn't know which task to boost/deboost, if there was a + * need to. * * We call schedule in futex_wait_queue_me() when we enqueue and return there * via the following: @@ -2272,9 +2272,6 @@ static int futex_wait_requeue_pi(u32 __user *uaddr, unsigned int flags, struct futex_q q = futex_q_init; int res, ret; - if (uaddr == uaddr2) - return -EINVAL; - if (!bitset) return -EINVAL; @@ -2346,7 +2343,7 @@ static int futex_wait_requeue_pi(u32 __user *uaddr, unsigned int flags, * signal. futex_unlock_pi() will not destroy the lock_ptr nor * the pi_state. */ - WARN_ON(!q.pi_state); + WARN_ON(!&q.pi_state); pi_mutex = &q.pi_state->pi_mutex; ret = rt_mutex_finish_proxy_lock(pi_mutex, to, &rt_waiter, 1); debug_rt_mutex_free_waiter(&rt_waiter); @@ -2373,7 +2370,7 @@ static int futex_wait_requeue_pi(u32 __user *uaddr, unsigned int flags, * fault, unlock the rt_mutex and return the fault to userspace. */ if (ret == -EFAULT) { - if (pi_mutex && rt_mutex_owner(pi_mutex) == current) + if (rt_mutex_owner(pi_mutex) == current) rt_mutex_unlock(pi_mutex); } else if (ret == -EINTR) { /* diff --git a/trunk/kernel/irq/chip.c b/trunk/kernel/irq/chip.c index 57d86d07221e..eebd6d5cfb44 100644 --- a/trunk/kernel/irq/chip.c +++ b/trunk/kernel/irq/chip.c @@ -671,7 +671,6 @@ irq_set_chip_and_handler_name(unsigned int irq, struct irq_chip *chip, irq_set_chip(irq, chip); __irq_set_handler(irq, handle, 0, name); } -EXPORT_SYMBOL_GPL(irq_set_chip_and_handler_name); void irq_modify_status(unsigned int irq, unsigned long clr, unsigned long set) { diff --git a/trunk/kernel/irq/dummychip.c b/trunk/kernel/irq/dummychip.c index 988dc58e8847..b5fcd96c7102 100644 --- a/trunk/kernel/irq/dummychip.c +++ b/trunk/kernel/irq/dummychip.c @@ -6,7 +6,6 @@ */ #include #include -#include #include "internals.h" @@ -58,4 +57,3 @@ struct irq_chip dummy_irq_chip = { .irq_mask = noop, .irq_unmask = noop, }; -EXPORT_SYMBOL_GPL(dummy_irq_chip); diff --git a/trunk/kernel/irq/manage.c b/trunk/kernel/irq/manage.c index 4c69326aa773..0a8e8f059627 100644 --- a/trunk/kernel/irq/manage.c +++ b/trunk/kernel/irq/manage.c @@ -943,18 +943,6 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new) goto out_thread; } - /* - * Drivers are often written to work w/o knowledge about the - * underlying irq chip implementation, so a request for a - * threaded irq without a primary hard irq context handler - * requires the ONESHOT flag to be set. Some irq chips like - * MSI based interrupts are per se one shot safe. Check the - * chip flags, so we can avoid the unmask dance at the end of - * the threaded handler for those. - */ - if (desc->irq_data.chip->flags & IRQCHIP_ONESHOT_SAFE) - new->flags &= ~IRQF_ONESHOT; - /* * The following block of code has to be executed atomically */ @@ -1029,8 +1017,7 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new) */ new->thread_mask = 1 << ffz(thread_mask); - } else if (new->handler == irq_default_primary_handler && - !(desc->irq_data.chip->flags & IRQCHIP_ONESHOT_SAFE)) { + } else if (new->handler == irq_default_primary_handler) { /* * The interrupt was requested with handler = NULL, so * we use the default primary handler for it. But it diff --git a/trunk/kernel/kprobes.c b/trunk/kernel/kprobes.c index 098f396aa409..c62b8546cc90 100644 --- a/trunk/kernel/kprobes.c +++ b/trunk/kernel/kprobes.c @@ -561,9 +561,9 @@ static __kprobes void kprobe_optimizer(struct work_struct *work) { LIST_HEAD(free_list); - mutex_lock(&kprobe_mutex); /* Lock modules while optimizing kprobes */ mutex_lock(&module_mutex); + mutex_lock(&kprobe_mutex); /* * Step 1: Unoptimize kprobes and collect cleaned (unused and disarmed) @@ -586,8 +586,8 @@ static __kprobes void kprobe_optimizer(struct work_struct *work) /* Step 4: Free cleaned kprobes after quiesence period */ do_free_cleaned_kprobes(&free_list); - mutex_unlock(&module_mutex); mutex_unlock(&kprobe_mutex); + mutex_unlock(&module_mutex); /* Step 5: Kick optimizer again if needed */ if (!list_empty(&optimizing_list) || !list_empty(&unoptimizing_list)) @@ -759,32 +759,20 @@ static __kprobes void try_to_optimize_kprobe(struct kprobe *p) struct kprobe *ap; struct optimized_kprobe *op; - /* Impossible to optimize ftrace-based kprobe */ - if (kprobe_ftrace(p)) - return; - - /* For preparing optimization, jump_label_text_reserved() is called */ - jump_label_lock(); - mutex_lock(&text_mutex); - ap = alloc_aggr_kprobe(p); if (!ap) - goto out; + return; op = container_of(ap, struct optimized_kprobe, kp); if (!arch_prepared_optinsn(&op->optinsn)) { /* If failed to setup optimizing, fallback to kprobe */ arch_remove_optimized_kprobe(op); kfree(op); - goto out; + return; } init_aggr_kprobe(ap, p); - optimize_kprobe(ap); /* This just kicks optimizer thread */ - -out: - mutex_unlock(&text_mutex); - jump_label_unlock(); + optimize_kprobe(ap); } #ifdef CONFIG_SYSCTL @@ -919,64 +907,9 @@ static __kprobes struct kprobe *alloc_aggr_kprobe(struct kprobe *p) } #endif /* CONFIG_OPTPROBES */ -#ifdef KPROBES_CAN_USE_FTRACE -static struct ftrace_ops kprobe_ftrace_ops __read_mostly = { - .func = kprobe_ftrace_handler, - .flags = FTRACE_OPS_FL_SAVE_REGS, -}; -static int kprobe_ftrace_enabled; - -/* Must ensure p->addr is really on ftrace */ -static int __kprobes prepare_kprobe(struct kprobe *p) -{ - if (!kprobe_ftrace(p)) - return arch_prepare_kprobe(p); - - return arch_prepare_kprobe_ftrace(p); -} - -/* Caller must lock kprobe_mutex */ -static void __kprobes arm_kprobe_ftrace(struct kprobe *p) -{ - int ret; - - ret = ftrace_set_filter_ip(&kprobe_ftrace_ops, - (unsigned long)p->addr, 0, 0); - WARN(ret < 0, "Failed to arm kprobe-ftrace at %p (%d)\n", p->addr, ret); - kprobe_ftrace_enabled++; - if (kprobe_ftrace_enabled == 1) { - ret = register_ftrace_function(&kprobe_ftrace_ops); - WARN(ret < 0, "Failed to init kprobe-ftrace (%d)\n", ret); - } -} - -/* Caller must lock kprobe_mutex */ -static void __kprobes disarm_kprobe_ftrace(struct kprobe *p) -{ - int ret; - - kprobe_ftrace_enabled--; - if (kprobe_ftrace_enabled == 0) { - ret = unregister_ftrace_function(&kprobe_ftrace_ops); - WARN(ret < 0, "Failed to init kprobe-ftrace (%d)\n", ret); - } - ret = ftrace_set_filter_ip(&kprobe_ftrace_ops, - (unsigned long)p->addr, 1, 0); - WARN(ret < 0, "Failed to disarm kprobe-ftrace at %p (%d)\n", p->addr, ret); -} -#else /* !KPROBES_CAN_USE_FTRACE */ -#define prepare_kprobe(p) arch_prepare_kprobe(p) -#define arm_kprobe_ftrace(p) do {} while (0) -#define disarm_kprobe_ftrace(p) do {} while (0) -#endif - /* Arm a kprobe with text_mutex */ static void __kprobes arm_kprobe(struct kprobe *kp) { - if (unlikely(kprobe_ftrace(kp))) { - arm_kprobe_ftrace(kp); - return; - } /* * Here, since __arm_kprobe() doesn't use stop_machine(), * this doesn't cause deadlock on text_mutex. So, we don't @@ -988,15 +921,11 @@ static void __kprobes arm_kprobe(struct kprobe *kp) } /* Disarm a kprobe with text_mutex */ -static void __kprobes disarm_kprobe(struct kprobe *kp, bool reopt) +static void __kprobes disarm_kprobe(struct kprobe *kp) { - if (unlikely(kprobe_ftrace(kp))) { - disarm_kprobe_ftrace(kp); - return; - } /* Ditto */ mutex_lock(&text_mutex); - __disarm_kprobe(kp, reopt); + __disarm_kprobe(kp, true); mutex_unlock(&text_mutex); } @@ -1215,6 +1144,12 @@ static int __kprobes add_new_kprobe(struct kprobe *ap, struct kprobe *p) if (p->post_handler && !ap->post_handler) ap->post_handler = aggr_post_handler; + if (kprobe_disabled(ap) && !kprobe_disabled(p)) { + ap->flags &= ~KPROBE_FLAG_DISABLED; + if (!kprobes_all_disarmed) + /* Arm the breakpoint again. */ + __arm_kprobe(ap); + } return 0; } @@ -1254,22 +1189,11 @@ static int __kprobes register_aggr_kprobe(struct kprobe *orig_p, int ret = 0; struct kprobe *ap = orig_p; - /* For preparing optimization, jump_label_text_reserved() is called */ - jump_label_lock(); - /* - * Get online CPUs to avoid text_mutex deadlock.with stop machine, - * which is invoked by unoptimize_kprobe() in add_new_kprobe() - */ - get_online_cpus(); - mutex_lock(&text_mutex); - if (!kprobe_aggrprobe(orig_p)) { /* If orig_p is not an aggr_kprobe, create new aggr_kprobe. */ ap = alloc_aggr_kprobe(orig_p); - if (!ap) { - ret = -ENOMEM; - goto out; - } + if (!ap) + return -ENOMEM; init_aggr_kprobe(ap, orig_p); } else if (kprobe_unused(ap)) /* This probe is going to die. Rescue it */ @@ -1289,7 +1213,7 @@ static int __kprobes register_aggr_kprobe(struct kprobe *orig_p, * free aggr_probe. It will be used next time, or * freed by unregister_kprobe. */ - goto out; + return ret; /* Prepare optimized instructions if possible. */ prepare_optimized_kprobe(ap); @@ -1304,20 +1228,7 @@ static int __kprobes register_aggr_kprobe(struct kprobe *orig_p, /* Copy ap's insn slot to p */ copy_kprobe(ap, p); - ret = add_new_kprobe(ap, p); - -out: - mutex_unlock(&text_mutex); - put_online_cpus(); - jump_label_unlock(); - - if (ret == 0 && kprobe_disabled(ap) && !kprobe_disabled(p)) { - ap->flags &= ~KPROBE_FLAG_DISABLED; - if (!kprobes_all_disarmed) - /* Arm the breakpoint again. */ - arm_kprobe(ap); - } - return ret; + return add_new_kprobe(ap, p); } static int __kprobes in_kprobes_functions(unsigned long addr) @@ -1402,96 +1313,71 @@ static inline int check_kprobe_rereg(struct kprobe *p) return ret; } -static __kprobes int check_kprobe_address_safe(struct kprobe *p, - struct module **probed_mod) +int __kprobes register_kprobe(struct kprobe *p) { int ret = 0; - unsigned long ftrace_addr; + struct kprobe *old_p; + struct module *probed_mod; + kprobe_opcode_t *addr; - /* - * If the address is located on a ftrace nop, set the - * breakpoint to the following instruction. - */ - ftrace_addr = ftrace_location((unsigned long)p->addr); - if (ftrace_addr) { -#ifdef KPROBES_CAN_USE_FTRACE - /* Given address is not on the instruction boundary */ - if ((unsigned long)p->addr != ftrace_addr) - return -EILSEQ; - p->flags |= KPROBE_FLAG_FTRACE; -#else /* !KPROBES_CAN_USE_FTRACE */ - return -EINVAL; -#endif - } + addr = kprobe_addr(p); + if (IS_ERR(addr)) + return PTR_ERR(addr); + p->addr = addr; + + ret = check_kprobe_rereg(p); + if (ret) + return ret; jump_label_lock(); preempt_disable(); - - /* Ensure it is not in reserved area nor out of text */ if (!kernel_text_address((unsigned long) p->addr) || in_kprobes_functions((unsigned long) p->addr) || + ftrace_text_reserved(p->addr, p->addr) || jump_label_text_reserved(p->addr, p->addr)) { ret = -EINVAL; - goto out; + goto cannot_probe; } - /* Check if are we probing a module */ - *probed_mod = __module_text_address((unsigned long) p->addr); - if (*probed_mod) { + /* User can pass only KPROBE_FLAG_DISABLED to register_kprobe */ + p->flags &= KPROBE_FLAG_DISABLED; + + /* + * Check if are we probing a module. + */ + probed_mod = __module_text_address((unsigned long) p->addr); + if (probed_mod) { + /* Return -ENOENT if fail. */ + ret = -ENOENT; /* * We must hold a refcount of the probed module while updating * its code to prohibit unexpected unloading. */ - if (unlikely(!try_module_get(*probed_mod))) { - ret = -ENOENT; - goto out; - } + if (unlikely(!try_module_get(probed_mod))) + goto cannot_probe; /* * If the module freed .init.text, we couldn't insert * kprobes in there. */ - if (within_module_init((unsigned long)p->addr, *probed_mod) && - (*probed_mod)->state != MODULE_STATE_COMING) { - module_put(*probed_mod); - *probed_mod = NULL; - ret = -ENOENT; + if (within_module_init((unsigned long)p->addr, probed_mod) && + probed_mod->state != MODULE_STATE_COMING) { + module_put(probed_mod); + goto cannot_probe; } + /* ret will be updated by following code */ } -out: preempt_enable(); jump_label_unlock(); - return ret; -} - -int __kprobes register_kprobe(struct kprobe *p) -{ - int ret; - struct kprobe *old_p; - struct module *probed_mod; - kprobe_opcode_t *addr; - - /* Adjust probe address from symbol */ - addr = kprobe_addr(p); - if (IS_ERR(addr)) - return PTR_ERR(addr); - p->addr = addr; - - ret = check_kprobe_rereg(p); - if (ret) - return ret; - - /* User can pass only KPROBE_FLAG_DISABLED to register_kprobe */ - p->flags &= KPROBE_FLAG_DISABLED; p->nmissed = 0; INIT_LIST_HEAD(&p->list); + mutex_lock(&kprobe_mutex); - ret = check_kprobe_address_safe(p, &probed_mod); - if (ret) - return ret; + jump_label_lock(); /* needed to call jump_label_text_reserved() */ - mutex_lock(&kprobe_mutex); + get_online_cpus(); /* For avoiding text_mutex deadlock. */ + mutex_lock(&text_mutex); old_p = get_kprobe(p->addr); if (old_p) { @@ -1500,9 +1386,7 @@ int __kprobes register_kprobe(struct kprobe *p) goto out; } - mutex_lock(&text_mutex); /* Avoiding text modification */ - ret = prepare_kprobe(p); - mutex_unlock(&text_mutex); + ret = arch_prepare_kprobe(p); if (ret) goto out; @@ -1511,18 +1395,26 @@ int __kprobes register_kprobe(struct kprobe *p) &kprobe_table[hash_ptr(p->addr, KPROBE_HASH_BITS)]); if (!kprobes_all_disarmed && !kprobe_disabled(p)) - arm_kprobe(p); + __arm_kprobe(p); /* Try to optimize kprobe */ try_to_optimize_kprobe(p); out: + mutex_unlock(&text_mutex); + put_online_cpus(); + jump_label_unlock(); mutex_unlock(&kprobe_mutex); if (probed_mod) module_put(probed_mod); return ret; + +cannot_probe: + preempt_enable(); + jump_label_unlock(); + return ret; } EXPORT_SYMBOL_GPL(register_kprobe); @@ -1559,7 +1451,7 @@ static struct kprobe *__kprobes __disable_kprobe(struct kprobe *p) /* Try to disarm and disable this/parent probe */ if (p == orig_p || aggr_kprobe_disabled(orig_p)) { - disarm_kprobe(orig_p, true); + disarm_kprobe(orig_p); orig_p->flags |= KPROBE_FLAG_DISABLED; } } @@ -2157,11 +2049,10 @@ static void __kprobes report_probe(struct seq_file *pi, struct kprobe *p, if (!pp) pp = p; - seq_printf(pi, "%s%s%s%s\n", + seq_printf(pi, "%s%s%s\n", (kprobe_gone(p) ? "[GONE]" : ""), ((kprobe_disabled(p) && !kprobe_gone(p)) ? "[DISABLED]" : ""), - (kprobe_optimized(pp) ? "[OPTIMIZED]" : ""), - (kprobe_ftrace(pp) ? "[FTRACE]" : "")); + (kprobe_optimized(pp) ? "[OPTIMIZED]" : "")); } static void __kprobes *kprobe_seq_start(struct seq_file *f, loff_t *pos) @@ -2240,12 +2131,14 @@ static void __kprobes arm_all_kprobes(void) goto already_enabled; /* Arming kprobes doesn't optimize kprobe itself */ + mutex_lock(&text_mutex); for (i = 0; i < KPROBE_TABLE_SIZE; i++) { head = &kprobe_table[i]; hlist_for_each_entry_rcu(p, node, head, hlist) if (!kprobe_disabled(p)) - arm_kprobe(p); + __arm_kprobe(p); } + mutex_unlock(&text_mutex); kprobes_all_disarmed = false; printk(KERN_INFO "Kprobes globally enabled\n"); @@ -2273,13 +2166,15 @@ static void __kprobes disarm_all_kprobes(void) kprobes_all_disarmed = true; printk(KERN_INFO "Kprobes globally disabled\n"); + mutex_lock(&text_mutex); for (i = 0; i < KPROBE_TABLE_SIZE; i++) { head = &kprobe_table[i]; hlist_for_each_entry_rcu(p, node, head, hlist) { if (!arch_trampoline_kprobe(p) && !kprobe_disabled(p)) - disarm_kprobe(p, false); + __disarm_kprobe(p, false); } } + mutex_unlock(&text_mutex); mutex_unlock(&kprobe_mutex); /* Wait for disarming all kprobes by optimizer */ diff --git a/trunk/kernel/kthread.c b/trunk/kernel/kthread.c index 146a6fa96825..b579af57ea10 100644 --- a/trunk/kernel/kthread.c +++ b/trunk/kernel/kthread.c @@ -37,20 +37,11 @@ struct kthread_create_info }; struct kthread { - unsigned long flags; - unsigned int cpu; + int should_stop; void *data; - struct completion parked; struct completion exited; }; -enum KTHREAD_BITS { - KTHREAD_IS_PER_CPU = 0, - KTHREAD_SHOULD_STOP, - KTHREAD_SHOULD_PARK, - KTHREAD_IS_PARKED, -}; - #define to_kthread(tsk) \ container_of((tsk)->vfork_done, struct kthread, exited) @@ -61,28 +52,12 @@ enum KTHREAD_BITS { * and this will return true. You should then return, and your return * value will be passed through to kthread_stop(). */ -bool kthread_should_stop(void) +int kthread_should_stop(void) { - return test_bit(KTHREAD_SHOULD_STOP, &to_kthread(current)->flags); + return to_kthread(current)->should_stop; } EXPORT_SYMBOL(kthread_should_stop); -/** - * kthread_should_park - should this kthread park now? - * - * When someone calls kthread_park() on your kthread, it will be woken - * and this will return true. You should then do the necessary - * cleanup and call kthread_parkme() - * - * Similar to kthread_should_stop(), but this keeps the thread alive - * and in a park position. kthread_unpark() "restarts" the thread and - * calls the thread function again. - */ -bool kthread_should_park(void) -{ - return test_bit(KTHREAD_SHOULD_PARK, &to_kthread(current)->flags); -} - /** * kthread_freezable_should_stop - should this freezable kthread return now? * @was_frozen: optional out parameter, indicates whether %current was frozen @@ -121,24 +96,6 @@ void *kthread_data(struct task_struct *task) return to_kthread(task)->data; } -static void __kthread_parkme(struct kthread *self) -{ - __set_current_state(TASK_INTERRUPTIBLE); - while (test_bit(KTHREAD_SHOULD_PARK, &self->flags)) { - if (!test_and_set_bit(KTHREAD_IS_PARKED, &self->flags)) - complete(&self->parked); - schedule(); - __set_current_state(TASK_INTERRUPTIBLE); - } - clear_bit(KTHREAD_IS_PARKED, &self->flags); - __set_current_state(TASK_RUNNING); -} - -void kthread_parkme(void) -{ - __kthread_parkme(to_kthread(current)); -} - static int kthread(void *_create) { /* Copy data: it's on kthread's stack */ @@ -148,10 +105,9 @@ static int kthread(void *_create) struct kthread self; int ret; - self.flags = 0; + self.should_stop = 0; self.data = data; init_completion(&self.exited); - init_completion(&self.parked); current->vfork_done = &self.exited; /* OK, tell user we're spawned, wait for stop or wakeup */ @@ -161,11 +117,9 @@ static int kthread(void *_create) schedule(); ret = -EINTR; - - if (!test_bit(KTHREAD_SHOULD_STOP, &self.flags)) { - __kthread_parkme(&self); + if (!self.should_stop) ret = threadfn(data); - } + /* we can't just return, we must preserve "self" on stack */ do_exit(ret); } @@ -218,7 +172,8 @@ static void create_kthread(struct kthread_create_info *create) * Returns a task_struct or ERR_PTR(-ENOMEM). */ struct task_struct *kthread_create_on_node(int (*threadfn)(void *data), - void *data, int node, + void *data, + int node, const char namefmt[], ...) { @@ -255,13 +210,6 @@ struct task_struct *kthread_create_on_node(int (*threadfn)(void *data), } EXPORT_SYMBOL(kthread_create_on_node); -static void __kthread_bind(struct task_struct *p, unsigned int cpu) -{ - /* It's safe because the task is inactive. */ - do_set_cpus_allowed(p, cpumask_of(cpu)); - p->flags |= PF_THREAD_BOUND; -} - /** * kthread_bind - bind a just-created kthread to a cpu. * @p: thread created by kthread_create(). @@ -278,110 +226,12 @@ void kthread_bind(struct task_struct *p, unsigned int cpu) WARN_ON(1); return; } - __kthread_bind(p, cpu); -} -EXPORT_SYMBOL(kthread_bind); -/** - * kthread_create_on_cpu - Create a cpu bound kthread - * @threadfn: the function to run until signal_pending(current). - * @data: data ptr for @threadfn. - * @cpu: The cpu on which the thread should be bound, - * @namefmt: printf-style name for the thread. Format is restricted - * to "name.*%u". Code fills in cpu number. - * - * Description: This helper function creates and names a kernel thread - * The thread will be woken and put into park mode. - */ -struct task_struct *kthread_create_on_cpu(int (*threadfn)(void *data), - void *data, unsigned int cpu, - const char *namefmt) -{ - struct task_struct *p; - - p = kthread_create_on_node(threadfn, data, cpu_to_node(cpu), namefmt, - cpu); - if (IS_ERR(p)) - return p; - set_bit(KTHREAD_IS_PER_CPU, &to_kthread(p)->flags); - to_kthread(p)->cpu = cpu; - /* Park the thread to get it out of TASK_UNINTERRUPTIBLE state */ - kthread_park(p); - return p; -} - -static struct kthread *task_get_live_kthread(struct task_struct *k) -{ - struct kthread *kthread; - - get_task_struct(k); - kthread = to_kthread(k); - /* It might have exited */ - barrier(); - if (k->vfork_done != NULL) - return kthread; - return NULL; -} - -/** - * kthread_unpark - unpark a thread created by kthread_create(). - * @k: thread created by kthread_create(). - * - * Sets kthread_should_park() for @k to return false, wakes it, and - * waits for it to return. If the thread is marked percpu then its - * bound to the cpu again. - */ -void kthread_unpark(struct task_struct *k) -{ - struct kthread *kthread = task_get_live_kthread(k); - - if (kthread) { - clear_bit(KTHREAD_SHOULD_PARK, &kthread->flags); - /* - * We clear the IS_PARKED bit here as we don't wait - * until the task has left the park code. So if we'd - * park before that happens we'd see the IS_PARKED bit - * which might be about to be cleared. - */ - if (test_and_clear_bit(KTHREAD_IS_PARKED, &kthread->flags)) { - if (test_bit(KTHREAD_IS_PER_CPU, &kthread->flags)) - __kthread_bind(k, kthread->cpu); - wake_up_process(k); - } - } - put_task_struct(k); -} - -/** - * kthread_park - park a thread created by kthread_create(). - * @k: thread created by kthread_create(). - * - * Sets kthread_should_park() for @k to return true, wakes it, and - * waits for it to return. This can also be called after kthread_create() - * instead of calling wake_up_process(): the thread will park without - * calling threadfn(). - * - * Returns 0 if the thread is parked, -ENOSYS if the thread exited. - * If called by the kthread itself just the park bit is set. - */ -int kthread_park(struct task_struct *k) -{ - struct kthread *kthread = task_get_live_kthread(k); - int ret = -ENOSYS; - - if (kthread) { - if (!test_bit(KTHREAD_IS_PARKED, &kthread->flags)) { - set_bit(KTHREAD_SHOULD_PARK, &kthread->flags); - if (k != current) { - wake_up_process(k); - wait_for_completion(&kthread->parked); - } - } - ret = 0; - } - put_task_struct(k); - return ret; + /* It's safe because the task is inactive. */ + do_set_cpus_allowed(p, cpumask_of(cpu)); + p->flags |= PF_THREAD_BOUND; } +EXPORT_SYMBOL(kthread_bind); /** * kthread_stop - stop a thread created by kthread_create(). @@ -400,13 +250,16 @@ int kthread_park(struct task_struct *k) */ int kthread_stop(struct task_struct *k) { - struct kthread *kthread = task_get_live_kthread(k); + struct kthread *kthread; int ret; trace_sched_kthread_stop(k); - if (kthread) { - set_bit(KTHREAD_SHOULD_STOP, &kthread->flags); - clear_bit(KTHREAD_SHOULD_PARK, &kthread->flags); + get_task_struct(k); + + kthread = to_kthread(k); + barrier(); /* it might have exited */ + if (k->vfork_done != NULL) { + kthread->should_stop = 1; wake_up_process(k); wait_for_completion(&kthread->exited); } diff --git a/trunk/kernel/lockdep.c b/trunk/kernel/lockdep.c index 7981e5b2350d..ea9ee4518c35 100644 --- a/trunk/kernel/lockdep.c +++ b/trunk/kernel/lockdep.c @@ -2998,42 +2998,6 @@ EXPORT_SYMBOL_GPL(lockdep_init_map); struct lock_class_key __lockdep_no_validate__; -static int -print_lock_nested_lock_not_held(struct task_struct *curr, - struct held_lock *hlock, - unsigned long ip) -{ - if (!debug_locks_off()) - return 0; - if (debug_locks_silent) - return 0; - - printk("\n"); - printk("==================================\n"); - printk("[ BUG: Nested lock was not taken ]\n"); - print_kernel_ident(); - printk("----------------------------------\n"); - - printk("%s/%d is trying to lock:\n", curr->comm, task_pid_nr(curr)); - print_lock(hlock); - - printk("\nbut this task is not holding:\n"); - printk("%s\n", hlock->nest_lock->name); - - printk("\nstack backtrace:\n"); - dump_stack(); - - printk("\nother info that might help us debug this:\n"); - lockdep_print_held_locks(curr); - - printk("\nstack backtrace:\n"); - dump_stack(); - - return 0; -} - -static int __lock_is_held(struct lockdep_map *lock); - /* * This gets called for every mutex_lock*()/spin_lock*() operation. * We maintain the dependency maps and validate the locking attempt: @@ -3175,9 +3139,6 @@ static int __lock_acquire(struct lockdep_map *lock, unsigned int subclass, } chain_key = iterate_chain_key(chain_key, id); - if (nest_lock && !__lock_is_held(nest_lock)) - return print_lock_nested_lock_not_held(curr, hlock, ip); - if (!validate_chain(curr, lock, hlock, chain_head, chain_key)) return 0; diff --git a/trunk/kernel/pid_namespace.c b/trunk/kernel/pid_namespace.c index 6144bab8fd8e..b3c7fd554250 100644 --- a/trunk/kernel/pid_namespace.c +++ b/trunk/kernel/pid_namespace.c @@ -232,19 +232,15 @@ static int pid_ns_ctl_handler(struct ctl_table *table, int write, */ tmp.data = ¤t->nsproxy->pid_ns->last_pid; - return proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos); + return proc_dointvec(&tmp, write, buffer, lenp, ppos); } -extern int pid_max; -static int zero = 0; static struct ctl_table pid_ns_ctl_table[] = { { .procname = "ns_last_pid", .maxlen = sizeof(int), .mode = 0666, /* permissions are checked in the handler */ .proc_handler = pid_ns_ctl_handler, - .extra1 = &zero, - .extra2 = &pid_max, }, { } }; diff --git a/trunk/kernel/power/suspend.c b/trunk/kernel/power/suspend.c index c8b7446b27df..1da39ea248fd 100644 --- a/trunk/kernel/power/suspend.c +++ b/trunk/kernel/power/suspend.c @@ -178,6 +178,9 @@ static int suspend_enter(suspend_state_t state, bool *wakeup) arch_suspend_enable_irqs(); BUG_ON(irqs_disabled()); + /* Kick the lockup detector */ + lockup_detector_bootcpu_resume(); + Enable_cpus: enable_nonboot_cpus(); diff --git a/trunk/kernel/printk.c b/trunk/kernel/printk.c index 66a2ea37b576..6a76ab9d4476 100644 --- a/trunk/kernel/printk.c +++ b/trunk/kernel/printk.c @@ -1034,7 +1034,6 @@ static int syslog_print_all(char __user *buf, int size, bool clear) struct log *msg = log_from_idx(idx); len += msg_print_text(msg, prev, true, NULL, 0); - prev = msg->flags; idx = log_next(idx); seq++; } @@ -1047,7 +1046,6 @@ static int syslog_print_all(char __user *buf, int size, bool clear) struct log *msg = log_from_idx(idx); len -= msg_print_text(msg, prev, true, NULL, 0); - prev = msg->flags; idx = log_next(idx); seq++; } diff --git a/trunk/kernel/rcupdate.c b/trunk/kernel/rcupdate.c index 29ca1c6da594..4e6a61b15e86 100644 --- a/trunk/kernel/rcupdate.c +++ b/trunk/kernel/rcupdate.c @@ -45,7 +45,6 @@ #include #include #include -#include #define CREATE_TRACE_POINTS #include @@ -82,9 +81,6 @@ void __rcu_read_unlock(void) } else { barrier(); /* critical section before exit code. */ t->rcu_read_lock_nesting = INT_MIN; -#ifdef CONFIG_PROVE_RCU_DELAY - udelay(10); /* Make preemption more probable. */ -#endif /* #ifdef CONFIG_PROVE_RCU_DELAY */ barrier(); /* assign before ->rcu_read_unlock_special load */ if (unlikely(ACCESS_ONCE(t->rcu_read_unlock_special))) rcu_read_unlock_special(t); diff --git a/trunk/kernel/rcutiny.c b/trunk/kernel/rcutiny.c index e4c6a598d6f7..547b1fe5b052 100644 --- a/trunk/kernel/rcutiny.c +++ b/trunk/kernel/rcutiny.c @@ -56,28 +56,25 @@ static void __call_rcu(struct rcu_head *head, static long long rcu_dynticks_nesting = DYNTICK_TASK_EXIT_IDLE; /* Common code for rcu_idle_enter() and rcu_irq_exit(), see kernel/rcutree.c. */ -static void rcu_idle_enter_common(long long newval) +static void rcu_idle_enter_common(long long oldval) { - if (newval) { + if (rcu_dynticks_nesting) { RCU_TRACE(trace_rcu_dyntick("--=", - rcu_dynticks_nesting, newval)); - rcu_dynticks_nesting = newval; + oldval, rcu_dynticks_nesting)); return; } - RCU_TRACE(trace_rcu_dyntick("Start", rcu_dynticks_nesting, newval)); + RCU_TRACE(trace_rcu_dyntick("Start", oldval, rcu_dynticks_nesting)); if (!is_idle_task(current)) { struct task_struct *idle = idle_task(smp_processor_id()); RCU_TRACE(trace_rcu_dyntick("Error on entry: not idle task", - rcu_dynticks_nesting, newval)); + oldval, rcu_dynticks_nesting)); ftrace_dump(DUMP_ALL); WARN_ONCE(1, "Current pid: %d comm: %s / Idle pid: %d comm: %s", current->pid, current->comm, idle->pid, idle->comm); /* must be idle task! */ } rcu_sched_qs(0); /* implies rcu_bh_qsctr_inc(0) */ - barrier(); - rcu_dynticks_nesting = newval; } /* @@ -87,16 +84,17 @@ static void rcu_idle_enter_common(long long newval) void rcu_idle_enter(void) { unsigned long flags; - long long newval; + long long oldval; local_irq_save(flags); + oldval = rcu_dynticks_nesting; WARN_ON_ONCE((rcu_dynticks_nesting & DYNTICK_TASK_NEST_MASK) == 0); if ((rcu_dynticks_nesting & DYNTICK_TASK_NEST_MASK) == DYNTICK_TASK_NEST_VALUE) - newval = 0; + rcu_dynticks_nesting = 0; else - newval = rcu_dynticks_nesting - DYNTICK_TASK_NEST_VALUE; - rcu_idle_enter_common(newval); + rcu_dynticks_nesting -= DYNTICK_TASK_NEST_VALUE; + rcu_idle_enter_common(oldval); local_irq_restore(flags); } EXPORT_SYMBOL_GPL(rcu_idle_enter); @@ -107,15 +105,15 @@ EXPORT_SYMBOL_GPL(rcu_idle_enter); void rcu_irq_exit(void) { unsigned long flags; - long long newval; + long long oldval; local_irq_save(flags); - newval = rcu_dynticks_nesting - 1; - WARN_ON_ONCE(newval < 0); - rcu_idle_enter_common(newval); + oldval = rcu_dynticks_nesting; + rcu_dynticks_nesting--; + WARN_ON_ONCE(rcu_dynticks_nesting < 0); + rcu_idle_enter_common(oldval); local_irq_restore(flags); } -EXPORT_SYMBOL_GPL(rcu_irq_exit); /* Common code for rcu_idle_exit() and rcu_irq_enter(), see kernel/rcutree.c. */ static void rcu_idle_exit_common(long long oldval) @@ -173,7 +171,6 @@ void rcu_irq_enter(void) rcu_idle_exit_common(oldval); local_irq_restore(flags); } -EXPORT_SYMBOL_GPL(rcu_irq_enter); #ifdef CONFIG_DEBUG_LOCK_ALLOC diff --git a/trunk/kernel/rcutiny_plugin.h b/trunk/kernel/rcutiny_plugin.h index 3d0190282204..918fd1e8509c 100644 --- a/trunk/kernel/rcutiny_plugin.h +++ b/trunk/kernel/rcutiny_plugin.h @@ -278,7 +278,7 @@ static int rcu_boost(void) rcu_preempt_ctrlblk.exp_tasks == NULL) return 0; /* Nothing to boost. */ - local_irq_save(flags); + raw_local_irq_save(flags); /* * Recheck with irqs disabled: all tasks in need of boosting @@ -287,7 +287,7 @@ static int rcu_boost(void) */ if (rcu_preempt_ctrlblk.boost_tasks == NULL && rcu_preempt_ctrlblk.exp_tasks == NULL) { - local_irq_restore(flags); + raw_local_irq_restore(flags); return 0; } @@ -317,7 +317,7 @@ static int rcu_boost(void) t = container_of(tb, struct task_struct, rcu_node_entry); rt_mutex_init_proxy_locked(&mtx, t); t->rcu_boost_mutex = &mtx; - local_irq_restore(flags); + raw_local_irq_restore(flags); rt_mutex_lock(&mtx); rt_mutex_unlock(&mtx); /* Keep lockdep happy. */ @@ -991,9 +991,9 @@ static void rcu_trace_sub_qlen(struct rcu_ctrlblk *rcp, int n) { unsigned long flags; - local_irq_save(flags); + raw_local_irq_save(flags); rcp->qlen -= n; - local_irq_restore(flags); + raw_local_irq_restore(flags); } /* diff --git a/trunk/kernel/rcutorture.c b/trunk/kernel/rcutorture.c index aaa7b9f3532a..25b15033c61f 100644 --- a/trunk/kernel/rcutorture.c +++ b/trunk/kernel/rcutorture.c @@ -53,11 +53,10 @@ MODULE_AUTHOR("Paul E. McKenney and Josh Triplett can_boost, - test_boost_interval, test_boost_duration, shutdown_secs, - onoff_interval, onoff_holdoff); + printk(KERN_ALERT "%s" TORTURE_FLAG + "--- %s: nreaders=%d nfakewriters=%d " + "stat_interval=%d verbose=%d test_no_idle_hz=%d " + "shuffle_interval=%d stutter=%d irqreader=%d " + "fqs_duration=%d fqs_holdoff=%d fqs_stutter=%d " + "test_boost=%d/%d test_boost_interval=%d " + "test_boost_duration=%d shutdown_secs=%d " + "onoff_interval=%d onoff_holdoff=%d\n", + torture_type, tag, nrealreaders, nfakewriters, + stat_interval, verbose, test_no_idle_hz, shuffle_interval, + stutter, irqreader, fqs_duration, fqs_holdoff, fqs_stutter, + test_boost, cur_ops->can_boost, + test_boost_interval, test_boost_duration, shutdown_secs, + onoff_interval, onoff_holdoff); } static struct notifier_block rcutorture_shutdown_nb = { @@ -1469,9 +1460,9 @@ rcu_torture_shutdown(void *arg) !kthread_should_stop()) { delta = shutdown_time - jiffies_snap; if (verbose) - pr_alert("%s" TORTURE_FLAG - "rcu_torture_shutdown task: %lu jiffies remaining\n", - torture_type, delta); + printk(KERN_ALERT "%s" TORTURE_FLAG + "rcu_torture_shutdown task: %lu jiffies remaining\n", + torture_type, delta); schedule_timeout_interruptible(delta); jiffies_snap = ACCESS_ONCE(jiffies); } @@ -1499,10 +1490,8 @@ static int __cpuinit rcu_torture_onoff(void *arg) { int cpu; - unsigned long delta; int maxcpu = -1; DEFINE_RCU_RANDOM(rand); - unsigned long starttime; VERBOSE_PRINTK_STRING("rcu_torture_onoff task started"); for_each_online_cpu(cpu) @@ -1517,51 +1506,29 @@ rcu_torture_onoff(void *arg) cpu = (rcu_random(&rand) >> 4) % (maxcpu + 1); if (cpu_online(cpu) && cpu_is_hotpluggable(cpu)) { if (verbose) - pr_alert("%s" TORTURE_FLAG - "rcu_torture_onoff task: offlining %d\n", - torture_type, cpu); - starttime = jiffies; + printk(KERN_ALERT "%s" TORTURE_FLAG + "rcu_torture_onoff task: offlining %d\n", + torture_type, cpu); n_offline_attempts++; if (cpu_down(cpu) == 0) { if (verbose) - pr_alert("%s" TORTURE_FLAG - "rcu_torture_onoff task: offlined %d\n", - torture_type, cpu); + printk(KERN_ALERT "%s" TORTURE_FLAG + "rcu_torture_onoff task: offlined %d\n", + torture_type, cpu); n_offline_successes++; - delta = jiffies - starttime; - sum_offline += delta; - if (min_offline < 0) { - min_offline = delta; - max_offline = delta; - } - if (min_offline > delta) - min_offline = delta; - if (max_offline < delta) - max_offline = delta; } } else if (cpu_is_hotpluggable(cpu)) { if (verbose) - pr_alert("%s" TORTURE_FLAG - "rcu_torture_onoff task: onlining %d\n", - torture_type, cpu); - starttime = jiffies; + printk(KERN_ALERT "%s" TORTURE_FLAG + "rcu_torture_onoff task: onlining %d\n", + torture_type, cpu); n_online_attempts++; if (cpu_up(cpu) == 0) { if (verbose) - pr_alert("%s" TORTURE_FLAG - "rcu_torture_onoff task: onlined %d\n", - torture_type, cpu); + printk(KERN_ALERT "%s" TORTURE_FLAG + "rcu_torture_onoff task: onlined %d\n", + torture_type, cpu); n_online_successes++; - delta = jiffies - starttime; - sum_online += delta; - if (min_online < 0) { - min_online = delta; - max_online = delta; - } - if (min_online > delta) - min_online = delta; - if (max_online < delta) - max_online = delta; } } schedule_timeout_interruptible(onoff_interval * HZ); @@ -1626,14 +1593,14 @@ static int __cpuinit rcu_torture_stall(void *args) if (!kthread_should_stop()) { stop_at = get_seconds() + stall_cpu; /* RCU CPU stall is expected behavior in following code. */ - pr_alert("rcu_torture_stall start.\n"); + printk(KERN_ALERT "rcu_torture_stall start.\n"); rcu_read_lock(); preempt_disable(); while (ULONG_CMP_LT(get_seconds(), stop_at)) continue; /* Induce RCU CPU stall warning. */ preempt_enable(); rcu_read_unlock(); - pr_alert("rcu_torture_stall end.\n"); + printk(KERN_ALERT "rcu_torture_stall end.\n"); } rcutorture_shutdown_absorb("rcu_torture_stall"); while (!kthread_should_stop()) @@ -1749,12 +1716,12 @@ static int rcu_torture_barrier_init(void) if (n_barrier_cbs == 0) return 0; if (cur_ops->call == NULL || cur_ops->cb_barrier == NULL) { - pr_alert("%s" TORTURE_FLAG - " Call or barrier ops missing for %s,\n", - torture_type, cur_ops->name); - pr_alert("%s" TORTURE_FLAG - " RCU barrier testing omitted from run.\n", - torture_type); + printk(KERN_ALERT "%s" TORTURE_FLAG + " Call or barrier ops missing for %s,\n", + torture_type, cur_ops->name); + printk(KERN_ALERT "%s" TORTURE_FLAG + " RCU barrier testing omitted from run.\n", + torture_type); return 0; } atomic_set(&barrier_cbs_count, 0); @@ -1847,7 +1814,7 @@ rcu_torture_cleanup(void) mutex_lock(&fullstop_mutex); rcutorture_record_test_transition(); if (fullstop == FULLSTOP_SHUTDOWN) { - pr_warn(/* but going down anyway, so... */ + printk(KERN_WARNING /* but going down anyway, so... */ "Concurrent 'rmmod rcutorture' and shutdown illegal!\n"); mutex_unlock(&fullstop_mutex); schedule_timeout_uninterruptible(10); @@ -1971,17 +1938,17 @@ rcu_torture_init(void) break; } if (i == ARRAY_SIZE(torture_ops)) { - pr_alert("rcu-torture: invalid torture type: \"%s\"\n", - torture_type); - pr_alert("rcu-torture types:"); + printk(KERN_ALERT "rcu-torture: invalid torture type: \"%s\"\n", + torture_type); + printk(KERN_ALERT "rcu-torture types:"); for (i = 0; i < ARRAY_SIZE(torture_ops); i++) - pr_alert(" %s", torture_ops[i]->name); - pr_alert("\n"); + printk(KERN_ALERT " %s", torture_ops[i]->name); + printk(KERN_ALERT "\n"); mutex_unlock(&fullstop_mutex); return -EINVAL; } if (cur_ops->fqs == NULL && fqs_duration != 0) { - pr_alert("rcu-torture: ->fqs NULL and non-zero fqs_duration, fqs disabled.\n"); + printk(KERN_ALERT "rcu-torture: ->fqs NULL and non-zero fqs_duration, fqs disabled.\n"); fqs_duration = 0; } if (cur_ops->init) @@ -2029,15 +1996,14 @@ rcu_torture_init(void) /* Start up the kthreads. */ VERBOSE_PRINTK_STRING("Creating rcu_torture_writer task"); - writer_task = kthread_create(rcu_torture_writer, NULL, - "rcu_torture_writer"); + writer_task = kthread_run(rcu_torture_writer, NULL, + "rcu_torture_writer"); if (IS_ERR(writer_task)) { firsterr = PTR_ERR(writer_task); VERBOSE_PRINTK_ERRSTRING("Failed to create writer"); writer_task = NULL; goto unwind; } - wake_up_process(writer_task); fakewriter_tasks = kzalloc(nfakewriters * sizeof(fakewriter_tasks[0]), GFP_KERNEL); if (fakewriter_tasks == NULL) { @@ -2152,15 +2118,14 @@ rcu_torture_init(void) } if (shutdown_secs > 0) { shutdown_time = jiffies + shutdown_secs * HZ; - shutdown_task = kthread_create(rcu_torture_shutdown, NULL, - "rcu_torture_shutdown"); + shutdown_task = kthread_run(rcu_torture_shutdown, NULL, + "rcu_torture_shutdown"); if (IS_ERR(shutdown_task)) { firsterr = PTR_ERR(shutdown_task); VERBOSE_PRINTK_ERRSTRING("Failed to create shutdown"); shutdown_task = NULL; goto unwind; } - wake_up_process(shutdown_task); } i = rcu_torture_onoff_init(); if (i != 0) { diff --git a/trunk/kernel/rcutree.c b/trunk/kernel/rcutree.c index 4fb2376ddf06..f280e542e3e9 100644 --- a/trunk/kernel/rcutree.c +++ b/trunk/kernel/rcutree.c @@ -52,7 +52,6 @@ #include #include #include -#include #include "rcutree.h" #include @@ -62,7 +61,6 @@ /* Data structures. */ static struct lock_class_key rcu_node_class[RCU_NUM_LVLS]; -static struct lock_class_key rcu_fqs_class[RCU_NUM_LVLS]; #define RCU_STATE_INITIALIZER(sname, cr) { \ .level = { &sname##_state.node[0] }, \ @@ -74,6 +72,7 @@ static struct lock_class_key rcu_fqs_class[RCU_NUM_LVLS]; .orphan_nxttail = &sname##_state.orphan_nxtlist, \ .orphan_donetail = &sname##_state.orphan_donelist, \ .barrier_mutex = __MUTEX_INITIALIZER(sname##_state.barrier_mutex), \ + .fqslock = __RAW_SPIN_LOCK_UNLOCKED(&sname##_state.fqslock), \ .name = #sname, \ } @@ -89,7 +88,7 @@ LIST_HEAD(rcu_struct_flavors); /* Increase (but not decrease) the CONFIG_RCU_FANOUT_LEAF at boot time. */ static int rcu_fanout_leaf = CONFIG_RCU_FANOUT_LEAF; -module_param(rcu_fanout_leaf, int, 0444); +module_param(rcu_fanout_leaf, int, 0); int rcu_num_lvls __read_mostly = RCU_NUM_LVLS; static int num_rcu_lvl[] = { /* Number of rcu_nodes at specified level. */ NUM_RCU_LVL_0, @@ -134,12 +133,13 @@ static int rcu_scheduler_fully_active __read_mostly; */ static DEFINE_PER_CPU(struct task_struct *, rcu_cpu_kthread_task); DEFINE_PER_CPU(unsigned int, rcu_cpu_kthread_status); +DEFINE_PER_CPU(int, rcu_cpu_kthread_cpu); DEFINE_PER_CPU(unsigned int, rcu_cpu_kthread_loops); DEFINE_PER_CPU(char, rcu_cpu_has_work); #endif /* #ifdef CONFIG_RCU_BOOST */ -static void rcu_boost_kthread_setaffinity(struct rcu_node *rnp, int outgoingcpu); +static void rcu_node_kthread_setaffinity(struct rcu_node *rnp, int outgoingcpu); static void invoke_rcu_core(void); static void invoke_rcu_callbacks(struct rcu_state *rsp, struct rcu_data *rdp); @@ -175,6 +175,8 @@ void rcu_sched_qs(int cpu) { struct rcu_data *rdp = &per_cpu(rcu_sched_data, cpu); + rdp->passed_quiesce_gpnum = rdp->gpnum; + barrier(); if (rdp->passed_quiesce == 0) trace_rcu_grace_period("rcu_sched", rdp->gpnum, "cpuqs"); rdp->passed_quiesce = 1; @@ -184,6 +186,8 @@ void rcu_bh_qs(int cpu) { struct rcu_data *rdp = &per_cpu(rcu_bh_data, cpu); + rdp->passed_quiesce_gpnum = rdp->gpnum; + barrier(); if (rdp->passed_quiesce == 0) trace_rcu_grace_period("rcu_bh", rdp->gpnum, "cpuqs"); rdp->passed_quiesce = 1; @@ -206,18 +210,15 @@ EXPORT_SYMBOL_GPL(rcu_note_context_switch); DEFINE_PER_CPU(struct rcu_dynticks, rcu_dynticks) = { .dynticks_nesting = DYNTICK_TASK_EXIT_IDLE, .dynticks = ATOMIC_INIT(1), -#if defined(CONFIG_RCU_USER_QS) && !defined(CONFIG_RCU_USER_QS_FORCE) - .ignore_user_qs = true, -#endif }; static int blimit = 10; /* Maximum callbacks per rcu_do_batch. */ static int qhimark = 10000; /* If this many pending, ignore blimit. */ static int qlowmark = 100; /* Once only this many pending, use blimit. */ -module_param(blimit, int, 0444); -module_param(qhimark, int, 0444); -module_param(qlowmark, int, 0444); +module_param(blimit, int, 0); +module_param(qhimark, int, 0); +module_param(qlowmark, int, 0); int rcu_cpu_stall_suppress __read_mostly; /* 1 = suppress stall warnings. */ int rcu_cpu_stall_timeout __read_mostly = CONFIG_RCU_CPU_STALL_TIMEOUT; @@ -225,14 +226,7 @@ int rcu_cpu_stall_timeout __read_mostly = CONFIG_RCU_CPU_STALL_TIMEOUT; module_param(rcu_cpu_stall_suppress, int, 0644); module_param(rcu_cpu_stall_timeout, int, 0644); -static ulong jiffies_till_first_fqs = RCU_JIFFIES_TILL_FORCE_QS; -static ulong jiffies_till_next_fqs = RCU_JIFFIES_TILL_FORCE_QS; - -module_param(jiffies_till_first_fqs, ulong, 0644); -module_param(jiffies_till_next_fqs, ulong, 0644); - -static void force_qs_rnp(struct rcu_state *rsp, int (*f)(struct rcu_data *)); -static void force_quiescent_state(struct rcu_state *rsp); +static void force_quiescent_state(struct rcu_state *rsp, int relaxed); static int rcu_pending(int cpu); /* @@ -258,7 +252,7 @@ EXPORT_SYMBOL_GPL(rcu_batches_completed_bh); */ void rcu_bh_force_quiescent_state(void) { - force_quiescent_state(&rcu_bh_state); + force_quiescent_state(&rcu_bh_state, 0); } EXPORT_SYMBOL_GPL(rcu_bh_force_quiescent_state); @@ -292,7 +286,7 @@ EXPORT_SYMBOL_GPL(rcutorture_record_progress); */ void rcu_sched_force_quiescent_state(void) { - force_quiescent_state(&rcu_sched_state); + force_quiescent_state(&rcu_sched_state, 0); } EXPORT_SYMBOL_GPL(rcu_sched_force_quiescent_state); @@ -311,9 +305,7 @@ cpu_has_callbacks_ready_to_invoke(struct rcu_data *rdp) static int cpu_needs_another_gp(struct rcu_state *rsp, struct rcu_data *rdp) { - return *rdp->nxttail[RCU_DONE_TAIL + - ACCESS_ONCE(rsp->completed) != rdp->completed] && - !rcu_gp_in_progress(rsp); + return *rdp->nxttail[RCU_DONE_TAIL] && !rcu_gp_in_progress(rsp); } /* @@ -325,17 +317,45 @@ static struct rcu_node *rcu_get_root(struct rcu_state *rsp) } /* - * rcu_eqs_enter_common - current CPU is moving towards extended quiescent state + * If the specified CPU is offline, tell the caller that it is in + * a quiescent state. Otherwise, whack it with a reschedule IPI. + * Grace periods can end up waiting on an offline CPU when that + * CPU is in the process of coming online -- it will be added to the + * rcu_node bitmasks before it actually makes it online. The same thing + * can happen while a CPU is in the process of coming online. Because this + * race is quite rare, we check for it after detecting that the grace + * period has been delayed rather than checking each and every CPU + * each and every time we start a new grace period. + */ +static int rcu_implicit_offline_qs(struct rcu_data *rdp) +{ + /* + * If the CPU is offline for more than a jiffy, it is in a quiescent + * state. We can trust its state not to change because interrupts + * are disabled. The reason for the jiffy's worth of slack is to + * handle CPUs initializing on the way up and finding their way + * to the idle loop on the way down. + */ + if (cpu_is_offline(rdp->cpu) && + ULONG_CMP_LT(rdp->rsp->gp_start + 2, jiffies)) { + trace_rcu_fqs(rdp->rsp->name, rdp->gpnum, rdp->cpu, "ofl"); + rdp->offline_fqs++; + return 1; + } + return 0; +} + +/* + * rcu_idle_enter_common - inform RCU that current CPU is moving towards idle * * If the new value of the ->dynticks_nesting counter now is zero, * we really have entered idle, and must do the appropriate accounting. * The caller must have disabled interrupts. */ -static void rcu_eqs_enter_common(struct rcu_dynticks *rdtp, long long oldval, - bool user) +static void rcu_idle_enter_common(struct rcu_dynticks *rdtp, long long oldval) { trace_rcu_dyntick("Start", oldval, 0); - if (!user && !is_idle_task(current)) { + if (!is_idle_task(current)) { struct task_struct *idle = idle_task(smp_processor_id()); trace_rcu_dyntick("Error on entry: not idle task", oldval, 0); @@ -352,7 +372,7 @@ static void rcu_eqs_enter_common(struct rcu_dynticks *rdtp, long long oldval, WARN_ON_ONCE(atomic_read(&rdtp->dynticks) & 0x1); /* - * It is illegal to enter an extended quiescent state while + * The idle task is not permitted to enter the idle loop while * in an RCU read-side critical section. */ rcu_lockdep_assert(!lock_is_held(&rcu_lock_map), @@ -363,25 +383,6 @@ static void rcu_eqs_enter_common(struct rcu_dynticks *rdtp, long long oldval, "Illegal idle entry in RCU-sched read-side critical section."); } -/* - * Enter an RCU extended quiescent state, which can be either the - * idle loop or adaptive-tickless usermode execution. - */ -static void rcu_eqs_enter(bool user) -{ - long long oldval; - struct rcu_dynticks *rdtp; - - rdtp = &__get_cpu_var(rcu_dynticks); - oldval = rdtp->dynticks_nesting; - WARN_ON_ONCE((oldval & DYNTICK_TASK_NEST_MASK) == 0); - if ((oldval & DYNTICK_TASK_NEST_MASK) == DYNTICK_TASK_NEST_VALUE) - rdtp->dynticks_nesting = 0; - else - rdtp->dynticks_nesting -= DYNTICK_TASK_NEST_VALUE; - rcu_eqs_enter_common(rdtp, oldval, user); -} - /** * rcu_idle_enter - inform RCU that current CPU is entering idle * @@ -397,70 +398,21 @@ static void rcu_eqs_enter(bool user) void rcu_idle_enter(void) { unsigned long flags; - - local_irq_save(flags); - rcu_eqs_enter(false); - local_irq_restore(flags); -} -EXPORT_SYMBOL_GPL(rcu_idle_enter); - -#ifdef CONFIG_RCU_USER_QS -/** - * rcu_user_enter - inform RCU that we are resuming userspace. - * - * Enter RCU idle mode right before resuming userspace. No use of RCU - * is permitted between this call and rcu_user_exit(). This way the - * CPU doesn't need to maintain the tick for RCU maintenance purposes - * when the CPU runs in userspace. - */ -void rcu_user_enter(void) -{ - unsigned long flags; - struct rcu_dynticks *rdtp; - - /* - * Some contexts may involve an exception occuring in an irq, - * leading to that nesting: - * rcu_irq_enter() rcu_user_exit() rcu_user_exit() rcu_irq_exit() - * This would mess up the dyntick_nesting count though. And rcu_irq_*() - * helpers are enough to protect RCU uses inside the exception. So - * just return immediately if we detect we are in an IRQ. - */ - if (in_interrupt()) - return; - - WARN_ON_ONCE(!current->mm); - - local_irq_save(flags); - rdtp = &__get_cpu_var(rcu_dynticks); - if (!rdtp->ignore_user_qs && !rdtp->in_user) { - rdtp->in_user = true; - rcu_eqs_enter(true); - } - local_irq_restore(flags); -} - -/** - * rcu_user_enter_after_irq - inform RCU that we are going to resume userspace - * after the current irq returns. - * - * This is similar to rcu_user_enter() but in the context of a non-nesting - * irq. After this call, RCU enters into idle mode when the interrupt - * returns. - */ -void rcu_user_enter_after_irq(void) -{ - unsigned long flags; + long long oldval; struct rcu_dynticks *rdtp; local_irq_save(flags); rdtp = &__get_cpu_var(rcu_dynticks); - /* Ensure this irq is interrupting a non-idle RCU state. */ - WARN_ON_ONCE(!(rdtp->dynticks_nesting & DYNTICK_TASK_MASK)); - rdtp->dynticks_nesting = 1; + oldval = rdtp->dynticks_nesting; + WARN_ON_ONCE((oldval & DYNTICK_TASK_NEST_MASK) == 0); + if ((oldval & DYNTICK_TASK_NEST_MASK) == DYNTICK_TASK_NEST_VALUE) + rdtp->dynticks_nesting = 0; + else + rdtp->dynticks_nesting -= DYNTICK_TASK_NEST_VALUE; + rcu_idle_enter_common(rdtp, oldval); local_irq_restore(flags); } -#endif /* CONFIG_RCU_USER_QS */ +EXPORT_SYMBOL_GPL(rcu_idle_enter); /** * rcu_irq_exit - inform RCU that current CPU is exiting irq towards idle @@ -492,19 +444,18 @@ void rcu_irq_exit(void) if (rdtp->dynticks_nesting) trace_rcu_dyntick("--=", oldval, rdtp->dynticks_nesting); else - rcu_eqs_enter_common(rdtp, oldval, true); + rcu_idle_enter_common(rdtp, oldval); local_irq_restore(flags); } /* - * rcu_eqs_exit_common - current CPU moving away from extended quiescent state + * rcu_idle_exit_common - inform RCU that current CPU is moving away from idle * * If the new value of the ->dynticks_nesting counter was previously zero, * we really have exited idle, and must do the appropriate accounting. * The caller must have disabled interrupts. */ -static void rcu_eqs_exit_common(struct rcu_dynticks *rdtp, long long oldval, - int user) +static void rcu_idle_exit_common(struct rcu_dynticks *rdtp, long long oldval) { smp_mb__before_atomic_inc(); /* Force ordering w/previous sojourn. */ atomic_inc(&rdtp->dynticks); @@ -513,7 +464,7 @@ static void rcu_eqs_exit_common(struct rcu_dynticks *rdtp, long long oldval, WARN_ON_ONCE(!(atomic_read(&rdtp->dynticks) & 0x1)); rcu_cleanup_after_idle(smp_processor_id()); trace_rcu_dyntick("End", oldval, rdtp->dynticks_nesting); - if (!user && !is_idle_task(current)) { + if (!is_idle_task(current)) { struct task_struct *idle = idle_task(smp_processor_id()); trace_rcu_dyntick("Error on exit: not idle task", @@ -525,25 +476,6 @@ static void rcu_eqs_exit_common(struct rcu_dynticks *rdtp, long long oldval, } } -/* - * Exit an RCU extended quiescent state, which can be either the - * idle loop or adaptive-tickless usermode execution. - */ -static void rcu_eqs_exit(bool user) -{ - struct rcu_dynticks *rdtp; - long long oldval; - - rdtp = &__get_cpu_var(rcu_dynticks); - oldval = rdtp->dynticks_nesting; - WARN_ON_ONCE(oldval < 0); - if (oldval & DYNTICK_TASK_NEST_MASK) - rdtp->dynticks_nesting += DYNTICK_TASK_NEST_VALUE; - else - rdtp->dynticks_nesting = DYNTICK_TASK_EXIT_IDLE; - rcu_eqs_exit_common(rdtp, oldval, user); -} - /** * rcu_idle_exit - inform RCU that current CPU is leaving idle * @@ -556,69 +488,23 @@ static void rcu_eqs_exit(bool user) * now starting. */ void rcu_idle_exit(void) -{ - unsigned long flags; - - local_irq_save(flags); - rcu_eqs_exit(false); - local_irq_restore(flags); -} -EXPORT_SYMBOL_GPL(rcu_idle_exit); - -#ifdef CONFIG_RCU_USER_QS -/** - * rcu_user_exit - inform RCU that we are exiting userspace. - * - * Exit RCU idle mode while entering the kernel because it can - * run a RCU read side critical section anytime. - */ -void rcu_user_exit(void) -{ - unsigned long flags; - struct rcu_dynticks *rdtp; - - /* - * Some contexts may involve an exception occuring in an irq, - * leading to that nesting: - * rcu_irq_enter() rcu_user_exit() rcu_user_exit() rcu_irq_exit() - * This would mess up the dyntick_nesting count though. And rcu_irq_*() - * helpers are enough to protect RCU uses inside the exception. So - * just return immediately if we detect we are in an IRQ. - */ - if (in_interrupt()) - return; - - local_irq_save(flags); - rdtp = &__get_cpu_var(rcu_dynticks); - if (rdtp->in_user) { - rdtp->in_user = false; - rcu_eqs_exit(true); - } - local_irq_restore(flags); -} - -/** - * rcu_user_exit_after_irq - inform RCU that we won't resume to userspace - * idle mode after the current non-nesting irq returns. - * - * This is similar to rcu_user_exit() but in the context of an irq. - * This is called when the irq has interrupted a userspace RCU idle mode - * context. When the current non-nesting interrupt returns after this call, - * the CPU won't restore the RCU idle mode. - */ -void rcu_user_exit_after_irq(void) { unsigned long flags; struct rcu_dynticks *rdtp; + long long oldval; local_irq_save(flags); rdtp = &__get_cpu_var(rcu_dynticks); - /* Ensure we are interrupting an RCU idle mode. */ - WARN_ON_ONCE(rdtp->dynticks_nesting & DYNTICK_TASK_NEST_MASK); - rdtp->dynticks_nesting += DYNTICK_TASK_EXIT_IDLE; + oldval = rdtp->dynticks_nesting; + WARN_ON_ONCE(oldval < 0); + if (oldval & DYNTICK_TASK_NEST_MASK) + rdtp->dynticks_nesting += DYNTICK_TASK_NEST_VALUE; + else + rdtp->dynticks_nesting = DYNTICK_TASK_EXIT_IDLE; + rcu_idle_exit_common(rdtp, oldval); local_irq_restore(flags); } -#endif /* CONFIG_RCU_USER_QS */ +EXPORT_SYMBOL_GPL(rcu_idle_exit); /** * rcu_irq_enter - inform RCU that current CPU is entering irq away from idle @@ -653,7 +539,7 @@ void rcu_irq_enter(void) if (oldval) trace_rcu_dyntick("++=", oldval, rdtp->dynticks_nesting); else - rcu_eqs_exit_common(rdtp, oldval, true); + rcu_idle_exit_common(rdtp, oldval); local_irq_restore(flags); } @@ -717,21 +603,6 @@ int rcu_is_cpu_idle(void) } EXPORT_SYMBOL(rcu_is_cpu_idle); -#ifdef CONFIG_RCU_USER_QS -void rcu_user_hooks_switch(struct task_struct *prev, - struct task_struct *next) -{ - struct rcu_dynticks *rdtp; - - /* Interrupts are disabled in context switch */ - rdtp = &__get_cpu_var(rcu_dynticks); - if (!rdtp->ignore_user_qs) { - clear_tsk_thread_flag(prev, TIF_NOHZ); - set_tsk_thread_flag(next, TIF_NOHZ); - } -} -#endif /* #ifdef CONFIG_RCU_USER_QS */ - #if defined(CONFIG_PROVE_RCU) && defined(CONFIG_HOTPLUG_CPU) /* @@ -802,7 +673,7 @@ static int dyntick_save_progress_counter(struct rcu_data *rdp) * Return true if the specified CPU has passed through a quiescent * state by virtue of being in or having passed through an dynticks * idle state since the last call to dyntick_save_progress_counter() - * for this same CPU, or by virtue of having been offline. + * for this same CPU. */ static int rcu_implicit_dynticks_qs(struct rcu_data *rdp) { @@ -826,26 +697,8 @@ static int rcu_implicit_dynticks_qs(struct rcu_data *rdp) return 1; } - /* - * Check for the CPU being offline, but only if the grace period - * is old enough. We don't need to worry about the CPU changing - * state: If we see it offline even once, it has been through a - * quiescent state. - * - * The reason for insisting that the grace period be at least - * one jiffy old is that CPUs that are not quite online and that - * have just gone offline can still execute RCU read-side critical - * sections. - */ - if (ULONG_CMP_GE(rdp->rsp->gp_start + 2, jiffies)) - return 0; /* Grace period is not old enough. */ - barrier(); - if (cpu_is_offline(rdp->cpu)) { - trace_rcu_fqs(rdp->rsp->name, rdp->gpnum, rdp->cpu, "ofl"); - rdp->offline_fqs++; - return 1; - } - return 0; + /* Go check for the CPU being offline. */ + return rcu_implicit_offline_qs(rdp); } static int jiffies_till_stall_check(void) @@ -902,15 +755,14 @@ static void print_other_cpu_stall(struct rcu_state *rsp) rcu_for_each_leaf_node(rsp, rnp) { raw_spin_lock_irqsave(&rnp->lock, flags); ndetected += rcu_print_task_stall(rnp); - if (rnp->qsmask != 0) { - for (cpu = 0; cpu <= rnp->grphi - rnp->grplo; cpu++) - if (rnp->qsmask & (1UL << cpu)) { - print_cpu_stall_info(rsp, - rnp->grplo + cpu); - ndetected++; - } - } raw_spin_unlock_irqrestore(&rnp->lock, flags); + if (rnp->qsmask == 0) + continue; + for (cpu = 0; cpu <= rnp->grphi - rnp->grplo; cpu++) + if (rnp->qsmask & (1UL << cpu)) { + print_cpu_stall_info(rsp, rnp->grplo + cpu); + ndetected++; + } } /* @@ -930,11 +782,11 @@ static void print_other_cpu_stall(struct rcu_state *rsp) else if (!trigger_all_cpu_backtrace()) dump_stack(); - /* Complain about tasks blocking the grace period. */ + /* If so configured, complain about tasks blocking the grace period. */ rcu_print_detail_task_stall(rsp); - force_quiescent_state(rsp); /* Kick them all. */ + force_quiescent_state(rsp, 0); /* Kick them all. */ } static void print_cpu_stall(struct rcu_state *rsp) @@ -975,8 +827,7 @@ static void check_cpu_stall(struct rcu_state *rsp, struct rcu_data *rdp) j = ACCESS_ONCE(jiffies); js = ACCESS_ONCE(rsp->jiffies_stall); rnp = rdp->mynode; - if (rcu_gp_in_progress(rsp) && - (ACCESS_ONCE(rnp->qsmask) & rdp->grpmask) && ULONG_CMP_GE(j, js)) { + if ((ACCESS_ONCE(rnp->qsmask) & rdp->grpmask) && ULONG_CMP_GE(j, js)) { /* We haven't checked in, so go dump stack. */ print_cpu_stall(rsp); @@ -1038,8 +889,12 @@ static void __note_new_gpnum(struct rcu_state *rsp, struct rcu_node *rnp, struct */ rdp->gpnum = rnp->gpnum; trace_rcu_grace_period(rsp->name, rdp->gpnum, "cpustart"); - rdp->passed_quiesce = 0; - rdp->qs_pending = !!(rnp->qsmask & rdp->grpmask); + if (rnp->qsmask & rdp->grpmask) { + rdp->qs_pending = 1; + rdp->passed_quiesce = 0; + } else { + rdp->qs_pending = 0; + } zero_cpu_stall_ticks(rdp); } } @@ -1119,13 +974,10 @@ __rcu_process_gp_end(struct rcu_state *rsp, struct rcu_node *rnp, struct rcu_dat * our behalf. Catch up with this state to avoid noting * spurious new grace periods. If another grace period * has started, then rnp->gpnum will have advanced, so - * we will detect this later on. Of course, any quiescent - * states we found for the old GP are now invalid. + * we will detect this later on. */ - if (ULONG_CMP_LT(rdp->gpnum, rdp->completed)) { + if (ULONG_CMP_LT(rdp->gpnum, rdp->completed)) rdp->gpnum = rdp->completed; - rdp->passed_quiesce = 0; - } /* * If RCU does not need a quiescent state from this CPU, @@ -1169,56 +1021,97 @@ rcu_start_gp_per_cpu(struct rcu_state *rsp, struct rcu_node *rnp, struct rcu_dat /* Prior grace period ended, so advance callbacks for current CPU. */ __rcu_process_gp_end(rsp, rnp, rdp); + /* + * Because this CPU just now started the new grace period, we know + * that all of its callbacks will be covered by this upcoming grace + * period, even the ones that were registered arbitrarily recently. + * Therefore, advance all outstanding callbacks to RCU_WAIT_TAIL. + * + * Other CPUs cannot be sure exactly when the grace period started. + * Therefore, their recently registered callbacks must pass through + * an additional RCU_NEXT_READY stage, so that they will be handled + * by the next RCU grace period. + */ + rdp->nxttail[RCU_NEXT_READY_TAIL] = rdp->nxttail[RCU_NEXT_TAIL]; + rdp->nxttail[RCU_WAIT_TAIL] = rdp->nxttail[RCU_NEXT_TAIL]; + /* Set state so that this CPU will detect the next quiescent state. */ __note_new_gpnum(rsp, rnp, rdp); } /* - * Initialize a new grace period. + * Start a new RCU grace period if warranted, re-initializing the hierarchy + * in preparation for detecting the next grace period. The caller must hold + * the root node's ->lock, which is released before return. Hard irqs must + * be disabled. + * + * Note that it is legal for a dying CPU (which is marked as offline) to + * invoke this function. This can happen when the dying CPU reports its + * quiescent state. */ -static int rcu_gp_init(struct rcu_state *rsp) +static void +rcu_start_gp(struct rcu_state *rsp, unsigned long flags) + __releases(rcu_get_root(rsp)->lock) { - struct rcu_data *rdp; + struct rcu_data *rdp = this_cpu_ptr(rsp->rda); struct rcu_node *rnp = rcu_get_root(rsp); - raw_spin_lock_irq(&rnp->lock); - rsp->gp_flags = 0; /* Clear all flags: New grace period. */ + if (!rcu_scheduler_fully_active || + !cpu_needs_another_gp(rsp, rdp)) { + /* + * Either the scheduler hasn't yet spawned the first + * non-idle task or this CPU does not need another + * grace period. Either way, don't start a new grace + * period. + */ + raw_spin_unlock_irqrestore(&rnp->lock, flags); + return; + } - if (rcu_gp_in_progress(rsp)) { - /* Grace period already in progress, don't start another. */ - raw_spin_unlock_irq(&rnp->lock); - return 0; + if (rsp->fqs_active) { + /* + * This CPU needs a grace period, but force_quiescent_state() + * is running. Tell it to start one on this CPU's behalf. + */ + rsp->fqs_need_gp = 1; + raw_spin_unlock_irqrestore(&rnp->lock, flags); + return; } /* Advance to a new grace period and initialize state. */ rsp->gpnum++; trace_rcu_grace_period(rsp->name, rsp->gpnum, "start"); + WARN_ON_ONCE(rsp->fqs_state == RCU_GP_INIT); + rsp->fqs_state = RCU_GP_INIT; /* Hold off force_quiescent_state. */ + rsp->jiffies_force_qs = jiffies + RCU_JIFFIES_TILL_FORCE_QS; record_gp_stall_check_time(rsp); - raw_spin_unlock_irq(&rnp->lock); + raw_spin_unlock(&rnp->lock); /* leave irqs disabled. */ /* Exclude any concurrent CPU-hotplug operations. */ - get_online_cpus(); + raw_spin_lock(&rsp->onofflock); /* irqs already disabled. */ /* * Set the quiescent-state-needed bits in all the rcu_node - * structures for all currently online CPUs in breadth-first order, - * starting from the root rcu_node structure, relying on the layout - * of the tree within the rsp->node[] array. Note that other CPUs - * will access only the leaves of the hierarchy, thus seeing that no + * structures for all currently online CPUs in breadth-first + * order, starting from the root rcu_node structure. This + * operation relies on the layout of the hierarchy within the + * rsp->node[] array. Note that other CPUs will access only + * the leaves of the hierarchy, which still indicate that no * grace period is in progress, at least until the corresponding * leaf node has been initialized. In addition, we have excluded * CPU-hotplug operations. * - * The grace period cannot complete until the initialization - * process finishes, because this kthread handles both. + * Note that the grace period cannot complete until we finish + * the initialization process, as there will be at least one + * qsmask bit set in the root node until that time, namely the + * one corresponding to this CPU, due to the fact that we have + * irqs disabled. */ rcu_for_each_node_breadth_first(rsp, rnp) { - raw_spin_lock_irq(&rnp->lock); - rdp = this_cpu_ptr(rsp->rda); + raw_spin_lock(&rnp->lock); /* irqs already disabled. */ rcu_preempt_check_blocked_tasks(rnp); rnp->qsmask = rnp->qsmaskinit; rnp->gpnum = rsp->gpnum; - WARN_ON_ONCE(rnp->completed != rsp->completed); rnp->completed = rsp->completed; if (rnp == rdp->mynode) rcu_start_gp_per_cpu(rsp, rnp, rdp); @@ -1226,54 +1119,37 @@ static int rcu_gp_init(struct rcu_state *rsp) trace_rcu_grace_period_init(rsp->name, rnp->gpnum, rnp->level, rnp->grplo, rnp->grphi, rnp->qsmask); - raw_spin_unlock_irq(&rnp->lock); -#ifdef CONFIG_PROVE_RCU_DELAY - if ((random32() % (rcu_num_nodes * 8)) == 0) - schedule_timeout_uninterruptible(2); -#endif /* #ifdef CONFIG_PROVE_RCU_DELAY */ - cond_resched(); + raw_spin_unlock(&rnp->lock); /* irqs remain disabled. */ } - put_online_cpus(); - return 1; -} - -/* - * Do one round of quiescent-state forcing. - */ -int rcu_gp_fqs(struct rcu_state *rsp, int fqs_state_in) -{ - int fqs_state = fqs_state_in; - struct rcu_node *rnp = rcu_get_root(rsp); - - rsp->n_force_qs++; - if (fqs_state == RCU_SAVE_DYNTICK) { - /* Collect dyntick-idle snapshots. */ - force_qs_rnp(rsp, dyntick_save_progress_counter); - fqs_state = RCU_FORCE_QS; - } else { - /* Handle dyntick-idle and offline CPUs. */ - force_qs_rnp(rsp, rcu_implicit_dynticks_qs); - } - /* Clear flag to prevent immediate re-entry. */ - if (ACCESS_ONCE(rsp->gp_flags) & RCU_GP_FLAG_FQS) { - raw_spin_lock_irq(&rnp->lock); - rsp->gp_flags &= ~RCU_GP_FLAG_FQS; - raw_spin_unlock_irq(&rnp->lock); - } - return fqs_state; + rnp = rcu_get_root(rsp); + raw_spin_lock(&rnp->lock); /* irqs already disabled. */ + rsp->fqs_state = RCU_SIGNAL_INIT; /* force_quiescent_state now OK. */ + raw_spin_unlock(&rnp->lock); /* irqs remain disabled. */ + raw_spin_unlock_irqrestore(&rsp->onofflock, flags); } /* - * Clean up after the old grace period. + * Report a full set of quiescent states to the specified rcu_state + * data structure. This involves cleaning up after the prior grace + * period and letting rcu_start_gp() start up the next grace period + * if one is needed. Note that the caller must hold rnp->lock, as + * required by rcu_start_gp(), which will release it. */ -static void rcu_gp_cleanup(struct rcu_state *rsp) +static void rcu_report_qs_rsp(struct rcu_state *rsp, unsigned long flags) + __releases(rcu_get_root(rsp)->lock) { unsigned long gp_duration; - struct rcu_data *rdp; struct rcu_node *rnp = rcu_get_root(rsp); + struct rcu_data *rdp = this_cpu_ptr(rsp->rda); - raw_spin_lock_irq(&rnp->lock); + WARN_ON_ONCE(!rcu_gp_in_progress(rsp)); + + /* + * Ensure that all grace-period and pre-grace-period activity + * is seen before the assignment to rsp->completed. + */ + smp_mb(); /* See above block comment. */ gp_duration = jiffies - rsp->gp_start; if (gp_duration > rsp->gp_max) rsp->gp_max = gp_duration; @@ -1285,149 +1161,35 @@ static void rcu_gp_cleanup(struct rcu_state *rsp) * they can do to advance the grace period. It is therefore * safe for us to drop the lock in order to mark the grace * period as completed in all of the rcu_node structures. + * + * But if this CPU needs another grace period, it will take + * care of this while initializing the next grace period. + * We use RCU_WAIT_TAIL instead of the usual RCU_DONE_TAIL + * because the callbacks have not yet been advanced: Those + * callbacks are waiting on the grace period that just now + * completed. */ - raw_spin_unlock_irq(&rnp->lock); - - /* - * Propagate new ->completed value to rcu_node structures so - * that other CPUs don't have to wait until the start of the next - * grace period to process their callbacks. This also avoids - * some nasty RCU grace-period initialization races by forcing - * the end of the current grace period to be completely recorded in - * all of the rcu_node structures before the beginning of the next - * grace period is recorded in any of the rcu_node structures. - */ - rcu_for_each_node_breadth_first(rsp, rnp) { - raw_spin_lock_irq(&rnp->lock); - rnp->completed = rsp->gpnum; - raw_spin_unlock_irq(&rnp->lock); - cond_resched(); - } - rnp = rcu_get_root(rsp); - raw_spin_lock_irq(&rnp->lock); + if (*rdp->nxttail[RCU_WAIT_TAIL] == NULL) { + raw_spin_unlock(&rnp->lock); /* irqs remain disabled. */ - rsp->completed = rsp->gpnum; /* Declare grace period done. */ - trace_rcu_grace_period(rsp->name, rsp->completed, "end"); - rsp->fqs_state = RCU_GP_IDLE; - rdp = this_cpu_ptr(rsp->rda); - if (cpu_needs_another_gp(rsp, rdp)) - rsp->gp_flags = 1; - raw_spin_unlock_irq(&rnp->lock); -} - -/* - * Body of kthread that handles grace periods. - */ -static int __noreturn rcu_gp_kthread(void *arg) -{ - int fqs_state; - unsigned long j; - int ret; - struct rcu_state *rsp = arg; - struct rcu_node *rnp = rcu_get_root(rsp); - - for (;;) { - - /* Handle grace-period start. */ - for (;;) { - wait_event_interruptible(rsp->gp_wq, - rsp->gp_flags & - RCU_GP_FLAG_INIT); - if ((rsp->gp_flags & RCU_GP_FLAG_INIT) && - rcu_gp_init(rsp)) - break; - cond_resched(); - flush_signals(current); - } - - /* Handle quiescent-state forcing. */ - fqs_state = RCU_SAVE_DYNTICK; - j = jiffies_till_first_fqs; - if (j > HZ) { - j = HZ; - jiffies_till_first_fqs = HZ; - } - for (;;) { - rsp->jiffies_force_qs = jiffies + j; - ret = wait_event_interruptible_timeout(rsp->gp_wq, - (rsp->gp_flags & RCU_GP_FLAG_FQS) || - (!ACCESS_ONCE(rnp->qsmask) && - !rcu_preempt_blocked_readers_cgp(rnp)), - j); - /* If grace period done, leave loop. */ - if (!ACCESS_ONCE(rnp->qsmask) && - !rcu_preempt_blocked_readers_cgp(rnp)) - break; - /* If time for quiescent-state forcing, do it. */ - if (ret == 0 || (rsp->gp_flags & RCU_GP_FLAG_FQS)) { - fqs_state = rcu_gp_fqs(rsp, fqs_state); - cond_resched(); - } else { - /* Deal with stray signal. */ - cond_resched(); - flush_signals(current); - } - j = jiffies_till_next_fqs; - if (j > HZ) { - j = HZ; - jiffies_till_next_fqs = HZ; - } else if (j < 1) { - j = 1; - jiffies_till_next_fqs = 1; - } - } - - /* Handle grace-period end. */ - rcu_gp_cleanup(rsp); - } -} - -/* - * Start a new RCU grace period if warranted, re-initializing the hierarchy - * in preparation for detecting the next grace period. The caller must hold - * the root node's ->lock, which is released before return. Hard irqs must - * be disabled. - * - * Note that it is legal for a dying CPU (which is marked as offline) to - * invoke this function. This can happen when the dying CPU reports its - * quiescent state. - */ -static void -rcu_start_gp(struct rcu_state *rsp, unsigned long flags) - __releases(rcu_get_root(rsp)->lock) -{ - struct rcu_data *rdp = this_cpu_ptr(rsp->rda); - struct rcu_node *rnp = rcu_get_root(rsp); - - if (!rsp->gp_kthread || - !cpu_needs_another_gp(rsp, rdp)) { /* - * Either we have not yet spawned the grace-period - * task or this CPU does not need another grace period. - * Either way, don't start a new grace period. + * Propagate new ->completed value to rcu_node structures + * so that other CPUs don't have to wait until the start + * of the next grace period to process their callbacks. */ - raw_spin_unlock_irqrestore(&rnp->lock, flags); - return; + rcu_for_each_node_breadth_first(rsp, rnp) { + raw_spin_lock(&rnp->lock); /* irqs already disabled. */ + rnp->completed = rsp->gpnum; + raw_spin_unlock(&rnp->lock); /* irqs remain disabled. */ + } + rnp = rcu_get_root(rsp); + raw_spin_lock(&rnp->lock); /* irqs already disabled. */ } - rsp->gp_flags = RCU_GP_FLAG_INIT; - raw_spin_unlock_irqrestore(&rnp->lock, flags); - wake_up(&rsp->gp_wq); -} - -/* - * Report a full set of quiescent states to the specified rcu_state - * data structure. This involves cleaning up after the prior grace - * period and letting rcu_start_gp() start up the next grace period - * if one is needed. Note that the caller must hold rnp->lock, as - * required by rcu_start_gp(), which will release it. - */ -static void rcu_report_qs_rsp(struct rcu_state *rsp, unsigned long flags) - __releases(rcu_get_root(rsp)->lock) -{ - WARN_ON_ONCE(!rcu_gp_in_progress(rsp)); - raw_spin_unlock_irqrestore(&rcu_get_root(rsp)->lock, flags); - wake_up(&rsp->gp_wq); /* Memory barrier implied by wake_up() path. */ + rsp->completed = rsp->gpnum; /* Declare the grace period complete. */ + trace_rcu_grace_period(rsp->name, rsp->completed, "end"); + rsp->fqs_state = RCU_GP_IDLE; + rcu_start_gp(rsp, flags); /* releases root node's rnp->lock. */ } /* @@ -1496,7 +1258,7 @@ rcu_report_qs_rnp(unsigned long mask, struct rcu_state *rsp, * based on quiescent states detected in an earlier grace period! */ static void -rcu_report_qs_rdp(int cpu, struct rcu_state *rsp, struct rcu_data *rdp) +rcu_report_qs_rdp(int cpu, struct rcu_state *rsp, struct rcu_data *rdp, long lastgp) { unsigned long flags; unsigned long mask; @@ -1504,8 +1266,7 @@ rcu_report_qs_rdp(int cpu, struct rcu_state *rsp, struct rcu_data *rdp) rnp = rdp->mynode; raw_spin_lock_irqsave(&rnp->lock, flags); - if (rdp->passed_quiesce == 0 || rdp->gpnum != rnp->gpnum || - rnp->completed == rnp->gpnum) { + if (lastgp != rnp->gpnum || rnp->completed == rnp->gpnum) { /* * The grace period in which this quiescent state was @@ -1564,7 +1325,7 @@ rcu_check_quiescent_state(struct rcu_state *rsp, struct rcu_data *rdp) * Tell RCU we are done (but rcu_report_qs_rdp() will be the * judge of that). */ - rcu_report_qs_rdp(rdp->cpu, rsp, rdp); + rcu_report_qs_rdp(rdp->cpu, rsp, rdp, rdp->passed_quiesce_gpnum); } #ifdef CONFIG_HOTPLUG_CPU @@ -1629,6 +1390,17 @@ static void rcu_adopt_orphan_cbs(struct rcu_state *rsp) int i; struct rcu_data *rdp = __this_cpu_ptr(rsp->rda); + /* + * If there is an rcu_barrier() operation in progress, then + * only the task doing that operation is permitted to adopt + * callbacks. To do otherwise breaks rcu_barrier() and friends + * by causing them to fail to wait for the callbacks in the + * orphanage. + */ + if (rsp->rcu_barrier_in_progress && + rsp->rcu_barrier_in_progress != current) + return; + /* Do the accounting first. */ rdp->qlen_lazy += rsp->qlen_lazy; rdp->qlen += rsp->qlen; @@ -1683,8 +1455,9 @@ static void rcu_cleanup_dying_cpu(struct rcu_state *rsp) * The CPU has been completely removed, and some other CPU is reporting * this fact from process context. Do the remainder of the cleanup, * including orphaning the outgoing CPU's RCU callbacks, and also - * adopting them. There can only be one CPU hotplug operation at a time, - * so no other CPU can be attempting to update rcu_cpu_kthread_task. + * adopting them, if there is no _rcu_barrier() instance running. + * There can only be one CPU hotplug operation at a time, so no other + * CPU can be attempting to update rcu_cpu_kthread_task. */ static void rcu_cleanup_dead_cpu(int cpu, struct rcu_state *rsp) { @@ -1695,7 +1468,8 @@ static void rcu_cleanup_dead_cpu(int cpu, struct rcu_state *rsp) struct rcu_node *rnp = rdp->mynode; /* Outgoing CPU's rdp & rnp. */ /* Adjust any no-longer-needed kthreads. */ - rcu_boost_kthread_setaffinity(rnp, -1); + rcu_stop_cpu_kthread(cpu); + rcu_node_kthread_setaffinity(rnp, -1); /* Remove the dead CPU from the bitmasks in the rcu_node hierarchy. */ @@ -1741,13 +1515,14 @@ static void rcu_cleanup_dead_cpu(int cpu, struct rcu_state *rsp) WARN_ONCE(rdp->qlen != 0 || rdp->nxtlist != NULL, "rcu_cleanup_dead_cpu: Callbacks on offline CPU %d: qlen=%lu, nxtlist=%p\n", cpu, rdp->qlen, rdp->nxtlist); - init_callback_list(rdp); - /* Disallow further callbacks on this CPU. */ - rdp->nxttail[RCU_NEXT_TAIL] = NULL; } #else /* #ifdef CONFIG_HOTPLUG_CPU */ +static void rcu_adopt_orphan_cbs(struct rcu_state *rsp) +{ +} + static void rcu_cleanup_dying_cpu(struct rcu_state *rsp) { } @@ -1912,7 +1687,6 @@ static void force_qs_rnp(struct rcu_state *rsp, int (*f)(struct rcu_data *)) struct rcu_node *rnp; rcu_for_each_leaf_node(rsp, rnp) { - cond_resched(); mask = 0; raw_spin_lock_irqsave(&rnp->lock, flags); if (!rcu_gp_in_progress(rsp)) { @@ -1949,39 +1723,72 @@ static void force_qs_rnp(struct rcu_state *rsp, int (*f)(struct rcu_data *)) * Force quiescent states on reluctant CPUs, and also detect which * CPUs are in dyntick-idle mode. */ -static void force_quiescent_state(struct rcu_state *rsp) +static void force_quiescent_state(struct rcu_state *rsp, int relaxed) { unsigned long flags; - bool ret; - struct rcu_node *rnp; - struct rcu_node *rnp_old = NULL; - - /* Funnel through hierarchy to reduce memory contention. */ - rnp = per_cpu_ptr(rsp->rda, raw_smp_processor_id())->mynode; - for (; rnp != NULL; rnp = rnp->parent) { - ret = (ACCESS_ONCE(rsp->gp_flags) & RCU_GP_FLAG_FQS) || - !raw_spin_trylock(&rnp->fqslock); - if (rnp_old != NULL) - raw_spin_unlock(&rnp_old->fqslock); - if (ret) { - rsp->n_force_qs_lh++; - return; - } - rnp_old = rnp; + struct rcu_node *rnp = rcu_get_root(rsp); + + trace_rcu_utilization("Start fqs"); + if (!rcu_gp_in_progress(rsp)) { + trace_rcu_utilization("End fqs"); + return; /* No grace period in progress, nothing to force. */ + } + if (!raw_spin_trylock_irqsave(&rsp->fqslock, flags)) { + rsp->n_force_qs_lh++; /* Inexact, can lose counts. Tough! */ + trace_rcu_utilization("End fqs"); + return; /* Someone else is already on the job. */ + } + if (relaxed && ULONG_CMP_GE(rsp->jiffies_force_qs, jiffies)) + goto unlock_fqs_ret; /* no emergency and done recently. */ + rsp->n_force_qs++; + raw_spin_lock(&rnp->lock); /* irqs already disabled */ + rsp->jiffies_force_qs = jiffies + RCU_JIFFIES_TILL_FORCE_QS; + if(!rcu_gp_in_progress(rsp)) { + rsp->n_force_qs_ngp++; + raw_spin_unlock(&rnp->lock); /* irqs remain disabled */ + goto unlock_fqs_ret; /* no GP in progress, time updated. */ + } + rsp->fqs_active = 1; + switch (rsp->fqs_state) { + case RCU_GP_IDLE: + case RCU_GP_INIT: + + break; /* grace period idle or initializing, ignore. */ + + case RCU_SAVE_DYNTICK: + + raw_spin_unlock(&rnp->lock); /* irqs remain disabled */ + + /* Record dyntick-idle state. */ + force_qs_rnp(rsp, dyntick_save_progress_counter); + raw_spin_lock(&rnp->lock); /* irqs already disabled */ + if (rcu_gp_in_progress(rsp)) + rsp->fqs_state = RCU_FORCE_QS; + break; + + case RCU_FORCE_QS: + + /* Check dyntick-idle state, send IPI to laggarts. */ + raw_spin_unlock(&rnp->lock); /* irqs remain disabled */ + force_qs_rnp(rsp, rcu_implicit_dynticks_qs); + + /* Leave state in case more forcing is required. */ + + raw_spin_lock(&rnp->lock); /* irqs already disabled */ + break; } - /* rnp_old == rcu_get_root(rsp), rnp == NULL. */ - - /* Reached the root of the rcu_node tree, acquire lock. */ - raw_spin_lock_irqsave(&rnp_old->lock, flags); - raw_spin_unlock(&rnp_old->fqslock); - if (ACCESS_ONCE(rsp->gp_flags) & RCU_GP_FLAG_FQS) { - rsp->n_force_qs_lh++; - raw_spin_unlock_irqrestore(&rnp_old->lock, flags); - return; /* Someone beat us to it. */ + rsp->fqs_active = 0; + if (rsp->fqs_need_gp) { + raw_spin_unlock(&rsp->fqslock); /* irqs remain disabled */ + rsp->fqs_need_gp = 0; + rcu_start_gp(rsp, flags); /* releases rnp->lock */ + trace_rcu_utilization("End fqs"); + return; } - rsp->gp_flags |= RCU_GP_FLAG_FQS; - raw_spin_unlock_irqrestore(&rnp_old->lock, flags); - wake_up(&rsp->gp_wq); /* Memory barrier implied by wake_up() path. */ + raw_spin_unlock(&rnp->lock); /* irqs remain disabled */ +unlock_fqs_ret: + raw_spin_unlock_irqrestore(&rsp->fqslock, flags); + trace_rcu_utilization("End fqs"); } /* @@ -1997,6 +1804,13 @@ __rcu_process_callbacks(struct rcu_state *rsp) WARN_ON_ONCE(rdp->beenonline == 0); + /* + * If an RCU GP has gone long enough, go check for dyntick + * idle CPUs and, if needed, send resched IPIs. + */ + if (ULONG_CMP_LT(ACCESS_ONCE(rsp->jiffies_force_qs), jiffies)) + force_quiescent_state(rsp, 1); + /* * Advance callbacks in response to end of earlier grace * period that some other CPU ended. @@ -2024,8 +1838,6 @@ static void rcu_process_callbacks(struct softirq_action *unused) { struct rcu_state *rsp; - if (cpu_is_offline(smp_processor_id())) - return; trace_rcu_utilization("Start RCU core"); for_each_rcu_flavor(rsp) __rcu_process_callbacks(rsp); @@ -2097,11 +1909,12 @@ static void __call_rcu_core(struct rcu_state *rsp, struct rcu_data *rdp, rdp->blimit = LONG_MAX; if (rsp->n_force_qs == rdp->n_force_qs_snap && *rdp->nxttail[RCU_DONE_TAIL] != head) - force_quiescent_state(rsp); + force_quiescent_state(rsp, 0); rdp->n_force_qs_snap = rsp->n_force_qs; rdp->qlen_last_fqs_check = rdp->qlen; } - } + } else if (ULONG_CMP_LT(ACCESS_ONCE(rsp->jiffies_force_qs), jiffies)) + force_quiescent_state(rsp, 1); } static void @@ -2116,6 +1929,8 @@ __call_rcu(struct rcu_head *head, void (*func)(struct rcu_head *rcu), head->func = func; head->next = NULL; + smp_mb(); /* Ensure RCU update seen before callback registry. */ + /* * Opportunistically note grace-period endings and beginnings. * Note that we might see a beginning right after we see an @@ -2126,12 +1941,6 @@ __call_rcu(struct rcu_head *head, void (*func)(struct rcu_head *rcu), rdp = this_cpu_ptr(rsp->rda); /* Add the callback to our list. */ - if (unlikely(rdp->nxttail[RCU_NEXT_TAIL] == NULL)) { - /* _call_rcu() is illegal on offline CPU; leak the callback. */ - WARN_ON_ONCE(1); - local_irq_restore(flags); - return; - } ACCESS_ONCE(rdp->qlen)++; if (lazy) rdp->qlen_lazy++; @@ -2386,7 +2195,17 @@ static int __rcu_pending(struct rcu_state *rsp, struct rcu_data *rdp) /* Is the RCU core waiting for a quiescent state from this CPU? */ if (rcu_scheduler_fully_active && rdp->qs_pending && !rdp->passed_quiesce) { + + /* + * If force_quiescent_state() coming soon and this CPU + * needs a quiescent state, and this is either RCU-sched + * or RCU-bh, force a local reschedule. + */ rdp->n_rp_qs_pending++; + if (!rdp->preemptible && + ULONG_CMP_LT(ACCESS_ONCE(rsp->jiffies_force_qs) - 1, + jiffies)) + set_need_resched(); } else if (rdp->qs_pending && rdp->passed_quiesce) { rdp->n_rp_report_qs++; return 1; @@ -2416,6 +2235,13 @@ static int __rcu_pending(struct rcu_state *rsp, struct rcu_data *rdp) return 1; } + /* Has an RCU GP gone long enough to send resched IPIs &c? */ + if (rcu_gp_in_progress(rsp) && + ULONG_CMP_LT(ACCESS_ONCE(rsp->jiffies_force_qs), jiffies)) { + rdp->n_rp_need_fqs++; + return 1; + } + /* nothing to do */ rdp->n_rp_need_nothing++; return 0; @@ -2500,10 +2326,13 @@ static void rcu_barrier_func(void *type) static void _rcu_barrier(struct rcu_state *rsp) { int cpu; + unsigned long flags; struct rcu_data *rdp; + struct rcu_data rd; unsigned long snap = ACCESS_ONCE(rsp->n_barrier_done); unsigned long snap_done; + init_rcu_head_on_stack(&rd.barrier_head); _rcu_barrier_trace(rsp, "Begin", -1, snap); /* Take mutex to serialize concurrent rcu_barrier() requests. */ @@ -2543,30 +2372,70 @@ static void _rcu_barrier(struct rcu_state *rsp) /* * Initialize the count to one rather than to zero in order to * avoid a too-soon return to zero in case of a short grace period - * (or preemption of this task). Exclude CPU-hotplug operations - * to ensure that no offline CPU has callbacks queued. + * (or preemption of this task). Also flag this task as doing + * an rcu_barrier(). This will prevent anyone else from adopting + * orphaned callbacks, which could cause otherwise failure if a + * CPU went offline and quickly came back online. To see this, + * consider the following sequence of events: + * + * 1. We cause CPU 0 to post an rcu_barrier_callback() callback. + * 2. CPU 1 goes offline, orphaning its callbacks. + * 3. CPU 0 adopts CPU 1's orphaned callbacks. + * 4. CPU 1 comes back online. + * 5. We cause CPU 1 to post an rcu_barrier_callback() callback. + * 6. Both rcu_barrier_callback() callbacks are invoked, awakening + * us -- but before CPU 1's orphaned callbacks are invoked!!! */ init_completion(&rsp->barrier_completion); atomic_set(&rsp->barrier_cpu_count, 1); - get_online_cpus(); + raw_spin_lock_irqsave(&rsp->onofflock, flags); + rsp->rcu_barrier_in_progress = current; + raw_spin_unlock_irqrestore(&rsp->onofflock, flags); /* - * Force each CPU with callbacks to register a new callback. - * When that callback is invoked, we will know that all of the - * corresponding CPU's preceding callbacks have been invoked. + * Force every CPU with callbacks to register a new callback + * that will tell us when all the preceding callbacks have + * been invoked. If an offline CPU has callbacks, wait for + * it to either come back online or to finish orphaning those + * callbacks. */ - for_each_online_cpu(cpu) { + for_each_possible_cpu(cpu) { + preempt_disable(); rdp = per_cpu_ptr(rsp->rda, cpu); - if (ACCESS_ONCE(rdp->qlen)) { + if (cpu_is_offline(cpu)) { + _rcu_barrier_trace(rsp, "Offline", cpu, + rsp->n_barrier_done); + preempt_enable(); + while (cpu_is_offline(cpu) && ACCESS_ONCE(rdp->qlen)) + schedule_timeout_interruptible(1); + } else if (ACCESS_ONCE(rdp->qlen)) { _rcu_barrier_trace(rsp, "OnlineQ", cpu, rsp->n_barrier_done); smp_call_function_single(cpu, rcu_barrier_func, rsp, 1); + preempt_enable(); } else { _rcu_barrier_trace(rsp, "OnlineNQ", cpu, rsp->n_barrier_done); + preempt_enable(); } } - put_online_cpus(); + + /* + * Now that all online CPUs have rcu_barrier_callback() callbacks + * posted, we can adopt all of the orphaned callbacks and place + * an rcu_barrier_callback() callback after them. When that is done, + * we are guaranteed to have an rcu_barrier_callback() callback + * following every callback that could possibly have been + * registered before _rcu_barrier() was called. + */ + raw_spin_lock_irqsave(&rsp->onofflock, flags); + rcu_adopt_orphan_cbs(rsp); + rsp->rcu_barrier_in_progress = NULL; + raw_spin_unlock_irqrestore(&rsp->onofflock, flags); + atomic_inc(&rsp->barrier_cpu_count); + smp_mb__after_atomic_inc(); /* Ensure atomic_inc() before callback. */ + rd.rsp = rsp; + rsp->call(&rd.barrier_head, rcu_barrier_callback); /* * Now that we have an rcu_barrier_callback() callback on each @@ -2587,6 +2456,8 @@ static void _rcu_barrier(struct rcu_state *rsp) /* Other rcu_barrier() invocations can now safely proceed. */ mutex_unlock(&rsp->barrier_mutex); + + destroy_rcu_head_on_stack(&rd.barrier_head); } /** @@ -2626,9 +2497,6 @@ rcu_boot_init_percpu_data(int cpu, struct rcu_state *rsp) rdp->dynticks = &per_cpu(rcu_dynticks, cpu); WARN_ON_ONCE(rdp->dynticks->dynticks_nesting != DYNTICK_TASK_EXIT_IDLE); WARN_ON_ONCE(atomic_read(&rdp->dynticks->dynticks) != 1); -#ifdef CONFIG_RCU_USER_QS - WARN_ON_ONCE(rdp->dynticks->in_user); -#endif rdp->cpu = cpu; rdp->rsp = rsp; raw_spin_unlock_irqrestore(&rnp->lock, flags); @@ -2655,7 +2523,6 @@ rcu_init_percpu_data(int cpu, struct rcu_state *rsp, int preemptible) rdp->qlen_last_fqs_check = 0; rdp->n_force_qs_snap = rsp->n_force_qs; rdp->blimit = blimit; - init_callback_list(rdp); /* Re-enable callbacks on this CPU. */ rdp->dynticks->dynticks_nesting = DYNTICK_TASK_EXIT_IDLE; atomic_set(&rdp->dynticks->dynticks, (atomic_read(&rdp->dynticks->dynticks) & ~0x1) + 1); @@ -2688,6 +2555,7 @@ rcu_init_percpu_data(int cpu, struct rcu_state *rsp, int preemptible) rdp->completed = rnp->completed; rdp->passed_quiesce = 0; rdp->qs_pending = 0; + rdp->passed_quiesce_gpnum = rnp->gpnum - 1; trace_rcu_grace_period(rsp->name, rdp->gpnum, "cpuonl"); } raw_spin_unlock(&rnp->lock); /* irqs already disabled. */ @@ -2726,10 +2594,12 @@ static int __cpuinit rcu_cpu_notify(struct notifier_block *self, break; case CPU_ONLINE: case CPU_DOWN_FAILED: - rcu_boost_kthread_setaffinity(rnp, -1); + rcu_node_kthread_setaffinity(rnp, -1); + rcu_cpu_kthread_setrt(cpu, 1); break; case CPU_DOWN_PREPARE: - rcu_boost_kthread_setaffinity(rnp, cpu); + rcu_node_kthread_setaffinity(rnp, cpu); + rcu_cpu_kthread_setrt(cpu, 0); break; case CPU_DYING: case CPU_DYING_FROZEN: @@ -2756,28 +2626,6 @@ static int __cpuinit rcu_cpu_notify(struct notifier_block *self, return NOTIFY_OK; } -/* - * Spawn the kthread that handles this RCU flavor's grace periods. - */ -static int __init rcu_spawn_gp_kthread(void) -{ - unsigned long flags; - struct rcu_node *rnp; - struct rcu_state *rsp; - struct task_struct *t; - - for_each_rcu_flavor(rsp) { - t = kthread_run(rcu_gp_kthread, rsp, rsp->name); - BUG_ON(IS_ERR(t)); - rnp = rcu_get_root(rsp); - raw_spin_lock_irqsave(&rnp->lock, flags); - rsp->gp_kthread = t; - raw_spin_unlock_irqrestore(&rnp->lock, flags); - } - return 0; -} -early_initcall(rcu_spawn_gp_kthread); - /* * This function is invoked towards the end of the scheduler's initialization * process. Before this is called, the idle task might contain @@ -2813,7 +2661,7 @@ static void __init rcu_init_levelspread(struct rcu_state *rsp) int cprv; int i; - cprv = nr_cpu_ids; + cprv = NR_CPUS; for (i = rcu_num_lvls - 1; i >= 0; i--) { ccur = rsp->levelcnt[i]; rsp->levelspread[i] = (cprv + ccur - 1) / ccur; @@ -2828,14 +2676,10 @@ static void __init rcu_init_levelspread(struct rcu_state *rsp) static void __init rcu_init_one(struct rcu_state *rsp, struct rcu_data __percpu *rda) { - static char *buf[] = { "rcu_node_0", - "rcu_node_1", - "rcu_node_2", - "rcu_node_3" }; /* Match MAX_RCU_LVLS */ - static char *fqs[] = { "rcu_node_fqs_0", - "rcu_node_fqs_1", - "rcu_node_fqs_2", - "rcu_node_fqs_3" }; /* Match MAX_RCU_LVLS */ + static char *buf[] = { "rcu_node_level_0", + "rcu_node_level_1", + "rcu_node_level_2", + "rcu_node_level_3" }; /* Match MAX_RCU_LVLS */ int cpustride = 1; int i; int j; @@ -2860,11 +2704,7 @@ static void __init rcu_init_one(struct rcu_state *rsp, raw_spin_lock_init(&rnp->lock); lockdep_set_class_and_name(&rnp->lock, &rcu_node_class[i], buf[i]); - raw_spin_lock_init(&rnp->fqslock); - lockdep_set_class_and_name(&rnp->fqslock, - &rcu_fqs_class[i], fqs[i]); - rnp->gpnum = rsp->gpnum; - rnp->completed = rsp->completed; + rnp->gpnum = 0; rnp->qsmask = 0; rnp->qsmaskinit = 0; rnp->grplo = j * cpustride; @@ -2887,7 +2727,6 @@ static void __init rcu_init_one(struct rcu_state *rsp, } rsp->rda = rda; - init_waitqueue_head(&rsp->gp_wq); rnp = rsp->level[rcu_num_lvls - 1]; for_each_possible_cpu(i) { while (i > rnp->grphi) @@ -2911,8 +2750,7 @@ static void __init rcu_init_geometry(void) int rcu_capacity[MAX_RCU_LVLS + 1]; /* If the compile-time values are accurate, just leave. */ - if (rcu_fanout_leaf == CONFIG_RCU_FANOUT_LEAF && - nr_cpu_ids == NR_CPUS) + if (rcu_fanout_leaf == CONFIG_RCU_FANOUT_LEAF) return; /* diff --git a/trunk/kernel/rcutree.h b/trunk/kernel/rcutree.h index 5faf05d68326..4d29169f2124 100644 --- a/trunk/kernel/rcutree.h +++ b/trunk/kernel/rcutree.h @@ -102,10 +102,6 @@ struct rcu_dynticks { /* idle-period nonlazy_posted snapshot. */ int tick_nohz_enabled_snap; /* Previously seen value from sysfs. */ #endif /* #ifdef CONFIG_RCU_FAST_NO_HZ */ -#ifdef CONFIG_RCU_USER_QS - bool ignore_user_qs; /* Treat userspace as extended QS or not */ - bool in_user; /* Is the CPU in userland from RCU POV? */ -#endif }; /* RCU's kthread states for tracing. */ @@ -200,7 +196,12 @@ struct rcu_node { /* Refused to boost: not sure why, though. */ /* This can happen due to race conditions. */ #endif /* #ifdef CONFIG_RCU_BOOST */ - raw_spinlock_t fqslock ____cacheline_internodealigned_in_smp; + struct task_struct *node_kthread_task; + /* kthread that takes care of this rcu_node */ + /* structure, for example, awakening the */ + /* per-CPU kthreads as needed. */ + unsigned int node_kthread_status; + /* State of node_kthread_task for tracing. */ } ____cacheline_internodealigned_in_smp; /* @@ -244,6 +245,8 @@ struct rcu_data { /* in order to detect GP end. */ unsigned long gpnum; /* Highest gp number that this CPU */ /* is aware of having started. */ + unsigned long passed_quiesce_gpnum; + /* gpnum at time of quiescent state. */ bool passed_quiesce; /* User-mode/idle loop etc. */ bool qs_pending; /* Core waits for quiesc state. */ bool beenonline; /* CPU online at least once. */ @@ -309,13 +312,11 @@ struct rcu_data { unsigned long n_rp_cpu_needs_gp; unsigned long n_rp_gp_completed; unsigned long n_rp_gp_started; + unsigned long n_rp_need_fqs; unsigned long n_rp_need_nothing; - /* 6) _rcu_barrier() and OOM callbacks. */ + /* 6) _rcu_barrier() callback. */ struct rcu_head barrier_head; -#ifdef CONFIG_RCU_FAST_NO_HZ - struct rcu_head oom_head; -#endif /* #ifdef CONFIG_RCU_FAST_NO_HZ */ int cpu; struct rcu_state *rsp; @@ -374,17 +375,20 @@ struct rcu_state { u8 fqs_state ____cacheline_internodealigned_in_smp; /* Force QS state. */ + u8 fqs_active; /* force_quiescent_state() */ + /* is running. */ + u8 fqs_need_gp; /* A CPU was prevented from */ + /* starting a new grace */ + /* period because */ + /* force_quiescent_state() */ + /* was running. */ u8 boost; /* Subject to priority boost. */ unsigned long gpnum; /* Current gp number. */ unsigned long completed; /* # of last completed gp. */ - struct task_struct *gp_kthread; /* Task for grace periods. */ - wait_queue_head_t gp_wq; /* Where GP task waits. */ - int gp_flags; /* Commands for GP task. */ /* End of fields guarded by root rcu_node's lock. */ - raw_spinlock_t onofflock ____cacheline_internodealigned_in_smp; - /* exclude on/offline and */ + raw_spinlock_t onofflock; /* exclude on/offline and */ /* starting new GP. */ struct rcu_head *orphan_nxtlist; /* Orphaned callbacks that */ /* need a grace period. */ @@ -394,11 +398,16 @@ struct rcu_state { struct rcu_head **orphan_donetail; /* Tail of above. */ long qlen_lazy; /* Number of lazy callbacks. */ long qlen; /* Total number of callbacks. */ + struct task_struct *rcu_barrier_in_progress; + /* Task doing rcu_barrier(), */ + /* or NULL if no barrier. */ struct mutex barrier_mutex; /* Guards barrier fields. */ atomic_t barrier_cpu_count; /* # CPUs waiting on. */ struct completion barrier_completion; /* Wake at barrier end. */ unsigned long n_barrier_done; /* ++ at start and end of */ /* _rcu_barrier(). */ + raw_spinlock_t fqslock; /* Only one task forcing */ + /* quiescent states. */ unsigned long jiffies_force_qs; /* Time at which to invoke */ /* force_quiescent_state(). */ unsigned long n_force_qs; /* Number of calls to */ @@ -417,10 +426,6 @@ struct rcu_state { struct list_head flavors; /* List of RCU flavors. */ }; -/* Values for rcu_state structure's gp_flags field. */ -#define RCU_GP_FLAG_INIT 0x1 /* Need grace-period initialization. */ -#define RCU_GP_FLAG_FQS 0x2 /* Need grace-period quiescent-state forcing. */ - extern struct list_head rcu_struct_flavors; #define for_each_rcu_flavor(rsp) \ list_for_each_entry((rsp), &rcu_struct_flavors, flavors) @@ -463,6 +468,7 @@ static int rcu_preempt_blocked_readers_cgp(struct rcu_node *rnp); #ifdef CONFIG_HOTPLUG_CPU static void rcu_report_unblock_qs_rnp(struct rcu_node *rnp, unsigned long flags); +static void rcu_stop_cpu_kthread(int cpu); #endif /* #ifdef CONFIG_HOTPLUG_CPU */ static void rcu_print_detail_task_stall(struct rcu_state *rsp); static int rcu_print_task_stall(struct rcu_node *rnp); @@ -485,9 +491,15 @@ static void invoke_rcu_callbacks_kthread(void); static bool rcu_is_callbacks_kthread(void); #ifdef CONFIG_RCU_BOOST static void rcu_preempt_do_callbacks(void); +static void rcu_boost_kthread_setaffinity(struct rcu_node *rnp, + cpumask_var_t cm); static int __cpuinit rcu_spawn_one_boost_kthread(struct rcu_state *rsp, - struct rcu_node *rnp); + struct rcu_node *rnp, + int rnp_index); +static void invoke_rcu_node_kthread(struct rcu_node *rnp); +static void rcu_yield(void (*f)(unsigned long), unsigned long arg); #endif /* #ifdef CONFIG_RCU_BOOST */ +static void rcu_cpu_kthread_setrt(int cpu, int to_rt); static void __cpuinit rcu_prepare_kthreads(int cpu); static void rcu_prepare_for_idle_init(int cpu); static void rcu_cleanup_after_idle(int cpu); diff --git a/trunk/kernel/rcutree_plugin.h b/trunk/kernel/rcutree_plugin.h index f92115488187..7f3244c0df01 100644 --- a/trunk/kernel/rcutree_plugin.h +++ b/trunk/kernel/rcutree_plugin.h @@ -25,8 +25,6 @@ */ #include -#include -#include #define RCU_KTHREAD_PRIO 1 @@ -120,7 +118,7 @@ EXPORT_SYMBOL_GPL(rcu_batches_completed); */ void rcu_force_quiescent_state(void) { - force_quiescent_state(&rcu_preempt_state); + force_quiescent_state(&rcu_preempt_state, 0); } EXPORT_SYMBOL_GPL(rcu_force_quiescent_state); @@ -138,6 +136,8 @@ static void rcu_preempt_qs(int cpu) { struct rcu_data *rdp = &per_cpu(rcu_preempt_data, cpu); + rdp->passed_quiesce_gpnum = rdp->gpnum; + barrier(); if (rdp->passed_quiesce == 0) trace_rcu_grace_period("rcu_preempt", rdp->gpnum, "cpuqs"); rdp->passed_quiesce = 1; @@ -422,11 +422,9 @@ static void rcu_print_detail_task_stall_rnp(struct rcu_node *rnp) unsigned long flags; struct task_struct *t; - raw_spin_lock_irqsave(&rnp->lock, flags); - if (!rcu_preempt_blocked_readers_cgp(rnp)) { - raw_spin_unlock_irqrestore(&rnp->lock, flags); + if (!rcu_preempt_blocked_readers_cgp(rnp)) return; - } + raw_spin_lock_irqsave(&rnp->lock, flags); t = list_entry(rnp->gp_tasks, struct task_struct, rcu_node_entry); list_for_each_entry_continue(t, &rnp->blkd_tasks, rcu_node_entry) @@ -586,23 +584,17 @@ static int rcu_preempt_offline_tasks(struct rcu_state *rsp, raw_spin_unlock(&rnp_root->lock); /* irqs still disabled */ } - rnp->gp_tasks = NULL; - rnp->exp_tasks = NULL; #ifdef CONFIG_RCU_BOOST - rnp->boost_tasks = NULL; - /* - * In case root is being boosted and leaf was not. Make sure - * that we boost the tasks blocking the current grace period - * in this case. - */ + /* In case root is being boosted and leaf is not. */ raw_spin_lock(&rnp_root->lock); /* irqs already disabled */ if (rnp_root->boost_tasks != NULL && - rnp_root->boost_tasks != rnp_root->gp_tasks && - rnp_root->boost_tasks != rnp_root->exp_tasks) + rnp_root->boost_tasks != rnp_root->gp_tasks) rnp_root->boost_tasks = rnp_root->gp_tasks; raw_spin_unlock(&rnp_root->lock); /* irqs still disabled */ #endif /* #ifdef CONFIG_RCU_BOOST */ + rnp->gp_tasks = NULL; + rnp->exp_tasks = NULL; return retval; } @@ -684,7 +676,7 @@ void synchronize_rcu(void) EXPORT_SYMBOL_GPL(synchronize_rcu); static DECLARE_WAIT_QUEUE_HEAD(sync_rcu_preempt_exp_wq); -static unsigned long sync_rcu_preempt_exp_count; +static long sync_rcu_preempt_exp_count; static DEFINE_MUTEX(sync_rcu_preempt_exp_mutex); /* @@ -799,55 +791,41 @@ void synchronize_rcu_expedited(void) unsigned long flags; struct rcu_node *rnp; struct rcu_state *rsp = &rcu_preempt_state; - unsigned long snap; + long snap; int trycount = 0; smp_mb(); /* Caller's modifications seen first by other CPUs. */ snap = ACCESS_ONCE(sync_rcu_preempt_exp_count) + 1; smp_mb(); /* Above access cannot bleed into critical section. */ - /* - * Block CPU-hotplug operations. This means that any CPU-hotplug - * operation that finds an rcu_node structure with tasks in the - * process of being boosted will know that all tasks blocking - * this expedited grace period will already be in the process of - * being boosted. This simplifies the process of moving tasks - * from leaf to root rcu_node structures. - */ - get_online_cpus(); - /* * Acquire lock, falling back to synchronize_rcu() if too many * lock-acquisition failures. Of course, if someone does the * expedited grace period for us, just leave. */ while (!mutex_trylock(&sync_rcu_preempt_exp_mutex)) { - if (ULONG_CMP_LT(snap, - ACCESS_ONCE(sync_rcu_preempt_exp_count))) { - put_online_cpus(); - goto mb_ret; /* Others did our work for us. */ - } if (trycount++ < 10) { udelay(trycount * num_online_cpus()); } else { - put_online_cpus(); synchronize_rcu(); return; } + if ((ACCESS_ONCE(sync_rcu_preempt_exp_count) - snap) > 0) + goto mb_ret; /* Others did our work for us. */ } - if (ULONG_CMP_LT(snap, ACCESS_ONCE(sync_rcu_preempt_exp_count))) { - put_online_cpus(); + if ((ACCESS_ONCE(sync_rcu_preempt_exp_count) - snap) > 0) goto unlock_mb_ret; /* Others did our work for us. */ - } /* force all RCU readers onto ->blkd_tasks lists. */ synchronize_sched_expedited(); + raw_spin_lock_irqsave(&rsp->onofflock, flags); + /* Initialize ->expmask for all non-leaf rcu_node structures. */ rcu_for_each_nonleaf_node_breadth_first(rsp, rnp) { - raw_spin_lock_irqsave(&rnp->lock, flags); + raw_spin_lock(&rnp->lock); /* irqs already disabled. */ rnp->expmask = rnp->qsmaskinit; - raw_spin_unlock_irqrestore(&rnp->lock, flags); + raw_spin_unlock(&rnp->lock); /* irqs remain disabled. */ } /* Snapshot current state of ->blkd_tasks lists. */ @@ -856,7 +834,7 @@ void synchronize_rcu_expedited(void) if (NUM_RCU_NODES > 1) sync_rcu_preempt_exp_init(rsp, rcu_get_root(rsp)); - put_online_cpus(); + raw_spin_unlock_irqrestore(&rsp->onofflock, flags); /* Wait for snapshotted ->blkd_tasks lists to drain. */ rnp = rcu_get_root(rsp); @@ -1091,16 +1069,6 @@ static void rcu_initiate_boost_trace(struct rcu_node *rnp) #endif /* #else #ifdef CONFIG_RCU_TRACE */ -static void rcu_wake_cond(struct task_struct *t, int status) -{ - /* - * If the thread is yielding, only wake it when this - * is invoked from idle - */ - if (status != RCU_KTHREAD_YIELDING || is_idle_task(current)) - wake_up_process(t); -} - /* * Carry out RCU priority boosting on the task indicated by ->exp_tasks * or ->boost_tasks, advancing the pointer to the next task in the @@ -1172,6 +1140,17 @@ static int rcu_boost(struct rcu_node *rnp) ACCESS_ONCE(rnp->boost_tasks) != NULL; } +/* + * Timer handler to initiate waking up of boost kthreads that + * have yielded the CPU due to excessive numbers of tasks to + * boost. We wake up the per-rcu_node kthread, which in turn + * will wake up the booster kthread. + */ +static void rcu_boost_kthread_timer(unsigned long arg) +{ + invoke_rcu_node_kthread((struct rcu_node *)arg); +} + /* * Priority-boosting kthread. One per leaf rcu_node and one for the * root rcu_node. @@ -1195,9 +1174,8 @@ static int rcu_boost_kthread(void *arg) else spincnt = 0; if (spincnt > 10) { - rnp->boost_kthread_status = RCU_KTHREAD_YIELDING; trace_rcu_utilization("End boost kthread@rcu_yield"); - schedule_timeout_interruptible(2); + rcu_yield(rcu_boost_kthread_timer, (unsigned long)rnp); trace_rcu_utilization("Start boost kthread@rcu_yield"); spincnt = 0; } @@ -1213,9 +1191,9 @@ static int rcu_boost_kthread(void *arg) * kthread to start boosting them. If there is an expedited grace * period in progress, it is always time to boost. * - * The caller must hold rnp->lock, which this function releases. - * The ->boost_kthread_task is immortal, so we don't need to worry - * about it going away. + * The caller must hold rnp->lock, which this function releases, + * but irqs remain disabled. The ->boost_kthread_task is immortal, + * so we don't need to worry about it going away. */ static void rcu_initiate_boost(struct rcu_node *rnp, unsigned long flags) { @@ -1235,8 +1213,8 @@ static void rcu_initiate_boost(struct rcu_node *rnp, unsigned long flags) rnp->boost_tasks = rnp->gp_tasks; raw_spin_unlock_irqrestore(&rnp->lock, flags); t = rnp->boost_kthread_task; - if (t) - rcu_wake_cond(t, rnp->boost_kthread_status); + if (t != NULL) + wake_up_process(t); } else { rcu_initiate_boost_trace(rnp); raw_spin_unlock_irqrestore(&rnp->lock, flags); @@ -1253,10 +1231,8 @@ static void invoke_rcu_callbacks_kthread(void) local_irq_save(flags); __this_cpu_write(rcu_cpu_has_work, 1); if (__this_cpu_read(rcu_cpu_kthread_task) != NULL && - current != __this_cpu_read(rcu_cpu_kthread_task)) { - rcu_wake_cond(__this_cpu_read(rcu_cpu_kthread_task), - __this_cpu_read(rcu_cpu_kthread_status)); - } + current != __this_cpu_read(rcu_cpu_kthread_task)) + wake_up_process(__this_cpu_read(rcu_cpu_kthread_task)); local_irq_restore(flags); } @@ -1269,6 +1245,21 @@ static bool rcu_is_callbacks_kthread(void) return __get_cpu_var(rcu_cpu_kthread_task) == current; } +/* + * Set the affinity of the boost kthread. The CPU-hotplug locks are + * held, so no one should be messing with the existence of the boost + * kthread. + */ +static void rcu_boost_kthread_setaffinity(struct rcu_node *rnp, + cpumask_var_t cm) +{ + struct task_struct *t; + + t = rnp->boost_kthread_task; + if (t != NULL) + set_cpus_allowed_ptr(rnp->boost_kthread_task, cm); +} + #define RCU_BOOST_DELAY_JIFFIES DIV_ROUND_UP(CONFIG_RCU_BOOST_DELAY * HZ, 1000) /* @@ -1285,19 +1276,15 @@ static void rcu_preempt_boost_start_gp(struct rcu_node *rnp) * Returns zero if all is well, a negated errno otherwise. */ static int __cpuinit rcu_spawn_one_boost_kthread(struct rcu_state *rsp, - struct rcu_node *rnp) + struct rcu_node *rnp, + int rnp_index) { - int rnp_index = rnp - &rsp->node[0]; unsigned long flags; struct sched_param sp; struct task_struct *t; if (&rcu_preempt_state != rsp) return 0; - - if (!rcu_scheduler_fully_active || rnp->qsmaskinit == 0) - return 0; - rsp->boost = 1; if (rnp->boost_kthread_task != NULL) return 0; @@ -1314,6 +1301,25 @@ static int __cpuinit rcu_spawn_one_boost_kthread(struct rcu_state *rsp, return 0; } +#ifdef CONFIG_HOTPLUG_CPU + +/* + * Stop the RCU's per-CPU kthread when its CPU goes offline,. + */ +static void rcu_stop_cpu_kthread(int cpu) +{ + struct task_struct *t; + + /* Stop the CPU's kthread. */ + t = per_cpu(rcu_cpu_kthread_task, cpu); + if (t != NULL) { + per_cpu(rcu_cpu_kthread_task, cpu) = NULL; + kthread_stop(t); + } +} + +#endif /* #ifdef CONFIG_HOTPLUG_CPU */ + static void rcu_kthread_do_work(void) { rcu_do_batch(&rcu_sched_state, &__get_cpu_var(rcu_sched_data)); @@ -1321,22 +1327,112 @@ static void rcu_kthread_do_work(void) rcu_preempt_do_callbacks(); } -static void rcu_cpu_kthread_setup(unsigned int cpu) +/* + * Wake up the specified per-rcu_node-structure kthread. + * Because the per-rcu_node kthreads are immortal, we don't need + * to do anything to keep them alive. + */ +static void invoke_rcu_node_kthread(struct rcu_node *rnp) +{ + struct task_struct *t; + + t = rnp->node_kthread_task; + if (t != NULL) + wake_up_process(t); +} + +/* + * Set the specified CPU's kthread to run RT or not, as specified by + * the to_rt argument. The CPU-hotplug locks are held, so the task + * is not going away. + */ +static void rcu_cpu_kthread_setrt(int cpu, int to_rt) { + int policy; struct sched_param sp; + struct task_struct *t; - sp.sched_priority = RCU_KTHREAD_PRIO; - sched_setscheduler_nocheck(current, SCHED_FIFO, &sp); + t = per_cpu(rcu_cpu_kthread_task, cpu); + if (t == NULL) + return; + if (to_rt) { + policy = SCHED_FIFO; + sp.sched_priority = RCU_KTHREAD_PRIO; + } else { + policy = SCHED_NORMAL; + sp.sched_priority = 0; + } + sched_setscheduler_nocheck(t, policy, &sp); } -static void rcu_cpu_kthread_park(unsigned int cpu) +/* + * Timer handler to initiate the waking up of per-CPU kthreads that + * have yielded the CPU due to excess numbers of RCU callbacks. + * We wake up the per-rcu_node kthread, which in turn will wake up + * the booster kthread. + */ +static void rcu_cpu_kthread_timer(unsigned long arg) { - per_cpu(rcu_cpu_kthread_status, cpu) = RCU_KTHREAD_OFFCPU; + struct rcu_data *rdp = per_cpu_ptr(rcu_state->rda, arg); + struct rcu_node *rnp = rdp->mynode; + + atomic_or(rdp->grpmask, &rnp->wakemask); + invoke_rcu_node_kthread(rnp); } -static int rcu_cpu_kthread_should_run(unsigned int cpu) +/* + * Drop to non-real-time priority and yield, but only after posting a + * timer that will cause us to regain our real-time priority if we + * remain preempted. Either way, we restore our real-time priority + * before returning. + */ +static void rcu_yield(void (*f)(unsigned long), unsigned long arg) { - return __get_cpu_var(rcu_cpu_has_work); + struct sched_param sp; + struct timer_list yield_timer; + int prio = current->rt_priority; + + setup_timer_on_stack(&yield_timer, f, arg); + mod_timer(&yield_timer, jiffies + 2); + sp.sched_priority = 0; + sched_setscheduler_nocheck(current, SCHED_NORMAL, &sp); + set_user_nice(current, 19); + schedule(); + set_user_nice(current, 0); + sp.sched_priority = prio; + sched_setscheduler_nocheck(current, SCHED_FIFO, &sp); + del_timer(&yield_timer); +} + +/* + * Handle cases where the rcu_cpu_kthread() ends up on the wrong CPU. + * This can happen while the corresponding CPU is either coming online + * or going offline. We cannot wait until the CPU is fully online + * before starting the kthread, because the various notifier functions + * can wait for RCU grace periods. So we park rcu_cpu_kthread() until + * the corresponding CPU is online. + * + * Return 1 if the kthread needs to stop, 0 otherwise. + * + * Caller must disable bh. This function can momentarily enable it. + */ +static int rcu_cpu_kthread_should_stop(int cpu) +{ + while (cpu_is_offline(cpu) || + !cpumask_equal(¤t->cpus_allowed, cpumask_of(cpu)) || + smp_processor_id() != cpu) { + if (kthread_should_stop()) + return 1; + per_cpu(rcu_cpu_kthread_status, cpu) = RCU_KTHREAD_OFFCPU; + per_cpu(rcu_cpu_kthread_cpu, cpu) = raw_smp_processor_id(); + local_bh_enable(); + schedule_timeout_uninterruptible(1); + if (!cpumask_equal(¤t->cpus_allowed, cpumask_of(cpu))) + set_cpus_allowed_ptr(current, cpumask_of(cpu)); + local_bh_disable(); + } + per_cpu(rcu_cpu_kthread_cpu, cpu) = cpu; + return 0; } /* @@ -1344,35 +1440,138 @@ static int rcu_cpu_kthread_should_run(unsigned int cpu) * RCU softirq used in flavors and configurations of RCU that do not * support RCU priority boosting. */ -static void rcu_cpu_kthread(unsigned int cpu) +static int rcu_cpu_kthread(void *arg) { - unsigned int *statusp = &__get_cpu_var(rcu_cpu_kthread_status); - char work, *workp = &__get_cpu_var(rcu_cpu_has_work); - int spincnt; + int cpu = (int)(long)arg; + unsigned long flags; + int spincnt = 0; + unsigned int *statusp = &per_cpu(rcu_cpu_kthread_status, cpu); + char work; + char *workp = &per_cpu(rcu_cpu_has_work, cpu); - for (spincnt = 0; spincnt < 10; spincnt++) { + trace_rcu_utilization("Start CPU kthread@init"); + for (;;) { + *statusp = RCU_KTHREAD_WAITING; + trace_rcu_utilization("End CPU kthread@rcu_wait"); + rcu_wait(*workp != 0 || kthread_should_stop()); trace_rcu_utilization("Start CPU kthread@rcu_wait"); local_bh_disable(); + if (rcu_cpu_kthread_should_stop(cpu)) { + local_bh_enable(); + break; + } *statusp = RCU_KTHREAD_RUNNING; - this_cpu_inc(rcu_cpu_kthread_loops); - local_irq_disable(); + per_cpu(rcu_cpu_kthread_loops, cpu)++; + local_irq_save(flags); work = *workp; *workp = 0; - local_irq_enable(); + local_irq_restore(flags); if (work) rcu_kthread_do_work(); local_bh_enable(); - if (*workp == 0) { - trace_rcu_utilization("End CPU kthread@rcu_wait"); - *statusp = RCU_KTHREAD_WAITING; - return; + if (*workp != 0) + spincnt++; + else + spincnt = 0; + if (spincnt > 10) { + *statusp = RCU_KTHREAD_YIELDING; + trace_rcu_utilization("End CPU kthread@rcu_yield"); + rcu_yield(rcu_cpu_kthread_timer, (unsigned long)cpu); + trace_rcu_utilization("Start CPU kthread@rcu_yield"); + spincnt = 0; + } + } + *statusp = RCU_KTHREAD_STOPPED; + trace_rcu_utilization("End CPU kthread@term"); + return 0; +} + +/* + * Spawn a per-CPU kthread, setting up affinity and priority. + * Because the CPU hotplug lock is held, no other CPU will be attempting + * to manipulate rcu_cpu_kthread_task. There might be another CPU + * attempting to access it during boot, but the locking in kthread_bind() + * will enforce sufficient ordering. + * + * Please note that we cannot simply refuse to wake up the per-CPU + * kthread because kthreads are created in TASK_UNINTERRUPTIBLE state, + * which can result in softlockup complaints if the task ends up being + * idle for more than a couple of minutes. + * + * However, please note also that we cannot bind the per-CPU kthread to its + * CPU until that CPU is fully online. We also cannot wait until the + * CPU is fully online before we create its per-CPU kthread, as this would + * deadlock the system when CPU notifiers tried waiting for grace + * periods. So we bind the per-CPU kthread to its CPU only if the CPU + * is online. If its CPU is not yet fully online, then the code in + * rcu_cpu_kthread() will wait until it is fully online, and then do + * the binding. + */ +static int __cpuinit rcu_spawn_one_cpu_kthread(int cpu) +{ + struct sched_param sp; + struct task_struct *t; + + if (!rcu_scheduler_fully_active || + per_cpu(rcu_cpu_kthread_task, cpu) != NULL) + return 0; + t = kthread_create_on_node(rcu_cpu_kthread, + (void *)(long)cpu, + cpu_to_node(cpu), + "rcuc/%d", cpu); + if (IS_ERR(t)) + return PTR_ERR(t); + if (cpu_online(cpu)) + kthread_bind(t, cpu); + per_cpu(rcu_cpu_kthread_cpu, cpu) = cpu; + WARN_ON_ONCE(per_cpu(rcu_cpu_kthread_task, cpu) != NULL); + sp.sched_priority = RCU_KTHREAD_PRIO; + sched_setscheduler_nocheck(t, SCHED_FIFO, &sp); + per_cpu(rcu_cpu_kthread_task, cpu) = t; + wake_up_process(t); /* Get to TASK_INTERRUPTIBLE quickly. */ + return 0; +} + +/* + * Per-rcu_node kthread, which is in charge of waking up the per-CPU + * kthreads when needed. We ignore requests to wake up kthreads + * for offline CPUs, which is OK because force_quiescent_state() + * takes care of this case. + */ +static int rcu_node_kthread(void *arg) +{ + int cpu; + unsigned long flags; + unsigned long mask; + struct rcu_node *rnp = (struct rcu_node *)arg; + struct sched_param sp; + struct task_struct *t; + + for (;;) { + rnp->node_kthread_status = RCU_KTHREAD_WAITING; + rcu_wait(atomic_read(&rnp->wakemask) != 0); + rnp->node_kthread_status = RCU_KTHREAD_RUNNING; + raw_spin_lock_irqsave(&rnp->lock, flags); + mask = atomic_xchg(&rnp->wakemask, 0); + rcu_initiate_boost(rnp, flags); /* releases rnp->lock. */ + for (cpu = rnp->grplo; cpu <= rnp->grphi; cpu++, mask >>= 1) { + if ((mask & 0x1) == 0) + continue; + preempt_disable(); + t = per_cpu(rcu_cpu_kthread_task, cpu); + if (!cpu_online(cpu) || t == NULL) { + preempt_enable(); + continue; + } + per_cpu(rcu_cpu_has_work, cpu) = 1; + sp.sched_priority = RCU_KTHREAD_PRIO; + sched_setscheduler_nocheck(t, SCHED_FIFO, &sp); + preempt_enable(); } } - *statusp = RCU_KTHREAD_YIELDING; - trace_rcu_utilization("Start CPU kthread@rcu_yield"); - schedule_timeout_interruptible(2); - trace_rcu_utilization("End CPU kthread@rcu_yield"); - *statusp = RCU_KTHREAD_WAITING; + /* NOTREACHED */ + rnp->node_kthread_status = RCU_KTHREAD_STOPPED; + return 0; } /* @@ -1384,17 +1583,17 @@ static void rcu_cpu_kthread(unsigned int cpu) * no outgoing CPU. If there are no CPUs left in the affinity set, * this function allows the kthread to execute on any CPU. */ -static void rcu_boost_kthread_setaffinity(struct rcu_node *rnp, int outgoingcpu) +static void rcu_node_kthread_setaffinity(struct rcu_node *rnp, int outgoingcpu) { - struct task_struct *t = rnp->boost_kthread_task; - unsigned long mask = rnp->qsmaskinit; cpumask_var_t cm; int cpu; + unsigned long mask = rnp->qsmaskinit; - if (!t) + if (rnp->node_kthread_task == NULL) return; - if (!zalloc_cpumask_var(&cm, GFP_KERNEL)) + if (!alloc_cpumask_var(&cm, GFP_KERNEL)) return; + cpumask_clear(cm); for (cpu = rnp->grplo; cpu <= rnp->grphi; cpu++, mask >>= 1) if ((mask & 0x1) && cpu != outgoingcpu) cpumask_set_cpu(cpu, cm); @@ -1404,36 +1603,62 @@ static void rcu_boost_kthread_setaffinity(struct rcu_node *rnp, int outgoingcpu) cpumask_clear_cpu(cpu, cm); WARN_ON_ONCE(cpumask_weight(cm) == 0); } - set_cpus_allowed_ptr(t, cm); + set_cpus_allowed_ptr(rnp->node_kthread_task, cm); + rcu_boost_kthread_setaffinity(rnp, cm); free_cpumask_var(cm); } -static struct smp_hotplug_thread rcu_cpu_thread_spec = { - .store = &rcu_cpu_kthread_task, - .thread_should_run = rcu_cpu_kthread_should_run, - .thread_fn = rcu_cpu_kthread, - .thread_comm = "rcuc/%u", - .setup = rcu_cpu_kthread_setup, - .park = rcu_cpu_kthread_park, -}; +/* + * Spawn a per-rcu_node kthread, setting priority and affinity. + * Called during boot before online/offline can happen, or, if + * during runtime, with the main CPU-hotplug locks held. So only + * one of these can be executing at a time. + */ +static int __cpuinit rcu_spawn_one_node_kthread(struct rcu_state *rsp, + struct rcu_node *rnp) +{ + unsigned long flags; + int rnp_index = rnp - &rsp->node[0]; + struct sched_param sp; + struct task_struct *t; + + if (!rcu_scheduler_fully_active || + rnp->qsmaskinit == 0) + return 0; + if (rnp->node_kthread_task == NULL) { + t = kthread_create(rcu_node_kthread, (void *)rnp, + "rcun/%d", rnp_index); + if (IS_ERR(t)) + return PTR_ERR(t); + raw_spin_lock_irqsave(&rnp->lock, flags); + rnp->node_kthread_task = t; + raw_spin_unlock_irqrestore(&rnp->lock, flags); + sp.sched_priority = 99; + sched_setscheduler_nocheck(t, SCHED_FIFO, &sp); + wake_up_process(t); /* get to TASK_INTERRUPTIBLE quickly. */ + } + return rcu_spawn_one_boost_kthread(rsp, rnp, rnp_index); +} /* * Spawn all kthreads -- called as soon as the scheduler is running. */ static int __init rcu_spawn_kthreads(void) { - struct rcu_node *rnp; int cpu; + struct rcu_node *rnp; rcu_scheduler_fully_active = 1; - for_each_possible_cpu(cpu) + for_each_possible_cpu(cpu) { per_cpu(rcu_cpu_has_work, cpu) = 0; - BUG_ON(smpboot_register_percpu_thread(&rcu_cpu_thread_spec)); + if (cpu_online(cpu)) + (void)rcu_spawn_one_cpu_kthread(cpu); + } rnp = rcu_get_root(rcu_state); - (void)rcu_spawn_one_boost_kthread(rcu_state, rnp); + (void)rcu_spawn_one_node_kthread(rcu_state, rnp); if (NUM_RCU_NODES > 1) { rcu_for_each_leaf_node(rcu_state, rnp) - (void)rcu_spawn_one_boost_kthread(rcu_state, rnp); + (void)rcu_spawn_one_node_kthread(rcu_state, rnp); } return 0; } @@ -1445,8 +1670,11 @@ static void __cpuinit rcu_prepare_kthreads(int cpu) struct rcu_node *rnp = rdp->mynode; /* Fire up the incoming CPU's kthread and leaf rcu_node kthread. */ - if (rcu_scheduler_fully_active) - (void)rcu_spawn_one_boost_kthread(rcu_state, rnp); + if (rcu_scheduler_fully_active) { + (void)rcu_spawn_one_cpu_kthread(cpu); + if (rnp->node_kthread_task == NULL) + (void)rcu_spawn_one_node_kthread(rcu_state, rnp); + } } #else /* #ifdef CONFIG_RCU_BOOST */ @@ -1470,7 +1698,19 @@ static void rcu_preempt_boost_start_gp(struct rcu_node *rnp) { } -static void rcu_boost_kthread_setaffinity(struct rcu_node *rnp, int outgoingcpu) +#ifdef CONFIG_HOTPLUG_CPU + +static void rcu_stop_cpu_kthread(int cpu) +{ +} + +#endif /* #ifdef CONFIG_HOTPLUG_CPU */ + +static void rcu_node_kthread_setaffinity(struct rcu_node *rnp, int outgoingcpu) +{ +} + +static void rcu_cpu_kthread_setrt(int cpu, int to_rt) { } @@ -1757,26 +1997,6 @@ static void rcu_prepare_for_idle(int cpu) if (!tne) return; - /* Adaptive-tick mode, where usermode execution is idle to RCU. */ - if (!is_idle_task(current)) { - rdtp->dyntick_holdoff = jiffies - 1; - if (rcu_cpu_has_nonlazy_callbacks(cpu)) { - trace_rcu_prep_idle("User dyntick with callbacks"); - rdtp->idle_gp_timer_expires = - round_up(jiffies + RCU_IDLE_GP_DELAY, - RCU_IDLE_GP_DELAY); - } else if (rcu_cpu_has_callbacks(cpu)) { - rdtp->idle_gp_timer_expires = - round_jiffies(jiffies + RCU_IDLE_LAZY_GP_DELAY); - trace_rcu_prep_idle("User dyntick with lazy callbacks"); - } else { - return; - } - tp = &rdtp->idle_gp_timer; - mod_timer_pinned(tp, rdtp->idle_gp_timer_expires); - return; - } - /* * If this is an idle re-entry, for example, due to use of * RCU_NONIDLE() or the new idle-loop tracing API within the idle @@ -1855,16 +2075,16 @@ static void rcu_prepare_for_idle(int cpu) #ifdef CONFIG_TREE_PREEMPT_RCU if (per_cpu(rcu_preempt_data, cpu).nxtlist) { rcu_preempt_qs(cpu); - force_quiescent_state(&rcu_preempt_state); + force_quiescent_state(&rcu_preempt_state, 0); } #endif /* #ifdef CONFIG_TREE_PREEMPT_RCU */ if (per_cpu(rcu_sched_data, cpu).nxtlist) { rcu_sched_qs(cpu); - force_quiescent_state(&rcu_sched_state); + force_quiescent_state(&rcu_sched_state, 0); } if (per_cpu(rcu_bh_data, cpu).nxtlist) { rcu_bh_qs(cpu); - force_quiescent_state(&rcu_bh_state); + force_quiescent_state(&rcu_bh_state, 0); } /* @@ -1892,88 +2112,6 @@ static void rcu_idle_count_callbacks_posted(void) __this_cpu_add(rcu_dynticks.nonlazy_posted, 1); } -/* - * Data for flushing lazy RCU callbacks at OOM time. - */ -static atomic_t oom_callback_count; -static DECLARE_WAIT_QUEUE_HEAD(oom_callback_wq); - -/* - * RCU OOM callback -- decrement the outstanding count and deliver the - * wake-up if we are the last one. - */ -static void rcu_oom_callback(struct rcu_head *rhp) -{ - if (atomic_dec_and_test(&oom_callback_count)) - wake_up(&oom_callback_wq); -} - -/* - * Post an rcu_oom_notify callback on the current CPU if it has at - * least one lazy callback. This will unnecessarily post callbacks - * to CPUs that already have a non-lazy callback at the end of their - * callback list, but this is an infrequent operation, so accept some - * extra overhead to keep things simple. - */ -static void rcu_oom_notify_cpu(void *unused) -{ - struct rcu_state *rsp; - struct rcu_data *rdp; - - for_each_rcu_flavor(rsp) { - rdp = __this_cpu_ptr(rsp->rda); - if (rdp->qlen_lazy != 0) { - atomic_inc(&oom_callback_count); - rsp->call(&rdp->oom_head, rcu_oom_callback); - } - } -} - -/* - * If low on memory, ensure that each CPU has a non-lazy callback. - * This will wake up CPUs that have only lazy callbacks, in turn - * ensuring that they free up the corresponding memory in a timely manner. - * Because an uncertain amount of memory will be freed in some uncertain - * timeframe, we do not claim to have freed anything. - */ -static int rcu_oom_notify(struct notifier_block *self, - unsigned long notused, void *nfreed) -{ - int cpu; - - /* Wait for callbacks from earlier instance to complete. */ - wait_event(oom_callback_wq, atomic_read(&oom_callback_count) == 0); - - /* - * Prevent premature wakeup: ensure that all increments happen - * before there is a chance of the counter reaching zero. - */ - atomic_set(&oom_callback_count, 1); - - get_online_cpus(); - for_each_online_cpu(cpu) { - smp_call_function_single(cpu, rcu_oom_notify_cpu, NULL, 1); - cond_resched(); - } - put_online_cpus(); - - /* Unconditionally decrement: no need to wake ourselves up. */ - atomic_dec(&oom_callback_count); - - return NOTIFY_OK; -} - -static struct notifier_block rcu_oom_nb = { - .notifier_call = rcu_oom_notify -}; - -static int __init rcu_register_oom_notifier(void) -{ - register_oom_notifier(&rcu_oom_nb); - return 0; -} -early_initcall(rcu_register_oom_notifier); - #endif /* #else #if !defined(CONFIG_RCU_FAST_NO_HZ) */ #ifdef CONFIG_RCU_CPU_STALL_INFO @@ -1984,15 +2122,11 @@ static void print_cpu_stall_fast_no_hz(char *cp, int cpu) { struct rcu_dynticks *rdtp = &per_cpu(rcu_dynticks, cpu); struct timer_list *tltp = &rdtp->idle_gp_timer; - char c; - c = rdtp->dyntick_holdoff == jiffies ? 'H' : '.'; - if (timer_pending(tltp)) - sprintf(cp, "drain=%d %c timer=%lu", - rdtp->dyntick_drain, c, tltp->expires - jiffies); - else - sprintf(cp, "drain=%d %c timer not pending", - rdtp->dyntick_drain, c); + sprintf(cp, "drain=%d %c timer=%lu", + rdtp->dyntick_drain, + rdtp->dyntick_holdoff == jiffies ? 'H' : '.', + timer_pending(tltp) ? tltp->expires - jiffies : -1); } #else /* #ifdef CONFIG_RCU_FAST_NO_HZ */ @@ -2060,10 +2194,11 @@ static void zero_cpu_stall_ticks(struct rcu_data *rdp) /* Increment ->ticks_this_gp for all flavors of RCU. */ static void increment_cpu_stall_ticks(void) { - struct rcu_state *rsp; - - for_each_rcu_flavor(rsp) - __this_cpu_ptr(rsp->rda)->ticks_this_gp++; + __get_cpu_var(rcu_sched_data).ticks_this_gp++; + __get_cpu_var(rcu_bh_data).ticks_this_gp++; +#ifdef CONFIG_TREE_PREEMPT_RCU + __get_cpu_var(rcu_preempt_data).ticks_this_gp++; +#endif /* #ifdef CONFIG_TREE_PREEMPT_RCU */ } #else /* #ifdef CONFIG_RCU_CPU_STALL_INFO */ diff --git a/trunk/kernel/rcutree_trace.c b/trunk/kernel/rcutree_trace.c index 693513bc50e6..abffb486e94e 100644 --- a/trunk/kernel/rcutree_trace.c +++ b/trunk/kernel/rcutree_trace.c @@ -51,8 +51,8 @@ static int show_rcubarrier(struct seq_file *m, void *unused) struct rcu_state *rsp; for_each_rcu_flavor(rsp) - seq_printf(m, "%s: bcc: %d nbd: %lu\n", - rsp->name, + seq_printf(m, "%s: %c bcc: %d nbd: %lu\n", + rsp->name, rsp->rcu_barrier_in_progress ? 'B' : '.', atomic_read(&rsp->barrier_cpu_count), rsp->n_barrier_done); return 0; @@ -86,11 +86,12 @@ static void print_one_rcu_data(struct seq_file *m, struct rcu_data *rdp) { if (!rdp->beenonline) return; - seq_printf(m, "%3d%cc=%lu g=%lu pq=%d qp=%d", + seq_printf(m, "%3d%cc=%lu g=%lu pq=%d pgp=%lu qp=%d", rdp->cpu, cpu_is_offline(rdp->cpu) ? '!' : ' ', rdp->completed, rdp->gpnum, - rdp->passed_quiesce, rdp->qs_pending); + rdp->passed_quiesce, rdp->passed_quiesce_gpnum, + rdp->qs_pending); seq_printf(m, " dt=%d/%llx/%d df=%lu", atomic_read(&rdp->dynticks->dynticks), rdp->dynticks->dynticks_nesting, @@ -107,10 +108,11 @@ static void print_one_rcu_data(struct seq_file *m, struct rcu_data *rdp) rdp->nxttail[RCU_WAIT_TAIL]], ".D"[&rdp->nxtlist != rdp->nxttail[RCU_DONE_TAIL]]); #ifdef CONFIG_RCU_BOOST - seq_printf(m, " kt=%d/%c ktl=%x", + seq_printf(m, " kt=%d/%c/%d ktl=%x", per_cpu(rcu_cpu_has_work, rdp->cpu), convert_kthread_status(per_cpu(rcu_cpu_kthread_status, rdp->cpu)), + per_cpu(rcu_cpu_kthread_cpu, rdp->cpu), per_cpu(rcu_cpu_kthread_loops, rdp->cpu) & 0xffff); #endif /* #ifdef CONFIG_RCU_BOOST */ seq_printf(m, " b=%ld", rdp->blimit); @@ -148,11 +150,12 @@ static void print_one_rcu_data_csv(struct seq_file *m, struct rcu_data *rdp) { if (!rdp->beenonline) return; - seq_printf(m, "%d,%s,%lu,%lu,%d,%d", + seq_printf(m, "%d,%s,%lu,%lu,%d,%lu,%d", rdp->cpu, cpu_is_offline(rdp->cpu) ? "\"N\"" : "\"Y\"", rdp->completed, rdp->gpnum, - rdp->passed_quiesce, rdp->qs_pending); + rdp->passed_quiesce, rdp->passed_quiesce_gpnum, + rdp->qs_pending); seq_printf(m, ",%d,%llx,%d,%lu", atomic_read(&rdp->dynticks->dynticks), rdp->dynticks->dynticks_nesting, @@ -183,7 +186,7 @@ static int show_rcudata_csv(struct seq_file *m, void *unused) int cpu; struct rcu_state *rsp; - seq_puts(m, "\"CPU\",\"Online?\",\"c\",\"g\",\"pq\",\"pq\","); + seq_puts(m, "\"CPU\",\"Online?\",\"c\",\"g\",\"pq\",\"pgp\",\"pq\","); seq_puts(m, "\"dt\",\"dt nesting\",\"dt NMI nesting\",\"df\","); seq_puts(m, "\"of\",\"qll\",\"ql\",\"qs\""); #ifdef CONFIG_RCU_BOOST @@ -383,9 +386,10 @@ static void print_one_rcu_pending(struct seq_file *m, struct rcu_data *rdp) rdp->n_rp_report_qs, rdp->n_rp_cb_ready, rdp->n_rp_cpu_needs_gp); - seq_printf(m, "gpc=%ld gps=%ld nn=%ld\n", + seq_printf(m, "gpc=%ld gps=%ld nf=%ld nn=%ld\n", rdp->n_rp_gp_completed, rdp->n_rp_gp_started, + rdp->n_rp_need_fqs, rdp->n_rp_need_nothing); } diff --git a/trunk/kernel/sched/Makefile b/trunk/kernel/sched/Makefile index f06d249e103b..173ea52f3af0 100644 --- a/trunk/kernel/sched/Makefile +++ b/trunk/kernel/sched/Makefile @@ -11,7 +11,7 @@ ifneq ($(CONFIG_SCHED_OMIT_FRAME_POINTER),y) CFLAGS_core.o := $(PROFILING) -fno-omit-frame-pointer endif -obj-y += core.o clock.o cputime.o idle_task.o fair.o rt.o stop_task.o +obj-y += core.o clock.o idle_task.o fair.o rt.o stop_task.o obj-$(CONFIG_SMP) += cpupri.o obj-$(CONFIG_SCHED_AUTOGROUP) += auto_group.o obj-$(CONFIG_SCHEDSTATS) += stats.o diff --git a/trunk/kernel/sched/core.c b/trunk/kernel/sched/core.c index c17747236438..d325c4b2dcbb 100644 --- a/trunk/kernel/sched/core.c +++ b/trunk/kernel/sched/core.c @@ -740,6 +740,126 @@ void deactivate_task(struct rq *rq, struct task_struct *p, int flags) dequeue_task(rq, p, flags); } +#ifdef CONFIG_IRQ_TIME_ACCOUNTING + +/* + * There are no locks covering percpu hardirq/softirq time. + * They are only modified in account_system_vtime, on corresponding CPU + * with interrupts disabled. So, writes are safe. + * They are read and saved off onto struct rq in update_rq_clock(). + * This may result in other CPU reading this CPU's irq time and can + * race with irq/account_system_vtime on this CPU. We would either get old + * or new value with a side effect of accounting a slice of irq time to wrong + * task when irq is in progress while we read rq->clock. That is a worthy + * compromise in place of having locks on each irq in account_system_time. + */ +static DEFINE_PER_CPU(u64, cpu_hardirq_time); +static DEFINE_PER_CPU(u64, cpu_softirq_time); + +static DEFINE_PER_CPU(u64, irq_start_time); +static int sched_clock_irqtime; + +void enable_sched_clock_irqtime(void) +{ + sched_clock_irqtime = 1; +} + +void disable_sched_clock_irqtime(void) +{ + sched_clock_irqtime = 0; +} + +#ifndef CONFIG_64BIT +static DEFINE_PER_CPU(seqcount_t, irq_time_seq); + +static inline void irq_time_write_begin(void) +{ + __this_cpu_inc(irq_time_seq.sequence); + smp_wmb(); +} + +static inline void irq_time_write_end(void) +{ + smp_wmb(); + __this_cpu_inc(irq_time_seq.sequence); +} + +static inline u64 irq_time_read(int cpu) +{ + u64 irq_time; + unsigned seq; + + do { + seq = read_seqcount_begin(&per_cpu(irq_time_seq, cpu)); + irq_time = per_cpu(cpu_softirq_time, cpu) + + per_cpu(cpu_hardirq_time, cpu); + } while (read_seqcount_retry(&per_cpu(irq_time_seq, cpu), seq)); + + return irq_time; +} +#else /* CONFIG_64BIT */ +static inline void irq_time_write_begin(void) +{ +} + +static inline void irq_time_write_end(void) +{ +} + +static inline u64 irq_time_read(int cpu) +{ + return per_cpu(cpu_softirq_time, cpu) + per_cpu(cpu_hardirq_time, cpu); +} +#endif /* CONFIG_64BIT */ + +/* + * Called before incrementing preempt_count on {soft,}irq_enter + * and before decrementing preempt_count on {soft,}irq_exit. + */ +void account_system_vtime(struct task_struct *curr) +{ + unsigned long flags; + s64 delta; + int cpu; + + if (!sched_clock_irqtime) + return; + + local_irq_save(flags); + + cpu = smp_processor_id(); + delta = sched_clock_cpu(cpu) - __this_cpu_read(irq_start_time); + __this_cpu_add(irq_start_time, delta); + + irq_time_write_begin(); + /* + * We do not account for softirq time from ksoftirqd here. + * We want to continue accounting softirq time to ksoftirqd thread + * in that case, so as not to confuse scheduler with a special task + * that do not consume any time, but still wants to run. + */ + if (hardirq_count()) + __this_cpu_add(cpu_hardirq_time, delta); + else if (in_serving_softirq() && curr != this_cpu_ksoftirqd()) + __this_cpu_add(cpu_softirq_time, delta); + + irq_time_write_end(); + local_irq_restore(flags); +} +EXPORT_SYMBOL_GPL(account_system_vtime); + +#endif /* CONFIG_IRQ_TIME_ACCOUNTING */ + +#ifdef CONFIG_PARAVIRT +static inline u64 steal_ticks(u64 steal) +{ + if (unlikely(steal > NSEC_PER_SEC)) + return div_u64(steal, TICK_NSEC); + + return __iter_div_u64_rem(steal, TICK_NSEC, &steal); +} +#endif + static void update_rq_clock_task(struct rq *rq, s64 delta) { /* @@ -800,6 +920,43 @@ static void update_rq_clock_task(struct rq *rq, s64 delta) #endif } +#ifdef CONFIG_IRQ_TIME_ACCOUNTING +static int irqtime_account_hi_update(void) +{ + u64 *cpustat = kcpustat_this_cpu->cpustat; + unsigned long flags; + u64 latest_ns; + int ret = 0; + + local_irq_save(flags); + latest_ns = this_cpu_read(cpu_hardirq_time); + if (nsecs_to_cputime64(latest_ns) > cpustat[CPUTIME_IRQ]) + ret = 1; + local_irq_restore(flags); + return ret; +} + +static int irqtime_account_si_update(void) +{ + u64 *cpustat = kcpustat_this_cpu->cpustat; + unsigned long flags; + u64 latest_ns; + int ret = 0; + + local_irq_save(flags); + latest_ns = this_cpu_read(cpu_softirq_time); + if (nsecs_to_cputime64(latest_ns) > cpustat[CPUTIME_SOFTIRQ]) + ret = 1; + local_irq_restore(flags); + return ret; +} + +#else /* CONFIG_IRQ_TIME_ACCOUNTING */ + +#define sched_clock_irqtime (0) + +#endif + void sched_set_stop_task(int cpu, struct task_struct *stop) { struct sched_param param = { .sched_priority = MAX_RT_PRIO - 1 }; @@ -1361,6 +1518,25 @@ static void ttwu_queue_remote(struct task_struct *p, int cpu) smp_send_reschedule(cpu); } +#ifdef __ARCH_WANT_INTERRUPTS_ON_CTXSW +static int ttwu_activate_remote(struct task_struct *p, int wake_flags) +{ + struct rq *rq; + int ret = 0; + + rq = __task_rq_lock(p); + if (p->on_cpu) { + ttwu_activate(rq, p, ENQUEUE_WAKEUP); + ttwu_do_wakeup(rq, p, wake_flags); + ret = 1; + } + __task_rq_unlock(rq); + + return ret; + +} +#endif /* __ARCH_WANT_INTERRUPTS_ON_CTXSW */ + bool cpus_share_cache(int this_cpu, int that_cpu) { return per_cpu(sd_llc_id, this_cpu) == per_cpu(sd_llc_id, that_cpu); @@ -1421,8 +1597,21 @@ try_to_wake_up(struct task_struct *p, unsigned int state, int wake_flags) * If the owning (remote) cpu is still in the middle of schedule() with * this task as prev, wait until its done referencing the task. */ - while (p->on_cpu) + while (p->on_cpu) { +#ifdef __ARCH_WANT_INTERRUPTS_ON_CTXSW + /* + * In case the architecture enables interrupts in + * context_switch(), we cannot busy wait, since that + * would lead to deadlocks when an interrupt hits and + * tries to wake up @prev. So bail and do a complete + * remote wakeup. + */ + if (ttwu_activate_remote(p, wake_flags)) + goto stat; +#else cpu_relax(); +#endif + } /* * Pairs with the smp_wmb() in finish_lock_switch(). */ @@ -1764,9 +1953,14 @@ static void finish_task_switch(struct rq *rq, struct task_struct *prev) * Manfred Spraul */ prev_state = prev->state; - vtime_task_switch(prev); finish_arch_switch(prev); +#ifdef __ARCH_WANT_INTERRUPTS_ON_CTXSW + local_irq_disable(); +#endif /* __ARCH_WANT_INTERRUPTS_ON_CTXSW */ perf_event_task_sched_in(prev, current); +#ifdef __ARCH_WANT_INTERRUPTS_ON_CTXSW + local_irq_enable(); +#endif /* __ARCH_WANT_INTERRUPTS_ON_CTXSW */ finish_lock_switch(rq, prev); finish_arch_post_lock_switch(); @@ -1887,7 +2081,6 @@ context_switch(struct rq *rq, struct task_struct *prev, #endif /* Here we just switch the register state and the stack. */ - rcu_switch(prev, next); switch_to(prev, next, prev); barrier(); @@ -2616,6 +2809,398 @@ unsigned long long task_sched_runtime(struct task_struct *p) return ns; } +#ifdef CONFIG_CGROUP_CPUACCT +struct cgroup_subsys cpuacct_subsys; +struct cpuacct root_cpuacct; +#endif + +static inline void task_group_account_field(struct task_struct *p, int index, + u64 tmp) +{ +#ifdef CONFIG_CGROUP_CPUACCT + struct kernel_cpustat *kcpustat; + struct cpuacct *ca; +#endif + /* + * Since all updates are sure to touch the root cgroup, we + * get ourselves ahead and touch it first. If the root cgroup + * is the only cgroup, then nothing else should be necessary. + * + */ + __get_cpu_var(kernel_cpustat).cpustat[index] += tmp; + +#ifdef CONFIG_CGROUP_CPUACCT + if (unlikely(!cpuacct_subsys.active)) + return; + + rcu_read_lock(); + ca = task_ca(p); + while (ca && (ca != &root_cpuacct)) { + kcpustat = this_cpu_ptr(ca->cpustat); + kcpustat->cpustat[index] += tmp; + ca = parent_ca(ca); + } + rcu_read_unlock(); +#endif +} + + +/* + * Account user cpu time to a process. + * @p: the process that the cpu time gets accounted to + * @cputime: the cpu time spent in user space since the last update + * @cputime_scaled: cputime scaled by cpu frequency + */ +void account_user_time(struct task_struct *p, cputime_t cputime, + cputime_t cputime_scaled) +{ + int index; + + /* Add user time to process. */ + p->utime += cputime; + p->utimescaled += cputime_scaled; + account_group_user_time(p, cputime); + + index = (TASK_NICE(p) > 0) ? CPUTIME_NICE : CPUTIME_USER; + + /* Add user time to cpustat. */ + task_group_account_field(p, index, (__force u64) cputime); + + /* Account for user time used */ + acct_update_integrals(p); +} + +/* + * Account guest cpu time to a process. + * @p: the process that the cpu time gets accounted to + * @cputime: the cpu time spent in virtual machine since the last update + * @cputime_scaled: cputime scaled by cpu frequency + */ +static void account_guest_time(struct task_struct *p, cputime_t cputime, + cputime_t cputime_scaled) +{ + u64 *cpustat = kcpustat_this_cpu->cpustat; + + /* Add guest time to process. */ + p->utime += cputime; + p->utimescaled += cputime_scaled; + account_group_user_time(p, cputime); + p->gtime += cputime; + + /* Add guest time to cpustat. */ + if (TASK_NICE(p) > 0) { + cpustat[CPUTIME_NICE] += (__force u64) cputime; + cpustat[CPUTIME_GUEST_NICE] += (__force u64) cputime; + } else { + cpustat[CPUTIME_USER] += (__force u64) cputime; + cpustat[CPUTIME_GUEST] += (__force u64) cputime; + } +} + +/* + * Account system cpu time to a process and desired cpustat field + * @p: the process that the cpu time gets accounted to + * @cputime: the cpu time spent in kernel space since the last update + * @cputime_scaled: cputime scaled by cpu frequency + * @target_cputime64: pointer to cpustat field that has to be updated + */ +static inline +void __account_system_time(struct task_struct *p, cputime_t cputime, + cputime_t cputime_scaled, int index) +{ + /* Add system time to process. */ + p->stime += cputime; + p->stimescaled += cputime_scaled; + account_group_system_time(p, cputime); + + /* Add system time to cpustat. */ + task_group_account_field(p, index, (__force u64) cputime); + + /* Account for system time used */ + acct_update_integrals(p); +} + +/* + * Account system cpu time to a process. + * @p: the process that the cpu time gets accounted to + * @hardirq_offset: the offset to subtract from hardirq_count() + * @cputime: the cpu time spent in kernel space since the last update + * @cputime_scaled: cputime scaled by cpu frequency + */ +void account_system_time(struct task_struct *p, int hardirq_offset, + cputime_t cputime, cputime_t cputime_scaled) +{ + int index; + + if ((p->flags & PF_VCPU) && (irq_count() - hardirq_offset == 0)) { + account_guest_time(p, cputime, cputime_scaled); + return; + } + + if (hardirq_count() - hardirq_offset) + index = CPUTIME_IRQ; + else if (in_serving_softirq()) + index = CPUTIME_SOFTIRQ; + else + index = CPUTIME_SYSTEM; + + __account_system_time(p, cputime, cputime_scaled, index); +} + +/* + * Account for involuntary wait time. + * @cputime: the cpu time spent in involuntary wait + */ +void account_steal_time(cputime_t cputime) +{ + u64 *cpustat = kcpustat_this_cpu->cpustat; + + cpustat[CPUTIME_STEAL] += (__force u64) cputime; +} + +/* + * Account for idle time. + * @cputime: the cpu time spent in idle wait + */ +void account_idle_time(cputime_t cputime) +{ + u64 *cpustat = kcpustat_this_cpu->cpustat; + struct rq *rq = this_rq(); + + if (atomic_read(&rq->nr_iowait) > 0) + cpustat[CPUTIME_IOWAIT] += (__force u64) cputime; + else + cpustat[CPUTIME_IDLE] += (__force u64) cputime; +} + +static __always_inline bool steal_account_process_tick(void) +{ +#ifdef CONFIG_PARAVIRT + if (static_key_false(¶virt_steal_enabled)) { + u64 steal, st = 0; + + steal = paravirt_steal_clock(smp_processor_id()); + steal -= this_rq()->prev_steal_time; + + st = steal_ticks(steal); + this_rq()->prev_steal_time += st * TICK_NSEC; + + account_steal_time(st); + return st; + } +#endif + return false; +} + +#ifndef CONFIG_VIRT_CPU_ACCOUNTING + +#ifdef CONFIG_IRQ_TIME_ACCOUNTING +/* + * Account a tick to a process and cpustat + * @p: the process that the cpu time gets accounted to + * @user_tick: is the tick from userspace + * @rq: the pointer to rq + * + * Tick demultiplexing follows the order + * - pending hardirq update + * - pending softirq update + * - user_time + * - idle_time + * - system time + * - check for guest_time + * - else account as system_time + * + * Check for hardirq is done both for system and user time as there is + * no timer going off while we are on hardirq and hence we may never get an + * opportunity to update it solely in system time. + * p->stime and friends are only updated on system time and not on irq + * softirq as those do not count in task exec_runtime any more. + */ +static void irqtime_account_process_tick(struct task_struct *p, int user_tick, + struct rq *rq) +{ + cputime_t one_jiffy_scaled = cputime_to_scaled(cputime_one_jiffy); + u64 *cpustat = kcpustat_this_cpu->cpustat; + + if (steal_account_process_tick()) + return; + + if (irqtime_account_hi_update()) { + cpustat[CPUTIME_IRQ] += (__force u64) cputime_one_jiffy; + } else if (irqtime_account_si_update()) { + cpustat[CPUTIME_SOFTIRQ] += (__force u64) cputime_one_jiffy; + } else if (this_cpu_ksoftirqd() == p) { + /* + * ksoftirqd time do not get accounted in cpu_softirq_time. + * So, we have to handle it separately here. + * Also, p->stime needs to be updated for ksoftirqd. + */ + __account_system_time(p, cputime_one_jiffy, one_jiffy_scaled, + CPUTIME_SOFTIRQ); + } else if (user_tick) { + account_user_time(p, cputime_one_jiffy, one_jiffy_scaled); + } else if (p == rq->idle) { + account_idle_time(cputime_one_jiffy); + } else if (p->flags & PF_VCPU) { /* System time or guest time */ + account_guest_time(p, cputime_one_jiffy, one_jiffy_scaled); + } else { + __account_system_time(p, cputime_one_jiffy, one_jiffy_scaled, + CPUTIME_SYSTEM); + } +} + +static void irqtime_account_idle_ticks(int ticks) +{ + int i; + struct rq *rq = this_rq(); + + for (i = 0; i < ticks; i++) + irqtime_account_process_tick(current, 0, rq); +} +#else /* CONFIG_IRQ_TIME_ACCOUNTING */ +static void irqtime_account_idle_ticks(int ticks) {} +static void irqtime_account_process_tick(struct task_struct *p, int user_tick, + struct rq *rq) {} +#endif /* CONFIG_IRQ_TIME_ACCOUNTING */ + +/* + * Account a single tick of cpu time. + * @p: the process that the cpu time gets accounted to + * @user_tick: indicates if the tick is a user or a system tick + */ +void account_process_tick(struct task_struct *p, int user_tick) +{ + cputime_t one_jiffy_scaled = cputime_to_scaled(cputime_one_jiffy); + struct rq *rq = this_rq(); + + if (sched_clock_irqtime) { + irqtime_account_process_tick(p, user_tick, rq); + return; + } + + if (steal_account_process_tick()) + return; + + if (user_tick) + account_user_time(p, cputime_one_jiffy, one_jiffy_scaled); + else if ((p != rq->idle) || (irq_count() != HARDIRQ_OFFSET)) + account_system_time(p, HARDIRQ_OFFSET, cputime_one_jiffy, + one_jiffy_scaled); + else + account_idle_time(cputime_one_jiffy); +} + +/* + * Account multiple ticks of steal time. + * @p: the process from which the cpu time has been stolen + * @ticks: number of stolen ticks + */ +void account_steal_ticks(unsigned long ticks) +{ + account_steal_time(jiffies_to_cputime(ticks)); +} + +/* + * Account multiple ticks of idle time. + * @ticks: number of stolen ticks + */ +void account_idle_ticks(unsigned long ticks) +{ + + if (sched_clock_irqtime) { + irqtime_account_idle_ticks(ticks); + return; + } + + account_idle_time(jiffies_to_cputime(ticks)); +} + +#endif + +/* + * Use precise platform statistics if available: + */ +#ifdef CONFIG_VIRT_CPU_ACCOUNTING +void task_times(struct task_struct *p, cputime_t *ut, cputime_t *st) +{ + *ut = p->utime; + *st = p->stime; +} + +void thread_group_times(struct task_struct *p, cputime_t *ut, cputime_t *st) +{ + struct task_cputime cputime; + + thread_group_cputime(p, &cputime); + + *ut = cputime.utime; + *st = cputime.stime; +} +#else + +#ifndef nsecs_to_cputime +# define nsecs_to_cputime(__nsecs) nsecs_to_jiffies(__nsecs) +#endif + +void task_times(struct task_struct *p, cputime_t *ut, cputime_t *st) +{ + cputime_t rtime, utime = p->utime, total = utime + p->stime; + + /* + * Use CFS's precise accounting: + */ + rtime = nsecs_to_cputime(p->se.sum_exec_runtime); + + if (total) { + u64 temp = (__force u64) rtime; + + temp *= (__force u64) utime; + do_div(temp, (__force u32) total); + utime = (__force cputime_t) temp; + } else + utime = rtime; + + /* + * Compare with previous values, to keep monotonicity: + */ + p->prev_utime = max(p->prev_utime, utime); + p->prev_stime = max(p->prev_stime, rtime - p->prev_utime); + + *ut = p->prev_utime; + *st = p->prev_stime; +} + +/* + * Must be called with siglock held. + */ +void thread_group_times(struct task_struct *p, cputime_t *ut, cputime_t *st) +{ + struct signal_struct *sig = p->signal; + struct task_cputime cputime; + cputime_t rtime, utime, total; + + thread_group_cputime(p, &cputime); + + total = cputime.utime + cputime.stime; + rtime = nsecs_to_cputime(cputime.sum_exec_runtime); + + if (total) { + u64 temp = (__force u64) rtime; + + temp *= (__force u64) cputime.utime; + do_div(temp, (__force u32) total); + utime = (__force cputime_t) temp; + } else + utime = rtime; + + sig->prev_utime = max(sig->prev_utime, utime); + sig->prev_stime = max(sig->prev_stime, rtime - sig->prev_utime); + + *ut = sig->prev_utime; + *st = sig->prev_stime; +} +#endif + /* * This function gets called by the timer code, with HZ frequency. * We call it with interrupts disabled. @@ -2776,40 +3361,6 @@ pick_next_task(struct rq *rq) /* * __schedule() is the main scheduler function. - * - * The main means of driving the scheduler and thus entering this function are: - * - * 1. Explicit blocking: mutex, semaphore, waitqueue, etc. - * - * 2. TIF_NEED_RESCHED flag is checked on interrupt and userspace return - * paths. For example, see arch/x86/entry_64.S. - * - * To drive preemption between tasks, the scheduler sets the flag in timer - * interrupt handler scheduler_tick(). - * - * 3. Wakeups don't really cause entry into schedule(). They add a - * task to the run-queue and that's it. - * - * Now, if the new task added to the run-queue preempts the current - * task, then the wakeup sets TIF_NEED_RESCHED and schedule() gets - * called on the nearest possible occasion: - * - * - If the kernel is preemptible (CONFIG_PREEMPT=y): - * - * - in syscall or exception context, at the next outmost - * preempt_enable(). (this might be as soon as the wake_up()'s - * spin_unlock()!) - * - * - in IRQ context, return from interrupt-handler to - * preemptible context - * - * - If the kernel is not preemptible (CONFIG_PREEMPT is not set) - * then at the next: - * - * - cond_resched() call - * - explicit schedule() call - * - return from syscall or exception to user-space - * - return from interrupt-handler to user-space */ static void __sched __schedule(void) { @@ -2911,21 +3462,6 @@ asmlinkage void __sched schedule(void) } EXPORT_SYMBOL(schedule); -#ifdef CONFIG_RCU_USER_QS -asmlinkage void __sched schedule_user(void) -{ - /* - * If we come here after a random call to set_need_resched(), - * or we have been woken up remotely but the IPI has not yet arrived, - * we haven't yet exited the RCU idle mode. Do it here manually until - * we find a better solution. - */ - rcu_user_exit(); - schedule(); - rcu_user_enter(); -} -#endif - /** * schedule_preempt_disabled - called with preemption disabled * @@ -3027,7 +3563,6 @@ asmlinkage void __sched preempt_schedule_irq(void) /* Catch callers which need to be fixed */ BUG_ON(ti->preempt_count || !irqs_disabled()); - rcu_user_exit(); do { add_preempt_count(PREEMPT_ACTIVE); local_irq_enable(); @@ -3805,7 +4340,9 @@ static int __sched_setscheduler(struct task_struct *p, int policy, */ if (unlikely(policy == p->policy && (!rt_policy(policy) || param->sched_priority == p->rt_priority))) { - task_rq_unlock(rq, p, &flags); + + __task_rq_unlock(rq); + raw_spin_unlock_irqrestore(&p->pi_lock, flags); return 0; } @@ -4327,6 +4864,13 @@ bool __sched yield_to(struct task_struct *p, bool preempt) */ if (preempt && rq != p_rq) resched_task(p_rq->curr); + } else { + /* + * We might have set it in task_yield_fair(), but are + * not going to schedule(), so don't want to skip + * the next update. + */ + rq->skip_clock_update = 0; } out: @@ -4756,17 +5300,27 @@ void idle_task_exit(void) } /* - * Since this CPU is going 'away' for a while, fold any nr_active delta - * we might have. Assumes we're called after migrate_tasks() so that the - * nr_active count is stable. - * - * Also see the comment "Global load-average calculations". + * While a dead CPU has no uninterruptible tasks queued at this point, + * it might still have a nonzero ->nr_uninterruptible counter, because + * for performance reasons the counter is not stricly tracking tasks to + * their home CPUs. So we just add the counter to another CPU's counter, + * to keep the global sum constant after CPU-down: */ -static void calc_load_migrate(struct rq *rq) +static void migrate_nr_uninterruptible(struct rq *rq_src) { - long delta = calc_load_fold_active(rq); - if (delta) - atomic_long_add(delta, &calc_load_tasks); + struct rq *rq_dest = cpu_rq(cpumask_any(cpu_active_mask)); + + rq_dest->nr_uninterruptible += rq_src->nr_uninterruptible; + rq_src->nr_uninterruptible = 0; +} + +/* + * remove the tasks which were accounted by rq from calc_load_tasks. + */ +static void calc_global_load_remove(struct rq *rq) +{ + atomic_long_sub(rq->calc_load_active, &calc_load_tasks); + rq->calc_load_active = 0; } /* @@ -4794,6 +5348,9 @@ static void migrate_tasks(unsigned int dead_cpu) */ rq->stop = NULL; + /* Ensure any throttled groups are reachable by pick_next_task */ + unthrottle_offline_cfs_rqs(rq); + for ( ; ; ) { /* * There's this thread running, bail when that's the only @@ -4868,25 +5425,16 @@ static void sd_free_ctl_entry(struct ctl_table **tablep) *tablep = NULL; } -static int min_load_idx = 0; -static int max_load_idx = CPU_LOAD_IDX_MAX; - static void set_table_entry(struct ctl_table *entry, const char *procname, void *data, int maxlen, - umode_t mode, proc_handler *proc_handler, - bool load_idx) + umode_t mode, proc_handler *proc_handler) { entry->procname = procname; entry->data = data; entry->maxlen = maxlen; entry->mode = mode; entry->proc_handler = proc_handler; - - if (load_idx) { - entry->extra1 = &min_load_idx; - entry->extra2 = &max_load_idx; - } } static struct ctl_table * @@ -4898,30 +5446,30 @@ sd_alloc_ctl_domain_table(struct sched_domain *sd) return NULL; set_table_entry(&table[0], "min_interval", &sd->min_interval, - sizeof(long), 0644, proc_doulongvec_minmax, false); + sizeof(long), 0644, proc_doulongvec_minmax); set_table_entry(&table[1], "max_interval", &sd->max_interval, - sizeof(long), 0644, proc_doulongvec_minmax, false); + sizeof(long), 0644, proc_doulongvec_minmax); set_table_entry(&table[2], "busy_idx", &sd->busy_idx, - sizeof(int), 0644, proc_dointvec_minmax, true); + sizeof(int), 0644, proc_dointvec_minmax); set_table_entry(&table[3], "idle_idx", &sd->idle_idx, - sizeof(int), 0644, proc_dointvec_minmax, true); + sizeof(int), 0644, proc_dointvec_minmax); set_table_entry(&table[4], "newidle_idx", &sd->newidle_idx, - sizeof(int), 0644, proc_dointvec_minmax, true); + sizeof(int), 0644, proc_dointvec_minmax); set_table_entry(&table[5], "wake_idx", &sd->wake_idx, - sizeof(int), 0644, proc_dointvec_minmax, true); + sizeof(int), 0644, proc_dointvec_minmax); set_table_entry(&table[6], "forkexec_idx", &sd->forkexec_idx, - sizeof(int), 0644, proc_dointvec_minmax, true); + sizeof(int), 0644, proc_dointvec_minmax); set_table_entry(&table[7], "busy_factor", &sd->busy_factor, - sizeof(int), 0644, proc_dointvec_minmax, false); + sizeof(int), 0644, proc_dointvec_minmax); set_table_entry(&table[8], "imbalance_pct", &sd->imbalance_pct, - sizeof(int), 0644, proc_dointvec_minmax, false); + sizeof(int), 0644, proc_dointvec_minmax); set_table_entry(&table[9], "cache_nice_tries", &sd->cache_nice_tries, - sizeof(int), 0644, proc_dointvec_minmax, false); + sizeof(int), 0644, proc_dointvec_minmax); set_table_entry(&table[10], "flags", &sd->flags, - sizeof(int), 0644, proc_dointvec_minmax, false); + sizeof(int), 0644, proc_dointvec_minmax); set_table_entry(&table[11], "name", sd->name, - CORENAME_MAX_SIZE, 0444, proc_dostring, false); + CORENAME_MAX_SIZE, 0444, proc_dostring); /* &table[12] is terminator */ return table; @@ -5065,10 +5613,9 @@ migration_call(struct notifier_block *nfb, unsigned long action, void *hcpu) migrate_tasks(cpu); BUG_ON(rq->nr_running != 1); /* the migration thread */ raw_spin_unlock_irqrestore(&rq->lock, flags); - break; - case CPU_DEAD: - calc_load_migrate(rq); + migrate_nr_uninterruptible(rq); + calc_global_load_remove(rq); break; #endif } @@ -5477,6 +6024,11 @@ static void destroy_sched_domains(struct sched_domain *sd, int cpu) * SD_SHARE_PKG_RESOURCE set (Last Level Cache Domain) for this * allows us to avoid some pointer chasing select_idle_sibling(). * + * Iterate domains and sched_groups downward, assigning CPUs to be + * select_idle_sibling() hw buddy. Cross-wiring hw makes bouncing + * due to random perturbation self canceling, ie sw buddies pull + * their counterpart to their CPU's hw counterpart. + * * Also keep a unique ID per domain (we use the first cpu number in * the cpumask of the domain), this allows us to quickly tell if * two cpus are in the same cache domain, see cpus_share_cache(). @@ -5490,8 +6042,40 @@ static void update_top_cache_domain(int cpu) int id = cpu; sd = highest_flag_domain(cpu, SD_SHARE_PKG_RESOURCES); - if (sd) + if (sd) { + struct sched_domain *tmp = sd; + struct sched_group *sg, *prev; + bool right; + + /* + * Traverse to first CPU in group, and count hops + * to cpu from there, switching direction on each + * hop, never ever pointing the last CPU rightward. + */ + do { + id = cpumask_first(sched_domain_span(tmp)); + prev = sg = tmp->groups; + right = 1; + + while (cpumask_first(sched_group_cpus(sg)) != id) + sg = sg->next; + + while (!cpumask_test_cpu(cpu, sched_group_cpus(sg))) { + prev = sg; + sg = sg->next; + right = !right; + } + + /* A CPU went down, never point back to domain start. */ + if (right && cpumask_first(sched_group_cpus(sg->next)) == id) + right = false; + + sg = right ? sg->next : prev; + tmp->idle_buddy = cpumask_first(sched_group_cpus(sg)); + } while ((tmp = tmp->child)); + id = cpumask_first(sched_domain_span(sd)); + } rcu_assign_pointer(per_cpu(sd_llc, cpu), sd); per_cpu(sd_llc_id, cpu) = id; @@ -6000,6 +6584,7 @@ sd_numa_init(struct sched_domain_topology_level *tl, int cpu) | 0*SD_BALANCE_FORK | 0*SD_BALANCE_WAKE | 0*SD_WAKE_AFFINE + | 0*SD_PREFER_LOCAL | 0*SD_SHARE_CPUPOWER | 0*SD_SHARE_PKG_RESOURCES | 1*SD_SERIALIZE @@ -6663,7 +7248,6 @@ int in_sched_functions(unsigned long addr) #ifdef CONFIG_CGROUP_SCHED struct task_group root_task_group; -LIST_HEAD(task_groups); #endif DECLARE_PER_CPU(cpumask_var_t, load_balance_tmpmask); @@ -7797,8 +8381,6 @@ struct cgroup_subsys cpu_cgroup_subsys = { * (balbir@in.ibm.com). */ -struct cpuacct root_cpuacct; - /* create a new cpu accounting group */ static struct cgroup_subsys_state *cpuacct_create(struct cgroup *cgrp) { diff --git a/trunk/kernel/sched/cpupri.c b/trunk/kernel/sched/cpupri.c index 23aa789c53ee..d72586fdf660 100644 --- a/trunk/kernel/sched/cpupri.c +++ b/trunk/kernel/sched/cpupri.c @@ -65,8 +65,8 @@ static int convert_prio(int prio) int cpupri_find(struct cpupri *cp, struct task_struct *p, struct cpumask *lowest_mask) { - int idx = 0; - int task_pri = convert_prio(p->prio); + int idx = 0; + int task_pri = convert_prio(p->prio); if (task_pri >= MAX_RT_PRIO) return 0; @@ -137,9 +137,9 @@ int cpupri_find(struct cpupri *cp, struct task_struct *p, */ void cpupri_set(struct cpupri *cp, int cpu, int newpri) { - int *currpri = &cp->cpu_to_pri[cpu]; - int oldpri = *currpri; - int do_mb = 0; + int *currpri = &cp->cpu_to_pri[cpu]; + int oldpri = *currpri; + int do_mb = 0; newpri = convert_prio(newpri); diff --git a/trunk/kernel/sched/cputime.c b/trunk/kernel/sched/cputime.c deleted file mode 100644 index 81b763ba58a6..000000000000 --- a/trunk/kernel/sched/cputime.c +++ /dev/null @@ -1,530 +0,0 @@ -#include -#include -#include -#include -#include -#include "sched.h" - - -#ifdef CONFIG_IRQ_TIME_ACCOUNTING - -/* - * There are no locks covering percpu hardirq/softirq time. - * They are only modified in vtime_account, on corresponding CPU - * with interrupts disabled. So, writes are safe. - * They are read and saved off onto struct rq in update_rq_clock(). - * This may result in other CPU reading this CPU's irq time and can - * race with irq/vtime_account on this CPU. We would either get old - * or new value with a side effect of accounting a slice of irq time to wrong - * task when irq is in progress while we read rq->clock. That is a worthy - * compromise in place of having locks on each irq in account_system_time. - */ -DEFINE_PER_CPU(u64, cpu_hardirq_time); -DEFINE_PER_CPU(u64, cpu_softirq_time); - -static DEFINE_PER_CPU(u64, irq_start_time); -static int sched_clock_irqtime; - -void enable_sched_clock_irqtime(void) -{ - sched_clock_irqtime = 1; -} - -void disable_sched_clock_irqtime(void) -{ - sched_clock_irqtime = 0; -} - -#ifndef CONFIG_64BIT -DEFINE_PER_CPU(seqcount_t, irq_time_seq); -#endif /* CONFIG_64BIT */ - -/* - * Called before incrementing preempt_count on {soft,}irq_enter - * and before decrementing preempt_count on {soft,}irq_exit. - */ -void vtime_account(struct task_struct *curr) -{ - unsigned long flags; - s64 delta; - int cpu; - - if (!sched_clock_irqtime) - return; - - local_irq_save(flags); - - cpu = smp_processor_id(); - delta = sched_clock_cpu(cpu) - __this_cpu_read(irq_start_time); - __this_cpu_add(irq_start_time, delta); - - irq_time_write_begin(); - /* - * We do not account for softirq time from ksoftirqd here. - * We want to continue accounting softirq time to ksoftirqd thread - * in that case, so as not to confuse scheduler with a special task - * that do not consume any time, but still wants to run. - */ - if (hardirq_count()) - __this_cpu_add(cpu_hardirq_time, delta); - else if (in_serving_softirq() && curr != this_cpu_ksoftirqd()) - __this_cpu_add(cpu_softirq_time, delta); - - irq_time_write_end(); - local_irq_restore(flags); -} -EXPORT_SYMBOL_GPL(vtime_account); - -static int irqtime_account_hi_update(void) -{ - u64 *cpustat = kcpustat_this_cpu->cpustat; - unsigned long flags; - u64 latest_ns; - int ret = 0; - - local_irq_save(flags); - latest_ns = this_cpu_read(cpu_hardirq_time); - if (nsecs_to_cputime64(latest_ns) > cpustat[CPUTIME_IRQ]) - ret = 1; - local_irq_restore(flags); - return ret; -} - -static int irqtime_account_si_update(void) -{ - u64 *cpustat = kcpustat_this_cpu->cpustat; - unsigned long flags; - u64 latest_ns; - int ret = 0; - - local_irq_save(flags); - latest_ns = this_cpu_read(cpu_softirq_time); - if (nsecs_to_cputime64(latest_ns) > cpustat[CPUTIME_SOFTIRQ]) - ret = 1; - local_irq_restore(flags); - return ret; -} - -#else /* CONFIG_IRQ_TIME_ACCOUNTING */ - -#define sched_clock_irqtime (0) - -#endif /* !CONFIG_IRQ_TIME_ACCOUNTING */ - -static inline void task_group_account_field(struct task_struct *p, int index, - u64 tmp) -{ -#ifdef CONFIG_CGROUP_CPUACCT - struct kernel_cpustat *kcpustat; - struct cpuacct *ca; -#endif - /* - * Since all updates are sure to touch the root cgroup, we - * get ourselves ahead and touch it first. If the root cgroup - * is the only cgroup, then nothing else should be necessary. - * - */ - __get_cpu_var(kernel_cpustat).cpustat[index] += tmp; - -#ifdef CONFIG_CGROUP_CPUACCT - if (unlikely(!cpuacct_subsys.active)) - return; - - rcu_read_lock(); - ca = task_ca(p); - while (ca && (ca != &root_cpuacct)) { - kcpustat = this_cpu_ptr(ca->cpustat); - kcpustat->cpustat[index] += tmp; - ca = parent_ca(ca); - } - rcu_read_unlock(); -#endif -} - -/* - * Account user cpu time to a process. - * @p: the process that the cpu time gets accounted to - * @cputime: the cpu time spent in user space since the last update - * @cputime_scaled: cputime scaled by cpu frequency - */ -void account_user_time(struct task_struct *p, cputime_t cputime, - cputime_t cputime_scaled) -{ - int index; - - /* Add user time to process. */ - p->utime += cputime; - p->utimescaled += cputime_scaled; - account_group_user_time(p, cputime); - - index = (TASK_NICE(p) > 0) ? CPUTIME_NICE : CPUTIME_USER; - - /* Add user time to cpustat. */ - task_group_account_field(p, index, (__force u64) cputime); - - /* Account for user time used */ - acct_update_integrals(p); -} - -/* - * Account guest cpu time to a process. - * @p: the process that the cpu time gets accounted to - * @cputime: the cpu time spent in virtual machine since the last update - * @cputime_scaled: cputime scaled by cpu frequency - */ -static void account_guest_time(struct task_struct *p, cputime_t cputime, - cputime_t cputime_scaled) -{ - u64 *cpustat = kcpustat_this_cpu->cpustat; - - /* Add guest time to process. */ - p->utime += cputime; - p->utimescaled += cputime_scaled; - account_group_user_time(p, cputime); - p->gtime += cputime; - - /* Add guest time to cpustat. */ - if (TASK_NICE(p) > 0) { - cpustat[CPUTIME_NICE] += (__force u64) cputime; - cpustat[CPUTIME_GUEST_NICE] += (__force u64) cputime; - } else { - cpustat[CPUTIME_USER] += (__force u64) cputime; - cpustat[CPUTIME_GUEST] += (__force u64) cputime; - } -} - -/* - * Account system cpu time to a process and desired cpustat field - * @p: the process that the cpu time gets accounted to - * @cputime: the cpu time spent in kernel space since the last update - * @cputime_scaled: cputime scaled by cpu frequency - * @target_cputime64: pointer to cpustat field that has to be updated - */ -static inline -void __account_system_time(struct task_struct *p, cputime_t cputime, - cputime_t cputime_scaled, int index) -{ - /* Add system time to process. */ - p->stime += cputime; - p->stimescaled += cputime_scaled; - account_group_system_time(p, cputime); - - /* Add system time to cpustat. */ - task_group_account_field(p, index, (__force u64) cputime); - - /* Account for system time used */ - acct_update_integrals(p); -} - -/* - * Account system cpu time to a process. - * @p: the process that the cpu time gets accounted to - * @hardirq_offset: the offset to subtract from hardirq_count() - * @cputime: the cpu time spent in kernel space since the last update - * @cputime_scaled: cputime scaled by cpu frequency - */ -void account_system_time(struct task_struct *p, int hardirq_offset, - cputime_t cputime, cputime_t cputime_scaled) -{ - int index; - - if ((p->flags & PF_VCPU) && (irq_count() - hardirq_offset == 0)) { - account_guest_time(p, cputime, cputime_scaled); - return; - } - - if (hardirq_count() - hardirq_offset) - index = CPUTIME_IRQ; - else if (in_serving_softirq()) - index = CPUTIME_SOFTIRQ; - else - index = CPUTIME_SYSTEM; - - __account_system_time(p, cputime, cputime_scaled, index); -} - -/* - * Account for involuntary wait time. - * @cputime: the cpu time spent in involuntary wait - */ -void account_steal_time(cputime_t cputime) -{ - u64 *cpustat = kcpustat_this_cpu->cpustat; - - cpustat[CPUTIME_STEAL] += (__force u64) cputime; -} - -/* - * Account for idle time. - * @cputime: the cpu time spent in idle wait - */ -void account_idle_time(cputime_t cputime) -{ - u64 *cpustat = kcpustat_this_cpu->cpustat; - struct rq *rq = this_rq(); - - if (atomic_read(&rq->nr_iowait) > 0) - cpustat[CPUTIME_IOWAIT] += (__force u64) cputime; - else - cpustat[CPUTIME_IDLE] += (__force u64) cputime; -} - -static __always_inline bool steal_account_process_tick(void) -{ -#ifdef CONFIG_PARAVIRT - if (static_key_false(¶virt_steal_enabled)) { - u64 steal, st = 0; - - steal = paravirt_steal_clock(smp_processor_id()); - steal -= this_rq()->prev_steal_time; - - st = steal_ticks(steal); - this_rq()->prev_steal_time += st * TICK_NSEC; - - account_steal_time(st); - return st; - } -#endif - return false; -} - -#ifndef CONFIG_VIRT_CPU_ACCOUNTING - -#ifdef CONFIG_IRQ_TIME_ACCOUNTING -/* - * Account a tick to a process and cpustat - * @p: the process that the cpu time gets accounted to - * @user_tick: is the tick from userspace - * @rq: the pointer to rq - * - * Tick demultiplexing follows the order - * - pending hardirq update - * - pending softirq update - * - user_time - * - idle_time - * - system time - * - check for guest_time - * - else account as system_time - * - * Check for hardirq is done both for system and user time as there is - * no timer going off while we are on hardirq and hence we may never get an - * opportunity to update it solely in system time. - * p->stime and friends are only updated on system time and not on irq - * softirq as those do not count in task exec_runtime any more. - */ -static void irqtime_account_process_tick(struct task_struct *p, int user_tick, - struct rq *rq) -{ - cputime_t one_jiffy_scaled = cputime_to_scaled(cputime_one_jiffy); - u64 *cpustat = kcpustat_this_cpu->cpustat; - - if (steal_account_process_tick()) - return; - - if (irqtime_account_hi_update()) { - cpustat[CPUTIME_IRQ] += (__force u64) cputime_one_jiffy; - } else if (irqtime_account_si_update()) { - cpustat[CPUTIME_SOFTIRQ] += (__force u64) cputime_one_jiffy; - } else if (this_cpu_ksoftirqd() == p) { - /* - * ksoftirqd time do not get accounted in cpu_softirq_time. - * So, we have to handle it separately here. - * Also, p->stime needs to be updated for ksoftirqd. - */ - __account_system_time(p, cputime_one_jiffy, one_jiffy_scaled, - CPUTIME_SOFTIRQ); - } else if (user_tick) { - account_user_time(p, cputime_one_jiffy, one_jiffy_scaled); - } else if (p == rq->idle) { - account_idle_time(cputime_one_jiffy); - } else if (p->flags & PF_VCPU) { /* System time or guest time */ - account_guest_time(p, cputime_one_jiffy, one_jiffy_scaled); - } else { - __account_system_time(p, cputime_one_jiffy, one_jiffy_scaled, - CPUTIME_SYSTEM); - } -} - -static void irqtime_account_idle_ticks(int ticks) -{ - int i; - struct rq *rq = this_rq(); - - for (i = 0; i < ticks; i++) - irqtime_account_process_tick(current, 0, rq); -} -#else /* CONFIG_IRQ_TIME_ACCOUNTING */ -static void irqtime_account_idle_ticks(int ticks) {} -static void irqtime_account_process_tick(struct task_struct *p, int user_tick, - struct rq *rq) {} -#endif /* CONFIG_IRQ_TIME_ACCOUNTING */ - -/* - * Account a single tick of cpu time. - * @p: the process that the cpu time gets accounted to - * @user_tick: indicates if the tick is a user or a system tick - */ -void account_process_tick(struct task_struct *p, int user_tick) -{ - cputime_t one_jiffy_scaled = cputime_to_scaled(cputime_one_jiffy); - struct rq *rq = this_rq(); - - if (sched_clock_irqtime) { - irqtime_account_process_tick(p, user_tick, rq); - return; - } - - if (steal_account_process_tick()) - return; - - if (user_tick) - account_user_time(p, cputime_one_jiffy, one_jiffy_scaled); - else if ((p != rq->idle) || (irq_count() != HARDIRQ_OFFSET)) - account_system_time(p, HARDIRQ_OFFSET, cputime_one_jiffy, - one_jiffy_scaled); - else - account_idle_time(cputime_one_jiffy); -} - -/* - * Account multiple ticks of steal time. - * @p: the process from which the cpu time has been stolen - * @ticks: number of stolen ticks - */ -void account_steal_ticks(unsigned long ticks) -{ - account_steal_time(jiffies_to_cputime(ticks)); -} - -/* - * Account multiple ticks of idle time. - * @ticks: number of stolen ticks - */ -void account_idle_ticks(unsigned long ticks) -{ - - if (sched_clock_irqtime) { - irqtime_account_idle_ticks(ticks); - return; - } - - account_idle_time(jiffies_to_cputime(ticks)); -} - -#endif - -/* - * Use precise platform statistics if available: - */ -#ifdef CONFIG_VIRT_CPU_ACCOUNTING -void task_times(struct task_struct *p, cputime_t *ut, cputime_t *st) -{ - *ut = p->utime; - *st = p->stime; -} - -void thread_group_times(struct task_struct *p, cputime_t *ut, cputime_t *st) -{ - struct task_cputime cputime; - - thread_group_cputime(p, &cputime); - - *ut = cputime.utime; - *st = cputime.stime; -} - -/* - * Archs that account the whole time spent in the idle task - * (outside irq) as idle time can rely on this and just implement - * vtime_account_system() and vtime_account_idle(). Archs that - * have other meaning of the idle time (s390 only includes the - * time spent by the CPU when it's in low power mode) must override - * vtime_account(). - */ -#ifndef __ARCH_HAS_VTIME_ACCOUNT -void vtime_account(struct task_struct *tsk) -{ - unsigned long flags; - - local_irq_save(flags); - - if (in_interrupt() || !is_idle_task(tsk)) - vtime_account_system(tsk); - else - vtime_account_idle(tsk); - - local_irq_restore(flags); -} -EXPORT_SYMBOL_GPL(vtime_account); -#endif /* __ARCH_HAS_VTIME_ACCOUNT */ - -#else - -#ifndef nsecs_to_cputime -# define nsecs_to_cputime(__nsecs) nsecs_to_jiffies(__nsecs) -#endif - -static cputime_t scale_utime(cputime_t utime, cputime_t rtime, cputime_t total) -{ - u64 temp = (__force u64) rtime; - - temp *= (__force u64) utime; - - if (sizeof(cputime_t) == 4) - temp = div_u64(temp, (__force u32) total); - else - temp = div64_u64(temp, (__force u64) total); - - return (__force cputime_t) temp; -} - -void task_times(struct task_struct *p, cputime_t *ut, cputime_t *st) -{ - cputime_t rtime, utime = p->utime, total = utime + p->stime; - - /* - * Use CFS's precise accounting: - */ - rtime = nsecs_to_cputime(p->se.sum_exec_runtime); - - if (total) - utime = scale_utime(utime, rtime, total); - else - utime = rtime; - - /* - * Compare with previous values, to keep monotonicity: - */ - p->prev_utime = max(p->prev_utime, utime); - p->prev_stime = max(p->prev_stime, rtime - p->prev_utime); - - *ut = p->prev_utime; - *st = p->prev_stime; -} - -/* - * Must be called with siglock held. - */ -void thread_group_times(struct task_struct *p, cputime_t *ut, cputime_t *st) -{ - struct signal_struct *sig = p->signal; - struct task_cputime cputime; - cputime_t rtime, utime, total; - - thread_group_cputime(p, &cputime); - - total = cputime.utime + cputime.stime; - rtime = nsecs_to_cputime(cputime.sum_exec_runtime); - - if (total) - utime = scale_utime(cputime.utime, rtime, total); - else - utime = rtime; - - sig->prev_utime = max(sig->prev_utime, utime); - sig->prev_stime = max(sig->prev_stime, rtime - sig->prev_utime); - - *ut = sig->prev_utime; - *st = sig->prev_stime; -} -#endif diff --git a/trunk/kernel/sched/fair.c b/trunk/kernel/sched/fair.c index 6b800a14b990..22321db64952 100644 --- a/trunk/kernel/sched/fair.c +++ b/trunk/kernel/sched/fair.c @@ -597,7 +597,7 @@ calc_delta_fair(unsigned long delta, struct sched_entity *se) /* * The idea is to set a period in which each task runs once. * - * When there are too many tasks (sched_nr_latency) we have to stretch + * When there are too many tasks (sysctl_sched_nr_latency) we have to stretch * this period because otherwise the slices get too small. * * p = (nr <= nl) ? l : l*nr/nl @@ -2052,7 +2052,7 @@ static void destroy_cfs_bandwidth(struct cfs_bandwidth *cfs_b) hrtimer_cancel(&cfs_b->slack_timer); } -static void unthrottle_offline_cfs_rqs(struct rq *rq) +void unthrottle_offline_cfs_rqs(struct rq *rq) { struct cfs_rq *cfs_rq; @@ -2106,7 +2106,7 @@ static inline struct cfs_bandwidth *tg_cfs_bandwidth(struct task_group *tg) return NULL; } static inline void destroy_cfs_bandwidth(struct cfs_bandwidth *cfs_b) {} -static inline void unthrottle_offline_cfs_rqs(struct rq *rq) {} +void unthrottle_offline_cfs_rqs(struct rq *rq) {} #endif /* CONFIG_CFS_BANDWIDTH */ @@ -2637,8 +2637,6 @@ static int select_idle_sibling(struct task_struct *p, int target) int cpu = smp_processor_id(); int prev_cpu = task_cpu(p); struct sched_domain *sd; - struct sched_group *sg; - int i; /* * If the task is going to be woken-up on this cpu and if it is @@ -2655,29 +2653,17 @@ static int select_idle_sibling(struct task_struct *p, int target) return prev_cpu; /* - * Otherwise, iterate the domains and find an elegible idle cpu. + * Otherwise, check assigned siblings to find an elegible idle cpu. */ sd = rcu_dereference(per_cpu(sd_llc, target)); - for_each_lower_domain(sd) { - sg = sd->groups; - do { - if (!cpumask_intersects(sched_group_cpus(sg), - tsk_cpus_allowed(p))) - goto next; - - for_each_cpu(i, sched_group_cpus(sg)) { - if (!idle_cpu(i)) - goto next; - } - target = cpumask_first_and(sched_group_cpus(sg), - tsk_cpus_allowed(p)); - goto done; -next: - sg = sg->next; - } while (sg != sd->groups); + for_each_lower_domain(sd) { + if (!cpumask_test_cpu(sd->idle_buddy, tsk_cpus_allowed(p))) + continue; + if (idle_cpu(sd->idle_buddy)) + return sd->idle_buddy; } -done: + return target; } @@ -2700,6 +2686,7 @@ select_task_rq_fair(struct task_struct *p, int sd_flag, int wake_flags) int prev_cpu = task_cpu(p); int new_cpu = cpu; int want_affine = 0; + int want_sd = 1; int sync = wake_flags & WF_SYNC; if (p->nr_cpus_allowed == 1) @@ -2716,6 +2703,27 @@ select_task_rq_fair(struct task_struct *p, int sd_flag, int wake_flags) if (!(tmp->flags & SD_LOAD_BALANCE)) continue; + /* + * If power savings logic is enabled for a domain, see if we + * are not overloaded, if so, don't balance wider. + */ + if (tmp->flags & (SD_PREFER_LOCAL)) { + unsigned long power = 0; + unsigned long nr_running = 0; + unsigned long capacity; + int i; + + for_each_cpu(i, sched_domain_span(tmp)) { + power += power_of(i); + nr_running += cpu_rq(i)->cfs.nr_running; + } + + capacity = DIV_ROUND_CLOSEST(power, SCHED_POWER_SCALE); + + if (nr_running < capacity) + want_sd = 0; + } + /* * If both cpu and prev_cpu are part of this domain, * cpu is a valid SD_WAKE_AFFINE target. @@ -2723,15 +2731,21 @@ select_task_rq_fair(struct task_struct *p, int sd_flag, int wake_flags) if (want_affine && (tmp->flags & SD_WAKE_AFFINE) && cpumask_test_cpu(prev_cpu, sched_domain_span(tmp))) { affine_sd = tmp; - break; + want_affine = 0; } - if (tmp->flags & sd_flag) + if (!want_sd && !want_affine) + break; + + if (!(tmp->flags & sd_flag)) + continue; + + if (want_sd) sd = tmp; } if (affine_sd) { - if (cpu != prev_cpu && wake_affine(affine_sd, p, sync)) + if (cpu == prev_cpu || wake_affine(affine_sd, p, sync)) prev_cpu = cpu; new_cpu = select_idle_sibling(p, prev_cpu); @@ -3055,9 +3069,6 @@ struct lb_env { int new_dst_cpu; enum cpu_idle_type idle; long imbalance; - /* The set of CPUs under consideration for load-balancing */ - struct cpumask *cpus; - unsigned int flags; unsigned int loop; @@ -3373,14 +3384,6 @@ static int tg_load_down(struct task_group *tg, void *data) static void update_h_load(long cpu) { - struct rq *rq = cpu_rq(cpu); - unsigned long now = jiffies; - - if (rq->h_load_throttle == now) - return; - - rq->h_load_throttle = now; - rcu_read_lock(); walk_tg_tree(tg_load_down, tg_nop, (void *)cpu); rcu_read_unlock(); @@ -3644,12 +3647,14 @@ fix_small_capacity(struct sched_domain *sd, struct sched_group *group) * @group: sched_group whose statistics are to be updated. * @load_idx: Load index of sched_domain of this_cpu for load calc. * @local_group: Does group contain this_cpu. + * @cpus: Set of cpus considered for load balancing. * @balance: Should we balance. * @sgs: variable to hold the statistics for this group. */ static inline void update_sg_lb_stats(struct lb_env *env, struct sched_group *group, int load_idx, - int local_group, int *balance, struct sg_lb_stats *sgs) + int local_group, const struct cpumask *cpus, + int *balance, struct sg_lb_stats *sgs) { unsigned long nr_running, max_nr_running, min_nr_running; unsigned long load, max_cpu_load, min_cpu_load; @@ -3666,7 +3671,7 @@ static inline void update_sg_lb_stats(struct lb_env *env, max_nr_running = 0; min_nr_running = ~0UL; - for_each_cpu_and(i, sched_group_cpus(group), env->cpus) { + for_each_cpu_and(i, sched_group_cpus(group), cpus) { struct rq *rq = cpu_rq(i); nr_running = rq->nr_running; @@ -3790,11 +3795,13 @@ static bool update_sd_pick_busiest(struct lb_env *env, /** * update_sd_lb_stats - Update sched_domain's statistics for load balancing. * @env: The load balancing environment. + * @cpus: Set of cpus considered for load balancing. * @balance: Should we balance. * @sds: variable to hold the statistics for this sched_domain. */ static inline void update_sd_lb_stats(struct lb_env *env, - int *balance, struct sd_lb_stats *sds) + const struct cpumask *cpus, + int *balance, struct sd_lb_stats *sds) { struct sched_domain *child = env->sd->child; struct sched_group *sg = env->sd->groups; @@ -3811,7 +3818,8 @@ static inline void update_sd_lb_stats(struct lb_env *env, local_group = cpumask_test_cpu(env->dst_cpu, sched_group_cpus(sg)); memset(&sgs, 0, sizeof(sgs)); - update_sg_lb_stats(env, sg, load_idx, local_group, balance, &sgs); + update_sg_lb_stats(env, sg, load_idx, local_group, + cpus, balance, &sgs); if (local_group && !(*balance)) return; @@ -4047,6 +4055,7 @@ static inline void calculate_imbalance(struct lb_env *env, struct sd_lb_stats *s * to restore balance. * * @env: The load balancing environment. + * @cpus: The set of CPUs under consideration for load-balancing. * @balance: Pointer to a variable indicating if this_cpu * is the appropriate cpu to perform load balancing at this_level. * @@ -4056,7 +4065,7 @@ static inline void calculate_imbalance(struct lb_env *env, struct sd_lb_stats *s * put to idle by rebalancing its tasks onto our group. */ static struct sched_group * -find_busiest_group(struct lb_env *env, int *balance) +find_busiest_group(struct lb_env *env, const struct cpumask *cpus, int *balance) { struct sd_lb_stats sds; @@ -4066,7 +4075,7 @@ find_busiest_group(struct lb_env *env, int *balance) * Compute the various statistics relavent for load balancing at * this level. */ - update_sd_lb_stats(env, balance, &sds); + update_sd_lb_stats(env, cpus, balance, &sds); /* * this_cpu is not the appropriate cpu to perform load balancing at @@ -4146,7 +4155,8 @@ find_busiest_group(struct lb_env *env, int *balance) * find_busiest_queue - find the busiest runqueue among the cpus in group. */ static struct rq *find_busiest_queue(struct lb_env *env, - struct sched_group *group) + struct sched_group *group, + const struct cpumask *cpus) { struct rq *busiest = NULL, *rq; unsigned long max_load = 0; @@ -4161,7 +4171,7 @@ static struct rq *find_busiest_queue(struct lb_env *env, if (!capacity) capacity = fix_small_capacity(env->sd, group); - if (!cpumask_test_cpu(i, env->cpus)) + if (!cpumask_test_cpu(i, cpus)) continue; rq = cpu_rq(i); @@ -4242,7 +4252,6 @@ static int load_balance(int this_cpu, struct rq *this_rq, .dst_grpmask = sched_group_cpus(sd->groups), .idle = idle, .loop_break = sched_nr_migrate_break, - .cpus = cpus, }; cpumask_copy(cpus, cpu_active_mask); @@ -4251,7 +4260,7 @@ static int load_balance(int this_cpu, struct rq *this_rq, schedstat_inc(sd, lb_count[idle]); redo: - group = find_busiest_group(&env, balance); + group = find_busiest_group(&env, cpus, balance); if (*balance == 0) goto out_balanced; @@ -4261,13 +4270,13 @@ static int load_balance(int this_cpu, struct rq *this_rq, goto out_balanced; } - busiest = find_busiest_queue(&env, group); + busiest = find_busiest_queue(&env, group, cpus); if (!busiest) { schedstat_inc(sd, lb_nobusyq[idle]); goto out_balanced; } - BUG_ON(busiest == env.dst_rq); + BUG_ON(busiest == this_rq); schedstat_add(sd, lb_imbalance[idle], env.imbalance); @@ -4285,10 +4294,11 @@ static int load_balance(int this_cpu, struct rq *this_rq, env.src_rq = busiest; env.loop_max = min(sysctl_sched_nr_migrate, busiest->nr_running); - update_h_load(env.src_cpu); more_balance: local_irq_save(flags); - double_rq_lock(env.dst_rq, busiest); + double_rq_lock(this_rq, busiest); + if (!env.loop) + update_h_load(env.src_cpu); /* * cur_ld_moved - load moved in current iteration @@ -4296,7 +4306,7 @@ static int load_balance(int this_cpu, struct rq *this_rq, */ cur_ld_moved = move_tasks(&env); ld_moved += cur_ld_moved; - double_rq_unlock(env.dst_rq, busiest); + double_rq_unlock(this_rq, busiest); local_irq_restore(flags); if (env.flags & LBF_NEED_BREAK) { @@ -4332,7 +4342,8 @@ static int load_balance(int this_cpu, struct rq *this_rq, if ((env.flags & LBF_SOME_PINNED) && env.imbalance > 0 && lb_iterations++ < max_lb_iterations) { - env.dst_rq = cpu_rq(env.new_dst_cpu); + this_rq = cpu_rq(env.new_dst_cpu); + env.dst_rq = this_rq; env.dst_cpu = env.new_dst_cpu; env.flags &= ~LBF_SOME_PINNED; env.loop = 0; @@ -4617,7 +4628,7 @@ static void nohz_balancer_kick(int cpu) return; } -static inline void nohz_balance_exit_idle(int cpu) +static inline void clear_nohz_tick_stopped(int cpu) { if (unlikely(test_bit(NOHZ_TICK_STOPPED, nohz_flags(cpu)))) { cpumask_clear_cpu(cpu, nohz.idle_cpus_mask); @@ -4657,23 +4668,28 @@ void set_cpu_sd_state_idle(void) } /* - * This routine will record that the cpu is going idle with tick stopped. + * This routine will record that this cpu is going idle with tick stopped. * This info will be used in performing idle load balancing in the future. */ -void nohz_balance_enter_idle(int cpu) +void select_nohz_load_balancer(int stop_tick) { + int cpu = smp_processor_id(); + /* * If this cpu is going down, then nothing needs to be done. */ if (!cpu_active(cpu)) return; - if (test_bit(NOHZ_TICK_STOPPED, nohz_flags(cpu))) - return; + if (stop_tick) { + if (test_bit(NOHZ_TICK_STOPPED, nohz_flags(cpu))) + return; - cpumask_set_cpu(cpu, nohz.idle_cpus_mask); - atomic_inc(&nohz.nr_cpus); - set_bit(NOHZ_TICK_STOPPED, nohz_flags(cpu)); + cpumask_set_cpu(cpu, nohz.idle_cpus_mask); + atomic_inc(&nohz.nr_cpus); + set_bit(NOHZ_TICK_STOPPED, nohz_flags(cpu)); + } + return; } static int __cpuinit sched_ilb_notifier(struct notifier_block *nfb, @@ -4681,7 +4697,7 @@ static int __cpuinit sched_ilb_notifier(struct notifier_block *nfb, { switch (action & ~CPU_TASKS_FROZEN) { case CPU_DYING: - nohz_balance_exit_idle(smp_processor_id()); + clear_nohz_tick_stopped(smp_processor_id()); return NOTIFY_OK; default: return NOTIFY_DONE; @@ -4803,15 +4819,14 @@ static void nohz_idle_balance(int this_cpu, enum cpu_idle_type idle) if (need_resched()) break; - rq = cpu_rq(balance_cpu); - - raw_spin_lock_irq(&rq->lock); - update_rq_clock(rq); - update_idle_cpu_load(rq); - raw_spin_unlock_irq(&rq->lock); + raw_spin_lock_irq(&this_rq->lock); + update_rq_clock(this_rq); + update_idle_cpu_load(this_rq); + raw_spin_unlock_irq(&this_rq->lock); rebalance_domains(balance_cpu, CPU_IDLE); + rq = cpu_rq(balance_cpu); if (time_after(this_rq->next_balance, rq->next_balance)) this_rq->next_balance = rq->next_balance; } @@ -4842,7 +4857,7 @@ static inline int nohz_kick_needed(struct rq *rq, int cpu) * busy tick after returning from idle, we will update the busy stats. */ set_cpu_sd_state_busy(); - nohz_balance_exit_idle(cpu); + clear_nohz_tick_stopped(cpu); /* * None are in tickless mode and hence no need for NOHZ idle load @@ -4935,9 +4950,6 @@ static void rq_online_fair(struct rq *rq) static void rq_offline_fair(struct rq *rq) { update_sysctl(); - - /* Ensure any throttled groups are reachable by pick_next_task */ - unthrottle_offline_cfs_rqs(rq); } #endif /* CONFIG_SMP */ diff --git a/trunk/kernel/sched/features.h b/trunk/kernel/sched/features.h index eebefcad7027..de00a486c5c6 100644 --- a/trunk/kernel/sched/features.h +++ b/trunk/kernel/sched/features.h @@ -11,6 +11,14 @@ SCHED_FEAT(GENTLE_FAIR_SLEEPERS, true) */ SCHED_FEAT(START_DEBIT, true) +/* + * Based on load and program behaviour, see if it makes sense to place + * a newly woken task on the same cpu as the task that woke it -- + * improve cache locality. Typically used with SYNC wakeups as + * generated by pipes and the like, see also SYNC_WAKEUPS. + */ +SCHED_FEAT(AFFINE_WAKEUPS, true) + /* * Prefer to schedule the task we woke last (assuming it failed * wakeup-preemption), since its likely going to consume data we @@ -34,7 +42,7 @@ SCHED_FEAT(CACHE_HOT_BUDDY, true) /* * Use arch dependent cpu power functions */ -SCHED_FEAT(ARCH_POWER, true) +SCHED_FEAT(ARCH_POWER, false) SCHED_FEAT(HRTICK, false) SCHED_FEAT(DOUBLE_TICK, false) diff --git a/trunk/kernel/sched/rt.c b/trunk/kernel/sched/rt.c index 418feb01344e..573e1ca01102 100644 --- a/trunk/kernel/sched/rt.c +++ b/trunk/kernel/sched/rt.c @@ -691,7 +691,6 @@ static void __disable_runtime(struct rq *rq) * runtime - in which case borrowing doesn't make sense. */ rt_rq->rt_runtime = RUNTIME_INF; - rt_rq->rt_throttled = 0; raw_spin_unlock(&rt_rq->rt_runtime_lock); raw_spin_unlock(&rt_b->rt_runtime_lock); } @@ -789,19 +788,6 @@ static int do_sched_rt_period_timer(struct rt_bandwidth *rt_b, int overrun) const struct cpumask *span; span = sched_rt_period_mask(); -#ifdef CONFIG_RT_GROUP_SCHED - /* - * FIXME: isolated CPUs should really leave the root task group, - * whether they are isolcpus or were isolated via cpusets, lest - * the timer run on a CPU which does not service all runqueues, - * potentially leaving other CPUs indefinitely throttled. If - * isolation is really required, the user will turn the throttle - * off to kill the perturbations it causes anyway. Meanwhile, - * this maintains functionality for boot and/or troubleshooting. - */ - if (rt_b == &root_task_group.rt_bandwidth) - span = cpu_online_mask; -#endif for_each_cpu(i, span) { int enqueue = 0; struct rt_rq *rt_rq = sched_rt_period_rt_rq(rt_b, i); @@ -1632,6 +1618,11 @@ static int push_rt_task(struct rq *rq) if (!next_task) return 0; +#ifdef __ARCH_WANT_INTERRUPTS_ON_CTXSW + if (unlikely(task_running(rq, next_task))) + return 0; +#endif + retry: if (unlikely(next_task == rq->curr)) { WARN_ON(1); diff --git a/trunk/kernel/sched/sched.h b/trunk/kernel/sched/sched.h index 7a7db09cfabc..c35a1a7dd4d6 100644 --- a/trunk/kernel/sched/sched.h +++ b/trunk/kernel/sched/sched.h @@ -80,7 +80,7 @@ extern struct mutex sched_domains_mutex; struct cfs_rq; struct rt_rq; -extern struct list_head task_groups; +static LIST_HEAD(task_groups); struct cfs_bandwidth { #ifdef CONFIG_CFS_BANDWIDTH @@ -374,11 +374,7 @@ struct rq { #ifdef CONFIG_FAIR_GROUP_SCHED /* list of leaf cfs_rq on this cpu: */ struct list_head leaf_cfs_rq_list; -#ifdef CONFIG_SMP - unsigned long h_load_throttle; -#endif /* CONFIG_SMP */ -#endif /* CONFIG_FAIR_GROUP_SCHED */ - +#endif #ifdef CONFIG_RT_GROUP_SCHED struct list_head leaf_rt_rq_list; #endif @@ -737,7 +733,11 @@ static inline void prepare_lock_switch(struct rq *rq, struct task_struct *next) */ next->on_cpu = 1; #endif +#ifdef __ARCH_WANT_INTERRUPTS_ON_CTXSW + raw_spin_unlock_irq(&rq->lock); +#else raw_spin_unlock(&rq->lock); +#endif } static inline void finish_lock_switch(struct rq *rq, struct task_struct *prev) @@ -751,7 +751,9 @@ static inline void finish_lock_switch(struct rq *rq, struct task_struct *prev) smp_wmb(); prev->on_cpu = 0; #endif +#ifndef __ARCH_WANT_INTERRUPTS_ON_CTXSW local_irq_enable(); +#endif } #endif /* __ARCH_WANT_UNLOCKED_CTXSW */ @@ -885,9 +887,6 @@ struct cpuacct { struct kernel_cpustat __percpu *cpustat; }; -extern struct cgroup_subsys cpuacct_subsys; -extern struct cpuacct root_cpuacct; - /* return cpu accounting group corresponding to this container */ static inline struct cpuacct *cgroup_ca(struct cgroup *cgrp) { @@ -914,16 +913,6 @@ extern void cpuacct_charge(struct task_struct *tsk, u64 cputime); static inline void cpuacct_charge(struct task_struct *tsk, u64 cputime) {} #endif -#ifdef CONFIG_PARAVIRT -static inline u64 steal_ticks(u64 steal) -{ - if (unlikely(steal > NSEC_PER_SEC)) - return div_u64(steal, TICK_NSEC); - - return __iter_div_u64_rem(steal, TICK_NSEC, &steal); -} -#endif - static inline void inc_nr_running(struct rq *rq) { rq->nr_running++; @@ -1151,6 +1140,7 @@ extern void print_rt_stats(struct seq_file *m, int cpu); extern void init_cfs_rq(struct cfs_rq *cfs_rq); extern void init_rt_rq(struct rt_rq *rt_rq, struct rq *rq); +extern void unthrottle_offline_cfs_rqs(struct rq *rq); extern void account_cfs_bandwidth_used(int enabled, int was_enabled); @@ -1163,53 +1153,3 @@ enum rq_nohz_flag_bits { #define nohz_flags(cpu) (&cpu_rq(cpu)->nohz_flags) #endif - -#ifdef CONFIG_IRQ_TIME_ACCOUNTING - -DECLARE_PER_CPU(u64, cpu_hardirq_time); -DECLARE_PER_CPU(u64, cpu_softirq_time); - -#ifndef CONFIG_64BIT -DECLARE_PER_CPU(seqcount_t, irq_time_seq); - -static inline void irq_time_write_begin(void) -{ - __this_cpu_inc(irq_time_seq.sequence); - smp_wmb(); -} - -static inline void irq_time_write_end(void) -{ - smp_wmb(); - __this_cpu_inc(irq_time_seq.sequence); -} - -static inline u64 irq_time_read(int cpu) -{ - u64 irq_time; - unsigned seq; - - do { - seq = read_seqcount_begin(&per_cpu(irq_time_seq, cpu)); - irq_time = per_cpu(cpu_softirq_time, cpu) + - per_cpu(cpu_hardirq_time, cpu); - } while (read_seqcount_retry(&per_cpu(irq_time_seq, cpu), seq)); - - return irq_time; -} -#else /* CONFIG_64BIT */ -static inline void irq_time_write_begin(void) -{ -} - -static inline void irq_time_write_end(void) -{ -} - -static inline u64 irq_time_read(int cpu) -{ - return per_cpu(cpu_softirq_time, cpu) + per_cpu(cpu_hardirq_time, cpu); -} -#endif /* CONFIG_64BIT */ -#endif /* CONFIG_IRQ_TIME_ACCOUNTING */ - diff --git a/trunk/kernel/sched/stop_task.c b/trunk/kernel/sched/stop_task.c index da5eb5bed84a..7b386e86fd23 100644 --- a/trunk/kernel/sched/stop_task.c +++ b/trunk/kernel/sched/stop_task.c @@ -27,10 +27,8 @@ static struct task_struct *pick_next_task_stop(struct rq *rq) { struct task_struct *stop = rq->stop; - if (stop && stop->on_rq) { - stop->se.exec_start = rq->clock_task; + if (stop && stop->on_rq) return stop; - } return NULL; } @@ -54,21 +52,6 @@ static void yield_task_stop(struct rq *rq) static void put_prev_task_stop(struct rq *rq, struct task_struct *prev) { - struct task_struct *curr = rq->curr; - u64 delta_exec; - - delta_exec = rq->clock_task - curr->se.exec_start; - if (unlikely((s64)delta_exec < 0)) - delta_exec = 0; - - schedstat_set(curr->se.statistics.exec_max, - max(curr->se.statistics.exec_max, delta_exec)); - - curr->se.sum_exec_runtime += delta_exec; - account_group_exec_runtime(curr, delta_exec); - - curr->se.exec_start = rq->clock_task; - cpuacct_charge(curr, delta_exec); } static void task_tick_stop(struct rq *rq, struct task_struct *curr, int queued) @@ -77,9 +60,6 @@ static void task_tick_stop(struct rq *rq, struct task_struct *curr, int queued) static void set_curr_task_stop(struct rq *rq) { - struct task_struct *stop = rq->stop; - - stop->se.exec_start = rq->clock_task; } static void switched_to_stop(struct rq *rq, struct task_struct *p) diff --git a/trunk/kernel/signal.c b/trunk/kernel/signal.c index 2c681f11b7d2..be4f856d52f8 100644 --- a/trunk/kernel/signal.c +++ b/trunk/kernel/signal.c @@ -1971,8 +1971,13 @@ static void ptrace_do_notify(int signr, int exit_code, int why) void ptrace_notify(int exit_code) { BUG_ON((exit_code & (0x7f | ~0xffff)) != SIGTRAP); - if (unlikely(current->task_works)) - task_work_run(); + if (unlikely(current->task_works)) { + if (test_and_clear_ti_thread_flag(current_thread_info(), + TIF_NOTIFY_RESUME)) { + smp_mb__after_clear_bit(); + task_work_run(); + } + } spin_lock_irq(¤t->sighand->siglock); ptrace_do_notify(SIGTRAP, exit_code, CLD_TRAPPED); @@ -2193,8 +2198,13 @@ int get_signal_to_deliver(siginfo_t *info, struct k_sigaction *return_ka, struct signal_struct *signal = current->signal; int signr; - if (unlikely(current->task_works)) - task_work_run(); + if (unlikely(current->task_works)) { + if (test_and_clear_ti_thread_flag(current_thread_info(), + TIF_NOTIFY_RESUME)) { + smp_mb__after_clear_bit(); + task_work_run(); + } + } if (unlikely(uprobe_deny_signal())) return 0; diff --git a/trunk/kernel/smpboot.c b/trunk/kernel/smpboot.c index d6c5fc054242..98f60c5caa1b 100644 --- a/trunk/kernel/smpboot.c +++ b/trunk/kernel/smpboot.c @@ -1,22 +1,14 @@ /* * Common SMP CPU bringup/teardown functions */ -#include #include #include #include -#include -#include #include -#include #include -#include -#include #include "smpboot.h" -#ifdef CONFIG_SMP - #ifdef CONFIG_GENERIC_SMP_IDLE_THREAD /* * For the hotplug case we keep the task structs around and reuse @@ -73,228 +65,3 @@ void __init idle_threads_init(void) } } #endif - -#endif /* #ifdef CONFIG_SMP */ - -static LIST_HEAD(hotplug_threads); -static DEFINE_MUTEX(smpboot_threads_lock); - -struct smpboot_thread_data { - unsigned int cpu; - unsigned int status; - struct smp_hotplug_thread *ht; -}; - -enum { - HP_THREAD_NONE = 0, - HP_THREAD_ACTIVE, - HP_THREAD_PARKED, -}; - -/** - * smpboot_thread_fn - percpu hotplug thread loop function - * @data: thread data pointer - * - * Checks for thread stop and park conditions. Calls the necessary - * setup, cleanup, park and unpark functions for the registered - * thread. - * - * Returns 1 when the thread should exit, 0 otherwise. - */ -static int smpboot_thread_fn(void *data) -{ - struct smpboot_thread_data *td = data; - struct smp_hotplug_thread *ht = td->ht; - - while (1) { - set_current_state(TASK_INTERRUPTIBLE); - preempt_disable(); - if (kthread_should_stop()) { - set_current_state(TASK_RUNNING); - preempt_enable(); - if (ht->cleanup) - ht->cleanup(td->cpu, cpu_online(td->cpu)); - kfree(td); - return 0; - } - - if (kthread_should_park()) { - __set_current_state(TASK_RUNNING); - preempt_enable(); - if (ht->park && td->status == HP_THREAD_ACTIVE) { - BUG_ON(td->cpu != smp_processor_id()); - ht->park(td->cpu); - td->status = HP_THREAD_PARKED; - } - kthread_parkme(); - /* We might have been woken for stop */ - continue; - } - - BUG_ON(td->cpu != smp_processor_id()); - - /* Check for state change setup */ - switch (td->status) { - case HP_THREAD_NONE: - preempt_enable(); - if (ht->setup) - ht->setup(td->cpu); - td->status = HP_THREAD_ACTIVE; - preempt_disable(); - break; - case HP_THREAD_PARKED: - preempt_enable(); - if (ht->unpark) - ht->unpark(td->cpu); - td->status = HP_THREAD_ACTIVE; - preempt_disable(); - break; - } - - if (!ht->thread_should_run(td->cpu)) { - preempt_enable(); - schedule(); - } else { - set_current_state(TASK_RUNNING); - preempt_enable(); - ht->thread_fn(td->cpu); - } - } -} - -static int -__smpboot_create_thread(struct smp_hotplug_thread *ht, unsigned int cpu) -{ - struct task_struct *tsk = *per_cpu_ptr(ht->store, cpu); - struct smpboot_thread_data *td; - - if (tsk) - return 0; - - td = kzalloc_node(sizeof(*td), GFP_KERNEL, cpu_to_node(cpu)); - if (!td) - return -ENOMEM; - td->cpu = cpu; - td->ht = ht; - - tsk = kthread_create_on_cpu(smpboot_thread_fn, td, cpu, - ht->thread_comm); - if (IS_ERR(tsk)) { - kfree(td); - return PTR_ERR(tsk); - } - - get_task_struct(tsk); - *per_cpu_ptr(ht->store, cpu) = tsk; - return 0; -} - -int smpboot_create_threads(unsigned int cpu) -{ - struct smp_hotplug_thread *cur; - int ret = 0; - - mutex_lock(&smpboot_threads_lock); - list_for_each_entry(cur, &hotplug_threads, list) { - ret = __smpboot_create_thread(cur, cpu); - if (ret) - break; - } - mutex_unlock(&smpboot_threads_lock); - return ret; -} - -static void smpboot_unpark_thread(struct smp_hotplug_thread *ht, unsigned int cpu) -{ - struct task_struct *tsk = *per_cpu_ptr(ht->store, cpu); - - kthread_unpark(tsk); -} - -void smpboot_unpark_threads(unsigned int cpu) -{ - struct smp_hotplug_thread *cur; - - mutex_lock(&smpboot_threads_lock); - list_for_each_entry(cur, &hotplug_threads, list) - smpboot_unpark_thread(cur, cpu); - mutex_unlock(&smpboot_threads_lock); -} - -static void smpboot_park_thread(struct smp_hotplug_thread *ht, unsigned int cpu) -{ - struct task_struct *tsk = *per_cpu_ptr(ht->store, cpu); - - if (tsk) - kthread_park(tsk); -} - -void smpboot_park_threads(unsigned int cpu) -{ - struct smp_hotplug_thread *cur; - - mutex_lock(&smpboot_threads_lock); - list_for_each_entry_reverse(cur, &hotplug_threads, list) - smpboot_park_thread(cur, cpu); - mutex_unlock(&smpboot_threads_lock); -} - -static void smpboot_destroy_threads(struct smp_hotplug_thread *ht) -{ - unsigned int cpu; - - /* We need to destroy also the parked threads of offline cpus */ - for_each_possible_cpu(cpu) { - struct task_struct *tsk = *per_cpu_ptr(ht->store, cpu); - - if (tsk) { - kthread_stop(tsk); - put_task_struct(tsk); - *per_cpu_ptr(ht->store, cpu) = NULL; - } - } -} - -/** - * smpboot_register_percpu_thread - Register a per_cpu thread related to hotplug - * @plug_thread: Hotplug thread descriptor - * - * Creates and starts the threads on all online cpus. - */ -int smpboot_register_percpu_thread(struct smp_hotplug_thread *plug_thread) -{ - unsigned int cpu; - int ret = 0; - - mutex_lock(&smpboot_threads_lock); - for_each_online_cpu(cpu) { - ret = __smpboot_create_thread(plug_thread, cpu); - if (ret) { - smpboot_destroy_threads(plug_thread); - goto out; - } - smpboot_unpark_thread(plug_thread, cpu); - } - list_add(&plug_thread->list, &hotplug_threads); -out: - mutex_unlock(&smpboot_threads_lock); - return ret; -} -EXPORT_SYMBOL_GPL(smpboot_register_percpu_thread); - -/** - * smpboot_unregister_percpu_thread - Unregister a per_cpu thread related to hotplug - * @plug_thread: Hotplug thread descriptor - * - * Stops all threads on all possible cpus. - */ -void smpboot_unregister_percpu_thread(struct smp_hotplug_thread *plug_thread) -{ - get_online_cpus(); - mutex_lock(&smpboot_threads_lock); - list_del(&plug_thread->list); - smpboot_destroy_threads(plug_thread); - mutex_unlock(&smpboot_threads_lock); - put_online_cpus(); -} -EXPORT_SYMBOL_GPL(smpboot_unregister_percpu_thread); diff --git a/trunk/kernel/smpboot.h b/trunk/kernel/smpboot.h index 72415a0eb955..6ef9433e1c70 100644 --- a/trunk/kernel/smpboot.h +++ b/trunk/kernel/smpboot.h @@ -13,8 +13,4 @@ static inline void idle_thread_set_boot_cpu(void) { } static inline void idle_threads_init(void) { } #endif -int smpboot_create_threads(unsigned int cpu); -void smpboot_park_threads(unsigned int cpu); -void smpboot_unpark_threads(unsigned int cpu); - #endif diff --git a/trunk/kernel/softirq.c b/trunk/kernel/softirq.c index cc96bdc0c2c9..b73e681df09e 100644 --- a/trunk/kernel/softirq.c +++ b/trunk/kernel/softirq.c @@ -23,7 +23,6 @@ #include #include #include -#include #include #define CREATE_TRACE_POINTS @@ -221,7 +220,7 @@ asmlinkage void __do_softirq(void) current->flags &= ~PF_MEMALLOC; pending = local_softirq_pending(); - vtime_account(current); + account_system_vtime(current); __local_bh_disable((unsigned long)__builtin_return_address(0), SOFTIRQ_OFFSET); @@ -272,7 +271,7 @@ asmlinkage void __do_softirq(void) lockdep_softirq_exit(); - vtime_account(current); + account_system_vtime(current); __local_bh_enable(SOFTIRQ_OFFSET); tsk_restore_flags(current, old_flags, PF_MEMALLOC); } @@ -341,7 +340,7 @@ static inline void invoke_softirq(void) */ void irq_exit(void) { - vtime_account(current); + account_system_vtime(current); trace_hardirq_exit(); sub_preempt_count(IRQ_EXIT_OFFSET); if (!in_interrupt() && local_softirq_pending()) @@ -743,22 +742,49 @@ void __init softirq_init(void) open_softirq(HI_SOFTIRQ, tasklet_hi_action); } -static int ksoftirqd_should_run(unsigned int cpu) +static int run_ksoftirqd(void * __bind_cpu) { - return local_softirq_pending(); -} + set_current_state(TASK_INTERRUPTIBLE); -static void run_ksoftirqd(unsigned int cpu) -{ - local_irq_disable(); - if (local_softirq_pending()) { - __do_softirq(); - rcu_note_context_switch(cpu); - local_irq_enable(); - cond_resched(); - return; + while (!kthread_should_stop()) { + preempt_disable(); + if (!local_softirq_pending()) { + schedule_preempt_disabled(); + } + + __set_current_state(TASK_RUNNING); + + while (local_softirq_pending()) { + /* Preempt disable stops cpu going offline. + If already offline, we'll be on wrong CPU: + don't process */ + if (cpu_is_offline((long)__bind_cpu)) + goto wait_to_die; + local_irq_disable(); + if (local_softirq_pending()) + __do_softirq(); + local_irq_enable(); + sched_preempt_enable_no_resched(); + cond_resched(); + preempt_disable(); + rcu_note_context_switch((long)__bind_cpu); + } + preempt_enable(); + set_current_state(TASK_INTERRUPTIBLE); } - local_irq_enable(); + __set_current_state(TASK_RUNNING); + return 0; + +wait_to_die: + preempt_enable(); + /* Wait for kthread_stop */ + set_current_state(TASK_INTERRUPTIBLE); + while (!kthread_should_stop()) { + schedule(); + set_current_state(TASK_INTERRUPTIBLE); + } + __set_current_state(TASK_RUNNING); + return 0; } #ifdef CONFIG_HOTPLUG_CPU @@ -824,14 +850,50 @@ static int __cpuinit cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) { + int hotcpu = (unsigned long)hcpu; + struct task_struct *p; + switch (action) { + case CPU_UP_PREPARE: + case CPU_UP_PREPARE_FROZEN: + p = kthread_create_on_node(run_ksoftirqd, + hcpu, + cpu_to_node(hotcpu), + "ksoftirqd/%d", hotcpu); + if (IS_ERR(p)) { + printk("ksoftirqd for %i failed\n", hotcpu); + return notifier_from_errno(PTR_ERR(p)); + } + kthread_bind(p, hotcpu); + per_cpu(ksoftirqd, hotcpu) = p; + break; + case CPU_ONLINE: + case CPU_ONLINE_FROZEN: + wake_up_process(per_cpu(ksoftirqd, hotcpu)); + break; #ifdef CONFIG_HOTPLUG_CPU + case CPU_UP_CANCELED: + case CPU_UP_CANCELED_FROZEN: + if (!per_cpu(ksoftirqd, hotcpu)) + break; + /* Unbind so it can run. Fall thru. */ + kthread_bind(per_cpu(ksoftirqd, hotcpu), + cpumask_any(cpu_online_mask)); case CPU_DEAD: - case CPU_DEAD_FROZEN: - takeover_tasklets((unsigned long)hcpu); + case CPU_DEAD_FROZEN: { + static const struct sched_param param = { + .sched_priority = MAX_RT_PRIO-1 + }; + + p = per_cpu(ksoftirqd, hotcpu); + per_cpu(ksoftirqd, hotcpu) = NULL; + sched_setscheduler_nocheck(p, SCHED_FIFO, ¶m); + kthread_stop(p); + takeover_tasklets(hotcpu); break; -#endif /* CONFIG_HOTPLUG_CPU */ } +#endif /* CONFIG_HOTPLUG_CPU */ + } return NOTIFY_OK; } @@ -839,19 +901,14 @@ static struct notifier_block __cpuinitdata cpu_nfb = { .notifier_call = cpu_callback }; -static struct smp_hotplug_thread softirq_threads = { - .store = &ksoftirqd, - .thread_should_run = ksoftirqd_should_run, - .thread_fn = run_ksoftirqd, - .thread_comm = "ksoftirqd/%u", -}; - static __init int spawn_ksoftirqd(void) { - register_cpu_notifier(&cpu_nfb); - - BUG_ON(smpboot_register_percpu_thread(&softirq_threads)); + void *cpu = (void *)(long)smp_processor_id(); + int err = cpu_callback(&cpu_nfb, CPU_UP_PREPARE, cpu); + BUG_ON(err != NOTIFY_OK); + cpu_callback(&cpu_nfb, CPU_ONLINE, cpu); + register_cpu_notifier(&cpu_nfb); return 0; } early_initcall(spawn_ksoftirqd); diff --git a/trunk/kernel/sysctl.c b/trunk/kernel/sysctl.c index 84c76a34e41c..87174ef59161 100644 --- a/trunk/kernel/sysctl.c +++ b/trunk/kernel/sysctl.c @@ -307,7 +307,7 @@ static struct ctl_table kern_table[] = { .extra2 = &max_sched_tunable_scaling, }, { - .procname = "sched_migration_cost_ns", + .procname = "sched_migration_cost", .data = &sysctl_sched_migration_cost, .maxlen = sizeof(unsigned int), .mode = 0644, @@ -321,14 +321,14 @@ static struct ctl_table kern_table[] = { .proc_handler = proc_dointvec, }, { - .procname = "sched_time_avg_ms", + .procname = "sched_time_avg", .data = &sysctl_sched_time_avg, .maxlen = sizeof(unsigned int), .mode = 0644, .proc_handler = proc_dointvec, }, { - .procname = "sched_shares_window_ns", + .procname = "sched_shares_window", .data = &sysctl_sched_shares_window, .maxlen = sizeof(unsigned int), .mode = 0644, @@ -1544,7 +1544,7 @@ static struct ctl_table fs_table[] = { static struct ctl_table debug_table[] = { #if defined(CONFIG_X86) || defined(CONFIG_PPC) || defined(CONFIG_SPARC) || \ - defined(CONFIG_S390) || defined(CONFIG_TILE) || defined(CONFIG_ARM64) + defined(CONFIG_S390) || defined(CONFIG_TILE) { .procname = "exception-trace", .data = &show_unhandled_signals, diff --git a/trunk/kernel/task_work.c b/trunk/kernel/task_work.c index 65bd3c92d6f3..91d4e1742a0c 100644 --- a/trunk/kernel/task_work.c +++ b/trunk/kernel/task_work.c @@ -2,20 +2,26 @@ #include #include -static struct callback_head work_exited; /* all we need is ->next == NULL */ - int -task_work_add(struct task_struct *task, struct callback_head *work, bool notify) +task_work_add(struct task_struct *task, struct callback_head *twork, bool notify) { - struct callback_head *head; + struct callback_head *last, *first; + unsigned long flags; - do { - head = ACCESS_ONCE(task->task_works); - if (unlikely(head == &work_exited)) - return -ESRCH; - work->next = head; - } while (cmpxchg(&task->task_works, head, work) != head); + /* + * Not inserting the new work if the task has already passed + * exit_task_work() is the responisbility of callers. + */ + raw_spin_lock_irqsave(&task->pi_lock, flags); + last = task->task_works; + first = last ? last->next : twork; + twork->next = first; + if (last) + last->next = twork; + task->task_works = twork; + raw_spin_unlock_irqrestore(&task->pi_lock, flags); + /* test_and_set_bit() implies mb(), see tracehook_notify_resume(). */ if (notify) set_notify_resume(task); return 0; @@ -24,69 +30,51 @@ task_work_add(struct task_struct *task, struct callback_head *work, bool notify) struct callback_head * task_work_cancel(struct task_struct *task, task_work_func_t func) { - struct callback_head **pprev = &task->task_works; - struct callback_head *work = NULL; unsigned long flags; - /* - * If cmpxchg() fails we continue without updating pprev. - * Either we raced with task_work_add() which added the - * new entry before this work, we will find it again. Or - * we raced with task_work_run(), *pprev == NULL/exited. - */ + struct callback_head *last, *res = NULL; + raw_spin_lock_irqsave(&task->pi_lock, flags); - while ((work = ACCESS_ONCE(*pprev))) { - read_barrier_depends(); - if (work->func != func) - pprev = &work->next; - else if (cmpxchg(pprev, work, work->next) == work) - break; + last = task->task_works; + if (last) { + struct callback_head *q = last, *p = q->next; + while (1) { + if (p->func == func) { + q->next = p->next; + if (p == last) + task->task_works = q == p ? NULL : q; + res = p; + break; + } + if (p == last) + break; + q = p; + p = q->next; + } } raw_spin_unlock_irqrestore(&task->pi_lock, flags); - - return work; + return res; } void task_work_run(void) { struct task_struct *task = current; - struct callback_head *work, *head, *next; - - for (;;) { - /* - * work->func() can do task_work_add(), do not set - * work_exited unless the list is empty. - */ - do { - work = ACCESS_ONCE(task->task_works); - head = !work && (task->flags & PF_EXITING) ? - &work_exited : NULL; - } while (cmpxchg(&task->task_works, work, head) != work); + struct callback_head *p, *q; - if (!work) - break; - /* - * Synchronize with task_work_cancel(). It can't remove - * the first entry == work, cmpxchg(task_works) should - * fail, but it can play with *work and other entries. - */ - raw_spin_unlock_wait(&task->pi_lock); - smp_mb(); + while (1) { + raw_spin_lock_irq(&task->pi_lock); + p = task->task_works; + task->task_works = NULL; + raw_spin_unlock_irq(&task->pi_lock); - /* Reverse the list to run the works in fifo order */ - head = NULL; - do { - next = work->next; - work->next = head; - head = work; - work = next; - } while (work); + if (unlikely(!p)) + return; - work = head; - do { - next = work->next; - work->func(work); - work = next; - cond_resched(); - } while (work); + q = p->next; /* head */ + p->next = NULL; /* cut it */ + while (q) { + p = q->next; + q->func(q); + q = p; + } } } diff --git a/trunk/kernel/time/jiffies.c b/trunk/kernel/time/jiffies.c index 46da0537c10b..a470154e0408 100644 --- a/trunk/kernel/time/jiffies.c +++ b/trunk/kernel/time/jiffies.c @@ -37,7 +37,7 @@ * requested HZ value. It is also not recommended * for "tick-less" systems. */ -#define NSEC_PER_JIFFY ((u32)((((u64)NSEC_PER_SEC)<<8)/SHIFTED_HZ)) +#define NSEC_PER_JIFFY ((u32)((((u64)NSEC_PER_SEC)<<8)/ACTHZ)) /* Since jiffies uses a simple NSEC_PER_JIFFY multiplier * conversion, the .shift value could be zero. However diff --git a/trunk/kernel/time/ntp.c b/trunk/kernel/time/ntp.c index 24174b4d669b..b7fbadc5c973 100644 --- a/trunk/kernel/time/ntp.c +++ b/trunk/kernel/time/ntp.c @@ -28,7 +28,7 @@ DEFINE_SPINLOCK(ntp_lock); /* USER_HZ period (usecs): */ unsigned long tick_usec = TICK_USEC; -/* SHIFTED_HZ period (nsecs): */ +/* ACTHZ period (nsecs): */ unsigned long tick_nsec; static u64 tick_length; diff --git a/trunk/kernel/time/tick-sched.c b/trunk/kernel/time/tick-sched.c index f423bdd035c2..024540f97f74 100644 --- a/trunk/kernel/time/tick-sched.c +++ b/trunk/kernel/time/tick-sched.c @@ -372,7 +372,7 @@ static ktime_t tick_nohz_stop_sched_tick(struct tick_sched *ts, * the scheduler tick in nohz_restart_sched_tick. */ if (!ts->tick_stopped) { - nohz_balance_enter_idle(cpu); + select_nohz_load_balancer(1); calc_load_enter_idle(); ts->last_tick = hrtimer_get_expires(&ts->sched_timer); @@ -436,8 +436,7 @@ static bool can_stop_idle_tick(int cpu, struct tick_sched *ts) if (unlikely(local_softirq_pending() && cpu_online(cpu))) { static int ratelimit; - if (ratelimit < 10 && - (local_softirq_pending() & SOFTIRQ_STOP_IDLE_MASK)) { + if (ratelimit < 10) { printk(KERN_ERR "NOHZ: local_softirq_pending %02x\n", (unsigned int) local_softirq_pending()); ratelimit++; @@ -570,10 +569,10 @@ static void tick_nohz_restart(struct tick_sched *ts, ktime_t now) static void tick_nohz_restart_sched_tick(struct tick_sched *ts, ktime_t now) { /* Update jiffies first */ + select_nohz_load_balancer(0); tick_do_update_jiffies64(now); update_cpu_load_nohz(); - calc_load_exit_idle(); touch_softlockup_watchdog(); /* * Cancel the scheduled timer and restore the tick diff --git a/trunk/kernel/time/timekeeping.c b/trunk/kernel/time/timekeeping.c index d3b91e75cecd..f045cc50832d 100644 --- a/trunk/kernel/time/timekeeping.c +++ b/trunk/kernel/time/timekeeping.c @@ -65,14 +65,14 @@ struct timekeeper { * used instead. */ struct timespec wall_to_monotonic; - /* Offset clock monotonic -> clock realtime */ - ktime_t offs_real; /* time spent in suspend */ struct timespec total_sleep_time; - /* Offset clock monotonic -> clock boottime */ - ktime_t offs_boot; /* The raw monotonic time for the CLOCK_MONOTONIC_RAW posix clock. */ struct timespec raw_time; + /* Offset clock monotonic -> clock realtime */ + ktime_t offs_real; + /* Offset clock monotonic -> clock boottime */ + ktime_t offs_boot; /* Seqlock for all timekeeper values */ seqlock_t lock; }; @@ -108,39 +108,13 @@ static struct timespec tk_xtime(struct timekeeper *tk) static void tk_set_xtime(struct timekeeper *tk, const struct timespec *ts) { tk->xtime_sec = ts->tv_sec; - tk->xtime_nsec = (u64)ts->tv_nsec << tk->shift; + tk->xtime_nsec = ts->tv_nsec << tk->shift; } static void tk_xtime_add(struct timekeeper *tk, const struct timespec *ts) { tk->xtime_sec += ts->tv_sec; - tk->xtime_nsec += (u64)ts->tv_nsec << tk->shift; - tk_normalize_xtime(tk); -} - -static void tk_set_wall_to_mono(struct timekeeper *tk, struct timespec wtm) -{ - struct timespec tmp; - - /* - * Verify consistency of: offset_real = -wall_to_monotonic - * before modifying anything - */ - set_normalized_timespec(&tmp, -tk->wall_to_monotonic.tv_sec, - -tk->wall_to_monotonic.tv_nsec); - WARN_ON_ONCE(tk->offs_real.tv64 != timespec_to_ktime(tmp).tv64); - tk->wall_to_monotonic = wtm; - set_normalized_timespec(&tmp, -wtm.tv_sec, -wtm.tv_nsec); - tk->offs_real = timespec_to_ktime(tmp); -} - -static void tk_set_sleep_time(struct timekeeper *tk, struct timespec t) -{ - /* Verify consistency before modifying */ - WARN_ON_ONCE(tk->offs_boot.tv64 != timespec_to_ktime(tk->total_sleep_time).tv64); - - tk->total_sleep_time = t; - tk->offs_boot = timespec_to_ktime(t); + tk->xtime_nsec += ts->tv_nsec << tk->shift; } /** @@ -243,6 +217,14 @@ static inline s64 timekeeping_get_ns_raw(struct timekeeper *tk) return nsec + arch_gettimeoffset(); } +static void update_rt_offset(struct timekeeper *tk) +{ + struct timespec tmp, *wtm = &tk->wall_to_monotonic; + + set_normalized_timespec(&tmp, -wtm->tv_sec, -wtm->tv_nsec); + tk->offs_real = timespec_to_ktime(tmp); +} + /* must hold write on timekeeper.lock */ static void timekeeping_update(struct timekeeper *tk, bool clearntp) { @@ -252,10 +234,12 @@ static void timekeeping_update(struct timekeeper *tk, bool clearntp) tk->ntp_error = 0; ntp_clear(); } + update_rt_offset(tk); xt = tk_xtime(tk); update_vsyscall(&xt, &tk->wall_to_monotonic, tk->clock, tk->mult); } + /** * timekeeping_forward_now - update clock to the current time * @@ -277,7 +261,7 @@ static void timekeeping_forward_now(struct timekeeper *tk) tk->xtime_nsec += cycle_delta * tk->mult; /* If arch requires, add in gettimeoffset() */ - tk->xtime_nsec += (u64)arch_gettimeoffset() << tk->shift; + tk->xtime_nsec += arch_gettimeoffset() << tk->shift; tk_normalize_xtime(tk); @@ -293,39 +277,38 @@ static void timekeeping_forward_now(struct timekeeper *tk) */ void getnstimeofday(struct timespec *ts) { - struct timekeeper *tk = &timekeeper; unsigned long seq; s64 nsecs = 0; WARN_ON(timekeeping_suspended); do { - seq = read_seqbegin(&tk->lock); + seq = read_seqbegin(&timekeeper.lock); - ts->tv_sec = tk->xtime_sec; - nsecs = timekeeping_get_ns(tk); + ts->tv_sec = timekeeper.xtime_sec; + ts->tv_nsec = timekeeping_get_ns(&timekeeper); - } while (read_seqretry(&tk->lock, seq)); + } while (read_seqretry(&timekeeper.lock, seq)); - ts->tv_nsec = 0; timespec_add_ns(ts, nsecs); } EXPORT_SYMBOL(getnstimeofday); ktime_t ktime_get(void) { - struct timekeeper *tk = &timekeeper; unsigned int seq; s64 secs, nsecs; WARN_ON(timekeeping_suspended); do { - seq = read_seqbegin(&tk->lock); - secs = tk->xtime_sec + tk->wall_to_monotonic.tv_sec; - nsecs = timekeeping_get_ns(tk) + tk->wall_to_monotonic.tv_nsec; + seq = read_seqbegin(&timekeeper.lock); + secs = timekeeper.xtime_sec + + timekeeper.wall_to_monotonic.tv_sec; + nsecs = timekeeping_get_ns(&timekeeper) + + timekeeper.wall_to_monotonic.tv_nsec; - } while (read_seqretry(&tk->lock, seq)); + } while (read_seqretry(&timekeeper.lock, seq)); /* * Use ktime_set/ktime_add_ns to create a proper ktime on * 32-bit architectures without CONFIG_KTIME_SCALAR. @@ -344,24 +327,21 @@ EXPORT_SYMBOL_GPL(ktime_get); */ void ktime_get_ts(struct timespec *ts) { - struct timekeeper *tk = &timekeeper; struct timespec tomono; - s64 nsec; unsigned int seq; WARN_ON(timekeeping_suspended); do { - seq = read_seqbegin(&tk->lock); - ts->tv_sec = tk->xtime_sec; - nsec = timekeeping_get_ns(tk); - tomono = tk->wall_to_monotonic; + seq = read_seqbegin(&timekeeper.lock); + ts->tv_sec = timekeeper.xtime_sec; + ts->tv_nsec = timekeeping_get_ns(&timekeeper); + tomono = timekeeper.wall_to_monotonic; - } while (read_seqretry(&tk->lock, seq)); + } while (read_seqretry(&timekeeper.lock, seq)); - ts->tv_sec += tomono.tv_sec; - ts->tv_nsec = 0; - timespec_add_ns(ts, nsec + tomono.tv_nsec); + set_normalized_timespec(ts, ts->tv_sec + tomono.tv_sec, + ts->tv_nsec + tomono.tv_nsec); } EXPORT_SYMBOL_GPL(ktime_get_ts); @@ -378,23 +358,22 @@ EXPORT_SYMBOL_GPL(ktime_get_ts); */ void getnstime_raw_and_real(struct timespec *ts_raw, struct timespec *ts_real) { - struct timekeeper *tk = &timekeeper; unsigned long seq; s64 nsecs_raw, nsecs_real; WARN_ON_ONCE(timekeeping_suspended); do { - seq = read_seqbegin(&tk->lock); + seq = read_seqbegin(&timekeeper.lock); - *ts_raw = tk->raw_time; - ts_real->tv_sec = tk->xtime_sec; + *ts_raw = timekeeper.raw_time; + ts_real->tv_sec = timekeeper.xtime_sec; ts_real->tv_nsec = 0; - nsecs_raw = timekeeping_get_ns_raw(tk); - nsecs_real = timekeeping_get_ns(tk); + nsecs_raw = timekeeping_get_ns_raw(&timekeeper); + nsecs_real = timekeeping_get_ns(&timekeeper); - } while (read_seqretry(&tk->lock, seq)); + } while (read_seqretry(&timekeeper.lock, seq)); timespec_add_ns(ts_raw, nsecs_raw); timespec_add_ns(ts_real, nsecs_real); @@ -427,28 +406,28 @@ EXPORT_SYMBOL(do_gettimeofday); */ int do_settimeofday(const struct timespec *tv) { - struct timekeeper *tk = &timekeeper; struct timespec ts_delta, xt; unsigned long flags; - if (!timespec_valid_strict(tv)) + if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC) return -EINVAL; - write_seqlock_irqsave(&tk->lock, flags); + write_seqlock_irqsave(&timekeeper.lock, flags); - timekeeping_forward_now(tk); + timekeeping_forward_now(&timekeeper); - xt = tk_xtime(tk); + xt = tk_xtime(&timekeeper); ts_delta.tv_sec = tv->tv_sec - xt.tv_sec; ts_delta.tv_nsec = tv->tv_nsec - xt.tv_nsec; - tk_set_wall_to_mono(tk, timespec_sub(tk->wall_to_monotonic, ts_delta)); + timekeeper.wall_to_monotonic = + timespec_sub(timekeeper.wall_to_monotonic, ts_delta); - tk_set_xtime(tk, tv); + tk_set_xtime(&timekeeper, tv); - timekeeping_update(tk, true); + timekeeping_update(&timekeeper, true); - write_sequnlock_irqrestore(&tk->lock, flags); + write_sequnlock_irqrestore(&timekeeper.lock, flags); /* signal hrtimers about time change */ clock_was_set(); @@ -457,6 +436,7 @@ int do_settimeofday(const struct timespec *tv) } EXPORT_SYMBOL(do_settimeofday); + /** * timekeeping_inject_offset - Adds or subtracts from the current time. * @tv: pointer to the timespec variable containing the offset @@ -465,37 +445,28 @@ EXPORT_SYMBOL(do_settimeofday); */ int timekeeping_inject_offset(struct timespec *ts) { - struct timekeeper *tk = &timekeeper; unsigned long flags; - struct timespec tmp; - int ret = 0; if ((unsigned long)ts->tv_nsec >= NSEC_PER_SEC) return -EINVAL; - write_seqlock_irqsave(&tk->lock, flags); + write_seqlock_irqsave(&timekeeper.lock, flags); - timekeeping_forward_now(tk); + timekeeping_forward_now(&timekeeper); - /* Make sure the proposed value is valid */ - tmp = timespec_add(tk_xtime(tk), *ts); - if (!timespec_valid_strict(&tmp)) { - ret = -EINVAL; - goto error; - } - tk_xtime_add(tk, ts); - tk_set_wall_to_mono(tk, timespec_sub(tk->wall_to_monotonic, *ts)); + tk_xtime_add(&timekeeper, ts); + timekeeper.wall_to_monotonic = + timespec_sub(timekeeper.wall_to_monotonic, *ts); -error: /* even if we error out, we forwarded the time, so call update */ - timekeeping_update(tk, true); + timekeeping_update(&timekeeper, true); - write_sequnlock_irqrestore(&tk->lock, flags); + write_sequnlock_irqrestore(&timekeeper.lock, flags); /* signal hrtimers about time change */ clock_was_set(); - return ret; + return 0; } EXPORT_SYMBOL(timekeeping_inject_offset); @@ -506,24 +477,23 @@ EXPORT_SYMBOL(timekeeping_inject_offset); */ static int change_clocksource(void *data) { - struct timekeeper *tk = &timekeeper; struct clocksource *new, *old; unsigned long flags; new = (struct clocksource *) data; - write_seqlock_irqsave(&tk->lock, flags); + write_seqlock_irqsave(&timekeeper.lock, flags); - timekeeping_forward_now(tk); + timekeeping_forward_now(&timekeeper); if (!new->enable || new->enable(new) == 0) { - old = tk->clock; - tk_setup_internals(tk, new); + old = timekeeper.clock; + tk_setup_internals(&timekeeper, new); if (old->disable) old->disable(old); } - timekeeping_update(tk, true); + timekeeping_update(&timekeeper, true); - write_sequnlock_irqrestore(&tk->lock, flags); + write_sequnlock_irqrestore(&timekeeper.lock, flags); return 0; } @@ -537,9 +507,7 @@ static int change_clocksource(void *data) */ void timekeeping_notify(struct clocksource *clock) { - struct timekeeper *tk = &timekeeper; - - if (tk->clock == clock) + if (timekeeper.clock == clock) return; stop_machine(change_clocksource, clock, NULL); tick_clock_notify(); @@ -568,36 +536,35 @@ EXPORT_SYMBOL_GPL(ktime_get_real); */ void getrawmonotonic(struct timespec *ts) { - struct timekeeper *tk = &timekeeper; unsigned long seq; s64 nsecs; do { - seq = read_seqbegin(&tk->lock); - nsecs = timekeeping_get_ns_raw(tk); - *ts = tk->raw_time; + seq = read_seqbegin(&timekeeper.lock); + nsecs = timekeeping_get_ns_raw(&timekeeper); + *ts = timekeeper.raw_time; - } while (read_seqretry(&tk->lock, seq)); + } while (read_seqretry(&timekeeper.lock, seq)); timespec_add_ns(ts, nsecs); } EXPORT_SYMBOL(getrawmonotonic); + /** * timekeeping_valid_for_hres - Check if timekeeping is suitable for hres */ int timekeeping_valid_for_hres(void) { - struct timekeeper *tk = &timekeeper; unsigned long seq; int ret; do { - seq = read_seqbegin(&tk->lock); + seq = read_seqbegin(&timekeeper.lock); - ret = tk->clock->flags & CLOCK_SOURCE_VALID_FOR_HRES; + ret = timekeeper.clock->flags & CLOCK_SOURCE_VALID_FOR_HRES; - } while (read_seqretry(&tk->lock, seq)); + } while (read_seqretry(&timekeeper.lock, seq)); return ret; } @@ -607,16 +574,15 @@ int timekeeping_valid_for_hres(void) */ u64 timekeeping_max_deferment(void) { - struct timekeeper *tk = &timekeeper; unsigned long seq; u64 ret; do { - seq = read_seqbegin(&tk->lock); + seq = read_seqbegin(&timekeeper.lock); - ret = tk->clock->max_idle_ns; + ret = timekeeper.clock->max_idle_ns; - } while (read_seqretry(&tk->lock, seq)); + } while (read_seqretry(&timekeeper.lock, seq)); return ret; } @@ -656,56 +622,46 @@ void __attribute__((weak)) read_boot_clock(struct timespec *ts) */ void __init timekeeping_init(void) { - struct timekeeper *tk = &timekeeper; struct clocksource *clock; unsigned long flags; - struct timespec now, boot, tmp; + struct timespec now, boot; read_persistent_clock(&now); - if (!timespec_valid_strict(&now)) { - pr_warn("WARNING: Persistent clock returned invalid value!\n" - " Check your CMOS/BIOS settings.\n"); - now.tv_sec = 0; - now.tv_nsec = 0; - } - read_boot_clock(&boot); - if (!timespec_valid_strict(&boot)) { - pr_warn("WARNING: Boot clock returned invalid value!\n" - " Check your CMOS/BIOS settings.\n"); - boot.tv_sec = 0; - boot.tv_nsec = 0; - } - seqlock_init(&tk->lock); + seqlock_init(&timekeeper.lock); ntp_init(); - write_seqlock_irqsave(&tk->lock, flags); + write_seqlock_irqsave(&timekeeper.lock, flags); clock = clocksource_default_clock(); if (clock->enable) clock->enable(clock); - tk_setup_internals(tk, clock); + tk_setup_internals(&timekeeper, clock); - tk_set_xtime(tk, &now); - tk->raw_time.tv_sec = 0; - tk->raw_time.tv_nsec = 0; + tk_set_xtime(&timekeeper, &now); + timekeeper.raw_time.tv_sec = 0; + timekeeper.raw_time.tv_nsec = 0; if (boot.tv_sec == 0 && boot.tv_nsec == 0) - boot = tk_xtime(tk); - - set_normalized_timespec(&tmp, -boot.tv_sec, -boot.tv_nsec); - tk_set_wall_to_mono(tk, tmp); - - tmp.tv_sec = 0; - tmp.tv_nsec = 0; - tk_set_sleep_time(tk, tmp); - - write_sequnlock_irqrestore(&tk->lock, flags); + boot = tk_xtime(&timekeeper); + + set_normalized_timespec(&timekeeper.wall_to_monotonic, + -boot.tv_sec, -boot.tv_nsec); + update_rt_offset(&timekeeper); + timekeeper.total_sleep_time.tv_sec = 0; + timekeeper.total_sleep_time.tv_nsec = 0; + write_sequnlock_irqrestore(&timekeeper.lock, flags); } /* time in seconds when suspend began */ static struct timespec timekeeping_suspend_time; +static void update_sleep_time(struct timespec t) +{ + timekeeper.total_sleep_time = t; + timekeeper.offs_boot = timespec_to_ktime(t); +} + /** * __timekeeping_inject_sleeptime - Internal function to add sleep interval * @delta: pointer to a timespec delta value @@ -716,16 +672,18 @@ static struct timespec timekeeping_suspend_time; static void __timekeeping_inject_sleeptime(struct timekeeper *tk, struct timespec *delta) { - if (!timespec_valid_strict(delta)) { + if (!timespec_valid(delta)) { printk(KERN_WARNING "__timekeeping_inject_sleeptime: Invalid " "sleep delta value!\n"); return; } + tk_xtime_add(tk, delta); - tk_set_wall_to_mono(tk, timespec_sub(tk->wall_to_monotonic, *delta)); - tk_set_sleep_time(tk, timespec_add(tk->total_sleep_time, *delta)); + tk->wall_to_monotonic = timespec_sub(tk->wall_to_monotonic, *delta); + update_sleep_time(timespec_add(tk->total_sleep_time, *delta)); } + /** * timekeeping_inject_sleeptime - Adds suspend interval to timeekeeping values * @delta: pointer to a timespec delta value @@ -738,7 +696,6 @@ static void __timekeeping_inject_sleeptime(struct timekeeper *tk, */ void timekeeping_inject_sleeptime(struct timespec *delta) { - struct timekeeper *tk = &timekeeper; unsigned long flags; struct timespec ts; @@ -747,20 +704,21 @@ void timekeeping_inject_sleeptime(struct timespec *delta) if (!(ts.tv_sec == 0 && ts.tv_nsec == 0)) return; - write_seqlock_irqsave(&tk->lock, flags); + write_seqlock_irqsave(&timekeeper.lock, flags); - timekeeping_forward_now(tk); + timekeeping_forward_now(&timekeeper); - __timekeeping_inject_sleeptime(tk, delta); + __timekeeping_inject_sleeptime(&timekeeper, delta); - timekeeping_update(tk, true); + timekeeping_update(&timekeeper, true); - write_sequnlock_irqrestore(&tk->lock, flags); + write_sequnlock_irqrestore(&timekeeper.lock, flags); /* signal hrtimers about time change */ clock_was_set(); } + /** * timekeeping_resume - Resumes the generic timekeeping subsystem. * @@ -770,7 +728,6 @@ void timekeeping_inject_sleeptime(struct timespec *delta) */ static void timekeeping_resume(void) { - struct timekeeper *tk = &timekeeper; unsigned long flags; struct timespec ts; @@ -778,18 +735,18 @@ static void timekeeping_resume(void) clocksource_resume(); - write_seqlock_irqsave(&tk->lock, flags); + write_seqlock_irqsave(&timekeeper.lock, flags); if (timespec_compare(&ts, &timekeeping_suspend_time) > 0) { ts = timespec_sub(ts, timekeeping_suspend_time); - __timekeeping_inject_sleeptime(tk, &ts); + __timekeeping_inject_sleeptime(&timekeeper, &ts); } /* re-base the last cycle value */ - tk->clock->cycle_last = tk->clock->read(tk->clock); - tk->ntp_error = 0; + timekeeper.clock->cycle_last = timekeeper.clock->read(timekeeper.clock); + timekeeper.ntp_error = 0; timekeeping_suspended = 0; - timekeeping_update(tk, false); - write_sequnlock_irqrestore(&tk->lock, flags); + timekeeping_update(&timekeeper, false); + write_sequnlock_irqrestore(&timekeeper.lock, flags); touch_softlockup_watchdog(); @@ -801,15 +758,14 @@ static void timekeeping_resume(void) static int timekeeping_suspend(void) { - struct timekeeper *tk = &timekeeper; unsigned long flags; struct timespec delta, delta_delta; static struct timespec old_delta; read_persistent_clock(&timekeeping_suspend_time); - write_seqlock_irqsave(&tk->lock, flags); - timekeeping_forward_now(tk); + write_seqlock_irqsave(&timekeeper.lock, flags); + timekeeping_forward_now(&timekeeper); timekeeping_suspended = 1; /* @@ -818,7 +774,7 @@ static int timekeeping_suspend(void) * try to compensate so the difference in system time * and persistent_clock time stays close to constant. */ - delta = timespec_sub(tk_xtime(tk), timekeeping_suspend_time); + delta = timespec_sub(tk_xtime(&timekeeper), timekeeping_suspend_time); delta_delta = timespec_sub(delta, old_delta); if (abs(delta_delta.tv_sec) >= 2) { /* @@ -831,7 +787,7 @@ static int timekeeping_suspend(void) timekeeping_suspend_time = timespec_add(timekeeping_suspend_time, delta_delta); } - write_sequnlock_irqrestore(&tk->lock, flags); + write_sequnlock_irqrestore(&timekeeper.lock, flags); clockevents_notify(CLOCK_EVT_NOTIFY_SUSPEND, NULL); clocksource_suspend(); @@ -942,29 +898,27 @@ static void timekeeping_adjust(struct timekeeper *tk, s64 offset) * the error. This causes the likely below to be unlikely. * * The proper fix is to avoid rounding up by using - * the high precision tk->xtime_nsec instead of + * the high precision timekeeper.xtime_nsec instead of * xtime.tv_nsec everywhere. Fixing this will take some * time. */ if (likely(error <= interval)) adj = 1; else - adj = timekeeping_bigadjust(tk, error, &interval, &offset); - } else { - if (error < -interval) { - /* See comment above, this is just switched for the negative */ - error >>= 2; - if (likely(error >= -interval)) { - adj = -1; - interval = -interval; - offset = -offset; - } else { - adj = timekeeping_bigadjust(tk, error, &interval, &offset); - } - } else { - goto out_adjust; - } - } + adj = timekeeping_bigadjust(tk, error, &interval, + &offset); + } else if (error < -interval) { + /* See comment above, this is just switched for the negative */ + error >>= 2; + if (likely(error >= -interval)) { + adj = -1; + interval = -interval; + offset = -offset; + } else + adj = timekeeping_bigadjust(tk, error, &interval, + &offset); + } else + return; if (unlikely(tk->clock->maxadj && (tk->mult + adj > tk->clock->mult + tk->clock->maxadj))) { @@ -1027,7 +981,6 @@ static void timekeeping_adjust(struct timekeeper *tk, s64 offset) tk->xtime_nsec -= offset; tk->ntp_error -= (interval - offset) << tk->ntp_error_shift; -out_adjust: /* * It may be possible that when we entered this function, xtime_nsec * was very small. Further, if we're slightly speeding the clocksource @@ -1050,6 +1003,7 @@ static void timekeeping_adjust(struct timekeeper *tk, s64 offset) } + /** * accumulate_nsecs_to_secs - Accumulates nsecs into secs * @@ -1070,21 +1024,15 @@ static inline void accumulate_nsecs_to_secs(struct timekeeper *tk) /* Figure out if its a leap sec and apply if needed */ leap = second_overflow(tk->xtime_sec); - if (unlikely(leap)) { - struct timespec ts; - - tk->xtime_sec += leap; - - ts.tv_sec = leap; - ts.tv_nsec = 0; - tk_set_wall_to_mono(tk, - timespec_sub(tk->wall_to_monotonic, ts)); - + tk->xtime_sec += leap; + tk->wall_to_monotonic.tv_sec -= leap; + if (leap) clock_was_set_delayed(); - } + } } + /** * logarithmic_accumulation - shifted accumulation of cycles * @@ -1128,6 +1076,7 @@ static cycle_t logarithmic_accumulation(struct timekeeper *tk, cycle_t offset, return offset; } + /** * update_wall_time - Uses the current clocksource to increment the wall time * @@ -1135,30 +1084,25 @@ static cycle_t logarithmic_accumulation(struct timekeeper *tk, cycle_t offset, static void update_wall_time(void) { struct clocksource *clock; - struct timekeeper *tk = &timekeeper; cycle_t offset; int shift = 0, maxshift; unsigned long flags; s64 remainder; - write_seqlock_irqsave(&tk->lock, flags); + write_seqlock_irqsave(&timekeeper.lock, flags); /* Make sure we're fully resumed: */ if (unlikely(timekeeping_suspended)) goto out; - clock = tk->clock; + clock = timekeeper.clock; #ifdef CONFIG_ARCH_USES_GETTIMEOFFSET - offset = tk->cycle_interval; + offset = timekeeper.cycle_interval; #else offset = (clock->read(clock) - clock->cycle_last) & clock->mask; #endif - /* Check if there's really nothing to do */ - if (offset < tk->cycle_interval) - goto out; - /* * With NO_HZ we may have to accumulate many cycle_intervals * (think "ticks") worth of time at once. To do this efficiently, @@ -1167,19 +1111,19 @@ static void update_wall_time(void) * chunk in one go, and then try to consume the next smaller * doubled multiple. */ - shift = ilog2(offset) - ilog2(tk->cycle_interval); + shift = ilog2(offset) - ilog2(timekeeper.cycle_interval); shift = max(0, shift); /* Bound shift to one less than what overflows tick_length */ maxshift = (64 - (ilog2(ntp_tick_length())+1)) - 1; shift = min(shift, maxshift); - while (offset >= tk->cycle_interval) { - offset = logarithmic_accumulation(tk, offset, shift); - if (offset < tk->cycle_interval<= timekeeper.cycle_interval) { + offset = logarithmic_accumulation(&timekeeper, offset, shift); + if(offset < timekeeper.cycle_interval<xtime_nsec & ((1ULL << tk->shift) - 1); - tk->xtime_nsec -= remainder; - tk->xtime_nsec += 1ULL << tk->shift; - tk->ntp_error += remainder << tk->ntp_error_shift; + remainder = timekeeper.xtime_nsec & ((1 << timekeeper.shift) - 1); + timekeeper.xtime_nsec -= remainder; + timekeeper.xtime_nsec += 1 << timekeeper.shift; + timekeeper.ntp_error += remainder << timekeeper.ntp_error_shift; /* * Finally, make sure that after the rounding * xtime_nsec isn't larger than NSEC_PER_SEC */ - accumulate_nsecs_to_secs(tk); + accumulate_nsecs_to_secs(&timekeeper); - timekeeping_update(tk, false); + timekeeping_update(&timekeeper, false); out: - write_sequnlock_irqrestore(&tk->lock, flags); + write_sequnlock_irqrestore(&timekeeper.lock, flags); } @@ -1222,18 +1166,18 @@ static void update_wall_time(void) */ void getboottime(struct timespec *ts) { - struct timekeeper *tk = &timekeeper; struct timespec boottime = { - .tv_sec = tk->wall_to_monotonic.tv_sec + - tk->total_sleep_time.tv_sec, - .tv_nsec = tk->wall_to_monotonic.tv_nsec + - tk->total_sleep_time.tv_nsec + .tv_sec = timekeeper.wall_to_monotonic.tv_sec + + timekeeper.total_sleep_time.tv_sec, + .tv_nsec = timekeeper.wall_to_monotonic.tv_nsec + + timekeeper.total_sleep_time.tv_nsec }; set_normalized_timespec(ts, -boottime.tv_sec, -boottime.tv_nsec); } EXPORT_SYMBOL_GPL(getboottime); + /** * get_monotonic_boottime - Returns monotonic time since boot * @ts: pointer to the timespec to be set @@ -1245,25 +1189,22 @@ EXPORT_SYMBOL_GPL(getboottime); */ void get_monotonic_boottime(struct timespec *ts) { - struct timekeeper *tk = &timekeeper; struct timespec tomono, sleep; - s64 nsec; unsigned int seq; WARN_ON(timekeeping_suspended); do { - seq = read_seqbegin(&tk->lock); - ts->tv_sec = tk->xtime_sec; - nsec = timekeeping_get_ns(tk); - tomono = tk->wall_to_monotonic; - sleep = tk->total_sleep_time; + seq = read_seqbegin(&timekeeper.lock); + ts->tv_sec = timekeeper.xtime_sec; + ts->tv_nsec = timekeeping_get_ns(&timekeeper); + tomono = timekeeper.wall_to_monotonic; + sleep = timekeeper.total_sleep_time; - } while (read_seqretry(&tk->lock, seq)); + } while (read_seqretry(&timekeeper.lock, seq)); - ts->tv_sec += tomono.tv_sec + sleep.tv_sec; - ts->tv_nsec = 0; - timespec_add_ns(ts, nsec + tomono.tv_nsec + sleep.tv_nsec); + set_normalized_timespec(ts, ts->tv_sec + tomono.tv_sec + sleep.tv_sec, + ts->tv_nsec + tomono.tv_nsec + sleep.tv_nsec); } EXPORT_SYMBOL_GPL(get_monotonic_boottime); @@ -1290,38 +1231,31 @@ EXPORT_SYMBOL_GPL(ktime_get_boottime); */ void monotonic_to_bootbased(struct timespec *ts) { - struct timekeeper *tk = &timekeeper; - - *ts = timespec_add(*ts, tk->total_sleep_time); + *ts = timespec_add(*ts, timekeeper.total_sleep_time); } EXPORT_SYMBOL_GPL(monotonic_to_bootbased); unsigned long get_seconds(void) { - struct timekeeper *tk = &timekeeper; - - return tk->xtime_sec; + return timekeeper.xtime_sec; } EXPORT_SYMBOL(get_seconds); struct timespec __current_kernel_time(void) { - struct timekeeper *tk = &timekeeper; - - return tk_xtime(tk); + return tk_xtime(&timekeeper); } struct timespec current_kernel_time(void) { - struct timekeeper *tk = &timekeeper; struct timespec now; unsigned long seq; do { - seq = read_seqbegin(&tk->lock); + seq = read_seqbegin(&timekeeper.lock); - now = tk_xtime(tk); - } while (read_seqretry(&tk->lock, seq)); + now = tk_xtime(&timekeeper); + } while (read_seqretry(&timekeeper.lock, seq)); return now; } @@ -1329,16 +1263,15 @@ EXPORT_SYMBOL(current_kernel_time); struct timespec get_monotonic_coarse(void) { - struct timekeeper *tk = &timekeeper; struct timespec now, mono; unsigned long seq; do { - seq = read_seqbegin(&tk->lock); + seq = read_seqbegin(&timekeeper.lock); - now = tk_xtime(tk); - mono = tk->wall_to_monotonic; - } while (read_seqretry(&tk->lock, seq)); + now = tk_xtime(&timekeeper); + mono = timekeeper.wall_to_monotonic; + } while (read_seqretry(&timekeeper.lock, seq)); set_normalized_timespec(&now, now.tv_sec + mono.tv_sec, now.tv_nsec + mono.tv_nsec); @@ -1367,15 +1300,14 @@ void do_timer(unsigned long ticks) void get_xtime_and_monotonic_and_sleep_offset(struct timespec *xtim, struct timespec *wtom, struct timespec *sleep) { - struct timekeeper *tk = &timekeeper; unsigned long seq; do { - seq = read_seqbegin(&tk->lock); - *xtim = tk_xtime(tk); - *wtom = tk->wall_to_monotonic; - *sleep = tk->total_sleep_time; - } while (read_seqretry(&tk->lock, seq)); + seq = read_seqbegin(&timekeeper.lock); + *xtim = tk_xtime(&timekeeper); + *wtom = timekeeper.wall_to_monotonic; + *sleep = timekeeper.total_sleep_time; + } while (read_seqretry(&timekeeper.lock, seq)); } #ifdef CONFIG_HIGH_RES_TIMERS @@ -1389,20 +1321,19 @@ void get_xtime_and_monotonic_and_sleep_offset(struct timespec *xtim, */ ktime_t ktime_get_update_offsets(ktime_t *offs_real, ktime_t *offs_boot) { - struct timekeeper *tk = &timekeeper; ktime_t now; unsigned int seq; u64 secs, nsecs; do { - seq = read_seqbegin(&tk->lock); + seq = read_seqbegin(&timekeeper.lock); - secs = tk->xtime_sec; - nsecs = timekeeping_get_ns(tk); + secs = timekeeper.xtime_sec; + nsecs = timekeeping_get_ns(&timekeeper); - *offs_real = tk->offs_real; - *offs_boot = tk->offs_boot; - } while (read_seqretry(&tk->lock, seq)); + *offs_real = timekeeper.offs_real; + *offs_boot = timekeeper.offs_boot; + } while (read_seqretry(&timekeeper.lock, seq)); now = ktime_add_ns(ktime_set(secs, 0), nsecs); now = ktime_sub(now, *offs_real); @@ -1415,19 +1346,19 @@ ktime_t ktime_get_update_offsets(ktime_t *offs_real, ktime_t *offs_boot) */ ktime_t ktime_get_monotonic_offset(void) { - struct timekeeper *tk = &timekeeper; unsigned long seq; struct timespec wtom; do { - seq = read_seqbegin(&tk->lock); - wtom = tk->wall_to_monotonic; - } while (read_seqretry(&tk->lock, seq)); + seq = read_seqbegin(&timekeeper.lock); + wtom = timekeeper.wall_to_monotonic; + } while (read_seqretry(&timekeeper.lock, seq)); return timespec_to_ktime(wtom); } EXPORT_SYMBOL_GPL(ktime_get_monotonic_offset); + /** * xtime_update() - advances the timekeeping infrastructure * @ticks: number of ticks, that have elapsed since the last call. diff --git a/trunk/kernel/timer.c b/trunk/kernel/timer.c index d5de1b2292aa..a61c09374eba 100644 --- a/trunk/kernel/timer.c +++ b/trunk/kernel/timer.c @@ -92,25 +92,24 @@ static DEFINE_PER_CPU(struct tvec_base *, tvec_bases) = &boot_tvec_bases; /* Functions below help us manage 'deferrable' flag */ static inline unsigned int tbase_get_deferrable(struct tvec_base *base) { - return ((unsigned int)(unsigned long)base & TIMER_DEFERRABLE); + return ((unsigned int)(unsigned long)base & TBASE_DEFERRABLE_FLAG); } -static inline unsigned int tbase_get_irqsafe(struct tvec_base *base) +static inline struct tvec_base *tbase_get_base(struct tvec_base *base) { - return ((unsigned int)(unsigned long)base & TIMER_IRQSAFE); + return ((struct tvec_base *)((unsigned long)base & ~TBASE_DEFERRABLE_FLAG)); } -static inline struct tvec_base *tbase_get_base(struct tvec_base *base) +static inline void timer_set_deferrable(struct timer_list *timer) { - return ((struct tvec_base *)((unsigned long)base & ~TIMER_FLAG_MASK)); + timer->base = TBASE_MAKE_DEFERRED(timer->base); } static inline void timer_set_base(struct timer_list *timer, struct tvec_base *new_base) { - unsigned long flags = (unsigned long)timer->base & TIMER_FLAG_MASK; - - timer->base = (struct tvec_base *)((unsigned long)(new_base) | flags); + timer->base = (struct tvec_base *)((unsigned long)(new_base) | + tbase_get_deferrable(timer->base)); } static unsigned long round_jiffies_common(unsigned long j, int cpu, @@ -564,14 +563,16 @@ static inline void debug_timer_assert_init(struct timer_list *timer) debug_object_assert_init(timer, &timer_debug_descr); } -static void do_init_timer(struct timer_list *timer, unsigned int flags, - const char *name, struct lock_class_key *key); +static void __init_timer(struct timer_list *timer, + const char *name, + struct lock_class_key *key); -void init_timer_on_stack_key(struct timer_list *timer, unsigned int flags, - const char *name, struct lock_class_key *key) +void init_timer_on_stack_key(struct timer_list *timer, + const char *name, + struct lock_class_key *key) { debug_object_init_on_stack(timer, &timer_debug_descr); - do_init_timer(timer, flags, name, key); + __init_timer(timer, name, key); } EXPORT_SYMBOL_GPL(init_timer_on_stack_key); @@ -612,13 +613,12 @@ static inline void debug_assert_init(struct timer_list *timer) debug_timer_assert_init(timer); } -static void do_init_timer(struct timer_list *timer, unsigned int flags, - const char *name, struct lock_class_key *key) +static void __init_timer(struct timer_list *timer, + const char *name, + struct lock_class_key *key) { - struct tvec_base *base = __raw_get_cpu_var(tvec_bases); - timer->entry.next = NULL; - timer->base = (void *)((unsigned long)base | flags); + timer->base = __raw_get_cpu_var(tvec_bases); timer->slack = -1; #ifdef CONFIG_TIMER_STATS timer->start_site = NULL; @@ -628,10 +628,22 @@ static void do_init_timer(struct timer_list *timer, unsigned int flags, lockdep_init_map(&timer->lockdep_map, name, key, 0); } +void setup_deferrable_timer_on_stack_key(struct timer_list *timer, + const char *name, + struct lock_class_key *key, + void (*function)(unsigned long), + unsigned long data) +{ + timer->function = function; + timer->data = data; + init_timer_on_stack_key(timer, name, key); + timer_set_deferrable(timer); +} +EXPORT_SYMBOL_GPL(setup_deferrable_timer_on_stack_key); + /** * init_timer_key - initialize a timer * @timer: the timer to be initialized - * @flags: timer flags * @name: name of the timer * @key: lockdep class key of the fake lock used for tracking timer * sync lock dependencies @@ -639,14 +651,24 @@ static void do_init_timer(struct timer_list *timer, unsigned int flags, * init_timer_key() must be done to a timer prior calling *any* of the * other timer functions. */ -void init_timer_key(struct timer_list *timer, unsigned int flags, - const char *name, struct lock_class_key *key) +void init_timer_key(struct timer_list *timer, + const char *name, + struct lock_class_key *key) { debug_init(timer); - do_init_timer(timer, flags, name, key); + __init_timer(timer, name, key); } EXPORT_SYMBOL(init_timer_key); +void init_timer_deferrable_key(struct timer_list *timer, + const char *name, + struct lock_class_key *key) +{ + init_timer_key(timer, name, key); + timer_set_deferrable(timer); +} +EXPORT_SYMBOL(init_timer_deferrable_key); + static inline void detach_timer(struct timer_list *timer, bool clear_pending) { struct list_head *entry = &timer->entry; @@ -664,7 +686,7 @@ detach_expired_timer(struct timer_list *timer, struct tvec_base *base) { detach_timer(timer, true); if (!tbase_get_deferrable(timer->base)) - base->active_timers--; + timer->base->active_timers--; } static int detach_if_pending(struct timer_list *timer, struct tvec_base *base, @@ -675,7 +697,7 @@ static int detach_if_pending(struct timer_list *timer, struct tvec_base *base, detach_timer(timer, clear_pending); if (!tbase_get_deferrable(timer->base)) { - base->active_timers--; + timer->base->active_timers--; if (timer->expires == base->next_timer) base->next_timer = base->timer_jiffies; } @@ -1007,14 +1029,14 @@ EXPORT_SYMBOL(try_to_del_timer_sync); * * Synchronization rules: Callers must prevent restarting of the timer, * otherwise this function is meaningless. It must not be called from - * interrupt contexts unless the timer is an irqsafe one. The caller must - * not hold locks which would prevent completion of the timer's - * handler. The timer's handler must not call add_timer_on(). Upon exit the - * timer is not queued and the handler is not running on any CPU. + * interrupt contexts. The caller must not hold locks which would prevent + * completion of the timer's handler. The timer's handler must not call + * add_timer_on(). Upon exit the timer is not queued and the handler is + * not running on any CPU. * - * Note: For !irqsafe timers, you must not hold locks that are held in - * interrupt context while calling this function. Even if the lock has - * nothing to do with the timer in question. Here's why: + * Note: You must not hold locks that are held in interrupt context + * while calling this function. Even if the lock has nothing to do + * with the timer in question. Here's why: * * CPU0 CPU1 * ---- ---- @@ -1051,7 +1073,7 @@ int del_timer_sync(struct timer_list *timer) * don't use it in hardirq context, because it * could lead to deadlock. */ - WARN_ON(in_irq() && !tbase_get_irqsafe(timer->base)); + WARN_ON(in_irq()); for (;;) { int ret = try_to_del_timer_sync(timer); if (ret >= 0) @@ -1158,27 +1180,19 @@ static inline void __run_timers(struct tvec_base *base) while (!list_empty(head)) { void (*fn)(unsigned long); unsigned long data; - bool irqsafe; timer = list_first_entry(head, struct timer_list,entry); fn = timer->function; data = timer->data; - irqsafe = tbase_get_irqsafe(timer->base); timer_stats_account_timer(timer); base->running_timer = timer; detach_expired_timer(timer, base); - if (irqsafe) { - spin_unlock(&base->lock); - call_timer_fn(timer, fn, data); - spin_lock(&base->lock); - } else { - spin_unlock_irq(&base->lock); - call_timer_fn(timer, fn, data); - spin_lock_irq(&base->lock); - } + spin_unlock_irq(&base->lock); + call_timer_fn(timer, fn, data); + spin_lock_irq(&base->lock); } } base->running_timer = NULL; @@ -1393,6 +1407,13 @@ SYSCALL_DEFINE1(alarm, unsigned int, seconds) #endif +#ifndef __alpha__ + +/* + * The Alpha uses getxpid, getxuid, and getxgid instead. Maybe this + * should be moved into arch/i386 instead? + */ + /** * sys_getpid - return the thread group id of the current process * @@ -1448,6 +1469,8 @@ SYSCALL_DEFINE0(getegid) return from_kgid_munged(current_user_ns(), current_egid()); } +#endif + static void process_timeout(unsigned long __data) { wake_up_process((struct task_struct *)__data); @@ -1777,13 +1800,9 @@ static struct notifier_block __cpuinitdata timers_nb = { void __init init_timers(void) { - int err; - - /* ensure there are enough low bits for flags in timer->base pointer */ - BUILD_BUG_ON(__alignof__(struct tvec_base) & TIMER_FLAG_MASK); + int err = timer_cpu_notify(&timers_nb, (unsigned long)CPU_UP_PREPARE, + (void *)(long)smp_processor_id()); - err = timer_cpu_notify(&timers_nb, (unsigned long)CPU_UP_PREPARE, - (void *)(long)smp_processor_id()); init_timer_stats(); BUG_ON(err != NOTIFY_OK); diff --git a/trunk/kernel/trace/Kconfig b/trunk/kernel/trace/Kconfig index 4cea4f41c1d9..8c4c07071cc5 100644 --- a/trunk/kernel/trace/Kconfig +++ b/trunk/kernel/trace/Kconfig @@ -49,11 +49,6 @@ config HAVE_SYSCALL_TRACEPOINTS help See Documentation/trace/ftrace-design.txt -config HAVE_FENTRY - bool - help - Arch supports the gcc options -pg with -mfentry - config HAVE_C_RECORDMCOUNT bool help @@ -62,12 +57,8 @@ config HAVE_C_RECORDMCOUNT config TRACER_MAX_TRACE bool -config TRACE_CLOCK - bool - config RING_BUFFER bool - select TRACE_CLOCK config FTRACE_NMI_ENTER bool @@ -118,7 +109,6 @@ config TRACING select NOP_TRACER select BINARY_PRINTF select EVENT_TRACING - select TRACE_CLOCK config GENERIC_TRACER bool diff --git a/trunk/kernel/trace/Makefile b/trunk/kernel/trace/Makefile index d7e2068e4b71..b831087c8200 100644 --- a/trunk/kernel/trace/Makefile +++ b/trunk/kernel/trace/Makefile @@ -5,12 +5,10 @@ ifdef CONFIG_FUNCTION_TRACER ORIG_CFLAGS := $(KBUILD_CFLAGS) KBUILD_CFLAGS = $(subst -pg,,$(ORIG_CFLAGS)) -ifdef CONFIG_FTRACE_SELFTEST # selftest needs instrumentation CFLAGS_trace_selftest_dynamic.o = -pg obj-y += trace_selftest_dynamic.o endif -endif # If unlikely tracing is enabled, do not trace these files ifdef CONFIG_TRACING_BRANCHES @@ -19,7 +17,11 @@ endif CFLAGS_trace_events_filter.o := -I$(src) -obj-$(CONFIG_TRACE_CLOCK) += trace_clock.o +# +# Make the trace clocks available generally: it's infrastructure +# relied on by ptrace for example: +# +obj-y += trace_clock.o obj-$(CONFIG_FUNCTION_TRACER) += libftrace.o obj-$(CONFIG_RING_BUFFER) += ring_buffer.o diff --git a/trunk/kernel/trace/ftrace.c b/trunk/kernel/trace/ftrace.c index 9dcf15d38380..b4f20fba09fc 100644 --- a/trunk/kernel/trace/ftrace.c +++ b/trunk/kernel/trace/ftrace.c @@ -64,20 +64,12 @@ #define FL_GLOBAL_CONTROL_MASK (FTRACE_OPS_FL_GLOBAL | FTRACE_OPS_FL_CONTROL) -static struct ftrace_ops ftrace_list_end __read_mostly = { - .func = ftrace_stub, - .flags = FTRACE_OPS_FL_RECURSION_SAFE, -}; - /* ftrace_enabled is a method to turn ftrace on or off */ int ftrace_enabled __read_mostly; static int last_ftrace_enabled; /* Quick disabling of function tracer. */ -int function_trace_stop __read_mostly; - -/* Current function tracing op */ -struct ftrace_ops *function_trace_op __read_mostly = &ftrace_list_end; +int function_trace_stop; /* List for set_ftrace_pid's pids. */ LIST_HEAD(ftrace_pids); @@ -94,43 +86,22 @@ static int ftrace_disabled __read_mostly; static DEFINE_MUTEX(ftrace_lock); +static struct ftrace_ops ftrace_list_end __read_mostly = { + .func = ftrace_stub, +}; + static struct ftrace_ops *ftrace_global_list __read_mostly = &ftrace_list_end; static struct ftrace_ops *ftrace_control_list __read_mostly = &ftrace_list_end; static struct ftrace_ops *ftrace_ops_list __read_mostly = &ftrace_list_end; ftrace_func_t ftrace_trace_function __read_mostly = ftrace_stub; +static ftrace_func_t __ftrace_trace_function_delay __read_mostly = ftrace_stub; +ftrace_func_t __ftrace_trace_function __read_mostly = ftrace_stub; ftrace_func_t ftrace_pid_function __read_mostly = ftrace_stub; static struct ftrace_ops global_ops; static struct ftrace_ops control_ops; -#if ARCH_SUPPORTS_FTRACE_OPS -static void ftrace_ops_list_func(unsigned long ip, unsigned long parent_ip, - struct ftrace_ops *op, struct pt_regs *regs); -#else -/* See comment below, where ftrace_ops_list_func is defined */ -static void ftrace_ops_no_ops(unsigned long ip, unsigned long parent_ip); -#define ftrace_ops_list_func ((ftrace_func_t)ftrace_ops_no_ops) -#endif - -/** - * ftrace_nr_registered_ops - return number of ops registered - * - * Returns the number of ftrace_ops registered and tracing functions - */ -int ftrace_nr_registered_ops(void) -{ - struct ftrace_ops *ops; - int cnt = 0; - - mutex_lock(&ftrace_lock); - - for (ops = ftrace_ops_list; - ops != &ftrace_list_end; ops = ops->next) - cnt++; - - mutex_unlock(&ftrace_lock); - - return cnt; -} +static void +ftrace_ops_list_func(unsigned long ip, unsigned long parent_ip); /* * Traverse the ftrace_global_list, invoking all entries. The reason that we @@ -141,29 +112,29 @@ int ftrace_nr_registered_ops(void) * * Silly Alpha and silly pointer-speculation compiler optimizations! */ -static void -ftrace_global_list_func(unsigned long ip, unsigned long parent_ip, - struct ftrace_ops *op, struct pt_regs *regs) +static void ftrace_global_list_func(unsigned long ip, + unsigned long parent_ip) { + struct ftrace_ops *op; + if (unlikely(trace_recursion_test(TRACE_GLOBAL_BIT))) return; trace_recursion_set(TRACE_GLOBAL_BIT); op = rcu_dereference_raw(ftrace_global_list); /*see above*/ while (op != &ftrace_list_end) { - op->func(ip, parent_ip, op, regs); + op->func(ip, parent_ip); op = rcu_dereference_raw(op->next); /*see above*/ }; trace_recursion_clear(TRACE_GLOBAL_BIT); } -static void ftrace_pid_func(unsigned long ip, unsigned long parent_ip, - struct ftrace_ops *op, struct pt_regs *regs) +static void ftrace_pid_func(unsigned long ip, unsigned long parent_ip) { if (!test_tsk_trace_trace(current)) return; - ftrace_pid_function(ip, parent_ip, op, regs); + ftrace_pid_function(ip, parent_ip); } static void set_ftrace_pid_function(ftrace_func_t func) @@ -182,9 +153,25 @@ static void set_ftrace_pid_function(ftrace_func_t func) void clear_ftrace_function(void) { ftrace_trace_function = ftrace_stub; + __ftrace_trace_function = ftrace_stub; + __ftrace_trace_function_delay = ftrace_stub; ftrace_pid_function = ftrace_stub; } +#ifndef CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST +/* + * For those archs that do not test ftrace_trace_stop in their + * mcount call site, we need to do it from C. + */ +static void ftrace_test_stop_func(unsigned long ip, unsigned long parent_ip) +{ + if (function_trace_stop) + return; + + __ftrace_trace_function(ip, parent_ip); +} +#endif + static void control_ops_disable_all(struct ftrace_ops *ops) { int cpu; @@ -243,27 +230,28 @@ static void update_ftrace_function(void) /* * If we are at the end of the list and this ops is - * recursion safe and not dynamic and the arch supports passing ops, - * then have the mcount trampoline call the function directly. + * not dynamic, then have the mcount trampoline call + * the function directly */ if (ftrace_ops_list == &ftrace_list_end || (ftrace_ops_list->next == &ftrace_list_end && - !(ftrace_ops_list->flags & FTRACE_OPS_FL_DYNAMIC) && - (ftrace_ops_list->flags & FTRACE_OPS_FL_RECURSION_SAFE) && - !FTRACE_FORCE_LIST_FUNC)) { - /* Set the ftrace_ops that the arch callback uses */ - if (ftrace_ops_list == &global_ops) - function_trace_op = ftrace_global_list; - else - function_trace_op = ftrace_ops_list; + !(ftrace_ops_list->flags & FTRACE_OPS_FL_DYNAMIC))) func = ftrace_ops_list->func; - } else { - /* Just use the default ftrace_ops */ - function_trace_op = &ftrace_list_end; + else func = ftrace_ops_list_func; - } +#ifdef CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST ftrace_trace_function = func; +#else +#ifdef CONFIG_DYNAMIC_FTRACE + /* do not update till all functions have been modified */ + __ftrace_trace_function_delay = func; +#else + __ftrace_trace_function = func; +#endif + ftrace_trace_function = + (func == ftrace_stub) ? func : ftrace_test_stop_func; +#endif } static void add_ftrace_ops(struct ftrace_ops **list, struct ftrace_ops *ops) @@ -337,20 +325,6 @@ static int __register_ftrace_function(struct ftrace_ops *ops) if ((ops->flags & FL_GLOBAL_CONTROL_MASK) == FL_GLOBAL_CONTROL_MASK) return -EINVAL; -#ifndef ARCH_SUPPORTS_FTRACE_SAVE_REGS - /* - * If the ftrace_ops specifies SAVE_REGS, then it only can be used - * if the arch supports it, or SAVE_REGS_IF_SUPPORTED is also set. - * Setting SAVE_REGS_IF_SUPPORTED makes SAVE_REGS irrelevant. - */ - if (ops->flags & FTRACE_OPS_FL_SAVE_REGS && - !(ops->flags & FTRACE_OPS_FL_SAVE_REGS_IF_SUPPORTED)) - return -EINVAL; - - if (ops->flags & FTRACE_OPS_FL_SAVE_REGS_IF_SUPPORTED) - ops->flags |= FTRACE_OPS_FL_SAVE_REGS; -#endif - if (!core_kernel_data((unsigned long)ops)) ops->flags |= FTRACE_OPS_FL_DYNAMIC; @@ -799,8 +773,7 @@ ftrace_profile_alloc(struct ftrace_profile_stat *stat, unsigned long ip) } static void -function_profile_call(unsigned long ip, unsigned long parent_ip, - struct ftrace_ops *ops, struct pt_regs *regs) +function_profile_call(unsigned long ip, unsigned long parent_ip) { struct ftrace_profile_stat *stat; struct ftrace_profile *rec; @@ -830,7 +803,7 @@ function_profile_call(unsigned long ip, unsigned long parent_ip, #ifdef CONFIG_FUNCTION_GRAPH_TRACER static int profile_graph_entry(struct ftrace_graph_ent *trace) { - function_profile_call(trace->func, 0, NULL, NULL); + function_profile_call(trace->func, 0); return 1; } @@ -890,7 +863,6 @@ static void unregister_ftrace_profiler(void) #else static struct ftrace_ops ftrace_profile_ops __read_mostly = { .func = function_profile_call, - .flags = FTRACE_OPS_FL_RECURSION_SAFE, }; static int register_ftrace_profiler(void) @@ -1073,7 +1045,6 @@ static struct ftrace_ops global_ops = { .func = ftrace_stub, .notrace_hash = EMPTY_HASH, .filter_hash = EMPTY_HASH, - .flags = FTRACE_OPS_FL_RECURSION_SAFE, }; static DEFINE_MUTEX(ftrace_regex_lock); @@ -1554,12 +1525,6 @@ static void __ftrace_hash_rec_update(struct ftrace_ops *ops, rec->flags++; if (FTRACE_WARN_ON((rec->flags & ~FTRACE_FL_MASK) == FTRACE_REF_MAX)) return; - /* - * If any ops wants regs saved for this function - * then all ops will get saved regs. - */ - if (ops->flags & FTRACE_OPS_FL_SAVE_REGS) - rec->flags |= FTRACE_FL_REGS; } else { if (FTRACE_WARN_ON((rec->flags & ~FTRACE_FL_MASK) == 0)) return; @@ -1651,59 +1616,18 @@ static int ftrace_check_record(struct dyn_ftrace *rec, int enable, int update) if (enable && (rec->flags & ~FTRACE_FL_MASK)) flag = FTRACE_FL_ENABLED; - /* - * If enabling and the REGS flag does not match the REGS_EN, then - * do not ignore this record. Set flags to fail the compare against - * ENABLED. - */ - if (flag && - (!(rec->flags & FTRACE_FL_REGS) != !(rec->flags & FTRACE_FL_REGS_EN))) - flag |= FTRACE_FL_REGS; - /* If the state of this record hasn't changed, then do nothing */ if ((rec->flags & FTRACE_FL_ENABLED) == flag) return FTRACE_UPDATE_IGNORE; if (flag) { - /* Save off if rec is being enabled (for return value) */ - flag ^= rec->flags & FTRACE_FL_ENABLED; - - if (update) { + if (update) rec->flags |= FTRACE_FL_ENABLED; - if (flag & FTRACE_FL_REGS) { - if (rec->flags & FTRACE_FL_REGS) - rec->flags |= FTRACE_FL_REGS_EN; - else - rec->flags &= ~FTRACE_FL_REGS_EN; - } - } - - /* - * If this record is being updated from a nop, then - * return UPDATE_MAKE_CALL. - * Otherwise, if the EN flag is set, then return - * UPDATE_MODIFY_CALL_REGS to tell the caller to convert - * from the non-save regs, to a save regs function. - * Otherwise, - * return UPDATE_MODIFY_CALL to tell the caller to convert - * from the save regs, to a non-save regs function. - */ - if (flag & FTRACE_FL_ENABLED) - return FTRACE_UPDATE_MAKE_CALL; - else if (rec->flags & FTRACE_FL_REGS_EN) - return FTRACE_UPDATE_MODIFY_CALL_REGS; - else - return FTRACE_UPDATE_MODIFY_CALL; + return FTRACE_UPDATE_MAKE_CALL; } - if (update) { - /* If there's no more users, clear all flags */ - if (!(rec->flags & ~FTRACE_FL_MASK)) - rec->flags = 0; - else - /* Just disable the record (keep REGS state) */ - rec->flags &= ~FTRACE_FL_ENABLED; - } + if (update) + rec->flags &= ~FTRACE_FL_ENABLED; return FTRACE_UPDATE_MAKE_NOP; } @@ -1738,16 +1662,12 @@ int ftrace_test_record(struct dyn_ftrace *rec, int enable) static int __ftrace_replace_code(struct dyn_ftrace *rec, int enable) { - unsigned long ftrace_old_addr; unsigned long ftrace_addr; int ret; - ret = ftrace_update_record(rec, enable); + ftrace_addr = (unsigned long)FTRACE_ADDR; - if (rec->flags & FTRACE_FL_REGS) - ftrace_addr = (unsigned long)FTRACE_REGS_ADDR; - else - ftrace_addr = (unsigned long)FTRACE_ADDR; + ret = ftrace_update_record(rec, enable); switch (ret) { case FTRACE_UPDATE_IGNORE: @@ -1758,15 +1678,6 @@ __ftrace_replace_code(struct dyn_ftrace *rec, int enable) case FTRACE_UPDATE_MAKE_NOP: return ftrace_make_nop(NULL, rec, ftrace_addr); - - case FTRACE_UPDATE_MODIFY_CALL_REGS: - case FTRACE_UPDATE_MODIFY_CALL: - if (rec->flags & FTRACE_FL_REGS) - ftrace_old_addr = (unsigned long)FTRACE_ADDR; - else - ftrace_old_addr = (unsigned long)FTRACE_REGS_ADDR; - - return ftrace_modify_call(rec, ftrace_old_addr, ftrace_addr); } return -1; /* unknow ftrace bug */ @@ -1971,6 +1882,16 @@ static void ftrace_run_update_code(int command) */ arch_ftrace_update_code(command); +#ifndef CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST + /* + * For archs that call ftrace_test_stop_func(), we must + * wait till after we update all the function callers + * before we update the callback. This keeps different + * ops that record different functions from corrupting + * each other. + */ + __ftrace_trace_function = __ftrace_trace_function_delay; +#endif function_trace_stop--; ret = ftrace_arch_code_modify_post_process(); @@ -2520,9 +2441,8 @@ static int t_show(struct seq_file *m, void *v) seq_printf(m, "%ps", (void *)rec->ip); if (iter->flags & FTRACE_ITER_ENABLED) - seq_printf(m, " (%ld)%s", - rec->flags & ~FTRACE_FL_MASK, - rec->flags & FTRACE_FL_REGS ? " R" : ""); + seq_printf(m, " (%ld)", + rec->flags & ~FTRACE_FL_MASK); seq_printf(m, "\n"); return 0; @@ -2870,8 +2790,8 @@ static int __init ftrace_mod_cmd_init(void) } device_initcall(ftrace_mod_cmd_init); -static void function_trace_probe_call(unsigned long ip, unsigned long parent_ip, - struct ftrace_ops *op, struct pt_regs *pt_regs) +static void +function_trace_probe_call(unsigned long ip, unsigned long parent_ip) { struct ftrace_func_probe *entry; struct hlist_head *hhd; @@ -3242,27 +3162,8 @@ ftrace_notrace_write(struct file *file, const char __user *ubuf, } static int -ftrace_match_addr(struct ftrace_hash *hash, unsigned long ip, int remove) -{ - struct ftrace_func_entry *entry; - - if (!ftrace_location(ip)) - return -EINVAL; - - if (remove) { - entry = ftrace_lookup_ip(hash, ip); - if (!entry) - return -ENOENT; - free_hash_entry(hash, entry); - return 0; - } - - return add_hash_entry(hash, ip); -} - -static int -ftrace_set_hash(struct ftrace_ops *ops, unsigned char *buf, int len, - unsigned long ip, int remove, int reset, int enable) +ftrace_set_regex(struct ftrace_ops *ops, unsigned char *buf, int len, + int reset, int enable) { struct ftrace_hash **orig_hash; struct ftrace_hash *hash; @@ -3291,11 +3192,6 @@ ftrace_set_hash(struct ftrace_ops *ops, unsigned char *buf, int len, ret = -EINVAL; goto out_regex_unlock; } - if (ip) { - ret = ftrace_match_addr(hash, ip, remove); - if (ret < 0) - goto out_regex_unlock; - } mutex_lock(&ftrace_lock); ret = ftrace_hash_move(ops, enable, orig_hash, hash); @@ -3312,37 +3208,6 @@ ftrace_set_hash(struct ftrace_ops *ops, unsigned char *buf, int len, return ret; } -static int -ftrace_set_addr(struct ftrace_ops *ops, unsigned long ip, int remove, - int reset, int enable) -{ - return ftrace_set_hash(ops, 0, 0, ip, remove, reset, enable); -} - -/** - * ftrace_set_filter_ip - set a function to filter on in ftrace by address - * @ops - the ops to set the filter with - * @ip - the address to add to or remove from the filter. - * @remove - non zero to remove the ip from the filter - * @reset - non zero to reset all filters before applying this filter. - * - * Filters denote which functions should be enabled when tracing is enabled - * If @ip is NULL, it failes to update filter. - */ -int ftrace_set_filter_ip(struct ftrace_ops *ops, unsigned long ip, - int remove, int reset) -{ - return ftrace_set_addr(ops, ip, remove, reset, 1); -} -EXPORT_SYMBOL_GPL(ftrace_set_filter_ip); - -static int -ftrace_set_regex(struct ftrace_ops *ops, unsigned char *buf, int len, - int reset, int enable) -{ - return ftrace_set_hash(ops, buf, len, 0, 0, reset, enable); -} - /** * ftrace_set_filter - set a function to filter on in ftrace * @ops - the ops to set the filter with @@ -4047,7 +3912,6 @@ void __init ftrace_init(void) static struct ftrace_ops global_ops = { .func = ftrace_stub, - .flags = FTRACE_OPS_FL_RECURSION_SAFE, }; static int __init ftrace_nodyn_init(void) @@ -4078,9 +3942,10 @@ ftrace_ops_test(struct ftrace_ops *ops, unsigned long ip) #endif /* CONFIG_DYNAMIC_FTRACE */ static void -ftrace_ops_control_func(unsigned long ip, unsigned long parent_ip, - struct ftrace_ops *op, struct pt_regs *regs) +ftrace_ops_control_func(unsigned long ip, unsigned long parent_ip) { + struct ftrace_ops *op; + if (unlikely(trace_recursion_test(TRACE_CONTROL_BIT))) return; @@ -4094,7 +3959,7 @@ ftrace_ops_control_func(unsigned long ip, unsigned long parent_ip, while (op != &ftrace_list_end) { if (!ftrace_function_local_disabled(op) && ftrace_ops_test(op, ip)) - op->func(ip, parent_ip, op, regs); + op->func(ip, parent_ip); op = rcu_dereference_raw(op->next); }; @@ -4104,18 +3969,13 @@ ftrace_ops_control_func(unsigned long ip, unsigned long parent_ip, static struct ftrace_ops control_ops = { .func = ftrace_ops_control_func, - .flags = FTRACE_OPS_FL_RECURSION_SAFE, }; -static inline void -__ftrace_ops_list_func(unsigned long ip, unsigned long parent_ip, - struct ftrace_ops *ignored, struct pt_regs *regs) +static void +ftrace_ops_list_func(unsigned long ip, unsigned long parent_ip) { struct ftrace_ops *op; - if (function_trace_stop) - return; - if (unlikely(trace_recursion_test(TRACE_INTERNAL_BIT))) return; @@ -4128,39 +3988,13 @@ __ftrace_ops_list_func(unsigned long ip, unsigned long parent_ip, op = rcu_dereference_raw(ftrace_ops_list); while (op != &ftrace_list_end) { if (ftrace_ops_test(op, ip)) - op->func(ip, parent_ip, op, regs); + op->func(ip, parent_ip); op = rcu_dereference_raw(op->next); }; preempt_enable_notrace(); trace_recursion_clear(TRACE_INTERNAL_BIT); } -/* - * Some archs only support passing ip and parent_ip. Even though - * the list function ignores the op parameter, we do not want any - * C side effects, where a function is called without the caller - * sending a third parameter. - * Archs are to support both the regs and ftrace_ops at the same time. - * If they support ftrace_ops, it is assumed they support regs. - * If call backs want to use regs, they must either check for regs - * being NULL, or ARCH_SUPPORTS_FTRACE_SAVE_REGS. - * Note, ARCH_SUPPORT_SAVE_REGS expects a full regs to be saved. - * An architecture can pass partial regs with ftrace_ops and still - * set the ARCH_SUPPORT_FTARCE_OPS. - */ -#if ARCH_SUPPORTS_FTRACE_OPS -static void ftrace_ops_list_func(unsigned long ip, unsigned long parent_ip, - struct ftrace_ops *op, struct pt_regs *regs) -{ - __ftrace_ops_list_func(ip, parent_ip, NULL, regs); -} -#else -static void ftrace_ops_no_ops(unsigned long ip, unsigned long parent_ip) -{ - __ftrace_ops_list_func(ip, parent_ip, NULL, NULL); -} -#endif - static void clear_ftrace_swapper(void) { struct task_struct *p; diff --git a/trunk/kernel/trace/ring_buffer.c b/trunk/kernel/trace/ring_buffer.c index b32ed0e385a5..49491fa7daa2 100644 --- a/trunk/kernel/trace/ring_buffer.c +++ b/trunk/kernel/trace/ring_buffer.c @@ -2816,7 +2816,7 @@ EXPORT_SYMBOL_GPL(ring_buffer_record_enable); * to the buffer after this will fail and return NULL. * * This is different than ring_buffer_record_disable() as - * it works like an on/off switch, where as the disable() version + * it works like an on/off switch, where as the disable() verison * must be paired with a enable(). */ void ring_buffer_record_off(struct ring_buffer *buffer) @@ -2839,7 +2839,7 @@ EXPORT_SYMBOL_GPL(ring_buffer_record_off); * ring_buffer_record_off(). * * This is different than ring_buffer_record_enable() as - * it works like an on/off switch, where as the enable() version + * it works like an on/off switch, where as the enable() verison * must be paired with a disable(). */ void ring_buffer_record_on(struct ring_buffer *buffer) diff --git a/trunk/kernel/trace/trace.c b/trunk/kernel/trace/trace.c index 1ec5c1dab629..5c38c81496ce 100644 --- a/trunk/kernel/trace/trace.c +++ b/trunk/kernel/trace/trace.c @@ -328,7 +328,7 @@ static DECLARE_WAIT_QUEUE_HEAD(trace_wait); unsigned long trace_flags = TRACE_ITER_PRINT_PARENT | TRACE_ITER_PRINTK | TRACE_ITER_ANNOTATE | TRACE_ITER_CONTEXT_INFO | TRACE_ITER_SLEEP_TIME | TRACE_ITER_GRAPH_TIME | TRACE_ITER_RECORD_CMD | TRACE_ITER_OVERWRITE | - TRACE_ITER_IRQ_INFO | TRACE_ITER_MARKERS; + TRACE_ITER_IRQ_INFO; static int trace_stop_count; static DEFINE_RAW_SPINLOCK(tracing_start_lock); @@ -426,15 +426,15 @@ __setup("trace_buf_size=", set_buf_size); static int __init set_tracing_thresh(char *str) { - unsigned long threshold; + unsigned long threshhold; int ret; if (!str) return 0; - ret = strict_strtoul(str, 0, &threshold); + ret = strict_strtoul(str, 0, &threshhold); if (ret < 0) return 0; - tracing_thresh = threshold * 1000; + tracing_thresh = threshhold * 1000; return 1; } __setup("tracing_thresh=", set_tracing_thresh); @@ -470,7 +470,6 @@ static const char *trace_options[] = { "overwrite", "disable_on_free", "irq-info", - "markers", NULL }; @@ -3887,9 +3886,6 @@ tracing_mark_write(struct file *filp, const char __user *ubuf, if (tracing_disabled) return -EINVAL; - if (!(trace_flags & TRACE_ITER_MARKERS)) - return -EINVAL; - if (cnt > TRACE_BUF_SIZE) cnt = TRACE_BUF_SIZE; diff --git a/trunk/kernel/trace/trace.h b/trunk/kernel/trace/trace.h index 63a2da0b9a6e..55e1f7f0db12 100644 --- a/trunk/kernel/trace/trace.h +++ b/trunk/kernel/trace/trace.h @@ -472,11 +472,11 @@ extern void trace_find_cmdline(int pid, char comm[]); #ifdef CONFIG_DYNAMIC_FTRACE extern unsigned long ftrace_update_tot_cnt; -#endif #define DYN_FTRACE_TEST_NAME trace_selftest_dynamic_test_func extern int DYN_FTRACE_TEST_NAME(void); #define DYN_FTRACE_TEST_NAME2 trace_selftest_dynamic_test_func2 extern int DYN_FTRACE_TEST_NAME2(void); +#endif extern int ring_buffer_expanded; extern bool tracing_selftest_disabled; @@ -680,7 +680,6 @@ enum trace_iterator_flags { TRACE_ITER_OVERWRITE = 0x200000, TRACE_ITER_STOP_ON_FREE = 0x400000, TRACE_ITER_IRQ_INFO = 0x800000, - TRACE_ITER_MARKERS = 0x1000000, }; /* diff --git a/trunk/kernel/trace/trace_event_perf.c b/trunk/kernel/trace/trace_event_perf.c index 84b1e045faba..fee3752ae8f6 100644 --- a/trunk/kernel/trace/trace_event_perf.c +++ b/trunk/kernel/trace/trace_event_perf.c @@ -258,8 +258,7 @@ EXPORT_SYMBOL_GPL(perf_trace_buf_prepare); #ifdef CONFIG_FUNCTION_TRACER static void -perf_ftrace_function_call(unsigned long ip, unsigned long parent_ip, - struct ftrace_ops *ops, struct pt_regs *pt_regs) +perf_ftrace_function_call(unsigned long ip, unsigned long parent_ip) { struct ftrace_entry *entry; struct hlist_head *head; @@ -282,7 +281,7 @@ perf_ftrace_function_call(unsigned long ip, unsigned long parent_ip, head = this_cpu_ptr(event_function.perf_events); perf_trace_buf_submit(entry, ENTRY_SIZE, rctx, 0, - 1, ®s, head, NULL); + 1, ®s, head); #undef ENTRY_SIZE } diff --git a/trunk/kernel/trace/trace_events.c b/trunk/kernel/trace/trace_events.c index d608d09d08c0..29111da1d100 100644 --- a/trunk/kernel/trace/trace_events.c +++ b/trunk/kernel/trace/trace_events.c @@ -1199,31 +1199,6 @@ event_create_dir(struct ftrace_event_call *call, struct dentry *d_events, return 0; } -static void event_remove(struct ftrace_event_call *call) -{ - ftrace_event_enable_disable(call, 0); - if (call->event.funcs) - __unregister_ftrace_event(&call->event); - list_del(&call->list); -} - -static int event_init(struct ftrace_event_call *call) -{ - int ret = 0; - - if (WARN_ON(!call->name)) - return -EINVAL; - - if (call->class->raw_init) { - ret = call->class->raw_init(call); - if (ret < 0 && ret != -ENOSYS) - pr_warn("Could not initialize trace events/%s\n", - call->name); - } - - return ret; -} - static int __trace_add_event_call(struct ftrace_event_call *call, struct module *mod, const struct file_operations *id, @@ -1234,9 +1209,19 @@ __trace_add_event_call(struct ftrace_event_call *call, struct module *mod, struct dentry *d_events; int ret; - ret = event_init(call); - if (ret < 0) - return ret; + /* The linker may leave blanks */ + if (!call->name) + return -EINVAL; + + if (call->class->raw_init) { + ret = call->class->raw_init(call); + if (ret < 0) { + if (ret != -ENOSYS) + pr_warning("Could not initialize trace events/%s\n", + call->name); + return ret; + } + } d_events = event_trace_events_dir(); if (!d_events) @@ -1287,10 +1272,13 @@ static void remove_subsystem_dir(const char *name) */ static void __trace_remove_event_call(struct ftrace_event_call *call) { - event_remove(call); + ftrace_event_enable_disable(call, 0); + if (call->event.funcs) + __unregister_ftrace_event(&call->event); + debugfs_remove_recursive(call->dir); + list_del(&call->list); trace_destroy_fields(call); destroy_preds(call); - debugfs_remove_recursive(call->dir); remove_subsystem_dir(call->class->system); } @@ -1462,43 +1450,15 @@ static __init int setup_trace_event(char *str) } __setup("trace_event=", setup_trace_event); -static __init int event_trace_enable(void) -{ - struct ftrace_event_call **iter, *call; - char *buf = bootup_event_buf; - char *token; - int ret; - - for_each_event(iter, __start_ftrace_events, __stop_ftrace_events) { - - call = *iter; - ret = event_init(call); - if (!ret) - list_add(&call->list, &ftrace_events); - } - - while (true) { - token = strsep(&buf, ","); - - if (!token) - break; - if (!*token) - continue; - - ret = ftrace_set_clr_event(token, 1); - if (ret) - pr_warn("Failed to enable trace event: %s\n", token); - } - return 0; -} - static __init int event_trace_init(void) { - struct ftrace_event_call *call; + struct ftrace_event_call **call; struct dentry *d_tracer; struct dentry *entry; struct dentry *d_events; int ret; + char *buf = bootup_event_buf; + char *token; d_tracer = tracing_init_dentry(); if (!d_tracer) @@ -1537,19 +1497,24 @@ static __init int event_trace_init(void) if (trace_define_common_fields()) pr_warning("tracing: Failed to allocate common fields"); - /* - * Early initialization already enabled ftrace event. - * Now it's only necessary to create the event directory. - */ - list_for_each_entry(call, &ftrace_events, list) { - - ret = event_create_dir(call, d_events, - &ftrace_event_id_fops, + for_each_event(call, __start_ftrace_events, __stop_ftrace_events) { + __trace_add_event_call(*call, NULL, &ftrace_event_id_fops, &ftrace_enable_fops, &ftrace_event_filter_fops, &ftrace_event_format_fops); - if (ret < 0) - event_remove(call); + } + + while (true) { + token = strsep(&buf, ","); + + if (!token) + break; + if (!*token) + continue; + + ret = ftrace_set_clr_event(token, 1); + if (ret) + pr_warning("Failed to enable trace event: %s\n", token); } ret = register_module_notifier(&trace_module_nb); @@ -1558,7 +1523,6 @@ static __init int event_trace_init(void) return 0; } -core_initcall(event_trace_enable); fs_initcall(event_trace_init); #ifdef CONFIG_FTRACE_STARTUP_TEST @@ -1682,11 +1646,9 @@ static __init void event_trace_self_tests(void) event_test_stuff(); ret = __ftrace_set_clr_event(NULL, system->name, NULL, 0); - if (WARN_ON_ONCE(ret)) { + if (WARN_ON_ONCE(ret)) pr_warning("error disabling system %s\n", system->name); - continue; - } pr_cont("OK\n"); } @@ -1719,8 +1681,7 @@ static __init void event_trace_self_tests(void) static DEFINE_PER_CPU(atomic_t, ftrace_test_event_disable); static void -function_test_events_call(unsigned long ip, unsigned long parent_ip, - struct ftrace_ops *op, struct pt_regs *pt_regs) +function_test_events_call(unsigned long ip, unsigned long parent_ip) { struct ring_buffer_event *event; struct ring_buffer *buffer; @@ -1759,7 +1720,6 @@ function_test_events_call(unsigned long ip, unsigned long parent_ip, static struct ftrace_ops trace_ops __initdata = { .func = function_test_events_call, - .flags = FTRACE_OPS_FL_RECURSION_SAFE, }; static __init void event_trace_self_test_with_function(void) diff --git a/trunk/kernel/trace/trace_events_filter.c b/trunk/kernel/trace/trace_events_filter.c index c154797a7ff7..431dba8b7542 100644 --- a/trunk/kernel/trace/trace_events_filter.c +++ b/trunk/kernel/trace/trace_events_filter.c @@ -2002,7 +2002,7 @@ static int ftrace_function_set_regexp(struct ftrace_ops *ops, int filter, static int __ftrace_function_set_filter(int filter, char *buf, int len, struct function_filter_data *data) { - int i, re_cnt, ret = -EINVAL; + int i, re_cnt, ret; int *reset; char **re; diff --git a/trunk/kernel/trace/trace_functions.c b/trunk/kernel/trace/trace_functions.c index 483162a9f908..a426f410c060 100644 --- a/trunk/kernel/trace/trace_functions.c +++ b/trunk/kernel/trace/trace_functions.c @@ -49,8 +49,7 @@ static void function_trace_start(struct trace_array *tr) } static void -function_trace_call_preempt_only(unsigned long ip, unsigned long parent_ip, - struct ftrace_ops *op, struct pt_regs *pt_regs) +function_trace_call_preempt_only(unsigned long ip, unsigned long parent_ip) { struct trace_array *tr = func_trace; struct trace_array_cpu *data; @@ -85,9 +84,7 @@ enum { static struct tracer_flags func_flags; static void -function_trace_call(unsigned long ip, unsigned long parent_ip, - struct ftrace_ops *op, struct pt_regs *pt_regs) - +function_trace_call(unsigned long ip, unsigned long parent_ip) { struct trace_array *tr = func_trace; struct trace_array_cpu *data; @@ -124,8 +121,7 @@ function_trace_call(unsigned long ip, unsigned long parent_ip, } static void -function_stack_trace_call(unsigned long ip, unsigned long parent_ip, - struct ftrace_ops *op, struct pt_regs *pt_regs) +function_stack_trace_call(unsigned long ip, unsigned long parent_ip) { struct trace_array *tr = func_trace; struct trace_array_cpu *data; @@ -168,13 +164,13 @@ function_stack_trace_call(unsigned long ip, unsigned long parent_ip, static struct ftrace_ops trace_ops __read_mostly = { .func = function_trace_call, - .flags = FTRACE_OPS_FL_GLOBAL | FTRACE_OPS_FL_RECURSION_SAFE, + .flags = FTRACE_OPS_FL_GLOBAL, }; static struct ftrace_ops trace_stack_ops __read_mostly = { .func = function_stack_trace_call, - .flags = FTRACE_OPS_FL_GLOBAL | FTRACE_OPS_FL_RECURSION_SAFE, + .flags = FTRACE_OPS_FL_GLOBAL, }; static struct tracer_opt func_opts[] = { diff --git a/trunk/kernel/trace/trace_functions_graph.c b/trunk/kernel/trace/trace_functions_graph.c index 99b4378393d5..ce27c8ba8d31 100644 --- a/trunk/kernel/trace/trace_functions_graph.c +++ b/trunk/kernel/trace/trace_functions_graph.c @@ -143,7 +143,7 @@ ftrace_pop_return_trace(struct ftrace_graph_ret *trace, unsigned long *ret, return; } -#if defined(CONFIG_HAVE_FUNCTION_GRAPH_FP_TEST) && !defined(CC_USING_FENTRY) +#ifdef CONFIG_HAVE_FUNCTION_GRAPH_FP_TEST /* * The arch may choose to record the frame pointer used * and check it here to make sure that it is what we expect it @@ -154,9 +154,6 @@ ftrace_pop_return_trace(struct ftrace_graph_ret *trace, unsigned long *ret, * * Currently, x86_32 with optimize for size (-Os) makes the latest * gcc do the above. - * - * Note, -mfentry does not use frame pointers, and this test - * is not needed if CC_USING_FENTRY is set. */ if (unlikely(current->ret_stack[index].fp != frame_pointer)) { ftrace_graph_stop(); diff --git a/trunk/kernel/trace/trace_irqsoff.c b/trunk/kernel/trace/trace_irqsoff.c index d98ee8283b29..99d20e920368 100644 --- a/trunk/kernel/trace/trace_irqsoff.c +++ b/trunk/kernel/trace/trace_irqsoff.c @@ -136,8 +136,7 @@ static int func_prolog_dec(struct trace_array *tr, * irqsoff uses its own tracer function to keep the overhead down: */ static void -irqsoff_tracer_call(unsigned long ip, unsigned long parent_ip, - struct ftrace_ops *op, struct pt_regs *pt_regs) +irqsoff_tracer_call(unsigned long ip, unsigned long parent_ip) { struct trace_array *tr = irqsoff_trace; struct trace_array_cpu *data; @@ -154,7 +153,7 @@ irqsoff_tracer_call(unsigned long ip, unsigned long parent_ip, static struct ftrace_ops trace_ops __read_mostly = { .func = irqsoff_tracer_call, - .flags = FTRACE_OPS_FL_GLOBAL | FTRACE_OPS_FL_RECURSION_SAFE, + .flags = FTRACE_OPS_FL_GLOBAL, }; #endif /* CONFIG_FUNCTION_TRACER */ diff --git a/trunk/kernel/trace/trace_kprobe.c b/trunk/kernel/trace/trace_kprobe.c index 1a2117043bb1..b31d3d5699fe 100644 --- a/trunk/kernel/trace/trace_kprobe.c +++ b/trunk/kernel/trace/trace_kprobe.c @@ -1002,8 +1002,7 @@ static __kprobes void kprobe_perf_func(struct kprobe *kp, store_trace_args(sizeof(*entry), tp, regs, (u8 *)&entry[1], dsize); head = this_cpu_ptr(call->perf_events); - perf_trace_buf_submit(entry, size, rctx, - entry->ip, 1, regs, head, NULL); + perf_trace_buf_submit(entry, size, rctx, entry->ip, 1, regs, head); } /* Kretprobe profile handler */ @@ -1034,8 +1033,7 @@ static __kprobes void kretprobe_perf_func(struct kretprobe_instance *ri, store_trace_args(sizeof(*entry), tp, regs, (u8 *)&entry[1], dsize); head = this_cpu_ptr(call->perf_events); - perf_trace_buf_submit(entry, size, rctx, - entry->ret_ip, 1, regs, head, NULL); + perf_trace_buf_submit(entry, size, rctx, entry->ret_ip, 1, regs, head); } #endif /* CONFIG_PERF_EVENTS */ diff --git a/trunk/kernel/trace/trace_sched_wakeup.c b/trunk/kernel/trace/trace_sched_wakeup.c index 02170c00c413..ff791ea48b57 100644 --- a/trunk/kernel/trace/trace_sched_wakeup.c +++ b/trunk/kernel/trace/trace_sched_wakeup.c @@ -108,8 +108,7 @@ func_prolog_preempt_disable(struct trace_array *tr, * wakeup uses its own tracer function to keep the overhead down: */ static void -wakeup_tracer_call(unsigned long ip, unsigned long parent_ip, - struct ftrace_ops *op, struct pt_regs *pt_regs) +wakeup_tracer_call(unsigned long ip, unsigned long parent_ip) { struct trace_array *tr = wakeup_trace; struct trace_array_cpu *data; @@ -130,7 +129,7 @@ wakeup_tracer_call(unsigned long ip, unsigned long parent_ip, static struct ftrace_ops trace_ops __read_mostly = { .func = wakeup_tracer_call, - .flags = FTRACE_OPS_FL_GLOBAL | FTRACE_OPS_FL_RECURSION_SAFE, + .flags = FTRACE_OPS_FL_GLOBAL, }; #endif /* CONFIG_FUNCTION_TRACER */ diff --git a/trunk/kernel/trace/trace_selftest.c b/trunk/kernel/trace/trace_selftest.c index 2c00a691a540..288541f977fb 100644 --- a/trunk/kernel/trace/trace_selftest.c +++ b/trunk/kernel/trace/trace_selftest.c @@ -103,67 +103,54 @@ static inline void warn_failed_init_tracer(struct tracer *trace, int init_ret) static int trace_selftest_test_probe1_cnt; static void trace_selftest_test_probe1_func(unsigned long ip, - unsigned long pip, - struct ftrace_ops *op, - struct pt_regs *pt_regs) + unsigned long pip) { trace_selftest_test_probe1_cnt++; } static int trace_selftest_test_probe2_cnt; static void trace_selftest_test_probe2_func(unsigned long ip, - unsigned long pip, - struct ftrace_ops *op, - struct pt_regs *pt_regs) + unsigned long pip) { trace_selftest_test_probe2_cnt++; } static int trace_selftest_test_probe3_cnt; static void trace_selftest_test_probe3_func(unsigned long ip, - unsigned long pip, - struct ftrace_ops *op, - struct pt_regs *pt_regs) + unsigned long pip) { trace_selftest_test_probe3_cnt++; } static int trace_selftest_test_global_cnt; static void trace_selftest_test_global_func(unsigned long ip, - unsigned long pip, - struct ftrace_ops *op, - struct pt_regs *pt_regs) + unsigned long pip) { trace_selftest_test_global_cnt++; } static int trace_selftest_test_dyn_cnt; static void trace_selftest_test_dyn_func(unsigned long ip, - unsigned long pip, - struct ftrace_ops *op, - struct pt_regs *pt_regs) + unsigned long pip) { trace_selftest_test_dyn_cnt++; } static struct ftrace_ops test_probe1 = { .func = trace_selftest_test_probe1_func, - .flags = FTRACE_OPS_FL_RECURSION_SAFE, }; static struct ftrace_ops test_probe2 = { .func = trace_selftest_test_probe2_func, - .flags = FTRACE_OPS_FL_RECURSION_SAFE, }; static struct ftrace_ops test_probe3 = { .func = trace_selftest_test_probe3_func, - .flags = FTRACE_OPS_FL_RECURSION_SAFE, }; static struct ftrace_ops test_global = { - .func = trace_selftest_test_global_func, - .flags = FTRACE_OPS_FL_GLOBAL | FTRACE_OPS_FL_RECURSION_SAFE, + .func = trace_selftest_test_global_func, + .flags = FTRACE_OPS_FL_GLOBAL, }; static void print_counts(void) @@ -406,253 +393,10 @@ int trace_selftest_startup_dynamic_tracing(struct tracer *trace, return ret; } - -static int trace_selftest_recursion_cnt; -static void trace_selftest_test_recursion_func(unsigned long ip, - unsigned long pip, - struct ftrace_ops *op, - struct pt_regs *pt_regs) -{ - /* - * This function is registered without the recursion safe flag. - * The ftrace infrastructure should provide the recursion - * protection. If not, this will crash the kernel! - */ - trace_selftest_recursion_cnt++; - DYN_FTRACE_TEST_NAME(); -} - -static void trace_selftest_test_recursion_safe_func(unsigned long ip, - unsigned long pip, - struct ftrace_ops *op, - struct pt_regs *pt_regs) -{ - /* - * We said we would provide our own recursion. By calling - * this function again, we should recurse back into this function - * and count again. But this only happens if the arch supports - * all of ftrace features and nothing else is using the function - * tracing utility. - */ - if (trace_selftest_recursion_cnt++) - return; - DYN_FTRACE_TEST_NAME(); -} - -static struct ftrace_ops test_rec_probe = { - .func = trace_selftest_test_recursion_func, -}; - -static struct ftrace_ops test_recsafe_probe = { - .func = trace_selftest_test_recursion_safe_func, - .flags = FTRACE_OPS_FL_RECURSION_SAFE, -}; - -static int -trace_selftest_function_recursion(void) -{ - int save_ftrace_enabled = ftrace_enabled; - int save_tracer_enabled = tracer_enabled; - char *func_name; - int len; - int ret; - int cnt; - - /* The previous test PASSED */ - pr_cont("PASSED\n"); - pr_info("Testing ftrace recursion: "); - - - /* enable tracing, and record the filter function */ - ftrace_enabled = 1; - tracer_enabled = 1; - - /* Handle PPC64 '.' name */ - func_name = "*" __stringify(DYN_FTRACE_TEST_NAME); - len = strlen(func_name); - - ret = ftrace_set_filter(&test_rec_probe, func_name, len, 1); - if (ret) { - pr_cont("*Could not set filter* "); - goto out; - } - - ret = register_ftrace_function(&test_rec_probe); - if (ret) { - pr_cont("*could not register callback* "); - goto out; - } - - DYN_FTRACE_TEST_NAME(); - - unregister_ftrace_function(&test_rec_probe); - - ret = -1; - if (trace_selftest_recursion_cnt != 1) { - pr_cont("*callback not called once (%d)* ", - trace_selftest_recursion_cnt); - goto out; - } - - trace_selftest_recursion_cnt = 1; - - pr_cont("PASSED\n"); - pr_info("Testing ftrace recursion safe: "); - - ret = ftrace_set_filter(&test_recsafe_probe, func_name, len, 1); - if (ret) { - pr_cont("*Could not set filter* "); - goto out; - } - - ret = register_ftrace_function(&test_recsafe_probe); - if (ret) { - pr_cont("*could not register callback* "); - goto out; - } - - DYN_FTRACE_TEST_NAME(); - - unregister_ftrace_function(&test_recsafe_probe); - - /* - * If arch supports all ftrace features, and no other task - * was on the list, we should be fine. - */ - if (!ftrace_nr_registered_ops() && !FTRACE_FORCE_LIST_FUNC) - cnt = 2; /* Should have recursed */ - else - cnt = 1; - - ret = -1; - if (trace_selftest_recursion_cnt != cnt) { - pr_cont("*callback not called expected %d times (%d)* ", - cnt, trace_selftest_recursion_cnt); - goto out; - } - - ret = 0; -out: - ftrace_enabled = save_ftrace_enabled; - tracer_enabled = save_tracer_enabled; - - return ret; -} #else # define trace_selftest_startup_dynamic_tracing(trace, tr, func) ({ 0; }) -# define trace_selftest_function_recursion() ({ 0; }) #endif /* CONFIG_DYNAMIC_FTRACE */ -static enum { - TRACE_SELFTEST_REGS_START, - TRACE_SELFTEST_REGS_FOUND, - TRACE_SELFTEST_REGS_NOT_FOUND, -} trace_selftest_regs_stat; - -static void trace_selftest_test_regs_func(unsigned long ip, - unsigned long pip, - struct ftrace_ops *op, - struct pt_regs *pt_regs) -{ - if (pt_regs) - trace_selftest_regs_stat = TRACE_SELFTEST_REGS_FOUND; - else - trace_selftest_regs_stat = TRACE_SELFTEST_REGS_NOT_FOUND; -} - -static struct ftrace_ops test_regs_probe = { - .func = trace_selftest_test_regs_func, - .flags = FTRACE_OPS_FL_RECURSION_SAFE | FTRACE_OPS_FL_SAVE_REGS, -}; - -static int -trace_selftest_function_regs(void) -{ - int save_ftrace_enabled = ftrace_enabled; - int save_tracer_enabled = tracer_enabled; - char *func_name; - int len; - int ret; - int supported = 0; - -#ifdef ARCH_SUPPORTS_FTRACE_SAVE_REGS - supported = 1; -#endif - - /* The previous test PASSED */ - pr_cont("PASSED\n"); - pr_info("Testing ftrace regs%s: ", - !supported ? "(no arch support)" : ""); - - /* enable tracing, and record the filter function */ - ftrace_enabled = 1; - tracer_enabled = 1; - - /* Handle PPC64 '.' name */ - func_name = "*" __stringify(DYN_FTRACE_TEST_NAME); - len = strlen(func_name); - - ret = ftrace_set_filter(&test_regs_probe, func_name, len, 1); - /* - * If DYNAMIC_FTRACE is not set, then we just trace all functions. - * This test really doesn't care. - */ - if (ret && ret != -ENODEV) { - pr_cont("*Could not set filter* "); - goto out; - } - - ret = register_ftrace_function(&test_regs_probe); - /* - * Now if the arch does not support passing regs, then this should - * have failed. - */ - if (!supported) { - if (!ret) { - pr_cont("*registered save-regs without arch support* "); - goto out; - } - test_regs_probe.flags |= FTRACE_OPS_FL_SAVE_REGS_IF_SUPPORTED; - ret = register_ftrace_function(&test_regs_probe); - } - if (ret) { - pr_cont("*could not register callback* "); - goto out; - } - - - DYN_FTRACE_TEST_NAME(); - - unregister_ftrace_function(&test_regs_probe); - - ret = -1; - - switch (trace_selftest_regs_stat) { - case TRACE_SELFTEST_REGS_START: - pr_cont("*callback never called* "); - goto out; - - case TRACE_SELFTEST_REGS_FOUND: - if (supported) - break; - pr_cont("*callback received regs without arch support* "); - goto out; - - case TRACE_SELFTEST_REGS_NOT_FOUND: - if (!supported) - break; - pr_cont("*callback received NULL regs* "); - goto out; - } - - ret = 0; -out: - ftrace_enabled = save_ftrace_enabled; - tracer_enabled = save_tracer_enabled; - - return ret; -} - /* * Simple verification test of ftrace function tracer. * Enable ftrace, sleep 1/10 second, and then read the trace @@ -698,14 +442,7 @@ trace_selftest_startup_function(struct tracer *trace, struct trace_array *tr) ret = trace_selftest_startup_dynamic_tracing(trace, tr, DYN_FTRACE_TEST_NAME); - if (ret) - goto out; - ret = trace_selftest_function_recursion(); - if (ret) - goto out; - - ret = trace_selftest_function_regs(); out: ftrace_enabled = save_ftrace_enabled; tracer_enabled = save_tracer_enabled; @@ -1041,8 +778,6 @@ static int trace_wakeup_test_thread(void *data) set_current_state(TASK_INTERRUPTIBLE); schedule(); - complete(x); - /* we are awake, now wait to disappear */ while (!kthread_should_stop()) { /* @@ -1086,21 +821,24 @@ trace_selftest_startup_wakeup(struct tracer *trace, struct trace_array *tr) /* reset the max latency */ tracing_max_latency = 0; - while (p->on_rq) { - /* - * Sleep to make sure the RT thread is asleep too. - * On virtual machines we can't rely on timings, - * but we want to make sure this test still works. - */ - msleep(100); - } + /* sleep to let the RT thread sleep too */ + msleep(100); - init_completion(&isrt); + /* + * Yes this is slightly racy. It is possible that for some + * strange reason that the RT thread we created, did not + * call schedule for 100ms after doing the completion, + * and we do a wakeup on a task that already is awake. + * But that is extremely unlikely, and the worst thing that + * happens in such a case, is that we disable tracing. + * Honestly, if this race does happen something is horrible + * wrong with the system. + */ wake_up_process(p); - /* Wait for the task to wake up */ - wait_for_completion(&isrt); + /* give a little time to let the thread wake up */ + msleep(100); /* stop the tracing. */ tracing_stop(); diff --git a/trunk/kernel/trace/trace_stack.c b/trunk/kernel/trace/trace_stack.c index 0c1b165778e5..d4545f49242e 100644 --- a/trunk/kernel/trace/trace_stack.c +++ b/trunk/kernel/trace/trace_stack.c @@ -111,8 +111,7 @@ static inline void check_stack(void) } static void -stack_trace_call(unsigned long ip, unsigned long parent_ip, - struct ftrace_ops *op, struct pt_regs *pt_regs) +stack_trace_call(unsigned long ip, unsigned long parent_ip) { int cpu; @@ -137,7 +136,6 @@ stack_trace_call(unsigned long ip, unsigned long parent_ip, static struct ftrace_ops trace_ops __read_mostly = { .func = stack_trace_call, - .flags = FTRACE_OPS_FL_RECURSION_SAFE, }; static ssize_t diff --git a/trunk/kernel/trace/trace_syscalls.c b/trunk/kernel/trace/trace_syscalls.c index 2485a7d09b11..96fc73369099 100644 --- a/trunk/kernel/trace/trace_syscalls.c +++ b/trunk/kernel/trace/trace_syscalls.c @@ -487,7 +487,7 @@ int __init init_ftrace_syscalls(void) return 0; } -early_initcall(init_ftrace_syscalls); +core_initcall(init_ftrace_syscalls); #ifdef CONFIG_PERF_EVENTS @@ -506,8 +506,6 @@ static void perf_syscall_enter(void *ignore, struct pt_regs *regs, long id) int size; syscall_nr = syscall_get_nr(current, regs); - if (syscall_nr < 0) - return; if (!test_bit(syscall_nr, enabled_perf_enter_syscalls)) return; @@ -534,7 +532,7 @@ static void perf_syscall_enter(void *ignore, struct pt_regs *regs, long id) (unsigned long *)&rec->args); head = this_cpu_ptr(sys_data->enter_event->perf_events); - perf_trace_buf_submit(rec, size, rctx, 0, 1, regs, head, NULL); + perf_trace_buf_submit(rec, size, rctx, 0, 1, regs, head); } int perf_sysenter_enable(struct ftrace_event_call *call) @@ -582,8 +580,6 @@ static void perf_syscall_exit(void *ignore, struct pt_regs *regs, long ret) int size; syscall_nr = syscall_get_nr(current, regs); - if (syscall_nr < 0) - return; if (!test_bit(syscall_nr, enabled_perf_exit_syscalls)) return; @@ -612,7 +608,7 @@ static void perf_syscall_exit(void *ignore, struct pt_regs *regs, long ret) rec->ret = syscall_get_return_value(current, regs); head = this_cpu_ptr(sys_data->exit_event->perf_events); - perf_trace_buf_submit(rec, size, rctx, 0, 1, regs, head, NULL); + perf_trace_buf_submit(rec, size, rctx, 0, 1, regs, head); } int perf_sysexit_enable(struct ftrace_event_call *call) diff --git a/trunk/kernel/trace/trace_uprobe.c b/trunk/kernel/trace/trace_uprobe.c index 03003cd7dd96..2b36ac68549e 100644 --- a/trunk/kernel/trace/trace_uprobe.c +++ b/trunk/kernel/trace/trace_uprobe.c @@ -670,7 +670,7 @@ static void uprobe_perf_func(struct trace_uprobe *tu, struct pt_regs *regs) call_fetch(&tu->args[i].fetch, regs, data + tu->args[i].offset); head = this_cpu_ptr(call->perf_events); - perf_trace_buf_submit(entry, size, rctx, entry->ip, 1, regs, head, NULL); + perf_trace_buf_submit(entry, size, rctx, entry->ip, 1, regs, head); out: preempt_enable(); diff --git a/trunk/kernel/watchdog.c b/trunk/kernel/watchdog.c index 9d4c8d5a1f53..69add8a9da68 100644 --- a/trunk/kernel/watchdog.c +++ b/trunk/kernel/watchdog.c @@ -22,7 +22,6 @@ #include #include #include -#include #include #include @@ -30,18 +29,16 @@ int watchdog_enabled = 1; int __read_mostly watchdog_thresh = 10; -static int __read_mostly watchdog_disabled; static DEFINE_PER_CPU(unsigned long, watchdog_touch_ts); static DEFINE_PER_CPU(struct task_struct *, softlockup_watchdog); static DEFINE_PER_CPU(struct hrtimer, watchdog_hrtimer); static DEFINE_PER_CPU(bool, softlockup_touch_sync); static DEFINE_PER_CPU(bool, soft_watchdog_warn); -static DEFINE_PER_CPU(unsigned long, hrtimer_interrupts); -static DEFINE_PER_CPU(unsigned long, soft_lockup_hrtimer_cnt); #ifdef CONFIG_HARDLOCKUP_DETECTOR static DEFINE_PER_CPU(bool, hard_watchdog_warn); static DEFINE_PER_CPU(bool, watchdog_nmi_touch); +static DEFINE_PER_CPU(unsigned long, hrtimer_interrupts); static DEFINE_PER_CPU(unsigned long, hrtimer_interrupts_saved); static DEFINE_PER_CPU(struct perf_event *, watchdog_ev); #endif @@ -251,15 +248,13 @@ static void watchdog_overflow_callback(struct perf_event *event, __this_cpu_write(hard_watchdog_warn, false); return; } -#endif /* CONFIG_HARDLOCKUP_DETECTOR */ - static void watchdog_interrupt_count(void) { __this_cpu_inc(hrtimer_interrupts); } - -static int watchdog_nmi_enable(unsigned int cpu); -static void watchdog_nmi_disable(unsigned int cpu); +#else +static inline void watchdog_interrupt_count(void) { return; } +#endif /* CONFIG_HARDLOCKUP_DETECTOR */ /* watchdog kicker functions */ static enum hrtimer_restart watchdog_timer_fn(struct hrtimer *hrtimer) @@ -332,68 +327,49 @@ static enum hrtimer_restart watchdog_timer_fn(struct hrtimer *hrtimer) return HRTIMER_RESTART; } -static void watchdog_set_prio(unsigned int policy, unsigned int prio) -{ - struct sched_param param = { .sched_priority = prio }; - - sched_setscheduler(current, policy, ¶m); -} -static void watchdog_enable(unsigned int cpu) +/* + * The watchdog thread - touches the timestamp. + */ +static int watchdog(void *unused) { + struct sched_param param = { .sched_priority = 0 }; struct hrtimer *hrtimer = &__raw_get_cpu_var(watchdog_hrtimer); - if (!watchdog_enabled) { - kthread_park(current); - return; - } - - /* Enable the perf event */ - watchdog_nmi_enable(cpu); + /* initialize timestamp */ + __touch_watchdog(); /* kick off the timer for the hardlockup detector */ - hrtimer_init(hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); - hrtimer->function = watchdog_timer_fn; - /* done here because hrtimer_start can only pin to smp_processor_id() */ hrtimer_start(hrtimer, ns_to_ktime(get_sample_period()), HRTIMER_MODE_REL_PINNED); - /* initialize timestamp */ - watchdog_set_prio(SCHED_FIFO, MAX_RT_PRIO - 1); - __touch_watchdog(); -} - -static void watchdog_disable(unsigned int cpu) -{ - struct hrtimer *hrtimer = &__raw_get_cpu_var(watchdog_hrtimer); + set_current_state(TASK_INTERRUPTIBLE); + /* + * Run briefly (kicked by the hrtimer callback function) once every + * get_sample_period() seconds (4 seconds by default) to reset the + * softlockup timestamp. If this gets delayed for more than + * 2*watchdog_thresh seconds then the debug-printout triggers in + * watchdog_timer_fn(). + */ + while (!kthread_should_stop()) { + __touch_watchdog(); + schedule(); - watchdog_set_prio(SCHED_NORMAL, 0); - hrtimer_cancel(hrtimer); - /* disable the perf event */ - watchdog_nmi_disable(cpu); -} + if (kthread_should_stop()) + break; -static int watchdog_should_run(unsigned int cpu) -{ - return __this_cpu_read(hrtimer_interrupts) != - __this_cpu_read(soft_lockup_hrtimer_cnt); + set_current_state(TASK_INTERRUPTIBLE); + } + /* + * Drop the policy/priority elevation during thread exit to avoid a + * scheduling latency spike. + */ + __set_current_state(TASK_RUNNING); + sched_setscheduler(current, SCHED_NORMAL, ¶m); + return 0; } -/* - * The watchdog thread function - touches the timestamp. - * - * It only runs once every get_sample_period() seconds (4 seconds by - * default) to reset the softlockup timestamp. If this gets delayed - * for more than 2*watchdog_thresh seconds then the debug-printout - * triggers in watchdog_timer_fn(). - */ -static void watchdog(unsigned int cpu) -{ - __this_cpu_write(soft_lockup_hrtimer_cnt, - __this_cpu_read(hrtimer_interrupts)); - __touch_watchdog(); -} #ifdef CONFIG_HARDLOCKUP_DETECTOR /* @@ -403,7 +379,7 @@ static void watchdog(unsigned int cpu) */ static unsigned long cpu0_err; -static int watchdog_nmi_enable(unsigned int cpu) +static int watchdog_nmi_enable(int cpu) { struct perf_event_attr *wd_attr; struct perf_event *event = per_cpu(watchdog_ev, cpu); @@ -457,7 +433,7 @@ static int watchdog_nmi_enable(unsigned int cpu) return 0; } -static void watchdog_nmi_disable(unsigned int cpu) +static void watchdog_nmi_disable(int cpu) { struct perf_event *event = per_cpu(watchdog_ev, cpu); @@ -471,35 +447,107 @@ static void watchdog_nmi_disable(unsigned int cpu) return; } #else -static int watchdog_nmi_enable(unsigned int cpu) { return 0; } -static void watchdog_nmi_disable(unsigned int cpu) { return; } +static int watchdog_nmi_enable(int cpu) { return 0; } +static void watchdog_nmi_disable(int cpu) { return; } #endif /* CONFIG_HARDLOCKUP_DETECTOR */ /* prepare/enable/disable routines */ +static void watchdog_prepare_cpu(int cpu) +{ + struct hrtimer *hrtimer = &per_cpu(watchdog_hrtimer, cpu); + + WARN_ON(per_cpu(softlockup_watchdog, cpu)); + hrtimer_init(hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + hrtimer->function = watchdog_timer_fn; +} + +static int watchdog_enable(int cpu) +{ + struct task_struct *p = per_cpu(softlockup_watchdog, cpu); + int err = 0; + + /* enable the perf event */ + err = watchdog_nmi_enable(cpu); + + /* Regardless of err above, fall through and start softlockup */ + + /* create the watchdog thread */ + if (!p) { + struct sched_param param = { .sched_priority = MAX_RT_PRIO-1 }; + p = kthread_create_on_node(watchdog, NULL, cpu_to_node(cpu), "watchdog/%d", cpu); + if (IS_ERR(p)) { + pr_err("softlockup watchdog for %i failed\n", cpu); + if (!err) { + /* if hardlockup hasn't already set this */ + err = PTR_ERR(p); + /* and disable the perf event */ + watchdog_nmi_disable(cpu); + } + goto out; + } + sched_setscheduler(p, SCHED_FIFO, ¶m); + kthread_bind(p, cpu); + per_cpu(watchdog_touch_ts, cpu) = 0; + per_cpu(softlockup_watchdog, cpu) = p; + wake_up_process(p); + } + +out: + return err; +} + +static void watchdog_disable(int cpu) +{ + struct task_struct *p = per_cpu(softlockup_watchdog, cpu); + struct hrtimer *hrtimer = &per_cpu(watchdog_hrtimer, cpu); + + /* + * cancel the timer first to stop incrementing the stats + * and waking up the kthread + */ + hrtimer_cancel(hrtimer); + + /* disable the perf event */ + watchdog_nmi_disable(cpu); + + /* stop the watchdog thread */ + if (p) { + per_cpu(softlockup_watchdog, cpu) = NULL; + kthread_stop(p); + } +} + /* sysctl functions */ #ifdef CONFIG_SYSCTL static void watchdog_enable_all_cpus(void) { - unsigned int cpu; + int cpu; + + watchdog_enabled = 0; + + for_each_online_cpu(cpu) + if (!watchdog_enable(cpu)) + /* if any cpu succeeds, watchdog is considered + enabled for the system */ + watchdog_enabled = 1; + + if (!watchdog_enabled) + pr_err("failed to be enabled on some cpus\n"); - if (watchdog_disabled) { - watchdog_disabled = 0; - for_each_online_cpu(cpu) - kthread_unpark(per_cpu(softlockup_watchdog, cpu)); - } } static void watchdog_disable_all_cpus(void) { - unsigned int cpu; + int cpu; - if (!watchdog_disabled) { - watchdog_disabled = 1; - for_each_online_cpu(cpu) - kthread_park(per_cpu(softlockup_watchdog, cpu)); - } + for_each_online_cpu(cpu) + watchdog_disable(cpu); + + /* if all watchdogs are disabled, then they are disabled for the system */ + watchdog_enabled = 0; } + /* * proc handler for /proc/sys/kernel/nmi_watchdog,watchdog_thresh */ @@ -509,36 +557,90 @@ int proc_dowatchdog(struct ctl_table *table, int write, { int ret; - if (watchdog_disabled < 0) - return -ENODEV; - ret = proc_dointvec_minmax(table, write, buffer, lenp, ppos); if (ret || !write) - return ret; + goto out; if (watchdog_enabled && watchdog_thresh) watchdog_enable_all_cpus(); else watchdog_disable_all_cpus(); +out: return ret; } #endif /* CONFIG_SYSCTL */ -static struct smp_hotplug_thread watchdog_threads = { - .store = &softlockup_watchdog, - .thread_should_run = watchdog_should_run, - .thread_fn = watchdog, - .thread_comm = "watchdog/%u", - .setup = watchdog_enable, - .park = watchdog_disable, - .unpark = watchdog_enable, + +/* + * Create/destroy watchdog threads as CPUs come and go: + */ +static int +cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) +{ + int hotcpu = (unsigned long)hcpu; + + switch (action) { + case CPU_UP_PREPARE: + case CPU_UP_PREPARE_FROZEN: + watchdog_prepare_cpu(hotcpu); + break; + case CPU_ONLINE: + case CPU_ONLINE_FROZEN: + if (watchdog_enabled) + watchdog_enable(hotcpu); + break; +#ifdef CONFIG_HOTPLUG_CPU + case CPU_UP_CANCELED: + case CPU_UP_CANCELED_FROZEN: + watchdog_disable(hotcpu); + break; + case CPU_DEAD: + case CPU_DEAD_FROZEN: + watchdog_disable(hotcpu); + break; +#endif /* CONFIG_HOTPLUG_CPU */ + } + + /* + * hardlockup and softlockup are not important enough + * to block cpu bring up. Just always succeed and + * rely on printk output to flag problems. + */ + return NOTIFY_OK; +} + +static struct notifier_block cpu_nfb = { + .notifier_call = cpu_callback }; +#ifdef CONFIG_SUSPEND +/* + * On exit from suspend we force an offline->online transition on the boot CPU + * so that the PMU state that was lost while in suspended state gets set up + * properly for the boot CPU. This information is required for restarting the + * NMI watchdog. + */ +void lockup_detector_bootcpu_resume(void) +{ + void *cpu = (void *)(long)smp_processor_id(); + + cpu_callback(&cpu_nfb, CPU_DEAD_FROZEN, cpu); + cpu_callback(&cpu_nfb, CPU_UP_PREPARE_FROZEN, cpu); + cpu_callback(&cpu_nfb, CPU_ONLINE_FROZEN, cpu); +} +#endif + void __init lockup_detector_init(void) { - if (smpboot_register_percpu_thread(&watchdog_threads)) { - pr_err("Failed to create watchdog threads, disabled\n"); - watchdog_disabled = -ENODEV; - } + void *cpu = (void *)(long)smp_processor_id(); + int err; + + err = cpu_callback(&cpu_nfb, CPU_UP_PREPARE, cpu); + WARN_ON(notifier_to_errno(err)); + + cpu_callback(&cpu_nfb, CPU_ONLINE, cpu); + register_cpu_notifier(&cpu_nfb); + + return; } diff --git a/trunk/kernel/workqueue.c b/trunk/kernel/workqueue.c index 3c5a79e2134c..692d97628a10 100644 --- a/trunk/kernel/workqueue.c +++ b/trunk/kernel/workqueue.c @@ -66,7 +66,6 @@ enum { /* pool flags */ POOL_MANAGE_WORKERS = 1 << 0, /* need to manage workers */ - POOL_MANAGING_WORKERS = 1 << 1, /* managing workers */ /* worker flags */ WORKER_STARTED = 1 << 0, /* started */ @@ -653,7 +652,7 @@ static bool need_to_manage_workers(struct worker_pool *pool) /* Do we have too many workers and should some go away? */ static bool too_many_workers(struct worker_pool *pool) { - bool managing = pool->flags & POOL_MANAGING_WORKERS; + bool managing = mutex_is_locked(&pool->manager_mutex); int nr_idle = pool->nr_idle + managing; /* manager is considered idle */ int nr_busy = pool->nr_workers - nr_idle; @@ -1327,15 +1326,6 @@ static void idle_worker_rebind(struct worker *worker) /* we did our part, wait for rebind_workers() to finish up */ wait_event(gcwq->rebind_hold, !(worker->flags & WORKER_REBIND)); - - /* - * rebind_workers() shouldn't finish until all workers passed the - * above WORKER_REBIND wait. Tell it when done. - */ - spin_lock_irq(&worker->pool->gcwq->lock); - if (!--worker->idle_rebind->cnt) - complete(&worker->idle_rebind->done); - spin_unlock_irq(&worker->pool->gcwq->lock); } /* @@ -1349,16 +1339,8 @@ static void busy_worker_rebind_fn(struct work_struct *work) struct worker *worker = container_of(work, struct worker, rebind_work); struct global_cwq *gcwq = worker->pool->gcwq; - worker_maybe_bind_and_lock(worker); - - /* - * %WORKER_REBIND must be cleared even if the above binding failed; - * otherwise, we may confuse the next CPU_UP cycle or oops / get - * stuck by calling idle_worker_rebind() prematurely. If CPU went - * down again inbetween, %WORKER_UNBOUND would be set, so clearing - * %WORKER_REBIND is always safe. - */ - worker_clr_flags(worker, WORKER_REBIND); + if (worker_maybe_bind_and_lock(worker)) + worker_clr_flags(worker, WORKER_REBIND); spin_unlock_irq(&gcwq->lock); } @@ -1414,15 +1396,12 @@ static void rebind_workers(struct global_cwq *gcwq) /* set REBIND and kick idle ones, we'll wait for these later */ for_each_worker_pool(pool, gcwq) { list_for_each_entry(worker, &pool->idle_list, entry) { - unsigned long worker_flags = worker->flags; - if (worker->flags & WORKER_REBIND) continue; - /* morph UNBOUND to REBIND atomically */ - worker_flags &= ~WORKER_UNBOUND; - worker_flags |= WORKER_REBIND; - ACCESS_ONCE(worker->flags) = worker_flags; + /* morph UNBOUND to REBIND */ + worker->flags &= ~WORKER_UNBOUND; + worker->flags |= WORKER_REBIND; idle_rebind.cnt++; worker->idle_rebind = &idle_rebind; @@ -1440,15 +1419,25 @@ static void rebind_workers(struct global_cwq *gcwq) goto retry; } - /* all idle workers are rebound, rebind busy workers */ + /* + * All idle workers are rebound and waiting for %WORKER_REBIND to + * be cleared inside idle_worker_rebind(). Clear and release. + * Clearing %WORKER_REBIND from this foreign context is safe + * because these workers are still guaranteed to be idle. + */ + for_each_worker_pool(pool, gcwq) + list_for_each_entry(worker, &pool->idle_list, entry) + worker->flags &= ~WORKER_REBIND; + + wake_up_all(&gcwq->rebind_hold); + + /* rebind busy workers */ for_each_busy_worker(worker, i, pos, gcwq) { struct work_struct *rebind_work = &worker->rebind_work; - unsigned long worker_flags = worker->flags; - /* morph UNBOUND to REBIND atomically */ - worker_flags &= ~WORKER_UNBOUND; - worker_flags |= WORKER_REBIND; - ACCESS_ONCE(worker->flags) = worker_flags; + /* morph UNBOUND to REBIND */ + worker->flags &= ~WORKER_UNBOUND; + worker->flags |= WORKER_REBIND; if (test_and_set_bit(WORK_STRUCT_PENDING_BIT, work_data_bits(rebind_work))) @@ -1460,34 +1449,6 @@ static void rebind_workers(struct global_cwq *gcwq) worker->scheduled.next, work_color_to_flags(WORK_NO_COLOR)); } - - /* - * All idle workers are rebound and waiting for %WORKER_REBIND to - * be cleared inside idle_worker_rebind(). Clear and release. - * Clearing %WORKER_REBIND from this foreign context is safe - * because these workers are still guaranteed to be idle. - * - * We need to make sure all idle workers passed WORKER_REBIND wait - * in idle_worker_rebind() before returning; otherwise, workers can - * get stuck at the wait if hotplug cycle repeats. - */ - idle_rebind.cnt = 1; - INIT_COMPLETION(idle_rebind.done); - - for_each_worker_pool(pool, gcwq) { - list_for_each_entry(worker, &pool->idle_list, entry) { - worker->flags &= ~WORKER_REBIND; - idle_rebind.cnt++; - } - } - - wake_up_all(&gcwq->rebind_hold); - - if (--idle_rebind.cnt) { - spin_unlock_irq(&gcwq->lock); - wait_for_completion(&idle_rebind.done); - spin_lock_irq(&gcwq->lock); - } } static struct worker *alloc_worker(void) @@ -1833,45 +1794,9 @@ static bool manage_workers(struct worker *worker) struct worker_pool *pool = worker->pool; bool ret = false; - if (pool->flags & POOL_MANAGING_WORKERS) + if (!mutex_trylock(&pool->manager_mutex)) return ret; - pool->flags |= POOL_MANAGING_WORKERS; - - /* - * To simplify both worker management and CPU hotplug, hold off - * management while hotplug is in progress. CPU hotplug path can't - * grab %POOL_MANAGING_WORKERS to achieve this because that can - * lead to idle worker depletion (all become busy thinking someone - * else is managing) which in turn can result in deadlock under - * extreme circumstances. Use @pool->manager_mutex to synchronize - * manager against CPU hotplug. - * - * manager_mutex would always be free unless CPU hotplug is in - * progress. trylock first without dropping @gcwq->lock. - */ - if (unlikely(!mutex_trylock(&pool->manager_mutex))) { - spin_unlock_irq(&pool->gcwq->lock); - mutex_lock(&pool->manager_mutex); - /* - * CPU hotplug could have happened while we were waiting - * for manager_mutex. Hotplug itself can't handle us - * because manager isn't either on idle or busy list, and - * @gcwq's state and ours could have deviated. - * - * As hotplug is now excluded via manager_mutex, we can - * simply try to bind. It will succeed or fail depending - * on @gcwq's current state. Try it and adjust - * %WORKER_UNBOUND accordingly. - */ - if (worker_maybe_bind_and_lock(worker)) - worker->flags &= ~WORKER_UNBOUND; - else - worker->flags |= WORKER_UNBOUND; - - ret = true; - } - pool->flags &= ~POOL_MANAGE_WORKERS; /* @@ -1881,7 +1806,6 @@ static bool manage_workers(struct worker *worker) ret |= maybe_destroy_workers(pool); ret |= maybe_create_worker(pool); - pool->flags &= ~POOL_MANAGING_WORKERS; mutex_unlock(&pool->manager_mutex); return ret; } @@ -3576,17 +3500,18 @@ static int __devinit workqueue_cpu_down_callback(struct notifier_block *nfb, #ifdef CONFIG_SMP struct work_for_cpu { - struct work_struct work; + struct completion completion; long (*fn)(void *); void *arg; long ret; }; -static void work_for_cpu_fn(struct work_struct *work) +static int do_work_for_cpu(void *_wfc) { - struct work_for_cpu *wfc = container_of(work, struct work_for_cpu, work); - + struct work_for_cpu *wfc = _wfc; wfc->ret = wfc->fn(wfc->arg); + complete(&wfc->completion); + return 0; } /** @@ -3601,11 +3526,19 @@ static void work_for_cpu_fn(struct work_struct *work) */ long work_on_cpu(unsigned int cpu, long (*fn)(void *), void *arg) { - struct work_for_cpu wfc = { .fn = fn, .arg = arg }; + struct task_struct *sub_thread; + struct work_for_cpu wfc = { + .completion = COMPLETION_INITIALIZER_ONSTACK(wfc.completion), + .fn = fn, + .arg = arg, + }; - INIT_WORK_ONSTACK(&wfc.work, work_for_cpu_fn); - schedule_work_on(cpu, &wfc.work); - flush_work(&wfc.work); + sub_thread = kthread_create(do_work_for_cpu, &wfc, "work_for_cpu"); + if (IS_ERR(sub_thread)) + return PTR_ERR(sub_thread); + kthread_bind(sub_thread, cpu); + wake_up_process(sub_thread); + wait_for_completion(&wfc.completion); return wfc.ret; } EXPORT_SYMBOL_GPL(work_on_cpu); diff --git a/trunk/lib/Kconfig.debug b/trunk/lib/Kconfig.debug index 35c4565ee8fa..2403a63b5da5 100644 --- a/trunk/lib/Kconfig.debug +++ b/trunk/lib/Kconfig.debug @@ -452,8 +452,7 @@ config SLUB_STATS config DEBUG_KMEMLEAK bool "Kernel memory leak detector" depends on DEBUG_KERNEL && EXPERIMENTAL && \ - (X86 || ARM || PPC || MIPS || S390 || SPARC64 || SUPERH || \ - MICROBLAZE || TILE || ARM64) + (X86 || ARM || PPC || MIPS || S390 || SPARC64 || SUPERH || MICROBLAZE || TILE) select DEBUG_FS select STACKTRACE if STACKTRACE_SUPPORT @@ -630,20 +629,6 @@ config PROVE_RCU_REPEATEDLY Say N if you are unsure. -config PROVE_RCU_DELAY - bool "RCU debugging: preemptible RCU race provocation" - depends on DEBUG_KERNEL && PREEMPT_RCU - default n - help - There is a class of races that involve an unlikely preemption - of __rcu_read_unlock() just after ->rcu_read_lock_nesting has - been set to INT_MIN. This feature inserts a delay at that - point to increase the probability of these races. - - Say Y to increase probability of preemption of __rcu_read_unlock(). - - Say N if you are unsure. - config SPARSE_RCU_POINTER bool "RCU debugging: sparse-based checks for pointer usage" default n @@ -754,8 +739,7 @@ config DEBUG_BUGVERBOSE bool "Verbose BUG() reporting (adds 70K)" if DEBUG_KERNEL && EXPERT depends on BUG depends on ARM || AVR32 || M32R || M68K || SPARC32 || SPARC64 || \ - FRV || SUPERH || GENERIC_BUG || BLACKFIN || MN10300 || \ - TILE || ARM64 + FRV || SUPERH || GENERIC_BUG || BLACKFIN || MN10300 || TILE default y help Say Y here to make BUG() panics output the file name and line number diff --git a/trunk/lib/digsig.c b/trunk/lib/digsig.c index 8c0e62975c88..286d558033e2 100644 --- a/trunk/lib/digsig.c +++ b/trunk/lib/digsig.c @@ -163,11 +163,9 @@ static int digsig_verify_rsa(struct key *key, memcpy(out1 + head, p, l); err = pkcs_1_v1_5_decode_emsa(out1, len, mblen, out2, &len); - if (err) - goto err; - if (len != hlen || memcmp(out2, h, hlen)) - err = -EINVAL; + if (!err && len == hlen) + err = memcmp(out2, h, hlen); err: mpi_free(in); diff --git a/trunk/lib/dynamic_debug.c b/trunk/lib/dynamic_debug.c index e7f7d993357a..7ca29a0a3019 100644 --- a/trunk/lib/dynamic_debug.c +++ b/trunk/lib/dynamic_debug.c @@ -521,25 +521,25 @@ static char *dynamic_emit_prefix(const struct _ddebug *desc, char *buf) int pos_after_tid; int pos = 0; - *buf = '\0'; - + pos += snprintf(buf + pos, remaining(pos), "%s", KERN_DEBUG); if (desc->flags & _DPRINTK_FLAGS_INCL_TID) { if (in_interrupt()) - pos += snprintf(buf + pos, remaining(pos), " "); + pos += snprintf(buf + pos, remaining(pos), "%s ", + ""); else pos += snprintf(buf + pos, remaining(pos), "[%d] ", - task_pid_vnr(current)); + task_pid_vnr(current)); } pos_after_tid = pos; if (desc->flags & _DPRINTK_FLAGS_INCL_MODNAME) pos += snprintf(buf + pos, remaining(pos), "%s:", - desc->modname); + desc->modname); if (desc->flags & _DPRINTK_FLAGS_INCL_FUNCNAME) pos += snprintf(buf + pos, remaining(pos), "%s:", - desc->function); + desc->function); if (desc->flags & _DPRINTK_FLAGS_INCL_LINENO) pos += snprintf(buf + pos, remaining(pos), "%d:", - desc->lineno); + desc->lineno); if (pos - pos_after_tid) pos += snprintf(buf + pos, remaining(pos), " "); if (pos >= PREFIX_SIZE) @@ -559,13 +559,9 @@ int __dynamic_pr_debug(struct _ddebug *descriptor, const char *fmt, ...) BUG_ON(!fmt); va_start(args, fmt); - vaf.fmt = fmt; vaf.va = &args; - - res = printk(KERN_DEBUG "%s%pV", - dynamic_emit_prefix(descriptor, buf), &vaf); - + res = printk("%s%pV", dynamic_emit_prefix(descriptor, buf), &vaf); va_end(args); return res; @@ -578,26 +574,15 @@ int __dynamic_dev_dbg(struct _ddebug *descriptor, struct va_format vaf; va_list args; int res; + char buf[PREFIX_SIZE]; BUG_ON(!descriptor); BUG_ON(!fmt); va_start(args, fmt); - vaf.fmt = fmt; vaf.va = &args; - - if (!dev) { - res = printk(KERN_DEBUG "(NULL device *): %pV", &vaf); - } else { - char buf[PREFIX_SIZE]; - - res = dev_printk_emit(7, dev, "%s%s %s: %pV", - dynamic_emit_prefix(descriptor, buf), - dev_driver_string(dev), dev_name(dev), - &vaf); - } - + res = __dev_printk(dynamic_emit_prefix(descriptor, buf), dev, &vaf); va_end(args); return res; @@ -607,35 +592,20 @@ EXPORT_SYMBOL(__dynamic_dev_dbg); #ifdef CONFIG_NET int __dynamic_netdev_dbg(struct _ddebug *descriptor, - const struct net_device *dev, const char *fmt, ...) + const struct net_device *dev, const char *fmt, ...) { struct va_format vaf; va_list args; int res; + char buf[PREFIX_SIZE]; BUG_ON(!descriptor); BUG_ON(!fmt); va_start(args, fmt); - vaf.fmt = fmt; vaf.va = &args; - - if (dev && dev->dev.parent) { - char buf[PREFIX_SIZE]; - - res = dev_printk_emit(7, dev->dev.parent, - "%s%s %s %s: %pV", - dynamic_emit_prefix(descriptor, buf), - dev_driver_string(dev->dev.parent), - dev_name(dev->dev.parent), - netdev_name(dev), &vaf); - } else if (dev) { - res = printk(KERN_DEBUG "%s: %pV", netdev_name(dev), &vaf); - } else { - res = printk(KERN_DEBUG "(NULL net_device): %pV", &vaf); - } - + res = __netdev_printk(dynamic_emit_prefix(descriptor, buf), dev, &vaf); va_end(args); return res; diff --git a/trunk/lib/flex_proportions.c b/trunk/lib/flex_proportions.c index ebf3bac460b0..c785554f9523 100644 --- a/trunk/lib/flex_proportions.c +++ b/trunk/lib/flex_proportions.c @@ -62,7 +62,7 @@ void fprop_global_destroy(struct fprop_global *p) */ bool fprop_new_period(struct fprop_global *p, int periods) { - s64 events; + u64 events; unsigned long flags; local_irq_save(flags); diff --git a/trunk/mm/backing-dev.c b/trunk/mm/backing-dev.c index b41823cc05e6..6b4718e2ee34 100644 --- a/trunk/mm/backing-dev.c +++ b/trunk/mm/backing-dev.c @@ -39,6 +39,12 @@ DEFINE_SPINLOCK(bdi_lock); LIST_HEAD(bdi_list); LIST_HEAD(bdi_pending_list); +static struct task_struct *sync_supers_tsk; +static struct timer_list sync_supers_timer; + +static int bdi_sync_supers(void *); +static void sync_supers_timer_fn(unsigned long); + void bdi_lock_two(struct bdi_writeback *wb1, struct bdi_writeback *wb2) { if (wb1 < wb2) { @@ -244,6 +250,12 @@ static int __init default_bdi_init(void) { int err; + sync_supers_tsk = kthread_run(bdi_sync_supers, NULL, "sync_supers"); + BUG_ON(IS_ERR(sync_supers_tsk)); + + setup_timer(&sync_supers_timer, sync_supers_timer_fn, 0); + bdi_arm_supers_timer(); + err = bdi_init(&default_backing_dev_info); if (!err) bdi_register(&default_backing_dev_info, NULL, "default"); @@ -258,6 +270,46 @@ int bdi_has_dirty_io(struct backing_dev_info *bdi) return wb_has_dirty_io(&bdi->wb); } +/* + * kupdated() used to do this. We cannot do it from the bdi_forker_thread() + * or we risk deadlocking on ->s_umount. The longer term solution would be + * to implement sync_supers_bdi() or similar and simply do it from the + * bdi writeback thread individually. + */ +static int bdi_sync_supers(void *unused) +{ + set_user_nice(current, 0); + + while (!kthread_should_stop()) { + set_current_state(TASK_INTERRUPTIBLE); + schedule(); + + /* + * Do this periodically, like kupdated() did before. + */ + sync_supers(); + } + + return 0; +} + +void bdi_arm_supers_timer(void) +{ + unsigned long next; + + if (!dirty_writeback_interval) + return; + + next = msecs_to_jiffies(dirty_writeback_interval * 10) + jiffies; + mod_timer(&sync_supers_timer, round_jiffies_up(next)); +} + +static void sync_supers_timer_fn(unsigned long unused) +{ + wake_up_process(sync_supers_tsk); + bdi_arm_supers_timer(); +} + static void wakeup_timer_fn(unsigned long data) { struct backing_dev_info *bdi = (struct backing_dev_info *)data; diff --git a/trunk/mm/bootmem.c b/trunk/mm/bootmem.c index f468185b3b28..bcb63ac48cc5 100644 --- a/trunk/mm/bootmem.c +++ b/trunk/mm/bootmem.c @@ -419,7 +419,7 @@ int __init reserve_bootmem_node(pg_data_t *pgdat, unsigned long physaddr, } /** - * reserve_bootmem - mark a page range as reserved + * reserve_bootmem - mark a page range as usable * @addr: starting address of the range * @size: size of the range in bytes * @flags: reservation flags (see linux/bootmem.h) diff --git a/trunk/mm/compaction.c b/trunk/mm/compaction.c index 7fcd3a52e68d..e78cb9688421 100644 --- a/trunk/mm/compaction.c +++ b/trunk/mm/compaction.c @@ -50,47 +50,6 @@ static inline bool migrate_async_suitable(int migratetype) return is_migrate_cma(migratetype) || migratetype == MIGRATE_MOVABLE; } -/* - * Compaction requires the taking of some coarse locks that are potentially - * very heavily contended. Check if the process needs to be scheduled or - * if the lock is contended. For async compaction, back out in the event - * if contention is severe. For sync compaction, schedule. - * - * Returns true if the lock is held. - * Returns false if the lock is released and compaction should abort - */ -static bool compact_checklock_irqsave(spinlock_t *lock, unsigned long *flags, - bool locked, struct compact_control *cc) -{ - if (need_resched() || spin_is_contended(lock)) { - if (locked) { - spin_unlock_irqrestore(lock, *flags); - locked = false; - } - - /* async aborts if taking too long or contended */ - if (!cc->sync) { - if (cc->contended) - *cc->contended = true; - return false; - } - - cond_resched(); - if (fatal_signal_pending(current)) - return false; - } - - if (!locked) - spin_lock_irqsave(lock, *flags); - return true; -} - -static inline bool compact_trylock_irqsave(spinlock_t *lock, - unsigned long *flags, struct compact_control *cc) -{ - return compact_checklock_irqsave(lock, flags, false, cc); -} - /* * Isolate free pages onto a private freelist. Caller must hold zone->lock. * If @strict is true, will abort returning 0 on any invalid PFNs or non-free @@ -214,7 +173,7 @@ isolate_freepages_range(unsigned long start_pfn, unsigned long end_pfn) } /* Update the number of anon and file isolated pages in the zone */ -static void acct_isolated(struct zone *zone, bool locked, struct compact_control *cc) +static void acct_isolated(struct zone *zone, struct compact_control *cc) { struct page *page; unsigned int count[2] = { 0, }; @@ -222,14 +181,8 @@ static void acct_isolated(struct zone *zone, bool locked, struct compact_control list_for_each_entry(page, &cc->migratepages, lru) count[!!page_is_file_cache(page)]++; - /* If locked we can use the interrupt unsafe versions */ - if (locked) { - __mod_zone_page_state(zone, NR_ISOLATED_ANON, count[0]); - __mod_zone_page_state(zone, NR_ISOLATED_FILE, count[1]); - } else { - mod_zone_page_state(zone, NR_ISOLATED_ANON, count[0]); - mod_zone_page_state(zone, NR_ISOLATED_FILE, count[1]); - } + __mod_zone_page_state(zone, NR_ISOLATED_ANON, count[0]); + __mod_zone_page_state(zone, NR_ISOLATED_FILE, count[1]); } /* Similar to reclaim, but different enough that they don't share logic */ @@ -275,8 +228,6 @@ isolate_migratepages_range(struct zone *zone, struct compact_control *cc, struct list_head *migratelist = &cc->migratepages; isolate_mode_t mode = 0; struct lruvec *lruvec; - unsigned long flags; - bool locked; /* * Ensure that there are not too many pages isolated from the LRU @@ -296,22 +247,25 @@ isolate_migratepages_range(struct zone *zone, struct compact_control *cc, /* Time to isolate some pages for migration */ cond_resched(); - spin_lock_irqsave(&zone->lru_lock, flags); - locked = true; + spin_lock_irq(&zone->lru_lock); for (; low_pfn < end_pfn; low_pfn++) { struct page *page; + bool locked = true; /* give a chance to irqs before checking need_resched() */ if (!((low_pfn+1) % SWAP_CLUSTER_MAX)) { - spin_unlock_irqrestore(&zone->lru_lock, flags); + spin_unlock_irq(&zone->lru_lock); locked = false; } - - /* Check if it is ok to still hold the lock */ - locked = compact_checklock_irqsave(&zone->lru_lock, &flags, - locked, cc); - if (!locked) - break; + if (need_resched() || spin_is_contended(&zone->lru_lock)) { + if (locked) + spin_unlock_irq(&zone->lru_lock); + cond_resched(); + spin_lock_irq(&zone->lru_lock); + if (fatal_signal_pending(current)) + break; + } else if (!locked) + spin_lock_irq(&zone->lru_lock); /* * migrate_pfn does not necessarily start aligned to a @@ -395,10 +349,9 @@ isolate_migratepages_range(struct zone *zone, struct compact_control *cc, } } - acct_isolated(zone, locked, cc); + acct_isolated(zone, cc); - if (locked) - spin_unlock_irqrestore(&zone->lru_lock, flags); + spin_unlock_irq(&zone->lru_lock); trace_mm_compaction_isolate_migratepages(nr_scanned, nr_isolated); @@ -430,20 +383,6 @@ static bool suitable_migration_target(struct page *page) return false; } -/* - * Returns the start pfn of the last page block in a zone. This is the starting - * point for full compaction of a zone. Compaction searches for free pages from - * the end of each zone, while isolate_freepages_block scans forward inside each - * page block. - */ -static unsigned long start_free_pfn(struct zone *zone) -{ - unsigned long free_pfn; - free_pfn = zone->zone_start_pfn + zone->spanned_pages; - free_pfn &= ~(pageblock_nr_pages-1); - return free_pfn; -} - /* * Based on information in the current compact_control, find blocks * suitable for isolating free pages from and then isolate them. @@ -483,6 +422,17 @@ static void isolate_freepages(struct zone *zone, pfn -= pageblock_nr_pages) { unsigned long isolated; + /* + * Skip ahead if another thread is compacting in the area + * simultaneously. If we wrapped around, we can only skip + * ahead if zone->compact_cached_free_pfn also wrapped to + * above our starting point. + */ + if (cc->order > 0 && (!cc->wrapped || + zone->compact_cached_free_pfn > + cc->start_free_pfn)) + pfn = min(pfn, zone->compact_cached_free_pfn); + if (!pfn_valid(pfn)) continue; @@ -508,16 +458,7 @@ static void isolate_freepages(struct zone *zone, * are disabled */ isolated = 0; - - /* - * The zone lock must be held to isolate freepages. This - * unfortunately this is a very coarse lock and can be - * heavily contended if there are parallel allocations - * or parallel compactions. For async compaction do not - * spin on the lock - */ - if (!compact_trylock_irqsave(&zone->lock, &flags, cc)) - break; + spin_lock_irqsave(&zone->lock, flags); if (suitable_migration_target(page)) { end_pfn = min(pfn + pageblock_nr_pages, zone_end_pfn); isolated = isolate_freepages_block(pfn, end_pfn, @@ -533,15 +474,7 @@ static void isolate_freepages(struct zone *zone, */ if (isolated) { high_pfn = max(high_pfn, pfn); - - /* - * If the free scanner has wrapped, update - * compact_cached_free_pfn to point to the highest - * pageblock with free pages. This reduces excessive - * scanning of full pageblocks near the end of the - * zone - */ - if (cc->order > 0 && cc->wrapped) + if (cc->order > 0) zone->compact_cached_free_pfn = high_pfn; } } @@ -551,11 +484,6 @@ static void isolate_freepages(struct zone *zone, cc->free_pfn = high_pfn; cc->nr_freepages = nr_freepages; - - /* If compact_cached_free_pfn is reset then set it now */ - if (cc->order > 0 && !cc->wrapped && - zone->compact_cached_free_pfn == start_free_pfn(zone)) - zone->compact_cached_free_pfn = high_pfn; } /* @@ -642,6 +570,20 @@ static isolate_migrate_t isolate_migratepages(struct zone *zone, return ISOLATE_SUCCESS; } +/* + * Returns the start pfn of the last page block in a zone. This is the starting + * point for full compaction of a zone. Compaction searches for free pages from + * the end of each zone, while isolate_freepages_block scans forward inside each + * page block. + */ +static unsigned long start_free_pfn(struct zone *zone) +{ + unsigned long free_pfn; + free_pfn = zone->zone_start_pfn + zone->spanned_pages; + free_pfn &= ~(pageblock_nr_pages-1); + return free_pfn; +} + static int compact_finished(struct zone *zone, struct compact_control *cc) { @@ -829,7 +771,7 @@ static int compact_zone(struct zone *zone, struct compact_control *cc) static unsigned long compact_zone_order(struct zone *zone, int order, gfp_t gfp_mask, - bool sync, bool *contended) + bool sync) { struct compact_control cc = { .nr_freepages = 0, @@ -838,7 +780,6 @@ static unsigned long compact_zone_order(struct zone *zone, .migratetype = allocflags_to_migratetype(gfp_mask), .zone = zone, .sync = sync, - .contended = contended, }; INIT_LIST_HEAD(&cc.freepages); INIT_LIST_HEAD(&cc.migratepages); @@ -860,7 +801,7 @@ int sysctl_extfrag_threshold = 500; */ unsigned long try_to_compact_pages(struct zonelist *zonelist, int order, gfp_t gfp_mask, nodemask_t *nodemask, - bool sync, bool *contended) + bool sync) { enum zone_type high_zoneidx = gfp_zone(gfp_mask); int may_enter_fs = gfp_mask & __GFP_FS; @@ -884,8 +825,7 @@ unsigned long try_to_compact_pages(struct zonelist *zonelist, nodemask) { int status; - status = compact_zone_order(zone, order, gfp_mask, sync, - contended); + status = compact_zone_order(zone, order, gfp_mask, sync); rc = max(status, rc); /* If a normal allocation would succeed, stop compacting */ @@ -921,7 +861,7 @@ static int __compact_pgdat(pg_data_t *pgdat, struct compact_control *cc) if (cc->order > 0) { int ok = zone_watermark_ok(zone, cc->order, low_wmark_pages(zone), 0, 0); - if (ok && cc->order >= zone->compact_order_failed) + if (ok && cc->order > zone->compact_order_failed) zone->compact_order_failed = cc->order + 1; /* Currently async compaction is never deferred. */ else if (!ok && cc->sync) diff --git a/trunk/mm/filemap.c b/trunk/mm/filemap.c index 384344575c37..fa5ca304148e 100644 --- a/trunk/mm/filemap.c +++ b/trunk/mm/filemap.c @@ -1412,8 +1412,12 @@ generic_file_aio_read(struct kiocb *iocb, const struct iovec *iov, retval = filemap_write_and_wait_range(mapping, pos, pos + iov_length(iov, nr_segs) - 1); if (!retval) { + struct blk_plug plug; + + blk_start_plug(&plug); retval = mapping->a_ops->direct_IO(READ, iocb, iov, pos, nr_segs); + blk_finish_plug(&plug); } if (retval > 0) { *ppos = pos + retval; @@ -2523,12 +2527,14 @@ ssize_t generic_file_aio_write(struct kiocb *iocb, const struct iovec *iov, { struct file *file = iocb->ki_filp; struct inode *inode = file->f_mapping->host; + struct blk_plug plug; ssize_t ret; BUG_ON(iocb->ki_pos != pos); sb_start_write(inode->i_sb); mutex_lock(&inode->i_mutex); + blk_start_plug(&plug); ret = __generic_file_aio_write(iocb, iov, nr_segs, &iocb->ki_pos); mutex_unlock(&inode->i_mutex); @@ -2539,6 +2545,7 @@ ssize_t generic_file_aio_write(struct kiocb *iocb, const struct iovec *iov, if (err < 0 && ret > 0) ret = err; } + blk_finish_plug(&plug); sb_end_write(inode->i_sb); return ret; } diff --git a/trunk/mm/huge_memory.c b/trunk/mm/huge_memory.c index 141dbb695097..57c4b9309015 100644 --- a/trunk/mm/huge_memory.c +++ b/trunk/mm/huge_memory.c @@ -1811,6 +1811,7 @@ static void __collapse_huge_page_copy(pte_t *pte, struct page *page, src_page = pte_page(pteval); copy_user_highpage(page, src_page, address, vma); VM_BUG_ON(page_mapcount(src_page) != 1); + VM_BUG_ON(page_count(src_page) != 2); release_pte_page(src_page); /* * ptl mostly unnecessary, but preempt has to diff --git a/trunk/mm/internal.h b/trunk/mm/internal.h index b8c91b342e24..3314f79d775a 100644 --- a/trunk/mm/internal.h +++ b/trunk/mm/internal.h @@ -130,7 +130,6 @@ struct compact_control { int order; /* order a direct compactor needs */ int migratetype; /* MOVABLE, RECLAIMABLE etc */ struct zone *zone; - bool *contended; /* True if a lock was contended */ }; unsigned long diff --git a/trunk/mm/kmemleak.c b/trunk/mm/kmemleak.c index 0de83b4541e9..45eb6217bf38 100644 --- a/trunk/mm/kmemleak.c +++ b/trunk/mm/kmemleak.c @@ -1483,11 +1483,13 @@ static void *kmemleak_seq_next(struct seq_file *seq, void *v, loff_t *pos) { struct kmemleak_object *prev_obj = v; struct kmemleak_object *next_obj = NULL; - struct kmemleak_object *obj = prev_obj; + struct list_head *n = &prev_obj->object_list; ++(*pos); - list_for_each_entry_continue_rcu(obj, &object_list, object_list) { + list_for_each_continue_rcu(n, &object_list) { + struct kmemleak_object *obj = + list_entry(n, struct kmemleak_object, object_list); if (get_object(obj)) { next_obj = obj; break; diff --git a/trunk/mm/memblock.c b/trunk/mm/memblock.c index 82aa349d2f7a..4d9393c7edc9 100644 --- a/trunk/mm/memblock.c +++ b/trunk/mm/memblock.c @@ -246,7 +246,7 @@ static int __init_memblock memblock_double_array(struct memblock_type *type, min(new_area_start, memblock.current_limit), new_alloc_size, PAGE_SIZE); - new_array = addr ? __va(addr) : NULL; + new_array = addr ? __va(addr) : 0; } if (!addr) { pr_err("memblock: Failed to double %s array from %ld to %ld entries !\n", diff --git a/trunk/mm/memory_hotplug.c b/trunk/mm/memory_hotplug.c index 6a5b90d0cfd7..3ad25f9d1fc1 100644 --- a/trunk/mm/memory_hotplug.c +++ b/trunk/mm/memory_hotplug.c @@ -126,6 +126,9 @@ static void register_page_bootmem_info_section(unsigned long start_pfn) struct mem_section *ms; struct page *page, *memmap; + if (!pfn_valid(start_pfn)) + return; + section_nr = pfn_to_section_nr(start_pfn); ms = __nr_to_section(section_nr); @@ -184,16 +187,9 @@ void register_page_bootmem_info_node(struct pglist_data *pgdat) end_pfn = pfn + pgdat->node_spanned_pages; /* register_section info */ - for (; pfn < end_pfn; pfn += PAGES_PER_SECTION) { - /* - * Some platforms can assign the same pfn to multiple nodes - on - * node0 as well as nodeN. To avoid registering a pfn against - * multiple nodes we check that this pfn does not already - * reside in some other node. - */ - if (pfn_valid(pfn) && (pfn_to_nid(pfn) == node)) - register_page_bootmem_info_section(pfn); - } + for (; pfn < end_pfn; pfn += PAGES_PER_SECTION) + register_page_bootmem_info_section(pfn); + } #endif /* !CONFIG_SPARSEMEM_VMEMMAP */ diff --git a/trunk/mm/mempolicy.c b/trunk/mm/mempolicy.c index 4ada3be6e252..bd92431d4c49 100644 --- a/trunk/mm/mempolicy.c +++ b/trunk/mm/mempolicy.c @@ -2562,7 +2562,7 @@ int mpol_to_str(char *buffer, int maxlen, struct mempolicy *pol, int no_context) break; default: - return -EINVAL; + BUG(); } l = strlen(policy_modes[mode]); diff --git a/trunk/mm/mmap.c b/trunk/mm/mmap.c index ae18a48e7e4e..e3e86914f11a 100644 --- a/trunk/mm/mmap.c +++ b/trunk/mm/mmap.c @@ -1356,8 +1356,9 @@ unsigned long mmap_region(struct file *file, unsigned long addr, } else if ((flags & MAP_POPULATE) && !(flags & MAP_NONBLOCK)) make_pages_present(addr, addr + len); - if (file) - uprobe_mmap(vma); + if (file && uprobe_mmap(vma)) + /* matching probes but cannot insert */ + goto unmap_and_free_vma; return addr; @@ -2308,7 +2309,7 @@ void exit_mmap(struct mm_struct *mm) } vm_unacct_memory(nr_accounted); - WARN_ON(mm->nr_ptes > (FIRST_USER_ADDRESS+PMD_SIZE-1)>>PMD_SHIFT); + BUG_ON(mm->nr_ptes > (FIRST_USER_ADDRESS+PMD_SIZE-1)>>PMD_SHIFT); } /* Insert vm structure into process list sorted by address diff --git a/trunk/mm/page-writeback.c b/trunk/mm/page-writeback.c index 5ad5ce23c1e0..e5363f34e025 100644 --- a/trunk/mm/page-writeback.c +++ b/trunk/mm/page-writeback.c @@ -1532,6 +1532,7 @@ int dirty_writeback_centisecs_handler(ctl_table *table, int write, void __user *buffer, size_t *length, loff_t *ppos) { proc_dointvec(table, write, buffer, length, ppos); + bdi_arm_supers_timer(); return 0; } diff --git a/trunk/mm/page_alloc.c b/trunk/mm/page_alloc.c index c13ea7538891..009ac285fea7 100644 --- a/trunk/mm/page_alloc.c +++ b/trunk/mm/page_alloc.c @@ -584,7 +584,7 @@ static inline void __free_one_page(struct page *page, combined_idx = buddy_idx & page_idx; higher_page = page + (combined_idx - page_idx); buddy_idx = __find_buddy_index(combined_idx, order + 1); - higher_buddy = higher_page + (buddy_idx - combined_idx); + higher_buddy = page + (buddy_idx - combined_idx); if (page_is_buddy(higher_page, higher_buddy, order + 1)) { list_add_tail(&page->lru, &zone->free_area[order].free_list[migratetype]); @@ -1928,17 +1928,6 @@ get_page_from_freelist(gfp_t gfp_mask, nodemask_t *nodemask, unsigned int order, zlc_active = 0; goto zonelist_scan; } - - if (page) - /* - * page->pfmemalloc is set when ALLOC_NO_WATERMARKS was - * necessary to allocate the page. The expectation is - * that the caller is taking steps that will free more - * memory. The caller should avoid the page being used - * for !PFMEMALLOC purposes. - */ - page->pfmemalloc = !!(alloc_flags & ALLOC_NO_WATERMARKS); - return page; } @@ -2102,7 +2091,7 @@ __alloc_pages_direct_compact(gfp_t gfp_mask, unsigned int order, struct zonelist *zonelist, enum zone_type high_zoneidx, nodemask_t *nodemask, int alloc_flags, struct zone *preferred_zone, int migratetype, bool sync_migration, - bool *contended_compaction, bool *deferred_compaction, + bool *deferred_compaction, unsigned long *did_some_progress) { struct page *page; @@ -2117,8 +2106,7 @@ __alloc_pages_direct_compact(gfp_t gfp_mask, unsigned int order, current->flags |= PF_MEMALLOC; *did_some_progress = try_to_compact_pages(zonelist, order, gfp_mask, - nodemask, sync_migration, - contended_compaction); + nodemask, sync_migration); current->flags &= ~PF_MEMALLOC; if (*did_some_progress != COMPACT_SKIPPED) { @@ -2164,7 +2152,7 @@ __alloc_pages_direct_compact(gfp_t gfp_mask, unsigned int order, struct zonelist *zonelist, enum zone_type high_zoneidx, nodemask_t *nodemask, int alloc_flags, struct zone *preferred_zone, int migratetype, bool sync_migration, - bool *contended_compaction, bool *deferred_compaction, + bool *deferred_compaction, unsigned long *did_some_progress) { return NULL; @@ -2337,7 +2325,6 @@ __alloc_pages_slowpath(gfp_t gfp_mask, unsigned int order, unsigned long did_some_progress; bool sync_migration = false; bool deferred_compaction = false; - bool contended_compaction = false; /* * In the slowpath, we sanity check order to avoid ever trying to @@ -2402,6 +2389,14 @@ __alloc_pages_slowpath(gfp_t gfp_mask, unsigned int order, zonelist, high_zoneidx, nodemask, preferred_zone, migratetype); if (page) { + /* + * page->pfmemalloc is set when ALLOC_NO_WATERMARKS was + * necessary to allocate the page. The expectation is + * that the caller is taking steps that will free more + * memory. The caller should avoid the page being used + * for !PFMEMALLOC purposes. + */ + page->pfmemalloc = true; goto got_pg; } } @@ -2427,7 +2422,6 @@ __alloc_pages_slowpath(gfp_t gfp_mask, unsigned int order, nodemask, alloc_flags, preferred_zone, migratetype, sync_migration, - &contended_compaction, &deferred_compaction, &did_some_progress); if (page) @@ -2437,11 +2431,10 @@ __alloc_pages_slowpath(gfp_t gfp_mask, unsigned int order, /* * If compaction is deferred for high-order allocations, it is because * sync compaction recently failed. In this is the case and the caller - * requested a movable allocation that does not heavily disrupt the - * system then fail the allocation instead of entering direct reclaim. + * has requested the system not be heavily disrupted, fail the + * allocation now instead of entering direct reclaim */ - if ((deferred_compaction || contended_compaction) && - (gfp_mask & __GFP_NO_KSWAPD)) + if (deferred_compaction && (gfp_mask & __GFP_NO_KSWAPD)) goto nopage; /* Try direct reclaim and then allocating */ @@ -2512,7 +2505,6 @@ __alloc_pages_slowpath(gfp_t gfp_mask, unsigned int order, nodemask, alloc_flags, preferred_zone, migratetype, sync_migration, - &contended_compaction, &deferred_compaction, &did_some_progress); if (page) @@ -2577,6 +2569,8 @@ __alloc_pages_nodemask(gfp_t gfp_mask, unsigned int order, page = __alloc_pages_slowpath(gfp_mask, order, zonelist, high_zoneidx, nodemask, preferred_zone, migratetype); + else + page->pfmemalloc = false; trace_mm_page_alloc(page, order, gfp_mask, migratetype); diff --git a/trunk/mm/slab.c b/trunk/mm/slab.c index c6854759bcf1..f8b0d539b482 100644 --- a/trunk/mm/slab.c +++ b/trunk/mm/slab.c @@ -983,7 +983,7 @@ static void *__ac_get_obj(struct kmem_cache *cachep, struct array_cache *ac, } /* The caller cannot use PFMEMALLOC objects, find another one */ - for (i = 0; i < ac->avail; i++) { + for (i = 1; i < ac->avail; i++) { /* If a !PFMEMALLOC object is found, swap them */ if (!is_obj_pfmemalloc(ac->entry[i])) { objp = ac->entry[i]; @@ -1000,7 +1000,7 @@ static void *__ac_get_obj(struct kmem_cache *cachep, struct array_cache *ac, l3 = cachep->nodelists[numa_mem_id()]; if (!list_empty(&l3->slabs_free) && force_refill) { struct slab *slabp = virt_to_slab(objp); - ClearPageSlabPfmemalloc(virt_to_head_page(slabp->s_mem)); + ClearPageSlabPfmemalloc(virt_to_page(slabp->s_mem)); clear_obj_pfmemalloc(&objp); recheck_pfmemalloc_active(cachep, ac); return objp; @@ -1032,7 +1032,7 @@ static void *__ac_put_obj(struct kmem_cache *cachep, struct array_cache *ac, { if (unlikely(pfmemalloc_active)) { /* Some pfmemalloc slabs exist, check if this is one */ - struct page *page = virt_to_head_page(objp); + struct page *page = virt_to_page(objp); if (PageSlabPfmemalloc(page)) set_obj_pfmemalloc(&objp); } @@ -3260,7 +3260,6 @@ static void *cache_alloc_refill(struct kmem_cache *cachep, gfp_t flags, /* cache_grow can reenable interrupts, then ac could change. */ ac = cpu_cache_get(cachep); - node = numa_mem_id(); /* no objects in sight? abort */ if (!x && (ac->avail == 0 || force_refill)) diff --git a/trunk/mm/slub.c b/trunk/mm/slub.c index 2fdd96f9e998..8f78e2577031 100644 --- a/trunk/mm/slub.c +++ b/trunk/mm/slub.c @@ -1524,13 +1524,12 @@ static inline void *acquire_slab(struct kmem_cache *s, } static int put_cpu_partial(struct kmem_cache *s, struct page *page, int drain); -static inline bool pfmemalloc_match(struct page *page, gfp_t gfpflags); /* * Try to allocate a partial slab from a specific node. */ -static void *get_partial_node(struct kmem_cache *s, struct kmem_cache_node *n, - struct kmem_cache_cpu *c, gfp_t flags) +static void *get_partial_node(struct kmem_cache *s, + struct kmem_cache_node *n, struct kmem_cache_cpu *c) { struct page *page, *page2; void *object = NULL; @@ -1546,13 +1545,9 @@ static void *get_partial_node(struct kmem_cache *s, struct kmem_cache_node *n, spin_lock(&n->list_lock); list_for_each_entry_safe(page, page2, &n->partial, lru) { - void *t; + void *t = acquire_slab(s, n, page, object == NULL); int available; - if (!pfmemalloc_match(page, flags)) - continue; - - t = acquire_slab(s, n, page, object == NULL); if (!t) break; @@ -1619,7 +1614,7 @@ static void *get_any_partial(struct kmem_cache *s, gfp_t flags, if (n && cpuset_zone_allowed_hardwall(zone, flags) && n->nr_partial > s->min_partial) { - object = get_partial_node(s, n, c, flags); + object = get_partial_node(s, n, c); if (object) { /* * Return the object even if @@ -1648,7 +1643,7 @@ static void *get_partial(struct kmem_cache *s, gfp_t flags, int node, void *object; int searchnode = (node == NUMA_NO_NODE) ? numa_node_id() : node; - object = get_partial_node(s, get_node(s, searchnode), c, flags); + object = get_partial_node(s, get_node(s, searchnode), c); if (object || node != NUMA_NO_NODE) return object; diff --git a/trunk/mm/vmscan.c b/trunk/mm/vmscan.c index 99b434b674c0..8d01243d9560 100644 --- a/trunk/mm/vmscan.c +++ b/trunk/mm/vmscan.c @@ -3102,7 +3102,6 @@ int kswapd_run(int nid) /* failure at boot is fatal */ BUG_ON(system_state == SYSTEM_BOOTING); printk("Failed to start kswapd on node %d\n",nid); - pgdat->kswapd = NULL; ret = -1; } return ret; diff --git a/trunk/net/8021q/vlan_dev.c b/trunk/net/8021q/vlan_dev.c index 402442402af7..73a2a83ee2da 100644 --- a/trunk/net/8021q/vlan_dev.c +++ b/trunk/net/8021q/vlan_dev.c @@ -137,21 +137,9 @@ static int vlan_dev_hard_header(struct sk_buff *skb, struct net_device *dev, return rc; } -static inline netdev_tx_t vlan_netpoll_send_skb(struct vlan_dev_priv *vlan, struct sk_buff *skb) -{ -#ifdef CONFIG_NET_POLL_CONTROLLER - if (vlan->netpoll) - netpoll_send_skb(vlan->netpoll, skb); -#else - BUG(); -#endif - return NETDEV_TX_OK; -} - static netdev_tx_t vlan_dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) { - struct vlan_dev_priv *vlan = vlan_dev_priv(dev); struct vlan_ethhdr *veth = (struct vlan_ethhdr *)(skb->data); unsigned int len; int ret; @@ -162,30 +150,29 @@ static netdev_tx_t vlan_dev_hard_start_xmit(struct sk_buff *skb, * OTHER THINGS LIKE FDDI/TokenRing/802.3 SNAPs... */ if (veth->h_vlan_proto != htons(ETH_P_8021Q) || - vlan->flags & VLAN_FLAG_REORDER_HDR) { + vlan_dev_priv(dev)->flags & VLAN_FLAG_REORDER_HDR) { u16 vlan_tci; - vlan_tci = vlan->vlan_id; + vlan_tci = vlan_dev_priv(dev)->vlan_id; vlan_tci |= vlan_dev_get_egress_qos_mask(dev, skb); skb = __vlan_hwaccel_put_tag(skb, vlan_tci); } - skb->dev = vlan->real_dev; + skb->dev = vlan_dev_priv(dev)->real_dev; len = skb->len; - if (unlikely(netpoll_tx_running(dev))) - return vlan_netpoll_send_skb(vlan, skb); - + if (netpoll_tx_running(dev)) + return skb->dev->netdev_ops->ndo_start_xmit(skb, skb->dev); ret = dev_queue_xmit(skb); if (likely(ret == NET_XMIT_SUCCESS || ret == NET_XMIT_CN)) { struct vlan_pcpu_stats *stats; - stats = this_cpu_ptr(vlan->vlan_pcpu_stats); + stats = this_cpu_ptr(vlan_dev_priv(dev)->vlan_pcpu_stats); u64_stats_update_begin(&stats->syncp); stats->tx_packets++; stats->tx_bytes += len; u64_stats_update_end(&stats->syncp); } else { - this_cpu_inc(vlan->vlan_pcpu_stats->tx_dropped); + this_cpu_inc(vlan_dev_priv(dev)->vlan_pcpu_stats->tx_dropped); } return ret; @@ -682,26 +669,25 @@ static void vlan_dev_poll_controller(struct net_device *dev) return; } -static int vlan_dev_netpoll_setup(struct net_device *dev, struct netpoll_info *npinfo, - gfp_t gfp) +static int vlan_dev_netpoll_setup(struct net_device *dev, struct netpoll_info *npinfo) { - struct vlan_dev_priv *vlan = vlan_dev_priv(dev); - struct net_device *real_dev = vlan->real_dev; + struct vlan_dev_priv *info = vlan_dev_priv(dev); + struct net_device *real_dev = info->real_dev; struct netpoll *netpoll; int err = 0; - netpoll = kzalloc(sizeof(*netpoll), gfp); + netpoll = kzalloc(sizeof(*netpoll), GFP_KERNEL); err = -ENOMEM; if (!netpoll) goto out; - err = __netpoll_setup(netpoll, real_dev, gfp); + err = __netpoll_setup(netpoll, real_dev); if (err) { kfree(netpoll); goto out; } - vlan->netpoll = netpoll; + info->netpoll = netpoll; out: return err; @@ -709,15 +695,19 @@ static int vlan_dev_netpoll_setup(struct net_device *dev, struct netpoll_info *n static void vlan_dev_netpoll_cleanup(struct net_device *dev) { - struct vlan_dev_priv *vlan= vlan_dev_priv(dev); - struct netpoll *netpoll = vlan->netpoll; + struct vlan_dev_priv *info = vlan_dev_priv(dev); + struct netpoll *netpoll = info->netpoll; if (!netpoll) return; - vlan->netpoll = NULL; + info->netpoll = NULL; + + /* Wait for transmitting packets to finish before freeing. */ + synchronize_rcu_bh(); - __netpoll_free_rcu(netpoll); + __netpoll_cleanup(netpoll); + kfree(netpoll); } #endif /* CONFIG_NET_POLL_CONTROLLER */ diff --git a/trunk/net/8021q/vlanproc.c b/trunk/net/8021q/vlanproc.c index 4de77ea5fa37..c718fd3664b6 100644 --- a/trunk/net/8021q/vlanproc.c +++ b/trunk/net/8021q/vlanproc.c @@ -105,7 +105,7 @@ static const struct file_operations vlandev_fops = { }; /* - * Proc filesystem directory entries. + * Proc filesystem derectory entries. */ /* Strings */ diff --git a/trunk/net/atm/common.c b/trunk/net/atm/common.c index 0c0ad930a632..b4b44dbed645 100644 --- a/trunk/net/atm/common.c +++ b/trunk/net/atm/common.c @@ -812,7 +812,6 @@ int vcc_getsockopt(struct socket *sock, int level, int optname, if (!vcc->dev || !test_bit(ATM_VF_ADDR, &vcc->flags)) return -ENOTCONN; - memset(&pvc, 0, sizeof(pvc)); pvc.sap_family = AF_ATMPVC; pvc.sap_addr.itf = vcc->dev->number; pvc.sap_addr.vpi = vcc->vpi; diff --git a/trunk/net/atm/pvc.c b/trunk/net/atm/pvc.c index ae0324021407..3a734919c36c 100644 --- a/trunk/net/atm/pvc.c +++ b/trunk/net/atm/pvc.c @@ -95,7 +95,6 @@ static int pvc_getname(struct socket *sock, struct sockaddr *sockaddr, return -ENOTCONN; *sockaddr_len = sizeof(struct sockaddr_atmpvc); addr = (struct sockaddr_atmpvc *)sockaddr; - memset(addr, 0, sizeof(*addr)); addr->sap_family = AF_ATMPVC; addr->sap_addr.itf = vcc->dev->number; addr->sap_addr.vpi = vcc->vpi; diff --git a/trunk/net/batman-adv/bat_iv_ogm.c b/trunk/net/batman-adv/bat_iv_ogm.c index 469daabd90c7..e877af8bdd1e 100644 --- a/trunk/net/batman-adv/bat_iv_ogm.c +++ b/trunk/net/batman-adv/bat_iv_ogm.c @@ -642,8 +642,7 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv, struct batadv_neigh_node *router = NULL; struct batadv_orig_node *orig_node_tmp; struct hlist_node *node; - int if_num; - uint8_t sum_orig, sum_neigh; + uint8_t bcast_own_sum_orig, bcast_own_sum_neigh; uint8_t *neigh_addr; batadv_dbg(BATADV_DBG_BATMAN, bat_priv, @@ -728,17 +727,17 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv, if (router && (neigh_node->tq_avg == router->tq_avg)) { orig_node_tmp = router->orig_node; spin_lock_bh(&orig_node_tmp->ogm_cnt_lock); - if_num = router->if_incoming->if_num; - sum_orig = orig_node_tmp->bcast_own_sum[if_num]; + bcast_own_sum_orig = + orig_node_tmp->bcast_own_sum[if_incoming->if_num]; spin_unlock_bh(&orig_node_tmp->ogm_cnt_lock); orig_node_tmp = neigh_node->orig_node; spin_lock_bh(&orig_node_tmp->ogm_cnt_lock); - if_num = neigh_node->if_incoming->if_num; - sum_neigh = orig_node_tmp->bcast_own_sum[if_num]; + bcast_own_sum_neigh = + orig_node_tmp->bcast_own_sum[if_incoming->if_num]; spin_unlock_bh(&orig_node_tmp->ogm_cnt_lock); - if (sum_orig >= sum_neigh) + if (bcast_own_sum_orig >= bcast_own_sum_neigh) goto update_tt; } diff --git a/trunk/net/batman-adv/bitarray.h b/trunk/net/batman-adv/bitarray.h index cebaae7e148b..a081ce1c0514 100644 --- a/trunk/net/batman-adv/bitarray.h +++ b/trunk/net/batman-adv/bitarray.h @@ -20,8 +20,8 @@ #ifndef _NET_BATMAN_ADV_BITARRAY_H_ #define _NET_BATMAN_ADV_BITARRAY_H_ -/* Returns 1 if the corresponding bit in the given seq_bits indicates true - * and curr_seqno is within range of last_seqno. Otherwise returns 0. +/* returns true if the corresponding bit in the given seq_bits indicates true + * and curr_seqno is within range of last_seqno */ static inline int batadv_test_bit(const unsigned long *seq_bits, uint32_t last_seqno, uint32_t curr_seqno) @@ -32,7 +32,7 @@ static inline int batadv_test_bit(const unsigned long *seq_bits, if (diff < 0 || diff >= BATADV_TQ_LOCAL_WINDOW_SIZE) return 0; else - return test_bit(diff, seq_bits) != 0; + return test_bit(diff, seq_bits); } /* turn corresponding bit on, so we can remember that we got the packet */ diff --git a/trunk/net/batman-adv/gateway_client.c b/trunk/net/batman-adv/gateway_client.c index fc866f2e4528..b421cc49d2cd 100644 --- a/trunk/net/batman-adv/gateway_client.c +++ b/trunk/net/batman-adv/gateway_client.c @@ -200,11 +200,11 @@ void batadv_gw_election(struct batadv_priv *bat_priv) if (atomic_read(&bat_priv->gw_mode) != BATADV_GW_MODE_CLIENT) goto out; - curr_gw = batadv_gw_get_selected_gw_node(bat_priv); - - if (!batadv_atomic_dec_not_zero(&bat_priv->gw_reselect) && curr_gw) + if (!batadv_atomic_dec_not_zero(&bat_priv->gw_reselect)) goto out; + curr_gw = batadv_gw_get_selected_gw_node(bat_priv); + next_gw = batadv_gw_get_best_gw_node(bat_priv); if (curr_gw == next_gw) diff --git a/trunk/net/batman-adv/soft-interface.c b/trunk/net/batman-adv/soft-interface.c index 21c53577c8d6..109ea2aae96c 100644 --- a/trunk/net/batman-adv/soft-interface.c +++ b/trunk/net/batman-adv/soft-interface.c @@ -100,21 +100,18 @@ static int batadv_interface_set_mac_addr(struct net_device *dev, void *p) { struct batadv_priv *bat_priv = netdev_priv(dev); struct sockaddr *addr = p; - uint8_t old_addr[ETH_ALEN]; if (!is_valid_ether_addr(addr->sa_data)) return -EADDRNOTAVAIL; - memcpy(old_addr, dev->dev_addr, ETH_ALEN); - memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN); - /* only modify transtable if it has been initialized before */ if (atomic_read(&bat_priv->mesh_state) == BATADV_MESH_ACTIVE) { - batadv_tt_local_remove(bat_priv, old_addr, + batadv_tt_local_remove(bat_priv, dev->dev_addr, "mac address changed", false); batadv_tt_local_add(dev, addr->sa_data, BATADV_NULL_IFINDEX); } + memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN); dev->addr_assign_type &= ~NET_ADDR_RANDOM; return 0; } diff --git a/trunk/net/batman-adv/translation-table.c b/trunk/net/batman-adv/translation-table.c index 99dd8f75b3ff..a438f4b582fc 100644 --- a/trunk/net/batman-adv/translation-table.c +++ b/trunk/net/batman-adv/translation-table.c @@ -197,7 +197,6 @@ static void batadv_tt_local_event(struct batadv_priv *bat_priv, del: list_del(&entry->list); kfree(entry); - kfree(tt_change_node); event_removed = true; goto unlock; } diff --git a/trunk/net/bluetooth/bnep/sock.c b/trunk/net/bluetooth/bnep/sock.c index 1eaacf10d19d..5e5f5b410e0b 100644 --- a/trunk/net/bluetooth/bnep/sock.c +++ b/trunk/net/bluetooth/bnep/sock.c @@ -58,7 +58,7 @@ static int bnep_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long switch (cmd) { case BNEPCONNADD: if (!capable(CAP_NET_ADMIN)) - return -EPERM; + return -EACCES; if (copy_from_user(&ca, argp, sizeof(ca))) return -EFAULT; @@ -84,7 +84,7 @@ static int bnep_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long case BNEPCONNDEL: if (!capable(CAP_NET_ADMIN)) - return -EPERM; + return -EACCES; if (copy_from_user(&cd, argp, sizeof(cd))) return -EFAULT; diff --git a/trunk/net/bluetooth/cmtp/sock.c b/trunk/net/bluetooth/cmtp/sock.c index 32dc83dcb6b2..311668d14571 100644 --- a/trunk/net/bluetooth/cmtp/sock.c +++ b/trunk/net/bluetooth/cmtp/sock.c @@ -72,7 +72,7 @@ static int cmtp_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long switch (cmd) { case CMTPCONNADD: if (!capable(CAP_NET_ADMIN)) - return -EPERM; + return -EACCES; if (copy_from_user(&ca, argp, sizeof(ca))) return -EFAULT; @@ -97,7 +97,7 @@ static int cmtp_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long case CMTPCONNDEL: if (!capable(CAP_NET_ADMIN)) - return -EPERM; + return -EACCES; if (copy_from_user(&cd, argp, sizeof(cd))) return -EFAULT; diff --git a/trunk/net/bluetooth/hci_conn.c b/trunk/net/bluetooth/hci_conn.c index 3c094e78dde9..5ad7da217474 100644 --- a/trunk/net/bluetooth/hci_conn.c +++ b/trunk/net/bluetooth/hci_conn.c @@ -29,7 +29,6 @@ #include #include #include -#include static void hci_le_connect(struct hci_conn *conn) { @@ -620,9 +619,6 @@ int hci_conn_security(struct hci_conn *conn, __u8 sec_level, __u8 auth_type) { BT_DBG("hcon %p", conn); - if (conn->type == LE_LINK) - return smp_conn_security(conn, sec_level); - /* For sdp we don't need the link key. */ if (sec_level == BT_SECURITY_SDP) return 1; diff --git a/trunk/net/bluetooth/hci_core.c b/trunk/net/bluetooth/hci_core.c index 0b997c8f9655..d4de5db18d5a 100644 --- a/trunk/net/bluetooth/hci_core.c +++ b/trunk/net/bluetooth/hci_core.c @@ -734,8 +734,6 @@ static int hci_dev_do_close(struct hci_dev *hdev) cancel_work_sync(&hdev->le_scan); - cancel_delayed_work(&hdev->power_off); - hci_req_cancel(hdev, ENODEV); hci_req_lock(hdev); diff --git a/trunk/net/bluetooth/hci_event.c b/trunk/net/bluetooth/hci_event.c index 715d7e33fba0..41ff978a33f9 100644 --- a/trunk/net/bluetooth/hci_event.c +++ b/trunk/net/bluetooth/hci_event.c @@ -1365,9 +1365,6 @@ static bool hci_resolve_next_name(struct hci_dev *hdev) return false; e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED); - if (!e) - return false; - if (hci_resolve_name(hdev, e) == 0) { e->name_state = NAME_PENDING; return true; @@ -1396,20 +1393,12 @@ static void hci_check_pending_name(struct hci_dev *hdev, struct hci_conn *conn, return; e = hci_inquiry_cache_lookup_resolve(hdev, bdaddr, NAME_PENDING); - /* If the device was not found in a list of found devices names of which - * are pending. there is no need to continue resolving a next name as it - * will be done upon receiving another Remote Name Request Complete - * Event */ - if (!e) - return; - - list_del(&e->list); - if (name) { + if (e) { e->name_state = NAME_KNOWN; - mgmt_remote_name(hdev, bdaddr, ACL_LINK, 0x00, - e->data.rssi, name, name_len); - } else { - e->name_state = NAME_NOT_KNOWN; + list_del(&e->list); + if (name) + mgmt_remote_name(hdev, bdaddr, ACL_LINK, 0x00, + e->data.rssi, name, name_len); } if (hci_resolve_next_name(hdev)) @@ -1773,12 +1762,7 @@ static void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) if (conn->type == ACL_LINK) { conn->state = BT_CONFIG; hci_conn_hold(conn); - - if (!conn->out && !hci_conn_ssp_enabled(conn) && - !hci_find_link_key(hdev, &ev->bdaddr)) - conn->disc_timeout = HCI_PAIRING_TIMEOUT; - else - conn->disc_timeout = HCI_DISCONN_TIMEOUT; + conn->disc_timeout = HCI_DISCONN_TIMEOUT; } else conn->state = BT_CONNECTED; diff --git a/trunk/net/bluetooth/hci_sock.c b/trunk/net/bluetooth/hci_sock.c index d5ace1eda3ed..a7f04de03d79 100644 --- a/trunk/net/bluetooth/hci_sock.c +++ b/trunk/net/bluetooth/hci_sock.c @@ -490,7 +490,7 @@ static int hci_sock_bound_ioctl(struct sock *sk, unsigned int cmd, switch (cmd) { case HCISETRAW: if (!capable(CAP_NET_ADMIN)) - return -EPERM; + return -EACCES; if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks)) return -EPERM; @@ -510,12 +510,12 @@ static int hci_sock_bound_ioctl(struct sock *sk, unsigned int cmd, case HCIBLOCKADDR: if (!capable(CAP_NET_ADMIN)) - return -EPERM; + return -EACCES; return hci_sock_blacklist_add(hdev, (void __user *) arg); case HCIUNBLOCKADDR: if (!capable(CAP_NET_ADMIN)) - return -EPERM; + return -EACCES; return hci_sock_blacklist_del(hdev, (void __user *) arg); default: @@ -546,22 +546,22 @@ static int hci_sock_ioctl(struct socket *sock, unsigned int cmd, case HCIDEVUP: if (!capable(CAP_NET_ADMIN)) - return -EPERM; + return -EACCES; return hci_dev_open(arg); case HCIDEVDOWN: if (!capable(CAP_NET_ADMIN)) - return -EPERM; + return -EACCES; return hci_dev_close(arg); case HCIDEVRESET: if (!capable(CAP_NET_ADMIN)) - return -EPERM; + return -EACCES; return hci_dev_reset(arg); case HCIDEVRESTAT: if (!capable(CAP_NET_ADMIN)) - return -EPERM; + return -EACCES; return hci_dev_reset_stat(arg); case HCISETSCAN: @@ -573,7 +573,7 @@ static int hci_sock_ioctl(struct socket *sock, unsigned int cmd, case HCISETACLMTU: case HCISETSCOMTU: if (!capable(CAP_NET_ADMIN)) - return -EPERM; + return -EACCES; return hci_dev_cmd(cmd, argp); case HCIINQUIRY: @@ -694,7 +694,6 @@ static int hci_sock_getname(struct socket *sock, struct sockaddr *addr, *addr_len = sizeof(*haddr); haddr->hci_family = AF_BLUETOOTH; haddr->hci_dev = hdev->id; - haddr->hci_channel= 0; release_sock(sk); return 0; @@ -1010,7 +1009,6 @@ static int hci_sock_getsockopt(struct socket *sock, int level, int optname, { struct hci_filter *f = &hci_pi(sk)->filter; - memset(&uf, 0, sizeof(uf)); uf.type_mask = f->type_mask; uf.opcode = f->opcode; uf.event_mask[0] = *((u32 *) f->event_mask + 0); diff --git a/trunk/net/bluetooth/hidp/sock.c b/trunk/net/bluetooth/hidp/sock.c index b24fb3bd8625..18b3f6892a36 100644 --- a/trunk/net/bluetooth/hidp/sock.c +++ b/trunk/net/bluetooth/hidp/sock.c @@ -56,7 +56,7 @@ static int hidp_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long switch (cmd) { case HIDPCONNADD: if (!capable(CAP_NET_ADMIN)) - return -EPERM; + return -EACCES; if (copy_from_user(&ca, argp, sizeof(ca))) return -EFAULT; @@ -91,7 +91,7 @@ static int hidp_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long case HIDPCONNDEL: if (!capable(CAP_NET_ADMIN)) - return -EPERM; + return -EACCES; if (copy_from_user(&cd, argp, sizeof(cd))) return -EFAULT; diff --git a/trunk/net/bluetooth/l2cap_core.c b/trunk/net/bluetooth/l2cap_core.c index 38c00f142203..a8964db04bfb 100644 --- a/trunk/net/bluetooth/l2cap_core.c +++ b/trunk/net/bluetooth/l2cap_core.c @@ -1008,7 +1008,7 @@ static void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *c if (!conn) return; - if (chan->mode == L2CAP_MODE_ERTM && chan->state == BT_CONNECTED) { + if (chan->mode == L2CAP_MODE_ERTM) { __clear_retrans_timer(chan); __clear_monitor_timer(chan); __clear_ack_timer(chan); @@ -1181,7 +1181,6 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn) sk = chan->sk; hci_conn_hold(conn->hcon); - conn->hcon->disc_timeout = HCI_DISCONN_TIMEOUT; bacpy(&bt_sk(sk)->src, conn->src); bacpy(&bt_sk(sk)->dst, conn->dst); @@ -1199,15 +1198,14 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn) static void l2cap_conn_ready(struct l2cap_conn *conn) { struct l2cap_chan *chan; - struct hci_conn *hcon = conn->hcon; BT_DBG("conn %p", conn); - if (!hcon->out && hcon->type == LE_LINK) + if (!conn->hcon->out && conn->hcon->type == LE_LINK) l2cap_le_conn_ready(conn); - if (hcon->out && hcon->type == LE_LINK) - smp_conn_security(hcon, hcon->pending_sec_level); + if (conn->hcon->out && conn->hcon->type == LE_LINK) + smp_conn_security(conn, conn->hcon->pending_sec_level); mutex_lock(&conn->chan_lock); @@ -1220,8 +1218,8 @@ static void l2cap_conn_ready(struct l2cap_conn *conn) continue; } - if (hcon->type == LE_LINK) { - if (smp_conn_security(hcon, chan->sec_level)) + if (conn->hcon->type == LE_LINK) { + if (smp_conn_security(conn, chan->sec_level)) l2cap_chan_ready(chan); } else if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) { diff --git a/trunk/net/bluetooth/l2cap_sock.c b/trunk/net/bluetooth/l2cap_sock.c index 34bbe1c5e389..a4bb27e8427e 100644 --- a/trunk/net/bluetooth/l2cap_sock.c +++ b/trunk/net/bluetooth/l2cap_sock.c @@ -245,7 +245,6 @@ static int l2cap_sock_getname(struct socket *sock, struct sockaddr *addr, int *l BT_DBG("sock %p, sk %p", sock, sk); - memset(la, 0, sizeof(struct sockaddr_l2)); addr->sa_family = AF_BLUETOOTH; *len = sizeof(struct sockaddr_l2); @@ -616,7 +615,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch break; } - if (smp_conn_security(conn->hcon, sec.level)) + if (smp_conn_security(conn, sec.level)) break; sk->sk_state = BT_CONFIG; chan->state = BT_CONFIG; @@ -1175,7 +1174,7 @@ static struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock, int p chan = l2cap_chan_create(); if (!chan) { - sk_free(sk); + l2cap_sock_kill(sk); return NULL; } diff --git a/trunk/net/bluetooth/mgmt.c b/trunk/net/bluetooth/mgmt.c index eba022de3c20..ad6613d17ca6 100644 --- a/trunk/net/bluetooth/mgmt.c +++ b/trunk/net/bluetooth/mgmt.c @@ -2875,22 +2875,6 @@ int mgmt_powered(struct hci_dev *hdev, u8 powered) if (scan) hci_send_cmd(hdev, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan); - if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) { - u8 ssp = 1; - - hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, 1, &ssp); - } - - if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) { - struct hci_cp_write_le_host_supported cp; - - cp.le = 1; - cp.simul = !!(hdev->features[6] & LMP_SIMUL_LE_BR); - - hci_send_cmd(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, - sizeof(cp), &cp); - } - update_class(hdev); update_name(hdev, hdev->dev_name); update_eir(hdev); diff --git a/trunk/net/bluetooth/rfcomm/sock.c b/trunk/net/bluetooth/rfcomm/sock.c index 1a17850d093c..7e1e59645c05 100644 --- a/trunk/net/bluetooth/rfcomm/sock.c +++ b/trunk/net/bluetooth/rfcomm/sock.c @@ -528,7 +528,6 @@ static int rfcomm_sock_getname(struct socket *sock, struct sockaddr *addr, int * BT_DBG("sock %p, sk %p", sock, sk); - memset(sa, 0, sizeof(*sa)); sa->rc_family = AF_BLUETOOTH; sa->rc_channel = rfcomm_pi(sk)->channel; if (peer) @@ -823,7 +822,6 @@ static int rfcomm_sock_getsockopt(struct socket *sock, int level, int optname, c } sec.level = rfcomm_pi(sk)->sec_level; - sec.key_size = 0; len = min_t(unsigned int, len, sizeof(sec)); if (copy_to_user(optval, (char *) &sec, len)) diff --git a/trunk/net/bluetooth/rfcomm/tty.c b/trunk/net/bluetooth/rfcomm/tty.c index ccc248791d50..cb960773c002 100644 --- a/trunk/net/bluetooth/rfcomm/tty.c +++ b/trunk/net/bluetooth/rfcomm/tty.c @@ -278,8 +278,8 @@ static int rfcomm_dev_add(struct rfcomm_dev_req *req, struct rfcomm_dlc *dlc) if (err < 0) goto free; - dev->tty_dev = tty_port_register_device(&dev->port, rfcomm_tty_driver, - dev->id, NULL); + dev->tty_dev = tty_register_device(rfcomm_tty_driver, dev->id, NULL); + if (IS_ERR(dev->tty_dev)) { err = PTR_ERR(dev->tty_dev); list_del(&dev->list); @@ -456,7 +456,7 @@ static int rfcomm_get_dev_list(void __user *arg) size = sizeof(*dl) + dev_num * sizeof(*di); - dl = kzalloc(size, GFP_KERNEL); + dl = kmalloc(size, GFP_KERNEL); if (!dl) return -ENOMEM; @@ -705,9 +705,9 @@ static int rfcomm_tty_open(struct tty_struct *tty, struct file *filp) break; } - tty_unlock(tty); + tty_unlock(); schedule(); - tty_lock(tty); + tty_lock(); } set_current_state(TASK_RUNNING); remove_wait_queue(&dev->wait, &wait); @@ -861,7 +861,7 @@ static int rfcomm_tty_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned l static void rfcomm_tty_set_termios(struct tty_struct *tty, struct ktermios *old) { - struct ktermios *new = &tty->termios; + struct ktermios *new = tty->termios; int old_baud_rate = tty_termios_baud_rate(old); int new_baud_rate = tty_termios_baud_rate(new); diff --git a/trunk/net/bluetooth/sco.c b/trunk/net/bluetooth/sco.c index 3589e21edb09..40bbe25dcff7 100644 --- a/trunk/net/bluetooth/sco.c +++ b/trunk/net/bluetooth/sco.c @@ -131,15 +131,6 @@ static int sco_conn_del(struct hci_conn *hcon, int err) sco_sock_clear_timer(sk); sco_chan_del(sk, err); bh_unlock_sock(sk); - - sco_conn_lock(conn); - conn->sk = NULL; - sco_pi(sk)->conn = NULL; - sco_conn_unlock(conn); - - if (conn->hcon) - hci_conn_put(conn->hcon); - sco_sock_kill(sk); } @@ -830,6 +821,16 @@ static void sco_chan_del(struct sock *sk, int err) BT_DBG("sk %p, conn %p, err %d", sk, conn, err); + if (conn) { + sco_conn_lock(conn); + conn->sk = NULL; + sco_pi(sk)->conn = NULL; + sco_conn_unlock(conn); + + if (conn->hcon) + hci_conn_put(conn->hcon); + } + sk->sk_state = BT_CLOSED; sk->sk_err = err; sk->sk_state_change(sk); diff --git a/trunk/net/bluetooth/smp.c b/trunk/net/bluetooth/smp.c index 8c225ef349cd..16ef0dc85a0a 100644 --- a/trunk/net/bluetooth/smp.c +++ b/trunk/net/bluetooth/smp.c @@ -267,10 +267,10 @@ static void smp_failure(struct l2cap_conn *conn, u8 reason, u8 send) mgmt_auth_failed(conn->hcon->hdev, conn->dst, hcon->type, hcon->dst_type, reason); - cancel_delayed_work_sync(&conn->security_timer); - - if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags)) + if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags)) { + cancel_delayed_work_sync(&conn->security_timer); smp_chan_destroy(conn); + } } #define JUST_WORKS 0x00 @@ -579,11 +579,8 @@ static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb) if (!test_and_set_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags)) smp = smp_chan_create(conn); - else - smp = conn->smp_chan; - if (!smp) - return SMP_UNSPECIFIED; + smp = conn->smp_chan; smp->preq[0] = SMP_CMD_PAIRING_REQ; memcpy(&smp->preq[1], req, sizeof(*req)); @@ -760,9 +757,9 @@ static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb) return 0; } -int smp_conn_security(struct hci_conn *hcon, __u8 sec_level) +int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level) { - struct l2cap_conn *conn = hcon->l2cap_data; + struct hci_conn *hcon = conn->hcon; struct smp_chan *smp = conn->smp_chan; __u8 authreq; diff --git a/trunk/net/bridge/br_device.c b/trunk/net/bridge/br_device.c index 070e8a68cfc6..333484537600 100644 --- a/trunk/net/bridge/br_device.c +++ b/trunk/net/bridge/br_device.c @@ -31,11 +31,9 @@ netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev) struct net_bridge_mdb_entry *mdst; struct br_cpu_netstats *brstats = this_cpu_ptr(br->stats); - rcu_read_lock(); #ifdef CONFIG_BRIDGE_NETFILTER if (skb->nf_bridge && (skb->nf_bridge->mask & BRNF_BRIDGED_DNAT)) { br_nf_pre_routing_finish_bridge_slow(skb); - rcu_read_unlock(); return NETDEV_TX_OK; } #endif @@ -50,6 +48,7 @@ netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev) skb_reset_mac_header(skb); skb_pull(skb, ETH_HLEN); + rcu_read_lock(); if (is_broadcast_ether_addr(dest)) br_flood_deliver(br, skb); else if (is_multicast_ether_addr(dest)) { @@ -207,23 +206,24 @@ static void br_poll_controller(struct net_device *br_dev) static void br_netpoll_cleanup(struct net_device *dev) { struct net_bridge *br = netdev_priv(dev); - struct net_bridge_port *p; + struct net_bridge_port *p, *n; - list_for_each_entry(p, &br->port_list, list) + list_for_each_entry_safe(p, n, &br->port_list, list) { br_netpoll_disable(p); + } } -static int br_netpoll_setup(struct net_device *dev, struct netpoll_info *ni, - gfp_t gfp) +static int br_netpoll_setup(struct net_device *dev, struct netpoll_info *ni) { struct net_bridge *br = netdev_priv(dev); - struct net_bridge_port *p; + struct net_bridge_port *p, *n; int err = 0; - list_for_each_entry(p, &br->port_list, list) { + list_for_each_entry_safe(p, n, &br->port_list, list) { if (!p->dev) continue; - err = br_netpoll_enable(p, gfp); + + err = br_netpoll_enable(p); if (err) goto fail; } @@ -236,17 +236,17 @@ static int br_netpoll_setup(struct net_device *dev, struct netpoll_info *ni, goto out; } -int br_netpoll_enable(struct net_bridge_port *p, gfp_t gfp) +int br_netpoll_enable(struct net_bridge_port *p) { struct netpoll *np; int err = 0; - np = kzalloc(sizeof(*p->np), gfp); + np = kzalloc(sizeof(*p->np), GFP_KERNEL); err = -ENOMEM; if (!np) goto out; - err = __netpoll_setup(np, p->dev, gfp); + err = __netpoll_setup(np, p->dev); if (err) { kfree(np); goto out; @@ -267,7 +267,11 @@ void br_netpoll_disable(struct net_bridge_port *p) p->np = NULL; - __netpoll_free_rcu(np); + /* Wait for transmitting packets to finish before freeing. */ + synchronize_rcu_bh(); + + __netpoll_cleanup(np); + kfree(np); } #endif diff --git a/trunk/net/bridge/br_forward.c b/trunk/net/bridge/br_forward.c index 02015a505d2a..e9466d412707 100644 --- a/trunk/net/bridge/br_forward.c +++ b/trunk/net/bridge/br_forward.c @@ -65,7 +65,7 @@ static void __br_deliver(const struct net_bridge_port *to, struct sk_buff *skb) { skb->dev = to->dev; - if (unlikely(netpoll_tx_running(to->br->dev))) { + if (unlikely(netpoll_tx_running(to->dev))) { if (packet_length(skb) > skb->dev->mtu && !skb_is_gso(skb)) kfree_skb(skb); else { diff --git a/trunk/net/bridge/br_if.c b/trunk/net/bridge/br_if.c index 1c8fdc3558cd..e1144e1617be 100644 --- a/trunk/net/bridge/br_if.c +++ b/trunk/net/bridge/br_if.c @@ -361,7 +361,7 @@ int br_add_if(struct net_bridge *br, struct net_device *dev) if (err) goto err2; - if (br_netpoll_info(br) && ((err = br_netpoll_enable(p, GFP_KERNEL)))) + if (br_netpoll_info(br) && ((err = br_netpoll_enable(p)))) goto err3; err = netdev_set_master(dev, br->dev); @@ -427,10 +427,6 @@ int br_del_if(struct net_bridge *br, struct net_device *dev) if (!p || p->br != br) return -EINVAL; - /* Since more than one interface can be attached to a bridge, - * there still maybe an alternate path for netconsole to use; - * therefore there is no reason for a NETDEV_RELEASE event. - */ del_nbp(p); spin_lock_bh(&br->lock); diff --git a/trunk/net/bridge/br_private.h b/trunk/net/bridge/br_private.h index f507d2af9646..a768b2408edf 100644 --- a/trunk/net/bridge/br_private.h +++ b/trunk/net/bridge/br_private.h @@ -316,7 +316,7 @@ static inline void br_netpoll_send_skb(const struct net_bridge_port *p, netpoll_send_skb(np, skb); } -extern int br_netpoll_enable(struct net_bridge_port *p, gfp_t gfp); +extern int br_netpoll_enable(struct net_bridge_port *p); extern void br_netpoll_disable(struct net_bridge_port *p); #else static inline struct netpoll_info *br_netpoll_info(struct net_bridge *br) @@ -329,7 +329,7 @@ static inline void br_netpoll_send_skb(const struct net_bridge_port *p, { } -static inline int br_netpoll_enable(struct net_bridge_port *p, gfp_t gfp) +static inline int br_netpoll_enable(struct net_bridge_port *p) { return 0; } diff --git a/trunk/net/bridge/netfilter/ebt_log.c b/trunk/net/bridge/netfilter/ebt_log.c index 92de5e5f9db2..f88ee537fb2b 100644 --- a/trunk/net/bridge/netfilter/ebt_log.c +++ b/trunk/net/bridge/netfilter/ebt_log.c @@ -80,7 +80,7 @@ ebt_log_packet(u_int8_t pf, unsigned int hooknum, unsigned int bitmask; spin_lock_bh(&ebt_log_lock); - printk(KERN_SOH "%c%s IN=%s OUT=%s MAC source = %pM MAC dest = %pM proto = 0x%04x", + printk("<%c>%s IN=%s OUT=%s MAC source = %pM MAC dest = %pM proto = 0x%04x", '0' + loginfo->u.log.level, prefix, in ? in->name : "", out ? out->name : "", eth_hdr(skb)->h_source, eth_hdr(skb)->h_dest, diff --git a/trunk/net/caif/cfsrvl.c b/trunk/net/caif/cfsrvl.c index ba217e90765e..dd485f6128e8 100644 --- a/trunk/net/caif/cfsrvl.c +++ b/trunk/net/caif/cfsrvl.c @@ -211,10 +211,9 @@ void caif_client_register_refcnt(struct cflayer *adapt_layer, void (*put)(struct cflayer *lyr)) { struct cfsrvl *service; - - if (WARN_ON(adapt_layer == NULL || adapt_layer->dn == NULL)) - return; service = container_of(adapt_layer->dn, struct cfsrvl, layer); + + WARN_ON(adapt_layer == NULL || adapt_layer->dn == NULL); service->hold = hold; service->put = put; } diff --git a/trunk/net/caif/chnl_net.c b/trunk/net/caif/chnl_net.c index e597733affb8..69771c04ba8f 100644 --- a/trunk/net/caif/chnl_net.c +++ b/trunk/net/caif/chnl_net.c @@ -94,10 +94,6 @@ static int chnl_recv_cb(struct cflayer *layr, struct cfpkt *pkt) /* check the version of IP */ ip_version = skb_header_pointer(skb, 0, 1, &buf); - if (!ip_version) { - kfree_skb(skb); - return -EINVAL; - } switch (*ip_version >> 4) { case 4: diff --git a/trunk/net/ceph/ceph_common.c b/trunk/net/ceph/ceph_common.c index a8020293f342..69e38db28e5f 100644 --- a/trunk/net/ceph/ceph_common.c +++ b/trunk/net/ceph/ceph_common.c @@ -84,6 +84,7 @@ int ceph_check_fsid(struct ceph_client *client, struct ceph_fsid *fsid) return -1; } } else { + pr_info("client%lld fsid %pU\n", ceph_client_id(client), fsid); memcpy(&client->fsid, fsid, sizeof(*fsid)); } return 0; diff --git a/trunk/net/ceph/debugfs.c b/trunk/net/ceph/debugfs.c index 38b5dc1823d4..54b531a01121 100644 --- a/trunk/net/ceph/debugfs.c +++ b/trunk/net/ceph/debugfs.c @@ -189,9 +189,6 @@ int ceph_debugfs_client_init(struct ceph_client *client) snprintf(name, sizeof(name), "%pU.client%lld", &client->fsid, client->monc.auth->global_id); - dout("ceph_debugfs_client_init %p %s\n", client, name); - - BUG_ON(client->debugfs_dir); client->debugfs_dir = debugfs_create_dir(name, ceph_debugfs_dir); if (!client->debugfs_dir) goto out; @@ -237,7 +234,6 @@ int ceph_debugfs_client_init(struct ceph_client *client) void ceph_debugfs_client_cleanup(struct ceph_client *client) { - dout("ceph_debugfs_client_cleanup %p\n", client); debugfs_remove(client->debugfs_osdmap); debugfs_remove(client->debugfs_monmap); debugfs_remove(client->osdc.debugfs_file); diff --git a/trunk/net/ceph/messenger.c b/trunk/net/ceph/messenger.c index 159aa8bef9e7..b9796750034a 100644 --- a/trunk/net/ceph/messenger.c +++ b/trunk/net/ceph/messenger.c @@ -915,6 +915,7 @@ static int prepare_write_connect(struct ceph_connection *con) con->out_connect.authorizer_len = auth ? cpu_to_le32(auth->authorizer_buf_len) : 0; + con_out_kvec_reset(con); con_out_kvec_add(con, sizeof (con->out_connect), &con->out_connect); if (auth && auth->authorizer_buf_len) @@ -1073,13 +1074,16 @@ static int write_partial_msg_pages(struct ceph_connection *con) BUG_ON(kaddr == NULL); base = kaddr + con->out_msg_pos.page_pos + bio_offset; crc = crc32c(crc, base, len); - kunmap(page); msg->footer.data_crc = cpu_to_le32(crc); con->out_msg_pos.did_page_crc = true; } ret = ceph_tcp_sendpage(con->sock, page, con->out_msg_pos.page_pos + bio_offset, len, 1); + + if (do_datacrc) + kunmap(page); + if (ret <= 0) goto out; @@ -1553,7 +1557,6 @@ static int process_connect(struct ceph_connection *con) return -1; } con->auth_retry = 1; - con_out_kvec_reset(con); ret = prepare_write_connect(con); if (ret < 0) return ret; @@ -1574,7 +1577,6 @@ static int process_connect(struct ceph_connection *con) ENTITY_NAME(con->peer_name), ceph_pr_addr(&con->peer_addr.in_addr)); reset_connection(con); - con_out_kvec_reset(con); ret = prepare_write_connect(con); if (ret < 0) return ret; @@ -1599,7 +1601,6 @@ static int process_connect(struct ceph_connection *con) le32_to_cpu(con->out_connect.connect_seq), le32_to_cpu(con->in_reply.connect_seq)); con->connect_seq = le32_to_cpu(con->in_reply.connect_seq); - con_out_kvec_reset(con); ret = prepare_write_connect(con); if (ret < 0) return ret; @@ -1616,7 +1617,6 @@ static int process_connect(struct ceph_connection *con) le32_to_cpu(con->in_reply.global_seq)); get_global_seq(con->msgr, le32_to_cpu(con->in_reply.global_seq)); - con_out_kvec_reset(con); ret = prepare_write_connect(con); if (ret < 0) return ret; @@ -2135,11 +2135,7 @@ static int try_read(struct ceph_connection *con) BUG_ON(con->state != CON_STATE_CONNECTING); con->state = CON_STATE_NEGOTIATING; - /* - * Received banner is good, exchange connection info. - * Do not reset out_kvec, as sending our banner raced - * with receiving peer banner after connect completed. - */ + /* Banner is good, exchange connection info */ ret = prepare_write_connect(con); if (ret < 0) goto out; diff --git a/trunk/net/ceph/mon_client.c b/trunk/net/ceph/mon_client.c index 900ea0f043fc..105d533b55f3 100644 --- a/trunk/net/ceph/mon_client.c +++ b/trunk/net/ceph/mon_client.c @@ -310,17 +310,6 @@ int ceph_monc_open_session(struct ceph_mon_client *monc) } EXPORT_SYMBOL(ceph_monc_open_session); -/* - * We require the fsid and global_id in order to initialize our - * debugfs dir. - */ -static bool have_debugfs_info(struct ceph_mon_client *monc) -{ - dout("have_debugfs_info fsid %d globalid %lld\n", - (int)monc->client->have_fsid, monc->auth->global_id); - return monc->client->have_fsid && monc->auth->global_id > 0; -} - /* * The monitor responds with mount ack indicate mount success. The * included client ticket allows the client to talk to MDSs and OSDs. @@ -331,12 +320,9 @@ static void ceph_monc_handle_map(struct ceph_mon_client *monc, struct ceph_client *client = monc->client; struct ceph_monmap *monmap = NULL, *old = monc->monmap; void *p, *end; - int had_debugfs_info, init_debugfs = 0; mutex_lock(&monc->mutex); - had_debugfs_info = have_debugfs_info(monc); - dout("handle_monmap\n"); p = msg->front.iov_base; end = p + msg->front.iov_len; @@ -358,22 +344,12 @@ static void ceph_monc_handle_map(struct ceph_mon_client *monc, if (!client->have_fsid) { client->have_fsid = true; - if (!had_debugfs_info && have_debugfs_info(monc)) { - pr_info("client%lld fsid %pU\n", - ceph_client_id(monc->client), - &monc->client->fsid); - init_debugfs = 1; - } mutex_unlock(&monc->mutex); - - if (init_debugfs) { - /* - * do debugfs initialization without mutex to avoid - * creating a locking dependency - */ - ceph_debugfs_client_init(monc->client); - } - + /* + * do debugfs initialization without mutex to avoid + * creating a locking dependency + */ + ceph_debugfs_client_init(client); goto out_unlocked; } out: @@ -889,10 +865,8 @@ static void handle_auth_reply(struct ceph_mon_client *monc, { int ret; int was_auth = 0; - int had_debugfs_info, init_debugfs = 0; mutex_lock(&monc->mutex); - had_debugfs_info = have_debugfs_info(monc); if (monc->auth->ops) was_auth = monc->auth->ops->is_authenticated(monc->auth); monc->pending_auth = 0; @@ -915,22 +889,7 @@ static void handle_auth_reply(struct ceph_mon_client *monc, __send_subscribe(monc); __resend_generic_request(monc); } - - if (!had_debugfs_info && have_debugfs_info(monc)) { - pr_info("client%lld fsid %pU\n", - ceph_client_id(monc->client), - &monc->client->fsid); - init_debugfs = 1; - } mutex_unlock(&monc->mutex); - - if (init_debugfs) { - /* - * do debugfs initialization without mutex to avoid - * creating a locking dependency - */ - ceph_debugfs_client_init(monc->client); - } } static int __validate_auth(struct ceph_mon_client *monc) diff --git a/trunk/net/core/dev.c b/trunk/net/core/dev.c index 36c4a0cdb6c1..0cb3fe8d8e72 100644 --- a/trunk/net/core/dev.c +++ b/trunk/net/core/dev.c @@ -1055,8 +1055,6 @@ int dev_change_name(struct net_device *dev, const char *newname) */ int dev_set_alias(struct net_device *dev, const char *alias, size_t len) { - char *new_ifalias; - ASSERT_RTNL(); if (len >= IFALIASZ) @@ -1070,10 +1068,9 @@ int dev_set_alias(struct net_device *dev, const char *alias, size_t len) return 0; } - new_ifalias = krealloc(dev->ifalias, len + 1, GFP_KERNEL); - if (!new_ifalias) + dev->ifalias = krealloc(dev->ifalias, len + 1, GFP_KERNEL); + if (!dev->ifalias) return -ENOMEM; - dev->ifalias = new_ifalias; strlcpy(dev->ifalias, alias, len+1); return len; @@ -1642,19 +1639,6 @@ static inline int deliver_skb(struct sk_buff *skb, return pt_prev->func(skb, skb->dev, pt_prev, orig_dev); } -static inline bool skb_loop_sk(struct packet_type *ptype, struct sk_buff *skb) -{ - if (ptype->af_packet_priv == NULL) - return false; - - if (ptype->id_match) - return ptype->id_match(ptype, skb->sk); - else if ((struct sock *)ptype->af_packet_priv == skb->sk) - return true; - - return false; -} - /* * Support routine. Sends outgoing frames to any network * taps currently in use. @@ -1672,7 +1656,8 @@ static void dev_queue_xmit_nit(struct sk_buff *skb, struct net_device *dev) * they originated from - MvS (miquels@drinkel.ow.org) */ if ((ptype->dev == dev || !ptype->dev) && - (!skb_loop_sk(ptype, skb))) { + (ptype->af_packet_priv == NULL || + (struct sock *)ptype->af_packet_priv != skb->sk)) { if (pt_prev) { deliver_skb(skb2, pt_prev, skb->dev); pt_prev = ptype; @@ -2134,8 +2119,7 @@ static bool can_checksum_protocol(netdev_features_t features, __be16 protocol) static netdev_features_t harmonize_features(struct sk_buff *skb, __be16 protocol, netdev_features_t features) { - if (skb->ip_summed != CHECKSUM_NONE && - !can_checksum_protocol(features, protocol)) { + if (!can_checksum_protocol(features, protocol)) { features &= ~NETIF_F_ALL_CSUM; features &= ~NETIF_F_SG; } else if (illegal_highdma(skb->dev, skb)) { @@ -2150,9 +2134,6 @@ netdev_features_t netif_skb_features(struct sk_buff *skb) __be16 protocol = skb->protocol; netdev_features_t features = skb->dev->features; - if (skb_shinfo(skb)->gso_segs > skb->dev->gso_max_segs) - features &= ~NETIF_F_GSO_MASK; - if (protocol == htons(ETH_P_8021Q)) { struct vlan_ethhdr *veh = (struct vlan_ethhdr *)skb->data; protocol = veh->h_vlan_encapsulated_proto; @@ -2648,16 +2629,15 @@ void __skb_get_rxhash(struct sk_buff *skb) if (!skb_flow_dissect(skb, &keys)) return; - if (keys.ports) + if (keys.ports) { + if ((__force u16)keys.port16[1] < (__force u16)keys.port16[0]) + swap(keys.port16[0], keys.port16[1]); skb->l4_rxhash = 1; + } /* get a consistent hash (same value on both flow directions) */ - if (((__force u32)keys.dst < (__force u32)keys.src) || - (((__force u32)keys.dst == (__force u32)keys.src) && - ((__force u16)keys.port16[1] < (__force u16)keys.port16[0]))) { + if ((__force u32)keys.dst < (__force u32)keys.src) swap(keys.dst, keys.src); - swap(keys.port16[0], keys.port16[1]); - } hash = jhash_3words((__force u32)keys.dst, (__force u32)keys.src, @@ -3323,7 +3303,7 @@ static int __netif_receive_skb(struct sk_buff *skb) if (pt_prev) { if (unlikely(skb_orphan_frags(skb, GFP_ATOMIC))) - goto drop; + ret = -ENOMEM; else ret = pt_prev->func(skb, skb->dev, pt_prev, orig_dev); } else { @@ -5746,7 +5726,6 @@ EXPORT_SYMBOL(netdev_refcnt_read); /** * netdev_wait_allrefs - wait until all references are gone. - * @dev: target net_device * * This is called when unregistering network devices. * @@ -6007,7 +5986,6 @@ struct net_device *alloc_netdev_mqs(int sizeof_priv, const char *name, dev_net_set(dev, &init_net); dev->gso_max_size = GSO_MAX_SIZE; - dev->gso_max_segs = GSO_MAX_SEGS; INIT_LIST_HEAD(&dev->napi_list); INIT_LIST_HEAD(&dev->unreg_list); @@ -6424,26 +6402,22 @@ const char *netdev_drivername(const struct net_device *dev) return empty; } -static int __netdev_printk(const char *level, const struct net_device *dev, +int __netdev_printk(const char *level, const struct net_device *dev, struct va_format *vaf) { int r; - if (dev && dev->dev.parent) { - r = dev_printk_emit(level[1] - '0', - dev->dev.parent, - "%s %s %s: %pV", - dev_driver_string(dev->dev.parent), - dev_name(dev->dev.parent), - netdev_name(dev), vaf); - } else if (dev) { + if (dev && dev->dev.parent) + r = dev_printk(level, dev->dev.parent, "%s: %pV", + netdev_name(dev), vaf); + else if (dev) r = printk("%s%s: %pV", level, netdev_name(dev), vaf); - } else { + else r = printk("%s(NULL net_device): %pV", level, vaf); - } return r; } +EXPORT_SYMBOL(__netdev_printk); int netdev_printk(const char *level, const struct net_device *dev, const char *format, ...) @@ -6458,7 +6432,6 @@ int netdev_printk(const char *level, const struct net_device *dev, vaf.va = &args; r = __netdev_printk(level, dev, &vaf); - va_end(args); return r; @@ -6478,7 +6451,6 @@ int func(const struct net_device *dev, const char *fmt, ...) \ vaf.va = &args; \ \ r = __netdev_printk(level, dev, &vaf); \ - \ va_end(args); \ \ return r; \ diff --git a/trunk/net/core/dst.c b/trunk/net/core/dst.c index 56d63612e1e4..069d51d29414 100644 --- a/trunk/net/core/dst.c +++ b/trunk/net/core/dst.c @@ -149,15 +149,7 @@ int dst_discard(struct sk_buff *skb) } EXPORT_SYMBOL(dst_discard); -const u32 dst_default_metrics[RTAX_MAX + 1] = { - /* This initializer is needed to force linker to place this variable - * into const section. Otherwise it might end into bss section. - * We really want to avoid false sharing on this variable, and catch - * any writes on it. - */ - [RTAX_MAX] = 0xdeadbeef, -}; - +const u32 dst_default_metrics[RTAX_MAX]; void *dst_alloc(struct dst_ops *ops, struct net_device *dev, int initial_ref, int initial_obsolete, unsigned short flags) diff --git a/trunk/net/core/netpoll.c b/trunk/net/core/netpoll.c index e4ba3e70c174..b4c90e42b443 100644 --- a/trunk/net/core/netpoll.c +++ b/trunk/net/core/netpoll.c @@ -26,7 +26,6 @@ #include #include #include -#include #include #include #include @@ -55,7 +54,7 @@ static atomic_t trapped; MAX_UDP_CHUNK) static void zap_completion_queue(void); -static void netpoll_arp_reply(struct sk_buff *skb, struct netpoll_info *npinfo); +static void arp_reply(struct sk_buff *skb); static unsigned int carrier_timeout = 4; module_param(carrier_timeout, uint, 0644); @@ -171,8 +170,7 @@ static void poll_napi(struct net_device *dev) list_for_each_entry(napi, &dev->napi_list, dev_list) { if (napi->poll_owner != smp_processor_id() && spin_trylock(&napi->poll_lock)) { - budget = poll_one_napi(rcu_dereference_bh(dev->npinfo), - napi, budget); + budget = poll_one_napi(dev->npinfo, napi, budget); spin_unlock(&napi->poll_lock); if (!budget) @@ -187,14 +185,13 @@ static void service_arp_queue(struct netpoll_info *npi) struct sk_buff *skb; while ((skb = skb_dequeue(&npi->arp_tx))) - netpoll_arp_reply(skb, npi); + arp_reply(skb); } } static void netpoll_poll_dev(struct net_device *dev) { const struct net_device_ops *ops; - struct netpoll_info *ni = rcu_dereference_bh(dev->npinfo); if (!dev || !netif_running(dev)) return; @@ -209,18 +206,17 @@ static void netpoll_poll_dev(struct net_device *dev) poll_napi(dev); if (dev->flags & IFF_SLAVE) { - if (ni) { + if (dev->npinfo) { struct net_device *bond_dev = dev->master; struct sk_buff *skb; - struct netpoll_info *bond_ni = rcu_dereference_bh(bond_dev->npinfo); - while ((skb = skb_dequeue(&ni->arp_tx))) { + while ((skb = skb_dequeue(&dev->npinfo->arp_tx))) { skb->dev = bond_dev; - skb_queue_tail(&bond_ni->arp_tx, skb); + skb_queue_tail(&bond_dev->npinfo->arp_tx, skb); } } } - service_arp_queue(ni); + service_arp_queue(dev->npinfo); zap_completion_queue(); } @@ -306,7 +302,6 @@ static int netpoll_owner_active(struct net_device *dev) return 0; } -/* call with IRQ disabled */ void netpoll_send_skb_on_dev(struct netpoll *np, struct sk_buff *skb, struct net_device *dev) { @@ -314,11 +309,8 @@ void netpoll_send_skb_on_dev(struct netpoll *np, struct sk_buff *skb, unsigned long tries; const struct net_device_ops *ops = dev->netdev_ops; /* It is up to the caller to keep npinfo alive. */ - struct netpoll_info *npinfo; - - WARN_ON_ONCE(!irqs_disabled()); + struct netpoll_info *npinfo = np->dev->npinfo; - npinfo = rcu_dereference_bh(np->dev->npinfo); if (!npinfo || !netif_running(dev) || !netif_device_present(dev)) { __kfree_skb(skb); return; @@ -327,22 +319,16 @@ void netpoll_send_skb_on_dev(struct netpoll *np, struct sk_buff *skb, /* don't get messages out of order, and no recursion */ if (skb_queue_len(&npinfo->txq) == 0 && !netpoll_owner_active(dev)) { struct netdev_queue *txq; + unsigned long flags; txq = netdev_get_tx_queue(dev, skb_get_queue_mapping(skb)); + local_irq_save(flags); /* try until next clock tick */ for (tries = jiffies_to_usecs(1)/USEC_PER_POLL; tries > 0; --tries) { if (__netif_tx_trylock(txq)) { if (!netif_xmit_stopped(txq)) { - if (vlan_tx_tag_present(skb) && - !(netif_skb_features(skb) & NETIF_F_HW_VLAN_TX)) { - skb = __vlan_put_tag(skb, vlan_tx_tag_get(skb)); - if (unlikely(!skb)) - break; - skb->vlan_tci = 0; - } - status = ops->ndo_start_xmit(skb, dev); if (status == NETDEV_TX_OK) txq_trans_update(txq); @@ -361,9 +347,10 @@ void netpoll_send_skb_on_dev(struct netpoll *np, struct sk_buff *skb, } WARN_ONCE(!irqs_disabled(), - "netpoll_send_skb_on_dev(): %s enabled interrupts in poll (%pF)\n", + "netpoll_send_skb(): %s enabled interrupts in poll (%pF)\n", dev->name, ops->ndo_start_xmit); + local_irq_restore(flags); } if (status != NETDEV_TX_OK) { @@ -436,8 +423,9 @@ void netpoll_send_udp(struct netpoll *np, const char *msg, int len) } EXPORT_SYMBOL(netpoll_send_udp); -static void netpoll_arp_reply(struct sk_buff *skb, struct netpoll_info *npinfo) +static void arp_reply(struct sk_buff *skb) { + struct netpoll_info *npinfo = skb->dev->npinfo; struct arphdr *arp; unsigned char *arp_ptr; int size, type = ARPOP_REPLY, ptype = ETH_P_ARP; @@ -555,12 +543,13 @@ static void netpoll_arp_reply(struct sk_buff *skb, struct netpoll_info *npinfo) spin_unlock_irqrestore(&npinfo->rx_lock, flags); } -int __netpoll_rx(struct sk_buff *skb, struct netpoll_info *npinfo) +int __netpoll_rx(struct sk_buff *skb) { int proto, len, ulen; int hits = 0; const struct iphdr *iph; struct udphdr *uh; + struct netpoll_info *npinfo = skb->dev->npinfo; struct netpoll *np, *tmp; if (list_empty(&npinfo->rx_np)) @@ -576,12 +565,6 @@ int __netpoll_rx(struct sk_buff *skb, struct netpoll_info *npinfo) return 1; } - if (skb->protocol == cpu_to_be16(ETH_P_8021Q)) { - skb = vlan_untag(skb); - if (unlikely(!skb)) - goto out; - } - proto = ntohs(eth_hdr(skb)->h_proto); if (proto != ETH_P_IP) goto out; @@ -732,7 +715,7 @@ int netpoll_parse_options(struct netpoll *np, char *opt) } EXPORT_SYMBOL(netpoll_parse_options); -int __netpoll_setup(struct netpoll *np, struct net_device *ndev, gfp_t gfp) +int __netpoll_setup(struct netpoll *np, struct net_device *ndev) { struct netpoll_info *npinfo; const struct net_device_ops *ops; @@ -751,7 +734,7 @@ int __netpoll_setup(struct netpoll *np, struct net_device *ndev, gfp_t gfp) } if (!ndev->npinfo) { - npinfo = kmalloc(sizeof(*npinfo), gfp); + npinfo = kmalloc(sizeof(*npinfo), GFP_KERNEL); if (!npinfo) { err = -ENOMEM; goto out; @@ -769,7 +752,7 @@ int __netpoll_setup(struct netpoll *np, struct net_device *ndev, gfp_t gfp) ops = np->dev->netdev_ops; if (ops->ndo_netpoll_setup) { - err = ops->ndo_netpoll_setup(ndev, npinfo, gfp); + err = ops->ndo_netpoll_setup(ndev, npinfo); if (err) goto free_npinfo; } @@ -874,7 +857,7 @@ int netpoll_setup(struct netpoll *np) refill_skbs(); rtnl_lock(); - err = __netpoll_setup(np, ndev, GFP_KERNEL); + err = __netpoll_setup(np, ndev); rtnl_unlock(); if (err) @@ -895,24 +878,6 @@ static int __init netpoll_init(void) } core_initcall(netpoll_init); -static void rcu_cleanup_netpoll_info(struct rcu_head *rcu_head) -{ - struct netpoll_info *npinfo = - container_of(rcu_head, struct netpoll_info, rcu); - - skb_queue_purge(&npinfo->arp_tx); - skb_queue_purge(&npinfo->txq); - - /* we can't call cancel_delayed_work_sync here, as we are in softirq */ - cancel_delayed_work(&npinfo->tx_work); - - /* clean after last, unfinished work */ - __skb_queue_purge(&npinfo->txq); - /* now cancel it again */ - cancel_delayed_work(&npinfo->tx_work); - kfree(npinfo); -} - void __netpoll_cleanup(struct netpoll *np) { struct netpoll_info *npinfo; @@ -938,24 +903,20 @@ void __netpoll_cleanup(struct netpoll *np) ops->ndo_netpoll_cleanup(np->dev); RCU_INIT_POINTER(np->dev->npinfo, NULL); - call_rcu_bh(&npinfo->rcu, rcu_cleanup_netpoll_info); - } -} -EXPORT_SYMBOL_GPL(__netpoll_cleanup); -static void rcu_cleanup_netpoll(struct rcu_head *rcu_head) -{ - struct netpoll *np = container_of(rcu_head, struct netpoll, rcu); + /* avoid racing with NAPI reading npinfo */ + synchronize_rcu_bh(); - __netpoll_cleanup(np); - kfree(np); -} + skb_queue_purge(&npinfo->arp_tx); + skb_queue_purge(&npinfo->txq); + cancel_delayed_work_sync(&npinfo->tx_work); -void __netpoll_free_rcu(struct netpoll *np) -{ - call_rcu_bh(&np->rcu, rcu_cleanup_netpoll); + /* clean after last, unfinished work */ + __skb_queue_purge(&npinfo->txq); + kfree(npinfo); + } } -EXPORT_SYMBOL_GPL(__netpoll_free_rcu); +EXPORT_SYMBOL_GPL(__netpoll_cleanup); void netpoll_cleanup(struct netpoll *np) { diff --git a/trunk/net/core/netprio_cgroup.c b/trunk/net/core/netprio_cgroup.c index c75e3f9d060f..ed0c0431fcd8 100644 --- a/trunk/net/core/netprio_cgroup.c +++ b/trunk/net/core/netprio_cgroup.c @@ -101,10 +101,12 @@ static int write_update_netdev_table(struct net_device *dev) u32 max_len; struct netprio_map *map; + rtnl_lock(); max_len = atomic_read(&max_prioidx) + 1; map = rtnl_dereference(dev->priomap); if (!map || map->priomap_len < max_len) ret = extend_netdev_table(dev, max_len); + rtnl_unlock(); return ret; } @@ -254,17 +256,17 @@ static int write_priomap(struct cgroup *cgrp, struct cftype *cft, if (!dev) goto out_free_devname; - rtnl_lock(); ret = write_update_netdev_table(dev); if (ret < 0) goto out_put_dev; - map = rtnl_dereference(dev->priomap); + rcu_read_lock(); + map = rcu_dereference(dev->priomap); if (map) map->priomap[prioidx] = priority; + rcu_read_unlock(); out_put_dev: - rtnl_unlock(); dev_put(dev); out_free_devname: @@ -275,6 +277,12 @@ static int write_priomap(struct cgroup *cgrp, struct cftype *cft, void net_prio_attach(struct cgroup *cgrp, struct cgroup_taskset *tset) { struct task_struct *p; + char *tmp = kzalloc(sizeof(char) * PATH_MAX, GFP_KERNEL); + + if (!tmp) { + pr_warn("Unable to attach cgrp due to alloc failure!\n"); + return; + } cgroup_taskset_for_each(p, cgrp, tset) { unsigned int fd; @@ -288,24 +296,32 @@ void net_prio_attach(struct cgroup *cgrp, struct cgroup_taskset *tset) continue; } - spin_lock(&files->file_lock); + rcu_read_lock(); fdt = files_fdtable(files); for (fd = 0; fd < fdt->max_fds; fd++) { + char *path; struct file *file; struct socket *sock; - int err; + unsigned long s; + int rv, err = 0; file = fcheck_files(files, fd); if (!file) continue; + path = d_path(&file->f_path, tmp, PAGE_SIZE); + rv = sscanf(path, "socket:[%lu]", &s); + if (rv <= 0) + continue; + sock = sock_from_file(file, &err); - if (sock) + if (!err) sock_update_netprioidx(sock->sk, p); } - spin_unlock(&files->file_lock); + rcu_read_unlock(); task_unlock(p); } + kfree(tmp); } static struct cftype ss_files[] = { diff --git a/trunk/net/core/pktgen.c b/trunk/net/core/pktgen.c index 148e73d2c451..cce9e53528b1 100644 --- a/trunk/net/core/pktgen.c +++ b/trunk/net/core/pktgen.c @@ -2721,7 +2721,7 @@ static struct sk_buff *fill_packet_ipv4(struct net_device *odev, /* Eth + IPh + UDPh + mpls */ datalen = pkt_dev->cur_pkt_size - 14 - 20 - 8 - pkt_dev->pkt_overhead; - if (datalen < 0 || datalen < sizeof(struct pktgen_hdr)) + if (datalen < sizeof(struct pktgen_hdr)) datalen = sizeof(struct pktgen_hdr); udph->source = htons(pkt_dev->cur_udp_src); diff --git a/trunk/net/core/scm.c b/trunk/net/core/scm.c index 040cebeed45b..8f6ccfd68ef4 100644 --- a/trunk/net/core/scm.c +++ b/trunk/net/core/scm.c @@ -265,7 +265,6 @@ void scm_detach_fds(struct msghdr *msg, struct scm_cookie *scm) for (i=0, cmfptr=(__force int __user *)CMSG_DATA(cm); isk, current); fd_install(new_fd, fp[i]); } diff --git a/trunk/net/core/skbuff.c b/trunk/net/core/skbuff.c index e33ebae519c8..fe00d1208167 100644 --- a/trunk/net/core/skbuff.c +++ b/trunk/net/core/skbuff.c @@ -3502,9 +3502,7 @@ bool skb_try_coalesce(struct sk_buff *to, struct sk_buff *from, if (!skb_cloned(from)) skb_shinfo(from)->nr_frags = 0; - /* if the skb is not cloned this does nothing - * since we set nr_frags to 0. - */ + /* if the skb is cloned this does nothing since we set nr_frags to 0 */ for (i = 0; i < skb_shinfo(from)->nr_frags; i++) skb_frag_ref(from, i); diff --git a/trunk/net/core/sock.c b/trunk/net/core/sock.c index a6000fbad294..6b654b3ddfda 100644 --- a/trunk/net/core/sock.c +++ b/trunk/net/core/sock.c @@ -691,8 +691,7 @@ int sock_setsockopt(struct socket *sock, int level, int optname, case SO_KEEPALIVE: #ifdef CONFIG_INET - if (sk->sk_protocol == IPPROTO_TCP && - sk->sk_type == SOCK_STREAM) + if (sk->sk_protocol == IPPROTO_TCP) tcp_set_keepalive(sk, valbool); #endif sock_valbool_flag(sk, SOCK_KEEPOPEN, valbool); @@ -1459,7 +1458,6 @@ void sk_setup_caps(struct sock *sk, struct dst_entry *dst) } else { sk->sk_route_caps |= NETIF_F_SG | NETIF_F_HW_CSUM; sk->sk_gso_max_size = dst->dev->gso_max_size; - sk->sk_gso_max_segs = dst->dev->gso_max_segs; } } } @@ -1524,14 +1522,7 @@ EXPORT_SYMBOL(sock_rfree); void sock_edemux(struct sk_buff *skb) { - struct sock *sk = skb->sk; - -#ifdef CONFIG_INET - if (sk->sk_state == TCP_TIME_WAIT) - inet_twsk_put(inet_twsk(sk)); - else -#endif - sock_put(sk); + sock_put(skb->sk); } EXPORT_SYMBOL(sock_edemux); diff --git a/trunk/net/dccp/ccid.h b/trunk/net/dccp/ccid.h index fb85d371a8de..75c3582a7678 100644 --- a/trunk/net/dccp/ccid.h +++ b/trunk/net/dccp/ccid.h @@ -246,7 +246,7 @@ static inline int ccid_hc_rx_getsockopt(struct ccid *ccid, struct sock *sk, u32 __user *optval, int __user *optlen) { int rc = -ENOPROTOOPT; - if (ccid != NULL && ccid->ccid_ops->ccid_hc_rx_getsockopt != NULL) + if (ccid->ccid_ops->ccid_hc_rx_getsockopt != NULL) rc = ccid->ccid_ops->ccid_hc_rx_getsockopt(sk, optname, len, optval, optlen); return rc; @@ -257,7 +257,7 @@ static inline int ccid_hc_tx_getsockopt(struct ccid *ccid, struct sock *sk, u32 __user *optval, int __user *optlen) { int rc = -ENOPROTOOPT; - if (ccid != NULL && ccid->ccid_ops->ccid_hc_tx_getsockopt != NULL) + if (ccid->ccid_ops->ccid_hc_tx_getsockopt != NULL) rc = ccid->ccid_ops->ccid_hc_tx_getsockopt(sk, optname, len, optval, optlen); return rc; diff --git a/trunk/net/dccp/ccids/ccid3.c b/trunk/net/dccp/ccids/ccid3.c index 119c04317d48..d65e98798eca 100644 --- a/trunk/net/dccp/ccids/ccid3.c +++ b/trunk/net/dccp/ccids/ccid3.c @@ -535,7 +535,6 @@ static int ccid3_hc_tx_getsockopt(struct sock *sk, const int optname, int len, case DCCP_SOCKOPT_CCID_TX_INFO: if (len < sizeof(tfrc)) return -EINVAL; - memset(&tfrc, 0, sizeof(tfrc)); tfrc.tfrctx_x = hc->tx_x; tfrc.tfrctx_x_recv = hc->tx_x_recv; tfrc.tfrctx_x_calc = hc->tx_x_calc; diff --git a/trunk/net/ipv4/arp.c b/trunk/net/ipv4/arp.c index 47800459e4cb..77e87aff419a 100644 --- a/trunk/net/ipv4/arp.c +++ b/trunk/net/ipv4/arp.c @@ -1225,7 +1225,7 @@ static int arp_netdev_event(struct notifier_block *this, unsigned long event, switch (event) { case NETDEV_CHANGEADDR: neigh_changeaddr(&arp_tbl, dev); - rt_cache_flush(dev_net(dev)); + rt_cache_flush(dev_net(dev), 0); break; default: break; diff --git a/trunk/net/ipv4/devinet.c b/trunk/net/ipv4/devinet.c index e12fad773852..44bf82e3aef7 100644 --- a/trunk/net/ipv4/devinet.c +++ b/trunk/net/ipv4/devinet.c @@ -725,7 +725,7 @@ int devinet_ioctl(struct net *net, unsigned int cmd, void __user *arg) break; case SIOCSIFFLAGS: - ret = -EPERM; + ret = -EACCES; if (!capable(CAP_NET_ADMIN)) goto out; break; @@ -733,7 +733,7 @@ int devinet_ioctl(struct net *net, unsigned int cmd, void __user *arg) case SIOCSIFBRDADDR: /* Set the broadcast address */ case SIOCSIFDSTADDR: /* Set the destination address */ case SIOCSIFNETMASK: /* Set the netmask for the interface */ - ret = -EPERM; + ret = -EACCES; if (!capable(CAP_NET_ADMIN)) goto out; ret = -EINVAL; @@ -1503,7 +1503,7 @@ static int devinet_conf_proc(ctl_table *ctl, int write, if (i == IPV4_DEVCONF_ACCEPT_LOCAL - 1 || i == IPV4_DEVCONF_ROUTE_LOCALNET - 1) if ((new_value == 0) && (old_value != 0)) - rt_cache_flush(net); + rt_cache_flush(net, 0); } return ret; @@ -1537,7 +1537,7 @@ static int devinet_sysctl_forward(ctl_table *ctl, int write, dev_disable_lro(idev->dev); } rtnl_unlock(); - rt_cache_flush(net); + rt_cache_flush(net, 0); } } @@ -1554,7 +1554,7 @@ static int ipv4_doint_and_flush(ctl_table *ctl, int write, struct net *net = ctl->extra2; if (write && *valp != val) - rt_cache_flush(net); + rt_cache_flush(net, 0); return ret; } diff --git a/trunk/net/ipv4/fib_frontend.c b/trunk/net/ipv4/fib_frontend.c index 8e2b475da9fa..c43ae3fba792 100644 --- a/trunk/net/ipv4/fib_frontend.c +++ b/trunk/net/ipv4/fib_frontend.c @@ -148,7 +148,7 @@ static void fib_flush(struct net *net) } if (flushed) - rt_cache_flush(net); + rt_cache_flush(net, -1); } /* @@ -999,11 +999,11 @@ static void nl_fib_lookup_exit(struct net *net) net->ipv4.fibnl = NULL; } -static void fib_disable_ip(struct net_device *dev, int force) +static void fib_disable_ip(struct net_device *dev, int force, int delay) { if (fib_sync_down_dev(dev, force)) fib_flush(dev_net(dev)); - rt_cache_flush(dev_net(dev)); + rt_cache_flush(dev_net(dev), delay); arp_ifdown(dev); } @@ -1020,7 +1020,7 @@ static int fib_inetaddr_event(struct notifier_block *this, unsigned long event, fib_sync_up(dev); #endif atomic_inc(&net->ipv4.dev_addr_genid); - rt_cache_flush(dev_net(dev)); + rt_cache_flush(dev_net(dev), -1); break; case NETDEV_DOWN: fib_del_ifaddr(ifa, NULL); @@ -1029,9 +1029,9 @@ static int fib_inetaddr_event(struct notifier_block *this, unsigned long event, /* Last address was deleted from this interface. * Disable IP. */ - fib_disable_ip(dev, 1); + fib_disable_ip(dev, 1, 0); } else { - rt_cache_flush(dev_net(dev)); + rt_cache_flush(dev_net(dev), -1); } break; } @@ -1045,7 +1045,7 @@ static int fib_netdev_event(struct notifier_block *this, unsigned long event, vo struct net *net = dev_net(dev); if (event == NETDEV_UNREGISTER) { - fib_disable_ip(dev, 2); + fib_disable_ip(dev, 2, -1); rt_flush_dev(dev); return NOTIFY_DONE; } @@ -1062,14 +1062,14 @@ static int fib_netdev_event(struct notifier_block *this, unsigned long event, vo fib_sync_up(dev); #endif atomic_inc(&net->ipv4.dev_addr_genid); - rt_cache_flush(dev_net(dev)); + rt_cache_flush(dev_net(dev), -1); break; case NETDEV_DOWN: - fib_disable_ip(dev, 0); + fib_disable_ip(dev, 0, 0); break; case NETDEV_CHANGEMTU: case NETDEV_CHANGE: - rt_cache_flush(dev_net(dev)); + rt_cache_flush(dev_net(dev), 0); break; case NETDEV_UNREGISTER_BATCH: break; diff --git a/trunk/net/ipv4/fib_rules.c b/trunk/net/ipv4/fib_rules.c index 274309d3aded..a83d74e498d2 100644 --- a/trunk/net/ipv4/fib_rules.c +++ b/trunk/net/ipv4/fib_rules.c @@ -259,7 +259,7 @@ static size_t fib4_rule_nlmsg_payload(struct fib_rule *rule) static void fib4_rule_flush_cache(struct fib_rules_ops *ops) { - rt_cache_flush(ops->fro_net); + rt_cache_flush(ops->fro_net, -1); } static const struct fib_rules_ops __net_initdata fib4_rules_ops_template = { diff --git a/trunk/net/ipv4/fib_trie.c b/trunk/net/ipv4/fib_trie.c index d1b93595b4a7..f0cdb30921c0 100644 --- a/trunk/net/ipv4/fib_trie.c +++ b/trunk/net/ipv4/fib_trie.c @@ -367,7 +367,7 @@ static void __leaf_free_rcu(struct rcu_head *head) static inline void free_leaf(struct leaf *l) { - call_rcu(&l->rcu, __leaf_free_rcu); + call_rcu_bh(&l->rcu, __leaf_free_rcu); } static inline void free_leaf_info(struct leaf_info *leaf) @@ -1286,7 +1286,7 @@ int fib_table_insert(struct fib_table *tb, struct fib_config *cfg) fib_release_info(fi_drop); if (state & FA_S_ACCESSED) - rt_cache_flush(cfg->fc_nlinfo.nl_net); + rt_cache_flush(cfg->fc_nlinfo.nl_net, -1); rtmsg_fib(RTM_NEWROUTE, htonl(key), new_fa, plen, tb->tb_id, &cfg->fc_nlinfo, NLM_F_REPLACE); @@ -1333,7 +1333,7 @@ int fib_table_insert(struct fib_table *tb, struct fib_config *cfg) list_add_tail_rcu(&new_fa->fa_list, (fa ? &fa->fa_list : fa_head)); - rt_cache_flush(cfg->fc_nlinfo.nl_net); + rt_cache_flush(cfg->fc_nlinfo.nl_net, -1); rtmsg_fib(RTM_NEWROUTE, htonl(key), new_fa, plen, tb->tb_id, &cfg->fc_nlinfo, 0); succeeded: @@ -1708,7 +1708,7 @@ int fib_table_delete(struct fib_table *tb, struct fib_config *cfg) trie_leaf_remove(t, l); if (fa->fa_state & FA_S_ACCESSED) - rt_cache_flush(cfg->fc_nlinfo.nl_net); + rt_cache_flush(cfg->fc_nlinfo.nl_net, -1); fib_release_info(fa->fa_info); alias_free_mem_rcu(fa); diff --git a/trunk/net/ipv4/inet_connection_sock.c b/trunk/net/ipv4/inet_connection_sock.c index 7f75f21d7b83..db0cf17c00f7 100644 --- a/trunk/net/ipv4/inet_connection_sock.c +++ b/trunk/net/ipv4/inet_connection_sock.c @@ -404,15 +404,12 @@ struct dst_entry *inet_csk_route_child_sock(struct sock *sk, { const struct inet_request_sock *ireq = inet_rsk(req); struct inet_sock *newinet = inet_sk(newsk); - struct ip_options_rcu *opt; + struct ip_options_rcu *opt = ireq->opt; struct net *net = sock_net(sk); struct flowi4 *fl4; struct rtable *rt; fl4 = &newinet->cork.fl.u.ip4; - - rcu_read_lock(); - opt = rcu_dereference(newinet->inet_opt); flowi4_init_output(fl4, sk->sk_bound_dev_if, sk->sk_mark, RT_CONN_FLAGS(sk), RT_SCOPE_UNIVERSE, sk->sk_protocol, inet_sk_flowi_flags(sk), @@ -424,13 +421,11 @@ struct dst_entry *inet_csk_route_child_sock(struct sock *sk, goto no_route; if (opt && opt->opt.is_strictroute && rt->rt_gateway) goto route_err; - rcu_read_unlock(); return &rt->dst; route_err: ip_rt_put(rt); no_route: - rcu_read_unlock(); IP_INC_STATS_BH(net, IPSTATS_MIB_OUTNOROUTES); return NULL; } diff --git a/trunk/net/ipv4/inetpeer.c b/trunk/net/ipv4/inetpeer.c index c7527f6b9ad9..e1e0a4e8fd34 100644 --- a/trunk/net/ipv4/inetpeer.c +++ b/trunk/net/ipv4/inetpeer.c @@ -510,10 +510,7 @@ struct inet_peer *inet_getpeer(struct inet_peer_base *base, secure_ipv6_id(daddr->addr.a6)); p->metrics[RTAX_LOCK-1] = INETPEER_METRICS_NEW; p->rate_tokens = 0; - /* 60*HZ is arbitrary, but chosen enough high so that the first - * calculation of tokens is at its maximum. - */ - p->rate_last = jiffies - 60*HZ; + p->rate_last = 0; INIT_LIST_HEAD(&p->gc_list); /* Link the node. */ diff --git a/trunk/net/ipv4/ip_output.c b/trunk/net/ipv4/ip_output.c index c196d749daf2..ba39a52d18c1 100644 --- a/trunk/net/ipv4/ip_output.c +++ b/trunk/net/ipv4/ip_output.c @@ -197,7 +197,7 @@ static inline int ip_finish_output2(struct sk_buff *skb) neigh = __ipv4_neigh_lookup_noref(dev, nexthop); if (unlikely(!neigh)) neigh = __neigh_create(&arp_tbl, &nexthop, dev, false); - if (!IS_ERR(neigh)) { + if (neigh) { int res = dst_neigh_output(dst, neigh, skb); rcu_read_unlock_bh(); @@ -1338,10 +1338,10 @@ struct sk_buff *__ip_make_skb(struct sock *sk, iph->ihl = 5; iph->tos = inet->tos; iph->frag_off = df; + ip_select_ident(iph, &rt->dst, sk); iph->ttl = ttl; iph->protocol = sk->sk_protocol; ip_copy_addrs(iph, fl4); - ip_select_ident(iph, &rt->dst, sk); if (opt) { iph->ihl += opt->optlen>>2; @@ -1366,8 +1366,9 @@ struct sk_buff *__ip_make_skb(struct sock *sk, return skb; } -int ip_send_skb(struct net *net, struct sk_buff *skb) +int ip_send_skb(struct sk_buff *skb) { + struct net *net = sock_net(skb->sk); int err; err = ip_local_out(skb); @@ -1390,7 +1391,7 @@ int ip_push_pending_frames(struct sock *sk, struct flowi4 *fl4) return 0; /* Netfilter gets whole the not fragmented skb. */ - return ip_send_skb(sock_net(sk), skb); + return ip_send_skb(skb); } /* @@ -1535,7 +1536,6 @@ void ip_send_unicast_reply(struct net *net, struct sk_buff *skb, __be32 daddr, arg->csumoffset) = csum_fold(csum_add(nskb->csum, arg->csum)); nskb->ip_summed = CHECKSUM_NONE; - skb_orphan(nskb); skb_set_queue_mapping(nskb, skb_get_queue_mapping(skb)); ip_push_pending_frames(sk, &fl4); } diff --git a/trunk/net/ipv4/ipmr.c b/trunk/net/ipv4/ipmr.c index ebdf06f938bf..8eec8f4a0536 100644 --- a/trunk/net/ipv4/ipmr.c +++ b/trunk/net/ipv4/ipmr.c @@ -124,8 +124,6 @@ static DEFINE_SPINLOCK(mfc_unres_lock); static struct kmem_cache *mrt_cachep __read_mostly; static struct mr_table *ipmr_new_table(struct net *net, u32 id); -static void ipmr_free_table(struct mr_table *mrt); - static int ip_mr_forward(struct net *net, struct mr_table *mrt, struct sk_buff *skb, struct mfc_cache *cache, int local); @@ -133,7 +131,6 @@ static int ipmr_cache_report(struct mr_table *mrt, struct sk_buff *pkt, vifi_t vifi, int assert); static int __ipmr_fill_mroute(struct mr_table *mrt, struct sk_buff *skb, struct mfc_cache *c, struct rtmsg *rtm); -static void mroute_clean_tables(struct mr_table *mrt); static void ipmr_expire_process(unsigned long arg); #ifdef CONFIG_IP_MROUTE_MULTIPLE_TABLES @@ -274,7 +271,7 @@ static void __net_exit ipmr_rules_exit(struct net *net) list_for_each_entry_safe(mrt, next, &net->ipv4.mr_tables, list) { list_del(&mrt->list); - ipmr_free_table(mrt); + kfree(mrt); } fib_rules_unregister(net->ipv4.mr_rules_ops); } @@ -302,7 +299,7 @@ static int __net_init ipmr_rules_init(struct net *net) static void __net_exit ipmr_rules_exit(struct net *net) { - ipmr_free_table(net->ipv4.mrt); + kfree(net->ipv4.mrt); } #endif @@ -339,13 +336,6 @@ static struct mr_table *ipmr_new_table(struct net *net, u32 id) return mrt; } -static void ipmr_free_table(struct mr_table *mrt) -{ - del_timer_sync(&mrt->ipmr_expire_timer); - mroute_clean_tables(mrt); - kfree(mrt); -} - /* Service routines creating virtual interfaces: DVMRP tunnels and PIMREG */ static void ipmr_del_tunnel(struct net_device *dev, struct vifctl *v) diff --git a/trunk/net/ipv4/netfilter/nf_nat_sip.c b/trunk/net/ipv4/netfilter/nf_nat_sip.c index 9c87cde28ff8..ea4a23813d26 100644 --- a/trunk/net/ipv4/netfilter/nf_nat_sip.c +++ b/trunk/net/ipv4/netfilter/nf_nat_sip.c @@ -148,7 +148,7 @@ static unsigned int ip_nat_sip(struct sk_buff *skb, unsigned int dataoff, if (ct_sip_parse_header_uri(ct, *dptr, NULL, *datalen, hdr, NULL, &matchoff, &matchlen, &addr, &port) > 0) { - unsigned int olen, matchend, poff, plen, buflen, n; + unsigned int matchend, poff, plen, buflen, n; char buffer[sizeof("nnn.nnn.nnn.nnn:nnnnn")]; /* We're only interested in headers related to this @@ -163,18 +163,17 @@ static unsigned int ip_nat_sip(struct sk_buff *skb, unsigned int dataoff, goto next; } - olen = *datalen; if (!map_addr(skb, dataoff, dptr, datalen, matchoff, matchlen, &addr, port)) return NF_DROP; - matchend = matchoff + matchlen + *datalen - olen; + matchend = matchoff + matchlen; /* The maddr= parameter (RFC 2361) specifies where to send * the reply. */ if (ct_sip_parse_address_param(ct, *dptr, matchend, *datalen, "maddr=", &poff, &plen, - &addr, true) > 0 && + &addr) > 0 && addr.ip == ct->tuplehash[dir].tuple.src.u3.ip && addr.ip != ct->tuplehash[!dir].tuple.dst.u3.ip) { buflen = sprintf(buffer, "%pI4", @@ -188,7 +187,7 @@ static unsigned int ip_nat_sip(struct sk_buff *skb, unsigned int dataoff, * from which the server received the request. */ if (ct_sip_parse_address_param(ct, *dptr, matchend, *datalen, "received=", &poff, &plen, - &addr, false) > 0 && + &addr) > 0 && addr.ip == ct->tuplehash[dir].tuple.dst.u3.ip && addr.ip != ct->tuplehash[!dir].tuple.src.u3.ip) { buflen = sprintf(buffer, "%pI4", @@ -502,10 +501,7 @@ static unsigned int ip_nat_sdp_media(struct sk_buff *skb, unsigned int dataoff, ret = nf_ct_expect_related(rtcp_exp); if (ret == 0) break; - else if (ret == -EBUSY) { - nf_ct_unexpect_related(rtp_exp); - continue; - } else if (ret < 0) { + else if (ret != -EBUSY) { nf_ct_unexpect_related(rtp_exp); port = 0; break; diff --git a/trunk/net/ipv4/raw.c b/trunk/net/ipv4/raw.c index d23c6571ba1c..ff0f071969ea 100644 --- a/trunk/net/ipv4/raw.c +++ b/trunk/net/ipv4/raw.c @@ -131,20 +131,18 @@ static struct sock *__raw_v4_lookup(struct net *net, struct sock *sk, * 0 - deliver * 1 - block */ -static int icmp_filter(const struct sock *sk, const struct sk_buff *skb) +static __inline__ int icmp_filter(struct sock *sk, struct sk_buff *skb) { - struct icmphdr _hdr; - const struct icmphdr *hdr; + int type; - hdr = skb_header_pointer(skb, skb_transport_offset(skb), - sizeof(_hdr), &_hdr); - if (!hdr) + if (!pskb_may_pull(skb, sizeof(struct icmphdr))) return 1; - if (hdr->type < 32) { + type = icmp_hdr(skb)->type; + if (type < 32) { __u32 data = raw_sk(sk)->filter.data; - return ((1U << hdr->type) & data) != 0; + return ((1 << type) & data) != 0; } /* Do not block unknown ICMP types */ diff --git a/trunk/net/ipv4/route.c b/trunk/net/ipv4/route.c index fd9af60397b5..c035251beb07 100644 --- a/trunk/net/ipv4/route.c +++ b/trunk/net/ipv4/route.c @@ -70,6 +70,7 @@ #include #include #include +#include #include #include #include @@ -79,6 +80,7 @@ #include #include #include +#include #include #include #include @@ -86,9 +88,11 @@ #include #include #include +#include #include #include #include +#include #include #include #include @@ -202,6 +206,11 @@ EXPORT_SYMBOL(ip_tos2prio); static DEFINE_PER_CPU(struct rt_cache_stat, rt_cache_stat); #define RT_CACHE_STAT_INC(field) __this_cpu_inc(rt_cache_stat.field) +static inline int rt_genid(struct net *net) +{ + return atomic_read(&net->ipv4.rt_genid); +} + #ifdef CONFIG_PROC_FS static void *rt_cache_seq_start(struct seq_file *seq, loff_t *pos) { @@ -442,9 +451,27 @@ static inline bool rt_is_expired(const struct rtable *rth) return rth->rt_genid != rt_genid(dev_net(rth->dst.dev)); } -void rt_cache_flush(struct net *net) +/* + * Perturbation of rt_genid by a small quantity [1..256] + * Using 8 bits of shuffling ensure we can call rt_cache_invalidate() + * many times (2^24) without giving recent rt_genid. + * Jenkins hash is strong enough that litle changes of rt_genid are OK. + */ +static void rt_cache_invalidate(struct net *net) +{ + unsigned char shuffle; + + get_random_bytes(&shuffle, sizeof(shuffle)); + atomic_add(shuffle + 1U, &net->ipv4.rt_genid); +} + +/* + * delay < 0 : invalidate cache (fast : entries will be deleted later) + * delay >= 0 : invalidate & flush cache (can be long) + */ +void rt_cache_flush(struct net *net, int delay) { - rt_genid_bump(net); + rt_cache_invalidate(net); } static struct neighbour *ipv4_neigh_lookup(const struct dst_entry *dst, @@ -911,14 +938,12 @@ static u32 __ip_rt_update_pmtu(struct rtable *rt, struct flowi4 *fl4, u32 mtu) if (mtu < ip_rt_min_pmtu) mtu = ip_rt_min_pmtu; - rcu_read_lock(); if (fib_lookup(dev_net(rt->dst.dev), fl4, &res) == 0) { struct fib_nh *nh = &FIB_RES_NH(res); update_or_create_fnhe(nh, fl4->daddr, 0, mtu, jiffies + ip_rt_mtu_expires); } - rcu_read_unlock(); return mtu; } @@ -935,7 +960,7 @@ static void ip_rt_update_pmtu(struct dst_entry *dst, struct sock *sk, dst->obsolete = DST_OBSOLETE_KILL; } else { rt->rt_pmtu = mtu; - rt->dst.expires = max(1UL, jiffies + ip_rt_mtu_expires); + dst_set_expires(&rt->dst, ip_rt_mtu_expires); } } @@ -1242,7 +1267,7 @@ static void ipv4_dst_destroy(struct dst_entry *dst) { struct rtable *rt = (struct rtable *) dst; - if (!list_empty(&rt->rt_uncached)) { + if (dst->flags & DST_NOCACHE) { spin_lock_bh(&rt_uncached_lock); list_del(&rt->rt_uncached); spin_unlock_bh(&rt_uncached_lock); @@ -2007,6 +2032,7 @@ struct rtable *__ip_route_output_key(struct net *net, struct flowi4 *fl4) } dev_out = net->loopback_dev; fl4->flowi4_oif = dev_out->ifindex; + res.fi = NULL; flags |= RTCF_LOCAL; goto make_route; } @@ -2322,7 +2348,7 @@ int ip_rt_dump(struct sk_buff *skb, struct netlink_callback *cb) void ip_rt_multicast_event(struct in_device *in_dev) { - rt_cache_flush(dev_net(in_dev->dev)); + rt_cache_flush(dev_net(in_dev->dev), 0); } #ifdef CONFIG_SYSCTL @@ -2331,7 +2357,16 @@ static int ipv4_sysctl_rtcache_flush(ctl_table *__ctl, int write, size_t *lenp, loff_t *ppos) { if (write) { - rt_cache_flush((struct net *)__ctl->extra1); + int flush_delay; + ctl_table ctl; + struct net *net; + + memcpy(&ctl, __ctl, sizeof(ctl)); + ctl.data = &flush_delay; + proc_dointvec(&ctl, write, buffer, lenp, ppos); + + net = (struct net *)__ctl->extra1; + rt_cache_flush(net, flush_delay); return 0; } @@ -2501,7 +2536,8 @@ static __net_initdata struct pernet_operations sysctl_route_ops = { static __net_init int rt_genid_init(struct net *net) { - atomic_set(&net->rt_genid, 0); + get_random_bytes(&net->ipv4.rt_genid, + sizeof(net->ipv4.rt_genid)); get_random_bytes(&net->ipv4.dev_addr_genid, sizeof(net->ipv4.dev_addr_genid)); return 0; diff --git a/trunk/net/ipv4/tcp.c b/trunk/net/ipv4/tcp.c index 5f6419341821..e7e6eeae49c0 100644 --- a/trunk/net/ipv4/tcp.c +++ b/trunk/net/ipv4/tcp.c @@ -811,9 +811,7 @@ static unsigned int tcp_xmit_size_goal(struct sock *sk, u32 mss_now, old_size_goal + mss_now > xmit_size_goal)) { xmit_size_goal = old_size_goal; } else { - tp->xmit_size_goal_segs = - min_t(u16, xmit_size_goal / mss_now, - sk->sk_gso_max_segs); + tp->xmit_size_goal_segs = xmit_size_goal / mss_now; xmit_size_goal = tp->xmit_size_goal_segs * mss_now; } } @@ -1762,14 +1760,8 @@ int tcp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, } #ifdef CONFIG_NET_DMA - if (tp->ucopy.dma_chan) { - if (tp->rcv_wnd == 0 && - !skb_queue_empty(&sk->sk_async_wait_queue)) { - tcp_service_net_dma(sk, true); - tcp_cleanup_rbuf(sk, copied); - } else - dma_async_memcpy_issue_pending(tp->ucopy.dma_chan); - } + if (tp->ucopy.dma_chan) + dma_async_memcpy_issue_pending(tp->ucopy.dma_chan); #endif if (copied >= target) { /* Do not sleep, just process backlog. */ @@ -2331,17 +2323,10 @@ static int tcp_repair_options_est(struct tcp_sock *tp, tp->rx_opt.mss_clamp = opt.opt_val; break; case TCPOPT_WINDOW: - { - u16 snd_wscale = opt.opt_val & 0xFFFF; - u16 rcv_wscale = opt.opt_val >> 16; - - if (snd_wscale > 14 || rcv_wscale > 14) - return -EFBIG; + if (opt.opt_val > 14) + return -EFBIG; - tp->rx_opt.snd_wscale = snd_wscale; - tp->rx_opt.rcv_wscale = rcv_wscale; - tp->rx_opt.wscale_ok = 1; - } + tp->rx_opt.snd_wscale = opt.opt_val; break; case TCPOPT_SACK_PERM: if (opt.opt_val != 0) diff --git a/trunk/net/ipv4/tcp_cong.c b/trunk/net/ipv4/tcp_cong.c index 1432cdb0644c..4d4db16e336e 100644 --- a/trunk/net/ipv4/tcp_cong.c +++ b/trunk/net/ipv4/tcp_cong.c @@ -291,8 +291,7 @@ bool tcp_is_cwnd_limited(const struct sock *sk, u32 in_flight) left = tp->snd_cwnd - in_flight; if (sk_can_gso(sk) && left * sysctl_tcp_tso_win_divisor < tp->snd_cwnd && - left * tp->mss_cache < sk->sk_gso_max_size && - left < sk->sk_gso_max_segs) + left * tp->mss_cache < sk->sk_gso_max_size) return true; return left <= tcp_max_tso_deferred_mss(tp); } diff --git a/trunk/net/ipv4/tcp_input.c b/trunk/net/ipv4/tcp_input.c index d377f4854cb8..2fd2bc9e3c64 100644 --- a/trunk/net/ipv4/tcp_input.c +++ b/trunk/net/ipv4/tcp_input.c @@ -2926,14 +2926,13 @@ static void tcp_enter_recovery(struct sock *sk, bool ece_ack) * tcp_xmit_retransmit_queue(). */ static void tcp_fastretrans_alert(struct sock *sk, int pkts_acked, - int prior_sacked, bool is_dupack, + int newly_acked_sacked, bool is_dupack, int flag) { struct inet_connection_sock *icsk = inet_csk(sk); struct tcp_sock *tp = tcp_sk(sk); int do_lost = is_dupack || ((flag & FLAG_DATA_SACKED) && (tcp_fackets_out(tp) > tp->reordering)); - int newly_acked_sacked = 0; int fast_rexmit = 0; if (WARN_ON(!tp->packets_out && tp->sacked_out)) @@ -2993,7 +2992,6 @@ static void tcp_fastretrans_alert(struct sock *sk, int pkts_acked, tcp_add_reno_sack(sk); } else do_lost = tcp_try_undo_partial(sk, pkts_acked); - newly_acked_sacked = pkts_acked + tp->sacked_out - prior_sacked; break; case TCP_CA_Loss: if (flag & FLAG_DATA_ACKED) @@ -3015,7 +3013,6 @@ static void tcp_fastretrans_alert(struct sock *sk, int pkts_acked, if (is_dupack) tcp_add_reno_sack(sk); } - newly_acked_sacked = pkts_acked + tp->sacked_out - prior_sacked; if (icsk->icsk_ca_state <= TCP_CA_Disorder) tcp_try_undo_dsack(sk); @@ -3593,6 +3590,7 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag) int prior_packets; int prior_sacked = tp->sacked_out; int pkts_acked = 0; + int newly_acked_sacked = 0; bool frto_cwnd = false; /* If the ack is older than previous acks @@ -3668,6 +3666,8 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag) flag |= tcp_clean_rtx_queue(sk, prior_fackets, prior_snd_una); pkts_acked = prior_packets - tp->packets_out; + newly_acked_sacked = (prior_packets - prior_sacked) - + (tp->packets_out - tp->sacked_out); if (tp->frto_counter) frto_cwnd = tcp_process_frto(sk, flag); @@ -3681,7 +3681,7 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag) tcp_may_raise_cwnd(sk, flag)) tcp_cong_avoid(sk, ack, prior_in_flight); is_dupack = !(flag & (FLAG_SND_UNA_ADVANCED | FLAG_NOT_DUP)); - tcp_fastretrans_alert(sk, pkts_acked, prior_sacked, + tcp_fastretrans_alert(sk, pkts_acked, newly_acked_sacked, is_dupack, flag); } else { if ((flag & FLAG_DATA_ACKED) && !frto_cwnd) @@ -3698,7 +3698,7 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag) no_queue: /* If data was DSACKed, see if we can undo a cwnd reduction. */ if (flag & FLAG_DSACKING_ACK) - tcp_fastretrans_alert(sk, pkts_acked, prior_sacked, + tcp_fastretrans_alert(sk, pkts_acked, newly_acked_sacked, is_dupack, flag); /* If this ack opens up a zero window, clear backoff. It was * being used to time the probes, and is probably far higher than @@ -3718,7 +3718,8 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag) */ if (TCP_SKB_CB(skb)->sacked) { flag |= tcp_sacktag_write_queue(sk, skb, prior_snd_una); - tcp_fastretrans_alert(sk, pkts_acked, prior_sacked, + newly_acked_sacked = tp->sacked_out - prior_sacked; + tcp_fastretrans_alert(sk, pkts_acked, newly_acked_sacked, is_dupack, flag); } @@ -4661,7 +4662,7 @@ static void tcp_data_queue(struct sock *sk, struct sk_buff *skb) if (eaten > 0) kfree_skb_partial(skb, fragstolen); - if (!sock_flag(sk, SOCK_DEAD)) + else if (!sock_flag(sk, SOCK_DEAD)) sk->sk_data_ready(sk, 0); return; } @@ -5391,8 +5392,6 @@ int tcp_rcv_established(struct sock *sk, struct sk_buff *skb, { struct tcp_sock *tp = tcp_sk(sk); - if (unlikely(sk->sk_rx_dst == NULL)) - inet_csk(sk)->icsk_af_ops->sk_rx_dst_set(sk, skb); /* * Header prediction. * The code loosely follows the one in the famous @@ -5556,7 +5555,8 @@ int tcp_rcv_established(struct sock *sk, struct sk_buff *skb, #endif if (eaten) kfree_skb_partial(skb, fragstolen); - sk->sk_data_ready(sk, 0); + else + sk->sk_data_ready(sk, 0); return 0; } } @@ -5605,7 +5605,7 @@ void tcp_finish_connect(struct sock *sk, struct sk_buff *skb) tcp_set_state(sk, TCP_ESTABLISHED); if (skb != NULL) { - icsk->icsk_af_ops->sk_rx_dst_set(sk, skb); + inet_sk_rx_dst_set(sk, skb); security_inet_conn_established(sk, skb); } diff --git a/trunk/net/ipv4/tcp_ipv4.c b/trunk/net/ipv4/tcp_ipv4.c index 00a748d14062..42b2a6a73092 100644 --- a/trunk/net/ipv4/tcp_ipv4.c +++ b/trunk/net/ipv4/tcp_ipv4.c @@ -417,12 +417,10 @@ void tcp_v4_err(struct sk_buff *icmp_skb, u32 info) if (code == ICMP_FRAG_NEEDED) { /* PMTU discovery (RFC1191) */ tp->mtu_info = info; - if (!sock_owned_by_user(sk)) { + if (!sock_owned_by_user(sk)) tcp_v4_mtu_reduced(sk); - } else { - if (!test_and_set_bit(TCP_MTU_REDUCED_DEFERRED, &tp->tsq_flags)) - sock_hold(sk); - } + else + set_bit(TCP_MTU_REDUCED_DEFERRED, &tp->tsq_flags); goto out; } @@ -1464,7 +1462,6 @@ struct sock *tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb, goto exit_nonewsk; newsk->sk_gso_type = SKB_GSO_TCPV4; - inet_sk_rx_dst_set(newsk, skb); newtp = tcp_sk(newsk); newinet = inet_sk(newsk); @@ -1630,6 +1627,9 @@ int tcp_v4_do_rcv(struct sock *sk, struct sk_buff *skb) sk->sk_rx_dst = NULL; } } + if (unlikely(sk->sk_rx_dst == NULL)) + inet_sk_rx_dst_set(sk, skb); + if (tcp_rcv_established(sk, skb, tcp_hdr(skb), skb->len)) { rsk = sk; goto reset; @@ -1872,21 +1872,10 @@ static struct timewait_sock_ops tcp_timewait_sock_ops = { .twsk_destructor= tcp_twsk_destructor, }; -void inet_sk_rx_dst_set(struct sock *sk, const struct sk_buff *skb) -{ - struct dst_entry *dst = skb_dst(skb); - - dst_hold(dst); - sk->sk_rx_dst = dst; - inet_sk(sk)->rx_dst_ifindex = skb->skb_iif; -} -EXPORT_SYMBOL(inet_sk_rx_dst_set); - const struct inet_connection_sock_af_ops ipv4_specific = { .queue_xmit = ip_queue_xmit, .send_check = tcp_v4_send_check, .rebuild_header = inet_sk_rebuild_header, - .sk_rx_dst_set = inet_sk_rx_dst_set, .conn_request = tcp_v4_conn_request, .syn_recv_sock = tcp_v4_syn_recv_sock, .net_header_len = sizeof(struct iphdr), diff --git a/trunk/net/ipv4/tcp_metrics.c b/trunk/net/ipv4/tcp_metrics.c index 0abe67bb4d3a..2288a6399e1e 100644 --- a/trunk/net/ipv4/tcp_metrics.c +++ b/trunk/net/ipv4/tcp_metrics.c @@ -731,18 +731,6 @@ static int __net_init tcp_net_metrics_init(struct net *net) static void __net_exit tcp_net_metrics_exit(struct net *net) { - unsigned int i; - - for (i = 0; i < (1U << net->ipv4.tcp_metrics_hash_log) ; i++) { - struct tcp_metrics_block *tm, *next; - - tm = rcu_dereference_protected(net->ipv4.tcp_metrics_hash[i].chain, 1); - while (tm) { - next = rcu_dereference_protected(tm->tcpm_next, 1); - kfree(tm); - tm = next; - } - } kfree(net->ipv4.tcp_metrics_hash); } diff --git a/trunk/net/ipv4/tcp_minisocks.c b/trunk/net/ipv4/tcp_minisocks.c index 6ff7f10dce9d..232a90c3ec86 100644 --- a/trunk/net/ipv4/tcp_minisocks.c +++ b/trunk/net/ipv4/tcp_minisocks.c @@ -387,6 +387,8 @@ struct sock *tcp_create_openreq_child(struct sock *sk, struct request_sock *req, struct tcp_sock *oldtp = tcp_sk(sk); struct tcp_cookie_values *oldcvp = oldtp->cookie_values; + inet_sk_rx_dst_set(newsk, skb); + /* TCP Cookie Transactions require space for the cookie pair, * as it differs for each connection. There is no need to * copy any s_data_payload stored at the original socket. diff --git a/trunk/net/ipv4/tcp_output.c b/trunk/net/ipv4/tcp_output.c index d04632673a9e..3f1bcff0b10b 100644 --- a/trunk/net/ipv4/tcp_output.c +++ b/trunk/net/ipv4/tcp_output.c @@ -910,18 +910,14 @@ void tcp_release_cb(struct sock *sk) if (flags & (1UL << TCP_TSQ_DEFERRED)) tcp_tsq_handler(sk); - if (flags & (1UL << TCP_WRITE_TIMER_DEFERRED)) { + if (flags & (1UL << TCP_WRITE_TIMER_DEFERRED)) tcp_write_timer_handler(sk); - __sock_put(sk); - } - if (flags & (1UL << TCP_DELACK_TIMER_DEFERRED)) { + + if (flags & (1UL << TCP_DELACK_TIMER_DEFERRED)) tcp_delack_timer_handler(sk); - __sock_put(sk); - } - if (flags & (1UL << TCP_MTU_REDUCED_DEFERRED)) { + + if (flags & (1UL << TCP_MTU_REDUCED_DEFERRED)) sk->sk_prot->mtu_reduced(sk); - __sock_put(sk); - } } EXPORT_SYMBOL(tcp_release_cb); @@ -944,7 +940,7 @@ void __init tcp_tasklet_init(void) * We cant xmit new skbs from this context, as we might already * hold qdisc lock. */ -static void tcp_wfree(struct sk_buff *skb) +void tcp_wfree(struct sk_buff *skb) { struct sock *sk = skb->sk; struct tcp_sock *tp = tcp_sk(sk); @@ -1526,21 +1522,21 @@ static void tcp_cwnd_validate(struct sock *sk) * when we would be allowed to send the split-due-to-Nagle skb fully. */ static unsigned int tcp_mss_split_point(const struct sock *sk, const struct sk_buff *skb, - unsigned int mss_now, unsigned int max_segs) + unsigned int mss_now, unsigned int cwnd) { const struct tcp_sock *tp = tcp_sk(sk); - u32 needed, window, max_len; + u32 needed, window, cwnd_len; window = tcp_wnd_end(tp) - TCP_SKB_CB(skb)->seq; - max_len = mss_now * max_segs; + cwnd_len = mss_now * cwnd; - if (likely(max_len <= window && skb != tcp_write_queue_tail(sk))) - return max_len; + if (likely(cwnd_len <= window && skb != tcp_write_queue_tail(sk))) + return cwnd_len; needed = min(skb->len, window); - if (max_len <= needed) - return max_len; + if (cwnd_len <= needed) + return cwnd_len; return needed - needed % mss_now; } @@ -1769,8 +1765,7 @@ static bool tcp_tso_should_defer(struct sock *sk, struct sk_buff *skb) limit = min(send_win, cong_win); /* If a full-sized TSO skb can be sent, do it. */ - if (limit >= min_t(unsigned int, sk->sk_gso_max_size, - sk->sk_gso_max_segs * tp->mss_cache)) + if (limit >= sk->sk_gso_max_size) goto send_now; /* Middle in queue won't get any more data, full sendable already? */ @@ -2004,9 +1999,7 @@ static bool tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle, limit = mss_now; if (tso_segs > 1 && !tcp_urg_mode(tp)) limit = tcp_mss_split_point(sk, skb, mss_now, - min_t(unsigned int, - cwnd_quota, - sk->sk_gso_max_segs)); + cwnd_quota); if (skb->len > limit && unlikely(tso_fragment(sk, skb, limit, mss_now, gfp))) diff --git a/trunk/net/ipv4/tcp_timer.c b/trunk/net/ipv4/tcp_timer.c index b774a03bd1dc..6df36ad55a38 100644 --- a/trunk/net/ipv4/tcp_timer.c +++ b/trunk/net/ipv4/tcp_timer.c @@ -252,8 +252,7 @@ static void tcp_delack_timer(unsigned long data) inet_csk(sk)->icsk_ack.blocked = 1; NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_DELAYEDACKLOCKED); /* deleguate our work to tcp_release_cb() */ - if (!test_and_set_bit(TCP_DELACK_TIMER_DEFERRED, &tcp_sk(sk)->tsq_flags)) - sock_hold(sk); + set_bit(TCP_WRITE_TIMER_DEFERRED, &tcp_sk(sk)->tsq_flags); } bh_unlock_sock(sk); sock_put(sk); @@ -482,8 +481,7 @@ static void tcp_write_timer(unsigned long data) tcp_write_timer_handler(sk); } else { /* deleguate our work to tcp_release_cb() */ - if (!test_and_set_bit(TCP_WRITE_TIMER_DEFERRED, &tcp_sk(sk)->tsq_flags)) - sock_hold(sk); + set_bit(TCP_WRITE_TIMER_DEFERRED, &tcp_sk(sk)->tsq_flags); } bh_unlock_sock(sk); sock_put(sk); diff --git a/trunk/net/ipv4/udp.c b/trunk/net/ipv4/udp.c index 2814f66dac64..b4c3582a991f 100644 --- a/trunk/net/ipv4/udp.c +++ b/trunk/net/ipv4/udp.c @@ -758,7 +758,7 @@ static int udp_send_skb(struct sk_buff *skb, struct flowi4 *fl4) uh->check = CSUM_MANGLED_0; send: - err = ip_send_skb(sock_net(sk), skb); + err = ip_send_skb(skb); if (err) { if (err == -ENOBUFS && !inet->recverr) { UDP_INC_STATS_USER(sock_net(sk), @@ -1226,11 +1226,6 @@ int udp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, if (unlikely(err)) { trace_kfree_skb(skb, udp_recvmsg); - if (!peeked) { - atomic_inc(&sk->sk_drops); - UDP_INC_STATS_USER(sock_net(sk), - UDP_MIB_INERRORS, is_udplite); - } goto out_free; } diff --git a/trunk/net/ipv6/addrconf.c b/trunk/net/ipv6/addrconf.c index 6bc85f7c31e3..79181819a24f 100644 --- a/trunk/net/ipv6/addrconf.c +++ b/trunk/net/ipv6/addrconf.c @@ -494,7 +494,8 @@ static void addrconf_forward_change(struct net *net, __s32 newf) struct net_device *dev; struct inet6_dev *idev; - for_each_netdev(net, dev) { + rcu_read_lock(); + for_each_netdev_rcu(net, dev) { idev = __in6_dev_get(dev); if (idev) { int changed = (!idev->cnf.forwarding) ^ (!newf); @@ -503,6 +504,7 @@ static void addrconf_forward_change(struct net *net, __s32 newf) dev_forward_change(idev); } } + rcu_read_unlock(); } static int addrconf_fixup_forwarding(struct ctl_table *table, int *p, int newf) diff --git a/trunk/net/ipv6/esp6.c b/trunk/net/ipv6/esp6.c index 282f3723ee19..6dc7fd353ef5 100644 --- a/trunk/net/ipv6/esp6.c +++ b/trunk/net/ipv6/esp6.c @@ -167,6 +167,8 @@ static int esp6_output(struct xfrm_state *x, struct sk_buff *skb) struct esp_data *esp = x->data; /* skb is pure payload to encrypt */ + err = -ENOMEM; + aead = esp->aead; alen = crypto_aead_authsize(aead); @@ -201,10 +203,8 @@ static int esp6_output(struct xfrm_state *x, struct sk_buff *skb) } tmp = esp_alloc_tmp(aead, nfrags + sglists, seqhilen); - if (!tmp) { - err = -ENOMEM; + if (!tmp) goto error; - } seqhi = esp_tmp_seqhi(tmp); iv = esp_tmp_iv(aead, tmp, seqhilen); diff --git a/trunk/net/ipv6/inet6_connection_sock.c b/trunk/net/ipv6/inet6_connection_sock.c index c4f934176cab..0251a6005be8 100644 --- a/trunk/net/ipv6/inet6_connection_sock.c +++ b/trunk/net/ipv6/inet6_connection_sock.c @@ -175,12 +175,33 @@ void __inet6_csk_dst_store(struct sock *sk, struct dst_entry *dst, const struct in6_addr *saddr) { __ip6_dst_store(sk, dst, daddr, saddr); + +#ifdef CONFIG_XFRM + { + struct rt6_info *rt = (struct rt6_info *)dst; + rt->rt6i_flow_cache_genid = atomic_read(&flow_cache_genid); + } +#endif } static inline struct dst_entry *__inet6_csk_dst_check(struct sock *sk, u32 cookie) { - return __sk_dst_check(sk, cookie); + struct dst_entry *dst; + + dst = __sk_dst_check(sk, cookie); + +#ifdef CONFIG_XFRM + if (dst) { + struct rt6_info *rt = (struct rt6_info *)dst; + if (rt->rt6i_flow_cache_genid != atomic_read(&flow_cache_genid)) { + __sk_dst_reset(sk); + dst = NULL; + } + } +#endif + + return dst; } static struct dst_entry *inet6_csk_route_socket(struct sock *sk, diff --git a/trunk/net/ipv6/ip6_fib.c b/trunk/net/ipv6/ip6_fib.c index 286acfc21250..13690d650c3e 100644 --- a/trunk/net/ipv6/ip6_fib.c +++ b/trunk/net/ipv6/ip6_fib.c @@ -819,10 +819,6 @@ int fib6_add(struct fib6_node *root, struct rt6_info *rt, struct nl_info *info) offsetof(struct rt6_info, rt6i_src), allow_create, replace_required); - if (IS_ERR(sn)) { - err = PTR_ERR(sn); - sn = NULL; - } if (!sn) { /* If it is failed, discard just allocated root, and then (in st_failure) stale node diff --git a/trunk/net/ipv6/mip6.c b/trunk/net/ipv6/mip6.c index 0f9bdc5ee9f3..5b087c31d87b 100644 --- a/trunk/net/ipv6/mip6.c +++ b/trunk/net/ipv6/mip6.c @@ -86,30 +86,28 @@ static int mip6_mh_len(int type) static int mip6_mh_filter(struct sock *sk, struct sk_buff *skb) { - struct ip6_mh _hdr; - const struct ip6_mh *mh; + struct ip6_mh *mh; - mh = skb_header_pointer(skb, skb_transport_offset(skb), - sizeof(_hdr), &_hdr); - if (!mh) + if (!pskb_may_pull(skb, (skb_transport_offset(skb)) + 8) || + !pskb_may_pull(skb, (skb_transport_offset(skb) + + ((skb_transport_header(skb)[1] + 1) << 3)))) return -1; - if (((mh->ip6mh_hdrlen + 1) << 3) > skb->len) - return -1; + mh = (struct ip6_mh *)skb_transport_header(skb); if (mh->ip6mh_hdrlen < mip6_mh_len(mh->ip6mh_type)) { LIMIT_NETDEBUG(KERN_DEBUG "mip6: MH message too short: %d vs >=%d\n", mh->ip6mh_hdrlen, mip6_mh_len(mh->ip6mh_type)); - mip6_param_prob(skb, 0, offsetof(struct ip6_mh, ip6mh_hdrlen) + - skb_network_header_len(skb)); + mip6_param_prob(skb, 0, ((&mh->ip6mh_hdrlen) - + skb_network_header(skb))); return -1; } if (mh->ip6mh_proto != IPPROTO_NONE) { LIMIT_NETDEBUG(KERN_DEBUG "mip6: MH invalid payload proto = %d\n", mh->ip6mh_proto); - mip6_param_prob(skb, 0, offsetof(struct ip6_mh, ip6mh_proto) + - skb_network_header_len(skb)); + mip6_param_prob(skb, 0, ((&mh->ip6mh_proto) - + skb_network_header(skb))); return -1; } diff --git a/trunk/net/ipv6/proc.c b/trunk/net/ipv6/proc.c index 745a32042950..da2e92d05c15 100644 --- a/trunk/net/ipv6/proc.c +++ b/trunk/net/ipv6/proc.c @@ -307,10 +307,10 @@ static int __net_init ipv6_proc_init_net(struct net *net) goto proc_dev_snmp6_fail; return 0; -proc_dev_snmp6_fail: - proc_net_remove(net, "snmp6"); proc_snmp6_fail: proc_net_remove(net, "sockstat6"); +proc_dev_snmp6_fail: + proc_net_remove(net, "dev_snmp6"); return -ENOMEM; } diff --git a/trunk/net/ipv6/raw.c b/trunk/net/ipv6/raw.c index 4a5f78b50495..ef0579d5bca6 100644 --- a/trunk/net/ipv6/raw.c +++ b/trunk/net/ipv6/raw.c @@ -107,20 +107,21 @@ static struct sock *__raw_v6_lookup(struct net *net, struct sock *sk, * 0 - deliver * 1 - block */ -static int icmpv6_filter(const struct sock *sk, const struct sk_buff *skb) +static __inline__ int icmpv6_filter(struct sock *sk, struct sk_buff *skb) { - struct icmp6hdr *_hdr; - const struct icmp6hdr *hdr; + struct icmp6hdr *icmph; + struct raw6_sock *rp = raw6_sk(sk); + + if (pskb_may_pull(skb, sizeof(struct icmp6hdr))) { + __u32 *data = &rp->filter.data[0]; + int bit_nr; - hdr = skb_header_pointer(skb, skb_transport_offset(skb), - sizeof(_hdr), &_hdr); - if (hdr) { - const __u32 *data = &raw6_sk(sk)->filter.data[0]; - unsigned int type = hdr->icmp6_type; + icmph = (struct icmp6hdr *) skb->data; + bit_nr = icmph->icmp6_type; - return (data[type >> 5] & (1U << (type & 31))) != 0; + return (data[bit_nr >> 5] & (1 << (bit_nr & 31))) != 0; } - return 1; + return 0; } #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) diff --git a/trunk/net/ipv6/route.c b/trunk/net/ipv6/route.c index 854e4018d205..8e80fd279100 100644 --- a/trunk/net/ipv6/route.c +++ b/trunk/net/ipv6/route.c @@ -226,7 +226,7 @@ static struct rt6_info ip6_null_entry_template = { .dst = { .__refcnt = ATOMIC_INIT(1), .__use = 1, - .obsolete = DST_OBSOLETE_FORCE_CHK, + .obsolete = -1, .error = -ENETUNREACH, .input = ip6_pkt_discard, .output = ip6_pkt_discard_out, @@ -246,7 +246,7 @@ static struct rt6_info ip6_prohibit_entry_template = { .dst = { .__refcnt = ATOMIC_INIT(1), .__use = 1, - .obsolete = DST_OBSOLETE_FORCE_CHK, + .obsolete = -1, .error = -EACCES, .input = ip6_pkt_prohibit, .output = ip6_pkt_prohibit_out, @@ -261,7 +261,7 @@ static struct rt6_info ip6_blk_hole_entry_template = { .dst = { .__refcnt = ATOMIC_INIT(1), .__use = 1, - .obsolete = DST_OBSOLETE_FORCE_CHK, + .obsolete = -1, .error = -EINVAL, .input = dst_discard, .output = dst_discard, @@ -281,14 +281,13 @@ static inline struct rt6_info *ip6_dst_alloc(struct net *net, struct fib6_table *table) { struct rt6_info *rt = dst_alloc(&net->ipv6.ip6_dst_ops, dev, - 0, DST_OBSOLETE_FORCE_CHK, flags); + 0, DST_OBSOLETE_NONE, flags); if (rt) { struct dst_entry *dst = &rt->dst; memset(dst + 1, 0, sizeof(*rt) - sizeof(*dst)); rt6_init_peer(rt, table ? &table->tb6_peers : net->ipv6.peers); - rt->rt6i_genid = rt_genid(net); } return rt; } @@ -1032,13 +1031,6 @@ static struct dst_entry *ip6_dst_check(struct dst_entry *dst, u32 cookie) rt = (struct rt6_info *) dst; - /* All IPV6 dsts are created with ->obsolete set to the value - * DST_OBSOLETE_FORCE_CHK which forces validation calls down - * into this function always. - */ - if (rt->rt6i_genid != rt_genid(dev_net(rt->dst.dev))) - return NULL; - if (rt->rt6i_node && (rt->rt6i_node->fn_sernum == cookie)) { if (rt->rt6i_peer_genid != rt6_peer_genid()) { if (!rt6_has_peer(rt)) @@ -1405,6 +1397,8 @@ int ip6_route_add(struct fib6_config *cfg) goto out; } + rt->dst.obsolete = -1; + if (cfg->fc_flags & RTF_EXPIRES) rt6_set_expires(rt, jiffies + clock_t_to_jiffies(cfg->fc_expires)); @@ -2086,6 +2080,7 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev, rt->dst.input = ip6_input; rt->dst.output = ip6_output; rt->rt6i_idev = idev; + rt->dst.obsolete = -1; rt->rt6i_flags = RTF_UP | RTF_NONEXTHOP; if (anycast) diff --git a/trunk/net/ipv6/tcp_ipv6.c b/trunk/net/ipv6/tcp_ipv6.c index acd32e3f1b68..c66b90f71c9b 100644 --- a/trunk/net/ipv6/tcp_ipv6.c +++ b/trunk/net/ipv6/tcp_ipv6.c @@ -94,18 +94,6 @@ static struct tcp_md5sig_key *tcp_v6_md5_do_lookup(struct sock *sk, } #endif -static void inet6_sk_rx_dst_set(struct sock *sk, const struct sk_buff *skb) -{ - struct dst_entry *dst = skb_dst(skb); - const struct rt6_info *rt = (const struct rt6_info *)dst; - - dst_hold(dst); - sk->sk_rx_dst = dst; - inet_sk(sk)->rx_dst_ifindex = skb->skb_iif; - if (rt->rt6i_node) - inet6_sk(sk)->rx_dst_cookie = rt->rt6i_node->fn_sernum; -} - static void tcp_v6_hash(struct sock *sk) { if (sk->sk_state != TCP_CLOSE) { @@ -403,9 +391,8 @@ static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, tp->mtu_info = ntohl(info); if (!sock_owned_by_user(sk)) tcp_v6_mtu_reduced(sk); - else if (!test_and_set_bit(TCP_MTU_REDUCED_DEFERRED, - &tp->tsq_flags)) - sock_hold(sk); + else + set_bit(TCP_MTU_REDUCED_DEFERRED, &tp->tsq_flags); goto out; } @@ -1283,7 +1270,6 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb, newsk->sk_gso_type = SKB_GSO_TCPV6; __ip6_dst_store(newsk, dst, NULL, NULL); - inet6_sk_rx_dst_set(newsk, skb); newtcp6sk = (struct tcp6_sock *)newsk; inet_sk(newsk)->pinet6 = &newtcp6sk->inet6; @@ -1461,17 +1447,7 @@ static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb) opt_skb = skb_clone(skb, sk_gfp_atomic(sk, GFP_ATOMIC)); if (sk->sk_state == TCP_ESTABLISHED) { /* Fast path */ - struct dst_entry *dst = sk->sk_rx_dst; - sock_rps_save_rxhash(sk, skb); - if (dst) { - if (inet_sk(sk)->rx_dst_ifindex != skb->skb_iif || - dst->ops->check(dst, np->rx_dst_cookie) == NULL) { - dst_release(dst); - sk->sk_rx_dst = NULL; - } - } - if (tcp_rcv_established(sk, skb, tcp_hdr(skb), skb->len)) goto reset; if (opt_skb) @@ -1729,9 +1705,9 @@ static void tcp_v6_early_demux(struct sk_buff *skb) struct dst_entry *dst = sk->sk_rx_dst; struct inet_sock *icsk = inet_sk(sk); if (dst) - dst = dst_check(dst, inet6_sk(sk)->rx_dst_cookie); + dst = dst_check(dst, 0); if (dst && - icsk->rx_dst_ifindex == skb->skb_iif) + icsk->rx_dst_ifindex == inet6_iif(skb)) skb_dst_set_noref(skb, dst); } } @@ -1747,7 +1723,6 @@ static const struct inet_connection_sock_af_ops ipv6_specific = { .queue_xmit = inet6_csk_xmit, .send_check = tcp_v6_send_check, .rebuild_header = inet6_sk_rebuild_header, - .sk_rx_dst_set = inet6_sk_rx_dst_set, .conn_request = tcp_v6_conn_request, .syn_recv_sock = tcp_v6_syn_recv_sock, .net_header_len = sizeof(struct ipv6hdr), @@ -1779,7 +1754,6 @@ static const struct inet_connection_sock_af_ops ipv6_mapped = { .queue_xmit = ip_queue_xmit, .send_check = tcp_v4_send_check, .rebuild_header = inet_sk_rebuild_header, - .sk_rx_dst_set = inet_sk_rx_dst_set, .conn_request = tcp_v6_conn_request, .syn_recv_sock = tcp_v6_syn_recv_sock, .net_header_len = sizeof(struct iphdr), diff --git a/trunk/net/ipv6/udp.c b/trunk/net/ipv6/udp.c index 07e2bfef6845..99d0077b56b8 100644 --- a/trunk/net/ipv6/udp.c +++ b/trunk/net/ipv6/udp.c @@ -394,17 +394,6 @@ int udpv6_recvmsg(struct kiocb *iocb, struct sock *sk, } if (unlikely(err)) { trace_kfree_skb(skb, udpv6_recvmsg); - if (!peeked) { - atomic_inc(&sk->sk_drops); - if (is_udp4) - UDP_INC_STATS_USER(sock_net(sk), - UDP_MIB_INERRORS, - is_udplite); - else - UDP6_INC_STATS_USER(sock_net(sk), - UDP_MIB_INERRORS, - is_udplite); - } goto out_free; } if (!peeked) { diff --git a/trunk/net/ipv6/xfrm6_policy.c b/trunk/net/ipv6/xfrm6_policy.c index f8c4c08ffb60..ef39812107b1 100644 --- a/trunk/net/ipv6/xfrm6_policy.c +++ b/trunk/net/ipv6/xfrm6_policy.c @@ -73,13 +73,6 @@ static int xfrm6_get_tos(const struct flowi *fl) return 0; } -static void xfrm6_init_dst(struct net *net, struct xfrm_dst *xdst) -{ - struct rt6_info *rt = (struct rt6_info *)xdst; - - rt6_init_peer(rt, net->ipv6.peers); -} - static int xfrm6_init_path(struct xfrm_dst *path, struct dst_entry *dst, int nfheader_len) { @@ -293,7 +286,6 @@ static struct xfrm_policy_afinfo xfrm6_policy_afinfo = { .get_saddr = xfrm6_get_saddr, .decode_session = _decode_session6, .get_tos = xfrm6_get_tos, - .init_dst = xfrm6_init_dst, .init_path = xfrm6_init_path, .fill_dst = xfrm6_fill_dst, .blackhole_route = ip6_blackhole_route, diff --git a/trunk/net/irda/ircomm/ircomm_param.c b/trunk/net/irda/ircomm/ircomm_param.c index 308939128359..8b915f3ac3b9 100644 --- a/trunk/net/irda/ircomm/ircomm_param.c +++ b/trunk/net/irda/ircomm/ircomm_param.c @@ -99,6 +99,7 @@ pi_param_info_t ircomm_param_info = { pi_major_call_table, 3, 0x0f, 4 }; */ int ircomm_param_request(struct ircomm_tty_cb *self, __u8 pi, int flush) { + struct tty_struct *tty; unsigned long flags; struct sk_buff *skb; int count; @@ -108,6 +109,10 @@ int ircomm_param_request(struct ircomm_tty_cb *self, __u8 pi, int flush) IRDA_ASSERT(self != NULL, return -1;); IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;); + tty = self->tty; + if (!tty) + return 0; + /* Make sure we don't send parameters for raw mode */ if (self->service_type == IRCOMM_3_WIRE_RAW) return 0; diff --git a/trunk/net/irda/ircomm/ircomm_tty.c b/trunk/net/irda/ircomm/ircomm_tty.c index 95a3a7a336ba..6b9d5a0e42f9 100644 --- a/trunk/net/irda/ircomm/ircomm_tty.c +++ b/trunk/net/irda/ircomm/ircomm_tty.c @@ -52,8 +52,6 @@ #include #include -static int ircomm_tty_install(struct tty_driver *driver, - struct tty_struct *tty); static int ircomm_tty_open(struct tty_struct *tty, struct file *filp); static void ircomm_tty_close(struct tty_struct * tty, struct file *filp); static int ircomm_tty_write(struct tty_struct * tty, @@ -84,7 +82,6 @@ static struct tty_driver *driver; static hashbin_t *ircomm_tty = NULL; static const struct tty_operations ops = { - .install = ircomm_tty_install, .open = ircomm_tty_open, .close = ircomm_tty_close, .write = ircomm_tty_write, @@ -107,35 +104,6 @@ static const struct tty_operations ops = { #endif /* CONFIG_PROC_FS */ }; -static void ircomm_port_raise_dtr_rts(struct tty_port *port, int raise) -{ - struct ircomm_tty_cb *self = container_of(port, struct ircomm_tty_cb, - port); - /* - * Here, we use to lock those two guys, but as ircomm_param_request() - * does it itself, I don't see the point (and I see the deadlock). - * Jean II - */ - if (raise) - self->settings.dte |= IRCOMM_RTS | IRCOMM_DTR; - else - self->settings.dte &= ~(IRCOMM_RTS | IRCOMM_DTR); - - ircomm_param_request(self, IRCOMM_DTE, TRUE); -} - -static int ircomm_port_carrier_raised(struct tty_port *port) -{ - struct ircomm_tty_cb *self = container_of(port, struct ircomm_tty_cb, - port); - return self->settings.dce & IRCOMM_CD; -} - -static const struct tty_port_operations ircomm_port_ops = { - .dtr_rts = ircomm_port_raise_dtr_rts, - .carrier_raised = ircomm_port_carrier_raised, -}; - /* * Function ircomm_tty_init() * @@ -226,7 +194,7 @@ static int ircomm_tty_startup(struct ircomm_tty_cb *self) IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;); /* Check if already open */ - if (test_and_set_bit(ASYNCB_INITIALIZED, &self->port.flags)) { + if (test_and_set_bit(ASYNC_B_INITIALIZED, &self->flags)) { IRDA_DEBUG(2, "%s(), already open so break out!\n", __func__ ); return 0; } @@ -263,7 +231,7 @@ static int ircomm_tty_startup(struct ircomm_tty_cb *self) return 0; err: - clear_bit(ASYNCB_INITIALIZED, &self->port.flags); + clear_bit(ASYNC_B_INITIALIZED, &self->flags); return ret; } @@ -274,62 +242,72 @@ static int ircomm_tty_startup(struct ircomm_tty_cb *self) * */ static int ircomm_tty_block_til_ready(struct ircomm_tty_cb *self, - struct tty_struct *tty, struct file *filp) + struct file *filp) { - struct tty_port *port = &self->port; DECLARE_WAITQUEUE(wait, current); int retval; int do_clocal = 0, extra_count = 0; unsigned long flags; + struct tty_struct *tty; IRDA_DEBUG(2, "%s()\n", __func__ ); + tty = self->tty; + /* * If non-blocking mode is set, or the port is not enabled, * then make the check up front and then exit. */ if (filp->f_flags & O_NONBLOCK || tty->flags & (1 << TTY_IO_ERROR)){ /* nonblock mode is set or port is not enabled */ - port->flags |= ASYNC_NORMAL_ACTIVE; + self->flags |= ASYNC_NORMAL_ACTIVE; IRDA_DEBUG(1, "%s(), O_NONBLOCK requested!\n", __func__ ); return 0; } - if (tty->termios.c_cflag & CLOCAL) { + if (tty->termios->c_cflag & CLOCAL) { IRDA_DEBUG(1, "%s(), doing CLOCAL!\n", __func__ ); do_clocal = 1; } /* Wait for carrier detect and the line to become * free (i.e., not in use by the callout). While we are in - * this loop, port->count is dropped by one, so that + * this loop, self->open_count is dropped by one, so that * mgsl_close() knows when to free things. We restore it upon * exit, either normal or abnormal. */ retval = 0; - add_wait_queue(&port->open_wait, &wait); + add_wait_queue(&self->open_wait, &wait); IRDA_DEBUG(2, "%s(%d):block_til_ready before block on %s open_count=%d\n", - __FILE__, __LINE__, tty->driver->name, port->count); + __FILE__,__LINE__, tty->driver->name, self->open_count ); - spin_lock_irqsave(&port->lock, flags); + /* As far as I can see, we protect open_count - Jean II */ + spin_lock_irqsave(&self->spinlock, flags); if (!tty_hung_up_p(filp)) { extra_count = 1; - port->count--; + self->open_count--; } - spin_unlock_irqrestore(&port->lock, flags); - port->blocked_open++; + spin_unlock_irqrestore(&self->spinlock, flags); + self->blocked_open++; while (1) { - if (tty->termios.c_cflag & CBAUD) - tty_port_raise_dtr_rts(port); + if (tty->termios->c_cflag & CBAUD) { + /* Here, we use to lock those two guys, but + * as ircomm_param_request() does it itself, + * I don't see the point (and I see the deadlock). + * Jean II */ + self->settings.dte |= IRCOMM_RTS + IRCOMM_DTR; + + ircomm_param_request(self, IRCOMM_DTE, TRUE); + } current->state = TASK_INTERRUPTIBLE; if (tty_hung_up_p(filp) || - !test_bit(ASYNCB_INITIALIZED, &port->flags)) { - retval = (port->flags & ASYNC_HUP_NOTIFY) ? + !test_bit(ASYNC_B_INITIALIZED, &self->flags)) { + retval = (self->flags & ASYNC_HUP_NOTIFY) ? -EAGAIN : -ERESTARTSYS; break; } @@ -339,8 +317,8 @@ static int ircomm_tty_block_til_ready(struct ircomm_tty_cb *self, * specified, we cannot return before the IrCOMM link is * ready */ - if (!test_bit(ASYNCB_CLOSING, &port->flags) && - (do_clocal || tty_port_carrier_raised(port)) && + if (!test_bit(ASYNC_B_CLOSING, &self->flags) && + (do_clocal || (self->settings.dce & IRCOMM_CD)) && self->state == IRCOMM_TTY_READY) { break; @@ -352,36 +330,46 @@ static int ircomm_tty_block_til_ready(struct ircomm_tty_cb *self, } IRDA_DEBUG(1, "%s(%d):block_til_ready blocking on %s open_count=%d\n", - __FILE__, __LINE__, tty->driver->name, port->count); + __FILE__,__LINE__, tty->driver->name, self->open_count ); schedule(); } __set_current_state(TASK_RUNNING); - remove_wait_queue(&port->open_wait, &wait); + remove_wait_queue(&self->open_wait, &wait); if (extra_count) { /* ++ is not atomic, so this should be protected - Jean II */ - spin_lock_irqsave(&port->lock, flags); - port->count++; - spin_unlock_irqrestore(&port->lock, flags); + spin_lock_irqsave(&self->spinlock, flags); + self->open_count++; + spin_unlock_irqrestore(&self->spinlock, flags); } - port->blocked_open--; + self->blocked_open--; IRDA_DEBUG(1, "%s(%d):block_til_ready after blocking on %s open_count=%d\n", - __FILE__, __LINE__, tty->driver->name, port->count); + __FILE__,__LINE__, tty->driver->name, self->open_count); if (!retval) - port->flags |= ASYNC_NORMAL_ACTIVE; + self->flags |= ASYNC_NORMAL_ACTIVE; return retval; } - -static int ircomm_tty_install(struct tty_driver *driver, struct tty_struct *tty) +/* + * Function ircomm_tty_open (tty, filp) + * + * This routine is called when a particular tty device is opened. This + * routine is mandatory; if this routine is not filled in, the attempted + * open will fail with ENODEV. + */ +static int ircomm_tty_open(struct tty_struct *tty, struct file *filp) { struct ircomm_tty_cb *self; unsigned int line = tty->index; + unsigned long flags; + int ret; + + IRDA_DEBUG(2, "%s()\n", __func__ ); /* Check if instance already exists */ self = hashbin_lock_find(ircomm_tty, line, NULL); @@ -393,8 +381,6 @@ static int ircomm_tty_install(struct tty_driver *driver, struct tty_struct *tty) return -ENOMEM; } - tty_port_init(&self->port); - self->port.ops = &ircomm_port_ops; self->magic = IRCOMM_TTY_MAGIC; self->flow = FLOW_STOP; @@ -402,9 +388,13 @@ static int ircomm_tty_install(struct tty_driver *driver, struct tty_struct *tty) INIT_WORK(&self->tqueue, ircomm_tty_do_softint); self->max_header_size = IRCOMM_TTY_HDR_UNINITIALISED; self->max_data_size = IRCOMM_TTY_DATA_UNINITIALISED; + self->close_delay = 5*HZ/10; + self->closing_wait = 30*HZ; /* Init some important stuff */ init_timer(&self->watchdog_timer); + init_waitqueue_head(&self->open_wait); + init_waitqueue_head(&self->close_wait); spin_lock_init(&self->spinlock); /* @@ -414,48 +404,31 @@ static int ircomm_tty_install(struct tty_driver *driver, struct tty_struct *tty) * * Note this is completely usafe and doesn't work properly */ - tty->termios.c_iflag = 0; - tty->termios.c_oflag = 0; + tty->termios->c_iflag = 0; + tty->termios->c_oflag = 0; /* Insert into hash */ hashbin_insert(ircomm_tty, (irda_queue_t *) self, line, NULL); } - - return tty_port_install(&self->port, driver, tty); -} - -/* - * Function ircomm_tty_open (tty, filp) - * - * This routine is called when a particular tty device is opened. This - * routine is mandatory; if this routine is not filled in, the attempted - * open will fail with ENODEV. - */ -static int ircomm_tty_open(struct tty_struct *tty, struct file *filp) -{ - struct ircomm_tty_cb *self = tty->driver_data; - unsigned long flags; - int ret; - - IRDA_DEBUG(2, "%s()\n", __func__ ); - /* ++ is not atomic, so this should be protected - Jean II */ - spin_lock_irqsave(&self->port.lock, flags); - self->port.count++; - spin_unlock_irqrestore(&self->port.lock, flags); - tty_port_tty_set(&self->port, tty); + spin_lock_irqsave(&self->spinlock, flags); + self->open_count++; + + tty->driver_data = self; + self->tty = tty; + spin_unlock_irqrestore(&self->spinlock, flags); IRDA_DEBUG(1, "%s(), %s%d, count = %d\n", __func__ , tty->driver->name, - self->line, self->port.count); + self->line, self->open_count); /* Not really used by us, but lets do it anyway */ - tty->low_latency = (self->port.flags & ASYNC_LOW_LATENCY) ? 1 : 0; + self->tty->low_latency = (self->flags & ASYNC_LOW_LATENCY) ? 1 : 0; /* * If the port is the middle of closing, bail out now */ if (tty_hung_up_p(filp) || - test_bit(ASYNCB_CLOSING, &self->port.flags)) { + test_bit(ASYNC_B_CLOSING, &self->flags)) { /* Hm, why are we blocking on ASYNC_CLOSING if we * do return -EAGAIN/-ERESTARTSYS below anyway? @@ -465,15 +438,14 @@ static int ircomm_tty_open(struct tty_struct *tty, struct file *filp) * probably better sleep uninterruptible? */ - if (wait_event_interruptible(self->port.close_wait, - !test_bit(ASYNCB_CLOSING, &self->port.flags))) { + if (wait_event_interruptible(self->close_wait, !test_bit(ASYNC_B_CLOSING, &self->flags))) { IRDA_WARNING("%s - got signal while blocking on ASYNC_CLOSING!\n", __func__); return -ERESTARTSYS; } #ifdef SERIAL_DO_RESTART - return (self->port.flags & ASYNC_HUP_NOTIFY) ? + return (self->flags & ASYNC_HUP_NOTIFY) ? -EAGAIN : -ERESTARTSYS; #else return -EAGAIN; @@ -481,7 +453,7 @@ static int ircomm_tty_open(struct tty_struct *tty, struct file *filp) } /* Check if this is a "normal" ircomm device, or an irlpt device */ - if (self->line < 0x10) { + if (line < 0x10) { self->service_type = IRCOMM_3_WIRE | IRCOMM_9_WIRE; self->settings.service_type = IRCOMM_9_WIRE; /* 9 wire as default */ /* Jan Kiszka -> add DSR/RI -> Conform to IrCOMM spec */ @@ -497,7 +469,7 @@ static int ircomm_tty_open(struct tty_struct *tty, struct file *filp) if (ret) return ret; - ret = ircomm_tty_block_til_ready(self, tty, filp); + ret = ircomm_tty_block_til_ready(self, filp); if (ret) { IRDA_DEBUG(2, "%s(), returning after block_til_ready with %d\n", __func__ , @@ -517,22 +489,81 @@ static int ircomm_tty_open(struct tty_struct *tty, struct file *filp) static void ircomm_tty_close(struct tty_struct *tty, struct file *filp) { struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data; - struct tty_port *port = &self->port; + unsigned long flags; IRDA_DEBUG(0, "%s()\n", __func__ ); IRDA_ASSERT(self != NULL, return;); IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;); - if (tty_port_close_start(port, tty, filp) == 0) + spin_lock_irqsave(&self->spinlock, flags); + + if (tty_hung_up_p(filp)) { + spin_unlock_irqrestore(&self->spinlock, flags); + + IRDA_DEBUG(0, "%s(), returning 1\n", __func__ ); + return; + } + + if ((tty->count == 1) && (self->open_count != 1)) { + /* + * Uh, oh. tty->count is 1, which means that the tty + * structure will be freed. state->count should always + * be one in these conditions. If it's greater than + * one, we've got real problems, since it means the + * serial port won't be shutdown. + */ + IRDA_DEBUG(0, "%s(), bad serial port count; " + "tty->count is 1, state->count is %d\n", __func__ , + self->open_count); + self->open_count = 1; + } + + if (--self->open_count < 0) { + IRDA_ERROR("%s(), bad serial port count for ttys%d: %d\n", + __func__, self->line, self->open_count); + self->open_count = 0; + } + if (self->open_count) { + spin_unlock_irqrestore(&self->spinlock, flags); + + IRDA_DEBUG(0, "%s(), open count > 0\n", __func__ ); return; + } + + /* Hum... Should be test_and_set_bit ??? - Jean II */ + set_bit(ASYNC_B_CLOSING, &self->flags); + + /* We need to unlock here (we were unlocking at the end of this + * function), because tty_wait_until_sent() may schedule. + * I don't know if the rest should be protected somehow, + * so someone should check. - Jean II */ + spin_unlock_irqrestore(&self->spinlock, flags); + + /* + * Now we wait for the transmit buffer to clear; and we notify + * the line discipline to only process XON/XOFF characters. + */ + tty->closing = 1; + if (self->closing_wait != ASYNC_CLOSING_WAIT_NONE) + tty_wait_until_sent_from_close(tty, self->closing_wait); ircomm_tty_shutdown(self); tty_driver_flush_buffer(tty); + tty_ldisc_flush(tty); + + tty->closing = 0; + self->tty = NULL; - tty_port_close_end(port, tty); - tty_port_tty_set(port, NULL); + if (self->blocked_open) { + if (self->close_delay) + schedule_timeout_interruptible(self->close_delay); + wake_up_interruptible(&self->open_wait); + } + + self->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING); + wake_up_interruptible(&self->close_wait); } /* @@ -575,7 +606,7 @@ static void ircomm_tty_do_softint(struct work_struct *work) if (!self || self->magic != IRCOMM_TTY_MAGIC) return; - tty = tty_port_tty_get(&self->port); + tty = self->tty; if (!tty) return; @@ -596,7 +627,7 @@ static void ircomm_tty_do_softint(struct work_struct *work) } if (tty->hw_stopped) - goto put; + return; /* Unlink transmit buffer */ spin_lock_irqsave(&self->spinlock, flags); @@ -615,8 +646,6 @@ static void ircomm_tty_do_softint(struct work_struct *work) /* Check if user (still) wants to be waken up */ tty_wakeup(tty); -put: - tty_kref_put(tty); } /* @@ -851,7 +880,7 @@ static void ircomm_tty_throttle(struct tty_struct *tty) ircomm_tty_send_xchar(tty, STOP_CHAR(tty)); /* Hardware flow control? */ - if (tty->termios.c_cflag & CRTSCTS) { + if (tty->termios->c_cflag & CRTSCTS) { self->settings.dte &= ~IRCOMM_RTS; self->settings.dte |= IRCOMM_DELTA_RTS; @@ -883,7 +912,7 @@ static void ircomm_tty_unthrottle(struct tty_struct *tty) } /* Using hardware flow control? */ - if (tty->termios.c_cflag & CRTSCTS) { + if (tty->termios->c_cflag & CRTSCTS) { self->settings.dte |= (IRCOMM_RTS|IRCOMM_DELTA_RTS); ircomm_param_request(self, IRCOMM_DTE, TRUE); @@ -926,7 +955,7 @@ static void ircomm_tty_shutdown(struct ircomm_tty_cb *self) IRDA_DEBUG(0, "%s()\n", __func__ ); - if (!test_and_clear_bit(ASYNCB_INITIALIZED, &self->port.flags)) + if (!test_and_clear_bit(ASYNC_B_INITIALIZED, &self->flags)) return; ircomm_tty_detach_cable(self); @@ -965,7 +994,6 @@ static void ircomm_tty_shutdown(struct ircomm_tty_cb *self) static void ircomm_tty_hangup(struct tty_struct *tty) { struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data; - struct tty_port *port = &self->port; unsigned long flags; IRDA_DEBUG(0, "%s()\n", __func__ ); @@ -976,17 +1004,14 @@ static void ircomm_tty_hangup(struct tty_struct *tty) /* ircomm_tty_flush_buffer(tty); */ ircomm_tty_shutdown(self); - spin_lock_irqsave(&port->lock, flags); - port->flags &= ~ASYNC_NORMAL_ACTIVE; - if (port->tty) { - set_bit(TTY_IO_ERROR, &port->tty->flags); - tty_kref_put(port->tty); - } - port->tty = NULL; - port->count = 0; - spin_unlock_irqrestore(&port->lock, flags); + /* I guess we need to lock here - Jean II */ + spin_lock_irqsave(&self->spinlock, flags); + self->flags &= ~ASYNC_NORMAL_ACTIVE; + self->tty = NULL; + self->open_count = 0; + spin_unlock_irqrestore(&self->spinlock, flags); - wake_up_interruptible(&port->open_wait); + wake_up_interruptible(&self->open_wait); } /* @@ -1046,20 +1071,20 @@ void ircomm_tty_check_modem_status(struct ircomm_tty_cb *self) IRDA_ASSERT(self != NULL, return;); IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;); - tty = tty_port_tty_get(&self->port); + tty = self->tty; status = self->settings.dce; if (status & IRCOMM_DCE_DELTA_ANY) { /*wake_up_interruptible(&self->delta_msr_wait);*/ } - if ((self->port.flags & ASYNC_CHECK_CD) && (status & IRCOMM_DELTA_CD)) { + if ((self->flags & ASYNC_CHECK_CD) && (status & IRCOMM_DELTA_CD)) { IRDA_DEBUG(2, "%s(), ircomm%d CD now %s...\n", __func__ , self->line, (status & IRCOMM_CD) ? "on" : "off"); if (status & IRCOMM_CD) { - wake_up_interruptible(&self->port.open_wait); + wake_up_interruptible(&self->open_wait); } else { IRDA_DEBUG(2, "%s(), Doing serial hangup..\n", __func__ ); @@ -1067,10 +1092,10 @@ void ircomm_tty_check_modem_status(struct ircomm_tty_cb *self) tty_hangup(tty); /* Hangup will remote the tty, so better break out */ - goto put; + return; } } - if (tty && tty_port_cts_enabled(&self->port)) { + if (self->flags & ASYNC_CTS_FLOW) { if (tty->hw_stopped) { if (status & IRCOMM_CTS) { IRDA_DEBUG(2, @@ -1078,10 +1103,10 @@ void ircomm_tty_check_modem_status(struct ircomm_tty_cb *self) tty->hw_stopped = 0; /* Wake up processes blocked on open */ - wake_up_interruptible(&self->port.open_wait); + wake_up_interruptible(&self->open_wait); schedule_work(&self->tqueue); - goto put; + return; } } else { if (!(status & IRCOMM_CTS)) { @@ -1091,8 +1116,6 @@ void ircomm_tty_check_modem_status(struct ircomm_tty_cb *self) } } } -put: - tty_kref_put(tty); } /* @@ -1105,7 +1128,6 @@ static int ircomm_tty_data_indication(void *instance, void *sap, struct sk_buff *skb) { struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance; - struct tty_struct *tty; IRDA_DEBUG(2, "%s()\n", __func__ ); @@ -1113,8 +1135,7 @@ static int ircomm_tty_data_indication(void *instance, void *sap, IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;); IRDA_ASSERT(skb != NULL, return -1;); - tty = tty_port_tty_get(&self->port); - if (!tty) { + if (!self->tty) { IRDA_DEBUG(0, "%s(), no tty!\n", __func__ ); return 0; } @@ -1125,7 +1146,7 @@ static int ircomm_tty_data_indication(void *instance, void *sap, * Devices like WinCE can do this, and since they don't send any * params, we can just as well declare the hardware for running. */ - if (tty->hw_stopped && (self->flow == FLOW_START)) { + if (self->tty->hw_stopped && (self->flow == FLOW_START)) { IRDA_DEBUG(0, "%s(), polling for line settings!\n", __func__ ); ircomm_param_request(self, IRCOMM_POLL, TRUE); @@ -1138,9 +1159,8 @@ static int ircomm_tty_data_indication(void *instance, void *sap, * Use flip buffer functions since the code may be called from interrupt * context */ - tty_insert_flip_string(tty, skb->data, skb->len); - tty_flip_buffer_push(tty); - tty_kref_put(tty); + tty_insert_flip_string(self->tty, skb->data, skb->len); + tty_flip_buffer_push(self->tty); /* No need to kfree_skb - see ircomm_ttp_data_indication() */ @@ -1191,13 +1211,12 @@ static void ircomm_tty_flow_indication(void *instance, void *sap, IRDA_ASSERT(self != NULL, return;); IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;); - tty = tty_port_tty_get(&self->port); + tty = self->tty; switch (cmd) { case FLOW_START: IRDA_DEBUG(2, "%s(), hw start!\n", __func__ ); - if (tty) - tty->hw_stopped = 0; + tty->hw_stopped = 0; /* ircomm_tty_do_softint will take care of the rest */ schedule_work(&self->tqueue); @@ -1205,19 +1224,15 @@ static void ircomm_tty_flow_indication(void *instance, void *sap, default: /* If we get here, something is very wrong, better stop */ case FLOW_STOP: IRDA_DEBUG(2, "%s(), hw stopped!\n", __func__ ); - if (tty) - tty->hw_stopped = 1; + tty->hw_stopped = 1; break; } - - tty_kref_put(tty); self->flow = cmd; } #ifdef CONFIG_PROC_FS static void ircomm_tty_line_info(struct ircomm_tty_cb *self, struct seq_file *m) { - struct tty_struct *tty; char sep; seq_printf(m, "State: %s\n", ircomm_tty_state[self->state]); @@ -1313,43 +1328,40 @@ static void ircomm_tty_line_info(struct ircomm_tty_cb *self, struct seq_file *m) seq_puts(m, "Flags:"); sep = ' '; - if (tty_port_cts_enabled(&self->port)) { + if (self->flags & ASYNC_CTS_FLOW) { seq_printf(m, "%cASYNC_CTS_FLOW", sep); sep = '|'; } - if (self->port.flags & ASYNC_CHECK_CD) { + if (self->flags & ASYNC_CHECK_CD) { seq_printf(m, "%cASYNC_CHECK_CD", sep); sep = '|'; } - if (self->port.flags & ASYNC_INITIALIZED) { + if (self->flags & ASYNC_INITIALIZED) { seq_printf(m, "%cASYNC_INITIALIZED", sep); sep = '|'; } - if (self->port.flags & ASYNC_LOW_LATENCY) { + if (self->flags & ASYNC_LOW_LATENCY) { seq_printf(m, "%cASYNC_LOW_LATENCY", sep); sep = '|'; } - if (self->port.flags & ASYNC_CLOSING) { + if (self->flags & ASYNC_CLOSING) { seq_printf(m, "%cASYNC_CLOSING", sep); sep = '|'; } - if (self->port.flags & ASYNC_NORMAL_ACTIVE) { + if (self->flags & ASYNC_NORMAL_ACTIVE) { seq_printf(m, "%cASYNC_NORMAL_ACTIVE", sep); sep = '|'; } seq_putc(m, '\n'); seq_printf(m, "Role: %s\n", self->client ? "client" : "server"); - seq_printf(m, "Open count: %d\n", self->port.count); + seq_printf(m, "Open count: %d\n", self->open_count); seq_printf(m, "Max data size: %d\n", self->max_data_size); seq_printf(m, "Max header size: %d\n", self->max_header_size); - tty = tty_port_tty_get(&self->port); - if (tty) { + if (self->tty) seq_printf(m, "Hardware: %s\n", - tty->hw_stopped ? "Stopped" : "Running"); - tty_kref_put(tty); - } + self->tty->hw_stopped ? "Stopped" : "Running"); } static int ircomm_tty_proc_show(struct seq_file *m, void *v) diff --git a/trunk/net/irda/ircomm/ircomm_tty_attach.c b/trunk/net/irda/ircomm/ircomm_tty_attach.c index edab393e0c82..b65d66e0d817 100644 --- a/trunk/net/irda/ircomm/ircomm_tty_attach.c +++ b/trunk/net/irda/ircomm/ircomm_tty_attach.c @@ -130,8 +130,6 @@ static int (*state[])(struct ircomm_tty_cb *self, IRCOMM_TTY_EVENT event, */ int ircomm_tty_attach_cable(struct ircomm_tty_cb *self) { - struct tty_struct *tty; - IRDA_DEBUG(0, "%s()\n", __func__ ); IRDA_ASSERT(self != NULL, return -1;); @@ -144,11 +142,7 @@ int ircomm_tty_attach_cable(struct ircomm_tty_cb *self) } /* Make sure nobody tries to write before the link is up */ - tty = tty_port_tty_get(&self->port); - if (tty) { - tty->hw_stopped = 1; - tty_kref_put(tty); - } + self->tty->hw_stopped = 1; ircomm_tty_ias_register(self); @@ -404,26 +398,23 @@ void ircomm_tty_disconnect_indication(void *instance, void *sap, struct sk_buff *skb) { struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance; - struct tty_struct *tty; IRDA_DEBUG(2, "%s()\n", __func__ ); IRDA_ASSERT(self != NULL, return;); IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;); - tty = tty_port_tty_get(&self->port); - if (!tty) + if (!self->tty) return; /* This will stop control data transfers */ self->flow = FLOW_STOP; /* Stop data transfers */ - tty->hw_stopped = 1; + self->tty->hw_stopped = 1; ircomm_tty_do_event(self, IRCOMM_TTY_DISCONNECT_INDICATION, NULL, NULL); - tty_kref_put(tty); } /* @@ -559,15 +550,12 @@ void ircomm_tty_connect_indication(void *instance, void *sap, */ void ircomm_tty_link_established(struct ircomm_tty_cb *self) { - struct tty_struct *tty; - IRDA_DEBUG(2, "%s()\n", __func__ ); IRDA_ASSERT(self != NULL, return;); IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;); - tty = tty_port_tty_get(&self->port); - if (!tty) + if (!self->tty) return; del_timer(&self->watchdog_timer); @@ -578,22 +566,19 @@ void ircomm_tty_link_established(struct ircomm_tty_cb *self) * will have to wait for the peer device (DCE) to raise the CTS * line. */ - if (tty_port_cts_enabled(&self->port) && - ((self->settings.dce & IRCOMM_CTS) == 0)) { + if ((self->flags & ASYNC_CTS_FLOW) && ((self->settings.dce & IRCOMM_CTS) == 0)) { IRDA_DEBUG(0, "%s(), waiting for CTS ...\n", __func__ ); - goto put; + return; } else { IRDA_DEBUG(1, "%s(), starting hardware!\n", __func__ ); - tty->hw_stopped = 0; + self->tty->hw_stopped = 0; /* Wake up processes blocked on open */ - wake_up_interruptible(&self->port.open_wait); + wake_up_interruptible(&self->open_wait); } schedule_work(&self->tqueue); -put: - tty_kref_put(tty); } /* @@ -992,17 +977,14 @@ static int ircomm_tty_state_ready(struct ircomm_tty_cb *self, ircomm_tty_next_state(self, IRCOMM_TTY_SEARCH); ircomm_tty_start_watchdog_timer(self, 3*HZ); - if (self->port.flags & ASYNC_CHECK_CD) { + if (self->flags & ASYNC_CHECK_CD) { /* Drop carrier */ self->settings.dce = IRCOMM_DELTA_CD; ircomm_tty_check_modem_status(self); } else { - struct tty_struct *tty = tty_port_tty_get(&self->port); IRDA_DEBUG(0, "%s(), hanging up!\n", __func__ ); - if (tty) { - tty_hangup(tty); - tty_kref_put(tty); - } + if (self->tty) + tty_hangup(self->tty); } break; default: diff --git a/trunk/net/irda/ircomm/ircomm_tty_ioctl.c b/trunk/net/irda/ircomm/ircomm_tty_ioctl.c index b343f50dc8d7..d0667d68351d 100644 --- a/trunk/net/irda/ircomm/ircomm_tty_ioctl.c +++ b/trunk/net/irda/ircomm/ircomm_tty_ioctl.c @@ -52,18 +52,17 @@ * Change speed of the driver. If the remote device is a DCE, then this * should make it change the speed of its serial port */ -static void ircomm_tty_change_speed(struct ircomm_tty_cb *self, - struct tty_struct *tty) +static void ircomm_tty_change_speed(struct ircomm_tty_cb *self) { unsigned int cflag, cval; int baud; IRDA_DEBUG(2, "%s()\n", __func__ ); - if (!self->ircomm) + if (!self->tty || !self->tty->termios || !self->ircomm) return; - cflag = tty->termios.c_cflag; + cflag = self->tty->termios->c_cflag; /* byte size and parity */ switch (cflag & CSIZE) { @@ -82,7 +81,7 @@ static void ircomm_tty_change_speed(struct ircomm_tty_cb *self, cval |= IRCOMM_PARITY_EVEN; /* Determine divisor based on baud rate */ - baud = tty_get_baud_rate(tty); + baud = tty_get_baud_rate(self->tty); if (!baud) baud = 9600; /* B0 transition handled in rs_set_termios */ @@ -91,19 +90,19 @@ static void ircomm_tty_change_speed(struct ircomm_tty_cb *self, /* CTS flow control flag and modem status interrupts */ if (cflag & CRTSCTS) { - self->port.flags |= ASYNC_CTS_FLOW; + self->flags |= ASYNC_CTS_FLOW; self->settings.flow_control |= IRCOMM_RTS_CTS_IN; /* This got me. Bummer. Jean II */ if (self->service_type == IRCOMM_3_WIRE_RAW) IRDA_WARNING("%s(), enabling RTS/CTS on link that doesn't support it (3-wire-raw)\n", __func__); } else { - self->port.flags &= ~ASYNC_CTS_FLOW; + self->flags &= ~ASYNC_CTS_FLOW; self->settings.flow_control &= ~IRCOMM_RTS_CTS_IN; } if (cflag & CLOCAL) - self->port.flags &= ~ASYNC_CHECK_CD; + self->flags &= ~ASYNC_CHECK_CD; else - self->port.flags |= ASYNC_CHECK_CD; + self->flags |= ASYNC_CHECK_CD; #if 0 /* * Set up parity check flag @@ -149,18 +148,18 @@ void ircomm_tty_set_termios(struct tty_struct *tty, struct ktermios *old_termios) { struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data; - unsigned int cflag = tty->termios.c_cflag; + unsigned int cflag = tty->termios->c_cflag; IRDA_DEBUG(2, "%s()\n", __func__ ); if ((cflag == old_termios->c_cflag) && - (RELEVANT_IFLAG(tty->termios.c_iflag) == + (RELEVANT_IFLAG(tty->termios->c_iflag) == RELEVANT_IFLAG(old_termios->c_iflag))) { return; } - ircomm_tty_change_speed(self, tty); + ircomm_tty_change_speed(self); /* Handle transition to B0 status */ if ((old_termios->c_cflag & CBAUD) && @@ -173,7 +172,7 @@ void ircomm_tty_set_termios(struct tty_struct *tty, if (!(old_termios->c_cflag & CBAUD) && (cflag & CBAUD)) { self->settings.dte |= IRCOMM_DTR; - if (!(tty->termios.c_cflag & CRTSCTS) || + if (!(tty->termios->c_cflag & CRTSCTS) || !test_bit(TTY_THROTTLED, &tty->flags)) { self->settings.dte |= IRCOMM_RTS; } @@ -182,7 +181,7 @@ void ircomm_tty_set_termios(struct tty_struct *tty, /* Handle turning off CRTSCTS */ if ((old_termios->c_cflag & CRTSCTS) && - !(tty->termios.c_cflag & CRTSCTS)) + !(tty->termios->c_cflag & CRTSCTS)) { tty->hw_stopped = 0; ircomm_tty_start(tty); @@ -271,10 +270,10 @@ static int ircomm_tty_get_serial_info(struct ircomm_tty_cb *self, memset(&info, 0, sizeof(info)); info.line = self->line; - info.flags = self->port.flags; + info.flags = self->flags; info.baud_base = self->settings.data_rate; - info.close_delay = self->port.close_delay; - info.closing_wait = self->port.closing_wait; + info.close_delay = self->close_delay; + info.closing_wait = self->closing_wait; /* For compatibility */ info.type = PORT_16550A; diff --git a/trunk/net/l2tp/l2tp_core.c b/trunk/net/l2tp/l2tp_core.c index 1a9f3723c13c..393355d37b47 100644 --- a/trunk/net/l2tp/l2tp_core.c +++ b/trunk/net/l2tp/l2tp_core.c @@ -1347,10 +1347,11 @@ static void l2tp_tunnel_free(struct l2tp_tunnel *tunnel) /* Remove from tunnel list */ spin_lock_bh(&pn->l2tp_tunnel_list_lock); list_del_rcu(&tunnel->list); - kfree_rcu(tunnel, rcu); spin_unlock_bh(&pn->l2tp_tunnel_list_lock); + synchronize_rcu(); atomic_dec(&l2tp_tunnel_count); + kfree(tunnel); } /* Create a socket for the tunnel, if one isn't set up by @@ -1501,8 +1502,6 @@ static int l2tp_tunnel_sock_create(u32 tunnel_id, u32 peer_tunnel_id, struct l2t return err; } -static struct lock_class_key l2tp_socket_class; - int l2tp_tunnel_create(struct net *net, int fd, int version, u32 tunnel_id, u32 peer_tunnel_id, struct l2tp_tunnel_cfg *cfg, struct l2tp_tunnel **tunnelp) { struct l2tp_tunnel *tunnel = NULL; @@ -1607,8 +1606,6 @@ int l2tp_tunnel_create(struct net *net, int fd, int version, u32 tunnel_id, u32 tunnel->old_sk_destruct = sk->sk_destruct; sk->sk_destruct = &l2tp_tunnel_destruct; tunnel->sock = sk; - lockdep_set_class_and_name(&sk->sk_lock.slock, &l2tp_socket_class, "l2tp_sock"); - sk->sk_allocation = GFP_ATOMIC; /* Add tunnel to our list */ diff --git a/trunk/net/l2tp/l2tp_core.h b/trunk/net/l2tp/l2tp_core.h index 56d583e083a7..a38ec6cdeee1 100644 --- a/trunk/net/l2tp/l2tp_core.h +++ b/trunk/net/l2tp/l2tp_core.h @@ -163,7 +163,6 @@ struct l2tp_tunnel_cfg { struct l2tp_tunnel { int magic; /* Should be L2TP_TUNNEL_MAGIC */ - struct rcu_head rcu; rwlock_t hlist_lock; /* protect session_hlist */ struct hlist_head session_hlist[L2TP_HASH_SIZE]; /* hashed list of sessions, diff --git a/trunk/net/l2tp/l2tp_eth.c b/trunk/net/l2tp/l2tp_eth.c index 3bfb34aaee29..f9ee74deeac2 100644 --- a/trunk/net/l2tp/l2tp_eth.c +++ b/trunk/net/l2tp/l2tp_eth.c @@ -153,7 +153,7 @@ static void l2tp_eth_dev_recv(struct l2tp_session *session, struct sk_buff *skb, print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, skb->data, length); } - if (!pskb_may_pull(skb, ETH_HLEN)) + if (!pskb_may_pull(skb, sizeof(ETH_HLEN))) goto error; secpath_reset(skb); diff --git a/trunk/net/l2tp/l2tp_ip6.c b/trunk/net/l2tp/l2tp_ip6.c index 927547171bc7..35e1e4bde587 100644 --- a/trunk/net/l2tp/l2tp_ip6.c +++ b/trunk/net/l2tp/l2tp_ip6.c @@ -410,7 +410,6 @@ static int l2tp_ip6_getname(struct socket *sock, struct sockaddr *uaddr, lsa->l2tp_family = AF_INET6; lsa->l2tp_flowinfo = 0; lsa->l2tp_scope_id = 0; - lsa->l2tp_unused = 0; if (peer) { if (!lsk->peer_conn_id) return -ENOTCONN; diff --git a/trunk/net/l2tp/l2tp_netlink.c b/trunk/net/l2tp/l2tp_netlink.c index 6f936358d664..d71cd9229a47 100644 --- a/trunk/net/l2tp/l2tp_netlink.c +++ b/trunk/net/l2tp/l2tp_netlink.c @@ -80,8 +80,8 @@ static int l2tp_nl_cmd_noop(struct sk_buff *skb, struct genl_info *info) hdr = genlmsg_put(msg, info->snd_pid, info->snd_seq, &l2tp_nl_family, 0, L2TP_CMD_NOOP); - if (!hdr) { - ret = -EMSGSIZE; + if (IS_ERR(hdr)) { + ret = PTR_ERR(hdr); goto err_out; } @@ -250,8 +250,8 @@ static int l2tp_nl_tunnel_send(struct sk_buff *skb, u32 pid, u32 seq, int flags, hdr = genlmsg_put(skb, pid, seq, &l2tp_nl_family, flags, L2TP_CMD_TUNNEL_GET); - if (!hdr) - return -EMSGSIZE; + if (IS_ERR(hdr)) + return PTR_ERR(hdr); if (nla_put_u8(skb, L2TP_ATTR_PROTO_VERSION, tunnel->version) || nla_put_u32(skb, L2TP_ATTR_CONN_ID, tunnel->tunnel_id) || @@ -617,8 +617,8 @@ static int l2tp_nl_session_send(struct sk_buff *skb, u32 pid, u32 seq, int flags sk = tunnel->sock; hdr = genlmsg_put(skb, pid, seq, &l2tp_nl_family, flags, L2TP_CMD_SESSION_GET); - if (!hdr) - return -EMSGSIZE; + if (IS_ERR(hdr)) + return PTR_ERR(hdr); if (nla_put_u32(skb, L2TP_ATTR_CONN_ID, tunnel->tunnel_id) || nla_put_u32(skb, L2TP_ATTR_SESSION_ID, session->session_id) || diff --git a/trunk/net/llc/af_llc.c b/trunk/net/llc/af_llc.c index c2190005a114..f6fe4d400502 100644 --- a/trunk/net/llc/af_llc.c +++ b/trunk/net/llc/af_llc.c @@ -969,13 +969,14 @@ static int llc_ui_getname(struct socket *sock, struct sockaddr *uaddr, struct sockaddr_llc sllc; struct sock *sk = sock->sk; struct llc_sock *llc = llc_sk(sk); - int rc = -EBADF; + int rc = 0; memset(&sllc, 0, sizeof(sllc)); lock_sock(sk); if (sock_flag(sk, SOCK_ZAPPED)) goto out; *uaddrlen = sizeof(sllc); + memset(uaddr, 0, *uaddrlen); if (peer) { rc = -ENOTCONN; if (sk->sk_state != TCP_ESTABLISHED) @@ -1205,7 +1206,7 @@ static int __init llc2_init(void) rc = llc_proc_init(); if (rc != 0) { printk(llc_proc_err_msg); - goto out_station; + goto out_unregister_llc_proto; } rc = llc_sysctl_init(); if (rc) { @@ -1225,8 +1226,7 @@ static int __init llc2_init(void) llc_sysctl_exit(); out_proc: llc_proc_exit(); -out_station: - llc_station_exit(); +out_unregister_llc_proto: proto_unregister(&llc_proto); goto out; } diff --git a/trunk/net/llc/llc_input.c b/trunk/net/llc/llc_input.c index dd3e83328ad5..e32cab44ea95 100644 --- a/trunk/net/llc/llc_input.c +++ b/trunk/net/llc/llc_input.c @@ -42,7 +42,6 @@ static void (*llc_type_handlers[2])(struct llc_sap *sap, void llc_add_pack(int type, void (*handler)(struct llc_sap *sap, struct sk_buff *skb)) { - smp_wmb(); /* ensure initialisation is complete before it's called */ if (type == LLC_DEST_SAP || type == LLC_DEST_CONN) llc_type_handlers[type - 1] = handler; } @@ -51,19 +50,11 @@ void llc_remove_pack(int type) { if (type == LLC_DEST_SAP || type == LLC_DEST_CONN) llc_type_handlers[type - 1] = NULL; - synchronize_net(); } void llc_set_station_handler(void (*handler)(struct sk_buff *skb)) { - /* Ensure initialisation is complete before it's called */ - if (handler) - smp_wmb(); - llc_station_handler = handler; - - if (!handler) - synchronize_net(); } /** @@ -159,8 +150,6 @@ int llc_rcv(struct sk_buff *skb, struct net_device *dev, int dest; int (*rcv)(struct sk_buff *, struct net_device *, struct packet_type *, struct net_device *); - void (*sta_handler)(struct sk_buff *skb); - void (*sap_handler)(struct llc_sap *sap, struct sk_buff *skb); if (!net_eq(dev_net(dev), &init_net)) goto drop; @@ -193,8 +182,7 @@ int llc_rcv(struct sk_buff *skb, struct net_device *dev, */ rcv = rcu_dereference(sap->rcv_func); dest = llc_pdu_type(skb); - sap_handler = dest ? ACCESS_ONCE(llc_type_handlers[dest - 1]) : NULL; - if (unlikely(!sap_handler)) { + if (unlikely(!dest || !llc_type_handlers[dest - 1])) { if (rcv) rcv(skb, dev, pt, orig_dev); else @@ -205,7 +193,7 @@ int llc_rcv(struct sk_buff *skb, struct net_device *dev, if (cskb) rcv(cskb, dev, pt, orig_dev); } - sap_handler(sap, skb); + llc_type_handlers[dest - 1](sap, skb); } llc_sap_put(sap); out: @@ -214,10 +202,9 @@ int llc_rcv(struct sk_buff *skb, struct net_device *dev, kfree_skb(skb); goto out; handle_station: - sta_handler = ACCESS_ONCE(llc_station_handler); - if (!sta_handler) + if (!llc_station_handler) goto drop; - sta_handler(skb); + llc_station_handler(skb); goto out; } diff --git a/trunk/net/llc/llc_station.c b/trunk/net/llc/llc_station.c index b2f2bac2c2a2..39a8d8924b9c 100644 --- a/trunk/net/llc/llc_station.c +++ b/trunk/net/llc/llc_station.c @@ -268,7 +268,7 @@ static int llc_station_ac_send_null_dsap_xid_c(struct sk_buff *skb) out: return rc; free: - kfree_skb(nskb); + kfree_skb(skb); goto out; } @@ -293,7 +293,7 @@ static int llc_station_ac_send_xid_r(struct sk_buff *skb) out: return rc; free: - kfree_skb(nskb); + kfree_skb(skb); goto out; } @@ -322,7 +322,7 @@ static int llc_station_ac_send_test_r(struct sk_buff *skb) out: return rc; free: - kfree_skb(nskb); + kfree_skb(skb); goto out; } @@ -687,8 +687,12 @@ static void llc_station_rcv(struct sk_buff *skb) llc_station_state_process(skb); } -void __init llc_station_init(void) +int __init llc_station_init(void) { + int rc = -ENOBUFS; + struct sk_buff *skb; + struct llc_station_state_ev *ev; + skb_queue_head_init(&llc_main_station.mac_pdu_q); skb_queue_head_init(&llc_main_station.ev_q.list); spin_lock_init(&llc_main_station.ev_q.lock); @@ -696,12 +700,23 @@ void __init llc_station_init(void) (unsigned long)&llc_main_station); llc_main_station.ack_timer.expires = jiffies + sysctl_llc_station_ack_timeout; - llc_main_station.maximum_retry = 1; - llc_main_station.state = LLC_STATION_STATE_UP; + skb = alloc_skb(0, GFP_ATOMIC); + if (!skb) + goto out; + rc = 0; llc_set_station_handler(llc_station_rcv); + ev = llc_station_ev(skb); + memset(ev, 0, sizeof(*ev)); + llc_main_station.maximum_retry = 1; + llc_main_station.state = LLC_STATION_STATE_DOWN; + ev->type = LLC_STATION_EV_TYPE_SIMPLE; + ev->prim_type = LLC_STATION_EV_ENABLE_WITHOUT_DUP_ADDR_CHECK; + rc = llc_station_next_state(skb); +out: + return rc; } -void llc_station_exit(void) +void __exit llc_station_exit(void) { llc_set_station_handler(NULL); } diff --git a/trunk/net/mac80211/cfg.c b/trunk/net/mac80211/cfg.c index a58c0b649ba1..d41974aacf51 100644 --- a/trunk/net/mac80211/cfg.c +++ b/trunk/net/mac80211/cfg.c @@ -1378,8 +1378,6 @@ static void mpath_set_pinfo(struct mesh_path *mpath, u8 *next_hop, else memset(next_hop, 0, ETH_ALEN); - memset(pinfo, 0, sizeof(*pinfo)); - pinfo->generation = mesh_paths_generation; pinfo->filled = MPATH_INFO_FRAME_QLEN | @@ -1398,6 +1396,7 @@ static void mpath_set_pinfo(struct mesh_path *mpath, u8 *next_hop, pinfo->discovery_timeout = jiffies_to_msecs(mpath->discovery_timeout); pinfo->discovery_retries = mpath->discovery_retries; + pinfo->flags = 0; if (mpath->flags & MESH_PATH_ACTIVE) pinfo->flags |= NL80211_MPATH_FLAG_ACTIVE; if (mpath->flags & MESH_PATH_RESOLVING) @@ -1406,8 +1405,10 @@ static void mpath_set_pinfo(struct mesh_path *mpath, u8 *next_hop, pinfo->flags |= NL80211_MPATH_FLAG_SN_VALID; if (mpath->flags & MESH_PATH_FIXED) pinfo->flags |= NL80211_MPATH_FLAG_FIXED; - if (mpath->flags & MESH_PATH_RESOLVED) - pinfo->flags |= NL80211_MPATH_FLAG_RESOLVED; + if (mpath->flags & MESH_PATH_RESOLVING) + pinfo->flags |= NL80211_MPATH_FLAG_RESOLVING; + + pinfo->flags = mpath->flags; } static int ieee80211_get_mpath(struct wiphy *wiphy, struct net_device *dev, diff --git a/trunk/net/mac80211/mesh.c b/trunk/net/mac80211/mesh.c index 85572353a7e3..6fac18c0423f 100644 --- a/trunk/net/mac80211/mesh.c +++ b/trunk/net/mac80211/mesh.c @@ -622,7 +622,6 @@ void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata) del_timer_sync(&sdata->u.mesh.housekeeping_timer); del_timer_sync(&sdata->u.mesh.mesh_path_root_timer); - del_timer_sync(&sdata->u.mesh.mesh_path_timer); /* * If the timer fired while we waited for it, it will have * requeued the work. Now the work will be running again @@ -635,8 +634,6 @@ void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata) local->fif_other_bss--; atomic_dec(&local->iff_allmultis); ieee80211_configure_filter(local); - - sdata->u.mesh.timers_running = 0; } static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata, diff --git a/trunk/net/mac80211/mlme.c b/trunk/net/mac80211/mlme.c index f76b83341cf9..cef0c9e79aba 100644 --- a/trunk/net/mac80211/mlme.c +++ b/trunk/net/mac80211/mlme.c @@ -1430,8 +1430,6 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, del_timer_sync(&sdata->u.mgd.bcn_mon_timer); del_timer_sync(&sdata->u.mgd.timer); del_timer_sync(&sdata->u.mgd.chswitch_timer); - - sdata->u.mgd.timers_running = 0; } void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata, @@ -3248,8 +3246,6 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata, goto out_unlock; err_clear: - memset(ifmgd->bssid, 0, ETH_ALEN); - ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BSSID); ifmgd->auth_data = NULL; err_free: kfree(auth_data); @@ -3441,8 +3437,6 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, err = 0; goto out; err_clear: - memset(ifmgd->bssid, 0, ETH_ALEN); - ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BSSID); ifmgd->assoc_data = NULL; err_free: kfree(assoc_data); diff --git a/trunk/net/mac80211/scan.c b/trunk/net/mac80211/scan.c index 839dd9737989..bcaee5d12839 100644 --- a/trunk/net/mac80211/scan.c +++ b/trunk/net/mac80211/scan.c @@ -299,7 +299,7 @@ static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted, if (local->scan_req != local->int_scan_req) cfg80211_scan_done(local->scan_req, aborted); local->scan_req = NULL; - rcu_assign_pointer(local->scan_sdata, NULL); + local->scan_sdata = NULL; local->scanning = 0; local->scan_channel = NULL; @@ -984,6 +984,7 @@ int ieee80211_request_sched_scan_stop(struct ieee80211_sub_if_data *sdata) kfree(local->sched_scan_ies.ie[i]); drv_sched_scan_stop(local, sdata); + rcu_assign_pointer(local->sched_scan_sdata, NULL); } out: mutex_unlock(&local->mtx); diff --git a/trunk/net/mac80211/tx.c b/trunk/net/mac80211/tx.c index c5e8c9c31f76..acf712ffb5e6 100644 --- a/trunk/net/mac80211/tx.c +++ b/trunk/net/mac80211/tx.c @@ -1811,31 +1811,37 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, meshhdrlen = ieee80211_new_mesh_header(&mesh_hdr, sdata, NULL, NULL); } else { - /* DS -> MBSS (802.11-2012 13.11.3.3). - * For unicast with unknown forwarding information, - * destination might be in the MBSS or if that fails - * forwarded to another mesh gate. In either case - * resolution will be handled in ieee80211_xmit(), so - * leave the original DA. This also works for mcast */ - const u8 *mesh_da = skb->data; - - if (mppath) - mesh_da = mppath->mpp; - else if (mpath) - mesh_da = mpath->dst; - rcu_read_unlock(); + int is_mesh_mcast = 1; + const u8 *mesh_da; + if (is_multicast_ether_addr(skb->data)) + /* DA TA mSA AE:SA */ + mesh_da = skb->data; + else { + static const u8 bcast[ETH_ALEN] = + { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; + if (mppath) { + /* RA TA mDA mSA AE:DA SA */ + mesh_da = mppath->mpp; + is_mesh_mcast = 0; + } else if (mpath) { + mesh_da = mpath->dst; + is_mesh_mcast = 0; + } else { + /* DA TA mSA AE:SA */ + mesh_da = bcast; + } + } hdrlen = ieee80211_fill_mesh_addresses(&hdr, &fc, mesh_da, sdata->vif.addr); - if (is_multicast_ether_addr(mesh_da)) - /* DA TA mSA AE:SA */ + rcu_read_unlock(); + if (is_mesh_mcast) meshhdrlen = ieee80211_new_mesh_header(&mesh_hdr, sdata, skb->data + ETH_ALEN, NULL); else - /* RA TA mDA mSA AE:DA SA */ meshhdrlen = ieee80211_new_mesh_header(&mesh_hdr, sdata, diff --git a/trunk/net/netfilter/ipvs/ip_vs_ctl.c b/trunk/net/netfilter/ipvs/ip_vs_ctl.c index f51013c07b9f..84444dda194b 100644 --- a/trunk/net/netfilter/ipvs/ip_vs_ctl.c +++ b/trunk/net/netfilter/ipvs/ip_vs_ctl.c @@ -1171,10 +1171,8 @@ ip_vs_add_service(struct net *net, struct ip_vs_service_user_kern *u, goto out_err; } svc->stats.cpustats = alloc_percpu(struct ip_vs_cpu_stats); - if (!svc->stats.cpustats) { - ret = -ENOMEM; + if (!svc->stats.cpustats) goto out_err; - } /* I'm the first user of the service */ atomic_set(&svc->usecnt, 0); @@ -2761,7 +2759,6 @@ do_ip_vs_get_ctl(struct sock *sk, int cmd, void __user *user, int *len) { struct ip_vs_timeout_user t; - memset(&t, 0, sizeof(t)); __ip_vs_get_timeouts(net, &t); if (copy_to_user(user, &t, sizeof(t)) != 0) ret = -EFAULT; diff --git a/trunk/net/netfilter/nf_conntrack_core.c b/trunk/net/netfilter/nf_conntrack_core.c index 2ceec64b19f9..cf4875565d67 100644 --- a/trunk/net/netfilter/nf_conntrack_core.c +++ b/trunk/net/netfilter/nf_conntrack_core.c @@ -249,15 +249,12 @@ static void death_by_event(unsigned long ul_conntrack) { struct nf_conn *ct = (void *)ul_conntrack; struct net *net = nf_ct_net(ct); - struct nf_conntrack_ecache *ecache = nf_ct_ecache_find(ct); - - BUG_ON(ecache == NULL); if (nf_conntrack_event(IPCT_DESTROY, ct) < 0) { /* bad luck, let's retry again */ - ecache->timeout.expires = jiffies + + ct->timeout.expires = jiffies + (random32() % net->ct.sysctl_events_retry_timeout); - add_timer(&ecache->timeout); + add_timer(&ct->timeout); return; } /* we've got the event delivered, now it's dying */ @@ -271,9 +268,6 @@ static void death_by_event(unsigned long ul_conntrack) void nf_ct_insert_dying_list(struct nf_conn *ct) { struct net *net = nf_ct_net(ct); - struct nf_conntrack_ecache *ecache = nf_ct_ecache_find(ct); - - BUG_ON(ecache == NULL); /* add this conntrack to the dying list */ spin_lock_bh(&nf_conntrack_lock); @@ -281,10 +275,10 @@ void nf_ct_insert_dying_list(struct nf_conn *ct) &net->ct.dying); spin_unlock_bh(&nf_conntrack_lock); /* set a new timer to retry event delivery */ - setup_timer(&ecache->timeout, death_by_event, (unsigned long)ct); - ecache->timeout.expires = jiffies + + setup_timer(&ct->timeout, death_by_event, (unsigned long)ct); + ct->timeout.expires = jiffies + (random32() % net->ct.sysctl_events_retry_timeout); - add_timer(&ecache->timeout); + add_timer(&ct->timeout); } EXPORT_SYMBOL_GPL(nf_ct_insert_dying_list); diff --git a/trunk/net/netfilter/nf_conntrack_expect.c b/trunk/net/netfilter/nf_conntrack_expect.c index 527651a53a45..45cf602a76bc 100644 --- a/trunk/net/netfilter/nf_conntrack_expect.c +++ b/trunk/net/netfilter/nf_conntrack_expect.c @@ -361,6 +361,23 @@ static void evict_oldest_expect(struct nf_conn *master, } } +static inline int refresh_timer(struct nf_conntrack_expect *i) +{ + struct nf_conn_help *master_help = nfct_help(i->master); + const struct nf_conntrack_expect_policy *p; + + if (!del_timer(&i->timeout)) + return 0; + + p = &rcu_dereference_protected( + master_help->helper, + lockdep_is_held(&nf_conntrack_lock) + )->expect_policy[i->class]; + i->timeout.expires = jiffies + p->timeout * HZ; + add_timer(&i->timeout); + return 1; +} + static inline int __nf_ct_expect_check(struct nf_conntrack_expect *expect) { const struct nf_conntrack_expect_policy *p; @@ -369,7 +386,7 @@ static inline int __nf_ct_expect_check(struct nf_conntrack_expect *expect) struct nf_conn_help *master_help = nfct_help(master); struct nf_conntrack_helper *helper; struct net *net = nf_ct_exp_net(expect); - struct hlist_node *n, *next; + struct hlist_node *n; unsigned int h; int ret = 1; @@ -378,12 +395,12 @@ static inline int __nf_ct_expect_check(struct nf_conntrack_expect *expect) goto out; } h = nf_ct_expect_dst_hash(&expect->tuple); - hlist_for_each_entry_safe(i, n, next, &net->ct.expect_hash[h], hnode) { + hlist_for_each_entry(i, n, &net->ct.expect_hash[h], hnode) { if (expect_matches(i, expect)) { - if (del_timer(&i->timeout)) { - nf_ct_unlink_expect(i); - nf_ct_expect_put(i); - break; + /* Refresh timer: if it's dying, ignore.. */ + if (refresh_timer(i)) { + ret = 0; + goto out; } } else if (expect_clash(i, expect)) { ret = -EBUSY; diff --git a/trunk/net/netfilter/nf_conntrack_netlink.c b/trunk/net/netfilter/nf_conntrack_netlink.c index 9807f3278fcb..14f67a2cbcb5 100644 --- a/trunk/net/netfilter/nf_conntrack_netlink.c +++ b/trunk/net/netfilter/nf_conntrack_netlink.c @@ -1896,15 +1896,10 @@ static int ctnetlink_nfqueue_parse(const struct nlattr *attr, struct nf_conn *ct) { struct nlattr *cda[CTA_MAX+1]; - int ret; nla_parse_nested(cda, CTA_MAX, attr, ct_nla_policy); - spin_lock_bh(&nf_conntrack_lock); - ret = ctnetlink_nfqueue_parse_ct((const struct nlattr **)cda, ct); - spin_unlock_bh(&nf_conntrack_lock); - - return ret; + return ctnetlink_nfqueue_parse_ct((const struct nlattr **)cda, ct); } static struct nfq_ct_hook ctnetlink_nfqueue_hook = { @@ -2790,8 +2785,7 @@ static int __init ctnetlink_init(void) goto err_unreg_subsys; } - ret = register_pernet_subsys(&ctnetlink_net_ops); - if (ret < 0) { + if (register_pernet_subsys(&ctnetlink_net_ops)) { pr_err("ctnetlink_init: cannot register pernet operations\n"); goto err_unreg_exp_subsys; } diff --git a/trunk/net/netfilter/nf_conntrack_proto_tcp.c b/trunk/net/netfilter/nf_conntrack_proto_tcp.c index e046b3756aab..a5ac11ebef33 100644 --- a/trunk/net/netfilter/nf_conntrack_proto_tcp.c +++ b/trunk/net/netfilter/nf_conntrack_proto_tcp.c @@ -158,18 +158,21 @@ static const u8 tcp_conntracks[2][6][TCP_CONNTRACK_MAX] = { * sCL -> sSS */ /* sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sS2 */ -/*synack*/ { sIV, sIV, sSR, sIV, sIV, sIV, sIV, sIV, sIV, sSR }, +/*synack*/ { sIV, sIV, sIG, sIG, sIG, sIG, sIG, sIG, sIG, sSR }, /* * sNO -> sIV Too late and no reason to do anything * sSS -> sIV Client can't send SYN and then SYN/ACK * sS2 -> sSR SYN/ACK sent to SYN2 in simultaneous open - * sSR -> sSR Late retransmitted SYN/ACK in simultaneous open - * sES -> sIV Invalid SYN/ACK packets sent by the client - * sFW -> sIV - * sCW -> sIV - * sLA -> sIV - * sTW -> sIV - * sCL -> sIV + * sSR -> sIG + * sES -> sIG Error: SYNs in window outside the SYN_SENT state + * are errors. Receiver will reply with RST + * and close the connection. + * Or we are not in sync and hold a dead connection. + * sFW -> sIG + * sCW -> sIG + * sLA -> sIG + * sTW -> sIG + * sCL -> sIG */ /* sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sS2 */ /*fin*/ { sIV, sIV, sFW, sFW, sLA, sLA, sLA, sTW, sCL, sIV }, @@ -630,9 +633,15 @@ static bool tcp_in_window(const struct nf_conn *ct, ack = sack = receiver->td_end; } - if (tcph->rst && seq == 0 && state->state == TCP_CONNTRACK_SYN_SENT) + if (seq == end + && (!tcph->rst + || (seq == 0 && state->state == TCP_CONNTRACK_SYN_SENT))) /* - * RST sent answering SYN. + * Packets contains no data: we assume it is valid + * and check the ack value only. + * However RST segments are always validated by their + * SEQ number, except when seq == 0 (reset sent answering + * SYN. */ seq = end = sender->td_end; diff --git a/trunk/net/netfilter/nf_conntrack_sip.c b/trunk/net/netfilter/nf_conntrack_sip.c index 5c0a112aeee6..758a1bacc126 100644 --- a/trunk/net/netfilter/nf_conntrack_sip.c +++ b/trunk/net/netfilter/nf_conntrack_sip.c @@ -183,12 +183,12 @@ static int media_len(const struct nf_conn *ct, const char *dptr, return len + digits_len(ct, dptr, limit, shift); } -static int sip_parse_addr(const struct nf_conn *ct, const char *cp, - const char **endp, union nf_inet_addr *addr, - const char *limit, bool delim) +static int parse_addr(const struct nf_conn *ct, const char *cp, + const char **endp, union nf_inet_addr *addr, + const char *limit) { const char *end; - int ret; + int ret = 0; if (!ct) return 0; @@ -197,28 +197,16 @@ static int sip_parse_addr(const struct nf_conn *ct, const char *cp, switch (nf_ct_l3num(ct)) { case AF_INET: ret = in4_pton(cp, limit - cp, (u8 *)&addr->ip, -1, &end); - if (ret == 0) - return 0; break; case AF_INET6: - if (cp < limit && *cp == '[') - cp++; - else if (delim) - return 0; - ret = in6_pton(cp, limit - cp, (u8 *)&addr->ip6, -1, &end); - if (ret == 0) - return 0; - - if (end < limit && *end == ']') - end++; - else if (delim) - return 0; break; default: BUG(); } + if (ret == 0 || end == cp) + return 0; if (endp) *endp = end; return 1; @@ -231,7 +219,7 @@ static int epaddr_len(const struct nf_conn *ct, const char *dptr, union nf_inet_addr addr; const char *aux = dptr; - if (!sip_parse_addr(ct, dptr, &dptr, &addr, limit, true)) { + if (!parse_addr(ct, dptr, &dptr, &addr, limit)) { pr_debug("ip: %s parse failed.!\n", dptr); return 0; } @@ -308,7 +296,7 @@ int ct_sip_parse_request(const struct nf_conn *ct, return 0; dptr += shift; - if (!sip_parse_addr(ct, dptr, &end, addr, limit, true)) + if (!parse_addr(ct, dptr, &end, addr, limit)) return -1; if (end < limit && *end == ':') { end++; @@ -562,7 +550,7 @@ int ct_sip_parse_header_uri(const struct nf_conn *ct, const char *dptr, if (ret == 0) return ret; - if (!sip_parse_addr(ct, dptr + *matchoff, &c, addr, limit, true)) + if (!parse_addr(ct, dptr + *matchoff, &c, addr, limit)) return -1; if (*c == ':') { c++; @@ -611,7 +599,7 @@ int ct_sip_parse_address_param(const struct nf_conn *ct, const char *dptr, unsigned int dataoff, unsigned int datalen, const char *name, unsigned int *matchoff, unsigned int *matchlen, - union nf_inet_addr *addr, bool delim) + union nf_inet_addr *addr) { const char *limit = dptr + datalen; const char *start, *end; @@ -625,7 +613,7 @@ int ct_sip_parse_address_param(const struct nf_conn *ct, const char *dptr, return 0; start += strlen(name); - if (!sip_parse_addr(ct, start, &end, addr, limit, delim)) + if (!parse_addr(ct, start, &end, addr, limit)) return 0; *matchoff = start - dptr; *matchlen = end - start; @@ -687,47 +675,6 @@ static int ct_sip_parse_transport(struct nf_conn *ct, const char *dptr, return 1; } -static int sdp_parse_addr(const struct nf_conn *ct, const char *cp, - const char **endp, union nf_inet_addr *addr, - const char *limit) -{ - const char *end; - int ret; - - memset(addr, 0, sizeof(*addr)); - switch (nf_ct_l3num(ct)) { - case AF_INET: - ret = in4_pton(cp, limit - cp, (u8 *)&addr->ip, -1, &end); - break; - case AF_INET6: - ret = in6_pton(cp, limit - cp, (u8 *)&addr->ip6, -1, &end); - break; - default: - BUG(); - } - - if (ret == 0) - return 0; - if (endp) - *endp = end; - return 1; -} - -/* skip ip address. returns its length. */ -static int sdp_addr_len(const struct nf_conn *ct, const char *dptr, - const char *limit, int *shift) -{ - union nf_inet_addr addr; - const char *aux = dptr; - - if (!sdp_parse_addr(ct, dptr, &dptr, &addr, limit)) { - pr_debug("ip: %s parse failed.!\n", dptr); - return 0; - } - - return dptr - aux; -} - /* SDP header parsing: a SDP session description contains an ordered set of * headers, starting with a section containing general session parameters, * optionally followed by multiple media descriptions. @@ -739,10 +686,10 @@ static int sdp_addr_len(const struct nf_conn *ct, const char *dptr, */ static const struct sip_header ct_sdp_hdrs[] = { [SDP_HDR_VERSION] = SDP_HDR("v=", NULL, digits_len), - [SDP_HDR_OWNER_IP4] = SDP_HDR("o=", "IN IP4 ", sdp_addr_len), - [SDP_HDR_CONNECTION_IP4] = SDP_HDR("c=", "IN IP4 ", sdp_addr_len), - [SDP_HDR_OWNER_IP6] = SDP_HDR("o=", "IN IP6 ", sdp_addr_len), - [SDP_HDR_CONNECTION_IP6] = SDP_HDR("c=", "IN IP6 ", sdp_addr_len), + [SDP_HDR_OWNER_IP4] = SDP_HDR("o=", "IN IP4 ", epaddr_len), + [SDP_HDR_CONNECTION_IP4] = SDP_HDR("c=", "IN IP4 ", epaddr_len), + [SDP_HDR_OWNER_IP6] = SDP_HDR("o=", "IN IP6 ", epaddr_len), + [SDP_HDR_CONNECTION_IP6] = SDP_HDR("c=", "IN IP6 ", epaddr_len), [SDP_HDR_MEDIA] = SDP_HDR("m=", NULL, media_len), }; @@ -828,8 +775,8 @@ static int ct_sip_parse_sdp_addr(const struct nf_conn *ct, const char *dptr, if (ret <= 0) return ret; - if (!sdp_parse_addr(ct, dptr + *matchoff, NULL, addr, - dptr + *matchoff + *matchlen)) + if (!parse_addr(ct, dptr + *matchoff, NULL, addr, + dptr + *matchoff + *matchlen)) return -1; return 1; } @@ -1568,6 +1515,7 @@ static int sip_help_udp(struct sk_buff *skb, unsigned int protoff, } static struct nf_conntrack_helper sip[MAX_PORTS][4] __read_mostly; +static char sip_names[MAX_PORTS][4][sizeof("sip-65535")] __read_mostly; static const struct nf_conntrack_expect_policy sip_exp_policy[SIP_EXPECT_MAX + 1] = { [SIP_EXPECT_SIGNALLING] = { @@ -1637,9 +1585,9 @@ static int __init nf_conntrack_sip_init(void) sip[i][j].me = THIS_MODULE; if (ports[i] == SIP_PORT) - sprintf(sip[i][j].name, "sip"); + sprintf(sip_names[i][j], "sip"); else - sprintf(sip[i][j].name, "sip-%u", i); + sprintf(sip_names[i][j], "sip-%u", i); pr_debug("port #%u: %u\n", i, ports[i]); diff --git a/trunk/net/netfilter/nfnetlink_log.c b/trunk/net/netfilter/nfnetlink_log.c index 5cfb5bedb2b8..169ab59ed9d4 100644 --- a/trunk/net/netfilter/nfnetlink_log.c +++ b/trunk/net/netfilter/nfnetlink_log.c @@ -381,7 +381,6 @@ __build_packet_message(struct nfulnl_instance *inst, struct nlmsghdr *nlh; struct nfgenmsg *nfmsg; sk_buff_data_t old_tail = inst->skb->tail; - struct sock *sk; nlh = nlmsg_put(inst->skb, 0, 0, NFNL_SUBSYS_ULOG << 8 | NFULNL_MSG_PACKET, @@ -481,7 +480,7 @@ __build_packet_message(struct nfulnl_instance *inst, } if (indev && skb_mac_header_was_set(skb)) { - if (nla_put_be16(inst->skb, NFULA_HWTYPE, htons(skb->dev->type)) || + if (nla_put_be32(inst->skb, NFULA_HWTYPE, htons(skb->dev->type)) || nla_put_be16(inst->skb, NFULA_HWLEN, htons(skb->dev->hard_header_len)) || nla_put(inst->skb, NFULA_HWHEADER, skb->dev->hard_header_len, @@ -500,19 +499,18 @@ __build_packet_message(struct nfulnl_instance *inst, } /* UID */ - sk = skb->sk; - if (sk && sk->sk_state != TCP_TIME_WAIT) { - read_lock_bh(&sk->sk_callback_lock); - if (sk->sk_socket && sk->sk_socket->file) { - struct file *file = sk->sk_socket->file; + if (skb->sk) { + read_lock_bh(&skb->sk->sk_callback_lock); + if (skb->sk->sk_socket && skb->sk->sk_socket->file) { + struct file *file = skb->sk->sk_socket->file; __be32 uid = htonl(file->f_cred->fsuid); __be32 gid = htonl(file->f_cred->fsgid); - read_unlock_bh(&sk->sk_callback_lock); + read_unlock_bh(&skb->sk->sk_callback_lock); if (nla_put_be32(inst->skb, NFULA_UID, uid) || nla_put_be32(inst->skb, NFULA_GID, gid)) goto nla_put_failure; } else - read_unlock_bh(&sk->sk_callback_lock); + read_unlock_bh(&skb->sk->sk_callback_lock); } /* local sequence number */ @@ -998,10 +996,8 @@ static int __init nfnetlink_log_init(void) #ifdef CONFIG_PROC_FS if (!proc_create("nfnetlink_log", 0440, - proc_net_netfilter, &nful_file_ops)) { - status = -ENOMEM; + proc_net_netfilter, &nful_file_ops)) goto cleanup_logger; - } #endif return status; diff --git a/trunk/net/netfilter/xt_LOG.c b/trunk/net/netfilter/xt_LOG.c index 91e9af4d1f42..ff5f75fddb15 100644 --- a/trunk/net/netfilter/xt_LOG.c +++ b/trunk/net/netfilter/xt_LOG.c @@ -145,19 +145,6 @@ static int dump_tcp_header(struct sbuff *m, const struct sk_buff *skb, return 0; } -static void dump_sk_uid_gid(struct sbuff *m, struct sock *sk) -{ - if (!sk || sk->sk_state == TCP_TIME_WAIT) - return; - - read_lock_bh(&sk->sk_callback_lock); - if (sk->sk_socket && sk->sk_socket->file) - sb_add(m, "UID=%u GID=%u ", - sk->sk_socket->file->f_cred->fsuid, - sk->sk_socket->file->f_cred->fsgid); - read_unlock_bh(&sk->sk_callback_lock); -} - /* One level of recursion won't kill us */ static void dump_ipv4_packet(struct sbuff *m, const struct nf_loginfo *info, @@ -374,8 +361,14 @@ static void dump_ipv4_packet(struct sbuff *m, } /* Max length: 15 "UID=4294967295 " */ - if ((logflags & XT_LOG_UID) && !iphoff) - dump_sk_uid_gid(m, skb->sk); + if ((logflags & XT_LOG_UID) && !iphoff && skb->sk) { + read_lock_bh(&skb->sk->sk_callback_lock); + if (skb->sk->sk_socket && skb->sk->sk_socket->file) + sb_add(m, "UID=%u GID=%u ", + skb->sk->sk_socket->file->f_cred->fsuid, + skb->sk->sk_socket->file->f_cred->fsgid); + read_unlock_bh(&skb->sk->sk_callback_lock); + } /* Max length: 16 "MARK=0xFFFFFFFF " */ if (!iphoff && skb->mark) @@ -443,8 +436,8 @@ log_packet_common(struct sbuff *m, const struct nf_loginfo *loginfo, const char *prefix) { - sb_add(m, KERN_SOH "%c%sIN=%s OUT=%s ", - '0' + loginfo->u.log.level, prefix, + sb_add(m, "<%d>%sIN=%s OUT=%s ", loginfo->u.log.level, + prefix, in ? in->name : "", out ? out->name : ""); #ifdef CONFIG_BRIDGE_NETFILTER @@ -724,8 +717,14 @@ static void dump_ipv6_packet(struct sbuff *m, } /* Max length: 15 "UID=4294967295 " */ - if ((logflags & XT_LOG_UID) && recurse) - dump_sk_uid_gid(m, skb->sk); + if ((logflags & XT_LOG_UID) && recurse && skb->sk) { + read_lock_bh(&skb->sk->sk_callback_lock); + if (skb->sk->sk_socket && skb->sk->sk_socket->file) + sb_add(m, "UID=%u GID=%u ", + skb->sk->sk_socket->file->f_cred->fsuid, + skb->sk->sk_socket->file->f_cred->fsgid); + read_unlock_bh(&skb->sk->sk_callback_lock); + } /* Max length: 16 "MARK=0xFFFFFFFF " */ if (!recurse && skb->mark) diff --git a/trunk/net/netfilter/xt_limit.c b/trunk/net/netfilter/xt_limit.c index a4c1e4528cac..5c22ce8ab309 100644 --- a/trunk/net/netfilter/xt_limit.c +++ b/trunk/net/netfilter/xt_limit.c @@ -117,11 +117,11 @@ static int limit_mt_check(const struct xt_mtchk_param *par) /* For SMP, we only want to use one set of state. */ r->master = priv; - /* User avg in seconds * XT_LIMIT_SCALE: convert to jiffies * - 128. */ - priv->prev = jiffies; - priv->credit = user2credits(r->avg * r->burst); /* Credits full. */ if (r->cost == 0) { + /* User avg in seconds * XT_LIMIT_SCALE: convert to jiffies * + 128. */ + priv->prev = jiffies; + priv->credit = user2credits(r->avg * r->burst); /* Credits full. */ r->credit_cap = priv->credit; /* Credits full. */ r->cost = user2credits(r->avg); } diff --git a/trunk/net/netlink/af_netlink.c b/trunk/net/netlink/af_netlink.c index 527023823b5c..5463969da45b 100644 --- a/trunk/net/netlink/af_netlink.c +++ b/trunk/net/netlink/af_netlink.c @@ -1362,7 +1362,7 @@ static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock, if (NULL == siocb->scm) siocb->scm = &scm; - err = scm_send(sock, msg, siocb->scm, true); + err = scm_send(sock, msg, siocb->scm); if (err < 0) return err; @@ -1373,8 +1373,7 @@ static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock, dst_pid = addr->nl_pid; dst_group = ffs(addr->nl_groups); err = -EPERM; - if ((dst_group || dst_pid) && - !netlink_capable(sock, NL_NONROOT_SEND)) + if (dst_group && !netlink_capable(sock, NL_NONROOT_SEND)) goto out; } else { dst_pid = nlk->dst_pid; @@ -2148,7 +2147,6 @@ static void __init netlink_add_usersock_entry(void) rcu_assign_pointer(nl_table[NETLINK_USERSOCK].listeners, listeners); nl_table[NETLINK_USERSOCK].module = THIS_MODULE; nl_table[NETLINK_USERSOCK].registered = 1; - nl_table[NETLINK_USERSOCK].nl_nonroot = NL_NONROOT_SEND; netlink_table_ungrab(); } diff --git a/trunk/net/netrom/af_netrom.c b/trunk/net/netrom/af_netrom.c index 7261eb81974f..06592d8b4a2b 100644 --- a/trunk/net/netrom/af_netrom.c +++ b/trunk/net/netrom/af_netrom.c @@ -601,7 +601,7 @@ static int nr_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) if (!capable(CAP_NET_BIND_SERVICE)) { dev_put(dev); release_sock(sk); - return -EPERM; + return -EACCES; } nr->user_addr = addr->fsa_digipeater[0]; nr->source_addr = addr->fsa_ax25.sax25_call; @@ -1169,12 +1169,7 @@ static int nr_recvmsg(struct kiocb *iocb, struct socket *sock, msg->msg_flags |= MSG_TRUNC; } - er = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied); - if (er < 0) { - skb_free_datagram(sk, skb); - release_sock(sk); - return er; - } + skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied); if (sax != NULL) { sax->sax25_family = AF_NETROM; diff --git a/trunk/net/openvswitch/actions.c b/trunk/net/openvswitch/actions.c index 954405ceae9e..f3f96badf5aa 100644 --- a/trunk/net/openvswitch/actions.c +++ b/trunk/net/openvswitch/actions.c @@ -45,7 +45,7 @@ static int make_writable(struct sk_buff *skb, int write_len) return pskb_expand_head(skb, 0, 0, GFP_ATOMIC); } -/* remove VLAN header from packet and update csum accordingly. */ +/* remove VLAN header from packet and update csum accrodingly. */ static int __pop_vlan_tci(struct sk_buff *skb, __be16 *current_tci) { struct vlan_hdr *vhdr; diff --git a/trunk/net/openvswitch/datapath.c b/trunk/net/openvswitch/datapath.c index cf58cedad083..d8277d29e710 100644 --- a/trunk/net/openvswitch/datapath.c +++ b/trunk/net/openvswitch/datapath.c @@ -425,10 +425,10 @@ static int validate_sample(const struct nlattr *attr, static int validate_tp_port(const struct sw_flow_key *flow_key) { if (flow_key->eth.type == htons(ETH_P_IP)) { - if (flow_key->ipv4.tp.src || flow_key->ipv4.tp.dst) + if (flow_key->ipv4.tp.src && flow_key->ipv4.tp.dst) return 0; } else if (flow_key->eth.type == htons(ETH_P_IPV6)) { - if (flow_key->ipv6.tp.src || flow_key->ipv6.tp.dst) + if (flow_key->ipv6.tp.src && flow_key->ipv6.tp.dst) return 0; } @@ -460,7 +460,7 @@ static int validate_set(const struct nlattr *a, if (flow_key->eth.type != htons(ETH_P_IP)) return -EINVAL; - if (!flow_key->ip.proto) + if (!flow_key->ipv4.addr.src || !flow_key->ipv4.addr.dst) return -EINVAL; ipv4_key = nla_data(ovs_key); diff --git a/trunk/net/openvswitch/flow.h b/trunk/net/openvswitch/flow.h index c30df1a10c67..9b75617ca4e0 100644 --- a/trunk/net/openvswitch/flow.h +++ b/trunk/net/openvswitch/flow.h @@ -145,17 +145,15 @@ u64 ovs_flow_used_time(unsigned long flow_jiffies); * OVS_KEY_ATTR_PRIORITY 4 -- 4 8 * OVS_KEY_ATTR_IN_PORT 4 -- 4 8 * OVS_KEY_ATTR_ETHERNET 12 -- 4 16 - * OVS_KEY_ATTR_ETHERTYPE 2 2 4 8 (outer VLAN ethertype) * OVS_KEY_ATTR_8021Q 4 -- 4 8 - * OVS_KEY_ATTR_ENCAP 0 -- 4 4 (VLAN encapsulation) - * OVS_KEY_ATTR_ETHERTYPE 2 2 4 8 (inner VLAN ethertype) + * OVS_KEY_ATTR_ETHERTYPE 2 2 4 8 * OVS_KEY_ATTR_IPV6 40 -- 4 44 * OVS_KEY_ATTR_ICMPV6 2 2 4 8 * OVS_KEY_ATTR_ND 28 -- 4 32 * ------------------------------------------------- - * total 144 + * total 132 */ -#define FLOW_BUFSIZE 144 +#define FLOW_BUFSIZE 132 int ovs_flow_to_nlattrs(const struct sw_flow_key *, struct sk_buff *); int ovs_flow_from_nlattrs(struct sw_flow_key *swkey, int *key_lenp, diff --git a/trunk/net/packet/af_packet.c b/trunk/net/packet/af_packet.c index c5c9e2a54218..ceaca7c134a0 100644 --- a/trunk/net/packet/af_packet.c +++ b/trunk/net/packet/af_packet.c @@ -1079,7 +1079,7 @@ static void *packet_current_rx_frame(struct packet_sock *po, default: WARN(1, "TPACKET version not supported\n"); BUG(); - return NULL; + return 0; } } @@ -1273,14 +1273,6 @@ static void __fanout_unlink(struct sock *sk, struct packet_sock *po) spin_unlock(&f->lock); } -static bool match_fanout_group(struct packet_type *ptype, struct sock * sk) -{ - if (ptype->af_packet_priv == (void*)((struct packet_sock *)sk)->fanout) - return true; - - return false; -} - static int fanout_add(struct sock *sk, u16 id, u16 type_flags) { struct packet_sock *po = pkt_sk(sk); @@ -1333,7 +1325,6 @@ static int fanout_add(struct sock *sk, u16 id, u16 type_flags) match->prot_hook.dev = po->prot_hook.dev; match->prot_hook.func = packet_rcv_fanout; match->prot_hook.af_packet_priv = match; - match->prot_hook.id_match = match_fanout_group; dev_add_pack(&match->prot_hook); list_add(&match->list, &fanout_list); } @@ -1945,6 +1936,7 @@ static void tpacket_destruct_skb(struct sk_buff *skb) if (likely(po->tx_ring.pg_vec)) { ph = skb_shinfo(skb)->destructor_arg; + BUG_ON(__packet_get_status(po, ph) != TP_STATUS_SENDING); BUG_ON(atomic_read(&po->tx_ring.pending) == 0); atomic_dec(&po->tx_ring.pending); __packet_set_status(po, ph, TP_STATUS_AVAILABLE); diff --git a/trunk/net/sched/act_gact.c b/trunk/net/sched/act_gact.c index 05d60859d8e3..f10fb8256442 100644 --- a/trunk/net/sched/act_gact.c +++ b/trunk/net/sched/act_gact.c @@ -67,9 +67,6 @@ static int tcf_gact_init(struct nlattr *nla, struct nlattr *est, struct tcf_common *pc; int ret = 0; int err; -#ifdef CONFIG_GACT_PROB - struct tc_gact_p *p_parm = NULL; -#endif if (nla == NULL) return -EINVAL; @@ -85,12 +82,6 @@ static int tcf_gact_init(struct nlattr *nla, struct nlattr *est, #ifndef CONFIG_GACT_PROB if (tb[TCA_GACT_PROB] != NULL) return -EOPNOTSUPP; -#else - if (tb[TCA_GACT_PROB]) { - p_parm = nla_data(tb[TCA_GACT_PROB]); - if (p_parm->ptype >= MAX_RAND) - return -EINVAL; - } #endif pc = tcf_hash_check(parm->index, a, bind, &gact_hash_info); @@ -112,7 +103,8 @@ static int tcf_gact_init(struct nlattr *nla, struct nlattr *est, spin_lock_bh(&gact->tcf_lock); gact->tcf_action = parm->action; #ifdef CONFIG_GACT_PROB - if (p_parm) { + if (tb[TCA_GACT_PROB] != NULL) { + struct tc_gact_p *p_parm = nla_data(tb[TCA_GACT_PROB]); gact->tcfg_paction = p_parm->paction; gact->tcfg_pval = p_parm->pval; gact->tcfg_ptype = p_parm->ptype; @@ -141,7 +133,7 @@ static int tcf_gact(struct sk_buff *skb, const struct tc_action *a, spin_lock(&gact->tcf_lock); #ifdef CONFIG_GACT_PROB - if (gact->tcfg_ptype) + if (gact->tcfg_ptype && gact_rand[gact->tcfg_ptype] != NULL) action = gact_rand[gact->tcfg_ptype](gact); else action = gact->tcf_action; diff --git a/trunk/net/sched/act_ipt.c b/trunk/net/sched/act_ipt.c index 58fb3c7aab9e..60e281ad0f07 100644 --- a/trunk/net/sched/act_ipt.c +++ b/trunk/net/sched/act_ipt.c @@ -185,12 +185,7 @@ static int tcf_ipt_init(struct nlattr *nla, struct nlattr *est, err2: kfree(tname); err1: - if (ret == ACT_P_CREATED) { - if (est) - gen_kill_estimator(&pc->tcfc_bstats, - &pc->tcfc_rate_est); - kfree_rcu(pc, tcfc_rcu); - } + kfree(pc); return err; } diff --git a/trunk/net/sched/act_mirred.c b/trunk/net/sched/act_mirred.c index 9c0fd0c78814..fe81cc18e9e0 100644 --- a/trunk/net/sched/act_mirred.c +++ b/trunk/net/sched/act_mirred.c @@ -200,12 +200,13 @@ static int tcf_mirred(struct sk_buff *skb, const struct tc_action *a, out: if (err) { m->tcf_qstats.overlimits++; - if (m->tcfm_eaction != TCA_EGRESS_MIRROR) - retval = TC_ACT_SHOT; - else - retval = m->tcf_action; - } else + /* should we be asking for packet to be dropped? + * may make sense for redirect case only + */ + retval = TC_ACT_SHOT; + } else { retval = m->tcf_action; + } spin_unlock(&m->tcf_lock); return retval; diff --git a/trunk/net/sched/act_pedit.c b/trunk/net/sched/act_pedit.c index 45c53ab067a6..26aa2f6ce257 100644 --- a/trunk/net/sched/act_pedit.c +++ b/trunk/net/sched/act_pedit.c @@ -74,10 +74,7 @@ static int tcf_pedit_init(struct nlattr *nla, struct nlattr *est, p = to_pedit(pc); keys = kmalloc(ksize, GFP_KERNEL); if (keys == NULL) { - if (est) - gen_kill_estimator(&pc->tcfc_bstats, - &pc->tcfc_rate_est); - kfree_rcu(pc, tcfc_rcu); + kfree(pc); return -ENOMEM; } ret = ACT_P_CREATED; diff --git a/trunk/net/sched/act_simple.c b/trunk/net/sched/act_simple.c index 3714f60f0b3c..3922f2a2821b 100644 --- a/trunk/net/sched/act_simple.c +++ b/trunk/net/sched/act_simple.c @@ -131,10 +131,7 @@ static int tcf_simp_init(struct nlattr *nla, struct nlattr *est, d = to_defact(pc); ret = alloc_defdata(d, defdata); if (ret < 0) { - if (est) - gen_kill_estimator(&pc->tcfc_bstats, - &pc->tcfc_rate_est); - kfree_rcu(pc, tcfc_rcu); + kfree(pc); return ret; } d->tcf_action = parm->action; diff --git a/trunk/net/sched/sch_cbq.c b/trunk/net/sched/sch_cbq.c index 564b9fc8efd3..6aabd77d1cfd 100644 --- a/trunk/net/sched/sch_cbq.c +++ b/trunk/net/sched/sch_cbq.c @@ -250,11 +250,10 @@ cbq_classify(struct sk_buff *skb, struct Qdisc *sch, int *qerr) else if ((cl = defmap[res.classid & TC_PRIO_MAX]) == NULL) cl = defmap[TC_PRIO_BESTEFFORT]; - if (cl == NULL) + if (cl == NULL || cl->level >= head->level) goto fallback; } - if (cl->level >= head->level) - goto fallback; + #ifdef CONFIG_NET_CLS_ACT switch (result) { case TC_ACT_QUEUED: diff --git a/trunk/net/sched/sch_fq_codel.c b/trunk/net/sched/sch_fq_codel.c index 4e606fcb2534..9fc1c62ec80e 100644 --- a/trunk/net/sched/sch_fq_codel.c +++ b/trunk/net/sched/sch_fq_codel.c @@ -191,6 +191,7 @@ static int fq_codel_enqueue(struct sk_buff *skb, struct Qdisc *sch) if (list_empty(&flow->flowchain)) { list_add_tail(&flow->flowchain, &q->new_flows); + codel_vars_init(&flow->cvars); q->new_flow_count++; flow->deficit = q->quantum; flow->dropped = 0; @@ -417,7 +418,6 @@ static int fq_codel_init(struct Qdisc *sch, struct nlattr *opt) struct fq_codel_flow *flow = q->flows + i; INIT_LIST_HEAD(&flow->flowchain); - codel_vars_init(&flow->cvars); } } if (sch->limit >= 1) diff --git a/trunk/net/sched/sch_gred.c b/trunk/net/sched/sch_gred.c index d42234c0f13b..e901583e4ea5 100644 --- a/trunk/net/sched/sch_gred.c +++ b/trunk/net/sched/sch_gred.c @@ -102,8 +102,9 @@ static inline int gred_wred_mode_check(struct Qdisc *sch) if (q == NULL) continue; - for (n = i + 1; n < table->DPs; n++) - if (table->tab[n] && table->tab[n]->prio == q->prio) + for (n = 0; n < table->DPs; n++) + if (table->tab[n] && table->tab[n] != q && + table->tab[n]->prio == q->prio) return 1; } @@ -136,7 +137,6 @@ static inline void gred_store_wred_set(struct gred_sched *table, struct gred_sched_data *q) { table->wred_set.qavg = q->vars.qavg; - table->wred_set.qidlestart = q->vars.qidlestart; } static inline int gred_use_ecn(struct gred_sched *t) @@ -176,7 +176,7 @@ static int gred_enqueue(struct sk_buff *skb, struct Qdisc *sch) skb->tc_index = (skb->tc_index & ~GRED_VQ_MASK) | dp; } - /* sum up all the qaves of prios < ours to get the new qave */ + /* sum up all the qaves of prios <= to ours to get the new qave */ if (!gred_wred_mode(t) && gred_rio_mode(t)) { int i; @@ -260,18 +260,16 @@ static struct sk_buff *gred_dequeue(struct Qdisc *sch) } else { q->backlog -= qdisc_pkt_len(skb); - if (gred_wred_mode(t)) { - if (!sch->qstats.backlog) - red_start_of_idle_period(&t->wred_set); - } else { - if (!q->backlog) - red_start_of_idle_period(&q->vars); - } + if (!q->backlog && !gred_wred_mode(t)) + red_start_of_idle_period(&q->vars); } return skb; } + if (gred_wred_mode(t) && !red_is_idling(&t->wred_set)) + red_start_of_idle_period(&t->wred_set); + return NULL; } @@ -293,20 +291,19 @@ static unsigned int gred_drop(struct Qdisc *sch) q->backlog -= len; q->stats.other++; - if (gred_wred_mode(t)) { - if (!sch->qstats.backlog) - red_start_of_idle_period(&t->wred_set); - } else { - if (!q->backlog) - red_start_of_idle_period(&q->vars); - } + if (!q->backlog && !gred_wred_mode(t)) + red_start_of_idle_period(&q->vars); } qdisc_drop(skb, sch); return len; } + if (gred_wred_mode(t) && !red_is_idling(&t->wred_set)) + red_start_of_idle_period(&t->wred_set); + return 0; + } static void gred_reset(struct Qdisc *sch) @@ -538,7 +535,6 @@ static int gred_dump(struct Qdisc *sch, struct sk_buff *skb) for (i = 0; i < MAX_DPs; i++) { struct gred_sched_data *q = table->tab[i]; struct tc_gred_qopt opt; - unsigned long qavg; memset(&opt, 0, sizeof(opt)); @@ -570,9 +566,7 @@ static int gred_dump(struct Qdisc *sch, struct sk_buff *skb) if (gred_wred_mode(table)) gred_load_wred_set(table, q); - qavg = red_calc_qavg(&q->parms, &q->vars, - q->vars.qavg >> q->parms.Wlog); - opt.qave = qavg >> q->parms.Wlog; + opt.qave = red_calc_qavg(&q->parms, &q->vars, q->vars.qavg); append_opt: if (nla_append(skb, sizeof(opt), &opt) < 0) diff --git a/trunk/net/sched/sch_qfq.c b/trunk/net/sched/sch_qfq.c index 211a21217045..9af01f3df18c 100644 --- a/trunk/net/sched/sch_qfq.c +++ b/trunk/net/sched/sch_qfq.c @@ -203,34 +203,6 @@ static int qfq_calc_index(u32 inv_w, unsigned int maxlen) return index; } -/* Length of the next packet (0 if the queue is empty). */ -static unsigned int qdisc_peek_len(struct Qdisc *sch) -{ - struct sk_buff *skb; - - skb = sch->ops->peek(sch); - return skb ? qdisc_pkt_len(skb) : 0; -} - -static void qfq_deactivate_class(struct qfq_sched *, struct qfq_class *); -static void qfq_activate_class(struct qfq_sched *q, struct qfq_class *cl, - unsigned int len); - -static void qfq_update_class_params(struct qfq_sched *q, struct qfq_class *cl, - u32 lmax, u32 inv_w, int delta_w) -{ - int i; - - /* update qfq-specific data */ - cl->lmax = lmax; - cl->inv_w = inv_w; - i = qfq_calc_index(cl->inv_w, cl->lmax); - - cl->grp = &q->groups[i]; - - q->wsum += delta_w; -} - static int qfq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, struct nlattr **tca, unsigned long *arg) { @@ -278,8 +250,6 @@ static int qfq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, lmax = 1UL << QFQ_MTU_SHIFT; if (cl != NULL) { - bool need_reactivation = false; - if (tca[TCA_RATE]) { err = gen_replace_estimator(&cl->bstats, &cl->rate_est, qdisc_root_sleeping_lock(sch), @@ -288,29 +258,12 @@ static int qfq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, return err; } - if (lmax == cl->lmax && inv_w == cl->inv_w) - return 0; /* nothing to update */ - - i = qfq_calc_index(inv_w, lmax); - sch_tree_lock(sch); - if (&q->groups[i] != cl->grp && cl->qdisc->q.qlen > 0) { - /* - * shift cl->F back, to not charge the - * class for the not-yet-served head - * packet - */ - cl->F = cl->S; - /* remove class from its slot in the old group */ - qfq_deactivate_class(q, cl); - need_reactivation = true; + if (inv_w != cl->inv_w) { + sch_tree_lock(sch); + q->wsum += delta_w; + cl->inv_w = inv_w; + sch_tree_unlock(sch); } - - qfq_update_class_params(q, cl, lmax, inv_w, delta_w); - - if (need_reactivation) /* activate in new group */ - qfq_activate_class(q, cl, qdisc_peek_len(cl->qdisc)); - sch_tree_unlock(sch); - return 0; } @@ -320,8 +273,11 @@ static int qfq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, cl->refcnt = 1; cl->common.classid = classid; + cl->lmax = lmax; + cl->inv_w = inv_w; + i = qfq_calc_index(cl->inv_w, cl->lmax); - qfq_update_class_params(q, cl, lmax, inv_w, delta_w); + cl->grp = &q->groups[i]; cl->qdisc = qdisc_create_dflt(sch->dev_queue, &pfifo_qdisc_ops, classid); @@ -338,6 +294,7 @@ static int qfq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, return err; } } + q->wsum += weight; sch_tree_lock(sch); qdisc_class_hash_insert(&q->clhash, &cl->common); @@ -754,6 +711,15 @@ static void qfq_update_eligible(struct qfq_sched *q, u64 old_V) } } +/* What is length of next packet in queue (0 if queue is empty) */ +static unsigned int qdisc_peek_len(struct Qdisc *sch) +{ + struct sk_buff *skb; + + skb = sch->ops->peek(sch); + return skb ? qdisc_pkt_len(skb) : 0; +} + /* * Updates the class, returns true if also the group needs to be updated. */ @@ -865,10 +831,7 @@ static void qfq_update_start(struct qfq_sched *q, struct qfq_class *cl) if (mask) { struct qfq_group *next = qfq_ffs(q, mask); if (qfq_gt(roundedF, next->F)) { - if (qfq_gt(limit, next->F)) - cl->S = next->F; - else /* preserve timestamp correctness */ - cl->S = limit; + cl->S = next->F; return; } } @@ -880,8 +843,11 @@ static void qfq_update_start(struct qfq_sched *q, struct qfq_class *cl) static int qfq_enqueue(struct sk_buff *skb, struct Qdisc *sch) { struct qfq_sched *q = qdisc_priv(sch); + struct qfq_group *grp; struct qfq_class *cl; int err; + u64 roundedS; + int s; cl = qfq_classify(skb, sch, &err); if (cl == NULL) { @@ -910,25 +876,11 @@ static int qfq_enqueue(struct sk_buff *skb, struct Qdisc *sch) return err; /* If reach this point, queue q was idle */ - qfq_activate_class(q, cl, qdisc_pkt_len(skb)); - - return err; -} - -/* - * Handle class switch from idle to backlogged. - */ -static void qfq_activate_class(struct qfq_sched *q, struct qfq_class *cl, - unsigned int pkt_len) -{ - struct qfq_group *grp = cl->grp; - u64 roundedS; - int s; - + grp = cl->grp; qfq_update_start(q, cl); /* compute new finish time and rounded start. */ - cl->F = cl->S + (u64)pkt_len * cl->inv_w; + cl->F = cl->S + (u64)qdisc_pkt_len(skb) * cl->inv_w; roundedS = qfq_round_down(cl->S, grp->slot_shift); /* @@ -965,6 +917,8 @@ static void qfq_activate_class(struct qfq_sched *q, struct qfq_class *cl, skip_update: qfq_slot_insert(grp, cl, roundedS); + + return err; } diff --git a/trunk/net/sctp/output.c b/trunk/net/sctp/output.c index be50aa234dcd..838e18b4d7ea 100644 --- a/trunk/net/sctp/output.c +++ b/trunk/net/sctp/output.c @@ -364,25 +364,6 @@ sctp_xmit_t sctp_packet_append_chunk(struct sctp_packet *packet, return retval; } -static void sctp_packet_release_owner(struct sk_buff *skb) -{ - sk_free(skb->sk); -} - -static void sctp_packet_set_owner_w(struct sk_buff *skb, struct sock *sk) -{ - skb_orphan(skb); - skb->sk = sk; - skb->destructor = sctp_packet_release_owner; - - /* - * The data chunks have already been accounted for in sctp_sendmsg(), - * therefore only reserve a single byte to keep socket around until - * the packet has been transmitted. - */ - atomic_inc(&sk->sk_wmem_alloc); -} - /* All packets are sent to the network through this function from * sctp_outq_tail(). * @@ -424,7 +405,7 @@ int sctp_packet_transmit(struct sctp_packet *packet) /* Set the owning socket so that we know where to get the * destination IP address. */ - sctp_packet_set_owner_w(nskb, sk); + skb_set_owner_w(nskb, sk); if (!sctp_transport_dst_check(tp)) { sctp_transport_route(tp, NULL, sctp_sk(sk)); diff --git a/trunk/net/socket.c b/trunk/net/socket.c index edc3c4af9085..dfe5b66c97e0 100644 --- a/trunk/net/socket.c +++ b/trunk/net/socket.c @@ -2604,7 +2604,7 @@ static int do_siocgstamp(struct net *net, struct socket *sock, err = sock_do_ioctl(net, sock, cmd, (unsigned long)&ktv); set_fs(old_fs); if (!err) - err = compat_put_timeval(&ktv, up); + err = compat_put_timeval(up, &ktv); return err; } @@ -2620,7 +2620,7 @@ static int do_siocgstampns(struct net *net, struct socket *sock, err = sock_do_ioctl(net, sock, cmd, (unsigned long)&kts); set_fs(old_fs); if (!err) - err = compat_put_timespec(&kts, up); + err = compat_put_timespec(up, &kts); return err; } @@ -2657,7 +2657,6 @@ static int dev_ifconf(struct net *net, struct compat_ifconf __user *uifc32) if (copy_from_user(&ifc32, uifc32, sizeof(struct compat_ifconf))) return -EFAULT; - memset(&ifc, 0, sizeof(ifc)); if (ifc32.ifcbuf == 0) { ifc32.ifc_len = 0; ifc.ifc_len = 0; diff --git a/trunk/net/sunrpc/svc_xprt.c b/trunk/net/sunrpc/svc_xprt.c index bac973a31367..88f2bf671960 100644 --- a/trunk/net/sunrpc/svc_xprt.c +++ b/trunk/net/sunrpc/svc_xprt.c @@ -316,6 +316,7 @@ static bool svc_xprt_has_something_to_do(struct svc_xprt *xprt) */ void svc_xprt_enqueue(struct svc_xprt *xprt) { + struct svc_serv *serv = xprt->xpt_server; struct svc_pool *pool; struct svc_rqst *rqstp; int cpu; @@ -361,6 +362,8 @@ void svc_xprt_enqueue(struct svc_xprt *xprt) rqstp, rqstp->rq_xprt); rqstp->rq_xprt = xprt; svc_xprt_get(xprt); + rqstp->rq_reserved = serv->sv_max_mesg; + atomic_add(rqstp->rq_reserved, &xprt->xpt_reserved); pool->sp_stats.threads_woken++; wake_up(&rqstp->rq_wait); } else { @@ -637,6 +640,8 @@ int svc_recv(struct svc_rqst *rqstp, long timeout) if (xprt) { rqstp->rq_xprt = xprt; svc_xprt_get(xprt); + rqstp->rq_reserved = serv->sv_max_mesg; + atomic_add(rqstp->rq_reserved, &xprt->xpt_reserved); /* As there is a shortage of threads and this request * had to be queued, don't allow the thread to wait so @@ -733,8 +738,6 @@ int svc_recv(struct svc_rqst *rqstp, long timeout) else len = xprt->xpt_ops->xpo_recvfrom(rqstp); dprintk("svc: got len=%d\n", len); - rqstp->rq_reserved = serv->sv_max_mesg; - atomic_add(rqstp->rq_reserved, &xprt->xpt_reserved); } svc_xprt_received(xprt); @@ -791,8 +794,7 @@ int svc_send(struct svc_rqst *rqstp) /* Grab mutex to serialize outgoing data. */ mutex_lock(&xprt->xpt_mutex); - if (test_bit(XPT_DEAD, &xprt->xpt_flags) - || test_bit(XPT_CLOSE, &xprt->xpt_flags)) + if (test_bit(XPT_DEAD, &xprt->xpt_flags)) len = -ENOTCONN; else len = xprt->xpt_ops->xpo_sendto(rqstp); diff --git a/trunk/net/sunrpc/svcsock.c b/trunk/net/sunrpc/svcsock.c index 998aa8c1807c..18bc130255a7 100644 --- a/trunk/net/sunrpc/svcsock.c +++ b/trunk/net/sunrpc/svcsock.c @@ -1129,9 +1129,9 @@ static int svc_tcp_recvfrom(struct svc_rqst *rqstp) if (len >= 0) svsk->sk_tcplen += len; if (len != want) { - svc_tcp_save_pages(svsk, rqstp); if (len < 0 && len != -EAGAIN) goto err_other; + svc_tcp_save_pages(svsk, rqstp); dprintk("svc: incomplete TCP record (%d of %d)\n", svsk->sk_tcplen, svsk->sk_reclen); goto err_noclose; diff --git a/trunk/net/sunrpc/xprt.c b/trunk/net/sunrpc/xprt.c index 5d7f61d7559c..a5a402a7d21f 100644 --- a/trunk/net/sunrpc/xprt.c +++ b/trunk/net/sunrpc/xprt.c @@ -969,11 +969,11 @@ static bool xprt_dynamic_free_slot(struct rpc_xprt *xprt, struct rpc_rqst *req) return false; } -void xprt_alloc_slot(struct rpc_xprt *xprt, struct rpc_task *task) +static void xprt_alloc_slot(struct rpc_task *task) { + struct rpc_xprt *xprt = task->tk_xprt; struct rpc_rqst *req; - spin_lock(&xprt->reserve_lock); if (!list_empty(&xprt->free)) { req = list_entry(xprt->free.next, struct rpc_rqst, rq_list); list_del(&req->rq_list); @@ -994,29 +994,12 @@ void xprt_alloc_slot(struct rpc_xprt *xprt, struct rpc_task *task) default: task->tk_status = -EAGAIN; } - spin_unlock(&xprt->reserve_lock); return; out_init_req: task->tk_status = 0; task->tk_rqstp = req; xprt_request_init(task, xprt); - spin_unlock(&xprt->reserve_lock); -} -EXPORT_SYMBOL_GPL(xprt_alloc_slot); - -void xprt_lock_and_alloc_slot(struct rpc_xprt *xprt, struct rpc_task *task) -{ - /* Note: grabbing the xprt_lock_write() ensures that we throttle - * new slot allocation if the transport is congested (i.e. when - * reconnecting a stream transport or when out of socket write - * buffer space). - */ - if (xprt_lock_write(xprt, task)) { - xprt_alloc_slot(xprt, task); - xprt_release_write(xprt, task); - } } -EXPORT_SYMBOL_GPL(xprt_lock_and_alloc_slot); static void xprt_free_slot(struct rpc_xprt *xprt, struct rpc_rqst *req) { @@ -1100,9 +1083,20 @@ void xprt_reserve(struct rpc_task *task) if (task->tk_rqstp != NULL) return; + /* Note: grabbing the xprt_lock_write() here is not strictly needed, + * but ensures that we throttle new slot allocation if the transport + * is congested (e.g. if reconnecting or if we're out of socket + * write buffer space). + */ task->tk_timeout = 0; task->tk_status = -EAGAIN; - xprt->ops->alloc_slot(xprt, task); + if (!xprt_lock_write(xprt, task)) + return; + + spin_lock(&xprt->reserve_lock); + xprt_alloc_slot(task); + spin_unlock(&xprt->reserve_lock); + xprt_release_write(xprt, task); } static inline __be32 xprt_alloc_xid(struct rpc_xprt *xprt) diff --git a/trunk/net/sunrpc/xprtrdma/transport.c b/trunk/net/sunrpc/xprtrdma/transport.c index 5d9202dc7cb1..06cdbff79e4a 100644 --- a/trunk/net/sunrpc/xprtrdma/transport.c +++ b/trunk/net/sunrpc/xprtrdma/transport.c @@ -713,7 +713,6 @@ static void xprt_rdma_print_stats(struct rpc_xprt *xprt, struct seq_file *seq) static struct rpc_xprt_ops xprt_rdma_procs = { .reserve_xprt = xprt_rdma_reserve_xprt, .release_xprt = xprt_release_xprt_cong, /* sunrpc/xprt.c */ - .alloc_slot = xprt_alloc_slot, .release_request = xprt_release_rqst_cong, /* ditto */ .set_retrans_timeout = xprt_set_retrans_timeout_def, /* ditto */ .rpcbind = rpcb_getport_async, /* sunrpc/rpcb_clnt.c */ diff --git a/trunk/net/sunrpc/xprtsock.c b/trunk/net/sunrpc/xprtsock.c index a35b8e52e551..400567243f84 100644 --- a/trunk/net/sunrpc/xprtsock.c +++ b/trunk/net/sunrpc/xprtsock.c @@ -2473,7 +2473,6 @@ static void bc_destroy(struct rpc_xprt *xprt) static struct rpc_xprt_ops xs_local_ops = { .reserve_xprt = xprt_reserve_xprt, .release_xprt = xs_tcp_release_xprt, - .alloc_slot = xprt_alloc_slot, .rpcbind = xs_local_rpcbind, .set_port = xs_local_set_port, .connect = xs_connect, @@ -2490,7 +2489,6 @@ static struct rpc_xprt_ops xs_udp_ops = { .set_buffer_size = xs_udp_set_buffer_size, .reserve_xprt = xprt_reserve_xprt_cong, .release_xprt = xprt_release_xprt_cong, - .alloc_slot = xprt_alloc_slot, .rpcbind = rpcb_getport_async, .set_port = xs_set_port, .connect = xs_connect, @@ -2508,7 +2506,6 @@ static struct rpc_xprt_ops xs_udp_ops = { static struct rpc_xprt_ops xs_tcp_ops = { .reserve_xprt = xprt_reserve_xprt, .release_xprt = xs_tcp_release_xprt, - .alloc_slot = xprt_lock_and_alloc_slot, .rpcbind = rpcb_getport_async, .set_port = xs_set_port, .connect = xs_connect, diff --git a/trunk/net/unix/af_unix.c b/trunk/net/unix/af_unix.c index c5ee4ff61364..e4768c180da2 100644 --- a/trunk/net/unix/af_unix.c +++ b/trunk/net/unix/af_unix.c @@ -1450,7 +1450,7 @@ static int unix_dgram_sendmsg(struct kiocb *kiocb, struct socket *sock, if (NULL == siocb->scm) siocb->scm = &tmp_scm; wait_for_unix_gc(); - err = scm_send(sock, msg, siocb->scm, false); + err = scm_send(sock, msg, siocb->scm); if (err < 0) return err; @@ -1619,7 +1619,7 @@ static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock, if (NULL == siocb->scm) siocb->scm = &tmp_scm; wait_for_unix_gc(); - err = scm_send(sock, msg, siocb->scm, false); + err = scm_send(sock, msg, siocb->scm); if (err < 0) return err; diff --git a/trunk/net/wireless/core.c b/trunk/net/wireless/core.c index dcd64d5b07aa..31b40cc4a9c3 100644 --- a/trunk/net/wireless/core.c +++ b/trunk/net/wireless/core.c @@ -952,11 +952,6 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb, */ synchronize_rcu(); INIT_LIST_HEAD(&wdev->list); - /* - * Ensure that all events have been processed and - * freed. - */ - cfg80211_process_wdev_events(wdev); break; case NETDEV_PRE_UP: if (!(wdev->wiphy->interface_modes & BIT(wdev->iftype))) diff --git a/trunk/net/wireless/core.h b/trunk/net/wireless/core.h index bc7430b54771..5206c6844fd7 100644 --- a/trunk/net/wireless/core.h +++ b/trunk/net/wireless/core.h @@ -426,7 +426,6 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev, struct net_device *dev, enum nl80211_iftype ntype, u32 *flags, struct vif_params *params); void cfg80211_process_rdev_events(struct cfg80211_registered_device *rdev); -void cfg80211_process_wdev_events(struct wireless_dev *wdev); int cfg80211_can_use_iftype_chan(struct cfg80211_registered_device *rdev, struct wireless_dev *wdev, diff --git a/trunk/net/wireless/nl80211.c b/trunk/net/wireless/nl80211.c index 1e37dbf00cb3..97026f3b215a 100644 --- a/trunk/net/wireless/nl80211.c +++ b/trunk/net/wireless/nl80211.c @@ -5633,10 +5633,8 @@ static int nl80211_connect(struct sk_buff *skb, struct genl_info *info) sizeof(connect.ht_capa_mask)); if (info->attrs[NL80211_ATTR_HT_CAPABILITY]) { - if (!info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK]) { - kfree(connkeys); + if (!info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK]) return -EINVAL; - } memcpy(&connect.ht_capa, nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]), sizeof(connect.ht_capa)); diff --git a/trunk/net/wireless/reg.c b/trunk/net/wireless/reg.c index 72d170ca3406..2303ee73b50a 100644 --- a/trunk/net/wireless/reg.c +++ b/trunk/net/wireless/reg.c @@ -350,9 +350,6 @@ static void reg_regdb_search(struct work_struct *work) struct reg_regdb_search_request *request; const struct ieee80211_regdomain *curdom, *regdom; int i, r; - bool set_reg = false; - - mutex_lock(&cfg80211_mutex); mutex_lock(®_regdb_search_mutex); while (!list_empty(®_regdb_search_list)) { @@ -368,7 +365,9 @@ static void reg_regdb_search(struct work_struct *work) r = reg_copy_regd(®dom, curdom); if (r) break; - set_reg = true; + mutex_lock(&cfg80211_mutex); + set_regdom(regdom); + mutex_unlock(&cfg80211_mutex); break; } } @@ -376,11 +375,6 @@ static void reg_regdb_search(struct work_struct *work) kfree(request); } mutex_unlock(®_regdb_search_mutex); - - if (set_reg) - set_regdom(regdom); - - mutex_unlock(&cfg80211_mutex); } static DECLARE_WORK(reg_regdb_work, reg_regdb_search); @@ -686,8 +680,6 @@ static u32 map_regdom_flags(u32 rd_flags) channel_flags |= IEEE80211_CHAN_NO_IBSS; if (rd_flags & NL80211_RRF_DFS) channel_flags |= IEEE80211_CHAN_RADAR; - if (rd_flags & NL80211_RRF_NO_OFDM) - channel_flags |= IEEE80211_CHAN_NO_OFDM; return channel_flags; } @@ -909,21 +901,7 @@ static void handle_channel(struct wiphy *wiphy, chan->max_antenna_gain = min(chan->orig_mag, (int) MBI_TO_DBI(power_rule->max_antenna_gain)); chan->max_reg_power = (int) MBM_TO_DBM(power_rule->max_eirp); - if (chan->orig_mpwr) { - /* - * Devices that have their own custom regulatory domain - * but also use WIPHY_FLAG_STRICT_REGULATORY will follow the - * passed country IE power settings. - */ - if (initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE && - wiphy->flags & WIPHY_FLAG_CUSTOM_REGULATORY && - wiphy->flags & WIPHY_FLAG_STRICT_REGULATORY) - chan->max_power = chan->max_reg_power; - else - chan->max_power = min(chan->orig_mpwr, - chan->max_reg_power); - } else - chan->max_power = chan->max_reg_power; + chan->max_power = min(chan->max_power, chan->max_reg_power); } static void handle_band(struct wiphy *wiphy, @@ -1907,7 +1885,6 @@ static void restore_custom_reg_settings(struct wiphy *wiphy) chan->flags = chan->orig_flags; chan->max_antenna_gain = chan->orig_mag; chan->max_power = chan->orig_mpwr; - chan->beacon_found = false; } } } diff --git a/trunk/net/wireless/util.c b/trunk/net/wireless/util.c index 994e2f0cc7a8..26f8cd30f712 100644 --- a/trunk/net/wireless/util.c +++ b/trunk/net/wireless/util.c @@ -735,7 +735,7 @@ void cfg80211_upload_connect_keys(struct wireless_dev *wdev) wdev->connect_keys = NULL; } -void cfg80211_process_wdev_events(struct wireless_dev *wdev) +static void cfg80211_process_wdev_events(struct wireless_dev *wdev) { struct cfg80211_event *ev; unsigned long flags; diff --git a/trunk/net/xfrm/xfrm_input.c b/trunk/net/xfrm/xfrm_input.c index ab2bb42fe094..54a0dc2e2f8d 100644 --- a/trunk/net/xfrm/xfrm_input.c +++ b/trunk/net/xfrm/xfrm_input.c @@ -212,7 +212,7 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type) /* only the first xfrm gets the encap type */ encap_type = 0; - if (async && x->repl->recheck(x, skb, seq)) { + if (async && x->repl->check(x, skb, seq)) { XFRM_INC_STATS(net, LINUX_MIB_XFRMINSTATESEQERROR); goto drop_unlock; } diff --git a/trunk/net/xfrm/xfrm_policy.c b/trunk/net/xfrm/xfrm_policy.c index 387848e90078..c5a5165a5927 100644 --- a/trunk/net/xfrm/xfrm_policy.c +++ b/trunk/net/xfrm/xfrm_policy.c @@ -585,7 +585,6 @@ int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl) xfrm_pol_hold(policy); net->xfrm.policy_count[dir]++; atomic_inc(&flow_cache_genid); - rt_genid_bump(net); if (delpol) __xfrm_policy_unlink(delpol, dir); policy->index = delpol ? delpol->index : xfrm_gen_index(net, dir); @@ -1358,8 +1357,6 @@ static inline struct xfrm_dst *xfrm_alloc_dst(struct net *net, int family) memset(dst + 1, 0, sizeof(*xdst) - sizeof(*dst)); xdst->flo.ops = &xfrm_bundle_fc_ops; - if (afinfo->init_dst) - afinfo->init_dst(net, xdst); } else xdst = ERR_PTR(-ENOBUFS); @@ -1764,7 +1761,7 @@ static struct dst_entry *make_blackhole(struct net *net, u16 family, if (!afinfo) { dst_release(dst_orig); - return ERR_PTR(-EINVAL); + ret = ERR_PTR(-EINVAL); } else { ret = afinfo->blackhole_route(net, dst_orig); } diff --git a/trunk/net/xfrm/xfrm_replay.c b/trunk/net/xfrm/xfrm_replay.c index 3efb07d3eb27..2f6d11d04a2b 100644 --- a/trunk/net/xfrm/xfrm_replay.c +++ b/trunk/net/xfrm/xfrm_replay.c @@ -420,18 +420,6 @@ static int xfrm_replay_check_esn(struct xfrm_state *x, return -EINVAL; } -static int xfrm_replay_recheck_esn(struct xfrm_state *x, - struct sk_buff *skb, __be32 net_seq) -{ - if (unlikely(XFRM_SKB_CB(skb)->seq.input.hi != - htonl(xfrm_replay_seqhi(x, net_seq)))) { - x->stats.replay_window++; - return -EINVAL; - } - - return xfrm_replay_check_esn(x, skb, net_seq); -} - static void xfrm_replay_advance_esn(struct xfrm_state *x, __be32 net_seq) { unsigned int bitnr, nr, i; @@ -491,7 +479,6 @@ static void xfrm_replay_advance_esn(struct xfrm_state *x, __be32 net_seq) static struct xfrm_replay xfrm_replay_legacy = { .advance = xfrm_replay_advance, .check = xfrm_replay_check, - .recheck = xfrm_replay_check, .notify = xfrm_replay_notify, .overflow = xfrm_replay_overflow, }; @@ -499,7 +486,6 @@ static struct xfrm_replay xfrm_replay_legacy = { static struct xfrm_replay xfrm_replay_bmp = { .advance = xfrm_replay_advance_bmp, .check = xfrm_replay_check_bmp, - .recheck = xfrm_replay_check_bmp, .notify = xfrm_replay_notify_bmp, .overflow = xfrm_replay_overflow_bmp, }; @@ -507,7 +493,6 @@ static struct xfrm_replay xfrm_replay_bmp = { static struct xfrm_replay xfrm_replay_esn = { .advance = xfrm_replay_advance_esn, .check = xfrm_replay_check_esn, - .recheck = xfrm_replay_recheck_esn, .notify = xfrm_replay_notify_bmp, .overflow = xfrm_replay_overflow_esn, }; diff --git a/trunk/net/xfrm/xfrm_state.c b/trunk/net/xfrm/xfrm_state.c index 210be48d8ae3..5b228f97d4b3 100644 --- a/trunk/net/xfrm/xfrm_state.c +++ b/trunk/net/xfrm/xfrm_state.c @@ -415,17 +415,8 @@ static enum hrtimer_restart xfrm_timer_handler(struct hrtimer * me) if (x->lft.hard_add_expires_seconds) { long tmo = x->lft.hard_add_expires_seconds + x->curlft.add_time - now; - if (tmo <= 0) { - if (x->xflags & XFRM_SOFT_EXPIRE) { - /* enter hard expire without soft expire first?! - * setting a new date could trigger this. - * workarbound: fix x->curflt.add_time by below: - */ - x->curlft.add_time = now - x->saved_tmo - 1; - tmo = x->lft.hard_add_expires_seconds - x->saved_tmo; - } else - goto expired; - } + if (tmo <= 0) + goto expired; if (tmo < next) next = tmo; } @@ -442,14 +433,10 @@ static enum hrtimer_restart xfrm_timer_handler(struct hrtimer * me) if (x->lft.soft_add_expires_seconds) { long tmo = x->lft.soft_add_expires_seconds + x->curlft.add_time - now; - if (tmo <= 0) { + if (tmo <= 0) warn = 1; - x->xflags &= ~XFRM_SOFT_EXPIRE; - } else if (tmo < next) { + else if (tmo < next) next = tmo; - x->xflags |= XFRM_SOFT_EXPIRE; - x->saved_tmo = tmo; - } } if (x->lft.soft_use_expires_seconds) { long tmo = x->lft.soft_use_expires_seconds + @@ -1994,10 +1981,8 @@ int __xfrm_init_state(struct xfrm_state *x, bool init_replay) goto error; x->outer_mode = xfrm_get_mode(x->props.mode, family); - if (x->outer_mode == NULL) { - err = -EPROTONOSUPPORT; + if (x->outer_mode == NULL) goto error; - } if (init_replay) { err = xfrm_init_replay(x); diff --git a/trunk/net/xfrm/xfrm_user.c b/trunk/net/xfrm/xfrm_user.c index 289f4bf18ff0..e75d8e47f35c 100644 --- a/trunk/net/xfrm/xfrm_user.c +++ b/trunk/net/xfrm/xfrm_user.c @@ -123,21 +123,9 @@ static inline int verify_replay(struct xfrm_usersa_info *p, struct nlattr **attrs) { struct nlattr *rt = attrs[XFRMA_REPLAY_ESN_VAL]; - struct xfrm_replay_state_esn *rs; - if (p->flags & XFRM_STATE_ESN) { - if (!rt) - return -EINVAL; - - rs = nla_data(rt); - - if (rs->bmp_len > XFRMA_REPLAY_ESN_MAX / sizeof(rs->bmp[0]) / 8) - return -EINVAL; - - if (nla_len(rt) < xfrm_replay_state_esn_len(rs) && - nla_len(rt) != sizeof(*rs)) - return -EINVAL; - } + if ((p->flags & XFRM_STATE_ESN) && !rt) + return -EINVAL; if (!rt) return 0; @@ -382,15 +370,14 @@ static inline int xfrm_replay_verify_len(struct xfrm_replay_state_esn *replay_es struct nlattr *rp) { struct xfrm_replay_state_esn *up; - int ulen; if (!replay_esn || !rp) return 0; up = nla_data(rp); - ulen = xfrm_replay_state_esn_len(up); - if (nla_len(rp) < ulen || xfrm_replay_state_esn_len(replay_esn) != ulen) + if (xfrm_replay_state_esn_len(replay_esn) != + xfrm_replay_state_esn_len(up)) return -EINVAL; return 0; @@ -401,28 +388,22 @@ static int xfrm_alloc_replay_state_esn(struct xfrm_replay_state_esn **replay_esn struct nlattr *rta) { struct xfrm_replay_state_esn *p, *pp, *up; - int klen, ulen; if (!rta) return 0; up = nla_data(rta); - klen = xfrm_replay_state_esn_len(up); - ulen = nla_len(rta) >= klen ? klen : sizeof(*up); - p = kzalloc(klen, GFP_KERNEL); + p = kmemdup(up, xfrm_replay_state_esn_len(up), GFP_KERNEL); if (!p) return -ENOMEM; - pp = kzalloc(klen, GFP_KERNEL); + pp = kmemdup(up, xfrm_replay_state_esn_len(up), GFP_KERNEL); if (!pp) { kfree(p); return -ENOMEM; } - memcpy(p, up, ulen); - memcpy(pp, up, ulen); - *replay_esn = p; *preplay_esn = pp; @@ -461,11 +442,10 @@ static void copy_from_user_state(struct xfrm_state *x, struct xfrm_usersa_info * * somehow made shareable and move it to xfrm_state.c - JHS * */ -static void xfrm_update_ae_params(struct xfrm_state *x, struct nlattr **attrs, - int update_esn) +static void xfrm_update_ae_params(struct xfrm_state *x, struct nlattr **attrs) { struct nlattr *rp = attrs[XFRMA_REPLAY_VAL]; - struct nlattr *re = update_esn ? attrs[XFRMA_REPLAY_ESN_VAL] : NULL; + struct nlattr *re = attrs[XFRMA_REPLAY_ESN_VAL]; struct nlattr *lt = attrs[XFRMA_LTIME_VAL]; struct nlattr *et = attrs[XFRMA_ETIMER_THRESH]; struct nlattr *rt = attrs[XFRMA_REPLAY_THRESH]; @@ -575,7 +555,7 @@ static struct xfrm_state *xfrm_state_construct(struct net *net, goto error; /* override default values from above */ - xfrm_update_ae_params(x, attrs, 0); + xfrm_update_ae_params(x, attrs); return x; @@ -709,7 +689,6 @@ static int xfrm_del_sa(struct sk_buff *skb, struct nlmsghdr *nlh, static void copy_to_user_state(struct xfrm_state *x, struct xfrm_usersa_info *p) { - memset(p, 0, sizeof(*p)); memcpy(&p->id, &x->id, sizeof(p->id)); memcpy(&p->sel, &x->sel, sizeof(p->sel)); memcpy(&p->lft, &x->lft, sizeof(p->lft)); @@ -763,7 +742,7 @@ static int copy_to_user_auth(struct xfrm_algo_auth *auth, struct sk_buff *skb) return -EMSGSIZE; algo = nla_data(nla); - strncpy(algo->alg_name, auth->alg_name, sizeof(algo->alg_name)); + strcpy(algo->alg_name, auth->alg_name); memcpy(algo->alg_key, auth->alg_key, (auth->alg_key_len + 7) / 8); algo->alg_key_len = auth->alg_key_len; @@ -899,7 +878,6 @@ static struct sk_buff *xfrm_state_netlink(struct sk_buff *in_skb, { struct xfrm_dump_info info; struct sk_buff *skb; - int err; skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC); if (!skb) @@ -910,10 +888,9 @@ static struct sk_buff *xfrm_state_netlink(struct sk_buff *in_skb, info.nlmsg_seq = seq; info.nlmsg_flags = 0; - err = dump_one_state(x, 0, &info); - if (err) { + if (dump_one_state(x, 0, &info)) { kfree_skb(skb); - return ERR_PTR(err); + return NULL; } return skb; @@ -1340,7 +1317,6 @@ static void copy_from_user_policy(struct xfrm_policy *xp, struct xfrm_userpolicy static void copy_to_user_policy(struct xfrm_policy *xp, struct xfrm_userpolicy_info *p, int dir) { - memset(p, 0, sizeof(*p)); memcpy(&p->sel, &xp->selector, sizeof(p->sel)); memcpy(&p->lft, &xp->lft, sizeof(p->lft)); memcpy(&p->curlft, &xp->curlft, sizeof(p->curlft)); @@ -1445,7 +1421,6 @@ static int copy_to_user_tmpl(struct xfrm_policy *xp, struct sk_buff *skb) struct xfrm_user_tmpl *up = &vec[i]; struct xfrm_tmpl *kp = &xp->xfrm_vec[i]; - memset(up, 0, sizeof(*up)); memcpy(&up->id, &kp->id, sizeof(up->id)); up->family = kp->encap_family; memcpy(&up->saddr, &kp->saddr, sizeof(up->saddr)); @@ -1571,7 +1546,6 @@ static struct sk_buff *xfrm_policy_netlink(struct sk_buff *in_skb, { struct xfrm_dump_info info; struct sk_buff *skb; - int err; skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); if (!skb) @@ -1582,10 +1556,9 @@ static struct sk_buff *xfrm_policy_netlink(struct sk_buff *in_skb, info.nlmsg_seq = seq; info.nlmsg_flags = 0; - err = dump_one_policy(xp, dir, 0, &info); - if (err) { + if (dump_one_policy(xp, dir, 0, &info) < 0) { kfree_skb(skb); - return ERR_PTR(err); + return NULL; } return skb; @@ -1849,7 +1822,7 @@ static int xfrm_new_ae(struct sk_buff *skb, struct nlmsghdr *nlh, goto out; spin_lock_bh(&x->lock); - xfrm_update_ae_params(x, attrs, 1); + xfrm_update_ae_params(x, attrs); spin_unlock_bh(&x->lock); c.event = nlh->nlmsg_type; diff --git a/trunk/scripts/Makefile.fwinst b/trunk/scripts/Makefile.fwinst index 4d908d16c035..6bf8e87f1dcf 100644 --- a/trunk/scripts/Makefile.fwinst +++ b/trunk/scripts/Makefile.fwinst @@ -27,7 +27,7 @@ endif installed-mod-fw := $(addprefix $(INSTALL_FW_PATH)/,$(mod-fw)) installed-fw := $(addprefix $(INSTALL_FW_PATH)/,$(fw-shipped-all)) -installed-fw-dirs := $(sort $(dir $(installed-fw))) $(INSTALL_FW_PATH)/./ +installed-fw-dirs := $(sort $(dir $(installed-fw))) $(INSTALL_FW_PATH)/. # Workaround for make < 3.81, where .SECONDEXPANSION doesn't work. PHONY += $(INSTALL_FW_PATH)/$$(%) install-all-dirs diff --git a/trunk/scripts/checkpatch.pl b/trunk/scripts/checkpatch.pl index ca05ba217f5f..913d6bdfdda3 100755 --- a/trunk/scripts/checkpatch.pl +++ b/trunk/scripts/checkpatch.pl @@ -3016,8 +3016,7 @@ sub process { $herectx .= raw_line($linenr, $n) . "\n"; } - if (($stmts =~ tr/;/;/) == 1 && - $stmts !~ /^\s*(if|while|for|switch)\b/) { + if (($stmts =~ tr/;/;/) == 1) { WARN("SINGLE_STATEMENT_DO_WHILE_MACRO", "Single statement macros should not use a do {} while (0) loop\n" . "$herectx"); } diff --git a/trunk/scripts/checksyscalls.sh b/trunk/scripts/checksyscalls.sh index fd8fa9aa7c4e..d24810fc6af6 100755 --- a/trunk/scripts/checksyscalls.sh +++ b/trunk/scripts/checksyscalls.sh @@ -200,7 +200,7 @@ EOF syscall_list() { grep '^[0-9]' "$1" | sort -n | ( while read nr abi name entry ; do - cat <> $T.s disas $T cat $T.dis >> $T.aa -faultline=`cat $T.dis | head -1 | cut -d":" -f2-` +faultline=`cat $T.dis | head -1 | cut -d":" -f2` faultline=`echo "$faultline" | sed -e 's/\[/\\\[/g; s/\]/\\\]/g'` cat $T.oo | sed -e "s/\($faultline\)/\*\1 <-- trapping instruction/g" diff --git a/trunk/scripts/kconfig/streamline_config.pl b/trunk/scripts/kconfig/streamline_config.pl index 33689396953a..2fbbbc1ddea0 100644 --- a/trunk/scripts/kconfig/streamline_config.pl +++ b/trunk/scripts/kconfig/streamline_config.pl @@ -100,7 +100,7 @@ sub dprint { }, ); -sub read_config { +sub find_config { foreach my $conf (@searchconfigs) { my $file = $conf->{"file"}; @@ -115,15 +115,17 @@ sub read_config { print STDERR "using config: '$file'\n"; - open(my $infile, '-|', "$exec $file") || die "Failed to run $exec $file"; - my @x = <$infile>; - close $infile; - return @x; + open(CIN, "$exec $file |") || die "Failed to run $exec $file"; + return; } die "No config file found"; } -my @config_file = read_config; +find_config; + +# Read in the entire config file into config_file +my @config_file = ; +close CIN; # Parse options my $localmodconfig = 0; @@ -133,7 +135,7 @@ sub read_config { "localyesconfig" => \$localyesconfig); # Get the build source and top level Kconfig file (passed in) -my $ksource = ($ARGV[0] ? $ARGV[0] : '.'); +my $ksource = $ARGV[0]; my $kconfig = $ARGV[1]; my $lsmod_file = $ENV{'LSMOD'}; @@ -171,8 +173,8 @@ sub read_kconfig { $source =~ s/\$$env/$ENV{$env}/; } - open(my $kinfile, '<', $source) || die "Can't open $kconfig"; - while (<$kinfile>) { + open(KIN, "$source") || die "Can't open $kconfig"; + while () { chomp; # Make sure that lines ending with \ continue @@ -249,10 +251,10 @@ sub read_kconfig { $state = "NONE"; } } - close($kinfile); + close(KIN); # read in any configs that were found. - foreach my $kconfig (@kconfigs) { + foreach $kconfig (@kconfigs) { if (!defined($read_kconfigs{$kconfig})) { $read_kconfigs{$kconfig} = 1; read_kconfig($kconfig); @@ -293,8 +295,8 @@ sub convert_vars { my $line = ""; my %make_vars; - open(my $infile, '<', $makefile) || die "Can't open $makefile"; - while (<$infile>) { + open(MIN,$makefile) || die "Can't open $makefile"; + while () { # if this line ends with a backslash, continue chomp; if (/^(.*)\\$/) { @@ -341,11 +343,10 @@ sub convert_vars { } } } - close($infile); + close(MIN); } my %modules; -my $linfile; if (defined($lsmod_file)) { if ( ! -f $lsmod_file) { @@ -355,10 +356,13 @@ sub convert_vars { die "$lsmod_file not found"; } } - - my $otype = ( -x $lsmod_file) ? '-|' : '<'; - open($linfile, $otype, $lsmod_file); - + if ( -x $lsmod_file) { + # the file is executable, run it + open(LIN, "$lsmod_file|"); + } else { + # Just read the contents + open(LIN, "$lsmod_file"); + } } else { # see what modules are loaded on this system @@ -375,16 +379,16 @@ sub convert_vars { $lsmod = "lsmod"; } - open($linfile, '-|', $lsmod) || die "Can not call lsmod with $lsmod"; + open(LIN,"$lsmod|") || die "Can not call lsmod with $lsmod"; } -while (<$linfile>) { +while () { next if (/^Module/); # Skip the first line. if (/^(\S+)/) { $modules{$1} = 1; } } -close ($linfile); +close (LIN); # add to the configs hash all configs that are needed to enable # a loaded module. This is a direct obj-${CONFIG_FOO} += bar.o @@ -601,8 +605,6 @@ sub loop_select { if (defined($configs{$1})) { if ($localyesconfig) { $setconfigs{$1} = 'y'; - print "$1=y\n"; - next; } else { $setconfigs{$1} = $2; } diff --git a/trunk/scripts/kernel-doc b/trunk/scripts/kernel-doc index 8fd107a3fac4..9b0c0b8b4ab4 100755 --- a/trunk/scripts/kernel-doc +++ b/trunk/scripts/kernel-doc @@ -1786,7 +1786,6 @@ sub dump_function($$) { $prototype =~ s/__init +//; $prototype =~ s/__init_or_module +//; $prototype =~ s/__must_check +//; - $prototype =~ s/__weak +//; $prototype =~ s/^#\s*define\s+//; #ak added $prototype =~ s/__attribute__\s*\(\([a-z,]*\)\)//; diff --git a/trunk/scripts/link-vmlinux.sh b/trunk/scripts/link-vmlinux.sh index b3d907eb93a9..4629038c9e5a 100644 --- a/trunk/scripts/link-vmlinux.sh +++ b/trunk/scripts/link-vmlinux.sh @@ -74,13 +74,8 @@ kallsyms() info KSYM ${2} local kallsymopt; - if [ -n "${CONFIG_SYMBOL_PREFIX}" ]; then - kallsymopt="${kallsymopt} \ - --symbol-prefix=${CONFIG_SYMBOL_PREFIX}" - fi - if [ -n "${CONFIG_KALLSYMS_ALL}" ]; then - kallsymopt="${kallsymopt} --all-symbols" + kallsymopt=--all-symbols fi local aflags="${KBUILD_AFLAGS} ${KBUILD_AFLAGS_KERNEL} \ @@ -216,7 +211,7 @@ if [ -n "${CONFIG_KALLSYMS}" ]; then if ! cmp -s System.map .tmp_System.map; then echo >&2 Inconsistent kallsyms data - echo >&2 Try "make KALLSYMS_EXTRA_PASS=1" as a workaround + echo >&2 echo Try "make KALLSYMS_EXTRA_PASS=1" as a workaround cleanup exit 1 fi diff --git a/trunk/scripts/mod/file2alias.c b/trunk/scripts/mod/file2alias.c index df4fc23dd836..7ed6864ef65b 100644 --- a/trunk/scripts/mod/file2alias.c +++ b/trunk/scripts/mod/file2alias.c @@ -966,21 +966,6 @@ static int do_isapnp_entry(const char *filename, } ADD_TO_DEVTABLE("isapnp", struct isapnp_device_id, do_isapnp_entry); -/* Looks like: "ipack:fNvNdN". */ -static int do_ipack_entry(const char *filename, - struct ipack_device_id *id, char *alias) -{ - id->vendor = TO_NATIVE(id->vendor); - id->device = TO_NATIVE(id->device); - strcpy(alias, "ipack:"); - ADD(alias, "f", id->format != IPACK_ANY_FORMAT, id->format); - ADD(alias, "v", id->vendor != IPACK_ANY_ID, id->vendor); - ADD(alias, "d", id->device != IPACK_ANY_ID, id->device); - add_wildcard(alias); - return 1; -} -ADD_TO_DEVTABLE("ipack", struct ipack_device_id, do_ipack_entry); - /* * Append a match expression for a single masked hex digit. * outp points to a pointer to the character at which to append. diff --git a/trunk/scripts/recordmcount.h b/trunk/scripts/recordmcount.h index 9d1421e63ff8..54e35c1e5948 100644 --- a/trunk/scripts/recordmcount.h +++ b/trunk/scripts/recordmcount.h @@ -261,13 +261,11 @@ static unsigned get_mcountsym(Elf_Sym const *const sym0, &sym0[Elf_r_sym(relp)]; char const *symname = &str0[w(symp->st_name)]; char const *mcount = gpfx == '_' ? "_mcount" : "mcount"; - char const *fentry = "__fentry__"; if (symname[0] == '.') ++symname; /* ppc64 hack */ if (strcmp(mcount, symname) == 0 || - (altmcount && strcmp(altmcount, symname) == 0) || - (strcmp(fentry, symname) == 0)) + (altmcount && strcmp(altmcount, symname) == 0)) mcountsym = Elf_r_sym(relp); return mcountsym; diff --git a/trunk/scripts/sortextable.c b/trunk/scripts/sortextable.c index f19ddc47304c..6acf83449105 100644 --- a/trunk/scripts/sortextable.c +++ b/trunk/scripts/sortextable.c @@ -161,7 +161,7 @@ typedef void (*table_sort_t)(char *, int); #define SORTEXTABLE_64 #include "sortextable.h" -static int compare_relative_table(const void *a, const void *b) +static int compare_x86_table(const void *a, const void *b) { int32_t av = (int32_t)r(a); int32_t bv = (int32_t)r(b); @@ -173,7 +173,7 @@ static int compare_relative_table(const void *a, const void *b) return 0; } -static void sort_relative_table(char *extab_image, int image_size) +static void sort_x86_table(char *extab_image, int image_size) { int i; @@ -188,7 +188,7 @@ static void sort_relative_table(char *extab_image, int image_size) i += 4; } - qsort(extab_image, image_size / 8, 8, compare_relative_table); + qsort(extab_image, image_size / 8, 8, compare_x86_table); /* Now denormalize. */ i = 0; @@ -245,9 +245,9 @@ do_file(char const *const fname) break; case EM_386: case EM_X86_64: - case EM_S390: - custom_sort = sort_relative_table; + custom_sort = sort_x86_table; break; + case EM_S390: case EM_MIPS: break; } /* end switch */ diff --git a/trunk/security/apparmor/.gitignore b/trunk/security/apparmor/.gitignore index 9cdec70d72b8..4d995aeaebc0 100644 --- a/trunk/security/apparmor/.gitignore +++ b/trunk/security/apparmor/.gitignore @@ -1,5 +1,6 @@ # # Generated include files # +af_names.h capability_names.h rlim_names.h diff --git a/trunk/security/keys/keyctl.c b/trunk/security/keys/keyctl.c index 6cfc6478863e..3364fbf46807 100644 --- a/trunk/security/keys/keyctl.c +++ b/trunk/security/keys/keyctl.c @@ -1486,6 +1486,7 @@ long keyctl_session_to_parent(void) oldwork = NULL; parent = me->real_parent; + task_lock(parent); /* the parent mustn't be init and mustn't be a kernel thread */ if (parent->pid <= 1 || !parent->mm) goto unlock; @@ -1529,6 +1530,7 @@ long keyctl_session_to_parent(void) if (!ret) newwork = NULL; unlock: + task_unlock(parent); write_unlock_irq(&tasklist_lock); rcu_read_unlock(); if (oldwork) diff --git a/trunk/security/selinux/include/xfrm.h b/trunk/security/selinux/include/xfrm.h index 65f67cb0aefb..c220f314709c 100644 --- a/trunk/security/selinux/include/xfrm.h +++ b/trunk/security/selinux/include/xfrm.h @@ -51,7 +51,6 @@ int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int ckall); static inline void selinux_xfrm_notify_policyload(void) { atomic_inc(&flow_cache_genid); - rt_genid_bump(&init_net); } #else static inline int selinux_xfrm_enabled(void) diff --git a/trunk/security/yama/yama_lsm.c b/trunk/security/yama/yama_lsm.c index 0cc99a3ea42d..83554ee8a587 100644 --- a/trunk/security/yama/yama_lsm.c +++ b/trunk/security/yama/yama_lsm.c @@ -279,46 +279,12 @@ static int yama_ptrace_access_check(struct task_struct *child, } if (rc) { + char name[sizeof(current->comm)]; printk_ratelimited(KERN_NOTICE "ptrace of pid %d was attempted by: %s (pid %d)\n", - child->pid, current->comm, current->pid); - } - - return rc; -} - -/** - * yama_ptrace_traceme - validate PTRACE_TRACEME calls - * @parent: task that will become the ptracer of the current task - * - * Returns 0 if following the ptrace is allowed, -ve on error. - */ -static int yama_ptrace_traceme(struct task_struct *parent) -{ - int rc; - - /* If standard caps disallows it, so does Yama. We should - * only tighten restrictions further. - */ - rc = cap_ptrace_traceme(parent); - if (rc) - return rc; - - /* Only disallow PTRACE_TRACEME on more aggressive settings. */ - switch (ptrace_scope) { - case YAMA_SCOPE_CAPABILITY: - if (!ns_capable(task_user_ns(parent), CAP_SYS_PTRACE)) - rc = -EPERM; - break; - case YAMA_SCOPE_NO_ATTACH: - rc = -EPERM; - break; - } - - if (rc) { - printk_ratelimited(KERN_NOTICE - "ptraceme of pid %d was attempted by: %s (pid %d)\n", - current->pid, parent->comm, parent->pid); + child->pid, + get_task_comm(name, current), + current->pid); } return rc; @@ -328,7 +294,6 @@ static struct security_operations yama_ops = { .name = "yama", .ptrace_access_check = yama_ptrace_access_check, - .ptrace_traceme = yama_ptrace_traceme, .task_prctl = yama_task_prctl, .task_free = yama_task_free, }; diff --git a/trunk/sound/arm/pxa2xx-ac97.c b/trunk/sound/arm/pxa2xx-ac97.c index 4e1fda75c1c9..0d7b25e81643 100644 --- a/trunk/sound/arm/pxa2xx-ac97.c +++ b/trunk/sound/arm/pxa2xx-ac97.c @@ -106,7 +106,7 @@ static struct pxa2xx_pcm_client pxa2xx_ac97_pcm_client = { .prepare = pxa2xx_ac97_pcm_prepare, }; -#ifdef CONFIG_PM_SLEEP +#ifdef CONFIG_PM static int pxa2xx_ac97_do_suspend(struct snd_card *card) { @@ -243,7 +243,7 @@ static struct platform_driver pxa2xx_ac97_driver = { .driver = { .name = "pxa2xx-ac97", .owner = THIS_MODULE, -#ifdef CONFIG_PM_SLEEP +#ifdef CONFIG_PM .pm = &pxa2xx_ac97_pm_ops, #endif }, diff --git a/trunk/sound/atmel/abdac.c b/trunk/sound/atmel/abdac.c index 277ebce23a45..eb4ceb71123e 100644 --- a/trunk/sound/atmel/abdac.c +++ b/trunk/sound/atmel/abdac.c @@ -452,7 +452,6 @@ static int __devinit atmel_abdac_probe(struct platform_device *pdev) dac->regs = ioremap(regs->start, resource_size(regs)); if (!dac->regs) { dev_dbg(&pdev->dev, "could not remap register memory\n"); - retval = -ENOMEM; goto out_free_card; } @@ -535,7 +534,7 @@ static int __devinit atmel_abdac_probe(struct platform_device *pdev) return retval; } -#ifdef CONFIG_PM_SLEEP +#ifdef CONFIG_PM static int atmel_abdac_suspend(struct device *pdev) { struct snd_card *card = dev_get_drvdata(pdev); diff --git a/trunk/sound/atmel/ac97c.c b/trunk/sound/atmel/ac97c.c index 9052aff37f64..bf47025bdf45 100644 --- a/trunk/sound/atmel/ac97c.c +++ b/trunk/sound/atmel/ac97c.c @@ -278,9 +278,14 @@ static int atmel_ac97c_capture_hw_params(struct snd_pcm_substream *substream, if (retval < 0) return retval; /* snd_pcm_lib_malloc_pages returns 1 if buffer is changed. */ - if (cpu_is_at32ap7000() && retval == 1) - if (test_and_clear_bit(DMA_RX_READY, &chip->flags)) - dw_dma_cyclic_free(chip->dma.rx_chan); + if (cpu_is_at32ap7000()) { + if (retval < 0) + return retval; + /* snd_pcm_lib_malloc_pages returns 1 if buffer is changed. */ + if (retval == 1) + if (test_and_clear_bit(DMA_RX_READY, &chip->flags)) + dw_dma_cyclic_free(chip->dma.rx_chan); + } /* Set restrictions to params. */ mutex_lock(&opened_mutex); @@ -975,7 +980,6 @@ static int __devinit atmel_ac97c_probe(struct platform_device *pdev) if (!chip->regs) { dev_dbg(&pdev->dev, "could not remap register memory\n"); - retval = -ENOMEM; goto err_ioremap; } @@ -1130,7 +1134,7 @@ static int __devinit atmel_ac97c_probe(struct platform_device *pdev) return retval; } -#ifdef CONFIG_PM_SLEEP +#ifdef CONFIG_PM static int atmel_ac97c_suspend(struct device *pdev) { struct snd_card *card = dev_get_drvdata(pdev); diff --git a/trunk/sound/core/compress_offload.c b/trunk/sound/core/compress_offload.c index eb60cb8dbb8a..ec2118d0e27a 100644 --- a/trunk/sound/core/compress_offload.c +++ b/trunk/sound/core/compress_offload.c @@ -80,12 +80,14 @@ static int snd_compr_open(struct inode *inode, struct file *f) int maj = imajor(inode); int ret; - if ((f->f_flags & O_ACCMODE) == O_WRONLY) + if (f->f_flags & O_WRONLY) dirn = SND_COMPRESS_PLAYBACK; - else if ((f->f_flags & O_ACCMODE) == O_RDONLY) + else if (f->f_flags & O_RDONLY) dirn = SND_COMPRESS_CAPTURE; - else + else { + pr_err("invalid direction\n"); return -EINVAL; + } if (maj == snd_major) compr = snd_lookup_minor_data(iminor(inode), diff --git a/trunk/sound/core/sgbuf.c b/trunk/sound/core/sgbuf.c index d0f00356fc11..4e7ec2b49873 100644 --- a/trunk/sound/core/sgbuf.c +++ b/trunk/sound/core/sgbuf.c @@ -101,7 +101,7 @@ void *snd_malloc_sgbuf_pages(struct device *device, if (snd_dma_alloc_pages_fallback(SNDRV_DMA_TYPE_DEV, device, chunk, &tmpb) < 0) { if (!sgbuf->pages) - goto _failed; + return NULL; if (!res_size) goto _failed; size = sgbuf->pages * PAGE_SIZE; diff --git a/trunk/sound/drivers/aloop.c b/trunk/sound/drivers/aloop.c index 5a34355e78e8..1128b35b2b05 100644 --- a/trunk/sound/drivers/aloop.c +++ b/trunk/sound/drivers/aloop.c @@ -1176,7 +1176,7 @@ static int __devexit loopback_remove(struct platform_device *devptr) return 0; } -#ifdef CONFIG_PM_SLEEP +#ifdef CONFIG_PM static int loopback_suspend(struct device *pdev) { struct snd_card *card = dev_get_drvdata(pdev); diff --git a/trunk/sound/drivers/dummy.c b/trunk/sound/drivers/dummy.c index 54bb6644a598..f7d3bfc6bca8 100644 --- a/trunk/sound/drivers/dummy.c +++ b/trunk/sound/drivers/dummy.c @@ -1064,7 +1064,7 @@ static int __devexit snd_dummy_remove(struct platform_device *devptr) return 0; } -#ifdef CONFIG_PM_SLEEP +#ifdef CONFIG_PM static int snd_dummy_suspend(struct device *pdev) { struct snd_card *card = dev_get_drvdata(pdev); diff --git a/trunk/sound/drivers/pcsp/pcsp.c b/trunk/sound/drivers/pcsp/pcsp.c index ef171295f6d4..6ca59fc6dcb9 100644 --- a/trunk/sound/drivers/pcsp/pcsp.c +++ b/trunk/sound/drivers/pcsp/pcsp.c @@ -199,7 +199,7 @@ static void pcsp_stop_beep(struct snd_pcsp *chip) pcspkr_stop_sound(); } -#ifdef CONFIG_PM_SLEEP +#ifdef CONFIG_PM static int pcsp_suspend(struct device *dev) { struct snd_pcsp *chip = dev_get_drvdata(dev); @@ -212,7 +212,7 @@ static SIMPLE_DEV_PM_OPS(pcsp_pm, pcsp_suspend, NULL); #define PCSP_PM_OPS &pcsp_pm #else #define PCSP_PM_OPS NULL -#endif /* CONFIG_PM_SLEEP */ +#endif /* CONFIG_PM */ static void pcsp_shutdown(struct platform_device *dev) { diff --git a/trunk/sound/isa/als100.c b/trunk/sound/isa/als100.c index f7cdaf51512d..2d67c78c9f4b 100644 --- a/trunk/sound/isa/als100.c +++ b/trunk/sound/isa/als100.c @@ -233,7 +233,7 @@ static int __devinit snd_card_als100_probe(int dev, irq[dev], dma8[dev], dma16[dev]); } - if ((error = snd_sb16dsp_pcm(chip, 0, &chip->pcm)) < 0) { + if ((error = snd_sb16dsp_pcm(chip, 0, NULL)) < 0) { snd_card_free(card); return error; } diff --git a/trunk/sound/oss/.gitignore b/trunk/sound/oss/.gitignore index 12a3920d6fb6..7efb12b45502 100644 --- a/trunk/sound/oss/.gitignore +++ b/trunk/sound/oss/.gitignore @@ -1,3 +1,4 @@ #Ignore generated files +maui_boot.h pss_boot.h trix_boot.h diff --git a/trunk/sound/oss/sb_audio.c b/trunk/sound/oss/sb_audio.c index b2b3c014221a..733b014ec7d1 100644 --- a/trunk/sound/oss/sb_audio.c +++ b/trunk/sound/oss/sb_audio.c @@ -575,15 +575,13 @@ static int jazz16_audio_set_speed(int dev, int speed) if (speed > 0) { int tmp; - int s; + int s = speed * devc->channels; if (speed < 5000) speed = 5000; if (speed > 44100) speed = 44100; - s = speed * devc->channels; - devc->tconst = (256 - ((1000000 + s / 2) / s)) & 0xff; tmp = 256 - devc->tconst; diff --git a/trunk/sound/pci/cs46xx/cs46xx_lib.c b/trunk/sound/pci/cs46xx/cs46xx_lib.c index a71d1c14a0f6..f75f5ffdfdfb 100644 --- a/trunk/sound/pci/cs46xx/cs46xx_lib.c +++ b/trunk/sound/pci/cs46xx/cs46xx_lib.c @@ -94,7 +94,7 @@ static unsigned short snd_cs46xx_codec_read(struct snd_cs46xx *chip, if (snd_BUG_ON(codec_index != CS46XX_PRIMARY_CODEC_INDEX && codec_index != CS46XX_SECONDARY_CODEC_INDEX)) - return 0xffff; + return -EINVAL; chip->active_ctrl(chip, 1); diff --git a/trunk/sound/pci/ctxfi/ctatc.c b/trunk/sound/pci/ctxfi/ctatc.c index 2f6e9c762d3f..8e40262d4117 100644 --- a/trunk/sound/pci/ctxfi/ctatc.c +++ b/trunk/sound/pci/ctxfi/ctatc.c @@ -1725,10 +1725,8 @@ int __devinit ct_atc_create(struct snd_card *card, struct pci_dev *pci, atc_connect_resources(atc); atc->timer = ct_timer_new(atc); - if (!atc->timer) { - err = -ENOMEM; + if (!atc->timer) goto error1; - } err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, atc, &ops); if (err < 0) diff --git a/trunk/sound/pci/emu10k1/memory.c b/trunk/sound/pci/emu10k1/memory.c index 0a436626182b..4f502a2bdc3c 100644 --- a/trunk/sound/pci/emu10k1/memory.c +++ b/trunk/sound/pci/emu10k1/memory.c @@ -326,10 +326,7 @@ snd_emu10k1_alloc_pages(struct snd_emu10k1 *emu, struct snd_pcm_substream *subst for (page = blk->first_page; page <= blk->last_page; page++, idx++) { unsigned long ofs = idx << PAGE_SHIFT; dma_addr_t addr; - if (ofs >= runtime->dma_bytes) - addr = emu->silent_page.addr; - else - addr = snd_pcm_sgbuf_get_addr(substream, ofs); + addr = snd_pcm_sgbuf_get_addr(substream, ofs); if (! is_valid_page(emu, addr)) { printk(KERN_ERR "emu: failure page = %d\n", idx); mutex_unlock(&hdr->block_mutex); diff --git a/trunk/sound/pci/hda/hda_auto_parser.c b/trunk/sound/pci/hda/hda_auto_parser.c index 4f7d2dfcef7b..647218d69f68 100644 --- a/trunk/sound/pci/hda/hda_auto_parser.c +++ b/trunk/sound/pci/hda/hda_auto_parser.c @@ -332,12 +332,13 @@ int snd_hda_parse_pin_defcfg(struct hda_codec *codec, if (cfg->dig_outs) snd_printd(" dig-out=0x%x/0x%x\n", cfg->dig_out_pins[0], cfg->dig_out_pins[1]); - snd_printd(" inputs:\n"); + snd_printd(" inputs:"); for (i = 0; i < cfg->num_inputs; i++) { - snd_printd(" %s=0x%x\n", + snd_printd(" %s=0x%x", hda_get_autocfg_input_label(codec, cfg, i), cfg->inputs[i].pin); } + snd_printd("\n"); if (cfg->dig_in_pin) snd_printd(" dig-in=0x%x\n", cfg->dig_in_pin); diff --git a/trunk/sound/pci/hda/hda_beep.c b/trunk/sound/pci/hda/hda_beep.c index 0849aac449f2..0bc2315b181d 100644 --- a/trunk/sound/pci/hda/hda_beep.c +++ b/trunk/sound/pci/hda/hda_beep.c @@ -231,22 +231,16 @@ void snd_hda_detach_beep_device(struct hda_codec *codec) } EXPORT_SYMBOL_HDA(snd_hda_detach_beep_device); -static bool ctl_has_mute(struct snd_kcontrol *kcontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - return query_amp_caps(codec, get_amp_nid(kcontrol), - get_amp_direction(kcontrol)) & AC_AMPCAP_MUTE; -} - /* get/put callbacks for beep mute mixer switches */ int snd_hda_mixer_amp_switch_get_beep(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct hda_codec *codec = snd_kcontrol_chip(kcontrol); struct hda_beep *beep = codec->beep; - if (beep && (!beep->enabled || !ctl_has_mute(kcontrol))) { + if (beep) { ucontrol->value.integer.value[0] = - ucontrol->value.integer.value[1] = beep->enabled; + ucontrol->value.integer.value[1] = + beep->enabled; return 0; } return snd_hda_mixer_amp_switch_get(kcontrol, ucontrol); @@ -258,20 +252,9 @@ int snd_hda_mixer_amp_switch_put_beep(struct snd_kcontrol *kcontrol, { struct hda_codec *codec = snd_kcontrol_chip(kcontrol); struct hda_beep *beep = codec->beep; - if (beep) { - u8 chs = get_amp_channels(kcontrol); - int enable = 0; - long *valp = ucontrol->value.integer.value; - if (chs & 1) { - enable |= *valp; - valp++; - } - if (chs & 2) - enable |= *valp; - snd_hda_enable_beep_device(codec, enable); - } - if (!ctl_has_mute(kcontrol)) - return 0; + if (beep) + snd_hda_enable_beep_device(codec, + *ucontrol->value.integer.value); return snd_hda_mixer_amp_switch_put(kcontrol, ucontrol); } EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_put_beep); diff --git a/trunk/sound/pci/hda/hda_codec.c b/trunk/sound/pci/hda/hda_codec.c index 1c65cc5e3a31..88a9c20eb7a2 100644 --- a/trunk/sound/pci/hda/hda_codec.c +++ b/trunk/sound/pci/hda/hda_codec.c @@ -1209,9 +1209,6 @@ static void snd_hda_codec_free(struct hda_codec *codec) kfree(codec); } -static bool snd_hda_codec_get_supported_ps(struct hda_codec *codec, - hda_nid_t fg, unsigned int power_state); - static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg, unsigned int power_state); @@ -1320,10 +1317,6 @@ int /*__devinit*/ snd_hda_codec_new(struct hda_bus *bus, AC_VERB_GET_SUBSYSTEM_ID, 0); } - codec->epss = snd_hda_codec_get_supported_ps(codec, - codec->afg ? codec->afg : codec->mfg, - AC_PWRST_EPSS); - /* power-up all before initialization */ hda_set_power_state(codec, codec->afg ? codec->afg : codec->mfg, @@ -1393,44 +1386,6 @@ int snd_hda_codec_configure(struct hda_codec *codec) } EXPORT_SYMBOL_HDA(snd_hda_codec_configure); -/* update the stream-id if changed */ -static void update_pcm_stream_id(struct hda_codec *codec, - struct hda_cvt_setup *p, hda_nid_t nid, - u32 stream_tag, int channel_id) -{ - unsigned int oldval, newval; - - if (p->stream_tag != stream_tag || p->channel_id != channel_id) { - oldval = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONV, 0); - newval = (stream_tag << 4) | channel_id; - if (oldval != newval) - snd_hda_codec_write(codec, nid, 0, - AC_VERB_SET_CHANNEL_STREAMID, - newval); - p->stream_tag = stream_tag; - p->channel_id = channel_id; - } -} - -/* update the format-id if changed */ -static void update_pcm_format(struct hda_codec *codec, struct hda_cvt_setup *p, - hda_nid_t nid, int format) -{ - unsigned int oldval; - - if (p->format_id != format) { - oldval = snd_hda_codec_read(codec, nid, 0, - AC_VERB_GET_STREAM_FORMAT, 0); - if (oldval != format) { - msleep(1); - snd_hda_codec_write(codec, nid, 0, - AC_VERB_SET_STREAM_FORMAT, - format); - } - p->format_id = format; - } -} - /** * snd_hda_codec_setup_stream - set up the codec for streaming * @codec: the CODEC to set up @@ -1445,6 +1400,7 @@ void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid, { struct hda_codec *c; struct hda_cvt_setup *p; + unsigned int oldval, newval; int type; int i; @@ -1457,13 +1413,29 @@ void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid, p = get_hda_cvt_setup(codec, nid); if (!p) return; - - if (codec->pcm_format_first) - update_pcm_format(codec, p, nid, format); - update_pcm_stream_id(codec, p, nid, stream_tag, channel_id); - if (!codec->pcm_format_first) - update_pcm_format(codec, p, nid, format); - + /* update the stream-id if changed */ + if (p->stream_tag != stream_tag || p->channel_id != channel_id) { + oldval = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONV, 0); + newval = (stream_tag << 4) | channel_id; + if (oldval != newval) + snd_hda_codec_write(codec, nid, 0, + AC_VERB_SET_CHANNEL_STREAMID, + newval); + p->stream_tag = stream_tag; + p->channel_id = channel_id; + } + /* update the format-id if changed */ + if (p->format_id != format) { + oldval = snd_hda_codec_read(codec, nid, 0, + AC_VERB_GET_STREAM_FORMAT, 0); + if (oldval != format) { + msleep(1); + snd_hda_codec_write(codec, nid, 0, + AC_VERB_SET_STREAM_FORMAT, + format); + } + p->format_id = format; + } p->active = 1; p->dirty = 0; @@ -2353,7 +2325,6 @@ int snd_hda_codec_reset(struct hda_codec *codec) } if (codec->patch_ops.free) codec->patch_ops.free(codec); - memset(&codec->patch_ops, 0, sizeof(codec->patch_ops)); snd_hda_jack_tbl_clear(codec); codec->proc_widget_hook = NULL; codec->spec = NULL; @@ -2369,6 +2340,7 @@ int snd_hda_codec_reset(struct hda_codec *codec) codec->num_pcms = 0; codec->pcm_info = NULL; codec->preset = NULL; + memset(&codec->patch_ops, 0, sizeof(codec->patch_ops)); codec->slave_dig_outs = NULL; codec->spdif_status_reset = 0; module_put(codec->owner); @@ -3525,7 +3497,7 @@ static bool snd_hda_codec_get_supported_ps(struct hda_codec *codec, hda_nid_t fg { int sup = snd_hda_param_read(codec, fg, AC_PAR_POWER_STATE); - if (sup == -1) + if (sup < 0) return false; if (sup & power_state) return true; @@ -3550,7 +3522,8 @@ static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg, /* this delay seems necessary to avoid click noise at power-down */ if (power_state == AC_PWRST_D3) { /* transition time less than 10ms for power down */ - msleep(codec->epss ? 10 : 100); + bool epss = snd_hda_codec_get_supported_ps(codec, fg, AC_PWRST_EPSS); + msleep(epss ? 10 : 100); } /* repeat power states setting at most 10 times*/ @@ -4460,8 +4433,6 @@ static void __snd_hda_power_up(struct hda_codec *codec, bool wait_power_down) * then there is no need to go through power up here. */ if (codec->power_on) { - if (codec->power_transition < 0) - codec->power_transition = 0; spin_unlock(&codec->power_lock); return; } diff --git a/trunk/sound/pci/hda/hda_codec.h b/trunk/sound/pci/hda/hda_codec.h index e5a7e19a8071..c422d330ca54 100644 --- a/trunk/sound/pci/hda/hda_codec.h +++ b/trunk/sound/pci/hda/hda_codec.h @@ -861,8 +861,6 @@ struct hda_codec { unsigned int no_trigger_sense:1; /* don't trigger at pin-sensing */ unsigned int ignore_misc_bit:1; /* ignore MISC_NO_PRESENCE bit */ unsigned int no_jack_detect:1; /* Machine has no jack-detection */ - unsigned int pcm_format_first:1; /* PCM format must be set first */ - unsigned int epss:1; /* supporting EPSS? */ #ifdef CONFIG_SND_HDA_POWER_SAVE unsigned int power_on :1; /* current (global) power-state */ int power_transition; /* power-state in transition */ diff --git a/trunk/sound/pci/hda/hda_intel.c b/trunk/sound/pci/hda/hda_intel.c index c4763c52eaf6..c8aced182fd1 100644 --- a/trunk/sound/pci/hda/hda_intel.c +++ b/trunk/sound/pci/hda/hda_intel.c @@ -151,7 +151,6 @@ MODULE_SUPPORTED_DEVICE("{{Intel, ICH6}," "{Intel, CPT}," "{Intel, PPT}," "{Intel, LPT}," - "{Intel, LPT_LP}," "{Intel, HPT}," "{Intel, PBG}," "{Intel, SCH}," @@ -2701,8 +2700,6 @@ static struct snd_pci_quirk position_fix_list[] __devinitdata = { SND_PCI_QUIRK(0x1043, 0x813d, "ASUS P5AD2", POS_FIX_LPIB), SND_PCI_QUIRK(0x1043, 0x81b3, "ASUS", POS_FIX_LPIB), SND_PCI_QUIRK(0x1043, 0x81e7, "ASUS M2V", POS_FIX_LPIB), - SND_PCI_QUIRK(0x1043, 0x1ac3, "ASUS X53S", POS_FIX_POSBUF), - SND_PCI_QUIRK(0x1043, 0x1b43, "ASUS K53E", POS_FIX_POSBUF), SND_PCI_QUIRK(0x104d, 0x9069, "Sony VPCS11V9E", POS_FIX_LPIB), SND_PCI_QUIRK(0x10de, 0xcb89, "Macbook Pro 7,1", POS_FIX_LPIB), SND_PCI_QUIRK(0x1297, 0x3166, "Shuttle", POS_FIX_LPIB), @@ -3273,14 +3270,6 @@ static DEFINE_PCI_DEVICE_TABLE(azx_ids) = { { PCI_DEVICE(0x8086, 0x8c20), .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP | AZX_DCAPS_BUFSIZE | AZX_DCAPS_POSFIX_COMBO }, - /* Lynx Point-LP */ - { PCI_DEVICE(0x8086, 0x9c20), - .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP | - AZX_DCAPS_BUFSIZE | AZX_DCAPS_POSFIX_COMBO }, - /* Lynx Point-LP */ - { PCI_DEVICE(0x8086, 0x9c21), - .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP | - AZX_DCAPS_BUFSIZE | AZX_DCAPS_POSFIX_COMBO }, /* Haswell */ { PCI_DEVICE(0x8086, 0x0c0c), .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_SCH_SNOOP | diff --git a/trunk/sound/pci/hda/hda_proc.c b/trunk/sound/pci/hda/hda_proc.c index 6894ec66258c..7e46258fc700 100644 --- a/trunk/sound/pci/hda/hda_proc.c +++ b/trunk/sound/pci/hda/hda_proc.c @@ -412,7 +412,7 @@ static void print_digital_conv(struct snd_info_buffer *buffer, if (digi1 & AC_DIG1_EMPHASIS) snd_iprintf(buffer, " Preemphasis"); if (digi1 & AC_DIG1_COPYRIGHT) - snd_iprintf(buffer, " Non-Copyright"); + snd_iprintf(buffer, " Copyright"); if (digi1 & AC_DIG1_NONAUDIO) snd_iprintf(buffer, " Non-Audio"); if (digi1 & AC_DIG1_PROFESSIONAL) diff --git a/trunk/sound/pci/hda/patch_ca0132.c b/trunk/sound/pci/hda/patch_ca0132.c index 49750a96d649..d0d3540e39e7 100644 --- a/trunk/sound/pci/hda/patch_ca0132.c +++ b/trunk/sound/pci/hda/patch_ca0132.c @@ -246,7 +246,7 @@ static void init_output(struct hda_codec *codec, hda_nid_t pin, hda_nid_t dac) AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE); } - if (dac && (get_wcaps(codec, dac) & AC_WCAP_OUT_AMP)) + if (dac) snd_hda_codec_write(codec, dac, 0, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO); } @@ -261,7 +261,7 @@ static void init_input(struct hda_codec *codec, hda_nid_t pin, hda_nid_t adc) AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)); } - if (adc && (get_wcaps(codec, adc) & AC_WCAP_IN_AMP)) + if (adc) snd_hda_codec_write(codec, adc, 0, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)); } @@ -275,10 +275,6 @@ static int _add_switch(struct hda_codec *codec, hda_nid_t nid, const char *pfx, int type = dir ? HDA_INPUT : HDA_OUTPUT; struct snd_kcontrol_new knew = HDA_CODEC_MUTE_MONO(namestr, nid, chan, 0, type); - if ((query_amp_caps(codec, nid, type) & AC_AMPCAP_MUTE) == 0) { - snd_printdd("Skipping '%s %s Switch' (no mute on node 0x%x)\n", pfx, dirstr[dir], nid); - return 0; - } sprintf(namestr, "%s %s Switch", pfx, dirstr[dir]); return snd_hda_ctl_add(codec, nid, snd_ctl_new1(&knew, codec)); } @@ -290,10 +286,6 @@ static int _add_volume(struct hda_codec *codec, hda_nid_t nid, const char *pfx, int type = dir ? HDA_INPUT : HDA_OUTPUT; struct snd_kcontrol_new knew = HDA_CODEC_VOLUME_MONO(namestr, nid, chan, 0, type); - if ((query_amp_caps(codec, nid, type) & AC_AMPCAP_NUM_STEPS) == 0) { - snd_printdd("Skipping '%s %s Volume' (no amp on node 0x%x)\n", pfx, dirstr[dir], nid); - return 0; - } sprintf(namestr, "%s %s Volume", pfx, dirstr[dir]); return snd_hda_ctl_add(codec, nid, snd_ctl_new1(&knew, codec)); } @@ -472,17 +464,50 @@ static int chipio_read(struct hda_codec *codec, } /* - * PCM callbacks + * PCM stuffs */ -static int ca0132_playback_pcm_open(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - struct snd_pcm_substream *substream) +static void ca0132_setup_stream(struct hda_codec *codec, hda_nid_t nid, + u32 stream_tag, + int channel_id, int format) { - struct ca0132_spec *spec = codec->spec; - return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream, - hinfo); + unsigned int oldval, newval; + + if (!nid) + return; + + snd_printdd("ca0132_setup_stream: " + "NID=0x%x, stream=0x%x, channel=%d, format=0x%x\n", + nid, stream_tag, channel_id, format); + + /* update the format-id if changed */ + oldval = snd_hda_codec_read(codec, nid, 0, + AC_VERB_GET_STREAM_FORMAT, + 0); + if (oldval != format) { + msleep(20); + snd_hda_codec_write(codec, nid, 0, + AC_VERB_SET_STREAM_FORMAT, + format); + } + + oldval = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONV, 0); + newval = (stream_tag << 4) | channel_id; + if (oldval != newval) { + snd_hda_codec_write(codec, nid, 0, + AC_VERB_SET_CHANNEL_STREAMID, + newval); + } } +static void ca0132_cleanup_stream(struct hda_codec *codec, hda_nid_t nid) +{ + snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_STREAM_FORMAT, 0); + snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CHANNEL_STREAMID, 0); +} + +/* + * PCM callbacks + */ static int ca0132_playback_pcm_prepare(struct hda_pcm_stream *hinfo, struct hda_codec *codec, unsigned int stream_tag, @@ -490,8 +515,10 @@ static int ca0132_playback_pcm_prepare(struct hda_pcm_stream *hinfo, struct snd_pcm_substream *substream) { struct ca0132_spec *spec = codec->spec; - return snd_hda_multi_out_analog_prepare(codec, &spec->multiout, - stream_tag, format, substream); + + ca0132_setup_stream(codec, spec->dacs[0], stream_tag, 0, format); + + return 0; } static int ca0132_playback_pcm_cleanup(struct hda_pcm_stream *hinfo, @@ -499,45 +526,92 @@ static int ca0132_playback_pcm_cleanup(struct hda_pcm_stream *hinfo, struct snd_pcm_substream *substream) { struct ca0132_spec *spec = codec->spec; - return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout); + + ca0132_cleanup_stream(codec, spec->dacs[0]); + + return 0; } /* * Digital out */ -static int ca0132_dig_playback_pcm_open(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - struct snd_pcm_substream *substream) +static int ca0132_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo, + struct hda_codec *codec, + unsigned int stream_tag, + unsigned int format, + struct snd_pcm_substream *substream) { struct ca0132_spec *spec = codec->spec; - return snd_hda_multi_out_dig_open(codec, &spec->multiout); + + ca0132_setup_stream(codec, spec->dig_out, stream_tag, 0, format); + + return 0; } -static int ca0132_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo, +static int ca0132_dig_playback_pcm_cleanup(struct hda_pcm_stream *hinfo, + struct hda_codec *codec, + struct snd_pcm_substream *substream) +{ + struct ca0132_spec *spec = codec->spec; + + ca0132_cleanup_stream(codec, spec->dig_out); + + return 0; +} + +/* + * Analog capture + */ +static int ca0132_capture_pcm_prepare(struct hda_pcm_stream *hinfo, struct hda_codec *codec, unsigned int stream_tag, unsigned int format, struct snd_pcm_substream *substream) { struct ca0132_spec *spec = codec->spec; - return snd_hda_multi_out_dig_prepare(codec, &spec->multiout, - stream_tag, format, substream); + + ca0132_setup_stream(codec, spec->adcs[substream->number], + stream_tag, 0, format); + + return 0; } -static int ca0132_dig_playback_pcm_cleanup(struct hda_pcm_stream *hinfo, +static int ca0132_capture_pcm_cleanup(struct hda_pcm_stream *hinfo, struct hda_codec *codec, struct snd_pcm_substream *substream) { struct ca0132_spec *spec = codec->spec; - return snd_hda_multi_out_dig_cleanup(codec, &spec->multiout); + + ca0132_cleanup_stream(codec, spec->adcs[substream->number]); + + return 0; } -static int ca0132_dig_playback_pcm_close(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - struct snd_pcm_substream *substream) +/* + * Digital capture + */ +static int ca0132_dig_capture_pcm_prepare(struct hda_pcm_stream *hinfo, + struct hda_codec *codec, + unsigned int stream_tag, + unsigned int format, + struct snd_pcm_substream *substream) { struct ca0132_spec *spec = codec->spec; - return snd_hda_multi_out_dig_close(codec, &spec->multiout); + + ca0132_setup_stream(codec, spec->dig_in, stream_tag, 0, format); + + return 0; +} + +static int ca0132_dig_capture_pcm_cleanup(struct hda_pcm_stream *hinfo, + struct hda_codec *codec, + struct snd_pcm_substream *substream) +{ + struct ca0132_spec *spec = codec->spec; + + ca0132_cleanup_stream(codec, spec->dig_in); + + return 0; } /* @@ -547,7 +621,6 @@ static struct hda_pcm_stream ca0132_pcm_analog_playback = { .channels_min = 2, .channels_max = 2, .ops = { - .open = ca0132_playback_pcm_open, .prepare = ca0132_playback_pcm_prepare, .cleanup = ca0132_playback_pcm_cleanup }, @@ -557,6 +630,10 @@ static struct hda_pcm_stream ca0132_pcm_analog_capture = { .substreams = 1, .channels_min = 2, .channels_max = 2, + .ops = { + .prepare = ca0132_capture_pcm_prepare, + .cleanup = ca0132_capture_pcm_cleanup + }, }; static struct hda_pcm_stream ca0132_pcm_digital_playback = { @@ -564,8 +641,6 @@ static struct hda_pcm_stream ca0132_pcm_digital_playback = { .channels_min = 2, .channels_max = 2, .ops = { - .open = ca0132_dig_playback_pcm_open, - .close = ca0132_dig_playback_pcm_close, .prepare = ca0132_dig_playback_pcm_prepare, .cleanup = ca0132_dig_playback_pcm_cleanup }, @@ -575,6 +650,10 @@ static struct hda_pcm_stream ca0132_pcm_digital_capture = { .substreams = 1, .channels_min = 2, .channels_max = 2, + .ops = { + .prepare = ca0132_dig_capture_pcm_prepare, + .cleanup = ca0132_dig_capture_pcm_cleanup + }, }; static int ca0132_build_pcms(struct hda_codec *codec) @@ -849,16 +928,18 @@ static int ca0132_build_controls(struct hda_codec *codec) spec->dig_out); if (err < 0) return err; - err = snd_hda_create_spdif_share_sw(codec, &spec->multiout); + err = add_out_volume(codec, spec->dig_out, "IEC958"); if (err < 0) return err; - /* spec->multiout.share_spdif = 1; */ } if (spec->dig_in) { err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in); if (err < 0) return err; + err = add_in_volume(codec, spec->dig_in, "IEC958"); + if (err < 0) + return err; } return 0; } @@ -880,9 +961,6 @@ static void ca0132_config(struct hda_codec *codec) struct ca0132_spec *spec = codec->spec; struct auto_pin_cfg *cfg = &spec->autocfg; - codec->pcm_format_first = 1; - codec->no_sticky_stream = 1; - /* line-outs */ cfg->line_outs = 1; cfg->line_out_pins[0] = 0x0b; /* front */ @@ -910,24 +988,14 @@ static void ca0132_config(struct hda_codec *codec) /* Mic-in */ spec->input_pins[0] = 0x12; - spec->input_labels[0] = "Mic"; + spec->input_labels[0] = "Mic-In"; spec->adcs[0] = 0x07; /* Line-In */ spec->input_pins[1] = 0x11; - spec->input_labels[1] = "Line"; + spec->input_labels[1] = "Line-In"; spec->adcs[1] = 0x08; spec->num_inputs = 2; - - /* SPDIF I/O */ - spec->dig_out = 0x05; - spec->multiout.dig_out_nid = spec->dig_out; - cfg->dig_out_pins[0] = 0x0c; - cfg->dig_outs = 1; - cfg->dig_out_type[0] = HDA_PCM_TYPE_SPDIF; - spec->dig_in = 0x09; - cfg->dig_in_pin = 0x0e; - cfg->dig_in_type = HDA_PCM_TYPE_SPDIF; } static void ca0132_init_chip(struct hda_codec *codec) diff --git a/trunk/sound/pci/hda/patch_conexant.c b/trunk/sound/pci/hda/patch_conexant.c index 5e22a8f43d2e..14361184ae1e 100644 --- a/trunk/sound/pci/hda/patch_conexant.c +++ b/trunk/sound/pci/hda/patch_conexant.c @@ -2967,10 +2967,12 @@ static const char * const cxt5066_models[CXT5066_MODELS] = { }; static const struct snd_pci_quirk cxt5066_cfg_tbl[] = { + SND_PCI_QUIRK(0x1025, 0x054c, "Acer Aspire 3830TG", CXT5066_AUTO), SND_PCI_QUIRK_MASK(0x1025, 0xff00, 0x0400, "Acer", CXT5066_IDEAPAD), SND_PCI_QUIRK(0x1028, 0x02d8, "Dell Vostro", CXT5066_DELL_VOSTRO), SND_PCI_QUIRK(0x1028, 0x02f5, "Dell Vostro 320", CXT5066_IDEAPAD), SND_PCI_QUIRK(0x1028, 0x0401, "Dell Vostro 1014", CXT5066_DELL_VOSTRO), + SND_PCI_QUIRK(0x1028, 0x0402, "Dell Vostro", CXT5066_DELL_VOSTRO), SND_PCI_QUIRK(0x1028, 0x0408, "Dell Inspiron One 19T", CXT5066_IDEAPAD), SND_PCI_QUIRK(0x1028, 0x050f, "Dell Inspiron", CXT5066_IDEAPAD), SND_PCI_QUIRK(0x1028, 0x0510, "Dell Vostro", CXT5066_IDEAPAD), @@ -2986,10 +2988,14 @@ static const struct snd_pci_quirk cxt5066_cfg_tbl[] = { SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo T400s", CXT5066_THINKPAD), SND_PCI_QUIRK(0x17aa, 0x21c5, "Thinkpad Edge 13", CXT5066_THINKPAD), SND_PCI_QUIRK(0x17aa, 0x21c6, "Thinkpad Edge 13", CXT5066_ASUS), + SND_PCI_QUIRK(0x17aa, 0x215e, "Lenovo T510", CXT5066_AUTO), + SND_PCI_QUIRK(0x17aa, 0x21cf, "Lenovo T520 & W520", CXT5066_AUTO), SND_PCI_QUIRK(0x17aa, 0x21da, "Lenovo X220", CXT5066_THINKPAD), SND_PCI_QUIRK(0x17aa, 0x21db, "Lenovo X220-tablet", CXT5066_THINKPAD), SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo U350", CXT5066_ASUS), SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo G560", CXT5066_ASUS), + SND_PCI_QUIRK(0x17aa, 0x3938, "Lenovo G565", CXT5066_AUTO), + SND_PCI_QUIRK(0x1b0a, 0x2092, "CyberpowerPC Gamer Xplorer N57001", CXT5066_AUTO), {} }; diff --git a/trunk/sound/pci/hda/patch_hdmi.c b/trunk/sound/pci/hda/patch_hdmi.c index 8f23374fa642..69b928449789 100644 --- a/trunk/sound/pci/hda/patch_hdmi.c +++ b/trunk/sound/pci/hda/patch_hdmi.c @@ -877,6 +877,8 @@ static int hdmi_pcm_open(struct hda_pcm_stream *hinfo, struct hdmi_eld *eld; struct hdmi_spec_per_cvt *per_cvt = NULL; + hinfo->nid = 0; /* clear the leftover value */ + /* Validate hinfo */ pin_idx = hinfo_to_pin_index(spec, hinfo); if (snd_BUG_ON(pin_idx < 0)) @@ -1161,14 +1163,6 @@ static int generic_hdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo, return hdmi_setup_stream(codec, cvt_nid, pin_nid, stream_tag, format); } -static int generic_hdmi_playback_pcm_cleanup(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - struct snd_pcm_substream *substream) -{ - snd_hda_codec_cleanup_stream(codec, hinfo->nid); - return 0; -} - static int hdmi_pcm_close(struct hda_pcm_stream *hinfo, struct hda_codec *codec, struct snd_pcm_substream *substream) @@ -1208,7 +1202,6 @@ static const struct hda_pcm_ops generic_ops = { .open = hdmi_pcm_open, .close = hdmi_pcm_close, .prepare = generic_hdmi_playback_pcm_prepare, - .cleanup = generic_hdmi_playback_pcm_cleanup, }; static int generic_hdmi_build_pcms(struct hda_codec *codec) @@ -1227,6 +1220,7 @@ static int generic_hdmi_build_pcms(struct hda_codec *codec) pstr = &info->stream[SNDRV_PCM_STREAM_PLAYBACK]; pstr->substreams = 1; pstr->ops = generic_ops; + pstr->nid = 1; /* FIXME: just for avoiding a debug WARNING */ /* other pstr fields are set in open */ } diff --git a/trunk/sound/pci/hda/patch_realtek.c b/trunk/sound/pci/hda/patch_realtek.c index 4f81dd44c837..344b221d2102 100644 --- a/trunk/sound/pci/hda/patch_realtek.c +++ b/trunk/sound/pci/hda/patch_realtek.c @@ -6099,8 +6099,6 @@ static const struct alc_fixup alc269_fixups[] = { [ALC269_FIXUP_PCM_44K] = { .type = ALC_FIXUP_FUNC, .v.func = alc269_fixup_pcm_44k, - .chained = true, - .chain_id = ALC269_FIXUP_QUANTA_MUTE }, [ALC269_FIXUP_STEREO_DMIC] = { .type = ALC_FIXUP_FUNC, @@ -6208,11 +6206,9 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x17aa, 0x21b8, "Thinkpad Edge 14", ALC269_FIXUP_SKU_IGNORE), SND_PCI_QUIRK(0x17aa, 0x21ca, "Thinkpad L412", ALC269_FIXUP_SKU_IGNORE), SND_PCI_QUIRK(0x17aa, 0x21e9, "Thinkpad Edge 15", ALC269_FIXUP_SKU_IGNORE), - SND_PCI_QUIRK(0x17aa, 0x21f6, "Thinkpad T530", ALC269_FIXUP_LENOVO_DOCK), - SND_PCI_QUIRK(0x17aa, 0x21fa, "Thinkpad X230", ALC269_FIXUP_LENOVO_DOCK), - SND_PCI_QUIRK(0x17aa, 0x21fb, "Thinkpad T430s", ALC269_FIXUP_LENOVO_DOCK), SND_PCI_QUIRK(0x17aa, 0x2203, "Thinkpad X230 Tablet", ALC269_FIXUP_LENOVO_DOCK), - SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_FIXUP_PCM_44K), + SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_FIXUP_QUANTA_MUTE), + SND_PCI_QUIRK(0x17aa, 0x3bf8, "Lenovo Ideapd", ALC269_FIXUP_PCM_44K), SND_PCI_QUIRK(0x17aa, 0x9e54, "LENOVO NB", ALC269_FIXUP_LENOVO_EAPD), #if 0 diff --git a/trunk/sound/pci/hda/patch_sigmatel.c b/trunk/sound/pci/hda/patch_sigmatel.c index 3d4722f0a1ca..94040ccf8e8f 100644 --- a/trunk/sound/pci/hda/patch_sigmatel.c +++ b/trunk/sound/pci/hda/patch_sigmatel.c @@ -1075,7 +1075,7 @@ static struct snd_kcontrol_new stac_smux_mixer = { static const char * const slave_pfxs[] = { "Front", "Surround", "Center", "LFE", "Side", - "Headphone", "Speaker", "IEC958", "PCM", + "Headphone", "Speaker", "IEC958", NULL }; @@ -4272,8 +4272,7 @@ static int stac92xx_init(struct hda_codec *codec) unsigned int gpio; int i; - if (spec->init) - snd_hda_sequence_write(codec, spec->init); + snd_hda_sequence_write(codec, spec->init); /* power down adcs initially */ if (spec->powerdown_adcs) @@ -4543,9 +4542,6 @@ static void stac92xx_line_out_detect(struct hda_codec *codec, struct auto_pin_cfg *cfg = &spec->autocfg; int i; - if (cfg->speaker_outs == 0) - return; - for (i = 0; i < cfg->line_outs; i++) { if (presence) break; @@ -5534,7 +5530,6 @@ static int patch_stac92hd83xxx(struct hda_codec *codec) snd_hda_codec_set_pincfg(codec, 0xf, 0x2181205e); } - codec->epss = 0; /* longer delay needed for D3 */ codec->no_trigger_sense = 1; codec->spec = spec; @@ -5753,6 +5748,7 @@ static int patch_stac92hd71bxx(struct hda_codec *codec) /* fallthru */ case 0x111d76b4: /* 6 Port without Analog Mixer */ case 0x111d76b5: + spec->init = stac92hd71bxx_core_init; codec->slave_dig_outs = stac92hd71bxx_slave_dig_outs; spec->num_dmics = stac92xx_connected_ports(codec, stac92hd71bxx_dmic_nids, @@ -5777,6 +5773,7 @@ static int patch_stac92hd71bxx(struct hda_codec *codec) spec->stream_delay = 40; /* 40 milliseconds */ /* disable VSW */ + spec->init = stac92hd71bxx_core_init; unmute_init++; snd_hda_codec_set_pincfg(codec, 0x0f, 0x40f000f0); snd_hda_codec_set_pincfg(codec, 0x19, 0x40f000f3); @@ -5791,6 +5788,7 @@ static int patch_stac92hd71bxx(struct hda_codec *codec) /* fallthru */ default: + spec->init = stac92hd71bxx_core_init; codec->slave_dig_outs = stac92hd71bxx_slave_dig_outs; spec->num_dmics = stac92xx_connected_ports(codec, stac92hd71bxx_dmic_nids, @@ -5798,9 +5796,6 @@ static int patch_stac92hd71bxx(struct hda_codec *codec) break; } - if (get_wcaps_type(get_wcaps(codec, 0x28)) == AC_WID_VOL_KNB) - spec->init = stac92hd71bxx_core_init; - if (get_wcaps(codec, 0xa) & AC_WCAP_IN_AMP) snd_hda_sequence_write_cache(codec, unmute_init); diff --git a/trunk/sound/pci/hda/patch_via.c b/trunk/sound/pci/hda/patch_via.c index 430771776915..80d90cb42853 100644 --- a/trunk/sound/pci/hda/patch_via.c +++ b/trunk/sound/pci/hda/patch_via.c @@ -1752,14 +1752,6 @@ static int via_suspend(struct hda_codec *codec) { struct via_spec *spec = codec->spec; vt1708_stop_hp_work(spec); - - if (spec->codec_type == VT1802) { - /* Fix pop noise on headphones */ - int i; - for (i = 0; i < spec->autocfg.hp_outs; i++) - snd_hda_set_pin_ctl(codec, spec->autocfg.hp_pins[i], 0); - } - return 0; } #endif diff --git a/trunk/sound/pci/ice1712/prodigy_hifi.c b/trunk/sound/pci/ice1712/prodigy_hifi.c index 075d5aa1fee0..764cc93dbca4 100644 --- a/trunk/sound/pci/ice1712/prodigy_hifi.c +++ b/trunk/sound/pci/ice1712/prodigy_hifi.c @@ -297,7 +297,6 @@ static int ak4396_dac_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem } static const DECLARE_TLV_DB_SCALE(db_scale_wm_dac, -12700, 100, 1); -static const DECLARE_TLV_DB_LINEAR(ak4396_db_scale, TLV_DB_GAIN_MUTE, 0); static struct snd_kcontrol_new prodigy_hd2_controls[] __devinitdata = { { @@ -308,7 +307,7 @@ static struct snd_kcontrol_new prodigy_hd2_controls[] __devinitdata = { .info = ak4396_dac_vol_info, .get = ak4396_dac_vol_get, .put = ak4396_dac_vol_put, - .tlv = { .p = ak4396_db_scale }, + .tlv = { .p = db_scale_wm_dac }, }, }; diff --git a/trunk/sound/pci/lx6464es/lx6464es.c b/trunk/sound/pci/lx6464es/lx6464es.c index 5579b08bb35b..d1ab43706735 100644 --- a/trunk/sound/pci/lx6464es/lx6464es.c +++ b/trunk/sound/pci/lx6464es/lx6464es.c @@ -851,8 +851,6 @@ static int __devinit lx_pcm_create(struct lx6464es *chip) /* hardcoded device name & channel count */ err = snd_pcm_new(chip->card, (char *)card_name, 0, 1, 1, &pcm); - if (err < 0) - return err; pcm->private_data = chip; diff --git a/trunk/sound/pci/rme9652/hdspm.c b/trunk/sound/pci/rme9652/hdspm.c index b12308b5ba2a..b8ac8710f47f 100644 --- a/trunk/sound/pci/rme9652/hdspm.c +++ b/trunk/sound/pci/rme9652/hdspm.c @@ -6585,7 +6585,7 @@ static int __devinit snd_hdspm_create(struct snd_card *card, snd_printk(KERN_ERR "HDSPM: " "unable to kmalloc Mixer memory of %d Bytes\n", (int)sizeof(struct hdspm_mixer)); - return -ENOMEM; + return err; } hdspm->port_names_in = NULL; diff --git a/trunk/sound/pci/sis7019.c b/trunk/sound/pci/sis7019.c index 805ab6e9a78f..512434efcc31 100644 --- a/trunk/sound/pci/sis7019.c +++ b/trunk/sound/pci/sis7019.c @@ -1377,9 +1377,8 @@ static int __devinit sis_chip_create(struct snd_card *card, if (rc) goto error_out_cleanup; - rc = request_irq(pci->irq, sis_interrupt, IRQF_SHARED, KBUILD_MODNAME, - sis); - if (rc) { + if (request_irq(pci->irq, sis_interrupt, IRQF_SHARED, KBUILD_MODNAME, + sis)) { dev_err(&pci->dev, "unable to allocate irq %d\n", sis->irq); goto error_out_cleanup; } diff --git a/trunk/sound/ppc/powermac.c b/trunk/sound/ppc/powermac.c index 210cafe04890..f5ceb6f282de 100644 --- a/trunk/sound/ppc/powermac.c +++ b/trunk/sound/ppc/powermac.c @@ -143,7 +143,7 @@ static int __devexit snd_pmac_remove(struct platform_device *devptr) return 0; } -#ifdef CONFIG_PM_SLEEP +#ifdef CONFIG_PM static int snd_pmac_driver_suspend(struct device *dev) { struct snd_card *card = dev_get_drvdata(dev); diff --git a/trunk/sound/ppc/snd_ps3.c b/trunk/sound/ppc/snd_ps3.c index 9b18b5243a56..1aa52eff526a 100644 --- a/trunk/sound/ppc/snd_ps3.c +++ b/trunk/sound/ppc/snd_ps3.c @@ -1040,7 +1040,6 @@ static int __devinit snd_ps3_driver_probe(struct ps3_system_bus_device *dev) GFP_KERNEL); if (!the_card.null_buffer_start_vaddr) { pr_info("%s: nullbuffer alloc failed\n", __func__); - ret = -ENOMEM; goto clean_preallocate; } pr_debug("%s: null vaddr=%p dma=%#llx\n", __func__, diff --git a/trunk/sound/soc/blackfin/bf6xx-sport.c b/trunk/sound/soc/blackfin/bf6xx-sport.c index dfb744381c42..318c5ba5360f 100644 --- a/trunk/sound/soc/blackfin/bf6xx-sport.c +++ b/trunk/sound/soc/blackfin/bf6xx-sport.c @@ -413,14 +413,7 @@ EXPORT_SYMBOL(sport_create); void sport_delete(struct sport_device *sport) { - if (sport->tx_desc) - dma_free_coherent(NULL, sport->tx_desc_size, - sport->tx_desc, 0); - if (sport->rx_desc) - dma_free_coherent(NULL, sport->rx_desc_size, - sport->rx_desc, 0); sport_free_resource(sport); - kfree(sport); } EXPORT_SYMBOL(sport_delete); diff --git a/trunk/sound/soc/codecs/ab8500-codec.c b/trunk/sound/soc/codecs/ab8500-codec.c index 23b40186f9b8..3c795921c5f6 100644 --- a/trunk/sound/soc/codecs/ab8500-codec.c +++ b/trunk/sound/soc/codecs/ab8500-codec.c @@ -2406,10 +2406,6 @@ static int ab8500_codec_probe(struct snd_soc_codec *codec) /* Setup AB8500 according to board-settings */ pdata = (struct ab8500_platform_data *)dev_get_platdata(dev->parent); - - /* Inform SoC Core that we have our own I/O arrangements. */ - codec->control_data = (void *)true; - status = ab8500_audio_setup_mics(codec, &pdata->codec->amics); if (status < 0) { pr_err("%s: Failed to setup mics (%d)!\n", __func__, status); diff --git a/trunk/sound/soc/codecs/ad1980.c b/trunk/sound/soc/codecs/ad1980.c index 11b1b714b8b5..8c39dddd7d00 100644 --- a/trunk/sound/soc/codecs/ad1980.c +++ b/trunk/sound/soc/codecs/ad1980.c @@ -186,7 +186,6 @@ static int ad1980_soc_probe(struct snd_soc_codec *codec) printk(KERN_INFO "AD1980 SoC Audio Codec\n"); - codec->control_data = codec; /* we don't use regmap! */ ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0); if (ret < 0) { printk(KERN_ERR "ad1980: failed to register AC97 codec\n"); diff --git a/trunk/sound/soc/codecs/arizona.c b/trunk/sound/soc/codecs/arizona.c index 1cf7a32d1b21..5c9cacaf2d52 100644 --- a/trunk/sound/soc/codecs/arizona.c +++ b/trunk/sound/soc/codecs/arizona.c @@ -426,7 +426,7 @@ static const int arizona_44k1_bclk_rates[] = { 940800, 1411200, 1881600, - 2822400, + 2882400, 3763200, 5644800, 7526400, diff --git a/trunk/sound/soc/codecs/mc13783.c b/trunk/sound/soc/codecs/mc13783.c index 115a40301810..6276e352125f 100644 --- a/trunk/sound/soc/codecs/mc13783.c +++ b/trunk/sound/soc/codecs/mc13783.c @@ -581,8 +581,6 @@ static int mc13783_probe(struct snd_soc_codec *codec) { struct mc13783_priv *priv = snd_soc_codec_get_drvdata(codec); - codec->control_data = priv->mc13xxx; - mc13xxx_lock(priv->mc13xxx); /* these are the reset values */ @@ -659,7 +657,7 @@ static struct snd_soc_dai_driver mc13783_dai_async[] = { .id = MC13783_ID_STEREO_DAC, .playback = { .stream_name = "Playback", - .channels_min = 2, + .channels_min = 1, .channels_max = 2, .rates = SNDRV_PCM_RATE_8000_96000, .formats = MC13783_FORMATS, @@ -670,7 +668,7 @@ static struct snd_soc_dai_driver mc13783_dai_async[] = { .id = MC13783_ID_STEREO_CODEC, .capture = { .stream_name = "Capture", - .channels_min = 2, + .channels_min = 1, .channels_max = 2, .rates = MC13783_RATES_RECORD, .formats = MC13783_FORMATS, @@ -692,14 +690,14 @@ static struct snd_soc_dai_driver mc13783_dai_sync[] = { .id = MC13783_ID_SYNC, .playback = { .stream_name = "Playback", - .channels_min = 2, + .channels_min = 1, .channels_max = 2, .rates = SNDRV_PCM_RATE_8000_96000, .formats = MC13783_FORMATS, }, .capture = { .stream_name = "Capture", - .channels_min = 2, + .channels_min = 1, .channels_max = 2, .rates = MC13783_RATES_RECORD, .formats = MC13783_FORMATS, diff --git a/trunk/sound/soc/codecs/sgtl5000.c b/trunk/sound/soc/codecs/sgtl5000.c index df2f99d1d428..8af6a5245b18 100644 --- a/trunk/sound/soc/codecs/sgtl5000.c +++ b/trunk/sound/soc/codecs/sgtl5000.c @@ -239,7 +239,6 @@ static const struct snd_soc_dapm_route sgtl5000_dapm_routes[] = { {"Headphone Mux", "DAC", "DAC"}, /* dac --> hp_mux */ {"LO", NULL, "DAC"}, /* dac --> line_out */ - {"LINE_IN", NULL, "VAG_POWER"}, {"Headphone Mux", "LINE_IN", "LINE_IN"},/* line_in --> hp_mux */ {"HP", NULL, "Headphone Mux"}, /* hp_mux --> hp */ @@ -1358,6 +1357,8 @@ static int sgtl5000_probe(struct snd_soc_codec *codec) if (ret) goto err; + snd_soc_dapm_new_widgets(&codec->dapm); + return 0; err: diff --git a/trunk/sound/soc/codecs/stac9766.c b/trunk/sound/soc/codecs/stac9766.c index 33c0f3d39c87..982e437799a8 100644 --- a/trunk/sound/soc/codecs/stac9766.c +++ b/trunk/sound/soc/codecs/stac9766.c @@ -340,7 +340,6 @@ static int stac9766_codec_probe(struct snd_soc_codec *codec) printk(KERN_INFO "STAC9766 SoC Audio Codec %s\n", STAC9766_VERSION); - codec->control_data = codec; /* we don't use regmap! */ ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0); if (ret < 0) goto codec_err; diff --git a/trunk/sound/soc/codecs/wm2000.c b/trunk/sound/soc/codecs/wm2000.c index a3acb7a85f6a..3fd5b29dc933 100644 --- a/trunk/sound/soc/codecs/wm2000.c +++ b/trunk/sound/soc/codecs/wm2000.c @@ -702,7 +702,7 @@ static bool wm2000_readable_reg(struct device *dev, unsigned int reg) } static const struct regmap_config wm2000_regmap = { - .reg_bits = 16, + .reg_bits = 8, .val_bits = 8, .max_register = WM2000_REG_IF_CTL, diff --git a/trunk/sound/soc/codecs/wm5102.c b/trunk/sound/soc/codecs/wm5102.c index e33d327396ad..6537f16d383e 100644 --- a/trunk/sound/soc/codecs/wm5102.c +++ b/trunk/sound/soc/codecs/wm5102.c @@ -128,9 +128,13 @@ SOC_SINGLE_TLV("EQ4 B5 Volume", ARIZONA_EQ4_2, ARIZONA_EQ4_B5_GAIN_SHIFT, ARIZONA_MIXER_CONTROLS("DRC1L", ARIZONA_DRC1LMIX_INPUT_1_SOURCE), ARIZONA_MIXER_CONTROLS("DRC1R", ARIZONA_DRC1RMIX_INPUT_1_SOURCE), +ARIZONA_MIXER_CONTROLS("DRC2L", ARIZONA_DRC2LMIX_INPUT_1_SOURCE), +ARIZONA_MIXER_CONTROLS("DRC2R", ARIZONA_DRC2RMIX_INPUT_1_SOURCE), SND_SOC_BYTES_MASK("DRC1", ARIZONA_DRC1_CTRL1, 5, ARIZONA_DRC1R_ENA | ARIZONA_DRC1L_ENA), +SND_SOC_BYTES_MASK("DRC2", ARIZONA_DRC2_CTRL1, 5, + ARIZONA_DRC2R_ENA | ARIZONA_DRC2L_ENA), ARIZONA_MIXER_CONTROLS("LHPF1", ARIZONA_HPLP1MIX_INPUT_1_SOURCE), ARIZONA_MIXER_CONTROLS("LHPF2", ARIZONA_HPLP2MIX_INPUT_1_SOURCE), @@ -232,6 +236,8 @@ ARIZONA_MIXER_ENUMS(EQ4, ARIZONA_EQ4MIX_INPUT_1_SOURCE); ARIZONA_MIXER_ENUMS(DRC1L, ARIZONA_DRC1LMIX_INPUT_1_SOURCE); ARIZONA_MIXER_ENUMS(DRC1R, ARIZONA_DRC1RMIX_INPUT_1_SOURCE); +ARIZONA_MIXER_ENUMS(DRC2L, ARIZONA_DRC2LMIX_INPUT_1_SOURCE); +ARIZONA_MIXER_ENUMS(DRC2R, ARIZONA_DRC2RMIX_INPUT_1_SOURCE); ARIZONA_MIXER_ENUMS(LHPF1, ARIZONA_HPLP1MIX_INPUT_1_SOURCE); ARIZONA_MIXER_ENUMS(LHPF2, ARIZONA_HPLP2MIX_INPUT_1_SOURCE); @@ -343,6 +349,10 @@ SND_SOC_DAPM_PGA("DRC1L", ARIZONA_DRC1_CTRL1, ARIZONA_DRC1L_ENA_SHIFT, 0, NULL, 0), SND_SOC_DAPM_PGA("DRC1R", ARIZONA_DRC1_CTRL1, ARIZONA_DRC1R_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("DRC2L", ARIZONA_DRC2_CTRL1, ARIZONA_DRC2L_ENA_SHIFT, 0, + NULL, 0), +SND_SOC_DAPM_PGA("DRC2R", ARIZONA_DRC2_CTRL1, ARIZONA_DRC2R_ENA_SHIFT, 0, + NULL, 0), SND_SOC_DAPM_PGA("LHPF1", ARIZONA_HPLPF1_1, ARIZONA_LHPF1_ENA_SHIFT, 0, NULL, 0), @@ -456,6 +466,8 @@ ARIZONA_MIXER_WIDGETS(EQ4, "EQ4"), ARIZONA_MIXER_WIDGETS(DRC1L, "DRC1L"), ARIZONA_MIXER_WIDGETS(DRC1R, "DRC1R"), +ARIZONA_MIXER_WIDGETS(DRC2L, "DRC2L"), +ARIZONA_MIXER_WIDGETS(DRC2R, "DRC2R"), ARIZONA_MIXER_WIDGETS(LHPF1, "LHPF1"), ARIZONA_MIXER_WIDGETS(LHPF2, "LHPF2"), @@ -541,6 +553,8 @@ SND_SOC_DAPM_OUTPUT("SPKDAT1R"), { name, "EQ4", "EQ4" }, \ { name, "DRC1L", "DRC1L" }, \ { name, "DRC1R", "DRC1R" }, \ + { name, "DRC2L", "DRC2L" }, \ + { name, "DRC2R", "DRC2R" }, \ { name, "LHPF1", "LHPF1" }, \ { name, "LHPF2", "LHPF2" }, \ { name, "LHPF3", "LHPF3" }, \ @@ -625,15 +639,6 @@ static const struct snd_soc_dapm_route wm5102_dapm_routes[] = { { "AIF2 Capture", NULL, "SYSCLK" }, { "AIF3 Capture", NULL, "SYSCLK" }, - { "IN1L PGA", NULL, "IN1L" }, - { "IN1R PGA", NULL, "IN1R" }, - - { "IN2L PGA", NULL, "IN2L" }, - { "IN2R PGA", NULL, "IN2R" }, - - { "IN3L PGA", NULL, "IN3L" }, - { "IN3R PGA", NULL, "IN3R" }, - ARIZONA_MIXER_ROUTES("OUT1L", "HPOUT1L"), ARIZONA_MIXER_ROUTES("OUT1R", "HPOUT1R"), ARIZONA_MIXER_ROUTES("OUT2L", "HPOUT2L"), @@ -670,6 +675,8 @@ static const struct snd_soc_dapm_route wm5102_dapm_routes[] = { ARIZONA_MIXER_ROUTES("DRC1L", "DRC1L"), ARIZONA_MIXER_ROUTES("DRC1R", "DRC1R"), + ARIZONA_MIXER_ROUTES("DRC2L", "DRC2L"), + ARIZONA_MIXER_ROUTES("DRC2R", "DRC2R"), ARIZONA_MIXER_ROUTES("LHPF1", "LHPF1"), ARIZONA_MIXER_ROUTES("LHPF2", "LHPF2"), diff --git a/trunk/sound/soc/codecs/wm5110.c b/trunk/sound/soc/codecs/wm5110.c index 01ebbcc5c6a4..8033f7065189 100644 --- a/trunk/sound/soc/codecs/wm5110.c +++ b/trunk/sound/soc/codecs/wm5110.c @@ -681,18 +681,6 @@ static const struct snd_soc_dapm_route wm5110_dapm_routes[] = { { "AIF2 Capture", NULL, "SYSCLK" }, { "AIF3 Capture", NULL, "SYSCLK" }, - { "IN1L PGA", NULL, "IN1L" }, - { "IN1R PGA", NULL, "IN1R" }, - - { "IN2L PGA", NULL, "IN2L" }, - { "IN2R PGA", NULL, "IN2R" }, - - { "IN3L PGA", NULL, "IN3L" }, - { "IN3R PGA", NULL, "IN3R" }, - - { "IN4L PGA", NULL, "IN4L" }, - { "IN4R PGA", NULL, "IN4R" }, - ARIZONA_MIXER_ROUTES("OUT1L", "HPOUT1L"), ARIZONA_MIXER_ROUTES("OUT1R", "HPOUT1R"), ARIZONA_MIXER_ROUTES("OUT2L", "HPOUT2L"), diff --git a/trunk/sound/soc/codecs/wm8904.c b/trunk/sound/soc/codecs/wm8904.c index dc4262eea4b7..0013afe48e66 100644 --- a/trunk/sound/soc/codecs/wm8904.c +++ b/trunk/sound/soc/codecs/wm8904.c @@ -100,7 +100,7 @@ static const struct reg_default wm8904_reg_defaults[] = { { 14, 0x0000 }, /* R14 - Power Management 2 */ { 15, 0x0000 }, /* R15 - Power Management 3 */ { 18, 0x0000 }, /* R18 - Power Management 6 */ - { 20, 0x945E }, /* R20 - Clock Rates 0 */ + { 19, 0x945E }, /* R20 - Clock Rates 0 */ { 21, 0x0C05 }, /* R21 - Clock Rates 1 */ { 22, 0x0006 }, /* R22 - Clock Rates 2 */ { 24, 0x0050 }, /* R24 - Audio Interface 0 */ diff --git a/trunk/sound/soc/codecs/wm8962.c b/trunk/sound/soc/codecs/wm8962.c index ce6720073798..eaf65863ec21 100644 --- a/trunk/sound/soc/codecs/wm8962.c +++ b/trunk/sound/soc/codecs/wm8962.c @@ -2501,9 +2501,6 @@ static int wm8962_set_bias_level(struct snd_soc_codec *codec, /* VMID 2*250k */ snd_soc_update_bits(codec, WM8962_PWR_MGMT_1, WM8962_VMID_SEL_MASK, 0x100); - - if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) - msleep(100); break; case SND_SOC_BIAS_OFF: @@ -3733,6 +3730,21 @@ static int wm8962_runtime_resume(struct device *dev) regcache_sync(wm8962->regmap); + regmap_update_bits(wm8962->regmap, WM8962_ANTI_POP, + WM8962_STARTUP_BIAS_ENA | WM8962_VMID_BUF_ENA, + WM8962_STARTUP_BIAS_ENA | WM8962_VMID_BUF_ENA); + + /* Bias enable at 2*50k for ramp */ + regmap_update_bits(wm8962->regmap, WM8962_PWR_MGMT_1, + WM8962_VMID_SEL_MASK | WM8962_BIAS_ENA, + WM8962_BIAS_ENA | 0x180); + + msleep(5); + + /* VMID back to 2x250k for standby */ + regmap_update_bits(wm8962->regmap, WM8962_PWR_MGMT_1, + WM8962_VMID_SEL_MASK, 0x100); + return 0; } diff --git a/trunk/sound/soc/codecs/wm8994.c b/trunk/sound/soc/codecs/wm8994.c index 6c9eeca85b95..bb62f4b3d563 100644 --- a/trunk/sound/soc/codecs/wm8994.c +++ b/trunk/sound/soc/codecs/wm8994.c @@ -2649,7 +2649,7 @@ static int wm8994_hw_params(struct snd_pcm_substream *substream, return -EINVAL; } - bclk_rate = params_rate(params) * 4; + bclk_rate = params_rate(params) * 2; switch (params_format(params)) { case SNDRV_PCM_FORMAT_S16_LE: bclk_rate *= 16; @@ -3253,13 +3253,10 @@ static void wm8994_mic_work(struct work_struct *work) int ret; int report; - pm_runtime_get_sync(dev); - ret = regmap_read(regmap, WM8994_INTERRUPT_RAW_STATUS_2, ®); if (ret < 0) { dev_err(dev, "Failed to read microphone status: %d\n", ret); - pm_runtime_put(dev); return; } @@ -3302,8 +3299,6 @@ static void wm8994_mic_work(struct work_struct *work) snd_soc_jack_report(priv->micdet[1].jack, report, SND_JACK_HEADSET | SND_JACK_BTN_0); - - pm_runtime_put(dev); } static irqreturn_t wm8994_mic_irq(int irq, void *data) @@ -3426,15 +3421,12 @@ static irqreturn_t wm1811_jackdet_irq(int irq, void *data) int reg; bool present; - pm_runtime_get_sync(codec->dev); - mutex_lock(&wm8994->accdet_lock); reg = snd_soc_read(codec, WM1811_JACKDET_CTRL); if (reg < 0) { dev_err(codec->dev, "Failed to read jack status: %d\n", reg); mutex_unlock(&wm8994->accdet_lock); - pm_runtime_put(codec->dev); return IRQ_NONE; } @@ -3499,7 +3491,6 @@ static irqreturn_t wm1811_jackdet_irq(int irq, void *data) SND_JACK_MECHANICAL | SND_JACK_HEADSET | wm8994->btn_mask); - pm_runtime_put(codec->dev); return IRQ_HANDLED; } @@ -3611,8 +3602,6 @@ static irqreturn_t wm8958_mic_irq(int irq, void *data) if (!(snd_soc_read(codec, WM8958_MIC_DETECT_1) & WM8958_MICD_ENA)) return IRQ_HANDLED; - pm_runtime_get_sync(codec->dev); - /* We may occasionally read a detection without an impedence * range being provided - if that happens loop again. */ @@ -3623,7 +3612,6 @@ static irqreturn_t wm8958_mic_irq(int irq, void *data) dev_err(codec->dev, "Failed to read mic detect status: %d\n", reg); - pm_runtime_put(codec->dev); return IRQ_NONE; } @@ -3651,7 +3639,6 @@ static irqreturn_t wm8958_mic_irq(int irq, void *data) dev_warn(codec->dev, "Accessory detection with no callback\n"); out: - pm_runtime_put(codec->dev); return IRQ_HANDLED; } @@ -4038,8 +4025,6 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec) break; case WM8958: if (wm8994->revision < 1) { - snd_soc_dapm_add_routes(dapm, wm8994_intercon, - ARRAY_SIZE(wm8994_intercon)); snd_soc_dapm_add_routes(dapm, wm8994_revd_intercon, ARRAY_SIZE(wm8994_revd_intercon)); snd_soc_dapm_add_routes(dapm, wm8994_lateclk_revd_intercon, diff --git a/trunk/sound/soc/codecs/wm9712.c b/trunk/sound/soc/codecs/wm9712.c index c6d2076a796b..099e6ec32125 100644 --- a/trunk/sound/soc/codecs/wm9712.c +++ b/trunk/sound/soc/codecs/wm9712.c @@ -148,7 +148,7 @@ SOC_SINGLE("Treble Volume", AC97_MASTER_TONE, 0, 15, 1), SOC_SINGLE("Capture ADC Switch", AC97_REC_GAIN, 15, 1, 1), SOC_ENUM("Capture Volume Steps", wm9712_enum[6]), -SOC_DOUBLE("Capture Volume", AC97_REC_GAIN, 8, 0, 63, 0), +SOC_DOUBLE("Capture Volume", AC97_REC_GAIN, 8, 0, 63, 1), SOC_SINGLE("Capture ZC Switch", AC97_REC_GAIN, 7, 1, 0), SOC_SINGLE_TLV("Mic 1 Volume", AC97_MIC, 8, 31, 1, main_tlv), @@ -272,7 +272,7 @@ SOC_DAPM_ENUM("Route", wm9712_enum[9]); /* Mic select */ static const struct snd_kcontrol_new wm9712_mic_src_controls = -SOC_DAPM_ENUM("Mic Source Select", wm9712_enum[7]); +SOC_DAPM_ENUM("Route", wm9712_enum[7]); /* diff select */ static const struct snd_kcontrol_new wm9712_diff_sel_controls = @@ -291,9 +291,7 @@ SND_SOC_DAPM_MUX("Left Capture Select", SND_SOC_NOPM, 0, 0, &wm9712_capture_selectl_controls), SND_SOC_DAPM_MUX("Right Capture Select", SND_SOC_NOPM, 0, 0, &wm9712_capture_selectr_controls), -SND_SOC_DAPM_MUX("Left Mic Select Source", SND_SOC_NOPM, 0, 0, - &wm9712_mic_src_controls), -SND_SOC_DAPM_MUX("Right Mic Select Source", SND_SOC_NOPM, 0, 0, +SND_SOC_DAPM_MUX("Mic Select Source", SND_SOC_NOPM, 0, 0, &wm9712_mic_src_controls), SND_SOC_DAPM_MUX("Differential Source", SND_SOC_NOPM, 0, 0, &wm9712_diff_sel_controls), @@ -321,7 +319,6 @@ SND_SOC_DAPM_PGA("Out 3 PGA", AC97_INT_PAGING, 5, 1, NULL, 0), SND_SOC_DAPM_PGA("Line PGA", AC97_INT_PAGING, 2, 1, NULL, 0), SND_SOC_DAPM_PGA("Phone PGA", AC97_INT_PAGING, 1, 1, NULL, 0), SND_SOC_DAPM_PGA("Mic PGA", AC97_INT_PAGING, 0, 1, NULL, 0), -SND_SOC_DAPM_PGA("Differential Mic", SND_SOC_NOPM, 0, 0, NULL, 0), SND_SOC_DAPM_MICBIAS("Mic Bias", AC97_INT_PAGING, 10, 1), SND_SOC_DAPM_OUTPUT("MONOOUT"), SND_SOC_DAPM_OUTPUT("HPOUTL"), @@ -382,18 +379,6 @@ static const struct snd_soc_dapm_route wm9712_audio_map[] = { {"Mic PGA", NULL, "MIC1"}, {"Mic PGA", NULL, "MIC2"}, - /* microphones */ - {"Differential Mic", NULL, "MIC1"}, - {"Differential Mic", NULL, "MIC2"}, - {"Left Mic Select Source", "Mic 1", "MIC1"}, - {"Left Mic Select Source", "Mic 2", "MIC2"}, - {"Left Mic Select Source", "Stereo", "MIC1"}, - {"Left Mic Select Source", "Differential", "Differential Mic"}, - {"Right Mic Select Source", "Mic 1", "MIC1"}, - {"Right Mic Select Source", "Mic 2", "MIC2"}, - {"Right Mic Select Source", "Stereo", "MIC2"}, - {"Right Mic Select Source", "Differential", "Differential Mic"}, - /* left capture selector */ {"Left Capture Select", "Mic", "MIC1"}, {"Left Capture Select", "Speaker Mixer", "Speaker Mixer"}, @@ -634,7 +619,6 @@ static int wm9712_soc_probe(struct snd_soc_codec *codec) { int ret = 0; - codec->control_data = codec; /* we don't use regmap! */ ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0); if (ret < 0) { printk(KERN_ERR "wm9712: failed to register AC97 codec\n"); diff --git a/trunk/sound/soc/codecs/wm9713.c b/trunk/sound/soc/codecs/wm9713.c index d0b8a3287a85..3eb19fb71d17 100644 --- a/trunk/sound/soc/codecs/wm9713.c +++ b/trunk/sound/soc/codecs/wm9713.c @@ -1196,7 +1196,6 @@ static int wm9713_soc_probe(struct snd_soc_codec *codec) if (wm9713 == NULL) return -ENOMEM; snd_soc_codec_set_drvdata(codec, wm9713); - codec->control_data = wm9713; /* we don't use regmap! */ ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0); if (ret < 0) diff --git a/trunk/sound/soc/davinci/davinci-mcasp.c b/trunk/sound/soc/davinci/davinci-mcasp.c index ce5e5cd254dd..95441bfc8190 100644 --- a/trunk/sound/soc/davinci/davinci-mcasp.c +++ b/trunk/sound/soc/davinci/davinci-mcasp.c @@ -380,20 +380,14 @@ static void mcasp_start_tx(struct davinci_audio_dev *dev) static void davinci_mcasp_start(struct davinci_audio_dev *dev, int stream) { if (stream == SNDRV_PCM_STREAM_PLAYBACK) { - if (dev->txnumevt) { /* enable FIFO */ - mcasp_clr_bits(dev->base + DAVINCI_MCASP_WFIFOCTL, - FIFO_ENABLE); + if (dev->txnumevt) /* enable FIFO */ mcasp_set_bits(dev->base + DAVINCI_MCASP_WFIFOCTL, FIFO_ENABLE); - } mcasp_start_tx(dev); } else { - if (dev->rxnumevt) { /* enable FIFO */ - mcasp_clr_bits(dev->base + DAVINCI_MCASP_RFIFOCTL, - FIFO_ENABLE); + if (dev->rxnumevt) /* enable FIFO */ mcasp_set_bits(dev->base + DAVINCI_MCASP_RFIFOCTL, FIFO_ENABLE); - } mcasp_start_rx(dev); } } diff --git a/trunk/sound/soc/fsl/imx-sgtl5000.c b/trunk/sound/soc/fsl/imx-sgtl5000.c index 199408ec4261..fb21b17f17f5 100644 --- a/trunk/sound/soc/fsl/imx-sgtl5000.c +++ b/trunk/sound/soc/fsl/imx-sgtl5000.c @@ -94,7 +94,7 @@ static int __devinit imx_sgtl5000_probe(struct platform_device *pdev) dev_err(&pdev->dev, "audmux internal port setup failed\n"); return ret; } - ret = imx_audmux_v2_configure_port(ext_port, + imx_audmux_v2_configure_port(ext_port, IMX_AUDMUX_V2_PTCR_SYN, IMX_AUDMUX_V2_PDCR_RXDSEL(int_port)); if (ret) { diff --git a/trunk/sound/soc/fsl/imx-ssi.c b/trunk/sound/soc/fsl/imx-ssi.c index 81d7728cf67f..28dd76c7cb1c 100644 --- a/trunk/sound/soc/fsl/imx-ssi.c +++ b/trunk/sound/soc/fsl/imx-ssi.c @@ -380,14 +380,13 @@ static int imx_ssi_dai_probe(struct snd_soc_dai *dai) static struct snd_soc_dai_driver imx_ssi_dai = { .probe = imx_ssi_dai_probe, .playback = { - /* The SSI does not support monaural audio. */ - .channels_min = 2, + .channels_min = 1, .channels_max = 2, .rates = SNDRV_PCM_RATE_8000_96000, .formats = SNDRV_PCM_FMTBIT_S16_LE, }, .capture = { - .channels_min = 2, + .channels_min = 1, .channels_max = 2, .rates = SNDRV_PCM_RATE_8000_96000, .formats = SNDRV_PCM_FMTBIT_S16_LE, diff --git a/trunk/sound/soc/mxs/Kconfig b/trunk/sound/soc/mxs/Kconfig index b6fa77678d97..99a997f19bb9 100644 --- a/trunk/sound/soc/mxs/Kconfig +++ b/trunk/sound/soc/mxs/Kconfig @@ -10,7 +10,7 @@ menuconfig SND_MXS_SOC if SND_MXS_SOC config SND_SOC_MXS_SGTL5000 - tristate "SoC Audio support for MXS boards with sgtl5000" + tristate "SoC Audio support for i.MX boards with sgtl5000" depends on I2C select SND_SOC_SGTL5000 help diff --git a/trunk/sound/soc/mxs/mxs-saif.c b/trunk/sound/soc/mxs/mxs-saif.c index b3030718c228..aba71bfa33b1 100644 --- a/trunk/sound/soc/mxs/mxs-saif.c +++ b/trunk/sound/soc/mxs/mxs-saif.c @@ -394,14 +394,9 @@ static int mxs_saif_hw_params(struct snd_pcm_substream *substream, struct snd_soc_dai *cpu_dai) { struct mxs_saif *saif = snd_soc_dai_get_drvdata(cpu_dai); - struct mxs_saif *master_saif; u32 scr, stat; int ret; - master_saif = mxs_saif_get_master(saif); - if (!master_saif) - return -EINVAL; - /* mclk should already be set */ if (!saif->mclk && saif->mclk_in_use) { dev_err(cpu_dai->dev, "set mclk first\n"); @@ -425,25 +420,6 @@ static int mxs_saif_hw_params(struct snd_pcm_substream *substream, return ret; } - /* prepare clk in hw_param, enable in trigger */ - clk_prepare(saif->clk); - if (saif != master_saif) { - /* - * Set an initial clock rate for the saif internal logic to work - * properly. This is important when working in EXTMASTER mode - * that uses the other saif's BITCLK&LRCLK but it still needs a - * basic clock which should be fast enough for the internal - * logic. - */ - clk_enable(saif->clk); - ret = clk_set_rate(saif->clk, 24000000); - clk_disable(saif->clk); - if (ret) - return ret; - - clk_prepare(master_saif->clk); - } - scr = __raw_readl(saif->base + SAIF_CTRL); scr &= ~BM_SAIF_CTRL_WORD_LENGTH; diff --git a/trunk/sound/soc/omap/am3517evm.c b/trunk/sound/soc/omap/am3517evm.c index df65f98211ec..009533ab8d18 100644 --- a/trunk/sound/soc/omap/am3517evm.c +++ b/trunk/sound/soc/omap/am3517evm.c @@ -59,7 +59,7 @@ static int am3517evm_hw_params(struct snd_pcm_substream *substream, return ret; } - ret = snd_soc_dai_set_sysclk(cpu_dai, OMAP_MCBSP_FSR_SRC_FSX, 0, + snd_soc_dai_set_sysclk(cpu_dai, OMAP_MCBSP_FSR_SRC_FSX, 0, SND_SOC_CLOCK_IN); if (ret < 0) { printk(KERN_ERR "can't set CPU system clock OMAP_MCBSP_FSR_SRC_FSX\n"); diff --git a/trunk/sound/soc/omap/mcbsp.c b/trunk/sound/soc/omap/mcbsp.c index d33c48baaf71..34835e8a9160 100644 --- a/trunk/sound/soc/omap/mcbsp.c +++ b/trunk/sound/soc/omap/mcbsp.c @@ -745,7 +745,7 @@ int omap_mcbsp_6pin_src_mux(struct omap_mcbsp *mcbsp, u8 mux) { const char *signal, *src; - if (!mcbsp->pdata->mux_signal) + if (mcbsp->pdata->mux_signal) return -EINVAL; switch (mux) { diff --git a/trunk/sound/soc/omap/omap-mcbsp.c b/trunk/sound/soc/omap/omap-mcbsp.c index acdd3ef14e08..1046083e90a0 100644 --- a/trunk/sound/soc/omap/omap-mcbsp.c +++ b/trunk/sound/soc/omap/omap-mcbsp.c @@ -820,4 +820,3 @@ module_platform_driver(asoc_mcbsp_driver); MODULE_AUTHOR("Jarkko Nikula "); MODULE_DESCRIPTION("OMAP I2S SoC Interface"); MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:omap-mcbsp"); diff --git a/trunk/sound/soc/omap/omap-pcm.c b/trunk/sound/soc/omap/omap-pcm.c index f0feb06615f8..5a649da9122a 100644 --- a/trunk/sound/soc/omap/omap-pcm.c +++ b/trunk/sound/soc/omap/omap-pcm.c @@ -441,4 +441,3 @@ module_platform_driver(omap_pcm_driver); MODULE_AUTHOR("Jarkko Nikula "); MODULE_DESCRIPTION("OMAP PCM DMA module"); MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:omap-pcm-audio"); diff --git a/trunk/sound/soc/samsung/dma.c b/trunk/sound/soc/samsung/dma.c index b70964ea448c..f3ebc38c10fe 100644 --- a/trunk/sound/soc/samsung/dma.c +++ b/trunk/sound/soc/samsung/dma.c @@ -34,7 +34,9 @@ static const struct snd_pcm_hardware dma_hardware = { .info = SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_MMAP_VALID, + SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_PAUSE | + SNDRV_PCM_INFO_RESUME, .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_U16_LE | SNDRV_PCM_FMTBIT_U8 | @@ -246,11 +248,15 @@ static int dma_trigger(struct snd_pcm_substream *substream, int cmd) switch (cmd) { case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: prtd->state |= ST_RUNNING; prtd->params->ops->trigger(prtd->params->ch); break; case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: prtd->state &= ~ST_RUNNING; prtd->params->ops->stop(prtd->params->ch); break; diff --git a/trunk/sound/soc/samsung/pcm.c b/trunk/sound/soc/samsung/pcm.c index 89b064650f14..b7b2a1f91425 100644 --- a/trunk/sound/soc/samsung/pcm.c +++ b/trunk/sound/soc/samsung/pcm.c @@ -20,7 +20,7 @@ #include #include -#include +#include #include "dma.h" #include "pcm.h" diff --git a/trunk/sound/soc/soc-core.c b/trunk/sound/soc/soc-core.c index c501af6d8dbe..f219b2f7ee68 100644 --- a/trunk/sound/soc/soc-core.c +++ b/trunk/sound/soc/soc-core.c @@ -826,7 +826,7 @@ static int soc_bind_dai_link(struct snd_soc_card *card, int num) } if (!rtd->cpu_dai) { - dev_err(card->dev, "CPU DAI %s not registered\n", + dev_dbg(card->dev, "CPU DAI %s not registered\n", dai_link->cpu_dai_name); return -EPROBE_DEFER; } @@ -857,14 +857,14 @@ static int soc_bind_dai_link(struct snd_soc_card *card, int num) } if (!rtd->codec_dai) { - dev_err(card->dev, "CODEC DAI %s not registered\n", + dev_dbg(card->dev, "CODEC DAI %s not registered\n", dai_link->codec_dai_name); return -EPROBE_DEFER; } } if (!rtd->codec) { - dev_err(card->dev, "CODEC %s not registered\n", + dev_dbg(card->dev, "CODEC %s not registered\n", dai_link->codec_name); return -EPROBE_DEFER; } @@ -888,7 +888,7 @@ static int soc_bind_dai_link(struct snd_soc_card *card, int num) rtd->platform = platform; } if (!rtd->platform) { - dev_err(card->dev, "platform %s not registered\n", + dev_dbg(card->dev, "platform %s not registered\n", dai_link->platform_name); return -EPROBE_DEFER; } @@ -1096,7 +1096,7 @@ static int soc_probe_codec(struct snd_soc_card *card, } /* If the driver didn't set I/O up try regmap */ - if (!codec->write && dev_get_regmap(codec->dev, NULL)) + if (!codec->control_data) snd_soc_codec_set_cache_io(codec, 0, 0, SND_SOC_REGMAP); if (driver->controls) @@ -1481,8 +1481,6 @@ static int soc_check_aux_dev(struct snd_soc_card *card, int num) return 0; } - dev_err(card->dev, "%s not registered\n", aux_dev->codec_name); - return -EPROBE_DEFER; } diff --git a/trunk/sound/soc/soc-dapm.c b/trunk/sound/soc/soc-dapm.c index f90139b5f50d..dd7c49fafd75 100644 --- a/trunk/sound/soc/soc-dapm.c +++ b/trunk/sound/soc/soc-dapm.c @@ -291,11 +291,8 @@ static int snd_soc_dapm_set_bias_level(struct snd_soc_dapm_context *dapm, if (dapm->codec->driver->set_bias_level) ret = dapm->codec->driver->set_bias_level(dapm->codec, level); - else - dapm->bias_level = level; - } else if (!card || dapm != &card->dapm) { + } else dapm->bias_level = level; - } if (ret != 0) goto out; diff --git a/trunk/sound/soc/soc-jack.c b/trunk/sound/soc/soc-jack.c index 0c172938b82a..7f8b3b7428bb 100644 --- a/trunk/sound/soc/soc-jack.c +++ b/trunk/sound/soc/soc-jack.c @@ -103,7 +103,7 @@ void snd_soc_jack_report(struct snd_soc_jack *jack, int status, int mask) } /* Report before the DAPM sync to help users updating micbias status */ - blocking_notifier_call_chain(&jack->notifier, jack->status, jack); + blocking_notifier_call_chain(&jack->notifier, status, jack); snd_soc_dapm_sync(dapm); diff --git a/trunk/sound/soc/spear/spear_pcm.c b/trunk/sound/soc/spear/spear_pcm.c index 8c7f23729446..97c2cac8e92c 100644 --- a/trunk/sound/soc/spear/spear_pcm.c +++ b/trunk/sound/soc/spear/spear_pcm.c @@ -138,7 +138,7 @@ static void spear_pcm_free(struct snd_pcm *pcm) continue; buf = &substream->dma_buffer; - if (!buf || !buf->area) + if (!buf && !buf->area) continue; dma_free_writecombine(pcm->card->dev, buf->bytes, diff --git a/trunk/sound/soc/tegra/tegra_alc5632.c b/trunk/sound/soc/tegra/tegra_alc5632.c index 76cb1b363b71..d684df294c0c 100644 --- a/trunk/sound/soc/tegra/tegra_alc5632.c +++ b/trunk/sound/soc/tegra/tegra_alc5632.c @@ -89,6 +89,7 @@ static struct snd_soc_jack_gpio tegra_alc5632_hp_jack_gpio = { .name = "Headset detection", .report = SND_JACK_HEADSET, .debounce_time = 150, + .invert = 1, }; static const struct snd_soc_dapm_widget tegra_alc5632_dapm_widgets[] = { @@ -176,7 +177,7 @@ static __devinit int tegra_alc5632_probe(struct platform_device *pdev) } alc5632->gpio_hp_det = of_get_named_gpio(np, "nvidia,hp-det-gpios", 0); - if (alc5632->gpio_hp_det == -EPROBE_DEFER) + if (alc5632->gpio_hp_det == -ENODEV) return -EPROBE_DEFER; ret = snd_soc_of_parse_card_name(card, "nvidia,model"); diff --git a/trunk/sound/soc/tegra/tegra_pcm.c b/trunk/sound/soc/tegra/tegra_pcm.c index 8d6900c1ee47..5658bcec1931 100644 --- a/trunk/sound/soc/tegra/tegra_pcm.c +++ b/trunk/sound/soc/tegra/tegra_pcm.c @@ -334,11 +334,11 @@ static int tegra_pcm_hw_params(struct snd_pcm_substream *substream, if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { slave_config.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; slave_config.dst_addr = dmap->addr; - slave_config.dst_maxburst = 4; + slave_config.src_maxburst = 0; } else { slave_config.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; slave_config.src_addr = dmap->addr; - slave_config.src_maxburst = 4; + slave_config.dst_maxburst = 0; } slave_config.slave_id = dmap->req_sel; diff --git a/trunk/sound/soc/tegra/tegra_wm8903.c b/trunk/sound/soc/tegra/tegra_wm8903.c index d4f14e492341..0c5bb33d258e 100644 --- a/trunk/sound/soc/tegra/tegra_wm8903.c +++ b/trunk/sound/soc/tegra/tegra_wm8903.c @@ -284,27 +284,27 @@ static __devinit int tegra_wm8903_driver_probe(struct platform_device *pdev) } else if (np) { pdata->gpio_spkr_en = of_get_named_gpio(np, "nvidia,spkr-en-gpios", 0); - if (pdata->gpio_spkr_en == -EPROBE_DEFER) + if (pdata->gpio_spkr_en == -ENODEV) return -EPROBE_DEFER; pdata->gpio_hp_mute = of_get_named_gpio(np, "nvidia,hp-mute-gpios", 0); - if (pdata->gpio_hp_mute == -EPROBE_DEFER) + if (pdata->gpio_hp_mute == -ENODEV) return -EPROBE_DEFER; pdata->gpio_hp_det = of_get_named_gpio(np, "nvidia,hp-det-gpios", 0); - if (pdata->gpio_hp_det == -EPROBE_DEFER) + if (pdata->gpio_hp_det == -ENODEV) return -EPROBE_DEFER; pdata->gpio_int_mic_en = of_get_named_gpio(np, "nvidia,int-mic-en-gpios", 0); - if (pdata->gpio_int_mic_en == -EPROBE_DEFER) + if (pdata->gpio_int_mic_en == -ENODEV) return -EPROBE_DEFER; pdata->gpio_ext_mic_en = of_get_named_gpio(np, "nvidia,ext-mic-en-gpios", 0); - if (pdata->gpio_ext_mic_en == -EPROBE_DEFER) + if (pdata->gpio_ext_mic_en == -ENODEV) return -EPROBE_DEFER; } diff --git a/trunk/sound/soc/ux500/ux500_msp_dai.c b/trunk/sound/soc/ux500/ux500_msp_dai.c index 057e28ef770e..62ac0285bfaf 100644 --- a/trunk/sound/soc/ux500/ux500_msp_dai.c +++ b/trunk/sound/soc/ux500/ux500_msp_dai.c @@ -21,7 +21,7 @@ #include #include -#include +#include #include #include diff --git a/trunk/sound/soc/ux500/ux500_msp_i2s.c b/trunk/sound/soc/ux500/ux500_msp_i2s.c index eb85113d472a..ee14d2dac2f5 100644 --- a/trunk/sound/soc/ux500/ux500_msp_i2s.c +++ b/trunk/sound/soc/ux500/ux500_msp_i2s.c @@ -19,7 +19,7 @@ #include #include -#include +#include #include @@ -663,6 +663,7 @@ int ux500_msp_i2s_init_msp(struct platform_device *pdev, struct ux500_msp **msp_p, struct msp_i2s_platform_data *platform_data) { + int ret = 0; struct resource *res = NULL; struct i2s_controller *i2s_cont; struct ux500_msp *msp; @@ -684,14 +685,15 @@ int ux500_msp_i2s_init_msp(struct platform_device *pdev, if (res == NULL) { dev_err(&pdev->dev, "%s: ERROR: Unable to get resource!\n", __func__); - return -ENOMEM; + ret = -ENOMEM; + goto err_res; } - msp->registers = devm_ioremap(&pdev->dev, res->start, - resource_size(res)); + msp->registers = ioremap(res->start, (res->end - res->start + 1)); if (msp->registers == NULL) { dev_err(&pdev->dev, "%s: ERROR: ioremap failed!\n", __func__); - return -ENOMEM; + ret = -ENOMEM; + goto err_res; } msp->msp_state = MSP_STATE_IDLE; @@ -703,7 +705,7 @@ int ux500_msp_i2s_init_msp(struct platform_device *pdev, dev_err(&pdev->dev, "%s: ERROR: Failed to allocate I2S-controller!\n", __func__); - return -ENOMEM; + goto err_i2s_cont; } i2s_cont->dev.parent = &pdev->dev; i2s_cont->data = (void *)msp; @@ -714,6 +716,14 @@ int ux500_msp_i2s_init_msp(struct platform_device *pdev, msp->i2s_cont = i2s_cont; return 0; + +err_i2s_cont: + iounmap(msp->registers); + +err_res: + devm_kfree(&pdev->dev, msp); + + return ret; } void ux500_msp_i2s_cleanup_msp(struct platform_device *pdev, @@ -722,6 +732,11 @@ void ux500_msp_i2s_cleanup_msp(struct platform_device *pdev, dev_dbg(msp->dev, "%s: Enter (id = %d).\n", __func__, msp->id); device_unregister(&msp->i2s_cont->dev); + devm_kfree(&pdev->dev, msp->i2s_cont); + + iounmap(msp->registers); + + devm_kfree(&pdev->dev, msp); } MODULE_LICENSE("GPL v2"); diff --git a/trunk/sound/soc/ux500/ux500_msp_i2s.h b/trunk/sound/soc/ux500/ux500_msp_i2s.h index 2d9136da9865..7f71b4a0d4bc 100644 --- a/trunk/sound/soc/ux500/ux500_msp_i2s.h +++ b/trunk/sound/soc/ux500/ux500_msp_i2s.h @@ -17,7 +17,7 @@ #include -#include +#include #define MSP_INPUT_FREQ_APB 48000000 diff --git a/trunk/sound/usb/card.c b/trunk/sound/usb/card.c index 4a469f0cb6d4..d5b5c3388e28 100644 --- a/trunk/sound/usb/card.c +++ b/trunk/sound/usb/card.c @@ -553,7 +553,7 @@ static void snd_usb_audio_disconnect(struct usb_device *dev, struct snd_usb_audio *chip) { struct snd_card *card; - struct list_head *p, *n; + struct list_head *p; if (chip == (void *)-1L) return; @@ -570,7 +570,7 @@ static void snd_usb_audio_disconnect(struct usb_device *dev, snd_usb_stream_disconnect(p); } /* release the endpoint resources */ - list_for_each_safe(p, n, &chip->ep_list) { + list_for_each(p, &chip->ep_list) { snd_usb_endpoint_free(p); } /* release the midi resources */ diff --git a/trunk/sound/usb/endpoint.c b/trunk/sound/usb/endpoint.c index 060dccb9ec75..0f647d22cb4a 100644 --- a/trunk/sound/usb/endpoint.c +++ b/trunk/sound/usb/endpoint.c @@ -141,7 +141,7 @@ int snd_usb_endpoint_implict_feedback_sink(struct snd_usb_endpoint *ep) * * For implicit feedback, next_packet_size() is unused. */ -int snd_usb_endpoint_next_packet_size(struct snd_usb_endpoint *ep) +static int next_packet_size(struct snd_usb_endpoint *ep) { unsigned long flags; int ret; @@ -177,6 +177,15 @@ static void retire_inbound_urb(struct snd_usb_endpoint *ep, ep->retire_data_urb(ep->data_subs, urb); } +static void prepare_outbound_urb_sizes(struct snd_usb_endpoint *ep, + struct snd_urb_ctx *ctx) +{ + int i; + + for (i = 0; i < ctx->packets; ++i) + ctx->packet_size[i] = next_packet_size(ep); +} + /* * Prepare a PLAYBACK urb for submission to the bus. */ @@ -197,13 +206,7 @@ static void prepare_outbound_urb(struct snd_usb_endpoint *ep, /* no data provider, so send silence */ unsigned int offs = 0; for (i = 0; i < ctx->packets; ++i) { - int counts; - - if (ctx->packet_size[i]) - counts = ctx->packet_size[i]; - else - counts = snd_usb_endpoint_next_packet_size(ep); - + int counts = ctx->packet_size[i]; urb->iso_frame_desc[i].offset = offs * ep->stride; urb->iso_frame_desc[i].length = counts * ep->stride; offs += counts; @@ -367,6 +370,7 @@ static void snd_complete_urb(struct urb *urb) goto exit_clear; } + prepare_outbound_urb_sizes(ep, ctx); prepare_outbound_urb(ep, ctx); } else { retire_inbound_urb(ep, ctx); @@ -795,9 +799,7 @@ int snd_usb_endpoint_set_params(struct snd_usb_endpoint *ep, /** * snd_usb_endpoint_start: start an snd_usb_endpoint * - * @ep: the endpoint to start - * @can_sleep: flag indicating whether the operation is executed in - * non-atomic context + * @ep: the endpoint to start * * A call to this function will increment the use count of the endpoint. * In case it is not already running, the URBs for this endpoint will be @@ -807,7 +809,7 @@ int snd_usb_endpoint_set_params(struct snd_usb_endpoint *ep, * * Returns an error if the URB submission failed, 0 in all other cases. */ -int snd_usb_endpoint_start(struct snd_usb_endpoint *ep, int can_sleep) +int snd_usb_endpoint_start(struct snd_usb_endpoint *ep) { int err; unsigned int i; @@ -820,9 +822,8 @@ int snd_usb_endpoint_start(struct snd_usb_endpoint *ep, int can_sleep) return 0; /* just to be sure */ - deactivate_urbs(ep, 0, can_sleep); - if (can_sleep) - wait_clear_urbs(ep); + deactivate_urbs(ep, 0, 1); + wait_clear_urbs(ep); ep->active_mask = 0; ep->unlink_mask = 0; @@ -853,6 +854,7 @@ int snd_usb_endpoint_start(struct snd_usb_endpoint *ep, int can_sleep) goto __error; if (usb_pipeout(ep->pipe)) { + prepare_outbound_urb_sizes(ep, urb->context); prepare_outbound_urb(ep, urb->context); } else { prepare_inbound_urb(ep, urb->context); diff --git a/trunk/sound/usb/endpoint.h b/trunk/sound/usb/endpoint.h index cbbbdf226d66..ee2723fb174f 100644 --- a/trunk/sound/usb/endpoint.h +++ b/trunk/sound/usb/endpoint.h @@ -13,7 +13,7 @@ int snd_usb_endpoint_set_params(struct snd_usb_endpoint *ep, struct audioformat *fmt, struct snd_usb_endpoint *sync_ep); -int snd_usb_endpoint_start(struct snd_usb_endpoint *ep, int can_sleep); +int snd_usb_endpoint_start(struct snd_usb_endpoint *ep); void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep, int force, int can_sleep, int wait); int snd_usb_endpoint_activate(struct snd_usb_endpoint *ep); @@ -21,7 +21,6 @@ int snd_usb_endpoint_deactivate(struct snd_usb_endpoint *ep); void snd_usb_endpoint_free(struct list_head *head); int snd_usb_endpoint_implict_feedback_sink(struct snd_usb_endpoint *ep); -int snd_usb_endpoint_next_packet_size(struct snd_usb_endpoint *ep); void snd_usb_handle_sync_urb(struct snd_usb_endpoint *ep, struct snd_usb_endpoint *sender, diff --git a/trunk/sound/usb/pcm.c b/trunk/sound/usb/pcm.c index f782ce19bf5a..a1298f379428 100644 --- a/trunk/sound/usb/pcm.c +++ b/trunk/sound/usb/pcm.c @@ -212,7 +212,7 @@ int snd_usb_init_pitch(struct snd_usb_audio *chip, int iface, } } -static int start_endpoints(struct snd_usb_substream *subs, int can_sleep) +static int start_endpoints(struct snd_usb_substream *subs) { int err; @@ -225,7 +225,7 @@ static int start_endpoints(struct snd_usb_substream *subs, int can_sleep) snd_printdd(KERN_DEBUG "Starting data EP @%p\n", ep); ep->data_subs = subs; - err = snd_usb_endpoint_start(ep, can_sleep); + err = snd_usb_endpoint_start(ep); if (err < 0) { clear_bit(SUBSTREAM_FLAG_DATA_EP_STARTED, &subs->flags); return err; @@ -236,25 +236,10 @@ static int start_endpoints(struct snd_usb_substream *subs, int can_sleep) !test_and_set_bit(SUBSTREAM_FLAG_SYNC_EP_STARTED, &subs->flags)) { struct snd_usb_endpoint *ep = subs->sync_endpoint; - if (subs->data_endpoint->iface != subs->sync_endpoint->iface || - subs->data_endpoint->alt_idx != subs->sync_endpoint->alt_idx) { - err = usb_set_interface(subs->dev, - subs->sync_endpoint->iface, - subs->sync_endpoint->alt_idx); - if (err < 0) { - snd_printk(KERN_ERR - "%d:%d:%d: cannot set interface (%d)\n", - subs->dev->devnum, - subs->sync_endpoint->iface, - subs->sync_endpoint->alt_idx, err); - return -EIO; - } - } - snd_printdd(KERN_DEBUG "Starting sync EP @%p\n", ep); ep->sync_slave = subs->data_endpoint; - err = snd_usb_endpoint_start(ep, can_sleep); + err = snd_usb_endpoint_start(ep); if (err < 0) { clear_bit(SUBSTREAM_FLAG_SYNC_EP_STARTED, &subs->flags); return err; @@ -562,7 +547,7 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream) /* for playback, submit the URBs now; otherwise, the first hwptr_done * updates for all URBs would happen at the same time when starting */ if (subs->direction == SNDRV_PCM_STREAM_PLAYBACK) - return start_endpoints(subs, 1); + return start_endpoints(subs); return 0; } @@ -1044,7 +1029,6 @@ static void prepare_playback_urb(struct snd_usb_substream *subs, struct urb *urb) { struct snd_pcm_runtime *runtime = subs->pcm_substream->runtime; - struct snd_usb_endpoint *ep = subs->data_endpoint; struct snd_urb_ctx *ctx = urb->context; unsigned int counts, frames, bytes; int i, stride, period_elapsed = 0; @@ -1056,11 +1040,7 @@ static void prepare_playback_urb(struct snd_usb_substream *subs, urb->number_of_packets = 0; spin_lock_irqsave(&subs->lock, flags); for (i = 0; i < ctx->packets; i++) { - if (ctx->packet_size[i]) - counts = ctx->packet_size[i]; - else - counts = snd_usb_endpoint_next_packet_size(ep); - + counts = ctx->packet_size[i]; /* set up descriptor */ urb->iso_frame_desc[i].offset = frames * stride; urb->iso_frame_desc[i].length = counts * stride; @@ -1111,16 +1091,7 @@ static void prepare_playback_urb(struct snd_usb_substream *subs, subs->hwptr_done += bytes; if (subs->hwptr_done >= runtime->buffer_size * stride) subs->hwptr_done -= runtime->buffer_size * stride; - - /* update delay with exact number of samples queued */ - runtime->delay = subs->last_delay; runtime->delay += frames; - subs->last_delay = runtime->delay; - - /* realign last_frame_number */ - subs->last_frame_number = usb_get_current_frame_number(subs->dev); - subs->last_frame_number &= 0xFF; /* keep 8 LSBs */ - spin_unlock_irqrestore(&subs->lock, flags); urb->transfer_buffer_length = bytes; if (period_elapsed) @@ -1138,32 +1109,12 @@ static void retire_playback_urb(struct snd_usb_substream *subs, struct snd_pcm_runtime *runtime = subs->pcm_substream->runtime; int stride = runtime->frame_bits >> 3; int processed = urb->transfer_buffer_length / stride; - int est_delay; - - /* ignore the delay accounting when procssed=0 is given, i.e. - * silent payloads are procssed before handling the actual data - */ - if (!processed) - return; spin_lock_irqsave(&subs->lock, flags); - est_delay = snd_usb_pcm_delay(subs, runtime->rate); - /* update delay with exact number of samples played */ - if (processed > subs->last_delay) - subs->last_delay = 0; + if (processed > runtime->delay) + runtime->delay = 0; else - subs->last_delay -= processed; - runtime->delay = subs->last_delay; - - /* - * Report when delay estimate is off by more than 2ms. - * The error should be lower than 2ms since the estimate relies - * on two reads of a counter updated every ms. - */ - if (abs(est_delay - subs->last_delay) * 1000 > runtime->rate * 2) - snd_printk(KERN_DEBUG "delay: estimated %d, actual %d\n", - est_delay, subs->last_delay); - + runtime->delay -= processed; spin_unlock_irqrestore(&subs->lock, flags); } @@ -1221,7 +1172,7 @@ static int snd_usb_substream_capture_trigger(struct snd_pcm_substream *substream switch (cmd) { case SNDRV_PCM_TRIGGER_START: - err = start_endpoints(subs, 0); + err = start_endpoints(subs); if (err < 0) return err; diff --git a/trunk/tools/hv/hv_get_dhcp_info.sh b/trunk/tools/hv/hv_get_dhcp_info.sh deleted file mode 100755 index ccd3e9532764..000000000000 --- a/trunk/tools/hv/hv_get_dhcp_info.sh +++ /dev/null @@ -1,28 +0,0 @@ -#!/bin/bash - -# This example script retrieves the DHCP state of a given interface. -# In the interest of keeping the KVP daemon code free of distro specific -# information; the kvp daemon code invokes this external script to gather -# DHCP setting for the specific interface. -# -# Input: Name of the interface -# -# Output: The script prints the string "Enabled" to stdout to indicate -# that DHCP is enabled on the interface. If DHCP is not enabled, -# the script prints the string "Disabled" to stdout. -# -# Each Distro is expected to implement this script in a distro specific -# fashion. For instance on Distros that ship with Network Manager enabled, -# this script can be based on the Network Manager APIs for retrieving DHCP -# information. - -if_file="/etc/sysconfig/network-scripts/ifcfg-"$1 - -dhcp=$(grep "dhcp" $if_file 2>/dev/null) - -if [ "$dhcp" != "" ]; -then -echo "Enabled" -else -echo "Disabled" -fi diff --git a/trunk/tools/hv/hv_get_dns_info.sh b/trunk/tools/hv/hv_get_dns_info.sh deleted file mode 100755 index 058c17b46ffc..000000000000 --- a/trunk/tools/hv/hv_get_dns_info.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/bash - -# This example script parses /etc/resolv.conf to retrive DNS information. -# In the interest of keeping the KVP daemon code free of distro specific -# information; the kvp daemon code invokes this external script to gather -# DNS information. -# This script is expected to print the nameserver values to stdout. -# Each Distro is expected to implement this script in a distro specific -# fashion. For instance on Distros that ship with Network Manager enabled, -# this script can be based on the Network Manager APIs for retrieving DNS -# entries. - -cat /etc/resolv.conf 2>/dev/null | awk '/^nameserver/ { print $2 }' diff --git a/trunk/tools/hv/hv_kvp_daemon.c b/trunk/tools/hv/hv_kvp_daemon.c index 5959affd8820..d9834b362943 100644 --- a/trunk/tools/hv/hv_kvp_daemon.c +++ b/trunk/tools/hv/hv_kvp_daemon.c @@ -31,7 +31,6 @@ #include #include #include -#include #include #include #include @@ -42,7 +41,6 @@ #include #include #include -#include /* * KVP protocol: The user mode component first registers with the @@ -70,39 +68,25 @@ enum key_index { ProcessorArchitecture }; - -enum { - IPADDR = 0, - NETMASK, - GATEWAY, - DNS -}; - static char kvp_send_buffer[4096]; -static char kvp_recv_buffer[4096 * 2]; +static char kvp_recv_buffer[4096]; static struct sockaddr_nl addr; -static int in_hand_shake = 1; static char *os_name = ""; static char *os_major = ""; static char *os_minor = ""; static char *processor_arch; static char *os_build; -static char *lic_version = "Unknown version"; +static char *lic_version; static struct utsname uts_buf; -/* - * The location of the interface configuration file. - */ - -#define KVP_CONFIG_LOC "/var/opt/" #define MAX_FILE_NAME 100 #define ENTRIES_PER_BLOCK 50 struct kvp_record { - char key[HV_KVP_EXCHANGE_MAX_KEY_SIZE]; - char value[HV_KVP_EXCHANGE_MAX_VALUE_SIZE]; + __u8 key[HV_KVP_EXCHANGE_MAX_KEY_SIZE]; + __u8 value[HV_KVP_EXCHANGE_MAX_VALUE_SIZE]; }; struct kvp_file_state { @@ -110,7 +94,7 @@ struct kvp_file_state { int num_blocks; struct kvp_record *records; int num_records; - char fname[MAX_FILE_NAME]; + __u8 fname[MAX_FILE_NAME]; }; static struct kvp_file_state kvp_file_info[KVP_POOL_COUNT]; @@ -122,7 +106,7 @@ static void kvp_acquire_lock(int pool) if (fcntl(kvp_file_info[pool].fd, F_SETLKW, &fl) == -1) { syslog(LOG_ERR, "Failed to acquire the lock pool: %d", pool); - exit(EXIT_FAILURE); + exit(-1); } } @@ -134,7 +118,7 @@ static void kvp_release_lock(int pool) if (fcntl(kvp_file_info[pool].fd, F_SETLK, &fl) == -1) { perror("fcntl"); syslog(LOG_ERR, "Failed to release the lock pool: %d", pool); - exit(EXIT_FAILURE); + exit(-1); } } @@ -153,19 +137,14 @@ static void kvp_update_file(int pool) if (!filep) { kvp_release_lock(pool); syslog(LOG_ERR, "Failed to open file, pool: %d", pool); - exit(EXIT_FAILURE); + exit(-1); } bytes_written = fwrite(kvp_file_info[pool].records, sizeof(struct kvp_record), kvp_file_info[pool].num_records, filep); - if (ferror(filep) || fclose(filep)) { - kvp_release_lock(pool); - syslog(LOG_ERR, "Failed to write file, pool: %d", pool); - exit(EXIT_FAILURE); - } - + fflush(filep); kvp_release_lock(pool); } @@ -184,19 +163,14 @@ static void kvp_update_mem_state(int pool) if (!filep) { kvp_release_lock(pool); syslog(LOG_ERR, "Failed to open file, pool: %d", pool); - exit(EXIT_FAILURE); + exit(-1); } - for (;;) { + while (!feof(filep)) { readp = &record[records_read]; records_read += fread(readp, sizeof(struct kvp_record), ENTRIES_PER_BLOCK * num_blocks, filep); - if (ferror(filep)) { - syslog(LOG_ERR, "Failed to read file, pool: %d", pool); - exit(EXIT_FAILURE); - } - if (!feof(filep)) { /* * We have more data to read. @@ -206,7 +180,7 @@ static void kvp_update_mem_state(int pool) if (record == NULL) { syslog(LOG_ERR, "malloc failed"); - exit(EXIT_FAILURE); + exit(-1); } continue; } @@ -217,15 +191,14 @@ static void kvp_update_mem_state(int pool) kvp_file_info[pool].records = record; kvp_file_info[pool].num_records = records_read; - fclose(filep); kvp_release_lock(pool); } static int kvp_file_init(void) { - int fd; + int ret, fd; FILE *filep; size_t records_read; - char *fname; + __u8 *fname; struct kvp_record *record; struct kvp_record *readp; int num_blocks; @@ -235,7 +208,7 @@ static int kvp_file_init(void) if (access("/var/opt/hyperv", F_OK)) { if (mkdir("/var/opt/hyperv", S_IRUSR | S_IWUSR | S_IROTH)) { syslog(LOG_ERR, " Failed to create /var/opt/hyperv"); - exit(EXIT_FAILURE); + exit(-1); } } @@ -259,18 +232,12 @@ static int kvp_file_init(void) fclose(filep); return 1; } - for (;;) { + while (!feof(filep)) { readp = &record[records_read]; records_read += fread(readp, sizeof(struct kvp_record), ENTRIES_PER_BLOCK, filep); - if (ferror(filep)) { - syslog(LOG_ERR, "Failed to read file, pool: %d", - i); - exit(EXIT_FAILURE); - } - if (!feof(filep)) { /* * We have more data to read. @@ -344,6 +311,7 @@ static int kvp_key_add_or_modify(int pool, __u8 *key, int key_size, __u8 *value, int value_size) { int i; + int j, k; int num_records; struct kvp_record *record; int num_blocks; @@ -426,7 +394,7 @@ static int kvp_get_value(int pool, __u8 *key, int key_size, __u8 *value, return 1; } -static int kvp_pool_enumerate(int pool, int index, __u8 *key, int key_size, +static void kvp_pool_enumerate(int pool, int index, __u8 *key, int key_size, __u8 *value, int value_size) { struct kvp_record *record; @@ -438,12 +406,16 @@ static int kvp_pool_enumerate(int pool, int index, __u8 *key, int key_size, record = kvp_file_info[pool].records; if (index >= kvp_file_info[pool].num_records) { - return 1; + /* + * This is an invalid index; terminate enumeration; + * - a NULL value will do the trick. + */ + strcpy(value, ""); + return; } memcpy(key, record[index].key, key_size); memcpy(value, record[index].value, value_size); - return 0; } @@ -454,7 +426,6 @@ void kvp_get_os_info(void) uname(&uts_buf); os_build = uts_buf.release; - os_name = uts_buf.sysname; processor_arch = uts_buf.machine; /* @@ -466,70 +437,20 @@ void kvp_get_os_info(void) if (p) *p = '\0'; - /* - * Parse the /etc/os-release file if present: - * http://www.freedesktop.org/software/systemd/man/os-release.html - */ - file = fopen("/etc/os-release", "r"); - if (file != NULL) { - while (fgets(buf, sizeof(buf), file)) { - char *value, *q; - - /* Ignore comments */ - if (buf[0] == '#') - continue; - - /* Split into name=value */ - p = strchr(buf, '='); - if (!p) - continue; - *p++ = 0; - - /* Remove quotes and newline; un-escape */ - value = p; - q = p; - while (*p) { - if (*p == '\\') { - ++p; - if (!*p) - break; - *q++ = *p++; - } else if (*p == '\'' || *p == '"' || - *p == '\n') { - ++p; - } else { - *q++ = *p++; - } - } - *q = 0; - - if (!strcmp(buf, "NAME")) { - p = strdup(value); - if (!p) - break; - os_name = p; - } else if (!strcmp(buf, "VERSION_ID")) { - p = strdup(value); - if (!p) - break; - os_major = p; - } - } - fclose(file); - return; - } - - /* Fallback for older RH/SUSE releases */ file = fopen("/etc/SuSE-release", "r"); if (file != NULL) goto kvp_osinfo_found; file = fopen("/etc/redhat-release", "r"); if (file != NULL) goto kvp_osinfo_found; + /* + * Add code for other supported platforms. + */ /* * We don't have information about the os. */ + os_name = uts_buf.sysname; return; kvp_osinfo_found: @@ -573,458 +494,82 @@ void kvp_get_os_info(void) return; } - - -/* - * Retrieve an interface name corresponding to the specified guid. - * If there is a match, the function returns a pointer - * to the interface name and if not, a NULL is returned. - * If a match is found, the caller is responsible for - * freeing the memory. - */ - -static char *kvp_get_if_name(char *guid) -{ - DIR *dir; - struct dirent *entry; - FILE *file; - char *p, *q, *x; - char *if_name = NULL; - char buf[256]; - char *kvp_net_dir = "/sys/class/net/"; - char dev_id[256]; - - dir = opendir(kvp_net_dir); - if (dir == NULL) - return NULL; - - snprintf(dev_id, sizeof(dev_id), "%s", kvp_net_dir); - q = dev_id + strlen(kvp_net_dir); - - while ((entry = readdir(dir)) != NULL) { - /* - * Set the state for the next pass. - */ - *q = '\0'; - strcat(dev_id, entry->d_name); - strcat(dev_id, "/device/device_id"); - - file = fopen(dev_id, "r"); - if (file == NULL) - continue; - - p = fgets(buf, sizeof(buf), file); - if (p) { - x = strchr(p, '\n'); - if (x) - *x = '\0'; - - if (!strcmp(p, guid)) { - /* - * Found the guid match; return the interface - * name. The caller will free the memory. - */ - if_name = strdup(entry->d_name); - fclose(file); - break; - } - } - fclose(file); - } - - closedir(dir); - return if_name; -} - -/* - * Retrieve the MAC address given the interface name. - */ - -static char *kvp_if_name_to_mac(char *if_name) -{ - FILE *file; - char *p, *x; - char buf[256]; - char addr_file[256]; - int i; - char *mac_addr = NULL; - - snprintf(addr_file, sizeof(addr_file), "%s%s%s", "/sys/class/net/", - if_name, "/address"); - - file = fopen(addr_file, "r"); - if (file == NULL) - return NULL; - - p = fgets(buf, sizeof(buf), file); - if (p) { - x = strchr(p, '\n'); - if (x) - *x = '\0'; - for (i = 0; i < strlen(p); i++) - p[i] = toupper(p[i]); - mac_addr = strdup(p); - } - - fclose(file); - return mac_addr; -} - - -/* - * Retrieve the interface name given tha MAC address. - */ - -static char *kvp_mac_to_if_name(char *mac) -{ - DIR *dir; - struct dirent *entry; - FILE *file; - char *p, *q, *x; - char *if_name = NULL; - char buf[256]; - char *kvp_net_dir = "/sys/class/net/"; - char dev_id[256]; - int i; - - dir = opendir(kvp_net_dir); - if (dir == NULL) - return NULL; - - snprintf(dev_id, sizeof(dev_id), kvp_net_dir); - q = dev_id + strlen(kvp_net_dir); - - while ((entry = readdir(dir)) != NULL) { - /* - * Set the state for the next pass. - */ - *q = '\0'; - - strcat(dev_id, entry->d_name); - strcat(dev_id, "/address"); - - file = fopen(dev_id, "r"); - if (file == NULL) - continue; - - p = fgets(buf, sizeof(buf), file); - if (p) { - x = strchr(p, '\n'); - if (x) - *x = '\0'; - - for (i = 0; i < strlen(p); i++) - p[i] = toupper(p[i]); - - if (!strcmp(p, mac)) { - /* - * Found the MAC match; return the interface - * name. The caller will free the memory. - */ - if_name = strdup(entry->d_name); - fclose(file); - break; - } - } - fclose(file); - } - - closedir(dir); - return if_name; -} - - -static void kvp_process_ipconfig_file(char *cmd, - char *config_buf, int len, - int element_size, int offset) -{ - char buf[256]; - char *p; - char *x; - FILE *file; - - /* - * First execute the command. - */ - file = popen(cmd, "r"); - if (file == NULL) - return; - - if (offset == 0) - memset(config_buf, 0, len); - while ((p = fgets(buf, sizeof(buf), file)) != NULL) { - if ((len - strlen(config_buf)) < (element_size + 1)) - break; - - x = strchr(p, '\n'); - *x = '\0'; - strcat(config_buf, p); - strcat(config_buf, ";"); - } - pclose(file); -} - -static void kvp_get_ipconfig_info(char *if_name, - struct hv_kvp_ipaddr_value *buffer) -{ - char cmd[512]; - char dhcp_info[128]; - char *p; - FILE *file; - - /* - * Get the address of default gateway (ipv4). - */ - sprintf(cmd, "%s %s", "ip route show dev", if_name); - strcat(cmd, " | awk '/default/ {print $3 }'"); - - /* - * Execute the command to gather gateway info. - */ - kvp_process_ipconfig_file(cmd, (char *)buffer->gate_way, - (MAX_GATEWAY_SIZE * 2), INET_ADDRSTRLEN, 0); - - /* - * Get the address of default gateway (ipv6). - */ - sprintf(cmd, "%s %s", "ip -f inet6 route show dev", if_name); - strcat(cmd, " | awk '/default/ {print $3 }'"); - - /* - * Execute the command to gather gateway info (ipv6). - */ - kvp_process_ipconfig_file(cmd, (char *)buffer->gate_way, - (MAX_GATEWAY_SIZE * 2), INET6_ADDRSTRLEN, 1); - - - /* - * Gather the DNS state. - * Since there is no standard way to get this information - * across various distributions of interest; we just invoke - * an external script that needs to be ported across distros - * of interest. - * - * Following is the expected format of the information from the script: - * - * ipaddr1 (nameserver1) - * ipaddr2 (nameserver2) - * . - * . - */ - - sprintf(cmd, "%s", "hv_get_dns_info"); - - /* - * Execute the command to gather DNS info. - */ - kvp_process_ipconfig_file(cmd, (char *)buffer->dns_addr, - (MAX_IP_ADDR_SIZE * 2), INET_ADDRSTRLEN, 0); - - /* - * Gather the DHCP state. - * We will gather this state by invoking an external script. - * The parameter to the script is the interface name. - * Here is the expected output: - * - * Enabled: DHCP enabled. - */ - - sprintf(cmd, "%s %s", "hv_get_dhcp_info", if_name); - - file = popen(cmd, "r"); - if (file == NULL) - return; - - p = fgets(dhcp_info, sizeof(dhcp_info), file); - if (p == NULL) { - pclose(file); - return; - } - - if (!strncmp(p, "Enabled", 7)) - buffer->dhcp_enabled = 1; - else - buffer->dhcp_enabled = 0; - - pclose(file); -} - - -static unsigned int hweight32(unsigned int *w) -{ - unsigned int res = *w - ((*w >> 1) & 0x55555555); - res = (res & 0x33333333) + ((res >> 2) & 0x33333333); - res = (res + (res >> 4)) & 0x0F0F0F0F; - res = res + (res >> 8); - return (res + (res >> 16)) & 0x000000FF; -} - -static int kvp_process_ip_address(void *addrp, - int family, char *buffer, - int length, int *offset) -{ - struct sockaddr_in *addr; - struct sockaddr_in6 *addr6; - int addr_length; - char tmp[50]; - const char *str; - - if (family == AF_INET) { - addr = (struct sockaddr_in *)addrp; - str = inet_ntop(family, &addr->sin_addr, tmp, 50); - addr_length = INET_ADDRSTRLEN; - } else { - addr6 = (struct sockaddr_in6 *)addrp; - str = inet_ntop(family, &addr6->sin6_addr.s6_addr, tmp, 50); - addr_length = INET6_ADDRSTRLEN; - } - - if ((length - *offset) < addr_length + 1) - return HV_E_FAIL; - if (str == NULL) { - strcpy(buffer, "inet_ntop failed\n"); - return HV_E_FAIL; - } - if (*offset == 0) - strcpy(buffer, tmp); - else - strcat(buffer, tmp); - strcat(buffer, ";"); - - *offset += strlen(str) + 1; - return 0; -} - static int -kvp_get_ip_info(int family, char *if_name, int op, - void *out_buffer, int length) +kvp_get_ip_address(int family, char *buffer, int length) { struct ifaddrs *ifap; struct ifaddrs *curp; + int ipv4_len = strlen("255.255.255.255") + 1; + int ipv6_len = strlen("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff")+1; int offset = 0; - int sn_offset = 0; + const char *str; + char tmp[50]; int error = 0; - char *buffer; - struct hv_kvp_ipaddr_value *ip_buffer; - char cidr_mask[5]; /* /xyz */ - int weight; - int i; - unsigned int *w; - char *sn_str; - struct sockaddr_in6 *addr6; - - if (op == KVP_OP_ENUMERATE) { - buffer = out_buffer; - } else { - ip_buffer = out_buffer; - buffer = (char *)ip_buffer->ip_addr; - ip_buffer->addr_family = 0; - } + /* * On entry into this function, the buffer is capable of holding the - * maximum key value. + * maximum key value (2048 bytes). */ if (getifaddrs(&ifap)) { strcpy(buffer, "getifaddrs failed\n"); - return HV_E_FAIL; + return 1; } curp = ifap; while (curp != NULL) { - if (curp->ifa_addr == NULL) { - curp = curp->ifa_next; - continue; - } + if ((curp->ifa_addr != NULL) && + (curp->ifa_addr->sa_family == family)) { + if (family == AF_INET) { + struct sockaddr_in *addr = + (struct sockaddr_in *) curp->ifa_addr; + + str = inet_ntop(family, &addr->sin_addr, + tmp, 50); + if (str == NULL) { + strcpy(buffer, "inet_ntop failed\n"); + error = 1; + goto getaddr_done; + } + if (offset == 0) + strcpy(buffer, tmp); + else + strcat(buffer, tmp); + strcat(buffer, ";"); - if ((if_name != NULL) && - (strncmp(curp->ifa_name, if_name, strlen(if_name)))) { - /* - * We want info about a specific interface; - * just continue. - */ - curp = curp->ifa_next; - continue; - } + offset += strlen(str) + 1; + if ((length - offset) < (ipv4_len + 1)) + goto getaddr_done; - /* - * We only support two address families: AF_INET and AF_INET6. - * If a family value of 0 is specified, we collect both - * supported address families; if not we gather info on - * the specified address family. - */ - if ((family != 0) && (curp->ifa_addr->sa_family != family)) { - curp = curp->ifa_next; - continue; - } - if ((curp->ifa_addr->sa_family != AF_INET) && - (curp->ifa_addr->sa_family != AF_INET6)) { - curp = curp->ifa_next; - continue; - } + } else { - if (op == KVP_OP_GET_IP_INFO) { /* - * Gather info other than the IP address. - * IP address info will be gathered later. + * We only support AF_INET and AF_INET6 + * and the list of addresses is separated by a ";". */ - if (curp->ifa_addr->sa_family == AF_INET) { - ip_buffer->addr_family |= ADDR_FAMILY_IPV4; - /* - * Get subnet info. - */ - error = kvp_process_ip_address( - curp->ifa_netmask, - AF_INET, - (char *) - ip_buffer->sub_net, - length, - &sn_offset); - if (error) - goto gather_ipaddr; - } else { - ip_buffer->addr_family |= ADDR_FAMILY_IPV6; - - /* - * Get subnet info in CIDR format. - */ - weight = 0; - sn_str = (char *)ip_buffer->sub_net; - addr6 = (struct sockaddr_in6 *) - curp->ifa_netmask; - w = addr6->sin6_addr.s6_addr32; - - for (i = 0; i < 4; i++) - weight += hweight32(&w[i]); - - sprintf(cidr_mask, "/%d", weight); - if ((length - sn_offset) < - (strlen(cidr_mask) + 1)) - goto gather_ipaddr; - - if (sn_offset == 0) - strcpy(sn_str, cidr_mask); + struct sockaddr_in6 *addr = + (struct sockaddr_in6 *) curp->ifa_addr; + + str = inet_ntop(family, + &addr->sin6_addr.s6_addr, + tmp, 50); + if (str == NULL) { + strcpy(buffer, "inet_ntop failed\n"); + error = 1; + goto getaddr_done; + } + if (offset == 0) + strcpy(buffer, tmp); else - strcat(sn_str, cidr_mask); - strcat((char *)ip_buffer->sub_net, ";"); - sn_offset += strlen(sn_str) + 1; - } + strcat(buffer, tmp); + strcat(buffer, ";"); + offset += strlen(str) + 1; + if ((length - offset) < (ipv6_len + 1)) + goto getaddr_done; - /* - * Collect other ip related configuration info. - */ + } - kvp_get_ipconfig_info(if_name, ip_buffer); } - -gather_ipaddr: - error = kvp_process_ip_address(curp->ifa_addr, - curp->ifa_addr->sa_family, - buffer, - length, &offset); - if (error) - goto getaddr_done; - curp = curp->ifa_next; } @@ -1034,315 +579,6 @@ kvp_get_ip_info(int family, char *if_name, int op, } -static int expand_ipv6(char *addr, int type) -{ - int ret; - struct in6_addr v6_addr; - - ret = inet_pton(AF_INET6, addr, &v6_addr); - - if (ret != 1) { - if (type == NETMASK) - return 1; - return 0; - } - - sprintf(addr, "%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:" - "%02x%02x:%02x%02x:%02x%02x", - (int)v6_addr.s6_addr[0], (int)v6_addr.s6_addr[1], - (int)v6_addr.s6_addr[2], (int)v6_addr.s6_addr[3], - (int)v6_addr.s6_addr[4], (int)v6_addr.s6_addr[5], - (int)v6_addr.s6_addr[6], (int)v6_addr.s6_addr[7], - (int)v6_addr.s6_addr[8], (int)v6_addr.s6_addr[9], - (int)v6_addr.s6_addr[10], (int)v6_addr.s6_addr[11], - (int)v6_addr.s6_addr[12], (int)v6_addr.s6_addr[13], - (int)v6_addr.s6_addr[14], (int)v6_addr.s6_addr[15]); - - return 1; - -} - -static int is_ipv4(char *addr) -{ - int ret; - struct in_addr ipv4_addr; - - ret = inet_pton(AF_INET, addr, &ipv4_addr); - - if (ret == 1) - return 1; - return 0; -} - -static int parse_ip_val_buffer(char *in_buf, int *offset, - char *out_buf, int out_len) -{ - char *x; - char *start; - - /* - * in_buf has sequence of characters that are seperated by - * the character ';'. The last sequence does not have the - * terminating ";" character. - */ - start = in_buf + *offset; - - x = strchr(start, ';'); - if (x) - *x = 0; - else - x = start + strlen(start); - - if (strlen(start) != 0) { - int i = 0; - /* - * Get rid of leading spaces. - */ - while (start[i] == ' ') - i++; - - if ((x - start) <= out_len) { - strcpy(out_buf, (start + i)); - *offset += (x - start) + 1; - return 1; - } - } - return 0; -} - -static int kvp_write_file(FILE *f, char *s1, char *s2, char *s3) -{ - int ret; - - ret = fprintf(f, "%s%s%s%s\n", s1, s2, "=", s3); - - if (ret < 0) - return HV_E_FAIL; - - return 0; -} - - -static int process_ip_string(FILE *f, char *ip_string, int type) -{ - int error = 0; - char addr[INET6_ADDRSTRLEN]; - int i = 0; - int j = 0; - char str[256]; - char sub_str[10]; - int offset = 0; - - memset(addr, 0, sizeof(addr)); - - while (parse_ip_val_buffer(ip_string, &offset, addr, - (MAX_IP_ADDR_SIZE * 2))) { - - sub_str[0] = 0; - if (is_ipv4(addr)) { - switch (type) { - case IPADDR: - snprintf(str, sizeof(str), "%s", "IPADDR"); - break; - case NETMASK: - snprintf(str, sizeof(str), "%s", "NETMASK"); - break; - case GATEWAY: - snprintf(str, sizeof(str), "%s", "GATEWAY"); - break; - case DNS: - snprintf(str, sizeof(str), "%s", "DNS"); - break; - } - if (i != 0) { - if (type != DNS) { - snprintf(sub_str, sizeof(sub_str), - "_%d", i++); - } else { - snprintf(sub_str, sizeof(sub_str), - "%d", ++i); - } - } else if (type == DNS) { - snprintf(sub_str, sizeof(sub_str), "%d", ++i); - } - - - } else if (expand_ipv6(addr, type)) { - switch (type) { - case IPADDR: - snprintf(str, sizeof(str), "%s", "IPV6ADDR"); - break; - case NETMASK: - snprintf(str, sizeof(str), "%s", "IPV6NETMASK"); - break; - case GATEWAY: - snprintf(str, sizeof(str), "%s", - "IPV6_DEFAULTGW"); - break; - case DNS: - snprintf(str, sizeof(str), "%s", "DNS"); - break; - } - if ((j != 0) || (type == DNS)) { - if (type != DNS) { - snprintf(sub_str, sizeof(sub_str), - "_%d", j++); - } else { - snprintf(sub_str, sizeof(sub_str), - "%d", ++i); - } - } else if (type == DNS) { - snprintf(sub_str, sizeof(sub_str), - "%d", ++i); - } - } else { - return HV_INVALIDARG; - } - - error = kvp_write_file(f, str, sub_str, addr); - if (error) - return error; - memset(addr, 0, sizeof(addr)); - } - - return 0; -} - -static int kvp_set_ip_info(char *if_name, struct hv_kvp_ipaddr_value *new_val) -{ - int error = 0; - char if_file[128]; - FILE *file; - char cmd[512]; - char *mac_addr; - - /* - * Set the configuration for the specified interface with - * the information provided. Since there is no standard - * way to configure an interface, we will have an external - * script that does the job of configuring the interface and - * flushing the configuration. - * - * The parameters passed to this external script are: - * 1. A configuration file that has the specified configuration. - * - * We will embed the name of the interface in the configuration - * file: ifcfg-ethx (where ethx is the interface name). - * - * The information provided here may be more than what is needed - * in a given distro to configure the interface and so are free - * ignore information that may not be relevant. - * - * Here is the format of the ip configuration file: - * - * HWADDR=macaddr - * IF_NAME=interface name - * DHCP=yes (This is optional; if yes, DHCP is configured) - * - * IPADDR=ipaddr1 - * IPADDR_1=ipaddr2 - * IPADDR_x=ipaddry (where y = x + 1) - * - * NETMASK=netmask1 - * NETMASK_x=netmasky (where y = x + 1) - * - * GATEWAY=ipaddr1 - * GATEWAY_x=ipaddry (where y = x + 1) - * - * DNSx=ipaddrx (where first DNS address is tagged as DNS1 etc) - * - * IPV6 addresses will be tagged as IPV6ADDR, IPV6 gateway will be - * tagged as IPV6_DEFAULTGW and IPV6 NETMASK will be tagged as - * IPV6NETMASK. - * - * The host can specify multiple ipv4 and ipv6 addresses to be - * configured for the interface. Furthermore, the configuration - * needs to be persistent. A subsequent GET call on the interface - * is expected to return the configuration that is set via the SET - * call. - */ - - snprintf(if_file, sizeof(if_file), "%s%s%s", KVP_CONFIG_LOC, - "hyperv/ifcfg-", if_name); - - file = fopen(if_file, "w"); - - if (file == NULL) { - syslog(LOG_ERR, "Failed to open config file"); - return HV_E_FAIL; - } - - /* - * First write out the MAC address. - */ - - mac_addr = kvp_if_name_to_mac(if_name); - if (mac_addr == NULL) { - error = HV_E_FAIL; - goto setval_error; - } - - error = kvp_write_file(file, "HWADDR", "", mac_addr); - if (error) - goto setval_error; - - error = kvp_write_file(file, "IF_NAME", "", if_name); - if (error) - goto setval_error; - - if (new_val->dhcp_enabled) { - error = kvp_write_file(file, "DHCP", "", "yes"); - if (error) - goto setval_error; - - /* - * We are done!. - */ - goto setval_done; - } - - /* - * Write the configuration for ipaddress, netmask, gateway and - * name servers. - */ - - error = process_ip_string(file, (char *)new_val->ip_addr, IPADDR); - if (error) - goto setval_error; - - error = process_ip_string(file, (char *)new_val->sub_net, NETMASK); - if (error) - goto setval_error; - - error = process_ip_string(file, (char *)new_val->gate_way, GATEWAY); - if (error) - goto setval_error; - - error = process_ip_string(file, (char *)new_val->dns_addr, DNS); - if (error) - goto setval_error; - -setval_done: - free(mac_addr); - fclose(file); - - /* - * Now that we have populated the configuration file, - * invoke the external script to do its magic. - */ - - snprintf(cmd, sizeof(cmd), "%s %s", "hv_set_ifconfig", if_file); - system(cmd); - return 0; - -setval_error: - syslog(LOG_ERR, "Failed to write config file"); - free(mac_addr); - fclose(file); - return error; -} - - static int kvp_get_domain_name(char *buffer, int length) { @@ -1410,10 +646,6 @@ int main(void) char *p; char *key_value; char *key_name; - int op; - int pool; - char *if_name; - struct hv_kvp_ipaddr_value *kvp_ip_val; daemon(1, 0); openlog("KVP", 0, LOG_USER); @@ -1425,13 +657,13 @@ int main(void) if (kvp_file_init()) { syslog(LOG_ERR, "Failed to initialize the pools"); - exit(EXIT_FAILURE); + exit(-1); } fd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_CONNECTOR); if (fd < 0) { syslog(LOG_ERR, "netlink socket creation failed; error:%d", fd); - exit(EXIT_FAILURE); + exit(-1); } addr.nl_family = AF_NETLINK; addr.nl_pad = 0; @@ -1443,7 +675,7 @@ int main(void) if (error < 0) { syslog(LOG_ERR, "bind failed; error:%d", error); close(fd); - exit(EXIT_FAILURE); + exit(-1); } sock_opt = addr.nl_groups; setsockopt(fd, 270, 1, &sock_opt, sizeof(sock_opt)); @@ -1455,7 +687,7 @@ int main(void) message->id.val = CN_KVP_VAL; hv_msg = (struct hv_kvp_msg *)message->data; - hv_msg->kvp_hdr.operation = KVP_OP_REGISTER1; + hv_msg->kvp_hdr.operation = KVP_OP_REGISTER; message->ack = 0; message->len = sizeof(struct hv_kvp_msg); @@ -1463,7 +695,7 @@ int main(void) if (len < 0) { syslog(LOG_ERR, "netlink_send failed; error:%d", len); close(fd); - exit(EXIT_FAILURE); + exit(-1); } pfd.fd = fd; @@ -1489,21 +721,12 @@ int main(void) incoming_cn_msg = (struct cn_msg *)NLMSG_DATA(incoming_msg); hv_msg = (struct hv_kvp_msg *)incoming_cn_msg->data; - /* - * We will use the KVP header information to pass back - * the error from this daemon. So, first copy the state - * and set the error code to success. - */ - op = hv_msg->kvp_hdr.operation; - pool = hv_msg->kvp_hdr.pool; - hv_msg->error = HV_S_OK; - - if ((in_hand_shake) && (op == KVP_OP_REGISTER1)) { + switch (hv_msg->kvp_hdr.operation) { + case KVP_OP_REGISTER: /* * Driver is registering with us; stash away the version * information. */ - in_hand_shake = 0; p = (char *)hv_msg->body.kvp_register.version; lic_version = malloc(strlen(p) + 1); if (lic_version) { @@ -1514,82 +737,44 @@ int main(void) syslog(LOG_ERR, "malloc failed"); } continue; - } - switch (op) { - case KVP_OP_GET_IP_INFO: - kvp_ip_val = &hv_msg->body.kvp_ip_val; - if_name = - kvp_mac_to_if_name((char *)kvp_ip_val->adapter_id); - - if (if_name == NULL) { - /* - * We could not map the mac address to an - * interface name; return error. - */ - hv_msg->error = HV_E_FAIL; - break; - } - error = kvp_get_ip_info( - 0, if_name, KVP_OP_GET_IP_INFO, - kvp_ip_val, - (MAX_IP_ADDR_SIZE * 2)); - - if (error) - hv_msg->error = error; - - free(if_name); - break; - - case KVP_OP_SET_IP_INFO: - kvp_ip_val = &hv_msg->body.kvp_ip_val; - if_name = kvp_get_if_name( - (char *)kvp_ip_val->adapter_id); - if (if_name == NULL) { - /* - * We could not map the guid to an - * interface name; return error. - */ - hv_msg->error = HV_GUID_NOTFOUND; - break; - } - error = kvp_set_ip_info(if_name, kvp_ip_val); - if (error) - hv_msg->error = error; - - free(if_name); - break; + /* + * The current protocol with the kernel component uses a + * NULL key name to pass an error condition. + * For the SET, GET and DELETE operations, + * use the existing protocol to pass back error. + */ case KVP_OP_SET: - if (kvp_key_add_or_modify(pool, + if (kvp_key_add_or_modify(hv_msg->kvp_hdr.pool, hv_msg->body.kvp_set.data.key, hv_msg->body.kvp_set.data.key_size, hv_msg->body.kvp_set.data.value, hv_msg->body.kvp_set.data.value_size)) - hv_msg->error = HV_S_CONT; + strcpy(hv_msg->body.kvp_set.data.key, ""); break; case KVP_OP_GET: - if (kvp_get_value(pool, + if (kvp_get_value(hv_msg->kvp_hdr.pool, hv_msg->body.kvp_set.data.key, hv_msg->body.kvp_set.data.key_size, hv_msg->body.kvp_set.data.value, hv_msg->body.kvp_set.data.value_size)) - hv_msg->error = HV_S_CONT; + strcpy(hv_msg->body.kvp_set.data.key, ""); break; case KVP_OP_DELETE: - if (kvp_key_delete(pool, + if (kvp_key_delete(hv_msg->kvp_hdr.pool, hv_msg->body.kvp_delete.key, hv_msg->body.kvp_delete.key_size)) - hv_msg->error = HV_S_CONT; + strcpy(hv_msg->body.kvp_delete.key, ""); break; default: break; } - if (op != KVP_OP_ENUMERATE) + if (hv_msg->kvp_hdr.operation != KVP_OP_ENUMERATE) goto kvp_done; /* @@ -1597,14 +782,13 @@ int main(void) * both the key and the value; if not read from the * appropriate pool. */ - if (pool != KVP_POOL_AUTO) { - if (kvp_pool_enumerate(pool, + if (hv_msg->kvp_hdr.pool != KVP_POOL_AUTO) { + kvp_pool_enumerate(hv_msg->kvp_hdr.pool, hv_msg->body.kvp_enum_data.index, hv_msg->body.kvp_enum_data.data.key, HV_KVP_EXCHANGE_MAX_KEY_SIZE, hv_msg->body.kvp_enum_data.data.value, - HV_KVP_EXCHANGE_MAX_VALUE_SIZE)) - hv_msg->error = HV_S_CONT; + HV_KVP_EXCHANGE_MAX_VALUE_SIZE); goto kvp_done; } @@ -1623,13 +807,13 @@ int main(void) strcpy(key_value, lic_version); break; case NetworkAddressIPv4: - kvp_get_ip_info(AF_INET, NULL, KVP_OP_ENUMERATE, - key_value, HV_KVP_EXCHANGE_MAX_VALUE_SIZE); + kvp_get_ip_address(AF_INET, key_value, + HV_KVP_EXCHANGE_MAX_VALUE_SIZE); strcpy(key_name, "NetworkAddressIPv4"); break; case NetworkAddressIPv6: - kvp_get_ip_info(AF_INET6, NULL, KVP_OP_ENUMERATE, - key_value, HV_KVP_EXCHANGE_MAX_VALUE_SIZE); + kvp_get_ip_address(AF_INET6, key_value, + HV_KVP_EXCHANGE_MAX_VALUE_SIZE); strcpy(key_name, "NetworkAddressIPv6"); break; case OSBuildNumber: @@ -1657,7 +841,11 @@ int main(void) strcpy(key_name, "ProcessorArchitecture"); break; default: - hv_msg->error = HV_S_CONT; + strcpy(key_value, "Unknown Key"); + /* + * We use a null key name to terminate enumeration. + */ + strcpy(key_name, ""); break; } /* @@ -1675,7 +863,7 @@ int main(void) len = netlink_send(fd, incoming_cn_msg); if (len < 0) { syslog(LOG_ERR, "net_link send failed; error:%d", len); - exit(EXIT_FAILURE); + exit(-1); } } diff --git a/trunk/tools/hv/hv_set_ifconfig.sh b/trunk/tools/hv/hv_set_ifconfig.sh deleted file mode 100755 index 3e9427e08d80..000000000000 --- a/trunk/tools/hv/hv_set_ifconfig.sh +++ /dev/null @@ -1,68 +0,0 @@ -#!/bin/bash - -# This example script activates an interface based on the specified -# configuration. -# -# In the interest of keeping the KVP daemon code free of distro specific -# information; the kvp daemon code invokes this external script to configure -# the interface. -# -# The only argument to this script is the configuration file that is to -# be used to configure the interface. -# -# Each Distro is expected to implement this script in a distro specific -# fashion. For instance on Distros that ship with Network Manager enabled, -# this script can be based on the Network Manager APIs for configuring the -# interface. -# -# This example script is based on a RHEL environment. -# -# Here is the format of the ip configuration file: -# -# HWADDR=macaddr -# IF_NAME=interface name -# DHCP=yes (This is optional; if yes, DHCP is configured) -# -# IPADDR=ipaddr1 -# IPADDR_1=ipaddr2 -# IPADDR_x=ipaddry (where y = x + 1) -# -# NETMASK=netmask1 -# NETMASK_x=netmasky (where y = x + 1) -# -# GATEWAY=ipaddr1 -# GATEWAY_x=ipaddry (where y = x + 1) -# -# DNSx=ipaddrx (where first DNS address is tagged as DNS1 etc) -# -# IPV6 addresses will be tagged as IPV6ADDR, IPV6 gateway will be -# tagged as IPV6_DEFAULTGW and IPV6 NETMASK will be tagged as -# IPV6NETMASK. -# -# The host can specify multiple ipv4 and ipv6 addresses to be -# configured for the interface. Furthermore, the configuration -# needs to be persistent. A subsequent GET call on the interface -# is expected to return the configuration that is set via the SET -# call. -# - - - -echo "IPV6INIT=yes" >> $1 -echo "NM_CONTROLLED=no" >> $1 -echo "PEERDNS=yes" >> $1 -echo "ONBOOT=yes" >> $1 - -dhcp=$(grep "DHCP" $1 2>/dev/null) -if [ "$dhcp" != "" ]; -then -echo "BOOTPROTO=dhcp" >> $1; -fi - -cp $1 /etc/sysconfig/network-scripts/ - - -interface=$(echo $1 | awk -F - '{ print $2 }') - -/sbin/ifdown $interface 2>/dev/null -/sbin/ifup $interfac 2>/dev/null diff --git a/trunk/tools/lib/traceevent/Makefile b/trunk/tools/lib/traceevent/Makefile index 04d959fa0226..14131cb0522d 100644 --- a/trunk/tools/lib/traceevent/Makefile +++ b/trunk/tools/lib/traceevent/Makefile @@ -129,7 +129,7 @@ CFLAGS ?= -g -Wall # Append required CFLAGS override CFLAGS += $(CONFIG_FLAGS) $(INCLUDES) $(PLUGIN_DIR_SQ) -override CFLAGS += $(udis86-flags) -D_GNU_SOURCE +override CFLAGS += $(udis86-flags) ifeq ($(VERBOSE),1) Q = diff --git a/trunk/tools/lib/traceevent/event-parse.c b/trunk/tools/lib/traceevent/event-parse.c index 47264b4652b9..5f34aa371b56 100644 --- a/trunk/tools/lib/traceevent/event-parse.c +++ b/trunk/tools/lib/traceevent/event-parse.c @@ -24,14 +24,13 @@ * Frederic Weisbecker gave his permission to relicense the code to * the Lesser General Public License. */ +#define _GNU_SOURCE #include #include #include #include #include #include -#include -#include #include "event-parse.h" #include "event-utils.h" @@ -118,7 +117,14 @@ void breakpoint(void) struct print_arg *alloc_arg(void) { - return calloc(1, sizeof(struct print_arg)); + struct print_arg *arg; + + arg = malloc_or_die(sizeof(*arg)); + if (!arg) + return NULL; + memset(arg, 0, sizeof(*arg)); + + return arg; } struct cmdline { @@ -152,9 +158,7 @@ static int cmdline_init(struct pevent *pevent) struct cmdline *cmdlines; int i; - cmdlines = malloc(sizeof(*cmdlines) * pevent->cmdline_count); - if (!cmdlines) - return -1; + cmdlines = malloc_or_die(sizeof(*cmdlines) * pevent->cmdline_count); i = 0; while (cmdlist) { @@ -182,8 +186,8 @@ static char *find_cmdline(struct pevent *pevent, int pid) if (!pid) return ""; - if (!pevent->cmdlines && cmdline_init(pevent)) - return ""; + if (!pevent->cmdlines) + cmdline_init(pevent); key.pid = pid; @@ -211,8 +215,8 @@ int pevent_pid_is_registered(struct pevent *pevent, int pid) if (!pid) return 1; - if (!pevent->cmdlines && cmdline_init(pevent)) - return 0; + if (!pevent->cmdlines) + cmdline_init(pevent); key.pid = pid; @@ -254,14 +258,10 @@ static int add_new_comm(struct pevent *pevent, const char *comm, int pid) return -1; } - cmdlines[pevent->cmdline_count].comm = strdup(comm); - if (!cmdlines[pevent->cmdline_count].comm) { - free(cmdlines); - errno = ENOMEM; - return -1; - } - cmdlines[pevent->cmdline_count].pid = pid; + cmdlines[pevent->cmdline_count].comm = strdup(comm); + if (!cmdlines[pevent->cmdline_count].comm) + die("malloc comm"); if (cmdlines[pevent->cmdline_count].comm) pevent->cmdline_count++; @@ -288,15 +288,10 @@ int pevent_register_comm(struct pevent *pevent, const char *comm, int pid) if (pevent->cmdlines) return add_new_comm(pevent, comm, pid); - item = malloc(sizeof(*item)); - if (!item) - return -1; - + item = malloc_or_die(sizeof(*item)); item->comm = strdup(comm); - if (!item->comm) { - free(item); - return -1; - } + if (!item->comm) + die("malloc comm"); item->pid = pid; item->next = pevent->cmdlist; @@ -360,10 +355,7 @@ static int func_map_init(struct pevent *pevent) struct func_map *func_map; int i; - func_map = malloc(sizeof(*func_map) * (pevent->func_count + 1)); - if (!func_map) - return -1; - + func_map = malloc_or_die(sizeof(*func_map) * (pevent->func_count + 1)); funclist = pevent->funclist; i = 0; @@ -463,36 +455,25 @@ pevent_find_function_address(struct pevent *pevent, unsigned long long addr) int pevent_register_function(struct pevent *pevent, char *func, unsigned long long addr, char *mod) { - struct func_list *item = malloc(sizeof(*item)); + struct func_list *item; - if (!item) - return -1; + item = malloc_or_die(sizeof(*item)); item->next = pevent->funclist; item->func = strdup(func); - if (!item->func) - goto out_free; - - if (mod) { + if (mod) item->mod = strdup(mod); - if (!item->mod) - goto out_free_func; - } else + else item->mod = NULL; item->addr = addr; + if (!item->func || (mod && !item->mod)) + die("malloc func"); + pevent->funclist = item; pevent->func_count++; return 0; - -out_free_func: - free(item->func); - item->func = NULL; -out_free: - free(item); - errno = ENOMEM; - return -1; } /** @@ -543,16 +524,14 @@ static int printk_cmp(const void *a, const void *b) return 0; } -static int printk_map_init(struct pevent *pevent) +static void printk_map_init(struct pevent *pevent) { struct printk_list *printklist; struct printk_list *item; struct printk_map *printk_map; int i; - printk_map = malloc(sizeof(*printk_map) * (pevent->printk_count + 1)); - if (!printk_map) - return -1; + printk_map = malloc_or_die(sizeof(*printk_map) * (pevent->printk_count + 1)); printklist = pevent->printklist; @@ -570,8 +549,6 @@ static int printk_map_init(struct pevent *pevent) pevent->printk_map = printk_map; pevent->printklist = NULL; - - return 0; } static struct printk_map * @@ -580,8 +557,8 @@ find_printk(struct pevent *pevent, unsigned long long addr) struct printk_map *printk; struct printk_map key; - if (!pevent->printk_map && printk_map_init(pevent)) - return NULL; + if (!pevent->printk_map) + printk_map_init(pevent); key.addr = addr; @@ -603,27 +580,21 @@ find_printk(struct pevent *pevent, unsigned long long addr) int pevent_register_print_string(struct pevent *pevent, char *fmt, unsigned long long addr) { - struct printk_list *item = malloc(sizeof(*item)); + struct printk_list *item; - if (!item) - return -1; + item = malloc_or_die(sizeof(*item)); item->next = pevent->printklist; + item->printk = strdup(fmt); item->addr = addr; - item->printk = strdup(fmt); if (!item->printk) - goto out_free; + die("malloc fmt"); pevent->printklist = item; pevent->printk_count++; return 0; - -out_free: - free(item); - errno = ENOMEM; - return -1; } /** @@ -648,18 +619,24 @@ void pevent_print_printk(struct pevent *pevent) static struct event_format *alloc_event(void) { - return calloc(1, sizeof(struct event_format)); + struct event_format *event; + + event = malloc(sizeof(*event)); + if (!event) + return NULL; + memset(event, 0, sizeof(*event)); + + return event; } -static int add_event(struct pevent *pevent, struct event_format *event) +static void add_event(struct pevent *pevent, struct event_format *event) { int i; - struct event_format **events = realloc(pevent->events, sizeof(event) * - (pevent->nr_events + 1)); - if (!events) - return -1; - pevent->events = events; + pevent->events = realloc(pevent->events, sizeof(event) * + (pevent->nr_events + 1)); + if (!pevent->events) + die("Can not allocate events"); for (i = 0; i < pevent->nr_events; i++) { if (pevent->events[i]->id > event->id) @@ -674,8 +651,6 @@ static int add_event(struct pevent *pevent, struct event_format *event) pevent->nr_events++; event->pevent = pevent; - - return 0; } static int event_item_type(enum event_type type) @@ -852,9 +827,9 @@ static enum event_type __read_token(char **tok) switch (type) { case EVENT_NEWLINE: case EVENT_DELIM: - if (asprintf(tok, "%c", ch) < 0) - return EVENT_ERROR; - + *tok = malloc_or_die(2); + (*tok)[0] = ch; + (*tok)[1] = 0; return type; case EVENT_OP: @@ -1265,10 +1240,8 @@ static int event_read_fields(struct event_format *event, struct format_field **f last_token = token; - field = calloc(1, sizeof(*field)); - if (!field) - goto fail; - + field = malloc_or_die(sizeof(*field)); + memset(field, 0, sizeof(*field)); field->event = event; /* read the rest of the type */ @@ -1309,7 +1282,7 @@ static int event_read_fields(struct event_format *event, struct format_field **f } if (!field->type) { - do_warning("%s: no type found", __func__); + die("no type found"); goto fail; } field->name = last_token; @@ -1356,7 +1329,7 @@ static int event_read_fields(struct event_format *event, struct format_field **f free_token(token); type = read_token(&token); if (type == EVENT_NONE) { - do_warning("failed to find token"); + die("failed to find token"); goto fail; } } @@ -1565,14 +1538,6 @@ process_cond(struct event_format *event, struct print_arg *top, char **tok) left = alloc_arg(); right = alloc_arg(); - if (!arg || !left || !right) { - do_warning("%s: not enough memory!", __func__); - /* arg will be freed at out_free */ - free_arg(left); - free_arg(right); - goto out_free; - } - arg->type = PRINT_OP; arg->op.left = left; arg->op.right = right; @@ -1615,12 +1580,6 @@ process_array(struct event_format *event, struct print_arg *top, char **tok) char *token = NULL; arg = alloc_arg(); - if (!arg) { - do_warning("%s: not enough memory!", __func__); - /* '*tok' is set to top->op.op. No need to free. */ - *tok = NULL; - return EVENT_ERROR; - } *tok = NULL; type = process_arg(event, arg, &token); @@ -1636,7 +1595,8 @@ process_array(struct event_format *event, struct print_arg *top, char **tok) return type; out_free: - free_token(token); + free_token(*tok); + *tok = NULL; free_arg(arg); return EVENT_ERROR; } @@ -1722,7 +1682,7 @@ process_op(struct event_format *event, struct print_arg *arg, char **tok) if (arg->type == PRINT_OP && !arg->op.left) { /* handle single op */ if (token[1]) { - do_warning("bad op token %s", token); + die("bad op token %s", token); goto out_free; } switch (token[0]) { @@ -1739,16 +1699,10 @@ process_op(struct event_format *event, struct print_arg *arg, char **tok) /* make an empty left */ left = alloc_arg(); - if (!left) - goto out_warn_free; - left->type = PRINT_NULL; arg->op.left = left; right = alloc_arg(); - if (!right) - goto out_warn_free; - arg->op.right = right; /* do not free the token, it belongs to an op */ @@ -1758,9 +1712,6 @@ process_op(struct event_format *event, struct print_arg *arg, char **tok) } else if (strcmp(token, "?") == 0) { left = alloc_arg(); - if (!left) - goto out_warn_free; - /* copy the top arg to the left */ *left = *arg; @@ -1769,7 +1720,6 @@ process_op(struct event_format *event, struct print_arg *arg, char **tok) arg->op.left = left; arg->op.prio = 0; - /* it will set arg->op.right */ type = process_cond(event, arg, tok); } else if (strcmp(token, ">>") == 0 || @@ -1789,8 +1739,6 @@ process_op(struct event_format *event, struct print_arg *arg, char **tok) strcmp(token, "!=") == 0) { left = alloc_arg(); - if (!left) - goto out_warn_free; /* copy the top arg to the left */ *left = *arg; @@ -1798,7 +1746,6 @@ process_op(struct event_format *event, struct print_arg *arg, char **tok) arg->type = PRINT_OP; arg->op.op = token; arg->op.left = left; - arg->op.right = NULL; if (set_op_prio(arg) == -1) { event->flags |= EVENT_FL_FAILED; @@ -1815,14 +1762,12 @@ process_op(struct event_format *event, struct print_arg *arg, char **tok) type == EVENT_DELIM && (strcmp(token, ")") == 0)) { char *new_atom; - if (left->type != PRINT_ATOM) { - do_warning("bad pointer type"); - goto out_free; - } + if (left->type != PRINT_ATOM) + die("bad pointer type"); new_atom = realloc(left->atom.atom, strlen(left->atom.atom) + 3); if (!new_atom) - goto out_warn_free; + goto out_free; left->atom.atom = new_atom; strcat(left->atom.atom, " *"); @@ -1834,18 +1779,12 @@ process_op(struct event_format *event, struct print_arg *arg, char **tok) } right = alloc_arg(); - if (!right) - goto out_warn_free; - type = process_arg_token(event, right, tok, type); arg->op.right = right; } else if (strcmp(token, "[") == 0) { left = alloc_arg(); - if (!left) - goto out_warn_free; - *left = *arg; arg->type = PRINT_OP; @@ -1854,7 +1793,6 @@ process_op(struct event_format *event, struct print_arg *arg, char **tok) arg->op.prio = 0; - /* it will set arg->op.right */ type = process_array(event, arg, tok); } else { @@ -1878,16 +1816,14 @@ process_op(struct event_format *event, struct print_arg *arg, char **tok) return type; -out_warn_free: - do_warning("%s: not enough memory!", __func__); -out_free: + out_free: free_token(token); *tok = NULL; return EVENT_ERROR; } static enum event_type -process_entry(struct event_format *event __maybe_unused, struct print_arg *arg, +process_entry(struct event_format *event __unused, struct print_arg *arg, char **tok) { enum event_type type; @@ -1944,11 +1880,7 @@ eval_type_str(unsigned long long val, const char *type, int pointer) return val; } - ref = malloc(len); - if (!ref) { - do_warning("%s: not enough memory!", __func__); - return val; - } + ref = malloc_or_die(len); memcpy(ref, type, len); /* chop off the " *" */ @@ -2025,10 +1957,8 @@ eval_type_str(unsigned long long val, const char *type, int pointer) static unsigned long long eval_type(unsigned long long val, struct print_arg *arg, int pointer) { - if (arg->type != PRINT_TYPE) { - do_warning("expected type argument"); - return 0; - } + if (arg->type != PRINT_TYPE) + die("expected type argument"); return eval_type_str(val, arg->typecast.type, pointer); } @@ -2213,7 +2143,7 @@ static char *arg_eval (struct print_arg *arg) case PRINT_STRING: case PRINT_BSTRING: default: - do_warning("invalid eval type %d", arg->type); + die("invalid eval type %d", arg->type); break; } @@ -2236,8 +2166,6 @@ process_fields(struct event_format *event, struct print_flag_sym **list, char ** break; arg = alloc_arg(); - if (!arg) - goto out_free; free_token(token); type = process_arg(event, arg, &token); @@ -2251,33 +2179,30 @@ process_fields(struct event_format *event, struct print_flag_sym **list, char ** if (test_type_token(type, token, EVENT_DELIM, ",")) goto out_free; - field = calloc(1, sizeof(*field)); - if (!field) - goto out_free; + field = malloc_or_die(sizeof(*field)); + memset(field, 0, sizeof(*field)); value = arg_eval(arg); if (value == NULL) - goto out_free_field; + goto out_free; field->value = strdup(value); if (field->value == NULL) - goto out_free_field; + goto out_free; free_arg(arg); arg = alloc_arg(); - if (!arg) - goto out_free; free_token(token); type = process_arg(event, arg, &token); if (test_type_token(type, token, EVENT_OP, "}")) - goto out_free_field; + goto out_free; value = arg_eval(arg); if (value == NULL) - goto out_free_field; + goto out_free; field->str = strdup(value); if (field->str == NULL) - goto out_free_field; + goto out_free; free_arg(arg); arg = NULL; @@ -2291,8 +2216,6 @@ process_fields(struct event_format *event, struct print_flag_sym **list, char ** *tok = token; return type; -out_free_field: - free_flag_sym(field); out_free: free_arg(arg); free_token(token); @@ -2312,10 +2235,6 @@ process_flags(struct event_format *event, struct print_arg *arg, char **tok) arg->type = PRINT_FLAGS; field = alloc_arg(); - if (!field) { - do_warning("%s: not enough memory!", __func__); - goto out_free; - } type = process_arg(event, field, &token); @@ -2324,7 +2243,7 @@ process_flags(struct event_format *event, struct print_arg *arg, char **tok) type = process_op(event, field, &token); if (test_type_token(type, token, EVENT_DELIM, ",")) - goto out_free_field; + goto out_free; free_token(token); arg->flags.field = field; @@ -2346,9 +2265,7 @@ process_flags(struct event_format *event, struct print_arg *arg, char **tok) type = read_token_item(tok); return type; -out_free_field: - free_arg(field); -out_free: + out_free: free_token(token); *tok = NULL; return EVENT_ERROR; @@ -2365,14 +2282,10 @@ process_symbols(struct event_format *event, struct print_arg *arg, char **tok) arg->type = PRINT_SYMBOL; field = alloc_arg(); - if (!field) { - do_warning("%s: not enough memory!", __func__); - goto out_free; - } type = process_arg(event, field, &token); if (test_type_token(type, token, EVENT_DELIM, ",")) - goto out_free_field; + goto out_free; arg->symbol.field = field; @@ -2384,9 +2297,7 @@ process_symbols(struct event_format *event, struct print_arg *arg, char **tok) type = read_token_item(tok); return type; -out_free_field: - free_arg(field); -out_free: + out_free: free_token(token); *tok = NULL; return EVENT_ERROR; @@ -2403,11 +2314,6 @@ process_hex(struct event_format *event, struct print_arg *arg, char **tok) arg->type = PRINT_HEX; field = alloc_arg(); - if (!field) { - do_warning("%s: not enough memory!", __func__); - goto out_free; - } - type = process_arg(event, field, &token); if (test_type_token(type, token, EVENT_DELIM, ",")) @@ -2418,12 +2324,6 @@ process_hex(struct event_format *event, struct print_arg *arg, char **tok) free_token(token); field = alloc_arg(); - if (!field) { - do_warning("%s: not enough memory!", __func__); - *tok = NULL; - return EVENT_ERROR; - } - type = process_arg(event, field, &token); if (test_type_token(type, token, EVENT_DELIM, ")")) @@ -2481,12 +2381,6 @@ process_dynamic_array(struct event_format *event, struct print_arg *arg, char ** free_token(token); arg = alloc_arg(); - if (!field) { - do_warning("%s: not enough memory!", __func__); - *tok = NULL; - return EVENT_ERROR; - } - type = process_arg(event, arg, &token); if (type == EVENT_ERROR) goto out_free_arg; @@ -2540,16 +2434,10 @@ process_paren(struct event_format *event, struct print_arg *arg, char **tok) /* make this a typecast and contine */ /* prevous must be an atom */ - if (arg->type != PRINT_ATOM) { - do_warning("previous needed to be PRINT_ATOM"); - goto out_free; - } + if (arg->type != PRINT_ATOM) + die("previous needed to be PRINT_ATOM"); item_arg = alloc_arg(); - if (!item_arg) { - do_warning("%s: not enough memory!", __func__); - goto out_free; - } arg->type = PRINT_TYPE; arg->typecast.type = arg->atom.atom; @@ -2569,8 +2457,7 @@ process_paren(struct event_format *event, struct print_arg *arg, char **tok) static enum event_type -process_str(struct event_format *event __maybe_unused, struct print_arg *arg, - char **tok) +process_str(struct event_format *event __unused, struct print_arg *arg, char **tok) { enum event_type type; char *token; @@ -2645,11 +2532,6 @@ process_func_handler(struct event_format *event, struct pevent_function_handler next_arg = &(arg->func.args); for (i = 0; i < func->nr_args; i++) { farg = alloc_arg(); - if (!farg) { - do_warning("%s: not enough memory!", __func__); - return EVENT_ERROR; - } - type = process_arg(event, farg, &token); if (i < (func->nr_args - 1)) test = ","; @@ -2794,8 +2676,7 @@ process_arg_token(struct event_format *event, struct print_arg *arg, case EVENT_ERROR ... EVENT_NEWLINE: default: - do_warning("unexpected type %d", type); - return EVENT_ERROR; + die("unexpected type %d", type); } *tok = token; @@ -2816,10 +2697,6 @@ static int event_read_print_args(struct event_format *event, struct print_arg ** } arg = alloc_arg(); - if (!arg) { - do_warning("%s: not enough memory!", __func__); - return -1; - } type = process_arg(event, arg, &token); @@ -2891,8 +2768,10 @@ static int event_read_print(struct event_format *event) if (type == EVENT_DQUOTE) { char *cat; - if (asprintf(&cat, "%s%s", event->print_fmt.format, token) < 0) - goto fail; + cat = malloc_or_die(strlen(event->print_fmt.format) + + strlen(token) + 1); + strcpy(cat, event->print_fmt.format); + strcat(cat, token); free_token(token); free_token(event->print_fmt.format); event->print_fmt.format = NULL; @@ -3046,10 +2925,8 @@ static int get_common_info(struct pevent *pevent, * All events should have the same common elements. * Pick any event to find where the type is; */ - if (!pevent->events) { - do_warning("no event_list!"); - return -1; - } + if (!pevent->events) + die("no event_list!"); event = pevent->events[0]; field = pevent_find_common_field(event, type); @@ -3207,8 +3084,7 @@ eval_num_arg(void *data, int size, struct event_format *event, struct print_arg if (!arg->field.field) { arg->field.field = pevent_find_any_field(event, arg->field.name); if (!arg->field.field) - goto out_warning_field; - + die("field %s not found", arg->field.name); } /* must be a number */ val = pevent_read_number(pevent, data + arg->field.field->offset, @@ -3269,10 +3145,8 @@ eval_num_arg(void *data, int size, struct event_format *event, struct print_arg if (!larg->field.field) { larg->field.field = pevent_find_any_field(event, larg->field.name); - if (!larg->field.field) { - arg = larg; - goto out_warning_field; - } + if (!larg->field.field) + die("field %s not found", larg->field.name); } field_size = larg->field.field->elementsize; offset = larg->field.field->offset + @@ -3308,7 +3182,7 @@ eval_num_arg(void *data, int size, struct event_format *event, struct print_arg val = left != right; break; default: - goto out_warning_op; + die("unknown op '%s'", arg->op.op); } break; case '~': @@ -3338,7 +3212,7 @@ eval_num_arg(void *data, int size, struct event_format *event, struct print_arg val = left <= right; break; default: - goto out_warning_op; + die("unknown op '%s'", arg->op.op); } break; case '>': @@ -3353,13 +3227,12 @@ eval_num_arg(void *data, int size, struct event_format *event, struct print_arg val = left >= right; break; default: - goto out_warning_op; + die("unknown op '%s'", arg->op.op); } break; case '=': if (arg->op.op[1] != '=') - goto out_warning_op; - + die("unknown op '%s'", arg->op.op); val = left == right; break; case '-': @@ -3375,21 +3248,13 @@ eval_num_arg(void *data, int size, struct event_format *event, struct print_arg val = left * right; break; default: - goto out_warning_op; + die("unknown op '%s'", arg->op.op); } break; default: /* not sure what to do there */ return 0; } return val; - -out_warning_op: - do_warning("%s: unknown op '%s'", __func__, arg->op.op); - return 0; - -out_warning_field: - do_warning("%s: field %s not found", __func__, arg->field.name); - return 0; } struct flag { @@ -3466,10 +3331,8 @@ static void print_str_arg(struct trace_seq *s, void *data, int size, field = arg->field.field; if (!field) { field = pevent_find_any_field(event, arg->field.name); - if (!field) { - str = arg->field.name; - goto out_warning_field; - } + if (!field) + die("field %s not found", arg->field.name); arg->field.field = field; } /* Zero sized fields, mean the rest of the data */ @@ -3486,11 +3349,7 @@ static void print_str_arg(struct trace_seq *s, void *data, int size, trace_seq_printf(s, "%lx", addr); break; } - str = malloc(len + 1); - if (!str) { - do_warning("%s: not enough memory!", __func__); - return; - } + str = malloc_or_die(len + 1); memcpy(str, data + field->offset, len); str[len] = 0; print_str_to_seq(s, format, len_arg, str); @@ -3530,7 +3389,7 @@ static void print_str_arg(struct trace_seq *s, void *data, int size, str = arg->hex.field->field.name; field = pevent_find_any_field(event, str); if (!field) - goto out_warning_field; + die("field %s not found", str); arg->hex.field->field.field = field; } hex = data + field->offset; @@ -3582,11 +3441,6 @@ static void print_str_arg(struct trace_seq *s, void *data, int size, /* well... */ break; } - - return; - -out_warning_field: - do_warning("%s: field %s not found", __func__, arg->field.name); } static unsigned long long @@ -3613,11 +3467,7 @@ process_defined_func(struct trace_seq *s, void *data, int size, farg = arg->func.args; param = func_handle->params; - ret = ULLONG_MAX; - args = malloc(sizeof(*args) * func_handle->nr_args); - if (!args) - goto out; - + args = malloc_or_die(sizeof(*args) * func_handle->nr_args); for (i = 0; i < func_handle->nr_args; i++) { switch (param->type) { case PEVENT_FUNC_ARG_INT: @@ -3629,19 +3479,13 @@ process_defined_func(struct trace_seq *s, void *data, int size, trace_seq_init(&str); print_str_arg(&str, data, size, event, "%s", -1, farg); trace_seq_terminate(&str); - string = malloc(sizeof(*string)); - if (!string) { - do_warning("%s(%d): malloc str", __func__, __LINE__); - goto out_free; - } + string = malloc_or_die(sizeof(*string)); string->next = strings; string->str = strdup(str.buffer); - if (!string->str) { - free(string); - do_warning("%s(%d): malloc str", __func__, __LINE__); - goto out_free; - } - args[i] = (uintptr_t)string->str; + if (!string->str) + die("malloc str"); + + args[i] = (unsigned long long)string->str; strings = string; trace_seq_destroy(&str); break; @@ -3650,15 +3494,14 @@ process_defined_func(struct trace_seq *s, void *data, int size, * Something went totally wrong, this is not * an input error, something in this code broke. */ - do_warning("Unexpected end of arguments\n"); - goto out_free; + die("Unexpected end of arguments\n"); + break; } farg = farg->next; param = param->next; } ret = (*func_handle->func)(s, args); -out_free: free(args); while (strings) { string = strings; @@ -3672,18 +3515,6 @@ process_defined_func(struct trace_seq *s, void *data, int size, return ret; } -static void free_args(struct print_arg *args) -{ - struct print_arg *next; - - while (args) { - next = args->next; - - free_arg(args); - args = next; - } -} - static struct print_arg *make_bprint_args(char *fmt, void *data, int size, struct event_format *event) { struct pevent *pevent = event->pevent; @@ -3699,15 +3530,11 @@ static struct print_arg *make_bprint_args(char *fmt, void *data, int size, struc if (!field) { field = pevent_find_field(event, "buf"); - if (!field) { - do_warning("can't find buffer field for binary printk"); - return NULL; - } + if (!field) + die("can't find buffer field for binary printk"); ip_field = pevent_find_field(event, "ip"); - if (!ip_field) { - do_warning("can't find ip field for binary printk"); - return NULL; - } + if (!ip_field) + die("can't find ip field for binary printk"); pevent->bprint_buf_field = field; pevent->bprint_ip_field = ip_field; } @@ -3718,18 +3545,13 @@ static struct print_arg *make_bprint_args(char *fmt, void *data, int size, struc * The first arg is the IP pointer. */ args = alloc_arg(); - if (!args) { - do_warning("%s(%d): not enough memory!", __func__, __LINE__); - return NULL; - } arg = args; arg->next = NULL; next = &arg->next; arg->type = PRINT_ATOM; - - if (asprintf(&arg->atom.atom, "%lld", ip) < 0) - goto out_free; + arg->atom.atom = malloc_or_die(32); + sprintf(arg->atom.atom, "%lld", ip); /* skip the first "%pf : " */ for (ptr = fmt + 6, bptr = data + field->offset; @@ -3784,17 +3606,10 @@ static struct print_arg *make_bprint_args(char *fmt, void *data, int size, struc val = pevent_read_number(pevent, bptr, vsize); bptr += vsize; arg = alloc_arg(); - if (!arg) { - do_warning("%s(%d): not enough memory!", - __func__, __LINE__); - goto out_free; - } arg->next = NULL; arg->type = PRINT_ATOM; - if (asprintf(&arg->atom.atom, "%lld", val) < 0) { - free(arg); - goto out_free; - } + arg->atom.atom = malloc_or_die(32); + sprintf(arg->atom.atom, "%lld", val); *next = arg; next = &arg->next; /* @@ -3807,16 +3622,11 @@ static struct print_arg *make_bprint_args(char *fmt, void *data, int size, struc break; case 's': arg = alloc_arg(); - if (!arg) { - do_warning("%s(%d): not enough memory!", - __func__, __LINE__); - goto out_free; - } arg->next = NULL; arg->type = PRINT_BSTRING; arg->string.string = strdup(bptr); if (!arg->string.string) - goto out_free; + break; bptr += strlen(bptr) + 1; *next = arg; next = &arg->next; @@ -3827,15 +3637,22 @@ static struct print_arg *make_bprint_args(char *fmt, void *data, int size, struc } return args; +} -out_free: - free_args(args); - return NULL; +static void free_args(struct print_arg *args) +{ + struct print_arg *next; + + while (args) { + next = args->next; + + free_arg(args); + args = next; + } } static char * -get_bprint_format(void *data, int size __maybe_unused, - struct event_format *event) +get_bprint_format(void *data, int size __unused, struct event_format *event) { struct pevent *pevent = event->pevent; unsigned long long addr; @@ -3848,10 +3665,8 @@ get_bprint_format(void *data, int size __maybe_unused, if (!field) { field = pevent_find_field(event, "fmt"); - if (!field) { - do_warning("can't find format field for binary printk"); - return NULL; - } + if (!field) + die("can't find format field for binary printk"); pevent->bprint_fmt_field = field; } @@ -3859,8 +3674,9 @@ get_bprint_format(void *data, int size __maybe_unused, printk = find_printk(pevent, addr); if (!printk) { - if (asprintf(&format, "%%pf : (NO FORMAT FOUND at %llx)\n", addr) < 0) - return NULL; + format = malloc_or_die(45); + sprintf(format, "%%pf : (NO FORMAT FOUND at %llx)\n", + addr); return format; } @@ -3868,8 +3684,8 @@ get_bprint_format(void *data, int size __maybe_unused, /* Remove any quotes. */ if (*p == '"') p++; - if (asprintf(&format, "%s : %s", "%pf", p) < 0) - return NULL; + format = malloc_or_die(strlen(p) + 10); + sprintf(format, "%s : %s", "%pf", p); /* remove ending quotes and new line since we will add one too */ p = format + strlen(format) - 1; if (*p == '"') @@ -3904,11 +3720,8 @@ static void print_mac_arg(struct trace_seq *s, int mac, void *data, int size, if (!arg->field.field) { arg->field.field = pevent_find_any_field(event, arg->field.name); - if (!arg->field.field) { - do_warning("%s: field %s not found", - __func__, arg->field.name); - return; - } + if (!arg->field.field) + die("field %s not found", arg->field.name); } if (arg->field.field->size != 6) { trace_seq_printf(s, "INVALIDMAC"); @@ -4075,11 +3888,8 @@ static void pretty_print(struct trace_seq *s, void *data, int size, struct event goto cont_process; case '*': /* The argument is the length. */ - if (!arg) { - do_warning("no argument match"); - event->flags |= EVENT_FL_FAILED; - goto out_failed; - } + if (!arg) + die("no argument match"); len_arg = eval_num_arg(data, size, event, arg); len_as_arg = 1; arg = arg->next; @@ -4112,21 +3922,15 @@ static void pretty_print(struct trace_seq *s, void *data, int size, struct event case 'x': case 'X': case 'u': - if (!arg) { - do_warning("no argument match"); - event->flags |= EVENT_FL_FAILED; - goto out_failed; - } + if (!arg) + die("no argument match"); len = ((unsigned long)ptr + 1) - (unsigned long)saveptr; /* should never happen */ - if (len > 31) { - do_warning("bad format!"); - event->flags |= EVENT_FL_FAILED; - len = 31; - } + if (len > 31) + die("bad format!"); memcpy(format, saveptr, len); format[len] = 0; @@ -4190,26 +3994,19 @@ static void pretty_print(struct trace_seq *s, void *data, int size, struct event trace_seq_printf(s, format, (long long)val); break; default: - do_warning("bad count (%d)", ls); - event->flags |= EVENT_FL_FAILED; + die("bad count (%d)", ls); } break; case 's': - if (!arg) { - do_warning("no matching argument"); - event->flags |= EVENT_FL_FAILED; - goto out_failed; - } + if (!arg) + die("no matching argument"); len = ((unsigned long)ptr + 1) - (unsigned long)saveptr; /* should never happen */ - if (len > 31) { - do_warning("bad format!"); - event->flags |= EVENT_FL_FAILED; - len = 31; - } + if (len > 31) + die("bad format!"); memcpy(format, saveptr, len); format[len] = 0; @@ -4227,11 +4024,6 @@ static void pretty_print(struct trace_seq *s, void *data, int size, struct event trace_seq_putc(s, *ptr); } - if (event->flags & EVENT_FL_FAILED) { -out_failed: - trace_seq_printf(s, "[FAILED TO PARSE]"); - } - if (args) { free_args(args); free(bprint_fmt); @@ -4564,10 +4356,7 @@ get_event_fields(const char *type, const char *name, struct format_field *field; int i = 0; - fields = malloc(sizeof(*fields) * (count + 1)); - if (!fields) - return NULL; - + fields = malloc_or_die(sizeof(*fields) * (count + 1)); for (field = list; field; field = field->next) { fields[i++] = field; if (i == count + 1) { @@ -4883,7 +4672,8 @@ static int find_event_handle(struct pevent *pevent, struct event_format *event) } /** - * __pevent_parse_format - parse the event format + * pevent_parse_event - parse the event format + * @pevent: the handle to the pevent * @buf: the buffer storing the event format string * @size: the size of @buf * @sys: the system the event belongs to @@ -4895,27 +4685,28 @@ static int find_event_handle(struct pevent *pevent, struct event_format *event) * * /sys/kernel/debug/tracing/events/.../.../format */ -enum pevent_errno __pevent_parse_format(struct event_format **eventp, - struct pevent *pevent, const char *buf, - unsigned long size, const char *sys) +int pevent_parse_event(struct pevent *pevent, + const char *buf, unsigned long size, + const char *sys) { struct event_format *event; int ret; init_input_buf(buf, size); - *eventp = event = alloc_event(); + event = alloc_event(); if (!event) - return PEVENT_ERRNO__MEM_ALLOC_FAILED; + return -ENOMEM; event->name = event_read_name(); if (!event->name) { /* Bad event? */ - ret = PEVENT_ERRNO__MEM_ALLOC_FAILED; - goto event_alloc_failed; + free(event); + return -1; } if (strcmp(sys, "ftrace") == 0) { + event->flags |= EVENT_FL_ISFTRACE; if (strcmp(event->name, "bprint") == 0) @@ -4923,189 +4714,74 @@ enum pevent_errno __pevent_parse_format(struct event_format **eventp, } event->id = event_read_id(); - if (event->id < 0) { - ret = PEVENT_ERRNO__READ_ID_FAILED; - /* - * This isn't an allocation error actually. - * But as the ID is critical, just bail out. - */ - goto event_alloc_failed; - } + if (event->id < 0) + die("failed to read event id"); event->system = strdup(sys); - if (!event->system) { - ret = PEVENT_ERRNO__MEM_ALLOC_FAILED; - goto event_alloc_failed; - } + if (!event->system) + die("failed to allocate system"); + + /* Add pevent to event so that it can be referenced */ + event->pevent = pevent; ret = event_read_format(event); if (ret < 0) { - ret = PEVENT_ERRNO__READ_FORMAT_FAILED; - goto event_parse_failed; + do_warning("failed to read event format for %s", event->name); + goto event_failed; } /* * If the event has an override, don't print warnings if the event * print format fails to parse. */ - if (pevent && find_event_handle(pevent, event)) + if (find_event_handle(pevent, event)) show_warning = 0; ret = event_read_print(event); - show_warning = 1; - if (ret < 0) { - ret = PEVENT_ERRNO__READ_PRINT_FAILED; - goto event_parse_failed; + do_warning("failed to read event print fmt for %s", + event->name); + show_warning = 1; + goto event_failed; } + show_warning = 1; + + add_event(pevent, event); if (!ret && (event->flags & EVENT_FL_ISFTRACE)) { struct format_field *field; struct print_arg *arg, **list; /* old ftrace had no args */ + list = &event->print_fmt.args; for (field = event->format.fields; field; field = field->next) { arg = alloc_arg(); - if (!arg) { - event->flags |= EVENT_FL_FAILED; - return PEVENT_ERRNO__OLD_FTRACE_ARG_FAILED; - } + *list = arg; + list = &arg->next; arg->type = PRINT_FIELD; arg->field.name = strdup(field->name); if (!arg->field.name) { + do_warning("failed to allocate field name"); event->flags |= EVENT_FL_FAILED; - free_arg(arg); - return PEVENT_ERRNO__OLD_FTRACE_ARG_FAILED; + return -1; } arg->field.field = field; - *list = arg; - list = &arg->next; } return 0; } - return 0; - - event_parse_failed: - event->flags |= EVENT_FL_FAILED; - return ret; - - event_alloc_failed: - free(event->system); - free(event->name); - free(event); - *eventp = NULL; - return ret; -} - -/** - * pevent_parse_format - parse the event format - * @buf: the buffer storing the event format string - * @size: the size of @buf - * @sys: the system the event belongs to - * - * This parses the event format and creates an event structure - * to quickly parse raw data for a given event. - * - * These files currently come from: - * - * /sys/kernel/debug/tracing/events/.../.../format - */ -enum pevent_errno pevent_parse_format(struct event_format **eventp, const char *buf, - unsigned long size, const char *sys) -{ - return __pevent_parse_format(eventp, NULL, buf, size, sys); -} - -/** - * pevent_parse_event - parse the event format - * @pevent: the handle to the pevent - * @buf: the buffer storing the event format string - * @size: the size of @buf - * @sys: the system the event belongs to - * - * This parses the event format and creates an event structure - * to quickly parse raw data for a given event. - * - * These files currently come from: - * - * /sys/kernel/debug/tracing/events/.../.../format - */ -enum pevent_errno pevent_parse_event(struct pevent *pevent, const char *buf, - unsigned long size, const char *sys) -{ - struct event_format *event = NULL; - int ret = __pevent_parse_format(&event, pevent, buf, size, sys); - - if (event == NULL) - return ret; - - /* Add pevent to event so that it can be referenced */ - event->pevent = pevent; - - if (add_event(pevent, event)) { - ret = PEVENT_ERRNO__MEM_ALLOC_FAILED; - goto event_add_failed; - } - #define PRINT_ARGS 0 if (PRINT_ARGS && event->print_fmt.args) print_args(event->print_fmt.args); return 0; -event_add_failed: - pevent_free_format(event); - return ret; -} - -#undef _PE -#define _PE(code, str) str -static const char * const pevent_error_str[] = { - PEVENT_ERRORS -}; -#undef _PE - -int pevent_strerror(struct pevent *pevent, enum pevent_errno errnum, - char *buf, size_t buflen) -{ - int idx; - const char *msg; - - if (errnum >= 0) { - msg = strerror_r(errnum, buf, buflen); - if (msg != buf) { - size_t len = strlen(msg); - memcpy(buf, msg, min(buflen - 1, len)); - *(buf + min(buflen - 1, len)) = '\0'; - } - return 0; - } - - if (errnum <= __PEVENT_ERRNO__START || - errnum >= __PEVENT_ERRNO__END) - return -1; - - idx = errnum - __PEVENT_ERRNO__START - 1; - msg = pevent_error_str[idx]; - - switch (errnum) { - case PEVENT_ERRNO__MEM_ALLOC_FAILED: - case PEVENT_ERRNO__PARSE_EVENT_FAILED: - case PEVENT_ERRNO__READ_ID_FAILED: - case PEVENT_ERRNO__READ_FORMAT_FAILED: - case PEVENT_ERRNO__READ_PRINT_FAILED: - case PEVENT_ERRNO__OLD_FTRACE_ARG_FAILED: - snprintf(buf, buflen, "%s", msg); - break; - - default: - /* cannot reach here */ - break; - } - - return 0; + event_failed: + event->flags |= EVENT_FL_FAILED; + /* still add it even if it failed */ + add_event(pevent, event); + return -1; } int get_field_val(struct trace_seq *s, struct format_field *field, @@ -5324,7 +5000,6 @@ int pevent_register_print_function(struct pevent *pevent, struct pevent_func_params *param; enum pevent_func_arg_type type; va_list ap; - int ret; func_handle = find_func_handler(pevent, name); if (func_handle) { @@ -5337,20 +5012,14 @@ int pevent_register_print_function(struct pevent *pevent, remove_func_handler(pevent, name); } - func_handle = calloc(1, sizeof(*func_handle)); - if (!func_handle) { - do_warning("Failed to allocate function handler"); - return PEVENT_ERRNO__MEM_ALLOC_FAILED; - } + func_handle = malloc_or_die(sizeof(*func_handle)); + memset(func_handle, 0, sizeof(*func_handle)); func_handle->ret_type = ret_type; func_handle->name = strdup(name); func_handle->func = func; - if (!func_handle->name) { - do_warning("Failed to allocate function name"); - free(func_handle); - return PEVENT_ERRNO__MEM_ALLOC_FAILED; - } + if (!func_handle->name) + die("Failed to allocate function name"); next_param = &(func_handle->params); va_start(ap, name); @@ -5360,17 +5029,11 @@ int pevent_register_print_function(struct pevent *pevent, break; if (type < 0 || type >= PEVENT_FUNC_ARG_MAX_TYPES) { - do_warning("Invalid argument type %d", type); - ret = PEVENT_ERRNO__INVALID_ARG_TYPE; + warning("Invalid argument type %d", type); goto out_free; } - param = malloc(sizeof(*param)); - if (!param) { - do_warning("Failed to allocate function param"); - ret = PEVENT_ERRNO__MEM_ALLOC_FAILED; - goto out_free; - } + param = malloc_or_die(sizeof(*param)); param->type = type; param->next = NULL; @@ -5388,7 +5051,7 @@ int pevent_register_print_function(struct pevent *pevent, out_free: va_end(ap); free_func_handle(func_handle); - return ret; + return -1; } /** @@ -5440,12 +5103,8 @@ int pevent_register_event_handler(struct pevent *pevent, not_found: /* Save for later use. */ - handle = calloc(1, sizeof(*handle)); - if (!handle) { - do_warning("Failed to allocate event handler"); - return PEVENT_ERRNO__MEM_ALLOC_FAILED; - } - + handle = malloc_or_die(sizeof(*handle)); + memset(handle, 0, sizeof(*handle)); handle->id = id; if (event_name) handle->event_name = strdup(event_name); @@ -5454,11 +5113,7 @@ int pevent_register_event_handler(struct pevent *pevent, if ((event_name && !handle->event_name) || (sys_name && !handle->sys_name)) { - do_warning("Failed to allocate event/sys name"); - free((void *)handle->event_name); - free((void *)handle->sys_name); - free(handle); - return PEVENT_ERRNO__MEM_ALLOC_FAILED; + die("Failed to allocate event/sys name"); } handle->func = func; @@ -5474,10 +5129,13 @@ int pevent_register_event_handler(struct pevent *pevent, */ struct pevent *pevent_alloc(void) { - struct pevent *pevent = calloc(1, sizeof(*pevent)); + struct pevent *pevent; - if (pevent) - pevent->ref_count = 1; + pevent = malloc(sizeof(*pevent)); + if (!pevent) + return NULL; + memset(pevent, 0, sizeof(*pevent)); + pevent->ref_count = 1; return pevent; } @@ -5506,7 +5164,7 @@ static void free_formats(struct format *format) free_format_fields(format->fields); } -void pevent_free_format(struct event_format *event) +static void free_event(struct event_format *event) { free(event->name); free(event->system); @@ -5592,7 +5250,7 @@ void pevent_free(struct pevent *pevent) } for (i = 0; i < pevent->nr_events; i++) - pevent_free_format(pevent->events[i]); + free_event(pevent->events[i]); while (pevent->handlers) { handle = pevent->handlers; diff --git a/trunk/tools/lib/traceevent/event-parse.h b/trunk/tools/lib/traceevent/event-parse.h index 24a4bbabc5d5..5772ad8cb386 100644 --- a/trunk/tools/lib/traceevent/event-parse.h +++ b/trunk/tools/lib/traceevent/event-parse.h @@ -24,8 +24,8 @@ #include #include -#ifndef __maybe_unused -#define __maybe_unused __attribute__((unused)) +#ifndef __unused +#define __unused __attribute__ ((unused)) #endif /* ----------------------- trace_seq ----------------------- */ @@ -49,7 +49,7 @@ struct pevent_record { int cpu; int ref_count; int locked; /* Do not free, even if ref_count is zero */ - void *priv; + void *private; #if DEBUG_RECORD struct pevent_record *prev; struct pevent_record *next; @@ -106,7 +106,7 @@ struct plugin_option { char *plugin_alias; char *description; char *value; - void *priv; + void *private; int set; }; @@ -345,35 +345,6 @@ enum pevent_flag { PEVENT_NSEC_OUTPUT = 1, /* output in NSECS */ }; -#define PEVENT_ERRORS \ - _PE(MEM_ALLOC_FAILED, "failed to allocate memory"), \ - _PE(PARSE_EVENT_FAILED, "failed to parse event"), \ - _PE(READ_ID_FAILED, "failed to read event id"), \ - _PE(READ_FORMAT_FAILED, "failed to read event format"), \ - _PE(READ_PRINT_FAILED, "failed to read event print fmt"), \ - _PE(OLD_FTRACE_ARG_FAILED,"failed to allocate field name for ftrace"),\ - _PE(INVALID_ARG_TYPE, "invalid argument type") - -#undef _PE -#define _PE(__code, __str) PEVENT_ERRNO__ ## __code -enum pevent_errno { - PEVENT_ERRNO__SUCCESS = 0, - - /* - * Choose an arbitrary negative big number not to clash with standard - * errno since SUS requires the errno has distinct positive values. - * See 'Issue 6' in the link below. - * - * http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/errno.h.html - */ - __PEVENT_ERRNO__START = -100000, - - PEVENT_ERRORS, - - __PEVENT_ERRNO__END, -}; -#undef _PE - struct cmdline; struct cmdline_list; struct func_map; @@ -538,11 +509,8 @@ void pevent_print_event(struct pevent *pevent, struct trace_seq *s, int pevent_parse_header_page(struct pevent *pevent, char *buf, unsigned long size, int long_size); -enum pevent_errno pevent_parse_event(struct pevent *pevent, const char *buf, - unsigned long size, const char *sys); -enum pevent_errno pevent_parse_format(struct event_format **eventp, const char *buf, - unsigned long size, const char *sys); -void pevent_free_format(struct event_format *event); +int pevent_parse_event(struct pevent *pevent, const char *buf, + unsigned long size, const char *sys); void *pevent_get_field_raw(struct trace_seq *s, struct event_format *event, const char *name, struct pevent_record *record, @@ -593,8 +561,6 @@ int pevent_data_pid(struct pevent *pevent, struct pevent_record *rec); const char *pevent_data_comm_from_pid(struct pevent *pevent, int pid); void pevent_event_info(struct trace_seq *s, struct event_format *event, struct pevent_record *record); -int pevent_strerror(struct pevent *pevent, enum pevent_errno errnum, - char *buf, size_t buflen); struct event_format **pevent_list_events(struct pevent *pevent, enum event_sort_type); struct format_field **pevent_event_common_fields(struct event_format *event); diff --git a/trunk/tools/lib/traceevent/event-utils.h b/trunk/tools/lib/traceevent/event-utils.h index bc075006966e..08296383d1e6 100644 --- a/trunk/tools/lib/traceevent/event-utils.h +++ b/trunk/tools/lib/traceevent/event-utils.h @@ -39,12 +39,6 @@ void __vdie(const char *fmt, ...); void __vwarning(const char *fmt, ...); void __vpr_stat(const char *fmt, ...); -#define min(x, y) ({ \ - typeof(x) _min1 = (x); \ - typeof(y) _min2 = (y); \ - (void) (&_min1 == &_min2); \ - _min1 < _min2 ? _min1 : _min2; }) - static inline char *strim(char *string) { char *ret; diff --git a/trunk/tools/perf/.gitignore b/trunk/tools/perf/.gitignore index 8f8fbc227a46..26b823b61aa1 100644 --- a/trunk/tools/perf/.gitignore +++ b/trunk/tools/perf/.gitignore @@ -21,5 +21,3 @@ config.mak config.mak.autogen *-bison.* *-flex.* -*.pyc -*.pyo diff --git a/trunk/tools/perf/Documentation/Makefile b/trunk/tools/perf/Documentation/Makefile index 9f2e44f2b17a..ca600e09c8d4 100644 --- a/trunk/tools/perf/Documentation/Makefile +++ b/trunk/tools/perf/Documentation/Makefile @@ -195,10 +195,10 @@ install-pdf: pdf #install-html: html # '$(SHELL_PATH_SQ)' ./install-webdoc.sh $(DESTDIR)$(htmldir) -$(OUTPUT)PERF-VERSION-FILE: .FORCE-PERF-VERSION-FILE - $(QUIET_SUBDIR0)../ $(QUIET_SUBDIR1) $(OUTPUT)PERF-VERSION-FILE +../PERF-VERSION-FILE: .FORCE-PERF-VERSION-FILE + $(QUIET_SUBDIR0)../ $(QUIET_SUBDIR1) PERF-VERSION-FILE --include $(OUTPUT)PERF-VERSION-FILE +-include ../PERF-VERSION-FILE # # Determine "include::" file references in asciidoc files. diff --git a/trunk/tools/perf/Documentation/jit-interface.txt b/trunk/tools/perf/Documentation/jit-interface.txt deleted file mode 100644 index a8656f564915..000000000000 --- a/trunk/tools/perf/Documentation/jit-interface.txt +++ /dev/null @@ -1,15 +0,0 @@ -perf supports a simple JIT interface to resolve symbols for dynamic code generated -by a JIT. - -The JIT has to write a /tmp/perf-%d.map (%d = pid of process) file - -This is a text file. - -Each line has the following format, fields separated with spaces: - -START SIZE symbolname - -START and SIZE are hex numbers without 0x. -symbolname is the rest of the line, so it could contain special characters. - -The ownership of the file has to match the process. diff --git a/trunk/tools/perf/Documentation/perf-annotate.txt b/trunk/tools/perf/Documentation/perf-annotate.txt index c8ffd9fd5c6a..c89f9e1453f7 100644 --- a/trunk/tools/perf/Documentation/perf-annotate.txt +++ b/trunk/tools/perf/Documentation/perf-annotate.txt @@ -85,9 +85,6 @@ OPTIONS -M:: --disassembler-style=:: Set disassembler style for objdump. ---objdump=:: - Path to objdump binary. - SEE ALSO -------- linkperf:perf-record[1], linkperf:perf-report[1] diff --git a/trunk/tools/perf/Documentation/perf-diff.txt b/trunk/tools/perf/Documentation/perf-diff.txt index ab7f667de1b1..74d7481ed7a6 100644 --- a/trunk/tools/perf/Documentation/perf-diff.txt +++ b/trunk/tools/perf/Documentation/perf-diff.txt @@ -17,9 +17,6 @@ captured via perf record. If no parameters are passed it will assume perf.data.old and perf.data. -The differential profile is displayed only for events matching both -specified perf.data files. - OPTIONS ------- -M:: diff --git a/trunk/tools/perf/Documentation/perf-kvm.txt b/trunk/tools/perf/Documentation/perf-kvm.txt index 326f2cb333cb..dd84cb2f0a88 100644 --- a/trunk/tools/perf/Documentation/perf-kvm.txt +++ b/trunk/tools/perf/Documentation/perf-kvm.txt @@ -12,7 +12,7 @@ SYNOPSIS [--guestkallsyms= --guestmodules= | --guestvmlinux=]] {top|record|report|diff|buildid-list} 'perf kvm' [--host] [--guest] [--guestkallsyms= --guestmodules= - | --guestvmlinux=] {top|record|report|diff|buildid-list|stat} + | --guestvmlinux=] {top|record|report|diff|buildid-list} DESCRIPTION ----------- @@ -38,18 +38,6 @@ There are a couple of variants of perf kvm: so that other tools can be used to fetch packages with matching symbol tables for use by perf report. - 'perf kvm stat ' to run a command and gather performance counter - statistics. - Especially, perf 'kvm stat record/report' generates a statistical analysis - of KVM events. Currently, vmexit, mmio and ioport events are supported. - 'perf kvm stat record ' records kvm events and the events between - start and end . - And this command produces a file which contains tracing results of kvm - events. - - 'perf kvm stat report' reports statistical data which includes events - handled time, samples, and so on. - OPTIONS ------- -i:: @@ -80,21 +68,7 @@ OPTIONS --guestvmlinux=:: Guest os kernel vmlinux. -STAT REPORT OPTIONS -------------------- ---vcpu=:: - analyze events which occures on this vcpu. (default: all vcpus) - ---events=:: - events to be analyzed. Possible values: vmexit, mmio, ioport. - (default: vmexit) --k:: ---key=:: - Sorting key. Possible values: sample (default, sort by samples - number), time (sort by average time). - SEE ALSO -------- linkperf:perf-top[1], linkperf:perf-record[1], linkperf:perf-report[1], -linkperf:perf-diff[1], linkperf:perf-buildid-list[1], -linkperf:perf-stat[1] +linkperf:perf-diff[1], linkperf:perf-buildid-list[1] diff --git a/trunk/tools/perf/Documentation/perf-list.txt b/trunk/tools/perf/Documentation/perf-list.txt index d1e39dc8c810..ddc22525228d 100644 --- a/trunk/tools/perf/Documentation/perf-list.txt +++ b/trunk/tools/perf/Documentation/perf-list.txt @@ -15,43 +15,24 @@ DESCRIPTION This command displays the symbolic event types which can be selected in the various perf commands with the -e option. -[[EVENT_MODIFIERS]] EVENT MODIFIERS --------------- Events can optionally have a modifer by appending a colon and one or -more modifiers. Modifiers allow the user to restrict the events to be -counted. The following modifiers exist: - - u - user-space counting - k - kernel counting - h - hypervisor counting - G - guest counting (in KVM guests) - H - host counting (not in KVM guests) - p - precise level +more modifiers. Modifiers allow the user to restrict when events are +counted with 'u' for user-space, 'k' for kernel, 'h' for hypervisor. +Additional modifiers are 'G' for guest counting (in KVM guests) and 'H' +for host counting (not in KVM guests). The 'p' modifier can be used for specifying how precise the instruction -address should be. The 'p' modifier can be specified multiple times: - - 0 - SAMPLE_IP can have arbitrary skid - 1 - SAMPLE_IP must have constant skid - 2 - SAMPLE_IP requested to have 0 skid - 3 - SAMPLE_IP must have 0 skid - -For Intel systems precise event sampling is implemented with PEBS -which supports up to precise-level 2. +address should be. The 'p' modifier is currently only implemented for +Intel PEBS and can be specified multiple times: + 0 - SAMPLE_IP can have arbitrary skid + 1 - SAMPLE_IP must have constant skid + 2 - SAMPLE_IP requested to have 0 skid + 3 - SAMPLE_IP must have 0 skid -On AMD systems it is implemented using IBS (up to precise-level 2). -The precise modifier works with event types 0x76 (cpu-cycles, CPU -clocks not halted) and 0xC1 (micro-ops retired). Both events map to -IBS execution sampling (IBS op) with the IBS Op Counter Control bit -(IbsOpCntCtl) set respectively (see AMD64 Architecture Programmer’s -Manual Volume 2: System Programming, 13.3 Instruction-Based -Sampling). Examples to use IBS: - - perf record -a -e cpu-cycles:p ... # use ibs op counting cycles - perf record -a -e r076:p ... # same as -e cpu-cycles:p - perf record -a -e r0C1:p ... # use ibs op counting micro-ops +The PEBS implementation now supports up to 2. RAW HARDWARE EVENT DESCRIPTOR ----------------------------- @@ -63,11 +44,6 @@ layout of IA32_PERFEVTSELx MSRs (see [Intel® 64 and IA-32 Architectures Softwar of IA32_PERFEVTSELx MSRs) or AMD's PerfEvtSeln (see [AMD64 Architecture Programmer’s Manual Volume 2: System Programming], Page 344, Figure 13-7 Performance Event-Select Register (PerfEvtSeln)). -Note: Only the following bit fields can be set in x86 counter -registers: event, umask, edge, inv, cmask. Esp. guest/host only and -OS/user mode flags must be setup using <>. - Example: If the Intel docs for a QM720 Core i7 describe an event as: @@ -115,4 +91,4 @@ SEE ALSO linkperf:perf-stat[1], linkperf:perf-top[1], linkperf:perf-record[1], http://www.intel.com/Assets/PDF/manual/253669.pdf[Intel® 64 and IA-32 Architectures Software Developer's Manual Volume 3B: System Programming Guide], -http://support.amd.com/us/Processor_TechDocs/24593_APM_v2.pdf[AMD64 Architecture Programmer’s Manual Volume 2: System Programming] +http://support.amd.com/us/Processor_TechDocs/24593.pdf[AMD64 Architecture Programmer’s Manual Volume 2: System Programming] diff --git a/trunk/tools/perf/Documentation/perf-report.txt b/trunk/tools/perf/Documentation/perf-report.txt index f4d91bebd59d..495210a612c4 100644 --- a/trunk/tools/perf/Documentation/perf-report.txt +++ b/trunk/tools/perf/Documentation/perf-report.txt @@ -168,9 +168,6 @@ OPTIONS branch stacks and it will automatically switch to the branch view mode, unless --no-branch-stack is used. ---objdump=:: - Path to objdump binary. - SEE ALSO -------- linkperf:perf-stat[1], linkperf:perf-annotate[1] diff --git a/trunk/tools/perf/Documentation/perf-script-perl.txt b/trunk/tools/perf/Documentation/perf-script-perl.txt index d00bef231340..3152cca15501 100644 --- a/trunk/tools/perf/Documentation/perf-script-perl.txt +++ b/trunk/tools/perf/Documentation/perf-script-perl.txt @@ -116,8 +116,8 @@ search path and 'use'ing a few support modules (see module descriptions below): ---- - use lib "$ENV{'PERF_EXEC_PATH'}/scripts/perl/Perf-Trace-Util/lib"; - use lib "./Perf-Trace-Util/lib"; + use lib "$ENV{'PERF_EXEC_PATH'}/scripts/perl/perf-script-Util/lib"; + use lib "./perf-script-Util/lib"; use Perf::Trace::Core; use Perf::Trace::Context; use Perf::Trace::Util; diff --git a/trunk/tools/perf/Documentation/perf-script-python.txt b/trunk/tools/perf/Documentation/perf-script-python.txt index a4027f221a53..471022069119 100644 --- a/trunk/tools/perf/Documentation/perf-script-python.txt +++ b/trunk/tools/perf/Documentation/perf-script-python.txt @@ -129,7 +129,7 @@ import os import sys sys.path.append(os.environ['PERF_EXEC_PATH'] + \ - '/scripts/python/Perf-Trace-Util/lib/Perf/Trace') + '/scripts/python/perf-script-Util/lib/Perf/Trace') from perf_trace_context import * from Core import * @@ -216,7 +216,7 @@ import os import sys sys.path.append(os.environ['PERF_EXEC_PATH'] + \ - '/scripts/python/Perf-Trace-Util/lib/Perf/Trace') + '/scripts/python/perf-script-Util/lib/Perf/Trace') from perf_trace_context import * from Core import * @@ -279,7 +279,7 @@ import os import sys sys.path.append(os.environ['PERF_EXEC_PATH'] + \ - '/scripts/python/Perf-Trace-Util/lib/Perf/Trace') + '/scripts/python/perf-script-Util/lib/Perf/Trace') from perf_trace_context import * from Core import * @@ -391,7 +391,7 @@ drwxr-xr-x 4 trz trz 4096 2010-01-26 22:30 . drwxr-xr-x 4 trz trz 4096 2010-01-26 22:29 .. drwxr-xr-x 2 trz trz 4096 2010-01-26 22:29 bin -rw-r--r-- 1 trz trz 2548 2010-01-26 22:29 check-perf-script.py -drwxr-xr-x 3 trz trz 4096 2010-01-26 22:49 Perf-Trace-Util +drwxr-xr-x 3 trz trz 4096 2010-01-26 22:49 perf-script-Util -rw-r--r-- 1 trz trz 1462 2010-01-26 22:30 syscall-counts.py ---- @@ -518,7 +518,7 @@ descriptions below): import sys sys.path.append(os.environ['PERF_EXEC_PATH'] + \ - '/scripts/python/Perf-Trace-Util/lib/Perf/Trace') + '/scripts/python/perf-script-Util/lib/Perf/Trace') from perf_trace_context import * from Core import * diff --git a/trunk/tools/perf/Documentation/perf-trace.txt b/trunk/tools/perf/Documentation/perf-trace.txt deleted file mode 100644 index 3a2ae37310a9..000000000000 --- a/trunk/tools/perf/Documentation/perf-trace.txt +++ /dev/null @@ -1,53 +0,0 @@ -perf-trace(1) -============= - -NAME ----- -perf-trace - strace inspired tool - -SYNOPSIS --------- -[verse] -'perf trace' - -DESCRIPTION ------------ -This command will show the events associated with the target, initially -syscalls, but other system events like pagefaults, task lifetime events, -scheduling events, etc. - -Initially this is a live mode only tool, but eventually will work with -perf.data files like the other tools, allowing a detached 'record' from -analysis phases. - -OPTIONS -------- - ---all-cpus:: - System-wide collection from all CPUs. - --p:: ---pid=:: - Record events on existing process ID (comma separated list). - ---tid=:: - Record events on existing thread ID (comma separated list). - ---uid=:: - Record events in threads owned by uid. Name or number. - ---no-inherit:: - Child tasks do not inherit counters. - ---mmap-pages=:: - Number of mmap data pages. Must be a power of two. - ---cpu:: -Collect samples only on the list of CPUs provided. Multiple CPUs can be provided as a -comma-separated list with no space: 0,1. Ranges of CPUs are specified with -: 0-2. -In per-thread mode with inheritance mode on (default), Events are captured only when -the thread executes on the designated CPUs. Default is to monitor all CPUs. - -SEE ALSO --------- -linkperf:perf-record[1], linkperf:perf-script[1] diff --git a/trunk/tools/perf/MANIFEST b/trunk/tools/perf/MANIFEST index 80db3f4bcf7a..b4b572e8c100 100644 --- a/trunk/tools/perf/MANIFEST +++ b/trunk/tools/perf/MANIFEST @@ -10,12 +10,8 @@ include/linux/stringify.h lib/rbtree.c include/linux/swab.h arch/*/include/asm/unistd*.h -arch/*/include/asm/perf_regs.h arch/*/lib/memcpy*.S arch/*/lib/memset*.S include/linux/poison.h include/linux/magic.h include/linux/hw_breakpoint.h -arch/x86/include/asm/svm.h -arch/x86/include/asm/vmx.h -arch/x86/include/asm/kvm_host.h diff --git a/trunk/tools/perf/Makefile b/trunk/tools/perf/Makefile index e5e71e7d95a0..77f124fe57ad 100644 --- a/trunk/tools/perf/Makefile +++ b/trunk/tools/perf/Makefile @@ -37,14 +37,7 @@ include config/utilities.mak # # Define NO_NEWT if you do not want TUI support. # -# Define NO_GTK2 if you do not want GTK+ GUI support. -# # Define NO_DEMANGLE if you do not want C++ symbol demangling. -# -# Define NO_LIBELF if you do not want libelf dependency (e.g. cross-builds) -# -# Define NO_LIBUNWIND if you do not want libunwind dependency for dwarf -# backtrace post unwind. $(OUTPUT)PERF-VERSION-FILE: .FORCE-PERF-VERSION-FILE @$(SHELL_PATH) util/PERF-VERSION-GEN $(OUTPUT) @@ -57,19 +50,16 @@ ARCH ?= $(shell echo $(uname_M) | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ \ -e s/s390x/s390/ -e s/parisc64/parisc/ \ -e s/ppc.*/powerpc/ -e s/mips.*/mips/ \ -e s/sh[234].*/sh/ ) -NO_PERF_REGS := 1 CC = $(CROSS_COMPILE)gcc AR = $(CROSS_COMPILE)ar # Additional ARCH settings for x86 ifeq ($(ARCH),i386) - override ARCH := x86 - NO_PERF_REGS := 0 - LIBUNWIND_LIBS = -lunwind -lunwind-x86 + ARCH := x86 endif ifeq ($(ARCH),x86_64) - override ARCH := x86 + ARCH := x86 IS_X86_64 := 0 ifeq (, $(findstring m32,$(EXTRA_CFLAGS))) IS_X86_64 := $(shell echo __x86_64__ | ${CC} -E -xc - | tail -n 1) @@ -79,8 +69,6 @@ ifeq ($(ARCH),x86_64) ARCH_CFLAGS := -DARCH_X86_64 ARCH_INCLUDE = ../../arch/x86/lib/memcpy_64.S ../../arch/x86/lib/memset_64.S endif - NO_PERF_REGS := 0 - LIBUNWIND_LIBS = -lunwind -lunwind-x86_64 endif # Treat warnings as errors unless directed not to @@ -101,7 +89,7 @@ ifdef PARSER_DEBUG PARSER_DEBUG_CFLAGS := -DPARSER_DEBUG endif -CFLAGS = -fno-omit-frame-pointer -ggdb3 -funwind-tables -Wall -Wextra -std=gnu99 $(CFLAGS_WERROR) $(CFLAGS_OPTIMIZE) $(EXTRA_WARNINGS) $(EXTRA_CFLAGS) $(PARSER_DEBUG_CFLAGS) +CFLAGS = -fno-omit-frame-pointer -ggdb3 -Wall -Wextra -std=gnu99 $(CFLAGS_WERROR) $(CFLAGS_OPTIMIZE) $(EXTRA_WARNINGS) $(EXTRA_CFLAGS) $(PARSER_DEBUG_CFLAGS) EXTLIBS = -lpthread -lrt -lelf -lm ALL_CFLAGS = $(CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE ALL_LDFLAGS = $(LDFLAGS) @@ -198,10 +186,10 @@ SCRIPTS = $(patsubst %.sh,%,$(SCRIPT_SH)) TRACE_EVENT_DIR = ../lib/traceevent/ -ifneq ($(OUTPUT),) - TE_PATH=$(OUTPUT) +ifeq ("$(origin O)", "command line") + TE_PATH=$(OUTPUT)/ else - TE_PATH=$(TRACE_EVENT_DIR) + TE_PATH=$(TRACE_EVENT_DIR)/ endif LIBTRACEEVENT = $(TE_PATH)libtraceevent.a @@ -233,13 +221,13 @@ export PERL_PATH FLEX = flex BISON= bison -$(OUTPUT)util/parse-events-flex.c: util/parse-events.l $(OUTPUT)util/parse-events-bison.c +$(OUTPUT)util/parse-events-flex.c: util/parse-events.l $(QUIET_FLEX)$(FLEX) --header-file=$(OUTPUT)util/parse-events-flex.h $(PARSER_DEBUG_FLEX) -t util/parse-events.l > $(OUTPUT)util/parse-events-flex.c $(OUTPUT)util/parse-events-bison.c: util/parse-events.y $(QUIET_BISON)$(BISON) -v util/parse-events.y -d $(PARSER_DEBUG_BISON) -o $(OUTPUT)util/parse-events-bison.c -$(OUTPUT)util/pmu-flex.c: util/pmu.l $(OUTPUT)util/pmu-bison.c +$(OUTPUT)util/pmu-flex.c: util/pmu.l $(QUIET_FLEX)$(FLEX) --header-file=$(OUTPUT)util/pmu-flex.h -t util/pmu.l > $(OUTPUT)util/pmu-flex.c $(OUTPUT)util/pmu-bison.c: util/pmu.y @@ -264,7 +252,6 @@ LIB_H += util/include/linux/ctype.h LIB_H += util/include/linux/kernel.h LIB_H += util/include/linux/list.h LIB_H += util/include/linux/export.h -LIB_H += util/include/linux/magic.h LIB_H += util/include/linux/poison.h LIB_H += util/include/linux/prefetch.h LIB_H += util/include/linux/rbtree.h @@ -332,12 +319,6 @@ LIB_H += $(ARCH_INCLUDE) LIB_H += util/cgroup.h LIB_H += $(TRACE_EVENT_DIR)event-parse.h LIB_H += util/target.h -LIB_H += util/rblist.h -LIB_H += util/intlist.h -LIB_H += util/perf_regs.h -LIB_H += util/unwind.h -LIB_H += ui/helpline.h -LIB_H += util/vdso.h LIB_OBJS += $(OUTPUT)util/abspath.o LIB_OBJS += $(OUTPUT)util/alias.o @@ -373,7 +354,6 @@ LIB_OBJS += $(OUTPUT)util/usage.o LIB_OBJS += $(OUTPUT)util/wrapper.o LIB_OBJS += $(OUTPUT)util/sigchain.o LIB_OBJS += $(OUTPUT)util/symbol.o -LIB_OBJS += $(OUTPUT)util/symbol-elf.o LIB_OBJS += $(OUTPUT)util/dso-test-data.o LIB_OBJS += $(OUTPUT)util/color.o LIB_OBJS += $(OUTPUT)util/pager.o @@ -403,17 +383,11 @@ LIB_OBJS += $(OUTPUT)util/xyarray.o LIB_OBJS += $(OUTPUT)util/cpumap.o LIB_OBJS += $(OUTPUT)util/cgroup.o LIB_OBJS += $(OUTPUT)util/target.o -LIB_OBJS += $(OUTPUT)util/rblist.o -LIB_OBJS += $(OUTPUT)util/intlist.o -LIB_OBJS += $(OUTPUT)util/vdso.o -LIB_OBJS += $(OUTPUT)util/stat.o - -LIB_OBJS += $(OUTPUT)ui/helpline.o -LIB_OBJS += $(OUTPUT)ui/hist.o -LIB_OBJS += $(OUTPUT)ui/stdio/hist.o BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o + BUILTIN_OBJS += $(OUTPUT)builtin-bench.o + # Benchmark modules BUILTIN_OBJS += $(OUTPUT)bench/sched-messaging.o BUILTIN_OBJS += $(OUTPUT)bench/sched-pipe.o @@ -471,73 +445,34 @@ PYRF_OBJS += $(OUTPUT)util/xyarray.o -include config.mak.autogen -include config.mak -ifdef NO_LIBELF +ifndef NO_DWARF +FLAGS_DWARF=$(ALL_CFLAGS) -ldw -lelf $(ALL_LDFLAGS) $(EXTLIBS) +ifneq ($(call try-cc,$(SOURCE_DWARF),$(FLAGS_DWARF)),y) + msg := $(warning No libdw.h found or old libdw.h found or elfutils is older than 0.138, disables dwarf support. Please install new elfutils-devel/libdw-dev); NO_DWARF := 1 - NO_DEMANGLE := 1 - NO_LIBUNWIND := 1 -else +endif # Dwarf support +endif # NO_DWARF + +-include arch/$(ARCH)/Makefile + +ifneq ($(OUTPUT),) + BASIC_CFLAGS += -I$(OUTPUT) +endif + FLAGS_LIBELF=$(ALL_CFLAGS) $(ALL_LDFLAGS) $(EXTLIBS) ifneq ($(call try-cc,$(SOURCE_LIBELF),$(FLAGS_LIBELF)),y) FLAGS_GLIBC=$(ALL_CFLAGS) $(ALL_LDFLAGS) ifneq ($(call try-cc,$(SOURCE_GLIBC),$(FLAGS_GLIBC)),y) msg := $(error No gnu/libc-version.h found, please install glibc-dev[el]/glibc-static); else - NO_LIBELF := 1 - NO_DWARF := 1 - NO_DEMANGLE := 1 + msg := $(error No libelf.h/libelf found, please install libelf-dev/elfutils-libelf-devel); endif endif -endif # NO_LIBELF - -ifndef NO_LIBUNWIND -# for linking with debug library, run like: -# make DEBUG=1 LIBUNWIND_DIR=/opt/libunwind/ -ifdef LIBUNWIND_DIR - LIBUNWIND_CFLAGS := -I$(LIBUNWIND_DIR)/include - LIBUNWIND_LDFLAGS := -L$(LIBUNWIND_DIR)/lib -endif - -FLAGS_UNWIND=$(LIBUNWIND_CFLAGS) $(ALL_CFLAGS) $(LIBUNWIND_LDFLAGS) $(ALL_LDFLAGS) $(EXTLIBS) $(LIBUNWIND_LIBS) -ifneq ($(call try-cc,$(SOURCE_LIBUNWIND),$(FLAGS_UNWIND)),y) - msg := $(warning No libunwind found, disabling post unwind support. Please install libunwind-dev[el] >= 0.99); - NO_LIBUNWIND := 1 -endif # Libunwind support -endif # NO_LIBUNWIND - --include arch/$(ARCH)/Makefile - -ifneq ($(OUTPUT),) - BASIC_CFLAGS += -I$(OUTPUT) -endif - -ifdef NO_LIBELF -BASIC_CFLAGS += -DNO_LIBELF_SUPPORT - -EXTLIBS := $(filter-out -lelf,$(EXTLIBS)) - -# Remove ELF/DWARF dependent codes -LIB_OBJS := $(filter-out $(OUTPUT)util/symbol-elf.o,$(LIB_OBJS)) -LIB_OBJS := $(filter-out $(OUTPUT)util/dwarf-aux.o,$(LIB_OBJS)) -LIB_OBJS := $(filter-out $(OUTPUT)util/probe-event.o,$(LIB_OBJS)) -LIB_OBJS := $(filter-out $(OUTPUT)util/probe-finder.o,$(LIB_OBJS)) - -BUILTIN_OBJS := $(filter-out $(OUTPUT)builtin-probe.o,$(BUILTIN_OBJS)) - -# Use minimal symbol handling -LIB_OBJS += $(OUTPUT)util/symbol-minimal.o - -else # NO_LIBELF ifneq ($(call try-cc,$(SOURCE_ELF_MMAP),$(FLAGS_COMMON)),y) BASIC_CFLAGS += -DLIBELF_NO_MMAP endif -FLAGS_DWARF=$(ALL_CFLAGS) -ldw -lelf $(ALL_LDFLAGS) $(EXTLIBS) -ifneq ($(call try-cc,$(SOURCE_DWARF),$(FLAGS_DWARF)),y) - msg := $(warning No libdw.h found or old libdw.h found or elfutils is older than 0.138, disables dwarf support. Please install new elfutils-devel/libdw-dev); - NO_DWARF := 1 -endif # Dwarf support - ifndef NO_DWARF ifeq ($(origin PERF_HAVE_DWARF_REGS), undefined) msg := $(warning DWARF register mappings have not been defined for architecture $(ARCH), DWARF support disabled); @@ -548,29 +483,6 @@ else LIB_OBJS += $(OUTPUT)util/dwarf-aux.o endif # PERF_HAVE_DWARF_REGS endif # NO_DWARF -endif # NO_LIBELF - -ifdef NO_LIBUNWIND - BASIC_CFLAGS += -DNO_LIBUNWIND_SUPPORT -else - EXTLIBS += $(LIBUNWIND_LIBS) - BASIC_CFLAGS := $(LIBUNWIND_CFLAGS) $(BASIC_CFLAGS) - BASIC_LDFLAGS := $(LIBUNWIND_LDFLAGS) $(BASIC_LDFLAGS) - LIB_OBJS += $(OUTPUT)util/unwind.o -endif - -ifdef NO_LIBAUDIT - BASIC_CFLAGS += -DNO_LIBAUDIT_SUPPORT -else - FLAGS_LIBAUDIT = $(ALL_CFLAGS) $(ALL_LDFLAGS) -laudit - ifneq ($(call try-cc,$(SOURCE_LIBAUDIT),$(FLAGS_LIBAUDIT)),y) - msg := $(warning No libaudit.h found, disables 'trace' tool, please install audit-libs-devel or libaudit-dev); - BASIC_CFLAGS += -DNO_LIBAUDIT_SUPPORT - else - BUILTIN_OBJS += $(OUTPUT)builtin-trace.o - EXTLIBS += -laudit - endif -endif ifdef NO_NEWT BASIC_CFLAGS += -DNO_NEWT_SUPPORT @@ -588,13 +500,14 @@ else LIB_OBJS += $(OUTPUT)ui/browsers/annotate.o LIB_OBJS += $(OUTPUT)ui/browsers/hists.o LIB_OBJS += $(OUTPUT)ui/browsers/map.o + LIB_OBJS += $(OUTPUT)ui/helpline.o LIB_OBJS += $(OUTPUT)ui/progress.o LIB_OBJS += $(OUTPUT)ui/util.o LIB_OBJS += $(OUTPUT)ui/tui/setup.o LIB_OBJS += $(OUTPUT)ui/tui/util.o - LIB_OBJS += $(OUTPUT)ui/tui/helpline.o LIB_H += ui/browser.h LIB_H += ui/browsers/map.h + LIB_H += ui/helpline.h LIB_H += ui/keysyms.h LIB_H += ui/libslang.h LIB_H += ui/progress.h @@ -606,7 +519,7 @@ endif ifdef NO_GTK2 BASIC_CFLAGS += -DNO_GTK2_SUPPORT else - FLAGS_GTK2=$(ALL_CFLAGS) $(ALL_LDFLAGS) $(EXTLIBS) $(shell pkg-config --libs --cflags gtk+-2.0 2>/dev/null) + FLAGS_GTK2=$(ALL_CFLAGS) $(ALL_LDFLAGS) $(EXTLIBS) $(shell pkg-config --libs --cflags gtk+-2.0) ifneq ($(call try-cc,$(SOURCE_GTK2),$(FLAGS_GTK2)),y) msg := $(warning GTK2 not found, disables GTK2 support. Please install gtk2-devel or libgtk2.0-dev); BASIC_CFLAGS += -DNO_GTK2_SUPPORT @@ -614,12 +527,11 @@ else ifeq ($(call try-cc,$(SOURCE_GTK2_INFOBAR),$(FLAGS_GTK2)),y) BASIC_CFLAGS += -DHAVE_GTK_INFO_BAR endif - BASIC_CFLAGS += $(shell pkg-config --cflags gtk+-2.0 2>/dev/null) - EXTLIBS += $(shell pkg-config --libs gtk+-2.0 2>/dev/null) + BASIC_CFLAGS += $(shell pkg-config --cflags gtk+-2.0) + EXTLIBS += $(shell pkg-config --libs gtk+-2.0) LIB_OBJS += $(OUTPUT)ui/gtk/browser.o LIB_OBJS += $(OUTPUT)ui/gtk/setup.o LIB_OBJS += $(OUTPUT)ui/gtk/util.o - LIB_OBJS += $(OUTPUT)ui/gtk/helpline.o # Make sure that it'd be included only once. ifneq ($(findstring -DNO_NEWT_SUPPORT,$(BASIC_CFLAGS)),) LIB_OBJS += $(OUTPUT)ui/setup.o @@ -728,7 +640,7 @@ else EXTLIBS += -liberty BASIC_CFLAGS += -DHAVE_CPLUS_DEMANGLE else - FLAGS_BFD=$(ALL_CFLAGS) $(ALL_LDFLAGS) $(EXTLIBS) -DPACKAGE='perf' -lbfd + FLAGS_BFD=$(ALL_CFLAGS) $(ALL_LDFLAGS) $(EXTLIBS) -lbfd has_bfd := $(call try-cc,$(SOURCE_BFD),$(FLAGS_BFD)) ifeq ($(has_bfd),y) EXTLIBS += -lbfd @@ -758,13 +670,6 @@ else endif endif -ifeq ($(NO_PERF_REGS),0) - ifeq ($(ARCH),x86) - LIB_H += arch/x86/include/perf_regs.h - endif -else - BASIC_CFLAGS += -DNO_PERF_REGS -endif ifdef NO_STRLCPY BASIC_CFLAGS += -DNO_STRLCPY @@ -774,14 +679,6 @@ else endif endif -ifdef NO_BACKTRACE - BASIC_CFLAGS += -DNO_BACKTRACE -else - ifneq ($(call try-cc,$(SOURCE_BACKTRACE),),y) - BASIC_CFLAGS += -DNO_BACKTRACE - endif -endif - ifdef ASCIIDOC8 export ASCIIDOC8 endif @@ -799,7 +696,6 @@ perfexecdir_SQ = $(subst ','\'',$(perfexecdir)) template_dir_SQ = $(subst ','\'',$(template_dir)) htmldir_SQ = $(subst ','\'',$(htmldir)) prefix_SQ = $(subst ','\'',$(prefix)) -sysconfdir_SQ = $(subst ','\'',$(sysconfdir)) SHELL_PATH_SQ = $(subst ','\'',$(SHELL_PATH)) @@ -867,10 +763,10 @@ $(OUTPUT)perf.o perf.spec \ # over the general rule for .o $(OUTPUT)util/%-flex.o: $(OUTPUT)util/%-flex.c $(OUTPUT)PERF-CFLAGS - $(QUIET_CC)$(CC) -o $@ -c -Iutil/ $(ALL_CFLAGS) -w $< + $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -Iutil/ -w $< $(OUTPUT)util/%-bison.o: $(OUTPUT)util/%-bison.c $(OUTPUT)PERF-CFLAGS - $(QUIET_CC)$(CC) -o $@ -c -Iutil/ $(ALL_CFLAGS) -DYYENABLE_NLS=0 -DYYLTYPE_IS_TRIVIAL=0 -w $< + $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DYYENABLE_NLS=0 -DYYLTYPE_IS_TRIVIAL=0 -Iutil/ -w $< $(OUTPUT)%.o: %.c $(OUTPUT)PERF-CFLAGS $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) $< @@ -942,10 +838,7 @@ $(LIB_FILE): $(LIB_OBJS) # libtraceevent.a $(LIBTRACEEVENT): - $(QUIET_SUBDIR0)$(TRACE_EVENT_DIR) $(QUIET_SUBDIR1) O=$(OUTPUT) libtraceevent.a - -$(LIBTRACEEVENT)-clean: - $(QUIET_SUBDIR0)$(TRACE_EVENT_DIR) $(QUIET_SUBDIR1) O=$(OUTPUT) clean + $(QUIET_SUBDIR0)$(TRACE_EVENT_DIR) $(QUIET_SUBDIR1) $(COMMAND_O) libtraceevent.a help: @echo 'Perf make targets:' @@ -1054,8 +947,6 @@ install: all $(INSTALL) scripts/python/Perf-Trace-Util/lib/Perf/Trace/* -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python/Perf-Trace-Util/lib/Perf/Trace' $(INSTALL) scripts/python/*.py -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python' $(INSTALL) scripts/python/bin/* -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python/bin' - $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(sysconfdir_SQ)/bash_completion.d' - $(INSTALL) bash_completion '$(DESTDIR_SQ)$(sysconfdir_SQ)/bash_completion.d/perf' install-python_ext: $(PYTHON_WORD) util/setup.py --quiet install --root='/$(DESTDIR_SQ)' @@ -1086,14 +977,13 @@ quick-install-html: ### Cleaning rules -clean: $(LIBTRACEEVENT)-clean +clean: $(RM) $(LIB_OBJS) $(BUILTIN_OBJS) $(LIB_FILE) $(OUTPUT)perf-archive $(OUTPUT)perf.o $(LANG_BINDINGS) $(RM) $(ALL_PROGRAMS) perf $(RM) *.spec *.pyc *.pyo */*.pyc */*.pyo $(OUTPUT)common-cmds.h TAGS tags cscope* $(MAKE) -C Documentation/ clean $(RM) $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)PERF-CFLAGS - $(RM) $(OUTPUT)util/*-bison* - $(RM) $(OUTPUT)util/*-flex* + $(RM) $(OUTPUT)util/*-{bison,flex}* $(python-clean) .PHONY: all install clean strip $(LIBTRACEEVENT) diff --git a/trunk/tools/perf/arch/x86/Makefile b/trunk/tools/perf/arch/x86/Makefile index 815841c04eb2..744e629797be 100644 --- a/trunk/tools/perf/arch/x86/Makefile +++ b/trunk/tools/perf/arch/x86/Makefile @@ -2,7 +2,4 @@ ifndef NO_DWARF PERF_HAVE_DWARF_REGS := 1 LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/dwarf-regs.o endif -ifndef NO_LIBUNWIND -LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/unwind.o -endif LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/header.o diff --git a/trunk/tools/perf/arch/x86/include/perf_regs.h b/trunk/tools/perf/arch/x86/include/perf_regs.h deleted file mode 100644 index 46fc9f15c6b3..000000000000 --- a/trunk/tools/perf/arch/x86/include/perf_regs.h +++ /dev/null @@ -1,80 +0,0 @@ -#ifndef ARCH_PERF_REGS_H -#define ARCH_PERF_REGS_H - -#include -#include "../../util/types.h" -#include "../../../../../arch/x86/include/asm/perf_regs.h" - -#ifndef ARCH_X86_64 -#define PERF_REGS_MASK ((1ULL << PERF_REG_X86_32_MAX) - 1) -#else -#define REG_NOSUPPORT ((1ULL << PERF_REG_X86_DS) | \ - (1ULL << PERF_REG_X86_ES) | \ - (1ULL << PERF_REG_X86_FS) | \ - (1ULL << PERF_REG_X86_GS)) -#define PERF_REGS_MASK (((1ULL << PERF_REG_X86_64_MAX) - 1) & ~REG_NOSUPPORT) -#endif -#define PERF_REG_IP PERF_REG_X86_IP -#define PERF_REG_SP PERF_REG_X86_SP - -static inline const char *perf_reg_name(int id) -{ - switch (id) { - case PERF_REG_X86_AX: - return "AX"; - case PERF_REG_X86_BX: - return "BX"; - case PERF_REG_X86_CX: - return "CX"; - case PERF_REG_X86_DX: - return "DX"; - case PERF_REG_X86_SI: - return "SI"; - case PERF_REG_X86_DI: - return "DI"; - case PERF_REG_X86_BP: - return "BP"; - case PERF_REG_X86_SP: - return "SP"; - case PERF_REG_X86_IP: - return "IP"; - case PERF_REG_X86_FLAGS: - return "FLAGS"; - case PERF_REG_X86_CS: - return "CS"; - case PERF_REG_X86_SS: - return "SS"; - case PERF_REG_X86_DS: - return "DS"; - case PERF_REG_X86_ES: - return "ES"; - case PERF_REG_X86_FS: - return "FS"; - case PERF_REG_X86_GS: - return "GS"; -#ifdef ARCH_X86_64 - case PERF_REG_X86_R8: - return "R8"; - case PERF_REG_X86_R9: - return "R9"; - case PERF_REG_X86_R10: - return "R10"; - case PERF_REG_X86_R11: - return "R11"; - case PERF_REG_X86_R12: - return "R12"; - case PERF_REG_X86_R13: - return "R13"; - case PERF_REG_X86_R14: - return "R14"; - case PERF_REG_X86_R15: - return "R15"; -#endif /* ARCH_X86_64 */ - default: - return NULL; - } - - return NULL; -} - -#endif /* ARCH_PERF_REGS_H */ diff --git a/trunk/tools/perf/arch/x86/util/unwind.c b/trunk/tools/perf/arch/x86/util/unwind.c deleted file mode 100644 index 78d956eff96f..000000000000 --- a/trunk/tools/perf/arch/x86/util/unwind.c +++ /dev/null @@ -1,111 +0,0 @@ - -#include -#include -#include "perf_regs.h" -#include "../../util/unwind.h" - -#ifdef ARCH_X86_64 -int unwind__arch_reg_id(int regnum) -{ - int id; - - switch (regnum) { - case UNW_X86_64_RAX: - id = PERF_REG_X86_AX; - break; - case UNW_X86_64_RDX: - id = PERF_REG_X86_DX; - break; - case UNW_X86_64_RCX: - id = PERF_REG_X86_CX; - break; - case UNW_X86_64_RBX: - id = PERF_REG_X86_BX; - break; - case UNW_X86_64_RSI: - id = PERF_REG_X86_SI; - break; - case UNW_X86_64_RDI: - id = PERF_REG_X86_DI; - break; - case UNW_X86_64_RBP: - id = PERF_REG_X86_BP; - break; - case UNW_X86_64_RSP: - id = PERF_REG_X86_SP; - break; - case UNW_X86_64_R8: - id = PERF_REG_X86_R8; - break; - case UNW_X86_64_R9: - id = PERF_REG_X86_R9; - break; - case UNW_X86_64_R10: - id = PERF_REG_X86_R10; - break; - case UNW_X86_64_R11: - id = PERF_REG_X86_R11; - break; - case UNW_X86_64_R12: - id = PERF_REG_X86_R12; - break; - case UNW_X86_64_R13: - id = PERF_REG_X86_R13; - break; - case UNW_X86_64_R14: - id = PERF_REG_X86_R14; - break; - case UNW_X86_64_R15: - id = PERF_REG_X86_R15; - break; - case UNW_X86_64_RIP: - id = PERF_REG_X86_IP; - break; - default: - pr_err("unwind: invalid reg id %d\n", regnum); - return -EINVAL; - } - - return id; -} -#else -int unwind__arch_reg_id(int regnum) -{ - int id; - - switch (regnum) { - case UNW_X86_EAX: - id = PERF_REG_X86_AX; - break; - case UNW_X86_EDX: - id = PERF_REG_X86_DX; - break; - case UNW_X86_ECX: - id = PERF_REG_X86_CX; - break; - case UNW_X86_EBX: - id = PERF_REG_X86_BX; - break; - case UNW_X86_ESI: - id = PERF_REG_X86_SI; - break; - case UNW_X86_EDI: - id = PERF_REG_X86_DI; - break; - case UNW_X86_EBP: - id = PERF_REG_X86_BP; - break; - case UNW_X86_ESP: - id = PERF_REG_X86_SP; - break; - case UNW_X86_EIP: - id = PERF_REG_X86_IP; - break; - default: - pr_err("unwind: invalid reg id %d\n", regnum); - return -EINVAL; - } - - return id; -} -#endif /* ARCH_X86_64 */ diff --git a/trunk/tools/perf/bash_completion b/trunk/tools/perf/bash_completion deleted file mode 100644 index 1958fa539d0f..000000000000 --- a/trunk/tools/perf/bash_completion +++ /dev/null @@ -1,26 +0,0 @@ -# perf completion - -have perf && -_perf() -{ - local cur cmd - - COMPREPLY=() - _get_comp_words_by_ref cur prev - - cmd=${COMP_WORDS[0]} - - # List perf subcommands - if [ $COMP_CWORD -eq 1 ]; then - cmds=$($cmd --list-cmds) - COMPREPLY=( $( compgen -W '$cmds' -- "$cur" ) ) - # List possible events for -e option - elif [[ $prev == "-e" && "${COMP_WORDS[1]}" == @(record|stat|top) ]]; then - cmds=$($cmd list --raw-dump) - COMPREPLY=( $( compgen -W '$cmds' -- "$cur" ) ) - # Fall down to list regular files - else - _filedir - fi -} && -complete -F _perf perf diff --git a/trunk/tools/perf/bench/bench.h b/trunk/tools/perf/bench/bench.h index 8f89998eeaf4..a09bece6dad2 100644 --- a/trunk/tools/perf/bench/bench.h +++ b/trunk/tools/perf/bench/bench.h @@ -3,8 +3,7 @@ extern int bench_sched_messaging(int argc, const char **argv, const char *prefix); extern int bench_sched_pipe(int argc, const char **argv, const char *prefix); -extern int bench_mem_memcpy(int argc, const char **argv, - const char *prefix __maybe_unused); +extern int bench_mem_memcpy(int argc, const char **argv, const char *prefix __used); extern int bench_mem_memset(int argc, const char **argv, const char *prefix); #define BENCH_FORMAT_DEFAULT_STR "default" diff --git a/trunk/tools/perf/bench/mem-memcpy.c b/trunk/tools/perf/bench/mem-memcpy.c index 93c83e3cb4a7..02dad5d3359b 100644 --- a/trunk/tools/perf/bench/mem-memcpy.c +++ b/trunk/tools/perf/bench/mem-memcpy.c @@ -177,7 +177,7 @@ static double do_memcpy_gettimeofday(memcpy_t fn, size_t len, bool prefault) } while (0) int bench_mem_memcpy(int argc, const char **argv, - const char *prefix __maybe_unused) + const char *prefix __used) { int i; size_t len; diff --git a/trunk/tools/perf/bench/mem-memset.c b/trunk/tools/perf/bench/mem-memset.c index c6e4bc523492..350cc9557265 100644 --- a/trunk/tools/perf/bench/mem-memset.c +++ b/trunk/tools/perf/bench/mem-memset.c @@ -171,7 +171,7 @@ static double do_memset_gettimeofday(memset_t fn, size_t len, bool prefault) } while (0) int bench_mem_memset(int argc, const char **argv, - const char *prefix __maybe_unused) + const char *prefix __used) { int i; size_t len; diff --git a/trunk/tools/perf/bench/sched-messaging.c b/trunk/tools/perf/bench/sched-messaging.c index cc1190a0849b..d1d1b30f99c1 100644 --- a/trunk/tools/perf/bench/sched-messaging.c +++ b/trunk/tools/perf/bench/sched-messaging.c @@ -267,7 +267,7 @@ static const char * const bench_sched_message_usage[] = { }; int bench_sched_messaging(int argc, const char **argv, - const char *prefix __maybe_unused) + const char *prefix __used) { unsigned int i, total_children; struct timeval start, stop, diff; diff --git a/trunk/tools/perf/bench/sched-pipe.c b/trunk/tools/perf/bench/sched-pipe.c index 69cfba8d4c6c..0c7454f8b8a9 100644 --- a/trunk/tools/perf/bench/sched-pipe.c +++ b/trunk/tools/perf/bench/sched-pipe.c @@ -43,7 +43,7 @@ static const char * const bench_sched_pipe_usage[] = { }; int bench_sched_pipe(int argc, const char **argv, - const char *prefix __maybe_unused) + const char *prefix __used) { int pipe_1[2], pipe_2[2]; int m = 0, i; @@ -55,14 +55,14 @@ int bench_sched_pipe(int argc, const char **argv, * discarding returned value of read(), write() * causes error in building environment for perf */ - int __maybe_unused ret, wait_stat; - pid_t pid, retpid __maybe_unused; + int __used ret, wait_stat; + pid_t pid, retpid; argc = parse_options(argc, argv, options, bench_sched_pipe_usage, 0); - BUG_ON(pipe(pipe_1)); - BUG_ON(pipe(pipe_2)); + assert(!pipe(pipe_1)); + assert(!pipe(pipe_2)); pid = fork(); assert(pid >= 0); diff --git a/trunk/tools/perf/builtin-annotate.c b/trunk/tools/perf/builtin-annotate.c index 9ea38540b873..67522cf87405 100644 --- a/trunk/tools/perf/builtin-annotate.c +++ b/trunk/tools/perf/builtin-annotate.c @@ -239,7 +239,7 @@ static const char * const annotate_usage[] = { NULL }; -int cmd_annotate(int argc, const char **argv, const char *prefix __maybe_unused) +int cmd_annotate(int argc, const char **argv, const char *prefix __used) { struct perf_annotate annotate = { .tool = { @@ -282,8 +282,6 @@ int cmd_annotate(int argc, const char **argv, const char *prefix __maybe_unused) "Display raw encoding of assembly instructions (default)"), OPT_STRING('M', "disassembler-style", &disassembler_style, "disassembler style", "Specify disassembler style (e.g. -M intel for intel syntax)"), - OPT_STRING(0, "objdump", &objdump_path, "path", - "objdump binary to use for disassembly and annotations"), OPT_END() }; diff --git a/trunk/tools/perf/builtin-bench.c b/trunk/tools/perf/builtin-bench.c index cae9a5fd2ecf..1f3100216448 100644 --- a/trunk/tools/perf/builtin-bench.c +++ b/trunk/tools/perf/builtin-bench.c @@ -173,7 +173,7 @@ static void all_subsystem(void) all_suite(&subsystems[i]); } -int cmd_bench(int argc, const char **argv, const char *prefix __maybe_unused) +int cmd_bench(int argc, const char **argv, const char *prefix __used) { int i, j, status = 0; diff --git a/trunk/tools/perf/builtin-buildid-cache.c b/trunk/tools/perf/builtin-buildid-cache.c index 83654557e108..29ad20e67919 100644 --- a/trunk/tools/perf/builtin-buildid-cache.c +++ b/trunk/tools/perf/builtin-buildid-cache.c @@ -43,16 +43,15 @@ static int build_id_cache__add_file(const char *filename, const char *debugdir) } build_id__sprintf(build_id, sizeof(build_id), sbuild_id); - err = build_id_cache__add_s(sbuild_id, debugdir, filename, - false, false); + err = build_id_cache__add_s(sbuild_id, debugdir, filename, false); if (verbose) pr_info("Adding %s %s: %s\n", sbuild_id, filename, err ? "FAIL" : "Ok"); return err; } -static int build_id_cache__remove_file(const char *filename __maybe_unused, - const char *debugdir __maybe_unused) +static int build_id_cache__remove_file(const char *filename __used, + const char *debugdir __used) { u8 build_id[BUILD_ID_SIZE]; char sbuild_id[BUILD_ID_SIZE * 2 + 1]; @@ -120,8 +119,7 @@ static int __cmd_buildid_cache(void) return 0; } -int cmd_buildid_cache(int argc, const char **argv, - const char *prefix __maybe_unused) +int cmd_buildid_cache(int argc, const char **argv, const char *prefix __used) { argc = parse_options(argc, argv, buildid_cache_options, buildid_cache_usage, 0); diff --git a/trunk/tools/perf/builtin-buildid-list.c b/trunk/tools/perf/builtin-buildid-list.c index 1159feeebb19..6b2bcfbde150 100644 --- a/trunk/tools/perf/builtin-buildid-list.c +++ b/trunk/tools/perf/builtin-buildid-list.c @@ -16,6 +16,8 @@ #include "util/session.h" #include "util/symbol.h" +#include + static const char *input_name; static bool force; static bool show_kernel; @@ -69,7 +71,7 @@ static int perf_session__list_build_ids(void) { struct perf_session *session; - symbol__elf_init(); + elf_version(EV_CURRENT); session = perf_session__new(input_name, O_RDONLY, force, false, &build_id__mark_dso_hit_ops); @@ -103,8 +105,7 @@ static int __cmd_buildid_list(void) return perf_session__list_build_ids(); } -int cmd_buildid_list(int argc, const char **argv, - const char *prefix __maybe_unused) +int cmd_buildid_list(int argc, const char **argv, const char *prefix __used) { argc = parse_options(argc, argv, options, buildid_list_usage, 0); setup_pager(); diff --git a/trunk/tools/perf/builtin-diff.c b/trunk/tools/perf/builtin-diff.c index 761f4197a9e2..d29d350fb2b7 100644 --- a/trunk/tools/perf/builtin-diff.c +++ b/trunk/tools/perf/builtin-diff.c @@ -10,7 +10,6 @@ #include "util/event.h" #include "util/hist.h" #include "util/evsel.h" -#include "util/evlist.h" #include "util/session.h" #include "util/tool.h" #include "util/sort.h" @@ -25,6 +24,11 @@ static char diff__default_sort_order[] = "dso,symbol"; static bool force; static bool show_displacement; +struct perf_diff { + struct perf_tool tool; + struct perf_session *session; +}; + static int hists__add_entry(struct hists *self, struct addr_location *al, u64 period) { @@ -33,12 +37,14 @@ static int hists__add_entry(struct hists *self, return -ENOMEM; } -static int diff__process_sample_event(struct perf_tool *tool __maybe_unused, +static int diff__process_sample_event(struct perf_tool *tool, union perf_event *event, struct perf_sample *sample, - struct perf_evsel *evsel, + struct perf_evsel *evsel __used, struct machine *machine) { + struct perf_diff *_diff = container_of(tool, struct perf_diff, tool); + struct perf_session *session = _diff->session; struct addr_location al; if (perf_event__preprocess_sample(event, machine, &al, sample, NULL) < 0) { @@ -50,24 +56,26 @@ static int diff__process_sample_event(struct perf_tool *tool __maybe_unused, if (al.filtered || al.sym == NULL) return 0; - if (hists__add_entry(&evsel->hists, &al, sample->period)) { + if (hists__add_entry(&session->hists, &al, sample->period)) { pr_warning("problem incrementing symbol period, skipping event\n"); return -1; } - evsel->hists.stats.total_period += sample->period; + session->hists.stats.total_period += sample->period; return 0; } -static struct perf_tool tool = { - .sample = diff__process_sample_event, - .mmap = perf_event__process_mmap, - .comm = perf_event__process_comm, - .exit = perf_event__process_task, - .fork = perf_event__process_task, - .lost = perf_event__process_lost, - .ordered_samples = true, - .ordering_requires_timestamps = true, +static struct perf_diff diff = { + .tool = { + .sample = diff__process_sample_event, + .mmap = perf_event__process_mmap, + .comm = perf_event__process_comm, + .exit = perf_event__process_task, + .fork = perf_event__process_task, + .lost = perf_event__process_lost, + .ordered_samples = true, + .ordering_requires_timestamps = true, + }, }; static void perf_session__insert_hist_entry_by_name(struct rb_root *root, @@ -138,71 +146,34 @@ static void hists__match(struct hists *older, struct hists *newer) } } -static struct perf_evsel *evsel_match(struct perf_evsel *evsel, - struct perf_evlist *evlist) -{ - struct perf_evsel *e; - - list_for_each_entry(e, &evlist->entries, node) - if (perf_evsel__match2(evsel, e)) - return e; - - return NULL; -} - static int __cmd_diff(void) { int ret, i; #define older (session[0]) #define newer (session[1]) struct perf_session *session[2]; - struct perf_evlist *evlist_new, *evlist_old; - struct perf_evsel *evsel; - bool first = true; older = perf_session__new(input_old, O_RDONLY, force, false, - &tool); + &diff.tool); newer = perf_session__new(input_new, O_RDONLY, force, false, - &tool); + &diff.tool); if (session[0] == NULL || session[1] == NULL) return -ENOMEM; for (i = 0; i < 2; ++i) { - ret = perf_session__process_events(session[i], &tool); + diff.session = session[i]; + ret = perf_session__process_events(session[i], &diff.tool); if (ret) goto out_delete; + hists__output_resort(&session[i]->hists); } - evlist_old = older->evlist; - evlist_new = newer->evlist; - - list_for_each_entry(evsel, &evlist_new->entries, node) - hists__output_resort(&evsel->hists); - - list_for_each_entry(evsel, &evlist_old->entries, node) { - hists__output_resort(&evsel->hists); - - if (show_displacement) - hists__resort_entries(&evsel->hists); - } - - list_for_each_entry(evsel, &evlist_new->entries, node) { - struct perf_evsel *evsel_old; - - evsel_old = evsel_match(evsel, evlist_old); - if (!evsel_old) - continue; - - fprintf(stdout, "%s# Event '%s'\n#\n", first ? "" : "\n", - perf_evsel__name(evsel)); - - first = false; - - hists__match(&evsel_old->hists, &evsel->hists); - hists__fprintf(&evsel->hists, &evsel_old->hists, - show_displacement, true, 0, 0, stdout); - } + if (show_displacement) + hists__resort_entries(&older->hists); + hists__match(&older->hists, &newer->hists); + hists__fprintf(&newer->hists, &older->hists, + show_displacement, true, 0, 0, stdout); out_delete: for (i = 0; i < 2; ++i) perf_session__delete(session[i]); @@ -242,7 +213,7 @@ static const struct option options[] = { OPT_END() }; -int cmd_diff(int argc, const char **argv, const char *prefix __maybe_unused) +int cmd_diff(int argc, const char **argv, const char *prefix __used) { sort_order = diff__default_sort_order; argc = parse_options(argc, argv, options, diff_usage, 0); @@ -264,7 +235,6 @@ int cmd_diff(int argc, const char **argv, const char *prefix __maybe_unused) if (symbol__init() < 0) return -1; - perf_hpp__init(true, show_displacement); setup_sorting(diff_usage, options); setup_pager(); diff --git a/trunk/tools/perf/builtin-evlist.c b/trunk/tools/perf/builtin-evlist.c index 1fb164164fd0..0dd5a058f766 100644 --- a/trunk/tools/perf/builtin-evlist.c +++ b/trunk/tools/perf/builtin-evlist.c @@ -113,7 +113,7 @@ static const char * const evlist_usage[] = { NULL }; -int cmd_evlist(int argc, const char **argv, const char *prefix __maybe_unused) +int cmd_evlist(int argc, const char **argv, const char *prefix __used) { struct perf_attr_details details = { .verbose = false, }; const char *input_name = NULL; diff --git a/trunk/tools/perf/builtin-help.c b/trunk/tools/perf/builtin-help.c index 25c8b942ff85..6d5a8a7faf48 100644 --- a/trunk/tools/perf/builtin-help.c +++ b/trunk/tools/perf/builtin-help.c @@ -24,14 +24,13 @@ static struct man_viewer_info_list { } *man_viewer_info_list; enum help_format { - HELP_FORMAT_NONE, HELP_FORMAT_MAN, HELP_FORMAT_INFO, HELP_FORMAT_WEB, }; static bool show_all = false; -static enum help_format help_format = HELP_FORMAT_NONE; +static enum help_format help_format = HELP_FORMAT_MAN; static struct option builtin_help_options[] = { OPT_BOOLEAN('a', "all", &show_all, "print all available commands"), OPT_SET_UINT('m', "man", &help_format, "show man page", HELP_FORMAT_MAN), @@ -55,9 +54,7 @@ static enum help_format parse_help_format(const char *format) return HELP_FORMAT_INFO; if (!strcmp(format, "web") || !strcmp(format, "html")) return HELP_FORMAT_WEB; - - pr_err("unrecognized help format '%s'", format); - return HELP_FORMAT_NONE; + die("unrecognized help format '%s'", format); } static const char *get_man_viewer_info(const char *name) @@ -262,8 +259,6 @@ static int perf_help_config(const char *var, const char *value, void *cb) if (!value) return config_error_nonbool(var); help_format = parse_help_format(value); - if (help_format == HELP_FORMAT_NONE) - return -1; return 0; } if (!strcmp(var, "man.viewer")) { @@ -357,7 +352,7 @@ static void exec_viewer(const char *name, const char *page) warning("'%s': unknown man viewer.", name); } -static int show_man_page(const char *perf_cmd) +static void show_man_page(const char *perf_cmd) { struct man_viewer_list *viewer; const char *page = cmd_to_page(perf_cmd); @@ -370,35 +365,28 @@ static int show_man_page(const char *perf_cmd) if (fallback) exec_viewer(fallback, page); exec_viewer("man", page); - - pr_err("no man viewer handled the request"); - return -1; + die("no man viewer handled the request"); } -static int show_info_page(const char *perf_cmd) +static void show_info_page(const char *perf_cmd) { const char *page = cmd_to_page(perf_cmd); setenv("INFOPATH", system_path(PERF_INFO_PATH), 1); execlp("info", "info", "perfman", page, NULL); - return -1; } -static int get_html_page_path(struct strbuf *page_path, const char *page) +static void get_html_page_path(struct strbuf *page_path, const char *page) { struct stat st; const char *html_path = system_path(PERF_HTML_PATH); /* Check that we have a perf documentation directory. */ if (stat(mkpath("%s/perf.html", html_path), &st) - || !S_ISREG(st.st_mode)) { - pr_err("'%s': not a documentation directory.", html_path); - return -1; - } + || !S_ISREG(st.st_mode)) + die("'%s': not a documentation directory.", html_path); strbuf_init(page_path, 0); strbuf_addf(page_path, "%s/%s.html", html_path, page); - - return 0; } /* @@ -413,23 +401,19 @@ static void open_html(const char *path) } #endif -static int show_html_page(const char *perf_cmd) +static void show_html_page(const char *perf_cmd) { const char *page = cmd_to_page(perf_cmd); struct strbuf page_path; /* it leaks but we exec bellow */ - if (get_html_page_path(&page_path, page) != 0) - return -1; + get_html_page_path(&page_path, page); open_html(page_path.buf); - - return 0; } -int cmd_help(int argc, const char **argv, const char *prefix __maybe_unused) +int cmd_help(int argc, const char **argv, const char *prefix __used) { const char *alias; - int rc = 0; load_command_list("perf-", &main_cmds, &other_cmds); @@ -460,20 +444,16 @@ int cmd_help(int argc, const char **argv, const char *prefix __maybe_unused) switch (help_format) { case HELP_FORMAT_MAN: - rc = show_man_page(argv[0]); + show_man_page(argv[0]); break; case HELP_FORMAT_INFO: - rc = show_info_page(argv[0]); + show_info_page(argv[0]); break; case HELP_FORMAT_WEB: - rc = show_html_page(argv[0]); - break; - case HELP_FORMAT_NONE: - /* fall-through */ + show_html_page(argv[0]); default: - rc = -1; break; } - return rc; + return 0; } diff --git a/trunk/tools/perf/builtin-inject.c b/trunk/tools/perf/builtin-inject.c index 1eaa6617c814..3beab489afc5 100644 --- a/trunk/tools/perf/builtin-inject.c +++ b/trunk/tools/perf/builtin-inject.c @@ -17,9 +17,9 @@ static char const *input_name = "-"; static bool inject_build_ids; -static int perf_event__repipe_synth(struct perf_tool *tool __maybe_unused, +static int perf_event__repipe_synth(struct perf_tool *tool __used, union perf_event *event, - struct machine *machine __maybe_unused) + struct machine *machine __used) { uint32_t size; void *buf = event; @@ -40,8 +40,7 @@ static int perf_event__repipe_synth(struct perf_tool *tool __maybe_unused, static int perf_event__repipe_op2_synth(struct perf_tool *tool, union perf_event *event, - struct perf_session *session - __maybe_unused) + struct perf_session *session __used) { return perf_event__repipe_synth(tool, event, NULL); } @@ -53,14 +52,13 @@ static int perf_event__repipe_event_type_synth(struct perf_tool *tool, } static int perf_event__repipe_tracing_data_synth(union perf_event *event, - struct perf_session *session - __maybe_unused) + struct perf_session *session __used) { return perf_event__repipe_synth(NULL, event, NULL); } static int perf_event__repipe_attr(union perf_event *event, - struct perf_evlist **pevlist __maybe_unused) + struct perf_evlist **pevlist __used) { int ret; ret = perf_event__process_attr(event, pevlist); @@ -72,7 +70,7 @@ static int perf_event__repipe_attr(union perf_event *event, static int perf_event__repipe(struct perf_tool *tool, union perf_event *event, - struct perf_sample *sample __maybe_unused, + struct perf_sample *sample __used, struct machine *machine) { return perf_event__repipe_synth(tool, event, machine); @@ -80,8 +78,8 @@ static int perf_event__repipe(struct perf_tool *tool, static int perf_event__repipe_sample(struct perf_tool *tool, union perf_event *event, - struct perf_sample *sample __maybe_unused, - struct perf_evsel *evsel __maybe_unused, + struct perf_sample *sample __used, + struct perf_evsel *evsel __used, struct machine *machine) { return perf_event__repipe_synth(tool, event, machine); @@ -165,7 +163,7 @@ static int dso__inject_build_id(struct dso *self, struct perf_tool *tool, static int perf_event__inject_buildid(struct perf_tool *tool, union perf_event *event, struct perf_sample *sample, - struct perf_evsel *evsel __maybe_unused, + struct perf_evsel *evsel __used, struct machine *machine) { struct addr_location al; @@ -193,13 +191,10 @@ static int perf_event__inject_buildid(struct perf_tool *tool, * If this fails, too bad, let the other side * account this as unresolved. */ - } else { -#ifndef NO_LIBELF_SUPPORT + } else pr_warning("no symbols found in %s, maybe " "install a debug package?\n", al.map->dso->long_name); -#endif - } } } @@ -226,7 +221,7 @@ struct perf_tool perf_inject = { extern volatile int session_done; -static void sig_handler(int sig __maybe_unused) +static void sig_handler(int sig __attribute__((__unused__))) { session_done = 1; } @@ -269,7 +264,7 @@ static const struct option options[] = { OPT_END() }; -int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused) +int cmd_inject(int argc, const char **argv, const char *prefix __used) { argc = parse_options(argc, argv, options, report_usage, 0); diff --git a/trunk/tools/perf/builtin-kmem.c b/trunk/tools/perf/builtin-kmem.c index bc912c68f49a..ce35015f2dc6 100644 --- a/trunk/tools/perf/builtin-kmem.c +++ b/trunk/tools/perf/builtin-kmem.c @@ -1,8 +1,6 @@ #include "builtin.h" #include "perf.h" -#include "util/evlist.h" -#include "util/evsel.h" #include "util/util.h" #include "util/cache.h" #include "util/symbol.h" @@ -59,52 +57,46 @@ static unsigned long nr_allocs, nr_cross_allocs; #define PATH_SYS_NODE "/sys/devices/system/node" -static int init_cpunode_map(void) +struct perf_kmem { + struct perf_tool tool; + struct perf_session *session; +}; + +static void init_cpunode_map(void) { FILE *fp; - int i, err = -1; + int i; fp = fopen("/sys/devices/system/cpu/kernel_max", "r"); if (!fp) { max_cpu_num = 4096; - return 0; - } - - if (fscanf(fp, "%d", &max_cpu_num) < 1) { - pr_err("Failed to read 'kernel_max' from sysfs"); - goto out_close; + return; } + if (fscanf(fp, "%d", &max_cpu_num) < 1) + die("Failed to read 'kernel_max' from sysfs"); max_cpu_num++; cpunode_map = calloc(max_cpu_num, sizeof(int)); - if (!cpunode_map) { - pr_err("%s: calloc failed\n", __func__); - goto out_close; - } - + if (!cpunode_map) + die("calloc"); for (i = 0; i < max_cpu_num; i++) cpunode_map[i] = -1; - - err = 0; -out_close: fclose(fp); - return err; } -static int setup_cpunode_map(void) +static void setup_cpunode_map(void) { struct dirent *dent1, *dent2; DIR *dir1, *dir2; unsigned int cpu, mem; char buf[PATH_MAX]; - if (init_cpunode_map()) - return -1; + init_cpunode_map(); dir1 = opendir(PATH_SYS_NODE); if (!dir1) - return -1; + return; while ((dent1 = readdir(dir1)) != NULL) { if (dent1->d_type != DT_DIR || @@ -124,11 +116,10 @@ static int setup_cpunode_map(void) closedir(dir2); } closedir(dir1); - return 0; } -static int insert_alloc_stat(unsigned long call_site, unsigned long ptr, - int bytes_req, int bytes_alloc, int cpu) +static void insert_alloc_stat(unsigned long call_site, unsigned long ptr, + int bytes_req, int bytes_alloc, int cpu) { struct rb_node **node = &root_alloc_stat.rb_node; struct rb_node *parent = NULL; @@ -152,10 +143,8 @@ static int insert_alloc_stat(unsigned long call_site, unsigned long ptr, data->bytes_alloc += bytes_alloc; } else { data = malloc(sizeof(*data)); - if (!data) { - pr_err("%s: malloc failed\n", __func__); - return -1; - } + if (!data) + die("malloc"); data->ptr = ptr; data->pingpong = 0; data->hit = 1; @@ -167,10 +156,9 @@ static int insert_alloc_stat(unsigned long call_site, unsigned long ptr, } data->call_site = call_site; data->alloc_cpu = cpu; - return 0; } -static int insert_caller_stat(unsigned long call_site, +static void insert_caller_stat(unsigned long call_site, int bytes_req, int bytes_alloc) { struct rb_node **node = &root_caller_stat.rb_node; @@ -195,10 +183,8 @@ static int insert_caller_stat(unsigned long call_site, data->bytes_alloc += bytes_alloc; } else { data = malloc(sizeof(*data)); - if (!data) { - pr_err("%s: malloc failed\n", __func__); - return -1; - } + if (!data) + die("malloc"); data->call_site = call_site; data->pingpong = 0; data->hit = 1; @@ -208,43 +194,39 @@ static int insert_caller_stat(unsigned long call_site, rb_link_node(&data->node, parent, node); rb_insert_color(&data->node, &root_caller_stat); } - - return 0; } -static int perf_evsel__process_alloc_event(struct perf_evsel *evsel, - struct perf_sample *sample) +static void process_alloc_event(void *data, + struct event_format *event, + int cpu, + u64 timestamp __used, + struct thread *thread __used, + int node) { - unsigned long ptr = perf_evsel__intval(evsel, sample, "ptr"), - call_site = perf_evsel__intval(evsel, sample, "call_site"); - int bytes_req = perf_evsel__intval(evsel, sample, "bytes_req"), - bytes_alloc = perf_evsel__intval(evsel, sample, "bytes_alloc"); + unsigned long call_site; + unsigned long ptr; + int bytes_req; + int bytes_alloc; + int node1, node2; - if (insert_alloc_stat(call_site, ptr, bytes_req, bytes_alloc, sample->cpu) || - insert_caller_stat(call_site, bytes_req, bytes_alloc)) - return -1; + ptr = raw_field_value(event, "ptr", data); + call_site = raw_field_value(event, "call_site", data); + bytes_req = raw_field_value(event, "bytes_req", data); + bytes_alloc = raw_field_value(event, "bytes_alloc", data); + + insert_alloc_stat(call_site, ptr, bytes_req, bytes_alloc, cpu); + insert_caller_stat(call_site, bytes_req, bytes_alloc); total_requested += bytes_req; total_allocated += bytes_alloc; - nr_allocs++; - return 0; -} - -static int perf_evsel__process_alloc_node_event(struct perf_evsel *evsel, - struct perf_sample *sample) -{ - int ret = perf_evsel__process_alloc_event(evsel, sample); - - if (!ret) { - int node1 = cpunode_map[sample->cpu], - node2 = perf_evsel__intval(evsel, sample, "node"); - + if (node) { + node1 = cpunode_map[cpu]; + node2 = raw_field_value(event, "node", data); if (node1 != node2) nr_cross_allocs++; } - - return ret; + nr_allocs++; } static int ptr_cmp(struct alloc_stat *, struct alloc_stat *); @@ -275,37 +257,66 @@ static struct alloc_stat *search_alloc_stat(unsigned long ptr, return NULL; } -static int perf_evsel__process_free_event(struct perf_evsel *evsel, - struct perf_sample *sample) +static void process_free_event(void *data, + struct event_format *event, + int cpu, + u64 timestamp __used, + struct thread *thread __used) { - unsigned long ptr = perf_evsel__intval(evsel, sample, "ptr"); + unsigned long ptr; struct alloc_stat *s_alloc, *s_caller; + ptr = raw_field_value(event, "ptr", data); + s_alloc = search_alloc_stat(ptr, 0, &root_alloc_stat, ptr_cmp); if (!s_alloc) - return 0; + return; - if ((short)sample->cpu != s_alloc->alloc_cpu) { + if (cpu != s_alloc->alloc_cpu) { s_alloc->pingpong++; s_caller = search_alloc_stat(0, s_alloc->call_site, &root_caller_stat, callsite_cmp); - if (!s_caller) - return -1; + assert(s_caller); s_caller->pingpong++; } s_alloc->alloc_cpu = -1; - - return 0; } -typedef int (*tracepoint_handler)(struct perf_evsel *evsel, - struct perf_sample *sample); +static void process_raw_event(struct perf_tool *tool, + union perf_event *raw_event __used, void *data, + int cpu, u64 timestamp, struct thread *thread) +{ + struct perf_kmem *kmem = container_of(tool, struct perf_kmem, tool); + struct event_format *event; + int type; + + type = trace_parse_common_type(kmem->session->pevent, data); + event = pevent_find_event(kmem->session->pevent, type); -static int process_sample_event(struct perf_tool *tool __maybe_unused, + if (!strcmp(event->name, "kmalloc") || + !strcmp(event->name, "kmem_cache_alloc")) { + process_alloc_event(data, event, cpu, timestamp, thread, 0); + return; + } + + if (!strcmp(event->name, "kmalloc_node") || + !strcmp(event->name, "kmem_cache_alloc_node")) { + process_alloc_event(data, event, cpu, timestamp, thread, 1); + return; + } + + if (!strcmp(event->name, "kfree") || + !strcmp(event->name, "kmem_cache_free")) { + process_free_event(data, event, cpu, timestamp, thread); + return; + } +} + +static int process_sample_event(struct perf_tool *tool, union perf_event *event, struct perf_sample *sample, - struct perf_evsel *evsel, + struct perf_evsel *evsel __used, struct machine *machine) { struct thread *thread = machine__findnew_thread(machine, event->ip.pid); @@ -318,18 +329,18 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused, dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid); - if (evsel->handler.func != NULL) { - tracepoint_handler f = evsel->handler.func; - return f(evsel, sample); - } + process_raw_event(tool, event, sample->raw_data, sample->cpu, + sample->time, thread); return 0; } -static struct perf_tool perf_kmem = { - .sample = process_sample_event, - .comm = perf_event__process_comm, - .ordered_samples = true, +static struct perf_kmem perf_kmem = { + .tool = { + .sample = process_sample_event, + .comm = perf_event__process_comm, + .ordered_samples = true, + }, }; static double fragmentation(unsigned long n_req, unsigned long n_alloc) @@ -485,32 +496,22 @@ static int __cmd_kmem(void) { int err = -EINVAL; struct perf_session *session; - const struct perf_evsel_str_handler kmem_tracepoints[] = { - { "kmem:kmalloc", perf_evsel__process_alloc_event, }, - { "kmem:kmem_cache_alloc", perf_evsel__process_alloc_event, }, - { "kmem:kmalloc_node", perf_evsel__process_alloc_node_event, }, - { "kmem:kmem_cache_alloc_node", perf_evsel__process_alloc_node_event, }, - { "kmem:kfree", perf_evsel__process_free_event, }, - { "kmem:kmem_cache_free", perf_evsel__process_free_event, }, - }; - - session = perf_session__new(input_name, O_RDONLY, 0, false, &perf_kmem); + + session = perf_session__new(input_name, O_RDONLY, 0, false, + &perf_kmem.tool); if (session == NULL) return -ENOMEM; + perf_kmem.session = session; + if (perf_session__create_kernel_maps(session) < 0) goto out_delete; if (!perf_session__has_traces(session, "kmem record")) goto out_delete; - if (perf_session__set_tracepoints_handlers(session, kmem_tracepoints)) { - pr_err("Initializing perf session tracepoint handlers failed\n"); - return -1; - } - setup_pager(); - err = perf_session__process_events(session, &perf_kmem); + err = perf_session__process_events(session, &perf_kmem.tool); if (err != 0) goto out_delete; sort_result(); @@ -634,10 +635,8 @@ static int sort_dimension__add(const char *tok, struct list_head *list) for (i = 0; i < NUM_AVAIL_SORTS; i++) { if (!strcmp(avail_sorts[i]->name, tok)) { sort = malloc(sizeof(*sort)); - if (!sort) { - pr_err("%s: malloc failed\n", __func__); - return -1; - } + if (!sort) + die("malloc"); memcpy(sort, avail_sorts[i], sizeof(*sort)); list_add_tail(&sort->list, list); return 0; @@ -652,10 +651,8 @@ static int setup_sorting(struct list_head *sort_list, const char *arg) char *tok; char *str = strdup(arg); - if (!str) { - pr_err("%s: strdup failed\n", __func__); - return -1; - } + if (!str) + die("strdup"); while (true) { tok = strsep(&str, ","); @@ -672,8 +669,8 @@ static int setup_sorting(struct list_head *sort_list, const char *arg) return 0; } -static int parse_sort_opt(const struct option *opt __maybe_unused, - const char *arg, int unset __maybe_unused) +static int parse_sort_opt(const struct option *opt __used, + const char *arg, int unset __used) { if (!arg) return -1; @@ -686,24 +683,22 @@ static int parse_sort_opt(const struct option *opt __maybe_unused, return 0; } -static int parse_caller_opt(const struct option *opt __maybe_unused, - const char *arg __maybe_unused, - int unset __maybe_unused) +static int parse_caller_opt(const struct option *opt __used, + const char *arg __used, int unset __used) { caller_flag = (alloc_flag + 1); return 0; } -static int parse_alloc_opt(const struct option *opt __maybe_unused, - const char *arg __maybe_unused, - int unset __maybe_unused) +static int parse_alloc_opt(const struct option *opt __used, + const char *arg __used, int unset __used) { alloc_flag = (caller_flag + 1); return 0; } -static int parse_line_opt(const struct option *opt __maybe_unused, - const char *arg, int unset __maybe_unused) +static int parse_line_opt(const struct option *opt __used, + const char *arg, int unset __used) { int lines; @@ -773,7 +768,7 @@ static int __cmd_record(int argc, const char **argv) return cmd_record(i, rec_argv, NULL); } -int cmd_kmem(int argc, const char **argv, const char *prefix __maybe_unused) +int cmd_kmem(int argc, const char **argv, const char *prefix __used) { argc = parse_options(argc, argv, kmem_options, kmem_usage, 0); @@ -785,8 +780,7 @@ int cmd_kmem(int argc, const char **argv, const char *prefix __maybe_unused) if (!strncmp(argv[0], "rec", 3)) { return __cmd_record(argc, argv); } else if (!strcmp(argv[0], "stat")) { - if (setup_cpunode_map()) - return -1; + setup_cpunode_map(); if (list_empty(&caller_sort)) setup_sorting(&caller_sort, default_sort_order); diff --git a/trunk/tools/perf/builtin-kvm.c b/trunk/tools/perf/builtin-kvm.c index a28c9cad9048..9fc6e0fa3dce 100644 --- a/trunk/tools/perf/builtin-kvm.c +++ b/trunk/tools/perf/builtin-kvm.c @@ -1,7 +1,6 @@ #include "builtin.h" #include "perf.h" -#include "util/evsel.h" #include "util/util.h" #include "util/cache.h" #include "util/symbol.h" @@ -11,10 +10,8 @@ #include "util/parse-options.h" #include "util/trace-event.h" + #include "util/debug.h" -#include "util/debugfs.h" -#include "util/tool.h" -#include "util/stat.h" #include @@ -22,836 +19,11 @@ #include #include -#include "../../arch/x86/include/asm/svm.h" -#include "../../arch/x86/include/asm/vmx.h" -#include "../../arch/x86/include/asm/kvm.h" - -struct event_key { - #define INVALID_KEY (~0ULL) - u64 key; - int info; -}; - -struct kvm_events_ops { - bool (*is_begin_event)(struct perf_evsel *evsel, - struct perf_sample *sample, - struct event_key *key); - bool (*is_end_event)(struct perf_evsel *evsel, - struct perf_sample *sample, struct event_key *key); - void (*decode_key)(struct event_key *key, char decode[20]); - const char *name; -}; - -static void exit_event_get_key(struct perf_evsel *evsel, - struct perf_sample *sample, - struct event_key *key) -{ - key->info = 0; - key->key = perf_evsel__intval(evsel, sample, "exit_reason"); -} - -static bool kvm_exit_event(struct perf_evsel *evsel) -{ - return !strcmp(evsel->name, "kvm:kvm_exit"); -} - -static bool exit_event_begin(struct perf_evsel *evsel, - struct perf_sample *sample, struct event_key *key) -{ - if (kvm_exit_event(evsel)) { - exit_event_get_key(evsel, sample, key); - return true; - } - - return false; -} - -static bool kvm_entry_event(struct perf_evsel *evsel) -{ - return !strcmp(evsel->name, "kvm:kvm_entry"); -} - -static bool exit_event_end(struct perf_evsel *evsel, - struct perf_sample *sample __maybe_unused, - struct event_key *key __maybe_unused) -{ - return kvm_entry_event(evsel); -} - -struct exit_reasons_table { - unsigned long exit_code; - const char *reason; -}; - -struct exit_reasons_table vmx_exit_reasons[] = { - VMX_EXIT_REASONS -}; - -struct exit_reasons_table svm_exit_reasons[] = { - SVM_EXIT_REASONS -}; - -static int cpu_isa; - -static const char *get_exit_reason(u64 exit_code) -{ - int table_size = ARRAY_SIZE(svm_exit_reasons); - struct exit_reasons_table *table = svm_exit_reasons; - - if (cpu_isa == 1) { - table = vmx_exit_reasons; - table_size = ARRAY_SIZE(vmx_exit_reasons); - } - - while (table_size--) { - if (table->exit_code == exit_code) - return table->reason; - table++; - } - - pr_err("unknown kvm exit code:%lld on %s\n", - (unsigned long long)exit_code, cpu_isa ? "VMX" : "SVM"); - return "UNKNOWN"; -} - -static void exit_event_decode_key(struct event_key *key, char decode[20]) -{ - const char *exit_reason = get_exit_reason(key->key); - - scnprintf(decode, 20, "%s", exit_reason); -} - -static struct kvm_events_ops exit_events = { - .is_begin_event = exit_event_begin, - .is_end_event = exit_event_end, - .decode_key = exit_event_decode_key, - .name = "VM-EXIT" -}; - - /* - * For the mmio events, we treat: - * the time of MMIO write: kvm_mmio(KVM_TRACE_MMIO_WRITE...) -> kvm_entry - * the time of MMIO read: kvm_exit -> kvm_mmio(KVM_TRACE_MMIO_READ...). - */ -static void mmio_event_get_key(struct perf_evsel *evsel, struct perf_sample *sample, - struct event_key *key) -{ - key->key = perf_evsel__intval(evsel, sample, "gpa"); - key->info = perf_evsel__intval(evsel, sample, "type"); -} - -#define KVM_TRACE_MMIO_READ_UNSATISFIED 0 -#define KVM_TRACE_MMIO_READ 1 -#define KVM_TRACE_MMIO_WRITE 2 - -static bool mmio_event_begin(struct perf_evsel *evsel, - struct perf_sample *sample, struct event_key *key) -{ - /* MMIO read begin event in kernel. */ - if (kvm_exit_event(evsel)) - return true; - - /* MMIO write begin event in kernel. */ - if (!strcmp(evsel->name, "kvm:kvm_mmio") && - perf_evsel__intval(evsel, sample, "type") == KVM_TRACE_MMIO_WRITE) { - mmio_event_get_key(evsel, sample, key); - return true; - } - - return false; -} - -static bool mmio_event_end(struct perf_evsel *evsel, struct perf_sample *sample, - struct event_key *key) -{ - /* MMIO write end event in kernel. */ - if (kvm_entry_event(evsel)) - return true; - - /* MMIO read end event in kernel.*/ - if (!strcmp(evsel->name, "kvm:kvm_mmio") && - perf_evsel__intval(evsel, sample, "type") == KVM_TRACE_MMIO_READ) { - mmio_event_get_key(evsel, sample, key); - return true; - } - - return false; -} - -static void mmio_event_decode_key(struct event_key *key, char decode[20]) -{ - scnprintf(decode, 20, "%#lx:%s", (unsigned long)key->key, - key->info == KVM_TRACE_MMIO_WRITE ? "W" : "R"); -} - -static struct kvm_events_ops mmio_events = { - .is_begin_event = mmio_event_begin, - .is_end_event = mmio_event_end, - .decode_key = mmio_event_decode_key, - .name = "MMIO Access" -}; - - /* The time of emulation pio access is from kvm_pio to kvm_entry. */ -static void ioport_event_get_key(struct perf_evsel *evsel, - struct perf_sample *sample, - struct event_key *key) -{ - key->key = perf_evsel__intval(evsel, sample, "port"); - key->info = perf_evsel__intval(evsel, sample, "rw"); -} - -static bool ioport_event_begin(struct perf_evsel *evsel, - struct perf_sample *sample, - struct event_key *key) -{ - if (!strcmp(evsel->name, "kvm:kvm_pio")) { - ioport_event_get_key(evsel, sample, key); - return true; - } - - return false; -} - -static bool ioport_event_end(struct perf_evsel *evsel, - struct perf_sample *sample __maybe_unused, - struct event_key *key __maybe_unused) -{ - return kvm_entry_event(evsel); -} - -static void ioport_event_decode_key(struct event_key *key, char decode[20]) -{ - scnprintf(decode, 20, "%#llx:%s", (unsigned long long)key->key, - key->info ? "POUT" : "PIN"); -} - -static struct kvm_events_ops ioport_events = { - .is_begin_event = ioport_event_begin, - .is_end_event = ioport_event_end, - .decode_key = ioport_event_decode_key, - .name = "IO Port Access" -}; - -static const char *report_event = "vmexit"; -struct kvm_events_ops *events_ops; - -static bool register_kvm_events_ops(void) -{ - bool ret = true; - - if (!strcmp(report_event, "vmexit")) - events_ops = &exit_events; - else if (!strcmp(report_event, "mmio")) - events_ops = &mmio_events; - else if (!strcmp(report_event, "ioport")) - events_ops = &ioport_events; - else { - pr_err("Unknown report event:%s\n", report_event); - ret = false; - } - - return ret; -} - -struct kvm_event_stats { - u64 time; - struct stats stats; -}; - -struct kvm_event { - struct list_head hash_entry; - struct rb_node rb; - - struct event_key key; - - struct kvm_event_stats total; - - #define DEFAULT_VCPU_NUM 8 - int max_vcpu; - struct kvm_event_stats *vcpu; -}; - -struct vcpu_event_record { - int vcpu_id; - u64 start_time; - struct kvm_event *last_event; -}; - -#define EVENTS_BITS 12 -#define EVENTS_CACHE_SIZE (1UL << EVENTS_BITS) - -static u64 total_time; -static u64 total_count; -static struct list_head kvm_events_cache[EVENTS_CACHE_SIZE]; - -static void init_kvm_event_record(void) -{ - int i; - - for (i = 0; i < (int)EVENTS_CACHE_SIZE; i++) - INIT_LIST_HEAD(&kvm_events_cache[i]); -} - -static int kvm_events_hash_fn(u64 key) -{ - return key & (EVENTS_CACHE_SIZE - 1); -} - -static bool kvm_event_expand(struct kvm_event *event, int vcpu_id) -{ - int old_max_vcpu = event->max_vcpu; - - if (vcpu_id < event->max_vcpu) - return true; - - while (event->max_vcpu <= vcpu_id) - event->max_vcpu += DEFAULT_VCPU_NUM; - - event->vcpu = realloc(event->vcpu, - event->max_vcpu * sizeof(*event->vcpu)); - if (!event->vcpu) { - pr_err("Not enough memory\n"); - return false; - } - - memset(event->vcpu + old_max_vcpu, 0, - (event->max_vcpu - old_max_vcpu) * sizeof(*event->vcpu)); - return true; -} - -static struct kvm_event *kvm_alloc_init_event(struct event_key *key) -{ - struct kvm_event *event; - - event = zalloc(sizeof(*event)); - if (!event) { - pr_err("Not enough memory\n"); - return NULL; - } - - event->key = *key; - return event; -} - -static struct kvm_event *find_create_kvm_event(struct event_key *key) -{ - struct kvm_event *event; - struct list_head *head; - - BUG_ON(key->key == INVALID_KEY); - - head = &kvm_events_cache[kvm_events_hash_fn(key->key)]; - list_for_each_entry(event, head, hash_entry) - if (event->key.key == key->key && event->key.info == key->info) - return event; - - event = kvm_alloc_init_event(key); - if (!event) - return NULL; - - list_add(&event->hash_entry, head); - return event; -} - -static bool handle_begin_event(struct vcpu_event_record *vcpu_record, - struct event_key *key, u64 timestamp) -{ - struct kvm_event *event = NULL; - - if (key->key != INVALID_KEY) - event = find_create_kvm_event(key); - - vcpu_record->last_event = event; - vcpu_record->start_time = timestamp; - return true; -} - -static void -kvm_update_event_stats(struct kvm_event_stats *kvm_stats, u64 time_diff) -{ - kvm_stats->time += time_diff; - update_stats(&kvm_stats->stats, time_diff); -} - -static double kvm_event_rel_stddev(int vcpu_id, struct kvm_event *event) -{ - struct kvm_event_stats *kvm_stats = &event->total; - - if (vcpu_id != -1) - kvm_stats = &event->vcpu[vcpu_id]; - - return rel_stddev_stats(stddev_stats(&kvm_stats->stats), - avg_stats(&kvm_stats->stats)); -} - -static bool update_kvm_event(struct kvm_event *event, int vcpu_id, - u64 time_diff) -{ - kvm_update_event_stats(&event->total, time_diff); - - if (!kvm_event_expand(event, vcpu_id)) - return false; - - kvm_update_event_stats(&event->vcpu[vcpu_id], time_diff); - return true; -} - -static bool handle_end_event(struct vcpu_event_record *vcpu_record, - struct event_key *key, u64 timestamp) -{ - struct kvm_event *event; - u64 time_begin, time_diff; - - event = vcpu_record->last_event; - time_begin = vcpu_record->start_time; - - /* The begin event is not caught. */ - if (!time_begin) - return true; - - /* - * In some case, the 'begin event' only records the start timestamp, - * the actual event is recognized in the 'end event' (e.g. mmio-event). - */ - - /* Both begin and end events did not get the key. */ - if (!event && key->key == INVALID_KEY) - return true; - - if (!event) - event = find_create_kvm_event(key); - - if (!event) - return false; - - vcpu_record->last_event = NULL; - vcpu_record->start_time = 0; - - BUG_ON(timestamp < time_begin); - - time_diff = timestamp - time_begin; - return update_kvm_event(event, vcpu_record->vcpu_id, time_diff); -} - -static -struct vcpu_event_record *per_vcpu_record(struct thread *thread, - struct perf_evsel *evsel, - struct perf_sample *sample) -{ - /* Only kvm_entry records vcpu id. */ - if (!thread->priv && kvm_entry_event(evsel)) { - struct vcpu_event_record *vcpu_record; - - vcpu_record = zalloc(sizeof(*vcpu_record)); - if (!vcpu_record) { - pr_err("%s: Not enough memory\n", __func__); - return NULL; - } - - vcpu_record->vcpu_id = perf_evsel__intval(evsel, sample, "vcpu_id"); - thread->priv = vcpu_record; - } - - return thread->priv; -} - -static bool handle_kvm_event(struct thread *thread, struct perf_evsel *evsel, - struct perf_sample *sample) -{ - struct vcpu_event_record *vcpu_record; - struct event_key key = {.key = INVALID_KEY}; - - vcpu_record = per_vcpu_record(thread, evsel, sample); - if (!vcpu_record) - return true; - - if (events_ops->is_begin_event(evsel, sample, &key)) - return handle_begin_event(vcpu_record, &key, sample->time); - - if (events_ops->is_end_event(evsel, sample, &key)) - return handle_end_event(vcpu_record, &key, sample->time); - - return true; -} - -typedef int (*key_cmp_fun)(struct kvm_event*, struct kvm_event*, int); -struct kvm_event_key { - const char *name; - key_cmp_fun key; -}; - -static int trace_vcpu = -1; -#define GET_EVENT_KEY(func, field) \ -static u64 get_event_ ##func(struct kvm_event *event, int vcpu) \ -{ \ - if (vcpu == -1) \ - return event->total.field; \ - \ - if (vcpu >= event->max_vcpu) \ - return 0; \ - \ - return event->vcpu[vcpu].field; \ -} - -#define COMPARE_EVENT_KEY(func, field) \ -GET_EVENT_KEY(func, field) \ -static int compare_kvm_event_ ## func(struct kvm_event *one, \ - struct kvm_event *two, int vcpu)\ -{ \ - return get_event_ ##func(one, vcpu) > \ - get_event_ ##func(two, vcpu); \ -} - -GET_EVENT_KEY(time, time); -COMPARE_EVENT_KEY(count, stats.n); -COMPARE_EVENT_KEY(mean, stats.mean); - -#define DEF_SORT_NAME_KEY(name, compare_key) \ - { #name, compare_kvm_event_ ## compare_key } - -static struct kvm_event_key keys[] = { - DEF_SORT_NAME_KEY(sample, count), - DEF_SORT_NAME_KEY(time, mean), - { NULL, NULL } -}; - -static const char *sort_key = "sample"; -static key_cmp_fun compare; - -static bool select_key(void) -{ - int i; - - for (i = 0; keys[i].name; i++) { - if (!strcmp(keys[i].name, sort_key)) { - compare = keys[i].key; - return true; - } - } - - pr_err("Unknown compare key:%s\n", sort_key); - return false; -} - -static struct rb_root result; -static void insert_to_result(struct kvm_event *event, key_cmp_fun bigger, - int vcpu) -{ - struct rb_node **rb = &result.rb_node; - struct rb_node *parent = NULL; - struct kvm_event *p; - - while (*rb) { - p = container_of(*rb, struct kvm_event, rb); - parent = *rb; - - if (bigger(event, p, vcpu)) - rb = &(*rb)->rb_left; - else - rb = &(*rb)->rb_right; - } - - rb_link_node(&event->rb, parent, rb); - rb_insert_color(&event->rb, &result); -} - -static void update_total_count(struct kvm_event *event, int vcpu) -{ - total_count += get_event_count(event, vcpu); - total_time += get_event_time(event, vcpu); -} - -static bool event_is_valid(struct kvm_event *event, int vcpu) -{ - return !!get_event_count(event, vcpu); -} - -static void sort_result(int vcpu) -{ - unsigned int i; - struct kvm_event *event; - - for (i = 0; i < EVENTS_CACHE_SIZE; i++) - list_for_each_entry(event, &kvm_events_cache[i], hash_entry) - if (event_is_valid(event, vcpu)) { - update_total_count(event, vcpu); - insert_to_result(event, compare, vcpu); - } -} - -/* returns left most element of result, and erase it */ -static struct kvm_event *pop_from_result(void) -{ - struct rb_node *node = rb_first(&result); - - if (!node) - return NULL; - - rb_erase(node, &result); - return container_of(node, struct kvm_event, rb); -} - -static void print_vcpu_info(int vcpu) -{ - pr_info("Analyze events for "); - - if (vcpu == -1) - pr_info("all VCPUs:\n\n"); - else - pr_info("VCPU %d:\n\n", vcpu); -} - -static void print_result(int vcpu) -{ - char decode[20]; - struct kvm_event *event; - - pr_info("\n\n"); - print_vcpu_info(vcpu); - pr_info("%20s ", events_ops->name); - pr_info("%10s ", "Samples"); - pr_info("%9s ", "Samples%"); - - pr_info("%9s ", "Time%"); - pr_info("%16s ", "Avg time"); - pr_info("\n\n"); - - while ((event = pop_from_result())) { - u64 ecount, etime; - - ecount = get_event_count(event, vcpu); - etime = get_event_time(event, vcpu); - - events_ops->decode_key(&event->key, decode); - pr_info("%20s ", decode); - pr_info("%10llu ", (unsigned long long)ecount); - pr_info("%8.2f%% ", (double)ecount / total_count * 100); - pr_info("%8.2f%% ", (double)etime / total_time * 100); - pr_info("%9.2fus ( +-%7.2f%% )", (double)etime / ecount/1e3, - kvm_event_rel_stddev(vcpu, event)); - pr_info("\n"); - } - - pr_info("\nTotal Samples:%lld, Total events handled time:%.2fus.\n\n", - (unsigned long long)total_count, total_time / 1e3); -} - -static int process_sample_event(struct perf_tool *tool __maybe_unused, - union perf_event *event, - struct perf_sample *sample, - struct perf_evsel *evsel, - struct machine *machine) -{ - struct thread *thread = machine__findnew_thread(machine, sample->tid); - - if (thread == NULL) { - pr_debug("problem processing %d event, skipping it.\n", - event->header.type); - return -1; - } - - if (!handle_kvm_event(thread, evsel, sample)) - return -1; - - return 0; -} - -static struct perf_tool eops = { - .sample = process_sample_event, - .comm = perf_event__process_comm, - .ordered_samples = true, -}; - -static int get_cpu_isa(struct perf_session *session) -{ - char *cpuid = session->header.env.cpuid; - int isa; - - if (strstr(cpuid, "Intel")) - isa = 1; - else if (strstr(cpuid, "AMD")) - isa = 0; - else { - pr_err("CPU %s is not supported.\n", cpuid); - isa = -ENOTSUP; - } - - return isa; -} - -static const char *file_name; - -static int read_events(void) -{ - struct perf_session *kvm_session; - int ret; - - kvm_session = perf_session__new(file_name, O_RDONLY, 0, false, &eops); - if (!kvm_session) { - pr_err("Initializing perf session failed\n"); - return -EINVAL; - } - - if (!perf_session__has_traces(kvm_session, "kvm record")) - return -EINVAL; - - /* - * Do not use 'isa' recorded in kvm_exit tracepoint since it is not - * traced in the old kernel. - */ - ret = get_cpu_isa(kvm_session); - - if (ret < 0) - return ret; - - cpu_isa = ret; - - return perf_session__process_events(kvm_session, &eops); -} - -static bool verify_vcpu(int vcpu) -{ - if (vcpu != -1 && vcpu < 0) { - pr_err("Invalid vcpu:%d.\n", vcpu); - return false; - } - - return true; -} - -static int kvm_events_report_vcpu(int vcpu) -{ - int ret = -EINVAL; - - if (!verify_vcpu(vcpu)) - goto exit; - - if (!select_key()) - goto exit; - - if (!register_kvm_events_ops()) - goto exit; - - init_kvm_event_record(); - setup_pager(); - - ret = read_events(); - if (ret) - goto exit; - - sort_result(vcpu); - print_result(vcpu); -exit: - return ret; -} - -static const char * const record_args[] = { - "record", - "-R", - "-f", - "-m", "1024", - "-c", "1", - "-e", "kvm:kvm_entry", - "-e", "kvm:kvm_exit", - "-e", "kvm:kvm_mmio", - "-e", "kvm:kvm_pio", -}; - -#define STRDUP_FAIL_EXIT(s) \ - ({ char *_p; \ - _p = strdup(s); \ - if (!_p) \ - return -ENOMEM; \ - _p; \ - }) - -static int kvm_events_record(int argc, const char **argv) -{ - unsigned int rec_argc, i, j; - const char **rec_argv; - - rec_argc = ARRAY_SIZE(record_args) + argc + 2; - rec_argv = calloc(rec_argc + 1, sizeof(char *)); - - if (rec_argv == NULL) - return -ENOMEM; - - for (i = 0; i < ARRAY_SIZE(record_args); i++) - rec_argv[i] = STRDUP_FAIL_EXIT(record_args[i]); - - rec_argv[i++] = STRDUP_FAIL_EXIT("-o"); - rec_argv[i++] = STRDUP_FAIL_EXIT(file_name); - - for (j = 1; j < (unsigned int)argc; j++, i++) - rec_argv[i] = argv[j]; - - return cmd_record(i, rec_argv, NULL); -} - -static const char * const kvm_events_report_usage[] = { - "perf kvm stat report []", - NULL -}; - -static const struct option kvm_events_report_options[] = { - OPT_STRING(0, "event", &report_event, "report event", - "event for reporting: vmexit, mmio, ioport"), - OPT_INTEGER(0, "vcpu", &trace_vcpu, - "vcpu id to report"), - OPT_STRING('k', "key", &sort_key, "sort-key", - "key for sorting: sample(sort by samples number)" - " time (sort by avg time)"), - OPT_END() -}; - -static int kvm_events_report(int argc, const char **argv) -{ - symbol__init(); - - if (argc) { - argc = parse_options(argc, argv, - kvm_events_report_options, - kvm_events_report_usage, 0); - if (argc) - usage_with_options(kvm_events_report_usage, - kvm_events_report_options); - } - - return kvm_events_report_vcpu(trace_vcpu); -} - -static void print_kvm_stat_usage(void) -{ - printf("Usage: perf kvm stat \n\n"); - - printf("# Available commands:\n"); - printf("\trecord: record kvm events\n"); - printf("\treport: report statistical data of kvm events\n"); - - printf("\nOtherwise, it is the alias of 'perf stat':\n"); -} - -static int kvm_cmd_stat(int argc, const char **argv) -{ - if (argc == 1) { - print_kvm_stat_usage(); - goto perf_stat; - } - - if (!strncmp(argv[1], "rec", 3)) - return kvm_events_record(argc - 1, argv + 1); - - if (!strncmp(argv[1], "rep", 3)) - return kvm_events_report(argc - 1 , argv + 1); - -perf_stat: - return cmd_stat(argc, argv, NULL); -} - +static const char *file_name; static char name_buffer[256]; static const char * const kvm_usage[] = { - "perf kvm [] {top|record|report|diff|buildid-list|stat}", + "perf kvm [] {top|record|report|diff|buildid-list}", NULL }; @@ -930,7 +102,7 @@ static int __cmd_buildid_list(int argc, const char **argv) return cmd_buildid_list(i, rec_argv, NULL); } -int cmd_kvm(int argc, const char **argv, const char *prefix __maybe_unused) +int cmd_kvm(int argc, const char **argv, const char *prefix __used) { perf_host = 0; perf_guest = 1; @@ -963,8 +135,6 @@ int cmd_kvm(int argc, const char **argv, const char *prefix __maybe_unused) return cmd_top(argc, argv, NULL); else if (!strncmp(argv[0], "buildid-list", 12)) return __cmd_buildid_list(argc, argv); - else if (!strncmp(argv[0], "stat", 4)) - return kvm_cmd_stat(argc, argv); else usage_with_options(kvm_usage, kvm_options); diff --git a/trunk/tools/perf/builtin-list.c b/trunk/tools/perf/builtin-list.c index 1948eceb517a..6313b6eb3ebb 100644 --- a/trunk/tools/perf/builtin-list.c +++ b/trunk/tools/perf/builtin-list.c @@ -14,20 +14,20 @@ #include "util/parse-events.h" #include "util/cache.h" -int cmd_list(int argc, const char **argv, const char *prefix __maybe_unused) +int cmd_list(int argc, const char **argv, const char *prefix __used) { setup_pager(); if (argc == 1) - print_events(NULL, false); + print_events(NULL); else { int i; for (i = 1; i < argc; ++i) { - if (i > 2) + if (i > 1) putchar('\n'); if (strncmp(argv[i], "tracepoint", 10) == 0) - print_tracepoint_events(NULL, NULL, false); + print_tracepoint_events(NULL, NULL); else if (strcmp(argv[i], "hw") == 0 || strcmp(argv[i], "hardware") == 0) print_events_type(PERF_TYPE_HARDWARE); @@ -36,15 +36,13 @@ int cmd_list(int argc, const char **argv, const char *prefix __maybe_unused) print_events_type(PERF_TYPE_SOFTWARE); else if (strcmp(argv[i], "cache") == 0 || strcmp(argv[i], "hwcache") == 0) - print_hwcache_events(NULL, false); - else if (strcmp(argv[i], "--raw-dump") == 0) - print_events(NULL, true); + print_hwcache_events(NULL); else { char *sep = strchr(argv[i], ':'), *s; int sep_idx; if (sep == NULL) { - print_events(argv[i], false); + print_events(argv[i]); continue; } sep_idx = sep - argv[i]; @@ -53,7 +51,7 @@ int cmd_list(int argc, const char **argv, const char *prefix __maybe_unused) return -1; s[sep_idx] = '\0'; - print_tracepoint_events(s, s + sep_idx + 1, false); + print_tracepoint_events(s, s + sep_idx + 1); free(s); } } diff --git a/trunk/tools/perf/builtin-lock.c b/trunk/tools/perf/builtin-lock.c index 7d6e09949880..b3c428548868 100644 --- a/trunk/tools/perf/builtin-lock.c +++ b/trunk/tools/perf/builtin-lock.c @@ -1,8 +1,6 @@ #include "builtin.h" #include "perf.h" -#include "util/evlist.h" -#include "util/evsel.h" #include "util/util.h" #include "util/cache.h" #include "util/symbol.h" @@ -42,7 +40,7 @@ struct lock_stat { struct rb_node rb; /* used for sorting */ /* - * FIXME: perf_evsel__intval() returns u64, + * FIXME: raw_field_value() returns unsigned long long, * so address of lockdep_map should be dealed as 64bit. * Is there more better solution? */ @@ -162,10 +160,8 @@ static struct thread_stat *thread_stat_findnew_after_first(u32 tid) return st; st = zalloc(sizeof(struct thread_stat)); - if (!st) { - pr_err("memory allocation failed\n"); - return NULL; - } + if (!st) + die("memory allocation failed\n"); st->tid = tid; INIT_LIST_HEAD(&st->seq_list); @@ -184,10 +180,8 @@ static struct thread_stat *thread_stat_findnew_first(u32 tid) struct thread_stat *st; st = zalloc(sizeof(struct thread_stat)); - if (!st) { - pr_err("memory allocation failed\n"); - return NULL; - } + if (!st) + die("memory allocation failed\n"); st->tid = tid; INIT_LIST_HEAD(&st->seq_list); @@ -253,20 +247,18 @@ struct lock_key keys[] = { { NULL, NULL } }; -static int select_key(void) +static void select_key(void) { int i; for (i = 0; keys[i].name; i++) { if (!strcmp(keys[i].name, sort_key)) { compare = keys[i].key; - return 0; + return; } } - pr_err("Unknown compare key: %s\n", sort_key); - - return -1; + die("Unknown compare key:%s\n", sort_key); } static void insert_to_result(struct lock_stat *st, @@ -331,24 +323,61 @@ static struct lock_stat *lock_stat_findnew(void *addr, const char *name) return new; alloc_failed: - pr_err("memory allocation failed\n"); - return NULL; + die("memory allocation failed\n"); } static const char *input_name; -struct trace_lock_handler { - int (*acquire_event)(struct perf_evsel *evsel, - struct perf_sample *sample); +struct raw_event_sample { + u32 size; + char data[0]; +}; + +struct trace_acquire_event { + void *addr; + const char *name; + int flag; +}; + +struct trace_acquired_event { + void *addr; + const char *name; +}; - int (*acquired_event)(struct perf_evsel *evsel, - struct perf_sample *sample); +struct trace_contended_event { + void *addr; + const char *name; +}; - int (*contended_event)(struct perf_evsel *evsel, - struct perf_sample *sample); +struct trace_release_event { + void *addr; + const char *name; +}; - int (*release_event)(struct perf_evsel *evsel, - struct perf_sample *sample); +struct trace_lock_handler { + void (*acquire_event)(struct trace_acquire_event *, + struct event_format *, + int cpu, + u64 timestamp, + struct thread *thread); + + void (*acquired_event)(struct trace_acquired_event *, + struct event_format *, + int cpu, + u64 timestamp, + struct thread *thread); + + void (*contended_event)(struct trace_contended_event *, + struct event_format *, + int cpu, + u64 timestamp, + struct thread *thread); + + void (*release_event)(struct trace_release_event *, + struct event_format *, + int cpu, + u64 timestamp, + struct thread *thread); }; static struct lock_seq_stat *get_seq(struct thread_stat *ts, void *addr) @@ -361,10 +390,8 @@ static struct lock_seq_stat *get_seq(struct thread_stat *ts, void *addr) } seq = zalloc(sizeof(struct lock_seq_stat)); - if (!seq) { - pr_err("memory allocation failed\n"); - return NULL; - } + if (!seq) + die("Not enough memory\n"); seq->state = SEQ_STATE_UNINITIALIZED; seq->addr = addr; @@ -387,42 +414,33 @@ enum acquire_flags { READ_LOCK = 2, }; -static int report_lock_acquire_event(struct perf_evsel *evsel, - struct perf_sample *sample) +static void +report_lock_acquire_event(struct trace_acquire_event *acquire_event, + struct event_format *__event __used, + int cpu __used, + u64 timestamp __used, + struct thread *thread __used) { - void *addr; struct lock_stat *ls; struct thread_stat *ts; struct lock_seq_stat *seq; - const char *name = perf_evsel__strval(evsel, sample, "name"); - u64 tmp = perf_evsel__intval(evsel, sample, "lockdep_addr"); - int flag = perf_evsel__intval(evsel, sample, "flag"); - - memcpy(&addr, &tmp, sizeof(void *)); - ls = lock_stat_findnew(addr, name); - if (!ls) - return -1; + ls = lock_stat_findnew(acquire_event->addr, acquire_event->name); if (ls->discard) - return 0; + return; - ts = thread_stat_findnew(sample->tid); - if (!ts) - return -1; - - seq = get_seq(ts, addr); - if (!seq) - return -1; + ts = thread_stat_findnew(thread->pid); + seq = get_seq(ts, acquire_event->addr); switch (seq->state) { case SEQ_STATE_UNINITIALIZED: case SEQ_STATE_RELEASED: - if (!flag) { + if (!acquire_event->flag) { seq->state = SEQ_STATE_ACQUIRING; } else { - if (flag & TRY_LOCK) + if (acquire_event->flag & TRY_LOCK) ls->nr_trylock++; - if (flag & READ_LOCK) + if (acquire_event->flag & READ_LOCK) ls->nr_readlock++; seq->state = SEQ_STATE_READ_ACQUIRED; seq->read_count = 1; @@ -430,7 +448,7 @@ static int report_lock_acquire_event(struct perf_evsel *evsel, } break; case SEQ_STATE_READ_ACQUIRED: - if (flag & READ_LOCK) { + if (acquire_event->flag & READ_LOCK) { seq->read_count++; ls->nr_acquired++; goto end; @@ -455,46 +473,38 @@ static int report_lock_acquire_event(struct perf_evsel *evsel, } ls->nr_acquire++; - seq->prev_event_time = sample->time; + seq->prev_event_time = timestamp; end: - return 0; + return; } -static int report_lock_acquired_event(struct perf_evsel *evsel, - struct perf_sample *sample) +static void +report_lock_acquired_event(struct trace_acquired_event *acquired_event, + struct event_format *__event __used, + int cpu __used, + u64 timestamp __used, + struct thread *thread __used) { - void *addr; struct lock_stat *ls; struct thread_stat *ts; struct lock_seq_stat *seq; u64 contended_term; - const char *name = perf_evsel__strval(evsel, sample, "name"); - u64 tmp = perf_evsel__intval(evsel, sample, "lockdep_addr"); - - memcpy(&addr, &tmp, sizeof(void *)); - ls = lock_stat_findnew(addr, name); - if (!ls) - return -1; + ls = lock_stat_findnew(acquired_event->addr, acquired_event->name); if (ls->discard) - return 0; - - ts = thread_stat_findnew(sample->tid); - if (!ts) - return -1; + return; - seq = get_seq(ts, addr); - if (!seq) - return -1; + ts = thread_stat_findnew(thread->pid); + seq = get_seq(ts, acquired_event->addr); switch (seq->state) { case SEQ_STATE_UNINITIALIZED: /* orphan event, do nothing */ - return 0; + return; case SEQ_STATE_ACQUIRING: break; case SEQ_STATE_CONTENDED: - contended_term = sample->time - seq->prev_event_time; + contended_term = timestamp - seq->prev_event_time; ls->wait_time_total += contended_term; if (contended_term < ls->wait_time_min) ls->wait_time_min = contended_term; @@ -519,41 +529,33 @@ static int report_lock_acquired_event(struct perf_evsel *evsel, seq->state = SEQ_STATE_ACQUIRED; ls->nr_acquired++; - seq->prev_event_time = sample->time; + seq->prev_event_time = timestamp; end: - return 0; + return; } -static int report_lock_contended_event(struct perf_evsel *evsel, - struct perf_sample *sample) +static void +report_lock_contended_event(struct trace_contended_event *contended_event, + struct event_format *__event __used, + int cpu __used, + u64 timestamp __used, + struct thread *thread __used) { - void *addr; struct lock_stat *ls; struct thread_stat *ts; struct lock_seq_stat *seq; - const char *name = perf_evsel__strval(evsel, sample, "name"); - u64 tmp = perf_evsel__intval(evsel, sample, "lockdep_addr"); - memcpy(&addr, &tmp, sizeof(void *)); - - ls = lock_stat_findnew(addr, name); - if (!ls) - return -1; + ls = lock_stat_findnew(contended_event->addr, contended_event->name); if (ls->discard) - return 0; - - ts = thread_stat_findnew(sample->tid); - if (!ts) - return -1; + return; - seq = get_seq(ts, addr); - if (!seq) - return -1; + ts = thread_stat_findnew(thread->pid); + seq = get_seq(ts, contended_event->addr); switch (seq->state) { case SEQ_STATE_UNINITIALIZED: /* orphan event, do nothing */ - return 0; + return; case SEQ_STATE_ACQUIRING: break; case SEQ_STATE_RELEASED: @@ -574,36 +576,28 @@ static int report_lock_contended_event(struct perf_evsel *evsel, seq->state = SEQ_STATE_CONTENDED; ls->nr_contended++; - seq->prev_event_time = sample->time; + seq->prev_event_time = timestamp; end: - return 0; + return; } -static int report_lock_release_event(struct perf_evsel *evsel, - struct perf_sample *sample) +static void +report_lock_release_event(struct trace_release_event *release_event, + struct event_format *__event __used, + int cpu __used, + u64 timestamp __used, + struct thread *thread __used) { - void *addr; struct lock_stat *ls; struct thread_stat *ts; struct lock_seq_stat *seq; - const char *name = perf_evsel__strval(evsel, sample, "name"); - u64 tmp = perf_evsel__intval(evsel, sample, "lockdep_addr"); - - memcpy(&addr, &tmp, sizeof(void *)); - ls = lock_stat_findnew(addr, name); - if (!ls) - return -1; + ls = lock_stat_findnew(release_event->addr, release_event->name); if (ls->discard) - return 0; - - ts = thread_stat_findnew(sample->tid); - if (!ts) - return -1; + return; - seq = get_seq(ts, addr); - if (!seq) - return -1; + ts = thread_stat_findnew(thread->pid); + seq = get_seq(ts, release_event->addr); switch (seq->state) { case SEQ_STATE_UNINITIALIZED: @@ -637,7 +631,7 @@ static int report_lock_release_event(struct perf_evsel *evsel, list_del(&seq->list); free(seq); end: - return 0; + return; } /* lock oriented handlers */ @@ -651,36 +645,96 @@ static struct trace_lock_handler report_lock_ops = { static struct trace_lock_handler *trace_handler; -static int perf_evsel__process_lock_acquire(struct perf_evsel *evsel, - struct perf_sample *sample) +static void +process_lock_acquire_event(void *data, + struct event_format *event __used, + int cpu __used, + u64 timestamp __used, + struct thread *thread __used) { + struct trace_acquire_event acquire_event; + u64 tmp; /* this is required for casting... */ + + tmp = raw_field_value(event, "lockdep_addr", data); + memcpy(&acquire_event.addr, &tmp, sizeof(void *)); + acquire_event.name = (char *)raw_field_ptr(event, "name", data); + acquire_event.flag = (int)raw_field_value(event, "flag", data); + if (trace_handler->acquire_event) - return trace_handler->acquire_event(evsel, sample); - return 0; + trace_handler->acquire_event(&acquire_event, event, cpu, timestamp, thread); } -static int perf_evsel__process_lock_acquired(struct perf_evsel *evsel, - struct perf_sample *sample) +static void +process_lock_acquired_event(void *data, + struct event_format *event __used, + int cpu __used, + u64 timestamp __used, + struct thread *thread __used) { - if (trace_handler->acquired_event) - return trace_handler->acquired_event(evsel, sample); - return 0; + struct trace_acquired_event acquired_event; + u64 tmp; /* this is required for casting... */ + + tmp = raw_field_value(event, "lockdep_addr", data); + memcpy(&acquired_event.addr, &tmp, sizeof(void *)); + acquired_event.name = (char *)raw_field_ptr(event, "name", data); + + if (trace_handler->acquire_event) + trace_handler->acquired_event(&acquired_event, event, cpu, timestamp, thread); } -static int perf_evsel__process_lock_contended(struct perf_evsel *evsel, - struct perf_sample *sample) +static void +process_lock_contended_event(void *data, + struct event_format *event __used, + int cpu __used, + u64 timestamp __used, + struct thread *thread __used) { - if (trace_handler->contended_event) - return trace_handler->contended_event(evsel, sample); - return 0; + struct trace_contended_event contended_event; + u64 tmp; /* this is required for casting... */ + + tmp = raw_field_value(event, "lockdep_addr", data); + memcpy(&contended_event.addr, &tmp, sizeof(void *)); + contended_event.name = (char *)raw_field_ptr(event, "name", data); + + if (trace_handler->acquire_event) + trace_handler->contended_event(&contended_event, event, cpu, timestamp, thread); } -static int perf_evsel__process_lock_release(struct perf_evsel *evsel, - struct perf_sample *sample) +static void +process_lock_release_event(void *data, + struct event_format *event __used, + int cpu __used, + u64 timestamp __used, + struct thread *thread __used) { - if (trace_handler->release_event) - return trace_handler->release_event(evsel, sample); - return 0; + struct trace_release_event release_event; + u64 tmp; /* this is required for casting... */ + + tmp = raw_field_value(event, "lockdep_addr", data); + memcpy(&release_event.addr, &tmp, sizeof(void *)); + release_event.name = (char *)raw_field_ptr(event, "name", data); + + if (trace_handler->acquire_event) + trace_handler->release_event(&release_event, event, cpu, timestamp, thread); +} + +static void +process_raw_event(void *data, int cpu, u64 timestamp, struct thread *thread) +{ + struct event_format *event; + int type; + + type = trace_parse_common_type(session->pevent, data); + event = pevent_find_event(session->pevent, type); + + if (!strcmp(event->name, "lock_acquire")) + process_lock_acquire_event(data, event, cpu, timestamp, thread); + if (!strcmp(event->name, "lock_acquired")) + process_lock_acquired_event(data, event, cpu, timestamp, thread); + if (!strcmp(event->name, "lock_contended")) + process_lock_contended_event(data, event, cpu, timestamp, thread); + if (!strcmp(event->name, "lock_release")) + process_lock_release_event(data, event, cpu, timestamp, thread); } static void print_bad_events(int bad, int total) @@ -782,29 +836,20 @@ static void dump_map(void) } } -static int dump_info(void) +static void dump_info(void) { - int rc = 0; - if (info_threads) dump_threads(); else if (info_map) dump_map(); - else { - rc = -1; - pr_err("Unknown type of information\n"); - } - - return rc; + else + die("Unknown type of information\n"); } -typedef int (*tracepoint_handler)(struct perf_evsel *evsel, - struct perf_sample *sample); - -static int process_sample_event(struct perf_tool *tool __maybe_unused, +static int process_sample_event(struct perf_tool *tool __used, union perf_event *event, struct perf_sample *sample, - struct perf_evsel *evsel, + struct perf_evsel *evsel __used, struct machine *machine) { struct thread *thread = machine__findnew_thread(machine, sample->tid); @@ -815,10 +860,7 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused, return -1; } - if (evsel->handler.func != NULL) { - tracepoint_handler f = evsel->handler.func; - return f(evsel, sample); - } + process_raw_event(sample->raw_data, sample->cpu, sample->time, thread); return 0; } @@ -829,25 +871,11 @@ static struct perf_tool eops = { .ordered_samples = true, }; -static const struct perf_evsel_str_handler lock_tracepoints[] = { - { "lock:lock_acquire", perf_evsel__process_lock_acquire, }, /* CONFIG_LOCKDEP */ - { "lock:lock_acquired", perf_evsel__process_lock_acquired, }, /* CONFIG_LOCKDEP, CONFIG_LOCK_STAT */ - { "lock:lock_contended", perf_evsel__process_lock_contended, }, /* CONFIG_LOCKDEP, CONFIG_LOCK_STAT */ - { "lock:lock_release", perf_evsel__process_lock_release, }, /* CONFIG_LOCKDEP */ -}; - static int read_events(void) { session = perf_session__new(input_name, O_RDONLY, 0, false, &eops); - if (!session) { - pr_err("Initializing perf session failed\n"); - return -1; - } - - if (perf_session__set_tracepoints_handlers(session, lock_tracepoints)) { - pr_err("Initializing perf session tracepoint handlers failed\n"); - return -1; - } + if (!session) + die("Initializing perf session failed\n"); return perf_session__process_events(session, &eops); } @@ -864,18 +892,13 @@ static void sort_result(void) } } -static int __cmd_report(void) +static void __cmd_report(void) { setup_pager(); - - if ((select_key() != 0) || - (read_events() != 0)) - return -1; - + select_key(); + read_events(); sort_result(); print_result(); - - return 0; } static const char * const report_usage[] = { @@ -921,6 +944,10 @@ static const char *record_args[] = { "-f", "-m", "1024", "-c", "1", + "-e", "lock:lock_acquire", + "-e", "lock:lock_acquired", + "-e", "lock:lock_contended", + "-e", "lock:lock_release", }; static int __cmd_record(int argc, const char **argv) @@ -928,31 +955,15 @@ static int __cmd_record(int argc, const char **argv) unsigned int rec_argc, i, j; const char **rec_argv; - for (i = 0; i < ARRAY_SIZE(lock_tracepoints); i++) { - if (!is_valid_tracepoint(lock_tracepoints[i].name)) { - pr_err("tracepoint %s is not enabled. " - "Are CONFIG_LOCKDEP and CONFIG_LOCK_STAT enabled?\n", - lock_tracepoints[i].name); - return 1; - } - } - rec_argc = ARRAY_SIZE(record_args) + argc - 1; - /* factor of 2 is for -e in front of each tracepoint */ - rec_argc += 2 * ARRAY_SIZE(lock_tracepoints); - rec_argv = calloc(rec_argc + 1, sizeof(char *)); + if (rec_argv == NULL) return -ENOMEM; for (i = 0; i < ARRAY_SIZE(record_args); i++) rec_argv[i] = strdup(record_args[i]); - for (j = 0; j < ARRAY_SIZE(lock_tracepoints); j++) { - rec_argv[i++] = "-e"; - rec_argv[i++] = strdup(lock_tracepoints[j].name); - } - for (j = 1; j < (unsigned int)argc; j++, i++) rec_argv[i] = argv[j]; @@ -961,10 +972,9 @@ static int __cmd_record(int argc, const char **argv) return cmd_record(i, rec_argv, NULL); } -int cmd_lock(int argc, const char **argv, const char *prefix __maybe_unused) +int cmd_lock(int argc, const char **argv, const char *prefix __used) { unsigned int i; - int rc = 0; symbol__init(); for (i = 0; i < LOCKHASH_SIZE; i++) @@ -999,13 +1009,11 @@ int cmd_lock(int argc, const char **argv, const char *prefix __maybe_unused) /* recycling report_lock_ops */ trace_handler = &report_lock_ops; setup_pager(); - if (read_events() != 0) - rc = -1; - else - rc = dump_info(); + read_events(); + dump_info(); } else { usage_with_options(lock_usage, lock_options); } - return rc; + return 0; } diff --git a/trunk/tools/perf/builtin-probe.c b/trunk/tools/perf/builtin-probe.c index 118aa8946573..e215ae61b2ae 100644 --- a/trunk/tools/perf/builtin-probe.c +++ b/trunk/tools/perf/builtin-probe.c @@ -143,8 +143,8 @@ static int parse_probe_event_argv(int argc, const char **argv) return ret; } -static int opt_add_probe_event(const struct option *opt __maybe_unused, - const char *str, int unset __maybe_unused) +static int opt_add_probe_event(const struct option *opt __used, + const char *str, int unset __used) { if (str) { params.mod_events = true; @@ -153,8 +153,8 @@ static int opt_add_probe_event(const struct option *opt __maybe_unused, return 0; } -static int opt_del_probe_event(const struct option *opt __maybe_unused, - const char *str, int unset __maybe_unused) +static int opt_del_probe_event(const struct option *opt __used, + const char *str, int unset __used) { if (str) { params.mod_events = true; @@ -166,7 +166,7 @@ static int opt_del_probe_event(const struct option *opt __maybe_unused, } static int opt_set_target(const struct option *opt, const char *str, - int unset __maybe_unused) + int unset __used) { int ret = -ENOENT; @@ -188,8 +188,8 @@ static int opt_set_target(const struct option *opt, const char *str, } #ifdef DWARF_SUPPORT -static int opt_show_lines(const struct option *opt __maybe_unused, - const char *str, int unset __maybe_unused) +static int opt_show_lines(const struct option *opt __used, + const char *str, int unset __used) { int ret = 0; @@ -209,8 +209,8 @@ static int opt_show_lines(const struct option *opt __maybe_unused, return ret; } -static int opt_show_vars(const struct option *opt __maybe_unused, - const char *str, int unset __maybe_unused) +static int opt_show_vars(const struct option *opt __used, + const char *str, int unset __used) { struct perf_probe_event *pev = ¶ms.events[params.nevents]; int ret; @@ -229,8 +229,8 @@ static int opt_show_vars(const struct option *opt __maybe_unused, } #endif -static int opt_set_filter(const struct option *opt __maybe_unused, - const char *str, int unset __maybe_unused) +static int opt_set_filter(const struct option *opt __used, + const char *str, int unset __used) { const char *err; @@ -327,7 +327,7 @@ static const struct option options[] = { OPT_END() }; -int cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused) +int cmd_probe(int argc, const char **argv, const char *prefix __used) { int ret; diff --git a/trunk/tools/perf/builtin-record.c b/trunk/tools/perf/builtin-record.c index f14cb5fdb91f..f5a6452931e6 100644 --- a/trunk/tools/perf/builtin-record.c +++ b/trunk/tools/perf/builtin-record.c @@ -31,15 +31,6 @@ #include #include -#define CALLCHAIN_HELP "do call-graph (stack chain/backtrace) recording: " - -#ifdef NO_LIBUNWIND_SUPPORT -static char callchain_help[] = CALLCHAIN_HELP "[fp]"; -#else -static unsigned long default_stack_dump_size = 8192; -static char callchain_help[] = CALLCHAIN_HELP "[fp] dwarf"; -#endif - enum write_mode_t { WRITE_FORCE, WRITE_APPEND @@ -71,38 +62,32 @@ static void advance_output(struct perf_record *rec, size_t size) rec->bytes_written += size; } -static int write_output(struct perf_record *rec, void *buf, size_t size) +static void write_output(struct perf_record *rec, void *buf, size_t size) { while (size) { int ret = write(rec->output, buf, size); - if (ret < 0) { - pr_err("failed to write\n"); - return -1; - } + if (ret < 0) + die("failed to write"); size -= ret; buf += ret; rec->bytes_written += ret; } - - return 0; } static int process_synthesized_event(struct perf_tool *tool, union perf_event *event, - struct perf_sample *sample __maybe_unused, - struct machine *machine __maybe_unused) + struct perf_sample *sample __used, + struct machine *machine __used) { struct perf_record *rec = container_of(tool, struct perf_record, tool); - if (write_output(rec, event, event->header.size) < 0) - return -1; - + write_output(rec, event, event->header.size); return 0; } -static int perf_record__mmap_read(struct perf_record *rec, +static void perf_record__mmap_read(struct perf_record *rec, struct perf_mmap *md) { unsigned int head = perf_mmap__read_head(md); @@ -110,10 +95,9 @@ static int perf_record__mmap_read(struct perf_record *rec, unsigned char *data = md->base + rec->page_size; unsigned long size; void *buf; - int rc = 0; if (old == head) - return 0; + return; rec->samples++; @@ -124,26 +108,17 @@ static int perf_record__mmap_read(struct perf_record *rec, size = md->mask + 1 - (old & md->mask); old += size; - if (write_output(rec, buf, size) < 0) { - rc = -1; - goto out; - } + write_output(rec, buf, size); } buf = &data[old & md->mask]; size = head - old; old += size; - if (write_output(rec, buf, size) < 0) { - rc = -1; - goto out; - } + write_output(rec, buf, size); md->prev = old; perf_mmap__write_tail(md, old); - -out: - return rc; } static volatile int done = 0; @@ -159,7 +134,7 @@ static void sig_handler(int sig) signr = sig; } -static void perf_record__sig_exit(int exit_status __maybe_unused, void *arg) +static void perf_record__sig_exit(int exit_status __used, void *arg) { struct perf_record *rec = arg; int status; @@ -188,32 +163,31 @@ static bool perf_evlist__equal(struct perf_evlist *evlist, if (evlist->nr_entries != other->nr_entries) return false; - pair = perf_evlist__first(other); + pair = list_entry(other->entries.next, struct perf_evsel, node); list_for_each_entry(pos, &evlist->entries, node) { if (memcmp(&pos->attr, &pair->attr, sizeof(pos->attr) != 0)) return false; - pair = perf_evsel__next(pair); + pair = list_entry(pair->node.next, struct perf_evsel, node); } return true; } -static int perf_record__open(struct perf_record *rec) +static void perf_record__open(struct perf_record *rec) { - struct perf_evsel *pos; + struct perf_evsel *pos, *first; struct perf_evlist *evlist = rec->evlist; struct perf_session *session = rec->session; struct perf_record_opts *opts = &rec->opts; - int rc = 0; - perf_evlist__config_attrs(evlist, opts); + first = list_entry(evlist->entries.next, struct perf_evsel, node); - if (opts->group) - perf_evlist__set_leader(evlist); + perf_evlist__config_attrs(evlist, opts); list_for_each_entry(pos, &evlist->entries, node) { struct perf_event_attr *attr = &pos->attr; + struct xyarray *group_fd = NULL; /* * Check if parse_single_tracepoint_event has already asked for * PERF_SAMPLE_TIME. @@ -228,24 +202,24 @@ static int perf_record__open(struct perf_record *rec) */ bool time_needed = attr->sample_type & PERF_SAMPLE_TIME; + if (opts->group && pos != first) + group_fd = first->fd; fallback_missing_features: if (opts->exclude_guest_missing) attr->exclude_guest = attr->exclude_host = 0; retry_sample_id: attr->sample_id_all = opts->sample_id_all_missing ? 0 : 1; try_again: - if (perf_evsel__open(pos, evlist->cpus, evlist->threads) < 0) { + if (perf_evsel__open(pos, evlist->cpus, evlist->threads, + opts->group, group_fd) < 0) { int err = errno; if (err == EPERM || err == EACCES) { ui__error_paranoid(); - rc = -err; - goto out; + exit(EXIT_FAILURE); } else if (err == ENODEV && opts->target.cpu_list) { - pr_err("No such device - did you specify" - " an out-of-range profile CPU?\n"); - rc = -err; - goto out; + die("No such device - did you specify" + " an out-of-range profile CPU?\n"); } else if (err == EINVAL) { if (!opts->exclude_guest_missing && (attr->exclude_guest || attr->exclude_host)) { @@ -292,57 +266,42 @@ static int perf_record__open(struct perf_record *rec) if (err == ENOENT) { ui__error("The %s event is not supported.\n", perf_evsel__name(pos)); - rc = -err; - goto out; + exit(EXIT_FAILURE); } printf("\n"); - error("sys_perf_event_open() syscall returned with %d " - "(%s) for event %s. /bin/dmesg may provide " - "additional information.\n", - err, strerror(err), perf_evsel__name(pos)); + error("sys_perf_event_open() syscall returned with %d (%s). /bin/dmesg may provide additional information.\n", + err, strerror(err)); #if defined(__i386__) || defined(__x86_64__) - if (attr->type == PERF_TYPE_HARDWARE && - err == EOPNOTSUPP) { - pr_err("No hardware sampling interrupt available." - " No APIC? If so then you can boot the kernel" - " with the \"lapic\" boot parameter to" - " force-enable it.\n"); - rc = -err; - goto out; - } + if (attr->type == PERF_TYPE_HARDWARE && err == EOPNOTSUPP) + die("No hardware sampling interrupt available." + " No APIC? If so then you can boot the kernel" + " with the \"lapic\" boot parameter to" + " force-enable it.\n"); #endif - pr_err("No CONFIG_PERF_EVENTS=y kernel support configured?\n"); - rc = -err; - goto out; + die("No CONFIG_PERF_EVENTS=y kernel support configured?\n"); } } - if (perf_evlist__apply_filters(evlist)) { + if (perf_evlist__set_filters(evlist)) { error("failed to set filter with %d (%s)\n", errno, strerror(errno)); - rc = -1; - goto out; + exit(-1); } if (perf_evlist__mmap(evlist, opts->mmap_pages, false) < 0) { - if (errno == EPERM) { - pr_err("Permission error mapping pages.\n" - "Consider increasing " - "/proc/sys/kernel/perf_event_mlock_kb,\n" - "or try again with a smaller value of -m/--mmap_pages.\n" - "(current value: %d)\n", opts->mmap_pages); - rc = -errno; - } else if (!is_power_of_2(opts->mmap_pages)) { - pr_err("--mmap_pages/-m value must be a power of two."); - rc = -EINVAL; - } else { - pr_err("failed to mmap with %d (%s)\n", errno, strerror(errno)); - rc = -errno; - } - goto out; + if (errno == EPERM) + die("Permission error mapping pages.\n" + "Consider increasing " + "/proc/sys/kernel/perf_event_mlock_kb,\n" + "or try again with a smaller value of -m/--mmap_pages.\n" + "(current value: %d)\n", opts->mmap_pages); + else if (!is_power_of_2(opts->mmap_pages)) + die("--mmap_pages/-m value must be a power of two."); + + die("failed to mmap with %d (%s)\n", errno, strerror(errno)); } if (rec->file_new) @@ -350,14 +309,11 @@ static int perf_record__open(struct perf_record *rec) else { if (!perf_evlist__equal(session->evlist, evlist)) { fprintf(stderr, "incompatible append\n"); - rc = -1; - goto out; + exit(-1); } } - perf_session__set_id_hdr_size(session); -out: - return rc; + perf_session__update_sample_type(session); } static int process_buildids(struct perf_record *rec) @@ -373,13 +329,10 @@ static int process_buildids(struct perf_record *rec) size, &build_id__mark_dso_hit_ops); } -static void perf_record__exit(int status, void *arg) +static void perf_record__exit(int status __used, void *arg) { struct perf_record *rec = arg; - if (status != 0) - return; - if (!rec->opts.pipe_output) { rec->session->header.data_size += rec->bytes_written; @@ -434,26 +387,17 @@ static struct perf_event_header finished_round_event = { .type = PERF_RECORD_FINISHED_ROUND, }; -static int perf_record__mmap_read_all(struct perf_record *rec) +static void perf_record__mmap_read_all(struct perf_record *rec) { int i; - int rc = 0; for (i = 0; i < rec->evlist->nr_mmaps; i++) { - if (rec->evlist->mmap[i].base) { - if (perf_record__mmap_read(rec, &rec->evlist->mmap[i]) != 0) { - rc = -1; - goto out; - } - } + if (rec->evlist->mmap[i].base) + perf_record__mmap_read(rec, &rec->evlist->mmap[i]); } if (perf_header__has_feat(&rec->session->header, HEADER_TRACING_DATA)) - rc = write_output(rec, &finished_round_event, - sizeof(finished_round_event)); - -out: - return rc; + write_output(rec, &finished_round_event, sizeof(finished_round_event)); } static int __cmd_record(struct perf_record *rec, int argc, const char **argv) @@ -513,7 +457,7 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv) output = open(output_name, flags, S_IRUSR | S_IWUSR); if (output < 0) { perror("failed to create output file"); - return -1; + exit(-1); } rec->output = output; @@ -553,10 +497,7 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv) } } - if (perf_record__open(rec) != 0) { - err = -1; - goto out_delete_session; - } + perf_record__open(rec); /* * perf_session__delete(session) will be called at perf_record__exit() @@ -566,20 +507,19 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv) if (opts->pipe_output) { err = perf_header__write_pipe(output); if (err < 0) - goto out_delete_session; + return err; } else if (rec->file_new) { err = perf_session__write_header(session, evsel_list, output, false); if (err < 0) - goto out_delete_session; + return err; } if (!rec->no_buildid && !perf_header__has_feat(&session->header, HEADER_BUILD_ID)) { pr_err("Couldn't generate buildids. " "Use --no-buildid to profile anyway.\n"); - err = -1; - goto out_delete_session; + return -1; } rec->post_processing_offset = lseek(output, 0, SEEK_CUR); @@ -587,8 +527,7 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv) machine = perf_session__find_host_machine(session); if (!machine) { pr_err("Couldn't find native kernel information.\n"); - err = -1; - goto out_delete_session; + return -1; } if (opts->pipe_output) { @@ -596,14 +535,14 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv) process_synthesized_event); if (err < 0) { pr_err("Couldn't synthesize attrs.\n"); - goto out_delete_session; + return err; } err = perf_event__synthesize_event_types(tool, process_synthesized_event, machine); if (err < 0) { pr_err("Couldn't synthesize event_types.\n"); - goto out_delete_session; + return err; } if (have_tracepoints(&evsel_list->entries)) { @@ -619,7 +558,7 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv) process_synthesized_event); if (err <= 0) { pr_err("Couldn't record tracing data.\n"); - goto out_delete_session; + return err; } advance_output(rec, err); } @@ -647,24 +586,20 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv) perf_event__synthesize_guest_os); if (!opts->target.system_wide) - err = perf_event__synthesize_thread_map(tool, evsel_list->threads, + perf_event__synthesize_thread_map(tool, evsel_list->threads, process_synthesized_event, machine); else - err = perf_event__synthesize_threads(tool, process_synthesized_event, + perf_event__synthesize_threads(tool, process_synthesized_event, machine); - if (err != 0) - goto out_delete_session; - if (rec->realtime_prio) { struct sched_param param; param.sched_priority = rec->realtime_prio; if (sched_setscheduler(0, SCHED_FIFO, ¶m)) { pr_err("Could not set realtime priority.\n"); - err = -1; - goto out_delete_session; + exit(-1); } } @@ -679,10 +614,7 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv) for (;;) { int hits = rec->samples; - if (perf_record__mmap_read_all(rec) < 0) { - err = -1; - goto out_delete_session; - } + perf_record__mmap_read_all(rec); if (hits == rec->samples) { if (done) @@ -800,106 +732,6 @@ parse_branch_stack(const struct option *opt, const char *str, int unset) return ret; } -#ifndef NO_LIBUNWIND_SUPPORT -static int get_stack_size(char *str, unsigned long *_size) -{ - char *endptr; - unsigned long size; - unsigned long max_size = round_down(USHRT_MAX, sizeof(u64)); - - size = strtoul(str, &endptr, 0); - - do { - if (*endptr) - break; - - size = round_up(size, sizeof(u64)); - if (!size || size > max_size) - break; - - *_size = size; - return 0; - - } while (0); - - pr_err("callchain: Incorrect stack dump size (max %ld): %s\n", - max_size, str); - return -1; -} -#endif /* !NO_LIBUNWIND_SUPPORT */ - -static int -parse_callchain_opt(const struct option *opt __maybe_unused, const char *arg, - int unset) -{ - struct perf_record *rec = (struct perf_record *)opt->value; - char *tok, *name, *saveptr = NULL; - char *buf; - int ret = -1; - - /* --no-call-graph */ - if (unset) - return 0; - - /* We specified default option if none is provided. */ - BUG_ON(!arg); - - /* We need buffer that we know we can write to. */ - buf = malloc(strlen(arg) + 1); - if (!buf) - return -ENOMEM; - - strcpy(buf, arg); - - tok = strtok_r((char *)buf, ",", &saveptr); - name = tok ? : (char *)buf; - - do { - /* Framepointer style */ - if (!strncmp(name, "fp", sizeof("fp"))) { - if (!strtok_r(NULL, ",", &saveptr)) { - rec->opts.call_graph = CALLCHAIN_FP; - ret = 0; - } else - pr_err("callchain: No more arguments " - "needed for -g fp\n"); - break; - -#ifndef NO_LIBUNWIND_SUPPORT - /* Dwarf style */ - } else if (!strncmp(name, "dwarf", sizeof("dwarf"))) { - ret = 0; - rec->opts.call_graph = CALLCHAIN_DWARF; - rec->opts.stack_dump_size = default_stack_dump_size; - - tok = strtok_r(NULL, ",", &saveptr); - if (tok) { - unsigned long size = 0; - - ret = get_stack_size(tok, &size); - rec->opts.stack_dump_size = size; - } - - if (!ret) - pr_debug("callchain: stack dump size %d\n", - rec->opts.stack_dump_size); -#endif /* !NO_LIBUNWIND_SUPPORT */ - } else { - pr_err("callchain: Unknown -g option " - "value: %s\n", arg); - break; - } - - } while (0); - - free(buf); - - if (!ret) - pr_debug("callchain: type %d\n", rec->opts.call_graph); - - return ret; -} - static const char * const record_usage[] = { "perf record [] []", "perf record [] -- []", @@ -971,9 +803,8 @@ const struct option record_options[] = { "number of mmap data pages"), OPT_BOOLEAN(0, "group", &record.opts.group, "put the counters into a counter group"), - OPT_CALLBACK_DEFAULT('g', "call-graph", &record, "mode[,dump_size]", - callchain_help, &parse_callchain_opt, - "fp"), + OPT_BOOLEAN('g', "call-graph", &record.opts.call_graph, + "do call-graph (stack chain/backtrace) recording"), OPT_INCR('v', "verbose", &verbose, "be more verbose (show counter open errors, etc)"), OPT_BOOLEAN('q', "quiet", &quiet, "don't print any message"), @@ -1005,7 +836,7 @@ const struct option record_options[] = { OPT_END() }; -int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused) +int cmd_record(int argc, const char **argv, const char *prefix __used) { int err = -ENOMEM; struct perf_evsel *pos; @@ -1013,6 +844,8 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused) struct perf_record *rec = &record; char errbuf[BUFSIZ]; + perf_header__set_cmdline(argc, argv); + evsel_list = perf_evlist__new(NULL, NULL); if (evsel_list == NULL) return -ENOMEM; diff --git a/trunk/tools/perf/builtin-report.c b/trunk/tools/perf/builtin-report.c index 1da243dfbc3e..69b1c1185159 100644 --- a/trunk/tools/perf/builtin-report.c +++ b/trunk/tools/perf/builtin-report.c @@ -69,8 +69,8 @@ static int perf_report__add_branch_hist_entry(struct perf_tool *tool, if ((sort__has_parent || symbol_conf.use_callchain) && sample->callchain) { - err = machine__resolve_callchain(machine, evsel, al->thread, - sample, &parent); + err = machine__resolve_callchain(machine, al->thread, + sample->callchain, &parent); if (err) return err; } @@ -93,7 +93,7 @@ static int perf_report__add_branch_hist_entry(struct perf_tool *tool, struct annotation *notes; err = -ENOMEM; bx = he->branch_info; - if (bx->from.sym && use_browser == 1 && sort__has_sym) { + if (bx->from.sym && use_browser > 0) { notes = symbol__annotation(bx->from.sym); if (!notes->src && symbol__alloc_hist(bx->from.sym) < 0) @@ -107,7 +107,7 @@ static int perf_report__add_branch_hist_entry(struct perf_tool *tool, goto out; } - if (bx->to.sym && use_browser == 1 && sort__has_sym) { + if (bx->to.sym && use_browser > 0) { notes = symbol__annotation(bx->to.sym); if (!notes->src && symbol__alloc_hist(bx->to.sym) < 0) @@ -140,8 +140,8 @@ static int perf_evsel__add_hist_entry(struct perf_evsel *evsel, struct hist_entry *he; if ((sort__has_parent || symbol_conf.use_callchain) && sample->callchain) { - err = machine__resolve_callchain(machine, evsel, al->thread, - sample, &parent); + err = machine__resolve_callchain(machine, al->thread, + sample->callchain, &parent); if (err) return err; } @@ -162,7 +162,7 @@ static int perf_evsel__add_hist_entry(struct perf_evsel *evsel, * so we don't allocated the extra space needed because the stdio * code will not use it. */ - if (he->ms.sym != NULL && use_browser == 1 && sort__has_sym) { + if (he->ms.sym != NULL && use_browser > 0) { struct annotation *notes = symbol__annotation(he->ms.sym); assert(evsel != NULL); @@ -223,9 +223,9 @@ static int process_sample_event(struct perf_tool *tool, static int process_read_event(struct perf_tool *tool, union perf_event *event, - struct perf_sample *sample __maybe_unused, + struct perf_sample *sample __used, struct perf_evsel *evsel, - struct machine *machine __maybe_unused) + struct machine *machine __used) { struct perf_report *rep = container_of(tool, struct perf_report, tool); @@ -249,9 +249,8 @@ static int process_read_event(struct perf_tool *tool, static int perf_report__setup_sample_type(struct perf_report *rep) { struct perf_session *self = rep->session; - u64 sample_type = perf_evlist__sample_type(self->evlist); - if (!self->fd_pipe && !(sample_type & PERF_SAMPLE_CALLCHAIN)) { + if (!self->fd_pipe && !(self->sample_type & PERF_SAMPLE_CALLCHAIN)) { if (sort__has_parent) { ui__error("Selected --sort parent, but no " "callchain data. Did you call " @@ -275,7 +274,7 @@ static int perf_report__setup_sample_type(struct perf_report *rep) if (sort__branch_mode == 1) { if (!self->fd_pipe && - !(sample_type & PERF_SAMPLE_BRANCH_STACK)) { + !(self->sample_type & PERF_SAMPLE_BRANCH_STACK)) { ui__error("Selected -b but no branch data. " "Did you call perf record without -b?\n"); return -1; @@ -287,7 +286,7 @@ static int perf_report__setup_sample_type(struct perf_report *rep) extern volatile int session_done; -static void sig_handler(int sig __maybe_unused) +static void sig_handler(int sig __used) { session_done = 1; } @@ -397,17 +396,17 @@ static int __cmd_report(struct perf_report *rep) desc); } + if (dump_trace) { + perf_session__fprintf_nr_events(session, stdout); + goto out_delete; + } + if (verbose > 3) perf_session__fprintf(session, stdout); if (verbose > 2) perf_session__fprintf_dsos(session, stdout); - if (dump_trace) { - perf_session__fprintf_nr_events(session, stdout); - goto out_delete; - } - nr_samples = 0; list_for_each_entry(pos, &session->evlist->entries, node) { struct hists *hists = &pos->hists; @@ -533,14 +532,13 @@ parse_callchain_opt(const struct option *opt, const char *arg, int unset) } static int -parse_branch_mode(const struct option *opt __maybe_unused, - const char *str __maybe_unused, int unset) +parse_branch_mode(const struct option *opt __used, const char *str __used, int unset) { sort__branch_mode = !unset; return 0; } -int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused) +int cmd_report(int argc, const char **argv, const char *prefix __used) { struct perf_session *session; struct stat st; @@ -639,8 +637,6 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused) "Show a column with the sum of periods"), OPT_CALLBACK_NOOPT('b', "branch-stack", &sort__branch_mode, "", "use branch records for histogram filling", parse_branch_mode), - OPT_STRING(0, "objdump", &objdump_path, "path", - "objdump binary to use for disassembly and annotations"), OPT_END() }; @@ -689,19 +685,15 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused) if (strcmp(report.input_name, "-") != 0) setup_browser(true); - else { + else use_browser = 0; - perf_hpp__init(false, false); - } - - setup_sorting(report_usage, options); /* * Only in the newt browser we are doing integrated annotation, * so don't allocate extra space that won't be used in the stdio * implementation. */ - if (use_browser == 1 && sort__has_sym) { + if (use_browser > 0) { symbol_conf.priv_size = sizeof(struct annotation); report.annotate_init = symbol__annotate_init; /* @@ -724,6 +716,8 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused) if (symbol__init() < 0) goto error; + setup_sorting(report_usage, options); + if (parent_pattern != default_parent_pattern) { if (sort_dimension__add("parent") < 0) goto error; diff --git a/trunk/tools/perf/builtin-sched.c b/trunk/tools/perf/builtin-sched.c index 9b9e32eaa805..7a9ad2b1ee76 100644 --- a/trunk/tools/perf/builtin-sched.c +++ b/trunk/tools/perf/builtin-sched.c @@ -23,12 +23,31 @@ #include #include +static const char *input_name; + +static char default_sort_order[] = "avg, max, switch, runtime"; +static const char *sort_order = default_sort_order; + +static int profile_cpu = -1; + #define PR_SET_NAME 15 /* Set process name */ #define MAX_CPUS 4096 + +static u64 run_measurement_overhead; +static u64 sleep_measurement_overhead; + #define COMM_LEN 20 #define SYM_LEN 129 + #define MAX_PID 65536 +static unsigned long nr_tasks; + +struct perf_sched { + struct perf_tool tool; + struct perf_session *session; +}; + struct sched_atom; struct task_desc { @@ -66,6 +85,44 @@ struct sched_atom { struct task_desc *wakee; }; +static struct task_desc *pid_to_task[MAX_PID]; + +static struct task_desc **tasks; + +static pthread_mutex_t start_work_mutex = PTHREAD_MUTEX_INITIALIZER; +static u64 start_time; + +static pthread_mutex_t work_done_wait_mutex = PTHREAD_MUTEX_INITIALIZER; + +static unsigned long nr_run_events; +static unsigned long nr_sleep_events; +static unsigned long nr_wakeup_events; + +static unsigned long nr_sleep_corrections; +static unsigned long nr_run_events_optimized; + +static unsigned long targetless_wakeups; +static unsigned long multitarget_wakeups; + +static u64 cpu_usage; +static u64 runavg_cpu_usage; +static u64 parent_cpu_usage; +static u64 runavg_parent_cpu_usage; + +static unsigned long nr_runs; +static u64 sum_runtime; +static u64 sum_fluct; +static u64 run_avg; + +static unsigned int replay_repeat = 10; +static unsigned long nr_timestamps; +static unsigned long nr_unordered_timestamps; +static unsigned long nr_state_machine_bugs; +static unsigned long nr_context_switch_bugs; +static unsigned long nr_events; +static unsigned long nr_lost_chunks; +static unsigned long nr_lost_events; + #define TASK_STATE_TO_CHAR_STR "RSDTtZX" enum thread_state { @@ -97,79 +154,11 @@ struct work_atoms { typedef int (*sort_fn_t)(struct work_atoms *, struct work_atoms *); -struct perf_sched; - -struct trace_sched_handler { - int (*switch_event)(struct perf_sched *sched, struct perf_evsel *evsel, - struct perf_sample *sample, struct machine *machine); +static struct rb_root atom_root, sorted_atom_root; - int (*runtime_event)(struct perf_sched *sched, struct perf_evsel *evsel, - struct perf_sample *sample, struct machine *machine); +static u64 all_runtime; +static u64 all_count; - int (*wakeup_event)(struct perf_sched *sched, struct perf_evsel *evsel, - struct perf_sample *sample, struct machine *machine); - - int (*fork_event)(struct perf_sched *sched, struct perf_evsel *evsel, - struct perf_sample *sample); - - int (*migrate_task_event)(struct perf_sched *sched, - struct perf_evsel *evsel, - struct perf_sample *sample, - struct machine *machine); -}; - -struct perf_sched { - struct perf_tool tool; - const char *input_name; - const char *sort_order; - unsigned long nr_tasks; - struct task_desc *pid_to_task[MAX_PID]; - struct task_desc **tasks; - const struct trace_sched_handler *tp_handler; - pthread_mutex_t start_work_mutex; - pthread_mutex_t work_done_wait_mutex; - int profile_cpu; -/* - * Track the current task - that way we can know whether there's any - * weird events, such as a task being switched away that is not current. - */ - int max_cpu; - u32 curr_pid[MAX_CPUS]; - struct thread *curr_thread[MAX_CPUS]; - char next_shortname1; - char next_shortname2; - unsigned int replay_repeat; - unsigned long nr_run_events; - unsigned long nr_sleep_events; - unsigned long nr_wakeup_events; - unsigned long nr_sleep_corrections; - unsigned long nr_run_events_optimized; - unsigned long targetless_wakeups; - unsigned long multitarget_wakeups; - unsigned long nr_runs; - unsigned long nr_timestamps; - unsigned long nr_unordered_timestamps; - unsigned long nr_state_machine_bugs; - unsigned long nr_context_switch_bugs; - unsigned long nr_events; - unsigned long nr_lost_chunks; - unsigned long nr_lost_events; - u64 run_measurement_overhead; - u64 sleep_measurement_overhead; - u64 start_time; - u64 cpu_usage; - u64 runavg_cpu_usage; - u64 parent_cpu_usage; - u64 runavg_parent_cpu_usage; - u64 sum_runtime; - u64 sum_fluct; - u64 run_avg; - u64 all_runtime; - u64 all_count; - u64 cpu_last_switched[MAX_CPUS]; - struct rb_root atom_root, sorted_atom_root; - struct list_head sort_list, cmp_pid; -}; static u64 get_nsecs(void) { @@ -180,13 +169,13 @@ static u64 get_nsecs(void) return ts.tv_sec * 1000000000ULL + ts.tv_nsec; } -static void burn_nsecs(struct perf_sched *sched, u64 nsecs) +static void burn_nsecs(u64 nsecs) { u64 T0 = get_nsecs(), T1; do { T1 = get_nsecs(); - } while (T1 + sched->run_measurement_overhead < T0 + nsecs); + } while (T1 + run_measurement_overhead < T0 + nsecs); } static void sleep_nsecs(u64 nsecs) @@ -199,24 +188,24 @@ static void sleep_nsecs(u64 nsecs) nanosleep(&ts, NULL); } -static void calibrate_run_measurement_overhead(struct perf_sched *sched) +static void calibrate_run_measurement_overhead(void) { u64 T0, T1, delta, min_delta = 1000000000ULL; int i; for (i = 0; i < 10; i++) { T0 = get_nsecs(); - burn_nsecs(sched, 0); + burn_nsecs(0); T1 = get_nsecs(); delta = T1-T0; min_delta = min(min_delta, delta); } - sched->run_measurement_overhead = min_delta; + run_measurement_overhead = min_delta; printf("run measurement overhead: %" PRIu64 " nsecs\n", min_delta); } -static void calibrate_sleep_measurement_overhead(struct perf_sched *sched) +static void calibrate_sleep_measurement_overhead(void) { u64 T0, T1, delta, min_delta = 1000000000ULL; int i; @@ -229,7 +218,7 @@ static void calibrate_sleep_measurement_overhead(struct perf_sched *sched) min_delta = min(min_delta, delta); } min_delta -= 10000; - sched->sleep_measurement_overhead = min_delta; + sleep_measurement_overhead = min_delta; printf("sleep measurement overhead: %" PRIu64 " nsecs\n", min_delta); } @@ -262,8 +251,8 @@ static struct sched_atom *last_event(struct task_desc *task) return task->atoms[task->nr_events - 1]; } -static void add_sched_event_run(struct perf_sched *sched, struct task_desc *task, - u64 timestamp, u64 duration) +static void +add_sched_event_run(struct task_desc *task, u64 timestamp, u64 duration) { struct sched_atom *event, *curr_event = last_event(task); @@ -272,7 +261,7 @@ static void add_sched_event_run(struct perf_sched *sched, struct task_desc *task * to it: */ if (curr_event && curr_event->type == SCHED_EVENT_RUN) { - sched->nr_run_events_optimized++; + nr_run_events_optimized++; curr_event->duration += duration; return; } @@ -282,11 +271,12 @@ static void add_sched_event_run(struct perf_sched *sched, struct task_desc *task event->type = SCHED_EVENT_RUN; event->duration = duration; - sched->nr_run_events++; + nr_run_events++; } -static void add_sched_event_wakeup(struct perf_sched *sched, struct task_desc *task, - u64 timestamp, struct task_desc *wakee) +static void +add_sched_event_wakeup(struct task_desc *task, u64 timestamp, + struct task_desc *wakee) { struct sched_atom *event, *wakee_event; @@ -296,11 +286,11 @@ static void add_sched_event_wakeup(struct perf_sched *sched, struct task_desc *t wakee_event = last_event(wakee); if (!wakee_event || wakee_event->type != SCHED_EVENT_SLEEP) { - sched->targetless_wakeups++; + targetless_wakeups++; return; } if (wakee_event->wait_sem) { - sched->multitarget_wakeups++; + multitarget_wakeups++; return; } @@ -309,89 +299,89 @@ static void add_sched_event_wakeup(struct perf_sched *sched, struct task_desc *t wakee_event->specific_wait = 1; event->wait_sem = wakee_event->wait_sem; - sched->nr_wakeup_events++; + nr_wakeup_events++; } -static void add_sched_event_sleep(struct perf_sched *sched, struct task_desc *task, - u64 timestamp, u64 task_state __maybe_unused) +static void +add_sched_event_sleep(struct task_desc *task, u64 timestamp, + u64 task_state __used) { struct sched_atom *event = get_new_event(task, timestamp); event->type = SCHED_EVENT_SLEEP; - sched->nr_sleep_events++; + nr_sleep_events++; } -static struct task_desc *register_pid(struct perf_sched *sched, - unsigned long pid, const char *comm) +static struct task_desc *register_pid(unsigned long pid, const char *comm) { struct task_desc *task; BUG_ON(pid >= MAX_PID); - task = sched->pid_to_task[pid]; + task = pid_to_task[pid]; if (task) return task; task = zalloc(sizeof(*task)); task->pid = pid; - task->nr = sched->nr_tasks; + task->nr = nr_tasks; strcpy(task->comm, comm); /* * every task starts in sleeping state - this gets ignored * if there's no wakeup pointing to this sleep state: */ - add_sched_event_sleep(sched, task, 0, 0); + add_sched_event_sleep(task, 0, 0); - sched->pid_to_task[pid] = task; - sched->nr_tasks++; - sched->tasks = realloc(sched->tasks, sched->nr_tasks * sizeof(struct task_task *)); - BUG_ON(!sched->tasks); - sched->tasks[task->nr] = task; + pid_to_task[pid] = task; + nr_tasks++; + tasks = realloc(tasks, nr_tasks*sizeof(struct task_task *)); + BUG_ON(!tasks); + tasks[task->nr] = task; if (verbose) - printf("registered task #%ld, PID %ld (%s)\n", sched->nr_tasks, pid, comm); + printf("registered task #%ld, PID %ld (%s)\n", nr_tasks, pid, comm); return task; } -static void print_task_traces(struct perf_sched *sched) +static void print_task_traces(void) { struct task_desc *task; unsigned long i; - for (i = 0; i < sched->nr_tasks; i++) { - task = sched->tasks[i]; + for (i = 0; i < nr_tasks; i++) { + task = tasks[i]; printf("task %6ld (%20s:%10ld), nr_events: %ld\n", task->nr, task->comm, task->pid, task->nr_events); } } -static void add_cross_task_wakeups(struct perf_sched *sched) +static void add_cross_task_wakeups(void) { struct task_desc *task1, *task2; unsigned long i, j; - for (i = 0; i < sched->nr_tasks; i++) { - task1 = sched->tasks[i]; + for (i = 0; i < nr_tasks; i++) { + task1 = tasks[i]; j = i + 1; - if (j == sched->nr_tasks) + if (j == nr_tasks) j = 0; - task2 = sched->tasks[j]; - add_sched_event_wakeup(sched, task1, 0, task2); + task2 = tasks[j]; + add_sched_event_wakeup(task1, 0, task2); } } -static void perf_sched__process_event(struct perf_sched *sched, - struct sched_atom *atom) +static void +process_sched_event(struct task_desc *this_task __used, struct sched_atom *atom) { int ret = 0; switch (atom->type) { case SCHED_EVENT_RUN: - burn_nsecs(sched, atom->duration); + burn_nsecs(atom->duration); break; case SCHED_EVENT_SLEEP: if (atom->wait_sem) @@ -438,8 +428,8 @@ static int self_open_counters(void) fd = sys_perf_event_open(&attr, 0, -1, -1, 0); if (fd < 0) - pr_err("Error: sys_perf_event_open() syscall returned " - "with %d (%s)\n", fd, strerror(errno)); + die("Error: sys_perf_event_open() syscall returned" + "with %d (%s)\n", fd, strerror(errno)); return fd; } @@ -454,41 +444,31 @@ static u64 get_cpu_usage_nsec_self(int fd) return runtime; } -struct sched_thread_parms { - struct task_desc *task; - struct perf_sched *sched; -}; - static void *thread_func(void *ctx) { - struct sched_thread_parms *parms = ctx; - struct task_desc *this_task = parms->task; - struct perf_sched *sched = parms->sched; + struct task_desc *this_task = ctx; u64 cpu_usage_0, cpu_usage_1; unsigned long i, ret; char comm2[22]; int fd; - free(parms); - sprintf(comm2, ":%s", this_task->comm); prctl(PR_SET_NAME, comm2); fd = self_open_counters(); - if (fd < 0) - return NULL; + again: ret = sem_post(&this_task->ready_for_work); BUG_ON(ret); - ret = pthread_mutex_lock(&sched->start_work_mutex); + ret = pthread_mutex_lock(&start_work_mutex); BUG_ON(ret); - ret = pthread_mutex_unlock(&sched->start_work_mutex); + ret = pthread_mutex_unlock(&start_work_mutex); BUG_ON(ret); cpu_usage_0 = get_cpu_usage_nsec_self(fd); for (i = 0; i < this_task->nr_events; i++) { this_task->curr_event = i; - perf_sched__process_event(sched, this_task->atoms[i]); + process_sched_event(this_task, this_task->atoms[i]); } cpu_usage_1 = get_cpu_usage_nsec_self(fd); @@ -496,15 +476,15 @@ static void *thread_func(void *ctx) ret = sem_post(&this_task->work_done_sem); BUG_ON(ret); - ret = pthread_mutex_lock(&sched->work_done_wait_mutex); + ret = pthread_mutex_lock(&work_done_wait_mutex); BUG_ON(ret); - ret = pthread_mutex_unlock(&sched->work_done_wait_mutex); + ret = pthread_mutex_unlock(&work_done_wait_mutex); BUG_ON(ret); goto again; } -static void create_tasks(struct perf_sched *sched) +static void create_tasks(void) { struct task_desc *task; pthread_attr_t attr; @@ -516,129 +496,128 @@ static void create_tasks(struct perf_sched *sched) err = pthread_attr_setstacksize(&attr, (size_t) max(16 * 1024, PTHREAD_STACK_MIN)); BUG_ON(err); - err = pthread_mutex_lock(&sched->start_work_mutex); + err = pthread_mutex_lock(&start_work_mutex); BUG_ON(err); - err = pthread_mutex_lock(&sched->work_done_wait_mutex); + err = pthread_mutex_lock(&work_done_wait_mutex); BUG_ON(err); - for (i = 0; i < sched->nr_tasks; i++) { - struct sched_thread_parms *parms = malloc(sizeof(*parms)); - BUG_ON(parms == NULL); - parms->task = task = sched->tasks[i]; - parms->sched = sched; + for (i = 0; i < nr_tasks; i++) { + task = tasks[i]; sem_init(&task->sleep_sem, 0, 0); sem_init(&task->ready_for_work, 0, 0); sem_init(&task->work_done_sem, 0, 0); task->curr_event = 0; - err = pthread_create(&task->thread, &attr, thread_func, parms); + err = pthread_create(&task->thread, &attr, thread_func, task); BUG_ON(err); } } -static void wait_for_tasks(struct perf_sched *sched) +static void wait_for_tasks(void) { u64 cpu_usage_0, cpu_usage_1; struct task_desc *task; unsigned long i, ret; - sched->start_time = get_nsecs(); - sched->cpu_usage = 0; - pthread_mutex_unlock(&sched->work_done_wait_mutex); + start_time = get_nsecs(); + cpu_usage = 0; + pthread_mutex_unlock(&work_done_wait_mutex); - for (i = 0; i < sched->nr_tasks; i++) { - task = sched->tasks[i]; + for (i = 0; i < nr_tasks; i++) { + task = tasks[i]; ret = sem_wait(&task->ready_for_work); BUG_ON(ret); sem_init(&task->ready_for_work, 0, 0); } - ret = pthread_mutex_lock(&sched->work_done_wait_mutex); + ret = pthread_mutex_lock(&work_done_wait_mutex); BUG_ON(ret); cpu_usage_0 = get_cpu_usage_nsec_parent(); - pthread_mutex_unlock(&sched->start_work_mutex); + pthread_mutex_unlock(&start_work_mutex); - for (i = 0; i < sched->nr_tasks; i++) { - task = sched->tasks[i]; + for (i = 0; i < nr_tasks; i++) { + task = tasks[i]; ret = sem_wait(&task->work_done_sem); BUG_ON(ret); sem_init(&task->work_done_sem, 0, 0); - sched->cpu_usage += task->cpu_usage; + cpu_usage += task->cpu_usage; task->cpu_usage = 0; } cpu_usage_1 = get_cpu_usage_nsec_parent(); - if (!sched->runavg_cpu_usage) - sched->runavg_cpu_usage = sched->cpu_usage; - sched->runavg_cpu_usage = (sched->runavg_cpu_usage * 9 + sched->cpu_usage) / 10; + if (!runavg_cpu_usage) + runavg_cpu_usage = cpu_usage; + runavg_cpu_usage = (runavg_cpu_usage*9 + cpu_usage)/10; - sched->parent_cpu_usage = cpu_usage_1 - cpu_usage_0; - if (!sched->runavg_parent_cpu_usage) - sched->runavg_parent_cpu_usage = sched->parent_cpu_usage; - sched->runavg_parent_cpu_usage = (sched->runavg_parent_cpu_usage * 9 + - sched->parent_cpu_usage)/10; + parent_cpu_usage = cpu_usage_1 - cpu_usage_0; + if (!runavg_parent_cpu_usage) + runavg_parent_cpu_usage = parent_cpu_usage; + runavg_parent_cpu_usage = (runavg_parent_cpu_usage*9 + + parent_cpu_usage)/10; - ret = pthread_mutex_lock(&sched->start_work_mutex); + ret = pthread_mutex_lock(&start_work_mutex); BUG_ON(ret); - for (i = 0; i < sched->nr_tasks; i++) { - task = sched->tasks[i]; + for (i = 0; i < nr_tasks; i++) { + task = tasks[i]; sem_init(&task->sleep_sem, 0, 0); task->curr_event = 0; } } -static void run_one_test(struct perf_sched *sched) +static void run_one_test(void) { u64 T0, T1, delta, avg_delta, fluct; T0 = get_nsecs(); - wait_for_tasks(sched); + wait_for_tasks(); T1 = get_nsecs(); delta = T1 - T0; - sched->sum_runtime += delta; - sched->nr_runs++; + sum_runtime += delta; + nr_runs++; - avg_delta = sched->sum_runtime / sched->nr_runs; + avg_delta = sum_runtime / nr_runs; if (delta < avg_delta) fluct = avg_delta - delta; else fluct = delta - avg_delta; - sched->sum_fluct += fluct; - if (!sched->run_avg) - sched->run_avg = delta; - sched->run_avg = (sched->run_avg * 9 + delta) / 10; + sum_fluct += fluct; + if (!run_avg) + run_avg = delta; + run_avg = (run_avg*9 + delta)/10; - printf("#%-3ld: %0.3f, ", sched->nr_runs, (double)delta / 1000000.0); + printf("#%-3ld: %0.3f, ", + nr_runs, (double)delta/1000000.0); - printf("ravg: %0.2f, ", (double)sched->run_avg / 1e6); + printf("ravg: %0.2f, ", + (double)run_avg/1e6); printf("cpu: %0.2f / %0.2f", - (double)sched->cpu_usage / 1e6, (double)sched->runavg_cpu_usage / 1e6); + (double)cpu_usage/1e6, (double)runavg_cpu_usage/1e6); #if 0 /* * rusage statistics done by the parent, these are less - * accurate than the sched->sum_exec_runtime based statistics: + * accurate than the sum_exec_runtime based statistics: */ printf(" [%0.2f / %0.2f]", - (double)sched->parent_cpu_usage/1e6, - (double)sched->runavg_parent_cpu_usage/1e6); + (double)parent_cpu_usage/1e6, + (double)runavg_parent_cpu_usage/1e6); #endif printf("\n"); - if (sched->nr_sleep_corrections) - printf(" (%ld sleep corrections)\n", sched->nr_sleep_corrections); - sched->nr_sleep_corrections = 0; + if (nr_sleep_corrections) + printf(" (%ld sleep corrections)\n", nr_sleep_corrections); + nr_sleep_corrections = 0; } -static void test_calibrations(struct perf_sched *sched) +static void test_calibrations(void) { u64 T0, T1; T0 = get_nsecs(); - burn_nsecs(sched, 1e6); + burn_nsecs(1e6); T1 = get_nsecs(); printf("the run test took %" PRIu64 " nsecs\n", T1 - T0); @@ -650,99 +629,245 @@ static void test_calibrations(struct perf_sched *sched) printf("the sleep test took %" PRIu64 " nsecs\n", T1 - T0); } -static int -replay_wakeup_event(struct perf_sched *sched, - struct perf_evsel *evsel, struct perf_sample *sample, - struct machine *machine __maybe_unused) +#define FILL_FIELD(ptr, field, event, data) \ + ptr.field = (typeof(ptr.field)) raw_field_value(event, #field, data) + +#define FILL_ARRAY(ptr, array, event, data) \ +do { \ + void *__array = raw_field_ptr(event, #array, data); \ + memcpy(ptr.array, __array, sizeof(ptr.array)); \ +} while(0) + +#define FILL_COMMON_FIELDS(ptr, event, data) \ +do { \ + FILL_FIELD(ptr, common_type, event, data); \ + FILL_FIELD(ptr, common_flags, event, data); \ + FILL_FIELD(ptr, common_preempt_count, event, data); \ + FILL_FIELD(ptr, common_pid, event, data); \ + FILL_FIELD(ptr, common_tgid, event, data); \ +} while (0) + + + +struct trace_switch_event { + u32 size; + + u16 common_type; + u8 common_flags; + u8 common_preempt_count; + u32 common_pid; + u32 common_tgid; + + char prev_comm[16]; + u32 prev_pid; + u32 prev_prio; + u64 prev_state; + char next_comm[16]; + u32 next_pid; + u32 next_prio; +}; + +struct trace_runtime_event { + u32 size; + + u16 common_type; + u8 common_flags; + u8 common_preempt_count; + u32 common_pid; + u32 common_tgid; + + char comm[16]; + u32 pid; + u64 runtime; + u64 vruntime; +}; + +struct trace_wakeup_event { + u32 size; + + u16 common_type; + u8 common_flags; + u8 common_preempt_count; + u32 common_pid; + u32 common_tgid; + + char comm[16]; + u32 pid; + + u32 prio; + u32 success; + u32 cpu; +}; + +struct trace_fork_event { + u32 size; + + u16 common_type; + u8 common_flags; + u8 common_preempt_count; + u32 common_pid; + u32 common_tgid; + + char parent_comm[16]; + u32 parent_pid; + char child_comm[16]; + u32 child_pid; +}; + +struct trace_migrate_task_event { + u32 size; + + u16 common_type; + u8 common_flags; + u8 common_preempt_count; + u32 common_pid; + u32 common_tgid; + + char comm[16]; + u32 pid; + + u32 prio; + u32 cpu; +}; + +struct trace_sched_handler { + void (*switch_event)(struct trace_switch_event *, + struct machine *, + struct event_format *, + int cpu, + u64 timestamp, + struct thread *thread); + + void (*runtime_event)(struct trace_runtime_event *, + struct machine *, + struct event_format *, + int cpu, + u64 timestamp, + struct thread *thread); + + void (*wakeup_event)(struct trace_wakeup_event *, + struct machine *, + struct event_format *, + int cpu, + u64 timestamp, + struct thread *thread); + + void (*fork_event)(struct trace_fork_event *, + struct event_format *, + int cpu, + u64 timestamp, + struct thread *thread); + + void (*migrate_task_event)(struct trace_migrate_task_event *, + struct machine *machine, + struct event_format *, + int cpu, + u64 timestamp, + struct thread *thread); +}; + + +static void +replay_wakeup_event(struct trace_wakeup_event *wakeup_event, + struct machine *machine __used, + struct event_format *event, + int cpu __used, + u64 timestamp __used, + struct thread *thread __used) { - const char *comm = perf_evsel__strval(evsel, sample, "comm"); - const u32 pid = perf_evsel__intval(evsel, sample, "pid"); struct task_desc *waker, *wakee; if (verbose) { - printf("sched_wakeup event %p\n", evsel); + printf("sched_wakeup event %p\n", event); - printf(" ... pid %d woke up %s/%d\n", sample->tid, comm, pid); + printf(" ... pid %d woke up %s/%d\n", + wakeup_event->common_pid, + wakeup_event->comm, + wakeup_event->pid); } - waker = register_pid(sched, sample->tid, ""); - wakee = register_pid(sched, pid, comm); + waker = register_pid(wakeup_event->common_pid, ""); + wakee = register_pid(wakeup_event->pid, wakeup_event->comm); - add_sched_event_wakeup(sched, waker, sample->time, wakee); - return 0; + add_sched_event_wakeup(waker, timestamp, wakee); } -static int replay_switch_event(struct perf_sched *sched, - struct perf_evsel *evsel, - struct perf_sample *sample, - struct machine *machine __maybe_unused) +static u64 cpu_last_switched[MAX_CPUS]; + +static void +replay_switch_event(struct trace_switch_event *switch_event, + struct machine *machine __used, + struct event_format *event, + int cpu, + u64 timestamp, + struct thread *thread __used) { - const char *prev_comm = perf_evsel__strval(evsel, sample, "prev_comm"), - *next_comm = perf_evsel__strval(evsel, sample, "next_comm"); - const u32 prev_pid = perf_evsel__intval(evsel, sample, "prev_pid"), - next_pid = perf_evsel__intval(evsel, sample, "next_pid"); - const u64 prev_state = perf_evsel__intval(evsel, sample, "prev_state"); - struct task_desc *prev, __maybe_unused *next; - u64 timestamp0, timestamp = sample->time; - int cpu = sample->cpu; + struct task_desc *prev, __used *next; + u64 timestamp0; s64 delta; if (verbose) - printf("sched_switch event %p\n", evsel); + printf("sched_switch event %p\n", event); if (cpu >= MAX_CPUS || cpu < 0) - return 0; + return; - timestamp0 = sched->cpu_last_switched[cpu]; + timestamp0 = cpu_last_switched[cpu]; if (timestamp0) delta = timestamp - timestamp0; else delta = 0; - if (delta < 0) { - pr_err("hm, delta: %" PRIu64 " < 0 ?\n", delta); - return -1; - } + if (delta < 0) + die("hm, delta: %" PRIu64 " < 0 ?\n", delta); - pr_debug(" ... switch from %s/%d to %s/%d [ran %" PRIu64 " nsecs]\n", - prev_comm, prev_pid, next_comm, next_pid, delta); - - prev = register_pid(sched, prev_pid, prev_comm); - next = register_pid(sched, next_pid, next_comm); + if (verbose) { + printf(" ... switch from %s/%d to %s/%d [ran %" PRIu64 " nsecs]\n", + switch_event->prev_comm, switch_event->prev_pid, + switch_event->next_comm, switch_event->next_pid, + delta); + } - sched->cpu_last_switched[cpu] = timestamp; + prev = register_pid(switch_event->prev_pid, switch_event->prev_comm); + next = register_pid(switch_event->next_pid, switch_event->next_comm); - add_sched_event_run(sched, prev, timestamp, delta); - add_sched_event_sleep(sched, prev, timestamp, prev_state); + cpu_last_switched[cpu] = timestamp; - return 0; + add_sched_event_run(prev, timestamp, delta); + add_sched_event_sleep(prev, timestamp, switch_event->prev_state); } -static int replay_fork_event(struct perf_sched *sched, struct perf_evsel *evsel, - struct perf_sample *sample) -{ - const char *parent_comm = perf_evsel__strval(evsel, sample, "parent_comm"), - *child_comm = perf_evsel__strval(evsel, sample, "child_comm"); - const u32 parent_pid = perf_evsel__intval(evsel, sample, "parent_pid"), - child_pid = perf_evsel__intval(evsel, sample, "child_pid"); +static void +replay_fork_event(struct trace_fork_event *fork_event, + struct event_format *event, + int cpu __used, + u64 timestamp __used, + struct thread *thread __used) +{ if (verbose) { - printf("sched_fork event %p\n", evsel); - printf("... parent: %s/%d\n", parent_comm, parent_pid); - printf("... child: %s/%d\n", child_comm, child_pid); + printf("sched_fork event %p\n", event); + printf("... parent: %s/%d\n", fork_event->parent_comm, fork_event->parent_pid); + printf("... child: %s/%d\n", fork_event->child_comm, fork_event->child_pid); } - - register_pid(sched, parent_pid, parent_comm); - register_pid(sched, child_pid, child_comm); - return 0; + register_pid(fork_event->parent_pid, fork_event->parent_comm); + register_pid(fork_event->child_pid, fork_event->child_comm); } +static struct trace_sched_handler replay_ops = { + .wakeup_event = replay_wakeup_event, + .switch_event = replay_switch_event, + .fork_event = replay_fork_event, +}; + struct sort_dimension { const char *name; sort_fn_t cmp; struct list_head list; }; +static LIST_HEAD(cmp_pid); + static int thread_lat_cmp(struct list_head *list, struct work_atoms *l, struct work_atoms *r) { @@ -811,45 +936,43 @@ __thread_latency_insert(struct rb_root *root, struct work_atoms *data, rb_insert_color(&data->node, root); } -static int thread_atoms_insert(struct perf_sched *sched, struct thread *thread) +static void thread_atoms_insert(struct thread *thread) { struct work_atoms *atoms = zalloc(sizeof(*atoms)); - if (!atoms) { - pr_err("No memory at %s\n", __func__); - return -1; - } + if (!atoms) + die("No memory"); atoms->thread = thread; INIT_LIST_HEAD(&atoms->work_list); - __thread_latency_insert(&sched->atom_root, atoms, &sched->cmp_pid); - return 0; + __thread_latency_insert(&atom_root, atoms, &cmp_pid); } -static int latency_fork_event(struct perf_sched *sched __maybe_unused, - struct perf_evsel *evsel __maybe_unused, - struct perf_sample *sample __maybe_unused) +static void +latency_fork_event(struct trace_fork_event *fork_event __used, + struct event_format *event __used, + int cpu __used, + u64 timestamp __used, + struct thread *thread __used) { /* should insert the newcomer */ - return 0; } -static char sched_out_state(u64 prev_state) +__used +static char sched_out_state(struct trace_switch_event *switch_event) { const char *str = TASK_STATE_TO_CHAR_STR; - return str[prev_state]; + return str[switch_event->prev_state]; } -static int +static void add_sched_out_event(struct work_atoms *atoms, char run_state, u64 timestamp) { struct work_atom *atom = zalloc(sizeof(*atom)); - if (!atom) { - pr_err("Non memory at %s", __func__); - return -1; - } + if (!atom) + die("Non memory"); atom->sched_out_time = timestamp; @@ -859,12 +982,10 @@ add_sched_out_event(struct work_atoms *atoms, } list_add_tail(&atom->list, &atoms->work_list); - return 0; } static void -add_runtime_event(struct work_atoms *atoms, u64 delta, - u64 timestamp __maybe_unused) +add_runtime_event(struct work_atoms *atoms, u64 delta, u64 timestamp __used) { struct work_atom *atom; @@ -907,128 +1028,106 @@ add_sched_in_event(struct work_atoms *atoms, u64 timestamp) atoms->nb_atoms++; } -static int latency_switch_event(struct perf_sched *sched, - struct perf_evsel *evsel, - struct perf_sample *sample, - struct machine *machine) +static void +latency_switch_event(struct trace_switch_event *switch_event, + struct machine *machine, + struct event_format *event __used, + int cpu, + u64 timestamp, + struct thread *thread __used) { - const u32 prev_pid = perf_evsel__intval(evsel, sample, "prev_pid"), - next_pid = perf_evsel__intval(evsel, sample, "next_pid"); - const u64 prev_state = perf_evsel__intval(evsel, sample, "prev_state"); struct work_atoms *out_events, *in_events; struct thread *sched_out, *sched_in; - u64 timestamp0, timestamp = sample->time; - int cpu = sample->cpu; + u64 timestamp0; s64 delta; BUG_ON(cpu >= MAX_CPUS || cpu < 0); - timestamp0 = sched->cpu_last_switched[cpu]; - sched->cpu_last_switched[cpu] = timestamp; + timestamp0 = cpu_last_switched[cpu]; + cpu_last_switched[cpu] = timestamp; if (timestamp0) delta = timestamp - timestamp0; else delta = 0; - if (delta < 0) { - pr_err("hm, delta: %" PRIu64 " < 0 ?\n", delta); - return -1; - } + if (delta < 0) + die("hm, delta: %" PRIu64 " < 0 ?\n", delta); + - sched_out = machine__findnew_thread(machine, prev_pid); - sched_in = machine__findnew_thread(machine, next_pid); + sched_out = machine__findnew_thread(machine, switch_event->prev_pid); + sched_in = machine__findnew_thread(machine, switch_event->next_pid); - out_events = thread_atoms_search(&sched->atom_root, sched_out, &sched->cmp_pid); + out_events = thread_atoms_search(&atom_root, sched_out, &cmp_pid); if (!out_events) { - if (thread_atoms_insert(sched, sched_out)) - return -1; - out_events = thread_atoms_search(&sched->atom_root, sched_out, &sched->cmp_pid); - if (!out_events) { - pr_err("out-event: Internal tree error"); - return -1; - } + thread_atoms_insert(sched_out); + out_events = thread_atoms_search(&atom_root, sched_out, &cmp_pid); + if (!out_events) + die("out-event: Internal tree error"); } - if (add_sched_out_event(out_events, sched_out_state(prev_state), timestamp)) - return -1; + add_sched_out_event(out_events, sched_out_state(switch_event), timestamp); - in_events = thread_atoms_search(&sched->atom_root, sched_in, &sched->cmp_pid); + in_events = thread_atoms_search(&atom_root, sched_in, &cmp_pid); if (!in_events) { - if (thread_atoms_insert(sched, sched_in)) - return -1; - in_events = thread_atoms_search(&sched->atom_root, sched_in, &sched->cmp_pid); - if (!in_events) { - pr_err("in-event: Internal tree error"); - return -1; - } + thread_atoms_insert(sched_in); + in_events = thread_atoms_search(&atom_root, sched_in, &cmp_pid); + if (!in_events) + die("in-event: Internal tree error"); /* * Take came in we have not heard about yet, * add in an initial atom in runnable state: */ - if (add_sched_out_event(in_events, 'R', timestamp)) - return -1; + add_sched_out_event(in_events, 'R', timestamp); } add_sched_in_event(in_events, timestamp); - - return 0; } -static int latency_runtime_event(struct perf_sched *sched, - struct perf_evsel *evsel, - struct perf_sample *sample, - struct machine *machine) +static void +latency_runtime_event(struct trace_runtime_event *runtime_event, + struct machine *machine, + struct event_format *event __used, + int cpu, + u64 timestamp, + struct thread *this_thread __used) { - const u32 pid = perf_evsel__intval(evsel, sample, "pid"); - const u64 runtime = perf_evsel__intval(evsel, sample, "runtime"); - struct thread *thread = machine__findnew_thread(machine, pid); - struct work_atoms *atoms = thread_atoms_search(&sched->atom_root, thread, &sched->cmp_pid); - u64 timestamp = sample->time; - int cpu = sample->cpu; + struct thread *thread = machine__findnew_thread(machine, runtime_event->pid); + struct work_atoms *atoms = thread_atoms_search(&atom_root, thread, &cmp_pid); BUG_ON(cpu >= MAX_CPUS || cpu < 0); if (!atoms) { - if (thread_atoms_insert(sched, thread)) - return -1; - atoms = thread_atoms_search(&sched->atom_root, thread, &sched->cmp_pid); - if (!atoms) { - pr_err("in-event: Internal tree error"); - return -1; - } - if (add_sched_out_event(atoms, 'R', timestamp)) - return -1; + thread_atoms_insert(thread); + atoms = thread_atoms_search(&atom_root, thread, &cmp_pid); + if (!atoms) + die("in-event: Internal tree error"); + add_sched_out_event(atoms, 'R', timestamp); } - add_runtime_event(atoms, runtime, timestamp); - return 0; + add_runtime_event(atoms, runtime_event->runtime, timestamp); } -static int latency_wakeup_event(struct perf_sched *sched, - struct perf_evsel *evsel, - struct perf_sample *sample, - struct machine *machine) +static void +latency_wakeup_event(struct trace_wakeup_event *wakeup_event, + struct machine *machine, + struct event_format *__event __used, + int cpu __used, + u64 timestamp, + struct thread *thread __used) { - const u32 pid = perf_evsel__intval(evsel, sample, "pid"), - success = perf_evsel__intval(evsel, sample, "success"); struct work_atoms *atoms; struct work_atom *atom; struct thread *wakee; - u64 timestamp = sample->time; /* Note for later, it may be interesting to observe the failing cases */ - if (!success) - return 0; + if (!wakeup_event->success) + return; - wakee = machine__findnew_thread(machine, pid); - atoms = thread_atoms_search(&sched->atom_root, wakee, &sched->cmp_pid); + wakee = machine__findnew_thread(machine, wakeup_event->pid); + atoms = thread_atoms_search(&atom_root, wakee, &cmp_pid); if (!atoms) { - if (thread_atoms_insert(sched, wakee)) - return -1; - atoms = thread_atoms_search(&sched->atom_root, wakee, &sched->cmp_pid); - if (!atoms) { - pr_err("wakeup-event: Internal tree error"); - return -1; - } - if (add_sched_out_event(atoms, 'S', timestamp)) - return -1; + thread_atoms_insert(wakee); + atoms = thread_atoms_search(&atom_root, wakee, &cmp_pid); + if (!atoms) + die("wakeup-event: Internal tree error"); + add_sched_out_event(atoms, 'S', timestamp); } BUG_ON(list_empty(&atoms->work_list)); @@ -1040,27 +1139,27 @@ static int latency_wakeup_event(struct perf_sched *sched, * one CPU, or are only looking at only one, so don't * make useless noise. */ - if (sched->profile_cpu == -1 && atom->state != THREAD_SLEEPING) - sched->nr_state_machine_bugs++; + if (profile_cpu == -1 && atom->state != THREAD_SLEEPING) + nr_state_machine_bugs++; - sched->nr_timestamps++; + nr_timestamps++; if (atom->sched_out_time > timestamp) { - sched->nr_unordered_timestamps++; - return 0; + nr_unordered_timestamps++; + return; } atom->state = THREAD_WAIT_CPU; atom->wake_up_time = timestamp; - return 0; } -static int latency_migrate_task_event(struct perf_sched *sched, - struct perf_evsel *evsel, - struct perf_sample *sample, - struct machine *machine) +static void +latency_migrate_task_event(struct trace_migrate_task_event *migrate_task_event, + struct machine *machine, + struct event_format *__event __used, + int cpu __used, + u64 timestamp, + struct thread *thread __used) { - const u32 pid = perf_evsel__intval(evsel, sample, "pid"); - u64 timestamp = sample->time; struct work_atoms *atoms; struct work_atom *atom; struct thread *migrant; @@ -1068,22 +1167,18 @@ static int latency_migrate_task_event(struct perf_sched *sched, /* * Only need to worry about migration when profiling one CPU. */ - if (sched->profile_cpu == -1) - return 0; + if (profile_cpu == -1) + return; - migrant = machine__findnew_thread(machine, pid); - atoms = thread_atoms_search(&sched->atom_root, migrant, &sched->cmp_pid); + migrant = machine__findnew_thread(machine, migrate_task_event->pid); + atoms = thread_atoms_search(&atom_root, migrant, &cmp_pid); if (!atoms) { - if (thread_atoms_insert(sched, migrant)) - return -1; - register_pid(sched, migrant->pid, migrant->comm); - atoms = thread_atoms_search(&sched->atom_root, migrant, &sched->cmp_pid); - if (!atoms) { - pr_err("migration-event: Internal tree error"); - return -1; - } - if (add_sched_out_event(atoms, 'R', timestamp)) - return -1; + thread_atoms_insert(migrant); + register_pid(migrant->pid, migrant->comm); + atoms = thread_atoms_search(&atom_root, migrant, &cmp_pid); + if (!atoms) + die("migration-event: Internal tree error"); + add_sched_out_event(atoms, 'R', timestamp); } BUG_ON(list_empty(&atoms->work_list)); @@ -1091,15 +1186,21 @@ static int latency_migrate_task_event(struct perf_sched *sched, atom = list_entry(atoms->work_list.prev, struct work_atom, list); atom->sched_in_time = atom->sched_out_time = atom->wake_up_time = timestamp; - sched->nr_timestamps++; + nr_timestamps++; if (atom->sched_out_time > timestamp) - sched->nr_unordered_timestamps++; - - return 0; + nr_unordered_timestamps++; } -static void output_lat_thread(struct perf_sched *sched, struct work_atoms *work_list) +static struct trace_sched_handler lat_ops = { + .wakeup_event = latency_wakeup_event, + .switch_event = latency_switch_event, + .runtime_event = latency_runtime_event, + .fork_event = latency_fork_event, + .migrate_task_event = latency_migrate_task_event, +}; + +static void output_lat_thread(struct work_atoms *work_list) { int i; int ret; @@ -1113,8 +1214,8 @@ static void output_lat_thread(struct perf_sched *sched, struct work_atoms *work_ if (!strcmp(work_list->thread->comm, "swapper")) return; - sched->all_runtime += work_list->total_runtime; - sched->all_count += work_list->nb_atoms; + all_runtime += work_list->total_runtime; + all_count += work_list->nb_atoms; ret = printf(" %s:%d ", work_list->thread->comm, work_list->thread->pid); @@ -1140,6 +1241,11 @@ static int pid_cmp(struct work_atoms *l, struct work_atoms *r) return 0; } +static struct sort_dimension pid_sort_dimension = { + .name = "pid", + .cmp = pid_cmp, +}; + static int avg_cmp(struct work_atoms *l, struct work_atoms *r) { u64 avgl, avgr; @@ -1161,6 +1267,11 @@ static int avg_cmp(struct work_atoms *l, struct work_atoms *r) return 0; } +static struct sort_dimension avg_sort_dimension = { + .name = "avg", + .cmp = avg_cmp, +}; + static int max_cmp(struct work_atoms *l, struct work_atoms *r) { if (l->max_lat < r->max_lat) @@ -1171,6 +1282,11 @@ static int max_cmp(struct work_atoms *l, struct work_atoms *r) return 0; } +static struct sort_dimension max_sort_dimension = { + .name = "max", + .cmp = max_cmp, +}; + static int switch_cmp(struct work_atoms *l, struct work_atoms *r) { if (l->nb_atoms < r->nb_atoms) @@ -1181,6 +1297,11 @@ static int switch_cmp(struct work_atoms *l, struct work_atoms *r) return 0; } +static struct sort_dimension switch_sort_dimension = { + .name = "switch", + .cmp = switch_cmp, +}; + static int runtime_cmp(struct work_atoms *l, struct work_atoms *r) { if (l->total_runtime < r->total_runtime) @@ -1191,38 +1312,28 @@ static int runtime_cmp(struct work_atoms *l, struct work_atoms *r) return 0; } +static struct sort_dimension runtime_sort_dimension = { + .name = "runtime", + .cmp = runtime_cmp, +}; + +static struct sort_dimension *available_sorts[] = { + &pid_sort_dimension, + &avg_sort_dimension, + &max_sort_dimension, + &switch_sort_dimension, + &runtime_sort_dimension, +}; + +#define NB_AVAILABLE_SORTS (int)(sizeof(available_sorts) / sizeof(struct sort_dimension *)) + +static LIST_HEAD(sort_list); + static int sort_dimension__add(const char *tok, struct list_head *list) { - size_t i; - static struct sort_dimension avg_sort_dimension = { - .name = "avg", - .cmp = avg_cmp, - }; - static struct sort_dimension max_sort_dimension = { - .name = "max", - .cmp = max_cmp, - }; - static struct sort_dimension pid_sort_dimension = { - .name = "pid", - .cmp = pid_cmp, - }; - static struct sort_dimension runtime_sort_dimension = { - .name = "runtime", - .cmp = runtime_cmp, - }; - static struct sort_dimension switch_sort_dimension = { - .name = "switch", - .cmp = switch_cmp, - }; - struct sort_dimension *available_sorts[] = { - &pid_sort_dimension, - &avg_sort_dimension, - &max_sort_dimension, - &switch_sort_dimension, - &runtime_sort_dimension, - }; + int i; - for (i = 0; i < ARRAY_SIZE(available_sorts); i++) { + for (i = 0; i < NB_AVAILABLE_SORTS; i++) { if (!strcmp(available_sorts[i]->name, tok)) { list_add_tail(&available_sorts[i]->list, list); @@ -1233,97 +1344,126 @@ static int sort_dimension__add(const char *tok, struct list_head *list) return -1; } -static void perf_sched__sort_lat(struct perf_sched *sched) +static void setup_sorting(void); + +static void sort_lat(void) { struct rb_node *node; for (;;) { struct work_atoms *data; - node = rb_first(&sched->atom_root); + node = rb_first(&atom_root); if (!node) break; - rb_erase(node, &sched->atom_root); + rb_erase(node, &atom_root); data = rb_entry(node, struct work_atoms, node); - __thread_latency_insert(&sched->sorted_atom_root, data, &sched->sort_list); + __thread_latency_insert(&sorted_atom_root, data, &sort_list); } } -static int process_sched_wakeup_event(struct perf_tool *tool, - struct perf_evsel *evsel, - struct perf_sample *sample, - struct machine *machine) +static struct trace_sched_handler *trace_handler; + +static void +process_sched_wakeup_event(struct perf_tool *tool __used, + struct event_format *event, + struct perf_sample *sample, + struct machine *machine, + struct thread *thread) { - struct perf_sched *sched = container_of(tool, struct perf_sched, tool); + void *data = sample->raw_data; + struct trace_wakeup_event wakeup_event; - if (sched->tp_handler->wakeup_event) - return sched->tp_handler->wakeup_event(sched, evsel, sample, machine); + FILL_COMMON_FIELDS(wakeup_event, event, data); - return 0; + FILL_ARRAY(wakeup_event, comm, event, data); + FILL_FIELD(wakeup_event, pid, event, data); + FILL_FIELD(wakeup_event, prio, event, data); + FILL_FIELD(wakeup_event, success, event, data); + FILL_FIELD(wakeup_event, cpu, event, data); + + if (trace_handler->wakeup_event) + trace_handler->wakeup_event(&wakeup_event, machine, event, + sample->cpu, sample->time, thread); } -static int map_switch_event(struct perf_sched *sched, struct perf_evsel *evsel, - struct perf_sample *sample, struct machine *machine) +/* + * Track the current task - that way we can know whether there's any + * weird events, such as a task being switched away that is not current. + */ +static int max_cpu; + +static u32 curr_pid[MAX_CPUS] = { [0 ... MAX_CPUS-1] = -1 }; + +static struct thread *curr_thread[MAX_CPUS]; + +static char next_shortname1 = 'A'; +static char next_shortname2 = '0'; + +static void +map_switch_event(struct trace_switch_event *switch_event, + struct machine *machine, + struct event_format *event __used, + int this_cpu, + u64 timestamp, + struct thread *thread __used) { - const u32 prev_pid = perf_evsel__intval(evsel, sample, "prev_pid"), - next_pid = perf_evsel__intval(evsel, sample, "next_pid"); - struct thread *sched_out __maybe_unused, *sched_in; + struct thread *sched_out __used, *sched_in; int new_shortname; - u64 timestamp0, timestamp = sample->time; + u64 timestamp0; s64 delta; - int cpu, this_cpu = sample->cpu; + int cpu; BUG_ON(this_cpu >= MAX_CPUS || this_cpu < 0); - if (this_cpu > sched->max_cpu) - sched->max_cpu = this_cpu; + if (this_cpu > max_cpu) + max_cpu = this_cpu; - timestamp0 = sched->cpu_last_switched[this_cpu]; - sched->cpu_last_switched[this_cpu] = timestamp; + timestamp0 = cpu_last_switched[this_cpu]; + cpu_last_switched[this_cpu] = timestamp; if (timestamp0) delta = timestamp - timestamp0; else delta = 0; - if (delta < 0) { - pr_err("hm, delta: %" PRIu64 " < 0 ?\n", delta); - return -1; - } + if (delta < 0) + die("hm, delta: %" PRIu64 " < 0 ?\n", delta); - sched_out = machine__findnew_thread(machine, prev_pid); - sched_in = machine__findnew_thread(machine, next_pid); - sched->curr_thread[this_cpu] = sched_in; + sched_out = machine__findnew_thread(machine, switch_event->prev_pid); + sched_in = machine__findnew_thread(machine, switch_event->next_pid); + + curr_thread[this_cpu] = sched_in; printf(" "); new_shortname = 0; if (!sched_in->shortname[0]) { - sched_in->shortname[0] = sched->next_shortname1; - sched_in->shortname[1] = sched->next_shortname2; + sched_in->shortname[0] = next_shortname1; + sched_in->shortname[1] = next_shortname2; - if (sched->next_shortname1 < 'Z') { - sched->next_shortname1++; + if (next_shortname1 < 'Z') { + next_shortname1++; } else { - sched->next_shortname1='A'; - if (sched->next_shortname2 < '9') { - sched->next_shortname2++; + next_shortname1='A'; + if (next_shortname2 < '9') { + next_shortname2++; } else { - sched->next_shortname2='0'; + next_shortname2='0'; } } new_shortname = 1; } - for (cpu = 0; cpu <= sched->max_cpu; cpu++) { + for (cpu = 0; cpu <= max_cpu; cpu++) { if (cpu != this_cpu) printf(" "); else printf("*"); - if (sched->curr_thread[cpu]) { - if (sched->curr_thread[cpu]->pid) - printf("%2s ", sched->curr_thread[cpu]->shortname); + if (curr_thread[cpu]) { + if (curr_thread[cpu]->pid) + printf("%2s ", curr_thread[cpu]->shortname); else printf(". "); } else @@ -1337,97 +1477,134 @@ static int map_switch_event(struct perf_sched *sched, struct perf_evsel *evsel, } else { printf("\n"); } - - return 0; } -static int process_sched_switch_event(struct perf_tool *tool, - struct perf_evsel *evsel, - struct perf_sample *sample, - struct machine *machine) +static void +process_sched_switch_event(struct perf_tool *tool __used, + struct event_format *event, + struct perf_sample *sample, + struct machine *machine, + struct thread *thread) { - struct perf_sched *sched = container_of(tool, struct perf_sched, tool); - int this_cpu = sample->cpu, err = 0; - u32 prev_pid = perf_evsel__intval(evsel, sample, "prev_pid"), - next_pid = perf_evsel__intval(evsel, sample, "next_pid"); + int this_cpu = sample->cpu; + void *data = sample->raw_data; + struct trace_switch_event switch_event; + + FILL_COMMON_FIELDS(switch_event, event, data); - if (sched->curr_pid[this_cpu] != (u32)-1) { + FILL_ARRAY(switch_event, prev_comm, event, data); + FILL_FIELD(switch_event, prev_pid, event, data); + FILL_FIELD(switch_event, prev_prio, event, data); + FILL_FIELD(switch_event, prev_state, event, data); + FILL_ARRAY(switch_event, next_comm, event, data); + FILL_FIELD(switch_event, next_pid, event, data); + FILL_FIELD(switch_event, next_prio, event, data); + + if (curr_pid[this_cpu] != (u32)-1) { /* * Are we trying to switch away a PID that is * not current? */ - if (sched->curr_pid[this_cpu] != prev_pid) - sched->nr_context_switch_bugs++; + if (curr_pid[this_cpu] != switch_event.prev_pid) + nr_context_switch_bugs++; } + if (trace_handler->switch_event) + trace_handler->switch_event(&switch_event, machine, event, + this_cpu, sample->time, thread); - if (sched->tp_handler->switch_event) - err = sched->tp_handler->switch_event(sched, evsel, sample, machine); - - sched->curr_pid[this_cpu] = next_pid; - return err; + curr_pid[this_cpu] = switch_event.next_pid; } -static int process_sched_runtime_event(struct perf_tool *tool, - struct perf_evsel *evsel, - struct perf_sample *sample, - struct machine *machine) +static void +process_sched_runtime_event(struct perf_tool *tool __used, + struct event_format *event, + struct perf_sample *sample, + struct machine *machine, + struct thread *thread) { - struct perf_sched *sched = container_of(tool, struct perf_sched, tool); + void *data = sample->raw_data; + struct trace_runtime_event runtime_event; - if (sched->tp_handler->runtime_event) - return sched->tp_handler->runtime_event(sched, evsel, sample, machine); + FILL_ARRAY(runtime_event, comm, event, data); + FILL_FIELD(runtime_event, pid, event, data); + FILL_FIELD(runtime_event, runtime, event, data); + FILL_FIELD(runtime_event, vruntime, event, data); - return 0; + if (trace_handler->runtime_event) + trace_handler->runtime_event(&runtime_event, machine, event, + sample->cpu, sample->time, thread); } -static int process_sched_fork_event(struct perf_tool *tool, - struct perf_evsel *evsel, - struct perf_sample *sample, - struct machine *machine __maybe_unused) +static void +process_sched_fork_event(struct perf_tool *tool __used, + struct event_format *event, + struct perf_sample *sample, + struct machine *machine __used, + struct thread *thread) { - struct perf_sched *sched = container_of(tool, struct perf_sched, tool); + void *data = sample->raw_data; + struct trace_fork_event fork_event; - if (sched->tp_handler->fork_event) - return sched->tp_handler->fork_event(sched, evsel, sample); + FILL_COMMON_FIELDS(fork_event, event, data); - return 0; + FILL_ARRAY(fork_event, parent_comm, event, data); + FILL_FIELD(fork_event, parent_pid, event, data); + FILL_ARRAY(fork_event, child_comm, event, data); + FILL_FIELD(fork_event, child_pid, event, data); + + if (trace_handler->fork_event) + trace_handler->fork_event(&fork_event, event, + sample->cpu, sample->time, thread); } -static int process_sched_exit_event(struct perf_tool *tool __maybe_unused, - struct perf_evsel *evsel, - struct perf_sample *sample __maybe_unused, - struct machine *machine __maybe_unused) +static void +process_sched_exit_event(struct perf_tool *tool __used, + struct event_format *event, + struct perf_sample *sample __used, + struct machine *machine __used, + struct thread *thread __used) { - pr_debug("sched_exit event %p\n", evsel); - return 0; + if (verbose) + printf("sched_exit event %p\n", event); } -static int process_sched_migrate_task_event(struct perf_tool *tool, - struct perf_evsel *evsel, - struct perf_sample *sample, - struct machine *machine) +static void +process_sched_migrate_task_event(struct perf_tool *tool __used, + struct event_format *event, + struct perf_sample *sample, + struct machine *machine, + struct thread *thread) { - struct perf_sched *sched = container_of(tool, struct perf_sched, tool); + void *data = sample->raw_data; + struct trace_migrate_task_event migrate_task_event; - if (sched->tp_handler->migrate_task_event) - return sched->tp_handler->migrate_task_event(sched, evsel, sample, machine); + FILL_COMMON_FIELDS(migrate_task_event, event, data); - return 0; + FILL_ARRAY(migrate_task_event, comm, event, data); + FILL_FIELD(migrate_task_event, pid, event, data); + FILL_FIELD(migrate_task_event, prio, event, data); + FILL_FIELD(migrate_task_event, cpu, event, data); + + if (trace_handler->migrate_task_event) + trace_handler->migrate_task_event(&migrate_task_event, machine, + event, sample->cpu, + sample->time, thread); } -typedef int (*tracepoint_handler)(struct perf_tool *tool, - struct perf_evsel *evsel, - struct perf_sample *sample, - struct machine *machine); +typedef void (*tracepoint_handler)(struct perf_tool *tool, struct event_format *event, + struct perf_sample *sample, + struct machine *machine, + struct thread *thread); -static int perf_sched__process_tracepoint_sample(struct perf_tool *tool __maybe_unused, - union perf_event *event __maybe_unused, +static int perf_sched__process_tracepoint_sample(struct perf_tool *tool, + union perf_event *event __used, struct perf_sample *sample, struct perf_evsel *evsel, struct machine *machine) { + struct perf_sched *sched = container_of(tool, struct perf_sched, tool); + struct pevent *pevent = sched->session->pevent; struct thread *thread = machine__findnew_thread(machine, sample->pid); - int err = 0; if (thread == NULL) { pr_debug("problem processing %s event, skipping it.\n", @@ -1440,15 +1617,30 @@ static int perf_sched__process_tracepoint_sample(struct perf_tool *tool __maybe_ if (evsel->handler.func != NULL) { tracepoint_handler f = evsel->handler.func; - err = f(tool, evsel, sample, machine); + + if (evsel->handler.data == NULL) + evsel->handler.data = pevent_find_event(pevent, + evsel->attr.config); + + f(tool, evsel->handler.data, sample, machine, thread); } - return err; + return 0; } -static int perf_sched__read_events(struct perf_sched *sched, bool destroy, - struct perf_session **psession) +static struct perf_sched perf_sched = { + .tool = { + .sample = perf_sched__process_tracepoint_sample, + .comm = perf_event__process_comm, + .lost = perf_event__process_lost, + .fork = perf_event__process_task, + .ordered_samples = true, + }, +}; + +static void read_events(bool destroy, struct perf_session **psession) { + int err = -EINVAL; const struct perf_evsel_str_handler handlers[] = { { "sched:sched_switch", process_sched_switch_event, }, { "sched:sched_stat_runtime", process_sched_runtime_event, }, @@ -1460,25 +1652,24 @@ static int perf_sched__read_events(struct perf_sched *sched, bool destroy, }; struct perf_session *session; - session = perf_session__new(sched->input_name, O_RDONLY, 0, false, &sched->tool); - if (session == NULL) { - pr_debug("No Memory for session\n"); - return -1; - } + session = perf_session__new(input_name, O_RDONLY, 0, false, + &perf_sched.tool); + if (session == NULL) + die("No Memory"); + + perf_sched.session = session; - if (perf_session__set_tracepoints_handlers(session, handlers)) - goto out_delete; + err = perf_session__set_tracepoints_handlers(session, handlers); + assert(err == 0); if (perf_session__has_traces(session, "record -R")) { - int err = perf_session__process_events(session, &sched->tool); - if (err) { - pr_err("Failed to process events, error %d", err); - goto out_delete; - } + err = perf_session__process_events(session, &perf_sched.tool); + if (err) + die("Failed to process events, error %d", err); - sched->nr_events = session->hists.stats.nr_events[0]; - sched->nr_lost_events = session->hists.stats.total_lost; - sched->nr_lost_chunks = session->hists.stats.nr_events[PERF_RECORD_LOST]; + nr_events = session->hists.stats.nr_events[0]; + nr_lost_events = session->hists.stats.total_lost; + nr_lost_chunks = session->hists.stats.nr_events[PERF_RECORD_LOST]; } if (destroy) @@ -1486,166 +1677,208 @@ static int perf_sched__read_events(struct perf_sched *sched, bool destroy, if (psession) *psession = session; - - return 0; - -out_delete: - perf_session__delete(session); - return -1; } -static void print_bad_events(struct perf_sched *sched) +static void print_bad_events(void) { - if (sched->nr_unordered_timestamps && sched->nr_timestamps) { + if (nr_unordered_timestamps && nr_timestamps) { printf(" INFO: %.3f%% unordered timestamps (%ld out of %ld)\n", - (double)sched->nr_unordered_timestamps/(double)sched->nr_timestamps*100.0, - sched->nr_unordered_timestamps, sched->nr_timestamps); + (double)nr_unordered_timestamps/(double)nr_timestamps*100.0, + nr_unordered_timestamps, nr_timestamps); } - if (sched->nr_lost_events && sched->nr_events) { + if (nr_lost_events && nr_events) { printf(" INFO: %.3f%% lost events (%ld out of %ld, in %ld chunks)\n", - (double)sched->nr_lost_events/(double)sched->nr_events * 100.0, - sched->nr_lost_events, sched->nr_events, sched->nr_lost_chunks); + (double)nr_lost_events/(double)nr_events*100.0, + nr_lost_events, nr_events, nr_lost_chunks); } - if (sched->nr_state_machine_bugs && sched->nr_timestamps) { + if (nr_state_machine_bugs && nr_timestamps) { printf(" INFO: %.3f%% state machine bugs (%ld out of %ld)", - (double)sched->nr_state_machine_bugs/(double)sched->nr_timestamps*100.0, - sched->nr_state_machine_bugs, sched->nr_timestamps); - if (sched->nr_lost_events) + (double)nr_state_machine_bugs/(double)nr_timestamps*100.0, + nr_state_machine_bugs, nr_timestamps); + if (nr_lost_events) printf(" (due to lost events?)"); printf("\n"); } - if (sched->nr_context_switch_bugs && sched->nr_timestamps) { + if (nr_context_switch_bugs && nr_timestamps) { printf(" INFO: %.3f%% context switch bugs (%ld out of %ld)", - (double)sched->nr_context_switch_bugs/(double)sched->nr_timestamps*100.0, - sched->nr_context_switch_bugs, sched->nr_timestamps); - if (sched->nr_lost_events) + (double)nr_context_switch_bugs/(double)nr_timestamps*100.0, + nr_context_switch_bugs, nr_timestamps); + if (nr_lost_events) printf(" (due to lost events?)"); printf("\n"); } } -static int perf_sched__lat(struct perf_sched *sched) +static void __cmd_lat(void) { struct rb_node *next; struct perf_session *session; setup_pager(); - if (perf_sched__read_events(sched, false, &session)) - return -1; - perf_sched__sort_lat(sched); + read_events(false, &session); + sort_lat(); printf("\n ---------------------------------------------------------------------------------------------------------------\n"); printf(" Task | Runtime ms | Switches | Average delay ms | Maximum delay ms | Maximum delay at |\n"); printf(" ---------------------------------------------------------------------------------------------------------------\n"); - next = rb_first(&sched->sorted_atom_root); + next = rb_first(&sorted_atom_root); while (next) { struct work_atoms *work_list; work_list = rb_entry(next, struct work_atoms, node); - output_lat_thread(sched, work_list); + output_lat_thread(work_list); next = rb_next(next); } printf(" -----------------------------------------------------------------------------------------\n"); printf(" TOTAL: |%11.3f ms |%9" PRIu64 " |\n", - (double)sched->all_runtime / 1e6, sched->all_count); + (double)all_runtime/1e6, all_count); printf(" ---------------------------------------------------\n"); - print_bad_events(sched); + print_bad_events(); printf("\n"); perf_session__delete(session); - return 0; } -static int perf_sched__map(struct perf_sched *sched) +static struct trace_sched_handler map_ops = { + .wakeup_event = NULL, + .switch_event = map_switch_event, + .runtime_event = NULL, + .fork_event = NULL, +}; + +static void __cmd_map(void) { - sched->max_cpu = sysconf(_SC_NPROCESSORS_CONF); + max_cpu = sysconf(_SC_NPROCESSORS_CONF); setup_pager(); - if (perf_sched__read_events(sched, true, NULL)) - return -1; - print_bad_events(sched); - return 0; + read_events(true, NULL); + print_bad_events(); } -static int perf_sched__replay(struct perf_sched *sched) +static void __cmd_replay(void) { unsigned long i; - calibrate_run_measurement_overhead(sched); - calibrate_sleep_measurement_overhead(sched); + calibrate_run_measurement_overhead(); + calibrate_sleep_measurement_overhead(); - test_calibrations(sched); + test_calibrations(); - if (perf_sched__read_events(sched, true, NULL)) - return -1; + read_events(true, NULL); - printf("nr_run_events: %ld\n", sched->nr_run_events); - printf("nr_sleep_events: %ld\n", sched->nr_sleep_events); - printf("nr_wakeup_events: %ld\n", sched->nr_wakeup_events); + printf("nr_run_events: %ld\n", nr_run_events); + printf("nr_sleep_events: %ld\n", nr_sleep_events); + printf("nr_wakeup_events: %ld\n", nr_wakeup_events); - if (sched->targetless_wakeups) - printf("target-less wakeups: %ld\n", sched->targetless_wakeups); - if (sched->multitarget_wakeups) - printf("multi-target wakeups: %ld\n", sched->multitarget_wakeups); - if (sched->nr_run_events_optimized) + if (targetless_wakeups) + printf("target-less wakeups: %ld\n", targetless_wakeups); + if (multitarget_wakeups) + printf("multi-target wakeups: %ld\n", multitarget_wakeups); + if (nr_run_events_optimized) printf("run atoms optimized: %ld\n", - sched->nr_run_events_optimized); + nr_run_events_optimized); - print_task_traces(sched); - add_cross_task_wakeups(sched); + print_task_traces(); + add_cross_task_wakeups(); - create_tasks(sched); + create_tasks(); printf("------------------------------------------------------------\n"); - for (i = 0; i < sched->replay_repeat; i++) - run_one_test(sched); - - return 0; + for (i = 0; i < replay_repeat; i++) + run_one_test(); } -static void setup_sorting(struct perf_sched *sched, const struct option *options, - const char * const usage_msg[]) + +static const char * const sched_usage[] = { + "perf sched [] {record|latency|map|replay|script}", + NULL +}; + +static const struct option sched_options[] = { + OPT_STRING('i', "input", &input_name, "file", + "input file name"), + OPT_INCR('v', "verbose", &verbose, + "be more verbose (show symbol address, etc)"), + OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, + "dump raw trace in ASCII"), + OPT_END() +}; + +static const char * const latency_usage[] = { + "perf sched latency []", + NULL +}; + +static const struct option latency_options[] = { + OPT_STRING('s', "sort", &sort_order, "key[,key2...]", + "sort by key(s): runtime, switch, avg, max"), + OPT_INCR('v', "verbose", &verbose, + "be more verbose (show symbol address, etc)"), + OPT_INTEGER('C', "CPU", &profile_cpu, + "CPU to profile on"), + OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, + "dump raw trace in ASCII"), + OPT_END() +}; + +static const char * const replay_usage[] = { + "perf sched replay []", + NULL +}; + +static const struct option replay_options[] = { + OPT_UINTEGER('r', "repeat", &replay_repeat, + "repeat the workload replay N times (-1: infinite)"), + OPT_INCR('v', "verbose", &verbose, + "be more verbose (show symbol address, etc)"), + OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, + "dump raw trace in ASCII"), + OPT_END() +}; + +static void setup_sorting(void) { - char *tmp, *tok, *str = strdup(sched->sort_order); + char *tmp, *tok, *str = strdup(sort_order); for (tok = strtok_r(str, ", ", &tmp); tok; tok = strtok_r(NULL, ", ", &tmp)) { - if (sort_dimension__add(tok, &sched->sort_list) < 0) { + if (sort_dimension__add(tok, &sort_list) < 0) { error("Unknown --sort key: `%s'", tok); - usage_with_options(usage_msg, options); + usage_with_options(latency_usage, latency_options); } } free(str); - sort_dimension__add("pid", &sched->cmp_pid); + sort_dimension__add("pid", &cmp_pid); } +static const char *record_args[] = { + "record", + "-a", + "-R", + "-f", + "-m", "1024", + "-c", "1", + "-e", "sched:sched_switch", + "-e", "sched:sched_stat_wait", + "-e", "sched:sched_stat_sleep", + "-e", "sched:sched_stat_iowait", + "-e", "sched:sched_stat_runtime", + "-e", "sched:sched_process_exit", + "-e", "sched:sched_process_fork", + "-e", "sched:sched_wakeup", + "-e", "sched:sched_migrate_task", +}; + static int __cmd_record(int argc, const char **argv) { unsigned int rec_argc, i, j; const char **rec_argv; - const char * const record_args[] = { - "record", - "-a", - "-R", - "-f", - "-m", "1024", - "-c", "1", - "-e", "sched:sched_switch", - "-e", "sched:sched_stat_wait", - "-e", "sched:sched_stat_sleep", - "-e", "sched:sched_stat_iowait", - "-e", "sched:sched_stat_runtime", - "-e", "sched:sched_process_exit", - "-e", "sched:sched_process_fork", - "-e", "sched:sched_wakeup", - "-e", "sched:sched_migrate_task", - }; rec_argc = ARRAY_SIZE(record_args) + argc - 1; rec_argv = calloc(rec_argc + 1, sizeof(char *)); @@ -1664,85 +1897,8 @@ static int __cmd_record(int argc, const char **argv) return cmd_record(i, rec_argv, NULL); } -int cmd_sched(int argc, const char **argv, const char *prefix __maybe_unused) +int cmd_sched(int argc, const char **argv, const char *prefix __used) { - const char default_sort_order[] = "avg, max, switch, runtime"; - struct perf_sched sched = { - .tool = { - .sample = perf_sched__process_tracepoint_sample, - .comm = perf_event__process_comm, - .lost = perf_event__process_lost, - .fork = perf_event__process_task, - .ordered_samples = true, - }, - .cmp_pid = LIST_HEAD_INIT(sched.cmp_pid), - .sort_list = LIST_HEAD_INIT(sched.sort_list), - .start_work_mutex = PTHREAD_MUTEX_INITIALIZER, - .work_done_wait_mutex = PTHREAD_MUTEX_INITIALIZER, - .curr_pid = { [0 ... MAX_CPUS - 1] = -1 }, - .sort_order = default_sort_order, - .replay_repeat = 10, - .profile_cpu = -1, - .next_shortname1 = 'A', - .next_shortname2 = '0', - }; - const struct option latency_options[] = { - OPT_STRING('s', "sort", &sched.sort_order, "key[,key2...]", - "sort by key(s): runtime, switch, avg, max"), - OPT_INCR('v', "verbose", &verbose, - "be more verbose (show symbol address, etc)"), - OPT_INTEGER('C', "CPU", &sched.profile_cpu, - "CPU to profile on"), - OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, - "dump raw trace in ASCII"), - OPT_END() - }; - const struct option replay_options[] = { - OPT_UINTEGER('r', "repeat", &sched.replay_repeat, - "repeat the workload replay N times (-1: infinite)"), - OPT_INCR('v', "verbose", &verbose, - "be more verbose (show symbol address, etc)"), - OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, - "dump raw trace in ASCII"), - OPT_END() - }; - const struct option sched_options[] = { - OPT_STRING('i', "input", &sched.input_name, "file", - "input file name"), - OPT_INCR('v', "verbose", &verbose, - "be more verbose (show symbol address, etc)"), - OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, - "dump raw trace in ASCII"), - OPT_END() - }; - const char * const latency_usage[] = { - "perf sched latency []", - NULL - }; - const char * const replay_usage[] = { - "perf sched replay []", - NULL - }; - const char * const sched_usage[] = { - "perf sched [] {record|latency|map|replay|script}", - NULL - }; - struct trace_sched_handler lat_ops = { - .wakeup_event = latency_wakeup_event, - .switch_event = latency_switch_event, - .runtime_event = latency_runtime_event, - .fork_event = latency_fork_event, - .migrate_task_event = latency_migrate_task_event, - }; - struct trace_sched_handler map_ops = { - .switch_event = map_switch_event, - }; - struct trace_sched_handler replay_ops = { - .wakeup_event = replay_wakeup_event, - .switch_event = replay_switch_event, - .fork_event = replay_fork_event, - }; - argc = parse_options(argc, argv, sched_options, sched_usage, PARSE_OPT_STOP_AT_NON_OPTION); if (!argc) @@ -1758,26 +1914,26 @@ int cmd_sched(int argc, const char **argv, const char *prefix __maybe_unused) if (!strncmp(argv[0], "rec", 3)) { return __cmd_record(argc, argv); } else if (!strncmp(argv[0], "lat", 3)) { - sched.tp_handler = &lat_ops; + trace_handler = &lat_ops; if (argc > 1) { argc = parse_options(argc, argv, latency_options, latency_usage, 0); if (argc) usage_with_options(latency_usage, latency_options); } - setup_sorting(&sched, latency_options, latency_usage); - return perf_sched__lat(&sched); + setup_sorting(); + __cmd_lat(); } else if (!strcmp(argv[0], "map")) { - sched.tp_handler = &map_ops; - setup_sorting(&sched, latency_options, latency_usage); - return perf_sched__map(&sched); + trace_handler = &map_ops; + setup_sorting(); + __cmd_map(); } else if (!strncmp(argv[0], "rep", 3)) { - sched.tp_handler = &replay_ops; + trace_handler = &replay_ops; if (argc) { argc = parse_options(argc, argv, replay_options, replay_usage, 0); if (argc) usage_with_options(replay_usage, replay_options); } - return perf_sched__replay(&sched); + __cmd_replay(); } else { usage_with_options(sched_usage, sched_options); } diff --git a/trunk/tools/perf/builtin-script.c b/trunk/tools/perf/builtin-script.c index 1be843aa1546..1e60ab70b2b1 100644 --- a/trunk/tools/perf/builtin-script.c +++ b/trunk/tools/perf/builtin-script.c @@ -14,7 +14,6 @@ #include "util/util.h" #include "util/evlist.h" #include "util/evsel.h" -#include "util/sort.h" #include static char const *script_name; @@ -29,6 +28,11 @@ static bool system_wide; static const char *cpu_list; static DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS); +struct perf_script { + struct perf_tool tool; + struct perf_session *session; +}; + enum perf_output_field { PERF_OUTPUT_COMM = 1U << 0, PERF_OUTPUT_TID = 1U << 1, @@ -258,11 +262,14 @@ static int perf_session__check_output_opt(struct perf_session *session) return 0; } -static void print_sample_start(struct perf_sample *sample, +static void print_sample_start(struct pevent *pevent, + struct perf_sample *sample, struct thread *thread, struct perf_evsel *evsel) { + int type; struct perf_event_attr *attr = &evsel->attr; + struct event_format *event; const char *evname = NULL; unsigned long secs; unsigned long usecs; @@ -300,7 +307,20 @@ static void print_sample_start(struct perf_sample *sample, } if (PRINT_FIELD(EVNAME)) { - evname = perf_evsel__name(evsel); + if (attr->type == PERF_TYPE_TRACEPOINT) { + /* + * XXX Do we really need this here? + * perf_evlist__set_tracepoint_names should have done + * this already + */ + type = trace_parse_common_type(pevent, + sample->raw_data); + event = pevent_find_event(pevent, type); + if (event) + evname = event->name; + } else + evname = perf_evsel__name(evsel); + printf("%s: ", evname ? evname : "[unknown]"); } } @@ -381,7 +401,7 @@ static void print_sample_bts(union perf_event *event, printf(" "); else printf("\n"); - perf_evsel__print_ip(evsel, event, sample, machine, + perf_event__print_ip(event, sample, machine, PRINT_FIELD(SYM), PRINT_FIELD(DSO), PRINT_FIELD(SYMOFFSET)); } @@ -395,17 +415,19 @@ static void print_sample_bts(union perf_event *event, printf("\n"); } -static void process_event(union perf_event *event, struct perf_sample *sample, - struct perf_evsel *evsel, struct machine *machine, - struct addr_location *al) +static void process_event(union perf_event *event __unused, + struct pevent *pevent, + struct perf_sample *sample, + struct perf_evsel *evsel, + struct machine *machine, + struct thread *thread) { struct perf_event_attr *attr = &evsel->attr; - struct thread *thread = al->thread; if (output[attr->type].fields == 0) return; - print_sample_start(sample, thread, evsel); + print_sample_start(pevent, sample, thread, evsel); if (is_bts_event(attr)) { print_sample_bts(event, sample, evsel, machine, thread); @@ -413,8 +435,9 @@ static void process_event(union perf_event *event, struct perf_sample *sample, } if (PRINT_FIELD(TRACE)) - event_format__print(evsel->tp_format, sample->cpu, - sample->raw_data, sample->raw_size); + print_trace_event(pevent, sample->cpu, sample->raw_data, + sample->raw_size); + if (PRINT_FIELD(ADDR)) print_sample_addr(event, sample, machine, thread, attr); @@ -423,7 +446,7 @@ static void process_event(union perf_event *event, struct perf_sample *sample, printf(" "); else printf("\n"); - perf_evsel__print_ip(evsel, event, sample, machine, + perf_event__print_ip(event, sample, machine, PRINT_FIELD(SYM), PRINT_FIELD(DSO), PRINT_FIELD(SYMOFFSET)); } @@ -431,9 +454,9 @@ static void process_event(union perf_event *event, struct perf_sample *sample, printf("\n"); } -static int default_start_script(const char *script __maybe_unused, - int argc __maybe_unused, - const char **argv __maybe_unused) +static int default_start_script(const char *script __unused, + int argc __unused, + const char **argv __unused) { return 0; } @@ -443,8 +466,8 @@ static int default_stop_script(void) return 0; } -static int default_generate_script(struct pevent *pevent __maybe_unused, - const char *outfile __maybe_unused) +static int default_generate_script(struct pevent *pevent __unused, + const char *outfile __unused) { return 0; } @@ -475,13 +498,14 @@ static int cleanup_scripting(void) static const char *input_name; -static int process_sample_event(struct perf_tool *tool __maybe_unused, +static int process_sample_event(struct perf_tool *tool __used, union perf_event *event, struct perf_sample *sample, struct perf_evsel *evsel, struct machine *machine) { struct addr_location al; + struct perf_script *scr = container_of(tool, struct perf_script, tool); struct thread *thread = machine__findnew_thread(machine, event->ip.tid); if (thread == NULL) { @@ -513,29 +537,32 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused, if (cpu_list && !test_bit(sample->cpu, cpu_bitmap)) return 0; - scripting_ops->process_event(event, sample, evsel, machine, &al); + scripting_ops->process_event(event, scr->session->pevent, + sample, evsel, machine, thread); evsel->hists.stats.total_period += sample->period; return 0; } -static struct perf_tool perf_script = { - .sample = process_sample_event, - .mmap = perf_event__process_mmap, - .comm = perf_event__process_comm, - .exit = perf_event__process_task, - .fork = perf_event__process_task, - .attr = perf_event__process_attr, - .event_type = perf_event__process_event_type, - .tracing_data = perf_event__process_tracing_data, - .build_id = perf_event__process_build_id, - .ordered_samples = true, - .ordering_requires_timestamps = true, +static struct perf_script perf_script = { + .tool = { + .sample = process_sample_event, + .mmap = perf_event__process_mmap, + .comm = perf_event__process_comm, + .exit = perf_event__process_task, + .fork = perf_event__process_task, + .attr = perf_event__process_attr, + .event_type = perf_event__process_event_type, + .tracing_data = perf_event__process_tracing_data, + .build_id = perf_event__process_build_id, + .ordered_samples = true, + .ordering_requires_timestamps = true, + }, }; extern volatile int session_done; -static void sig_handler(int sig __maybe_unused) +static void sig_handler(int sig __unused) { session_done = 1; } @@ -546,7 +573,7 @@ static int __cmd_script(struct perf_session *session) signal(SIGINT, sig_handler); - ret = perf_session__process_events(session, &perf_script); + ret = perf_session__process_events(session, &perf_script.tool); if (debug_mode) pr_err("Misordered timestamps: %" PRIu64 "\n", nr_unordered); @@ -645,8 +672,8 @@ static void list_available_languages(void) fprintf(stderr, "\n"); } -static int parse_scriptname(const struct option *opt __maybe_unused, - const char *str, int unset __maybe_unused) +static int parse_scriptname(const struct option *opt __used, + const char *str, int unset __used) { char spec[PATH_MAX]; const char *script, *ext; @@ -691,8 +718,8 @@ static int parse_scriptname(const struct option *opt __maybe_unused, return 0; } -static int parse_output_fields(const struct option *opt __maybe_unused, - const char *arg, int unset __maybe_unused) +static int parse_output_fields(const struct option *opt __used, + const char *arg, int unset __used) { char *tok; int i, imax = sizeof(all_output_options) / sizeof(struct output_option); @@ -983,9 +1010,8 @@ static char *get_script_root(struct dirent *script_dirent, const char *suffix) return script_root; } -static int list_available_scripts(const struct option *opt __maybe_unused, - const char *s __maybe_unused, - int unset __maybe_unused) +static int list_available_scripts(const struct option *opt __used, + const char *s __used, int unset __used) { struct dirent *script_next, *lang_next, script_dirent, lang_dirent; char scripts_path[MAXPATHLEN]; @@ -1032,61 +1058,6 @@ static int list_available_scripts(const struct option *opt __maybe_unused, exit(0); } -/* - * Return -1 if none is found, otherwise the actual scripts number. - * - * Currently the only user of this function is the script browser, which - * will list all statically runnable scripts, select one, execute it and - * show the output in a perf browser. - */ -int find_scripts(char **scripts_array, char **scripts_path_array) -{ - struct dirent *script_next, *lang_next, script_dirent, lang_dirent; - char scripts_path[MAXPATHLEN]; - DIR *scripts_dir, *lang_dir; - char lang_path[MAXPATHLEN]; - char *temp; - int i = 0; - - snprintf(scripts_path, MAXPATHLEN, "%s/scripts", perf_exec_path()); - - scripts_dir = opendir(scripts_path); - if (!scripts_dir) - return -1; - - for_each_lang(scripts_path, scripts_dir, lang_dirent, lang_next) { - snprintf(lang_path, MAXPATHLEN, "%s/%s", scripts_path, - lang_dirent.d_name); -#ifdef NO_LIBPERL - if (strstr(lang_path, "perl")) - continue; -#endif -#ifdef NO_LIBPYTHON - if (strstr(lang_path, "python")) - continue; -#endif - - lang_dir = opendir(lang_path); - if (!lang_dir) - continue; - - for_each_script(lang_path, lang_dir, script_dirent, script_next) { - /* Skip those real time scripts: xxxtop.p[yl] */ - if (strstr(script_dirent.d_name, "top.")) - continue; - sprintf(scripts_path_array[i], "%s/%s", lang_path, - script_dirent.d_name); - temp = strchr(script_dirent.d_name, '.'); - snprintf(scripts_array[i], - (temp - script_dirent.d_name) + 1, - "%s", script_dirent.d_name); - i++; - } - } - - return i; -} - static char *get_script_path(const char *script_root, const char *suffix) { struct dirent *script_next, *lang_next, script_dirent, lang_dirent; @@ -1199,8 +1170,6 @@ static const struct option options[] = { parse_output_fields), OPT_BOOLEAN('a', "all-cpus", &system_wide, "system-wide collection from all CPUs"), - OPT_STRING('S', "symbols", &symbol_conf.sym_list_str, "symbol[,symbol...]", - "only consider these symbols"), OPT_STRING('C', "cpu", &cpu_list, "cpu", "list of cpus to profile"), OPT_STRING('c', "comms", &symbol_conf.comm_list_str, "comm[,comm...]", "only display events for these comms"), @@ -1212,26 +1181,21 @@ static const struct option options[] = { OPT_END() }; -static int have_cmd(int argc, const char **argv) +static bool have_cmd(int argc, const char **argv) { char **__argv = malloc(sizeof(const char *) * argc); - if (!__argv) { - pr_err("malloc failed\n"); - return -1; - } - + if (!__argv) + die("malloc"); memcpy(__argv, argv, sizeof(const char *) * argc); argc = parse_options(argc, (const char **)__argv, record_options, NULL, PARSE_OPT_STOP_AT_NON_OPTION); free(__argv); - system_wide = (argc == 0); - - return 0; + return argc != 0; } -int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused) +int cmd_script(int argc, const char **argv, const char *prefix __used) { char *rec_script_path = NULL; char *rep_script_path = NULL; @@ -1295,13 +1259,13 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused) if (pipe(live_pipe) < 0) { perror("failed to create pipe"); - return -1; + exit(-1); } pid = fork(); if (pid < 0) { perror("failed to fork"); - return -1; + exit(-1); } if (!pid) { @@ -1313,18 +1277,13 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused) if (is_top_script(argv[0])) { system_wide = true; } else if (!system_wide) { - if (have_cmd(argc - rep_args, &argv[rep_args]) != 0) { - err = -1; - goto out; - } + system_wide = !have_cmd(argc - rep_args, + &argv[rep_args]); } __argv = malloc((argc + 6) * sizeof(const char *)); - if (!__argv) { - pr_err("malloc failed\n"); - err = -ENOMEM; - goto out; - } + if (!__argv) + die("malloc"); __argv[j++] = "/bin/sh"; __argv[j++] = rec_script_path; @@ -1346,12 +1305,8 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused) close(live_pipe[1]); __argv = malloc((argc + 4) * sizeof(const char *)); - if (!__argv) { - pr_err("malloc failed\n"); - err = -ENOMEM; - goto out; - } - + if (!__argv) + die("malloc"); j = 0; __argv[j++] = "/bin/sh"; __argv[j++] = rep_script_path; @@ -1376,20 +1331,12 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused) if (!rec_script_path) system_wide = false; - else if (!system_wide) { - if (have_cmd(argc - 1, &argv[1]) != 0) { - err = -1; - goto out; - } - } + else if (!system_wide) + system_wide = !have_cmd(argc - 1, &argv[1]); __argv = malloc((argc + 2) * sizeof(const char *)); - if (!__argv) { - pr_err("malloc failed\n"); - err = -ENOMEM; - goto out; - } - + if (!__argv) + die("malloc"); __argv[j++] = "/bin/sh"; __argv[j++] = script_path; if (system_wide) @@ -1409,10 +1356,12 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused) setup_pager(); session = perf_session__new(input_name, O_RDONLY, 0, false, - &perf_script); + &perf_script.tool); if (session == NULL) return -ENOMEM; + perf_script.session = session; + if (cpu_list) { if (perf_session__cpu_bitmap(session, cpu_list, cpu_bitmap)) return -1; @@ -1438,18 +1387,18 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused) input = open(session->filename, O_RDONLY); /* input_name */ if (input < 0) { perror("failed to open file"); - return -1; + exit(-1); } err = fstat(input, &perf_stat); if (err < 0) { perror("failed to stat file"); - return -1; + exit(-1); } if (!perf_stat.st_size) { fprintf(stderr, "zero-sized file, nothing to do!\n"); - return 0; + exit(0); } scripting_ops = script_spec__lookup(generate_script_lang); diff --git a/trunk/tools/perf/builtin-stat.c b/trunk/tools/perf/builtin-stat.c index e8cd4d81b06e..861f0aec77ae 100644 --- a/trunk/tools/perf/builtin-stat.c +++ b/trunk/tools/perf/builtin-stat.c @@ -51,13 +51,13 @@ #include "util/evsel.h" #include "util/debug.h" #include "util/color.h" -#include "util/stat.h" #include "util/header.h" #include "util/cpumap.h" #include "util/thread.h" #include "util/thread_map.h" #include +#include #include #define DEFAULT_SEPARATOR " " @@ -199,6 +199,11 @@ static int output_fd; static volatile int done = 0; +struct stats +{ + double n, mean, M2; +}; + struct perf_stat { struct stats res_stats[3]; }; @@ -215,14 +220,48 @@ static void perf_evsel__free_stat_priv(struct perf_evsel *evsel) evsel->priv = NULL; } -static inline struct cpu_map *perf_evsel__cpus(struct perf_evsel *evsel) +static void update_stats(struct stats *stats, u64 val) +{ + double delta; + + stats->n++; + delta = val - stats->mean; + stats->mean += delta / stats->n; + stats->M2 += delta*(val - stats->mean); +} + +static double avg_stats(struct stats *stats) { - return (evsel->cpus && !target.cpu_list) ? evsel->cpus : evsel_list->cpus; + return stats->mean; } -static inline int perf_evsel__nr_cpus(struct perf_evsel *evsel) +/* + * http://en.wikipedia.org/wiki/Algorithms_for_calculating_variance + * + * (\Sum n_i^2) - ((\Sum n_i)^2)/n + * s^2 = ------------------------------- + * n - 1 + * + * http://en.wikipedia.org/wiki/Stddev + * + * The std dev of the mean is related to the std dev by: + * + * s + * s_mean = ------- + * sqrt(n) + * + */ +static double stddev_stats(struct stats *stats) { - return perf_evsel__cpus(evsel)->nr; + double variance, variance_mean; + + if (!stats->n) + return 0.0; + + variance = stats->M2 / (stats->n - 1); + variance_mean = variance / stats->n; + + return sqrt(variance_mean); } static struct stats runtime_nsecs_stats[MAX_NR_CPUS]; @@ -242,9 +281,13 @@ static int create_perf_stat_counter(struct perf_evsel *evsel, struct perf_evsel *first) { struct perf_event_attr *attr = &evsel->attr; + struct xyarray *group_fd = NULL; bool exclude_guest_missing = false; int ret; + if (group && evsel != first) + group_fd = first->fd; + if (scale) attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED | PERF_FORMAT_TOTAL_TIME_RUNNING; @@ -256,7 +299,8 @@ static int create_perf_stat_counter(struct perf_evsel *evsel, evsel->attr.exclude_guest = evsel->attr.exclude_host = 0; if (perf_target__has_cpu(&target)) { - ret = perf_evsel__open_per_cpu(evsel, perf_evsel__cpus(evsel)); + ret = perf_evsel__open_per_cpu(evsel, evsel_list->cpus, + group, group_fd); if (ret) goto check_ret; return 0; @@ -267,7 +311,8 @@ static int create_perf_stat_counter(struct perf_evsel *evsel, attr->enable_on_exec = 1; } - ret = perf_evsel__open_per_thread(evsel, evsel_list->threads); + ret = perf_evsel__open_per_thread(evsel, evsel_list->threads, + group, group_fd); if (!ret) return 0; /* fall through */ @@ -337,7 +382,7 @@ static int read_counter_aggr(struct perf_evsel *counter) u64 *count = counter->counts->aggr.values; int i; - if (__perf_evsel__read(counter, perf_evsel__nr_cpus(counter), + if (__perf_evsel__read(counter, evsel_list->cpus->nr, evsel_list->threads->nr, scale) < 0) return -1; @@ -366,7 +411,7 @@ static int read_counter(struct perf_evsel *counter) u64 *count; int cpu; - for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) { + for (cpu = 0; cpu < evsel_list->cpus->nr; cpu++) { if (__perf_evsel__read_on_cpu(counter, cpu, 0, scale) < 0) return -1; @@ -378,7 +423,7 @@ static int read_counter(struct perf_evsel *counter) return 0; } -static int run_perf_stat(int argc __maybe_unused, const char **argv) +static int run_perf_stat(int argc __used, const char **argv) { unsigned long long t0, t1; struct perf_evsel *counter, *first; @@ -389,7 +434,7 @@ static int run_perf_stat(int argc __maybe_unused, const char **argv) if (forks && (pipe(child_ready_pipe) < 0 || pipe(go_pipe) < 0)) { perror("failed to create pipes"); - return -1; + exit(1); } if (forks) { @@ -438,10 +483,7 @@ static int run_perf_stat(int argc __maybe_unused, const char **argv) close(child_ready_pipe[0]); } - if (group) - perf_evlist__set_leader(evsel_list); - - first = perf_evlist__first(evsel_list); + first = list_entry(evsel_list->entries.next, struct perf_evsel, node); list_for_each_entry(counter, &evsel_list->entries, node) { if (create_perf_stat_counter(counter, first) < 0) { @@ -471,14 +513,13 @@ static int run_perf_stat(int argc __maybe_unused, const char **argv) } if (child_pid != -1) kill(child_pid, SIGTERM); - - pr_err("Not all events could be opened.\n"); + die("Not all events could be opened.\n"); return -1; } counter->supported = true; } - if (perf_evlist__apply_filters(evsel_list)) { + if (perf_evlist__set_filters(evsel_list)) { error("failed to set filter with %d (%s)\n", errno, strerror(errno)); return -1; @@ -505,12 +546,12 @@ static int run_perf_stat(int argc __maybe_unused, const char **argv) if (no_aggr) { list_for_each_entry(counter, &evsel_list->entries, node) { read_counter(counter); - perf_evsel__close_fd(counter, perf_evsel__nr_cpus(counter), 1); + perf_evsel__close_fd(counter, evsel_list->cpus->nr, 1); } } else { list_for_each_entry(counter, &evsel_list->entries, node) { read_counter_aggr(counter); - perf_evsel__close_fd(counter, perf_evsel__nr_cpus(counter), + perf_evsel__close_fd(counter, evsel_list->cpus->nr, evsel_list->threads->nr); } } @@ -520,7 +561,10 @@ static int run_perf_stat(int argc __maybe_unused, const char **argv) static void print_noise_pct(double total, double avg) { - double pct = rel_stddev_stats(total, avg); + double pct = 0.0; + + if (avg) + pct = 100.0*total/avg; if (csv_output) fprintf(output, "%s%.2f%%", csv_sep, pct); @@ -548,7 +592,7 @@ static void nsec_printout(int cpu, struct perf_evsel *evsel, double avg) if (no_aggr) sprintf(cpustr, "CPU%*d%s", csv_output ? 0 : -4, - perf_evsel__cpus(evsel)->map[cpu], csv_sep); + evsel_list->cpus->map[cpu], csv_sep); fprintf(output, fmt, cpustr, msecs, csv_sep, perf_evsel__name(evsel)); @@ -592,9 +636,7 @@ static const char *get_ratio_color(enum grc_type type, double ratio) return color; } -static void print_stalled_cycles_frontend(int cpu, - struct perf_evsel *evsel - __maybe_unused, double avg) +static void print_stalled_cycles_frontend(int cpu, struct perf_evsel *evsel __used, double avg) { double total, ratio = 0.0; const char *color; @@ -611,9 +653,7 @@ static void print_stalled_cycles_frontend(int cpu, fprintf(output, " frontend cycles idle "); } -static void print_stalled_cycles_backend(int cpu, - struct perf_evsel *evsel - __maybe_unused, double avg) +static void print_stalled_cycles_backend(int cpu, struct perf_evsel *evsel __used, double avg) { double total, ratio = 0.0; const char *color; @@ -630,9 +670,7 @@ static void print_stalled_cycles_backend(int cpu, fprintf(output, " backend cycles idle "); } -static void print_branch_misses(int cpu, - struct perf_evsel *evsel __maybe_unused, - double avg) +static void print_branch_misses(int cpu, struct perf_evsel *evsel __used, double avg) { double total, ratio = 0.0; const char *color; @@ -649,9 +687,7 @@ static void print_branch_misses(int cpu, fprintf(output, " of all branches "); } -static void print_l1_dcache_misses(int cpu, - struct perf_evsel *evsel __maybe_unused, - double avg) +static void print_l1_dcache_misses(int cpu, struct perf_evsel *evsel __used, double avg) { double total, ratio = 0.0; const char *color; @@ -668,9 +704,7 @@ static void print_l1_dcache_misses(int cpu, fprintf(output, " of all L1-dcache hits "); } -static void print_l1_icache_misses(int cpu, - struct perf_evsel *evsel __maybe_unused, - double avg) +static void print_l1_icache_misses(int cpu, struct perf_evsel *evsel __used, double avg) { double total, ratio = 0.0; const char *color; @@ -687,9 +721,7 @@ static void print_l1_icache_misses(int cpu, fprintf(output, " of all L1-icache hits "); } -static void print_dtlb_cache_misses(int cpu, - struct perf_evsel *evsel __maybe_unused, - double avg) +static void print_dtlb_cache_misses(int cpu, struct perf_evsel *evsel __used, double avg) { double total, ratio = 0.0; const char *color; @@ -706,9 +738,7 @@ static void print_dtlb_cache_misses(int cpu, fprintf(output, " of all dTLB cache hits "); } -static void print_itlb_cache_misses(int cpu, - struct perf_evsel *evsel __maybe_unused, - double avg) +static void print_itlb_cache_misses(int cpu, struct perf_evsel *evsel __used, double avg) { double total, ratio = 0.0; const char *color; @@ -725,9 +755,7 @@ static void print_itlb_cache_misses(int cpu, fprintf(output, " of all iTLB cache hits "); } -static void print_ll_cache_misses(int cpu, - struct perf_evsel *evsel __maybe_unused, - double avg) +static void print_ll_cache_misses(int cpu, struct perf_evsel *evsel __used, double avg) { double total, ratio = 0.0; const char *color; @@ -760,7 +788,7 @@ static void abs_printout(int cpu, struct perf_evsel *evsel, double avg) if (no_aggr) sprintf(cpustr, "CPU%*d%s", csv_output ? 0 : -4, - perf_evsel__cpus(evsel)->map[cpu], csv_sep); + evsel_list->cpus->map[cpu], csv_sep); else cpu = 0; @@ -921,14 +949,14 @@ static void print_counter(struct perf_evsel *counter) u64 ena, run, val; int cpu; - for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) { + for (cpu = 0; cpu < evsel_list->cpus->nr; cpu++) { val = counter->counts->cpu[cpu].val; ena = counter->counts->cpu[cpu].ena; run = counter->counts->cpu[cpu].run; if (run == 0 || ena == 0) { fprintf(output, "CPU%*d%s%*s%s%*s", csv_output ? 0 : -4, - perf_evsel__cpus(counter)->map[cpu], csv_sep, + evsel_list->cpus->map[cpu], csv_sep, csv_output ? 0 : 18, counter->supported ? CNTR_NOT_COUNTED : CNTR_NOT_SUPPORTED, csv_sep, @@ -1033,8 +1061,8 @@ static const char * const stat_usage[] = { NULL }; -static int stat__set_big_num(const struct option *opt __maybe_unused, - const char *s __maybe_unused, int unset) +static int stat__set_big_num(const struct option *opt __used, + const char *s __used, int unset) { big_num_opt = unset ? 0 : 1; return 0; @@ -1128,7 +1156,7 @@ static int add_default_attributes(void) return perf_evlist__add_default_attrs(evsel_list, very_very_detailed_attrs); } -int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused) +int cmd_stat(int argc, const char **argv, const char *prefix __used) { struct perf_evsel *pos; int status = -ENOMEM; @@ -1164,7 +1192,7 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused) output = fopen(output_name, mode); if (!output) { perror("failed to create output file"); - return -1; + exit(-1); } clock_gettime(CLOCK_REALTIME, &tm); fprintf(output, "# started on %s\n", ctime(&tm.tv_sec)); @@ -1227,7 +1255,7 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused) list_for_each_entry(pos, &evsel_list->entries, node) { if (perf_evsel__alloc_stat_priv(pos) < 0 || - perf_evsel__alloc_counts(pos, perf_evsel__nr_cpus(pos)) < 0) + perf_evsel__alloc_counts(pos, evsel_list->cpus->nr) < 0) goto out_free_fd; } diff --git a/trunk/tools/perf/builtin-test.c b/trunk/tools/perf/builtin-test.c index 484f26cc0c00..d909eb74a0eb 100644 --- a/trunk/tools/perf/builtin-test.c +++ b/trunk/tools/perf/builtin-test.c @@ -14,13 +14,11 @@ #include "util/symbol.h" #include "util/thread_map.h" #include "util/pmu.h" -#include "event-parse.h" #include "../../include/linux/hw_breakpoint.h" #include -static int vmlinux_matches_kallsyms_filter(struct map *map __maybe_unused, - struct symbol *sym) +static int vmlinux_matches_kallsyms_filter(struct map *map __used, struct symbol *sym) { bool *visited = symbol__priv(sym); *visited = true; @@ -296,7 +294,7 @@ static int test__open_syscall_event(void) goto out_thread_map_delete; } - if (perf_evsel__open_per_thread(evsel, threads) < 0) { + if (perf_evsel__open_per_thread(evsel, threads, false, NULL) < 0) { pr_debug("failed to open counter: %s, " "tweak /proc/sys/kernel/perf_event_paranoid?\n", strerror(errno)); @@ -371,7 +369,7 @@ static int test__open_syscall_event_on_all_cpus(void) goto out_thread_map_delete; } - if (perf_evsel__open(evsel, cpus, threads) < 0) { + if (perf_evsel__open(evsel, cpus, threads, false, NULL) < 0) { pr_debug("failed to open counter: %s, " "tweak /proc/sys/kernel/perf_event_paranoid?\n", strerror(errno)); @@ -480,6 +478,7 @@ static int test__basic_mmap(void) unsigned int nr_events[nsyscalls], expected_nr_events[nsyscalls], i, j; struct perf_evsel *evsels[nsyscalls], *evsel; + int sample_size = __perf_evsel__sample_size(attr.sample_type); for (i = 0; i < nsyscalls; ++i) { char name[64]; @@ -535,7 +534,7 @@ static int test__basic_mmap(void) perf_evlist__add(evlist, evsels[i]); - if (perf_evsel__open(evsels[i], cpus, threads) < 0) { + if (perf_evsel__open(evsels[i], cpus, threads, false, NULL) < 0) { pr_debug("failed to open counter: %s, " "tweak /proc/sys/kernel/perf_event_paranoid?\n", strerror(errno)); @@ -564,7 +563,8 @@ static int test__basic_mmap(void) goto out_munmap; } - err = perf_evlist__parse_sample(evlist, event, &sample); + err = perf_event__parse_sample(event, attr.sample_type, sample_size, + false, &sample, false); if (err) { pr_err("Can't parse sample, err = %d\n", err); goto out_munmap; @@ -661,12 +661,12 @@ static int test__PERF_RECORD(void) const char *cmd = "sleep"; const char *argv[] = { cmd, "1", NULL, }; char *bname; - u64 prev_time = 0; + u64 sample_type, prev_time = 0; bool found_cmd_mmap = false, found_libc_mmap = false, found_vdso_mmap = false, found_ld_mmap = false; - int err = -1, errs = 0, i, wakeups = 0; + int err = -1, errs = 0, i, wakeups = 0, sample_size; u32 cpu; int total_events = 0, nr_events[PERF_RECORD_MAX] = { 0, }; @@ -712,7 +712,7 @@ static int test__PERF_RECORD(void) /* * Config the evsels, setting attr->comm on the first one, etc. */ - evsel = perf_evlist__first(evlist); + evsel = list_entry(evlist->entries.next, struct perf_evsel, node); evsel->attr.sample_type |= PERF_SAMPLE_CPU; evsel->attr.sample_type |= PERF_SAMPLE_TID; evsel->attr.sample_type |= PERF_SAMPLE_TIME; @@ -739,7 +739,7 @@ static int test__PERF_RECORD(void) * Call sys_perf_event_open on all the fds on all the evsels, * grouping them if asked to. */ - err = perf_evlist__open(evlist); + err = perf_evlist__open(evlist, opts.group); if (err < 0) { pr_debug("perf_evlist__open: %s\n", strerror(errno)); goto out_delete_evlist; @@ -756,6 +756,13 @@ static int test__PERF_RECORD(void) goto out_delete_evlist; } + /* + * We'll need these two to parse the PERF_SAMPLE_* fields in each + * event. + */ + sample_type = perf_evlist__sample_type(evlist); + sample_size = __perf_evsel__sample_size(sample_type); + /* * Now that all is properly set up, enable the events, they will * count just on workload.pid, which will start... @@ -781,7 +788,9 @@ static int test__PERF_RECORD(void) if (type < PERF_RECORD_MAX) nr_events[type]++; - err = perf_evlist__parse_sample(evlist, event, &sample); + err = perf_event__parse_sample(event, sample_type, + sample_size, true, + &sample, false); if (err < 0) { if (verbose) perf_event__fprintf(event, stderr); @@ -998,9 +1007,7 @@ static u64 mmap_read_self(void *addr) /* * If the RDPMC instruction faults then signal this back to the test parent task: */ -static void segfault_handler(int sig __maybe_unused, - siginfo_t *info __maybe_unused, - void *uc __maybe_unused) +static void segfault_handler(int sig __used, siginfo_t *info __used, void *uc __used) { exit(-1); } @@ -1027,16 +1034,14 @@ static int __test__rdpmc(void) fd = sys_perf_event_open(&attr, 0, -1, -1, 0); if (fd < 0) { - pr_err("Error: sys_perf_event_open() syscall returned " - "with %d (%s)\n", fd, strerror(errno)); - return -1; + die("Error: sys_perf_event_open() syscall returned " + "with %d (%s)\n", fd, strerror(errno)); } addr = mmap(NULL, page_size, PROT_READ, MAP_SHARED, fd, 0); if (addr == (void *)(-1)) { - pr_err("Error: mmap() syscall returned with (%s)\n", - strerror(errno)); - goto out_close; + die("Error: mmap() syscall returned " + "with (%s)\n", strerror(errno)); } for (n = 0; n < 6; n++) { @@ -1057,10 +1062,10 @@ static int __test__rdpmc(void) } munmap(addr, page_size); - pr_debug(" "); -out_close: close(fd); + pr_debug(" "); + if (!delta_sum) return -1; @@ -1098,309 +1103,6 @@ static int test__perf_pmu(void) return perf_pmu__test(); } -static int perf_evsel__roundtrip_cache_name_test(void) -{ - char name[128]; - int type, op, err = 0, ret = 0, i, idx; - struct perf_evsel *evsel; - struct perf_evlist *evlist = perf_evlist__new(NULL, NULL); - - if (evlist == NULL) - return -ENOMEM; - - for (type = 0; type < PERF_COUNT_HW_CACHE_MAX; type++) { - for (op = 0; op < PERF_COUNT_HW_CACHE_OP_MAX; op++) { - /* skip invalid cache type */ - if (!perf_evsel__is_cache_op_valid(type, op)) - continue; - - for (i = 0; i < PERF_COUNT_HW_CACHE_RESULT_MAX; i++) { - __perf_evsel__hw_cache_type_op_res_name(type, op, i, - name, sizeof(name)); - err = parse_events(evlist, name, 0); - if (err) - ret = err; - } - } - } - - idx = 0; - evsel = perf_evlist__first(evlist); - - for (type = 0; type < PERF_COUNT_HW_CACHE_MAX; type++) { - for (op = 0; op < PERF_COUNT_HW_CACHE_OP_MAX; op++) { - /* skip invalid cache type */ - if (!perf_evsel__is_cache_op_valid(type, op)) - continue; - - for (i = 0; i < PERF_COUNT_HW_CACHE_RESULT_MAX; i++) { - __perf_evsel__hw_cache_type_op_res_name(type, op, i, - name, sizeof(name)); - if (evsel->idx != idx) - continue; - - ++idx; - - if (strcmp(perf_evsel__name(evsel), name)) { - pr_debug("%s != %s\n", perf_evsel__name(evsel), name); - ret = -1; - } - - evsel = perf_evsel__next(evsel); - } - } - } - - perf_evlist__delete(evlist); - return ret; -} - -static int __perf_evsel__name_array_test(const char *names[], int nr_names) -{ - int i, err; - struct perf_evsel *evsel; - struct perf_evlist *evlist = perf_evlist__new(NULL, NULL); - - if (evlist == NULL) - return -ENOMEM; - - for (i = 0; i < nr_names; ++i) { - err = parse_events(evlist, names[i], 0); - if (err) { - pr_debug("failed to parse event '%s', err %d\n", - names[i], err); - goto out_delete_evlist; - } - } - - err = 0; - list_for_each_entry(evsel, &evlist->entries, node) { - if (strcmp(perf_evsel__name(evsel), names[evsel->idx])) { - --err; - pr_debug("%s != %s\n", perf_evsel__name(evsel), names[evsel->idx]); - } - } - -out_delete_evlist: - perf_evlist__delete(evlist); - return err; -} - -#define perf_evsel__name_array_test(names) \ - __perf_evsel__name_array_test(names, ARRAY_SIZE(names)) - -static int perf_evsel__roundtrip_name_test(void) -{ - int err = 0, ret = 0; - - err = perf_evsel__name_array_test(perf_evsel__hw_names); - if (err) - ret = err; - - err = perf_evsel__name_array_test(perf_evsel__sw_names); - if (err) - ret = err; - - err = perf_evsel__roundtrip_cache_name_test(); - if (err) - ret = err; - - return ret; -} - -static int perf_evsel__test_field(struct perf_evsel *evsel, const char *name, - int size, bool should_be_signed) -{ - struct format_field *field = perf_evsel__field(evsel, name); - int is_signed; - int ret = 0; - - if (field == NULL) { - pr_debug("%s: \"%s\" field not found!\n", evsel->name, name); - return -1; - } - - is_signed = !!(field->flags | FIELD_IS_SIGNED); - if (should_be_signed && !is_signed) { - pr_debug("%s: \"%s\" signedness(%d) is wrong, should be %d\n", - evsel->name, name, is_signed, should_be_signed); - ret = -1; - } - - if (field->size != size) { - pr_debug("%s: \"%s\" size (%d) should be %d!\n", - evsel->name, name, field->size, size); - ret = -1; - } - - return ret; -} - -static int perf_evsel__tp_sched_test(void) -{ - struct perf_evsel *evsel = perf_evsel__newtp("sched", "sched_switch", 0); - int ret = 0; - - if (evsel == NULL) { - pr_debug("perf_evsel__new\n"); - return -1; - } - - if (perf_evsel__test_field(evsel, "prev_comm", 16, true)) - ret = -1; - - if (perf_evsel__test_field(evsel, "prev_pid", 4, true)) - ret = -1; - - if (perf_evsel__test_field(evsel, "prev_prio", 4, true)) - ret = -1; - - if (perf_evsel__test_field(evsel, "prev_state", 8, true)) - ret = -1; - - if (perf_evsel__test_field(evsel, "next_comm", 16, true)) - ret = -1; - - if (perf_evsel__test_field(evsel, "next_pid", 4, true)) - ret = -1; - - if (perf_evsel__test_field(evsel, "next_prio", 4, true)) - ret = -1; - - perf_evsel__delete(evsel); - - evsel = perf_evsel__newtp("sched", "sched_wakeup", 0); - - if (perf_evsel__test_field(evsel, "comm", 16, true)) - ret = -1; - - if (perf_evsel__test_field(evsel, "pid", 4, true)) - ret = -1; - - if (perf_evsel__test_field(evsel, "prio", 4, true)) - ret = -1; - - if (perf_evsel__test_field(evsel, "success", 4, true)) - ret = -1; - - if (perf_evsel__test_field(evsel, "target_cpu", 4, true)) - ret = -1; - - return ret; -} - -static int test__syscall_open_tp_fields(void) -{ - struct perf_record_opts opts = { - .target = { - .uid = UINT_MAX, - .uses_mmap = true, - }, - .no_delay = true, - .freq = 1, - .mmap_pages = 256, - .raw_samples = true, - }; - const char *filename = "/etc/passwd"; - int flags = O_RDONLY | O_DIRECTORY; - struct perf_evlist *evlist = perf_evlist__new(NULL, NULL); - struct perf_evsel *evsel; - int err = -1, i, nr_events = 0, nr_polls = 0; - - if (evlist == NULL) { - pr_debug("%s: perf_evlist__new\n", __func__); - goto out; - } - - evsel = perf_evsel__newtp("syscalls", "sys_enter_open", 0); - if (evsel == NULL) { - pr_debug("%s: perf_evsel__newtp\n", __func__); - goto out_delete_evlist; - } - - perf_evlist__add(evlist, evsel); - - err = perf_evlist__create_maps(evlist, &opts.target); - if (err < 0) { - pr_debug("%s: perf_evlist__create_maps\n", __func__); - goto out_delete_evlist; - } - - perf_evsel__config(evsel, &opts, evsel); - - evlist->threads->map[0] = getpid(); - - err = perf_evlist__open(evlist); - if (err < 0) { - pr_debug("perf_evlist__open: %s\n", strerror(errno)); - goto out_delete_evlist; - } - - err = perf_evlist__mmap(evlist, UINT_MAX, false); - if (err < 0) { - pr_debug("perf_evlist__mmap: %s\n", strerror(errno)); - goto out_delete_evlist; - } - - perf_evlist__enable(evlist); - - /* - * Generate the event: - */ - open(filename, flags); - - while (1) { - int before = nr_events; - - for (i = 0; i < evlist->nr_mmaps; i++) { - union perf_event *event; - - while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) { - const u32 type = event->header.type; - int tp_flags; - struct perf_sample sample; - - ++nr_events; - - if (type != PERF_RECORD_SAMPLE) - continue; - - err = perf_evsel__parse_sample(evsel, event, &sample); - if (err) { - pr_err("Can't parse sample, err = %d\n", err); - goto out_munmap; - } - - tp_flags = perf_evsel__intval(evsel, &sample, "flags"); - - if (flags != tp_flags) { - pr_debug("%s: Expected flags=%#x, got %#x\n", - __func__, flags, tp_flags); - goto out_munmap; - } - - goto out_ok; - } - } - - if (nr_events == before) - poll(evlist->pollfd, evlist->nr_fds, 10); - - if (++nr_polls > 5) { - pr_debug("%s: no events!\n", __func__); - goto out_munmap; - } - } -out_ok: - err = 0; -out_munmap: - perf_evlist__munmap(evlist); -out_delete_evlist: - perf_evlist__delete(evlist); -out: - return err; -} - static struct test { const char *desc; int (*func)(void); @@ -1443,18 +1145,6 @@ static struct test { .desc = "Test dso data interface", .func = dso__test_data, }, - { - .desc = "roundtrip evsel->name check", - .func = perf_evsel__roundtrip_name_test, - }, - { - .desc = "Check parsing of sched tracepoints fields", - .func = perf_evsel__tp_sched_test, - }, - { - .desc = "Generate and check syscalls:sys_enter_open event fields", - .func = test__syscall_open_tp_fields, - }, { .func = NULL, }, @@ -1520,7 +1210,7 @@ static int perf_test__list(int argc, const char **argv) return 0; } -int cmd_test(int argc, const char **argv, const char *prefix __maybe_unused) +int cmd_test(int argc, const char **argv, const char *prefix __used) { const char * const test_usage[] = { "perf test [] [{list |[|]}]", diff --git a/trunk/tools/perf/builtin-timechart.c b/trunk/tools/perf/builtin-timechart.c index b1a8a3b841cc..3b75b2e21ea5 100644 --- a/trunk/tools/perf/builtin-timechart.c +++ b/trunk/tools/perf/builtin-timechart.c @@ -168,8 +168,9 @@ static struct per_pid *find_create_pid(int pid) return cursor; cursor = cursor->next; } - cursor = zalloc(sizeof(*cursor)); + cursor = malloc(sizeof(struct per_pid)); assert(cursor != NULL); + memset(cursor, 0, sizeof(struct per_pid)); cursor->pid = pid; cursor->next = all_data; all_data = cursor; @@ -194,8 +195,9 @@ static void pid_set_comm(int pid, char *comm) } c = c->next; } - c = zalloc(sizeof(*c)); + c = malloc(sizeof(struct per_pidcomm)); assert(c != NULL); + memset(c, 0, sizeof(struct per_pidcomm)); c->comm = strdup(comm); p->current = c; c->next = p->all; @@ -237,15 +239,17 @@ pid_put_sample(int pid, int type, unsigned int cpu, u64 start, u64 end) p = find_create_pid(pid); c = p->current; if (!c) { - c = zalloc(sizeof(*c)); + c = malloc(sizeof(struct per_pidcomm)); assert(c != NULL); + memset(c, 0, sizeof(struct per_pidcomm)); p->current = c; c->next = p->all; p->all = c; } - sample = zalloc(sizeof(*sample)); + sample = malloc(sizeof(struct cpu_sample)); assert(sample != NULL); + memset(sample, 0, sizeof(struct cpu_sample)); sample->start_time = start; sample->end_time = end; sample->type = type; @@ -271,28 +275,28 @@ static int cpus_cstate_state[MAX_CPUS]; static u64 cpus_pstate_start_times[MAX_CPUS]; static u64 cpus_pstate_state[MAX_CPUS]; -static int process_comm_event(struct perf_tool *tool __maybe_unused, +static int process_comm_event(struct perf_tool *tool __used, union perf_event *event, - struct perf_sample *sample __maybe_unused, - struct machine *machine __maybe_unused) + struct perf_sample *sample __used, + struct machine *machine __used) { pid_set_comm(event->comm.tid, event->comm.comm); return 0; } -static int process_fork_event(struct perf_tool *tool __maybe_unused, +static int process_fork_event(struct perf_tool *tool __used, union perf_event *event, - struct perf_sample *sample __maybe_unused, - struct machine *machine __maybe_unused) + struct perf_sample *sample __used, + struct machine *machine __used) { pid_fork(event->fork.pid, event->fork.ppid, event->fork.time); return 0; } -static int process_exit_event(struct perf_tool *tool __maybe_unused, +static int process_exit_event(struct perf_tool *tool __used, union perf_event *event, - struct perf_sample *sample __maybe_unused, - struct machine *machine __maybe_unused) + struct perf_sample *sample __used, + struct machine *machine __used) { pid_exit(event->fork.pid, event->fork.time); return 0; @@ -369,10 +373,11 @@ static void c_state_start(int cpu, u64 timestamp, int state) static void c_state_end(int cpu, u64 timestamp) { - struct power_event *pwr = zalloc(sizeof(*pwr)); - + struct power_event *pwr; + pwr = malloc(sizeof(struct power_event)); if (!pwr) return; + memset(pwr, 0, sizeof(struct power_event)); pwr->state = cpus_cstate_state[cpu]; pwr->start_time = cpus_cstate_start_times[cpu]; @@ -387,13 +392,14 @@ static void c_state_end(int cpu, u64 timestamp) static void p_state_change(int cpu, u64 timestamp, u64 new_freq) { struct power_event *pwr; + pwr = malloc(sizeof(struct power_event)); if (new_freq > 8000000) /* detect invalid data */ return; - pwr = zalloc(sizeof(*pwr)); if (!pwr) return; + memset(pwr, 0, sizeof(struct power_event)); pwr->state = cpus_pstate_state[cpu]; pwr->start_time = cpus_pstate_start_times[cpu]; @@ -423,13 +429,15 @@ static void p_state_change(int cpu, u64 timestamp, u64 new_freq) static void sched_wakeup(int cpu, u64 timestamp, int pid, struct trace_entry *te) { + struct wake_event *we; struct per_pid *p; struct wakeup_entry *wake = (void *)te; - struct wake_event *we = zalloc(sizeof(*we)); + we = malloc(sizeof(struct wake_event)); if (!we) return; + memset(we, 0, sizeof(struct wake_event)); we->time = timestamp; we->waker = pid; @@ -483,11 +491,11 @@ static void sched_switch(int cpu, u64 timestamp, struct trace_entry *te) } -static int process_sample_event(struct perf_tool *tool __maybe_unused, - union perf_event *event __maybe_unused, +static int process_sample_event(struct perf_tool *tool __used, + union perf_event *event __used, struct perf_sample *sample, struct perf_evsel *evsel, - struct machine *machine __maybe_unused) + struct machine *machine __used) { struct trace_entry *te; @@ -571,12 +579,13 @@ static void end_sample_processing(void) struct power_event *pwr; for (cpu = 0; cpu <= numcpus; cpu++) { - /* C state */ -#if 0 - pwr = zalloc(sizeof(*pwr)); + pwr = malloc(sizeof(struct power_event)); if (!pwr) return; + memset(pwr, 0, sizeof(struct power_event)); + /* C state */ +#if 0 pwr->state = cpus_cstate_state[cpu]; pwr->start_time = cpus_cstate_start_times[cpu]; pwr->end_time = last_time; @@ -588,9 +597,10 @@ static void end_sample_processing(void) #endif /* P state */ - pwr = zalloc(sizeof(*pwr)); + pwr = malloc(sizeof(struct power_event)); if (!pwr) return; + memset(pwr, 0, sizeof(struct power_event)); pwr->state = cpus_pstate_state[cpu]; pwr->start_time = cpus_pstate_start_times[cpu]; @@ -820,9 +830,11 @@ static void draw_process_bars(void) static void add_process_filter(const char *string) { - int pid = strtoull(string, NULL, 10); - struct process_filter *filt = malloc(sizeof(*filt)); + struct process_filter *filt; + int pid; + pid = strtoull(string, NULL, 10); + filt = malloc(sizeof(struct process_filter)); if (!filt) return; @@ -1069,8 +1081,7 @@ static int __cmd_record(int argc, const char **argv) } static int -parse_process(const struct option *opt __maybe_unused, const char *arg, - int __maybe_unused unset) +parse_process(const struct option *opt __used, const char *arg, int __used unset) { if (arg) add_process_filter(arg); @@ -1095,8 +1106,7 @@ static const struct option options[] = { }; -int cmd_timechart(int argc, const char **argv, - const char *prefix __maybe_unused) +int cmd_timechart(int argc, const char **argv, const char *prefix __used) { argc = parse_options(argc, argv, options, timechart_usage, PARSE_OPT_STOP_AT_NON_OPTION); diff --git a/trunk/tools/perf/builtin-top.c b/trunk/tools/perf/builtin-top.c index e434a16bb5ac..35e86c6df713 100644 --- a/trunk/tools/perf/builtin-top.c +++ b/trunk/tools/perf/builtin-top.c @@ -38,7 +38,6 @@ #include "util/cpumap.h" #include "util/xyarray.h" #include "util/sort.h" -#include "util/intlist.h" #include "util/debug.h" @@ -95,8 +94,7 @@ static void perf_top__update_print_entries(struct perf_top *top) top->print_entries -= 9; } -static void perf_top__sig_winch(int sig __maybe_unused, - siginfo_t *info __maybe_unused, void *arg) +static void perf_top__sig_winch(int sig __used, siginfo_t *info __used, void *arg) { struct perf_top *top = arg; @@ -510,7 +508,7 @@ static void perf_top__handle_keypress(struct perf_top *top, int c) prompt_integer(&counter, "Enter details event counter"); if (counter >= top->evlist->nr_entries) { - top->sym_evsel = perf_evlist__first(top->evlist); + top->sym_evsel = list_entry(top->evlist->entries.next, struct perf_evsel, node); fprintf(stderr, "Sorry, no such event, using %s.\n", perf_evsel__name(top->sym_evsel)); sleep(1); break; @@ -519,7 +517,7 @@ static void perf_top__handle_keypress(struct perf_top *top, int c) if (top->sym_evsel->idx == counter) break; } else - top->sym_evsel = perf_evlist__first(top->evlist); + top->sym_evsel = list_entry(top->evlist->entries.next, struct perf_evsel, node); break; case 'f': prompt_integer(&top->count_filter, "Enter display event count filter"); @@ -664,7 +662,7 @@ static const char *skip_symbols[] = { NULL }; -static int symbol_filter(struct map *map __maybe_unused, struct symbol *sym) +static int symbol_filter(struct map *map __used, struct symbol *sym) { const char *name = sym->name; int i; @@ -708,16 +706,8 @@ static void perf_event__process_sample(struct perf_tool *tool, int err; if (!machine && perf_guest) { - static struct intlist *seen; - - if (!seen) - seen = intlist__new(); - - if (!intlist__has_entry(seen, event->ip.pid)) { - pr_err("Can't find guest [%d]'s kernel information\n", - event->ip.pid); - intlist__add(seen, event->ip.pid); - } + pr_err("Can't find guest [%d]'s kernel information\n", + event->ip.pid); return; } @@ -784,10 +774,8 @@ static void perf_event__process_sample(struct perf_tool *tool, if ((sort__has_parent || symbol_conf.use_callchain) && sample->callchain) { - err = machine__resolve_callchain(machine, evsel, - al.thread, sample, - &parent); - + err = machine__resolve_callchain(machine, al.thread, + sample->callchain, &parent); if (err) return; } @@ -823,7 +811,7 @@ static void perf_top__mmap_read_idx(struct perf_top *top, int idx) int ret; while ((event = perf_evlist__mmap_read(top->evlist, idx)) != NULL) { - ret = perf_evlist__parse_sample(top->evlist, event, &sample); + ret = perf_session__parse_sample(session, event, &sample); if (ret) { pr_err("Can't parse sample, err = %d\n", ret); continue; @@ -887,14 +875,17 @@ static void perf_top__mmap_read(struct perf_top *top) static void perf_top__start_counters(struct perf_top *top) { - struct perf_evsel *counter; + struct perf_evsel *counter, *first; struct perf_evlist *evlist = top->evlist; - if (top->group) - perf_evlist__set_leader(evlist); + first = list_entry(evlist->entries.next, struct perf_evsel, node); list_for_each_entry(counter, &evlist->entries, node) { struct perf_event_attr *attr = &counter->attr; + struct xyarray *group_fd = NULL; + + if (top->group && counter != first) + group_fd = first->fd; attr->sample_type = PERF_SAMPLE_IP | PERF_SAMPLE_TID; @@ -925,7 +916,8 @@ static void perf_top__start_counters(struct perf_top *top) attr->sample_id_all = top->sample_id_all_missing ? 0 : 1; try_again: if (perf_evsel__open(counter, top->evlist->cpus, - top->evlist->threads) < 0) { + top->evlist->threads, top->group, + group_fd) < 0) { int err = errno; if (err == EPERM || err == EACCES) { @@ -951,10 +943,8 @@ static void perf_top__start_counters(struct perf_top *top) * based cpu-clock-tick sw counter, which * is always available even if no PMU support: */ - if ((err == ENOENT || err == ENXIO) && - (attr->type == PERF_TYPE_HARDWARE) && - (attr->config == PERF_COUNT_HW_CPU_CYCLES)) { - + if (attr->type == PERF_TYPE_HARDWARE && + attr->config == PERF_COUNT_HW_CPU_CYCLES) { if (verbose) ui__warning("Cycles event not supported,\n" "trying to fall back to cpu-clock-ticks\n"); @@ -1042,7 +1032,7 @@ static int __cmd_top(struct perf_top *top) &top->session->host_machine); perf_top__start_counters(top); top->session->evlist = top->evlist; - perf_session__set_id_hdr_size(top->session); + perf_session__update_sample_type(top->session); /* Wait for a minimal set of events before starting the snapshot */ poll(top->evlist->pollfd, top->evlist->nr_fds, 100); @@ -1164,7 +1154,7 @@ static const char * const top_usage[] = { NULL }; -int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused) +int cmd_top(int argc, const char **argv, const char *prefix __used) { struct perf_evsel *pos; int status; @@ -1327,7 +1317,7 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused) pos->attr.sample_period = top.default_interval; } - top.sym_evsel = perf_evlist__first(top.evlist); + top.sym_evsel = list_entry(top.evlist->entries.next, struct perf_evsel, node); symbol_conf.priv_size = sizeof(struct annotation); diff --git a/trunk/tools/perf/builtin-trace.c b/trunk/tools/perf/builtin-trace.c deleted file mode 100644 index 8f113dab8bf1..000000000000 --- a/trunk/tools/perf/builtin-trace.c +++ /dev/null @@ -1,310 +0,0 @@ -#include "builtin.h" -#include "util/evlist.h" -#include "util/parse-options.h" -#include "util/thread_map.h" -#include "event-parse.h" - -#include -#include - -static struct syscall_fmt { - const char *name; - const char *alias; - bool errmsg; - bool timeout; -} syscall_fmts[] = { - { .name = "arch_prctl", .errmsg = true, .alias = "prctl", }, - { .name = "fstat", .errmsg = true, .alias = "newfstat", }, - { .name = "fstatat", .errmsg = true, .alias = "newfstatat", }, - { .name = "futex", .errmsg = true, }, - { .name = "poll", .errmsg = true, .timeout = true, }, - { .name = "ppoll", .errmsg = true, .timeout = true, }, - { .name = "read", .errmsg = true, }, - { .name = "recvfrom", .errmsg = true, }, - { .name = "select", .errmsg = true, .timeout = true, }, - { .name = "stat", .errmsg = true, .alias = "newstat", }, -}; - -static int syscall_fmt__cmp(const void *name, const void *fmtp) -{ - const struct syscall_fmt *fmt = fmtp; - return strcmp(name, fmt->name); -} - -static struct syscall_fmt *syscall_fmt__find(const char *name) -{ - const int nmemb = ARRAY_SIZE(syscall_fmts); - return bsearch(name, syscall_fmts, nmemb, sizeof(struct syscall_fmt), syscall_fmt__cmp); -} - -struct syscall { - struct event_format *tp_format; - const char *name; - struct syscall_fmt *fmt; -}; - -struct trace { - int audit_machine; - struct { - int max; - struct syscall *table; - } syscalls; - struct perf_record_opts opts; -}; - -static int trace__read_syscall_info(struct trace *trace, int id) -{ - char tp_name[128]; - struct syscall *sc; - - if (id > trace->syscalls.max) { - struct syscall *nsyscalls = realloc(trace->syscalls.table, (id + 1) * sizeof(*sc)); - - if (nsyscalls == NULL) - return -1; - - if (trace->syscalls.max != -1) { - memset(nsyscalls + trace->syscalls.max + 1, 0, - (id - trace->syscalls.max) * sizeof(*sc)); - } else { - memset(nsyscalls, 0, (id + 1) * sizeof(*sc)); - } - - trace->syscalls.table = nsyscalls; - trace->syscalls.max = id; - } - - sc = trace->syscalls.table + id; - sc->name = audit_syscall_to_name(id, trace->audit_machine); - if (sc->name == NULL) - return -1; - - sc->fmt = syscall_fmt__find(sc->name); - - snprintf(tp_name, sizeof(tp_name), "sys_enter_%s", sc->name); - sc->tp_format = event_format__new("syscalls", tp_name); - - if (sc->tp_format == NULL && sc->fmt && sc->fmt->alias) { - snprintf(tp_name, sizeof(tp_name), "sys_enter_%s", sc->fmt->alias); - sc->tp_format = event_format__new("syscalls", tp_name); - } - - return sc->tp_format != NULL ? 0 : -1; -} - -static size_t syscall__fprintf_args(struct syscall *sc, unsigned long *args, FILE *fp) -{ - int i = 0; - size_t printed = 0; - - if (sc->tp_format != NULL) { - struct format_field *field; - - for (field = sc->tp_format->format.fields->next; field; field = field->next) { - printed += fprintf(fp, "%s%s: %ld", printed ? ", " : "", - field->name, args[i++]); - } - } else { - while (i < 6) { - printed += fprintf(fp, "%sarg%d: %ld", printed ? ", " : "", i, args[i]); - ++i; - } - } - - return printed; -} - -static int trace__run(struct trace *trace) -{ - struct perf_evlist *evlist = perf_evlist__new(NULL, NULL); - struct perf_evsel *evsel, *evsel_enter, *evsel_exit; - int err = -1, i, nr_events = 0, before; - - if (evlist == NULL) { - printf("Not enough memory to run!\n"); - goto out; - } - - evsel_enter = perf_evsel__newtp("raw_syscalls", "sys_enter", 0); - if (evsel_enter == NULL) { - printf("Couldn't read the raw_syscalls:sys_enter tracepoint information!\n"); - goto out_delete_evlist; - } - - perf_evlist__add(evlist, evsel_enter); - - evsel_exit = perf_evsel__newtp("raw_syscalls", "sys_exit", 1); - if (evsel_exit == NULL) { - printf("Couldn't read the raw_syscalls:sys_exit tracepoint information!\n"); - goto out_delete_evlist; - } - - perf_evlist__add(evlist, evsel_exit); - - err = perf_evlist__create_maps(evlist, &trace->opts.target); - if (err < 0) { - printf("Problems parsing the target to trace, check your options!\n"); - goto out_delete_evlist; - } - - perf_evlist__config_attrs(evlist, &trace->opts); - - err = perf_evlist__open(evlist); - if (err < 0) { - printf("Couldn't create the events: %s\n", strerror(errno)); - goto out_delete_evlist; - } - - err = perf_evlist__mmap(evlist, UINT_MAX, false); - if (err < 0) { - printf("Couldn't mmap the events: %s\n", strerror(errno)); - goto out_delete_evlist; - } - - perf_evlist__enable(evlist); -again: - before = nr_events; - - for (i = 0; i < evlist->nr_mmaps; i++) { - union perf_event *event; - - while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) { - const u32 type = event->header.type; - struct syscall *sc; - struct perf_sample sample; - int id; - - ++nr_events; - - switch (type) { - case PERF_RECORD_SAMPLE: - break; - case PERF_RECORD_LOST: - printf("LOST %" PRIu64 " events!\n", event->lost.lost); - continue; - default: - printf("Unexpected %s event, skipping...\n", - perf_event__name(type)); - continue; - } - - err = perf_evlist__parse_sample(evlist, event, &sample); - if (err) { - printf("Can't parse sample, err = %d, skipping...\n", err); - continue; - } - - evsel = perf_evlist__id2evsel(evlist, sample.id); - if (evsel == NULL) { - printf("Unknown tp ID %" PRIu64 ", skipping...\n", sample.id); - continue; - } - - id = perf_evsel__intval(evsel, &sample, "id"); - if (id < 0) { - printf("Invalid syscall %d id, skipping...\n", id); - continue; - } - - if ((id > trace->syscalls.max || trace->syscalls.table[id].name == NULL) && - trace__read_syscall_info(trace, id)) - continue; - - if ((id > trace->syscalls.max || trace->syscalls.table[id].name == NULL)) - continue; - - sc = &trace->syscalls.table[id]; - - if (evlist->threads->map[0] == -1 || evlist->threads->nr > 1) - printf("%d ", sample.tid); - - if (evsel == evsel_enter) { - void *args = perf_evsel__rawptr(evsel, &sample, "args"); - - printf("%s(", sc->name); - syscall__fprintf_args(sc, args, stdout); - } else if (evsel == evsel_exit) { - int ret = perf_evsel__intval(evsel, &sample, "ret"); - - if (ret < 0 && sc->fmt && sc->fmt->errmsg) { - char bf[256]; - const char *emsg = strerror_r(-ret, bf, sizeof(bf)), - *e = audit_errno_to_name(-ret); - - printf(") = -1 %s %s", e, emsg); - } else if (ret == 0 && sc->fmt && sc->fmt->timeout) - printf(") = 0 Timeout"); - else - printf(") = %d", ret); - - putchar('\n'); - } - } - } - - if (nr_events == before) - poll(evlist->pollfd, evlist->nr_fds, -1); - - goto again; - -out_delete_evlist: - perf_evlist__delete(evlist); -out: - return err; -} - -int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused) -{ - const char * const trace_usage[] = { - "perf trace []", - NULL - }; - struct trace trace = { - .audit_machine = audit_detect_machine(), - .syscalls = { - . max = -1, - }, - .opts = { - .target = { - .uid = UINT_MAX, - .uses_mmap = true, - }, - .user_freq = UINT_MAX, - .user_interval = ULLONG_MAX, - .no_delay = true, - .mmap_pages = 1024, - }, - }; - const struct option trace_options[] = { - OPT_STRING('p', "pid", &trace.opts.target.pid, "pid", - "trace events on existing process id"), - OPT_STRING(0, "tid", &trace.opts.target.tid, "tid", - "trace events on existing thread id"), - OPT_BOOLEAN(0, "all-cpus", &trace.opts.target.system_wide, - "system-wide collection from all CPUs"), - OPT_STRING(0, "cpu", &trace.opts.target.cpu_list, "cpu", - "list of cpus to monitor"), - OPT_BOOLEAN(0, "no-inherit", &trace.opts.no_inherit, - "child tasks do not inherit counters"), - OPT_UINTEGER(0, "mmap-pages", &trace.opts.mmap_pages, - "number of mmap data pages"), - OPT_STRING(0, "uid", &trace.opts.target.uid_str, "user", - "user to profile"), - OPT_END() - }; - int err; - - argc = parse_options(argc, argv, trace_options, trace_usage, 0); - if (argc) - usage_with_options(trace_usage, trace_options); - - err = perf_target__parse_uid(&trace.opts.target); - if (err) { - char bf[BUFSIZ]; - perf_target__strerror(&trace.opts.target, err, bf, sizeof(bf)); - printf("%s", bf); - return err; - } - - return trace__run(&trace); -} diff --git a/trunk/tools/perf/builtin.h b/trunk/tools/perf/builtin.h index 08143bd854c7..b382bd551aac 100644 --- a/trunk/tools/perf/builtin.h +++ b/trunk/tools/perf/builtin.h @@ -34,8 +34,6 @@ extern int cmd_kmem(int argc, const char **argv, const char *prefix); extern int cmd_lock(int argc, const char **argv, const char *prefix); extern int cmd_kvm(int argc, const char **argv, const char *prefix); extern int cmd_test(int argc, const char **argv, const char *prefix); -extern int cmd_trace(int argc, const char **argv, const char *prefix); extern int cmd_inject(int argc, const char **argv, const char *prefix); -extern int find_scripts(char **scripts_array, char **scripts_path_array); #endif diff --git a/trunk/tools/perf/command-list.txt b/trunk/tools/perf/command-list.txt index 3e86bbd8c2d5..d695fe40fbff 100644 --- a/trunk/tools/perf/command-list.txt +++ b/trunk/tools/perf/command-list.txt @@ -17,9 +17,8 @@ perf-report mainporcelain common perf-stat mainporcelain common perf-timechart mainporcelain common perf-top mainporcelain common -perf-trace mainporcelain common perf-script mainporcelain common -perf-probe mainporcelain full +perf-probe mainporcelain common perf-kmem mainporcelain common perf-lock mainporcelain common perf-kvm mainporcelain common diff --git a/trunk/tools/perf/config/feature-tests.mak b/trunk/tools/perf/config/feature-tests.mak index 4add41bb0c7e..6c18785a6417 100644 --- a/trunk/tools/perf/config/feature-tests.mak +++ b/trunk/tools/perf/config/feature-tests.mak @@ -154,53 +154,3 @@ int main(void) return 0; } endef - -ifndef NO_LIBUNWIND -define SOURCE_LIBUNWIND -#include -#include - -extern int UNW_OBJ(dwarf_search_unwind_table) (unw_addr_space_t as, - unw_word_t ip, - unw_dyn_info_t *di, - unw_proc_info_t *pi, - int need_unwind_info, void *arg); - - -#define dwarf_search_unwind_table UNW_OBJ(dwarf_search_unwind_table) - -int main(void) -{ - unw_addr_space_t addr_space; - addr_space = unw_create_addr_space(NULL, 0); - unw_init_remote(NULL, addr_space, NULL); - dwarf_search_unwind_table(addr_space, 0, NULL, NULL, 0, NULL); - return 0; -} -endef -endif - -ifndef NO_BACKTRACE -define SOURCE_BACKTRACE -#include -#include - -int main(void) -{ - backtrace(NULL, 0); - backtrace_symbols(NULL, 0); - return 0; -} -endef -endif - -ifndef NO_LIBAUDIT -define SOURCE_LIBAUDIT -#include - -int main(void) -{ - return audit_open(); -} -endef -endif \ No newline at end of file diff --git a/trunk/tools/perf/perf-archive.sh b/trunk/tools/perf/perf-archive.sh index e91930620269..95b6f8b6177a 100644 --- a/trunk/tools/perf/perf-archive.sh +++ b/trunk/tools/perf/perf-archive.sh @@ -24,7 +24,7 @@ NOBUILDID=0000000000000000000000000000000000000000 perf buildid-list -i $PERF_DATA --with-hits | grep -v "^$NOBUILDID " > $BUILDIDS if [ ! -s $BUILDIDS ] ; then echo "perf archive: no build-ids found" - rm $BUILDIDS || true + rm -f $BUILDIDS exit 1 fi @@ -39,8 +39,8 @@ while read build_id ; do echo ${filename#$PERF_BUILDID_LINKDIR} >> $MANIFEST done -tar cjf $PERF_DATA.tar.bz2 -C $PERF_BUILDID_DIR -T $MANIFEST -rm $MANIFEST $BUILDIDS || true +tar cfj $PERF_DATA.tar.bz2 -C $PERF_BUILDID_DIR -T $MANIFEST +rm -f $MANIFEST $BUILDIDS echo -e "Now please run:\n" echo -e "$ tar xvf $PERF_DATA.tar.bz2 -C ~/.debug\n" echo "wherever you need to run 'perf report' on." diff --git a/trunk/tools/perf/perf.c b/trunk/tools/perf/perf.c index fc2f770e3027..2b2e225a4d4c 100644 --- a/trunk/tools/perf/perf.c +++ b/trunk/tools/perf/perf.c @@ -14,7 +14,6 @@ #include "util/run-command.h" #include "util/parse-events.h" #include "util/debugfs.h" -#include const char perf_usage_string[] = "perf [--version] [--help] COMMAND [ARGS]"; @@ -25,42 +24,6 @@ const char perf_more_info_string[] = int use_browser = -1; static int use_pager = -1; -struct cmd_struct { - const char *cmd; - int (*fn)(int, const char **, const char *); - int option; -}; - -static struct cmd_struct commands[] = { - { "buildid-cache", cmd_buildid_cache, 0 }, - { "buildid-list", cmd_buildid_list, 0 }, - { "diff", cmd_diff, 0 }, - { "evlist", cmd_evlist, 0 }, - { "help", cmd_help, 0 }, - { "list", cmd_list, 0 }, - { "record", cmd_record, 0 }, - { "report", cmd_report, 0 }, - { "bench", cmd_bench, 0 }, - { "stat", cmd_stat, 0 }, - { "timechart", cmd_timechart, 0 }, - { "top", cmd_top, 0 }, - { "annotate", cmd_annotate, 0 }, - { "version", cmd_version, 0 }, - { "script", cmd_script, 0 }, - { "sched", cmd_sched, 0 }, -#ifndef NO_LIBELF_SUPPORT - { "probe", cmd_probe, 0 }, -#endif - { "kmem", cmd_kmem, 0 }, - { "lock", cmd_lock, 0 }, - { "kvm", cmd_kvm, 0 }, - { "test", cmd_test, 0 }, -#ifndef NO_LIBAUDIT_SUPPORT - { "trace", cmd_trace, 0 }, -#endif - { "inject", cmd_inject, 0 }, -}; - struct pager_config { const char *cmd; int val; @@ -197,14 +160,6 @@ static int handle_options(const char ***argv, int *argc, int *envchanged) fprintf(stderr, "dir: %s\n", debugfs_mountpoint); if (envchanged) *envchanged = 1; - } else if (!strcmp(cmd, "--list-cmds")) { - unsigned int i; - - for (i = 0; i < ARRAY_SIZE(commands); i++) { - struct cmd_struct *p = commands+i; - printf("%s ", p->cmd); - } - exit(0); } else { fprintf(stderr, "Unknown option: %s\n", cmd); usage(perf_usage_string); @@ -290,6 +245,12 @@ const char perf_version_string[] = PERF_VERSION; */ #define NEED_WORK_TREE (1<<2) +struct cmd_struct { + const char *cmd; + int (*fn)(int, const char **, const char *); + int option; +}; + static int run_builtin(struct cmd_struct *p, int argc, const char **argv) { int status; @@ -335,6 +296,30 @@ static int run_builtin(struct cmd_struct *p, int argc, const char **argv) static void handle_internal_command(int argc, const char **argv) { const char *cmd = argv[0]; + static struct cmd_struct commands[] = { + { "buildid-cache", cmd_buildid_cache, 0 }, + { "buildid-list", cmd_buildid_list, 0 }, + { "diff", cmd_diff, 0 }, + { "evlist", cmd_evlist, 0 }, + { "help", cmd_help, 0 }, + { "list", cmd_list, 0 }, + { "record", cmd_record, 0 }, + { "report", cmd_report, 0 }, + { "bench", cmd_bench, 0 }, + { "stat", cmd_stat, 0 }, + { "timechart", cmd_timechart, 0 }, + { "top", cmd_top, 0 }, + { "annotate", cmd_annotate, 0 }, + { "version", cmd_version, 0 }, + { "script", cmd_script, 0 }, + { "sched", cmd_sched, 0 }, + { "probe", cmd_probe, 0 }, + { "kmem", cmd_kmem, 0 }, + { "lock", cmd_lock, 0 }, + { "kvm", cmd_kvm, 0 }, + { "test", cmd_test, 0 }, + { "inject", cmd_inject, 0 }, + }; unsigned int i; static const char ext[] = STRIP_EXTENSION; diff --git a/trunk/tools/perf/perf.h b/trunk/tools/perf/perf.h index a89cbbb61801..f960ccb2edc6 100644 --- a/trunk/tools/perf/perf.h +++ b/trunk/tools/perf/perf.h @@ -88,12 +88,6 @@ void get_term_dimensions(struct winsize *ws); #define CPUINFO_PROC "Processor" #endif -#ifdef __aarch64__ -#include "../../arch/arm64/include/asm/unistd.h" -#define rmb() asm volatile("dmb ld" ::: "memory") -#define cpu_relax() asm volatile("yield" ::: "memory") -#endif - #ifdef __mips__ #include "../../arch/mips/include/asm/unistd.h" #define rmb() asm volatile( \ @@ -215,15 +209,9 @@ void pthread__unblock_sigwinch(void); #include "util/target.h" -enum perf_call_graph_mode { - CALLCHAIN_NONE, - CALLCHAIN_FP, - CALLCHAIN_DWARF -}; - struct perf_record_opts { struct perf_target target; - int call_graph; + bool call_graph; bool group; bool inherit_stat; bool no_delay; @@ -242,7 +230,6 @@ struct perf_record_opts { u64 branch_stack; u64 default_interval; u64 user_interval; - u16 stack_dump_size; }; #endif diff --git a/trunk/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/EventClass.py b/trunk/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/EventClass.py deleted file mode 100755 index 9e0985794e20..000000000000 --- a/trunk/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/EventClass.py +++ /dev/null @@ -1,94 +0,0 @@ -# EventClass.py -# -# This is a library defining some events types classes, which could -# be used by other scripts to analyzing the perf samples. -# -# Currently there are just a few classes defined for examples, -# PerfEvent is the base class for all perf event sample, PebsEvent -# is a HW base Intel x86 PEBS event, and user could add more SW/HW -# event classes based on requirements. - -import struct - -# Event types, user could add more here -EVTYPE_GENERIC = 0 -EVTYPE_PEBS = 1 # Basic PEBS event -EVTYPE_PEBS_LL = 2 # PEBS event with load latency info -EVTYPE_IBS = 3 - -# -# Currently we don't have good way to tell the event type, but by -# the size of raw buffer, raw PEBS event with load latency data's -# size is 176 bytes, while the pure PEBS event's size is 144 bytes. -# -def create_event(name, comm, dso, symbol, raw_buf): - if (len(raw_buf) == 144): - event = PebsEvent(name, comm, dso, symbol, raw_buf) - elif (len(raw_buf) == 176): - event = PebsNHM(name, comm, dso, symbol, raw_buf) - else: - event = PerfEvent(name, comm, dso, symbol, raw_buf) - - return event - -class PerfEvent(object): - event_num = 0 - def __init__(self, name, comm, dso, symbol, raw_buf, ev_type=EVTYPE_GENERIC): - self.name = name - self.comm = comm - self.dso = dso - self.symbol = symbol - self.raw_buf = raw_buf - self.ev_type = ev_type - PerfEvent.event_num += 1 - - def show(self): - print "PMU event: name=%12s, symbol=%24s, comm=%8s, dso=%12s" % (self.name, self.symbol, self.comm, self.dso) - -# -# Basic Intel PEBS (Precise Event-based Sampling) event, whose raw buffer -# contains the context info when that event happened: the EFLAGS and -# linear IP info, as well as all the registers. -# -class PebsEvent(PerfEvent): - pebs_num = 0 - def __init__(self, name, comm, dso, symbol, raw_buf, ev_type=EVTYPE_PEBS): - tmp_buf=raw_buf[0:80] - flags, ip, ax, bx, cx, dx, si, di, bp, sp = struct.unpack('QQQQQQQQQQ', tmp_buf) - self.flags = flags - self.ip = ip - self.ax = ax - self.bx = bx - self.cx = cx - self.dx = dx - self.si = si - self.di = di - self.bp = bp - self.sp = sp - - PerfEvent.__init__(self, name, comm, dso, symbol, raw_buf, ev_type) - PebsEvent.pebs_num += 1 - del tmp_buf - -# -# Intel Nehalem and Westmere support PEBS plus Load Latency info which lie -# in the four 64 bit words write after the PEBS data: -# Status: records the IA32_PERF_GLOBAL_STATUS register value -# DLA: Data Linear Address (EIP) -# DSE: Data Source Encoding, where the latency happens, hit or miss -# in L1/L2/L3 or IO operations -# LAT: the actual latency in cycles -# -class PebsNHM(PebsEvent): - pebs_nhm_num = 0 - def __init__(self, name, comm, dso, symbol, raw_buf, ev_type=EVTYPE_PEBS_LL): - tmp_buf=raw_buf[144:176] - status, dla, dse, lat = struct.unpack('QQQQ', tmp_buf) - self.status = status - self.dla = dla - self.dse = dse - self.lat = lat - - PebsEvent.__init__(self, name, comm, dso, symbol, raw_buf, ev_type) - PebsNHM.pebs_nhm_num += 1 - del tmp_buf diff --git a/trunk/tools/perf/scripts/python/bin/event_analyzing_sample-record b/trunk/tools/perf/scripts/python/bin/event_analyzing_sample-record deleted file mode 100644 index 5ce652dabd02..000000000000 --- a/trunk/tools/perf/scripts/python/bin/event_analyzing_sample-record +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/bash - -# -# event_analyzing_sample.py can cover all type of perf samples including -# the tracepoints, so no special record requirements, just record what -# you want to analyze. -# -perf record $@ diff --git a/trunk/tools/perf/scripts/python/bin/event_analyzing_sample-report b/trunk/tools/perf/scripts/python/bin/event_analyzing_sample-report deleted file mode 100644 index 0941fc94e158..000000000000 --- a/trunk/tools/perf/scripts/python/bin/event_analyzing_sample-report +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash -# description: analyze all perf samples -perf script $@ -s "$PERF_EXEC_PATH"/scripts/python/event_analyzing_sample.py diff --git a/trunk/tools/perf/scripts/python/event_analyzing_sample.py b/trunk/tools/perf/scripts/python/event_analyzing_sample.py deleted file mode 100644 index 163c39fa12d9..000000000000 --- a/trunk/tools/perf/scripts/python/event_analyzing_sample.py +++ /dev/null @@ -1,189 +0,0 @@ -# event_analyzing_sample.py: general event handler in python -# -# Current perf report is already very powerful with the annotation integrated, -# and this script is not trying to be as powerful as perf report, but -# providing end user/developer a flexible way to analyze the events other -# than trace points. -# -# The 2 database related functions in this script just show how to gather -# the basic information, and users can modify and write their own functions -# according to their specific requirement. -# -# The first function "show_general_events" just does a basic grouping for all -# generic events with the help of sqlite, and the 2nd one "show_pebs_ll" is -# for a x86 HW PMU event: PEBS with load latency data. -# - -import os -import sys -import math -import struct -import sqlite3 - -sys.path.append(os.environ['PERF_EXEC_PATH'] + \ - '/scripts/python/Perf-Trace-Util/lib/Perf/Trace') - -from perf_trace_context import * -from EventClass import * - -# -# If the perf.data has a big number of samples, then the insert operation -# will be very time consuming (about 10+ minutes for 10000 samples) if the -# .db database is on disk. Move the .db file to RAM based FS to speedup -# the handling, which will cut the time down to several seconds. -# -con = sqlite3.connect("/dev/shm/perf.db") -con.isolation_level = None - -def trace_begin(): - print "In trace_begin:\n" - - # - # Will create several tables at the start, pebs_ll is for PEBS data with - # load latency info, while gen_events is for general event. - # - con.execute(""" - create table if not exists gen_events ( - name text, - symbol text, - comm text, - dso text - );""") - con.execute(""" - create table if not exists pebs_ll ( - name text, - symbol text, - comm text, - dso text, - flags integer, - ip integer, - status integer, - dse integer, - dla integer, - lat integer - );""") - -# -# Create and insert event object to a database so that user could -# do more analysis with simple database commands. -# -def process_event(param_dict): - event_attr = param_dict["attr"] - sample = param_dict["sample"] - raw_buf = param_dict["raw_buf"] - comm = param_dict["comm"] - name = param_dict["ev_name"] - - # Symbol and dso info are not always resolved - if (param_dict.has_key("dso")): - dso = param_dict["dso"] - else: - dso = "Unknown_dso" - - if (param_dict.has_key("symbol")): - symbol = param_dict["symbol"] - else: - symbol = "Unknown_symbol" - - # Create the event object and insert it to the right table in database - event = create_event(name, comm, dso, symbol, raw_buf) - insert_db(event) - -def insert_db(event): - if event.ev_type == EVTYPE_GENERIC: - con.execute("insert into gen_events values(?, ?, ?, ?)", - (event.name, event.symbol, event.comm, event.dso)) - elif event.ev_type == EVTYPE_PEBS_LL: - event.ip &= 0x7fffffffffffffff - event.dla &= 0x7fffffffffffffff - con.execute("insert into pebs_ll values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", - (event.name, event.symbol, event.comm, event.dso, event.flags, - event.ip, event.status, event.dse, event.dla, event.lat)) - -def trace_end(): - print "In trace_end:\n" - # We show the basic info for the 2 type of event classes - show_general_events() - show_pebs_ll() - con.close() - -# -# As the event number may be very big, so we can't use linear way -# to show the histogram in real number, but use a log2 algorithm. -# - -def num2sym(num): - # Each number will have at least one '#' - snum = '#' * (int)(math.log(num, 2) + 1) - return snum - -def show_general_events(): - - # Check the total record number in the table - count = con.execute("select count(*) from gen_events") - for t in count: - print "There is %d records in gen_events table" % t[0] - if t[0] == 0: - return - - print "Statistics about the general events grouped by thread/symbol/dso: \n" - - # Group by thread - commq = con.execute("select comm, count(comm) from gen_events group by comm order by -count(comm)") - print "\n%16s %8s %16s\n%s" % ("comm", "number", "histogram", "="*42) - for row in commq: - print "%16s %8d %s" % (row[0], row[1], num2sym(row[1])) - - # Group by symbol - print "\n%32s %8s %16s\n%s" % ("symbol", "number", "histogram", "="*58) - symbolq = con.execute("select symbol, count(symbol) from gen_events group by symbol order by -count(symbol)") - for row in symbolq: - print "%32s %8d %s" % (row[0], row[1], num2sym(row[1])) - - # Group by dso - print "\n%40s %8s %16s\n%s" % ("dso", "number", "histogram", "="*74) - dsoq = con.execute("select dso, count(dso) from gen_events group by dso order by -count(dso)") - for row in dsoq: - print "%40s %8d %s" % (row[0], row[1], num2sym(row[1])) - -# -# This function just shows the basic info, and we could do more with the -# data in the tables, like checking the function parameters when some -# big latency events happen. -# -def show_pebs_ll(): - - count = con.execute("select count(*) from pebs_ll") - for t in count: - print "There is %d records in pebs_ll table" % t[0] - if t[0] == 0: - return - - print "Statistics about the PEBS Load Latency events grouped by thread/symbol/dse/latency: \n" - - # Group by thread - commq = con.execute("select comm, count(comm) from pebs_ll group by comm order by -count(comm)") - print "\n%16s %8s %16s\n%s" % ("comm", "number", "histogram", "="*42) - for row in commq: - print "%16s %8d %s" % (row[0], row[1], num2sym(row[1])) - - # Group by symbol - print "\n%32s %8s %16s\n%s" % ("symbol", "number", "histogram", "="*58) - symbolq = con.execute("select symbol, count(symbol) from pebs_ll group by symbol order by -count(symbol)") - for row in symbolq: - print "%32s %8d %s" % (row[0], row[1], num2sym(row[1])) - - # Group by dse - dseq = con.execute("select dse, count(dse) from pebs_ll group by dse order by -count(dse)") - print "\n%32s %8s %16s\n%s" % ("dse", "number", "histogram", "="*58) - for row in dseq: - print "%32s %8d %s" % (row[0], row[1], num2sym(row[1])) - - # Group by latency - latq = con.execute("select lat, count(lat) from pebs_ll group by lat order by lat") - print "\n%32s %8s %16s\n%s" % ("latency", "number", "histogram", "="*58) - for row in latq: - print "%32s %8d %s" % (row[0], row[1], num2sym(row[1])) - -def trace_unhandled(event_name, context, event_fields_dict): - print ' '.join(['%s=%s'%(k,str(v))for k,v in sorted(event_fields_dict.items())]) diff --git a/trunk/tools/perf/ui/browser.c b/trunk/tools/perf/ui/browser.c index 4aeb7d5df939..1818a531f1d3 100644 --- a/trunk/tools/perf/ui/browser.c +++ b/trunk/tools/perf/ui/browser.c @@ -269,7 +269,7 @@ int ui_browser__show(struct ui_browser *browser, const char *title, return err ? 0 : -1; } -void ui_browser__hide(struct ui_browser *browser __maybe_unused) +void ui_browser__hide(struct ui_browser *browser __used) { pthread_mutex_lock(&ui__lock); ui_helpline__pop(); @@ -518,7 +518,7 @@ static struct ui_browser__colorset { static int ui_browser__color_config(const char *var, const char *value, - void *data __maybe_unused) + void *data __used) { char *fg = NULL, *bg; int i; @@ -602,8 +602,7 @@ void __ui_browser__vline(struct ui_browser *browser, unsigned int column, SLsmg_set_char_set(0); } -void ui_browser__write_graph(struct ui_browser *browser __maybe_unused, - int graph) +void ui_browser__write_graph(struct ui_browser *browser __used, int graph) { SLsmg_set_char_set(1); SLsmg_write_char(graph); diff --git a/trunk/tools/perf/ui/browsers/annotate.c b/trunk/tools/perf/ui/browsers/annotate.c index 8f8cd2d73b3b..67a2703e666a 100644 --- a/trunk/tools/perf/ui/browsers/annotate.c +++ b/trunk/tools/perf/ui/browsers/annotate.c @@ -54,8 +54,7 @@ static inline struct browser_disasm_line *disasm_line__browser(struct disasm_lin return (struct browser_disasm_line *)(dl + 1); } -static bool disasm_line__filter(struct ui_browser *browser __maybe_unused, - void *entry) +static bool disasm_line__filter(struct ui_browser *browser __used, void *entry) { if (annotate_browser__opts.hide_src_code) { struct disasm_line *dl = list_entry(entry, struct disasm_line, node); @@ -929,8 +928,7 @@ static int annotate_config__cmp(const void *name, const void *cfgp) return strcmp(name, cfg->name); } -static int annotate__config(const char *var, const char *value, - void *data __maybe_unused) +static int annotate__config(const char *var, const char *value, void *data __used) { struct annotate__config *cfg; const char *name; diff --git a/trunk/tools/perf/ui/browsers/hists.c b/trunk/tools/perf/ui/browsers/hists.c index a21f40bebbac..413bd62eedb1 100644 --- a/trunk/tools/perf/ui/browsers/hists.c +++ b/trunk/tools/perf/ui/browsers/hists.c @@ -24,12 +24,9 @@ struct hist_browser { struct hist_entry *he_selection; struct map_symbol *selection; int print_seq; - bool show_dso; bool has_symbols; }; -extern void hist_browser__init_hpp(void); - static int hists__browser_title(struct hists *hists, char *bf, size_t size, const char *ev_name); @@ -379,19 +376,12 @@ static int hist_browser__run(struct hist_browser *browser, const char *ev_name, } static char *callchain_list__sym_name(struct callchain_list *cl, - char *bf, size_t bfsize, bool show_dso) + char *bf, size_t bfsize) { - int printed; - if (cl->ms.sym) - printed = scnprintf(bf, bfsize, "%s", cl->ms.sym->name); - else - printed = scnprintf(bf, bfsize, "%#" PRIx64, cl->ip); - - if (show_dso) - scnprintf(bf + printed, bfsize - printed, " %s", - cl->ms.map ? cl->ms.map->dso->short_name : "unknown"); + return cl->ms.sym->name; + snprintf(bf, bfsize, "%#" PRIx64, cl->ip); return bf; } @@ -427,7 +417,7 @@ static int hist_browser__show_callchain_node_rb_tree(struct hist_browser *browse remaining -= cumul; list_for_each_entry(chain, &child->val, list) { - char bf[1024], *alloc_str; + char ipstr[BITS_PER_LONG / 4 + 1], *alloc_str; const char *str; int color; bool was_first = first; @@ -444,8 +434,7 @@ static int hist_browser__show_callchain_node_rb_tree(struct hist_browser *browse } alloc_str = NULL; - str = callchain_list__sym_name(chain, bf, sizeof(bf), - browser->show_dso); + str = callchain_list__sym_name(chain, ipstr, sizeof(ipstr)); if (was_first) { double percent = cumul * 100.0 / new_total; @@ -504,7 +493,7 @@ static int hist_browser__show_callchain_node(struct hist_browser *browser, char folded_sign = ' '; list_for_each_entry(chain, &node->val, list) { - char bf[1024], *s; + char ipstr[BITS_PER_LONG / 4 + 1], *s; int color; folded_sign = callchain_list__folded(chain); @@ -521,8 +510,7 @@ static int hist_browser__show_callchain_node(struct hist_browser *browser, *is_current_entry = true; } - s = callchain_list__sym_name(chain, bf, sizeof(bf), - browser->show_dso); + s = callchain_list__sym_name(chain, ipstr, sizeof(ipstr)); ui_browser__gotorc(&browser->b, row, 0); ui_browser__set_color(&browser->b, color); slsmg_write_nstring(" ", offset); @@ -565,47 +553,14 @@ static int hist_browser__show_callchain(struct hist_browser *browser, return row - first_row; } -#define HPP__COLOR_FN(_name, _field) \ -static int hist_browser__hpp_color_ ## _name(struct perf_hpp *hpp, \ - struct hist_entry *he) \ -{ \ - double percent = 100.0 * he->_field / hpp->total_period; \ - *(double *)hpp->ptr = percent; \ - return scnprintf(hpp->buf, hpp->size, "%6.2f%%", percent); \ -} - -HPP__COLOR_FN(overhead, period) -HPP__COLOR_FN(overhead_sys, period_sys) -HPP__COLOR_FN(overhead_us, period_us) -HPP__COLOR_FN(overhead_guest_sys, period_guest_sys) -HPP__COLOR_FN(overhead_guest_us, period_guest_us) - -#undef HPP__COLOR_FN - -void hist_browser__init_hpp(void) -{ - perf_hpp__init(false, false); - - perf_hpp__format[PERF_HPP__OVERHEAD].color = - hist_browser__hpp_color_overhead; - perf_hpp__format[PERF_HPP__OVERHEAD_SYS].color = - hist_browser__hpp_color_overhead_sys; - perf_hpp__format[PERF_HPP__OVERHEAD_US].color = - hist_browser__hpp_color_overhead_us; - perf_hpp__format[PERF_HPP__OVERHEAD_GUEST_SYS].color = - hist_browser__hpp_color_overhead_guest_sys; - perf_hpp__format[PERF_HPP__OVERHEAD_GUEST_US].color = - hist_browser__hpp_color_overhead_guest_us; -} - static int hist_browser__show_entry(struct hist_browser *browser, struct hist_entry *entry, unsigned short row) { char s[256]; double percent; - int i, printed = 0; - int width = browser->b.width; + int printed = 0; + int width = browser->b.width - 6; /* The percentage */ char folded_sign = ' '; bool current_entry = ui_browser__is_current_entry(&browser->b, row); off_t row_offset = entry->row_offset; @@ -621,50 +576,35 @@ static int hist_browser__show_entry(struct hist_browser *browser, } if (row_offset == 0) { - struct perf_hpp hpp = { - .buf = s, - .size = sizeof(s), - .total_period = browser->hists->stats.total_period, - }; + hist_entry__snprintf(entry, s, sizeof(s), browser->hists); + percent = (entry->period * 100.0) / browser->hists->stats.total_period; + ui_browser__set_percent_color(&browser->b, percent, current_entry); ui_browser__gotorc(&browser->b, row, 0); + if (symbol_conf.use_callchain) { + slsmg_printf("%c ", folded_sign); + width -= 2; + } - for (i = 0; i < PERF_HPP__MAX_INDEX; i++) { - if (!perf_hpp__format[i].cond) - continue; - - if (i) { - slsmg_printf(" "); - width -= 2; - } - - if (perf_hpp__format[i].color) { - hpp.ptr = &percent; - /* It will set percent for us. See HPP__COLOR_FN above. */ - width -= perf_hpp__format[i].color(&hpp, entry); - - ui_browser__set_percent_color(&browser->b, percent, current_entry); + slsmg_printf(" %5.2f%%", percent); - if (i == 0 && symbol_conf.use_callchain) { - slsmg_printf("%c ", folded_sign); - width -= 2; - } + /* The scroll bar isn't being used */ + if (!browser->b.navkeypressed) + width += 1; - slsmg_printf("%s", s); + if (!current_entry || !browser->b.navkeypressed) + ui_browser__set_color(&browser->b, HE_COLORSET_NORMAL); - if (!current_entry || !browser->b.navkeypressed) - ui_browser__set_color(&browser->b, HE_COLORSET_NORMAL); - } else { - width -= perf_hpp__format[i].entry(&hpp, entry); - slsmg_printf("%s", s); - } + if (symbol_conf.show_nr_samples) { + slsmg_printf(" %11u", entry->nr_events); + width -= 12; } - /* The scroll bar isn't being used */ - if (!browser->b.navkeypressed) - width += 1; + if (symbol_conf.show_total_period) { + slsmg_printf(" %12" PRIu64, entry->period); + width -= 13; + } - hist_entry__sort_snprintf(entry, s, sizeof(s), browser->hists); slsmg_write_nstring(s, width); ++row; ++printed; @@ -890,7 +830,7 @@ static int hist_browser__fprintf_callchain_node_rb_tree(struct hist_browser *bro remaining -= cumul; list_for_each_entry(chain, &child->val, list) { - char bf[1024], *alloc_str; + char ipstr[BITS_PER_LONG / 4 + 1], *alloc_str; const char *str; bool was_first = first; @@ -902,8 +842,7 @@ static int hist_browser__fprintf_callchain_node_rb_tree(struct hist_browser *bro folded_sign = callchain_list__folded(chain); alloc_str = NULL; - str = callchain_list__sym_name(chain, bf, sizeof(bf), - browser->show_dso); + str = callchain_list__sym_name(chain, ipstr, sizeof(ipstr)); if (was_first) { double percent = cumul * 100.0 / new_total; @@ -941,10 +880,10 @@ static int hist_browser__fprintf_callchain_node(struct hist_browser *browser, int printed = 0; list_for_each_entry(chain, &node->val, list) { - char bf[1024], *s; + char ipstr[BITS_PER_LONG / 4 + 1], *s; folded_sign = callchain_list__folded(chain); - s = callchain_list__sym_name(chain, bf, sizeof(bf), browser->show_dso); + s = callchain_list__sym_name(chain, ipstr, sizeof(ipstr)); printed += fprintf(fp, "%*s%c %s\n", offset, " ", folded_sign, s); } @@ -981,7 +920,7 @@ static int hist_browser__fprintf_entry(struct hist_browser *browser, if (symbol_conf.use_callchain) folded_sign = hist_entry__folded(he); - hist_entry__sort_snprintf(he, s, sizeof(s), browser->hists); + hist_entry__snprintf(he, s, sizeof(s), browser->hists); percent = (he->period * 100.0) / browser->hists->stats.total_period; if (symbol_conf.use_callchain) @@ -1194,9 +1133,6 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events, continue; case 'd': goto zoom_dso; - case 'V': - browser->show_dso = !browser->show_dso; - continue; case 't': goto zoom_thread; case '/': @@ -1228,7 +1164,6 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events, "d Zoom into current DSO\n" "t Zoom into current Thread\n" "P Print histograms to perf.hist.N\n" - "V Verbose (DSO names in callchains, etc)\n" "/ Filter symbol by name"); continue; case K_ENTER: diff --git a/trunk/tools/perf/ui/gtk/browser.c b/trunk/tools/perf/ui/gtk/browser.c index 7ff99ec1d95e..ec12e0b4ded6 100644 --- a/trunk/tools/perf/ui/gtk/browser.c +++ b/trunk/tools/perf/ui/gtk/browser.c @@ -3,7 +3,6 @@ #include "../evsel.h" #include "../sort.h" #include "../hist.h" -#include "../helpline.h" #include "gtk.h" #include @@ -36,57 +35,6 @@ static void perf_gtk__resize_window(GtkWidget *window) gtk_window_resize(GTK_WINDOW(window), width, height); } -static const char *perf_gtk__get_percent_color(double percent) -{ - if (percent >= MIN_RED) - return ""; - if (percent >= MIN_GREEN) - return ""; - return NULL; -} - -#define HPP__COLOR_FN(_name, _field) \ -static int perf_gtk__hpp_color_ ## _name(struct perf_hpp *hpp, \ - struct hist_entry *he) \ -{ \ - double percent = 100.0 * he->_field / hpp->total_period; \ - const char *markup; \ - int ret = 0; \ - \ - markup = perf_gtk__get_percent_color(percent); \ - if (markup) \ - ret += scnprintf(hpp->buf, hpp->size, "%s", markup); \ - ret += scnprintf(hpp->buf + ret, hpp->size - ret, "%6.2f%%", percent); \ - if (markup) \ - ret += scnprintf(hpp->buf + ret, hpp->size - ret, ""); \ - \ - return ret; \ -} - -HPP__COLOR_FN(overhead, period) -HPP__COLOR_FN(overhead_sys, period_sys) -HPP__COLOR_FN(overhead_us, period_us) -HPP__COLOR_FN(overhead_guest_sys, period_guest_sys) -HPP__COLOR_FN(overhead_guest_us, period_guest_us) - -#undef HPP__COLOR_FN - -void perf_gtk__init_hpp(void) -{ - perf_hpp__init(false, false); - - perf_hpp__format[PERF_HPP__OVERHEAD].color = - perf_gtk__hpp_color_overhead; - perf_hpp__format[PERF_HPP__OVERHEAD_SYS].color = - perf_gtk__hpp_color_overhead_sys; - perf_hpp__format[PERF_HPP__OVERHEAD_US].color = - perf_gtk__hpp_color_overhead_us; - perf_hpp__format[PERF_HPP__OVERHEAD_GUEST_SYS].color = - perf_gtk__hpp_color_overhead_guest_sys; - perf_hpp__format[PERF_HPP__OVERHEAD_GUEST_US].color = - perf_gtk__hpp_color_overhead_guest_us; -} - static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists) { GType col_types[MAX_COLUMNS]; @@ -94,25 +42,15 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists) struct sort_entry *se; GtkListStore *store; struct rb_node *nd; + u64 total_period; GtkWidget *view; - int i, col_idx; + int col_idx; int nr_cols; - char s[512]; - - struct perf_hpp hpp = { - .buf = s, - .size = sizeof(s), - .total_period = hists->stats.total_period, - }; nr_cols = 0; - for (i = 0; i < PERF_HPP__MAX_INDEX; i++) { - if (!perf_hpp__format[i].cond) - continue; - - col_types[nr_cols++] = G_TYPE_STRING; - } + /* The percentage column */ + col_types[nr_cols++] = G_TYPE_STRING; list_for_each_entry(se, &hist_entry__sort_list, list) { if (se->elide) @@ -129,17 +67,11 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists) col_idx = 0; - for (i = 0; i < PERF_HPP__MAX_INDEX; i++) { - if (!perf_hpp__format[i].cond) - continue; - - perf_hpp__format[i].header(&hpp); - - gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view), - -1, s, - renderer, "markup", - col_idx++, NULL); - } + /* The percentage column */ + gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view), + -1, "Overhead (%)", + renderer, "text", + col_idx++, NULL); list_for_each_entry(se, &hist_entry__sort_list, list) { if (se->elide) @@ -155,9 +87,13 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists) g_object_unref(GTK_TREE_MODEL(store)); + total_period = hists->stats.total_period; + for (nd = rb_first(&hists->entries); nd; nd = rb_next(nd)) { struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node); GtkTreeIter iter; + double percent; + char s[512]; if (h->filtered) continue; @@ -166,17 +102,11 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists) col_idx = 0; - for (i = 0; i < PERF_HPP__MAX_INDEX; i++) { - if (!perf_hpp__format[i].cond) - continue; + percent = (h->period * 100.0) / total_period; - if (perf_hpp__format[i].color) - perf_hpp__format[i].color(&hpp, h); - else - perf_hpp__format[i].entry(&hpp, h); + snprintf(s, ARRAY_SIZE(s), "%.2f", percent); - gtk_list_store_set(store, &iter, col_idx++, s, -1); - } + gtk_list_store_set(store, &iter, col_idx++, s, -1); list_for_each_entry(se, &hist_entry__sort_list, list) { if (se->elide) @@ -236,10 +166,9 @@ static GtkWidget *perf_gtk__setup_statusbar(void) } int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist, - const char *help, - void (*timer) (void *arg)__maybe_unused, - void *arg __maybe_unused, - int delay_secs __maybe_unused) + const char *help __used, + void (*timer) (void *arg)__used, + void *arg __used, int delay_secs __used) { struct perf_evsel *pos; GtkWidget *vbox; @@ -304,8 +233,6 @@ int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist, gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER); - ui_helpline__push(help); - gtk_main(); perf_gtk__deactivate_context(&pgctx); diff --git a/trunk/tools/perf/ui/gtk/gtk.h b/trunk/tools/perf/ui/gtk/gtk.h index 687af0bba187..a4d0f2b4a2dc 100644 --- a/trunk/tools/perf/ui/gtk/gtk.h +++ b/trunk/tools/perf/ui/gtk/gtk.h @@ -29,9 +29,6 @@ static inline bool perf_gtk__is_active_context(struct perf_gtk_context *ctx) struct perf_gtk_context *perf_gtk__activate_context(GtkWidget *window); int perf_gtk__deactivate_context(struct perf_gtk_context **ctx); -void perf_gtk__init_helpline(void); -void perf_gtk__init_hpp(void); - #ifndef HAVE_GTK_INFO_BAR static inline GtkWidget *perf_gtk__setup_info_bar(void) { diff --git a/trunk/tools/perf/ui/gtk/helpline.c b/trunk/tools/perf/ui/gtk/helpline.c deleted file mode 100644 index 5db4432ff12a..000000000000 --- a/trunk/tools/perf/ui/gtk/helpline.c +++ /dev/null @@ -1,56 +0,0 @@ -#include -#include - -#include "gtk.h" -#include "../ui.h" -#include "../helpline.h" -#include "../../util/debug.h" - -static void gtk_helpline_pop(void) -{ - if (!perf_gtk__is_active_context(pgctx)) - return; - - gtk_statusbar_pop(GTK_STATUSBAR(pgctx->statbar), - pgctx->statbar_ctx_id); -} - -static void gtk_helpline_push(const char *msg) -{ - if (!perf_gtk__is_active_context(pgctx)) - return; - - gtk_statusbar_push(GTK_STATUSBAR(pgctx->statbar), - pgctx->statbar_ctx_id, msg); -} - -static struct ui_helpline gtk_helpline_fns = { - .pop = gtk_helpline_pop, - .push = gtk_helpline_push, -}; - -void perf_gtk__init_helpline(void) -{ - helpline_fns = >k_helpline_fns; -} - -int perf_gtk__show_helpline(const char *fmt, va_list ap) -{ - int ret; - char *ptr; - static int backlog; - - ret = vscnprintf(ui_helpline__current + backlog, - sizeof(ui_helpline__current) - backlog, fmt, ap); - backlog += ret; - - /* only first line can be displayed */ - ptr = strchr(ui_helpline__current, '\n'); - if (ptr && (ptr - ui_helpline__current) <= backlog) { - *ptr = '\0'; - ui_helpline__puts(ui_helpline__current); - backlog = 0; - } - - return ret; -} diff --git a/trunk/tools/perf/ui/gtk/setup.c b/trunk/tools/perf/ui/gtk/setup.c index 3c4c6ef78283..92879ce61e2f 100644 --- a/trunk/tools/perf/ui/gtk/setup.c +++ b/trunk/tools/perf/ui/gtk/setup.c @@ -7,15 +7,11 @@ extern struct perf_error_ops perf_gtk_eops; int perf_gtk__init(void) { perf_error__register(&perf_gtk_eops); - perf_gtk__init_helpline(); - perf_gtk__init_hpp(); return gtk_init_check(NULL, NULL) ? 0 : -1; } -void perf_gtk__exit(bool wait_for_ok __maybe_unused) +void perf_gtk__exit(bool wait_for_ok __used) { - if (!perf_gtk__is_active_context(pgctx)) - return; perf_error__unregister(&perf_gtk_eops); gtk_main_quit(); } diff --git a/trunk/tools/perf/ui/gtk/util.c b/trunk/tools/perf/ui/gtk/util.c index 8aada5b3c04c..0ead373c0dfb 100644 --- a/trunk/tools/perf/ui/gtk/util.c +++ b/trunk/tools/perf/ui/gtk/util.c @@ -117,8 +117,13 @@ struct perf_error_ops perf_gtk_eops = { * For now, just add stubs for NO_NEWT=1 build. */ #ifdef NO_NEWT_SUPPORT -void ui_progress__update(u64 curr __maybe_unused, u64 total __maybe_unused, - const char *title __maybe_unused) +int ui_helpline__show_help(const char *format __used, va_list ap __used) +{ + return 0; +} + +void ui_progress__update(u64 curr __used, u64 total __used, + const char *title __used) { } #endif diff --git a/trunk/tools/perf/ui/helpline.c b/trunk/tools/perf/ui/helpline.c index a49bcf3c190b..2f950c2641c8 100644 --- a/trunk/tools/perf/ui/helpline.c +++ b/trunk/tools/perf/ui/helpline.c @@ -5,32 +5,23 @@ #include "../debug.h" #include "helpline.h" #include "ui.h" - -char ui_helpline__current[512]; - -static void nop_helpline__pop(void) -{ -} - -static void nop_helpline__push(const char *msg __maybe_unused) -{ -} - -static struct ui_helpline default_helpline_fns = { - .pop = nop_helpline__pop, - .push = nop_helpline__push, -}; - -struct ui_helpline *helpline_fns = &default_helpline_fns; +#include "libslang.h" void ui_helpline__pop(void) { - helpline_fns->pop(); } +char ui_helpline__current[512]; + void ui_helpline__push(const char *msg) { - helpline_fns->push(msg); + const size_t sz = sizeof(ui_helpline__current); + + SLsmg_gotorc(SLtt_Screen_Rows - 1, 0); + SLsmg_set_color(0); + SLsmg_write_nstring((char *)msg, SLtt_Screen_Cols); + SLsmg_refresh(); + strncpy(ui_helpline__current, msg, sz)[sz - 1] = '\0'; } void ui_helpline__vpush(const char *fmt, va_list ap) @@ -59,3 +50,30 @@ void ui_helpline__puts(const char *msg) ui_helpline__pop(); ui_helpline__push(msg); } + +void ui_helpline__init(void) +{ + ui_helpline__puts(" "); +} + +char ui_helpline__last_msg[1024]; + +int ui_helpline__show_help(const char *format, va_list ap) +{ + int ret; + static int backlog; + + pthread_mutex_lock(&ui__lock); + ret = vscnprintf(ui_helpline__last_msg + backlog, + sizeof(ui_helpline__last_msg) - backlog, format, ap); + backlog += ret; + + if (ui_helpline__last_msg[backlog - 1] == '\n') { + ui_helpline__puts(ui_helpline__last_msg); + SLsmg_refresh(); + backlog = 0; + } + pthread_mutex_unlock(&ui__lock); + + return ret; +} diff --git a/trunk/tools/perf/ui/helpline.h b/trunk/tools/perf/ui/helpline.h index 2b667ee454c3..7bab6b34e35e 100644 --- a/trunk/tools/perf/ui/helpline.h +++ b/trunk/tools/perf/ui/helpline.h @@ -4,44 +4,13 @@ #include #include -#include "../util/cache.h" - -struct ui_helpline { - void (*pop)(void); - void (*push)(const char *msg); -}; - -extern struct ui_helpline *helpline_fns; - void ui_helpline__init(void); - void ui_helpline__pop(void); void ui_helpline__push(const char *msg); void ui_helpline__vpush(const char *fmt, va_list ap); void ui_helpline__fpush(const char *fmt, ...); void ui_helpline__puts(const char *msg); -extern char ui_helpline__current[512]; - -#ifdef NO_NEWT_SUPPORT -static inline int ui_helpline__show_help(const char *format __maybe_unused, - va_list ap __maybe_unused) -{ - return 0; -} -#else -extern char ui_helpline__last_msg[]; -int ui_helpline__show_help(const char *format, va_list ap); -#endif /* NO_NEWT_SUPPORT */ - -#ifdef NO_GTK2_SUPPORT -static inline int perf_gtk__show_helpline(const char *format __maybe_unused, - va_list ap __maybe_unused) -{ - return 0; -} -#else -int perf_gtk__show_helpline(const char *format, va_list ap); -#endif /* NO_GTK2_SUPPORT */ +extern char ui_helpline__current[]; #endif /* _PERF_UI_HELPLINE_H_ */ diff --git a/trunk/tools/perf/ui/hist.c b/trunk/tools/perf/ui/hist.c deleted file mode 100644 index e3f8cd46e7d7..000000000000 --- a/trunk/tools/perf/ui/hist.c +++ /dev/null @@ -1,390 +0,0 @@ -#include - -#include "../util/hist.h" -#include "../util/util.h" -#include "../util/sort.h" - - -/* hist period print (hpp) functions */ -static int hpp__header_overhead(struct perf_hpp *hpp) -{ - const char *fmt = hpp->ptr ? "Baseline" : "Overhead"; - - return scnprintf(hpp->buf, hpp->size, fmt); -} - -static int hpp__width_overhead(struct perf_hpp *hpp __maybe_unused) -{ - return 8; -} - -static int hpp__color_overhead(struct perf_hpp *hpp, struct hist_entry *he) -{ - double percent = 100.0 * he->period / hpp->total_period; - - if (hpp->ptr) { - struct hists *old_hists = hpp->ptr; - u64 total_period = old_hists->stats.total_period; - u64 base_period = he->pair ? he->pair->period : 0; - - if (total_period) - percent = 100.0 * base_period / total_period; - else - percent = 0.0; - } - - return percent_color_snprintf(hpp->buf, hpp->size, " %6.2f%%", percent); -} - -static int hpp__entry_overhead(struct perf_hpp *hpp, struct hist_entry *he) -{ - double percent = 100.0 * he->period / hpp->total_period; - const char *fmt = symbol_conf.field_sep ? "%.2f" : " %6.2f%%"; - - if (hpp->ptr) { - struct hists *old_hists = hpp->ptr; - u64 total_period = old_hists->stats.total_period; - u64 base_period = he->pair ? he->pair->period : 0; - - if (total_period) - percent = 100.0 * base_period / total_period; - else - percent = 0.0; - } - - return scnprintf(hpp->buf, hpp->size, fmt, percent); -} - -static int hpp__header_overhead_sys(struct perf_hpp *hpp) -{ - const char *fmt = symbol_conf.field_sep ? "%s" : "%7s"; - - return scnprintf(hpp->buf, hpp->size, fmt, "sys"); -} - -static int hpp__width_overhead_sys(struct perf_hpp *hpp __maybe_unused) -{ - return 7; -} - -static int hpp__color_overhead_sys(struct perf_hpp *hpp, struct hist_entry *he) -{ - double percent = 100.0 * he->period_sys / hpp->total_period; - return percent_color_snprintf(hpp->buf, hpp->size, "%6.2f%%", percent); -} - -static int hpp__entry_overhead_sys(struct perf_hpp *hpp, struct hist_entry *he) -{ - double percent = 100.0 * he->period_sys / hpp->total_period; - const char *fmt = symbol_conf.field_sep ? "%.2f" : "%6.2f%%"; - - return scnprintf(hpp->buf, hpp->size, fmt, percent); -} - -static int hpp__header_overhead_us(struct perf_hpp *hpp) -{ - const char *fmt = symbol_conf.field_sep ? "%s" : "%7s"; - - return scnprintf(hpp->buf, hpp->size, fmt, "user"); -} - -static int hpp__width_overhead_us(struct perf_hpp *hpp __maybe_unused) -{ - return 7; -} - -static int hpp__color_overhead_us(struct perf_hpp *hpp, struct hist_entry *he) -{ - double percent = 100.0 * he->period_us / hpp->total_period; - return percent_color_snprintf(hpp->buf, hpp->size, "%6.2f%%", percent); -} - -static int hpp__entry_overhead_us(struct perf_hpp *hpp, struct hist_entry *he) -{ - double percent = 100.0 * he->period_us / hpp->total_period; - const char *fmt = symbol_conf.field_sep ? "%.2f" : "%6.2f%%"; - - return scnprintf(hpp->buf, hpp->size, fmt, percent); -} - -static int hpp__header_overhead_guest_sys(struct perf_hpp *hpp) -{ - return scnprintf(hpp->buf, hpp->size, "guest sys"); -} - -static int hpp__width_overhead_guest_sys(struct perf_hpp *hpp __maybe_unused) -{ - return 9; -} - -static int hpp__color_overhead_guest_sys(struct perf_hpp *hpp, - struct hist_entry *he) -{ - double percent = 100.0 * he->period_guest_sys / hpp->total_period; - return percent_color_snprintf(hpp->buf, hpp->size, " %6.2f%% ", percent); -} - -static int hpp__entry_overhead_guest_sys(struct perf_hpp *hpp, - struct hist_entry *he) -{ - double percent = 100.0 * he->period_guest_sys / hpp->total_period; - const char *fmt = symbol_conf.field_sep ? "%.2f" : " %6.2f%% "; - - return scnprintf(hpp->buf, hpp->size, fmt, percent); -} - -static int hpp__header_overhead_guest_us(struct perf_hpp *hpp) -{ - return scnprintf(hpp->buf, hpp->size, "guest usr"); -} - -static int hpp__width_overhead_guest_us(struct perf_hpp *hpp __maybe_unused) -{ - return 9; -} - -static int hpp__color_overhead_guest_us(struct perf_hpp *hpp, - struct hist_entry *he) -{ - double percent = 100.0 * he->period_guest_us / hpp->total_period; - return percent_color_snprintf(hpp->buf, hpp->size, " %6.2f%% ", percent); -} - -static int hpp__entry_overhead_guest_us(struct perf_hpp *hpp, - struct hist_entry *he) -{ - double percent = 100.0 * he->period_guest_us / hpp->total_period; - const char *fmt = symbol_conf.field_sep ? "%.2f" : " %6.2f%% "; - - return scnprintf(hpp->buf, hpp->size, fmt, percent); -} - -static int hpp__header_samples(struct perf_hpp *hpp) -{ - const char *fmt = symbol_conf.field_sep ? "%s" : "%11s"; - - return scnprintf(hpp->buf, hpp->size, fmt, "Samples"); -} - -static int hpp__width_samples(struct perf_hpp *hpp __maybe_unused) -{ - return 11; -} - -static int hpp__entry_samples(struct perf_hpp *hpp, struct hist_entry *he) -{ - const char *fmt = symbol_conf.field_sep ? "%" PRIu64 : "%11" PRIu64; - - return scnprintf(hpp->buf, hpp->size, fmt, he->nr_events); -} - -static int hpp__header_period(struct perf_hpp *hpp) -{ - const char *fmt = symbol_conf.field_sep ? "%s" : "%12s"; - - return scnprintf(hpp->buf, hpp->size, fmt, "Period"); -} - -static int hpp__width_period(struct perf_hpp *hpp __maybe_unused) -{ - return 12; -} - -static int hpp__entry_period(struct perf_hpp *hpp, struct hist_entry *he) -{ - const char *fmt = symbol_conf.field_sep ? "%" PRIu64 : "%12" PRIu64; - - return scnprintf(hpp->buf, hpp->size, fmt, he->period); -} - -static int hpp__header_delta(struct perf_hpp *hpp) -{ - const char *fmt = symbol_conf.field_sep ? "%s" : "%7s"; - - return scnprintf(hpp->buf, hpp->size, fmt, "Delta"); -} - -static int hpp__width_delta(struct perf_hpp *hpp __maybe_unused) -{ - return 7; -} - -static int hpp__entry_delta(struct perf_hpp *hpp, struct hist_entry *he) -{ - struct hists *pair_hists = hpp->ptr; - u64 old_total, new_total; - double old_percent = 0, new_percent = 0; - double diff; - const char *fmt = symbol_conf.field_sep ? "%s" : "%7.7s"; - char buf[32] = " "; - - old_total = pair_hists->stats.total_period; - if (old_total > 0 && he->pair) - old_percent = 100.0 * he->pair->period / old_total; - - new_total = hpp->total_period; - if (new_total > 0) - new_percent = 100.0 * he->period / new_total; - - diff = new_percent - old_percent; - if (fabs(diff) >= 0.01) - scnprintf(buf, sizeof(buf), "%+4.2F%%", diff); - - return scnprintf(hpp->buf, hpp->size, fmt, buf); -} - -static int hpp__header_displ(struct perf_hpp *hpp) -{ - return scnprintf(hpp->buf, hpp->size, "Displ."); -} - -static int hpp__width_displ(struct perf_hpp *hpp __maybe_unused) -{ - return 6; -} - -static int hpp__entry_displ(struct perf_hpp *hpp, - struct hist_entry *he __maybe_unused) -{ - const char *fmt = symbol_conf.field_sep ? "%s" : "%6.6s"; - char buf[32] = " "; - - if (hpp->displacement) - scnprintf(buf, sizeof(buf), "%+4ld", hpp->displacement); - - return scnprintf(hpp->buf, hpp->size, fmt, buf); -} - -#define HPP__COLOR_PRINT_FNS(_name) \ - .header = hpp__header_ ## _name, \ - .width = hpp__width_ ## _name, \ - .color = hpp__color_ ## _name, \ - .entry = hpp__entry_ ## _name - -#define HPP__PRINT_FNS(_name) \ - .header = hpp__header_ ## _name, \ - .width = hpp__width_ ## _name, \ - .entry = hpp__entry_ ## _name - -struct perf_hpp_fmt perf_hpp__format[] = { - { .cond = true, HPP__COLOR_PRINT_FNS(overhead) }, - { .cond = false, HPP__COLOR_PRINT_FNS(overhead_sys) }, - { .cond = false, HPP__COLOR_PRINT_FNS(overhead_us) }, - { .cond = false, HPP__COLOR_PRINT_FNS(overhead_guest_sys) }, - { .cond = false, HPP__COLOR_PRINT_FNS(overhead_guest_us) }, - { .cond = false, HPP__PRINT_FNS(samples) }, - { .cond = false, HPP__PRINT_FNS(period) }, - { .cond = false, HPP__PRINT_FNS(delta) }, - { .cond = false, HPP__PRINT_FNS(displ) } -}; - -#undef HPP__COLOR_PRINT_FNS -#undef HPP__PRINT_FNS - -void perf_hpp__init(bool need_pair, bool show_displacement) -{ - if (symbol_conf.show_cpu_utilization) { - perf_hpp__format[PERF_HPP__OVERHEAD_SYS].cond = true; - perf_hpp__format[PERF_HPP__OVERHEAD_US].cond = true; - - if (perf_guest) { - perf_hpp__format[PERF_HPP__OVERHEAD_GUEST_SYS].cond = true; - perf_hpp__format[PERF_HPP__OVERHEAD_GUEST_US].cond = true; - } - } - - if (symbol_conf.show_nr_samples) - perf_hpp__format[PERF_HPP__SAMPLES].cond = true; - - if (symbol_conf.show_total_period) - perf_hpp__format[PERF_HPP__PERIOD].cond = true; - - if (need_pair) { - perf_hpp__format[PERF_HPP__DELTA].cond = true; - - if (show_displacement) - perf_hpp__format[PERF_HPP__DISPL].cond = true; - } -} - -static inline void advance_hpp(struct perf_hpp *hpp, int inc) -{ - hpp->buf += inc; - hpp->size -= inc; -} - -int hist_entry__period_snprintf(struct perf_hpp *hpp, struct hist_entry *he, - bool color) -{ - const char *sep = symbol_conf.field_sep; - char *start = hpp->buf; - int i, ret; - - if (symbol_conf.exclude_other && !he->parent) - return 0; - - for (i = 0; i < PERF_HPP__MAX_INDEX; i++) { - if (!perf_hpp__format[i].cond) - continue; - - if (!sep || i > 0) { - ret = scnprintf(hpp->buf, hpp->size, "%s", sep ?: " "); - advance_hpp(hpp, ret); - } - - if (color && perf_hpp__format[i].color) - ret = perf_hpp__format[i].color(hpp, he); - else - ret = perf_hpp__format[i].entry(hpp, he); - - advance_hpp(hpp, ret); - } - - return hpp->buf - start; -} - -int hist_entry__sort_snprintf(struct hist_entry *he, char *s, size_t size, - struct hists *hists) -{ - const char *sep = symbol_conf.field_sep; - struct sort_entry *se; - int ret = 0; - - list_for_each_entry(se, &hist_entry__sort_list, list) { - if (se->elide) - continue; - - ret += scnprintf(s + ret, size - ret, "%s", sep ?: " "); - ret += se->se_snprintf(he, s + ret, size - ret, - hists__col_len(hists, se->se_width_idx)); - } - - return ret; -} - -/* - * See hists__fprintf to match the column widths - */ -unsigned int hists__sort_list_width(struct hists *hists) -{ - struct sort_entry *se; - int i, ret = 0; - - for (i = 0; i < PERF_HPP__MAX_INDEX; i++) { - if (!perf_hpp__format[i].cond) - continue; - if (i) - ret += 2; - - ret += perf_hpp__format[i].width(NULL); - } - - list_for_each_entry(se, &hist_entry__sort_list, list) - if (!se->elide) - ret += 2 + hists__col_len(hists, se->se_width_idx); - - if (verbose) /* Addr + origin */ - ret += 3 + BITS_PER_LONG / 4; - - return ret; -} diff --git a/trunk/tools/perf/ui/setup.c b/trunk/tools/perf/ui/setup.c index bd7d460f844c..791fb15ce350 100644 --- a/trunk/tools/perf/ui/setup.c +++ b/trunk/tools/perf/ui/setup.c @@ -1,10 +1,6 @@ -#include +#include "../cache.h" +#include "../debug.h" -#include "../util/cache.h" -#include "../util/debug.h" -#include "../util/hist.h" - -pthread_mutex_t ui__lock = PTHREAD_MUTEX_INITIALIZER; void setup_browser(bool fallback_to_pager) { @@ -29,8 +25,6 @@ void setup_browser(bool fallback_to_pager) use_browser = 0; if (fallback_to_pager) setup_pager(); - - perf_hpp__init(false, false); break; } } diff --git a/trunk/tools/perf/ui/stdio/hist.c b/trunk/tools/perf/ui/stdio/hist.c deleted file mode 100644 index 882461a42830..000000000000 --- a/trunk/tools/perf/ui/stdio/hist.c +++ /dev/null @@ -1,498 +0,0 @@ -#include - -#include "../../util/util.h" -#include "../../util/hist.h" -#include "../../util/sort.h" - - -static size_t callchain__fprintf_left_margin(FILE *fp, int left_margin) -{ - int i; - int ret = fprintf(fp, " "); - - for (i = 0; i < left_margin; i++) - ret += fprintf(fp, " "); - - return ret; -} - -static size_t ipchain__fprintf_graph_line(FILE *fp, int depth, int depth_mask, - int left_margin) -{ - int i; - size_t ret = callchain__fprintf_left_margin(fp, left_margin); - - for (i = 0; i < depth; i++) - if (depth_mask & (1 << i)) - ret += fprintf(fp, "| "); - else - ret += fprintf(fp, " "); - - ret += fprintf(fp, "\n"); - - return ret; -} - -static size_t ipchain__fprintf_graph(FILE *fp, struct callchain_list *chain, - int depth, int depth_mask, int period, - u64 total_samples, u64 hits, - int left_margin) -{ - int i; - size_t ret = 0; - - ret += callchain__fprintf_left_margin(fp, left_margin); - for (i = 0; i < depth; i++) { - if (depth_mask & (1 << i)) - ret += fprintf(fp, "|"); - else - ret += fprintf(fp, " "); - if (!period && i == depth - 1) { - double percent; - - percent = hits * 100.0 / total_samples; - ret += percent_color_fprintf(fp, "--%2.2f%%-- ", percent); - } else - ret += fprintf(fp, "%s", " "); - } - if (chain->ms.sym) - ret += fprintf(fp, "%s\n", chain->ms.sym->name); - else - ret += fprintf(fp, "0x%0" PRIx64 "\n", chain->ip); - - return ret; -} - -static struct symbol *rem_sq_bracket; -static struct callchain_list rem_hits; - -static void init_rem_hits(void) -{ - rem_sq_bracket = malloc(sizeof(*rem_sq_bracket) + 6); - if (!rem_sq_bracket) { - fprintf(stderr, "Not enough memory to display remaining hits\n"); - return; - } - - strcpy(rem_sq_bracket->name, "[...]"); - rem_hits.ms.sym = rem_sq_bracket; -} - -static size_t __callchain__fprintf_graph(FILE *fp, struct rb_root *root, - u64 total_samples, int depth, - int depth_mask, int left_margin) -{ - struct rb_node *node, *next; - struct callchain_node *child; - struct callchain_list *chain; - int new_depth_mask = depth_mask; - u64 remaining; - size_t ret = 0; - int i; - uint entries_printed = 0; - - remaining = total_samples; - - node = rb_first(root); - while (node) { - u64 new_total; - u64 cumul; - - child = rb_entry(node, struct callchain_node, rb_node); - cumul = callchain_cumul_hits(child); - remaining -= cumul; - - /* - * The depth mask manages the output of pipes that show - * the depth. We don't want to keep the pipes of the current - * level for the last child of this depth. - * Except if we have remaining filtered hits. They will - * supersede the last child - */ - next = rb_next(node); - if (!next && (callchain_param.mode != CHAIN_GRAPH_REL || !remaining)) - new_depth_mask &= ~(1 << (depth - 1)); - - /* - * But we keep the older depth mask for the line separator - * to keep the level link until we reach the last child - */ - ret += ipchain__fprintf_graph_line(fp, depth, depth_mask, - left_margin); - i = 0; - list_for_each_entry(chain, &child->val, list) { - ret += ipchain__fprintf_graph(fp, chain, depth, - new_depth_mask, i++, - total_samples, - cumul, - left_margin); - } - - if (callchain_param.mode == CHAIN_GRAPH_REL) - new_total = child->children_hit; - else - new_total = total_samples; - - ret += __callchain__fprintf_graph(fp, &child->rb_root, new_total, - depth + 1, - new_depth_mask | (1 << depth), - left_margin); - node = next; - if (++entries_printed == callchain_param.print_limit) - break; - } - - if (callchain_param.mode == CHAIN_GRAPH_REL && - remaining && remaining != total_samples) { - - if (!rem_sq_bracket) - return ret; - - new_depth_mask &= ~(1 << (depth - 1)); - ret += ipchain__fprintf_graph(fp, &rem_hits, depth, - new_depth_mask, 0, total_samples, - remaining, left_margin); - } - - return ret; -} - -static size_t callchain__fprintf_graph(FILE *fp, struct rb_root *root, - u64 total_samples, int left_margin) -{ - struct callchain_node *cnode; - struct callchain_list *chain; - u32 entries_printed = 0; - bool printed = false; - struct rb_node *node; - int i = 0; - int ret = 0; - - /* - * If have one single callchain root, don't bother printing - * its percentage (100 % in fractal mode and the same percentage - * than the hist in graph mode). This also avoid one level of column. - */ - node = rb_first(root); - if (node && !rb_next(node)) { - cnode = rb_entry(node, struct callchain_node, rb_node); - list_for_each_entry(chain, &cnode->val, list) { - /* - * If we sort by symbol, the first entry is the same than - * the symbol. No need to print it otherwise it appears as - * displayed twice. - */ - if (!i++ && sort__first_dimension == SORT_SYM) - continue; - if (!printed) { - ret += callchain__fprintf_left_margin(fp, left_margin); - ret += fprintf(fp, "|\n"); - ret += callchain__fprintf_left_margin(fp, left_margin); - ret += fprintf(fp, "---"); - left_margin += 3; - printed = true; - } else - ret += callchain__fprintf_left_margin(fp, left_margin); - - if (chain->ms.sym) - ret += fprintf(fp, " %s\n", chain->ms.sym->name); - else - ret += fprintf(fp, " %p\n", (void *)(long)chain->ip); - - if (++entries_printed == callchain_param.print_limit) - break; - } - root = &cnode->rb_root; - } - - ret += __callchain__fprintf_graph(fp, root, total_samples, - 1, 1, left_margin); - ret += fprintf(fp, "\n"); - - return ret; -} - -static size_t __callchain__fprintf_flat(FILE *fp, - struct callchain_node *self, - u64 total_samples) -{ - struct callchain_list *chain; - size_t ret = 0; - - if (!self) - return 0; - - ret += __callchain__fprintf_flat(fp, self->parent, total_samples); - - - list_for_each_entry(chain, &self->val, list) { - if (chain->ip >= PERF_CONTEXT_MAX) - continue; - if (chain->ms.sym) - ret += fprintf(fp, " %s\n", chain->ms.sym->name); - else - ret += fprintf(fp, " %p\n", - (void *)(long)chain->ip); - } - - return ret; -} - -static size_t callchain__fprintf_flat(FILE *fp, struct rb_root *self, - u64 total_samples) -{ - size_t ret = 0; - u32 entries_printed = 0; - struct rb_node *rb_node; - struct callchain_node *chain; - - rb_node = rb_first(self); - while (rb_node) { - double percent; - - chain = rb_entry(rb_node, struct callchain_node, rb_node); - percent = chain->hit * 100.0 / total_samples; - - ret = percent_color_fprintf(fp, " %6.2f%%\n", percent); - ret += __callchain__fprintf_flat(fp, chain, total_samples); - ret += fprintf(fp, "\n"); - if (++entries_printed == callchain_param.print_limit) - break; - - rb_node = rb_next(rb_node); - } - - return ret; -} - -static size_t hist_entry_callchain__fprintf(struct hist_entry *he, - u64 total_samples, int left_margin, - FILE *fp) -{ - switch (callchain_param.mode) { - case CHAIN_GRAPH_REL: - return callchain__fprintf_graph(fp, &he->sorted_chain, he->period, - left_margin); - break; - case CHAIN_GRAPH_ABS: - return callchain__fprintf_graph(fp, &he->sorted_chain, total_samples, - left_margin); - break; - case CHAIN_FLAT: - return callchain__fprintf_flat(fp, &he->sorted_chain, total_samples); - break; - case CHAIN_NONE: - break; - default: - pr_err("Bad callchain mode\n"); - } - - return 0; -} - -static size_t hist_entry__callchain_fprintf(struct hist_entry *he, - struct hists *hists, - u64 total_period, FILE *fp) -{ - int left_margin = 0; - - if (sort__first_dimension == SORT_COMM) { - struct sort_entry *se = list_first_entry(&hist_entry__sort_list, - typeof(*se), list); - left_margin = hists__col_len(hists, se->se_width_idx); - left_margin -= thread__comm_len(he->thread); - } - - return hist_entry_callchain__fprintf(he, total_period, left_margin, fp); -} - -static int hist_entry__fprintf(struct hist_entry *he, size_t size, - struct hists *hists, struct hists *pair_hists, - long displacement, u64 total_period, FILE *fp) -{ - char bf[512]; - int ret; - struct perf_hpp hpp = { - .buf = bf, - .size = size, - .total_period = total_period, - .displacement = displacement, - .ptr = pair_hists, - }; - bool color = !symbol_conf.field_sep; - - if (size == 0 || size > sizeof(bf)) - size = hpp.size = sizeof(bf); - - ret = hist_entry__period_snprintf(&hpp, he, color); - hist_entry__sort_snprintf(he, bf + ret, size - ret, hists); - - ret = fprintf(fp, "%s\n", bf); - - if (symbol_conf.use_callchain) - ret += hist_entry__callchain_fprintf(he, hists, - total_period, fp); - - return ret; -} - -size_t hists__fprintf(struct hists *hists, struct hists *pair, - bool show_displacement, bool show_header, int max_rows, - int max_cols, FILE *fp) -{ - struct sort_entry *se; - struct rb_node *nd; - size_t ret = 0; - u64 total_period; - unsigned long position = 1; - long displacement = 0; - unsigned int width; - const char *sep = symbol_conf.field_sep; - const char *col_width = symbol_conf.col_width_list_str; - int idx, nr_rows = 0; - char bf[64]; - struct perf_hpp dummy_hpp = { - .buf = bf, - .size = sizeof(bf), - .ptr = pair, - }; - - init_rem_hits(); - - if (!show_header) - goto print_entries; - - fprintf(fp, "# "); - for (idx = 0; idx < PERF_HPP__MAX_INDEX; idx++) { - if (!perf_hpp__format[idx].cond) - continue; - - if (idx) - fprintf(fp, "%s", sep ?: " "); - - perf_hpp__format[idx].header(&dummy_hpp); - fprintf(fp, "%s", bf); - } - - list_for_each_entry(se, &hist_entry__sort_list, list) { - if (se->elide) - continue; - if (sep) { - fprintf(fp, "%c%s", *sep, se->se_header); - continue; - } - width = strlen(se->se_header); - if (symbol_conf.col_width_list_str) { - if (col_width) { - hists__set_col_len(hists, se->se_width_idx, - atoi(col_width)); - col_width = strchr(col_width, ','); - if (col_width) - ++col_width; - } - } - if (!hists__new_col_len(hists, se->se_width_idx, width)) - width = hists__col_len(hists, se->se_width_idx); - fprintf(fp, " %*s", width, se->se_header); - } - - fprintf(fp, "\n"); - if (max_rows && ++nr_rows >= max_rows) - goto out; - - if (sep) - goto print_entries; - - fprintf(fp, "# "); - for (idx = 0; idx < PERF_HPP__MAX_INDEX; idx++) { - unsigned int i; - - if (!perf_hpp__format[idx].cond) - continue; - - if (idx) - fprintf(fp, "%s", sep ?: " "); - - width = perf_hpp__format[idx].width(&dummy_hpp); - for (i = 0; i < width; i++) - fprintf(fp, "."); - } - - list_for_each_entry(se, &hist_entry__sort_list, list) { - unsigned int i; - - if (se->elide) - continue; - - fprintf(fp, " "); - width = hists__col_len(hists, se->se_width_idx); - if (width == 0) - width = strlen(se->se_header); - for (i = 0; i < width; i++) - fprintf(fp, "."); - } - - fprintf(fp, "\n"); - if (max_rows && ++nr_rows >= max_rows) - goto out; - - fprintf(fp, "#\n"); - if (max_rows && ++nr_rows >= max_rows) - goto out; - -print_entries: - total_period = hists->stats.total_period; - - for (nd = rb_first(&hists->entries); nd; nd = rb_next(nd)) { - struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node); - - if (h->filtered) - continue; - - if (show_displacement) { - if (h->pair != NULL) - displacement = ((long)h->pair->position - - (long)position); - else - displacement = 0; - ++position; - } - ret += hist_entry__fprintf(h, max_cols, hists, pair, displacement, - total_period, fp); - - if (max_rows && ++nr_rows >= max_rows) - goto out; - - if (h->ms.map == NULL && verbose > 1) { - __map_groups__fprintf_maps(&h->thread->mg, - MAP__FUNCTION, verbose, fp); - fprintf(fp, "%.10s end\n", graph_dotted_line); - } - } -out: - free(rem_sq_bracket); - - return ret; -} - -size_t hists__fprintf_nr_events(struct hists *hists, FILE *fp) -{ - int i; - size_t ret = 0; - - for (i = 0; i < PERF_RECORD_HEADER_MAX; ++i) { - const char *name; - - if (hists->stats.nr_events[i] == 0) - continue; - - name = perf_event__name(i); - if (!strcmp(name, "UNKNOWN")) - continue; - - ret += fprintf(fp, "%16s events: %10d\n", name, - hists->stats.nr_events[i]); - } - - return ret; -} diff --git a/trunk/tools/perf/ui/tui/helpline.c b/trunk/tools/perf/ui/tui/helpline.c deleted file mode 100644 index 2884d2f41e33..000000000000 --- a/trunk/tools/perf/ui/tui/helpline.c +++ /dev/null @@ -1,57 +0,0 @@ -#include -#include -#include -#include - -#include "../../util/debug.h" -#include "../helpline.h" -#include "../ui.h" -#include "../libslang.h" - -static void tui_helpline__pop(void) -{ -} - -static void tui_helpline__push(const char *msg) -{ - const size_t sz = sizeof(ui_helpline__current); - - SLsmg_gotorc(SLtt_Screen_Rows - 1, 0); - SLsmg_set_color(0); - SLsmg_write_nstring((char *)msg, SLtt_Screen_Cols); - SLsmg_refresh(); - strncpy(ui_helpline__current, msg, sz)[sz - 1] = '\0'; -} - -struct ui_helpline tui_helpline_fns = { - .pop = tui_helpline__pop, - .push = tui_helpline__push, -}; - -void ui_helpline__init(void) -{ - helpline_fns = &tui_helpline_fns; - ui_helpline__puts(" "); -} - -char ui_helpline__last_msg[1024]; - -int ui_helpline__show_help(const char *format, va_list ap) -{ - int ret; - static int backlog; - - pthread_mutex_lock(&ui__lock); - ret = vscnprintf(ui_helpline__last_msg + backlog, - sizeof(ui_helpline__last_msg) - backlog, format, ap); - backlog += ret; - - if (ui_helpline__last_msg[backlog - 1] == '\n') { - ui_helpline__puts(ui_helpline__last_msg); - SLsmg_refresh(); - backlog = 0; - } - pthread_mutex_unlock(&ui__lock); - - return ret; -} diff --git a/trunk/tools/perf/ui/tui/setup.c b/trunk/tools/perf/ui/tui/setup.c index 60debb81537a..e813c1d17346 100644 --- a/trunk/tools/perf/ui/tui/setup.c +++ b/trunk/tools/perf/ui/tui/setup.c @@ -11,12 +11,12 @@ #include "../libslang.h" #include "../keysyms.h" +pthread_mutex_t ui__lock = PTHREAD_MUTEX_INITIALIZER; + static volatile int ui__need_resize; extern struct perf_error_ops perf_tui_eops; -extern void hist_browser__init_hpp(void); - void ui__refresh_dimensions(bool force) { if (force || ui__need_resize) { @@ -28,7 +28,7 @@ void ui__refresh_dimensions(bool force) } } -static void ui__sigwinch(int sig __maybe_unused) +static void ui__sigwinch(int sig __used) { ui__need_resize = 1; } @@ -88,7 +88,7 @@ int ui__getch(int delay_secs) return SLkp_getkey(); } -static void newt_suspend(void *d __maybe_unused) +static void newt_suspend(void *d __used) { newtSuspend(); raise(SIGTSTP); @@ -126,8 +126,6 @@ int ui__init(void) signal(SIGTERM, ui__signal); perf_error__register(&perf_tui_eops); - - hist_browser__init_hpp(); out: return err; } diff --git a/trunk/tools/perf/util/alias.c b/trunk/tools/perf/util/alias.c index e6d134773d0a..b8144e80bb1e 100644 --- a/trunk/tools/perf/util/alias.c +++ b/trunk/tools/perf/util/alias.c @@ -3,8 +3,7 @@ static const char *alias_key; static char *alias_val; -static int alias_lookup_cb(const char *k, const char *v, - void *cb __maybe_unused) +static int alias_lookup_cb(const char *k, const char *v, void *cb __used) { if (!prefixcmp(k, "alias.") && !strcmp(k+6, alias_key)) { if (!v) diff --git a/trunk/tools/perf/util/annotate.c b/trunk/tools/perf/util/annotate.c index f0a910371377..3a282c0057d2 100644 --- a/trunk/tools/perf/util/annotate.c +++ b/trunk/tools/perf/util/annotate.c @@ -17,7 +17,6 @@ #include const char *disassembler_style; -const char *objdump_path; static struct ins *ins__find(const char *name); static int disasm_line__parse(char *line, char **namep, char **rawp); @@ -313,8 +312,8 @@ static struct ins_ops dec_ops = { .scnprintf = dec__scnprintf, }; -static int nop__scnprintf(struct ins *ins __maybe_unused, char *bf, size_t size, - struct ins_operands *ops __maybe_unused) +static int nop__scnprintf(struct ins *ins __used, char *bf, size_t size, + struct ins_operands *ops __used) { return scnprintf(bf, size, "%-6.6s", "nop"); } @@ -416,7 +415,7 @@ static struct ins *ins__find(const char *name) return bsearch(name, instructions, nmemb, sizeof(struct ins), ins__cmp); } -int symbol__annotate_init(struct map *map __maybe_unused, struct symbol *sym) +int symbol__annotate_init(struct map *map __used, struct symbol *sym) { struct annotation *notes = symbol__annotation(sym); pthread_mutex_init(¬es->lock, NULL); @@ -821,10 +820,9 @@ int symbol__annotate(struct symbol *sym, struct map *map, size_t privsize) dso, dso->long_name, sym, sym->name); snprintf(command, sizeof(command), - "%s %s%s --start-address=0x%016" PRIx64 + "objdump %s%s --start-address=0x%016" PRIx64 " --stop-address=0x%016" PRIx64 " -d %s %s -C %s|grep -v %s|expand", - objdump_path ? objdump_path : "objdump", disassembler_style ? "-M " : "", disassembler_style ? disassembler_style : "", map__rip_2objdump(map, sym->start), @@ -984,8 +982,7 @@ int symbol__annotate_printf(struct symbol *sym, struct map *map, int evidx, int context) { struct dso *dso = map->dso; - char *filename; - const char *d_filename; + const char *filename = dso->long_name, *d_filename; struct annotation *notes = symbol__annotation(sym); struct disasm_line *pos, *queue = NULL; u64 start = map__rip_2objdump(map, sym->start); @@ -993,10 +990,6 @@ int symbol__annotate_printf(struct symbol *sym, struct map *map, int evidx, int more = 0; u64 len; - filename = strdup(dso->long_name); - if (!filename) - return -ENOMEM; - if (full_paths) d_filename = filename; else @@ -1047,8 +1040,6 @@ int symbol__annotate_printf(struct symbol *sym, struct map *map, int evidx, } } - free(filename); - return more; } diff --git a/trunk/tools/perf/util/annotate.h b/trunk/tools/perf/util/annotate.h index 9b5b21e7b032..78a5692dd718 100644 --- a/trunk/tools/perf/util/annotate.h +++ b/trunk/tools/perf/util/annotate.h @@ -7,7 +7,6 @@ #include "symbol.h" #include #include -#include struct ins; @@ -126,7 +125,7 @@ int symbol__alloc_hist(struct symbol *sym); void symbol__annotate_zero_histograms(struct symbol *sym); int symbol__annotate(struct symbol *sym, struct map *map, size_t privsize); -int symbol__annotate_init(struct map *map __maybe_unused, struct symbol *sym); +int symbol__annotate_init(struct map *map __used, struct symbol *sym); int symbol__annotate_printf(struct symbol *sym, struct map *map, int evidx, bool full_paths, int min_pcnt, int max_lines, int context); @@ -139,12 +138,11 @@ int symbol__tty_annotate(struct symbol *sym, struct map *map, int evidx, int max_lines); #ifdef NO_NEWT_SUPPORT -static inline int symbol__tui_annotate(struct symbol *sym __maybe_unused, - struct map *map __maybe_unused, - int evidx __maybe_unused, - void(*timer)(void *arg) __maybe_unused, - void *arg __maybe_unused, - int delay_secs __maybe_unused) +static inline int symbol__tui_annotate(struct symbol *sym __used, + struct map *map __used, + int evidx __used, + void(*timer)(void *arg) __used, + void *arg __used, int delay_secs __used) { return 0; } @@ -154,6 +152,5 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx, #endif extern const char *disassembler_style; -extern const char *objdump_path; #endif /* __PERF_ANNOTATE_H */ diff --git a/trunk/tools/perf/util/build-id.c b/trunk/tools/perf/util/build-id.c index 8e3a740ddbd4..fd9a5944b627 100644 --- a/trunk/tools/perf/util/build-id.c +++ b/trunk/tools/perf/util/build-id.c @@ -16,10 +16,10 @@ #include "session.h" #include "tool.h" -static int build_id__mark_dso_hit(struct perf_tool *tool __maybe_unused, +static int build_id__mark_dso_hit(struct perf_tool *tool __used, union perf_event *event, - struct perf_sample *sample __maybe_unused, - struct perf_evsel *evsel __maybe_unused, + struct perf_sample *sample __used, + struct perf_evsel *evsel __used, struct machine *machine) { struct addr_location al; @@ -41,10 +41,9 @@ static int build_id__mark_dso_hit(struct perf_tool *tool __maybe_unused, return 0; } -static int perf_event__exit_del_thread(struct perf_tool *tool __maybe_unused, +static int perf_event__exit_del_thread(struct perf_tool *tool __used, union perf_event *event, - struct perf_sample *sample - __maybe_unused, + struct perf_sample *sample __used, struct machine *machine) { struct thread *thread = machine__findnew_thread(machine, event->fork.tid); diff --git a/trunk/tools/perf/util/cache.h b/trunk/tools/perf/util/cache.h index ab1769426541..cff18c617d13 100644 --- a/trunk/tools/perf/util/cache.h +++ b/trunk/tools/perf/util/cache.h @@ -39,7 +39,7 @@ static inline void setup_browser(bool fallback_to_pager) if (fallback_to_pager) setup_pager(); } -static inline void exit_browser(bool wait_for_ok __maybe_unused) {} +static inline void exit_browser(bool wait_for_ok __used) {} #else void setup_browser(bool fallback_to_pager); void exit_browser(bool wait_for_ok); @@ -49,7 +49,7 @@ static inline int ui__init(void) { return -1; } -static inline void ui__exit(bool wait_for_ok __maybe_unused) {} +static inline void ui__exit(bool wait_for_ok __used) {} #else int ui__init(void); void ui__exit(bool wait_for_ok); @@ -60,7 +60,7 @@ static inline int perf_gtk__init(void) { return -1; } -static inline void perf_gtk__exit(bool wait_for_ok __maybe_unused) {} +static inline void perf_gtk__exit(bool wait_for_ok __used) {} #else int perf_gtk__init(void); void perf_gtk__exit(bool wait_for_ok); diff --git a/trunk/tools/perf/util/callchain.c b/trunk/tools/perf/util/callchain.c index d3b3f5d82137..3a6bff47614f 100644 --- a/trunk/tools/perf/util/callchain.c +++ b/trunk/tools/perf/util/callchain.c @@ -93,7 +93,7 @@ __sort_chain_flat(struct rb_root *rb_root, struct callchain_node *node, */ static void sort_chain_flat(struct rb_root *rb_root, struct callchain_root *root, - u64 min_hit, struct callchain_param *param __maybe_unused) + u64 min_hit, struct callchain_param *param __used) { __sort_chain_flat(rb_root, &root->node, min_hit); } @@ -115,7 +115,7 @@ static void __sort_chain_graph_abs(struct callchain_node *node, static void sort_chain_graph_abs(struct rb_root *rb_root, struct callchain_root *chain_root, - u64 min_hit, struct callchain_param *param __maybe_unused) + u64 min_hit, struct callchain_param *param __used) { __sort_chain_graph_abs(&chain_root->node, min_hit); rb_root->rb_node = chain_root->node.rb_root.rb_node; @@ -140,7 +140,7 @@ static void __sort_chain_graph_rel(struct callchain_node *node, static void sort_chain_graph_rel(struct rb_root *rb_root, struct callchain_root *chain_root, - u64 min_hit __maybe_unused, struct callchain_param *param) + u64 min_hit __used, struct callchain_param *param) { __sort_chain_graph_rel(&chain_root->node, param->min_percent / 100.0); rb_root->rb_node = chain_root->node.rb_root.rb_node; diff --git a/trunk/tools/perf/util/callchain.h b/trunk/tools/perf/util/callchain.h index eb340571e7d6..3bdb407f9cd9 100644 --- a/trunk/tools/perf/util/callchain.h +++ b/trunk/tools/perf/util/callchain.h @@ -58,7 +58,7 @@ struct callchain_list { /* * A callchain cursor is a single linked list that * let one feed a callchain progressively. - * It keeps persistent allocated entries to minimize + * It keeps persitent allocated entries to minimize * allocations. */ struct callchain_cursor_node { diff --git a/trunk/tools/perf/util/cgroup.c b/trunk/tools/perf/util/cgroup.c index 96bbda1ddb83..dbe2f16b1a1a 100644 --- a/trunk/tools/perf/util/cgroup.c +++ b/trunk/tools/perf/util/cgroup.c @@ -138,8 +138,8 @@ void close_cgroup(struct cgroup_sel *cgrp) } } -int parse_cgroups(const struct option *opt __maybe_unused, const char *str, - int unset __maybe_unused) +int parse_cgroups(const struct option *opt __used, const char *str, + int unset __used) { struct perf_evlist *evlist = *(struct perf_evlist **)opt->value; const char *p, *e, *eos = str + strlen(str); diff --git a/trunk/tools/perf/util/config.c b/trunk/tools/perf/util/config.c index 3e0fdd369ccb..6faa3a18bfbd 100644 --- a/trunk/tools/perf/util/config.c +++ b/trunk/tools/perf/util/config.c @@ -342,15 +342,13 @@ const char *perf_config_dirname(const char *name, const char *value) return value; } -static int perf_default_core_config(const char *var __maybe_unused, - const char *value __maybe_unused) +static int perf_default_core_config(const char *var __used, const char *value __used) { /* Add other config variables here. */ return 0; } -int perf_default_config(const char *var, const char *value, - void *dummy __maybe_unused) +int perf_default_config(const char *var, const char *value, void *dummy __used) { if (!prefixcmp(var, "core.")) return perf_default_core_config(var, value); diff --git a/trunk/tools/perf/util/cpumap.c b/trunk/tools/perf/util/cpumap.c index 2b32ffa9ebdb..adc72f09914d 100644 --- a/trunk/tools/perf/util/cpumap.c +++ b/trunk/tools/perf/util/cpumap.c @@ -38,19 +38,24 @@ static struct cpu_map *cpu_map__trim_new(int nr_cpus, int *tmp_cpus) return cpus; } -struct cpu_map *cpu_map__read(FILE *file) +static struct cpu_map *cpu_map__read_all_cpu_map(void) { struct cpu_map *cpus = NULL; + FILE *onlnf; int nr_cpus = 0; int *tmp_cpus = NULL, *tmp; int max_entries = 0; int n, cpu, prev; char sep; + onlnf = fopen("/sys/devices/system/cpu/online", "r"); + if (!onlnf) + return cpu_map__default_new(); + sep = 0; prev = -1; for (;;) { - n = fscanf(file, "%u%c", &cpu, &sep); + n = fscanf(onlnf, "%u%c", &cpu, &sep); if (n <= 0) break; if (prev >= 0) { @@ -90,19 +95,6 @@ struct cpu_map *cpu_map__read(FILE *file) cpus = cpu_map__default_new(); out_free_tmp: free(tmp_cpus); - return cpus; -} - -static struct cpu_map *cpu_map__read_all_cpu_map(void) -{ - struct cpu_map *cpus = NULL; - FILE *onlnf; - - onlnf = fopen("/sys/devices/system/cpu/online", "r"); - if (!onlnf) - return cpu_map__default_new(); - - cpus = cpu_map__read(onlnf); fclose(onlnf); return cpus; } diff --git a/trunk/tools/perf/util/cpumap.h b/trunk/tools/perf/util/cpumap.h index 2f68a3b8c285..c41518573c6a 100644 --- a/trunk/tools/perf/util/cpumap.h +++ b/trunk/tools/perf/util/cpumap.h @@ -2,7 +2,6 @@ #define __PERF_CPUMAP_H #include -#include struct cpu_map { int nr; @@ -12,17 +11,7 @@ struct cpu_map { struct cpu_map *cpu_map__new(const char *cpu_list); struct cpu_map *cpu_map__dummy_new(void); void cpu_map__delete(struct cpu_map *map); -struct cpu_map *cpu_map__read(FILE *file); -size_t cpu_map__fprintf(struct cpu_map *map, FILE *fp); - -static inline int cpu_map__nr(const struct cpu_map *map) -{ - return map ? map->nr : 1; -} -static inline bool cpu_map__all(const struct cpu_map *map) -{ - return map ? map->map[0] == -1 : true; -} +size_t cpu_map__fprintf(struct cpu_map *map, FILE *fp); #endif /* __PERF_CPUMAP_H */ diff --git a/trunk/tools/perf/util/debug.c b/trunk/tools/perf/util/debug.c index 66eb3828ceb5..4dfe0bb3c322 100644 --- a/trunk/tools/perf/util/debug.c +++ b/trunk/tools/perf/util/debug.c @@ -23,10 +23,8 @@ int eprintf(int level, const char *fmt, ...) if (verbose >= level) { va_start(args, fmt); - if (use_browser == 1) + if (use_browser > 0) ret = ui_helpline__show_help(fmt, args); - else if (use_browser == 2) - ret = perf_gtk__show_helpline(fmt, args); else ret = vfprintf(stderr, fmt, args); va_end(args); diff --git a/trunk/tools/perf/util/debug.h b/trunk/tools/perf/util/debug.h index bb2e7d1007ab..015c91dbc096 100644 --- a/trunk/tools/perf/util/debug.h +++ b/trunk/tools/perf/util/debug.h @@ -4,7 +4,6 @@ #include #include "event.h" -#include "../ui/helpline.h" extern int verbose; extern bool quiet, dump_trace; @@ -16,26 +15,32 @@ struct ui_progress; struct perf_error_ops; #if defined(NO_NEWT_SUPPORT) && defined(NO_GTK2_SUPPORT) -static inline void ui_progress__update(u64 curr __maybe_unused, - u64 total __maybe_unused, - const char *title __maybe_unused) {} +static inline int ui_helpline__show_help(const char *format __used, va_list ap __used) +{ + return 0; +} + +static inline void ui_progress__update(u64 curr __used, u64 total __used, + const char *title __used) {} #define ui__error(format, arg...) ui__warning(format, ##arg) static inline int -perf_error__register(struct perf_error_ops *eops __maybe_unused) +perf_error__register(struct perf_error_ops *eops __used) { return 0; } static inline int -perf_error__unregister(struct perf_error_ops *eops __maybe_unused) +perf_error__unregister(struct perf_error_ops *eops __used) { return 0; } #else /* NO_NEWT_SUPPORT && NO_GTK2_SUPPORT */ +extern char ui_helpline__last_msg[]; +int ui_helpline__show_help(const char *format, va_list ap); #include "../ui/progress.h" int ui__error(const char *format, ...) __attribute__((format(printf, 1, 2))); #include "../ui/util.h" diff --git a/trunk/tools/perf/util/dso-test-data.c b/trunk/tools/perf/util/dso-test-data.c index c6caedeb1d6b..541cdc72c7df 100644 --- a/trunk/tools/perf/util/dso-test-data.c +++ b/trunk/tools/perf/util/dso-test-data.c @@ -23,7 +23,7 @@ static char *test_file(int size) int fd, i; unsigned char *buf; - fd = mkstemp(templ); + fd = mkostemp(templ, O_CREAT|O_WRONLY|O_TRUNC); buf = malloc(size); if (!buf) { diff --git a/trunk/tools/perf/util/dwarf-aux.c b/trunk/tools/perf/util/dwarf-aux.c index 3e5f5430a28a..ee51e9b4dc09 100644 --- a/trunk/tools/perf/util/dwarf-aux.c +++ b/trunk/tools/perf/util/dwarf-aux.c @@ -804,8 +804,6 @@ int die_get_typename(Dwarf_Die *vr_die, char *buf, int len) tmp = "union "; else if (tag == DW_TAG_structure_type) tmp = "struct "; - else if (tag == DW_TAG_enumeration_type) - tmp = "enum "; /* Write a base name */ ret = snprintf(buf, len, "%s%s", tmp, dwarf_diename(&type)); return (ret >= len) ? -E2BIG : ret; diff --git a/trunk/tools/perf/util/event.c b/trunk/tools/perf/util/event.c index 6715b1938725..2a6f33cd888c 100644 --- a/trunk/tools/perf/util/event.c +++ b/trunk/tools/perf/util/event.c @@ -112,7 +112,7 @@ static pid_t perf_event__synthesize_comm(struct perf_tool *tool, event->comm.header.type = PERF_RECORD_COMM; size = strlen(event->comm.comm) + 1; - size = PERF_ALIGN(size, sizeof(u64)); + size = ALIGN(size, sizeof(u64)); memset(event->comm.comm + size, 0, machine->id_hdr_size); event->comm.header.size = (sizeof(event->comm) - (sizeof(event->comm.comm) - size) + @@ -120,9 +120,7 @@ static pid_t perf_event__synthesize_comm(struct perf_tool *tool, if (!full) { event->comm.tid = pid; - if (process(tool, event, &synth_sample, machine) != 0) - return -1; - + process(tool, event, &synth_sample, machine); goto out; } @@ -145,7 +143,7 @@ static pid_t perf_event__synthesize_comm(struct perf_tool *tool, sizeof(event->comm.comm)); size = strlen(event->comm.comm) + 1; - size = PERF_ALIGN(size, sizeof(u64)); + size = ALIGN(size, sizeof(u64)); memset(event->comm.comm + size, 0, machine->id_hdr_size); event->comm.header.size = (sizeof(event->comm) - (sizeof(event->comm.comm) - size) + @@ -153,10 +151,7 @@ static pid_t perf_event__synthesize_comm(struct perf_tool *tool, event->comm.tid = pid; - if (process(tool, event, &synth_sample, machine) != 0) { - tgid = -1; - break; - } + process(tool, event, &synth_sample, machine); } closedir(tasks); @@ -172,7 +167,6 @@ static int perf_event__synthesize_mmap_events(struct perf_tool *tool, { char filename[PATH_MAX]; FILE *fp; - int rc = 0; snprintf(filename, sizeof(filename), "/proc/%d/maps", pid); @@ -228,7 +222,7 @@ static int perf_event__synthesize_mmap_events(struct perf_tool *tool, size = strlen(execname); execname[size - 1] = '\0'; /* Remove \n */ memcpy(event->mmap.filename, execname, size); - size = PERF_ALIGN(size, sizeof(u64)); + size = ALIGN(size, sizeof(u64)); event->mmap.len -= event->mmap.start; event->mmap.header.size = (sizeof(event->mmap) - (sizeof(event->mmap.filename) - size)); @@ -237,22 +231,18 @@ static int perf_event__synthesize_mmap_events(struct perf_tool *tool, event->mmap.pid = tgid; event->mmap.tid = pid; - if (process(tool, event, &synth_sample, machine) != 0) { - rc = -1; - break; - } + process(tool, event, &synth_sample, machine); } } fclose(fp); - return rc; + return 0; } int perf_event__synthesize_modules(struct perf_tool *tool, perf_event__handler_t process, struct machine *machine) { - int rc = 0; struct rb_node *nd; struct map_groups *kmaps = &machine->kmaps; union perf_event *event = zalloc((sizeof(event->mmap) + @@ -282,7 +272,7 @@ int perf_event__synthesize_modules(struct perf_tool *tool, if (pos->dso->kernel) continue; - size = PERF_ALIGN(pos->dso->long_name_len + 1, sizeof(u64)); + size = ALIGN(pos->dso->long_name_len + 1, sizeof(u64)); event->mmap.header.type = PERF_RECORD_MMAP; event->mmap.header.size = (sizeof(event->mmap) - (sizeof(event->mmap.filename) - size)); @@ -294,14 +284,11 @@ int perf_event__synthesize_modules(struct perf_tool *tool, memcpy(event->mmap.filename, pos->dso->long_name, pos->dso->long_name_len + 1); - if (process(tool, event, &synth_sample, machine) != 0) { - rc = -1; - break; - } + process(tool, event, &synth_sample, machine); } free(event); - return rc; + return 0; } static int __event__synthesize_thread(union perf_event *comm_event, @@ -405,16 +392,12 @@ int perf_event__synthesize_threads(struct perf_tool *tool, if (*end) /* only interested in proper numerical dirents */ continue; - if (__event__synthesize_thread(comm_event, mmap_event, pid, 1, - process, tool, machine) != 0) { - err = -1; - goto out_closedir; - } + __event__synthesize_thread(comm_event, mmap_event, pid, 1, + process, tool, machine); } - err = 0; -out_closedir: closedir(proc); + err = 0; out_free_mmap: free(mmap_event); out_free_comm: @@ -429,7 +412,7 @@ struct process_symbol_args { }; static int find_symbol_cb(void *arg, const char *name, char type, - u64 start) + u64 start, u64 end __used) { struct process_symbol_args *args = arg; @@ -494,7 +477,7 @@ int perf_event__synthesize_kernel_mmap(struct perf_tool *tool, map = machine->vmlinux_maps[MAP__FUNCTION]; size = snprintf(event->mmap.filename, sizeof(event->mmap.filename), "%s%s", mmap_name, symbol_name) + 1; - size = PERF_ALIGN(size, sizeof(u64)); + size = ALIGN(size, sizeof(u64)); event->mmap.header.type = PERF_RECORD_MMAP; event->mmap.header.size = (sizeof(event->mmap) - (sizeof(event->mmap.filename) - size) + machine->id_hdr_size); @@ -514,9 +497,9 @@ size_t perf_event__fprintf_comm(union perf_event *event, FILE *fp) return fprintf(fp, ": %s:%d\n", event->comm.comm, event->comm.tid); } -int perf_event__process_comm(struct perf_tool *tool __maybe_unused, +int perf_event__process_comm(struct perf_tool *tool __used, union perf_event *event, - struct perf_sample *sample __maybe_unused, + struct perf_sample *sample __used, struct machine *machine) { struct thread *thread = machine__findnew_thread(machine, event->comm.tid); @@ -532,10 +515,10 @@ int perf_event__process_comm(struct perf_tool *tool __maybe_unused, return 0; } -int perf_event__process_lost(struct perf_tool *tool __maybe_unused, +int perf_event__process_lost(struct perf_tool *tool __used, union perf_event *event, - struct perf_sample *sample __maybe_unused, - struct machine *machine __maybe_unused) + struct perf_sample *sample __used, + struct machine *machine __used) { dump_printf(": id:%" PRIu64 ": lost:%" PRIu64 "\n", event->lost.id, event->lost.lost); @@ -555,8 +538,7 @@ static void perf_event__set_kernel_mmap_len(union perf_event *event, maps[MAP__FUNCTION]->end = ~0ULL; } -static int perf_event__process_kernel_mmap(struct perf_tool *tool - __maybe_unused, +static int perf_event__process_kernel_mmap(struct perf_tool *tool __used, union perf_event *event, struct machine *machine) { @@ -658,7 +640,7 @@ size_t perf_event__fprintf_mmap(union perf_event *event, FILE *fp) int perf_event__process_mmap(struct perf_tool *tool, union perf_event *event, - struct perf_sample *sample __maybe_unused, + struct perf_sample *sample __used, struct machine *machine) { struct thread *thread; @@ -702,9 +684,9 @@ size_t perf_event__fprintf_task(union perf_event *event, FILE *fp) event->fork.ppid, event->fork.ptid); } -int perf_event__process_task(struct perf_tool *tool __maybe_unused, +int perf_event__process_task(struct perf_tool *tool __used, union perf_event *event, - struct perf_sample *sample __maybe_unused, + struct perf_sample *sample __used, struct machine *machine) { struct thread *thread = machine__findnew_thread(machine, event->fork.tid); @@ -904,9 +886,8 @@ int perf_event__preprocess_sample(const union perf_event *event, al->sym = map__find_symbol(al->map, al->addr, filter); } - if (symbol_conf.sym_list && - (!al->sym || !strlist__has_entry(symbol_conf.sym_list, - al->sym->name))) + if (symbol_conf.sym_list && al->sym && + !strlist__has_entry(symbol_conf.sym_list, al->sym->name)) goto out_filtered; return 0; diff --git a/trunk/tools/perf/util/event.h b/trunk/tools/perf/util/event.h index 21b99e741a87..1b197280c621 100644 --- a/trunk/tools/perf/util/event.h +++ b/trunk/tools/perf/util/event.h @@ -69,16 +69,6 @@ struct sample_event { u64 array[]; }; -struct regs_dump { - u64 *regs; -}; - -struct stack_dump { - u16 offset; - u64 size; - char *data; -}; - struct perf_sample { u64 ip; u32 pid, tid; @@ -92,8 +82,6 @@ struct perf_sample { void *raw_data; struct ip_callchain *callchain; struct branch_stack *branch_stack; - struct regs_dump user_regs; - struct stack_dump user_stack; }; #define BUILD_ID_SIZE 20 @@ -101,7 +89,7 @@ struct perf_sample { struct build_id_event { struct perf_event_header header; pid_t pid; - u8 build_id[PERF_ALIGN(BUILD_ID_SIZE, sizeof(u64))]; + u8 build_id[ALIGN(BUILD_ID_SIZE, sizeof(u64))]; char filename[]; }; @@ -209,6 +197,9 @@ int perf_event__preprocess_sample(const union perf_event *self, const char *perf_event__name(unsigned int id); +int perf_event__parse_sample(const union perf_event *event, u64 type, + int sample_size, bool sample_id_all, + struct perf_sample *sample, bool swapped); int perf_event__synthesize_sample(union perf_event *event, u64 type, const struct perf_sample *sample, bool swapped); diff --git a/trunk/tools/perf/util/evlist.c b/trunk/tools/perf/util/evlist.c index ae89686102f4..3edfd3483816 100644 --- a/trunk/tools/perf/util/evlist.c +++ b/trunk/tools/perf/util/evlist.c @@ -57,7 +57,7 @@ void perf_evlist__config_attrs(struct perf_evlist *evlist, if (evlist->cpus->map[0] < 0) opts->no_inherit = true; - first = perf_evlist__first(evlist); + first = list_entry(evlist->entries.next, struct perf_evsel, node); list_for_each_entry(evsel, &evlist->entries, node) { perf_evsel__config(evsel, opts, first); @@ -108,25 +108,6 @@ void perf_evlist__splice_list_tail(struct perf_evlist *evlist, evlist->nr_entries += nr_entries; } -void __perf_evlist__set_leader(struct list_head *list) -{ - struct perf_evsel *evsel, *leader; - - leader = list_entry(list->next, struct perf_evsel, node); - leader->leader = NULL; - - list_for_each_entry(evsel, list, node) { - if (evsel != leader) - evsel->leader = leader; - } -} - -void perf_evlist__set_leader(struct perf_evlist *evlist) -{ - if (evlist->nr_entries) - __perf_evlist__set_leader(&evlist->entries); -} - int perf_evlist__add_default(struct perf_evlist *evlist) { struct perf_event_attr attr = { @@ -304,7 +285,7 @@ void perf_evlist__enable(struct perf_evlist *evlist) int cpu, thread; struct perf_evsel *pos; - for (cpu = 0; cpu < cpu_map__nr(evlist->cpus); cpu++) { + for (cpu = 0; cpu < evlist->cpus->nr; cpu++) { list_for_each_entry(pos, &evlist->entries, node) { for (thread = 0; thread < evlist->threads->nr; thread++) ioctl(FD(pos, cpu, thread), @@ -315,7 +296,7 @@ void perf_evlist__enable(struct perf_evlist *evlist) static int perf_evlist__alloc_pollfd(struct perf_evlist *evlist) { - int nfds = cpu_map__nr(evlist->cpus) * evlist->threads->nr * evlist->nr_entries; + int nfds = evlist->cpus->nr * evlist->threads->nr * evlist->nr_entries; evlist->pollfd = malloc(sizeof(struct pollfd) * nfds); return evlist->pollfd != NULL ? 0 : -ENOMEM; } @@ -376,7 +357,7 @@ struct perf_evsel *perf_evlist__id2evsel(struct perf_evlist *evlist, u64 id) int hash; if (evlist->nr_entries == 1) - return perf_evlist__first(evlist); + return list_entry(evlist->entries.next, struct perf_evsel, node); hash = hash_64(id, PERF_EVLIST__HLIST_BITS); head = &evlist->heads[hash]; @@ -386,7 +367,7 @@ struct perf_evsel *perf_evlist__id2evsel(struct perf_evlist *evlist, u64 id) return sid->evsel; if (!perf_evlist__sample_id_all(evlist)) - return perf_evlist__first(evlist); + return list_entry(evlist->entries.next, struct perf_evsel, node); return NULL; } @@ -475,8 +456,8 @@ void perf_evlist__munmap(struct perf_evlist *evlist) static int perf_evlist__alloc_mmap(struct perf_evlist *evlist) { - evlist->nr_mmaps = cpu_map__nr(evlist->cpus); - if (cpu_map__all(evlist->cpus)) + evlist->nr_mmaps = evlist->cpus->nr; + if (evlist->cpus->map[0] == -1) evlist->nr_mmaps = evlist->threads->nr; evlist->mmap = zalloc(evlist->nr_mmaps * sizeof(struct perf_mmap)); return evlist->mmap != NULL ? 0 : -ENOMEM; @@ -622,11 +603,11 @@ int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages, list_for_each_entry(evsel, &evlist->entries, node) { if ((evsel->attr.read_format & PERF_FORMAT_ID) && evsel->sample_id == NULL && - perf_evsel__alloc_id(evsel, cpu_map__nr(cpus), threads->nr) < 0) + perf_evsel__alloc_id(evsel, cpus->nr, threads->nr) < 0) return -ENOMEM; } - if (cpu_map__all(cpus)) + if (evlist->cpus->map[0] == -1) return perf_evlist__mmap_per_thread(evlist, prot, mask); return perf_evlist__mmap_per_cpu(evlist, prot, mask); @@ -666,44 +647,39 @@ void perf_evlist__delete_maps(struct perf_evlist *evlist) evlist->threads = NULL; } -int perf_evlist__apply_filters(struct perf_evlist *evlist) +int perf_evlist__set_filters(struct perf_evlist *evlist) { + const struct thread_map *threads = evlist->threads; + const struct cpu_map *cpus = evlist->cpus; struct perf_evsel *evsel; - int err = 0; - const int ncpus = cpu_map__nr(evlist->cpus), - nthreads = evlist->threads->nr; + char *filter; + int thread; + int cpu; + int err; + int fd; list_for_each_entry(evsel, &evlist->entries, node) { - if (evsel->filter == NULL) + filter = evsel->filter; + if (!filter) continue; - - err = perf_evsel__set_filter(evsel, ncpus, nthreads, evsel->filter); - if (err) - break; + for (cpu = 0; cpu < cpus->nr; cpu++) { + for (thread = 0; thread < threads->nr; thread++) { + fd = FD(evsel, cpu, thread); + err = ioctl(fd, PERF_EVENT_IOC_SET_FILTER, filter); + if (err) + return err; + } + } } - return err; + return 0; } -int perf_evlist__set_filter(struct perf_evlist *evlist, const char *filter) +bool perf_evlist__valid_sample_type(const struct perf_evlist *evlist) { - struct perf_evsel *evsel; - int err = 0; - const int ncpus = cpu_map__nr(evlist->cpus), - nthreads = evlist->threads->nr; + struct perf_evsel *pos, *first; - list_for_each_entry(evsel, &evlist->entries, node) { - err = perf_evsel__set_filter(evsel, ncpus, nthreads, filter); - if (err) - break; - } - - return err; -} - -bool perf_evlist__valid_sample_type(struct perf_evlist *evlist) -{ - struct perf_evsel *first = perf_evlist__first(evlist), *pos = first; + pos = first = list_entry(evlist->entries.next, struct perf_evsel, node); list_for_each_entry_continue(pos, &evlist->entries, node) { if (first->attr.sample_type != pos->attr.sample_type) @@ -713,19 +689,23 @@ bool perf_evlist__valid_sample_type(struct perf_evlist *evlist) return true; } -u64 perf_evlist__sample_type(struct perf_evlist *evlist) +u64 perf_evlist__sample_type(const struct perf_evlist *evlist) { - struct perf_evsel *first = perf_evlist__first(evlist); + struct perf_evsel *first; + + first = list_entry(evlist->entries.next, struct perf_evsel, node); return first->attr.sample_type; } -u16 perf_evlist__id_hdr_size(struct perf_evlist *evlist) +u16 perf_evlist__id_hdr_size(const struct perf_evlist *evlist) { - struct perf_evsel *first = perf_evlist__first(evlist); + struct perf_evsel *first; struct perf_sample *data; u64 sample_type; u16 size = 0; + first = list_entry(evlist->entries.next, struct perf_evsel, node); + if (!first->attr.sample_id_all) goto out; @@ -749,9 +729,11 @@ u16 perf_evlist__id_hdr_size(struct perf_evlist *evlist) return size; } -bool perf_evlist__valid_sample_id_all(struct perf_evlist *evlist) +bool perf_evlist__valid_sample_id_all(const struct perf_evlist *evlist) { - struct perf_evsel *first = perf_evlist__first(evlist), *pos = first; + struct perf_evsel *pos, *first; + + pos = first = list_entry(evlist->entries.next, struct perf_evsel, node); list_for_each_entry_continue(pos, &evlist->entries, node) { if (first->attr.sample_id_all != pos->attr.sample_id_all) @@ -761,9 +743,11 @@ bool perf_evlist__valid_sample_id_all(struct perf_evlist *evlist) return true; } -bool perf_evlist__sample_id_all(struct perf_evlist *evlist) +bool perf_evlist__sample_id_all(const struct perf_evlist *evlist) { - struct perf_evsel *first = perf_evlist__first(evlist); + struct perf_evsel *first; + + first = list_entry(evlist->entries.next, struct perf_evsel, node); return first->attr.sample_id_all; } @@ -773,13 +757,21 @@ void perf_evlist__set_selected(struct perf_evlist *evlist, evlist->selected = evsel; } -int perf_evlist__open(struct perf_evlist *evlist) +int perf_evlist__open(struct perf_evlist *evlist, bool group) { - struct perf_evsel *evsel; + struct perf_evsel *evsel, *first; int err, ncpus, nthreads; + first = list_entry(evlist->entries.next, struct perf_evsel, node); + list_for_each_entry(evsel, &evlist->entries, node) { - err = perf_evsel__open(evsel, evlist->cpus, evlist->threads); + struct xyarray *group_fd = NULL; + + if (group && evsel != first) + group_fd = first->fd; + + err = perf_evsel__open(evsel, evlist->cpus, evlist->threads, + group, group_fd); if (err < 0) goto out_err; } @@ -889,23 +881,3 @@ int perf_evlist__start_workload(struct perf_evlist *evlist) return 0; } - -int perf_evlist__parse_sample(struct perf_evlist *evlist, union perf_event *event, - struct perf_sample *sample) -{ - struct perf_evsel *evsel = perf_evlist__first(evlist); - return perf_evsel__parse_sample(evsel, event, sample); -} - -size_t perf_evlist__fprintf(struct perf_evlist *evlist, FILE *fp) -{ - struct perf_evsel *evsel; - size_t printed = 0; - - list_for_each_entry(evsel, &evlist->entries, node) { - printed += fprintf(fp, "%s%s", evsel->idx ? ", " : "", - perf_evsel__name(evsel)); - } - - return printed + fprintf(fp, "\n");; -} diff --git a/trunk/tools/perf/util/evlist.h b/trunk/tools/perf/util/evlist.h index 3f1fb66be022..40d4d3cdced0 100644 --- a/trunk/tools/perf/util/evlist.h +++ b/trunk/tools/perf/util/evlist.h @@ -5,7 +5,6 @@ #include #include "../perf.h" #include "event.h" -#include "evsel.h" #include "util.h" #include @@ -42,6 +41,8 @@ struct perf_evsel_str_handler { void *handler; }; +struct perf_evsel; + struct perf_evlist *perf_evlist__new(struct cpu_map *cpus, struct thread_map *threads); void perf_evlist__init(struct perf_evlist *evlist, struct cpu_map *cpus, @@ -72,8 +73,6 @@ int perf_evlist__set_tracepoints_handlers(struct perf_evlist *evlist, #define perf_evlist__set_tracepoints_handlers_array(evlist, array) \ perf_evlist__set_tracepoints_handlers(evlist, array, ARRAY_SIZE(array)) -int perf_evlist__set_filter(struct perf_evlist *evlist, const char *filter); - struct perf_evsel * perf_evlist__find_tracepoint_by_id(struct perf_evlist *evlist, int id); @@ -86,7 +85,7 @@ struct perf_evsel *perf_evlist__id2evsel(struct perf_evlist *evlist, u64 id); union perf_event *perf_evlist__mmap_read(struct perf_evlist *self, int idx); -int perf_evlist__open(struct perf_evlist *evlist); +int perf_evlist__open(struct perf_evlist *evlist, bool group); void perf_evlist__config_attrs(struct perf_evlist *evlist, struct perf_record_opts *opts); @@ -117,34 +116,17 @@ static inline void perf_evlist__set_maps(struct perf_evlist *evlist, int perf_evlist__create_maps(struct perf_evlist *evlist, struct perf_target *target); void perf_evlist__delete_maps(struct perf_evlist *evlist); -int perf_evlist__apply_filters(struct perf_evlist *evlist); - -void __perf_evlist__set_leader(struct list_head *list); -void perf_evlist__set_leader(struct perf_evlist *evlist); +int perf_evlist__set_filters(struct perf_evlist *evlist); -u64 perf_evlist__sample_type(struct perf_evlist *evlist); -bool perf_evlist__sample_id_all(struct perf_evlist *evlist); -u16 perf_evlist__id_hdr_size(struct perf_evlist *evlist); +u64 perf_evlist__sample_type(const struct perf_evlist *evlist); +bool perf_evlist__sample_id_all(const const struct perf_evlist *evlist); +u16 perf_evlist__id_hdr_size(const struct perf_evlist *evlist); -int perf_evlist__parse_sample(struct perf_evlist *evlist, union perf_event *event, - struct perf_sample *sample); - -bool perf_evlist__valid_sample_type(struct perf_evlist *evlist); -bool perf_evlist__valid_sample_id_all(struct perf_evlist *evlist); +bool perf_evlist__valid_sample_type(const struct perf_evlist *evlist); +bool perf_evlist__valid_sample_id_all(const struct perf_evlist *evlist); void perf_evlist__splice_list_tail(struct perf_evlist *evlist, struct list_head *list, int nr_entries); -static inline struct perf_evsel *perf_evlist__first(struct perf_evlist *evlist) -{ - return list_entry(evlist->entries.next, struct perf_evsel, node); -} - -static inline struct perf_evsel *perf_evlist__last(struct perf_evlist *evlist) -{ - return list_entry(evlist->entries.prev, struct perf_evsel, node); -} - -size_t perf_evlist__fprintf(struct perf_evlist *evlist, FILE *fp); #endif /* __PERF_EVLIST_H */ diff --git a/trunk/tools/perf/util/evsel.c b/trunk/tools/perf/util/evsel.c index ffdd94e9c9c3..e81771364867 100644 --- a/trunk/tools/perf/util/evsel.c +++ b/trunk/tools/perf/util/evsel.c @@ -8,10 +8,7 @@ */ #include -#include #include "asm/bug.h" -#include "debugfs.h" -#include "event-parse.h" #include "evsel.h" #include "evlist.h" #include "util.h" @@ -19,12 +16,11 @@ #include "thread_map.h" #include "target.h" #include "../../../include/linux/hw_breakpoint.h" -#include "../../include/linux/perf_event.h" -#include "perf_regs.h" #define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y)) +#define GROUP_FD(group_fd, cpu) (*(int *)xyarray__entry(group_fd, cpu, 0)) -static int __perf_evsel__sample_size(u64 sample_type) +int __perf_evsel__sample_size(u64 sample_type) { u64 mask = sample_type & PERF_SAMPLE_MASK; int size = 0; @@ -57,7 +53,6 @@ void perf_evsel__init(struct perf_evsel *evsel, evsel->attr = *attr; INIT_LIST_HEAD(&evsel->node); hists__init(&evsel->hists); - evsel->sample_size = __perf_evsel__sample_size(attr->sample_type); } struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr, int idx) @@ -70,80 +65,7 @@ struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr, int idx) return evsel; } -struct event_format *event_format__new(const char *sys, const char *name) -{ - int fd, n; - char *filename; - void *bf = NULL, *nbf; - size_t size = 0, alloc_size = 0; - struct event_format *format = NULL; - - if (asprintf(&filename, "%s/%s/%s/format", tracing_events_path, sys, name) < 0) - goto out; - - fd = open(filename, O_RDONLY); - if (fd < 0) - goto out_free_filename; - - do { - if (size == alloc_size) { - alloc_size += BUFSIZ; - nbf = realloc(bf, alloc_size); - if (nbf == NULL) - goto out_free_bf; - bf = nbf; - } - - n = read(fd, bf + size, BUFSIZ); - if (n < 0) - goto out_free_bf; - size += n; - } while (n > 0); - - pevent_parse_format(&format, bf, size, sys); - -out_free_bf: - free(bf); - close(fd); -out_free_filename: - free(filename); -out: - return format; -} - -struct perf_evsel *perf_evsel__newtp(const char *sys, const char *name, int idx) -{ - struct perf_evsel *evsel = zalloc(sizeof(*evsel)); - - if (evsel != NULL) { - struct perf_event_attr attr = { - .type = PERF_TYPE_TRACEPOINT, - .sample_type = (PERF_SAMPLE_RAW | PERF_SAMPLE_TIME | - PERF_SAMPLE_CPU | PERF_SAMPLE_PERIOD), - }; - - if (asprintf(&evsel->name, "%s:%s", sys, name) < 0) - goto out_free; - - evsel->tp_format = event_format__new(sys, name); - if (evsel->tp_format == NULL) - goto out_free; - - event_attr_init(&attr); - attr.config = evsel->tp_format->id; - attr.sample_period = 1; - perf_evsel__init(evsel, &attr, idx); - } - - return evsel; - -out_free: - free(evsel->name); - free(evsel); - return NULL; -} - -const char *perf_evsel__hw_names[PERF_COUNT_HW_MAX] = { +static const char *perf_evsel__hw_names[PERF_COUNT_HW_MAX] = { "cycles", "instructions", "cache-references", @@ -206,12 +128,12 @@ static int perf_evsel__hw_name(struct perf_evsel *evsel, char *bf, size_t size) return r + perf_evsel__add_modifiers(evsel, bf + r, size - r); } -const char *perf_evsel__sw_names[PERF_COUNT_SW_MAX] = { +static const char *perf_evsel__sw_names[PERF_COUNT_SW_MAX] = { "cpu-clock", "task-clock", "page-faults", "context-switches", - "cpu-migrations", + "CPU-migrations", "minor-faults", "major-faults", "alignment-faults", @@ -394,8 +316,7 @@ const char *perf_evsel__name(struct perf_evsel *evsel) break; default: - scnprintf(bf, sizeof(bf), "unknown attr type: %d", - evsel->attr.type); + scnprintf(bf, sizeof(bf), "%s", "unknown attr type"); break; } @@ -445,18 +366,9 @@ void perf_evsel__config(struct perf_evsel *evsel, struct perf_record_opts *opts, attr->mmap_data = track; } - if (opts->call_graph) { + if (opts->call_graph) attr->sample_type |= PERF_SAMPLE_CALLCHAIN; - if (opts->call_graph == CALLCHAIN_DWARF) { - attr->sample_type |= PERF_SAMPLE_REGS_USER | - PERF_SAMPLE_STACK_USER; - attr->sample_regs_user = PERF_REGS_MASK; - attr->sample_stack_user = opts->stack_dump_size; - attr->exclude_callchain_user = 1; - } - } - if (perf_target__has_cpu(&opts->target)) attr->sample_type |= PERF_SAMPLE_CPU; @@ -508,24 +420,6 @@ int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads) return evsel->fd != NULL ? 0 : -ENOMEM; } -int perf_evsel__set_filter(struct perf_evsel *evsel, int ncpus, int nthreads, - const char *filter) -{ - int cpu, thread; - - for (cpu = 0; cpu < ncpus; cpu++) { - for (thread = 0; thread < nthreads; thread++) { - int fd = FD(evsel, cpu, thread), - err = ioctl(fd, PERF_EVENT_IOC_SET_FILTER, filter); - - if (err) - return err; - } - } - - return 0; -} - int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads) { evsel->sample_id = xyarray__new(ncpus, nthreads, sizeof(struct perf_sample_id)); @@ -586,9 +480,6 @@ void perf_evsel__delete(struct perf_evsel *evsel) { perf_evsel__exit(evsel); close_cgroup(evsel->cgrp); - free(evsel->group_name); - if (evsel->tp_format) - pevent_free_format(evsel->tp_format); free(evsel->name); free(evsel); } @@ -664,28 +555,9 @@ int __perf_evsel__read(struct perf_evsel *evsel, return 0; } -static int get_group_fd(struct perf_evsel *evsel, int cpu, int thread) -{ - struct perf_evsel *leader = evsel->leader; - int fd; - - if (!leader) - return -1; - - /* - * Leader must be already processed/open, - * if not it's a bug. - */ - BUG_ON(!leader->fd); - - fd = FD(leader, cpu, thread); - BUG_ON(fd == -1); - - return fd; -} - static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus, - struct thread_map *threads) + struct thread_map *threads, bool group, + struct xyarray *group_fds) { int cpu, thread; unsigned long flags = 0; @@ -701,15 +573,13 @@ static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus, } for (cpu = 0; cpu < cpus->nr; cpu++) { + int group_fd = group_fds ? GROUP_FD(group_fds, cpu) : -1; for (thread = 0; thread < threads->nr; thread++) { - int group_fd; if (!evsel->cgrp) pid = threads->map[thread]; - group_fd = get_group_fd(evsel, cpu, thread); - FD(evsel, cpu, thread) = sys_perf_event_open(&evsel->attr, pid, cpus->map[cpu], @@ -718,6 +588,9 @@ static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus, err = -errno; goto out_close; } + + if (group && group_fd == -1) + group_fd = FD(evsel, cpu, thread); } } @@ -761,7 +634,8 @@ static struct { }; int perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus, - struct thread_map *threads) + struct thread_map *threads, bool group, + struct xyarray *group_fd) { if (cpus == NULL) { /* Work around old compiler warnings about strict aliasing */ @@ -771,28 +645,30 @@ int perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus, if (threads == NULL) threads = &empty_thread_map.map; - return __perf_evsel__open(evsel, cpus, threads); + return __perf_evsel__open(evsel, cpus, threads, group, group_fd); } int perf_evsel__open_per_cpu(struct perf_evsel *evsel, - struct cpu_map *cpus) + struct cpu_map *cpus, bool group, + struct xyarray *group_fd) { - return __perf_evsel__open(evsel, cpus, &empty_thread_map.map); + return __perf_evsel__open(evsel, cpus, &empty_thread_map.map, group, + group_fd); } int perf_evsel__open_per_thread(struct perf_evsel *evsel, - struct thread_map *threads) + struct thread_map *threads, bool group, + struct xyarray *group_fd) { - return __perf_evsel__open(evsel, &empty_cpu_map.map, threads); + return __perf_evsel__open(evsel, &empty_cpu_map.map, threads, group, + group_fd); } -static int perf_evsel__parse_id_sample(const struct perf_evsel *evsel, - const union perf_event *event, - struct perf_sample *sample) +static int perf_event__parse_id_sample(const union perf_event *event, u64 type, + struct perf_sample *sample, + bool swapped) { - u64 type = evsel->attr.sample_type; const u64 *array = event->sample.array; - bool swapped = evsel->needs_swap; union u64_swap u; array += ((event->header.size - @@ -852,12 +728,10 @@ static bool sample_overlap(const union perf_event *event, return false; } -int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event, - struct perf_sample *data) +int perf_event__parse_sample(const union perf_event *event, u64 type, + int sample_size, bool sample_id_all, + struct perf_sample *data, bool swapped) { - u64 type = evsel->attr.sample_type; - u64 regs_user = evsel->attr.sample_regs_user; - bool swapped = evsel->needs_swap; const u64 *array; /* @@ -872,14 +746,14 @@ int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event, data->period = 1; if (event->header.type != PERF_RECORD_SAMPLE) { - if (!evsel->attr.sample_id_all) + if (!sample_id_all) return 0; - return perf_evsel__parse_id_sample(evsel, event, data); + return perf_event__parse_id_sample(event, type, data, swapped); } array = event->sample.array; - if (evsel->sample_size + sizeof(event->header) > event->header.size) + if (sample_size + sizeof(event->header) > event->header.size) return -EFAULT; if (type & PERF_SAMPLE_IP) { @@ -994,32 +868,6 @@ int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event, sz /= sizeof(u64); array += sz; } - - if (type & PERF_SAMPLE_REGS_USER) { - /* First u64 tells us if we have any regs in sample. */ - u64 avail = *array++; - - if (avail) { - data->user_regs.regs = (u64 *)array; - array += hweight_long(regs_user); - } - } - - if (type & PERF_SAMPLE_STACK_USER) { - u64 size = *array++; - - data->user_stack.offset = ((char *)(array - 1) - - (char *) event); - - if (!size) { - data->user_stack.size = 0; - } else { - data->user_stack.data = (char *)array; - array += size / sizeof(*array); - data->user_stack.size = *array; - } - } - return 0; } @@ -1047,7 +895,7 @@ int perf_event__synthesize_sample(union perf_event *event, u64 type, u.val32[1] = sample->tid; if (swapped) { /* - * Inverse of what is done in perf_evsel__parse_sample + * Inverse of what is done in perf_event__parse_sample */ u.val32[0] = bswap_32(u.val32[0]); u.val32[1] = bswap_32(u.val32[1]); @@ -1082,7 +930,7 @@ int perf_event__synthesize_sample(union perf_event *event, u64 type, u.val32[0] = sample->cpu; if (swapped) { /* - * Inverse of what is done in perf_evsel__parse_sample + * Inverse of what is done in perf_event__parse_sample */ u.val32[0] = bswap_32(u.val32[0]); u.val64 = bswap_64(u.val64); @@ -1098,72 +946,3 @@ int perf_event__synthesize_sample(union perf_event *event, u64 type, return 0; } - -struct format_field *perf_evsel__field(struct perf_evsel *evsel, const char *name) -{ - return pevent_find_field(evsel->tp_format, name); -} - -void *perf_evsel__rawptr(struct perf_evsel *evsel, struct perf_sample *sample, - const char *name) -{ - struct format_field *field = perf_evsel__field(evsel, name); - int offset; - - if (!field) - return NULL; - - offset = field->offset; - - if (field->flags & FIELD_IS_DYNAMIC) { - offset = *(int *)(sample->raw_data + field->offset); - offset &= 0xffff; - } - - return sample->raw_data + offset; -} - -u64 perf_evsel__intval(struct perf_evsel *evsel, struct perf_sample *sample, - const char *name) -{ - struct format_field *field = perf_evsel__field(evsel, name); - void *ptr; - u64 value; - - if (!field) - return 0; - - ptr = sample->raw_data + field->offset; - - switch (field->size) { - case 1: - return *(u8 *)ptr; - case 2: - value = *(u16 *)ptr; - break; - case 4: - value = *(u32 *)ptr; - break; - case 8: - value = *(u64 *)ptr; - break; - default: - return 0; - } - - if (!evsel->needs_swap) - return value; - - switch (field->size) { - case 2: - return bswap_16(value); - case 4: - return bswap_32(value); - case 8: - return bswap_64(value); - default: - return 0; - } - - return 0; -} diff --git a/trunk/tools/perf/util/evsel.h b/trunk/tools/perf/util/evsel.h index 3ead0d59c03d..67cc5033d192 100644 --- a/trunk/tools/perf/util/evsel.h +++ b/trunk/tools/perf/util/evsel.h @@ -53,10 +53,9 @@ struct perf_evsel { u64 *id; struct perf_counts *counts; int idx; - u32 ids; + int ids; struct hists hists; char *name; - struct event_format *tp_format; union { void *priv; off_t id_offset; @@ -66,14 +65,7 @@ struct perf_evsel { void *func; void *data; } handler; - struct cpu_map *cpus; - unsigned int sample_size; bool supported; - bool needs_swap; - /* parse modifier helper */ - int exclude_GH; - struct perf_evsel *leader; - char *group_name; }; struct cpu_map; @@ -82,10 +74,6 @@ struct perf_evlist; struct perf_record_opts; struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr, int idx); -struct perf_evsel *perf_evsel__newtp(const char *sys, const char *name, int idx); - -struct event_format *event_format__new(const char *sys, const char *name); - void perf_evsel__init(struct perf_evsel *evsel, struct perf_event_attr *attr, int idx); void perf_evsel__exit(struct perf_evsel *evsel); @@ -103,10 +91,8 @@ extern const char *perf_evsel__hw_cache[PERF_COUNT_HW_CACHE_MAX] [PERF_EVSEL__MAX_ALIASES]; extern const char *perf_evsel__hw_cache_op[PERF_COUNT_HW_CACHE_OP_MAX] [PERF_EVSEL__MAX_ALIASES]; -extern const char *perf_evsel__hw_cache_result[PERF_COUNT_HW_CACHE_RESULT_MAX] - [PERF_EVSEL__MAX_ALIASES]; -extern const char *perf_evsel__hw_names[PERF_COUNT_HW_MAX]; -extern const char *perf_evsel__sw_names[PERF_COUNT_SW_MAX]; +const char *perf_evsel__hw_cache_result[PERF_COUNT_HW_CACHE_RESULT_MAX] + [PERF_EVSEL__MAX_ALIASES]; int __perf_evsel__hw_cache_type_op_res_name(u8 type, u8 op, u8 result, char *bf, size_t size); const char *perf_evsel__name(struct perf_evsel *evsel); @@ -118,46 +104,21 @@ void perf_evsel__free_fd(struct perf_evsel *evsel); void perf_evsel__free_id(struct perf_evsel *evsel); void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads); -int perf_evsel__set_filter(struct perf_evsel *evsel, int ncpus, int nthreads, - const char *filter); - int perf_evsel__open_per_cpu(struct perf_evsel *evsel, - struct cpu_map *cpus); + struct cpu_map *cpus, bool group, + struct xyarray *group_fds); int perf_evsel__open_per_thread(struct perf_evsel *evsel, - struct thread_map *threads); + struct thread_map *threads, bool group, + struct xyarray *group_fds); int perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus, - struct thread_map *threads); + struct thread_map *threads, bool group, + struct xyarray *group_fds); void perf_evsel__close(struct perf_evsel *evsel, int ncpus, int nthreads); -struct perf_sample; - -void *perf_evsel__rawptr(struct perf_evsel *evsel, struct perf_sample *sample, - const char *name); -u64 perf_evsel__intval(struct perf_evsel *evsel, struct perf_sample *sample, - const char *name); - -static inline char *perf_evsel__strval(struct perf_evsel *evsel, - struct perf_sample *sample, - const char *name) -{ - return perf_evsel__rawptr(evsel, sample, name); -} - -struct format_field; - -struct format_field *perf_evsel__field(struct perf_evsel *evsel, const char *name); - #define perf_evsel__match(evsel, t, c) \ (evsel->attr.type == PERF_TYPE_##t && \ evsel->attr.config == PERF_COUNT_##c) -static inline bool perf_evsel__match2(struct perf_evsel *e1, - struct perf_evsel *e2) -{ - return (e1->attr.type == e2->attr.type) && - (e1->attr.config == e2->attr.config); -} - int __perf_evsel__read_on_cpu(struct perf_evsel *evsel, int cpu, int thread, bool scale); @@ -216,13 +177,13 @@ static inline int perf_evsel__read_scaled(struct perf_evsel *evsel, return __perf_evsel__read(evsel, ncpus, nthreads, true); } -void hists__init(struct hists *hists); +int __perf_evsel__sample_size(u64 sample_type); -int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event, - struct perf_sample *sample); - -static inline struct perf_evsel *perf_evsel__next(struct perf_evsel *evsel) +static inline int perf_evsel__sample_size(struct perf_evsel *evsel) { - return list_entry(evsel->node.next, struct perf_evsel, node); + return __perf_evsel__sample_size(evsel->attr.sample_type); } + +void hists__init(struct hists *hists); + #endif /* __PERF_EVSEL_H */ diff --git a/trunk/tools/perf/util/generate-cmdlist.sh b/trunk/tools/perf/util/generate-cmdlist.sh index 389590c1ad21..f06f6fd148f8 100755 --- a/trunk/tools/perf/util/generate-cmdlist.sh +++ b/trunk/tools/perf/util/generate-cmdlist.sh @@ -21,19 +21,4 @@ do p }' "Documentation/perf-$cmd.txt" done - -echo "#ifndef NO_LIBELF_SUPPORT" -sed -n -e 's/^perf-\([^ ]*\)[ ].* full.*/\1/p' command-list.txt | -sort | -while read cmd -do - sed -n ' - /^NAME/,/perf-'"$cmd"'/H - ${ - x - s/.*perf-'"$cmd"' - \(.*\)/ {"'"$cmd"'", "\1"},/ - p - }' "Documentation/perf-$cmd.txt" -done -echo "#endif /* NO_LIBELF_SUPPORT */" echo "};" diff --git a/trunk/tools/perf/util/header.c b/trunk/tools/perf/util/header.c index 7daad237dea5..3a6d20443330 100644 --- a/trunk/tools/perf/util/header.c +++ b/trunk/tools/perf/util/header.c @@ -20,14 +20,11 @@ #include "symbol.h" #include "debug.h" #include "cpumap.h" -#include "pmu.h" -#include "vdso.h" -#include "strbuf.h" static bool no_buildid_cache = false; -static int trace_event_count; -static struct perf_trace_event_type *trace_events; +static int event_count; +static struct perf_trace_event_type *events; static u32 header_argc; static const char **header_argv; @@ -39,24 +36,24 @@ int perf_header__push_event(u64 id, const char *name) if (strlen(name) > MAX_EVENT_NAME) pr_warning("Event %s will be truncated\n", name); - nevents = realloc(trace_events, (trace_event_count + 1) * sizeof(*trace_events)); + nevents = realloc(events, (event_count + 1) * sizeof(*events)); if (nevents == NULL) return -ENOMEM; - trace_events = nevents; + events = nevents; - memset(&trace_events[trace_event_count], 0, sizeof(struct perf_trace_event_type)); - trace_events[trace_event_count].event_id = id; - strncpy(trace_events[trace_event_count].name, name, MAX_EVENT_NAME - 1); - trace_event_count++; + memset(&events[event_count], 0, sizeof(struct perf_trace_event_type)); + events[event_count].event_id = id; + strncpy(events[event_count].name, name, MAX_EVENT_NAME - 1); + event_count++; return 0; } char *perf_header__find_event(u64 id) { int i; - for (i = 0 ; i < trace_event_count; i++) { - if (trace_events[i].event_id == id) - return trace_events[i].name; + for (i = 0 ; i < event_count; i++) { + if (events[i].event_id == id) + return events[i].name; } return NULL; } @@ -131,7 +128,7 @@ static int do_write_string(int fd, const char *str) int ret; olen = strlen(str) + 1; - len = PERF_ALIGN(olen, NAME_ALIGN); + len = ALIGN(olen, NAME_ALIGN); /* write len, incl. \0 */ ret = do_write(fd, &len, sizeof(len)); @@ -177,15 +174,6 @@ perf_header__set_cmdline(int argc, const char **argv) { int i; - /* - * If header_argv has already been set, do not override it. - * This allows a command to set the cmdline, parse args and - * then call another builtin function that implements a - * command -- e.g, cmd_kvm calling cmd_record. - */ - if (header_argv) - return 0; - header_argc = (u32)argc; /* do not include NULL termination */ @@ -209,29 +197,6 @@ perf_header__set_cmdline(int argc, const char **argv) continue; \ else -static int write_buildid(char *name, size_t name_len, u8 *build_id, - pid_t pid, u16 misc, int fd) -{ - int err; - struct build_id_event b; - size_t len; - - len = name_len + 1; - len = PERF_ALIGN(len, NAME_ALIGN); - - memset(&b, 0, sizeof(b)); - memcpy(&b.build_id, build_id, BUILD_ID_SIZE); - b.pid = pid; - b.header.misc = misc; - b.header.size = sizeof(b) + len; - - err = do_write(fd, &b, sizeof(b)); - if (err < 0) - return err; - - return write_padded(fd, name, name_len + 1, len); -} - static int __dsos__write_buildid_table(struct list_head *head, pid_t pid, u16 misc, int fd) { @@ -239,23 +204,24 @@ static int __dsos__write_buildid_table(struct list_head *head, pid_t pid, dsos__for_each_with_build_id(pos, head) { int err; - char *name; - size_t name_len; + struct build_id_event b; + size_t len; if (!pos->hit) continue; - - if (is_vdso_map(pos->short_name)) { - name = (char *) VDSO__MAP_NAME; - name_len = sizeof(VDSO__MAP_NAME) + 1; - } else { - name = pos->long_name; - name_len = pos->long_name_len + 1; - } - - err = write_buildid(name, name_len, pos->build_id, - pid, misc, fd); - if (err) + len = pos->long_name_len + 1; + len = ALIGN(len, NAME_ALIGN); + memset(&b, 0, sizeof(b)); + memcpy(&b.build_id, pos->build_id, sizeof(pos->build_id)); + b.pid = pid; + b.header.misc = misc; + b.header.size = sizeof(b) + len; + err = do_write(fd, &b, sizeof(b)); + if (err < 0) + return err; + err = write_padded(fd, pos->long_name, + pos->long_name_len + 1, len); + if (err < 0) return err; } @@ -301,20 +267,19 @@ static int dsos__write_buildid_table(struct perf_header *header, int fd) } int build_id_cache__add_s(const char *sbuild_id, const char *debugdir, - const char *name, bool is_kallsyms, bool is_vdso) + const char *name, bool is_kallsyms) { const size_t size = PATH_MAX; char *realname, *filename = zalloc(size), *linkname = zalloc(size), *targetname; int len, err = -1; - bool slash = is_kallsyms || is_vdso; if (is_kallsyms) { if (symbol_conf.kptr_restrict) { pr_debug("Not caching a kptr_restrict'ed /proc/kallsyms\n"); return 0; } - realname = (char *) name; + realname = (char *)name; } else realname = realpath(name, NULL); @@ -322,8 +287,7 @@ int build_id_cache__add_s(const char *sbuild_id, const char *debugdir, goto out_free; len = scnprintf(filename, size, "%s%s%s", - debugdir, slash ? "/" : "", - is_vdso ? VDSO__MAP_NAME : realname); + debugdir, is_kallsyms ? "/" : "", realname); if (mkdir_p(filename, 0755)) goto out_free; @@ -359,14 +323,13 @@ int build_id_cache__add_s(const char *sbuild_id, const char *debugdir, static int build_id_cache__add_b(const u8 *build_id, size_t build_id_size, const char *name, const char *debugdir, - bool is_kallsyms, bool is_vdso) + bool is_kallsyms) { char sbuild_id[BUILD_ID_SIZE * 2 + 1]; build_id__sprintf(build_id, build_id_size, sbuild_id); - return build_id_cache__add_s(sbuild_id, debugdir, name, - is_kallsyms, is_vdso); + return build_id_cache__add_s(sbuild_id, debugdir, name, is_kallsyms); } int build_id_cache__remove_s(const char *sbuild_id, const char *debugdir) @@ -410,11 +373,9 @@ int build_id_cache__remove_s(const char *sbuild_id, const char *debugdir) static int dso__cache_build_id(struct dso *dso, const char *debugdir) { bool is_kallsyms = dso->kernel && dso->long_name[0] != '/'; - bool is_vdso = is_vdso_map(dso->short_name); return build_id_cache__add_b(dso->build_id, sizeof(dso->build_id), - dso->long_name, debugdir, - is_kallsyms, is_vdso); + dso->long_name, debugdir, is_kallsyms); } static int __dsos__cache_build_ids(struct list_head *head, const char *debugdir) @@ -476,7 +437,7 @@ static bool perf_session__read_build_ids(struct perf_session *session, bool with return ret; } -static int write_tracing_data(int fd, struct perf_header *h __maybe_unused, +static int write_tracing_data(int fd, struct perf_header *h __used, struct perf_evlist *evlist) { return read_tracing_data(fd, &evlist->entries); @@ -484,7 +445,7 @@ static int write_tracing_data(int fd, struct perf_header *h __maybe_unused, static int write_build_id(int fd, struct perf_header *h, - struct perf_evlist *evlist __maybe_unused) + struct perf_evlist *evlist __used) { struct perf_session *session; int err; @@ -505,8 +466,8 @@ static int write_build_id(int fd, struct perf_header *h, return 0; } -static int write_hostname(int fd, struct perf_header *h __maybe_unused, - struct perf_evlist *evlist __maybe_unused) +static int write_hostname(int fd, struct perf_header *h __used, + struct perf_evlist *evlist __used) { struct utsname uts; int ret; @@ -518,8 +479,8 @@ static int write_hostname(int fd, struct perf_header *h __maybe_unused, return do_write_string(fd, uts.nodename); } -static int write_osrelease(int fd, struct perf_header *h __maybe_unused, - struct perf_evlist *evlist __maybe_unused) +static int write_osrelease(int fd, struct perf_header *h __used, + struct perf_evlist *evlist __used) { struct utsname uts; int ret; @@ -531,8 +492,8 @@ static int write_osrelease(int fd, struct perf_header *h __maybe_unused, return do_write_string(fd, uts.release); } -static int write_arch(int fd, struct perf_header *h __maybe_unused, - struct perf_evlist *evlist __maybe_unused) +static int write_arch(int fd, struct perf_header *h __used, + struct perf_evlist *evlist __used) { struct utsname uts; int ret; @@ -544,14 +505,14 @@ static int write_arch(int fd, struct perf_header *h __maybe_unused, return do_write_string(fd, uts.machine); } -static int write_version(int fd, struct perf_header *h __maybe_unused, - struct perf_evlist *evlist __maybe_unused) +static int write_version(int fd, struct perf_header *h __used, + struct perf_evlist *evlist __used) { return do_write_string(fd, perf_version_string); } -static int write_cpudesc(int fd, struct perf_header *h __maybe_unused, - struct perf_evlist *evlist __maybe_unused) +static int write_cpudesc(int fd, struct perf_header *h __used, + struct perf_evlist *evlist __used) { #ifndef CPUINFO_PROC #define CPUINFO_PROC NULL @@ -609,8 +570,8 @@ static int write_cpudesc(int fd, struct perf_header *h __maybe_unused, return ret; } -static int write_nrcpus(int fd, struct perf_header *h __maybe_unused, - struct perf_evlist *evlist __maybe_unused) +static int write_nrcpus(int fd, struct perf_header *h __used, + struct perf_evlist *evlist __used) { long nr; u32 nrc, nra; @@ -635,14 +596,15 @@ static int write_nrcpus(int fd, struct perf_header *h __maybe_unused, return do_write(fd, &nra, sizeof(nra)); } -static int write_event_desc(int fd, struct perf_header *h __maybe_unused, +static int write_event_desc(int fd, struct perf_header *h __used, struct perf_evlist *evlist) { - struct perf_evsel *evsel; - u32 nre, nri, sz; + struct perf_evsel *attr; + u32 nre = 0, nri, sz; int ret; - nre = evlist->nr_entries; + list_for_each_entry(attr, &evlist->entries, node) + nre++; /* * write number of events @@ -654,14 +616,14 @@ static int write_event_desc(int fd, struct perf_header *h __maybe_unused, /* * size of perf_event_attr struct */ - sz = (u32)sizeof(evsel->attr); + sz = (u32)sizeof(attr->attr); ret = do_write(fd, &sz, sizeof(sz)); if (ret < 0) return ret; - list_for_each_entry(evsel, &evlist->entries, node) { + list_for_each_entry(attr, &evlist->entries, node) { - ret = do_write(fd, &evsel->attr, sz); + ret = do_write(fd, &attr->attr, sz); if (ret < 0) return ret; /* @@ -671,7 +633,7 @@ static int write_event_desc(int fd, struct perf_header *h __maybe_unused, * copy into an nri to be independent of the * type of ids, */ - nri = evsel->ids; + nri = attr->ids; ret = do_write(fd, &nri, sizeof(nri)); if (ret < 0) return ret; @@ -679,21 +641,21 @@ static int write_event_desc(int fd, struct perf_header *h __maybe_unused, /* * write event string as passed on cmdline */ - ret = do_write_string(fd, perf_evsel__name(evsel)); + ret = do_write_string(fd, perf_evsel__name(attr)); if (ret < 0) return ret; /* * write unique ids for this event */ - ret = do_write(fd, evsel->id, evsel->ids * sizeof(u64)); + ret = do_write(fd, attr->id, attr->ids * sizeof(u64)); if (ret < 0) return ret; } return 0; } -static int write_cmdline(int fd, struct perf_header *h __maybe_unused, - struct perf_evlist *evlist __maybe_unused) +static int write_cmdline(int fd, struct perf_header *h __used, + struct perf_evlist *evlist __used) { char buf[MAXPATHLEN]; char proc[32]; @@ -861,8 +823,8 @@ static struct cpu_topo *build_cpu_topology(void) return tp; } -static int write_cpu_topology(int fd, struct perf_header *h __maybe_unused, - struct perf_evlist *evlist __maybe_unused) +static int write_cpu_topology(int fd, struct perf_header *h __used, + struct perf_evlist *evlist __used) { struct cpu_topo *tp; u32 i; @@ -897,8 +859,8 @@ static int write_cpu_topology(int fd, struct perf_header *h __maybe_unused, -static int write_total_mem(int fd, struct perf_header *h __maybe_unused, - struct perf_evlist *evlist __maybe_unused) +static int write_total_mem(int fd, struct perf_header *h __used, + struct perf_evlist *evlist __used) { char *buf = NULL; FILE *fp; @@ -983,8 +945,8 @@ static int write_topo_node(int fd, int node) return ret; } -static int write_numa_topology(int fd, struct perf_header *h __maybe_unused, - struct perf_evlist *evlist __maybe_unused) +static int write_numa_topology(int fd, struct perf_header *h __used, + struct perf_evlist *evlist __used) { char *buf = NULL; size_t len = 0; @@ -1032,57 +994,17 @@ static int write_numa_topology(int fd, struct perf_header *h __maybe_unused, return ret; } -/* - * File format: - * - * struct pmu_mappings { - * u32 pmu_num; - * struct pmu_map { - * u32 type; - * char name[]; - * }[pmu_num]; - * }; - */ - -static int write_pmu_mappings(int fd, struct perf_header *h __maybe_unused, - struct perf_evlist *evlist __maybe_unused) -{ - struct perf_pmu *pmu = NULL; - off_t offset = lseek(fd, 0, SEEK_CUR); - __u32 pmu_num = 0; - - /* write real pmu_num later */ - do_write(fd, &pmu_num, sizeof(pmu_num)); - - while ((pmu = perf_pmu__scan(pmu))) { - if (!pmu->name) - continue; - pmu_num++; - do_write(fd, &pmu->type, sizeof(pmu->type)); - do_write_string(fd, pmu->name); - } - - if (pwrite(fd, &pmu_num, sizeof(pmu_num), offset) != sizeof(pmu_num)) { - /* discard all */ - lseek(fd, offset, SEEK_SET); - return -1; - } - - return 0; -} - /* * default get_cpuid(): nothing gets recorded * actual implementation must be in arch/$(ARCH)/util/header.c */ -int __attribute__ ((weak)) get_cpuid(char *buffer __maybe_unused, - size_t sz __maybe_unused) +int __attribute__((weak)) get_cpuid(char *buffer __used, size_t sz __used) { return -1; } -static int write_cpuid(int fd, struct perf_header *h __maybe_unused, - struct perf_evlist *evlist __maybe_unused) +static int write_cpuid(int fd, struct perf_header *h __used, + struct perf_evlist *evlist __used) { char buffer[64]; int ret; @@ -1096,113 +1018,133 @@ static int write_cpuid(int fd, struct perf_header *h __maybe_unused, return do_write_string(fd, buffer); } -static int write_branch_stack(int fd __maybe_unused, - struct perf_header *h __maybe_unused, - struct perf_evlist *evlist __maybe_unused) +static int write_branch_stack(int fd __used, struct perf_header *h __used, + struct perf_evlist *evlist __used) { return 0; } -static void print_hostname(struct perf_header *ph, int fd __maybe_unused, - FILE *fp) +static void print_hostname(struct perf_header *ph, int fd, FILE *fp) { - fprintf(fp, "# hostname : %s\n", ph->env.hostname); + char *str = do_read_string(fd, ph); + fprintf(fp, "# hostname : %s\n", str); + free(str); } -static void print_osrelease(struct perf_header *ph, int fd __maybe_unused, - FILE *fp) +static void print_osrelease(struct perf_header *ph, int fd, FILE *fp) { - fprintf(fp, "# os release : %s\n", ph->env.os_release); + char *str = do_read_string(fd, ph); + fprintf(fp, "# os release : %s\n", str); + free(str); } -static void print_arch(struct perf_header *ph, int fd __maybe_unused, FILE *fp) +static void print_arch(struct perf_header *ph, int fd, FILE *fp) { - fprintf(fp, "# arch : %s\n", ph->env.arch); + char *str = do_read_string(fd, ph); + fprintf(fp, "# arch : %s\n", str); + free(str); } -static void print_cpudesc(struct perf_header *ph, int fd __maybe_unused, - FILE *fp) +static void print_cpudesc(struct perf_header *ph, int fd, FILE *fp) { - fprintf(fp, "# cpudesc : %s\n", ph->env.cpu_desc); + char *str = do_read_string(fd, ph); + fprintf(fp, "# cpudesc : %s\n", str); + free(str); } -static void print_nrcpus(struct perf_header *ph, int fd __maybe_unused, - FILE *fp) +static void print_nrcpus(struct perf_header *ph, int fd, FILE *fp) { - fprintf(fp, "# nrcpus online : %u\n", ph->env.nr_cpus_online); - fprintf(fp, "# nrcpus avail : %u\n", ph->env.nr_cpus_avail); + ssize_t ret; + u32 nr; + + ret = read(fd, &nr, sizeof(nr)); + if (ret != (ssize_t)sizeof(nr)) + nr = -1; /* interpreted as error */ + + if (ph->needs_swap) + nr = bswap_32(nr); + + fprintf(fp, "# nrcpus online : %u\n", nr); + + ret = read(fd, &nr, sizeof(nr)); + if (ret != (ssize_t)sizeof(nr)) + nr = -1; /* interpreted as error */ + + if (ph->needs_swap) + nr = bswap_32(nr); + + fprintf(fp, "# nrcpus avail : %u\n", nr); } -static void print_version(struct perf_header *ph, int fd __maybe_unused, - FILE *fp) +static void print_version(struct perf_header *ph, int fd, FILE *fp) { - fprintf(fp, "# perf version : %s\n", ph->env.version); + char *str = do_read_string(fd, ph); + fprintf(fp, "# perf version : %s\n", str); + free(str); } -static void print_cmdline(struct perf_header *ph, int fd __maybe_unused, - FILE *fp) +static void print_cmdline(struct perf_header *ph, int fd, FILE *fp) { - int nr, i; + ssize_t ret; char *str; + u32 nr, i; - nr = ph->env.nr_cmdline; - str = ph->env.cmdline; + ret = read(fd, &nr, sizeof(nr)); + if (ret != (ssize_t)sizeof(nr)) + return; + + if (ph->needs_swap) + nr = bswap_32(nr); fprintf(fp, "# cmdline : "); for (i = 0; i < nr; i++) { + str = do_read_string(fd, ph); fprintf(fp, "%s ", str); - str += strlen(str) + 1; + free(str); } fputc('\n', fp); } -static void print_cpu_topology(struct perf_header *ph, int fd __maybe_unused, - FILE *fp) +static void print_cpu_topology(struct perf_header *ph, int fd, FILE *fp) { - int nr, i; + ssize_t ret; + u32 nr, i; char *str; - nr = ph->env.nr_sibling_cores; - str = ph->env.sibling_cores; + ret = read(fd, &nr, sizeof(nr)); + if (ret != (ssize_t)sizeof(nr)) + return; + + if (ph->needs_swap) + nr = bswap_32(nr); for (i = 0; i < nr; i++) { + str = do_read_string(fd, ph); fprintf(fp, "# sibling cores : %s\n", str); - str += strlen(str) + 1; + free(str); } - nr = ph->env.nr_sibling_threads; - str = ph->env.sibling_threads; + ret = read(fd, &nr, sizeof(nr)); + if (ret != (ssize_t)sizeof(nr)) + return; + + if (ph->needs_swap) + nr = bswap_32(nr); for (i = 0; i < nr; i++) { + str = do_read_string(fd, ph); fprintf(fp, "# sibling threads : %s\n", str); - str += strlen(str) + 1; - } -} - -static void free_event_desc(struct perf_evsel *events) -{ - struct perf_evsel *evsel; - - if (!events) - return; - - for (evsel = events; evsel->attr.size; evsel++) { - if (evsel->name) - free(evsel->name); - if (evsel->id) - free(evsel->id); + free(str); } - - free(events); } -static struct perf_evsel * -read_event_desc(struct perf_header *ph, int fd) +static void print_event_desc(struct perf_header *ph, int fd, FILE *fp) { - struct perf_evsel *evsel, *events = NULL; - u64 *id; + struct perf_event_attr attr; + uint64_t id; void *buf = NULL; + char *str; u32 nre, sz, nr, i, j; ssize_t ret; size_t msz; @@ -1222,22 +1164,18 @@ read_event_desc(struct perf_header *ph, int fd) if (ph->needs_swap) sz = bswap_32(sz); + memset(&attr, 0, sizeof(attr)); + /* buffer to hold on file attr struct */ buf = malloc(sz); if (!buf) goto error; - /* the last event terminates with evsel->attr.size == 0: */ - events = calloc(nre + 1, sizeof(*events)); - if (!events) - goto error; - - msz = sizeof(evsel->attr); + msz = sizeof(attr); if (sz < msz) msz = sz; - for (i = 0, evsel = events; i < nre; evsel++, i++) { - evsel->idx = i; + for (i = 0 ; i < nre; i++) { /* * must read entire on-file attr struct to @@ -1250,186 +1188,144 @@ read_event_desc(struct perf_header *ph, int fd) if (ph->needs_swap) perf_event__attr_swap(buf); - memcpy(&evsel->attr, buf, msz); + memcpy(&attr, buf, msz); ret = read(fd, &nr, sizeof(nr)); if (ret != (ssize_t)sizeof(nr)) goto error; - if (ph->needs_swap) { + if (ph->needs_swap) nr = bswap_32(nr); - evsel->needs_swap = true; - } - - evsel->name = do_read_string(fd, ph); - - if (!nr) - continue; - id = calloc(nr, sizeof(*id)); - if (!id) - goto error; - evsel->ids = nr; - evsel->id = id; - - for (j = 0 ; j < nr; j++) { - ret = read(fd, id, sizeof(*id)); - if (ret != (ssize_t)sizeof(*id)) - goto error; - if (ph->needs_swap) - *id = bswap_64(*id); - id++; - } - } -out: - if (buf) - free(buf); - return events; -error: - if (events) - free_event_desc(events); - events = NULL; - goto out; -} - -static void print_event_desc(struct perf_header *ph, int fd, FILE *fp) -{ - struct perf_evsel *evsel, *events = read_event_desc(ph, fd); - u32 j; - u64 *id; - - if (!events) { - fprintf(fp, "# event desc: not available or unable to read\n"); - return; - } - - for (evsel = events; evsel->attr.size; evsel++) { - fprintf(fp, "# event : name = %s, ", evsel->name); + str = do_read_string(fd, ph); + fprintf(fp, "# event : name = %s, ", str); + free(str); fprintf(fp, "type = %d, config = 0x%"PRIx64 ", config1 = 0x%"PRIx64", config2 = 0x%"PRIx64, - evsel->attr.type, - (u64)evsel->attr.config, - (u64)evsel->attr.config1, - (u64)evsel->attr.config2); + attr.type, + (u64)attr.config, + (u64)attr.config1, + (u64)attr.config2); fprintf(fp, ", excl_usr = %d, excl_kern = %d", - evsel->attr.exclude_user, - evsel->attr.exclude_kernel); + attr.exclude_user, + attr.exclude_kernel); fprintf(fp, ", excl_host = %d, excl_guest = %d", - evsel->attr.exclude_host, - evsel->attr.exclude_guest); + attr.exclude_host, + attr.exclude_guest); - fprintf(fp, ", precise_ip = %d", evsel->attr.precise_ip); + fprintf(fp, ", precise_ip = %d", attr.precise_ip); - if (evsel->ids) { + if (nr) fprintf(fp, ", id = {"); - for (j = 0, id = evsel->id; j < evsel->ids; j++, id++) { - if (j) - fputc(',', fp); - fprintf(fp, " %"PRIu64, *id); - } - fprintf(fp, " }"); - } + for (j = 0 ; j < nr; j++) { + ret = read(fd, &id, sizeof(id)); + if (ret != (ssize_t)sizeof(id)) + goto error; + + if (ph->needs_swap) + id = bswap_64(id); + + if (j) + fputc(',', fp); + + fprintf(fp, " %"PRIu64, id); + } + if (nr && j == nr) + fprintf(fp, " }"); fputc('\n', fp); } - - free_event_desc(events); + free(buf); + return; +error: + fprintf(fp, "# event desc: not available or unable to read\n"); } -static void print_total_mem(struct perf_header *ph, int fd __maybe_unused, - FILE *fp) +static void print_total_mem(struct perf_header *h __used, int fd, FILE *fp) { - fprintf(fp, "# total memory : %Lu kB\n", ph->env.total_mem); + uint64_t mem; + ssize_t ret; + + ret = read(fd, &mem, sizeof(mem)); + if (ret != sizeof(mem)) + goto error; + + if (h->needs_swap) + mem = bswap_64(mem); + + fprintf(fp, "# total memory : %"PRIu64" kB\n", mem); + return; +error: + fprintf(fp, "# total memory : unknown\n"); } -static void print_numa_topology(struct perf_header *ph, int fd __maybe_unused, - FILE *fp) +static void print_numa_topology(struct perf_header *h __used, int fd, FILE *fp) { + ssize_t ret; u32 nr, c, i; - char *str, *tmp; + char *str; uint64_t mem_total, mem_free; /* nr nodes */ - nr = ph->env.nr_numa_nodes; - str = ph->env.numa_nodes; + ret = read(fd, &nr, sizeof(nr)); + if (ret != (ssize_t)sizeof(nr)) + goto error; + + if (h->needs_swap) + nr = bswap_32(nr); for (i = 0; i < nr; i++) { + /* node number */ - c = strtoul(str, &tmp, 0); - if (*tmp != ':') + ret = read(fd, &c, sizeof(c)); + if (ret != (ssize_t)sizeof(c)) goto error; - str = tmp + 1; - mem_total = strtoull(str, &tmp, 0); - if (*tmp != ':') + if (h->needs_swap) + c = bswap_32(c); + + ret = read(fd, &mem_total, sizeof(u64)); + if (ret != sizeof(u64)) goto error; - str = tmp + 1; - mem_free = strtoull(str, &tmp, 0); - if (*tmp != ':') + ret = read(fd, &mem_free, sizeof(u64)); + if (ret != sizeof(u64)) goto error; + if (h->needs_swap) { + mem_total = bswap_64(mem_total); + mem_free = bswap_64(mem_free); + } + fprintf(fp, "# node%u meminfo : total = %"PRIu64" kB," " free = %"PRIu64" kB\n", - c, mem_total, mem_free); + c, + mem_total, + mem_free); - str = tmp + 1; + str = do_read_string(fd, h); fprintf(fp, "# node%u cpu list : %s\n", c, str); + free(str); } return; error: fprintf(fp, "# numa topology : not available\n"); } -static void print_cpuid(struct perf_header *ph, int fd __maybe_unused, FILE *fp) -{ - fprintf(fp, "# cpuid : %s\n", ph->env.cpuid); -} - -static void print_branch_stack(struct perf_header *ph __maybe_unused, - int fd __maybe_unused, FILE *fp) +static void print_cpuid(struct perf_header *ph, int fd, FILE *fp) { - fprintf(fp, "# contains samples with branch stack\n"); + char *str = do_read_string(fd, ph); + fprintf(fp, "# cpuid : %s\n", str); + free(str); } -static void print_pmu_mappings(struct perf_header *ph, int fd __maybe_unused, +static void print_branch_stack(struct perf_header *ph __used, int fd __used, FILE *fp) { - const char *delimiter = "# pmu mappings: "; - char *str, *tmp; - u32 pmu_num; - u32 type; - - pmu_num = ph->env.nr_pmu_mappings; - if (!pmu_num) { - fprintf(fp, "# pmu mappings: not available\n"); - return; - } - - str = ph->env.pmu_mappings; - - while (pmu_num) { - type = strtoul(str, &tmp, 0); - if (*tmp != ':') - goto error; - - str = tmp + 1; - fprintf(fp, "%s%s = %" PRIu32, delimiter, str, type); - - delimiter = ", "; - str += strlen(str) + 1; - pmu_num--; - } - - fprintf(fp, "\n"); - - if (!pmu_num) - return; -error: - fprintf(fp, "# pmu mappings: unable to read\n"); + fprintf(fp, "# contains samples with branch stack\n"); } static int __event_process_build_id(struct build_id_event *bev, @@ -1493,7 +1389,7 @@ static int perf_header__read_build_ids_abi_quirk(struct perf_header *header, struct perf_session *session = container_of(header, struct perf_session, header); struct { struct perf_event_header header; - u8 build_id[PERF_ALIGN(BUILD_ID_SIZE, sizeof(u64))]; + u8 build_id[ALIGN(BUILD_ID_SIZE, sizeof(u64))]; char filename[0]; } old_bev; struct build_id_event bev; @@ -1582,375 +1478,28 @@ static int perf_header__read_build_ids(struct perf_header *header, return err; } -static int process_tracing_data(struct perf_file_section *section __maybe_unused, - struct perf_header *ph __maybe_unused, - int fd, void *data) +static int process_tracing_data(struct perf_file_section *section __unused, + struct perf_header *ph __unused, + int feat __unused, int fd, void *data) { trace_report(fd, data, false); return 0; } static int process_build_id(struct perf_file_section *section, - struct perf_header *ph, int fd, - void *data __maybe_unused) + struct perf_header *ph, + int feat __unused, int fd, void *data __used) { if (perf_header__read_build_ids(ph, fd, section->offset, section->size)) pr_debug("Failed to read buildids, continuing...\n"); return 0; } -static int process_hostname(struct perf_file_section *section __maybe_unused, - struct perf_header *ph, int fd, - void *data __maybe_unused) -{ - ph->env.hostname = do_read_string(fd, ph); - return ph->env.hostname ? 0 : -ENOMEM; -} - -static int process_osrelease(struct perf_file_section *section __maybe_unused, - struct perf_header *ph, int fd, - void *data __maybe_unused) -{ - ph->env.os_release = do_read_string(fd, ph); - return ph->env.os_release ? 0 : -ENOMEM; -} - -static int process_version(struct perf_file_section *section __maybe_unused, - struct perf_header *ph, int fd, - void *data __maybe_unused) -{ - ph->env.version = do_read_string(fd, ph); - return ph->env.version ? 0 : -ENOMEM; -} - -static int process_arch(struct perf_file_section *section __maybe_unused, - struct perf_header *ph, int fd, - void *data __maybe_unused) -{ - ph->env.arch = do_read_string(fd, ph); - return ph->env.arch ? 0 : -ENOMEM; -} - -static int process_nrcpus(struct perf_file_section *section __maybe_unused, - struct perf_header *ph, int fd, - void *data __maybe_unused) -{ - size_t ret; - u32 nr; - - ret = read(fd, &nr, sizeof(nr)); - if (ret != sizeof(nr)) - return -1; - - if (ph->needs_swap) - nr = bswap_32(nr); - - ph->env.nr_cpus_online = nr; - - ret = read(fd, &nr, sizeof(nr)); - if (ret != sizeof(nr)) - return -1; - - if (ph->needs_swap) - nr = bswap_32(nr); - - ph->env.nr_cpus_avail = nr; - return 0; -} - -static int process_cpudesc(struct perf_file_section *section __maybe_unused, - struct perf_header *ph, int fd, - void *data __maybe_unused) -{ - ph->env.cpu_desc = do_read_string(fd, ph); - return ph->env.cpu_desc ? 0 : -ENOMEM; -} - -static int process_cpuid(struct perf_file_section *section __maybe_unused, - struct perf_header *ph, int fd, - void *data __maybe_unused) -{ - ph->env.cpuid = do_read_string(fd, ph); - return ph->env.cpuid ? 0 : -ENOMEM; -} - -static int process_total_mem(struct perf_file_section *section __maybe_unused, - struct perf_header *ph, int fd, - void *data __maybe_unused) -{ - uint64_t mem; - size_t ret; - - ret = read(fd, &mem, sizeof(mem)); - if (ret != sizeof(mem)) - return -1; - - if (ph->needs_swap) - mem = bswap_64(mem); - - ph->env.total_mem = mem; - return 0; -} - -static struct perf_evsel * -perf_evlist__find_by_index(struct perf_evlist *evlist, int idx) -{ - struct perf_evsel *evsel; - - list_for_each_entry(evsel, &evlist->entries, node) { - if (evsel->idx == idx) - return evsel; - } - - return NULL; -} - -static void -perf_evlist__set_event_name(struct perf_evlist *evlist, - struct perf_evsel *event) -{ - struct perf_evsel *evsel; - - if (!event->name) - return; - - evsel = perf_evlist__find_by_index(evlist, event->idx); - if (!evsel) - return; - - if (evsel->name) - return; - - evsel->name = strdup(event->name); -} - -static int -process_event_desc(struct perf_file_section *section __maybe_unused, - struct perf_header *header, int fd, - void *data __maybe_unused) -{ - struct perf_session *session; - struct perf_evsel *evsel, *events = read_event_desc(header, fd); - - if (!events) - return 0; - - session = container_of(header, struct perf_session, header); - for (evsel = events; evsel->attr.size; evsel++) - perf_evlist__set_event_name(session->evlist, evsel); - - free_event_desc(events); - - return 0; -} - -static int process_cmdline(struct perf_file_section *section __maybe_unused, - struct perf_header *ph, int fd, - void *data __maybe_unused) -{ - size_t ret; - char *str; - u32 nr, i; - struct strbuf sb; - - ret = read(fd, &nr, sizeof(nr)); - if (ret != sizeof(nr)) - return -1; - - if (ph->needs_swap) - nr = bswap_32(nr); - - ph->env.nr_cmdline = nr; - strbuf_init(&sb, 128); - - for (i = 0; i < nr; i++) { - str = do_read_string(fd, ph); - if (!str) - goto error; - - /* include a NULL character at the end */ - strbuf_add(&sb, str, strlen(str) + 1); - free(str); - } - ph->env.cmdline = strbuf_detach(&sb, NULL); - return 0; - -error: - strbuf_release(&sb); - return -1; -} - -static int process_cpu_topology(struct perf_file_section *section __maybe_unused, - struct perf_header *ph, int fd, - void *data __maybe_unused) -{ - size_t ret; - u32 nr, i; - char *str; - struct strbuf sb; - - ret = read(fd, &nr, sizeof(nr)); - if (ret != sizeof(nr)) - return -1; - - if (ph->needs_swap) - nr = bswap_32(nr); - - ph->env.nr_sibling_cores = nr; - strbuf_init(&sb, 128); - - for (i = 0; i < nr; i++) { - str = do_read_string(fd, ph); - if (!str) - goto error; - - /* include a NULL character at the end */ - strbuf_add(&sb, str, strlen(str) + 1); - free(str); - } - ph->env.sibling_cores = strbuf_detach(&sb, NULL); - - ret = read(fd, &nr, sizeof(nr)); - if (ret != sizeof(nr)) - return -1; - - if (ph->needs_swap) - nr = bswap_32(nr); - - ph->env.nr_sibling_threads = nr; - - for (i = 0; i < nr; i++) { - str = do_read_string(fd, ph); - if (!str) - goto error; - - /* include a NULL character at the end */ - strbuf_add(&sb, str, strlen(str) + 1); - free(str); - } - ph->env.sibling_threads = strbuf_detach(&sb, NULL); - return 0; - -error: - strbuf_release(&sb); - return -1; -} - -static int process_numa_topology(struct perf_file_section *section __maybe_unused, - struct perf_header *ph, int fd, - void *data __maybe_unused) -{ - size_t ret; - u32 nr, node, i; - char *str; - uint64_t mem_total, mem_free; - struct strbuf sb; - - /* nr nodes */ - ret = read(fd, &nr, sizeof(nr)); - if (ret != sizeof(nr)) - goto error; - - if (ph->needs_swap) - nr = bswap_32(nr); - - ph->env.nr_numa_nodes = nr; - strbuf_init(&sb, 256); - - for (i = 0; i < nr; i++) { - /* node number */ - ret = read(fd, &node, sizeof(node)); - if (ret != sizeof(node)) - goto error; - - ret = read(fd, &mem_total, sizeof(u64)); - if (ret != sizeof(u64)) - goto error; - - ret = read(fd, &mem_free, sizeof(u64)); - if (ret != sizeof(u64)) - goto error; - - if (ph->needs_swap) { - node = bswap_32(node); - mem_total = bswap_64(mem_total); - mem_free = bswap_64(mem_free); - } - - strbuf_addf(&sb, "%u:%"PRIu64":%"PRIu64":", - node, mem_total, mem_free); - - str = do_read_string(fd, ph); - if (!str) - goto error; - - /* include a NULL character at the end */ - strbuf_add(&sb, str, strlen(str) + 1); - free(str); - } - ph->env.numa_nodes = strbuf_detach(&sb, NULL); - return 0; - -error: - strbuf_release(&sb); - return -1; -} - -static int process_pmu_mappings(struct perf_file_section *section __maybe_unused, - struct perf_header *ph, int fd, - void *data __maybe_unused) -{ - size_t ret; - char *name; - u32 pmu_num; - u32 type; - struct strbuf sb; - - ret = read(fd, &pmu_num, sizeof(pmu_num)); - if (ret != sizeof(pmu_num)) - return -1; - - if (ph->needs_swap) - pmu_num = bswap_32(pmu_num); - - if (!pmu_num) { - pr_debug("pmu mappings not available\n"); - return 0; - } - - ph->env.nr_pmu_mappings = pmu_num; - strbuf_init(&sb, 128); - - while (pmu_num) { - if (read(fd, &type, sizeof(type)) != sizeof(type)) - goto error; - if (ph->needs_swap) - type = bswap_32(type); - - name = do_read_string(fd, ph); - if (!name) - goto error; - - strbuf_addf(&sb, "%u:%s", type, name); - /* include a NULL character at the end */ - strbuf_add(&sb, "", 1); - - free(name); - pmu_num--; - } - ph->env.pmu_mappings = strbuf_detach(&sb, NULL); - return 0; - -error: - strbuf_release(&sb); - return -1; -} - struct feature_ops { int (*write)(int fd, struct perf_header *h, struct perf_evlist *evlist); void (*print)(struct perf_header *h, int fd, FILE *fp); int (*process)(struct perf_file_section *section, - struct perf_header *h, int fd, void *data); + struct perf_header *h, int feat, int fd, void *data); const char *name; bool full_only; }; @@ -1962,7 +1511,7 @@ struct feature_ops { .process = process_##func } #define FEAT_OPF(n, func) \ [n] = { .name = #n, .write = write_##func, .print = print_##func, \ - .process = process_##func, .full_only = true } + .full_only = true } /* feature_ops not implemented: */ #define print_tracing_data NULL @@ -1971,20 +1520,19 @@ struct feature_ops { static const struct feature_ops feat_ops[HEADER_LAST_FEATURE] = { FEAT_OPP(HEADER_TRACING_DATA, tracing_data), FEAT_OPP(HEADER_BUILD_ID, build_id), - FEAT_OPP(HEADER_HOSTNAME, hostname), - FEAT_OPP(HEADER_OSRELEASE, osrelease), - FEAT_OPP(HEADER_VERSION, version), - FEAT_OPP(HEADER_ARCH, arch), - FEAT_OPP(HEADER_NRCPUS, nrcpus), - FEAT_OPP(HEADER_CPUDESC, cpudesc), - FEAT_OPP(HEADER_CPUID, cpuid), - FEAT_OPP(HEADER_TOTAL_MEM, total_mem), - FEAT_OPP(HEADER_EVENT_DESC, event_desc), - FEAT_OPP(HEADER_CMDLINE, cmdline), + FEAT_OPA(HEADER_HOSTNAME, hostname), + FEAT_OPA(HEADER_OSRELEASE, osrelease), + FEAT_OPA(HEADER_VERSION, version), + FEAT_OPA(HEADER_ARCH, arch), + FEAT_OPA(HEADER_NRCPUS, nrcpus), + FEAT_OPA(HEADER_CPUDESC, cpudesc), + FEAT_OPA(HEADER_CPUID, cpuid), + FEAT_OPA(HEADER_TOTAL_MEM, total_mem), + FEAT_OPA(HEADER_EVENT_DESC, event_desc), + FEAT_OPA(HEADER_CMDLINE, cmdline), FEAT_OPF(HEADER_CPU_TOPOLOGY, cpu_topology), FEAT_OPF(HEADER_NUMA_TOPOLOGY, numa_topology), FEAT_OPA(HEADER_BRANCH_STACK, branch_stack), - FEAT_OPP(HEADER_PMU_MAPPINGS, pmu_mappings), }; struct header_print_data { @@ -2126,17 +1674,17 @@ int perf_session__write_header(struct perf_session *session, struct perf_file_header f_header; struct perf_file_attr f_attr; struct perf_header *header = &session->header; - struct perf_evsel *evsel, *pair = NULL; + struct perf_evsel *attr, *pair = NULL; int err; lseek(fd, sizeof(f_header), SEEK_SET); if (session->evlist != evlist) - pair = perf_evlist__first(session->evlist); + pair = list_entry(session->evlist->entries.next, struct perf_evsel, node); - list_for_each_entry(evsel, &evlist->entries, node) { - evsel->id_offset = lseek(fd, 0, SEEK_CUR); - err = do_write(fd, evsel->id, evsel->ids * sizeof(u64)); + list_for_each_entry(attr, &evlist->entries, node) { + attr->id_offset = lseek(fd, 0, SEEK_CUR); + err = do_write(fd, attr->id, attr->ids * sizeof(u64)); if (err < 0) { out_err_write: pr_debug("failed to write perf header\n"); @@ -2146,19 +1694,19 @@ int perf_session__write_header(struct perf_session *session, err = do_write(fd, pair->id, pair->ids * sizeof(u64)); if (err < 0) goto out_err_write; - evsel->ids += pair->ids; - pair = perf_evsel__next(pair); + attr->ids += pair->ids; + pair = list_entry(pair->node.next, struct perf_evsel, node); } } header->attr_offset = lseek(fd, 0, SEEK_CUR); - list_for_each_entry(evsel, &evlist->entries, node) { + list_for_each_entry(attr, &evlist->entries, node) { f_attr = (struct perf_file_attr){ - .attr = evsel->attr, + .attr = attr->attr, .ids = { - .offset = evsel->id_offset, - .size = evsel->ids * sizeof(u64), + .offset = attr->id_offset, + .size = attr->ids * sizeof(u64), } }; err = do_write(fd, &f_attr, sizeof(f_attr)); @@ -2169,9 +1717,9 @@ int perf_session__write_header(struct perf_session *session, } header->event_offset = lseek(fd, 0, SEEK_CUR); - header->event_size = trace_event_count * sizeof(struct perf_trace_event_type); - if (trace_events) { - err = do_write(fd, trace_events, header->event_size); + header->event_size = event_count * sizeof(struct perf_trace_event_type); + if (events) { + err = do_write(fd, events, header->event_size); if (err < 0) { pr_debug("failed to write perf header events\n"); return err; @@ -2272,8 +1820,6 @@ int perf_header__process_sections(struct perf_header *header, int fd, static const int attr_file_abi_sizes[] = { [0] = PERF_ATTR_SIZE_VER0, [1] = PERF_ATTR_SIZE_VER1, - [2] = PERF_ATTR_SIZE_VER2, - [3] = PERF_ATTR_SIZE_VER3, 0, }; @@ -2464,7 +2010,7 @@ static int perf_file_section__process(struct perf_file_section *section, if (!feat_ops[feat].process) return 0; - return feat_ops[feat].process(section, ph, fd, data); + return feat_ops[feat].process(section, ph, feat, fd, data); } static int perf_file_header__read_pipe(struct perf_pipe_file_header *header, @@ -2553,39 +2099,32 @@ static int read_attr(int fd, struct perf_header *ph, return ret <= 0 ? -1 : 0; } -static int perf_evsel__prepare_tracepoint_event(struct perf_evsel *evsel, - struct pevent *pevent) +static int perf_evsel__set_tracepoint_name(struct perf_evsel *evsel, + struct pevent *pevent) { - struct event_format *event; + struct event_format *event = pevent_find_event(pevent, + evsel->attr.config); char bf[128]; - /* already prepared */ - if (evsel->tp_format) - return 0; - - event = pevent_find_event(pevent, evsel->attr.config); if (event == NULL) return -1; - if (!evsel->name) { - snprintf(bf, sizeof(bf), "%s:%s", event->system, event->name); - evsel->name = strdup(bf); - if (evsel->name == NULL) - return -1; - } + snprintf(bf, sizeof(bf), "%s:%s", event->system, event->name); + evsel->name = strdup(bf); + if (event->name == NULL) + return -1; - evsel->tp_format = event; return 0; } -static int perf_evlist__prepare_tracepoint_events(struct perf_evlist *evlist, - struct pevent *pevent) +static int perf_evlist__set_tracepoint_names(struct perf_evlist *evlist, + struct pevent *pevent) { struct perf_evsel *pos; list_for_each_entry(pos, &evlist->entries, node) { if (pos->attr.type == PERF_TYPE_TRACEPOINT && - perf_evsel__prepare_tracepoint_event(pos, pevent)) + perf_evsel__set_tracepoint_name(pos, pevent)) return -1; } @@ -2628,8 +2167,6 @@ int perf_session__read_header(struct perf_session *session, int fd) if (evsel == NULL) goto out_delete_evlist; - - evsel->needs_swap = header->needs_swap; /* * Do it before so that if perf_evsel__alloc_id fails, this * entry gets purged too at perf_evlist__delete(). @@ -2661,13 +2198,13 @@ int perf_session__read_header(struct perf_session *session, int fd) if (f_header.event_types.size) { lseek(fd, f_header.event_types.offset, SEEK_SET); - trace_events = malloc(f_header.event_types.size); - if (trace_events == NULL) + events = malloc(f_header.event_types.size); + if (events == NULL) return -ENOMEM; - if (perf_header__getbuffer64(header, fd, trace_events, + if (perf_header__getbuffer64(header, fd, events, f_header.event_types.size)) goto out_errno; - trace_event_count = f_header.event_types.size / sizeof(struct perf_trace_event_type); + event_count = f_header.event_types.size / sizeof(struct perf_trace_event_type); } perf_header__process_sections(header, fd, &session->pevent, @@ -2675,8 +2212,7 @@ int perf_session__read_header(struct perf_session *session, int fd) lseek(fd, header->data_offset, SEEK_SET); - if (perf_evlist__prepare_tracepoint_events(session->evlist, - session->pevent)) + if (perf_evlist__set_tracepoint_names(session->evlist, session->pevent)) goto out_delete_evlist; header->frozen = 1; @@ -2691,7 +2227,7 @@ int perf_session__read_header(struct perf_session *session, int fd) } int perf_event__synthesize_attr(struct perf_tool *tool, - struct perf_event_attr *attr, u32 ids, u64 *id, + struct perf_event_attr *attr, u16 ids, u64 *id, perf_event__handler_t process) { union perf_event *ev; @@ -2699,7 +2235,7 @@ int perf_event__synthesize_attr(struct perf_tool *tool, int err; size = sizeof(struct perf_event_attr); - size = PERF_ALIGN(size, sizeof(u64)); + size = ALIGN(size, sizeof(u64)); size += sizeof(struct perf_event_header); size += ids * sizeof(u64); @@ -2712,12 +2248,9 @@ int perf_event__synthesize_attr(struct perf_tool *tool, memcpy(ev->attr.id, id, ids * sizeof(u64)); ev->attr.header.type = PERF_RECORD_HEADER_ATTR; - ev->attr.header.size = (u16)size; + ev->attr.header.size = size; - if (ev->attr.header.size == size) - err = process(tool, ev, NULL, NULL); - else - err = -E2BIG; + err = process(tool, ev, NULL, NULL); free(ev); @@ -2728,12 +2261,12 @@ int perf_event__synthesize_attrs(struct perf_tool *tool, struct perf_session *session, perf_event__handler_t process) { - struct perf_evsel *evsel; + struct perf_evsel *attr; int err = 0; - list_for_each_entry(evsel, &session->evlist->entries, node) { - err = perf_event__synthesize_attr(tool, &evsel->attr, evsel->ids, - evsel->id, process); + list_for_each_entry(attr, &session->evlist->entries, node) { + err = perf_event__synthesize_attr(tool, &attr->attr, attr->ids, + attr->id, process); if (err) { pr_debug("failed to create perf header attribute\n"); return err; @@ -2746,7 +2279,7 @@ int perf_event__synthesize_attrs(struct perf_tool *tool, int perf_event__process_attr(union perf_event *event, struct perf_evlist **pevlist) { - u32 i, ids, n_ids; + unsigned int i, ids, n_ids; struct perf_evsel *evsel; struct perf_evlist *evlist = *pevlist; @@ -2797,7 +2330,7 @@ int perf_event__synthesize_event_type(struct perf_tool *tool, ev.event_type.header.type = PERF_RECORD_HEADER_EVENT_TYPE; size = strlen(ev.event_type.event_type.name); - size = PERF_ALIGN(size, sizeof(u64)); + size = ALIGN(size, sizeof(u64)); ev.event_type.header.size = sizeof(ev.event_type) - (sizeof(ev.event_type.event_type.name) - size); @@ -2813,8 +2346,8 @@ int perf_event__synthesize_event_types(struct perf_tool *tool, struct perf_trace_event_type *type; int i, err = 0; - for (i = 0; i < trace_event_count; i++) { - type = &trace_events[i]; + for (i = 0; i < event_count; i++) { + type = &events[i]; err = perf_event__synthesize_event_type(tool, type->event_id, type->name, process, @@ -2828,7 +2361,7 @@ int perf_event__synthesize_event_types(struct perf_tool *tool, return err; } -int perf_event__process_event_type(struct perf_tool *tool __maybe_unused, +int perf_event__process_event_type(struct perf_tool *tool __unused, union perf_event *event) { if (perf_header__push_event(event->event_type.event_type.event_id, @@ -2845,7 +2378,7 @@ int perf_event__synthesize_tracing_data(struct perf_tool *tool, int fd, union perf_event ev; struct tracing_data *tdata; ssize_t size = 0, aligned_size = 0, padding; - int err __maybe_unused = 0; + int err __used = 0; /* * We are going to store the size of the data followed @@ -2866,7 +2399,7 @@ int perf_event__synthesize_tracing_data(struct perf_tool *tool, int fd, ev.tracing_data.header.type = PERF_RECORD_HEADER_TRACING_DATA; size = tdata->size; - aligned_size = PERF_ALIGN(size, sizeof(u64)); + aligned_size = ALIGN(size, sizeof(u64)); padding = aligned_size - size; ev.tracing_data.header.size = sizeof(ev.tracing_data); ev.tracing_data.size = aligned_size; @@ -2897,7 +2430,7 @@ int perf_event__process_tracing_data(union perf_event *event, size_read = trace_report(session->fd, &session->pevent, session->repipe); - padding = PERF_ALIGN(size_read, sizeof(u64)) - size_read; + padding = ALIGN(size_read, sizeof(u64)) - size_read; if (read(session->fd, buf, padding) < 0) die("reading input file"); @@ -2910,9 +2443,6 @@ int perf_event__process_tracing_data(union perf_event *event, if (size_read + padding != size) die("tracing data size mismatch"); - perf_evlist__prepare_tracepoint_events(session->evlist, - session->pevent); - return size_read + padding; } @@ -2931,7 +2461,7 @@ int perf_event__synthesize_build_id(struct perf_tool *tool, memset(&ev, 0, sizeof(ev)); len = pos->long_name_len + 1; - len = PERF_ALIGN(len, NAME_ALIGN); + len = ALIGN(len, NAME_ALIGN); memcpy(&ev.build_id.build_id, pos->build_id, sizeof(pos->build_id)); ev.build_id.header.type = PERF_RECORD_HEADER_BUILD_ID; ev.build_id.header.misc = misc; @@ -2944,7 +2474,7 @@ int perf_event__synthesize_build_id(struct perf_tool *tool, return err; } -int perf_event__process_build_id(struct perf_tool *tool __maybe_unused, +int perf_event__process_build_id(struct perf_tool *tool __used, union perf_event *event, struct perf_session *session) { diff --git a/trunk/tools/perf/util/header.h b/trunk/tools/perf/util/header.h index 99bdd3abce59..2d42b3e1826f 100644 --- a/trunk/tools/perf/util/header.h +++ b/trunk/tools/perf/util/header.h @@ -28,7 +28,6 @@ enum { HEADER_CPU_TOPOLOGY, HEADER_NUMA_TOPOLOGY, HEADER_BRANCH_STACK, - HEADER_PMU_MAPPINGS, HEADER_LAST_FEATURE, HEADER_FEAT_BITS = 256, }; @@ -58,29 +57,6 @@ struct perf_header; int perf_file_header__read(struct perf_file_header *header, struct perf_header *ph, int fd); -struct perf_session_env { - char *hostname; - char *os_release; - char *version; - char *arch; - int nr_cpus_online; - int nr_cpus_avail; - char *cpu_desc; - char *cpuid; - unsigned long long total_mem; - - int nr_cmdline; - char *cmdline; - int nr_sibling_cores; - char *sibling_cores; - int nr_sibling_threads; - char *sibling_threads; - int nr_numa_nodes; - char *numa_nodes; - int nr_pmu_mappings; - char *pmu_mappings; -}; - struct perf_header { int frozen; bool needs_swap; @@ -90,7 +66,6 @@ struct perf_header { u64 event_offset; u64 event_size; DECLARE_BITMAP(adds_features, HEADER_FEAT_BITS); - struct perf_session_env env; }; struct perf_evlist; @@ -120,11 +95,11 @@ int perf_header__process_sections(struct perf_header *header, int fd, int perf_header__fprintf_info(struct perf_session *s, FILE *fp, bool full); int build_id_cache__add_s(const char *sbuild_id, const char *debugdir, - const char *name, bool is_kallsyms, bool is_vdso); + const char *name, bool is_kallsyms); int build_id_cache__remove_s(const char *sbuild_id, const char *debugdir); int perf_event__synthesize_attr(struct perf_tool *tool, - struct perf_event_attr *attr, u32 ids, u64 *id, + struct perf_event_attr *attr, u16 ids, u64 *id, perf_event__handler_t process); int perf_event__synthesize_attrs(struct perf_tool *tool, struct perf_session *session, diff --git a/trunk/tools/perf/util/help.c b/trunk/tools/perf/util/help.c index 8b1f6e891b8a..6f2975a00358 100644 --- a/trunk/tools/perf/util/help.c +++ b/trunk/tools/perf/util/help.c @@ -3,7 +3,6 @@ #include "exec_cmd.h" #include "levenshtein.h" #include "help.h" -#include void add_cmdname(struct cmdnames *cmds, const char *name, size_t len) { @@ -332,8 +331,7 @@ const char *help_unknown_cmd(const char *cmd) exit(1); } -int cmd_version(int argc __maybe_unused, const char **argv __maybe_unused, - const char *prefix __maybe_unused) +int cmd_version(int argc __used, const char **argv __used, const char *prefix __used) { printf("perf version %s\n", perf_version_string); return 0; diff --git a/trunk/tools/perf/util/hist.c b/trunk/tools/perf/util/hist.c index 236bc9d98ff2..f247ef2789a4 100644 --- a/trunk/tools/perf/util/hist.c +++ b/trunk/tools/perf/util/hist.c @@ -45,7 +45,7 @@ bool hists__new_col_len(struct hists *hists, enum hist_column col, u16 len) return false; } -void hists__reset_col_len(struct hists *hists) +static void hists__reset_col_len(struct hists *hists) { enum hist_column col; @@ -63,7 +63,7 @@ static void hists__set_unres_dso_col_len(struct hists *hists, int dso) hists__set_col_len(hists, dso, unresolved_col_width); } -void hists__calc_col_len(struct hists *hists, struct hist_entry *h) +static void hists__calc_col_len(struct hists *hists, struct hist_entry *h) { const unsigned int unresolved_col_width = BITS_PER_LONG / 4; u16 len; @@ -114,22 +114,6 @@ void hists__calc_col_len(struct hists *hists, struct hist_entry *h) } } -void hists__output_recalc_col_len(struct hists *hists, int max_rows) -{ - struct rb_node *next = rb_first(&hists->entries); - struct hist_entry *n; - int row = 0; - - hists__reset_col_len(hists); - - while (next && row++ < max_rows) { - n = rb_entry(next, struct hist_entry, rb_node); - if (!n->filtered) - hists__calc_col_len(hists, n); - next = rb_next(&n->rb_node); - } -} - static void hist_entry__add_cpumode_period(struct hist_entry *he, unsigned int cpumode, u64 period) { @@ -394,7 +378,7 @@ void hist_entry__free(struct hist_entry *he) * collapse the histogram */ -static bool hists__collapse_insert_entry(struct hists *hists __maybe_unused, +static bool hists__collapse_insert_entry(struct hists *hists __used, struct rb_root *root, struct hist_entry *he) { @@ -410,13 +394,8 @@ static bool hists__collapse_insert_entry(struct hists *hists __maybe_unused, cmp = hist_entry__collapse(iter, he); if (!cmp) { - iter->period += he->period; - iter->period_sys += he->period_sys; - iter->period_us += he->period_us; - iter->period_guest_sys += he->period_guest_sys; - iter->period_guest_us += he->period_guest_us; - iter->nr_events += he->nr_events; - + iter->period += he->period; + iter->nr_events += he->nr_events; if (symbol_conf.use_callchain) { callchain_cursor_reset(&callchain_cursor); callchain_merge(&callchain_cursor, @@ -568,6 +547,674 @@ void hists__output_resort_threaded(struct hists *hists) return __hists__output_resort(hists, true); } +static size_t callchain__fprintf_left_margin(FILE *fp, int left_margin) +{ + int i; + int ret = fprintf(fp, " "); + + for (i = 0; i < left_margin; i++) + ret += fprintf(fp, " "); + + return ret; +} + +static size_t ipchain__fprintf_graph_line(FILE *fp, int depth, int depth_mask, + int left_margin) +{ + int i; + size_t ret = callchain__fprintf_left_margin(fp, left_margin); + + for (i = 0; i < depth; i++) + if (depth_mask & (1 << i)) + ret += fprintf(fp, "| "); + else + ret += fprintf(fp, " "); + + ret += fprintf(fp, "\n"); + + return ret; +} + +static size_t ipchain__fprintf_graph(FILE *fp, struct callchain_list *chain, + int depth, int depth_mask, int period, + u64 total_samples, u64 hits, + int left_margin) +{ + int i; + size_t ret = 0; + + ret += callchain__fprintf_left_margin(fp, left_margin); + for (i = 0; i < depth; i++) { + if (depth_mask & (1 << i)) + ret += fprintf(fp, "|"); + else + ret += fprintf(fp, " "); + if (!period && i == depth - 1) { + double percent; + + percent = hits * 100.0 / total_samples; + ret += percent_color_fprintf(fp, "--%2.2f%%-- ", percent); + } else + ret += fprintf(fp, "%s", " "); + } + if (chain->ms.sym) + ret += fprintf(fp, "%s\n", chain->ms.sym->name); + else + ret += fprintf(fp, "0x%0" PRIx64 "\n", chain->ip); + + return ret; +} + +static struct symbol *rem_sq_bracket; +static struct callchain_list rem_hits; + +static void init_rem_hits(void) +{ + rem_sq_bracket = malloc(sizeof(*rem_sq_bracket) + 6); + if (!rem_sq_bracket) { + fprintf(stderr, "Not enough memory to display remaining hits\n"); + return; + } + + strcpy(rem_sq_bracket->name, "[...]"); + rem_hits.ms.sym = rem_sq_bracket; +} + +static size_t __callchain__fprintf_graph(FILE *fp, struct rb_root *root, + u64 total_samples, int depth, + int depth_mask, int left_margin) +{ + struct rb_node *node, *next; + struct callchain_node *child; + struct callchain_list *chain; + int new_depth_mask = depth_mask; + u64 remaining; + size_t ret = 0; + int i; + uint entries_printed = 0; + + remaining = total_samples; + + node = rb_first(root); + while (node) { + u64 new_total; + u64 cumul; + + child = rb_entry(node, struct callchain_node, rb_node); + cumul = callchain_cumul_hits(child); + remaining -= cumul; + + /* + * The depth mask manages the output of pipes that show + * the depth. We don't want to keep the pipes of the current + * level for the last child of this depth. + * Except if we have remaining filtered hits. They will + * supersede the last child + */ + next = rb_next(node); + if (!next && (callchain_param.mode != CHAIN_GRAPH_REL || !remaining)) + new_depth_mask &= ~(1 << (depth - 1)); + + /* + * But we keep the older depth mask for the line separator + * to keep the level link until we reach the last child + */ + ret += ipchain__fprintf_graph_line(fp, depth, depth_mask, + left_margin); + i = 0; + list_for_each_entry(chain, &child->val, list) { + ret += ipchain__fprintf_graph(fp, chain, depth, + new_depth_mask, i++, + total_samples, + cumul, + left_margin); + } + + if (callchain_param.mode == CHAIN_GRAPH_REL) + new_total = child->children_hit; + else + new_total = total_samples; + + ret += __callchain__fprintf_graph(fp, &child->rb_root, new_total, + depth + 1, + new_depth_mask | (1 << depth), + left_margin); + node = next; + if (++entries_printed == callchain_param.print_limit) + break; + } + + if (callchain_param.mode == CHAIN_GRAPH_REL && + remaining && remaining != total_samples) { + + if (!rem_sq_bracket) + return ret; + + new_depth_mask &= ~(1 << (depth - 1)); + ret += ipchain__fprintf_graph(fp, &rem_hits, depth, + new_depth_mask, 0, total_samples, + remaining, left_margin); + } + + return ret; +} + +static size_t callchain__fprintf_graph(FILE *fp, struct rb_root *root, + u64 total_samples, int left_margin) +{ + struct callchain_node *cnode; + struct callchain_list *chain; + u32 entries_printed = 0; + bool printed = false; + struct rb_node *node; + int i = 0; + int ret = 0; + + /* + * If have one single callchain root, don't bother printing + * its percentage (100 % in fractal mode and the same percentage + * than the hist in graph mode). This also avoid one level of column. + */ + node = rb_first(root); + if (node && !rb_next(node)) { + cnode = rb_entry(node, struct callchain_node, rb_node); + list_for_each_entry(chain, &cnode->val, list) { + /* + * If we sort by symbol, the first entry is the same than + * the symbol. No need to print it otherwise it appears as + * displayed twice. + */ + if (!i++ && sort__first_dimension == SORT_SYM) + continue; + if (!printed) { + ret += callchain__fprintf_left_margin(fp, left_margin); + ret += fprintf(fp, "|\n"); + ret += callchain__fprintf_left_margin(fp, left_margin); + ret += fprintf(fp, "---"); + left_margin += 3; + printed = true; + } else + ret += callchain__fprintf_left_margin(fp, left_margin); + + if (chain->ms.sym) + ret += fprintf(fp, " %s\n", chain->ms.sym->name); + else + ret += fprintf(fp, " %p\n", (void *)(long)chain->ip); + + if (++entries_printed == callchain_param.print_limit) + break; + } + root = &cnode->rb_root; + } + + ret += __callchain__fprintf_graph(fp, root, total_samples, + 1, 1, left_margin); + ret += fprintf(fp, "\n"); + + return ret; +} + +static size_t __callchain__fprintf_flat(FILE *fp, + struct callchain_node *self, + u64 total_samples) +{ + struct callchain_list *chain; + size_t ret = 0; + + if (!self) + return 0; + + ret += __callchain__fprintf_flat(fp, self->parent, total_samples); + + + list_for_each_entry(chain, &self->val, list) { + if (chain->ip >= PERF_CONTEXT_MAX) + continue; + if (chain->ms.sym) + ret += fprintf(fp, " %s\n", chain->ms.sym->name); + else + ret += fprintf(fp, " %p\n", + (void *)(long)chain->ip); + } + + return ret; +} + +static size_t callchain__fprintf_flat(FILE *fp, struct rb_root *self, + u64 total_samples) +{ + size_t ret = 0; + u32 entries_printed = 0; + struct rb_node *rb_node; + struct callchain_node *chain; + + rb_node = rb_first(self); + while (rb_node) { + double percent; + + chain = rb_entry(rb_node, struct callchain_node, rb_node); + percent = chain->hit * 100.0 / total_samples; + + ret = percent_color_fprintf(fp, " %6.2f%%\n", percent); + ret += __callchain__fprintf_flat(fp, chain, total_samples); + ret += fprintf(fp, "\n"); + if (++entries_printed == callchain_param.print_limit) + break; + + rb_node = rb_next(rb_node); + } + + return ret; +} + +static size_t hist_entry_callchain__fprintf(struct hist_entry *he, + u64 total_samples, int left_margin, + FILE *fp) +{ + switch (callchain_param.mode) { + case CHAIN_GRAPH_REL: + return callchain__fprintf_graph(fp, &he->sorted_chain, he->period, + left_margin); + break; + case CHAIN_GRAPH_ABS: + return callchain__fprintf_graph(fp, &he->sorted_chain, total_samples, + left_margin); + break; + case CHAIN_FLAT: + return callchain__fprintf_flat(fp, &he->sorted_chain, total_samples); + break; + case CHAIN_NONE: + break; + default: + pr_err("Bad callchain mode\n"); + } + + return 0; +} + +void hists__output_recalc_col_len(struct hists *hists, int max_rows) +{ + struct rb_node *next = rb_first(&hists->entries); + struct hist_entry *n; + int row = 0; + + hists__reset_col_len(hists); + + while (next && row++ < max_rows) { + n = rb_entry(next, struct hist_entry, rb_node); + if (!n->filtered) + hists__calc_col_len(hists, n); + next = rb_next(&n->rb_node); + } +} + +static int hist_entry__pcnt_snprintf(struct hist_entry *he, char *s, + size_t size, struct hists *pair_hists, + bool show_displacement, long displacement, + bool color, u64 total_period) +{ + u64 period, total, period_sys, period_us, period_guest_sys, period_guest_us; + u64 nr_events; + const char *sep = symbol_conf.field_sep; + int ret; + + if (symbol_conf.exclude_other && !he->parent) + return 0; + + if (pair_hists) { + period = he->pair ? he->pair->period : 0; + nr_events = he->pair ? he->pair->nr_events : 0; + total = pair_hists->stats.total_period; + period_sys = he->pair ? he->pair->period_sys : 0; + period_us = he->pair ? he->pair->period_us : 0; + period_guest_sys = he->pair ? he->pair->period_guest_sys : 0; + period_guest_us = he->pair ? he->pair->period_guest_us : 0; + } else { + period = he->period; + nr_events = he->nr_events; + total = total_period; + period_sys = he->period_sys; + period_us = he->period_us; + period_guest_sys = he->period_guest_sys; + period_guest_us = he->period_guest_us; + } + + if (total) { + if (color) + ret = percent_color_snprintf(s, size, + sep ? "%.2f" : " %6.2f%%", + (period * 100.0) / total); + else + ret = scnprintf(s, size, sep ? "%.2f" : " %6.2f%%", + (period * 100.0) / total); + if (symbol_conf.show_cpu_utilization) { + ret += percent_color_snprintf(s + ret, size - ret, + sep ? "%.2f" : " %6.2f%%", + (period_sys * 100.0) / total); + ret += percent_color_snprintf(s + ret, size - ret, + sep ? "%.2f" : " %6.2f%%", + (period_us * 100.0) / total); + if (perf_guest) { + ret += percent_color_snprintf(s + ret, + size - ret, + sep ? "%.2f" : " %6.2f%%", + (period_guest_sys * 100.0) / + total); + ret += percent_color_snprintf(s + ret, + size - ret, + sep ? "%.2f" : " %6.2f%%", + (period_guest_us * 100.0) / + total); + } + } + } else + ret = scnprintf(s, size, sep ? "%" PRIu64 : "%12" PRIu64 " ", period); + + if (symbol_conf.show_nr_samples) { + if (sep) + ret += scnprintf(s + ret, size - ret, "%c%" PRIu64, *sep, nr_events); + else + ret += scnprintf(s + ret, size - ret, "%11" PRIu64, nr_events); + } + + if (symbol_conf.show_total_period) { + if (sep) + ret += scnprintf(s + ret, size - ret, "%c%" PRIu64, *sep, period); + else + ret += scnprintf(s + ret, size - ret, " %12" PRIu64, period); + } + + if (pair_hists) { + char bf[32]; + double old_percent = 0, new_percent = 0, diff; + + if (total > 0) + old_percent = (period * 100.0) / total; + if (total_period > 0) + new_percent = (he->period * 100.0) / total_period; + + diff = new_percent - old_percent; + + if (fabs(diff) >= 0.01) + scnprintf(bf, sizeof(bf), "%+4.2F%%", diff); + else + scnprintf(bf, sizeof(bf), " "); + + if (sep) + ret += scnprintf(s + ret, size - ret, "%c%s", *sep, bf); + else + ret += scnprintf(s + ret, size - ret, "%11.11s", bf); + + if (show_displacement) { + if (displacement) + scnprintf(bf, sizeof(bf), "%+4ld", displacement); + else + scnprintf(bf, sizeof(bf), " "); + + if (sep) + ret += scnprintf(s + ret, size - ret, "%c%s", *sep, bf); + else + ret += scnprintf(s + ret, size - ret, "%6.6s", bf); + } + } + + return ret; +} + +int hist_entry__snprintf(struct hist_entry *he, char *s, size_t size, + struct hists *hists) +{ + const char *sep = symbol_conf.field_sep; + struct sort_entry *se; + int ret = 0; + + list_for_each_entry(se, &hist_entry__sort_list, list) { + if (se->elide) + continue; + + ret += scnprintf(s + ret, size - ret, "%s", sep ?: " "); + ret += se->se_snprintf(he, s + ret, size - ret, + hists__col_len(hists, se->se_width_idx)); + } + + return ret; +} + +static int hist_entry__fprintf(struct hist_entry *he, size_t size, + struct hists *hists, struct hists *pair_hists, + bool show_displacement, long displacement, + u64 total_period, FILE *fp) +{ + char bf[512]; + int ret; + + if (size == 0 || size > sizeof(bf)) + size = sizeof(bf); + + ret = hist_entry__pcnt_snprintf(he, bf, size, pair_hists, + show_displacement, displacement, + true, total_period); + hist_entry__snprintf(he, bf + ret, size - ret, hists); + return fprintf(fp, "%s\n", bf); +} + +static size_t hist_entry__fprintf_callchain(struct hist_entry *he, + struct hists *hists, + u64 total_period, FILE *fp) +{ + int left_margin = 0; + + if (sort__first_dimension == SORT_COMM) { + struct sort_entry *se = list_first_entry(&hist_entry__sort_list, + typeof(*se), list); + left_margin = hists__col_len(hists, se->se_width_idx); + left_margin -= thread__comm_len(he->thread); + } + + return hist_entry_callchain__fprintf(he, total_period, left_margin, fp); +} + +size_t hists__fprintf(struct hists *hists, struct hists *pair, + bool show_displacement, bool show_header, int max_rows, + int max_cols, FILE *fp) +{ + struct sort_entry *se; + struct rb_node *nd; + size_t ret = 0; + u64 total_period; + unsigned long position = 1; + long displacement = 0; + unsigned int width; + const char *sep = symbol_conf.field_sep; + const char *col_width = symbol_conf.col_width_list_str; + int nr_rows = 0; + + init_rem_hits(); + + if (!show_header) + goto print_entries; + + fprintf(fp, "# %s", pair ? "Baseline" : "Overhead"); + + if (symbol_conf.show_cpu_utilization) { + if (sep) { + ret += fprintf(fp, "%csys", *sep); + ret += fprintf(fp, "%cus", *sep); + if (perf_guest) { + ret += fprintf(fp, "%cguest sys", *sep); + ret += fprintf(fp, "%cguest us", *sep); + } + } else { + ret += fprintf(fp, " sys "); + ret += fprintf(fp, " us "); + if (perf_guest) { + ret += fprintf(fp, " guest sys "); + ret += fprintf(fp, " guest us "); + } + } + } + + if (symbol_conf.show_nr_samples) { + if (sep) + fprintf(fp, "%cSamples", *sep); + else + fputs(" Samples ", fp); + } + + if (symbol_conf.show_total_period) { + if (sep) + ret += fprintf(fp, "%cPeriod", *sep); + else + ret += fprintf(fp, " Period "); + } + + if (pair) { + if (sep) + ret += fprintf(fp, "%cDelta", *sep); + else + ret += fprintf(fp, " Delta "); + + if (show_displacement) { + if (sep) + ret += fprintf(fp, "%cDisplacement", *sep); + else + ret += fprintf(fp, " Displ"); + } + } + + list_for_each_entry(se, &hist_entry__sort_list, list) { + if (se->elide) + continue; + if (sep) { + fprintf(fp, "%c%s", *sep, se->se_header); + continue; + } + width = strlen(se->se_header); + if (symbol_conf.col_width_list_str) { + if (col_width) { + hists__set_col_len(hists, se->se_width_idx, + atoi(col_width)); + col_width = strchr(col_width, ','); + if (col_width) + ++col_width; + } + } + if (!hists__new_col_len(hists, se->se_width_idx, width)) + width = hists__col_len(hists, se->se_width_idx); + fprintf(fp, " %*s", width, se->se_header); + } + + fprintf(fp, "\n"); + if (max_rows && ++nr_rows >= max_rows) + goto out; + + if (sep) + goto print_entries; + + fprintf(fp, "# ........"); + if (symbol_conf.show_cpu_utilization) + fprintf(fp, " ....... ......."); + if (symbol_conf.show_nr_samples) + fprintf(fp, " .........."); + if (symbol_conf.show_total_period) + fprintf(fp, " ............"); + if (pair) { + fprintf(fp, " .........."); + if (show_displacement) + fprintf(fp, " ....."); + } + list_for_each_entry(se, &hist_entry__sort_list, list) { + unsigned int i; + + if (se->elide) + continue; + + fprintf(fp, " "); + width = hists__col_len(hists, se->se_width_idx); + if (width == 0) + width = strlen(se->se_header); + for (i = 0; i < width; i++) + fprintf(fp, "."); + } + + fprintf(fp, "\n"); + if (max_rows && ++nr_rows >= max_rows) + goto out; + + fprintf(fp, "#\n"); + if (max_rows && ++nr_rows >= max_rows) + goto out; + +print_entries: + total_period = hists->stats.total_period; + + for (nd = rb_first(&hists->entries); nd; nd = rb_next(nd)) { + struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node); + + if (h->filtered) + continue; + + if (show_displacement) { + if (h->pair != NULL) + displacement = ((long)h->pair->position - + (long)position); + else + displacement = 0; + ++position; + } + ret += hist_entry__fprintf(h, max_cols, hists, pair, show_displacement, + displacement, total_period, fp); + + if (symbol_conf.use_callchain) + ret += hist_entry__fprintf_callchain(h, hists, total_period, fp); + if (max_rows && ++nr_rows >= max_rows) + goto out; + + if (h->ms.map == NULL && verbose > 1) { + __map_groups__fprintf_maps(&h->thread->mg, + MAP__FUNCTION, verbose, fp); + fprintf(fp, "%.10s end\n", graph_dotted_line); + } + } +out: + free(rem_sq_bracket); + + return ret; +} + +/* + * See hists__fprintf to match the column widths + */ +unsigned int hists__sort_list_width(struct hists *hists) +{ + struct sort_entry *se; + int ret = 9; /* total % */ + + if (symbol_conf.show_cpu_utilization) { + ret += 7; /* count_sys % */ + ret += 6; /* count_us % */ + if (perf_guest) { + ret += 13; /* count_guest_sys % */ + ret += 12; /* count_guest_us % */ + } + } + + if (symbol_conf.show_nr_samples) + ret += 11; + + if (symbol_conf.show_total_period) + ret += 13; + + list_for_each_entry(se, &hist_entry__sort_list, list) + if (!se->elide) + ret += 2 + hists__col_len(hists, se->se_width_idx); + + if (verbose) /* Addr + origin */ + ret += 3 + BITS_PER_LONG / 4; + + return ret; +} + static void hists__remove_entry_filter(struct hists *hists, struct hist_entry *h, enum hist_filter filter) { @@ -695,3 +1342,25 @@ void hists__inc_nr_events(struct hists *hists, u32 type) ++hists->stats.nr_events[0]; ++hists->stats.nr_events[type]; } + +size_t hists__fprintf_nr_events(struct hists *hists, FILE *fp) +{ + int i; + size_t ret = 0; + + for (i = 0; i < PERF_RECORD_HEADER_MAX; ++i) { + const char *name; + + if (hists->stats.nr_events[i] == 0) + continue; + + name = perf_event__name(i); + if (!strcmp(name, "UNKNOWN")) + continue; + + ret += fprintf(fp, "%16s events: %10d\n", name, + hists->stats.nr_events[i]); + } + + return ret; +} diff --git a/trunk/tools/perf/util/hist.h b/trunk/tools/perf/util/hist.h index f011ad4756e8..0b096c27a419 100644 --- a/trunk/tools/perf/util/hist.h +++ b/trunk/tools/perf/util/hist.h @@ -75,8 +75,8 @@ struct hist_entry *__hists__add_entry(struct hists *self, struct symbol *parent, u64 period); int64_t hist_entry__cmp(struct hist_entry *left, struct hist_entry *right); int64_t hist_entry__collapse(struct hist_entry *left, struct hist_entry *right); -int hist_entry__sort_snprintf(struct hist_entry *self, char *bf, size_t size, - struct hists *hists); +int hist_entry__snprintf(struct hist_entry *self, char *bf, size_t size, + struct hists *hists); void hist_entry__free(struct hist_entry *); struct hist_entry *__hists__add_branch_entry(struct hists *self, @@ -112,66 +112,25 @@ void hists__filter_by_symbol(struct hists *hists); u16 hists__col_len(struct hists *self, enum hist_column col); void hists__set_col_len(struct hists *self, enum hist_column col, u16 len); bool hists__new_col_len(struct hists *self, enum hist_column col, u16 len); -void hists__reset_col_len(struct hists *hists); -void hists__calc_col_len(struct hists *hists, struct hist_entry *he); - -struct perf_hpp { - char *buf; - size_t size; - u64 total_period; - const char *sep; - long displacement; - void *ptr; -}; - -struct perf_hpp_fmt { - bool cond; - int (*header)(struct perf_hpp *hpp); - int (*width)(struct perf_hpp *hpp); - int (*color)(struct perf_hpp *hpp, struct hist_entry *he); - int (*entry)(struct perf_hpp *hpp, struct hist_entry *he); -}; - -extern struct perf_hpp_fmt perf_hpp__format[]; - -enum { - PERF_HPP__OVERHEAD, - PERF_HPP__OVERHEAD_SYS, - PERF_HPP__OVERHEAD_US, - PERF_HPP__OVERHEAD_GUEST_SYS, - PERF_HPP__OVERHEAD_GUEST_US, - PERF_HPP__SAMPLES, - PERF_HPP__PERIOD, - PERF_HPP__DELTA, - PERF_HPP__DISPL, - - PERF_HPP__MAX_INDEX -}; - -void perf_hpp__init(bool need_pair, bool show_displacement); -int hist_entry__period_snprintf(struct perf_hpp *hpp, struct hist_entry *he, - bool color); struct perf_evlist; #ifdef NO_NEWT_SUPPORT static inline -int perf_evlist__tui_browse_hists(struct perf_evlist *evlist __maybe_unused, - const char *help __maybe_unused, - void(*timer)(void *arg) __maybe_unused, - void *arg __maybe_unused, - int refresh __maybe_unused) +int perf_evlist__tui_browse_hists(struct perf_evlist *evlist __used, + const char *help __used, + void(*timer)(void *arg) __used, + void *arg __used, + int refresh __used) { return 0; } -static inline int hist_entry__tui_annotate(struct hist_entry *self - __maybe_unused, - int evidx __maybe_unused, - void(*timer)(void *arg) - __maybe_unused, - void *arg __maybe_unused, - int delay_secs __maybe_unused) +static inline int hist_entry__tui_annotate(struct hist_entry *self __used, + int evidx __used, + void(*timer)(void *arg) __used, + void *arg __used, + int delay_secs __used) { return 0; } @@ -189,11 +148,11 @@ int perf_evlist__tui_browse_hists(struct perf_evlist *evlist, const char *help, #ifdef NO_GTK2_SUPPORT static inline -int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist __maybe_unused, - const char *help __maybe_unused, - void(*timer)(void *arg) __maybe_unused, - void *arg __maybe_unused, - int refresh __maybe_unused) +int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist __used, + const char *help __used, + void(*timer)(void *arg) __used, + void *arg __used, + int refresh __used) { return 0; } diff --git a/trunk/tools/perf/util/include/linux/bitops.h b/trunk/tools/perf/util/include/linux/bitops.h index a55d8cf083c9..587a230d2075 100644 --- a/trunk/tools/perf/util/include/linux/bitops.h +++ b/trunk/tools/perf/util/include/linux/bitops.h @@ -5,10 +5,6 @@ #include #include -#ifndef __WORDSIZE -#define __WORDSIZE (__SIZEOF_LONG__ * 8) -#endif - #define BITS_PER_LONG __WORDSIZE #define BITS_PER_BYTE 8 #define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long)) diff --git a/trunk/tools/perf/util/include/linux/compiler.h b/trunk/tools/perf/util/include/linux/compiler.h index 96b919dae11c..547628e97f3d 100644 --- a/trunk/tools/perf/util/include/linux/compiler.h +++ b/trunk/tools/perf/util/include/linux/compiler.h @@ -9,13 +9,6 @@ #define __attribute_const__ #endif -#ifndef __maybe_unused -#define __maybe_unused __attribute__((unused)) -#endif -#define __packed __attribute__((__packed__)) - -#ifndef __force -#define __force -#endif +#define __used __attribute__((__unused__)) #endif diff --git a/trunk/tools/perf/util/include/linux/kernel.h b/trunk/tools/perf/util/include/linux/kernel.h index d8c927c868ee..b6842c1d02a8 100644 --- a/trunk/tools/perf/util/include/linux/kernel.h +++ b/trunk/tools/perf/util/include/linux/kernel.h @@ -8,8 +8,8 @@ #define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d)) -#define PERF_ALIGN(x, a) __PERF_ALIGN_MASK(x, (typeof(x))(a)-1) -#define __PERF_ALIGN_MASK(x, mask) (((x)+(mask))&~(mask)) +#define ALIGN(x,a) __ALIGN_MASK(x,(typeof(x))(a)-1) +#define __ALIGN_MASK(x,mask) (((x)+(mask))&~(mask)) #ifndef offsetof #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) @@ -46,22 +46,9 @@ _min1 < _min2 ? _min1 : _min2; }) #endif -#ifndef roundup -#define roundup(x, y) ( \ -{ \ - const typeof(y) __y = y; \ - (((x) + (__y - 1)) / __y) * __y; \ -} \ -) -#endif - #ifndef BUG_ON -#ifdef NDEBUG -#define BUG_ON(cond) do { if (cond) {} } while (0) -#else #define BUG_ON(cond) assert(!(cond)) #endif -#endif /* * Both need more care to handle endianness diff --git a/trunk/tools/perf/util/include/linux/magic.h b/trunk/tools/perf/util/include/linux/magic.h deleted file mode 100644 index 58b64ed4da12..000000000000 --- a/trunk/tools/perf/util/include/linux/magic.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef _PERF_LINUX_MAGIC_H_ -#define _PERF_LINUX_MAGIC_H_ - -#ifndef DEBUGFS_MAGIC -#define DEBUGFS_MAGIC 0x64626720 -#endif - -#ifndef SYSFS_MAGIC -#define SYSFS_MAGIC 0x62656572 -#endif - -#endif diff --git a/trunk/tools/perf/util/include/linux/rbtree.h b/trunk/tools/perf/util/include/linux/rbtree.h index 2a030c5af3aa..7a243a143037 100644 --- a/trunk/tools/perf/util/include/linux/rbtree.h +++ b/trunk/tools/perf/util/include/linux/rbtree.h @@ -1,2 +1 @@ -#include #include "../../../../include/linux/rbtree.h" diff --git a/trunk/tools/perf/util/include/linux/string.h b/trunk/tools/perf/util/include/linux/string.h index 6f19c548ecc0..3b2f5900276f 100644 --- a/trunk/tools/perf/util/include/linux/string.h +++ b/trunk/tools/perf/util/include/linux/string.h @@ -1,3 +1 @@ #include - -void *memdup(const void *src, size_t len); diff --git a/trunk/tools/perf/util/include/linux/types.h b/trunk/tools/perf/util/include/linux/types.h index eb464786c084..12de3b8112f9 100644 --- a/trunk/tools/perf/util/include/linux/types.h +++ b/trunk/tools/perf/util/include/linux/types.h @@ -3,14 +3,6 @@ #include -#ifndef __bitwise -#define __bitwise -#endif - -#ifndef __le32 -typedef __u32 __bitwise __le32; -#endif - #define DECLARE_BITMAP(name,bits) \ unsigned long name[BITS_TO_LONGS(bits)] diff --git a/trunk/tools/perf/util/intlist.c b/trunk/tools/perf/util/intlist.c deleted file mode 100644 index 9d0740024ba8..000000000000 --- a/trunk/tools/perf/util/intlist.c +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Based on intlist.c by: - * (c) 2009 Arnaldo Carvalho de Melo - * - * Licensed under the GPLv2. - */ - -#include -#include -#include - -#include "intlist.h" - -static struct rb_node *intlist__node_new(struct rblist *rblist __maybe_unused, - const void *entry) -{ - int i = (int)((long)entry); - struct rb_node *rc = NULL; - struct int_node *node = malloc(sizeof(*node)); - - if (node != NULL) { - node->i = i; - rc = &node->rb_node; - } - - return rc; -} - -static void int_node__delete(struct int_node *ilist) -{ - free(ilist); -} - -static void intlist__node_delete(struct rblist *rblist __maybe_unused, - struct rb_node *rb_node) -{ - struct int_node *node = container_of(rb_node, struct int_node, rb_node); - - int_node__delete(node); -} - -static int intlist__node_cmp(struct rb_node *rb_node, const void *entry) -{ - int i = (int)((long)entry); - struct int_node *node = container_of(rb_node, struct int_node, rb_node); - - return node->i - i; -} - -int intlist__add(struct intlist *ilist, int i) -{ - return rblist__add_node(&ilist->rblist, (void *)((long)i)); -} - -void intlist__remove(struct intlist *ilist, struct int_node *node) -{ - rblist__remove_node(&ilist->rblist, &node->rb_node); -} - -struct int_node *intlist__find(struct intlist *ilist, int i) -{ - struct int_node *node = NULL; - struct rb_node *rb_node = rblist__find(&ilist->rblist, (void *)((long)i)); - - if (rb_node) - node = container_of(rb_node, struct int_node, rb_node); - - return node; -} - -struct intlist *intlist__new(void) -{ - struct intlist *ilist = malloc(sizeof(*ilist)); - - if (ilist != NULL) { - rblist__init(&ilist->rblist); - ilist->rblist.node_cmp = intlist__node_cmp; - ilist->rblist.node_new = intlist__node_new; - ilist->rblist.node_delete = intlist__node_delete; - } - - return ilist; -} - -void intlist__delete(struct intlist *ilist) -{ - if (ilist != NULL) - rblist__delete(&ilist->rblist); -} - -struct int_node *intlist__entry(const struct intlist *ilist, unsigned int idx) -{ - struct int_node *node = NULL; - struct rb_node *rb_node; - - rb_node = rblist__entry(&ilist->rblist, idx); - if (rb_node) - node = container_of(rb_node, struct int_node, rb_node); - - return node; -} diff --git a/trunk/tools/perf/util/intlist.h b/trunk/tools/perf/util/intlist.h deleted file mode 100644 index 6d63ab90db50..000000000000 --- a/trunk/tools/perf/util/intlist.h +++ /dev/null @@ -1,75 +0,0 @@ -#ifndef __PERF_INTLIST_H -#define __PERF_INTLIST_H - -#include -#include - -#include "rblist.h" - -struct int_node { - struct rb_node rb_node; - int i; -}; - -struct intlist { - struct rblist rblist; -}; - -struct intlist *intlist__new(void); -void intlist__delete(struct intlist *ilist); - -void intlist__remove(struct intlist *ilist, struct int_node *in); -int intlist__add(struct intlist *ilist, int i); - -struct int_node *intlist__entry(const struct intlist *ilist, unsigned int idx); -struct int_node *intlist__find(struct intlist *ilist, int i); - -static inline bool intlist__has_entry(struct intlist *ilist, int i) -{ - return intlist__find(ilist, i) != NULL; -} - -static inline bool intlist__empty(const struct intlist *ilist) -{ - return rblist__empty(&ilist->rblist); -} - -static inline unsigned int intlist__nr_entries(const struct intlist *ilist) -{ - return rblist__nr_entries(&ilist->rblist); -} - -/* For intlist iteration */ -static inline struct int_node *intlist__first(struct intlist *ilist) -{ - struct rb_node *rn = rb_first(&ilist->rblist.entries); - return rn ? rb_entry(rn, struct int_node, rb_node) : NULL; -} -static inline struct int_node *intlist__next(struct int_node *in) -{ - struct rb_node *rn; - if (!in) - return NULL; - rn = rb_next(&in->rb_node); - return rn ? rb_entry(rn, struct int_node, rb_node) : NULL; -} - -/** - * intlist_for_each - iterate over a intlist - * @pos: the &struct int_node to use as a loop cursor. - * @ilist: the &struct intlist for loop. - */ -#define intlist__for_each(pos, ilist) \ - for (pos = intlist__first(ilist); pos; pos = intlist__next(pos)) - -/** - * intlist_for_each_safe - iterate over a intlist safe against removal of - * int_node - * @pos: the &struct int_node to use as a loop cursor. - * @n: another &struct int_node to use as temporary storage. - * @ilist: the &struct intlist for loop. - */ -#define intlist__for_each_safe(pos, n, ilist) \ - for (pos = intlist__first(ilist), n = intlist__next(pos); pos;\ - pos = n, n = intlist__next(n)) -#endif /* __PERF_INTLIST_H */ diff --git a/trunk/tools/perf/util/map.c b/trunk/tools/perf/util/map.c index ead5316b3f89..cc33486ad9e2 100644 --- a/trunk/tools/perf/util/map.c +++ b/trunk/tools/perf/util/map.c @@ -9,7 +9,6 @@ #include "map.h" #include "thread.h" #include "strlist.h" -#include "vdso.h" const char *map_type__name[MAP__NR_TYPES] = { [MAP__FUNCTION] = "Functions", @@ -24,6 +23,7 @@ static inline int is_anon_memory(const char *filename) static inline int is_no_dso_memory(const char *filename) { return !strcmp(filename, "[stack]") || + !strcmp(filename, "[vdso]") || !strcmp(filename, "[heap]"); } @@ -52,10 +52,9 @@ struct map *map__new(struct list_head *dsos__list, u64 start, u64 len, if (self != NULL) { char newfilename[PATH_MAX]; struct dso *dso; - int anon, no_dso, vdso; + int anon, no_dso; anon = is_anon_memory(filename); - vdso = is_vdso_map(filename); no_dso = is_no_dso_memory(filename); if (anon) { @@ -63,12 +62,7 @@ struct map *map__new(struct list_head *dsos__list, u64 start, u64 len, filename = newfilename; } - if (vdso) { - pgoff = 0; - dso = vdso__dso_findnew(dsos__list); - } else - dso = __dsos__findnew(dsos__list, filename); - + dso = __dsos__findnew(dsos__list, filename); if (dso == NULL) goto out_delete; @@ -92,25 +86,6 @@ struct map *map__new(struct list_head *dsos__list, u64 start, u64 len, return NULL; } -/* - * Constructor variant for modules (where we know from /proc/modules where - * they are loaded) and for vmlinux, where only after we load all the - * symbols we'll know where it starts and ends. - */ -struct map *map__new2(u64 start, struct dso *dso, enum map_type type) -{ - struct map *map = calloc(1, (sizeof(*map) + - (dso->kernel ? sizeof(struct kmap) : 0))); - if (map != NULL) { - /* - * ->end will be filled after we load all the symbols - */ - map__init(map, type, start, 0, 0, dso); - } - - return map; -} - void map__delete(struct map *self) { free(self); @@ -162,7 +137,6 @@ int map__load(struct map *self, symbol_filter_t filter) pr_warning(", continuing without symbols\n"); return -1; } else if (nr == 0) { -#ifndef NO_LIBELF_SUPPORT const size_t len = strlen(name); const size_t real_len = len - sizeof(DSO__DELETED); @@ -175,7 +149,7 @@ int map__load(struct map *self, symbol_filter_t filter) pr_warning("no symbols found in %s, maybe install " "a debug package?\n", name); } -#endif + return -1; } /* @@ -243,14 +217,15 @@ size_t map__fprintf(struct map *self, FILE *fp) size_t map__fprintf_dsoname(struct map *map, FILE *fp) { - const char *dsoname = "[unknown]"; + const char *dsoname; if (map && map->dso && (map->dso->name || map->dso->long_name)) { if (symbol_conf.show_kernel_path && map->dso->long_name) dsoname = map->dso->long_name; else if (map->dso->name) dsoname = map->dso->name; - } + } else + dsoname = "[unknown]"; return fprintf(fp, "%s", dsoname); } @@ -267,6 +242,14 @@ u64 map__rip_2objdump(struct map *map, u64 rip) return addr; } +u64 map__objdump_2ip(struct map *map, u64 addr) +{ + u64 ip = map->dso->adjust_symbols ? + addr : + map->unmap_ip(map, addr); /* RIP -> IP */ + return ip; +} + void map_groups__init(struct map_groups *mg) { int i; diff --git a/trunk/tools/perf/util/map.h b/trunk/tools/perf/util/map.h index d2250fc97e25..03a1e9b08b21 100644 --- a/trunk/tools/perf/util/map.h +++ b/trunk/tools/perf/util/map.h @@ -96,7 +96,7 @@ static inline u64 map__unmap_ip(struct map *map, u64 ip) return ip + map->start - map->pgoff; } -static inline u64 identity__map_ip(struct map *map __maybe_unused, u64 ip) +static inline u64 identity__map_ip(struct map *map __used, u64 ip) { return ip; } @@ -104,6 +104,7 @@ static inline u64 identity__map_ip(struct map *map __maybe_unused, u64 ip) /* rip/ip <-> addr suitable for passing to `objdump --start-address=` */ u64 map__rip_2objdump(struct map *map, u64 rip); +u64 map__objdump_2ip(struct map *map, u64 addr); struct symbol; @@ -114,7 +115,6 @@ void map__init(struct map *self, enum map_type type, struct map *map__new(struct list_head *dsos__list, u64 start, u64 len, u64 pgoff, u32 pid, char *filename, enum map_type type); -struct map *map__new2(u64 start, struct dso *dso, enum map_type type); void map__delete(struct map *self); struct map *map__clone(struct map *self); int map__overlap(struct map *l, struct map *r); @@ -157,12 +157,9 @@ int machine__init(struct machine *self, const char *root_dir, pid_t pid); void machine__exit(struct machine *self); void machine__delete(struct machine *self); -struct perf_evsel; -struct perf_sample; int machine__resolve_callchain(struct machine *machine, - struct perf_evsel *evsel, struct thread *thread, - struct perf_sample *sample, + struct ip_callchain *chain, struct symbol **parent); int maps__set_kallsyms_ref_reloc_sym(struct map **maps, const char *symbol_name, u64 addr); diff --git a/trunk/tools/perf/util/parse-events-test.c b/trunk/tools/perf/util/parse-events-test.c index 28c18d1d52c3..1b997d2b89ce 100644 --- a/trunk/tools/perf/util/parse-events-test.c +++ b/trunk/tools/perf/util/parse-events-test.c @@ -13,17 +13,16 @@ do { \ } \ } while (0) -#define PERF_TP_SAMPLE_TYPE (PERF_SAMPLE_RAW | PERF_SAMPLE_TIME | \ - PERF_SAMPLE_CPU | PERF_SAMPLE_PERIOD) - static int test__checkevent_tracepoint(struct perf_evlist *evlist) { - struct perf_evsel *evsel = perf_evlist__first(evlist); + struct perf_evsel *evsel = list_entry(evlist->entries.next, + struct perf_evsel, node); TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries); TEST_ASSERT_VAL("wrong type", PERF_TYPE_TRACEPOINT == evsel->attr.type); TEST_ASSERT_VAL("wrong sample_type", - PERF_TP_SAMPLE_TYPE == evsel->attr.sample_type); + (PERF_SAMPLE_RAW | PERF_SAMPLE_TIME | PERF_SAMPLE_CPU) == + evsel->attr.sample_type); TEST_ASSERT_VAL("wrong sample_period", 1 == evsel->attr.sample_period); return 0; } @@ -38,7 +37,8 @@ static int test__checkevent_tracepoint_multi(struct perf_evlist *evlist) TEST_ASSERT_VAL("wrong type", PERF_TYPE_TRACEPOINT == evsel->attr.type); TEST_ASSERT_VAL("wrong sample_type", - PERF_TP_SAMPLE_TYPE == evsel->attr.sample_type); + (PERF_SAMPLE_RAW | PERF_SAMPLE_TIME | PERF_SAMPLE_CPU) + == evsel->attr.sample_type); TEST_ASSERT_VAL("wrong sample_period", 1 == evsel->attr.sample_period); } @@ -47,7 +47,8 @@ static int test__checkevent_tracepoint_multi(struct perf_evlist *evlist) static int test__checkevent_raw(struct perf_evlist *evlist) { - struct perf_evsel *evsel = perf_evlist__first(evlist); + struct perf_evsel *evsel = list_entry(evlist->entries.next, + struct perf_evsel, node); TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries); TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->attr.type); @@ -57,7 +58,8 @@ static int test__checkevent_raw(struct perf_evlist *evlist) static int test__checkevent_numeric(struct perf_evlist *evlist) { - struct perf_evsel *evsel = perf_evlist__first(evlist); + struct perf_evsel *evsel = list_entry(evlist->entries.next, + struct perf_evsel, node); TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries); TEST_ASSERT_VAL("wrong type", 1 == evsel->attr.type); @@ -67,7 +69,8 @@ static int test__checkevent_numeric(struct perf_evlist *evlist) static int test__checkevent_symbolic_name(struct perf_evlist *evlist) { - struct perf_evsel *evsel = perf_evlist__first(evlist); + struct perf_evsel *evsel = list_entry(evlist->entries.next, + struct perf_evsel, node); TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries); TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type); @@ -78,7 +81,8 @@ static int test__checkevent_symbolic_name(struct perf_evlist *evlist) static int test__checkevent_symbolic_name_config(struct perf_evlist *evlist) { - struct perf_evsel *evsel = perf_evlist__first(evlist); + struct perf_evsel *evsel = list_entry(evlist->entries.next, + struct perf_evsel, node); TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries); TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type); @@ -95,7 +99,8 @@ static int test__checkevent_symbolic_name_config(struct perf_evlist *evlist) static int test__checkevent_symbolic_alias(struct perf_evlist *evlist) { - struct perf_evsel *evsel = perf_evlist__first(evlist); + struct perf_evsel *evsel = list_entry(evlist->entries.next, + struct perf_evsel, node); TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries); TEST_ASSERT_VAL("wrong type", PERF_TYPE_SOFTWARE == evsel->attr.type); @@ -106,7 +111,8 @@ static int test__checkevent_symbolic_alias(struct perf_evlist *evlist) static int test__checkevent_genhw(struct perf_evlist *evlist) { - struct perf_evsel *evsel = perf_evlist__first(evlist); + struct perf_evsel *evsel = list_entry(evlist->entries.next, + struct perf_evsel, node); TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries); TEST_ASSERT_VAL("wrong type", PERF_TYPE_HW_CACHE == evsel->attr.type); @@ -116,7 +122,8 @@ static int test__checkevent_genhw(struct perf_evlist *evlist) static int test__checkevent_breakpoint(struct perf_evlist *evlist) { - struct perf_evsel *evsel = perf_evlist__first(evlist); + struct perf_evsel *evsel = list_entry(evlist->entries.next, + struct perf_evsel, node); TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries); TEST_ASSERT_VAL("wrong type", PERF_TYPE_BREAKPOINT == evsel->attr.type); @@ -130,7 +137,8 @@ static int test__checkevent_breakpoint(struct perf_evlist *evlist) static int test__checkevent_breakpoint_x(struct perf_evlist *evlist) { - struct perf_evsel *evsel = perf_evlist__first(evlist); + struct perf_evsel *evsel = list_entry(evlist->entries.next, + struct perf_evsel, node); TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries); TEST_ASSERT_VAL("wrong type", PERF_TYPE_BREAKPOINT == evsel->attr.type); @@ -143,7 +151,8 @@ static int test__checkevent_breakpoint_x(struct perf_evlist *evlist) static int test__checkevent_breakpoint_r(struct perf_evlist *evlist) { - struct perf_evsel *evsel = perf_evlist__first(evlist); + struct perf_evsel *evsel = list_entry(evlist->entries.next, + struct perf_evsel, node); TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries); TEST_ASSERT_VAL("wrong type", @@ -158,7 +167,8 @@ static int test__checkevent_breakpoint_r(struct perf_evlist *evlist) static int test__checkevent_breakpoint_w(struct perf_evlist *evlist) { - struct perf_evsel *evsel = perf_evlist__first(evlist); + struct perf_evsel *evsel = list_entry(evlist->entries.next, + struct perf_evsel, node); TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries); TEST_ASSERT_VAL("wrong type", @@ -173,7 +183,8 @@ static int test__checkevent_breakpoint_w(struct perf_evlist *evlist) static int test__checkevent_breakpoint_rw(struct perf_evlist *evlist) { - struct perf_evsel *evsel = perf_evlist__first(evlist); + struct perf_evsel *evsel = list_entry(evlist->entries.next, + struct perf_evsel, node); TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries); TEST_ASSERT_VAL("wrong type", @@ -188,7 +199,8 @@ static int test__checkevent_breakpoint_rw(struct perf_evlist *evlist) static int test__checkevent_tracepoint_modifier(struct perf_evlist *evlist) { - struct perf_evsel *evsel = perf_evlist__first(evlist); + struct perf_evsel *evsel = list_entry(evlist->entries.next, + struct perf_evsel, node); TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user); TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel); @@ -219,7 +231,8 @@ test__checkevent_tracepoint_multi_modifier(struct perf_evlist *evlist) static int test__checkevent_raw_modifier(struct perf_evlist *evlist) { - struct perf_evsel *evsel = perf_evlist__first(evlist); + struct perf_evsel *evsel = list_entry(evlist->entries.next, + struct perf_evsel, node); TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user); TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel); @@ -231,7 +244,8 @@ static int test__checkevent_raw_modifier(struct perf_evlist *evlist) static int test__checkevent_numeric_modifier(struct perf_evlist *evlist) { - struct perf_evsel *evsel = perf_evlist__first(evlist); + struct perf_evsel *evsel = list_entry(evlist->entries.next, + struct perf_evsel, node); TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user); TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel); @@ -243,7 +257,8 @@ static int test__checkevent_numeric_modifier(struct perf_evlist *evlist) static int test__checkevent_symbolic_name_modifier(struct perf_evlist *evlist) { - struct perf_evsel *evsel = perf_evlist__first(evlist); + struct perf_evsel *evsel = list_entry(evlist->entries.next, + struct perf_evsel, node); TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user); TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel); @@ -255,7 +270,8 @@ static int test__checkevent_symbolic_name_modifier(struct perf_evlist *evlist) static int test__checkevent_exclude_host_modifier(struct perf_evlist *evlist) { - struct perf_evsel *evsel = perf_evlist__first(evlist); + struct perf_evsel *evsel = list_entry(evlist->entries.next, + struct perf_evsel, node); TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest); TEST_ASSERT_VAL("wrong exclude host", evsel->attr.exclude_host); @@ -265,7 +281,8 @@ static int test__checkevent_exclude_host_modifier(struct perf_evlist *evlist) static int test__checkevent_exclude_guest_modifier(struct perf_evlist *evlist) { - struct perf_evsel *evsel = perf_evlist__first(evlist); + struct perf_evsel *evsel = list_entry(evlist->entries.next, + struct perf_evsel, node); TEST_ASSERT_VAL("wrong exclude guest", evsel->attr.exclude_guest); TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host); @@ -275,7 +292,8 @@ static int test__checkevent_exclude_guest_modifier(struct perf_evlist *evlist) static int test__checkevent_symbolic_alias_modifier(struct perf_evlist *evlist) { - struct perf_evsel *evsel = perf_evlist__first(evlist); + struct perf_evsel *evsel = list_entry(evlist->entries.next, + struct perf_evsel, node); TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user); TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel); @@ -287,7 +305,8 @@ static int test__checkevent_symbolic_alias_modifier(struct perf_evlist *evlist) static int test__checkevent_genhw_modifier(struct perf_evlist *evlist) { - struct perf_evsel *evsel = perf_evlist__first(evlist); + struct perf_evsel *evsel = list_entry(evlist->entries.next, + struct perf_evsel, node); TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user); TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel); @@ -299,71 +318,75 @@ static int test__checkevent_genhw_modifier(struct perf_evlist *evlist) static int test__checkevent_breakpoint_modifier(struct perf_evlist *evlist) { - struct perf_evsel *evsel = perf_evlist__first(evlist); - + struct perf_evsel *evsel = list_entry(evlist->entries.next, + struct perf_evsel, node); TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user); TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel); TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); TEST_ASSERT_VAL("wrong name", - !strcmp(perf_evsel__name(evsel), "mem:0:u")); + !strcmp(perf_evsel__name(evsel), "mem:0x0:rw:u")); return test__checkevent_breakpoint(evlist); } static int test__checkevent_breakpoint_x_modifier(struct perf_evlist *evlist) { - struct perf_evsel *evsel = perf_evlist__first(evlist); + struct perf_evsel *evsel = list_entry(evlist->entries.next, + struct perf_evsel, node); TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user); TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel); TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); TEST_ASSERT_VAL("wrong name", - !strcmp(perf_evsel__name(evsel), "mem:0:x:k")); + !strcmp(perf_evsel__name(evsel), "mem:0x0:x:k")); return test__checkevent_breakpoint_x(evlist); } static int test__checkevent_breakpoint_r_modifier(struct perf_evlist *evlist) { - struct perf_evsel *evsel = perf_evlist__first(evlist); + struct perf_evsel *evsel = list_entry(evlist->entries.next, + struct perf_evsel, node); TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user); TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel); TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv); TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip); TEST_ASSERT_VAL("wrong name", - !strcmp(perf_evsel__name(evsel), "mem:0:r:hp")); + !strcmp(perf_evsel__name(evsel), "mem:0x0:r:hp")); return test__checkevent_breakpoint_r(evlist); } static int test__checkevent_breakpoint_w_modifier(struct perf_evlist *evlist) { - struct perf_evsel *evsel = perf_evlist__first(evlist); + struct perf_evsel *evsel = list_entry(evlist->entries.next, + struct perf_evsel, node); TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user); TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel); TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip); TEST_ASSERT_VAL("wrong name", - !strcmp(perf_evsel__name(evsel), "mem:0:w:up")); + !strcmp(perf_evsel__name(evsel), "mem:0x0:w:up")); return test__checkevent_breakpoint_w(evlist); } static int test__checkevent_breakpoint_rw_modifier(struct perf_evlist *evlist) { - struct perf_evsel *evsel = perf_evlist__first(evlist); + struct perf_evsel *evsel = list_entry(evlist->entries.next, + struct perf_evsel, node); TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user); TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel); TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip); TEST_ASSERT_VAL("wrong name", - !strcmp(perf_evsel__name(evsel), "mem:0:rw:kp")); + !strcmp(perf_evsel__name(evsel), "mem:0x0:rw:kp")); return test__checkevent_breakpoint_rw(evlist); } @@ -371,7 +394,8 @@ static int test__checkevent_breakpoint_rw_modifier(struct perf_evlist *evlist) static int test__checkevent_pmu(struct perf_evlist *evlist) { - struct perf_evsel *evsel = perf_evlist__first(evlist); + struct perf_evsel *evsel = list_entry(evlist->entries.next, + struct perf_evsel, node); TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries); TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->attr.type); @@ -385,11 +409,12 @@ static int test__checkevent_pmu(struct perf_evlist *evlist) static int test__checkevent_list(struct perf_evlist *evlist) { - struct perf_evsel *evsel = perf_evlist__first(evlist); + struct perf_evsel *evsel; TEST_ASSERT_VAL("wrong number of entries", 3 == evlist->nr_entries); /* r1 */ + evsel = list_entry(evlist->entries.next, struct perf_evsel, node); TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->attr.type); TEST_ASSERT_VAL("wrong config", 1 == evsel->attr.config); TEST_ASSERT_VAL("wrong config1", 0 == evsel->attr.config1); @@ -400,10 +425,11 @@ static int test__checkevent_list(struct perf_evlist *evlist) TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); /* syscalls:sys_enter_open:k */ - evsel = perf_evsel__next(evsel); + evsel = list_entry(evsel->node.next, struct perf_evsel, node); TEST_ASSERT_VAL("wrong type", PERF_TYPE_TRACEPOINT == evsel->attr.type); TEST_ASSERT_VAL("wrong sample_type", - PERF_TP_SAMPLE_TYPE == evsel->attr.sample_type); + (PERF_SAMPLE_RAW | PERF_SAMPLE_TIME | PERF_SAMPLE_CPU) == + evsel->attr.sample_type); TEST_ASSERT_VAL("wrong sample_period", 1 == evsel->attr.sample_period); TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user); TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel); @@ -411,7 +437,7 @@ static int test__checkevent_list(struct perf_evlist *evlist) TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); /* 1:1:hp */ - evsel = perf_evsel__next(evsel); + evsel = list_entry(evsel->node.next, struct perf_evsel, node); TEST_ASSERT_VAL("wrong type", 1 == evsel->attr.type); TEST_ASSERT_VAL("wrong config", 1 == evsel->attr.config); TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user); @@ -424,21 +450,22 @@ static int test__checkevent_list(struct perf_evlist *evlist) static int test__checkevent_pmu_name(struct perf_evlist *evlist) { - struct perf_evsel *evsel = perf_evlist__first(evlist); + struct perf_evsel *evsel; /* cpu/config=1,name=krava/u */ + evsel = list_entry(evlist->entries.next, struct perf_evsel, node); TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->nr_entries); TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->attr.type); TEST_ASSERT_VAL("wrong config", 1 == evsel->attr.config); TEST_ASSERT_VAL("wrong name", !strcmp(perf_evsel__name(evsel), "krava")); /* cpu/config=2/u" */ - evsel = perf_evsel__next(evsel); + evsel = list_entry(evsel->node.next, struct perf_evsel, node); TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->nr_entries); TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->attr.type); TEST_ASSERT_VAL("wrong config", 2 == evsel->attr.config); TEST_ASSERT_VAL("wrong name", - !strcmp(perf_evsel__name(evsel), "cpu/config=2/u")); + !strcmp(perf_evsel__name(evsel), "raw 0x2:u")); return 0; } @@ -486,280 +513,6 @@ static int test__checkterms_simple(struct list_head *terms) return 0; } -static int test__group1(struct perf_evlist *evlist) -{ - struct perf_evsel *evsel, *leader; - - TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->nr_entries); - - /* instructions:k */ - evsel = leader = perf_evlist__first(evlist); - TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type); - TEST_ASSERT_VAL("wrong config", - PERF_COUNT_HW_INSTRUCTIONS == evsel->attr.config); - TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); - TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest); - TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host); - TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); - TEST_ASSERT_VAL("wrong leader", evsel->leader == NULL); - - /* cycles:upp */ - evsel = perf_evsel__next(evsel); - TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type); - TEST_ASSERT_VAL("wrong config", - PERF_COUNT_HW_CPU_CYCLES == evsel->attr.config); - TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); - TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest); - TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host); - TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip == 2); - TEST_ASSERT_VAL("wrong leader", evsel->leader == leader); - - return 0; -} - -static int test__group2(struct perf_evlist *evlist) -{ - struct perf_evsel *evsel, *leader; - - TEST_ASSERT_VAL("wrong number of entries", 3 == evlist->nr_entries); - - /* faults + :ku modifier */ - evsel = leader = perf_evlist__first(evlist); - TEST_ASSERT_VAL("wrong type", PERF_TYPE_SOFTWARE == evsel->attr.type); - TEST_ASSERT_VAL("wrong config", - PERF_COUNT_SW_PAGE_FAULTS == evsel->attr.config); - TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); - TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest); - TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host); - TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); - TEST_ASSERT_VAL("wrong leader", evsel->leader == NULL); - - /* cache-references + :u modifier */ - evsel = perf_evsel__next(evsel); - TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type); - TEST_ASSERT_VAL("wrong config", - PERF_COUNT_HW_CACHE_REFERENCES == evsel->attr.config); - TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); - TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest); - TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host); - TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); - TEST_ASSERT_VAL("wrong leader", evsel->leader == leader); - - /* cycles:k */ - evsel = perf_evsel__next(evsel); - TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type); - TEST_ASSERT_VAL("wrong config", - PERF_COUNT_HW_CPU_CYCLES == evsel->attr.config); - TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); - TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest); - TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host); - TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); - TEST_ASSERT_VAL("wrong leader", evsel->leader == NULL); - - return 0; -} - -static int test__group3(struct perf_evlist *evlist __maybe_unused) -{ - struct perf_evsel *evsel, *leader; - - TEST_ASSERT_VAL("wrong number of entries", 5 == evlist->nr_entries); - - /* group1 syscalls:sys_enter_open:H */ - evsel = leader = perf_evlist__first(evlist); - TEST_ASSERT_VAL("wrong type", PERF_TYPE_TRACEPOINT == evsel->attr.type); - TEST_ASSERT_VAL("wrong sample_type", - PERF_TP_SAMPLE_TYPE == evsel->attr.sample_type); - TEST_ASSERT_VAL("wrong sample_period", 1 == evsel->attr.sample_period); - TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv); - TEST_ASSERT_VAL("wrong exclude guest", evsel->attr.exclude_guest); - TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host); - TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); - TEST_ASSERT_VAL("wrong leader", evsel->leader == NULL); - TEST_ASSERT_VAL("wrong group name", - !strcmp(leader->group_name, "group1")); - - /* group1 cycles:kppp */ - evsel = perf_evsel__next(evsel); - TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type); - TEST_ASSERT_VAL("wrong config", - PERF_COUNT_HW_CPU_CYCLES == evsel->attr.config); - TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); - TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest); - TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host); - TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip == 3); - TEST_ASSERT_VAL("wrong leader", evsel->leader == leader); - TEST_ASSERT_VAL("wrong group name", !evsel->group_name); - - /* group2 cycles + G modifier */ - evsel = leader = perf_evsel__next(evsel); - TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type); - TEST_ASSERT_VAL("wrong config", - PERF_COUNT_HW_CPU_CYCLES == evsel->attr.config); - TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv); - TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest); - TEST_ASSERT_VAL("wrong exclude host", evsel->attr.exclude_host); - TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); - TEST_ASSERT_VAL("wrong leader", evsel->leader == NULL); - TEST_ASSERT_VAL("wrong group name", - !strcmp(leader->group_name, "group2")); - - /* group2 1:3 + G modifier */ - evsel = perf_evsel__next(evsel); - TEST_ASSERT_VAL("wrong type", 1 == evsel->attr.type); - TEST_ASSERT_VAL("wrong config", 3 == evsel->attr.config); - TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv); - TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest); - TEST_ASSERT_VAL("wrong exclude host", evsel->attr.exclude_host); - TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); - TEST_ASSERT_VAL("wrong leader", evsel->leader == leader); - - /* instructions:u */ - evsel = perf_evsel__next(evsel); - TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type); - TEST_ASSERT_VAL("wrong config", - PERF_COUNT_HW_INSTRUCTIONS == evsel->attr.config); - TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); - TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest); - TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host); - TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); - TEST_ASSERT_VAL("wrong leader", evsel->leader == NULL); - - return 0; -} - -static int test__group4(struct perf_evlist *evlist __maybe_unused) -{ - struct perf_evsel *evsel, *leader; - - TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->nr_entries); - - /* cycles:u + p */ - evsel = leader = perf_evlist__first(evlist); - TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type); - TEST_ASSERT_VAL("wrong config", - PERF_COUNT_HW_CPU_CYCLES == evsel->attr.config); - TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); - TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest); - TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host); - TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip == 1); - TEST_ASSERT_VAL("wrong group name", !evsel->group_name); - TEST_ASSERT_VAL("wrong leader", evsel->leader == NULL); - - /* instructions:kp + p */ - evsel = perf_evsel__next(evsel); - TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type); - TEST_ASSERT_VAL("wrong config", - PERF_COUNT_HW_INSTRUCTIONS == evsel->attr.config); - TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); - TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest); - TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host); - TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip == 2); - TEST_ASSERT_VAL("wrong leader", evsel->leader == leader); - - return 0; -} - -static int test__group5(struct perf_evlist *evlist __maybe_unused) -{ - struct perf_evsel *evsel, *leader; - - TEST_ASSERT_VAL("wrong number of entries", 5 == evlist->nr_entries); - - /* cycles + G */ - evsel = leader = perf_evlist__first(evlist); - TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type); - TEST_ASSERT_VAL("wrong config", - PERF_COUNT_HW_CPU_CYCLES == evsel->attr.config); - TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv); - TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest); - TEST_ASSERT_VAL("wrong exclude host", evsel->attr.exclude_host); - TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); - TEST_ASSERT_VAL("wrong group name", !evsel->group_name); - TEST_ASSERT_VAL("wrong leader", evsel->leader == NULL); - - /* instructions + G */ - evsel = perf_evsel__next(evsel); - TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type); - TEST_ASSERT_VAL("wrong config", - PERF_COUNT_HW_INSTRUCTIONS == evsel->attr.config); - TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv); - TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest); - TEST_ASSERT_VAL("wrong exclude host", evsel->attr.exclude_host); - TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); - TEST_ASSERT_VAL("wrong leader", evsel->leader == leader); - - /* cycles:G */ - evsel = leader = perf_evsel__next(evsel); - TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type); - TEST_ASSERT_VAL("wrong config", - PERF_COUNT_HW_CPU_CYCLES == evsel->attr.config); - TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv); - TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest); - TEST_ASSERT_VAL("wrong exclude host", evsel->attr.exclude_host); - TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); - TEST_ASSERT_VAL("wrong group name", !evsel->group_name); - TEST_ASSERT_VAL("wrong leader", evsel->leader == NULL); - - /* instructions:G */ - evsel = perf_evsel__next(evsel); - TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type); - TEST_ASSERT_VAL("wrong config", - PERF_COUNT_HW_INSTRUCTIONS == evsel->attr.config); - TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv); - TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest); - TEST_ASSERT_VAL("wrong exclude host", evsel->attr.exclude_host); - TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); - TEST_ASSERT_VAL("wrong leader", evsel->leader == leader); - - /* cycles */ - evsel = perf_evsel__next(evsel); - TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type); - TEST_ASSERT_VAL("wrong config", - PERF_COUNT_HW_CPU_CYCLES == evsel->attr.config); - TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv); - TEST_ASSERT_VAL("wrong exclude guest", evsel->attr.exclude_guest); - TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host); - TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); - TEST_ASSERT_VAL("wrong leader", evsel->leader == NULL); - - return 0; -} - struct test__event_st { const char *name; __u32 type; @@ -879,26 +632,6 @@ static struct test__event_st test__events[] = { .name = "mem:0:rw:kp", .check = test__checkevent_breakpoint_rw_modifier, }, - [28] = { - .name = "{instructions:k,cycles:upp}", - .check = test__group1, - }, - [29] = { - .name = "{faults:k,cache-references}:u,cycles:k", - .check = test__group2, - }, - [30] = { - .name = "group1{syscalls:sys_enter_open:H,cycles:kppp},group2{cycles,1:3}:G,instructions:u", - .check = test__group3, - }, - [31] = { - .name = "{cycles:u,instructions:kp}:p", - .check = test__group4, - }, - [32] = { - .name = "{cycles,instructions}:G,{cycles:G,instructions:G},cycles", - .check = test__group5, - }, }; static struct test__event_st test__events_pmu[] = { @@ -925,6 +658,9 @@ static struct test__term test__terms[] = { }, }; +#define TEST__TERMS_CNT (sizeof(test__terms) / \ + sizeof(struct test__term)) + static int test_event(struct test__event_st *e) { struct perf_evlist *evlist; @@ -949,19 +685,19 @@ static int test_event(struct test__event_st *e) static int test_events(struct test__event_st *events, unsigned cnt) { - int ret1, ret2 = 0; + int ret = 0; unsigned i; for (i = 0; i < cnt; i++) { struct test__event_st *e = &events[i]; pr_debug("running test %d '%s'\n", i, e->name); - ret1 = test_event(e); - if (ret1) - ret2 = ret1; + ret = test_event(e); + if (ret) + break; } - return ret2; + return ret; } static int test_term(struct test__term *t) @@ -1016,19 +752,19 @@ static int test_pmu(void) ret = stat(path, &st); if (ret) - pr_debug("omitting PMU cpu tests\n"); + pr_debug("ommiting PMU cpu tests\n"); return !ret; } int parse_events__test(void) { - int ret1, ret2 = 0; + int ret; #define TEST_EVENTS(tests) \ do { \ - ret1 = test_events(tests, ARRAY_SIZE(tests)); \ - if (!ret2) \ - ret2 = ret1; \ + ret = test_events(tests, ARRAY_SIZE(tests)); \ + if (ret) \ + return ret; \ } while (0) TEST_EVENTS(test__events); @@ -1036,9 +772,5 @@ do { \ if (test_pmu()) TEST_EVENTS(test__events_pmu); - ret1 = test_terms(test__terms, ARRAY_SIZE(test__terms)); - if (!ret2) - ret2 = ret1; - - return ret2; + return test_terms(test__terms, ARRAY_SIZE(test__terms)); } diff --git a/trunk/tools/perf/util/parse-events.c b/trunk/tools/perf/util/parse-events.c index aed38e4b9dfa..74a5af4d33ec 100644 --- a/trunk/tools/perf/util/parse-events.c +++ b/trunk/tools/perf/util/parse-events.c @@ -239,11 +239,8 @@ const char *event_type(int type) return "unknown"; } - - -static int __add_event(struct list_head **_list, int *idx, - struct perf_event_attr *attr, - char *name, struct cpu_map *cpus) +static int add_event(struct list_head **_list, int *idx, + struct perf_event_attr *attr, char *name) { struct perf_evsel *evsel; struct list_head *list = *_list; @@ -263,7 +260,6 @@ static int __add_event(struct list_head **_list, int *idx, return -ENOMEM; } - evsel->cpus = cpus; if (name) evsel->name = strdup(name); list_add_tail(&evsel->node, list); @@ -271,12 +267,6 @@ static int __add_event(struct list_head **_list, int *idx, return 0; } -static int add_event(struct list_head **_list, int *idx, - struct perf_event_attr *attr, char *name) -{ - return __add_event(_list, idx, attr, name, NULL); -} - static int parse_aliases(char *str, const char *names[][PERF_EVSEL__MAX_ALIASES], int size) { int i, j; @@ -318,7 +308,7 @@ int parse_events_add_cache(struct list_head **list, int *idx, for (i = 0; (i < 2) && (op_result[i]); i++) { char *str = op_result[i]; - n += snprintf(name + n, MAX_NAME_LEN - n, "-%s", str); + snprintf(name + n, MAX_NAME_LEN - n, "-%s\n", str); if (cache_op == -1) { cache_op = parse_aliases(str, perf_evsel__hw_cache_op, @@ -356,28 +346,42 @@ int parse_events_add_cache(struct list_head **list, int *idx, return add_event(list, idx, &attr, name); } -static int add_tracepoint(struct list_head **listp, int *idx, +static int add_tracepoint(struct list_head **list, int *idx, char *sys_name, char *evt_name) { - struct perf_evsel *evsel; - struct list_head *list = *listp; + struct perf_event_attr attr; + char name[MAX_NAME_LEN]; + char evt_path[MAXPATHLEN]; + char id_buf[4]; + u64 id; + int fd; - if (!list) { - list = malloc(sizeof(*list)); - if (!list) - return -ENOMEM; - INIT_LIST_HEAD(list); - } + snprintf(evt_path, MAXPATHLEN, "%s/%s/%s/id", tracing_events_path, + sys_name, evt_name); - evsel = perf_evsel__newtp(sys_name, evt_name, (*idx)++); - if (!evsel) { - free(list); - return -ENOMEM; + fd = open(evt_path, O_RDONLY); + if (fd < 0) + return -1; + + if (read(fd, id_buf, sizeof(id_buf)) < 0) { + close(fd); + return -1; } - list_add_tail(&evsel->node, list); - *listp = list; - return 0; + close(fd); + id = atoll(id_buf); + + memset(&attr, 0, sizeof(attr)); + attr.config = id; + attr.type = PERF_TYPE_TRACEPOINT; + attr.sample_type |= PERF_SAMPLE_RAW; + attr.sample_type |= PERF_SAMPLE_TIME; + attr.sample_type |= PERF_SAMPLE_CPU; + attr.sample_type |= PERF_SAMPLE_PERIOD; + attr.sample_period = 1; + + snprintf(name, MAX_NAME_LEN, "%s:%s", sys_name, evt_name); + return add_event(list, idx, &attr, name); } static int add_tracepoint_multi(struct list_head **list, int *idx, @@ -547,7 +551,7 @@ static int config_attr(struct perf_event_attr *attr, } int parse_events_add_numeric(struct list_head **list, int *idx, - u32 type, u64 config, + unsigned long type, unsigned long config, struct list_head *head_config) { struct perf_event_attr attr; @@ -603,23 +607,8 @@ int parse_events_add_pmu(struct list_head **list, int *idx, if (perf_pmu__config(pmu, &attr, head_config)) return -EINVAL; - return __add_event(list, idx, &attr, pmu_event_name(head_config), - pmu->cpus); -} - -int parse_events__modifier_group(struct list_head *list, - char *event_mod) -{ - return parse_events__modifier_event(list, event_mod, true); -} - -void parse_events__set_leader(char *name, struct list_head *list) -{ - struct perf_evsel *leader; - - __perf_evlist__set_leader(list); - leader = list_entry(list->next, struct perf_evsel, node); - leader->group_name = name ? strdup(name) : NULL; + return add_event(list, idx, &attr, + pmu_event_name(head_config)); } void parse_events_update_lists(struct list_head *list_event, @@ -627,45 +616,21 @@ void parse_events_update_lists(struct list_head *list_event, { /* * Called for single event definition. Update the - * 'all event' list, and reinit the 'single event' + * 'all event' list, and reinit the 'signle event' * list, for next event definition. */ list_splice_tail(list_event, list_all); free(list_event); } -struct event_modifier { - int eu; - int ek; - int eh; - int eH; - int eG; - int precise; - int exclude_GH; -}; - -static int get_event_modifier(struct event_modifier *mod, char *str, - struct perf_evsel *evsel) +int parse_events_modifier(struct list_head *list, char *str) { - int eu = evsel ? evsel->attr.exclude_user : 0; - int ek = evsel ? evsel->attr.exclude_kernel : 0; - int eh = evsel ? evsel->attr.exclude_hv : 0; - int eH = evsel ? evsel->attr.exclude_host : 0; - int eG = evsel ? evsel->attr.exclude_guest : 0; - int precise = evsel ? evsel->attr.precise_ip : 0; - - int exclude = eu | ek | eh; - int exclude_GH = evsel ? evsel->exclude_GH : 0; - - /* - * We are here for group and 'GH' was not set as event - * modifier and whatever event/group modifier override - * default 'GH' setup. - */ - if (evsel && !exclude_GH) - eH = eG = 0; + struct perf_evsel *evsel; + int exclude = 0, exclude_GH = 0; + int eu = 0, ek = 0, eh = 0, eH = 0, eG = 0, precise = 0; - memset(mod, 0, sizeof(*mod)); + if (str == NULL) + return 0; while (*str) { if (*str == 'u') { @@ -709,51 +674,13 @@ static int get_event_modifier(struct event_modifier *mod, char *str, if (precise > 3) return -EINVAL; - mod->eu = eu; - mod->ek = ek; - mod->eh = eh; - mod->eH = eH; - mod->eG = eG; - mod->precise = precise; - mod->exclude_GH = exclude_GH; - return 0; -} - -int parse_events__modifier_event(struct list_head *list, char *str, bool add) -{ - struct perf_evsel *evsel; - struct event_modifier mod; - - if (str == NULL) - return 0; - - if (!add && get_event_modifier(&mod, str, NULL)) - return -EINVAL; - list_for_each_entry(evsel, list, node) { - - if (add && get_event_modifier(&mod, str, evsel)) - return -EINVAL; - - evsel->attr.exclude_user = mod.eu; - evsel->attr.exclude_kernel = mod.ek; - evsel->attr.exclude_hv = mod.eh; - evsel->attr.precise_ip = mod.precise; - evsel->attr.exclude_host = mod.eH; - evsel->attr.exclude_guest = mod.eG; - evsel->exclude_GH = mod.exclude_GH; - } - - return 0; -} - -int parse_events_name(struct list_head *list, char *name) -{ - struct perf_evsel *evsel; - - list_for_each_entry(evsel, list, node) { - if (!evsel->name) - evsel->name = strdup(name); + evsel->attr.exclude_user = eu; + evsel->attr.exclude_kernel = ek; + evsel->attr.exclude_hv = eh; + evsel->attr.precise_ip = precise; + evsel->attr.exclude_host = eH; + evsel->attr.exclude_guest = eG; } return 0; @@ -803,8 +730,7 @@ int parse_events_terms(struct list_head *terms, const char *str) return ret; } -int parse_events(struct perf_evlist *evlist, const char *str, - int unset __maybe_unused) +int parse_events(struct perf_evlist *evlist, const char *str, int unset __used) { struct parse_events_data__events data = { .list = LIST_HEAD_INIT(data.list), @@ -830,20 +756,20 @@ int parse_events(struct perf_evlist *evlist, const char *str, } int parse_events_option(const struct option *opt, const char *str, - int unset __maybe_unused) + int unset __used) { struct perf_evlist *evlist = *(struct perf_evlist **)opt->value; return parse_events(evlist, str, unset); } int parse_filter(const struct option *opt, const char *str, - int unset __maybe_unused) + int unset __used) { struct perf_evlist *evlist = *(struct perf_evlist **)opt->value; struct perf_evsel *last = NULL; if (evlist->nr_entries > 0) - last = perf_evlist__last(evlist); + last = list_entry(evlist->entries.prev, struct perf_evsel, node); if (last == NULL || last->attr.type != PERF_TYPE_TRACEPOINT) { fprintf(stderr, @@ -873,8 +799,7 @@ static const char * const event_type_descriptors[] = { * Print the events from /tracing/events */ -void print_tracepoint_events(const char *subsys_glob, const char *event_glob, - bool name_only) +void print_tracepoint_events(const char *subsys_glob, const char *event_glob) { DIR *sys_dir, *evt_dir; struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent; @@ -904,11 +829,6 @@ void print_tracepoint_events(const char *subsys_glob, const char *event_glob, !strglobmatch(evt_dirent.d_name, event_glob)) continue; - if (name_only) { - printf("%s:%s ", sys_dirent.d_name, evt_dirent.d_name); - continue; - } - snprintf(evt_path, MAXPATHLEN, "%s:%s", sys_dirent.d_name, evt_dirent.d_name); printf(" %-50s [%s]\n", evt_path, @@ -986,7 +906,7 @@ void print_events_type(u8 type) __print_events_type(type, event_symbols_hw, PERF_COUNT_HW_MAX); } -int print_hwcache_events(const char *event_glob, bool name_only) +int print_hwcache_events(const char *event_glob) { unsigned int type, op, i, printed = 0; char name[64]; @@ -1003,11 +923,8 @@ int print_hwcache_events(const char *event_glob, bool name_only) if (event_glob != NULL && !strglobmatch(name, event_glob)) continue; - if (name_only) - printf("%s ", name); - else - printf(" %-50s [%s]\n", name, - event_type_descriptors[PERF_TYPE_HW_CACHE]); + printf(" %-50s [%s]\n", name, + event_type_descriptors[PERF_TYPE_HW_CACHE]); ++printed; } } @@ -1017,8 +934,7 @@ int print_hwcache_events(const char *event_glob, bool name_only) } static void print_symbol_events(const char *event_glob, unsigned type, - struct event_symbol *syms, unsigned max, - bool name_only) + struct event_symbol *syms, unsigned max) { unsigned i, printed = 0; char name[MAX_NAME_LEN]; @@ -1030,11 +946,6 @@ static void print_symbol_events(const char *event_glob, unsigned type, (syms->alias && strglobmatch(syms->alias, event_glob)))) continue; - if (name_only) { - printf("%s ", syms->symbol); - continue; - } - if (strlen(syms->alias)) snprintf(name, MAX_NAME_LEN, "%s OR %s", syms->symbol, syms->alias); else @@ -1052,42 +963,39 @@ static void print_symbol_events(const char *event_glob, unsigned type, /* * Print the help text for the event symbols: */ -void print_events(const char *event_glob, bool name_only) +void print_events(const char *event_glob) { - if (!name_only) { - printf("\n"); - printf("List of pre-defined events (to be used in -e):\n"); - } + + printf("\n"); + printf("List of pre-defined events (to be used in -e):\n"); print_symbol_events(event_glob, PERF_TYPE_HARDWARE, - event_symbols_hw, PERF_COUNT_HW_MAX, name_only); + event_symbols_hw, PERF_COUNT_HW_MAX); print_symbol_events(event_glob, PERF_TYPE_SOFTWARE, - event_symbols_sw, PERF_COUNT_SW_MAX, name_only); + event_symbols_sw, PERF_COUNT_SW_MAX); - print_hwcache_events(event_glob, name_only); + print_hwcache_events(event_glob); if (event_glob != NULL) return; - if (!name_only) { - printf("\n"); - printf(" %-50s [%s]\n", - "rNNN", - event_type_descriptors[PERF_TYPE_RAW]); - printf(" %-50s [%s]\n", - "cpu/t1=v1[,t2=v2,t3 ...]/modifier", - event_type_descriptors[PERF_TYPE_RAW]); - printf(" (see 'perf list --help' on how to encode it)\n"); - printf("\n"); - - printf(" %-50s [%s]\n", - "mem:[:access]", + printf("\n"); + printf(" %-50s [%s]\n", + "rNNN", + event_type_descriptors[PERF_TYPE_RAW]); + printf(" %-50s [%s]\n", + "cpu/t1=v1[,t2=v2,t3 ...]/modifier", + event_type_descriptors[PERF_TYPE_RAW]); + printf(" (see 'perf list --help' on how to encode it)\n"); + printf("\n"); + + printf(" %-50s [%s]\n", + "mem:[:access]", event_type_descriptors[PERF_TYPE_BREAKPOINT]); - printf("\n"); - } + printf("\n"); - print_tracepoint_events(NULL, NULL, name_only); + print_tracepoint_events(NULL, NULL); } int parse_events__is_hardcoded_term(struct parse_events__term *term) @@ -1097,7 +1005,7 @@ int parse_events__is_hardcoded_term(struct parse_events__term *term) static int new_term(struct parse_events__term **_term, int type_val, int type_term, char *config, - char *str, u64 num) + char *str, long num) { struct parse_events__term *term; @@ -1126,7 +1034,7 @@ static int new_term(struct parse_events__term **_term, int type_val, } int parse_events__term_num(struct parse_events__term **term, - int type_term, char *config, u64 num) + int type_term, char *config, long num) { return new_term(term, PARSE_EVENTS__TERM_TYPE_NUM, type_term, config, NULL, num); diff --git a/trunk/tools/perf/util/parse-events.h b/trunk/tools/perf/util/parse-events.h index c356e443448d..ee9c218a193c 100644 --- a/trunk/tools/perf/util/parse-events.h +++ b/trunk/tools/perf/util/parse-events.h @@ -55,7 +55,7 @@ struct parse_events__term { char *config; union { char *str; - u64 num; + long num; } val; int type_val; int type_term; @@ -73,19 +73,17 @@ struct parse_events_data__terms { int parse_events__is_hardcoded_term(struct parse_events__term *term); int parse_events__term_num(struct parse_events__term **_term, - int type_term, char *config, u64 num); + int type_term, char *config, long num); int parse_events__term_str(struct parse_events__term **_term, int type_term, char *config, char *str); int parse_events__term_clone(struct parse_events__term **new, struct parse_events__term *term); void parse_events__free_terms(struct list_head *terms); -int parse_events__modifier_event(struct list_head *list, char *str, bool add); -int parse_events__modifier_group(struct list_head *list, char *event_mod); -int parse_events_name(struct list_head *list, char *name); +int parse_events_modifier(struct list_head *list, char *str); int parse_events_add_tracepoint(struct list_head **list, int *idx, char *sys, char *event); int parse_events_add_numeric(struct list_head **list, int *idx, - u32 type, u64 config, + unsigned long type, unsigned long config, struct list_head *head_config); int parse_events_add_cache(struct list_head **list, int *idx, char *type, char *op_result1, char *op_result2); @@ -93,17 +91,15 @@ int parse_events_add_breakpoint(struct list_head **list, int *idx, void *ptr, char *type); int parse_events_add_pmu(struct list_head **list, int *idx, char *pmu , struct list_head *head_config); -void parse_events__set_leader(char *name, struct list_head *list); void parse_events_update_lists(struct list_head *list_event, struct list_head *list_all); void parse_events_error(void *data, void *scanner, char const *msg); int parse_events__test(void); -void print_events(const char *event_glob, bool name_only); +void print_events(const char *event_glob); void print_events_type(u8 type); -void print_tracepoint_events(const char *subsys_glob, const char *event_glob, - bool name_only); -int print_hwcache_events(const char *event_glob, bool name_only); +void print_tracepoint_events(const char *subsys_glob, const char *event_glob); +int print_hwcache_events(const char *event_glob); extern int is_valid_tracepoint(const char *event_string); extern int valid_debugfs_mount(const char *debugfs); diff --git a/trunk/tools/perf/util/parse-events.l b/trunk/tools/perf/util/parse-events.l index c87efc12579d..384ca74c6b22 100644 --- a/trunk/tools/perf/util/parse-events.l +++ b/trunk/tools/perf/util/parse-events.l @@ -15,10 +15,10 @@ YYSTYPE *parse_events_get_lval(yyscan_t yyscanner); static int __value(YYSTYPE *yylval, char *str, int base, int token) { - u64 num; + long num; errno = 0; - num = strtoull(str, NULL, base); + num = strtoul(str, NULL, base); if (errno) return PE_ERROR; @@ -70,12 +70,6 @@ static int term(yyscan_t scanner, int type) %} %x mem -%s config -%x event - -group [^,{}/]*[{][^}]*[}][^,{}/]* -event_pmu [^,{}/]+[/][^/]*[/][^,{}/]* -event [^,{}/]+ num_dec [0-9]+ num_hex 0x[a-fA-F0-9]+ @@ -90,13 +84,7 @@ modifier_bp [rwx]{1,3} { int start_token; - start_token = parse_events_get_extra(yyscanner); - - if (start_token == PE_START_TERMS) - BEGIN(config); - else if (start_token == PE_START_EVENTS) - BEGIN(event); - + start_token = (int) parse_events_get_extra(yyscanner); if (start_token) { parse_events_set_extra(NULL, yyscanner); return start_token; @@ -104,26 +92,6 @@ modifier_bp [rwx]{1,3} } %} -{ - -{group} { - BEGIN(INITIAL); yyless(0); - } - -{event_pmu} | -{event} { - str(yyscanner, PE_EVENT_NAME); - BEGIN(INITIAL); yyless(0); - return PE_EVENT_NAME; - } - -. | -<> { - BEGIN(INITIAL); yyless(0); - } - -} - cpu-cycles|cycles { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_CPU_CYCLES); } stalled-cycles-frontend|idle-cycles-frontend { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_STALLED_CYCLES_FRONTEND); } stalled-cycles-backend|idle-cycles-backend { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_STALLED_CYCLES_BACKEND); } @@ -159,16 +127,18 @@ speculative-read|speculative-load | refs|Reference|ops|access | misses|miss { return str(yyscanner, PE_NAME_CACHE_OP_RESULT); } -{ + /* + * These are event config hardcoded term names to be specified + * within xxx/.../ syntax. So far we dont clash with other names, + * so we can put them here directly. In case the we have a conflict + * in future, this needs to go into '//' condition block. + */ config { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CONFIG); } config1 { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CONFIG1); } config2 { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CONFIG2); } name { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_NAME); } period { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD); } branch_type { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE); } -, { return ','; } -"/" { BEGIN(INITIAL); return '/'; } -} mem: { BEGIN(mem); return PE_PREFIX_MEM; } r{num_raw_hex} { return raw(yyscanner); } @@ -177,12 +147,10 @@ r{num_raw_hex} { return raw(yyscanner); } {modifier_event} { return str(yyscanner, PE_MODIFIER_EVENT); } {name} { return str(yyscanner, PE_NAME); } -"/" { BEGIN(config); return '/'; } +"/" { return '/'; } - { return '-'; } -, { BEGIN(event); return ','; } +, { return ','; } : { return ':'; } -"{" { BEGIN(event); return '{'; } -"}" { return '}'; } = { return '='; } \n { } @@ -207,7 +175,7 @@ r{num_raw_hex} { return raw(yyscanner); } %% -int parse_events_wrap(void *scanner __maybe_unused) +int parse_events_wrap(void *scanner __used) { return 1; } diff --git a/trunk/tools/perf/util/parse-events.y b/trunk/tools/perf/util/parse-events.y index cd88209e3c58..2bc5fbff2b5d 100644 --- a/trunk/tools/perf/util/parse-events.y +++ b/trunk/tools/perf/util/parse-events.y @@ -27,11 +27,10 @@ do { \ %token PE_START_EVENTS PE_START_TERMS %token PE_VALUE PE_VALUE_SYM_HW PE_VALUE_SYM_SW PE_RAW PE_TERM -%token PE_EVENT_NAME %token PE_NAME %token PE_MODIFIER_EVENT PE_MODIFIER_BP %token PE_NAME_CACHE_TYPE PE_NAME_CACHE_OP_RESULT -%token PE_PREFIX_MEM PE_PREFIX_RAW PE_PREFIX_GROUP +%token PE_PREFIX_MEM PE_PREFIX_RAW %token PE_ERROR %type PE_VALUE %type PE_VALUE_SYM_HW @@ -43,7 +42,6 @@ do { \ %type PE_NAME_CACHE_OP_RESULT %type PE_MODIFIER_EVENT %type PE_MODIFIER_BP -%type PE_EVENT_NAME %type value_sym %type event_config %type event_term @@ -55,125 +53,44 @@ do { \ %type event_legacy_numeric %type event_legacy_raw %type event_def -%type event_mod -%type event_name -%type event -%type events -%type group_def -%type group -%type groups %union { char *str; - u64 num; + unsigned long num; struct list_head *head; struct parse_events__term *term; } %% start: -PE_START_EVENTS start_events +PE_START_EVENTS events | -PE_START_TERMS start_terms - -start_events: groups -{ - struct parse_events_data__events *data = _data; - - parse_events_update_lists($1, &data->list); -} - -groups: -groups ',' group -{ - struct list_head *list = $1; - struct list_head *group = $3; - - parse_events_update_lists(group, list); - $$ = list; -} -| -groups ',' event -{ - struct list_head *list = $1; - struct list_head *event = $3; - - parse_events_update_lists(event, list); - $$ = list; -} -| -group -| -event - -group: -group_def ':' PE_MODIFIER_EVENT -{ - struct list_head *list = $1; - - ABORT_ON(parse_events__modifier_group(list, $3)); - $$ = list; -} -| -group_def - -group_def: -PE_NAME '{' events '}' -{ - struct list_head *list = $3; - - parse_events__set_leader($1, list); - $$ = list; -} -| -'{' events '}' -{ - struct list_head *list = $2; - - parse_events__set_leader(NULL, list); - $$ = list; -} +PE_START_TERMS terms events: -events ',' event -{ - struct list_head *event = $3; - struct list_head *list = $1; +events ',' event | event - parse_events_update_lists(event, list); - $$ = list; -} -| -event - -event: event_mod - -event_mod: -event_name PE_MODIFIER_EVENT +event: +event_def PE_MODIFIER_EVENT { - struct list_head *list = $1; + struct parse_events_data__events *data = _data; /* * Apply modifier on all events added by single event definition * (there could be more events added for multiple tracepoint * definitions via '*?'. */ - ABORT_ON(parse_events__modifier_event(list, $2, false)); - $$ = list; + ABORT_ON(parse_events_modifier($1, $2)); + parse_events_update_lists($1, &data->list); } | -event_name - -event_name: -PE_EVENT_NAME event_def +event_def { - ABORT_ON(parse_events_name($2, $1)); - free($1); - $$ = $2; + struct parse_events_data__events *data = _data; + + parse_events_update_lists($1, &data->list); } -| -event_def event_def: event_pmu | event_legacy_symbol | @@ -290,7 +207,7 @@ PE_VALUE ':' PE_VALUE struct parse_events_data__events *data = _data; struct list_head *list = NULL; - ABORT_ON(parse_events_add_numeric(&list, &data->idx, (u32)$1, $3, NULL)); + ABORT_ON(parse_events_add_numeric(&list, &data->idx, $1, $3, NULL)); $$ = list; } @@ -305,7 +222,7 @@ PE_RAW $$ = list; } -start_terms: event_config +terms: event_config { struct parse_events_data__terms *data = _data; data->terms = $1; @@ -365,7 +282,7 @@ PE_TERM '=' PE_NAME { struct parse_events__term *term; - ABORT_ON(parse_events__term_str(&term, (int)$1, NULL, $3)); + ABORT_ON(parse_events__term_str(&term, $1, NULL, $3)); $$ = term; } | @@ -373,7 +290,7 @@ PE_TERM '=' PE_VALUE { struct parse_events__term *term; - ABORT_ON(parse_events__term_num(&term, (int)$1, NULL, $3)); + ABORT_ON(parse_events__term_num(&term, $1, NULL, $3)); $$ = term; } | @@ -381,7 +298,7 @@ PE_TERM { struct parse_events__term *term; - ABORT_ON(parse_events__term_num(&term, (int)$1, NULL, 1)); + ABORT_ON(parse_events__term_num(&term, $1, NULL, 1)); $$ = term; } @@ -391,7 +308,7 @@ sep_slash_dc: '/' | ':' | %% -void parse_events_error(void *data __maybe_unused, void *scanner __maybe_unused, - char const *msg __maybe_unused) +void parse_events_error(void *data __used, void *scanner __used, + char const *msg __used) { } diff --git a/trunk/tools/perf/util/parse-options.c b/trunk/tools/perf/util/parse-options.c index 443fc116512b..99d02aa57dbf 100644 --- a/trunk/tools/perf/util/parse-options.c +++ b/trunk/tools/perf/util/parse-options.c @@ -1,7 +1,6 @@ #include "util.h" #include "parse-options.h" #include "cache.h" -#include "header.h" #define OPT_SHORT 1 #define OPT_UNSET 2 @@ -414,8 +413,6 @@ int parse_options(int argc, const char **argv, const struct option *options, { struct parse_opt_ctx_t ctx; - perf_header__set_cmdline(argc, argv); - parse_options_start(&ctx, argc, argv, flags); switch (parse_options_step(&ctx, options, usagestr)) { case PARSE_OPT_HELP: @@ -557,8 +554,7 @@ int parse_options_usage(const char * const *usagestr, } -int parse_opt_verbosity_cb(const struct option *opt, - const char *arg __maybe_unused, +int parse_opt_verbosity_cb(const struct option *opt, const char *arg __used, int unset) { int *target = opt->value; diff --git a/trunk/tools/perf/util/perf_regs.h b/trunk/tools/perf/util/perf_regs.h deleted file mode 100644 index 316dbe7f86ed..000000000000 --- a/trunk/tools/perf/util/perf_regs.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef __PERF_REGS_H -#define __PERF_REGS_H - -#ifndef NO_PERF_REGS -#include -#else -#define PERF_REGS_MASK 0 - -static inline const char *perf_reg_name(int id __maybe_unused) -{ - return NULL; -} -#endif /* NO_PERF_REGS */ -#endif /* __PERF_REGS_H */ diff --git a/trunk/tools/perf/util/pmu.c b/trunk/tools/perf/util/pmu.c index 8a2229da594f..67715a42cd6d 100644 --- a/trunk/tools/perf/util/pmu.c +++ b/trunk/tools/perf/util/pmu.c @@ -9,9 +9,6 @@ #include "util.h" #include "pmu.h" #include "parse-events.h" -#include "cpumap.h" - -#define EVENT_SOURCE_DEVICE_PATH "/bus/event_source/devices/" int perf_pmu_parse(struct list_head *list, char *name); extern FILE *perf_pmu_in; @@ -72,7 +69,7 @@ static int pmu_format(char *name, struct list_head *format) return -1; snprintf(path, PATH_MAX, - "%s" EVENT_SOURCE_DEVICE_PATH "%s/format", sysfs, name); + "%s/bus/event_source/devices/%s/format", sysfs, name); if (stat(path, &st) < 0) return 0; /* no error if format does not exist */ @@ -209,7 +206,7 @@ static int pmu_type(char *name, __u32 *type) return -1; snprintf(path, PATH_MAX, - "%s" EVENT_SOURCE_DEVICE_PATH "%s/type", sysfs, name); + "%s/bus/event_source/devices/%s/type", sysfs, name); if (stat(path, &st) < 0) return -1; @@ -225,62 +222,6 @@ static int pmu_type(char *name, __u32 *type) return ret; } -/* Add all pmus in sysfs to pmu list: */ -static void pmu_read_sysfs(void) -{ - char path[PATH_MAX]; - const char *sysfs; - DIR *dir; - struct dirent *dent; - - sysfs = sysfs_find_mountpoint(); - if (!sysfs) - return; - - snprintf(path, PATH_MAX, - "%s" EVENT_SOURCE_DEVICE_PATH, sysfs); - - dir = opendir(path); - if (!dir) - return; - - while ((dent = readdir(dir))) { - if (!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, "..")) - continue; - /* add to static LIST_HEAD(pmus): */ - perf_pmu__find(dent->d_name); - } - - closedir(dir); -} - -static struct cpu_map *pmu_cpumask(char *name) -{ - struct stat st; - char path[PATH_MAX]; - const char *sysfs; - FILE *file; - struct cpu_map *cpus; - - sysfs = sysfs_find_mountpoint(); - if (!sysfs) - return NULL; - - snprintf(path, PATH_MAX, - "%s/bus/event_source/devices/%s/cpumask", sysfs, name); - - if (stat(path, &st) < 0) - return NULL; - - file = fopen(path, "r"); - if (!file) - return NULL; - - cpus = cpu_map__read(file); - fclose(file); - return cpus; -} - static struct perf_pmu *pmu_lookup(char *name) { struct perf_pmu *pmu; @@ -303,8 +244,6 @@ static struct perf_pmu *pmu_lookup(char *name) if (!pmu) return NULL; - pmu->cpus = pmu_cpumask(name); - pmu_aliases(name, &aliases); INIT_LIST_HEAD(&pmu->format); @@ -328,21 +267,6 @@ static struct perf_pmu *pmu_find(char *name) return NULL; } -struct perf_pmu *perf_pmu__scan(struct perf_pmu *pmu) -{ - /* - * pmu iterator: If pmu is NULL, we start at the begin, - * otherwise return the next pmu. Returns NULL on end. - */ - if (!pmu) { - pmu_read_sysfs(); - pmu = list_prepare_entry(pmu, &pmus, list); - } - list_for_each_entry_continue(pmu, &pmus, list) - return pmu; - return NULL; -} - struct perf_pmu *perf_pmu__find(char *name) { struct perf_pmu *pmu; diff --git a/trunk/tools/perf/util/pmu.h b/trunk/tools/perf/util/pmu.h index 53c7794fc4be..535f2c5258ab 100644 --- a/trunk/tools/perf/util/pmu.h +++ b/trunk/tools/perf/util/pmu.h @@ -28,7 +28,6 @@ struct perf_pmu__alias { struct perf_pmu { char *name; __u32 type; - struct cpu_map *cpus; struct list_head format; struct list_head aliases; struct list_head list; @@ -47,7 +46,5 @@ int perf_pmu__new_format(struct list_head *list, char *name, int config, unsigned long *bits); void perf_pmu__set_format(unsigned long *bits, long from, long to); -struct perf_pmu *perf_pmu__scan(struct perf_pmu *pmu); - int perf_pmu__test(void); #endif /* __PMU_H */ diff --git a/trunk/tools/perf/util/pmu.y b/trunk/tools/perf/util/pmu.y index ec898047ebb9..20ea77e93169 100644 --- a/trunk/tools/perf/util/pmu.y +++ b/trunk/tools/perf/util/pmu.y @@ -86,8 +86,8 @@ PP_VALUE %% -void perf_pmu_error(struct list_head *list __maybe_unused, - char *name __maybe_unused, - char const *msg __maybe_unused) +void perf_pmu_error(struct list_head *list __used, + char *name __used, + char const *msg __used) { } diff --git a/trunk/tools/perf/util/probe-event.c b/trunk/tools/perf/util/probe-event.c index 49a256e6e0a2..0dda25d82d06 100644 --- a/trunk/tools/perf/util/probe-event.c +++ b/trunk/tools/perf/util/probe-event.c @@ -41,7 +41,7 @@ #include "symbol.h" #include "thread.h" #include "debugfs.h" -#include "trace-event.h" /* For __maybe_unused */ +#include "trace-event.h" /* For __unused */ #include "probe-event.h" #include "probe-finder.h" #include "session.h" @@ -647,8 +647,8 @@ static int kprobe_convert_to_perf_probe(struct probe_trace_point *tp, } static int try_to_find_probe_trace_events(struct perf_probe_event *pev, - struct probe_trace_event **tevs __maybe_unused, - int max_tevs __maybe_unused, const char *target) + struct probe_trace_event **tevs __unused, + int max_tevs __unused, const char *target) { if (perf_probe_event_need_dwarf(pev)) { pr_warning("Debuginfo-analysis is not supported.\n"); @@ -661,18 +661,17 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev, return 0; } -int show_line_range(struct line_range *lr __maybe_unused, - const char *module __maybe_unused) +int show_line_range(struct line_range *lr __unused, const char *module __unused) { pr_warning("Debuginfo-analysis is not supported.\n"); return -ENOSYS; } -int show_available_vars(struct perf_probe_event *pevs __maybe_unused, - int npevs __maybe_unused, int max_vls __maybe_unused, - const char *module __maybe_unused, - struct strfilter *filter __maybe_unused, - bool externs __maybe_unused) +int show_available_vars(struct perf_probe_event *pevs __unused, + int npevs __unused, int max_vls __unused, + const char *module __unused, + struct strfilter *filter __unused, + bool externs __unused) { pr_warning("Debuginfo-analysis is not supported.\n"); return -ENOSYS; @@ -1100,7 +1099,6 @@ static int parse_probe_trace_command(const char *cmd, struct probe_trace_point *tp = &tev->point; char pr; char *p; - char *argv0_str = NULL, *fmt, *fmt1_str, *fmt2_str, *fmt3_str; int ret, i, argc; char **argv; @@ -1117,27 +1115,14 @@ static int parse_probe_trace_command(const char *cmd, } /* Scan event and group name. */ - argv0_str = strdup(argv[0]); - if (argv0_str == NULL) { - ret = -ENOMEM; - goto out; - } - fmt1_str = strtok_r(argv0_str, ":", &fmt); - fmt2_str = strtok_r(NULL, "/", &fmt); - fmt3_str = strtok_r(NULL, " \t", &fmt); - if (fmt1_str == NULL || strlen(fmt1_str) != 1 || fmt2_str == NULL - || fmt3_str == NULL) { + ret = sscanf(argv[0], "%c:%a[^/ \t]/%a[^ \t]", + &pr, (float *)(void *)&tev->group, + (float *)(void *)&tev->event); + if (ret != 3) { semantic_error("Failed to parse event name: %s\n", argv[0]); ret = -EINVAL; goto out; } - pr = fmt1_str[0]; - tev->group = strdup(fmt2_str); - tev->event = strdup(fmt3_str); - if (tev->group == NULL || tev->event == NULL) { - ret = -ENOMEM; - goto out; - } pr_debug("Group:%s Event:%s probe:%c\n", tev->group, tev->event, pr); tp->retprobe = (pr == 'r'); @@ -1149,17 +1134,10 @@ static int parse_probe_trace_command(const char *cmd, p++; } else p = argv[1]; - fmt1_str = strtok_r(p, "+", &fmt); - tp->symbol = strdup(fmt1_str); - if (tp->symbol == NULL) { - ret = -ENOMEM; - goto out; - } - fmt2_str = strtok_r(NULL, "", &fmt); - if (fmt2_str == NULL) + ret = sscanf(p, "%a[^+]+%lu", (float *)(void *)&tp->symbol, + &tp->offset); + if (ret == 1) tp->offset = 0; - else - tp->offset = strtoul(fmt2_str, NULL, 10); tev->nargs = argc - 2; tev->args = zalloc(sizeof(struct probe_trace_arg) * tev->nargs); @@ -1183,7 +1161,6 @@ static int parse_probe_trace_command(const char *cmd, } ret = 0; out: - free(argv0_str); argv_free(argv); return ret; } @@ -2206,7 +2183,7 @@ static struct strfilter *available_func_filter; * If a symbol corresponds to a function with global binding and * matches filter return 0. For all others return 1. */ -static int filter_available_functions(struct map *map __maybe_unused, +static int filter_available_functions(struct map *map __unused, struct symbol *sym) { if (sym->binding == STB_GLOBAL && @@ -2330,17 +2307,10 @@ static int convert_name_to_addr(struct perf_probe_event *pev, const char *exec) function = NULL; } if (!pev->group) { - char *ptr1, *ptr2, *exec_copy; + char *ptr1, *ptr2; pev->group = zalloc(sizeof(char *) * 64); - exec_copy = strdup(exec); - if (!exec_copy) { - ret = -ENOMEM; - pr_warning("Failed to copy exec string.\n"); - goto out; - } - - ptr1 = strdup(basename(exec_copy)); + ptr1 = strdup(basename(exec)); if (ptr1) { ptr2 = strpbrk(ptr1, "-._"); if (ptr2) @@ -2349,7 +2319,6 @@ static int convert_name_to_addr(struct perf_probe_event *pev, const char *exec) ptr1); free(ptr1); } - free(exec_copy); } free(pp->function); pp->function = zalloc(sizeof(char *) * MAX_PROBE_ARGS); diff --git a/trunk/tools/perf/util/probe-finder.c b/trunk/tools/perf/util/probe-finder.c index 1daf5c14e751..d448984ed789 100644 --- a/trunk/tools/perf/util/probe-finder.c +++ b/trunk/tools/perf/util/probe-finder.c @@ -207,7 +207,7 @@ static int debuginfo__init_online_kernel_dwarf(struct debuginfo *self, #else /* With older elfutils, this just support kernel module... */ static int debuginfo__init_online_kernel_dwarf(struct debuginfo *self, - Dwarf_Addr addr __maybe_unused) + Dwarf_Addr addr __used) { const char *path = kernel_get_module_path("kernel"); @@ -525,10 +525,8 @@ static int convert_variable_fields(Dwarf_Die *vr_die, const char *varname, return -ENOENT; } /* Verify it is a data structure */ - tag = dwarf_tag(&type); - if (tag != DW_TAG_structure_type && tag != DW_TAG_union_type) { - pr_warning("%s is not a data structure nor an union.\n", - varname); + if (dwarf_tag(&type) != DW_TAG_structure_type) { + pr_warning("%s is not a data structure.\n", varname); return -EINVAL; } @@ -541,9 +539,8 @@ static int convert_variable_fields(Dwarf_Die *vr_die, const char *varname, *ref_ptr = ref; } else { /* Verify it is a data structure */ - if (tag != DW_TAG_structure_type && tag != DW_TAG_union_type) { - pr_warning("%s is not a data structure nor an union.\n", - varname); + if (tag != DW_TAG_structure_type) { + pr_warning("%s is not a data structure.\n", varname); return -EINVAL; } if (field->name[0] == '[') { @@ -570,15 +567,10 @@ static int convert_variable_fields(Dwarf_Die *vr_die, const char *varname, } /* Get the offset of the field */ - if (tag == DW_TAG_union_type) { - offs = 0; - } else { - ret = die_get_data_member_location(die_mem, &offs); - if (ret < 0) { - pr_warning("Failed to get the offset of %s.\n", - field->name); - return ret; - } + ret = die_get_data_member_location(die_mem, &offs); + if (ret < 0) { + pr_warning("Failed to get the offset of %s.\n", field->name); + return ret; } ref->offset += (long)offs; @@ -1427,7 +1419,7 @@ static int line_range_add_line(const char *src, unsigned int lineno, } static int line_range_walk_cb(const char *fname, int lineno, - Dwarf_Addr addr __maybe_unused, + Dwarf_Addr addr __used, void *data) { struct line_finder *lf = data; diff --git a/trunk/tools/perf/util/python-ext-sources b/trunk/tools/perf/util/python-ext-sources index c40c2d33199e..2884e67ee625 100644 --- a/trunk/tools/perf/util/python-ext-sources +++ b/trunk/tools/perf/util/python-ext-sources @@ -1,5 +1,5 @@ # -# List of files needed by perf python extension +# List of files needed by perf python extention # # Each source file must be placed on its own line so that it can be # processed by Makefile and util/setup.py accordingly. @@ -10,12 +10,10 @@ util/ctype.c util/evlist.c util/evsel.c util/cpumap.c -util/hweight.c util/thread_map.c util/util.c util/xyarray.c util/cgroup.c util/debugfs.c -util/rblist.c util/strlist.c ../../lib/rbtree.c diff --git a/trunk/tools/perf/util/python.c b/trunk/tools/perf/util/python.c index 9181bf212fb9..e03b58a48424 100644 --- a/trunk/tools/perf/util/python.c +++ b/trunk/tools/perf/util/python.c @@ -627,7 +627,7 @@ static PyObject *pyrf_evsel__open(struct pyrf_evsel *pevsel, * This will group just the fds for this single evsel, to group * multiple events, use evlist.open(). */ - if (perf_evsel__open(evsel, cpus, threads) < 0) { + if (perf_evsel__open(evsel, cpus, threads, group, NULL) < 0) { PyErr_SetFromErrno(PyExc_OSError); return NULL; } @@ -672,7 +672,7 @@ struct pyrf_evlist { }; static int pyrf_evlist__init(struct pyrf_evlist *pevlist, - PyObject *args, PyObject *kwargs __maybe_unused) + PyObject *args, PyObject *kwargs __used) { PyObject *pcpus = NULL, *pthreads = NULL; struct cpu_map *cpus; @@ -733,8 +733,7 @@ static PyObject *pyrf_evlist__poll(struct pyrf_evlist *pevlist, } static PyObject *pyrf_evlist__get_pollfd(struct pyrf_evlist *pevlist, - PyObject *args __maybe_unused, - PyObject *kwargs __maybe_unused) + PyObject *args __used, PyObject *kwargs __used) { struct perf_evlist *evlist = &pevlist->evlist; PyObject *list = PyList_New(0); @@ -766,8 +765,7 @@ static PyObject *pyrf_evlist__get_pollfd(struct pyrf_evlist *pevlist, static PyObject *pyrf_evlist__add(struct pyrf_evlist *pevlist, - PyObject *args, - PyObject *kwargs __maybe_unused) + PyObject *args, PyObject *kwargs __used) { struct perf_evlist *evlist = &pevlist->evlist; PyObject *pevsel; @@ -799,13 +797,17 @@ static PyObject *pyrf_evlist__read_on_cpu(struct pyrf_evlist *pevlist, event = perf_evlist__mmap_read(evlist, cpu); if (event != NULL) { + struct perf_evsel *first; PyObject *pyevent = pyrf_event__new(event); struct pyrf_event *pevent = (struct pyrf_event *)pyevent; if (pyevent == NULL) return PyErr_NoMemory(); - err = perf_evlist__parse_sample(evlist, event, &pevent->sample); + first = list_entry(evlist->entries.next, struct perf_evsel, node); + err = perf_event__parse_sample(event, first->attr.sample_type, + perf_evsel__sample_size(first), + sample_id_all, &pevent->sample, false); if (err) return PyErr_Format(PyExc_OSError, "perf: can't parse sample, err=%d", err); @@ -826,10 +828,7 @@ static PyObject *pyrf_evlist__open(struct pyrf_evlist *pevlist, if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OOii", kwlist, &group)) return NULL; - if (group) - perf_evlist__set_leader(evlist); - - if (perf_evlist__open(evlist) < 0) { + if (perf_evlist__open(evlist, group) < 0) { PyErr_SetFromErrno(PyExc_OSError); return NULL; } diff --git a/trunk/tools/perf/util/rblist.c b/trunk/tools/perf/util/rblist.c deleted file mode 100644 index 0171fb611004..000000000000 --- a/trunk/tools/perf/util/rblist.c +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Based on strlist.c by: - * (c) 2009 Arnaldo Carvalho de Melo - * - * Licensed under the GPLv2. - */ - -#include -#include -#include - -#include "rblist.h" - -int rblist__add_node(struct rblist *rblist, const void *new_entry) -{ - struct rb_node **p = &rblist->entries.rb_node; - struct rb_node *parent = NULL, *new_node; - - while (*p != NULL) { - int rc; - - parent = *p; - - rc = rblist->node_cmp(parent, new_entry); - if (rc > 0) - p = &(*p)->rb_left; - else if (rc < 0) - p = &(*p)->rb_right; - else - return -EEXIST; - } - - new_node = rblist->node_new(rblist, new_entry); - if (new_node == NULL) - return -ENOMEM; - - rb_link_node(new_node, parent, p); - rb_insert_color(new_node, &rblist->entries); - ++rblist->nr_entries; - - return 0; -} - -void rblist__remove_node(struct rblist *rblist, struct rb_node *rb_node) -{ - rb_erase(rb_node, &rblist->entries); - rblist->node_delete(rblist, rb_node); -} - -struct rb_node *rblist__find(struct rblist *rblist, const void *entry) -{ - struct rb_node **p = &rblist->entries.rb_node; - struct rb_node *parent = NULL; - - while (*p != NULL) { - int rc; - - parent = *p; - - rc = rblist->node_cmp(parent, entry); - if (rc > 0) - p = &(*p)->rb_left; - else if (rc < 0) - p = &(*p)->rb_right; - else - return parent; - } - - return NULL; -} - -void rblist__init(struct rblist *rblist) -{ - if (rblist != NULL) { - rblist->entries = RB_ROOT; - rblist->nr_entries = 0; - } - - return; -} - -void rblist__delete(struct rblist *rblist) -{ - if (rblist != NULL) { - struct rb_node *pos, *next = rb_first(&rblist->entries); - - while (next) { - pos = next; - next = rb_next(pos); - rb_erase(pos, &rblist->entries); - rblist->node_delete(rblist, pos); - } - free(rblist); - } -} - -struct rb_node *rblist__entry(const struct rblist *rblist, unsigned int idx) -{ - struct rb_node *node; - - for (node = rb_first(&rblist->entries); node; node = rb_next(node)) { - if (!idx--) - return node; - } - - return NULL; -} diff --git a/trunk/tools/perf/util/rblist.h b/trunk/tools/perf/util/rblist.h deleted file mode 100644 index 6d0cae5ae83d..000000000000 --- a/trunk/tools/perf/util/rblist.h +++ /dev/null @@ -1,47 +0,0 @@ -#ifndef __PERF_RBLIST_H -#define __PERF_RBLIST_H - -#include -#include - -/* - * create node structs of the form: - * struct my_node { - * struct rb_node rb_node; - * ... my data ... - * }; - * - * create list structs of the form: - * struct mylist { - * struct rblist rblist; - * ... my data ... - * }; - */ - -struct rblist { - struct rb_root entries; - unsigned int nr_entries; - - int (*node_cmp)(struct rb_node *rbn, const void *entry); - struct rb_node *(*node_new)(struct rblist *rlist, const void *new_entry); - void (*node_delete)(struct rblist *rblist, struct rb_node *rb_node); -}; - -void rblist__init(struct rblist *rblist); -void rblist__delete(struct rblist *rblist); -int rblist__add_node(struct rblist *rblist, const void *new_entry); -void rblist__remove_node(struct rblist *rblist, struct rb_node *rb_node); -struct rb_node *rblist__find(struct rblist *rblist, const void *entry); -struct rb_node *rblist__entry(const struct rblist *rblist, unsigned int idx); - -static inline bool rblist__empty(const struct rblist *rblist) -{ - return rblist->nr_entries == 0; -} - -static inline unsigned int rblist__nr_entries(const struct rblist *rblist) -{ - return rblist->nr_entries; -} - -#endif /* __PERF_RBLIST_H */ diff --git a/trunk/tools/perf/util/scripting-engines/trace-event-perl.c b/trunk/tools/perf/util/scripting-engines/trace-event-perl.c index f80605eb1855..02dfa19a467f 100644 --- a/trunk/tools/perf/util/scripting-engines/trace-event-perl.c +++ b/trunk/tools/perf/util/scripting-engines/trace-event-perl.c @@ -25,16 +25,16 @@ #include #include -#include "../util.h" -#include -#include - #include "../../perf.h" +#include "../util.h" #include "../thread.h" #include "../event.h" #include "../trace-event.h" #include "../evsel.h" +#include +#include + void boot_Perf__Trace__Context(pTHX_ CV *cv); void boot_DynaLoader(pTHX_ CV *cv); typedef PerlInterpreter * INTERP; @@ -237,16 +237,16 @@ static void define_event_symbols(struct event_format *event, define_event_symbols(event, ev_name, args->next); } -static inline struct event_format *find_cache_event(struct perf_evsel *evsel) +static inline +struct event_format *find_cache_event(struct pevent *pevent, int type) { static char ev_name[256]; struct event_format *event; - int type = evsel->attr.config; if (events[type]) return events[type]; - events[type] = event = evsel->tp_format; + events[type] = event = pevent_find_event(pevent, type); if (!event) return NULL; @@ -257,22 +257,23 @@ static inline struct event_format *find_cache_event(struct perf_evsel *evsel) return event; } -static void perl_process_tracepoint(union perf_event *perf_event __maybe_unused, +static void perl_process_tracepoint(union perf_event *perf_event __unused, + struct pevent *pevent, struct perf_sample *sample, struct perf_evsel *evsel, - struct machine *machine __maybe_unused, - struct addr_location *al) + struct machine *machine __unused, + struct thread *thread) { struct format_field *field; static char handler[256]; unsigned long long val; unsigned long s, ns; struct event_format *event; + int type; int pid; int cpu = sample->cpu; void *data = sample->raw_data; unsigned long long nsecs = sample->time; - struct thread *thread = al->thread; char *comm = thread->comm; dSP; @@ -280,11 +281,13 @@ static void perl_process_tracepoint(union perf_event *perf_event __maybe_unused, if (evsel->attr.type != PERF_TYPE_TRACEPOINT) return; - event = find_cache_event(evsel); + type = trace_parse_common_type(pevent, data); + + event = find_cache_event(pevent, type); if (!event) - die("ug! no event found for type %" PRIu64, evsel->attr.config); + die("ug! no event found for type %d", type); - pid = raw_field_value(event, "common_pid", data); + pid = trace_parse_common_pid(pevent, data); sprintf(handler, "%s::%s", event->system, event->name); @@ -317,7 +320,7 @@ static void perl_process_tracepoint(union perf_event *perf_event __maybe_unused, offset = field->offset; XPUSHs(sv_2mortal(newSVpv((char *)data + offset, 0))); } else { /* FIELD_IS_NUMERIC */ - val = read_size(event, data + field->offset, + val = read_size(pevent, data + field->offset, field->size); if (field->flags & FIELD_IS_SIGNED) { XPUSHs(sv_2mortal(newSViv(val))); @@ -346,11 +349,11 @@ static void perl_process_tracepoint(union perf_event *perf_event __maybe_unused, LEAVE; } -static void perl_process_event_generic(union perf_event *event, +static void perl_process_event_generic(union perf_event *pevent __unused, struct perf_sample *sample, - struct perf_evsel *evsel, - struct machine *machine __maybe_unused, - struct addr_location *al __maybe_unused) + struct perf_evsel *evsel __unused, + struct machine *machine __unused, + struct thread *thread __unused) { dSP; @@ -360,7 +363,7 @@ static void perl_process_event_generic(union perf_event *event, ENTER; SAVETMPS; PUSHMARK(SP); - XPUSHs(sv_2mortal(newSVpvn((const char *)event, event->header.size))); + XPUSHs(sv_2mortal(newSVpvn((const char *)pevent, pevent->header.size))); XPUSHs(sv_2mortal(newSVpvn((const char *)&evsel->attr, sizeof(evsel->attr)))); XPUSHs(sv_2mortal(newSVpvn((const char *)sample, sizeof(*sample)))); XPUSHs(sv_2mortal(newSVpvn((const char *)sample->raw_data, sample->raw_size))); @@ -373,13 +376,14 @@ static void perl_process_event_generic(union perf_event *event, } static void perl_process_event(union perf_event *event, + struct pevent *pevent, struct perf_sample *sample, struct perf_evsel *evsel, struct machine *machine, - struct addr_location *al) + struct thread *thread) { - perl_process_tracepoint(event, sample, evsel, machine, al); - perl_process_event_generic(event, sample, evsel, machine, al); + perl_process_tracepoint(event, pevent, sample, evsel, machine, thread); + perl_process_event_generic(event, sample, evsel, machine, thread); } static void run_start_sub(void) diff --git a/trunk/tools/perf/util/scripting-engines/trace-event-python.c b/trunk/tools/perf/util/scripting-engines/trace-event-python.c index 730c6630cba5..ce4d1b0c3862 100644 --- a/trunk/tools/perf/util/scripting-engines/trace-event-python.c +++ b/trunk/tools/perf/util/scripting-engines/trace-event-python.c @@ -27,12 +27,10 @@ #include #include "../../perf.h" -#include "../evsel.h" #include "../util.h" #include "../event.h" #include "../thread.h" #include "../trace-event.h" -#include "../evsel.h" PyMODINIT_FUNC initperf_trace_context(void); @@ -196,21 +194,16 @@ static void define_event_symbols(struct event_format *event, define_event_symbols(event, ev_name, args->next); } -static inline struct event_format *find_cache_event(struct perf_evsel *evsel) +static inline +struct event_format *find_cache_event(struct pevent *pevent, int type) { static char ev_name[256]; struct event_format *event; - int type = evsel->attr.config; - /* - * XXX: Do we really need to cache this since now we have evsel->tp_format - * cached already? Need to re-read this "cache" routine that as well calls - * define_event_symbols() :-\ - */ if (events[type]) return events[type]; - events[type] = event = evsel->tp_format; + events[type] = event = pevent_find_event(pevent, type); if (!event) return NULL; @@ -221,12 +214,12 @@ static inline struct event_format *find_cache_event(struct perf_evsel *evsel) return event; } -static void python_process_tracepoint(union perf_event *perf_event - __maybe_unused, +static void python_process_event(union perf_event *perf_event __unused, + struct pevent *pevent, struct perf_sample *sample, - struct perf_evsel *evsel, - struct machine *machine __maybe_unused, - struct addr_location *al) + struct perf_evsel *evsel __unused, + struct machine *machine __unused, + struct thread *thread) { PyObject *handler, *retval, *context, *t, *obj, *dict = NULL; static char handler_name[256]; @@ -235,22 +228,24 @@ static void python_process_tracepoint(union perf_event *perf_event unsigned long s, ns; struct event_format *event; unsigned n = 0; + int type; int pid; int cpu = sample->cpu; void *data = sample->raw_data; unsigned long long nsecs = sample->time; - struct thread *thread = al->thread; char *comm = thread->comm; t = PyTuple_New(MAX_FIELDS); if (!t) Py_FatalError("couldn't create Python tuple"); - event = find_cache_event(evsel); + type = trace_parse_common_type(pevent, data); + + event = find_cache_event(pevent, type); if (!event) - die("ug! no event found for type %d", (int)evsel->attr.config); + die("ug! no event found for type %d", type); - pid = raw_field_value(event, "common_pid", data); + pid = trace_parse_common_pid(pevent, data); sprintf(handler_name, "%s__%s", event->system, event->name); @@ -295,7 +290,7 @@ static void python_process_tracepoint(union perf_event *perf_event offset = field->offset; obj = PyString_FromString((char *)data + offset); } else { /* FIELD_IS_NUMERIC */ - val = read_size(event, data + field->offset, + val = read_size(pevent, data + field->offset, field->size); if (field->flags & FIELD_IS_SIGNED) { if ((long long)val >= LONG_MIN && @@ -340,84 +335,6 @@ static void python_process_tracepoint(union perf_event *perf_event Py_DECREF(t); } -static void python_process_general_event(union perf_event *perf_event - __maybe_unused, - struct perf_sample *sample, - struct perf_evsel *evsel, - struct machine *machine __maybe_unused, - struct addr_location *al) -{ - PyObject *handler, *retval, *t, *dict; - static char handler_name[64]; - unsigned n = 0; - struct thread *thread = al->thread; - - /* - * Use the MAX_FIELDS to make the function expandable, though - * currently there is only one item for the tuple. - */ - t = PyTuple_New(MAX_FIELDS); - if (!t) - Py_FatalError("couldn't create Python tuple"); - - dict = PyDict_New(); - if (!dict) - Py_FatalError("couldn't create Python dictionary"); - - snprintf(handler_name, sizeof(handler_name), "%s", "process_event"); - - handler = PyDict_GetItemString(main_dict, handler_name); - if (!handler || !PyCallable_Check(handler)) - goto exit; - - PyDict_SetItemString(dict, "ev_name", PyString_FromString(perf_evsel__name(evsel))); - PyDict_SetItemString(dict, "attr", PyString_FromStringAndSize( - (const char *)&evsel->attr, sizeof(evsel->attr))); - PyDict_SetItemString(dict, "sample", PyString_FromStringAndSize( - (const char *)sample, sizeof(*sample))); - PyDict_SetItemString(dict, "raw_buf", PyString_FromStringAndSize( - (const char *)sample->raw_data, sample->raw_size)); - PyDict_SetItemString(dict, "comm", - PyString_FromString(thread->comm)); - if (al->map) { - PyDict_SetItemString(dict, "dso", - PyString_FromString(al->map->dso->name)); - } - if (al->sym) { - PyDict_SetItemString(dict, "symbol", - PyString_FromString(al->sym->name)); - } - - PyTuple_SetItem(t, n++, dict); - if (_PyTuple_Resize(&t, n) == -1) - Py_FatalError("error resizing Python tuple"); - - retval = PyObject_CallObject(handler, t); - if (retval == NULL) - handler_call_die(handler_name); -exit: - Py_DECREF(dict); - Py_DECREF(t); -} - -static void python_process_event(union perf_event *perf_event, - struct perf_sample *sample, - struct perf_evsel *evsel, - struct machine *machine, - struct addr_location *al) -{ - switch (evsel->attr.type) { - case PERF_TYPE_TRACEPOINT: - python_process_tracepoint(perf_event, sample, evsel, - machine, al); - break; - /* Reserve for future process_hw/sw/raw APIs */ - default: - python_process_general_event(perf_event, sample, evsel, - machine, al); - } -} - static int run_start_sub(void) { PyObject *handler, *retval; diff --git a/trunk/tools/perf/util/session.c b/trunk/tools/perf/util/session.c index 8cdd23239c90..8e4f0755d2aa 100644 --- a/trunk/tools/perf/util/session.c +++ b/trunk/tools/perf/util/session.c @@ -15,9 +15,6 @@ #include "util.h" #include "cpumap.h" #include "event-parse.h" -#include "perf_regs.h" -#include "unwind.h" -#include "vdso.h" static int perf_session__open(struct perf_session *self, bool force) { @@ -83,12 +80,14 @@ static int perf_session__open(struct perf_session *self, bool force) return -1; } -void perf_session__set_id_hdr_size(struct perf_session *session) +void perf_session__update_sample_type(struct perf_session *self) { - u16 id_hdr_size = perf_evlist__id_hdr_size(session->evlist); - - session->host_machine.id_hdr_size = id_hdr_size; - machines__set_id_hdr_size(&session->machines, id_hdr_size); + self->sample_type = perf_evlist__sample_type(self->evlist); + self->sample_size = __perf_evsel__sample_size(self->sample_type); + self->sample_id_all = perf_evlist__sample_id_all(self->evlist); + self->id_hdr_size = perf_evlist__id_hdr_size(self->evlist); + self->host_machine.id_hdr_size = self->id_hdr_size; + machines__set_id_hdr_size(&self->machines, self->id_hdr_size); } int perf_session__create_kernel_maps(struct perf_session *self) @@ -148,7 +147,7 @@ struct perf_session *perf_session__new(const char *filename, int mode, if (mode == O_RDONLY) { if (perf_session__open(self, force) < 0) goto out_delete; - perf_session__set_id_hdr_size(self); + perf_session__update_sample_type(self); } else if (mode == O_WRONLY) { /* * In O_RDONLY mode this will be performed when reading the @@ -159,7 +158,7 @@ struct perf_session *perf_session__new(const char *filename, int mode, } if (tool && tool->ordering_requires_timestamps && - tool->ordered_samples && !perf_evlist__sample_id_all(self->evlist)) { + tool->ordered_samples && !self->sample_id_all) { dump_printf("WARNING: No sample_id_all support, falling back to unordered processing\n"); tool->ordered_samples = false; } @@ -212,7 +211,6 @@ void perf_session__delete(struct perf_session *self) machine__exit(&self->host_machine); close(self->fd); free(self); - vdso__exit(); } void machine__remove_thread(struct machine *self, struct thread *th) @@ -292,11 +290,10 @@ struct branch_info *machine__resolve_bstack(struct machine *self, return bi; } -static int machine__resolve_callchain_sample(struct machine *machine, - struct thread *thread, - struct ip_callchain *chain, - struct symbol **parent) - +int machine__resolve_callchain(struct machine *self, + struct thread *thread, + struct ip_callchain *chain, + struct symbol **parent) { u8 cpumode = PERF_RECORD_MISC_USER; unsigned int i; @@ -321,14 +318,11 @@ static int machine__resolve_callchain_sample(struct machine *machine, if (ip >= PERF_CONTEXT_MAX) { switch (ip) { case PERF_CONTEXT_HV: - cpumode = PERF_RECORD_MISC_HYPERVISOR; - break; + cpumode = PERF_RECORD_MISC_HYPERVISOR; break; case PERF_CONTEXT_KERNEL: - cpumode = PERF_RECORD_MISC_KERNEL; - break; + cpumode = PERF_RECORD_MISC_KERNEL; break; case PERF_CONTEXT_USER: - cpumode = PERF_RECORD_MISC_USER; - break; + cpumode = PERF_RECORD_MISC_USER; break; default: pr_debug("invalid callchain context: " "%"PRId64"\n", (s64) ip); @@ -343,7 +337,7 @@ static int machine__resolve_callchain_sample(struct machine *machine, } al.filtered = false; - thread__find_addr_location(thread, machine, cpumode, + thread__find_addr_location(thread, self, cpumode, MAP__FUNCTION, ip, &al, NULL); if (al.sym != NULL) { if (sort__has_parent && !*parent && @@ -362,92 +356,49 @@ static int machine__resolve_callchain_sample(struct machine *machine, return 0; } -static int unwind_entry(struct unwind_entry *entry, void *arg) -{ - struct callchain_cursor *cursor = arg; - return callchain_cursor_append(cursor, entry->ip, - entry->map, entry->sym); -} - -int machine__resolve_callchain(struct machine *machine, - struct perf_evsel *evsel, - struct thread *thread, - struct perf_sample *sample, - struct symbol **parent) - -{ - int ret; - - callchain_cursor_reset(&callchain_cursor); - - ret = machine__resolve_callchain_sample(machine, thread, - sample->callchain, parent); - if (ret) - return ret; - - /* Can we do dwarf post unwind? */ - if (!((evsel->attr.sample_type & PERF_SAMPLE_REGS_USER) && - (evsel->attr.sample_type & PERF_SAMPLE_STACK_USER))) - return 0; - - /* Bail out if nothing was captured. */ - if ((!sample->user_regs.regs) || - (!sample->user_stack.size)) - return 0; - - return unwind__get_entries(unwind_entry, &callchain_cursor, machine, - thread, evsel->attr.sample_regs_user, - sample); - -} - -static int process_event_synth_tracing_data_stub(union perf_event *event - __maybe_unused, - struct perf_session *session - __maybe_unused) +static int process_event_synth_tracing_data_stub(union perf_event *event __used, + struct perf_session *session __used) { dump_printf(": unhandled!\n"); return 0; } -static int process_event_synth_attr_stub(union perf_event *event __maybe_unused, - struct perf_evlist **pevlist - __maybe_unused) +static int process_event_synth_attr_stub(union perf_event *event __used, + struct perf_evlist **pevlist __used) { dump_printf(": unhandled!\n"); return 0; } -static int process_event_sample_stub(struct perf_tool *tool __maybe_unused, - union perf_event *event __maybe_unused, - struct perf_sample *sample __maybe_unused, - struct perf_evsel *evsel __maybe_unused, - struct machine *machine __maybe_unused) +static int process_event_sample_stub(struct perf_tool *tool __used, + union perf_event *event __used, + struct perf_sample *sample __used, + struct perf_evsel *evsel __used, + struct machine *machine __used) { dump_printf(": unhandled!\n"); return 0; } -static int process_event_stub(struct perf_tool *tool __maybe_unused, - union perf_event *event __maybe_unused, - struct perf_sample *sample __maybe_unused, - struct machine *machine __maybe_unused) +static int process_event_stub(struct perf_tool *tool __used, + union perf_event *event __used, + struct perf_sample *sample __used, + struct machine *machine __used) { dump_printf(": unhandled!\n"); return 0; } -static int process_finished_round_stub(struct perf_tool *tool __maybe_unused, - union perf_event *event __maybe_unused, - struct perf_session *perf_session - __maybe_unused) +static int process_finished_round_stub(struct perf_tool *tool __used, + union perf_event *event __used, + struct perf_session *perf_session __used) { dump_printf(": unhandled!\n"); return 0; } -static int process_event_type_stub(struct perf_tool *tool __maybe_unused, - union perf_event *event __maybe_unused) +static int process_event_type_stub(struct perf_tool *tool __used, + union perf_event *event __used) { dump_printf(": unhandled!\n"); return 0; @@ -524,7 +475,7 @@ static void swap_sample_id_all(union perf_event *event, void *data) } static void perf_event__all64_swap(union perf_event *event, - bool sample_id_all __maybe_unused) + bool sample_id_all __used) { struct perf_event_header *hdr = &event->header; mem_bswap_64(hdr + 1, event->header.size - sizeof(*hdr)); @@ -538,7 +489,7 @@ static void perf_event__comm_swap(union perf_event *event, bool sample_id_all) if (sample_id_all) { void *data = &event->comm.comm; - data += PERF_ALIGN(strlen(data) + 1, sizeof(u64)); + data += ALIGN(strlen(data) + 1, sizeof(u64)); swap_sample_id_all(event, data); } } @@ -555,7 +506,7 @@ static void perf_event__mmap_swap(union perf_event *event, if (sample_id_all) { void *data = &event->mmap.filename; - data += PERF_ALIGN(strlen(data) + 1, sizeof(u64)); + data += ALIGN(strlen(data) + 1, sizeof(u64)); swap_sample_id_all(event, data); } } @@ -635,7 +586,7 @@ void perf_event__attr_swap(struct perf_event_attr *attr) } static void perf_event__hdr_attr_swap(union perf_event *event, - bool sample_id_all __maybe_unused) + bool sample_id_all __used) { size_t size; @@ -647,14 +598,14 @@ static void perf_event__hdr_attr_swap(union perf_event *event, } static void perf_event__event_type_swap(union perf_event *event, - bool sample_id_all __maybe_unused) + bool sample_id_all __used) { event->event_type.event_type.event_id = bswap_64(event->event_type.event_type.event_id); } static void perf_event__tracing_data_swap(union perf_event *event, - bool sample_id_all __maybe_unused) + bool sample_id_all __used) { event->tracing_data.size = bswap_32(event->tracing_data.size); } @@ -703,7 +654,7 @@ static int perf_session_deliver_event(struct perf_session *session, struct perf_tool *tool, u64 file_offset); -static int flush_sample_queue(struct perf_session *s, +static void flush_sample_queue(struct perf_session *s, struct perf_tool *tool) { struct ordered_samples *os = &s->ordered_samples; @@ -716,21 +667,18 @@ static int flush_sample_queue(struct perf_session *s, int ret; if (!tool->ordered_samples || !limit) - return 0; + return; list_for_each_entry_safe(iter, tmp, head, list) { if (iter->timestamp > limit) break; - ret = perf_evlist__parse_sample(s->evlist, iter->event, &sample); + ret = perf_session__parse_sample(s, iter->event, &sample); if (ret) pr_err("Can't parse sample, err = %d\n", ret); - else { - ret = perf_session_deliver_event(s, iter->event, &sample, tool, - iter->file_offset); - if (ret) - return ret; - } + else + perf_session_deliver_event(s, iter->event, &sample, tool, + iter->file_offset); os->last_flush = iter->timestamp; list_del(&iter->list); @@ -750,8 +698,6 @@ static int flush_sample_queue(struct perf_session *s, } os->nr_samples = 0; - - return 0; } /* @@ -794,14 +740,13 @@ static int flush_sample_queue(struct perf_session *s, * etc... */ static int process_finished_round(struct perf_tool *tool, - union perf_event *event __maybe_unused, + union perf_event *event __used, struct perf_session *session) { - int ret = flush_sample_queue(session, tool); - if (!ret) - session->ordered_samples.next_flush = session->ordered_samples.max_timestamp; + flush_sample_queue(session, tool); + session->ordered_samples.next_flush = session->ordered_samples.max_timestamp; - return ret; + return 0; } /* The queue is ordered by time */ @@ -916,50 +861,20 @@ static void branch_stack__printf(struct perf_sample *sample) sample->branch_stack->entries[i].to); } -static void regs_dump__printf(u64 mask, u64 *regs) -{ - unsigned rid, i = 0; - - for_each_set_bit(rid, (unsigned long *) &mask, sizeof(mask) * 8) { - u64 val = regs[i++]; - - printf(".... %-5s 0x%" PRIx64 "\n", - perf_reg_name(rid), val); - } -} - -static void regs_user__printf(struct perf_sample *sample, u64 mask) -{ - struct regs_dump *user_regs = &sample->user_regs; - - if (user_regs->regs) { - printf("... user regs: mask 0x%" PRIx64 "\n", mask); - regs_dump__printf(mask, user_regs->regs); - } -} - -static void stack_user__printf(struct stack_dump *dump) -{ - printf("... ustack: size %" PRIu64 ", offset 0x%x\n", - dump->size, dump->offset); -} - static void perf_session__print_tstamp(struct perf_session *session, union perf_event *event, struct perf_sample *sample) { - u64 sample_type = perf_evlist__sample_type(session->evlist); - if (event->header.type != PERF_RECORD_SAMPLE && - !perf_evlist__sample_id_all(session->evlist)) { + !session->sample_id_all) { fputs("-1 -1 ", stdout); return; } - if ((sample_type & PERF_SAMPLE_CPU)) + if ((session->sample_type & PERF_SAMPLE_CPU)) printf("%u ", sample->cpu); - if (sample_type & PERF_SAMPLE_TIME) + if (session->sample_type & PERF_SAMPLE_TIME) printf("%" PRIu64 " ", sample->time); } @@ -981,11 +896,9 @@ static void dump_event(struct perf_session *session, union perf_event *event, event->header.size, perf_event__name(event->header.type)); } -static void dump_sample(struct perf_evsel *evsel, union perf_event *event, +static void dump_sample(struct perf_session *session, union perf_event *event, struct perf_sample *sample) { - u64 sample_type; - if (!dump_trace) return; @@ -993,19 +906,11 @@ static void dump_sample(struct perf_evsel *evsel, union perf_event *event, event->header.misc, sample->pid, sample->tid, sample->ip, sample->period, sample->addr); - sample_type = evsel->attr.sample_type; - - if (sample_type & PERF_SAMPLE_CALLCHAIN) + if (session->sample_type & PERF_SAMPLE_CALLCHAIN) callchain__printf(sample); - if (sample_type & PERF_SAMPLE_BRANCH_STACK) + if (session->sample_type & PERF_SAMPLE_BRANCH_STACK) branch_stack__printf(sample); - - if (sample_type & PERF_SAMPLE_REGS_USER) - regs_user__printf(sample, evsel->attr.sample_regs_user); - - if (sample_type & PERF_SAMPLE_STACK_USER) - stack_user__printf(&sample->user_stack); } static struct machine * @@ -1063,7 +968,7 @@ static int perf_session_deliver_event(struct perf_session *session, switch (event->header.type) { case PERF_RECORD_SAMPLE: - dump_sample(evsel, event, sample); + dump_sample(session, event, sample); if (evsel == NULL) { ++session->hists.stats.nr_unknown_id; return 0; @@ -1101,7 +1006,7 @@ static int perf_session__preprocess_sample(struct perf_session *session, union perf_event *event, struct perf_sample *sample) { if (event->header.type != PERF_RECORD_SAMPLE || - !(perf_evlist__sample_type(session->evlist) & PERF_SAMPLE_CALLCHAIN)) + !(session->sample_type & PERF_SAMPLE_CALLCHAIN)) return 0; if (!ip_callchain__valid(sample->callchain, event)) { @@ -1125,7 +1030,7 @@ static int perf_session__process_user_event(struct perf_session *session, union case PERF_RECORD_HEADER_ATTR: err = tool->attr(event, &session->evlist); if (err == 0) - perf_session__set_id_hdr_size(session); + perf_session__update_sample_type(session); return err; case PERF_RECORD_HEADER_EVENT_TYPE: return tool->event_type(tool, event); @@ -1160,7 +1065,7 @@ static int perf_session__process_event(struct perf_session *session, int ret; if (session->header.needs_swap) - event_swap(event, perf_evlist__sample_id_all(session->evlist)); + event_swap(event, session->sample_id_all); if (event->header.type >= PERF_RECORD_HEADER_MAX) return -EINVAL; @@ -1173,7 +1078,7 @@ static int perf_session__process_event(struct perf_session *session, /* * For all kernel events we get the sample data */ - ret = perf_evlist__parse_sample(session->evlist, event, &sample); + ret = perf_session__parse_sample(session, event, &sample); if (ret) return ret; @@ -1458,7 +1363,7 @@ int __perf_session__process_events(struct perf_session *session, err = 0; /* do the final flush for ordered samples */ session->ordered_samples.next_flush = ULLONG_MAX; - err = flush_sample_queue(session, tool); + flush_sample_queue(session, tool); out_err: perf_session__warn_about_errors(session, tool); perf_session_free_sample_buffers(session); @@ -1484,9 +1389,9 @@ int perf_session__process_events(struct perf_session *self, return err; } -bool perf_session__has_traces(struct perf_session *session, const char *msg) +bool perf_session__has_traces(struct perf_session *self, const char *msg) { - if (!(perf_evlist__sample_type(session->evlist) & PERF_SAMPLE_RAW)) { + if (!(self->sample_type & PERF_SAMPLE_RAW)) { pr_err("No trace sample to read. Did you call 'perf %s'?\n", msg); return false; } @@ -1587,9 +1492,9 @@ struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session, return NULL; } -void perf_evsel__print_ip(struct perf_evsel *evsel, union perf_event *event, - struct perf_sample *sample, struct machine *machine, - int print_sym, int print_dso, int print_symoffset) +void perf_event__print_ip(union perf_event *event, struct perf_sample *sample, + struct machine *machine, int print_sym, + int print_dso, int print_symoffset) { struct addr_location al; struct callchain_cursor_node *node; @@ -1603,9 +1508,8 @@ void perf_evsel__print_ip(struct perf_evsel *evsel, union perf_event *event, if (symbol_conf.use_callchain && sample->callchain) { - - if (machine__resolve_callchain(machine, evsel, al.thread, - sample, NULL) != 0) { + if (machine__resolve_callchain(machine, al.thread, + sample->callchain, NULL) != 0) { if (verbose) error("Failed to resolve callchain. Skipping\n"); return; diff --git a/trunk/tools/perf/util/session.h b/trunk/tools/perf/util/session.h index aab414fbb64b..7c435bde6eb0 100644 --- a/trunk/tools/perf/util/session.h +++ b/trunk/tools/perf/util/session.h @@ -36,12 +36,18 @@ struct perf_session { struct pevent *pevent; /* * FIXME: Need to split this up further, we need global - * stats + per event stats. + * stats + per event stats. 'perf diff' also needs + * to properly support multiple events in a single + * perf.data file. */ struct hists hists; + u64 sample_type; + int sample_size; int fd; bool fd_pipe; bool repipe; + bool sample_id_all; + u16 id_hdr_size; int cwdlen; char *cwd; struct ordered_samples ordered_samples; @@ -80,7 +86,7 @@ void perf_event__attr_swap(struct perf_event_attr *attr); int perf_session__create_kernel_maps(struct perf_session *self); -void perf_session__set_id_hdr_size(struct perf_session *session); +void perf_session__update_sample_type(struct perf_session *self); void perf_session__remove_thread(struct perf_session *self, struct thread *th); static inline @@ -124,12 +130,30 @@ size_t perf_session__fprintf_dsos_buildid(struct perf_session *self, size_t perf_session__fprintf_nr_events(struct perf_session *session, FILE *fp); +static inline int perf_session__parse_sample(struct perf_session *session, + const union perf_event *event, + struct perf_sample *sample) +{ + return perf_event__parse_sample(event, session->sample_type, + session->sample_size, + session->sample_id_all, sample, + session->header.needs_swap); +} + +static inline int perf_session__synthesize_sample(struct perf_session *session, + union perf_event *event, + const struct perf_sample *sample) +{ + return perf_event__synthesize_sample(event, session->sample_type, + sample, session->header.needs_swap); +} + struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session, unsigned int type); -void perf_evsel__print_ip(struct perf_evsel *evsel, union perf_event *event, - struct perf_sample *sample, struct machine *machine, - int print_sym, int print_dso, int print_symoffset); +void perf_event__print_ip(union perf_event *event, struct perf_sample *sample, + struct machine *machine, int print_sym, + int print_dso, int print_symoffset); int perf_session__cpu_bitmap(struct perf_session *session, const char *cpu_list, unsigned long *cpu_bitmap); diff --git a/trunk/tools/perf/util/sort.c b/trunk/tools/perf/util/sort.c index b5b1b9211960..0f5a0a496bc4 100644 --- a/trunk/tools/perf/util/sort.c +++ b/trunk/tools/perf/util/sort.c @@ -8,11 +8,12 @@ const char default_sort_order[] = "comm,dso,symbol"; const char *sort_order = default_sort_order; int sort__need_collapse = 0; int sort__has_parent = 0; -int sort__has_sym = 0; int sort__branch_mode = -1; /* -1 = means not set */ enum sort_type sort__first_dimension; +char * field_sep; + LIST_HEAD(hist_entry__sort_list); static int repsep_snprintf(char *bf, size_t size, const char *fmt, ...) @@ -22,11 +23,11 @@ static int repsep_snprintf(char *bf, size_t size, const char *fmt, ...) va_start(ap, fmt); n = vsnprintf(bf, size, fmt, ap); - if (symbol_conf.field_sep && n > 0) { + if (field_sep && n > 0) { char *sep = bf; while (1) { - sep = strchr(sep, *symbol_conf.field_sep); + sep = strchr(sep, *field_sep); if (sep == NULL) break; *sep = '.'; @@ -171,7 +172,7 @@ static int hist_entry__dso_snprintf(struct hist_entry *self, char *bf, static int _hist_entry__sym_snprintf(struct map *map, struct symbol *sym, u64 ip, char level, char *bf, size_t size, - unsigned int width __maybe_unused) + unsigned int width __used) { size_t ret = 0; @@ -206,8 +207,7 @@ struct sort_entry sort_dso = { }; static int hist_entry__sym_snprintf(struct hist_entry *self, char *bf, - size_t size, - unsigned int width __maybe_unused) + size_t size, unsigned int width __used) { return _hist_entry__sym_snprintf(self->ms.map, self->ms.sym, self->ip, self->level, bf, size, width); @@ -250,8 +250,7 @@ sort__srcline_cmp(struct hist_entry *left, struct hist_entry *right) } static int hist_entry__srcline_snprintf(struct hist_entry *self, char *bf, - size_t size, - unsigned int width __maybe_unused) + size_t size, unsigned int width __used) { FILE *fp; char cmd[PATH_MAX + 2], *path = self->srcline, *nl; @@ -400,8 +399,7 @@ sort__sym_to_cmp(struct hist_entry *left, struct hist_entry *right) } static int hist_entry__sym_from_snprintf(struct hist_entry *self, char *bf, - size_t size, - unsigned int width __maybe_unused) + size_t size, unsigned int width __used) { struct addr_map_symbol *from = &self->branch_info->from; return _hist_entry__sym_snprintf(from->map, from->sym, from->addr, @@ -410,8 +408,7 @@ static int hist_entry__sym_from_snprintf(struct hist_entry *self, char *bf, } static int hist_entry__sym_to_snprintf(struct hist_entry *self, char *bf, - size_t size, - unsigned int width __maybe_unused) + size_t size, unsigned int width __used) { struct addr_map_symbol *to = &self->branch_info->to; return _hist_entry__sym_snprintf(to->map, to->sym, to->addr, @@ -512,10 +509,6 @@ int sort_dimension__add(const char *tok) return -EINVAL; } sort__has_parent = 1; - } else if (sd->entry == &sort_sym || - sd->entry == &sort_sym_from || - sd->entry == &sort_sym_to) { - sort__has_sym = 1; } if (sd->taken) diff --git a/trunk/tools/perf/util/sort.h b/trunk/tools/perf/util/sort.h index 12d634792de5..e724b26acd51 100644 --- a/trunk/tools/perf/util/sort.h +++ b/trunk/tools/perf/util/sort.h @@ -31,8 +31,8 @@ extern const char *parent_pattern; extern const char default_sort_order[]; extern int sort__need_collapse; extern int sort__has_parent; -extern int sort__has_sym; extern int sort__branch_mode; +extern char *field_sep; extern struct sort_entry sort_comm; extern struct sort_entry sort_dso; extern struct sort_entry sort_sym; diff --git a/trunk/tools/perf/util/stat.c b/trunk/tools/perf/util/stat.c deleted file mode 100644 index 23742126f47c..000000000000 --- a/trunk/tools/perf/util/stat.c +++ /dev/null @@ -1,57 +0,0 @@ -#include - -#include "stat.h" - -void update_stats(struct stats *stats, u64 val) -{ - double delta; - - stats->n++; - delta = val - stats->mean; - stats->mean += delta / stats->n; - stats->M2 += delta*(val - stats->mean); -} - -double avg_stats(struct stats *stats) -{ - return stats->mean; -} - -/* - * http://en.wikipedia.org/wiki/Algorithms_for_calculating_variance - * - * (\Sum n_i^2) - ((\Sum n_i)^2)/n - * s^2 = ------------------------------- - * n - 1 - * - * http://en.wikipedia.org/wiki/Stddev - * - * The std dev of the mean is related to the std dev by: - * - * s - * s_mean = ------- - * sqrt(n) - * - */ -double stddev_stats(struct stats *stats) -{ - double variance, variance_mean; - - if (!stats->n) - return 0.0; - - variance = stats->M2 / (stats->n - 1); - variance_mean = variance / stats->n; - - return sqrt(variance_mean); -} - -double rel_stddev_stats(double stddev, double avg) -{ - double pct = 0.0; - - if (avg) - pct = 100.0 * stddev/avg; - - return pct; -} diff --git a/trunk/tools/perf/util/stat.h b/trunk/tools/perf/util/stat.h deleted file mode 100644 index 588367c3c767..000000000000 --- a/trunk/tools/perf/util/stat.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef __PERF_STATS_H -#define __PERF_STATS_H - -#include "types.h" - -struct stats -{ - double n, mean, M2; -}; - -void update_stats(struct stats *stats, u64 val); -double avg_stats(struct stats *stats); -double stddev_stats(struct stats *stats); -double rel_stddev_stats(double stddev, double avg); - -#endif diff --git a/trunk/tools/perf/util/string.c b/trunk/tools/perf/util/string.c index 32170590892d..199bc4d8905d 100644 --- a/trunk/tools/perf/util/string.c +++ b/trunk/tools/perf/util/string.c @@ -1,5 +1,5 @@ #include "util.h" -#include "linux/string.h" +#include "string.h" #define K 1024LL /* @@ -335,19 +335,3 @@ char *rtrim(char *s) return s; } - -/** - * memdup - duplicate region of memory - * @src: memory region to duplicate - * @len: memory region length - */ -void *memdup(const void *src, size_t len) -{ - void *p; - - p = malloc(len); - if (p) - memcpy(p, src, len); - - return p; -} diff --git a/trunk/tools/perf/util/strlist.c b/trunk/tools/perf/util/strlist.c index 155d8b7078a7..6783a2043555 100644 --- a/trunk/tools/perf/util/strlist.c +++ b/trunk/tools/perf/util/strlist.c @@ -10,28 +10,23 @@ #include #include -static -struct rb_node *strlist__node_new(struct rblist *rblist, const void *entry) +static struct str_node *str_node__new(const char *s, bool dupstr) { - const char *s = entry; - struct rb_node *rc = NULL; - struct strlist *strlist = container_of(rblist, struct strlist, rblist); - struct str_node *snode = malloc(sizeof(*snode)); + struct str_node *self = malloc(sizeof(*self)); - if (snode != NULL) { - if (strlist->dupstr) { + if (self != NULL) { + if (dupstr) { s = strdup(s); if (s == NULL) goto out_delete; } - snode->s = s; - rc = &snode->rb_node; + self->s = s; } - return rc; + return self; out_delete: - free(snode); + free(self); return NULL; } @@ -42,26 +37,36 @@ static void str_node__delete(struct str_node *self, bool dupstr) free(self); } -static -void strlist__node_delete(struct rblist *rblist, struct rb_node *rb_node) +int strlist__add(struct strlist *self, const char *new_entry) { - struct strlist *slist = container_of(rblist, struct strlist, rblist); - struct str_node *snode = container_of(rb_node, struct str_node, rb_node); - - str_node__delete(snode, slist->dupstr); -} + struct rb_node **p = &self->entries.rb_node; + struct rb_node *parent = NULL; + struct str_node *sn; + + while (*p != NULL) { + int rc; + + parent = *p; + sn = rb_entry(parent, struct str_node, rb_node); + rc = strcmp(sn->s, new_entry); + + if (rc > 0) + p = &(*p)->rb_left; + else if (rc < 0) + p = &(*p)->rb_right; + else + return -EEXIST; + } -static int strlist__node_cmp(struct rb_node *rb_node, const void *entry) -{ - const char *str = entry; - struct str_node *snode = container_of(rb_node, struct str_node, rb_node); + sn = str_node__new(new_entry, self->dupstr); + if (sn == NULL) + return -ENOMEM; - return strcmp(snode->s, str); -} + rb_link_node(&sn->rb_node, parent, p); + rb_insert_color(&sn->rb_node, &self->entries); + ++self->nr_entries; -int strlist__add(struct strlist *self, const char *new_entry) -{ - return rblist__add_node(&self->rblist, new_entry); + return 0; } int strlist__load(struct strlist *self, const char *filename) @@ -91,20 +96,34 @@ int strlist__load(struct strlist *self, const char *filename) return err; } -void strlist__remove(struct strlist *slist, struct str_node *snode) +void strlist__remove(struct strlist *self, struct str_node *sn) { - rblist__remove_node(&slist->rblist, &snode->rb_node); + rb_erase(&sn->rb_node, &self->entries); + str_node__delete(sn, self->dupstr); } -struct str_node *strlist__find(struct strlist *slist, const char *entry) +struct str_node *strlist__find(struct strlist *self, const char *entry) { - struct str_node *snode = NULL; - struct rb_node *rb_node = rblist__find(&slist->rblist, entry); - - if (rb_node) - snode = container_of(rb_node, struct str_node, rb_node); + struct rb_node **p = &self->entries.rb_node; + struct rb_node *parent = NULL; + + while (*p != NULL) { + struct str_node *sn; + int rc; + + parent = *p; + sn = rb_entry(parent, struct str_node, rb_node); + rc = strcmp(sn->s, entry); + + if (rc > 0) + p = &(*p)->rb_left; + else if (rc < 0) + p = &(*p)->rb_right; + else + return sn; + } - return snode; + return NULL; } static int strlist__parse_list_entry(struct strlist *self, const char *s) @@ -137,12 +156,9 @@ struct strlist *strlist__new(bool dupstr, const char *slist) struct strlist *self = malloc(sizeof(*self)); if (self != NULL) { - rblist__init(&self->rblist); - self->rblist.node_cmp = strlist__node_cmp; - self->rblist.node_new = strlist__node_new; - self->rblist.node_delete = strlist__node_delete; - + self->entries = RB_ROOT; self->dupstr = dupstr; + self->nr_entries = 0; if (slist && strlist__parse_list(self, slist) != 0) goto out_error; } @@ -155,18 +171,30 @@ struct strlist *strlist__new(bool dupstr, const char *slist) void strlist__delete(struct strlist *self) { - if (self != NULL) - rblist__delete(&self->rblist); + if (self != NULL) { + struct str_node *pos; + struct rb_node *next = rb_first(&self->entries); + + while (next) { + pos = rb_entry(next, struct str_node, rb_node); + next = rb_next(&pos->rb_node); + strlist__remove(self, pos); + } + self->entries = RB_ROOT; + free(self); + } } -struct str_node *strlist__entry(const struct strlist *slist, unsigned int idx) +struct str_node *strlist__entry(const struct strlist *self, unsigned int idx) { - struct str_node *snode = NULL; - struct rb_node *rb_node; + struct rb_node *nd; - rb_node = rblist__entry(&slist->rblist, idx); - if (rb_node) - snode = container_of(rb_node, struct str_node, rb_node); + for (nd = rb_first(&self->entries); nd; nd = rb_next(nd)) { + struct str_node *pos = rb_entry(nd, struct str_node, rb_node); - return snode; + if (!idx--) + return pos; + } + + return NULL; } diff --git a/trunk/tools/perf/util/strlist.h b/trunk/tools/perf/util/strlist.h index dd9f922ec67c..3ba839007d2c 100644 --- a/trunk/tools/perf/util/strlist.h +++ b/trunk/tools/perf/util/strlist.h @@ -4,15 +4,14 @@ #include #include -#include "rblist.h" - struct str_node { struct rb_node rb_node; const char *s; }; struct strlist { - struct rblist rblist; + struct rb_root entries; + unsigned int nr_entries; bool dupstr; }; @@ -33,18 +32,18 @@ static inline bool strlist__has_entry(struct strlist *self, const char *entry) static inline bool strlist__empty(const struct strlist *self) { - return rblist__empty(&self->rblist); + return self->nr_entries == 0; } static inline unsigned int strlist__nr_entries(const struct strlist *self) { - return rblist__nr_entries(&self->rblist); + return self->nr_entries; } /* For strlist iteration */ static inline struct str_node *strlist__first(struct strlist *self) { - struct rb_node *rn = rb_first(&self->rblist.entries); + struct rb_node *rn = rb_first(&self->entries); return rn ? rb_entry(rn, struct str_node, rb_node) : NULL; } static inline struct str_node *strlist__next(struct str_node *sn) diff --git a/trunk/tools/perf/util/symbol-elf.c b/trunk/tools/perf/util/symbol-elf.c deleted file mode 100644 index db0cc92cf2ea..000000000000 --- a/trunk/tools/perf/util/symbol-elf.c +++ /dev/null @@ -1,841 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "symbol.h" -#include "debug.h" - -#ifndef NT_GNU_BUILD_ID -#define NT_GNU_BUILD_ID 3 -#endif - -/** - * elf_symtab__for_each_symbol - iterate thru all the symbols - * - * @syms: struct elf_symtab instance to iterate - * @idx: uint32_t idx - * @sym: GElf_Sym iterator - */ -#define elf_symtab__for_each_symbol(syms, nr_syms, idx, sym) \ - for (idx = 0, gelf_getsym(syms, idx, &sym);\ - idx < nr_syms; \ - idx++, gelf_getsym(syms, idx, &sym)) - -static inline uint8_t elf_sym__type(const GElf_Sym *sym) -{ - return GELF_ST_TYPE(sym->st_info); -} - -static inline int elf_sym__is_function(const GElf_Sym *sym) -{ - return elf_sym__type(sym) == STT_FUNC && - sym->st_name != 0 && - sym->st_shndx != SHN_UNDEF; -} - -static inline bool elf_sym__is_object(const GElf_Sym *sym) -{ - return elf_sym__type(sym) == STT_OBJECT && - sym->st_name != 0 && - sym->st_shndx != SHN_UNDEF; -} - -static inline int elf_sym__is_label(const GElf_Sym *sym) -{ - return elf_sym__type(sym) == STT_NOTYPE && - sym->st_name != 0 && - sym->st_shndx != SHN_UNDEF && - sym->st_shndx != SHN_ABS; -} - -static bool elf_sym__is_a(GElf_Sym *sym, enum map_type type) -{ - switch (type) { - case MAP__FUNCTION: - return elf_sym__is_function(sym); - case MAP__VARIABLE: - return elf_sym__is_object(sym); - default: - return false; - } -} - -static inline const char *elf_sym__name(const GElf_Sym *sym, - const Elf_Data *symstrs) -{ - return symstrs->d_buf + sym->st_name; -} - -static inline const char *elf_sec__name(const GElf_Shdr *shdr, - const Elf_Data *secstrs) -{ - return secstrs->d_buf + shdr->sh_name; -} - -static inline int elf_sec__is_text(const GElf_Shdr *shdr, - const Elf_Data *secstrs) -{ - return strstr(elf_sec__name(shdr, secstrs), "text") != NULL; -} - -static inline bool elf_sec__is_data(const GElf_Shdr *shdr, - const Elf_Data *secstrs) -{ - return strstr(elf_sec__name(shdr, secstrs), "data") != NULL; -} - -static bool elf_sec__is_a(GElf_Shdr *shdr, Elf_Data *secstrs, - enum map_type type) -{ - switch (type) { - case MAP__FUNCTION: - return elf_sec__is_text(shdr, secstrs); - case MAP__VARIABLE: - return elf_sec__is_data(shdr, secstrs); - default: - return false; - } -} - -static size_t elf_addr_to_index(Elf *elf, GElf_Addr addr) -{ - Elf_Scn *sec = NULL; - GElf_Shdr shdr; - size_t cnt = 1; - - while ((sec = elf_nextscn(elf, sec)) != NULL) { - gelf_getshdr(sec, &shdr); - - if ((addr >= shdr.sh_addr) && - (addr < (shdr.sh_addr + shdr.sh_size))) - return cnt; - - ++cnt; - } - - return -1; -} - -static Elf_Scn *elf_section_by_name(Elf *elf, GElf_Ehdr *ep, - GElf_Shdr *shp, const char *name, - size_t *idx) -{ - Elf_Scn *sec = NULL; - size_t cnt = 1; - - /* Elf is corrupted/truncated, avoid calling elf_strptr. */ - if (!elf_rawdata(elf_getscn(elf, ep->e_shstrndx), NULL)) - return NULL; - - while ((sec = elf_nextscn(elf, sec)) != NULL) { - char *str; - - gelf_getshdr(sec, shp); - str = elf_strptr(elf, ep->e_shstrndx, shp->sh_name); - if (!strcmp(name, str)) { - if (idx) - *idx = cnt; - break; - } - ++cnt; - } - - return sec; -} - -#define elf_section__for_each_rel(reldata, pos, pos_mem, idx, nr_entries) \ - for (idx = 0, pos = gelf_getrel(reldata, 0, &pos_mem); \ - idx < nr_entries; \ - ++idx, pos = gelf_getrel(reldata, idx, &pos_mem)) - -#define elf_section__for_each_rela(reldata, pos, pos_mem, idx, nr_entries) \ - for (idx = 0, pos = gelf_getrela(reldata, 0, &pos_mem); \ - idx < nr_entries; \ - ++idx, pos = gelf_getrela(reldata, idx, &pos_mem)) - -/* - * We need to check if we have a .dynsym, so that we can handle the - * .plt, synthesizing its symbols, that aren't on the symtabs (be it - * .dynsym or .symtab). - * And always look at the original dso, not at debuginfo packages, that - * have the PLT data stripped out (shdr_rel_plt.sh_type == SHT_NOBITS). - */ -int dso__synthesize_plt_symbols(struct dso *dso, struct symsrc *ss, struct map *map, - symbol_filter_t filter) -{ - uint32_t nr_rel_entries, idx; - GElf_Sym sym; - u64 plt_offset; - GElf_Shdr shdr_plt; - struct symbol *f; - GElf_Shdr shdr_rel_plt, shdr_dynsym; - Elf_Data *reldata, *syms, *symstrs; - Elf_Scn *scn_plt_rel, *scn_symstrs, *scn_dynsym; - size_t dynsym_idx; - GElf_Ehdr ehdr; - char sympltname[1024]; - Elf *elf; - int nr = 0, symidx, err = 0; - - if (!ss->dynsym) - return 0; - - elf = ss->elf; - ehdr = ss->ehdr; - - scn_dynsym = ss->dynsym; - shdr_dynsym = ss->dynshdr; - dynsym_idx = ss->dynsym_idx; - - if (scn_dynsym == NULL) - goto out_elf_end; - - scn_plt_rel = elf_section_by_name(elf, &ehdr, &shdr_rel_plt, - ".rela.plt", NULL); - if (scn_plt_rel == NULL) { - scn_plt_rel = elf_section_by_name(elf, &ehdr, &shdr_rel_plt, - ".rel.plt", NULL); - if (scn_plt_rel == NULL) - goto out_elf_end; - } - - err = -1; - - if (shdr_rel_plt.sh_link != dynsym_idx) - goto out_elf_end; - - if (elf_section_by_name(elf, &ehdr, &shdr_plt, ".plt", NULL) == NULL) - goto out_elf_end; - - /* - * Fetch the relocation section to find the idxes to the GOT - * and the symbols in the .dynsym they refer to. - */ - reldata = elf_getdata(scn_plt_rel, NULL); - if (reldata == NULL) - goto out_elf_end; - - syms = elf_getdata(scn_dynsym, NULL); - if (syms == NULL) - goto out_elf_end; - - scn_symstrs = elf_getscn(elf, shdr_dynsym.sh_link); - if (scn_symstrs == NULL) - goto out_elf_end; - - symstrs = elf_getdata(scn_symstrs, NULL); - if (symstrs == NULL) - goto out_elf_end; - - if (symstrs->d_size == 0) - goto out_elf_end; - - nr_rel_entries = shdr_rel_plt.sh_size / shdr_rel_plt.sh_entsize; - plt_offset = shdr_plt.sh_offset; - - if (shdr_rel_plt.sh_type == SHT_RELA) { - GElf_Rela pos_mem, *pos; - - elf_section__for_each_rela(reldata, pos, pos_mem, idx, - nr_rel_entries) { - symidx = GELF_R_SYM(pos->r_info); - plt_offset += shdr_plt.sh_entsize; - gelf_getsym(syms, symidx, &sym); - snprintf(sympltname, sizeof(sympltname), - "%s@plt", elf_sym__name(&sym, symstrs)); - - f = symbol__new(plt_offset, shdr_plt.sh_entsize, - STB_GLOBAL, sympltname); - if (!f) - goto out_elf_end; - - if (filter && filter(map, f)) - symbol__delete(f); - else { - symbols__insert(&dso->symbols[map->type], f); - ++nr; - } - } - } else if (shdr_rel_plt.sh_type == SHT_REL) { - GElf_Rel pos_mem, *pos; - elf_section__for_each_rel(reldata, pos, pos_mem, idx, - nr_rel_entries) { - symidx = GELF_R_SYM(pos->r_info); - plt_offset += shdr_plt.sh_entsize; - gelf_getsym(syms, symidx, &sym); - snprintf(sympltname, sizeof(sympltname), - "%s@plt", elf_sym__name(&sym, symstrs)); - - f = symbol__new(plt_offset, shdr_plt.sh_entsize, - STB_GLOBAL, sympltname); - if (!f) - goto out_elf_end; - - if (filter && filter(map, f)) - symbol__delete(f); - else { - symbols__insert(&dso->symbols[map->type], f); - ++nr; - } - } - } - - err = 0; -out_elf_end: - if (err == 0) - return nr; - pr_debug("%s: problems reading %s PLT info.\n", - __func__, dso->long_name); - return 0; -} - -/* - * Align offset to 4 bytes as needed for note name and descriptor data. - */ -#define NOTE_ALIGN(n) (((n) + 3) & -4U) - -static int elf_read_build_id(Elf *elf, void *bf, size_t size) -{ - int err = -1; - GElf_Ehdr ehdr; - GElf_Shdr shdr; - Elf_Data *data; - Elf_Scn *sec; - Elf_Kind ek; - void *ptr; - - if (size < BUILD_ID_SIZE) - goto out; - - ek = elf_kind(elf); - if (ek != ELF_K_ELF) - goto out; - - if (gelf_getehdr(elf, &ehdr) == NULL) { - pr_err("%s: cannot get elf header.\n", __func__); - goto out; - } - - /* - * Check following sections for notes: - * '.note.gnu.build-id' - * '.notes' - * '.note' (VDSO specific) - */ - do { - sec = elf_section_by_name(elf, &ehdr, &shdr, - ".note.gnu.build-id", NULL); - if (sec) - break; - - sec = elf_section_by_name(elf, &ehdr, &shdr, - ".notes", NULL); - if (sec) - break; - - sec = elf_section_by_name(elf, &ehdr, &shdr, - ".note", NULL); - if (sec) - break; - - return err; - - } while (0); - - data = elf_getdata(sec, NULL); - if (data == NULL) - goto out; - - ptr = data->d_buf; - while (ptr < (data->d_buf + data->d_size)) { - GElf_Nhdr *nhdr = ptr; - size_t namesz = NOTE_ALIGN(nhdr->n_namesz), - descsz = NOTE_ALIGN(nhdr->n_descsz); - const char *name; - - ptr += sizeof(*nhdr); - name = ptr; - ptr += namesz; - if (nhdr->n_type == NT_GNU_BUILD_ID && - nhdr->n_namesz == sizeof("GNU")) { - if (memcmp(name, "GNU", sizeof("GNU")) == 0) { - size_t sz = min(size, descsz); - memcpy(bf, ptr, sz); - memset(bf + sz, 0, size - sz); - err = descsz; - break; - } - } - ptr += descsz; - } - -out: - return err; -} - -int filename__read_build_id(const char *filename, void *bf, size_t size) -{ - int fd, err = -1; - Elf *elf; - - if (size < BUILD_ID_SIZE) - goto out; - - fd = open(filename, O_RDONLY); - if (fd < 0) - goto out; - - elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL); - if (elf == NULL) { - pr_debug2("%s: cannot read %s ELF file.\n", __func__, filename); - goto out_close; - } - - err = elf_read_build_id(elf, bf, size); - - elf_end(elf); -out_close: - close(fd); -out: - return err; -} - -int sysfs__read_build_id(const char *filename, void *build_id, size_t size) -{ - int fd, err = -1; - - if (size < BUILD_ID_SIZE) - goto out; - - fd = open(filename, O_RDONLY); - if (fd < 0) - goto out; - - while (1) { - char bf[BUFSIZ]; - GElf_Nhdr nhdr; - size_t namesz, descsz; - - if (read(fd, &nhdr, sizeof(nhdr)) != sizeof(nhdr)) - break; - - namesz = NOTE_ALIGN(nhdr.n_namesz); - descsz = NOTE_ALIGN(nhdr.n_descsz); - if (nhdr.n_type == NT_GNU_BUILD_ID && - nhdr.n_namesz == sizeof("GNU")) { - if (read(fd, bf, namesz) != (ssize_t)namesz) - break; - if (memcmp(bf, "GNU", sizeof("GNU")) == 0) { - size_t sz = min(descsz, size); - if (read(fd, build_id, sz) == (ssize_t)sz) { - memset(build_id + sz, 0, size - sz); - err = 0; - break; - } - } else if (read(fd, bf, descsz) != (ssize_t)descsz) - break; - } else { - int n = namesz + descsz; - if (read(fd, bf, n) != n) - break; - } - } - close(fd); -out: - return err; -} - -int filename__read_debuglink(const char *filename, char *debuglink, - size_t size) -{ - int fd, err = -1; - Elf *elf; - GElf_Ehdr ehdr; - GElf_Shdr shdr; - Elf_Data *data; - Elf_Scn *sec; - Elf_Kind ek; - - fd = open(filename, O_RDONLY); - if (fd < 0) - goto out; - - elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL); - if (elf == NULL) { - pr_debug2("%s: cannot read %s ELF file.\n", __func__, filename); - goto out_close; - } - - ek = elf_kind(elf); - if (ek != ELF_K_ELF) - goto out_close; - - if (gelf_getehdr(elf, &ehdr) == NULL) { - pr_err("%s: cannot get elf header.\n", __func__); - goto out_close; - } - - sec = elf_section_by_name(elf, &ehdr, &shdr, - ".gnu_debuglink", NULL); - if (sec == NULL) - goto out_close; - - data = elf_getdata(sec, NULL); - if (data == NULL) - goto out_close; - - /* the start of this section is a zero-terminated string */ - strncpy(debuglink, data->d_buf, size); - - elf_end(elf); - -out_close: - close(fd); -out: - return err; -} - -static int dso__swap_init(struct dso *dso, unsigned char eidata) -{ - static unsigned int const endian = 1; - - dso->needs_swap = DSO_SWAP__NO; - - switch (eidata) { - case ELFDATA2LSB: - /* We are big endian, DSO is little endian. */ - if (*(unsigned char const *)&endian != 1) - dso->needs_swap = DSO_SWAP__YES; - break; - - case ELFDATA2MSB: - /* We are little endian, DSO is big endian. */ - if (*(unsigned char const *)&endian != 0) - dso->needs_swap = DSO_SWAP__YES; - break; - - default: - pr_err("unrecognized DSO data encoding %d\n", eidata); - return -EINVAL; - } - - return 0; -} - -bool symsrc__possibly_runtime(struct symsrc *ss) -{ - return ss->dynsym || ss->opdsec; -} - -bool symsrc__has_symtab(struct symsrc *ss) -{ - return ss->symtab != NULL; -} - -void symsrc__destroy(struct symsrc *ss) -{ - free(ss->name); - elf_end(ss->elf); - close(ss->fd); -} - -int symsrc__init(struct symsrc *ss, struct dso *dso, const char *name, - enum dso_binary_type type) -{ - int err = -1; - GElf_Ehdr ehdr; - Elf *elf; - int fd; - - fd = open(name, O_RDONLY); - if (fd < 0) - return -1; - - elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL); - if (elf == NULL) { - pr_debug("%s: cannot read %s ELF file.\n", __func__, name); - goto out_close; - } - - if (gelf_getehdr(elf, &ehdr) == NULL) { - pr_debug("%s: cannot get elf header.\n", __func__); - goto out_elf_end; - } - - if (dso__swap_init(dso, ehdr.e_ident[EI_DATA])) - goto out_elf_end; - - /* Always reject images with a mismatched build-id: */ - if (dso->has_build_id) { - u8 build_id[BUILD_ID_SIZE]; - - if (elf_read_build_id(elf, build_id, BUILD_ID_SIZE) < 0) - goto out_elf_end; - - if (!dso__build_id_equal(dso, build_id)) - goto out_elf_end; - } - - ss->symtab = elf_section_by_name(elf, &ehdr, &ss->symshdr, ".symtab", - NULL); - if (ss->symshdr.sh_type != SHT_SYMTAB) - ss->symtab = NULL; - - ss->dynsym_idx = 0; - ss->dynsym = elf_section_by_name(elf, &ehdr, &ss->dynshdr, ".dynsym", - &ss->dynsym_idx); - if (ss->dynshdr.sh_type != SHT_DYNSYM) - ss->dynsym = NULL; - - ss->opdidx = 0; - ss->opdsec = elf_section_by_name(elf, &ehdr, &ss->opdshdr, ".opd", - &ss->opdidx); - if (ss->opdshdr.sh_type != SHT_PROGBITS) - ss->opdsec = NULL; - - if (dso->kernel == DSO_TYPE_USER) { - GElf_Shdr shdr; - ss->adjust_symbols = (ehdr.e_type == ET_EXEC || - elf_section_by_name(elf, &ehdr, &shdr, - ".gnu.prelink_undo", - NULL) != NULL); - } else { - ss->adjust_symbols = 0; - } - - ss->name = strdup(name); - if (!ss->name) - goto out_elf_end; - - ss->elf = elf; - ss->fd = fd; - ss->ehdr = ehdr; - ss->type = type; - - return 0; - -out_elf_end: - elf_end(elf); -out_close: - close(fd); - return err; -} - -int dso__load_sym(struct dso *dso, struct map *map, - struct symsrc *syms_ss, struct symsrc *runtime_ss, - symbol_filter_t filter, int kmodule) -{ - struct kmap *kmap = dso->kernel ? map__kmap(map) : NULL; - struct map *curr_map = map; - struct dso *curr_dso = dso; - Elf_Data *symstrs, *secstrs; - uint32_t nr_syms; - int err = -1; - uint32_t idx; - GElf_Ehdr ehdr; - GElf_Shdr shdr; - Elf_Data *syms, *opddata = NULL; - GElf_Sym sym; - Elf_Scn *sec, *sec_strndx; - Elf *elf; - int nr = 0; - - dso->symtab_type = syms_ss->type; - - if (!syms_ss->symtab) { - syms_ss->symtab = syms_ss->dynsym; - syms_ss->symshdr = syms_ss->dynshdr; - } - - elf = syms_ss->elf; - ehdr = syms_ss->ehdr; - sec = syms_ss->symtab; - shdr = syms_ss->symshdr; - - if (runtime_ss->opdsec) - opddata = elf_rawdata(runtime_ss->opdsec, NULL); - - syms = elf_getdata(sec, NULL); - if (syms == NULL) - goto out_elf_end; - - sec = elf_getscn(elf, shdr.sh_link); - if (sec == NULL) - goto out_elf_end; - - symstrs = elf_getdata(sec, NULL); - if (symstrs == NULL) - goto out_elf_end; - - sec_strndx = elf_getscn(elf, ehdr.e_shstrndx); - if (sec_strndx == NULL) - goto out_elf_end; - - secstrs = elf_getdata(sec_strndx, NULL); - if (secstrs == NULL) - goto out_elf_end; - - nr_syms = shdr.sh_size / shdr.sh_entsize; - - memset(&sym, 0, sizeof(sym)); - dso->adjust_symbols = runtime_ss->adjust_symbols; - elf_symtab__for_each_symbol(syms, nr_syms, idx, sym) { - struct symbol *f; - const char *elf_name = elf_sym__name(&sym, symstrs); - char *demangled = NULL; - int is_label = elf_sym__is_label(&sym); - const char *section_name; - bool used_opd = false; - - if (kmap && kmap->ref_reloc_sym && kmap->ref_reloc_sym->name && - strcmp(elf_name, kmap->ref_reloc_sym->name) == 0) - kmap->ref_reloc_sym->unrelocated_addr = sym.st_value; - - if (!is_label && !elf_sym__is_a(&sym, map->type)) - continue; - - /* Reject ARM ELF "mapping symbols": these aren't unique and - * don't identify functions, so will confuse the profile - * output: */ - if (ehdr.e_machine == EM_ARM) { - if (!strcmp(elf_name, "$a") || - !strcmp(elf_name, "$d") || - !strcmp(elf_name, "$t")) - continue; - } - - if (runtime_ss->opdsec && sym.st_shndx == runtime_ss->opdidx) { - u32 offset = sym.st_value - syms_ss->opdshdr.sh_addr; - u64 *opd = opddata->d_buf + offset; - sym.st_value = DSO__SWAP(dso, u64, *opd); - sym.st_shndx = elf_addr_to_index(runtime_ss->elf, - sym.st_value); - used_opd = true; - } - - sec = elf_getscn(runtime_ss->elf, sym.st_shndx); - if (!sec) - goto out_elf_end; - - gelf_getshdr(sec, &shdr); - - if (is_label && !elf_sec__is_a(&shdr, secstrs, map->type)) - continue; - - section_name = elf_sec__name(&shdr, secstrs); - - /* On ARM, symbols for thumb functions have 1 added to - * the symbol address as a flag - remove it */ - if ((ehdr.e_machine == EM_ARM) && - (map->type == MAP__FUNCTION) && - (sym.st_value & 1)) - --sym.st_value; - - if (dso->kernel != DSO_TYPE_USER || kmodule) { - char dso_name[PATH_MAX]; - - if (strcmp(section_name, - (curr_dso->short_name + - dso->short_name_len)) == 0) - goto new_symbol; - - if (strcmp(section_name, ".text") == 0) { - curr_map = map; - curr_dso = dso; - goto new_symbol; - } - - snprintf(dso_name, sizeof(dso_name), - "%s%s", dso->short_name, section_name); - - curr_map = map_groups__find_by_name(kmap->kmaps, map->type, dso_name); - if (curr_map == NULL) { - u64 start = sym.st_value; - - if (kmodule) - start += map->start + shdr.sh_offset; - - curr_dso = dso__new(dso_name); - if (curr_dso == NULL) - goto out_elf_end; - curr_dso->kernel = dso->kernel; - curr_dso->long_name = dso->long_name; - curr_dso->long_name_len = dso->long_name_len; - curr_map = map__new2(start, curr_dso, - map->type); - if (curr_map == NULL) { - dso__delete(curr_dso); - goto out_elf_end; - } - curr_map->map_ip = identity__map_ip; - curr_map->unmap_ip = identity__map_ip; - curr_dso->symtab_type = dso->symtab_type; - map_groups__insert(kmap->kmaps, curr_map); - dsos__add(&dso->node, curr_dso); - dso__set_loaded(curr_dso, map->type); - } else - curr_dso = curr_map->dso; - - goto new_symbol; - } - - if ((used_opd && runtime_ss->adjust_symbols) - || (!used_opd && syms_ss->adjust_symbols)) { - pr_debug4("%s: adjusting symbol: st_value: %#" PRIx64 " " - "sh_addr: %#" PRIx64 " sh_offset: %#" PRIx64 "\n", __func__, - (u64)sym.st_value, (u64)shdr.sh_addr, - (u64)shdr.sh_offset); - sym.st_value -= shdr.sh_addr - shdr.sh_offset; - } - /* - * We need to figure out if the object was created from C++ sources - * DWARF DW_compile_unit has this, but we don't always have access - * to it... - */ - demangled = bfd_demangle(NULL, elf_name, DMGL_PARAMS | DMGL_ANSI); - if (demangled != NULL) - elf_name = demangled; -new_symbol: - f = symbol__new(sym.st_value, sym.st_size, - GELF_ST_BIND(sym.st_info), elf_name); - free(demangled); - if (!f) - goto out_elf_end; - - if (filter && filter(curr_map, f)) - symbol__delete(f); - else { - symbols__insert(&curr_dso->symbols[curr_map->type], f); - nr++; - } - } - - /* - * For misannotated, zeroed, ASM function sizes. - */ - if (nr > 0) { - symbols__fixup_duplicate(&dso->symbols[map->type]); - symbols__fixup_end(&dso->symbols[map->type]); - if (kmap) { - /* - * We need to fixup this here too because we create new - * maps here, for things like vsyscall sections. - */ - __map_groups__fixup_end(kmap->kmaps, map->type); - } - } - err = nr; -out_elf_end: - return err; -} - -void symbol__elf_init(void) -{ - elf_version(EV_CURRENT); -} diff --git a/trunk/tools/perf/util/symbol-minimal.c b/trunk/tools/perf/util/symbol-minimal.c deleted file mode 100644 index 259f8f2ea9c9..000000000000 --- a/trunk/tools/perf/util/symbol-minimal.c +++ /dev/null @@ -1,307 +0,0 @@ -#include "symbol.h" - -#include -#include -#include -#include -#include -#include - - -static bool check_need_swap(int file_endian) -{ - const int data = 1; - u8 *check = (u8 *)&data; - int host_endian; - - if (check[0] == 1) - host_endian = ELFDATA2LSB; - else - host_endian = ELFDATA2MSB; - - return host_endian != file_endian; -} - -#define NOTE_ALIGN(sz) (((sz) + 3) & ~3) - -#define NT_GNU_BUILD_ID 3 - -static int read_build_id(void *note_data, size_t note_len, void *bf, - size_t size, bool need_swap) -{ - struct { - u32 n_namesz; - u32 n_descsz; - u32 n_type; - } *nhdr; - void *ptr; - - ptr = note_data; - while (ptr < (note_data + note_len)) { - const char *name; - size_t namesz, descsz; - - nhdr = ptr; - if (need_swap) { - nhdr->n_namesz = bswap_32(nhdr->n_namesz); - nhdr->n_descsz = bswap_32(nhdr->n_descsz); - nhdr->n_type = bswap_32(nhdr->n_type); - } - - namesz = NOTE_ALIGN(nhdr->n_namesz); - descsz = NOTE_ALIGN(nhdr->n_descsz); - - ptr += sizeof(*nhdr); - name = ptr; - ptr += namesz; - if (nhdr->n_type == NT_GNU_BUILD_ID && - nhdr->n_namesz == sizeof("GNU")) { - if (memcmp(name, "GNU", sizeof("GNU")) == 0) { - size_t sz = min(size, descsz); - memcpy(bf, ptr, sz); - memset(bf + sz, 0, size - sz); - return 0; - } - } - ptr += descsz; - } - - return -1; -} - -int filename__read_debuglink(const char *filename __maybe_unused, - char *debuglink __maybe_unused, - size_t size __maybe_unused) -{ - return -1; -} - -/* - * Just try PT_NOTE header otherwise fails - */ -int filename__read_build_id(const char *filename, void *bf, size_t size) -{ - FILE *fp; - int ret = -1; - bool need_swap = false; - u8 e_ident[EI_NIDENT]; - size_t buf_size; - void *buf; - int i; - - fp = fopen(filename, "r"); - if (fp == NULL) - return -1; - - if (fread(e_ident, sizeof(e_ident), 1, fp) != 1) - goto out; - - if (memcmp(e_ident, ELFMAG, SELFMAG) || - e_ident[EI_VERSION] != EV_CURRENT) - goto out; - - need_swap = check_need_swap(e_ident[EI_DATA]); - - /* for simplicity */ - fseek(fp, 0, SEEK_SET); - - if (e_ident[EI_CLASS] == ELFCLASS32) { - Elf32_Ehdr ehdr; - Elf32_Phdr *phdr; - - if (fread(&ehdr, sizeof(ehdr), 1, fp) != 1) - goto out; - - if (need_swap) { - ehdr.e_phoff = bswap_32(ehdr.e_phoff); - ehdr.e_phentsize = bswap_16(ehdr.e_phentsize); - ehdr.e_phnum = bswap_16(ehdr.e_phnum); - } - - buf_size = ehdr.e_phentsize * ehdr.e_phnum; - buf = malloc(buf_size); - if (buf == NULL) - goto out; - - fseek(fp, ehdr.e_phoff, SEEK_SET); - if (fread(buf, buf_size, 1, fp) != 1) - goto out_free; - - for (i = 0, phdr = buf; i < ehdr.e_phnum; i++, phdr++) { - void *tmp; - - if (need_swap) { - phdr->p_type = bswap_32(phdr->p_type); - phdr->p_offset = bswap_32(phdr->p_offset); - phdr->p_filesz = bswap_32(phdr->p_filesz); - } - - if (phdr->p_type != PT_NOTE) - continue; - - buf_size = phdr->p_filesz; - tmp = realloc(buf, buf_size); - if (tmp == NULL) - goto out_free; - - buf = tmp; - fseek(fp, phdr->p_offset, SEEK_SET); - if (fread(buf, buf_size, 1, fp) != 1) - goto out_free; - - ret = read_build_id(buf, buf_size, bf, size, need_swap); - if (ret == 0) - ret = size; - break; - } - } else { - Elf64_Ehdr ehdr; - Elf64_Phdr *phdr; - - if (fread(&ehdr, sizeof(ehdr), 1, fp) != 1) - goto out; - - if (need_swap) { - ehdr.e_phoff = bswap_64(ehdr.e_phoff); - ehdr.e_phentsize = bswap_16(ehdr.e_phentsize); - ehdr.e_phnum = bswap_16(ehdr.e_phnum); - } - - buf_size = ehdr.e_phentsize * ehdr.e_phnum; - buf = malloc(buf_size); - if (buf == NULL) - goto out; - - fseek(fp, ehdr.e_phoff, SEEK_SET); - if (fread(buf, buf_size, 1, fp) != 1) - goto out_free; - - for (i = 0, phdr = buf; i < ehdr.e_phnum; i++, phdr++) { - void *tmp; - - if (need_swap) { - phdr->p_type = bswap_32(phdr->p_type); - phdr->p_offset = bswap_64(phdr->p_offset); - phdr->p_filesz = bswap_64(phdr->p_filesz); - } - - if (phdr->p_type != PT_NOTE) - continue; - - buf_size = phdr->p_filesz; - tmp = realloc(buf, buf_size); - if (tmp == NULL) - goto out_free; - - buf = tmp; - fseek(fp, phdr->p_offset, SEEK_SET); - if (fread(buf, buf_size, 1, fp) != 1) - goto out_free; - - ret = read_build_id(buf, buf_size, bf, size, need_swap); - if (ret == 0) - ret = size; - break; - } - } -out_free: - free(buf); -out: - fclose(fp); - return ret; -} - -int sysfs__read_build_id(const char *filename, void *build_id, size_t size) -{ - int fd; - int ret = -1; - struct stat stbuf; - size_t buf_size; - void *buf; - - fd = open(filename, O_RDONLY); - if (fd < 0) - return -1; - - if (fstat(fd, &stbuf) < 0) - goto out; - - buf_size = stbuf.st_size; - buf = malloc(buf_size); - if (buf == NULL) - goto out; - - if (read(fd, buf, buf_size) != (ssize_t) buf_size) - goto out_free; - - ret = read_build_id(buf, buf_size, build_id, size, false); -out_free: - free(buf); -out: - close(fd); - return ret; -} - -int symsrc__init(struct symsrc *ss, struct dso *dso __maybe_unused, - const char *name, - enum dso_binary_type type) -{ - int fd = open(name, O_RDONLY); - if (fd < 0) - return -1; - - ss->name = strdup(name); - if (!ss->name) - goto out_close; - - ss->type = type; - - return 0; -out_close: - close(fd); - return -1; -} - -bool symsrc__possibly_runtime(struct symsrc *ss __maybe_unused) -{ - /* Assume all sym sources could be a runtime image. */ - return true; -} - -bool symsrc__has_symtab(struct symsrc *ss __maybe_unused) -{ - return false; -} - -void symsrc__destroy(struct symsrc *ss) -{ - free(ss->name); - close(ss->fd); -} - -int dso__synthesize_plt_symbols(struct dso *dso __maybe_unused, - struct symsrc *ss __maybe_unused, - struct map *map __maybe_unused, - symbol_filter_t filter __maybe_unused) -{ - return 0; -} - -int dso__load_sym(struct dso *dso, struct map *map __maybe_unused, - struct symsrc *ss, - struct symsrc *runtime_ss __maybe_unused, - symbol_filter_t filter __maybe_unused, - int kmodule __maybe_unused) -{ - unsigned char *build_id[BUILD_ID_SIZE]; - - if (filename__read_build_id(ss->name, build_id, BUILD_ID_SIZE) > 0) { - dso__set_build_id(dso, build_id); - return 1; - } - return 0; -} - -void symbol__elf_init(void) -{ -} diff --git a/trunk/tools/perf/util/symbol.c b/trunk/tools/perf/util/symbol.c index e2e8c697cffe..fdad4eeeb429 100644 --- a/trunk/tools/perf/util/symbol.c +++ b/trunk/tools/perf/util/symbol.c @@ -15,6 +15,8 @@ #include "symbol.h" #include "strlist.h" +#include +#include #include #include #include @@ -23,7 +25,15 @@ #define KSYM_NAME_LEN 256 #endif +#ifndef NT_GNU_BUILD_ID +#define NT_GNU_BUILD_ID 3 +#endif + static void dso_cache__free(struct rb_root *root); +static bool dso__build_id_equal(const struct dso *dso, u8 *build_id); +static int elf_read_build_id(Elf *elf, void *bf, size_t size); +static void dsos__add(struct list_head *head, struct dso *dso); +static struct map *map__new2(u64 start, struct dso *dso, enum map_type type); static int dso__load_kernel_sym(struct dso *dso, struct map *map, symbol_filter_t filter); static int dso__load_guest_kernel_sym(struct dso *dso, struct map *map, @@ -54,7 +64,7 @@ static enum dso_binary_type binary_type_symtab[] = { DSO_BINARY_TYPE__NOT_FOUND, }; -#define DSO_BINARY_TYPE__SYMTAB_CNT ARRAY_SIZE(binary_type_symtab) +#define DSO_BINARY_TYPE__SYMTAB_CNT sizeof(binary_type_symtab) static enum dso_binary_type binary_type_data[] = { DSO_BINARY_TYPE__BUILD_ID_CACHE, @@ -62,7 +72,7 @@ static enum dso_binary_type binary_type_data[] = { DSO_BINARY_TYPE__NOT_FOUND, }; -#define DSO_BINARY_TYPE__DATA_CNT ARRAY_SIZE(binary_type_data) +#define DSO_BINARY_TYPE__DATA_CNT sizeof(binary_type_data) int dso__name_len(const struct dso *dso) { @@ -160,7 +170,7 @@ static int choose_best_symbol(struct symbol *syma, struct symbol *symb) return SYMBOL_B; } -void symbols__fixup_duplicate(struct rb_root *symbols) +static void symbols__fixup_duplicate(struct rb_root *symbols) { struct rb_node *nd; struct symbol *curr, *next; @@ -189,7 +199,7 @@ void symbols__fixup_duplicate(struct rb_root *symbols) } } -void symbols__fixup_end(struct rb_root *symbols) +static void symbols__fixup_end(struct rb_root *symbols) { struct rb_node *nd, *prevnd = rb_first(symbols); struct symbol *curr, *prev; @@ -212,7 +222,7 @@ void symbols__fixup_end(struct rb_root *symbols) curr->end = roundup(curr->start, 4096); } -void __map_groups__fixup_end(struct map_groups *mg, enum map_type type) +static void __map_groups__fixup_end(struct map_groups *mg, enum map_type type) { struct map *prev, *curr; struct rb_node *nd, *prevnd = rb_first(&mg->maps[type]); @@ -242,7 +252,8 @@ static void map_groups__fixup_end(struct map_groups *mg) __map_groups__fixup_end(mg, i); } -struct symbol *symbol__new(u64 start, u64 len, u8 binding, const char *name) +static struct symbol *symbol__new(u64 start, u64 len, u8 binding, + const char *name) { size_t namelen = strlen(name) + 1; struct symbol *sym = calloc(1, (symbol_conf.priv_size + @@ -379,7 +390,7 @@ void dso__set_build_id(struct dso *dso, void *build_id) dso->has_build_id = 1; } -void symbols__insert(struct rb_root *symbols, struct symbol *sym) +static void symbols__insert(struct rb_root *symbols, struct symbol *sym) { struct rb_node **p = &symbols->rb_node; struct rb_node *parent = NULL; @@ -563,7 +574,7 @@ size_t dso__fprintf(struct dso *dso, enum map_type type, FILE *fp) int kallsyms__parse(const char *filename, void *arg, int (*process_symbol)(void *arg, const char *name, - char type, u64 start)) + char type, u64 start, u64 end)) { char *line = NULL; size_t n; @@ -603,8 +614,13 @@ int kallsyms__parse(const char *filename, void *arg, break; } + /* + * module symbols are not sorted so we add all + * symbols with zero length and rely on + * symbols__fixup_end() to fix it up. + */ err = process_symbol(arg, symbol_name, - symbol_type, start); + symbol_type, start, start); if (err) break; } @@ -631,7 +647,7 @@ static u8 kallsyms2elf_type(char type) } static int map__process_kallsym_symbol(void *arg, const char *name, - char type, u64 start) + char type, u64 start, u64 end) { struct symbol *sym; struct process_kallsyms_args *a = arg; @@ -640,12 +656,8 @@ static int map__process_kallsym_symbol(void *arg, const char *name, if (!symbol_type__is_a(type, a->map->type)) return 0; - /* - * module symbols are not sorted so we add all - * symbols, setting length to 0, and rely on - * symbols__fixup_end() to fix it up. - */ - sym = symbol__new(start, 0, kallsyms2elf_type(type), name); + sym = symbol__new(start, end - start + 1, + kallsyms2elf_type(type), name); if (sym == NULL) return -ENOMEM; /* @@ -892,7 +904,556 @@ static int dso__load_perf_map(struct dso *dso, struct map *map, return -1; } -bool dso__build_id_equal(const struct dso *dso, u8 *build_id) +/** + * elf_symtab__for_each_symbol - iterate thru all the symbols + * + * @syms: struct elf_symtab instance to iterate + * @idx: uint32_t idx + * @sym: GElf_Sym iterator + */ +#define elf_symtab__for_each_symbol(syms, nr_syms, idx, sym) \ + for (idx = 0, gelf_getsym(syms, idx, &sym);\ + idx < nr_syms; \ + idx++, gelf_getsym(syms, idx, &sym)) + +static inline uint8_t elf_sym__type(const GElf_Sym *sym) +{ + return GELF_ST_TYPE(sym->st_info); +} + +static inline int elf_sym__is_function(const GElf_Sym *sym) +{ + return elf_sym__type(sym) == STT_FUNC && + sym->st_name != 0 && + sym->st_shndx != SHN_UNDEF; +} + +static inline bool elf_sym__is_object(const GElf_Sym *sym) +{ + return elf_sym__type(sym) == STT_OBJECT && + sym->st_name != 0 && + sym->st_shndx != SHN_UNDEF; +} + +static inline int elf_sym__is_label(const GElf_Sym *sym) +{ + return elf_sym__type(sym) == STT_NOTYPE && + sym->st_name != 0 && + sym->st_shndx != SHN_UNDEF && + sym->st_shndx != SHN_ABS; +} + +static inline const char *elf_sec__name(const GElf_Shdr *shdr, + const Elf_Data *secstrs) +{ + return secstrs->d_buf + shdr->sh_name; +} + +static inline int elf_sec__is_text(const GElf_Shdr *shdr, + const Elf_Data *secstrs) +{ + return strstr(elf_sec__name(shdr, secstrs), "text") != NULL; +} + +static inline bool elf_sec__is_data(const GElf_Shdr *shdr, + const Elf_Data *secstrs) +{ + return strstr(elf_sec__name(shdr, secstrs), "data") != NULL; +} + +static inline const char *elf_sym__name(const GElf_Sym *sym, + const Elf_Data *symstrs) +{ + return symstrs->d_buf + sym->st_name; +} + +static Elf_Scn *elf_section_by_name(Elf *elf, GElf_Ehdr *ep, + GElf_Shdr *shp, const char *name, + size_t *idx) +{ + Elf_Scn *sec = NULL; + size_t cnt = 1; + + while ((sec = elf_nextscn(elf, sec)) != NULL) { + char *str; + + gelf_getshdr(sec, shp); + str = elf_strptr(elf, ep->e_shstrndx, shp->sh_name); + if (!strcmp(name, str)) { + if (idx) + *idx = cnt; + break; + } + ++cnt; + } + + return sec; +} + +#define elf_section__for_each_rel(reldata, pos, pos_mem, idx, nr_entries) \ + for (idx = 0, pos = gelf_getrel(reldata, 0, &pos_mem); \ + idx < nr_entries; \ + ++idx, pos = gelf_getrel(reldata, idx, &pos_mem)) + +#define elf_section__for_each_rela(reldata, pos, pos_mem, idx, nr_entries) \ + for (idx = 0, pos = gelf_getrela(reldata, 0, &pos_mem); \ + idx < nr_entries; \ + ++idx, pos = gelf_getrela(reldata, idx, &pos_mem)) + +/* + * We need to check if we have a .dynsym, so that we can handle the + * .plt, synthesizing its symbols, that aren't on the symtabs (be it + * .dynsym or .symtab). + * And always look at the original dso, not at debuginfo packages, that + * have the PLT data stripped out (shdr_rel_plt.sh_type == SHT_NOBITS). + */ +static int +dso__synthesize_plt_symbols(struct dso *dso, char *name, struct map *map, + symbol_filter_t filter) +{ + uint32_t nr_rel_entries, idx; + GElf_Sym sym; + u64 plt_offset; + GElf_Shdr shdr_plt; + struct symbol *f; + GElf_Shdr shdr_rel_plt, shdr_dynsym; + Elf_Data *reldata, *syms, *symstrs; + Elf_Scn *scn_plt_rel, *scn_symstrs, *scn_dynsym; + size_t dynsym_idx; + GElf_Ehdr ehdr; + char sympltname[1024]; + Elf *elf; + int nr = 0, symidx, fd, err = 0; + + fd = open(name, O_RDONLY); + if (fd < 0) + goto out; + + elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL); + if (elf == NULL) + goto out_close; + + if (gelf_getehdr(elf, &ehdr) == NULL) + goto out_elf_end; + + scn_dynsym = elf_section_by_name(elf, &ehdr, &shdr_dynsym, + ".dynsym", &dynsym_idx); + if (scn_dynsym == NULL) + goto out_elf_end; + + scn_plt_rel = elf_section_by_name(elf, &ehdr, &shdr_rel_plt, + ".rela.plt", NULL); + if (scn_plt_rel == NULL) { + scn_plt_rel = elf_section_by_name(elf, &ehdr, &shdr_rel_plt, + ".rel.plt", NULL); + if (scn_plt_rel == NULL) + goto out_elf_end; + } + + err = -1; + + if (shdr_rel_plt.sh_link != dynsym_idx) + goto out_elf_end; + + if (elf_section_by_name(elf, &ehdr, &shdr_plt, ".plt", NULL) == NULL) + goto out_elf_end; + + /* + * Fetch the relocation section to find the idxes to the GOT + * and the symbols in the .dynsym they refer to. + */ + reldata = elf_getdata(scn_plt_rel, NULL); + if (reldata == NULL) + goto out_elf_end; + + syms = elf_getdata(scn_dynsym, NULL); + if (syms == NULL) + goto out_elf_end; + + scn_symstrs = elf_getscn(elf, shdr_dynsym.sh_link); + if (scn_symstrs == NULL) + goto out_elf_end; + + symstrs = elf_getdata(scn_symstrs, NULL); + if (symstrs == NULL) + goto out_elf_end; + + nr_rel_entries = shdr_rel_plt.sh_size / shdr_rel_plt.sh_entsize; + plt_offset = shdr_plt.sh_offset; + + if (shdr_rel_plt.sh_type == SHT_RELA) { + GElf_Rela pos_mem, *pos; + + elf_section__for_each_rela(reldata, pos, pos_mem, idx, + nr_rel_entries) { + symidx = GELF_R_SYM(pos->r_info); + plt_offset += shdr_plt.sh_entsize; + gelf_getsym(syms, symidx, &sym); + snprintf(sympltname, sizeof(sympltname), + "%s@plt", elf_sym__name(&sym, symstrs)); + + f = symbol__new(plt_offset, shdr_plt.sh_entsize, + STB_GLOBAL, sympltname); + if (!f) + goto out_elf_end; + + if (filter && filter(map, f)) + symbol__delete(f); + else { + symbols__insert(&dso->symbols[map->type], f); + ++nr; + } + } + } else if (shdr_rel_plt.sh_type == SHT_REL) { + GElf_Rel pos_mem, *pos; + elf_section__for_each_rel(reldata, pos, pos_mem, idx, + nr_rel_entries) { + symidx = GELF_R_SYM(pos->r_info); + plt_offset += shdr_plt.sh_entsize; + gelf_getsym(syms, symidx, &sym); + snprintf(sympltname, sizeof(sympltname), + "%s@plt", elf_sym__name(&sym, symstrs)); + + f = symbol__new(plt_offset, shdr_plt.sh_entsize, + STB_GLOBAL, sympltname); + if (!f) + goto out_elf_end; + + if (filter && filter(map, f)) + symbol__delete(f); + else { + symbols__insert(&dso->symbols[map->type], f); + ++nr; + } + } + } + + err = 0; +out_elf_end: + elf_end(elf); +out_close: + close(fd); + + if (err == 0) + return nr; +out: + pr_debug("%s: problems reading %s PLT info.\n", + __func__, dso->long_name); + return 0; +} + +static bool elf_sym__is_a(GElf_Sym *sym, enum map_type type) +{ + switch (type) { + case MAP__FUNCTION: + return elf_sym__is_function(sym); + case MAP__VARIABLE: + return elf_sym__is_object(sym); + default: + return false; + } +} + +static bool elf_sec__is_a(GElf_Shdr *shdr, Elf_Data *secstrs, + enum map_type type) +{ + switch (type) { + case MAP__FUNCTION: + return elf_sec__is_text(shdr, secstrs); + case MAP__VARIABLE: + return elf_sec__is_data(shdr, secstrs); + default: + return false; + } +} + +static size_t elf_addr_to_index(Elf *elf, GElf_Addr addr) +{ + Elf_Scn *sec = NULL; + GElf_Shdr shdr; + size_t cnt = 1; + + while ((sec = elf_nextscn(elf, sec)) != NULL) { + gelf_getshdr(sec, &shdr); + + if ((addr >= shdr.sh_addr) && + (addr < (shdr.sh_addr + shdr.sh_size))) + return cnt; + + ++cnt; + } + + return -1; +} + +static int dso__swap_init(struct dso *dso, unsigned char eidata) +{ + static unsigned int const endian = 1; + + dso->needs_swap = DSO_SWAP__NO; + + switch (eidata) { + case ELFDATA2LSB: + /* We are big endian, DSO is little endian. */ + if (*(unsigned char const *)&endian != 1) + dso->needs_swap = DSO_SWAP__YES; + break; + + case ELFDATA2MSB: + /* We are little endian, DSO is big endian. */ + if (*(unsigned char const *)&endian != 0) + dso->needs_swap = DSO_SWAP__YES; + break; + + default: + pr_err("unrecognized DSO data encoding %d\n", eidata); + return -EINVAL; + } + + return 0; +} + +static int dso__load_sym(struct dso *dso, struct map *map, const char *name, + int fd, symbol_filter_t filter, int kmodule, + int want_symtab) +{ + struct kmap *kmap = dso->kernel ? map__kmap(map) : NULL; + struct map *curr_map = map; + struct dso *curr_dso = dso; + Elf_Data *symstrs, *secstrs; + uint32_t nr_syms; + int err = -1; + uint32_t idx; + GElf_Ehdr ehdr; + GElf_Shdr shdr, opdshdr; + Elf_Data *syms, *opddata = NULL; + GElf_Sym sym; + Elf_Scn *sec, *sec_strndx, *opdsec; + Elf *elf; + int nr = 0; + size_t opdidx = 0; + + elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL); + if (elf == NULL) { + pr_debug("%s: cannot read %s ELF file.\n", __func__, name); + goto out_close; + } + + if (gelf_getehdr(elf, &ehdr) == NULL) { + pr_debug("%s: cannot get elf header.\n", __func__); + goto out_elf_end; + } + + if (dso__swap_init(dso, ehdr.e_ident[EI_DATA])) + goto out_elf_end; + + /* Always reject images with a mismatched build-id: */ + if (dso->has_build_id) { + u8 build_id[BUILD_ID_SIZE]; + + if (elf_read_build_id(elf, build_id, BUILD_ID_SIZE) < 0) + goto out_elf_end; + + if (!dso__build_id_equal(dso, build_id)) + goto out_elf_end; + } + + sec = elf_section_by_name(elf, &ehdr, &shdr, ".symtab", NULL); + if (sec == NULL) { + if (want_symtab) + goto out_elf_end; + + sec = elf_section_by_name(elf, &ehdr, &shdr, ".dynsym", NULL); + if (sec == NULL) + goto out_elf_end; + } + + opdsec = elf_section_by_name(elf, &ehdr, &opdshdr, ".opd", &opdidx); + if (opdshdr.sh_type != SHT_PROGBITS) + opdsec = NULL; + if (opdsec) + opddata = elf_rawdata(opdsec, NULL); + + syms = elf_getdata(sec, NULL); + if (syms == NULL) + goto out_elf_end; + + sec = elf_getscn(elf, shdr.sh_link); + if (sec == NULL) + goto out_elf_end; + + symstrs = elf_getdata(sec, NULL); + if (symstrs == NULL) + goto out_elf_end; + + sec_strndx = elf_getscn(elf, ehdr.e_shstrndx); + if (sec_strndx == NULL) + goto out_elf_end; + + secstrs = elf_getdata(sec_strndx, NULL); + if (secstrs == NULL) + goto out_elf_end; + + nr_syms = shdr.sh_size / shdr.sh_entsize; + + memset(&sym, 0, sizeof(sym)); + if (dso->kernel == DSO_TYPE_USER) { + dso->adjust_symbols = (ehdr.e_type == ET_EXEC || + elf_section_by_name(elf, &ehdr, &shdr, + ".gnu.prelink_undo", + NULL) != NULL); + } else { + dso->adjust_symbols = 0; + } + elf_symtab__for_each_symbol(syms, nr_syms, idx, sym) { + struct symbol *f; + const char *elf_name = elf_sym__name(&sym, symstrs); + char *demangled = NULL; + int is_label = elf_sym__is_label(&sym); + const char *section_name; + + if (kmap && kmap->ref_reloc_sym && kmap->ref_reloc_sym->name && + strcmp(elf_name, kmap->ref_reloc_sym->name) == 0) + kmap->ref_reloc_sym->unrelocated_addr = sym.st_value; + + if (!is_label && !elf_sym__is_a(&sym, map->type)) + continue; + + /* Reject ARM ELF "mapping symbols": these aren't unique and + * don't identify functions, so will confuse the profile + * output: */ + if (ehdr.e_machine == EM_ARM) { + if (!strcmp(elf_name, "$a") || + !strcmp(elf_name, "$d") || + !strcmp(elf_name, "$t")) + continue; + } + + if (opdsec && sym.st_shndx == opdidx) { + u32 offset = sym.st_value - opdshdr.sh_addr; + u64 *opd = opddata->d_buf + offset; + sym.st_value = DSO__SWAP(dso, u64, *opd); + sym.st_shndx = elf_addr_to_index(elf, sym.st_value); + } + + sec = elf_getscn(elf, sym.st_shndx); + if (!sec) + goto out_elf_end; + + gelf_getshdr(sec, &shdr); + + if (is_label && !elf_sec__is_a(&shdr, secstrs, map->type)) + continue; + + section_name = elf_sec__name(&shdr, secstrs); + + /* On ARM, symbols for thumb functions have 1 added to + * the symbol address as a flag - remove it */ + if ((ehdr.e_machine == EM_ARM) && + (map->type == MAP__FUNCTION) && + (sym.st_value & 1)) + --sym.st_value; + + if (dso->kernel != DSO_TYPE_USER || kmodule) { + char dso_name[PATH_MAX]; + + if (strcmp(section_name, + (curr_dso->short_name + + dso->short_name_len)) == 0) + goto new_symbol; + + if (strcmp(section_name, ".text") == 0) { + curr_map = map; + curr_dso = dso; + goto new_symbol; + } + + snprintf(dso_name, sizeof(dso_name), + "%s%s", dso->short_name, section_name); + + curr_map = map_groups__find_by_name(kmap->kmaps, map->type, dso_name); + if (curr_map == NULL) { + u64 start = sym.st_value; + + if (kmodule) + start += map->start + shdr.sh_offset; + + curr_dso = dso__new(dso_name); + if (curr_dso == NULL) + goto out_elf_end; + curr_dso->kernel = dso->kernel; + curr_dso->long_name = dso->long_name; + curr_dso->long_name_len = dso->long_name_len; + curr_map = map__new2(start, curr_dso, + map->type); + if (curr_map == NULL) { + dso__delete(curr_dso); + goto out_elf_end; + } + curr_map->map_ip = identity__map_ip; + curr_map->unmap_ip = identity__map_ip; + curr_dso->symtab_type = dso->symtab_type; + map_groups__insert(kmap->kmaps, curr_map); + dsos__add(&dso->node, curr_dso); + dso__set_loaded(curr_dso, map->type); + } else + curr_dso = curr_map->dso; + + goto new_symbol; + } + + if (curr_dso->adjust_symbols) { + pr_debug4("%s: adjusting symbol: st_value: %#" PRIx64 " " + "sh_addr: %#" PRIx64 " sh_offset: %#" PRIx64 "\n", __func__, + (u64)sym.st_value, (u64)shdr.sh_addr, + (u64)shdr.sh_offset); + sym.st_value -= shdr.sh_addr - shdr.sh_offset; + } + /* + * We need to figure out if the object was created from C++ sources + * DWARF DW_compile_unit has this, but we don't always have access + * to it... + */ + demangled = bfd_demangle(NULL, elf_name, DMGL_PARAMS | DMGL_ANSI); + if (demangled != NULL) + elf_name = demangled; +new_symbol: + f = symbol__new(sym.st_value, sym.st_size, + GELF_ST_BIND(sym.st_info), elf_name); + free(demangled); + if (!f) + goto out_elf_end; + + if (filter && filter(curr_map, f)) + symbol__delete(f); + else { + symbols__insert(&curr_dso->symbols[curr_map->type], f); + nr++; + } + } + + /* + * For misannotated, zeroed, ASM function sizes. + */ + if (nr > 0) { + symbols__fixup_duplicate(&dso->symbols[map->type]); + symbols__fixup_end(&dso->symbols[map->type]); + if (kmap) { + /* + * We need to fixup this here too because we create new + * maps here, for things like vsyscall sections. + */ + __map_groups__fixup_end(kmap->kmaps, map->type); + } + } + err = nr; +out_elf_end: + elf_end(elf); +out_close: + return err; +} + +static bool dso__build_id_equal(const struct dso *dso, u8 *build_id) { return memcmp(dso->build_id, build_id, sizeof(dso->build_id)) == 0; } @@ -919,11 +1480,216 @@ bool __dsos__read_build_ids(struct list_head *head, bool with_hits) return have_build_id; } +/* + * Align offset to 4 bytes as needed for note name and descriptor data. + */ +#define NOTE_ALIGN(n) (((n) + 3) & -4U) + +static int elf_read_build_id(Elf *elf, void *bf, size_t size) +{ + int err = -1; + GElf_Ehdr ehdr; + GElf_Shdr shdr; + Elf_Data *data; + Elf_Scn *sec; + Elf_Kind ek; + void *ptr; + + if (size < BUILD_ID_SIZE) + goto out; + + ek = elf_kind(elf); + if (ek != ELF_K_ELF) + goto out; + + if (gelf_getehdr(elf, &ehdr) == NULL) { + pr_err("%s: cannot get elf header.\n", __func__); + goto out; + } + + /* + * Check following sections for notes: + * '.note.gnu.build-id' + * '.notes' + * '.note' (VDSO specific) + */ + do { + sec = elf_section_by_name(elf, &ehdr, &shdr, + ".note.gnu.build-id", NULL); + if (sec) + break; + + sec = elf_section_by_name(elf, &ehdr, &shdr, + ".notes", NULL); + if (sec) + break; + + sec = elf_section_by_name(elf, &ehdr, &shdr, + ".note", NULL); + if (sec) + break; + + return err; + + } while (0); + + data = elf_getdata(sec, NULL); + if (data == NULL) + goto out; + + ptr = data->d_buf; + while (ptr < (data->d_buf + data->d_size)) { + GElf_Nhdr *nhdr = ptr; + size_t namesz = NOTE_ALIGN(nhdr->n_namesz), + descsz = NOTE_ALIGN(nhdr->n_descsz); + const char *name; + + ptr += sizeof(*nhdr); + name = ptr; + ptr += namesz; + if (nhdr->n_type == NT_GNU_BUILD_ID && + nhdr->n_namesz == sizeof("GNU")) { + if (memcmp(name, "GNU", sizeof("GNU")) == 0) { + size_t sz = min(size, descsz); + memcpy(bf, ptr, sz); + memset(bf + sz, 0, size - sz); + err = descsz; + break; + } + } + ptr += descsz; + } + +out: + return err; +} + +int filename__read_build_id(const char *filename, void *bf, size_t size) +{ + int fd, err = -1; + Elf *elf; + + if (size < BUILD_ID_SIZE) + goto out; + + fd = open(filename, O_RDONLY); + if (fd < 0) + goto out; + + elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL); + if (elf == NULL) { + pr_debug2("%s: cannot read %s ELF file.\n", __func__, filename); + goto out_close; + } + + err = elf_read_build_id(elf, bf, size); + + elf_end(elf); +out_close: + close(fd); +out: + return err; +} + +int sysfs__read_build_id(const char *filename, void *build_id, size_t size) +{ + int fd, err = -1; + + if (size < BUILD_ID_SIZE) + goto out; + + fd = open(filename, O_RDONLY); + if (fd < 0) + goto out; + + while (1) { + char bf[BUFSIZ]; + GElf_Nhdr nhdr; + size_t namesz, descsz; + + if (read(fd, &nhdr, sizeof(nhdr)) != sizeof(nhdr)) + break; + + namesz = NOTE_ALIGN(nhdr.n_namesz); + descsz = NOTE_ALIGN(nhdr.n_descsz); + if (nhdr.n_type == NT_GNU_BUILD_ID && + nhdr.n_namesz == sizeof("GNU")) { + if (read(fd, bf, namesz) != (ssize_t)namesz) + break; + if (memcmp(bf, "GNU", sizeof("GNU")) == 0) { + size_t sz = min(descsz, size); + if (read(fd, build_id, sz) == (ssize_t)sz) { + memset(build_id + sz, 0, size - sz); + err = 0; + break; + } + } else if (read(fd, bf, descsz) != (ssize_t)descsz) + break; + } else { + int n = namesz + descsz; + if (read(fd, bf, n) != n) + break; + } + } + close(fd); +out: + return err; +} + +static int filename__read_debuglink(const char *filename, + char *debuglink, size_t size) +{ + int fd, err = -1; + Elf *elf; + GElf_Ehdr ehdr; + GElf_Shdr shdr; + Elf_Data *data; + Elf_Scn *sec; + Elf_Kind ek; + + fd = open(filename, O_RDONLY); + if (fd < 0) + goto out; + + elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL); + if (elf == NULL) { + pr_debug2("%s: cannot read %s ELF file.\n", __func__, filename); + goto out_close; + } + + ek = elf_kind(elf); + if (ek != ELF_K_ELF) + goto out_close; + + if (gelf_getehdr(elf, &ehdr) == NULL) { + pr_err("%s: cannot get elf header.\n", __func__); + goto out_close; + } + + sec = elf_section_by_name(elf, &ehdr, &shdr, + ".gnu_debuglink", NULL); + if (sec == NULL) + goto out_close; + + data = elf_getdata(sec, NULL); + if (data == NULL) + goto out_close; + + /* the start of this section is a zero-terminated string */ + strncpy(debuglink, data->d_buf, size); + + elf_end(elf); + +out_close: + close(fd); +out: + return err; +} + char dso__symtab_origin(const struct dso *dso) { static const char origin[] = { [DSO_BINARY_TYPE__KALLSYMS] = 'k', - [DSO_BINARY_TYPE__VMLINUX] = 'v', [DSO_BINARY_TYPE__JAVA_JIT] = 'j', [DSO_BINARY_TYPE__DEBUGLINK] = 'l', [DSO_BINARY_TYPE__BUILD_ID_CACHE] = 'B', @@ -934,7 +1700,6 @@ char dso__symtab_origin(const struct dso *dso) [DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE] = 'K', [DSO_BINARY_TYPE__GUEST_KALLSYMS] = 'g', [DSO_BINARY_TYPE__GUEST_KMODULE] = 'G', - [DSO_BINARY_TYPE__GUEST_VMLINUX] = 'V', }; if (dso == NULL || dso->symtab_type == DSO_BINARY_TYPE__NOT_FOUND) @@ -1010,9 +1775,7 @@ int dso__binary_type_file(struct dso *dso, enum dso_binary_type type, default: case DSO_BINARY_TYPE__KALLSYMS: - case DSO_BINARY_TYPE__VMLINUX: case DSO_BINARY_TYPE__GUEST_KALLSYMS: - case DSO_BINARY_TYPE__GUEST_VMLINUX: case DSO_BINARY_TYPE__JAVA_JIT: case DSO_BINARY_TYPE__NOT_FOUND: ret = -1; @@ -1026,12 +1789,11 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter) { char *name; int ret = -1; + int fd; u_int i; struct machine *machine; char *root_dir = (char *) ""; - int ss_pos = 0; - struct symsrc ss_[2]; - struct symsrc *syms_ss = NULL, *runtime_ss = NULL; + int want_symtab; dso__set_loaded(dso, map->type); @@ -1073,69 +1835,54 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter) root_dir = machine->root_dir; /* Iterate over candidate debug images. - * Keep track of "interesting" ones (those which have a symtab, dynsym, - * and/or opd section) for processing. + * On the first pass, only load images if they have a full symtab. + * Failing that, do a second pass where we accept .dynsym also */ + want_symtab = 1; +restart: for (i = 0; i < DSO_BINARY_TYPE__SYMTAB_CNT; i++) { - struct symsrc *ss = &ss_[ss_pos]; - bool next_slot = false; - enum dso_binary_type symtab_type = binary_type_symtab[i]; + dso->symtab_type = binary_type_symtab[i]; - if (dso__binary_type_file(dso, symtab_type, + if (dso__binary_type_file(dso, dso->symtab_type, root_dir, name, PATH_MAX)) continue; /* Name is now the name of the next image to try */ - if (symsrc__init(ss, dso, name, symtab_type) < 0) + fd = open(name, O_RDONLY); + if (fd < 0) continue; - if (!syms_ss && symsrc__has_symtab(ss)) { - syms_ss = ss; - next_slot = true; - } + ret = dso__load_sym(dso, map, name, fd, filter, 0, + want_symtab); + close(fd); - if (!runtime_ss && symsrc__possibly_runtime(ss)) { - runtime_ss = ss; - next_slot = true; - } + /* + * Some people seem to have debuginfo files _WITHOUT_ debug + * info!?!? + */ + if (!ret) + continue; - if (next_slot) { - ss_pos++; + if (ret > 0) { + int nr_plt; - if (syms_ss && runtime_ss) - break; + nr_plt = dso__synthesize_plt_symbols(dso, name, map, filter); + if (nr_plt > 0) + ret += nr_plt; + break; } - } - if (!runtime_ss && !syms_ss) - goto out_free; - - if (runtime_ss && !syms_ss) { - syms_ss = runtime_ss; - } - - /* We'll have to hope for the best */ - if (!runtime_ss && syms_ss) - runtime_ss = syms_ss; - - if (syms_ss) - ret = dso__load_sym(dso, map, syms_ss, runtime_ss, filter, 0); - else - ret = -1; - - if (ret > 0) { - int nr_plt; - - nr_plt = dso__synthesize_plt_symbols(dso, runtime_ss, map, filter); - if (nr_plt > 0) - ret += nr_plt; + /* + * If we wanted a full symtab but no image had one, + * relax our requirements and repeat the search. + */ + if (ret <= 0 && want_symtab) { + want_symtab = 0; + goto restart; } - for (; ss_pos > 0; ss_pos--) - symsrc__destroy(&ss_[ss_pos - 1]); -out_free: free(name); if (ret < 0 && strstr(dso->name, " (deleted)") != NULL) return 0; @@ -1283,6 +2030,25 @@ static int machine__set_modules_path(struct machine *machine) return map_groups__set_modules_path_dir(&machine->kmaps, modules_path); } +/* + * Constructor variant for modules (where we know from /proc/modules where + * they are loaded) and for vmlinux, where only after we load all the + * symbols we'll know where it starts and ends. + */ +static struct map *map__new2(u64 start, struct dso *dso, enum map_type type) +{ + struct map *map = calloc(1, (sizeof(*map) + + (dso->kernel ? sizeof(struct kmap) : 0))); + if (map != NULL) { + /* + * ->end will be filled after we load all the symbols + */ + map__init(map, type, start, 0, 0, dso); + } + + return map; +} + struct map *machine__new_module(struct machine *machine, u64 start, const char *filename) { @@ -1375,30 +2141,22 @@ static int machine__create_modules(struct machine *machine) int dso__load_vmlinux(struct dso *dso, struct map *map, const char *vmlinux, symbol_filter_t filter) { - int err = -1; - struct symsrc ss; + int err = -1, fd; char symfs_vmlinux[PATH_MAX]; - enum dso_binary_type symtab_type; snprintf(symfs_vmlinux, sizeof(symfs_vmlinux), "%s%s", symbol_conf.symfs, vmlinux); - - if (dso->kernel == DSO_TYPE_GUEST_KERNEL) - symtab_type = DSO_BINARY_TYPE__GUEST_VMLINUX; - else - symtab_type = DSO_BINARY_TYPE__VMLINUX; - - if (symsrc__init(&ss, dso, symfs_vmlinux, symtab_type)) + fd = open(symfs_vmlinux, O_RDONLY); + if (fd < 0) return -1; - err = dso__load_sym(dso, map, &ss, &ss, filter, 0); - symsrc__destroy(&ss); + dso__set_long_name(dso, (char *)vmlinux); + dso__set_loaded(dso, map->type); + err = dso__load_sym(dso, map, symfs_vmlinux, fd, filter, 0, 0); + close(fd); - if (err > 0) { - dso__set_long_name(dso, (char *)vmlinux); - dso__set_loaded(dso, map->type); + if (err > 0) pr_debug("Using %s for symbols\n", symfs_vmlinux); - } return err; } @@ -1415,8 +2173,10 @@ int dso__load_vmlinux_path(struct dso *dso, struct map *map, filename = dso__build_id_filename(dso, NULL, 0); if (filename != NULL) { err = dso__load_vmlinux(dso, map, filename, filter); - if (err > 0) + if (err > 0) { + dso__set_long_name(dso, filename); goto out; + } free(filename); } @@ -1531,8 +2291,9 @@ static int dso__load_kernel_sym(struct dso *dso, struct map *map, free(kallsyms_allocated_filename); if (err > 0) { - dso__set_long_name(dso, strdup("[kernel.kallsyms]")); out_fixup: + if (kallsyms_filename != NULL) + dso__set_long_name(dso, strdup("[kernel.kallsyms]")); map__fixup_start(map); map__fixup_end(map); } @@ -1591,12 +2352,12 @@ static int dso__load_guest_kernel_sym(struct dso *dso, struct map *map, return err; } -void dsos__add(struct list_head *head, struct dso *dso) +static void dsos__add(struct list_head *head, struct dso *dso) { list_add_tail(&dso->node, head); } -struct dso *dsos__find(struct list_head *head, const char *name) +static struct dso *dsos__find(struct list_head *head, const char *name) { struct dso *pos; @@ -1755,7 +2516,7 @@ struct process_args { }; static int symbol__in_kernel(void *arg, const char *name, - char type __maybe_unused, u64 start) + char type __used, u64 start, u64 end __used) { struct process_args *args = arg; @@ -1991,10 +2752,9 @@ int symbol__init(void) if (symbol_conf.initialized) return 0; - symbol_conf.priv_size = PERF_ALIGN(symbol_conf.priv_size, sizeof(u64)); - - symbol__elf_init(); + symbol_conf.priv_size = ALIGN(symbol_conf.priv_size, sizeof(u64)); + elf_version(EV_CURRENT); if (symbol_conf.sort_by_name) symbol_conf.priv_size += (sizeof(struct symbol_name_rb_node) - sizeof(struct symbol)); @@ -2115,7 +2875,6 @@ int machines__create_guest_kernel_maps(struct rb_root *machines) int i, items = 0; char path[PATH_MAX]; pid_t pid; - char *endp; if (symbol_conf.default_guest_vmlinux_name || symbol_conf.default_guest_modules || @@ -2132,14 +2891,7 @@ int machines__create_guest_kernel_maps(struct rb_root *machines) /* Filter out . and .. */ continue; } - pid = (pid_t)strtol(namelist[i]->d_name, &endp, 10); - if ((*endp != '\0') || - (endp == namelist[i]->d_name) || - (errno == ERANGE)) { - pr_debug("invalid directory (%s). Skipping.\n", - namelist[i]->d_name); - continue; - } + pid = atoi(namelist[i]->d_name); sprintf(path, "%s/%s/proc/kallsyms", symbol_conf.guestmount, namelist[i]->d_name); diff --git a/trunk/tools/perf/util/symbol.h b/trunk/tools/perf/util/symbol.h index b441b07172b7..1fe733a1e21f 100644 --- a/trunk/tools/perf/util/symbol.h +++ b/trunk/tools/perf/util/symbol.h @@ -10,31 +10,22 @@ #include #include #include -#include - -#ifndef NO_LIBELF_SUPPORT -#include -#include -#include -#endif #ifdef HAVE_CPLUS_DEMANGLE extern char *cplus_demangle(const char *, int); -static inline char *bfd_demangle(void __maybe_unused *v, const char *c, int i) +static inline char *bfd_demangle(void __used *v, const char *c, int i) { return cplus_demangle(c, i); } #else #ifdef NO_DEMANGLE -static inline char *bfd_demangle(void __maybe_unused *v, - const char __maybe_unused *c, - int __maybe_unused i) +static inline char *bfd_demangle(void __used *v, const char __used *c, + int __used i) { return NULL; } #else -#define PACKAGE 'perf' #include #endif #endif @@ -167,8 +158,6 @@ struct addr_location { enum dso_binary_type { DSO_BINARY_TYPE__KALLSYMS = 0, DSO_BINARY_TYPE__GUEST_KALLSYMS, - DSO_BINARY_TYPE__VMLINUX, - DSO_BINARY_TYPE__GUEST_VMLINUX, DSO_BINARY_TYPE__JAVA_JIT, DSO_BINARY_TYPE__DEBUGLINK, DSO_BINARY_TYPE__BUILD_ID_CACHE, @@ -228,36 +217,6 @@ struct dso { char name[0]; }; -struct symsrc { - char *name; - int fd; - enum dso_binary_type type; - -#ifndef NO_LIBELF_SUPPORT - Elf *elf; - GElf_Ehdr ehdr; - - Elf_Scn *opdsec; - size_t opdidx; - GElf_Shdr opdshdr; - - Elf_Scn *symtab; - GElf_Shdr symshdr; - - Elf_Scn *dynsym; - size_t dynsym_idx; - GElf_Shdr dynshdr; - - bool adjust_symbols; -#endif -}; - -void symsrc__destroy(struct symsrc *ss); -int symsrc__init(struct symsrc *ss, struct dso *dso, const char *name, - enum dso_binary_type type); -bool symsrc__has_symtab(struct symsrc *ss); -bool symsrc__possibly_runtime(struct symsrc *ss); - #define DSO__SWAP(dso, type, val) \ ({ \ type ____r = val; \ @@ -295,8 +254,6 @@ static inline void dso__set_loaded(struct dso *dso, enum map_type type) void dso__sort_by_name(struct dso *dso, enum map_type type); -void dsos__add(struct list_head *head, struct dso *dso); -struct dso *dsos__find(struct list_head *head, const char *name); struct dso *__dsos__findnew(struct list_head *head, const char *name); int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter); @@ -326,7 +283,6 @@ size_t dso__fprintf(struct dso *dso, enum map_type type, FILE *fp); char dso__symtab_origin(const struct dso *dso); void dso__set_long_name(struct dso *dso, char *name); void dso__set_build_id(struct dso *dso, void *build_id); -bool dso__build_id_equal(const struct dso *dso, u8 *build_id); void dso__read_running_kernel_build_id(struct dso *dso, struct machine *machine); struct map *dso__new_map(const char *name); @@ -341,9 +297,7 @@ bool __dsos__read_build_ids(struct list_head *head, bool with_hits); int build_id__sprintf(const u8 *build_id, int len, char *bf); int kallsyms__parse(const char *filename, void *arg, int (*process_symbol)(void *arg, const char *name, - char type, u64 start)); -int filename__read_debuglink(const char *filename, char *debuglink, - size_t size); + char type, u64 start, u64 end)); void machine__destroy_kernel_maps(struct machine *machine); int __machine__create_kernel_maps(struct machine *machine, struct dso *kernel); @@ -355,8 +309,6 @@ void machines__destroy_guest_kernel_maps(struct rb_root *machines); int symbol__init(void); void symbol__exit(void); -void symbol__elf_init(void); -struct symbol *symbol__new(u64 start, u64 len, u8 binding, const char *name); size_t symbol__fprintf_symname_offs(const struct symbol *sym, const struct addr_location *al, FILE *fp); size_t symbol__fprintf_symname(const struct symbol *sym, FILE *fp); @@ -374,15 +326,4 @@ ssize_t dso__data_read_addr(struct dso *dso, struct map *map, struct machine *machine, u64 addr, u8 *data, ssize_t size); int dso__test_data(void); -int dso__load_sym(struct dso *dso, struct map *map, struct symsrc *syms_ss, - struct symsrc *runtime_ss, symbol_filter_t filter, - int kmodule); -int dso__synthesize_plt_symbols(struct dso *dso, struct symsrc *ss, - struct map *map, symbol_filter_t filter); - -void symbols__insert(struct rb_root *symbols, struct symbol *sym); -void symbols__fixup_duplicate(struct rb_root *symbols); -void symbols__fixup_end(struct rb_root *symbols); -void __map_groups__fixup_end(struct map_groups *mg, enum map_type type); - #endif /* __PERF_SYMBOL */ diff --git a/trunk/tools/perf/util/target.c b/trunk/tools/perf/util/target.c index 065528b7563e..3f59c496e64c 100644 --- a/trunk/tools/perf/util/target.c +++ b/trunk/tools/perf/util/target.c @@ -110,15 +110,15 @@ int perf_target__strerror(struct perf_target *target, int errnum, int idx; const char *msg; - BUG_ON(buflen == 0); + BUG_ON(buflen > 0); if (errnum >= 0) { const char *err = strerror_r(errnum, buf, buflen); if (err != buf) { size_t len = strlen(err); - memcpy(buf, err, min(buflen - 1, len)); - *(buf + min(buflen - 1, len)) = '\0'; + char *c = mempcpy(buf, err, min(buflen - 1, len)); + *c = '\0'; } return 0; diff --git a/trunk/tools/perf/util/thread.h b/trunk/tools/perf/util/thread.h index f66610b7bacf..70c2c13ff679 100644 --- a/trunk/tools/perf/util/thread.h +++ b/trunk/tools/perf/util/thread.h @@ -16,8 +16,6 @@ struct thread { bool comm_set; char *comm; int comm_len; - - void *priv; }; struct machine; diff --git a/trunk/tools/perf/util/top.c b/trunk/tools/perf/util/top.c index 884dde9b9bc1..7eeebcee291c 100644 --- a/trunk/tools/perf/util/top.c +++ b/trunk/tools/perf/util/top.c @@ -58,7 +58,8 @@ size_t perf_top__header_snprintf(struct perf_top *top, char *bf, size_t size) } if (top->evlist->nr_entries == 1) { - struct perf_evsel *first = perf_evlist__first(top->evlist); + struct perf_evsel *first; + first = list_entry(top->evlist->entries.next, struct perf_evsel, node); ret += SNPRINTF(bf + ret, size - ret, "%" PRIu64 "%s ", (uint64_t)first->attr.sample_period, top->freq ? "Hz" : ""); diff --git a/trunk/tools/perf/util/top.h b/trunk/tools/perf/util/top.h index 86ff1b15059b..33347ca89ee4 100644 --- a/trunk/tools/perf/util/top.h +++ b/trunk/tools/perf/util/top.h @@ -5,7 +5,6 @@ #include "types.h" #include #include -#include struct perf_evlist; struct perf_evsel; diff --git a/trunk/tools/perf/util/trace-event-parse.c b/trunk/tools/perf/util/trace-event-parse.c index 3aabcd687cd5..0715c843c2e7 100644 --- a/trunk/tools/perf/util/trace-event-parse.c +++ b/trunk/tools/perf/util/trace-event-parse.c @@ -162,16 +162,25 @@ int trace_parse_common_pid(struct pevent *pevent, void *data) return pevent_data_pid(pevent, &record); } -unsigned long long read_size(struct event_format *event, void *ptr, int size) +unsigned long long read_size(struct pevent *pevent, void *ptr, int size) { - return pevent_read_number(event->pevent, ptr, size); + return pevent_read_number(pevent, ptr, size); } -void event_format__print(struct event_format *event, - int cpu, void *data, int size) +void print_trace_event(struct pevent *pevent, int cpu, void *data, int size) { + struct event_format *event; struct pevent_record record; struct trace_seq s; + int type; + + type = trace_parse_common_type(pevent, data); + + event = pevent_find_event(pevent, type); + if (!event) { + warning("ug! no event found for type %d", type); + return; + } memset(&record, 0, sizeof(record)); record.cpu = cpu; @@ -183,19 +192,6 @@ void event_format__print(struct event_format *event, trace_seq_do_printf(&s); } -void print_trace_event(struct pevent *pevent, int cpu, void *data, int size) -{ - int type = trace_parse_common_type(pevent, data); - struct event_format *event = pevent_find_event(pevent, type); - - if (!event) { - warning("ug! no event found for type %d", type); - return; - } - - event_format__print(event, cpu, data, size); -} - void print_event(struct pevent *pevent, int cpu, void *data, int size, unsigned long long nsecs, char *comm) { @@ -221,7 +217,7 @@ void print_event(struct pevent *pevent, int cpu, void *data, int size, } void parse_proc_kallsyms(struct pevent *pevent, - char *file, unsigned int size __maybe_unused) + char *file, unsigned int size __unused) { unsigned long long addr; char *func; @@ -229,29 +225,31 @@ void parse_proc_kallsyms(struct pevent *pevent, char *next = NULL; char *addr_str; char *mod; - char *fmt; + char ch; line = strtok_r(file, "\n", &next); while (line) { mod = NULL; - addr_str = strtok_r(line, " ", &fmt); + sscanf(line, "%as %c %as\t[%as", + (float *)(void *)&addr_str, /* workaround gcc warning */ + &ch, (float *)(void *)&func, (float *)(void *)&mod); addr = strtoull(addr_str, NULL, 16); - /* skip character */ - strtok_r(NULL, " ", &fmt); - func = strtok_r(NULL, "\t", &fmt); - mod = strtok_r(NULL, "]", &fmt); - /* truncate the extra '[' */ + free(addr_str); + + /* truncate the extra ']' */ if (mod) - mod = mod + 1; + mod[strlen(mod) - 1] = 0; pevent_register_function(pevent, func, addr, mod); + free(func); + free(mod); line = strtok_r(NULL, "\n", &next); } } void parse_ftrace_printk(struct pevent *pevent, - char *file, unsigned int size __maybe_unused) + char *file, unsigned int size __unused) { unsigned long long addr; char *printk; @@ -291,7 +289,7 @@ struct event_format *trace_find_next_event(struct pevent *pevent, { static int idx; - if (!pevent || !pevent->events) + if (!pevent->events) return NULL; if (!event) { diff --git a/trunk/tools/perf/util/trace-event-scripting.c b/trunk/tools/perf/util/trace-event-scripting.c index 8715a1006d00..474aa7a7df43 100644 --- a/trunk/tools/perf/util/trace-event-scripting.c +++ b/trunk/tools/perf/util/trace-event-scripting.c @@ -35,11 +35,12 @@ static int stop_script_unsupported(void) return 0; } -static void process_event_unsupported(union perf_event *event __maybe_unused, - struct perf_sample *sample __maybe_unused, - struct perf_evsel *evsel __maybe_unused, - struct machine *machine __maybe_unused, - struct addr_location *al __maybe_unused) +static void process_event_unsupported(union perf_event *event __unused, + struct pevent *pevent __unused, + struct perf_sample *sample __unused, + struct perf_evsel *evsel __unused, + struct machine *machine __unused, + struct thread *thread __unused) { } @@ -52,19 +53,17 @@ static void print_python_unsupported_msg(void) "\n etc.\n"); } -static int python_start_script_unsupported(const char *script __maybe_unused, - int argc __maybe_unused, - const char **argv __maybe_unused) +static int python_start_script_unsupported(const char *script __unused, + int argc __unused, + const char **argv __unused) { print_python_unsupported_msg(); return -1; } -static int python_generate_script_unsupported(struct pevent *pevent - __maybe_unused, - const char *outfile - __maybe_unused) +static int python_generate_script_unsupported(struct pevent *pevent __unused, + const char *outfile __unused) { print_python_unsupported_msg(); @@ -116,18 +115,17 @@ static void print_perl_unsupported_msg(void) "\n etc.\n"); } -static int perl_start_script_unsupported(const char *script __maybe_unused, - int argc __maybe_unused, - const char **argv __maybe_unused) +static int perl_start_script_unsupported(const char *script __unused, + int argc __unused, + const char **argv __unused) { print_perl_unsupported_msg(); return -1; } -static int perl_generate_script_unsupported(struct pevent *pevent - __maybe_unused, - const char *outfile __maybe_unused) +static int perl_generate_script_unsupported(struct pevent *pevent __unused, + const char *outfile __unused) { print_perl_unsupported_msg(); diff --git a/trunk/tools/perf/util/trace-event.h b/trunk/tools/perf/util/trace-event.h index a55fd37ffea1..8fef1d6687b7 100644 --- a/trunk/tools/perf/util/trace-event.h +++ b/trunk/tools/perf/util/trace-event.h @@ -9,6 +9,7 @@ struct machine; struct perf_sample; union perf_event; struct perf_tool; +struct thread; extern int header_page_size_size; extern int header_page_ts_size; @@ -31,8 +32,6 @@ int bigendian(void); struct pevent *read_trace_init(int file_bigendian, int host_bigendian); void print_trace_event(struct pevent *pevent, int cpu, void *data, int size); -void event_format__print(struct event_format *event, - int cpu, void *data, int size); void print_event(struct pevent *pevent, int cpu, void *data, int size, unsigned long long nsecs, char *comm); @@ -57,7 +56,7 @@ int trace_parse_common_pid(struct pevent *pevent, void *data); struct event_format *trace_find_next_event(struct pevent *pevent, struct event_format *event); -unsigned long long read_size(struct event_format *event, void *ptr, int size); +unsigned long long read_size(struct pevent *pevent, void *ptr, int size); unsigned long long eval_flag(const char *flag); struct pevent_record *trace_read_data(struct pevent *pevent, int cpu); @@ -75,19 +74,16 @@ struct tracing_data *tracing_data_get(struct list_head *pattrs, void tracing_data_put(struct tracing_data *tdata); -struct addr_location; - -struct perf_session; - struct scripting_ops { const char *name; int (*start_script) (const char *script, int argc, const char **argv); int (*stop_script) (void); void (*process_event) (union perf_event *event, + struct pevent *pevent, struct perf_sample *sample, struct perf_evsel *evsel, struct machine *machine, - struct addr_location *al); + struct thread *thread); int (*generate_script) (struct pevent *pevent, const char *outfile); }; diff --git a/trunk/tools/perf/util/unwind.c b/trunk/tools/perf/util/unwind.c deleted file mode 100644 index 958723ba3d2e..000000000000 --- a/trunk/tools/perf/util/unwind.c +++ /dev/null @@ -1,571 +0,0 @@ -/* - * Post mortem Dwarf CFI based unwinding on top of regs and stack dumps. - * - * Lots of this code have been borrowed or heavily inspired from parts of - * the libunwind 0.99 code which are (amongst other contributors I may have - * forgotten): - * - * Copyright (C) 2002-2007 Hewlett-Packard Co - * Contributed by David Mosberger-Tang - * - * And the bugs have been added by: - * - * Copyright (C) 2010, Frederic Weisbecker - * Copyright (C) 2012, Jiri Olsa - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "thread.h" -#include "session.h" -#include "perf_regs.h" -#include "unwind.h" -#include "util.h" - -extern int -UNW_OBJ(dwarf_search_unwind_table) (unw_addr_space_t as, - unw_word_t ip, - unw_dyn_info_t *di, - unw_proc_info_t *pi, - int need_unwind_info, void *arg); - -#define dwarf_search_unwind_table UNW_OBJ(dwarf_search_unwind_table) - -#define DW_EH_PE_FORMAT_MASK 0x0f /* format of the encoded value */ -#define DW_EH_PE_APPL_MASK 0x70 /* how the value is to be applied */ - -/* Pointer-encoding formats: */ -#define DW_EH_PE_omit 0xff -#define DW_EH_PE_ptr 0x00 /* pointer-sized unsigned value */ -#define DW_EH_PE_udata4 0x03 /* unsigned 32-bit value */ -#define DW_EH_PE_udata8 0x04 /* unsigned 64-bit value */ -#define DW_EH_PE_sdata4 0x0b /* signed 32-bit value */ -#define DW_EH_PE_sdata8 0x0c /* signed 64-bit value */ - -/* Pointer-encoding application: */ -#define DW_EH_PE_absptr 0x00 /* absolute value */ -#define DW_EH_PE_pcrel 0x10 /* rel. to addr. of encoded value */ - -/* - * The following are not documented by LSB v1.3, yet they are used by - * GCC, presumably they aren't documented by LSB since they aren't - * used on Linux: - */ -#define DW_EH_PE_funcrel 0x40 /* start-of-procedure-relative */ -#define DW_EH_PE_aligned 0x50 /* aligned pointer */ - -/* Flags intentionaly not handled, since they're not needed: - * #define DW_EH_PE_indirect 0x80 - * #define DW_EH_PE_uleb128 0x01 - * #define DW_EH_PE_udata2 0x02 - * #define DW_EH_PE_sleb128 0x09 - * #define DW_EH_PE_sdata2 0x0a - * #define DW_EH_PE_textrel 0x20 - * #define DW_EH_PE_datarel 0x30 - */ - -struct unwind_info { - struct perf_sample *sample; - struct machine *machine; - struct thread *thread; - u64 sample_uregs; -}; - -#define dw_read(ptr, type, end) ({ \ - type *__p = (type *) ptr; \ - type __v; \ - if ((__p + 1) > (type *) end) \ - return -EINVAL; \ - __v = *__p++; \ - ptr = (typeof(ptr)) __p; \ - __v; \ - }) - -static int __dw_read_encoded_value(u8 **p, u8 *end, u64 *val, - u8 encoding) -{ - u8 *cur = *p; - *val = 0; - - switch (encoding) { - case DW_EH_PE_omit: - *val = 0; - goto out; - case DW_EH_PE_ptr: - *val = dw_read(cur, unsigned long, end); - goto out; - default: - break; - } - - switch (encoding & DW_EH_PE_APPL_MASK) { - case DW_EH_PE_absptr: - break; - case DW_EH_PE_pcrel: - *val = (unsigned long) cur; - break; - default: - return -EINVAL; - } - - if ((encoding & 0x07) == 0x00) - encoding |= DW_EH_PE_udata4; - - switch (encoding & DW_EH_PE_FORMAT_MASK) { - case DW_EH_PE_sdata4: - *val += dw_read(cur, s32, end); - break; - case DW_EH_PE_udata4: - *val += dw_read(cur, u32, end); - break; - case DW_EH_PE_sdata8: - *val += dw_read(cur, s64, end); - break; - case DW_EH_PE_udata8: - *val += dw_read(cur, u64, end); - break; - default: - return -EINVAL; - } - - out: - *p = cur; - return 0; -} - -#define dw_read_encoded_value(ptr, end, enc) ({ \ - u64 __v; \ - if (__dw_read_encoded_value(&ptr, end, &__v, enc)) { \ - return -EINVAL; \ - } \ - __v; \ - }) - -static Elf_Scn *elf_section_by_name(Elf *elf, GElf_Ehdr *ep, - GElf_Shdr *shp, const char *name) -{ - Elf_Scn *sec = NULL; - - while ((sec = elf_nextscn(elf, sec)) != NULL) { - char *str; - - gelf_getshdr(sec, shp); - str = elf_strptr(elf, ep->e_shstrndx, shp->sh_name); - if (!strcmp(name, str)) - break; - } - - return sec; -} - -static u64 elf_section_offset(int fd, const char *name) -{ - Elf *elf; - GElf_Ehdr ehdr; - GElf_Shdr shdr; - u64 offset = 0; - - elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL); - if (elf == NULL) - return 0; - - do { - if (gelf_getehdr(elf, &ehdr) == NULL) - break; - - if (!elf_section_by_name(elf, &ehdr, &shdr, name)) - break; - - offset = shdr.sh_offset; - } while (0); - - elf_end(elf); - return offset; -} - -struct table_entry { - u32 start_ip_offset; - u32 fde_offset; -}; - -struct eh_frame_hdr { - unsigned char version; - unsigned char eh_frame_ptr_enc; - unsigned char fde_count_enc; - unsigned char table_enc; - - /* - * The rest of the header is variable-length and consists of the - * following members: - * - * encoded_t eh_frame_ptr; - * encoded_t fde_count; - */ - - /* A single encoded pointer should not be more than 8 bytes. */ - u64 enc[2]; - - /* - * struct { - * encoded_t start_ip; - * encoded_t fde_addr; - * } binary_search_table[fde_count]; - */ - char data[0]; -} __packed; - -static int unwind_spec_ehframe(struct dso *dso, struct machine *machine, - u64 offset, u64 *table_data, u64 *segbase, - u64 *fde_count) -{ - struct eh_frame_hdr hdr; - u8 *enc = (u8 *) &hdr.enc; - u8 *end = (u8 *) &hdr.data; - ssize_t r; - - r = dso__data_read_offset(dso, machine, offset, - (u8 *) &hdr, sizeof(hdr)); - if (r != sizeof(hdr)) - return -EINVAL; - - /* We dont need eh_frame_ptr, just skip it. */ - dw_read_encoded_value(enc, end, hdr.eh_frame_ptr_enc); - - *fde_count = dw_read_encoded_value(enc, end, hdr.fde_count_enc); - *segbase = offset; - *table_data = (enc - (u8 *) &hdr) + offset; - return 0; -} - -static int read_unwind_spec(struct dso *dso, struct machine *machine, - u64 *table_data, u64 *segbase, u64 *fde_count) -{ - int ret = -EINVAL, fd; - u64 offset; - - fd = dso__data_fd(dso, machine); - if (fd < 0) - return -EINVAL; - - offset = elf_section_offset(fd, ".eh_frame_hdr"); - close(fd); - - if (offset) - ret = unwind_spec_ehframe(dso, machine, offset, - table_data, segbase, - fde_count); - - /* TODO .debug_frame check if eh_frame_hdr fails */ - return ret; -} - -static struct map *find_map(unw_word_t ip, struct unwind_info *ui) -{ - struct addr_location al; - - thread__find_addr_map(ui->thread, ui->machine, PERF_RECORD_MISC_USER, - MAP__FUNCTION, ip, &al); - return al.map; -} - -static int -find_proc_info(unw_addr_space_t as, unw_word_t ip, unw_proc_info_t *pi, - int need_unwind_info, void *arg) -{ - struct unwind_info *ui = arg; - struct map *map; - unw_dyn_info_t di; - u64 table_data, segbase, fde_count; - - map = find_map(ip, ui); - if (!map || !map->dso) - return -EINVAL; - - pr_debug("unwind: find_proc_info dso %s\n", map->dso->name); - - if (read_unwind_spec(map->dso, ui->machine, - &table_data, &segbase, &fde_count)) - return -EINVAL; - - memset(&di, 0, sizeof(di)); - di.format = UNW_INFO_FORMAT_REMOTE_TABLE; - di.start_ip = map->start; - di.end_ip = map->end; - di.u.rti.segbase = map->start + segbase; - di.u.rti.table_data = map->start + table_data; - di.u.rti.table_len = fde_count * sizeof(struct table_entry) - / sizeof(unw_word_t); - return dwarf_search_unwind_table(as, ip, &di, pi, - need_unwind_info, arg); -} - -static int access_fpreg(unw_addr_space_t __maybe_unused as, - unw_regnum_t __maybe_unused num, - unw_fpreg_t __maybe_unused *val, - int __maybe_unused __write, - void __maybe_unused *arg) -{ - pr_err("unwind: access_fpreg unsupported\n"); - return -UNW_EINVAL; -} - -static int get_dyn_info_list_addr(unw_addr_space_t __maybe_unused as, - unw_word_t __maybe_unused *dil_addr, - void __maybe_unused *arg) -{ - return -UNW_ENOINFO; -} - -static int resume(unw_addr_space_t __maybe_unused as, - unw_cursor_t __maybe_unused *cu, - void __maybe_unused *arg) -{ - pr_err("unwind: resume unsupported\n"); - return -UNW_EINVAL; -} - -static int -get_proc_name(unw_addr_space_t __maybe_unused as, - unw_word_t __maybe_unused addr, - char __maybe_unused *bufp, size_t __maybe_unused buf_len, - unw_word_t __maybe_unused *offp, void __maybe_unused *arg) -{ - pr_err("unwind: get_proc_name unsupported\n"); - return -UNW_EINVAL; -} - -static int access_dso_mem(struct unwind_info *ui, unw_word_t addr, - unw_word_t *data) -{ - struct addr_location al; - ssize_t size; - - thread__find_addr_map(ui->thread, ui->machine, PERF_RECORD_MISC_USER, - MAP__FUNCTION, addr, &al); - if (!al.map) { - pr_debug("unwind: no map for %lx\n", (unsigned long)addr); - return -1; - } - - if (!al.map->dso) - return -1; - - size = dso__data_read_addr(al.map->dso, al.map, ui->machine, - addr, (u8 *) data, sizeof(*data)); - - return !(size == sizeof(*data)); -} - -static int reg_value(unw_word_t *valp, struct regs_dump *regs, int id, - u64 sample_regs) -{ - int i, idx = 0; - - if (!(sample_regs & (1 << id))) - return -EINVAL; - - for (i = 0; i < id; i++) { - if (sample_regs & (1 << i)) - idx++; - } - - *valp = regs->regs[idx]; - return 0; -} - -static int access_mem(unw_addr_space_t __maybe_unused as, - unw_word_t addr, unw_word_t *valp, - int __write, void *arg) -{ - struct unwind_info *ui = arg; - struct stack_dump *stack = &ui->sample->user_stack; - unw_word_t start, end; - int offset; - int ret; - - /* Don't support write, probably not needed. */ - if (__write || !stack || !ui->sample->user_regs.regs) { - *valp = 0; - return 0; - } - - ret = reg_value(&start, &ui->sample->user_regs, PERF_REG_SP, - ui->sample_uregs); - if (ret) - return ret; - - end = start + stack->size; - - /* Check overflow. */ - if (addr + sizeof(unw_word_t) < addr) - return -EINVAL; - - if (addr < start || addr + sizeof(unw_word_t) >= end) { - ret = access_dso_mem(ui, addr, valp); - if (ret) { - pr_debug("unwind: access_mem %p not inside range %p-%p\n", - (void *)addr, (void *)start, (void *)end); - *valp = 0; - return ret; - } - return 0; - } - - offset = addr - start; - *valp = *(unw_word_t *)&stack->data[offset]; - pr_debug("unwind: access_mem addr %p, val %lx, offset %d\n", - (void *)addr, (unsigned long)*valp, offset); - return 0; -} - -static int access_reg(unw_addr_space_t __maybe_unused as, - unw_regnum_t regnum, unw_word_t *valp, - int __write, void *arg) -{ - struct unwind_info *ui = arg; - int id, ret; - - /* Don't support write, I suspect we don't need it. */ - if (__write) { - pr_err("unwind: access_reg w %d\n", regnum); - return 0; - } - - if (!ui->sample->user_regs.regs) { - *valp = 0; - return 0; - } - - id = unwind__arch_reg_id(regnum); - if (id < 0) - return -EINVAL; - - ret = reg_value(valp, &ui->sample->user_regs, id, ui->sample_uregs); - if (ret) { - pr_err("unwind: can't read reg %d\n", regnum); - return ret; - } - - pr_debug("unwind: reg %d, val %lx\n", regnum, (unsigned long)*valp); - return 0; -} - -static void put_unwind_info(unw_addr_space_t __maybe_unused as, - unw_proc_info_t *pi __maybe_unused, - void *arg __maybe_unused) -{ - pr_debug("unwind: put_unwind_info called\n"); -} - -static int entry(u64 ip, struct thread *thread, struct machine *machine, - unwind_entry_cb_t cb, void *arg) -{ - struct unwind_entry e; - struct addr_location al; - - thread__find_addr_location(thread, machine, - PERF_RECORD_MISC_USER, - MAP__FUNCTION, ip, &al, NULL); - - e.ip = ip; - e.map = al.map; - e.sym = al.sym; - - pr_debug("unwind: %s:ip = 0x%" PRIx64 " (0x%" PRIx64 ")\n", - al.sym ? al.sym->name : "''", - ip, - al.map ? al.map->map_ip(al.map, ip) : (u64) 0); - - return cb(&e, arg); -} - -static void display_error(int err) -{ - switch (err) { - case UNW_EINVAL: - pr_err("unwind: Only supports local.\n"); - break; - case UNW_EUNSPEC: - pr_err("unwind: Unspecified error.\n"); - break; - case UNW_EBADREG: - pr_err("unwind: Register unavailable.\n"); - break; - default: - break; - } -} - -static unw_accessors_t accessors = { - .find_proc_info = find_proc_info, - .put_unwind_info = put_unwind_info, - .get_dyn_info_list_addr = get_dyn_info_list_addr, - .access_mem = access_mem, - .access_reg = access_reg, - .access_fpreg = access_fpreg, - .resume = resume, - .get_proc_name = get_proc_name, -}; - -static int get_entries(struct unwind_info *ui, unwind_entry_cb_t cb, - void *arg) -{ - unw_addr_space_t addr_space; - unw_cursor_t c; - int ret; - - addr_space = unw_create_addr_space(&accessors, 0); - if (!addr_space) { - pr_err("unwind: Can't create unwind address space.\n"); - return -ENOMEM; - } - - ret = unw_init_remote(&c, addr_space, ui); - if (ret) - display_error(ret); - - while (!ret && (unw_step(&c) > 0)) { - unw_word_t ip; - - unw_get_reg(&c, UNW_REG_IP, &ip); - ret = entry(ip, ui->thread, ui->machine, cb, arg); - } - - unw_destroy_addr_space(addr_space); - return ret; -} - -int unwind__get_entries(unwind_entry_cb_t cb, void *arg, - struct machine *machine, struct thread *thread, - u64 sample_uregs, struct perf_sample *data) -{ - unw_word_t ip; - struct unwind_info ui = { - .sample = data, - .sample_uregs = sample_uregs, - .thread = thread, - .machine = machine, - }; - int ret; - - if (!data->user_regs.regs) - return -EINVAL; - - ret = reg_value(&ip, &data->user_regs, PERF_REG_IP, sample_uregs); - if (ret) - return ret; - - ret = entry(ip, thread, machine, cb, arg); - if (ret) - return -ENOMEM; - - return get_entries(&ui, cb, arg); -} diff --git a/trunk/tools/perf/util/unwind.h b/trunk/tools/perf/util/unwind.h deleted file mode 100644 index a78c8b303bb5..000000000000 --- a/trunk/tools/perf/util/unwind.h +++ /dev/null @@ -1,35 +0,0 @@ -#ifndef __UNWIND_H -#define __UNWIND_H - -#include "types.h" -#include "event.h" -#include "symbol.h" - -struct unwind_entry { - struct map *map; - struct symbol *sym; - u64 ip; -}; - -typedef int (*unwind_entry_cb_t)(struct unwind_entry *entry, void *arg); - -#ifndef NO_LIBUNWIND_SUPPORT -int unwind__get_entries(unwind_entry_cb_t cb, void *arg, - struct machine *machine, - struct thread *thread, - u64 sample_uregs, - struct perf_sample *data); -int unwind__arch_reg_id(int regnum); -#else -static inline int -unwind__get_entries(unwind_entry_cb_t cb __maybe_unused, - void *arg __maybe_unused, - struct machine *machine __maybe_unused, - struct thread *thread __maybe_unused, - u64 sample_uregs __maybe_unused, - struct perf_sample *data __maybe_unused) -{ - return 0; -} -#endif /* NO_LIBUNWIND_SUPPORT */ -#endif /* __UNWIND_H */ diff --git a/trunk/tools/perf/util/util.c b/trunk/tools/perf/util/util.c index 2055cf38041c..d03599fbe78b 100644 --- a/trunk/tools/perf/util/util.c +++ b/trunk/tools/perf/util/util.c @@ -1,11 +1,6 @@ #include "../perf.h" #include "util.h" #include -#ifndef NO_BACKTRACE -#include -#endif -#include -#include /* * XXX We need to find a better place for these things... @@ -163,23 +158,3 @@ size_t hex_width(u64 v) return n; } - -/* Obtain a backtrace and print it to stdout. */ -#ifndef NO_BACKTRACE -void dump_stack(void) -{ - void *array[16]; - size_t size = backtrace(array, ARRAY_SIZE(array)); - char **strings = backtrace_symbols(array, size); - size_t i; - - printf("Obtained %zd stack frames.\n", size); - - for (i = 0; i < size; i++) - printf("%s\n", strings[i]); - - free(strings); -} -#else -void dump_stack(void) {} -#endif diff --git a/trunk/tools/perf/util/util.h b/trunk/tools/perf/util/util.h index 70fa70b535b2..b13c7331eaf8 100644 --- a/trunk/tools/perf/util/util.h +++ b/trunk/tools/perf/util/util.h @@ -69,8 +69,13 @@ #include #include #include +#include +#include +#include +#include +#include #include -#include +#include "../../../include/linux/magic.h" #include "types.h" #include @@ -261,6 +266,4 @@ size_t hex_width(u64 v); char *rtrim(char *s); -void dump_stack(void); - #endif diff --git a/trunk/tools/perf/util/vdso.c b/trunk/tools/perf/util/vdso.c deleted file mode 100644 index e60951fcdb12..000000000000 --- a/trunk/tools/perf/util/vdso.c +++ /dev/null @@ -1,111 +0,0 @@ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "vdso.h" -#include "util.h" -#include "symbol.h" -#include "linux/string.h" - -static bool vdso_found; -static char vdso_file[] = "/tmp/perf-vdso.so-XXXXXX"; - -static int find_vdso_map(void **start, void **end) -{ - FILE *maps; - char line[128]; - int found = 0; - - maps = fopen("/proc/self/maps", "r"); - if (!maps) { - pr_err("vdso: cannot open maps\n"); - return -1; - } - - while (!found && fgets(line, sizeof(line), maps)) { - int m = -1; - - /* We care only about private r-x mappings. */ - if (2 != sscanf(line, "%p-%p r-xp %*x %*x:%*x %*u %n", - start, end, &m)) - continue; - if (m < 0) - continue; - - if (!strncmp(&line[m], VDSO__MAP_NAME, - sizeof(VDSO__MAP_NAME) - 1)) - found = 1; - } - - fclose(maps); - return !found; -} - -static char *get_file(void) -{ - char *vdso = NULL; - char *buf = NULL; - void *start, *end; - size_t size; - int fd; - - if (vdso_found) - return vdso_file; - - if (find_vdso_map(&start, &end)) - return NULL; - - size = end - start; - - buf = memdup(start, size); - if (!buf) - return NULL; - - fd = mkstemp(vdso_file); - if (fd < 0) - goto out; - - if (size == (size_t) write(fd, buf, size)) - vdso = vdso_file; - - close(fd); - - out: - free(buf); - - vdso_found = (vdso != NULL); - return vdso; -} - -void vdso__exit(void) -{ - if (vdso_found) - unlink(vdso_file); -} - -struct dso *vdso__dso_findnew(struct list_head *head) -{ - struct dso *dso = dsos__find(head, VDSO__MAP_NAME); - - if (!dso) { - char *file; - - file = get_file(); - if (!file) - return NULL; - - dso = dso__new(VDSO__MAP_NAME); - if (dso != NULL) { - dsos__add(head, dso); - dso__set_long_name(dso, file); - } - } - - return dso; -} diff --git a/trunk/tools/perf/util/vdso.h b/trunk/tools/perf/util/vdso.h deleted file mode 100644 index 0f76e7caf6f8..000000000000 --- a/trunk/tools/perf/util/vdso.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef __PERF_VDSO__ -#define __PERF_VDSO__ - -#include -#include -#include - -#define VDSO__MAP_NAME "[vdso]" - -static inline bool is_vdso_map(const char *filename) -{ - return !strcmp(filename, VDSO__MAP_NAME); -} - -struct dso *vdso__dso_findnew(struct list_head *head); -void vdso__exit(void); - -#endif /* __PERF_VDSO__ */ diff --git a/trunk/tools/perf/util/wrapper.c b/trunk/tools/perf/util/wrapper.c index 19f15b650703..73e900edb5a2 100644 --- a/trunk/tools/perf/util/wrapper.c +++ b/trunk/tools/perf/util/wrapper.c @@ -7,8 +7,7 @@ * There's no pack memory to release - but stay close to the Git * version so wrap this away: */ -static inline void release_pack_memory(size_t size __maybe_unused, - int flag __maybe_unused) +static inline void release_pack_memory(size_t size __used, int flag __used) { } diff --git a/trunk/tools/scripts/Makefile.include b/trunk/tools/scripts/Makefile.include index 96ce80a3743b..bde8521d56bb 100644 --- a/trunk/tools/scripts/Makefile.include +++ b/trunk/tools/scripts/Makefile.include @@ -1,8 +1,6 @@ ifeq ("$(origin O)", "command line") - dummy := $(if $(shell test -d $(O) || echo $(O)),$(error O=$(O) does not exist),) - ABSOLUTE_O := $(shell cd $(O) ; pwd) - OUTPUT := $(ABSOLUTE_O)/ - COMMAND_O := O=$(ABSOLUTE_O) + OUTPUT := $(O)/ + COMMAND_O := O=$(O) endif ifneq ($(OUTPUT),) diff --git a/trunk/tools/testing/ktest/examples/include/defaults.conf b/trunk/tools/testing/ktest/examples/include/defaults.conf index 63a1a83f4f0b..323a552ce642 100644 --- a/trunk/tools/testing/ktest/examples/include/defaults.conf +++ b/trunk/tools/testing/ktest/examples/include/defaults.conf @@ -33,7 +33,7 @@ DEFAULTS THIS_DIR := ${PWD} -# to organize your configs, having each machine save their configs +# to orginize your configs, having each machine save their configs # into a separate directly is useful. CONFIG_DIR := ${THIS_DIR}/configs/${MACHINE} diff --git a/trunk/tools/testing/ktest/examples/include/tests.conf b/trunk/tools/testing/ktest/examples/include/tests.conf index 60cedb1a1154..4fdb811bd810 100644 --- a/trunk/tools/testing/ktest/examples/include/tests.conf +++ b/trunk/tools/testing/ktest/examples/include/tests.conf @@ -47,7 +47,7 @@ BUILD_NOCLEAN = 1 # Build, install, boot and test with a randconfg 10 times. # It is important that you have set MIN_CONFIG in the config # that includes this file otherwise it is likely that the -# randconfig will not have the necessary configs needed to +# randconfig will not have the neccessary configs needed to # boot your box. This version of the test requires a min # config that has enough to make sure the target has network # working. diff --git a/trunk/tools/testing/ktest/ktest.pl b/trunk/tools/testing/ktest/ktest.pl index c05bcd293d8c..52b7959cd513 100755 --- a/trunk/tools/testing/ktest/ktest.pl +++ b/trunk/tools/testing/ktest/ktest.pl @@ -840,9 +840,7 @@ sub __read_config { if ($rest =~ /\sIF\s+(.*)/) { # May be a ELSE IF section. - if (process_if($name, $1)) { - $if_set = 1; - } else { + if (!process_if($name, $1)) { $skip = 1; } $rest = ""; diff --git a/trunk/tools/testing/selftests/vm/run_vmtests b/trunk/tools/testing/selftests/vm/run_vmtests index 4c53cae6c273..8b40bd5e5cc2 100644 --- a/trunk/tools/testing/selftests/vm/run_vmtests +++ b/trunk/tools/testing/selftests/vm/run_vmtests @@ -36,7 +36,7 @@ mkdir $mnt mount -t hugetlbfs none $mnt echo "--------------------" -echo "running hugepage-mmap" +echo "runing hugepage-mmap" echo "--------------------" ./hugepage-mmap if [ $? -ne 0 ]; then @@ -50,7 +50,7 @@ shmall=`cat /proc/sys/kernel/shmall` echo 268435456 > /proc/sys/kernel/shmmax echo 4194304 > /proc/sys/kernel/shmall echo "--------------------" -echo "running hugepage-shm" +echo "runing hugepage-shm" echo "--------------------" ./hugepage-shm if [ $? -ne 0 ]; then @@ -62,7 +62,7 @@ echo $shmmax > /proc/sys/kernel/shmmax echo $shmall > /proc/sys/kernel/shmall echo "--------------------" -echo "running map_hugetlb" +echo "runing map_hugetlb" echo "--------------------" ./map_hugetlb if [ $? -ne 0 ]; then diff --git a/trunk/virt/kvm/kvm_main.c b/trunk/virt/kvm/kvm_main.c index d617f69131d7..246852397e30 100644 --- a/trunk/virt/kvm/kvm_main.c +++ b/trunk/virt/kvm/kvm_main.c @@ -1976,10 +1976,9 @@ static long kvm_vcpu_compat_ioctl(struct file *filp, if (copy_from_user(&csigset, sigmask_arg->sigset, sizeof csigset)) goto out; - sigset_from_compat(&sigset, &csigset); - r = kvm_vcpu_ioctl_set_sigmask(vcpu, &sigset); - } else - r = kvm_vcpu_ioctl_set_sigmask(vcpu, NULL); + } + sigset_from_compat(&sigset, &csigset); + r = kvm_vcpu_ioctl_set_sigmask(vcpu, &sigset); break; } default: